[Pkg-golang-commits] [golang] 02/03: Imported Upstream version 1.6

Tianon Gravi tianon at debian.org
Sat Feb 20 09:17:42 UTC 2016


This is an automated email from the git hooks/post-receive script.

tianon pushed a commit to branch debian-sid
in repository golang.

commit fe8b797360d1037d5682e80e093242fbcee7969d
Author: Tianon Gravi <tianon at debian.org>
Date:   Sat Feb 20 01:16:22 2016 -0800

    Imported Upstream version 1.6
---
 AUTHORS                                            |   120 +-
 CONTRIBUTORS                                       |   161 +-
 README.md                                          |     4 +-
 VERSION                                            |     2 +-
 api/README                                         |     2 +-
 api/go1.1.txt                                      |    30 +-
 api/go1.6.txt                                      |   275 +
 doc/asm.html                                       |    22 +-
 doc/code.html                                      |    49 +-
 doc/codewalk/codewalk.xml                          |     2 +-
 doc/conduct.html                                   |     2 +-
 doc/contrib.html                                   |     3 -
 doc/contribute.html                                |    55 +-
 doc/debugging_with_gdb.html                        |     2 +-
 doc/devel/release.html                             |    18 +
 doc/go1.5.html                                     |     2 +-
 doc/go1.6.html                                     |   925 ++
 doc/go_faq.html                                    |    32 +-
 doc/go_spec.html                                   |    93 +-
 doc/help.html                                      |    68 +-
 doc/install-source.html                            |    49 +-
 doc/install.html                                   |    35 +-
 doc/play/pi.go                                     |     2 +-
 doc/progs/run.go                                   |     0
 lib/time/update.bash                               |     5 +-
 lib/time/zoneinfo.zip                              |   Bin 359824 -> 360703 bytes
 misc/cgo/errors/issue11097a.go                     |    15 +
 misc/cgo/errors/issue11097b.go                     |    15 +
 misc/cgo/errors/issue13129.go                      |    14 +
 misc/cgo/errors/issue13423.go                      |    12 +
 misc/cgo/errors/issue13635.go                      |    24 +
 misc/cgo/errors/ptr.go                             |   513 +
 misc/cgo/errors/test.bash                          |    27 +-
 misc/cgo/gmp/pi.go                                 |    41 +-
 misc/cgo/life/main.go                              |     2 +-
 misc/cgo/stdio/chain.go                            |     5 +-
 misc/cgo/stdio/fib.go                              |     5 +-
 misc/cgo/stdio/hello.go                            |     2 +-
 misc/cgo/test/buildid_linux.go                     |     2 +-
 misc/cgo/test/callback.go                          |    57 +-
 misc/cgo/test/callback_c.c                         |     8 +
 misc/cgo/test/cgo_test.go                          |     3 +
 misc/cgo/test/cgo_unix_test.go                     |    11 +
 misc/cgo/test/env.go                               |     2 +-
 misc/cgo/test/gcc68255.go                          |    17 +
 misc/cgo/test/gcc68255/a.go                        |    17 +
 misc/cgo/test/gcc68255/c.c                         |     8 +
 misc/cgo/test/gcc68255/c.h                         |     5 +
 misc/cgo/test/issue10303.go                        |     6 +
 misc/cgo/test/issue13402.go                        |    10 +
 misc/cgo/test/issue4029.c                          |    10 +
 misc/cgo/test/issue4029.go                         |    17 +-
 misc/cgo/test/issue6997_linux.go                   |     4 +-
 misc/cgo/test/issue7665.go                         |     2 +-
 misc/cgo/test/issue7978.go                         |     4 +-
 misc/cgo/test/issue8694.go                         |     4 +-
 misc/cgo/test/issue9400/asm_ppc64x.s               |     2 +-
 misc/cgo/test/issue9510.go                         |    24 +
 misc/cgo/test/issue9510a/a.go                      |    15 +
 misc/cgo/test/issue9510b/b.go                      |    15 +
 misc/cgo/test/sigaltstack.go                       |    73 +
 misc/cgo/testcarchive/main.c                       |    39 +
 misc/cgo/testcarchive/main2.c                      |   185 +
 misc/cgo/testcarchive/main3.c                      |   153 +
 misc/cgo/testcarchive/main4.c                      |   194 +
 misc/cgo/testcarchive/src/libgo2/libgo2.go         |    45 +
 misc/cgo/testcarchive/src/libgo3/libgo3.go         |    44 +
 misc/cgo/testcarchive/src/libgo4/libgo4.go         |    52 +
 misc/cgo/testcarchive/test.bash                    |    68 +-
 misc/cgo/testcshared/main2.c                       |     4 +-
 misc/cgo/testcshared/main4.c                       |   214 +
 misc/cgo/testcshared/main5.c                       |   197 +
 misc/cgo/testcshared/src/libgo2/dup2.go            |    13 +
 misc/cgo/testcshared/src/libgo2/dup3.go            |    13 +
 misc/cgo/testcshared/src/libgo2/libgo2.go          |     4 +-
 misc/cgo/testcshared/src/libgo4/libgo4.go          |    45 +
 misc/cgo/testcshared/src/libgo5/libgo5.go          |    44 +
 misc/cgo/testcshared/test.bash                     |    87 +-
 misc/cgo/testsanitizers/msan.go                    |    35 +
 misc/cgo/testsanitizers/msan2.go                   |    35 +
 misc/cgo/testsanitizers/msan3.go                   |    33 +
 misc/cgo/testsanitizers/msan4.go                   |    50 +
 misc/cgo/testsanitizers/msan_fail.go               |    36 +
 misc/cgo/testsanitizers/test.bash                  |    89 +
 misc/cgo/testshared/shared_test.go                 |   141 +-
 misc/cgo/testshared/src/explicit/explicit.go       |     9 +
 misc/cgo/testshared/src/implicit/implicit.go       |     5 +
 misc/cgo/testshared/src/implicitcmd/implicitcmd.go |    10 +
 misc/cgo/testsigfwd/main.go                        |    60 +-
 misc/ios/detect.go                                 |     3 +
 misc/ios/go_darwin_arm_exec.go                     |     2 +-
 misc/nacl/testzip.proto                            |    21 +-
 misc/sortac/sortac.go                              |    79 +
 src/androidtest.bash                               |    19 +-
 src/archive/tar/common.go                          |    11 +
 src/archive/tar/example_test.go                    |     4 +-
 src/archive/tar/reader.go                          |   654 +-
 src/archive/tar/reader_test.go                     |   963 +-
 src/archive/tar/testdata/gnu-multi-hdrs.tar        |   Bin 0 -> 4608 bytes
 src/archive/tar/testdata/hdr-only.tar              |   Bin 0 -> 10240 bytes
 src/archive/tar/testdata/issue12435.tar            |   Bin 0 -> 512 bytes
 src/archive/tar/testdata/neg-size.tar              |   Bin 512 -> 512 bytes
 src/archive/tar/testdata/pax-multi-hdrs.tar        |   Bin 0 -> 4608 bytes
 src/archive/tar/testdata/pax-path-hdr.tar          |   Bin 0 -> 1024 bytes
 src/archive/tar/testdata/ustar-file-reg.tar        |   Bin 0 -> 1536 bytes
 src/archive/tar/writer.go                          |   222 +-
 src/archive/tar/writer_test.go                     |   212 +-
 src/archive/zip/example_test.go                    |    18 +
 src/archive/zip/reader.go                          |   113 +-
 src/archive/zip/reader_test.go                     |   272 +-
 src/archive/zip/register.go                        |    27 +-
 src/archive/zip/struct.go                          |     2 +-
 src/archive/zip/writer.go                          |    32 +-
 src/archive/zip/zip_test.go                        |    62 +-
 src/bootstrap.bash                                 |     2 +-
 src/bufio/bufio.go                                 |     2 +-
 src/bufio/example_test.go                          |    29 +
 src/bufio/scan.go                                  |    60 +-
 src/bufio/scan_test.go                             |    42 +-
 src/buildall.bash                                  |     2 +-
 src/bytes/buffer.go                                |    17 +-
 src/bytes/bytes_test.go                            |    31 +
 src/cmd/api/goapi.go                               |    18 +-
 src/cmd/api/run.go                                 |     2 +-
 src/cmd/api/testdata/src/pkg/p1/golden.txt         |     2 +-
 src/cmd/asm/doc.go                                 |    48 +
 src/cmd/asm/internal/arch/arch.go                  |    69 +-
 src/cmd/asm/internal/arch/arm.go                   |     1 +
 src/cmd/asm/internal/arch/mips64.go                |    64 +
 src/cmd/asm/internal/asm/asm.go                    |   107 +-
 src/cmd/asm/internal/asm/endtoend_test.go          |   380 +-
 src/cmd/asm/internal/asm/operand_test.go           |    97 +-
 src/cmd/asm/internal/asm/parse.go                  |    72 +-
 src/cmd/asm/internal/asm/pseudo_test.go            |    73 +
 src/cmd/asm/internal/asm/testdata/386.out          |    49 -
 src/cmd/asm/internal/asm/testdata/386.s            |    37 +-
 src/cmd/asm/internal/asm/testdata/amd64.out        |    57 -
 src/cmd/asm/internal/asm/testdata/amd64.s          |    88 +-
 src/cmd/asm/internal/asm/testdata/amd64enc.s       | 10682 +++++++++++++++++++
 src/cmd/asm/internal/asm/testdata/amd64error.s     |     7 +
 src/cmd/asm/internal/asm/testdata/arm.out          |    61 -
 src/cmd/asm/internal/asm/testdata/arm.s            |    55 +-
 src/cmd/asm/internal/asm/testdata/arm64.out        |    55 -
 src/cmd/asm/internal/asm/testdata/arm64.s          |    23 +-
 src/cmd/asm/internal/asm/testdata/mips64.s         |   403 +
 src/cmd/asm/internal/asm/testdata/ppc64.out        |   114 -
 src/cmd/asm/internal/asm/testdata/ppc64.s          |    78 +-
 src/cmd/asm/internal/flags/flags.go                |     4 +
 src/cmd/asm/internal/lex/input.go                  |    25 +-
 src/cmd/asm/internal/lex/lex_test.go               |   208 +
 src/cmd/asm/internal/lex/slice.go                  |    12 +-
 src/cmd/asm/main.go                                |    13 +-
 src/cmd/cgo/ast.go                                 |   104 +-
 src/cmd/cgo/doc.go                                 |   149 +-
 src/cmd/cgo/gcc.go                                 |   354 +-
 src/cmd/cgo/godefs.go                              |     3 +-
 src/cmd/cgo/main.go                                |    44 +-
 src/cmd/cgo/out.go                                 |   248 +-
 src/cmd/compile/doc.go                             |     6 +-
 src/cmd/compile/internal/amd64/cgen.go             |    16 +-
 src/cmd/compile/internal/amd64/galign.go           |     6 +-
 src/cmd/compile/internal/amd64/ggen.go             |   371 +-
 src/cmd/compile/internal/amd64/gsubr.go            |   639 +-
 src/cmd/compile/internal/amd64/peep.go             |     8 +-
 src/cmd/compile/internal/amd64/prog.go             |   437 +-
 src/cmd/compile/internal/amd64/reg.go              |     1 +
 src/cmd/compile/internal/arm/cgen.go               |    13 +-
 src/cmd/compile/internal/arm/cgen64.go             |    14 +-
 src/cmd/compile/internal/arm/galign.go             |     6 +-
 src/cmd/compile/internal/arm/ggen.go               |    18 +-
 src/cmd/compile/internal/arm/gsubr.go              |   411 +-
 src/cmd/compile/internal/arm/peep.go               |     9 +-
 src/cmd/compile/internal/arm/prog.go               |   175 +-
 src/cmd/compile/internal/arm64/cgen.go             |    14 +-
 src/cmd/compile/internal/arm64/galign.go           |     6 +-
 src/cmd/compile/internal/arm64/ggen.go             |    30 +-
 src/cmd/compile/internal/arm64/gsubr.go            |   480 +-
 src/cmd/compile/internal/arm64/peep.go             |     4 +-
 src/cmd/compile/internal/arm64/prog.go             |   173 +-
 src/cmd/compile/internal/big/decimal.go            |    18 +-
 src/cmd/compile/internal/big/decimal_test.go       |    10 +
 src/cmd/compile/internal/big/example_test.go       |    77 +
 src/cmd/compile/internal/big/float.go              |     8 +-
 src/cmd/compile/internal/big/floatconv.go          |   110 +-
 src/cmd/compile/internal/big/floatconv_test.go     |   179 +-
 src/cmd/compile/internal/big/floatexample_test.go  |    30 +
 src/cmd/compile/internal/big/ftoa.go               |   104 +-
 src/cmd/compile/internal/big/int.go                |   136 +-
 src/cmd/compile/internal/big/int_test.go           |   233 +-
 src/cmd/compile/internal/big/intconv.go            |    94 +-
 src/cmd/compile/internal/big/intconv_test.go       |    89 +-
 src/cmd/compile/internal/big/nat.go                |   120 +-
 src/cmd/compile/internal/big/nat_test.go           |   109 +-
 src/cmd/compile/internal/big/natconv.go            |   103 +-
 src/cmd/compile/internal/big/natconv_test.go       |    85 +-
 src/cmd/compile/internal/big/rat.go                |    60 -
 src/cmd/compile/internal/big/rat_test.go           |   114 -
 src/cmd/compile/internal/big/ratconv.go            |    39 +-
 src/cmd/compile/internal/big/ratconv_test.go       |     2 +
 src/cmd/compile/internal/gc/align.go               |   226 +-
 src/cmd/compile/internal/gc/bexport.go             |  1041 ++
 src/cmd/compile/internal/gc/bimport.go             |   634 ++
 src/cmd/compile/internal/gc/builtin.go             |     6 +-
 src/cmd/compile/internal/gc/builtin/runtime.go     |    10 +-
 src/cmd/compile/internal/gc/bv.go                  |    14 +-
 src/cmd/compile/internal/gc/cgen.go                |   423 +-
 src/cmd/compile/internal/gc/closure.go             |    24 +-
 src/cmd/compile/internal/gc/const.go               |   360 +-
 src/cmd/compile/internal/gc/cplx.go                |    33 +-
 src/cmd/compile/internal/gc/dcl.go                 |   402 +-
 src/cmd/compile/internal/gc/esc.go                 |   219 +-
 src/cmd/compile/internal/gc/export.go              |   208 +-
 src/cmd/compile/internal/gc/float_test.go          |   102 +
 src/cmd/compile/internal/gc/fmt.go                 |    98 +-
 src/cmd/compile/internal/gc/gen.go                 |   140 +-
 src/cmd/compile/internal/gc/global_test.go         |    64 +
 src/cmd/compile/internal/gc/go.go                  |   201 +-
 src/cmd/compile/internal/gc/go.y                   |  2316 ----
 src/cmd/compile/internal/gc/gsubr.go               |   101 +-
 src/cmd/compile/internal/gc/init.go                |    46 +-
 src/cmd/compile/internal/gc/inl.go                 |    57 +-
 src/cmd/compile/internal/gc/lex.go                 |   890 +-
 src/cmd/compile/internal/gc/mkbuiltin.go           |     5 +-
 src/cmd/compile/internal/gc/mparith2.go            |     8 +-
 src/cmd/compile/internal/gc/mparith3.go            |    81 +-
 src/cmd/compile/internal/gc/obj.go                 |    62 +-
 src/cmd/compile/internal/gc/opnames.go             |     1 +
 src/cmd/compile/internal/gc/order.go               |    75 +-
 src/cmd/compile/internal/gc/parser.go              |  3506 ++++++
 src/cmd/compile/internal/gc/pgen.go                |    75 +-
 src/cmd/compile/internal/gc/pgen_test.go           |   176 +
 src/cmd/compile/internal/gc/plive.go               |    76 +-
 src/cmd/compile/internal/gc/popt.go                |   183 +-
 src/cmd/compile/internal/gc/racewalk.go            |   198 +-
 src/cmd/compile/internal/gc/range.go               |   170 +-
 src/cmd/compile/internal/gc/reflect.go             |   391 +-
 src/cmd/compile/internal/gc/reflect_test.go        |    47 +
 src/cmd/compile/internal/gc/reg.go                 |   159 +-
 src/cmd/compile/internal/gc/select.go              |    22 +-
 src/cmd/compile/internal/gc/sinit.go               |   382 +-
 src/cmd/compile/internal/gc/subr.go                |   580 +-
 src/cmd/compile/internal/gc/swt.go                 |    67 +-
 src/cmd/compile/internal/gc/swt_test.go            |   144 +
 src/cmd/compile/internal/gc/syntax.go              |    47 +-
 src/cmd/compile/internal/gc/typecheck.go           |   419 +-
 src/cmd/compile/internal/gc/unsafe.go              |    14 +-
 src/cmd/compile/internal/gc/util.go                |    51 +-
 src/cmd/compile/internal/gc/walk.go                |   516 +-
 src/cmd/compile/internal/gc/y.go                   |  3526 ------
 src/cmd/compile/internal/mips64/cgen.go            |   157 +
 src/cmd/compile/internal/mips64/galign.go          |   100 +
 src/cmd/compile/internal/mips64/ggen.go            |   494 +
 src/cmd/compile/internal/mips64/gsubr.go           |  1063 ++
 src/cmd/compile/internal/mips64/peep.go            |   788 ++
 src/cmd/compile/internal/mips64/prog.go            |   174 +
 src/cmd/compile/internal/mips64/reg.go             |   162 +
 src/cmd/compile/internal/ppc64/cgen.go             |    12 +-
 src/cmd/compile/internal/ppc64/galign.go           |    11 +-
 src/cmd/compile/internal/ppc64/ggen.go             |    48 +-
 src/cmd/compile/internal/ppc64/gsubr.go            |   482 +-
 src/cmd/compile/internal/ppc64/peep.go             |     4 +-
 src/cmd/compile/internal/ppc64/prog.go             |   299 +-
 src/cmd/compile/internal/ppc64/reg.go              |     6 +
 src/cmd/compile/internal/x86/cgen64.go             |    32 +-
 src/cmd/compile/internal/x86/galign.go             |     6 +-
 src/cmd/compile/internal/x86/ggen.go               |   115 +-
 src/cmd/compile/internal/x86/gsubr.go              |   582 +-
 src/cmd/compile/internal/x86/peep.go               |     4 +-
 src/cmd/compile/internal/x86/prog.go               |   429 +-
 src/cmd/compile/internal/x86/reg.go                |     6 +-
 src/cmd/compile/main.go                            |     8 +
 src/cmd/cover/html.go                              |    24 +-
 src/cmd/dist/build.go                              |   163 +-
 src/cmd/dist/buildruntime.go                       |    22 +-
 src/cmd/dist/buildtool.go                          |     3 +
 src/cmd/dist/deps.go                               |    64 +
 src/cmd/dist/mkdeps.bash                           |    47 +
 src/cmd/dist/test.go                               |   441 +-
 src/cmd/dist/util.go                               |   150 +-
 src/cmd/dist/util_gc.go                            |     8 +
 src/cmd/dist/util_gccgo.go                         |     4 +
 src/cmd/dist/vfp_arm.s                             |    17 +
 src/cmd/dist/vfp_default.s                         |    13 +
 src/cmd/doc/dirs.go                                |   115 +
 src/cmd/doc/doc_test.go                            |   146 +-
 src/cmd/doc/main.go                                |   217 +-
 src/cmd/doc/pkg.go                                 |    94 +-
 src/cmd/doc/testdata/pkg.go                        |    23 +-
 src/cmd/go/alldocs.go                              |   196 +-
 src/cmd/go/build.go                                |   528 +-
 src/cmd/go/discovery.go                            |     4 +-
 src/cmd/go/doc.go                                  |    23 +-
 src/cmd/go/env.go                                  |     7 +-
 src/cmd/go/generate.go                             |    50 +-
 src/cmd/go/generate_test.go                        |     1 +
 src/cmd/go/get.go                                  |    18 +-
 src/cmd/go/go_test.go                              |   466 +-
 src/cmd/go/go_unix_test.go                         |    31 +
 src/cmd/go/help.go                                 |    50 +-
 src/cmd/go/http.go                                 |    24 +-
 src/cmd/go/list.go                                 |     8 +
 src/cmd/go/main.go                                 |    33 +-
 src/cmd/go/note.go                                 |    27 +-
 src/cmd/go/note_test.go                            |    38 +-
 src/cmd/go/pkg.go                                  |   182 +-
 src/cmd/go/pkg_test.go                             |   118 +
 src/cmd/go/run.go                                  |    16 +-
 src/cmd/go/test.go                                 |   105 +-
 src/cmd/go/testdata/flag_test.go                   |    16 +
 src/cmd/go/testdata/src/run/bad.go                 |     5 +
 src/cmd/go/testdata/src/run/good.go                |     5 +
 src/cmd/go/testdata/src/run/internal/internal.go   |     1 +
 .../src/run/subdir/internal/private/private.go     |     1 +
 src/cmd/go/testdata/src/vend/dir1/dir1.go          |     1 +
 src/cmd/go/testdata/src/vend/hello/hello_test.go   |     2 +-
 src/cmd/go/testdata/src/vend/hello/hellox_test.go  |     2 +-
 .../src/vend/vendor/vend/dir1/dir2/dir2.go         |     1 +
 src/cmd/go/testdata/src/vend/x/x.go                |     2 +
 src/cmd/go/testflag.go                             |     9 +
 src/cmd/go/tool.go                                 |     1 +
 src/cmd/go/vcs.go                                  |    53 +-
 src/cmd/go/vcs_test.go                             |     4 +-
 src/cmd/go/vendor_test.go                          |    26 +-
 src/cmd/gofmt/gofmt.go                             |     5 +-
 src/cmd/gofmt/internal.go                          |   176 +
 src/cmd/gofmt/long_test.go                         |     5 +-
 src/cmd/gofmt/testdata/old.golden                  |     9 -
 src/cmd/gofmt/testdata/old.input                   |     8 -
 src/cmd/internal/goobj/read.go                     |     4 +-
 src/cmd/internal/obj/ar.go                         |    30 -
 src/cmd/internal/obj/arm/a.out.go                  |    12 +-
 src/cmd/internal/obj/arm/anames.go                 |     2 -
 src/cmd/internal/obj/arm/anames5.go                |     3 +
 src/cmd/internal/obj/arm/asm5.go                   |   537 +-
 src/cmd/internal/obj/arm/obj5.go                   |   210 +-
 src/cmd/internal/obj/arm64/a.out.go                |    22 +-
 src/cmd/internal/obj/arm64/anames.go               |     9 -
 src/cmd/internal/obj/arm64/anames7.go              |     3 +
 src/cmd/internal/obj/arm64/asm7.go                 |   202 +-
 src/cmd/internal/obj/arm64/obj7.go                 |   127 +-
 src/cmd/internal/obj/data.go                       |   140 +-
 src/cmd/internal/obj/fmt.go                        |     8 +-
 src/cmd/internal/obj/funcdata.go                   |    35 +-
 src/cmd/internal/obj/libc.go                       |    12 -
 src/cmd/internal/obj/link.go                       |   178 +-
 src/cmd/internal/obj/mgc0.go                       |    30 -
 src/cmd/internal/obj/mips/a.out.go                 |   376 +
 src/cmd/internal/obj/mips/anames.go                |   112 +
 src/cmd/internal/obj/mips/anames0.go               |    38 +
 src/cmd/internal/obj/mips/asm0.go                  |  1733 +++
 src/cmd/internal/obj/mips/list0.go                 |    80 +
 src/cmd/internal/obj/mips/obj0.go                  |  1497 +++
 src/cmd/internal/obj/obj.go                        |     6 +-
 src/cmd/internal/obj/objfile.go                    |    40 +-
 src/cmd/internal/obj/ppc64/a.out.go                |     4 +
 src/cmd/internal/obj/ppc64/anames9.go              |     3 +
 src/cmd/internal/obj/ppc64/asm9.go                 |   818 +-
 src/cmd/internal/obj/ppc64/obj9.go                 |   309 +-
 src/cmd/internal/obj/stack.go                      |    32 +-
 src/cmd/internal/obj/sym.go                        |    67 +-
 src/cmd/internal/obj/textflag.go                   |     9 +
 src/cmd/internal/obj/util.go                       |    64 +-
 src/cmd/internal/obj/x86/a.out.go                  |   114 +-
 src/cmd/internal/obj/x86/anames.go                 |    92 +-
 src/cmd/internal/obj/x86/asm6.go                   |  2218 ++--
 src/cmd/internal/obj/x86/list6.go                  |    16 +
 src/cmd/internal/obj/x86/obj6.go                   |   336 +-
 src/cmd/internal/obj/x86/obj6_test.go              |    17 +-
 src/cmd/internal/objfile/disasm.go                 |     8 +-
 src/cmd/internal/rsc.io/arm/armasm/decode_test.go  |    69 -
 src/cmd/internal/rsc.io/arm/armasm/ext_test.go     |   614 --
 src/cmd/internal/rsc.io/arm/armasm/objdump_test.go |   258 -
 .../internal/rsc.io/arm/armasm/objdumpext_test.go  |   260 -
 src/cmd/internal/rsc.io/arm/armasm/plan9x.go       |   211 -
 src/cmd/internal/rsc.io/x86/x86asm/decode.go       |  1616 ---
 src/cmd/internal/rsc.io/x86/x86asm/decode_test.go  |    71 -
 src/cmd/internal/rsc.io/x86/x86asm/ext_test.go     |   811 --
 src/cmd/internal/rsc.io/x86/x86asm/inst.go         |   641 --
 src/cmd/internal/rsc.io/x86/x86asm/objdump_test.go |   383 -
 .../internal/rsc.io/x86/x86asm/objdumpext_test.go  |   314 -
 .../internal/rsc.io/x86/x86asm/plan9ext_test.go    |   120 -
 src/cmd/internal/rsc.io/x86/x86asm/plan9x.go       |   346 -
 src/cmd/internal/rsc.io/x86/x86asm/xedext_test.go  |   206 -
 .../golang.org/x/arch}/arm/armasm/Makefile         |     0
 .../golang.org/x/arch}/arm/armasm/decode.go        |     0
 .../golang.org/x/arch/arm/armasm/decode_test.go    |    69 +
 .../golang.org/x/arch/arm/armasm/ext_test.go       |   614 ++
 .../golang.org/x/arch}/arm/armasm/gnu.go           |     0
 .../golang.org/x/arch}/arm/armasm/inst.go          |     0
 .../golang.org/x/arch/arm/armasm/objdump_test.go   |   268 +
 .../x/arch/arm/armasm/objdumpext_test.go           |   259 +
 .../golang.org/x/arch/arm/armasm/plan9x.go         |   211 +
 .../golang.org/x/arch}/arm/armasm/tables.go        |     0
 .../x/arch}/arm/armasm/testdata/Makefile           |     0
 .../x/arch}/arm/armasm/testdata/decode.txt         |     0
 .../golang.org/x/arch}/x86/x86asm/Makefile         |     0
 .../golang.org/x/arch/x86/x86asm/decode.go         |  1646 +++
 .../golang.org/x/arch/x86/x86asm/decode_test.go    |    71 +
 .../golang.org/x/arch/x86/x86asm/ext_test.go       |   810 ++
 .../golang.org/x/arch}/x86/x86asm/gnu.go           |     0
 .../unvendor/golang.org/x/arch/x86/x86asm/inst.go  |   643 ++
 .../golang.org/x/arch}/x86/x86asm/inst_test.go     |     0
 .../golang.org/x/arch}/x86/x86asm/intel.go         |     0
 .../golang.org/x/arch/x86/x86asm/objdump_test.go   |   385 +
 .../x/arch/x86/x86asm/objdumpext_test.go           |   313 +
 .../golang.org/x/arch/x86/x86asm/plan9ext_test.go  |   119 +
 .../golang.org/x/arch/x86/x86asm/plan9x.go         |   346 +
 .../golang.org/x/arch}/x86/x86asm/plan9x_test.go   |     0
 .../golang.org/x/arch}/x86/x86asm/tables.go        |     0
 .../x/arch}/x86/x86asm/testdata/Makefile           |     0
 .../x/arch}/x86/x86asm/testdata/decode.txt         |     0
 .../x/arch/x86/x86asm/testdata/libmach8db.c        |  2075 ++++
 .../golang.org/x/arch}/x86/x86asm/xed_test.go      |     0
 .../golang.org/x/arch/x86/x86asm/xedext_test.go    |   205 +
 src/cmd/internal/unvendor/vendor.json              |    16 +
 src/cmd/link/doc.go                                |    11 +
 src/cmd/link/internal/amd64/asm.go                 |     6 +-
 src/cmd/link/internal/arm/asm.go                   |   102 +-
 src/cmd/link/internal/arm/l.go                     |     3 -
 src/cmd/link/internal/arm/obj.go                   |    10 +-
 src/cmd/link/internal/arm64/asm.go                 |   170 +-
 src/cmd/link/internal/arm64/l.go                   |     3 -
 src/cmd/link/internal/arm64/obj.go                 |     4 +
 src/cmd/link/internal/ld/ar.go                     |   139 +-
 src/cmd/link/internal/ld/arch.go                   |    18 +
 src/cmd/link/internal/ld/data.go                   |   184 +-
 src/cmd/link/internal/ld/decodesym.go              |    10 +-
 src/cmd/link/internal/ld/dwarf.go                  |   247 +-
 src/cmd/link/internal/ld/elf.go                    |   755 +-
 src/cmd/link/internal/ld/go.go                     |   238 +-
 src/cmd/link/internal/ld/ldelf.go                  |   154 +-
 src/cmd/link/internal/ld/ldpe.go                   |     5 +-
 src/cmd/link/internal/ld/lib.go                    |   450 +-
 src/cmd/link/internal/ld/link.go                   |    93 +-
 src/cmd/link/internal/ld/macho.go                  |    25 +-
 src/cmd/link/internal/ld/pcln.go                   |    15 +
 src/cmd/link/internal/ld/pe.go                     |    35 +-
 src/cmd/link/internal/ld/pobj.go                   |     4 +-
 src/cmd/link/internal/ld/sym.go                    |    29 +-
 src/cmd/link/internal/ld/symtab.go                 |    74 +-
 src/cmd/link/internal/ld/textflag.go               |    29 -
 src/cmd/link/internal/ld/util.go                   |    18 -
 src/cmd/link/internal/mips64/asm.go                |   248 +
 src/cmd/link/internal/mips64/l.go                  |    75 +
 src/cmd/link/internal/mips64/obj.go                |   158 +
 src/cmd/link/internal/ppc64/asm.go                 |   316 +-
 src/cmd/link/internal/ppc64/l.go                   |     3 -
 src/cmd/link/internal/ppc64/obj.go                 |    17 +
 src/cmd/link/internal/x86/asm.go                   |   135 +-
 src/cmd/link/internal/x86/l.go                     |     2 -
 src/cmd/link/internal/x86/obj.go                   |     7 +
 src/cmd/link/main.go                               |     3 +
 src/cmd/objdump/objdump_test.go                    |     4 +
 src/cmd/pprof/internal/profile/legacy_profile.go   |     2 +-
 src/cmd/pprof/internal/report/report.go            |     2 +-
 src/cmd/pprof/pprof.go                             |     1 +
 src/cmd/trace/main.go                              |     2 +-
 src/cmd/vet/cgo.go                                 |   130 +
 src/cmd/vet/composite.go                           |     2 +-
 src/cmd/vet/copylock.go                            |    22 +-
 src/cmd/vet/doc.go                                 |   127 +-
 src/cmd/vet/example.go                             |   124 +
 src/cmd/vet/internal/whitelist/whitelist.go        |    53 +
 src/cmd/vet/main.go                                |    33 +-
 src/cmd/vet/print.go                               |    19 +-
 src/cmd/vet/shadow.go                              |     2 +
 src/cmd/vet/testdata/cgo.go                        |    54 +
 src/cmd/vet/testdata/cgo2.go                       |     9 +
 src/cmd/vet/testdata/copylock.go                   |    28 +
 src/cmd/vet/testdata/copylock_func.go              |    22 +-
 src/cmd/vet/testdata/copylock_range.go             |    26 +-
 src/cmd/vet/testdata/divergent/buf.go              |    17 +
 src/cmd/vet/testdata/divergent/buf_test.go         |    35 +
 src/cmd/vet/testdata/examples_test.go              |    48 +
 src/cmd/vet/testdata/incomplete/examples_test.go   |    33 +
 src/cmd/vet/testdata/print.go                      |    14 +-
 src/cmd/vet/testdata/shadow.go                     |     7 +-
 src/cmd/vet/vet_test.go                            |   101 +-
 src/cmd/vet/whitelist/whitelist.go                 |    53 -
 src/cmd/yacc/yacc.go                               |    44 +-
 src/compress/bzip2/bit_reader.go                   |     8 -
 src/compress/bzip2/bzip2_test.go                   |     6 +-
 src/compress/bzip2/huffman.go                      |    44 +-
 .../bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2   |   Bin 124744 -> 118509 bytes
 src/compress/bzip2/testdata/random.data.bz2        |   Bin 0 -> 16846 bytes
 src/compress/flate/deflate_test.go                 |    10 +-
 src/compress/flate/fixedhuff.go                    |    78 -
 src/compress/flate/flate_test.go                   |    14 +
 src/compress/flate/gen.go                          |   265 -
 src/compress/flate/inflate.go                      |    66 +-
 src/compress/flate/reader_test.go                  |     2 +-
 src/compress/flate/token.go                        |    10 +-
 src/compress/gzip/gunzip.go                        |    24 +-
 src/compress/gzip/gunzip_test.go                   |    32 +
 src/compress/gzip/gzip.go                          |     7 +-
 src/compress/lzw/reader.go                         |    17 +-
 src/compress/lzw/writer_test.go                    |    10 +-
 src/compress/testdata/Mark.Twain-Tom.Sawyer.txt    |   393 -
 src/compress/testdata/gettysburg.txt               |    29 +
 src/compress/zlib/reader.go                        |     9 +
 src/compress/zlib/reader_test.go                   |    24 +
 src/compress/zlib/writer_test.go                   |    27 +-
 src/crypto/aes/aes_gcm.go                          |   172 +
 src/crypto/aes/asm_amd64.s                         |     8 +-
 src/crypto/aes/cipher.go                           |     9 +-
 src/crypto/aes/cipher_generic.go                   |     8 +
 src/crypto/aes/gcm_amd64.s                         |  1277 +++
 src/crypto/cipher/benchmark_test.go                |    30 +-
 src/crypto/cipher/ctr.go                           |     5 +-
 src/crypto/cipher/ctr_test.go                      |    55 +
 src/crypto/cipher/example_test.go                  |    52 +
 src/crypto/cipher/gcm.go                           |    39 +-
 src/crypto/cipher/gcm_test.go                      |    92 +-
 src/crypto/crypto.go                               |     8 +-
 src/crypto/dsa/dsa.go                              |     2 +-
 src/crypto/ecdsa/ecdsa.go                          |    39 +-
 src/crypto/ecdsa/ecdsa_test.go                     |    43 +-
 src/crypto/elliptic/elliptic.go                    |     9 +-
 src/crypto/elliptic/elliptic_test.go               |    12 +
 src/crypto/elliptic/p256.go                        |     2 +
 src/crypto/elliptic/p256_amd64.go                  |   552 +
 src/crypto/elliptic/p256_asm_amd64.s               |  2295 ++++
 src/crypto/hmac/hmac.go                            |     4 +-
 src/crypto/md5/md5.go                              |    10 +-
 src/crypto/rsa/example_test.go                     |   169 +
 src/crypto/rsa/pkcs1v15.go                         |    25 +-
 src/crypto/rsa/pkcs1v15_test.go                    |     2 +-
 src/crypto/rsa/pss.go                              |     2 +-
 src/crypto/rsa/rsa.go                              |    56 +-
 src/crypto/rsa/rsa_test.go                         |    27 +-
 src/crypto/tls/cipher_suites.go                    |     4 +
 src/crypto/tls/common.go                           |     6 +-
 src/crypto/tls/conn.go                             |   103 +-
 src/crypto/tls/handshake_client.go                 |    13 +-
 src/crypto/tls/handshake_client_test.go            |    94 +
 src/crypto/tls/handshake_messages.go               |     4 +
 src/crypto/tls/handshake_server_test.go            |     2 +-
 src/crypto/tls/prf.go                              |    17 +-
 .../testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA  |   104 +-
 .../testdata/Client-TLSv10-ClientCert-ECDSA-RSA    |   167 +-
 .../testdata/Client-TLSv10-ClientCert-RSA-ECDSA    |   100 +-
 .../tls/testdata/Client-TLSv10-ClientCert-RSA-RSA  |   167 +-
 .../tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES     |    84 +-
 .../tls/testdata/Client-TLSv10-ECDHE-RSA-AES       |   165 +-
 src/crypto/tls/testdata/Client-TLSv10-RSA-RC4      |   149 +-
 .../tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES     |    84 +-
 .../tls/testdata/Client-TLSv11-ECDHE-RSA-AES       |   165 +-
 src/crypto/tls/testdata/Client-TLSv11-RSA-RC4      |   149 +-
 .../tls/testdata/Client-TLSv12-AES128-GCM-SHA256   |    81 +
 .../tls/testdata/Client-TLSv12-AES256-GCM-SHA384   |    81 +
 src/crypto/tls/testdata/Client-TLSv12-ALPN         |   164 +-
 src/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch |   161 +-
 .../testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA  |   111 +-
 .../testdata/Client-TLSv12-ClientCert-ECDSA-RSA    |   171 +-
 .../Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384 |   183 +-
 .../testdata/Client-TLSv12-ClientCert-RSA-ECDSA    |   107 +-
 .../tls/testdata/Client-TLSv12-ClientCert-RSA-RSA  |   171 +-
 .../tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES     |    84 +-
 .../tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM |    76 +-
 .../Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384    |    76 +-
 .../tls/testdata/Client-TLSv12-ECDHE-RSA-AES       |   165 +-
 src/crypto/tls/testdata/Client-TLSv12-RSA-RC4      |   149 +-
 src/crypto/tls/testdata/Client-TLSv12-SCT          |   161 +-
 src/crypto/tls/testdata/Server-SSLv3-RSA-3DES      |    60 +-
 src/crypto/tls/testdata/Server-SSLv3-RSA-AES       |    62 +-
 src/crypto/tls/testdata/Server-SSLv3-RSA-RC4       |    52 +-
 .../tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES     |    78 +-
 src/crypto/tls/testdata/Server-TLSv10-RSA-3DES     |    52 +-
 src/crypto/tls/testdata/Server-TLSv10-RSA-AES      |    58 +-
 src/crypto/tls/testdata/Server-TLSv10-RSA-RC4      |    46 +-
 src/crypto/tls/testdata/Server-TLSv11-FallbackSCSV |    28 +-
 src/crypto/tls/testdata/Server-TLSv11-RSA-RC4      |    46 +-
 src/crypto/tls/testdata/Server-TLSv12-ALPN         |    84 +-
 src/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch |    84 +-
 .../Server-TLSv12-CipherSuiteCertPreferenceECDSA   |    76 +-
 .../Server-TLSv12-CipherSuiteCertPreferenceRSA     |    76 +-
 .../Server-TLSv12-ClientAuthRequestedAndECDSAGiven |    68 +-
 .../Server-TLSv12-ClientAuthRequestedAndGiven      |    68 +-
 .../Server-TLSv12-ClientAuthRequestedNotGiven      |    50 +-
 .../tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES     |    78 +-
 src/crypto/tls/testdata/Server-TLSv12-IssueTicket  |    64 +-
 .../testdata/Server-TLSv12-IssueTicketPreDisable   |    64 +-
 src/crypto/tls/testdata/Server-TLSv12-RSA-3DES     |    56 +-
 src/crypto/tls/testdata/Server-TLSv12-RSA-AES      |    60 +-
 src/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM  |    67 +-
 .../testdata/Server-TLSv12-RSA-AES256-GCM-SHA384   |    67 +-
 src/crypto/tls/testdata/Server-TLSv12-RSA-RC4      |    50 +-
 src/crypto/tls/testdata/Server-TLSv12-Resume       |    60 +-
 .../tls/testdata/Server-TLSv12-ResumeDisabled      |    70 +-
 src/crypto/tls/testdata/Server-TLSv12-SNI          |    44 +-
 .../tls/testdata/Server-TLSv12-SNI-GetCertificate  |    44 +-
 .../Server-TLSv12-SNI-GetCertificateNotFound       |    44 +-
 src/crypto/tls/tls.go                              |    55 +-
 src/crypto/tls/tls_test.go                         |   134 +
 src/crypto/x509/pkix/pkix.go                       |     6 +-
 src/crypto/x509/root_unix.go                       |     1 +
 src/crypto/x509/sec1.go                            |    28 +-
 src/crypto/x509/sec1_test.go                       |    42 +-
 src/crypto/x509/verify.go                          |    18 +
 src/crypto/x509/x509.go                            |   119 +-
 src/crypto/x509/x509_test.go                       |   101 +-
 src/database/sql/convert.go                        |    38 +-
 src/database/sql/convert_test.go                   |    61 +-
 src/database/sql/driver/types.go                   |    13 +-
 src/database/sql/fakedb_test.go                    |    59 +-
 src/database/sql/sql.go                            |   258 +-
 src/database/sql/sql_test.go                       |   341 +-
 src/debug/dwarf/class_string.go                    |     7 +-
 src/debug/dwarf/entry.go                           |    11 +-
 src/debug/dwarf/entry_test.go                      |    36 +
 src/debug/dwarf/testdata/cycle.c                   |     7 +
 src/debug/dwarf/testdata/cycle.elf                 |   Bin 0 -> 2624 bytes
 src/debug/dwarf/testdata/line-clang.elf            |   Bin
 src/debug/dwarf/testdata/line-gcc.elf              |   Bin
 src/debug/dwarf/testdata/split.c                   |     5 +
 src/debug/dwarf/testdata/split.elf                 |   Bin 0 -> 9509 bytes
 src/debug/dwarf/type.go                            |    34 +-
 src/debug/dwarf/type_test.go                       |    34 +
 src/debug/dwarf/typeunit.go                        |     2 +-
 src/debug/elf/elf.go                               |   148 +
 src/debug/elf/file.go                              |   159 +-
 src/debug/elf/file_test.go                         |   503 +-
 src/debug/elf/reader.go                            |   108 +
 src/debug/elf/testdata/compressed-32.obj           |   Bin 0 -> 2208 bytes
 src/debug/elf/testdata/compressed-64.obj           |   Bin 0 -> 3280 bytes
 src/debug/elf/testdata/gcc-386-freebsd-exec        |   Bin
 src/debug/elf/testdata/gcc-amd64-linux-exec        |   Bin
 .../testdata/go-relocation-test-gcc492-mips64.obj  |   Bin 0 -> 4120 bytes
 .../go-relocation-test-gcc493-mips64le.obj         |   Bin 0 -> 4160 bytes
 .../elf/testdata/zdebug-test-gcc484-x86-64.obj     |   Bin 0 -> 3216 bytes
 src/debug/gosym/pclntab_test.go                    |    48 +-
 src/debug/macho/testdata/gcc-386-darwin-exec       |   Bin
 src/debug/macho/testdata/gcc-amd64-darwin-exec     |   Bin
 src/debug/plan9obj/testdata/386-plan9-exec         |   Bin
 src/debug/plan9obj/testdata/amd64-plan9-exec       |   Bin
 src/encoding/asn1/asn1.go                          |   111 +-
 src/encoding/asn1/asn1_test.go                     |    73 +-
 src/encoding/asn1/common.go                        |    74 +-
 src/encoding/asn1/marshal.go                       |    37 +-
 src/encoding/base64/base64.go                      |    78 +-
 src/encoding/base64/base64_test.go                 |    35 +-
 src/encoding/base64/example_test.go                |    15 +
 src/encoding/binary/binary.go                      |     4 +
 src/encoding/binary/binary_test.go                 |    30 +
 src/encoding/csv/reader.go                         |     2 +-
 src/encoding/gob/codec_test.go                     |     4 +-
 src/encoding/gob/dec_helpers.go                    |     9 +-
 src/encoding/gob/decgen.go                         |     9 +-
 src/encoding/gob/decode.go                         |    64 +-
 src/encoding/gob/doc.go                            |    29 +-
 src/encoding/gob/encode.go                         |    19 +-
 src/encoding/gob/encoder_test.go                   |     2 +-
 src/encoding/gob/timing_test.go                    |    45 +-
 src/encoding/gob/type.go                           |     2 +-
 src/encoding/json/decode.go                        |    90 +-
 src/encoding/json/decode_test.go                   |    43 +-
 src/encoding/json/encode.go                        |    29 +-
 src/encoding/json/encode_test.go                   |    22 +-
 src/encoding/json/indent.go                        |    12 +-
 src/encoding/json/number_test.go                   |   133 +
 src/encoding/json/scanner.go                       |   101 +-
 src/encoding/json/stream.go                        |     8 +-
 src/encoding/pem/pem_test.go                       |    28 +-
 src/encoding/xml/marshal.go                        |    36 +-
 src/encoding/xml/marshal_test.go                   |    61 +-
 src/encoding/xml/read.go                           |     2 +-
 src/encoding/xml/read_test.go                      |    21 +
 src/encoding/xml/typeinfo.go                       |     9 +-
 src/encoding/xml/xml.go                            |    55 +-
 src/encoding/xml/xml_test.go                       |    53 +
 src/fmt/doc.go                                     |     8 +-
 src/fmt/fmt_test.go                                |    16 +-
 src/fmt/norace_test.go                             |     9 -
 src/fmt/print.go                                   |    23 +-
 src/fmt/race_test.go                               |     9 -
 src/fmt/scan.go                                    |    12 +-
 src/fmt/scan_test.go                               |     5 +
 src/go/ast/import.go                               |     6 +-
 src/go/build/build.go                              |   198 +-
 src/go/build/build_test.go                         |    73 +-
 src/go/build/deps_test.go                          |    67 +-
 src/go/build/doc.go                                |     1 +
 src/go/constant/go13.go                            |    24 -
 src/go/constant/go14.go                            |    13 -
 src/go/constant/value.go                           |   661 +-
 src/go/constant/value_test.go                      |   118 +-
 src/go/doc/reader.go                               |    25 +-
 src/go/doc/testdata/issue13742.0.golden            |    25 +
 src/go/doc/testdata/issue13742.1.golden            |    25 +
 src/go/doc/testdata/issue13742.2.golden            |    25 +
 src/go/doc/testdata/issue13742.go                  |    18 +
 src/go/format/format.go                            |     5 +-
 src/go/format/format_test.go                       |    23 +-
 src/go/format/internal.go                          |   176 +
 src/go/importer/importer.go                        |    47 +-
 src/go/internal/gccgoimporter/importer_test.go     |     8 +-
 src/go/internal/gcimporter/bimport.go              |   681 ++
 src/go/internal/gcimporter/exportdata.go           |    11 +-
 src/go/internal/gcimporter/gcimporter.go           |   181 +-
 src/go/internal/gcimporter/gcimporter_test.go      |   176 +-
 src/go/internal/gcimporter/testdata/a.go           |    14 +
 src/go/internal/gcimporter/testdata/b.go           |    11 +
 src/go/parser/parser.go                            |   110 +-
 src/go/parser/short_test.go                        |    31 +-
 src/go/printer/nodes.go                            |    43 +-
 src/go/printer/printer.go                          |     4 +-
 src/go/printer/printer_test.go                     |    41 +
 src/go/printer/testdata/expressions.golden         |    22 +-
 src/go/printer/testdata/expressions.input          |    18 +
 src/go/printer/testdata/expressions.raw            |    22 +-
 src/go/types/api.go                                |    55 +-
 src/go/types/api_test.go                           |    34 +-
 src/go/types/assignments.go                        |    89 +-
 src/go/types/builtins.go                           |   184 +-
 src/go/types/call.go                               |    35 +-
 src/go/types/check_test.go                         |     5 +
 src/go/types/conversions.go                        |     4 +-
 src/go/types/decl.go                               |     2 +-
 src/go/types/eval_test.go                          |     2 +-
 src/go/types/expr.go                               |   255 +-
 src/go/types/go11.go                               |    17 -
 src/go/types/go12.go                               |    17 -
 src/go/types/gotype.go                             |   322 +
 src/go/types/issues_test.go                        |    88 +
 src/go/types/operand.go                            |    98 +-
 src/go/types/package.go                            |     3 +
 src/go/types/resolver.go                           |    62 +-
 src/go/types/resolver_test.go                      |    15 +-
 src/go/types/sizes.go                              |    48 +-
 src/go/types/stdlib_test.go                        |    19 +-
 src/go/types/stmt.go                               |   142 +-
 src/go/types/testdata/builtins.src                 |    84 +-
 src/go/types/testdata/const0.src                   |    13 +
 src/go/types/testdata/const1.src                   |     8 +
 src/go/types/testdata/decls0.src                   |     5 +-
 src/go/types/testdata/decls1.src                   |    16 +-
 src/go/types/testdata/errors.src                   |     4 +-
 src/go/types/testdata/expr0.src                    |     8 +-
 src/go/types/testdata/expr1.src                    |   120 +
 src/go/types/testdata/expr3.src                    |    48 +-
 src/go/types/testdata/importC.src                  |    10 +
 src/go/types/testdata/issues.src                   |    99 +-
 src/go/types/testdata/stmt0.src                    |   182 +-
 src/go/types/testdata/vardecl.src                  |     4 +-
 src/go/types/type.go                               |    17 +-
 src/go/types/typestring.go                         |     4 +-
 src/go/types/typestring_test.go                    |     1 +
 src/go/types/typexpr.go                            |    21 +-
 src/hash/adler32/adler32.go                        |     1 +
 src/hash/crc32/crc32.go                            |    23 +-
 src/hash/crc32/crc32_amd64.go                      |    56 +
 src/hash/crc32/crc32_amd64.s                       |   167 +
 src/hash/crc32/crc32_amd64p32.go                   |    38 +
 src/hash/crc32/crc32_amd64x.go                     |    27 -
 src/hash/crc32/crc32_generic.go                    |    13 +-
 src/hash/crc64/crc64.go                            |     4 +-
 src/hash/fnv/fnv.go                                |     6 +-
 src/html/escape.go                                 |    60 +-
 src/html/escape_test.go                            |    20 +-
 src/html/template/clone_test.go                    |    12 +-
 src/html/template/context.go                       |     3 +-
 src/html/template/escape_test.go                   |   124 +-
 src/html/template/example_test.go                  |    37 +
 src/html/template/template.go                      |    21 +-
 src/html/template/template_test.go                 |    29 +
 src/html/template/transition.go                    |     2 +-
 src/image/color/ycbcr.go                           |    62 +-
 src/image/color/ycbcr_test.go                      |    26 +-
 src/image/draw/draw.go                             |    50 +-
 src/image/gif/writer.go                            |     2 +-
 src/image/gif/writer_test.go                       |    10 +-
 src/image/image.go                                 |    21 +-
 src/image/png/reader.go                            |     7 +-
 src/image/png/reader_test.go                       |    12 +
 src/image/ycbcr.go                                 |   126 +-
 src/internal/format/format.go                      |   163 -
 .../golang.org/x/net/http2/hpack/encode.go         |   251 +
 .../golang.org/x/net/http2/hpack/encode_test.go    |   330 +
 src/internal/golang.org/x/net/http2/hpack/hpack.go |   533 +
 .../golang.org/x/net/http2/hpack/hpack_test.go     |   813 ++
 .../golang.org/x/net/http2/hpack/huffman.go        |   190 +
 .../golang.org/x/net/http2/hpack/tables.go         |   352 +
 src/internal/race/doc.go                           |    11 +
 src/internal/race/norace.go                        |    40 +
 src/internal/race/race.go                          |    50 +
 src/internal/syscall/unix/getrandom_linux.go       |     9 -
 src/internal/syscall/unix/getrandom_linux_386.go   |     7 +
 src/internal/syscall/unix/getrandom_linux_amd64.go |     7 +
 src/internal/syscall/unix/getrandom_linux_arm.go   |     7 +
 .../syscall/unix/getrandom_linux_generic.go        |     9 +
 .../syscall/unix/getrandom_linux_mips64x.go        |     9 +
 .../syscall/unix/getrandom_linux_ppc64x.go         |     9 +
 .../syscall/windows/registry/registry_test.go      |    74 +
 src/internal/syscall/windows/registry/syscall.go   |     5 +
 src/internal/syscall/windows/registry/value.go     |    65 +-
 .../syscall/windows/registry/zsyscall_windows.go   |     9 +
 src/internal/syscall/windows/syscall_windows.go    |    17 +-
 src/internal/syscall/windows/zsyscall_windows.go   |    25 +-
 src/internal/trace/parser.go                       |     2 +-
 src/internal/trace/parser_test.go                  |     2 +-
 src/io/example_test.go                             |   223 +
 src/io/io.go                                       |    13 +-
 src/io/ioutil/example_test.go                      |    71 +
 src/io/ioutil/ioutil.go                            |     2 +-
 src/io/multi.go                                    |    24 +
 src/io/multi_test.go                               |    53 +-
 src/log/syslog/doc.go                              |    14 +-
 src/log/syslog/syslog_test.go                      |    43 +-
 src/make.bash                                      |     9 +-
 src/math/abs.go                                    |    13 +-
 src/math/abs_386.s                                 |    12 -
 src/math/abs_amd64.s                               |    14 -
 src/math/abs_amd64p32.s                            |     5 -
 src/math/abs_arm.s                                 |    13 -
 src/math/abs_arm64.s                               |    11 -
 src/math/abs_ppc64x.s                              |    14 -
 src/math/all_test.go                               |    26 +-
 src/math/big/arith_mips64x.s                       |    46 +
 src/math/big/decimal.go                            |    18 +-
 src/math/big/decimal_test.go                       |    10 +
 src/math/big/doc.go                                |    99 +
 src/math/big/example_rat_test.go                   |    65 +
 src/math/big/float.go                              |     8 +-
 src/math/big/floatconv.go                          |   110 +-
 src/math/big/floatconv_test.go                     |   179 +-
 src/math/big/floatexample_test.go                  |    30 +
 src/math/big/floatmarsh.go                         |    33 +
 src/math/big/floatmarsh_test.go                    |    54 +
 src/math/big/ftoa.go                               |   104 +-
 src/math/big/int.go                                |   128 +-
 src/math/big/int_test.go                           |   208 +-
 src/math/big/intconv.go                            |    94 +-
 src/math/big/intconv_test.go                       |    89 +-
 src/math/big/intmarsh.go                           |    74 +
 src/math/big/intmarsh_test.go                      |   121 +
 src/math/big/nat.go                                |    82 +-
 src/math/big/nat_test.go                           |    22 +-
 src/math/big/natconv.go                            |   103 +-
 src/math/big/natconv_test.go                       |    85 +-
 src/math/big/rat.go                                |    60 -
 src/math/big/rat_test.go                           |   114 -
 src/math/big/ratconv.go                            |    36 +-
 src/math/big/ratmarsh.go                           |    73 +
 src/math/big/ratmarsh_test.go                      |   125 +
 src/math/cmplx/cmath_test.go                       |    10 +-
 src/math/cmplx/sqrt.go                             |     2 +-
 src/math/expm1.go                                  |     2 +-
 src/math/floor_amd64.s                             |    23 +
 src/math/floor_asm.go                              |    12 +
 src/math/j0.go                                     |     4 +-
 src/math/j1.go                                     |     4 +-
 src/math/jn.go                                     |     2 -
 src/math/modf.go                                   |     5 +-
 src/math/modf_386.s                                |    13 +
 src/math/rand/rand.go                              |    47 +-
 src/math/rand/rand_test.go                         |    84 +-
 src/math/rand/regress_test.go                      |    77 +-
 src/math/sqrt.go                                   |     2 +-
 src/math/stubs_mips64x.s                           |    91 +
 src/mime/encodedword.go                            |   161 +-
 src/mime/encodedword_test.go                       |    95 +-
 src/mime/example_test.go                           |    98 +
 src/mime/mediatype.go                              |    43 +-
 src/mime/mediatype_test.go                         |     9 +-
 src/mime/multipart/multipart.go                    |     2 +-
 src/mime/multipart/multipart_test.go               |    79 +
 src/net/addrselect.go                              |    43 +
 src/net/addrselect_test.go                         |   115 +
 src/net/cgo_socknew.go                             |     4 +-
 src/net/cgo_sockold.go                             |     4 +-
 src/net/cgo_unix.go                                |    19 +-
 src/net/conf.go                                    |     3 +-
 src/net/dial.go                                    |    17 +-
 src/net/dial_test.go                               |    74 +-
 src/net/dnsclient.go                               |    33 +-
 src/net/dnsclient_test.go                          |    48 +
 src/net/dnsclient_unix.go                          |    41 +-
 src/net/dnsclient_unix_test.go                     |   133 +-
 src/net/dnsmsg.go                                  |     3 +
 src/net/error_test.go                              |    48 +-
 src/net/fd_plan9.go                                |     8 +
 src/net/fd_unix.go                                 |    20 +-
 src/net/fd_windows.go                              |    41 +-
 src/net/file_test.go                               |   366 +-
 src/net/file_unix.go                               |     2 +-
 src/net/hosts.go                                   |    95 +-
 src/net/hosts_test.go                              |    27 +-
 src/net/http/cgi/host.go                           |    24 +-
 src/net/http/cgi/host_test.go                      |    27 +-
 src/net/http/client.go                             |   221 +-
 src/net/http/client_test.go                        |   209 +-
 src/net/http/clientserver_test.go                  |  1056 ++
 src/net/http/doc.go                                |    15 +
 src/net/http/export_test.go                        |   106 +-
 src/net/http/fcgi/child.go                         |     3 +
 src/net/http/fcgi/fcgi_test.go                     |    24 +
 src/net/http/fs.go                                 |    76 +-
 src/net/http/fs_test.go                            |   129 +-
 src/net/http/h2_bundle.go                          |  6671 ++++++++++++
 src/net/http/header.go                             |    10 +
 src/net/http/httptest/recorder.go                  |    45 +-
 src/net/http/httptest/recorder_test.go             |    55 +
 src/net/http/httptest/server.go                    |   285 +-
 src/net/http/httptest/server_test.go               |    71 +
 src/net/http/httputil/dump.go                      |    63 +-
 src/net/http/httputil/dump_test.go                 |    17 +
 src/net/http/httputil/example_test.go              |   123 +
 src/net/http/httputil/reverseproxy.go              |    31 +-
 src/net/http/httputil/reverseproxy_test.go         |   124 +-
 src/net/http/internal/chunked.go                   |    42 +-
 src/net/http/internal/chunked_test.go              |    51 +-
 src/net/http/internal/testcert.go                  |    41 +
 src/net/http/lex.go                                |    14 +
 src/net/http/main_test.go                          |    18 +
 src/net/http/method.go                             |    20 +
 src/net/http/pprof/pprof.go                        |    15 +-
 src/net/http/request.go                            |   219 +-
 src/net/http/request_test.go                       |    38 +-
 src/net/http/response.go                           |    22 +-
 src/net/http/response_test.go                      |   157 +-
 src/net/http/serve_test.go                         |   976 +-
 src/net/http/server.go                             |   741 +-
 src/net/http/sniff.go                              |    29 +-
 src/net/http/sniff_test.go                         |    46 +-
 src/net/http/status.go                             |    46 +-
 src/net/http/transfer.go                           |    87 +-
 src/net/http/transport.go                          |   753 +-
 src/net/http/transport_test.go                     |   431 +-
 src/net/http/triv.go                               |     5 +-
 src/net/interface_test.go                          |    44 +-
 src/net/interface_windows.go                       |   330 +-
 src/net/interface_windows_test.go                  |   132 +
 src/net/internal/socktest/switch.go                |     4 +-
 src/net/iprawsock_posix.go                         |     4 +-
 src/net/ipsock.go                                  |     2 +-
 src/net/ipsock_posix.go                            |    15 +-
 src/net/listen_test.go                             |     4 +-
 src/net/lookup.go                                  |    18 +-
 src/net/lookup_plan9.go                            |    12 +-
 src/net/lookup_test.go                             |   201 +-
 src/net/lookup_windows.go                          |    21 +-
 src/net/lookup_windows_test.go                     |    20 +-
 src/net/mac.go                                     |    11 +-
 src/net/mac_test.go                                |    24 +
 src/net/mail/message.go                            |    23 +-
 src/net/mail/message_test.go                       |    68 +-
 src/net/net.go                                     |    24 +-
 src/net/net_test.go                                |    52 +-
 src/net/net_windows_test.go                        |   407 +-
 src/net/non_unix_test.go                           |    15 +-
 src/net/parse.go                                   |    44 +-
 src/net/parse_test.go                              |    22 +
 src/net/platform_test.go                           |     4 +-
 src/net/port.go                                    |    24 -
 src/net/port_test.go                               |    57 -
 src/net/race.go                                    |    31 -
 src/net/race0.go                                   |    26 -
 src/net/rpc/server.go                              |     8 +-
 src/net/rpc/server_test.go                         |    37 +
 src/net/sendfile_solaris.go                        |     2 +
 src/net/server_test.go                             |     6 +-
 src/net/sock_posix.go                              |     8 +-
 src/net/tcp_test.go                                |     8 +-
 src/net/tcpsock_plan9.go                           |     5 +-
 src/net/tcpsock_posix.go                           |    10 +-
 src/net/tcpsockopt_plan9.go                        |     3 +-
 src/net/testdata/case-hosts                        |     2 +
 src/net/testdata/hosts                             |     3 +-
 src/net/textproto/reader.go                        |    18 +-
 src/net/textproto/reader_test.go                   |    55 +
 src/net/timeout_test.go                            |    51 +-
 src/net/udpsock_posix.go                           |     6 +-
 src/net/unix_test.go                               |    50 +-
 src/net/unixsock_posix.go                          |    11 +-
 src/net/url/url.go                                 |   119 +-
 src/net/url/url_test.go                            |   224 +-
 src/os/doc.go                                      |     6 +-
 src/os/error.go                                    |     2 +-
 src/os/error_plan9.go                              |     6 +
 src/os/error_test.go                               |    19 +
 src/os/error_unix.go                               |     6 +
 src/os/error_windows.go                            |     9 +
 src/os/exec/exec.go                                |   114 +-
 src/os/exec/exec_test.go                           |    19 +
 src/os/exec/internal_test.go                       |    61 +
 src/os/file.go                                     |    12 +-
 src/os/file_plan9.go                               |    11 +-
 src/os/file_unix.go                                |    55 +-
 src/os/file_windows.go                             |    47 +-
 src/os/os_test.go                                  |    59 +-
 src/os/os_unix_test.go                             |    23 +-
 src/os/os_windows_test.go                          |    97 +
 src/os/path_test.go                                |     2 +-
 src/os/pipe_test.go                                |   113 +
 src/os/signal/doc.go                               |   220 +
 src/os/signal/example_test.go                      |     2 +-
 src/os/signal/sig.s                                |    32 +-
 src/os/signal/signal.go                            |     1 -
 src/os/signal/signal_test.go                       |    18 +-
 src/os/signal/signal_unix.go                       |     2 +-
 src/os/stat_darwin.go                              |    28 +-
 src/os/stat_dragonfly.go                           |    28 +-
 src/os/stat_freebsd.go                             |    28 +-
 src/os/stat_linux.go                               |    28 +-
 src/os/stat_nacl.go                                |    28 +-
 src/os/stat_netbsd.go                              |    28 +-
 src/os/stat_openbsd.go                             |    28 +-
 src/os/stat_solaris.go                             |    28 +-
 src/os/stat_windows.go                             |     2 +-
 src/os/types_notwin.go                             |    25 -
 src/os/types_plan9.go                              |    21 +
 src/os/types_unix.go                               |    27 +
 src/os/user/lookup_unix.go                         |    19 +-
 src/path/filepath/example_unix_test.go             |     2 +-
 src/path/filepath/match_test.go                    |     2 +-
 src/path/filepath/path.go                          |    10 +-
 src/path/filepath/path_plan9.go                    |     4 +
 src/path/filepath/path_test.go                     |   193 +-
 src/path/filepath/path_unix.go                     |     4 +
 src/path/filepath/path_windows.go                  |     9 +
 src/path/filepath/path_windows_test.go             |    63 +
 src/path/filepath/symlink.go                       |   135 +-
 src/path/filepath/symlink_windows.go               |     1 -
 src/path/path.go                                   |     2 +-
 src/race.bash                                      |     2 +-
 src/race.bat                                       |     2 +-
 src/reflect/all_test.go                            |   232 +
 src/reflect/asm_mips64x.s                          |    34 +
 src/reflect/asm_ppc64x.s                           |     9 +-
 src/reflect/deepequal.go                           |    87 +-
 src/reflect/export_test.go                         |     4 +-
 src/reflect/type.go                                |    54 +-
 src/reflect/value.go                               |    49 +-
 src/regexp/all_test.go                             |    63 +-
 src/regexp/example_test.go                         |    22 +
 src/regexp/onepass.go                              |    90 +-
 src/regexp/onepass_test.go                         |    99 +-
 src/regexp/regexp.go                               |    15 +
 src/regexp/syntax/parse.go                         |    24 +-
 src/regexp/syntax/parse_test.go                    |     9 +-
 src/regexp/syntax/regexp.go                        |     4 +-
 src/regexp/syntax/simplify_test.go                 |     4 +-
 src/regexp/testdata/re2-search.txt                 |     5 +
 src/run.bash                                       |     2 +-
 src/run.bat                                        |     2 +-
 src/run.rc                                         |     2 +-
 src/runtime/alg.go                                 |    36 +-
 src/runtime/arch1_386.go                           |    15 -
 src/runtime/arch1_amd64.go                         |    15 -
 src/runtime/arch1_amd64p32.go                      |    15 -
 src/runtime/arch1_arm.go                           |    15 -
 src/runtime/arch1_arm64.go                         |    15 -
 src/runtime/arch1_ppc64.go                         |    15 -
 src/runtime/arch1_ppc64le.go                       |    15 -
 src/runtime/arch_386.go                            |     8 -
 src/runtime/arch_amd64.go                          |     8 -
 src/runtime/arch_amd64p32.go                       |     8 -
 src/runtime/arch_arm.go                            |     8 -
 src/runtime/arch_arm64.go                          |     8 -
 src/runtime/arch_ppc64.go                          |     8 -
 src/runtime/arch_ppc64le.go                        |     8 -
 src/runtime/asm_386.s                              |   510 +-
 src/runtime/asm_amd64.s                            |   923 +-
 src/runtime/asm_amd64p32.s                         |   154 +-
 src/runtime/asm_arm.s                              |    95 +-
 src/runtime/asm_arm64.s                            |    81 +-
 src/runtime/asm_mips64x.s                          |   829 ++
 src/runtime/asm_ppc64x.h                           |    25 +
 src/runtime/asm_ppc64x.s                           |   521 +-
 src/runtime/atomic_386.go                          |    82 -
 src/runtime/atomic_amd64x.go                       |    72 -
 src/runtime/atomic_arm.go                          |   175 -
 src/runtime/atomic_arm64.go                        |    82 -
 src/runtime/atomic_arm64.s                         |   108 -
 src/runtime/atomic_mips64x.s                       |    13 +
 src/runtime/atomic_pointer.go                      |    20 +-
 src/runtime/atomic_ppc64x.go                       |    60 -
 src/runtime/atomic_ppc64x.s                        |    35 +-
 src/runtime/atomic_test.go                         |    66 -
 src/runtime/cgo/asm_ppc64x.s                       |    16 +-
 src/runtime/cgo/gcc_386.S                          |     5 -
 src/runtime/cgo/gcc_android.c                      |     2 +
 src/runtime/cgo/gcc_android_386.c                  |    89 +
 src/runtime/cgo/gcc_android_amd64.c                |    94 +
 src/runtime/cgo/gcc_android_arm.c                  |     2 +
 src/runtime/cgo/gcc_android_arm64.c                |    40 +
 src/runtime/cgo/gcc_arm.S                          |     4 -
 src/runtime/cgo/gcc_arm64.S                        |     4 -
 src/runtime/cgo/gcc_darwin_386.c                   |     2 +
 src/runtime/cgo/gcc_darwin_amd64.c                 |     2 +
 src/runtime/cgo/gcc_darwin_arm.c                   |     2 +
 src/runtime/cgo/gcc_darwin_arm64.c                 |     2 +
 src/runtime/cgo/gcc_dragonfly_amd64.c              |    14 +
 src/runtime/cgo/gcc_fatalf.c                       |     2 +
 src/runtime/cgo/gcc_freebsd_386.c                  |     2 +
 src/runtime/cgo/gcc_freebsd_amd64.c                |     2 +
 src/runtime/cgo/gcc_freebsd_arm.c                  |     2 +
 src/runtime/cgo/gcc_libinit.c                      |     1 +
 src/runtime/cgo/gcc_libinit_linux_ppc64x.c         |     2 +
 src/runtime/cgo/gcc_libinit_openbsd.c              |     2 +
 src/runtime/cgo/gcc_libinit_windows.c              |     2 +
 src/runtime/cgo/gcc_linux_386.c                    |    14 +
 src/runtime/cgo/gcc_linux_amd64.c                  |    46 +-
 src/runtime/cgo/gcc_linux_arm.c                    |     2 +
 src/runtime/cgo/gcc_linux_arm64.c                  |     2 +
 src/runtime/cgo/gcc_linux_ppc64x.c                 |     2 +
 src/runtime/cgo/gcc_mmap.c                         |    23 +
 src/runtime/cgo/gcc_netbsd_386.c                   |    14 +
 src/runtime/cgo/gcc_netbsd_amd64.c                 |    14 +
 src/runtime/cgo/gcc_netbsd_arm.c                   |    14 +
 src/runtime/cgo/gcc_openbsd_386.c                  |     2 +
 src/runtime/cgo/gcc_openbsd_amd64.c                |     2 +
 src/runtime/cgo/gcc_ppc64x.S                       |     7 +-
 src/runtime/cgo/gcc_setenv.c                       |     1 +
 src/runtime/cgo/gcc_signal_darwin_armx.c           |     2 +
 src/runtime/cgo/gcc_signal_darwin_lldb.c           |     2 +
 src/runtime/cgo/gcc_solaris_amd64.c                |     8 +
 src/runtime/cgo/gcc_util.c                         |     2 +
 src/runtime/cgo/gcc_windows_386.c                  |     2 +
 src/runtime/cgo/gcc_windows_amd64.c                |     2 +
 src/runtime/cgo/mmap.go                            |    22 +
 src/runtime/cgo_mmap.go                            |    41 +
 src/runtime/cgo_ppc64x.go                          |    12 +
 src/runtime/cgocall.go                             |   335 +-
 src/runtime/cgocheck.go                            |   240 +
 src/runtime/chan.go                                |   514 +-
 src/runtime/cpuprof.go                             |    13 +-
 src/runtime/cputicks.go                            |     2 +
 src/runtime/crash_cgo_test.go                      |   408 +-
 src/runtime/crash_test.go                          |   445 +-
 src/runtime/crash_unix_test.go                     |    43 +
 src/runtime/debug.go                               |    11 +-
 src/runtime/debug/garbage.go                       |    11 +
 src/runtime/debug/garbage_test.go                  |     5 +-
 src/runtime/debug/heapdump_test.go                 |     3 +-
 src/runtime/debug/stack.go                         |    86 +-
 src/runtime/debug/stack_test.go                    |    41 +-
 src/runtime/debug/stubs.go                         |     8 +-
 src/runtime/debug/stubs.s                          |    30 -
 src/runtime/defs_darwin.go                         |     2 +-
 src/runtime/defs_darwin_386.go                     |     6 +
 src/runtime/defs_darwin_amd64.go                   |     6 +
 src/runtime/defs_darwin_arm.go                     |     6 +
 src/runtime/defs_darwin_arm64.go                   |     6 +
 src/runtime/defs_linux_386.go                      |     9 +
 src/runtime/defs_linux_amd64.go                    |     9 +
 src/runtime/defs_linux_arm64.go                    |     9 +
 src/runtime/defs_linux_mips64x.go                  |   183 +
 src/runtime/duff_amd64.s                           |  1244 +--
 src/runtime/duff_mips64x.s                         |   268 +
 src/runtime/duff_ppc64x.s                          |     2 +-
 src/runtime/env_plan9.go                           |     4 +-
 src/runtime/env_posix.go                           |     3 +-
 src/runtime/error.go                               |     4 +-
 src/runtime/export_linux_test.go                   |     1 +
 src/runtime/export_mmap_test.go                    |    15 +
 src/runtime/export_test.go                         |    32 +-
 src/runtime/export_windows_test.go                 |     8 +
 src/runtime/extern.go                              |    55 +-
 src/runtime/fastlog2.go                            |    33 +
 src/runtime/fastlog2_test.go                       |    34 +
 src/runtime/fastlog2table.go                       |    43 +
 src/runtime/funcdata.h                             |    11 -
 src/runtime/futex_test.go                          |    25 +-
 src/runtime/gc_test.go                             |    85 +-
 src/runtime/gcinfo_test.go                         |     2 +-
 src/runtime/gengoos.go                             |    84 -
 src/runtime/hash32.go                              |     6 +-
 src/runtime/hash64.go                              |     8 +-
 src/runtime/hash_test.go                           |    99 +-
 src/runtime/hashmap.go                             |   158 +-
 src/runtime/hashmap_fast.go                        |    92 +-
 src/runtime/heapdump.go                            |    43 +-
 src/runtime/iface.go                               |   215 +-
 src/runtime/internal/atomic/asm.s                  |     8 +
 src/runtime/internal/atomic/asm_386.s              |   166 +
 src/runtime/internal/atomic/asm_amd64.s            |   150 +
 src/runtime/internal/atomic/asm_amd64p32.s         |   150 +
 src/runtime/internal/atomic/asm_arm.s              |    71 +
 src/runtime/internal/atomic/asm_arm64.s            |    58 +
 src/runtime/internal/atomic/asm_mips64x.s          |   231 +
 src/runtime/internal/atomic/asm_ppc64x.s           |   225 +
 src/runtime/internal/atomic/atomic_386.go          |    76 +
 src/runtime/internal/atomic/atomic_amd64x.go       |    65 +
 src/runtime/internal/atomic/atomic_arm.go          |   183 +
 src/runtime/internal/atomic/atomic_arm64.go        |    80 +
 src/runtime/internal/atomic/atomic_arm64.s         |   113 +
 src/runtime/internal/atomic/atomic_mips64x.go      |    56 +
 src/runtime/internal/atomic/atomic_mips64x.s       |    36 +
 src/runtime/internal/atomic/atomic_ppc64x.go       |    56 +
 src/runtime/internal/atomic/atomic_ppc64x.s        |    40 +
 src/runtime/internal/atomic/atomic_test.go         |    67 +
 src/runtime/internal/atomic/stubs.go               |    33 +
 src/runtime/internal/atomic/sys_darwin_arm.s       |    11 +
 src/runtime/internal/atomic/sys_freebsd_arm.s      |    19 +
 src/runtime/internal/atomic/sys_linux_arm.s        |    42 +
 src/runtime/internal/atomic/sys_nacl_arm.s         |    16 +
 src/runtime/internal/atomic/sys_netbsd_arm.s       |    21 +
 src/runtime/internal/atomic/sys_openbsd_arm.s      |    11 +
 src/runtime/internal/sys/arch_386.go               |    18 +
 src/runtime/internal/sys/arch_amd64.go             |    18 +
 src/runtime/internal/sys/arch_amd64p32.go          |    18 +
 src/runtime/internal/sys/arch_arm.go               |    18 +
 src/runtime/internal/sys/arch_arm64.go             |    18 +
 src/runtime/internal/sys/arch_mips64.go            |    18 +
 src/runtime/internal/sys/arch_mips64le.go          |    18 +
 src/runtime/internal/sys/arch_ppc64.go             |    18 +
 src/runtime/internal/sys/arch_ppc64le.go           |    18 +
 src/runtime/internal/sys/gengoos.go                |    84 +
 src/runtime/internal/sys/stubs.go                  |    11 +
 src/runtime/internal/sys/sys.go                    |    15 +
 src/runtime/internal/sys/zgoarch_386.go            |    26 +
 src/runtime/internal/sys/zgoarch_amd64.go          |    26 +
 src/runtime/internal/sys/zgoarch_amd64p32.go       |    26 +
 src/runtime/internal/sys/zgoarch_arm.go            |    26 +
 src/runtime/internal/sys/zgoarch_arm64.go          |    26 +
 src/runtime/internal/sys/zgoarch_mips64.go         |    26 +
 src/runtime/internal/sys/zgoarch_mips64le.go       |    26 +
 src/runtime/internal/sys/zgoarch_ppc64.go          |    26 +
 src/runtime/internal/sys/zgoarch_ppc64le.go        |    26 +
 src/runtime/internal/sys/zgoos_android.go          |    17 +
 src/runtime/internal/sys/zgoos_darwin.go           |    17 +
 src/runtime/internal/sys/zgoos_dragonfly.go        |    17 +
 src/runtime/internal/sys/zgoos_freebsd.go          |    17 +
 src/runtime/internal/sys/zgoos_linux.go            |    19 +
 src/runtime/internal/sys/zgoos_nacl.go             |    17 +
 src/runtime/internal/sys/zgoos_netbsd.go           |    17 +
 src/runtime/internal/sys/zgoos_openbsd.go          |    17 +
 src/runtime/internal/sys/zgoos_plan9.go            |    17 +
 src/runtime/internal/sys/zgoos_solaris.go          |    17 +
 src/runtime/internal/sys/zgoos_windows.go          |    17 +
 src/runtime/lfstack.go                             |    17 +-
 src/runtime/lfstack_linux_mips64x.go               |    32 +
 src/runtime/lock_futex.go                          |    27 +-
 src/runtime/lock_sema.go                           |    67 +-
 src/runtime/malloc.go                              |   222 +-
 src/runtime/malloc_test.go                         |    30 +-
 src/runtime/mbarrier.go                            |    51 +-
 src/runtime/mbitmap.go                             |   216 +-
 src/runtime/mcache.go                              |    46 +-
 src/runtime/mcentral.go                            |    87 +-
 src/runtime/mem_bsd.go                             |    11 +-
 src/runtime/mem_darwin.go                          |     6 +-
 src/runtime/mem_linux.go                           |    25 +-
 src/runtime/mem_plan9.go                           |    33 +-
 src/runtime/mem_windows.go                         |    10 +-
 src/runtime/memclr_amd64.s                         |    55 +-
 src/runtime/memclr_mips64x.s                       |    42 +
 src/runtime/memclr_ppc64x.s                        |     2 +-
 src/runtime/memmove_mips64x.s                      |   105 +
 src/runtime/memmove_ppc64x.s                       |     2 +-
 src/runtime/memmove_test.go                        |     5 +
 src/runtime/mfinal.go                              |    49 +-
 src/runtime/mfixalloc.go                           |    21 +-
 src/runtime/mgc.go                                 |  1120 +-
 src/runtime/mgcmark.go                             |  1006 +-
 src/runtime/mgcsweep.go                            |   146 +-
 src/runtime/mgcwork.go                             |   239 +-
 src/runtime/mheap.go                               |   399 +-
 src/runtime/mkduff.go                              |    54 +-
 src/runtime/mkfastlog2table.go                     |    52 +
 src/runtime/mmap.go                                |    16 +
 src/runtime/mprof.go                               |    87 +-
 src/runtime/msan.go                                |    55 +
 src/runtime/msan/msan.go                           |    32 +
 src/runtime/msan0.go                               |    22 +
 src/runtime/msan_amd64.s                           |    76 +
 src/runtime/mstats.go                              |    51 +-
 src/runtime/mstkbar.go                             |   365 +
 src/runtime/netpoll.go                             |    17 +-
 src/runtime/netpoll_epoll.go                       |     7 +-
 src/runtime/netpoll_kqueue.go                      |     7 +-
 src/runtime/netpoll_solaris.go                     |     7 +-
 src/runtime/noasm.go                               |     8 +-
 src/runtime/os1_darwin.go                          |   104 +-
 src/runtime/os1_dragonfly.go                       |    41 +-
 src/runtime/os1_freebsd.go                         |    51 +-
 src/runtime/os1_linux.go                           |    84 +-
 src/runtime/os1_linux_generic.go                   |    27 +
 src/runtime/os1_linux_mips64x.go                   |    26 +
 src/runtime/os1_nacl.go                            |    36 +-
 src/runtime/os1_netbsd.go                          |    69 +-
 src/runtime/os1_openbsd.go                         |    71 +-
 src/runtime/os1_plan9.go                           |    18 +-
 src/runtime/os1_windows.go                         |   131 +-
 src/runtime/os2_dragonfly.go                       |     2 +-
 src/runtime/os2_linux.go                           |    25 -
 src/runtime/os2_linux_generic.go                   |    29 +
 src/runtime/os2_linux_mips64x.go                   |    25 +
 src/runtime/os2_nacl.go                            |    25 +-
 src/runtime/os3_plan9.go                           |    18 +-
 src/runtime/os3_solaris.go                         |    81 +-
 src/runtime/{os_android_arm.go => os_android.go}   |     0
 src/runtime/os_darwin.go                           |     8 +-
 src/runtime/os_dragonfly.go                        |     5 +-
 src/runtime/os_freebsd.go                          |     5 +-
 src/runtime/os_linux.go                            |     5 +-
 src/runtime/os_linux_386.go                        |     7 +-
 src/runtime/os_linux_arm.go                        |     7 +-
 src/runtime/os_linux_mips64x.go                    |    18 +
 src/runtime/os_nacl.go                             |    14 +-
 src/runtime/os_netbsd.go                           |     8 +-
 src/runtime/os_openbsd.go                          |     9 +-
 src/runtime/os_plan9.go                            |     6 +
 src/runtime/os_solaris.go                          |    22 +-
 src/runtime/os_windows.go                          |     4 +
 src/runtime/panic.go                               |   148 +-
 src/runtime/panic1.go                              |   150 -
 src/runtime/parfor.go                              |    35 +-
 src/runtime/pprof/mprof_test.go                    |    15 +-
 src/runtime/pprof/pprof.go                         |    14 +-
 src/runtime/pprof/pprof_test.go                    |   186 +-
 src/runtime/print.go                               |   221 +
 src/runtime/print1.go                              |   231 -
 src/runtime/print1_write_android.go                |   160 -
 src/runtime/proc.go                                |  3890 ++++++-
 src/runtime/proc1.go                               |  3747 -------
 src/runtime/proc_test.go                           |   134 +-
 src/runtime/race.go                                |   305 +
 src/runtime/race/README                            |    11 +-
 src/runtime/race/output_test.go                    |     5 +-
 src/runtime/race/race.go                           |     2 +-
 src/runtime/race/race_darwin_amd64.syso            |   Bin 314000 -> 300192 bytes
 src/runtime/race/race_freebsd_amd64.syso           |   Bin 316816 -> 368688 bytes
 src/runtime/race/race_linux_amd64.syso             |   Bin 330232 -> 352664 bytes
 src/runtime/race/race_test.go                      |    15 +-
 src/runtime/race/race_windows_amd64.syso           |   Bin 331489 -> 349411 bytes
 src/runtime/race/testdata/chan_test.go             |    39 +
 src/runtime/race/testdata/issue12225_test.go       |     7 +
 src/runtime/race/testdata/issue12664_test.go       |    76 +
 src/runtime/race/testdata/issue13264_test.go       |    13 +
 src/runtime/race/testdata/mop_test.go              |     8 +-
 src/runtime/race/testdata/regression_test.go       |     9 +-
 src/runtime/race/testdata/select_test.go           |     2 +-
 src/runtime/race1.go                               |   315 -
 src/runtime/rdebug.go                              |     4 +
 src/runtime/rt0_android_386.s                      |    32 +
 src/runtime/rt0_android_amd64.s                    |    33 +
 src/runtime/rt0_android_arm64.s                    |    25 +
 src/runtime/rt0_darwin_386.s                       |    59 +
 src/runtime/rt0_darwin_amd64.s                     |    24 +-
 src/runtime/rt0_darwin_arm.s                       |     4 +
 src/runtime/rt0_darwin_arm64.s                     |     5 +
 src/runtime/rt0_linux_386.s                        |     4 +
 src/runtime/rt0_linux_amd64.s                      |     4 +
 src/runtime/rt0_linux_arm.s                        |     4 +
 src/runtime/rt0_linux_arm64.s                      |    48 +
 src/runtime/rt0_linux_mips64x.s                    |    31 +
 src/runtime/rt0_linux_ppc64.s                      |     4 +-
 src/runtime/rt0_linux_ppc64le.s                    |     7 +-
 src/runtime/rt0_plan9_386.s                        |     2 -
 src/runtime/rt0_plan9_amd64.s                      |     2 -
 src/runtime/rt0_solaris_amd64.s                    |     3 -
 src/runtime/rt0_windows_386.s                      |     4 -
 src/runtime/rt0_windows_amd64.s                    |     3 -
 src/runtime/runtime-gdb_test.go                    |    11 +-
 src/runtime/runtime-lldb_test.go                   |   262 +
 src/runtime/runtime.go                             |    12 +-
 src/runtime/runtime1.go                            |   146 +-
 src/runtime/runtime2.go                            |   119 +-
 src/runtime/runtime_linux_test.go                  |    13 +
 src/runtime/runtime_mmap_test.go                   |    30 +
 src/runtime/runtime_test.go                        |    28 +
 src/runtime/select.go                              |   138 +-
 src/runtime/sema.go                                |    24 +-
 src/runtime/signal1_unix.go                        |   136 +-
 src/runtime/signal2_unix.go                        |    69 +
 src/runtime/signal_386.go                          |    24 +-
 src/runtime/signal_amd64x.go                       |    20 +-
 src/runtime/signal_arm.go                          |    13 +-
 src/runtime/signal_arm64.go                        |    20 +-
 src/runtime/signal_darwin.go                       |    31 +-
 src/runtime/signal_darwin_386.go                   |    22 +
 src/runtime/signal_darwin_amd64.go                 |    22 +
 src/runtime/signal_darwin_arm.go                   |    21 +
 src/runtime/signal_darwin_arm64.go                 |    22 +
 src/runtime/signal_dragonfly.go                    |     2 +-
 src/runtime/signal_freebsd.go                      |    43 +-
 src/runtime/signal_linux.go                        |    96 -
 src/runtime/signal_linux_386.go                    |     7 +-
 src/runtime/signal_linux_amd64.go                  |     7 +-
 src/runtime/signal_linux_arm.go                    |     7 +-
 src/runtime/signal_linux_arm64.go                  |     7 +-
 src/runtime/signal_linux_mips64x.go                |    70 +
 src/runtime/signal_linux_ppc64x.go                 |     8 +-
 src/runtime/signal_mips64x.go                      |   188 +
 src/runtime/signal_nacl.go                         |     2 +-
 src/runtime/signal_netbsd.go                       |     2 +-
 src/runtime/signal_openbsd.go                      |    43 +-
 src/runtime/signal_plan9.go                        |     3 +
 src/runtime/signal_ppc64x.go                       |    21 +-
 src/runtime/signal_sigtramp.go                     |    50 +
 src/runtime/signal_solaris.go                      |     6 +-
 src/runtime/signal_unix.go                         |    36 +-
 src/runtime/signal_windows.go                      |     6 +-
 src/runtime/sigqueue.go                            |    54 +-
 src/runtime/sigqueue_plan9.go                      |     6 +
 src/runtime/sigtab_linux_generic.go                |    82 +
 src/runtime/sigtab_linux_mips64x.go                |    81 +
 src/runtime/slice.go                               |    14 +-
 src/runtime/softfloat_arm.go                       |    11 +
 src/runtime/sqrt.go                                |     2 +-
 src/runtime/sqrt_test.go                           |     2 +
 src/runtime/stack.go                               |  1068 ++
 src/runtime/stack1.go                              |   923 --
 src/runtime/stack2.go                              |   106 -
 src/runtime/stack_test.go                          |     4 +-
 src/runtime/string.go                              |    94 +-
 src/runtime/string1.go                             |    67 -
 src/runtime/string_test.go                         |    30 +-
 src/runtime/stubs.go                               |    45 +-
 src/runtime/stubs2.go                              |     1 -
 src/runtime/stubs_android.go                       |     8 +-
 src/runtime/symtab.go                              |    84 +-
 src/runtime/sys_darwin_386.s                       |    84 +-
 src/runtime/sys_darwin_amd64.s                     |     6 +-
 src/runtime/sys_darwin_arm.s                       |    22 +-
 src/runtime/sys_darwin_arm64.s                     |    12 +-
 src/runtime/sys_dragonfly_amd64.s                  |    44 +-
 src/runtime/sys_freebsd_386.s                      |    42 +-
 src/runtime/sys_freebsd_amd64.s                    |    32 +-
 src/runtime/sys_freebsd_arm.s                      |    55 +-
 src/runtime/sys_linux_386.s                        |   151 +-
 src/runtime/sys_linux_amd64.s                      |    54 +-
 src/runtime/sys_linux_arm.s                        |    33 +-
 src/runtime/sys_linux_arm64.s                      |    36 +
 src/runtime/sys_linux_mips64x.s                    |   428 +
 src/runtime/sys_linux_ppc64x.s                     |    72 +-
 src/runtime/sys_mips64x.go                         |    43 +
 src/runtime/sys_nacl_386.s                         |     3 +
 src/runtime/sys_nacl_arm.s                         |    15 -
 src/runtime/sys_netbsd_386.s                       |    37 +-
 src/runtime/sys_netbsd_amd64.s                     |    40 +-
 src/runtime/sys_netbsd_arm.s                       |    55 +-
 src/runtime/sys_nonppc64x.go                       |    10 +
 src/runtime/sys_openbsd_386.s                      |    40 +-
 src/runtime/sys_openbsd_amd64.s                    |    34 +-
 src/runtime/sys_openbsd_arm.s                      |    48 +-
 src/runtime/sys_plan9_386.s                        |     2 +-
 src/runtime/sys_plan9_amd64.s                      |     2 +-
 src/runtime/sys_ppc64x.go                          |     2 +
 src/runtime/sys_solaris_amd64.s                    |    16 +-
 src/runtime/sys_windows_386.s                      |     3 +-
 src/runtime/sys_windows_amd64.s                    |    12 +-
 src/runtime/sys_x86.go                             |    11 +-
 src/runtime/syscall2_solaris.go                    |     6 -
 src/runtime/syscall_windows.go                     |     8 +-
 src/runtime/syscall_windows_test.go                |   179 +-
 src/runtime/testdata/testprog/crash.go             |    45 +
 src/runtime/testdata/testprog/deadlock.go          |   191 +
 src/runtime/testdata/testprog/gc.go                |    74 +
 src/runtime/testdata/testprog/main.go              |    35 +
 src/runtime/testdata/testprog/misc.go              |    15 +
 src/runtime/testdata/testprog/signal.go            |    17 +
 src/runtime/testdata/testprog/stringconcat.go      |    20 +
 src/runtime/testdata/testprog/syscall_windows.go   |    27 +
 src/runtime/testdata/testprogcgo/callback.go       |    89 +
 src/runtime/testdata/testprogcgo/cgo.go            |    80 +
 src/runtime/testdata/testprogcgo/crash.go          |    45 +
 src/runtime/testdata/testprogcgo/dll_windows.go    |    25 +
 src/runtime/testdata/testprogcgo/dropm.go          |    59 +
 src/runtime/testdata/testprogcgo/dropm_stub.go     |    11 +
 src/runtime/testdata/testprogcgo/exec.go           |    89 +
 src/runtime/testdata/testprogcgo/main.go           |    35 +
 src/runtime/testdata/testprogcgo/threadpanic.go    |    24 +
 .../testdata/testprogcgo/threadpanic_unix.c        |    26 +
 .../testdata/testprogcgo/threadpanic_windows.c     |    22 +
 src/runtime/testdata/testprogcgo/threadprof.go     |    93 +
 src/runtime/testdata/testprogcgo/windows/win.go    |    16 +
 src/runtime/testdata/testprognet/main.go           |    35 +
 src/runtime/testdata/testprognet/net.go            |    29 +
 src/runtime/testdata/testprognet/signal.go         |    26 +
 src/runtime/textflag.h                             |     7 +
 src/runtime/time.go                                |     2 +-
 src/runtime/tls_arm.s                              |    30 +-
 src/runtime/tls_arm64.h                            |     7 +
 src/runtime/tls_arm64.s                            |    15 +-
 src/runtime/tls_mips64x.s                          |    23 +
 src/runtime/tls_ppc64x.s                           |    27 +-
 src/runtime/trace.go                               |   293 +-
 src/runtime/trace/trace_stack_test.go              |   154 +-
 src/runtime/trace/trace_test.go                    |    16 +-
 src/runtime/traceback.go                           |   111 +-
 src/runtime/type.go                                |    30 +-
 src/runtime/typekind.go                            |    60 +-
 src/runtime/typekind1.go                           |    39 -
 src/runtime/unaligned2.go                          |     2 +-
 src/runtime/vdso_linux_amd64.go                    |     7 +-
 src/runtime/{print1_write.go => write_err.go}      |     0
 src/runtime/write_err_android.go                   |   160 +
 src/runtime/zgoarch_386.go                         |    13 -
 src/runtime/zgoarch_amd64.go                       |    13 -
 src/runtime/zgoarch_amd64p32.go                    |    13 -
 src/runtime/zgoarch_arm.go                         |    13 -
 src/runtime/zgoarch_arm64.go                       |    13 -
 src/runtime/zgoarch_ppc64.go                       |    13 -
 src/runtime/zgoarch_ppc64le.go                     |    13 -
 src/runtime/zgoos_android.go                       |    17 -
 src/runtime/zgoos_darwin.go                        |    17 -
 src/runtime/zgoos_dragonfly.go                     |    17 -
 src/runtime/zgoos_freebsd.go                       |    17 -
 src/runtime/zgoos_linux.go                         |    19 -
 src/runtime/zgoos_nacl.go                          |    17 -
 src/runtime/zgoos_netbsd.go                        |    17 -
 src/runtime/zgoos_openbsd.go                       |    17 -
 src/runtime/zgoos_plan9.go                         |    17 -
 src/runtime/zgoos_solaris.go                       |    17 -
 src/runtime/zgoos_windows.go                       |    17 -
 src/sort/example_multi_test.go                     |     4 +-
 src/sort/search.go                                 |     2 +-
 src/sort/sort.go                                   |   112 +-
 src/strconv/ftoa.go                                |    18 +-
 src/strconv/ftoa_test.go                           |     6 +-
 src/strconv/isprint.go                             |    20 +
 src/strconv/itoa.go                                |     2 +-
 src/strconv/makeisprint.go                         |    17 +
 src/strconv/quote.go                               |    67 +-
 src/strconv/quote_test.go                          |    88 +-
 src/strings/example_test.go                        |    22 +
 src/strings/strings.go                             |    37 -
 src/strings/strings_amd64.go                       |    49 +
 src/strings/strings_generic.go                     |    47 +
 src/strings/strings_test.go                        |    53 +
 src/sync/atomic/asm_linux_arm.s                    |     2 +-
 src/sync/atomic/asm_mips64x.s                      |   181 +
 src/sync/cond.go                                   |    21 +-
 src/sync/export_test.go                            |     2 -
 src/sync/mutex.go                                  |    13 +-
 src/sync/pool.go                                   |     5 +-
 src/sync/race.go                                   |    42 -
 src/sync/race0.go                                  |    34 -
 src/sync/rwmutex.go                                |    49 +-
 src/sync/waitgroup.go                              |    33 +-
 src/sync/waitgroup_test.go                         |    14 +-
 src/syscall/asm_linux_386.s                        |    27 +-
 src/syscall/asm_linux_mips64x.s                    |   104 +
 src/syscall/asm_solaris_amd64.s                    |     9 -
 src/syscall/dll_windows.go                         |     4 +-
 src/syscall/errors_plan9.go                        |    10 +
 src/syscall/exec_bsd.go                            |     1 +
 src/syscall/exec_linux.go                          |    12 +-
 src/syscall/exec_linux_test.go                     |    65 +-
 src/syscall/exec_plan9.go                          |     6 +-
 src/syscall/exec_solaris.go                        |     1 +
 src/syscall/mkerrors.sh                            |     6 +
 src/syscall/mksyscall_solaris.pl                   |    35 +-
 src/syscall/mksysnum_plan9.sh                      |     2 -
 src/syscall/msan.go                                |    22 +
 src/syscall/msan0.go                               |    19 +
 src/syscall/net_nacl.go                            |    12 +-
 src/syscall/race.go                                |    30 -
 src/syscall/race0.go                               |    25 -
 src/syscall/route_bsd.go                           |    11 +-
 src/syscall/route_bsd_test.go                      |    35 +
 src/syscall/sockcmsg_unix.go                       |     6 +-
 src/syscall/srpc_nacl.go                           |   822 --
 src/syscall/syscall.go                             |     3 +
 src/syscall/syscall_linux.go                       |     4 +-
 src/syscall/syscall_linux_386.go                   |     5 +-
 src/syscall/syscall_linux_amd64.go                 |     5 +-
 src/syscall/syscall_linux_arm.go                   |     5 +-
 src/syscall/syscall_linux_arm64.go                 |     5 +-
 src/syscall/syscall_linux_mips64x.go               |   210 +
 src/syscall/syscall_linux_ppc64x.go                |     5 +-
 src/syscall/syscall_linux_test.go                  |     6 +-
 src/syscall/syscall_solaris.go                     |    21 +-
 src/syscall/syscall_unix.go                        |    25 +-
 src/syscall/syscall_windows.go                     |    21 +-
 src/syscall/types_linux.go                         |     2 +
 src/syscall/types_solaris.go                       |     7 +
 src/syscall/zerrors_linux_mips64.go                |  1817 ++++
 src/syscall/zerrors_linux_mips64le.go              |  1817 ++++
 src/syscall/zsyscall_linux_386.go                  |     2 +-
 src/syscall/zsyscall_linux_amd64.go                |     2 +-
 src/syscall/zsyscall_linux_arm.go                  |     2 +-
 src/syscall/zsyscall_linux_arm64.go                |     2 +-
 src/syscall/zsyscall_linux_mips64.go               |  1765 +++
 src/syscall/zsyscall_linux_mips64le.go             |  1765 +++
 src/syscall/zsyscall_linux_ppc64.go                |     2 +-
 src/syscall/zsyscall_linux_ppc64le.go              |     2 +-
 src/syscall/zsyscall_solaris_amd64.go              |    16 +
 src/syscall/zsysnum_linux_mips64.go                |   323 +
 src/syscall/zsysnum_linux_mips64le.go              |   323 +
 src/syscall/ztypes_linux_mips64.go                 |   602 ++
 src/syscall/ztypes_linux_mips64le.go               |   602 ++
 src/syscall/ztypes_solaris_amd64.go                |     1 +
 src/testing/benchmark.go                           |    11 +
 src/testing/quick/quick.go                         |    38 +-
 src/testing/quick/quick_test.go                    |    53 +-
 src/testing/testing.go                             |    32 +-
 src/text/scanner/scanner.go                        |     2 +-
 src/text/template/doc.go                           |    39 +-
 src/text/template/example_test.go                  |    45 +-
 src/text/template/exec.go                          |    69 +-
 src/text/template/exec_test.go                     |   211 +-
 src/text/template/funcs.go                         |    79 +-
 src/text/template/multi_test.go                    |    22 +-
 src/text/template/parse/lex.go                     |    98 +-
 src/text/template/parse/lex_test.go                |    31 +-
 src/text/template/parse/parse.go                   |    83 +-
 src/text/template/parse/parse_test.go              |    34 +
 src/text/template/template.go                      |    37 +-
 src/time/format.go                                 |    48 +-
 src/time/format_test.go                            |    83 +
 src/time/time.go                                   |    13 +-
 src/time/time_test.go                              |    14 +
 src/time/zoneinfo.go                               |     2 +-
 src/time/zoneinfo_windows.go                       |    32 +-
 src/time/zoneinfo_windows_test.go                  |    22 +-
 src/unicode/example_test.go                        |   196 +
 src/unicode/maketables.go                          |     3 -
 src/unicode/tables.go                              |     4 +-
 src/unicode/utf8/utf8.go                           |   473 +-
 src/unicode/utf8/utf8_test.go                      |    68 +-
 src/unsafe/unsafe.go                               |   166 +-
 src/vendor/README                                  |     8 +
 test/bench/go1/jsondata_test.go                    |     2 +-
 test/bench/shootout/binary-tree-freelist.go        |   129 -
 test/bench/shootout/binary-tree-freelist.txt       |     8 -
 test/bench/shootout/binary-tree.c                  |   164 -
 test/bench/shootout/binary-tree.go                 |    92 -
 test/bench/shootout/binary-tree.txt                |     8 -
 test/bench/shootout/chameneosredux.c               |   330 -
 test/bench/shootout/chameneosredux.go              |   180 -
 test/bench/shootout/chameneosredux.txt             |    29 -
 test/bench/shootout/fannkuch-parallel.go           |   224 -
 test/bench/shootout/fannkuch-parallel.txt          |    31 -
 test/bench/shootout/fannkuch.c                     |   134 -
 test/bench/shootout/fannkuch.go                    |   122 -
 test/bench/shootout/fannkuch.txt                   |    31 -
 test/bench/shootout/fasta-1000.txt                 |   171 -
 test/bench/shootout/fasta.c                        |   219 -
 test/bench/shootout/fasta.go                       |   205 -
 test/bench/shootout/fasta.txt                      |   171 -
 test/bench/shootout/k-nucleotide-parallel.go       |   157 -
 test/bench/shootout/k-nucleotide-parallel.txt      |    27 -
 test/bench/shootout/k-nucleotide.c                 |   228 -
 test/bench/shootout/k-nucleotide.go                |   140 -
 test/bench/shootout/k-nucleotide.txt               |    27 -
 test/bench/shootout/mandelbrot.c                   |    91 -
 test/bench/shootout/mandelbrot.go                  |    95 -
 test/bench/shootout/mandelbrot.txt                 |   Bin 5011 -> 0 bytes
 test/bench/shootout/meteor-contest.c               |   626 --
 test/bench/shootout/meteor-contest.go              |   656 --
 test/bench/shootout/meteor-contest.txt             |    24 -
 test/bench/shootout/nbody.c                        |   170 -
 test/bench/shootout/nbody.go                       |   177 -
 test/bench/shootout/nbody.txt                      |     2 -
 test/bench/shootout/pidigits.c                     |   123 -
 test/bench/shootout/pidigits.go                    |   135 -
 test/bench/shootout/pidigits.txt                   |     3 -
 test/bench/shootout/regex-dna-parallel.go          |   124 -
 test/bench/shootout/regex-dna-parallel.txt         |    13 -
 test/bench/shootout/regex-dna.c                    |   154 -
 test/bench/shootout/regex-dna.go                   |   106 -
 test/bench/shootout/regex-dna.txt                  |    13 -
 test/bench/shootout/reverse-complement.c           |   100 -
 test/bench/shootout/reverse-complement.go          |   105 -
 test/bench/shootout/reverse-complement.txt         |   171 -
 test/bench/shootout/spectral-norm-parallel.go      |   111 -
 test/bench/shootout/spectral-norm.c                |    82 -
 test/bench/shootout/spectral-norm.go               |    93 -
 test/bench/shootout/spectral-norm.txt              |     1 -
 test/bench/shootout/threadring.c                   |   113 -
 test/bench/shootout/threadring.go                  |    71 -
 test/bench/shootout/threadring.txt                 |     1 -
 test/bench/shootout/timing.log                     |  1254 ---
 test/bench/shootout/timing.sh                      |   252 -
 test/blank1.go                                     |     4 +
 test/const.go                                      |     5 +
 test/escape2.go                                    |    36 +-
 test/escape2n.go                                   |    36 +-
 test/finprofiled.go                                |    74 +
 test/fixedbugs/bug13343.go                         |    18 +
 test/fixedbugs/bug358.go                           |     7 +-
 test/fixedbugs/bug401.go                           |     3 +-
 test/fixedbugs/bug484.go                           |    26 +-
 test/fixedbugs/bug496.go                           |    29 +
 test/fixedbugs/bug497.go                           |    28 +
 test/fixedbugs/gcc67968.dir/a.go                   |    12 +
 test/fixedbugs/gcc67968.dir/b.go                   |    12 +
 test/fixedbugs/gcc67968.go                         |    14 +
 test/fixedbugs/issue10441.go                       |     2 +-
 test/fixedbugs/issue10607.go                       |     2 +-
 test/fixedbugs/issue10975.go                       |    18 +
 test/fixedbugs/issue11326.go                       |    39 +-
 test/fixedbugs/issue11326b.go                      |    20 +-
 test/fixedbugs/issue11359.go                       |    11 +
 test/fixedbugs/issue11362.go                       |    15 +
 test/fixedbugs/issue11590.go                       |    11 +
 test/fixedbugs/issue11610.go                       |    17 +
 test/fixedbugs/issue11614.go                       |    26 +
 test/fixedbugs/issue11656.go                       |    39 +-
 test/fixedbugs/issue11699.go                       |    12 +
 test/fixedbugs/issue11737.go                       |    17 +
 test/fixedbugs/issue12006.go                       |   174 +
 test/fixedbugs/issue12108.go                       |    37 +
 test/fixedbugs/issue12133.go                       |     4 +-
 test/fixedbugs/issue12411.go                       |    24 +
 test/fixedbugs/issue12413.go                       |    19 +
 test/fixedbugs/issue12577.go                       |    66 +
 test/fixedbugs/issue12588.go                       |    88 +
 test/fixedbugs/issue12677.dir/p.go                 |     8 +
 test/fixedbugs/issue12677.dir/q.go                 |     7 +
 test/fixedbugs/issue12677.go                       |     9 +
 test/fixedbugs/issue12944.go                       |    13 +
 test/fixedbugs/issue13169.go                       |    49 +
 test/fixedbugs/issue13171.go                       |    34 +
 test/fixedbugs/issue13248.go                       |    13 +
 test/fixedbugs/issue13261.go                       |    29 +
 test/fixedbugs/issue13266.go                       |    10 +
 test/fixedbugs/issue13268.go                       |    48 +
 test/fixedbugs/issue13273.go                       |    55 +
 test/fixedbugs/issue13274.go                       |    11 +
 test/fixedbugs/issue13319.go                       |    18 +
 test/fixedbugs/issue13365.go                       |    25 +
 test/fixedbugs/issue13415.go                       |    19 +
 test/fixedbugs/issue13471.go                       |    25 +
 test/fixedbugs/issue13480.go                       |    38 +
 test/fixedbugs/issue13539.go                       |    20 +
 test/fixedbugs/issue13559.go                       |    89 +
 test/fixedbugs/issue13587.go                       |    19 +
 test/fixedbugs/issue13684.go                       |    17 +
 test/fixedbugs/issue13777.dir/burnin.go            |    19 +
 test/fixedbugs/issue13777.dir/main.go              |    11 +
 test/fixedbugs/issue13777.go                       |     7 +
 test/fixedbugs/issue13799.go                       |   190 +
 test/fixedbugs/issue13821.go                       |    15 +
 test/fixedbugs/issue13821b.go                      |    24 +
 test/fixedbugs/issue14006.go                       |    64 +
 test/fixedbugs/issue14010.go                       |    15 +
 test/fixedbugs/issue14164.dir/a.go                 |    47 +
 test/fixedbugs/issue14164.dir/main.go              |    12 +
 test/fixedbugs/issue14164.go                       |     7 +
 test/fixedbugs/issue14331.dir/a.go                 |    14 +
 test/fixedbugs/issue14331.dir/b.go                 |    11 +
 test/fixedbugs/issue14331.go                       |     9 +
 test/fixedbugs/issue4468.go                        |     8 +-
 test/fixedbugs/issue4518.go                        |     6 +-
 test/fixedbugs/issue4964.dir/a.go                  |     6 +-
 test/fixedbugs/issue5957.dir/c.go                  |     2 +-
 test/fixedbugs/issue7150.go                        |    10 +-
 test/fixedbugs/issue7153.go                        |     2 +-
 test/fixedbugs/issue7995b.dir/x1.go                |     6 +-
 test/fixedbugs/issue8036.go                        |     4 +-
 test/func8.go                                      |     6 +-
 test/heapsampling.go                               |   172 +
 test/import4.dir/import4.go                        |     4 +-
 test/initloop.go                                   |    17 +
 test/inline.go                                     |     9 +
 test/linkmain.go                                   |    12 +
 test/linkmain_run.go                               |    66 +
 test/live_syscall.go                               |    28 +
 test/nilptr3.go                                    |     3 +-
 test/nosplit.go                                    |    67 +-
 test/recover4.go                                   |     4 +-
 test/reorder2.go                                   |    24 +-
 test/run.go                                        |    54 +-
 test/switch2.go                                    |    39 +
 test/syntax/chan.go                                |     6 +-
 test/syntax/composite.go                           |     2 +-
 test/syntax/forvar.go                              |     1 +
 test/syntax/semi4.go                               |     2 +-
 test/syntax/semi6.go                               |     6 +-
 test/syntax/semi7.go                               |     2 +-
 test/syntax/vareq1.go                              |     2 +-
 test/tinyfin.go                                    |    66 +-
 test/typecheckloop.go                              |    14 +
 test/writebarrier.go                               |    14 +
 1769 files changed, 131374 insertions(+), 57839 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index 54a10ad..34a78e5 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -2,24 +2,29 @@
 # This file is distinct from the CONTRIBUTORS files.
 # See the latter for an explanation.
 
-# Names should be added to this file as
-#	Name or Organization <email address>
-# The email address is not required for organizations.
+# Names should be added to this file as one of
+#     Organization's name
+#     Individual's name <submission email address>
+#     Individual's name <submission email address> <email2> <emailN>
+# See CONTRIBUTORS for the meaning of multiple email addresses.
 
 # Please keep the list sorted.
 
 A Medium Corporation
 Aamir Khan <syst3m.w0rm at gmail.com>
 Aaron France <aaron.l.france at gmail.com>
+Aaron Torres <tcboox at gmail.com>
 Abhinav Gupta <abhinav.g90 at gmail.com>
 Adrian Nos <nos.adrian at gmail.com>
 Adrian O'Grady <elpollouk at gmail.com>
 Adrien Bustany <adrien-xx-google at bustany.org>
+Aécio Júnior <aeciodantasjunior at gmail.com>
 Ahmed Waheed Moanes <oneofone at gmail.com>
 Ainar Garipov <gugl.zadolbal at gmail.com>
 Akshat Kumar <seed at mail.nanosouffle.net>
 Alan Shreve <alan at inconshreveable.com>
 Albert Strasheim <fullung at gmail.com>
+Alberto Bertogli <albertito at blitiri.com.ar>
 Alberto Donizetti <alb.donizetti at gmail.com>
 Alberto García Hierro <alberto at garciahierro.com> <alberto.garcia.hierro at gmail.com>
 Aleksandar Dezelin <dezelin at gmail.com>
@@ -29,8 +34,10 @@ Alex Jin <toalexjin at gmail.com>
 Alex Plugaru <alex at plugaru.org> <alexandru.plugaru at gmail.com>
 Alex Schroeder <alex at gnu.org>
 Alex Sergeyev <abc at alexsergeyev.com>
+Alexander Demakin <alexander.demakin at gmail.com>
 Alexander Larsson <alexander.larsson at gmail.com>
 Alexander Morozov <lk4d4math at gmail.com>
+Alexander Neumann <alexander at bumpern.de>
 Alexander Orlov <alexander.orlov at loxal.net>
 Alexander Reece <awreece at gmail.com>
 Alexander Surma <surma at surmair.de>
@@ -41,6 +48,8 @@ Alexandre Normand <alexandre.normand at gmail.com>
 Alexei Sholik <alcosholik at gmail.com>
 Alexey Borzenkov <snaury at gmail.com>
 Alexey Palazhchenko <alexey.palazhchenko at gmail.com>
+Aliaksandr Valialkin <valyala at gmail.com>
+Alif Rachmawadi <subosito at gmail.com>
 Amir Mohammad Saied <amir at gluegadget.com>
 Amrut Joshi <amrut.joshi at gmail.com>
 Andrei Korzhevskii <a.korzhevskiy at gmail.com>
@@ -49,6 +58,7 @@ Andrew Balholm <andybalholm at gmail.com>
 Andrew Bonventre <andybons at chromium.org>
 Andrew Bursavich <abursavich at gmail.com>
 Andrew Ekstedt <andrew.ekstedt at gmail.com>
+Andrew Etter <andrew.etter at gmail.com>
 Andrew Harding <andrew at spacemonkey.com>
 Andrew Lutomirski <andy at luto.us>
 Andrew Pritchard <awpritchard at gmail.com>
@@ -60,11 +70,15 @@ Andrew Williams <williams.andrew at gmail.com>
 Andrey Mirtchovski <mirtchovski at gmail.com>
 Andrey Petrov <andrey.petrov at shazow.net>
 Andriy Lytvynov <lytvynov.a.v at gmail.com>
+Andy Balholm <andy at balholm.com>
 Andy Davis <andy at bigandian.com>
 Andy Maloney <asmaloney at gmail.com>
 Anfernee Yongkun Gui <anfernee.gui at gmail.com>
+Angelo Bulfone <mbulfone at gmail.com>
 Anh Hai Trinh <anh.hai.trinh at gmail.com>
+Anmol Sethi <anmol at aubble.com>
 Anschel Schaffer-Cohen <anschelsc at gmail.com>
+Anthony Canino <anthony.canino1 at gmail.com>
 Anthony Eufemio <anthony.eufemio at gmail.com>
 Anthony Martin <ality at pbrane.org>
 Anthony Starks <ajstarks at gmail.com>
@@ -73,7 +87,9 @@ Aram Hăvărneanu <aram at mgk.ro>
 Areski Belaid <areski at gmail.com>
 Arnaud Ysmal <arnaud.ysmal at gmail.com>
 Arne Hormann <arnehormann at gmail.com>
+Arnout Engelen <arnout at bzzt.net>
 Aron Nopanen <aron.nopanen at gmail.com>
+Artyom Pervukhin <artyom.pervukhin at gmail.com>
 Arvindh Rajesh Tamilmani <art at a-30.net>
 Ato Araki <ato.araki at gmail.com>
 Aulus Egnatius Varialus <varialus at gmail.com>
@@ -112,6 +128,7 @@ Charles L. Dorian <cldorian at gmail.com>
 Charles Lee <zombie.fml at gmail.com>
 Chris Dollin <ehog.hedge at gmail.com>
 Chris Farmiloe <chrisfarms at gmail.com>
+Chris Hines <chris.cs.guy at gmail.com>
 Chris Howey <howeyc at gmail.com>
 Chris Jones <chris at cjones.org>
 Chris Kastorff <encryptio at gmail.com>
@@ -126,20 +143,27 @@ Christopher Guiney <chris at guiney.net>
 Christopher Nielsen <m4dh4tt3r at gmail.com>
 Christopher Redden <christopher.redden at gmail.com>
 Christopher Wedgwood <cw at f00f.org>
+CL Sung <clsung at gmail.com> <cl_sung at htc.com>
 Clement Skau <clementskau at gmail.com>
 CloudFlare Inc.
 Colin Kennedy <moshen.colin at gmail.com>
 Conrad Meyer <cemeyer at cs.washington.edu>
+CoreOS, Inc.
 Corey Thomasson <cthom.lists at gmail.com>
 Cristian Staretu <unclejacksons at gmail.com>
 Damian Gryski <dgryski at gmail.com>
+Dan Caddigan <goldcaddy77 at gmail.com>
 Dan Callahan <dan.callahan at gmail.com>
 Dan Peterson <dpiddy at gmail.com>
 Dan Sinclair <dan.sinclair at gmail.com>
 Daniel Fleischman <danielfleischman at gmail.com>
+Daniel Johansson <dajo2002 at gmail.com>
+Daniel Kerwin <d.kerwin at gini.net>
 Daniel Krech <eikeon at eikeon.com>
 Daniel Lidén <daniel.liden.87 at gmail.com>
 Daniel Morsing <daniel.morsing at gmail.com>
+Daniel Ortiz Pereira da Silva <daniel.particular at gmail.com>
+Daniel Skinner <daniel at dasa.cc>
 Daniel Theophanes <kardianos at gmail.com>
 Darren Elwood <darren at textnode.com>
 Dave Cheney <dave at cheney.net>
@@ -148,24 +172,31 @@ David Calavera <david.calavera at gmail.com>
 David du Colombier <0intro at gmail.com>
 David Forsythe <dforsythe at gmail.com>
 David G. Andersen <dave.andersen at gmail.com>
+David Howden <dhowden at gmail.com>
 David Jakob Fritz <david.jakob.fritz at gmail.com>
 David Leon Gil <coruus at gmail.com>
+David R. Jenni <david.r.jenni at gmail.com>
 David Thomas <davidthomas426 at gmail.com>
 David Titarenco <david.titarenco at gmail.com>
 Davies Liu <davies.liu at gmail.com>
 Dean Prichard <dean.prichard at gmail.com>
+Denis Bernard <db047h at gmail.com>
 Denis Brandolini <denis.brandolini at gmail.com>
 Derek Buitenhuis <derek.buitenhuis at gmail.com>
 Derek Parker <parkerderek86 at gmail.com>
+Develer SRL
 Devon H. O'Dell <devon.odell at gmail.com>
 Dhiru Kholia <dhiru.kholia at gmail.com>
 Didier Spezia <didier.06 at gmail.com>
 Dimitri Tcaciuc <dtcaciuc at gmail.com>
+Dirk Gadsden <dirk at esherido.com>
 Dmitri Shuralyov <shurcooL at gmail.com>
 Dmitriy Shelenin <deemok at googlemail.com> <deemok at gmail.com>
 Dmitry Chestnykh <dchest at gmail.com>
 Dmitry Savintsev <dsavints at gmail.com>
+Dmitry Yakunin <nonamezeil at gmail.com>
 Dominik Honnef <dominik.honnef at gmail.com>
+Donald Huang <don.hcd at gmail.com>
 Donovan Hide <donovanhide at gmail.com>
 Dropbox, Inc.
 Duncan Holm <mail at frou.org>
@@ -173,22 +204,27 @@ Dustin Sallings <dsallings at gmail.com>
 Dustin Shields-Cloues <dcloues at gmail.com>
 Dvir Volk <dvir at everything.me> <dvirsky at gmail.com>
 Eden Li <eden.li at gmail.com>
+Edward Muller <edwardam at interlix.com>
 Egon Elbre <egonelbre at gmail.com>
 Ehren Kret <ehren.kret at gmail.com>
 Eivind Uggedal <eivind at uggedal.com>
 Elias Naur <elias.naur at gmail.com>
 Emil Hessman <c.emil.hessman at gmail.com> <emil at hessman.se>
+Emmanuel Odeke <emm.odeke at gmail.com> <odeke at ualberta.ca>
 Eoghan Sherry <ejsherry at gmail.com>
 Eric Clark <zerohp at gmail.com>
+Eric Lagergren <ericscottlagergren at gmail.com>
 Eric Milliken <emilliken at gmail.com>
 Eric Roshan-Eisner <eric.d.eisner at gmail.com>
 Erik Aigner <aigner.erik at gmail.com>
+Erik Dubbelboer <erik at dubbelboer.com>
 Erik St. Martin <alakriti at gmail.com>
 Erik Westrup <erik.westrup at gmail.com>
 Esko Luontola <esko.luontola at gmail.com>
 Evan Phoenix <evan at phx.io>
 Evan Shaw <chickencha at gmail.com>
 Ewan Chou <coocood at gmail.com>
+Fabian Wickborn <fabian at wickborn.net>
 Fabrizio Milo <mistobaan at gmail.com>
 Fan Hongjian <fan.howard at gmail.com>
 Fastly, Inc.
@@ -199,12 +235,15 @@ Firmansyah Adiputra <frm.adiputra at gmail.com>
 Florian Uekermann <florian at uekermann-online.de>
 Florian Weimer <fw at deneb.enyo.de>
 Florin Patan <florinpatan at gmail.com>
+Ford Hurley <ford.hurley at gmail.com>
+Francisco Claude <fclaude at recoded.cl>
 Francisco Souza <franciscossouza at gmail.com>
 Frederick Kelly Mayle III <frederickmayle at gmail.com>
 Fredrik Enestad <fredrik.enestad at soundtrackyourbrand.com>
 Frithjof Schulze <schulze at math.uni-hannover.de> <sfrithjof at gmail.com>
 Gabriel Aszalos <gabriel.aszalos at gmail.com>
 Gary Burd <gary at beagledreams.com>
+Gaurish Sharma <contact at gaurishsharma.com>
 Gautham Thambidorai <gautham.dorai at gmail.com>
 Geert-Johan Riemer <gjr19912 at gmail.com>
 Georg Reinke <guelfey at gmail.com>
@@ -233,7 +272,11 @@ Hector Martin Cantero <hector at marcansoft.com>
 Henning Schmiedehausen <henning at schmiedehausen.org>
 Henrik Edwards <henrik.edwards at gmail.com>
 Herbert Georg Fischer <herbert.fischer at gmail.com>
+Hiroshi Ioka <hirochachacha at gmail.com>
 Hong Ruiqi <hongruiqi at gmail.com>
+Hsin-Ho Yeh <yhh92u at gmail.com>
+Hu Keping <hukeping at huawei.com>
+Ian Gudger <ian at loosescre.ws>
 IBM
 Icarus Sparry <golang at icarus.freeuk.com>
 Igneous Systems, Inc.
@@ -241,6 +284,7 @@ Igor Dolzhikov <bluesriverz at gmail.com>
 INADA Naoki <songofacandy at gmail.com>
 Ingo Krabbe <ikrabbe.ask at gmail.com>
 Ingo Oeser <nightlyone at googlemail.com>
+Intel Corporation
 Isaac Wagner <ibw at isaacwagner.me>
 Ivan Ukhov <ivan.ukhov at gmail.com>
 Jae Kwon <jae at tendermint.com>
@@ -251,6 +295,8 @@ James Fysh <james.fysh at gmail.com>
 James Gray <james at james4k.com>
 James Meneghello <rawrz0r at gmail.com>
 James P. Cooper <jamespcooper at gmail.com>
+James Schofield <james at shoeboxapp.com>
+James Sweet <james.sweet88 at googlemail.com>
 James Toy <nil at opensesame.st>
 James Whitehead <jnwhiteh at gmail.com>
 Jan H. Hosang <jan.hosang at gmail.com>
@@ -269,9 +315,11 @@ Jeff Sickel <jas at corpus-callosum.com>
 Jeff Wendling <jeff at spacemonkey.com>
 Jens Frederich <jfrederich at gmail.com>
 Jeremy Jackins <jeremyjackins at gmail.com>
+Jihyun Yu <yjh0502 at gmail.com>
 Jim McGrath <jimmc2 at gmail.com>
 Jimmy Zelinskie <jimmyzelinskie at gmail.com>
 Jingcheng Zhang <diogin at gmail.com>
+Jingguo Yao <yaojingguo at gmail.com>
 Jiong Du <londevil at gmail.com>
 Joakim Sernbrant <serbaut at gmail.com>
 Joe Harrison <joehazzers at gmail.com>
@@ -283,9 +331,11 @@ John Asmuth <jasmuth at gmail.com>
 John C Barstow <jbowtie at amathaine.com>
 John Graham-Cumming <jgc at jgc.org> <jgrahamc at gmail.com>
 John Howard Palevich <jack.palevich at gmail.com>
+John Jenkins <twodopeshaggy at gmail.com>
 John Potocny <johnp at vividcortex.com>
 John Shahid <jvshahid at gmail.com>
 John Tuley <john at tuley.org>
+Jonathan Boulle <jonathanboulle at gmail.com>
 Jonathan Gold <jgold.bg at gmail.com>
 Jonathan Mark <jhmark at xenops.com>
 Jonathan Rudenberg <jonathan at titanous.com>
@@ -297,6 +347,7 @@ Josh Bleecher Snyder <josharian at gmail.com>
 Josh Goebel <dreamer3 at gmail.com>
 Josh Holland <jrh at joshh.co.uk>
 Joshua Chase <jcjoshuachase at gmail.com>
+Jostein Stuhaug <js at solidsystem.no>
 JT Olds <jtolds at xnet5.com>
 Jukka-Pekka Kekkonen <karatepekka at gmail.com>
 Julian Phillips <julian at quantumfyre.co.uk>
@@ -308,13 +359,20 @@ Kang Hu <hukangustc at gmail.com>
 Kato Kazuyoshi <kato.kazuyoshi at gmail.com>
 Katrina Owen <katrina.owen at gmail.com>
 Kei Son <hey.calmdown at gmail.com>
+Keith Ball <inflatablewoman at gmail.com>
 Keith Rarick <kr at xph.us>
 Kelsey Hightower <kelsey.hightower at gmail.com>
 Kelvin Foo Chuan Lyi <vmirage at gmail.com>
 Ken Friedenbach <kenliz at cruzio.com>
 Ken Rockot <ken at oz.gs>
+Ken Sedgwick <ken at bonsai.com>
+Kenny Grant <kennygrant at gmail.com>
 Kevin Ballard <kevin at sb.org>
+Klaus Post <klauspost at gmail.com>
 Konstantin Shaposhnikov <k.shaposhnikov at gmail.com>
+KPCompass, Inc.
+Kristopher Watts <traetox at gmail.com>
+Kun Li <likunarmstrong at gmail.com>
 Kyle Consalus <consalus at gmail.com>
 Kyle Isom <kyle at gokyle.net>
 Kyle Lemons <kyle at kylelemons.net>
@@ -322,14 +380,19 @@ L Campbell <unpantsu at gmail.com>
 Lai Jiangshan <eag0628 at gmail.com>
 Larz Conwell <larzconwell at gmail.com>
 Lee Packham <lpackham at gmail.com>
+Lewin Bormann <lewin.bormann at gmail.com>
+Liberty Fund Inc
 Linaro Limited
 Lloyd Dewolf <foolswisdom at gmail.com>
 Lorenzo Stoakes <lstoakes at gmail.com>
 Luca Greco <luca.greco at alcacoop.it>
+Lucien Stuker <lucien.stuker at gmail.com>
 Lucio De Re <lucio.dere at gmail.com>
 Luit van Drongelen <luitvd at gmail.com>
 Luka Zakrajšek <tr00.g33k at gmail.com>
 Luke Curley <qpingu at gmail.com>
+Mal Curtis <mal at mal.co.nz>
+Manu S Ajith <neo at codingarena.in>
 Manuel Mendez <mmendez534 at gmail.com>
 Marc Weistroff <marc at weistroff.net>
 Marco Hennings <marco.hennings at freiheit.com>
@@ -344,12 +407,14 @@ Markus Zimmermann <zimmski at gmail.com>
 Martin Möhrmann <martisch at uos.de>
 Martin Neubauer <m.ne at gmx.net>
 Martin Olsson <martin at minimum.se>
+Marvin Stenger <marvin.stenger94 at gmail.com>
 Mateusz Czapliński <czapkofan at gmail.com>
 Mathias Beke <git at denbeke.be>
 Mathieu Lonjaret <mathieu.lonjaret at gmail.com>
 Mats Lidell <mats.lidell at cag.se>
 Matt Aimonetti <mattaimonetti at gmail.com>
 Matt Bostock <matt at mattbostock.com>
+Matt Drollette <matt at drollette.com>
 Matt Jibson <matt.jibson at gmail.com>
 Matt Joiner <anacrolix at gmail.com>
 Matt Layher <mdlayher at gmail.com>
@@ -362,6 +427,9 @@ Matthew Holt <Matthew.Holt+git at gmail.com>
 Matthew Horsnell <matthew.horsnell at gmail.com>
 Maxim Khitrov <max at mxcrypt.com>
 Meir Fischer <meirfischer at gmail.com>
+Meng Zhuo <mengzhuo1203 at gmail.com>
+Meteor Development Group
+Mhd Sulhan <m.shulhan at gmail.com>
 Micah Stetson <micah.stetson at gmail.com>
 Michael Chaten <mchaten at gmail.com>
 Michael Elkins <michael.elkins at gmail.com>
@@ -376,6 +444,7 @@ Michael Schaller <michael at 5challer.de>
 Michael Stapelberg <michael at stapelberg.de>
 Michael Teichgräber <mteichgraeber at gmx.de>
 Michael Vetter <g.bluehut at gmail.com>
+Michal Bohuslávek <mbohuslavek at gmail.com>
 Michał Derkacz <ziutek at lnet.pl>
 Miek Gieben <miek at miek.nl>
 Mihai Borobocea <MihaiBorobocea at gmail.com>
@@ -387,13 +456,17 @@ Miki Tebeka <miki.tebeka at gmail.com>
 Mikio Hara <mikioh.mikioh at gmail.com>
 Mikkel Krautz <mikkel at krautz.dk>
 Miquel Sabaté Solà <mikisabate at gmail.com>
+Mohit Agarwal <mohit at sdf.org>
 Moov Corporation
 Moriyoshi Koizumi <mozo at mozo.jp>
 Môshe van der Sterre <moshevds at gmail.com>
 Nan Deng <monnand at gmail.com>
 Nathan John Youngman <nj at nathany.com>
+Nathan Otterness <otternes at cs.unc.edu>
 Nathan P Finch <nate.finch at gmail.com>
+Nathan VanBenschoten <nvanbenschoten at gmail.com>
 Nathan Youngman <git at nathany.com>
+Neelesh Chandola <neelesh.c98 at gmail.com>
 Nevins Bartolomeo <nevins.bartolomeo at gmail.com>
 ngmoco, LLC
 Nicholas Katsaros <nick at nickkatsaros.com>
@@ -405,7 +478,10 @@ Nicolas Kaiser <nikai at nikai.net>
 Nicolas Owens <mischief at offblast.org>
 Nicolas S. Dade <nic.dade at gmail.com>
 Nigel Kerr <nigel.kerr at gmail.com>
+Nikolay Turpitko <nikolay at turpitko.com>
 Noah Campbell <noahcampbell at gmail.com>
+Norberto Lopes <nlopes.ml at gmail.com>
+Oleku Konko <oleku.konko at gmail.com>
 Oling Cat <olingcat at gmail.com>
 Oliver Hookins <ohookins at gmail.com>
 Olivier Antoine <olivier.antoine at gmail.com>
@@ -426,11 +502,16 @@ Patrick Smith <pat42smith at gmail.com>
 Paul A Querna <paul.querna at gmail.com>
 Paul Hammond <paul at paulhammond.org>
 Paul Lalonde <paul.a.lalonde at gmail.com>
+Paul Meyer <paul.meyer at microsoft.com>
+Paul Rosania <paul.rosania at gmail.com>
 Paul Sbarra <Sbarra.Paul at gmail.com>
 Paul Smith <paulsmith at pobox.com> <paulsmith at gmail.com>
 Paul van Brouwershaven <paul at vanbrouwershaven.com>
+Pavel Paulau <pavel.paulau at gmail.com>
 Pavel Zinovkin <pavel.zinovkin at gmail.com>
+Pawel Knap <pawelknap88 at gmail.com>
 Percy Wegmann <ox.to.a.cart at gmail.com>
+Perry Abbott <perry.j.abbott at gmail.com>
 Petar Maymounkov <petarm at gmail.com>
 Peter Armitage <peter.armitage at gmail.com>
 Peter Froehlich <peter.hans.froehlich at gmail.com>
@@ -443,14 +524,19 @@ Peter Waldschmidt <peter at waldschmidt.com>
 Peter Waller <peter.waller at gmail.com>
 Peter Williams <pwil3058 at gmail.com>
 Philip K. Warren <pkwarren at gmail.com>
+Pierre Roullon <pierre.roullon at gmail.com>
 Pieter Droogendijk <pieter at binky.org.uk>
 Pietro Gagliardi <pietro10 at mac.com>
 Preetam Jinka <pj at preet.am>
 Quan Yong Zhai <qyzhai at gmail.com>
+Quentin Perez <qperez at ocs.online.net>
 Quoc-Viet Nguyen <afelion at gmail.com>
+RackTop Systems Inc.
 Raif S. Naffah <go at naffah-raif.name>
 Rajat Goel <rajat.goel2010 at gmail.com>
+Ralph Corderoy <ralph at inputplus.co.uk>
 Red Hat, Inc.
+Reinaldo de Souza Jr <juniorz at gmail.com>
 Rémy Oudompheng <oudomphe at phare.normalesup.org>
 Richard Barnes <rlb at ipv.sx>
 Richard Crowley <r at rcrowley.org>
@@ -458,11 +544,13 @@ Richard Eric Gavaletz <gavaletz at gmail.com>
 Richard Musiol <mail at richard-musiol.de>
 Rick Arnold <rickarnoldjr at gmail.com>
 Risto Jaakko Saarelma <rsaarelm at gmail.com>
+Rob Norman <rob.norman at infinitycloud.com>
 Robert Daniel Kortschak <dan.kortschak at adelaide.edu.au>
 Robert Dinu <r at varp.se>
 Robert Figueiredo <robfig at gmail.com>
 Robert Hencke <robert.hencke at gmail.com>
 Robert Obryk <robryk at gmail.com>
+Robert Stepanek <robert.stepanek at gmail.com>
 Robin Eklind <r.eklind.87 at gmail.com>
 Rodrigo Moraes de Oliveira <rodrigo.moraes at gmail.com>
 Rodrigo Rafael Monti Kochenburger <divoxx at gmail.com>
@@ -472,27 +560,34 @@ Ron Hashimoto <mail at h2so5.net>
 Ron Minnich <rminnich at gmail.com>
 Ross Light <rlight2 at gmail.com>
 Rowan Worth <sqweek at gmail.com>
+Russell Haering <russellhaering at gmail.com>
 Ryan Hitchman <hitchmanr at gmail.com>
+Ryan Lower <rpjlower at gmail.com>
 Ryan Seys <ryan at ryanseys.com>
 Ryan Slade <ryanslade at gmail.com>
 S.Çağlar Onur <caglar at 10ur.org>
+Salmān Aljammāz <s at 0x65.net>
 Sanjay Menakuru <balasanjay at gmail.com>
 Scott Barron <scott.barron at github.com>
 Scott Ferguson <scottwferg at gmail.com>
 Scott Lawrence <bytbox at gmail.com>
-Sebastien Binet	<seb.binet at gmail.com>
+Sebastien Binet <seb.binet at gmail.com>
 Sébastien Paolacci <sebastien.paolacci at gmail.com>
 Sergei Skorobogatov <skorobo at rambler.ru>
 Sergey 'SnakE'  Gromov <snake.scaly at gmail.com>
 Sergio Luis O. B. Correia <sergio at correia.cc>
+Seth Hoenig <seth.a.hoenig at gmail.com>
 Shane Hansen <shanemhansen at gmail.com>
+Shaozhen Ding <dsz0111 at gmail.com>
 Shawn Smith <shawn.p.smith at gmail.com>
 Shenghou Ma <minux.ma at gmail.com>
 Shivakumar GN <shivakumar.gn at gmail.com>
 Silvan Jegen <s.jegen at gmail.com>
 Simon Whitehead <chemnova at gmail.com>
 Sokolov Yura <funny.falcon at gmail.com>
+Spencer Nelson <s at spenczar.com>
 Spring Mc <heresy.mc at gmail.com>
+Square, Inc.
 StalkR <stalkr at stalkr.net>
 Stan Schwertly <stan at schwertly.com>
 Stefan Nilsson <snilsson at nada.kth.se> <trolleriprofessorn at gmail.com>
@@ -500,6 +595,7 @@ Stéphane Travostino <stephane.travostino at gmail.com>
 Stephen McQuay <stephen at mcquay.me>
 Stephen Weinberg <stephen at q5comm.com>
 Steve McCoy <mccoyst at gmail.com>
+Steve Phillips <elimisteve at gmail.com>
 Steve Streeting <steve at stevestreeting.com>
 Steven Elliot Harris <seharris at gmail.com>
 Steven Hartland <steven.hartland at multiplay.co.uk>
@@ -508,13 +604,18 @@ Sven Almgren <sven at tras.se>
 Szabolcs Nagy <nsz at port70.net>
 Tad Glines <tad.glines at gmail.com>
 Taj Khattra <taj.khattra at gmail.com>
+Takeshi YAMANASHI <9.nashi at gmail.com>
 Tamir Duberstein <tamird at gmail.com>
 Tarmigan Casebolt <tarmigan at gmail.com>
 Taru Karttunen <taruti at taruti.net>
+Tatsuhiro Tsujikawa <tatsuhiro.t at gmail.com>
 Tetsuo Kiso <tetsuokiso9 at gmail.com>
 Thiago Fransosi Farina <thiago.farina at gmail.com>
 Thomas Alan Copeland <talan.copeland at gmail.com>
+Thomas Desrosiers <thomasdesr at gmail.com>
 Thomas Kappler <tkappler at gmail.com>
+Thorben Krueger <thorben.krueger at gmail.com>
+Tim Cooijmans <timcooijmans at gmail.com>
 Timo Savola <timo.savola at gmail.com>
 Timo Truyts <alkaloid.btx at gmail.com>
 Tobias Columbus <tobias.columbus at gmail.com>
@@ -523,12 +624,16 @@ Tom Heng <zhm20070928 at gmail.com>
 Tom Linford <tomlinford at gmail.com>
 Tommy Schaefer <tommy.schaefer at teecom.com>
 Tor Andersson <tor.andersson at gmail.com>
+Tormod Erevik Lea <tormodlea at gmail.com>
+Totoro W <tw19881113 at gmail.com>
 Travis Cline <travis.cline at gmail.com>
+Trey Tacon <ttacon at gmail.com>
 Tudor Golubenco <tudor.g at gmail.com>
-Tw <tw19881113 at gmail.com>
 Tyler Bunnell <tylerbunnell at gmail.com>
+Tyler Treat <ttreat31 at gmail.com>
 Ugorji Nwoke <ugorji at gmail.com>
 Ulf Holm Nielsen <doktor at dyregod.dk>
+Ulrich Kunitz <uli.kunitz at gmail.com>
 Uriel Mangado <uriel at berlinblue.org>
 Vadim Vygonets <unixdj at gmail.com>
 Vincent Ambo <tazjin at googlemail.com>
@@ -543,7 +648,12 @@ William Josephson <wjosephson at gmail.com>
 William Orr <will at worrbase.com> <ay1244 at gmail.com>
 Xia Bin <snyh at snyh.org>
 Xing Xing <mikespook at gmail.com>
+Yahoo Inc.
+Yann Kerhervé <yann.kerherve at gmail.com>
+Yao Zhang <lunaria21 at gmail.com>
+Yasuharu Goto <matope.ono at gmail.com>
 Yasuhiro Matsumoto <mattn.jp at gmail.com>
+Yesudeep Mangalapilly <yesudeep at google.com>
 Yissakhar Z. Beck <yissakhar.beck at gmail.com>
 Yo-An Lin <yoanlin93 at gmail.com>
 Yongjian Xu <i3dmaster at gmail.com>
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index d974f36..ae07cfc 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -22,12 +22,13 @@
 # individual or corporate CLA was used.
 
 # Names should be added to this file like so:
-#     Name <email address>
+#     Individual's name <submission email address>
+#     Individual's name <submission email address> <email2> <emailN>
 #
-# An entry with two email addresses specifies that the
+# An entry with multiple email addresses specifies that the
 # first address should be used in the submit logs and
-# that the second address should be recognized as the
-# same person when interacting with Rietveld.
+# that the other addresses should be recognized as the
+# same person when interacting with Gerrit.
 
 # Please keep the list sorted.
 
@@ -35,17 +36,20 @@ Aamir Khan <syst3m.w0rm at gmail.com>
 Aaron France <aaron.l.france at gmail.com>
 Aaron Jacobs <jacobsa at google.com>
 Aaron Kemp <kemp.aaron at gmail.com>
+Aaron Torres <tcboox at gmail.com>
 Abhinav Gupta <abhinav.g90 at gmail.com>
 Adam Langley <agl at golang.org>
 Adrian Nos <nos.adrian at gmail.com>
 Adrian O'Grady <elpollouk at gmail.com>
 Adrien Bustany <adrien-xx-google at bustany.org>
+Aécio Júnior <aeciodantasjunior at gmail.com>
 Ahmed Waheed Moanes <oneofone at gmail.com>
 Ainar Garipov <gugl.zadolbal at gmail.com>
 Akshat Kumar <seed at mail.nanosouffle.net>
 Alan Donovan <adonovan at google.com>
 Alan Shreve <alan at inconshreveable.com>
 Albert Strasheim <fullung at gmail.com>
+Alberto Bertogli <albertito at blitiri.com.ar>
 Alberto Donizetti <alb.donizetti at gmail.com>
 Alberto García Hierro <alberto at garciahierro.com> <alberto.garcia.hierro at gmail.com>
 Aleksandar Dezelin <dezelin at gmail.com>
@@ -56,8 +60,10 @@ Alex Jin <toalexjin at gmail.com>
 Alex Plugaru <alex at plugaru.org> <alexandru.plugaru at gmail.com>
 Alex Schroeder <alex at gnu.org>
 Alex Sergeyev <abc at alexsergeyev.com>
+Alexander Demakin <alexander.demakin at gmail.com>
 Alexander Larsson <alexander.larsson at gmail.com>
 Alexander Morozov <lk4d4math at gmail.com>
+Alexander Neumann <alexander at bumpern.de>
 Alexander Orlov <alexander.orlov at loxal.net>
 Alexander Reece <awreece at gmail.com>
 Alexander Surma <surma at surmair.de>
@@ -70,6 +76,8 @@ Alexei Sholik <alcosholik at gmail.com>
 Alexey Borzenkov <snaury at gmail.com>
 Alexey Palazhchenko <alexey.palazhchenko at gmail.com>
 Alexis Imperial-Legrand <ail at google.com>
+Aliaksandr Valialkin <valyala at gmail.com>
+Alif Rachmawadi <subosito at gmail.com>
 Amir Mohammad Saied <amir at gluegadget.com>
 Amrut Joshi <amrut.joshi at gmail.com>
 Andrea Spadaccini <spadaccio at google.com>
@@ -81,6 +89,7 @@ Andrew Balholm <andybalholm at gmail.com>
 Andrew Bonventre <andybons at chromium.org>
 Andrew Bursavich <abursavich at gmail.com>
 Andrew Ekstedt <andrew.ekstedt at gmail.com>
+Andrew Etter <andrew.etter at gmail.com>
 Andrew Gerrand <adg at golang.org>
 Andrew Harding <andrew at spacemonkey.com>
 Andrew Lutomirski <andy at luto.us>
@@ -94,20 +103,27 @@ Andrew Williams <williams.andrew at gmail.com>
 Andrey Mirtchovski <mirtchovski at gmail.com>
 Andrey Petrov <andrey.petrov at shazow.net>
 Andriy Lytvynov <lytvynov.a.v at gmail.com>
+Andy Balholm <andy at balholm.com>
 Andy Davis <andy at bigandian.com>
 Andy Maloney <asmaloney at gmail.com>
 Anfernee Yongkun Gui <anfernee.gui at gmail.com>
+Angelo Bulfone <mbulfone at gmail.com>
 Anh Hai Trinh <anh.hai.trinh at gmail.com>
+Anmol Sethi <anmol at aubble.com>
 Anschel Schaffer-Cohen <anschelsc at gmail.com>
+Anthony Canino <anthony.canino1 at gmail.com>
 Anthony Eufemio <anthony.eufemio at gmail.com>
 Anthony Martin <ality at pbrane.org>
 Anthony Starks <ajstarks at gmail.com>
 Apisak Darakananda <pongad at gmail.com>
 Aram Hăvărneanu <aram at mgk.ro>
 Areski Belaid <areski at gmail.com>
+Arkadi Pyuro <arkadi at google.com>
 Arnaud Ysmal <arnaud.ysmal at gmail.com>
 Arne Hormann <arnehormann at gmail.com>
+Arnout Engelen <arnout at bzzt.net>
 Aron Nopanen <aron.nopanen at gmail.com>
+Artyom Pervukhin <artyom.pervukhin at gmail.com>
 Arvindh Rajesh Tamilmani <art at a-30.net>
 Asim Shankar <asimshankar at gmail.com>
 Ato Araki <ato.araki at gmail.com>
@@ -122,6 +138,7 @@ Ben Fried <ben.fried at gmail.com>
 Ben Lynn <benlynn at gmail.com>
 Ben Olive <sionide21 at gmail.com>
 Benjamin Black <b at b3k.us>
+Benjamin Prosnitz <bprosnitz at google.com>
 Benny Siegert <bsiegert at gmail.com>
 Benoit Sigoure <tsunanet at gmail.com>
 Berengar Lehr <Berengar.Lehr at gmx.de>
@@ -141,10 +158,11 @@ Brendan O'Dea <bod at golang.org>
 Brett Cannon <bcannon at gmail.com>
 Brian Dellisanti <briandellisanti at gmail.com>
 Brian G. Merrell <bgmerrell at gmail.com>
-Brian Gitonga Marete <marete at toshnix.com> <bgmarete at gmail.com>
+Brian Gitonga Marete <marete at toshnix.com> <bgmarete at gmail.com> <bgm at google.com>
 Brian Ketelsen <bketelsen at gmail.com>
 Brian Slesinsky <skybrian at google.com>
 Brian Smith <ohohvi at gmail.com>
+Bryan C. Mills <bcmills at google.com>
 Bryan Ford <brynosaurus at gmail.com>
 Burcu Dogan <jbd at google.com> <burcujdogan at gmail.com>
 Caine Tighe <arctanofyourface at gmail.com>
@@ -159,13 +177,16 @@ Cary Hull <chull at google.com>
 Case Nelson <case.nelson at gmail.com>
 Casey Marshall <casey.marshall at gmail.com>
 Catalin Patulea <catalinp at google.com>
+Cedric Staub <cs at squareup.com>
 Cezar Sá Espinola <cezarsa at gmail.com>
 ChaiShushan <chaishushan at gmail.com>
 Charles L. Dorian <cldorian at gmail.com>
 Charles Lee <zombie.fml at gmail.com>
+Charles Weill <weill at google.com>
 Chris Broadfoot <cbro at golang.org>
 Chris Dollin <ehog.hedge at gmail.com>
 Chris Farmiloe <chrisfarms at gmail.com>
+Chris Hines <chris.cs.guy at gmail.com>
 Chris Howey <howeyc at gmail.com>
 Chris Hundt <hundt at google.com>
 Chris Jones <chris at cjones.org> <chris.jones.yar at gmail.com>
@@ -183,8 +204,10 @@ Christopher Nielsen <m4dh4tt3r at gmail.com>
 Christopher Redden <christopher.redden at gmail.com>
 Christopher Swenson <cswenson at google.com>
 Christopher Wedgwood <cw at f00f.org>
+CL Sung <clsung at gmail.com> <cl_sung at htc.com>
 Clement Skau <clementskau at gmail.com>
 Colby Ranger <cranger at google.com>
+Colin Cross <ccross at android.com>
 Colin Kennedy <moshen.colin at gmail.com>
 Conrad Meyer <cemeyer at cs.washington.edu>
 Corey Thomasson <cthom.lists at gmail.com>
@@ -192,23 +215,31 @@ Cosmos Nicolaou <cnicolaou at google.com>
 Cristian Staretu <unclejacksons at gmail.com>
 Damian Gryski <dgryski at gmail.com>
 Damien Neil <dneil at google.com>
+Dan Caddigan <goldcaddy77 at gmail.com>
 Dan Callahan <dan.callahan at gmail.com>
+Dan Jacques <dnj at google.com>
 Dan Peterson <dpiddy at gmail.com>
 Dan Pupius <dan at medium.com>
 Dan Sinclair <dan.sinclair at gmail.com>
 Daniel Fleischman <danielfleischman at gmail.com>
+Daniel Johansson <dajo2002 at gmail.com>
+Daniel Kerwin <d.kerwin at gini.net>
 Daniel Krech <eikeon at eikeon.com>
 Daniel Lidén <daniel.liden.87 at gmail.com>
 Daniel Morsing <daniel.morsing at gmail.com>
 Daniel Nadasi <dnadasi at google.com>
+Daniel Ortiz Pereira da Silva <daniel.particular at gmail.com>
+Daniel Skinner <daniel at dasa.cc>
 Daniel Theophanes <kardianos at gmail.com>
 Darren Elwood <darren at textnode.com>
 Dave Borowitz <dborowitz at google.com>
+Dave Bort <dbort at golang.org>
 Dave Cheney <dave at cheney.net>
 Dave Day <djd at golang.org>
 Dave Grijalva <dgrijalva at ngmoco.com>
 David Anderson <danderson at google.com>
 David Barnett <dbarnett at google.com>
+David Benjamin <davidben at google.com>
 David Bürgin <676c7473 at gmail.com>
 David Calavera <david.calavera at gmail.com>
 David Chase <drchase at google.com>
@@ -217,29 +248,37 @@ David Crawshaw <david.crawshaw at zentus.com> <crawshaw at google.com> <crawshaw at golan
 David du Colombier <0intro at gmail.com>
 David Forsythe <dforsythe at gmail.com>
 David G. Andersen <dave.andersen at gmail.com>
+David Glasser <glasser at meteor.com>
+David Howden <dhowden at gmail.com>
 David Jakob Fritz <david.jakob.fritz at gmail.com>
 David Leon Gil <coruus at gmail.com>
 David McLeish <davemc at google.com>
 David Presotto <presotto at gmail.com>
+David R. Jenni <david.r.jenni at gmail.com>
 David Symonds <dsymonds at golang.org>
 David Thomas <davidthomas426 at gmail.com>
 David Titarenco <david.titarenco at gmail.com>
 Davies Liu <davies.liu at gmail.com>
 Dean Prichard <dean.prichard at gmail.com>
+Denis Bernard <db047h at gmail.com>
 Denis Brandolini <denis.brandolini at gmail.com>
 Derek Buitenhuis <derek.buitenhuis at gmail.com>
+Derek Che <drc at yahoo-inc.com>
 Derek Parker <parkerderek86 at gmail.com>
 Devon H. O'Dell <devon.odell at gmail.com>
 Dhiru Kholia <dhiru.kholia at gmail.com>
 Didier Spezia <didier.06 at gmail.com>
 Dimitri Tcaciuc <dtcaciuc at gmail.com>
+Dirk Gadsden <dirk at esherido.com>
 Dmitri Shuralyov <shurcooL at gmail.com>
 Dmitriy Shelenin <deemok at googlemail.com> <deemok at gmail.com>
 Dmitriy Vyukov <dvyukov at google.com>
 Dmitry Chestnykh <dchest at gmail.com>
 Dmitry Savintsev <dsavints at gmail.com>
+Dmitry Yakunin <nonamezeil at gmail.com>
 Dominik Honnef <dominik.honnef at gmail.com>
 Dominik Vogt <vogt at linux.vnet.ibm.com>
+Donald Huang <don.hcd at gmail.com>
 Donovan Hide <donovanhide at gmail.com>
 Drew Hintz <adhintz at google.com>
 Duncan Holm <mail at frou.org>
@@ -248,35 +287,47 @@ Dustin Sallings <dsallings at gmail.com>
 Dustin Shields-Cloues <dcloues at gmail.com>
 Dvir Volk <dvir at everything.me> <dvirsky at gmail.com>
 Eden Li <eden.li at gmail.com>
+Edward Muller <edwardam at interlix.com>
 Egon Elbre <egonelbre at gmail.com>
 Ehren Kret <ehren.kret at gmail.com>
 Eivind Uggedal <eivind at uggedal.com>
 Elias Naur <elias.naur at gmail.com>
 Emil Hessman <c.emil.hessman at gmail.com> <emil at hessman.se>
+Emmanuel Odeke <emm.odeke at gmail.com> <odeke at ualberta.ca>
 Eoghan Sherry <ejsherry at gmail.com>
 Eric Clark <zerohp at gmail.com>
+Eric Garrido <ekg at google.com>
+Eric Koleda <ekoleda+devrel at google.com>
+Eric Lagergren <ericscottlagergren at gmail.com>
 Eric Milliken <emilliken at gmail.com>
 Eric Roshan-Eisner <eric.d.eisner at gmail.com>
 Erik Aigner <aigner.erik at gmail.com>
+Erik Dubbelboer <erik at dubbelboer.com>
 Erik St. Martin <alakriti at gmail.com>
 Erik Westrup <erik.westrup at gmail.com>
 Esko Luontola <esko.luontola at gmail.com>
+Evan Broder <evan at stripe.com>
+Evan Brown <evanbrown at google.com>
 Evan Kroske <evankroske at google.com>
 Evan Martin <evan.martin at gmail.com>
 Evan Phoenix <evan at phx.io>
 Evan Shaw <chickencha at gmail.com>
 Ewan Chou <coocood at gmail.com>
+Fabian Wickborn <fabian at wickborn.net>
 Fabrizio Milo <mistobaan at gmail.com>
 Fan Hongjian <fan.howard at gmail.com>
 Fatih Arslan <fatih at arslan.io>
 Fazlul Shahriar <fshahriar at gmail.com>
+Federico Simoncelli <fsimonce at redhat.com>
 Felix Geisendörfer <haimuiba at gmail.com>
 Firmansyah Adiputra <frm.adiputra at gmail.com>
 Florian Uekermann <florian at uekermann-online.de> <f1 at uekermann-online.de>
 Florian Weimer <fw at deneb.enyo.de>
 Florin Patan <florinpatan at gmail.com>
 Folke Behrens <folke at google.com>
+Ford Hurley <ford.hurley at gmail.com>
 Francesc Campoy <campoy at golang.org>
+Francisco Claude <fclaude at recoded.cl>
 Francisco Souza <franciscossouza at gmail.com>
 Frederick Kelly Mayle III <frederickmayle at gmail.com>
 Fredrik Enestad <fredrik.enestad at soundtrackyourbrand.com>
@@ -284,7 +335,9 @@ Frithjof Schulze <schulze at math.uni-hannover.de> <sfrithjof at gmail.com>
 Fumitoshi Ukai <ukai at google.com>
 Gaal Yahas <gaal at google.com>
 Gabriel Aszalos <gabriel.aszalos at gmail.com>
+Garrick Evans <garrick at google.com>
 Gary Burd <gary at beagledreams.com> <gary.burd at gmail.com>
+Gaurish Sharma <contact at gaurishsharma.com>
 Gautham Thambidorai <gautham.dorai at gmail.com>
 Geert-Johan Riemer <gjr19912 at gmail.com>
 Georg Reinke <guelfey at gmail.com>
@@ -292,7 +345,9 @@ George Shammas <george at shamm.as> <georgyo at gmail.com>
 Gerasimos Dimitriadis <gedimitr at gmail.com>
 Gideon Jan-Wessel Redelinghuys <gjredelinghuys at gmail.com>
 Giles Lean <giles.lean at pobox.com>
+Giovanni Bajo <rasky at develer.com>
 Giulio Iotti <dullgiulio at gmail.com>
+Glenn Brown <glennb at google.com>
 Glenn Lewis <gmlewis at google.com>
 Gordon Klaus <gordon.klaus at gmail.com>
 Graham King <graham4king at gmail.com>
@@ -315,12 +370,17 @@ Hector Martin Cantero <hector at marcansoft.com>
 Henning Schmiedehausen <henning at schmiedehausen.org>
 Henrik Edwards <henrik.edwards at gmail.com>
 Herbert Georg Fischer <herbert.fischer at gmail.com>
+Hiroshi Ioka <hirochachacha at gmail.com>
 Hong Ruiqi <hongruiqi at gmail.com>
 Hossein Sheikh Attar <hattar at google.com>
+Hsin-Ho Yeh <yhh92u at gmail.com>
+Hu Keping <hukeping at huawei.com>
 Hyang-Ah Hana Kim <hakim at google.com> <hyangah at gmail.com>
+Ian Gudger <ian at loosescre.ws>
 Ian Lance Taylor <iant at golang.org>
 Icarus Sparry <golang at icarus.freeuk.com>
 Igor Dolzhikov <bluesriverz at gmail.com>
+Ilya Tocar <ilya.tocar at intel.com>
 INADA Naoki <songofacandy at gmail.com>
 Ingo Krabbe <ikrabbe.ask at gmail.com>
 Ingo Oeser <nightlyone at googlemail.com> <nightlyone at gmail.com>
@@ -331,6 +391,7 @@ Jacob Baskin <jbaskin at google.com>
 Jacob H. Haven <jacob at cloudflare.com>
 Jae Kwon <jae at tendermint.com>
 Jakob Borg <jakob at nym.se>
+Jakub Čajka <jcajka at redhat.com>
 Jakub Ryszard Czarnowicz <j.czarnowicz at gmail.com>
 James Aguilar <jaguilar at google.com>
 James David Chalfant <james.chalfant at gmail.com>
@@ -339,6 +400,8 @@ James Gray <james at james4k.com>
 James Meneghello <rawrz0r at gmail.com>
 James P. Cooper <jamespcooper at gmail.com>
 James Robinson <jamesr at google.com> <jamesr.gatech at gmail.com>
+James Schofield <james at shoeboxapp.com>
+James Sweet <james.sweet88 at googlemail.com>
 James Toy <nil at opensesame.st>
 James Tucker <raggi at google.com>
 James Whitehead <jnwhiteh at gmail.com>
@@ -354,6 +417,7 @@ Jan Ziak <0xe2.0x9a.0x9b at gmail.com>
 Jani Monoses <jani.monoses at ubuntu.com> <jani.monoses at gmail.com>
 Jaroslavas Počepko <jp at webmaster.ms>
 Jason Del Ponte <delpontej at gmail.com>
+Jason Hall <jasonhall at google.com>
 Jason Travis <infomaniac7 at gmail.com>
 Jay Weisskopf <jay at jayschwa.net>
 Jean-Marc Eurin <jmeurin at google.com>
@@ -366,9 +430,12 @@ Jens Frederich <jfrederich at gmail.com>
 Jeremiah Harmsen <jeremiah at google.com>
 Jeremy Jackins <jeremyjackins at gmail.com>
 Jeremy Schlatter <jeremy.schlatter at gmail.com>
+Jihyun Yu <yjh0502 at gmail.com>
+Jim Cote <jfcote87 at gmail.com>
 Jim McGrath <jimmc2 at gmail.com>
 Jimmy Zelinskie <jimmyzelinskie at gmail.com>
 Jingcheng Zhang <diogin at gmail.com>
+Jingguo Yao <yaojingguo at gmail.com>
 Jiong Du <londevil at gmail.com>
 Joakim Sernbrant <serbaut at gmail.com>
 Joe Harrison <joehazzers at gmail.com>
@@ -385,11 +452,13 @@ John DeNero <denero at google.com>
 John Dethridge <jcd at golang.org>
 John Graham-Cumming <jgc at jgc.org> <jgrahamc at gmail.com>
 John Howard Palevich <jack.palevich at gmail.com>
+John Jenkins <twodopeshaggy at gmail.com>
 John Newlin <jnewlin at google.com>
 John Potocny <johnp at vividcortex.com>
 John Shahid <jvshahid at gmail.com>
 John Tuley <john at tuley.org>
 Jonathan Allie <jonallie at google.com>
+Jonathan Boulle <jonathanboulle at gmail.com>
 Jonathan Feinberg <feinberg at google.com>
 Jonathan Gold <jgold.bg at gmail.com>
 Jonathan Hseu <jhseu at google.com>
@@ -408,11 +477,13 @@ Josh Goebel <dreamer3 at gmail.com>
 Josh Hoak <jhoak at google.com>
 Josh Holland <jrh at joshh.co.uk>
 Joshua Chase <jcjoshuachase at gmail.com>
+Jostein Stuhaug <js at solidsystem.no>
 JP Sugarbroad <jpsugar at google.com>
 JT Olds <jtolds at xnet5.com>
 Jukka-Pekka Kekkonen <karatepekka at gmail.com>
 Julian Phillips <julian at quantumfyre.co.uk>
 Julien Schmidt <google at julienschmidt.com>
+Jungho Ahn <jhahn at google.com>
 Justin Nuß <nuss.justin at gmail.com>
 Kai Backman <kaib at golang.org>
 Kamil Kisiel <kamil at kamilkisiel.net> <kamil.kisiel at gmail.com>
@@ -420,18 +491,27 @@ Kang Hu <hukangustc at gmail.com>
 Kato Kazuyoshi <kato.kazuyoshi at gmail.com>
 Katrina Owen <katrina.owen at gmail.com>
 Kay Zhu <kayzhu at google.com>
+KB Sriram <kbsriram at google.com>
 Kei Son <hey.calmdown at gmail.com>
+Keith Ball <inflatablewoman at gmail.com>
 Keith Randall <khr at golang.org>
 Keith Rarick <kr at xph.us>
 Kelsey Hightower <kelsey.hightower at gmail.com>
 Kelvin Foo Chuan Lyi <vmirage at gmail.com>
 Ken Friedenbach <kenliz at cruzio.com>
 Ken Rockot <ken at oz.gs> <ken.rockot at gmail.com>
+Ken Sedgwick <ken at bonsai.com>
 Ken Thompson <ken at golang.org>
+Kenny Grant <kennygrant at gmail.com>
 Kevin Ballard <kevin at sb.org>
 Kevin Klues <klueska at gmail.com> <klueska at google.com>
+Kevin Malachowski <chowski at google.com>
+Kim Shrier <kshrier at racktopsystems.com>
 Kirklin McDonald <kirklin.mcdonald at gmail.com>
+Klaus Post <klauspost at gmail.com>
 Konstantin Shaposhnikov <k.shaposhnikov at gmail.com>
+Kristopher Watts <traetox at gmail.com>
+Kun Li <likunarmstrong at gmail.com>
 Kyle Consalus <consalus at gmail.com>
 Kyle Isom <kyle at gokyle.net>
 Kyle Lemons <kyle at kylelemons.net> <kevlar at google.com>
@@ -440,10 +520,12 @@ Lai Jiangshan <eag0628 at gmail.com>
 Larry Hosken <lahosken at golang.org>
 Larz Conwell <larzconwell at gmail.com>
 Lee Packham <lpackham at gmail.com>
+Lewin Bormann <lewin.bormann at gmail.com>
 Lloyd Dewolf <foolswisdom at gmail.com>
 Lorenzo Stoakes <lstoakes at gmail.com>
 Louis Kruger <louisk at google.com>
 Luca Greco <luca.greco at alcacoop.it>
+Lucien Stuker <lucien.stuker at gmail.com>
 Lucio De Re <lucio.dere at gmail.com>
 Luit van Drongelen <luitvd at gmail.com>
 Luka Zakrajšek <tr00.g33k at gmail.com>
@@ -451,12 +533,15 @@ Luke Curley <qpingu at gmail.com>
 Luna Duclos <luna.duclos at palmstonegames.com>
 Luuk van Dijk <lvd at golang.org> <lvd at google.com>
 Lynn Boger <laboger at linux.vnet.ibm.com>
+Mal Curtis <mal at mal.co.nz>
 Manoj Dayaram <platform-dev at moovweb.com> <manoj.dayaram at moovweb.com>
 Manu Garg <manugarg at google.com>
+Manu S Ajith <neo at codingarena.in>
 Manuel Mendez <mmendez534 at gmail.com>
 Marc Weistroff <marc at weistroff.net>
 Marcel van Lohuizen <mpvl at golang.org>
 Marco Hennings <marco.hennings at freiheit.com>
+Marga Manterola <marga at google.com>
 Marius Nuennerich <mnu at google.com>
 Mark Bucciarelli <mkbucc at gmail.com>
 Mark Theunissen <mark.theunissen at gmail.com>
@@ -470,6 +555,7 @@ Markus Zimmermann <zimmski at gmail.com>
 Martin Möhrmann <martisch at uos.de>
 Martin Neubauer <m.ne at gmx.net>
 Martin Olsson <martin at minimum.se>
+Marvin Stenger <marvin.stenger94 at gmail.com>
 Mateusz Czapliński <czapkofan at gmail.com>
 Mathias Beke <git at denbeke.be>
 Mathieu Lonjaret <mathieu.lonjaret at gmail.com>
@@ -477,6 +563,7 @@ Mats Lidell <mats.lidell at cag.se> <mats.lidell at gmail.com>
 Matt Aimonetti <mattaimonetti at gmail.com>
 Matt Bostock <matt at mattbostock.com>
 Matt Brown <mdbrown at google.com>
+Matt Drollette <matt at drollette.com>
 Matt Jibson <matt.jibson at gmail.com>
 Matt Joiner <anacrolix at gmail.com>
 Matt Jones <mrjones at google.com>
@@ -493,6 +580,8 @@ Maxim Khitrov <max at mxcrypt.com>
 Maxim Pimenov <mpimenov at google.com>
 Maxim Ushakov <ushakov at google.com>
 Meir Fischer <meirfischer at gmail.com>
+Meng Zhuo <mengzhuo1203 at gmail.com>
+Mhd Sulhan <m.shulhan at gmail.com>
 Micah Stetson <micah.stetson at gmail.com>
 Michael Chaten <mchaten at gmail.com>
 Michael Elkins <michael.elkins at gmail.com>
@@ -504,6 +593,7 @@ Michael Käufl <golang at c.michael-kaeufl.de>
 Michael Kelly <mjk at google.com>
 Michael Lewis <mikelikespie at gmail.com>
 Michael MacInnis <Michael.P.MacInnis at gmail.com>
+Michael Marineau <michael.marineau at coreos.com>
 Michael Matloob <matloob at google.com>
 Michael McGreevy <mcgreevy at golang.org>
 Michael Pearson <mipearson at gmail.com>
@@ -514,6 +604,7 @@ Michael Stapelberg <michael at stapelberg.de> <mstplbrg at googlemail.com>
 Michael T. Jones <mtj at google.com> <michael.jones at gmail.com>
 Michael Teichgräber <mteichgraeber at gmx.de> <mt4swm at googlemail.com>
 Michael Vetter <g.bluehut at gmail.com>
+Michal Bohuslávek <mbohuslavek at gmail.com>
 Michal Cierniak <cierniak at google.com>
 Michał Derkacz <ziutek at lnet.pl>
 Michalis Kargakis <michaliskargakis at gmail.com>
@@ -529,13 +620,18 @@ Miki Tebeka <miki.tebeka at gmail.com>
 Mikio Hara <mikioh.mikioh at gmail.com>
 Mikkel Krautz <mikkel at krautz.dk> <krautz at gmail.com>
 Miquel Sabaté Solà <mikisabate at gmail.com>
+Mohit Agarwal <mohit at sdf.org>
 Moriyoshi Koizumi <mozo at mozo.jp>
 Môshe van der Sterre <moshevds at gmail.com>
 Mrunal Patel <mrunalp at gmail.com>
 Nan Deng <monnand at gmail.com>
 Nathan John Youngman <nj at nathany.com>
+Nathan Otterness <otternes at cs.unc.edu>
 Nathan P Finch <nate.finch at gmail.com>
+Nathan VanBenschoten <nvanbenschoten at gmail.com>
 Nathan Youngman <git at nathany.com>
+Nathan(yinian) Hu <nathanhu at google.com>
+Neelesh Chandola <neelesh.c98 at gmail.com>
 Nevins Bartolomeo <nevins.bartolomeo at gmail.com>
 Nicholas Katsaros <nick at nickkatsaros.com>
 Nicholas Presta <nick at nickpresta.ca> <nick1presta at gmail.com>
@@ -548,7 +644,11 @@ Nicolas Owens <mischief at offblast.org>
 Nicolas S. Dade <nic.dade at gmail.com>
 Nigel Kerr <nigel.kerr at gmail.com>
 Nigel Tao <nigeltao at golang.org>
+Nikolay Turpitko <nikolay at turpitko.com>
 Noah Campbell <noahcampbell at gmail.com>
+Nodir Turakulov <nodir at google.com>
+Norberto Lopes <nlopes.ml at gmail.com>
+Oleku Konko <oleku.konko at gmail.com>
 Oling Cat <olingcat at gmail.com>
 Oliver Hookins <ohookins at gmail.com>
 Olivier Antoine <olivier.antoine at gmail.com>
@@ -569,15 +669,21 @@ Paul A Querna <paul.querna at gmail.com>
 Paul Borman <borman at google.com>
 Paul Chang <paulchang at google.com>
 Paul Hammond <paul at paulhammond.org>
+Paul Hankin <paulhankin at google.com>
 Paul Lalonde <paul.a.lalonde at gmail.com>
 Paul Marks <pmarks at google.com>
+Paul Meyer <paul.meyer at microsoft.com>
 Paul Nasrat <pnasrat at google.com>
+Paul Rosania <paul.rosania at gmail.com>
 Paul Sbarra <Sbarra.Paul at gmail.com>
 Paul Smith <paulsmith at pobox.com> <paulsmith at gmail.com>
 Paul van Brouwershaven <paul at vanbrouwershaven.com>
+Pavel Paulau <pavel.paulau at gmail.com>
 Pavel Zinovkin <pavel.zinovkin at gmail.com>
+Pawel Knap <pawelknap88 at gmail.com>
 Pawel Szczur <filemon at google.com>
 Percy Wegmann <ox.to.a.cart at gmail.com>
+Perry Abbott <perry.j.abbott at gmail.com>
 Petar Maymounkov <petarm at gmail.com>
 Peter Armitage <peter.armitage at gmail.com>
 Peter Collingbourne <pcc at google.com>
@@ -589,22 +695,27 @@ Peter Mundy <go.peter.90 at gmail.com>
 Péter Surányi <speter.go1 at gmail.com>
 Péter Szabó <pts at google.com>
 Péter Szilágyi <peterke at gmail.com>
+Peter Tseng <ptseng at squareup.com>
 Peter Waldschmidt <peter at waldschmidt.com>
 Peter Waller <peter.waller at gmail.com>
 Peter Weinberger <pjw at golang.org>
 Peter Williams <pwil3058 at gmail.com>
 Phil Pennock <pdp at golang.org>
 Philip K. Warren <pkwarren at gmail.com>
+Pierre Roullon <pierre.roullon at gmail.com>
 Pieter Droogendijk <pieter at binky.org.uk>
 Pietro Gagliardi <pietro10 at mac.com>
 Preetam Jinka <pj at preet.am>
 Quan Yong Zhai <qyzhai at gmail.com>
+Quentin Perez <qperez at ocs.online.net>
 Quoc-Viet Nguyen <afelion at gmail.com>
 Rahul Chaudhry <rahulchaudhry at chromium.org>
 Raif S. Naffah <go at naffah-raif.name>
 Rajat Goel <rajat.goel2010 at gmail.com>
+Ralph Corderoy <ralph at inputplus.co.uk>
 Raph Levien <raph at google.com>
 Raul Silvera <rsilvera at google.com>
+Reinaldo de Souza Jr <juniorz at gmail.com>
 Rémy Oudompheng <oudomphe at phare.normalesup.org> <remyoudompheng at gmail.com>
 Richard Barnes <rlb at ipv.sx>
 Richard Crowley <r at rcrowley.org>
@@ -613,15 +724,19 @@ Richard Musiol <mail at richard-musiol.de> <neelance at gmail.com>
 Rick Arnold <rickarnoldjr at gmail.com>
 Rick Hudson <rlh at golang.org>
 Risto Jaakko Saarelma <rsaarelm at gmail.com>
+Rob Earhart <earhart at google.com>
+Rob Norman <rob.norman at infinitycloud.com>
 Rob Pike <r at golang.org>
 Robert Daniel Kortschak <dan.kortschak at adelaide.edu.au>
 Robert Dinu <r at varp.se>
 Robert Figueiredo <robfig at gmail.com>
 Robert Griesemer <gri at golang.org>
 Robert Hencke <robert.hencke at gmail.com>
+Robert Iannucci <iannucci at google.com>
 Robert Obryk <robryk at gmail.com>
 Robert Sesek <rsesek at google.com>
 Robert Snedegar <roberts at google.com>
+Robert Stepanek <robert.stepanek at gmail.com>
 Robin Eklind <r.eklind.87 at gmail.com>
 Rodrigo Moraes de Oliveira <rodrigo.moraes at gmail.com>
 Rodrigo Rafael Monti Kochenburger <divoxx at gmail.com>
@@ -633,33 +748,45 @@ Ross Light <light at google.com> <rlight2 at gmail.com>
 Rowan Worth <sqweek at gmail.com>
 Rui Ueyama <ruiu at google.com>
 Russ Cox <rsc at golang.org>
+Russell Haering <russellhaering at gmail.com>
 Ryan Barrett <ryanb at google.com>
 Ryan Brown <ribrdb at google.com>
 Ryan Hitchman <hitchmanr at gmail.com>
+Ryan Lower <rpjlower at gmail.com>
 Ryan Seys <ryan at ryanseys.com>
 Ryan Slade <ryanslade at gmail.com>
 S.Çağlar Onur <caglar at 10ur.org>
+Salmān Aljammāz <s at 0x65.net>
 Sam Thorogood <thorogood at google.com> <sam.thorogood at gmail.com>
 Sameer Ajmani <sameer at golang.org> <ajmani at gmail.com>
 Sanjay Menakuru <balasanjay at gmail.com>
+Sasha Lionheart <lionhearts at google.com>
 Scott Barron <scott.barron at github.com>
 Scott Ferguson <scottwferg at gmail.com>
 Scott Lawrence <bytbox at gmail.com>
 Scott Schwartz <scotts at golang.org>
+Scott Van Woudenberg <scottvw at google.com>
 Sean Burford <sburford at google.com>
+Sean Dolphin <Sean.Dolphin at kpcompass.com>
 Sebastien Binet <seb.binet at gmail.com>
 Sébastien Paolacci <sebastien.paolacci at gmail.com>
 Sergei Skorobogatov <skorobo at rambler.ru>
 Sergey 'SnakE' Gromov <snake.scaly at gmail.com>
+Sergey Arseev <sergey.arseev at intel.com>
 Sergio Luis O. B. Correia <sergio at correia.cc>
+Seth Hoenig <seth.a.hoenig at gmail.com>
 Shane Hansen <shanemhansen at gmail.com>
+Shaozhen Ding <dsz0111 at gmail.com>
 Shawn Ledbetter <sledbetter at google.com>
 Shawn Smith <shawn.p.smith at gmail.com>
+Shawn Walker-Salas <shawn.walker at oracle.com>
 Shenghou Ma <minux at golang.org> <minux.ma at gmail.com>
 Shivakumar GN <shivakumar.gn at gmail.com>
+Shun Fan <sfan at google.com>
 Silvan Jegen <s.jegen at gmail.com>
 Simon Whitehead <chemnova at gmail.com>
 Sokolov Yura <funny.falcon at gmail.com>
+Spencer Nelson <s at spenczar.com>
 Spring Mc <heresy.mc at gmail.com>
 Srdjan Petrovic <spetrovic at google.com>
 StalkR <stalkr at stalkr.net>
@@ -670,6 +797,8 @@ Stephen Ma <stephenm at golang.org>
 Stephen McQuay <stephen at mcquay.me>
 Stephen Weinberg <stephen at q5comm.com>
 Steve McCoy <mccoyst at gmail.com>
+Steve Newman <snewman at google.com>
+Steve Phillips <elimisteve at gmail.com>
 Steve Streeting <steve at stevestreeting.com>
 Steven Elliot Harris <seharris at gmail.com>
 Steven Hartland <steven.hartland at multiplay.co.uk>
@@ -678,14 +807,21 @@ Sven Almgren <sven at tras.se>
 Szabolcs Nagy <nsz at port70.net>
 Tad Glines <tad.glines at gmail.com>
 Taj Khattra <taj.khattra at gmail.com>
+Takashi Matsuo <tmatsuo at google.com>
+Takeshi YAMANASHI <9.nashi at gmail.com>
 Tamir Duberstein <tamird at gmail.com>
 Tarmigan Casebolt <tarmigan at gmail.com>
 Taru Karttunen <taruti at taruti.net>
+Tatsuhiro Tsujikawa <tatsuhiro.t at gmail.com>
 Tetsuo Kiso <tetsuokiso9 at gmail.com>
 Thiago Fransosi Farina <thiago.farina at gmail.com> <tfarina at chromium.org>
 Thomas Alan Copeland <talan.copeland at gmail.com>
+Thomas Desrosiers <thomasdesr at gmail.com>
 Thomas Habets <habets at google.com>
 Thomas Kappler <tkappler at gmail.com>
+Thorben Krueger <thorben.krueger at gmail.com>
+Tim Cooijmans <timcooijmans at gmail.com>
+Tim Hockin <thockin at google.com>
 Timo Savola <timo.savola at gmail.com>
 Timo Truyts <alkaloid.btx at gmail.com>
 Tobias Columbus <tobias.columbus at gmail.com> <tobias.columbus at googlemail.com>
@@ -696,14 +832,19 @@ Tom Linford <tomlinford at gmail.com>
 Tom Szymanski <tgs at google.com>
 Tommy Schaefer <tommy.schaefer at teecom.com>
 Tor Andersson <tor.andersson at gmail.com>
+Tormod Erevik Lea <tormodlea at gmail.com>
+Totoro W <tw19881113 at gmail.com>
 Travis Cline <travis.cline at gmail.com>
 Trevor Strohman <trevor.strohman at gmail.com>
+Trey Tacon <ttacon at gmail.com>
 Tudor Golubenco <tudor.g at gmail.com>
-Tw <tw19881113 at gmail.com>
 Tyler Bunnell <tylerbunnell at gmail.com>
+Tyler Treat <ttreat31 at gmail.com>
 Ugorji Nwoke <ugorji at gmail.com>
 Ulf Holm Nielsen <doktor at dyregod.dk>
+Ulrich Kunitz <uli.kunitz at gmail.com>
 Uriel Mangado <uriel at berlinblue.org>
+Uttam C Pawar <uttam.c.pawar at intel.com>
 Vadim Vygonets <unixdj at gmail.com>
 Vega Garcia Luis Alfonso <vegacom at gmail.com>
 Vincent Ambo <tazjin at googlemail.com>
@@ -715,6 +856,7 @@ Vlad Krasnov <vlad at cloudflare.com>
 Vladimir Nikishenko <vova616 at gmail.com>
 Volker Dobler <dr.volker.dobler at gmail.com>
 Wei Guangjing <vcc.163 at gmail.com>
+Will Chan <willchan at google.com>
 Will Norris <willnorris at google.com>
 Willem van der Schyff <willemvds at gmail.com>
 William Chan <willchan at chromium.org>
@@ -723,15 +865,20 @@ William Orr <will at worrbase.com> <ay1244 at gmail.com>
 Xia Bin <snyh at snyh.org>
 Xing Xing <mikespook at gmail.com>
 Yan Zou <yzou at google.com>
+Yann Kerhervé <yann.kerherve at gmail.com>
+Yao Zhang <lunaria21 at gmail.com>
+Yasuharu Goto <matope.ono at gmail.com>
 Yasuhiro Matsumoto <mattn.jp at gmail.com>
+Yesudeep Mangalapilly <yesudeep at google.com>
 Yissakhar Z. Beck <yissakhar.beck at gmail.com>
 Yo-An Lin <yoanlin93 at gmail.com>
 Yongjian Xu <i3dmaster at gmail.com>
 Yoshiyuki Kanno <nekotaroh at gmail.com> <yoshiyuki.kanno at stoic.co.jp>
+Yuki Yugui Sonoda <yugui at google.com>
 Yusuke Kagiwada <block.rxckin.beats at gmail.com>
 Yuusei Kuwana <kuwana at kumama.org>
 Yuval Pavel Zholkover <paulzhol at gmail.com>
-Yves Junqueira <yves.junqueira at gmail.com>
+Yves Junqueira <yvesj at google.com> <yves.junqueira at gmail.com>
 Ziad Hatahet <hatahet at gmail.com>
 Zorion Arrizabalaga <zorionk at gmail.com>
 申习之 <bronze1man at gmail.com>
diff --git a/README.md b/README.md
index 4e6d7bd..281deec 100644
--- a/README.md
+++ b/README.md
@@ -12,14 +12,12 @@ in your web browser.
 Our canonical Git repository is located at https://go.googlesource.com/go.
 There is a mirror of the repository at https://github.com/golang/go.
 
-Please report issues here: https://golang.org/issue/new
-
 Go is the work of hundreds of contributors. We appreciate your help!
 
 To contribute, please read the contribution guidelines:
 	https://golang.org/doc/contribute.html
 
-##### Please note that we do not use pull requests.
+##### Note that we do not accept pull requests and that we use the issue tracker for bug reports and proposals only. Please ask questions on https://forum.golangbridge.org or https://groups.google.com/forum/#!forum/golang-nuts.
 
 Unless otherwise noted, the Go source files are distributed
 under the BSD-style license found in the LICENSE file.
diff --git a/VERSION b/VERSION
index b81a625..0be0043 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-go1.5.3
\ No newline at end of file
+go1.6
\ No newline at end of file
diff --git a/api/README b/api/README
index 897abc8..d3ad7c1 100644
--- a/api/README
+++ b/api/README
@@ -1,6 +1,6 @@
 Files in this directory are data for Go's API checker ("go tool api", in src/cmd/api).
 
-Each file is a list of of API features, one per line.
+Each file is a list of API features, one per line.
 
 go1.txt (and similarly named files) are frozen once a version has been
 shipped. Each file adds new lines but does not remove any.
diff --git a/api/go1.1.txt b/api/go1.1.txt
index 0b27523..81d0957 100644
--- a/api/go1.1.txt
+++ b/api/go1.1.txt
@@ -1983,13 +1983,13 @@ pkg log/syslog (openbsd-amd64-cgo), const LOG_SYSLOG = 40
 pkg log/syslog (openbsd-amd64-cgo), const LOG_USER = 8
 pkg log/syslog (openbsd-amd64-cgo), const LOG_UUCP = 64
 pkg log/syslog (openbsd-amd64-cgo), const LOG_WARNING = 4
-pkg math, const E = 271828182845904523536028747135266249775724709369995957496696763/100000000000000000000000000000000000000000000000000000000000000
-pkg math, const Ln10 = 23025850929940456840179914546843642076011014886287729760333279/10000000000000000000000000000000000000000000000000000000000000
-pkg math, const Ln2 = 693147180559945309417232121458176568075500134360255254120680009/1000000000000000000000000000000000000000000000000000000000000000
-pkg math, const Log10E = 10000000000000000000000000000000000000000000000000000000000000/23025850929940456840179914546843642076011014886287729760333279
-pkg math, const Log2E = 1000000000000000000000000000000000000000000000000000000000000000/693147180559945309417232121458176568075500134360255254120680009
-pkg math, const MaxFloat32 = 340282346638528859811704183484516925440
-pkg math, const MaxFloat64 = 179769313486231570814527423731704356798100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+pkg math, const E = 2.71828  // 271828182845904523536028747135266249775724709369995957496696763/100000000000000000000000000000000000000000000000000000000000000
+pkg math, const Ln10 = 2.30259  // 23025850929940456840179914546843642076011014886287729760333279/10000000000000000000000000000000000000000000000000000000000000
+pkg math, const Ln2 = 0.693147  // 693147180559945309417232121458176568075500134360255254120680009/1000000000000000000000000000000000000000000000000000000000000000
+pkg math, const Log10E = 0.434294  // 10000000000000000000000000000000000000000000000000000000000000/23025850929940456840179914546843642076011014886287729760333279
+pkg math, const Log2E = 1.4427  // 1000000000000000000000000000000000000000000000000000000000000000/693147180559945309417232121458176568075500134360255254120680009
+pkg math, const MaxFloat32 = 3.40282e+38  // 340282346638528859811704183484516925440
+pkg math, const MaxFloat64 = 1.79769e+308  // 179769313486231570814527423731704356798100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
 pkg math, const MaxInt16 = 32767
 pkg math, const MaxInt32 = 2147483647
 pkg math, const MaxInt64 = 9223372036854775807
@@ -2002,14 +2002,14 @@ pkg math, const MinInt16 = -32768
 pkg math, const MinInt32 = -2147483648
 pkg math, const MinInt64 = -9223372036854775808
 pkg math, const MinInt8 = -128
-pkg math, const Phi = 80901699437494742410229341718281905886015458990288143106772431/50000000000000000000000000000000000000000000000000000000000000
-pkg math, const Pi = 314159265358979323846264338327950288419716939937510582097494459/100000000000000000000000000000000000000000000000000000000000000
-pkg math, const SmallestNonzeroFloat32 = 17516230804060213386546619791123951641/12500000000000000000000000000000000000000000000000000000000000000000000000000000000
-pkg math, const SmallestNonzeroFloat64 = 4940656458412465441765687928682213723651/1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-pkg math, const Sqrt2 = 70710678118654752440084436210484903928483593768847403658833987/50000000000000000000000000000000000000000000000000000000000000
-pkg math, const SqrtE = 164872127070012814684865078781416357165377610071014801157507931/100000000000000000000000000000000000000000000000000000000000000
-pkg math, const SqrtPhi = 63600982475703448212621123086874574585780402092004812430832019/50000000000000000000000000000000000000000000000000000000000000
-pkg math, const SqrtPi = 177245385090551602729816748334114518279754945612238712821380779/100000000000000000000000000000000000000000000000000000000000000
+pkg math, const Phi = 1.61803  // 80901699437494742410229341718281905886015458990288143106772431/50000000000000000000000000000000000000000000000000000000000000
+pkg math, const Pi = 3.14159  // 314159265358979323846264338327950288419716939937510582097494459/100000000000000000000000000000000000000000000000000000000000000
+pkg math, const SmallestNonzeroFloat32 = 1.4013e-45  // 17516230804060213386546619791123951641/12500000000000000000000000000000000000000000000000000000000000000000000000000000000
+pkg math, const SmallestNonzeroFloat64 = 4.94066e-324  // 4940656458412465441765687928682213723651/1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+pkg math, const Sqrt2 = 1.41421  // 70710678118654752440084436210484903928483593768847403658833987/50000000000000000000000000000000000000000000000000000000000000
+pkg math, const SqrtE = 1.64872  // 164872127070012814684865078781416357165377610071014801157507931/100000000000000000000000000000000000000000000000000000000000000
+pkg math, const SqrtPhi = 1.27202  // 63600982475703448212621123086874574585780402092004812430832019/50000000000000000000000000000000000000000000000000000000000000
+pkg math, const SqrtPi = 1.77245  // 177245385090551602729816748334114518279754945612238712821380779/100000000000000000000000000000000000000000000000000000000000000
 pkg math/big, const MaxBase = 36
 pkg math/big, method (*Int) MarshalJSON() ([]uint8, error)
 pkg math/big, method (*Int) SetUint64(uint64) *Int
diff --git a/api/go1.6.txt b/api/go1.6.txt
new file mode 100644
index 0000000..d63efd0
--- /dev/null
+++ b/api/go1.6.txt
@@ -0,0 +1,275 @@
+pkg archive/zip, method (*ReadCloser) RegisterDecompressor(uint16, Decompressor)
+pkg archive/zip, method (*Reader) RegisterDecompressor(uint16, Decompressor)
+pkg archive/zip, method (*Writer) RegisterCompressor(uint16, Compressor)
+pkg bufio, method (*Scanner) Buffer([]uint8, int)
+pkg bufio, var ErrFinalToken error
+pkg crypto/tls, const TLS_RSA_WITH_AES_128_GCM_SHA256 = 156
+pkg crypto/tls, const TLS_RSA_WITH_AES_128_GCM_SHA256 uint16
+pkg crypto/tls, const TLS_RSA_WITH_AES_256_GCM_SHA384 = 157
+pkg crypto/tls, const TLS_RSA_WITH_AES_256_GCM_SHA384 uint16
+pkg crypto/tls, method (RecordHeaderError) Error() string
+pkg crypto/tls, type RecordHeaderError struct
+pkg crypto/tls, type RecordHeaderError struct, Msg string
+pkg crypto/tls, type RecordHeaderError struct, RecordHeader [5]uint8
+pkg crypto/x509, method (InsecureAlgorithmError) Error() string
+pkg crypto/x509, method (SignatureAlgorithm) String() string
+pkg crypto/x509, type InsecureAlgorithmError int
+pkg database/sql, method (*DB) SetConnMaxLifetime(time.Duration)
+pkg debug/dwarf, const ClassUnknown = 0
+pkg debug/dwarf, const ClassUnknown Class
+pkg debug/elf, const COMPRESS_HIOS = 1879048191
+pkg debug/elf, const COMPRESS_HIOS CompressionType
+pkg debug/elf, const COMPRESS_HIPROC = 2147483647
+pkg debug/elf, const COMPRESS_HIPROC CompressionType
+pkg debug/elf, const COMPRESS_LOOS = 1610612736
+pkg debug/elf, const COMPRESS_LOOS CompressionType
+pkg debug/elf, const COMPRESS_LOPROC = 1879048192
+pkg debug/elf, const COMPRESS_LOPROC CompressionType
+pkg debug/elf, const COMPRESS_ZLIB = 1
+pkg debug/elf, const COMPRESS_ZLIB CompressionType
+pkg debug/elf, const R_MIPS_16 = 1
+pkg debug/elf, const R_MIPS_16 R_MIPS
+pkg debug/elf, const R_MIPS_26 = 4
+pkg debug/elf, const R_MIPS_26 R_MIPS
+pkg debug/elf, const R_MIPS_32 = 2
+pkg debug/elf, const R_MIPS_32 R_MIPS
+pkg debug/elf, const R_MIPS_64 = 18
+pkg debug/elf, const R_MIPS_64 R_MIPS
+pkg debug/elf, const R_MIPS_ADD_IMMEDIATE = 34
+pkg debug/elf, const R_MIPS_ADD_IMMEDIATE R_MIPS
+pkg debug/elf, const R_MIPS_CALL16 = 11
+pkg debug/elf, const R_MIPS_CALL16 R_MIPS
+pkg debug/elf, const R_MIPS_CALL_HI16 = 30
+pkg debug/elf, const R_MIPS_CALL_HI16 R_MIPS
+pkg debug/elf, const R_MIPS_CALL_LO16 = 31
+pkg debug/elf, const R_MIPS_CALL_LO16 R_MIPS
+pkg debug/elf, const R_MIPS_DELETE = 27
+pkg debug/elf, const R_MIPS_DELETE R_MIPS
+pkg debug/elf, const R_MIPS_GOT16 = 9
+pkg debug/elf, const R_MIPS_GOT16 R_MIPS
+pkg debug/elf, const R_MIPS_GOT_DISP = 19
+pkg debug/elf, const R_MIPS_GOT_DISP R_MIPS
+pkg debug/elf, const R_MIPS_GOT_HI16 = 22
+pkg debug/elf, const R_MIPS_GOT_HI16 R_MIPS
+pkg debug/elf, const R_MIPS_GOT_LO16 = 23
+pkg debug/elf, const R_MIPS_GOT_LO16 R_MIPS
+pkg debug/elf, const R_MIPS_GOT_OFST = 21
+pkg debug/elf, const R_MIPS_GOT_OFST R_MIPS
+pkg debug/elf, const R_MIPS_GOT_PAGE = 20
+pkg debug/elf, const R_MIPS_GOT_PAGE R_MIPS
+pkg debug/elf, const R_MIPS_GPREL16 = 7
+pkg debug/elf, const R_MIPS_GPREL16 R_MIPS
+pkg debug/elf, const R_MIPS_GPREL32 = 12
+pkg debug/elf, const R_MIPS_GPREL32 R_MIPS
+pkg debug/elf, const R_MIPS_HI16 = 5
+pkg debug/elf, const R_MIPS_HI16 R_MIPS
+pkg debug/elf, const R_MIPS_HIGHER = 28
+pkg debug/elf, const R_MIPS_HIGHER R_MIPS
+pkg debug/elf, const R_MIPS_HIGHEST = 29
+pkg debug/elf, const R_MIPS_HIGHEST R_MIPS
+pkg debug/elf, const R_MIPS_INSERT_A = 25
+pkg debug/elf, const R_MIPS_INSERT_A R_MIPS
+pkg debug/elf, const R_MIPS_INSERT_B = 26
+pkg debug/elf, const R_MIPS_INSERT_B R_MIPS
+pkg debug/elf, const R_MIPS_JALR = 37
+pkg debug/elf, const R_MIPS_JALR R_MIPS
+pkg debug/elf, const R_MIPS_LITERAL = 8
+pkg debug/elf, const R_MIPS_LITERAL R_MIPS
+pkg debug/elf, const R_MIPS_LO16 = 6
+pkg debug/elf, const R_MIPS_LO16 R_MIPS
+pkg debug/elf, const R_MIPS_NONE = 0
+pkg debug/elf, const R_MIPS_NONE R_MIPS
+pkg debug/elf, const R_MIPS_PC16 = 10
+pkg debug/elf, const R_MIPS_PC16 R_MIPS
+pkg debug/elf, const R_MIPS_PJUMP = 35
+pkg debug/elf, const R_MIPS_PJUMP R_MIPS
+pkg debug/elf, const R_MIPS_REL16 = 33
+pkg debug/elf, const R_MIPS_REL16 R_MIPS
+pkg debug/elf, const R_MIPS_REL32 = 3
+pkg debug/elf, const R_MIPS_REL32 R_MIPS
+pkg debug/elf, const R_MIPS_RELGOT = 36
+pkg debug/elf, const R_MIPS_RELGOT R_MIPS
+pkg debug/elf, const R_MIPS_SCN_DISP = 32
+pkg debug/elf, const R_MIPS_SCN_DISP R_MIPS
+pkg debug/elf, const R_MIPS_SHIFT5 = 16
+pkg debug/elf, const R_MIPS_SHIFT5 R_MIPS
+pkg debug/elf, const R_MIPS_SHIFT6 = 17
+pkg debug/elf, const R_MIPS_SHIFT6 R_MIPS
+pkg debug/elf, const R_MIPS_SUB = 24
+pkg debug/elf, const R_MIPS_SUB R_MIPS
+pkg debug/elf, const R_MIPS_TLS_DTPMOD32 = 38
+pkg debug/elf, const R_MIPS_TLS_DTPMOD32 R_MIPS
+pkg debug/elf, const R_MIPS_TLS_DTPMOD64 = 40
+pkg debug/elf, const R_MIPS_TLS_DTPMOD64 R_MIPS
+pkg debug/elf, const R_MIPS_TLS_DTPREL32 = 39
+pkg debug/elf, const R_MIPS_TLS_DTPREL32 R_MIPS
+pkg debug/elf, const R_MIPS_TLS_DTPREL64 = 41
+pkg debug/elf, const R_MIPS_TLS_DTPREL64 R_MIPS
+pkg debug/elf, const R_MIPS_TLS_DTPREL_HI16 = 44
+pkg debug/elf, const R_MIPS_TLS_DTPREL_HI16 R_MIPS
+pkg debug/elf, const R_MIPS_TLS_DTPREL_LO16 = 45
+pkg debug/elf, const R_MIPS_TLS_DTPREL_LO16 R_MIPS
+pkg debug/elf, const R_MIPS_TLS_GD = 42
+pkg debug/elf, const R_MIPS_TLS_GD R_MIPS
+pkg debug/elf, const R_MIPS_TLS_GOTTPREL = 46
+pkg debug/elf, const R_MIPS_TLS_GOTTPREL R_MIPS
+pkg debug/elf, const R_MIPS_TLS_LDM = 43
+pkg debug/elf, const R_MIPS_TLS_LDM R_MIPS
+pkg debug/elf, const R_MIPS_TLS_TPREL32 = 47
+pkg debug/elf, const R_MIPS_TLS_TPREL32 R_MIPS
+pkg debug/elf, const R_MIPS_TLS_TPREL64 = 48
+pkg debug/elf, const R_MIPS_TLS_TPREL64 R_MIPS
+pkg debug/elf, const R_MIPS_TLS_TPREL_HI16 = 49
+pkg debug/elf, const R_MIPS_TLS_TPREL_HI16 R_MIPS
+pkg debug/elf, const R_MIPS_TLS_TPREL_LO16 = 50
+pkg debug/elf, const R_MIPS_TLS_TPREL_LO16 R_MIPS
+pkg debug/elf, const SHF_COMPRESSED = 2048
+pkg debug/elf, const SHF_COMPRESSED SectionFlag
+pkg debug/elf, method (CompressionType) GoString() string
+pkg debug/elf, method (CompressionType) String() string
+pkg debug/elf, method (R_MIPS) GoString() string
+pkg debug/elf, method (R_MIPS) String() string
+pkg debug/elf, type Chdr32 struct
+pkg debug/elf, type Chdr32 struct, Addralign uint32
+pkg debug/elf, type Chdr32 struct, Size uint32
+pkg debug/elf, type Chdr32 struct, Type uint32
+pkg debug/elf, type Chdr64 struct
+pkg debug/elf, type Chdr64 struct, Addralign uint64
+pkg debug/elf, type Chdr64 struct, Size uint64
+pkg debug/elf, type Chdr64 struct, Type uint32
+pkg debug/elf, type CompressionType int
+pkg debug/elf, type R_MIPS int
+pkg debug/elf, type SectionHeader struct, FileSize uint64
+pkg encoding/asn1, const ClassApplication = 1
+pkg encoding/asn1, const ClassApplication ideal-int
+pkg encoding/asn1, const ClassContextSpecific = 2
+pkg encoding/asn1, const ClassContextSpecific ideal-int
+pkg encoding/asn1, const ClassPrivate = 3
+pkg encoding/asn1, const ClassPrivate ideal-int
+pkg encoding/asn1, const ClassUniversal = 0
+pkg encoding/asn1, const ClassUniversal ideal-int
+pkg encoding/asn1, const TagBitString = 3
+pkg encoding/asn1, const TagBitString ideal-int
+pkg encoding/asn1, const TagBoolean = 1
+pkg encoding/asn1, const TagBoolean ideal-int
+pkg encoding/asn1, const TagEnum = 10
+pkg encoding/asn1, const TagEnum ideal-int
+pkg encoding/asn1, const TagGeneralString = 27
+pkg encoding/asn1, const TagGeneralString ideal-int
+pkg encoding/asn1, const TagGeneralizedTime = 24
+pkg encoding/asn1, const TagGeneralizedTime ideal-int
+pkg encoding/asn1, const TagIA5String = 22
+pkg encoding/asn1, const TagIA5String ideal-int
+pkg encoding/asn1, const TagInteger = 2
+pkg encoding/asn1, const TagInteger ideal-int
+pkg encoding/asn1, const TagOID = 6
+pkg encoding/asn1, const TagOID ideal-int
+pkg encoding/asn1, const TagOctetString = 4
+pkg encoding/asn1, const TagOctetString ideal-int
+pkg encoding/asn1, const TagPrintableString = 19
+pkg encoding/asn1, const TagPrintableString ideal-int
+pkg encoding/asn1, const TagSequence = 16
+pkg encoding/asn1, const TagSequence ideal-int
+pkg encoding/asn1, const TagSet = 17
+pkg encoding/asn1, const TagSet ideal-int
+pkg encoding/asn1, const TagT61String = 20
+pkg encoding/asn1, const TagT61String ideal-int
+pkg encoding/asn1, const TagUTCTime = 23
+pkg encoding/asn1, const TagUTCTime ideal-int
+pkg encoding/asn1, const TagUTF8String = 12
+pkg encoding/asn1, const TagUTF8String ideal-int
+pkg go/build, const IgnoreVendor = 8
+pkg go/build, const IgnoreVendor ImportMode
+pkg go/build, type Package struct, InvalidGoFiles []string
+pkg go/constant, func ToComplex(Value) Value
+pkg go/constant, func ToFloat(Value) Value
+pkg go/constant, func ToInt(Value) Value
+pkg go/constant, type Value interface, ExactString() string
+pkg go/types, method (*Package) SetName(string)
+pkg go/types, type ImportMode int
+pkg go/types, type ImporterFrom interface { Import, ImportFrom }
+pkg go/types, type ImporterFrom interface, Import(string) (*Package, error)
+pkg go/types, type ImporterFrom interface, ImportFrom(string, string, ImportMode) (*Package, error)
+pkg html/template, func IsTrue(interface{}) (bool, bool)
+pkg html/template, method (*Template) DefinedTemplates() string
+pkg image, func NewNYCbCrA(Rectangle, YCbCrSubsampleRatio) *NYCbCrA
+pkg image, method (*NYCbCrA) AOffset(int, int) int
+pkg image, method (*NYCbCrA) At(int, int) color.Color
+pkg image, method (*NYCbCrA) Bounds() Rectangle
+pkg image, method (*NYCbCrA) COffset(int, int) int
+pkg image, method (*NYCbCrA) ColorModel() color.Model
+pkg image, method (*NYCbCrA) NYCbCrAAt(int, int) color.NYCbCrA
+pkg image, method (*NYCbCrA) Opaque() bool
+pkg image, method (*NYCbCrA) SubImage(Rectangle) Image
+pkg image, method (*NYCbCrA) YCbCrAt(int, int) color.YCbCr
+pkg image, method (*NYCbCrA) YOffset(int, int) int
+pkg image, type NYCbCrA struct
+pkg image, type NYCbCrA struct, A []uint8
+pkg image, type NYCbCrA struct, AStride int
+pkg image, type NYCbCrA struct, embedded YCbCr
+pkg image/color, method (NYCbCrA) RGBA() (uint32, uint32, uint32, uint32)
+pkg image/color, type NYCbCrA struct
+pkg image/color, type NYCbCrA struct, A uint8
+pkg image/color, type NYCbCrA struct, embedded YCbCr
+pkg image/color, var NYCbCrAModel Model
+pkg math/big, method (*Float) MarshalText() ([]uint8, error)
+pkg math/big, method (*Float) UnmarshalText([]uint8) error
+pkg math/big, method (*Int) Append([]uint8, int) []uint8
+pkg math/big, method (*Int) Text(int) string
+pkg math/rand, func Read([]uint8) (int, error)
+pkg math/rand, method (*Rand) Read([]uint8) (int, error)
+pkg net, type DNSError struct, IsTemporary bool
+pkg net, type Dialer struct, Cancel <-chan struct
+pkg net/http, const MethodConnect = "CONNECT"
+pkg net/http, const MethodConnect ideal-string
+pkg net/http, const MethodDelete = "DELETE"
+pkg net/http, const MethodDelete ideal-string
+pkg net/http, const MethodGet = "GET"
+pkg net/http, const MethodGet ideal-string
+pkg net/http, const MethodHead = "HEAD"
+pkg net/http, const MethodHead ideal-string
+pkg net/http, const MethodOptions = "OPTIONS"
+pkg net/http, const MethodOptions ideal-string
+pkg net/http, const MethodPatch = "PATCH"
+pkg net/http, const MethodPatch ideal-string
+pkg net/http, const MethodPost = "POST"
+pkg net/http, const MethodPost ideal-string
+pkg net/http, const MethodPut = "PUT"
+pkg net/http, const MethodPut ideal-string
+pkg net/http, const MethodTrace = "TRACE"
+pkg net/http, const MethodTrace ideal-string
+pkg net/http, const StatusNetworkAuthenticationRequired = 511
+pkg net/http, const StatusNetworkAuthenticationRequired ideal-int
+pkg net/http, const StatusPreconditionRequired = 428
+pkg net/http, const StatusPreconditionRequired ideal-int
+pkg net/http, const StatusRequestHeaderFieldsTooLarge = 431
+pkg net/http, const StatusRequestHeaderFieldsTooLarge ideal-int
+pkg net/http, const StatusTooManyRequests = 429
+pkg net/http, const StatusTooManyRequests ideal-int
+pkg net/http, const StatusUnavailableForLegalReasons = 451
+pkg net/http, const StatusUnavailableForLegalReasons ideal-int
+pkg net/http, type Transport struct, ExpectContinueTimeout time.Duration
+pkg net/http, type Transport struct, TLSNextProto map[string]func(string, *tls.Conn) RoundTripper
+pkg net/http, var ErrSkipAltProtocol error
+pkg net/http/httptest, method (*ResponseRecorder) WriteString(string) (int, error)
+pkg net/http/httputil, type BufferPool interface { Get, Put }
+pkg net/http/httputil, type BufferPool interface, Get() []uint8
+pkg net/http/httputil, type BufferPool interface, Put([]uint8)
+pkg net/http/httputil, type ReverseProxy struct, BufferPool BufferPool
+pkg net/url, method (*Error) Temporary() bool
+pkg net/url, method (*Error) Timeout() bool
+pkg net/url, method (InvalidHostError) Error() string
+pkg net/url, type InvalidHostError string
+pkg os/exec, type ExitError struct, Stderr []uint8
+pkg regexp, method (*Regexp) Copy() *Regexp
+pkg runtime/debug, func SetTraceback(string)
+pkg strconv, func AppendQuoteRuneToGraphic([]uint8, int32) []uint8
+pkg strconv, func AppendQuoteToGraphic([]uint8, string) []uint8
+pkg strconv, func IsGraphic(int32) bool
+pkg strconv, func QuoteRuneToGraphic(int32) string
+pkg strconv, func QuoteToGraphic(string) string
+pkg text/template, func IsTrue(interface{}) (bool, bool)
+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/doc/asm.html b/doc/asm.html
index c992e14..392af17 100644
--- a/doc/asm.html
+++ b/doc/asm.html
@@ -12,7 +12,7 @@ The document is not comprehensive.
 
 <p>
 The assembler is based on the input style of the Plan 9 assemblers, which is documented in detail
-<a href="http://plan9.bell-labs.com/sys/doc/asm.html">elsewhere</a>.
+<a href="https://9p.io/sys/doc/asm.html">elsewhere</a>.
 If you plan to write assembly language, you should read that document although much of it is Plan 9-specific.
 The current document provides a summary of the syntax and the differences with
 what is explained in that document, and
@@ -23,7 +23,7 @@ describes the peculiarities that apply when writing assembly code to interact wi
 The most important thing to know about Go's assembler is that it is not a direct representation of the underlying machine.
 Some of the details map precisely to the machine, but some do not.
 This is because the compiler suite (see
-<a href="http://plan9.bell-labs.com/sys/doc/compiler.html">this description</a>)
+<a href="https://9p.io/sys/doc/compiler.html">this description</a>)
 needs no assembler pass in the usual pipeline.
 Instead, the compiler operates on a kind of semi-abstract instruction set,
 and instruction selection occurs partly after code generation.
@@ -176,7 +176,7 @@ This form is used to name global functions and data.
 Adding <code><></code> to the name, as in <span style="white-space: nowrap"><code>foo<>(SB)</code></span>, makes the name
 visible only in the current source file, like a top-level <code>static</code> declaration in a C file.
 Adding an offset to the name refers to that offset from the symbol's address, so
-<code>a+4(SB)</code> is four bytes past the start of <code>foo</code>.
+<code>foo+4(SB)</code> is four bytes past the start of <code>foo</code>.
 </p>
 
 <p>
@@ -510,6 +510,13 @@ the stack pointer may change during any function call:
 even pointers to stack data must not be kept in local variables.
 </p>
 
+<p>
+Assembly functions should always be given Go prototypes,
+both to provide pointer information for the arguments and results
+and to let <code>go</code> <code>vet</code> check that
+the offsets being used to access them are correct.
+</p>
+
 <h2 id="architectures">Architecture-specific details</h2>
 
 <p>
@@ -614,6 +621,15 @@ These modes accept only 1, 2, 4, and 8 as scale factors.
 
 </ul>
 
+<p>
+When using the compiler and assembler's
+<code>-dynlink</code> or <code>-shared</code> modes,
+any load or store of a fixed memory location such as a global variable
+must be assumed to overwrite <code>CX</code>.
+Therefore, to be safe for use with these modes,
+assembly sources should typically avoid CX except between memory references.
+</p>
+
 <h3 id="amd64">64-bit Intel 386 (a.k.a. amd64)</h3>
 
 <p>
diff --git a/doc/code.html b/doc/code.html
index 8cbfba0..fdca404 100644
--- a/doc/code.html
+++ b/doc/code.html
@@ -24,21 +24,31 @@ A similar explanation is available as a
 
 <h2 id="Organization">Code organization</h2>
 
-<h3 id="Workspaces">Workspaces</h3>
+<h3 id="Overview">Overview</h3>
+
+<ul>
+	<li>Go programmers typically keep all their Go code in a single <i>workspace</i>.</li>
+	<li>A workspace contains many version control <i>repositories</i>
+	    (managed by Git, for example).</li>
+	<li>Each repository contains one or more <i>packages</i>.</li>
+	<li>Each package consists of one or more Go source files in a single directory.</li>
+	<li>The path to a package's directory determines its <i>import path</i>.</li>
+</ul>
 
 <p>
-The <code>go</code> tool is designed to work with open source code maintained
-in public repositories. Although you don't need to publish your code, the model
-for how the environment is set up works the same whether you do or not.
+Note that this differs from other programming environments in which every
+project has a separate workspace and workspaces are closely tied to version
+control repositories.
 </p>
 
+<h3 id="Workspaces">Workspaces</h3>
+
 <p>
-Go code must be kept inside a <i>workspace</i>.
 A workspace is a directory hierarchy with three directories at its root:
 </p>
 
 <ul>
-<li><code>src</code> contains Go source files organized into packages (one package per directory),
+<li><code>src</code> contains Go source files,
 <li><code>pkg</code> contains package objects, and
 <li><code>bin</code> contains executable commands.
 </ul>
@@ -77,16 +87,25 @@ src/
 	stringutil/
 	    reverse.go             # package source
 	    reverse_test.go        # test source
+    <a href="https://golang.org/x/image/">golang.org/x/image/</a>
+        .git/                      # Git repository metadata
+	bmp/
+	    reader.go              # package source
+	    writer.go              # package source
+    ... (many more repositories and packages omitted) ...
 </pre>
 
 <p>
-This workspace contains one repository (<code>example</code>)
-comprising two commands (<code>hello</code> and <code>outyet</code>)
-and one library (<code>stringutil</code>).
+The tree above shows a workspace containing two repositories
+(<code>example</code> and <code>image</code>).
+The <code>example</code> repository contains two commands (<code>hello</code>
+and <code>outyet</code>) and one library (<code>stringutil</code>).
+The <code>image</code> repository contains the <code>bmp</code> package
+and <a href="https://godoc.org/golang.org/x/image">several others</a>.
 </p>
 
 <p>
-A typical workspace would contain many source repositories containing many
+A typical workspace contains many source repositories containing many
 packages and commands. Most Go programmers keep <i>all</i> their Go source code
 and dependencies in a single workspace.
 </p>
@@ -133,10 +152,16 @@ please see
 <a href="/cmd/go/#hdr-GOPATH_environment_variable"><code>go help gopath</code></a>
 </p>
 
-<h3 id="PackagePaths">Package paths</h3>
+<h3 id="ImportPaths">Import paths</h3>
+
+<p>
+An <i>import path</i> is a string that uniquely identifies a package.
+A package's import path corresponds to its location inside a workspace
+or in a remote repository (explained below).
+</p>
 
 <p>
-The packages from the standard library are given short paths such as
+The packages from the standard library are given short import paths such as
 <code>"fmt"</code> and <code>"net/http"</code>.
 For your own packages, you must choose a base path that is unlikely to
 collide with future additions to the standard library or other external
diff --git a/doc/codewalk/codewalk.xml b/doc/codewalk/codewalk.xml
index 3496db7..34e6e91 100644
--- a/doc/codewalk/codewalk.xml
+++ b/doc/codewalk/codewalk.xml
@@ -91,7 +91,7 @@
 
 	The full address syntax is summarized in this table
 	(an excerpt of Table II from
-	<a href="http://plan9.bell-labs.com/sys/doc/sam/sam.html">The text editor <code>sam</code></a>):
+	<a href="https://9p.io/sys/doc/sam/sam.html">The text editor <code>sam</code></a>):
 	<br/><br/>
 
 	<table>
diff --git a/doc/conduct.html b/doc/conduct.html
index 73b68f0..ce824a1 100644
--- a/doc/conduct.html
+++ b/doc/conduct.html
@@ -159,7 +159,7 @@ values”.
 If you conduct yourself in a way that is explicitly forbidden by the CoC,
 you will be warned and asked to stop.
 If you do not stop, you will be removed from our community spaces temporarily.
-Repeated, wilful breaches of the CoC will result in a permanent ban.
+Repeated, willful breaches of the CoC will result in a permanent ban.
 </p>
 
 <p>
diff --git a/doc/contrib.html b/doc/contrib.html
index 66e5af9..31bb0a4 100644
--- a/doc/contrib.html
+++ b/doc/contrib.html
@@ -67,9 +67,6 @@ href="https://groups.google.com/group/golang-nuts">golang-nuts</a>.</p>
 <h3 id="golang-checkins"><a href="https://groups.google.com/group/golang-checkins">Checkins Mailing List</a></h3>
 <p>A mailing list that receives a message summarizing each checkin to the Go repository.</p>
 
-<h3 id="golang-bugs"><a href="https://groups.google.com/group/golang-bugs">Bugs Mailing List</a></h3>
-<p>A mailing list that receives each update to the Go <a href="//golang.org/issue">issue tracker</a>.</p>
-
 <h3 id="build_status"><a href="//build.golang.org/">Build Status</a></h3>
 <p>View the status of Go builds across the supported operating
 systems and architectures.</p>
diff --git a/doc/contribute.html b/doc/contribute.html
index 45ed8f1..4619c81 100644
--- a/doc/contribute.html
+++ b/doc/contribute.html
@@ -81,7 +81,7 @@ discussed below, helps manage the code review process through a Google-hosted
 system called <a href="https://code.google.com/p/gerrit/">Gerrit</a>.
 </p>
 
-<h3>Set up authentication for code review</h3>
+<h3 id="auth">Set up authentication for code review</h3>
 
 <p>
 Gerrit uses Google Accounts for authentication. If you don't have
@@ -120,7 +120,7 @@ Your secret authentication token is now in a <code>.gitcookie</code> file
 and Git is configured to use this file.
 </p>
 
-<h3>Register with Gerrit</h3>
+<h3 id="gerrit">Register with Gerrit</h3>
 
 <p>
 Now that you have your authentication token,
@@ -132,7 +132,7 @@ to Google Accounts. Sign in using the same Google Account you used above.
 That is all that is required.
 </p>
 
-<h3>Contributor License Agreement</h3>
+<h3 id="cla">Contributor License Agreement</h3>
 
 <p>Gerrit serves as the gatekeeper and uses your e-mail address as the key.
 To send your first change to the Go project from a given address,
@@ -167,7 +167,14 @@ you can create one by clicking "New Contributor Agreement" and following the ste
 This rigmarole only needs to be done for your first submission for each email address.
 </p>
 
-<h3>Install the git-codereview command</h3>
+<p>
+If the copyright holder for the code you are submitting changes—for example,
+if you start contributing code on behalf of a new company—please send email
+to let us know, so that we can make sure an appropriate agreement is completed
+and update the <code>AUTHORS</code> file.
+</p>
+
+<h3 id="git-codereview">Install the git-codereview command</h3>
 
 <p>
 Now install the <code>git-codereview</code> command by running,
@@ -191,9 +198,13 @@ prints help text, not an error.
 </p>
 
 <p>
-Note to Git aficionados: The <code>git-codereview</code> command is not required to
+<b>Note to Git aficionados:</b>
+The <code>git-codereview</code> command is not required to
 upload and manage Gerrit code reviews. For those who prefer plain Git, the text
-below gives the Git equivalent of each git-codereview command. If you do use plain
+below gives the Git equivalent of each git-codereview command.
+</p>
+
+<p>If you do use plain
 Git, note that you still need the commit hooks that the git-codereview command
 configures; those hooks add a Gerrit <code>Change-Id</code> line to the commit
 message and check that all Go source files have been formatted with gofmt. Even
@@ -201,7 +212,13 @@ if you intend to use plain Git for daily work, install the hooks in a new Git
 checkout by running <code>git-codereview</code> <code>hooks</code>.
 </p>
 
-<h3>Set up git aliases</h3>
+<p>
+The workflow described below assumes a single change per branch.
+It is also possible to prepare a sequence of (usually related) changes in a single branch.
+See the <a href="https://golang.org/x/review/git-codereview">git-codereview documentation</a> for details.
+</p>
+
+<h3 id="git-config">Set up git aliases</h3>
 
 <p>
 The <code>git-codereview</code> command can be run directly from the shell
@@ -243,7 +260,7 @@ To install them, copy this text into your Git configuration file
 	sync = codereview sync
 </pre>
 
-<h3>Understanding the git-codereview command</h3>
+<h3 id="help">Understanding the git-codereview command</h3>
 
 <p>After installing the <code>git-codereview</code> command, you can run</p>
 
@@ -256,7 +273,7 @@ to learn more about its commands.
 You can also read the <a href="https://godoc.org/golang.org/x/review/git-codereview">command documentation</a>.
 </p>
 
-<h3>Switch to the master branch</h3>
+<h3 id="master">Switch to the master branch</h3>
 
 <p>
 Most Go installations use a release branch, but new changes should
@@ -276,7 +293,7 @@ $ git sync
 <code>git</code> <code>pull</code> <code>-r</code>.)
 </p>
 
-<h3>Make a change</h3>
+<h3 id="change">Make a change</h3>
 
 <p>
 The entire checked-out tree is writable.
@@ -405,7 +422,7 @@ Do not edit or delete it.
 runs <code>git</code> <code>commit</code> <code>--amend</code>.)
 </p>
 
-<h3>Mail the change for review</h3>
+<h3 id="mail">Mail the change for review</h3>
 
 <p>
 Once the change is ready, mail it out for review:
@@ -455,7 +472,7 @@ remote: New Changes:
 remote:   https://go-review.googlesource.com/99999 math: improved Sin, Cos and Tan precision for very large arguments
 </pre>
 
-<h3>Reviewing code</h3>
+<h3 id="review">Reviewing code</h3>
 
 <p>
 Running <code>git</code> <code>mail</code> will send an email to you and the
@@ -467,7 +484,7 @@ You must reply through the web interface.
 (Unlike with the old Rietveld review system, replying by mail has no effect.)
 </p>
 
-<h3>Revise and upload</h3>
+<h3 id="revise">Revise and upload</h3>
 
 <p>
 You must respond to review comments through the web interface.
@@ -494,7 +511,7 @@ You can see a list of your pending changes by running <code>git</code>
 <code>change</code> <code><i><branch></i></code>.
 </p>
 
-<h3>Synchronize your client</h3>
+<h3 id="sync">Synchronize your client</h3>
 
 <p>
 While you were working, others might have submitted changes to the repository.
@@ -577,7 +594,7 @@ might turn up:
 <<<<<<< HEAD
 	if arg < 1e9 {
 =======
-	if arg &lh; 1e10 {
+	if arg < 1e10 {
 >>>>>>> mcgillicutty
 		largeReduce(arg)
 </pre>
@@ -612,7 +629,7 @@ Then run <code>git</code> <code>rebase</code> <code>--continue</code> to
 restore the change commit.
 </p>
 
-<h3>Reviewing code by others</h3>
+<h3 id="download">Reviewing code by others</h3>
 
 <p>
 You can import a change proposed by someone else into your local Git repository.
@@ -629,7 +646,7 @@ $ git fetch https://go.googlesource.com/review refs/changes/21/1221/1 &&
 To revert, change back to the branch you were working in.
 </p>
 
-<h3>Submit the change after the review</h3>
+<h3 id="submit">Submit the change after the review</h3>
 
 <p>
 After the code has been <code>LGTM</code>'ed, an approver may
@@ -648,7 +665,7 @@ the commit hashes in the repository will be changed by
 the submit operation.
 </p>
 
-<h3>More information</h3>
+<h3 id="more">More information</h3>
 
 <p>
 In addition to the information here, the Go community maintains a <a href="https://golang.org/wiki/CodeReview">CodeReview</a> wiki page.
@@ -674,7 +691,7 @@ These files will be periodically updated based on the commit logs.
 <p>Code that you contribute should use the standard copyright header:</p>
 
 <pre>
-// Copyright 2015 The Go Authors. All rights reserved.
+// 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.
 </pre>
diff --git a/doc/debugging_with_gdb.html b/doc/debugging_with_gdb.html
index 8368164..52a6e76 100644
--- a/doc/debugging_with_gdb.html
+++ b/doc/debugging_with_gdb.html
@@ -124,7 +124,7 @@ href="/src/runtime/runtime-gdb.py">src/runtime/runtime-gdb.py</a> in
 the Go source distribution. It depends on some special magic types
 (<code>hash<T,U></code>) and variables (<code>runtime.m</code> and
 <code>runtime.g</code>) that the linker
-(<a href="/src/cmd/ld/dwarf.c">src/cmd/ld/dwarf.c</a>) ensures are described in
+(<a href="/src/cmd/link/internal/ld/dwarf.go">src/cmd/link/internal/ld/dwarf.go</a>) ensures are described in
 the DWARF code.
 </p>
 
diff --git a/doc/devel/release.html b/doc/devel/release.html
index e629e5d..ad060a8 100644
--- a/doc/devel/release.html
+++ b/doc/devel/release.html
@@ -12,6 +12,24 @@ git pull
 git checkout <i>release-branch</i>
 </pre>
 
+<h2 id="policy">Release Policy</h2>
+
+<p>
+Each major Go release obsoletes and ends support for the previous one.
+For example, if Go 1.5 has been released, then it is the current release
+and Go 1.4 and earlier are no longer supported.
+We fix critical problems in the current release as needed by issuing minor revisions
+(for example, Go 1.5.1, Go 1.5.2, and so on).
+</p>
+
+<p>
+As a special case, we issue minor revisions for critical security problems
+in both the current release and the previous release.
+For example, if Go 1.5 is the current release then we will issue minor revisions
+to fix critical security problems in both Go 1.4 and Go 1.5 as they arise.
+See the <a href="/security">security policy</a> for more details.
+</p>
+
 <h2 id="go1.5">go1.5 (released 2015/08/19)</h2>
 
 <p>
diff --git a/doc/go1.5.html b/doc/go1.5.html
index 693a185..2c77cf4 100644
--- a/doc/go1.5.html
+++ b/doc/go1.5.html
@@ -547,7 +547,7 @@ This acts as a custom replacement for <code>go tool</code>.
 The <code>test</code> subcommand now has a <code>-count</code>
 flag to specify how many times to run each test and benchmark.
 The <a href="/pkg/testing/"><code>testing</code></a> package
-does the work here, through by the <code>-test.count</code> flag.
+does the work here, through the <code>-test.count</code> flag.
 </li>
 
 <li>
diff --git a/doc/go1.6.html b/doc/go1.6.html
new file mode 100644
index 0000000..17c3536
--- /dev/null
+++ b/doc/go1.6.html
@@ -0,0 +1,925 @@
+<!--{
+	"Title": "Go 1.6 Release Notes",
+	"Path":  "/doc/go1.6",
+	"Template": true
+}-->
+
+<!--
+Edit .,s;^PKG:([a-z][A-Za-z0-9_/]+);<a href="/pkg/\1/"><code>\1</code></a>;g
+Edit .,s;^([a-z][A-Za-z0-9_/]+)\.([A-Z][A-Za-z0-9_]+\.)?([A-Z][A-Za-z0-9_]+)([ .',]|$);<a href="/pkg/\1/#\2\3"><code>\3</code></a>\4;g
+-->
+
+<style>
+ul li { margin: 0.5em 0; }
+</style>
+
+<h2 id="introduction">Introduction to Go 1.6</h2>
+
+<p>
+The latest Go release, version 1.6, arrives six months after 1.5.
+Most of its changes are in the implementation of the language, runtime, and libraries.
+There are no changes to the language specification.
+As always, the release maintains the Go 1 <a href="/doc/go1compat.html">promise of compatibility</a>.
+We expect almost all Go programs to continue to compile and run as before.
+</p>
+
+<p>
+The release adds new ports to <a href="#ports">Linux on 64-bit MIPS and Android on 32-bit x86</a>;
+defined and enforced <a href="#cgo">rules for sharing Go pointers with C</a>;
+transparent, automatic <a href="#http2">support for HTTP/2</a>;
+and a new mechanism for <a href="#template">template reuse</a>.
+</p>
+
+<h2 id="language">Changes to the language</h2>
+
+<p>
+There are no language changes in this release.
+</p>
+
+<h2 id="ports">Ports</h2>
+
+<p>
+Go 1.6 adds experimental ports to
+Linux on 64-bit MIPS (<code>linux/mips64</code> and <code>linux/mips64le</code>).
+These ports support <code>cgo</code> but only with internal linking.
+</p>
+
+<p>
+Go 1.6 also adds an experimental port to Android on 32-bit x86 (<code>android/386</code>).
+</p>
+
+<p>
+On FreeBSD, Go 1.6 defaults to using <code>clang</code>, not <code>gcc</code>, as the external C compiler.
+</p>
+
+<p>
+On Linux on little-endian 64-bit PowerPC (<code>linux/ppc64le</code>),
+Go 1.6 now supports <code>cgo</code> with external linking and
+is roughly feature complete.
+</p>
+
+<p>
+On NaCl, Go 1.5 required SDK version pepper-41.
+Go 1.6 adds support for later SDK versions.
+</p>
+
+<p>
+On 32-bit x86 systems using the <code>-dynlink</code> or <code>-shared</code> compilation modes,
+the register CX is now overwritten by certain memory references and should
+be avoided in hand-written assembly.
+See the <a href="/doc/asm#x86">assembly documentation</a> for details.
+</p>
+
+<h2 id="tools">Tools</h2>
+
+<h3 id="cgo">Cgo</h3>
+
+<p>
+There is one major change to <a href="/cmd/cgo/"><code>cgo</code></a>, along with one minor change.
+</p>
+
+<p>
+The major change is the definition of rules for sharing Go pointers with C code,
+to ensure that such C code can coexist with Go's garbage collector.
+Briefly, Go and C may share memory allocated by Go
+when a pointer to that memory is passed to C as part of a <code>cgo</code> call,
+provided that the memory itself contains no pointers to Go-allocated memory,
+and provided that C does not retain the pointer after the call returns.
+These rules are checked by the runtime during program execution:
+if the runtime detects a violation, it prints a diagnosis and crashes the program.
+The checks can be disabled by setting the environment variable
+<code>GODEBUG=cgocheck=0</code>, but note that the vast majority of
+code identified by the checks is subtly incompatible with garbage collection
+in one way or another.
+Disabling the checks will typically only lead to more mysterious failure modes.
+Fixing the code in question should be strongly preferred
+over turning off the checks.
+See the <a href="/cmd/cgo/#hdr-Passing_pointers"><code>cgo</code> documentation</a> for more details.
+</p>
+
+<p>
+The minor change is
+the addition of explicit <code>C.complexfloat</code> and <code>C.complexdouble</code> types,
+separate from Go's <code>complex64</code> and <code>complex128</code>.
+Matching the other numeric types, C's complex types and Go's complex type are
+no longer interchangeable.
+</p>
+
+<h3 id="compiler">Compiler Toolchain</h3>
+
+<p>
+The compiler toolchain is mostly unchanged.
+Internally, the most significant change is that the parser is now hand-written
+instead of generated from <a href="/cmd/yacc/">yacc</a>.
+</p>
+
+<p>
+The compiler, linker, and <code>go</code> command have a new flag <code>-msan</code>,
+analogous to <code>-race</code> and only available on linux/amd64,
+that enables interoperation with the <a href="http://clang.llvm.org/docs/MemorySanitizer.html">Clang MemorySanitizer</a>.
+Such interoperation is useful mainly for testing a program containing suspect C or C++ code.
+</p>
+
+<p>
+The linker has a new option <code>-libgcc</code> to set the expected location
+of the C compiler support library when linking <a href="/cmd/cgo/"><code>cgo</code></a> code.
+The option is only consulted when using <code>-linkmode=internal</code>,
+and it may be set to <code>none</code> to disable the use of a support library.
+</p>
+
+<p>
+The implementation of <a href="/doc/go1.5#link">build modes started in Go 1.5</a> has been expanded to more systems.
+This release adds support for the <code>c-shared</code> mode on <code>android/386</code>, <code>android/amd64</code>,
+<code>android/arm64</code>, <code>linux/386</code>, and <code>linux/arm64</code>;
+for the <code>shared</code> mode on <code>linux/386</code>, <code>linux/arm</code>, <code>linux/amd64</code>, and <code>linux/ppc64le</code>;
+and for the new <code>pie</code> mode (generating position-independent executables) on
+<code>android/386</code>, <code>android/amd64</code>, <code>android/arm</code>, <code>android/arm64</code>, <code>linux/386</code>,
+<code>linux/amd64</code>, <code>linux/arm</code>, <code>linux/arm64</code>, and <code>linux/ppc64le</code>.
+See the <a href="https://golang.org/s/execmodes">design document</a> for details.
+</p>
+
+<p>
+As a reminder, the linker's <code>-X</code> flag changed in Go 1.5.
+In Go 1.4 and earlier, it took two arguments, as in
+</p>
+
+<pre>
+-X importpath.name value
+</pre>
+
+<p>
+Go 1.5 added an alternative syntax using a single argument
+that is itself a <code>name=value</code> pair:
+</p>
+
+<pre>
+-X importpath.name=value
+</pre>
+
+<p>
+In Go 1.5 the old syntax was still accepted, after printing a warning
+suggesting use of the new syntax instead.
+Go 1.6 continues to accept the old syntax and print the warning.
+Go 1.7 will remove support for the old syntax.
+</p>
+
+<h3 id="gccgo">Gccgo</h3>
+
+<p>
+The release schedules for the GCC and Go projects do not coincide.
+GCC release 5 contains the Go 1.4 version of gccgo.
+The next release, GCC 6, will have the Go 1.5 version of gccgo.
+Due to release scheduling, it is likely that
+Go 1.6 will not be in a GCC release until GCC 7.
+</p>
+
+<h3 id="go_command">Go command</h3>
+
+<p>
+The <a href="/cmd/go"><code>go</code></a> command's basic operation
+is unchanged, but there are a number of changes worth noting.
+</p>
+
+<p>
+Go 1.5 introduced experimental support for vendoring,
+enabled by setting the <code>GO15VENDOREXPERIMENT</code> environment variable to <code>1</code>.
+Go 1.6 keeps the vendoring support, no longer considered experimental,
+and enables it by default.
+It can be disabled explicitly by setting
+the <code>GO15VENDOREXPERIMENT</code> environment variable to <code>0</code>.
+Go 1.7 will remove support for the environment variable.
+</p>
+
+<p>
+The most likely problem caused by enabling vendoring by default happens
+in source trees containing an existing directory named <code>vendor</code> that
+does not expect to be interpreted according to new vendoring semantics.
+In this case, the simplest fix is to rename the directory to anything other
+than <code>vendor</code> and update any affected import paths.
+</p>
+
+<p>
+For details about vendoring,
+see the documentation for the <a href="/cmd/go/#hdr-Vendor_Directories"><code>go</code> command</a>
+and the <a href="https://golang.org/s/go15vendor">design document</a>.
+</p>
+
+<p>
+There is a new build flag, <code>-msan</code>,
+that compiles Go with support for the LLVM memory sanitizer.
+This is intended mainly for use when linking against C or C++ code
+that is being checked with the memory sanitizer.
+</p>
+
+<h3 id="doc_command">Go doc command</h3>
+
+<p>
+Go 1.5 introduced the
+<a href="/cmd/go/#hdr-Show_documentation_for_package_or_symbol"><code>go doc</code></a> command,
+which allows references to packages using only the package name, as in
+<code>go</code> <code>doc</code> <code>http</code>.
+In the event of ambiguity, the Go 1.5 behavior was to use the package
+with the lexicographically earliest import path.
+In Go 1.6, ambiguity is resolved by preferring import paths with
+fewer elements, breaking ties using lexicographic comparison.
+An important effect of this change is that original copies of packages
+are now preferred over vendored copies.
+Successful searches also tend to run faster.
+</p>
+
+<h3 id="vet_command">Go vet command</h3>
+
+<p>
+The <a href="/cmd/vet"><code>go vet</code></a> command now diagnoses
+passing function or method values as arguments to <code>Printf</code>,
+such as when passing <code>f</code> where <code>f()</code> was intended.
+</p>
+
+<h2 id="performance">Performance</h2>
+
+<p>
+As always, the changes are so general and varied that precise statements
+about performance are difficult to make.
+Some programs may run faster, some slower.
+On average the programs in the Go 1 benchmark suite run a few percent faster in Go 1.6
+than they did in Go 1.5.
+The garbage collector's pauses are even lower than in Go 1.5,
+especially for programs using
+a large amount of memory.
+</p>
+
+<p>
+There have been significant optimizations bringing more than 10% improvements
+to implementations of the
+<a href="/pkg/compress/bzip2/"><code>compress/bzip2</code></a>,
+<a href="/pkg/compress/gzip/"><code>compress/gzip</code></a>,
+<a href="/pkg/crypto/aes/"><code>crypto/aes</code></a>,
+<a href="/pkg/crypto/elliptic/"><code>crypto/elliptic</code></a>,
+<a href="/pkg/crypto/ecdsa/"><code>crypto/ecdsa</code></a>, and
+<a href="/pkg/sort/"><code>sort</code></a> packages.
+</p>
+
+<h2 id="library">Core library</h2>
+
+<h3 id="http2">HTTP/2</h3>
+
+<p>
+Go 1.6 adds transparent support in the
+<a href="/pkg/net/http/"><code>net/http</code></a> package
+for the new <a href="https://http2.github.io/">HTTP/2 protocol</a>.
+Go clients and servers will automatically use HTTP/2 as appropriate when using HTTPS.
+There is no exported API specific to details of the HTTP/2 protocol handling,
+just as there is no exported API specific to HTTP/1.1.
+</p>
+
+<p>
+Programs that must disable HTTP/2 can do so by setting
+<a href="/pkg/net/http/#Transport"><code>Transport.TLSNextProto</code></a> (for clients)
+or
+<a href="/pkg/net/http/#Server"><code>Server.TLSNextProto</code></a> (for servers)
+to a non-nil, empty map.
+</p>
+
+<p>
+Programs that must adjust HTTP/2 protocol-specific details can import and use
+<a href="https://golang.org/x/net/http2"><code>golang.org/x/net/http2</code></a>,
+in particular its
+<a href="https://godoc.org/golang.org/x/net/http2/#ConfigureServer">ConfigureServer</a>
+and
+<a href="https://godoc.org/golang.org/x/net/http2/#ConfigureTransport">ConfigureTransport</a>
+functions.
+</p>
+
+<h3 id="runtime">Runtime</h3>
+
+<p>
+The runtime has added lightweight, best-effort detection of concurrent misuse of maps.
+As always, if one goroutine is writing to a map, no other goroutine should be
+reading or writing the map concurrently.
+If the runtime detects this condition, it prints a diagnosis and crashes the program.
+The best way to find out more about the problem is to run the program
+under the
+<a href="https://blog.golang.org/race-detector">race detector</a>,
+which will more reliably identify the race
+and give more detail.
+</p>
+
+<p>
+For program-ending panics, the runtime now by default
+prints only the stack of the running goroutine,
+not all existing goroutines.
+Usually only the current goroutine is relevant to a panic,
+so omitting the others significantly reduces irrelevant output
+in a crash message.
+To see the stacks from all goroutines in crash messages, set the environment variable
+<code>GOTRACEBACK</code> to <code>all</code>
+or call
+<a href="/pkg/runtime/debug/#SetTraceback"><code>debug.SetTraceback</code></a>
+before the crash, and rerun the program.
+See the <a href="/pkg/runtime/#hdr-Environment_Variables">runtime documentation</a> for details.
+</p>
+
+<p>
+<em>Updating</em>:
+Uncaught panics intended to dump the state of the entire program,
+such as when a timeout is detected or when explicitly handling a received signal,
+should now call <code>debug.SetTraceback("all")</code> before panicking.
+Searching for uses of
+<a href="/pkg/os/signal/#Notify"><code>signal.Notify</code></a> may help identify such code.
+</p>
+
+<p>
+On Windows, Go programs in Go 1.5 and earlier forced
+the global Windows timer resolution to 1ms at startup
+by calling <code>timeBeginPeriod(1)</code>.
+Go no longer needs this for good scheduler performance,
+and changing the global timer resolution caused problems on some systems,
+so the call has been removed.
+</p>
+
+<p>
+When using <code>-buildmode=c-archive</code> or
+<code>-buildmode=c-shared</code> to build an archive or a shared
+library, the handling of signals has changed.
+In Go 1.5 the archive or shared library would install a signal handler
+for most signals.
+In Go 1.6 it will only install a signal handler for the
+synchronous signals needed to handle run-time panics in Go code:
+SIGBUS, SIGFPE, SIGSEGV.
+See the <a href="/pkg/os/signal">os/signal</a> package for more
+details.
+</p>
+
+<h3 id="reflect">Reflect</h3>
+
+<p>
+The
+<a href="/pkg/reflect/"><code>reflect</code></a> package has
+<a href="https://golang.org/issue/12367">resolved a long-standing incompatibility</a>
+between the gc and gccgo toolchains
+regarding embedded unexported struct types containing exported fields.
+Code that walks data structures using reflection, especially to implement
+serialization in the spirit
+of the
+<a href="/pkg/encoding/json/"><code>encoding/json</code></a> and
+<a href="/pkg/encoding/xml/"><code>encoding/xml</code></a> packages,
+may need to be updated.
+</p>
+
+<p>
+The problem arises when using reflection to walk through
+an embedded unexported struct-typed field
+into an exported field of that struct.
+In this case, <code>reflect</code> had incorrectly reported
+the embedded field as exported, by returning an empty <code>Field.PkgPath</code>.
+Now it correctly reports the field as unexported
+but ignores that fact when evaluating access to exported fields
+contained within the struct.
+</p>
+
+<p>
+<em>Updating</em>:
+Typically, code that previously walked over structs and used
+</p>
+
+<pre>
+f.PkgPath != ""
+</pre>
+
+<p>
+to exclude inaccessible fields
+should now use
+</p>
+
+<pre>
+f.PkgPath != "" && !f.Anonymous
+</pre>
+
+<p>
+For example, see the changes to the implementations of
+<a href="https://go-review.googlesource.com/#/c/14011/2/src/encoding/json/encode.go"><code>encoding/json</code></a> and
+<a href="https://go-review.googlesource.com/#/c/14012/2/src/encoding/xml/typeinfo.go"><code>encoding/xml</code></a>.
+</p>
+
+<h3 id="sort">Sorting</h3>
+
+<p>
+In the
+<a href="/pkg/sort/"><code>sort</code></a>
+package,
+the implementation of
+<a href="/pkg/sort/#Sort"><code>Sort</code></a>
+has been rewritten to make about 10% fewer calls to the
+<a href="/pkg/sort/#Interface"><code>Interface</code></a>'s
+<code>Less</code> and <code>Swap</code>
+methods, with a corresponding overall time savings.
+The new algorithm does choose a different ordering than before
+for values that compare equal (those pairs for which <code>Less(i,</code> <code>j)</code> and <code>Less(j,</code> <code>i)</code> are false).
+</p>
+
+<p>
+<em>Updating</em>:
+The definition of <code>Sort</code> makes no guarantee about the final order of equal values,
+but the new behavior may still break programs that expect a specific order.
+Such programs should either refine their <code>Less</code> implementations
+to report the desired order
+or should switch to
+<a href="/pkg/sort/#Stable"><code>Stable</code></a>,
+which preserves the original input order
+of equal values.
+</p>
+
+<h3 id="template">Templates</h3>
+
+<p>
+In the
+<a href="/pkg/text/template/">text/template</a> package,
+there are two significant new features to make writing templates easier.
+</p>
+
+<p>
+First, it is now possible to <a href="/pkg/text/template/#hdr-Text_and_spaces">trim spaces around template actions</a>,
+which can make template definitions more readable.
+A minus sign at the beginning of an action says to trim space before the action,
+and a minus sign at the end of an action says to trim space after the action.
+For example, the template
+</p>
+
+<pre>
+{{"{{"}}23 -}}
+   <
+{{"{{"}}- 45}}
+</pre>
+
+<p>
+formats as <code>23<45</code>.
+</p>
+
+<p>
+Second, the new <a href="/pkg/text/template/#hdr-Actions"><code>{{"{{"}}block}}</code> action</a>,
+combined with allowing redefinition of named templates,
+provides a simple way to define pieces of a template that
+can be replaced in different instantiations.
+There is <a href="/pkg/text/template/#example_Template_block">an example</a>
+in the <code>text/template</code> package that demonstrates this new feature.
+</p>
+
+<h3 id="minor_library_changes">Minor changes to the library</h3>
+
+<ul>
+
+<li>
+The <a href="/pkg/archive/tar/"><code>archive/tar</code></a> package's
+implementation corrects many bugs in rare corner cases of the file format.
+One visible change is that the
+<a href="/pkg/archive/tar/#Reader"><code>Reader</code></a> type's
+<a href="/pkg/archive/tar/#Reader.Read"><code>Read</code></a> method
+now presents the content of special file types as being empty,
+returning <code>io.EOF</code> immediately.
+</li>
+
+<li>
+In the <a href="/pkg/archive/zip/"><code>archive/zip</code></a> package, the
+<a href="/pkg/archive/zip/#Reader"><code>Reader</code></a> type now has a
+<a href="/pkg/archive/zip/#Reader.RegisterDecompressor"><code>RegisterDecompressor</code></a> method,
+and the
+<a href="/pkg/archive/zip/#Writer"><code>Writer</code></a> type now has a
+<a href="/pkg/archive/zip/#Writer.RegisterCompressor"><code>RegisterCompressor</code></a> method,
+enabling control over compression options for individual zip files.
+These take precedence over the pre-existing global
+<a href="/pkg/archive/zip/#RegisterDecompressor"><code>RegisterDecompressor</code></a> and
+<a href="/pkg/archive/zip/#RegisterCompressor"><code>RegisterCompressor</code></a> functions.
+</li>
+
+<li>
+The <a href="/pkg/bufio/"><code>bufio</code></a> package's
+<a href="/pkg/bufio/#Scanner"><code>Scanner</code></a> type now has a
+<a href="/pkg/bufio/#Scanner.Buffer"><code>Buffer</code></a> method,
+to specify an initial buffer and maximum buffer size to use during scanning.
+This makes it possible, when needed, to scan tokens larger than
+<code>MaxScanTokenSize</code>.
+Also for the <code>Scanner</code>, the package now defines the
+<a href="/pkg/bufio/#ErrFinalToken"><code>ErrFinalToken</code></a> error value, for use by
+<a href="/pkg/bufio/#SplitFunc">split functions</a> to abort processing or to return a final empty token.
+</li>
+
+<li>
+The <a href="/pkg/compress/flate/"><code>compress/flate</code></a> package
+has deprecated its
+<a href="/pkg/compress/flate/#ReadError"><code>ReadError</code></a> and
+<a href="/pkg/compress/flate/#WriteError"><code>WriteError</code></a> error implementations.
+In Go 1.5 they were only rarely returned when an error was encountered;
+now they are never returned, although they remain defined for compatibility.
+</li>
+
+<li>
+The <a href="/pkg/compress/flate/"><code>compress/flate</code></a>,
+<a href="/pkg/compress/gzip/"><code>compress/gzip</code></a>, and
+<a href="/pkg/compress/zlib/"><code>compress/zlib</code></a> packages
+now report
+<a href="/pkg/io/#ErrUnexpectedEOF"><code>io.ErrUnexpectedEOF</code></a> for truncated input streams, instead of
+<a href="/pkg/io/#EOF"><code>io.EOF</code></a>.
+</li>
+
+<li>
+The <a href="/pkg/crypto/cipher/"><code>crypto/cipher</code></a> package now
+overwrites the destination buffer in the event of a GCM decryption failure.
+This is to allow the AESNI code to avoid using a temporary buffer.
+</li>
+
+<li>
+The <a href="/pkg/crypto/tls/"><code>crypto/tls</code></a> package
+has a variety of minor changes.
+It now allows
+<a href="/pkg/crypto/tls/#Listen"><code>Listen</code></a>
+to succeed when the
+<a href="/pkg/crypto/tls/#Config"><code>Config</code></a>
+has a nil <code>Certificates</code>, as long as the <code>GetCertificate</code> callback is set,
+it adds support for RSA with AES-GCM cipher suites,
+and
+it adds a
+<a href="/pkg/crypto/tls/#RecordHeaderError"><code>RecordHeaderError</code></a>
+to allow clients (in particular, the <a href="/pkg/net/http/"><code>net/http</code></a> package)
+to report a better error when attempting a TLS connection to a non-TLS server.
+</li>
+
+<li>
+The <a href="/pkg/crypto/x509/"><code>crypto/x509</code></a> package
+now permits certificates to contain negative serial numbers
+(technically an error, but unfortunately common in practice),
+and it defines a new
+<a href="/pkg/crypto/x509/#InsecureAlgorithmError"><code>InsecureAlgorithmError</code></a>
+to give a better error message when rejecting a certificate
+signed with an insecure algorithm like MD5.
+</li>
+
+<li>
+The <a href="/pkg/debug/dwarf"><code>debug/dwarf</code></a> and
+<a href="/pkg/debug/elf/"><code>debug/elf</code></a> packages
+together add support for compressed DWARF sections.
+User code needs no updating: the sections are decompressed automatically when read.
+</li>
+
+<li>
+The <a href="/pkg/debug/elf/"><code>debug/elf</code></a> package
+adds support for general compressed ELF sections.
+User code needs no updating: the sections are decompressed automatically when read.
+However, compressed
+<a href="/pkg/debug/elf/#Section"><code>Sections</code></a> do not support random access:
+they have a nil <code>ReaderAt</code> field.
+</li>
+
+<li>
+The <a href="/pkg/encoding/asn1/"><code>encoding/asn1</code></a> package
+now exports
+<a href="/pkg/encoding/asn1/#pkg-constants">tag and class constants</a>
+useful for advanced parsing of ASN.1 structures.
+</li>
+
+<li>
+Also in the <a href="/pkg/encoding/asn1/"><code>encoding/asn1</code></a> package,
+<a href="/pkg/encoding/asn1/#Unmarshal"><code>Unmarshal</code></a> now rejects various non-standard integer and length encodings.
+</li>
+
+<li>
+The <a href="/pkg/encoding/base64"><code>encoding/base64</code></a> package's
+<a href="/pkg/encoding/base64/#Decoder"><code>Decoder</code></a> has been fixed
+to process the final bytes of its input. Previously it processed as many four-byte tokens as
+possible but ignored the remainder, up to three bytes.
+The <code>Decoder</code> therefore now handles inputs in unpadded encodings (like
+<a href="/pkg/encoding/base64/#RawURLEncoding">RawURLEncoding</a>) correctly,
+but it also rejects inputs in padded encodings that are truncated or end with invalid bytes,
+such as trailing spaces.
+</li>
+
+<li>
+The <a href="/pkg/encoding/json/"><code>encoding/json</code></a> package
+now checks the syntax of a
+<a href="/pkg/encoding/json/#Number"><code>Number</code></a>
+before marshaling it, requiring that it conforms to the JSON specification for numeric values.
+As in previous releases, the zero <code>Number</code> (an empty string) is marshaled as a literal 0 (zero).
+</li>
+
+<li>
+The <a href="/pkg/encoding/xml/"><code>encoding/xml</code></a> package's
+<a href="/pkg/encoding/xml/#Marshal"><code>Marshal</code></a>
+function now supports a <code>cdata</code> attribute, such as <code>chardata</code>
+but encoding its argument in one or more <code><![CDATA[ ... ]]></code> tags.
+</li>
+
+<li>
+Also in the <a href="/pkg/encoding/xml/"><code>encoding/xml</code></a> package,
+<a href="/pkg/encoding/xml/#Decoder"><code>Decoder</code></a>'s
+<a href="/pkg/encoding/xml/#Decoder.Token"><code>Token</code></a> method
+now reports an error when encountering EOF before seeing all open tags closed,
+consistent with its general requirement that tags in the input be properly matched.
+To avoid that requirement, use
+<a href="/pkg/encoding/xml/#Decoder.RawToken"><code>RawToken</code></a>.
+</li>
+
+<li>
+The <a href="/pkg/fmt/"><code>fmt</code></a> package now allows
+any integer type as an argument to
+<a href="/pkg/fmt/#Printf"><code>Printf</code></a>'s <code>*</code> width and precision specification.
+In previous releases, the argument to <code>*</code> was required to have type <code>int</code>.
+</li>
+
+<li>
+Also in the <a href="/pkg/fmt/"><code>fmt</code></a> package,
+<a href="/pkg/fmt/#Scanf"><code>Scanf</code></a> can now scan hexadecimal strings using %X, as an alias for %x.
+Both formats accept any mix of upper- and lower-case hexadecimal.
+</li>
+
+<li>
+The <a href="/pkg/image/"><code>image</code></a>
+and
+<a href="/pkg/image/color/"><code>image/color</code></a> packages
+add
+<a href="/pkg/image/#NYCbCrA"><code>NYCbCrA</code></a>
+and
+<a href="/pkg/image/color/#NYCbCrA"><code>NYCbCrA</code></a>
+types, to support Y'CbCr images with non-premultiplied alpha.
+</li>
+
+<li>
+The <a href="/pkg/io/"><code>io</code></a> package's
+<a href="/pkg/io/#MultiWriter"><code>MultiWriter</code></a>
+implementation now implements a <code>WriteString</code> method,
+for use by
+<a href="/pkg/io/#WriteString"><code>WriteString</code></a>.
+</li>
+
+<li>
+In the <a href="/pkg/math/big/"><code>math/big</code></a> package,
+<a href="/pkg/math/big/#Int"><code>Int</code></a> adds
+<a href="/pkg/math/big/#Int.Append"><code>Append</code></a>
+and
+<a href="/pkg/math/big/#Int.Text"><code>Text</code></a>
+methods to give more control over printing.
+</li>
+
+<li>
+Also in the <a href="/pkg/math/big/"><code>math/big</code></a> package,
+<a href="/pkg/math/big/#Float"><code>Float</code></a> now implements
+<a href="/pkg/encoding/#TextMarshaler"><code>encoding.TextMarshaler</code></a> and
+<a href="/pkg/encoding/#TextUnmarshaler"><code>encoding.TextUnmarshaler</code></a>,
+allowing it to be serialized in a natural form by the
+<a href="/pkg/encoding/json/"><code>encoding/json</code></a> and
+<a href="/pkg/encoding/xml/"><code>encoding/xml</code></a> packages.
+</li>
+
+<li>
+Also in the <a href="/pkg/math/big/"><code>math/big</code></a> package,
+<a href="/pkg/math/big/#Float"><code>Float</code></a>'s
+<a href="/pkg/math/big/#Float.Append"><code>Append</code></a> method now supports the special precision argument -1.
+As in
+<a href="/pkg/strconv/#ParseFloat"><code>strconv.ParseFloat</code></a>,
+precision -1 means to use the smallest number of digits necessary such that
+<a href="/pkg/math/big/#Float.Parse"><code>Parse</code></a>
+reading the result into a <code>Float</code> of the same precision
+will yield the original value.
+</li>
+
+<li>
+The <a href="/pkg/math/rand/"><code>math/rand</code></a> package
+adds a
+<a href="/pkg/math/rand/#Read"><code>Read</code></a>
+function, and likewise
+<a href="/pkg/math/rand/#Rand"><code>Rand</code></a> adds a
+<a href="/pkg/math/rand/#Rand.Read"><code>Read</code></a> method.
+These make it easier to generate pseudorandom test data.
+Note that, like the rest of the package,
+these should not be used in cryptographic settings;
+for such purposes, use the <a href="/pkg/crypto/rand/"><code>crypto/rand</code></a> package instead.
+</li>
+
+<li>
+The <a href="/pkg/net/"><code>net</code></a> package's
+<a href="/pkg/net/#ParseMAC"><code>ParseMAC</code></a> function now accepts 20-byte IP-over-InfiniBand (IPoIB) link-layer addresses.
+</li>
+
+
+<li>
+Also in the <a href="/pkg/net/"><code>net</code></a> package,
+there have been a few changes to DNS lookups.
+First, the
+<a href="/pkg/net/#DNSError"><code>DNSError</code></a> error implementation now implements
+<a href="/pkg/net/#Error"><code>Error</code></a>,
+and in particular its new
+<a href="/pkg/net/#DNSError.IsTemporary"><code>IsTemporary</code></a>
+method returns true for DNS server errors.
+Second, DNS lookup functions such as
+<a href="/pkg/net/#LookupAddr"><code>LookupAddr</code></a>
+now return rooted domain names (with a trailing dot)
+on Plan 9 and Windows, to match the behavior of Go on Unix systems.
+</li>
+
+<li>
+The <a href="/pkg/net/http/"><code>net/http</code></a> package has
+a number of minor additions beyond the HTTP/2 support already discussed.
+First, the
+<a href="/pkg/net/http/#FileServer"><code>FileServer</code></a> now sorts its generated directory listings by file name.
+Second, the
+<a href="/pkg/net/http/#ServeFile"><code>ServeFile</code></a> function now refuses to serve a result
+if the request's URL path contains “..” (dot-dot) as a path element.
+Programs should typically use <code>FileServer</code> and 
+<a href="/pkg/net/http/#Dir"><code>Dir</code></a>
+instead of calling <code>ServeFile</code> directly.
+Programs that need to serve file content in response to requests for URLs containing dot-dot can 
+still call <a href="/pkg/net/http/#ServeContent"><code>ServeContent</code></a>.
+Third, the
+<a href="/pkg/net/http/#Client"><code>Client</code></a> now allows user code to set the
+<code>Expect:</code> <code>100-continue</code> header (see
+<a href="/pkg/net/http/#Transport"><code>Transport.ExpectContinueTimeout</code></a>).
+Fourth, there are
+<a href="/pkg/net/http/#pkg-constants">five new error codes</a>:
+<code>StatusPreconditionRequired</code> (428),
+<code>StatusTooManyRequests</code> (429),
+<code>StatusRequestHeaderFieldsTooLarge</code> (431), and
+<code>StatusNetworkAuthenticationRequired</code> (511) from RFC 6585,
+as well as the recently-approved
+<code>StatusUnavailableForLegalReasons</code> (451).
+Fifth, the implementation and documentation of
+<a href="/pkg/net/http/#CloseNotifier"><code>CloseNotifier</code></a>
+has been substantially changed.
+The <a href="/pkg/net/http/#Hijacker"><code>Hijacker</code></a>
+interface now works correctly on connections that have previously
+been used with <code>CloseNotifier</code>.
+The documentation now describes when <code>CloseNotifier</code>
+is expected to work.
+</li>
+
+<li>
+Also in the <a href="/pkg/net/http/"><code>net/http</code></a> package,
+there are a few changes related to the handling of a
+<a href="/pkg/net/http/#Request"><code>Request</code></a> data structure with its <code>Method</code> field set to the empty string.
+An empty <code>Method</code> field has always been documented as an alias for <code>"GET"</code>
+and it remains so.
+However, Go 1.6 fixes a few routines that did not treat an empty
+<code>Method</code> the same as an explicit <code>"GET"</code>.
+Most notably, in previous releases
+<a href="/pkg/net/http/#Client"><code>Client</code></a> followed redirects only with
+<code>Method</code> set explicitly to <code>"GET"</code>;
+in Go 1.6 <code>Client</code> also follows redirects for the empty <code>Method</code>.
+Finally,
+<a href="/pkg/net/http/#NewRequest"><code>NewRequest</code></a> accepts a <code>method</code> argument that has not been
+documented as allowed to be empty.
+In past releases, passing an empty <code>method</code> argument resulted
+in a <code>Request</code> with an empty <code>Method</code> field.
+In Go 1.6, the resulting <code>Request</code> always has an initialized
+<code>Method</code> field: if its argument is an empty string, <code>NewRequest</code>
+sets the <code>Method</code> field in the returned <code>Request</code> to <code>"GET"</code>.
+</li>
+
+<li>
+The <a href="/pkg/net/http/httptest/"><code>net/http/httptest</code></a> package's
+<a href="/pkg/net/http/httptest/#ResponseRecorder"><code>ResponseRecorder</code></a> now initializes a default Content-Type header
+using the same content-sniffing algorithm as in
+<a href="/pkg/net/http/#Server"><code>http.Server</code></a>.
+</li>
+
+<li>
+The <a href="/pkg/net/url/"><code>net/url</code></a> package's
+<a href="/pkg/net/url/#Parse"><code>Parse</code></a> is now stricter and more spec-compliant regarding the parsing
+of host names.
+For example, spaces in the host name are no longer accepted.
+</li>
+
+<li>
+Also in the <a href="/pkg/net/url/"><code>net/url</code></a> package,
+the <a href="/pkg/net/url/#Error"><code>Error</code></a> type now implements
+<a href="/pkg/net/#Error"><code>net.Error</code></a>.
+</li>
+
+<li>
+The <a href="/pkg/os/"><code>os</code></a> package's
+<a href="/pkg/os/#IsExist"><code>IsExist</code></a>,
+<a href="/pkg/os/#IsNotExist"><code>IsNotExist</code></a>,
+and
+<a href="/pkg/os/#IsPermission"><code>IsPermission</code></a>
+now return correct results when inquiring about an
+<a href="/pkg/os/#SyscallError"><code>SyscallError</code></a>.
+</li>
+
+<li>
+On Unix-like systems, when a write
+to <a href="/pkg/os/#pkg-variables"><code>os.Stdout</code>
+or <code>os.Stderr</code></a> (more precisely, an <code>os.File</code>
+opened for file descriptor 1 or 2) fails due to a broken pipe error,
+the program will raise a <code>SIGPIPE</code> signal.
+By default this will cause the program to exit; this may be changed by
+calling the
+<a href="/pkg/os/signal"><code>os/signal</code></a>
+<a href="/pkg/os/signal/#Notify"><code>Notify</code></a> function
+for <code>syscall.SIGPIPE</code>.
+A write to a broken pipe on a file descriptor other 1 or 2 will simply
+return <code>syscall.EPIPE</code> (possibly wrapped in
+<a href="/pkg/os#PathError"><code>os.PathError</code></a>
+and/or <a href="/pkg/os#SyscallError"><code>os.SyscallError</code></a>)
+to the caller.
+The old behavior of raising an uncatchable <code>SIGPIPE</code> signal
+after 10 consecutive writes to a broken pipe no longer occurs.
+</li>
+
+<li>
+In the <a href="/pkg/os/exec/"><code>os/exec</code></a> package,
+<a href="/pkg/os/exec/#Cmd"><code>Cmd</code></a>'s
+<a href="/pkg/os/exec/#Cmd.Output"><code>Output</code></a> method continues to return an
+<a href="/pkg/os/exec/#ExitError"><code>ExitError</code></a> when a command exits with an unsuccessful status.
+If standard error would otherwise have been discarded,
+the returned <code>ExitError</code> now holds a prefix and suffix
+(currently 32 kB) of the failed command's standard error output,
+for debugging or for inclusion in error messages.
+The <code>ExitError</code>'s
+<a href="/pkg/os/exec/#ExitError.String"><code>String</code></a>
+method does not show the captured standard error;
+programs must retrieve it from the data structure
+separately.
+</li>
+
+<li>
+On Windows, the <a href="/pkg/path/filepath/"><code>path/filepath</code></a> package's
+<a href="/pkg/path/filepath/#Join"><code>Join</code></a> function now correctly handles the case when the base is a relative drive path.
+For example, <code>Join(`c:`,</code> <code>`a`)</code> now
+returns <code>`c:a`</code> instead of <code>`c:\a`</code> as in past releases.
+This may affect code that expects the incorrect result.
+</li>
+
+<li>
+In the <a href="/pkg/regexp/"><code>regexp</code></a> package,
+the
+<a href="/pkg/regexp/#Regexp"><code>Regexp</code></a> type has always been safe for use by
+concurrent goroutines.
+It uses a <a href="/pkg/sync/#Mutex"><code>sync.Mutex</code></a> to protect
+a cache of scratch spaces used during regular expression searches.
+Some high-concurrency servers using the same <code>Regexp</code> from many goroutines
+have seen degraded performance due to contention on that mutex.
+To help such servers, <code>Regexp</code> now has a
+<a href="/pkg/regexp/#Regexp.Copy"><code>Copy</code></a> method,
+which makes a copy of a <code>Regexp</code> that shares most of the structure
+of the original but has its own scratch space cache.
+Two goroutines can use different copies of a <code>Regexp</code>
+without mutex contention.
+A copy does have additional space overhead, so <code>Copy</code>
+should only be used when contention has been observed.
+</li>
+
+<li>
+The <a href="/pkg/strconv/"><code>strconv</code></a> package adds
+<a href="/pkg/strconv/#IsGraphic"><code>IsGraphic</code></a>,
+similar to <a href="/pkg/strconv/#IsPrint"><code>IsPrint</code></a>.
+It also adds
+<a href="/pkg/strconv/#QuoteToGraphic"><code>QuoteToGraphic</code></a>,
+<a href="/pkg/strconv/#QuoteRuneToGraphic"><code>QuoteRuneToGraphic</code></a>,
+<a href="/pkg/strconv/#AppendQuoteToGraphic"><code>AppendQuoteToGraphic</code></a>,
+and
+<a href="/pkg/strconv/#AppendQuoteRuneToGraphic"><code>AppendQuoteRuneToGraphic</code></a>,
+analogous to
+<a href="/pkg/strconv/#QuoteToASCII"><code>QuoteToASCII</code></a>,
+<a href="/pkg/strconv/#QuoteRuneToASCII"><code>QuoteRuneToASCII</code></a>,
+and so on.
+The <code>ASCII</code> family escapes all space characters except ASCII space (U+0020).
+In contrast, the <code>Graphic</code> family does not escape any Unicode space characters (category Zs).
+</li>
+
+<li>
+In the <a href="/pkg/testing/"><code>testing</code></a> package,
+when a test calls
+<a href="/pkg/testing/#T.Parallel">t.Parallel</a>,
+that test is paused until all non-parallel tests complete, and then
+that test continues execution with all other parallel tests.
+Go 1.6 changes the time reported for such a test:
+previously the time counted only the parallel execution,
+but now it also counts the time from the start of testing
+until the call to <code>t.Parallel</code>.
+</li>
+
+<li>
+The <a href="/pkg/text/template/"><code>text/template</code></a> package
+contains two minor changes, in addition to the <a href="#template">major changes</a>
+described above.
+First, it adds a new
+<a href="/pkg/text/template/#ExecError"><code>ExecError</code></a> type
+returned for any error during
+<a href="/pkg/text/template/#Template.Execute"><code>Execute</code></a>
+that does not originate in a <code>Write</code> to the underlying writer.
+Callers can distinguish template usage errors from I/O errors by checking for
+<code>ExecError</code>.
+Second, the
+<a href="/pkg/text/template/#Template.Funcs"><code>Funcs</code></a> method
+now checks that the names used as keys in the
+<a href="/pkg/text/template/#FuncMap"><code>FuncMap</code></a>
+are identifiers that can appear in a template function invocation.
+If not, <code>Funcs</code> panics.
+</li>
+
+<li>
+The <a href="/pkg/time/"><code>time</code></a> package's
+<a href="/pkg/time/#Parse"><code>Parse</code></a> function has always rejected any day of month larger than 31,
+such as January 32.
+In Go 1.6, <code>Parse</code> now also rejects February 29 in non-leap years,
+February 30, February 31, April 31, June 31, September 31, and November 31.
+</li>
+
+</ul>
+
diff --git a/doc/go_faq.html b/doc/go_faq.html
index 33636fc..b5f9772 100644
--- a/doc/go_faq.html
+++ b/doc/go_faq.html
@@ -98,7 +98,7 @@ What's the origin of the mascot?</h3>
 <p>
 The mascot and logo were designed by
 <a href="http://reneefrench.blogspot.com">Renée French</a>, who also designed
-<a href="http://plan9.bell-labs.com/plan9/glenda.html">Glenda</a>,
+<a href="https://9p.io/plan9/glenda.html">Glenda</a>,
 the Plan 9 bunny.
 The <a href="https://blog.golang.org/gopher">gopher</a>
 is derived from one she used for an <a href="http://wfmu.org/">WFMU</a>
@@ -860,6 +860,36 @@ value to hold the error and a type switch to discriminate cases.  The
 syntax tree example is also doable, although not as elegantly.
 </p>
 
+<h3 id="covariant_types">
+Why does Go not have covariant result types?</h3>
+
+<p>
+Covariant result types would mean that an interface like
+
+<pre>
+type Copyable interface {
+	Copy() interface{}
+}
+</pre>
+
+would be satisfied by the method
+
+<pre>
+func (v Value) Copy() Value
+</pre>
+
+because <code>Value</code> implements the empty interface.
+In Go method types must match exactly, so <code>Value</code> does not
+implement <code>Copyable</code>.
+Go separates the notion of what a
+type does—its methods—from the type's implementation.
+If two methods return different types, they are not doing the same thing.
+Programmers who want covariant result types are often trying to
+express a type hierarchy through interfaces.
+In Go it's more natural to have a clean separation between interface
+and implementation.
+</p>
+
 <h2 id="values">Values</h2>
 
 <h3 id="conversions">
diff --git a/doc/go_spec.html b/doc/go_spec.html
index 22f9701..6b6e75c 100644
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,6 +1,6 @@
 <!--{
 	"Title": "The Go Programming Language Specification",
-	"Subtitle": "Version of August 5, 2015",
+	"Subtitle": "Version of January 5, 2016",
 	"Path": "/ref/spec"
 }-->
 
@@ -101,15 +101,14 @@ The following terms are used to denote specific Unicode character classes:
 newline        = /* the Unicode code point U+000A */ .
 unicode_char   = /* an arbitrary Unicode code point except newline */ .
 unicode_letter = /* a Unicode code point classified as "Letter" */ .
-unicode_digit  = /* a Unicode code point classified as "Decimal Digit" */ .
+unicode_digit  = /* a Unicode code point classified as "Number, decimal digit" */ .
 </pre>
 
 <p>
-In <a href="http://www.unicode.org/versions/Unicode6.3.0/">The Unicode Standard 6.3</a>,
-Section 4.5 "General Category"
-defines a set of character categories.  Go treats
-those characters in category Lu, Ll, Lt, Lm, or Lo as Unicode letters,
-and those in category Nd as Unicode digits.
+In <a href="http://www.unicode.org/versions/Unicode8.0.0/">The Unicode Standard 8.0</a>,
+Section 4.5 "General Category" defines a set of character categories.
+Go treats all characters in any of the Letter categories Lu, Ll, Lt, Lm, or Lo
+as Unicode letters, and those in the Number category Nd as Unicode digits.
 </p>
 
 <h3 id="Letters_and_digits">Letters and digits</h3>
@@ -558,7 +557,9 @@ and are discussed in that section.
 </p>
 
 <p>
-Numeric constants represent values of arbitrary precision and do not overflow.
+Numeric constants represent exact values of arbitrary precision and do not overflow.
+Consequently, there are no constants denoting the IEEE-754 negative zero, infinity,
+and not-a-number values.
 </p>
 
 <p>
@@ -594,16 +595,6 @@ complex, or string constant.
 </p>
 
 <p>
-There are no constants denoting the IEEE-754 infinity and not-a-number values,
-but the <a href="/pkg/math/"><code>math</code> package</a>'s
-<a href="/pkg/math/#Inf">Inf</a>,
-<a href="/pkg/math/#NaN">NaN</a>,
-<a href="/pkg/math/#IsInf">IsInf</a>, and
-<a href="/pkg/math/#IsNaN">IsNaN</a>
-functions return and test for those values at run time.
-</p>
-
-<p>
 Implementation restriction: Although numeric constants have arbitrary
 precision in the language, a compiler may implement them using an
 internal representation with limited precision.  That said, every
@@ -1059,12 +1050,18 @@ but are otherwise ignored.
 </p>
 
 <pre>
-// A struct corresponding to the TimeStamp protocol buffer.
-// The tag strings define the protocol buffer field numbers.
 struct {
-	microsec  uint64 "field 1"
-	serverIP6 uint64 "field 2"
-	process   string "field 3"
+	x, y float64 ""  // an empty tag string is like an absent tag
+	name string  "any string is permitted as a tag"
+	_    [4]byte "ceci n'est pas un champ de structure"
+}
+
+// A struct corresponding to a TimeStamp protocol buffer.
+// The tag strings define the protocol buffer field numbers;
+// they follow the convention outlined by the reflect package.
+struct {
+	microsec  uint64 `protobuf:"1"`
+	serverIP6 uint64 `protobuf:"2"`
 }
 </pre>
 
@@ -1116,7 +1113,7 @@ one unnamed result it may be written as an unparenthesized type.
 </p>
 
 <p>
-The final parameter in a function signature may have
+The final incoming parameter in a function signature may have
 a type prefixed with <code>...</code>.
 A function with such a parameter is called <i>variadic</i> and
 may be invoked with zero or more arguments for that parameter.
@@ -1797,26 +1794,27 @@ It can be used to construct a set of related constants:
 </p>
 
 <pre>
-const (  // iota is reset to 0
+const ( // iota is reset to 0
 	c0 = iota  // c0 == 0
 	c1 = iota  // c1 == 1
 	c2 = iota  // c2 == 2
 )
 
-const (
-	a = 1 << iota  // a == 1 (iota has been reset)
+const ( // iota is reset to 0
+	a = 1 << iota  // a == 1
 	b = 1 << iota  // b == 2
-	c = 1 << iota  // c == 4
+	c = 3          // c == 3  (iota is not used but still incremented)
+	d = 1 << iota  // d == 8
 )
 
-const (
+const ( // iota is reset to 0
 	u         = iota * 42  // u == 0     (untyped integer constant)
 	v float64 = iota * 42  // v == 42.0  (float64 constant)
 	w         = iota * 42  // w == 84    (untyped integer constant)
 )
 
-const x = iota  // x == 0 (iota has been reset)
-const y = iota  // y == 0 (iota has been reset)
+const x = iota  // x == 0  (iota has been reset)
+const y = iota  // y == 0  (iota has been reset)
 </pre>
 
 <p>
@@ -2091,7 +2089,7 @@ Receiver     = Parameters .
 
 <p>
 The receiver is specified via an extra parameter section preceding the method
-name. That parameter section must declare a single parameter, the receiver.
+name. That parameter section must declare a single non-variadic parameter, the receiver.
 Its type must be of the form <code>T</code> or <code>*T</code> (possibly using
 parentheses) where <code>T</code> is a type name. The type denoted by <code>T</code> is called
 the receiver <i>base type</i>; it must not be a pointer or interface type and
@@ -2210,9 +2208,8 @@ math.Sin	// denotes the Sin function in package math
 <p>
 Composite literals construct values for structs, arrays, slices, and maps
 and create a new value each time they are evaluated.
-They consist of the type of the value
-followed by a brace-bound list of composite elements. An element may be
-a single expression or a key-value pair.
+They consist of the type of the literal followed by a brace-bound list of elements.
+Each element may optionally be preceded by a corresponding key.
 </p>
 
 <pre class="ebnf">
@@ -2220,19 +2217,19 @@ CompositeLit  = LiteralType LiteralValue .
 LiteralType   = StructType | ArrayType | "[" "..." "]" ElementType |
                 SliceType | MapType | TypeName .
 LiteralValue  = "{" [ ElementList [ "," ] ] "}" .
-ElementList   = Element { "," Element } .
-Element       = [ Key ":" ] Value .
+ElementList   = KeyedElement { "," KeyedElement } .
+KeyedElement  = [ Key ":" ] Element .
 Key           = FieldName | Expression | LiteralValue .
 FieldName     = identifier .
-Value         = Expression | LiteralValue .
+Element       = Expression | LiteralValue .
 </pre>
 
 <p>
-The LiteralType must be a struct, array, slice, or map type
+The LiteralType's underlying type must be a struct, array, slice, or map type
 (the grammar enforces this constraint except when the type is given
 as a TypeName).
-The types of the expressions must be <a href="#Assignability">assignable</a>
-to the respective field, element, and key types of the LiteralType;
+The types of the elements and keys must be <a href="#Assignability">assignable</a>
+to the respective field, element, and key types of the literal type;
 there is no additional conversion.
 The key is interpreted as a field name for struct literals,
 an index for array and slice literals, and a key for map literals.
@@ -2245,7 +2242,7 @@ constant key value.
 For struct literals the following rules apply:
 </p>
 <ul>
-	<li>A key must be a field name declared in the LiteralType.
+	<li>A key must be a field name declared in the struct type.
 	</li>
 	<li>An element list that does not contain any keys must
 	    list an element for each struct field in the
@@ -2307,7 +2304,7 @@ var pointer *Point3D = &Point3D{y: 1000}
 </pre>
 
 <p>
-The length of an array literal is the length specified in the LiteralType.
+The length of an array literal is the length specified in the literal type.
 If fewer elements than the length are provided in the literal, the missing
 elements are set to the zero value for the array element type.
 It is an error to provide elements with index values outside the index range
@@ -3647,12 +3644,12 @@ is also allowed and follows from the general rules above.
 </p>
 
 <pre>
-const c = 3 < 4            // c is the untyped bool constant true
+const c = 3 < 4            // c is the untyped boolean constant true
 
 type MyBool bool
 var x, y int
 var (
-	// The result of a comparison is an untyped bool.
+	// The result of a comparison is an untyped boolean.
 	// The usual assignment rules apply.
 	b3        = x == y // b3 has type bool
 	b4 bool   = x == y // b4 has type bool
@@ -3796,7 +3793,8 @@ type <code>T</code> in any of these cases:
 	<code>T</code> is a floating-point type,
 	and <code>x</code> is representable by a value
 	of type <code>T</code> after rounding using
-	IEEE 754 round-to-even rules.
+	IEEE 754 round-to-even rules, but with an IEEE <code>-0.0</code>
+	further rounded to an unsigned <code>0.0</code>.
 	The constant <code>T(x)</code> is the rounded value.
 	</li>
 	<li>
@@ -3816,6 +3814,7 @@ uint(iota)               // iota value of type uint
 float32(2.718281828)     // 2.718281828 of type float32
 complex128(1)            // 1.0 + 0.0i of type complex128
 float32(0.49999999)      // 0.5 of type float32
+float64(-1e-1000)        // 0.0 of type float64
 string('x')              // "x" of type string
 string(0x266c)           // "♬" of type string
 MyString("foo" + "bar")  // "foobar" of type MyString
@@ -5330,7 +5329,7 @@ the "for" statement's block but the <code>goto</code> is not.
 
 <p>
 A "fallthrough" statement transfers control to the first statement of the
-next case clause in a <a href="#Expression_switches">expression "switch" statement</a>.
+next case clause in an <a href="#Expression_switches">expression "switch" statement</a>.
 It may be used only as the final non-empty statement in such a clause.
 </p>
 
diff --git a/doc/help.html b/doc/help.html
index 979d7bc..6448191 100644
--- a/doc/help.html
+++ b/doc/help.html
@@ -1,46 +1,62 @@
 <!--{
-	"Title": "Getting Help",
+	"Title": "Help",
 	"Path": "/help/"
 }-->
 
-<img class="gopher" src="/doc/gopher/help.png"/>
-
-<p>
-Need help with Go? Try these resources.
-</p>
-
 <div id="manual-nav"></div>
 
-<h3 id="faq"><a href="/doc/faq">Frequently Asked Questions (FAQ)</a></h3>
-<p>Answers to common questions about Go.</p>
+<h2 id="help">Get help</h2>
 
-<h3 id="playground"><a href="/play">The Go Playground</a></h3>
-<p>A place to write, run, and share Go code.</p>
-
-<h3 id="wiki"><a href="/wiki">The Go Wiki</a></h3>
-<p>A wiki maintained by the Go community.</p>
+<img class="gopher" src="/doc/gopher/help.png"/>
 
-<h3 id="mailinglist"><a href="//groups.google.com/group/golang-nuts">Go Nuts Mailing List</a></h3>
+<h3 id="mailinglist"><a href="https://groups.google.com/group/golang-nuts">Go Nuts Mailing List</a></h3>
 <p>
-Search the <a href="//groups.google.com/group/golang-nuts">golang-nuts</a>
+Search the <a href="https://groups.google.com/group/golang-nuts">golang-nuts</a>
 archives and consult the <a href="/doc/go_faq.html">FAQ</a> and
 <a href="//golang.org/wiki">wiki</a> before posting.
 </p>
 
+<h3 id="forum"><a href="https://forum.golangbridge.org/">Go Forum</a></h3>
+<p>
+The <a href="https://forum.golangbridge.org/">Go Forum</a> is an alternate discussion
+forum for Go programmers.
+</p>
+
+<h3 id="slack"><a href="https://blog.gopheracademy.com/gophers-slack-community/">Gopher Slack</a></h3>
+<p>Get live support from the official Go slack channel.</p>
+
 <h3 id="irc"><a href="irc:irc.freenode.net/go-nuts">Go IRC Channel</a></h3>
 <p>Get live support at <b>#go-nuts</b> on <b>irc.freenode.net</b>, the official
 Go IRC channel.</p>
 
-<h3 id="pluscom"><a href="https://plus.google.com/communities/114112804251407510571">The Go+ community</a></h3>
-<p>The Google+ community for Go enthusiasts.</p>
+<h3 id="faq"><a href="/doc/faq">Frequently Asked Questions (FAQ)</a></h3>
+<p>Answers to common questions about Go.</p>
+
+<h2 id="inform">Stay informed</h2>
+
+<h3 id="announce"><a href="https://groups.google.com/group/golang-announce">Go Announcements Mailing List</a></h3>
+<p>
+Subscribe to
+<a href="https://groups.google.com/group/golang-announce">golang-announce</a>
+for important announcements, such as the availability of new Go releases.
+</p>
 
-<h3 id="plus"><a href="https://plus.google.com/101406623878176903605/posts">The Go Programming Language at Google+</a></h3>
-<p>The Go project's Google+ page.</p>
+<h3 id="blog"><a href="//blog.golang.org">Go Blog</a></h3>
+<p>The Go project's official blog.</p>
 
-<h3 id="twitter"><a href="//twitter.com/golang">@golang at Twitter</a></h3>
+<h3 id="twitter"><a href="https://twitter.com/golang">@golang at Twitter</a></h3>
 <p>The Go project's official Twitter account.</p>
-<p>Tweeting about your problem with the <code>#golang</code> hashtag usually
-generates some helpful responses.</p>
+
+<h3 id="pluscom"><a href="https://plus.google.com/communities/114112804251407510571">Go+ community</a></h3>
+<p>A Google+ community for Go enthusiasts.</p>
+
+<h3 id="reddit"><a href="https://reddit.com/r/golang">golang sub-Reddit</a></h3>
+<p>
+The <a href="https://reddit.com/r/golang">golang sub-Reddit</a> is a place
+for Go news and discussion.
+</p>
+
+<h2 id="community">Community resources</h2>
 
 <h3 id="go_user_groups"><a href="/wiki/GoUserGroups">Go User Groups</a></h3>
 <p>
@@ -48,6 +64,12 @@ Each month in places around the world, groups of Go programmers ("gophers")
 meet to talk about Go. Find a chapter near you.
 </p>
 
+<h3 id="playground"><a href="/play">Go Playground</a></h3>
+<p>A place to write, run, and share Go code.</p>
+
+<h3 id="wiki"><a href="/wiki">Go Wiki</a></h3>
+<p>A wiki maintained by the Go community.</p>
+
 <h3 id="conduct"><a href="/conduct">Code of Conduct</a></h3>
 <p>
 Guidelines for participating in Go community spaces
diff --git a/doc/install-source.html b/doc/install-source.html
index bffaa27..332c720 100644
--- a/doc/install-source.html
+++ b/doc/install-source.html
@@ -71,6 +71,12 @@ architectures.
 <dd>
 	Supports Linux binaries. New in 1.5 and not as well excercised as other ports.
 </dd>
+<dt>
+	<code>mips64, mips64le</code> (64-bit MIPS big- and little-endian)
+</dt>
+<dd>
+	Supports Linux binaries. New in 1.6 and not as well excercised as other ports.
+</dd>
 </dl>
 
 <p>
@@ -87,6 +93,17 @@ The full set of supported combinations is listed in the discussion of
 <a href="#environment">environment variables</a> below.
 </p>
 
+<p>
+See the main installation page for the <a href="/doc/install#requirements">overall system requirements</a>.
+The following additional constraints apply to systems that can be built only from source:
+</p>
+
+<ul>
+<li>For Linux on PowerPC 64-bit, the minimum supported kernel version is 2.6.37, meaning that
+Go does not support CentOS 6 on these systems.
+</li>
+</ul>
+
 </div>
 
 <h2 id="go14">Install Go compiler binaries</h2>
@@ -112,7 +129,7 @@ location).
 
 <p>
 If you want to install Go 1.5 on a system that is not supported by Go 1.4 (such
-as <code>linux/ppc64</code>) you can either use
+as <code>linux/ppc64</code> and <code>linux/mips64le</code>) you can either use
 <a href="/src/bootstrap.bash">bootstrap.bash</a> on a system that can bootstrap Go
 1.5 normally, or bootstrap with gccgo 5.
 </p>
@@ -133,7 +150,7 @@ and used as <code>GOROOT_BOOTSTRAP</code> to bootstrap a local build.
 </p>
 
 <p>
-To use gccgo, you need to arrange for <code>$GOROOT_BOOSTRAP/bin/go</code> to be
+To use gccgo, you need to arrange for <code>$GOROOT_BOOTSTRAP/bin/go</code> to be
 the go tool that comes as part of gccgo 5. For example on Ubuntu Vivid:
 </p>
 
@@ -156,6 +173,21 @@ follow the instructions on the
 <a href="http://git-scm.com/downloads">Git downloads</a> page.
 </p>
 
+<h2 id="ccompiler">(Optional) Install a C compiler</h2>
+
+<p>
+To build a Go installation
+with <code><a href="/cmd/cgo">cgo</a></code> support, which permits Go
+programs to import C libraries, a C compiler such as <code>gcc</code>
+or <code>clang</code> must be installed first. Do this using whatever
+installation method is standard on the system.
+</p>
+
+<p>
+To build without <code>cgo</code>, set the environment variable
+<code>CGO_ENABLED=0</code> before running <code>all.bash</code> or
+<code>make.bash</code>.
+</p>
 
 <h2 id="fetch">Fetch the repository</h2>
 
@@ -167,7 +199,7 @@ Then clone the repository and check out the latest release tag:</p>
 <pre>
 $ git clone https://go.googlesource.com/go
 $ cd go
-$ git checkout go1.5.2
+$ git checkout go1.5.3
 </pre>
 
 <h2 id="head">(Optional) Switch to the master branch</h2>
@@ -346,7 +378,7 @@ New releases are announced on the
 <a href="//groups.google.com/group/golang-announce">golang-announce</a>
 mailing list.
 Each announcement mentions the latest release tag, for instance,
-<code>go1.5.2</code>.
+<code>go1.5.3</code>.
 </p>
 
 <p>
@@ -405,7 +437,8 @@ Choices for <code>$GOOS</code> are
 Choices for <code>$GOARCH</code> are
 <code>amd64</code> (64-bit x86, the most mature port),
 <code>386</code> (32-bit x86), <code>arm</code> (32-bit ARM), <code>arm64</code> (64-bit ARM),
-<code>ppc64le</code> (PowerPC 64-bit, little-endian), and <code>ppc64</code> (PowerPC 64-bit, big-endian).
+<code>ppc64le</code> (PowerPC 64-bit, little-endian), <code>ppc64</code> (PowerPC 64-bit, big-endian),
+<code>mips64le</code> (MIPS 64-bit, little-endian), and <code>mips64</code> (MIPS 64-bit, big-endian).
 The valid combinations of <code>$GOOS</code> and <code>$GOARCH</code> are:
 <table cellpadding="0">
 <tr>
@@ -454,6 +487,12 @@ The valid combinations of <code>$GOOS</code> and <code>$GOARCH</code> are:
 <td></td><td><code>linux</code></td> <td><code>ppc64le</code></td>
 </tr>
 <tr>
+<td></td><td><code>linux</code></td> <td><code>mips64</code></td>
+</tr>
+<tr>
+<td></td><td><code>linux</code></td> <td><code>mips64le</code></td>
+</tr>
+<tr>
 <td></td><td><code>netbsd</code></td> <td><code>386</code></td>
 </tr>
 <tr>
diff --git a/doc/install.html b/doc/install.html
index e9f0f0d..96a7672 100644
--- a/doc/install.html
+++ b/doc/install.html
@@ -48,7 +48,7 @@ If your OS or architecture is not on the list, you may be able to
 </tr>
 <tr><td colspan="3"><hr></td></tr>
 <tr><td>FreeBSD 8-STABLE or later</td> <td>amd64</td> <td>Debian GNU/kFreeBSD not supported</td></tr>
-<tr><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm</td> <td>CentOS/RHEL 5.x not supported; install from source for ARM</td></tr>
+<tr><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm</td> <td>CentOS/RHEL 5.x not supported</td></tr>
 <tr><td>Mac OS X 10.7 or later</td> <td>amd64</td> <td>use the clang or gcc<sup>†</sup> that comes with Xcode<sup>‡</sup></td></tr>
 <tr><td>Windows XP or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>†</sup>. No need for cygwin or msys.</td></tr>
 </table>
@@ -220,19 +220,29 @@ and building a simple program, as follows.
 
 <p>
 Create a directory to contain your <a href="code.html#Workspaces">workspace</a>,
-<code>$HOME/work</code> for example, and set the <code>GOPATH</code> environment
+<code class="testUnix">$HOME/work</code>
+<code class="testWindows" style="display: none">%HOME%\work</code>
+for example, and set the <code>GOPATH</code> environment
 variable to point to that location.
 </p>
 
-<pre>
+<pre class="testUnix">
 $ <b>export GOPATH=$HOME/work</b>
 </pre>
 
+<pre class="testWindows" style="display: none">
+C:\> <b>set GOPATH=%HOME%\work</b>
+</pre>
+
 <p>
+<span class="testUnix">
 You should put the above command in your shell startup script
-(<code>$HOME/.profile</code> for example) or, if you use Windows,
-follow the <a href="#windows_env">instructions above</a> to set the
+(<code>$HOME/.profile</code> for example).
+</span>
+<span class="testWindows">
+On Windows, follow the <a href="#windows_env">instructions above</a> to set the
 <code>GOPATH</code> environment variable on your system.
+</span>
 </p>
 
 <p>
@@ -256,21 +266,30 @@ func main() {
 Then compile it with the <code>go</code> tool:
 </p>
 
-<pre>
+<pre class="testUnix">
 $ <b>go install github.com/user/hello</b>
 </pre>
 
+<pre class="testWindows" style="display: none">
+C:\> <b>go install github.com/user/hello</b>
+</pre>
+
 <p>
-The above command will put an executable command named <code>hello</code> 
+The command above will put an executable command named <code>hello</code> 
 (or <code>hello.exe</code>) inside the <code>bin</code> directory of your workspace.
 Execute the command to see the greeting:
 </p>
 
-<pre>
+<pre class="testUnix">
 $ <b>$GOPATH/bin/hello</b>
 hello, world
 </pre>
 
+<pre class="testWindows" style="display: none">
+C:\> <b>%GOPATH%\bin\hello</b>
+hello, world
+</pre>
+
 <p>
 If you see the "hello, world" message then your Go installation is working.
 </p>
diff --git a/doc/play/pi.go b/doc/play/pi.go
index f2f5dca..f61884e 100644
--- a/doc/play/pi.go
+++ b/doc/play/pi.go
@@ -1,5 +1,5 @@
 // Concurrent computation of pi.
-// See http://goo.gl/ZuTZM.
+// See https://goo.gl/la6Kli.
 //
 // This demonstrates Go's ability to handle
 // large numbers of concurrent processes.
diff --git a/doc/progs/run.go b/doc/progs/run.go
old mode 100755
new mode 100644
diff --git a/lib/time/update.bash b/lib/time/update.bash
index 3ef1df5..86b1f21 100755
--- a/lib/time/update.bash
+++ b/lib/time/update.bash
@@ -5,10 +5,11 @@
 
 # This script rebuilds the time zone files using files
 # downloaded from the ICANN/IANA distribution.
+# Consult http://www.iana.org/time-zones for the latest versions.
 
 # Versions to use.
-CODE=2015e
-DATA=2015e
+CODE=2016a
+DATA=2016a
 
 set -e
 rm -rf work
diff --git a/lib/time/zoneinfo.zip b/lib/time/zoneinfo.zip
index 73c30b4..0207d6b 100644
Binary files a/lib/time/zoneinfo.zip and b/lib/time/zoneinfo.zip differ
diff --git a/misc/cgo/errors/issue11097a.go b/misc/cgo/errors/issue11097a.go
new file mode 100644
index 0000000..4508213
--- /dev/null
+++ b/misc/cgo/errors/issue11097a.go
@@ -0,0 +1,15 @@
+// Copyright 2015 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
+
+/*
+//enum test { foo, bar };
+*/
+import "C"
+
+func main() {
+	var a = C.enum_test(1) // ERROR HERE
+	_ = a
+}
diff --git a/misc/cgo/errors/issue11097b.go b/misc/cgo/errors/issue11097b.go
new file mode 100644
index 0000000..68c5c7c
--- /dev/null
+++ b/misc/cgo/errors/issue11097b.go
@@ -0,0 +1,15 @@
+// Copyright 2015 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
+
+/*
+//enum test { foo, bar };
+*/
+import "C"
+
+func main() {
+	p := new(C.enum_test) // ERROR HERE
+	_ = p
+}
diff --git a/misc/cgo/errors/issue13129.go b/misc/cgo/errors/issue13129.go
new file mode 100644
index 0000000..942d2f7
--- /dev/null
+++ b/misc/cgo/errors/issue13129.go
@@ -0,0 +1,14 @@
+// Copyright 2015 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 13129: used to output error about C.unsignedshort with CC=clang
+
+package main
+
+import "C"
+
+func main() {
+	var x C.ushort
+	x = int(0) // ERROR HERE
+}
diff --git a/misc/cgo/errors/issue13423.go b/misc/cgo/errors/issue13423.go
new file mode 100644
index 0000000..6b2ad58
--- /dev/null
+++ b/misc/cgo/errors/issue13423.go
@@ -0,0 +1,12 @@
+// Copyright 2015 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
+
+// #include <stdio.h>
+import "C"
+
+func main() {
+	_ = C.fopen() // ERROR HERE
+}
diff --git a/misc/cgo/errors/issue13635.go b/misc/cgo/errors/issue13635.go
new file mode 100644
index 0000000..689e958
--- /dev/null
+++ b/misc/cgo/errors/issue13635.go
@@ -0,0 +1,24 @@
+// Copyright 2015 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 13635: used to output error about C.unsignedchar.
+// This test tests all such types.
+
+package pkg
+
+import "C"
+
+func main() {
+	var (
+		_ C.uchar         = "uc"  // ERROR HERE
+		_ C.schar         = "sc"  // ERROR HERE
+		_ C.ushort        = "us"  // ERROR HERE
+		_ C.uint          = "ui"  // ERROR HERE
+		_ C.ulong         = "ul"  // ERROR HERE
+		_ C.longlong      = "ll"  // ERROR HERE
+		_ C.ulonglong     = "ull" // ERROR HERE
+		_ C.complexfloat  = "cf"  // ERROR HERE
+		_ C.complexdouble = "cd"  // ERROR HERE
+	)
+}
diff --git a/misc/cgo/errors/ptr.go b/misc/cgo/errors/ptr.go
new file mode 100644
index 0000000..834cde9
--- /dev/null
+++ b/misc/cgo/errors/ptr.go
@@ -0,0 +1,513 @@
+// Copyright 2015 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.
+
+// Tests that cgo detects invalid pointer passing at runtime.
+
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"sync"
+)
+
+// ptrTest is the tests without the boilerplate.
+type ptrTest struct {
+	name      string   // for reporting
+	c         string   // the cgo comment
+	imports   []string // a list of imports
+	support   string   // supporting functions
+	body      string   // the body of the main function
+	extra     []extra  // extra files
+	fail      bool     // whether the test should fail
+	expensive bool     // whether the test requires the expensive check
+}
+
+type extra struct {
+	name     string
+	contents string
+}
+
+var ptrTests = []ptrTest{
+	{
+		// Passing a pointer to a struct that contains a Go pointer.
+		name: "ptr1",
+		c:    `typedef struct s { int *p; } s; void f(s *ps) {}`,
+		body: `C.f(&C.s{new(C.int)})`,
+		fail: true,
+	},
+	{
+		// Passing a pointer to a struct that contains a Go pointer.
+		name: "ptr2",
+		c:    `typedef struct s { int *p; } s; void f(s *ps) {}`,
+		body: `p := &C.s{new(C.int)}; C.f(p)`,
+		fail: true,
+	},
+	{
+		// Passing a pointer to an int field of a Go struct
+		// that (irrelevantly) contains a Go pointer.
+		name: "ok1",
+		c:    `struct s { int i; int *p; }; void f(int *p) {}`,
+		body: `p := &C.struct_s{i: 0, p: new(C.int)}; C.f(&p.i)`,
+		fail: false,
+	},
+	{
+		// Passing a pointer to a pointer field of a Go struct.
+		name: "ptr-field",
+		c:    `struct s { int i; int *p; }; void f(int **p) {}`,
+		body: `p := &C.struct_s{i: 0, p: new(C.int)}; C.f(&p.p)`,
+		fail: true,
+	},
+	{
+		// Passing a pointer to a pointer field of a Go
+		// struct, where the field does not contain a Go
+		// pointer, but another field (irrelevantly) does.
+		name: "ptr-field-ok",
+		c:    `struct s { int *p1; int *p2; }; void f(int **p) {}`,
+		body: `p := &C.struct_s{p1: nil, p2: new(C.int)}; C.f(&p.p1)`,
+		fail: false,
+	},
+	{
+		// Passing the address of a slice with no Go pointers.
+		name:    "slice-ok-1",
+		c:       `void f(void **p) {}`,
+		imports: []string{"unsafe"},
+		body:    `s := []unsafe.Pointer{nil}; C.f(&s[0])`,
+		fail:    false,
+	},
+	{
+		// Passing the address of a slice with a Go pointer.
+		name:    "slice-ptr-1",
+		c:       `void f(void **p) {}`,
+		imports: []string{"unsafe"},
+		body:    `i := 0; s := []unsafe.Pointer{unsafe.Pointer(&i)}; C.f(&s[0])`,
+		fail:    true,
+	},
+	{
+		// Passing the address of a slice with a Go pointer,
+		// where we are passing the address of an element that
+		// is not a Go pointer.
+		name:    "slice-ptr-2",
+		c:       `void f(void **p) {}`,
+		imports: []string{"unsafe"},
+		body:    `i := 0; s := []unsafe.Pointer{nil, unsafe.Pointer(&i)}; C.f(&s[0])`,
+		fail:    true,
+	},
+	{
+		// Passing the address of a slice that is an element
+		// in a struct only looks at the slice.
+		name:    "slice-ok-2",
+		c:       `void f(void **p) {}`,
+		imports: []string{"unsafe"},
+		support: `type S struct { p *int; s []unsafe.Pointer }`,
+		body:    `i := 0; p := &S{p:&i, s:[]unsafe.Pointer{nil}}; C.f(&p.s[0])`,
+		fail:    false,
+	},
+	{
+		// Passing the address of a slice of an array that is
+		// an element in a struct, with a type conversion.
+		name:    "slice-ok-3",
+		c:       `void f(void* p) {}`,
+		imports: []string{"unsafe"},
+		support: `type S struct { p *int; a [4]byte }`,
+		body:    `i := 0; p := &S{p:&i}; s := p.a[:]; C.f(unsafe.Pointer(&s[0]))`,
+		fail:    false,
+	},
+	{
+		// Passing the address of a static variable with no
+		// pointers doesn't matter.
+		name:    "varok",
+		c:       `void f(char** parg) {}`,
+		support: `var hello = [...]C.char{'h', 'e', 'l', 'l', 'o'}`,
+		body:    `parg := [1]*C.char{&hello[0]}; C.f(&parg[0])`,
+		fail:    false,
+	},
+	{
+		// Passing the address of a static variable with
+		// pointers does matter.
+		name:    "var",
+		c:       `void f(char*** parg) {}`,
+		support: `var hello = [...]*C.char{new(C.char)}`,
+		body:    `parg := [1]**C.char{&hello[0]}; C.f(&parg[0])`,
+		fail:    true,
+	},
+	{
+		// Storing a Go pointer into C memory should fail.
+		name: "barrier",
+		c: `#include <stdlib.h>
+                    char **f1() { return malloc(sizeof(char*)); }
+                    void f2(char **p) {}`,
+		body:      `p := C.f1(); *p = new(C.char); C.f2(p)`,
+		fail:      true,
+		expensive: true,
+	},
+	{
+		// Storing a Go pointer into C memory by assigning a
+		// large value should fail.
+		name: "barrier-struct",
+		c: `#include <stdlib.h>
+                    struct s { char *a[10]; };
+                    struct s *f1() { return malloc(sizeof(struct s)); }
+                    void f2(struct s *p) {}`,
+		body:      `p := C.f1(); p.a = [10]*C.char{new(C.char)}; C.f2(p)`,
+		fail:      true,
+		expensive: true,
+	},
+	{
+		// Storing a Go pointer into C memory using a slice
+		// copy should fail.
+		name: "barrier-slice",
+		c: `#include <stdlib.h>
+                    struct s { char *a[10]; };
+                    struct s *f1() { return malloc(sizeof(struct s)); }
+                    void f2(struct s *p) {}`,
+		body:      `p := C.f1(); copy(p.a[:], []*C.char{new(C.char)}); C.f2(p)`,
+		fail:      true,
+		expensive: true,
+	},
+	{
+		// A very large value uses a GC program, which is a
+		// different code path.
+		name: "barrier-gcprog-array",
+		c: `#include <stdlib.h>
+                    struct s { char *a[32769]; };
+                    struct s *f1() { return malloc(sizeof(struct s)); }
+                    void f2(struct s *p) {}`,
+		body:      `p := C.f1(); p.a = [32769]*C.char{new(C.char)}; C.f2(p)`,
+		fail:      true,
+		expensive: true,
+	},
+	{
+		// Similar case, with a source on the heap.
+		name: "barrier-gcprog-array-heap",
+		c: `#include <stdlib.h>
+                    struct s { char *a[32769]; };
+                    struct s *f1() { return malloc(sizeof(struct s)); }
+                    void f2(struct s *p) {}
+                    void f3(void *p) {}`,
+		imports:   []string{"unsafe"},
+		body:      `p := C.f1(); n := &[32769]*C.char{new(C.char)}; p.a = *n; C.f2(p); n[0] = nil; C.f3(unsafe.Pointer(n))`,
+		fail:      true,
+		expensive: true,
+	},
+	{
+		// A GC program with a struct.
+		name: "barrier-gcprog-struct",
+		c: `#include <stdlib.h>
+                    struct s { char *a[32769]; };
+                    struct s2 { struct s f; };
+                    struct s2 *f1() { return malloc(sizeof(struct s2)); }
+                    void f2(struct s2 *p) {}`,
+		body:      `p := C.f1(); p.f = C.struct_s{[32769]*C.char{new(C.char)}}; C.f2(p)`,
+		fail:      true,
+		expensive: true,
+	},
+	{
+		// Similar case, with a source on the heap.
+		name: "barrier-gcprog-struct-heap",
+		c: `#include <stdlib.h>
+                    struct s { char *a[32769]; };
+                    struct s2 { struct s f; };
+                    struct s2 *f1() { return malloc(sizeof(struct s2)); }
+                    void f2(struct s2 *p) {}
+                    void f3(void *p) {}`,
+		imports:   []string{"unsafe"},
+		body:      `p := C.f1(); n := &C.struct_s{[32769]*C.char{new(C.char)}}; p.f = *n; C.f2(p); n.a[0] = nil; C.f3(unsafe.Pointer(n))`,
+		fail:      true,
+		expensive: true,
+	},
+	{
+		// Exported functions may not return Go pointers.
+		name: "export1",
+		c:    `extern unsigned char *GoFn();`,
+		support: `//export GoFn
+                          func GoFn() *byte { return new(byte) }`,
+		body: `C.GoFn()`,
+		fail: true,
+	},
+	{
+		// Returning a C pointer is fine.
+		name: "exportok",
+		c: `#include <stdlib.h>
+                    extern unsigned char *GoFn();`,
+		support: `//export GoFn
+                          func GoFn() *byte { return (*byte)(C.malloc(1)) }`,
+		body: `C.GoFn()`,
+	},
+	{
+		// Passing a Go string is fine.
+		name: "pass-string",
+		c: `#include <stddef.h>
+                    typedef struct { const char *p; ptrdiff_t n; } gostring;
+                    gostring f(gostring s) { return s; }`,
+		imports: []string{"unsafe"},
+		body:    `s := "a"; r := C.f(*(*C.gostring)(unsafe.Pointer(&s))); if *(*string)(unsafe.Pointer(&r)) != s { panic(r) }`,
+	},
+	{
+		// Passing a slice of Go strings fails.
+		name:    "pass-string-slice",
+		c:       `void f(void *p) {}`,
+		imports: []string{"strings", "unsafe"},
+		support: `type S struct { a [1]string }`,
+		body:    `s := S{a:[1]string{strings.Repeat("a", 2)}}; C.f(unsafe.Pointer(&s.a[0]))`,
+		fail:    true,
+	},
+	{
+		// Exported functions may not return strings.
+		name:    "ret-string",
+		c:       `extern void f();`,
+		imports: []string{"strings"},
+		support: `//export GoStr
+                          func GoStr() string { return strings.Repeat("a", 2) }`,
+		body: `C.f()`,
+		extra: []extra{
+			{
+				"call.c",
+				`#include <stddef.h>
+                                 typedef struct { const char *p; ptrdiff_t n; } gostring;
+                                 extern gostring GoStr();
+                                 void f() { GoStr(); }`,
+			},
+		},
+		fail: true,
+	},
+}
+
+func main() {
+	os.Exit(doTests())
+}
+
+func doTests() int {
+	gopath, err := ioutil.TempDir("", "cgoerrors")
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		return 2
+	}
+	defer os.RemoveAll(gopath)
+
+	if err := os.MkdirAll(filepath.Join(gopath, "src"), 0777); err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		return 2
+	}
+
+	workers := runtime.NumCPU() + 1
+
+	var wg sync.WaitGroup
+	c := make(chan int)
+	errs := make(chan int)
+	for i := 0; i < workers; i++ {
+		wg.Add(1)
+		go func() {
+			worker(gopath, c, errs)
+			wg.Done()
+		}()
+	}
+
+	for i := range ptrTests {
+		c <- i
+	}
+	close(c)
+
+	go func() {
+		wg.Wait()
+		close(errs)
+	}()
+
+	tot := 0
+	for e := range errs {
+		tot += e
+	}
+	return tot
+}
+
+func worker(gopath string, c, errs chan int) {
+	e := 0
+	for i := range c {
+		if !doOne(gopath, i) {
+			e++
+		}
+	}
+	if e > 0 {
+		errs <- e
+	}
+}
+
+func doOne(gopath string, i int) bool {
+	t := &ptrTests[i]
+
+	dir := filepath.Join(gopath, "src", fmt.Sprintf("dir%d", i))
+	if err := os.Mkdir(dir, 0777); err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		return false
+	}
+
+	name := filepath.Join(dir, fmt.Sprintf("t%d.go", i))
+	f, err := os.Create(name)
+	if err != nil {
+		fmt.Fprintln(os.Stderr, err)
+		return false
+	}
+
+	b := bufio.NewWriter(f)
+	fmt.Fprintln(b, `package main`)
+	fmt.Fprintln(b)
+	fmt.Fprintln(b, `/*`)
+	fmt.Fprintln(b, t.c)
+	fmt.Fprintln(b, `*/`)
+	fmt.Fprintln(b, `import "C"`)
+	fmt.Fprintln(b)
+	for _, imp := range t.imports {
+		fmt.Fprintln(b, `import "`+imp+`"`)
+	}
+	if len(t.imports) > 0 {
+		fmt.Fprintln(b)
+	}
+	if len(t.support) > 0 {
+		fmt.Fprintln(b, t.support)
+		fmt.Fprintln(b)
+	}
+	fmt.Fprintln(b, `func main() {`)
+	fmt.Fprintln(b, t.body)
+	fmt.Fprintln(b, `}`)
+
+	if err := b.Flush(); err != nil {
+		fmt.Fprintf(os.Stderr, "flushing %s: %v\n", name, err)
+		return false
+	}
+	if err := f.Close(); err != nil {
+		fmt.Fprintf(os.Stderr, "closing %s: %v\n", name, err)
+		return false
+	}
+
+	for _, e := range t.extra {
+		if err := ioutil.WriteFile(filepath.Join(dir, e.name), []byte(e.contents), 0644); err != nil {
+			fmt.Fprintf(os.Stderr, "writing %s: %v\n", e.name, err)
+			return false
+		}
+	}
+
+	ok := true
+
+	cmd := exec.Command("go", "build")
+	cmd.Dir = dir
+	cmd.Env = addEnv("GOPATH", gopath)
+	buf, err := cmd.CombinedOutput()
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "test %s failed to build: %v\n%s", t.name, err, buf)
+		return false
+	}
+
+	exe := filepath.Join(dir, filepath.Base(dir))
+	cmd = exec.Command(exe)
+	cmd.Dir = dir
+
+	if t.expensive {
+		cmd.Env = cgocheckEnv("1")
+		buf, err := cmd.CombinedOutput()
+		if err != nil {
+			var errbuf bytes.Buffer
+			if t.fail {
+				fmt.Fprintf(&errbuf, "test %s marked expensive but failed when not expensive: %v\n", t.name, err)
+			} else {
+				fmt.Fprintf(&errbuf, "test %s failed unexpectedly with GODEBUG=cgocheck=1: %v\n", t.name, err)
+			}
+			reportTestOutput(&errbuf, t.name, buf)
+			os.Stderr.Write(errbuf.Bytes())
+			ok = false
+		}
+
+		cmd = exec.Command(exe)
+		cmd.Dir = dir
+	}
+
+	if t.expensive {
+		cmd.Env = cgocheckEnv("2")
+	}
+
+	buf, err = cmd.CombinedOutput()
+
+	if t.fail {
+		if err == nil {
+			var errbuf bytes.Buffer
+			fmt.Fprintf(&errbuf, "test %s did not fail as expected\n", t.name)
+			reportTestOutput(&errbuf, t.name, buf)
+			os.Stderr.Write(errbuf.Bytes())
+			ok = false
+		} else if !bytes.Contains(buf, []byte("Go pointer")) {
+			var errbuf bytes.Buffer
+			fmt.Fprintf(&errbuf, "test %s output does not contain expected error (failed with %v)\n", t.name, err)
+			reportTestOutput(&errbuf, t.name, buf)
+			os.Stderr.Write(errbuf.Bytes())
+			ok = false
+		}
+	} else {
+		if err != nil {
+			var errbuf bytes.Buffer
+			fmt.Fprintf(&errbuf, "test %s failed unexpectedly: %v\n", t.name, err)
+			reportTestOutput(&errbuf, t.name, buf)
+			os.Stderr.Write(errbuf.Bytes())
+			ok = false
+		}
+
+		if !t.expensive && ok {
+			// Make sure it passes with the expensive checks.
+			cmd := exec.Command(exe)
+			cmd.Dir = dir
+			cmd.Env = cgocheckEnv("2")
+			buf, err := cmd.CombinedOutput()
+			if err != nil {
+				var errbuf bytes.Buffer
+				fmt.Fprintf(&errbuf, "test %s failed unexpectedly with expensive checks: %v\n", t.name, err)
+				reportTestOutput(&errbuf, t.name, buf)
+				os.Stderr.Write(errbuf.Bytes())
+				ok = false
+			}
+		}
+	}
+
+	if t.fail && ok {
+		cmd = exec.Command(exe)
+		cmd.Dir = dir
+		cmd.Env = cgocheckEnv("0")
+		buf, err := cmd.CombinedOutput()
+		if err != nil {
+			var errbuf bytes.Buffer
+			fmt.Fprintf(&errbuf, "test %s failed unexpectedly with GODEBUG=cgocheck=0: %v\n", t.name, err)
+			reportTestOutput(&errbuf, t.name, buf)
+			os.Stderr.Write(errbuf.Bytes())
+			ok = false
+		}
+	}
+
+	return ok
+}
+
+func reportTestOutput(w io.Writer, name string, buf []byte) {
+	fmt.Fprintf(w, "=== test %s output ===\n", name)
+	fmt.Fprintf(w, "%s", buf)
+	fmt.Fprintf(w, "=== end of test %s output ===\n", name)
+}
+
+func cgocheckEnv(val string) []string {
+	return addEnv("GODEBUG", "cgocheck="+val)
+}
+
+func addEnv(key, val string) []string {
+	env := []string{key + "=" + val}
+	look := key + "="
+	for _, e := range os.Environ() {
+		if !strings.HasPrefix(e, look) {
+			env = append(env, e)
+		}
+	}
+	return env
+}
diff --git a/misc/cgo/errors/test.bash b/misc/cgo/errors/test.bash
index c880ad6..cd358a1 100755
--- a/misc/cgo/errors/test.bash
+++ b/misc/cgo/errors/test.bash
@@ -11,6 +11,12 @@ check() {
 		echo 1>&2 misc/cgo/errors/test.bash: BUG: cannot find ERROR HERE in $file
 		exit 1
 	fi
+	expect $file $file:$line:
+}
+
+expect() {
+	file=$1
+	shift
 	if go build $file >errs 2>&1; then
 		echo 1>&2 misc/cgo/errors/test.bash: BUG: expected cgo to fail but it succeeded
 		exit 1
@@ -19,11 +25,13 @@ check() {
 		echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error output but saw none
 		exit 1
 	fi
-	if ! fgrep $file:$line: errs >/dev/null 2>&1; then
-		echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error on line $line but saw:
-		cat 1>&2 errs
-		exit 1
-	fi
+	for error; do
+		if ! fgrep $error errs >/dev/null 2>&1; then
+			echo 1>&2 misc/cgo/errors/test.bash: BUG: expected error output to contain \"$error\" but saw:
+			cat 1>&2 errs
+			exit 1
+		fi
+	done
 }
 
 check err1.go
@@ -31,6 +39,15 @@ check err2.go
 check err3.go
 check issue7757.go
 check issue8442.go
+check issue11097a.go
+check issue11097b.go
+expect issue13129.go C.ushort
+check issue13423.go
+expect issue13635.go C.uchar C.schar C.ushort C.uint C.ulong C.longlong C.ulonglong C.complexfloat C.complexdouble
+
+if ! go run ptr.go; then
+	exit 1
+fi
 
 rm -rf errs _obj
 exit 0
diff --git a/misc/cgo/gmp/pi.go b/misc/cgo/gmp/pi.go
index 1914cf2..a189375 100644
--- a/misc/cgo/gmp/pi.go
+++ b/misc/cgo/gmp/pi.go
@@ -1,41 +1,8 @@
-// +build ignore
-
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
+// Copyright 2009 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.
 
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * based on pidigits.c (by Paolo Bonzini & Sean Bartlett,
- *                      modified by Michael Mellor)
- */
+// +build ignore
 
 package main
 
diff --git a/misc/cgo/life/main.go b/misc/cgo/life/main.go
index 725e10f..c17cd6c 100644
--- a/misc/cgo/life/main.go
+++ b/misc/cgo/life/main.go
@@ -4,7 +4,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build ignore
+// +build test_run
 
 // Run the game of life in C using Go for parallelization.
 
diff --git a/misc/cgo/stdio/chain.go b/misc/cgo/stdio/chain.go
index a55cefa..1256133 100644
--- a/misc/cgo/stdio/chain.go
+++ b/misc/cgo/stdio/chain.go
@@ -4,16 +4,17 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build ignore
+// +build test_run
 
 // Pass numbers along a chain of threads.
 
 package main
 
 import (
-	"../stdio"
 	"runtime"
 	"strconv"
+
+	"../stdio"
 )
 
 const N = 10
diff --git a/misc/cgo/stdio/fib.go b/misc/cgo/stdio/fib.go
index 981ffeb..eb43cf5 100644
--- a/misc/cgo/stdio/fib.go
+++ b/misc/cgo/stdio/fib.go
@@ -4,7 +4,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build ignore
+// +build test_run
 
 // Compute Fibonacci numbers with two goroutines
 // that pass integers back and forth.  No actual
@@ -14,9 +14,10 @@
 package main
 
 import (
-	"../stdio"
 	"runtime"
 	"strconv"
+
+	"../stdio"
 )
 
 func fibber(c, out chan int64, i int64) {
diff --git a/misc/cgo/stdio/hello.go b/misc/cgo/stdio/hello.go
index 9cfeefb..60c0304 100644
--- a/misc/cgo/stdio/hello.go
+++ b/misc/cgo/stdio/hello.go
@@ -4,7 +4,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build ignore
+// +build test_run
 
 package main
 
diff --git a/misc/cgo/test/buildid_linux.go b/misc/cgo/test/buildid_linux.go
index a3a86ed..2641dd5 100644
--- a/misc/cgo/test/buildid_linux.go
+++ b/misc/cgo/test/buildid_linux.go
@@ -22,7 +22,7 @@ func testBuildID(t *testing.T) {
 		if os.IsNotExist(err) {
 			t.Skip("no /proc/self/exe")
 		}
-		t.Fatalf("opening /proc/self/exe: ", err)
+		t.Fatal("opening /proc/self/exe: ", err)
 	}
 	defer f.Close()
 
diff --git a/misc/cgo/test/callback.go b/misc/cgo/test/callback.go
index bff770f..21d1df5 100644
--- a/misc/cgo/test/callback.go
+++ b/misc/cgo/test/callback.go
@@ -12,6 +12,7 @@ void callPanic(void);
 int callGoReturnVal(void);
 int returnAfterGrow(void);
 int returnAfterGrowFromGo(void);
+void callGoWithString(void);
 */
 import "C"
 
@@ -19,20 +20,47 @@ import (
 	"path"
 	"runtime"
 	"strings"
+	"sync"
 	"testing"
 	"unsafe"
 )
 
+// Pass a func value from nestedCall to goCallback using an integer token.
+var callbackMutex sync.Mutex
+var callbackToken int
+var callbackFuncs = make(map[int]func())
+
 // nestedCall calls into C, back into Go, and finally to f.
 func nestedCall(f func()) {
-	// NOTE: Depends on representation of f.
 	// callback(x) calls goCallback(x)
-	C.callback(*(*unsafe.Pointer)(unsafe.Pointer(&f)))
+	callbackMutex.Lock()
+	callbackToken++
+	i := callbackToken
+	callbackFuncs[i] = f
+	callbackMutex.Unlock()
+
+	// Pass the address of i because the C function was written to
+	// take a pointer.  We could pass an int if we felt like
+	// rewriting the C code.
+	C.callback(unsafe.Pointer(&i))
+
+	callbackMutex.Lock()
+	delete(callbackFuncs, i)
+	callbackMutex.Unlock()
 }
 
 //export goCallback
 func goCallback(p unsafe.Pointer) {
-	(*(*func())(unsafe.Pointer(&p)))()
+	i := *(*int)(p)
+
+	callbackMutex.Lock()
+	f := callbackFuncs[i]
+	callbackMutex.Unlock()
+
+	if f == nil {
+		panic("missing callback function")
+	}
+	f()
 }
 
 func testCallback(t *testing.T) {
@@ -151,7 +179,6 @@ func testCallbackCallers(t *testing.T) {
 	pc := make([]uintptr, 100)
 	n := 0
 	name := []string{
-		"test.goCallback",
 		"runtime.call16",
 		"runtime.cgocallbackg1",
 		"runtime.cgocallbackg",
@@ -166,10 +193,10 @@ func testCallbackCallers(t *testing.T) {
 		"runtime.goexit",
 	}
 	if unsafe.Sizeof((*byte)(nil)) == 8 {
-		name[1] = "runtime.call32"
+		name[0] = "runtime.call32"
 	}
 	nestedCall(func() {
-		n = runtime.Callers(2, pc)
+		n = runtime.Callers(4, pc)
 	})
 	if n != len(name) {
 		t.Errorf("expected %d frames, got %d", len(name), n)
@@ -177,7 +204,7 @@ func testCallbackCallers(t *testing.T) {
 	for i := 0; i < n; i++ {
 		f := runtime.FuncForPC(pc[i])
 		if f == nil {
-			t.Fatalf("expected non-nil Func for pc %p", pc[i])
+			t.Fatalf("expected non-nil Func for pc %d", pc[i])
 		}
 		fname := f.Name()
 		// Remove the prepended pathname from automatically
@@ -250,6 +277,22 @@ func goReturnVal() (r C.int) {
 	return
 }
 
+// Test that C can pass in a Go string from a string constant.
+func testCallGoWithString(t *testing.T) {
+	C.callGoWithString()
+	want := "string passed from C to Go"
+	if stringFromGo != want {
+		t.Errorf("string passed through C is %s, want %s", stringFromGo, want)
+	}
+}
+
+var stringFromGo string
+
+//export goWithString
+func goWithString(s string) {
+	stringFromGo = s
+}
+
 func testCallbackStack(t *testing.T) {
 	// Make cgo call and callback with different amount of stack stack available.
 	// We do not do any explicit checks, just ensure that it does not crash.
diff --git a/misc/cgo/test/callback_c.c b/misc/cgo/test/callback_c.c
index 5bb6425..5ae237b 100644
--- a/misc/cgo/test/callback_c.c
+++ b/misc/cgo/test/callback_c.c
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+#include <string.h>
 #include <sys/types.h>
 #include <unistd.h>
 #include "_cgo_export.h"
@@ -80,3 +81,10 @@ returnAfterGrowFromGo(void)
 	return goReturnVal();
 }
 
+void
+callGoWithString(void)
+{
+	extern void goWithString(GoString);
+	const char *str = "string passed from C to Go";
+	goWithString((GoString){str, strlen(str)});
+}
diff --git a/misc/cgo/test/cgo_test.go b/misc/cgo/test/cgo_test.go
index 4060338..48fb6f1 100644
--- a/misc/cgo/test/cgo_test.go
+++ b/misc/cgo/test/cgo_test.go
@@ -62,9 +62,12 @@ func Test8811(t *testing.T)                  { test8811(t) }
 func TestReturnAfterGrow(t *testing.T)       { testReturnAfterGrow(t) }
 func TestReturnAfterGrowFromGo(t *testing.T) { testReturnAfterGrowFromGo(t) }
 func Test9026(t *testing.T)                  { test9026(t) }
+func Test9510(t *testing.T)                  { test9510(t) }
 func Test9557(t *testing.T)                  { test9557(t) }
 func Test10303(t *testing.T)                 { test10303(t, 10) }
 func Test11925(t *testing.T)                 { test11925(t) }
 func Test12030(t *testing.T)                 { test12030(t) }
+func TestGCC68255(t *testing.T)              { testGCC68255(t) }
+func TestCallGoWithString(t *testing.T)      { testCallGoWithString(t) }
 
 func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
diff --git a/misc/cgo/test/cgo_unix_test.go b/misc/cgo/test/cgo_unix_test.go
new file mode 100644
index 0000000..5808e6e
--- /dev/null
+++ b/misc/cgo/test/cgo_unix_test.go
@@ -0,0 +1,11 @@
+// Copyright 2015 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.
+
+// +build !windows
+
+package cgotest
+
+import "testing"
+
+func TestSigaltstack(t *testing.T) { testSigaltstack(t) }
diff --git a/misc/cgo/test/env.go b/misc/cgo/test/env.go
index 8d3ba58..b2081b7 100644
--- a/misc/cgo/test/env.go
+++ b/misc/cgo/test/env.go
@@ -31,7 +31,7 @@ func testSetEnv(t *testing.T) {
 	keyc := C.CString(key)
 	defer C.free(unsafe.Pointer(keyc))
 	v := C.getenv(keyc)
-	if v == (*C.char)(unsafe.Pointer(uintptr(0))) {
+	if uintptr(unsafe.Pointer(v)) == 0 {
 		t.Fatal("getenv returned NULL")
 	}
 	vs := C.GoString(v)
diff --git a/misc/cgo/test/gcc68255.go b/misc/cgo/test/gcc68255.go
new file mode 100644
index 0000000..2c4f931
--- /dev/null
+++ b/misc/cgo/test/gcc68255.go
@@ -0,0 +1,17 @@
+// Copyright 2015 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 cgotest
+
+import (
+	"testing"
+
+	"./gcc68255"
+)
+
+func testGCC68255(t *testing.T) {
+	if !gcc68255.F() {
+		t.Error("C global variable was not initialized")
+	}
+}
diff --git a/misc/cgo/test/gcc68255/a.go b/misc/cgo/test/gcc68255/a.go
new file mode 100644
index 0000000..02e5494
--- /dev/null
+++ b/misc/cgo/test/gcc68255/a.go
@@ -0,0 +1,17 @@
+// Copyright 2015 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 that it's OK to have C code that does nothing other than
+// initialize a global variable.  This used to fail with gccgo.
+
+package gcc68255
+
+/*
+#include "c.h"
+*/
+import "C"
+
+func F() bool {
+	return C.v != nil
+}
diff --git a/misc/cgo/test/gcc68255/c.c b/misc/cgo/test/gcc68255/c.c
new file mode 100644
index 0000000..28cfe72
--- /dev/null
+++ b/misc/cgo/test/gcc68255/c.c
@@ -0,0 +1,8 @@
+// Copyright 2015 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.
+
+static void f(void) {
+}
+
+void (*v)(void) = f;
diff --git a/misc/cgo/test/gcc68255/c.h b/misc/cgo/test/gcc68255/c.h
new file mode 100644
index 0000000..644003e
--- /dev/null
+++ b/misc/cgo/test/gcc68255/c.h
@@ -0,0 +1,5 @@
+// Copyright 2015 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.
+
+extern void (*v)(void);
diff --git a/misc/cgo/test/issue10303.go b/misc/cgo/test/issue10303.go
index ea623d7..dd19dfb 100644
--- a/misc/cgo/test/issue10303.go
+++ b/misc/cgo/test/issue10303.go
@@ -6,6 +6,8 @@
 
 package cgotest
 
+import "runtime"
+
 /*
 typedef int *intptr;
 
@@ -39,6 +41,10 @@ import (
 )
 
 func test10303(t *testing.T, n int) {
+	if runtime.Compiler == "gccgo" {
+		t.Skip("gccgo permits C pointers on the stack")
+	}
+
 	// Run at a few different stack depths just to avoid an unlucky pass
 	// due to variables ending up on different pages.
 	if n > 0 {
diff --git a/misc/cgo/test/issue13402.go b/misc/cgo/test/issue13402.go
new file mode 100644
index 0000000..6e3e24c
--- /dev/null
+++ b/misc/cgo/test/issue13402.go
@@ -0,0 +1,10 @@
+// Copyright 2015 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 cgotest
+
+import "C"
+
+var _ C.complexfloat
+var _ C.complexdouble
diff --git a/misc/cgo/test/issue4029.c b/misc/cgo/test/issue4029.c
new file mode 100644
index 0000000..1ff97ec
--- /dev/null
+++ b/misc/cgo/test/issue4029.c
@@ -0,0 +1,10 @@
+// Copyright 2015 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.
+
+// +build !windows
+
+void call4029(void *arg) {
+	void (*fn)(void) = arg;
+	fn();
+}
diff --git a/misc/cgo/test/issue4029.go b/misc/cgo/test/issue4029.go
index b0385eb..9282725 100644
--- a/misc/cgo/test/issue4029.go
+++ b/misc/cgo/test/issue4029.go
@@ -9,32 +9,35 @@ package cgotest
 /*
 #include <dlfcn.h>
 #cgo linux LDFLAGS: -ldl
+
+extern void call4029(void *arg);
 */
 import "C"
 
 import (
-	"fmt"
 	"testing"
 )
 
+var callbacks int
+
 //export IMPIsOpaque
 func IMPIsOpaque() {
-	fmt.Println("isOpaque")
+	callbacks++
 }
 
 //export IMPInitWithFrame
 func IMPInitWithFrame() {
-	fmt.Println("IInitWithFrame")
+	callbacks++
 }
 
 //export IMPDrawRect
 func IMPDrawRect() {
-	fmt.Println("drawRect:")
+	callbacks++
 }
 
 //export IMPWindowResize
 func IMPWindowResize() {
-	fmt.Println("windowDidResize:")
+	callbacks++
 }
 
 func test4029(t *testing.T) {
@@ -42,6 +45,9 @@ func test4029(t *testing.T) {
 	loadThySelf(t, "IMPDrawRect")
 	loadThySelf(t, "IMPInitWithFrame")
 	loadThySelf(t, "IMPIsOpaque")
+	if callbacks != 4 {
+		t.Errorf("got %d callbacks, expected 4", callbacks)
+	}
 }
 
 func loadThySelf(t *testing.T, symbol string) {
@@ -58,4 +64,5 @@ func loadThySelf(t *testing.T, symbol string) {
 		return
 	}
 	t.Log(symbol, symbol_address)
+	C.call4029(symbol_address)
 }
diff --git a/misc/cgo/test/issue6997_linux.go b/misc/cgo/test/issue6997_linux.go
index 07fd58e..638c3b0 100644
--- a/misc/cgo/test/issue6997_linux.go
+++ b/misc/cgo/test/issue6997_linux.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // Test that pthread_cancel works as expected
-// (NPTL uses SIGRTMIN to implement thread cancellation)
+// (NPTL uses SIGRTMIN to implement thread cancelation)
 // See https://golang.org/issue/6997
 package cgotest
 
@@ -32,7 +32,7 @@ func test6997(t *testing.T) {
 	select {
 	case r = <-c:
 		if r == 0 {
-			t.Error("pthread finished but wasn't cancelled??")
+			t.Error("pthread finished but wasn't canceled??")
 		}
 	case <-time.After(30 * time.Second):
 		t.Error("hung in pthread_cancel/pthread_join")
diff --git a/misc/cgo/test/issue7665.go b/misc/cgo/test/issue7665.go
index 4f36dce..da97131 100644
--- a/misc/cgo/test/issue7665.go
+++ b/misc/cgo/test/issue7665.go
@@ -19,7 +19,7 @@ var bad7665 unsafe.Pointer = C.f7665
 var good7665 uintptr = uintptr(C.f7665)
 
 func test7665(t *testing.T) {
-	if bad7665 == nil || bad7665 != unsafe.Pointer(good7665) {
+	if bad7665 == nil || uintptr(bad7665) != good7665 {
 		t.Errorf("ptrs = %p, %#x, want same non-nil pointer", bad7665, good7665)
 	}
 }
diff --git a/misc/cgo/test/issue7978.go b/misc/cgo/test/issue7978.go
index 094ccc1..e8f340f 100644
--- a/misc/cgo/test/issue7978.go
+++ b/misc/cgo/test/issue7978.go
@@ -110,13 +110,13 @@ func test7978(t *testing.T) {
 	go issue7978go()
 	// test in c code, before callback
 	issue7978wait(0, 1)
-	issue7978check(t, "runtime.cgocall(", "", 1)
+	issue7978check(t, "_Cfunc_issue7978c(", "", 1)
 	// test in go code, during callback
 	issue7978wait(2, 3)
 	issue7978check(t, "test.issue7978cb(", "test.issue7978go", 3)
 	// test in c code, after callback
 	issue7978wait(4, 5)
-	issue7978check(t, "runtime.cgocall(", "runtime.cgocallback", 1)
+	issue7978check(t, "_Cfunc_issue7978c(", "_cgoexpwrap", 1)
 	// test in go code, after return from cgo
 	issue7978wait(6, 7)
 	issue7978check(t, "test.issue7978go(", "", 3)
diff --git a/misc/cgo/test/issue8694.go b/misc/cgo/test/issue8694.go
index 1876f78..ba7a344 100644
--- a/misc/cgo/test/issue8694.go
+++ b/misc/cgo/test/issue8694.go
@@ -22,14 +22,14 @@ func test8694(t *testing.T) {
 		t.Skip("test8694 is disabled on ARM because 5l cannot handle thumb library.")
 	}
 	// Really just testing that this compiles, but check answer anyway.
-	x := complex64(2 + 3i)
+	x := C.complexfloat(2 + 3i)
 	x2 := x * x
 	cx2 := C.complexFloatSquared(x)
 	if cx2 != x2 {
 		t.Errorf("C.complexFloatSquared(%v) = %v, want %v", x, cx2, x2)
 	}
 
-	y := complex128(2 + 3i)
+	y := C.complexdouble(2 + 3i)
 	y2 := y * y
 	cy2 := C.complexDoubleSquared(y)
 	if cy2 != y2 {
diff --git a/misc/cgo/test/issue9400/asm_ppc64x.s b/misc/cgo/test/issue9400/asm_ppc64x.s
index 7dfe37e..9f80087 100644
--- a/misc/cgo/test/issue9400/asm_ppc64x.s
+++ b/misc/cgo/test/issue9400/asm_ppc64x.s
@@ -7,7 +7,7 @@
 
 #include "textflag.h"
 
-TEXT ·RewindAndSetgid(SB),NOSPLIT,$-8-0
+TEXT ·RewindAndSetgid(SB),NOSPLIT|NOFRAME,$0-0
 	// Rewind stack pointer so anything that happens on the stack
 	// will clobber the test pattern created by the caller
 	ADD	$(1024 * 8), R1
diff --git a/misc/cgo/test/issue9510.go b/misc/cgo/test/issue9510.go
new file mode 100644
index 0000000..a940bfb
--- /dev/null
+++ b/misc/cgo/test/issue9510.go
@@ -0,0 +1,24 @@
+// Copyright 2015 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 that we can link together two different cgo packages that both
+// use the same libgcc function.
+
+package cgotest
+
+import (
+	"runtime"
+	"testing"
+
+	"./issue9510a"
+	"./issue9510b"
+)
+
+func test9510(t *testing.T) {
+	if runtime.GOARCH == "arm" {
+		t.Skip("skipping because libgcc may be a Thumb library")
+	}
+	issue9510a.F(1, 1)
+	issue9510b.F(1, 1)
+}
diff --git a/misc/cgo/test/issue9510a/a.go b/misc/cgo/test/issue9510a/a.go
new file mode 100644
index 0000000..1a5224b
--- /dev/null
+++ b/misc/cgo/test/issue9510a/a.go
@@ -0,0 +1,15 @@
+package issue9510a
+
+/*
+static double csquare(double a, double b) {
+	__complex__ double d;
+	__real__ d = a;
+	__imag__ d = b;
+	return __real__ (d * d);
+}
+*/
+import "C"
+
+func F(a, b float64) float64 {
+	return float64(C.csquare(C.double(a), C.double(b)))
+}
diff --git a/misc/cgo/test/issue9510b/b.go b/misc/cgo/test/issue9510b/b.go
new file mode 100644
index 0000000..5016b39
--- /dev/null
+++ b/misc/cgo/test/issue9510b/b.go
@@ -0,0 +1,15 @@
+package issue9510b
+
+/*
+static double csquare(double a, double b) {
+	__complex__ double d;
+	__real__ d = a;
+	__imag__ d = b;
+	return __real__ (d * d);
+}
+*/
+import "C"
+
+func F(a, b float64) float64 {
+	return float64(C.csquare(C.double(a), C.double(b)))
+}
diff --git a/misc/cgo/test/sigaltstack.go b/misc/cgo/test/sigaltstack.go
new file mode 100644
index 0000000..b641ff6
--- /dev/null
+++ b/misc/cgo/test/sigaltstack.go
@@ -0,0 +1,73 @@
+// Copyright 2015 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.
+
+// +build !windows
+
+// Test that the Go runtime still works if C code changes the signal stack.
+
+package cgotest
+
+/*
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static stack_t oss;
+static char signalStack[SIGSTKSZ];
+
+static void changeSignalStack() {
+	stack_t ss;
+	memset(&ss, 0, sizeof ss);
+	ss.ss_sp = signalStack;
+	ss.ss_flags = 0;
+	ss.ss_size = SIGSTKSZ;
+	if (sigaltstack(&ss, &oss) < 0) {
+		perror("sigaltstack");
+		abort();
+	}
+}
+
+static void restoreSignalStack() {
+#if (defined(__x86_64__) || defined(__i386__)) && defined(__APPLE__)
+	// The Darwin C library enforces a minimum that the kernel does not.
+	// This is OK since we allocated this much space in mpreinit,
+	// it was just removed from the buffer by stackalloc.
+	oss.ss_size = MINSIGSTKSZ;
+#endif
+	if (sigaltstack(&oss, NULL) < 0) {
+		perror("sigaltstack restore");
+		abort();
+	}
+}
+
+static int zero() {
+	return 0;
+}
+*/
+import "C"
+
+import (
+	"runtime"
+	"testing"
+)
+
+func testSigaltstack(t *testing.T) {
+	switch {
+	case runtime.GOOS == "solaris", runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64"):
+		t.Skipf("switching signal stack not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
+	case runtime.GOOS == "darwin" && runtime.GOARCH == "386":
+		t.Skipf("sigaltstack fails on darwin/386")
+	}
+
+	C.changeSignalStack()
+	defer C.restoreSignalStack()
+	defer func() {
+		if recover() == nil {
+			t.Error("did not see expected panic")
+		}
+	}()
+	v := 1 / int(C.zero())
+	t.Errorf("unexpected success of division by zero == %d", v)
+}
diff --git a/misc/cgo/testcarchive/main.c b/misc/cgo/testcarchive/main.c
index cc3170d..a90138f 100644
--- a/misc/cgo/testcarchive/main.c
+++ b/misc/cgo/testcarchive/main.c
@@ -2,15 +2,44 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+#include <signal.h>
 #include <stdint.h>
 #include <stdio.h>
+#include <string.h>
 
 #include "p.h"
 #include "libgo.h"
 
+static void (*oldHandler)(int, siginfo_t*, void*);
+
+static void handler(int signo, siginfo_t* info, void* ctxt) {
+	if (oldHandler) {
+		oldHandler(signo, info, ctxt);
+	}
+}
+
 int main(void) {
+	struct sigaction sa;
+	struct sigaction osa;
 	int32_t res;
 
+	// Install our own signal handler.
+	memset(&sa, 0, sizeof sa);
+	sa.sa_sigaction = handler;
+	sigemptyset(&sa.sa_mask);
+	sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
+	memset(&osa, 0, sizeof osa);
+	sigemptyset(&osa.sa_mask);
+	if (sigaction(SIGSEGV, &sa, &osa) < 0) {
+		perror("sigaction");
+		return 2;
+	}
+	if (osa.sa_handler == SIG_DFL || (osa.sa_flags&SA_ONSTACK) == 0) {
+		fprintf(stderr, "Go runtime did not install signal handler\n");
+		return 2;
+	}
+	oldHandler = osa.sa_sigaction;
+
 	if (!DidInitRun()) {
 		fprintf(stderr, "ERROR: buildmode=c-archive init should run\n");
 		return 2;
@@ -21,6 +50,16 @@ int main(void) {
 		return 2;
 	}
 
+	// Make sure our signal handler is still the one in use.
+	if (sigaction(SIGSEGV, NULL, &sa) < 0) {
+		perror("sigaction check");
+		return 2;
+	}
+	if (sa.sa_sigaction != handler) {
+		fprintf(stderr, "ERROR: wrong signal handler: %p != %p\n", sa.sa_sigaction, handler);
+		return 2;
+	}
+
 	res = FromPkg();
 	if (res != 1024) {
 		fprintf(stderr, "ERROR: FromPkg()=%d, want 1024\n", res);
diff --git a/misc/cgo/testcarchive/main2.c b/misc/cgo/testcarchive/main2.c
new file mode 100644
index 0000000..3726977
--- /dev/null
+++ b/misc/cgo/testcarchive/main2.c
@@ -0,0 +1,185 @@
+// Copyright 2015 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 installing a signal handler before the Go code starts.
+// This is a lot like misc/cgo/testcshared/main4.c.
+
+#include <setjmp.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sched.h>
+#include <time.h>
+
+#include "libgo2.h"
+
+static void die(const char* msg) {
+	perror(msg);
+	exit(EXIT_FAILURE);
+}
+
+static volatile sig_atomic_t sigioSeen;
+
+// Use up some stack space.
+static void recur(int i, char *p) {
+	char a[1024];
+
+	*p = '\0';
+	if (i > 0) {
+		recur(i - 1, a);
+	}
+}
+
+// Signal handler that uses up more stack space than a goroutine will have.
+static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
+	char a[1024];
+
+	recur(4, a);
+	sigioSeen = 1;
+}
+
+static jmp_buf jmp;
+static char* nullPointer;
+
+// Signal handler for SIGSEGV on a C thread.
+static void segvHandler(int signo, siginfo_t* info, void* ctxt) {
+	sigset_t mask;
+	int i;
+
+	if (sigemptyset(&mask) < 0) {
+		die("sigemptyset");
+	}
+	if (sigaddset(&mask, SIGSEGV) < 0) {
+		die("sigaddset");
+	}
+	i = sigprocmask(SIG_UNBLOCK, &mask, NULL);
+	if (i != 0) {
+		fprintf(stderr, "sigprocmask: %s\n", strerror(i));
+		exit(EXIT_FAILURE);
+	}
+
+	// Don't try this at home.
+	longjmp(jmp, signo);
+
+	// We should never get here.
+	abort();
+}
+
+// Set up the signal handlers in a high priority constructor,
+// so that they are installed before the Go code starts.
+
+static void init(void) __attribute__ ((constructor (200)));
+
+static void init() {
+	struct sigaction sa;
+
+	memset(&sa, 0, sizeof sa);
+	sa.sa_sigaction = ioHandler;
+	if (sigemptyset(&sa.sa_mask) < 0) {
+		die("sigemptyset");
+	}
+	sa.sa_flags = SA_SIGINFO;
+	if (sigaction(SIGIO, &sa, NULL) < 0) {
+		die("sigaction");
+	}
+
+	sa.sa_sigaction = segvHandler;
+	if (sigaction(SIGSEGV, &sa, NULL) < 0 || sigaction(SIGBUS, &sa, NULL) < 0) {
+		die("sigaction");
+	}
+
+}
+
+int main(int argc, char** argv) {
+	int verbose;
+	sigset_t mask;
+	int i;
+
+	verbose = argc > 1;
+	setvbuf(stdout, NULL, _IONBF, 0);
+
+	// Call setsid so that we can use kill(0, SIGIO) below.
+	// Don't check the return value so that this works both from
+	// a job control shell and from a shell script.
+	setsid();
+
+	if (verbose) {
+		printf("calling RunGoroutines\n");
+	}
+
+	RunGoroutines();
+
+	// Block SIGIO in this thread to make it more likely that it
+	// will be delivered to a goroutine.
+
+	if (verbose) {
+		printf("calling pthread_sigmask\n");
+	}
+
+	if (sigemptyset(&mask) < 0) {
+		die("sigemptyset");
+	}
+	if (sigaddset(&mask, SIGIO) < 0) {
+		die("sigaddset");
+	}
+	i = pthread_sigmask(SIG_BLOCK, &mask, NULL);
+	if (i != 0) {
+		fprintf(stderr, "pthread_sigmask: %s\n", strerror(i));
+		exit(EXIT_FAILURE);
+	}
+
+	if (verbose) {
+		printf("calling kill\n");
+	}
+
+	if (kill(0, SIGIO) < 0) {
+		die("kill");
+	}
+
+	if (verbose) {
+		printf("waiting for sigioSeen\n");
+	}
+
+	// Wait until the signal has been delivered.
+	i = 0;
+	while (!sigioSeen) {
+		if (sched_yield() < 0) {
+			perror("sched_yield");
+		}
+		i++;
+		if (i > 100000) {
+			fprintf(stderr, "looping too long waiting for signal\n");
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	if (verbose) {
+		printf("calling setjmp\n");
+	}
+
+	// Test that a SIGSEGV on this thread is delivered to us.
+	if (setjmp(jmp) == 0) {
+		if (verbose) {
+			printf("triggering SIGSEGV\n");
+		}
+
+		*nullPointer = '\0';
+
+		fprintf(stderr, "continued after address error\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if (verbose) {
+		printf("calling TestSEGV\n");
+	}
+
+	TestSEGV();
+
+	printf("PASS\n");
+	return 0;
+}
diff --git a/misc/cgo/testcarchive/main3.c b/misc/cgo/testcarchive/main3.c
new file mode 100644
index 0000000..11046d0
--- /dev/null
+++ b/misc/cgo/testcarchive/main3.c
@@ -0,0 +1,153 @@
+// Copyright 2015 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 os/signal.Notify and os/signal.Reset.
+// This is a lot like misc/cgo/testcshared/main5.c.
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sched.h>
+
+#include "libgo3.h"
+
+static void die(const char* msg) {
+	perror(msg);
+	exit(EXIT_FAILURE);
+}
+
+static volatile sig_atomic_t sigioSeen;
+
+static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
+	sigioSeen = 1;
+}
+
+int main(int argc, char** argv) {
+	int verbose;
+	struct sigaction sa;
+	int i;
+
+	verbose = argc > 2;
+	setvbuf(stdout, NULL, _IONBF, 0);
+
+	if (verbose) {
+		printf("calling sigaction\n");
+	}
+
+	memset(&sa, 0, sizeof sa);
+	sa.sa_sigaction = ioHandler;
+	if (sigemptyset(&sa.sa_mask) < 0) {
+		die("sigemptyset");
+	}
+	sa.sa_flags = SA_SIGINFO;
+	if (sigaction(SIGIO, &sa, NULL) < 0) {
+		die("sigaction");
+	}
+
+	// At this point there should not be a Go signal handler
+	// installed for SIGIO.
+
+	if (verbose) {
+		printf("raising SIGIO\n");
+	}
+
+	if (raise(SIGIO) < 0) {
+		die("raise");
+	}
+
+	if (verbose) {
+		printf("waiting for sigioSeen\n");
+	}
+
+	// Wait until the signal has been delivered.
+	i = 0;
+	while (!sigioSeen) {
+		if (sched_yield() < 0) {
+			perror("sched_yield");
+		}
+		i++;
+		if (i > 100000) {
+			fprintf(stderr, "looping too long waiting for signal\n");
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	sigioSeen = 0;
+
+	// Tell the Go code to catch SIGIO.
+
+	if (verbose) {
+		printf("calling CatchSIGIO\n");
+	}
+
+	CatchSIGIO();
+
+	if (verbose) {
+		printf("raising SIGIO\n");
+	}
+
+	if (raise(SIGIO) < 0) {
+		die("raise");
+	}
+
+	if (verbose) {
+		printf("calling SawSIGIO\n");
+	}
+
+	if (!SawSIGIO()) {
+		fprintf(stderr, "Go handler did not see SIGIO\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if (sigioSeen != 0) {
+		fprintf(stderr, "C handler saw SIGIO when only Go handler should have\n");
+		exit(EXIT_FAILURE);
+	}
+
+	// Tell the Go code to stop catching SIGIO.
+
+	if (verbose) {
+		printf("calling ResetSIGIO\n");
+	}
+
+	ResetSIGIO();
+
+	if (verbose) {
+		printf("raising SIGIO\n");
+	}
+
+	if (raise(SIGIO) < 0) {
+		die("raise");
+	}
+
+	if (verbose) {
+		printf("calling SawSIGIO\n");
+	}
+
+	if (SawSIGIO()) {
+		fprintf(stderr, "Go handler saw SIGIO after Reset\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if (verbose) {
+		printf("waiting for sigioSeen\n");
+	}
+
+	// Wait until the signal has been delivered.
+	i = 0;
+	while (!sigioSeen) {
+		if (sched_yield() < 0) {
+			perror("sched_yield");
+		}
+		i++;
+		if (i > 100000) {
+			fprintf(stderr, "looping too long waiting for signal\n");
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	printf("PASS\n");
+	return 0;
+}
diff --git a/misc/cgo/testcarchive/main4.c b/misc/cgo/testcarchive/main4.c
new file mode 100644
index 0000000..2aaf09b
--- /dev/null
+++ b/misc/cgo/testcarchive/main4.c
@@ -0,0 +1,194 @@
+// Copyright 2015 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 a C thread that calls sigaltstack and then calls Go code.
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sched.h>
+#include <pthread.h>
+
+#include "libgo4.h"
+
+static void die(const char* msg) {
+	perror(msg);
+	exit(EXIT_FAILURE);
+}
+
+static int ok = 1;
+
+static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
+}
+
+// Set up the SIGIO signal handler in a high priority constructor, so
+// that it is installed before the Go code starts.
+
+static void init(void) __attribute__ ((constructor (200)));
+
+static void init() {
+	struct sigaction sa;
+
+	memset(&sa, 0, sizeof sa);
+	sa.sa_sigaction = ioHandler;
+	if (sigemptyset(&sa.sa_mask) < 0) {
+		die("sigemptyset");
+	}
+	sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
+	if (sigaction(SIGIO, &sa, NULL) < 0) {
+		die("sigaction");
+	}
+}
+
+// Test raising SIGIO on a C thread with an alternate signal stack
+// when there is a Go signal handler for SIGIO.
+static void* thread1(void* arg) {
+	pthread_t* ptid = (pthread_t*)(arg);
+	stack_t ss;
+	int i;
+	stack_t nss;
+
+	// Set up an alternate signal stack for this thread.
+	memset(&ss, 0, sizeof ss);
+	ss.ss_sp = malloc(SIGSTKSZ);
+	if (ss.ss_sp == NULL) {
+		die("malloc");
+	}
+	ss.ss_flags = 0;
+	ss.ss_size = SIGSTKSZ;
+	if (sigaltstack(&ss, NULL) < 0) {
+		die("sigaltstack");
+	}
+
+	// Send ourselves a SIGIO.  This will be caught by the Go
+	// signal handler which should forward to the C signal
+	// handler.
+	i = pthread_kill(*ptid, SIGIO);
+	if (i != 0) {
+		fprintf(stderr, "pthread_kill: %s\n", strerror(i));
+		exit(EXIT_FAILURE);
+	}
+
+	// Wait until the signal has been delivered.
+	i = 0;
+	while (SIGIOCount() == 0) {
+		if (sched_yield() < 0) {
+			perror("sched_yield");
+		}
+		i++;
+		if (i > 100000) {
+			fprintf(stderr, "looping too long waiting for signal\n");
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	// We should still be on the same signal stack.
+	if (sigaltstack(NULL, &nss) < 0) {
+		die("sigaltstack check");
+	}
+	if ((nss.ss_flags & SS_DISABLE) != 0) {
+		fprintf(stderr, "sigaltstack disabled on return from Go\n");
+		ok = 0;
+	} else if (nss.ss_sp != ss.ss_sp) {
+		fprintf(stderr, "sigalstack changed on return from Go\n");
+		ok = 0;
+	}
+
+	return NULL;
+}
+
+// Test calling a Go function to raise SIGIO on a C thread with an
+// alternate signal stack when there is a Go signal handler for SIGIO.
+static void* thread2(void* arg) {
+	pthread_t* ptid = (pthread_t*)(arg);
+	stack_t ss;
+	int i;
+	int oldcount;
+	stack_t nss;
+
+	// Set up an alternate signal stack for this thread.
+	memset(&ss, 0, sizeof ss);
+	ss.ss_sp = malloc(SIGSTKSZ);
+	if (ss.ss_sp == NULL) {
+		die("malloc");
+	}
+	ss.ss_flags = 0;
+	ss.ss_size = SIGSTKSZ;
+	if (sigaltstack(&ss, NULL) < 0) {
+		die("sigaltstack");
+	}
+
+	oldcount = SIGIOCount();
+
+	// Call a Go function that will call a C function to send us a
+	// SIGIO.
+	GoRaiseSIGIO(ptid);
+
+	// Wait until the signal has been delivered.
+	i = 0;
+	while (SIGIOCount() == oldcount) {
+		if (sched_yield() < 0) {
+			perror("sched_yield");
+		}
+		i++;
+		if (i > 100000) {
+			fprintf(stderr, "looping too long waiting for signal\n");
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	// We should still be on the same signal stack.
+	if (sigaltstack(NULL, &nss) < 0) {
+		die("sigaltstack check");
+	}
+	if ((nss.ss_flags & SS_DISABLE) != 0) {
+		fprintf(stderr, "sigaltstack disabled on return from Go\n");
+		ok = 0;
+	} else if (nss.ss_sp != ss.ss_sp) {
+		fprintf(stderr, "sigalstack changed on return from Go\n");
+		ok = 0;
+	}
+
+	return NULL;
+}
+
+int main(int argc, char **argv) {
+	pthread_t tid;
+	int i;
+
+	// Tell the Go library to start looking for SIGIO.
+	GoCatchSIGIO();
+
+	i = pthread_create(&tid, NULL, thread1, (void*)(&tid));
+	if (i != 0) {
+		fprintf(stderr, "pthread_create: %s\n", strerror(i));
+		exit(EXIT_FAILURE);
+	}
+
+	i = pthread_join(tid, NULL);
+	if (i != 0) {
+		fprintf(stderr, "pthread_join: %s\n", strerror(i));
+		exit(EXIT_FAILURE);
+	}
+
+	i = pthread_create(&tid, NULL, thread2, (void*)(&tid));
+	if (i != 0) {
+		fprintf(stderr, "pthread_create: %s\n", strerror(i));
+		exit(EXIT_FAILURE);
+	}
+
+	i = pthread_join(tid, NULL);
+	if (i != 0) {
+		fprintf(stderr, "pthread_join: %s\n", strerror(i));
+		exit(EXIT_FAILURE);
+	}
+
+	if (!ok) {
+		exit(EXIT_FAILURE);
+	}
+
+	printf("PASS\n");
+	return 0;
+}
diff --git a/misc/cgo/testcarchive/src/libgo2/libgo2.go b/misc/cgo/testcarchive/src/libgo2/libgo2.go
new file mode 100644
index 0000000..ab40b75
--- /dev/null
+++ b/misc/cgo/testcarchive/src/libgo2/libgo2.go
@@ -0,0 +1,45 @@
+// Copyright 2015 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 "C"
+
+import (
+	"fmt"
+	"os"
+	"runtime"
+)
+
+// RunGoroutines starts some goroutines that don't do anything.
+// The idea is to get some threads going, so that a signal will be delivered
+// to a thread started by Go.
+//export RunGoroutines
+func RunGoroutines() {
+	for i := 0; i < 4; i++ {
+		go func() {
+			runtime.LockOSThread()
+			select {}
+		}()
+	}
+}
+
+var P *byte
+
+// TestSEGV makes sure that an invalid address turns into a run-time Go panic.
+//export TestSEGV
+func TestSEGV() {
+	defer func() {
+		if recover() == nil {
+			fmt.Fprintln(os.Stderr, "no panic from segv")
+			os.Exit(1)
+		}
+	}()
+	*P = 0
+	fmt.Fprintln(os.Stderr, "continued after segv")
+	os.Exit(1)
+}
+
+func main() {
+}
diff --git a/misc/cgo/testcarchive/src/libgo3/libgo3.go b/misc/cgo/testcarchive/src/libgo3/libgo3.go
new file mode 100644
index 0000000..94e5d21
--- /dev/null
+++ b/misc/cgo/testcarchive/src/libgo3/libgo3.go
@@ -0,0 +1,44 @@
+// Copyright 2015 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 "C"
+
+import (
+	"os"
+	"os/signal"
+	"syscall"
+	"time"
+)
+
+// The channel used to read SIGIO signals.
+var sigioChan chan os.Signal
+
+// CatchSIGIO starts catching SIGIO signals.
+//export CatchSIGIO
+func CatchSIGIO() {
+	sigioChan = make(chan os.Signal, 1)
+	signal.Notify(sigioChan, syscall.SIGIO)
+}
+
+// ResetSIGIO stops catching SIGIO signals.
+//export ResetSIGIO
+func ResetSIGIO() {
+	signal.Reset(syscall.SIGIO)
+}
+
+// SawSIGIO returns whether we saw a SIGIO within a brief pause.
+//export SawSIGIO
+func SawSIGIO() C.int {
+	select {
+	case <-sigioChan:
+		return 1
+	case <-time.After(100 * time.Millisecond):
+		return 0
+	}
+}
+
+func main() {
+}
diff --git a/misc/cgo/testcarchive/src/libgo4/libgo4.go b/misc/cgo/testcarchive/src/libgo4/libgo4.go
new file mode 100644
index 0000000..8cc1895
--- /dev/null
+++ b/misc/cgo/testcarchive/src/libgo4/libgo4.go
@@ -0,0 +1,52 @@
+// Copyright 2015 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
+
+/*
+#include <signal.h>
+#include <pthread.h>
+
+// Raise SIGIO.
+static void CRaiseSIGIO(pthread_t* p) {
+	pthread_kill(*p, SIGIO);
+}
+*/
+import "C"
+
+import (
+	"os"
+	"os/signal"
+	"sync/atomic"
+	"syscall"
+)
+
+var sigioCount int32
+
+// Catch SIGIO.
+//export GoCatchSIGIO
+func GoCatchSIGIO() {
+	c := make(chan os.Signal, 1)
+	signal.Notify(c, syscall.SIGIO)
+	go func() {
+		for range c {
+			atomic.AddInt32(&sigioCount, 1)
+		}
+	}()
+}
+
+// Raise SIGIO.
+//export GoRaiseSIGIO
+func GoRaiseSIGIO(p *C.pthread_t) {
+	C.CRaiseSIGIO(p)
+}
+
+// Return the number of SIGIO signals seen.
+//export SIGIOCount
+func SIGIOCount() C.int {
+	return C.int(atomic.LoadInt32(&sigioCount))
+}
+
+func main() {
+}
diff --git a/misc/cgo/testcarchive/test.bash b/misc/cgo/testcarchive/test.bash
index 89b761b..f4e7c45 100755
--- a/misc/cgo/testcarchive/test.bash
+++ b/misc/cgo/testcarchive/test.bash
@@ -23,11 +23,16 @@ fi
 
 rm -rf libgo.a libgo.h testp pkg
 
+status=0
+
 # Installing first will create the header files we want.
 
 GOPATH=$(pwd) go install -buildmode=c-archive libgo
 $(go env CC) $(go env GOGCCFLAGS) $ccargs -o testp main.c pkg/$(go env GOOS)_$(go env GOARCH)/libgo.a
-$bin arg1 arg2
+if ! $bin arg1 arg2; then
+    echo "FAIL test1a"
+    status=1
+fi
 rm -f libgo.a libgo.h testp
 
 # Test building libgo other than installing it.
@@ -35,10 +40,67 @@ rm -f libgo.a libgo.h testp
 
 GOPATH=$(pwd) go build -buildmode=c-archive src/libgo/libgo.go
 $(go env CC) $(go env GOGCCFLAGS) $ccargs -o testp main.c libgo.a
-$bin arg1 arg2
+if ! $bin arg1 arg2; then
+    echo "FAIL test1b"
+    status=1
+fi
 rm -f libgo.a libgo.h testp
 
 GOPATH=$(pwd) go build -buildmode=c-archive -o libgo.a libgo
 $(go env CC) $(go env GOGCCFLAGS) $ccargs -o testp main.c libgo.a
-$bin arg1 arg2
+if ! $bin arg1 arg2; then
+    echo "FAIL test1c"
+    status=1
+fi
 rm -rf libgo.a libgo.h testp pkg
+
+case "$(go env GOOS)/$(go env GOARCH)" in
+"darwin/arm" | "darwin/arm64")
+    echo "Skipping test2; see https://golang.org/issue/13701"
+    ;;
+*)
+    GOPATH=$(pwd) go build -buildmode=c-archive -o libgo2.a libgo2
+    $(go env CC) $(go env GOGCCFLAGS) $ccargs -o testp main2.c libgo2.a
+    if ! $bin; then
+        echo "FAIL test2"
+        status=1
+    fi
+    rm -rf libgo2.a libgo2.h testp pkg
+    ;;
+esac
+
+GOPATH=$(pwd) go build -buildmode=c-archive -o libgo3.a libgo3
+$(go env CC) $(go env GOGCCFLAGS) $ccargs -o testp main3.c libgo3.a
+if ! $bin; then
+    echo "FAIL test3"
+    status=1
+fi
+rm -rf libgo3.a libgo3.h testp pkg
+
+GOPATH=$(pwd) go build -buildmode=c-archive -o libgo4.a libgo4
+$(go env CC) $(go env GOGCCFLAGS) $ccargs -o testp main4.c libgo4.a
+if ! $bin; then
+    echo "FAIL test4"
+    status=1
+fi
+rm -rf libgo4.a libgo4.h testp pkg
+
+rm -f testar
+cat >testar <<EOF
+#!/usr/bin/env bash
+while expr \$1 : '[-]' >/dev/null; do
+  shift
+done
+echo "testar" > \$1
+echo "testar" > $(pwd)/testar.ran
+EOF
+chmod +x testar
+rm -f testar.ran
+GOPATH=$(pwd) go build -buildmode=c-archive -ldflags=-extar=$(pwd)/testar -o libgo4.a libgo4
+if ! test -f testar.ran; then
+    echo "FAIL test5"
+    status=1
+fi
+rm -rf libgo4.a libgo4.h testar testar.ran pkg
+
+exit $status
diff --git a/misc/cgo/testcshared/main2.c b/misc/cgo/testcshared/main2.c
index 4023383..9752006 100644
--- a/misc/cgo/testcshared/main2.c
+++ b/misc/cgo/testcshared/main2.c
@@ -9,7 +9,7 @@
 #include <time.h>
 #include <unistd.h>
 
-#define fd (10)
+#define fd (100)
 
 // Tests libgo2.so, which does not export any functions.
 // Read a string from the file descriptor and print it.
@@ -25,7 +25,7 @@ int main(void) {
     n = read(fd, buf, sizeof buf);
     if (n >= 0)
       break;
-    if (errno != EBADF) {
+    if (errno != EBADF && errno != EINVAL) {
       fprintf(stderr, "BUG: read: %s\n", strerror(errno));
       return 2;
     }
diff --git a/misc/cgo/testcshared/main4.c b/misc/cgo/testcshared/main4.c
new file mode 100644
index 0000000..fd7b5b3
--- /dev/null
+++ b/misc/cgo/testcshared/main4.c
@@ -0,0 +1,214 @@
+// Copyright 2015 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 that a signal handler that uses up stack space does not crash
+// if the signal is delivered to a thread running a goroutine.
+// This is a lot like misc/cgo/testcarchive/main2.c.
+
+#include <setjmp.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sched.h>
+#include <time.h>
+#include <dlfcn.h>
+
+static void die(const char* msg) {
+	perror(msg);
+	exit(EXIT_FAILURE);
+}
+
+static volatile sig_atomic_t sigioSeen;
+
+// Use up some stack space.
+static void recur(int i, char *p) {
+	char a[1024];
+
+	*p = '\0';
+	if (i > 0) {
+		recur(i - 1, a);
+	}
+}
+
+// Signal handler that uses up more stack space than a goroutine will have.
+static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
+	char a[1024];
+
+	recur(4, a);
+	sigioSeen = 1;
+}
+
+static jmp_buf jmp;
+static char* nullPointer;
+
+// Signal handler for SIGSEGV on a C thread.
+static void segvHandler(int signo, siginfo_t* info, void* ctxt) {
+	sigset_t mask;
+	int i;
+
+	if (sigemptyset(&mask) < 0) {
+		die("sigemptyset");
+	}
+	if (sigaddset(&mask, SIGSEGV) < 0) {
+		die("sigaddset");
+	}
+	i = sigprocmask(SIG_UNBLOCK, &mask, NULL);
+	if (i != 0) {
+		fprintf(stderr, "sigprocmask: %s\n", strerror(i));
+		exit(EXIT_FAILURE);
+	}
+
+	// Don't try this at home.
+	longjmp(jmp, signo);
+
+	// We should never get here.
+	abort();
+}
+
+int main(int argc, char** argv) {
+	int verbose;
+	struct sigaction sa;
+	void* handle;
+	void (*fn)(void);
+	sigset_t mask;
+	int i;
+
+	verbose = argc > 2;
+	setvbuf(stdout, NULL, _IONBF, 0);
+
+	// Call setsid so that we can use kill(0, SIGIO) below.
+	// Don't check the return value so that this works both from
+	// a job control shell and from a shell script.
+	setsid();
+
+	if (verbose) {
+		printf("calling sigaction\n");
+	}
+
+	memset(&sa, 0, sizeof sa);
+	sa.sa_sigaction = ioHandler;
+	if (sigemptyset(&sa.sa_mask) < 0) {
+		die("sigemptyset");
+	}
+	sa.sa_flags = SA_SIGINFO;
+	if (sigaction(SIGIO, &sa, NULL) < 0) {
+		die("sigaction");
+	}
+
+	sa.sa_sigaction = segvHandler;
+	if (sigaction(SIGSEGV, &sa, NULL) < 0 || sigaction(SIGBUS, &sa, NULL) < 0) {
+		die("sigaction");
+	}
+
+	if (verbose) {
+		printf("calling dlopen\n");
+	}
+
+	handle = dlopen(argv[1], RTLD_NOW | RTLD_GLOBAL);
+	if (handle == NULL) {
+		fprintf(stderr, "%s\n", dlerror());
+		exit(EXIT_FAILURE);
+	}
+
+	if (verbose) {
+		printf("calling dlsym\n");
+	}
+
+	// Start some goroutines.
+	fn = (void(*)(void))dlsym(handle, "RunGoroutines");
+	if (fn == NULL) {
+		fprintf(stderr, "%s\n", dlerror());
+		exit(EXIT_FAILURE);
+	}
+
+	if (verbose) {
+		printf("calling RunGoroutines\n");
+	}
+
+	fn();
+
+	// Block SIGIO in this thread to make it more likely that it
+	// will be delivered to a goroutine.
+
+	if (verbose) {
+		printf("calling pthread_sigmask\n");
+	}
+
+	if (sigemptyset(&mask) < 0) {
+		die("sigemptyset");
+	}
+	if (sigaddset(&mask, SIGIO) < 0) {
+		die("sigaddset");
+	}
+	i = pthread_sigmask(SIG_BLOCK, &mask, NULL);
+	if (i != 0) {
+		fprintf(stderr, "pthread_sigmask: %s\n", strerror(i));
+		exit(EXIT_FAILURE);
+	}
+
+	if (verbose) {
+		printf("calling kill\n");
+	}
+
+	if (kill(0, SIGIO) < 0) {
+		die("kill");
+	}
+
+	if (verbose) {
+		printf("waiting for sigioSeen\n");
+	}
+
+	// Wait until the signal has been delivered.
+	i = 0;
+	while (!sigioSeen) {
+		if (sched_yield() < 0) {
+			perror("sched_yield");
+		}
+		i++;
+		if (i > 100000) {
+			fprintf(stderr, "looping too long waiting for signal\n");
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	if (verbose) {
+		printf("calling setjmp\n");
+	}
+
+	// Test that a SIGSEGV on this thread is delivered to us.
+	if (setjmp(jmp) == 0) {
+		if (verbose) {
+			printf("triggering SIGSEGV\n");
+		}
+
+		*nullPointer = '\0';
+
+		fprintf(stderr, "continued after address error\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if (verbose) {
+		printf("calling dlsym\n");
+	}
+
+	// Make sure that a SIGSEGV in Go causes a run-time panic.
+	fn = (void (*)(void))dlsym(handle, "TestSEGV");
+	if (fn == NULL) {
+		fprintf(stderr, "%s\n", dlerror());
+		exit(EXIT_FAILURE);
+	}
+
+	if (verbose) {
+		printf("calling TestSEGV\n");
+	}
+
+	fn();
+
+	printf("PASS\n");
+	return 0;
+}
diff --git a/misc/cgo/testcshared/main5.c b/misc/cgo/testcshared/main5.c
new file mode 100644
index 0000000..97a258f
--- /dev/null
+++ b/misc/cgo/testcshared/main5.c
@@ -0,0 +1,197 @@
+// Copyright 2015 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 that a signal handler works in non-Go code when using
+// os/signal.Notify.
+// This is a lot like misc/cgo/testcarchive/main3.c.
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sched.h>
+#include <dlfcn.h>
+
+static void die(const char* msg) {
+	perror(msg);
+	exit(EXIT_FAILURE);
+}
+
+static volatile sig_atomic_t sigioSeen;
+
+static void ioHandler(int signo, siginfo_t* info, void* ctxt) {
+	sigioSeen = 1;
+}
+
+int main(int argc, char** argv) {
+	int verbose;
+	struct sigaction sa;
+	void* handle;
+	void (*fn1)(void);
+	int (*sawSIGIO)(void);
+	int i;
+
+	verbose = argc > 2;
+	setvbuf(stdout, NULL, _IONBF, 0);
+
+	if (verbose) {
+		printf("calling sigaction\n");
+	}
+
+	memset(&sa, 0, sizeof sa);
+	sa.sa_sigaction = ioHandler;
+	if (sigemptyset(&sa.sa_mask) < 0) {
+		die("sigemptyset");
+	}
+	sa.sa_flags = SA_SIGINFO;
+	if (sigaction(SIGIO, &sa, NULL) < 0) {
+		die("sigaction");
+	}
+
+	if (verbose) {
+		printf("calling dlopen\n");
+	}
+
+	handle = dlopen(argv[1], RTLD_NOW | RTLD_GLOBAL);
+	if (handle == NULL) {
+		fprintf(stderr, "%s\n", dlerror());
+		exit(EXIT_FAILURE);
+	}
+
+	// At this point there should not be a Go signal handler
+	// installed for SIGIO.
+
+	if (verbose) {
+		printf("raising SIGIO\n");
+	}
+
+	if (raise(SIGIO) < 0) {
+		die("raise");
+	}
+
+	if (verbose) {
+		printf("waiting for sigioSeen\n");
+	}
+
+	// Wait until the signal has been delivered.
+	i = 0;
+	while (!sigioSeen) {
+		if (sched_yield() < 0) {
+			perror("sched_yield");
+		}
+		i++;
+		if (i > 100000) {
+			fprintf(stderr, "looping too long waiting for signal\n");
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	sigioSeen = 0;
+
+	// Tell the Go code to catch SIGIO.
+
+	if (verbose) {
+		printf("calling dlsym\n");
+	}
+
+	fn1 = (void(*)(void))dlsym(handle, "CatchSIGIO");
+	if (fn1 == NULL) {
+		fprintf(stderr, "%s\n", dlerror());
+		exit(EXIT_FAILURE);
+	}
+
+	if (verbose) {
+		printf("calling CatchSIGIO\n");
+	}
+
+	fn1();
+
+	if (verbose) {
+		printf("raising SIGIO\n");
+	}
+
+	if (raise(SIGIO) < 0) {
+		die("raise");
+	}
+
+	if (verbose) {
+		printf("calling dlsym\n");
+	}
+
+	// Check that the Go code saw SIGIO.
+	sawSIGIO = (int (*)(void))dlsym(handle, "SawSIGIO");
+	if (sawSIGIO == NULL) {
+		fprintf(stderr, "%s\n", dlerror());
+		exit(EXIT_FAILURE);
+	}
+
+	if (verbose) {
+		printf("calling SawSIGIO\n");
+	}
+
+	if (!sawSIGIO()) {
+		fprintf(stderr, "Go handler did not see SIGIO\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if (sigioSeen != 0) {
+		fprintf(stderr, "C handler saw SIGIO when only Go handler should have\n");
+		exit(EXIT_FAILURE);
+	}
+
+	// Tell the Go code to stop catching SIGIO.
+
+	if (verbose) {
+		printf("calling dlsym\n");
+	}
+
+	fn1 = (void(*)(void))dlsym(handle, "ResetSIGIO");
+	if (fn1 == NULL) {
+		fprintf(stderr, "%s\n", dlerror());
+		exit(EXIT_FAILURE);
+	}
+
+	if (verbose) {
+		printf("calling ResetSIGIO\n");
+	}
+
+	fn1();
+
+	if (verbose) {
+		printf("raising SIGIO\n");
+	}
+
+	if (raise(SIGIO) < 0) {
+		die("raise");
+	}
+
+	if (verbose) {
+		printf("calling SawSIGIO\n");
+	}
+
+	if (sawSIGIO()) {
+		fprintf(stderr, "Go handler saw SIGIO after Reset\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if (verbose) {
+		printf("waiting for sigioSeen\n");
+	}
+
+	// Wait until the signal has been delivered.
+	i = 0;
+	while (!sigioSeen) {
+		if (sched_yield() < 0) {
+			perror("sched_yield");
+		}
+		i++;
+		if (i > 100000) {
+			fprintf(stderr, "looping too long waiting for signal\n");
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	printf("PASS\n");
+	return 0;
+}
diff --git a/misc/cgo/testcshared/src/libgo2/dup2.go b/misc/cgo/testcshared/src/libgo2/dup2.go
new file mode 100644
index 0000000..d18f0b1
--- /dev/null
+++ b/misc/cgo/testcshared/src/libgo2/dup2.go
@@ -0,0 +1,13 @@
+// Copyright 2015 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.
+
+// +build darwin dragonfly freebsd linux,!arm64 netbsd openbsd
+
+package main
+
+import "syscall"
+
+func dup2(oldfd, newfd int) error {
+	return syscall.Dup2(oldfd, newfd)
+}
diff --git a/misc/cgo/testcshared/src/libgo2/dup3.go b/misc/cgo/testcshared/src/libgo2/dup3.go
new file mode 100644
index 0000000..c9c65a6
--- /dev/null
+++ b/misc/cgo/testcshared/src/libgo2/dup3.go
@@ -0,0 +1,13 @@
+// Copyright 2015 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.
+
+// +build linux,arm64
+
+package main
+
+import "syscall"
+
+func dup2(oldfd, newfd int) error {
+	return syscall.Dup3(oldfd, newfd, 0)
+}
diff --git a/misc/cgo/testcshared/src/libgo2/libgo2.go b/misc/cgo/testcshared/src/libgo2/libgo2.go
index 6096860..1b69d8f 100644
--- a/misc/cgo/testcshared/src/libgo2/libgo2.go
+++ b/misc/cgo/testcshared/src/libgo2/libgo2.go
@@ -21,7 +21,7 @@ import (
 // that the C code can also use.
 
 const (
-	fd = 10
+	fd = 100
 )
 
 func init() {
@@ -31,7 +31,7 @@ func init() {
 		os.Exit(2)
 	}
 
-	if e := syscall.Dup2(p[0], fd); e != nil {
+	if e := dup2(p[0], fd); e != nil {
 		fmt.Fprintf(os.Stderr, "dup2: %v\n", e)
 		os.Exit(2)
 	}
diff --git a/misc/cgo/testcshared/src/libgo4/libgo4.go b/misc/cgo/testcshared/src/libgo4/libgo4.go
new file mode 100644
index 0000000..ab40b75
--- /dev/null
+++ b/misc/cgo/testcshared/src/libgo4/libgo4.go
@@ -0,0 +1,45 @@
+// Copyright 2015 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 "C"
+
+import (
+	"fmt"
+	"os"
+	"runtime"
+)
+
+// RunGoroutines starts some goroutines that don't do anything.
+// The idea is to get some threads going, so that a signal will be delivered
+// to a thread started by Go.
+//export RunGoroutines
+func RunGoroutines() {
+	for i := 0; i < 4; i++ {
+		go func() {
+			runtime.LockOSThread()
+			select {}
+		}()
+	}
+}
+
+var P *byte
+
+// TestSEGV makes sure that an invalid address turns into a run-time Go panic.
+//export TestSEGV
+func TestSEGV() {
+	defer func() {
+		if recover() == nil {
+			fmt.Fprintln(os.Stderr, "no panic from segv")
+			os.Exit(1)
+		}
+	}()
+	*P = 0
+	fmt.Fprintln(os.Stderr, "continued after segv")
+	os.Exit(1)
+}
+
+func main() {
+}
diff --git a/misc/cgo/testcshared/src/libgo5/libgo5.go b/misc/cgo/testcshared/src/libgo5/libgo5.go
new file mode 100644
index 0000000..94e5d21
--- /dev/null
+++ b/misc/cgo/testcshared/src/libgo5/libgo5.go
@@ -0,0 +1,44 @@
+// Copyright 2015 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 "C"
+
+import (
+	"os"
+	"os/signal"
+	"syscall"
+	"time"
+)
+
+// The channel used to read SIGIO signals.
+var sigioChan chan os.Signal
+
+// CatchSIGIO starts catching SIGIO signals.
+//export CatchSIGIO
+func CatchSIGIO() {
+	sigioChan = make(chan os.Signal, 1)
+	signal.Notify(sigioChan, syscall.SIGIO)
+}
+
+// ResetSIGIO stops catching SIGIO signals.
+//export ResetSIGIO
+func ResetSIGIO() {
+	signal.Reset(syscall.SIGIO)
+}
+
+// SawSIGIO returns whether we saw a SIGIO within a brief pause.
+//export SawSIGIO
+func SawSIGIO() C.int {
+	select {
+	case <-sigioChan:
+		return 1
+	case <-time.After(100 * time.Millisecond):
+		return 0
+	}
+}
+
+func main() {
+}
diff --git a/misc/cgo/testcshared/test.bash b/misc/cgo/testcshared/test.bash
index 57221bc..23c9767 100755
--- a/misc/cgo/testcshared/test.bash
+++ b/misc/cgo/testcshared/test.bash
@@ -16,11 +16,18 @@ fi
 
 goos=$(go env GOOS)
 goarch=$(go env GOARCH)
+goroot=$(go env GOROOT)
+if [ ! -d "$goroot" ]; then
+	echo 'misc/cgo/testcshared/test.bash cannnot find GOROOT' 1>&2
+	echo '$GOROOT:' "$GOROOT" 1>&2
+	echo 'go env GOROOT:' "$goroot" 1>&2
+	exit 1
+fi
 
 # Directory where cgo headers and outputs will be installed.
 # The installation directory format varies depending on the platform.
 installdir=pkg/${goos}_${goarch}_testcshared_shared
-if [ "${goos}/${goarch}" == "android/arm" ] || [ "${goos}/${goarch}" == "darwin/amd64" ]; then
+if [ "${goos}" == "darwin" ]; then
 	installdir=pkg/${goos}_${goarch}_testcshared
 fi
 
@@ -28,12 +35,13 @@ fi
 androidpath=/data/local/tmp/testcshared-$$
 
 function cleanup() {
-	rm -rf libgo.$libext libgo2.$libext libgo.h testp testp2 testp3 pkg
-
-	rm -rf $(go env GOROOT)/${installdir}
+	rm -f libgo.$libext libgo2.$libext libgo4.$libext libgo5.$libext
+	rm -f libgo.h libgo4.h libgo5.h
+	rm -f testp testp2 testp3 testp4 testp5
+	rm -rf pkg "${goroot}/${installdir}"
 
 	if [ "$goos" == "android" ]; then
-		adb shell rm -rf $androidpath
+		adb shell rm -rf "$androidpath"
 	fi
 }
 trap cleanup EXIT
@@ -81,49 +89,98 @@ GOPATH=$(pwd) go install -buildmode=c-shared $suffix libgo
 GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo.$libext src/libgo/libgo.go
 binpush libgo.$libext
 
+if [ "$goos" == "linux" ] || [ "$goos" == "android" ] ; then
+    if readelf -d libgo.$libext | grep TEXTREL >/dev/null; then
+        echo "libgo.$libext has TEXTREL set"
+        exit 1
+    fi
+fi
+
+GOGCCFLAGS=$(go env GOGCCFLAGS)
+if [ "$goos" == "android" ]; then
+	GOGCCFLAGS="${GOGCCFLAGS} -pie"
+fi
+
+status=0
+
 # test0: exported symbols in shared lib are accessible.
 # TODO(iant): using _shared here shouldn't really be necessary.
-$(go env CC) $(go env GOGCCFLAGS) -I ${installdir} -o testp main0.c libgo.$libext
+$(go env CC) ${GOGCCFLAGS} -I ${installdir} -o testp main0.c libgo.$libext
 binpush testp
 
 output=$(run LD_LIBRARY_PATH=. ./testp)
 if [ "$output" != "PASS" ]; then
 	echo "FAIL test0 got ${output}"
-	exit 1
+	status=1
 fi
 
 # test1: shared library can be dynamically loaded and exported symbols are accessible.
-$(go env CC) $(go env GOGCCFLAGS) -o testp main1.c -ldl
+$(go env CC) ${GOGCCFLAGS} -o testp main1.c -ldl
 binpush testp
 output=$(run ./testp ./libgo.$libext)
 if [ "$output" != "PASS" ]; then
 	echo "FAIL test1 got ${output}"
-	exit 1
+	status=1
 fi
 
 # test2: tests libgo2 which does not export any functions.
-GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo2.$libext src/libgo2/libgo2.go
+GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo2.$libext libgo2
 binpush libgo2.$libext
 linkflags="-Wl,--no-as-needed"
 if [ "$goos" == "darwin" ]; then
 	linkflags=""
 fi
-$(go env CC) $(go env GOGCCFLAGS) -o testp2 main2.c $linkflags libgo2.$libext
+$(go env CC) ${GOGCCFLAGS} -o testp2 main2.c $linkflags libgo2.$libext
 binpush testp2
 output=$(run LD_LIBRARY_PATH=. ./testp2)
 if [ "$output" != "PASS" ]; then
 	echo "FAIL test2 got ${output}"
-	exit 1
+	status=1
 fi
 
 # test3: tests main.main is exported on android.
 if [ "$goos" == "android" ]; then
-	$(go env CC) $(go env GOGCCFLAGS) -o testp3 main3.c -ldl
+	$(go env CC) ${GOGCCFLAGS} -o testp3 main3.c -ldl
 	binpush testp3
 	output=$(run ./testp ./libgo.so)
 	if [ "$output" != "PASS" ]; then
 		echo "FAIL test3 got ${output}"
-		exit 1
+		status=1
 	fi
 fi
-echo "ok"
+
+# test4: tests signal handlers
+GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo4.$libext libgo4
+binpush libgo4.$libext
+$(go env CC) ${GOGCCFLAGS} -pthread -o testp4 main4.c -ldl
+binpush testp4
+output=$(run ./testp4 ./libgo4.$libext 2>&1)
+if test "$output" != "PASS"; then
+    echo "FAIL test4 got ${output}"
+    if test "$goos" != "android"; then
+	echo "re-running test4 in verbose mode"
+	./testp4 ./libgo4.$libext verbose
+    fi
+    status=1
+fi
+
+# test5: tests signal handlers with os/signal.Notify
+GOPATH=$(pwd) go build -buildmode=c-shared $suffix -o libgo5.$libext libgo5
+binpush libgo5.$libext
+$(go env CC) ${GOGCCFLAGS} -pthread -o testp5 main5.c -ldl
+binpush testp5
+output=$(run ./testp5 ./libgo5.$libext 2>&1)
+if test "$output" != "PASS"; then
+    echo "FAIL test5 got ${output}"
+    if test "$goos" != "android"; then
+	echo "re-running test5 in verbose mode"
+	./testp5 ./libgo5.$libext verbose
+    fi
+    status=1
+fi
+
+if test $status = 0; then
+    echo "ok"
+fi
+
+exit $status
diff --git a/misc/cgo/testsanitizers/msan.go b/misc/cgo/testsanitizers/msan.go
new file mode 100644
index 0000000..ebfd5c3
--- /dev/null
+++ b/misc/cgo/testsanitizers/msan.go
@@ -0,0 +1,35 @@
+// Copyright 2015 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
+
+/*
+#include <stdint.h>
+
+void f(int32_t *p, int n) {
+  int i;
+
+  for (i = 0; i < n; i++) {
+    p[i] = (int32_t)i;
+  }
+}
+*/
+import "C"
+
+import (
+	"fmt"
+	"os"
+	"unsafe"
+)
+
+func main() {
+	a := make([]int32, 10)
+	C.f((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a)))
+	for i, v := range a {
+		if i != int(v) {
+			fmt.Println("bad %d: %v\n", i, a)
+			os.Exit(1)
+		}
+	}
+}
diff --git a/misc/cgo/testsanitizers/msan2.go b/misc/cgo/testsanitizers/msan2.go
new file mode 100644
index 0000000..42dcd20
--- /dev/null
+++ b/misc/cgo/testsanitizers/msan2.go
@@ -0,0 +1,35 @@
+// Copyright 2015 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
+
+/*
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+void f(int32_t *p, int n) {
+  int32_t * volatile q = (int32_t *)malloc(sizeof(int32_t) * n);
+  memcpy(p, q, n * sizeof(*p));
+  free(q);
+}
+
+void g(int32_t *p, int n) {
+  if (p[4] != 1) {
+    abort();
+  }
+}
+*/
+import "C"
+
+import (
+	"unsafe"
+)
+
+func main() {
+	a := make([]int32, 10)
+	C.f((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a)))
+	a[4] = 1
+	C.g((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a)))
+}
diff --git a/misc/cgo/testsanitizers/msan3.go b/misc/cgo/testsanitizers/msan3.go
new file mode 100644
index 0000000..61a9c29
--- /dev/null
+++ b/misc/cgo/testsanitizers/msan3.go
@@ -0,0 +1,33 @@
+// Copyright 2015 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
+
+/*
+extern int *GoFn(int *);
+
+// Yes, you can have definitions if you use //export, as long as they are weak.
+int f(void) __attribute__ ((weak));
+
+int f() {
+  int i;
+  int *p = GoFn(&i);
+  if (*p != 12345)
+    return 0;
+  return 1;
+}
+*/
+import "C"
+
+//export GoFn
+func GoFn(p *C.int) *C.int {
+	*p = C.int(12345)
+	return p
+}
+
+func main() {
+	if r := C.f(); r != 1 {
+		panic(r)
+	}
+}
diff --git a/misc/cgo/testsanitizers/msan4.go b/misc/cgo/testsanitizers/msan4.go
new file mode 100644
index 0000000..c75e1c3
--- /dev/null
+++ b/misc/cgo/testsanitizers/msan4.go
@@ -0,0 +1,50 @@
+// Copyright 2015 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
+
+// The memory profiler can call copy from a slice on the system stack,
+// which msan used to think meant a reference to uninitialized memory.
+
+/*
+#include <time.h>
+#include <unistd.h>
+
+extern void Nop(char*);
+
+// Use weak as a hack to permit defining a function even though we use export.
+void poison() __attribute__ ((weak));
+
+// Poison the stack.
+void poison() {
+	char a[1024];
+	Nop(&a[0]);
+}
+
+*/
+import "C"
+
+import (
+	"runtime"
+)
+
+func main() {
+	runtime.MemProfileRate = 1
+	start(100)
+}
+
+func start(i int) {
+	if i == 0 {
+		return
+	}
+	C.poison()
+	// Tie up a thread.
+	// We won't actually wait for this sleep to complete.
+	go func() { C.sleep(1) }()
+	start(i - 1)
+}
+
+//export Nop
+func Nop(*C.char) {
+}
diff --git a/misc/cgo/testsanitizers/msan_fail.go b/misc/cgo/testsanitizers/msan_fail.go
new file mode 100644
index 0000000..757e22c
--- /dev/null
+++ b/misc/cgo/testsanitizers/msan_fail.go
@@ -0,0 +1,36 @@
+// Copyright 2015 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
+
+/*
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+void f(int32_t *p, int n) {
+  int32_t * volatile q = (int32_t *)malloc(sizeof(int32_t) * n);
+  memcpy(p, q, n * sizeof(*p));
+  free(q);
+}
+
+void g(int32_t *p, int n) {
+  if (p[4] != 1) {
+    // We shouldn't get here; msan should stop us first.
+    exit(0);
+  }
+}
+*/
+import "C"
+
+import (
+	"unsafe"
+)
+
+func main() {
+	a := make([]int32, 10)
+	C.f((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a)))
+	a[3] = 1
+	C.g((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a)))
+}
diff --git a/misc/cgo/testsanitizers/test.bash b/misc/cgo/testsanitizers/test.bash
new file mode 100755
index 0000000..feacd89
--- /dev/null
+++ b/misc/cgo/testsanitizers/test.bash
@@ -0,0 +1,89 @@
+#!/usr/bin/env bash
+# Copyright 2015 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 directory is intended to test the use of Go with sanitizers
+# like msan, asan, etc.  See https://github.com/google/sanitizers .
+
+set -e
+
+# The sanitizers were originally developed with clang, so prefer it.
+CC=cc
+if test -x "$(type -p clang)"; then
+  CC=clang
+fi
+export CC
+
+TMPDIR=${TMPDIR:-/tmp}
+echo > ${TMPDIR}/testsanitizers$$.c
+if $CC -fsanitize=memory -c ${TMPDIR}/testsanitizers$$.c -o ${TMPDIR}/testsanitizers$$.o 2>&1 | grep "unrecognized" >& /dev/null; then
+  echo "skipping msan test: -fsanitize=memory not supported"
+  rm -f ${TMPDIR}/testsanitizers$$.*
+  exit 0
+fi
+rm -f ${TMPDIR}/testsanitizers$$.*
+
+# The memory sanitizer in versions of clang before 3.6 don't work with Go.
+if $CC --version | grep clang >& /dev/null; then
+  ver=$($CC --version | sed -e 's/.* version \([0-9.-]*\).*/\1/')
+  major=$(echo $ver | sed -e 's/\([0-9]*\).*/\1/')
+  minor=$(echo $ver | sed -e 's/[0-9]*\.\([0-9]*\).*/\1/')
+  if test "$major" -lt 3 || test "$major" -eq 3 -a "$minor" -lt 6; then
+    echo "skipping msan test; clang version $major.$minor (older than 3.6)"
+    exit 0
+  fi
+
+  # Clang before 3.8 does not work with Linux at or after 4.1.
+  # golang.org/issue/12898.
+  if test "$major" -lt 3 || test "$major" -eq 3 -a "$minor" -lt 8; then
+    if test "$(uname)" = Linux; then
+      linuxver=$(uname -r)
+      linuxmajor=$(echo $linuxver | sed -e 's/\([0-9]*\).*/\1/')
+      linuxminor=$(echo $linuxver | sed -e 's/[0-9]*\.\([0-9]*\).*/\1/')
+      if test "$linuxmajor" -gt 4 || test "$linuxmajor" -eq 4 -a "$linuxminor" -ge 1; then
+        echo "skipping msan test; clang version $major.$minor (older than 3.8) incompatible with linux version $linuxmajor.$linuxminor (4.1 or newer)"
+        exit 0
+      fi
+    fi
+  fi
+fi
+
+status=0
+
+if ! go build -msan std; then
+  echo "FAIL: build -msan std"
+  status=1
+fi
+
+if ! go run -msan msan.go; then
+  echo "FAIL: msan"
+  status=1
+fi
+
+if ! CGO_LDFLAGS="-fsanitize=memory" CGO_CPPFLAGS="-fsanitize=memory" go run -msan -a msan2.go; then
+  echo "FAIL: msan2 with -fsanitize=memory"
+  status=1
+fi
+
+if ! go run -msan -a msan2.go; then
+  echo "FAIL: msan2"
+  status=1
+fi
+
+if ! go run -msan msan3.go; then
+  echo "FAIL: msan3"
+  status=1
+fi
+
+if ! go run -msan msan4.go; then
+  echo "FAIL: msan4"
+  status=1
+fi
+
+if go run -msan msan_fail.go 2>/dev/null; then
+  echo "FAIL: msan_fail"
+  status=1
+fi
+
+exit $status
diff --git a/misc/cgo/testshared/shared_test.go b/misc/cgo/testshared/shared_test.go
index 6ef448c..86fb530 100644
--- a/misc/cgo/testshared/shared_test.go
+++ b/misc/cgo/testshared/shared_test.go
@@ -21,6 +21,7 @@ import (
 	"os/exec"
 	"path/filepath"
 	"regexp"
+	"runtime"
 	"strings"
 	"testing"
 	"time"
@@ -163,12 +164,54 @@ func TestSOBuilt(t *testing.T) {
 	}
 }
 
+func hasDynTag(f *elf.File, tag elf.DynTag) bool {
+	ds := f.SectionByType(elf.SHT_DYNAMIC)
+	if ds == nil {
+		return false
+	}
+	d, err := ds.Data()
+	if err != nil {
+		return false
+	}
+	for len(d) > 0 {
+		var t elf.DynTag
+		switch f.Class {
+		case elf.ELFCLASS32:
+			t = elf.DynTag(f.ByteOrder.Uint32(d[0:4]))
+			d = d[8:]
+		case elf.ELFCLASS64:
+			t = elf.DynTag(f.ByteOrder.Uint64(d[0:8]))
+			d = d[16:]
+		}
+		if t == tag {
+			return true
+		}
+	}
+	return false
+}
+
+// The shared library does not have relocations against the text segment.
+func TestNoTextrel(t *testing.T) {
+	sopath := filepath.Join(gorootInstallDir, soname)
+	f, err := elf.Open(sopath)
+	if err != nil {
+		t.Fatal("elf.Open failed: ", err)
+	}
+	defer f.Close()
+	if hasDynTag(f, elf.DT_TEXTREL) {
+		t.Errorf("%s has DT_TEXTREL set", soname)
+	}
+}
+
 // The install command should have created a "shlibname" file for the
-// listed packages (and runtime/cgo) indicating the name of the shared
-// library containing it.
+// listed packages (and runtime/cgo, and math on arm) indicating the
+// name of the shared library containing it.
 func TestShlibnameFiles(t *testing.T) {
 	pkgs := append([]string{}, minpkgs...)
 	pkgs = append(pkgs, "runtime/cgo")
+	if runtime.GOARCH == "arm" {
+		pkgs = append(pkgs, "math")
+	}
 	for _, pkg := range pkgs {
 		shlibnamefile := filepath.Join(gorootInstallDir, pkg+".shlibname")
 		contentsb, err := ioutil.ReadFile(shlibnamefile)
@@ -242,23 +285,23 @@ func readNotes(f *elf.File) ([]*note, error) {
 				if err == io.EOF {
 					break
 				}
-				return nil, fmt.Errorf("read namesize failed:", err)
+				return nil, fmt.Errorf("read namesize failed: %v", err)
 			}
 			err = binary.Read(r, f.ByteOrder, &descsize)
 			if err != nil {
-				return nil, fmt.Errorf("read descsize failed:", err)
+				return nil, fmt.Errorf("read descsize failed: %v", err)
 			}
 			err = binary.Read(r, f.ByteOrder, &tag)
 			if err != nil {
-				return nil, fmt.Errorf("read type failed:", err)
+				return nil, fmt.Errorf("read type failed: %v", err)
 			}
 			name, err := readwithpad(r, namesize)
 			if err != nil {
-				return nil, fmt.Errorf("read name failed:", err)
+				return nil, fmt.Errorf("read name failed: %v", err)
 			}
 			desc, err := readwithpad(r, descsize)
 			if err != nil {
-				return nil, fmt.Errorf("read desc failed:", err)
+				return nil, fmt.Errorf("read desc failed: %v", err)
 			}
 			notes = append(notes, &note{name: string(name), tag: tag, desc: string(desc), section: sect})
 		}
@@ -320,6 +363,36 @@ func TestCgoExecutable(t *testing.T) {
 	run(t, "cgo executable", "./bin/execgo")
 }
 
+func checkPIE(t *testing.T, name string) {
+	f, err := elf.Open(name)
+	if err != nil {
+		t.Fatal("elf.Open failed: ", err)
+	}
+	defer f.Close()
+	if f.Type != elf.ET_DYN {
+		t.Errorf("%s has type %v, want ET_DYN", name, f.Type)
+	}
+	if hasDynTag(f, elf.DT_TEXTREL) {
+		t.Errorf("%s has DT_TEXTREL set", name)
+	}
+}
+
+func TestTrivialPIE(t *testing.T) {
+	name := "trivial_pie"
+	goCmd(t, "build", "-buildmode=pie", "-o="+name, "trivial")
+	defer os.Remove(name)
+	run(t, name, "./"+name)
+	checkPIE(t, name)
+}
+
+func TestCgoPIE(t *testing.T) {
+	name := "cgo_pie"
+	goCmd(t, "build", "-buildmode=pie", "-o="+name, "execgo")
+	defer os.Remove(name)
+	run(t, name, "./"+name)
+	checkPIE(t, name)
+}
+
 // Build a GOPATH package into a shared library that links against the goroot runtime
 // and an executable that links against both.
 func TestGopathShlib(t *testing.T) {
@@ -460,24 +533,39 @@ func TestTwoGopathShlibs(t *testing.T) {
 	run(t, "executable linked to GOPATH library", "./bin/exe2")
 }
 
-// Build a GOPATH package into a shared library with gccgo and an executable that
-// links against it.
-func TestGoPathShlibGccgo(t *testing.T) {
+// If gccgo is not available or not new enough call t.Skip. Otherwise,
+// return a build.Context that is set up for gccgo.
+func prepGccgo(t *testing.T) build.Context {
 	gccgoName := os.Getenv("GCCGO")
 	if gccgoName == "" {
 		gccgoName = "gccgo"
 	}
-	_, err := exec.LookPath(gccgoName)
+	gccgoPath, err := exec.LookPath(gccgoName)
 	if err != nil {
 		t.Skip("gccgo not found")
 	}
-
-	libgoRE := regexp.MustCompile("libgo.so.[0-9]+")
-
+	cmd := exec.Command(gccgoPath, "-dumpversion")
+	output, err := cmd.CombinedOutput()
+	if err != nil {
+		t.Fatalf("%s -dumpversion failed: %v\n%s", gccgoPath, err, output)
+	}
+	if string(output) < "5" {
+		t.Skipf("gccgo too old (%s)", strings.TrimSpace(string(output)))
+	}
 	gccgoContext := build.Default
 	gccgoContext.InstallSuffix = suffix + "_fPIC"
 	gccgoContext.Compiler = "gccgo"
 	gccgoContext.GOPATH = os.Getenv("GOPATH")
+	return gccgoContext
+}
+
+// Build a GOPATH package into a shared library with gccgo and an executable that
+// links against it.
+func TestGoPathShlibGccgo(t *testing.T) {
+	gccgoContext := prepGccgo(t)
+
+	libgoRE := regexp.MustCompile("libgo.so.[0-9]+")
+
 	depP, err := gccgoContext.Import("dep", ".", build.ImportComment)
 	if err != nil {
 		t.Fatalf("import failed: %v", err)
@@ -497,21 +585,10 @@ func TestGoPathShlibGccgo(t *testing.T) {
 // library with gccgo, another GOPATH package that depends on the first and an
 // executable that links the second library.
 func TestTwoGopathShlibsGccgo(t *testing.T) {
-	gccgoName := os.Getenv("GCCGO")
-	if gccgoName == "" {
-		gccgoName = "gccgo"
-	}
-	_, err := exec.LookPath(gccgoName)
-	if err != nil {
-		t.Skip("gccgo not found")
-	}
+	gccgoContext := prepGccgo(t)
 
 	libgoRE := regexp.MustCompile("libgo.so.[0-9]+")
 
-	gccgoContext := build.Default
-	gccgoContext.InstallSuffix = suffix + "_fPIC"
-	gccgoContext.Compiler = "gccgo"
-	gccgoContext.GOPATH = os.Getenv("GOPATH")
 	depP, err := gccgoContext.Import("dep", ".", build.ImportComment)
 	if err != nil {
 		t.Fatalf("import failed: %v", err)
@@ -672,3 +749,15 @@ func TestABIChecking(t *testing.T) {
 	goCmd(t, "install", "-buildmode=shared", "-linkshared", "dep")
 	run(t, "after non-ABI breaking change", "./bin/exe")
 }
+
+// If a package 'explicit' imports a package 'implicit', building
+// 'explicit' into a shared library implicitly includes implicit in
+// the shared library. Building an executable that imports both
+// explicit and implicit builds the code from implicit into the
+// executable rather than fetching it from the shared library. The
+// link still succeeds and the executable still runs though.
+func TestImplicitInclusion(t *testing.T) {
+	goCmd(t, "install", "-buildmode=shared", "-linkshared", "explicit")
+	goCmd(t, "install", "-linkshared", "implicitcmd")
+	run(t, "running executable linked against library that contains same package as it", "./bin/implicitcmd")
+}
diff --git a/misc/cgo/testshared/src/explicit/explicit.go b/misc/cgo/testshared/src/explicit/explicit.go
new file mode 100644
index 0000000..6a4453f
--- /dev/null
+++ b/misc/cgo/testshared/src/explicit/explicit.go
@@ -0,0 +1,9 @@
+package explicit
+
+import (
+	"implicit"
+)
+
+func E() int {
+	return implicit.I()
+}
diff --git a/misc/cgo/testshared/src/implicit/implicit.go b/misc/cgo/testshared/src/implicit/implicit.go
new file mode 100644
index 0000000..5360188
--- /dev/null
+++ b/misc/cgo/testshared/src/implicit/implicit.go
@@ -0,0 +1,5 @@
+package implicit
+
+func I() int {
+	return 42
+}
diff --git a/misc/cgo/testshared/src/implicitcmd/implicitcmd.go b/misc/cgo/testshared/src/implicitcmd/implicitcmd.go
new file mode 100644
index 0000000..f611293
--- /dev/null
+++ b/misc/cgo/testshared/src/implicitcmd/implicitcmd.go
@@ -0,0 +1,10 @@
+package main
+
+import (
+	"explicit"
+	"implicit"
+)
+
+func main() {
+	println(implicit.I() + explicit.E())
+}
diff --git a/misc/cgo/testsigfwd/main.go b/misc/cgo/testsigfwd/main.go
index 6641c9d..d5fbf50 100644
--- a/misc/cgo/testsigfwd/main.go
+++ b/misc/cgo/testsigfwd/main.go
@@ -7,9 +7,14 @@ package main
 import "fmt"
 
 /*
+#cgo CFLAGS: -pthread
+#cgo LDFLAGS: -pthread
+
 #include <signal.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
+#include <pthread.h>
 
 int *p;
 static void sigsegv() {
@@ -18,16 +23,65 @@ static void sigsegv() {
 	exit(2);
 }
 
-static void sighandler(int signum) {
+static void segvhandler(int signum) {
 	if (signum == SIGSEGV) {
 		exit(0);  // success
 	}
 }
 
+static volatile sig_atomic_t sigioSeen;
+
+// Use up some stack space.
+static void recur(int i, char *p) {
+	char a[1024];
+
+	*p = '\0';
+	if (i > 0) {
+		recur(i - 1, a);
+	}
+}
+
+static void iohandler(int signum) {
+	char a[1024];
+
+	recur(4, a);
+	sigioSeen = 1;
+}
+
+static void* sigioThread(void* arg __attribute__ ((unused))) {
+	raise(SIGIO);
+}
+
+static void sigioOnThread() {
+	pthread_t tid;
+	int i;
+
+	pthread_create(&tid, NULL, sigioThread, NULL);
+	pthread_join(tid, NULL);
+
+	// Wait until the signal has been delivered.
+	i = 0;
+	while (!sigioSeen) {
+		if (sched_yield() < 0) {
+			perror("sched_yield");
+		}
+		i++;
+		if (i > 10000) {
+			fprintf(stderr, "looping too long waiting for signal\n");
+			exit(EXIT_FAILURE);
+		}
+	}
+}
+
 static void __attribute__ ((constructor)) sigsetup(void) {
 	struct sigaction act;
-	act.sa_handler = &sighandler;
-	sigaction(SIGSEGV, &act, 0);
+
+	memset(&act, 0, sizeof act);
+	act.sa_handler = segvhandler;
+	sigaction(SIGSEGV, &act, NULL);
+
+	act.sa_handler = iohandler;
+	sigaction(SIGIO, &act, NULL);
 }
 */
 import "C"
diff --git a/misc/ios/detect.go b/misc/ios/detect.go
index d305458..53749ad 100644
--- a/misc/ios/detect.go
+++ b/misc/ios/detect.go
@@ -55,6 +55,9 @@ func detectDevID() string {
 		if !bytes.Contains(line, []byte("iPhone Developer")) {
 			continue
 		}
+		if bytes.Contains(line, []byte("REVOKED")) {
+			continue
+		}
 		fields := bytes.Fields(line)
 		return string(fields[1])
 	}
diff --git a/misc/ios/go_darwin_arm_exec.go b/misc/ios/go_darwin_arm_exec.go
index 3131b15..828efe9 100644
--- a/misc/ios/go_darwin_arm_exec.go
+++ b/misc/ios/go_darwin_arm_exec.go
@@ -103,7 +103,7 @@ func main() {
 func getenv(envvar string) string {
 	s := os.Getenv(envvar)
 	if s == "" {
-		log.Fatalf("%s not set\nrun $GOROOT/misc/ios/detect.go to attempt to autodetect", s)
+		log.Fatalf("%s not set\nrun $GOROOT/misc/ios/detect.go to attempt to autodetect", envvar)
 	}
 	return s
 }
diff --git a/misc/nacl/testzip.proto b/misc/nacl/testzip.proto
index bc382d5..4e82ac9 100644
--- a/misc/nacl/testzip.proto
+++ b/misc/nacl/testzip.proto
@@ -27,15 +27,18 @@ go	src=..
 			internal
 				objfile
 					objfile.go
-				rsc.io
-					arm
-						armasm
-							testdata
-								+
-					x86
-						x86asm
-							testdata
-								+
+				unvendor
+					golang.org
+							x
+								arch
+									arm
+										armasm
+											testdata
+													+
+									x86
+										x86asm
+											testdata
+													+
 			gofmt
 				gofmt.go
 				gofmt_test.go
diff --git a/misc/sortac/sortac.go b/misc/sortac/sortac.go
new file mode 100644
index 0000000..f61aa96
--- /dev/null
+++ b/misc/sortac/sortac.go
@@ -0,0 +1,79 @@
+// Copyright 2015 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.
+
+// Sortac sorts the AUTHORS and CONTRIBUTORS files.
+//
+// Usage:
+//
+//    sortac [file...]
+//
+// Sortac sorts the named files in place.
+// If given no arguments, it sorts standard input to standard output.
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"flag"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"os"
+
+	"golang.org/x/text/collate"
+	"golang.org/x/text/language"
+)
+
+func main() {
+	log.SetFlags(0)
+	log.SetPrefix("sortac: ")
+	flag.Parse()
+
+	args := flag.Args()
+	if len(args) == 0 {
+		os.Stdout.Write(sortAC(os.Stdin))
+	} else {
+		for _, arg := range args {
+			f, err := os.Open(arg)
+			if err != nil {
+				log.Fatal(err)
+			}
+			sorted := sortAC(f)
+			f.Close()
+			if err := ioutil.WriteFile(arg, sorted, 0644); err != nil {
+				log.Fatal(err)
+			}
+		}
+	}
+}
+
+func sortAC(r io.Reader) []byte {
+	bs := bufio.NewScanner(r)
+	var header []string
+	var lines []string
+	for bs.Scan() {
+		t := bs.Text()
+		lines = append(lines, t)
+		if t == "# Please keep the list sorted." {
+			header = lines
+			lines = nil
+			continue
+		}
+	}
+	if err := bs.Err(); err != nil {
+		log.Fatal(err)
+	}
+
+	var out bytes.Buffer
+	c := collate.New(language.Und, collate.Loose)
+	c.SortStrings(lines)
+	for _, l := range header {
+		fmt.Fprintln(&out, l)
+	}
+	for _, l := range lines {
+		fmt.Fprintln(&out, l)
+	}
+	return out.Bytes()
+}
diff --git a/src/androidtest.bash b/src/androidtest.bash
index 0010738..84c2222 100755
--- a/src/androidtest.bash
+++ b/src/androidtest.bash
@@ -23,6 +23,14 @@ if [ "$GOOS" != "android" ]; then
 	exit 1
 fi
 
+if [ -z $GOARM ]; then
+	export GOARM=7
+fi
+if [ "$GOARM" != "7" ]; then
+	echo "android only supports GOARM=7, got GOARM=$GOARM" 1>&2
+	exit 1
+fi
+
 export CGO_ENABLED=1
 unset GOBIN
 
@@ -56,7 +64,16 @@ mkdir -p $FAKE_GOROOT/pkg
 cp -a "${GOROOT}/src" "${FAKE_GOROOT}/"
 cp -a "${GOROOT}/test" "${FAKE_GOROOT}/"
 cp -a "${GOROOT}/lib" "${FAKE_GOROOT}/"
-cp -a "${GOROOT}/pkg/android_$GOARCH" "${FAKE_GOROOT}/pkg/"
+
+# For android, the go tool will install the compiled package in
+# pkg/android_${GOARCH}_shared directory by default, not in
+# the usual pkg/${GOOS}_${GOARCH}. Some tests in src/go/* assume
+# the compiled packages were installed in the usual places.
+# Instead of reflecting this exception into the go/* packages,
+# we copy the compiled packages into the usual places.
+cp -a "${GOROOT}/pkg/android_${GOARCH}_shared" "${FAKE_GOROOT}/pkg/"
+mv "${FAKE_GOROOT}/pkg/android_${GOARCH}_shared" "${FAKE_GOROOT}/pkg/android_${GOARCH}"
+
 echo '# Syncing test files to android device'
 adb shell mkdir -p /data/local/tmp/goroot
 time adb sync data &> /dev/null
diff --git a/src/archive/tar/common.go b/src/archive/tar/common.go
index c31df06..36f4e23 100644
--- a/src/archive/tar/common.go
+++ b/src/archive/tar/common.go
@@ -327,3 +327,14 @@ func toASCII(s string) string {
 	}
 	return buf.String()
 }
+
+// isHeaderOnlyType checks if the given type flag is of the type that has no
+// data section even if a size is specified.
+func isHeaderOnlyType(flag byte) bool {
+	switch flag {
+	case TypeLink, TypeSymlink, TypeChar, TypeBlock, TypeDir, TypeFifo:
+		return true
+	default:
+		return false
+	}
+}
diff --git a/src/archive/tar/example_test.go b/src/archive/tar/example_test.go
index 2317f44..5f0ce2f 100644
--- a/src/archive/tar/example_test.go
+++ b/src/archive/tar/example_test.go
@@ -26,7 +26,7 @@ func Example() {
 	}{
 		{"readme.txt", "This archive contains some text files."},
 		{"gopher.txt", "Gopher names:\nGeorge\nGeoffrey\nGonzo"},
-		{"todo.txt", "Get animal handling licence."},
+		{"todo.txt", "Get animal handling license."},
 	}
 	for _, file := range files {
 		hdr := &tar.Header{
@@ -76,5 +76,5 @@ func Example() {
 	// Geoffrey
 	// Gonzo
 	// Contents of todo.txt:
-	// Get animal handling licence.
+	// Get animal handling license.
 }
diff --git a/src/archive/tar/reader.go b/src/archive/tar/reader.go
index 67daca2..c8cb69a 100644
--- a/src/archive/tar/reader.go
+++ b/src/archive/tar/reader.go
@@ -12,6 +12,7 @@ import (
 	"errors"
 	"io"
 	"io/ioutil"
+	"math"
 	"os"
 	"strconv"
 	"strings"
@@ -36,6 +37,10 @@ type Reader struct {
 	hdrBuff [blockSize]byte // buffer to use in readHeader
 }
 
+type parser struct {
+	err error // Last error seen
+}
+
 // A numBytesReader is an io.Reader with a numBytes method, returning the number
 // of bytes remaining in the underlying encoded data.
 type numBytesReader interface {
@@ -49,12 +54,36 @@ type regFileReader struct {
 	nb int64     // number of unread bytes for current file entry
 }
 
-// A sparseFileReader is a numBytesReader for reading sparse file data from a tar archive.
+// A sparseFileReader is a numBytesReader for reading sparse file data from a
+// tar archive.
 type sparseFileReader struct {
-	rfr *regFileReader // reads the sparse-encoded file data
-	sp  []sparseEntry  // the sparse map for the file
-	pos int64          // keeps track of file position
-	tot int64          // total size of the file
+	rfr   numBytesReader // Reads the sparse-encoded file data
+	sp    []sparseEntry  // The sparse map for the file
+	pos   int64          // Keeps track of file position
+	total int64          // Total size of the file
+}
+
+// A sparseEntry holds a single entry in a sparse file's sparse map.
+//
+// Sparse files are represented using a series of sparseEntrys.
+// Despite the name, a sparseEntry represents an actual data fragment that
+// references data found in the underlying archive stream. All regions not
+// covered by a sparseEntry are logically filled with zeros.
+//
+// For example, if the underlying raw file contains the 10-byte data:
+//	var compactData = "abcdefgh"
+//
+// And the sparse map has the following entries:
+//	var sp = []sparseEntry{
+//		{offset: 2,  numBytes: 5} // Data fragment for [2..7]
+//		{offset: 18, numBytes: 3} // Data fragment for [18..21]
+//	}
+//
+// Then the content of the resulting sparse file with a "real" size of 25 is:
+//	var sparseData = "\x00"*2 + "abcde" + "\x00"*11 + "fgh" + "\x00"*4
+type sparseEntry struct {
+	offset   int64 // Starting position of the fragment
+	numBytes int64 // Length of the fragment
 }
 
 // Keywords for GNU sparse files in a PAX extended header
@@ -88,69 +117,82 @@ func NewReader(r io.Reader) *Reader { return &Reader{r: r} }
 //
 // io.EOF is returned at the end of the input.
 func (tr *Reader) Next() (*Header, error) {
-	var hdr *Header
-	if tr.err == nil {
-		tr.skipUnread()
-	}
 	if tr.err != nil {
-		return hdr, tr.err
-	}
-	hdr = tr.readHeader()
-	if hdr == nil {
-		return hdr, tr.err
+		return nil, tr.err
 	}
-	// Check for PAX/GNU header.
-	switch hdr.Typeflag {
-	case TypeXHeader:
-		//  PAX extended header
-		headers, err := parsePAX(tr)
-		if err != nil {
-			return nil, err
-		}
-		// We actually read the whole file,
-		// but this skips alignment padding
-		tr.skipUnread()
+
+	var hdr *Header
+	var extHdrs map[string]string
+
+	// Externally, Next iterates through the tar archive as if it is a series of
+	// files. Internally, the tar format often uses fake "files" to add meta
+	// data that describes the next file. These meta data "files" should not
+	// normally be visible to the outside. As such, this loop iterates through
+	// one or more "header files" until it finds a "normal file".
+loop:
+	for {
+		tr.err = tr.skipUnread()
 		if tr.err != nil {
 			return nil, tr.err
 		}
+
 		hdr = tr.readHeader()
-		if hdr == nil {
+		if tr.err != nil {
 			return nil, tr.err
 		}
-		mergePAX(hdr, headers)
 
-		// Check for a PAX format sparse file
-		sp, err := tr.checkForGNUSparsePAXHeaders(hdr, headers)
-		if err != nil {
-			tr.err = err
-			return nil, err
-		}
-		if sp != nil {
-			// Current file is a PAX format GNU sparse file.
-			// Set the current file reader to a sparse file reader.
-			tr.curr = &sparseFileReader{rfr: tr.curr.(*regFileReader), sp: sp, tot: hdr.Size}
-		}
-		return hdr, nil
-	case TypeGNULongName:
-		// We have a GNU long name header. Its contents are the real file name.
-		realname, err := ioutil.ReadAll(tr)
-		if err != nil {
-			return nil, err
-		}
-		hdr, err := tr.Next()
-		hdr.Name = cString(realname)
-		return hdr, err
-	case TypeGNULongLink:
-		// We have a GNU long link header.
-		realname, err := ioutil.ReadAll(tr)
-		if err != nil {
-			return nil, err
+		// Check for PAX/GNU special headers and files.
+		switch hdr.Typeflag {
+		case TypeXHeader:
+			extHdrs, tr.err = parsePAX(tr)
+			if tr.err != nil {
+				return nil, tr.err
+			}
+			continue loop // This is a meta header affecting the next header
+		case TypeGNULongName, TypeGNULongLink:
+			var realname []byte
+			realname, tr.err = ioutil.ReadAll(tr)
+			if tr.err != nil {
+				return nil, tr.err
+			}
+
+			// Convert GNU extensions to use PAX headers.
+			if extHdrs == nil {
+				extHdrs = make(map[string]string)
+			}
+			var p parser
+			switch hdr.Typeflag {
+			case TypeGNULongName:
+				extHdrs[paxPath] = p.parseString(realname)
+			case TypeGNULongLink:
+				extHdrs[paxLinkpath] = p.parseString(realname)
+			}
+			if p.err != nil {
+				tr.err = p.err
+				return nil, tr.err
+			}
+			continue loop // This is a meta header affecting the next header
+		default:
+			mergePAX(hdr, extHdrs)
+
+			// Check for a PAX format sparse file
+			sp, err := tr.checkForGNUSparsePAXHeaders(hdr, extHdrs)
+			if err != nil {
+				tr.err = err
+				return nil, err
+			}
+			if sp != nil {
+				// Current file is a PAX format GNU sparse file.
+				// Set the current file reader to a sparse file reader.
+				tr.curr, tr.err = newSparseFileReader(tr.curr, sp, hdr.Size)
+				if tr.err != nil {
+					return nil, tr.err
+				}
+			}
+			break loop // This is a file, so stop
 		}
-		hdr, err := tr.Next()
-		hdr.Linkname = cString(realname)
-		return hdr, err
 	}
-	return hdr, tr.err
+	return hdr, nil
 }
 
 // checkForGNUSparsePAXHeaders checks the PAX headers for GNU sparse headers. If they are found, then
@@ -321,6 +363,7 @@ func parsePAX(r io.Reader) (map[string]string, error) {
 	if err != nil {
 		return nil, err
 	}
+	sbuf := string(buf)
 
 	// For GNU PAX sparse format 0.0 support.
 	// This function transforms the sparse format 0.0 headers into sparse format 0.1 headers.
@@ -329,35 +372,17 @@ func parsePAX(r io.Reader) (map[string]string, error) {
 	headers := make(map[string]string)
 	// Each record is constructed as
 	//     "%d %s=%s\n", length, keyword, value
-	for len(buf) > 0 {
-		// or the header was empty to start with.
-		var sp int
-		// The size field ends at the first space.
-		sp = bytes.IndexByte(buf, ' ')
-		if sp == -1 {
-			return nil, ErrHeader
-		}
-		// Parse the first token as a decimal integer.
-		n, err := strconv.ParseInt(string(buf[:sp]), 10, 0)
-		if err != nil || n < 5 || int64(len(buf)) < n {
-			return nil, ErrHeader
-		}
-		// Extract everything between the decimal and the n -1 on the
-		// beginning to eat the ' ', -1 on the end to skip the newline.
-		var record []byte
-		record, buf = buf[sp+1:n-1], buf[n:]
-		// The first equals is guaranteed to mark the end of the key.
-		// Everything else is value.
-		eq := bytes.IndexByte(record, '=')
-		if eq == -1 {
+	for len(sbuf) > 0 {
+		key, value, residual, err := parsePAXRecord(sbuf)
+		if err != nil {
 			return nil, ErrHeader
 		}
-		key, value := record[:eq], record[eq+1:]
+		sbuf = residual
 
 		keyStr := string(key)
 		if keyStr == paxGNUSparseOffset || keyStr == paxGNUSparseNumBytes {
 			// GNU sparse format 0.0 special key. Write to sparseMap instead of using the headers map.
-			sparseMap.Write(value)
+			sparseMap.WriteString(value)
 			sparseMap.Write([]byte{','})
 		} else {
 			// Normal key. Set the value in the headers map.
@@ -372,9 +397,42 @@ func parsePAX(r io.Reader) (map[string]string, error) {
 	return headers, nil
 }
 
-// cString parses bytes as a NUL-terminated C-style string.
+// parsePAXRecord parses the input PAX record string into a key-value pair.
+// If parsing is successful, it will slice off the currently read record and
+// return the remainder as r.
+//
+// A PAX record is of the following form:
+//	"%d %s=%s\n" % (size, key, value)
+func parsePAXRecord(s string) (k, v, r string, err error) {
+	// The size field ends at the first space.
+	sp := strings.IndexByte(s, ' ')
+	if sp == -1 {
+		return "", "", s, ErrHeader
+	}
+
+	// Parse the first token as a decimal integer.
+	n, perr := strconv.ParseInt(s[:sp], 10, 0) // Intentionally parse as native int
+	if perr != nil || n < 5 || int64(len(s)) < n {
+		return "", "", s, ErrHeader
+	}
+
+	// Extract everything between the space and the final newline.
+	rec, nl, rem := s[sp+1:n-1], s[n-1:n], s[n:]
+	if nl != "\n" {
+		return "", "", s, ErrHeader
+	}
+
+	// The first equals separates the key from the value.
+	eq := strings.IndexByte(rec, '=')
+	if eq == -1 {
+		return "", "", s, ErrHeader
+	}
+	return rec[:eq], rec[eq+1:], rem, nil
+}
+
+// parseString parses bytes as a NUL-terminated C-style string.
 // If a NUL byte is not found then the whole slice is returned as a string.
-func cString(b []byte) string {
+func (*parser) parseString(b []byte) string {
 	n := 0
 	for n < len(b) && b[n] != 0 {
 		n++
@@ -382,19 +440,51 @@ func cString(b []byte) string {
 	return string(b[0:n])
 }
 
-func (tr *Reader) octal(b []byte) int64 {
-	// Check for binary format first.
+// parseNumeric parses the input as being encoded in either base-256 or octal.
+// This function may return negative numbers.
+// If parsing fails or an integer overflow occurs, err will be set.
+func (p *parser) parseNumeric(b []byte) int64 {
+	// Check for base-256 (binary) format first.
+	// If the first bit is set, then all following bits constitute a two's
+	// complement encoded number in big-endian byte order.
 	if len(b) > 0 && b[0]&0x80 != 0 {
-		var x int64
+		// Handling negative numbers relies on the following identity:
+		//	-a-1 == ^a
+		//
+		// If the number is negative, we use an inversion mask to invert the
+		// data bytes and treat the value as an unsigned number.
+		var inv byte // 0x00 if positive or zero, 0xff if negative
+		if b[0]&0x40 != 0 {
+			inv = 0xff
+		}
+
+		var x uint64
 		for i, c := range b {
+			c ^= inv // Inverts c only if inv is 0xff, otherwise does nothing
 			if i == 0 {
-				c &= 0x7f // ignore signal bit in first byte
+				c &= 0x7f // Ignore signal bit in first byte
+			}
+			if (x >> 56) > 0 {
+				p.err = ErrHeader // Integer overflow
+				return 0
 			}
-			x = x<<8 | int64(c)
+			x = x<<8 | uint64(c)
+		}
+		if (x >> 63) > 0 {
+			p.err = ErrHeader // Integer overflow
+			return 0
+		}
+		if inv == 0xff {
+			return ^int64(x)
 		}
-		return x
+		return int64(x)
 	}
 
+	// Normal case is base-8 (octal) format.
+	return p.parseOctal(b)
+}
+
+func (p *parser) parseOctal(b []byte) int64 {
 	// Because unused fields are filled with NULs, we need
 	// to skip leading NULs. Fields may also be padded with
 	// spaces or NULs.
@@ -405,23 +495,52 @@ func (tr *Reader) octal(b []byte) int64 {
 	if len(b) == 0 {
 		return 0
 	}
-	x, err := strconv.ParseUint(cString(b), 8, 64)
-	if err != nil {
-		tr.err = err
+	x, perr := strconv.ParseUint(p.parseString(b), 8, 64)
+	if perr != nil {
+		p.err = ErrHeader
 	}
 	return int64(x)
 }
 
-// skipUnread skips any unread bytes in the existing file entry, as well as any alignment padding.
-func (tr *Reader) skipUnread() {
-	nr := tr.numBytes() + tr.pad // number of bytes to skip
+// skipUnread skips any unread bytes in the existing file entry, as well as any
+// alignment padding. It returns io.ErrUnexpectedEOF if any io.EOF is
+// encountered in the data portion; it is okay to hit io.EOF in the padding.
+//
+// Note that this function still works properly even when sparse files are being
+// used since numBytes returns the bytes remaining in the underlying io.Reader.
+func (tr *Reader) skipUnread() error {
+	dataSkip := tr.numBytes()      // Number of data bytes to skip
+	totalSkip := dataSkip + tr.pad // Total number of bytes to skip
 	tr.curr, tr.pad = nil, 0
-	if sr, ok := tr.r.(io.Seeker); ok {
-		if _, err := sr.Seek(nr, os.SEEK_CUR); err == nil {
-			return
+
+	// If possible, Seek to the last byte before the end of the data section.
+	// Do this because Seek is often lazy about reporting errors; this will mask
+	// the fact that the tar stream may be truncated. We can rely on the
+	// io.CopyN done shortly afterwards to trigger any IO errors.
+	var seekSkipped int64 // Number of bytes skipped via Seek
+	if sr, ok := tr.r.(io.Seeker); ok && dataSkip > 1 {
+		// Not all io.Seeker can actually Seek. For example, os.Stdin implements
+		// io.Seeker, but calling Seek always returns an error and performs
+		// no action. Thus, we try an innocent seek to the current position
+		// to see if Seek is really supported.
+		pos1, err := sr.Seek(0, os.SEEK_CUR)
+		if err == nil {
+			// Seek seems supported, so perform the real Seek.
+			pos2, err := sr.Seek(dataSkip-1, os.SEEK_CUR)
+			if err != nil {
+				tr.err = err
+				return tr.err
+			}
+			seekSkipped = pos2 - pos1
 		}
 	}
-	_, tr.err = io.CopyN(ioutil.Discard, tr.r, nr)
+
+	var copySkipped int64 // Number of bytes skipped via CopyN
+	copySkipped, tr.err = io.CopyN(ioutil.Discard, tr.r, totalSkip-seekSkipped)
+	if tr.err == io.EOF && seekSkipped+copySkipped < dataSkip {
+		tr.err = io.ErrUnexpectedEOF
+	}
+	return tr.err
 }
 
 func (tr *Reader) verifyChecksum(header []byte) bool {
@@ -429,23 +548,31 @@ func (tr *Reader) verifyChecksum(header []byte) bool {
 		return false
 	}
 
-	given := tr.octal(header[148:156])
+	var p parser
+	given := p.parseOctal(header[148:156])
 	unsigned, signed := checksum(header)
-	return given == unsigned || given == signed
+	return p.err == nil && (given == unsigned || given == signed)
 }
 
+// readHeader reads the next block header and assumes that the underlying reader
+// is already aligned to a block boundary.
+//
+// The err will be set to io.EOF only when one of the following occurs:
+//	* Exactly 0 bytes are read and EOF is hit.
+//	* Exactly 1 block of zeros is read and EOF is hit.
+//	* At least 2 blocks of zeros are read.
 func (tr *Reader) readHeader() *Header {
 	header := tr.hdrBuff[:]
 	copy(header, zeroBlock)
 
 	if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil {
-		return nil
+		return nil // io.EOF is okay here
 	}
 
 	// Two blocks of zero bytes marks the end of the archive.
 	if bytes.Equal(header, zeroBlock[0:blockSize]) {
 		if _, tr.err = io.ReadFull(tr.r, header); tr.err != nil {
-			return nil
+			return nil // io.EOF is okay here
 		}
 		if bytes.Equal(header, zeroBlock[0:blockSize]) {
 			tr.err = io.EOF
@@ -461,22 +588,19 @@ func (tr *Reader) readHeader() *Header {
 	}
 
 	// Unpack
+	var p parser
 	hdr := new(Header)
 	s := slicer(header)
 
-	hdr.Name = cString(s.next(100))
-	hdr.Mode = tr.octal(s.next(8))
-	hdr.Uid = int(tr.octal(s.next(8)))
-	hdr.Gid = int(tr.octal(s.next(8)))
-	hdr.Size = tr.octal(s.next(12))
-	if hdr.Size < 0 {
-		tr.err = ErrHeader
-		return nil
-	}
-	hdr.ModTime = time.Unix(tr.octal(s.next(12)), 0)
+	hdr.Name = p.parseString(s.next(100))
+	hdr.Mode = p.parseNumeric(s.next(8))
+	hdr.Uid = int(p.parseNumeric(s.next(8)))
+	hdr.Gid = int(p.parseNumeric(s.next(8)))
+	hdr.Size = p.parseNumeric(s.next(12))
+	hdr.ModTime = time.Unix(p.parseNumeric(s.next(12)), 0)
 	s.next(8) // chksum
 	hdr.Typeflag = s.next(1)[0]
-	hdr.Linkname = cString(s.next(100))
+	hdr.Linkname = p.parseString(s.next(100))
 
 	// The remainder of the header depends on the value of magic.
 	// The original (v7) version of tar had no explicit magic field,
@@ -496,70 +620,76 @@ func (tr *Reader) readHeader() *Header {
 
 	switch format {
 	case "posix", "gnu", "star":
-		hdr.Uname = cString(s.next(32))
-		hdr.Gname = cString(s.next(32))
+		hdr.Uname = p.parseString(s.next(32))
+		hdr.Gname = p.parseString(s.next(32))
 		devmajor := s.next(8)
 		devminor := s.next(8)
 		if hdr.Typeflag == TypeChar || hdr.Typeflag == TypeBlock {
-			hdr.Devmajor = tr.octal(devmajor)
-			hdr.Devminor = tr.octal(devminor)
+			hdr.Devmajor = p.parseNumeric(devmajor)
+			hdr.Devminor = p.parseNumeric(devminor)
 		}
 		var prefix string
 		switch format {
 		case "posix", "gnu":
-			prefix = cString(s.next(155))
+			prefix = p.parseString(s.next(155))
 		case "star":
-			prefix = cString(s.next(131))
-			hdr.AccessTime = time.Unix(tr.octal(s.next(12)), 0)
-			hdr.ChangeTime = time.Unix(tr.octal(s.next(12)), 0)
+			prefix = p.parseString(s.next(131))
+			hdr.AccessTime = time.Unix(p.parseNumeric(s.next(12)), 0)
+			hdr.ChangeTime = time.Unix(p.parseNumeric(s.next(12)), 0)
 		}
 		if len(prefix) > 0 {
 			hdr.Name = prefix + "/" + hdr.Name
 		}
 	}
 
-	if tr.err != nil {
-		tr.err = ErrHeader
+	if p.err != nil {
+		tr.err = p.err
 		return nil
 	}
 
-	// Maximum value of hdr.Size is 64 GB (12 octal digits),
-	// so there's no risk of int64 overflowing.
-	nb := int64(hdr.Size)
-	tr.pad = -nb & (blockSize - 1) // blockSize is a power of two
+	nb := hdr.Size
+	if isHeaderOnlyType(hdr.Typeflag) {
+		nb = 0
+	}
+	if nb < 0 {
+		tr.err = ErrHeader
+		return nil
+	}
 
 	// Set the current file reader.
+	tr.pad = -nb & (blockSize - 1) // blockSize is a power of two
 	tr.curr = &regFileReader{r: tr.r, nb: nb}
 
 	// Check for old GNU sparse format entry.
 	if hdr.Typeflag == TypeGNUSparse {
 		// Get the real size of the file.
-		hdr.Size = tr.octal(header[483:495])
+		hdr.Size = p.parseNumeric(header[483:495])
+		if p.err != nil {
+			tr.err = p.err
+			return nil
+		}
 
 		// Read the sparse map.
 		sp := tr.readOldGNUSparseMap(header)
 		if tr.err != nil {
 			return nil
 		}
+
 		// Current file is a GNU sparse file. Update the current file reader.
-		tr.curr = &sparseFileReader{rfr: tr.curr.(*regFileReader), sp: sp, tot: hdr.Size}
+		tr.curr, tr.err = newSparseFileReader(tr.curr, sp, hdr.Size)
+		if tr.err != nil {
+			return nil
+		}
 	}
 
 	return hdr
 }
 
-// A sparseEntry holds a single entry in a sparse file's sparse map.
-// A sparse entry indicates the offset and size in a sparse file of a
-// block of data.
-type sparseEntry struct {
-	offset   int64
-	numBytes int64
-}
-
 // readOldGNUSparseMap reads the sparse map as stored in the old GNU sparse format.
 // The sparse map is stored in the tar header if it's small enough. If it's larger than four entries,
 // then one or more extension headers are used to store the rest of the sparse map.
 func (tr *Reader) readOldGNUSparseMap(header []byte) []sparseEntry {
+	var p parser
 	isExtended := header[oldGNUSparseMainHeaderIsExtendedOffset] != 0
 	spCap := oldGNUSparseMainHeaderNumEntries
 	if isExtended {
@@ -570,10 +700,10 @@ func (tr *Reader) readOldGNUSparseMap(header []byte) []sparseEntry {
 
 	// Read the four entries from the main tar header
 	for i := 0; i < oldGNUSparseMainHeaderNumEntries; i++ {
-		offset := tr.octal(s.next(oldGNUSparseOffsetSize))
-		numBytes := tr.octal(s.next(oldGNUSparseNumBytesSize))
-		if tr.err != nil {
-			tr.err = ErrHeader
+		offset := p.parseNumeric(s.next(oldGNUSparseOffsetSize))
+		numBytes := p.parseNumeric(s.next(oldGNUSparseNumBytesSize))
+		if p.err != nil {
+			tr.err = p.err
 			return nil
 		}
 		if offset == 0 && numBytes == 0 {
@@ -591,10 +721,10 @@ func (tr *Reader) readOldGNUSparseMap(header []byte) []sparseEntry {
 		isExtended = sparseHeader[oldGNUSparseExtendedHeaderIsExtendedOffset] != 0
 		s = slicer(sparseHeader)
 		for i := 0; i < oldGNUSparseExtendedHeaderNumEntries; i++ {
-			offset := tr.octal(s.next(oldGNUSparseOffsetSize))
-			numBytes := tr.octal(s.next(oldGNUSparseNumBytesSize))
-			if tr.err != nil {
-				tr.err = ErrHeader
+			offset := p.parseNumeric(s.next(oldGNUSparseOffsetSize))
+			numBytes := p.parseNumeric(s.next(oldGNUSparseNumBytesSize))
+			if p.err != nil {
+				tr.err = p.err
 				return nil
 			}
 			if offset == 0 && numBytes == 0 {
@@ -606,122 +736,111 @@ func (tr *Reader) readOldGNUSparseMap(header []byte) []sparseEntry {
 	return sp
 }
 
-// readGNUSparseMap1x0 reads the sparse map as stored in GNU's PAX sparse format version 1.0.
-// The sparse map is stored just before the file data and padded out to the nearest block boundary.
+// readGNUSparseMap1x0 reads the sparse map as stored in GNU's PAX sparse format
+// version 1.0. The format of the sparse map consists of a series of
+// newline-terminated numeric fields. The first field is the number of entries
+// and is always present. Following this are the entries, consisting of two
+// fields (offset, numBytes). This function must stop reading at the end
+// boundary of the block containing the last newline.
+//
+// Note that the GNU manual says that numeric values should be encoded in octal
+// format. However, the GNU tar utility itself outputs these values in decimal.
+// As such, this library treats values as being encoded in decimal.
 func readGNUSparseMap1x0(r io.Reader) ([]sparseEntry, error) {
-	buf := make([]byte, 2*blockSize)
-	sparseHeader := buf[:blockSize]
-
-	// readDecimal is a helper function to read a decimal integer from the sparse map
-	// while making sure to read from the file in blocks of size blockSize
-	readDecimal := func() (int64, error) {
-		// Look for newline
-		nl := bytes.IndexByte(sparseHeader, '\n')
-		if nl == -1 {
-			if len(sparseHeader) >= blockSize {
-				// This is an error
-				return 0, ErrHeader
-			}
-			oldLen := len(sparseHeader)
-			newLen := oldLen + blockSize
-			if cap(sparseHeader) < newLen {
-				// There's more header, but we need to make room for the next block
-				copy(buf, sparseHeader)
-				sparseHeader = buf[:newLen]
-			} else {
-				// There's more header, and we can just reslice
-				sparseHeader = sparseHeader[:newLen]
-			}
-
-			// Now that sparseHeader is large enough, read next block
-			if _, err := io.ReadFull(r, sparseHeader[oldLen:newLen]); err != nil {
-				return 0, err
+	var cntNewline int64
+	var buf bytes.Buffer
+	var blk = make([]byte, blockSize)
+
+	// feedTokens copies data in numBlock chunks from r into buf until there are
+	// at least cnt newlines in buf. It will not read more blocks than needed.
+	var feedTokens = func(cnt int64) error {
+		for cntNewline < cnt {
+			if _, err := io.ReadFull(r, blk); err != nil {
+				if err == io.EOF {
+					err = io.ErrUnexpectedEOF
+				}
+				return err
 			}
-
-			// Look for a newline in the new data
-			nl = bytes.IndexByte(sparseHeader[oldLen:newLen], '\n')
-			if nl == -1 {
-				// This is an error
-				return 0, ErrHeader
+			buf.Write(blk)
+			for _, c := range blk {
+				if c == '\n' {
+					cntNewline++
+				}
 			}
-			nl += oldLen // We want the position from the beginning
-		}
-		// Now that we've found a newline, read a number
-		n, err := strconv.ParseInt(string(sparseHeader[:nl]), 10, 0)
-		if err != nil {
-			return 0, ErrHeader
 		}
+		return nil
+	}
 
-		// Update sparseHeader to consume this number
-		sparseHeader = sparseHeader[nl+1:]
-		return n, nil
+	// nextToken gets the next token delimited by a newline. This assumes that
+	// at least one newline exists in the buffer.
+	var nextToken = func() string {
+		cntNewline--
+		tok, _ := buf.ReadString('\n')
+		return tok[:len(tok)-1] // Cut off newline
 	}
 
-	// Read the first block
-	if _, err := io.ReadFull(r, sparseHeader); err != nil {
+	// Parse for the number of entries.
+	// Use integer overflow resistant math to check this.
+	if err := feedTokens(1); err != nil {
 		return nil, err
 	}
+	numEntries, err := strconv.ParseInt(nextToken(), 10, 0) // Intentionally parse as native int
+	if err != nil || numEntries < 0 || int(2*numEntries) < int(numEntries) {
+		return nil, ErrHeader
+	}
 
-	// The first line contains the number of entries
-	numEntries, err := readDecimal()
-	if err != nil {
+	// Parse for all member entries.
+	// numEntries is trusted after this since a potential attacker must have
+	// committed resources proportional to what this library used.
+	if err := feedTokens(2 * numEntries); err != nil {
 		return nil, err
 	}
-
-	// Read all the entries
 	sp := make([]sparseEntry, 0, numEntries)
 	for i := int64(0); i < numEntries; i++ {
-		// Read the offset
-		offset, err := readDecimal()
+		offset, err := strconv.ParseInt(nextToken(), 10, 64)
 		if err != nil {
-			return nil, err
+			return nil, ErrHeader
 		}
-		// Read numBytes
-		numBytes, err := readDecimal()
+		numBytes, err := strconv.ParseInt(nextToken(), 10, 64)
 		if err != nil {
-			return nil, err
+			return nil, ErrHeader
 		}
-
 		sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes})
 	}
-
 	return sp, nil
 }
 
-// readGNUSparseMap0x1 reads the sparse map as stored in GNU's PAX sparse format version 0.1.
-// The sparse map is stored in the PAX headers.
-func readGNUSparseMap0x1(headers map[string]string) ([]sparseEntry, error) {
-	// Get number of entries
-	numEntriesStr, ok := headers[paxGNUSparseNumBlocks]
-	if !ok {
-		return nil, ErrHeader
-	}
-	numEntries, err := strconv.ParseInt(numEntriesStr, 10, 0)
-	if err != nil {
+// readGNUSparseMap0x1 reads the sparse map as stored in GNU's PAX sparse format
+// version 0.1. The sparse map is stored in the PAX headers.
+func readGNUSparseMap0x1(extHdrs map[string]string) ([]sparseEntry, error) {
+	// Get number of entries.
+	// Use integer overflow resistant math to check this.
+	numEntriesStr := extHdrs[paxGNUSparseNumBlocks]
+	numEntries, err := strconv.ParseInt(numEntriesStr, 10, 0) // Intentionally parse as native int
+	if err != nil || numEntries < 0 || int(2*numEntries) < int(numEntries) {
 		return nil, ErrHeader
 	}
 
-	sparseMap := strings.Split(headers[paxGNUSparseMap], ",")
-
-	// There should be two numbers in sparseMap for each entry
+	// There should be two numbers in sparseMap for each entry.
+	sparseMap := strings.Split(extHdrs[paxGNUSparseMap], ",")
 	if int64(len(sparseMap)) != 2*numEntries {
 		return nil, ErrHeader
 	}
 
-	// Loop through the entries in the sparse map
+	// Loop through the entries in the sparse map.
+	// numEntries is trusted now.
 	sp := make([]sparseEntry, 0, numEntries)
 	for i := int64(0); i < numEntries; i++ {
-		offset, err := strconv.ParseInt(sparseMap[2*i], 10, 0)
+		offset, err := strconv.ParseInt(sparseMap[2*i], 10, 64)
 		if err != nil {
 			return nil, ErrHeader
 		}
-		numBytes, err := strconv.ParseInt(sparseMap[2*i+1], 10, 0)
+		numBytes, err := strconv.ParseInt(sparseMap[2*i+1], 10, 64)
 		if err != nil {
 			return nil, ErrHeader
 		}
 		sp = append(sp, sparseEntry{offset: offset, numBytes: numBytes})
 	}
-
 	return sp, nil
 }
 
@@ -738,10 +857,18 @@ func (tr *Reader) numBytes() int64 {
 // Read reads from the current entry in the tar archive.
 // It returns 0, io.EOF when it reaches the end of that entry,
 // until Next is called to advance to the next entry.
+//
+// Calling Read on special types like TypeLink, TypeSymLink, TypeChar,
+// TypeBlock, TypeDir, and TypeFifo returns 0, io.EOF regardless of what
+// the Header.Size claims.
 func (tr *Reader) Read(b []byte) (n int, err error) {
+	if tr.err != nil {
+		return 0, tr.err
+	}
 	if tr.curr == nil {
 		return 0, io.EOF
 	}
+
 	n, err = tr.curr.Read(b)
 	if err != nil && err != io.EOF {
 		tr.err = err
@@ -771,9 +898,33 @@ func (rfr *regFileReader) numBytes() int64 {
 	return rfr.nb
 }
 
-// readHole reads a sparse file hole ending at offset toOffset
-func (sfr *sparseFileReader) readHole(b []byte, toOffset int64) int {
-	n64 := toOffset - sfr.pos
+// newSparseFileReader creates a new sparseFileReader, but validates all of the
+// sparse entries before doing so.
+func newSparseFileReader(rfr numBytesReader, sp []sparseEntry, total int64) (*sparseFileReader, error) {
+	if total < 0 {
+		return nil, ErrHeader // Total size cannot be negative
+	}
+
+	// Validate all sparse entries. These are the same checks as performed by
+	// the BSD tar utility.
+	for i, s := range sp {
+		switch {
+		case s.offset < 0 || s.numBytes < 0:
+			return nil, ErrHeader // Negative values are never okay
+		case s.offset > math.MaxInt64-s.numBytes:
+			return nil, ErrHeader // Integer overflow with large length
+		case s.offset+s.numBytes > total:
+			return nil, ErrHeader // Region extends beyond the "real" size
+		case i > 0 && sp[i-1].offset+sp[i-1].numBytes > s.offset:
+			return nil, ErrHeader // Regions can't overlap and must be in order
+		}
+	}
+	return &sparseFileReader{rfr: rfr, sp: sp, total: total}, nil
+}
+
+// readHole reads a sparse hole ending at endOffset.
+func (sfr *sparseFileReader) readHole(b []byte, endOffset int64) int {
+	n64 := endOffset - sfr.pos
 	if n64 > int64(len(b)) {
 		n64 = int64(len(b))
 	}
@@ -787,49 +938,54 @@ func (sfr *sparseFileReader) readHole(b []byte, toOffset int64) int {
 
 // Read reads the sparse file data in expanded form.
 func (sfr *sparseFileReader) Read(b []byte) (n int, err error) {
+	// Skip past all empty fragments.
+	for len(sfr.sp) > 0 && sfr.sp[0].numBytes == 0 {
+		sfr.sp = sfr.sp[1:]
+	}
+
+	// If there are no more fragments, then it is possible that there
+	// is one last sparse hole.
 	if len(sfr.sp) == 0 {
-		// No more data fragments to read from.
-		if sfr.pos < sfr.tot {
-			// We're in the last hole
-			n = sfr.readHole(b, sfr.tot)
-			return
+		// This behavior matches the BSD tar utility.
+		// However, GNU tar stops returning data even if sfr.total is unmet.
+		if sfr.pos < sfr.total {
+			return sfr.readHole(b, sfr.total), nil
 		}
-		// Otherwise, we're at the end of the file
 		return 0, io.EOF
 	}
-	if sfr.tot < sfr.sp[0].offset {
-		return 0, io.ErrUnexpectedEOF
-	}
+
+	// In front of a data fragment, so read a hole.
 	if sfr.pos < sfr.sp[0].offset {
-		// We're in a hole
-		n = sfr.readHole(b, sfr.sp[0].offset)
-		return
+		return sfr.readHole(b, sfr.sp[0].offset), nil
 	}
 
-	// We're not in a hole, so we'll read from the next data fragment
-	posInFragment := sfr.pos - sfr.sp[0].offset
-	bytesLeft := sfr.sp[0].numBytes - posInFragment
+	// In a data fragment, so read from it.
+	// This math is overflow free since we verify that offset and numBytes can
+	// be safely added when creating the sparseFileReader.
+	endPos := sfr.sp[0].offset + sfr.sp[0].numBytes // End offset of fragment
+	bytesLeft := endPos - sfr.pos                   // Bytes left in fragment
 	if int64(len(b)) > bytesLeft {
-		b = b[0:bytesLeft]
+		b = b[:bytesLeft]
 	}
 
 	n, err = sfr.rfr.Read(b)
 	sfr.pos += int64(n)
-
-	if int64(n) == bytesLeft {
-		// We're done with this fragment
-		sfr.sp = sfr.sp[1:]
+	if err == io.EOF {
+		if sfr.pos < endPos {
+			err = io.ErrUnexpectedEOF // There was supposed to be more data
+		} else if sfr.pos < sfr.total {
+			err = nil // There is still an implicit sparse hole at the end
+		}
 	}
 
-	if err == io.EOF && sfr.pos < sfr.tot {
-		// We reached the end of the last fragment's data, but there's a final hole
-		err = nil
+	if sfr.pos == endPos {
+		sfr.sp = sfr.sp[1:] // We are done with this fragment, so pop it
 	}
-	return
+	return n, err
 }
 
 // numBytes returns the number of bytes left to read in the sparse file's
 // sparse-encoded data in the tar archive.
 func (sfr *sparseFileReader) numBytes() int64 {
-	return sfr.rfr.nb
+	return sfr.rfr.numBytes()
 }
diff --git a/src/archive/tar/reader_test.go b/src/archive/tar/reader_test.go
index da01f26..7b148b5 100644
--- a/src/archive/tar/reader_test.go
+++ b/src/archive/tar/reader_test.go
@@ -10,6 +10,7 @@ import (
 	"fmt"
 	"io"
 	"io/ioutil"
+	"math"
 	"os"
 	"reflect"
 	"strings"
@@ -18,9 +19,10 @@ import (
 )
 
 type untarTest struct {
-	file    string
-	headers []*Header
-	cksums  []string
+	file    string    // Test input file
+	headers []*Header // Expected output headers
+	chksums []string  // MD5 checksum of files, leave as nil if not checked
+	err     error     // Expected error to occur
 }
 
 var gnuTarTest = &untarTest{
@@ -49,7 +51,7 @@ var gnuTarTest = &untarTest{
 			Gname:    "eng",
 		},
 	},
-	cksums: []string{
+	chksums: []string{
 		"e38b27eaccb4391bdec553a7f3ae6b2f",
 		"c65bd2e50a56a2138bf1716f2fd56fe9",
 	},
@@ -129,7 +131,7 @@ var sparseTarTest = &untarTest{
 			Devminor: 0,
 		},
 	},
-	cksums: []string{
+	chksums: []string{
 		"6f53234398c2449fe67c1812d993012f",
 		"6f53234398c2449fe67c1812d993012f",
 		"6f53234398c2449fe67c1812d993012f",
@@ -286,37 +288,119 @@ var untarTests = []*untarTest{
 			},
 		},
 	},
+	{
+		// Matches the behavior of GNU, BSD, and STAR tar utilities.
+		file: "testdata/gnu-multi-hdrs.tar",
+		headers: []*Header{
+			{
+				Name:     "GNU2/GNU2/long-path-name",
+				Linkname: "GNU4/GNU4/long-linkpath-name",
+				ModTime:  time.Unix(0, 0),
+				Typeflag: '2',
+			},
+		},
+	},
+	{
+		// Matches the behavior of GNU and BSD tar utilities.
+		file: "testdata/pax-multi-hdrs.tar",
+		headers: []*Header{
+			{
+				Name:     "bar",
+				Linkname: "PAX4/PAX4/long-linkpath-name",
+				ModTime:  time.Unix(0, 0),
+				Typeflag: '2',
+			},
+		},
+	},
+	{
+		file: "testdata/neg-size.tar",
+		err:  ErrHeader,
+	},
+	{
+		file: "testdata/issue10968.tar",
+		err:  ErrHeader,
+	},
+	{
+		file: "testdata/issue11169.tar",
+		err:  ErrHeader,
+	},
+	{
+		file: "testdata/issue12435.tar",
+		err:  ErrHeader,
+	},
 }
 
 func TestReader(t *testing.T) {
-testLoop:
-	for i, test := range untarTests {
-		f, err := os.Open(test.file)
+	for i, v := range untarTests {
+		f, err := os.Open(v.file)
 		if err != nil {
-			t.Errorf("test %d: Unexpected error: %v", i, err)
+			t.Errorf("file %s, test %d: unexpected error: %v", v.file, i, err)
 			continue
 		}
 		defer f.Close()
-		tr := NewReader(f)
-		for j, header := range test.headers {
-			hdr, err := tr.Next()
-			if err != nil || hdr == nil {
-				t.Errorf("test %d, entry %d: Didn't get entry: %v", i, j, err)
-				f.Close()
-				continue testLoop
+
+		// Capture all headers and checksums.
+		var (
+			tr      = NewReader(f)
+			hdrs    []*Header
+			chksums []string
+			rdbuf   = make([]byte, 8)
+		)
+		for {
+			var hdr *Header
+			hdr, err = tr.Next()
+			if err != nil {
+				if err == io.EOF {
+					err = nil // Expected error
+				}
+				break
 			}
-			if !reflect.DeepEqual(*hdr, *header) {
-				t.Errorf("test %d, entry %d: Incorrect header:\nhave %+v\nwant %+v",
-					i, j, *hdr, *header)
+			hdrs = append(hdrs, hdr)
+
+			if v.chksums == nil {
+				continue
+			}
+			h := md5.New()
+			_, err = io.CopyBuffer(h, tr, rdbuf) // Effectively an incremental read
+			if err != nil {
+				break
 			}
+			chksums = append(chksums, fmt.Sprintf("%x", h.Sum(nil)))
 		}
-		hdr, err := tr.Next()
-		if err == io.EOF {
-			continue testLoop
+
+		for j, hdr := range hdrs {
+			if j >= len(v.headers) {
+				t.Errorf("file %s, test %d, entry %d: unexpected header:\ngot %+v",
+					v.file, i, j, *hdr)
+				continue
+			}
+			if !reflect.DeepEqual(*hdr, *v.headers[j]) {
+				t.Errorf("file %s, test %d, entry %d: incorrect header:\ngot  %+v\nwant %+v",
+					v.file, i, j, *hdr, *v.headers[j])
+			}
+		}
+		if len(hdrs) != len(v.headers) {
+			t.Errorf("file %s, test %d: got %d headers, want %d headers",
+				v.file, i, len(hdrs), len(v.headers))
+		}
+
+		for j, sum := range chksums {
+			if j >= len(v.chksums) {
+				t.Errorf("file %s, test %d, entry %d: unexpected sum: got %s",
+					v.file, i, j, sum)
+				continue
+			}
+			if sum != v.chksums[j] {
+				t.Errorf("file %s, test %d, entry %d: incorrect checksum: got %s, want %s",
+					v.file, i, j, sum, v.chksums[j])
+			}
 		}
-		if hdr != nil || err != nil {
-			t.Errorf("test %d: Unexpected entry or error: hdr=%v err=%v", i, hdr, err)
+
+		if err != v.err {
+			t.Errorf("file %s, test %d: unexpected error: got %v, want %v",
+				v.file, i, err, v.err)
 		}
+		f.Close()
 	}
 }
 
@@ -356,89 +440,6 @@ func TestPartialRead(t *testing.T) {
 	}
 }
 
-func TestIncrementalRead(t *testing.T) {
-	test := gnuTarTest
-	f, err := os.Open(test.file)
-	if err != nil {
-		t.Fatalf("Unexpected error: %v", err)
-	}
-	defer f.Close()
-
-	tr := NewReader(f)
-
-	headers := test.headers
-	cksums := test.cksums
-	nread := 0
-
-	// loop over all files
-	for ; ; nread++ {
-		hdr, err := tr.Next()
-		if hdr == nil || err == io.EOF {
-			break
-		}
-
-		// check the header
-		if !reflect.DeepEqual(*hdr, *headers[nread]) {
-			t.Errorf("Incorrect header:\nhave %+v\nwant %+v",
-				*hdr, headers[nread])
-		}
-
-		// read file contents in little chunks EOF,
-		// checksumming all the way
-		h := md5.New()
-		rdbuf := make([]uint8, 8)
-		for {
-			nr, err := tr.Read(rdbuf)
-			if err == io.EOF {
-				break
-			}
-			if err != nil {
-				t.Errorf("Read: unexpected error %v\n", err)
-				break
-			}
-			h.Write(rdbuf[0:nr])
-		}
-		// verify checksum
-		have := fmt.Sprintf("%x", h.Sum(nil))
-		want := cksums[nread]
-		if want != have {
-			t.Errorf("Bad checksum on file %s:\nhave %+v\nwant %+v", hdr.Name, have, want)
-		}
-	}
-	if nread != len(headers) {
-		t.Errorf("Didn't process all files\nexpected: %d\nprocessed %d\n", len(headers), nread)
-	}
-}
-
-func TestNonSeekable(t *testing.T) {
-	test := gnuTarTest
-	f, err := os.Open(test.file)
-	if err != nil {
-		t.Fatalf("Unexpected error: %v", err)
-	}
-	defer f.Close()
-
-	type readerOnly struct {
-		io.Reader
-	}
-	tr := NewReader(readerOnly{f})
-	nread := 0
-
-	for ; ; nread++ {
-		_, err := tr.Next()
-		if err == io.EOF {
-			break
-		}
-		if err != nil {
-			t.Fatalf("Unexpected error: %v", err)
-		}
-	}
-
-	if nread != len(test.headers) {
-		t.Errorf("Didn't process all files\nexpected: %d\nprocessed %d\n", len(test.headers), nread)
-	}
-}
-
 func TestParsePAXHeader(t *testing.T) {
 	paxTests := [][3]string{
 		{"a", "a=name", "10 a=name\n"}, // Test case involving multiple acceptable lengths
@@ -514,220 +515,312 @@ func TestMergePAX(t *testing.T) {
 	}
 }
 
-func TestSparseEndToEnd(t *testing.T) {
-	test := sparseTarTest
-	f, err := os.Open(test.file)
-	if err != nil {
-		t.Fatalf("Unexpected error: %v", err)
-	}
-	defer f.Close()
-
-	tr := NewReader(f)
-
-	headers := test.headers
-	cksums := test.cksums
-	nread := 0
-
-	// loop over all files
-	for ; ; nread++ {
-		hdr, err := tr.Next()
-		if hdr == nil || err == io.EOF {
-			break
-		}
-
-		// check the header
-		if !reflect.DeepEqual(*hdr, *headers[nread]) {
-			t.Errorf("Incorrect header:\nhave %+v\nwant %+v",
-				*hdr, headers[nread])
-		}
-
-		// read and checksum the file data
-		h := md5.New()
-		_, err = io.Copy(h, tr)
-		if err != nil {
-			t.Fatalf("Unexpected error: %v", err)
-		}
-
-		// verify checksum
-		have := fmt.Sprintf("%x", h.Sum(nil))
-		want := cksums[nread]
-		if want != have {
-			t.Errorf("Bad checksum on file %s:\nhave %+v\nwant %+v", hdr.Name, have, want)
-		}
-	}
-	if nread != len(headers) {
-		t.Errorf("Didn't process all files\nexpected: %d\nprocessed %d\n", len(headers), nread)
-	}
-}
-
-type sparseFileReadTest struct {
-	sparseData []byte
-	sparseMap  []sparseEntry
-	realSize   int64
-	expected   []byte
-}
-
-var sparseFileReadTests = []sparseFileReadTest{
-	{
-		sparseData: []byte("abcde"),
+func TestSparseFileReader(t *testing.T) {
+	var vectors = []struct {
+		realSize   int64         // Real size of the output file
+		sparseMap  []sparseEntry // Input sparse map
+		sparseData string        // Input compact data
+		expected   string        // Expected output data
+		err        error         // Expected error outcome
+	}{{
+		realSize: 8,
 		sparseMap: []sparseEntry{
 			{offset: 0, numBytes: 2},
 			{offset: 5, numBytes: 3},
 		},
-		realSize: 8,
-		expected: []byte("ab\x00\x00\x00cde"),
-	},
-	{
-		sparseData: []byte("abcde"),
+		sparseData: "abcde",
+		expected:   "ab\x00\x00\x00cde",
+	}, {
+		realSize: 10,
 		sparseMap: []sparseEntry{
 			{offset: 0, numBytes: 2},
 			{offset: 5, numBytes: 3},
 		},
-		realSize: 10,
-		expected: []byte("ab\x00\x00\x00cde\x00\x00"),
-	},
-	{
-		sparseData: []byte("abcde"),
+		sparseData: "abcde",
+		expected:   "ab\x00\x00\x00cde\x00\x00",
+	}, {
+		realSize: 8,
 		sparseMap: []sparseEntry{
 			{offset: 1, numBytes: 3},
 			{offset: 6, numBytes: 2},
 		},
+		sparseData: "abcde",
+		expected:   "\x00abc\x00\x00de",
+	}, {
 		realSize: 8,
-		expected: []byte("\x00abc\x00\x00de"),
-	},
-	{
-		sparseData: []byte("abcde"),
 		sparseMap: []sparseEntry{
 			{offset: 1, numBytes: 3},
+			{offset: 6, numBytes: 0},
+			{offset: 6, numBytes: 0},
 			{offset: 6, numBytes: 2},
 		},
+		sparseData: "abcde",
+		expected:   "\x00abc\x00\x00de",
+	}, {
 		realSize: 10,
-		expected: []byte("\x00abc\x00\x00de\x00\x00"),
-	},
-	{
-		sparseData: []byte(""),
-		sparseMap:  nil,
+		sparseMap: []sparseEntry{
+			{offset: 1, numBytes: 3},
+			{offset: 6, numBytes: 2},
+		},
+		sparseData: "abcde",
+		expected:   "\x00abc\x00\x00de\x00\x00",
+	}, {
+		realSize: 10,
+		sparseMap: []sparseEntry{
+			{offset: 1, numBytes: 3},
+			{offset: 6, numBytes: 2},
+			{offset: 8, numBytes: 0},
+			{offset: 8, numBytes: 0},
+			{offset: 8, numBytes: 0},
+			{offset: 8, numBytes: 0},
+		},
+		sparseData: "abcde",
+		expected:   "\x00abc\x00\x00de\x00\x00",
+	}, {
 		realSize:   2,
-		expected:   []byte("\x00\x00"),
-	},
-}
+		sparseMap:  []sparseEntry{},
+		sparseData: "",
+		expected:   "\x00\x00",
+	}, {
+		realSize:  -2,
+		sparseMap: []sparseEntry{},
+		err:       ErrHeader,
+	}, {
+		realSize: -10,
+		sparseMap: []sparseEntry{
+			{offset: 1, numBytes: 3},
+			{offset: 6, numBytes: 2},
+		},
+		sparseData: "abcde",
+		err:        ErrHeader,
+	}, {
+		realSize: 10,
+		sparseMap: []sparseEntry{
+			{offset: 1, numBytes: 3},
+			{offset: 6, numBytes: 5},
+		},
+		sparseData: "abcde",
+		err:        ErrHeader,
+	}, {
+		realSize: 35,
+		sparseMap: []sparseEntry{
+			{offset: 1, numBytes: 3},
+			{offset: 6, numBytes: 5},
+		},
+		sparseData: "abcde",
+		err:        io.ErrUnexpectedEOF,
+	}, {
+		realSize: 35,
+		sparseMap: []sparseEntry{
+			{offset: 1, numBytes: 3},
+			{offset: 6, numBytes: -5},
+		},
+		sparseData: "abcde",
+		err:        ErrHeader,
+	}, {
+		realSize: 35,
+		sparseMap: []sparseEntry{
+			{offset: math.MaxInt64, numBytes: 3},
+			{offset: 6, numBytes: -5},
+		},
+		sparseData: "abcde",
+		err:        ErrHeader,
+	}, {
+		realSize: 10,
+		sparseMap: []sparseEntry{
+			{offset: 1, numBytes: 3},
+			{offset: 2, numBytes: 2},
+		},
+		sparseData: "abcde",
+		err:        ErrHeader,
+	}}
 
-func TestSparseFileReader(t *testing.T) {
-	for i, test := range sparseFileReadTests {
-		r := bytes.NewReader(test.sparseData)
-		nb := int64(r.Len())
-		sfr := &sparseFileReader{
-			rfr: &regFileReader{r: r, nb: nb},
-			sp:  test.sparseMap,
-			pos: 0,
-			tot: test.realSize,
-		}
-		if sfr.numBytes() != nb {
-			t.Errorf("test %d: Before reading, sfr.numBytes() = %d, want %d", i, sfr.numBytes(), nb)
-		}
-		buf, err := ioutil.ReadAll(sfr)
+	for i, v := range vectors {
+		r := bytes.NewReader([]byte(v.sparseData))
+		rfr := &regFileReader{r: r, nb: int64(len(v.sparseData))}
+
+		var sfr *sparseFileReader
+		var err error
+		var buf []byte
+
+		sfr, err = newSparseFileReader(rfr, v.sparseMap, v.realSize)
+		if err != nil {
+			goto fail
+		}
+		if sfr.numBytes() != int64(len(v.sparseData)) {
+			t.Errorf("test %d, numBytes() before reading: got %d, want %d", i, sfr.numBytes(), len(v.sparseData))
+		}
+		buf, err = ioutil.ReadAll(sfr)
 		if err != nil {
-			t.Errorf("test %d: Unexpected error: %v", i, err)
+			goto fail
 		}
-		if e := test.expected; !bytes.Equal(buf, e) {
-			t.Errorf("test %d: Contents = %v, want %v", i, buf, e)
+		if string(buf) != v.expected {
+			t.Errorf("test %d, ReadAll(): got %q, want %q", i, string(buf), v.expected)
 		}
 		if sfr.numBytes() != 0 {
-			t.Errorf("test %d: After draining the reader, numBytes() was nonzero", i)
+			t.Errorf("test %d, numBytes() after reading: got %d, want %d", i, sfr.numBytes(), 0)
+		}
+
+	fail:
+		if err != v.err {
+			t.Errorf("test %d, unexpected error: got %v, want %v", i, err, v.err)
 		}
 	}
 }
 
-func TestSparseIncrementalRead(t *testing.T) {
-	sparseMap := []sparseEntry{{10, 2}}
-	sparseData := []byte("Go")
-	expected := "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Go\x00\x00\x00\x00\x00\x00\x00\x00"
+func TestReadGNUSparseMap0x1(t *testing.T) {
+	const (
+		maxUint = ^uint(0)
+		maxInt  = int(maxUint >> 1)
+	)
+	var (
+		big1 = fmt.Sprintf("%d", int64(maxInt))
+		big2 = fmt.Sprintf("%d", (int64(maxInt)/2)+1)
+		big3 = fmt.Sprintf("%d", (int64(maxInt) / 3))
+	)
 
-	r := bytes.NewReader(sparseData)
-	nb := int64(r.Len())
-	sfr := &sparseFileReader{
-		rfr: &regFileReader{r: r, nb: nb},
-		sp:  sparseMap,
-		pos: 0,
-		tot: int64(len(expected)),
-	}
+	var vectors = []struct {
+		extHdrs   map[string]string // Input data
+		sparseMap []sparseEntry     // Expected sparse entries to be outputted
+		err       error             // Expected errors that may be raised
+	}{{
+		extHdrs: map[string]string{paxGNUSparseNumBlocks: "-4"},
+		err:     ErrHeader,
+	}, {
+		extHdrs: map[string]string{paxGNUSparseNumBlocks: "fee "},
+		err:     ErrHeader,
+	}, {
+		extHdrs: map[string]string{
+			paxGNUSparseNumBlocks: big1,
+			paxGNUSparseMap:       "0,5,10,5,20,5,30,5",
+		},
+		err: ErrHeader,
+	}, {
+		extHdrs: map[string]string{
+			paxGNUSparseNumBlocks: big2,
+			paxGNUSparseMap:       "0,5,10,5,20,5,30,5",
+		},
+		err: ErrHeader,
+	}, {
+		extHdrs: map[string]string{
+			paxGNUSparseNumBlocks: big3,
+			paxGNUSparseMap:       "0,5,10,5,20,5,30,5",
+		},
+		err: ErrHeader,
+	}, {
+		extHdrs: map[string]string{
+			paxGNUSparseNumBlocks: "4",
+			paxGNUSparseMap:       "0.5,5,10,5,20,5,30,5",
+		},
+		err: ErrHeader,
+	}, {
+		extHdrs: map[string]string{
+			paxGNUSparseNumBlocks: "4",
+			paxGNUSparseMap:       "0,5.5,10,5,20,5,30,5",
+		},
+		err: ErrHeader,
+	}, {
+		extHdrs: map[string]string{
+			paxGNUSparseNumBlocks: "4",
+			paxGNUSparseMap:       "0,fewafewa.5,fewafw,5,20,5,30,5",
+		},
+		err: ErrHeader,
+	}, {
+		extHdrs: map[string]string{
+			paxGNUSparseNumBlocks: "4",
+			paxGNUSparseMap:       "0,5,10,5,20,5,30,5",
+		},
+		sparseMap: []sparseEntry{{0, 5}, {10, 5}, {20, 5}, {30, 5}},
+	}}
 
-	// We'll read the data 6 bytes at a time, with a hole of size 10 at
-	// the beginning and one of size 8 at the end.
-	var outputBuf bytes.Buffer
-	buf := make([]byte, 6)
-	for {
-		n, err := sfr.Read(buf)
-		if err == io.EOF {
-			break
+	for i, v := range vectors {
+		sp, err := readGNUSparseMap0x1(v.extHdrs)
+		if !reflect.DeepEqual(sp, v.sparseMap) && !(len(sp) == 0 && len(v.sparseMap) == 0) {
+			t.Errorf("test %d, readGNUSparseMap0x1(...): got %v, want %v", i, sp, v.sparseMap)
 		}
-		if err != nil {
-			t.Errorf("Read: unexpected error %v\n", err)
-		}
-		if n > 0 {
-			_, err := outputBuf.Write(buf[:n])
-			if err != nil {
-				t.Errorf("Write: unexpected error %v\n", err)
-			}
+		if err != v.err {
+			t.Errorf("test %d, unexpected error: got %v, want %v", i, err, v.err)
 		}
 	}
-	got := outputBuf.String()
-	if got != expected {
-		t.Errorf("Contents = %v, want %v", got, expected)
-	}
 }
 
-func TestReadGNUSparseMap0x1(t *testing.T) {
-	headers := map[string]string{
-		paxGNUSparseNumBlocks: "4",
-		paxGNUSparseMap:       "0,5,10,5,20,5,30,5",
-	}
-	expected := []sparseEntry{
-		{offset: 0, numBytes: 5},
-		{offset: 10, numBytes: 5},
-		{offset: 20, numBytes: 5},
-		{offset: 30, numBytes: 5},
+func TestReadGNUSparseMap1x0(t *testing.T) {
+	var sp = []sparseEntry{{1, 2}, {3, 4}}
+	for i := 0; i < 98; i++ {
+		sp = append(sp, sparseEntry{54321, 12345})
 	}
 
-	sp, err := readGNUSparseMap0x1(headers)
-	if err != nil {
-		t.Errorf("Unexpected error: %v", err)
-	}
-	if !reflect.DeepEqual(sp, expected) {
-		t.Errorf("Incorrect sparse map: got %v, wanted %v", sp, expected)
-	}
-}
+	var vectors = []struct {
+		input     string        // Input data
+		sparseMap []sparseEntry // Expected sparse entries to be outputted
+		cnt       int           // Expected number of bytes read
+		err       error         // Expected errors that may be raised
+	}{{
+		input: "",
+		cnt:   0,
+		err:   io.ErrUnexpectedEOF,
+	}, {
+		input: "ab",
+		cnt:   2,
+		err:   io.ErrUnexpectedEOF,
+	}, {
+		input: strings.Repeat("\x00", 512),
+		cnt:   512,
+		err:   io.ErrUnexpectedEOF,
+	}, {
+		input: strings.Repeat("\x00", 511) + "\n",
+		cnt:   512,
+		err:   ErrHeader,
+	}, {
+		input: strings.Repeat("\n", 512),
+		cnt:   512,
+		err:   ErrHeader,
+	}, {
+		input:     "0\n" + strings.Repeat("\x00", 510) + strings.Repeat("a", 512),
+		sparseMap: []sparseEntry{},
+		cnt:       512,
+	}, {
+		input:     strings.Repeat("0", 512) + "0\n" + strings.Repeat("\x00", 510),
+		sparseMap: []sparseEntry{},
+		cnt:       1024,
+	}, {
+		input:     strings.Repeat("0", 1024) + "1\n2\n3\n" + strings.Repeat("\x00", 506),
+		sparseMap: []sparseEntry{{2, 3}},
+		cnt:       1536,
+	}, {
+		input: strings.Repeat("0", 1024) + "1\n2\n\n" + strings.Repeat("\x00", 509),
+		cnt:   1536,
+		err:   ErrHeader,
+	}, {
+		input: strings.Repeat("0", 1024) + "1\n2\n" + strings.Repeat("\x00", 508),
+		cnt:   1536,
+		err:   io.ErrUnexpectedEOF,
+	}, {
+		input: "-1\n2\n\n" + strings.Repeat("\x00", 506),
+		cnt:   512,
+		err:   ErrHeader,
+	}, {
+		input: "1\nk\n2\n" + strings.Repeat("\x00", 506),
+		cnt:   512,
+		err:   ErrHeader,
+	}, {
+		input:     "100\n1\n2\n3\n4\n" + strings.Repeat("54321\n0000000000000012345\n", 98) + strings.Repeat("\x00", 512),
+		cnt:       2560,
+		sparseMap: sp,
+	}}
 
-func TestReadGNUSparseMap1x0(t *testing.T) {
-	// This test uses lots of holes so the sparse header takes up more than two blocks
-	numEntries := 100
-	expected := make([]sparseEntry, 0, numEntries)
-	sparseMap := new(bytes.Buffer)
-
-	fmt.Fprintf(sparseMap, "%d\n", numEntries)
-	for i := 0; i < numEntries; i++ {
-		offset := int64(2048 * i)
-		numBytes := int64(1024)
-		expected = append(expected, sparseEntry{offset: offset, numBytes: numBytes})
-		fmt.Fprintf(sparseMap, "%d\n%d\n", offset, numBytes)
-	}
-
-	// Make the header the smallest multiple of blockSize that fits the sparseMap
-	headerBlocks := (sparseMap.Len() + blockSize - 1) / blockSize
-	bufLen := blockSize * headerBlocks
-	buf := make([]byte, bufLen)
-	copy(buf, sparseMap.Bytes())
-
-	// Get an reader to read the sparse map
-	r := bytes.NewReader(buf)
-
-	// Read the sparse map
-	sp, err := readGNUSparseMap1x0(r)
-	if err != nil {
-		t.Errorf("Unexpected error: %v", err)
-	}
-	if !reflect.DeepEqual(sp, expected) {
-		t.Errorf("Incorrect sparse map: got %v, wanted %v", sp, expected)
+	for i, v := range vectors {
+		r := strings.NewReader(v.input)
+		sp, err := readGNUSparseMap1x0(r)
+		if !reflect.DeepEqual(sp, v.sparseMap) && !(len(sp) == 0 && len(v.sparseMap) == 0) {
+			t.Errorf("test %d, readGNUSparseMap1x0(...): got %v, want %v", i, sp, v.sparseMap)
+		}
+		if numBytes := len(v.input) - r.Len(); numBytes != v.cnt {
+			t.Errorf("test %d, bytes read: got %v, want %v", i, numBytes, v.cnt)
+		}
+		if err != v.err {
+			t.Errorf("test %d, unexpected error: got %v, want %v", i, err, v.err)
+		}
 	}
 }
 
@@ -747,52 +840,286 @@ func TestUninitializedRead(t *testing.T) {
 
 }
 
-// Negative header size should not cause panic.
-// Issues 10959 and 10960.
-func TestNegativeHdrSize(t *testing.T) {
-	f, err := os.Open("testdata/neg-size.tar")
-	if err != nil {
-		t.Fatal(err)
+type reader struct{ io.Reader }
+type readSeeker struct{ io.ReadSeeker }
+type readBadSeeker struct{ io.ReadSeeker }
+
+func (rbs *readBadSeeker) Seek(int64, int) (int64, error) { return 0, fmt.Errorf("illegal seek") }
+
+// TestReadTruncation test the ending condition on various truncated files and
+// that truncated files are still detected even if the underlying io.Reader
+// satisfies io.Seeker.
+func TestReadTruncation(t *testing.T) {
+	var ss []string
+	for _, p := range []string{
+		"testdata/gnu.tar",
+		"testdata/ustar-file-reg.tar",
+		"testdata/pax-path-hdr.tar",
+		"testdata/sparse-formats.tar",
+	} {
+		buf, err := ioutil.ReadFile(p)
+		if err != nil {
+			t.Fatalf("unexpected error: %v", err)
+		}
+		ss = append(ss, string(buf))
 	}
-	defer f.Close()
-	r := NewReader(f)
-	_, err = r.Next()
-	if err != ErrHeader {
-		t.Error("want ErrHeader, got", err)
+
+	data1, data2, pax, sparse := ss[0], ss[1], ss[2], ss[3]
+	data2 += strings.Repeat("\x00", 10*512)
+	trash := strings.Repeat("garbage ", 64) // Exactly 512 bytes
+
+	var vectors = []struct {
+		input string // Input stream
+		cnt   int    // Expected number of headers read
+		err   error  // Expected error outcome
+	}{
+		{"", 0, io.EOF}, // Empty file is a "valid" tar file
+		{data1[:511], 0, io.ErrUnexpectedEOF},
+		{data1[:512], 1, io.ErrUnexpectedEOF},
+		{data1[:1024], 1, io.EOF},
+		{data1[:1536], 2, io.ErrUnexpectedEOF},
+		{data1[:2048], 2, io.EOF},
+		{data1, 2, io.EOF},
+		{data1[:2048] + data2[:1536], 3, io.EOF},
+		{data2[:511], 0, io.ErrUnexpectedEOF},
+		{data2[:512], 1, io.ErrUnexpectedEOF},
+		{data2[:1195], 1, io.ErrUnexpectedEOF},
+		{data2[:1196], 1, io.EOF}, // Exact end of data and start of padding
+		{data2[:1200], 1, io.EOF},
+		{data2[:1535], 1, io.EOF},
+		{data2[:1536], 1, io.EOF}, // Exact end of padding
+		{data2[:1536] + trash[:1], 1, io.ErrUnexpectedEOF},
+		{data2[:1536] + trash[:511], 1, io.ErrUnexpectedEOF},
+		{data2[:1536] + trash, 1, ErrHeader},
+		{data2[:2048], 1, io.EOF}, // Exactly 1 empty block
+		{data2[:2048] + trash[:1], 1, io.ErrUnexpectedEOF},
+		{data2[:2048] + trash[:511], 1, io.ErrUnexpectedEOF},
+		{data2[:2048] + trash, 1, ErrHeader},
+		{data2[:2560], 1, io.EOF}, // Exactly 2 empty blocks (normal end-of-stream)
+		{data2[:2560] + trash[:1], 1, io.EOF},
+		{data2[:2560] + trash[:511], 1, io.EOF},
+		{data2[:2560] + trash, 1, io.EOF},
+		{data2[:3072], 1, io.EOF},
+		{pax, 0, io.EOF}, // PAX header without data is a "valid" tar file
+		{pax + trash[:1], 0, io.ErrUnexpectedEOF},
+		{pax + trash[:511], 0, io.ErrUnexpectedEOF},
+		{sparse[:511], 0, io.ErrUnexpectedEOF},
+		// TODO(dsnet): This should pass, but currently fails.
+		// {sparse[:512], 0, io.ErrUnexpectedEOF},
+		{sparse[:3584], 1, io.EOF},
+		{sparse[:9200], 1, io.EOF}, // Terminate in padding of sparse header
+		{sparse[:9216], 1, io.EOF},
+		{sparse[:9728], 2, io.ErrUnexpectedEOF},
+		{sparse[:10240], 2, io.EOF},
+		{sparse[:11264], 2, io.ErrUnexpectedEOF},
+		{sparse, 5, io.EOF},
+		{sparse + trash, 5, io.EOF},
+	}
+
+	for i, v := range vectors {
+		for j := 0; j < 6; j++ {
+			var tr *Reader
+			var s1, s2 string
+
+			switch j {
+			case 0:
+				tr = NewReader(&reader{strings.NewReader(v.input)})
+				s1, s2 = "io.Reader", "auto"
+			case 1:
+				tr = NewReader(&reader{strings.NewReader(v.input)})
+				s1, s2 = "io.Reader", "manual"
+			case 2:
+				tr = NewReader(&readSeeker{strings.NewReader(v.input)})
+				s1, s2 = "io.ReadSeeker", "auto"
+			case 3:
+				tr = NewReader(&readSeeker{strings.NewReader(v.input)})
+				s1, s2 = "io.ReadSeeker", "manual"
+			case 4:
+				tr = NewReader(&readBadSeeker{strings.NewReader(v.input)})
+				s1, s2 = "ReadBadSeeker", "auto"
+			case 5:
+				tr = NewReader(&readBadSeeker{strings.NewReader(v.input)})
+				s1, s2 = "ReadBadSeeker", "manual"
+			}
+
+			var cnt int
+			var err error
+			for {
+				if _, err = tr.Next(); err != nil {
+					break
+				}
+				cnt++
+				if s2 == "manual" {
+					if _, err = io.Copy(ioutil.Discard, tr); err != nil {
+						break
+					}
+				}
+			}
+			if err != v.err {
+				t.Errorf("test %d, NewReader(%s(...)) with %s discard: got %v, want %v",
+					i, s1, s2, err, v.err)
+			}
+			if cnt != v.cnt {
+				t.Errorf("test %d, NewReader(%s(...)) with %s discard: got %d headers, want %d headers",
+					i, s1, s2, cnt, v.cnt)
+			}
+		}
 	}
-	io.Copy(ioutil.Discard, r)
 }
 
-// This used to hang in (*sparseFileReader).readHole due to missing
-// verification of sparse offsets against file size.
-func TestIssue10968(t *testing.T) {
-	f, err := os.Open("testdata/issue10968.tar")
+// TestReadHeaderOnly tests that Reader does not attempt to read special
+// header-only files.
+func TestReadHeaderOnly(t *testing.T) {
+	f, err := os.Open("testdata/hdr-only.tar")
 	if err != nil {
-		t.Fatal(err)
+		t.Fatalf("unexpected error: %v", err)
 	}
 	defer f.Close()
-	r := NewReader(f)
-	_, err = r.Next()
-	if err != nil {
-		t.Fatal(err)
+
+	var hdrs []*Header
+	tr := NewReader(f)
+	for {
+		hdr, err := tr.Next()
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			t.Errorf("Next(): got %v, want %v", err, nil)
+			continue
+		}
+		hdrs = append(hdrs, hdr)
+
+		// If a special flag, we should read nothing.
+		cnt, _ := io.ReadFull(tr, []byte{0})
+		if cnt > 0 && hdr.Typeflag != TypeReg {
+			t.Errorf("ReadFull(...): got %d bytes, want 0 bytes", cnt)
+		}
+	}
+
+	// File is crafted with 16 entries. The later 8 are identical to the first
+	// 8 except that the size is set.
+	if len(hdrs) != 16 {
+		t.Fatalf("len(hdrs): got %d, want %d", len(hdrs), 16)
 	}
-	_, err = io.Copy(ioutil.Discard, r)
-	if err != io.ErrUnexpectedEOF {
-		t.Fatalf("expected %q, got %q", io.ErrUnexpectedEOF, err)
+	for i := 0; i < 8; i++ {
+		var hdr1, hdr2 = hdrs[i+0], hdrs[i+8]
+		hdr1.Size, hdr2.Size = 0, 0
+		if !reflect.DeepEqual(*hdr1, *hdr2) {
+			t.Errorf("incorrect header:\ngot  %+v\nwant %+v", *hdr1, *hdr2)
+		}
 	}
 }
 
-// Do not panic if there are errors in header blocks after the pax header.
-// Issue 11169
-func TestIssue11169(t *testing.T) {
-	f, err := os.Open("testdata/issue11169.tar")
-	if err != nil {
-		t.Fatal(err)
+func TestParsePAXRecord(t *testing.T) {
+	var medName = strings.Repeat("CD", 50)
+	var longName = strings.Repeat("AB", 100)
+
+	var vectors = []struct {
+		input     string
+		residual  string
+		outputKey string
+		outputVal string
+		ok        bool
+	}{
+		{"6 k=v\n\n", "\n", "k", "v", true},
+		{"19 path=/etc/hosts\n", "", "path", "/etc/hosts", true},
+		{"210 path=" + longName + "\nabc", "abc", "path", longName, true},
+		{"110 path=" + medName + "\n", "", "path", medName, true},
+		{"9 foo=ba\n", "", "foo", "ba", true},
+		{"11 foo=bar\n\x00", "\x00", "foo", "bar", true},
+		{"18 foo=b=\nar=\n==\x00\n", "", "foo", "b=\nar=\n==\x00", true},
+		{"27 foo=hello9 foo=ba\nworld\n", "", "foo", "hello9 foo=ba\nworld", true},
+		{"27 ☺☻☹=日a本b語ç\nmeow mix", "meow mix", "☺☻☹", "日a本b語ç", true},
+		{"17 \x00hello=\x00world\n", "", "\x00hello", "\x00world", true},
+		{"1 k=1\n", "1 k=1\n", "", "", false},
+		{"6 k~1\n", "6 k~1\n", "", "", false},
+		{"6_k=1\n", "6_k=1\n", "", "", false},
+		{"6 k=1 ", "6 k=1 ", "", "", false},
+		{"632 k=1\n", "632 k=1\n", "", "", false},
+		{"16 longkeyname=hahaha\n", "16 longkeyname=hahaha\n", "", "", false},
+		{"3 somelongkey=\n", "3 somelongkey=\n", "", "", false},
+		{"50 tooshort=\n", "50 tooshort=\n", "", "", false},
 	}
-	defer f.Close()
-	r := NewReader(f)
-	_, err = r.Next()
-	if err == nil {
-		t.Fatal("Unexpected success")
+
+	for _, v := range vectors {
+		key, val, res, err := parsePAXRecord(v.input)
+		ok := (err == nil)
+		if v.ok != ok {
+			if v.ok {
+				t.Errorf("parsePAXRecord(%q): got parsing failure, want success", v.input)
+			} else {
+				t.Errorf("parsePAXRecord(%q): got parsing success, want failure", v.input)
+			}
+		}
+		if ok && (key != v.outputKey || val != v.outputVal) {
+			t.Errorf("parsePAXRecord(%q): got (%q: %q), want (%q: %q)",
+				v.input, key, val, v.outputKey, v.outputVal)
+		}
+		if res != v.residual {
+			t.Errorf("parsePAXRecord(%q): got residual %q, want residual %q",
+				v.input, res, v.residual)
+		}
+	}
+}
+
+func TestParseNumeric(t *testing.T) {
+	var vectors = []struct {
+		input  string
+		output int64
+		ok     bool
+	}{
+		// Test base-256 (binary) encoded values.
+		{"", 0, true},
+		{"\x80", 0, true},
+		{"\x80\x00", 0, true},
+		{"\x80\x00\x00", 0, true},
+		{"\xbf", (1 << 6) - 1, true},
+		{"\xbf\xff", (1 << 14) - 1, true},
+		{"\xbf\xff\xff", (1 << 22) - 1, true},
+		{"\xff", -1, true},
+		{"\xff\xff", -1, true},
+		{"\xff\xff\xff", -1, true},
+		{"\xc0", -1 * (1 << 6), true},
+		{"\xc0\x00", -1 * (1 << 14), true},
+		{"\xc0\x00\x00", -1 * (1 << 22), true},
+		{"\x87\x76\xa2\x22\xeb\x8a\x72\x61", 537795476381659745, true},
+		{"\x80\x00\x00\x00\x07\x76\xa2\x22\xeb\x8a\x72\x61", 537795476381659745, true},
+		{"\xf7\x76\xa2\x22\xeb\x8a\x72\x61", -615126028225187231, true},
+		{"\xff\xff\xff\xff\xf7\x76\xa2\x22\xeb\x8a\x72\x61", -615126028225187231, true},
+		{"\x80\x7f\xff\xff\xff\xff\xff\xff\xff", math.MaxInt64, true},
+		{"\x80\x80\x00\x00\x00\x00\x00\x00\x00", 0, false},
+		{"\xff\x80\x00\x00\x00\x00\x00\x00\x00", math.MinInt64, true},
+		{"\xff\x7f\xff\xff\xff\xff\xff\xff\xff", 0, false},
+		{"\xf5\xec\xd1\xc7\x7e\x5f\x26\x48\x81\x9f\x8f\x9b", 0, false},
+
+		// Test base-8 (octal) encoded values.
+		{"0000000\x00", 0, true},
+		{" \x0000000\x00", 0, true},
+		{" \x0000003\x00", 3, true},
+		{"00000000227\x00", 0227, true},
+		{"032033\x00 ", 032033, true},
+		{"320330\x00 ", 0320330, true},
+		{"0000660\x00 ", 0660, true},
+		{"\x00 0000660\x00 ", 0660, true},
+		{"0123456789abcdef", 0, false},
+		{"0123456789\x00abcdef", 0, false},
+		{"01234567\x0089abcdef", 342391, true},
+		{"0123\x7e\x5f\x264123", 0, false},
+	}
+
+	for _, v := range vectors {
+		var p parser
+		num := p.parseNumeric([]byte(v.input))
+		ok := (p.err == nil)
+		if v.ok != ok {
+			if v.ok {
+				t.Errorf("parseNumeric(%q): got parsing failure, want success", v.input)
+			} else {
+				t.Errorf("parseNumeric(%q): got parsing success, want failure", v.input)
+			}
+		}
+		if ok && num != v.output {
+			t.Errorf("parseNumeric(%q): got %d, want %d", v.input, num, v.output)
+		}
 	}
 }
diff --git a/src/archive/tar/testdata/gnu-multi-hdrs.tar b/src/archive/tar/testdata/gnu-multi-hdrs.tar
new file mode 100644
index 0000000..8bcad55
Binary files /dev/null and b/src/archive/tar/testdata/gnu-multi-hdrs.tar differ
diff --git a/src/archive/tar/testdata/hdr-only.tar b/src/archive/tar/testdata/hdr-only.tar
new file mode 100644
index 0000000..f250340
Binary files /dev/null and b/src/archive/tar/testdata/hdr-only.tar differ
diff --git a/src/archive/tar/testdata/issue12435.tar b/src/archive/tar/testdata/issue12435.tar
new file mode 100644
index 0000000..3542dd8
Binary files /dev/null and b/src/archive/tar/testdata/issue12435.tar differ
diff --git a/src/archive/tar/testdata/neg-size.tar b/src/archive/tar/testdata/neg-size.tar
index 5deea3d..21edf38 100644
Binary files a/src/archive/tar/testdata/neg-size.tar and b/src/archive/tar/testdata/neg-size.tar differ
diff --git a/src/archive/tar/testdata/pax-multi-hdrs.tar b/src/archive/tar/testdata/pax-multi-hdrs.tar
new file mode 100644
index 0000000..14bc759
Binary files /dev/null and b/src/archive/tar/testdata/pax-multi-hdrs.tar differ
diff --git a/src/archive/tar/testdata/pax-path-hdr.tar b/src/archive/tar/testdata/pax-path-hdr.tar
new file mode 100644
index 0000000..ab8fc32
Binary files /dev/null and b/src/archive/tar/testdata/pax-path-hdr.tar differ
diff --git a/src/archive/tar/testdata/ustar-file-reg.tar b/src/archive/tar/testdata/ustar-file-reg.tar
new file mode 100644
index 0000000..c84fa27
Binary files /dev/null and b/src/archive/tar/testdata/ustar-file-reg.tar differ
diff --git a/src/archive/tar/writer.go b/src/archive/tar/writer.go
index 9dbc01a..0426381 100644
--- a/src/archive/tar/writer.go
+++ b/src/archive/tar/writer.go
@@ -12,8 +12,8 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"os"
 	"path"
+	"sort"
 	"strconv"
 	"strings"
 	"time"
@@ -23,7 +23,6 @@ var (
 	ErrWriteTooLong    = errors.New("archive/tar: write too long")
 	ErrFieldTooLong    = errors.New("archive/tar: header field too long")
 	ErrWriteAfterClose = errors.New("archive/tar: write after close")
-	errNameTooLong     = errors.New("archive/tar: name too long")
 	errInvalidHeader   = errors.New("archive/tar: header field too long or contains invalid values")
 )
 
@@ -43,6 +42,10 @@ type Writer struct {
 	paxHdrBuff [blockSize]byte // buffer to use in writeHeader when writing a pax header
 }
 
+type formatter struct {
+	err error // Last error seen
+}
+
 // NewWriter creates a new Writer writing to w.
 func NewWriter(w io.Writer) *Writer { return &Writer{w: w} }
 
@@ -69,17 +72,9 @@ func (tw *Writer) Flush() error {
 }
 
 // Write s into b, terminating it with a NUL if there is room.
-// If the value is too long for the field and allowPax is true add a paxheader record instead
-func (tw *Writer) cString(b []byte, s string, allowPax bool, paxKeyword string, paxHeaders map[string]string) {
-	needsPaxHeader := allowPax && len(s) > len(b) || !isASCII(s)
-	if needsPaxHeader {
-		paxHeaders[paxKeyword] = s
-		return
-	}
+func (f *formatter) formatString(b []byte, s string) {
 	if len(s) > len(b) {
-		if tw.err == nil {
-			tw.err = ErrFieldTooLong
-		}
+		f.err = ErrFieldTooLong
 		return
 	}
 	ascii := toASCII(s)
@@ -90,40 +85,40 @@ func (tw *Writer) cString(b []byte, s string, allowPax bool, paxKeyword string,
 }
 
 // Encode x as an octal ASCII string and write it into b with leading zeros.
-func (tw *Writer) octal(b []byte, x int64) {
+func (f *formatter) formatOctal(b []byte, x int64) {
 	s := strconv.FormatInt(x, 8)
 	// leading zeros, but leave room for a NUL.
 	for len(s)+1 < len(b) {
 		s = "0" + s
 	}
-	tw.cString(b, s, false, paxNone, nil)
+	f.formatString(b, s)
 }
 
-// Write x into b, either as octal or as binary (GNUtar/star extension).
-// If the value is too long for the field and writingPax is enabled both for the field and the add a paxheader record instead
-func (tw *Writer) numeric(b []byte, x int64, allowPax bool, paxKeyword string, paxHeaders map[string]string) {
-	// Try octal first.
-	s := strconv.FormatInt(x, 8)
-	if len(s) < len(b) {
-		tw.octal(b, x)
-		return
-	}
+// fitsInBase256 reports whether x can be encoded into n bytes using base-256
+// encoding. Unlike octal encoding, base-256 encoding does not require that the
+// string ends with a NUL character. Thus, all n bytes are available for output.
+//
+// If operating in binary mode, this assumes strict GNU binary mode; which means
+// that the first byte can only be either 0x80 or 0xff. Thus, the first byte is
+// equivalent to the sign bit in two's complement form.
+func fitsInBase256(n int, x int64) bool {
+	var binBits = uint(n-1) * 8
+	return n >= 9 || (x >= -1<<binBits && x < 1<<binBits)
+}
 
-	// If it is too long for octal, and pax is preferred, use a pax header
-	if allowPax && tw.preferPax {
-		tw.octal(b, 0)
-		s := strconv.FormatInt(x, 10)
-		paxHeaders[paxKeyword] = s
+// Write x into b, as binary (GNUtar/star extension).
+func (f *formatter) formatNumeric(b []byte, x int64) {
+	if fitsInBase256(len(b), x) {
+		for i := len(b) - 1; i >= 0; i-- {
+			b[i] = byte(x)
+			x >>= 8
+		}
+		b[0] |= 0x80 // Highest bit indicates binary format
 		return
 	}
 
-	// Too big: use binary (big-endian).
-	tw.usedBinary = true
-	for i := len(b) - 1; x > 0 && i >= 0; i-- {
-		b[i] = byte(x)
-		x >>= 8
-	}
-	b[0] |= 0x80 // highest bit indicates binary format
+	f.formatOctal(b, 0) // Last resort, just write zero
+	f.err = ErrFieldTooLong
 }
 
 var (
@@ -162,6 +157,7 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
 	// subsecond time resolution, but for now let's just capture
 	// too long fields or non ascii characters
 
+	var f formatter
 	var header []byte
 
 	// We need to select which scratch buffer to use carefully,
@@ -176,10 +172,40 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
 	copy(header, zeroBlock)
 	s := slicer(header)
 
+	// Wrappers around formatter that automatically sets paxHeaders if the
+	// argument extends beyond the capacity of the input byte slice.
+	var formatString = func(b []byte, s string, paxKeyword string) {
+		needsPaxHeader := paxKeyword != paxNone && len(s) > len(b) || !isASCII(s)
+		if needsPaxHeader {
+			paxHeaders[paxKeyword] = s
+			return
+		}
+		f.formatString(b, s)
+	}
+	var formatNumeric = func(b []byte, x int64, paxKeyword string) {
+		// Try octal first.
+		s := strconv.FormatInt(x, 8)
+		if len(s) < len(b) {
+			f.formatOctal(b, x)
+			return
+		}
+
+		// If it is too long for octal, and PAX is preferred, use a PAX header.
+		if paxKeyword != paxNone && tw.preferPax {
+			f.formatOctal(b, 0)
+			s := strconv.FormatInt(x, 10)
+			paxHeaders[paxKeyword] = s
+			return
+		}
+
+		tw.usedBinary = true
+		f.formatNumeric(b, x)
+	}
+
 	// keep a reference to the filename to allow to overwrite it later if we detect that we can use ustar longnames instead of pax
 	pathHeaderBytes := s.next(fileNameSize)
 
-	tw.cString(pathHeaderBytes, hdr.Name, true, paxPath, paxHeaders)
+	formatString(pathHeaderBytes, hdr.Name, paxPath)
 
 	// Handle out of range ModTime carefully.
 	var modTime int64
@@ -187,25 +213,25 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
 		modTime = hdr.ModTime.Unix()
 	}
 
-	tw.octal(s.next(8), hdr.Mode)                                   // 100:108
-	tw.numeric(s.next(8), int64(hdr.Uid), true, paxUid, paxHeaders) // 108:116
-	tw.numeric(s.next(8), int64(hdr.Gid), true, paxGid, paxHeaders) // 116:124
-	tw.numeric(s.next(12), hdr.Size, true, paxSize, paxHeaders)     // 124:136
-	tw.numeric(s.next(12), modTime, false, paxNone, nil)            // 136:148 --- consider using pax for finer granularity
-	s.next(8)                                                       // chksum (148:156)
-	s.next(1)[0] = hdr.Typeflag                                     // 156:157
+	f.formatOctal(s.next(8), hdr.Mode)               // 100:108
+	formatNumeric(s.next(8), int64(hdr.Uid), paxUid) // 108:116
+	formatNumeric(s.next(8), int64(hdr.Gid), paxGid) // 116:124
+	formatNumeric(s.next(12), hdr.Size, paxSize)     // 124:136
+	formatNumeric(s.next(12), modTime, paxNone)      // 136:148 --- consider using pax for finer granularity
+	s.next(8)                                        // chksum (148:156)
+	s.next(1)[0] = hdr.Typeflag                      // 156:157
 
-	tw.cString(s.next(100), hdr.Linkname, true, paxLinkpath, paxHeaders)
+	formatString(s.next(100), hdr.Linkname, paxLinkpath)
 
-	copy(s.next(8), []byte("ustar\x0000"))                        // 257:265
-	tw.cString(s.next(32), hdr.Uname, true, paxUname, paxHeaders) // 265:297
-	tw.cString(s.next(32), hdr.Gname, true, paxGname, paxHeaders) // 297:329
-	tw.numeric(s.next(8), hdr.Devmajor, false, paxNone, nil)      // 329:337
-	tw.numeric(s.next(8), hdr.Devminor, false, paxNone, nil)      // 337:345
+	copy(s.next(8), []byte("ustar\x0000"))          // 257:265
+	formatString(s.next(32), hdr.Uname, paxUname)   // 265:297
+	formatString(s.next(32), hdr.Gname, paxGname)   // 297:329
+	formatNumeric(s.next(8), hdr.Devmajor, paxNone) // 329:337
+	formatNumeric(s.next(8), hdr.Devminor, paxNone) // 337:345
 
 	// keep a reference to the prefix to allow to overwrite it later if we detect that we can use ustar longnames instead of pax
 	prefixHeaderBytes := s.next(155)
-	tw.cString(prefixHeaderBytes, "", false, paxNone, nil) // 345:500  prefix
+	formatString(prefixHeaderBytes, "", paxNone) // 345:500  prefix
 
 	// Use the GNU magic instead of POSIX magic if we used any GNU extensions.
 	if tw.usedBinary {
@@ -215,37 +241,26 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
 	_, paxPathUsed := paxHeaders[paxPath]
 	// try to use a ustar header when only the name is too long
 	if !tw.preferPax && len(paxHeaders) == 1 && paxPathUsed {
-		suffix := hdr.Name
-		prefix := ""
-		if len(hdr.Name) > fileNameSize && isASCII(hdr.Name) {
-			var err error
-			prefix, suffix, err = tw.splitUSTARLongName(hdr.Name)
-			if err == nil {
-				// ok we can use a ustar long name instead of pax, now correct the fields
-
-				// remove the path field from the pax header. this will suppress the pax header
-				delete(paxHeaders, paxPath)
-
-				// update the path fields
-				tw.cString(pathHeaderBytes, suffix, false, paxNone, nil)
-				tw.cString(prefixHeaderBytes, prefix, false, paxNone, nil)
-
-				// Use the ustar magic if we used ustar long names.
-				if len(prefix) > 0 && !tw.usedBinary {
-					copy(header[257:265], []byte("ustar\x00"))
-				}
-			}
+		prefix, suffix, ok := splitUSTARPath(hdr.Name)
+		if ok {
+			// Since we can encode in USTAR format, disable PAX header.
+			delete(paxHeaders, paxPath)
+
+			// Update the path fields
+			formatString(pathHeaderBytes, suffix, paxNone)
+			formatString(prefixHeaderBytes, prefix, paxNone)
 		}
 	}
 
 	// The chksum field is terminated by a NUL and a space.
 	// This is different from the other octal fields.
 	chksum, _ := checksum(header)
-	tw.octal(header[148:155], chksum)
+	f.formatOctal(header[148:155], chksum) // Never fails
 	header[155] = ' '
 
-	if tw.err != nil {
-		// problem with header; probably integer too big for a field.
+	// Check if there were any formatting errors.
+	if f.err != nil {
+		tw.err = f.err
 		return tw.err
 	}
 
@@ -270,28 +285,25 @@ func (tw *Writer) writeHeader(hdr *Header, allowPax bool) error {
 	return tw.err
 }
 
-// writeUSTARLongName splits a USTAR long name hdr.Name.
-// name must be < 256 characters. errNameTooLong is returned
-// if hdr.Name can't be split. The splitting heuristic
-// is compatible with gnu tar.
-func (tw *Writer) splitUSTARLongName(name string) (prefix, suffix string, err error) {
+// splitUSTARPath splits a path according to USTAR prefix and suffix rules.
+// If the path is not splittable, then it will return ("", "", false).
+func splitUSTARPath(name string) (prefix, suffix string, ok bool) {
 	length := len(name)
-	if length > fileNamePrefixSize+1 {
+	if length <= fileNameSize || !isASCII(name) {
+		return "", "", false
+	} else if length > fileNamePrefixSize+1 {
 		length = fileNamePrefixSize + 1
 	} else if name[length-1] == '/' {
 		length--
 	}
+
 	i := strings.LastIndex(name[:length], "/")
-	// nlen contains the resulting length in the name field.
-	// plen contains the resulting length in the prefix field.
-	nlen := len(name) - i - 1
-	plen := i
+	nlen := len(name) - i - 1 // nlen is length of suffix
+	plen := i                 // plen is length of prefix
 	if i <= 0 || nlen > fileNameSize || nlen == 0 || plen > fileNamePrefixSize {
-		err = errNameTooLong
-		return
+		return "", "", false
 	}
-	prefix, suffix = name[:i], name[i+1:]
-	return
+	return name[:i], name[i+1:], true
 }
 
 // writePaxHeader writes an extended pax header to the
@@ -304,11 +316,11 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHeaders map[string]string) erro
 	// succeed, and seems harmless enough.
 	ext.ModTime = hdr.ModTime
 	// The spec asks that we namespace our pseudo files
-	// with the current pid.
-	pid := os.Getpid()
+	// with the current pid.  However, this results in differing outputs
+	// for identical inputs.  As such, the constant 0 is now used instead.
+	// golang.org/issue/12358
 	dir, file := path.Split(hdr.Name)
-	fullName := path.Join(dir,
-		fmt.Sprintf("PaxHeaders.%d", pid), file)
+	fullName := path.Join(dir, "PaxHeaders.0", file)
 
 	ascii := toASCII(fullName)
 	if len(ascii) > 100 {
@@ -318,8 +330,15 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHeaders map[string]string) erro
 	// Construct the body
 	var buf bytes.Buffer
 
-	for k, v := range paxHeaders {
-		fmt.Fprint(&buf, paxHeader(k+"="+v))
+	// Keys are sorted before writing to body to allow deterministic output.
+	var keys []string
+	for k := range paxHeaders {
+		keys = append(keys, k)
+	}
+	sort.Strings(keys)
+
+	for _, k := range keys {
+		fmt.Fprint(&buf, formatPAXRecord(k, paxHeaders[k]))
 	}
 
 	ext.Size = int64(len(buf.Bytes()))
@@ -335,17 +354,18 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHeaders map[string]string) erro
 	return nil
 }
 
-// paxHeader formats a single pax record, prefixing it with the appropriate length
-func paxHeader(msg string) string {
-	const padding = 2 // Extra padding for space and newline
-	size := len(msg) + padding
+// formatPAXRecord formats a single PAX record, prefixing it with the
+// appropriate length.
+func formatPAXRecord(k, v string) string {
+	const padding = 3 // Extra padding for ' ', '=', and '\n'
+	size := len(k) + len(v) + padding
 	size += len(strconv.Itoa(size))
-	record := fmt.Sprintf("%d %s\n", size, msg)
+	record := fmt.Sprintf("%d %s=%s\n", size, k, v)
+
+	// Final adjustment if adding size field increased the record size.
 	if len(record) != size {
-		// Final adjustment if adding size increased
-		// the number of digits in size
 		size = len(record)
-		record = fmt.Sprintf("%d %s\n", size, msg)
+		record = fmt.Sprintf("%d %s=%s\n", size, k, v)
 	}
 	return record
 }
diff --git a/src/archive/tar/writer_test.go b/src/archive/tar/writer_test.go
index fe46a67..6e91d90 100644
--- a/src/archive/tar/writer_test.go
+++ b/src/archive/tar/writer_test.go
@@ -9,8 +9,10 @@ import (
 	"fmt"
 	"io"
 	"io/ioutil"
+	"math"
 	"os"
 	"reflect"
+	"sort"
 	"strings"
 	"testing"
 	"testing/iotest"
@@ -291,7 +293,7 @@ func TestPax(t *testing.T) {
 		t.Fatal(err)
 	}
 	// Simple test to make sure PAX extensions are in effect
-	if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.")) {
+	if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.0")) {
 		t.Fatal("Expected at least one PAX header to be written.")
 	}
 	// Test that we can get a long name back out of the archive.
@@ -330,7 +332,7 @@ func TestPaxSymlink(t *testing.T) {
 		t.Fatal(err)
 	}
 	// Simple test to make sure PAX extensions are in effect
-	if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.")) {
+	if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.0")) {
 		t.Fatal("Expected at least one PAX header to be written.")
 	}
 	// Test that we can get a long name back out of the archive.
@@ -380,7 +382,7 @@ func TestPaxNonAscii(t *testing.T) {
 		t.Fatal(err)
 	}
 	// Simple test to make sure PAX extensions are in effect
-	if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.")) {
+	if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.0")) {
 		t.Fatal("Expected at least one PAX header to be written.")
 	}
 	// Test that we can get a long name back out of the archive.
@@ -439,21 +441,49 @@ func TestPaxXattrs(t *testing.T) {
 	}
 }
 
-func TestPAXHeader(t *testing.T) {
-	medName := strings.Repeat("CD", 50)
-	longName := strings.Repeat("AB", 100)
-	paxTests := [][2]string{
-		{paxPath + "=/etc/hosts", "19 path=/etc/hosts\n"},
-		{"a=b", "6 a=b\n"},          // Single digit length
-		{"a=names", "11 a=names\n"}, // Test case involving carries
-		{paxPath + "=" + longName, fmt.Sprintf("210 path=%s\n", longName)},
-		{paxPath + "=" + medName, fmt.Sprintf("110 path=%s\n", medName)}}
-
-	for _, test := range paxTests {
-		key, expected := test[0], test[1]
-		if result := paxHeader(key); result != expected {
-			t.Fatalf("paxHeader: got %s, expected %s", result, expected)
-		}
+func TestPaxHeadersSorted(t *testing.T) {
+	fileinfo, err := os.Stat("testdata/small.txt")
+	if err != nil {
+		t.Fatal(err)
+	}
+	hdr, err := FileInfoHeader(fileinfo, "")
+	if err != nil {
+		t.Fatalf("os.Stat: %v", err)
+	}
+	contents := strings.Repeat(" ", int(hdr.Size))
+
+	hdr.Xattrs = map[string]string{
+		"foo": "foo",
+		"bar": "bar",
+		"baz": "baz",
+		"qux": "qux",
+	}
+
+	var buf bytes.Buffer
+	writer := NewWriter(&buf)
+	if err := writer.WriteHeader(hdr); err != nil {
+		t.Fatal(err)
+	}
+	if _, err = writer.Write([]byte(contents)); err != nil {
+		t.Fatal(err)
+	}
+	if err := writer.Close(); err != nil {
+		t.Fatal(err)
+	}
+	// Simple test to make sure PAX extensions are in effect
+	if !bytes.Contains(buf.Bytes(), []byte("PaxHeaders.0")) {
+		t.Fatal("Expected at least one PAX header to be written.")
+	}
+
+	// xattr bar should always appear before others
+	indices := []int{
+		bytes.Index(buf.Bytes(), []byte("bar=bar")),
+		bytes.Index(buf.Bytes(), []byte("baz=baz")),
+		bytes.Index(buf.Bytes(), []byte("foo=foo")),
+		bytes.Index(buf.Bytes(), []byte("qux=qux")),
+	}
+	if !sort.IntsAreSorted(indices) {
+		t.Fatal("PAX headers are not sorted")
 	}
 }
 
@@ -544,3 +574,149 @@ func TestWriteAfterClose(t *testing.T) {
 		t.Fatalf("Write: got %v; want ErrWriteAfterClose", err)
 	}
 }
+
+func TestSplitUSTARPath(t *testing.T) {
+	var sr = strings.Repeat
+
+	var vectors = []struct {
+		input  string // Input path
+		prefix string // Expected output prefix
+		suffix string // Expected output suffix
+		ok     bool   // Split success?
+	}{
+		{"", "", "", false},
+		{"abc", "", "", false},
+		{"用戶名", "", "", false},
+		{sr("a", fileNameSize), "", "", false},
+		{sr("a", fileNameSize) + "/", "", "", false},
+		{sr("a", fileNameSize) + "/a", sr("a", fileNameSize), "a", true},
+		{sr("a", fileNamePrefixSize) + "/", "", "", false},
+		{sr("a", fileNamePrefixSize) + "/a", sr("a", fileNamePrefixSize), "a", true},
+		{sr("a", fileNameSize+1), "", "", false},
+		{sr("/", fileNameSize+1), sr("/", fileNameSize-1), "/", true},
+		{sr("a", fileNamePrefixSize) + "/" + sr("b", fileNameSize),
+			sr("a", fileNamePrefixSize), sr("b", fileNameSize), true},
+		{sr("a", fileNamePrefixSize) + "//" + sr("b", fileNameSize), "", "", false},
+		{sr("a/", fileNameSize), sr("a/", 77) + "a", sr("a/", 22), true},
+	}
+
+	for _, v := range vectors {
+		prefix, suffix, ok := splitUSTARPath(v.input)
+		if prefix != v.prefix || suffix != v.suffix || ok != v.ok {
+			t.Errorf("splitUSTARPath(%q):\ngot  (%q, %q, %v)\nwant (%q, %q, %v)",
+				v.input, prefix, suffix, ok, v.prefix, v.suffix, v.ok)
+		}
+	}
+}
+
+func TestFormatPAXRecord(t *testing.T) {
+	var medName = strings.Repeat("CD", 50)
+	var longName = strings.Repeat("AB", 100)
+
+	var vectors = []struct {
+		inputKey string
+		inputVal string
+		output   string
+	}{
+		{"k", "v", "6 k=v\n"},
+		{"path", "/etc/hosts", "19 path=/etc/hosts\n"},
+		{"path", longName, "210 path=" + longName + "\n"},
+		{"path", medName, "110 path=" + medName + "\n"},
+		{"foo", "ba", "9 foo=ba\n"},
+		{"foo", "bar", "11 foo=bar\n"},
+		{"foo", "b=\nar=\n==\x00", "18 foo=b=\nar=\n==\x00\n"},
+		{"foo", "hello9 foo=ba\nworld", "27 foo=hello9 foo=ba\nworld\n"},
+		{"☺☻☹", "日a本b語ç", "27 ☺☻☹=日a本b語ç\n"},
+		{"\x00hello", "\x00world", "17 \x00hello=\x00world\n"},
+	}
+
+	for _, v := range vectors {
+		output := formatPAXRecord(v.inputKey, v.inputVal)
+		if output != v.output {
+			t.Errorf("formatPAXRecord(%q, %q): got %q, want %q",
+				v.inputKey, v.inputVal, output, v.output)
+		}
+	}
+}
+
+func TestFitsInBase256(t *testing.T) {
+	var vectors = []struct {
+		input int64
+		width int
+		ok    bool
+	}{
+		{+1, 8, true},
+		{0, 8, true},
+		{-1, 8, true},
+		{1 << 56, 8, false},
+		{(1 << 56) - 1, 8, true},
+		{-1 << 56, 8, true},
+		{(-1 << 56) - 1, 8, false},
+		{121654, 8, true},
+		{-9849849, 8, true},
+		{math.MaxInt64, 9, true},
+		{0, 9, true},
+		{math.MinInt64, 9, true},
+		{math.MaxInt64, 12, true},
+		{0, 12, true},
+		{math.MinInt64, 12, true},
+	}
+
+	for _, v := range vectors {
+		ok := fitsInBase256(v.width, v.input)
+		if ok != v.ok {
+			t.Errorf("checkNumeric(%d, %d): got %v, want %v", v.input, v.width, ok, v.ok)
+		}
+	}
+}
+
+func TestFormatNumeric(t *testing.T) {
+	var vectors = []struct {
+		input  int64
+		output string
+		ok     bool
+	}{
+		// Test base-256 (binary) encoded values.
+		{-1, "\xff", true},
+		{-1, "\xff\xff", true},
+		{-1, "\xff\xff\xff", true},
+		{(1 << 0), "0", false},
+		{(1 << 8) - 1, "\x80\xff", true},
+		{(1 << 8), "0\x00", false},
+		{(1 << 16) - 1, "\x80\xff\xff", true},
+		{(1 << 16), "00\x00", false},
+		{-1 * (1 << 0), "\xff", true},
+		{-1*(1<<0) - 1, "0", false},
+		{-1 * (1 << 8), "\xff\x00", true},
+		{-1*(1<<8) - 1, "0\x00", false},
+		{-1 * (1 << 16), "\xff\x00\x00", true},
+		{-1*(1<<16) - 1, "00\x00", false},
+		{537795476381659745, "0000000\x00", false},
+		{537795476381659745, "\x80\x00\x00\x00\x07\x76\xa2\x22\xeb\x8a\x72\x61", true},
+		{-615126028225187231, "0000000\x00", false},
+		{-615126028225187231, "\xff\xff\xff\xff\xf7\x76\xa2\x22\xeb\x8a\x72\x61", true},
+		{math.MaxInt64, "0000000\x00", false},
+		{math.MaxInt64, "\x80\x00\x00\x00\x7f\xff\xff\xff\xff\xff\xff\xff", true},
+		{math.MinInt64, "0000000\x00", false},
+		{math.MinInt64, "\xff\xff\xff\xff\x80\x00\x00\x00\x00\x00\x00\x00", true},
+		{math.MaxInt64, "\x80\x7f\xff\xff\xff\xff\xff\xff\xff", true},
+		{math.MinInt64, "\xff\x80\x00\x00\x00\x00\x00\x00\x00", true},
+	}
+
+	for _, v := range vectors {
+		var f formatter
+		output := make([]byte, len(v.output))
+		f.formatNumeric(output, v.input)
+		ok := (f.err == nil)
+		if ok != v.ok {
+			if v.ok {
+				t.Errorf("formatNumeric(%d): got formatting failure, want success", v.input)
+			} else {
+				t.Errorf("formatNumeric(%d): got formatting success, want failure", v.input)
+			}
+		}
+		if string(output) != v.output {
+			t.Errorf("formatNumeric(%d): got %q, want %q", v.input, output, v.output)
+		}
+	}
+}
diff --git a/src/archive/zip/example_test.go b/src/archive/zip/example_test.go
index c2ed9e7..1eed304 100644
--- a/src/archive/zip/example_test.go
+++ b/src/archive/zip/example_test.go
@@ -7,6 +7,7 @@ package zip_test
 import (
 	"archive/zip"
 	"bytes"
+	"compress/flate"
 	"fmt"
 	"io"
 	"log"
@@ -73,3 +74,20 @@ func ExampleReader() {
 	// Contents of README:
 	// This is the source code repository for the Go programming language.
 }
+
+func ExampleWriter_RegisterCompressor() {
+	// Override the default Deflate compressor with a higher compression level.
+
+	// Create a buffer to write our archive to.
+	buf := new(bytes.Buffer)
+
+	// Create a new zip archive.
+	w := zip.NewWriter(buf)
+
+	// Register a custom Deflate compressor.
+	w.RegisterCompressor(zip.Deflate, func(out io.Writer) (io.WriteCloser, error) {
+		return flate.NewWriter(out, flate.BestCompression)
+	})
+
+	// Proceed to add files to w.
+}
diff --git a/src/archive/zip/reader.go b/src/archive/zip/reader.go
index 519748b..10e8172 100644
--- a/src/archive/zip/reader.go
+++ b/src/archive/zip/reader.go
@@ -22,9 +22,10 @@ var (
 )
 
 type Reader struct {
-	r       io.ReaderAt
-	File    []*File
-	Comment string
+	r             io.ReaderAt
+	File          []*File
+	Comment       string
+	decompressors map[uint16]Decompressor
 }
 
 type ReadCloser struct {
@@ -34,6 +35,7 @@ type ReadCloser struct {
 
 type File struct {
 	FileHeader
+	zip          *Reader
 	zipr         io.ReaderAt
 	zipsize      int64
 	headerOffset int64
@@ -95,7 +97,7 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
 	// a bad one, and then only report a ErrFormat or UnexpectedEOF if
 	// the file count modulo 65536 is incorrect.
 	for {
-		f := &File{zipr: r, zipsize: size}
+		f := &File{zip: z, zipr: r, zipsize: size}
 		err = readDirectoryHeader(f, buf)
 		if err == ErrFormat || err == io.ErrUnexpectedEOF {
 			break
@@ -113,6 +115,24 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
 	return nil
 }
 
+// RegisterDecompressor registers or overrides a custom decompressor for a
+// specific method ID. If a decompressor for a given method is not found,
+// Reader will default to looking up the decompressor at the package level.
+func (z *Reader) RegisterDecompressor(method uint16, dcomp Decompressor) {
+	if z.decompressors == nil {
+		z.decompressors = make(map[uint16]Decompressor)
+	}
+	z.decompressors[method] = dcomp
+}
+
+func (z *Reader) decompressor(method uint16) Decompressor {
+	dcomp := z.decompressors[method]
+	if dcomp == nil {
+		dcomp = decompressor(method)
+	}
+	return dcomp
+}
+
 // Close closes the Zip file, rendering it unusable for I/O.
 func (rc *ReadCloser) Close() error {
 	return rc.f.Close()
@@ -140,7 +160,7 @@ func (f *File) Open() (rc io.ReadCloser, err error) {
 	}
 	size := int64(f.CompressedSize64)
 	r := io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset, size)
-	dcomp := decompressor(f.Method)
+	dcomp := f.zip.decompressor(f.Method)
 	if dcomp == nil {
 		err = ErrAlgorithm
 		return
@@ -261,39 +281,69 @@ func readDirectoryHeader(f *File, r io.Reader) error {
 	f.Extra = d[filenameLen : filenameLen+extraLen]
 	f.Comment = string(d[filenameLen+extraLen:])
 
+	needUSize := f.UncompressedSize == ^uint32(0)
+	needCSize := f.CompressedSize == ^uint32(0)
+	needHeaderOffset := f.headerOffset == int64(^uint32(0))
+
 	if len(f.Extra) > 0 {
+		// Best effort to find what we need.
+		// Other zip authors might not even follow the basic format,
+		// and we'll just ignore the Extra content in that case.
 		b := readBuf(f.Extra)
 		for len(b) >= 4 { // need at least tag and size
 			tag := b.uint16()
 			size := b.uint16()
 			if int(size) > len(b) {
-				return ErrFormat
+				break
 			}
 			if tag == zip64ExtraId {
-				// update directory values from the zip64 extra block
+				// update directory values from the zip64 extra block.
+				// They should only be consulted if the sizes read earlier
+				// are maxed out.
+				// See golang.org/issue/13367.
 				eb := readBuf(b[:size])
-				if len(eb) >= 8 {
+
+				if needUSize {
+					needUSize = false
+					if len(eb) < 8 {
+						return ErrFormat
+					}
 					f.UncompressedSize64 = eb.uint64()
 				}
-				if len(eb) >= 8 {
+				if needCSize {
+					needCSize = false
+					if len(eb) < 8 {
+						return ErrFormat
+					}
 					f.CompressedSize64 = eb.uint64()
 				}
-				if len(eb) >= 8 {
+				if needHeaderOffset {
+					needHeaderOffset = false
+					if len(eb) < 8 {
+						return ErrFormat
+					}
 					f.headerOffset = int64(eb.uint64())
 				}
+				break
 			}
 			b = b[size:]
 		}
-		// Should have consumed the whole header.
-		// But popular zip & JAR creation tools are broken and
-		// may pad extra zeros at the end, so accept those
-		// too. See golang.org/issue/8186.
-		for _, v := range b {
-			if v != 0 {
-				return ErrFormat
-			}
-		}
 	}
+
+	// Assume that uncompressed size 2³²-1 could plausibly happen in
+	// an old zip32 file that was sharding inputs into the largest chunks
+	// possible (or is just malicious; search the web for 42.zip).
+	// If needUSize is true still, it means we didn't see a zip64 extension.
+	// As long as the compressed size is not also 2³²-1 (implausible)
+	// and the header is not also 2³²-1 (equally implausible),
+	// accept the uncompressed size 2³²-1 as valid.
+	// If nothing else, this keeps archive/zip working with 42.zip.
+	_ = needUSize
+
+	if needCSize || needHeaderOffset {
+		return ErrFormat
+	}
+
 	return nil
 }
 
@@ -376,14 +426,16 @@ func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error)
 	}
 	d.comment = string(b[:l])
 
-	p, err := findDirectory64End(r, directoryEndOffset)
-	if err == nil && p >= 0 {
-		err = readDirectory64End(r, p, d)
-	}
-	if err != nil {
-		return nil, err
+	// These values mean that the file can be a zip64 file
+	if d.directoryRecords == 0xffff || d.directorySize == 0xffff || d.directoryOffset == 0xffffffff {
+		p, err := findDirectory64End(r, directoryEndOffset)
+		if err == nil && p >= 0 {
+			err = readDirectory64End(r, p, d)
+		}
+		if err != nil {
+			return nil, err
+		}
 	}
-
 	// Make sure directoryOffset points to somewhere in our file.
 	if o := int64(d.directoryOffset); o < 0 || o >= size {
 		return nil, ErrFormat
@@ -407,8 +459,13 @@ func findDirectory64End(r io.ReaderAt, directoryEndOffset int64) (int64, error)
 	if sig := b.uint32(); sig != directory64LocSignature {
 		return -1, nil
 	}
-	b = b[4:]       // skip number of the disk with the start of the zip64 end of central directory
-	p := b.uint64() // relative offset of the zip64 end of central directory record
+	if b.uint32() != 0 { // number of the disk with the start of the zip64 end of central directory
+		return -1, nil // the file is not a valid zip64-file
+	}
+	p := b.uint64()      // relative offset of the zip64 end of central directory record
+	if b.uint32() != 1 { // total number of disks
+		return -1, nil // the file is not a valid zip64-file
+	}
 	return int64(p), nil
 }
 
diff --git a/src/archive/zip/reader_test.go b/src/archive/zip/reader_test.go
index 547dd39..72cf5d9 100644
--- a/src/archive/zip/reader_test.go
+++ b/src/archive/zip/reader_test.go
@@ -27,12 +27,24 @@ type ZipTest struct {
 }
 
 type ZipTestFile struct {
-	Name       string
-	Content    []byte // if blank, will attempt to compare against File
+	Name  string
+	Mode  os.FileMode
+	Mtime string // optional, modified time in format "mm-dd-yy hh:mm:ss"
+
+	// Information describing expected zip file content.
+	// First, reading the entire content should produce the error ContentErr.
+	// Second, if ContentErr==nil, the content should match Content.
+	// If content is large, an alternative to setting Content is to set File,
+	// which names a file in the testdata/ directory containing the
+	// uncompressed expected content.
+	// If content is very large, an alternative to setting Content or File
+	// is to set Size, which will then be checked against the header-reported size
+	// but will bypass the decompressing of the actual data.
+	// This last option is used for testing very large (multi-GB) compressed files.
 	ContentErr error
-	File       string // name of file to compare to (relative to testdata/)
-	Mtime      string // modified time in format "mm-dd-yy hh:mm:ss"
-	Mode       os.FileMode
+	Content    []byte
+	File       string
+	Size       uint64
 }
 
 // Caution: The Mtime values found for the test files should correspond to
@@ -248,6 +260,19 @@ var tests = []ZipTest{
 			},
 		},
 	},
+	// Largest possible non-zip64 file, with no zip64 header.
+	{
+		Name:   "big.zip",
+		Source: returnBigZipBytes,
+		File: []ZipTestFile{
+			{
+				Name:    "big.file",
+				Content: nil,
+				Size:    1<<32 - 1,
+				Mode:    0666,
+			},
+		},
+	},
 }
 
 var crossPlatform = []ZipTestFile{
@@ -356,13 +381,31 @@ func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) {
 
 	testFileMode(t, zt.Name, f, ft.Mode)
 
-	var b bytes.Buffer
+	size := uint64(f.UncompressedSize)
+	if size == uint32max {
+		size = f.UncompressedSize64
+	} else if size != f.UncompressedSize64 {
+		t.Errorf("%v: UncompressedSize=%#x does not match UncompressedSize64=%#x", f.Name, size, f.UncompressedSize64)
+	}
+
 	r, err := f.Open()
 	if err != nil {
 		t.Errorf("%s: %v", zt.Name, err)
 		return
 	}
 
+	// For very large files, just check that the size is correct.
+	// The content is expected to be all zeros.
+	// Don't bother uncompressing: too big.
+	if ft.Content == nil && ft.File == "" && ft.Size > 0 {
+		if size != ft.Size {
+			t.Errorf("%v: uncompressed size %#x, want %#x", size, ft.Size)
+		}
+		r.Close()
+		return
+	}
+
+	var b bytes.Buffer
 	_, err = io.Copy(&b, r)
 	if err != ft.ContentErr {
 		t.Errorf("%s: copying contents: %v (want %v)", zt.Name, err, ft.ContentErr)
@@ -372,10 +415,6 @@ func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) {
 	}
 	r.Close()
 
-	size := uint64(f.UncompressedSize)
-	if size == uint32max {
-		size = f.UncompressedSize64
-	}
 	if g := uint64(b.Len()); g != size {
 		t.Errorf("%v: read %v bytes but f.UncompressedSize == %v", f.Name, g, size)
 	}
@@ -510,6 +549,182 @@ func returnRecursiveZip() (r io.ReaderAt, size int64) {
 	return bytes.NewReader(b), int64(len(b))
 }
 
+// biggestZipBytes returns the bytes of a zip file biggest.zip
+// that contains a zip file bigger.zip that contains a zip file
+// big.zip that contains big.file, which contains 2³²-1 zeros.
+// The big.zip file is interesting because it has no zip64 header,
+// much like the innermost zip files in the well-known 42.zip.
+//
+// biggest.zip was generated by changing isZip64 to use > uint32max
+// instead of >= uint32max and then running this program:
+//
+//	package main
+//
+//	import (
+//		"archive/zip"
+//		"bytes"
+//		"io"
+//		"io/ioutil"
+//		"log"
+//	)
+//
+//	type zeros struct{}
+//
+//	func (zeros) Read(b []byte) (int, error) {
+//		for i := range b {
+//			b[i] = 0
+//		}
+//		return len(b), nil
+//	}
+//
+//	func main() {
+//		bigZip := makeZip("big.file", io.LimitReader(zeros{}, 1<<32-1))
+//		if err := ioutil.WriteFile("/tmp/big.zip", bigZip, 0666); err != nil {
+//			log.Fatal(err)
+//		}
+//
+//		biggerZip := makeZip("big.zip", bytes.NewReader(bigZip))
+//		if err := ioutil.WriteFile("/tmp/bigger.zip", biggerZip, 0666); err != nil {
+//			log.Fatal(err)
+//		}
+//
+//		biggestZip := makeZip("bigger.zip", bytes.NewReader(biggerZip))
+//		if err := ioutil.WriteFile("/tmp/biggest.zip", biggestZip, 0666); err != nil {
+//			log.Fatal(err)
+//		}
+//	}
+//
+//	func makeZip(name string, r io.Reader) []byte {
+//		var buf bytes.Buffer
+//		w := zip.NewWriter(&buf)
+//		wf, err := w.Create(name)
+//		if err != nil {
+//			log.Fatal(err)
+//		}
+//		if _, err = io.Copy(wf, r); err != nil {
+//			log.Fatal(err)
+//		}
+//		if err := w.Close(); err != nil {
+//			log.Fatal(err)
+//		}
+//		return buf.Bytes()
+//	}
+//
+// The 4 GB of zeros compresses to 4 MB, which compresses to 20 kB,
+// which compresses to 1252 bytes (in the hex dump below).
+//
+// It's here in hex for the same reason as rZipBytes above: to avoid
+// problems with on-disk virus scanners or other zip processors.
+//
+func biggestZipBytes() []byte {
+	s := `
+0000000 50 4b 03 04 14 00 08 00 08 00 00 00 00 00 00 00
+0000010 00 00 00 00 00 00 00 00 00 00 0a 00 00 00 62 69
+0000020 67 67 65 72 2e 7a 69 70 ec dc 6b 4c 53 67 18 07
+0000030 f0 16 c5 ca 65 2e cb b8 94 20 61 1f 44 33 c7 cd
+0000040 c0 86 4a b5 c0 62 8a 61 05 c6 cd 91 b2 54 8c 1b
+0000050 63 8b 03 9c 1b 95 52 5a e3 a0 19 6c b2 05 59 44
+0000060 64 9d 73 83 71 11 46 61 14 b9 1d 14 09 4a c3 60
+0000070 2e 4c 6e a5 60 45 02 62 81 95 b6 94 9e 9e 77 e7
+0000080 d0 43 b6 f8 71 df 96 3c e7 a4 69 ce bf cf e9 79
+0000090 ce ef 79 3f bf f1 31 db b6 bb 31 76 92 e7 f3 07
+00000a0 8b fc 9c ca cc 08 cc cb cc 5e d2 1c 88 d9 7e bb
+00000b0 4f bb 3a 3f 75 f1 5d 7f 8f c2 68 67 77 8f 25 ff
+00000c0 84 e2 93 2d ef a4 95 3d 71 4e 2c b9 b0 87 c3 be
+00000d0 3d f8 a7 60 24 61 c5 ef ae 9e c8 6c 6d 4e 69 c8
+00000e0 67 65 34 f8 37 76 2d 76 5c 54 f3 95 65 49 c7 0f
+00000f0 18 71 4b 7e 5b 6a d1 79 47 61 41 b0 4e 2a 74 45
+0000100 43 58 12 b2 5a a5 c6 7d 68 55 88 d4 98 75 18 6d
+0000110 08 d1 1f 8f 5a 9e 96 ee 45 cf a4 84 4e 4b e8 50
+0000120 a7 13 d9 06 de 52 81 97 36 b2 d7 b8 fc 2b 5f 55
+0000130 23 1f 32 59 cf 30 27 fb e2 8a b9 de 45 dd 63 9c
+0000140 4b b5 8b 96 4c 7a 62 62 cc a1 a7 cf fa f1 fe dd
+0000150 54 62 11 bf 36 78 b3 c7 b1 b5 f2 61 4d 4e dd 66
+0000160 32 2e e6 70 34 5f f4 c9 e6 6c 43 6f da 6b c6 c3
+0000170 09 2c ce 09 57 7f d2 7e b4 23 ba 7c 1b 99 bc 22
+0000180 3e f1 de 91 2f e3 9c 1b 82 cc c2 84 39 aa e6 de
+0000190 b4 69 fc cc cb 72 a6 61 45 f0 d3 1d 26 19 7c 8d
+00001a0 29 c8 66 02 be 77 6a f9 3d 34 79 17 19 c8 96 24
+00001b0 a3 ac e4 dd 3b 1a 8e c6 fe 96 38 6b bf 67 5a 23
+00001c0 f4 16 f4 e6 8a b4 fc c2 cd bf 95 66 1d bb 35 aa
+00001d0 92 7d 66 d8 08 8d a5 1f 54 2a af 09 cf 61 ff d2
+00001e0 85 9d 8f b6 d7 88 07 4a 86 03 db 64 f3 d9 92 73
+00001f0 df ec a7 fc 23 4c 8d 83 79 63 2a d9 fd 8d b3 c8
+0000200 8f 7e d4 19 85 e6 8d 1c 76 f0 8b 58 32 fd 9a d6
+0000210 85 e2 48 ad c3 d5 60 6f 7e 22 dd ef 09 49 7c 7f
+0000220 3a 45 c3 71 b7 df f3 4c 63 fb b5 d9 31 5f 6e d6
+0000230 24 1d a4 4a fe 32 a7 5c 16 48 5c 3e 08 6b 8a d3
+0000240 25 1d a2 12 a5 59 24 ea 20 5f 52 6d ad 94 db 6b
+0000250 94 b9 5d eb 4b a7 5c 44 bb 1e f2 3c 6b cf 52 c9
+0000260 e9 e5 ba 06 b9 c4 e5 0a d0 00 0d d0 00 0d d0 00
+0000270 0d d0 00 0d d0 00 0d d0 00 0d d0 00 0d d0 00 0d
+0000280 d0 00 0d d0 00 0d d0 00 0d d0 00 0d d0 00 0d d0
+0000290 00 0d d0 00 0d d0 00 0d d0 00 0d d0 00 0d d0 00
+00002a0 0d d0 00 cd ff 9e 46 86 fa a7 7d 3a 43 d7 8e 10
+00002b0 52 e9 be e6 6e cf eb 9e 85 4d 65 ce cc 30 c1 44
+00002c0 c0 4e af bc 9c 6c 4b a0 d7 54 ff 1d d5 5c 89 fb
+00002d0 b5 34 7e c4 c2 9e f5 a0 f6 5b 7e 6e ca 73 c7 ef
+00002e0 5d be de f9 e8 81 eb a5 0a a5 63 54 2c d7 1c d1
+00002f0 89 17 85 f8 16 94 f2 8a b2 a3 f5 b6 6d df 75 cd
+0000300 90 dd 64 bd 5d 55 4e f2 55 19 1b b7 cc ef 1b ea
+0000310 2e 05 9c f4 aa 1e a8 cd a6 82 c7 59 0f 5e 9d e0
+0000320 bb fc 6c d6 99 23 eb 36 ad c6 c5 e1 d8 e1 e2 3e
+0000330 d9 90 5a f7 91 5d 6f bc 33 6d 98 47 d2 7c 2e 2f
+0000340 99 a4 25 72 85 49 2c be 0b 5b af 8f e5 6e 81 a6
+0000350 a3 5a 6f 39 53 3a ab 7a 8b 1e 26 f7 46 6c 7d 26
+0000360 53 b3 22 31 94 d3 83 f2 18 4d f5 92 33 27 53 97
+0000370 0f d3 e6 55 9c a6 c5 31 87 6f d3 f3 ae 39 6f 56
+0000380 10 7b ab 7e d0 b4 ca f2 b8 05 be 3f 0e 6e 5a 75
+0000390 ab 0c f5 37 0e ba 8e 75 71 7a aa ed 7a dd 6a 63
+00003a0 be 9b a0 97 27 6a 6f e7 d3 8b c4 7c ec d3 91 56
+00003b0 d9 ac 5e bf 16 42 2f 00 1f 93 a2 23 87 bd e2 59
+00003c0 a0 de 1a 66 c8 62 eb 55 8f 91 17 b4 61 42 7a 50
+00003d0 40 03 34 40 03 34 40 03 34 40 03 34 40 03 34 40
+00003e0 03 34 40 03 34 40 03 34 40 03 34 40 03 34 40 03
+00003f0 34 40 03 34 40 03 34 ff 85 86 90 8b ea 67 90 0d
+0000400 e1 42 1b d2 61 d6 79 ec fd 3e 44 28 a4 51 6c 5c
+0000410 fc d2 72 ca ba 82 18 46 16 61 cd 93 a9 0f d1 24
+0000420 17 99 e2 2c 71 16 84 0c c8 7a 13 0f 9a 5e c5 f0
+0000430 79 64 e2 12 4d c8 82 a1 81 19 2d aa 44 6d 87 54
+0000440 84 71 c1 f6 d4 ca 25 8c 77 b9 08 c7 c8 5e 10 8a
+0000450 8f 61 ed 8c ba 30 1f 79 9a c7 60 34 2b b9 8c f8
+0000460 18 a6 83 1b e3 9f ad 79 fe fd 1b 8b f1 fc 41 6f
+0000470 d4 13 1f e3 b8 83 ba 64 92 e7 eb e4 77 05 8f ba
+0000480 fa 3b 00 00 ff ff 50 4b 07 08 a6 18 b1 91 5e 04
+0000490 00 00 e4 47 00 00 50 4b 01 02 14 00 14 00 08 00
+00004a0 08 00 00 00 00 00 a6 18 b1 91 5e 04 00 00 e4 47
+00004b0 00 00 0a 00 00 00 00 00 00 00 00 00 00 00 00 00
+00004c0 00 00 00 00 62 69 67 67 65 72 2e 7a 69 70 50 4b
+00004d0 05 06 00 00 00 00 01 00 01 00 38 00 00 00 96 04
+00004e0 00 00 00 00`
+	s = regexp.MustCompile(`[0-9a-f]{7}`).ReplaceAllString(s, "")
+	s = regexp.MustCompile(`\s+`).ReplaceAllString(s, "")
+	b, err := hex.DecodeString(s)
+	if err != nil {
+		panic(err)
+	}
+	return b
+}
+
+func returnBigZipBytes() (r io.ReaderAt, size int64) {
+	b := biggestZipBytes()
+	for i := 0; i < 2; i++ {
+		r, err := NewReader(bytes.NewReader(b), int64(len(b)))
+		if err != nil {
+			panic(err)
+		}
+		f, err := r.File[0].Open()
+		if err != nil {
+			panic(err)
+		}
+		b, err = ioutil.ReadAll(f)
+		if err != nil {
+			panic(err)
+		}
+	}
+	return bytes.NewReader(b), int64(len(b))
+}
+
 func TestIssue8186(t *testing.T) {
 	// Directory headers & data found in the TOC of a JAR file.
 	dirEnts := []string{
@@ -605,3 +820,40 @@ func TestIssue11146(t *testing.T) {
 	}
 	r.Close()
 }
+
+// Verify we do not treat non-zip64 archives as zip64
+func TestIssue12449(t *testing.T) {
+	data := []byte{
+		0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x00,
+		0x00, 0x00, 0x6b, 0xb4, 0xba, 0x46, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x03, 0x00, 0x18, 0x00, 0xca, 0x64,
+		0x55, 0x75, 0x78, 0x0b, 0x00, 0x50, 0x4b, 0x05,
+		0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
+		0x00, 0x49, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00,
+		0x00, 0x31, 0x31, 0x31, 0x32, 0x32, 0x32, 0x0a,
+		0x50, 0x4b, 0x07, 0x08, 0x1d, 0x88, 0x77, 0xb0,
+		0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+		0x50, 0x4b, 0x01, 0x02, 0x14, 0x03, 0x14, 0x00,
+		0x08, 0x00, 0x00, 0x00, 0x6b, 0xb4, 0xba, 0x46,
+		0x1d, 0x88, 0x77, 0xb0, 0x07, 0x00, 0x00, 0x00,
+		0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x18, 0x00,
+		0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0xa0, 0x81, 0x00, 0x00, 0x00, 0x00, 0xca, 0x64,
+		0x55, 0x75, 0x78, 0x0b, 0x00, 0x50, 0x4b, 0x05,
+		0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
+		0x00, 0x49, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00,
+		0x00, 0x97, 0x2b, 0x49, 0x23, 0x05, 0xc5, 0x0b,
+		0xa7, 0xd1, 0x52, 0xa2, 0x9c, 0x50, 0x4b, 0x06,
+		0x07, 0xc8, 0x19, 0xc1, 0xaf, 0x94, 0x9c, 0x61,
+		0x44, 0xbe, 0x94, 0x19, 0x42, 0x58, 0x12, 0xc6,
+		0x5b, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00,
+		0x00, 0x01, 0x00, 0x01, 0x00, 0x69, 0x00, 0x00,
+		0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00,
+	}
+	// Read in the archive.
+	_, err := NewReader(bytes.NewReader([]byte(data)), int64(len(data)))
+	if err != nil {
+		t.Errorf("Error reading the archive: %v", err)
+	}
+}
diff --git a/src/archive/zip/register.go b/src/archive/zip/register.go
index 4211ec7..8fccbf7 100644
--- a/src/archive/zip/register.go
+++ b/src/archive/zip/register.go
@@ -12,15 +12,19 @@ import (
 	"sync"
 )
 
-// A Compressor returns a compressing writer, writing to the
-// provided writer. On Close, any pending data should be flushed.
-type Compressor func(io.Writer) (io.WriteCloser, error)
-
-// Decompressor is a function that wraps a Reader with a decompressing Reader.
-// The decompressed ReadCloser is returned to callers who open files from
-// within the archive.  These callers are responsible for closing this reader
-// when they're finished reading.
-type Decompressor func(io.Reader) io.ReadCloser
+// A Compressor returns a new compressing writer, writing to w.
+// The WriteCloser's Close method must be used to flush pending data to w.
+// The Compressor itself must be safe to invoke from multiple goroutines
+// simultaneously, but each returned writer will be used only by
+// one goroutine at a time.
+type Compressor func(w io.Writer) (io.WriteCloser, error)
+
+// A Decompressor returns a new decompressing reader, reading from r.
+// The ReadCloser's Close method must be used to release associated resources.
+// The Decompressor itself must be safe to invoke from multiple goroutines
+// simultaneously, but each returned reader will be used only by
+// one goroutine at a time.
+type Decompressor func(r io.Reader) io.ReadCloser
 
 var flateWriterPool sync.Pool
 
@@ -75,14 +79,15 @@ var (
 )
 
 // RegisterDecompressor allows custom decompressors for a specified method ID.
-func RegisterDecompressor(method uint16, d Decompressor) {
+// The common methods Store and Deflate are built in.
+func RegisterDecompressor(method uint16, dcomp Decompressor) {
 	mu.Lock()
 	defer mu.Unlock()
 
 	if _, ok := decompressors[method]; ok {
 		panic("decompressor already registered")
 	}
-	decompressors[method] = d
+	decompressors[method] = dcomp
 }
 
 // RegisterCompressor registers custom compressors for a specified method ID.
diff --git a/src/archive/zip/struct.go b/src/archive/zip/struct.go
index 137d049..5ee4f88 100644
--- a/src/archive/zip/struct.go
+++ b/src/archive/zip/struct.go
@@ -235,7 +235,7 @@ func (h *FileHeader) SetMode(mode os.FileMode) {
 
 // isZip64 reports whether the file size exceeds the 32 bit limit
 func (fh *FileHeader) isZip64() bool {
-	return fh.CompressedSize64 > uint32max || fh.UncompressedSize64 > uint32max
+	return fh.CompressedSize64 >= uint32max || fh.UncompressedSize64 >= uint32max
 }
 
 func msdosModeToFileMode(m uint32) (mode os.FileMode) {
diff --git a/src/archive/zip/writer.go b/src/archive/zip/writer.go
index 3be2b5f..5ce66e6 100644
--- a/src/archive/zip/writer.go
+++ b/src/archive/zip/writer.go
@@ -14,14 +14,14 @@ import (
 )
 
 // TODO(adg): support zip file comments
-// TODO(adg): support specifying deflate level
 
 // Writer implements a zip file writer.
 type Writer struct {
-	cw     *countWriter
-	dir    []*header
-	last   *fileWriter
-	closed bool
+	cw          *countWriter
+	dir         []*header
+	last        *fileWriter
+	closed      bool
+	compressors map[uint16]Compressor
 }
 
 type header struct {
@@ -78,7 +78,7 @@ func (w *Writer) Close() error {
 		b.uint16(h.ModifiedTime)
 		b.uint16(h.ModifiedDate)
 		b.uint32(h.CRC32)
-		if h.isZip64() || h.offset > uint32max {
+		if h.isZip64() || h.offset >= uint32max {
 			// the file needs a zip64 header. store maxint in both
 			// 32 bit size fields (and offset later) to signal that the
 			// zip64 extra header should be used.
@@ -220,7 +220,7 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
 		compCount: &countWriter{w: w.cw},
 		crc32:     crc32.NewIEEE(),
 	}
-	comp := compressor(fh.Method)
+	comp := w.compressor(fh.Method)
 	if comp == nil {
 		return nil, ErrAlgorithm
 	}
@@ -270,6 +270,24 @@ func writeHeader(w io.Writer, h *FileHeader) error {
 	return err
 }
 
+// RegisterCompressor registers or overrides a custom compressor for a specific
+// method ID. If a compressor for a given method is not found, Writer will
+// default to looking up the compressor at the package level.
+func (w *Writer) RegisterCompressor(method uint16, comp Compressor) {
+	if w.compressors == nil {
+		w.compressors = make(map[uint16]Compressor)
+	}
+	w.compressors[method] = comp
+}
+
+func (w *Writer) compressor(method uint16) Compressor {
+	comp := w.compressors[method]
+	if comp == nil {
+		comp = compressor(method)
+	}
+	return comp
+}
+
 type fileWriter struct {
 	*header
 	zipw      io.Writer
diff --git a/src/archive/zip/zip_test.go b/src/archive/zip/zip_test.go
index f00ff47..f785abf 100644
--- a/src/archive/zip/zip_test.go
+++ b/src/archive/zip/zip_test.go
@@ -10,6 +10,7 @@ import (
 	"bytes"
 	"fmt"
 	"hash"
+	"internal/testenv"
 	"io"
 	"io/ioutil"
 	"sort"
@@ -19,6 +20,9 @@ import (
 )
 
 func TestOver65kFiles(t *testing.T) {
+	if testing.Short() && testenv.Builder() == "" {
+		t.Skip("skipping in short mode")
+	}
 	buf := new(bytes.Buffer)
 	w := NewWriter(buf)
 	const nFiles = (1 << 16) + 42
@@ -233,10 +237,24 @@ func TestZip64(t *testing.T) {
 	testZip64DirectoryRecordLength(buf, t)
 }
 
+func TestZip64EdgeCase(t *testing.T) {
+	if testing.Short() {
+		t.Skip("slow test; skipping")
+	}
+	// Test a zip file with uncompressed size 0xFFFFFFFF.
+	// That's the magic marker for a 64-bit file, so even though
+	// it fits in a 32-bit field we must use the 64-bit field.
+	// Go 1.5 and earlier got this wrong,
+	// writing an invalid zip file.
+	const size = 1<<32 - 1 - int64(len("END\n")) // before the "END\n" part
+	buf := testZip64(t, size)
+	testZip64DirectoryRecordLength(buf, t)
+}
+
 func testZip64(t testing.TB, size int64) *rleBuffer {
 	const chunkSize = 1024
 	chunks := int(size / chunkSize)
-	// write 2^32 bytes plus "END\n" to a zip file
+	// write size bytes plus "END\n" to a zip file
 	buf := new(rleBuffer)
 	w := NewWriter(buf)
 	f, err := w.CreateHeader(&FileHeader{
@@ -257,6 +275,12 @@ func testZip64(t testing.TB, size int64) *rleBuffer {
 			t.Fatal("write chunk:", err)
 		}
 	}
+	if frag := int(size % chunkSize); frag > 0 {
+		_, err := f.Write(chunk[:frag])
+		if err != nil {
+			t.Fatal("write chunk:", err)
+		}
+	}
 	end := []byte("END\n")
 	_, err = f.Write(end)
 	if err != nil {
@@ -283,6 +307,12 @@ func testZip64(t testing.TB, size int64) *rleBuffer {
 			t.Fatal("read:", err)
 		}
 	}
+	if frag := int(size % chunkSize); frag > 0 {
+		_, err := io.ReadFull(rc, chunk[:frag])
+		if err != nil {
+			t.Fatal("read:", err)
+		}
+	}
 	gotEnd, err := ioutil.ReadAll(rc)
 	if err != nil {
 		t.Fatal("read end:", err)
@@ -294,14 +324,14 @@ func testZip64(t testing.TB, size int64) *rleBuffer {
 	if err != nil {
 		t.Fatal("closing:", err)
 	}
-	if size == 1<<32 {
+	if size+int64(len("END\n")) >= 1<<32-1 {
 		if got, want := f0.UncompressedSize, uint32(uint32max); got != want {
-			t.Errorf("UncompressedSize %d, want %d", got, want)
+			t.Errorf("UncompressedSize %#x, want %#x", got, want)
 		}
 	}
 
 	if got, want := f0.UncompressedSize64, uint64(size)+uint64(len(end)); got != want {
-		t.Errorf("UncompressedSize64 %d, want %d", got, want)
+		t.Errorf("UncompressedSize64 %#x, want %#x", got, want)
 	}
 
 	return buf
@@ -373,9 +403,14 @@ func testValidHeader(h *FileHeader, t *testing.T) {
 	}
 
 	b := buf.Bytes()
-	if _, err = NewReader(bytes.NewReader(b), int64(len(b))); err != nil {
+	zf, err := NewReader(bytes.NewReader(b), int64(len(b)))
+	if err != nil {
 		t.Fatalf("got %v, expected nil", err)
 	}
+	zh := zf.File[0].FileHeader
+	if zh.Name != h.Name || zh.Method != h.Method || zh.UncompressedSize64 != uint64(len("hi")) {
+		t.Fatalf("got %q/%d/%d expected %q/%d/%d", zh.Name, zh.Method, zh.UncompressedSize64, h.Name, h.Method, len("hi"))
+	}
 }
 
 // Issue 4302.
@@ -388,20 +423,29 @@ func TestHeaderInvalidTagAndSize(t *testing.T) {
 	h := FileHeader{
 		Name:   filename,
 		Method: Deflate,
-		Extra:  []byte(ts.Format(time.RFC3339Nano)), // missing tag and len
+		Extra:  []byte(ts.Format(time.RFC3339Nano)), // missing tag and len, but Extra is best-effort parsing
 	}
 	h.SetModTime(ts)
 
-	testInvalidHeader(&h, t)
+	testValidHeader(&h, t)
 }
 
 func TestHeaderTooShort(t *testing.T) {
 	h := FileHeader{
 		Name:   "foo.txt",
 		Method: Deflate,
-		Extra:  []byte{zip64ExtraId}, // missing size
+		Extra:  []byte{zip64ExtraId}, // missing size and second half of tag, but Extra is best-effort parsing
 	}
-	testInvalidHeader(&h, t)
+	testValidHeader(&h, t)
+}
+
+func TestHeaderIgnoredSize(t *testing.T) {
+	h := FileHeader{
+		Name:   "foo.txt",
+		Method: Deflate,
+		Extra:  []byte{zip64ExtraId & 0xFF, zip64ExtraId >> 8, 24, 0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}, // bad size but shouldn't be consulted
+	}
+	testValidHeader(&h, t)
 }
 
 // Issue 4393. It is valid to have an extra data header
diff --git a/src/bootstrap.bash b/src/bootstrap.bash
index 1b5ba7c..7947e84 100755
--- a/src/bootstrap.bash
+++ b/src/bootstrap.bash
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 # Copyright 2015 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.
diff --git a/src/bufio/bufio.go b/src/bufio/bufio.go
index 3bbb933..6a70f70 100644
--- a/src/bufio/bufio.go
+++ b/src/bufio/bufio.go
@@ -179,7 +179,7 @@ func (b *Reader) Discard(n int) (discarded int, err error) {
 
 // Read reads data into p.
 // It returns the number of bytes read into p.
-// It calls Read at most once on the underlying Reader,
+// The bytes are taken from at most one Read on the underlying Reader,
 // hence n may be less than len(p).
 // At EOF, the count will be zero and err will be io.EOF.
 func (b *Reader) Read(p []byte) (n int, err error) {
diff --git a/src/bufio/example_test.go b/src/bufio/example_test.go
index 3da9141..4666e6d 100644
--- a/src/bufio/example_test.go
+++ b/src/bufio/example_test.go
@@ -80,3 +80,32 @@ func ExampleScanner_custom() {
 	// 5678
 	// Invalid input: strconv.ParseInt: parsing "1234567901234567890": value out of range
 }
+
+// Use a Scanner with a custom split function to parse a comma-separated
+// list with an empty final value.
+func ExampleScanner_emptyFinalToken() {
+	// Comma-separated list; last entry is empty.
+	const input = "1,2,3,4,"
+	scanner := bufio.NewScanner(strings.NewReader(input))
+	// Define a split function that separates on commas.
+	onComma := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
+		for i := 0; i < len(data); i++ {
+			if data[i] == ',' {
+				return i + 1, data[:i], nil
+			}
+		}
+		// There is one final token to be delivered, which may be the empty string.
+		// Returning bufio.ErrFinalToken here tells Scan there are no more tokens after this
+		// but does not trigger an error to be returned from Scan itself.
+		return 0, data, bufio.ErrFinalToken
+	}
+	scanner.Split(onComma)
+	// Scan.
+	for scanner.Scan() {
+		fmt.Printf("%q ", scanner.Text())
+	}
+	if err := scanner.Err(); err != nil {
+		fmt.Fprintln(os.Stderr, "reading input:", err)
+	}
+	// Output: "1" "2" "3" "4" ""
+}
diff --git a/src/bufio/scan.go b/src/bufio/scan.go
index 7a349fa..27a0f00 100644
--- a/src/bufio/scan.go
+++ b/src/bufio/scan.go
@@ -37,6 +37,8 @@ type Scanner struct {
 	end          int       // End of data in buf.
 	err          error     // Sticky error.
 	empties      int       // Count of successive empty tokens.
+	scanCalled   bool      // Scan has been called; buffer is in use.
+	done         bool      // Scan has finished.
 }
 
 // SplitFunc is the signature of the split function used to tokenize the
@@ -65,10 +67,13 @@ var (
 )
 
 const (
-	// MaxScanTokenSize is the maximum size used to buffer a token.
+	// MaxScanTokenSize is the maximum size used to buffer a token
+	// unless the user provides an explicit buffer with Scan.Buffer.
 	// The actual maximum token size may be smaller as the buffer
 	// may need to include, for instance, a newline.
 	MaxScanTokenSize = 64 * 1024
+
+	startBufSize = 4096 // Size of initial allocation for buffer.
 )
 
 // NewScanner returns a new Scanner to read from r.
@@ -78,7 +83,6 @@ func NewScanner(r io.Reader) *Scanner {
 		r:            r,
 		split:        ScanLines,
 		maxTokenSize: MaxScanTokenSize,
-		buf:          make([]byte, 4096), // Plausible starting size; needn't be large.
 	}
 }
 
@@ -103,6 +107,16 @@ func (s *Scanner) Text() string {
 	return string(s.token)
 }
 
+// ErrFinalToken is a special sentinel error value. It is intended to be
+// returned by a Split function to indicate that the token being delivered
+// with the error is the last token and scanning should stop after this one.
+// After ErrFinalToken is received by Scan, scanning stops with no error.
+// The value is useful to stop processing early or when it is necessary to
+// deliver a final empty token. One could achieve the same behavior
+// with a custom error value but providing one here is tidier.
+// See the emptyFinalToken example for a use of this value.
+var ErrFinalToken = errors.New("final token")
+
 // Scan advances the Scanner to the next token, which will then be
 // available through the Bytes or Text method. It returns false when the
 // scan stops, either by reaching the end of the input or an error.
@@ -112,6 +126,10 @@ func (s *Scanner) Text() string {
 // Scan panics if the split function returns 100 empty tokens without
 // advancing the input. This is a common error mode for scanners.
 func (s *Scanner) Scan() bool {
+	if s.done {
+		return false
+	}
+	s.scanCalled = true
 	// Loop until we have a token.
 	for {
 		// See if we can get a token with what we already have.
@@ -120,6 +138,11 @@ func (s *Scanner) Scan() bool {
 		if s.end > s.start || s.err != nil {
 			advance, token, err := s.split(s.buf[s.start:s.end], s.err != nil)
 			if err != nil {
+				if err == ErrFinalToken {
+					s.token = token
+					s.done = true
+					return true
+				}
 				s.setErr(err)
 				return false
 			}
@@ -158,11 +181,16 @@ func (s *Scanner) Scan() bool {
 		}
 		// Is the buffer full? If so, resize.
 		if s.end == len(s.buf) {
-			if len(s.buf) >= s.maxTokenSize {
+			// Guarantee no overflow in the multiplication below.
+			const maxInt = int(^uint(0) >> 1)
+			if len(s.buf) >= s.maxTokenSize || len(s.buf) > maxInt/2 {
 				s.setErr(ErrTooLong)
 				return false
 			}
 			newSize := len(s.buf) * 2
+			if newSize == 0 {
+				newSize = startBufSize
+			}
 			if newSize > s.maxTokenSize {
 				newSize = s.maxTokenSize
 			}
@@ -217,9 +245,31 @@ func (s *Scanner) setErr(err error) {
 	}
 }
 
-// Split sets the split function for the Scanner. If called, it must be
-// called before Scan. The default split function is ScanLines.
+// Buffer sets the initial buffer to use when scanning and the maximum
+// size of buffer that may be allocated during scanning. The maximum
+// token size is the larger of max and cap(buf). If max <= cap(buf),
+// Scan will use this buffer only and do no allocation.
+//
+// By default, Scan uses an internal buffer and sets the
+// maximum token size to MaxScanTokenSize.
+//
+// Buffer panics if it is called after scanning has started.
+func (s *Scanner) Buffer(buf []byte, max int) {
+	if s.scanCalled {
+		panic("Buffer called after Scan")
+	}
+	s.buf = buf[0:cap(buf)]
+	s.maxTokenSize = max
+}
+
+// Split sets the split function for the Scanner.
+// The default split function is ScanLines.
+//
+// Split panics if it is called after scanning has started.
 func (s *Scanner) Split(split SplitFunc) {
+	if s.scanCalled {
+		panic("Split called after Scan")
+	}
 	s.split = split
 }
 
diff --git a/src/bufio/scan_test.go b/src/bufio/scan_test.go
index eea87cb..07b1a56 100644
--- a/src/bufio/scan_test.go
+++ b/src/bufio/scan_test.go
@@ -429,33 +429,37 @@ func commaSplit(data []byte, atEOF bool) (advance int, token []byte, err error)
 			return i + 1, data[:i], nil
 		}
 	}
-	if !atEOF {
-		return 0, nil, nil
-	}
-	return 0, data, nil
+	return 0, data, ErrFinalToken
 }
 
-func TestEmptyTokens(t *testing.T) {
-	s := NewScanner(strings.NewReader("1,2,3,"))
-	values := []string{"1", "2", "3", ""}
+func testEmptyTokens(t *testing.T, text string, values []string) {
+	s := NewScanner(strings.NewReader(text))
 	s.Split(commaSplit)
 	var i int
-	for i = 0; i < len(values); i++ {
-		if !s.Scan() {
-			break
+	for i = 0; s.Scan(); i++ {
+		if i >= len(values) {
+			t.Fatalf("got %d fields, expected %d", i+1, len(values))
 		}
 		if s.Text() != values[i] {
 			t.Errorf("%d: expected %q got %q", i, values[i], s.Text())
 		}
 	}
 	if i != len(values) {
-		t.Errorf("got %d fields, expected %d", i, len(values))
+		t.Fatalf("got %d fields, expected %d", i, len(values))
 	}
 	if err := s.Err(); err != nil {
 		t.Fatal(err)
 	}
 }
 
+func TestEmptyTokens(t *testing.T) {
+	testEmptyTokens(t, "1,2,3,", []string{"1", "2", "3", ""})
+}
+
+func TestWithNoEmptyTokens(t *testing.T) {
+	testEmptyTokens(t, "1,2,3", []string{"1", "2", "3"})
+}
+
 func loopAtEOFSplit(data []byte, atEOF bool) (advance int, token []byte, err error) {
 	if len(data) > 0 {
 		return 1, data[:1], nil
@@ -522,3 +526,19 @@ func TestEmptyLinesOK(t *testing.T) {
 		t.Fatalf("stopped with %d left to process", c)
 	}
 }
+
+// Make sure we can read a huge token if a big enough buffer is provided.
+func TestHugeBuffer(t *testing.T) {
+	text := strings.Repeat("x", 2*MaxScanTokenSize)
+	s := NewScanner(strings.NewReader(text + "\n"))
+	s.Buffer(make([]byte, 100), 3*MaxScanTokenSize)
+	for s.Scan() {
+		token := s.Text()
+		if token != text {
+			t.Errorf("scan got incorrect token of length %d", len(token))
+		}
+	}
+	if s.Err() != nil {
+		t.Fatal("after scan:", s.Err())
+	}
+}
diff --git a/src/buildall.bash b/src/buildall.bash
index ba23d31..f686dd8 100755
--- a/src/buildall.bash
+++ b/src/buildall.bash
@@ -33,7 +33,7 @@ if [ "$pattern" = "" ]; then
 fi
 
 # put linux, nacl first in the target list to get all the architectures up front.
-targets="$((ls runtime | sed -n 's/^rt0_\(.*\)_\(.*\)\.s/\1-\2/p'; echo linux-386-387 linux-arm-arm5) | sort | egrep -v android-arm | egrep "$pattern" | egrep 'linux|nacl')
+targets="$((ls runtime | sed -n 's/^rt0_\(.*\)_\(.*\)\.s/\1-\2/p'; echo linux-386-387 linux-arm-arm5) | sort | sed -e 's|linux-mips64x|linux-mips64 linux-mips64le|' | egrep -v android-arm | egrep "$pattern" | egrep 'linux|nacl')
 $(ls runtime | sed -n 's/^rt0_\(.*\)_\(.*\)\.s/\1-\2/p' | egrep -v 'android-arm|darwin-arm' | egrep "$pattern" | egrep -v 'linux|nacl')"
 
 ./make.bash || exit 1
diff --git a/src/bytes/buffer.go b/src/bytes/buffer.go
index 4db9386..ddaba3b 100644
--- a/src/bytes/buffer.go
+++ b/src/bytes/buffer.go
@@ -36,10 +36,11 @@ const (
 // ErrTooLarge is passed to panic if memory cannot be allocated to store data in a buffer.
 var ErrTooLarge = errors.New("bytes.Buffer: too large")
 
-// Bytes returns a slice of the contents of the unread portion of the buffer;
-// len(b.Bytes()) == b.Len().  If the caller changes the contents of the
-// returned slice, the contents of the buffer will change provided there
-// are no intervening method calls on the Buffer.
+// Bytes returns a slice of length b.Len() holding the unread portion of the buffer.
+// The slice is valid for use only until the next buffer modification (that is,
+// only until the next call to a method like Read, Write, Reset, or Truncate).
+// The slice aliases the buffer content at least until the next buffer modification,
+// so immediate changes to the slice will affect the result of future reads.
 func (b *Buffer) Bytes() []byte { return b.buf[b.off:] }
 
 // String returns the contents of the unread portion of the buffer
@@ -60,7 +61,8 @@ func (b *Buffer) Len() int { return len(b.buf) - b.off }
 // total space allocated for the buffer's data.
 func (b *Buffer) Cap() int { return cap(b.buf) }
 
-// Truncate discards all but the first n unread bytes from the buffer.
+// Truncate discards all but the first n unread bytes from the buffer
+// but continues to use the same allocated storage.
 // It panics if n is negative or greater than the length of the buffer.
 func (b *Buffer) Truncate(n int) {
 	b.lastRead = opInvalid
@@ -74,8 +76,9 @@ func (b *Buffer) Truncate(n int) {
 	b.buf = b.buf[0 : b.off+n]
 }
 
-// Reset resets the buffer so it has no content.
-// b.Reset() is the same as b.Truncate(0).
+// Reset resets the buffer to be empty,
+// but it retains the underlying storage for use by future writes.
+// Reset is the same as Truncate(0).
 func (b *Buffer) Reset() { b.Truncate(0) }
 
 // grow grows the buffer to guarantee space for n more bytes.
diff --git a/src/bytes/bytes_test.go b/src/bytes/bytes_test.go
index 6245e48..8df62fc 100644
--- a/src/bytes/bytes_test.go
+++ b/src/bytes/bytes_test.go
@@ -1255,3 +1255,34 @@ func BenchmarkRepeat(b *testing.B) {
 		Repeat([]byte("-"), 80)
 	}
 }
+
+func benchmarkBytesCompare(b *testing.B, n int) {
+	var x = make([]byte, n)
+	var y = make([]byte, n)
+
+	for i := 0; i < n; i++ {
+		x[i] = 'a'
+	}
+
+	for i := 0; i < n; i++ {
+		y[i] = 'a'
+	}
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		Compare(x, y)
+	}
+}
+
+func BenchmarkBytesCompare1(b *testing.B)    { benchmarkBytesCompare(b, 1) }
+func BenchmarkBytesCompare2(b *testing.B)    { benchmarkBytesCompare(b, 2) }
+func BenchmarkBytesCompare4(b *testing.B)    { benchmarkBytesCompare(b, 4) }
+func BenchmarkBytesCompare8(b *testing.B)    { benchmarkBytesCompare(b, 8) }
+func BenchmarkBytesCompare16(b *testing.B)   { benchmarkBytesCompare(b, 16) }
+func BenchmarkBytesCompare32(b *testing.B)   { benchmarkBytesCompare(b, 32) }
+func BenchmarkBytesCompare64(b *testing.B)   { benchmarkBytesCompare(b, 64) }
+func BenchmarkBytesCompare128(b *testing.B)  { benchmarkBytesCompare(b, 128) }
+func BenchmarkBytesCompare256(b *testing.B)  { benchmarkBytesCompare(b, 256) }
+func BenchmarkBytesCompare512(b *testing.B)  { benchmarkBytesCompare(b, 512) }
+func BenchmarkBytesCompare1024(b *testing.B) { benchmarkBytesCompare(b, 1024) }
+func BenchmarkBytesCompare2048(b *testing.B) { benchmarkBytesCompare(b, 2048) }
diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go
index 01b6def..8b20d12 100644
--- a/src/cmd/api/goapi.go
+++ b/src/cmd/api/goapi.go
@@ -428,10 +428,15 @@ func (w *Walker) Import(name string) (*types.Package, error) {
 	}
 	w.imported[name] = &importing
 
+	root := w.root
+	if strings.HasPrefix(name, "golang.org/x/") {
+		root = filepath.Join(root, "vendor")
+	}
+
 	// Determine package files.
-	dir := filepath.Join(w.root, filepath.FromSlash(name))
+	dir := filepath.Join(root, filepath.FromSlash(name))
 	if fi, err := os.Stat(dir); err != nil || !fi.IsDir() {
-		log.Fatalf("no source in tree for package %q", pkg)
+		log.Fatalf("no source in tree for import %q: %v", name, err)
 	}
 
 	context := w.context
@@ -675,7 +680,14 @@ func (w *Walker) emitObj(obj types.Object) {
 	switch obj := obj.(type) {
 	case *types.Const:
 		w.emitf("const %s %s", obj.Name(), w.typeString(obj.Type()))
-		w.emitf("const %s = %s", obj.Name(), obj.Val())
+		x := obj.Val()
+		short := x.String()
+		exact := x.ExactString()
+		if short == exact {
+			w.emitf("const %s = %s", obj.Name(), short)
+		} else {
+			w.emitf("const %s = %s  // %s", obj.Name(), short, exact)
+		}
 	case *types.Var:
 		w.emitf("var %s %s", obj.Name(), w.typeString(obj.Type()))
 	case *types.TypeName:
diff --git a/src/cmd/api/run.go b/src/cmd/api/run.go
index eaffa0a..2c1ad87 100644
--- a/src/cmd/api/run.go
+++ b/src/cmd/api/run.go
@@ -26,7 +26,7 @@ func main() {
 	}
 
 	out, err := exec.Command("go", "tool", "api",
-		"-c", file("go1", "go1.1", "go1.2", "go1.3", "go1.4", "go1.5"),
+		"-c", file("go1", "go1.1", "go1.2", "go1.3", "go1.4", "go1.5", "go1.6"),
 		"-next", file("next"),
 		"-except", file("except")).CombinedOutput()
 	if err != nil {
diff --git a/src/cmd/api/testdata/src/pkg/p1/golden.txt b/src/cmd/api/testdata/src/pkg/p1/golden.txt
index 3c43a22..0378a56 100644
--- a/src/cmd/api/testdata/src/pkg/p1/golden.txt
+++ b/src/cmd/api/testdata/src/pkg/p1/golden.txt
@@ -10,7 +10,7 @@ pkg p1, const ConstChase2 = 11
 pkg p1, const ConstChase2 ideal-int
 pkg p1, const ConversionConst = 5
 pkg p1, const ConversionConst MyInt
-pkg p1, const FloatConst = 3/2
+pkg p1, const FloatConst = 1.5  // 3/2
 pkg p1, const FloatConst ideal-float
 pkg p1, const StrConst = "foo"
 pkg p1, const StrConst ideal-string
diff --git a/src/cmd/asm/doc.go b/src/cmd/asm/doc.go
new file mode 100644
index 0000000..a9c8bfb
--- /dev/null
+++ b/src/cmd/asm/doc.go
@@ -0,0 +1,48 @@
+// Copyright 2015 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.
+
+/*
+Asm, typically invoked as ``go tool asm'', assembles the source file into an object
+file named for the basename of the argument source file with a .o suffix. The
+object file can then be combined with other objects into a package archive.
+
+Command Line
+
+Usage:
+
+	go tool asm [flags] file
+
+The specified file must be a Go assembly file.
+The same assembler is used for all target operating systems and architectures.
+The GOOS and GOARCH environment variables set the desired target.
+
+Flags:
+
+	-D value
+		predefined symbol with optional simple value -D=identifer=value;
+		can be set multiple times
+	-I value
+		include directory; can be set multiple times
+	-S	print assembly and machine code
+	-debug
+		dump instructions as they are parsed
+	-dynlink
+		support references to Go symbols defined in other shared libraries
+	-o string
+		output file; default foo.o for /a/b/c/foo.s
+	-shared
+		generate code that can be linked into a shared library
+	-trimpath string
+		remove prefix from recorded source file paths
+
+Input language:
+
+The assembler uses mostly the same syntax for all architectures,
+the main variation having to do with addressing modes. Input is
+run through a simplified C preprocessor that implements #include,
+#define, #ifdef/endif, but not #if or ##.
+
+For more information, see https://golang.org/doc/asm.
+*/
+package main
diff --git a/src/cmd/asm/internal/arch/arch.go b/src/cmd/asm/internal/arch/arch.go
index e6901eb..c14a13c 100644
--- a/src/cmd/asm/internal/arch/arch.go
+++ b/src/cmd/asm/internal/arch/arch.go
@@ -8,6 +8,7 @@ import (
 	"cmd/internal/obj"
 	"cmd/internal/obj/arm"
 	"cmd/internal/obj/arm64"
+	"cmd/internal/obj/mips"
 	"cmd/internal/obj/ppc64"
 	"cmd/internal/obj/x86"
 	"fmt"
@@ -65,6 +66,14 @@ func Set(GOARCH string) *Arch {
 		return archArm()
 	case "arm64":
 		return archArm64()
+	case "mips64":
+		a := archMips64()
+		a.LinkArch = &mips.Linkmips64
+		return a
+	case "mips64le":
+		a := archMips64()
+		a.LinkArch = &mips.Linkmips64le
+		return a
 	case "ppc64":
 		a := archPPC64()
 		a.LinkArch = &ppc64.Linkppc64
@@ -78,7 +87,7 @@ func Set(GOARCH string) *Arch {
 }
 
 func jumpX86(word string) bool {
-	return word[0] == 'J' || word == "CALL" || strings.HasPrefix(word, "LOOP")
+	return word[0] == 'J' || word == "CALL" || strings.HasPrefix(word, "LOOP") || word == "XBEGIN"
 }
 
 func archX86(linkArch *obj.LinkArch) *Arch {
@@ -153,11 +162,11 @@ func archX86(linkArch *obj.LinkArch) *Arch {
 	instructions["MOVDQ2Q"] = x86.AMOVQ
 	instructions["MOVNTDQ"] = x86.AMOVNTO
 	instructions["MOVOA"] = x86.AMOVO
-	instructions["MOVOA"] = x86.AMOVO
 	instructions["PF2ID"] = x86.APF2IL
 	instructions["PI2FD"] = x86.API2FL
 	instructions["PSLLDQ"] = x86.APSLLO
 	instructions["PSRLDQ"] = x86.APSRLO
+	instructions["PADDD"] = x86.APADDL
 
 	return &Arch{
 		LinkArch:       linkArch,
@@ -252,7 +261,9 @@ func archArm64() *Arch {
 	register["EQ"] = arm64.COND_EQ
 	register["NE"] = arm64.COND_NE
 	register["HS"] = arm64.COND_HS
+	register["CS"] = arm64.COND_HS
 	register["LO"] = arm64.COND_LO
+	register["CC"] = arm64.COND_LO
 	register["MI"] = arm64.COND_MI
 	register["PL"] = arm64.COND_PL
 	register["VS"] = arm64.COND_VS
@@ -361,3 +372,57 @@ func archPPC64() *Arch {
 		IsJump:         jumpPPC64,
 	}
 }
+
+func archMips64() *Arch {
+	register := make(map[string]int16)
+	// Create maps for easy lookup of instruction names etc.
+	// Note that there is no list of names as there is for x86.
+	for i := mips.REG_R0; i <= mips.REG_R31; i++ {
+		register[obj.Rconv(i)] = int16(i)
+	}
+	for i := mips.REG_F0; i <= mips.REG_F31; i++ {
+		register[obj.Rconv(i)] = int16(i)
+	}
+	for i := mips.REG_M0; i <= mips.REG_M31; i++ {
+		register[obj.Rconv(i)] = int16(i)
+	}
+	for i := mips.REG_FCR0; i <= mips.REG_FCR31; i++ {
+		register[obj.Rconv(i)] = int16(i)
+	}
+	register["HI"] = mips.REG_HI
+	register["LO"] = mips.REG_LO
+	// Pseudo-registers.
+	register["SB"] = RSB
+	register["FP"] = RFP
+	register["PC"] = RPC
+	// Avoid unintentionally clobbering g using R30.
+	delete(register, "R30")
+	register["g"] = mips.REG_R30
+	registerPrefix := map[string]bool{
+		"F":   true,
+		"FCR": true,
+		"M":   true,
+		"R":   true,
+	}
+
+	instructions := make(map[string]int)
+	for i, s := range obj.Anames {
+		instructions[s] = i
+	}
+	for i, s := range mips.Anames {
+		if i >= obj.A_ARCHSPECIFIC {
+			instructions[s] = i + obj.ABaseMIPS64
+		}
+	}
+	// Annoying alias.
+	instructions["JAL"] = mips.AJAL
+
+	return &Arch{
+		LinkArch:       &mips.Linkmips64,
+		Instructions:   instructions,
+		Register:       register,
+		RegisterPrefix: registerPrefix,
+		RegisterNumber: mipsRegisterNumber,
+		IsJump:         jumpMIPS64,
+	}
+}
diff --git a/src/cmd/asm/internal/arch/arm.go b/src/cmd/asm/internal/arch/arm.go
index 8df994e..502a906 100644
--- a/src/cmd/asm/internal/arch/arm.go
+++ b/src/cmd/asm/internal/arch/arm.go
@@ -62,6 +62,7 @@ var armSCOND = map[string]uint8{
 var armJump = map[string]bool{
 	"B":    true,
 	"BL":   true,
+	"BX":   true,
 	"BEQ":  true,
 	"BNE":  true,
 	"BCS":  true,
diff --git a/src/cmd/asm/internal/arch/mips64.go b/src/cmd/asm/internal/arch/mips64.go
new file mode 100644
index 0000000..b5867d9
--- /dev/null
+++ b/src/cmd/asm/internal/arch/mips64.go
@@ -0,0 +1,64 @@
+// Copyright 2015 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 file encapsulates some of the odd characteristics of the
+// 64-bit MIPS (MIPS64) instruction set, to minimize its interaction
+// with the core of the assembler.
+
+package arch
+
+import "cmd/internal/obj/mips"
+
+func jumpMIPS64(word string) bool {
+	switch word {
+	case "BEQ", "BFPF", "BFPT", "BGEZ", "BGEZAL", "BGTZ", "BLEZ", "BLTZ", "BLTZAL", "BNE", "JMP", "JAL", "CALL":
+		return true
+	}
+	return false
+}
+
+// IsMIPS64CMP reports whether the op (as defined by an mips.A* constant) is
+// one of the CMP instructions that require special handling.
+func IsMIPS64CMP(op int) bool {
+	switch op {
+	case mips.ACMPEQF, mips.ACMPEQD, mips.ACMPGEF, mips.ACMPGED,
+		mips.ACMPGTF, mips.ACMPGTD:
+		return true
+	}
+	return false
+}
+
+// IsMIPS64MUL reports whether the op (as defined by an mips.A* constant) is
+// one of the MUL/DIV/REM instructions that require special handling.
+func IsMIPS64MUL(op int) bool {
+	switch op {
+	case mips.AMUL, mips.AMULU, mips.AMULV, mips.AMULVU,
+		mips.ADIV, mips.ADIVU, mips.ADIVV, mips.ADIVVU,
+		mips.AREM, mips.AREMU, mips.AREMV, mips.AREMVU:
+		return true
+	}
+	return false
+}
+
+func mipsRegisterNumber(name string, n int16) (int16, bool) {
+	switch name {
+	case "F":
+		if 0 <= n && n <= 31 {
+			return mips.REG_F0 + n, true
+		}
+	case "FCR":
+		if 0 <= n && n <= 31 {
+			return mips.REG_FCR0 + n, true
+		}
+	case "M":
+		if 0 <= n && n <= 31 {
+			return mips.REG_M0 + n, true
+		}
+	case "R":
+		if 0 <= n && n <= 31 {
+			return mips.REG_R0 + n, true
+		}
+	}
+	return 0, false
+}
diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go
index 3563c1a..9827d70 100644
--- a/src/cmd/asm/internal/asm/asm.go
+++ b/src/cmd/asm/internal/asm/asm.go
@@ -27,15 +27,18 @@ func (p *Parser) append(prog *obj.Prog, cond string, doLabel bool) {
 		case '5':
 			if !arch.ARMConditionCodes(prog, cond) {
 				p.errorf("unrecognized condition code .%q", cond)
+				return
 			}
 
 		case '7':
 			if !arch.ARM64Suffix(prog, cond) {
 				p.errorf("unrecognized suffix .%q", cond)
+				return
 			}
 
 		default:
 			p.errorf("unrecognized suffix .%q", cond)
+			return
 		}
 	}
 	if p.firstProg == nil {
@@ -49,6 +52,7 @@ func (p *Parser) append(prog *obj.Prog, cond string, doLabel bool) {
 		for _, label := range p.pendingLabels {
 			if p.labels[label] != nil {
 				p.errorf("label %q multiply defined", label)
+				return
 			}
 			p.labels[label] = prog
 		}
@@ -59,18 +63,21 @@ func (p *Parser) append(prog *obj.Prog, cond string, doLabel bool) {
 		fmt.Println(p.histLineNum, prog)
 	}
 	if testOut != nil {
-		fmt.Fprintln(testOut, p.histLineNum, prog)
+		fmt.Fprintln(testOut, prog)
 	}
 }
 
-// validateSymbol checks that addr represents a valid name for a pseudo-op.
-func (p *Parser) validateSymbol(pseudo string, addr *obj.Addr, offsetOk bool) {
+// validSymbol checks that addr represents a valid name for a pseudo-op.
+func (p *Parser) validSymbol(pseudo string, addr *obj.Addr, offsetOk bool) bool {
 	if addr.Name != obj.NAME_EXTERN && addr.Name != obj.NAME_STATIC || addr.Scale != 0 || addr.Reg != 0 {
-		p.errorf("%s symbol %q must be a symbol(SB)", pseudo, addr.Sym.Name)
+		p.errorf("%s symbol %q must be a symbol(SB)", pseudo, symbolName(addr))
+		return false
 	}
 	if !offsetOk && addr.Offset != 0 {
-		p.errorf("%s symbol %q must not be offset from SB", pseudo, addr.Sym.Name)
+		p.errorf("%s symbol %q must not be offset from SB", pseudo, symbolName(addr))
+		return false
 	}
+	return true
 }
 
 // evalInteger evaluates an integer constant for a pseudo-op.
@@ -79,11 +86,13 @@ func (p *Parser) evalInteger(pseudo string, operands []lex.Token) int64 {
 	return p.getConstantPseudo(pseudo, &addr)
 }
 
-// validateImmediate checks that addr represents an immediate constant.
-func (p *Parser) validateImmediate(pseudo string, addr *obj.Addr) {
+// validImmediate checks that addr represents an immediate constant.
+func (p *Parser) validImmediate(pseudo string, addr *obj.Addr) bool {
 	if addr.Type != obj.TYPE_CONST || addr.Name != 0 || addr.Reg != 0 || addr.Index != 0 {
 		p.errorf("%s: expected immediate constant; found %s", pseudo, obj.Dconv(&emptyProg, addr))
+		return false
 	}
+	return true
 }
 
 // asmText assembles a TEXT pseudo-op.
@@ -91,6 +100,7 @@ func (p *Parser) validateImmediate(pseudo string, addr *obj.Addr) {
 func (p *Parser) asmText(word string, operands [][]lex.Token) {
 	if len(operands) != 2 && len(operands) != 3 {
 		p.errorf("expect two or three operands for TEXT")
+		return
 	}
 
 	// Labels are function scoped. Patch existing labels and
@@ -101,8 +111,10 @@ func (p *Parser) asmText(word string, operands [][]lex.Token) {
 	// Operand 0 is the symbol name in the form foo(SB).
 	// That means symbol plus indirect on SB and no offset.
 	nameAddr := p.address(operands[0])
-	p.validateSymbol("TEXT", &nameAddr, false)
-	name := nameAddr.Sym.Name
+	if !p.validSymbol("TEXT", &nameAddr, false) {
+		return
+	}
+	name := symbolName(&nameAddr)
 	next := 1
 
 	// Next operand is the optional text flag, a literal integer.
@@ -143,6 +155,7 @@ func (p *Parser) asmText(word string, operands [][]lex.Token) {
 		// There is an argument size. It must be a minus sign followed by a non-negative integer literal.
 		if len(op) != 2 || op[0].ScanToken != '-' || op[1].ScanToken != scanner.Int {
 			p.errorf("TEXT %s: argument size must be of form -integer", name)
+			return
 		}
 		argSize = p.positiveAtoi(op[1].String())
 	}
@@ -171,6 +184,7 @@ func (p *Parser) asmText(word string, operands [][]lex.Token) {
 func (p *Parser) asmData(word string, operands [][]lex.Token) {
 	if len(operands) != 2 {
 		p.errorf("expect two operands for DATA")
+		return
 	}
 
 	// Operand 0 has the general form foo<>+0x04(SB)/4.
@@ -178,12 +192,15 @@ func (p *Parser) asmData(word string, operands [][]lex.Token) {
 	n := len(op)
 	if n < 3 || op[n-2].ScanToken != '/' || op[n-1].ScanToken != scanner.Int {
 		p.errorf("expect /size for DATA argument")
+		return
 	}
 	scale := p.parseScale(op[n-1].String())
 	op = op[:n-2]
 	nameAddr := p.address(op)
-	p.validateSymbol("DATA", &nameAddr, true)
-	name := nameAddr.Sym.Name
+	if !p.validSymbol("DATA", &nameAddr, true) {
+		return
+	}
+	name := symbolName(&nameAddr)
 
 	// Operand 1 is an immediate constant or address.
 	valueAddr := p.address(operands[1])
@@ -192,11 +209,13 @@ func (p *Parser) asmData(word string, operands [][]lex.Token) {
 		// OK
 	default:
 		p.errorf("DATA value must be an immediate constant or address")
+		return
 	}
 
 	// The addresses must not overlap. Easiest test: require monotonicity.
 	if lastAddr, ok := p.dataAddr[name]; ok && nameAddr.Offset < lastAddr {
 		p.errorf("overlapping DATA entry for %s", name)
+		return
 	}
 	p.dataAddr[name] = nameAddr.Offset + int64(scale)
 
@@ -220,11 +239,14 @@ func (p *Parser) asmData(word string, operands [][]lex.Token) {
 func (p *Parser) asmGlobl(word string, operands [][]lex.Token) {
 	if len(operands) != 2 && len(operands) != 3 {
 		p.errorf("expect two or three operands for GLOBL")
+		return
 	}
 
 	// Operand 0 has the general form foo<>+0x04(SB).
 	nameAddr := p.address(operands[0])
-	p.validateSymbol("GLOBL", &nameAddr, false)
+	if !p.validSymbol("GLOBL", &nameAddr, false) {
+		return
+	}
 	next := 1
 
 	// Next operand is the optional flag, a literal integer.
@@ -236,7 +258,9 @@ func (p *Parser) asmGlobl(word string, operands [][]lex.Token) {
 
 	// Final operand is an immediate constant.
 	addr := p.address(operands[next])
-	p.validateImmediate("GLOBL", &addr)
+	if !p.validImmediate("GLOBL", &addr) {
+		return
+	}
 
 	// log.Printf("GLOBL %s %d, $%d", name, flag, size)
 	prog := &obj.Prog{
@@ -257,15 +281,20 @@ func (p *Parser) asmGlobl(word string, operands [][]lex.Token) {
 func (p *Parser) asmPCData(word string, operands [][]lex.Token) {
 	if len(operands) != 2 {
 		p.errorf("expect two operands for PCDATA")
+		return
 	}
 
 	// Operand 0 must be an immediate constant.
 	key := p.address(operands[0])
-	p.validateImmediate("PCDATA", &key)
+	if !p.validImmediate("PCDATA", &key) {
+		return
+	}
 
 	// Operand 1 must be an immediate constant.
 	value := p.address(operands[1])
-	p.validateImmediate("PCDATA", &value)
+	if !p.validImmediate("PCDATA", &value) {
+		return
+	}
 
 	// log.Printf("PCDATA $%d, $%d", key.Offset, value.Offset)
 	prog := &obj.Prog{
@@ -283,15 +312,20 @@ func (p *Parser) asmPCData(word string, operands [][]lex.Token) {
 func (p *Parser) asmFuncData(word string, operands [][]lex.Token) {
 	if len(operands) != 2 {
 		p.errorf("expect two operands for FUNCDATA")
+		return
 	}
 
 	// Operand 0 must be an immediate constant.
 	valueAddr := p.address(operands[0])
-	p.validateImmediate("FUNCDATA", &valueAddr)
+	if !p.validImmediate("FUNCDATA", &valueAddr) {
+		return
+	}
 
 	// Operand 1 is a symbol name in the form foo(SB).
 	nameAddr := p.address(operands[1])
-	p.validateSymbol("FUNCDATA", &nameAddr, true)
+	if !p.validSymbol("FUNCDATA", &nameAddr, true) {
+		return
+	}
 
 	prog := &obj.Prog{
 		Ctxt:   p.ctxt,
@@ -334,10 +368,19 @@ func (p *Parser) asmJump(op int, cond string, a []obj.Addr) {
 			reg, ok := p.arch.RegisterNumber("R", int16(reg))
 			if !ok {
 				p.errorf("bad register number %d", reg)
+				return
 			}
 			prog.Reg = reg
 			break
 		}
+		if p.arch.Thechar == '0' {
+			// 3-operand jumps.
+			// First two must be registers
+			target = &a[2]
+			prog.From = a[0]
+			prog.Reg = p.getRegister(prog, op, &a[1])
+			break
+		}
 		fallthrough
 	default:
 		p.errorf("wrong number of arguments to %s instruction", obj.Aconv(op))
@@ -384,6 +427,7 @@ func (p *Parser) asmJump(op int, cond string, a []obj.Addr) {
 		prog.To = a[0]
 	default:
 		p.errorf("cannot assemble jump %+v", target)
+		return
 	}
 
 	p.append(prog, cond, true)
@@ -394,9 +438,9 @@ func (p *Parser) patch() {
 		targetProg := p.labels[patch.label]
 		if targetProg == nil {
 			p.errorf("undefined label %s", patch.label)
-		} else {
-			p.branch(patch.prog, targetProg)
+			return
 		}
+		p.branch(patch.prog, targetProg)
 	}
 	p.toPatch = p.toPatch[:0]
 }
@@ -462,6 +506,7 @@ func (p *Parser) asmInstruction(op int, cond string, a []obj.Addr) {
 					break
 				}
 				p.errorf("unrecognized addressing for %s", obj.Aconv(op))
+				return
 			}
 			if arch.IsARMFloatCmp(op) {
 				prog.From = a[0]
@@ -472,11 +517,21 @@ func (p *Parser) asmInstruction(op int, cond string, a []obj.Addr) {
 			prog.From = a[0]
 			prog.Reg = p.getRegister(prog, op, &a[1])
 			break
+		} else if p.arch.Thechar == '0' {
+			if arch.IsMIPS64CMP(op) || arch.IsMIPS64MUL(op) {
+				prog.From = a[0]
+				prog.Reg = p.getRegister(prog, op, &a[1])
+				break
+			}
 		}
 		prog.From = a[0]
 		prog.To = a[1]
 	case 3:
 		switch p.arch.Thechar {
+		case '0':
+			prog.From = a[0]
+			prog.Reg = p.getRegister(prog, op, &a[1])
+			prog.To = a[2]
 		case '5':
 			// Special cases.
 			if arch.IsARMSTREX(op) {
@@ -500,6 +555,7 @@ func (p *Parser) asmInstruction(op int, cond string, a []obj.Addr) {
 				prog.To = a[1]
 				if a[2].Type != obj.TYPE_REG {
 					p.errorf("invalid addressing modes for third operand to %s instruction, must be register", obj.Aconv(op))
+					return
 				}
 				prog.RegTo2 = a[2].Reg
 				break
@@ -535,9 +591,11 @@ func (p *Parser) asmInstruction(op int, cond string, a []obj.Addr) {
 				prog.To = a[2]
 			default:
 				p.errorf("invalid addressing modes for %s instruction", obj.Aconv(op))
+				return
 			}
 		default:
 			p.errorf("TODO: implement three-operand instructions for this architecture")
+			return
 		}
 	case 4:
 		if p.arch.Thechar == '5' && arch.IsARMMULA(op) {
@@ -571,6 +629,7 @@ func (p *Parser) asmInstruction(op int, cond string, a []obj.Addr) {
 			break
 		}
 		p.errorf("can't handle %s instruction with 4 operands", obj.Aconv(op))
+		return
 	case 5:
 		if p.arch.Thechar == '9' && arch.IsPPC64RLD(op) {
 			// Always reg, reg, con, con, reg.  (con, con is a 'mask').
@@ -592,6 +651,7 @@ func (p *Parser) asmInstruction(op int, cond string, a []obj.Addr) {
 			break
 		}
 		p.errorf("can't handle %s instruction with 5 operands", obj.Aconv(op))
+		return
 	case 6:
 		if p.arch.Thechar == '5' && arch.IsARMMRC(op) {
 			// Strange special case: MCR, MRC.
@@ -615,6 +675,7 @@ func (p *Parser) asmInstruction(op int, cond string, a []obj.Addr) {
 		fallthrough
 	default:
 		p.errorf("can't handle %s instruction with %d operands", obj.Aconv(op), len(a))
+		return
 	}
 
 	p.append(prog, cond, true)
@@ -627,6 +688,14 @@ func newAddr(x obj.Addr) *obj.Addr {
 	return p
 }
 
+// symbolName returns the symbol name, or an error string if none if available.
+func symbolName(addr *obj.Addr) string {
+	if addr.Sym != nil {
+		return addr.Sym.Name
+	}
+	return "<erroneous symbol>"
+}
+
 var emptyProg obj.Prog
 
 // getConstantPseudo checks that addr represents a plain constant and returns its value.
diff --git a/src/cmd/asm/internal/asm/endtoend_test.go b/src/cmd/asm/internal/asm/endtoend_test.go
index abe4e4e..4bc7e2f 100644
--- a/src/cmd/asm/internal/asm/endtoend_test.go
+++ b/src/cmd/asm/internal/asm/endtoend_test.go
@@ -8,9 +8,11 @@ import (
 	"bytes"
 	"fmt"
 	"io/ioutil"
-	"log"
 	"os"
 	"path/filepath"
+	"regexp"
+	"sort"
+	"strconv"
 	"strings"
 	"testing"
 
@@ -22,70 +24,368 @@ import (
 // Output is generated by, in effect, turning on -S and comparing the
 // result against a golden file.
 
-func testEndToEnd(t *testing.T, goarch string) {
+func testEndToEnd(t *testing.T, goarch, file string) {
 	lex.InitHist()
-	input := filepath.Join("testdata", goarch+".s")
-	output := filepath.Join("testdata", goarch+".out")
+	input := filepath.Join("testdata", file+".s")
 	architecture, ctxt := setArch(goarch)
 	lexer := lex.NewLexer(input, ctxt)
 	parser := NewParser(ctxt, architecture, lexer)
 	pList := obj.Linknewplist(ctxt)
 	var ok bool
-	testOut = new(bytes.Buffer) // The assembler writes -S output to this buffer.
+	testOut = new(bytes.Buffer) // The assembler writes test output to this buffer.
 	ctxt.Bso = obj.Binitw(os.Stdout)
 	defer ctxt.Bso.Flush()
-	ctxt.Diag = log.Fatalf
-	obj.Binitw(ioutil.Discard)
+	failed := false
+	ctxt.DiagFunc = func(format string, args ...interface{}) {
+		failed = true
+		t.Errorf(format, args...)
+	}
 	pList.Firstpc, ok = parser.Parse()
-	if !ok {
-		t.Fatalf("asm: %s assembly failed", goarch)
+	if !ok || failed {
+		t.Errorf("asm: %s assembly failed", goarch)
+		return
 	}
-	result := string(testOut.Bytes())
-	expect, err := ioutil.ReadFile(output)
-	// For Windows.
-	result = strings.Replace(result, `testdata\`, `testdata/`, -1)
+	output := strings.Split(testOut.String(), "\n")
+
+	// Reconstruct expected output by independently "parsing" the input.
+	data, err := ioutil.ReadFile(input)
 	if err != nil {
-		t.Fatal(err)
-	}
-	if result != string(expect) {
-		if false { // Enable to capture output.
-			fmt.Printf("%s", result)
-			os.Exit(1)
-		}
-		t.Errorf("%s failed: output differs", goarch)
-		r := strings.Split(result, "\n")
-		e := strings.Split(string(expect), "\n")
-		if len(r) != len(e) {
-			t.Errorf("%s: expected %d lines, got %d", goarch, len(e), len(r))
-		}
-		n := len(e)
-		if n > len(r) {
-			n = len(r)
-		}
-		for i := 0; i < n; i++ {
-			if r[i] != e[i] {
-				t.Errorf("%s:%d:\nexpected\n\t%s\ngot\n\t%s", output, i, e[i], r[i])
+		t.Error(err)
+		return
+	}
+	lineno := 0
+	seq := 0
+	hexByLine := map[string]string{}
+	lines := strings.SplitAfter(string(data), "\n")
+Diff:
+	for _, line := range lines {
+		lineno++
+
+		// The general form of a test input line is:
+		//	// comment
+		//	INST args [// printed form] [// hex encoding]
+		parts := strings.Split(line, "//")
+		printed := strings.TrimSpace(parts[0])
+		if printed == "" || strings.HasSuffix(printed, ":") { // empty or label
+			continue
+		}
+		seq++
+
+		var hexes string
+		switch len(parts) {
+		default:
+			t.Errorf("%s:%d: unable to understand comments: %s", input, lineno, line)
+		case 1:
+			// no comment
+		case 2:
+			// might be printed form or hex
+			note := strings.TrimSpace(parts[1])
+			if isHexes(note) {
+				hexes = note
+			} else {
+				printed = note
+			}
+		case 3:
+			// printed form, then hex
+			printed = strings.TrimSpace(parts[1])
+			hexes = strings.TrimSpace(parts[2])
+			if !isHexes(hexes) {
+				t.Errorf("%s:%d: malformed hex instruction encoding: %s", input, lineno, line)
+			}
+		}
+
+		if hexes != "" {
+			hexByLine[fmt.Sprintf("%s:%d", input, lineno)] = hexes
+		}
+
+		// Canonicalize spacing in printed form.
+		// First field is opcode, then tab, then arguments separated by spaces.
+		// Canonicalize spaces after commas first.
+		// Comma to separate argument gets a space; comma within does not.
+		var buf []byte
+		nest := 0
+		for i := 0; i < len(printed); i++ {
+			c := printed[i]
+			switch c {
+			case '{', '[':
+				nest++
+			case '}', ']':
+				nest--
+			case ',':
+				buf = append(buf, ',')
+				if nest == 0 {
+					buf = append(buf, ' ')
+				}
+				for i+1 < len(printed) && (printed[i+1] == ' ' || printed[i+1] == '\t') {
+					i++
+				}
+				continue
+			}
+			buf = append(buf, c)
+		}
+
+		f := strings.Fields(string(buf))
+
+		// Turn relative (PC) into absolute (PC) automatically,
+		// so that most branch instructions don't need comments
+		// giving the absolute form.
+		if len(f) > 0 && strings.HasSuffix(printed, "(PC)") {
+			last := f[len(f)-1]
+			n, err := strconv.Atoi(last[:len(last)-len("(PC)")])
+			if err == nil {
+				f[len(f)-1] = fmt.Sprintf("%d(PC)", seq+n)
+			}
+		}
+
+		if len(f) == 1 {
+			printed = f[0]
+		} else {
+			printed = f[0] + "\t" + strings.Join(f[1:], " ")
+		}
+
+		want := fmt.Sprintf("%05d (%s:%d)\t%s", seq, input, lineno, printed)
+		for len(output) > 0 && (output[0] < want || output[0] != want && len(output[0]) >= 5 && output[0][:5] == want[:5]) {
+			if len(output[0]) >= 5 && output[0][:5] == want[:5] {
+				t.Errorf("mismatched output:\nhave %s\nwant %s", output[0], want)
+				output = output[1:]
+				continue Diff
+			}
+			t.Errorf("unexpected output: %q", output[0])
+			output = output[1:]
+		}
+		if len(output) > 0 && output[0] == want {
+			output = output[1:]
+		} else {
+			t.Errorf("missing output: %q", want)
+		}
+	}
+	for len(output) > 0 {
+		if output[0] == "" {
+			// spurious blank caused by Split on "\n"
+			output = output[1:]
+			continue
+		}
+		t.Errorf("unexpected output: %q", output[0])
+		output = output[1:]
+	}
+
+	// Checked printing.
+	// Now check machine code layout.
+
+	top := pList.Firstpc
+	var text *obj.LSym
+	ok = true
+	ctxt.DiagFunc = func(format string, args ...interface{}) {
+		t.Errorf(format, args...)
+		ok = false
+	}
+	obj.Flushplist(ctxt)
+
+	for p := top; p != nil; p = p.Link {
+		if p.As == obj.ATEXT {
+			text = p.From.Sym
+		}
+		hexes := hexByLine[p.Line()]
+		if hexes == "" {
+			continue
+		}
+		delete(hexByLine, p.Line())
+		if text == nil {
+			t.Errorf("%s: instruction outside TEXT", p)
+		}
+		size := int64(len(text.P)) - p.Pc
+		if p.Link != nil {
+			size = p.Link.Pc - p.Pc
+		} else if p.Isize != 0 {
+			size = int64(p.Isize)
+		}
+		var code []byte
+		if p.Pc < int64(len(text.P)) {
+			code = text.P[p.Pc:]
+			if size < int64(len(code)) {
+				code = code[:size]
+			}
+		}
+		codeHex := fmt.Sprintf("%x", code)
+		if codeHex == "" {
+			codeHex = "empty"
+		}
+		ok := false
+		for _, hex := range strings.Split(hexes, " or ") {
+			if codeHex == hex {
+				ok = true
+				break
 			}
 		}
+		if !ok {
+			t.Errorf("%s: have encoding %s, want %s", p, codeHex, hexes)
+		}
+	}
+
+	if len(hexByLine) > 0 {
+		var missing []string
+		for key := range hexByLine {
+			missing = append(missing, key)
+		}
+		sort.Strings(missing)
+		for _, line := range missing {
+			t.Errorf("%s: did not find instruction encoding", line)
+		}
 	}
+
 }
 
-func TestPPC64EndToEnd(t *testing.T) {
-	testEndToEnd(t, "ppc64")
+func isHexes(s string) bool {
+	if s == "" {
+		return false
+	}
+	if s == "empty" {
+		return true
+	}
+	for _, f := range strings.Split(s, " or ") {
+		if f == "" || len(f)%2 != 0 || strings.TrimLeft(f, "0123456789abcdef") != "" {
+			return false
+		}
+	}
+	return true
+}
+
+// It would be nice if the error messages began with
+// the standard file:line: prefix,
+// but that's not where we are today.
+// It might be at the beginning but it might be in the middle of the printed instruction.
+var fileLineRE = regexp.MustCompile(`(?:^|\()(testdata[/\\][0-9a-z]+\.s:[0-9]+)(?:$|\))`)
+
+// Same as in test/run.go
+var (
+	errRE       = regexp.MustCompile(`// ERROR ?(.*)`)
+	errQuotesRE = regexp.MustCompile(`"([^"]*)"`)
+)
+
+func testErrors(t *testing.T, goarch, file string) {
+	lex.InitHist()
+	input := filepath.Join("testdata", file+".s")
+	architecture, ctxt := setArch(goarch)
+	lexer := lex.NewLexer(input, ctxt)
+	parser := NewParser(ctxt, architecture, lexer)
+	pList := obj.Linknewplist(ctxt)
+	var ok bool
+	testOut = new(bytes.Buffer) // The assembler writes test output to this buffer.
+	ctxt.Bso = obj.Binitw(os.Stdout)
+	defer ctxt.Bso.Flush()
+	failed := false
+	var errBuf bytes.Buffer
+	ctxt.DiagFunc = func(format string, args ...interface{}) {
+		failed = true
+		s := fmt.Sprintf(format, args...)
+		if !strings.HasSuffix(s, "\n") {
+			s += "\n"
+		}
+		errBuf.WriteString(s)
+	}
+	pList.Firstpc, ok = parser.Parse()
+	obj.Flushplist(ctxt)
+	if ok && !failed {
+		t.Errorf("asm: %s had no errors", goarch)
+	}
+
+	errors := map[string]string{}
+	for _, line := range strings.Split(errBuf.String(), "\n") {
+		if line == "" || strings.HasPrefix(line, "\t") {
+			continue
+		}
+		m := fileLineRE.FindStringSubmatch(line)
+		if m == nil {
+			t.Errorf("unexpected error: %v", line)
+			continue
+		}
+		fileline := m[1]
+		if errors[fileline] != "" {
+			t.Errorf("multiple errors on %s:\n\t%s\n\t%s", fileline, errors[fileline], line)
+			continue
+		}
+		errors[fileline] = line
+	}
+
+	// Reconstruct expected errors by independently "parsing" the input.
+	data, err := ioutil.ReadFile(input)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	lineno := 0
+	lines := strings.Split(string(data), "\n")
+	for _, line := range lines {
+		lineno++
+
+		fileline := fmt.Sprintf("%s:%d", input, lineno)
+		if m := errRE.FindStringSubmatch(line); m != nil {
+			all := m[1]
+			mm := errQuotesRE.FindAllStringSubmatch(all, -1)
+			if len(mm) != 1 {
+				t.Errorf("%s: invalid errorcheck line:\n%s", fileline, line)
+			} else if err := errors[fileline]; err == "" {
+				t.Errorf("%s: missing error, want %s", fileline, all)
+			} else if !strings.Contains(err, mm[0][1]) {
+				t.Errorf("%s: wrong error for %s:\n%s", fileline, all, err)
+			}
+		} else {
+			if errors[fileline] != "" {
+				t.Errorf("unexpected error on %s: %v", fileline, errors[fileline])
+			}
+		}
+		delete(errors, fileline)
+	}
+	var extra []string
+	for key := range errors {
+		extra = append(extra, key)
+	}
+	sort.Strings(extra)
+	for _, fileline := range extra {
+		t.Errorf("unexpected error on %s: %v", fileline, errors[fileline])
+	}
+}
+
+func Test386EndToEnd(t *testing.T) {
+	defer os.Setenv("GO386", os.Getenv("GO386"))
+
+	for _, go386 := range []string{"387", "sse"} {
+		os.Setenv("GO386", go386)
+		t.Logf("GO386=%v", os.Getenv("GO386"))
+		testEndToEnd(t, "386", "386")
+	}
 }
 
 func TestARMEndToEnd(t *testing.T) {
-	testEndToEnd(t, "arm")
+	defer os.Setenv("GOARM", os.Getenv("GOARM"))
+
+	for _, goarm := range []string{"5", "6", "7"} {
+		os.Setenv("GOARM", goarm)
+		t.Logf("GOARM=%v", os.Getenv("GOARM"))
+		testEndToEnd(t, "arm", "arm")
+	}
 }
 
 func TestARM64EndToEnd(t *testing.T) {
-	testEndToEnd(t, "arm64")
+	testEndToEnd(t, "arm64", "arm64")
 }
 
 func TestAMD64EndToEnd(t *testing.T) {
-	testEndToEnd(t, "amd64")
+	testEndToEnd(t, "amd64", "amd64")
 }
 
-func Test386EndToEnd(t *testing.T) {
-	testEndToEnd(t, "386")
+func TestAMD64Encoder(t *testing.T) {
+	testEndToEnd(t, "amd64", "amd64enc")
+}
+
+func TestAMD64Errors(t *testing.T) {
+	testErrors(t, "amd64", "amd64error")
+}
+
+func TestMIPS64EndToEnd(t *testing.T) {
+	testEndToEnd(t, "mips64", "mips64")
+}
+
+func TestPPC64EndToEnd(t *testing.T) {
+	testEndToEnd(t, "ppc64", "ppc64")
 }
diff --git a/src/cmd/asm/internal/asm/operand_test.go b/src/cmd/asm/internal/asm/operand_test.go
index 01335ed..ecf52c5 100644
--- a/src/cmd/asm/internal/asm/operand_test.go
+++ b/src/cmd/asm/internal/asm/operand_test.go
@@ -65,6 +65,11 @@ func TestPPC64OperandParser(t *testing.T) {
 	testOperandParser(t, parser, ppc64OperandTests)
 }
 
+func TestMIPS64OperandParser(t *testing.T) {
+	parser := newParser("mips64")
+	testOperandParser(t, parser, mips64OperandTests)
+}
+
 type operandTest struct {
 	input, output string
 }
@@ -183,6 +188,7 @@ var amd64OperandTests = []operandTest{
 	{"y+56(FP)", "y+56(FP)"},
 	{"·AddUint32(SB)", "\"\".AddUint32(SB)"},
 	{"·callReflect(SB)", "\"\".callReflect(SB)"},
+	{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
 }
 
 var x86OperandTests = []operandTest{
@@ -240,6 +246,7 @@ var x86OperandTests = []operandTest{
 	{"x+4(FP)", "x+4(FP)"},
 	{"·AddUint32(SB)", "\"\".AddUint32(SB)"},
 	{"·reflectcall(SB)", "\"\".reflectcall(SB)"},
+	{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
 }
 
 var armOperandTests = []operandTest{
@@ -288,7 +295,10 @@ var armOperandTests = []operandTest{
 	{"runtime·_sfloat2(SB)", "runtime._sfloat2(SB)"},
 	{"·AddUint32(SB)", "\"\".AddUint32(SB)"},
 	{"(R1, R3)", "(R1, R3)"},
-	{"[R0,R1,g,R15", ""}, // Issue 11764 - previously asm just hung parsing ']' missing register lists
+	{"[R0,R1,g,R15", ""}, // Issue 11764 - asm hung parsing ']' missing register lists.
+	{"[):[o-FP", ""},     // Issue 12469 - there was no infinite loop for ARM; these are just sanity checks.
+	{"[):[R0-FP", ""},
+	{"(", ""}, // Issue 12466 - backed up before beginning of line.
 }
 
 var ppc64OperandTests = []operandTest{
@@ -378,6 +388,7 @@ var ppc64OperandTests = []operandTest{
 	{"runtime·abort(SB)", "runtime.abort(SB)"},
 	{"·AddUint32(SB)", "\"\".AddUint32(SB)"},
 	{"·trunc(SB)", "\"\".trunc(SB)"},
+	{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
 }
 
 var arm64OperandTests = []operandTest{
@@ -427,4 +438,88 @@ var arm64OperandTests = []operandTest{
 	{"ZR", "ZR"},
 	{"(ZR)", "(ZR)"},
 	{"(R29, RSP)", "(R29, RSP)"},
+	{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
+}
+
+var mips64OperandTests = []operandTest{
+	{"$((1<<63)-1)", "$9223372036854775807"},
+	{"$(-64*1024)", "$-65536"},
+	{"$(1024 * 8)", "$8192"},
+	{"$-1", "$-1"},
+	{"$-24(R4)", "$-24(R4)"},
+	{"$0", "$0"},
+	{"$0(R1)", "$(R1)"},
+	{"$0.5", "$(0.5)"},
+	{"$0x7000", "$28672"},
+	{"$0x88888eef", "$2290650863"},
+	{"$1", "$1"},
+	{"$_main<>(SB)", "$_main<>(SB)"},
+	{"$argframe(FP)", "$argframe(FP)"},
+	{"$~3", "$-4"},
+	{"(-288-3*8)(R1)", "-312(R1)"},
+	{"(16)(R7)", "16(R7)"},
+	{"(8)(g)", "8(g)"},
+	{"(R0)", "(R0)"},
+	{"(R3)", "(R3)"},
+	{"(R4)", "(R4)"},
+	{"(R5)", "(R5)"},
+	{"-1(R4)", "-1(R4)"},
+	{"-1(R5)", "-1(R5)"},
+	{"6(PC)", "6(PC)"},
+	{"F14", "F14"},
+	{"F15", "F15"},
+	{"F16", "F16"},
+	{"F17", "F17"},
+	{"F18", "F18"},
+	{"F19", "F19"},
+	{"F20", "F20"},
+	{"F21", "F21"},
+	{"F22", "F22"},
+	{"F23", "F23"},
+	{"F24", "F24"},
+	{"F25", "F25"},
+	{"F26", "F26"},
+	{"F27", "F27"},
+	{"F28", "F28"},
+	{"F29", "F29"},
+	{"F30", "F30"},
+	{"F31", "F31"},
+	{"R0", "R0"},
+	{"R1", "R1"},
+	{"R11", "R11"},
+	{"R12", "R12"},
+	{"R13", "R13"},
+	{"R14", "R14"},
+	{"R15", "R15"},
+	{"R16", "R16"},
+	{"R17", "R17"},
+	{"R18", "R18"},
+	{"R19", "R19"},
+	{"R2", "R2"},
+	{"R20", "R20"},
+	{"R21", "R21"},
+	{"R22", "R22"},
+	{"R23", "R23"},
+	{"R24", "R24"},
+	{"R25", "R25"},
+	{"R26", "R26"},
+	{"R27", "R27"},
+	{"R28", "R28"},
+	{"R29", "R29"},
+	{"R3", "R3"},
+	{"R31", "R31"},
+	{"R4", "R4"},
+	{"R5", "R5"},
+	{"R6", "R6"},
+	{"R7", "R7"},
+	{"R8", "R8"},
+	{"R9", "R9"},
+	{"LO", "LO"},
+	{"a(FP)", "a(FP)"},
+	{"g", "g"},
+	{"ret+8(FP)", "ret+8(FP)"},
+	{"runtime·abort(SB)", "runtime.abort(SB)"},
+	{"·AddUint32(SB)", "\"\".AddUint32(SB)"},
+	{"·trunc(SB)", "\"\".trunc(SB)"},
+	{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
 }
diff --git a/src/cmd/asm/internal/asm/parse.go b/src/cmd/asm/internal/asm/parse.go
index 6cf50df..4258c5c 100644
--- a/src/cmd/asm/internal/asm/parse.go
+++ b/src/cmd/asm/internal/asm/parse.go
@@ -8,6 +8,7 @@ package asm
 
 import (
 	"fmt"
+	"io"
 	"log"
 	"os"
 	"strconv"
@@ -15,6 +16,7 @@ import (
 	"unicode/utf8"
 
 	"cmd/asm/internal/arch"
+	"cmd/asm/internal/flags"
 	"cmd/asm/internal/lex"
 	"cmd/internal/obj"
 )
@@ -37,6 +39,8 @@ type Parser struct {
 	firstProg     *obj.Prog
 	lastProg      *obj.Prog
 	dataAddr      map[string]int64 // Most recent address for DATA for this symbol.
+	isJump        bool             // Instruction being assembled is a jump.
+	errorWriter   io.Writer
 }
 
 type Patch struct {
@@ -46,11 +50,12 @@ type Patch struct {
 
 func NewParser(ctxt *obj.Link, ar *arch.Arch, lexer lex.TokenReader) *Parser {
 	return &Parser{
-		ctxt:     ctxt,
-		arch:     ar,
-		lex:      lexer,
-		labels:   make(map[string]*obj.Prog),
-		dataAddr: make(map[string]int64),
+		ctxt:        ctxt,
+		arch:        ar,
+		lex:         lexer,
+		labels:      make(map[string]*obj.Prog),
+		dataAddr:    make(map[string]int64),
+		errorWriter: os.Stderr,
 	}
 }
 
@@ -67,12 +72,14 @@ func (p *Parser) errorf(format string, args ...interface{}) {
 		return
 	}
 	p.errorLine = p.histLineNum
-	// Put file and line information on head of message.
-	format = "%s:%d: " + format + "\n"
-	args = append([]interface{}{p.lex.File(), p.lineNum}, args...)
-	fmt.Fprintf(os.Stderr, format, args...)
+	if p.lex != nil {
+		// Put file and line information on head of message.
+		format = "%s:%d: " + format + "\n"
+		args = append([]interface{}{p.lex.File(), p.lineNum}, args...)
+	}
+	fmt.Fprintf(p.errorWriter, format, args...)
 	p.errorCount++
-	if p.errorCount > 10 {
+	if p.errorCount > 10 && !*flags.AllErrors {
 		log.Fatal("too many errors")
 	}
 }
@@ -150,6 +157,7 @@ func (p *Parser) line() bool {
 					// Remember this location so we can swap the operands below.
 					if colon >= 0 {
 						p.errorf("invalid ':' in operand")
+						return true
 					}
 					colon = len(operands)
 				}
@@ -191,15 +199,15 @@ func (p *Parser) line() bool {
 
 func (p *Parser) instruction(op int, word, cond string, operands [][]lex.Token) {
 	p.addr = p.addr[0:0]
-	isJump := p.arch.IsJump(word)
+	p.isJump = p.arch.IsJump(word)
 	for _, op := range operands {
 		addr := p.address(op)
-		if !isJump && addr.Reg < 0 { // Jumps refer to PC, a pseudo.
+		if !p.isJump && addr.Reg < 0 { // Jumps refer to PC, a pseudo.
 			p.errorf("illegal use of pseudo-register in %s", word)
 		}
 		p.addr = append(p.addr, addr)
 	}
-	if isJump {
+	if p.isJump {
 		p.asmJump(op, cond, p.addr)
 		return
 	}
@@ -333,8 +341,13 @@ func (p *Parser) operand(a *obj.Addr) bool {
 	case scanner.Int, scanner.Float, scanner.String, scanner.Char, '+', '-', '~':
 		haveConstant = true
 	case '(':
-		// Could be parenthesized expression or (R).
-		rname := p.next().String()
+		// Could be parenthesized expression or (R). Must be something, though.
+		tok := p.next()
+		if tok.ScanToken == scanner.EOF {
+			p.errorf("missing right parenthesis")
+			return false
+		}
+		rname := tok.String()
 		p.back()
 		haveConstant = !p.atStartOfRegister(rname)
 		if !haveConstant {
@@ -356,6 +369,7 @@ func (p *Parser) operand(a *obj.Addr) bool {
 		if p.have(scanner.String) {
 			if prefix != '$' {
 				p.errorf("string constant must be an immediate")
+				return false
 			}
 			str, err := strconv.Unquote(p.get(scanner.String).String())
 			if err != nil {
@@ -563,12 +577,14 @@ func (p *Parser) symbolReference(a *obj.Addr, name string, prefix rune) {
 	}
 	a.Sym = obj.Linklookup(p.ctxt, name, isStatic)
 	if p.peek() == scanner.EOF {
-		if prefix != 0 {
-			p.errorf("illegal addressing mode for symbol %s", name)
+		if prefix == 0 && p.isJump {
+			// Symbols without prefix or suffix are jump labels.
+			return
 		}
+		p.errorf("illegal or missing addressing mode for symbol %s", name)
 		return
 	}
-	// Expect (SB) or (FP), (PC), (SB), or (SP)
+	// Expect (SB), (FP), (PC), or (SP)
 	p.get('(')
 	reg := p.get(scanner.Ident).String()
 	p.get(')')
@@ -697,6 +713,7 @@ func (p *Parser) registerIndirect(a *obj.Addr, prefix rune) {
 // The opening bracket has been consumed.
 func (p *Parser) registerList(a *obj.Addr) {
 	// One range per loop.
+	const maxReg = 16
 	var bits uint16
 ListLoop:
 	for {
@@ -708,6 +725,7 @@ ListLoop:
 			p.errorf("missing ']' in register list")
 			return
 		}
+		// Parse the upper and lower bounds.
 		lo := p.registerNumber(tok.String())
 		hi := lo
 		if p.peek() == '-' {
@@ -717,7 +735,8 @@ ListLoop:
 		if hi < lo {
 			lo, hi = hi, lo
 		}
-		for lo <= hi {
+		// Check there are no duplicates in the register list.
+		for i := 0; lo <= hi && i < maxReg; i++ {
 			if bits&(1<<lo) != 0 {
 				p.errorf("register R%d already in list", lo)
 			}
@@ -739,12 +758,19 @@ func (p *Parser) registerNumber(name string) uint16 {
 	}
 	if name[0] != 'R' {
 		p.errorf("expected g or R0 through R15; found %s", name)
+		return 0
 	}
 	r, ok := p.registerReference(name)
 	if !ok {
 		return 0
 	}
-	return uint16(r - p.arch.Register["R0"])
+	reg := r - p.arch.Register["R0"]
+	if reg < 0 {
+		// Could happen for an architecture having other registers prefixed by R
+		p.errorf("expected g or R0 through R15; found %s", name)
+		return 0
+	}
+	return uint16(reg)
 }
 
 // Note: There are two changes in the expression handling here
@@ -937,7 +963,11 @@ func (p *Parser) next() lex.Token {
 }
 
 func (p *Parser) back() {
-	p.inputPos--
+	if p.inputPos == 0 {
+		p.errorf("internal error: backing up before BOL")
+	} else {
+		p.inputPos--
+	}
 }
 
 func (p *Parser) peek() lex.ScanToken {
diff --git a/src/cmd/asm/internal/asm/pseudo_test.go b/src/cmd/asm/internal/asm/pseudo_test.go
new file mode 100644
index 0000000..ee13b72
--- /dev/null
+++ b/src/cmd/asm/internal/asm/pseudo_test.go
@@ -0,0 +1,73 @@
+// Copyright 2015 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 asm
+
+import (
+	"bytes"
+	"strings"
+	"testing"
+
+	"cmd/asm/internal/arch"
+	"cmd/asm/internal/lex"
+)
+
+func tokenize(s string) [][]lex.Token {
+	res := [][]lex.Token{}
+	if len(s) == 0 {
+		return res
+	}
+	for _, o := range strings.Split(s, ",") {
+		res = append(res, lex.Tokenize(o))
+	}
+	return res
+}
+
+func TestErroneous(t *testing.T) {
+
+	tests := []struct {
+		pseudo   string
+		operands string
+		expected string
+	}{
+		{"TEXT", "", "expect two or three operands for TEXT"},
+		{"TEXT", "%", "expect two or three operands for TEXT"},
+		{"TEXT", "1, 1", "TEXT symbol \"<erroneous symbol>\" must be a symbol(SB)"},
+		{"TEXT", "$\"foo\", 0, $1", "TEXT symbol \"<erroneous symbol>\" must be a symbol(SB)"},
+		{"TEXT", "$0É:0, 0, $1", "expected EOF, found É"},   // Issue #12467.
+		{"TEXT", "$:0:(SB, 0, $1", "expected '(', found 0"}, // Issue 12468.
+		{"FUNCDATA", "", "expect two operands for FUNCDATA"},
+		{"FUNCDATA", "(SB ", "expect two operands for FUNCDATA"},
+		{"DATA", "", "expect two operands for DATA"},
+		{"DATA", "0", "expect two operands for DATA"},
+		{"DATA", "(0), 1", "expect /size for DATA argument"},
+		{"GLOBL", "", "expect two or three operands for GLOBL"},
+		{"GLOBL", "0,1", "GLOBL symbol \"<erroneous symbol>\" must be a symbol(SB)"},
+		{"PCDATA", "", "expect two operands for PCDATA"},
+		{"PCDATA", "1", "expect two operands for PCDATA"},
+	}
+
+	// Note these errors should be independent of the architecture.
+	// Just run the test with amd64.
+	parser := newParser("amd64")
+	var buf bytes.Buffer
+	parser.errorWriter = &buf
+
+	for _, test := range tests {
+		parser.errorCount = 0
+		parser.lineNum++
+		parser.histLineNum++
+		op, ok := arch.Pseudos[test.pseudo]
+		if !ok {
+			t.Fatalf("Wrong pseudo-instruction: %s", test.pseudo)
+		}
+		parser.pseudo(op, test.pseudo, tokenize(test.operands))
+		errorLine := buf.String()
+		if test.expected != errorLine {
+			t.Errorf("Unexpected error %q; expected %q", errorLine, test.expected)
+		}
+		buf.Reset()
+	}
+
+}
diff --git a/src/cmd/asm/internal/asm/testdata/386.out b/src/cmd/asm/internal/asm/testdata/386.out
deleted file mode 100644
index be43ccb..0000000
--- a/src/cmd/asm/internal/asm/testdata/386.out
+++ /dev/null
@@ -1,49 +0,0 @@
-5 00001 (testdata/386.s:5)	TEXT	foo(SB), 0, $0
-8 00002 (testdata/386.s:8)	SETCC	AX
-9 00003 (testdata/386.s:9)	SETCC	foo+4(SB)
-12 00004 (testdata/386.s:12)	DIVB	AX
-13 00005 (testdata/386.s:13)	DIVB	foo+4(SB)
-14 00006 (testdata/386.s:14)	PUSHL	$foo+4(SB)
-15 00007 (testdata/386.s:15)	POPL	AX
-18 00008 (testdata/386.s:18)	SUBB	$1, AX
-19 00009 (testdata/386.s:19)	SUBB	$1, foo+4(SB)
-20 00010 (testdata/386.s:20)	SUBB	BX, AX
-21 00011 (testdata/386.s:21)	SUBB	BX, foo+4(SB)
-24 00012 (testdata/386.s:24)	CMPB	AX, $1
-25 00013 (testdata/386.s:25)	CMPB	foo+4(SB), $4
-26 00014 (testdata/386.s:26)	CMPB	BX, AX
-27 00015 (testdata/386.s:27)	CMPB	foo+4(SB), BX
-31 00016 (testdata/386.s:31)	JCS
-32 00017 (testdata/386.s:32)	JCS	16(PC)
-35 00018 (testdata/386.s:35)	CALL	AX
-36 00019 (testdata/386.s:36)	JMP	AX
-37 00020 (testdata/386.s:37)	CALL	*foo(SB)
-38 00021 (testdata/386.s:38)	JMP	$4
-39 00022 (testdata/386.s:39)	JMP	16
-40 00023 (testdata/386.s:40)	CALL	foo(SB)
-42 00024 (testdata/386.s:42)	CALL	foo+4(SB)(AX*4)
-43 00025 (testdata/386.s:43)	CALL	4(SP)
-44 00026 (testdata/386.s:44)	CALL	(AX)
-45 00027 (testdata/386.s:45)	CALL	(SP)
-47 00028 (testdata/386.s:47)	CALL	(AX)(AX*4)
-48 00029 (testdata/386.s:48)	CALL	4(SP)
-49 00030 (testdata/386.s:49)	CALL	(AX)
-50 00031 (testdata/386.s:50)	CALL	(SP)
-52 00032 (testdata/386.s:52)	JMP	(AX)(AX*4)
-55 00033 (testdata/386.s:55)	NOP
-56 00034 (testdata/386.s:56)	NOP	AX
-57 00035 (testdata/386.s:57)	NOP	foo+4(SB)
-60 00036 (testdata/386.s:60)	SHLL	$4, BX
-61 00037 (testdata/386.s:61)	SHLL	$4, foo+4(SB)
-62 00038 (testdata/386.s:62)	SHLL	$4, AX, foo+4(SB)
-65 00039 (testdata/386.s:65)	MOVL	AX, BX
-66 00040 (testdata/386.s:66)	MOVL	$4, BX
-69 00041 (testdata/386.s:69)	IMULL	AX
-70 00042 (testdata/386.s:70)	IMULL	$4, CX
-71 00043 (testdata/386.s:71)	IMULL	AX, BX
-74 00044 (testdata/386.s:74)	CMPPD	X0, X1, 4
-75 00045 (testdata/386.s:75)	CMPPD	X0, foo+4(SB), 4
-78 00046 (testdata/386.s:78)	PINSRD	$1, (AX), X0
-79 00047 (testdata/386.s:79)	PINSRD	$2, foo+4(FP), X0
-83 00048 (testdata/386.s:83)	LOOP
-86 00049 (testdata/386.s:86)	RET
diff --git a/src/cmd/asm/internal/asm/testdata/386.s b/src/cmd/asm/internal/asm/testdata/386.s
index 6bee39f..4d969d1 100644
--- a/src/cmd/asm/internal/asm/testdata/386.s
+++ b/src/cmd/asm/internal/asm/testdata/386.s
@@ -2,7 +2,7 @@
 // the old assembler's (8a's) grammar and hand-writing complete
 // instructions for each rule, to guarantee we cover the same space.
 
-TEXT foo(SB), 0, $0
+TEXT foo(SB), 7, $0
 
 // LTYPE1 nonrem	{ outcode(int($1), &$2); }
 	SETCC	AX
@@ -12,7 +12,7 @@ TEXT foo(SB), 0, $0
 	DIVB	AX
 	DIVB	foo+4(SB)
 	PUSHL	$foo+4(SB)
-	POPL		AX // balance PUSHL
+	POPL		AX
 
 // LTYPE3 rimrem	{ outcode(int($1), &$2); }
 	SUBB	$1, AX
@@ -28,27 +28,31 @@ TEXT foo(SB), 0, $0
 
 // LTYPER nonrel	{ outcode(int($1), &$2); }
 label:
-	JC	label
-	JC	-1(PC)
+	JC	label // JCS
+	JC	-1(PC) // JCS -1(PC)
 
 // LTYPEC spec3	{ outcode(int($1), &$2); }
 	CALL	AX
-	JMP	*AX
+	JCS	2(PC)
+	JMP	*AX // JMP AX
 	CALL	*foo(SB)
+	JCS	2(PC)
 	JMP	$4
-	JMP	label
+	JCS	2(PC)
+	JMP	label // JMP 16
 	CALL	foo(SB)
-	CALL	(AX*4)
+//	CALL	(AX*4) // TODO: This line is silently dropped on the floor!
 	CALL	foo+4(SB)(AX*4)
-	CALL	*4(SP)
-	CALL	*(AX)
-	CALL	*(SP)
-	CALL	*(AX*4)
-	CALL	*(AX)(AX*4)
+	CALL	*4(SP) // CALL 4(SP)
+	CALL	*(AX) // CALL (AX)
+	CALL	*(SP) // CALL (SP)
+//	CALL	*(AX*4) // TODO: This line is silently dropped on the floor!
+	CALL	*(AX)(AX*4) // CALL (AX)(AX*4)
 	CALL	4(SP)
 	CALL	(AX)
 	CALL	(SP)
-	CALL	(AX*4)
+//	CALL	(AX*4) // TODO: This line is silently dropped on the floor!
+	JCS	2(PC)
 	JMP	(AX)(AX*4)
 
 // LTYPEN spec4	{ outcode(int($1), &$2); }
@@ -59,7 +63,7 @@ label:
 // LTYPES spec5	{ outcode(int($1), &$2); }
 	SHLL	$4, BX
 	SHLL	$4, foo+4(SB)
-	SHLL	$4, foo+4(SB):AX
+	SHLL	$4, foo+4(SB):AX // SHLL $4, AX, foo+4(SB)
 
 // LTYPEM spec6	{ outcode(int($1), &$2); }
 	MOVL	AX, BX
@@ -72,15 +76,16 @@ label:
 
 // LTYPEXC spec9	{ outcode(int($1), &$2); }
 	CMPPD	X0, X1, 4
-	CMPPD	X0, foo+4(SB), 4
+	CMPPD	foo+4(SB), X1, 4
 
 // LTYPEX spec10	{ outcode(int($1), &$2); }
 	PINSRD	$1, (AX), X0
 	PINSRD	$2, foo+4(FP), X0
 
 // Was bug: LOOP is a branch instruction.
+	JCS	2(PC)
 loop:
-	LOOP	loop
+	LOOP	loop // LOOP
 
 // LTYPE0 nonnon	{ outcode(int($1), &$2); }
 	RET
diff --git a/src/cmd/asm/internal/asm/testdata/amd64.out b/src/cmd/asm/internal/asm/testdata/amd64.out
deleted file mode 100644
index 850a78e..0000000
--- a/src/cmd/asm/internal/asm/testdata/amd64.out
+++ /dev/null
@@ -1,57 +0,0 @@
-9 00001 (testdata/amd64.s:9)	TEXT	foo(SB), 0, $0
-12 00002 (testdata/amd64.s:12)	NEGQ	R11
-13 00003 (testdata/amd64.s:13)	NEGQ	4(R11)
-14 00004 (testdata/amd64.s:14)	NEGQ	foo+4(SB)
-17 00005 (testdata/amd64.s:17)	INT	$4
-18 00006 (testdata/amd64.s:18)	DIVB	R11
-19 00007 (testdata/amd64.s:19)	DIVB	4(R11)
-20 00008 (testdata/amd64.s:20)	DIVB	foo+4(SB)
-23 00009 (testdata/amd64.s:23)	SUBQ	$4, DI
-24 00010 (testdata/amd64.s:24)	SUBQ	R11, DI
-25 00011 (testdata/amd64.s:25)	SUBQ	4(R11), DI
-26 00012 (testdata/amd64.s:26)	SUBQ	foo+4(SB), DI
-27 00013 (testdata/amd64.s:27)	SUBQ	$4, 8(R12)
-28 00014 (testdata/amd64.s:28)	SUBQ	R11, 8(R12)
-29 00015 (testdata/amd64.s:29)	SUBQ	R11, foo+4(SB)
-32 00016 (testdata/amd64.s:32)	CMPB	CX, $4
-36 00017 (testdata/amd64.s:36)	JCS	13(PC)
-37 00018 (testdata/amd64.s:37)	JCS	17
-40 00019 (testdata/amd64.s:40)	JMP	15(PC)
-41 00020 (testdata/amd64.s:41)	JMP	17
-42 00021 (testdata/amd64.s:42)	JMP	foo+4(SB)
-43 00022 (testdata/amd64.s:43)	JMP	bar<>+4(SB)
-44 00023 (testdata/amd64.s:44)	JMP	bar<>+4(SB)(R11*4)
-45 00024 (testdata/amd64.s:45)	JMP	4(SP)
-46 00025 (testdata/amd64.s:46)	JMP	(R12)
-48 00026 (testdata/amd64.s:48)	JMP	(R12)(R13*4)
-49 00027 (testdata/amd64.s:49)	JMP	(AX)
-50 00028 (testdata/amd64.s:50)	JMP	(SP)
-52 00029 (testdata/amd64.s:52)	JMP	(AX)(AX*4)
-53 00030 (testdata/amd64.s:53)	JMP	4(SP)
-54 00031 (testdata/amd64.s:54)	JMP	(R12)
-56 00032 (testdata/amd64.s:56)	JMP	(R12)(R13*4)
-57 00033 (testdata/amd64.s:57)	JMP	(AX)
-58 00034 (testdata/amd64.s:58)	JMP	(SP)
-60 00035 (testdata/amd64.s:60)	JMP	(AX)(AX*4)
-61 00036 (testdata/amd64.s:61)	JMP	R13
-64 00037 (testdata/amd64.s:64)	NOP
-65 00038 (testdata/amd64.s:65)	NOP	AX
-66 00039 (testdata/amd64.s:66)	NOP	foo+4(SB)
-69 00040 (testdata/amd64.s:69)	SHLL	R11, R12
-70 00041 (testdata/amd64.s:70)	SHLL	R11, foo+4(SB)
-71 00042 (testdata/amd64.s:71)	SHLL	R11, AX, R11
-74 00043 (testdata/amd64.s:74)	MOVL	AX, R11
-75 00044 (testdata/amd64.s:75)	MOVL	$4, R11
-76 00045 (testdata/amd64.s:76)	MOVL	AX, CS, AX
-79 00046 (testdata/amd64.s:79)	IMULB	$4
-80 00047 (testdata/amd64.s:80)	IMULB	R11
-81 00048 (testdata/amd64.s:81)	IMULB	$4, R11
-82 00049 (testdata/amd64.s:82)	IMULB	R11, R12
-83 00050 (testdata/amd64.s:83)	IMULB	R11, foo+4(SB)
-86 00051 (testdata/amd64.s:86)	CMPPD	R11, R12, 4
-87 00052 (testdata/amd64.s:87)	CMPPD	R11, foo+4(SB), 4
-90 00053 (testdata/amd64.s:90)	PINSRW	$4, R11, AX
-91 00054 (testdata/amd64.s:91)	PINSRW	$4, foo+4(SB), AX
-94 00055 (testdata/amd64.s:94)	RETFL	$4
-98 00056 (testdata/amd64.s:98)	LOOP
-101 00057 (testdata/amd64.s:101)	RET
diff --git a/src/cmd/asm/internal/asm/testdata/amd64.s b/src/cmd/asm/internal/asm/testdata/amd64.s
index 1b32ac4..70e7636 100644
--- a/src/cmd/asm/internal/asm/testdata/amd64.s
+++ b/src/cmd/asm/internal/asm/testdata/amd64.s
@@ -6,7 +6,7 @@
 // the old assembler's (6a's) grammar and hand-writing complete
 // instructions for each rule, to guarantee we cover the same space.
 
-TEXT	foo(SB), 0, $0
+TEXT	foo(SB), 7, $0
 
 // LTYPE1 nonrem	{ outcode($1, &$2); }
 	NEGQ	R11
@@ -33,31 +33,53 @@ TEXT	foo(SB), 0, $0
 
 // LTYPER nonrel	{ outcode($1, &$2); }
 label:
-	JB	-4(PC)
-	JB	label
+	JB	-4(PC) // JCS -4(PC)
+	JB	label // JCS 17
 
 // LTYPEC spec3	{ outcode($1, &$2); }
+	JCS	2(PC)
 	JMP	-4(PC)
-	JMP	label
+	JCS	2(PC)
+	JMP	label // JMP 17
+	JCS	2(PC)
 	JMP	foo+4(SB)
+	JCS	2(PC)
 	JMP	bar<>+4(SB)
+	JCS	2(PC)
 	JMP	bar<>+4(SB)(R11*4)
-	JMP	*4(SP)
-	JMP	*(R12)
-	JMP	*(R12*4)
-	JMP	*(R12)(R13*4)
-	JMP	*(AX)
-	JMP	*(SP)
-	JMP	*(AX*4)
-	JMP	*(AX)(AX*4)
+	JCS	2(PC)
+	JMP	*4(SP) // JMP 4(SP)
+	JCS	2(PC)
+	JMP	*(R12) // JMP (R12)
+	JCS	2(PC)
+//	JMP	*(R12*4) // TODO: This line is silently dropped on the floor!
+	JCS	2(PC)
+	JMP	*(R12)(R13*4) // JMP (R12)(R13*4)
+	JCS	2(PC)
+	JMP	*(AX) // JMP (AX)
+	JCS	2(PC)
+	JMP	*(SP) // JMP (SP)
+	JCS	2(PC)
+//	JMP	*(AX*4) // TODO: This line is silently dropped on the floor!
+	JCS	2(PC)
+	JMP	*(AX)(AX*4) // JMP (AX)(AX*4)
+	JCS	2(PC)
 	JMP	4(SP)
+	JCS	2(PC)
 	JMP	(R12)
-	JMP	(R12*4)
+	JCS	2(PC)
+//	JMP	(R12*4) // TODO: This line is silently dropped on the floor!
+	JCS	2(PC)
 	JMP	(R12)(R13*4)
+	JCS	2(PC)
 	JMP	(AX)
+	JCS	2(PC)
 	JMP	(SP)
-	JMP	(AX*4)
+	JCS	2(PC)
+//	JMP	(AX*4) // TODO: This line is silently dropped on the floor!
+	JCS	2(PC)
 	JMP	(AX)(AX*4)
+	JCS	2(PC)
 	JMP	R13
 
 // LTYPEN spec4	{ outcode($1, &$2); }
@@ -66,36 +88,44 @@ label:
 	NOP	foo+4(SB)
 
 // LTYPES spec5	{ outcode($1, &$2); }
-	SHLL	R11, R12
-	SHLL	R11, foo+4(SB)
-	SHLL	R11, R11:AX // Old syntax, still accepted.
+	SHLL	CX, R12
+	SHLL	CX, foo+4(SB)
+	// Old syntax, still accepted:
+	SHLL	CX, R11:AX // SHLL CX, AX, R11
 
 // LTYPEM spec6	{ outcode($1, &$2); }
 	MOVL	AX, R11
 	MOVL	$4, R11
-	MOVL	AX, AX:CS
+//	MOVL	AX, 0(AX):DS // no longer works - did it ever?
 
 // LTYPEI spec7	{ outcode($1, &$2); }
-	IMULB	$4
-	IMULB	R11
-	IMULB	$4, R11
-	IMULB	R11, R12
-	IMULB	R11, foo+4(SB)
+	IMULB	DX
+	IMULW	DX, BX
+	IMULL	R11, R12
+	IMULQ	foo+4(SB), R11
 
 // LTYPEXC spec8	{ outcode($1, &$2); }
-	CMPPD	R11, R12, 4
-	CMPPD	R11, foo+4(SB), 4
+	CMPPD	X1, X2, 4
+	CMPPD	foo+4(SB), X2, 4
 
 // LTYPEX spec9	{ outcode($1, &$2); }
-	PINSRW	$4, R11, AX
-	PINSRW	$4, foo+4(SB), AX
+	PINSRW	$4, AX, X2
+	PINSRW	$4, foo+4(SB), X2
 
 // LTYPERT spec10	{ outcode($1, &$2); }
+	JCS	2(PC)
 	RETFL	$4
 
 // Was bug: LOOP is a branch instruction.
+	JCS	2(PC)
 loop:
-	LOOP	loop
+	LOOP	loop // LOOP
+
+	// Intel pseudonyms for our own renamings.
+	PADDD	M2, M1 // PADDL M2, M1
+	MOVDQ2Q	X1, M1 // MOVQ X1, M1
+	MOVNTDQ	X1, (AX)	// MOVNTO X1, (AX)
+	MOVOA	(AX), X1	// MOVO (AX), X1
 
 // LTYPE0 nonnon	{ outcode($1, &$2); }
-	RET
+	RET // c3
diff --git a/src/cmd/asm/internal/asm/testdata/amd64enc.s b/src/cmd/asm/internal/asm/testdata/amd64enc.s
new file mode 100644
index 0000000..63fdcac
--- /dev/null
+++ b/src/cmd/asm/internal/asm/testdata/amd64enc.s
@@ -0,0 +1,10682 @@
+// generated by x86test -amd64
+// DO NOT EDIT
+
+TEXT asmtest(SB),7,$0
+	ADCB $7, AL                             // 1407
+	ADCW $61731, AX                         // 661523f1
+	ADCL $4045620583, AX                    // 15674523f1
+	ADCQ $-249346713, AX                    // 4815674523f1
+	ADCW $61731, (BX)                       // 66811323f1
+	ADCW $61731, (R11)                      // 6641811323f1
+	ADCW $61731, DX                         // 6681d223f1
+	ADCW $61731, R11                        // 664181d323f1
+	ADCW $7, (BX)                           // 66831307
+	ADCW $7, (R11)                          // 6641831307
+	ADCW $7, DX                             // 6683d207
+	ADCW $7, R11                            // 664183d307
+	ADCW DX, (BX)                           // 661113
+	ADCW R11, (BX)                          // 6644111b
+	ADCW DX, (R11)                          // 66411113
+	ADCW R11, (R11)                         // 6645111b
+	ADCW DX, DX                             // 6611d2 or 6613d2
+	ADCW R11, DX                            // 664411da or 664113d3
+	ADCW DX, R11                            // 664111d3 or 664413da
+	ADCW R11, R11                           // 664511db or 664513db
+	ADCL $4045620583, (BX)                  // 8113674523f1
+	ADCL $4045620583, (R11)                 // 418113674523f1
+	ADCL $4045620583, DX                    // 81d2674523f1
+	ADCL $4045620583, R11                   // 4181d3674523f1
+	ADCL $7, (BX)                           // 831307
+	ADCL $7, (R11)                          // 41831307
+	ADCL $7, DX                             // 83d207
+	ADCL $7, R11                            // 4183d307
+	ADCL DX, (BX)                           // 1113
+	ADCL R11, (BX)                          // 44111b
+	ADCL DX, (R11)                          // 411113
+	ADCL R11, (R11)                         // 45111b
+	ADCL DX, DX                             // 11d2 or 13d2
+	ADCL R11, DX                            // 4411da or 4113d3
+	ADCL DX, R11                            // 4111d3 or 4413da
+	ADCL R11, R11                           // 4511db or 4513db
+	ADCQ $-249346713, (BX)                  // 488113674523f1
+	ADCQ $-249346713, (R11)                 // 498113674523f1
+	ADCQ $-249346713, DX                    // 4881d2674523f1
+	ADCQ $-249346713, R11                   // 4981d3674523f1
+	ADCQ $7, (BX)                           // 48831307
+	ADCQ $7, (R11)                          // 49831307
+	ADCQ $7, DX                             // 4883d207
+	ADCQ $7, R11                            // 4983d307
+	ADCQ DX, (BX)                           // 481113
+	ADCQ R11, (BX)                          // 4c111b
+	ADCQ DX, (R11)                          // 491113
+	ADCQ R11, (R11)                         // 4d111b
+	ADCQ DX, DX                             // 4811d2 or 4813d2
+	ADCQ R11, DX                            // 4c11da or 4913d3
+	ADCQ DX, R11                            // 4911d3 or 4c13da
+	ADCQ R11, R11                           // 4d11db or 4d13db
+	ADCB $7, (BX)                           // 801307
+	ADCB $7, (R11)                          // 41801307
+	ADCB $7, DL                             // 80d207
+	ADCB $7, R11                            // 4180d307
+	ADCB DL, (BX)                           // 1013
+	ADCB R11, (BX)                          // 44101b
+	ADCB DL, (R11)                          // 411013
+	ADCB R11, (R11)                         // 45101b
+	ADCB DL, DL                             // 10d2 or 12d2
+	ADCB R11, DL                            // 4410da or 4112d3
+	ADCB DL, R11                            // 4110d3 or 4412da
+	ADCB R11, R11                           // 4510db or 4512db
+	ADCW (BX), DX                           // 661313
+	ADCW (R11), DX                          // 66411313
+	ADCW (BX), R11                          // 6644131b
+	ADCW (R11), R11                         // 6645131b
+	ADCL (BX), DX                           // 1313
+	ADCL (R11), DX                          // 411313
+	ADCL (BX), R11                          // 44131b
+	ADCL (R11), R11                         // 45131b
+	ADCQ (BX), DX                           // 481313
+	ADCQ (R11), DX                          // 491313
+	ADCQ (BX), R11                          // 4c131b
+	ADCQ (R11), R11                         // 4d131b
+	//TODO: ADCB (BX), DL                   // 1213
+	//TODO: ADCB (R11), DL                  // 411213
+	//TODO: ADCB (BX), R11                  // 44121b
+	//TODO: ADCB (R11), R11                 // 45121b
+	//TODO: ADCXL (BX), DX                  // 660f38f613
+	//TODO: ADCXL (R11), DX                 // 66410f38f613
+	//TODO: ADCXL DX, DX                    // 660f38f6d2
+	//TODO: ADCXL R11, DX                   // 66410f38f6d3
+	//TODO: ADCXL (BX), R11                 // 66440f38f61b
+	//TODO: ADCXL (R11), R11                // 66450f38f61b
+	//TODO: ADCXL DX, R11                   // 66440f38f6da
+	//TODO: ADCXL R11, R11                  // 66450f38f6db
+	//TODO: ADCXQ (BX), DX                  // 66480f38f613
+	//TODO: ADCXQ (R11), DX                 // 66490f38f613
+	//TODO: ADCXQ DX, DX                    // 66480f38f6d2
+	//TODO: ADCXQ R11, DX                   // 66490f38f6d3
+	//TODO: ADCXQ (BX), R11                 // 664c0f38f61b
+	//TODO: ADCXQ (R11), R11                // 664d0f38f61b
+	//TODO: ADCXQ DX, R11                   // 664c0f38f6da
+	//TODO: ADCXQ R11, R11                  // 664d0f38f6db
+	ADDB $7, AL                             // 0407
+	ADDW $61731, AX                         // 660523f1
+	ADDL $4045620583, AX                    // 05674523f1
+	ADDQ $-249346713, AX                    // 4805674523f1
+	ADDW $61731, (BX)                       // 66810323f1
+	ADDW $61731, (R11)                      // 6641810323f1
+	ADDW $61731, DX                         // 6681c223f1
+	ADDW $61731, R11                        // 664181c323f1
+	ADDW $7, (BX)                           // 66830307
+	ADDW $7, (R11)                          // 6641830307
+	ADDW $7, DX                             // 6683c207
+	ADDW $7, R11                            // 664183c307
+	ADDW DX, (BX)                           // 660113
+	ADDW R11, (BX)                          // 6644011b
+	ADDW DX, (R11)                          // 66410113
+	ADDW R11, (R11)                         // 6645011b
+	ADDW DX, DX                             // 6601d2 or 6603d2
+	ADDW R11, DX                            // 664401da or 664103d3
+	ADDW DX, R11                            // 664101d3 or 664403da
+	ADDW R11, R11                           // 664501db or 664503db
+	ADDL $4045620583, (BX)                  // 8103674523f1
+	ADDL $4045620583, (R11)                 // 418103674523f1
+	ADDL $4045620583, DX                    // 81c2674523f1
+	ADDL $4045620583, R11                   // 4181c3674523f1
+	ADDL $7, (BX)                           // 830307
+	ADDL $7, (R11)                          // 41830307
+	ADDL $7, DX                             // 83c207
+	ADDL $7, R11                            // 4183c307
+	ADDL DX, (BX)                           // 0113
+	ADDL R11, (BX)                          // 44011b
+	ADDL DX, (R11)                          // 410113
+	ADDL R11, (R11)                         // 45011b
+	ADDL DX, DX                             // 01d2 or 03d2
+	ADDL R11, DX                            // 4401da or 4103d3
+	ADDL DX, R11                            // 4101d3 or 4403da
+	ADDL R11, R11                           // 4501db or 4503db
+	ADDQ $-249346713, (BX)                  // 488103674523f1
+	ADDQ $-249346713, (R11)                 // 498103674523f1
+	ADDQ $-249346713, DX                    // 4881c2674523f1
+	ADDQ $-249346713, R11                   // 4981c3674523f1
+	ADDQ $7, (BX)                           // 48830307
+	ADDQ $7, (R11)                          // 49830307
+	ADDQ $7, DX                             // 4883c207
+	ADDQ $7, R11                            // 4983c307
+	ADDQ DX, (BX)                           // 480113
+	ADDQ R11, (BX)                          // 4c011b
+	ADDQ DX, (R11)                          // 490113
+	ADDQ R11, (R11)                         // 4d011b
+	ADDQ DX, DX                             // 4801d2 or 4803d2
+	ADDQ R11, DX                            // 4c01da or 4903d3
+	ADDQ DX, R11                            // 4901d3 or 4c03da
+	ADDQ R11, R11                           // 4d01db or 4d03db
+	ADDB $7, (BX)                           // 800307
+	ADDB $7, (R11)                          // 41800307
+	ADDB $7, DL                             // 80c207
+	ADDB $7, R11                            // 4180c307
+	ADDB DL, (BX)                           // 0013
+	ADDB R11, (BX)                          // 44001b
+	ADDB DL, (R11)                          // 410013
+	ADDB R11, (R11)                         // 45001b
+	ADDB DL, DL                             // 00d2 or 02d2
+	ADDB R11, DL                            // 4400da or 4102d3
+	ADDB DL, R11                            // 4100d3 or 4402da
+	ADDB R11, R11                           // 4500db or 4502db
+	ADDW (BX), DX                           // 660313
+	ADDW (R11), DX                          // 66410313
+	ADDW (BX), R11                          // 6644031b
+	ADDW (R11), R11                         // 6645031b
+	ADDL (BX), DX                           // 0313
+	ADDL (R11), DX                          // 410313
+	ADDL (BX), R11                          // 44031b
+	ADDL (R11), R11                         // 45031b
+	ADDQ (BX), DX                           // 480313
+	ADDQ (R11), DX                          // 490313
+	ADDQ (BX), R11                          // 4c031b
+	ADDQ (R11), R11                         // 4d031b
+	ADDB (BX), DL                           // 0213
+	ADDB (R11), DL                          // 410213
+	ADDB (BX), R11                          // 44021b
+	ADDB (R11), R11                         // 45021b
+	ADDPD (BX), X2                          // 660f5813
+	ADDPD (R11), X2                         // 66410f5813
+	ADDPD X2, X2                            // 660f58d2
+	ADDPD X11, X2                           // 66410f58d3
+	ADDPD (BX), X11                         // 66440f581b
+	ADDPD (R11), X11                        // 66450f581b
+	ADDPD X2, X11                           // 66440f58da
+	ADDPD X11, X11                          // 66450f58db
+	ADDPS (BX), X2                          // 0f5813
+	ADDPS (R11), X2                         // 410f5813
+	ADDPS X2, X2                            // 0f58d2
+	ADDPS X11, X2                           // 410f58d3
+	ADDPS (BX), X11                         // 440f581b
+	ADDPS (R11), X11                        // 450f581b
+	ADDPS X2, X11                           // 440f58da
+	ADDPS X11, X11                          // 450f58db
+	ADDSD (BX), X2                          // f20f5813
+	ADDSD (R11), X2                         // f2410f5813
+	ADDSD X2, X2                            // f20f58d2
+	ADDSD X11, X2                           // f2410f58d3
+	ADDSD (BX), X11                         // f2440f581b
+	ADDSD (R11), X11                        // f2450f581b
+	ADDSD X2, X11                           // f2440f58da
+	ADDSD X11, X11                          // f2450f58db
+	ADDSS (BX), X2                          // f30f5813
+	ADDSS (R11), X2                         // f3410f5813
+	ADDSS X2, X2                            // f30f58d2
+	ADDSS X11, X2                           // f3410f58d3
+	ADDSS (BX), X11                         // f3440f581b
+	ADDSS (R11), X11                        // f3450f581b
+	ADDSS X2, X11                           // f3440f58da
+	ADDSS X11, X11                          // f3450f58db
+	//TODO: ADDSUBPD (BX), X2               // 660fd013
+	//TODO: ADDSUBPD (R11), X2              // 66410fd013
+	//TODO: ADDSUBPD X2, X2                 // 660fd0d2
+	//TODO: ADDSUBPD X11, X2                // 66410fd0d3
+	//TODO: ADDSUBPD (BX), X11              // 66440fd01b
+	//TODO: ADDSUBPD (R11), X11             // 66450fd01b
+	//TODO: ADDSUBPD X2, X11                // 66440fd0da
+	//TODO: ADDSUBPD X11, X11               // 66450fd0db
+	//TODO: ADDSUBPS (BX), X2               // f20fd013
+	//TODO: ADDSUBPS (R11), X2              // f2410fd013
+	//TODO: ADDSUBPS X2, X2                 // f20fd0d2
+	//TODO: ADDSUBPS X11, X2                // f2410fd0d3
+	//TODO: ADDSUBPS (BX), X11              // f2440fd01b
+	//TODO: ADDSUBPS (R11), X11             // f2450fd01b
+	//TODO: ADDSUBPS X2, X11                // f2440fd0da
+	//TODO: ADDSUBPS X11, X11               // f2450fd0db
+	//TODO: ADOXL (BX), DX                  // f30f38f613
+	//TODO: ADOXL (R11), DX                 // f3410f38f613
+	//TODO: ADOXL DX, DX                    // f30f38f6d2
+	//TODO: ADOXL R11, DX                   // f3410f38f6d3
+	//TODO: ADOXL (BX), R11                 // f3440f38f61b
+	//TODO: ADOXL (R11), R11                // f3450f38f61b
+	//TODO: ADOXL DX, R11                   // f3440f38f6da
+	//TODO: ADOXL R11, R11                  // f3450f38f6db
+	//TODO: ADOXQ (BX), DX                  // f3480f38f613
+	//TODO: ADOXQ (R11), DX                 // f3490f38f613
+	//TODO: ADOXQ DX, DX                    // f3480f38f6d2
+	//TODO: ADOXQ R11, DX                   // f3490f38f6d3
+	//TODO: ADOXQ (BX), R11                 // f34c0f38f61b
+	//TODO: ADOXQ (R11), R11                // f34d0f38f61b
+	//TODO: ADOXQ DX, R11                   // f34c0f38f6da
+	//TODO: ADOXQ R11, R11                  // f34d0f38f6db
+	AESDEC (BX), X2                         // 660f38de13
+	AESDEC (R11), X2                        // 66410f38de13
+	AESDEC X2, X2                           // 660f38ded2
+	AESDEC X11, X2                          // 66410f38ded3
+	AESDEC (BX), X11                        // 66440f38de1b
+	AESDEC (R11), X11                       // 66450f38de1b
+	AESDEC X2, X11                          // 66440f38deda
+	AESDEC X11, X11                         // 66450f38dedb
+	AESDECLAST (BX), X2                     // 660f38df13
+	AESDECLAST (R11), X2                    // 66410f38df13
+	AESDECLAST X2, X2                       // 660f38dfd2
+	AESDECLAST X11, X2                      // 66410f38dfd3
+	AESDECLAST (BX), X11                    // 66440f38df1b
+	AESDECLAST (R11), X11                   // 66450f38df1b
+	AESDECLAST X2, X11                      // 66440f38dfda
+	AESDECLAST X11, X11                     // 66450f38dfdb
+	AESENC (BX), X2                         // 660f38dc13
+	AESENC (R11), X2                        // 66410f38dc13
+	AESENC X2, X2                           // 660f38dcd2
+	AESENC X11, X2                          // 66410f38dcd3
+	AESENC (BX), X11                        // 66440f38dc1b
+	AESENC (R11), X11                       // 66450f38dc1b
+	AESENC X2, X11                          // 66440f38dcda
+	AESENC X11, X11                         // 66450f38dcdb
+	AESENCLAST (BX), X2                     // 660f38dd13
+	AESENCLAST (R11), X2                    // 66410f38dd13
+	AESENCLAST X2, X2                       // 660f38ddd2
+	AESENCLAST X11, X2                      // 66410f38ddd3
+	AESENCLAST (BX), X11                    // 66440f38dd1b
+	AESENCLAST (R11), X11                   // 66450f38dd1b
+	AESENCLAST X2, X11                      // 66440f38ddda
+	AESENCLAST X11, X11                     // 66450f38dddb
+	AESIMC (BX), X2                         // 660f38db13
+	AESIMC (R11), X2                        // 66410f38db13
+	AESIMC X2, X2                           // 660f38dbd2
+	AESIMC X11, X2                          // 66410f38dbd3
+	AESIMC (BX), X11                        // 66440f38db1b
+	AESIMC (R11), X11                       // 66450f38db1b
+	AESIMC X2, X11                          // 66440f38dbda
+	AESIMC X11, X11                         // 66450f38dbdb
+	AESKEYGENASSIST $7, (BX), X2            // 660f3adf1307
+	AESKEYGENASSIST $7, (R11), X2           // 66410f3adf1307
+	AESKEYGENASSIST $7, X2, X2              // 660f3adfd207
+	AESKEYGENASSIST $7, X11, X2             // 66410f3adfd307
+	AESKEYGENASSIST $7, (BX), X11           // 66440f3adf1b07
+	AESKEYGENASSIST $7, (R11), X11          // 66450f3adf1b07
+	AESKEYGENASSIST $7, X2, X11             // 66440f3adfda07
+	AESKEYGENASSIST $7, X11, X11            // 66450f3adfdb07
+	ANDB $7, AL                             // 2407
+	ANDW $61731, AX                         // 662523f1
+	ANDL $4045620583, AX                    // 25674523f1
+	ANDQ $-249346713, AX                    // 4825674523f1
+	ANDW $61731, (BX)                       // 66812323f1
+	ANDW $61731, (R11)                      // 6641812323f1
+	ANDW $61731, DX                         // 6681e223f1
+	ANDW $61731, R11                        // 664181e323f1
+	ANDW $7, (BX)                           // 66832307
+	ANDW $7, (R11)                          // 6641832307
+	ANDW $7, DX                             // 6683e207
+	ANDW $7, R11                            // 664183e307
+	ANDW DX, (BX)                           // 662113
+	ANDW R11, (BX)                          // 6644211b
+	ANDW DX, (R11)                          // 66412113
+	ANDW R11, (R11)                         // 6645211b
+	ANDW DX, DX                             // 6621d2 or 6623d2
+	ANDW R11, DX                            // 664421da or 664123d3
+	ANDW DX, R11                            // 664121d3 or 664423da
+	ANDW R11, R11                           // 664521db or 664523db
+	ANDL $4045620583, (BX)                  // 8123674523f1
+	ANDL $4045620583, (R11)                 // 418123674523f1
+	ANDL $4045620583, DX                    // 81e2674523f1
+	ANDL $4045620583, R11                   // 4181e3674523f1
+	ANDL $7, (BX)                           // 832307
+	ANDL $7, (R11)                          // 41832307
+	ANDL $7, DX                             // 83e207
+	ANDL $7, R11                            // 4183e307
+	ANDL DX, (BX)                           // 2113
+	ANDL R11, (BX)                          // 44211b
+	ANDL DX, (R11)                          // 412113
+	ANDL R11, (R11)                         // 45211b
+	ANDL DX, DX                             // 21d2 or 23d2
+	ANDL R11, DX                            // 4421da or 4123d3
+	ANDL DX, R11                            // 4121d3 or 4423da
+	ANDL R11, R11                           // 4521db or 4523db
+	ANDQ $-249346713, (BX)                  // 488123674523f1
+	ANDQ $-249346713, (R11)                 // 498123674523f1
+	ANDQ $-249346713, DX                    // 4881e2674523f1
+	ANDQ $-249346713, R11                   // 4981e3674523f1
+	ANDQ $7, (BX)                           // 48832307
+	ANDQ $7, (R11)                          // 49832307
+	ANDQ $7, DX                             // 4883e207
+	ANDQ $7, R11                            // 4983e307
+	ANDQ DX, (BX)                           // 482113
+	ANDQ R11, (BX)                          // 4c211b
+	ANDQ DX, (R11)                          // 492113
+	ANDQ R11, (R11)                         // 4d211b
+	ANDQ DX, DX                             // 4821d2 or 4823d2
+	ANDQ R11, DX                            // 4c21da or 4923d3
+	ANDQ DX, R11                            // 4921d3 or 4c23da
+	ANDQ R11, R11                           // 4d21db or 4d23db
+	ANDB $7, (BX)                           // 802307
+	ANDB $7, (R11)                          // 41802307
+	ANDB $7, DL                             // 80e207
+	ANDB $7, R11                            // 4180e307
+	ANDB DL, (BX)                           // 2013
+	ANDB R11, (BX)                          // 44201b
+	ANDB DL, (R11)                          // 412013
+	ANDB R11, (R11)                         // 45201b
+	ANDB DL, DL                             // 20d2 or 22d2
+	ANDB R11, DL                            // 4420da or 4122d3
+	ANDB DL, R11                            // 4120d3 or 4422da
+	ANDB R11, R11                           // 4520db or 4522db
+	ANDW (BX), DX                           // 662313
+	ANDW (R11), DX                          // 66412313
+	ANDW (BX), R11                          // 6644231b
+	ANDW (R11), R11                         // 6645231b
+	ANDL (BX), DX                           // 2313
+	ANDL (R11), DX                          // 412313
+	ANDL (BX), R11                          // 44231b
+	ANDL (R11), R11                         // 45231b
+	ANDQ (BX), DX                           // 482313
+	ANDQ (R11), DX                          // 492313
+	ANDQ (BX), R11                          // 4c231b
+	ANDQ (R11), R11                         // 4d231b
+	ANDB (BX), DL                           // 2213
+	ANDB (R11), DL                          // 412213
+	ANDB (BX), R11                          // 44221b
+	ANDB (R11), R11                         // 45221b
+	ANDNL (BX), R9, DX                      // c4e230f213
+	ANDNL (R11), R9, DX                     // c4c230f213
+	ANDNL DX, R9, DX                        // c4e230f2d2
+	ANDNL R11, R9, DX                       // c4c230f2d3
+	ANDNL (BX), R9, R11                     // c46230f21b
+	ANDNL (R11), R9, R11                    // c44230f21b
+	ANDNL DX, R9, R11                       // c46230f2da
+	ANDNL R11, R9, R11                      // c44230f2db
+	ANDNQ (BX), R14, DX                     // c4e288f213
+	ANDNQ (R11), R14, DX                    // c4c288f213
+	ANDNQ DX, R14, DX                       // c4e288f2d2
+	ANDNQ R11, R14, DX                      // c4c288f2d3
+	ANDNQ (BX), R14, R11                    // c46288f21b
+	ANDNQ (R11), R14, R11                   // c44288f21b
+	ANDNQ DX, R14, R11                      // c46288f2da
+	ANDNQ R11, R14, R11                     // c44288f2db
+	ANDNPD (BX), X2                         // 660f5513
+	ANDNPD (R11), X2                        // 66410f5513
+	ANDNPD X2, X2                           // 660f55d2
+	ANDNPD X11, X2                          // 66410f55d3
+	ANDNPD (BX), X11                        // 66440f551b
+	ANDNPD (R11), X11                       // 66450f551b
+	ANDNPD X2, X11                          // 66440f55da
+	ANDNPD X11, X11                         // 66450f55db
+	ANDNPS (BX), X2                         // 0f5513
+	ANDNPS (R11), X2                        // 410f5513
+	ANDNPS X2, X2                           // 0f55d2
+	ANDNPS X11, X2                          // 410f55d3
+	ANDNPS (BX), X11                        // 440f551b
+	ANDNPS (R11), X11                       // 450f551b
+	ANDNPS X2, X11                          // 440f55da
+	ANDNPS X11, X11                         // 450f55db
+	ANDPD (BX), X2                          // 660f5413
+	ANDPD (R11), X2                         // 66410f5413
+	ANDPD X2, X2                            // 660f54d2
+	ANDPD X11, X2                           // 66410f54d3
+	ANDPD (BX), X11                         // 66440f541b
+	ANDPD (R11), X11                        // 66450f541b
+	ANDPD X2, X11                           // 66440f54da
+	ANDPD X11, X11                          // 66450f54db
+	//TODO: ANDPS (BX), X2                  // 0f5413
+	//TODO: ANDPS (R11), X2                 // 410f5413
+	//TODO: ANDPS X2, X2                    // 0f54d2
+	//TODO: ANDPS X11, X2                   // 410f54d3
+	//TODO: ANDPS (BX), X11                 // 440f541b
+	//TODO: ANDPS (R11), X11                // 450f541b
+	//TODO: ANDPS X2, X11                   // 440f54da
+	//TODO: ANDPS X11, X11                  // 450f54db
+	BEXTRL R9, (BX), DX                     // c4e230f713
+	BEXTRL R9, (R11), DX                    // c4c230f713
+	BEXTRL R9, DX, DX                       // c4e230f7d2
+	BEXTRL R9, R11, DX                      // c4c230f7d3
+	BEXTRL R9, (BX), R11                    // c46230f71b
+	BEXTRL R9, (R11), R11                   // c44230f71b
+	BEXTRL R9, DX, R11                      // c46230f7da
+	BEXTRL R9, R11, R11                     // c44230f7db
+	BEXTRQ R14, (BX), DX                    // c4e288f713
+	BEXTRQ R14, (R11), DX                   // c4c288f713
+	BEXTRQ R14, DX, DX                      // c4e288f7d2
+	BEXTRQ R14, R11, DX                     // c4c288f7d3
+	BEXTRQ R14, (BX), R11                   // c46288f71b
+	BEXTRQ R14, (R11), R11                  // c44288f71b
+	BEXTRQ R14, DX, R11                     // c46288f7da
+	BEXTRQ R14, R11, R11                    // c44288f7db
+	//TODO: BLENDPD $7, (BX), X2            // 660f3a0d1307
+	//TODO: BLENDPD $7, (R11), X2           // 66410f3a0d1307
+	//TODO: BLENDPD $7, X2, X2              // 660f3a0dd207
+	//TODO: BLENDPD $7, X11, X2             // 66410f3a0dd307
+	//TODO: BLENDPD $7, (BX), X11           // 66440f3a0d1b07
+	//TODO: BLENDPD $7, (R11), X11          // 66450f3a0d1b07
+	//TODO: BLENDPD $7, X2, X11             // 66440f3a0dda07
+	//TODO: BLENDPD $7, X11, X11            // 66450f3a0ddb07
+	//TODO: BLENDPS $7, (BX), X2            // 660f3a0c1307
+	//TODO: BLENDPS $7, (R11), X2           // 66410f3a0c1307
+	//TODO: BLENDPS $7, X2, X2              // 660f3a0cd207
+	//TODO: BLENDPS $7, X11, X2             // 66410f3a0cd307
+	//TODO: BLENDPS $7, (BX), X11           // 66440f3a0c1b07
+	//TODO: BLENDPS $7, (R11), X11          // 66450f3a0c1b07
+	//TODO: BLENDPS $7, X2, X11             // 66440f3a0cda07
+	//TODO: BLENDPS $7, X11, X11            // 66450f3a0cdb07
+	//TODO: BLENDVPD XMM0, (BX), X2         // 660f381513
+	//TODO: BLENDVPD XMM0, (R11), X2        // 66410f381513
+	//TODO: BLENDVPD XMM0, X2, X2           // 660f3815d2
+	//TODO: BLENDVPD XMM0, X11, X2          // 66410f3815d3
+	//TODO: BLENDVPD XMM0, (BX), X11        // 66440f38151b
+	//TODO: BLENDVPD XMM0, (R11), X11       // 66450f38151b
+	//TODO: BLENDVPD XMM0, X2, X11          // 66440f3815da
+	//TODO: BLENDVPD XMM0, X11, X11         // 66450f3815db
+	//TODO: BLENDVPS XMM0, (BX), X2         // 660f381413
+	//TODO: BLENDVPS XMM0, (R11), X2        // 66410f381413
+	//TODO: BLENDVPS XMM0, X2, X2           // 660f3814d2
+	//TODO: BLENDVPS XMM0, X11, X2          // 66410f3814d3
+	//TODO: BLENDVPS XMM0, (BX), X11        // 66440f38141b
+	//TODO: BLENDVPS XMM0, (R11), X11       // 66450f38141b
+	//TODO: BLENDVPS XMM0, X2, X11          // 66440f3814da
+	//TODO: BLENDVPS XMM0, X11, X11         // 66450f3814db
+	//TODO: BLSIL (BX), R9                  // c4e230f31b
+	//TODO: BLSIL (R11), R9                 // c4c230f31b
+	//TODO: BLSIL DX, R9                    // c4e230f3da
+	//TODO: BLSIL R11, R9                   // c4c230f3db
+	//TODO: BLSIQ (BX), R14                 // c4e288f31b
+	//TODO: BLSIQ (R11), R14                // c4c288f31b
+	//TODO: BLSIQ DX, R14                   // c4e288f3da
+	//TODO: BLSIQ R11, R14                  // c4c288f3db
+	//TODO: BLSMSKL (BX), R9                // c4e230f313
+	//TODO: BLSMSKL (R11), R9               // c4c230f313
+	//TODO: BLSMSKL DX, R9                  // c4e230f3d2
+	//TODO: BLSMSKL R11, R9                 // c4c230f3d3
+	//TODO: BLSMSKQ (BX), R14               // c4e288f313
+	//TODO: BLSMSKQ (R11), R14              // c4c288f313
+	//TODO: BLSMSKQ DX, R14                 // c4e288f3d2
+	//TODO: BLSMSKQ R11, R14                // c4c288f3d3
+	//TODO: BLSRL (BX), R9                  // c4e230f30b
+	//TODO: BLSRL (R11), R9                 // c4c230f30b
+	//TODO: BLSRL DX, R9                    // c4e230f3ca
+	//TODO: BLSRL R11, R9                   // c4c230f3cb
+	//TODO: BLSRQ (BX), R14                 // c4e288f30b
+	//TODO: BLSRQ (R11), R14                // c4c288f30b
+	//TODO: BLSRQ DX, R14                   // c4e288f3ca
+	//TODO: BLSRQ R11, R14                  // c4c288f3cb
+	//TODO: BNDCL (BX), BND2                // f30f1a13
+	//TODO: BNDCL (R11), BND2               // f3410f1a13
+	//TODO: BNDCL DX, BND2                  // f30f1ad2
+	//TODO: BNDCL R11, BND2                 // f3410f1ad3
+	//TODO: BNDCL (BX), BND3                // f30f1a1b
+	//TODO: BNDCL (R11), BND3               // f3410f1a1b
+	//TODO: BNDCL DX, BND3                  // f30f1ada
+	//TODO: BNDCL R11, BND3                 // f3410f1adb
+	//TODO: BNDCN (BX), BND2                // f20f1b13
+	//TODO: BNDCN (R11), BND2               // f2410f1b13
+	//TODO: BNDCN DX, BND2                  // f20f1bd2
+	//TODO: BNDCN R11, BND2                 // f2410f1bd3
+	//TODO: BNDCN (BX), BND3                // f20f1b1b
+	//TODO: BNDCN (R11), BND3               // f2410f1b1b
+	//TODO: BNDCN DX, BND3                  // f20f1bda
+	//TODO: BNDCN R11, BND3                 // f2410f1bdb
+	//TODO: BNDCU (BX), BND2                // f20f1a13
+	//TODO: BNDCU (R11), BND2               // f2410f1a13
+	//TODO: BNDCU DX, BND2                  // f20f1ad2
+	//TODO: BNDCU R11, BND2                 // f2410f1ad3
+	//TODO: BNDCU (BX), BND3                // f20f1a1b
+	//TODO: BNDCU (R11), BND3               // f2410f1a1b
+	//TODO: BNDCU DX, BND3                  // f20f1ada
+	//TODO: BNDCU R11, BND3                 // f2410f1adb
+	//TODO: BNDLDX (BX), BND2               // 0f1a13
+	//TODO: BNDLDX (R11), BND2              // 410f1a13
+	//TODO: BNDLDX (BX), BND3               // 0f1a1b
+	//TODO: BNDLDX (R11), BND3              // 410f1a1b
+	//TODO: BNDMK (BX), BND2                // f30f1b13
+	//TODO: BNDMK (R11), BND2               // f3410f1b13
+	//TODO: BNDMK (BX), BND3                // f30f1b1b
+	//TODO: BNDMK (R11), BND3               // f3410f1b1b
+	//TODO: BNDMOV (BX), BND2               // 660f1a13
+	//TODO: BNDMOV (R11), BND2              // 66410f1a13
+	//TODO: BNDMOV BND2, BND2               // 660f1ad2 or 660f1bd2
+	//TODO: BNDMOV BND3, BND2               // 660f1ad3 or 660f1bda
+	//TODO: BNDMOV (BX), BND3               // 660f1a1b
+	//TODO: BNDMOV (R11), BND3              // 66410f1a1b
+	//TODO: BNDMOV BND2, BND3               // 660f1ada or 660f1bd3
+	//TODO: BNDMOV BND3, BND3               // 660f1adb or 660f1bdb
+	//TODO: BNDMOV BND2, (BX)               // 660f1b13
+	//TODO: BNDMOV BND3, (BX)               // 660f1b1b
+	//TODO: BNDMOV BND2, (R11)              // 66410f1b13
+	//TODO: BNDMOV BND3, (R11)              // 66410f1b1b
+	//TODO: BNDSTX BND2, (BX)               // 0f1b13
+	//TODO: BNDSTX BND3, (BX)               // 0f1b1b
+	//TODO: BNDSTX BND2, (R11)              // 410f1b13
+	//TODO: BNDSTX BND3, (R11)              // 410f1b1b
+	BSFW (BX), DX                           // 660fbc13
+	BSFW (R11), DX                          // 66410fbc13
+	BSFW DX, DX                             // 660fbcd2
+	BSFW R11, DX                            // 66410fbcd3
+	BSFW (BX), R11                          // 66440fbc1b
+	BSFW (R11), R11                         // 66450fbc1b
+	BSFW DX, R11                            // 66440fbcda
+	BSFW R11, R11                           // 66450fbcdb
+	BSFL (BX), DX                           // 0fbc13
+	BSFL (R11), DX                          // 410fbc13
+	BSFL DX, DX                             // 0fbcd2
+	BSFL R11, DX                            // 410fbcd3
+	BSFL (BX), R11                          // 440fbc1b
+	BSFL (R11), R11                         // 450fbc1b
+	BSFL DX, R11                            // 440fbcda
+	BSFL R11, R11                           // 450fbcdb
+	BSFQ (BX), DX                           // 480fbc13
+	BSFQ (R11), DX                          // 490fbc13
+	BSFQ DX, DX                             // 480fbcd2
+	BSFQ R11, DX                            // 490fbcd3
+	BSFQ (BX), R11                          // 4c0fbc1b
+	BSFQ (R11), R11                         // 4d0fbc1b
+	BSFQ DX, R11                            // 4c0fbcda
+	BSFQ R11, R11                           // 4d0fbcdb
+	BSRW (BX), DX                           // 660fbd13
+	BSRW (R11), DX                          // 66410fbd13
+	BSRW DX, DX                             // 660fbdd2
+	BSRW R11, DX                            // 66410fbdd3
+	BSRW (BX), R11                          // 66440fbd1b
+	BSRW (R11), R11                         // 66450fbd1b
+	BSRW DX, R11                            // 66440fbdda
+	BSRW R11, R11                           // 66450fbddb
+	BSRL (BX), DX                           // 0fbd13
+	BSRL (R11), DX                          // 410fbd13
+	BSRL DX, DX                             // 0fbdd2
+	BSRL R11, DX                            // 410fbdd3
+	BSRL (BX), R11                          // 440fbd1b
+	BSRL (R11), R11                         // 450fbd1b
+	BSRL DX, R11                            // 440fbdda
+	BSRL R11, R11                           // 450fbddb
+	BSRQ (BX), DX                           // 480fbd13
+	BSRQ (R11), DX                          // 490fbd13
+	BSRQ DX, DX                             // 480fbdd2
+	BSRQ R11, DX                            // 490fbdd3
+	BSRQ (BX), R11                          // 4c0fbd1b
+	BSRQ (R11), R11                         // 4d0fbd1b
+	BSRQ DX, R11                            // 4c0fbdda
+	BSRQ R11, R11                           // 4d0fbddb
+	//TODO: BSWAPW DX                       // 660fca
+	//TODO: BSWAPW R11                      // 66410fcb
+	BSWAPL DX                               // 0fca
+	BSWAPL R11                              // 410fcb
+	BSWAPQ DX                               // 480fca
+	BSWAPQ R11                              // 490fcb
+	BTW $7, (BX)                            // 660fba2307
+	BTW $7, (R11)                           // 66410fba2307
+	BTW $7, DX                              // 660fbae207
+	BTW $7, R11                             // 66410fbae307
+	BTW DX, (BX)                            // 660fa313
+	BTW R11, (BX)                           // 66440fa31b
+	BTW DX, (R11)                           // 66410fa313
+	BTW R11, (R11)                          // 66450fa31b
+	BTW DX, DX                              // 660fa3d2
+	BTW R11, DX                             // 66440fa3da
+	BTW DX, R11                             // 66410fa3d3
+	BTW R11, R11                            // 66450fa3db
+	BTL $7, (BX)                            // 0fba2307
+	BTL $7, (R11)                           // 410fba2307
+	BTL $7, DX                              // 0fbae207
+	BTL $7, R11                             // 410fbae307
+	BTL DX, (BX)                            // 0fa313
+	BTL R11, (BX)                           // 440fa31b
+	BTL DX, (R11)                           // 410fa313
+	BTL R11, (R11)                          // 450fa31b
+	BTL DX, DX                              // 0fa3d2
+	BTL R11, DX                             // 440fa3da
+	BTL DX, R11                             // 410fa3d3
+	BTL R11, R11                            // 450fa3db
+	BTQ $7, (BX)                            // 480fba2307
+	BTQ $7, (R11)                           // 490fba2307
+	BTQ $7, DX                              // 480fbae207
+	BTQ $7, R11                             // 490fbae307
+	BTQ DX, (BX)                            // 480fa313
+	BTQ R11, (BX)                           // 4c0fa31b
+	BTQ DX, (R11)                           // 490fa313
+	BTQ R11, (R11)                          // 4d0fa31b
+	BTQ DX, DX                              // 480fa3d2
+	BTQ R11, DX                             // 4c0fa3da
+	BTQ DX, R11                             // 490fa3d3
+	BTQ R11, R11                            // 4d0fa3db
+	BTCW $7, (BX)                           // 660fba3b07
+	BTCW $7, (R11)                          // 66410fba3b07
+	BTCW $7, DX                             // 660fbafa07
+	BTCW $7, R11                            // 66410fbafb07
+	BTCW DX, (BX)                           // 660fbb13
+	BTCW R11, (BX)                          // 66440fbb1b
+	BTCW DX, (R11)                          // 66410fbb13
+	BTCW R11, (R11)                         // 66450fbb1b
+	BTCW DX, DX                             // 660fbbd2
+	BTCW R11, DX                            // 66440fbbda
+	BTCW DX, R11                            // 66410fbbd3
+	BTCW R11, R11                           // 66450fbbdb
+	BTCL $7, (BX)                           // 0fba3b07
+	BTCL $7, (R11)                          // 410fba3b07
+	BTCL $7, DX                             // 0fbafa07
+	BTCL $7, R11                            // 410fbafb07
+	BTCL DX, (BX)                           // 0fbb13
+	BTCL R11, (BX)                          // 440fbb1b
+	BTCL DX, (R11)                          // 410fbb13
+	BTCL R11, (R11)                         // 450fbb1b
+	BTCL DX, DX                             // 0fbbd2
+	BTCL R11, DX                            // 440fbbda
+	BTCL DX, R11                            // 410fbbd3
+	BTCL R11, R11                           // 450fbbdb
+	BTCQ $7, (BX)                           // 480fba3b07
+	BTCQ $7, (R11)                          // 490fba3b07
+	BTCQ $7, DX                             // 480fbafa07
+	BTCQ $7, R11                            // 490fbafb07
+	BTCQ DX, (BX)                           // 480fbb13
+	BTCQ R11, (BX)                          // 4c0fbb1b
+	BTCQ DX, (R11)                          // 490fbb13
+	BTCQ R11, (R11)                         // 4d0fbb1b
+	BTCQ DX, DX                             // 480fbbd2
+	BTCQ R11, DX                            // 4c0fbbda
+	BTCQ DX, R11                            // 490fbbd3
+	BTCQ R11, R11                           // 4d0fbbdb
+	BTRW $7, (BX)                           // 660fba3307
+	BTRW $7, (R11)                          // 66410fba3307
+	BTRW $7, DX                             // 660fbaf207
+	BTRW $7, R11                            // 66410fbaf307
+	BTRW DX, (BX)                           // 660fb313
+	BTRW R11, (BX)                          // 66440fb31b
+	BTRW DX, (R11)                          // 66410fb313
+	BTRW R11, (R11)                         // 66450fb31b
+	BTRW DX, DX                             // 660fb3d2
+	BTRW R11, DX                            // 66440fb3da
+	BTRW DX, R11                            // 66410fb3d3
+	BTRW R11, R11                           // 66450fb3db
+	BTRL $7, (BX)                           // 0fba3307
+	BTRL $7, (R11)                          // 410fba3307
+	BTRL $7, DX                             // 0fbaf207
+	BTRL $7, R11                            // 410fbaf307
+	BTRL DX, (BX)                           // 0fb313
+	BTRL R11, (BX)                          // 440fb31b
+	BTRL DX, (R11)                          // 410fb313
+	BTRL R11, (R11)                         // 450fb31b
+	BTRL DX, DX                             // 0fb3d2
+	BTRL R11, DX                            // 440fb3da
+	BTRL DX, R11                            // 410fb3d3
+	BTRL R11, R11                           // 450fb3db
+	BTRQ $7, (BX)                           // 480fba3307
+	BTRQ $7, (R11)                          // 490fba3307
+	BTRQ $7, DX                             // 480fbaf207
+	BTRQ $7, R11                            // 490fbaf307
+	BTRQ DX, (BX)                           // 480fb313
+	BTRQ R11, (BX)                          // 4c0fb31b
+	BTRQ DX, (R11)                          // 490fb313
+	BTRQ R11, (R11)                         // 4d0fb31b
+	BTRQ DX, DX                             // 480fb3d2
+	BTRQ R11, DX                            // 4c0fb3da
+	BTRQ DX, R11                            // 490fb3d3
+	BTRQ R11, R11                           // 4d0fb3db
+	BTSW $7, (BX)                           // 660fba2b07
+	BTSW $7, (R11)                          // 66410fba2b07
+	BTSW $7, DX                             // 660fbaea07
+	BTSW $7, R11                            // 66410fbaeb07
+	BTSW DX, (BX)                           // 660fab13
+	BTSW R11, (BX)                          // 66440fab1b
+	BTSW DX, (R11)                          // 66410fab13
+	BTSW R11, (R11)                         // 66450fab1b
+	BTSW DX, DX                             // 660fabd2
+	BTSW R11, DX                            // 66440fabda
+	BTSW DX, R11                            // 66410fabd3
+	BTSW R11, R11                           // 66450fabdb
+	BTSL $7, (BX)                           // 0fba2b07
+	BTSL $7, (R11)                          // 410fba2b07
+	BTSL $7, DX                             // 0fbaea07
+	BTSL $7, R11                            // 410fbaeb07
+	BTSL DX, (BX)                           // 0fab13
+	BTSL R11, (BX)                          // 440fab1b
+	BTSL DX, (R11)                          // 410fab13
+	BTSL R11, (R11)                         // 450fab1b
+	BTSL DX, DX                             // 0fabd2
+	BTSL R11, DX                            // 440fabda
+	BTSL DX, R11                            // 410fabd3
+	BTSL R11, R11                           // 450fabdb
+	BTSQ $7, (BX)                           // 480fba2b07
+	BTSQ $7, (R11)                          // 490fba2b07
+	BTSQ $7, DX                             // 480fbaea07
+	BTSQ $7, R11                            // 490fbaeb07
+	BTSQ DX, (BX)                           // 480fab13
+	BTSQ R11, (BX)                          // 4c0fab1b
+	BTSQ DX, (R11)                          // 490fab13
+	BTSQ R11, (R11)                         // 4d0fab1b
+	BTSQ DX, DX                             // 480fabd2
+	BTSQ R11, DX                            // 4c0fabda
+	BTSQ DX, R11                            // 490fabd3
+	BTSQ R11, R11                           // 4d0fabdb
+	BZHIL R9, (BX), DX                      // c4e230f513
+	BZHIL R9, (R11), DX                     // c4c230f513
+	BZHIL R9, DX, DX                        // c4e230f5d2
+	BZHIL R9, R11, DX                       // c4c230f5d3
+	BZHIL R9, (BX), R11                     // c46230f51b
+	BZHIL R9, (R11), R11                    // c44230f51b
+	BZHIL R9, DX, R11                       // c46230f5da
+	BZHIL R9, R11, R11                      // c44230f5db
+	BZHIQ R14, (BX), DX                     // c4e288f513
+	BZHIQ R14, (R11), DX                    // c4c288f513
+	BZHIQ R14, DX, DX                       // c4e288f5d2
+	BZHIQ R14, R11, DX                      // c4c288f5d3
+	BZHIQ R14, (BX), R11                    // c46288f51b
+	BZHIQ R14, (R11), R11                   // c44288f51b
+	BZHIQ R14, DX, R11                      // c46288f5da
+	BZHIQ R14, R11, R11                     // c44288f5db
+	//TODO: CALLQ* (BX)                     // ff13
+	//TODO: CALLQ* (R11)                    // 41ff13
+	//TODO: CALLQ* DX                       // ffd2
+	//TODO: CALLQ* R11                      // 41ffd3
+	//TODO: CALL .+$0x11223344              // e844332211 or 48e844332211
+	//TODO: LCALLW* (BX)                    // 66ff1b
+	//TODO: LCALLW* (R11)                   // 6641ff1b
+	//TODO: LCALLL* (BX)                    // ff1b
+	//TODO: LCALLL* (R11)                   // 41ff1b
+	//TODO: LCALLQ* (BX)                    // 48ff1b
+	//TODO: LCALLQ* (R11)                   // 49ff1b
+	//TODO: CBW                             // 6698
+	CDQ                                     // 99
+	//TODO: CDQE                            // 4898
+	//TODO: CLAC                            // 0f01ca
+	CLC                                     // f8
+	CLD                                     // fc
+	//TODO: CLFLUSH (BX)                    // 0fae3b
+	//TODO: CLFLUSH (R11)                   // 410fae3b
+	//TODO: CLFLUSHOPT (BX)                 // 660fae3b
+	//TODO: CLFLUSHOPT (R11)                // 66410fae3b
+	CLI                                     // fa
+	CLTS                                    // 0f06
+	CMC                                     // f5
+	CMOVWHI (BX), DX                        // 660f4713
+	CMOVWHI (R11), DX                       // 66410f4713
+	CMOVWHI DX, DX                          // 660f47d2
+	CMOVWHI R11, DX                         // 66410f47d3
+	CMOVWHI (BX), R11                       // 66440f471b
+	CMOVWHI (R11), R11                      // 66450f471b
+	CMOVWHI DX, R11                         // 66440f47da
+	CMOVWHI R11, R11                        // 66450f47db
+	CMOVLHI (BX), DX                        // 0f4713
+	CMOVLHI (R11), DX                       // 410f4713
+	CMOVLHI DX, DX                          // 0f47d2
+	CMOVLHI R11, DX                         // 410f47d3
+	CMOVLHI (BX), R11                       // 440f471b
+	CMOVLHI (R11), R11                      // 450f471b
+	CMOVLHI DX, R11                         // 440f47da
+	CMOVLHI R11, R11                        // 450f47db
+	CMOVQHI (BX), DX                        // 480f4713
+	CMOVQHI (R11), DX                       // 490f4713
+	CMOVQHI DX, DX                          // 480f47d2
+	CMOVQHI R11, DX                         // 490f47d3
+	CMOVQHI (BX), R11                       // 4c0f471b
+	CMOVQHI (R11), R11                      // 4d0f471b
+	CMOVQHI DX, R11                         // 4c0f47da
+	CMOVQHI R11, R11                        // 4d0f47db
+	CMOVWCC (BX), DX                        // 660f4313
+	CMOVWCC (R11), DX                       // 66410f4313
+	CMOVWCC DX, DX                          // 660f43d2
+	CMOVWCC R11, DX                         // 66410f43d3
+	CMOVWCC (BX), R11                       // 66440f431b
+	CMOVWCC (R11), R11                      // 66450f431b
+	CMOVWCC DX, R11                         // 66440f43da
+	CMOVWCC R11, R11                        // 66450f43db
+	CMOVLCC (BX), DX                        // 0f4313
+	CMOVLCC (R11), DX                       // 410f4313
+	CMOVLCC DX, DX                          // 0f43d2
+	CMOVLCC R11, DX                         // 410f43d3
+	CMOVLCC (BX), R11                       // 440f431b
+	CMOVLCC (R11), R11                      // 450f431b
+	CMOVLCC DX, R11                         // 440f43da
+	CMOVLCC R11, R11                        // 450f43db
+	CMOVQCC (BX), DX                        // 480f4313
+	CMOVQCC (R11), DX                       // 490f4313
+	CMOVQCC DX, DX                          // 480f43d2
+	CMOVQCC R11, DX                         // 490f43d3
+	CMOVQCC (BX), R11                       // 4c0f431b
+	CMOVQCC (R11), R11                      // 4d0f431b
+	CMOVQCC DX, R11                         // 4c0f43da
+	CMOVQCC R11, R11                        // 4d0f43db
+	CMOVWCS (BX), DX                        // 660f4213
+	CMOVWCS (R11), DX                       // 66410f4213
+	CMOVWCS DX, DX                          // 660f42d2
+	CMOVWCS R11, DX                         // 66410f42d3
+	CMOVWCS (BX), R11                       // 66440f421b
+	CMOVWCS (R11), R11                      // 66450f421b
+	CMOVWCS DX, R11                         // 66440f42da
+	CMOVWCS R11, R11                        // 66450f42db
+	CMOVLCS (BX), DX                        // 0f4213
+	CMOVLCS (R11), DX                       // 410f4213
+	CMOVLCS DX, DX                          // 0f42d2
+	CMOVLCS R11, DX                         // 410f42d3
+	CMOVLCS (BX), R11                       // 440f421b
+	CMOVLCS (R11), R11                      // 450f421b
+	CMOVLCS DX, R11                         // 440f42da
+	CMOVLCS R11, R11                        // 450f42db
+	CMOVQCS (BX), DX                        // 480f4213
+	CMOVQCS (R11), DX                       // 490f4213
+	CMOVQCS DX, DX                          // 480f42d2
+	CMOVQCS R11, DX                         // 490f42d3
+	CMOVQCS (BX), R11                       // 4c0f421b
+	CMOVQCS (R11), R11                      // 4d0f421b
+	CMOVQCS DX, R11                         // 4c0f42da
+	CMOVQCS R11, R11                        // 4d0f42db
+	CMOVWLS (BX), DX                        // 660f4613
+	CMOVWLS (R11), DX                       // 66410f4613
+	CMOVWLS DX, DX                          // 660f46d2
+	CMOVWLS R11, DX                         // 66410f46d3
+	CMOVWLS (BX), R11                       // 66440f461b
+	CMOVWLS (R11), R11                      // 66450f461b
+	CMOVWLS DX, R11                         // 66440f46da
+	CMOVWLS R11, R11                        // 66450f46db
+	CMOVLLS (BX), DX                        // 0f4613
+	CMOVLLS (R11), DX                       // 410f4613
+	CMOVLLS DX, DX                          // 0f46d2
+	CMOVLLS R11, DX                         // 410f46d3
+	CMOVLLS (BX), R11                       // 440f461b
+	CMOVLLS (R11), R11                      // 450f461b
+	CMOVLLS DX, R11                         // 440f46da
+	CMOVLLS R11, R11                        // 450f46db
+	CMOVQLS (BX), DX                        // 480f4613
+	CMOVQLS (R11), DX                       // 490f4613
+	CMOVQLS DX, DX                          // 480f46d2
+	CMOVQLS R11, DX                         // 490f46d3
+	CMOVQLS (BX), R11                       // 4c0f461b
+	CMOVQLS (R11), R11                      // 4d0f461b
+	CMOVQLS DX, R11                         // 4c0f46da
+	CMOVQLS R11, R11                        // 4d0f46db
+	CMOVWEQ (BX), DX                        // 660f4413
+	CMOVWEQ (R11), DX                       // 66410f4413
+	CMOVWEQ DX, DX                          // 660f44d2
+	CMOVWEQ R11, DX                         // 66410f44d3
+	CMOVWEQ (BX), R11                       // 66440f441b
+	CMOVWEQ (R11), R11                      // 66450f441b
+	CMOVWEQ DX, R11                         // 66440f44da
+	CMOVWEQ R11, R11                        // 66450f44db
+	CMOVLEQ (BX), DX                        // 0f4413
+	CMOVLEQ (R11), DX                       // 410f4413
+	CMOVLEQ DX, DX                          // 0f44d2
+	CMOVLEQ R11, DX                         // 410f44d3
+	CMOVLEQ (BX), R11                       // 440f441b
+	CMOVLEQ (R11), R11                      // 450f441b
+	CMOVLEQ DX, R11                         // 440f44da
+	CMOVLEQ R11, R11                        // 450f44db
+	CMOVQEQ (BX), DX                        // 480f4413
+	CMOVQEQ (R11), DX                       // 490f4413
+	CMOVQEQ DX, DX                          // 480f44d2
+	CMOVQEQ R11, DX                         // 490f44d3
+	CMOVQEQ (BX), R11                       // 4c0f441b
+	CMOVQEQ (R11), R11                      // 4d0f441b
+	CMOVQEQ DX, R11                         // 4c0f44da
+	CMOVQEQ R11, R11                        // 4d0f44db
+	CMOVWGT (BX), DX                        // 660f4f13
+	CMOVWGT (R11), DX                       // 66410f4f13
+	CMOVWGT DX, DX                          // 660f4fd2
+	CMOVWGT R11, DX                         // 66410f4fd3
+	CMOVWGT (BX), R11                       // 66440f4f1b
+	CMOVWGT (R11), R11                      // 66450f4f1b
+	CMOVWGT DX, R11                         // 66440f4fda
+	CMOVWGT R11, R11                        // 66450f4fdb
+	CMOVLGT (BX), DX                        // 0f4f13
+	CMOVLGT (R11), DX                       // 410f4f13
+	CMOVLGT DX, DX                          // 0f4fd2
+	CMOVLGT R11, DX                         // 410f4fd3
+	CMOVLGT (BX), R11                       // 440f4f1b
+	CMOVLGT (R11), R11                      // 450f4f1b
+	CMOVLGT DX, R11                         // 440f4fda
+	CMOVLGT R11, R11                        // 450f4fdb
+	CMOVQGT (BX), DX                        // 480f4f13
+	CMOVQGT (R11), DX                       // 490f4f13
+	CMOVQGT DX, DX                          // 480f4fd2
+	CMOVQGT R11, DX                         // 490f4fd3
+	CMOVQGT (BX), R11                       // 4c0f4f1b
+	CMOVQGT (R11), R11                      // 4d0f4f1b
+	CMOVQGT DX, R11                         // 4c0f4fda
+	CMOVQGT R11, R11                        // 4d0f4fdb
+	CMOVWGE (BX), DX                        // 660f4d13
+	CMOVWGE (R11), DX                       // 66410f4d13
+	CMOVWGE DX, DX                          // 660f4dd2
+	CMOVWGE R11, DX                         // 66410f4dd3
+	CMOVWGE (BX), R11                       // 66440f4d1b
+	CMOVWGE (R11), R11                      // 66450f4d1b
+	CMOVWGE DX, R11                         // 66440f4dda
+	CMOVWGE R11, R11                        // 66450f4ddb
+	CMOVLGE (BX), DX                        // 0f4d13
+	CMOVLGE (R11), DX                       // 410f4d13
+	CMOVLGE DX, DX                          // 0f4dd2
+	CMOVLGE R11, DX                         // 410f4dd3
+	CMOVLGE (BX), R11                       // 440f4d1b
+	CMOVLGE (R11), R11                      // 450f4d1b
+	CMOVLGE DX, R11                         // 440f4dda
+	CMOVLGE R11, R11                        // 450f4ddb
+	CMOVQGE (BX), DX                        // 480f4d13
+	CMOVQGE (R11), DX                       // 490f4d13
+	CMOVQGE DX, DX                          // 480f4dd2
+	CMOVQGE R11, DX                         // 490f4dd3
+	CMOVQGE (BX), R11                       // 4c0f4d1b
+	CMOVQGE (R11), R11                      // 4d0f4d1b
+	CMOVQGE DX, R11                         // 4c0f4dda
+	CMOVQGE R11, R11                        // 4d0f4ddb
+	CMOVWLT (BX), DX                        // 660f4c13
+	CMOVWLT (R11), DX                       // 66410f4c13
+	CMOVWLT DX, DX                          // 660f4cd2
+	CMOVWLT R11, DX                         // 66410f4cd3
+	CMOVWLT (BX), R11                       // 66440f4c1b
+	CMOVWLT (R11), R11                      // 66450f4c1b
+	CMOVWLT DX, R11                         // 66440f4cda
+	CMOVWLT R11, R11                        // 66450f4cdb
+	CMOVLLT (BX), DX                        // 0f4c13
+	CMOVLLT (R11), DX                       // 410f4c13
+	CMOVLLT DX, DX                          // 0f4cd2
+	CMOVLLT R11, DX                         // 410f4cd3
+	CMOVLLT (BX), R11                       // 440f4c1b
+	CMOVLLT (R11), R11                      // 450f4c1b
+	CMOVLLT DX, R11                         // 440f4cda
+	CMOVLLT R11, R11                        // 450f4cdb
+	CMOVQLT (BX), DX                        // 480f4c13
+	CMOVQLT (R11), DX                       // 490f4c13
+	CMOVQLT DX, DX                          // 480f4cd2
+	CMOVQLT R11, DX                         // 490f4cd3
+	CMOVQLT (BX), R11                       // 4c0f4c1b
+	CMOVQLT (R11), R11                      // 4d0f4c1b
+	CMOVQLT DX, R11                         // 4c0f4cda
+	CMOVQLT R11, R11                        // 4d0f4cdb
+	CMOVWLE (BX), DX                        // 660f4e13
+	CMOVWLE (R11), DX                       // 66410f4e13
+	CMOVWLE DX, DX                          // 660f4ed2
+	CMOVWLE R11, DX                         // 66410f4ed3
+	CMOVWLE (BX), R11                       // 66440f4e1b
+	CMOVWLE (R11), R11                      // 66450f4e1b
+	CMOVWLE DX, R11                         // 66440f4eda
+	CMOVWLE R11, R11                        // 66450f4edb
+	CMOVLLE (BX), DX                        // 0f4e13
+	CMOVLLE (R11), DX                       // 410f4e13
+	CMOVLLE DX, DX                          // 0f4ed2
+	CMOVLLE R11, DX                         // 410f4ed3
+	CMOVLLE (BX), R11                       // 440f4e1b
+	CMOVLLE (R11), R11                      // 450f4e1b
+	CMOVLLE DX, R11                         // 440f4eda
+	CMOVLLE R11, R11                        // 450f4edb
+	CMOVQLE (BX), DX                        // 480f4e13
+	CMOVQLE (R11), DX                       // 490f4e13
+	CMOVQLE DX, DX                          // 480f4ed2
+	CMOVQLE R11, DX                         // 490f4ed3
+	CMOVQLE (BX), R11                       // 4c0f4e1b
+	CMOVQLE (R11), R11                      // 4d0f4e1b
+	CMOVQLE DX, R11                         // 4c0f4eda
+	CMOVQLE R11, R11                        // 4d0f4edb
+	CMOVWNE (BX), DX                        // 660f4513
+	CMOVWNE (R11), DX                       // 66410f4513
+	CMOVWNE DX, DX                          // 660f45d2
+	CMOVWNE R11, DX                         // 66410f45d3
+	CMOVWNE (BX), R11                       // 66440f451b
+	CMOVWNE (R11), R11                      // 66450f451b
+	CMOVWNE DX, R11                         // 66440f45da
+	CMOVWNE R11, R11                        // 66450f45db
+	CMOVLNE (BX), DX                        // 0f4513
+	CMOVLNE (R11), DX                       // 410f4513
+	CMOVLNE DX, DX                          // 0f45d2
+	CMOVLNE R11, DX                         // 410f45d3
+	CMOVLNE (BX), R11                       // 440f451b
+	CMOVLNE (R11), R11                      // 450f451b
+	CMOVLNE DX, R11                         // 440f45da
+	CMOVLNE R11, R11                        // 450f45db
+	CMOVQNE (BX), DX                        // 480f4513
+	CMOVQNE (R11), DX                       // 490f4513
+	CMOVQNE DX, DX                          // 480f45d2
+	CMOVQNE R11, DX                         // 490f45d3
+	CMOVQNE (BX), R11                       // 4c0f451b
+	CMOVQNE (R11), R11                      // 4d0f451b
+	CMOVQNE DX, R11                         // 4c0f45da
+	CMOVQNE R11, R11                        // 4d0f45db
+	CMOVWOC (BX), DX                        // 660f4113
+	CMOVWOC (R11), DX                       // 66410f4113
+	CMOVWOC DX, DX                          // 660f41d2
+	CMOVWOC R11, DX                         // 66410f41d3
+	CMOVWOC (BX), R11                       // 66440f411b
+	CMOVWOC (R11), R11                      // 66450f411b
+	CMOVWOC DX, R11                         // 66440f41da
+	CMOVWOC R11, R11                        // 66450f41db
+	CMOVLOC (BX), DX                        // 0f4113
+	CMOVLOC (R11), DX                       // 410f4113
+	CMOVLOC DX, DX                          // 0f41d2
+	CMOVLOC R11, DX                         // 410f41d3
+	CMOVLOC (BX), R11                       // 440f411b
+	CMOVLOC (R11), R11                      // 450f411b
+	CMOVLOC DX, R11                         // 440f41da
+	CMOVLOC R11, R11                        // 450f41db
+	CMOVQOC (BX), DX                        // 480f4113
+	CMOVQOC (R11), DX                       // 490f4113
+	CMOVQOC DX, DX                          // 480f41d2
+	CMOVQOC R11, DX                         // 490f41d3
+	CMOVQOC (BX), R11                       // 4c0f411b
+	CMOVQOC (R11), R11                      // 4d0f411b
+	CMOVQOC DX, R11                         // 4c0f41da
+	CMOVQOC R11, R11                        // 4d0f41db
+	CMOVWPC (BX), DX                        // 660f4b13
+	CMOVWPC (R11), DX                       // 66410f4b13
+	CMOVWPC DX, DX                          // 660f4bd2
+	CMOVWPC R11, DX                         // 66410f4bd3
+	CMOVWPC (BX), R11                       // 66440f4b1b
+	CMOVWPC (R11), R11                      // 66450f4b1b
+	CMOVWPC DX, R11                         // 66440f4bda
+	CMOVWPC R11, R11                        // 66450f4bdb
+	CMOVLPC (BX), DX                        // 0f4b13
+	CMOVLPC (R11), DX                       // 410f4b13
+	CMOVLPC DX, DX                          // 0f4bd2
+	CMOVLPC R11, DX                         // 410f4bd3
+	CMOVLPC (BX), R11                       // 440f4b1b
+	CMOVLPC (R11), R11                      // 450f4b1b
+	CMOVLPC DX, R11                         // 440f4bda
+	CMOVLPC R11, R11                        // 450f4bdb
+	CMOVQPC (BX), DX                        // 480f4b13
+	CMOVQPC (R11), DX                       // 490f4b13
+	CMOVQPC DX, DX                          // 480f4bd2
+	CMOVQPC R11, DX                         // 490f4bd3
+	CMOVQPC (BX), R11                       // 4c0f4b1b
+	CMOVQPC (R11), R11                      // 4d0f4b1b
+	CMOVQPC DX, R11                         // 4c0f4bda
+	CMOVQPC R11, R11                        // 4d0f4bdb
+	CMOVWPL (BX), DX                        // 660f4913
+	CMOVWPL (R11), DX                       // 66410f4913
+	CMOVWPL DX, DX                          // 660f49d2
+	CMOVWPL R11, DX                         // 66410f49d3
+	CMOVWPL (BX), R11                       // 66440f491b
+	CMOVWPL (R11), R11                      // 66450f491b
+	CMOVWPL DX, R11                         // 66440f49da
+	CMOVWPL R11, R11                        // 66450f49db
+	CMOVLPL (BX), DX                        // 0f4913
+	CMOVLPL (R11), DX                       // 410f4913
+	CMOVLPL DX, DX                          // 0f49d2
+	CMOVLPL R11, DX                         // 410f49d3
+	CMOVLPL (BX), R11                       // 440f491b
+	CMOVLPL (R11), R11                      // 450f491b
+	CMOVLPL DX, R11                         // 440f49da
+	CMOVLPL R11, R11                        // 450f49db
+	CMOVQPL (BX), DX                        // 480f4913
+	CMOVQPL (R11), DX                       // 490f4913
+	CMOVQPL DX, DX                          // 480f49d2
+	CMOVQPL R11, DX                         // 490f49d3
+	CMOVQPL (BX), R11                       // 4c0f491b
+	CMOVQPL (R11), R11                      // 4d0f491b
+	CMOVQPL DX, R11                         // 4c0f49da
+	CMOVQPL R11, R11                        // 4d0f49db
+	CMOVWOS (BX), DX                        // 660f4013
+	CMOVWOS (R11), DX                       // 66410f4013
+	CMOVWOS DX, DX                          // 660f40d2
+	CMOVWOS R11, DX                         // 66410f40d3
+	CMOVWOS (BX), R11                       // 66440f401b
+	CMOVWOS (R11), R11                      // 66450f401b
+	CMOVWOS DX, R11                         // 66440f40da
+	CMOVWOS R11, R11                        // 66450f40db
+	CMOVLOS (BX), DX                        // 0f4013
+	CMOVLOS (R11), DX                       // 410f4013
+	CMOVLOS DX, DX                          // 0f40d2
+	CMOVLOS R11, DX                         // 410f40d3
+	CMOVLOS (BX), R11                       // 440f401b
+	CMOVLOS (R11), R11                      // 450f401b
+	CMOVLOS DX, R11                         // 440f40da
+	CMOVLOS R11, R11                        // 450f40db
+	CMOVQOS (BX), DX                        // 480f4013
+	CMOVQOS (R11), DX                       // 490f4013
+	CMOVQOS DX, DX                          // 480f40d2
+	CMOVQOS R11, DX                         // 490f40d3
+	CMOVQOS (BX), R11                       // 4c0f401b
+	CMOVQOS (R11), R11                      // 4d0f401b
+	CMOVQOS DX, R11                         // 4c0f40da
+	CMOVQOS R11, R11                        // 4d0f40db
+	CMOVWPS (BX), DX                        // 660f4a13
+	CMOVWPS (R11), DX                       // 66410f4a13
+	CMOVWPS DX, DX                          // 660f4ad2
+	CMOVWPS R11, DX                         // 66410f4ad3
+	CMOVWPS (BX), R11                       // 66440f4a1b
+	CMOVWPS (R11), R11                      // 66450f4a1b
+	CMOVWPS DX, R11                         // 66440f4ada
+	CMOVWPS R11, R11                        // 66450f4adb
+	CMOVLPS (BX), DX                        // 0f4a13
+	CMOVLPS (R11), DX                       // 410f4a13
+	CMOVLPS DX, DX                          // 0f4ad2
+	CMOVLPS R11, DX                         // 410f4ad3
+	CMOVLPS (BX), R11                       // 440f4a1b
+	CMOVLPS (R11), R11                      // 450f4a1b
+	CMOVLPS DX, R11                         // 440f4ada
+	CMOVLPS R11, R11                        // 450f4adb
+	CMOVQPS (BX), DX                        // 480f4a13
+	CMOVQPS (R11), DX                       // 490f4a13
+	CMOVQPS DX, DX                          // 480f4ad2
+	CMOVQPS R11, DX                         // 490f4ad3
+	CMOVQPS (BX), R11                       // 4c0f4a1b
+	CMOVQPS (R11), R11                      // 4d0f4a1b
+	CMOVQPS DX, R11                         // 4c0f4ada
+	CMOVQPS R11, R11                        // 4d0f4adb
+	CMOVWMI (BX), DX                        // 660f4813
+	CMOVWMI (R11), DX                       // 66410f4813
+	CMOVWMI DX, DX                          // 660f48d2
+	CMOVWMI R11, DX                         // 66410f48d3
+	CMOVWMI (BX), R11                       // 66440f481b
+	CMOVWMI (R11), R11                      // 66450f481b
+	CMOVWMI DX, R11                         // 66440f48da
+	CMOVWMI R11, R11                        // 66450f48db
+	CMOVLMI (BX), DX                        // 0f4813
+	CMOVLMI (R11), DX                       // 410f4813
+	CMOVLMI DX, DX                          // 0f48d2
+	CMOVLMI R11, DX                         // 410f48d3
+	CMOVLMI (BX), R11                       // 440f481b
+	CMOVLMI (R11), R11                      // 450f481b
+	CMOVLMI DX, R11                         // 440f48da
+	CMOVLMI R11, R11                        // 450f48db
+	CMOVQMI (BX), DX                        // 480f4813
+	CMOVQMI (R11), DX                       // 490f4813
+	CMOVQMI DX, DX                          // 480f48d2
+	CMOVQMI R11, DX                         // 490f48d3
+	CMOVQMI (BX), R11                       // 4c0f481b
+	CMOVQMI (R11), R11                      // 4d0f481b
+	CMOVQMI DX, R11                         // 4c0f48da
+	CMOVQMI R11, R11                        // 4d0f48db
+	CMPB AL, $7                             // 3c07
+	CMPW AX, $61731                         // 663d23f1
+	CMPL AX, $4045620583                    // 3d674523f1
+	CMPQ AX, $-249346713                    // 483d674523f1
+	CMPW (BX), $61731                       // 66813b23f1
+	CMPW (R11), $61731                      // 6641813b23f1
+	CMPW DX, $61731                         // 6681fa23f1
+	CMPW R11, $61731                        // 664181fb23f1
+	CMPW (BX), $7                           // 66833b07
+	CMPW (R11), $7                          // 6641833b07
+	CMPW DX, $7                             // 6683fa07
+	CMPW R11, $7                            // 664183fb07
+	CMPW (BX), DX                           // 663913
+	CMPW (BX), R11                          // 6644391b
+	CMPW (R11), DX                          // 66413913
+	CMPW (R11), R11                         // 6645391b
+	CMPW DX, DX                             // 6639d2 or 663bd2
+	CMPW DX, R11                            // 664439da or 66413bd3
+	CMPW R11, DX                            // 664139d3 or 66443bda
+	CMPW R11, R11                           // 664539db or 66453bdb
+	CMPL (BX), $4045620583                  // 813b674523f1
+	CMPL (R11), $4045620583                 // 41813b674523f1
+	CMPL DX, $4045620583                    // 81fa674523f1
+	CMPL R11, $4045620583                   // 4181fb674523f1
+	CMPL (BX), $7                           // 833b07
+	CMPL (R11), $7                          // 41833b07
+	CMPL DX, $7                             // 83fa07
+	CMPL R11, $7                            // 4183fb07
+	CMPL (BX), DX                           // 3913
+	CMPL (BX), R11                          // 44391b
+	CMPL (R11), DX                          // 413913
+	CMPL (R11), R11                         // 45391b
+	CMPL DX, DX                             // 39d2 or 3bd2
+	CMPL DX, R11                            // 4439da or 413bd3
+	CMPL R11, DX                            // 4139d3 or 443bda
+	CMPL R11, R11                           // 4539db or 453bdb
+	CMPQ (BX), $-249346713                  // 48813b674523f1
+	CMPQ (R11), $-249346713                 // 49813b674523f1
+	CMPQ DX, $-249346713                    // 4881fa674523f1
+	CMPQ R11, $-249346713                   // 4981fb674523f1
+	CMPQ (BX), $7                           // 48833b07
+	CMPQ (R11), $7                          // 49833b07
+	CMPQ DX, $7                             // 4883fa07
+	CMPQ R11, $7                            // 4983fb07
+	CMPQ (BX), DX                           // 483913
+	CMPQ (BX), R11                          // 4c391b
+	CMPQ (R11), DX                          // 493913
+	CMPQ (R11), R11                         // 4d391b
+	CMPQ DX, DX                             // 4839d2 or 483bd2
+	CMPQ DX, R11                            // 4c39da or 493bd3
+	CMPQ R11, DX                            // 4939d3 or 4c3bda
+	CMPQ R11, R11                           // 4d39db or 4d3bdb
+	CMPB (BX), $7                           // 803b07
+	CMPB (R11), $7                          // 41803b07
+	CMPB DL, $7                             // 80fa07
+	CMPB R11, $7                            // 4180fb07
+	CMPB (BX), DL                           // 3813
+	CMPB (BX), R11                          // 44381b
+	CMPB (R11), DL                          // 413813
+	CMPB (R11), R11                         // 45381b
+	CMPB DL, DL                             // 38d2 or 3ad2
+	CMPB DL, R11                            // 4438da or 413ad3
+	CMPB R11, DL                            // 4138d3 or 443ada
+	CMPB R11, R11                           // 4538db or 453adb
+	CMPW DX, (BX)                           // 663b13
+	CMPW DX, (R11)                          // 66413b13
+	CMPW R11, (BX)                          // 66443b1b
+	CMPW R11, (R11)                         // 66453b1b
+	CMPL DX, (BX)                           // 3b13
+	CMPL DX, (R11)                          // 413b13
+	CMPL R11, (BX)                          // 443b1b
+	CMPL R11, (R11)                         // 453b1b
+	CMPQ DX, (BX)                           // 483b13
+	CMPQ DX, (R11)                          // 493b13
+	CMPQ R11, (BX)                          // 4c3b1b
+	CMPQ R11, (R11)                         // 4d3b1b
+	CMPB DL, (BX)                           // 3a13
+	CMPB DL, (R11)                          // 413a13
+	CMPB R11, (BX)                          // 443a1b
+	CMPB R11, (R11)                         // 453a1b
+	//TODO: CMPPD $7, X2, (BX)              // 660fc21307
+	//TODO: CMPPD $7, X2, (R11)             // 66410fc21307
+	//TODO: CMPPD $7, X2, X2                // 660fc2d207
+	//TODO: CMPPD $7, X2, X11               // 66410fc2d307
+	//TODO: CMPPD $7, X11, (BX)             // 66440fc21b07
+	//TODO: CMPPD $7, X11, (R11)            // 66450fc21b07
+	//TODO: CMPPD $7, X11, X2               // 66440fc2da07
+	//TODO: CMPPD $7, X11, X11              // 66450fc2db07
+	//TODO: CMPPS $7, X2, (BX)              // 0fc21307
+	//TODO: CMPPS $7, X2, (R11)             // 410fc21307
+	//TODO: CMPPS $7, X2, X2                // 0fc2d207
+	//TODO: CMPPS $7, X2, X11               // 410fc2d307
+	//TODO: CMPPS $7, X11, (BX)             // 440fc21b07
+	//TODO: CMPPS $7, X11, (R11)            // 450fc21b07
+	//TODO: CMPPS $7, X11, X2               // 440fc2da07
+	//TODO: CMPPS $7, X11, X11              // 450fc2db07
+	CMPSB                                   // a6
+	CMPSL                                   // a7
+	//TODO: CMPSD $7, X2, (BX)              // f20fc21307
+	//TODO: CMPSD $7, X2, (R11)             // f2410fc21307
+	//TODO: CMPSD $7, X2, X2                // f20fc2d207
+	//TODO: CMPSD $7, X2, X11               // f2410fc2d307
+	//TODO: CMPSD $7, X11, (BX)             // f2440fc21b07
+	//TODO: CMPSD $7, X11, (R11)            // f2450fc21b07
+	//TODO: CMPSD $7, X11, X2               // f2440fc2da07
+	//TODO: CMPSD $7, X11, X11              // f2450fc2db07
+	CMPSQ                                   // 48a7
+	//TODO: CMPSS $7, X2, (BX)              // f30fc21307
+	//TODO: CMPSS $7, X2, (R11)             // f3410fc21307
+	//TODO: CMPSS $7, X2, X2                // f30fc2d207
+	//TODO: CMPSS $7, X2, X11               // f3410fc2d307
+	//TODO: CMPSS $7, X11, (BX)             // f3440fc21b07
+	//TODO: CMPSS $7, X11, (R11)            // f3450fc21b07
+	//TODO: CMPSS $7, X11, X2               // f3440fc2da07
+	//TODO: CMPSS $7, X11, X11              // f3450fc2db07
+	CMPSW                                   // 66a7
+	CMPXCHGW DX, (BX)                       // 660fb113
+	CMPXCHGW R11, (BX)                      // 66440fb11b
+	CMPXCHGW DX, (R11)                      // 66410fb113
+	CMPXCHGW R11, (R11)                     // 66450fb11b
+	CMPXCHGW DX, DX                         // 660fb1d2
+	CMPXCHGW R11, DX                        // 66440fb1da
+	CMPXCHGW DX, R11                        // 66410fb1d3
+	CMPXCHGW R11, R11                       // 66450fb1db
+	CMPXCHGL DX, (BX)                       // 0fb113
+	CMPXCHGL R11, (BX)                      // 440fb11b
+	CMPXCHGL DX, (R11)                      // 410fb113
+	CMPXCHGL R11, (R11)                     // 450fb11b
+	CMPXCHGL DX, DX                         // 0fb1d2
+	CMPXCHGL R11, DX                        // 440fb1da
+	CMPXCHGL DX, R11                        // 410fb1d3
+	CMPXCHGL R11, R11                       // 450fb1db
+	CMPXCHGQ DX, (BX)                       // 480fb113
+	CMPXCHGQ R11, (BX)                      // 4c0fb11b
+	CMPXCHGQ DX, (R11)                      // 490fb113
+	CMPXCHGQ R11, (R11)                     // 4d0fb11b
+	CMPXCHGQ DX, DX                         // 480fb1d2
+	CMPXCHGQ R11, DX                        // 4c0fb1da
+	CMPXCHGQ DX, R11                        // 490fb1d3
+	CMPXCHGQ R11, R11                       // 4d0fb1db
+	CMPXCHGB DL, (BX)                       // 0fb013
+	CMPXCHGB R11, (BX)                      // 440fb01b
+	CMPXCHGB DL, (R11)                      // 410fb013
+	CMPXCHGB R11, (R11)                     // 450fb01b
+	CMPXCHGB DL, DL                         // 0fb0d2
+	CMPXCHGB R11, DL                        // 440fb0da
+	CMPXCHGB DL, R11                        // 410fb0d3
+	CMPXCHGB R11, R11                       // 450fb0db
+	//TODO: CMPXCHG16B (BX)                 // 480fc70b
+	//TODO: CMPXCHG16B (R11)                // 490fc70b
+	CMPXCHG8B (BX)                          // 0fc70b
+	CMPXCHG8B (R11)                         // 410fc70b
+	COMISD (BX), X2                         // 660f2f13
+	COMISD (R11), X2                        // 66410f2f13
+	COMISD X2, X2                           // 660f2fd2
+	COMISD X11, X2                          // 66410f2fd3
+	COMISD (BX), X11                        // 66440f2f1b
+	COMISD (R11), X11                       // 66450f2f1b
+	COMISD X2, X11                          // 66440f2fda
+	COMISD X11, X11                         // 66450f2fdb
+	COMISS (BX), X2                         // 0f2f13
+	COMISS (R11), X2                        // 410f2f13
+	COMISS X2, X2                           // 0f2fd2
+	COMISS X11, X2                          // 410f2fd3
+	COMISS (BX), X11                        // 440f2f1b
+	COMISS (R11), X11                       // 450f2f1b
+	COMISS X2, X11                          // 440f2fda
+	COMISS X11, X11                         // 450f2fdb
+	CPUID                                   // 0fa2
+	CQO                                     // 4899
+	//TODO: CRC32W (BX), DX                 // 66f20f38f113
+	//TODO: CRC32W (R11), DX                // 66f2410f38f113
+	//TODO: CRC32W DX, DX                   // 66f20f38f1d2
+	//TODO: CRC32W R11, DX                  // 66f2410f38f1d3
+	//TODO: CRC32W (BX), R11                // 66f2440f38f11b
+	//TODO: CRC32W (R11), R11               // 66f2450f38f11b
+	//TODO: CRC32W DX, R11                  // 66f2440f38f1da
+	//TODO: CRC32W R11, R11                 // 66f2450f38f1db
+	//TODO: CRC32L (BX), DX                 // f20f38f113
+	//TODO: CRC32L (R11), DX                // f2410f38f113
+	//TODO: CRC32L DX, DX                   // f20f38f1d2
+	//TODO: CRC32L R11, DX                  // f2410f38f1d3
+	//TODO: CRC32L (BX), R11                // f2440f38f11b
+	//TODO: CRC32L (R11), R11               // f2450f38f11b
+	//TODO: CRC32L DX, R11                  // f2440f38f1da
+	//TODO: CRC32L R11, R11                 // f2450f38f1db
+	//TODO: CRC32B (BX), DX                 // f20f38f013 or f2480f38f013
+	//TODO: CRC32B (R11), DX                // f2410f38f013 or f2490f38f013
+	//TODO: CRC32B DL, DX                   // f20f38f0d2 or f2480f38f0d2
+	//TODO: CRC32B R11, DX                  // f2410f38f0d3 or f2490f38f0d3
+	//TODO: CRC32B (BX), R11                // f2440f38f01b or f24c0f38f01b
+	//TODO: CRC32B (R11), R11               // f2450f38f01b or f24d0f38f01b
+	//TODO: CRC32B DL, R11                  // f2440f38f0da or f24c0f38f0da
+	//TODO: CRC32B R11, R11                 // f2450f38f0db or f24d0f38f0db
+	CRC32Q (BX), DX                         // f2480f38f113
+	CRC32Q (R11), DX                        // f2490f38f113
+	CRC32Q DX, DX                           // f2480f38f1d2
+	CRC32Q R11, DX                          // f2490f38f1d3
+	CRC32Q (BX), R11                        // f24c0f38f11b
+	CRC32Q (R11), R11                       // f24d0f38f11b
+	CRC32Q DX, R11                          // f24c0f38f1da
+	CRC32Q R11, R11                         // f24d0f38f1db
+	CVTPL2PD (BX), X2                       // f30fe613
+	CVTPL2PD (R11), X2                      // f3410fe613
+	CVTPL2PD X2, X2                         // f30fe6d2
+	CVTPL2PD X11, X2                        // f3410fe6d3
+	CVTPL2PD (BX), X11                      // f3440fe61b
+	CVTPL2PD (R11), X11                     // f3450fe61b
+	CVTPL2PD X2, X11                        // f3440fe6da
+	CVTPL2PD X11, X11                       // f3450fe6db
+	CVTPL2PS (BX), X2                       // 0f5b13
+	CVTPL2PS (R11), X2                      // 410f5b13
+	CVTPL2PS X2, X2                         // 0f5bd2
+	CVTPL2PS X11, X2                        // 410f5bd3
+	CVTPL2PS (BX), X11                      // 440f5b1b
+	CVTPL2PS (R11), X11                     // 450f5b1b
+	CVTPL2PS X2, X11                        // 440f5bda
+	CVTPL2PS X11, X11                       // 450f5bdb
+	CVTPD2PL (BX), X2                       // f20fe613
+	CVTPD2PL (R11), X2                      // f2410fe613
+	CVTPD2PL X2, X2                         // f20fe6d2
+	CVTPD2PL X11, X2                        // f2410fe6d3
+	CVTPD2PL (BX), X11                      // f2440fe61b
+	CVTPD2PL (R11), X11                     // f2450fe61b
+	CVTPD2PL X2, X11                        // f2440fe6da
+	CVTPD2PL X11, X11                       // f2450fe6db
+	//TODO: CVTPD2PI (BX), M2               // 660f2d13
+	//TODO: CVTPD2PI (R11), M2              // 66410f2d13
+	//TODO: CVTPD2PI X2, M2                 // 660f2dd2
+	//TODO: CVTPD2PI X11, M2                // 66410f2dd3
+	//TODO: CVTPD2PI (BX), M3               // 660f2d1b
+	//TODO: CVTPD2PI (R11), M3              // 66410f2d1b
+	//TODO: CVTPD2PI X2, M3                 // 660f2dda
+	//TODO: CVTPD2PI X11, M3                // 66410f2ddb
+	CVTPD2PS (BX), X2                       // 660f5a13
+	CVTPD2PS (R11), X2                      // 66410f5a13
+	CVTPD2PS X2, X2                         // 660f5ad2
+	CVTPD2PS X11, X2                        // 66410f5ad3
+	CVTPD2PS (BX), X11                      // 66440f5a1b
+	CVTPD2PS (R11), X11                     // 66450f5a1b
+	CVTPD2PS X2, X11                        // 66440f5ada
+	CVTPD2PS X11, X11                       // 66450f5adb
+	//TODO: CVTPI2PD (BX), X2               // 660f2a13
+	//TODO: CVTPI2PD (R11), X2              // 66410f2a13
+	//TODO: CVTPI2PD M2, X2                 // 660f2ad2
+	//TODO: CVTPI2PD M3, X2                 // 660f2ad3
+	//TODO: CVTPI2PD (BX), X11              // 66440f2a1b
+	//TODO: CVTPI2PD (R11), X11             // 66450f2a1b
+	//TODO: CVTPI2PD M2, X11                // 66440f2ada
+	//TODO: CVTPI2PD M3, X11                // 66440f2adb
+	//TODO: CVTPI2PS (BX), X2               // 0f2a13
+	//TODO: CVTPI2PS (R11), X2              // 410f2a13
+	//TODO: CVTPI2PS M2, X2                 // 0f2ad2
+	//TODO: CVTPI2PS M3, X2                 // 0f2ad3
+	//TODO: CVTPI2PS (BX), X11              // 440f2a1b
+	//TODO: CVTPI2PS (R11), X11             // 450f2a1b
+	//TODO: CVTPI2PS M2, X11                // 440f2ada
+	//TODO: CVTPI2PS M3, X11                // 440f2adb
+	CVTPS2PL (BX), X2                       // 660f5b13
+	CVTPS2PL (R11), X2                      // 66410f5b13
+	CVTPS2PL X2, X2                         // 660f5bd2
+	CVTPS2PL X11, X2                        // 66410f5bd3
+	CVTPS2PL (BX), X11                      // 66440f5b1b
+	CVTPS2PL (R11), X11                     // 66450f5b1b
+	CVTPS2PL X2, X11                        // 66440f5bda
+	CVTPS2PL X11, X11                       // 66450f5bdb
+	CVTPS2PD (BX), X2                       // 0f5a13
+	CVTPS2PD (R11), X2                      // 410f5a13
+	CVTPS2PD X2, X2                         // 0f5ad2
+	CVTPS2PD X11, X2                        // 410f5ad3
+	CVTPS2PD (BX), X11                      // 440f5a1b
+	CVTPS2PD (R11), X11                     // 450f5a1b
+	CVTPS2PD X2, X11                        // 440f5ada
+	CVTPS2PD X11, X11                       // 450f5adb
+	//TODO: CVTPS2PI (BX), M2               // 0f2d13
+	//TODO: CVTPS2PI (R11), M2              // 410f2d13
+	//TODO: CVTPS2PI X2, M2                 // 0f2dd2
+	//TODO: CVTPS2PI X11, M2                // 410f2dd3
+	//TODO: CVTPS2PI (BX), M3               // 0f2d1b
+	//TODO: CVTPS2PI (R11), M3              // 410f2d1b
+	//TODO: CVTPS2PI X2, M3                 // 0f2dda
+	//TODO: CVTPS2PI X11, M3                // 410f2ddb
+	CVTSD2SL (BX), DX                       // f20f2d13 or f2480f2d13
+	CVTSD2SL (R11), DX                      // f2410f2d13 or f2490f2d13
+	CVTSD2SL X2, DX                         // f20f2dd2 or f2480f2dd2
+	CVTSD2SL X11, DX                        // f2410f2dd3 or f2490f2dd3
+	CVTSD2SL (BX), R11                      // f2440f2d1b or f24c0f2d1b
+	CVTSD2SL (R11), R11                     // f2450f2d1b or f24d0f2d1b
+	CVTSD2SL X2, R11                        // f2440f2dda or f24c0f2dda
+	CVTSD2SL X11, R11                       // f2450f2ddb or f24d0f2ddb
+	CVTSD2SS (BX), X2                       // f20f5a13
+	CVTSD2SS (R11), X2                      // f2410f5a13
+	CVTSD2SS X2, X2                         // f20f5ad2
+	CVTSD2SS X11, X2                        // f2410f5ad3
+	CVTSD2SS (BX), X11                      // f2440f5a1b
+	CVTSD2SS (R11), X11                     // f2450f5a1b
+	CVTSD2SS X2, X11                        // f2440f5ada
+	CVTSD2SS X11, X11                       // f2450f5adb
+	CVTSL2SD (BX), X2                       // f20f2a13
+	CVTSL2SD (R11), X2                      // f2410f2a13
+	CVTSL2SD DX, X2                         // f20f2ad2
+	CVTSL2SD R11, X2                        // f2410f2ad3
+	CVTSL2SD (BX), X11                      // f2440f2a1b
+	CVTSL2SD (R11), X11                     // f2450f2a1b
+	CVTSL2SD DX, X11                        // f2440f2ada
+	CVTSL2SD R11, X11                       // f2450f2adb
+	CVTSQ2SD (BX), X2                       // f2480f2a13
+	CVTSQ2SD (R11), X2                      // f2490f2a13
+	CVTSQ2SD DX, X2                         // f2480f2ad2
+	CVTSQ2SD R11, X2                        // f2490f2ad3
+	CVTSQ2SD (BX), X11                      // f24c0f2a1b
+	CVTSQ2SD (R11), X11                     // f24d0f2a1b
+	CVTSQ2SD DX, X11                        // f24c0f2ada
+	CVTSQ2SD R11, X11                       // f24d0f2adb
+	CVTSL2SS (BX), X2                       // f30f2a13
+	CVTSL2SS (R11), X2                      // f3410f2a13
+	CVTSL2SS DX, X2                         // f30f2ad2
+	CVTSL2SS R11, X2                        // f3410f2ad3
+	CVTSL2SS (BX), X11                      // f3440f2a1b
+	CVTSL2SS (R11), X11                     // f3450f2a1b
+	CVTSL2SS DX, X11                        // f3440f2ada
+	CVTSL2SS R11, X11                       // f3450f2adb
+	CVTSQ2SS (BX), X2                       // f3480f2a13
+	CVTSQ2SS (R11), X2                      // f3490f2a13
+	CVTSQ2SS DX, X2                         // f3480f2ad2
+	CVTSQ2SS R11, X2                        // f3490f2ad3
+	CVTSQ2SS (BX), X11                      // f34c0f2a1b
+	CVTSQ2SS (R11), X11                     // f34d0f2a1b
+	CVTSQ2SS DX, X11                        // f34c0f2ada
+	CVTSQ2SS R11, X11                       // f34d0f2adb
+	CVTSS2SD (BX), X2                       // f30f5a13
+	CVTSS2SD (R11), X2                      // f3410f5a13
+	CVTSS2SD X2, X2                         // f30f5ad2
+	CVTSS2SD X11, X2                        // f3410f5ad3
+	CVTSS2SD (BX), X11                      // f3440f5a1b
+	CVTSS2SD (R11), X11                     // f3450f5a1b
+	CVTSS2SD X2, X11                        // f3440f5ada
+	CVTSS2SD X11, X11                       // f3450f5adb
+	CVTSS2SL (BX), DX                       // f30f2d13 or f3480f2d13
+	CVTSS2SL (R11), DX                      // f3410f2d13 or f3490f2d13
+	CVTSS2SL X2, DX                         // f30f2dd2 or f3480f2dd2
+	CVTSS2SL X11, DX                        // f3410f2dd3 or f3490f2dd3
+	CVTSS2SL (BX), R11                      // f3440f2d1b or f34c0f2d1b
+	CVTSS2SL (R11), R11                     // f3450f2d1b or f34d0f2d1b
+	CVTSS2SL X2, R11                        // f3440f2dda or f34c0f2dda
+	CVTSS2SL X11, R11                       // f3450f2ddb or f34d0f2ddb
+	CVTTPD2PL (BX), X2                      // 660fe613
+	CVTTPD2PL (R11), X2                     // 66410fe613
+	CVTTPD2PL X2, X2                        // 660fe6d2
+	CVTTPD2PL X11, X2                       // 66410fe6d3
+	CVTTPD2PL (BX), X11                     // 66440fe61b
+	CVTTPD2PL (R11), X11                    // 66450fe61b
+	CVTTPD2PL X2, X11                       // 66440fe6da
+	CVTTPD2PL X11, X11                      // 66450fe6db
+	//TODO: CVTTPD2PI (BX), M2              // 660f2c13
+	//TODO: CVTTPD2PI (R11), M2             // 66410f2c13
+	//TODO: CVTTPD2PI X2, M2                // 660f2cd2
+	//TODO: CVTTPD2PI X11, M2               // 66410f2cd3
+	//TODO: CVTTPD2PI (BX), M3              // 660f2c1b
+	//TODO: CVTTPD2PI (R11), M3             // 66410f2c1b
+	//TODO: CVTTPD2PI X2, M3                // 660f2cda
+	//TODO: CVTTPD2PI X11, M3               // 66410f2cdb
+	CVTTPS2PL (BX), X2                      // f30f5b13
+	CVTTPS2PL (R11), X2                     // f3410f5b13
+	CVTTPS2PL X2, X2                        // f30f5bd2
+	CVTTPS2PL X11, X2                       // f3410f5bd3
+	CVTTPS2PL (BX), X11                     // f3440f5b1b
+	CVTTPS2PL (R11), X11                    // f3450f5b1b
+	CVTTPS2PL X2, X11                       // f3440f5bda
+	CVTTPS2PL X11, X11                      // f3450f5bdb
+	//TODO: CVTTPS2PI (BX), M2              // 0f2c13
+	//TODO: CVTTPS2PI (R11), M2             // 410f2c13
+	//TODO: CVTTPS2PI X2, M2                // 0f2cd2
+	//TODO: CVTTPS2PI X11, M2               // 410f2cd3
+	//TODO: CVTTPS2PI (BX), M3              // 0f2c1b
+	//TODO: CVTTPS2PI (R11), M3             // 410f2c1b
+	//TODO: CVTTPS2PI X2, M3                // 0f2cda
+	//TODO: CVTTPS2PI X11, M3               // 410f2cdb
+	CVTTSD2SL (BX), DX                      // f20f2c13 or f2480f2c13
+	CVTTSD2SL (R11), DX                     // f2410f2c13 or f2490f2c13
+	CVTTSD2SL X2, DX                        // f20f2cd2 or f2480f2cd2
+	CVTTSD2SL X11, DX                       // f2410f2cd3 or f2490f2cd3
+	CVTTSD2SL (BX), R11                     // f2440f2c1b or f24c0f2c1b
+	CVTTSD2SL (R11), R11                    // f2450f2c1b or f24d0f2c1b
+	CVTTSD2SL X2, R11                       // f2440f2cda or f24c0f2cda
+	CVTTSD2SL X11, R11                      // f2450f2cdb or f24d0f2cdb
+	CVTTSS2SL (BX), DX                      // f30f2c13 or f3480f2c13
+	CVTTSS2SL (R11), DX                     // f3410f2c13 or f3490f2c13
+	CVTTSS2SL X2, DX                        // f30f2cd2 or f3480f2cd2
+	CVTTSS2SL X11, DX                       // f3410f2cd3 or f3490f2cd3
+	CVTTSS2SL (BX), R11                     // f3440f2c1b or f34c0f2c1b
+	CVTTSS2SL (R11), R11                    // f3450f2c1b or f34d0f2c1b
+	CVTTSS2SL X2, R11                       // f3440f2cda or f34c0f2cda
+	CVTTSS2SL X11, R11                      // f3450f2cdb or f34d0f2cdb
+	CWD                                     // 6699
+	//TODO: CWDE                            // 98
+	DECW (BX)                               // 66ff0b
+	DECW (R11)                              // 6641ff0b
+	DECW DX                                 // 66ffca
+	DECW R11                                // 6641ffcb
+	DECL (BX)                               // ff0b
+	DECL (R11)                              // 41ff0b
+	DECL DX                                 // ffca
+	DECL R11                                // 41ffcb
+	DECQ (BX)                               // 48ff0b
+	DECQ (R11)                              // 49ff0b
+	DECQ DX                                 // 48ffca
+	DECQ R11                                // 49ffcb
+	DECB (BX)                               // fe0b
+	DECB (R11)                              // 41fe0b
+	DECB DL                                 // feca
+	DECB R11                                // 41fecb
+	DIVW (BX)                               // 66f733
+	DIVW (R11)                              // 6641f733
+	DIVW DX                                 // 66f7f2
+	DIVW R11                                // 6641f7f3
+	DIVL (BX)                               // f733
+	DIVL (R11)                              // 41f733
+	DIVL DX                                 // f7f2
+	DIVL R11                                // 41f7f3
+	DIVQ (BX)                               // 48f733
+	DIVQ (R11)                              // 49f733
+	DIVQ DX                                 // 48f7f2
+	DIVQ R11                                // 49f7f3
+	DIVB (BX)                               // f633
+	DIVB (R11)                              // 41f633
+	DIVB DL                                 // f6f2
+	DIVB R11                                // 41f6f3
+	DIVPD (BX), X2                          // 660f5e13
+	DIVPD (R11), X2                         // 66410f5e13
+	DIVPD X2, X2                            // 660f5ed2
+	DIVPD X11, X2                           // 66410f5ed3
+	DIVPD (BX), X11                         // 66440f5e1b
+	DIVPD (R11), X11                        // 66450f5e1b
+	DIVPD X2, X11                           // 66440f5eda
+	DIVPD X11, X11                          // 66450f5edb
+	DIVPS (BX), X2                          // 0f5e13
+	DIVPS (R11), X2                         // 410f5e13
+	DIVPS X2, X2                            // 0f5ed2
+	DIVPS X11, X2                           // 410f5ed3
+	DIVPS (BX), X11                         // 440f5e1b
+	DIVPS (R11), X11                        // 450f5e1b
+	DIVPS X2, X11                           // 440f5eda
+	DIVPS X11, X11                          // 450f5edb
+	DIVSD (BX), X2                          // f20f5e13
+	DIVSD (R11), X2                         // f2410f5e13
+	DIVSD X2, X2                            // f20f5ed2
+	DIVSD X11, X2                           // f2410f5ed3
+	DIVSD (BX), X11                         // f2440f5e1b
+	DIVSD (R11), X11                        // f2450f5e1b
+	DIVSD X2, X11                           // f2440f5eda
+	DIVSD X11, X11                          // f2450f5edb
+	DIVSS (BX), X2                          // f30f5e13
+	DIVSS (R11), X2                         // f3410f5e13
+	DIVSS X2, X2                            // f30f5ed2
+	DIVSS X11, X2                           // f3410f5ed3
+	DIVSS (BX), X11                         // f3440f5e1b
+	DIVSS (R11), X11                        // f3450f5e1b
+	DIVSS X2, X11                           // f3440f5eda
+	DIVSS X11, X11                          // f3450f5edb
+	//TODO: DPPD $7, (BX), X2               // 660f3a411307
+	//TODO: DPPD $7, (R11), X2              // 66410f3a411307
+	//TODO: DPPD $7, X2, X2                 // 660f3a41d207
+	//TODO: DPPD $7, X11, X2                // 66410f3a41d307
+	//TODO: DPPD $7, (BX), X11              // 66440f3a411b07
+	//TODO: DPPD $7, (R11), X11             // 66450f3a411b07
+	//TODO: DPPD $7, X2, X11                // 66440f3a41da07
+	//TODO: DPPD $7, X11, X11               // 66450f3a41db07
+	//TODO: DPPS $7, (BX), X2               // 660f3a401307
+	//TODO: DPPS $7, (R11), X2              // 66410f3a401307
+	//TODO: DPPS $7, X2, X2                 // 660f3a40d207
+	//TODO: DPPS $7, X11, X2                // 66410f3a40d307
+	//TODO: DPPS $7, (BX), X11              // 66440f3a401b07
+	//TODO: DPPS $7, (R11), X11             // 66450f3a401b07
+	//TODO: DPPS $7, X2, X11                // 66440f3a40da07
+	//TODO: DPPS $7, X11, X11               // 66450f3a40db07
+	EMMS                                    // 0f77
+	//TODO: ENTERQ $0x12, $0xf123           // c823f112
+	//TODO: EXTRACTPS $7, X2, (BX)          // 660f3a171307
+	//TODO: EXTRACTPS $7, X11, (BX)         // 66440f3a171b07
+	//TODO: EXTRACTPS $7, X2, (R11)         // 66410f3a171307
+	//TODO: EXTRACTPS $7, X11, (R11)        // 66450f3a171b07
+	//TODO: EXTRACTPS $7, X2, DX            // 660f3a17d207
+	//TODO: EXTRACTPS $7, X11, DX           // 66440f3a17da07
+	//TODO: EXTRACTPS $7, X2, R11           // 66410f3a17d307
+	//TODO: EXTRACTPS $7, X11, R11          // 66450f3a17db07
+	F2XM1                                   // d9f0
+	FABS                                    // d9e1
+	FADDD F2, F0                            // d8c2
+	FADDD F3, F0                            // d8c3
+	FADDD F0, F2                            // dcc2
+	FADDD F0, F3                            // dcc3
+	FADDD (BX), F0                          // d803 or dc03
+	FADDD (R11), F0                         // 41d803 or 41dc03
+	FADDDP F0, F2                           // dec2
+	FADDDP F0, F3                           // dec3
+	//TODO: FBLD (BX)                       // df23
+	//TODO: FBLD (R11)                      // 41df23
+	//TODO: FBSTP (BX)                      // df33
+	//TODO: FBSTP (R11)                     // 41df33
+	FCHS                                    // d9e0
+	//TODO: FCMOVB F2, F0                   // dac2
+	//TODO: FCMOVB F3, F0                   // dac3
+	//TODO: FCMOVBE F2, F0                  // dad2
+	//TODO: FCMOVBE F3, F0                  // dad3
+	//TODO: FCMOVE F2, F0                   // daca
+	//TODO: FCMOVE F3, F0                   // dacb
+	//TODO: FCMOVNB F2, F0                  // dbc2
+	//TODO: FCMOVNB F3, F0                  // dbc3
+	//TODO: FCMOVNBE F2, F0                 // dbd2
+	//TODO: FCMOVNBE F3, F0                 // dbd3
+	FCMOVNE F2, F0                          // dbca
+	FCMOVNE F3, F0                          // dbcb
+	FCMOVNU F2, F0                          // dbda
+	FCMOVNU F3, F0                          // dbdb
+	//TODO: FCMOVU F2, F0                   // dada
+	//TODO: FCMOVU F3, F0                   // dadb
+	FCOMD F2, F0                            // d8d2
+	FCOMD F3, F0                            // d8d3
+	FCOMD (BX), F0                          // d813 or dc13
+	FCOMD (R11), F0                         // 41d813 or 41dc13
+	//TODO: FCOMI F2, F0                    // dbf2
+	//TODO: FCOMI F3, F0                    // dbf3
+	//TODO: FCOMIP F2, F0                   // dff2
+	//TODO: FCOMIP F3, F0                   // dff3
+	//TODO: FCOMP F2                        // d8da
+	//TODO: FCOMP F3                        // d8db
+	//TODO: FCOMFP (BX)                     // d81b
+	//TODO: FCOMFP (R11)                    // 41d81b
+	//TODO: FCOMPL (BX)                     // dc1b
+	//TODO: FCOMPL (R11)                    // 41dc1b
+	//TODO: FCOMPP                          // ded9
+	FCOS                                    // d9ff
+	FDECSTP                                 // d9f6
+	FDIVD F2, F0                            // d8f2
+	FDIVD F3, F0                            // d8f3
+	FDIVD F0, F2                            // dcfa or dcf2
+	FDIVD F0, F3                            // dcfb or dcf3
+	FDIVD (BX), F0                          // d833 or dc33
+	FDIVD (R11), F0                         // 41d833 or 41dc33
+	//TODO: FDIVRP F0, F2                   // defa
+	//TODO: FDIVRP F0, F3                   // defb
+	//TODO: FDIVR F2, F0                    // d8fa
+	//TODO: FDIVR F3, F0                    // d8fb
+	//TODO: FDIVFR (BX)                     // d83b
+	//TODO: FDIVFR (R11)                    // 41d83b
+	//TODO: FDIVRL (BX)                     // dc3b
+	//TODO: FDIVRL (R11)                    // 41dc3b
+	//TODO: FDIVP F0, F2                    // def2
+	//TODO: FDIVP F0, F3                    // def3
+	//TODO: FFREE F2                        // ddc2
+	//TODO: FFREE F3                        // ddc3
+	//TODO: FFREEP F2                       // dfc2
+	//TODO: FFREEP F3                       // dfc3
+	//TODO: FIADD (BX)                      // de03
+	//TODO: FIADD (R11)                     // 41de03
+	//TODO: FIADDL (BX)                     // da03
+	//TODO: FIADDL (R11)                    // 41da03
+	//TODO: FICOM (BX)                      // de13
+	//TODO: FICOM (R11)                     // 41de13
+	//TODO: FICOML (BX)                     // da13
+	//TODO: FICOML (R11)                    // 41da13
+	//TODO: FICOMP (BX)                     // de1b
+	//TODO: FICOMP (R11)                    // 41de1b
+	//TODO: FICOMPL (BX)                    // da1b
+	//TODO: FICOMPL (R11)                   // 41da1b
+	//TODO: FIDIV (BX)                      // de33
+	//TODO: FIDIV (R11)                     // 41de33
+	//TODO: FIDIVL (BX)                     // da33
+	//TODO: FIDIVL (R11)                    // 41da33
+	//TODO: FIDIVR (BX)                     // de3b
+	//TODO: FIDIVR (R11)                    // 41de3b
+	//TODO: FIDIVRL (BX)                    // da3b
+	//TODO: FIDIVRL (R11)                   // 41da3b
+	//TODO: FILD (BX)                       // df03
+	//TODO: FILD (R11)                      // 41df03
+	//TODO: FILDL (BX)                      // db03
+	//TODO: FILDL (R11)                     // 41db03
+	//TODO: FILDLL (BX)                     // df2b
+	//TODO: FILDLL (R11)                    // 41df2b
+	//TODO: FIMUL (BX)                      // de0b
+	//TODO: FIMUL (R11)                     // 41de0b
+	//TODO: FIMULL (BX)                     // da0b
+	//TODO: FIMULL (R11)                    // 41da0b
+	FINCSTP                                 // d9f7
+	//TODO: FIST (BX)                       // df13
+	//TODO: FIST (R11)                      // 41df13
+	//TODO: FISTL (BX)                      // db13
+	//TODO: FISTL (R11)                     // 41db13
+	//TODO: FISTP (BX)                      // df1b
+	//TODO: FISTP (R11)                     // 41df1b
+	//TODO: FISTPL (BX)                     // db1b
+	//TODO: FISTPL (R11)                    // 41db1b
+	//TODO: FISTPLL (BX)                    // df3b
+	//TODO: FISTPLL (R11)                   // 41df3b
+	//TODO: FISTTP (BX)                     // df0b
+	//TODO: FISTTP (R11)                    // 41df0b
+	//TODO: FISTTPL (BX)                    // db0b
+	//TODO: FISTTPL (R11)                   // 41db0b
+	//TODO: FISTTPLL (BX)                   // dd0b
+	//TODO: FISTTPLL (R11)                  // 41dd0b
+	//TODO: FISUB (BX)                      // de23
+	//TODO: FISUB (R11)                     // 41de23
+	//TODO: FISUBL (BX)                     // da23
+	//TODO: FISUBL (R11)                    // 41da23
+	//TODO: FISUBR (BX)                     // de2b
+	//TODO: FISUBR (R11)                    // 41de2b
+	//TODO: FISUBRL (BX)                    // da2b
+	//TODO: FISUBRL (R11)                   // 41da2b
+	//TODO: FLD F2                          // d9c2
+	//TODO: FLD F3                          // d9c3
+	//TODO: FLDS (BX)                       // d903
+	//TODO: FLDS (R11)                      // 41d903
+	//TODO: FLDL (BX)                       // dd03
+	//TODO: FLDL (R11)                      // 41dd03
+	//TODO: FLDT (BX)                       // db2b
+	//TODO: FLDT (R11)                      // 41db2b
+	FLD1                                    // d9e8
+	FLDCW (BX)                              // d92b
+	FLDCW (R11)                             // 41d92b
+	//TODO: FLDENVL (BX)                    // d923
+	//TODO: FLDENVL (R11)                   // 41d923
+	FLDL2E                                  // d9ea
+	FLDL2T                                  // d9e9
+	FLDLG2                                  // d9ec
+	FLDPI                                   // d9eb
+	//TODO: FMUL F2, F0                     // d8ca
+	//TODO: FMUL F3, F0                     // d8cb
+	//TODO: FMUL F0, F2                     // dcca
+	//TODO: FMUL F0, F3                     // dccb
+	//TODO: FMULS (BX)                      // d80b
+	//TODO: FMULS (R11)                     // 41d80b
+	//TODO: FMULL (BX)                      // dc0b
+	//TODO: FMULL (R11)                     // 41dc0b
+	//TODO: FMULP F0, F2                    // deca
+	//TODO: FMULP F0, F3                    // decb
+	//TODO: FNCLEX                          // dbe2
+	//TODO: FNINIT                          // dbe3
+	FNOP                                    // d9d0
+	//TODO: FNSAVEL (BX)                    // dd33
+	//TODO: FNSAVEL (R11)                   // 41dd33
+	//TODO: FNSTCW (BX)                     // d93b
+	//TODO: FNSTCW (R11)                    // 41d93b
+	//TODO: FNSTENVL (BX)                   // d933
+	//TODO: FNSTENVL (R11)                  // 41d933
+	//TODO: FNSTSW AX                       // dfe0
+	//TODO: FNSTSW (BX)                     // dd3b
+	//TODO: FNSTSW (R11)                    // 41dd3b
+	FPATAN                                  // d9f3
+	FPREM                                   // d9f8
+	FPREM1                                  // d9f5
+	FPTAN                                   // d9f2
+	FRNDINT                                 // d9fc
+	//TODO: FRSTORL (BX)                    // dd23
+	//TODO: FRSTORL (R11)                   // 41dd23
+	FSCALE                                  // d9fd
+	FSIN                                    // d9fe
+	FSINCOS                                 // d9fb
+	FSQRT                                   // d9fa
+	//TODO: FST F2                          // ddd2
+	//TODO: FST F3                          // ddd3
+	//TODO: FSTS (BX)                       // d913
+	//TODO: FSTS (R11)                      // 41d913
+	//TODO: FSTL (BX)                       // dd13
+	//TODO: FSTL (R11)                      // 41dd13
+	//TODO: FSTP F2                         // ddda
+	//TODO: FSTP F3                         // dddb
+	//TODO: FSTPS (BX)                      // d91b
+	//TODO: FSTPS (R11)                     // 41d91b
+	//TODO: FSTPL (BX)                      // dd1b
+	//TODO: FSTPL (R11)                     // 41dd1b
+	//TODO: FSTPT (BX)                      // db3b
+	//TODO: FSTPT (R11)                     // 41db3b
+	//TODO: FSUB F2, F0                     // d8e2
+	//TODO: FSUB F3, F0                     // d8e3
+	//TODO: FSUBR F0, F2                    // dcea
+	//TODO: FSUBR F0, F3                    // dceb
+	//TODO: FSUBS (BX)                      // d823
+	//TODO: FSUBS (R11)                     // 41d823
+	//TODO: FSUBL (BX)                      // dc23
+	//TODO: FSUBL (R11)                     // 41dc23
+	//TODO: FSUBRP F0, F2                   // deea
+	//TODO: FSUBRP F0, F3                   // deeb
+	//TODO: FSUBR F2, F0                    // d8ea
+	//TODO: FSUBR F3, F0                    // d8eb
+	//TODO: FSUB F0, F2                     // dce2
+	//TODO: FSUB F0, F3                     // dce3
+	//TODO: FSUBRS (BX)                     // d82b
+	//TODO: FSUBRS (R11)                    // 41d82b
+	//TODO: FSUBRL (BX)                     // dc2b
+	//TODO: FSUBRL (R11)                    // 41dc2b
+	//TODO: FSUBP F0, F2                    // dee2
+	//TODO: FSUBP F0, F3                    // dee3
+	FTST                                    // d9e4
+	//TODO: FUCOM F2                        // dde2
+	//TODO: FUCOM F3                        // dde3
+	//TODO: FUCOMI F2, F0                   // dbea
+	//TODO: FUCOMI F3, F0                   // dbeb
+	//TODO: FUCOMIP F2, F0                  // dfea
+	//TODO: FUCOMIP F3, F0                  // dfeb
+	//TODO: FUCOMP F2                       // ddea
+	//TODO: FUCOMP F3                       // ddeb
+	//TODO: FUCOMPP                         // dae9
+	//TODO: FWAIT                           // 9b
+	FXAM                                    // d9e5
+	//TODO: FXCH F2                         // d9ca
+	//TODO: FXCH F3                         // d9cb
+	FXRSTOR (BX)                            // 0fae0b
+	FXRSTOR (R11)                           // 410fae0b
+	FXRSTOR64 (BX)                          // 480fae0b
+	FXRSTOR64 (R11)                         // 490fae0b
+	FXSAVE (BX)                             // 0fae03
+	FXSAVE (R11)                            // 410fae03
+	FXSAVE64 (BX)                           // 480fae03
+	FXSAVE64 (R11)                          // 490fae03
+	FXTRACT                                 // d9f4
+	FYL2X                                   // d9f1
+	FYL2XP1                                 // d9f9
+	HADDPD (BX), X2                         // 660f7c13
+	HADDPD (R11), X2                        // 66410f7c13
+	HADDPD X2, X2                           // 660f7cd2
+	HADDPD X11, X2                          // 66410f7cd3
+	HADDPD (BX), X11                        // 66440f7c1b
+	HADDPD (R11), X11                       // 66450f7c1b
+	HADDPD X2, X11                          // 66440f7cda
+	HADDPD X11, X11                         // 66450f7cdb
+	HADDPS (BX), X2                         // f20f7c13
+	HADDPS (R11), X2                        // f2410f7c13
+	HADDPS X2, X2                           // f20f7cd2
+	HADDPS X11, X2                          // f2410f7cd3
+	HADDPS (BX), X11                        // f2440f7c1b
+	HADDPS (R11), X11                       // f2450f7c1b
+	HADDPS X2, X11                          // f2440f7cda
+	HADDPS X11, X11                         // f2450f7cdb
+	HLT                                     // f4
+	HSUBPD (BX), X2                         // 660f7d13
+	HSUBPD (R11), X2                        // 66410f7d13
+	HSUBPD X2, X2                           // 660f7dd2
+	HSUBPD X11, X2                          // 66410f7dd3
+	HSUBPD (BX), X11                        // 66440f7d1b
+	HSUBPD (R11), X11                       // 66450f7d1b
+	HSUBPD X2, X11                          // 66440f7dda
+	HSUBPD X11, X11                         // 66450f7ddb
+	HSUBPS (BX), X2                         // f20f7d13
+	HSUBPS (R11), X2                        // f2410f7d13
+	HSUBPS X2, X2                           // f20f7dd2
+	HSUBPS X11, X2                          // f2410f7dd3
+	HSUBPS (BX), X11                        // f2440f7d1b
+	HSUBPS (R11), X11                       // f2450f7d1b
+	HSUBPS X2, X11                          // f2440f7dda
+	HSUBPS X11, X11                         // f2450f7ddb
+	//TODO: ICEBP                           // f1
+	IDIVW (BX)                              // 66f73b
+	IDIVW (R11)                             // 6641f73b
+	IDIVW DX                                // 66f7fa
+	IDIVW R11                               // 6641f7fb
+	IDIVL (BX)                              // f73b
+	IDIVL (R11)                             // 41f73b
+	IDIVL DX                                // f7fa
+	IDIVL R11                               // 41f7fb
+	IDIVQ (BX)                              // 48f73b
+	IDIVQ (R11)                             // 49f73b
+	IDIVQ DX                                // 48f7fa
+	IDIVQ R11                               // 49f7fb
+	IDIVB (BX)                              // f63b
+	IDIVB (R11)                             // 41f63b
+	IDIVB DL                                // f6fa
+	IDIVB R11                               // 41f6fb
+	IMULW (BX)                              // 66f72b
+	IMULW (R11)                             // 6641f72b
+	IMULW DX                                // 66f7ea
+	IMULW R11                               // 6641f7eb
+	IMULL (BX)                              // f72b
+	IMULL (R11)                             // 41f72b
+	IMULL DX                                // f7ea
+	IMULL R11                               // 41f7eb
+	IMULQ (BX)                              // 48f72b
+	IMULQ (R11)                             // 49f72b
+	IMULQ DX                                // 48f7ea
+	IMULQ R11                               // 49f7eb
+	IMULB (BX)                              // f62b
+	IMULB (R11)                             // 41f62b
+	IMULB DL                                // f6ea
+	IMULB R11                               // 41f6eb
+	IMULW (BX), DX                          // 660faf13
+	IMULW (R11), DX                         // 66410faf13
+	IMULW DX, DX                            // 660fafd2
+	IMULW R11, DX                           // 66410fafd3
+	IMULW (BX), R11                         // 66440faf1b
+	IMULW (R11), R11                        // 66450faf1b
+	IMULW DX, R11                           // 66440fafda
+	IMULW R11, R11                          // 66450fafdb
+	//TODO: IMULW $0xf123, (BX), DX         // 66691323f1
+	//TODO: IMULW $0xf123, (R11), DX        // 6641691323f1
+	//TODO: IMULW $0xf123, DX, DX           // 6669d223f1
+	//TODO: IMULW $0xf123, R11, DX          // 664169d323f1
+	//TODO: IMULW $0xf123, (BX), R11        // 6644691b23f1
+	//TODO: IMULW $0xf123, (R11), R11       // 6645691b23f1
+	//TODO: IMULW $0xf123, DX, R11          // 664469da23f1
+	//TODO: IMULW $0xf123, R11, R11         // 664569db23f1
+	//TODO: IMULW $7, (BX), DX              // 666b1307
+	//TODO: IMULW $7, (R11), DX             // 66416b1307
+	//TODO: IMULW $7, DX, DX                // 666bd207
+	//TODO: IMULW $7, R11, DX               // 66416bd307
+	//TODO: IMULW $7, (BX), R11             // 66446b1b07
+	//TODO: IMULW $7, (R11), R11            // 66456b1b07
+	//TODO: IMULW $7, DX, R11               // 66446bda07
+	//TODO: IMULW $7, R11, R11              // 66456bdb07
+	IMULL (BX), DX                          // 0faf13
+	IMULL (R11), DX                         // 410faf13
+	IMULL DX, DX                            // 0fafd2
+	IMULL R11, DX                           // 410fafd3
+	IMULL (BX), R11                         // 440faf1b
+	IMULL (R11), R11                        // 450faf1b
+	IMULL DX, R11                           // 440fafda
+	IMULL R11, R11                          // 450fafdb
+	//TODO: IMULL $0xf1234567, (BX), DX     // 6913674523f1
+	//TODO: IMULL $0xf1234567, (R11), DX    // 416913674523f1
+	//TODO: IMULL $0xf1234567, DX, DX       // 69d2674523f1
+	//TODO: IMULL $0xf1234567, R11, DX      // 4169d3674523f1
+	//TODO: IMULL $0xf1234567, (BX), R11    // 44691b674523f1
+	//TODO: IMULL $0xf1234567, (R11), R11   // 45691b674523f1
+	//TODO: IMULL $0xf1234567, DX, R11      // 4469da674523f1
+	//TODO: IMULL $0xf1234567, R11, R11     // 4569db674523f1
+	//TODO: IMULL $7, (BX), DX              // 6b1307
+	//TODO: IMULL $7, (R11), DX             // 416b1307
+	//TODO: IMULL $7, DX, DX                // 6bd207
+	//TODO: IMULL $7, R11, DX               // 416bd307
+	//TODO: IMULL $7, (BX), R11             // 446b1b07
+	//TODO: IMULL $7, (R11), R11            // 456b1b07
+	//TODO: IMULL $7, DX, R11               // 446bda07
+	//TODO: IMULL $7, R11, R11              // 456bdb07
+	IMULQ (BX), DX                          // 480faf13
+	IMULQ (R11), DX                         // 490faf13
+	IMULQ DX, DX                            // 480fafd2
+	IMULQ R11, DX                           // 490fafd3
+	IMULQ (BX), R11                         // 4c0faf1b
+	IMULQ (R11), R11                        // 4d0faf1b
+	IMULQ DX, R11                           // 4c0fafda
+	IMULQ R11, R11                          // 4d0fafdb
+	//TODO: IMULQ $0xfffffffff1234567, (BX), DX // 486913674523f1
+	//TODO: IMULQ $0xfffffffff1234567, (R11), DX // 496913674523f1
+	//TODO: IMULQ $0xfffffffff1234567, DX, DX // 4869d2674523f1
+	//TODO: IMULQ $0xfffffffff1234567, R11, DX // 4969d3674523f1
+	//TODO: IMULQ $0xfffffffff1234567, (BX), R11 // 4c691b674523f1
+	//TODO: IMULQ $0xfffffffff1234567, (R11), R11 // 4d691b674523f1
+	//TODO: IMULQ $0xfffffffff1234567, DX, R11 // 4c69da674523f1
+	//TODO: IMULQ $0xfffffffff1234567, R11, R11 // 4d69db674523f1
+	IMUL3Q $7, (BX), DX                     // 486b1307
+	IMUL3Q $7, (R11), DX                    // 496b1307
+	IMUL3Q $7, DX, DX                       // 486bd207
+	IMUL3Q $7, R11, DX                      // 496bd307
+	IMUL3Q $7, (BX), R11                    // 4c6b1b07
+	IMUL3Q $7, (R11), R11                   // 4d6b1b07
+	IMUL3Q $7, DX, R11                      // 4c6bda07
+	IMUL3Q $7, R11, R11                     // 4d6bdb07
+	//TODO: INB DX, AL                      // ec
+	//TODO: INB $7, AL                      // e407
+	//TODO: INW DX, AX                      // 66ed
+	//TODO: INW $7, AX                      // 66e507
+	//TODO: INL DX, AX                      // ed
+	//TODO: INL $7, AX                      // e507
+	INCW (BX)                               // 66ff03
+	INCW (R11)                              // 6641ff03
+	INCW DX                                 // 66ffc2
+	INCW R11                                // 6641ffc3
+	INCL (BX)                               // ff03
+	INCL (R11)                              // 41ff03
+	INCL DX                                 // ffc2
+	INCL R11                                // 41ffc3
+	INCQ (BX)                               // 48ff03
+	INCQ (R11)                              // 49ff03
+	INCQ DX                                 // 48ffc2
+	INCQ R11                                // 49ffc3
+	INCB (BX)                               // fe03
+	INCB (R11)                              // 41fe03
+	INCB DL                                 // fec2
+	INCB R11                                // 41fec3
+	INSB                                    // 6c
+	INSL                                    // 6d
+	//TODO: INSERTPS $7, (BX), X2           // 660f3a211307
+	//TODO: INSERTPS $7, (R11), X2          // 66410f3a211307
+	//TODO: INSERTPS $7, X2, X2             // 660f3a21d207
+	//TODO: INSERTPS $7, X11, X2            // 66410f3a21d307
+	//TODO: INSERTPS $7, (BX), X11          // 66440f3a211b07
+	//TODO: INSERTPS $7, (R11), X11         // 66450f3a211b07
+	//TODO: INSERTPS $7, X2, X11            // 66440f3a21da07
+	//TODO: INSERTPS $7, X11, X11           // 66450f3a21db07
+	INSW                                    // 666d
+	//TODO: INT $3                          // cc
+	INT $7                                  // cd07
+	INVD                                    // 0f08
+	INVLPG (BX)                             // 0f013b
+	INVLPG (R11)                            // 410f013b
+	//TODO: INVPCID (BX), DX                // 660f388213
+	//TODO: INVPCID (R11), DX               // 66410f388213
+	//TODO: INVPCID (BX), R11               // 66440f38821b
+	//TODO: INVPCID (R11), R11              // 66450f38821b
+	JCS 2(PC)
+	IRETW                                   // 66cf
+	JCS 2(PC)
+	IRETL                                   // cf
+	JCS 2(PC)
+	IRETQ                                   // 48cf
+	//TODO: JA .+$0x11223344                // 480f8744332211 or 0f8744332211
+	//TODO: JA .+$0x11                      // 7711
+	//TODO: JAE .+$0x11223344               // 0f8344332211 or 480f8344332211
+	//TODO: JAE .+$0x11                     // 7311
+	//TODO: JB .+$0x11223344                // 480f8244332211 or 0f8244332211
+	//TODO: JB .+$0x11                      // 7211
+	//TODO: JBE .+$0x11223344               // 0f8644332211 or 480f8644332211
+	//TODO: JBE .+$0x11                     // 7611
+	//TODO: JE .+$0x11223344                // 480f8444332211 or 0f8444332211
+	//TODO: JE .+$0x11                      // 7411
+	//TODO: JECXZ .+$0x11                   // e311
+	//TODO: JG .+$0x11223344                // 0f8f44332211 or 480f8f44332211
+	//TODO: JG .+$0x11                      // 7f11
+	//TODO: JGE .+$0x11223344               // 480f8d44332211 or 0f8d44332211
+	//TODO: JGE .+$0x11                     // 7d11
+	//TODO: JL .+$0x11223344                // 0f8c44332211 or 480f8c44332211
+	//TODO: JL .+$0x11                      // 7c11
+	//TODO: JLE .+$0x11223344               // 0f8e44332211 or 480f8e44332211
+	//TODO: JLE .+$0x11                     // 7e11
+	JCS 2(PC)
+	//TODO: JMPQ* (BX)                      // ff23
+	JCS 2(PC)
+	//TODO: JMPQ* (R11)                     // 41ff23
+	JCS 2(PC)
+	//TODO: JMPQ* DX                        // ffe2
+	JCS 2(PC)
+	//TODO: JMPQ* R11                       // 41ffe3
+	JCS 2(PC)
+	//TODO: JMP .+$0x11223344               // 48e944332211 or e944332211
+	JCS 2(PC)
+	JCS 2(PC)
+	//TODO: JMP .+$0x11                     // eb11
+	JCS 2(PC)
+	//TODO: LJMPW* (BX)                     // 66ff2b
+	JCS 2(PC)
+	//TODO: LJMPW* (R11)                    // 6641ff2b
+	JCS 2(PC)
+	//TODO: LJMPL* (BX)                     // ff2b
+	JCS 2(PC)
+	//TODO: LJMPL* (R11)                    // 41ff2b
+	JCS 2(PC)
+	//TODO: LJMPQ* (BX)                     // 48ff2b
+	JCS 2(PC)
+	//TODO: LJMPQ* (R11)                    // 49ff2b
+	//TODO: JNE .+$0x11223344               // 480f8544332211 or 0f8544332211
+	//TODO: JNE .+$0x11                     // 7511
+	//TODO: JNO .+$0x11223344               // 480f8144332211 or 0f8144332211
+	//TODO: JNO .+$0x11                     // 7111
+	//TODO: JNP .+$0x11223344               // 480f8b44332211 or 0f8b44332211
+	//TODO: JNP .+$0x11                     // 7b11
+	//TODO: JNS .+$0x11223344               // 0f8944332211 or 480f8944332211
+	//TODO: JNS .+$0x11                     // 7911
+	//TODO: JO .+$0x11223344                // 0f8044332211 or 480f8044332211
+	//TODO: JO .+$0x11                      // 7011
+	//TODO: JP .+$0x11223344                // 480f8a44332211 or 0f8a44332211
+	//TODO: JP .+$0x11                      // 7a11
+	//TODO: JRCXZ .+$0x11                   // e311
+	//TODO: JS .+$0x11223344                // 480f8844332211 or 0f8844332211
+	//TODO: JS .+$0x11                      // 7811
+	LAHF                                    // 9f
+	LARW (BX), DX                           // 660f0213
+	LARW (R11), DX                          // 66410f0213
+	LARW DX, DX                             // 660f02d2
+	LARW R11, DX                            // 66410f02d3
+	LARW (BX), R11                          // 66440f021b
+	LARW (R11), R11                         // 66450f021b
+	LARW DX, R11                            // 66440f02da
+	LARW R11, R11                           // 66450f02db
+	LARL (BX), DX                           // 0f0213
+	LARL (R11), DX                          // 410f0213
+	LARL DX, DX                             // 0f02d2
+	LARL R11, DX                            // 410f02d3
+	LARL (BX), R11                          // 440f021b
+	LARL (R11), R11                         // 450f021b
+	LARL DX, R11                            // 440f02da
+	LARL R11, R11                           // 450f02db
+	//TODO: LARQ (BX), DX                   // 480f0213
+	//TODO: LARQ (R11), DX                  // 490f0213
+	//TODO: LARQ DX, DX                     // 480f02d2
+	//TODO: LARQ R11, DX                    // 490f02d3
+	//TODO: LARQ (BX), R11                  // 4c0f021b
+	//TODO: LARQ (R11), R11                 // 4d0f021b
+	//TODO: LARQ DX, R11                    // 4c0f02da
+	//TODO: LARQ R11, R11                   // 4d0f02db
+	LDDQU (BX), X2                          // f20ff013
+	LDDQU (R11), X2                         // f2410ff013
+	LDDQU (BX), X11                         // f2440ff01b
+	LDDQU (R11), X11                        // f2450ff01b
+	LDMXCSR (BX)                            // 0fae13
+	LDMXCSR (R11)                           // 410fae13
+	LEAW (BX), DX                           // 668d13
+	LEAW (R11), DX                          // 66418d13
+	LEAW (BX), R11                          // 66448d1b
+	LEAW (R11), R11                         // 66458d1b
+	LEAL (BX), DX                           // 8d13
+	LEAL (R11), DX                          // 418d13
+	LEAL (BX), R11                          // 448d1b
+	LEAL (R11), R11                         // 458d1b
+	LEAQ (BX), DX                           // 488d13
+	LEAQ (R11), DX                          // 498d13
+	LEAQ (BX), R11                          // 4c8d1b
+	LEAQ (R11), R11                         // 4d8d1b
+	LEAVEQ                                  // 66c9 or c9
+	LFENCE                                  // 0faee8
+	//TODO: LFSW (BX), DX                   // 660fb413
+	//TODO: LFSW (R11), DX                  // 66410fb413
+	//TODO: LFSW (BX), R11                  // 66440fb41b
+	//TODO: LFSW (R11), R11                 // 66450fb41b
+	//TODO: LFSL (BX), DX                   // 0fb413
+	//TODO: LFSL (R11), DX                  // 410fb413
+	//TODO: LFSL (BX), R11                  // 440fb41b
+	//TODO: LFSL (R11), R11                 // 450fb41b
+	//TODO: LFSQ (BX), DX                   // 480fb413
+	//TODO: LFSQ (R11), DX                  // 490fb413
+	//TODO: LFSQ (BX), R11                  // 4c0fb41b
+	//TODO: LFSQ (R11), R11                 // 4d0fb41b
+	//TODO: LGDT (BX)                       // 0f0113
+	//TODO: LGDT (R11)                      // 410f0113
+	//TODO: LGSW (BX), DX                   // 660fb513
+	//TODO: LGSW (R11), DX                  // 66410fb513
+	//TODO: LGSW (BX), R11                  // 66440fb51b
+	//TODO: LGSW (R11), R11                 // 66450fb51b
+	//TODO: LGSL (BX), DX                   // 0fb513
+	//TODO: LGSL (R11), DX                  // 410fb513
+	//TODO: LGSL (BX), R11                  // 440fb51b
+	//TODO: LGSL (R11), R11                 // 450fb51b
+	//TODO: LGSQ (BX), DX                   // 480fb513
+	//TODO: LGSQ (R11), DX                  // 490fb513
+	//TODO: LGSQ (BX), R11                  // 4c0fb51b
+	//TODO: LGSQ (R11), R11                 // 4d0fb51b
+	//TODO: LIDT (BX)                       // 0f011b
+	//TODO: LIDT (R11)                      // 410f011b
+	//TODO: LLDT (BX)                       // 0f0013
+	//TODO: LLDT (R11)                      // 410f0013
+	//TODO: LLDT DX                         // 0f00d2
+	//TODO: LLDT R11                        // 410f00d3
+	//TODO: LMSW (BX)                       // 0f0133
+	//TODO: LMSW (R11)                      // 410f0133
+	//TODO: LMSW DX                         // 0f01f2
+	//TODO: LMSW R11                        // 410f01f3
+	LODSB                                   // ac
+	LODSL                                   // ad
+	LODSQ                                   // 48ad
+	LODSW                                   // 66ad
+	//TODO: LOOP .+$0x11                    // e211
+	//TODO: LOOPEQ .+$0x11                  // e111
+	//TODO: LOOPNE .+$0x11                  // e011
+	LSLW (BX), DX                           // 660f0313
+	LSLW (R11), DX                          // 66410f0313
+	LSLW DX, DX                             // 660f03d2
+	LSLW R11, DX                            // 66410f03d3
+	LSLW (BX), R11                          // 66440f031b
+	LSLW (R11), R11                         // 66450f031b
+	LSLW DX, R11                            // 66440f03da
+	LSLW R11, R11                           // 66450f03db
+	LSLL (BX), DX                           // 0f0313
+	LSLL (R11), DX                          // 410f0313
+	LSLL DX, DX                             // 0f03d2
+	LSLL R11, DX                            // 410f03d3
+	LSLL (BX), R11                          // 440f031b
+	LSLL (R11), R11                         // 450f031b
+	LSLL DX, R11                            // 440f03da
+	LSLL R11, R11                           // 450f03db
+	//TODO: LSLQ (BX), DX                   // 480f0313
+	//TODO: LSLQ (R11), DX                  // 490f0313
+	//TODO: LSLQ DX, DX                     // 480f03d2
+	//TODO: LSLQ R11, DX                    // 490f03d3
+	//TODO: LSLQ (BX), R11                  // 4c0f031b
+	//TODO: LSLQ (R11), R11                 // 4d0f031b
+	//TODO: LSLQ DX, R11                    // 4c0f03da
+	//TODO: LSLQ R11, R11                   // 4d0f03db
+	//TODO: LSSW (BX), DX                   // 660fb213
+	//TODO: LSSW (R11), DX                  // 66410fb213
+	//TODO: LSSW (BX), R11                  // 66440fb21b
+	//TODO: LSSW (R11), R11                 // 66450fb21b
+	//TODO: LSSL (BX), DX                   // 0fb213
+	//TODO: LSSL (R11), DX                  // 410fb213
+	//TODO: LSSL (BX), R11                  // 440fb21b
+	//TODO: LSSL (R11), R11                 // 450fb21b
+	//TODO: LSSQ (BX), DX                   // 480fb213
+	//TODO: LSSQ (R11), DX                  // 490fb213
+	//TODO: LSSQ (BX), R11                  // 4c0fb21b
+	//TODO: LSSQ (R11), R11                 // 4d0fb21b
+	//TODO: LTR (BX)                        // 0f001b
+	//TODO: LTR (R11)                       // 410f001b
+	//TODO: LTR DX                          // 0f00da
+	//TODO: LTR R11                         // 410f00db
+	//TODO: LZCNTW (BX), DX                 // 66f30fbd13
+	//TODO: LZCNTW (R11), DX                // 66f3410fbd13
+	//TODO: LZCNTW DX, DX                   // 66f30fbdd2
+	//TODO: LZCNTW R11, DX                  // 66f3410fbdd3
+	//TODO: LZCNTW (BX), R11                // 66f3440fbd1b
+	//TODO: LZCNTW (R11), R11               // 66f3450fbd1b
+	//TODO: LZCNTW DX, R11                  // 66f3440fbdda
+	//TODO: LZCNTW R11, R11                 // 66f3450fbddb
+	//TODO: LZCNTL (BX), DX                 // f30fbd13
+	//TODO: LZCNTL (R11), DX                // f3410fbd13
+	//TODO: LZCNTL DX, DX                   // f30fbdd2
+	//TODO: LZCNTL R11, DX                  // f3410fbdd3
+	//TODO: LZCNTL (BX), R11                // f3440fbd1b
+	//TODO: LZCNTL (R11), R11               // f3450fbd1b
+	//TODO: LZCNTL DX, R11                  // f3440fbdda
+	//TODO: LZCNTL R11, R11                 // f3450fbddb
+	//TODO: LZCNTQ (BX), DX                 // f3480fbd13
+	//TODO: LZCNTQ (R11), DX                // f3490fbd13
+	//TODO: LZCNTQ DX, DX                   // f3480fbdd2
+	//TODO: LZCNTQ R11, DX                  // f3490fbdd3
+	//TODO: LZCNTQ (BX), R11                // f34c0fbd1b
+	//TODO: LZCNTQ (R11), R11               // f34d0fbd1b
+	//TODO: LZCNTQ DX, R11                  // f34c0fbdda
+	//TODO: LZCNTQ R11, R11                 // f34d0fbddb
+	MASKMOVOU X2, X2                        // 660ff7d2
+	MASKMOVOU X11, X2                       // 66410ff7d3
+	MASKMOVOU X2, X11                       // 66440ff7da
+	MASKMOVOU X11, X11                      // 66450ff7db
+	MASKMOVQ M2, M2                         // 0ff7d2
+	MASKMOVQ M3, M2                         // 0ff7d3
+	MASKMOVQ M2, M3                         // 0ff7da
+	MASKMOVQ M3, M3                         // 0ff7db
+	MAXPD (BX), X2                          // 660f5f13
+	MAXPD (R11), X2                         // 66410f5f13
+	MAXPD X2, X2                            // 660f5fd2
+	MAXPD X11, X2                           // 66410f5fd3
+	MAXPD (BX), X11                         // 66440f5f1b
+	MAXPD (R11), X11                        // 66450f5f1b
+	MAXPD X2, X11                           // 66440f5fda
+	MAXPD X11, X11                          // 66450f5fdb
+	MAXPS (BX), X2                          // 0f5f13
+	MAXPS (R11), X2                         // 410f5f13
+	MAXPS X2, X2                            // 0f5fd2
+	MAXPS X11, X2                           // 410f5fd3
+	MAXPS (BX), X11                         // 440f5f1b
+	MAXPS (R11), X11                        // 450f5f1b
+	MAXPS X2, X11                           // 440f5fda
+	MAXPS X11, X11                          // 450f5fdb
+	MAXSD (BX), X2                          // f20f5f13
+	MAXSD (R11), X2                         // f2410f5f13
+	MAXSD X2, X2                            // f20f5fd2
+	MAXSD X11, X2                           // f2410f5fd3
+	MAXSD (BX), X11                         // f2440f5f1b
+	MAXSD (R11), X11                        // f2450f5f1b
+	MAXSD X2, X11                           // f2440f5fda
+	MAXSD X11, X11                          // f2450f5fdb
+	MAXSS (BX), X2                          // f30f5f13
+	MAXSS (R11), X2                         // f3410f5f13
+	MAXSS X2, X2                            // f30f5fd2
+	MAXSS X11, X2                           // f3410f5fd3
+	MAXSS (BX), X11                         // f3440f5f1b
+	MAXSS (R11), X11                        // f3450f5f1b
+	MAXSS X2, X11                           // f3440f5fda
+	MAXSS X11, X11                          // f3450f5fdb
+	MFENCE                                  // 0faef0
+	MINPD (BX), X2                          // 660f5d13
+	MINPD (R11), X2                         // 66410f5d13
+	MINPD X2, X2                            // 660f5dd2
+	MINPD X11, X2                           // 66410f5dd3
+	MINPD (BX), X11                         // 66440f5d1b
+	MINPD (R11), X11                        // 66450f5d1b
+	MINPD X2, X11                           // 66440f5dda
+	MINPD X11, X11                          // 66450f5ddb
+	MINPS (BX), X2                          // 0f5d13
+	MINPS (R11), X2                         // 410f5d13
+	MINPS X2, X2                            // 0f5dd2
+	MINPS X11, X2                           // 410f5dd3
+	MINPS (BX), X11                         // 440f5d1b
+	MINPS (R11), X11                        // 450f5d1b
+	MINPS X2, X11                           // 440f5dda
+	MINPS X11, X11                          // 450f5ddb
+	MINSD (BX), X2                          // f20f5d13
+	MINSD (R11), X2                         // f2410f5d13
+	MINSD X2, X2                            // f20f5dd2
+	MINSD X11, X2                           // f2410f5dd3
+	MINSD (BX), X11                         // f2440f5d1b
+	MINSD (R11), X11                        // f2450f5d1b
+	MINSD X2, X11                           // f2440f5dda
+	MINSD X11, X11                          // f2450f5ddb
+	MINSS (BX), X2                          // f30f5d13
+	MINSS (R11), X2                         // f3410f5d13
+	MINSS X2, X2                            // f30f5dd2
+	MINSS X11, X2                           // f3410f5dd3
+	MINSS (BX), X11                         // f3440f5d1b
+	MINSS (R11), X11                        // f3450f5d1b
+	MINSS X2, X11                           // f3440f5dda
+	MINSS X11, X11                          // f3450f5ddb
+	//TODO: MONITOR                         // 0f01c8
+	//TODO: MOVABSB 0x123456789abcdef1, AL  // a0f1debc9a78563412
+	//TODO: MOVW 0x123456789abcdef1, AX     // 66a1f1debc9a78563412
+	MOVQ DX, CR2                            // 0f22d2
+	MOVQ R11, CR2                           // 410f22d3
+	MOVQ DX, CR3                            // 0f22da
+	MOVQ R11, CR3                           // 410f22db
+	//TODO: MOVQ DX, DR2                    // 0f23d2
+	//TODO: MOVQ R11, DR2                   // 410f23d3
+	//TODO: MOVQ DX, DR3                    // 0f23da
+	//TODO: MOVQ R11, DR3                   // 410f23db
+	//TODO: MOVL 0x123456789abcdef1, AX     // a1f1debc9a78563412
+	//TODO: MOVQ 0x123456789abcdef1, AX     // 48a1f1debc9a78563412
+	//TODO: MOVW (BX), SS                   // 668e13 or 488e13
+	//TODO: MOVW (R11), SS                  // 66418e13 or 498e13
+	//TODO: MOVW DX, SS                     // 668ed2 or 488ed2
+	//TODO: MOVW R11, SS                    // 66418ed3 or 498ed3
+	//TODO: MOVW (BX), DS                   // 668e1b or 488e1b
+	//TODO: MOVW (R11), DS                  // 66418e1b or 498e1b
+	//TODO: MOVW DX, DS                     // 668eda or 488eda
+	//TODO: MOVW R11, DS                    // 66418edb or 498edb
+	//TODO: MOVL (BX), SS                   // 8e13
+	//TODO: MOVL (R11), SS                  // 418e13
+	//TODO: MOVL DX, SS                     // 8ed2
+	//TODO: MOVL R11, SS                    // 418ed3
+	//TODO: MOVL (BX), DS                   // 8e1b
+	//TODO: MOVL (R11), DS                  // 418e1b
+	//TODO: MOVL DX, DS                     // 8eda
+	//TODO: MOVL R11, DS                    // 418edb
+	//TODO: MOVW AX, 0x123456789abcdef1     // 66a3f1debc9a78563412
+	//TODO: MOVL AX, 0x123456789abcdef1     // a3f1debc9a78563412
+	//TODO: MOVQ AX, 0x123456789abcdef1     // 48a3f1debc9a78563412
+	//TODO: MOVABSB AL, 0x123456789abcdef1  // a2f1debc9a78563412
+	//TODO: MOVW SS, (BX)                   // 668c13 or 488c13
+	//TODO: MOVW DS, (BX)                   // 668c1b or 488c1b
+	//TODO: MOVW SS, (R11)                  // 66418c13 or 498c13
+	//TODO: MOVW DS, (R11)                  // 66418c1b or 498c1b
+	//TODO: MOVW SS, DX                     // 668cd2 or 488cd2
+	//TODO: MOVW DS, DX                     // 668cda or 488cda
+	//TODO: MOVW SS, R11                    // 66418cd3 or 498cd3
+	//TODO: MOVW DS, R11                    // 66418cdb or 498cdb
+	MOVW $61731, (BX)                       // 66c70323f1
+	MOVW $61731, (R11)                      // 6641c70323f1
+	MOVW $61731, DX                         // 66c7c223f1 or 66ba23f1
+	MOVW $61731, R11                        // 6641c7c323f1 or 6641bb23f1
+	MOVW DX, (BX)                           // 668913
+	MOVW R11, (BX)                          // 6644891b
+	MOVW DX, (R11)                          // 66418913
+	MOVW R11, (R11)                         // 6645891b
+	MOVW DX, DX                             // 6689d2 or 668bd2
+	MOVW R11, DX                            // 664489da or 66418bd3
+	MOVW DX, R11                            // 664189d3 or 66448bda
+	MOVW R11, R11                           // 664589db or 66458bdb
+	//TODO: MOVL SS, (BX)                   // 8c13
+	//TODO: MOVL DS, (BX)                   // 8c1b
+	//TODO: MOVL SS, (R11)                  // 418c13
+	//TODO: MOVL DS, (R11)                  // 418c1b
+	//TODO: MOVL SS, DX                     // 8cd2
+	//TODO: MOVL DS, DX                     // 8cda
+	//TODO: MOVL SS, R11                    // 418cd3
+	//TODO: MOVL DS, R11                    // 418cdb
+	MOVL $4045620583, (BX)                  // c703674523f1
+	MOVL $4045620583, (R11)                 // 41c703674523f1
+	MOVL $4045620583, DX                    // c7c2674523f1 or ba674523f1
+	MOVL $4045620583, R11                   // 41c7c3674523f1 or 41bb674523f1
+	MOVL DX, (BX)                           // 8913
+	MOVL R11, (BX)                          // 44891b
+	MOVL DX, (R11)                          // 418913
+	MOVL R11, (R11)                         // 45891b
+	MOVL DX, DX                             // 89d2 or 8bd2
+	MOVL R11, DX                            // 4489da or 418bd3
+	MOVL DX, R11                            // 4189d3 or 448bda
+	MOVL R11, R11                           // 4589db or 458bdb
+	MOVQ $-249346713, (BX)                  // 48c703674523f1
+	MOVQ $-249346713, (R11)                 // 49c703674523f1
+	MOVQ $-249346713, DX                    // 48c7c2674523f1
+	MOVQ $-249346713, R11                   // 49c7c3674523f1
+	MOVQ DX, (BX)                           // 488913
+	MOVQ R11, (BX)                          // 4c891b
+	MOVQ DX, (R11)                          // 498913
+	MOVQ R11, (R11)                         // 4d891b
+	MOVQ DX, DX                             // 4889d2 or 488bd2
+	MOVQ R11, DX                            // 4c89da or 498bd3
+	MOVQ DX, R11                            // 4989d3 or 4c8bda
+	MOVQ R11, R11                           // 4d89db or 4d8bdb
+	MOVB $7, (BX)                           // c60307
+	MOVB $7, (R11)                          // 41c60307
+	MOVB $7, DL                             // c6c207 or b207
+	MOVB $7, R11                            // 41c6c307 or 41b307
+	MOVB DL, (BX)                           // 8813
+	MOVB R11, (BX)                          // 44881b
+	MOVB DL, (R11)                          // 418813
+	MOVB R11, (R11)                         // 45881b
+	MOVB DL, DL                             // 88d2 or 8ad2
+	MOVB R11, DL                            // 4488da or 418ad3
+	MOVB DL, R11                            // 4188d3 or 448ada
+	MOVB R11, R11                           // 4588db or 458adb
+	MOVW (BX), DX                           // 668b13
+	MOVW (R11), DX                          // 66418b13
+	MOVW (BX), R11                          // 66448b1b
+	MOVW (R11), R11                         // 66458b1b
+	MOVL (BX), DX                           // 8b13
+	MOVL (R11), DX                          // 418b13
+	MOVL (BX), R11                          // 448b1b
+	MOVL (R11), R11                         // 458b1b
+	MOVQ (BX), DX                           // 488b13
+	MOVQ (R11), DX                          // 498b13
+	MOVQ (BX), R11                          // 4c8b1b
+	MOVQ (R11), R11                         // 4d8b1b
+	MOVQ $-1070935975390360081, DX          // 48baefcdab89674523f1
+	MOVQ $-1070935975390360081, R11         // 49bbefcdab89674523f1
+	MOVB (BX), DL                           // 8a13
+	MOVB (R11), DL                          // 418a13
+	MOVB (BX), R11                          // 448a1b
+	MOVB (R11), R11                         // 458a1b
+	MOVQ CR2, DX                            // 0f20d2
+	MOVQ CR3, DX                            // 0f20da
+	MOVQ CR2, R11                           // 410f20d3
+	MOVQ CR3, R11                           // 410f20db
+	//TODO: MOVQ DR2, DX                    // 0f21d2
+	//TODO: MOVQ DR3, DX                    // 0f21da
+	//TODO: MOVQ DR2, R11                   // 410f21d3
+	//TODO: MOVQ DR3, R11                   // 410f21db
+	MOVAPD (BX), X2                         // 660f2813
+	MOVAPD (R11), X2                        // 66410f2813
+	MOVAPD X2, X2                           // 660f28d2 or 660f29d2
+	MOVAPD X11, X2                          // 66410f28d3 or 66440f29da
+	MOVAPD (BX), X11                        // 66440f281b
+	MOVAPD (R11), X11                       // 66450f281b
+	MOVAPD X2, X11                          // 66440f28da or 66410f29d3
+	MOVAPD X11, X11                         // 66450f28db or 66450f29db
+	MOVAPD X2, (BX)                         // 660f2913
+	MOVAPD X11, (BX)                        // 66440f291b
+	MOVAPD X2, (R11)                        // 66410f2913
+	MOVAPD X11, (R11)                       // 66450f291b
+	MOVAPS (BX), X2                         // 0f2813
+	MOVAPS (R11), X2                        // 410f2813
+	MOVAPS X2, X2                           // 0f28d2 or 0f29d2
+	MOVAPS X11, X2                          // 410f28d3 or 440f29da
+	MOVAPS (BX), X11                        // 440f281b
+	MOVAPS (R11), X11                       // 450f281b
+	MOVAPS X2, X11                          // 440f28da or 410f29d3
+	MOVAPS X11, X11                         // 450f28db or 450f29db
+	MOVAPS X2, (BX)                         // 0f2913
+	MOVAPS X11, (BX)                        // 440f291b
+	MOVAPS X2, (R11)                        // 410f2913
+	MOVAPS X11, (R11)                       // 450f291b
+	//TODO: MOVBEWW DX, (BX)                // 660f38f113
+	//TODO: MOVBEWW R11, (BX)               // 66440f38f11b
+	//TODO: MOVBEWW DX, (R11)               // 66410f38f113
+	//TODO: MOVBEWW R11, (R11)              // 66450f38f11b
+	//TODO: MOVBELL DX, (BX)                // 0f38f113
+	//TODO: MOVBELL R11, (BX)               // 440f38f11b
+	//TODO: MOVBELL DX, (R11)               // 410f38f113
+	//TODO: MOVBELL R11, (R11)              // 450f38f11b
+	//TODO: MOVBEQQ DX, (BX)                // 480f38f113
+	//TODO: MOVBEQQ R11, (BX)               // 4c0f38f11b
+	//TODO: MOVBEQQ DX, (R11)               // 490f38f113
+	//TODO: MOVBEQQ R11, (R11)              // 4d0f38f11b
+	//TODO: MOVBEWW (BX), DX                // 660f38f013
+	//TODO: MOVBEWW (R11), DX               // 66410f38f013
+	//TODO: MOVBEWW (BX), R11               // 66440f38f01b
+	//TODO: MOVBEWW (R11), R11              // 66450f38f01b
+	//TODO: MOVBELL (BX), DX                // 0f38f013
+	//TODO: MOVBELL (R11), DX               // 410f38f013
+	//TODO: MOVBELL (BX), R11               // 440f38f01b
+	//TODO: MOVBELL (R11), R11              // 450f38f01b
+	//TODO: MOVBEQQ (BX), DX                // 480f38f013
+	//TODO: MOVBEQQ (R11), DX               // 490f38f013
+	//TODO: MOVBEQQ (BX), R11               // 4c0f38f01b
+	//TODO: MOVBEQQ (R11), R11              // 4d0f38f01b
+	MOVQ (BX), M2                           // 0f6e13 or 0f6f13 or 480f6e13
+	MOVQ (R11), M2                          // 410f6e13 or 410f6f13 or 490f6e13
+	MOVQ DX, M2                             // 0f6ed2 or 480f6ed2
+	MOVQ R11, M2                            // 410f6ed3 or 490f6ed3
+	MOVQ (BX), M3                           // 0f6e1b or 0f6f1b or 480f6e1b
+	MOVQ (R11), M3                          // 410f6e1b or 410f6f1b or 490f6e1b
+	MOVQ DX, M3                             // 0f6eda or 480f6eda
+	MOVQ R11, M3                            // 410f6edb or 490f6edb
+	MOVQ M2, (BX)                           // 0f7e13 or 0f7f13 or 480f7e13
+	MOVQ M3, (BX)                           // 0f7e1b or 0f7f1b or 480f7e1b
+	MOVQ M2, (R11)                          // 410f7e13 or 410f7f13 or 490f7e13
+	MOVQ M3, (R11)                          // 410f7e1b or 410f7f1b or 490f7e1b
+	MOVQ M2, DX                             // 0f7ed2 or 480f7ed2
+	MOVQ M3, DX                             // 0f7eda or 480f7eda
+	MOVQ M2, R11                            // 410f7ed3 or 490f7ed3
+	MOVQ M3, R11                            // 410f7edb or 490f7edb
+	MOVQ X2, (BX)                           // 660f7e13 or 66480f7e13 or 660fd613
+	MOVQ X11, (BX)                          // 66440f7e1b or 664c0f7e1b or 66440fd61b
+	MOVQ X2, (R11)                          // 66410f7e13 or 66490f7e13 or 66410fd613
+	MOVQ X11, (R11)                         // 66450f7e1b or 664d0f7e1b or 66450fd61b
+	MOVQ X2, DX                             // 660f7ed2 or 66480f7ed2
+	MOVQ X11, DX                            // 66440f7eda or 664c0f7eda
+	MOVQ X2, R11                            // 66410f7ed3 or 66490f7ed3
+	MOVQ X11, R11                           // 66450f7edb or 664d0f7edb
+	MOVQ (BX), X2                           // 660f6e13 or 66480f6e13 or f30f7e13
+	MOVQ (R11), X2                          // 66410f6e13 or 66490f6e13 or f3410f7e13
+	MOVQ DX, X2                             // 660f6ed2 or 66480f6ed2
+	MOVQ R11, X2                            // 66410f6ed3 or 66490f6ed3
+	MOVQ (BX), X11                          // 66440f6e1b or 664c0f6e1b or f3440f7e1b
+	MOVQ (R11), X11                         // 66450f6e1b or 664d0f6e1b or f3450f7e1b
+	MOVQ DX, X11                            // 66440f6eda or 664c0f6eda
+	MOVQ R11, X11                           // 66450f6edb or 664d0f6edb
+	//TODO: MOVDDUP (BX), X2                // f20f1213
+	//TODO: MOVDDUP (R11), X2               // f2410f1213
+	//TODO: MOVDDUP X2, X2                  // f20f12d2
+	//TODO: MOVDDUP X11, X2                 // f2410f12d3
+	//TODO: MOVDDUP (BX), X11               // f2440f121b
+	//TODO: MOVDDUP (R11), X11              // f2450f121b
+	//TODO: MOVDDUP X2, X11                 // f2440f12da
+	//TODO: MOVDDUP X11, X11                // f2450f12db
+	MOVQ X2, M2                             // f20fd6d2
+	MOVQ X11, M2                            // f2410fd6d3
+	MOVQ X2, M3                             // f20fd6da
+	MOVQ X11, M3                            // f2410fd6db
+	MOVO (BX), X2                           // 660f6f13
+	MOVO (R11), X2                          // 66410f6f13
+	MOVO X2, X2                             // 660f6fd2 or 660f7fd2
+	MOVO X11, X2                            // 66410f6fd3 or 66440f7fda
+	MOVO (BX), X11                          // 66440f6f1b
+	MOVO (R11), X11                         // 66450f6f1b
+	MOVO X2, X11                            // 66440f6fda or 66410f7fd3
+	MOVO X11, X11                           // 66450f6fdb or 66450f7fdb
+	MOVO X2, (BX)                           // 660f7f13
+	MOVO X11, (BX)                          // 66440f7f1b
+	MOVO X2, (R11)                          // 66410f7f13
+	MOVO X11, (R11)                         // 66450f7f1b
+	MOVOU (BX), X2                          // f30f6f13
+	MOVOU (R11), X2                         // f3410f6f13
+	MOVOU X2, X2                            // f30f6fd2 or f30f7fd2
+	MOVOU X11, X2                           // f3410f6fd3 or f3440f7fda
+	MOVOU (BX), X11                         // f3440f6f1b
+	MOVOU (R11), X11                        // f3450f6f1b
+	MOVOU X2, X11                           // f3440f6fda or f3410f7fd3
+	MOVOU X11, X11                          // f3450f6fdb or f3450f7fdb
+	MOVOU X2, (BX)                          // f30f7f13
+	MOVOU X11, (BX)                         // f3440f7f1b
+	MOVOU X2, (R11)                         // f3410f7f13
+	MOVOU X11, (R11)                        // f3450f7f1b
+	MOVHLPS X2, X2                          // 0f12d2
+	MOVHLPS X11, X2                         // 410f12d3
+	MOVHLPS X2, X11                         // 440f12da
+	MOVHLPS X11, X11                        // 450f12db
+	MOVHPD X2, (BX)                         // 660f1713
+	MOVHPD X11, (BX)                        // 66440f171b
+	MOVHPD X2, (R11)                        // 66410f1713
+	MOVHPD X11, (R11)                       // 66450f171b
+	MOVHPD (BX), X2                         // 660f1613
+	MOVHPD (R11), X2                        // 66410f1613
+	MOVHPD (BX), X11                        // 66440f161b
+	MOVHPD (R11), X11                       // 66450f161b
+	MOVHPS X2, (BX)                         // 0f1713
+	MOVHPS X11, (BX)                        // 440f171b
+	MOVHPS X2, (R11)                        // 410f1713
+	MOVHPS X11, (R11)                       // 450f171b
+	MOVHPS (BX), X2                         // 0f1613
+	MOVHPS (R11), X2                        // 410f1613
+	MOVHPS (BX), X11                        // 440f161b
+	MOVHPS (R11), X11                       // 450f161b
+	MOVLHPS X2, X2                          // 0f16d2
+	MOVLHPS X11, X2                         // 410f16d3
+	MOVLHPS X2, X11                         // 440f16da
+	MOVLHPS X11, X11                        // 450f16db
+	MOVLPD X2, (BX)                         // 660f1313
+	MOVLPD X11, (BX)                        // 66440f131b
+	MOVLPD X2, (R11)                        // 66410f1313
+	MOVLPD X11, (R11)                       // 66450f131b
+	MOVLPD (BX), X2                         // 660f1213
+	MOVLPD (R11), X2                        // 66410f1213
+	MOVLPD (BX), X11                        // 66440f121b
+	MOVLPD (R11), X11                       // 66450f121b
+	MOVLPS X2, (BX)                         // 0f1313
+	MOVLPS X11, (BX)                        // 440f131b
+	MOVLPS X2, (R11)                        // 410f1313
+	MOVLPS X11, (R11)                       // 450f131b
+	MOVLPS (BX), X2                         // 0f1213
+	MOVLPS (R11), X2                        // 410f1213
+	MOVLPS (BX), X11                        // 440f121b
+	MOVLPS (R11), X11                       // 450f121b
+	MOVMSKPD X2, DX                         // 660f50d2
+	MOVMSKPD X11, DX                        // 66410f50d3
+	MOVMSKPD X2, R11                        // 66440f50da
+	MOVMSKPD X11, R11                       // 66450f50db
+	MOVMSKPS X2, DX                         // 0f50d2
+	MOVMSKPS X11, DX                        // 410f50d3
+	MOVMSKPS X2, R11                        // 440f50da
+	MOVMSKPS X11, R11                       // 450f50db
+	MOVNTO X2, (BX)                         // 660fe713
+	MOVNTO X11, (BX)                        // 66440fe71b
+	MOVNTO X2, (R11)                        // 66410fe713
+	MOVNTO X11, (R11)                       // 66450fe71b
+	//TODO: MOVNTDQA (BX), X2               // 660f382a13
+	//TODO: MOVNTDQA (R11), X2              // 66410f382a13
+	//TODO: MOVNTDQA (BX), X11              // 66440f382a1b
+	//TODO: MOVNTDQA (R11), X11             // 66450f382a1b
+	MOVNTIL DX, (BX)                        // 0fc313
+	MOVNTIL R11, (BX)                       // 440fc31b
+	MOVNTIL DX, (R11)                       // 410fc313
+	MOVNTIL R11, (R11)                      // 450fc31b
+	MOVNTIQ DX, (BX)                        // 480fc313
+	MOVNTIQ R11, (BX)                       // 4c0fc31b
+	MOVNTIQ DX, (R11)                       // 490fc313
+	MOVNTIQ R11, (R11)                      // 4d0fc31b
+	MOVNTPD X2, (BX)                        // 660f2b13
+	MOVNTPD X11, (BX)                       // 66440f2b1b
+	MOVNTPD X2, (R11)                       // 66410f2b13
+	MOVNTPD X11, (R11)                      // 66450f2b1b
+	MOVNTPS X2, (BX)                        // 0f2b13
+	MOVNTPS X11, (BX)                       // 440f2b1b
+	MOVNTPS X2, (R11)                       // 410f2b13
+	MOVNTPS X11, (R11)                      // 450f2b1b
+	MOVNTQ M2, (BX)                         // 0fe713
+	MOVNTQ M3, (BX)                         // 0fe71b
+	MOVNTQ M2, (R11)                        // 410fe713
+	MOVNTQ M3, (R11)                        // 410fe71b
+	//TODO: MOVNTSD X2, (BX)                // f20f2b13
+	//TODO: MOVNTSD X11, (BX)               // f2440f2b1b
+	//TODO: MOVNTSD X2, (R11)               // f2410f2b13
+	//TODO: MOVNTSD X11, (R11)              // f2450f2b1b
+	//TODO: MOVNTSS X2, (BX)                // f30f2b13
+	//TODO: MOVNTSS X11, (BX)               // f3440f2b1b
+	//TODO: MOVNTSS X2, (R11)               // f3410f2b13
+	//TODO: MOVNTSS X11, (R11)              // f3450f2b1b
+	//TODO: MOVQ M2, M2                     // 0f6fd2 or 0f7fd2
+	//TODO: MOVQ M3, M2                     // 0f6fd3 or 0f7fda
+	//TODO: MOVQ M2, M3                     // 0f6fda or 0f7fd3
+	//TODO: MOVQ M3, M3                     // 0f6fdb or 0f7fdb
+	MOVQ X2, X2                             // f30f7ed2 or 660fd6d2
+	MOVQ X11, X2                            // f3410f7ed3 or 66440fd6da
+	MOVQ X2, X11                            // f3440f7eda or 66410fd6d3
+	MOVQ X11, X11                           // f3450f7edb or 66450fd6db
+	MOVQOZX M2, X2                          // f30fd6d2
+	MOVQOZX M3, X2                          // f30fd6d3
+	MOVQOZX M2, X11                         // f3440fd6da
+	MOVQOZX M3, X11                         // f3440fd6db
+	MOVSB                                   // a4
+	MOVSL                                   // a5
+	//TODO: MOVSD (BX), X2                  // f20f1013
+	//TODO: MOVSD (R11), X2                 // f2410f1013
+	//TODO: MOVSD X2, X2                    // f20f10d2 or f20f11d2
+	//TODO: MOVSD X11, X2                   // f2410f10d3 or f2440f11da
+	//TODO: MOVSD (BX), X11                 // f2440f101b
+	//TODO: MOVSD (R11), X11                // f2450f101b
+	//TODO: MOVSD X2, X11                   // f2440f10da or f2410f11d3
+	//TODO: MOVSD X11, X11                  // f2450f10db or f2450f11db
+	//TODO: MOVSD X2, (BX)                  // f20f1113
+	//TODO: MOVSD X11, (BX)                 // f2440f111b
+	//TODO: MOVSD X2, (R11)                 // f2410f1113
+	//TODO: MOVSD X11, (R11)                // f2450f111b
+	//TODO: MOVSHDUP (BX), X2               // f30f1613
+	//TODO: MOVSHDUP (R11), X2              // f3410f1613
+	//TODO: MOVSHDUP X2, X2                 // f30f16d2
+	//TODO: MOVSHDUP X11, X2                // f3410f16d3
+	//TODO: MOVSHDUP (BX), X11              // f3440f161b
+	//TODO: MOVSHDUP (R11), X11             // f3450f161b
+	//TODO: MOVSHDUP X2, X11                // f3440f16da
+	//TODO: MOVSHDUP X11, X11               // f3450f16db
+	//TODO: MOVSLDUP (BX), X2               // f30f1213
+	//TODO: MOVSLDUP (R11), X2              // f3410f1213
+	//TODO: MOVSLDUP X2, X2                 // f30f12d2
+	//TODO: MOVSLDUP X11, X2                // f3410f12d3
+	//TODO: MOVSLDUP (BX), X11              // f3440f121b
+	//TODO: MOVSLDUP (R11), X11             // f3450f121b
+	//TODO: MOVSLDUP X2, X11                // f3440f12da
+	//TODO: MOVSLDUP X11, X11               // f3450f12db
+	MOVSQ                                   // 48a5
+	MOVSS (BX), X2                          // f30f1013
+	MOVSS (R11), X2                         // f3410f1013
+	MOVSS X2, X2                            // f30f10d2 or f30f11d2
+	MOVSS X11, X2                           // f3410f10d3 or f3440f11da
+	MOVSS (BX), X11                         // f3440f101b
+	MOVSS (R11), X11                        // f3450f101b
+	MOVSS X2, X11                           // f3440f10da or f3410f11d3
+	MOVSS X11, X11                          // f3450f10db or f3450f11db
+	MOVSS X2, (BX)                          // f30f1113
+	MOVSS X11, (BX)                         // f3440f111b
+	MOVSS X2, (R11)                         // f3410f1113
+	MOVSS X11, (R11)                        // f3450f111b
+	MOVSW                                   // 66a5
+	//TODO: MOVSWW (BX), DX                 // 660fbf13
+	//TODO: MOVSWW (R11), DX                // 66410fbf13
+	//TODO: MOVSWW DX, DX                   // 660fbfd2
+	//TODO: MOVSWW R11, DX                  // 66410fbfd3
+	//TODO: MOVSWW (BX), R11                // 66440fbf1b
+	//TODO: MOVSWW (R11), R11               // 66450fbf1b
+	//TODO: MOVSWW DX, R11                  // 66440fbfda
+	//TODO: MOVSWW R11, R11                 // 66450fbfdb
+	MOVBWSX (BX), DX                        // 660fbe13
+	MOVBWSX (R11), DX                       // 66410fbe13
+	MOVBWSX DL, DX                          // 660fbed2
+	MOVBWSX R11, DX                         // 66410fbed3
+	MOVBWSX (BX), R11                       // 66440fbe1b
+	MOVBWSX (R11), R11                      // 66450fbe1b
+	MOVBWSX DL, R11                         // 66440fbeda
+	MOVBWSX R11, R11                        // 66450fbedb
+	MOVWLSX (BX), DX                        // 0fbf13
+	MOVWLSX (R11), DX                       // 410fbf13
+	MOVWLSX DX, DX                          // 0fbfd2
+	MOVWLSX R11, DX                         // 410fbfd3
+	MOVWLSX (BX), R11                       // 440fbf1b
+	MOVWLSX (R11), R11                      // 450fbf1b
+	MOVWLSX DX, R11                         // 440fbfda
+	MOVWLSX R11, R11                        // 450fbfdb
+	MOVBLSX (BX), DX                        // 0fbe13
+	MOVBLSX (R11), DX                       // 410fbe13
+	MOVBLSX DL, DX                          // 0fbed2
+	MOVBLSX R11, DX                         // 410fbed3
+	MOVBLSX (BX), R11                       // 440fbe1b
+	MOVBLSX (R11), R11                      // 450fbe1b
+	MOVBLSX DL, R11                         // 440fbeda
+	MOVBLSX R11, R11                        // 450fbedb
+	MOVWQSX (BX), DX                        // 480fbf13 or 666313
+	MOVWQSX (R11), DX                       // 490fbf13 or 66416313
+	MOVWQSX DX, DX                          // 480fbfd2 or 6663d2
+	MOVWQSX R11, DX                         // 490fbfd3 or 664163d3
+	MOVWQSX (BX), R11                       // 4c0fbf1b or 6644631b
+	MOVWQSX (R11), R11                      // 4d0fbf1b or 6645631b
+	MOVWQSX DX, R11                         // 4c0fbfda or 664463da
+	MOVWQSX R11, R11                        // 4d0fbfdb or 664563db
+	MOVBQSX (BX), DX                        // 480fbe13
+	MOVBQSX (R11), DX                       // 490fbe13
+	MOVBQSX DL, DX                          // 480fbed2
+	MOVBQSX R11, DX                         // 490fbed3
+	MOVBQSX (BX), R11                       // 4c0fbe1b
+	MOVBQSX (R11), R11                      // 4d0fbe1b
+	MOVBQSX DL, R11                         // 4c0fbeda
+	MOVBQSX R11, R11                        // 4d0fbedb
+	MOVLQSX (BX), DX                        // 6313 or 486313
+	MOVLQSX (R11), DX                       // 416313 or 496313
+	MOVLQSX DX, DX                          // 63d2 or 4863d2
+	MOVLQSX R11, DX                         // 4163d3 or 4963d3
+	MOVLQSX (BX), R11                       // 44631b or 4c631b
+	MOVLQSX (R11), R11                      // 45631b or 4d631b
+	MOVLQSX DX, R11                         // 4463da or 4c63da
+	MOVLQSX R11, R11                        // 4563db or 4d63db
+	MOVUPD (BX), X2                         // 660f1013
+	MOVUPD (R11), X2                        // 66410f1013
+	MOVUPD X2, X2                           // 660f10d2 or 660f11d2
+	MOVUPD X11, X2                          // 66410f10d3 or 66440f11da
+	MOVUPD (BX), X11                        // 66440f101b
+	MOVUPD (R11), X11                       // 66450f101b
+	MOVUPD X2, X11                          // 66440f10da or 66410f11d3
+	MOVUPD X11, X11                         // 66450f10db or 66450f11db
+	MOVUPD X2, (BX)                         // 660f1113
+	MOVUPD X11, (BX)                        // 66440f111b
+	MOVUPD X2, (R11)                        // 66410f1113
+	MOVUPD X11, (R11)                       // 66450f111b
+	MOVUPS (BX), X2                         // 0f1013
+	MOVUPS (R11), X2                        // 410f1013
+	MOVUPS X2, X2                           // 0f10d2 or 0f11d2
+	MOVUPS X11, X2                          // 410f10d3 or 440f11da
+	MOVUPS (BX), X11                        // 440f101b
+	MOVUPS (R11), X11                       // 450f101b
+	MOVUPS X2, X11                          // 440f10da or 410f11d3
+	MOVUPS X11, X11                         // 450f10db or 450f11db
+	MOVUPS X2, (BX)                         // 0f1113
+	MOVUPS X11, (BX)                        // 440f111b
+	MOVUPS X2, (R11)                        // 410f1113
+	MOVUPS X11, (R11)                       // 450f111b
+	//TODO: MOVZWW (BX), DX                 // 660fb713
+	//TODO: MOVZWW (R11), DX                // 66410fb713
+	//TODO: MOVZWW DX, DX                   // 660fb7d2
+	//TODO: MOVZWW R11, DX                  // 66410fb7d3
+	//TODO: MOVZWW (BX), R11                // 66440fb71b
+	//TODO: MOVZWW (R11), R11               // 66450fb71b
+	//TODO: MOVZWW DX, R11                  // 66440fb7da
+	//TODO: MOVZWW R11, R11                 // 66450fb7db
+	MOVBWZX (BX), DX                        // 660fb613
+	MOVBWZX (R11), DX                       // 66410fb613
+	MOVBWZX DL, DX                          // 660fb6d2
+	MOVBWZX R11, DX                         // 66410fb6d3
+	MOVBWZX (BX), R11                       // 66440fb61b
+	MOVBWZX (R11), R11                      // 66450fb61b
+	MOVBWZX DL, R11                         // 66440fb6da
+	MOVBWZX R11, R11                        // 66450fb6db
+	MOVWLZX (BX), DX                        // 0fb713
+	MOVWLZX (R11), DX                       // 410fb713
+	MOVWLZX DX, DX                          // 0fb7d2
+	MOVWLZX R11, DX                         // 410fb7d3
+	MOVWLZX (BX), R11                       // 440fb71b
+	MOVWLZX (R11), R11                      // 450fb71b
+	MOVWLZX DX, R11                         // 440fb7da
+	MOVWLZX R11, R11                        // 450fb7db
+	MOVBLZX (BX), DX                        // 0fb613
+	MOVBLZX (R11), DX                       // 410fb613
+	MOVBLZX DL, DX                          // 0fb6d2
+	MOVBLZX R11, DX                         // 410fb6d3
+	MOVBLZX (BX), R11                       // 440fb61b
+	MOVBLZX (R11), R11                      // 450fb61b
+	MOVBLZX DL, R11                         // 440fb6da
+	MOVBLZX R11, R11                        // 450fb6db
+	MOVWQZX (BX), DX                        // 480fb713
+	MOVWQZX (R11), DX                       // 490fb713
+	MOVWQZX DX, DX                          // 480fb7d2
+	MOVWQZX R11, DX                         // 490fb7d3
+	MOVWQZX (BX), R11                       // 4c0fb71b
+	MOVWQZX (R11), R11                      // 4d0fb71b
+	MOVWQZX DX, R11                         // 4c0fb7da
+	MOVWQZX R11, R11                        // 4d0fb7db
+	//TODO: MOVBQZX (BX), DX                // 480fb613
+	//TODO: MOVBQZX (R11), DX               // 490fb613
+	//TODO: MOVBQZX DL, DX                  // 480fb6d2
+	//TODO: MOVBQZX R11, DX                 // 490fb6d3
+	//TODO: MOVBQZX (BX), R11               // 4c0fb61b
+	//TODO: MOVBQZX (R11), R11              // 4d0fb61b
+	//TODO: MOVBQZX DL, R11                 // 4c0fb6da
+	//TODO: MOVBQZX R11, R11                // 4d0fb6db
+	//TODO: MPSADBW $7, (BX), X2            // 660f3a421307
+	//TODO: MPSADBW $7, (R11), X2           // 66410f3a421307
+	//TODO: MPSADBW $7, X2, X2              // 660f3a42d207
+	//TODO: MPSADBW $7, X11, X2             // 66410f3a42d307
+	//TODO: MPSADBW $7, (BX), X11           // 66440f3a421b07
+	//TODO: MPSADBW $7, (R11), X11          // 66450f3a421b07
+	//TODO: MPSADBW $7, X2, X11             // 66440f3a42da07
+	//TODO: MPSADBW $7, X11, X11            // 66450f3a42db07
+	MULW (BX)                               // 66f723
+	MULW (R11)                              // 6641f723
+	MULW DX                                 // 66f7e2
+	MULW R11                                // 6641f7e3
+	MULL (BX)                               // f723
+	MULL (R11)                              // 41f723
+	MULL DX                                 // f7e2
+	MULL R11                                // 41f7e3
+	MULQ (BX)                               // 48f723
+	MULQ (R11)                              // 49f723
+	MULQ DX                                 // 48f7e2
+	MULQ R11                                // 49f7e3
+	MULB (BX)                               // f623
+	MULB (R11)                              // 41f623
+	MULB DL                                 // f6e2
+	MULB R11                                // 41f6e3
+	MULPD (BX), X2                          // 660f5913
+	MULPD (R11), X2                         // 66410f5913
+	MULPD X2, X2                            // 660f59d2
+	MULPD X11, X2                           // 66410f59d3
+	MULPD (BX), X11                         // 66440f591b
+	MULPD (R11), X11                        // 66450f591b
+	MULPD X2, X11                           // 66440f59da
+	MULPD X11, X11                          // 66450f59db
+	MULPS (BX), X2                          // 0f5913
+	MULPS (R11), X2                         // 410f5913
+	MULPS X2, X2                            // 0f59d2
+	MULPS X11, X2                           // 410f59d3
+	MULPS (BX), X11                         // 440f591b
+	MULPS (R11), X11                        // 450f591b
+	MULPS X2, X11                           // 440f59da
+	MULPS X11, X11                          // 450f59db
+	MULSD (BX), X2                          // f20f5913
+	MULSD (R11), X2                         // f2410f5913
+	MULSD X2, X2                            // f20f59d2
+	MULSD X11, X2                           // f2410f59d3
+	MULSD (BX), X11                         // f2440f591b
+	MULSD (R11), X11                        // f2450f591b
+	MULSD X2, X11                           // f2440f59da
+	MULSD X11, X11                          // f2450f59db
+	MULSS (BX), X2                          // f30f5913
+	MULSS (R11), X2                         // f3410f5913
+	MULSS X2, X2                            // f30f59d2
+	MULSS X11, X2                           // f3410f59d3
+	MULSS (BX), X11                         // f3440f591b
+	MULSS (R11), X11                        // f3450f591b
+	MULSS X2, X11                           // f3440f59da
+	MULSS X11, X11                          // f3450f59db
+	MULXL (BX), R9, DX                      // c4e233f613
+	MULXL (R11), R9, DX                     // c4c233f613
+	MULXL DX, R9, DX                        // c4e233f6d2
+	MULXL R11, R9, DX                       // c4c233f6d3
+	MULXL (BX), R9, R11                     // c46233f61b
+	MULXL (R11), R9, R11                    // c44233f61b
+	MULXL DX, R9, R11                       // c46233f6da
+	MULXL R11, R9, R11                      // c44233f6db
+	MULXQ (BX), R14, DX                     // c4e28bf613
+	MULXQ (R11), R14, DX                    // c4c28bf613
+	MULXQ DX, R14, DX                       // c4e28bf6d2
+	MULXQ R11, R14, DX                      // c4c28bf6d3
+	MULXQ (BX), R14, R11                    // c4628bf61b
+	MULXQ (R11), R14, R11                   // c4428bf61b
+	MULXQ DX, R14, R11                      // c4628bf6da
+	MULXQ R11, R14, R11                     // c4428bf6db
+	//TODO: MWAIT                           // 0f01c9
+	NEGW (BX)                               // 66f71b
+	NEGW (R11)                              // 6641f71b
+	NEGW DX                                 // 66f7da
+	NEGW R11                                // 6641f7db
+	NEGL (BX)                               // f71b
+	NEGL (R11)                              // 41f71b
+	NEGL DX                                 // f7da
+	NEGL R11                                // 41f7db
+	NEGQ (BX)                               // 48f71b
+	NEGQ (R11)                              // 49f71b
+	NEGQ DX                                 // 48f7da
+	NEGQ R11                                // 49f7db
+	NEGB (BX)                               // f61b
+	NEGB (R11)                              // 41f61b
+	NEGB DL                                 // f6da
+	NEGB R11                                // 41f6db
+	//TODO: NOPW (BX)                       // 660f1f03
+	//TODO: NOPW (R11)                      // 66410f1f03
+	//TODO: NOPW DX                         // 660f1fc2
+	//TODO: NOPW R11                        // 66410f1fc3
+	//TODO: NOPL (BX)                       // 0f1f03
+	//TODO: NOPL (R11)                      // 410f1f03
+	//TODO: NOPL DX                         // 0f1fc2
+	//TODO: NOPL R11                        // 410f1fc3
+	NOTW (BX)                               // 66f713
+	NOTW (R11)                              // 6641f713
+	NOTW DX                                 // 66f7d2
+	NOTW R11                                // 6641f7d3
+	NOTL (BX)                               // f713
+	NOTL (R11)                              // 41f713
+	NOTL DX                                 // f7d2
+	NOTL R11                                // 41f7d3
+	NOTQ (BX)                               // 48f713
+	NOTQ (R11)                              // 49f713
+	NOTQ DX                                 // 48f7d2
+	NOTQ R11                                // 49f7d3
+	NOTB (BX)                               // f613
+	NOTB (R11)                              // 41f613
+	NOTB DL                                 // f6d2
+	NOTB R11                                // 41f6d3
+	ORB $7, AL                              // 0c07
+	ORW $61731, AX                          // 660d23f1
+	ORL $4045620583, AX                     // 0d674523f1
+	ORQ $-249346713, AX                     // 480d674523f1
+	ORW $61731, (BX)                        // 66810b23f1
+	ORW $61731, (R11)                       // 6641810b23f1
+	ORW $61731, DX                          // 6681ca23f1
+	ORW $61731, R11                         // 664181cb23f1
+	ORW $7, (BX)                            // 66830b07
+	ORW $7, (R11)                           // 6641830b07
+	ORW $7, DX                              // 6683ca07
+	ORW $7, R11                             // 664183cb07
+	ORW DX, (BX)                            // 660913
+	ORW R11, (BX)                           // 6644091b
+	ORW DX, (R11)                           // 66410913
+	ORW R11, (R11)                          // 6645091b
+	ORW DX, DX                              // 6609d2 or 660bd2
+	ORW R11, DX                             // 664409da or 66410bd3
+	ORW DX, R11                             // 664109d3 or 66440bda
+	ORW R11, R11                            // 664509db or 66450bdb
+	ORL $4045620583, (BX)                   // 810b674523f1
+	ORL $4045620583, (R11)                  // 41810b674523f1
+	ORL $4045620583, DX                     // 81ca674523f1
+	ORL $4045620583, R11                    // 4181cb674523f1
+	ORL $7, (BX)                            // 830b07
+	ORL $7, (R11)                           // 41830b07
+	ORL $7, DX                              // 83ca07
+	ORL $7, R11                             // 4183cb07
+	ORL DX, (BX)                            // 0913
+	ORL R11, (BX)                           // 44091b
+	ORL DX, (R11)                           // 410913
+	ORL R11, (R11)                          // 45091b
+	ORL DX, DX                              // 09d2 or 0bd2
+	ORL R11, DX                             // 4409da or 410bd3
+	ORL DX, R11                             // 4109d3 or 440bda
+	ORL R11, R11                            // 4509db or 450bdb
+	ORQ $-249346713, (BX)                   // 48810b674523f1
+	ORQ $-249346713, (R11)                  // 49810b674523f1
+	ORQ $-249346713, DX                     // 4881ca674523f1
+	ORQ $-249346713, R11                    // 4981cb674523f1
+	ORQ $7, (BX)                            // 48830b07
+	ORQ $7, (R11)                           // 49830b07
+	ORQ $7, DX                              // 4883ca07
+	ORQ $7, R11                             // 4983cb07
+	ORQ DX, (BX)                            // 480913
+	ORQ R11, (BX)                           // 4c091b
+	ORQ DX, (R11)                           // 490913
+	ORQ R11, (R11)                          // 4d091b
+	ORQ DX, DX                              // 4809d2 or 480bd2
+	ORQ R11, DX                             // 4c09da or 490bd3
+	ORQ DX, R11                             // 4909d3 or 4c0bda
+	ORQ R11, R11                            // 4d09db or 4d0bdb
+	ORB $7, (BX)                            // 800b07
+	ORB $7, (R11)                           // 41800b07
+	ORB $7, DL                              // 80ca07
+	ORB $7, R11                             // 4180cb07
+	ORB DL, (BX)                            // 0813
+	ORB R11, (BX)                           // 44081b
+	ORB DL, (R11)                           // 410813
+	ORB R11, (R11)                          // 45081b
+	ORB DL, DL                              // 08d2 or 0ad2
+	ORB R11, DL                             // 4408da or 410ad3
+	ORB DL, R11                             // 4108d3 or 440ada
+	ORB R11, R11                            // 4508db or 450adb
+	ORW (BX), DX                            // 660b13
+	ORW (R11), DX                           // 66410b13
+	ORW (BX), R11                           // 66440b1b
+	ORW (R11), R11                          // 66450b1b
+	ORL (BX), DX                            // 0b13
+	ORL (R11), DX                           // 410b13
+	ORL (BX), R11                           // 440b1b
+	ORL (R11), R11                          // 450b1b
+	ORQ (BX), DX                            // 480b13
+	ORQ (R11), DX                           // 490b13
+	ORQ (BX), R11                           // 4c0b1b
+	ORQ (R11), R11                          // 4d0b1b
+	ORB (BX), DL                            // 0a13
+	ORB (R11), DL                           // 410a13
+	ORB (BX), R11                           // 440a1b
+	ORB (R11), R11                          // 450a1b
+	ORPD (BX), X2                           // 660f5613
+	ORPD (R11), X2                          // 66410f5613
+	ORPD X2, X2                             // 660f56d2
+	ORPD X11, X2                            // 66410f56d3
+	ORPD (BX), X11                          // 66440f561b
+	ORPD (R11), X11                         // 66450f561b
+	ORPD X2, X11                            // 66440f56da
+	ORPD X11, X11                           // 66450f56db
+	ORPS (BX), X2                           // 0f5613
+	ORPS (R11), X2                          // 410f5613
+	ORPS X2, X2                             // 0f56d2
+	ORPS X11, X2                            // 410f56d3
+	ORPS (BX), X11                          // 440f561b
+	ORPS (R11), X11                         // 450f561b
+	ORPS X2, X11                            // 440f56da
+	ORPS X11, X11                           // 450f56db
+	//TODO: OUTB AL, DX                     // ee
+	//TODO: OUTW AX, DX                     // 66ef
+	//TODO: OUTL AX, DX                     // ef
+	//TODO: OUTB AL, $7                     // e607
+	//TODO: OUTW AX, $7                     // 66e707
+	//TODO: OUTL AX, $7                     // e707
+	OUTSB                                   // 6e
+	OUTSL                                   // 6f
+	OUTSW                                   // 666f
+	//TODO: PABSB (BX), M2                  // 0f381c13
+	//TODO: PABSB (R11), M2                 // 410f381c13
+	//TODO: PABSB M2, M2                    // 0f381cd2
+	//TODO: PABSB M3, M2                    // 0f381cd3
+	//TODO: PABSB (BX), M3                  // 0f381c1b
+	//TODO: PABSB (R11), M3                 // 410f381c1b
+	//TODO: PABSB M2, M3                    // 0f381cda
+	//TODO: PABSB M3, M3                    // 0f381cdb
+	//TODO: PABSB (BX), X2                  // 660f381c13
+	//TODO: PABSB (R11), X2                 // 66410f381c13
+	//TODO: PABSB X2, X2                    // 660f381cd2
+	//TODO: PABSB X11, X2                   // 66410f381cd3
+	//TODO: PABSB (BX), X11                 // 66440f381c1b
+	//TODO: PABSB (R11), X11                // 66450f381c1b
+	//TODO: PABSB X2, X11                   // 66440f381cda
+	//TODO: PABSB X11, X11                  // 66450f381cdb
+	//TODO: PABSD (BX), M2                  // 0f381e13
+	//TODO: PABSD (R11), M2                 // 410f381e13
+	//TODO: PABSD M2, M2                    // 0f381ed2
+	//TODO: PABSD M3, M2                    // 0f381ed3
+	//TODO: PABSD (BX), M3                  // 0f381e1b
+	//TODO: PABSD (R11), M3                 // 410f381e1b
+	//TODO: PABSD M2, M3                    // 0f381eda
+	//TODO: PABSD M3, M3                    // 0f381edb
+	//TODO: PABSD (BX), X2                  // 660f381e13
+	//TODO: PABSD (R11), X2                 // 66410f381e13
+	//TODO: PABSD X2, X2                    // 660f381ed2
+	//TODO: PABSD X11, X2                   // 66410f381ed3
+	//TODO: PABSD (BX), X11                 // 66440f381e1b
+	//TODO: PABSD (R11), X11                // 66450f381e1b
+	//TODO: PABSD X2, X11                   // 66440f381eda
+	//TODO: PABSD X11, X11                  // 66450f381edb
+	//TODO: PABSW (BX), M2                  // 0f381d13
+	//TODO: PABSW (R11), M2                 // 410f381d13
+	//TODO: PABSW M2, M2                    // 0f381dd2
+	//TODO: PABSW M3, M2                    // 0f381dd3
+	//TODO: PABSW (BX), M3                  // 0f381d1b
+	//TODO: PABSW (R11), M3                 // 410f381d1b
+	//TODO: PABSW M2, M3                    // 0f381dda
+	//TODO: PABSW M3, M3                    // 0f381ddb
+	//TODO: PABSW (BX), X2                  // 660f381d13
+	//TODO: PABSW (R11), X2                 // 66410f381d13
+	//TODO: PABSW X2, X2                    // 660f381dd2
+	//TODO: PABSW X11, X2                   // 66410f381dd3
+	//TODO: PABSW (BX), X11                 // 66440f381d1b
+	//TODO: PABSW (R11), X11                // 66450f381d1b
+	//TODO: PABSW X2, X11                   // 66440f381dda
+	//TODO: PABSW X11, X11                  // 66450f381ddb
+	PACKSSLW (BX), M2                       // 0f6b13
+	PACKSSLW (R11), M2                      // 410f6b13
+	PACKSSLW M2, M2                         // 0f6bd2
+	PACKSSLW M3, M2                         // 0f6bd3
+	PACKSSLW (BX), M3                       // 0f6b1b
+	PACKSSLW (R11), M3                      // 410f6b1b
+	PACKSSLW M2, M3                         // 0f6bda
+	PACKSSLW M3, M3                         // 0f6bdb
+	PACKSSLW (BX), X2                       // 660f6b13
+	PACKSSLW (R11), X2                      // 66410f6b13
+	PACKSSLW X2, X2                         // 660f6bd2
+	PACKSSLW X11, X2                        // 66410f6bd3
+	PACKSSLW (BX), X11                      // 66440f6b1b
+	PACKSSLW (R11), X11                     // 66450f6b1b
+	PACKSSLW X2, X11                        // 66440f6bda
+	PACKSSLW X11, X11                       // 66450f6bdb
+	PACKSSWB (BX), M2                       // 0f6313
+	PACKSSWB (R11), M2                      // 410f6313
+	PACKSSWB M2, M2                         // 0f63d2
+	PACKSSWB M3, M2                         // 0f63d3
+	PACKSSWB (BX), M3                       // 0f631b
+	PACKSSWB (R11), M3                      // 410f631b
+	PACKSSWB M2, M3                         // 0f63da
+	PACKSSWB M3, M3                         // 0f63db
+	PACKSSWB (BX), X2                       // 660f6313
+	PACKSSWB (R11), X2                      // 66410f6313
+	PACKSSWB X2, X2                         // 660f63d2
+	PACKSSWB X11, X2                        // 66410f63d3
+	PACKSSWB (BX), X11                      // 66440f631b
+	PACKSSWB (R11), X11                     // 66450f631b
+	PACKSSWB X2, X11                        // 66440f63da
+	PACKSSWB X11, X11                       // 66450f63db
+	//TODO: PACKUSDW (BX), X2               // 660f382b13
+	//TODO: PACKUSDW (R11), X2              // 66410f382b13
+	//TODO: PACKUSDW X2, X2                 // 660f382bd2
+	//TODO: PACKUSDW X11, X2                // 66410f382bd3
+	//TODO: PACKUSDW (BX), X11              // 66440f382b1b
+	//TODO: PACKUSDW (R11), X11             // 66450f382b1b
+	//TODO: PACKUSDW X2, X11                // 66440f382bda
+	//TODO: PACKUSDW X11, X11               // 66450f382bdb
+	PACKUSWB (BX), M2                       // 0f6713
+	PACKUSWB (R11), M2                      // 410f6713
+	PACKUSWB M2, M2                         // 0f67d2
+	PACKUSWB M3, M2                         // 0f67d3
+	PACKUSWB (BX), M3                       // 0f671b
+	PACKUSWB (R11), M3                      // 410f671b
+	PACKUSWB M2, M3                         // 0f67da
+	PACKUSWB M3, M3                         // 0f67db
+	PACKUSWB (BX), X2                       // 660f6713
+	PACKUSWB (R11), X2                      // 66410f6713
+	PACKUSWB X2, X2                         // 660f67d2
+	PACKUSWB X11, X2                        // 66410f67d3
+	PACKUSWB (BX), X11                      // 66440f671b
+	PACKUSWB (R11), X11                     // 66450f671b
+	PACKUSWB X2, X11                        // 66440f67da
+	PACKUSWB X11, X11                       // 66450f67db
+	PADDB (BX), M2                          // 0ffc13
+	PADDB (R11), M2                         // 410ffc13
+	PADDB M2, M2                            // 0ffcd2
+	PADDB M3, M2                            // 0ffcd3
+	PADDB (BX), M3                          // 0ffc1b
+	PADDB (R11), M3                         // 410ffc1b
+	PADDB M2, M3                            // 0ffcda
+	PADDB M3, M3                            // 0ffcdb
+	PADDB (BX), X2                          // 660ffc13
+	PADDB (R11), X2                         // 66410ffc13
+	PADDB X2, X2                            // 660ffcd2
+	PADDB X11, X2                           // 66410ffcd3
+	PADDB (BX), X11                         // 66440ffc1b
+	PADDB (R11), X11                        // 66450ffc1b
+	PADDB X2, X11                           // 66440ffcda
+	PADDB X11, X11                          // 66450ffcdb
+	PADDL (BX), M2                          // 0ffe13
+	PADDL (R11), M2                         // 410ffe13
+	PADDL M2, M2                            // 0ffed2
+	PADDL M3, M2                            // 0ffed3
+	PADDL (BX), M3                          // 0ffe1b
+	PADDL (R11), M3                         // 410ffe1b
+	PADDL M2, M3                            // 0ffeda
+	PADDL M3, M3                            // 0ffedb
+	PADDL (BX), X2                          // 660ffe13
+	PADDL (R11), X2                         // 66410ffe13
+	PADDL X2, X2                            // 660ffed2
+	PADDL X11, X2                           // 66410ffed3
+	PADDL (BX), X11                         // 66440ffe1b
+	PADDL (R11), X11                        // 66450ffe1b
+	PADDL X2, X11                           // 66440ffeda
+	PADDL X11, X11                          // 66450ffedb
+	//TODO: PADDQ (BX), M2                  // 0fd413
+	//TODO: PADDQ (R11), M2                 // 410fd413
+	//TODO: PADDQ M2, M2                    // 0fd4d2
+	//TODO: PADDQ M3, M2                    // 0fd4d3
+	//TODO: PADDQ (BX), M3                  // 0fd41b
+	//TODO: PADDQ (R11), M3                 // 410fd41b
+	//TODO: PADDQ M2, M3                    // 0fd4da
+	//TODO: PADDQ M3, M3                    // 0fd4db
+	PADDQ (BX), X2                          // 660fd413
+	PADDQ (R11), X2                         // 66410fd413
+	PADDQ X2, X2                            // 660fd4d2
+	PADDQ X11, X2                           // 66410fd4d3
+	PADDQ (BX), X11                         // 66440fd41b
+	PADDQ (R11), X11                        // 66450fd41b
+	PADDQ X2, X11                           // 66440fd4da
+	PADDQ X11, X11                          // 66450fd4db
+	PADDSB (BX), M2                         // 0fec13
+	PADDSB (R11), M2                        // 410fec13
+	PADDSB M2, M2                           // 0fecd2
+	PADDSB M3, M2                           // 0fecd3
+	PADDSB (BX), M3                         // 0fec1b
+	PADDSB (R11), M3                        // 410fec1b
+	PADDSB M2, M3                           // 0fecda
+	PADDSB M3, M3                           // 0fecdb
+	PADDSB (BX), X2                         // 660fec13
+	PADDSB (R11), X2                        // 66410fec13
+	PADDSB X2, X2                           // 660fecd2
+	PADDSB X11, X2                          // 66410fecd3
+	PADDSB (BX), X11                        // 66440fec1b
+	PADDSB (R11), X11                       // 66450fec1b
+	PADDSB X2, X11                          // 66440fecda
+	PADDSB X11, X11                         // 66450fecdb
+	PADDSW (BX), M2                         // 0fed13
+	PADDSW (R11), M2                        // 410fed13
+	PADDSW M2, M2                           // 0fedd2
+	PADDSW M3, M2                           // 0fedd3
+	PADDSW (BX), M3                         // 0fed1b
+	PADDSW (R11), M3                        // 410fed1b
+	PADDSW M2, M3                           // 0fedda
+	PADDSW M3, M3                           // 0feddb
+	PADDSW (BX), X2                         // 660fed13
+	PADDSW (R11), X2                        // 66410fed13
+	PADDSW X2, X2                           // 660fedd2
+	PADDSW X11, X2                          // 66410fedd3
+	PADDSW (BX), X11                        // 66440fed1b
+	PADDSW (R11), X11                       // 66450fed1b
+	PADDSW X2, X11                          // 66440fedda
+	PADDSW X11, X11                         // 66450feddb
+	PADDUSB (BX), M2                        // 0fdc13
+	PADDUSB (R11), M2                       // 410fdc13
+	PADDUSB M2, M2                          // 0fdcd2
+	PADDUSB M3, M2                          // 0fdcd3
+	PADDUSB (BX), M3                        // 0fdc1b
+	PADDUSB (R11), M3                       // 410fdc1b
+	PADDUSB M2, M3                          // 0fdcda
+	PADDUSB M3, M3                          // 0fdcdb
+	PADDUSB (BX), X2                        // 660fdc13
+	PADDUSB (R11), X2                       // 66410fdc13
+	PADDUSB X2, X2                          // 660fdcd2
+	PADDUSB X11, X2                         // 66410fdcd3
+	PADDUSB (BX), X11                       // 66440fdc1b
+	PADDUSB (R11), X11                      // 66450fdc1b
+	PADDUSB X2, X11                         // 66440fdcda
+	PADDUSB X11, X11                        // 66450fdcdb
+	PADDUSW (BX), M2                        // 0fdd13
+	PADDUSW (R11), M2                       // 410fdd13
+	PADDUSW M2, M2                          // 0fddd2
+	PADDUSW M3, M2                          // 0fddd3
+	PADDUSW (BX), M3                        // 0fdd1b
+	PADDUSW (R11), M3                       // 410fdd1b
+	PADDUSW M2, M3                          // 0fddda
+	PADDUSW M3, M3                          // 0fdddb
+	PADDUSW (BX), X2                        // 660fdd13
+	PADDUSW (R11), X2                       // 66410fdd13
+	PADDUSW X2, X2                          // 660fddd2
+	PADDUSW X11, X2                         // 66410fddd3
+	PADDUSW (BX), X11                       // 66440fdd1b
+	PADDUSW (R11), X11                      // 66450fdd1b
+	PADDUSW X2, X11                         // 66440fddda
+	PADDUSW X11, X11                        // 66450fdddb
+	PADDW (BX), M2                          // 0ffd13
+	PADDW (R11), M2                         // 410ffd13
+	PADDW M2, M2                            // 0ffdd2
+	PADDW M3, M2                            // 0ffdd3
+	PADDW (BX), M3                          // 0ffd1b
+	PADDW (R11), M3                         // 410ffd1b
+	PADDW M2, M3                            // 0ffdda
+	PADDW M3, M3                            // 0ffddb
+	PADDW (BX), X2                          // 660ffd13
+	PADDW (R11), X2                         // 66410ffd13
+	PADDW X2, X2                            // 660ffdd2
+	PADDW X11, X2                           // 66410ffdd3
+	PADDW (BX), X11                         // 66440ffd1b
+	PADDW (R11), X11                        // 66450ffd1b
+	PADDW X2, X11                           // 66440ffdda
+	PADDW X11, X11                          // 66450ffddb
+	//TODO: PALIGNR $7, (BX), M2            // 0f3a0f1307
+	//TODO: PALIGNR $7, (R11), M2           // 410f3a0f1307
+	//TODO: PALIGNR $7, M2, M2              // 0f3a0fd207
+	//TODO: PALIGNR $7, M3, M2              // 0f3a0fd307
+	//TODO: PALIGNR $7, (BX), M3            // 0f3a0f1b07
+	//TODO: PALIGNR $7, (R11), M3           // 410f3a0f1b07
+	//TODO: PALIGNR $7, M2, M3              // 0f3a0fda07
+	//TODO: PALIGNR $7, M3, M3              // 0f3a0fdb07
+	//TODO: PALIGNR $7, (BX), X2            // 660f3a0f1307
+	//TODO: PALIGNR $7, (R11), X2           // 66410f3a0f1307
+	//TODO: PALIGNR $7, X2, X2              // 660f3a0fd207
+	//TODO: PALIGNR $7, X11, X2             // 66410f3a0fd307
+	//TODO: PALIGNR $7, (BX), X11           // 66440f3a0f1b07
+	//TODO: PALIGNR $7, (R11), X11          // 66450f3a0f1b07
+	//TODO: PALIGNR $7, X2, X11             // 66440f3a0fda07
+	//TODO: PALIGNR $7, X11, X11            // 66450f3a0fdb07
+	PAND (BX), M2                           // 0fdb13
+	PAND (R11), M2                          // 410fdb13
+	PAND M2, M2                             // 0fdbd2
+	PAND M3, M2                             // 0fdbd3
+	PAND (BX), M3                           // 0fdb1b
+	PAND (R11), M3                          // 410fdb1b
+	PAND M2, M3                             // 0fdbda
+	PAND M3, M3                             // 0fdbdb
+	PAND (BX), X2                           // 660fdb13
+	PAND (R11), X2                          // 66410fdb13
+	PAND X2, X2                             // 660fdbd2
+	PAND X11, X2                            // 66410fdbd3
+	PAND (BX), X11                          // 66440fdb1b
+	PAND (R11), X11                         // 66450fdb1b
+	PAND X2, X11                            // 66440fdbda
+	PAND X11, X11                           // 66450fdbdb
+	PANDN (BX), M2                          // 0fdf13
+	PANDN (R11), M2                         // 410fdf13
+	PANDN M2, M2                            // 0fdfd2
+	PANDN M3, M2                            // 0fdfd3
+	PANDN (BX), M3                          // 0fdf1b
+	PANDN (R11), M3                         // 410fdf1b
+	PANDN M2, M3                            // 0fdfda
+	PANDN M3, M3                            // 0fdfdb
+	PANDN (BX), X2                          // 660fdf13
+	PANDN (R11), X2                         // 66410fdf13
+	PANDN X2, X2                            // 660fdfd2
+	PANDN X11, X2                           // 66410fdfd3
+	PANDN (BX), X11                         // 66440fdf1b
+	PANDN (R11), X11                        // 66450fdf1b
+	PANDN X2, X11                           // 66440fdfda
+	PANDN X11, X11                          // 66450fdfdb
+	PAVGB (BX), M2                          // 0fe013
+	PAVGB (R11), M2                         // 410fe013
+	PAVGB M2, M2                            // 0fe0d2
+	PAVGB M3, M2                            // 0fe0d3
+	PAVGB (BX), M3                          // 0fe01b
+	PAVGB (R11), M3                         // 410fe01b
+	PAVGB M2, M3                            // 0fe0da
+	PAVGB M3, M3                            // 0fe0db
+	PAVGB (BX), X2                          // 660fe013
+	PAVGB (R11), X2                         // 66410fe013
+	PAVGB X2, X2                            // 660fe0d2
+	PAVGB X11, X2                           // 66410fe0d3
+	PAVGB (BX), X11                         // 66440fe01b
+	PAVGB (R11), X11                        // 66450fe01b
+	PAVGB X2, X11                           // 66440fe0da
+	PAVGB X11, X11                          // 66450fe0db
+	PAVGW (BX), M2                          // 0fe313
+	PAVGW (R11), M2                         // 410fe313
+	PAVGW M2, M2                            // 0fe3d2
+	PAVGW M3, M2                            // 0fe3d3
+	PAVGW (BX), M3                          // 0fe31b
+	PAVGW (R11), M3                         // 410fe31b
+	PAVGW M2, M3                            // 0fe3da
+	PAVGW M3, M3                            // 0fe3db
+	PAVGW (BX), X2                          // 660fe313
+	PAVGW (R11), X2                         // 66410fe313
+	PAVGW X2, X2                            // 660fe3d2
+	PAVGW X11, X2                           // 66410fe3d3
+	PAVGW (BX), X11                         // 66440fe31b
+	PAVGW (R11), X11                        // 66450fe31b
+	PAVGW X2, X11                           // 66440fe3da
+	PAVGW X11, X11                          // 66450fe3db
+	//TODO: PBLENDVB XMM0, (BX), X2         // 660f381013
+	//TODO: PBLENDVB XMM0, (R11), X2        // 66410f381013
+	//TODO: PBLENDVB XMM0, X2, X2           // 660f3810d2
+	//TODO: PBLENDVB XMM0, X11, X2          // 66410f3810d3
+	//TODO: PBLENDVB XMM0, (BX), X11        // 66440f38101b
+	//TODO: PBLENDVB XMM0, (R11), X11       // 66450f38101b
+	//TODO: PBLENDVB XMM0, X2, X11          // 66440f3810da
+	//TODO: PBLENDVB XMM0, X11, X11         // 66450f3810db
+	//TODO: PBLENDW $7, (BX), X2            // 660f3a0e1307
+	//TODO: PBLENDW $7, (R11), X2           // 66410f3a0e1307
+	//TODO: PBLENDW $7, X2, X2              // 660f3a0ed207
+	//TODO: PBLENDW $7, X11, X2             // 66410f3a0ed307
+	//TODO: PBLENDW $7, (BX), X11           // 66440f3a0e1b07
+	//TODO: PBLENDW $7, (R11), X11          // 66450f3a0e1b07
+	//TODO: PBLENDW $7, X2, X11             // 66440f3a0eda07
+	//TODO: PBLENDW $7, X11, X11            // 66450f3a0edb07
+	PCLMULQDQ $7, (BX), X2                  // 660f3a441307
+	PCLMULQDQ $7, (R11), X2                 // 66410f3a441307
+	PCLMULQDQ $7, X2, X2                    // 660f3a44d207
+	PCLMULQDQ $7, X11, X2                   // 66410f3a44d307
+	PCLMULQDQ $7, (BX), X11                 // 66440f3a441b07
+	PCLMULQDQ $7, (R11), X11                // 66450f3a441b07
+	PCLMULQDQ $7, X2, X11                   // 66440f3a44da07
+	PCLMULQDQ $7, X11, X11                  // 66450f3a44db07
+	PCMPEQB (BX), M2                        // 0f7413
+	PCMPEQB (R11), M2                       // 410f7413
+	PCMPEQB M2, M2                          // 0f74d2
+	PCMPEQB M3, M2                          // 0f74d3
+	PCMPEQB (BX), M3                        // 0f741b
+	PCMPEQB (R11), M3                       // 410f741b
+	PCMPEQB M2, M3                          // 0f74da
+	PCMPEQB M3, M3                          // 0f74db
+	PCMPEQB (BX), X2                        // 660f7413
+	PCMPEQB (R11), X2                       // 66410f7413
+	PCMPEQB X2, X2                          // 660f74d2
+	PCMPEQB X11, X2                         // 66410f74d3
+	PCMPEQB (BX), X11                       // 66440f741b
+	PCMPEQB (R11), X11                      // 66450f741b
+	PCMPEQB X2, X11                         // 66440f74da
+	PCMPEQB X11, X11                        // 66450f74db
+	PCMPEQL (BX), M2                        // 0f7613
+	PCMPEQL (R11), M2                       // 410f7613
+	PCMPEQL M2, M2                          // 0f76d2
+	PCMPEQL M3, M2                          // 0f76d3
+	PCMPEQL (BX), M3                        // 0f761b
+	PCMPEQL (R11), M3                       // 410f761b
+	PCMPEQL M2, M3                          // 0f76da
+	PCMPEQL M3, M3                          // 0f76db
+	PCMPEQL (BX), X2                        // 660f7613
+	PCMPEQL (R11), X2                       // 66410f7613
+	PCMPEQL X2, X2                          // 660f76d2
+	PCMPEQL X11, X2                         // 66410f76d3
+	PCMPEQL (BX), X11                       // 66440f761b
+	PCMPEQL (R11), X11                      // 66450f761b
+	PCMPEQL X2, X11                         // 66440f76da
+	PCMPEQL X11, X11                        // 66450f76db
+	//TODO: PCMPEQQ (BX), X2                // 660f382913
+	//TODO: PCMPEQQ (R11), X2               // 66410f382913
+	//TODO: PCMPEQQ X2, X2                  // 660f3829d2
+	//TODO: PCMPEQQ X11, X2                 // 66410f3829d3
+	//TODO: PCMPEQQ (BX), X11               // 66440f38291b
+	//TODO: PCMPEQQ (R11), X11              // 66450f38291b
+	//TODO: PCMPEQQ X2, X11                 // 66440f3829da
+	//TODO: PCMPEQQ X11, X11                // 66450f3829db
+	PCMPEQW (BX), M2                        // 0f7513
+	PCMPEQW (R11), M2                       // 410f7513
+	PCMPEQW M2, M2                          // 0f75d2
+	PCMPEQW M3, M2                          // 0f75d3
+	PCMPEQW (BX), M3                        // 0f751b
+	PCMPEQW (R11), M3                       // 410f751b
+	PCMPEQW M2, M3                          // 0f75da
+	PCMPEQW M3, M3                          // 0f75db
+	PCMPEQW (BX), X2                        // 660f7513
+	PCMPEQW (R11), X2                       // 66410f7513
+	PCMPEQW X2, X2                          // 660f75d2
+	PCMPEQW X11, X2                         // 66410f75d3
+	PCMPEQW (BX), X11                       // 66440f751b
+	PCMPEQW (R11), X11                      // 66450f751b
+	PCMPEQW X2, X11                         // 66440f75da
+	PCMPEQW X11, X11                        // 66450f75db
+	//TODO: PCMPESTRI $7, (BX), X2          // 660f3a611307
+	//TODO: PCMPESTRI $7, (R11), X2         // 66410f3a611307
+	//TODO: PCMPESTRI $7, X2, X2            // 660f3a61d207
+	//TODO: PCMPESTRI $7, X11, X2           // 66410f3a61d307
+	//TODO: PCMPESTRI $7, (BX), X11         // 66440f3a611b07
+	//TODO: PCMPESTRI $7, (R11), X11        // 66450f3a611b07
+	//TODO: PCMPESTRI $7, X2, X11           // 66440f3a61da07
+	//TODO: PCMPESTRI $7, X11, X11          // 66450f3a61db07
+	//TODO: PCMPESTRM $7, (BX), X2          // 660f3a601307
+	//TODO: PCMPESTRM $7, (R11), X2         // 66410f3a601307
+	//TODO: PCMPESTRM $7, X2, X2            // 660f3a60d207
+	//TODO: PCMPESTRM $7, X11, X2           // 66410f3a60d307
+	//TODO: PCMPESTRM $7, (BX), X11         // 66440f3a601b07
+	//TODO: PCMPESTRM $7, (R11), X11        // 66450f3a601b07
+	//TODO: PCMPESTRM $7, X2, X11           // 66440f3a60da07
+	//TODO: PCMPESTRM $7, X11, X11          // 66450f3a60db07
+	PCMPGTB (BX), M2                        // 0f6413
+	PCMPGTB (R11), M2                       // 410f6413
+	PCMPGTB M2, M2                          // 0f64d2
+	PCMPGTB M3, M2                          // 0f64d3
+	PCMPGTB (BX), M3                        // 0f641b
+	PCMPGTB (R11), M3                       // 410f641b
+	PCMPGTB M2, M3                          // 0f64da
+	PCMPGTB M3, M3                          // 0f64db
+	PCMPGTB (BX), X2                        // 660f6413
+	PCMPGTB (R11), X2                       // 66410f6413
+	PCMPGTB X2, X2                          // 660f64d2
+	PCMPGTB X11, X2                         // 66410f64d3
+	PCMPGTB (BX), X11                       // 66440f641b
+	PCMPGTB (R11), X11                      // 66450f641b
+	PCMPGTB X2, X11                         // 66440f64da
+	PCMPGTB X11, X11                        // 66450f64db
+	PCMPGTL (BX), M2                        // 0f6613
+	PCMPGTL (R11), M2                       // 410f6613
+	PCMPGTL M2, M2                          // 0f66d2
+	PCMPGTL M3, M2                          // 0f66d3
+	PCMPGTL (BX), M3                        // 0f661b
+	PCMPGTL (R11), M3                       // 410f661b
+	PCMPGTL M2, M3                          // 0f66da
+	PCMPGTL M3, M3                          // 0f66db
+	PCMPGTL (BX), X2                        // 660f6613
+	PCMPGTL (R11), X2                       // 66410f6613
+	PCMPGTL X2, X2                          // 660f66d2
+	PCMPGTL X11, X2                         // 66410f66d3
+	PCMPGTL (BX), X11                       // 66440f661b
+	PCMPGTL (R11), X11                      // 66450f661b
+	PCMPGTL X2, X11                         // 66440f66da
+	PCMPGTL X11, X11                        // 66450f66db
+	//TODO: PCMPGTQ (BX), X2                // 660f383713
+	//TODO: PCMPGTQ (R11), X2               // 66410f383713
+	//TODO: PCMPGTQ X2, X2                  // 660f3837d2
+	//TODO: PCMPGTQ X11, X2                 // 66410f3837d3
+	//TODO: PCMPGTQ (BX), X11               // 66440f38371b
+	//TODO: PCMPGTQ (R11), X11              // 66450f38371b
+	//TODO: PCMPGTQ X2, X11                 // 66440f3837da
+	//TODO: PCMPGTQ X11, X11                // 66450f3837db
+	PCMPGTW (BX), M2                        // 0f6513
+	PCMPGTW (R11), M2                       // 410f6513
+	PCMPGTW M2, M2                          // 0f65d2
+	PCMPGTW M3, M2                          // 0f65d3
+	PCMPGTW (BX), M3                        // 0f651b
+	PCMPGTW (R11), M3                       // 410f651b
+	PCMPGTW M2, M3                          // 0f65da
+	PCMPGTW M3, M3                          // 0f65db
+	PCMPGTW (BX), X2                        // 660f6513
+	PCMPGTW (R11), X2                       // 66410f6513
+	PCMPGTW X2, X2                          // 660f65d2
+	PCMPGTW X11, X2                         // 66410f65d3
+	PCMPGTW (BX), X11                       // 66440f651b
+	PCMPGTW (R11), X11                      // 66450f651b
+	PCMPGTW X2, X11                         // 66440f65da
+	PCMPGTW X11, X11                        // 66450f65db
+	//TODO: PCMPISTRI $7, (BX), X2          // 660f3a631307
+	//TODO: PCMPISTRI $7, (R11), X2         // 66410f3a631307
+	//TODO: PCMPISTRI $7, X2, X2            // 660f3a63d207
+	//TODO: PCMPISTRI $7, X11, X2           // 66410f3a63d307
+	//TODO: PCMPISTRI $7, (BX), X11         // 66440f3a631b07
+	//TODO: PCMPISTRI $7, (R11), X11        // 66450f3a631b07
+	//TODO: PCMPISTRI $7, X2, X11           // 66440f3a63da07
+	//TODO: PCMPISTRI $7, X11, X11          // 66450f3a63db07
+	//TODO: PCMPISTRM $7, (BX), X2          // 660f3a621307
+	//TODO: PCMPISTRM $7, (R11), X2         // 66410f3a621307
+	//TODO: PCMPISTRM $7, X2, X2            // 660f3a62d207
+	//TODO: PCMPISTRM $7, X11, X2           // 66410f3a62d307
+	//TODO: PCMPISTRM $7, (BX), X11         // 66440f3a621b07
+	//TODO: PCMPISTRM $7, (R11), X11        // 66450f3a621b07
+	//TODO: PCMPISTRM $7, X2, X11           // 66440f3a62da07
+	//TODO: PCMPISTRM $7, X11, X11          // 66450f3a62db07
+	PDEPL (BX), R9, DX                      // c4e233f513
+	PDEPL (R11), R9, DX                     // c4c233f513
+	PDEPL DX, R9, DX                        // c4e233f5d2
+	PDEPL R11, R9, DX                       // c4c233f5d3
+	PDEPL (BX), R9, R11                     // c46233f51b
+	PDEPL (R11), R9, R11                    // c44233f51b
+	PDEPL DX, R9, R11                       // c46233f5da
+	PDEPL R11, R9, R11                      // c44233f5db
+	PDEPQ (BX), R14, DX                     // c4e28bf513
+	PDEPQ (R11), R14, DX                    // c4c28bf513
+	PDEPQ DX, R14, DX                       // c4e28bf5d2
+	PDEPQ R11, R14, DX                      // c4c28bf5d3
+	PDEPQ (BX), R14, R11                    // c4628bf51b
+	PDEPQ (R11), R14, R11                   // c4428bf51b
+	PDEPQ DX, R14, R11                      // c4628bf5da
+	PDEPQ R11, R14, R11                     // c4428bf5db
+	PEXTL (BX), R9, DX                      // c4e232f513
+	PEXTL (R11), R9, DX                     // c4c232f513
+	PEXTL DX, R9, DX                        // c4e232f5d2
+	PEXTL R11, R9, DX                       // c4c232f5d3
+	PEXTL (BX), R9, R11                     // c46232f51b
+	PEXTL (R11), R9, R11                    // c44232f51b
+	PEXTL DX, R9, R11                       // c46232f5da
+	PEXTL R11, R9, R11                      // c44232f5db
+	PEXTQ (BX), R14, DX                     // c4e28af513
+	PEXTQ (R11), R14, DX                    // c4c28af513
+	PEXTQ DX, R14, DX                       // c4e28af5d2
+	PEXTQ R11, R14, DX                      // c4c28af5d3
+	PEXTQ (BX), R14, R11                    // c4628af51b
+	PEXTQ (R11), R14, R11                   // c4428af51b
+	PEXTQ DX, R14, R11                      // c4628af5da
+	PEXTQ R11, R14, R11                     // c4428af5db
+	PEXTRB $7, X2, (BX)                     // 660f3a141307
+	PEXTRB $7, X11, (BX)                    // 66440f3a141b07
+	PEXTRB $7, X2, (R11)                    // 66410f3a141307
+	PEXTRB $7, X11, (R11)                   // 66450f3a141b07
+	PEXTRB $7, X2, DX                       // 660f3a14d207
+	PEXTRB $7, X11, DX                      // 66440f3a14da07
+	PEXTRB $7, X2, R11                      // 66410f3a14d307
+	PEXTRB $7, X11, R11                     // 66450f3a14db07
+	PEXTRD $7, X2, (BX)                     // 660f3a161307
+	PEXTRD $7, X11, (BX)                    // 66440f3a161b07
+	PEXTRD $7, X2, (R11)                    // 66410f3a161307
+	PEXTRD $7, X11, (R11)                   // 66450f3a161b07
+	PEXTRD $7, X2, DX                       // 660f3a16d207
+	PEXTRD $7, X11, DX                      // 66440f3a16da07
+	PEXTRD $7, X2, R11                      // 66410f3a16d307
+	PEXTRD $7, X11, R11                     // 66450f3a16db07
+	PEXTRQ $7, X2, (BX)                     // 66480f3a161307
+	PEXTRQ $7, X11, (BX)                    // 664c0f3a161b07
+	PEXTRQ $7, X2, (R11)                    // 66490f3a161307
+	PEXTRQ $7, X11, (R11)                   // 664d0f3a161b07
+	PEXTRQ $7, X2, DX                       // 66480f3a16d207
+	PEXTRQ $7, X11, DX                      // 664c0f3a16da07
+	PEXTRQ $7, X2, R11                      // 66490f3a16d307
+	PEXTRQ $7, X11, R11                     // 664d0f3a16db07
+	//TODO: PEXTRW $7, M2, DX               // 0fc5d207
+	//TODO: PEXTRW $7, M3, DX               // 0fc5d307
+	//TODO: PEXTRW $7, M2, R11              // 440fc5da07
+	//TODO: PEXTRW $7, M3, R11              // 440fc5db07
+	PEXTRW $7, X2, DX                       // 660fc5d207 or 660f3a15d207
+	PEXTRW $7, X11, DX                      // 66410fc5d307 or 66440f3a15da07
+	PEXTRW $7, X2, R11                      // 66440fc5da07 or 66410f3a15d307
+	PEXTRW $7, X11, R11                     // 66450fc5db07 or 66450f3a15db07
+	//TODO: PEXTRW $7, X2, (BX)             // 660f3a151307
+	//TODO: PEXTRW $7, X11, (BX)            // 66440f3a151b07
+	//TODO: PEXTRW $7, X2, (R11)            // 66410f3a151307
+	//TODO: PEXTRW $7, X11, (R11)           // 66450f3a151b07
+	PHADDD (BX), M2                         // 0f380213
+	PHADDD (R11), M2                        // 410f380213
+	PHADDD M2, M2                           // 0f3802d2
+	PHADDD M3, M2                           // 0f3802d3
+	PHADDD (BX), M3                         // 0f38021b
+	PHADDD (R11), M3                        // 410f38021b
+	PHADDD M2, M3                           // 0f3802da
+	PHADDD M3, M3                           // 0f3802db
+	PHADDD (BX), X2                         // 660f380213
+	PHADDD (R11), X2                        // 66410f380213
+	PHADDD X2, X2                           // 660f3802d2
+	PHADDD X11, X2                          // 66410f3802d3
+	PHADDD (BX), X11                        // 66440f38021b
+	PHADDD (R11), X11                       // 66450f38021b
+	PHADDD X2, X11                          // 66440f3802da
+	PHADDD X11, X11                         // 66450f3802db
+	//TODO: PHADDSW (BX), M2                // 0f380313
+	//TODO: PHADDSW (R11), M2               // 410f380313
+	//TODO: PHADDSW M2, M2                  // 0f3803d2
+	//TODO: PHADDSW M3, M2                  // 0f3803d3
+	//TODO: PHADDSW (BX), M3                // 0f38031b
+	//TODO: PHADDSW (R11), M3               // 410f38031b
+	//TODO: PHADDSW M2, M3                  // 0f3803da
+	//TODO: PHADDSW M3, M3                  // 0f3803db
+	//TODO: PHADDSW (BX), X2                // 660f380313
+	//TODO: PHADDSW (R11), X2               // 66410f380313
+	//TODO: PHADDSW X2, X2                  // 660f3803d2
+	//TODO: PHADDSW X11, X2                 // 66410f3803d3
+	//TODO: PHADDSW (BX), X11               // 66440f38031b
+	//TODO: PHADDSW (R11), X11              // 66450f38031b
+	//TODO: PHADDSW X2, X11                 // 66440f3803da
+	//TODO: PHADDSW X11, X11                // 66450f3803db
+	//TODO: PHADDW (BX), M2                 // 0f380113
+	//TODO: PHADDW (R11), M2                // 410f380113
+	//TODO: PHADDW M2, M2                   // 0f3801d2
+	//TODO: PHADDW M3, M2                   // 0f3801d3
+	//TODO: PHADDW (BX), M3                 // 0f38011b
+	//TODO: PHADDW (R11), M3                // 410f38011b
+	//TODO: PHADDW M2, M3                   // 0f3801da
+	//TODO: PHADDW M3, M3                   // 0f3801db
+	//TODO: PHADDW (BX), X2                 // 660f380113
+	//TODO: PHADDW (R11), X2                // 66410f380113
+	//TODO: PHADDW X2, X2                   // 660f3801d2
+	//TODO: PHADDW X11, X2                  // 66410f3801d3
+	//TODO: PHADDW (BX), X11                // 66440f38011b
+	//TODO: PHADDW (R11), X11               // 66450f38011b
+	//TODO: PHADDW X2, X11                  // 66440f3801da
+	//TODO: PHADDW X11, X11                 // 66450f3801db
+	//TODO: PHMINPOSUW (BX), X2             // 660f384113
+	//TODO: PHMINPOSUW (R11), X2            // 66410f384113
+	//TODO: PHMINPOSUW X2, X2               // 660f3841d2
+	//TODO: PHMINPOSUW X11, X2              // 66410f3841d3
+	//TODO: PHMINPOSUW (BX), X11            // 66440f38411b
+	//TODO: PHMINPOSUW (R11), X11           // 66450f38411b
+	//TODO: PHMINPOSUW X2, X11              // 66440f3841da
+	//TODO: PHMINPOSUW X11, X11             // 66450f3841db
+	//TODO: PHSUBD (BX), M2                 // 0f380613
+	//TODO: PHSUBD (R11), M2                // 410f380613
+	//TODO: PHSUBD M2, M2                   // 0f3806d2
+	//TODO: PHSUBD M3, M2                   // 0f3806d3
+	//TODO: PHSUBD (BX), M3                 // 0f38061b
+	//TODO: PHSUBD (R11), M3                // 410f38061b
+	//TODO: PHSUBD M2, M3                   // 0f3806da
+	//TODO: PHSUBD M3, M3                   // 0f3806db
+	//TODO: PHSUBD (BX), X2                 // 660f380613
+	//TODO: PHSUBD (R11), X2                // 66410f380613
+	//TODO: PHSUBD X2, X2                   // 660f3806d2
+	//TODO: PHSUBD X11, X2                  // 66410f3806d3
+	//TODO: PHSUBD (BX), X11                // 66440f38061b
+	//TODO: PHSUBD (R11), X11               // 66450f38061b
+	//TODO: PHSUBD X2, X11                  // 66440f3806da
+	//TODO: PHSUBD X11, X11                 // 66450f3806db
+	//TODO: PHSUBSW (BX), M2                // 0f380713
+	//TODO: PHSUBSW (R11), M2               // 410f380713
+	//TODO: PHSUBSW M2, M2                  // 0f3807d2
+	//TODO: PHSUBSW M3, M2                  // 0f3807d3
+	//TODO: PHSUBSW (BX), M3                // 0f38071b
+	//TODO: PHSUBSW (R11), M3               // 410f38071b
+	//TODO: PHSUBSW M2, M3                  // 0f3807da
+	//TODO: PHSUBSW M3, M3                  // 0f3807db
+	//TODO: PHSUBSW (BX), X2                // 660f380713
+	//TODO: PHSUBSW (R11), X2               // 66410f380713
+	//TODO: PHSUBSW X2, X2                  // 660f3807d2
+	//TODO: PHSUBSW X11, X2                 // 66410f3807d3
+	//TODO: PHSUBSW (BX), X11               // 66440f38071b
+	//TODO: PHSUBSW (R11), X11              // 66450f38071b
+	//TODO: PHSUBSW X2, X11                 // 66440f3807da
+	//TODO: PHSUBSW X11, X11                // 66450f3807db
+	//TODO: PHSUBW (BX), M2                 // 0f380513
+	//TODO: PHSUBW (R11), M2                // 410f380513
+	//TODO: PHSUBW M2, M2                   // 0f3805d2
+	//TODO: PHSUBW M3, M2                   // 0f3805d3
+	//TODO: PHSUBW (BX), M3                 // 0f38051b
+	//TODO: PHSUBW (R11), M3                // 410f38051b
+	//TODO: PHSUBW M2, M3                   // 0f3805da
+	//TODO: PHSUBW M3, M3                   // 0f3805db
+	//TODO: PHSUBW (BX), X2                 // 660f380513
+	//TODO: PHSUBW (R11), X2                // 66410f380513
+	//TODO: PHSUBW X2, X2                   // 660f3805d2
+	//TODO: PHSUBW X11, X2                  // 66410f3805d3
+	//TODO: PHSUBW (BX), X11                // 66440f38051b
+	//TODO: PHSUBW (R11), X11               // 66450f38051b
+	//TODO: PHSUBW X2, X11                  // 66440f3805da
+	//TODO: PHSUBW X11, X11                 // 66450f3805db
+	PINSRB $7, (BX), X2                     // 660f3a201307
+	PINSRB $7, (R11), X2                    // 66410f3a201307
+	PINSRB $7, DX, X2                       // 660f3a20d207
+	PINSRB $7, R11, X2                      // 66410f3a20d307
+	PINSRB $7, (BX), X11                    // 66440f3a201b07
+	PINSRB $7, (R11), X11                   // 66450f3a201b07
+	PINSRB $7, DX, X11                      // 66440f3a20da07
+	PINSRB $7, R11, X11                     // 66450f3a20db07
+	PINSRD $7, (BX), X2                     // 660f3a221307
+	PINSRD $7, (R11), X2                    // 66410f3a221307
+	PINSRD $7, DX, X2                       // 660f3a22d207
+	PINSRD $7, R11, X2                      // 66410f3a22d307
+	PINSRD $7, (BX), X11                    // 66440f3a221b07
+	PINSRD $7, (R11), X11                   // 66450f3a221b07
+	PINSRD $7, DX, X11                      // 66440f3a22da07
+	PINSRD $7, R11, X11                     // 66450f3a22db07
+	PINSRQ $7, (BX), X2                     // 66480f3a221307
+	PINSRQ $7, (R11), X2                    // 66490f3a221307
+	PINSRQ $7, DX, X2                       // 66480f3a22d207
+	PINSRQ $7, R11, X2                      // 66490f3a22d307
+	PINSRQ $7, (BX), X11                    // 664c0f3a221b07
+	PINSRQ $7, (R11), X11                   // 664d0f3a221b07
+	PINSRQ $7, DX, X11                      // 664c0f3a22da07
+	PINSRQ $7, R11, X11                     // 664d0f3a22db07
+	//TODO: PINSRW $7, (BX), M2             // 0fc41307
+	//TODO: PINSRW $7, (R11), M2            // 410fc41307
+	//TODO: PINSRW $7, DX, M2               // 0fc4d207
+	//TODO: PINSRW $7, R11, M2              // 410fc4d307
+	//TODO: PINSRW $7, (BX), M3             // 0fc41b07
+	//TODO: PINSRW $7, (R11), M3            // 410fc41b07
+	//TODO: PINSRW $7, DX, M3               // 0fc4da07
+	//TODO: PINSRW $7, R11, M3              // 410fc4db07
+	PINSRW $7, (BX), X2                     // 660fc41307
+	PINSRW $7, (R11), X2                    // 66410fc41307
+	PINSRW $7, DX, X2                       // 660fc4d207
+	PINSRW $7, R11, X2                      // 66410fc4d307
+	PINSRW $7, (BX), X11                    // 66440fc41b07
+	PINSRW $7, (R11), X11                   // 66450fc41b07
+	PINSRW $7, DX, X11                      // 66440fc4da07
+	PINSRW $7, R11, X11                     // 66450fc4db07
+	//TODO: PMADDUBSW (BX), M2              // 0f380413
+	//TODO: PMADDUBSW (R11), M2             // 410f380413
+	//TODO: PMADDUBSW M2, M2                // 0f3804d2
+	//TODO: PMADDUBSW M3, M2                // 0f3804d3
+	//TODO: PMADDUBSW (BX), M3              // 0f38041b
+	//TODO: PMADDUBSW (R11), M3             // 410f38041b
+	//TODO: PMADDUBSW M2, M3                // 0f3804da
+	//TODO: PMADDUBSW M3, M3                // 0f3804db
+	//TODO: PMADDUBSW (BX), X2              // 660f380413
+	//TODO: PMADDUBSW (R11), X2             // 66410f380413
+	//TODO: PMADDUBSW X2, X2                // 660f3804d2
+	//TODO: PMADDUBSW X11, X2               // 66410f3804d3
+	//TODO: PMADDUBSW (BX), X11             // 66440f38041b
+	//TODO: PMADDUBSW (R11), X11            // 66450f38041b
+	//TODO: PMADDUBSW X2, X11               // 66440f3804da
+	//TODO: PMADDUBSW X11, X11              // 66450f3804db
+	PMADDWL (BX), M2                        // 0ff513
+	PMADDWL (R11), M2                       // 410ff513
+	PMADDWL M2, M2                          // 0ff5d2
+	PMADDWL M3, M2                          // 0ff5d3
+	PMADDWL (BX), M3                        // 0ff51b
+	PMADDWL (R11), M3                       // 410ff51b
+	PMADDWL M2, M3                          // 0ff5da
+	PMADDWL M3, M3                          // 0ff5db
+	PMADDWL (BX), X2                        // 660ff513
+	PMADDWL (R11), X2                       // 66410ff513
+	PMADDWL X2, X2                          // 660ff5d2
+	PMADDWL X11, X2                         // 66410ff5d3
+	PMADDWL (BX), X11                       // 66440ff51b
+	PMADDWL (R11), X11                      // 66450ff51b
+	PMADDWL X2, X11                         // 66440ff5da
+	PMADDWL X11, X11                        // 66450ff5db
+	//TODO: PMAXSB (BX), X2                 // 660f383c13
+	//TODO: PMAXSB (R11), X2                // 66410f383c13
+	//TODO: PMAXSB X2, X2                   // 660f383cd2
+	//TODO: PMAXSB X11, X2                  // 66410f383cd3
+	//TODO: PMAXSB (BX), X11                // 66440f383c1b
+	//TODO: PMAXSB (R11), X11               // 66450f383c1b
+	//TODO: PMAXSB X2, X11                  // 66440f383cda
+	//TODO: PMAXSB X11, X11                 // 66450f383cdb
+	//TODO: PMAXSD (BX), X2                 // 660f383d13
+	//TODO: PMAXSD (R11), X2                // 66410f383d13
+	//TODO: PMAXSD X2, X2                   // 660f383dd2
+	//TODO: PMAXSD X11, X2                  // 66410f383dd3
+	//TODO: PMAXSD (BX), X11                // 66440f383d1b
+	//TODO: PMAXSD (R11), X11               // 66450f383d1b
+	//TODO: PMAXSD X2, X11                  // 66440f383dda
+	//TODO: PMAXSD X11, X11                 // 66450f383ddb
+	//TODO: PMAXSW (BX), M2                 // 0fee13
+	//TODO: PMAXSW (R11), M2                // 410fee13
+	//TODO: PMAXSW M2, M2                   // 0feed2
+	//TODO: PMAXSW M3, M2                   // 0feed3
+	//TODO: PMAXSW (BX), M3                 // 0fee1b
+	//TODO: PMAXSW (R11), M3                // 410fee1b
+	//TODO: PMAXSW M2, M3                   // 0feeda
+	//TODO: PMAXSW M3, M3                   // 0feedb
+	PMAXSW (BX), X2                         // 660fee13
+	PMAXSW (R11), X2                        // 66410fee13
+	PMAXSW X2, X2                           // 660feed2
+	PMAXSW X11, X2                          // 66410feed3
+	PMAXSW (BX), X11                        // 66440fee1b
+	PMAXSW (R11), X11                       // 66450fee1b
+	PMAXSW X2, X11                          // 66440feeda
+	PMAXSW X11, X11                         // 66450feedb
+	//TODO: PMAXUB (BX), M2                 // 0fde13
+	//TODO: PMAXUB (R11), M2                // 410fde13
+	//TODO: PMAXUB M2, M2                   // 0fded2
+	//TODO: PMAXUB M3, M2                   // 0fded3
+	//TODO: PMAXUB (BX), M3                 // 0fde1b
+	//TODO: PMAXUB (R11), M3                // 410fde1b
+	//TODO: PMAXUB M2, M3                   // 0fdeda
+	//TODO: PMAXUB M3, M3                   // 0fdedb
+	PMAXUB (BX), X2                         // 660fde13
+	PMAXUB (R11), X2                        // 66410fde13
+	PMAXUB X2, X2                           // 660fded2
+	PMAXUB X11, X2                          // 66410fded3
+	PMAXUB (BX), X11                        // 66440fde1b
+	PMAXUB (R11), X11                       // 66450fde1b
+	PMAXUB X2, X11                          // 66440fdeda
+	PMAXUB X11, X11                         // 66450fdedb
+	//TODO: PMAXUD (BX), X2                 // 660f383f13
+	//TODO: PMAXUD (R11), X2                // 66410f383f13
+	//TODO: PMAXUD X2, X2                   // 660f383fd2
+	//TODO: PMAXUD X11, X2                  // 66410f383fd3
+	//TODO: PMAXUD (BX), X11                // 66440f383f1b
+	//TODO: PMAXUD (R11), X11               // 66450f383f1b
+	//TODO: PMAXUD X2, X11                  // 66440f383fda
+	//TODO: PMAXUD X11, X11                 // 66450f383fdb
+	//TODO: PMAXUW (BX), X2                 // 660f383e13
+	//TODO: PMAXUW (R11), X2                // 66410f383e13
+	//TODO: PMAXUW X2, X2                   // 660f383ed2
+	//TODO: PMAXUW X11, X2                  // 66410f383ed3
+	//TODO: PMAXUW (BX), X11                // 66440f383e1b
+	//TODO: PMAXUW (R11), X11               // 66450f383e1b
+	//TODO: PMAXUW X2, X11                  // 66440f383eda
+	//TODO: PMAXUW X11, X11                 // 66450f383edb
+	//TODO: PMINSB (BX), X2                 // 660f383813
+	//TODO: PMINSB (R11), X2                // 66410f383813
+	//TODO: PMINSB X2, X2                   // 660f3838d2
+	//TODO: PMINSB X11, X2                  // 66410f3838d3
+	//TODO: PMINSB (BX), X11                // 66440f38381b
+	//TODO: PMINSB (R11), X11               // 66450f38381b
+	//TODO: PMINSB X2, X11                  // 66440f3838da
+	//TODO: PMINSB X11, X11                 // 66450f3838db
+	//TODO: PMINSD (BX), X2                 // 660f383913
+	//TODO: PMINSD (R11), X2                // 66410f383913
+	//TODO: PMINSD X2, X2                   // 660f3839d2
+	//TODO: PMINSD X11, X2                  // 66410f3839d3
+	//TODO: PMINSD (BX), X11                // 66440f38391b
+	//TODO: PMINSD (R11), X11               // 66450f38391b
+	//TODO: PMINSD X2, X11                  // 66440f3839da
+	//TODO: PMINSD X11, X11                 // 66450f3839db
+	//TODO: PMINSW (BX), M2                 // 0fea13
+	//TODO: PMINSW (R11), M2                // 410fea13
+	//TODO: PMINSW M2, M2                   // 0fead2
+	//TODO: PMINSW M3, M2                   // 0fead3
+	//TODO: PMINSW (BX), M3                 // 0fea1b
+	//TODO: PMINSW (R11), M3                // 410fea1b
+	//TODO: PMINSW M2, M3                   // 0feada
+	//TODO: PMINSW M3, M3                   // 0feadb
+	PMINSW (BX), X2                         // 660fea13
+	PMINSW (R11), X2                        // 66410fea13
+	PMINSW X2, X2                           // 660fead2
+	PMINSW X11, X2                          // 66410fead3
+	PMINSW (BX), X11                        // 66440fea1b
+	PMINSW (R11), X11                       // 66450fea1b
+	PMINSW X2, X11                          // 66440feada
+	PMINSW X11, X11                         // 66450feadb
+	//TODO: PMINUB (BX), M2                 // 0fda13
+	//TODO: PMINUB (R11), M2                // 410fda13
+	//TODO: PMINUB M2, M2                   // 0fdad2
+	//TODO: PMINUB M3, M2                   // 0fdad3
+	//TODO: PMINUB (BX), M3                 // 0fda1b
+	//TODO: PMINUB (R11), M3                // 410fda1b
+	//TODO: PMINUB M2, M3                   // 0fdada
+	//TODO: PMINUB M3, M3                   // 0fdadb
+	PMINUB (BX), X2                         // 660fda13
+	PMINUB (R11), X2                        // 66410fda13
+	PMINUB X2, X2                           // 660fdad2
+	PMINUB X11, X2                          // 66410fdad3
+	PMINUB (BX), X11                        // 66440fda1b
+	PMINUB (R11), X11                       // 66450fda1b
+	PMINUB X2, X11                          // 66440fdada
+	PMINUB X11, X11                         // 66450fdadb
+	//TODO: PMINUD (BX), X2                 // 660f383b13
+	//TODO: PMINUD (R11), X2                // 66410f383b13
+	//TODO: PMINUD X2, X2                   // 660f383bd2
+	//TODO: PMINUD X11, X2                  // 66410f383bd3
+	//TODO: PMINUD (BX), X11                // 66440f383b1b
+	//TODO: PMINUD (R11), X11               // 66450f383b1b
+	//TODO: PMINUD X2, X11                  // 66440f383bda
+	//TODO: PMINUD X11, X11                 // 66450f383bdb
+	//TODO: PMINUW (BX), X2                 // 660f383a13
+	//TODO: PMINUW (R11), X2                // 66410f383a13
+	//TODO: PMINUW X2, X2                   // 660f383ad2
+	//TODO: PMINUW X11, X2                  // 66410f383ad3
+	//TODO: PMINUW (BX), X11                // 66440f383a1b
+	//TODO: PMINUW (R11), X11               // 66450f383a1b
+	//TODO: PMINUW X2, X11                  // 66440f383ada
+	//TODO: PMINUW X11, X11                 // 66450f383adb
+	PMOVMSKB M2, DX                         // 0fd7d2
+	PMOVMSKB M3, DX                         // 0fd7d3
+	PMOVMSKB M2, R11                        // 440fd7da
+	PMOVMSKB M3, R11                        // 440fd7db
+	PMOVMSKB X2, DX                         // 660fd7d2
+	PMOVMSKB X11, DX                        // 66410fd7d3
+	PMOVMSKB X2, R11                        // 66440fd7da
+	PMOVMSKB X11, R11                       // 66450fd7db
+	PMOVSXBD (BX), X2                       // 660f382113
+	PMOVSXBD (R11), X2                      // 66410f382113
+	PMOVSXBD X2, X2                         // 660f3821d2
+	PMOVSXBD X11, X2                        // 66410f3821d3
+	PMOVSXBD (BX), X11                      // 66440f38211b
+	PMOVSXBD (R11), X11                     // 66450f38211b
+	PMOVSXBD X2, X11                        // 66440f3821da
+	PMOVSXBD X11, X11                       // 66450f3821db
+	PMOVSXBQ (BX), X2                       // 660f382213
+	PMOVSXBQ (R11), X2                      // 66410f382213
+	PMOVSXBQ X2, X2                         // 660f3822d2
+	PMOVSXBQ X11, X2                        // 66410f3822d3
+	PMOVSXBQ (BX), X11                      // 66440f38221b
+	PMOVSXBQ (R11), X11                     // 66450f38221b
+	PMOVSXBQ X2, X11                        // 66440f3822da
+	PMOVSXBQ X11, X11                       // 66450f3822db
+	PMOVSXBW (BX), X2                       // 660f382013
+	PMOVSXBW (R11), X2                      // 66410f382013
+	PMOVSXBW X2, X2                         // 660f3820d2
+	PMOVSXBW X11, X2                        // 66410f3820d3
+	PMOVSXBW (BX), X11                      // 66440f38201b
+	PMOVSXBW (R11), X11                     // 66450f38201b
+	PMOVSXBW X2, X11                        // 66440f3820da
+	PMOVSXBW X11, X11                       // 66450f3820db
+	PMOVSXDQ (BX), X2                       // 660f382513
+	PMOVSXDQ (R11), X2                      // 66410f382513
+	PMOVSXDQ X2, X2                         // 660f3825d2
+	PMOVSXDQ X11, X2                        // 66410f3825d3
+	PMOVSXDQ (BX), X11                      // 66440f38251b
+	PMOVSXDQ (R11), X11                     // 66450f38251b
+	PMOVSXDQ X2, X11                        // 66440f3825da
+	PMOVSXDQ X11, X11                       // 66450f3825db
+	PMOVSXWD (BX), X2                       // 660f382313
+	PMOVSXWD (R11), X2                      // 66410f382313
+	PMOVSXWD X2, X2                         // 660f3823d2
+	PMOVSXWD X11, X2                        // 66410f3823d3
+	PMOVSXWD (BX), X11                      // 66440f38231b
+	PMOVSXWD (R11), X11                     // 66450f38231b
+	PMOVSXWD X2, X11                        // 66440f3823da
+	PMOVSXWD X11, X11                       // 66450f3823db
+	PMOVSXWQ (BX), X2                       // 660f382413
+	PMOVSXWQ (R11), X2                      // 66410f382413
+	PMOVSXWQ X2, X2                         // 660f3824d2
+	PMOVSXWQ X11, X2                        // 66410f3824d3
+	PMOVSXWQ (BX), X11                      // 66440f38241b
+	PMOVSXWQ (R11), X11                     // 66450f38241b
+	PMOVSXWQ X2, X11                        // 66440f3824da
+	PMOVSXWQ X11, X11                       // 66450f3824db
+	PMOVZXBD (BX), X2                       // 660f383113
+	PMOVZXBD (R11), X2                      // 66410f383113
+	PMOVZXBD X2, X2                         // 660f3831d2
+	PMOVZXBD X11, X2                        // 66410f3831d3
+	PMOVZXBD (BX), X11                      // 66440f38311b
+	PMOVZXBD (R11), X11                     // 66450f38311b
+	PMOVZXBD X2, X11                        // 66440f3831da
+	PMOVZXBD X11, X11                       // 66450f3831db
+	PMOVZXBQ (BX), X2                       // 660f383213
+	PMOVZXBQ (R11), X2                      // 66410f383213
+	PMOVZXBQ X2, X2                         // 660f3832d2
+	PMOVZXBQ X11, X2                        // 66410f3832d3
+	PMOVZXBQ (BX), X11                      // 66440f38321b
+	PMOVZXBQ (R11), X11                     // 66450f38321b
+	PMOVZXBQ X2, X11                        // 66440f3832da
+	PMOVZXBQ X11, X11                       // 66450f3832db
+	PMOVZXBW (BX), X2                       // 660f383013
+	PMOVZXBW (R11), X2                      // 66410f383013
+	PMOVZXBW X2, X2                         // 660f3830d2
+	PMOVZXBW X11, X2                        // 66410f3830d3
+	PMOVZXBW (BX), X11                      // 66440f38301b
+	PMOVZXBW (R11), X11                     // 66450f38301b
+	PMOVZXBW X2, X11                        // 66440f3830da
+	PMOVZXBW X11, X11                       // 66450f3830db
+	PMOVZXDQ (BX), X2                       // 660f383513
+	PMOVZXDQ (R11), X2                      // 66410f383513
+	PMOVZXDQ X2, X2                         // 660f3835d2
+	PMOVZXDQ X11, X2                        // 66410f3835d3
+	PMOVZXDQ (BX), X11                      // 66440f38351b
+	PMOVZXDQ (R11), X11                     // 66450f38351b
+	PMOVZXDQ X2, X11                        // 66440f3835da
+	PMOVZXDQ X11, X11                       // 66450f3835db
+	PMOVZXWD (BX), X2                       // 660f383313
+	PMOVZXWD (R11), X2                      // 66410f383313
+	PMOVZXWD X2, X2                         // 660f3833d2
+	PMOVZXWD X11, X2                        // 66410f3833d3
+	PMOVZXWD (BX), X11                      // 66440f38331b
+	PMOVZXWD (R11), X11                     // 66450f38331b
+	PMOVZXWD X2, X11                        // 66440f3833da
+	PMOVZXWD X11, X11                       // 66450f3833db
+	PMOVZXWQ (BX), X2                       // 660f383413
+	PMOVZXWQ (R11), X2                      // 66410f383413
+	PMOVZXWQ X2, X2                         // 660f3834d2
+	PMOVZXWQ X11, X2                        // 66410f3834d3
+	PMOVZXWQ (BX), X11                      // 66440f38341b
+	PMOVZXWQ (R11), X11                     // 66450f38341b
+	PMOVZXWQ X2, X11                        // 66440f3834da
+	PMOVZXWQ X11, X11                       // 66450f3834db
+	PMULDQ (BX), X2                         // 660f382813
+	PMULDQ (R11), X2                        // 66410f382813
+	PMULDQ X2, X2                           // 660f3828d2
+	PMULDQ X11, X2                          // 66410f3828d3
+	PMULDQ (BX), X11                        // 66440f38281b
+	PMULDQ (R11), X11                       // 66450f38281b
+	PMULDQ X2, X11                          // 66440f3828da
+	PMULDQ X11, X11                         // 66450f3828db
+	//TODO: PMULHRSW (BX), M2               // 0f380b13
+	//TODO: PMULHRSW (R11), M2              // 410f380b13
+	//TODO: PMULHRSW M2, M2                 // 0f380bd2
+	//TODO: PMULHRSW M3, M2                 // 0f380bd3
+	//TODO: PMULHRSW (BX), M3               // 0f380b1b
+	//TODO: PMULHRSW (R11), M3              // 410f380b1b
+	//TODO: PMULHRSW M2, M3                 // 0f380bda
+	//TODO: PMULHRSW M3, M3                 // 0f380bdb
+	//TODO: PMULHRSW (BX), X2               // 660f380b13
+	//TODO: PMULHRSW (R11), X2              // 66410f380b13
+	//TODO: PMULHRSW X2, X2                 // 660f380bd2
+	//TODO: PMULHRSW X11, X2                // 66410f380bd3
+	//TODO: PMULHRSW (BX), X11              // 66440f380b1b
+	//TODO: PMULHRSW (R11), X11             // 66450f380b1b
+	//TODO: PMULHRSW X2, X11                // 66440f380bda
+	//TODO: PMULHRSW X11, X11               // 66450f380bdb
+	PMULHUW (BX), M2                        // 0fe413
+	PMULHUW (R11), M2                       // 410fe413
+	PMULHUW M2, M2                          // 0fe4d2
+	PMULHUW M3, M2                          // 0fe4d3
+	PMULHUW (BX), M3                        // 0fe41b
+	PMULHUW (R11), M3                       // 410fe41b
+	PMULHUW M2, M3                          // 0fe4da
+	PMULHUW M3, M3                          // 0fe4db
+	PMULHUW (BX), X2                        // 660fe413
+	PMULHUW (R11), X2                       // 66410fe413
+	PMULHUW X2, X2                          // 660fe4d2
+	PMULHUW X11, X2                         // 66410fe4d3
+	PMULHUW (BX), X11                       // 66440fe41b
+	PMULHUW (R11), X11                      // 66450fe41b
+	PMULHUW X2, X11                         // 66440fe4da
+	PMULHUW X11, X11                        // 66450fe4db
+	PMULHW (BX), M2                         // 0fe513
+	PMULHW (R11), M2                        // 410fe513
+	PMULHW M2, M2                           // 0fe5d2
+	PMULHW M3, M2                           // 0fe5d3
+	PMULHW (BX), M3                         // 0fe51b
+	PMULHW (R11), M3                        // 410fe51b
+	PMULHW M2, M3                           // 0fe5da
+	PMULHW M3, M3                           // 0fe5db
+	PMULHW (BX), X2                         // 660fe513
+	PMULHW (R11), X2                        // 66410fe513
+	PMULHW X2, X2                           // 660fe5d2
+	PMULHW X11, X2                          // 66410fe5d3
+	PMULHW (BX), X11                        // 66440fe51b
+	PMULHW (R11), X11                       // 66450fe51b
+	PMULHW X2, X11                          // 66440fe5da
+	PMULHW X11, X11                         // 66450fe5db
+	PMULLD (BX), X2                         // 660f384013
+	PMULLD (R11), X2                        // 66410f384013
+	PMULLD X2, X2                           // 660f3840d2
+	PMULLD X11, X2                          // 66410f3840d3
+	PMULLD (BX), X11                        // 66440f38401b
+	PMULLD (R11), X11                       // 66450f38401b
+	PMULLD X2, X11                          // 66440f3840da
+	PMULLD X11, X11                         // 66450f3840db
+	PMULLW (BX), M2                         // 0fd513
+	PMULLW (R11), M2                        // 410fd513
+	PMULLW M2, M2                           // 0fd5d2
+	PMULLW M3, M2                           // 0fd5d3
+	PMULLW (BX), M3                         // 0fd51b
+	PMULLW (R11), M3                        // 410fd51b
+	PMULLW M2, M3                           // 0fd5da
+	PMULLW M3, M3                           // 0fd5db
+	PMULLW (BX), X2                         // 660fd513
+	PMULLW (R11), X2                        // 66410fd513
+	PMULLW X2, X2                           // 660fd5d2
+	PMULLW X11, X2                          // 66410fd5d3
+	PMULLW (BX), X11                        // 66440fd51b
+	PMULLW (R11), X11                       // 66450fd51b
+	PMULLW X2, X11                          // 66440fd5da
+	PMULLW X11, X11                         // 66450fd5db
+	PMULULQ (BX), M2                        // 0ff413
+	PMULULQ (R11), M2                       // 410ff413
+	PMULULQ M2, M2                          // 0ff4d2
+	PMULULQ M3, M2                          // 0ff4d3
+	PMULULQ (BX), M3                        // 0ff41b
+	PMULULQ (R11), M3                       // 410ff41b
+	PMULULQ M2, M3                          // 0ff4da
+	PMULULQ M3, M3                          // 0ff4db
+	PMULULQ (BX), X2                        // 660ff413
+	PMULULQ (R11), X2                       // 66410ff413
+	PMULULQ X2, X2                          // 660ff4d2
+	PMULULQ X11, X2                         // 66410ff4d3
+	PMULULQ (BX), X11                       // 66440ff41b
+	PMULULQ (R11), X11                      // 66450ff41b
+	PMULULQ X2, X11                         // 66440ff4da
+	PMULULQ X11, X11                        // 66450ff4db
+	PUSHQ AX
+	POPQ FS                                 // 660fa1 or 0fa1
+	PUSHQ AX
+	POPQ GS                                 // 660fa9 or 0fa9
+	PUSHW AX
+	POPW (BX)                               // 668f03
+	PUSHW AX
+	POPW (R11)                              // 66418f03
+	PUSHW AX
+	POPW DX                                 // 668fc2 or 665a
+	PUSHW AX
+	POPW R11                                // 66418fc3 or 66415b
+	PUSHQ AX
+	POPQ (BX)                               // 8f03
+	PUSHQ AX
+	POPQ (R11)                              // 418f03
+	PUSHQ AX
+	POPQ DX                                 // 8fc2 or 5a
+	PUSHQ AX
+	POPQ R11                                // 418fc3 or 415b
+	POPCNTW (BX), DX                        // 66f30fb813
+	POPCNTW (R11), DX                       // 66f3410fb813
+	POPCNTW DX, DX                          // 66f30fb8d2
+	POPCNTW R11, DX                         // 66f3410fb8d3
+	POPCNTW (BX), R11                       // 66f3440fb81b
+	POPCNTW (R11), R11                      // 66f3450fb81b
+	POPCNTW DX, R11                         // 66f3440fb8da
+	POPCNTW R11, R11                        // 66f3450fb8db
+	POPCNTL (BX), DX                        // f30fb813
+	POPCNTL (R11), DX                       // f3410fb813
+	POPCNTL DX, DX                          // f30fb8d2
+	POPCNTL R11, DX                         // f3410fb8d3
+	POPCNTL (BX), R11                       // f3440fb81b
+	POPCNTL (R11), R11                      // f3450fb81b
+	POPCNTL DX, R11                         // f3440fb8da
+	POPCNTL R11, R11                        // f3450fb8db
+	POPCNTQ (BX), DX                        // f3480fb813
+	POPCNTQ (R11), DX                       // f3490fb813
+	POPCNTQ DX, DX                          // f3480fb8d2
+	POPCNTQ R11, DX                         // f3490fb8d3
+	POPCNTQ (BX), R11                       // f34c0fb81b
+	POPCNTQ (R11), R11                      // f34d0fb81b
+	POPCNTQ DX, R11                         // f34c0fb8da
+	POPCNTQ R11, R11                        // f34d0fb8db
+	PUSHFW
+	POPFW                                   // 669d
+	PUSHFQ
+	POPFQ                                   // 9d
+	POR (BX), M2                            // 0feb13
+	POR (R11), M2                           // 410feb13
+	POR M2, M2                              // 0febd2
+	POR M3, M2                              // 0febd3
+	POR (BX), M3                            // 0feb1b
+	POR (R11), M3                           // 410feb1b
+	POR M2, M3                              // 0febda
+	POR M3, M3                              // 0febdb
+	POR (BX), X2                            // 660feb13
+	POR (R11), X2                           // 66410feb13
+	POR X2, X2                              // 660febd2
+	POR X11, X2                             // 66410febd3
+	POR (BX), X11                           // 66440feb1b
+	POR (R11), X11                          // 66450feb1b
+	POR X2, X11                             // 66440febda
+	POR X11, X11                            // 66450febdb
+	PREFETCHNTA (BX)                        // 0f1803
+	PREFETCHNTA (R11)                       // 410f1803
+	PREFETCHT0 (BX)                         // 0f180b
+	PREFETCHT0 (R11)                        // 410f180b
+	PREFETCHT1 (BX)                         // 0f1813
+	PREFETCHT1 (R11)                        // 410f1813
+	PREFETCHT2 (BX)                         // 0f181b
+	PREFETCHT2 (R11)                        // 410f181b
+	//TODO: PREFETCHW (BX)                  // 0f0d0b
+	//TODO: PREFETCHW (R11)                 // 410f0d0b
+	//TODO: PREFETCHWT1 (BX)                // 0f0d13
+	//TODO: PREFETCHWT1 (R11)               // 410f0d13
+	//TODO: PSADBW (BX), M2                 // 0ff613
+	//TODO: PSADBW (R11), M2                // 410ff613
+	//TODO: PSADBW M2, M2                   // 0ff6d2
+	//TODO: PSADBW M3, M2                   // 0ff6d3
+	//TODO: PSADBW (BX), M3                 // 0ff61b
+	//TODO: PSADBW (R11), M3                // 410ff61b
+	//TODO: PSADBW M2, M3                   // 0ff6da
+	//TODO: PSADBW M3, M3                   // 0ff6db
+	PSADBW (BX), X2                         // 660ff613
+	PSADBW (R11), X2                        // 66410ff613
+	PSADBW X2, X2                           // 660ff6d2
+	PSADBW X11, X2                          // 66410ff6d3
+	PSADBW (BX), X11                        // 66440ff61b
+	PSADBW (R11), X11                       // 66450ff61b
+	PSADBW X2, X11                          // 66440ff6da
+	PSADBW X11, X11                         // 66450ff6db
+	//TODO: PSHUFB (BX), M2                 // 0f380013
+	//TODO: PSHUFB (R11), M2                // 410f380013
+	//TODO: PSHUFB M2, M2                   // 0f3800d2
+	//TODO: PSHUFB M3, M2                   // 0f3800d3
+	//TODO: PSHUFB (BX), M3                 // 0f38001b
+	//TODO: PSHUFB (R11), M3                // 410f38001b
+	//TODO: PSHUFB M2, M3                   // 0f3800da
+	//TODO: PSHUFB M3, M3                   // 0f3800db
+	PSHUFB (BX), X2                         // 660f380013
+	PSHUFB (R11), X2                        // 66410f380013
+	PSHUFB X2, X2                           // 660f3800d2
+	PSHUFB X11, X2                          // 66410f3800d3
+	PSHUFB (BX), X11                        // 66440f38001b
+	PSHUFB (R11), X11                       // 66450f38001b
+	PSHUFB X2, X11                          // 66440f3800da
+	PSHUFB X11, X11                         // 66450f3800db
+	PSHUFD $7, (BX), X2                     // 660f701307
+	PSHUFL $7, (BX), X2                     // 660f701307
+	PSHUFD $7, (R11), X2                    // 66410f701307
+	PSHUFL $7, (R11), X2                    // 66410f701307
+	PSHUFD $7, X2, X2                       // 660f70d207
+	PSHUFL $7, X2, X2                       // 660f70d207
+	PSHUFD $7, X11, X2                      // 66410f70d307
+	PSHUFL $7, X11, X2                      // 66410f70d307
+	PSHUFD $7, (BX), X11                    // 66440f701b07
+	PSHUFL $7, (BX), X11                    // 66440f701b07
+	PSHUFD $7, (R11), X11                   // 66450f701b07
+	PSHUFL $7, (R11), X11                   // 66450f701b07
+	PSHUFD $7, X2, X11                      // 66440f70da07
+	PSHUFL $7, X2, X11                      // 66440f70da07
+	PSHUFD $7, X11, X11                     // 66450f70db07
+	PSHUFL $7, X11, X11                     // 66450f70db07
+	PSHUFHW $7, (BX), X2                    // f30f701307
+	PSHUFHW $7, (R11), X2                   // f3410f701307
+	PSHUFHW $7, X2, X2                      // f30f70d207
+	PSHUFHW $7, X11, X2                     // f3410f70d307
+	PSHUFHW $7, (BX), X11                   // f3440f701b07
+	PSHUFHW $7, (R11), X11                  // f3450f701b07
+	PSHUFHW $7, X2, X11                     // f3440f70da07
+	PSHUFHW $7, X11, X11                    // f3450f70db07
+	PSHUFLW $7, (BX), X2                    // f20f701307
+	PSHUFLW $7, (R11), X2                   // f2410f701307
+	PSHUFLW $7, X2, X2                      // f20f70d207
+	PSHUFLW $7, X11, X2                     // f2410f70d307
+	PSHUFLW $7, (BX), X11                   // f2440f701b07
+	PSHUFLW $7, (R11), X11                  // f2450f701b07
+	PSHUFLW $7, X2, X11                     // f2440f70da07
+	PSHUFLW $7, X11, X11                    // f2450f70db07
+	PSHUFW $7, (BX), M2                     // 0f701307
+	PSHUFW $7, (R11), M2                    // 410f701307
+	PSHUFW $7, M2, M2                       // 0f70d207
+	PSHUFW $7, M3, M2                       // 0f70d307
+	PSHUFW $7, (BX), M3                     // 0f701b07
+	PSHUFW $7, (R11), M3                    // 410f701b07
+	PSHUFW $7, M2, M3                       // 0f70da07
+	PSHUFW $7, M3, M3                       // 0f70db07
+	//TODO: PSIGNB (BX), M2                 // 0f380813
+	//TODO: PSIGNB (R11), M2                // 410f380813
+	//TODO: PSIGNB M2, M2                   // 0f3808d2
+	//TODO: PSIGNB M3, M2                   // 0f3808d3
+	//TODO: PSIGNB (BX), M3                 // 0f38081b
+	//TODO: PSIGNB (R11), M3                // 410f38081b
+	//TODO: PSIGNB M2, M3                   // 0f3808da
+	//TODO: PSIGNB M3, M3                   // 0f3808db
+	//TODO: PSIGNB (BX), X2                 // 660f380813
+	//TODO: PSIGNB (R11), X2                // 66410f380813
+	//TODO: PSIGNB X2, X2                   // 660f3808d2
+	//TODO: PSIGNB X11, X2                  // 66410f3808d3
+	//TODO: PSIGNB (BX), X11                // 66440f38081b
+	//TODO: PSIGNB (R11), X11               // 66450f38081b
+	//TODO: PSIGNB X2, X11                  // 66440f3808da
+	//TODO: PSIGNB X11, X11                 // 66450f3808db
+	//TODO: PSIGND (BX), M2                 // 0f380a13
+	//TODO: PSIGND (R11), M2                // 410f380a13
+	//TODO: PSIGND M2, M2                   // 0f380ad2
+	//TODO: PSIGND M3, M2                   // 0f380ad3
+	//TODO: PSIGND (BX), M3                 // 0f380a1b
+	//TODO: PSIGND (R11), M3                // 410f380a1b
+	//TODO: PSIGND M2, M3                   // 0f380ada
+	//TODO: PSIGND M3, M3                   // 0f380adb
+	//TODO: PSIGND (BX), X2                 // 660f380a13
+	//TODO: PSIGND (R11), X2                // 66410f380a13
+	//TODO: PSIGND X2, X2                   // 660f380ad2
+	//TODO: PSIGND X11, X2                  // 66410f380ad3
+	//TODO: PSIGND (BX), X11                // 66440f380a1b
+	//TODO: PSIGND (R11), X11               // 66450f380a1b
+	//TODO: PSIGND X2, X11                  // 66440f380ada
+	//TODO: PSIGND X11, X11                 // 66450f380adb
+	//TODO: PSIGNW (BX), M2                 // 0f380913
+	//TODO: PSIGNW (R11), M2                // 410f380913
+	//TODO: PSIGNW M2, M2                   // 0f3809d2
+	//TODO: PSIGNW M3, M2                   // 0f3809d3
+	//TODO: PSIGNW (BX), M3                 // 0f38091b
+	//TODO: PSIGNW (R11), M3                // 410f38091b
+	//TODO: PSIGNW M2, M3                   // 0f3809da
+	//TODO: PSIGNW M3, M3                   // 0f3809db
+	//TODO: PSIGNW (BX), X2                 // 660f380913
+	//TODO: PSIGNW (R11), X2                // 66410f380913
+	//TODO: PSIGNW X2, X2                   // 660f3809d2
+	//TODO: PSIGNW X11, X2                  // 66410f3809d3
+	//TODO: PSIGNW (BX), X11                // 66440f38091b
+	//TODO: PSIGNW (R11), X11               // 66450f38091b
+	//TODO: PSIGNW X2, X11                  // 66440f3809da
+	//TODO: PSIGNW X11, X11                 // 66450f3809db
+	PSLLL (BX), M2                          // 0ff213
+	PSLLL (R11), M2                         // 410ff213
+	PSLLL M2, M2                            // 0ff2d2
+	PSLLL M3, M2                            // 0ff2d3
+	PSLLL (BX), M3                          // 0ff21b
+	PSLLL (R11), M3                         // 410ff21b
+	PSLLL M2, M3                            // 0ff2da
+	PSLLL M3, M3                            // 0ff2db
+	PSLLL $7, M2                            // 0f72f207
+	PSLLL $7, M3                            // 0f72f307
+	PSLLL (BX), X2                          // 660ff213
+	PSLLL (R11), X2                         // 66410ff213
+	PSLLL X2, X2                            // 660ff2d2
+	PSLLL X11, X2                           // 66410ff2d3
+	PSLLL (BX), X11                         // 66440ff21b
+	PSLLL (R11), X11                        // 66450ff21b
+	PSLLL X2, X11                           // 66440ff2da
+	PSLLL X11, X11                          // 66450ff2db
+	PSLLL $7, X2                            // 660f72f207
+	PSLLL $7, X11                           // 66410f72f307
+	PSLLO $7, X2                            // 660f73fa07
+	PSLLO $7, X11                           // 66410f73fb07
+	PSLLQ (BX), M2                          // 0ff313
+	PSLLQ (R11), M2                         // 410ff313
+	PSLLQ M2, M2                            // 0ff3d2
+	PSLLQ M3, M2                            // 0ff3d3
+	PSLLQ (BX), M3                          // 0ff31b
+	PSLLQ (R11), M3                         // 410ff31b
+	PSLLQ M2, M3                            // 0ff3da
+	PSLLQ M3, M3                            // 0ff3db
+	PSLLQ $7, M2                            // 0f73f207
+	PSLLQ $7, M3                            // 0f73f307
+	PSLLQ (BX), X2                          // 660ff313
+	PSLLQ (R11), X2                         // 66410ff313
+	PSLLQ X2, X2                            // 660ff3d2
+	PSLLQ X11, X2                           // 66410ff3d3
+	PSLLQ (BX), X11                         // 66440ff31b
+	PSLLQ (R11), X11                        // 66450ff31b
+	PSLLQ X2, X11                           // 66440ff3da
+	PSLLQ X11, X11                          // 66450ff3db
+	PSLLQ $7, X2                            // 660f73f207
+	PSLLQ $7, X11                           // 66410f73f307
+	PSLLW (BX), M2                          // 0ff113
+	PSLLW (R11), M2                         // 410ff113
+	PSLLW M2, M2                            // 0ff1d2
+	PSLLW M3, M2                            // 0ff1d3
+	PSLLW (BX), M3                          // 0ff11b
+	PSLLW (R11), M3                         // 410ff11b
+	PSLLW M2, M3                            // 0ff1da
+	PSLLW M3, M3                            // 0ff1db
+	PSLLW $7, M2                            // 0f71f207
+	PSLLW $7, M3                            // 0f71f307
+	PSLLW (BX), X2                          // 660ff113
+	PSLLW (R11), X2                         // 66410ff113
+	PSLLW X2, X2                            // 660ff1d2
+	PSLLW X11, X2                           // 66410ff1d3
+	PSLLW (BX), X11                         // 66440ff11b
+	PSLLW (R11), X11                        // 66450ff11b
+	PSLLW X2, X11                           // 66440ff1da
+	PSLLW X11, X11                          // 66450ff1db
+	PSLLW $7, X2                            // 660f71f207
+	PSLLW $7, X11                           // 66410f71f307
+	PSRAL (BX), M2                          // 0fe213
+	PSRAL (R11), M2                         // 410fe213
+	PSRAL M2, M2                            // 0fe2d2
+	PSRAL M3, M2                            // 0fe2d3
+	PSRAL (BX), M3                          // 0fe21b
+	PSRAL (R11), M3                         // 410fe21b
+	PSRAL M2, M3                            // 0fe2da
+	PSRAL M3, M3                            // 0fe2db
+	PSRAL $7, M2                            // 0f72e207
+	PSRAL $7, M3                            // 0f72e307
+	PSRAL (BX), X2                          // 660fe213
+	PSRAL (R11), X2                         // 66410fe213
+	PSRAL X2, X2                            // 660fe2d2
+	PSRAL X11, X2                           // 66410fe2d3
+	PSRAL (BX), X11                         // 66440fe21b
+	PSRAL (R11), X11                        // 66450fe21b
+	PSRAL X2, X11                           // 66440fe2da
+	PSRAL X11, X11                          // 66450fe2db
+	PSRAL $7, X2                            // 660f72e207
+	PSRAL $7, X11                           // 66410f72e307
+	PSRAW (BX), M2                          // 0fe113
+	PSRAW (R11), M2                         // 410fe113
+	PSRAW M2, M2                            // 0fe1d2
+	PSRAW M3, M2                            // 0fe1d3
+	PSRAW (BX), M3                          // 0fe11b
+	PSRAW (R11), M3                         // 410fe11b
+	PSRAW M2, M3                            // 0fe1da
+	PSRAW M3, M3                            // 0fe1db
+	PSRAW $7, M2                            // 0f71e207
+	PSRAW $7, M3                            // 0f71e307
+	PSRAW (BX), X2                          // 660fe113
+	PSRAW (R11), X2                         // 66410fe113
+	PSRAW X2, X2                            // 660fe1d2
+	PSRAW X11, X2                           // 66410fe1d3
+	PSRAW (BX), X11                         // 66440fe11b
+	PSRAW (R11), X11                        // 66450fe11b
+	PSRAW X2, X11                           // 66440fe1da
+	PSRAW X11, X11                          // 66450fe1db
+	PSRAW $7, X2                            // 660f71e207
+	PSRAW $7, X11                           // 66410f71e307
+	PSRLL (BX), M2                          // 0fd213
+	PSRLL (R11), M2                         // 410fd213
+	PSRLL M2, M2                            // 0fd2d2
+	PSRLL M3, M2                            // 0fd2d3
+	PSRLL (BX), M3                          // 0fd21b
+	PSRLL (R11), M3                         // 410fd21b
+	PSRLL M2, M3                            // 0fd2da
+	PSRLL M3, M3                            // 0fd2db
+	PSRLL $7, M2                            // 0f72d207
+	PSRLL $7, M3                            // 0f72d307
+	PSRLL (BX), X2                          // 660fd213
+	PSRLL (R11), X2                         // 66410fd213
+	PSRLL X2, X2                            // 660fd2d2
+	PSRLL X11, X2                           // 66410fd2d3
+	PSRLL (BX), X11                         // 66440fd21b
+	PSRLL (R11), X11                        // 66450fd21b
+	PSRLL X2, X11                           // 66440fd2da
+	PSRLL X11, X11                          // 66450fd2db
+	PSRLL $7, X2                            // 660f72d207
+	PSRLL $7, X11                           // 66410f72d307
+	PSRLO $7, X2                            // 660f73da07
+	PSRLO $7, X11                           // 66410f73db07
+	PSRLQ (BX), M2                          // 0fd313
+	PSRLQ (R11), M2                         // 410fd313
+	PSRLQ M2, M2                            // 0fd3d2
+	PSRLQ M3, M2                            // 0fd3d3
+	PSRLQ (BX), M3                          // 0fd31b
+	PSRLQ (R11), M3                         // 410fd31b
+	PSRLQ M2, M3                            // 0fd3da
+	PSRLQ M3, M3                            // 0fd3db
+	PSRLQ $7, M2                            // 0f73d207
+	PSRLQ $7, M3                            // 0f73d307
+	PSRLQ (BX), X2                          // 660fd313
+	PSRLQ (R11), X2                         // 66410fd313
+	PSRLQ X2, X2                            // 660fd3d2
+	PSRLQ X11, X2                           // 66410fd3d3
+	PSRLQ (BX), X11                         // 66440fd31b
+	PSRLQ (R11), X11                        // 66450fd31b
+	PSRLQ X2, X11                           // 66440fd3da
+	PSRLQ X11, X11                          // 66450fd3db
+	PSRLQ $7, X2                            // 660f73d207
+	PSRLQ $7, X11                           // 66410f73d307
+	PSRLW (BX), M2                          // 0fd113
+	PSRLW (R11), M2                         // 410fd113
+	PSRLW M2, M2                            // 0fd1d2
+	PSRLW M3, M2                            // 0fd1d3
+	PSRLW (BX), M3                          // 0fd11b
+	PSRLW (R11), M3                         // 410fd11b
+	PSRLW M2, M3                            // 0fd1da
+	PSRLW M3, M3                            // 0fd1db
+	PSRLW $7, M2                            // 0f71d207
+	PSRLW $7, M3                            // 0f71d307
+	PSRLW (BX), X2                          // 660fd113
+	PSRLW (R11), X2                         // 66410fd113
+	PSRLW X2, X2                            // 660fd1d2
+	PSRLW X11, X2                           // 66410fd1d3
+	PSRLW (BX), X11                         // 66440fd11b
+	PSRLW (R11), X11                        // 66450fd11b
+	PSRLW X2, X11                           // 66440fd1da
+	PSRLW X11, X11                          // 66450fd1db
+	PSRLW $7, X2                            // 660f71d207
+	PSRLW $7, X11                           // 66410f71d307
+	//TODO: PSUBB (BX), M2                  // 0ff813
+	//TODO: PSUBB (R11), M2                 // 410ff813
+	//TODO: PSUBB M2, M2                    // 0ff8d2
+	//TODO: PSUBB M3, M2                    // 0ff8d3
+	//TODO: PSUBB (BX), M3                  // 0ff81b
+	//TODO: PSUBB (R11), M3                 // 410ff81b
+	//TODO: PSUBB M2, M3                    // 0ff8da
+	//TODO: PSUBB M3, M3                    // 0ff8db
+	PSUBB (BX), X2                          // 660ff813
+	PSUBB (R11), X2                         // 66410ff813
+	PSUBB X2, X2                            // 660ff8d2
+	PSUBB X11, X2                           // 66410ff8d3
+	PSUBB (BX), X11                         // 66440ff81b
+	PSUBB (R11), X11                        // 66450ff81b
+	PSUBB X2, X11                           // 66440ff8da
+	PSUBB X11, X11                          // 66450ff8db
+	//TODO: PSUBL (BX), M2                  // 0ffa13
+	//TODO: PSUBL (R11), M2                 // 410ffa13
+	//TODO: PSUBL M2, M2                    // 0ffad2
+	//TODO: PSUBL M3, M2                    // 0ffad3
+	//TODO: PSUBL (BX), M3                  // 0ffa1b
+	//TODO: PSUBL (R11), M3                 // 410ffa1b
+	//TODO: PSUBL M2, M3                    // 0ffada
+	//TODO: PSUBL M3, M3                    // 0ffadb
+	PSUBL (BX), X2                          // 660ffa13
+	PSUBL (R11), X2                         // 66410ffa13
+	PSUBL X2, X2                            // 660ffad2
+	PSUBL X11, X2                           // 66410ffad3
+	PSUBL (BX), X11                         // 66440ffa1b
+	PSUBL (R11), X11                        // 66450ffa1b
+	PSUBL X2, X11                           // 66440ffada
+	PSUBL X11, X11                          // 66450ffadb
+	//TODO: PSUBQ (BX), M2                  // 0ffb13
+	//TODO: PSUBQ (R11), M2                 // 410ffb13
+	//TODO: PSUBQ M2, M2                    // 0ffbd2
+	//TODO: PSUBQ M3, M2                    // 0ffbd3
+	//TODO: PSUBQ (BX), M3                  // 0ffb1b
+	//TODO: PSUBQ (R11), M3                 // 410ffb1b
+	//TODO: PSUBQ M2, M3                    // 0ffbda
+	//TODO: PSUBQ M3, M3                    // 0ffbdb
+	PSUBQ (BX), X2                          // 660ffb13
+	PSUBQ (R11), X2                         // 66410ffb13
+	PSUBQ X2, X2                            // 660ffbd2
+	PSUBQ X11, X2                           // 66410ffbd3
+	PSUBQ (BX), X11                         // 66440ffb1b
+	PSUBQ (R11), X11                        // 66450ffb1b
+	PSUBQ X2, X11                           // 66440ffbda
+	PSUBQ X11, X11                          // 66450ffbdb
+	//TODO: PSUBSB (BX), M2                 // 0fe813
+	//TODO: PSUBSB (R11), M2                // 410fe813
+	//TODO: PSUBSB M2, M2                   // 0fe8d2
+	//TODO: PSUBSB M3, M2                   // 0fe8d3
+	//TODO: PSUBSB (BX), M3                 // 0fe81b
+	//TODO: PSUBSB (R11), M3                // 410fe81b
+	//TODO: PSUBSB M2, M3                   // 0fe8da
+	//TODO: PSUBSB M3, M3                   // 0fe8db
+	PSUBSB (BX), X2                         // 660fe813
+	PSUBSB (R11), X2                        // 66410fe813
+	PSUBSB X2, X2                           // 660fe8d2
+	PSUBSB X11, X2                          // 66410fe8d3
+	PSUBSB (BX), X11                        // 66440fe81b
+	PSUBSB (R11), X11                       // 66450fe81b
+	PSUBSB X2, X11                          // 66440fe8da
+	PSUBSB X11, X11                         // 66450fe8db
+	//TODO: PSUBSW (BX), M2                 // 0fe913
+	//TODO: PSUBSW (R11), M2                // 410fe913
+	//TODO: PSUBSW M2, M2                   // 0fe9d2
+	//TODO: PSUBSW M3, M2                   // 0fe9d3
+	//TODO: PSUBSW (BX), M3                 // 0fe91b
+	//TODO: PSUBSW (R11), M3                // 410fe91b
+	//TODO: PSUBSW M2, M3                   // 0fe9da
+	//TODO: PSUBSW M3, M3                   // 0fe9db
+	PSUBSW (BX), X2                         // 660fe913
+	PSUBSW (R11), X2                        // 66410fe913
+	PSUBSW X2, X2                           // 660fe9d2
+	PSUBSW X11, X2                          // 66410fe9d3
+	PSUBSW (BX), X11                        // 66440fe91b
+	PSUBSW (R11), X11                       // 66450fe91b
+	PSUBSW X2, X11                          // 66440fe9da
+	PSUBSW X11, X11                         // 66450fe9db
+	//TODO: PSUBUSB (BX), M2                // 0fd813
+	//TODO: PSUBUSB (R11), M2               // 410fd813
+	//TODO: PSUBUSB M2, M2                  // 0fd8d2
+	//TODO: PSUBUSB M3, M2                  // 0fd8d3
+	//TODO: PSUBUSB (BX), M3                // 0fd81b
+	//TODO: PSUBUSB (R11), M3               // 410fd81b
+	//TODO: PSUBUSB M2, M3                  // 0fd8da
+	//TODO: PSUBUSB M3, M3                  // 0fd8db
+	PSUBUSB (BX), X2                        // 660fd813
+	PSUBUSB (R11), X2                       // 66410fd813
+	PSUBUSB X2, X2                          // 660fd8d2
+	PSUBUSB X11, X2                         // 66410fd8d3
+	PSUBUSB (BX), X11                       // 66440fd81b
+	PSUBUSB (R11), X11                      // 66450fd81b
+	PSUBUSB X2, X11                         // 66440fd8da
+	PSUBUSB X11, X11                        // 66450fd8db
+	//TODO: PSUBUSW (BX), M2                // 0fd913
+	//TODO: PSUBUSW (R11), M2               // 410fd913
+	//TODO: PSUBUSW M2, M2                  // 0fd9d2
+	//TODO: PSUBUSW M3, M2                  // 0fd9d3
+	//TODO: PSUBUSW (BX), M3                // 0fd91b
+	//TODO: PSUBUSW (R11), M3               // 410fd91b
+	//TODO: PSUBUSW M2, M3                  // 0fd9da
+	//TODO: PSUBUSW M3, M3                  // 0fd9db
+	PSUBUSW (BX), X2                        // 660fd913
+	PSUBUSW (R11), X2                       // 66410fd913
+	PSUBUSW X2, X2                          // 660fd9d2
+	PSUBUSW X11, X2                         // 66410fd9d3
+	PSUBUSW (BX), X11                       // 66440fd91b
+	PSUBUSW (R11), X11                      // 66450fd91b
+	PSUBUSW X2, X11                         // 66440fd9da
+	PSUBUSW X11, X11                        // 66450fd9db
+	//TODO: PSUBW (BX), M2                  // 0ff913
+	//TODO: PSUBW (R11), M2                 // 410ff913
+	//TODO: PSUBW M2, M2                    // 0ff9d2
+	//TODO: PSUBW M3, M2                    // 0ff9d3
+	//TODO: PSUBW (BX), M3                  // 0ff91b
+	//TODO: PSUBW (R11), M3                 // 410ff91b
+	//TODO: PSUBW M2, M3                    // 0ff9da
+	//TODO: PSUBW M3, M3                    // 0ff9db
+	PSUBW (BX), X2                          // 660ff913
+	PSUBW (R11), X2                         // 66410ff913
+	PSUBW X2, X2                            // 660ff9d2
+	PSUBW X11, X2                           // 66410ff9d3
+	PSUBW (BX), X11                         // 66440ff91b
+	PSUBW (R11), X11                        // 66450ff91b
+	PSUBW X2, X11                           // 66440ff9da
+	PSUBW X11, X11                          // 66450ff9db
+	//TODO: PTEST (BX), X2                  // 660f381713
+	//TODO: PTEST (R11), X2                 // 66410f381713
+	//TODO: PTEST X2, X2                    // 660f3817d2
+	//TODO: PTEST X11, X2                   // 66410f3817d3
+	//TODO: PTEST (BX), X11                 // 66440f38171b
+	//TODO: PTEST (R11), X11                // 66450f38171b
+	//TODO: PTEST X2, X11                   // 66440f3817da
+	//TODO: PTEST X11, X11                  // 66450f3817db
+	PUNPCKHBW (BX), M2                      // 0f6813
+	PUNPCKHBW (R11), M2                     // 410f6813
+	PUNPCKHBW M2, M2                        // 0f68d2
+	PUNPCKHBW M3, M2                        // 0f68d3
+	PUNPCKHBW (BX), M3                      // 0f681b
+	PUNPCKHBW (R11), M3                     // 410f681b
+	PUNPCKHBW M2, M3                        // 0f68da
+	PUNPCKHBW M3, M3                        // 0f68db
+	PUNPCKHBW (BX), X2                      // 660f6813
+	PUNPCKHBW (R11), X2                     // 66410f6813
+	PUNPCKHBW X2, X2                        // 660f68d2
+	PUNPCKHBW X11, X2                       // 66410f68d3
+	PUNPCKHBW (BX), X11                     // 66440f681b
+	PUNPCKHBW (R11), X11                    // 66450f681b
+	PUNPCKHBW X2, X11                       // 66440f68da
+	PUNPCKHBW X11, X11                      // 66450f68db
+	PUNPCKHLQ (BX), M2                      // 0f6a13
+	PUNPCKHLQ (R11), M2                     // 410f6a13
+	PUNPCKHLQ M2, M2                        // 0f6ad2
+	PUNPCKHLQ M3, M2                        // 0f6ad3
+	PUNPCKHLQ (BX), M3                      // 0f6a1b
+	PUNPCKHLQ (R11), M3                     // 410f6a1b
+	PUNPCKHLQ M2, M3                        // 0f6ada
+	PUNPCKHLQ M3, M3                        // 0f6adb
+	PUNPCKHLQ (BX), X2                      // 660f6a13
+	PUNPCKHLQ (R11), X2                     // 66410f6a13
+	PUNPCKHLQ X2, X2                        // 660f6ad2
+	PUNPCKHLQ X11, X2                       // 66410f6ad3
+	PUNPCKHLQ (BX), X11                     // 66440f6a1b
+	PUNPCKHLQ (R11), X11                    // 66450f6a1b
+	PUNPCKHLQ X2, X11                       // 66440f6ada
+	PUNPCKHLQ X11, X11                      // 66450f6adb
+	PUNPCKHQDQ (BX), X2                     // 660f6d13
+	PUNPCKHQDQ (R11), X2                    // 66410f6d13
+	PUNPCKHQDQ X2, X2                       // 660f6dd2
+	PUNPCKHQDQ X11, X2                      // 66410f6dd3
+	PUNPCKHQDQ (BX), X11                    // 66440f6d1b
+	PUNPCKHQDQ (R11), X11                   // 66450f6d1b
+	PUNPCKHQDQ X2, X11                      // 66440f6dda
+	PUNPCKHQDQ X11, X11                     // 66450f6ddb
+	PUNPCKHWL (BX), M2                      // 0f6913
+	PUNPCKHWL (R11), M2                     // 410f6913
+	PUNPCKHWL M2, M2                        // 0f69d2
+	PUNPCKHWL M3, M2                        // 0f69d3
+	PUNPCKHWL (BX), M3                      // 0f691b
+	PUNPCKHWL (R11), M3                     // 410f691b
+	PUNPCKHWL M2, M3                        // 0f69da
+	PUNPCKHWL M3, M3                        // 0f69db
+	PUNPCKHWL (BX), X2                      // 660f6913
+	PUNPCKHWL (R11), X2                     // 66410f6913
+	PUNPCKHWL X2, X2                        // 660f69d2
+	PUNPCKHWL X11, X2                       // 66410f69d3
+	PUNPCKHWL (BX), X11                     // 66440f691b
+	PUNPCKHWL (R11), X11                    // 66450f691b
+	PUNPCKHWL X2, X11                       // 66440f69da
+	PUNPCKHWL X11, X11                      // 66450f69db
+	PUNPCKLBW (BX), M2                      // 0f6013
+	PUNPCKLBW (R11), M2                     // 410f6013
+	PUNPCKLBW M2, M2                        // 0f60d2
+	PUNPCKLBW M3, M2                        // 0f60d3
+	PUNPCKLBW (BX), M3                      // 0f601b
+	PUNPCKLBW (R11), M3                     // 410f601b
+	PUNPCKLBW M2, M3                        // 0f60da
+	PUNPCKLBW M3, M3                        // 0f60db
+	PUNPCKLBW (BX), X2                      // 660f6013
+	PUNPCKLBW (R11), X2                     // 66410f6013
+	PUNPCKLBW X2, X2                        // 660f60d2
+	PUNPCKLBW X11, X2                       // 66410f60d3
+	PUNPCKLBW (BX), X11                     // 66440f601b
+	PUNPCKLBW (R11), X11                    // 66450f601b
+	PUNPCKLBW X2, X11                       // 66440f60da
+	PUNPCKLBW X11, X11                      // 66450f60db
+	PUNPCKLLQ (BX), M2                      // 0f6213
+	PUNPCKLLQ (R11), M2                     // 410f6213
+	PUNPCKLLQ M2, M2                        // 0f62d2
+	PUNPCKLLQ M3, M2                        // 0f62d3
+	PUNPCKLLQ (BX), M3                      // 0f621b
+	PUNPCKLLQ (R11), M3                     // 410f621b
+	PUNPCKLLQ M2, M3                        // 0f62da
+	PUNPCKLLQ M3, M3                        // 0f62db
+	PUNPCKLLQ (BX), X2                      // 660f6213
+	PUNPCKLLQ (R11), X2                     // 66410f6213
+	PUNPCKLLQ X2, X2                        // 660f62d2
+	PUNPCKLLQ X11, X2                       // 66410f62d3
+	PUNPCKLLQ (BX), X11                     // 66440f621b
+	PUNPCKLLQ (R11), X11                    // 66450f621b
+	PUNPCKLLQ X2, X11                       // 66440f62da
+	PUNPCKLLQ X11, X11                      // 66450f62db
+	PUNPCKLQDQ (BX), X2                     // 660f6c13
+	PUNPCKLQDQ (R11), X2                    // 66410f6c13
+	PUNPCKLQDQ X2, X2                       // 660f6cd2
+	PUNPCKLQDQ X11, X2                      // 66410f6cd3
+	PUNPCKLQDQ (BX), X11                    // 66440f6c1b
+	PUNPCKLQDQ (R11), X11                   // 66450f6c1b
+	PUNPCKLQDQ X2, X11                      // 66440f6cda
+	PUNPCKLQDQ X11, X11                     // 66450f6cdb
+	PUNPCKLWL (BX), M2                      // 0f6113
+	PUNPCKLWL (R11), M2                     // 410f6113
+	PUNPCKLWL M2, M2                        // 0f61d2
+	PUNPCKLWL M3, M2                        // 0f61d3
+	PUNPCKLWL (BX), M3                      // 0f611b
+	PUNPCKLWL (R11), M3                     // 410f611b
+	PUNPCKLWL M2, M3                        // 0f61da
+	PUNPCKLWL M3, M3                        // 0f61db
+	PUNPCKLWL (BX), X2                      // 660f6113
+	PUNPCKLWL (R11), X2                     // 66410f6113
+	PUNPCKLWL X2, X2                        // 660f61d2
+	PUNPCKLWL X11, X2                       // 66410f61d3
+	PUNPCKLWL (BX), X11                     // 66440f611b
+	PUNPCKLWL (R11), X11                    // 66450f611b
+	PUNPCKLWL X2, X11                       // 66440f61da
+	PUNPCKLWL X11, X11                      // 66450f61db
+	PUSHQ FS                                // 0fa0
+	POPQ AX
+	PUSHQ GS                                // 0fa8
+	POPQ AX
+	PUSHW $61731                            // 666823f1
+	POPW AX
+	PUSHQ $4045620583                       // 68674523f1
+	POPQ AX
+	PUSHQ $7                                // 6a07
+	POPQ AX
+	PUSHW (BX)                              // 66ff33
+	POPW AX
+	PUSHW (R11)                             // 6641ff33
+	POPW AX
+	PUSHW DX                                // 66fff2 or 6652
+	POPW AX
+	PUSHW R11                               // 6641fff3 or 664153
+	POPW AX
+	PUSHQ (BX)                              // ff33
+	POPQ AX
+	PUSHQ (R11)                             // 41ff33
+	POPQ AX
+	PUSHQ DX                                // fff2 or 52
+	POPQ AX
+	PUSHQ R11                               // 41fff3 or 4153
+	POPQ AX
+	PUSHFW                                  // 669c
+	POPFW
+	PUSHFQ                                  // 9c
+	POPFQ
+	PXOR (BX), M2                           // 0fef13
+	PXOR (R11), M2                          // 410fef13
+	PXOR M2, M2                             // 0fefd2
+	PXOR M3, M2                             // 0fefd3
+	PXOR (BX), M3                           // 0fef1b
+	PXOR (R11), M3                          // 410fef1b
+	PXOR M2, M3                             // 0fefda
+	PXOR M3, M3                             // 0fefdb
+	PXOR (BX), X2                           // 660fef13
+	PXOR (R11), X2                          // 66410fef13
+	PXOR X2, X2                             // 660fefd2
+	PXOR X11, X2                            // 66410fefd3
+	PXOR (BX), X11                          // 66440fef1b
+	PXOR (R11), X11                         // 66450fef1b
+	PXOR X2, X11                            // 66440fefda
+	PXOR X11, X11                           // 66450fefdb
+	RCLW $1, (BX)                           // 66d113
+	RCLW $1, (R11)                          // 6641d113
+	RCLW $1, DX                             // 66d1d2
+	RCLW $1, R11                            // 6641d1d3
+	RCLW CL, (BX)                           // 66d313
+	RCLW CL, (R11)                          // 6641d313
+	RCLW CL, DX                             // 66d3d2
+	RCLW CL, R11                            // 6641d3d3
+	RCLW $7, (BX)                           // 66c11307
+	RCLW $7, (R11)                          // 6641c11307
+	RCLW $7, DX                             // 66c1d207
+	RCLW $7, R11                            // 6641c1d307
+	RCLL $1, (BX)                           // d113
+	RCLL $1, (R11)                          // 41d113
+	RCLL $1, DX                             // d1d2
+	RCLL $1, R11                            // 41d1d3
+	RCLL CL, (BX)                           // d313
+	RCLL CL, (R11)                          // 41d313
+	RCLL CL, DX                             // d3d2
+	RCLL CL, R11                            // 41d3d3
+	RCLL $7, (BX)                           // c11307
+	RCLL $7, (R11)                          // 41c11307
+	RCLL $7, DX                             // c1d207
+	RCLL $7, R11                            // 41c1d307
+	RCLQ $1, (BX)                           // 48d113
+	RCLQ $1, (R11)                          // 49d113
+	RCLQ $1, DX                             // 48d1d2
+	RCLQ $1, R11                            // 49d1d3
+	RCLQ CL, (BX)                           // 48d313
+	RCLQ CL, (R11)                          // 49d313
+	RCLQ CL, DX                             // 48d3d2
+	RCLQ CL, R11                            // 49d3d3
+	RCLQ $7, (BX)                           // 48c11307
+	RCLQ $7, (R11)                          // 49c11307
+	RCLQ $7, DX                             // 48c1d207
+	RCLQ $7, R11                            // 49c1d307
+	RCLB $1, (BX)                           // d013
+	RCLB $1, (R11)                          // 41d013
+	RCLB $1, DL                             // d0d2
+	RCLB $1, R11                            // 41d0d3
+	RCLB CL, (BX)                           // d213
+	RCLB CL, (R11)                          // 41d213
+	RCLB CL, DL                             // d2d2
+	RCLB CL, R11                            // 41d2d3
+	RCLB $7, (BX)                           // c01307
+	RCLB $7, (R11)                          // 41c01307
+	RCLB $7, DL                             // c0d207
+	RCLB $7, R11                            // 41c0d307
+	RCPPS (BX), X2                          // 0f5313
+	RCPPS (R11), X2                         // 410f5313
+	RCPPS X2, X2                            // 0f53d2
+	RCPPS X11, X2                           // 410f53d3
+	RCPPS (BX), X11                         // 440f531b
+	RCPPS (R11), X11                        // 450f531b
+	RCPPS X2, X11                           // 440f53da
+	RCPPS X11, X11                          // 450f53db
+	RCPSS (BX), X2                          // f30f5313
+	RCPSS (R11), X2                         // f3410f5313
+	RCPSS X2, X2                            // f30f53d2
+	RCPSS X11, X2                           // f3410f53d3
+	RCPSS (BX), X11                         // f3440f531b
+	RCPSS (R11), X11                        // f3450f531b
+	RCPSS X2, X11                           // f3440f53da
+	RCPSS X11, X11                          // f3450f53db
+	RCRW $1, (BX)                           // 66d11b
+	RCRW $1, (R11)                          // 6641d11b
+	RCRW $1, DX                             // 66d1da
+	RCRW $1, R11                            // 6641d1db
+	RCRW CL, (BX)                           // 66d31b
+	RCRW CL, (R11)                          // 6641d31b
+	RCRW CL, DX                             // 66d3da
+	RCRW CL, R11                            // 6641d3db
+	RCRW $7, (BX)                           // 66c11b07
+	RCRW $7, (R11)                          // 6641c11b07
+	RCRW $7, DX                             // 66c1da07
+	RCRW $7, R11                            // 6641c1db07
+	RCRL $1, (BX)                           // d11b
+	RCRL $1, (R11)                          // 41d11b
+	RCRL $1, DX                             // d1da
+	RCRL $1, R11                            // 41d1db
+	RCRL CL, (BX)                           // d31b
+	RCRL CL, (R11)                          // 41d31b
+	RCRL CL, DX                             // d3da
+	RCRL CL, R11                            // 41d3db
+	RCRL $7, (BX)                           // c11b07
+	RCRL $7, (R11)                          // 41c11b07
+	RCRL $7, DX                             // c1da07
+	RCRL $7, R11                            // 41c1db07
+	RCRQ $1, (BX)                           // 48d11b
+	RCRQ $1, (R11)                          // 49d11b
+	RCRQ $1, DX                             // 48d1da
+	RCRQ $1, R11                            // 49d1db
+	RCRQ CL, (BX)                           // 48d31b
+	RCRQ CL, (R11)                          // 49d31b
+	RCRQ CL, DX                             // 48d3da
+	RCRQ CL, R11                            // 49d3db
+	RCRQ $7, (BX)                           // 48c11b07
+	RCRQ $7, (R11)                          // 49c11b07
+	RCRQ $7, DX                             // 48c1da07
+	RCRQ $7, R11                            // 49c1db07
+	RCRB $1, (BX)                           // d01b
+	RCRB $1, (R11)                          // 41d01b
+	RCRB $1, DL                             // d0da
+	RCRB $1, R11                            // 41d0db
+	RCRB CL, (BX)                           // d21b
+	RCRB CL, (R11)                          // 41d21b
+	RCRB CL, DL                             // d2da
+	RCRB CL, R11                            // 41d2db
+	RCRB $7, (BX)                           // c01b07
+	RCRB $7, (R11)                          // 41c01b07
+	RCRB $7, DL                             // c0da07
+	RCRB $7, R11                            // 41c0db07
+	//TODO: RDFSBASE DX                     // f30faec2 or f3480faec2
+	//TODO: RDFSBASE R11                    // f3410faec3 or f3490faec3
+	//TODO: RDGSBASE DX                     // f30faeca or f3480faeca
+	//TODO: RDGSBASE R11                    // f3410faecb or f3490faecb
+	RDMSR                                   // 0f32
+	//TODO: RDPKRU                          // 0f01ee
+	RDPMC                                   // 0f33
+	//TODO: RDRAND DX                       // 660fc7f2 or 0fc7f2 or 480fc7f2
+	//TODO: RDRAND R11                      // 66410fc7f3 or 410fc7f3 or 490fc7f3
+	//TODO: RDSEED DX                       // 660fc7fa or 0fc7fa or 480fc7fa
+	//TODO: RDSEED R11                      // 66410fc7fb or 410fc7fb or 490fc7fb
+	RDTSC                                   // 0f31
+	//TODO: RDTSCP                          // 0f01f9
+	JCS 2(PC)
+	//TODO: RETQ                            // c3
+	JCS 2(PC)
+	//TODO: RETQ $0xf123                    // c223f1
+	JCS 2(PC)
+	//TODO: RETFQ                           // cb
+	JCS 2(PC)
+	//TODO: RETFQ $0xf123                   // ca23f1
+	ROLW $1, (BX)                           // 66d103
+	ROLW $1, (R11)                          // 6641d103
+	ROLW $1, DX                             // 66d1c2
+	ROLW $1, R11                            // 6641d1c3
+	ROLW CL, (BX)                           // 66d303
+	ROLW CL, (R11)                          // 6641d303
+	ROLW CL, DX                             // 66d3c2
+	ROLW CL, R11                            // 6641d3c3
+	ROLW $7, (BX)                           // 66c10307
+	ROLW $7, (R11)                          // 6641c10307
+	ROLW $7, DX                             // 66c1c207
+	ROLW $7, R11                            // 6641c1c307
+	ROLL $1, (BX)                           // d103
+	ROLL $1, (R11)                          // 41d103
+	ROLL $1, DX                             // d1c2
+	ROLL $1, R11                            // 41d1c3
+	ROLL CL, (BX)                           // d303
+	ROLL CL, (R11)                          // 41d303
+	ROLL CL, DX                             // d3c2
+	ROLL CL, R11                            // 41d3c3
+	ROLL $7, (BX)                           // c10307
+	ROLL $7, (R11)                          // 41c10307
+	ROLL $7, DX                             // c1c207
+	ROLL $7, R11                            // 41c1c307
+	ROLQ $1, (BX)                           // 48d103
+	ROLQ $1, (R11)                          // 49d103
+	ROLQ $1, DX                             // 48d1c2
+	ROLQ $1, R11                            // 49d1c3
+	ROLQ CL, (BX)                           // 48d303
+	ROLQ CL, (R11)                          // 49d303
+	ROLQ CL, DX                             // 48d3c2
+	ROLQ CL, R11                            // 49d3c3
+	ROLQ $7, (BX)                           // 48c10307
+	ROLQ $7, (R11)                          // 49c10307
+	ROLQ $7, DX                             // 48c1c207
+	ROLQ $7, R11                            // 49c1c307
+	ROLB $1, (BX)                           // d003
+	ROLB $1, (R11)                          // 41d003
+	ROLB $1, DL                             // d0c2
+	ROLB $1, R11                            // 41d0c3
+	ROLB CL, (BX)                           // d203
+	ROLB CL, (R11)                          // 41d203
+	ROLB CL, DL                             // d2c2
+	ROLB CL, R11                            // 41d2c3
+	ROLB $7, (BX)                           // c00307
+	ROLB $7, (R11)                          // 41c00307
+	ROLB $7, DL                             // c0c207
+	ROLB $7, R11                            // 41c0c307
+	RORW $1, (BX)                           // 66d10b
+	RORW $1, (R11)                          // 6641d10b
+	RORW $1, DX                             // 66d1ca
+	RORW $1, R11                            // 6641d1cb
+	RORW CL, (BX)                           // 66d30b
+	RORW CL, (R11)                          // 6641d30b
+	RORW CL, DX                             // 66d3ca
+	RORW CL, R11                            // 6641d3cb
+	RORW $7, (BX)                           // 66c10b07
+	RORW $7, (R11)                          // 6641c10b07
+	RORW $7, DX                             // 66c1ca07
+	RORW $7, R11                            // 6641c1cb07
+	RORL $1, (BX)                           // d10b
+	RORL $1, (R11)                          // 41d10b
+	RORL $1, DX                             // d1ca
+	RORL $1, R11                            // 41d1cb
+	RORL CL, (BX)                           // d30b
+	RORL CL, (R11)                          // 41d30b
+	RORL CL, DX                             // d3ca
+	RORL CL, R11                            // 41d3cb
+	RORL $7, (BX)                           // c10b07
+	RORL $7, (R11)                          // 41c10b07
+	RORL $7, DX                             // c1ca07
+	RORL $7, R11                            // 41c1cb07
+	RORQ $1, (BX)                           // 48d10b
+	RORQ $1, (R11)                          // 49d10b
+	RORQ $1, DX                             // 48d1ca
+	RORQ $1, R11                            // 49d1cb
+	RORQ CL, (BX)                           // 48d30b
+	RORQ CL, (R11)                          // 49d30b
+	RORQ CL, DX                             // 48d3ca
+	RORQ CL, R11                            // 49d3cb
+	RORQ $7, (BX)                           // 48c10b07
+	RORQ $7, (R11)                          // 49c10b07
+	RORQ $7, DX                             // 48c1ca07
+	RORQ $7, R11                            // 49c1cb07
+	RORB $1, (BX)                           // d00b
+	RORB $1, (R11)                          // 41d00b
+	RORB $1, DL                             // d0ca
+	RORB $1, R11                            // 41d0cb
+	RORB CL, (BX)                           // d20b
+	RORB CL, (R11)                          // 41d20b
+	RORB CL, DL                             // d2ca
+	RORB CL, R11                            // 41d2cb
+	RORB $7, (BX)                           // c00b07
+	RORB $7, (R11)                          // 41c00b07
+	RORB $7, DL                             // c0ca07
+	RORB $7, R11                            // 41c0cb07
+	//TODO: RORXL $7, (BX), DX              // c4e37bf01307
+	//TODO: RORXL $7, (R11), DX             // c4c37bf01307
+	//TODO: RORXL $7, DX, DX                // c4e37bf0d207
+	//TODO: RORXL $7, R11, DX               // c4c37bf0d307
+	//TODO: RORXL $7, (BX), R11             // c4637bf01b07
+	//TODO: RORXL $7, (R11), R11            // c4437bf01b07
+	//TODO: RORXL $7, DX, R11               // c4637bf0da07
+	//TODO: RORXL $7, R11, R11              // c4437bf0db07
+	//TODO: RORXQ $7, (BX), DX              // c4e3fbf01307
+	//TODO: RORXQ $7, (R11), DX             // c4c3fbf01307
+	//TODO: RORXQ $7, DX, DX                // c4e3fbf0d207
+	//TODO: RORXQ $7, R11, DX               // c4c3fbf0d307
+	//TODO: RORXQ $7, (BX), R11             // c463fbf01b07
+	//TODO: RORXQ $7, (R11), R11            // c443fbf01b07
+	//TODO: RORXQ $7, DX, R11               // c463fbf0da07
+	//TODO: RORXQ $7, R11, R11              // c443fbf0db07
+	ROUNDPD $7, (BX), X2                    // 660f3a091307
+	ROUNDPD $7, (R11), X2                   // 66410f3a091307
+	ROUNDPD $7, X2, X2                      // 660f3a09d207
+	ROUNDPD $7, X11, X2                     // 66410f3a09d307
+	ROUNDPD $7, (BX), X11                   // 66440f3a091b07
+	ROUNDPD $7, (R11), X11                  // 66450f3a091b07
+	ROUNDPD $7, X2, X11                     // 66440f3a09da07
+	ROUNDPD $7, X11, X11                    // 66450f3a09db07
+	ROUNDPS $7, (BX), X2                    // 660f3a081307
+	ROUNDPS $7, (R11), X2                   // 66410f3a081307
+	ROUNDPS $7, X2, X2                      // 660f3a08d207
+	ROUNDPS $7, X11, X2                     // 66410f3a08d307
+	ROUNDPS $7, (BX), X11                   // 66440f3a081b07
+	ROUNDPS $7, (R11), X11                  // 66450f3a081b07
+	ROUNDPS $7, X2, X11                     // 66440f3a08da07
+	ROUNDPS $7, X11, X11                    // 66450f3a08db07
+	ROUNDSD $7, (BX), X2                    // 660f3a0b1307
+	ROUNDSD $7, (R11), X2                   // 66410f3a0b1307
+	ROUNDSD $7, X2, X2                      // 660f3a0bd207
+	ROUNDSD $7, X11, X2                     // 66410f3a0bd307
+	ROUNDSD $7, (BX), X11                   // 66440f3a0b1b07
+	ROUNDSD $7, (R11), X11                  // 66450f3a0b1b07
+	ROUNDSD $7, X2, X11                     // 66440f3a0bda07
+	ROUNDSD $7, X11, X11                    // 66450f3a0bdb07
+	ROUNDSS $7, (BX), X2                    // 660f3a0a1307
+	ROUNDSS $7, (R11), X2                   // 66410f3a0a1307
+	ROUNDSS $7, X2, X2                      // 660f3a0ad207
+	ROUNDSS $7, X11, X2                     // 66410f3a0ad307
+	ROUNDSS $7, (BX), X11                   // 66440f3a0a1b07
+	ROUNDSS $7, (R11), X11                  // 66450f3a0a1b07
+	ROUNDSS $7, X2, X11                     // 66440f3a0ada07
+	ROUNDSS $7, X11, X11                    // 66450f3a0adb07
+	RSM                                     // 0faa
+	RSQRTPS (BX), X2                        // 0f5213
+	RSQRTPS (R11), X2                       // 410f5213
+	RSQRTPS X2, X2                          // 0f52d2
+	RSQRTPS X11, X2                         // 410f52d3
+	RSQRTPS (BX), X11                       // 440f521b
+	RSQRTPS (R11), X11                      // 450f521b
+	RSQRTPS X2, X11                         // 440f52da
+	RSQRTPS X11, X11                        // 450f52db
+	RSQRTSS (BX), X2                        // f30f5213
+	RSQRTSS (R11), X2                       // f3410f5213
+	RSQRTSS X2, X2                          // f30f52d2
+	RSQRTSS X11, X2                         // f3410f52d3
+	RSQRTSS (BX), X11                       // f3440f521b
+	RSQRTSS (R11), X11                      // f3450f521b
+	RSQRTSS X2, X11                         // f3440f52da
+	RSQRTSS X11, X11                        // f3450f52db
+	//TODO: SAHF                            // 9e
+	SARW $1, (BX)                           // 66d13b
+	SARW $1, (R11)                          // 6641d13b
+	SARW $1, DX                             // 66d1fa
+	SARW $1, R11                            // 6641d1fb
+	SARW CL, (BX)                           // 66d33b
+	SARW CL, (R11)                          // 6641d33b
+	SARW CL, DX                             // 66d3fa
+	SARW CL, R11                            // 6641d3fb
+	SARW $7, (BX)                           // 66c13b07
+	SARW $7, (R11)                          // 6641c13b07
+	SARW $7, DX                             // 66c1fa07
+	SARW $7, R11                            // 6641c1fb07
+	SARL $1, (BX)                           // d13b
+	SARL $1, (R11)                          // 41d13b
+	SARL $1, DX                             // d1fa
+	SARL $1, R11                            // 41d1fb
+	SARL CL, (BX)                           // d33b
+	SARL CL, (R11)                          // 41d33b
+	SARL CL, DX                             // d3fa
+	SARL CL, R11                            // 41d3fb
+	SARL $7, (BX)                           // c13b07
+	SARL $7, (R11)                          // 41c13b07
+	SARL $7, DX                             // c1fa07
+	SARL $7, R11                            // 41c1fb07
+	SARQ $1, (BX)                           // 48d13b
+	SARQ $1, (R11)                          // 49d13b
+	SARQ $1, DX                             // 48d1fa
+	SARQ $1, R11                            // 49d1fb
+	SARQ CL, (BX)                           // 48d33b
+	SARQ CL, (R11)                          // 49d33b
+	SARQ CL, DX                             // 48d3fa
+	SARQ CL, R11                            // 49d3fb
+	SARQ $7, (BX)                           // 48c13b07
+	SARQ $7, (R11)                          // 49c13b07
+	SARQ $7, DX                             // 48c1fa07
+	SARQ $7, R11                            // 49c1fb07
+	SARB $1, (BX)                           // d03b
+	SARB $1, (R11)                          // 41d03b
+	SARB $1, DL                             // d0fa
+	SARB $1, R11                            // 41d0fb
+	SARB CL, (BX)                           // d23b
+	SARB CL, (R11)                          // 41d23b
+	SARB CL, DL                             // d2fa
+	SARB CL, R11                            // 41d2fb
+	SARB $7, (BX)                           // c03b07
+	SARB $7, (R11)                          // 41c03b07
+	SARB $7, DL                             // c0fa07
+	SARB $7, R11                            // 41c0fb07
+	SARXL R9, (BX), DX                      // c4e232f713
+	SARXL R9, (R11), DX                     // c4c232f713
+	SARXL R9, DX, DX                        // c4e232f7d2
+	SARXL R9, R11, DX                       // c4c232f7d3
+	SARXL R9, (BX), R11                     // c46232f71b
+	SARXL R9, (R11), R11                    // c44232f71b
+	SARXL R9, DX, R11                       // c46232f7da
+	SARXL R9, R11, R11                      // c44232f7db
+	SARXQ R14, (BX), DX                     // c4e28af713
+	SARXQ R14, (R11), DX                    // c4c28af713
+	SARXQ R14, DX, DX                       // c4e28af7d2
+	SARXQ R14, R11, DX                      // c4c28af7d3
+	SARXQ R14, (BX), R11                    // c4628af71b
+	SARXQ R14, (R11), R11                   // c4428af71b
+	SARXQ R14, DX, R11                      // c4628af7da
+	SARXQ R14, R11, R11                     // c4428af7db
+	SBBB $7, AL                             // 1c07
+	SBBW $61731, AX                         // 661d23f1
+	SBBL $4045620583, AX                    // 1d674523f1
+	SBBQ $-249346713, AX                    // 481d674523f1
+	SBBW $61731, (BX)                       // 66811b23f1
+	SBBW $61731, (R11)                      // 6641811b23f1
+	SBBW $61731, DX                         // 6681da23f1
+	SBBW $61731, R11                        // 664181db23f1
+	SBBW $7, (BX)                           // 66831b07
+	SBBW $7, (R11)                          // 6641831b07
+	SBBW $7, DX                             // 6683da07
+	SBBW $7, R11                            // 664183db07
+	SBBW DX, (BX)                           // 661913
+	SBBW R11, (BX)                          // 6644191b
+	SBBW DX, (R11)                          // 66411913
+	SBBW R11, (R11)                         // 6645191b
+	SBBW DX, DX                             // 6619d2 or 661bd2
+	SBBW R11, DX                            // 664419da or 66411bd3
+	SBBW DX, R11                            // 664119d3 or 66441bda
+	SBBW R11, R11                           // 664519db or 66451bdb
+	SBBL $4045620583, (BX)                  // 811b674523f1
+	SBBL $4045620583, (R11)                 // 41811b674523f1
+	SBBL $4045620583, DX                    // 81da674523f1
+	SBBL $4045620583, R11                   // 4181db674523f1
+	SBBL $7, (BX)                           // 831b07
+	SBBL $7, (R11)                          // 41831b07
+	SBBL $7, DX                             // 83da07
+	SBBL $7, R11                            // 4183db07
+	SBBL DX, (BX)                           // 1913
+	SBBL R11, (BX)                          // 44191b
+	SBBL DX, (R11)                          // 411913
+	SBBL R11, (R11)                         // 45191b
+	SBBL DX, DX                             // 19d2 or 1bd2
+	SBBL R11, DX                            // 4419da or 411bd3
+	SBBL DX, R11                            // 4119d3 or 441bda
+	SBBL R11, R11                           // 4519db or 451bdb
+	SBBQ $-249346713, (BX)                  // 48811b674523f1
+	SBBQ $-249346713, (R11)                 // 49811b674523f1
+	SBBQ $-249346713, DX                    // 4881da674523f1
+	SBBQ $-249346713, R11                   // 4981db674523f1
+	SBBQ $7, (BX)                           // 48831b07
+	SBBQ $7, (R11)                          // 49831b07
+	SBBQ $7, DX                             // 4883da07
+	SBBQ $7, R11                            // 4983db07
+	SBBQ DX, (BX)                           // 481913
+	SBBQ R11, (BX)                          // 4c191b
+	SBBQ DX, (R11)                          // 491913
+	SBBQ R11, (R11)                         // 4d191b
+	SBBQ DX, DX                             // 4819d2 or 481bd2
+	SBBQ R11, DX                            // 4c19da or 491bd3
+	SBBQ DX, R11                            // 4919d3 or 4c1bda
+	SBBQ R11, R11                           // 4d19db or 4d1bdb
+	SBBB $7, (BX)                           // 801b07
+	SBBB $7, (R11)                          // 41801b07
+	SBBB $7, DL                             // 80da07
+	SBBB $7, R11                            // 4180db07
+	SBBB DL, (BX)                           // 1813
+	SBBB R11, (BX)                          // 44181b
+	SBBB DL, (R11)                          // 411813
+	SBBB R11, (R11)                         // 45181b
+	SBBB DL, DL                             // 18d2 or 1ad2
+	SBBB R11, DL                            // 4418da or 411ad3
+	SBBB DL, R11                            // 4118d3 or 441ada
+	SBBB R11, R11                           // 4518db or 451adb
+	SBBW (BX), DX                           // 661b13
+	SBBW (R11), DX                          // 66411b13
+	SBBW (BX), R11                          // 66441b1b
+	SBBW (R11), R11                         // 66451b1b
+	SBBL (BX), DX                           // 1b13
+	SBBL (R11), DX                          // 411b13
+	SBBL (BX), R11                          // 441b1b
+	SBBL (R11), R11                         // 451b1b
+	SBBQ (BX), DX                           // 481b13
+	SBBQ (R11), DX                          // 491b13
+	SBBQ (BX), R11                          // 4c1b1b
+	SBBQ (R11), R11                         // 4d1b1b
+	SBBB (BX), DL                           // 1a13
+	SBBB (R11), DL                          // 411a13
+	SBBB (BX), R11                          // 441a1b
+	SBBB (R11), R11                         // 451a1b
+	SCASB                                   // ae
+	SCASL                                   // af
+	SCASQ                                   // 48af
+	SCASW                                   // 66af
+	SETHI (BX)                              // 0f9703
+	SETHI (R11)                             // 410f9703
+	SETHI DL                                // 0f97c2
+	SETHI R11                               // 410f97c3
+	SETCC (BX)                              // 0f9303
+	SETCC (R11)                             // 410f9303
+	SETCC DL                                // 0f93c2
+	SETCC R11                               // 410f93c3
+	SETCS (BX)                              // 0f9203
+	SETCS (R11)                             // 410f9203
+	SETCS DL                                // 0f92c2
+	SETCS R11                               // 410f92c3
+	SETLS (BX)                              // 0f9603
+	SETLS (R11)                             // 410f9603
+	SETLS DL                                // 0f96c2
+	SETLS R11                               // 410f96c3
+	SETEQ (BX)                              // 0f9403
+	SETEQ (R11)                             // 410f9403
+	SETEQ DL                                // 0f94c2
+	SETEQ R11                               // 410f94c3
+	SETGT (BX)                              // 0f9f03
+	SETGT (R11)                             // 410f9f03
+	SETGT DL                                // 0f9fc2
+	SETGT R11                               // 410f9fc3
+	SETGE (BX)                              // 0f9d03
+	SETGE (R11)                             // 410f9d03
+	SETGE DL                                // 0f9dc2
+	SETGE R11                               // 410f9dc3
+	SETLT (BX)                              // 0f9c03
+	SETLT (R11)                             // 410f9c03
+	SETLT DL                                // 0f9cc2
+	SETLT R11                               // 410f9cc3
+	SETLE (BX)                              // 0f9e03
+	SETLE (R11)                             // 410f9e03
+	SETLE DL                                // 0f9ec2
+	SETLE R11                               // 410f9ec3
+	SETNE (BX)                              // 0f9503
+	SETNE (R11)                             // 410f9503
+	SETNE DL                                // 0f95c2
+	SETNE R11                               // 410f95c3
+	SETOC (BX)                              // 0f9103
+	SETOC (R11)                             // 410f9103
+	SETOC DL                                // 0f91c2
+	SETOC R11                               // 410f91c3
+	SETPC (BX)                              // 0f9b03
+	SETPC (R11)                             // 410f9b03
+	SETPC DL                                // 0f9bc2
+	SETPC R11                               // 410f9bc3
+	SETPL (BX)                              // 0f9903
+	SETPL (R11)                             // 410f9903
+	SETPL DL                                // 0f99c2
+	SETPL R11                               // 410f99c3
+	SETOS (BX)                              // 0f9003
+	SETOS (R11)                             // 410f9003
+	SETOS DL                                // 0f90c2
+	SETOS R11                               // 410f90c3
+	SETPS (BX)                              // 0f9a03
+	SETPS (R11)                             // 410f9a03
+	SETPS DL                                // 0f9ac2
+	SETPS R11                               // 410f9ac3
+	SETMI (BX)                              // 0f9803
+	SETMI (R11)                             // 410f9803
+	SETMI DL                                // 0f98c2
+	SETMI R11                               // 410f98c3
+	SFENCE                                  // 0faef8
+	//TODO: SGDT (BX)                       // 0f0103
+	//TODO: SGDT (R11)                      // 410f0103
+	SHLW $1, (BX)                           // 66d123
+	SHLW $1, (R11)                          // 6641d123
+	SHLW $1, DX                             // 66d1e2
+	SHLW $1, R11                            // 6641d1e3
+	SHLW CL, (BX)                           // 66d323
+	SHLW CL, (R11)                          // 6641d323
+	SHLW CL, DX                             // 66d3e2
+	SHLW CL, R11                            // 6641d3e3
+	SHLW $7, (BX)                           // 66c12307
+	SHLW $7, (R11)                          // 6641c12307
+	SHLW $7, DX                             // 66c1e207
+	SHLW $7, R11                            // 6641c1e307
+	SHLL $1, (BX)                           // d123
+	SHLL $1, (R11)                          // 41d123
+	SHLL $1, DX                             // d1e2
+	SHLL $1, R11                            // 41d1e3
+	SHLL CL, (BX)                           // d323
+	SHLL CL, (R11)                          // 41d323
+	SHLL CL, DX                             // d3e2
+	SHLL CL, R11                            // 41d3e3
+	SHLL $7, (BX)                           // c12307
+	SHLL $7, (R11)                          // 41c12307
+	SHLL $7, DX                             // c1e207
+	SHLL $7, R11                            // 41c1e307
+	SHLQ $1, (BX)                           // 48d123
+	SHLQ $1, (R11)                          // 49d123
+	SHLQ $1, DX                             // 48d1e2
+	SHLQ $1, R11                            // 49d1e3
+	SHLQ CL, (BX)                           // 48d323
+	SHLQ CL, (R11)                          // 49d323
+	SHLQ CL, DX                             // 48d3e2
+	SHLQ CL, R11                            // 49d3e3
+	SHLQ $7, (BX)                           // 48c12307
+	SHLQ $7, (R11)                          // 49c12307
+	SHLQ $7, DX                             // 48c1e207
+	SHLQ $7, R11                            // 49c1e307
+	SHLB $1, (BX)                           // d023
+	SHLB $1, (R11)                          // 41d023
+	SHLB $1, DL                             // d0e2
+	SHLB $1, R11                            // 41d0e3
+	SHLB CL, (BX)                           // d223
+	SHLB CL, (R11)                          // 41d223
+	SHLB CL, DL                             // d2e2
+	SHLB CL, R11                            // 41d2e3
+	SHLB $7, (BX)                           // c02307
+	SHLB $7, (R11)                          // 41c02307
+	SHLB $7, DL                             // c0e207
+	SHLB $7, R11                            // 41c0e307
+	SHLW CL, DX, (BX)                       // 660fa513
+	SHLW CL, R11, (BX)                      // 66440fa51b
+	SHLW CL, DX, (R11)                      // 66410fa513
+	SHLW CL, R11, (R11)                     // 66450fa51b
+	SHLW CL, DX, DX                         // 660fa5d2
+	SHLW CL, R11, DX                        // 66440fa5da
+	SHLW CL, DX, R11                        // 66410fa5d3
+	SHLW CL, R11, R11                       // 66450fa5db
+	SHLW $7, DX, (BX)                       // 660fa41307
+	SHLW $7, R11, (BX)                      // 66440fa41b07
+	SHLW $7, DX, (R11)                      // 66410fa41307
+	SHLW $7, R11, (R11)                     // 66450fa41b07
+	SHLW $7, DX, DX                         // 660fa4d207
+	SHLW $7, R11, DX                        // 66440fa4da07
+	SHLW $7, DX, R11                        // 66410fa4d307
+	SHLW $7, R11, R11                       // 66450fa4db07
+	SHLL CL, DX, (BX)                       // 0fa513
+	SHLL CL, R11, (BX)                      // 440fa51b
+	SHLL CL, DX, (R11)                      // 410fa513
+	SHLL CL, R11, (R11)                     // 450fa51b
+	SHLL CL, DX, DX                         // 0fa5d2
+	SHLL CL, R11, DX                        // 440fa5da
+	SHLL CL, DX, R11                        // 410fa5d3
+	SHLL CL, R11, R11                       // 450fa5db
+	SHLL $7, DX, (BX)                       // 0fa41307
+	SHLL $7, R11, (BX)                      // 440fa41b07
+	SHLL $7, DX, (R11)                      // 410fa41307
+	SHLL $7, R11, (R11)                     // 450fa41b07
+	SHLL $7, DX, DX                         // 0fa4d207
+	SHLL $7, R11, DX                        // 440fa4da07
+	SHLL $7, DX, R11                        // 410fa4d307
+	SHLL $7, R11, R11                       // 450fa4db07
+	SHLQ CL, DX, (BX)                       // 480fa513
+	SHLQ CL, R11, (BX)                      // 4c0fa51b
+	SHLQ CL, DX, (R11)                      // 490fa513
+	SHLQ CL, R11, (R11)                     // 4d0fa51b
+	SHLQ CL, DX, DX                         // 480fa5d2
+	SHLQ CL, R11, DX                        // 4c0fa5da
+	SHLQ CL, DX, R11                        // 490fa5d3
+	SHLQ CL, R11, R11                       // 4d0fa5db
+	SHLQ $7, DX, (BX)                       // 480fa41307
+	SHLQ $7, R11, (BX)                      // 4c0fa41b07
+	SHLQ $7, DX, (R11)                      // 490fa41307
+	SHLQ $7, R11, (R11)                     // 4d0fa41b07
+	SHLQ $7, DX, DX                         // 480fa4d207
+	SHLQ $7, R11, DX                        // 4c0fa4da07
+	SHLQ $7, DX, R11                        // 490fa4d307
+	SHLQ $7, R11, R11                       // 4d0fa4db07
+	SHLXL R9, (BX), DX                      // c4e231f713
+	SHLXL R9, (R11), DX                     // c4c231f713
+	SHLXL R9, DX, DX                        // c4e231f7d2
+	SHLXL R9, R11, DX                       // c4c231f7d3
+	SHLXL R9, (BX), R11                     // c46231f71b
+	SHLXL R9, (R11), R11                    // c44231f71b
+	SHLXL R9, DX, R11                       // c46231f7da
+	SHLXL R9, R11, R11                      // c44231f7db
+	SHLXQ R14, (BX), DX                     // c4e289f713
+	SHLXQ R14, (R11), DX                    // c4c289f713
+	SHLXQ R14, DX, DX                       // c4e289f7d2
+	SHLXQ R14, R11, DX                      // c4c289f7d3
+	SHLXQ R14, (BX), R11                    // c46289f71b
+	SHLXQ R14, (R11), R11                   // c44289f71b
+	SHLXQ R14, DX, R11                      // c46289f7da
+	SHLXQ R14, R11, R11                     // c44289f7db
+	SHRW $1, (BX)                           // 66d12b
+	SHRW $1, (R11)                          // 6641d12b
+	SHRW $1, DX                             // 66d1ea
+	SHRW $1, R11                            // 6641d1eb
+	SHRW CL, (BX)                           // 66d32b
+	SHRW CL, (R11)                          // 6641d32b
+	SHRW CL, DX                             // 66d3ea
+	SHRW CL, R11                            // 6641d3eb
+	SHRW $7, (BX)                           // 66c12b07
+	SHRW $7, (R11)                          // 6641c12b07
+	SHRW $7, DX                             // 66c1ea07
+	SHRW $7, R11                            // 6641c1eb07
+	SHRL $1, (BX)                           // d12b
+	SHRL $1, (R11)                          // 41d12b
+	SHRL $1, DX                             // d1ea
+	SHRL $1, R11                            // 41d1eb
+	SHRL CL, (BX)                           // d32b
+	SHRL CL, (R11)                          // 41d32b
+	SHRL CL, DX                             // d3ea
+	SHRL CL, R11                            // 41d3eb
+	SHRL $7, (BX)                           // c12b07
+	SHRL $7, (R11)                          // 41c12b07
+	SHRL $7, DX                             // c1ea07
+	SHRL $7, R11                            // 41c1eb07
+	SHRQ $1, (BX)                           // 48d12b
+	SHRQ $1, (R11)                          // 49d12b
+	SHRQ $1, DX                             // 48d1ea
+	SHRQ $1, R11                            // 49d1eb
+	SHRQ CL, (BX)                           // 48d32b
+	SHRQ CL, (R11)                          // 49d32b
+	SHRQ CL, DX                             // 48d3ea
+	SHRQ CL, R11                            // 49d3eb
+	SHRQ $7, (BX)                           // 48c12b07
+	SHRQ $7, (R11)                          // 49c12b07
+	SHRQ $7, DX                             // 48c1ea07
+	SHRQ $7, R11                            // 49c1eb07
+	SHRB $1, (BX)                           // d02b
+	SHRB $1, (R11)                          // 41d02b
+	SHRB $1, DL                             // d0ea
+	SHRB $1, R11                            // 41d0eb
+	SHRB CL, (BX)                           // d22b
+	SHRB CL, (R11)                          // 41d22b
+	SHRB CL, DL                             // d2ea
+	SHRB CL, R11                            // 41d2eb
+	SHRB $7, (BX)                           // c02b07
+	SHRB $7, (R11)                          // 41c02b07
+	SHRB $7, DL                             // c0ea07
+	SHRB $7, R11                            // 41c0eb07
+	SHRW CL, DX, (BX)                       // 660fad13
+	SHRW CL, R11, (BX)                      // 66440fad1b
+	SHRW CL, DX, (R11)                      // 66410fad13
+	SHRW CL, R11, (R11)                     // 66450fad1b
+	SHRW CL, DX, DX                         // 660fadd2
+	SHRW CL, R11, DX                        // 66440fadda
+	SHRW CL, DX, R11                        // 66410fadd3
+	SHRW CL, R11, R11                       // 66450faddb
+	SHRW $7, DX, (BX)                       // 660fac1307
+	SHRW $7, R11, (BX)                      // 66440fac1b07
+	SHRW $7, DX, (R11)                      // 66410fac1307
+	SHRW $7, R11, (R11)                     // 66450fac1b07
+	SHRW $7, DX, DX                         // 660facd207
+	SHRW $7, R11, DX                        // 66440facda07
+	SHRW $7, DX, R11                        // 66410facd307
+	SHRW $7, R11, R11                       // 66450facdb07
+	SHRL CL, DX, (BX)                       // 0fad13
+	SHRL CL, R11, (BX)                      // 440fad1b
+	SHRL CL, DX, (R11)                      // 410fad13
+	SHRL CL, R11, (R11)                     // 450fad1b
+	SHRL CL, DX, DX                         // 0fadd2
+	SHRL CL, R11, DX                        // 440fadda
+	SHRL CL, DX, R11                        // 410fadd3
+	SHRL CL, R11, R11                       // 450faddb
+	SHRL $7, DX, (BX)                       // 0fac1307
+	SHRL $7, R11, (BX)                      // 440fac1b07
+	SHRL $7, DX, (R11)                      // 410fac1307
+	SHRL $7, R11, (R11)                     // 450fac1b07
+	SHRL $7, DX, DX                         // 0facd207
+	SHRL $7, R11, DX                        // 440facda07
+	SHRL $7, DX, R11                        // 410facd307
+	SHRL $7, R11, R11                       // 450facdb07
+	SHRQ CL, DX, (BX)                       // 480fad13
+	SHRQ CL, R11, (BX)                      // 4c0fad1b
+	SHRQ CL, DX, (R11)                      // 490fad13
+	SHRQ CL, R11, (R11)                     // 4d0fad1b
+	SHRQ CL, DX, DX                         // 480fadd2
+	SHRQ CL, R11, DX                        // 4c0fadda
+	SHRQ CL, DX, R11                        // 490fadd3
+	SHRQ CL, R11, R11                       // 4d0faddb
+	SHRQ $7, DX, (BX)                       // 480fac1307
+	SHRQ $7, R11, (BX)                      // 4c0fac1b07
+	SHRQ $7, DX, (R11)                      // 490fac1307
+	SHRQ $7, R11, (R11)                     // 4d0fac1b07
+	SHRQ $7, DX, DX                         // 480facd207
+	SHRQ $7, R11, DX                        // 4c0facda07
+	SHRQ $7, DX, R11                        // 490facd307
+	SHRQ $7, R11, R11                       // 4d0facdb07
+	SHRXL R9, (BX), DX                      // c4e233f713
+	SHRXL R9, (R11), DX                     // c4c233f713
+	SHRXL R9, DX, DX                        // c4e233f7d2
+	SHRXL R9, R11, DX                       // c4c233f7d3
+	SHRXL R9, (BX), R11                     // c46233f71b
+	SHRXL R9, (R11), R11                    // c44233f71b
+	SHRXL R9, DX, R11                       // c46233f7da
+	SHRXL R9, R11, R11                      // c44233f7db
+	SHRXQ R14, (BX), DX                     // c4e28bf713
+	SHRXQ R14, (R11), DX                    // c4c28bf713
+	SHRXQ R14, DX, DX                       // c4e28bf7d2
+	SHRXQ R14, R11, DX                      // c4c28bf7d3
+	SHRXQ R14, (BX), R11                    // c4628bf71b
+	SHRXQ R14, (R11), R11                   // c4428bf71b
+	SHRXQ R14, DX, R11                      // c4628bf7da
+	SHRXQ R14, R11, R11                     // c4428bf7db
+	SHUFPD $7, (BX), X2                     // 660fc61307
+	SHUFPD $7, (R11), X2                    // 66410fc61307
+	SHUFPD $7, X2, X2                       // 660fc6d207
+	SHUFPD $7, X11, X2                      // 66410fc6d307
+	SHUFPD $7, (BX), X11                    // 66440fc61b07
+	SHUFPD $7, (R11), X11                   // 66450fc61b07
+	SHUFPD $7, X2, X11                      // 66440fc6da07
+	SHUFPD $7, X11, X11                     // 66450fc6db07
+	SHUFPS $7, (BX), X2                     // 0fc61307
+	SHUFPS $7, (R11), X2                    // 410fc61307
+	SHUFPS $7, X2, X2                       // 0fc6d207
+	SHUFPS $7, X11, X2                      // 410fc6d307
+	SHUFPS $7, (BX), X11                    // 440fc61b07
+	SHUFPS $7, (R11), X11                   // 450fc61b07
+	SHUFPS $7, X2, X11                      // 440fc6da07
+	SHUFPS $7, X11, X11                     // 450fc6db07
+	//TODO: SIDT (BX)                       // 0f010b
+	//TODO: SIDT (R11)                      // 410f010b
+	//TODO: SLDTW (BX)                      // 660f0003
+	//TODO: SLDTW (R11)                     // 66410f0003
+	//TODO: SLDTW DX                        // 660f00c2
+	//TODO: SLDTW R11                       // 66410f00c3
+	//TODO: SLDTL (BX)                      // 0f0003
+	//TODO: SLDTL (R11)                     // 410f0003
+	//TODO: SLDTL DX                        // 0f00c2
+	//TODO: SLDTL R11                       // 410f00c3
+	//TODO: SLDTQ (BX)                      // 480f0003
+	//TODO: SLDTQ (R11)                     // 490f0003
+	//TODO: SLDTQ DX                        // 480f00c2
+	//TODO: SLDTQ R11                       // 490f00c3
+	//TODO: SMSWW (BX)                      // 660f0123
+	//TODO: SMSWW (R11)                     // 66410f0123
+	//TODO: SMSWW DX                        // 660f01e2
+	//TODO: SMSWW R11                       // 66410f01e3
+	//TODO: SMSWL (BX)                      // 0f0123
+	//TODO: SMSWL (R11)                     // 410f0123
+	//TODO: SMSWL DX                        // 0f01e2
+	//TODO: SMSWL R11                       // 410f01e3
+	//TODO: SMSWQ (BX)                      // 480f0123
+	//TODO: SMSWQ (R11)                     // 490f0123
+	//TODO: SMSWQ DX                        // 480f01e2
+	//TODO: SMSWQ R11                       // 490f01e3
+	SQRTPD (BX), X2                         // 660f5113
+	SQRTPD (R11), X2                        // 66410f5113
+	SQRTPD X2, X2                           // 660f51d2
+	SQRTPD X11, X2                          // 66410f51d3
+	SQRTPD (BX), X11                        // 66440f511b
+	SQRTPD (R11), X11                       // 66450f511b
+	SQRTPD X2, X11                          // 66440f51da
+	SQRTPD X11, X11                         // 66450f51db
+	SQRTPS (BX), X2                         // 0f5113
+	SQRTPS (R11), X2                        // 410f5113
+	SQRTPS X2, X2                           // 0f51d2
+	SQRTPS X11, X2                          // 410f51d3
+	SQRTPS (BX), X11                        // 440f511b
+	SQRTPS (R11), X11                       // 450f511b
+	SQRTPS X2, X11                          // 440f51da
+	SQRTPS X11, X11                         // 450f51db
+	SQRTSD (BX), X2                         // f20f5113
+	SQRTSD (R11), X2                        // f2410f5113
+	SQRTSD X2, X2                           // f20f51d2
+	SQRTSD X11, X2                          // f2410f51d3
+	SQRTSD (BX), X11                        // f2440f511b
+	SQRTSD (R11), X11                       // f2450f511b
+	SQRTSD X2, X11                          // f2440f51da
+	SQRTSD X11, X11                         // f2450f51db
+	SQRTSS (BX), X2                         // f30f5113
+	SQRTSS (R11), X2                        // f3410f5113
+	SQRTSS X2, X2                           // f30f51d2
+	SQRTSS X11, X2                          // f3410f51d3
+	SQRTSS (BX), X11                        // f3440f511b
+	SQRTSS (R11), X11                       // f3450f511b
+	SQRTSS X2, X11                          // f3440f51da
+	SQRTSS X11, X11                         // f3450f51db
+	//TODO: STAC                            // 0f01cb
+	STC                                     // f9
+	STD                                     // fd
+	STI                                     // fb
+	STMXCSR (BX)                            // 0fae1b
+	STMXCSR (R11)                           // 410fae1b
+	STOSB                                   // aa
+	STOSL                                   // ab
+	STOSQ                                   // 48ab
+	STOSW                                   // 66ab
+	//TODO: STRW (BX)                       // 660f000b
+	//TODO: STRW (R11)                      // 66410f000b
+	//TODO: STRW DX                         // 660f00ca
+	//TODO: STRW R11                        // 66410f00cb
+	//TODO: STRL (BX)                       // 0f000b
+	//TODO: STRL (R11)                      // 410f000b
+	//TODO: STRL DX                         // 0f00ca
+	//TODO: STRL R11                        // 410f00cb
+	//TODO: STRQ (BX)                       // 480f000b
+	//TODO: STRQ (R11)                      // 490f000b
+	//TODO: STRQ DX                         // 480f00ca
+	//TODO: STRQ R11                        // 490f00cb
+	SUBB $7, AL                             // 2c07
+	SUBW $61731, AX                         // 662d23f1
+	SUBL $4045620583, AX                    // 2d674523f1
+	SUBQ $-249346713, AX                    // 482d674523f1
+	SUBW $61731, (BX)                       // 66812b23f1
+	SUBW $61731, (R11)                      // 6641812b23f1
+	SUBW $61731, DX                         // 6681ea23f1
+	SUBW $61731, R11                        // 664181eb23f1
+	SUBW $7, (BX)                           // 66832b07
+	SUBW $7, (R11)                          // 6641832b07
+	SUBW $7, DX                             // 6683ea07
+	SUBW $7, R11                            // 664183eb07
+	SUBW DX, (BX)                           // 662913
+	SUBW R11, (BX)                          // 6644291b
+	SUBW DX, (R11)                          // 66412913
+	SUBW R11, (R11)                         // 6645291b
+	SUBW DX, DX                             // 6629d2 or 662bd2
+	SUBW R11, DX                            // 664429da or 66412bd3
+	SUBW DX, R11                            // 664129d3 or 66442bda
+	SUBW R11, R11                           // 664529db or 66452bdb
+	SUBL $4045620583, (BX)                  // 812b674523f1
+	SUBL $4045620583, (R11)                 // 41812b674523f1
+	SUBL $4045620583, DX                    // 81ea674523f1
+	SUBL $4045620583, R11                   // 4181eb674523f1
+	SUBL $7, (BX)                           // 832b07
+	SUBL $7, (R11)                          // 41832b07
+	SUBL $7, DX                             // 83ea07
+	SUBL $7, R11                            // 4183eb07
+	SUBL DX, (BX)                           // 2913
+	SUBL R11, (BX)                          // 44291b
+	SUBL DX, (R11)                          // 412913
+	SUBL R11, (R11)                         // 45291b
+	SUBL DX, DX                             // 29d2 or 2bd2
+	SUBL R11, DX                            // 4429da or 412bd3
+	SUBL DX, R11                            // 4129d3 or 442bda
+	SUBL R11, R11                           // 4529db or 452bdb
+	SUBQ $-249346713, (BX)                  // 48812b674523f1
+	SUBQ $-249346713, (R11)                 // 49812b674523f1
+	SUBQ $-249346713, DX                    // 4881ea674523f1
+	SUBQ $-249346713, R11                   // 4981eb674523f1
+	SUBQ $7, (BX)                           // 48832b07
+	SUBQ $7, (R11)                          // 49832b07
+	SUBQ $7, DX                             // 4883ea07
+	SUBQ $7, R11                            // 4983eb07
+	SUBQ DX, (BX)                           // 482913
+	SUBQ R11, (BX)                          // 4c291b
+	SUBQ DX, (R11)                          // 492913
+	SUBQ R11, (R11)                         // 4d291b
+	SUBQ DX, DX                             // 4829d2 or 482bd2
+	SUBQ R11, DX                            // 4c29da or 492bd3
+	SUBQ DX, R11                            // 4929d3 or 4c2bda
+	SUBQ R11, R11                           // 4d29db or 4d2bdb
+	SUBB $7, (BX)                           // 802b07
+	SUBB $7, (R11)                          // 41802b07
+	SUBB $7, DL                             // 80ea07
+	SUBB $7, R11                            // 4180eb07
+	SUBB DL, (BX)                           // 2813
+	SUBB R11, (BX)                          // 44281b
+	SUBB DL, (R11)                          // 412813
+	SUBB R11, (R11)                         // 45281b
+	SUBB DL, DL                             // 28d2 or 2ad2
+	SUBB R11, DL                            // 4428da or 412ad3
+	SUBB DL, R11                            // 4128d3 or 442ada
+	SUBB R11, R11                           // 4528db or 452adb
+	SUBW (BX), DX                           // 662b13
+	SUBW (R11), DX                          // 66412b13
+	SUBW (BX), R11                          // 66442b1b
+	SUBW (R11), R11                         // 66452b1b
+	SUBL (BX), DX                           // 2b13
+	SUBL (R11), DX                          // 412b13
+	SUBL (BX), R11                          // 442b1b
+	SUBL (R11), R11                         // 452b1b
+	SUBQ (BX), DX                           // 482b13
+	SUBQ (R11), DX                          // 492b13
+	SUBQ (BX), R11                          // 4c2b1b
+	SUBQ (R11), R11                         // 4d2b1b
+	SUBB (BX), DL                           // 2a13
+	SUBB (R11), DL                          // 412a13
+	SUBB (BX), R11                          // 442a1b
+	SUBB (R11), R11                         // 452a1b
+	SUBPD (BX), X2                          // 660f5c13
+	SUBPD (R11), X2                         // 66410f5c13
+	SUBPD X2, X2                            // 660f5cd2
+	SUBPD X11, X2                           // 66410f5cd3
+	SUBPD (BX), X11                         // 66440f5c1b
+	SUBPD (R11), X11                        // 66450f5c1b
+	SUBPD X2, X11                           // 66440f5cda
+	SUBPD X11, X11                          // 66450f5cdb
+	SUBPS (BX), X2                          // 0f5c13
+	SUBPS (R11), X2                         // 410f5c13
+	SUBPS X2, X2                            // 0f5cd2
+	SUBPS X11, X2                           // 410f5cd3
+	SUBPS (BX), X11                         // 440f5c1b
+	SUBPS (R11), X11                        // 450f5c1b
+	SUBPS X2, X11                           // 440f5cda
+	SUBPS X11, X11                          // 450f5cdb
+	SUBSD (BX), X2                          // f20f5c13
+	SUBSD (R11), X2                         // f2410f5c13
+	SUBSD X2, X2                            // f20f5cd2
+	SUBSD X11, X2                           // f2410f5cd3
+	SUBSD (BX), X11                         // f2440f5c1b
+	SUBSD (R11), X11                        // f2450f5c1b
+	SUBSD X2, X11                           // f2440f5cda
+	SUBSD X11, X11                          // f2450f5cdb
+	SUBSS (BX), X2                          // f30f5c13
+	SUBSS (R11), X2                         // f3410f5c13
+	SUBSS X2, X2                            // f30f5cd2
+	SUBSS X11, X2                           // f3410f5cd3
+	SUBSS (BX), X11                         // f3440f5c1b
+	SUBSS (R11), X11                        // f3450f5c1b
+	SUBSS X2, X11                           // f3440f5cda
+	SUBSS X11, X11                          // f3450f5cdb
+	SWAPGS                                  // 0f01f8
+	SYSCALL                                 // 0f05
+	//TODO: SYSENTER                        // 0f34
+	//TODO: SYSEXIT                         // 0f35
+	SYSRET                                  // 0f07
+	TESTB $7, AL                            // a807
+	TESTW $61731, AX                        // 66a923f1
+	TESTL $4045620583, AX                   // a9674523f1
+	TESTQ $-249346713, AX                   // 48a9674523f1
+	TESTW $61731, (BX)                      // 66f70323f1
+	TESTW $61731, (R11)                     // 6641f70323f1
+	TESTW $61731, DX                        // 66f7c223f1
+	TESTW $61731, R11                       // 6641f7c323f1
+	TESTW DX, (BX)                          // 668513
+	TESTW R11, (BX)                         // 6644851b
+	TESTW DX, (R11)                         // 66418513
+	TESTW R11, (R11)                        // 6645851b
+	TESTW DX, DX                            // 6685d2
+	TESTW R11, DX                           // 664485da
+	TESTW DX, R11                           // 664185d3
+	TESTW R11, R11                          // 664585db
+	TESTL $4045620583, (BX)                 // f703674523f1
+	TESTL $4045620583, (R11)                // 41f703674523f1
+	TESTL $4045620583, DX                   // f7c2674523f1
+	TESTL $4045620583, R11                  // 41f7c3674523f1
+	TESTL DX, (BX)                          // 8513
+	TESTL R11, (BX)                         // 44851b
+	TESTL DX, (R11)                         // 418513
+	TESTL R11, (R11)                        // 45851b
+	TESTL DX, DX                            // 85d2
+	TESTL R11, DX                           // 4485da
+	TESTL DX, R11                           // 4185d3
+	TESTL R11, R11                          // 4585db
+	TESTQ $-249346713, (BX)                 // 48f703674523f1
+	TESTQ $-249346713, (R11)                // 49f703674523f1
+	TESTQ $-249346713, DX                   // 48f7c2674523f1
+	TESTQ $-249346713, R11                  // 49f7c3674523f1
+	TESTQ DX, (BX)                          // 488513
+	TESTQ R11, (BX)                         // 4c851b
+	TESTQ DX, (R11)                         // 498513
+	TESTQ R11, (R11)                        // 4d851b
+	TESTQ DX, DX                            // 4885d2
+	TESTQ R11, DX                           // 4c85da
+	TESTQ DX, R11                           // 4985d3
+	TESTQ R11, R11                          // 4d85db
+	TESTB $7, (BX)                          // f60307
+	TESTB $7, (R11)                         // 41f60307
+	TESTB $7, DL                            // f6c207
+	TESTB $7, R11                           // 41f6c307
+	TESTB DL, (BX)                          // 8413
+	TESTB R11, (BX)                         // 44841b
+	TESTB DL, (R11)                         // 418413
+	TESTB R11, (R11)                        // 45841b
+	TESTB DL, DL                            // 84d2
+	TESTB R11, DL                           // 4484da
+	TESTB DL, R11                           // 4184d3
+	TESTB R11, R11                          // 4584db
+	//TODO: TZCNTW (BX), DX                 // 66f30fbc13
+	//TODO: TZCNTW (R11), DX                // 66f3410fbc13
+	//TODO: TZCNTW DX, DX                   // 66f30fbcd2
+	//TODO: TZCNTW R11, DX                  // 66f3410fbcd3
+	//TODO: TZCNTW (BX), R11                // 66f3440fbc1b
+	//TODO: TZCNTW (R11), R11               // 66f3450fbc1b
+	//TODO: TZCNTW DX, R11                  // 66f3440fbcda
+	//TODO: TZCNTW R11, R11                 // 66f3450fbcdb
+	//TODO: TZCNTL (BX), DX                 // f30fbc13
+	//TODO: TZCNTL (R11), DX                // f3410fbc13
+	//TODO: TZCNTL DX, DX                   // f30fbcd2
+	//TODO: TZCNTL R11, DX                  // f3410fbcd3
+	//TODO: TZCNTL (BX), R11                // f3440fbc1b
+	//TODO: TZCNTL (R11), R11               // f3450fbc1b
+	//TODO: TZCNTL DX, R11                  // f3440fbcda
+	//TODO: TZCNTL R11, R11                 // f3450fbcdb
+	//TODO: TZCNTQ (BX), DX                 // f3480fbc13
+	//TODO: TZCNTQ (R11), DX                // f3490fbc13
+	//TODO: TZCNTQ DX, DX                   // f3480fbcd2
+	//TODO: TZCNTQ R11, DX                  // f3490fbcd3
+	//TODO: TZCNTQ (BX), R11                // f34c0fbc1b
+	//TODO: TZCNTQ (R11), R11               // f34d0fbc1b
+	//TODO: TZCNTQ DX, R11                  // f34c0fbcda
+	//TODO: TZCNTQ R11, R11                 // f34d0fbcdb
+	UCOMISD (BX), X2                        // 660f2e13
+	UCOMISD (R11), X2                       // 66410f2e13
+	UCOMISD X2, X2                          // 660f2ed2
+	UCOMISD X11, X2                         // 66410f2ed3
+	UCOMISD (BX), X11                       // 66440f2e1b
+	UCOMISD (R11), X11                      // 66450f2e1b
+	UCOMISD X2, X11                         // 66440f2eda
+	UCOMISD X11, X11                        // 66450f2edb
+	UCOMISS (BX), X2                        // 0f2e13
+	UCOMISS (R11), X2                       // 410f2e13
+	UCOMISS X2, X2                          // 0f2ed2
+	UCOMISS X11, X2                         // 410f2ed3
+	UCOMISS (BX), X11                       // 440f2e1b
+	UCOMISS (R11), X11                      // 450f2e1b
+	UCOMISS X2, X11                         // 440f2eda
+	UCOMISS X11, X11                        // 450f2edb
+	//TODO: UD1                             // 0fb9
+	//TODO: UD2                             // 0f0b
+	UNPCKHPD (BX), X2                       // 660f1513
+	UNPCKHPD (R11), X2                      // 66410f1513
+	UNPCKHPD X2, X2                         // 660f15d2
+	UNPCKHPD X11, X2                        // 66410f15d3
+	UNPCKHPD (BX), X11                      // 66440f151b
+	UNPCKHPD (R11), X11                     // 66450f151b
+	UNPCKHPD X2, X11                        // 66440f15da
+	UNPCKHPD X11, X11                       // 66450f15db
+	UNPCKHPS (BX), X2                       // 0f1513
+	UNPCKHPS (R11), X2                      // 410f1513
+	UNPCKHPS X2, X2                         // 0f15d2
+	UNPCKHPS X11, X2                        // 410f15d3
+	UNPCKHPS (BX), X11                      // 440f151b
+	UNPCKHPS (R11), X11                     // 450f151b
+	UNPCKHPS X2, X11                        // 440f15da
+	UNPCKHPS X11, X11                       // 450f15db
+	UNPCKLPD (BX), X2                       // 660f1413
+	UNPCKLPD (R11), X2                      // 66410f1413
+	UNPCKLPD X2, X2                         // 660f14d2
+	UNPCKLPD X11, X2                        // 66410f14d3
+	UNPCKLPD (BX), X11                      // 66440f141b
+	UNPCKLPD (R11), X11                     // 66450f141b
+	UNPCKLPD X2, X11                        // 66440f14da
+	UNPCKLPD X11, X11                       // 66450f14db
+	UNPCKLPS (BX), X2                       // 0f1413
+	UNPCKLPS (R11), X2                      // 410f1413
+	UNPCKLPS X2, X2                         // 0f14d2
+	UNPCKLPS X11, X2                        // 410f14d3
+	UNPCKLPS (BX), X11                      // 440f141b
+	UNPCKLPS (R11), X11                     // 450f141b
+	UNPCKLPS X2, X11                        // 440f14da
+	UNPCKLPS X11, X11                       // 450f14db
+	//TODO: VADDPD (BX), X9, X2             // c4e1315813 or c5b15813
+	//TODO: VADDPD (R11), X9, X2            // c4c1315813
+	//TODO: VADDPD X2, X9, X2               // c4e13158d2 or c5b158d2
+	//TODO: VADDPD X11, X9, X2              // c4c13158d3
+	//TODO: VADDPD (BX), X9, X11            // c46131581b or c531581b
+	//TODO: VADDPD (R11), X9, X11           // c44131581b
+	//TODO: VADDPD X2, X9, X11              // c4613158da or c53158da
+	//TODO: VADDPD X11, X9, X11             // c4413158db
+	//TODO: VADDPD (BX), Y15, Y2            // c4e1055813 or c5855813
+	//TODO: VADDPD (R11), Y15, Y2           // c4c1055813
+	//TODO: VADDPD Y2, Y15, Y2              // c4e10558d2 or c58558d2
+	//TODO: VADDPD Y11, Y15, Y2             // c4c10558d3
+	//TODO: VADDPD (BX), Y15, Y11           // c46105581b or c505581b
+	//TODO: VADDPD (R11), Y15, Y11          // c44105581b
+	//TODO: VADDPD Y2, Y15, Y11             // c4610558da or c50558da
+	//TODO: VADDPD Y11, Y15, Y11            // c4410558db
+	//TODO: VADDPS (BX), X9, X2             // c4e1305813 or c5b05813
+	//TODO: VADDPS (R11), X9, X2            // c4c1305813
+	//TODO: VADDPS X2, X9, X2               // c4e13058d2 or c5b058d2
+	//TODO: VADDPS X11, X9, X2              // c4c13058d3
+	//TODO: VADDPS (BX), X9, X11            // c46130581b or c530581b
+	//TODO: VADDPS (R11), X9, X11           // c44130581b
+	//TODO: VADDPS X2, X9, X11              // c4613058da or c53058da
+	//TODO: VADDPS X11, X9, X11             // c4413058db
+	//TODO: VADDPS (BX), Y15, Y2            // c4e1045813 or c5845813
+	//TODO: VADDPS (R11), Y15, Y2           // c4c1045813
+	//TODO: VADDPS Y2, Y15, Y2              // c4e10458d2 or c58458d2
+	//TODO: VADDPS Y11, Y15, Y2             // c4c10458d3
+	//TODO: VADDPS (BX), Y15, Y11           // c46104581b or c504581b
+	//TODO: VADDPS (R11), Y15, Y11          // c44104581b
+	//TODO: VADDPS Y2, Y15, Y11             // c4610458da or c50458da
+	//TODO: VADDPS Y11, Y15, Y11            // c4410458db
+	//TODO: VADDSD (BX), X9, X2             // c4e1335813 or c5b35813
+	//TODO: VADDSD (R11), X9, X2            // c4c1335813
+	//TODO: VADDSD X2, X9, X2               // c4e13358d2 or c5b358d2
+	//TODO: VADDSD X11, X9, X2              // c4c13358d3
+	//TODO: VADDSD (BX), X9, X11            // c46133581b or c533581b
+	//TODO: VADDSD (R11), X9, X11           // c44133581b
+	//TODO: VADDSD X2, X9, X11              // c4613358da or c53358da
+	//TODO: VADDSD X11, X9, X11             // c4413358db
+	//TODO: VADDSS (BX), X9, X2             // c4e1325813 or c5b25813
+	//TODO: VADDSS (R11), X9, X2            // c4c1325813
+	//TODO: VADDSS X2, X9, X2               // c4e13258d2 or c5b258d2
+	//TODO: VADDSS X11, X9, X2              // c4c13258d3
+	//TODO: VADDSS (BX), X9, X11            // c46132581b or c532581b
+	//TODO: VADDSS (R11), X9, X11           // c44132581b
+	//TODO: VADDSS X2, X9, X11              // c4613258da or c53258da
+	//TODO: VADDSS X11, X9, X11             // c4413258db
+	//TODO: VADDSUBPD (BX), X9, X2          // c4e131d013 or c5b1d013
+	//TODO: VADDSUBPD (R11), X9, X2         // c4c131d013
+	//TODO: VADDSUBPD X2, X9, X2            // c4e131d0d2 or c5b1d0d2
+	//TODO: VADDSUBPD X11, X9, X2           // c4c131d0d3
+	//TODO: VADDSUBPD (BX), X9, X11         // c46131d01b or c531d01b
+	//TODO: VADDSUBPD (R11), X9, X11        // c44131d01b
+	//TODO: VADDSUBPD X2, X9, X11           // c46131d0da or c531d0da
+	//TODO: VADDSUBPD X11, X9, X11          // c44131d0db
+	//TODO: VADDSUBPD (BX), Y15, Y2         // c4e105d013 or c585d013
+	//TODO: VADDSUBPD (R11), Y15, Y2        // c4c105d013
+	//TODO: VADDSUBPD Y2, Y15, Y2           // c4e105d0d2 or c585d0d2
+	//TODO: VADDSUBPD Y11, Y15, Y2          // c4c105d0d3
+	//TODO: VADDSUBPD (BX), Y15, Y11        // c46105d01b or c505d01b
+	//TODO: VADDSUBPD (R11), Y15, Y11       // c44105d01b
+	//TODO: VADDSUBPD Y2, Y15, Y11          // c46105d0da or c505d0da
+	//TODO: VADDSUBPD Y11, Y15, Y11         // c44105d0db
+	//TODO: VADDSUBPS (BX), X9, X2          // c4e133d013 or c5b3d013
+	//TODO: VADDSUBPS (R11), X9, X2         // c4c133d013
+	//TODO: VADDSUBPS X2, X9, X2            // c4e133d0d2 or c5b3d0d2
+	//TODO: VADDSUBPS X11, X9, X2           // c4c133d0d3
+	//TODO: VADDSUBPS (BX), X9, X11         // c46133d01b or c533d01b
+	//TODO: VADDSUBPS (R11), X9, X11        // c44133d01b
+	//TODO: VADDSUBPS X2, X9, X11           // c46133d0da or c533d0da
+	//TODO: VADDSUBPS X11, X9, X11          // c44133d0db
+	//TODO: VADDSUBPS (BX), Y15, Y2         // c4e107d013 or c587d013
+	//TODO: VADDSUBPS (R11), Y15, Y2        // c4c107d013
+	//TODO: VADDSUBPS Y2, Y15, Y2           // c4e107d0d2 or c587d0d2
+	//TODO: VADDSUBPS Y11, Y15, Y2          // c4c107d0d3
+	//TODO: VADDSUBPS (BX), Y15, Y11        // c46107d01b or c507d01b
+	//TODO: VADDSUBPS (R11), Y15, Y11       // c44107d01b
+	//TODO: VADDSUBPS Y2, Y15, Y11          // c46107d0da or c507d0da
+	//TODO: VADDSUBPS Y11, Y15, Y11         // c44107d0db
+	//TODO: VAESDEC (BX), X9, X2            // c4e231de13
+	//TODO: VAESDEC (R11), X9, X2           // c4c231de13
+	//TODO: VAESDEC X2, X9, X2              // c4e231ded2
+	//TODO: VAESDEC X11, X9, X2             // c4c231ded3
+	//TODO: VAESDEC (BX), X9, X11           // c46231de1b
+	//TODO: VAESDEC (R11), X9, X11          // c44231de1b
+	//TODO: VAESDEC X2, X9, X11             // c46231deda
+	//TODO: VAESDEC X11, X9, X11            // c44231dedb
+	//TODO: VAESDECLAST (BX), X9, X2        // c4e231df13
+	//TODO: VAESDECLAST (R11), X9, X2       // c4c231df13
+	//TODO: VAESDECLAST X2, X9, X2          // c4e231dfd2
+	//TODO: VAESDECLAST X11, X9, X2         // c4c231dfd3
+	//TODO: VAESDECLAST (BX), X9, X11       // c46231df1b
+	//TODO: VAESDECLAST (R11), X9, X11      // c44231df1b
+	//TODO: VAESDECLAST X2, X9, X11         // c46231dfda
+	//TODO: VAESDECLAST X11, X9, X11        // c44231dfdb
+	//TODO: VAESENC (BX), X9, X2            // c4e231dc13
+	//TODO: VAESENC (R11), X9, X2           // c4c231dc13
+	//TODO: VAESENC X2, X9, X2              // c4e231dcd2
+	//TODO: VAESENC X11, X9, X2             // c4c231dcd3
+	//TODO: VAESENC (BX), X9, X11           // c46231dc1b
+	//TODO: VAESENC (R11), X9, X11          // c44231dc1b
+	//TODO: VAESENC X2, X9, X11             // c46231dcda
+	//TODO: VAESENC X11, X9, X11            // c44231dcdb
+	//TODO: VAESENCLAST (BX), X9, X2        // c4e231dd13
+	//TODO: VAESENCLAST (R11), X9, X2       // c4c231dd13
+	//TODO: VAESENCLAST X2, X9, X2          // c4e231ddd2
+	//TODO: VAESENCLAST X11, X9, X2         // c4c231ddd3
+	//TODO: VAESENCLAST (BX), X9, X11       // c46231dd1b
+	//TODO: VAESENCLAST (R11), X9, X11      // c44231dd1b
+	//TODO: VAESENCLAST X2, X9, X11         // c46231ddda
+	//TODO: VAESENCLAST X11, X9, X11        // c44231dddb
+	//TODO: VAESIMC (BX), X2                // c4e279db13
+	//TODO: VAESIMC (R11), X2               // c4c279db13
+	//TODO: VAESIMC X2, X2                  // c4e279dbd2
+	//TODO: VAESIMC X11, X2                 // c4c279dbd3
+	//TODO: VAESIMC (BX), X11               // c46279db1b
+	//TODO: VAESIMC (R11), X11              // c44279db1b
+	//TODO: VAESIMC X2, X11                 // c46279dbda
+	//TODO: VAESIMC X11, X11                // c44279dbdb
+	//TODO: VAESKEYGENASSIST $7, (BX), X2   // c4e379df1307
+	//TODO: VAESKEYGENASSIST $7, (R11), X2  // c4c379df1307
+	//TODO: VAESKEYGENASSIST $7, X2, X2     // c4e379dfd207
+	//TODO: VAESKEYGENASSIST $7, X11, X2    // c4c379dfd307
+	//TODO: VAESKEYGENASSIST $7, (BX), X11  // c46379df1b07
+	//TODO: VAESKEYGENASSIST $7, (R11), X11 // c44379df1b07
+	//TODO: VAESKEYGENASSIST $7, X2, X11    // c46379dfda07
+	//TODO: VAESKEYGENASSIST $7, X11, X11   // c44379dfdb07
+	//TODO: VANDNPD (BX), X9, X2            // c4e1315513 or c5b15513
+	//TODO: VANDNPD (R11), X9, X2           // c4c1315513
+	//TODO: VANDNPD X2, X9, X2              // c4e13155d2 or c5b155d2
+	//TODO: VANDNPD X11, X9, X2             // c4c13155d3
+	//TODO: VANDNPD (BX), X9, X11           // c46131551b or c531551b
+	//TODO: VANDNPD (R11), X9, X11          // c44131551b
+	//TODO: VANDNPD X2, X9, X11             // c4613155da or c53155da
+	//TODO: VANDNPD X11, X9, X11            // c4413155db
+	//TODO: VANDNPD (BX), Y15, Y2           // c4e1055513 or c5855513
+	//TODO: VANDNPD (R11), Y15, Y2          // c4c1055513
+	//TODO: VANDNPD Y2, Y15, Y2             // c4e10555d2 or c58555d2
+	//TODO: VANDNPD Y11, Y15, Y2            // c4c10555d3
+	//TODO: VANDNPD (BX), Y15, Y11          // c46105551b or c505551b
+	//TODO: VANDNPD (R11), Y15, Y11         // c44105551b
+	//TODO: VANDNPD Y2, Y15, Y11            // c4610555da or c50555da
+	//TODO: VANDNPD Y11, Y15, Y11           // c4410555db
+	//TODO: VANDNPS (BX), X9, X2            // c4e1305513 or c5b05513
+	//TODO: VANDNPS (R11), X9, X2           // c4c1305513
+	//TODO: VANDNPS X2, X9, X2              // c4e13055d2 or c5b055d2
+	//TODO: VANDNPS X11, X9, X2             // c4c13055d3
+	//TODO: VANDNPS (BX), X9, X11           // c46130551b or c530551b
+	//TODO: VANDNPS (R11), X9, X11          // c44130551b
+	//TODO: VANDNPS X2, X9, X11             // c4613055da or c53055da
+	//TODO: VANDNPS X11, X9, X11            // c4413055db
+	//TODO: VANDNPS (BX), Y15, Y2           // c4e1045513 or c5845513
+	//TODO: VANDNPS (R11), Y15, Y2          // c4c1045513
+	//TODO: VANDNPS Y2, Y15, Y2             // c4e10455d2 or c58455d2
+	//TODO: VANDNPS Y11, Y15, Y2            // c4c10455d3
+	//TODO: VANDNPS (BX), Y15, Y11          // c46104551b or c504551b
+	//TODO: VANDNPS (R11), Y15, Y11         // c44104551b
+	//TODO: VANDNPS Y2, Y15, Y11            // c4610455da or c50455da
+	//TODO: VANDNPS Y11, Y15, Y11           // c4410455db
+	//TODO: VANDPD (BX), X9, X2             // c4e1315413 or c5b15413
+	//TODO: VANDPD (R11), X9, X2            // c4c1315413
+	//TODO: VANDPD X2, X9, X2               // c4e13154d2 or c5b154d2
+	//TODO: VANDPD X11, X9, X2              // c4c13154d3
+	//TODO: VANDPD (BX), X9, X11            // c46131541b or c531541b
+	//TODO: VANDPD (R11), X9, X11           // c44131541b
+	//TODO: VANDPD X2, X9, X11              // c4613154da or c53154da
+	//TODO: VANDPD X11, X9, X11             // c4413154db
+	//TODO: VANDPD (BX), Y15, Y2            // c4e1055413 or c5855413
+	//TODO: VANDPD (R11), Y15, Y2           // c4c1055413
+	//TODO: VANDPD Y2, Y15, Y2              // c4e10554d2 or c58554d2
+	//TODO: VANDPD Y11, Y15, Y2             // c4c10554d3
+	//TODO: VANDPD (BX), Y15, Y11           // c46105541b or c505541b
+	//TODO: VANDPD (R11), Y15, Y11          // c44105541b
+	//TODO: VANDPD Y2, Y15, Y11             // c4610554da or c50554da
+	//TODO: VANDPD Y11, Y15, Y11            // c4410554db
+	//TODO: VANDPS (BX), X9, X2             // c4e1305413 or c5b05413
+	//TODO: VANDPS (R11), X9, X2            // c4c1305413
+	//TODO: VANDPS X2, X9, X2               // c4e13054d2 or c5b054d2
+	//TODO: VANDPS X11, X9, X2              // c4c13054d3
+	//TODO: VANDPS (BX), X9, X11            // c46130541b or c530541b
+	//TODO: VANDPS (R11), X9, X11           // c44130541b
+	//TODO: VANDPS X2, X9, X11              // c4613054da or c53054da
+	//TODO: VANDPS X11, X9, X11             // c4413054db
+	//TODO: VANDPS (BX), Y15, Y2            // c4e1045413 or c5845413
+	//TODO: VANDPS (R11), Y15, Y2           // c4c1045413
+	//TODO: VANDPS Y2, Y15, Y2              // c4e10454d2 or c58454d2
+	//TODO: VANDPS Y11, Y15, Y2             // c4c10454d3
+	//TODO: VANDPS (BX), Y15, Y11           // c46104541b or c504541b
+	//TODO: VANDPS (R11), Y15, Y11          // c44104541b
+	//TODO: VANDPS Y2, Y15, Y11             // c4610454da or c50454da
+	//TODO: VANDPS Y11, Y15, Y11            // c4410454db
+	//TODO: VBLENDPD $7, (BX), X9, X2       // c4e3310d1307
+	//TODO: VBLENDPD $7, (R11), X9, X2      // c4c3310d1307
+	//TODO: VBLENDPD $7, X2, X9, X2         // c4e3310dd207
+	//TODO: VBLENDPD $7, X11, X9, X2        // c4c3310dd307
+	//TODO: VBLENDPD $7, (BX), X9, X11      // c463310d1b07
+	//TODO: VBLENDPD $7, (R11), X9, X11     // c443310d1b07
+	//TODO: VBLENDPD $7, X2, X9, X11        // c463310dda07
+	//TODO: VBLENDPD $7, X11, X9, X11       // c443310ddb07
+	//TODO: VBLENDPD $7, (BX), Y15, Y2      // c4e3050d1307
+	//TODO: VBLENDPD $7, (R11), Y15, Y2     // c4c3050d1307
+	//TODO: VBLENDPD $7, Y2, Y15, Y2        // c4e3050dd207
+	//TODO: VBLENDPD $7, Y11, Y15, Y2       // c4c3050dd307
+	//TODO: VBLENDPD $7, (BX), Y15, Y11     // c463050d1b07
+	//TODO: VBLENDPD $7, (R11), Y15, Y11    // c443050d1b07
+	//TODO: VBLENDPD $7, Y2, Y15, Y11       // c463050dda07
+	//TODO: VBLENDPD $7, Y11, Y15, Y11      // c443050ddb07
+	//TODO: VBLENDPS $7, (BX), X9, X2       // c4e3310c1307
+	//TODO: VBLENDPS $7, (R11), X9, X2      // c4c3310c1307
+	//TODO: VBLENDPS $7, X2, X9, X2         // c4e3310cd207
+	//TODO: VBLENDPS $7, X11, X9, X2        // c4c3310cd307
+	//TODO: VBLENDPS $7, (BX), X9, X11      // c463310c1b07
+	//TODO: VBLENDPS $7, (R11), X9, X11     // c443310c1b07
+	//TODO: VBLENDPS $7, X2, X9, X11        // c463310cda07
+	//TODO: VBLENDPS $7, X11, X9, X11       // c443310cdb07
+	//TODO: VBLENDPS $7, (BX), Y15, Y2      // c4e3050c1307
+	//TODO: VBLENDPS $7, (R11), Y15, Y2     // c4c3050c1307
+	//TODO: VBLENDPS $7, Y2, Y15, Y2        // c4e3050cd207
+	//TODO: VBLENDPS $7, Y11, Y15, Y2       // c4c3050cd307
+	//TODO: VBLENDPS $7, (BX), Y15, Y11     // c463050c1b07
+	//TODO: VBLENDPS $7, (R11), Y15, Y11    // c443050c1b07
+	//TODO: VBLENDPS $7, Y2, Y15, Y11       // c463050cda07
+	//TODO: VBLENDPS $7, Y11, Y15, Y11      // c443050cdb07
+	//TODO: VBLENDVPD XMM12, (BX), X9, X2   // c4e3314b13c0
+	//TODO: VBLENDVPD XMM12, (R11), X9, X2  // c4c3314b13c0
+	//TODO: VBLENDVPD XMM12, X2, X9, X2     // c4e3314bd2c0
+	//TODO: VBLENDVPD XMM12, X11, X9, X2    // c4c3314bd3c0
+	//TODO: VBLENDVPD XMM12, (BX), X9, X11  // c463314b1bc0
+	//TODO: VBLENDVPD XMM12, (R11), X9, X11 // c443314b1bc0
+	//TODO: VBLENDVPD XMM12, X2, X9, X11    // c463314bdac0
+	//TODO: VBLENDVPD XMM12, X11, X9, X11   // c443314bdbc0
+	//TODO: VBLENDVPD YMM13, (BX), Y15, Y2  // c4e3054b13d0
+	//TODO: VBLENDVPD YMM13, (R11), Y15, Y2 // c4c3054b13d0
+	//TODO: VBLENDVPD YMM13, Y2, Y15, Y2    // c4e3054bd2d0
+	//TODO: VBLENDVPD YMM13, Y11, Y15, Y2   // c4c3054bd3d0
+	//TODO: VBLENDVPD YMM13, (BX), Y15, Y11 // c463054b1bd0
+	//TODO: VBLENDVPD YMM13, (R11), Y15, Y11 // c443054b1bd0
+	//TODO: VBLENDVPD YMM13, Y2, Y15, Y11   // c463054bdad0
+	//TODO: VBLENDVPD YMM13, Y11, Y15, Y11  // c443054bdbd0
+	//TODO: VBLENDVPS XMM12, (BX), X9, X2   // c4e3314a13c0
+	//TODO: VBLENDVPS XMM12, (R11), X9, X2  // c4c3314a13c0
+	//TODO: VBLENDVPS XMM12, X2, X9, X2     // c4e3314ad2c0
+	//TODO: VBLENDVPS XMM12, X11, X9, X2    // c4c3314ad3c0
+	//TODO: VBLENDVPS XMM12, (BX), X9, X11  // c463314a1bc0
+	//TODO: VBLENDVPS XMM12, (R11), X9, X11 // c443314a1bc0
+	//TODO: VBLENDVPS XMM12, X2, X9, X11    // c463314adac0
+	//TODO: VBLENDVPS XMM12, X11, X9, X11   // c443314adbc0
+	//TODO: VBLENDVPS YMM13, (BX), Y15, Y2  // c4e3054a13d0
+	//TODO: VBLENDVPS YMM13, (R11), Y15, Y2 // c4c3054a13d0
+	//TODO: VBLENDVPS YMM13, Y2, Y15, Y2    // c4e3054ad2d0
+	//TODO: VBLENDVPS YMM13, Y11, Y15, Y2   // c4c3054ad3d0
+	//TODO: VBLENDVPS YMM13, (BX), Y15, Y11 // c463054a1bd0
+	//TODO: VBLENDVPS YMM13, (R11), Y15, Y11 // c443054a1bd0
+	//TODO: VBLENDVPS YMM13, Y2, Y15, Y11   // c463054adad0
+	//TODO: VBLENDVPS YMM13, Y11, Y15, Y11  // c443054adbd0
+	//TODO: VBROADCASTF128 (BX), Y2         // c4e27d1a13
+	//TODO: VBROADCASTF128 (R11), Y2        // c4c27d1a13
+	//TODO: VBROADCASTF128 (BX), Y11        // c4627d1a1b
+	//TODO: VBROADCASTF128 (R11), Y11       // c4427d1a1b
+	//TODO: VBROADCASTI128 (BX), Y2         // c4e27d5a13
+	//TODO: VBROADCASTI128 (R11), Y2        // c4c27d5a13
+	//TODO: VBROADCASTI128 (BX), Y11        // c4627d5a1b
+	//TODO: VBROADCASTI128 (R11), Y11       // c4427d5a1b
+	//TODO: VBROADCASTSD (BX), Y2           // c4e27d1913
+	//TODO: VBROADCASTSD (R11), Y2          // c4c27d1913
+	//TODO: VBROADCASTSD (BX), Y11          // c4627d191b
+	//TODO: VBROADCASTSD (R11), Y11         // c4427d191b
+	//TODO: VBROADCASTSD X2, Y2             // c4e27d19d2
+	//TODO: VBROADCASTSD X11, Y2            // c4c27d19d3
+	//TODO: VBROADCASTSD X2, Y11            // c4627d19da
+	//TODO: VBROADCASTSD X11, Y11           // c4427d19db
+	//TODO: VBROADCASTSS (BX), X2           // c4e2791813
+	//TODO: VBROADCASTSS (R11), X2          // c4c2791813
+	//TODO: VBROADCASTSS (BX), X11          // c46279181b
+	//TODO: VBROADCASTSS (R11), X11         // c44279181b
+	//TODO: VBROADCASTSS X2, X2             // c4e27918d2
+	//TODO: VBROADCASTSS X11, X2            // c4c27918d3
+	//TODO: VBROADCASTSS X2, X11            // c4627918da
+	//TODO: VBROADCASTSS X11, X11           // c4427918db
+	//TODO: VBROADCASTSS (BX), Y2           // c4e27d1813
+	//TODO: VBROADCASTSS (R11), Y2          // c4c27d1813
+	//TODO: VBROADCASTSS (BX), Y11          // c4627d181b
+	//TODO: VBROADCASTSS (R11), Y11         // c4427d181b
+	//TODO: VBROADCASTSS X2, Y2             // c4e27d18d2
+	//TODO: VBROADCASTSS X11, Y2            // c4c27d18d3
+	//TODO: VBROADCASTSS X2, Y11            // c4627d18da
+	//TODO: VBROADCASTSS X11, Y11           // c4427d18db
+	//TODO: VCMPPD $7, (BX), X9, X2         // c4e131c21307 or c5b1c21307
+	//TODO: VCMPPD $7, (R11), X9, X2        // c4c131c21307
+	//TODO: VCMPPD $7, X2, X9, X2           // c4e131c2d207 or c5b1c2d207
+	//TODO: VCMPPD $7, X11, X9, X2          // c4c131c2d307
+	//TODO: VCMPPD $7, (BX), X9, X11        // c46131c21b07 or c531c21b07
+	//TODO: VCMPPD $7, (R11), X9, X11       // c44131c21b07
+	//TODO: VCMPPD $7, X2, X9, X11          // c46131c2da07 or c531c2da07
+	//TODO: VCMPPD $7, X11, X9, X11         // c44131c2db07
+	//TODO: VCMPPD $7, (BX), Y15, Y2        // c4e105c21307 or c585c21307
+	//TODO: VCMPPD $7, (R11), Y15, Y2       // c4c105c21307
+	//TODO: VCMPPD $7, Y2, Y15, Y2          // c4e105c2d207 or c585c2d207
+	//TODO: VCMPPD $7, Y11, Y15, Y2         // c4c105c2d307
+	//TODO: VCMPPD $7, (BX), Y15, Y11       // c46105c21b07 or c505c21b07
+	//TODO: VCMPPD $7, (R11), Y15, Y11      // c44105c21b07
+	//TODO: VCMPPD $7, Y2, Y15, Y11         // c46105c2da07 or c505c2da07
+	//TODO: VCMPPD $7, Y11, Y15, Y11        // c44105c2db07
+	//TODO: VCMPPS $7, (BX), X9, X2         // c4e130c21307 or c5b0c21307
+	//TODO: VCMPPS $7, (R11), X9, X2        // c4c130c21307
+	//TODO: VCMPPS $7, X2, X9, X2           // c4e130c2d207 or c5b0c2d207
+	//TODO: VCMPPS $7, X11, X9, X2          // c4c130c2d307
+	//TODO: VCMPPS $7, (BX), X9, X11        // c46130c21b07 or c530c21b07
+	//TODO: VCMPPS $7, (R11), X9, X11       // c44130c21b07
+	//TODO: VCMPPS $7, X2, X9, X11          // c46130c2da07 or c530c2da07
+	//TODO: VCMPPS $7, X11, X9, X11         // c44130c2db07
+	//TODO: VCMPPS $7, (BX), Y15, Y2        // c4e104c21307 or c584c21307
+	//TODO: VCMPPS $7, (R11), Y15, Y2       // c4c104c21307
+	//TODO: VCMPPS $7, Y2, Y15, Y2          // c4e104c2d207 or c584c2d207
+	//TODO: VCMPPS $7, Y11, Y15, Y2         // c4c104c2d307
+	//TODO: VCMPPS $7, (BX), Y15, Y11       // c46104c21b07 or c504c21b07
+	//TODO: VCMPPS $7, (R11), Y15, Y11      // c44104c21b07
+	//TODO: VCMPPS $7, Y2, Y15, Y11         // c46104c2da07 or c504c2da07
+	//TODO: VCMPPS $7, Y11, Y15, Y11        // c44104c2db07
+	//TODO: VCMPSD $7, (BX), X9, X2         // c4e133c21307 or c5b3c21307
+	//TODO: VCMPSD $7, (R11), X9, X2        // c4c133c21307
+	//TODO: VCMPSD $7, X2, X9, X2           // c4e133c2d207 or c5b3c2d207
+	//TODO: VCMPSD $7, X11, X9, X2          // c4c133c2d307
+	//TODO: VCMPSD $7, (BX), X9, X11        // c46133c21b07 or c533c21b07
+	//TODO: VCMPSD $7, (R11), X9, X11       // c44133c21b07
+	//TODO: VCMPSD $7, X2, X9, X11          // c46133c2da07 or c533c2da07
+	//TODO: VCMPSD $7, X11, X9, X11         // c44133c2db07
+	//TODO: VCMPSS $7, (BX), X9, X2         // c4e132c21307 or c5b2c21307
+	//TODO: VCMPSS $7, (R11), X9, X2        // c4c132c21307
+	//TODO: VCMPSS $7, X2, X9, X2           // c4e132c2d207 or c5b2c2d207
+	//TODO: VCMPSS $7, X11, X9, X2          // c4c132c2d307
+	//TODO: VCMPSS $7, (BX), X9, X11        // c46132c21b07 or c532c21b07
+	//TODO: VCMPSS $7, (R11), X9, X11       // c44132c21b07
+	//TODO: VCMPSS $7, X2, X9, X11          // c46132c2da07 or c532c2da07
+	//TODO: VCMPSS $7, X11, X9, X11         // c44132c2db07
+	//TODO: VCOMISD (BX), X2                // c4e1792f13 or c5f92f13
+	//TODO: VCOMISD (R11), X2               // c4c1792f13
+	//TODO: VCOMISD X2, X2                  // c4e1792fd2 or c5f92fd2
+	//TODO: VCOMISD X11, X2                 // c4c1792fd3
+	//TODO: VCOMISD (BX), X11               // c461792f1b or c5792f1b
+	//TODO: VCOMISD (R11), X11              // c441792f1b
+	//TODO: VCOMISD X2, X11                 // c461792fda or c5792fda
+	//TODO: VCOMISD X11, X11                // c441792fdb
+	//TODO: VCOMISS (BX), X2                // c4e1782f13 or c5f82f13
+	//TODO: VCOMISS (R11), X2               // c4c1782f13
+	//TODO: VCOMISS X2, X2                  // c4e1782fd2 or c5f82fd2
+	//TODO: VCOMISS X11, X2                 // c4c1782fd3
+	//TODO: VCOMISS (BX), X11               // c461782f1b or c5782f1b
+	//TODO: VCOMISS (R11), X11              // c441782f1b
+	//TODO: VCOMISS X2, X11                 // c461782fda or c5782fda
+	//TODO: VCOMISS X11, X11                // c441782fdb
+	//TODO: VCVTDQ2PD (BX), X2              // c4e17ae613 or c5fae613
+	//TODO: VCVTDQ2PD (R11), X2             // c4c17ae613
+	//TODO: VCVTDQ2PD X2, X2                // c4e17ae6d2 or c5fae6d2
+	//TODO: VCVTDQ2PD X11, X2               // c4c17ae6d3
+	//TODO: VCVTDQ2PD (BX), X11             // c4617ae61b or c57ae61b
+	//TODO: VCVTDQ2PD (R11), X11            // c4417ae61b
+	//TODO: VCVTDQ2PD X2, X11               // c4617ae6da or c57ae6da
+	//TODO: VCVTDQ2PD X11, X11              // c4417ae6db
+	//TODO: VCVTDQ2PD (BX), Y2              // c4e17ee613 or c5fee613
+	//TODO: VCVTDQ2PD (R11), Y2             // c4c17ee613
+	//TODO: VCVTDQ2PD X2, Y2                // c4e17ee6d2 or c5fee6d2
+	//TODO: VCVTDQ2PD X11, Y2               // c4c17ee6d3
+	//TODO: VCVTDQ2PD (BX), Y11             // c4617ee61b or c57ee61b
+	//TODO: VCVTDQ2PD (R11), Y11            // c4417ee61b
+	//TODO: VCVTDQ2PD X2, Y11               // c4617ee6da or c57ee6da
+	//TODO: VCVTDQ2PD X11, Y11              // c4417ee6db
+	//TODO: VCVTDQ2PS (BX), X2              // c4e1785b13 or c5f85b13
+	//TODO: VCVTDQ2PS (R11), X2             // c4c1785b13
+	//TODO: VCVTDQ2PS X2, X2                // c4e1785bd2 or c5f85bd2
+	//TODO: VCVTDQ2PS X11, X2               // c4c1785bd3
+	//TODO: VCVTDQ2PS (BX), X11             // c461785b1b or c5785b1b
+	//TODO: VCVTDQ2PS (R11), X11            // c441785b1b
+	//TODO: VCVTDQ2PS X2, X11               // c461785bda or c5785bda
+	//TODO: VCVTDQ2PS X11, X11              // c441785bdb
+	//TODO: VCVTDQ2PS (BX), Y2              // c4e17c5b13 or c5fc5b13
+	//TODO: VCVTDQ2PS (R11), Y2             // c4c17c5b13
+	//TODO: VCVTDQ2PS Y2, Y2                // c4e17c5bd2 or c5fc5bd2
+	//TODO: VCVTDQ2PS Y11, Y2               // c4c17c5bd3
+	//TODO: VCVTDQ2PS (BX), Y11             // c4617c5b1b or c57c5b1b
+	//TODO: VCVTDQ2PS (R11), Y11            // c4417c5b1b
+	//TODO: VCVTDQ2PS Y2, Y11               // c4617c5bda or c57c5bda
+	//TODO: VCVTDQ2PS Y11, Y11              // c4417c5bdb
+	//TODO: VCVTPD2DQX (BX), X2             // c4e17be613 or c5fbe613
+	//TODO: VCVTPD2DQX (R11), X2            // c4c17be613
+	//TODO: VCVTPD2DQX X2, X2               // c4e17be6d2 or c5fbe6d2
+	//TODO: VCVTPD2DQX X11, X2              // c4c17be6d3
+	//TODO: VCVTPD2DQX (BX), X11            // c4617be61b or c57be61b
+	//TODO: VCVTPD2DQX (R11), X11           // c4417be61b
+	//TODO: VCVTPD2DQX X2, X11              // c4617be6da or c57be6da
+	//TODO: VCVTPD2DQX X11, X11             // c4417be6db
+	//TODO: VCVTPD2DQY (BX), X2             // c4e17fe613 or c5ffe613
+	//TODO: VCVTPD2DQY (R11), X2            // c4c17fe613
+	//TODO: VCVTPD2DQY Y2, X2               // c4e17fe6d2 or c5ffe6d2
+	//TODO: VCVTPD2DQY Y11, X2              // c4c17fe6d3
+	//TODO: VCVTPD2DQY (BX), X11            // c4617fe61b or c57fe61b
+	//TODO: VCVTPD2DQY (R11), X11           // c4417fe61b
+	//TODO: VCVTPD2DQY Y2, X11              // c4617fe6da or c57fe6da
+	//TODO: VCVTPD2DQY Y11, X11             // c4417fe6db
+	//TODO: VCVTPD2PSX (BX), X2             // c4e1795a13 or c5f95a13
+	//TODO: VCVTPD2PSX (R11), X2            // c4c1795a13
+	//TODO: VCVTPD2PSX X2, X2               // c4e1795ad2 or c5f95ad2
+	//TODO: VCVTPD2PSX X11, X2              // c4c1795ad3
+	//TODO: VCVTPD2PSX (BX), X11            // c461795a1b or c5795a1b
+	//TODO: VCVTPD2PSX (R11), X11           // c441795a1b
+	//TODO: VCVTPD2PSX X2, X11              // c461795ada or c5795ada
+	//TODO: VCVTPD2PSX X11, X11             // c441795adb
+	//TODO: VCVTPD2PSY (BX), X2             // c4e17d5a13 or c5fd5a13
+	//TODO: VCVTPD2PSY (R11), X2            // c4c17d5a13
+	//TODO: VCVTPD2PSY Y2, X2               // c4e17d5ad2 or c5fd5ad2
+	//TODO: VCVTPD2PSY Y11, X2              // c4c17d5ad3
+	//TODO: VCVTPD2PSY (BX), X11            // c4617d5a1b or c57d5a1b
+	//TODO: VCVTPD2PSY (R11), X11           // c4417d5a1b
+	//TODO: VCVTPD2PSY Y2, X11              // c4617d5ada or c57d5ada
+	//TODO: VCVTPD2PSY Y11, X11             // c4417d5adb
+	//TODO: VCVTPH2PS (BX), X2              // c4e2791313
+	//TODO: VCVTPH2PS (R11), X2             // c4c2791313
+	//TODO: VCVTPH2PS X2, X2                // c4e27913d2
+	//TODO: VCVTPH2PS X11, X2               // c4c27913d3
+	//TODO: VCVTPH2PS (BX), X11             // c46279131b
+	//TODO: VCVTPH2PS (R11), X11            // c44279131b
+	//TODO: VCVTPH2PS X2, X11               // c4627913da
+	//TODO: VCVTPH2PS X11, X11              // c4427913db
+	//TODO: VCVTPH2PS (BX), Y2              // c4e27d1313
+	//TODO: VCVTPH2PS (R11), Y2             // c4c27d1313
+	//TODO: VCVTPH2PS X2, Y2                // c4e27d13d2
+	//TODO: VCVTPH2PS X11, Y2               // c4c27d13d3
+	//TODO: VCVTPH2PS (BX), Y11             // c4627d131b
+	//TODO: VCVTPH2PS (R11), Y11            // c4427d131b
+	//TODO: VCVTPH2PS X2, Y11               // c4627d13da
+	//TODO: VCVTPH2PS X11, Y11              // c4427d13db
+	//TODO: VCVTPS2DQ (BX), X2              // c4e1795b13 or c5f95b13
+	//TODO: VCVTPS2DQ (R11), X2             // c4c1795b13
+	//TODO: VCVTPS2DQ X2, X2                // c4e1795bd2 or c5f95bd2
+	//TODO: VCVTPS2DQ X11, X2               // c4c1795bd3
+	//TODO: VCVTPS2DQ (BX), X11             // c461795b1b or c5795b1b
+	//TODO: VCVTPS2DQ (R11), X11            // c441795b1b
+	//TODO: VCVTPS2DQ X2, X11               // c461795bda or c5795bda
+	//TODO: VCVTPS2DQ X11, X11              // c441795bdb
+	//TODO: VCVTPS2DQ (BX), Y2              // c4e17d5b13 or c5fd5b13
+	//TODO: VCVTPS2DQ (R11), Y2             // c4c17d5b13
+	//TODO: VCVTPS2DQ Y2, Y2                // c4e17d5bd2 or c5fd5bd2
+	//TODO: VCVTPS2DQ Y11, Y2               // c4c17d5bd3
+	//TODO: VCVTPS2DQ (BX), Y11             // c4617d5b1b or c57d5b1b
+	//TODO: VCVTPS2DQ (R11), Y11            // c4417d5b1b
+	//TODO: VCVTPS2DQ Y2, Y11               // c4617d5bda or c57d5bda
+	//TODO: VCVTPS2DQ Y11, Y11              // c4417d5bdb
+	//TODO: VCVTPS2PD (BX), X2              // c4e1785a13 or c5f85a13
+	//TODO: VCVTPS2PD (R11), X2             // c4c1785a13
+	//TODO: VCVTPS2PD X2, X2                // c4e1785ad2 or c5f85ad2
+	//TODO: VCVTPS2PD X11, X2               // c4c1785ad3
+	//TODO: VCVTPS2PD (BX), X11             // c461785a1b or c5785a1b
+	//TODO: VCVTPS2PD (R11), X11            // c441785a1b
+	//TODO: VCVTPS2PD X2, X11               // c461785ada or c5785ada
+	//TODO: VCVTPS2PD X11, X11              // c441785adb
+	//TODO: VCVTPS2PD (BX), Y2              // c4e17c5a13 or c5fc5a13
+	//TODO: VCVTPS2PD (R11), Y2             // c4c17c5a13
+	//TODO: VCVTPS2PD X2, Y2                // c4e17c5ad2 or c5fc5ad2
+	//TODO: VCVTPS2PD X11, Y2               // c4c17c5ad3
+	//TODO: VCVTPS2PD (BX), Y11             // c4617c5a1b or c57c5a1b
+	//TODO: VCVTPS2PD (R11), Y11            // c4417c5a1b
+	//TODO: VCVTPS2PD X2, Y11               // c4617c5ada or c57c5ada
+	//TODO: VCVTPS2PD X11, Y11              // c4417c5adb
+	//TODO: VCVTPS2PH $7, Y2, (BX)          // c4e37d1d1307
+	//TODO: VCVTPS2PH $7, Y11, (BX)         // c4637d1d1b07
+	//TODO: VCVTPS2PH $7, Y2, (R11)         // c4c37d1d1307
+	//TODO: VCVTPS2PH $7, Y11, (R11)        // c4437d1d1b07
+	//TODO: VCVTPS2PH $7, Y2, X2            // c4e37d1dd207
+	//TODO: VCVTPS2PH $7, Y11, X2           // c4637d1dda07
+	//TODO: VCVTPS2PH $7, Y2, X11           // c4c37d1dd307
+	//TODO: VCVTPS2PH $7, Y11, X11          // c4437d1ddb07
+	//TODO: VCVTPS2PH $7, X2, (BX)          // c4e3791d1307
+	//TODO: VCVTPS2PH $7, X11, (BX)         // c463791d1b07
+	//TODO: VCVTPS2PH $7, X2, (R11)         // c4c3791d1307
+	//TODO: VCVTPS2PH $7, X11, (R11)        // c443791d1b07
+	//TODO: VCVTPS2PH $7, X2, X2            // c4e3791dd207
+	//TODO: VCVTPS2PH $7, X11, X2           // c463791dda07
+	//TODO: VCVTPS2PH $7, X2, X11           // c4c3791dd307
+	//TODO: VCVTPS2PH $7, X11, X11          // c443791ddb07
+	//TODO: VCVTSD2SI (BX), DX              // c4e17b2d13 or c5fb2d13
+	//TODO: VCVTSD2SI (R11), DX             // c4c17b2d13
+	//TODO: VCVTSD2SI X2, DX                // c4e17b2dd2 or c5fb2dd2
+	//TODO: VCVTSD2SI X11, DX               // c4c17b2dd3
+	//TODO: VCVTSD2SI (BX), R11             // c4617b2d1b or c57b2d1b
+	//TODO: VCVTSD2SI (R11), R11            // c4417b2d1b
+	//TODO: VCVTSD2SI X2, R11               // c4617b2dda or c57b2dda
+	//TODO: VCVTSD2SI X11, R11              // c4417b2ddb
+	//TODO: VCVTSD2SIQ (BX), DX             // c4e1fb2d13
+	//TODO: VCVTSD2SIQ (R11), DX            // c4c1fb2d13
+	//TODO: VCVTSD2SIQ X2, DX               // c4e1fb2dd2
+	//TODO: VCVTSD2SIQ X11, DX              // c4c1fb2dd3
+	//TODO: VCVTSD2SIQ (BX), R11            // c461fb2d1b
+	//TODO: VCVTSD2SIQ (R11), R11           // c441fb2d1b
+	//TODO: VCVTSD2SIQ X2, R11              // c461fb2dda
+	//TODO: VCVTSD2SIQ X11, R11             // c441fb2ddb
+	//TODO: VCVTSD2SS (BX), X9, X2          // c4e1335a13 or c5b35a13
+	//TODO: VCVTSD2SS (R11), X9, X2         // c4c1335a13
+	//TODO: VCVTSD2SS X2, X9, X2            // c4e1335ad2 or c5b35ad2
+	//TODO: VCVTSD2SS X11, X9, X2           // c4c1335ad3
+	//TODO: VCVTSD2SS (BX), X9, X11         // c461335a1b or c5335a1b
+	//TODO: VCVTSD2SS (R11), X9, X11        // c441335a1b
+	//TODO: VCVTSD2SS X2, X9, X11           // c461335ada or c5335ada
+	//TODO: VCVTSD2SS X11, X9, X11          // c441335adb
+	//TODO: VCVTSI2SDL (BX), X9, X2         // c4e1332a13 or c5b32a13
+	//TODO: VCVTSI2SDL (R11), X9, X2        // c4c1332a13
+	//TODO: VCVTSI2SDL DX, X9, X2           // c4e1332ad2 or c5b32ad2
+	//TODO: VCVTSI2SDL R11, X9, X2          // c4c1332ad3
+	//TODO: VCVTSI2SDL (BX), X9, X11        // c461332a1b or c5332a1b
+	//TODO: VCVTSI2SDL (R11), X9, X11       // c441332a1b
+	//TODO: VCVTSI2SDL DX, X9, X11          // c461332ada or c5332ada
+	//TODO: VCVTSI2SDL R11, X9, X11         // c441332adb
+	//TODO: VCVTSI2SDQ (BX), X9, X2         // c4e1b32a13
+	//TODO: VCVTSI2SDQ (R11), X9, X2        // c4c1b32a13
+	//TODO: VCVTSI2SDQ DX, X9, X2           // c4e1b32ad2
+	//TODO: VCVTSI2SDQ R11, X9, X2          // c4c1b32ad3
+	//TODO: VCVTSI2SDQ (BX), X9, X11        // c461b32a1b
+	//TODO: VCVTSI2SDQ (R11), X9, X11       // c441b32a1b
+	//TODO: VCVTSI2SDQ DX, X9, X11          // c461b32ada
+	//TODO: VCVTSI2SDQ R11, X9, X11         // c441b32adb
+	//TODO: VCVTSI2SSL (BX), X9, X2         // c4e1322a13 or c5b22a13
+	//TODO: VCVTSI2SSL (R11), X9, X2        // c4c1322a13
+	//TODO: VCVTSI2SSL DX, X9, X2           // c4e1322ad2 or c5b22ad2
+	//TODO: VCVTSI2SSL R11, X9, X2          // c4c1322ad3
+	//TODO: VCVTSI2SSL (BX), X9, X11        // c461322a1b or c5322a1b
+	//TODO: VCVTSI2SSL (R11), X9, X11       // c441322a1b
+	//TODO: VCVTSI2SSL DX, X9, X11          // c461322ada or c5322ada
+	//TODO: VCVTSI2SSL R11, X9, X11         // c441322adb
+	//TODO: VCVTSI2SSQ (BX), X9, X2         // c4e1b22a13
+	//TODO: VCVTSI2SSQ (R11), X9, X2        // c4c1b22a13
+	//TODO: VCVTSI2SSQ DX, X9, X2           // c4e1b22ad2
+	//TODO: VCVTSI2SSQ R11, X9, X2          // c4c1b22ad3
+	//TODO: VCVTSI2SSQ (BX), X9, X11        // c461b22a1b
+	//TODO: VCVTSI2SSQ (R11), X9, X11       // c441b22a1b
+	//TODO: VCVTSI2SSQ DX, X9, X11          // c461b22ada
+	//TODO: VCVTSI2SSQ R11, X9, X11         // c441b22adb
+	//TODO: VCVTSS2SD (BX), X9, X2          // c4e1325a13 or c5b25a13
+	//TODO: VCVTSS2SD (R11), X9, X2         // c4c1325a13
+	//TODO: VCVTSS2SD X2, X9, X2            // c4e1325ad2 or c5b25ad2
+	//TODO: VCVTSS2SD X11, X9, X2           // c4c1325ad3
+	//TODO: VCVTSS2SD (BX), X9, X11         // c461325a1b or c5325a1b
+	//TODO: VCVTSS2SD (R11), X9, X11        // c441325a1b
+	//TODO: VCVTSS2SD X2, X9, X11           // c461325ada or c5325ada
+	//TODO: VCVTSS2SD X11, X9, X11          // c441325adb
+	//TODO: VCVTSS2SI (BX), DX              // c4e17a2d13 or c5fa2d13
+	//TODO: VCVTSS2SI (R11), DX             // c4c17a2d13
+	//TODO: VCVTSS2SI X2, DX                // c4e17a2dd2 or c5fa2dd2
+	//TODO: VCVTSS2SI X11, DX               // c4c17a2dd3
+	//TODO: VCVTSS2SI (BX), R11             // c4617a2d1b or c57a2d1b
+	//TODO: VCVTSS2SI (R11), R11            // c4417a2d1b
+	//TODO: VCVTSS2SI X2, R11               // c4617a2dda or c57a2dda
+	//TODO: VCVTSS2SI X11, R11              // c4417a2ddb
+	//TODO: VCVTSS2SIQ (BX), DX             // c4e1fa2d13
+	//TODO: VCVTSS2SIQ (R11), DX            // c4c1fa2d13
+	//TODO: VCVTSS2SIQ X2, DX               // c4e1fa2dd2
+	//TODO: VCVTSS2SIQ X11, DX              // c4c1fa2dd3
+	//TODO: VCVTSS2SIQ (BX), R11            // c461fa2d1b
+	//TODO: VCVTSS2SIQ (R11), R11           // c441fa2d1b
+	//TODO: VCVTSS2SIQ X2, R11              // c461fa2dda
+	//TODO: VCVTSS2SIQ X11, R11             // c441fa2ddb
+	//TODO: VCVTTPD2DQX (BX), X2            // c4e179e613 or c5f9e613
+	//TODO: VCVTTPD2DQX (R11), X2           // c4c179e613
+	//TODO: VCVTTPD2DQX X2, X2              // c4e179e6d2 or c5f9e6d2
+	//TODO: VCVTTPD2DQX X11, X2             // c4c179e6d3
+	//TODO: VCVTTPD2DQX (BX), X11           // c46179e61b or c579e61b
+	//TODO: VCVTTPD2DQX (R11), X11          // c44179e61b
+	//TODO: VCVTTPD2DQX X2, X11             // c46179e6da or c579e6da
+	//TODO: VCVTTPD2DQX X11, X11            // c44179e6db
+	//TODO: VCVTTPD2DQY (BX), X2            // c4e17de613 or c5fde613
+	//TODO: VCVTTPD2DQY (R11), X2           // c4c17de613
+	//TODO: VCVTTPD2DQY Y2, X2              // c4e17de6d2 or c5fde6d2
+	//TODO: VCVTTPD2DQY Y11, X2             // c4c17de6d3
+	//TODO: VCVTTPD2DQY (BX), X11           // c4617de61b or c57de61b
+	//TODO: VCVTTPD2DQY (R11), X11          // c4417de61b
+	//TODO: VCVTTPD2DQY Y2, X11             // c4617de6da or c57de6da
+	//TODO: VCVTTPD2DQY Y11, X11            // c4417de6db
+	//TODO: VCVTTPS2DQ (BX), X2             // c4e17a5b13 or c5fa5b13
+	//TODO: VCVTTPS2DQ (R11), X2            // c4c17a5b13
+	//TODO: VCVTTPS2DQ X2, X2               // c4e17a5bd2 or c5fa5bd2
+	//TODO: VCVTTPS2DQ X11, X2              // c4c17a5bd3
+	//TODO: VCVTTPS2DQ (BX), X11            // c4617a5b1b or c57a5b1b
+	//TODO: VCVTTPS2DQ (R11), X11           // c4417a5b1b
+	//TODO: VCVTTPS2DQ X2, X11              // c4617a5bda or c57a5bda
+	//TODO: VCVTTPS2DQ X11, X11             // c4417a5bdb
+	//TODO: VCVTTPS2DQ (BX), Y2             // c4e17e5b13 or c5fe5b13
+	//TODO: VCVTTPS2DQ (R11), Y2            // c4c17e5b13
+	//TODO: VCVTTPS2DQ Y2, Y2               // c4e17e5bd2 or c5fe5bd2
+	//TODO: VCVTTPS2DQ Y11, Y2              // c4c17e5bd3
+	//TODO: VCVTTPS2DQ (BX), Y11            // c4617e5b1b or c57e5b1b
+	//TODO: VCVTTPS2DQ (R11), Y11           // c4417e5b1b
+	//TODO: VCVTTPS2DQ Y2, Y11              // c4617e5bda or c57e5bda
+	//TODO: VCVTTPS2DQ Y11, Y11             // c4417e5bdb
+	//TODO: VCVTTSD2SI (BX), DX             // c4e17b2c13 or c5fb2c13
+	//TODO: VCVTTSD2SI (R11), DX            // c4c17b2c13
+	//TODO: VCVTTSD2SI X2, DX               // c4e17b2cd2 or c5fb2cd2
+	//TODO: VCVTTSD2SI X11, DX              // c4c17b2cd3
+	//TODO: VCVTTSD2SI (BX), R11            // c4617b2c1b or c57b2c1b
+	//TODO: VCVTTSD2SI (R11), R11           // c4417b2c1b
+	//TODO: VCVTTSD2SI X2, R11              // c4617b2cda or c57b2cda
+	//TODO: VCVTTSD2SI X11, R11             // c4417b2cdb
+	//TODO: VCVTTSD2SIQ (BX), DX            // c4e1fb2c13
+	//TODO: VCVTTSD2SIQ (R11), DX           // c4c1fb2c13
+	//TODO: VCVTTSD2SIQ X2, DX              // c4e1fb2cd2
+	//TODO: VCVTTSD2SIQ X11, DX             // c4c1fb2cd3
+	//TODO: VCVTTSD2SIQ (BX), R11           // c461fb2c1b
+	//TODO: VCVTTSD2SIQ (R11), R11          // c441fb2c1b
+	//TODO: VCVTTSD2SIQ X2, R11             // c461fb2cda
+	//TODO: VCVTTSD2SIQ X11, R11            // c441fb2cdb
+	//TODO: VCVTTSS2SI (BX), DX             // c4e17a2c13 or c5fa2c13
+	//TODO: VCVTTSS2SI (R11), DX            // c4c17a2c13
+	//TODO: VCVTTSS2SI X2, DX               // c4e17a2cd2 or c5fa2cd2
+	//TODO: VCVTTSS2SI X11, DX              // c4c17a2cd3
+	//TODO: VCVTTSS2SI (BX), R11            // c4617a2c1b or c57a2c1b
+	//TODO: VCVTTSS2SI (R11), R11           // c4417a2c1b
+	//TODO: VCVTTSS2SI X2, R11              // c4617a2cda or c57a2cda
+	//TODO: VCVTTSS2SI X11, R11             // c4417a2cdb
+	//TODO: VCVTTSS2SIQ (BX), DX            // c4e1fa2c13
+	//TODO: VCVTTSS2SIQ (R11), DX           // c4c1fa2c13
+	//TODO: VCVTTSS2SIQ X2, DX              // c4e1fa2cd2
+	//TODO: VCVTTSS2SIQ X11, DX             // c4c1fa2cd3
+	//TODO: VCVTTSS2SIQ (BX), R11           // c461fa2c1b
+	//TODO: VCVTTSS2SIQ (R11), R11          // c441fa2c1b
+	//TODO: VCVTTSS2SIQ X2, R11             // c461fa2cda
+	//TODO: VCVTTSS2SIQ X11, R11            // c441fa2cdb
+	//TODO: VDIVPD (BX), X9, X2             // c4e1315e13 or c5b15e13
+	//TODO: VDIVPD (R11), X9, X2            // c4c1315e13
+	//TODO: VDIVPD X2, X9, X2               // c4e1315ed2 or c5b15ed2
+	//TODO: VDIVPD X11, X9, X2              // c4c1315ed3
+	//TODO: VDIVPD (BX), X9, X11            // c461315e1b or c5315e1b
+	//TODO: VDIVPD (R11), X9, X11           // c441315e1b
+	//TODO: VDIVPD X2, X9, X11              // c461315eda or c5315eda
+	//TODO: VDIVPD X11, X9, X11             // c441315edb
+	//TODO: VDIVPD (BX), Y15, Y2            // c4e1055e13 or c5855e13
+	//TODO: VDIVPD (R11), Y15, Y2           // c4c1055e13
+	//TODO: VDIVPD Y2, Y15, Y2              // c4e1055ed2 or c5855ed2
+	//TODO: VDIVPD Y11, Y15, Y2             // c4c1055ed3
+	//TODO: VDIVPD (BX), Y15, Y11           // c461055e1b or c5055e1b
+	//TODO: VDIVPD (R11), Y15, Y11          // c441055e1b
+	//TODO: VDIVPD Y2, Y15, Y11             // c461055eda or c5055eda
+	//TODO: VDIVPD Y11, Y15, Y11            // c441055edb
+	//TODO: VDIVPS (BX), X9, X2             // c4e1305e13 or c5b05e13
+	//TODO: VDIVPS (R11), X9, X2            // c4c1305e13
+	//TODO: VDIVPS X2, X9, X2               // c4e1305ed2 or c5b05ed2
+	//TODO: VDIVPS X11, X9, X2              // c4c1305ed3
+	//TODO: VDIVPS (BX), X9, X11            // c461305e1b or c5305e1b
+	//TODO: VDIVPS (R11), X9, X11           // c441305e1b
+	//TODO: VDIVPS X2, X9, X11              // c461305eda or c5305eda
+	//TODO: VDIVPS X11, X9, X11             // c441305edb
+	//TODO: VDIVPS (BX), Y15, Y2            // c4e1045e13 or c5845e13
+	//TODO: VDIVPS (R11), Y15, Y2           // c4c1045e13
+	//TODO: VDIVPS Y2, Y15, Y2              // c4e1045ed2 or c5845ed2
+	//TODO: VDIVPS Y11, Y15, Y2             // c4c1045ed3
+	//TODO: VDIVPS (BX), Y15, Y11           // c461045e1b or c5045e1b
+	//TODO: VDIVPS (R11), Y15, Y11          // c441045e1b
+	//TODO: VDIVPS Y2, Y15, Y11             // c461045eda or c5045eda
+	//TODO: VDIVPS Y11, Y15, Y11            // c441045edb
+	//TODO: VDIVSD (BX), X9, X2             // c4e1335e13 or c5b35e13
+	//TODO: VDIVSD (R11), X9, X2            // c4c1335e13
+	//TODO: VDIVSD X2, X9, X2               // c4e1335ed2 or c5b35ed2
+	//TODO: VDIVSD X11, X9, X2              // c4c1335ed3
+	//TODO: VDIVSD (BX), X9, X11            // c461335e1b or c5335e1b
+	//TODO: VDIVSD (R11), X9, X11           // c441335e1b
+	//TODO: VDIVSD X2, X9, X11              // c461335eda or c5335eda
+	//TODO: VDIVSD X11, X9, X11             // c441335edb
+	//TODO: VDIVSS (BX), X9, X2             // c4e1325e13 or c5b25e13
+	//TODO: VDIVSS (R11), X9, X2            // c4c1325e13
+	//TODO: VDIVSS X2, X9, X2               // c4e1325ed2 or c5b25ed2
+	//TODO: VDIVSS X11, X9, X2              // c4c1325ed3
+	//TODO: VDIVSS (BX), X9, X11            // c461325e1b or c5325e1b
+	//TODO: VDIVSS (R11), X9, X11           // c441325e1b
+	//TODO: VDIVSS X2, X9, X11              // c461325eda or c5325eda
+	//TODO: VDIVSS X11, X9, X11             // c441325edb
+	//TODO: VDPPD $7, (BX), X9, X2          // c4e331411307
+	//TODO: VDPPD $7, (R11), X9, X2         // c4c331411307
+	//TODO: VDPPD $7, X2, X9, X2            // c4e33141d207
+	//TODO: VDPPD $7, X11, X9, X2           // c4c33141d307
+	//TODO: VDPPD $7, (BX), X9, X11         // c46331411b07
+	//TODO: VDPPD $7, (R11), X9, X11        // c44331411b07
+	//TODO: VDPPD $7, X2, X9, X11           // c4633141da07
+	//TODO: VDPPD $7, X11, X9, X11          // c4433141db07
+	//TODO: VDPPS $7, (BX), X9, X2          // c4e331401307
+	//TODO: VDPPS $7, (R11), X9, X2         // c4c331401307
+	//TODO: VDPPS $7, X2, X9, X2            // c4e33140d207
+	//TODO: VDPPS $7, X11, X9, X2           // c4c33140d307
+	//TODO: VDPPS $7, (BX), X9, X11         // c46331401b07
+	//TODO: VDPPS $7, (R11), X9, X11        // c44331401b07
+	//TODO: VDPPS $7, X2, X9, X11           // c4633140da07
+	//TODO: VDPPS $7, X11, X9, X11          // c4433140db07
+	//TODO: VDPPS $7, (BX), Y15, Y2         // c4e305401307
+	//TODO: VDPPS $7, (R11), Y15, Y2        // c4c305401307
+	//TODO: VDPPS $7, Y2, Y15, Y2           // c4e30540d207
+	//TODO: VDPPS $7, Y11, Y15, Y2          // c4c30540d307
+	//TODO: VDPPS $7, (BX), Y15, Y11        // c46305401b07
+	//TODO: VDPPS $7, (R11), Y15, Y11       // c44305401b07
+	//TODO: VDPPS $7, Y2, Y15, Y11          // c4630540da07
+	//TODO: VDPPS $7, Y11, Y15, Y11         // c4430540db07
+	VERR (BX)                               // 0f0023
+	VERR (R11)                              // 410f0023
+	VERR DX                                 // 0f00e2
+	VERR R11                                // 410f00e3
+	VERW (BX)                               // 0f002b
+	VERW (R11)                              // 410f002b
+	VERW DX                                 // 0f00ea
+	VERW R11                                // 410f00eb
+	//TODO: VEXTRACTF128 $7, Y2, (BX)       // c4e37d191307
+	//TODO: VEXTRACTF128 $7, Y11, (BX)      // c4637d191b07
+	//TODO: VEXTRACTF128 $7, Y2, (R11)      // c4c37d191307
+	//TODO: VEXTRACTF128 $7, Y11, (R11)     // c4437d191b07
+	//TODO: VEXTRACTF128 $7, Y2, X2         // c4e37d19d207
+	//TODO: VEXTRACTF128 $7, Y11, X2        // c4637d19da07
+	//TODO: VEXTRACTF128 $7, Y2, X11        // c4c37d19d307
+	//TODO: VEXTRACTF128 $7, Y11, X11       // c4437d19db07
+	//TODO: VEXTRACTI128 $7, Y2, (BX)       // c4e37d391307
+	//TODO: VEXTRACTI128 $7, Y11, (BX)      // c4637d391b07
+	//TODO: VEXTRACTI128 $7, Y2, (R11)      // c4c37d391307
+	//TODO: VEXTRACTI128 $7, Y11, (R11)     // c4437d391b07
+	//TODO: VEXTRACTI128 $7, Y2, X2         // c4e37d39d207
+	//TODO: VEXTRACTI128 $7, Y11, X2        // c4637d39da07
+	//TODO: VEXTRACTI128 $7, Y2, X11        // c4c37d39d307
+	//TODO: VEXTRACTI128 $7, Y11, X11       // c4437d39db07
+	//TODO: VEXTRACTPS $7, X2, (BX)         // c4e379171307
+	//TODO: VEXTRACTPS $7, X11, (BX)        // c46379171b07
+	//TODO: VEXTRACTPS $7, X2, (R11)        // c4c379171307
+	//TODO: VEXTRACTPS $7, X11, (R11)       // c44379171b07
+	//TODO: VEXTRACTPS $7, X2, DX           // c4e37917d207
+	//TODO: VEXTRACTPS $7, X11, DX          // c4637917da07
+	//TODO: VEXTRACTPS $7, X2, R11          // c4c37917d307
+	//TODO: VEXTRACTPS $7, X11, R11         // c4437917db07
+	//TODO: VFMADD132PD (BX), X9, X2        // c4e2b19813
+	//TODO: VFMADD132PD (R11), X9, X2       // c4c2b19813
+	//TODO: VFMADD132PD X2, X9, X2          // c4e2b198d2
+	//TODO: VFMADD132PD X11, X9, X2         // c4c2b198d3
+	//TODO: VFMADD132PD (BX), X9, X11       // c462b1981b
+	//TODO: VFMADD132PD (R11), X9, X11      // c442b1981b
+	//TODO: VFMADD132PD X2, X9, X11         // c462b198da
+	//TODO: VFMADD132PD X11, X9, X11        // c442b198db
+	//TODO: VFMADD132PD (BX), Y15, Y2       // c4e2859813
+	//TODO: VFMADD132PD (R11), Y15, Y2      // c4c2859813
+	//TODO: VFMADD132PD Y2, Y15, Y2         // c4e28598d2
+	//TODO: VFMADD132PD Y11, Y15, Y2        // c4c28598d3
+	//TODO: VFMADD132PD (BX), Y15, Y11      // c46285981b
+	//TODO: VFMADD132PD (R11), Y15, Y11     // c44285981b
+	//TODO: VFMADD132PD Y2, Y15, Y11        // c4628598da
+	//TODO: VFMADD132PD Y11, Y15, Y11       // c4428598db
+	//TODO: VFMADD132PS (BX), X9, X2        // c4e2319813
+	//TODO: VFMADD132PS (R11), X9, X2       // c4c2319813
+	//TODO: VFMADD132PS X2, X9, X2          // c4e23198d2
+	//TODO: VFMADD132PS X11, X9, X2         // c4c23198d3
+	//TODO: VFMADD132PS (BX), X9, X11       // c46231981b
+	//TODO: VFMADD132PS (R11), X9, X11      // c44231981b
+	//TODO: VFMADD132PS X2, X9, X11         // c4623198da
+	//TODO: VFMADD132PS X11, X9, X11        // c4423198db
+	//TODO: VFMADD132PS (BX), Y15, Y2       // c4e2059813
+	//TODO: VFMADD132PS (R11), Y15, Y2      // c4c2059813
+	//TODO: VFMADD132PS Y2, Y15, Y2         // c4e20598d2
+	//TODO: VFMADD132PS Y11, Y15, Y2        // c4c20598d3
+	//TODO: VFMADD132PS (BX), Y15, Y11      // c46205981b
+	//TODO: VFMADD132PS (R11), Y15, Y11     // c44205981b
+	//TODO: VFMADD132PS Y2, Y15, Y11        // c4620598da
+	//TODO: VFMADD132PS Y11, Y15, Y11       // c4420598db
+	//TODO: VFMADD132SD (BX), X9, X2        // c4e2b19913
+	//TODO: VFMADD132SD (R11), X9, X2       // c4c2b19913
+	//TODO: VFMADD132SD X2, X9, X2          // c4e2b199d2
+	//TODO: VFMADD132SD X11, X9, X2         // c4c2b199d3
+	//TODO: VFMADD132SD (BX), X9, X11       // c462b1991b
+	//TODO: VFMADD132SD (R11), X9, X11      // c442b1991b
+	//TODO: VFMADD132SD X2, X9, X11         // c462b199da
+	//TODO: VFMADD132SD X11, X9, X11        // c442b199db
+	//TODO: VFMADD132SS (BX), X9, X2        // c4e2319913
+	//TODO: VFMADD132SS (R11), X9, X2       // c4c2319913
+	//TODO: VFMADD132SS X2, X9, X2          // c4e23199d2
+	//TODO: VFMADD132SS X11, X9, X2         // c4c23199d3
+	//TODO: VFMADD132SS (BX), X9, X11       // c46231991b
+	//TODO: VFMADD132SS (R11), X9, X11      // c44231991b
+	//TODO: VFMADD132SS X2, X9, X11         // c4623199da
+	//TODO: VFMADD132SS X11, X9, X11        // c4423199db
+	//TODO: VFMADD213PD (BX), X9, X2        // c4e2b1a813
+	//TODO: VFMADD213PD (R11), X9, X2       // c4c2b1a813
+	//TODO: VFMADD213PD X2, X9, X2          // c4e2b1a8d2
+	//TODO: VFMADD213PD X11, X9, X2         // c4c2b1a8d3
+	//TODO: VFMADD213PD (BX), X9, X11       // c462b1a81b
+	//TODO: VFMADD213PD (R11), X9, X11      // c442b1a81b
+	//TODO: VFMADD213PD X2, X9, X11         // c462b1a8da
+	//TODO: VFMADD213PD X11, X9, X11        // c442b1a8db
+	//TODO: VFMADD213PD (BX), Y15, Y2       // c4e285a813
+	//TODO: VFMADD213PD (R11), Y15, Y2      // c4c285a813
+	//TODO: VFMADD213PD Y2, Y15, Y2         // c4e285a8d2
+	//TODO: VFMADD213PD Y11, Y15, Y2        // c4c285a8d3
+	//TODO: VFMADD213PD (BX), Y15, Y11      // c46285a81b
+	//TODO: VFMADD213PD (R11), Y15, Y11     // c44285a81b
+	//TODO: VFMADD213PD Y2, Y15, Y11        // c46285a8da
+	//TODO: VFMADD213PD Y11, Y15, Y11       // c44285a8db
+	//TODO: VFMADD213PS (BX), X9, X2        // c4e231a813
+	//TODO: VFMADD213PS (R11), X9, X2       // c4c231a813
+	//TODO: VFMADD213PS X2, X9, X2          // c4e231a8d2
+	//TODO: VFMADD213PS X11, X9, X2         // c4c231a8d3
+	//TODO: VFMADD213PS (BX), X9, X11       // c46231a81b
+	//TODO: VFMADD213PS (R11), X9, X11      // c44231a81b
+	//TODO: VFMADD213PS X2, X9, X11         // c46231a8da
+	//TODO: VFMADD213PS X11, X9, X11        // c44231a8db
+	//TODO: VFMADD213PS (BX), Y15, Y2       // c4e205a813
+	//TODO: VFMADD213PS (R11), Y15, Y2      // c4c205a813
+	//TODO: VFMADD213PS Y2, Y15, Y2         // c4e205a8d2
+	//TODO: VFMADD213PS Y11, Y15, Y2        // c4c205a8d3
+	//TODO: VFMADD213PS (BX), Y15, Y11      // c46205a81b
+	//TODO: VFMADD213PS (R11), Y15, Y11     // c44205a81b
+	//TODO: VFMADD213PS Y2, Y15, Y11        // c46205a8da
+	//TODO: VFMADD213PS Y11, Y15, Y11       // c44205a8db
+	//TODO: VFMADD213SD (BX), X9, X2        // c4e2b1a913
+	//TODO: VFMADD213SD (R11), X9, X2       // c4c2b1a913
+	//TODO: VFMADD213SD X2, X9, X2          // c4e2b1a9d2
+	//TODO: VFMADD213SD X11, X9, X2         // c4c2b1a9d3
+	//TODO: VFMADD213SD (BX), X9, X11       // c462b1a91b
+	//TODO: VFMADD213SD (R11), X9, X11      // c442b1a91b
+	//TODO: VFMADD213SD X2, X9, X11         // c462b1a9da
+	//TODO: VFMADD213SD X11, X9, X11        // c442b1a9db
+	//TODO: VFMADD213SS (BX), X9, X2        // c4e231a913
+	//TODO: VFMADD213SS (R11), X9, X2       // c4c231a913
+	//TODO: VFMADD213SS X2, X9, X2          // c4e231a9d2
+	//TODO: VFMADD213SS X11, X9, X2         // c4c231a9d3
+	//TODO: VFMADD213SS (BX), X9, X11       // c46231a91b
+	//TODO: VFMADD213SS (R11), X9, X11      // c44231a91b
+	//TODO: VFMADD213SS X2, X9, X11         // c46231a9da
+	//TODO: VFMADD213SS X11, X9, X11        // c44231a9db
+	//TODO: VFMADD231PD (BX), X9, X2        // c4e2b1b813
+	//TODO: VFMADD231PD (R11), X9, X2       // c4c2b1b813
+	//TODO: VFMADD231PD X2, X9, X2          // c4e2b1b8d2
+	//TODO: VFMADD231PD X11, X9, X2         // c4c2b1b8d3
+	//TODO: VFMADD231PD (BX), X9, X11       // c462b1b81b
+	//TODO: VFMADD231PD (R11), X9, X11      // c442b1b81b
+	//TODO: VFMADD231PD X2, X9, X11         // c462b1b8da
+	//TODO: VFMADD231PD X11, X9, X11        // c442b1b8db
+	//TODO: VFMADD231PD (BX), Y15, Y2       // c4e285b813
+	//TODO: VFMADD231PD (R11), Y15, Y2      // c4c285b813
+	//TODO: VFMADD231PD Y2, Y15, Y2         // c4e285b8d2
+	//TODO: VFMADD231PD Y11, Y15, Y2        // c4c285b8d3
+	//TODO: VFMADD231PD (BX), Y15, Y11      // c46285b81b
+	//TODO: VFMADD231PD (R11), Y15, Y11     // c44285b81b
+	//TODO: VFMADD231PD Y2, Y15, Y11        // c46285b8da
+	//TODO: VFMADD231PD Y11, Y15, Y11       // c44285b8db
+	//TODO: VFMADD231PS (BX), X9, X2        // c4e231b813
+	//TODO: VFMADD231PS (R11), X9, X2       // c4c231b813
+	//TODO: VFMADD231PS X2, X9, X2          // c4e231b8d2
+	//TODO: VFMADD231PS X11, X9, X2         // c4c231b8d3
+	//TODO: VFMADD231PS (BX), X9, X11       // c46231b81b
+	//TODO: VFMADD231PS (R11), X9, X11      // c44231b81b
+	//TODO: VFMADD231PS X2, X9, X11         // c46231b8da
+	//TODO: VFMADD231PS X11, X9, X11        // c44231b8db
+	//TODO: VFMADD231PS (BX), Y15, Y2       // c4e205b813
+	//TODO: VFMADD231PS (R11), Y15, Y2      // c4c205b813
+	//TODO: VFMADD231PS Y2, Y15, Y2         // c4e205b8d2
+	//TODO: VFMADD231PS Y11, Y15, Y2        // c4c205b8d3
+	//TODO: VFMADD231PS (BX), Y15, Y11      // c46205b81b
+	//TODO: VFMADD231PS (R11), Y15, Y11     // c44205b81b
+	//TODO: VFMADD231PS Y2, Y15, Y11        // c46205b8da
+	//TODO: VFMADD231PS Y11, Y15, Y11       // c44205b8db
+	//TODO: VFMADD231SD (BX), X9, X2        // c4e2b1b913
+	//TODO: VFMADD231SD (R11), X9, X2       // c4c2b1b913
+	//TODO: VFMADD231SD X2, X9, X2          // c4e2b1b9d2
+	//TODO: VFMADD231SD X11, X9, X2         // c4c2b1b9d3
+	//TODO: VFMADD231SD (BX), X9, X11       // c462b1b91b
+	//TODO: VFMADD231SD (R11), X9, X11      // c442b1b91b
+	//TODO: VFMADD231SD X2, X9, X11         // c462b1b9da
+	//TODO: VFMADD231SD X11, X9, X11        // c442b1b9db
+	//TODO: VFMADD231SS (BX), X9, X2        // c4e231b913
+	//TODO: VFMADD231SS (R11), X9, X2       // c4c231b913
+	//TODO: VFMADD231SS X2, X9, X2          // c4e231b9d2
+	//TODO: VFMADD231SS X11, X9, X2         // c4c231b9d3
+	//TODO: VFMADD231SS (BX), X9, X11       // c46231b91b
+	//TODO: VFMADD231SS (R11), X9, X11      // c44231b91b
+	//TODO: VFMADD231SS X2, X9, X11         // c46231b9da
+	//TODO: VFMADD231SS X11, X9, X11        // c44231b9db
+	//TODO: VFMADDSUB132PD (BX), X9, X2     // c4e2b19613
+	//TODO: VFMADDSUB132PD (R11), X9, X2    // c4c2b19613
+	//TODO: VFMADDSUB132PD X2, X9, X2       // c4e2b196d2
+	//TODO: VFMADDSUB132PD X11, X9, X2      // c4c2b196d3
+	//TODO: VFMADDSUB132PD (BX), X9, X11    // c462b1961b
+	//TODO: VFMADDSUB132PD (R11), X9, X11   // c442b1961b
+	//TODO: VFMADDSUB132PD X2, X9, X11      // c462b196da
+	//TODO: VFMADDSUB132PD X11, X9, X11     // c442b196db
+	//TODO: VFMADDSUB132PD (BX), Y15, Y2    // c4e2859613
+	//TODO: VFMADDSUB132PD (R11), Y15, Y2   // c4c2859613
+	//TODO: VFMADDSUB132PD Y2, Y15, Y2      // c4e28596d2
+	//TODO: VFMADDSUB132PD Y11, Y15, Y2     // c4c28596d3
+	//TODO: VFMADDSUB132PD (BX), Y15, Y11   // c46285961b
+	//TODO: VFMADDSUB132PD (R11), Y15, Y11  // c44285961b
+	//TODO: VFMADDSUB132PD Y2, Y15, Y11     // c4628596da
+	//TODO: VFMADDSUB132PD Y11, Y15, Y11    // c4428596db
+	//TODO: VFMADDSUB132PS (BX), X9, X2     // c4e2319613
+	//TODO: VFMADDSUB132PS (R11), X9, X2    // c4c2319613
+	//TODO: VFMADDSUB132PS X2, X9, X2       // c4e23196d2
+	//TODO: VFMADDSUB132PS X11, X9, X2      // c4c23196d3
+	//TODO: VFMADDSUB132PS (BX), X9, X11    // c46231961b
+	//TODO: VFMADDSUB132PS (R11), X9, X11   // c44231961b
+	//TODO: VFMADDSUB132PS X2, X9, X11      // c4623196da
+	//TODO: VFMADDSUB132PS X11, X9, X11     // c4423196db
+	//TODO: VFMADDSUB132PS (BX), Y15, Y2    // c4e2059613
+	//TODO: VFMADDSUB132PS (R11), Y15, Y2   // c4c2059613
+	//TODO: VFMADDSUB132PS Y2, Y15, Y2      // c4e20596d2
+	//TODO: VFMADDSUB132PS Y11, Y15, Y2     // c4c20596d3
+	//TODO: VFMADDSUB132PS (BX), Y15, Y11   // c46205961b
+	//TODO: VFMADDSUB132PS (R11), Y15, Y11  // c44205961b
+	//TODO: VFMADDSUB132PS Y2, Y15, Y11     // c4620596da
+	//TODO: VFMADDSUB132PS Y11, Y15, Y11    // c4420596db
+	//TODO: VFMADDSUB213PD (BX), X9, X2     // c4e2b1a613
+	//TODO: VFMADDSUB213PD (R11), X9, X2    // c4c2b1a613
+	//TODO: VFMADDSUB213PD X2, X9, X2       // c4e2b1a6d2
+	//TODO: VFMADDSUB213PD X11, X9, X2      // c4c2b1a6d3
+	//TODO: VFMADDSUB213PD (BX), X9, X11    // c462b1a61b
+	//TODO: VFMADDSUB213PD (R11), X9, X11   // c442b1a61b
+	//TODO: VFMADDSUB213PD X2, X9, X11      // c462b1a6da
+	//TODO: VFMADDSUB213PD X11, X9, X11     // c442b1a6db
+	//TODO: VFMADDSUB213PD (BX), Y15, Y2    // c4e285a613
+	//TODO: VFMADDSUB213PD (R11), Y15, Y2   // c4c285a613
+	//TODO: VFMADDSUB213PD Y2, Y15, Y2      // c4e285a6d2
+	//TODO: VFMADDSUB213PD Y11, Y15, Y2     // c4c285a6d3
+	//TODO: VFMADDSUB213PD (BX), Y15, Y11   // c46285a61b
+	//TODO: VFMADDSUB213PD (R11), Y15, Y11  // c44285a61b
+	//TODO: VFMADDSUB213PD Y2, Y15, Y11     // c46285a6da
+	//TODO: VFMADDSUB213PD Y11, Y15, Y11    // c44285a6db
+	//TODO: VFMADDSUB213PS (BX), X9, X2     // c4e231a613
+	//TODO: VFMADDSUB213PS (R11), X9, X2    // c4c231a613
+	//TODO: VFMADDSUB213PS X2, X9, X2       // c4e231a6d2
+	//TODO: VFMADDSUB213PS X11, X9, X2      // c4c231a6d3
+	//TODO: VFMADDSUB213PS (BX), X9, X11    // c46231a61b
+	//TODO: VFMADDSUB213PS (R11), X9, X11   // c44231a61b
+	//TODO: VFMADDSUB213PS X2, X9, X11      // c46231a6da
+	//TODO: VFMADDSUB213PS X11, X9, X11     // c44231a6db
+	//TODO: VFMADDSUB213PS (BX), Y15, Y2    // c4e205a613
+	//TODO: VFMADDSUB213PS (R11), Y15, Y2   // c4c205a613
+	//TODO: VFMADDSUB213PS Y2, Y15, Y2      // c4e205a6d2
+	//TODO: VFMADDSUB213PS Y11, Y15, Y2     // c4c205a6d3
+	//TODO: VFMADDSUB213PS (BX), Y15, Y11   // c46205a61b
+	//TODO: VFMADDSUB213PS (R11), Y15, Y11  // c44205a61b
+	//TODO: VFMADDSUB213PS Y2, Y15, Y11     // c46205a6da
+	//TODO: VFMADDSUB213PS Y11, Y15, Y11    // c44205a6db
+	//TODO: VFMADDSUB231PD (BX), X9, X2     // c4e2b1b613
+	//TODO: VFMADDSUB231PD (R11), X9, X2    // c4c2b1b613
+	//TODO: VFMADDSUB231PD X2, X9, X2       // c4e2b1b6d2
+	//TODO: VFMADDSUB231PD X11, X9, X2      // c4c2b1b6d3
+	//TODO: VFMADDSUB231PD (BX), X9, X11    // c462b1b61b
+	//TODO: VFMADDSUB231PD (R11), X9, X11   // c442b1b61b
+	//TODO: VFMADDSUB231PD X2, X9, X11      // c462b1b6da
+	//TODO: VFMADDSUB231PD X11, X9, X11     // c442b1b6db
+	//TODO: VFMADDSUB231PD (BX), Y15, Y2    // c4e285b613
+	//TODO: VFMADDSUB231PD (R11), Y15, Y2   // c4c285b613
+	//TODO: VFMADDSUB231PD Y2, Y15, Y2      // c4e285b6d2
+	//TODO: VFMADDSUB231PD Y11, Y15, Y2     // c4c285b6d3
+	//TODO: VFMADDSUB231PD (BX), Y15, Y11   // c46285b61b
+	//TODO: VFMADDSUB231PD (R11), Y15, Y11  // c44285b61b
+	//TODO: VFMADDSUB231PD Y2, Y15, Y11     // c46285b6da
+	//TODO: VFMADDSUB231PD Y11, Y15, Y11    // c44285b6db
+	//TODO: VFMADDSUB231PS (BX), X9, X2     // c4e231b613
+	//TODO: VFMADDSUB231PS (R11), X9, X2    // c4c231b613
+	//TODO: VFMADDSUB231PS X2, X9, X2       // c4e231b6d2
+	//TODO: VFMADDSUB231PS X11, X9, X2      // c4c231b6d3
+	//TODO: VFMADDSUB231PS (BX), X9, X11    // c46231b61b
+	//TODO: VFMADDSUB231PS (R11), X9, X11   // c44231b61b
+	//TODO: VFMADDSUB231PS X2, X9, X11      // c46231b6da
+	//TODO: VFMADDSUB231PS X11, X9, X11     // c44231b6db
+	//TODO: VFMADDSUB231PS (BX), Y15, Y2    // c4e205b613
+	//TODO: VFMADDSUB231PS (R11), Y15, Y2   // c4c205b613
+	//TODO: VFMADDSUB231PS Y2, Y15, Y2      // c4e205b6d2
+	//TODO: VFMADDSUB231PS Y11, Y15, Y2     // c4c205b6d3
+	//TODO: VFMADDSUB231PS (BX), Y15, Y11   // c46205b61b
+	//TODO: VFMADDSUB231PS (R11), Y15, Y11  // c44205b61b
+	//TODO: VFMADDSUB231PS Y2, Y15, Y11     // c46205b6da
+	//TODO: VFMADDSUB231PS Y11, Y15, Y11    // c44205b6db
+	//TODO: VFMSUB132PD (BX), X9, X2        // c4e2b19a13
+	//TODO: VFMSUB132PD (R11), X9, X2       // c4c2b19a13
+	//TODO: VFMSUB132PD X2, X9, X2          // c4e2b19ad2
+	//TODO: VFMSUB132PD X11, X9, X2         // c4c2b19ad3
+	//TODO: VFMSUB132PD (BX), X9, X11       // c462b19a1b
+	//TODO: VFMSUB132PD (R11), X9, X11      // c442b19a1b
+	//TODO: VFMSUB132PD X2, X9, X11         // c462b19ada
+	//TODO: VFMSUB132PD X11, X9, X11        // c442b19adb
+	//TODO: VFMSUB132PD (BX), Y15, Y2       // c4e2859a13
+	//TODO: VFMSUB132PD (R11), Y15, Y2      // c4c2859a13
+	//TODO: VFMSUB132PD Y2, Y15, Y2         // c4e2859ad2
+	//TODO: VFMSUB132PD Y11, Y15, Y2        // c4c2859ad3
+	//TODO: VFMSUB132PD (BX), Y15, Y11      // c462859a1b
+	//TODO: VFMSUB132PD (R11), Y15, Y11     // c442859a1b
+	//TODO: VFMSUB132PD Y2, Y15, Y11        // c462859ada
+	//TODO: VFMSUB132PD Y11, Y15, Y11       // c442859adb
+	//TODO: VFMSUB132PS (BX), X9, X2        // c4e2319a13
+	//TODO: VFMSUB132PS (R11), X9, X2       // c4c2319a13
+	//TODO: VFMSUB132PS X2, X9, X2          // c4e2319ad2
+	//TODO: VFMSUB132PS X11, X9, X2         // c4c2319ad3
+	//TODO: VFMSUB132PS (BX), X9, X11       // c462319a1b
+	//TODO: VFMSUB132PS (R11), X9, X11      // c442319a1b
+	//TODO: VFMSUB132PS X2, X9, X11         // c462319ada
+	//TODO: VFMSUB132PS X11, X9, X11        // c442319adb
+	//TODO: VFMSUB132PS (BX), Y15, Y2       // c4e2059a13
+	//TODO: VFMSUB132PS (R11), Y15, Y2      // c4c2059a13
+	//TODO: VFMSUB132PS Y2, Y15, Y2         // c4e2059ad2
+	//TODO: VFMSUB132PS Y11, Y15, Y2        // c4c2059ad3
+	//TODO: VFMSUB132PS (BX), Y15, Y11      // c462059a1b
+	//TODO: VFMSUB132PS (R11), Y15, Y11     // c442059a1b
+	//TODO: VFMSUB132PS Y2, Y15, Y11        // c462059ada
+	//TODO: VFMSUB132PS Y11, Y15, Y11       // c442059adb
+	//TODO: VFMSUB132SD (BX), X9, X2        // c4e2b19b13
+	//TODO: VFMSUB132SD (R11), X9, X2       // c4c2b19b13
+	//TODO: VFMSUB132SD X2, X9, X2          // c4e2b19bd2
+	//TODO: VFMSUB132SD X11, X9, X2         // c4c2b19bd3
+	//TODO: VFMSUB132SD (BX), X9, X11       // c462b19b1b
+	//TODO: VFMSUB132SD (R11), X9, X11      // c442b19b1b
+	//TODO: VFMSUB132SD X2, X9, X11         // c462b19bda
+	//TODO: VFMSUB132SD X11, X9, X11        // c442b19bdb
+	//TODO: VFMSUB132SS (BX), X9, X2        // c4e2319b13
+	//TODO: VFMSUB132SS (R11), X9, X2       // c4c2319b13
+	//TODO: VFMSUB132SS X2, X9, X2          // c4e2319bd2
+	//TODO: VFMSUB132SS X11, X9, X2         // c4c2319bd3
+	//TODO: VFMSUB132SS (BX), X9, X11       // c462319b1b
+	//TODO: VFMSUB132SS (R11), X9, X11      // c442319b1b
+	//TODO: VFMSUB132SS X2, X9, X11         // c462319bda
+	//TODO: VFMSUB132SS X11, X9, X11        // c442319bdb
+	//TODO: VFMSUB213PD (BX), X9, X2        // c4e2b1aa13
+	//TODO: VFMSUB213PD (R11), X9, X2       // c4c2b1aa13
+	//TODO: VFMSUB213PD X2, X9, X2          // c4e2b1aad2
+	//TODO: VFMSUB213PD X11, X9, X2         // c4c2b1aad3
+	//TODO: VFMSUB213PD (BX), X9, X11       // c462b1aa1b
+	//TODO: VFMSUB213PD (R11), X9, X11      // c442b1aa1b
+	//TODO: VFMSUB213PD X2, X9, X11         // c462b1aada
+	//TODO: VFMSUB213PD X11, X9, X11        // c442b1aadb
+	//TODO: VFMSUB213PD (BX), Y15, Y2       // c4e285aa13
+	//TODO: VFMSUB213PD (R11), Y15, Y2      // c4c285aa13
+	//TODO: VFMSUB213PD Y2, Y15, Y2         // c4e285aad2
+	//TODO: VFMSUB213PD Y11, Y15, Y2        // c4c285aad3
+	//TODO: VFMSUB213PD (BX), Y15, Y11      // c46285aa1b
+	//TODO: VFMSUB213PD (R11), Y15, Y11     // c44285aa1b
+	//TODO: VFMSUB213PD Y2, Y15, Y11        // c46285aada
+	//TODO: VFMSUB213PD Y11, Y15, Y11       // c44285aadb
+	//TODO: VFMSUB213PS (BX), X9, X2        // c4e231aa13
+	//TODO: VFMSUB213PS (R11), X9, X2       // c4c231aa13
+	//TODO: VFMSUB213PS X2, X9, X2          // c4e231aad2
+	//TODO: VFMSUB213PS X11, X9, X2         // c4c231aad3
+	//TODO: VFMSUB213PS (BX), X9, X11       // c46231aa1b
+	//TODO: VFMSUB213PS (R11), X9, X11      // c44231aa1b
+	//TODO: VFMSUB213PS X2, X9, X11         // c46231aada
+	//TODO: VFMSUB213PS X11, X9, X11        // c44231aadb
+	//TODO: VFMSUB213PS (BX), Y15, Y2       // c4e205aa13
+	//TODO: VFMSUB213PS (R11), Y15, Y2      // c4c205aa13
+	//TODO: VFMSUB213PS Y2, Y15, Y2         // c4e205aad2
+	//TODO: VFMSUB213PS Y11, Y15, Y2        // c4c205aad3
+	//TODO: VFMSUB213PS (BX), Y15, Y11      // c46205aa1b
+	//TODO: VFMSUB213PS (R11), Y15, Y11     // c44205aa1b
+	//TODO: VFMSUB213PS Y2, Y15, Y11        // c46205aada
+	//TODO: VFMSUB213PS Y11, Y15, Y11       // c44205aadb
+	//TODO: VFMSUB213SD (BX), X9, X2        // c4e2b1ab13
+	//TODO: VFMSUB213SD (R11), X9, X2       // c4c2b1ab13
+	//TODO: VFMSUB213SD X2, X9, X2          // c4e2b1abd2
+	//TODO: VFMSUB213SD X11, X9, X2         // c4c2b1abd3
+	//TODO: VFMSUB213SD (BX), X9, X11       // c462b1ab1b
+	//TODO: VFMSUB213SD (R11), X9, X11      // c442b1ab1b
+	//TODO: VFMSUB213SD X2, X9, X11         // c462b1abda
+	//TODO: VFMSUB213SD X11, X9, X11        // c442b1abdb
+	//TODO: VFMSUB213SS (BX), X9, X2        // c4e231ab13
+	//TODO: VFMSUB213SS (R11), X9, X2       // c4c231ab13
+	//TODO: VFMSUB213SS X2, X9, X2          // c4e231abd2
+	//TODO: VFMSUB213SS X11, X9, X2         // c4c231abd3
+	//TODO: VFMSUB213SS (BX), X9, X11       // c46231ab1b
+	//TODO: VFMSUB213SS (R11), X9, X11      // c44231ab1b
+	//TODO: VFMSUB213SS X2, X9, X11         // c46231abda
+	//TODO: VFMSUB213SS X11, X9, X11        // c44231abdb
+	//TODO: VFMSUB231PD (BX), X9, X2        // c4e2b1ba13
+	//TODO: VFMSUB231PD (R11), X9, X2       // c4c2b1ba13
+	//TODO: VFMSUB231PD X2, X9, X2          // c4e2b1bad2
+	//TODO: VFMSUB231PD X11, X9, X2         // c4c2b1bad3
+	//TODO: VFMSUB231PD (BX), X9, X11       // c462b1ba1b
+	//TODO: VFMSUB231PD (R11), X9, X11      // c442b1ba1b
+	//TODO: VFMSUB231PD X2, X9, X11         // c462b1bada
+	//TODO: VFMSUB231PD X11, X9, X11        // c442b1badb
+	//TODO: VFMSUB231PD (BX), Y15, Y2       // c4e285ba13
+	//TODO: VFMSUB231PD (R11), Y15, Y2      // c4c285ba13
+	//TODO: VFMSUB231PD Y2, Y15, Y2         // c4e285bad2
+	//TODO: VFMSUB231PD Y11, Y15, Y2        // c4c285bad3
+	//TODO: VFMSUB231PD (BX), Y15, Y11      // c46285ba1b
+	//TODO: VFMSUB231PD (R11), Y15, Y11     // c44285ba1b
+	//TODO: VFMSUB231PD Y2, Y15, Y11        // c46285bada
+	//TODO: VFMSUB231PD Y11, Y15, Y11       // c44285badb
+	//TODO: VFMSUB231PS (BX), X9, X2        // c4e231ba13
+	//TODO: VFMSUB231PS (R11), X9, X2       // c4c231ba13
+	//TODO: VFMSUB231PS X2, X9, X2          // c4e231bad2
+	//TODO: VFMSUB231PS X11, X9, X2         // c4c231bad3
+	//TODO: VFMSUB231PS (BX), X9, X11       // c46231ba1b
+	//TODO: VFMSUB231PS (R11), X9, X11      // c44231ba1b
+	//TODO: VFMSUB231PS X2, X9, X11         // c46231bada
+	//TODO: VFMSUB231PS X11, X9, X11        // c44231badb
+	//TODO: VFMSUB231PS (BX), Y15, Y2       // c4e205ba13
+	//TODO: VFMSUB231PS (R11), Y15, Y2      // c4c205ba13
+	//TODO: VFMSUB231PS Y2, Y15, Y2         // c4e205bad2
+	//TODO: VFMSUB231PS Y11, Y15, Y2        // c4c205bad3
+	//TODO: VFMSUB231PS (BX), Y15, Y11      // c46205ba1b
+	//TODO: VFMSUB231PS (R11), Y15, Y11     // c44205ba1b
+	//TODO: VFMSUB231PS Y2, Y15, Y11        // c46205bada
+	//TODO: VFMSUB231PS Y11, Y15, Y11       // c44205badb
+	//TODO: VFMSUB231SD (BX), X9, X2        // c4e2b1bb13
+	//TODO: VFMSUB231SD (R11), X9, X2       // c4c2b1bb13
+	//TODO: VFMSUB231SD X2, X9, X2          // c4e2b1bbd2
+	//TODO: VFMSUB231SD X11, X9, X2         // c4c2b1bbd3
+	//TODO: VFMSUB231SD (BX), X9, X11       // c462b1bb1b
+	//TODO: VFMSUB231SD (R11), X9, X11      // c442b1bb1b
+	//TODO: VFMSUB231SD X2, X9, X11         // c462b1bbda
+	//TODO: VFMSUB231SD X11, X9, X11        // c442b1bbdb
+	//TODO: VFMSUB231SS (BX), X9, X2        // c4e231bb13
+	//TODO: VFMSUB231SS (R11), X9, X2       // c4c231bb13
+	//TODO: VFMSUB231SS X2, X9, X2          // c4e231bbd2
+	//TODO: VFMSUB231SS X11, X9, X2         // c4c231bbd3
+	//TODO: VFMSUB231SS (BX), X9, X11       // c46231bb1b
+	//TODO: VFMSUB231SS (R11), X9, X11      // c44231bb1b
+	//TODO: VFMSUB231SS X2, X9, X11         // c46231bbda
+	//TODO: VFMSUB231SS X11, X9, X11        // c44231bbdb
+	//TODO: VFMSUBADD132PD (BX), X9, X2     // c4e2b19713
+	//TODO: VFMSUBADD132PD (R11), X9, X2    // c4c2b19713
+	//TODO: VFMSUBADD132PD X2, X9, X2       // c4e2b197d2
+	//TODO: VFMSUBADD132PD X11, X9, X2      // c4c2b197d3
+	//TODO: VFMSUBADD132PD (BX), X9, X11    // c462b1971b
+	//TODO: VFMSUBADD132PD (R11), X9, X11   // c442b1971b
+	//TODO: VFMSUBADD132PD X2, X9, X11      // c462b197da
+	//TODO: VFMSUBADD132PD X11, X9, X11     // c442b197db
+	//TODO: VFMSUBADD132PD (BX), Y15, Y2    // c4e2859713
+	//TODO: VFMSUBADD132PD (R11), Y15, Y2   // c4c2859713
+	//TODO: VFMSUBADD132PD Y2, Y15, Y2      // c4e28597d2
+	//TODO: VFMSUBADD132PD Y11, Y15, Y2     // c4c28597d3
+	//TODO: VFMSUBADD132PD (BX), Y15, Y11   // c46285971b
+	//TODO: VFMSUBADD132PD (R11), Y15, Y11  // c44285971b
+	//TODO: VFMSUBADD132PD Y2, Y15, Y11     // c4628597da
+	//TODO: VFMSUBADD132PD Y11, Y15, Y11    // c4428597db
+	//TODO: VFMSUBADD132PS (BX), X9, X2     // c4e2319713
+	//TODO: VFMSUBADD132PS (R11), X9, X2    // c4c2319713
+	//TODO: VFMSUBADD132PS X2, X9, X2       // c4e23197d2
+	//TODO: VFMSUBADD132PS X11, X9, X2      // c4c23197d3
+	//TODO: VFMSUBADD132PS (BX), X9, X11    // c46231971b
+	//TODO: VFMSUBADD132PS (R11), X9, X11   // c44231971b
+	//TODO: VFMSUBADD132PS X2, X9, X11      // c4623197da
+	//TODO: VFMSUBADD132PS X11, X9, X11     // c4423197db
+	//TODO: VFMSUBADD132PS (BX), Y15, Y2    // c4e2059713
+	//TODO: VFMSUBADD132PS (R11), Y15, Y2   // c4c2059713
+	//TODO: VFMSUBADD132PS Y2, Y15, Y2      // c4e20597d2
+	//TODO: VFMSUBADD132PS Y11, Y15, Y2     // c4c20597d3
+	//TODO: VFMSUBADD132PS (BX), Y15, Y11   // c46205971b
+	//TODO: VFMSUBADD132PS (R11), Y15, Y11  // c44205971b
+	//TODO: VFMSUBADD132PS Y2, Y15, Y11     // c4620597da
+	//TODO: VFMSUBADD132PS Y11, Y15, Y11    // c4420597db
+	//TODO: VFMSUBADD213PD (BX), X9, X2     // c4e2b1a713
+	//TODO: VFMSUBADD213PD (R11), X9, X2    // c4c2b1a713
+	//TODO: VFMSUBADD213PD X2, X9, X2       // c4e2b1a7d2
+	//TODO: VFMSUBADD213PD X11, X9, X2      // c4c2b1a7d3
+	//TODO: VFMSUBADD213PD (BX), X9, X11    // c462b1a71b
+	//TODO: VFMSUBADD213PD (R11), X9, X11   // c442b1a71b
+	//TODO: VFMSUBADD213PD X2, X9, X11      // c462b1a7da
+	//TODO: VFMSUBADD213PD X11, X9, X11     // c442b1a7db
+	//TODO: VFMSUBADD213PD (BX), Y15, Y2    // c4e285a713
+	//TODO: VFMSUBADD213PD (R11), Y15, Y2   // c4c285a713
+	//TODO: VFMSUBADD213PD Y2, Y15, Y2      // c4e285a7d2
+	//TODO: VFMSUBADD213PD Y11, Y15, Y2     // c4c285a7d3
+	//TODO: VFMSUBADD213PD (BX), Y15, Y11   // c46285a71b
+	//TODO: VFMSUBADD213PD (R11), Y15, Y11  // c44285a71b
+	//TODO: VFMSUBADD213PD Y2, Y15, Y11     // c46285a7da
+	//TODO: VFMSUBADD213PD Y11, Y15, Y11    // c44285a7db
+	//TODO: VFMSUBADD213PS (BX), X9, X2     // c4e231a713
+	//TODO: VFMSUBADD213PS (R11), X9, X2    // c4c231a713
+	//TODO: VFMSUBADD213PS X2, X9, X2       // c4e231a7d2
+	//TODO: VFMSUBADD213PS X11, X9, X2      // c4c231a7d3
+	//TODO: VFMSUBADD213PS (BX), X9, X11    // c46231a71b
+	//TODO: VFMSUBADD213PS (R11), X9, X11   // c44231a71b
+	//TODO: VFMSUBADD213PS X2, X9, X11      // c46231a7da
+	//TODO: VFMSUBADD213PS X11, X9, X11     // c44231a7db
+	//TODO: VFMSUBADD213PS (BX), Y15, Y2    // c4e205a713
+	//TODO: VFMSUBADD213PS (R11), Y15, Y2   // c4c205a713
+	//TODO: VFMSUBADD213PS Y2, Y15, Y2      // c4e205a7d2
+	//TODO: VFMSUBADD213PS Y11, Y15, Y2     // c4c205a7d3
+	//TODO: VFMSUBADD213PS (BX), Y15, Y11   // c46205a71b
+	//TODO: VFMSUBADD213PS (R11), Y15, Y11  // c44205a71b
+	//TODO: VFMSUBADD213PS Y2, Y15, Y11     // c46205a7da
+	//TODO: VFMSUBADD213PS Y11, Y15, Y11    // c44205a7db
+	//TODO: VFMSUBADD231PD (BX), X9, X2     // c4e2b1b713
+	//TODO: VFMSUBADD231PD (R11), X9, X2    // c4c2b1b713
+	//TODO: VFMSUBADD231PD X2, X9, X2       // c4e2b1b7d2
+	//TODO: VFMSUBADD231PD X11, X9, X2      // c4c2b1b7d3
+	//TODO: VFMSUBADD231PD (BX), X9, X11    // c462b1b71b
+	//TODO: VFMSUBADD231PD (R11), X9, X11   // c442b1b71b
+	//TODO: VFMSUBADD231PD X2, X9, X11      // c462b1b7da
+	//TODO: VFMSUBADD231PD X11, X9, X11     // c442b1b7db
+	//TODO: VFMSUBADD231PD (BX), Y15, Y2    // c4e285b713
+	//TODO: VFMSUBADD231PD (R11), Y15, Y2   // c4c285b713
+	//TODO: VFMSUBADD231PD Y2, Y15, Y2      // c4e285b7d2
+	//TODO: VFMSUBADD231PD Y11, Y15, Y2     // c4c285b7d3
+	//TODO: VFMSUBADD231PD (BX), Y15, Y11   // c46285b71b
+	//TODO: VFMSUBADD231PD (R11), Y15, Y11  // c44285b71b
+	//TODO: VFMSUBADD231PD Y2, Y15, Y11     // c46285b7da
+	//TODO: VFMSUBADD231PD Y11, Y15, Y11    // c44285b7db
+	//TODO: VFMSUBADD231PS (BX), X9, X2     // c4e231b713
+	//TODO: VFMSUBADD231PS (R11), X9, X2    // c4c231b713
+	//TODO: VFMSUBADD231PS X2, X9, X2       // c4e231b7d2
+	//TODO: VFMSUBADD231PS X11, X9, X2      // c4c231b7d3
+	//TODO: VFMSUBADD231PS (BX), X9, X11    // c46231b71b
+	//TODO: VFMSUBADD231PS (R11), X9, X11   // c44231b71b
+	//TODO: VFMSUBADD231PS X2, X9, X11      // c46231b7da
+	//TODO: VFMSUBADD231PS X11, X9, X11     // c44231b7db
+	//TODO: VFMSUBADD231PS (BX), Y15, Y2    // c4e205b713
+	//TODO: VFMSUBADD231PS (R11), Y15, Y2   // c4c205b713
+	//TODO: VFMSUBADD231PS Y2, Y15, Y2      // c4e205b7d2
+	//TODO: VFMSUBADD231PS Y11, Y15, Y2     // c4c205b7d3
+	//TODO: VFMSUBADD231PS (BX), Y15, Y11   // c46205b71b
+	//TODO: VFMSUBADD231PS (R11), Y15, Y11  // c44205b71b
+	//TODO: VFMSUBADD231PS Y2, Y15, Y11     // c46205b7da
+	//TODO: VFMSUBADD231PS Y11, Y15, Y11    // c44205b7db
+	//TODO: VFNMADD132PD (BX), X9, X2       // c4e2b19c13
+	//TODO: VFNMADD132PD (R11), X9, X2      // c4c2b19c13
+	//TODO: VFNMADD132PD X2, X9, X2         // c4e2b19cd2
+	//TODO: VFNMADD132PD X11, X9, X2        // c4c2b19cd3
+	//TODO: VFNMADD132PD (BX), X9, X11      // c462b19c1b
+	//TODO: VFNMADD132PD (R11), X9, X11     // c442b19c1b
+	//TODO: VFNMADD132PD X2, X9, X11        // c462b19cda
+	//TODO: VFNMADD132PD X11, X9, X11       // c442b19cdb
+	//TODO: VFNMADD132PD (BX), Y15, Y2      // c4e2859c13
+	//TODO: VFNMADD132PD (R11), Y15, Y2     // c4c2859c13
+	//TODO: VFNMADD132PD Y2, Y15, Y2        // c4e2859cd2
+	//TODO: VFNMADD132PD Y11, Y15, Y2       // c4c2859cd3
+	//TODO: VFNMADD132PD (BX), Y15, Y11     // c462859c1b
+	//TODO: VFNMADD132PD (R11), Y15, Y11    // c442859c1b
+	//TODO: VFNMADD132PD Y2, Y15, Y11       // c462859cda
+	//TODO: VFNMADD132PD Y11, Y15, Y11      // c442859cdb
+	//TODO: VFNMADD132PS (BX), X9, X2       // c4e2319c13
+	//TODO: VFNMADD132PS (R11), X9, X2      // c4c2319c13
+	//TODO: VFNMADD132PS X2, X9, X2         // c4e2319cd2
+	//TODO: VFNMADD132PS X11, X9, X2        // c4c2319cd3
+	//TODO: VFNMADD132PS (BX), X9, X11      // c462319c1b
+	//TODO: VFNMADD132PS (R11), X9, X11     // c442319c1b
+	//TODO: VFNMADD132PS X2, X9, X11        // c462319cda
+	//TODO: VFNMADD132PS X11, X9, X11       // c442319cdb
+	//TODO: VFNMADD132PS (BX), Y15, Y2      // c4e2059c13
+	//TODO: VFNMADD132PS (R11), Y15, Y2     // c4c2059c13
+	//TODO: VFNMADD132PS Y2, Y15, Y2        // c4e2059cd2
+	//TODO: VFNMADD132PS Y11, Y15, Y2       // c4c2059cd3
+	//TODO: VFNMADD132PS (BX), Y15, Y11     // c462059c1b
+	//TODO: VFNMADD132PS (R11), Y15, Y11    // c442059c1b
+	//TODO: VFNMADD132PS Y2, Y15, Y11       // c462059cda
+	//TODO: VFNMADD132PS Y11, Y15, Y11      // c442059cdb
+	//TODO: VFNMADD132SD (BX), X9, X2       // c4e2b19d13
+	//TODO: VFNMADD132SD (R11), X9, X2      // c4c2b19d13
+	//TODO: VFNMADD132SD X2, X9, X2         // c4e2b19dd2
+	//TODO: VFNMADD132SD X11, X9, X2        // c4c2b19dd3
+	//TODO: VFNMADD132SD (BX), X9, X11      // c462b19d1b
+	//TODO: VFNMADD132SD (R11), X9, X11     // c442b19d1b
+	//TODO: VFNMADD132SD X2, X9, X11        // c462b19dda
+	//TODO: VFNMADD132SD X11, X9, X11       // c442b19ddb
+	//TODO: VFNMADD132SS (BX), X9, X2       // c4e2319d13
+	//TODO: VFNMADD132SS (R11), X9, X2      // c4c2319d13
+	//TODO: VFNMADD132SS X2, X9, X2         // c4e2319dd2
+	//TODO: VFNMADD132SS X11, X9, X2        // c4c2319dd3
+	//TODO: VFNMADD132SS (BX), X9, X11      // c462319d1b
+	//TODO: VFNMADD132SS (R11), X9, X11     // c442319d1b
+	//TODO: VFNMADD132SS X2, X9, X11        // c462319dda
+	//TODO: VFNMADD132SS X11, X9, X11       // c442319ddb
+	//TODO: VFNMADD213PD (BX), X9, X2       // c4e2b1ac13
+	//TODO: VFNMADD213PD (R11), X9, X2      // c4c2b1ac13
+	//TODO: VFNMADD213PD X2, X9, X2         // c4e2b1acd2
+	//TODO: VFNMADD213PD X11, X9, X2        // c4c2b1acd3
+	//TODO: VFNMADD213PD (BX), X9, X11      // c462b1ac1b
+	//TODO: VFNMADD213PD (R11), X9, X11     // c442b1ac1b
+	//TODO: VFNMADD213PD X2, X9, X11        // c462b1acda
+	//TODO: VFNMADD213PD X11, X9, X11       // c442b1acdb
+	//TODO: VFNMADD213PD (BX), Y15, Y2      // c4e285ac13
+	//TODO: VFNMADD213PD (R11), Y15, Y2     // c4c285ac13
+	//TODO: VFNMADD213PD Y2, Y15, Y2        // c4e285acd2
+	//TODO: VFNMADD213PD Y11, Y15, Y2       // c4c285acd3
+	//TODO: VFNMADD213PD (BX), Y15, Y11     // c46285ac1b
+	//TODO: VFNMADD213PD (R11), Y15, Y11    // c44285ac1b
+	//TODO: VFNMADD213PD Y2, Y15, Y11       // c46285acda
+	//TODO: VFNMADD213PD Y11, Y15, Y11      // c44285acdb
+	//TODO: VFNMADD213PS (BX), X9, X2       // c4e231ac13
+	//TODO: VFNMADD213PS (R11), X9, X2      // c4c231ac13
+	//TODO: VFNMADD213PS X2, X9, X2         // c4e231acd2
+	//TODO: VFNMADD213PS X11, X9, X2        // c4c231acd3
+	//TODO: VFNMADD213PS (BX), X9, X11      // c46231ac1b
+	//TODO: VFNMADD213PS (R11), X9, X11     // c44231ac1b
+	//TODO: VFNMADD213PS X2, X9, X11        // c46231acda
+	//TODO: VFNMADD213PS X11, X9, X11       // c44231acdb
+	//TODO: VFNMADD213PS (BX), Y15, Y2      // c4e205ac13
+	//TODO: VFNMADD213PS (R11), Y15, Y2     // c4c205ac13
+	//TODO: VFNMADD213PS Y2, Y15, Y2        // c4e205acd2
+	//TODO: VFNMADD213PS Y11, Y15, Y2       // c4c205acd3
+	//TODO: VFNMADD213PS (BX), Y15, Y11     // c46205ac1b
+	//TODO: VFNMADD213PS (R11), Y15, Y11    // c44205ac1b
+	//TODO: VFNMADD213PS Y2, Y15, Y11       // c46205acda
+	//TODO: VFNMADD213PS Y11, Y15, Y11      // c44205acdb
+	//TODO: VFNMADD213SD (BX), X9, X2       // c4e2b1ad13
+	//TODO: VFNMADD213SD (R11), X9, X2      // c4c2b1ad13
+	//TODO: VFNMADD213SD X2, X9, X2         // c4e2b1add2
+	//TODO: VFNMADD213SD X11, X9, X2        // c4c2b1add3
+	//TODO: VFNMADD213SD (BX), X9, X11      // c462b1ad1b
+	//TODO: VFNMADD213SD (R11), X9, X11     // c442b1ad1b
+	//TODO: VFNMADD213SD X2, X9, X11        // c462b1adda
+	//TODO: VFNMADD213SD X11, X9, X11       // c442b1addb
+	//TODO: VFNMADD213SS (BX), X9, X2       // c4e231ad13
+	//TODO: VFNMADD213SS (R11), X9, X2      // c4c231ad13
+	//TODO: VFNMADD213SS X2, X9, X2         // c4e231add2
+	//TODO: VFNMADD213SS X11, X9, X2        // c4c231add3
+	//TODO: VFNMADD213SS (BX), X9, X11      // c46231ad1b
+	//TODO: VFNMADD213SS (R11), X9, X11     // c44231ad1b
+	//TODO: VFNMADD213SS X2, X9, X11        // c46231adda
+	//TODO: VFNMADD213SS X11, X9, X11       // c44231addb
+	//TODO: VFNMADD231PD (BX), X9, X2       // c4e2b1bc13
+	//TODO: VFNMADD231PD (R11), X9, X2      // c4c2b1bc13
+	//TODO: VFNMADD231PD X2, X9, X2         // c4e2b1bcd2
+	//TODO: VFNMADD231PD X11, X9, X2        // c4c2b1bcd3
+	//TODO: VFNMADD231PD (BX), X9, X11      // c462b1bc1b
+	//TODO: VFNMADD231PD (R11), X9, X11     // c442b1bc1b
+	//TODO: VFNMADD231PD X2, X9, X11        // c462b1bcda
+	//TODO: VFNMADD231PD X11, X9, X11       // c442b1bcdb
+	//TODO: VFNMADD231PD (BX), Y15, Y2      // c4e285bc13
+	//TODO: VFNMADD231PD (R11), Y15, Y2     // c4c285bc13
+	//TODO: VFNMADD231PD Y2, Y15, Y2        // c4e285bcd2
+	//TODO: VFNMADD231PD Y11, Y15, Y2       // c4c285bcd3
+	//TODO: VFNMADD231PD (BX), Y15, Y11     // c46285bc1b
+	//TODO: VFNMADD231PD (R11), Y15, Y11    // c44285bc1b
+	//TODO: VFNMADD231PD Y2, Y15, Y11       // c46285bcda
+	//TODO: VFNMADD231PD Y11, Y15, Y11      // c44285bcdb
+	//TODO: VFNMADD231PS (BX), X9, X2       // c4e231bc13
+	//TODO: VFNMADD231PS (R11), X9, X2      // c4c231bc13
+	//TODO: VFNMADD231PS X2, X9, X2         // c4e231bcd2
+	//TODO: VFNMADD231PS X11, X9, X2        // c4c231bcd3
+	//TODO: VFNMADD231PS (BX), X9, X11      // c46231bc1b
+	//TODO: VFNMADD231PS (R11), X9, X11     // c44231bc1b
+	//TODO: VFNMADD231PS X2, X9, X11        // c46231bcda
+	//TODO: VFNMADD231PS X11, X9, X11       // c44231bcdb
+	//TODO: VFNMADD231PS (BX), Y15, Y2      // c4e205bc13
+	//TODO: VFNMADD231PS (R11), Y15, Y2     // c4c205bc13
+	//TODO: VFNMADD231PS Y2, Y15, Y2        // c4e205bcd2
+	//TODO: VFNMADD231PS Y11, Y15, Y2       // c4c205bcd3
+	//TODO: VFNMADD231PS (BX), Y15, Y11     // c46205bc1b
+	//TODO: VFNMADD231PS (R11), Y15, Y11    // c44205bc1b
+	//TODO: VFNMADD231PS Y2, Y15, Y11       // c46205bcda
+	//TODO: VFNMADD231PS Y11, Y15, Y11      // c44205bcdb
+	//TODO: VFNMADD231SD (BX), X9, X2       // c4e2b1bd13
+	//TODO: VFNMADD231SD (R11), X9, X2      // c4c2b1bd13
+	//TODO: VFNMADD231SD X2, X9, X2         // c4e2b1bdd2
+	//TODO: VFNMADD231SD X11, X9, X2        // c4c2b1bdd3
+	//TODO: VFNMADD231SD (BX), X9, X11      // c462b1bd1b
+	//TODO: VFNMADD231SD (R11), X9, X11     // c442b1bd1b
+	//TODO: VFNMADD231SD X2, X9, X11        // c462b1bdda
+	//TODO: VFNMADD231SD X11, X9, X11       // c442b1bddb
+	//TODO: VFNMADD231SS (BX), X9, X2       // c4e231bd13
+	//TODO: VFNMADD231SS (R11), X9, X2      // c4c231bd13
+	//TODO: VFNMADD231SS X2, X9, X2         // c4e231bdd2
+	//TODO: VFNMADD231SS X11, X9, X2        // c4c231bdd3
+	//TODO: VFNMADD231SS (BX), X9, X11      // c46231bd1b
+	//TODO: VFNMADD231SS (R11), X9, X11     // c44231bd1b
+	//TODO: VFNMADD231SS X2, X9, X11        // c46231bdda
+	//TODO: VFNMADD231SS X11, X9, X11       // c44231bddb
+	//TODO: VFNMSUB132PD (BX), X9, X2       // c4e2b19e13
+	//TODO: VFNMSUB132PD (R11), X9, X2      // c4c2b19e13
+	//TODO: VFNMSUB132PD X2, X9, X2         // c4e2b19ed2
+	//TODO: VFNMSUB132PD X11, X9, X2        // c4c2b19ed3
+	//TODO: VFNMSUB132PD (BX), X9, X11      // c462b19e1b
+	//TODO: VFNMSUB132PD (R11), X9, X11     // c442b19e1b
+	//TODO: VFNMSUB132PD X2, X9, X11        // c462b19eda
+	//TODO: VFNMSUB132PD X11, X9, X11       // c442b19edb
+	//TODO: VFNMSUB132PD (BX), Y15, Y2      // c4e2859e13
+	//TODO: VFNMSUB132PD (R11), Y15, Y2     // c4c2859e13
+	//TODO: VFNMSUB132PD Y2, Y15, Y2        // c4e2859ed2
+	//TODO: VFNMSUB132PD Y11, Y15, Y2       // c4c2859ed3
+	//TODO: VFNMSUB132PD (BX), Y15, Y11     // c462859e1b
+	//TODO: VFNMSUB132PD (R11), Y15, Y11    // c442859e1b
+	//TODO: VFNMSUB132PD Y2, Y15, Y11       // c462859eda
+	//TODO: VFNMSUB132PD Y11, Y15, Y11      // c442859edb
+	//TODO: VFNMSUB132PS (BX), X9, X2       // c4e2319e13
+	//TODO: VFNMSUB132PS (R11), X9, X2      // c4c2319e13
+	//TODO: VFNMSUB132PS X2, X9, X2         // c4e2319ed2
+	//TODO: VFNMSUB132PS X11, X9, X2        // c4c2319ed3
+	//TODO: VFNMSUB132PS (BX), X9, X11      // c462319e1b
+	//TODO: VFNMSUB132PS (R11), X9, X11     // c442319e1b
+	//TODO: VFNMSUB132PS X2, X9, X11        // c462319eda
+	//TODO: VFNMSUB132PS X11, X9, X11       // c442319edb
+	//TODO: VFNMSUB132PS (BX), Y15, Y2      // c4e2059e13
+	//TODO: VFNMSUB132PS (R11), Y15, Y2     // c4c2059e13
+	//TODO: VFNMSUB132PS Y2, Y15, Y2        // c4e2059ed2
+	//TODO: VFNMSUB132PS Y11, Y15, Y2       // c4c2059ed3
+	//TODO: VFNMSUB132PS (BX), Y15, Y11     // c462059e1b
+	//TODO: VFNMSUB132PS (R11), Y15, Y11    // c442059e1b
+	//TODO: VFNMSUB132PS Y2, Y15, Y11       // c462059eda
+	//TODO: VFNMSUB132PS Y11, Y15, Y11      // c442059edb
+	//TODO: VFNMSUB132SD (BX), X9, X2       // c4e2b19f13
+	//TODO: VFNMSUB132SD (R11), X9, X2      // c4c2b19f13
+	//TODO: VFNMSUB132SD X2, X9, X2         // c4e2b19fd2
+	//TODO: VFNMSUB132SD X11, X9, X2        // c4c2b19fd3
+	//TODO: VFNMSUB132SD (BX), X9, X11      // c462b19f1b
+	//TODO: VFNMSUB132SD (R11), X9, X11     // c442b19f1b
+	//TODO: VFNMSUB132SD X2, X9, X11        // c462b19fda
+	//TODO: VFNMSUB132SD X11, X9, X11       // c442b19fdb
+	//TODO: VFNMSUB132SS (BX), X9, X2       // c4e2319f13
+	//TODO: VFNMSUB132SS (R11), X9, X2      // c4c2319f13
+	//TODO: VFNMSUB132SS X2, X9, X2         // c4e2319fd2
+	//TODO: VFNMSUB132SS X11, X9, X2        // c4c2319fd3
+	//TODO: VFNMSUB132SS (BX), X9, X11      // c462319f1b
+	//TODO: VFNMSUB132SS (R11), X9, X11     // c442319f1b
+	//TODO: VFNMSUB132SS X2, X9, X11        // c462319fda
+	//TODO: VFNMSUB132SS X11, X9, X11       // c442319fdb
+	//TODO: VFNMSUB213PD (BX), X9, X2       // c4e2b1ae13
+	//TODO: VFNMSUB213PD (R11), X9, X2      // c4c2b1ae13
+	//TODO: VFNMSUB213PD X2, X9, X2         // c4e2b1aed2
+	//TODO: VFNMSUB213PD X11, X9, X2        // c4c2b1aed3
+	//TODO: VFNMSUB213PD (BX), X9, X11      // c462b1ae1b
+	//TODO: VFNMSUB213PD (R11), X9, X11     // c442b1ae1b
+	//TODO: VFNMSUB213PD X2, X9, X11        // c462b1aeda
+	//TODO: VFNMSUB213PD X11, X9, X11       // c442b1aedb
+	//TODO: VFNMSUB213PD (BX), Y15, Y2      // c4e285ae13
+	//TODO: VFNMSUB213PD (R11), Y15, Y2     // c4c285ae13
+	//TODO: VFNMSUB213PD Y2, Y15, Y2        // c4e285aed2
+	//TODO: VFNMSUB213PD Y11, Y15, Y2       // c4c285aed3
+	//TODO: VFNMSUB213PD (BX), Y15, Y11     // c46285ae1b
+	//TODO: VFNMSUB213PD (R11), Y15, Y11    // c44285ae1b
+	//TODO: VFNMSUB213PD Y2, Y15, Y11       // c46285aeda
+	//TODO: VFNMSUB213PD Y11, Y15, Y11      // c44285aedb
+	//TODO: VFNMSUB213PS (BX), X9, X2       // c4e231ae13
+	//TODO: VFNMSUB213PS (R11), X9, X2      // c4c231ae13
+	//TODO: VFNMSUB213PS X2, X9, X2         // c4e231aed2
+	//TODO: VFNMSUB213PS X11, X9, X2        // c4c231aed3
+	//TODO: VFNMSUB213PS (BX), X9, X11      // c46231ae1b
+	//TODO: VFNMSUB213PS (R11), X9, X11     // c44231ae1b
+	//TODO: VFNMSUB213PS X2, X9, X11        // c46231aeda
+	//TODO: VFNMSUB213PS X11, X9, X11       // c44231aedb
+	//TODO: VFNMSUB213PS (BX), Y15, Y2      // c4e205ae13
+	//TODO: VFNMSUB213PS (R11), Y15, Y2     // c4c205ae13
+	//TODO: VFNMSUB213PS Y2, Y15, Y2        // c4e205aed2
+	//TODO: VFNMSUB213PS Y11, Y15, Y2       // c4c205aed3
+	//TODO: VFNMSUB213PS (BX), Y15, Y11     // c46205ae1b
+	//TODO: VFNMSUB213PS (R11), Y15, Y11    // c44205ae1b
+	//TODO: VFNMSUB213PS Y2, Y15, Y11       // c46205aeda
+	//TODO: VFNMSUB213PS Y11, Y15, Y11      // c44205aedb
+	//TODO: VFNMSUB213SD (BX), X9, X2       // c4e2b1af13
+	//TODO: VFNMSUB213SD (R11), X9, X2      // c4c2b1af13
+	//TODO: VFNMSUB213SD X2, X9, X2         // c4e2b1afd2
+	//TODO: VFNMSUB213SD X11, X9, X2        // c4c2b1afd3
+	//TODO: VFNMSUB213SD (BX), X9, X11      // c462b1af1b
+	//TODO: VFNMSUB213SD (R11), X9, X11     // c442b1af1b
+	//TODO: VFNMSUB213SD X2, X9, X11        // c462b1afda
+	//TODO: VFNMSUB213SD X11, X9, X11       // c442b1afdb
+	//TODO: VFNMSUB213SS (BX), X9, X2       // c4e231af13
+	//TODO: VFNMSUB213SS (R11), X9, X2      // c4c231af13
+	//TODO: VFNMSUB213SS X2, X9, X2         // c4e231afd2
+	//TODO: VFNMSUB213SS X11, X9, X2        // c4c231afd3
+	//TODO: VFNMSUB213SS (BX), X9, X11      // c46231af1b
+	//TODO: VFNMSUB213SS (R11), X9, X11     // c44231af1b
+	//TODO: VFNMSUB213SS X2, X9, X11        // c46231afda
+	//TODO: VFNMSUB213SS X11, X9, X11       // c44231afdb
+	//TODO: VFNMSUB231PD (BX), X9, X2       // c4e2b1be13
+	//TODO: VFNMSUB231PD (R11), X9, X2      // c4c2b1be13
+	//TODO: VFNMSUB231PD X2, X9, X2         // c4e2b1bed2
+	//TODO: VFNMSUB231PD X11, X9, X2        // c4c2b1bed3
+	//TODO: VFNMSUB231PD (BX), X9, X11      // c462b1be1b
+	//TODO: VFNMSUB231PD (R11), X9, X11     // c442b1be1b
+	//TODO: VFNMSUB231PD X2, X9, X11        // c462b1beda
+	//TODO: VFNMSUB231PD X11, X9, X11       // c442b1bedb
+	//TODO: VFNMSUB231PD (BX), Y15, Y2      // c4e285be13
+	//TODO: VFNMSUB231PD (R11), Y15, Y2     // c4c285be13
+	//TODO: VFNMSUB231PD Y2, Y15, Y2        // c4e285bed2
+	//TODO: VFNMSUB231PD Y11, Y15, Y2       // c4c285bed3
+	//TODO: VFNMSUB231PD (BX), Y15, Y11     // c46285be1b
+	//TODO: VFNMSUB231PD (R11), Y15, Y11    // c44285be1b
+	//TODO: VFNMSUB231PD Y2, Y15, Y11       // c46285beda
+	//TODO: VFNMSUB231PD Y11, Y15, Y11      // c44285bedb
+	//TODO: VFNMSUB231PS (BX), X9, X2       // c4e231be13
+	//TODO: VFNMSUB231PS (R11), X9, X2      // c4c231be13
+	//TODO: VFNMSUB231PS X2, X9, X2         // c4e231bed2
+	//TODO: VFNMSUB231PS X11, X9, X2        // c4c231bed3
+	//TODO: VFNMSUB231PS (BX), X9, X11      // c46231be1b
+	//TODO: VFNMSUB231PS (R11), X9, X11     // c44231be1b
+	//TODO: VFNMSUB231PS X2, X9, X11        // c46231beda
+	//TODO: VFNMSUB231PS X11, X9, X11       // c44231bedb
+	//TODO: VFNMSUB231PS (BX), Y15, Y2      // c4e205be13
+	//TODO: VFNMSUB231PS (R11), Y15, Y2     // c4c205be13
+	//TODO: VFNMSUB231PS Y2, Y15, Y2        // c4e205bed2
+	//TODO: VFNMSUB231PS Y11, Y15, Y2       // c4c205bed3
+	//TODO: VFNMSUB231PS (BX), Y15, Y11     // c46205be1b
+	//TODO: VFNMSUB231PS (R11), Y15, Y11    // c44205be1b
+	//TODO: VFNMSUB231PS Y2, Y15, Y11       // c46205beda
+	//TODO: VFNMSUB231PS Y11, Y15, Y11      // c44205bedb
+	//TODO: VFNMSUB231SD (BX), X9, X2       // c4e2b1bf13
+	//TODO: VFNMSUB231SD (R11), X9, X2      // c4c2b1bf13
+	//TODO: VFNMSUB231SD X2, X9, X2         // c4e2b1bfd2
+	//TODO: VFNMSUB231SD X11, X9, X2        // c4c2b1bfd3
+	//TODO: VFNMSUB231SD (BX), X9, X11      // c462b1bf1b
+	//TODO: VFNMSUB231SD (R11), X9, X11     // c442b1bf1b
+	//TODO: VFNMSUB231SD X2, X9, X11        // c462b1bfda
+	//TODO: VFNMSUB231SD X11, X9, X11       // c442b1bfdb
+	//TODO: VFNMSUB231SS (BX), X9, X2       // c4e231bf13
+	//TODO: VFNMSUB231SS (R11), X9, X2      // c4c231bf13
+	//TODO: VFNMSUB231SS X2, X9, X2         // c4e231bfd2
+	//TODO: VFNMSUB231SS X11, X9, X2        // c4c231bfd3
+	//TODO: VFNMSUB231SS (BX), X9, X11      // c46231bf1b
+	//TODO: VFNMSUB231SS (R11), X9, X11     // c44231bf1b
+	//TODO: VFNMSUB231SS X2, X9, X11        // c46231bfda
+	//TODO: VFNMSUB231SS X11, X9, X11       // c44231bfdb
+	//TODO: VHADDPD (BX), X9, X2            // c4e1317c13 or c5b17c13
+	//TODO: VHADDPD (R11), X9, X2           // c4c1317c13
+	//TODO: VHADDPD X2, X9, X2              // c4e1317cd2 or c5b17cd2
+	//TODO: VHADDPD X11, X9, X2             // c4c1317cd3
+	//TODO: VHADDPD (BX), X9, X11           // c461317c1b or c5317c1b
+	//TODO: VHADDPD (R11), X9, X11          // c441317c1b
+	//TODO: VHADDPD X2, X9, X11             // c461317cda or c5317cda
+	//TODO: VHADDPD X11, X9, X11            // c441317cdb
+	//TODO: VHADDPD (BX), Y15, Y2           // c4e1057c13 or c5857c13
+	//TODO: VHADDPD (R11), Y15, Y2          // c4c1057c13
+	//TODO: VHADDPD Y2, Y15, Y2             // c4e1057cd2 or c5857cd2
+	//TODO: VHADDPD Y11, Y15, Y2            // c4c1057cd3
+	//TODO: VHADDPD (BX), Y15, Y11          // c461057c1b or c5057c1b
+	//TODO: VHADDPD (R11), Y15, Y11         // c441057c1b
+	//TODO: VHADDPD Y2, Y15, Y11            // c461057cda or c5057cda
+	//TODO: VHADDPD Y11, Y15, Y11           // c441057cdb
+	//TODO: VHADDPS (BX), X9, X2            // c4e1337c13 or c5b37c13
+	//TODO: VHADDPS (R11), X9, X2           // c4c1337c13
+	//TODO: VHADDPS X2, X9, X2              // c4e1337cd2 or c5b37cd2
+	//TODO: VHADDPS X11, X9, X2             // c4c1337cd3
+	//TODO: VHADDPS (BX), X9, X11           // c461337c1b or c5337c1b
+	//TODO: VHADDPS (R11), X9, X11          // c441337c1b
+	//TODO: VHADDPS X2, X9, X11             // c461337cda or c5337cda
+	//TODO: VHADDPS X11, X9, X11            // c441337cdb
+	//TODO: VHADDPS (BX), Y15, Y2           // c4e1077c13 or c5877c13
+	//TODO: VHADDPS (R11), Y15, Y2          // c4c1077c13
+	//TODO: VHADDPS Y2, Y15, Y2             // c4e1077cd2 or c5877cd2
+	//TODO: VHADDPS Y11, Y15, Y2            // c4c1077cd3
+	//TODO: VHADDPS (BX), Y15, Y11          // c461077c1b or c5077c1b
+	//TODO: VHADDPS (R11), Y15, Y11         // c441077c1b
+	//TODO: VHADDPS Y2, Y15, Y11            // c461077cda or c5077cda
+	//TODO: VHADDPS Y11, Y15, Y11           // c441077cdb
+	//TODO: VHSUBPD (BX), X9, X2            // c4e1317d13 or c5b17d13
+	//TODO: VHSUBPD (R11), X9, X2           // c4c1317d13
+	//TODO: VHSUBPD X2, X9, X2              // c4e1317dd2 or c5b17dd2
+	//TODO: VHSUBPD X11, X9, X2             // c4c1317dd3
+	//TODO: VHSUBPD (BX), X9, X11           // c461317d1b or c5317d1b
+	//TODO: VHSUBPD (R11), X9, X11          // c441317d1b
+	//TODO: VHSUBPD X2, X9, X11             // c461317dda or c5317dda
+	//TODO: VHSUBPD X11, X9, X11            // c441317ddb
+	//TODO: VHSUBPD (BX), Y15, Y2           // c4e1057d13 or c5857d13
+	//TODO: VHSUBPD (R11), Y15, Y2          // c4c1057d13
+	//TODO: VHSUBPD Y2, Y15, Y2             // c4e1057dd2 or c5857dd2
+	//TODO: VHSUBPD Y11, Y15, Y2            // c4c1057dd3
+	//TODO: VHSUBPD (BX), Y15, Y11          // c461057d1b or c5057d1b
+	//TODO: VHSUBPD (R11), Y15, Y11         // c441057d1b
+	//TODO: VHSUBPD Y2, Y15, Y11            // c461057dda or c5057dda
+	//TODO: VHSUBPD Y11, Y15, Y11           // c441057ddb
+	//TODO: VHSUBPS (BX), X9, X2            // c4e1337d13 or c5b37d13
+	//TODO: VHSUBPS (R11), X9, X2           // c4c1337d13
+	//TODO: VHSUBPS X2, X9, X2              // c4e1337dd2 or c5b37dd2
+	//TODO: VHSUBPS X11, X9, X2             // c4c1337dd3
+	//TODO: VHSUBPS (BX), X9, X11           // c461337d1b or c5337d1b
+	//TODO: VHSUBPS (R11), X9, X11          // c441337d1b
+	//TODO: VHSUBPS X2, X9, X11             // c461337dda or c5337dda
+	//TODO: VHSUBPS X11, X9, X11            // c441337ddb
+	//TODO: VHSUBPS (BX), Y15, Y2           // c4e1077d13 or c5877d13
+	//TODO: VHSUBPS (R11), Y15, Y2          // c4c1077d13
+	//TODO: VHSUBPS Y2, Y15, Y2             // c4e1077dd2 or c5877dd2
+	//TODO: VHSUBPS Y11, Y15, Y2            // c4c1077dd3
+	//TODO: VHSUBPS (BX), Y15, Y11          // c461077d1b or c5077d1b
+	//TODO: VHSUBPS (R11), Y15, Y11         // c441077d1b
+	//TODO: VHSUBPS Y2, Y15, Y11            // c461077dda or c5077dda
+	//TODO: VHSUBPS Y11, Y15, Y11           // c441077ddb
+	//TODO: VINSERTF128 $7, (BX), Y15, Y2   // c4e305181307
+	//TODO: VINSERTF128 $7, (R11), Y15, Y2  // c4c305181307
+	//TODO: VINSERTF128 $7, X2, Y15, Y2     // c4e30518d207
+	//TODO: VINSERTF128 $7, X11, Y15, Y2    // c4c30518d307
+	//TODO: VINSERTF128 $7, (BX), Y15, Y11  // c46305181b07
+	//TODO: VINSERTF128 $7, (R11), Y15, Y11 // c44305181b07
+	//TODO: VINSERTF128 $7, X2, Y15, Y11    // c4630518da07
+	//TODO: VINSERTF128 $7, X11, Y15, Y11   // c4430518db07
+	//TODO: VINSERTI128 $7, (BX), Y15, Y2   // c4e305381307
+	//TODO: VINSERTI128 $7, (R11), Y15, Y2  // c4c305381307
+	//TODO: VINSERTI128 $7, X2, Y15, Y2     // c4e30538d207
+	//TODO: VINSERTI128 $7, X11, Y15, Y2    // c4c30538d307
+	//TODO: VINSERTI128 $7, (BX), Y15, Y11  // c46305381b07
+	//TODO: VINSERTI128 $7, (R11), Y15, Y11 // c44305381b07
+	//TODO: VINSERTI128 $7, X2, Y15, Y11    // c4630538da07
+	//TODO: VINSERTI128 $7, X11, Y15, Y11   // c4430538db07
+	//TODO: VINSERTPS $7, (BX), X9, X2      // c4e331211307
+	//TODO: VINSERTPS $7, (R11), X9, X2     // c4c331211307
+	//TODO: VINSERTPS $7, X2, X9, X2        // c4e33121d207
+	//TODO: VINSERTPS $7, X11, X9, X2       // c4c33121d307
+	//TODO: VINSERTPS $7, (BX), X9, X11     // c46331211b07
+	//TODO: VINSERTPS $7, (R11), X9, X11    // c44331211b07
+	//TODO: VINSERTPS $7, X2, X9, X11       // c4633121da07
+	//TODO: VINSERTPS $7, X11, X9, X11      // c4433121db07
+	//TODO: VLDDQU (BX), X2                 // c4e17bf013 or c5fbf013
+	//TODO: VLDDQU (R11), X2                // c4c17bf013
+	//TODO: VLDDQU (BX), X11                // c4617bf01b or c57bf01b
+	//TODO: VLDDQU (R11), X11               // c4417bf01b
+	//TODO: VLDDQU (BX), Y2                 // c4e17ff013 or c5fff013
+	//TODO: VLDDQU (R11), Y2                // c4c17ff013
+	//TODO: VLDDQU (BX), Y11                // c4617ff01b or c57ff01b
+	//TODO: VLDDQU (R11), Y11               // c4417ff01b
+	//TODO: VLDMXCSR (BX)                   // c4e178ae13 or c5f8ae13
+	//TODO: VLDMXCSR (R11)                  // c4c178ae13
+	//TODO: VMASKMOVDQU X2, X2              // c4e179f7d2 or c5f9f7d2
+	//TODO: VMASKMOVDQU X11, X2             // c4c179f7d3
+	//TODO: VMASKMOVDQU X2, X11             // c46179f7da or c579f7da
+	//TODO: VMASKMOVDQU X11, X11            // c44179f7db
+	//TODO: VMASKMOVPD X2, X9, (BX)         // c4e2312f13
+	//TODO: VMASKMOVPD X11, X9, (BX)        // c462312f1b
+	//TODO: VMASKMOVPD X2, X9, (R11)        // c4c2312f13
+	//TODO: VMASKMOVPD X11, X9, (R11)       // c442312f1b
+	//TODO: VMASKMOVPD Y2, Y15, (BX)        // c4e2052f13
+	//TODO: VMASKMOVPD Y11, Y15, (BX)       // c462052f1b
+	//TODO: VMASKMOVPD Y2, Y15, (R11)       // c4c2052f13
+	//TODO: VMASKMOVPD Y11, Y15, (R11)      // c442052f1b
+	//TODO: VMASKMOVPD (BX), X9, X2         // c4e2312d13
+	//TODO: VMASKMOVPD (R11), X9, X2        // c4c2312d13
+	//TODO: VMASKMOVPD (BX), X9, X11        // c462312d1b
+	//TODO: VMASKMOVPD (R11), X9, X11       // c442312d1b
+	//TODO: VMASKMOVPD (BX), Y15, Y2        // c4e2052d13
+	//TODO: VMASKMOVPD (R11), Y15, Y2       // c4c2052d13
+	//TODO: VMASKMOVPD (BX), Y15, Y11       // c462052d1b
+	//TODO: VMASKMOVPD (R11), Y15, Y11      // c442052d1b
+	//TODO: VMASKMOVPS X2, X9, (BX)         // c4e2312e13
+	//TODO: VMASKMOVPS X11, X9, (BX)        // c462312e1b
+	//TODO: VMASKMOVPS X2, X9, (R11)        // c4c2312e13
+	//TODO: VMASKMOVPS X11, X9, (R11)       // c442312e1b
+	//TODO: VMASKMOVPS Y2, Y15, (BX)        // c4e2052e13
+	//TODO: VMASKMOVPS Y11, Y15, (BX)       // c462052e1b
+	//TODO: VMASKMOVPS Y2, Y15, (R11)       // c4c2052e13
+	//TODO: VMASKMOVPS Y11, Y15, (R11)      // c442052e1b
+	//TODO: VMASKMOVPS (BX), X9, X2         // c4e2312c13
+	//TODO: VMASKMOVPS (R11), X9, X2        // c4c2312c13
+	//TODO: VMASKMOVPS (BX), X9, X11        // c462312c1b
+	//TODO: VMASKMOVPS (R11), X9, X11       // c442312c1b
+	//TODO: VMASKMOVPS (BX), Y15, Y2        // c4e2052c13
+	//TODO: VMASKMOVPS (R11), Y15, Y2       // c4c2052c13
+	//TODO: VMASKMOVPS (BX), Y15, Y11       // c462052c1b
+	//TODO: VMASKMOVPS (R11), Y15, Y11      // c442052c1b
+	//TODO: VMAXPD (BX), X9, X2             // c4e1315f13 or c5b15f13
+	//TODO: VMAXPD (R11), X9, X2            // c4c1315f13
+	//TODO: VMAXPD X2, X9, X2               // c4e1315fd2 or c5b15fd2
+	//TODO: VMAXPD X11, X9, X2              // c4c1315fd3
+	//TODO: VMAXPD (BX), X9, X11            // c461315f1b or c5315f1b
+	//TODO: VMAXPD (R11), X9, X11           // c441315f1b
+	//TODO: VMAXPD X2, X9, X11              // c461315fda or c5315fda
+	//TODO: VMAXPD X11, X9, X11             // c441315fdb
+	//TODO: VMAXPD (BX), Y15, Y2            // c4e1055f13 or c5855f13
+	//TODO: VMAXPD (R11), Y15, Y2           // c4c1055f13
+	//TODO: VMAXPD Y2, Y15, Y2              // c4e1055fd2 or c5855fd2
+	//TODO: VMAXPD Y11, Y15, Y2             // c4c1055fd3
+	//TODO: VMAXPD (BX), Y15, Y11           // c461055f1b or c5055f1b
+	//TODO: VMAXPD (R11), Y15, Y11          // c441055f1b
+	//TODO: VMAXPD Y2, Y15, Y11             // c461055fda or c5055fda
+	//TODO: VMAXPD Y11, Y15, Y11            // c441055fdb
+	//TODO: VMAXPS (BX), X9, X2             // c4e1305f13 or c5b05f13
+	//TODO: VMAXPS (R11), X9, X2            // c4c1305f13
+	//TODO: VMAXPS X2, X9, X2               // c4e1305fd2 or c5b05fd2
+	//TODO: VMAXPS X11, X9, X2              // c4c1305fd3
+	//TODO: VMAXPS (BX), X9, X11            // c461305f1b or c5305f1b
+	//TODO: VMAXPS (R11), X9, X11           // c441305f1b
+	//TODO: VMAXPS X2, X9, X11              // c461305fda or c5305fda
+	//TODO: VMAXPS X11, X9, X11             // c441305fdb
+	//TODO: VMAXPS (BX), Y15, Y2            // c4e1045f13 or c5845f13
+	//TODO: VMAXPS (R11), Y15, Y2           // c4c1045f13
+	//TODO: VMAXPS Y2, Y15, Y2              // c4e1045fd2 or c5845fd2
+	//TODO: VMAXPS Y11, Y15, Y2             // c4c1045fd3
+	//TODO: VMAXPS (BX), Y15, Y11           // c461045f1b or c5045f1b
+	//TODO: VMAXPS (R11), Y15, Y11          // c441045f1b
+	//TODO: VMAXPS Y2, Y15, Y11             // c461045fda or c5045fda
+	//TODO: VMAXPS Y11, Y15, Y11            // c441045fdb
+	//TODO: VMAXSD (BX), X9, X2             // c4e1335f13 or c5b35f13
+	//TODO: VMAXSD (R11), X9, X2            // c4c1335f13
+	//TODO: VMAXSD X2, X9, X2               // c4e1335fd2 or c5b35fd2
+	//TODO: VMAXSD X11, X9, X2              // c4c1335fd3
+	//TODO: VMAXSD (BX), X9, X11            // c461335f1b or c5335f1b
+	//TODO: VMAXSD (R11), X9, X11           // c441335f1b
+	//TODO: VMAXSD X2, X9, X11              // c461335fda or c5335fda
+	//TODO: VMAXSD X11, X9, X11             // c441335fdb
+	//TODO: VMAXSS (BX), X9, X2             // c4e1325f13 or c5b25f13
+	//TODO: VMAXSS (R11), X9, X2            // c4c1325f13
+	//TODO: VMAXSS X2, X9, X2               // c4e1325fd2 or c5b25fd2
+	//TODO: VMAXSS X11, X9, X2              // c4c1325fd3
+	//TODO: VMAXSS (BX), X9, X11            // c461325f1b or c5325f1b
+	//TODO: VMAXSS (R11), X9, X11           // c441325f1b
+	//TODO: VMAXSS X2, X9, X11              // c461325fda or c5325fda
+	//TODO: VMAXSS X11, X9, X11             // c441325fdb
+	//TODO: VMINPD (BX), X9, X2             // c4e1315d13 or c5b15d13
+	//TODO: VMINPD (R11), X9, X2            // c4c1315d13
+	//TODO: VMINPD X2, X9, X2               // c4e1315dd2 or c5b15dd2
+	//TODO: VMINPD X11, X9, X2              // c4c1315dd3
+	//TODO: VMINPD (BX), X9, X11            // c461315d1b or c5315d1b
+	//TODO: VMINPD (R11), X9, X11           // c441315d1b
+	//TODO: VMINPD X2, X9, X11              // c461315dda or c5315dda
+	//TODO: VMINPD X11, X9, X11             // c441315ddb
+	//TODO: VMINPD (BX), Y15, Y2            // c4e1055d13 or c5855d13
+	//TODO: VMINPD (R11), Y15, Y2           // c4c1055d13
+	//TODO: VMINPD Y2, Y15, Y2              // c4e1055dd2 or c5855dd2
+	//TODO: VMINPD Y11, Y15, Y2             // c4c1055dd3
+	//TODO: VMINPD (BX), Y15, Y11           // c461055d1b or c5055d1b
+	//TODO: VMINPD (R11), Y15, Y11          // c441055d1b
+	//TODO: VMINPD Y2, Y15, Y11             // c461055dda or c5055dda
+	//TODO: VMINPD Y11, Y15, Y11            // c441055ddb
+	//TODO: VMINPS (BX), X9, X2             // c4e1305d13 or c5b05d13
+	//TODO: VMINPS (R11), X9, X2            // c4c1305d13
+	//TODO: VMINPS X2, X9, X2               // c4e1305dd2 or c5b05dd2
+	//TODO: VMINPS X11, X9, X2              // c4c1305dd3
+	//TODO: VMINPS (BX), X9, X11            // c461305d1b or c5305d1b
+	//TODO: VMINPS (R11), X9, X11           // c441305d1b
+	//TODO: VMINPS X2, X9, X11              // c461305dda or c5305dda
+	//TODO: VMINPS X11, X9, X11             // c441305ddb
+	//TODO: VMINPS (BX), Y15, Y2            // c4e1045d13 or c5845d13
+	//TODO: VMINPS (R11), Y15, Y2           // c4c1045d13
+	//TODO: VMINPS Y2, Y15, Y2              // c4e1045dd2 or c5845dd2
+	//TODO: VMINPS Y11, Y15, Y2             // c4c1045dd3
+	//TODO: VMINPS (BX), Y15, Y11           // c461045d1b or c5045d1b
+	//TODO: VMINPS (R11), Y15, Y11          // c441045d1b
+	//TODO: VMINPS Y2, Y15, Y11             // c461045dda or c5045dda
+	//TODO: VMINPS Y11, Y15, Y11            // c441045ddb
+	//TODO: VMINSD (BX), X9, X2             // c4e1335d13 or c5b35d13
+	//TODO: VMINSD (R11), X9, X2            // c4c1335d13
+	//TODO: VMINSD X2, X9, X2               // c4e1335dd2 or c5b35dd2
+	//TODO: VMINSD X11, X9, X2              // c4c1335dd3
+	//TODO: VMINSD (BX), X9, X11            // c461335d1b or c5335d1b
+	//TODO: VMINSD (R11), X9, X11           // c441335d1b
+	//TODO: VMINSD X2, X9, X11              // c461335dda or c5335dda
+	//TODO: VMINSD X11, X9, X11             // c441335ddb
+	//TODO: VMINSS (BX), X9, X2             // c4e1325d13 or c5b25d13
+	//TODO: VMINSS (R11), X9, X2            // c4c1325d13
+	//TODO: VMINSS X2, X9, X2               // c4e1325dd2 or c5b25dd2
+	//TODO: VMINSS X11, X9, X2              // c4c1325dd3
+	//TODO: VMINSS (BX), X9, X11            // c461325d1b or c5325d1b
+	//TODO: VMINSS (R11), X9, X11           // c441325d1b
+	//TODO: VMINSS X2, X9, X11              // c461325dda or c5325dda
+	//TODO: VMINSS X11, X9, X11             // c441325ddb
+	//TODO: VMOVAPD (BX), X2                // c4e1792813 or c5f92813
+	//TODO: VMOVAPD (R11), X2               // c4c1792813
+	//TODO: VMOVAPD X2, X2                  // c4e17928d2 or c5f928d2 or c4e17929d2 or c5f929d2
+	//TODO: VMOVAPD X11, X2                 // c4c17928d3 or c4617929da or c57929da
+	//TODO: VMOVAPD (BX), X11               // c46179281b or c579281b
+	//TODO: VMOVAPD (R11), X11              // c44179281b
+	//TODO: VMOVAPD X2, X11                 // c4617928da or c57928da or c4c17929d3
+	//TODO: VMOVAPD X11, X11                // c4417928db or c4417929db
+	//TODO: VMOVAPD X2, (BX)                // c4e1792913 or c5f92913
+	//TODO: VMOVAPD X11, (BX)               // c46179291b or c579291b
+	//TODO: VMOVAPD X2, (R11)               // c4c1792913
+	//TODO: VMOVAPD X11, (R11)              // c44179291b
+	//TODO: VMOVAPD (BX), Y2                // c4e17d2813 or c5fd2813
+	//TODO: VMOVAPD (R11), Y2               // c4c17d2813
+	//TODO: VMOVAPD Y2, Y2                  // c4e17d28d2 or c5fd28d2 or c4e17d29d2 or c5fd29d2
+	//TODO: VMOVAPD Y11, Y2                 // c4c17d28d3 or c4617d29da or c57d29da
+	//TODO: VMOVAPD (BX), Y11               // c4617d281b or c57d281b
+	//TODO: VMOVAPD (R11), Y11              // c4417d281b
+	//TODO: VMOVAPD Y2, Y11                 // c4617d28da or c57d28da or c4c17d29d3
+	//TODO: VMOVAPD Y11, Y11                // c4417d28db or c4417d29db
+	//TODO: VMOVAPD Y2, (BX)                // c4e17d2913 or c5fd2913
+	//TODO: VMOVAPD Y11, (BX)               // c4617d291b or c57d291b
+	//TODO: VMOVAPD Y2, (R11)               // c4c17d2913
+	//TODO: VMOVAPD Y11, (R11)              // c4417d291b
+	//TODO: VMOVAPS (BX), X2                // c4e1782813 or c5f82813
+	//TODO: VMOVAPS (R11), X2               // c4c1782813
+	//TODO: VMOVAPS X2, X2                  // c4e17828d2 or c5f828d2 or c4e17829d2 or c5f829d2
+	//TODO: VMOVAPS X11, X2                 // c4c17828d3 or c4617829da or c57829da
+	//TODO: VMOVAPS (BX), X11               // c46178281b or c578281b
+	//TODO: VMOVAPS (R11), X11              // c44178281b
+	//TODO: VMOVAPS X2, X11                 // c4617828da or c57828da or c4c17829d3
+	//TODO: VMOVAPS X11, X11                // c4417828db or c4417829db
+	//TODO: VMOVAPS X2, (BX)                // c4e1782913 or c5f82913
+	//TODO: VMOVAPS X11, (BX)               // c46178291b or c578291b
+	//TODO: VMOVAPS X2, (R11)               // c4c1782913
+	//TODO: VMOVAPS X11, (R11)              // c44178291b
+	//TODO: VMOVAPS (BX), Y2                // c4e17c2813 or c5fc2813
+	//TODO: VMOVAPS (R11), Y2               // c4c17c2813
+	//TODO: VMOVAPS Y2, Y2                  // c4e17c28d2 or c5fc28d2 or c4e17c29d2 or c5fc29d2
+	//TODO: VMOVAPS Y11, Y2                 // c4c17c28d3 or c4617c29da or c57c29da
+	//TODO: VMOVAPS (BX), Y11               // c4617c281b or c57c281b
+	//TODO: VMOVAPS (R11), Y11              // c4417c281b
+	//TODO: VMOVAPS Y2, Y11                 // c4617c28da or c57c28da or c4c17c29d3
+	//TODO: VMOVAPS Y11, Y11                // c4417c28db or c4417c29db
+	//TODO: VMOVAPS Y2, (BX)                // c4e17c2913 or c5fc2913
+	//TODO: VMOVAPS Y11, (BX)               // c4617c291b or c57c291b
+	//TODO: VMOVAPS Y2, (R11)               // c4c17c2913
+	//TODO: VMOVAPS Y11, (R11)              // c4417c291b
+	//TODO: VMOVD X2, (BX)                  // c4e1797e13 or c5f97e13
+	//TODO: VMOVD X11, (BX)                 // c461797e1b or c5797e1b
+	//TODO: VMOVD X2, (R11)                 // c4c1797e13
+	//TODO: VMOVD X11, (R11)                // c441797e1b
+	//TODO: VMOVD X2, DX                    // c4e1797ed2 or c5f97ed2
+	//TODO: VMOVD X11, DX                   // c461797eda or c5797eda
+	//TODO: VMOVD X2, R11                   // c4c1797ed3
+	//TODO: VMOVD X11, R11                  // c441797edb
+	//TODO: VMOVD (BX), X2                  // c4e1796e13 or c5f96e13
+	//TODO: VMOVD (R11), X2                 // c4c1796e13
+	//TODO: VMOVD DX, X2                    // c4e1796ed2 or c5f96ed2
+	//TODO: VMOVD R11, X2                   // c4c1796ed3
+	//TODO: VMOVD (BX), X11                 // c461796e1b or c5796e1b
+	//TODO: VMOVD (R11), X11                // c441796e1b
+	//TODO: VMOVD DX, X11                   // c461796eda or c5796eda
+	//TODO: VMOVD R11, X11                  // c441796edb
+	//TODO: VMOVDDUP (BX), X2               // c4e17b1213 or c5fb1213
+	//TODO: VMOVDDUP (R11), X2              // c4c17b1213
+	//TODO: VMOVDDUP X2, X2                 // c4e17b12d2 or c5fb12d2
+	//TODO: VMOVDDUP X11, X2                // c4c17b12d3
+	//TODO: VMOVDDUP (BX), X11              // c4617b121b or c57b121b
+	//TODO: VMOVDDUP (R11), X11             // c4417b121b
+	//TODO: VMOVDDUP X2, X11                // c4617b12da or c57b12da
+	//TODO: VMOVDDUP X11, X11               // c4417b12db
+	//TODO: VMOVDDUP (BX), Y2               // c4e17f1213 or c5ff1213
+	//TODO: VMOVDDUP (R11), Y2              // c4c17f1213
+	//TODO: VMOVDDUP Y2, Y2                 // c4e17f12d2 or c5ff12d2
+	//TODO: VMOVDDUP Y11, Y2                // c4c17f12d3
+	//TODO: VMOVDDUP (BX), Y11              // c4617f121b or c57f121b
+	//TODO: VMOVDDUP (R11), Y11             // c4417f121b
+	//TODO: VMOVDDUP Y2, Y11                // c4617f12da or c57f12da
+	//TODO: VMOVDDUP Y11, Y11               // c4417f12db
+	VMOVDQA (BX), X2                        // c4e1796f13 or c5f96f13
+	VMOVDQA (R11), X2                       // c4c1796f13
+	VMOVDQA X2, X2                          // c4e1796fd2 or c5f96fd2 or c4e1797fd2 or c5f97fd2
+	VMOVDQA X11, X2                         // c4c1796fd3 or c461797fda or c5797fda
+	VMOVDQA (BX), X11                       // c461796f1b or c5796f1b
+	VMOVDQA (R11), X11                      // c441796f1b
+	VMOVDQA X2, X11                         // c461796fda or c5796fda or c4c1797fd3
+	VMOVDQA X11, X11                        // c441796fdb or c441797fdb
+	VMOVDQA X2, (BX)                        // c4e1797f13 or c5f97f13
+	VMOVDQA X11, (BX)                       // c461797f1b or c5797f1b
+	VMOVDQA X2, (R11)                       // c4c1797f13
+	VMOVDQA X11, (R11)                      // c441797f1b
+	VMOVDQA (BX), Y2                        // c4e17d6f13 or c5fd6f13
+	VMOVDQA (R11), Y2                       // c4c17d6f13
+	VMOVDQA Y2, Y2                          // c4e17d6fd2 or c5fd6fd2 or c4e17d7fd2 or c5fd7fd2
+	VMOVDQA Y11, Y2                         // c4c17d6fd3 or c4617d7fda or c57d7fda
+	VMOVDQA (BX), Y11                       // c4617d6f1b or c57d6f1b
+	VMOVDQA (R11), Y11                      // c4417d6f1b
+	VMOVDQA Y2, Y11                         // c4617d6fda or c57d6fda or c4c17d7fd3
+	VMOVDQA Y11, Y11                        // c4417d6fdb or c4417d7fdb
+	VMOVDQA Y2, (BX)                        // c4e17d7f13 or c5fd7f13
+	VMOVDQA Y11, (BX)                       // c4617d7f1b or c57d7f1b
+	VMOVDQA Y2, (R11)                       // c4c17d7f13
+	VMOVDQA Y11, (R11)                      // c4417d7f1b
+	VMOVDQU (BX), X2                        // c4e17a6f13 or c5fa6f13
+	VMOVDQU (R11), X2                       // c4c17a6f13
+	VMOVDQU X2, X2                          // c4e17a6fd2 or c5fa6fd2 or c4e17a7fd2 or c5fa7fd2
+	VMOVDQU X11, X2                         // c4c17a6fd3 or c4617a7fda or c57a7fda
+	VMOVDQU (BX), X11                       // c4617a6f1b or c57a6f1b
+	VMOVDQU (R11), X11                      // c4417a6f1b
+	VMOVDQU X2, X11                         // c4617a6fda or c57a6fda or c4c17a7fd3
+	VMOVDQU X11, X11                        // c4417a6fdb or c4417a7fdb
+	VMOVDQU X2, (BX)                        // c4e17a7f13 or c5fa7f13
+	VMOVDQU X11, (BX)                       // c4617a7f1b or c57a7f1b
+	VMOVDQU X2, (R11)                       // c4c17a7f13
+	VMOVDQU X11, (R11)                      // c4417a7f1b
+	VMOVDQU (BX), Y2                        // c4e17e6f13 or c5fe6f13
+	VMOVDQU (R11), Y2                       // c4c17e6f13
+	VMOVDQU Y2, Y2                          // c4e17e6fd2 or c5fe6fd2 or c4e17e7fd2 or c5fe7fd2
+	VMOVDQU Y11, Y2                         // c4c17e6fd3 or c4617e7fda or c57e7fda
+	VMOVDQU (BX), Y11                       // c4617e6f1b or c57e6f1b
+	VMOVDQU (R11), Y11                      // c4417e6f1b
+	VMOVDQU Y2, Y11                         // c4617e6fda or c57e6fda or c4c17e7fd3
+	VMOVDQU Y11, Y11                        // c4417e6fdb or c4417e7fdb
+	VMOVDQU Y2, (BX)                        // c4e17e7f13 or c5fe7f13
+	VMOVDQU Y11, (BX)                       // c4617e7f1b or c57e7f1b
+	VMOVDQU Y2, (R11)                       // c4c17e7f13
+	VMOVDQU Y11, (R11)                      // c4417e7f1b
+	//TODO: VMOVHLPS X2, X9, X2             // c4e13012d2 or c5b012d2
+	//TODO: VMOVHLPS X11, X9, X2            // c4c13012d3
+	//TODO: VMOVHLPS X2, X9, X11            // c4613012da or c53012da
+	//TODO: VMOVHLPS X11, X9, X11           // c4413012db
+	//TODO: VMOVHPD X2, (BX)                // c4e1791713 or c5f91713
+	//TODO: VMOVHPD X11, (BX)               // c46179171b or c579171b
+	//TODO: VMOVHPD X2, (R11)               // c4c1791713
+	//TODO: VMOVHPD X11, (R11)              // c44179171b
+	//TODO: VMOVHPD (BX), X9, X2            // c4e1311613 or c5b11613
+	//TODO: VMOVHPD (R11), X9, X2           // c4c1311613
+	//TODO: VMOVHPD (BX), X9, X11           // c46131161b or c531161b
+	//TODO: VMOVHPD (R11), X9, X11          // c44131161b
+	//TODO: VMOVHPS X2, (BX)                // c4e1781713 or c5f81713
+	//TODO: VMOVHPS X11, (BX)               // c46178171b or c578171b
+	//TODO: VMOVHPS X2, (R11)               // c4c1781713
+	//TODO: VMOVHPS X11, (R11)              // c44178171b
+	//TODO: VMOVHPS (BX), X9, X2            // c4e1301613 or c5b01613
+	//TODO: VMOVHPS (R11), X9, X2           // c4c1301613
+	//TODO: VMOVHPS (BX), X9, X11           // c46130161b or c530161b
+	//TODO: VMOVHPS (R11), X9, X11          // c44130161b
+	//TODO: VMOVLHPS X2, X9, X2             // c4e13016d2 or c5b016d2
+	//TODO: VMOVLHPS X11, X9, X2            // c4c13016d3
+	//TODO: VMOVLHPS X2, X9, X11            // c4613016da or c53016da
+	//TODO: VMOVLHPS X11, X9, X11           // c4413016db
+	//TODO: VMOVLPD X2, (BX)                // c4e1791313 or c5f91313
+	//TODO: VMOVLPD X11, (BX)               // c46179131b or c579131b
+	//TODO: VMOVLPD X2, (R11)               // c4c1791313
+	//TODO: VMOVLPD X11, (R11)              // c44179131b
+	//TODO: VMOVLPD (BX), X9, X2            // c4e1311213 or c5b11213
+	//TODO: VMOVLPD (R11), X9, X2           // c4c1311213
+	//TODO: VMOVLPD (BX), X9, X11           // c46131121b or c531121b
+	//TODO: VMOVLPD (R11), X9, X11          // c44131121b
+	//TODO: VMOVLPS X2, (BX)                // c4e1781313 or c5f81313
+	//TODO: VMOVLPS X11, (BX)               // c46178131b or c578131b
+	//TODO: VMOVLPS X2, (R11)               // c4c1781313
+	//TODO: VMOVLPS X11, (R11)              // c44178131b
+	//TODO: VMOVLPS (BX), X9, X2            // c4e1301213 or c5b01213
+	//TODO: VMOVLPS (R11), X9, X2           // c4c1301213
+	//TODO: VMOVLPS (BX), X9, X11           // c46130121b or c530121b
+	//TODO: VMOVLPS (R11), X9, X11          // c44130121b
+	//TODO: VMOVMSKPD X2, DX                // c4e17950d2 or c5f950d2
+	//TODO: VMOVMSKPD X11, DX               // c4c17950d3
+	//TODO: VMOVMSKPD X2, R11               // c4617950da or c57950da
+	//TODO: VMOVMSKPD X11, R11              // c4417950db
+	//TODO: VMOVMSKPD Y2, DX                // c4e17d50d2 or c5fd50d2
+	//TODO: VMOVMSKPD Y11, DX               // c4c17d50d3
+	//TODO: VMOVMSKPD Y2, R11               // c4617d50da or c57d50da
+	//TODO: VMOVMSKPD Y11, R11              // c4417d50db
+	//TODO: VMOVMSKPS X2, DX                // c4e17850d2 or c5f850d2
+	//TODO: VMOVMSKPS X11, DX               // c4c17850d3
+	//TODO: VMOVMSKPS X2, R11               // c4617850da or c57850da
+	//TODO: VMOVMSKPS X11, R11              // c4417850db
+	//TODO: VMOVMSKPS Y2, DX                // c4e17c50d2 or c5fc50d2
+	//TODO: VMOVMSKPS Y11, DX               // c4c17c50d3
+	//TODO: VMOVMSKPS Y2, R11               // c4617c50da or c57c50da
+	//TODO: VMOVMSKPS Y11, R11              // c4417c50db
+	VMOVNTDQ X2, (BX)                       // c4e179e713 or c5f9e713
+	VMOVNTDQ X11, (BX)                      // c46179e71b or c579e71b
+	VMOVNTDQ X2, (R11)                      // c4c179e713
+	VMOVNTDQ X11, (R11)                     // c44179e71b
+	VMOVNTDQ Y2, (BX)                       // c4e17de713 or c5fde713
+	VMOVNTDQ Y11, (BX)                      // c4617de71b or c57de71b
+	VMOVNTDQ Y2, (R11)                      // c4c17de713
+	VMOVNTDQ Y11, (R11)                     // c4417de71b
+	//TODO: VMOVNTDQA (BX), X2              // c4e2792a13
+	//TODO: VMOVNTDQA (R11), X2             // c4c2792a13
+	//TODO: VMOVNTDQA (BX), X11             // c462792a1b
+	//TODO: VMOVNTDQA (R11), X11            // c442792a1b
+	//TODO: VMOVNTDQA (BX), Y2              // c4e27d2a13
+	//TODO: VMOVNTDQA (R11), Y2             // c4c27d2a13
+	//TODO: VMOVNTDQA (BX), Y11             // c4627d2a1b
+	//TODO: VMOVNTDQA (R11), Y11            // c4427d2a1b
+	//TODO: VMOVNTPD X2, (BX)               // c4e1792b13 or c5f92b13
+	//TODO: VMOVNTPD X11, (BX)              // c461792b1b or c5792b1b
+	//TODO: VMOVNTPD X2, (R11)              // c4c1792b13
+	//TODO: VMOVNTPD X11, (R11)             // c441792b1b
+	//TODO: VMOVNTPD Y2, (BX)               // c4e17d2b13 or c5fd2b13
+	//TODO: VMOVNTPD Y11, (BX)              // c4617d2b1b or c57d2b1b
+	//TODO: VMOVNTPD Y2, (R11)              // c4c17d2b13
+	//TODO: VMOVNTPD Y11, (R11)             // c4417d2b1b
+	//TODO: VMOVNTPS X2, (BX)               // c4e1782b13 or c5f82b13
+	//TODO: VMOVNTPS X11, (BX)              // c461782b1b or c5782b1b
+	//TODO: VMOVNTPS X2, (R11)              // c4c1782b13
+	//TODO: VMOVNTPS X11, (R11)             // c441782b1b
+	//TODO: VMOVNTPS Y2, (BX)               // c4e17c2b13 or c5fc2b13
+	//TODO: VMOVNTPS Y11, (BX)              // c4617c2b1b or c57c2b1b
+	//TODO: VMOVNTPS Y2, (R11)              // c4c17c2b13
+	//TODO: VMOVNTPS Y11, (R11)             // c4417c2b1b
+	//TODO: VMOVQ X2, (BX)                  // c4e1f97e13 or c4e179d613 or c5f9d613
+	//TODO: VMOVQ X11, (BX)                 // c461f97e1b or c46179d61b or c579d61b
+	//TODO: VMOVQ X2, (R11)                 // c4c1f97e13 or c4c179d613
+	//TODO: VMOVQ X11, (R11)                // c441f97e1b or c44179d61b
+	//TODO: VMOVQ X2, DX                    // c4e1f97ed2
+	//TODO: VMOVQ X11, DX                   // c461f97eda
+	//TODO: VMOVQ X2, R11                   // c4c1f97ed3
+	//TODO: VMOVQ X11, R11                  // c441f97edb
+	//TODO: VMOVQ (BX), X2                  // c4e17a7e13 or c5fa7e13 or c4e1f96e13
+	//TODO: VMOVQ (R11), X2                 // c4c17a7e13 or c4c1f96e13
+	//TODO: VMOVQ (BX), X11                 // c4617a7e1b or c57a7e1b or c461f96e1b
+	//TODO: VMOVQ (R11), X11                // c4417a7e1b or c441f96e1b
+	//TODO: VMOVQ DX, X2                    // c4e1f96ed2
+	//TODO: VMOVQ R11, X2                   // c4c1f96ed3
+	//TODO: VMOVQ DX, X11                   // c461f96eda
+	//TODO: VMOVQ R11, X11                  // c441f96edb
+	//TODO: VMOVQ X2, X2                    // c4e17a7ed2 or c5fa7ed2 or c4e179d6d2 or c5f9d6d2
+	//TODO: VMOVQ X11, X2                   // c4c17a7ed3 or c46179d6da or c579d6da
+	//TODO: VMOVQ X2, X11                   // c4617a7eda or c57a7eda or c4c179d6d3
+	//TODO: VMOVQ X11, X11                  // c4417a7edb or c44179d6db
+	//TODO: VMOVSD X2, (BX)                 // c4e17b1113 or c5fb1113
+	//TODO: VMOVSD X11, (BX)                // c4617b111b or c57b111b
+	//TODO: VMOVSD X2, (R11)                // c4c17b1113
+	//TODO: VMOVSD X11, (R11)               // c4417b111b
+	//TODO: VMOVSD (BX), X2                 // c4e17b1013 or c5fb1013
+	//TODO: VMOVSD (R11), X2                // c4c17b1013
+	//TODO: VMOVSD (BX), X11                // c4617b101b or c57b101b
+	//TODO: VMOVSD (R11), X11               // c4417b101b
+	//TODO: VMOVSD X2, X9, X2               // c4e13310d2 or c5b310d2 or c4e13311d2 or c5b311d2
+	//TODO: VMOVSD X11, X9, X2              // c4c13310d3 or c4613311da or c53311da
+	//TODO: VMOVSD X2, X9, X11              // c4613310da or c53310da or c4c13311d3
+	//TODO: VMOVSD X11, X9, X11             // c4413310db or c4413311db
+	//TODO: VMOVSHDUP (BX), X2              // c4e17a1613 or c5fa1613
+	//TODO: VMOVSHDUP (R11), X2             // c4c17a1613
+	//TODO: VMOVSHDUP X2, X2                // c4e17a16d2 or c5fa16d2
+	//TODO: VMOVSHDUP X11, X2               // c4c17a16d3
+	//TODO: VMOVSHDUP (BX), X11             // c4617a161b or c57a161b
+	//TODO: VMOVSHDUP (R11), X11            // c4417a161b
+	//TODO: VMOVSHDUP X2, X11               // c4617a16da or c57a16da
+	//TODO: VMOVSHDUP X11, X11              // c4417a16db
+	//TODO: VMOVSHDUP (BX), Y2              // c4e17e1613 or c5fe1613
+	//TODO: VMOVSHDUP (R11), Y2             // c4c17e1613
+	//TODO: VMOVSHDUP Y2, Y2                // c4e17e16d2 or c5fe16d2
+	//TODO: VMOVSHDUP Y11, Y2               // c4c17e16d3
+	//TODO: VMOVSHDUP (BX), Y11             // c4617e161b or c57e161b
+	//TODO: VMOVSHDUP (R11), Y11            // c4417e161b
+	//TODO: VMOVSHDUP Y2, Y11               // c4617e16da or c57e16da
+	//TODO: VMOVSHDUP Y11, Y11              // c4417e16db
+	//TODO: VMOVSLDUP (BX), X2              // c4e17a1213 or c5fa1213
+	//TODO: VMOVSLDUP (R11), X2             // c4c17a1213
+	//TODO: VMOVSLDUP X2, X2                // c4e17a12d2 or c5fa12d2
+	//TODO: VMOVSLDUP X11, X2               // c4c17a12d3
+	//TODO: VMOVSLDUP (BX), X11             // c4617a121b or c57a121b
+	//TODO: VMOVSLDUP (R11), X11            // c4417a121b
+	//TODO: VMOVSLDUP X2, X11               // c4617a12da or c57a12da
+	//TODO: VMOVSLDUP X11, X11              // c4417a12db
+	//TODO: VMOVSLDUP (BX), Y2              // c4e17e1213 or c5fe1213
+	//TODO: VMOVSLDUP (R11), Y2             // c4c17e1213
+	//TODO: VMOVSLDUP Y2, Y2                // c4e17e12d2 or c5fe12d2
+	//TODO: VMOVSLDUP Y11, Y2               // c4c17e12d3
+	//TODO: VMOVSLDUP (BX), Y11             // c4617e121b or c57e121b
+	//TODO: VMOVSLDUP (R11), Y11            // c4417e121b
+	//TODO: VMOVSLDUP Y2, Y11               // c4617e12da or c57e12da
+	//TODO: VMOVSLDUP Y11, Y11              // c4417e12db
+	//TODO: VMOVSS X2, (BX)                 // c4e17a1113 or c5fa1113
+	//TODO: VMOVSS X11, (BX)                // c4617a111b or c57a111b
+	//TODO: VMOVSS X2, (R11)                // c4c17a1113
+	//TODO: VMOVSS X11, (R11)               // c4417a111b
+	//TODO: VMOVSS (BX), X2                 // c4e17a1013 or c5fa1013
+	//TODO: VMOVSS (R11), X2                // c4c17a1013
+	//TODO: VMOVSS (BX), X11                // c4617a101b or c57a101b
+	//TODO: VMOVSS (R11), X11               // c4417a101b
+	//TODO: VMOVSS X2, X9, X2               // c4e13210d2 or c5b210d2 or c4e13211d2 or c5b211d2
+	//TODO: VMOVSS X11, X9, X2              // c4c13210d3 or c4613211da or c53211da
+	//TODO: VMOVSS X2, X9, X11              // c4613210da or c53210da or c4c13211d3
+	//TODO: VMOVSS X11, X9, X11             // c4413210db or c4413211db
+	//TODO: VMOVUPD (BX), X2                // c4e1791013 or c5f91013
+	//TODO: VMOVUPD (R11), X2               // c4c1791013
+	//TODO: VMOVUPD X2, X2                  // c4e17910d2 or c5f910d2 or c4e17911d2 or c5f911d2
+	//TODO: VMOVUPD X11, X2                 // c4c17910d3 or c4617911da or c57911da
+	//TODO: VMOVUPD (BX), X11               // c46179101b or c579101b
+	//TODO: VMOVUPD (R11), X11              // c44179101b
+	//TODO: VMOVUPD X2, X11                 // c4617910da or c57910da or c4c17911d3
+	//TODO: VMOVUPD X11, X11                // c4417910db or c4417911db
+	//TODO: VMOVUPD X2, (BX)                // c4e1791113 or c5f91113
+	//TODO: VMOVUPD X11, (BX)               // c46179111b or c579111b
+	//TODO: VMOVUPD X2, (R11)               // c4c1791113
+	//TODO: VMOVUPD X11, (R11)              // c44179111b
+	//TODO: VMOVUPD (BX), Y2                // c4e17d1013 or c5fd1013
+	//TODO: VMOVUPD (R11), Y2               // c4c17d1013
+	//TODO: VMOVUPD Y2, Y2                  // c4e17d10d2 or c5fd10d2 or c4e17d11d2 or c5fd11d2
+	//TODO: VMOVUPD Y11, Y2                 // c4c17d10d3 or c4617d11da or c57d11da
+	//TODO: VMOVUPD (BX), Y11               // c4617d101b or c57d101b
+	//TODO: VMOVUPD (R11), Y11              // c4417d101b
+	//TODO: VMOVUPD Y2, Y11                 // c4617d10da or c57d10da or c4c17d11d3
+	//TODO: VMOVUPD Y11, Y11                // c4417d10db or c4417d11db
+	//TODO: VMOVUPD Y2, (BX)                // c4e17d1113 or c5fd1113
+	//TODO: VMOVUPD Y11, (BX)               // c4617d111b or c57d111b
+	//TODO: VMOVUPD Y2, (R11)               // c4c17d1113
+	//TODO: VMOVUPD Y11, (R11)              // c4417d111b
+	//TODO: VMOVUPS (BX), X2                // c4e1781013 or c5f81013
+	//TODO: VMOVUPS (R11), X2               // c4c1781013
+	//TODO: VMOVUPS X2, X2                  // c4e17810d2 or c5f810d2 or c4e17811d2 or c5f811d2
+	//TODO: VMOVUPS X11, X2                 // c4c17810d3 or c4617811da or c57811da
+	//TODO: VMOVUPS (BX), X11               // c46178101b or c578101b
+	//TODO: VMOVUPS (R11), X11              // c44178101b
+	//TODO: VMOVUPS X2, X11                 // c4617810da or c57810da or c4c17811d3
+	//TODO: VMOVUPS X11, X11                // c4417810db or c4417811db
+	//TODO: VMOVUPS X2, (BX)                // c4e1781113 or c5f81113
+	//TODO: VMOVUPS X11, (BX)               // c46178111b or c578111b
+	//TODO: VMOVUPS X2, (R11)               // c4c1781113
+	//TODO: VMOVUPS X11, (R11)              // c44178111b
+	//TODO: VMOVUPS (BX), Y2                // c4e17c1013 or c5fc1013
+	//TODO: VMOVUPS (R11), Y2               // c4c17c1013
+	//TODO: VMOVUPS Y2, Y2                  // c4e17c10d2 or c5fc10d2 or c4e17c11d2 or c5fc11d2
+	//TODO: VMOVUPS Y11, Y2                 // c4c17c10d3 or c4617c11da or c57c11da
+	//TODO: VMOVUPS (BX), Y11               // c4617c101b or c57c101b
+	//TODO: VMOVUPS (R11), Y11              // c4417c101b
+	//TODO: VMOVUPS Y2, Y11                 // c4617c10da or c57c10da or c4c17c11d3
+	//TODO: VMOVUPS Y11, Y11                // c4417c10db or c4417c11db
+	//TODO: VMOVUPS Y2, (BX)                // c4e17c1113 or c5fc1113
+	//TODO: VMOVUPS Y11, (BX)               // c4617c111b or c57c111b
+	//TODO: VMOVUPS Y2, (R11)               // c4c17c1113
+	//TODO: VMOVUPS Y11, (R11)              // c4417c111b
+	//TODO: VMPSADBW $7, (BX), X9, X2       // c4e331421307
+	//TODO: VMPSADBW $7, (R11), X9, X2      // c4c331421307
+	//TODO: VMPSADBW $7, X2, X9, X2         // c4e33142d207
+	//TODO: VMPSADBW $7, X11, X9, X2        // c4c33142d307
+	//TODO: VMPSADBW $7, (BX), X9, X11      // c46331421b07
+	//TODO: VMPSADBW $7, (R11), X9, X11     // c44331421b07
+	//TODO: VMPSADBW $7, X2, X9, X11        // c4633142da07
+	//TODO: VMPSADBW $7, X11, X9, X11       // c4433142db07
+	//TODO: VMPSADBW $7, (BX), Y15, Y2      // c4e305421307
+	//TODO: VMPSADBW $7, (R11), Y15, Y2     // c4c305421307
+	//TODO: VMPSADBW $7, Y2, Y15, Y2        // c4e30542d207
+	//TODO: VMPSADBW $7, Y11, Y15, Y2       // c4c30542d307
+	//TODO: VMPSADBW $7, (BX), Y15, Y11     // c46305421b07
+	//TODO: VMPSADBW $7, (R11), Y15, Y11    // c44305421b07
+	//TODO: VMPSADBW $7, Y2, Y15, Y11       // c4630542da07
+	//TODO: VMPSADBW $7, Y11, Y15, Y11      // c4430542db07
+	//TODO: VMULPD (BX), X9, X2             // c4e1315913 or c5b15913
+	//TODO: VMULPD (R11), X9, X2            // c4c1315913
+	//TODO: VMULPD X2, X9, X2               // c4e13159d2 or c5b159d2
+	//TODO: VMULPD X11, X9, X2              // c4c13159d3
+	//TODO: VMULPD (BX), X9, X11            // c46131591b or c531591b
+	//TODO: VMULPD (R11), X9, X11           // c44131591b
+	//TODO: VMULPD X2, X9, X11              // c4613159da or c53159da
+	//TODO: VMULPD X11, X9, X11             // c4413159db
+	//TODO: VMULPD (BX), Y15, Y2            // c4e1055913 or c5855913
+	//TODO: VMULPD (R11), Y15, Y2           // c4c1055913
+	//TODO: VMULPD Y2, Y15, Y2              // c4e10559d2 or c58559d2
+	//TODO: VMULPD Y11, Y15, Y2             // c4c10559d3
+	//TODO: VMULPD (BX), Y15, Y11           // c46105591b or c505591b
+	//TODO: VMULPD (R11), Y15, Y11          // c44105591b
+	//TODO: VMULPD Y2, Y15, Y11             // c4610559da or c50559da
+	//TODO: VMULPD Y11, Y15, Y11            // c4410559db
+	//TODO: VMULPS (BX), X9, X2             // c4e1305913 or c5b05913
+	//TODO: VMULPS (R11), X9, X2            // c4c1305913
+	//TODO: VMULPS X2, X9, X2               // c4e13059d2 or c5b059d2
+	//TODO: VMULPS X11, X9, X2              // c4c13059d3
+	//TODO: VMULPS (BX), X9, X11            // c46130591b or c530591b
+	//TODO: VMULPS (R11), X9, X11           // c44130591b
+	//TODO: VMULPS X2, X9, X11              // c4613059da or c53059da
+	//TODO: VMULPS X11, X9, X11             // c4413059db
+	//TODO: VMULPS (BX), Y15, Y2            // c4e1045913 or c5845913
+	//TODO: VMULPS (R11), Y15, Y2           // c4c1045913
+	//TODO: VMULPS Y2, Y15, Y2              // c4e10459d2 or c58459d2
+	//TODO: VMULPS Y11, Y15, Y2             // c4c10459d3
+	//TODO: VMULPS (BX), Y15, Y11           // c46104591b or c504591b
+	//TODO: VMULPS (R11), Y15, Y11          // c44104591b
+	//TODO: VMULPS Y2, Y15, Y11             // c4610459da or c50459da
+	//TODO: VMULPS Y11, Y15, Y11            // c4410459db
+	//TODO: VMULSD (BX), X9, X2             // c4e1335913 or c5b35913
+	//TODO: VMULSD (R11), X9, X2            // c4c1335913
+	//TODO: VMULSD X2, X9, X2               // c4e13359d2 or c5b359d2
+	//TODO: VMULSD X11, X9, X2              // c4c13359d3
+	//TODO: VMULSD (BX), X9, X11            // c46133591b or c533591b
+	//TODO: VMULSD (R11), X9, X11           // c44133591b
+	//TODO: VMULSD X2, X9, X11              // c4613359da or c53359da
+	//TODO: VMULSD X11, X9, X11             // c4413359db
+	//TODO: VMULSS (BX), X9, X2             // c4e1325913 or c5b25913
+	//TODO: VMULSS (R11), X9, X2            // c4c1325913
+	//TODO: VMULSS X2, X9, X2               // c4e13259d2 or c5b259d2
+	//TODO: VMULSS X11, X9, X2              // c4c13259d3
+	//TODO: VMULSS (BX), X9, X11            // c46132591b or c532591b
+	//TODO: VMULSS (R11), X9, X11           // c44132591b
+	//TODO: VMULSS X2, X9, X11              // c4613259da or c53259da
+	//TODO: VMULSS X11, X9, X11             // c4413259db
+	//TODO: VORPD (BX), X9, X2              // c4e1315613 or c5b15613
+	//TODO: VORPD (R11), X9, X2             // c4c1315613
+	//TODO: VORPD X2, X9, X2                // c4e13156d2 or c5b156d2
+	//TODO: VORPD X11, X9, X2               // c4c13156d3
+	//TODO: VORPD (BX), X9, X11             // c46131561b or c531561b
+	//TODO: VORPD (R11), X9, X11            // c44131561b
+	//TODO: VORPD X2, X9, X11               // c4613156da or c53156da
+	//TODO: VORPD X11, X9, X11              // c4413156db
+	//TODO: VORPD (BX), Y15, Y2             // c4e1055613 or c5855613
+	//TODO: VORPD (R11), Y15, Y2            // c4c1055613
+	//TODO: VORPD Y2, Y15, Y2               // c4e10556d2 or c58556d2
+	//TODO: VORPD Y11, Y15, Y2              // c4c10556d3
+	//TODO: VORPD (BX), Y15, Y11            // c46105561b or c505561b
+	//TODO: VORPD (R11), Y15, Y11           // c44105561b
+	//TODO: VORPD Y2, Y15, Y11              // c4610556da or c50556da
+	//TODO: VORPD Y11, Y15, Y11             // c4410556db
+	//TODO: VORPS (BX), X9, X2              // c4e1305613 or c5b05613
+	//TODO: VORPS (R11), X9, X2             // c4c1305613
+	//TODO: VORPS X2, X9, X2                // c4e13056d2 or c5b056d2
+	//TODO: VORPS X11, X9, X2               // c4c13056d3
+	//TODO: VORPS (BX), X9, X11             // c46130561b or c530561b
+	//TODO: VORPS (R11), X9, X11            // c44130561b
+	//TODO: VORPS X2, X9, X11               // c4613056da or c53056da
+	//TODO: VORPS X11, X9, X11              // c4413056db
+	//TODO: VORPS (BX), Y15, Y2             // c4e1045613 or c5845613
+	//TODO: VORPS (R11), Y15, Y2            // c4c1045613
+	//TODO: VORPS Y2, Y15, Y2               // c4e10456d2 or c58456d2
+	//TODO: VORPS Y11, Y15, Y2              // c4c10456d3
+	//TODO: VORPS (BX), Y15, Y11            // c46104561b or c504561b
+	//TODO: VORPS (R11), Y15, Y11           // c44104561b
+	//TODO: VORPS Y2, Y15, Y11              // c4610456da or c50456da
+	//TODO: VORPS Y11, Y15, Y11             // c4410456db
+	//TODO: VPABSB (BX), X2                 // c4e2791c13
+	//TODO: VPABSB (R11), X2                // c4c2791c13
+	//TODO: VPABSB X2, X2                   // c4e2791cd2
+	//TODO: VPABSB X11, X2                  // c4c2791cd3
+	//TODO: VPABSB (BX), X11                // c462791c1b
+	//TODO: VPABSB (R11), X11               // c442791c1b
+	//TODO: VPABSB X2, X11                  // c462791cda
+	//TODO: VPABSB X11, X11                 // c442791cdb
+	//TODO: VPABSB (BX), Y2                 // c4e27d1c13
+	//TODO: VPABSB (R11), Y2                // c4c27d1c13
+	//TODO: VPABSB Y2, Y2                   // c4e27d1cd2
+	//TODO: VPABSB Y11, Y2                  // c4c27d1cd3
+	//TODO: VPABSB (BX), Y11                // c4627d1c1b
+	//TODO: VPABSB (R11), Y11               // c4427d1c1b
+	//TODO: VPABSB Y2, Y11                  // c4627d1cda
+	//TODO: VPABSB Y11, Y11                 // c4427d1cdb
+	//TODO: VPABSD (BX), X2                 // c4e2791e13
+	//TODO: VPABSD (R11), X2                // c4c2791e13
+	//TODO: VPABSD X2, X2                   // c4e2791ed2
+	//TODO: VPABSD X11, X2                  // c4c2791ed3
+	//TODO: VPABSD (BX), X11                // c462791e1b
+	//TODO: VPABSD (R11), X11               // c442791e1b
+	//TODO: VPABSD X2, X11                  // c462791eda
+	//TODO: VPABSD X11, X11                 // c442791edb
+	//TODO: VPABSD (BX), Y2                 // c4e27d1e13
+	//TODO: VPABSD (R11), Y2                // c4c27d1e13
+	//TODO: VPABSD Y2, Y2                   // c4e27d1ed2
+	//TODO: VPABSD Y11, Y2                  // c4c27d1ed3
+	//TODO: VPABSD (BX), Y11                // c4627d1e1b
+	//TODO: VPABSD (R11), Y11               // c4427d1e1b
+	//TODO: VPABSD Y2, Y11                  // c4627d1eda
+	//TODO: VPABSD Y11, Y11                 // c4427d1edb
+	//TODO: VPABSW (BX), X2                 // c4e2791d13
+	//TODO: VPABSW (R11), X2                // c4c2791d13
+	//TODO: VPABSW X2, X2                   // c4e2791dd2
+	//TODO: VPABSW X11, X2                  // c4c2791dd3
+	//TODO: VPABSW (BX), X11                // c462791d1b
+	//TODO: VPABSW (R11), X11               // c442791d1b
+	//TODO: VPABSW X2, X11                  // c462791dda
+	//TODO: VPABSW X11, X11                 // c442791ddb
+	//TODO: VPABSW (BX), Y2                 // c4e27d1d13
+	//TODO: VPABSW (R11), Y2                // c4c27d1d13
+	//TODO: VPABSW Y2, Y2                   // c4e27d1dd2
+	//TODO: VPABSW Y11, Y2                  // c4c27d1dd3
+	//TODO: VPABSW (BX), Y11                // c4627d1d1b
+	//TODO: VPABSW (R11), Y11               // c4427d1d1b
+	//TODO: VPABSW Y2, Y11                  // c4627d1dda
+	//TODO: VPABSW Y11, Y11                 // c4427d1ddb
+	//TODO: VPACKSSDW (BX), X9, X2          // c4e1316b13 or c5b16b13
+	//TODO: VPACKSSDW (R11), X9, X2         // c4c1316b13
+	//TODO: VPACKSSDW X2, X9, X2            // c4e1316bd2 or c5b16bd2
+	//TODO: VPACKSSDW X11, X9, X2           // c4c1316bd3
+	//TODO: VPACKSSDW (BX), X9, X11         // c461316b1b or c5316b1b
+	//TODO: VPACKSSDW (R11), X9, X11        // c441316b1b
+	//TODO: VPACKSSDW X2, X9, X11           // c461316bda or c5316bda
+	//TODO: VPACKSSDW X11, X9, X11          // c441316bdb
+	//TODO: VPACKSSDW (BX), Y15, Y2         // c4e1056b13 or c5856b13
+	//TODO: VPACKSSDW (R11), Y15, Y2        // c4c1056b13
+	//TODO: VPACKSSDW Y2, Y15, Y2           // c4e1056bd2 or c5856bd2
+	//TODO: VPACKSSDW Y11, Y15, Y2          // c4c1056bd3
+	//TODO: VPACKSSDW (BX), Y15, Y11        // c461056b1b or c5056b1b
+	//TODO: VPACKSSDW (R11), Y15, Y11       // c441056b1b
+	//TODO: VPACKSSDW Y2, Y15, Y11          // c461056bda or c5056bda
+	//TODO: VPACKSSDW Y11, Y15, Y11         // c441056bdb
+	//TODO: VPACKSSWB (BX), X9, X2          // c4e1316313 or c5b16313
+	//TODO: VPACKSSWB (R11), X9, X2         // c4c1316313
+	//TODO: VPACKSSWB X2, X9, X2            // c4e13163d2 or c5b163d2
+	//TODO: VPACKSSWB X11, X9, X2           // c4c13163d3
+	//TODO: VPACKSSWB (BX), X9, X11         // c46131631b or c531631b
+	//TODO: VPACKSSWB (R11), X9, X11        // c44131631b
+	//TODO: VPACKSSWB X2, X9, X11           // c4613163da or c53163da
+	//TODO: VPACKSSWB X11, X9, X11          // c4413163db
+	//TODO: VPACKSSWB (BX), Y15, Y2         // c4e1056313 or c5856313
+	//TODO: VPACKSSWB (R11), Y15, Y2        // c4c1056313
+	//TODO: VPACKSSWB Y2, Y15, Y2           // c4e10563d2 or c58563d2
+	//TODO: VPACKSSWB Y11, Y15, Y2          // c4c10563d3
+	//TODO: VPACKSSWB (BX), Y15, Y11        // c46105631b or c505631b
+	//TODO: VPACKSSWB (R11), Y15, Y11       // c44105631b
+	//TODO: VPACKSSWB Y2, Y15, Y11          // c4610563da or c50563da
+	//TODO: VPACKSSWB Y11, Y15, Y11         // c4410563db
+	//TODO: VPACKUSDW (BX), X9, X2          // c4e2312b13
+	//TODO: VPACKUSDW (R11), X9, X2         // c4c2312b13
+	//TODO: VPACKUSDW X2, X9, X2            // c4e2312bd2
+	//TODO: VPACKUSDW X11, X9, X2           // c4c2312bd3
+	//TODO: VPACKUSDW (BX), X9, X11         // c462312b1b
+	//TODO: VPACKUSDW (R11), X9, X11        // c442312b1b
+	//TODO: VPACKUSDW X2, X9, X11           // c462312bda
+	//TODO: VPACKUSDW X11, X9, X11          // c442312bdb
+	//TODO: VPACKUSDW (BX), Y15, Y2         // c4e2052b13
+	//TODO: VPACKUSDW (R11), Y15, Y2        // c4c2052b13
+	//TODO: VPACKUSDW Y2, Y15, Y2           // c4e2052bd2
+	//TODO: VPACKUSDW Y11, Y15, Y2          // c4c2052bd3
+	//TODO: VPACKUSDW (BX), Y15, Y11        // c462052b1b
+	//TODO: VPACKUSDW (R11), Y15, Y11       // c442052b1b
+	//TODO: VPACKUSDW Y2, Y15, Y11          // c462052bda
+	//TODO: VPACKUSDW Y11, Y15, Y11         // c442052bdb
+	//TODO: VPACKUSWB (BX), X9, X2          // c4e1316713 or c5b16713
+	//TODO: VPACKUSWB (R11), X9, X2         // c4c1316713
+	//TODO: VPACKUSWB X2, X9, X2            // c4e13167d2 or c5b167d2
+	//TODO: VPACKUSWB X11, X9, X2           // c4c13167d3
+	//TODO: VPACKUSWB (BX), X9, X11         // c46131671b or c531671b
+	//TODO: VPACKUSWB (R11), X9, X11        // c44131671b
+	//TODO: VPACKUSWB X2, X9, X11           // c4613167da or c53167da
+	//TODO: VPACKUSWB X11, X9, X11          // c4413167db
+	//TODO: VPACKUSWB (BX), Y15, Y2         // c4e1056713 or c5856713
+	//TODO: VPACKUSWB (R11), Y15, Y2        // c4c1056713
+	//TODO: VPACKUSWB Y2, Y15, Y2           // c4e10567d2 or c58567d2
+	//TODO: VPACKUSWB Y11, Y15, Y2          // c4c10567d3
+	//TODO: VPACKUSWB (BX), Y15, Y11        // c46105671b or c505671b
+	//TODO: VPACKUSWB (R11), Y15, Y11       // c44105671b
+	//TODO: VPACKUSWB Y2, Y15, Y11          // c4610567da or c50567da
+	//TODO: VPACKUSWB Y11, Y15, Y11         // c4410567db
+	//TODO: VPADDB (BX), X9, X2             // c4e131fc13 or c5b1fc13
+	//TODO: VPADDB (R11), X9, X2            // c4c131fc13
+	//TODO: VPADDB X2, X9, X2               // c4e131fcd2 or c5b1fcd2
+	//TODO: VPADDB X11, X9, X2              // c4c131fcd3
+	//TODO: VPADDB (BX), X9, X11            // c46131fc1b or c531fc1b
+	//TODO: VPADDB (R11), X9, X11           // c44131fc1b
+	//TODO: VPADDB X2, X9, X11              // c46131fcda or c531fcda
+	//TODO: VPADDB X11, X9, X11             // c44131fcdb
+	//TODO: VPADDB (BX), Y15, Y2            // c4e105fc13 or c585fc13
+	//TODO: VPADDB (R11), Y15, Y2           // c4c105fc13
+	//TODO: VPADDB Y2, Y15, Y2              // c4e105fcd2 or c585fcd2
+	//TODO: VPADDB Y11, Y15, Y2             // c4c105fcd3
+	//TODO: VPADDB (BX), Y15, Y11           // c46105fc1b or c505fc1b
+	//TODO: VPADDB (R11), Y15, Y11          // c44105fc1b
+	//TODO: VPADDB Y2, Y15, Y11             // c46105fcda or c505fcda
+	//TODO: VPADDB Y11, Y15, Y11            // c44105fcdb
+	//TODO: VPADDD (BX), X9, X2             // c4e131fe13 or c5b1fe13
+	//TODO: VPADDD (R11), X9, X2            // c4c131fe13
+	//TODO: VPADDD X2, X9, X2               // c4e131fed2 or c5b1fed2
+	//TODO: VPADDD X11, X9, X2              // c4c131fed3
+	//TODO: VPADDD (BX), X9, X11            // c46131fe1b or c531fe1b
+	//TODO: VPADDD (R11), X9, X11           // c44131fe1b
+	//TODO: VPADDD X2, X9, X11              // c46131feda or c531feda
+	//TODO: VPADDD X11, X9, X11             // c44131fedb
+	//TODO: VPADDD (BX), Y15, Y2            // c4e105fe13 or c585fe13
+	//TODO: VPADDD (R11), Y15, Y2           // c4c105fe13
+	//TODO: VPADDD Y2, Y15, Y2              // c4e105fed2 or c585fed2
+	//TODO: VPADDD Y11, Y15, Y2             // c4c105fed3
+	//TODO: VPADDD (BX), Y15, Y11           // c46105fe1b or c505fe1b
+	//TODO: VPADDD (R11), Y15, Y11          // c44105fe1b
+	//TODO: VPADDD Y2, Y15, Y11             // c46105feda or c505feda
+	//TODO: VPADDD Y11, Y15, Y11            // c44105fedb
+	//TODO: VPADDQ (BX), X9, X2             // c4e131d413 or c5b1d413
+	//TODO: VPADDQ (R11), X9, X2            // c4c131d413
+	//TODO: VPADDQ X2, X9, X2               // c4e131d4d2 or c5b1d4d2
+	//TODO: VPADDQ X11, X9, X2              // c4c131d4d3
+	//TODO: VPADDQ (BX), X9, X11            // c46131d41b or c531d41b
+	//TODO: VPADDQ (R11), X9, X11           // c44131d41b
+	//TODO: VPADDQ X2, X9, X11              // c46131d4da or c531d4da
+	//TODO: VPADDQ X11, X9, X11             // c44131d4db
+	//TODO: VPADDQ (BX), Y15, Y2            // c4e105d413 or c585d413
+	//TODO: VPADDQ (R11), Y15, Y2           // c4c105d413
+	//TODO: VPADDQ Y2, Y15, Y2              // c4e105d4d2 or c585d4d2
+	//TODO: VPADDQ Y11, Y15, Y2             // c4c105d4d3
+	//TODO: VPADDQ (BX), Y15, Y11           // c46105d41b or c505d41b
+	//TODO: VPADDQ (R11), Y15, Y11          // c44105d41b
+	//TODO: VPADDQ Y2, Y15, Y11             // c46105d4da or c505d4da
+	//TODO: VPADDQ Y11, Y15, Y11            // c44105d4db
+	//TODO: VPADDSB (BX), X9, X2            // c4e131ec13 or c5b1ec13
+	//TODO: VPADDSB (R11), X9, X2           // c4c131ec13
+	//TODO: VPADDSB X2, X9, X2              // c4e131ecd2 or c5b1ecd2
+	//TODO: VPADDSB X11, X9, X2             // c4c131ecd3
+	//TODO: VPADDSB (BX), X9, X11           // c46131ec1b or c531ec1b
+	//TODO: VPADDSB (R11), X9, X11          // c44131ec1b
+	//TODO: VPADDSB X2, X9, X11             // c46131ecda or c531ecda
+	//TODO: VPADDSB X11, X9, X11            // c44131ecdb
+	//TODO: VPADDSB (BX), Y15, Y2           // c4e105ec13 or c585ec13
+	//TODO: VPADDSB (R11), Y15, Y2          // c4c105ec13
+	//TODO: VPADDSB Y2, Y15, Y2             // c4e105ecd2 or c585ecd2
+	//TODO: VPADDSB Y11, Y15, Y2            // c4c105ecd3
+	//TODO: VPADDSB (BX), Y15, Y11          // c46105ec1b or c505ec1b
+	//TODO: VPADDSB (R11), Y15, Y11         // c44105ec1b
+	//TODO: VPADDSB Y2, Y15, Y11            // c46105ecda or c505ecda
+	//TODO: VPADDSB Y11, Y15, Y11           // c44105ecdb
+	//TODO: VPADDSW (BX), X9, X2            // c4e131ed13 or c5b1ed13
+	//TODO: VPADDSW (R11), X9, X2           // c4c131ed13
+	//TODO: VPADDSW X2, X9, X2              // c4e131edd2 or c5b1edd2
+	//TODO: VPADDSW X11, X9, X2             // c4c131edd3
+	//TODO: VPADDSW (BX), X9, X11           // c46131ed1b or c531ed1b
+	//TODO: VPADDSW (R11), X9, X11          // c44131ed1b
+	//TODO: VPADDSW X2, X9, X11             // c46131edda or c531edda
+	//TODO: VPADDSW X11, X9, X11            // c44131eddb
+	//TODO: VPADDSW (BX), Y15, Y2           // c4e105ed13 or c585ed13
+	//TODO: VPADDSW (R11), Y15, Y2          // c4c105ed13
+	//TODO: VPADDSW Y2, Y15, Y2             // c4e105edd2 or c585edd2
+	//TODO: VPADDSW Y11, Y15, Y2            // c4c105edd3
+	//TODO: VPADDSW (BX), Y15, Y11          // c46105ed1b or c505ed1b
+	//TODO: VPADDSW (R11), Y15, Y11         // c44105ed1b
+	//TODO: VPADDSW Y2, Y15, Y11            // c46105edda or c505edda
+	//TODO: VPADDSW Y11, Y15, Y11           // c44105eddb
+	//TODO: VPADDUSB (BX), X9, X2           // c4e131dc13 or c5b1dc13
+	//TODO: VPADDUSB (R11), X9, X2          // c4c131dc13
+	//TODO: VPADDUSB X2, X9, X2             // c4e131dcd2 or c5b1dcd2
+	//TODO: VPADDUSB X11, X9, X2            // c4c131dcd3
+	//TODO: VPADDUSB (BX), X9, X11          // c46131dc1b or c531dc1b
+	//TODO: VPADDUSB (R11), X9, X11         // c44131dc1b
+	//TODO: VPADDUSB X2, X9, X11            // c46131dcda or c531dcda
+	//TODO: VPADDUSB X11, X9, X11           // c44131dcdb
+	//TODO: VPADDUSB (BX), Y15, Y2          // c4e105dc13 or c585dc13
+	//TODO: VPADDUSB (R11), Y15, Y2         // c4c105dc13
+	//TODO: VPADDUSB Y2, Y15, Y2            // c4e105dcd2 or c585dcd2
+	//TODO: VPADDUSB Y11, Y15, Y2           // c4c105dcd3
+	//TODO: VPADDUSB (BX), Y15, Y11         // c46105dc1b or c505dc1b
+	//TODO: VPADDUSB (R11), Y15, Y11        // c44105dc1b
+	//TODO: VPADDUSB Y2, Y15, Y11           // c46105dcda or c505dcda
+	//TODO: VPADDUSB Y11, Y15, Y11          // c44105dcdb
+	//TODO: VPADDUSW (BX), X9, X2           // c4e131dd13 or c5b1dd13
+	//TODO: VPADDUSW (R11), X9, X2          // c4c131dd13
+	//TODO: VPADDUSW X2, X9, X2             // c4e131ddd2 or c5b1ddd2
+	//TODO: VPADDUSW X11, X9, X2            // c4c131ddd3
+	//TODO: VPADDUSW (BX), X9, X11          // c46131dd1b or c531dd1b
+	//TODO: VPADDUSW (R11), X9, X11         // c44131dd1b
+	//TODO: VPADDUSW X2, X9, X11            // c46131ddda or c531ddda
+	//TODO: VPADDUSW X11, X9, X11           // c44131dddb
+	//TODO: VPADDUSW (BX), Y15, Y2          // c4e105dd13 or c585dd13
+	//TODO: VPADDUSW (R11), Y15, Y2         // c4c105dd13
+	//TODO: VPADDUSW Y2, Y15, Y2            // c4e105ddd2 or c585ddd2
+	//TODO: VPADDUSW Y11, Y15, Y2           // c4c105ddd3
+	//TODO: VPADDUSW (BX), Y15, Y11         // c46105dd1b or c505dd1b
+	//TODO: VPADDUSW (R11), Y15, Y11        // c44105dd1b
+	//TODO: VPADDUSW Y2, Y15, Y11           // c46105ddda or c505ddda
+	//TODO: VPADDUSW Y11, Y15, Y11          // c44105dddb
+	//TODO: VPADDW (BX), X9, X2             // c4e131fd13 or c5b1fd13
+	//TODO: VPADDW (R11), X9, X2            // c4c131fd13
+	//TODO: VPADDW X2, X9, X2               // c4e131fdd2 or c5b1fdd2
+	//TODO: VPADDW X11, X9, X2              // c4c131fdd3
+	//TODO: VPADDW (BX), X9, X11            // c46131fd1b or c531fd1b
+	//TODO: VPADDW (R11), X9, X11           // c44131fd1b
+	//TODO: VPADDW X2, X9, X11              // c46131fdda or c531fdda
+	//TODO: VPADDW X11, X9, X11             // c44131fddb
+	//TODO: VPADDW (BX), Y15, Y2            // c4e105fd13 or c585fd13
+	//TODO: VPADDW (R11), Y15, Y2           // c4c105fd13
+	//TODO: VPADDW Y2, Y15, Y2              // c4e105fdd2 or c585fdd2
+	//TODO: VPADDW Y11, Y15, Y2             // c4c105fdd3
+	//TODO: VPADDW (BX), Y15, Y11           // c46105fd1b or c505fd1b
+	//TODO: VPADDW (R11), Y15, Y11          // c44105fd1b
+	//TODO: VPADDW Y2, Y15, Y11             // c46105fdda or c505fdda
+	//TODO: VPADDW Y11, Y15, Y11            // c44105fddb
+	//TODO: VPALIGNR $7, (BX), X9, X2       // c4e3310f1307
+	//TODO: VPALIGNR $7, (R11), X9, X2      // c4c3310f1307
+	//TODO: VPALIGNR $7, X2, X9, X2         // c4e3310fd207
+	//TODO: VPALIGNR $7, X11, X9, X2        // c4c3310fd307
+	//TODO: VPALIGNR $7, (BX), X9, X11      // c463310f1b07
+	//TODO: VPALIGNR $7, (R11), X9, X11     // c443310f1b07
+	//TODO: VPALIGNR $7, X2, X9, X11        // c463310fda07
+	//TODO: VPALIGNR $7, X11, X9, X11       // c443310fdb07
+	//TODO: VPALIGNR $7, (BX), Y15, Y2      // c4e3050f1307
+	//TODO: VPALIGNR $7, (R11), Y15, Y2     // c4c3050f1307
+	//TODO: VPALIGNR $7, Y2, Y15, Y2        // c4e3050fd207
+	//TODO: VPALIGNR $7, Y11, Y15, Y2       // c4c3050fd307
+	//TODO: VPALIGNR $7, (BX), Y15, Y11     // c463050f1b07
+	//TODO: VPALIGNR $7, (R11), Y15, Y11    // c443050f1b07
+	//TODO: VPALIGNR $7, Y2, Y15, Y11       // c463050fda07
+	//TODO: VPALIGNR $7, Y11, Y15, Y11      // c443050fdb07
+	VPAND (BX), X9, X2                      // c4e131db13 or c5b1db13
+	VPAND (R11), X9, X2                     // c4c131db13
+	VPAND X2, X9, X2                        // c4e131dbd2 or c5b1dbd2
+	VPAND X11, X9, X2                       // c4c131dbd3
+	VPAND (BX), X9, X11                     // c46131db1b or c531db1b
+	VPAND (R11), X9, X11                    // c44131db1b
+	VPAND X2, X9, X11                       // c46131dbda or c531dbda
+	VPAND X11, X9, X11                      // c44131dbdb
+	VPAND (BX), Y15, Y2                     // c4e105db13 or c585db13
+	VPAND (R11), Y15, Y2                    // c4c105db13
+	VPAND Y2, Y15, Y2                       // c4e105dbd2 or c585dbd2
+	VPAND Y11, Y15, Y2                      // c4c105dbd3
+	VPAND (BX), Y15, Y11                    // c46105db1b or c505db1b
+	VPAND (R11), Y15, Y11                   // c44105db1b
+	VPAND Y2, Y15, Y11                      // c46105dbda or c505dbda
+	VPAND Y11, Y15, Y11                     // c44105dbdb
+	//TODO: VPANDN (BX), X9, X2             // c4e131df13 or c5b1df13
+	//TODO: VPANDN (R11), X9, X2            // c4c131df13
+	//TODO: VPANDN X2, X9, X2               // c4e131dfd2 or c5b1dfd2
+	//TODO: VPANDN X11, X9, X2              // c4c131dfd3
+	//TODO: VPANDN (BX), X9, X11            // c46131df1b or c531df1b
+	//TODO: VPANDN (R11), X9, X11           // c44131df1b
+	//TODO: VPANDN X2, X9, X11              // c46131dfda or c531dfda
+	//TODO: VPANDN X11, X9, X11             // c44131dfdb
+	//TODO: VPANDN (BX), Y15, Y2            // c4e105df13 or c585df13
+	//TODO: VPANDN (R11), Y15, Y2           // c4c105df13
+	//TODO: VPANDN Y2, Y15, Y2              // c4e105dfd2 or c585dfd2
+	//TODO: VPANDN Y11, Y15, Y2             // c4c105dfd3
+	//TODO: VPANDN (BX), Y15, Y11           // c46105df1b or c505df1b
+	//TODO: VPANDN (R11), Y15, Y11          // c44105df1b
+	//TODO: VPANDN Y2, Y15, Y11             // c46105dfda or c505dfda
+	//TODO: VPANDN Y11, Y15, Y11            // c44105dfdb
+	//TODO: VPAVGB (BX), X9, X2             // c4e131e013 or c5b1e013
+	//TODO: VPAVGB (R11), X9, X2            // c4c131e013
+	//TODO: VPAVGB X2, X9, X2               // c4e131e0d2 or c5b1e0d2
+	//TODO: VPAVGB X11, X9, X2              // c4c131e0d3
+	//TODO: VPAVGB (BX), X9, X11            // c46131e01b or c531e01b
+	//TODO: VPAVGB (R11), X9, X11           // c44131e01b
+	//TODO: VPAVGB X2, X9, X11              // c46131e0da or c531e0da
+	//TODO: VPAVGB X11, X9, X11             // c44131e0db
+	//TODO: VPAVGB (BX), Y15, Y2            // c4e105e013 or c585e013
+	//TODO: VPAVGB (R11), Y15, Y2           // c4c105e013
+	//TODO: VPAVGB Y2, Y15, Y2              // c4e105e0d2 or c585e0d2
+	//TODO: VPAVGB Y11, Y15, Y2             // c4c105e0d3
+	//TODO: VPAVGB (BX), Y15, Y11           // c46105e01b or c505e01b
+	//TODO: VPAVGB (R11), Y15, Y11          // c44105e01b
+	//TODO: VPAVGB Y2, Y15, Y11             // c46105e0da or c505e0da
+	//TODO: VPAVGB Y11, Y15, Y11            // c44105e0db
+	//TODO: VPAVGW (BX), X9, X2             // c4e131e313 or c5b1e313
+	//TODO: VPAVGW (R11), X9, X2            // c4c131e313
+	//TODO: VPAVGW X2, X9, X2               // c4e131e3d2 or c5b1e3d2
+	//TODO: VPAVGW X11, X9, X2              // c4c131e3d3
+	//TODO: VPAVGW (BX), X9, X11            // c46131e31b or c531e31b
+	//TODO: VPAVGW (R11), X9, X11           // c44131e31b
+	//TODO: VPAVGW X2, X9, X11              // c46131e3da or c531e3da
+	//TODO: VPAVGW X11, X9, X11             // c44131e3db
+	//TODO: VPAVGW (BX), Y15, Y2            // c4e105e313 or c585e313
+	//TODO: VPAVGW (R11), Y15, Y2           // c4c105e313
+	//TODO: VPAVGW Y2, Y15, Y2              // c4e105e3d2 or c585e3d2
+	//TODO: VPAVGW Y11, Y15, Y2             // c4c105e3d3
+	//TODO: VPAVGW (BX), Y15, Y11           // c46105e31b or c505e31b
+	//TODO: VPAVGW (R11), Y15, Y11          // c44105e31b
+	//TODO: VPAVGW Y2, Y15, Y11             // c46105e3da or c505e3da
+	//TODO: VPAVGW Y11, Y15, Y11            // c44105e3db
+	//TODO: VPBLENDD $7, (BX), X9, X2       // c4e331021307
+	//TODO: VPBLENDD $7, (R11), X9, X2      // c4c331021307
+	//TODO: VPBLENDD $7, X2, X9, X2         // c4e33102d207
+	//TODO: VPBLENDD $7, X11, X9, X2        // c4c33102d307
+	//TODO: VPBLENDD $7, (BX), X9, X11      // c46331021b07
+	//TODO: VPBLENDD $7, (R11), X9, X11     // c44331021b07
+	//TODO: VPBLENDD $7, X2, X9, X11        // c4633102da07
+	//TODO: VPBLENDD $7, X11, X9, X11       // c4433102db07
+	//TODO: VPBLENDD $7, (BX), Y15, Y2      // c4e305021307
+	//TODO: VPBLENDD $7, (R11), Y15, Y2     // c4c305021307
+	//TODO: VPBLENDD $7, Y2, Y15, Y2        // c4e30502d207
+	//TODO: VPBLENDD $7, Y11, Y15, Y2       // c4c30502d307
+	//TODO: VPBLENDD $7, (BX), Y15, Y11     // c46305021b07
+	//TODO: VPBLENDD $7, (R11), Y15, Y11    // c44305021b07
+	//TODO: VPBLENDD $7, Y2, Y15, Y11       // c4630502da07
+	//TODO: VPBLENDD $7, Y11, Y15, Y11      // c4430502db07
+	//TODO: VPBLENDVB XMM12, (BX), X9, X2   // c4e3314c13c0
+	//TODO: VPBLENDVB XMM12, (R11), X9, X2  // c4c3314c13c0
+	//TODO: VPBLENDVB XMM12, X2, X9, X2     // c4e3314cd2c0
+	//TODO: VPBLENDVB XMM12, X11, X9, X2    // c4c3314cd3c0
+	//TODO: VPBLENDVB XMM12, (BX), X9, X11  // c463314c1bc0
+	//TODO: VPBLENDVB XMM12, (R11), X9, X11 // c443314c1bc0
+	//TODO: VPBLENDVB XMM12, X2, X9, X11    // c463314cdac0
+	//TODO: VPBLENDVB XMM12, X11, X9, X11   // c443314cdbc0
+	//TODO: VPBLENDVB YMM13, (BX), Y15, Y2  // c4e3054c13d0
+	//TODO: VPBLENDVB YMM13, (R11), Y15, Y2 // c4c3054c13d0
+	//TODO: VPBLENDVB YMM13, Y2, Y15, Y2    // c4e3054cd2d0
+	//TODO: VPBLENDVB YMM13, Y11, Y15, Y2   // c4c3054cd3d0
+	//TODO: VPBLENDVB YMM13, (BX), Y15, Y11 // c463054c1bd0
+	//TODO: VPBLENDVB YMM13, (R11), Y15, Y11 // c443054c1bd0
+	//TODO: VPBLENDVB YMM13, Y2, Y15, Y11   // c463054cdad0
+	//TODO: VPBLENDVB YMM13, Y11, Y15, Y11  // c443054cdbd0
+	//TODO: VPBLENDW $7, (BX), X9, X2       // c4e3310e1307
+	//TODO: VPBLENDW $7, (R11), X9, X2      // c4c3310e1307
+	//TODO: VPBLENDW $7, X2, X9, X2         // c4e3310ed207
+	//TODO: VPBLENDW $7, X11, X9, X2        // c4c3310ed307
+	//TODO: VPBLENDW $7, (BX), X9, X11      // c463310e1b07
+	//TODO: VPBLENDW $7, (R11), X9, X11     // c443310e1b07
+	//TODO: VPBLENDW $7, X2, X9, X11        // c463310eda07
+	//TODO: VPBLENDW $7, X11, X9, X11       // c443310edb07
+	//TODO: VPBLENDW $7, (BX), Y15, Y2      // c4e3050e1307
+	//TODO: VPBLENDW $7, (R11), Y15, Y2     // c4c3050e1307
+	//TODO: VPBLENDW $7, Y2, Y15, Y2        // c4e3050ed207
+	//TODO: VPBLENDW $7, Y11, Y15, Y2       // c4c3050ed307
+	//TODO: VPBLENDW $7, (BX), Y15, Y11     // c463050e1b07
+	//TODO: VPBLENDW $7, (R11), Y15, Y11    // c443050e1b07
+	//TODO: VPBLENDW $7, Y2, Y15, Y11       // c463050eda07
+	//TODO: VPBLENDW $7, Y11, Y15, Y11      // c443050edb07
+	VPBROADCASTB (BX), X2                   // c4e2797813
+	VPBROADCASTB (R11), X2                  // c4c2797813
+	VPBROADCASTB X2, X2                     // c4e27978d2
+	VPBROADCASTB X11, X2                    // c4c27978d3
+	VPBROADCASTB (BX), X11                  // c46279781b
+	VPBROADCASTB (R11), X11                 // c44279781b
+	VPBROADCASTB X2, X11                    // c4627978da
+	VPBROADCASTB X11, X11                   // c4427978db
+	VPBROADCASTB (BX), Y2                   // c4e27d7813
+	VPBROADCASTB (R11), Y2                  // c4c27d7813
+	VPBROADCASTB X2, Y2                     // c4e27d78d2
+	VPBROADCASTB X11, Y2                    // c4c27d78d3
+	VPBROADCASTB (BX), Y11                  // c4627d781b
+	VPBROADCASTB (R11), Y11                 // c4427d781b
+	VPBROADCASTB X2, Y11                    // c4627d78da
+	VPBROADCASTB X11, Y11                   // c4427d78db
+	//TODO: VPBROADCASTD (BX), X2           // c4e2795813
+	//TODO: VPBROADCASTD (R11), X2          // c4c2795813
+	//TODO: VPBROADCASTD X2, X2             // c4e27958d2
+	//TODO: VPBROADCASTD X11, X2            // c4c27958d3
+	//TODO: VPBROADCASTD (BX), X11          // c46279581b
+	//TODO: VPBROADCASTD (R11), X11         // c44279581b
+	//TODO: VPBROADCASTD X2, X11            // c4627958da
+	//TODO: VPBROADCASTD X11, X11           // c4427958db
+	//TODO: VPBROADCASTD (BX), Y2           // c4e27d5813
+	//TODO: VPBROADCASTD (R11), Y2          // c4c27d5813
+	//TODO: VPBROADCASTD X2, Y2             // c4e27d58d2
+	//TODO: VPBROADCASTD X11, Y2            // c4c27d58d3
+	//TODO: VPBROADCASTD (BX), Y11          // c4627d581b
+	//TODO: VPBROADCASTD (R11), Y11         // c4427d581b
+	//TODO: VPBROADCASTD X2, Y11            // c4627d58da
+	//TODO: VPBROADCASTD X11, Y11           // c4427d58db
+	//TODO: VPBROADCASTQ (BX), X2           // c4e2795913
+	//TODO: VPBROADCASTQ (R11), X2          // c4c2795913
+	//TODO: VPBROADCASTQ X2, X2             // c4e27959d2
+	//TODO: VPBROADCASTQ X11, X2            // c4c27959d3
+	//TODO: VPBROADCASTQ (BX), X11          // c46279591b
+	//TODO: VPBROADCASTQ (R11), X11         // c44279591b
+	//TODO: VPBROADCASTQ X2, X11            // c4627959da
+	//TODO: VPBROADCASTQ X11, X11           // c4427959db
+	//TODO: VPBROADCASTQ (BX), Y2           // c4e27d5913
+	//TODO: VPBROADCASTQ (R11), Y2          // c4c27d5913
+	//TODO: VPBROADCASTQ X2, Y2             // c4e27d59d2
+	//TODO: VPBROADCASTQ X11, Y2            // c4c27d59d3
+	//TODO: VPBROADCASTQ (BX), Y11          // c4627d591b
+	//TODO: VPBROADCASTQ (R11), Y11         // c4427d591b
+	//TODO: VPBROADCASTQ X2, Y11            // c4627d59da
+	//TODO: VPBROADCASTQ X11, Y11           // c4427d59db
+	//TODO: VPBROADCASTW (BX), X2           // c4e2797913
+	//TODO: VPBROADCASTW (R11), X2          // c4c2797913
+	//TODO: VPBROADCASTW X2, X2             // c4e27979d2
+	//TODO: VPBROADCASTW X11, X2            // c4c27979d3
+	//TODO: VPBROADCASTW (BX), X11          // c46279791b
+	//TODO: VPBROADCASTW (R11), X11         // c44279791b
+	//TODO: VPBROADCASTW X2, X11            // c4627979da
+	//TODO: VPBROADCASTW X11, X11           // c4427979db
+	//TODO: VPBROADCASTW (BX), Y2           // c4e27d7913
+	//TODO: VPBROADCASTW (R11), Y2          // c4c27d7913
+	//TODO: VPBROADCASTW X2, Y2             // c4e27d79d2
+	//TODO: VPBROADCASTW X11, Y2            // c4c27d79d3
+	//TODO: VPBROADCASTW (BX), Y11          // c4627d791b
+	//TODO: VPBROADCASTW (R11), Y11         // c4427d791b
+	//TODO: VPBROADCASTW X2, Y11            // c4627d79da
+	//TODO: VPBROADCASTW X11, Y11           // c4427d79db
+	//TODO: VPCLMULQDQ $7, (BX), X9, X2     // c4e331441307
+	//TODO: VPCLMULQDQ $7, (R11), X9, X2    // c4c331441307
+	//TODO: VPCLMULQDQ $7, X2, X9, X2       // c4e33144d207
+	//TODO: VPCLMULQDQ $7, X11, X9, X2      // c4c33144d307
+	//TODO: VPCLMULQDQ $7, (BX), X9, X11    // c46331441b07
+	//TODO: VPCLMULQDQ $7, (R11), X9, X11   // c44331441b07
+	//TODO: VPCLMULQDQ $7, X2, X9, X11      // c4633144da07
+	//TODO: VPCLMULQDQ $7, X11, X9, X11     // c4433144db07
+	VPCMPEQB (BX), X9, X2                   // c4e1317413 or c5b17413
+	VPCMPEQB (R11), X9, X2                  // c4c1317413
+	VPCMPEQB X2, X9, X2                     // c4e13174d2 or c5b174d2
+	VPCMPEQB X11, X9, X2                    // c4c13174d3
+	VPCMPEQB (BX), X9, X11                  // c46131741b or c531741b
+	VPCMPEQB (R11), X9, X11                 // c44131741b
+	VPCMPEQB X2, X9, X11                    // c4613174da or c53174da
+	VPCMPEQB X11, X9, X11                   // c4413174db
+	VPCMPEQB (BX), Y15, Y2                  // c4e1057413 or c5857413
+	VPCMPEQB (R11), Y15, Y2                 // c4c1057413
+	VPCMPEQB Y2, Y15, Y2                    // c4e10574d2 or c58574d2
+	VPCMPEQB Y11, Y15, Y2                   // c4c10574d3
+	VPCMPEQB (BX), Y15, Y11                 // c46105741b or c505741b
+	VPCMPEQB (R11), Y15, Y11                // c44105741b
+	VPCMPEQB Y2, Y15, Y11                   // c4610574da or c50574da
+	VPCMPEQB Y11, Y15, Y11                  // c4410574db
+	//TODO: VPCMPEQD (BX), X9, X2           // c4e1317613 or c5b17613
+	//TODO: VPCMPEQD (R11), X9, X2          // c4c1317613
+	//TODO: VPCMPEQD X2, X9, X2             // c4e13176d2 or c5b176d2
+	//TODO: VPCMPEQD X11, X9, X2            // c4c13176d3
+	//TODO: VPCMPEQD (BX), X9, X11          // c46131761b or c531761b
+	//TODO: VPCMPEQD (R11), X9, X11         // c44131761b
+	//TODO: VPCMPEQD X2, X9, X11            // c4613176da or c53176da
+	//TODO: VPCMPEQD X11, X9, X11           // c4413176db
+	//TODO: VPCMPEQD (BX), Y15, Y2          // c4e1057613 or c5857613
+	//TODO: VPCMPEQD (R11), Y15, Y2         // c4c1057613
+	//TODO: VPCMPEQD Y2, Y15, Y2            // c4e10576d2 or c58576d2
+	//TODO: VPCMPEQD Y11, Y15, Y2           // c4c10576d3
+	//TODO: VPCMPEQD (BX), Y15, Y11         // c46105761b or c505761b
+	//TODO: VPCMPEQD (R11), Y15, Y11        // c44105761b
+	//TODO: VPCMPEQD Y2, Y15, Y11           // c4610576da or c50576da
+	//TODO: VPCMPEQD Y11, Y15, Y11          // c4410576db
+	//TODO: VPCMPEQQ (BX), X9, X2           // c4e2312913
+	//TODO: VPCMPEQQ (R11), X9, X2          // c4c2312913
+	//TODO: VPCMPEQQ X2, X9, X2             // c4e23129d2
+	//TODO: VPCMPEQQ X11, X9, X2            // c4c23129d3
+	//TODO: VPCMPEQQ (BX), X9, X11          // c46231291b
+	//TODO: VPCMPEQQ (R11), X9, X11         // c44231291b
+	//TODO: VPCMPEQQ X2, X9, X11            // c4623129da
+	//TODO: VPCMPEQQ X11, X9, X11           // c4423129db
+	//TODO: VPCMPEQQ (BX), Y15, Y2          // c4e2052913
+	//TODO: VPCMPEQQ (R11), Y15, Y2         // c4c2052913
+	//TODO: VPCMPEQQ Y2, Y15, Y2            // c4e20529d2
+	//TODO: VPCMPEQQ Y11, Y15, Y2           // c4c20529d3
+	//TODO: VPCMPEQQ (BX), Y15, Y11         // c46205291b
+	//TODO: VPCMPEQQ (R11), Y15, Y11        // c44205291b
+	//TODO: VPCMPEQQ Y2, Y15, Y11           // c4620529da
+	//TODO: VPCMPEQQ Y11, Y15, Y11          // c4420529db
+	//TODO: VPCMPEQW (BX), X9, X2           // c4e1317513 or c5b17513
+	//TODO: VPCMPEQW (R11), X9, X2          // c4c1317513
+	//TODO: VPCMPEQW X2, X9, X2             // c4e13175d2 or c5b175d2
+	//TODO: VPCMPEQW X11, X9, X2            // c4c13175d3
+	//TODO: VPCMPEQW (BX), X9, X11          // c46131751b or c531751b
+	//TODO: VPCMPEQW (R11), X9, X11         // c44131751b
+	//TODO: VPCMPEQW X2, X9, X11            // c4613175da or c53175da
+	//TODO: VPCMPEQW X11, X9, X11           // c4413175db
+	//TODO: VPCMPEQW (BX), Y15, Y2          // c4e1057513 or c5857513
+	//TODO: VPCMPEQW (R11), Y15, Y2         // c4c1057513
+	//TODO: VPCMPEQW Y2, Y15, Y2            // c4e10575d2 or c58575d2
+	//TODO: VPCMPEQW Y11, Y15, Y2           // c4c10575d3
+	//TODO: VPCMPEQW (BX), Y15, Y11         // c46105751b or c505751b
+	//TODO: VPCMPEQW (R11), Y15, Y11        // c44105751b
+	//TODO: VPCMPEQW Y2, Y15, Y11           // c4610575da or c50575da
+	//TODO: VPCMPEQW Y11, Y15, Y11          // c4410575db
+	//TODO: VPCMPESTRI $7, (BX), X2         // c4e379611307
+	//TODO: VPCMPESTRI $7, (R11), X2        // c4c379611307
+	//TODO: VPCMPESTRI $7, X2, X2           // c4e37961d207
+	//TODO: VPCMPESTRI $7, X11, X2          // c4c37961d307
+	//TODO: VPCMPESTRI $7, (BX), X11        // c46379611b07
+	//TODO: VPCMPESTRI $7, (R11), X11       // c44379611b07
+	//TODO: VPCMPESTRI $7, X2, X11          // c4637961da07
+	//TODO: VPCMPESTRI $7, X11, X11         // c4437961db07
+	//TODO: VPCMPESTRM $7, (BX), X2         // c4e379601307
+	//TODO: VPCMPESTRM $7, (R11), X2        // c4c379601307
+	//TODO: VPCMPESTRM $7, X2, X2           // c4e37960d207
+	//TODO: VPCMPESTRM $7, X11, X2          // c4c37960d307
+	//TODO: VPCMPESTRM $7, (BX), X11        // c46379601b07
+	//TODO: VPCMPESTRM $7, (R11), X11       // c44379601b07
+	//TODO: VPCMPESTRM $7, X2, X11          // c4637960da07
+	//TODO: VPCMPESTRM $7, X11, X11         // c4437960db07
+	//TODO: VPCMPGTB (BX), X9, X2           // c4e1316413 or c5b16413
+	//TODO: VPCMPGTB (R11), X9, X2          // c4c1316413
+	//TODO: VPCMPGTB X2, X9, X2             // c4e13164d2 or c5b164d2
+	//TODO: VPCMPGTB X11, X9, X2            // c4c13164d3
+	//TODO: VPCMPGTB (BX), X9, X11          // c46131641b or c531641b
+	//TODO: VPCMPGTB (R11), X9, X11         // c44131641b
+	//TODO: VPCMPGTB X2, X9, X11            // c4613164da or c53164da
+	//TODO: VPCMPGTB X11, X9, X11           // c4413164db
+	//TODO: VPCMPGTB (BX), Y15, Y2          // c4e1056413 or c5856413
+	//TODO: VPCMPGTB (R11), Y15, Y2         // c4c1056413
+	//TODO: VPCMPGTB Y2, Y15, Y2            // c4e10564d2 or c58564d2
+	//TODO: VPCMPGTB Y11, Y15, Y2           // c4c10564d3
+	//TODO: VPCMPGTB (BX), Y15, Y11         // c46105641b or c505641b
+	//TODO: VPCMPGTB (R11), Y15, Y11        // c44105641b
+	//TODO: VPCMPGTB Y2, Y15, Y11           // c4610564da or c50564da
+	//TODO: VPCMPGTB Y11, Y15, Y11          // c4410564db
+	//TODO: VPCMPGTD (BX), X9, X2           // c4e1316613 or c5b16613
+	//TODO: VPCMPGTD (R11), X9, X2          // c4c1316613
+	//TODO: VPCMPGTD X2, X9, X2             // c4e13166d2 or c5b166d2
+	//TODO: VPCMPGTD X11, X9, X2            // c4c13166d3
+	//TODO: VPCMPGTD (BX), X9, X11          // c46131661b or c531661b
+	//TODO: VPCMPGTD (R11), X9, X11         // c44131661b
+	//TODO: VPCMPGTD X2, X9, X11            // c4613166da or c53166da
+	//TODO: VPCMPGTD X11, X9, X11           // c4413166db
+	//TODO: VPCMPGTD (BX), Y15, Y2          // c4e1056613 or c5856613
+	//TODO: VPCMPGTD (R11), Y15, Y2         // c4c1056613
+	//TODO: VPCMPGTD Y2, Y15, Y2            // c4e10566d2 or c58566d2
+	//TODO: VPCMPGTD Y11, Y15, Y2           // c4c10566d3
+	//TODO: VPCMPGTD (BX), Y15, Y11         // c46105661b or c505661b
+	//TODO: VPCMPGTD (R11), Y15, Y11        // c44105661b
+	//TODO: VPCMPGTD Y2, Y15, Y11           // c4610566da or c50566da
+	//TODO: VPCMPGTD Y11, Y15, Y11          // c4410566db
+	//TODO: VPCMPGTQ (BX), X9, X2           // c4e2313713
+	//TODO: VPCMPGTQ (R11), X9, X2          // c4c2313713
+	//TODO: VPCMPGTQ X2, X9, X2             // c4e23137d2
+	//TODO: VPCMPGTQ X11, X9, X2            // c4c23137d3
+	//TODO: VPCMPGTQ (BX), X9, X11          // c46231371b
+	//TODO: VPCMPGTQ (R11), X9, X11         // c44231371b
+	//TODO: VPCMPGTQ X2, X9, X11            // c4623137da
+	//TODO: VPCMPGTQ X11, X9, X11           // c4423137db
+	//TODO: VPCMPGTQ (BX), Y15, Y2          // c4e2053713
+	//TODO: VPCMPGTQ (R11), Y15, Y2         // c4c2053713
+	//TODO: VPCMPGTQ Y2, Y15, Y2            // c4e20537d2
+	//TODO: VPCMPGTQ Y11, Y15, Y2           // c4c20537d3
+	//TODO: VPCMPGTQ (BX), Y15, Y11         // c46205371b
+	//TODO: VPCMPGTQ (R11), Y15, Y11        // c44205371b
+	//TODO: VPCMPGTQ Y2, Y15, Y11           // c4620537da
+	//TODO: VPCMPGTQ Y11, Y15, Y11          // c4420537db
+	//TODO: VPCMPGTW (BX), X9, X2           // c4e1316513 or c5b16513
+	//TODO: VPCMPGTW (R11), X9, X2          // c4c1316513
+	//TODO: VPCMPGTW X2, X9, X2             // c4e13165d2 or c5b165d2
+	//TODO: VPCMPGTW X11, X9, X2            // c4c13165d3
+	//TODO: VPCMPGTW (BX), X9, X11          // c46131651b or c531651b
+	//TODO: VPCMPGTW (R11), X9, X11         // c44131651b
+	//TODO: VPCMPGTW X2, X9, X11            // c4613165da or c53165da
+	//TODO: VPCMPGTW X11, X9, X11           // c4413165db
+	//TODO: VPCMPGTW (BX), Y15, Y2          // c4e1056513 or c5856513
+	//TODO: VPCMPGTW (R11), Y15, Y2         // c4c1056513
+	//TODO: VPCMPGTW Y2, Y15, Y2            // c4e10565d2 or c58565d2
+	//TODO: VPCMPGTW Y11, Y15, Y2           // c4c10565d3
+	//TODO: VPCMPGTW (BX), Y15, Y11         // c46105651b or c505651b
+	//TODO: VPCMPGTW (R11), Y15, Y11        // c44105651b
+	//TODO: VPCMPGTW Y2, Y15, Y11           // c4610565da or c50565da
+	//TODO: VPCMPGTW Y11, Y15, Y11          // c4410565db
+	//TODO: VPCMPISTRI $7, (BX), X2         // c4e379631307
+	//TODO: VPCMPISTRI $7, (R11), X2        // c4c379631307
+	//TODO: VPCMPISTRI $7, X2, X2           // c4e37963d207
+	//TODO: VPCMPISTRI $7, X11, X2          // c4c37963d307
+	//TODO: VPCMPISTRI $7, (BX), X11        // c46379631b07
+	//TODO: VPCMPISTRI $7, (R11), X11       // c44379631b07
+	//TODO: VPCMPISTRI $7, X2, X11          // c4637963da07
+	//TODO: VPCMPISTRI $7, X11, X11         // c4437963db07
+	//TODO: VPCMPISTRM $7, (BX), X2         // c4e379621307
+	//TODO: VPCMPISTRM $7, (R11), X2        // c4c379621307
+	//TODO: VPCMPISTRM $7, X2, X2           // c4e37962d207
+	//TODO: VPCMPISTRM $7, X11, X2          // c4c37962d307
+	//TODO: VPCMPISTRM $7, (BX), X11        // c46379621b07
+	//TODO: VPCMPISTRM $7, (R11), X11       // c44379621b07
+	//TODO: VPCMPISTRM $7, X2, X11          // c4637962da07
+	//TODO: VPCMPISTRM $7, X11, X11         // c4437962db07
+	//TODO: VPERM2F128 $7, (BX), Y15, Y2    // c4e305061307
+	//TODO: VPERM2F128 $7, (R11), Y15, Y2   // c4c305061307
+	//TODO: VPERM2F128 $7, Y2, Y15, Y2      // c4e30506d207
+	//TODO: VPERM2F128 $7, Y11, Y15, Y2     // c4c30506d307
+	//TODO: VPERM2F128 $7, (BX), Y15, Y11   // c46305061b07
+	//TODO: VPERM2F128 $7, (R11), Y15, Y11  // c44305061b07
+	//TODO: VPERM2F128 $7, Y2, Y15, Y11     // c4630506da07
+	//TODO: VPERM2F128 $7, Y11, Y15, Y11    // c4430506db07
+	//TODO: VPERM2I128 $7, (BX), Y15, Y2    // c4e305461307
+	//TODO: VPERM2I128 $7, (R11), Y15, Y2   // c4c305461307
+	//TODO: VPERM2I128 $7, Y2, Y15, Y2      // c4e30546d207
+	//TODO: VPERM2I128 $7, Y11, Y15, Y2     // c4c30546d307
+	//TODO: VPERM2I128 $7, (BX), Y15, Y11   // c46305461b07
+	//TODO: VPERM2I128 $7, (R11), Y15, Y11  // c44305461b07
+	//TODO: VPERM2I128 $7, Y2, Y15, Y11     // c4630546da07
+	//TODO: VPERM2I128 $7, Y11, Y15, Y11    // c4430546db07
+	//TODO: VPERMD (BX), Y15, Y2            // c4e2053613
+	//TODO: VPERMD (R11), Y15, Y2           // c4c2053613
+	//TODO: VPERMD Y2, Y15, Y2              // c4e20536d2
+	//TODO: VPERMD Y11, Y15, Y2             // c4c20536d3
+	//TODO: VPERMD (BX), Y15, Y11           // c46205361b
+	//TODO: VPERMD (R11), Y15, Y11          // c44205361b
+	//TODO: VPERMD Y2, Y15, Y11             // c4620536da
+	//TODO: VPERMD Y11, Y15, Y11            // c4420536db
+	//TODO: VPERMILPD $7, (BX), X2          // c4e379051307
+	//TODO: VPERMILPD $7, (R11), X2         // c4c379051307
+	//TODO: VPERMILPD $7, X2, X2            // c4e37905d207
+	//TODO: VPERMILPD $7, X11, X2           // c4c37905d307
+	//TODO: VPERMILPD $7, (BX), X11         // c46379051b07
+	//TODO: VPERMILPD $7, (R11), X11        // c44379051b07
+	//TODO: VPERMILPD $7, X2, X11           // c4637905da07
+	//TODO: VPERMILPD $7, X11, X11          // c4437905db07
+	//TODO: VPERMILPD (BX), X9, X2          // c4e2310d13
+	//TODO: VPERMILPD (R11), X9, X2         // c4c2310d13
+	//TODO: VPERMILPD X2, X9, X2            // c4e2310dd2
+	//TODO: VPERMILPD X11, X9, X2           // c4c2310dd3
+	//TODO: VPERMILPD (BX), X9, X11         // c462310d1b
+	//TODO: VPERMILPD (R11), X9, X11        // c442310d1b
+	//TODO: VPERMILPD X2, X9, X11           // c462310dda
+	//TODO: VPERMILPD X11, X9, X11          // c442310ddb
+	//TODO: VPERMILPD $7, (BX), Y2          // c4e37d051307
+	//TODO: VPERMILPD $7, (R11), Y2         // c4c37d051307
+	//TODO: VPERMILPD $7, Y2, Y2            // c4e37d05d207
+	//TODO: VPERMILPD $7, Y11, Y2           // c4c37d05d307
+	//TODO: VPERMILPD $7, (BX), Y11         // c4637d051b07
+	//TODO: VPERMILPD $7, (R11), Y11        // c4437d051b07
+	//TODO: VPERMILPD $7, Y2, Y11           // c4637d05da07
+	//TODO: VPERMILPD $7, Y11, Y11          // c4437d05db07
+	//TODO: VPERMILPD (BX), Y15, Y2         // c4e2050d13
+	//TODO: VPERMILPD (R11), Y15, Y2        // c4c2050d13
+	//TODO: VPERMILPD Y2, Y15, Y2           // c4e2050dd2
+	//TODO: VPERMILPD Y11, Y15, Y2          // c4c2050dd3
+	//TODO: VPERMILPD (BX), Y15, Y11        // c462050d1b
+	//TODO: VPERMILPD (R11), Y15, Y11       // c442050d1b
+	//TODO: VPERMILPD Y2, Y15, Y11          // c462050dda
+	//TODO: VPERMILPD Y11, Y15, Y11         // c442050ddb
+	//TODO: VPERMILPS $7, (BX), X2          // c4e379041307
+	//TODO: VPERMILPS $7, (R11), X2         // c4c379041307
+	//TODO: VPERMILPS $7, X2, X2            // c4e37904d207
+	//TODO: VPERMILPS $7, X11, X2           // c4c37904d307
+	//TODO: VPERMILPS $7, (BX), X11         // c46379041b07
+	//TODO: VPERMILPS $7, (R11), X11        // c44379041b07
+	//TODO: VPERMILPS $7, X2, X11           // c4637904da07
+	//TODO: VPERMILPS $7, X11, X11          // c4437904db07
+	//TODO: VPERMILPS (BX), X9, X2          // c4e2310c13
+	//TODO: VPERMILPS (R11), X9, X2         // c4c2310c13
+	//TODO: VPERMILPS X2, X9, X2            // c4e2310cd2
+	//TODO: VPERMILPS X11, X9, X2           // c4c2310cd3
+	//TODO: VPERMILPS (BX), X9, X11         // c462310c1b
+	//TODO: VPERMILPS (R11), X9, X11        // c442310c1b
+	//TODO: VPERMILPS X2, X9, X11           // c462310cda
+	//TODO: VPERMILPS X11, X9, X11          // c442310cdb
+	//TODO: VPERMILPS $7, (BX), Y2          // c4e37d041307
+	//TODO: VPERMILPS $7, (R11), Y2         // c4c37d041307
+	//TODO: VPERMILPS $7, Y2, Y2            // c4e37d04d207
+	//TODO: VPERMILPS $7, Y11, Y2           // c4c37d04d307
+	//TODO: VPERMILPS $7, (BX), Y11         // c4637d041b07
+	//TODO: VPERMILPS $7, (R11), Y11        // c4437d041b07
+	//TODO: VPERMILPS $7, Y2, Y11           // c4637d04da07
+	//TODO: VPERMILPS $7, Y11, Y11          // c4437d04db07
+	//TODO: VPERMILPS (BX), Y15, Y2         // c4e2050c13
+	//TODO: VPERMILPS (R11), Y15, Y2        // c4c2050c13
+	//TODO: VPERMILPS Y2, Y15, Y2           // c4e2050cd2
+	//TODO: VPERMILPS Y11, Y15, Y2          // c4c2050cd3
+	//TODO: VPERMILPS (BX), Y15, Y11        // c462050c1b
+	//TODO: VPERMILPS (R11), Y15, Y11       // c442050c1b
+	//TODO: VPERMILPS Y2, Y15, Y11          // c462050cda
+	//TODO: VPERMILPS Y11, Y15, Y11         // c442050cdb
+	//TODO: VPERMPD $7, (BX), Y2            // c4e3fd011307
+	//TODO: VPERMPD $7, (R11), Y2           // c4c3fd011307
+	//TODO: VPERMPD $7, Y2, Y2              // c4e3fd01d207
+	//TODO: VPERMPD $7, Y11, Y2             // c4c3fd01d307
+	//TODO: VPERMPD $7, (BX), Y11           // c463fd011b07
+	//TODO: VPERMPD $7, (R11), Y11          // c443fd011b07
+	//TODO: VPERMPD $7, Y2, Y11             // c463fd01da07
+	//TODO: VPERMPD $7, Y11, Y11            // c443fd01db07
+	//TODO: VPERMPS (BX), Y15, Y2           // c4e2051613
+	//TODO: VPERMPS (R11), Y15, Y2          // c4c2051613
+	//TODO: VPERMPS Y2, Y15, Y2             // c4e20516d2
+	//TODO: VPERMPS Y11, Y15, Y2            // c4c20516d3
+	//TODO: VPERMPS (BX), Y15, Y11          // c46205161b
+	//TODO: VPERMPS (R11), Y15, Y11         // c44205161b
+	//TODO: VPERMPS Y2, Y15, Y11            // c4620516da
+	//TODO: VPERMPS Y11, Y15, Y11           // c4420516db
+	//TODO: VPERMQ $7, (BX), Y2             // c4e3fd001307
+	//TODO: VPERMQ $7, (R11), Y2            // c4c3fd001307
+	//TODO: VPERMQ $7, Y2, Y2               // c4e3fd00d207
+	//TODO: VPERMQ $7, Y11, Y2              // c4c3fd00d307
+	//TODO: VPERMQ $7, (BX), Y11            // c463fd001b07
+	//TODO: VPERMQ $7, (R11), Y11           // c443fd001b07
+	//TODO: VPERMQ $7, Y2, Y11              // c463fd00da07
+	//TODO: VPERMQ $7, Y11, Y11             // c443fd00db07
+	//TODO: VPEXTRB $7, X2, (BX)            // c4e379141307
+	//TODO: VPEXTRB $7, X11, (BX)           // c46379141b07
+	//TODO: VPEXTRB $7, X2, (R11)           // c4c379141307
+	//TODO: VPEXTRB $7, X11, (R11)          // c44379141b07
+	//TODO: VPEXTRB $7, X2, DX              // c4e37914d207
+	//TODO: VPEXTRB $7, X11, DX             // c4637914da07
+	//TODO: VPEXTRB $7, X2, R11             // c4c37914d307
+	//TODO: VPEXTRB $7, X11, R11            // c4437914db07
+	//TODO: VPEXTRD $7, X2, (BX)            // c4e379161307
+	//TODO: VPEXTRD $7, X11, (BX)           // c46379161b07
+	//TODO: VPEXTRD $7, X2, (R11)           // c4c379161307
+	//TODO: VPEXTRD $7, X11, (R11)          // c44379161b07
+	//TODO: VPEXTRD $7, X2, DX              // c4e37916d207
+	//TODO: VPEXTRD $7, X11, DX             // c4637916da07
+	//TODO: VPEXTRD $7, X2, R11             // c4c37916d307
+	//TODO: VPEXTRD $7, X11, R11            // c4437916db07
+	//TODO: VPEXTRQ $7, X2, (BX)            // c4e3f9161307
+	//TODO: VPEXTRQ $7, X11, (BX)           // c463f9161b07
+	//TODO: VPEXTRQ $7, X2, (R11)           // c4c3f9161307
+	//TODO: VPEXTRQ $7, X11, (R11)          // c443f9161b07
+	//TODO: VPEXTRQ $7, X2, DX              // c4e3f916d207
+	//TODO: VPEXTRQ $7, X11, DX             // c463f916da07
+	//TODO: VPEXTRQ $7, X2, R11             // c4c3f916d307
+	//TODO: VPEXTRQ $7, X11, R11            // c443f916db07
+	//TODO: VPEXTRW $7, X2, DX              // c4e179c5d207 or c5f9c5d207 or c4e37915d207
+	//TODO: VPEXTRW $7, X11, DX             // c4c179c5d307 or c4637915da07
+	//TODO: VPEXTRW $7, X2, R11             // c46179c5da07 or c579c5da07 or c4c37915d307
+	//TODO: VPEXTRW $7, X11, R11            // c44179c5db07 or c4437915db07
+	//TODO: VPEXTRW $7, X2, (BX)            // c4e379151307
+	//TODO: VPEXTRW $7, X11, (BX)           // c46379151b07
+	//TODO: VPEXTRW $7, X2, (R11)           // c4c379151307
+	//TODO: VPEXTRW $7, X11, (R11)          // c44379151b07
+	//TODO: VPHADDD (BX), X9, X2            // c4e2310213
+	//TODO: VPHADDD (R11), X9, X2           // c4c2310213
+	//TODO: VPHADDD X2, X9, X2              // c4e23102d2
+	//TODO: VPHADDD X11, X9, X2             // c4c23102d3
+	//TODO: VPHADDD (BX), X9, X11           // c46231021b
+	//TODO: VPHADDD (R11), X9, X11          // c44231021b
+	//TODO: VPHADDD X2, X9, X11             // c4623102da
+	//TODO: VPHADDD X11, X9, X11            // c4423102db
+	//TODO: VPHADDD (BX), Y15, Y2           // c4e2050213
+	//TODO: VPHADDD (R11), Y15, Y2          // c4c2050213
+	//TODO: VPHADDD Y2, Y15, Y2             // c4e20502d2
+	//TODO: VPHADDD Y11, Y15, Y2            // c4c20502d3
+	//TODO: VPHADDD (BX), Y15, Y11          // c46205021b
+	//TODO: VPHADDD (R11), Y15, Y11         // c44205021b
+	//TODO: VPHADDD Y2, Y15, Y11            // c4620502da
+	//TODO: VPHADDD Y11, Y15, Y11           // c4420502db
+	//TODO: VPHADDSW (BX), X9, X2           // c4e2310313
+	//TODO: VPHADDSW (R11), X9, X2          // c4c2310313
+	//TODO: VPHADDSW X2, X9, X2             // c4e23103d2
+	//TODO: VPHADDSW X11, X9, X2            // c4c23103d3
+	//TODO: VPHADDSW (BX), X9, X11          // c46231031b
+	//TODO: VPHADDSW (R11), X9, X11         // c44231031b
+	//TODO: VPHADDSW X2, X9, X11            // c4623103da
+	//TODO: VPHADDSW X11, X9, X11           // c4423103db
+	//TODO: VPHADDSW (BX), Y15, Y2          // c4e2050313
+	//TODO: VPHADDSW (R11), Y15, Y2         // c4c2050313
+	//TODO: VPHADDSW Y2, Y15, Y2            // c4e20503d2
+	//TODO: VPHADDSW Y11, Y15, Y2           // c4c20503d3
+	//TODO: VPHADDSW (BX), Y15, Y11         // c46205031b
+	//TODO: VPHADDSW (R11), Y15, Y11        // c44205031b
+	//TODO: VPHADDSW Y2, Y15, Y11           // c4620503da
+	//TODO: VPHADDSW Y11, Y15, Y11          // c4420503db
+	//TODO: VPHADDW (BX), X9, X2            // c4e2310113
+	//TODO: VPHADDW (R11), X9, X2           // c4c2310113
+	//TODO: VPHADDW X2, X9, X2              // c4e23101d2
+	//TODO: VPHADDW X11, X9, X2             // c4c23101d3
+	//TODO: VPHADDW (BX), X9, X11           // c46231011b
+	//TODO: VPHADDW (R11), X9, X11          // c44231011b
+	//TODO: VPHADDW X2, X9, X11             // c4623101da
+	//TODO: VPHADDW X11, X9, X11            // c4423101db
+	//TODO: VPHADDW (BX), Y15, Y2           // c4e2050113
+	//TODO: VPHADDW (R11), Y15, Y2          // c4c2050113
+	//TODO: VPHADDW Y2, Y15, Y2             // c4e20501d2
+	//TODO: VPHADDW Y11, Y15, Y2            // c4c20501d3
+	//TODO: VPHADDW (BX), Y15, Y11          // c46205011b
+	//TODO: VPHADDW (R11), Y15, Y11         // c44205011b
+	//TODO: VPHADDW Y2, Y15, Y11            // c4620501da
+	//TODO: VPHADDW Y11, Y15, Y11           // c4420501db
+	//TODO: VPHMINPOSUW (BX), X2            // c4e2794113
+	//TODO: VPHMINPOSUW (R11), X2           // c4c2794113
+	//TODO: VPHMINPOSUW X2, X2              // c4e27941d2
+	//TODO: VPHMINPOSUW X11, X2             // c4c27941d3
+	//TODO: VPHMINPOSUW (BX), X11           // c46279411b
+	//TODO: VPHMINPOSUW (R11), X11          // c44279411b
+	//TODO: VPHMINPOSUW X2, X11             // c4627941da
+	//TODO: VPHMINPOSUW X11, X11            // c4427941db
+	//TODO: VPHSUBD (BX), X9, X2            // c4e2310613
+	//TODO: VPHSUBD (R11), X9, X2           // c4c2310613
+	//TODO: VPHSUBD X2, X9, X2              // c4e23106d2
+	//TODO: VPHSUBD X11, X9, X2             // c4c23106d3
+	//TODO: VPHSUBD (BX), X9, X11           // c46231061b
+	//TODO: VPHSUBD (R11), X9, X11          // c44231061b
+	//TODO: VPHSUBD X2, X9, X11             // c4623106da
+	//TODO: VPHSUBD X11, X9, X11            // c4423106db
+	//TODO: VPHSUBD (BX), Y15, Y2           // c4e2050613
+	//TODO: VPHSUBD (R11), Y15, Y2          // c4c2050613
+	//TODO: VPHSUBD Y2, Y15, Y2             // c4e20506d2
+	//TODO: VPHSUBD Y11, Y15, Y2            // c4c20506d3
+	//TODO: VPHSUBD (BX), Y15, Y11          // c46205061b
+	//TODO: VPHSUBD (R11), Y15, Y11         // c44205061b
+	//TODO: VPHSUBD Y2, Y15, Y11            // c4620506da
+	//TODO: VPHSUBD Y11, Y15, Y11           // c4420506db
+	//TODO: VPHSUBSW (BX), X9, X2           // c4e2310713
+	//TODO: VPHSUBSW (R11), X9, X2          // c4c2310713
+	//TODO: VPHSUBSW X2, X9, X2             // c4e23107d2
+	//TODO: VPHSUBSW X11, X9, X2            // c4c23107d3
+	//TODO: VPHSUBSW (BX), X9, X11          // c46231071b
+	//TODO: VPHSUBSW (R11), X9, X11         // c44231071b
+	//TODO: VPHSUBSW X2, X9, X11            // c4623107da
+	//TODO: VPHSUBSW X11, X9, X11           // c4423107db
+	//TODO: VPHSUBSW (BX), Y15, Y2          // c4e2050713
+	//TODO: VPHSUBSW (R11), Y15, Y2         // c4c2050713
+	//TODO: VPHSUBSW Y2, Y15, Y2            // c4e20507d2
+	//TODO: VPHSUBSW Y11, Y15, Y2           // c4c20507d3
+	//TODO: VPHSUBSW (BX), Y15, Y11         // c46205071b
+	//TODO: VPHSUBSW (R11), Y15, Y11        // c44205071b
+	//TODO: VPHSUBSW Y2, Y15, Y11           // c4620507da
+	//TODO: VPHSUBSW Y11, Y15, Y11          // c4420507db
+	//TODO: VPHSUBW (BX), X9, X2            // c4e2310513
+	//TODO: VPHSUBW (R11), X9, X2           // c4c2310513
+	//TODO: VPHSUBW X2, X9, X2              // c4e23105d2
+	//TODO: VPHSUBW X11, X9, X2             // c4c23105d3
+	//TODO: VPHSUBW (BX), X9, X11           // c46231051b
+	//TODO: VPHSUBW (R11), X9, X11          // c44231051b
+	//TODO: VPHSUBW X2, X9, X11             // c4623105da
+	//TODO: VPHSUBW X11, X9, X11            // c4423105db
+	//TODO: VPHSUBW (BX), Y15, Y2           // c4e2050513
+	//TODO: VPHSUBW (R11), Y15, Y2          // c4c2050513
+	//TODO: VPHSUBW Y2, Y15, Y2             // c4e20505d2
+	//TODO: VPHSUBW Y11, Y15, Y2            // c4c20505d3
+	//TODO: VPHSUBW (BX), Y15, Y11          // c46205051b
+	//TODO: VPHSUBW (R11), Y15, Y11         // c44205051b
+	//TODO: VPHSUBW Y2, Y15, Y11            // c4620505da
+	//TODO: VPHSUBW Y11, Y15, Y11           // c4420505db
+	//TODO: VPINSRB $7, (BX), X9, X2        // c4e331201307
+	//TODO: VPINSRB $7, (R11), X9, X2       // c4c331201307
+	//TODO: VPINSRB $7, DX, X9, X2          // c4e33120d207
+	//TODO: VPINSRB $7, R11, X9, X2         // c4c33120d307
+	//TODO: VPINSRB $7, (BX), X9, X11       // c46331201b07
+	//TODO: VPINSRB $7, (R11), X9, X11      // c44331201b07
+	//TODO: VPINSRB $7, DX, X9, X11         // c4633120da07
+	//TODO: VPINSRB $7, R11, X9, X11        // c4433120db07
+	//TODO: VPINSRD $7, (BX), X9, X2        // c4e331221307
+	//TODO: VPINSRD $7, (R11), X9, X2       // c4c331221307
+	//TODO: VPINSRD $7, DX, X9, X2          // c4e33122d207
+	//TODO: VPINSRD $7, R11, X9, X2         // c4c33122d307
+	//TODO: VPINSRD $7, (BX), X9, X11       // c46331221b07
+	//TODO: VPINSRD $7, (R11), X9, X11      // c44331221b07
+	//TODO: VPINSRD $7, DX, X9, X11         // c4633122da07
+	//TODO: VPINSRD $7, R11, X9, X11        // c4433122db07
+	//TODO: VPINSRQ $7, (BX), X9, X2        // c4e3b1221307
+	//TODO: VPINSRQ $7, (R11), X9, X2       // c4c3b1221307
+	//TODO: VPINSRQ $7, DX, X9, X2          // c4e3b122d207
+	//TODO: VPINSRQ $7, R11, X9, X2         // c4c3b122d307
+	//TODO: VPINSRQ $7, (BX), X9, X11       // c463b1221b07
+	//TODO: VPINSRQ $7, (R11), X9, X11      // c443b1221b07
+	//TODO: VPINSRQ $7, DX, X9, X11         // c463b122da07
+	//TODO: VPINSRQ $7, R11, X9, X11        // c443b122db07
+	//TODO: VPINSRW $7, (BX), X9, X2        // c4e131c41307 or c5b1c41307
+	//TODO: VPINSRW $7, (R11), X9, X2       // c4c131c41307
+	//TODO: VPINSRW $7, DX, X9, X2          // c4e131c4d207 or c5b1c4d207
+	//TODO: VPINSRW $7, R11, X9, X2         // c4c131c4d307
+	//TODO: VPINSRW $7, (BX), X9, X11       // c46131c41b07 or c531c41b07
+	//TODO: VPINSRW $7, (R11), X9, X11      // c44131c41b07
+	//TODO: VPINSRW $7, DX, X9, X11         // c46131c4da07 or c531c4da07
+	//TODO: VPINSRW $7, R11, X9, X11        // c44131c4db07
+	//TODO: VPMADDUBSW (BX), X9, X2         // c4e2310413
+	//TODO: VPMADDUBSW (R11), X9, X2        // c4c2310413
+	//TODO: VPMADDUBSW X2, X9, X2           // c4e23104d2
+	//TODO: VPMADDUBSW X11, X9, X2          // c4c23104d3
+	//TODO: VPMADDUBSW (BX), X9, X11        // c46231041b
+	//TODO: VPMADDUBSW (R11), X9, X11       // c44231041b
+	//TODO: VPMADDUBSW X2, X9, X11          // c4623104da
+	//TODO: VPMADDUBSW X11, X9, X11         // c4423104db
+	//TODO: VPMADDUBSW (BX), Y15, Y2        // c4e2050413
+	//TODO: VPMADDUBSW (R11), Y15, Y2       // c4c2050413
+	//TODO: VPMADDUBSW Y2, Y15, Y2          // c4e20504d2
+	//TODO: VPMADDUBSW Y11, Y15, Y2         // c4c20504d3
+	//TODO: VPMADDUBSW (BX), Y15, Y11       // c46205041b
+	//TODO: VPMADDUBSW (R11), Y15, Y11      // c44205041b
+	//TODO: VPMADDUBSW Y2, Y15, Y11         // c4620504da
+	//TODO: VPMADDUBSW Y11, Y15, Y11        // c4420504db
+	//TODO: VPMADDWD (BX), X9, X2           // c4e131f513 or c5b1f513
+	//TODO: VPMADDWD (R11), X9, X2          // c4c131f513
+	//TODO: VPMADDWD X2, X9, X2             // c4e131f5d2 or c5b1f5d2
+	//TODO: VPMADDWD X11, X9, X2            // c4c131f5d3
+	//TODO: VPMADDWD (BX), X9, X11          // c46131f51b or c531f51b
+	//TODO: VPMADDWD (R11), X9, X11         // c44131f51b
+	//TODO: VPMADDWD X2, X9, X11            // c46131f5da or c531f5da
+	//TODO: VPMADDWD X11, X9, X11           // c44131f5db
+	//TODO: VPMADDWD (BX), Y15, Y2          // c4e105f513 or c585f513
+	//TODO: VPMADDWD (R11), Y15, Y2         // c4c105f513
+	//TODO: VPMADDWD Y2, Y15, Y2            // c4e105f5d2 or c585f5d2
+	//TODO: VPMADDWD Y11, Y15, Y2           // c4c105f5d3
+	//TODO: VPMADDWD (BX), Y15, Y11         // c46105f51b or c505f51b
+	//TODO: VPMADDWD (R11), Y15, Y11        // c44105f51b
+	//TODO: VPMADDWD Y2, Y15, Y11           // c46105f5da or c505f5da
+	//TODO: VPMADDWD Y11, Y15, Y11          // c44105f5db
+	//TODO: VPMASKMOVD X2, X9, (BX)         // c4e2318e13
+	//TODO: VPMASKMOVD X11, X9, (BX)        // c462318e1b
+	//TODO: VPMASKMOVD X2, X9, (R11)        // c4c2318e13
+	//TODO: VPMASKMOVD X11, X9, (R11)       // c442318e1b
+	//TODO: VPMASKMOVD Y2, Y15, (BX)        // c4e2058e13
+	//TODO: VPMASKMOVD Y11, Y15, (BX)       // c462058e1b
+	//TODO: VPMASKMOVD Y2, Y15, (R11)       // c4c2058e13
+	//TODO: VPMASKMOVD Y11, Y15, (R11)      // c442058e1b
+	//TODO: VPMASKMOVD (BX), X9, X2         // c4e2318c13
+	//TODO: VPMASKMOVD (R11), X9, X2        // c4c2318c13
+	//TODO: VPMASKMOVD (BX), X9, X11        // c462318c1b
+	//TODO: VPMASKMOVD (R11), X9, X11       // c442318c1b
+	//TODO: VPMASKMOVD (BX), Y15, Y2        // c4e2058c13
+	//TODO: VPMASKMOVD (R11), Y15, Y2       // c4c2058c13
+	//TODO: VPMASKMOVD (BX), Y15, Y11       // c462058c1b
+	//TODO: VPMASKMOVD (R11), Y15, Y11      // c442058c1b
+	//TODO: VPMASKMOVQ X2, X9, (BX)         // c4e2b18e13
+	//TODO: VPMASKMOVQ X11, X9, (BX)        // c462b18e1b
+	//TODO: VPMASKMOVQ X2, X9, (R11)        // c4c2b18e13
+	//TODO: VPMASKMOVQ X11, X9, (R11)       // c442b18e1b
+	//TODO: VPMASKMOVQ Y2, Y15, (BX)        // c4e2858e13
+	//TODO: VPMASKMOVQ Y11, Y15, (BX)       // c462858e1b
+	//TODO: VPMASKMOVQ Y2, Y15, (R11)       // c4c2858e13
+	//TODO: VPMASKMOVQ Y11, Y15, (R11)      // c442858e1b
+	//TODO: VPMASKMOVQ (BX), X9, X2         // c4e2b18c13
+	//TODO: VPMASKMOVQ (R11), X9, X2        // c4c2b18c13
+	//TODO: VPMASKMOVQ (BX), X9, X11        // c462b18c1b
+	//TODO: VPMASKMOVQ (R11), X9, X11       // c442b18c1b
+	//TODO: VPMASKMOVQ (BX), Y15, Y2        // c4e2858c13
+	//TODO: VPMASKMOVQ (R11), Y15, Y2       // c4c2858c13
+	//TODO: VPMASKMOVQ (BX), Y15, Y11       // c462858c1b
+	//TODO: VPMASKMOVQ (R11), Y15, Y11      // c442858c1b
+	//TODO: VPMAXSB (BX), X9, X2            // c4e2313c13
+	//TODO: VPMAXSB (R11), X9, X2           // c4c2313c13
+	//TODO: VPMAXSB X2, X9, X2              // c4e2313cd2
+	//TODO: VPMAXSB X11, X9, X2             // c4c2313cd3
+	//TODO: VPMAXSB (BX), X9, X11           // c462313c1b
+	//TODO: VPMAXSB (R11), X9, X11          // c442313c1b
+	//TODO: VPMAXSB X2, X9, X11             // c462313cda
+	//TODO: VPMAXSB X11, X9, X11            // c442313cdb
+	//TODO: VPMAXSB (BX), Y15, Y2           // c4e2053c13
+	//TODO: VPMAXSB (R11), Y15, Y2          // c4c2053c13
+	//TODO: VPMAXSB Y2, Y15, Y2             // c4e2053cd2
+	//TODO: VPMAXSB Y11, Y15, Y2            // c4c2053cd3
+	//TODO: VPMAXSB (BX), Y15, Y11          // c462053c1b
+	//TODO: VPMAXSB (R11), Y15, Y11         // c442053c1b
+	//TODO: VPMAXSB Y2, Y15, Y11            // c462053cda
+	//TODO: VPMAXSB Y11, Y15, Y11           // c442053cdb
+	//TODO: VPMAXSD (BX), X9, X2            // c4e2313d13
+	//TODO: VPMAXSD (R11), X9, X2           // c4c2313d13
+	//TODO: VPMAXSD X2, X9, X2              // c4e2313dd2
+	//TODO: VPMAXSD X11, X9, X2             // c4c2313dd3
+	//TODO: VPMAXSD (BX), X9, X11           // c462313d1b
+	//TODO: VPMAXSD (R11), X9, X11          // c442313d1b
+	//TODO: VPMAXSD X2, X9, X11             // c462313dda
+	//TODO: VPMAXSD X11, X9, X11            // c442313ddb
+	//TODO: VPMAXSD (BX), Y15, Y2           // c4e2053d13
+	//TODO: VPMAXSD (R11), Y15, Y2          // c4c2053d13
+	//TODO: VPMAXSD Y2, Y15, Y2             // c4e2053dd2
+	//TODO: VPMAXSD Y11, Y15, Y2            // c4c2053dd3
+	//TODO: VPMAXSD (BX), Y15, Y11          // c462053d1b
+	//TODO: VPMAXSD (R11), Y15, Y11         // c442053d1b
+	//TODO: VPMAXSD Y2, Y15, Y11            // c462053dda
+	//TODO: VPMAXSD Y11, Y15, Y11           // c442053ddb
+	//TODO: VPMAXSW (BX), X9, X2            // c4e131ee13 or c5b1ee13
+	//TODO: VPMAXSW (R11), X9, X2           // c4c131ee13
+	//TODO: VPMAXSW X2, X9, X2              // c4e131eed2 or c5b1eed2
+	//TODO: VPMAXSW X11, X9, X2             // c4c131eed3
+	//TODO: VPMAXSW (BX), X9, X11           // c46131ee1b or c531ee1b
+	//TODO: VPMAXSW (R11), X9, X11          // c44131ee1b
+	//TODO: VPMAXSW X2, X9, X11             // c46131eeda or c531eeda
+	//TODO: VPMAXSW X11, X9, X11            // c44131eedb
+	//TODO: VPMAXSW (BX), Y15, Y2           // c4e105ee13 or c585ee13
+	//TODO: VPMAXSW (R11), Y15, Y2          // c4c105ee13
+	//TODO: VPMAXSW Y2, Y15, Y2             // c4e105eed2 or c585eed2
+	//TODO: VPMAXSW Y11, Y15, Y2            // c4c105eed3
+	//TODO: VPMAXSW (BX), Y15, Y11          // c46105ee1b or c505ee1b
+	//TODO: VPMAXSW (R11), Y15, Y11         // c44105ee1b
+	//TODO: VPMAXSW Y2, Y15, Y11            // c46105eeda or c505eeda
+	//TODO: VPMAXSW Y11, Y15, Y11           // c44105eedb
+	//TODO: VPMAXUB (BX), X9, X2            // c4e131de13 or c5b1de13
+	//TODO: VPMAXUB (R11), X9, X2           // c4c131de13
+	//TODO: VPMAXUB X2, X9, X2              // c4e131ded2 or c5b1ded2
+	//TODO: VPMAXUB X11, X9, X2             // c4c131ded3
+	//TODO: VPMAXUB (BX), X9, X11           // c46131de1b or c531de1b
+	//TODO: VPMAXUB (R11), X9, X11          // c44131de1b
+	//TODO: VPMAXUB X2, X9, X11             // c46131deda or c531deda
+	//TODO: VPMAXUB X11, X9, X11            // c44131dedb
+	//TODO: VPMAXUB (BX), Y15, Y2           // c4e105de13 or c585de13
+	//TODO: VPMAXUB (R11), Y15, Y2          // c4c105de13
+	//TODO: VPMAXUB Y2, Y15, Y2             // c4e105ded2 or c585ded2
+	//TODO: VPMAXUB Y11, Y15, Y2            // c4c105ded3
+	//TODO: VPMAXUB (BX), Y15, Y11          // c46105de1b or c505de1b
+	//TODO: VPMAXUB (R11), Y15, Y11         // c44105de1b
+	//TODO: VPMAXUB Y2, Y15, Y11            // c46105deda or c505deda
+	//TODO: VPMAXUB Y11, Y15, Y11           // c44105dedb
+	//TODO: VPMAXUD (BX), X9, X2            // c4e2313f13
+	//TODO: VPMAXUD (R11), X9, X2           // c4c2313f13
+	//TODO: VPMAXUD X2, X9, X2              // c4e2313fd2
+	//TODO: VPMAXUD X11, X9, X2             // c4c2313fd3
+	//TODO: VPMAXUD (BX), X9, X11           // c462313f1b
+	//TODO: VPMAXUD (R11), X9, X11          // c442313f1b
+	//TODO: VPMAXUD X2, X9, X11             // c462313fda
+	//TODO: VPMAXUD X11, X9, X11            // c442313fdb
+	//TODO: VPMAXUD (BX), Y15, Y2           // c4e2053f13
+	//TODO: VPMAXUD (R11), Y15, Y2          // c4c2053f13
+	//TODO: VPMAXUD Y2, Y15, Y2             // c4e2053fd2
+	//TODO: VPMAXUD Y11, Y15, Y2            // c4c2053fd3
+	//TODO: VPMAXUD (BX), Y15, Y11          // c462053f1b
+	//TODO: VPMAXUD (R11), Y15, Y11         // c442053f1b
+	//TODO: VPMAXUD Y2, Y15, Y11            // c462053fda
+	//TODO: VPMAXUD Y11, Y15, Y11           // c442053fdb
+	//TODO: VPMAXUW (BX), X9, X2            // c4e2313e13
+	//TODO: VPMAXUW (R11), X9, X2           // c4c2313e13
+	//TODO: VPMAXUW X2, X9, X2              // c4e2313ed2
+	//TODO: VPMAXUW X11, X9, X2             // c4c2313ed3
+	//TODO: VPMAXUW (BX), X9, X11           // c462313e1b
+	//TODO: VPMAXUW (R11), X9, X11          // c442313e1b
+	//TODO: VPMAXUW X2, X9, X11             // c462313eda
+	//TODO: VPMAXUW X11, X9, X11            // c442313edb
+	//TODO: VPMAXUW (BX), Y15, Y2           // c4e2053e13
+	//TODO: VPMAXUW (R11), Y15, Y2          // c4c2053e13
+	//TODO: VPMAXUW Y2, Y15, Y2             // c4e2053ed2
+	//TODO: VPMAXUW Y11, Y15, Y2            // c4c2053ed3
+	//TODO: VPMAXUW (BX), Y15, Y11          // c462053e1b
+	//TODO: VPMAXUW (R11), Y15, Y11         // c442053e1b
+	//TODO: VPMAXUW Y2, Y15, Y11            // c462053eda
+	//TODO: VPMAXUW Y11, Y15, Y11           // c442053edb
+	//TODO: VPMINSB (BX), X9, X2            // c4e2313813
+	//TODO: VPMINSB (R11), X9, X2           // c4c2313813
+	//TODO: VPMINSB X2, X9, X2              // c4e23138d2
+	//TODO: VPMINSB X11, X9, X2             // c4c23138d3
+	//TODO: VPMINSB (BX), X9, X11           // c46231381b
+	//TODO: VPMINSB (R11), X9, X11          // c44231381b
+	//TODO: VPMINSB X2, X9, X11             // c4623138da
+	//TODO: VPMINSB X11, X9, X11            // c4423138db
+	//TODO: VPMINSB (BX), Y15, Y2           // c4e2053813
+	//TODO: VPMINSB (R11), Y15, Y2          // c4c2053813
+	//TODO: VPMINSB Y2, Y15, Y2             // c4e20538d2
+	//TODO: VPMINSB Y11, Y15, Y2            // c4c20538d3
+	//TODO: VPMINSB (BX), Y15, Y11          // c46205381b
+	//TODO: VPMINSB (R11), Y15, Y11         // c44205381b
+	//TODO: VPMINSB Y2, Y15, Y11            // c4620538da
+	//TODO: VPMINSB Y11, Y15, Y11           // c4420538db
+	//TODO: VPMINSD (BX), X9, X2            // c4e2313913
+	//TODO: VPMINSD (R11), X9, X2           // c4c2313913
+	//TODO: VPMINSD X2, X9, X2              // c4e23139d2
+	//TODO: VPMINSD X11, X9, X2             // c4c23139d3
+	//TODO: VPMINSD (BX), X9, X11           // c46231391b
+	//TODO: VPMINSD (R11), X9, X11          // c44231391b
+	//TODO: VPMINSD X2, X9, X11             // c4623139da
+	//TODO: VPMINSD X11, X9, X11            // c4423139db
+	//TODO: VPMINSD (BX), Y15, Y2           // c4e2053913
+	//TODO: VPMINSD (R11), Y15, Y2          // c4c2053913
+	//TODO: VPMINSD Y2, Y15, Y2             // c4e20539d2
+	//TODO: VPMINSD Y11, Y15, Y2            // c4c20539d3
+	//TODO: VPMINSD (BX), Y15, Y11          // c46205391b
+	//TODO: VPMINSD (R11), Y15, Y11         // c44205391b
+	//TODO: VPMINSD Y2, Y15, Y11            // c4620539da
+	//TODO: VPMINSD Y11, Y15, Y11           // c4420539db
+	//TODO: VPMINSW (BX), X9, X2            // c4e131ea13 or c5b1ea13
+	//TODO: VPMINSW (R11), X9, X2           // c4c131ea13
+	//TODO: VPMINSW X2, X9, X2              // c4e131ead2 or c5b1ead2
+	//TODO: VPMINSW X11, X9, X2             // c4c131ead3
+	//TODO: VPMINSW (BX), X9, X11           // c46131ea1b or c531ea1b
+	//TODO: VPMINSW (R11), X9, X11          // c44131ea1b
+	//TODO: VPMINSW X2, X9, X11             // c46131eada or c531eada
+	//TODO: VPMINSW X11, X9, X11            // c44131eadb
+	//TODO: VPMINSW (BX), Y15, Y2           // c4e105ea13 or c585ea13
+	//TODO: VPMINSW (R11), Y15, Y2          // c4c105ea13
+	//TODO: VPMINSW Y2, Y15, Y2             // c4e105ead2 or c585ead2
+	//TODO: VPMINSW Y11, Y15, Y2            // c4c105ead3
+	//TODO: VPMINSW (BX), Y15, Y11          // c46105ea1b or c505ea1b
+	//TODO: VPMINSW (R11), Y15, Y11         // c44105ea1b
+	//TODO: VPMINSW Y2, Y15, Y11            // c46105eada or c505eada
+	//TODO: VPMINSW Y11, Y15, Y11           // c44105eadb
+	//TODO: VPMINUB (BX), X9, X2            // c4e131da13 or c5b1da13
+	//TODO: VPMINUB (R11), X9, X2           // c4c131da13
+	//TODO: VPMINUB X2, X9, X2              // c4e131dad2 or c5b1dad2
+	//TODO: VPMINUB X11, X9, X2             // c4c131dad3
+	//TODO: VPMINUB (BX), X9, X11           // c46131da1b or c531da1b
+	//TODO: VPMINUB (R11), X9, X11          // c44131da1b
+	//TODO: VPMINUB X2, X9, X11             // c46131dada or c531dada
+	//TODO: VPMINUB X11, X9, X11            // c44131dadb
+	//TODO: VPMINUB (BX), Y15, Y2           // c4e105da13 or c585da13
+	//TODO: VPMINUB (R11), Y15, Y2          // c4c105da13
+	//TODO: VPMINUB Y2, Y15, Y2             // c4e105dad2 or c585dad2
+	//TODO: VPMINUB Y11, Y15, Y2            // c4c105dad3
+	//TODO: VPMINUB (BX), Y15, Y11          // c46105da1b or c505da1b
+	//TODO: VPMINUB (R11), Y15, Y11         // c44105da1b
+	//TODO: VPMINUB Y2, Y15, Y11            // c46105dada or c505dada
+	//TODO: VPMINUB Y11, Y15, Y11           // c44105dadb
+	//TODO: VPMINUD (BX), X9, X2            // c4e2313b13
+	//TODO: VPMINUD (R11), X9, X2           // c4c2313b13
+	//TODO: VPMINUD X2, X9, X2              // c4e2313bd2
+	//TODO: VPMINUD X11, X9, X2             // c4c2313bd3
+	//TODO: VPMINUD (BX), X9, X11           // c462313b1b
+	//TODO: VPMINUD (R11), X9, X11          // c442313b1b
+	//TODO: VPMINUD X2, X9, X11             // c462313bda
+	//TODO: VPMINUD X11, X9, X11            // c442313bdb
+	//TODO: VPMINUD (BX), Y15, Y2           // c4e2053b13
+	//TODO: VPMINUD (R11), Y15, Y2          // c4c2053b13
+	//TODO: VPMINUD Y2, Y15, Y2             // c4e2053bd2
+	//TODO: VPMINUD Y11, Y15, Y2            // c4c2053bd3
+	//TODO: VPMINUD (BX), Y15, Y11          // c462053b1b
+	//TODO: VPMINUD (R11), Y15, Y11         // c442053b1b
+	//TODO: VPMINUD Y2, Y15, Y11            // c462053bda
+	//TODO: VPMINUD Y11, Y15, Y11           // c442053bdb
+	//TODO: VPMINUW (BX), X9, X2            // c4e2313a13
+	//TODO: VPMINUW (R11), X9, X2           // c4c2313a13
+	//TODO: VPMINUW X2, X9, X2              // c4e2313ad2
+	//TODO: VPMINUW X11, X9, X2             // c4c2313ad3
+	//TODO: VPMINUW (BX), X9, X11           // c462313a1b
+	//TODO: VPMINUW (R11), X9, X11          // c442313a1b
+	//TODO: VPMINUW X2, X9, X11             // c462313ada
+	//TODO: VPMINUW X11, X9, X11            // c442313adb
+	//TODO: VPMINUW (BX), Y15, Y2           // c4e2053a13
+	//TODO: VPMINUW (R11), Y15, Y2          // c4c2053a13
+	//TODO: VPMINUW Y2, Y15, Y2             // c4e2053ad2
+	//TODO: VPMINUW Y11, Y15, Y2            // c4c2053ad3
+	//TODO: VPMINUW (BX), Y15, Y11          // c462053a1b
+	//TODO: VPMINUW (R11), Y15, Y11         // c442053a1b
+	//TODO: VPMINUW Y2, Y15, Y11            // c462053ada
+	//TODO: VPMINUW Y11, Y15, Y11           // c442053adb
+	VPMOVMSKB X2, DX                        // c4e179d7d2 or c5f9d7d2
+	VPMOVMSKB X11, DX                       // c4c179d7d3
+	VPMOVMSKB X2, R11                       // c46179d7da or c579d7da
+	VPMOVMSKB X11, R11                      // c44179d7db
+	VPMOVMSKB Y2, DX                        // c4e17dd7d2 or c5fdd7d2
+	VPMOVMSKB Y11, DX                       // c4c17dd7d3
+	VPMOVMSKB Y2, R11                       // c4617dd7da or c57dd7da
+	VPMOVMSKB Y11, R11                      // c4417dd7db
+	//TODO: VPMOVSXBD (BX), X2              // c4e2792113
+	//TODO: VPMOVSXBD (R11), X2             // c4c2792113
+	//TODO: VPMOVSXBD X2, X2                // c4e27921d2
+	//TODO: VPMOVSXBD X11, X2               // c4c27921d3
+	//TODO: VPMOVSXBD (BX), X11             // c46279211b
+	//TODO: VPMOVSXBD (R11), X11            // c44279211b
+	//TODO: VPMOVSXBD X2, X11               // c4627921da
+	//TODO: VPMOVSXBD X11, X11              // c4427921db
+	//TODO: VPMOVSXBD (BX), Y2              // c4e27d2113
+	//TODO: VPMOVSXBD (R11), Y2             // c4c27d2113
+	//TODO: VPMOVSXBD X2, Y2                // c4e27d21d2
+	//TODO: VPMOVSXBD X11, Y2               // c4c27d21d3
+	//TODO: VPMOVSXBD (BX), Y11             // c4627d211b
+	//TODO: VPMOVSXBD (R11), Y11            // c4427d211b
+	//TODO: VPMOVSXBD X2, Y11               // c4627d21da
+	//TODO: VPMOVSXBD X11, Y11              // c4427d21db
+	//TODO: VPMOVSXBQ (BX), X2              // c4e2792213
+	//TODO: VPMOVSXBQ (R11), X2             // c4c2792213
+	//TODO: VPMOVSXBQ X2, X2                // c4e27922d2
+	//TODO: VPMOVSXBQ X11, X2               // c4c27922d3
+	//TODO: VPMOVSXBQ (BX), X11             // c46279221b
+	//TODO: VPMOVSXBQ (R11), X11            // c44279221b
+	//TODO: VPMOVSXBQ X2, X11               // c4627922da
+	//TODO: VPMOVSXBQ X11, X11              // c4427922db
+	//TODO: VPMOVSXBQ (BX), Y2              // c4e27d2213
+	//TODO: VPMOVSXBQ (R11), Y2             // c4c27d2213
+	//TODO: VPMOVSXBQ X2, Y2                // c4e27d22d2
+	//TODO: VPMOVSXBQ X11, Y2               // c4c27d22d3
+	//TODO: VPMOVSXBQ (BX), Y11             // c4627d221b
+	//TODO: VPMOVSXBQ (R11), Y11            // c4427d221b
+	//TODO: VPMOVSXBQ X2, Y11               // c4627d22da
+	//TODO: VPMOVSXBQ X11, Y11              // c4427d22db
+	//TODO: VPMOVSXBW (BX), X2              // c4e2792013
+	//TODO: VPMOVSXBW (R11), X2             // c4c2792013
+	//TODO: VPMOVSXBW X2, X2                // c4e27920d2
+	//TODO: VPMOVSXBW X11, X2               // c4c27920d3
+	//TODO: VPMOVSXBW (BX), X11             // c46279201b
+	//TODO: VPMOVSXBW (R11), X11            // c44279201b
+	//TODO: VPMOVSXBW X2, X11               // c4627920da
+	//TODO: VPMOVSXBW X11, X11              // c4427920db
+	//TODO: VPMOVSXBW (BX), Y2              // c4e27d2013
+	//TODO: VPMOVSXBW (R11), Y2             // c4c27d2013
+	//TODO: VPMOVSXBW X2, Y2                // c4e27d20d2
+	//TODO: VPMOVSXBW X11, Y2               // c4c27d20d3
+	//TODO: VPMOVSXBW (BX), Y11             // c4627d201b
+	//TODO: VPMOVSXBW (R11), Y11            // c4427d201b
+	//TODO: VPMOVSXBW X2, Y11               // c4627d20da
+	//TODO: VPMOVSXBW X11, Y11              // c4427d20db
+	//TODO: VPMOVSXDQ (BX), X2              // c4e2792513
+	//TODO: VPMOVSXDQ (R11), X2             // c4c2792513
+	//TODO: VPMOVSXDQ X2, X2                // c4e27925d2
+	//TODO: VPMOVSXDQ X11, X2               // c4c27925d3
+	//TODO: VPMOVSXDQ (BX), X11             // c46279251b
+	//TODO: VPMOVSXDQ (R11), X11            // c44279251b
+	//TODO: VPMOVSXDQ X2, X11               // c4627925da
+	//TODO: VPMOVSXDQ X11, X11              // c4427925db
+	//TODO: VPMOVSXDQ (BX), Y2              // c4e27d2513
+	//TODO: VPMOVSXDQ (R11), Y2             // c4c27d2513
+	//TODO: VPMOVSXDQ X2, Y2                // c4e27d25d2
+	//TODO: VPMOVSXDQ X11, Y2               // c4c27d25d3
+	//TODO: VPMOVSXDQ (BX), Y11             // c4627d251b
+	//TODO: VPMOVSXDQ (R11), Y11            // c4427d251b
+	//TODO: VPMOVSXDQ X2, Y11               // c4627d25da
+	//TODO: VPMOVSXDQ X11, Y11              // c4427d25db
+	//TODO: VPMOVSXWD (BX), X2              // c4e2792313
+	//TODO: VPMOVSXWD (R11), X2             // c4c2792313
+	//TODO: VPMOVSXWD X2, X2                // c4e27923d2
+	//TODO: VPMOVSXWD X11, X2               // c4c27923d3
+	//TODO: VPMOVSXWD (BX), X11             // c46279231b
+	//TODO: VPMOVSXWD (R11), X11            // c44279231b
+	//TODO: VPMOVSXWD X2, X11               // c4627923da
+	//TODO: VPMOVSXWD X11, X11              // c4427923db
+	//TODO: VPMOVSXWD (BX), Y2              // c4e27d2313
+	//TODO: VPMOVSXWD (R11), Y2             // c4c27d2313
+	//TODO: VPMOVSXWD X2, Y2                // c4e27d23d2
+	//TODO: VPMOVSXWD X11, Y2               // c4c27d23d3
+	//TODO: VPMOVSXWD (BX), Y11             // c4627d231b
+	//TODO: VPMOVSXWD (R11), Y11            // c4427d231b
+	//TODO: VPMOVSXWD X2, Y11               // c4627d23da
+	//TODO: VPMOVSXWD X11, Y11              // c4427d23db
+	//TODO: VPMOVSXWQ (BX), X2              // c4e2792413
+	//TODO: VPMOVSXWQ (R11), X2             // c4c2792413
+	//TODO: VPMOVSXWQ X2, X2                // c4e27924d2
+	//TODO: VPMOVSXWQ X11, X2               // c4c27924d3
+	//TODO: VPMOVSXWQ (BX), X11             // c46279241b
+	//TODO: VPMOVSXWQ (R11), X11            // c44279241b
+	//TODO: VPMOVSXWQ X2, X11               // c4627924da
+	//TODO: VPMOVSXWQ X11, X11              // c4427924db
+	//TODO: VPMOVSXWQ (BX), Y2              // c4e27d2413
+	//TODO: VPMOVSXWQ (R11), Y2             // c4c27d2413
+	//TODO: VPMOVSXWQ X2, Y2                // c4e27d24d2
+	//TODO: VPMOVSXWQ X11, Y2               // c4c27d24d3
+	//TODO: VPMOVSXWQ (BX), Y11             // c4627d241b
+	//TODO: VPMOVSXWQ (R11), Y11            // c4427d241b
+	//TODO: VPMOVSXWQ X2, Y11               // c4627d24da
+	//TODO: VPMOVSXWQ X11, Y11              // c4427d24db
+	//TODO: VPMOVZXBD (BX), X2              // c4e2793113
+	//TODO: VPMOVZXBD (R11), X2             // c4c2793113
+	//TODO: VPMOVZXBD X2, X2                // c4e27931d2
+	//TODO: VPMOVZXBD X11, X2               // c4c27931d3
+	//TODO: VPMOVZXBD (BX), X11             // c46279311b
+	//TODO: VPMOVZXBD (R11), X11            // c44279311b
+	//TODO: VPMOVZXBD X2, X11               // c4627931da
+	//TODO: VPMOVZXBD X11, X11              // c4427931db
+	//TODO: VPMOVZXBD (BX), Y2              // c4e27d3113
+	//TODO: VPMOVZXBD (R11), Y2             // c4c27d3113
+	//TODO: VPMOVZXBD X2, Y2                // c4e27d31d2
+	//TODO: VPMOVZXBD X11, Y2               // c4c27d31d3
+	//TODO: VPMOVZXBD (BX), Y11             // c4627d311b
+	//TODO: VPMOVZXBD (R11), Y11            // c4427d311b
+	//TODO: VPMOVZXBD X2, Y11               // c4627d31da
+	//TODO: VPMOVZXBD X11, Y11              // c4427d31db
+	//TODO: VPMOVZXBQ (BX), X2              // c4e2793213
+	//TODO: VPMOVZXBQ (R11), X2             // c4c2793213
+	//TODO: VPMOVZXBQ X2, X2                // c4e27932d2
+	//TODO: VPMOVZXBQ X11, X2               // c4c27932d3
+	//TODO: VPMOVZXBQ (BX), X11             // c46279321b
+	//TODO: VPMOVZXBQ (R11), X11            // c44279321b
+	//TODO: VPMOVZXBQ X2, X11               // c4627932da
+	//TODO: VPMOVZXBQ X11, X11              // c4427932db
+	//TODO: VPMOVZXBQ (BX), Y2              // c4e27d3213
+	//TODO: VPMOVZXBQ (R11), Y2             // c4c27d3213
+	//TODO: VPMOVZXBQ X2, Y2                // c4e27d32d2
+	//TODO: VPMOVZXBQ X11, Y2               // c4c27d32d3
+	//TODO: VPMOVZXBQ (BX), Y11             // c4627d321b
+	//TODO: VPMOVZXBQ (R11), Y11            // c4427d321b
+	//TODO: VPMOVZXBQ X2, Y11               // c4627d32da
+	//TODO: VPMOVZXBQ X11, Y11              // c4427d32db
+	//TODO: VPMOVZXBW (BX), X2              // c4e2793013
+	//TODO: VPMOVZXBW (R11), X2             // c4c2793013
+	//TODO: VPMOVZXBW X2, X2                // c4e27930d2
+	//TODO: VPMOVZXBW X11, X2               // c4c27930d3
+	//TODO: VPMOVZXBW (BX), X11             // c46279301b
+	//TODO: VPMOVZXBW (R11), X11            // c44279301b
+	//TODO: VPMOVZXBW X2, X11               // c4627930da
+	//TODO: VPMOVZXBW X11, X11              // c4427930db
+	//TODO: VPMOVZXBW (BX), Y2              // c4e27d3013
+	//TODO: VPMOVZXBW (R11), Y2             // c4c27d3013
+	//TODO: VPMOVZXBW X2, Y2                // c4e27d30d2
+	//TODO: VPMOVZXBW X11, Y2               // c4c27d30d3
+	//TODO: VPMOVZXBW (BX), Y11             // c4627d301b
+	//TODO: VPMOVZXBW (R11), Y11            // c4427d301b
+	//TODO: VPMOVZXBW X2, Y11               // c4627d30da
+	//TODO: VPMOVZXBW X11, Y11              // c4427d30db
+	//TODO: VPMOVZXDQ (BX), X2              // c4e2793513
+	//TODO: VPMOVZXDQ (R11), X2             // c4c2793513
+	//TODO: VPMOVZXDQ X2, X2                // c4e27935d2
+	//TODO: VPMOVZXDQ X11, X2               // c4c27935d3
+	//TODO: VPMOVZXDQ (BX), X11             // c46279351b
+	//TODO: VPMOVZXDQ (R11), X11            // c44279351b
+	//TODO: VPMOVZXDQ X2, X11               // c4627935da
+	//TODO: VPMOVZXDQ X11, X11              // c4427935db
+	//TODO: VPMOVZXDQ (BX), Y2              // c4e27d3513
+	//TODO: VPMOVZXDQ (R11), Y2             // c4c27d3513
+	//TODO: VPMOVZXDQ X2, Y2                // c4e27d35d2
+	//TODO: VPMOVZXDQ X11, Y2               // c4c27d35d3
+	//TODO: VPMOVZXDQ (BX), Y11             // c4627d351b
+	//TODO: VPMOVZXDQ (R11), Y11            // c4427d351b
+	//TODO: VPMOVZXDQ X2, Y11               // c4627d35da
+	//TODO: VPMOVZXDQ X11, Y11              // c4427d35db
+	//TODO: VPMOVZXWD (BX), X2              // c4e2793313
+	//TODO: VPMOVZXWD (R11), X2             // c4c2793313
+	//TODO: VPMOVZXWD X2, X2                // c4e27933d2
+	//TODO: VPMOVZXWD X11, X2               // c4c27933d3
+	//TODO: VPMOVZXWD (BX), X11             // c46279331b
+	//TODO: VPMOVZXWD (R11), X11            // c44279331b
+	//TODO: VPMOVZXWD X2, X11               // c4627933da
+	//TODO: VPMOVZXWD X11, X11              // c4427933db
+	//TODO: VPMOVZXWD (BX), Y2              // c4e27d3313
+	//TODO: VPMOVZXWD (R11), Y2             // c4c27d3313
+	//TODO: VPMOVZXWD X2, Y2                // c4e27d33d2
+	//TODO: VPMOVZXWD X11, Y2               // c4c27d33d3
+	//TODO: VPMOVZXWD (BX), Y11             // c4627d331b
+	//TODO: VPMOVZXWD (R11), Y11            // c4427d331b
+	//TODO: VPMOVZXWD X2, Y11               // c4627d33da
+	//TODO: VPMOVZXWD X11, Y11              // c4427d33db
+	//TODO: VPMOVZXWQ (BX), X2              // c4e2793413
+	//TODO: VPMOVZXWQ (R11), X2             // c4c2793413
+	//TODO: VPMOVZXWQ X2, X2                // c4e27934d2
+	//TODO: VPMOVZXWQ X11, X2               // c4c27934d3
+	//TODO: VPMOVZXWQ (BX), X11             // c46279341b
+	//TODO: VPMOVZXWQ (R11), X11            // c44279341b
+	//TODO: VPMOVZXWQ X2, X11               // c4627934da
+	//TODO: VPMOVZXWQ X11, X11              // c4427934db
+	//TODO: VPMOVZXWQ (BX), Y2              // c4e27d3413
+	//TODO: VPMOVZXWQ (R11), Y2             // c4c27d3413
+	//TODO: VPMOVZXWQ X2, Y2                // c4e27d34d2
+	//TODO: VPMOVZXWQ X11, Y2               // c4c27d34d3
+	//TODO: VPMOVZXWQ (BX), Y11             // c4627d341b
+	//TODO: VPMOVZXWQ (R11), Y11            // c4427d341b
+	//TODO: VPMOVZXWQ X2, Y11               // c4627d34da
+	//TODO: VPMOVZXWQ X11, Y11              // c4427d34db
+	//TODO: VPMULDQ (BX), X9, X2            // c4e2312813
+	//TODO: VPMULDQ (R11), X9, X2           // c4c2312813
+	//TODO: VPMULDQ X2, X9, X2              // c4e23128d2
+	//TODO: VPMULDQ X11, X9, X2             // c4c23128d3
+	//TODO: VPMULDQ (BX), X9, X11           // c46231281b
+	//TODO: VPMULDQ (R11), X9, X11          // c44231281b
+	//TODO: VPMULDQ X2, X9, X11             // c4623128da
+	//TODO: VPMULDQ X11, X9, X11            // c4423128db
+	//TODO: VPMULDQ (BX), Y15, Y2           // c4e2052813
+	//TODO: VPMULDQ (R11), Y15, Y2          // c4c2052813
+	//TODO: VPMULDQ Y2, Y15, Y2             // c4e20528d2
+	//TODO: VPMULDQ Y11, Y15, Y2            // c4c20528d3
+	//TODO: VPMULDQ (BX), Y15, Y11          // c46205281b
+	//TODO: VPMULDQ (R11), Y15, Y11         // c44205281b
+	//TODO: VPMULDQ Y2, Y15, Y11            // c4620528da
+	//TODO: VPMULDQ Y11, Y15, Y11           // c4420528db
+	//TODO: VPMULHRSW (BX), X9, X2          // c4e2310b13
+	//TODO: VPMULHRSW (R11), X9, X2         // c4c2310b13
+	//TODO: VPMULHRSW X2, X9, X2            // c4e2310bd2
+	//TODO: VPMULHRSW X11, X9, X2           // c4c2310bd3
+	//TODO: VPMULHRSW (BX), X9, X11         // c462310b1b
+	//TODO: VPMULHRSW (R11), X9, X11        // c442310b1b
+	//TODO: VPMULHRSW X2, X9, X11           // c462310bda
+	//TODO: VPMULHRSW X11, X9, X11          // c442310bdb
+	//TODO: VPMULHRSW (BX), Y15, Y2         // c4e2050b13
+	//TODO: VPMULHRSW (R11), Y15, Y2        // c4c2050b13
+	//TODO: VPMULHRSW Y2, Y15, Y2           // c4e2050bd2
+	//TODO: VPMULHRSW Y11, Y15, Y2          // c4c2050bd3
+	//TODO: VPMULHRSW (BX), Y15, Y11        // c462050b1b
+	//TODO: VPMULHRSW (R11), Y15, Y11       // c442050b1b
+	//TODO: VPMULHRSW Y2, Y15, Y11          // c462050bda
+	//TODO: VPMULHRSW Y11, Y15, Y11         // c442050bdb
+	//TODO: VPMULHUW (BX), X9, X2           // c4e131e413 or c5b1e413
+	//TODO: VPMULHUW (R11), X9, X2          // c4c131e413
+	//TODO: VPMULHUW X2, X9, X2             // c4e131e4d2 or c5b1e4d2
+	//TODO: VPMULHUW X11, X9, X2            // c4c131e4d3
+	//TODO: VPMULHUW (BX), X9, X11          // c46131e41b or c531e41b
+	//TODO: VPMULHUW (R11), X9, X11         // c44131e41b
+	//TODO: VPMULHUW X2, X9, X11            // c46131e4da or c531e4da
+	//TODO: VPMULHUW X11, X9, X11           // c44131e4db
+	//TODO: VPMULHUW (BX), Y15, Y2          // c4e105e413 or c585e413
+	//TODO: VPMULHUW (R11), Y15, Y2         // c4c105e413
+	//TODO: VPMULHUW Y2, Y15, Y2            // c4e105e4d2 or c585e4d2
+	//TODO: VPMULHUW Y11, Y15, Y2           // c4c105e4d3
+	//TODO: VPMULHUW (BX), Y15, Y11         // c46105e41b or c505e41b
+	//TODO: VPMULHUW (R11), Y15, Y11        // c44105e41b
+	//TODO: VPMULHUW Y2, Y15, Y11           // c46105e4da or c505e4da
+	//TODO: VPMULHUW Y11, Y15, Y11          // c44105e4db
+	//TODO: VPMULHW (BX), X9, X2            // c4e131e513 or c5b1e513
+	//TODO: VPMULHW (R11), X9, X2           // c4c131e513
+	//TODO: VPMULHW X2, X9, X2              // c4e131e5d2 or c5b1e5d2
+	//TODO: VPMULHW X11, X9, X2             // c4c131e5d3
+	//TODO: VPMULHW (BX), X9, X11           // c46131e51b or c531e51b
+	//TODO: VPMULHW (R11), X9, X11          // c44131e51b
+	//TODO: VPMULHW X2, X9, X11             // c46131e5da or c531e5da
+	//TODO: VPMULHW X11, X9, X11            // c44131e5db
+	//TODO: VPMULHW (BX), Y15, Y2           // c4e105e513 or c585e513
+	//TODO: VPMULHW (R11), Y15, Y2          // c4c105e513
+	//TODO: VPMULHW Y2, Y15, Y2             // c4e105e5d2 or c585e5d2
+	//TODO: VPMULHW Y11, Y15, Y2            // c4c105e5d3
+	//TODO: VPMULHW (BX), Y15, Y11          // c46105e51b or c505e51b
+	//TODO: VPMULHW (R11), Y15, Y11         // c44105e51b
+	//TODO: VPMULHW Y2, Y15, Y11            // c46105e5da or c505e5da
+	//TODO: VPMULHW Y11, Y15, Y11           // c44105e5db
+	//TODO: VPMULLD (BX), X9, X2            // c4e2314013
+	//TODO: VPMULLD (R11), X9, X2           // c4c2314013
+	//TODO: VPMULLD X2, X9, X2              // c4e23140d2
+	//TODO: VPMULLD X11, X9, X2             // c4c23140d3
+	//TODO: VPMULLD (BX), X9, X11           // c46231401b
+	//TODO: VPMULLD (R11), X9, X11          // c44231401b
+	//TODO: VPMULLD X2, X9, X11             // c4623140da
+	//TODO: VPMULLD X11, X9, X11            // c4423140db
+	//TODO: VPMULLD (BX), Y15, Y2           // c4e2054013
+	//TODO: VPMULLD (R11), Y15, Y2          // c4c2054013
+	//TODO: VPMULLD Y2, Y15, Y2             // c4e20540d2
+	//TODO: VPMULLD Y11, Y15, Y2            // c4c20540d3
+	//TODO: VPMULLD (BX), Y15, Y11          // c46205401b
+	//TODO: VPMULLD (R11), Y15, Y11         // c44205401b
+	//TODO: VPMULLD Y2, Y15, Y11            // c4620540da
+	//TODO: VPMULLD Y11, Y15, Y11           // c4420540db
+	//TODO: VPMULLW (BX), X9, X2            // c4e131d513 or c5b1d513
+	//TODO: VPMULLW (R11), X9, X2           // c4c131d513
+	//TODO: VPMULLW X2, X9, X2              // c4e131d5d2 or c5b1d5d2
+	//TODO: VPMULLW X11, X9, X2             // c4c131d5d3
+	//TODO: VPMULLW (BX), X9, X11           // c46131d51b or c531d51b
+	//TODO: VPMULLW (R11), X9, X11          // c44131d51b
+	//TODO: VPMULLW X2, X9, X11             // c46131d5da or c531d5da
+	//TODO: VPMULLW X11, X9, X11            // c44131d5db
+	//TODO: VPMULLW (BX), Y15, Y2           // c4e105d513 or c585d513
+	//TODO: VPMULLW (R11), Y15, Y2          // c4c105d513
+	//TODO: VPMULLW Y2, Y15, Y2             // c4e105d5d2 or c585d5d2
+	//TODO: VPMULLW Y11, Y15, Y2            // c4c105d5d3
+	//TODO: VPMULLW (BX), Y15, Y11          // c46105d51b or c505d51b
+	//TODO: VPMULLW (R11), Y15, Y11         // c44105d51b
+	//TODO: VPMULLW Y2, Y15, Y11            // c46105d5da or c505d5da
+	//TODO: VPMULLW Y11, Y15, Y11           // c44105d5db
+	//TODO: VPMULUDQ (BX), X9, X2           // c4e131f413 or c5b1f413
+	//TODO: VPMULUDQ (R11), X9, X2          // c4c131f413
+	//TODO: VPMULUDQ X2, X9, X2             // c4e131f4d2 or c5b1f4d2
+	//TODO: VPMULUDQ X11, X9, X2            // c4c131f4d3
+	//TODO: VPMULUDQ (BX), X9, X11          // c46131f41b or c531f41b
+	//TODO: VPMULUDQ (R11), X9, X11         // c44131f41b
+	//TODO: VPMULUDQ X2, X9, X11            // c46131f4da or c531f4da
+	//TODO: VPMULUDQ X11, X9, X11           // c44131f4db
+	//TODO: VPMULUDQ (BX), Y15, Y2          // c4e105f413 or c585f413
+	//TODO: VPMULUDQ (R11), Y15, Y2         // c4c105f413
+	//TODO: VPMULUDQ Y2, Y15, Y2            // c4e105f4d2 or c585f4d2
+	//TODO: VPMULUDQ Y11, Y15, Y2           // c4c105f4d3
+	//TODO: VPMULUDQ (BX), Y15, Y11         // c46105f41b or c505f41b
+	//TODO: VPMULUDQ (R11), Y15, Y11        // c44105f41b
+	//TODO: VPMULUDQ Y2, Y15, Y11           // c46105f4da or c505f4da
+	//TODO: VPMULUDQ Y11, Y15, Y11          // c44105f4db
+	//TODO: VPOR (BX), X9, X2               // c4e131eb13 or c5b1eb13
+	//TODO: VPOR (R11), X9, X2              // c4c131eb13
+	//TODO: VPOR X2, X9, X2                 // c4e131ebd2 or c5b1ebd2
+	//TODO: VPOR X11, X9, X2                // c4c131ebd3
+	//TODO: VPOR (BX), X9, X11              // c46131eb1b or c531eb1b
+	//TODO: VPOR (R11), X9, X11             // c44131eb1b
+	//TODO: VPOR X2, X9, X11                // c46131ebda or c531ebda
+	//TODO: VPOR X11, X9, X11               // c44131ebdb
+	//TODO: VPOR (BX), Y15, Y2              // c4e105eb13 or c585eb13
+	//TODO: VPOR (R11), Y15, Y2             // c4c105eb13
+	//TODO: VPOR Y2, Y15, Y2                // c4e105ebd2 or c585ebd2
+	//TODO: VPOR Y11, Y15, Y2               // c4c105ebd3
+	//TODO: VPOR (BX), Y15, Y11             // c46105eb1b or c505eb1b
+	//TODO: VPOR (R11), Y15, Y11            // c44105eb1b
+	//TODO: VPOR Y2, Y15, Y11               // c46105ebda or c505ebda
+	//TODO: VPOR Y11, Y15, Y11              // c44105ebdb
+	//TODO: VPSADBW (BX), X9, X2            // c4e131f613 or c5b1f613
+	//TODO: VPSADBW (R11), X9, X2           // c4c131f613
+	//TODO: VPSADBW X2, X9, X2              // c4e131f6d2 or c5b1f6d2
+	//TODO: VPSADBW X11, X9, X2             // c4c131f6d3
+	//TODO: VPSADBW (BX), X9, X11           // c46131f61b or c531f61b
+	//TODO: VPSADBW (R11), X9, X11          // c44131f61b
+	//TODO: VPSADBW X2, X9, X11             // c46131f6da or c531f6da
+	//TODO: VPSADBW X11, X9, X11            // c44131f6db
+	//TODO: VPSADBW (BX), Y15, Y2           // c4e105f613 or c585f613
+	//TODO: VPSADBW (R11), Y15, Y2          // c4c105f613
+	//TODO: VPSADBW Y2, Y15, Y2             // c4e105f6d2 or c585f6d2
+	//TODO: VPSADBW Y11, Y15, Y2            // c4c105f6d3
+	//TODO: VPSADBW (BX), Y15, Y11          // c46105f61b or c505f61b
+	//TODO: VPSADBW (R11), Y15, Y11         // c44105f61b
+	//TODO: VPSADBW Y2, Y15, Y11            // c46105f6da or c505f6da
+	//TODO: VPSADBW Y11, Y15, Y11           // c44105f6db
+	//TODO: VPSHUFB (BX), X9, X2            // c4e2310013
+	//TODO: VPSHUFB (R11), X9, X2           // c4c2310013
+	//TODO: VPSHUFB X2, X9, X2              // c4e23100d2
+	//TODO: VPSHUFB X11, X9, X2             // c4c23100d3
+	//TODO: VPSHUFB (BX), X9, X11           // c46231001b
+	//TODO: VPSHUFB (R11), X9, X11          // c44231001b
+	//TODO: VPSHUFB X2, X9, X11             // c4623100da
+	//TODO: VPSHUFB X11, X9, X11            // c4423100db
+	//TODO: VPSHUFB (BX), Y15, Y2           // c4e2050013
+	//TODO: VPSHUFB (R11), Y15, Y2          // c4c2050013
+	//TODO: VPSHUFB Y2, Y15, Y2             // c4e20500d2
+	//TODO: VPSHUFB Y11, Y15, Y2            // c4c20500d3
+	//TODO: VPSHUFB (BX), Y15, Y11          // c46205001b
+	//TODO: VPSHUFB (R11), Y15, Y11         // c44205001b
+	//TODO: VPSHUFB Y2, Y15, Y11            // c4620500da
+	//TODO: VPSHUFB Y11, Y15, Y11           // c4420500db
+	//TODO: VPSHUFD $7, (BX), X2            // c4e179701307 or c5f9701307
+	//TODO: VPSHUFD $7, (R11), X2           // c4c179701307
+	//TODO: VPSHUFD $7, X2, X2              // c4e17970d207 or c5f970d207
+	//TODO: VPSHUFD $7, X11, X2             // c4c17970d307
+	//TODO: VPSHUFD $7, (BX), X11           // c46179701b07 or c579701b07
+	//TODO: VPSHUFD $7, (R11), X11          // c44179701b07
+	//TODO: VPSHUFD $7, X2, X11             // c4617970da07 or c57970da07
+	//TODO: VPSHUFD $7, X11, X11            // c4417970db07
+	//TODO: VPSHUFD $7, (BX), Y2            // c4e17d701307 or c5fd701307
+	//TODO: VPSHUFD $7, (R11), Y2           // c4c17d701307
+	//TODO: VPSHUFD $7, Y2, Y2              // c4e17d70d207 or c5fd70d207
+	//TODO: VPSHUFD $7, Y11, Y2             // c4c17d70d307
+	//TODO: VPSHUFD $7, (BX), Y11           // c4617d701b07 or c57d701b07
+	//TODO: VPSHUFD $7, (R11), Y11          // c4417d701b07
+	//TODO: VPSHUFD $7, Y2, Y11             // c4617d70da07 or c57d70da07
+	//TODO: VPSHUFD $7, Y11, Y11            // c4417d70db07
+	//TODO: VPSHUFHW $7, (BX), X2           // c4e17a701307 or c5fa701307
+	//TODO: VPSHUFHW $7, (R11), X2          // c4c17a701307
+	//TODO: VPSHUFHW $7, X2, X2             // c4e17a70d207 or c5fa70d207
+	//TODO: VPSHUFHW $7, X11, X2            // c4c17a70d307
+	//TODO: VPSHUFHW $7, (BX), X11          // c4617a701b07 or c57a701b07
+	//TODO: VPSHUFHW $7, (R11), X11         // c4417a701b07
+	//TODO: VPSHUFHW $7, X2, X11            // c4617a70da07 or c57a70da07
+	//TODO: VPSHUFHW $7, X11, X11           // c4417a70db07
+	//TODO: VPSHUFHW $7, (BX), Y2           // c4e17e701307 or c5fe701307
+	//TODO: VPSHUFHW $7, (R11), Y2          // c4c17e701307
+	//TODO: VPSHUFHW $7, Y2, Y2             // c4e17e70d207 or c5fe70d207
+	//TODO: VPSHUFHW $7, Y11, Y2            // c4c17e70d307
+	//TODO: VPSHUFHW $7, (BX), Y11          // c4617e701b07 or c57e701b07
+	//TODO: VPSHUFHW $7, (R11), Y11         // c4417e701b07
+	//TODO: VPSHUFHW $7, Y2, Y11            // c4617e70da07 or c57e70da07
+	//TODO: VPSHUFHW $7, Y11, Y11           // c4417e70db07
+	//TODO: VPSHUFLW $7, (BX), X2           // c4e17b701307 or c5fb701307
+	//TODO: VPSHUFLW $7, (R11), X2          // c4c17b701307
+	//TODO: VPSHUFLW $7, X2, X2             // c4e17b70d207 or c5fb70d207
+	//TODO: VPSHUFLW $7, X11, X2            // c4c17b70d307
+	//TODO: VPSHUFLW $7, (BX), X11          // c4617b701b07 or c57b701b07
+	//TODO: VPSHUFLW $7, (R11), X11         // c4417b701b07
+	//TODO: VPSHUFLW $7, X2, X11            // c4617b70da07 or c57b70da07
+	//TODO: VPSHUFLW $7, X11, X11           // c4417b70db07
+	//TODO: VPSHUFLW $7, (BX), Y2           // c4e17f701307 or c5ff701307
+	//TODO: VPSHUFLW $7, (R11), Y2          // c4c17f701307
+	//TODO: VPSHUFLW $7, Y2, Y2             // c4e17f70d207 or c5ff70d207
+	//TODO: VPSHUFLW $7, Y11, Y2            // c4c17f70d307
+	//TODO: VPSHUFLW $7, (BX), Y11          // c4617f701b07 or c57f701b07
+	//TODO: VPSHUFLW $7, (R11), Y11         // c4417f701b07
+	//TODO: VPSHUFLW $7, Y2, Y11            // c4617f70da07 or c57f70da07
+	//TODO: VPSHUFLW $7, Y11, Y11           // c4417f70db07
+	//TODO: VPSIGNB (BX), X9, X2            // c4e2310813
+	//TODO: VPSIGNB (R11), X9, X2           // c4c2310813
+	//TODO: VPSIGNB X2, X9, X2              // c4e23108d2
+	//TODO: VPSIGNB X11, X9, X2             // c4c23108d3
+	//TODO: VPSIGNB (BX), X9, X11           // c46231081b
+	//TODO: VPSIGNB (R11), X9, X11          // c44231081b
+	//TODO: VPSIGNB X2, X9, X11             // c4623108da
+	//TODO: VPSIGNB X11, X9, X11            // c4423108db
+	//TODO: VPSIGNB (BX), Y15, Y2           // c4e2050813
+	//TODO: VPSIGNB (R11), Y15, Y2          // c4c2050813
+	//TODO: VPSIGNB Y2, Y15, Y2             // c4e20508d2
+	//TODO: VPSIGNB Y11, Y15, Y2            // c4c20508d3
+	//TODO: VPSIGNB (BX), Y15, Y11          // c46205081b
+	//TODO: VPSIGNB (R11), Y15, Y11         // c44205081b
+	//TODO: VPSIGNB Y2, Y15, Y11            // c4620508da
+	//TODO: VPSIGNB Y11, Y15, Y11           // c4420508db
+	//TODO: VPSIGND (BX), X9, X2            // c4e2310a13
+	//TODO: VPSIGND (R11), X9, X2           // c4c2310a13
+	//TODO: VPSIGND X2, X9, X2              // c4e2310ad2
+	//TODO: VPSIGND X11, X9, X2             // c4c2310ad3
+	//TODO: VPSIGND (BX), X9, X11           // c462310a1b
+	//TODO: VPSIGND (R11), X9, X11          // c442310a1b
+	//TODO: VPSIGND X2, X9, X11             // c462310ada
+	//TODO: VPSIGND X11, X9, X11            // c442310adb
+	//TODO: VPSIGND (BX), Y15, Y2           // c4e2050a13
+	//TODO: VPSIGND (R11), Y15, Y2          // c4c2050a13
+	//TODO: VPSIGND Y2, Y15, Y2             // c4e2050ad2
+	//TODO: VPSIGND Y11, Y15, Y2            // c4c2050ad3
+	//TODO: VPSIGND (BX), Y15, Y11          // c462050a1b
+	//TODO: VPSIGND (R11), Y15, Y11         // c442050a1b
+	//TODO: VPSIGND Y2, Y15, Y11            // c462050ada
+	//TODO: VPSIGND Y11, Y15, Y11           // c442050adb
+	//TODO: VPSIGNW (BX), X9, X2            // c4e2310913
+	//TODO: VPSIGNW (R11), X9, X2           // c4c2310913
+	//TODO: VPSIGNW X2, X9, X2              // c4e23109d2
+	//TODO: VPSIGNW X11, X9, X2             // c4c23109d3
+	//TODO: VPSIGNW (BX), X9, X11           // c46231091b
+	//TODO: VPSIGNW (R11), X9, X11          // c44231091b
+	//TODO: VPSIGNW X2, X9, X11             // c4623109da
+	//TODO: VPSIGNW X11, X9, X11            // c4423109db
+	//TODO: VPSIGNW (BX), Y15, Y2           // c4e2050913
+	//TODO: VPSIGNW (R11), Y15, Y2          // c4c2050913
+	//TODO: VPSIGNW Y2, Y15, Y2             // c4e20509d2
+	//TODO: VPSIGNW Y11, Y15, Y2            // c4c20509d3
+	//TODO: VPSIGNW (BX), Y15, Y11          // c46205091b
+	//TODO: VPSIGNW (R11), Y15, Y11         // c44205091b
+	//TODO: VPSIGNW Y2, Y15, Y11            // c4620509da
+	//TODO: VPSIGNW Y11, Y15, Y11           // c4420509db
+	//TODO: VPSLLD (BX), X9, X2             // c4e131f213 or c5b1f213
+	//TODO: VPSLLD (R11), X9, X2            // c4c131f213
+	//TODO: VPSLLD X2, X9, X2               // c4e131f2d2 or c5b1f2d2
+	//TODO: VPSLLD X11, X9, X2              // c4c131f2d3
+	//TODO: VPSLLD (BX), X9, X11            // c46131f21b or c531f21b
+	//TODO: VPSLLD (R11), X9, X11           // c44131f21b
+	//TODO: VPSLLD X2, X9, X11              // c46131f2da or c531f2da
+	//TODO: VPSLLD X11, X9, X11             // c44131f2db
+	//TODO: VPSLLD $7, X2, X9               // c4e13172f207 or c5b172f207
+	//TODO: VPSLLD $7, X11, X9              // c4c13172f307
+	//TODO: VPSLLDQ $7, X2, X9              // c4e13173fa07 or c5b173fa07
+	//TODO: VPSLLDQ $7, X11, X9             // c4c13173fb07
+	//TODO: VPSLLDQ $7, Y2, Y15             // c4e10573fa07 or c58573fa07
+	//TODO: VPSLLDQ $7, Y11, Y15            // c4c10573fb07
+	//TODO: VPSLLQ (BX), X9, X2             // c4e131f313 or c5b1f313
+	//TODO: VPSLLQ (R11), X9, X2            // c4c131f313
+	//TODO: VPSLLQ X2, X9, X2               // c4e131f3d2 or c5b1f3d2
+	//TODO: VPSLLQ X11, X9, X2              // c4c131f3d3
+	//TODO: VPSLLQ (BX), X9, X11            // c46131f31b or c531f31b
+	//TODO: VPSLLQ (R11), X9, X11           // c44131f31b
+	//TODO: VPSLLQ X2, X9, X11              // c46131f3da or c531f3da
+	//TODO: VPSLLQ X11, X9, X11             // c44131f3db
+	//TODO: VPSLLQ $7, X2, X9               // c4e13173f207 or c5b173f207
+	//TODO: VPSLLQ $7, X11, X9              // c4c13173f307
+	//TODO: VPSLLVD (BX), X9, X2            // c4e2314713
+	//TODO: VPSLLVD (R11), X9, X2           // c4c2314713
+	//TODO: VPSLLVD X2, X9, X2              // c4e23147d2
+	//TODO: VPSLLVD X11, X9, X2             // c4c23147d3
+	//TODO: VPSLLVD (BX), X9, X11           // c46231471b
+	//TODO: VPSLLVD (R11), X9, X11          // c44231471b
+	//TODO: VPSLLVD X2, X9, X11             // c4623147da
+	//TODO: VPSLLVD X11, X9, X11            // c4423147db
+	//TODO: VPSLLVD (BX), Y15, Y2           // c4e2054713
+	//TODO: VPSLLVD (R11), Y15, Y2          // c4c2054713
+	//TODO: VPSLLVD Y2, Y15, Y2             // c4e20547d2
+	//TODO: VPSLLVD Y11, Y15, Y2            // c4c20547d3
+	//TODO: VPSLLVD (BX), Y15, Y11          // c46205471b
+	//TODO: VPSLLVD (R11), Y15, Y11         // c44205471b
+	//TODO: VPSLLVD Y2, Y15, Y11            // c4620547da
+	//TODO: VPSLLVD Y11, Y15, Y11           // c4420547db
+	//TODO: VPSLLVQ (BX), X9, X2            // c4e2b14713
+	//TODO: VPSLLVQ (R11), X9, X2           // c4c2b14713
+	//TODO: VPSLLVQ X2, X9, X2              // c4e2b147d2
+	//TODO: VPSLLVQ X11, X9, X2             // c4c2b147d3
+	//TODO: VPSLLVQ (BX), X9, X11           // c462b1471b
+	//TODO: VPSLLVQ (R11), X9, X11          // c442b1471b
+	//TODO: VPSLLVQ X2, X9, X11             // c462b147da
+	//TODO: VPSLLVQ X11, X9, X11            // c442b147db
+	//TODO: VPSLLVQ (BX), Y15, Y2           // c4e2854713
+	//TODO: VPSLLVQ (R11), Y15, Y2          // c4c2854713
+	//TODO: VPSLLVQ Y2, Y15, Y2             // c4e28547d2
+	//TODO: VPSLLVQ Y11, Y15, Y2            // c4c28547d3
+	//TODO: VPSLLVQ (BX), Y15, Y11          // c46285471b
+	//TODO: VPSLLVQ (R11), Y15, Y11         // c44285471b
+	//TODO: VPSLLVQ Y2, Y15, Y11            // c4628547da
+	//TODO: VPSLLVQ Y11, Y15, Y11           // c4428547db
+	//TODO: VPSLLW (BX), X9, X2             // c4e131f113 or c5b1f113
+	//TODO: VPSLLW (R11), X9, X2            // c4c131f113
+	//TODO: VPSLLW X2, X9, X2               // c4e131f1d2 or c5b1f1d2
+	//TODO: VPSLLW X11, X9, X2              // c4c131f1d3
+	//TODO: VPSLLW (BX), X9, X11            // c46131f11b or c531f11b
+	//TODO: VPSLLW (R11), X9, X11           // c44131f11b
+	//TODO: VPSLLW X2, X9, X11              // c46131f1da or c531f1da
+	//TODO: VPSLLW X11, X9, X11             // c44131f1db
+	//TODO: VPSLLW $7, X2, X9               // c4e13171f207 or c5b171f207
+	//TODO: VPSLLW $7, X11, X9              // c4c13171f307
+	//TODO: VPSLLW (BX), Y15, Y2            // c4e105f113 or c585f113
+	//TODO: VPSLLW (R11), Y15, Y2           // c4c105f113
+	//TODO: VPSLLW X2, Y15, Y2              // c4e105f1d2 or c585f1d2
+	//TODO: VPSLLW X11, Y15, Y2             // c4c105f1d3
+	//TODO: VPSLLW (BX), Y15, Y11           // c46105f11b or c505f11b
+	//TODO: VPSLLW (R11), Y15, Y11          // c44105f11b
+	//TODO: VPSLLW X2, Y15, Y11             // c46105f1da or c505f1da
+	//TODO: VPSLLW X11, Y15, Y11            // c44105f1db
+	//TODO: VPSLLW $7, Y2, Y15              // c4e10571f207 or c58571f207
+	//TODO: VPSLLW $7, Y11, Y15             // c4c10571f307
+	//TODO: VPSRAD (BX), X9, X2             // c4e131e213 or c5b1e213
+	//TODO: VPSRAD (R11), X9, X2            // c4c131e213
+	//TODO: VPSRAD X2, X9, X2               // c4e131e2d2 or c5b1e2d2
+	//TODO: VPSRAD X11, X9, X2              // c4c131e2d3
+	//TODO: VPSRAD (BX), X9, X11            // c46131e21b or c531e21b
+	//TODO: VPSRAD (R11), X9, X11           // c44131e21b
+	//TODO: VPSRAD X2, X9, X11              // c46131e2da or c531e2da
+	//TODO: VPSRAD X11, X9, X11             // c44131e2db
+	//TODO: VPSRAD $7, X2, X9               // c4e13172e207 or c5b172e207
+	//TODO: VPSRAD $7, X11, X9              // c4c13172e307
+	//TODO: VPSRAD (BX), Y15, Y2            // c4e105e213 or c585e213
+	//TODO: VPSRAD (R11), Y15, Y2           // c4c105e213
+	//TODO: VPSRAD X2, Y15, Y2              // c4e105e2d2 or c585e2d2
+	//TODO: VPSRAD X11, Y15, Y2             // c4c105e2d3
+	//TODO: VPSRAD (BX), Y15, Y11           // c46105e21b or c505e21b
+	//TODO: VPSRAD (R11), Y15, Y11          // c44105e21b
+	//TODO: VPSRAD X2, Y15, Y11             // c46105e2da or c505e2da
+	//TODO: VPSRAD X11, Y15, Y11            // c44105e2db
+	//TODO: VPSRAD $7, Y2, Y15              // c4e10572e207 or c58572e207
+	//TODO: VPSRAD $7, Y11, Y15             // c4c10572e307
+	//TODO: VPSRAVD (BX), X9, X2            // c4e2314613
+	//TODO: VPSRAVD (R11), X9, X2           // c4c2314613
+	//TODO: VPSRAVD X2, X9, X2              // c4e23146d2
+	//TODO: VPSRAVD X11, X9, X2             // c4c23146d3
+	//TODO: VPSRAVD (BX), X9, X11           // c46231461b
+	//TODO: VPSRAVD (R11), X9, X11          // c44231461b
+	//TODO: VPSRAVD X2, X9, X11             // c4623146da
+	//TODO: VPSRAVD X11, X9, X11            // c4423146db
+	//TODO: VPSRAVD (BX), Y15, Y2           // c4e2054613
+	//TODO: VPSRAVD (R11), Y15, Y2          // c4c2054613
+	//TODO: VPSRAVD Y2, Y15, Y2             // c4e20546d2
+	//TODO: VPSRAVD Y11, Y15, Y2            // c4c20546d3
+	//TODO: VPSRAVD (BX), Y15, Y11          // c46205461b
+	//TODO: VPSRAVD (R11), Y15, Y11         // c44205461b
+	//TODO: VPSRAVD Y2, Y15, Y11            // c4620546da
+	//TODO: VPSRAVD Y11, Y15, Y11           // c4420546db
+	//TODO: VPSRAW (BX), X9, X2             // c4e131e113 or c5b1e113
+	//TODO: VPSRAW (R11), X9, X2            // c4c131e113
+	//TODO: VPSRAW X2, X9, X2               // c4e131e1d2 or c5b1e1d2
+	//TODO: VPSRAW X11, X9, X2              // c4c131e1d3
+	//TODO: VPSRAW (BX), X9, X11            // c46131e11b or c531e11b
+	//TODO: VPSRAW (R11), X9, X11           // c44131e11b
+	//TODO: VPSRAW X2, X9, X11              // c46131e1da or c531e1da
+	//TODO: VPSRAW X11, X9, X11             // c44131e1db
+	//TODO: VPSRAW $7, X2, X9               // c4e13171e207 or c5b171e207
+	//TODO: VPSRAW $7, X11, X9              // c4c13171e307
+	//TODO: VPSRAW (BX), Y15, Y2            // c4e105e113 or c585e113
+	//TODO: VPSRAW (R11), Y15, Y2           // c4c105e113
+	//TODO: VPSRAW X2, Y15, Y2              // c4e105e1d2 or c585e1d2
+	//TODO: VPSRAW X11, Y15, Y2             // c4c105e1d3
+	//TODO: VPSRAW (BX), Y15, Y11           // c46105e11b or c505e11b
+	//TODO: VPSRAW (R11), Y15, Y11          // c44105e11b
+	//TODO: VPSRAW X2, Y15, Y11             // c46105e1da or c505e1da
+	//TODO: VPSRAW X11, Y15, Y11            // c44105e1db
+	//TODO: VPSRAW $7, Y2, Y15              // c4e10571e207 or c58571e207
+	//TODO: VPSRAW $7, Y11, Y15             // c4c10571e307
+	//TODO: VPSRLD (BX), X9, X2             // c4e131d213 or c5b1d213
+	//TODO: VPSRLD (R11), X9, X2            // c4c131d213
+	//TODO: VPSRLD X2, X9, X2               // c4e131d2d2 or c5b1d2d2
+	//TODO: VPSRLD X11, X9, X2              // c4c131d2d3
+	//TODO: VPSRLD (BX), X9, X11            // c46131d21b or c531d21b
+	//TODO: VPSRLD (R11), X9, X11           // c44131d21b
+	//TODO: VPSRLD X2, X9, X11              // c46131d2da or c531d2da
+	//TODO: VPSRLD X11, X9, X11             // c44131d2db
+	//TODO: VPSRLD $7, X2, X9               // c4e13172d207 or c5b172d207
+	//TODO: VPSRLD $7, X11, X9              // c4c13172d307
+	//TODO: VPSRLDQ $7, X2, X9              // c4e13173da07 or c5b173da07
+	//TODO: VPSRLDQ $7, X11, X9             // c4c13173db07
+	//TODO: VPSRLDQ $7, Y2, Y15             // c4e10573da07 or c58573da07
+	//TODO: VPSRLDQ $7, Y11, Y15            // c4c10573db07
+	//TODO: VPSRLQ (BX), X9, X2             // c4e131d313 or c5b1d313
+	//TODO: VPSRLQ (R11), X9, X2            // c4c131d313
+	//TODO: VPSRLQ X2, X9, X2               // c4e131d3d2 or c5b1d3d2
+	//TODO: VPSRLQ X11, X9, X2              // c4c131d3d3
+	//TODO: VPSRLQ (BX), X9, X11            // c46131d31b or c531d31b
+	//TODO: VPSRLQ (R11), X9, X11           // c44131d31b
+	//TODO: VPSRLQ X2, X9, X11              // c46131d3da or c531d3da
+	//TODO: VPSRLQ X11, X9, X11             // c44131d3db
+	//TODO: VPSRLQ $7, X2, X9               // c4e13173d207 or c5b173d207
+	//TODO: VPSRLQ $7, X11, X9              // c4c13173d307
+	//TODO: VPSRLVD (BX), X9, X2            // c4e2314513
+	//TODO: VPSRLVD (R11), X9, X2           // c4c2314513
+	//TODO: VPSRLVD X2, X9, X2              // c4e23145d2
+	//TODO: VPSRLVD X11, X9, X2             // c4c23145d3
+	//TODO: VPSRLVD (BX), X9, X11           // c46231451b
+	//TODO: VPSRLVD (R11), X9, X11          // c44231451b
+	//TODO: VPSRLVD X2, X9, X11             // c4623145da
+	//TODO: VPSRLVD X11, X9, X11            // c4423145db
+	//TODO: VPSRLVD (BX), Y15, Y2           // c4e2054513
+	//TODO: VPSRLVD (R11), Y15, Y2          // c4c2054513
+	//TODO: VPSRLVD Y2, Y15, Y2             // c4e20545d2
+	//TODO: VPSRLVD Y11, Y15, Y2            // c4c20545d3
+	//TODO: VPSRLVD (BX), Y15, Y11          // c46205451b
+	//TODO: VPSRLVD (R11), Y15, Y11         // c44205451b
+	//TODO: VPSRLVD Y2, Y15, Y11            // c4620545da
+	//TODO: VPSRLVD Y11, Y15, Y11           // c4420545db
+	//TODO: VPSRLVQ (BX), X9, X2            // c4e2b14513
+	//TODO: VPSRLVQ (R11), X9, X2           // c4c2b14513
+	//TODO: VPSRLVQ X2, X9, X2              // c4e2b145d2
+	//TODO: VPSRLVQ X11, X9, X2             // c4c2b145d3
+	//TODO: VPSRLVQ (BX), X9, X11           // c462b1451b
+	//TODO: VPSRLVQ (R11), X9, X11          // c442b1451b
+	//TODO: VPSRLVQ X2, X9, X11             // c462b145da
+	//TODO: VPSRLVQ X11, X9, X11            // c442b145db
+	//TODO: VPSRLVQ (BX), Y15, Y2           // c4e2854513
+	//TODO: VPSRLVQ (R11), Y15, Y2          // c4c2854513
+	//TODO: VPSRLVQ Y2, Y15, Y2             // c4e28545d2
+	//TODO: VPSRLVQ Y11, Y15, Y2            // c4c28545d3
+	//TODO: VPSRLVQ (BX), Y15, Y11          // c46285451b
+	//TODO: VPSRLVQ (R11), Y15, Y11         // c44285451b
+	//TODO: VPSRLVQ Y2, Y15, Y11            // c4628545da
+	//TODO: VPSRLVQ Y11, Y15, Y11           // c4428545db
+	//TODO: VPSRLW (BX), X9, X2             // c4e131d113 or c5b1d113
+	//TODO: VPSRLW (R11), X9, X2            // c4c131d113
+	//TODO: VPSRLW X2, X9, X2               // c4e131d1d2 or c5b1d1d2
+	//TODO: VPSRLW X11, X9, X2              // c4c131d1d3
+	//TODO: VPSRLW (BX), X9, X11            // c46131d11b or c531d11b
+	//TODO: VPSRLW (R11), X9, X11           // c44131d11b
+	//TODO: VPSRLW X2, X9, X11              // c46131d1da or c531d1da
+	//TODO: VPSRLW X11, X9, X11             // c44131d1db
+	//TODO: VPSRLW $7, X2, X9               // c4e13171d207 or c5b171d207
+	//TODO: VPSRLW $7, X11, X9              // c4c13171d307
+	//TODO: VPSRLW (BX), Y15, Y2            // c4e105d113 or c585d113
+	//TODO: VPSRLW (R11), Y15, Y2           // c4c105d113
+	//TODO: VPSRLW X2, Y15, Y2              // c4e105d1d2 or c585d1d2
+	//TODO: VPSRLW X11, Y15, Y2             // c4c105d1d3
+	//TODO: VPSRLW (BX), Y15, Y11           // c46105d11b or c505d11b
+	//TODO: VPSRLW (R11), Y15, Y11          // c44105d11b
+	//TODO: VPSRLW X2, Y15, Y11             // c46105d1da or c505d1da
+	//TODO: VPSRLW X11, Y15, Y11            // c44105d1db
+	//TODO: VPSRLW $7, Y2, Y15              // c4e10571d207 or c58571d207
+	//TODO: VPSRLW $7, Y11, Y15             // c4c10571d307
+	//TODO: VPSUBB (BX), X9, X2             // c4e131f813 or c5b1f813
+	//TODO: VPSUBB (R11), X9, X2            // c4c131f813
+	//TODO: VPSUBB X2, X9, X2               // c4e131f8d2 or c5b1f8d2
+	//TODO: VPSUBB X11, X9, X2              // c4c131f8d3
+	//TODO: VPSUBB (BX), X9, X11            // c46131f81b or c531f81b
+	//TODO: VPSUBB (R11), X9, X11           // c44131f81b
+	//TODO: VPSUBB X2, X9, X11              // c46131f8da or c531f8da
+	//TODO: VPSUBB X11, X9, X11             // c44131f8db
+	//TODO: VPSUBB (BX), Y15, Y2            // c4e105f813 or c585f813
+	//TODO: VPSUBB (R11), Y15, Y2           // c4c105f813
+	//TODO: VPSUBB Y2, Y15, Y2              // c4e105f8d2 or c585f8d2
+	//TODO: VPSUBB Y11, Y15, Y2             // c4c105f8d3
+	//TODO: VPSUBB (BX), Y15, Y11           // c46105f81b or c505f81b
+	//TODO: VPSUBB (R11), Y15, Y11          // c44105f81b
+	//TODO: VPSUBB Y2, Y15, Y11             // c46105f8da or c505f8da
+	//TODO: VPSUBB Y11, Y15, Y11            // c44105f8db
+	//TODO: VPSUBD (BX), X9, X2             // c4e131fa13 or c5b1fa13
+	//TODO: VPSUBD (R11), X9, X2            // c4c131fa13
+	//TODO: VPSUBD X2, X9, X2               // c4e131fad2 or c5b1fad2
+	//TODO: VPSUBD X11, X9, X2              // c4c131fad3
+	//TODO: VPSUBD (BX), X9, X11            // c46131fa1b or c531fa1b
+	//TODO: VPSUBD (R11), X9, X11           // c44131fa1b
+	//TODO: VPSUBD X2, X9, X11              // c46131fada or c531fada
+	//TODO: VPSUBD X11, X9, X11             // c44131fadb
+	//TODO: VPSUBD (BX), Y15, Y2            // c4e105fa13 or c585fa13
+	//TODO: VPSUBD (R11), Y15, Y2           // c4c105fa13
+	//TODO: VPSUBD Y2, Y15, Y2              // c4e105fad2 or c585fad2
+	//TODO: VPSUBD Y11, Y15, Y2             // c4c105fad3
+	//TODO: VPSUBD (BX), Y15, Y11           // c46105fa1b or c505fa1b
+	//TODO: VPSUBD (R11), Y15, Y11          // c44105fa1b
+	//TODO: VPSUBD Y2, Y15, Y11             // c46105fada or c505fada
+	//TODO: VPSUBD Y11, Y15, Y11            // c44105fadb
+	//TODO: VPSUBQ (BX), X9, X2             // c4e131fb13 or c5b1fb13
+	//TODO: VPSUBQ (R11), X9, X2            // c4c131fb13
+	//TODO: VPSUBQ X2, X9, X2               // c4e131fbd2 or c5b1fbd2
+	//TODO: VPSUBQ X11, X9, X2              // c4c131fbd3
+	//TODO: VPSUBQ (BX), X9, X11            // c46131fb1b or c531fb1b
+	//TODO: VPSUBQ (R11), X9, X11           // c44131fb1b
+	//TODO: VPSUBQ X2, X9, X11              // c46131fbda or c531fbda
+	//TODO: VPSUBQ X11, X9, X11             // c44131fbdb
+	//TODO: VPSUBQ (BX), Y15, Y2            // c4e105fb13 or c585fb13
+	//TODO: VPSUBQ (R11), Y15, Y2           // c4c105fb13
+	//TODO: VPSUBQ Y2, Y15, Y2              // c4e105fbd2 or c585fbd2
+	//TODO: VPSUBQ Y11, Y15, Y2             // c4c105fbd3
+	//TODO: VPSUBQ (BX), Y15, Y11           // c46105fb1b or c505fb1b
+	//TODO: VPSUBQ (R11), Y15, Y11          // c44105fb1b
+	//TODO: VPSUBQ Y2, Y15, Y11             // c46105fbda or c505fbda
+	//TODO: VPSUBQ Y11, Y15, Y11            // c44105fbdb
+	//TODO: VPSUBSB (BX), X9, X2            // c4e131e813 or c5b1e813
+	//TODO: VPSUBSB (R11), X9, X2           // c4c131e813
+	//TODO: VPSUBSB X2, X9, X2              // c4e131e8d2 or c5b1e8d2
+	//TODO: VPSUBSB X11, X9, X2             // c4c131e8d3
+	//TODO: VPSUBSB (BX), X9, X11           // c46131e81b or c531e81b
+	//TODO: VPSUBSB (R11), X9, X11          // c44131e81b
+	//TODO: VPSUBSB X2, X9, X11             // c46131e8da or c531e8da
+	//TODO: VPSUBSB X11, X9, X11            // c44131e8db
+	//TODO: VPSUBSB (BX), Y15, Y2           // c4e105e813 or c585e813
+	//TODO: VPSUBSB (R11), Y15, Y2          // c4c105e813
+	//TODO: VPSUBSB Y2, Y15, Y2             // c4e105e8d2 or c585e8d2
+	//TODO: VPSUBSB Y11, Y15, Y2            // c4c105e8d3
+	//TODO: VPSUBSB (BX), Y15, Y11          // c46105e81b or c505e81b
+	//TODO: VPSUBSB (R11), Y15, Y11         // c44105e81b
+	//TODO: VPSUBSB Y2, Y15, Y11            // c46105e8da or c505e8da
+	//TODO: VPSUBSB Y11, Y15, Y11           // c44105e8db
+	//TODO: VPSUBSW (BX), X9, X2            // c4e131e913 or c5b1e913
+	//TODO: VPSUBSW (R11), X9, X2           // c4c131e913
+	//TODO: VPSUBSW X2, X9, X2              // c4e131e9d2 or c5b1e9d2
+	//TODO: VPSUBSW X11, X9, X2             // c4c131e9d3
+	//TODO: VPSUBSW (BX), X9, X11           // c46131e91b or c531e91b
+	//TODO: VPSUBSW (R11), X9, X11          // c44131e91b
+	//TODO: VPSUBSW X2, X9, X11             // c46131e9da or c531e9da
+	//TODO: VPSUBSW X11, X9, X11            // c44131e9db
+	//TODO: VPSUBSW (BX), Y15, Y2           // c4e105e913 or c585e913
+	//TODO: VPSUBSW (R11), Y15, Y2          // c4c105e913
+	//TODO: VPSUBSW Y2, Y15, Y2             // c4e105e9d2 or c585e9d2
+	//TODO: VPSUBSW Y11, Y15, Y2            // c4c105e9d3
+	//TODO: VPSUBSW (BX), Y15, Y11          // c46105e91b or c505e91b
+	//TODO: VPSUBSW (R11), Y15, Y11         // c44105e91b
+	//TODO: VPSUBSW Y2, Y15, Y11            // c46105e9da or c505e9da
+	//TODO: VPSUBSW Y11, Y15, Y11           // c44105e9db
+	//TODO: VPSUBUSB (BX), X9, X2           // c4e131d813 or c5b1d813
+	//TODO: VPSUBUSB (R11), X9, X2          // c4c131d813
+	//TODO: VPSUBUSB X2, X9, X2             // c4e131d8d2 or c5b1d8d2
+	//TODO: VPSUBUSB X11, X9, X2            // c4c131d8d3
+	//TODO: VPSUBUSB (BX), X9, X11          // c46131d81b or c531d81b
+	//TODO: VPSUBUSB (R11), X9, X11         // c44131d81b
+	//TODO: VPSUBUSB X2, X9, X11            // c46131d8da or c531d8da
+	//TODO: VPSUBUSB X11, X9, X11           // c44131d8db
+	//TODO: VPSUBUSB (BX), Y15, Y2          // c4e105d813 or c585d813
+	//TODO: VPSUBUSB (R11), Y15, Y2         // c4c105d813
+	//TODO: VPSUBUSB Y2, Y15, Y2            // c4e105d8d2 or c585d8d2
+	//TODO: VPSUBUSB Y11, Y15, Y2           // c4c105d8d3
+	//TODO: VPSUBUSB (BX), Y15, Y11         // c46105d81b or c505d81b
+	//TODO: VPSUBUSB (R11), Y15, Y11        // c44105d81b
+	//TODO: VPSUBUSB Y2, Y15, Y11           // c46105d8da or c505d8da
+	//TODO: VPSUBUSB Y11, Y15, Y11          // c44105d8db
+	//TODO: VPSUBUSW (BX), X9, X2           // c4e131d913 or c5b1d913
+	//TODO: VPSUBUSW (R11), X9, X2          // c4c131d913
+	//TODO: VPSUBUSW X2, X9, X2             // c4e131d9d2 or c5b1d9d2
+	//TODO: VPSUBUSW X11, X9, X2            // c4c131d9d3
+	//TODO: VPSUBUSW (BX), X9, X11          // c46131d91b or c531d91b
+	//TODO: VPSUBUSW (R11), X9, X11         // c44131d91b
+	//TODO: VPSUBUSW X2, X9, X11            // c46131d9da or c531d9da
+	//TODO: VPSUBUSW X11, X9, X11           // c44131d9db
+	//TODO: VPSUBUSW (BX), Y15, Y2          // c4e105d913 or c585d913
+	//TODO: VPSUBUSW (R11), Y15, Y2         // c4c105d913
+	//TODO: VPSUBUSW Y2, Y15, Y2            // c4e105d9d2 or c585d9d2
+	//TODO: VPSUBUSW Y11, Y15, Y2           // c4c105d9d3
+	//TODO: VPSUBUSW (BX), Y15, Y11         // c46105d91b or c505d91b
+	//TODO: VPSUBUSW (R11), Y15, Y11        // c44105d91b
+	//TODO: VPSUBUSW Y2, Y15, Y11           // c46105d9da or c505d9da
+	//TODO: VPSUBUSW Y11, Y15, Y11          // c44105d9db
+	//TODO: VPSUBW (BX), X9, X2             // c4e131f913 or c5b1f913
+	//TODO: VPSUBW (R11), X9, X2            // c4c131f913
+	//TODO: VPSUBW X2, X9, X2               // c4e131f9d2 or c5b1f9d2
+	//TODO: VPSUBW X11, X9, X2              // c4c131f9d3
+	//TODO: VPSUBW (BX), X9, X11            // c46131f91b or c531f91b
+	//TODO: VPSUBW (R11), X9, X11           // c44131f91b
+	//TODO: VPSUBW X2, X9, X11              // c46131f9da or c531f9da
+	//TODO: VPSUBW X11, X9, X11             // c44131f9db
+	//TODO: VPSUBW (BX), Y15, Y2            // c4e105f913 or c585f913
+	//TODO: VPSUBW (R11), Y15, Y2           // c4c105f913
+	//TODO: VPSUBW Y2, Y15, Y2              // c4e105f9d2 or c585f9d2
+	//TODO: VPSUBW Y11, Y15, Y2             // c4c105f9d3
+	//TODO: VPSUBW (BX), Y15, Y11           // c46105f91b or c505f91b
+	//TODO: VPSUBW (R11), Y15, Y11          // c44105f91b
+	//TODO: VPSUBW Y2, Y15, Y11             // c46105f9da or c505f9da
+	//TODO: VPSUBW Y11, Y15, Y11            // c44105f9db
+	VPTEST (BX), X2                         // c4e2791713
+	VPTEST (R11), X2                        // c4c2791713
+	VPTEST X2, X2                           // c4e27917d2
+	VPTEST X11, X2                          // c4c27917d3
+	VPTEST (BX), X11                        // c46279171b
+	VPTEST (R11), X11                       // c44279171b
+	VPTEST X2, X11                          // c4627917da
+	VPTEST X11, X11                         // c4427917db
+	VPTEST (BX), Y2                         // c4e27d1713
+	VPTEST (R11), Y2                        // c4c27d1713
+	VPTEST Y2, Y2                           // c4e27d17d2
+	VPTEST Y11, Y2                          // c4c27d17d3
+	VPTEST (BX), Y11                        // c4627d171b
+	VPTEST (R11), Y11                       // c4427d171b
+	VPTEST Y2, Y11                          // c4627d17da
+	VPTEST Y11, Y11                         // c4427d17db
+	//TODO: VPUNPCKHBW (BX), X9, X2         // c4e1316813 or c5b16813
+	//TODO: VPUNPCKHBW (R11), X9, X2        // c4c1316813
+	//TODO: VPUNPCKHBW X2, X9, X2           // c4e13168d2 or c5b168d2
+	//TODO: VPUNPCKHBW X11, X9, X2          // c4c13168d3
+	//TODO: VPUNPCKHBW (BX), X9, X11        // c46131681b or c531681b
+	//TODO: VPUNPCKHBW (R11), X9, X11       // c44131681b
+	//TODO: VPUNPCKHBW X2, X9, X11          // c4613168da or c53168da
+	//TODO: VPUNPCKHBW X11, X9, X11         // c4413168db
+	//TODO: VPUNPCKHBW (BX), Y15, Y2        // c4e1056813 or c5856813
+	//TODO: VPUNPCKHBW (R11), Y15, Y2       // c4c1056813
+	//TODO: VPUNPCKHBW Y2, Y15, Y2          // c4e10568d2 or c58568d2
+	//TODO: VPUNPCKHBW Y11, Y15, Y2         // c4c10568d3
+	//TODO: VPUNPCKHBW (BX), Y15, Y11       // c46105681b or c505681b
+	//TODO: VPUNPCKHBW (R11), Y15, Y11      // c44105681b
+	//TODO: VPUNPCKHBW Y2, Y15, Y11         // c4610568da or c50568da
+	//TODO: VPUNPCKHBW Y11, Y15, Y11        // c4410568db
+	//TODO: VPUNPCKHDQ (BX), X9, X2         // c4e1316a13 or c5b16a13
+	//TODO: VPUNPCKHDQ (R11), X9, X2        // c4c1316a13
+	//TODO: VPUNPCKHDQ X2, X9, X2           // c4e1316ad2 or c5b16ad2
+	//TODO: VPUNPCKHDQ X11, X9, X2          // c4c1316ad3
+	//TODO: VPUNPCKHDQ (BX), X9, X11        // c461316a1b or c5316a1b
+	//TODO: VPUNPCKHDQ (R11), X9, X11       // c441316a1b
+	//TODO: VPUNPCKHDQ X2, X9, X11          // c461316ada or c5316ada
+	//TODO: VPUNPCKHDQ X11, X9, X11         // c441316adb
+	//TODO: VPUNPCKHDQ (BX), Y15, Y2        // c4e1056a13 or c5856a13
+	//TODO: VPUNPCKHDQ (R11), Y15, Y2       // c4c1056a13
+	//TODO: VPUNPCKHDQ Y2, Y15, Y2          // c4e1056ad2 or c5856ad2
+	//TODO: VPUNPCKHDQ Y11, Y15, Y2         // c4c1056ad3
+	//TODO: VPUNPCKHDQ (BX), Y15, Y11       // c461056a1b or c5056a1b
+	//TODO: VPUNPCKHDQ (R11), Y15, Y11      // c441056a1b
+	//TODO: VPUNPCKHDQ Y2, Y15, Y11         // c461056ada or c5056ada
+	//TODO: VPUNPCKHDQ Y11, Y15, Y11        // c441056adb
+	//TODO: VPUNPCKHQDQ (BX), X9, X2        // c4e1316d13 or c5b16d13
+	//TODO: VPUNPCKHQDQ (R11), X9, X2       // c4c1316d13
+	//TODO: VPUNPCKHQDQ X2, X9, X2          // c4e1316dd2 or c5b16dd2
+	//TODO: VPUNPCKHQDQ X11, X9, X2         // c4c1316dd3
+	//TODO: VPUNPCKHQDQ (BX), X9, X11       // c461316d1b or c5316d1b
+	//TODO: VPUNPCKHQDQ (R11), X9, X11      // c441316d1b
+	//TODO: VPUNPCKHQDQ X2, X9, X11         // c461316dda or c5316dda
+	//TODO: VPUNPCKHQDQ X11, X9, X11        // c441316ddb
+	//TODO: VPUNPCKHQDQ (BX), Y15, Y2       // c4e1056d13 or c5856d13
+	//TODO: VPUNPCKHQDQ (R11), Y15, Y2      // c4c1056d13
+	//TODO: VPUNPCKHQDQ Y2, Y15, Y2         // c4e1056dd2 or c5856dd2
+	//TODO: VPUNPCKHQDQ Y11, Y15, Y2        // c4c1056dd3
+	//TODO: VPUNPCKHQDQ (BX), Y15, Y11      // c461056d1b or c5056d1b
+	//TODO: VPUNPCKHQDQ (R11), Y15, Y11     // c441056d1b
+	//TODO: VPUNPCKHQDQ Y2, Y15, Y11        // c461056dda or c5056dda
+	//TODO: VPUNPCKHQDQ Y11, Y15, Y11       // c441056ddb
+	//TODO: VPUNPCKHWD (BX), X9, X2         // c4e1316913 or c5b16913
+	//TODO: VPUNPCKHWD (R11), X9, X2        // c4c1316913
+	//TODO: VPUNPCKHWD X2, X9, X2           // c4e13169d2 or c5b169d2
+	//TODO: VPUNPCKHWD X11, X9, X2          // c4c13169d3
+	//TODO: VPUNPCKHWD (BX), X9, X11        // c46131691b or c531691b
+	//TODO: VPUNPCKHWD (R11), X9, X11       // c44131691b
+	//TODO: VPUNPCKHWD X2, X9, X11          // c4613169da or c53169da
+	//TODO: VPUNPCKHWD X11, X9, X11         // c4413169db
+	//TODO: VPUNPCKHWD (BX), Y15, Y2        // c4e1056913 or c5856913
+	//TODO: VPUNPCKHWD (R11), Y15, Y2       // c4c1056913
+	//TODO: VPUNPCKHWD Y2, Y15, Y2          // c4e10569d2 or c58569d2
+	//TODO: VPUNPCKHWD Y11, Y15, Y2         // c4c10569d3
+	//TODO: VPUNPCKHWD (BX), Y15, Y11       // c46105691b or c505691b
+	//TODO: VPUNPCKHWD (R11), Y15, Y11      // c44105691b
+	//TODO: VPUNPCKHWD Y2, Y15, Y11         // c4610569da or c50569da
+	//TODO: VPUNPCKHWD Y11, Y15, Y11        // c4410569db
+	//TODO: VPUNPCKLBW (BX), X9, X2         // c4e1316013 or c5b16013
+	//TODO: VPUNPCKLBW (R11), X9, X2        // c4c1316013
+	//TODO: VPUNPCKLBW X2, X9, X2           // c4e13160d2 or c5b160d2
+	//TODO: VPUNPCKLBW X11, X9, X2          // c4c13160d3
+	//TODO: VPUNPCKLBW (BX), X9, X11        // c46131601b or c531601b
+	//TODO: VPUNPCKLBW (R11), X9, X11       // c44131601b
+	//TODO: VPUNPCKLBW X2, X9, X11          // c4613160da or c53160da
+	//TODO: VPUNPCKLBW X11, X9, X11         // c4413160db
+	//TODO: VPUNPCKLBW (BX), Y15, Y2        // c4e1056013 or c5856013
+	//TODO: VPUNPCKLBW (R11), Y15, Y2       // c4c1056013
+	//TODO: VPUNPCKLBW Y2, Y15, Y2          // c4e10560d2 or c58560d2
+	//TODO: VPUNPCKLBW Y11, Y15, Y2         // c4c10560d3
+	//TODO: VPUNPCKLBW (BX), Y15, Y11       // c46105601b or c505601b
+	//TODO: VPUNPCKLBW (R11), Y15, Y11      // c44105601b
+	//TODO: VPUNPCKLBW Y2, Y15, Y11         // c4610560da or c50560da
+	//TODO: VPUNPCKLBW Y11, Y15, Y11        // c4410560db
+	//TODO: VPUNPCKLDQ (BX), X9, X2         // c4e1316213 or c5b16213
+	//TODO: VPUNPCKLDQ (R11), X9, X2        // c4c1316213
+	//TODO: VPUNPCKLDQ X2, X9, X2           // c4e13162d2 or c5b162d2
+	//TODO: VPUNPCKLDQ X11, X9, X2          // c4c13162d3
+	//TODO: VPUNPCKLDQ (BX), X9, X11        // c46131621b or c531621b
+	//TODO: VPUNPCKLDQ (R11), X9, X11       // c44131621b
+	//TODO: VPUNPCKLDQ X2, X9, X11          // c4613162da or c53162da
+	//TODO: VPUNPCKLDQ X11, X9, X11         // c4413162db
+	//TODO: VPUNPCKLDQ (BX), Y15, Y2        // c4e1056213 or c5856213
+	//TODO: VPUNPCKLDQ (R11), Y15, Y2       // c4c1056213
+	//TODO: VPUNPCKLDQ Y2, Y15, Y2          // c4e10562d2 or c58562d2
+	//TODO: VPUNPCKLDQ Y11, Y15, Y2         // c4c10562d3
+	//TODO: VPUNPCKLDQ (BX), Y15, Y11       // c46105621b or c505621b
+	//TODO: VPUNPCKLDQ (R11), Y15, Y11      // c44105621b
+	//TODO: VPUNPCKLDQ Y2, Y15, Y11         // c4610562da or c50562da
+	//TODO: VPUNPCKLDQ Y11, Y15, Y11        // c4410562db
+	//TODO: VPUNPCKLQDQ (BX), X9, X2        // c4e1316c13 or c5b16c13
+	//TODO: VPUNPCKLQDQ (R11), X9, X2       // c4c1316c13
+	//TODO: VPUNPCKLQDQ X2, X9, X2          // c4e1316cd2 or c5b16cd2
+	//TODO: VPUNPCKLQDQ X11, X9, X2         // c4c1316cd3
+	//TODO: VPUNPCKLQDQ (BX), X9, X11       // c461316c1b or c5316c1b
+	//TODO: VPUNPCKLQDQ (R11), X9, X11      // c441316c1b
+	//TODO: VPUNPCKLQDQ X2, X9, X11         // c461316cda or c5316cda
+	//TODO: VPUNPCKLQDQ X11, X9, X11        // c441316cdb
+	//TODO: VPUNPCKLQDQ (BX), Y15, Y2       // c4e1056c13 or c5856c13
+	//TODO: VPUNPCKLQDQ (R11), Y15, Y2      // c4c1056c13
+	//TODO: VPUNPCKLQDQ Y2, Y15, Y2         // c4e1056cd2 or c5856cd2
+	//TODO: VPUNPCKLQDQ Y11, Y15, Y2        // c4c1056cd3
+	//TODO: VPUNPCKLQDQ (BX), Y15, Y11      // c461056c1b or c5056c1b
+	//TODO: VPUNPCKLQDQ (R11), Y15, Y11     // c441056c1b
+	//TODO: VPUNPCKLQDQ Y2, Y15, Y11        // c461056cda or c5056cda
+	//TODO: VPUNPCKLQDQ Y11, Y15, Y11       // c441056cdb
+	//TODO: VPUNPCKLWD (BX), X9, X2         // c4e1316113 or c5b16113
+	//TODO: VPUNPCKLWD (R11), X9, X2        // c4c1316113
+	//TODO: VPUNPCKLWD X2, X9, X2           // c4e13161d2 or c5b161d2
+	//TODO: VPUNPCKLWD X11, X9, X2          // c4c13161d3
+	//TODO: VPUNPCKLWD (BX), X9, X11        // c46131611b or c531611b
+	//TODO: VPUNPCKLWD (R11), X9, X11       // c44131611b
+	//TODO: VPUNPCKLWD X2, X9, X11          // c4613161da or c53161da
+	//TODO: VPUNPCKLWD X11, X9, X11         // c4413161db
+	//TODO: VPUNPCKLWD (BX), Y15, Y2        // c4e1056113 or c5856113
+	//TODO: VPUNPCKLWD (R11), Y15, Y2       // c4c1056113
+	//TODO: VPUNPCKLWD Y2, Y15, Y2          // c4e10561d2 or c58561d2
+	//TODO: VPUNPCKLWD Y11, Y15, Y2         // c4c10561d3
+	//TODO: VPUNPCKLWD (BX), Y15, Y11       // c46105611b or c505611b
+	//TODO: VPUNPCKLWD (R11), Y15, Y11      // c44105611b
+	//TODO: VPUNPCKLWD Y2, Y15, Y11         // c4610561da or c50561da
+	//TODO: VPUNPCKLWD Y11, Y15, Y11        // c4410561db
+	VPXOR (BX), X9, X2                      // c4e131ef13 or c5b1ef13
+	VPXOR (R11), X9, X2                     // c4c131ef13
+	VPXOR X2, X9, X2                        // c4e131efd2 or c5b1efd2
+	VPXOR X11, X9, X2                       // c4c131efd3
+	VPXOR (BX), X9, X11                     // c46131ef1b or c531ef1b
+	VPXOR (R11), X9, X11                    // c44131ef1b
+	VPXOR X2, X9, X11                       // c46131efda or c531efda
+	VPXOR X11, X9, X11                      // c44131efdb
+	VPXOR (BX), Y15, Y2                     // c4e105ef13 or c585ef13
+	VPXOR (R11), Y15, Y2                    // c4c105ef13
+	VPXOR Y2, Y15, Y2                       // c4e105efd2 or c585efd2
+	VPXOR Y11, Y15, Y2                      // c4c105efd3
+	VPXOR (BX), Y15, Y11                    // c46105ef1b or c505ef1b
+	VPXOR (R11), Y15, Y11                   // c44105ef1b
+	VPXOR Y2, Y15, Y11                      // c46105efda or c505efda
+	VPXOR Y11, Y15, Y11                     // c44105efdb
+	//TODO: VRCPPS (BX), X2                 // c4e1785313 or c5f85313
+	//TODO: VRCPPS (R11), X2                // c4c1785313
+	//TODO: VRCPPS X2, X2                   // c4e17853d2 or c5f853d2
+	//TODO: VRCPPS X11, X2                  // c4c17853d3
+	//TODO: VRCPPS (BX), X11                // c46178531b or c578531b
+	//TODO: VRCPPS (R11), X11               // c44178531b
+	//TODO: VRCPPS X2, X11                  // c4617853da or c57853da
+	//TODO: VRCPPS X11, X11                 // c4417853db
+	//TODO: VRCPPS (BX), Y2                 // c4e17c5313 or c5fc5313
+	//TODO: VRCPPS (R11), Y2                // c4c17c5313
+	//TODO: VRCPPS Y2, Y2                   // c4e17c53d2 or c5fc53d2
+	//TODO: VRCPPS Y11, Y2                  // c4c17c53d3
+	//TODO: VRCPPS (BX), Y11                // c4617c531b or c57c531b
+	//TODO: VRCPPS (R11), Y11               // c4417c531b
+	//TODO: VRCPPS Y2, Y11                  // c4617c53da or c57c53da
+	//TODO: VRCPPS Y11, Y11                 // c4417c53db
+	//TODO: VRCPSS (BX), X9, X2             // c4e1325313 or c5b25313
+	//TODO: VRCPSS (R11), X9, X2            // c4c1325313
+	//TODO: VRCPSS X2, X9, X2               // c4e13253d2 or c5b253d2
+	//TODO: VRCPSS X11, X9, X2              // c4c13253d3
+	//TODO: VRCPSS (BX), X9, X11            // c46132531b or c532531b
+	//TODO: VRCPSS (R11), X9, X11           // c44132531b
+	//TODO: VRCPSS X2, X9, X11              // c4613253da or c53253da
+	//TODO: VRCPSS X11, X9, X11             // c4413253db
+	//TODO: VROUNDPD $7, (BX), X2           // c4e379091307
+	//TODO: VROUNDPD $7, (R11), X2          // c4c379091307
+	//TODO: VROUNDPD $7, X2, X2             // c4e37909d207
+	//TODO: VROUNDPD $7, X11, X2            // c4c37909d307
+	//TODO: VROUNDPD $7, (BX), X11          // c46379091b07
+	//TODO: VROUNDPD $7, (R11), X11         // c44379091b07
+	//TODO: VROUNDPD $7, X2, X11            // c4637909da07
+	//TODO: VROUNDPD $7, X11, X11           // c4437909db07
+	//TODO: VROUNDPD $7, (BX), Y2           // c4e37d091307
+	//TODO: VROUNDPD $7, (R11), Y2          // c4c37d091307
+	//TODO: VROUNDPD $7, Y2, Y2             // c4e37d09d207
+	//TODO: VROUNDPD $7, Y11, Y2            // c4c37d09d307
+	//TODO: VROUNDPD $7, (BX), Y11          // c4637d091b07
+	//TODO: VROUNDPD $7, (R11), Y11         // c4437d091b07
+	//TODO: VROUNDPD $7, Y2, Y11            // c4637d09da07
+	//TODO: VROUNDPD $7, Y11, Y11           // c4437d09db07
+	//TODO: VROUNDPS $7, (BX), X2           // c4e379081307
+	//TODO: VROUNDPS $7, (R11), X2          // c4c379081307
+	//TODO: VROUNDPS $7, X2, X2             // c4e37908d207
+	//TODO: VROUNDPS $7, X11, X2            // c4c37908d307
+	//TODO: VROUNDPS $7, (BX), X11          // c46379081b07
+	//TODO: VROUNDPS $7, (R11), X11         // c44379081b07
+	//TODO: VROUNDPS $7, X2, X11            // c4637908da07
+	//TODO: VROUNDPS $7, X11, X11           // c4437908db07
+	//TODO: VROUNDPS $7, (BX), Y2           // c4e37d081307
+	//TODO: VROUNDPS $7, (R11), Y2          // c4c37d081307
+	//TODO: VROUNDPS $7, Y2, Y2             // c4e37d08d207
+	//TODO: VROUNDPS $7, Y11, Y2            // c4c37d08d307
+	//TODO: VROUNDPS $7, (BX), Y11          // c4637d081b07
+	//TODO: VROUNDPS $7, (R11), Y11         // c4437d081b07
+	//TODO: VROUNDPS $7, Y2, Y11            // c4637d08da07
+	//TODO: VROUNDPS $7, Y11, Y11           // c4437d08db07
+	//TODO: VROUNDSD $7, (BX), X9, X2       // c4e3310b1307
+	//TODO: VROUNDSD $7, (R11), X9, X2      // c4c3310b1307
+	//TODO: VROUNDSD $7, X2, X9, X2         // c4e3310bd207
+	//TODO: VROUNDSD $7, X11, X9, X2        // c4c3310bd307
+	//TODO: VROUNDSD $7, (BX), X9, X11      // c463310b1b07
+	//TODO: VROUNDSD $7, (R11), X9, X11     // c443310b1b07
+	//TODO: VROUNDSD $7, X2, X9, X11        // c463310bda07
+	//TODO: VROUNDSD $7, X11, X9, X11       // c443310bdb07
+	//TODO: VROUNDSS $7, (BX), X9, X2       // c4e3310a1307
+	//TODO: VROUNDSS $7, (R11), X9, X2      // c4c3310a1307
+	//TODO: VROUNDSS $7, X2, X9, X2         // c4e3310ad207
+	//TODO: VROUNDSS $7, X11, X9, X2        // c4c3310ad307
+	//TODO: VROUNDSS $7, (BX), X9, X11      // c463310a1b07
+	//TODO: VROUNDSS $7, (R11), X9, X11     // c443310a1b07
+	//TODO: VROUNDSS $7, X2, X9, X11        // c463310ada07
+	//TODO: VROUNDSS $7, X11, X9, X11       // c443310adb07
+	//TODO: VRSQRTPS (BX), X2               // c4e1785213 or c5f85213
+	//TODO: VRSQRTPS (R11), X2              // c4c1785213
+	//TODO: VRSQRTPS X2, X2                 // c4e17852d2 or c5f852d2
+	//TODO: VRSQRTPS X11, X2                // c4c17852d3
+	//TODO: VRSQRTPS (BX), X11              // c46178521b or c578521b
+	//TODO: VRSQRTPS (R11), X11             // c44178521b
+	//TODO: VRSQRTPS X2, X11                // c4617852da or c57852da
+	//TODO: VRSQRTPS X11, X11               // c4417852db
+	//TODO: VRSQRTPS (BX), Y2               // c4e17c5213 or c5fc5213
+	//TODO: VRSQRTPS (R11), Y2              // c4c17c5213
+	//TODO: VRSQRTPS Y2, Y2                 // c4e17c52d2 or c5fc52d2
+	//TODO: VRSQRTPS Y11, Y2                // c4c17c52d3
+	//TODO: VRSQRTPS (BX), Y11              // c4617c521b or c57c521b
+	//TODO: VRSQRTPS (R11), Y11             // c4417c521b
+	//TODO: VRSQRTPS Y2, Y11                // c4617c52da or c57c52da
+	//TODO: VRSQRTPS Y11, Y11               // c4417c52db
+	//TODO: VRSQRTSS (BX), X9, X2           // c4e1325213 or c5b25213
+	//TODO: VRSQRTSS (R11), X9, X2          // c4c1325213
+	//TODO: VRSQRTSS X2, X9, X2             // c4e13252d2 or c5b252d2
+	//TODO: VRSQRTSS X11, X9, X2            // c4c13252d3
+	//TODO: VRSQRTSS (BX), X9, X11          // c46132521b or c532521b
+	//TODO: VRSQRTSS (R11), X9, X11         // c44132521b
+	//TODO: VRSQRTSS X2, X9, X11            // c4613252da or c53252da
+	//TODO: VRSQRTSS X11, X9, X11           // c4413252db
+	//TODO: VSHUFPD $7, (BX), X9, X2        // c4e131c61307 or c5b1c61307
+	//TODO: VSHUFPD $7, (R11), X9, X2       // c4c131c61307
+	//TODO: VSHUFPD $7, X2, X9, X2          // c4e131c6d207 or c5b1c6d207
+	//TODO: VSHUFPD $7, X11, X9, X2         // c4c131c6d307
+	//TODO: VSHUFPD $7, (BX), X9, X11       // c46131c61b07 or c531c61b07
+	//TODO: VSHUFPD $7, (R11), X9, X11      // c44131c61b07
+	//TODO: VSHUFPD $7, X2, X9, X11         // c46131c6da07 or c531c6da07
+	//TODO: VSHUFPD $7, X11, X9, X11        // c44131c6db07
+	//TODO: VSHUFPD $7, (BX), Y15, Y2       // c4e105c61307 or c585c61307
+	//TODO: VSHUFPD $7, (R11), Y15, Y2      // c4c105c61307
+	//TODO: VSHUFPD $7, Y2, Y15, Y2         // c4e105c6d207 or c585c6d207
+	//TODO: VSHUFPD $7, Y11, Y15, Y2        // c4c105c6d307
+	//TODO: VSHUFPD $7, (BX), Y15, Y11      // c46105c61b07 or c505c61b07
+	//TODO: VSHUFPD $7, (R11), Y15, Y11     // c44105c61b07
+	//TODO: VSHUFPD $7, Y2, Y15, Y11        // c46105c6da07 or c505c6da07
+	//TODO: VSHUFPD $7, Y11, Y15, Y11       // c44105c6db07
+	//TODO: VSHUFPS $7, (BX), X9, X2        // c4e130c61307 or c5b0c61307
+	//TODO: VSHUFPS $7, (R11), X9, X2       // c4c130c61307
+	//TODO: VSHUFPS $7, X2, X9, X2          // c4e130c6d207 or c5b0c6d207
+	//TODO: VSHUFPS $7, X11, X9, X2         // c4c130c6d307
+	//TODO: VSHUFPS $7, (BX), X9, X11       // c46130c61b07 or c530c61b07
+	//TODO: VSHUFPS $7, (R11), X9, X11      // c44130c61b07
+	//TODO: VSHUFPS $7, X2, X9, X11         // c46130c6da07 or c530c6da07
+	//TODO: VSHUFPS $7, X11, X9, X11        // c44130c6db07
+	//TODO: VSHUFPS $7, (BX), Y15, Y2       // c4e104c61307 or c584c61307
+	//TODO: VSHUFPS $7, (R11), Y15, Y2      // c4c104c61307
+	//TODO: VSHUFPS $7, Y2, Y15, Y2         // c4e104c6d207 or c584c6d207
+	//TODO: VSHUFPS $7, Y11, Y15, Y2        // c4c104c6d307
+	//TODO: VSHUFPS $7, (BX), Y15, Y11      // c46104c61b07 or c504c61b07
+	//TODO: VSHUFPS $7, (R11), Y15, Y11     // c44104c61b07
+	//TODO: VSHUFPS $7, Y2, Y15, Y11        // c46104c6da07 or c504c6da07
+	//TODO: VSHUFPS $7, Y11, Y15, Y11       // c44104c6db07
+	//TODO: VSQRTPD (BX), X2                // c4e1795113 or c5f95113
+	//TODO: VSQRTPD (R11), X2               // c4c1795113
+	//TODO: VSQRTPD X2, X2                  // c4e17951d2 or c5f951d2
+	//TODO: VSQRTPD X11, X2                 // c4c17951d3
+	//TODO: VSQRTPD (BX), X11               // c46179511b or c579511b
+	//TODO: VSQRTPD (R11), X11              // c44179511b
+	//TODO: VSQRTPD X2, X11                 // c4617951da or c57951da
+	//TODO: VSQRTPD X11, X11                // c4417951db
+	//TODO: VSQRTPD (BX), Y2                // c4e17d5113 or c5fd5113
+	//TODO: VSQRTPD (R11), Y2               // c4c17d5113
+	//TODO: VSQRTPD Y2, Y2                  // c4e17d51d2 or c5fd51d2
+	//TODO: VSQRTPD Y11, Y2                 // c4c17d51d3
+	//TODO: VSQRTPD (BX), Y11               // c4617d511b or c57d511b
+	//TODO: VSQRTPD (R11), Y11              // c4417d511b
+	//TODO: VSQRTPD Y2, Y11                 // c4617d51da or c57d51da
+	//TODO: VSQRTPD Y11, Y11                // c4417d51db
+	//TODO: VSQRTPS (BX), X2                // c4e1785113 or c5f85113
+	//TODO: VSQRTPS (R11), X2               // c4c1785113
+	//TODO: VSQRTPS X2, X2                  // c4e17851d2 or c5f851d2
+	//TODO: VSQRTPS X11, X2                 // c4c17851d3
+	//TODO: VSQRTPS (BX), X11               // c46178511b or c578511b
+	//TODO: VSQRTPS (R11), X11              // c44178511b
+	//TODO: VSQRTPS X2, X11                 // c4617851da or c57851da
+	//TODO: VSQRTPS X11, X11                // c4417851db
+	//TODO: VSQRTPS (BX), Y2                // c4e17c5113 or c5fc5113
+	//TODO: VSQRTPS (R11), Y2               // c4c17c5113
+	//TODO: VSQRTPS Y2, Y2                  // c4e17c51d2 or c5fc51d2
+	//TODO: VSQRTPS Y11, Y2                 // c4c17c51d3
+	//TODO: VSQRTPS (BX), Y11               // c4617c511b or c57c511b
+	//TODO: VSQRTPS (R11), Y11              // c4417c511b
+	//TODO: VSQRTPS Y2, Y11                 // c4617c51da or c57c51da
+	//TODO: VSQRTPS Y11, Y11                // c4417c51db
+	//TODO: VSQRTSD (BX), X9, X2            // c4e1335113 or c5b35113
+	//TODO: VSQRTSD (R11), X9, X2           // c4c1335113
+	//TODO: VSQRTSD X2, X9, X2              // c4e13351d2 or c5b351d2
+	//TODO: VSQRTSD X11, X9, X2             // c4c13351d3
+	//TODO: VSQRTSD (BX), X9, X11           // c46133511b or c533511b
+	//TODO: VSQRTSD (R11), X9, X11          // c44133511b
+	//TODO: VSQRTSD X2, X9, X11             // c4613351da or c53351da
+	//TODO: VSQRTSD X11, X9, X11            // c4413351db
+	//TODO: VSQRTSS (BX), X9, X2            // c4e1325113 or c5b25113
+	//TODO: VSQRTSS (R11), X9, X2           // c4c1325113
+	//TODO: VSQRTSS X2, X9, X2              // c4e13251d2 or c5b251d2
+	//TODO: VSQRTSS X11, X9, X2             // c4c13251d3
+	//TODO: VSQRTSS (BX), X9, X11           // c46132511b or c532511b
+	//TODO: VSQRTSS (R11), X9, X11          // c44132511b
+	//TODO: VSQRTSS X2, X9, X11             // c4613251da or c53251da
+	//TODO: VSQRTSS X11, X9, X11            // c4413251db
+	//TODO: VSTMXCSR (BX)                   // c4e178ae1b or c5f8ae1b
+	//TODO: VSTMXCSR (R11)                  // c4c178ae1b
+	//TODO: VSUBPD (BX), X9, X2             // c4e1315c13 or c5b15c13
+	//TODO: VSUBPD (R11), X9, X2            // c4c1315c13
+	//TODO: VSUBPD X2, X9, X2               // c4e1315cd2 or c5b15cd2
+	//TODO: VSUBPD X11, X9, X2              // c4c1315cd3
+	//TODO: VSUBPD (BX), X9, X11            // c461315c1b or c5315c1b
+	//TODO: VSUBPD (R11), X9, X11           // c441315c1b
+	//TODO: VSUBPD X2, X9, X11              // c461315cda or c5315cda
+	//TODO: VSUBPD X11, X9, X11             // c441315cdb
+	//TODO: VSUBPD (BX), Y15, Y2            // c4e1055c13 or c5855c13
+	//TODO: VSUBPD (R11), Y15, Y2           // c4c1055c13
+	//TODO: VSUBPD Y2, Y15, Y2              // c4e1055cd2 or c5855cd2
+	//TODO: VSUBPD Y11, Y15, Y2             // c4c1055cd3
+	//TODO: VSUBPD (BX), Y15, Y11           // c461055c1b or c5055c1b
+	//TODO: VSUBPD (R11), Y15, Y11          // c441055c1b
+	//TODO: VSUBPD Y2, Y15, Y11             // c461055cda or c5055cda
+	//TODO: VSUBPD Y11, Y15, Y11            // c441055cdb
+	//TODO: VSUBPS (BX), X9, X2             // c4e1305c13 or c5b05c13
+	//TODO: VSUBPS (R11), X9, X2            // c4c1305c13
+	//TODO: VSUBPS X2, X9, X2               // c4e1305cd2 or c5b05cd2
+	//TODO: VSUBPS X11, X9, X2              // c4c1305cd3
+	//TODO: VSUBPS (BX), X9, X11            // c461305c1b or c5305c1b
+	//TODO: VSUBPS (R11), X9, X11           // c441305c1b
+	//TODO: VSUBPS X2, X9, X11              // c461305cda or c5305cda
+	//TODO: VSUBPS X11, X9, X11             // c441305cdb
+	//TODO: VSUBPS (BX), Y15, Y2            // c4e1045c13 or c5845c13
+	//TODO: VSUBPS (R11), Y15, Y2           // c4c1045c13
+	//TODO: VSUBPS Y2, Y15, Y2              // c4e1045cd2 or c5845cd2
+	//TODO: VSUBPS Y11, Y15, Y2             // c4c1045cd3
+	//TODO: VSUBPS (BX), Y15, Y11           // c461045c1b or c5045c1b
+	//TODO: VSUBPS (R11), Y15, Y11          // c441045c1b
+	//TODO: VSUBPS Y2, Y15, Y11             // c461045cda or c5045cda
+	//TODO: VSUBPS Y11, Y15, Y11            // c441045cdb
+	//TODO: VSUBSD (BX), X9, X2             // c4e1335c13 or c5b35c13
+	//TODO: VSUBSD (R11), X9, X2            // c4c1335c13
+	//TODO: VSUBSD X2, X9, X2               // c4e1335cd2 or c5b35cd2
+	//TODO: VSUBSD X11, X9, X2              // c4c1335cd3
+	//TODO: VSUBSD (BX), X9, X11            // c461335c1b or c5335c1b
+	//TODO: VSUBSD (R11), X9, X11           // c441335c1b
+	//TODO: VSUBSD X2, X9, X11              // c461335cda or c5335cda
+	//TODO: VSUBSD X11, X9, X11             // c441335cdb
+	//TODO: VSUBSS (BX), X9, X2             // c4e1325c13 or c5b25c13
+	//TODO: VSUBSS (R11), X9, X2            // c4c1325c13
+	//TODO: VSUBSS X2, X9, X2               // c4e1325cd2 or c5b25cd2
+	//TODO: VSUBSS X11, X9, X2              // c4c1325cd3
+	//TODO: VSUBSS (BX), X9, X11            // c461325c1b or c5325c1b
+	//TODO: VSUBSS (R11), X9, X11           // c441325c1b
+	//TODO: VSUBSS X2, X9, X11              // c461325cda or c5325cda
+	//TODO: VSUBSS X11, X9, X11             // c441325cdb
+	//TODO: VTESTPD (BX), X2                // c4e2790f13
+	//TODO: VTESTPD (R11), X2               // c4c2790f13
+	//TODO: VTESTPD X2, X2                  // c4e2790fd2
+	//TODO: VTESTPD X11, X2                 // c4c2790fd3
+	//TODO: VTESTPD (BX), X11               // c462790f1b
+	//TODO: VTESTPD (R11), X11              // c442790f1b
+	//TODO: VTESTPD X2, X11                 // c462790fda
+	//TODO: VTESTPD X11, X11                // c442790fdb
+	//TODO: VTESTPD (BX), Y2                // c4e27d0f13
+	//TODO: VTESTPD (R11), Y2               // c4c27d0f13
+	//TODO: VTESTPD Y2, Y2                  // c4e27d0fd2
+	//TODO: VTESTPD Y11, Y2                 // c4c27d0fd3
+	//TODO: VTESTPD (BX), Y11               // c4627d0f1b
+	//TODO: VTESTPD (R11), Y11              // c4427d0f1b
+	//TODO: VTESTPD Y2, Y11                 // c4627d0fda
+	//TODO: VTESTPD Y11, Y11                // c4427d0fdb
+	//TODO: VTESTPS (BX), X2                // c4e2790e13
+	//TODO: VTESTPS (R11), X2               // c4c2790e13
+	//TODO: VTESTPS X2, X2                  // c4e2790ed2
+	//TODO: VTESTPS X11, X2                 // c4c2790ed3
+	//TODO: VTESTPS (BX), X11               // c462790e1b
+	//TODO: VTESTPS (R11), X11              // c442790e1b
+	//TODO: VTESTPS X2, X11                 // c462790eda
+	//TODO: VTESTPS X11, X11                // c442790edb
+	//TODO: VTESTPS (BX), Y2                // c4e27d0e13
+	//TODO: VTESTPS (R11), Y2               // c4c27d0e13
+	//TODO: VTESTPS Y2, Y2                  // c4e27d0ed2
+	//TODO: VTESTPS Y11, Y2                 // c4c27d0ed3
+	//TODO: VTESTPS (BX), Y11               // c4627d0e1b
+	//TODO: VTESTPS (R11), Y11              // c4427d0e1b
+	//TODO: VTESTPS Y2, Y11                 // c4627d0eda
+	//TODO: VTESTPS Y11, Y11                // c4427d0edb
+	//TODO: VUCOMISD (BX), X2               // c4e1792e13 or c5f92e13
+	//TODO: VUCOMISD (R11), X2              // c4c1792e13
+	//TODO: VUCOMISD X2, X2                 // c4e1792ed2 or c5f92ed2
+	//TODO: VUCOMISD X11, X2                // c4c1792ed3
+	//TODO: VUCOMISD (BX), X11              // c461792e1b or c5792e1b
+	//TODO: VUCOMISD (R11), X11             // c441792e1b
+	//TODO: VUCOMISD X2, X11                // c461792eda or c5792eda
+	//TODO: VUCOMISD X11, X11               // c441792edb
+	//TODO: VUCOMISS (BX), X2               // c4e1782e13 or c5f82e13
+	//TODO: VUCOMISS (R11), X2              // c4c1782e13
+	//TODO: VUCOMISS X2, X2                 // c4e1782ed2 or c5f82ed2
+	//TODO: VUCOMISS X11, X2                // c4c1782ed3
+	//TODO: VUCOMISS (BX), X11              // c461782e1b or c5782e1b
+	//TODO: VUCOMISS (R11), X11             // c441782e1b
+	//TODO: VUCOMISS X2, X11                // c461782eda or c5782eda
+	//TODO: VUCOMISS X11, X11               // c441782edb
+	//TODO: VUNPCKHPD (BX), X9, X2          // c4e1311513 or c5b11513
+	//TODO: VUNPCKHPD (R11), X9, X2         // c4c1311513
+	//TODO: VUNPCKHPD X2, X9, X2            // c4e13115d2 or c5b115d2
+	//TODO: VUNPCKHPD X11, X9, X2           // c4c13115d3
+	//TODO: VUNPCKHPD (BX), X9, X11         // c46131151b or c531151b
+	//TODO: VUNPCKHPD (R11), X9, X11        // c44131151b
+	//TODO: VUNPCKHPD X2, X9, X11           // c4613115da or c53115da
+	//TODO: VUNPCKHPD X11, X9, X11          // c4413115db
+	//TODO: VUNPCKHPD (BX), Y15, Y2         // c4e1051513 or c5851513
+	//TODO: VUNPCKHPD (R11), Y15, Y2        // c4c1051513
+	//TODO: VUNPCKHPD Y2, Y15, Y2           // c4e10515d2 or c58515d2
+	//TODO: VUNPCKHPD Y11, Y15, Y2          // c4c10515d3
+	//TODO: VUNPCKHPD (BX), Y15, Y11        // c46105151b or c505151b
+	//TODO: VUNPCKHPD (R11), Y15, Y11       // c44105151b
+	//TODO: VUNPCKHPD Y2, Y15, Y11          // c4610515da or c50515da
+	//TODO: VUNPCKHPD Y11, Y15, Y11         // c4410515db
+	//TODO: VUNPCKHPS (BX), X9, X2          // c4e1301513 or c5b01513
+	//TODO: VUNPCKHPS (R11), X9, X2         // c4c1301513
+	//TODO: VUNPCKHPS X2, X9, X2            // c4e13015d2 or c5b015d2
+	//TODO: VUNPCKHPS X11, X9, X2           // c4c13015d3
+	//TODO: VUNPCKHPS (BX), X9, X11         // c46130151b or c530151b
+	//TODO: VUNPCKHPS (R11), X9, X11        // c44130151b
+	//TODO: VUNPCKHPS X2, X9, X11           // c4613015da or c53015da
+	//TODO: VUNPCKHPS X11, X9, X11          // c4413015db
+	//TODO: VUNPCKHPS (BX), Y15, Y2         // c4e1041513 or c5841513
+	//TODO: VUNPCKHPS (R11), Y15, Y2        // c4c1041513
+	//TODO: VUNPCKHPS Y2, Y15, Y2           // c4e10415d2 or c58415d2
+	//TODO: VUNPCKHPS Y11, Y15, Y2          // c4c10415d3
+	//TODO: VUNPCKHPS (BX), Y15, Y11        // c46104151b or c504151b
+	//TODO: VUNPCKHPS (R11), Y15, Y11       // c44104151b
+	//TODO: VUNPCKHPS Y2, Y15, Y11          // c4610415da or c50415da
+	//TODO: VUNPCKHPS Y11, Y15, Y11         // c4410415db
+	//TODO: VUNPCKLPD (BX), X9, X2          // c4e1311413 or c5b11413
+	//TODO: VUNPCKLPD (R11), X9, X2         // c4c1311413
+	//TODO: VUNPCKLPD X2, X9, X2            // c4e13114d2 or c5b114d2
+	//TODO: VUNPCKLPD X11, X9, X2           // c4c13114d3
+	//TODO: VUNPCKLPD (BX), X9, X11         // c46131141b or c531141b
+	//TODO: VUNPCKLPD (R11), X9, X11        // c44131141b
+	//TODO: VUNPCKLPD X2, X9, X11           // c4613114da or c53114da
+	//TODO: VUNPCKLPD X11, X9, X11          // c4413114db
+	//TODO: VUNPCKLPD (BX), Y15, Y2         // c4e1051413 or c5851413
+	//TODO: VUNPCKLPD (R11), Y15, Y2        // c4c1051413
+	//TODO: VUNPCKLPD Y2, Y15, Y2           // c4e10514d2 or c58514d2
+	//TODO: VUNPCKLPD Y11, Y15, Y2          // c4c10514d3
+	//TODO: VUNPCKLPD (BX), Y15, Y11        // c46105141b or c505141b
+	//TODO: VUNPCKLPD (R11), Y15, Y11       // c44105141b
+	//TODO: VUNPCKLPD Y2, Y15, Y11          // c4610514da or c50514da
+	//TODO: VUNPCKLPD Y11, Y15, Y11         // c4410514db
+	//TODO: VUNPCKLPS (BX), X9, X2          // c4e1301413 or c5b01413
+	//TODO: VUNPCKLPS (R11), X9, X2         // c4c1301413
+	//TODO: VUNPCKLPS X2, X9, X2            // c4e13014d2 or c5b014d2
+	//TODO: VUNPCKLPS X11, X9, X2           // c4c13014d3
+	//TODO: VUNPCKLPS (BX), X9, X11         // c46130141b or c530141b
+	//TODO: VUNPCKLPS (R11), X9, X11        // c44130141b
+	//TODO: VUNPCKLPS X2, X9, X11           // c4613014da or c53014da
+	//TODO: VUNPCKLPS X11, X9, X11          // c4413014db
+	//TODO: VUNPCKLPS (BX), Y15, Y2         // c4e1041413 or c5841413
+	//TODO: VUNPCKLPS (R11), Y15, Y2        // c4c1041413
+	//TODO: VUNPCKLPS Y2, Y15, Y2           // c4e10414d2 or c58414d2
+	//TODO: VUNPCKLPS Y11, Y15, Y2          // c4c10414d3
+	//TODO: VUNPCKLPS (BX), Y15, Y11        // c46104141b or c504141b
+	//TODO: VUNPCKLPS (R11), Y15, Y11       // c44104141b
+	//TODO: VUNPCKLPS Y2, Y15, Y11          // c4610414da or c50414da
+	//TODO: VUNPCKLPS Y11, Y15, Y11         // c4410414db
+	//TODO: VXORPD (BX), X9, X2             // c4e1315713 or c5b15713
+	//TODO: VXORPD (R11), X9, X2            // c4c1315713
+	//TODO: VXORPD X2, X9, X2               // c4e13157d2 or c5b157d2
+	//TODO: VXORPD X11, X9, X2              // c4c13157d3
+	//TODO: VXORPD (BX), X9, X11            // c46131571b or c531571b
+	//TODO: VXORPD (R11), X9, X11           // c44131571b
+	//TODO: VXORPD X2, X9, X11              // c4613157da or c53157da
+	//TODO: VXORPD X11, X9, X11             // c4413157db
+	//TODO: VXORPD (BX), Y15, Y2            // c4e1055713 or c5855713
+	//TODO: VXORPD (R11), Y15, Y2           // c4c1055713
+	//TODO: VXORPD Y2, Y15, Y2              // c4e10557d2 or c58557d2
+	//TODO: VXORPD Y11, Y15, Y2             // c4c10557d3
+	//TODO: VXORPD (BX), Y15, Y11           // c46105571b or c505571b
+	//TODO: VXORPD (R11), Y15, Y11          // c44105571b
+	//TODO: VXORPD Y2, Y15, Y11             // c4610557da or c50557da
+	//TODO: VXORPD Y11, Y15, Y11            // c4410557db
+	//TODO: VXORPS (BX), X9, X2             // c4e1305713 or c5b05713
+	//TODO: VXORPS (R11), X9, X2            // c4c1305713
+	//TODO: VXORPS X2, X9, X2               // c4e13057d2 or c5b057d2
+	//TODO: VXORPS X11, X9, X2              // c4c13057d3
+	//TODO: VXORPS (BX), X9, X11            // c46130571b or c530571b
+	//TODO: VXORPS (R11), X9, X11           // c44130571b
+	//TODO: VXORPS X2, X9, X11              // c4613057da or c53057da
+	//TODO: VXORPS X11, X9, X11             // c4413057db
+	//TODO: VXORPS (BX), Y15, Y2            // c4e1045713 or c5845713
+	//TODO: VXORPS (R11), Y15, Y2           // c4c1045713
+	//TODO: VXORPS Y2, Y15, Y2              // c4e10457d2 or c58457d2
+	//TODO: VXORPS Y11, Y15, Y2             // c4c10457d3
+	//TODO: VXORPS (BX), Y15, Y11           // c46104571b or c504571b
+	//TODO: VXORPS (R11), Y15, Y11          // c44104571b
+	//TODO: VXORPS Y2, Y15, Y11             // c4610457da or c50457da
+	//TODO: VXORPS Y11, Y15, Y11            // c4410457db
+	//TODO: VZEROALL                        // c4e17c77 or c5fc77
+	VZEROUPPER                              // c4e17877 or c5f877
+	WBINVD                                  // 0f09
+	//TODO: WRFSBASE DX                     // f30faed2 or f3480faed2
+	//TODO: WRFSBASE R11                    // f3410faed3 or f3490faed3
+	//TODO: WRGSBASE DX                     // f30faeda or f3480faeda
+	//TODO: WRGSBASE R11                    // f3410faedb or f3490faedb
+	WRMSR                                   // 0f30
+	//TODO: WRPKRU                          // 0f01ef
+	XABORT $7                               // c6f807
+	XADDW DX, (BX)                          // 660fc113
+	XADDW R11, (BX)                         // 66440fc11b
+	XADDW DX, (R11)                         // 66410fc113
+	XADDW R11, (R11)                        // 66450fc11b
+	XADDW DX, DX                            // 660fc1d2
+	XADDW R11, DX                           // 66440fc1da
+	XADDW DX, R11                           // 66410fc1d3
+	XADDW R11, R11                          // 66450fc1db
+	XADDL DX, (BX)                          // 0fc113
+	XADDL R11, (BX)                         // 440fc11b
+	XADDL DX, (R11)                         // 410fc113
+	XADDL R11, (R11)                        // 450fc11b
+	XADDL DX, DX                            // 0fc1d2
+	XADDL R11, DX                           // 440fc1da
+	XADDL DX, R11                           // 410fc1d3
+	XADDL R11, R11                          // 450fc1db
+	XADDQ DX, (BX)                          // 480fc113
+	XADDQ R11, (BX)                         // 4c0fc11b
+	XADDQ DX, (R11)                         // 490fc113
+	XADDQ R11, (R11)                        // 4d0fc11b
+	XADDQ DX, DX                            // 480fc1d2
+	XADDQ R11, DX                           // 4c0fc1da
+	XADDQ DX, R11                           // 490fc1d3
+	XADDQ R11, R11                          // 4d0fc1db
+	XADDB DL, (BX)                          // 0fc013
+	XADDB R11, (BX)                         // 440fc01b
+	XADDB DL, (R11)                         // 410fc013
+	XADDB R11, (R11)                        // 450fc01b
+	XADDB DL, DL                            // 0fc0d2
+	XADDB R11, DL                           // 440fc0da
+	XADDB DL, R11                           // 410fc0d3
+	XADDB R11, R11                          // 450fc0db
+	//TODO: XBEGIN .+$0x1122                // 66c7f82211
+	//TODO: XBEGIN .+$0x11223344            // c7f844332211
+	XCHGW DX, (BX)                          // 668713
+	XCHGW R11, (BX)                         // 6644871b
+	XCHGW DX, (R11)                         // 66418713
+	XCHGW R11, (R11)                        // 6645871b
+	XCHGW DX, DX                            // 6687d2
+	XCHGW R11, DX                           // 664487da
+	XCHGW DX, R11                           // 664187d3
+	XCHGW R11, R11                          // 664587db
+	XCHGL DX, (BX)                          // 8713
+	XCHGL R11, (BX)                         // 44871b
+	XCHGL DX, (R11)                         // 418713
+	XCHGL R11, (R11)                        // 45871b
+	XCHGL DX, DX                            // 87d2
+	XCHGL R11, DX                           // 4487da
+	XCHGL DX, R11                           // 4187d3
+	XCHGL R11, R11                          // 4587db
+	XCHGQ DX, (BX)                          // 488713
+	XCHGQ R11, (BX)                         // 4c871b
+	XCHGQ DX, (R11)                         // 498713
+	XCHGQ R11, (R11)                        // 4d871b
+	XCHGQ DX, DX                            // 4887d2
+	XCHGQ R11, DX                           // 4c87da
+	XCHGQ DX, R11                           // 4987d3
+	XCHGQ R11, R11                          // 4d87db
+	XCHGB DL, (BX)                          // 8613
+	XCHGB R11, (BX)                         // 44861b
+	XCHGB DL, (R11)                         // 418613
+	XCHGB R11, (R11)                        // 45861b
+	XCHGB DL, DL                            // 86d2
+	XCHGB R11, DL                           // 4486da
+	XCHGB DL, R11                           // 4186d3
+	XCHGB R11, R11                          // 4586db
+	XCHGW AX, DX                            // 6692
+	XCHGW AX, R11                           // 664193
+	XCHGL AX, DX                            // 92
+	XCHGL AX, R11                           // 4193
+	XCHGQ AX, DX                            // 4892
+	XCHGQ AX, R11                           // 4993
+	XEND                                    // 0f01d5
+	XGETBV                                  // 0f01d0
+	XLAT                                    // d7
+	XORB $7, AL                             // 3407
+	XORW $61731, AX                         // 663523f1
+	XORL $4045620583, AX                    // 35674523f1
+	XORQ $-249346713, AX                    // 4835674523f1
+	XORW $61731, (BX)                       // 66813323f1
+	XORW $61731, (R11)                      // 6641813323f1
+	XORW $61731, DX                         // 6681f223f1
+	XORW $61731, R11                        // 664181f323f1
+	XORW $7, (BX)                           // 66833307
+	XORW $7, (R11)                          // 6641833307
+	XORW $7, DX                             // 6683f207
+	XORW $7, R11                            // 664183f307
+	XORW DX, (BX)                           // 663113
+	XORW R11, (BX)                          // 6644311b
+	XORW DX, (R11)                          // 66413113
+	XORW R11, (R11)                         // 6645311b
+	XORW DX, DX                             // 6631d2 or 6633d2
+	XORW R11, DX                            // 664431da or 664133d3
+	XORW DX, R11                            // 664131d3 or 664433da
+	XORW R11, R11                           // 664531db or 664533db
+	XORL $4045620583, (BX)                  // 8133674523f1
+	XORL $4045620583, (R11)                 // 418133674523f1
+	XORL $4045620583, DX                    // 81f2674523f1
+	XORL $4045620583, R11                   // 4181f3674523f1
+	XORL $7, (BX)                           // 833307
+	XORL $7, (R11)                          // 41833307
+	XORL $7, DX                             // 83f207
+	XORL $7, R11                            // 4183f307
+	XORL DX, (BX)                           // 3113
+	XORL R11, (BX)                          // 44311b
+	XORL DX, (R11)                          // 413113
+	XORL R11, (R11)                         // 45311b
+	XORL DX, DX                             // 31d2 or 33d2
+	XORL R11, DX                            // 4431da or 4133d3
+	XORL DX, R11                            // 4131d3 or 4433da
+	XORL R11, R11                           // 4531db or 4533db
+	XORQ $-249346713, (BX)                  // 488133674523f1
+	XORQ $-249346713, (R11)                 // 498133674523f1
+	XORQ $-249346713, DX                    // 4881f2674523f1
+	XORQ $-249346713, R11                   // 4981f3674523f1
+	XORQ $7, (BX)                           // 48833307
+	XORQ $7, (R11)                          // 49833307
+	XORQ $7, DX                             // 4883f207
+	XORQ $7, R11                            // 4983f307
+	XORQ DX, (BX)                           // 483113
+	XORQ R11, (BX)                          // 4c311b
+	XORQ DX, (R11)                          // 493113
+	XORQ R11, (R11)                         // 4d311b
+	XORQ DX, DX                             // 4831d2 or 4833d2
+	XORQ R11, DX                            // 4c31da or 4933d3
+	XORQ DX, R11                            // 4931d3 or 4c33da
+	XORQ R11, R11                           // 4d31db or 4d33db
+	XORB $7, (BX)                           // 803307
+	XORB $7, (R11)                          // 41803307
+	XORB $7, DL                             // 80f207
+	XORB $7, R11                            // 4180f307
+	XORB DL, (BX)                           // 3013
+	XORB R11, (BX)                          // 44301b
+	XORB DL, (R11)                          // 413013
+	XORB R11, (R11)                         // 45301b
+	XORB DL, DL                             // 30d2 or 32d2
+	XORB R11, DL                            // 4430da or 4132d3
+	XORB DL, R11                            // 4130d3 or 4432da
+	XORB R11, R11                           // 4530db or 4532db
+	XORW (BX), DX                           // 663313
+	XORW (R11), DX                          // 66413313
+	XORW (BX), R11                          // 6644331b
+	XORW (R11), R11                         // 6645331b
+	XORL (BX), DX                           // 3313
+	XORL (R11), DX                          // 413313
+	XORL (BX), R11                          // 44331b
+	XORL (R11), R11                         // 45331b
+	XORQ (BX), DX                           // 483313
+	XORQ (R11), DX                          // 493313
+	XORQ (BX), R11                          // 4c331b
+	XORQ (R11), R11                         // 4d331b
+	XORB (BX), DL                           // 3213
+	XORB (R11), DL                          // 413213
+	XORB (BX), R11                          // 44321b
+	XORB (R11), R11                         // 45321b
+	XORPD (BX), X2                          // 660f5713
+	XORPD (R11), X2                         // 66410f5713
+	XORPD X2, X2                            // 660f57d2
+	XORPD X11, X2                           // 66410f57d3
+	XORPD (BX), X11                         // 66440f571b
+	XORPD (R11), X11                        // 66450f571b
+	XORPD X2, X11                           // 66440f57da
+	XORPD X11, X11                          // 66450f57db
+	XORPS (BX), X2                          // 0f5713
+	XORPS (R11), X2                         // 410f5713
+	XORPS X2, X2                            // 0f57d2
+	XORPS X11, X2                           // 410f57d3
+	XORPS (BX), X11                         // 440f571b
+	XORPS (R11), X11                        // 450f571b
+	XORPS X2, X11                           // 440f57da
+	XORPS X11, X11                          // 450f57db
+	//TODO: XRSTOR (BX)                     // 0fae2b
+	//TODO: XRSTOR (R11)                    // 410fae2b
+	//TODO: XRSTOR64 (BX)                   // 480fae2b
+	//TODO: XRSTOR64 (R11)                  // 490fae2b
+	//TODO: XRSTORS (BX)                    // 0fc71b
+	//TODO: XRSTORS (R11)                   // 410fc71b
+	//TODO: XRSTORS64 (BX)                  // 480fc71b
+	//TODO: XRSTORS64 (R11)                 // 490fc71b
+	//TODO: XSAVE (BX)                      // 0fae23
+	//TODO: XSAVE (R11)                     // 410fae23
+	//TODO: XSAVE64 (BX)                    // 480fae23
+	//TODO: XSAVE64 (R11)                   // 490fae23
+	//TODO: XSAVEC (BX)                     // 0fc723
+	//TODO: XSAVEC (R11)                    // 410fc723
+	//TODO: XSAVEC64 (BX)                   // 480fc723
+	//TODO: XSAVEC64 (R11)                  // 490fc723
+	//TODO: XSAVEOPT (BX)                   // 0fae33
+	//TODO: XSAVEOPT (R11)                  // 410fae33
+	//TODO: XSAVEOPT64 (BX)                 // 480fae33
+	//TODO: XSAVEOPT64 (R11)                // 490fae33
+	//TODO: XSAVES (BX)                     // 0fc72b
+	//TODO: XSAVES (R11)                    // 410fc72b
+	//TODO: XSAVES64 (BX)                   // 480fc72b
+	//TODO: XSAVES64 (R11)                  // 490fc72b
+	//TODO: XSETBV                          // 0f01d1
+	XTEST                                   // 0f01d6
+	RET
diff --git a/src/cmd/asm/internal/asm/testdata/amd64error.s b/src/cmd/asm/internal/asm/testdata/amd64error.s
new file mode 100644
index 0000000..9895b54
--- /dev/null
+++ b/src/cmd/asm/internal/asm/testdata/amd64error.s
@@ -0,0 +1,7 @@
+// 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.
+
+TEXT errors(SB),$0
+	MOVL	foo<>(SB)(AX), AX // ERROR "invalid instruction"
+	RET
diff --git a/src/cmd/asm/internal/asm/testdata/arm.out b/src/cmd/asm/internal/asm/testdata/arm.out
deleted file mode 100644
index 1af3999..0000000
--- a/src/cmd/asm/internal/asm/testdata/arm.out
+++ /dev/null
@@ -1,61 +0,0 @@
-9 00001 (testdata/arm.s:9)	TEXT	foo(SB), 0, $0
-18 00002 (testdata/arm.s:18)	ADD	$1, R2, R3
-19 00003 (testdata/arm.s:19)	ADD	R1<<R2, R3, R4
-20 00004 (testdata/arm.s:20)	ADD	R1>>R2, R3, R4
-21 00005 (testdata/arm.s:21)	ADD	R1@>R2, R3, R4
-22 00006 (testdata/arm.s:22)	ADD	R1->R2, R3, R4
-23 00007 (testdata/arm.s:23)	ADD	R1, R2, R3
-24 00008 (testdata/arm.s:24)	ADD	R1<<R2, R3, R4
-34 00009 (testdata/arm.s:34)	ADD	$1, R2
-35 00010 (testdata/arm.s:35)	ADD	R1<<R2, R3
-36 00011 (testdata/arm.s:36)	ADD	R1>>R2, R3
-37 00012 (testdata/arm.s:37)	ADD	R1@>R2, R3
-38 00013 (testdata/arm.s:38)	ADD	R1->R2, R3
-39 00014 (testdata/arm.s:39)	ADD	R1, R2
-48 00015 (testdata/arm.s:48)	CLZ.S	R1, R2
-57 00016 (testdata/arm.s:57)	MOVW.S	R1, R2
-58 00017 (testdata/arm.s:58)	MOVW.S	$1, R2
-59 00018 (testdata/arm.s:59)	MOVW.S	R1<<R2, R3
-68 00019 (testdata/arm.s:68)	JMP.S	20(PC)
-74 00020 (testdata/arm.s:74)	JMP.S	(R2)
-75 00021 (testdata/arm.s:75)	JMP.S	foo(SB)
-76 00022 (testdata/arm.s:76)	JMP.S	bar<>(SB)
-85 00023 (testdata/arm.s:85)	BX	(R2)
-94 00024 (testdata/arm.s:94)	BEQ	25(PC)
-103 00025 (testdata/arm.s:103)	SWI.S	R1
-104 00026 (testdata/arm.s:104)	SWI.S	(R1)
-105 00027 (testdata/arm.s:105)	SWI.S	foo(SB)
-114 00028 (testdata/arm.s:114)	CMP.S	$1, R2
-115 00029 (testdata/arm.s:115)	CMP.S	R1<<R2, R3
-116 00030 (testdata/arm.s:116)	CMP.S	R1, R2
-130 00031 (testdata/arm.s:130)	MOVM	(R1), [R2,R5,R8,g]
-131 00032 (testdata/arm.s:131)	MOVM	(R1), [R2,R3,R4,R5]
-132 00033 (testdata/arm.s:132)	MOVM.S	(R1), [R2]
-143 00034 (testdata/arm.s:143)	MOVM	[R2,R5,R8,g], (R1)
-144 00035 (testdata/arm.s:144)	MOVM	[R2,R3,R4,R5], (R1)
-145 00036 (testdata/arm.s:145)	MOVM.S	[R2], (R1)
-154 00037 (testdata/arm.s:154)	STREX.S	(R2), R1, R3
-160 00038 (testdata/arm.s:160)	STREX.S	(R2), R1, R1
-166 00039 (testdata/arm.s:166)	STREX.S	(R2), R3, R3
-174 00040 (testdata/arm.s:174)	CASE.S	R1
-183 00041 (testdata/arm.s:183)	WORD	$1234
-192 00042 (testdata/arm.s:192)	ABSF.S	F1, F2
-198 00043 (testdata/arm.s:198)	ADDD.S	F1, F2
-199 00044 (testdata/arm.s:199)	ADDD.S	$(0.5), F2
-205 00045 (testdata/arm.s:205)	ADDD.S	F1, F2, F3
-206 00046 (testdata/arm.s:206)	ADDD.S	$(0.5), F2, F3
-212 00047 (testdata/arm.s:212)	CMPD.S	F1, F2
-236 00048 (testdata/arm.s:236)	MRC	$8301712627
-237 00049 (testdata/arm.s:237)	MRC	$8300664051
-246 00050 (testdata/arm.s:246)	MULL	R1, R2, (R3, R4)
-258 00051 (testdata/arm.s:258)	MULAWT	R1, R2, R3, R4
-266 00052 (testdata/arm.s:266)	PLD	(R1)
-267 00053 (testdata/arm.s:267)	PLD	4(R1)
-276 00054 (testdata/arm.s:276)	RET
-280 00055 (testdata/arm.s:280)	JMP	foo(SB)
-281 00056 (testdata/arm.s:281)	CALL	foo(SB)
-282 00057 (testdata/arm.s:282)	JMP	foo(SB)
-283 00058 (testdata/arm.s:283)	CALL	foo(SB)
-286 00059 (testdata/arm.s:286)	CMPF	F1, F2
-287 00060 (testdata/arm.s:287)	CMPD	F1, F2
-296 00061 (testdata/arm.s:296)	END
diff --git a/src/cmd/asm/internal/asm/testdata/arm.s b/src/cmd/asm/internal/asm/testdata/arm.s
index 95fee50..8062750 100644
--- a/src/cmd/asm/internal/asm/testdata/arm.s
+++ b/src/cmd/asm/internal/asm/testdata/arm.s
@@ -6,7 +6,7 @@
 // the old assembler's (5a's) grammar and hand-writing complete
 // instructions for each rule, to guarantee we cover the same space.
 
-TEXT	foo(SB), 0, $0
+TEXT	foo(SB), 7, $0
 
 // ADD
 //
@@ -21,7 +21,7 @@ TEXT	foo(SB), 0, $0
 	ADD	R1@>R2, R3, R4
 	ADD	R1->R2, R3, R4
 	ADD	R1, R2, R3
-	ADD	R(1)<<R(2), R(3), R(4)
+	ADD	R(1)<<R(2), R(3), R(4) // ADD	R1<<R2, R3, R4
 
 //	LTYPE1 cond imsr ',' spreg ',' // asm doesn't support trailing comma.
 //	{
@@ -65,15 +65,16 @@ TEXT	foo(SB), 0, $0
 //	{
 //		outcode($1, $2, &nullgen, 0, &$4);
 //	}
-	B.S	1(PC)
+	B.EQ	1(PC) // BEQ 1(PC)
 
 //	LTYPE4 cond comma nireg
 //	{
 //		outcode($1, $2, &nullgen, 0, &$4);
 //	}
-	B.S	(R2)
-	B.S	foo(SB)
-	B.S	bar<>(SB)
+	BEQ	2(PC)
+	B	foo(SB) // JMP foo(SB)
+	BEQ	2(PC)
+	B	bar<>(SB) // JMP bar<>(SB)
 
 //
 // BX
@@ -82,7 +83,7 @@ TEXT	foo(SB), 0, $0
 //	{
 //		outcode($1, Always, &nullgen, 0, &$3);
 //	}
-	BX	(R2)
+	BX	(R0)
 
 //
 // BEQ
@@ -100,9 +101,9 @@ TEXT	foo(SB), 0, $0
 //	{
 //		outcode($1, $2, &nullgen, 0, &$4);
 //	}
-	SWI.S	R1
+	SWI.S	$2
 	SWI.S	(R1)
-	SWI.S	foo(SB)
+//	SWI.S	foo(SB) - TODO: classifying foo(SB) as C_TLS_LE
 
 //
 // CMP
@@ -127,8 +128,8 @@ TEXT	foo(SB), 0, $0
 //		g.Offset = int64($6);
 //		outcode($1, $2, &$3, 0, &g);
 //	}
-	MOVM	0(R1), [R2,R5,R8,g]
-	MOVM	0(R1), [R2-R5]
+	MOVM	0(R1), [R2,R5,R8,g] // MOVM	(R1), [R2,R5,R8,g]
+	MOVM	(R1), [R2-R5] // MOVM (R1), [R2,R3,R4,R5]
 	MOVM.S	(R1), [R2]
 
 //	LTYPE8 cond '[' reglist ']' ',' ioreg
@@ -140,8 +141,8 @@ TEXT	foo(SB), 0, $0
 //		g.Offset = int64($4);
 //		outcode($1, $2, &g, 0, &$7);
 //	}
-	MOVM	[R2,R5,R8,g], 0(R1)
-	MOVM	[R2-R5], 0(R1)
+	MOVM	[R2,R5,R8,g], 0(R1) // MOVM	[R2,R5,R8,g], (R1)
+	MOVM	[R2-R5], (R1) // MOVM [R2,R3,R4,R5], (R1)
 	MOVM.S	[R2], (R1)
 
 //
@@ -151,27 +152,19 @@ TEXT	foo(SB), 0, $0
 //	{
 //		outcode($1, $2, &$5, int32($3.Reg), &$7);
 //	}
-	STREX.S	R1, (R2), R3
+	STREX.S	R1, (R2), R3 // STREX.S (R2), R1, R3
 
 //	LTYPE9 cond reg ',' ireg
 //	{
 //		outcode($1, $2, &$5, int32($3.Reg), &$3);
 //	}
-	STREX.S	R1, (R2)
+	STREX.S	R1, (R2) // STREX.S (R2), R1, R1
 
 //	LTYPE9 cond comma ireg ',' reg
 //	{
 //		outcode($1, $2, &$4, int32($6.Reg), &$6);
 //	}
-	STREX.S	(R2), R3
-
-// CASE
-//
-//	LTYPED cond reg
-//	{
-//		outcode($1, $2, &$3, 0, &nullgen);
-//	}
-	CASE.S	R1
+	STREX.S	(R2), R3 // STREX.S (R2), R3, R3
 
 //
 // word
@@ -196,14 +189,13 @@ TEXT	foo(SB), 0, $0
 //		outcode($1, $2, &$3, 0, &$5);
 //	}
 	ADDD.S	F1, F2
-	ADDD.S	$0.5, F2
+	MOVF	$0.5, F2 // MOVF $(0.5), F2
 
 //	LTYPEK cond frcon ',' LFREG ',' freg
 //	{
 //		outcode($1, $2, &$3, $5, &$7);
 //	}
 	ADDD.S	F1, F2, F3
-	ADDD.S	$0.5, F2, F3
 
 //	LTYPEL cond freg ',' freg
 //	{
@@ -233,8 +225,8 @@ TEXT	foo(SB), 0, $0
 //			(1<<4));			/* must be set */
 //		outcode(AMRC, Always, &nullgen, 0, &g);
 //	}
-	MRC.S	4, 6, R1, C2, C3, 7
-	MCR.S	4, 6, R1, C2, C3, 7
+	MRC.S	4, 6, R1, C2, C3, 7 // MRC $8301712627
+	MCR.S	4, 6, R1, C2, C3, 7 // MRC $8300664051
 
 //
 // MULL r1,r2,(hi,lo)
@@ -273,12 +265,15 @@ TEXT	foo(SB), 0, $0
 //	{
 //		outcode($1, $2, &nullgen, 0, &nullgen);
 //	}
+	BEQ	2(PC)
 	RET
 
 // More B/BL cases, and canonical names JMP, CALL.
 
-	B	foo(SB)
-	BL	foo(SB)
+	BEQ	2(PC)
+	B	foo(SB) // JMP foo(SB)
+	BL	foo(SB) // CALL foo(SB)
+	BEQ	2(PC)
 	JMP	foo(SB)
 	CALL	foo(SB)
 
diff --git a/src/cmd/asm/internal/asm/testdata/arm64.out b/src/cmd/asm/internal/asm/testdata/arm64.out
deleted file mode 100644
index 0b7b430..0000000
--- a/src/cmd/asm/internal/asm/testdata/arm64.out
+++ /dev/null
@@ -1,55 +0,0 @@
-9 00001 (testdata/arm64.s:9)	TEXT	foo(SB), 7, $-8
-20 00002 (testdata/arm64.s:20)	ADDW	$1, R2, R3
-21 00003 (testdata/arm64.s:21)	ADDW	R1, R2, R3
-22 00004 (testdata/arm64.s:22)	ADDW	R1, ZR, R3
-23 00005 (testdata/arm64.s:23)	ADD	$1, R2, R3
-24 00006 (testdata/arm64.s:24)	ADD	R1, R2, R3
-25 00007 (testdata/arm64.s:25)	ADD	R1, ZR, R3
-26 00008 (testdata/arm64.s:26)	ADD	$1, R2, R3
-36 00009 (testdata/arm64.s:36)	ADDW	$1, R2
-37 00010 (testdata/arm64.s:37)	ADDW	R1, R2
-38 00011 (testdata/arm64.s:38)	ADD	$1, R2
-39 00012 (testdata/arm64.s:39)	ADD	R1, R2
-48 00013 (testdata/arm64.s:48)	CLSW	R1, R2
-49 00014 (testdata/arm64.s:49)	CLS	R1, R2
-58 00015 (testdata/arm64.s:58)	MOVW	R1, R2
-59 00016 (testdata/arm64.s:59)	MOVW	ZR, R1
-60 00017 (testdata/arm64.s:60)	MOVW	R1, ZR
-61 00018 (testdata/arm64.s:61)	MOVW	$1, ZR
-62 00019 (testdata/arm64.s:62)	MOVW	$1, R1
-63 00020 (testdata/arm64.s:63)	MOVW	ZR, (R1)
-64 00021 (testdata/arm64.s:64)	MOVD	R1, R2
-65 00022 (testdata/arm64.s:65)	MOVD	ZR, R1
-66 00023 (testdata/arm64.s:66)	MOVD	$1, ZR
-67 00024 (testdata/arm64.s:67)	MOVD	$1, R1
-68 00025 (testdata/arm64.s:68)	MOVD	ZR, (R1)
-77 00026 (testdata/arm64.s:77)	MOVK	$1, R1
-86 00027 (testdata/arm64.s:86)	CALL	28(PC)
-92 00028 (testdata/arm64.s:92)	CALL	(R2)
-93 00029 (testdata/arm64.s:93)	CALL	foo(SB)
-94 00030 (testdata/arm64.s:94)	CALL	bar<>(SB)
-102 00031 (testdata/arm64.s:102)	BEQ	32(PC)
-110 00032 (testdata/arm64.s:110)	SVC
-119 00033 (testdata/arm64.s:119)	CMP	$3, R2
-120 00034 (testdata/arm64.s:120)	CMP	R1, R2
-130 00035 (testdata/arm64.s:130)	CBZ	R1
-139 00036 (testdata/arm64.s:139)	CSET	GT, R1
-147 00037 (testdata/arm64.s:147)	CSEL	LT, R1, R2, ZR
-148 00038 (testdata/arm64.s:148)	CSINC	GT, R1, ZR, R3
-149 00039 (testdata/arm64.s:149)	CSNEG	MI, R1, R2, R3
-150 00040 (testdata/arm64.s:150)	CSINV	0, R1, R2, R3
-156 00041 (testdata/arm64.s:156)	CSEL	LT, R1, R2
-164 00042 (testdata/arm64.s:164)	CCMN	MI, ZR, R1, $4
-173 00043 (testdata/arm64.s:173)	FADDD	$(0.5), F1
-174 00044 (testdata/arm64.s:174)	FADDD	F1, F2
-180 00045 (testdata/arm64.s:180)	FADDD	$(0.69999999999999996), F1, F2
-181 00046 (testdata/arm64.s:181)	FADDD	F1, F2, F3
-233 00047 (testdata/arm64.s:233)	DMB	$1
-242 00048 (testdata/arm64.s:242)	LDAXRW	(R0), R2
-243 00049 (testdata/arm64.s:243)	STLXRW	R1, (R0), R3
-251 00050 (testdata/arm64.s:251)	RET
-255 00051 (testdata/arm64.s:255)	JMP	foo(SB)
-256 00052 (testdata/arm64.s:256)	CALL	foo(SB)
-257 00053 (testdata/arm64.s:257)	JMP	foo(SB)
-258 00054 (testdata/arm64.s:258)	CALL	foo(SB)
-266 00055 (testdata/arm64.s:266)	END
diff --git a/src/cmd/asm/internal/asm/testdata/arm64.s b/src/cmd/asm/internal/asm/testdata/arm64.s
index 2c8720b..22d4306 100644
--- a/src/cmd/asm/internal/asm/testdata/arm64.s
+++ b/src/cmd/asm/internal/asm/testdata/arm64.s
@@ -83,15 +83,15 @@ TEXT	foo(SB), 7, $-8
 //	{
 //		outcode($1, &nullgen, NREG, &$3);
 //	}
-	BL	1(PC)
+	BL	1(PC) // CALL 1(PC)
 
 //		LTYPE4 comma nireg
 //	{
 //		outcode($1, &nullgen, NREG, &$3);
 //	}
-	BL	(R2)
-	BL	foo(SB)
-	BL	bar<>(SB)
+	BL	(R2) // CALL (R2)
+	BL	foo(SB) // CALL foo(SB)
+	BL	bar<>(SB) // CALL bar<>(SB)
 //
 // BEQ
 //
@@ -127,7 +127,7 @@ TEXT	foo(SB), 7, $-8
 //		outcode($1, &$2, NREG, &$4);
 //	}
 again:
-	CBZ	R1, again
+	CBZ	R1, again // CBZ R1
 
 //
 // CSET
@@ -147,7 +147,7 @@ again:
 	CSEL	LT, R1, R2, ZR
 	CSINC	GT, R1, ZR, R3
 	CSNEG	MI, R1, R2, R3
-	CSINV	CS, R1, R2, R3
+	CSINV	CS, R1, R2, R3 // CSINV HS, R1, R2, R3
 
 //		LTYPES cond ',' reg ',' reg
 //	{
@@ -170,14 +170,14 @@ again:
 //	{
 //		outcode($1, &$2, NREG, &$4);
 //	}
-	FADDD	$0.5, F1
+	FADDD	$0.5, F1 // FADDD $(0.5), F1
 	FADDD	F1, F2
 
 //		LTYPEK frcon ',' freg ',' freg
 //	{
 //		outcode($1, &$2, $4.reg, &$6);
 //	}
-	FADDD	$0.7, F1, F2
+	FADDD	$0.7, F1, F2 // FADDD	$(0.69999999999999996), F1, F2
 	FADDD	F1, F2, F3
 
 //
@@ -248,12 +248,15 @@ again:
 //	{
 //		outcode($1, &nullgen, NREG, &nullgen);
 //	}
+	BEQ	2(PC)
 	RET
 
 // More B/BL cases, and canonical names JMP, CALL.
 
-	B	foo(SB)
-	BL	foo(SB)
+	BEQ	2(PC)
+	B	foo(SB) // JMP foo(SB)
+	BL	foo(SB) // CALL foo(SB)
+	BEQ	2(PC)
 	JMP	foo(SB)
 	CALL	foo(SB)
 
diff --git a/src/cmd/asm/internal/asm/testdata/mips64.s b/src/cmd/asm/internal/asm/testdata/mips64.s
new file mode 100644
index 0000000..12330a2
--- /dev/null
+++ b/src/cmd/asm/internal/asm/testdata/mips64.s
@@ -0,0 +1,403 @@
+// Copyright 2015 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 input was created by taking the ppc64 testcase and modified
+// by hand.
+
+TEXT foo(SB),7,$0
+
+//inst:
+//
+// load ints and bytes
+//
+//	LMOVW rreg ',' rreg
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	MOVW	R1, R2
+	MOVW	LO, R1
+	MOVW	HI, R1
+	MOVW	R1, LO
+	MOVW	R1, HI
+	MOVV	R1, R2
+	MOVV	LO, R1
+	MOVV	HI, R1
+	MOVV	R1, LO
+	MOVV	R1, HI
+
+//	LMOVW addr ',' rreg
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	MOVW	foo<>+3(SB), R2
+	MOVW	16(R1), R2
+	MOVW	(R1), R2
+	MOVV	foo<>+3(SB), R2
+	MOVV	16(R1), R2
+	MOVV	(R1), R2
+
+//	LMOVB rreg ',' rreg
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	MOVB	R1, R2
+
+//	LMOVB addr ',' rreg
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	MOVB	foo<>+3(SB), R2
+	MOVB	16(R1), R2
+	MOVB	(R1), R2
+
+//
+// load floats
+//
+//	LFMOV addr ',' freg
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	MOVD	foo<>+3(SB), F2
+	MOVD	16(R1), F2
+	MOVD	(R1), F2
+
+//	LFMOV fimm ',' freg
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	MOVD	$0.1, F2 // MOVD $(0.10000000000000001), F2
+
+//	LFMOV freg ',' freg
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	MOVD	F1, F2
+
+//	LFMOV freg ',' addr
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	MOVD	F2, foo<>+3(SB)
+	MOVD	F2, 16(R1)
+	MOVD	F2, (R1)
+
+//
+// store ints and bytes
+//
+//	LMOVW rreg ',' addr
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	MOVW	R1, foo<>+3(SB)
+	MOVW	R1, 16(R2)
+	MOVW	R1, (R2)
+	MOVV	R1, foo<>+3(SB)
+	MOVV	R1, 16(R2)
+	MOVV	R1, (R2)
+
+//	LMOVB rreg ',' addr
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	MOVB	R1, foo<>+3(SB)
+	MOVB	R1, 16(R2)
+	MOVB	R1, (R2)
+
+//
+// store floats
+//
+//	LMOVW freg ',' addr
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	MOVD	F1, foo<>+3(SB)
+	MOVD	F1, 16(R2)
+	MOVD	F1, (R2)
+
+//
+// floating point status
+//
+//	LMOVW fpscr ',' freg
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	MOVW	FCR0, R1
+
+//	LMOVW freg ','  fpscr
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	MOVW	R1, FCR0
+
+//	LMOVW rreg ',' mreg
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	MOVW	R1, M1
+	MOVV	R1, M1
+
+//	LMOVW mreg ',' rreg
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	MOVW	M1, R1
+	MOVV	M1, R1
+
+
+//
+// integer operations
+// logical instructions
+// shift instructions
+// unary instructions
+//
+//	LADDW rreg ',' sreg ',' rreg
+//	{
+//		outcode(int($1), &$2, int($4), &$6);
+//	}
+	ADD	R1, R2, R3
+
+//	LADDW imm ',' sreg ',' rreg
+//	{
+//		outcode(int($1), &$2, int($4), &$6);
+//	}
+	ADD	$1, R2, R3
+
+//	LADDW rreg ',' rreg
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	ADD	R1, R2
+
+//	LADDW imm ',' rreg
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	ADD	$4, R1
+
+//	LMUL rreg ',' rreg
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	MUL	R1, R2
+
+//	LSHW rreg ',' sreg ',' rreg
+//	{
+//		outcode(int($1), &$2, int($4), &$6);
+//	}
+	SLL	R1, R2, R3
+
+//	LSHW rreg ',' rreg
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	SLL	R1, R2
+
+//	LSHW imm ',' sreg ',' rreg
+//	{
+//		outcode(int($1), &$2, int($4), &$6);
+//	}
+	SLL	$4, R1, R2
+
+//	LSHW imm ',' rreg
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	SLL	$4, R1
+
+//
+// move immediate: macro for lui+or, addi, addis, and other combinations
+//
+//	LMOVW imm ',' rreg
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	MOVW	$1, R1
+	MOVV	$1, R1
+
+//	LMOVW ximm ',' rreg
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	MOVW	$1, R1
+	MOVW	$foo(SB), R1
+	MOVV	$1, R1
+	MOVV	$foo(SB), R1
+
+
+//
+// branch
+//
+//	LBRA rel
+//	{
+//		outcode(int($1), &nullgen, 0, &$2);
+//	}
+	BEQ	R1, 2(PC)
+label0:
+	JMP	1(PC)
+	BEQ	R1, 2(PC)
+	JMP	label0+0 // JMP 64
+	BEQ	R1, 2(PC)
+	JAL	1(PC) // CALL 1(PC)
+	BEQ	R1, 2(PC)
+	JAL	label0+0 // CALL 64
+
+//	LBRA addr
+//	{
+//		outcode(int($1), &nullgen, 0, &$2);
+//	}
+	BEQ	R1, 2(PC)
+	JMP	0(R1) // JMP (R1)
+	BEQ	R1, 2(PC)
+	JMP	foo+0(SB) // JMP foo(SB)
+	BEQ	R1, 2(PC)
+	JAL	0(R1) // CALL (R1)
+	BEQ	R1, 2(PC)
+	JAL	foo+0(SB) // CALL foo(SB)
+
+//
+// BEQ/BNE
+//
+//	LBRA rreg ',' rel
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+label1:
+	BEQ	R1, 1(PC)
+	BEQ	R1, label1 // BEQ R1, 79
+
+//	LBRA rreg ',' sreg ',' rel
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+label2:
+	BEQ	R1, R2, 1(PC)
+	BEQ	R1, R2, label2 // BEQ R1, R2, 81
+
+//
+// other integer conditional branch
+//
+//	LBRA rreg ',' rel
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+label3:
+	BLTZ	R1, 1(PC)
+	BLTZ	R1, label3 // BLTZ R1, 83
+
+//
+// floating point conditional branch
+//
+//	LBRA rel
+label4:
+	BFPT	1(PC)
+	BFPT	label4 // BFPT 85
+
+
+//
+// floating point operate
+//
+//	LFCONV freg ',' freg
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	ABSD	F1, F2
+
+//	LFADD freg ',' freg
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	ADDD	F1, F2
+
+//	LFADD freg ',' freg ',' freg
+//	{
+//		outcode(int($1), &$2, int($4.Reg), &$6);
+//	}
+	ADDD	F1, F2, F3
+
+//	LFCMP freg ',' freg
+//	{
+//		outcode(int($1), &$2, 0, &$4);
+//	}
+	CMPEQD	F1, F2
+
+
+//
+// WORD
+//
+	WORD	$1
+	WORD	$foo(SB)
+
+//
+// NOP
+//
+//	LNOP comma // asm doesn't support the trailing comma.
+//	{
+//		outcode(int($1), &nullgen, 0, &nullgen);
+//	}
+	NOP
+
+//	LNOP rreg comma // asm doesn't support the trailing comma.
+//	{
+//		outcode(int($1), &$2, 0, &nullgen);
+//	}
+	NOP R2
+
+//	LNOP freg comma // asm doesn't support the trailing comma.
+//	{
+//		outcode(int($1), &$2, 0, &nullgen);
+//	}
+	NOP	F2
+
+//	LNOP ',' rreg // asm doesn't support the leading comma.
+//	{
+//		outcode(int($1), &nullgen, 0, &$3);
+//	}
+	NOP	R2
+
+//	LNOP ',' freg // asm doesn't support the leading comma.
+//	{
+//		outcode(int($1), &nullgen, 0, &$3);
+//	}
+	NOP	F2
+
+//	LNOP imm
+//	{
+//		outcode(int($1), &$2, 0, &nullgen);
+//	}
+	NOP	$4
+
+//
+// special
+//
+	SYSCALL
+	BREAK
+	// overloaded cache opcode:
+	BREAK	R1, (R1)
+
+//
+// RET
+//
+//	LRETRN	comma // asm doesn't support the trailing comma.
+//	{
+//		outcode(int($1), &nullgen, 0, &nullgen);
+//	}
+	SYSCALL
+	BEQ	R1, 2(PC)
+	RET
+
+
+// More JMP/JAL cases, and canonical names JMP, CALL.
+
+	JAL	foo(SB) // CALL foo(SB)
+	BEQ	R1, 2(PC)
+	JMP	foo(SB)
+	CALL	foo(SB)
+
+// END
+//
+//	LEND	comma // asm doesn't support the trailing comma.
+//	{
+//		outcode(int($1), &nullgen, 0, &nullgen);
+//	}
+	END
diff --git a/src/cmd/asm/internal/asm/testdata/ppc64.out b/src/cmd/asm/internal/asm/testdata/ppc64.out
deleted file mode 100644
index 2a5d175..0000000
--- a/src/cmd/asm/internal/asm/testdata/ppc64.out
+++ /dev/null
@@ -1,114 +0,0 @@
-9 00001 (testdata/ppc64.s:9)	TEXT	foo(SB), 0, $0
-19 00002 (testdata/ppc64.s:19)	MOVW	R1, R2
-25 00003 (testdata/ppc64.s:25)	MOVW	foo<>+3(SB), R2
-26 00004 (testdata/ppc64.s:26)	MOVW	16(R1), R2
-32 00005 (testdata/ppc64.s:32)	MOVW	(R1), R2
-33 00006 (testdata/ppc64.s:33)	MOVW	(R1)(R2*1), R3
-39 00007 (testdata/ppc64.s:39)	MOVW	R1, R2
-45 00008 (testdata/ppc64.s:45)	MOVB	foo<>+3(SB), R2
-46 00009 (testdata/ppc64.s:46)	MOVB	16(R1), R2
-52 00010 (testdata/ppc64.s:52)	MOVB	(R1), R2
-53 00011 (testdata/ppc64.s:53)	MOVB	(R1)(R2*1), R3
-62 00012 (testdata/ppc64.s:62)	FMOVD	foo<>+3(SB), F2
-63 00013 (testdata/ppc64.s:63)	FMOVD	16(R1), F2
-69 00014 (testdata/ppc64.s:69)	FMOVD	(R1), F2
-75 00015 (testdata/ppc64.s:75)	FMOVD	$(0.10000000000000001), F2
-81 00016 (testdata/ppc64.s:81)	FMOVD	F1, F2
-87 00017 (testdata/ppc64.s:87)	FMOVD	F2, foo<>+3(SB)
-88 00018 (testdata/ppc64.s:88)	FMOVD	F2, 16(R1)
-94 00019 (testdata/ppc64.s:94)	FMOVD	F2, (R1)
-103 00020 (testdata/ppc64.s:103)	MOVW	R1, foo<>+3(SB)
-104 00021 (testdata/ppc64.s:104)	MOVW	R1, 16(R2)
-110 00022 (testdata/ppc64.s:110)	MOVW	R1, (R1)
-111 00023 (testdata/ppc64.s:111)	MOVW	R1, (R2)(R3*1)
-117 00024 (testdata/ppc64.s:117)	MOVB	R1, foo<>+3(SB)
-118 00025 (testdata/ppc64.s:118)	MOVB	R1, 16(R2)
-124 00026 (testdata/ppc64.s:124)	MOVB	R1, (R1)
-125 00027 (testdata/ppc64.s:125)	MOVB	R1, (R2)(R3*1)
-133 00028 (testdata/ppc64.s:133)	FMOVD	F1, foo<>+3(SB)
-134 00029 (testdata/ppc64.s:134)	FMOVD	F1, 16(R2)
-140 00030 (testdata/ppc64.s:140)	FMOVD	F1, (R1)
-149 00031 (testdata/ppc64.s:149)	MOVFL	FPSCR, F1
-155 00032 (testdata/ppc64.s:155)	MOVFL	F1, FPSCR
-161 00033 (testdata/ppc64.s:161)	MOVFL	F1, $4, FPSCR
-167 00034 (testdata/ppc64.s:167)	MOVFL	FPSCR, CR0
-188 00035 (testdata/ppc64.s:188)	MOVW	R1, CR1
-194 00036 (testdata/ppc64.s:194)	MOVW	R1, CR
-206 00037 (testdata/ppc64.s:206)	ADD	R1, R2, R3
-212 00038 (testdata/ppc64.s:212)	ADD	$1, R2, R3
-224 00039 (testdata/ppc64.s:224)	ADD	R1, R2
-230 00040 (testdata/ppc64.s:230)	ADD	$4, R1
-236 00041 (testdata/ppc64.s:236)	ADDE	R1, R2, R3
-242 00042 (testdata/ppc64.s:242)	ADDE	R1, R2
-248 00043 (testdata/ppc64.s:248)	SLW	R1, R2, R3
-254 00044 (testdata/ppc64.s:254)	SLW	R1, R2
-260 00045 (testdata/ppc64.s:260)	SLW	$4, R1, R2
-266 00046 (testdata/ppc64.s:266)	SLW	$4, R1
-272 00047 (testdata/ppc64.s:272)	SLW	$4, R1
-278 00048 (testdata/ppc64.s:278)	SUBME	R1, R1
-296 00049 (testdata/ppc64.s:296)	MOVW	$1, R1
-302 00050 (testdata/ppc64.s:302)	MOVW	$1, R1
-303 00051 (testdata/ppc64.s:303)	MOVW	$foo(SB), R1
-327 00052 (testdata/ppc64.s:327)	MOVFL	CR0, CR1
-339 00053 (testdata/ppc64.s:339)	MOVW	CR, R1
-345 00054 (testdata/ppc64.s:345)	MOVW	SPR(0), R1
-346 00055 (testdata/ppc64.s:346)	MOVW	SPR(7), R1
-352 00056 (testdata/ppc64.s:352)	MOVW	LR, R1
-353 00057 (testdata/ppc64.s:353)	MOVW	CTR, R1
-359 00058 (testdata/ppc64.s:359)	MOVW	R1, LR
-360 00059 (testdata/ppc64.s:360)	MOVW	R1, CTR
-372 00060 (testdata/ppc64.s:372)	MOVW	R1, SPR(7)
-384 00061 (testdata/ppc64.s:384)	JMP	62(PC)
-385 00062 (testdata/ppc64.s:385)	JMP	61
-391 00063 (testdata/ppc64.s:391)	JMP	4(R1)
-392 00064 (testdata/ppc64.s:392)	JMP	foo(SB)
-398 00065 (testdata/ppc64.s:398)	JMP	CTR
-417 00066 (testdata/ppc64.s:417)	BEQ	CR1, 67(PC)
-418 00067 (testdata/ppc64.s:418)	BEQ	CR1, 66
-444 00068 (testdata/ppc64.s:444)	BC	4, CTR
-454 00069 (testdata/ppc64.s:454)	BC	$3, R4, 66
-474 00070 (testdata/ppc64.s:474)	BC	$3, R3, LR
-504 00071 (testdata/ppc64.s:504)	FABS	F1, F2
-510 00072 (testdata/ppc64.s:510)	FADD	F1, F2
-516 00073 (testdata/ppc64.s:516)	FADD	F1, F2, F3
-522 00074 (testdata/ppc64.s:522)	FMADD	F1, F2, F3, F4
-528 00075 (testdata/ppc64.s:528)	FCMPU	F1, F2
-534 00076 (testdata/ppc64.s:534)	FCMPU	F1, F2, CR0
-543 00077 (testdata/ppc64.s:543)	CMP	R1, R2
-549 00078 (testdata/ppc64.s:549)	CMP	R1, $4
-555 00079 (testdata/ppc64.s:555)	CMP	R1, CR0, R2
-561 00080 (testdata/ppc64.s:561)	CMP	R1, CR0, $4
-570 00081 (testdata/ppc64.s:570)	RLDC	$4, R1, $5, R2
-576 00082 (testdata/ppc64.s:576)	RLDC	$26, R1, $201326592, R2
-582 00083 (testdata/ppc64.s:582)	RLDC	R1, R2, $4, R3
-588 00084 (testdata/ppc64.s:588)	RLWMI	R1, R2, $201326592, R3
-597 00085 (testdata/ppc64.s:597)	MOVMW	foo(SB), R2
-598 00086 (testdata/ppc64.s:598)	MOVMW	4(R1), R2
-604 00087 (testdata/ppc64.s:604)	MOVMW	R1, foo(SB)
-605 00088 (testdata/ppc64.s:605)	MOVMW	R1, 4(R2)
-615 00089 (testdata/ppc64.s:615)	LSW	(R1), R2
-616 00090 (testdata/ppc64.s:616)	LSW	(R1)(R2*1), R3
-622 00091 (testdata/ppc64.s:622)	LSW	(R1), $1, R2
-623 00092 (testdata/ppc64.s:623)	LSW	(R1)(R2*1), $1, R3
-629 00093 (testdata/ppc64.s:629)	STSW	R1, (R2)
-630 00094 (testdata/ppc64.s:630)	STSW	R1, (R2)(R3*1)
-636 00095 (testdata/ppc64.s:636)	STSW	R1, $1, (R2)
-637 00096 (testdata/ppc64.s:637)	STSW	R1, $1, (R2)(R3*1)
-643 00097 (testdata/ppc64.s:643)	MOVHBR	(R1), R2
-644 00098 (testdata/ppc64.s:644)	MOVHBR	(R1)(R2*1), R3
-650 00099 (testdata/ppc64.s:650)	MOVHBR	R1, (R2)
-651 00100 (testdata/ppc64.s:651)	MOVHBR	R1, (R2)(R3*1)
-657 00101 (testdata/ppc64.s:657)	DCBF	(R1)
-658 00102 (testdata/ppc64.s:658)	DCBF	(R1)(R2*1)
-667 00103 (testdata/ppc64.s:667)	NOP
-673 00104 (testdata/ppc64.s:673)	NOP	R2
-679 00105 (testdata/ppc64.s:679)	NOP	F2
-685 00106 (testdata/ppc64.s:685)	NOP	R2
-691 00107 (testdata/ppc64.s:691)	NOP	F2
-697 00108 (testdata/ppc64.s:697)	NOP	$4
-705 00109 (testdata/ppc64.s:705)	RET
-709 00110 (testdata/ppc64.s:709)	JMP	foo(SB)
-710 00111 (testdata/ppc64.s:710)	CALL	foo(SB)
-711 00112 (testdata/ppc64.s:711)	JMP	foo(SB)
-712 00113 (testdata/ppc64.s:712)	CALL	foo(SB)
-720 00114 (testdata/ppc64.s:720)	END
diff --git a/src/cmd/asm/internal/asm/testdata/ppc64.s b/src/cmd/asm/internal/asm/testdata/ppc64.s
index 46c1ee6..c46c6b2 100644
--- a/src/cmd/asm/internal/asm/testdata/ppc64.s
+++ b/src/cmd/asm/internal/asm/testdata/ppc64.s
@@ -6,7 +6,7 @@
 // the old assembler's (9a's) grammar and hand-writing complete
 // instructions for each rule, to guarantee we cover the same space.
 
-TEXT foo(SB),0,$0
+TEXT foo(SB),7,$0
 
 //inst:
 //
@@ -30,7 +30,7 @@ TEXT foo(SB),0,$0
 //		outcode(int($1), &$2, 0, &$4);
 //	}
 	MOVW	(R1), R2
-	MOVW	(R1+R2), R3
+	MOVW	(R1+R2), R3 // MOVW (R1)(R2*1), R3
 
 //	LMOVB rreg ',' rreg
 //	{
@@ -50,7 +50,7 @@ TEXT foo(SB),0,$0
 //		outcode(int($1), &$2, 0, &$4);
 //	}
 	MOVB	(R1), R2
-	MOVB	(R1+R2), R3
+	MOVB	(R1+R2), R3 // MOVB (R1)(R2*1), R3
 
 //
 // load floats
@@ -72,7 +72,7 @@ TEXT foo(SB),0,$0
 //	{
 //		outcode(int($1), &$2, 0, &$4);
 //	}
-	FMOVD	$0.1, F2
+	FMOVD	$0.1, F2 // FMOVD $(0.10000000000000001), F2
 
 //	LFMOV freg ',' freg
 //	{
@@ -108,7 +108,7 @@ TEXT foo(SB),0,$0
 //		outcode(int($1), &$2, 0, &$4);
 //	}
 	MOVW	R1, (R1)
-	MOVW	R1, (R2+R3)
+	MOVW	R1, (R2+R3) // MOVW R1, (R2)(R3*1)
 
 //	LMOVB rreg ',' addr
 //	{
@@ -122,7 +122,7 @@ TEXT foo(SB),0,$0
 //		outcode(int($1), &$2, 0, &$4);
 //	}
 	MOVB	R1, (R1)
-	MOVB	R1, (R2+R3)
+	MOVB	R1, (R2+R3) // MOVB R1, (R2)(R3*1)
 //
 // store floats
 //
@@ -275,7 +275,7 @@ TEXT foo(SB),0,$0
 //	{
 //		outcode(int($1), &$2, 0, &$2);
 //	}
-	SUBME	R1
+	SUBME	R1 // SUBME R1, R1
 
 //
 // multiply-accumulate
@@ -380,22 +380,29 @@ TEXT foo(SB),0,$0
 //	{
 //		outcode(int($1), &nullgen, 0, &$2);
 //	}
+	BEQ	CR1, 2(PC)
 label0:
-	BR	1(PC)
-	BR	label0+0
+	BR	1(PC) // JMP 1(PC)
+	BEQ	CR1, 2(PC)
+	BR	label0+0 // JMP 62
 
 //	LBRA addr
 //	{
 //		outcode(int($1), &nullgen, 0, &$2);
 //	}
-	BR	4(R1)
-	BR	foo+0(SB)
+	BEQ	CR1, 2(PC)
+	BR	LR // JMP LR
+	BEQ	CR1, 2(PC)
+//	BR	0(R1)	// TODO should work
+	BEQ	CR1, 2(PC)
+	BR	foo+0(SB) // JMP foo(SB)
 
 //	LBRA '(' xlreg ')'
 //	{
 //		outcode(int($1), &nullgen, 0, &$3);
 //	}
-	BR	(CTR)
+	BEQ	CR1, 2(PC)
+	BR	(CTR) // JMP CTR
 
 //	LBRA ',' rel  // asm doesn't support the leading comma
 //	{
@@ -415,7 +422,7 @@ label0:
 //	}
 label1:
 	BEQ	CR1, 1(PC)
-	BEQ	CR1, label1
+	BEQ	CR1, label1 // BEQ CR1, 72
 
 //	LBRA creg ',' addr // TODO DOES NOT WORK in 9a
 //	{
@@ -441,7 +448,7 @@ label1:
 //	{
 //		outcode(int($1), &nullgen, int($2), &$5);
 //	}
-	BC	4, (CTR)
+//	BC	4, (CTR)	// TODO - should work
 
 //	LBRA con ',' con ',' rel
 //	{
@@ -451,7 +458,7 @@ label1:
 //		g.Offset = $2;
 //		outcode(int($1), &g, int(REG_R0+$4), &$6);
 //	}
-	BC	3, 4, label1
+//	BC	3, 4, label1 // TODO - should work
 
 //	LBRA con ',' con ',' addr // TODO mystery
 //	{
@@ -471,7 +478,7 @@ label1:
 //		g.Offset = $2;
 //		outcode(int($1), &g, int(REG_R0+$4), &$7);
 //	}
-	BC	3, 3, (LR)
+	BC	3, 3, (LR) // BC $3, R3, LR
 
 //
 // conditional trap // TODO NOT DEFINED
@@ -531,7 +538,7 @@ label1:
 //	{
 //		outcode(int($1), &$2, int($6.Reg), &$4);
 //	}
-	FCMPU	F1, F2, CR0
+//	FCMPU	F1, F2, CR0
 
 //
 // CMP
@@ -552,13 +559,13 @@ label1:
 //	{
 //		outcode(int($1), &$2, int($6.Reg), &$4);
 //	}
-	CMP	R1, R2, CR0
+	CMP	R1, R2, CR0 // CMP R1, CR0, R2
 
 //	LCMP rreg ',' imm ',' creg
 //	{
 //		outcode(int($1), &$2, int($6.Reg), &$4);
 //	}
-	CMP	R1, $4, CR0
+	CMP	R1, $4, CR0 // CMP R1, CR0, $4
 
 //
 // rotate and mask
@@ -567,25 +574,25 @@ label1:
 //	{
 //		outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
 //	}
-	RLDC $4, R1, $5, R2
+	RLDC $4, R1, $16, R2
 
 //	LRLWM  imm ',' rreg ',' mask ',' rreg
 //	{
 //		outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
 //	}
-	RLDC $26, R1, 4, 5, R2
+	RLDC $26, R1, 4, 5, R2 // RLDC $26, R1, $201326592, R2
 
 //	LRLWM  rreg ',' rreg ',' imm ',' rreg
 //	{
 //		outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
 //	}
-	RLDC	R1, R2, $4, R3
+	RLDCL	R1, R2, $7, R3
 
 //	LRLWM  rreg ',' rreg ',' mask ',' rreg
 //	{
 //		outgcode(int($1), &$2, int($4.Reg), &$6, &$8);
 //	}
-	RLWMI	R1, R2, 4, 5, R3
+	RLWMI	R1, R2, 4, 5, R3 // RLWMI	R1, R2, $201326592, R3
 
 //
 // load/store multiple
@@ -594,14 +601,14 @@ label1:
 //	{
 //		outcode(int($1), &$2, 0, &$4);
 //	}
-	MOVMW	foo+0(SB), R2
+//	MOVMW	foo+0(SB), R2 // TODO TLS broke this!
 	MOVMW	4(R1), R2
 
 //	LMOVMW rreg ',' addr
 //	{
 //		outcode(int($1), &$2, 0, &$4);
 //	}
-	MOVMW	R1, foo+0(SB)
+//	MOVMW	R1, foo+0(SB) // TODO TLS broke this!
 	MOVMW	R1, 4(R2)
 
 //
@@ -613,49 +620,49 @@ label1:
 //		outcode(int($1), &$2, 0, &$4);
 //	}
 	LSW	(R1), R2
-	LSW	(R1+R2), R3
+	LSW	(R1+R2), R3 // LSW	(R1)(R2*1), R3
 
 //	LXLD regaddr ',' imm ',' rreg
 //	{
 //		outgcode(int($1), &$2, 0, &$4, &$6);
 //	}
 	LSW	(R1), $1, R2
-	LSW	(R1+R2), $1, R3
+	LSW	(R1+R2), $1, R3 // LSW	(R1)(R2*1), $1, R3
 
 //	LXST rreg ',' regaddr
 //	{
 //		outcode(int($1), &$2, 0, &$4);
 //	}
 	STSW	R1, (R2)
-	STSW	R1, (R2+R3)
+	STSW	R1, (R2+R3) // STSW	R1, (R2)(R3*1)
 
 //	LXST rreg ',' imm ',' regaddr
 //	{
 //		outgcode(int($1), &$2, 0, &$4, &$6);
 //	}
 	STSW	R1, $1, (R2)
-	STSW	R1, $1, (R2+R3)
+	STSW	R1, $1, (R2+R3) // STSW	R1, $1, (R2)(R3*1)
 
 //	LXMV regaddr ',' rreg
 //	{
 //		outcode(int($1), &$2, 0, &$4);
 //	}
 	MOVHBR	(R1), R2
-	MOVHBR	(R1+R2), R3
+	MOVHBR	(R1+R2), R3 // MOVHBR	(R1)(R2*1), R3
 
 //	LXMV rreg ',' regaddr
 //	{
 //		outcode(int($1), &$2, 0, &$4);
 //	}
 	MOVHBR	R1, (R2)
-	MOVHBR	R1, (R2+R3)
+	MOVHBR	R1, (R2+R3) // MOVHBR	R1, (R2)(R3*1)
 
 //	LXOP regaddr
 //	{
 //		outcode(int($1), &$2, 0, &nullgen);
 //	}
 	DCBF	(R1)
-	DCBF	(R1+R2)
+	DCBF	(R1+R2) // DCBF	(R1)(R2*1)
 
 //
 // NOP
@@ -702,12 +709,15 @@ label1:
 //	{
 //		outcode(int($1), &nullgen, 0, &nullgen);
 //	}
+	BEQ	2(PC)
 	RET
 
 // More BR/BL cases, and canonical names JMP, CALL.
 
-	BR	foo(SB)
-	BL	foo(SB)
+	BEQ	2(PC)
+	BR	foo(SB) // JMP foo(SB)
+	BL	foo(SB) //  CALL foo(SB)
+	BEQ	2(PC)
 	JMP	foo(SB)
 	CALL	foo(SB)
 
diff --git a/src/cmd/asm/internal/flags/flags.go b/src/cmd/asm/internal/flags/flags.go
index bf5cb1e..fd42e84 100644
--- a/src/cmd/asm/internal/flags/flags.go
+++ b/src/cmd/asm/internal/flags/flags.go
@@ -20,6 +20,7 @@ var (
 	TrimPath   = flag.String("trimpath", "", "remove prefix from recorded source file paths")
 	Shared     = flag.Bool("shared", false, "generate code that can be linked into a shared library")
 	Dynlink    = flag.Bool("dynlink", false, "support references to Go symbols defined in other shared libraries")
+	AllErrors = flag.Bool("e", false, "no limit on number of errors reported")
 )
 
 var (
@@ -36,6 +37,9 @@ func init() {
 type MultiFlag []string
 
 func (m *MultiFlag) String() string {
+	if len(*m) == 0 {
+		return ""
+	}
 	return fmt.Sprint(*m)
 }
 
diff --git a/src/cmd/asm/internal/lex/input.go b/src/cmd/asm/internal/lex/input.go
index 7e495b8..33b9d8a 100644
--- a/src/cmd/asm/internal/lex/input.go
+++ b/src/cmd/asm/internal/lex/input.go
@@ -63,7 +63,12 @@ func predefine(defines flags.MultiFlag) map[string]*Macro {
 	return macros
 }
 
+var panicOnError bool // For testing.
+
 func (in *Input) Error(args ...interface{}) {
+	if panicOnError {
+		panic(fmt.Errorf("%s:%d: %s", in.File(), in.Line(), fmt.Sprintln(args...)))
+	}
 	fmt.Fprintf(os.Stderr, "%s:%d: %s", in.File(), in.Line(), fmt.Sprintln(args...))
 	os.Exit(1)
 }
@@ -113,6 +118,10 @@ func (in *Input) Next() ScanToken {
 			}
 			fallthrough
 		default:
+			if tok == scanner.EOF && len(in.ifdefStack) > 0 {
+				// We're skipping text but have run out of input with no #endif.
+				in.Error("unclosed #ifdef or #ifndef")
+			}
 			in.beginningOfLine = tok == '\n'
 			if in.enabled() {
 				in.text = in.Stack.Text()
@@ -136,10 +145,11 @@ func (in *Input) hash() bool {
 		in.expectText("expected identifier after '#'")
 	}
 	if !in.enabled() {
-		// Can only start including again if we are at #else or #endif.
+		// Can only start including again if we are at #else or #endif but also
+		// need to keep track of nested #if[n]defs.
 		// We let #line through because it might affect errors.
 		switch in.Stack.Text() {
-		case "else", "endif", "line":
+		case "else", "endif", "ifdef", "ifndef", "line":
 			// Press on.
 		default:
 			return false
@@ -250,6 +260,9 @@ func (in *Input) macroDefinition(name string) ([]string, []Token) {
 	var tokens []Token
 	// Scan to newline. Backslashes escape newlines.
 	for tok != '\n' {
+		if tok == scanner.EOF {
+			in.Error("missing newline in definition for macro:", name)
+		}
 		if tok == '\\' {
 			tok = in.Stack.Next()
 			if tok != '\n' && tok != '\\' {
@@ -360,7 +373,9 @@ func (in *Input) collectArgument(macro *Macro) ([]Token, ScanToken) {
 func (in *Input) ifdef(truth bool) {
 	name := in.macroName()
 	in.expectNewline("#if[n]def")
-	if _, defined := in.macros[name]; !defined {
+	if !in.enabled() {
+		truth = false
+	} else if _, defined := in.macros[name]; !defined {
 		truth = !truth
 	}
 	in.ifdefStack = append(in.ifdefStack, truth)
@@ -372,7 +387,9 @@ func (in *Input) else_() {
 	if len(in.ifdefStack) == 0 {
 		in.Error("unmatched #else")
 	}
-	in.ifdefStack[len(in.ifdefStack)-1] = !in.ifdefStack[len(in.ifdefStack)-1]
+	if len(in.ifdefStack) == 1 || in.ifdefStack[len(in.ifdefStack)-2] {
+		in.ifdefStack[len(in.ifdefStack)-1] = !in.ifdefStack[len(in.ifdefStack)-1]
+	}
 }
 
 // #endif processing.
diff --git a/src/cmd/asm/internal/lex/lex_test.go b/src/cmd/asm/internal/lex/lex_test.go
index f034d69..f606ffe 100644
--- a/src/cmd/asm/internal/lex/lex_test.go
+++ b/src/cmd/asm/internal/lex/lex_test.go
@@ -120,6 +120,141 @@ var lexTests = []lexTest{
 		),
 		"\n.MOVBLZX.(.BP.).(.DX.*.4.).,.R8.\n.\n.MOVBLZX.(.(.8.+.1.).*.4.).(.R12.).,.BX.\n.ADDB.BX.,.DX.\n.MOVB.R8.,.(.8.*.4.).(.R12.).\n.PINSRW.$.0.,.(.BP.).(.R8.*.4.).,.X0.\n",
 	},
+	{
+		"taken #ifdef",
+		lines(
+			"#define A",
+			"#ifdef A",
+			"#define B 1234",
+			"#endif",
+			"B",
+		),
+		"1234.\n",
+	},
+	{
+		"not taken #ifdef",
+		lines(
+			"#ifdef A",
+			"#define B 1234",
+			"#endif",
+			"B",
+		),
+		"B.\n",
+	},
+	{
+		"taken #ifdef with else",
+		lines(
+			"#define A",
+			"#ifdef A",
+			"#define B 1234",
+			"#else",
+			"#define B 5678",
+			"#endif",
+			"B",
+		),
+		"1234.\n",
+	},
+	{
+		"not taken #ifdef with else",
+		lines(
+			"#ifdef A",
+			"#define B 1234",
+			"#else",
+			"#define B 5678",
+			"#endif",
+			"B",
+		),
+		"5678.\n",
+	},
+	{
+		"nested taken/taken #ifdef",
+		lines(
+			"#define A",
+			"#define B",
+			"#ifdef A",
+			"#ifdef B",
+			"#define C 1234",
+			"#else",
+			"#define C 5678",
+			"#endif",
+			"#endif",
+			"C",
+		),
+		"1234.\n",
+	},
+	{
+		"nested taken/not-taken #ifdef",
+		lines(
+			"#define A",
+			"#ifdef A",
+			"#ifdef B",
+			"#define C 1234",
+			"#else",
+			"#define C 5678",
+			"#endif",
+			"#endif",
+			"C",
+		),
+		"5678.\n",
+	},
+	{
+		"nested not-taken/would-be-taken #ifdef",
+		lines(
+			"#define B",
+			"#ifdef A",
+			"#ifdef B",
+			"#define C 1234",
+			"#else",
+			"#define C 5678",
+			"#endif",
+			"#endif",
+			"C",
+		),
+		"C.\n",
+	},
+	{
+		"nested not-taken/not-taken #ifdef",
+		lines(
+			"#ifdef A",
+			"#ifdef B",
+			"#define C 1234",
+			"#else",
+			"#define C 5678",
+			"#endif",
+			"#endif",
+			"C",
+		),
+		"C.\n",
+	},
+	{
+		"nested #define",
+		lines(
+			"#define A #define B THIS",
+			"A",
+			"B",
+		),
+		"THIS.\n",
+	},
+	{
+		"nested #define with args",
+		lines(
+			"#define A #define B(x) x",
+			"A",
+			"B(THIS)",
+		),
+		"THIS.\n",
+	},
+	/* This one fails. See comment in Slice.Col.
+	{
+		"nested #define with args",
+		lines(
+			"#define A #define B (x) x",
+			"A",
+			"B(THIS)",
+		),
+		"x.\n",
+	},
+	*/
 }
 
 func TestLex(t *testing.T) {
@@ -152,3 +287,76 @@ func drain(input *Input) string {
 		buf.WriteString(input.Text())
 	}
 }
+
+type badLexTest struct {
+	input string
+	error string
+}
+
+var badLexTests = []badLexTest{
+	{
+		"3 #define foo bar\n",
+		"'#' must be first item on line",
+	},
+	{
+		"#ifdef foo\nhello",
+		"unclosed #ifdef or #ifndef",
+	},
+	{
+		"#ifndef foo\nhello",
+		"unclosed #ifdef or #ifndef",
+	},
+	{
+		"#ifdef foo\nhello\n#else\nbye",
+		"unclosed #ifdef or #ifndef",
+	},
+	{
+		"#define A() A()\nA()",
+		"recursive macro invocation",
+	},
+	{
+		"#define A a\n#define A a\n",
+		"redefinition of macro",
+	},
+	{
+		"#define A a",
+		"no newline after macro definition",
+	},
+}
+
+func TestBadLex(t *testing.T) {
+	for _, test := range badLexTests {
+		input := NewInput(test.error)
+		input.Push(NewTokenizer(test.error, strings.NewReader(test.input), nil))
+		err := firstError(input)
+		if err == nil {
+			t.Errorf("%s: got no error", test.error)
+			continue
+		}
+		if !strings.Contains(err.Error(), test.error) {
+			t.Errorf("got error %q expected %q", err.Error(), test.error)
+		}
+	}
+}
+
+// firstError returns the first error value triggered by the input.
+func firstError(input *Input) (err error) {
+	panicOnError = true
+	defer func() {
+		panicOnError = false
+		switch e := recover(); e := e.(type) {
+		case nil:
+		case error:
+			err = e
+		default:
+			panic(e)
+		}
+	}()
+
+	for {
+		tok := input.Next()
+		if tok == scanner.EOF {
+			return
+		}
+	}
+}
diff --git a/src/cmd/asm/internal/lex/slice.go b/src/cmd/asm/internal/lex/slice.go
index e94106b..b0d5429 100644
--- a/src/cmd/asm/internal/lex/slice.go
+++ b/src/cmd/asm/internal/lex/slice.go
@@ -44,8 +44,16 @@ func (s *Slice) Line() int {
 }
 
 func (s *Slice) Col() int {
-	// Col is only called when defining a macro, which can't reach here.
-	panic("cannot happen: slice col")
+	// TODO: Col is only called when defining a macro and all it cares about is increasing
+	// position to discover whether there is a blank before the parenthesis.
+	// We only get here if defining a macro inside a macro.
+	// This imperfect implementation means we cannot tell the difference between
+	//	#define A #define B(x) x
+	// and
+	//	#define A #define B (x) x
+	// The first has definition of B has an argument, the second doesn't. Because we let
+	// text/scanner strip the blanks for us, this is extremely rare, hard to fix, and not worth it.
+	return s.pos
 }
 
 func (s *Slice) SetPos(line int, file string) {
diff --git a/src/cmd/asm/main.go b/src/cmd/asm/main.go
index db0e28e..f48050c 100644
--- a/src/cmd/asm/main.go
+++ b/src/cmd/asm/main.go
@@ -47,21 +47,28 @@ func main() {
 	}
 	ctxt.Bso = obj.Binitw(os.Stdout)
 	defer ctxt.Bso.Flush()
-	ctxt.Diag = log.Fatalf
 	output := obj.Binitw(fd)
 	fmt.Fprintf(output, "go object %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion())
 	fmt.Fprintf(output, "!\n")
 
 	lexer := lex.NewLexer(flag.Arg(0), ctxt)
 	parser := asm.NewParser(ctxt, architecture, lexer)
+	diag := false
+	ctxt.DiagFunc = func(format string, args ...interface{}) {
+		diag = true
+		log.Printf(format, args...)
+	}
 	pList := obj.Linknewplist(ctxt)
 	var ok bool
 	pList.Firstpc, ok = parser.Parse()
-	if !ok {
+	if ok {
+		// reports errors to parser.Errorf
+		obj.Writeobjdirect(ctxt, output)
+	}
+	if !ok || diag {
 		log.Printf("asm: assembly of %s failed", flag.Arg(0))
 		os.Remove(*flags.OutputFile)
 		os.Exit(1)
 	}
-	obj.Writeobjdirect(ctxt, output)
 	output.Flush()
 }
diff --git a/src/cmd/cgo/ast.go b/src/cmd/cgo/ast.go
index 8bbd1cc..c3a24c2 100644
--- a/src/cmd/cgo/ast.go
+++ b/src/cmd/cgo/ast.go
@@ -124,7 +124,7 @@ func (f *File) ReadGo(name string) {
 	if f.Ref == nil {
 		f.Ref = make([]*Ref, 0, 8)
 	}
-	f.walk(ast2, "prog", (*File).saveRef)
+	f.walk(ast2, "prog", (*File).saveExprs)
 
 	// Accumulate exported functions.
 	// The comments are only on ast1 but we need to
@@ -163,52 +163,72 @@ func commentText(g *ast.CommentGroup) string {
 	return strings.Join(pieces, "")
 }
 
+// Save various references we are going to need later.
+func (f *File) saveExprs(x interface{}, context string) {
+	switch x := x.(type) {
+	case *ast.Expr:
+		switch (*x).(type) {
+		case *ast.SelectorExpr:
+			f.saveRef(x, context)
+		}
+	case *ast.CallExpr:
+		f.saveCall(x)
+	}
+}
+
 // Save references to C.xxx for later processing.
-func (f *File) saveRef(x interface{}, context string) {
-	n, ok := x.(*ast.Expr)
-	if !ok {
+func (f *File) saveRef(n *ast.Expr, context string) {
+	sel := (*n).(*ast.SelectorExpr)
+	// For now, assume that the only instance of capital C is when
+	// used as the imported package identifier.
+	// The parser should take care of scoping in the future, so
+	// that we will be able to distinguish a "top-level C" from a
+	// local C.
+	if l, ok := sel.X.(*ast.Ident); !ok || l.Name != "C" {
 		return
 	}
-	if sel, ok := (*n).(*ast.SelectorExpr); ok {
-		// For now, assume that the only instance of capital C is
-		// when used as the imported package identifier.
-		// The parser should take care of scoping in the future,
-		// so that we will be able to distinguish a "top-level C"
-		// from a local C.
-		if l, ok := sel.X.(*ast.Ident); ok && l.Name == "C" {
-			if context == "as2" {
-				context = "expr"
-			}
-			if context == "embed-type" {
-				error_(sel.Pos(), "cannot embed C type")
-			}
-			goname := sel.Sel.Name
-			if goname == "errno" {
-				error_(sel.Pos(), "cannot refer to errno directly; see documentation")
-				return
-			}
-			if goname == "_CMalloc" {
-				error_(sel.Pos(), "cannot refer to C._CMalloc; use C.malloc")
-				return
-			}
-			if goname == "malloc" {
-				goname = "_CMalloc"
-			}
-			name := f.Name[goname]
-			if name == nil {
-				name = &Name{
-					Go: goname,
-				}
-				f.Name[goname] = name
-			}
-			f.Ref = append(f.Ref, &Ref{
-				Name:    name,
-				Expr:    n,
-				Context: context,
-			})
-			return
+	if context == "as2" {
+		context = "expr"
+	}
+	if context == "embed-type" {
+		error_(sel.Pos(), "cannot embed C type")
+	}
+	goname := sel.Sel.Name
+	if goname == "errno" {
+		error_(sel.Pos(), "cannot refer to errno directly; see documentation")
+		return
+	}
+	if goname == "_CMalloc" {
+		error_(sel.Pos(), "cannot refer to C._CMalloc; use C.malloc")
+		return
+	}
+	if goname == "malloc" {
+		goname = "_CMalloc"
+	}
+	name := f.Name[goname]
+	if name == nil {
+		name = &Name{
+			Go: goname,
 		}
+		f.Name[goname] = name
+	}
+	f.Ref = append(f.Ref, &Ref{
+		Name:    name,
+		Expr:    n,
+		Context: context,
+	})
+}
+
+// Save calls to C.xxx for later processing.
+func (f *File) saveCall(call *ast.CallExpr) {
+	sel, ok := call.Fun.(*ast.SelectorExpr)
+	if !ok {
+		return
+	}
+	if l, ok := sel.X.(*ast.Ident); !ok || l.Name != "C" {
+		return
 	}
+	f.Calls = append(f.Calls, call)
 }
 
 // If a function should be exported add it to ExpFunc.
diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go
index b2a5428..bd38a5c 100644
--- a/src/cmd/cgo/doc.go
+++ b/src/cmd/cgo/doc.go
@@ -117,17 +117,27 @@ The standard C numeric types are available under the names
 C.char, C.schar (signed char), C.uchar (unsigned char),
 C.short, C.ushort (unsigned short), C.int, C.uint (unsigned int),
 C.long, C.ulong (unsigned long), C.longlong (long long),
-C.ulonglong (unsigned long long), C.float, C.double.
+C.ulonglong (unsigned long long), C.float, C.double,
+C.complexfloat (complex float), and C.complexdouble (complex double).
 The C type void* is represented by Go's unsafe.Pointer.
+The C types __int128_t and __uint128_t are represented by [16]byte.
 
 To access a struct, union, or enum type directly, prefix it with
 struct_, union_, or enum_, as in C.struct_stat.
 
+The size of any C type T is available as C.sizeof_T, as in
+C.sizeof_struct_stat.
+
 As Go doesn't have support for C's union type in the general case,
 C's union types are represented as a Go byte array with the same length.
 
 Go structs cannot embed fields with C types.
 
+Go code can not refer to zero-sized fields that occur at the end of
+non-empty C structs.  To get the address of such a field (which is the
+only operation you can do with a zero-sized field) you must take the
+address of the struct and add the size of the struct.
+
 Cgo translates C types into equivalent unexported Go types.
 Because the translations are unexported, a Go package should not
 expose C types in its exported API: a C type used in one Go package
@@ -188,10 +198,10 @@ by making copies of the data.  In pseudo-Go definitions:
 	// C string to Go string
 	func C.GoString(*C.char) string
 
-	// C string, length to Go string
+	// C data with explicit length to Go string
 	func C.GoStringN(*C.char, C.int) string
 
-	// C pointer, length to Go []byte
+	// C data with explicit length to Go []byte
 	func C.GoBytes(unsafe.Pointer, C.int) []byte
 
 C references to Go
@@ -221,6 +231,55 @@ definitions and declarations, then the two output files will produce
 duplicate symbols and the linker will fail. To avoid this, definitions
 must be placed in preambles in other files, or in C source files.
 
+Passing pointers
+
+Go is a garbage collected language, and the garbage collector needs to
+know the location of every pointer to Go memory.  Because of this,
+there are restrictions on passing pointers between Go and C.
+
+In this section the term Go pointer means a pointer to memory
+allocated by Go (such as by using the & operator or calling the
+predefined new function) and the term C pointer means a pointer to
+memory allocated by C (such as by a call to C.malloc).  Whether a
+pointer is a Go pointer or a C pointer is a dynamic property
+determined by how the memory was allocated; it has nothing to do with
+the type of the pointer.
+
+Go code may pass a Go pointer to C provided the Go memory to which it
+points does not contain any Go pointers.  The C code must preserve
+this property: it must not store any Go pointers in Go memory, even
+temporarily.  When passing a pointer to a field in a struct, the Go
+memory in question is the memory occupied by the field, not the entire
+struct.  When passing a pointer to an element in an array or slice,
+the Go memory in question is the entire array or the entire backing
+array of the slice.
+
+C code may not keep a copy of a Go pointer after the call returns.
+
+A Go function called by C code may not return a Go pointer.  A Go
+function called by C code may take C pointers as arguments, and it may
+store non-pointer or C pointer data through those pointers, but it may
+not store a Go pointer in memory pointed to by a C pointer.  A Go
+function called by C code may take a Go pointer as an argument, but it
+must preserve the property that the Go memory to which it points does
+not contain any Go pointers.
+
+Go code may not store a Go pointer in C memory.  C code may store Go
+pointers in C memory, subject to the rule above: it must stop storing
+the Go pointer when the C function returns.
+
+These rules are checked dynamically at runtime.  The checking is
+controlled by the cgocheck setting of the GODEBUG environment
+variable.  The default setting is GODEBUG=cgocheck=1, which implements
+reasonably cheap dynamic checks.  These checks may be disabled
+entirely using GODEBUG=cgocheck=0.  Complete checking of pointer
+handling, at some cost in run time, is available via GODEBUG=cgocheck=2.
+
+It is possible to defeat this enforcement by using the unsafe package,
+and of course there is nothing stopping the C code from doing anything
+it likes.  However, programs that break these rules are likely to fail
+in unexpected and unpredictable ways.
+
 Using cgo directly
 
 Usage:
@@ -391,17 +450,13 @@ the translation process.
 
 Translating Go
 
-[The rest of this comment refers to 6g, the Go compiler that is part
-of the amd64 port of the gc Go toolchain. Everything here applies to
-another architecture's compilers as well.]
-
 Given the input Go files x.go and y.go, cgo generates these source
 files:
 
-	x.cgo1.go       # for 6g
-	y.cgo1.go       # for 6g
-	_cgo_gotypes.go # for 6g
-	_cgo_import.go  # for 6g (if -dynout _cgo_import.go)
+	x.cgo1.go       # for gc (cmd/compile)
+	y.cgo1.go       # for gc
+	_cgo_gotypes.go # for gc
+	_cgo_import.go  # for gc (if -dynout _cgo_import.go)
 	x.cgo2.c        # for gcc
 	y.cgo2.c        # for gcc
 	_cgo_defun.c    # for gcc (if -gccgo)
@@ -464,7 +519,7 @@ Linking
 
 Once the _cgo_export.c and *.cgo2.c files have been compiled with gcc,
 they need to be linked into the final binary, along with the libraries
-they might depend on (in the case of puts, stdio). 6l has been
+they might depend on (in the case of puts, stdio). cmd/link has been
 extended to understand basic ELF files, but it does not understand ELF
 in the full complexity that modern C libraries embrace, so it cannot
 in general generate direct references to the system libraries.
@@ -495,23 +550,23 @@ _cgo_import.go, which looks like:
 	//go:cgo_import_dynamic _ _ "libc.so.6"
 
 In the end, the compiled Go package, which will eventually be
-presented to 6l as part of a larger program, contains:
+presented to cmd/link as part of a larger program, contains:
 
-	_go_.6        # 6g-compiled object for _cgo_gotypes.go, _cgo_import.go, *.cgo1.go
+	_go_.o        # gc-compiled object for _cgo_gotypes.go, _cgo_import.go, *.cgo1.go
 	_all.o        # gcc-compiled object for _cgo_export.c, *.cgo2.c
 
-The final program will be a dynamic executable, so that 6l can avoid
+The final program will be a dynamic executable, so that cmd/link can avoid
 needing to process arbitrary .o files. It only needs to process the .o
 files generated from C files that cgo writes, and those are much more
 limited in the ELF or other features that they use.
 
-In essence, the _cgo_import.6 file includes the extra linking
-directives that 6l is not sophisticated enough to derive from _all.o
+In essence, the _cgo_import.o file includes the extra linking
+directives that cmd/link is not sophisticated enough to derive from _all.o
 on its own. Similarly, the _all.o uses dynamic references to real
-system object code because 6l is not sophisticated enough to process
+system object code because cmd/link is not sophisticated enough to process
 the real code.
 
-The main benefits of this system are that 6l remains relatively simple
+The main benefits of this system are that cmd/link remains relatively simple
 (it does not need to implement a complete ELF and Mach-O linker) and
 that gcc is not needed after the package is compiled. For example,
 package net uses cgo for access to name resolution functions provided
@@ -540,17 +595,17 @@ system calls.
 
 Internal and External Linking
 
-The text above describes "internal" linking, in which 6l parses and
+The text above describes "internal" linking, in which cmd/link parses and
 links host object files (ELF, Mach-O, PE, and so on) into the final
-executable itself. Keeping 6l simple means we cannot possibly
+executable itself. Keeping cmd/link simple means we cannot possibly
 implement the full semantics of the host linker, so the kinds of
 objects that can be linked directly into the binary is limited (other
 code can only be used as a dynamic library). On the other hand, when
-using internal linking, 6l can generate Go binaries by itself.
+using internal linking, cmd/link can generate Go binaries by itself.
 
 In order to allow linking arbitrary object files without requiring
 dynamic libraries, cgo supports an "external" linking mode too. In
-external linking mode, 6l does not process any host object files.
+external linking mode, cmd/link does not process any host object files.
 Instead, it collects all the Go code and writes a single go.o object
 file containing it. Then it invokes the host linker (usually gcc) to
 combine the go.o object file and any supporting non-Go code into a
@@ -582,8 +637,8 @@ to be made when linking the final binary.
 Linking Directives
 
 In either linking mode, package-specific directives must be passed
-through to 6l. These are communicated by writing //go: directives in a
-Go source file compiled by 6g. The directives are copied into the .6
+through to cmd/link. These are communicated by writing //go: directives in a
+Go source file compiled by gc. The directives are copied into the .o
 object file and then processed by the linker.
 
 The directives are:
@@ -672,7 +727,7 @@ Example
 As a simple example, consider a package that uses cgo to call C.sin.
 The following code will be generated by cgo:
 
-	// compiled by 6g
+	// compiled by gc
 
 	//go:cgo_ldflag "-lm"
 
@@ -708,7 +763,7 @@ Otherwise the link will be an internal one.
 The linking directives are used according to the kind of final link
 used.
 
-In internal mode, 6l itself processes all the host object files, in
+In internal mode, cmd/link itself processes all the host object files, in
 particular foo.cgo2.o. To do so, it uses the cgo_import_dynamic and
 cgo_dynamic_linker directives to learn that the otherwise undefined
 reference to sin in foo.cgo2.o should be rewritten to refer to the
@@ -716,56 +771,56 @@ symbol sin with version GLIBC_2.2.5 from the dynamic library
 "libm.so.6", and the binary should request "/lib/ld-linux.so.2" as its
 runtime dynamic linker.
 
-In external mode, 6l does not process any host object files, in
-particular foo.cgo2.o. It links together the 6g-generated object
+In external mode, cmd/link does not process any host object files, in
+particular foo.cgo2.o. It links together the gc-generated object
 files, along with any other Go code, into a go.o file. While doing
-that, 6l will discover that there is no definition for
-_cgo_gcc_Cfunc_sin, referred to by the 6g-compiled source file. This
-is okay, because 6l also processes the cgo_import_static directive and
+that, cmd/link will discover that there is no definition for
+_cgo_gcc_Cfunc_sin, referred to by the gc-compiled source file. This
+is okay, because cmd/link also processes the cgo_import_static directive and
 knows that _cgo_gcc_Cfunc_sin is expected to be supplied by a host
-object file, so 6l does not treat the missing symbol as an error when
+object file, so cmd/link does not treat the missing symbol as an error when
 creating go.o. Indeed, the definition for _cgo_gcc_Cfunc_sin will be
 provided to the host linker by foo2.cgo.o, which in turn will need the
-symbol 'sin'. 6l also processes the cgo_ldflag directives, so that it
+symbol 'sin'. cmd/link also processes the cgo_ldflag directives, so that it
 knows that the eventual host link command must include the -lm
 argument, so that the host linker will be able to find 'sin' in the
 math library.
 
-6l Command Line Interface
+cmd/link Command Line Interface
 
-The go command and any other Go-aware build systems invoke 6l
-to link a collection of packages into a single binary. By default, 6l will
+The go command and any other Go-aware build systems invoke cmd/link
+to link a collection of packages into a single binary. By default, cmd/link will
 present the same interface it does today:
 
-	6l main.a
+	cmd/link main.a
 
-produces a file named 6.out, even if 6l does so by invoking the host
+produces a file named a.out, even if cmd/link does so by invoking the host
 linker in external linking mode.
 
-By default, 6l will decide the linking mode as follows: if the only
+By default, cmd/link will decide the linking mode as follows: if the only
 packages using cgo are those on a whitelist of standard library
-packages (net, os/user, runtime/cgo), 6l will use internal linking
-mode. Otherwise, there are non-standard cgo packages involved, and 6l
+packages (net, os/user, runtime/cgo), cmd/link will use internal linking
+mode. Otherwise, there are non-standard cgo packages involved, and cmd/link
 will use external linking mode. The first rule means that a build of
 the godoc binary, which uses net but no other cgo, can run without
 needing gcc available. The second rule means that a build of a
 cgo-wrapped library like sqlite3 can generate a standalone executable
 instead of needing to refer to a dynamic library. The specific choice
-can be overridden using a command line flag: 6l -linkmode=internal or
-6l -linkmode=external.
+can be overridden using a command line flag: cmd/link -linkmode=internal or
+cmd/link -linkmode=external.
 
-In an external link, 6l will create a temporary directory, write any
+In an external link, cmd/link will create a temporary directory, write any
 host object files found in package archives to that directory (renamed
 to avoid conflicts), write the go.o file to that directory, and invoke
 the host linker. The default value for the host linker is $CC, split
 into fields, or else "gcc". The specific host linker command line can
-be overridden using command line flags: 6l -extld=clang
+be overridden using command line flags: cmd/link -extld=clang
 -extldflags='-ggdb -O3'.  If any package in a build includes a .cc or
 other file compiled by the C++ compiler, the go tool will use the
 -extld option to set the host linker to the C++ compiler.
 
 These defaults mean that Go-aware build systems can ignore the linking
-changes and keep running plain '6l' and get reasonable results, but
+changes and keep running plain 'cmd/link' and get reasonable results, but
 they can also control the linking details if desired.
 
 */
diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go
index e0b89ec..fb5049c 100644
--- a/src/cmd/cgo/gcc.go
+++ b/src/cmd/cgo/gcc.go
@@ -38,8 +38,8 @@ var nameToC = map[string]string{
 	"ulong":         "unsigned long",
 	"longlong":      "long long",
 	"ulonglong":     "unsigned long long",
-	"complexfloat":  "float complex",
-	"complexdouble": "double complex",
+	"complexfloat":  "float _Complex",
+	"complexdouble": "double _Complex",
 }
 
 // cname returns the C name to use for C.s.
@@ -167,6 +167,7 @@ func (p *Package) Translate(f *File) {
 	if len(needType) > 0 {
 		p.loadDWARF(f, needType)
 	}
+	p.rewriteCalls(f)
 	p.rewriteRef(f)
 }
 
@@ -575,6 +576,331 @@ func (p *Package) mangleName(n *Name) {
 	n.Mangle = prefix + n.Kind + "_" + n.Go
 }
 
+// rewriteCalls rewrites all calls that pass pointers to check that
+// they follow the rules for passing pointers between Go and C.
+func (p *Package) rewriteCalls(f *File) {
+	for _, call := range f.Calls {
+		// This is a call to C.xxx; set goname to "xxx".
+		goname := call.Fun.(*ast.SelectorExpr).Sel.Name
+		if goname == "malloc" {
+			continue
+		}
+		name := f.Name[goname]
+		if name.Kind != "func" {
+			// Probably a type conversion.
+			continue
+		}
+		p.rewriteCall(f, call, name)
+	}
+}
+
+// rewriteCall rewrites one call to add pointer checks.  We replace
+// each pointer argument x with _cgoCheckPointer(x).(T).
+func (p *Package) rewriteCall(f *File, call *ast.CallExpr, name *Name) {
+	for i, param := range name.FuncType.Params {
+		if len(call.Args) <= i {
+			// Avoid a crash; this will be caught when the
+			// generated file is compiled.
+			return
+		}
+
+		// An untyped nil does not need a pointer check, and
+		// when _cgoCheckPointer returns the untyped nil the
+		// type assertion we are going to insert will fail.
+		// Easier to just skip nil arguments.
+		// TODO: Note that this fails if nil is shadowed.
+		if id, ok := call.Args[i].(*ast.Ident); ok && id.Name == "nil" {
+			continue
+		}
+
+		if !p.needsPointerCheck(f, param.Go) {
+			continue
+		}
+
+		c := &ast.CallExpr{
+			Fun: ast.NewIdent("_cgoCheckPointer"),
+			Args: []ast.Expr{
+				call.Args[i],
+			},
+		}
+
+		// Add optional additional arguments for an address
+		// expression.
+		c.Args = p.checkAddrArgs(f, c.Args, call.Args[i])
+
+		// _cgoCheckPointer returns interface{}.
+		// We need to type assert that to the type we want.
+		// If the Go version of this C type uses
+		// unsafe.Pointer, we can't use a type assertion,
+		// because the Go file might not import unsafe.
+		// Instead we use a local variant of _cgoCheckPointer.
+
+		var arg ast.Expr
+		if n := p.unsafeCheckPointerName(param.Go); n != "" {
+			c.Fun = ast.NewIdent(n)
+			arg = c
+		} else {
+			// In order for the type assertion to succeed,
+			// we need it to match the actual type of the
+			// argument.  The only type we have is the
+			// type of the function parameter.  We know
+			// that the argument type must be assignable
+			// to the function parameter type, or the code
+			// would not compile, but there is nothing
+			// requiring that the types be exactly the
+			// same.  Add a type conversion to the
+			// argument so that the type assertion will
+			// succeed.
+			c.Args[0] = &ast.CallExpr{
+				Fun: param.Go,
+				Args: []ast.Expr{
+					c.Args[0],
+				},
+			}
+
+			arg = &ast.TypeAssertExpr{
+				X:    c,
+				Type: param.Go,
+			}
+		}
+
+		call.Args[i] = arg
+	}
+}
+
+// needsPointerCheck returns whether the type t needs a pointer check.
+// This is true if t is a pointer and if the value to which it points
+// might contain a pointer.
+func (p *Package) needsPointerCheck(f *File, t ast.Expr) bool {
+	return p.hasPointer(f, t, true)
+}
+
+// hasPointer is used by needsPointerCheck.  If top is true it returns
+// whether t is or contains a pointer that might point to a pointer.
+// If top is false it returns whether t is or contains a pointer.
+// f may be nil.
+func (p *Package) hasPointer(f *File, t ast.Expr, top bool) bool {
+	switch t := t.(type) {
+	case *ast.ArrayType:
+		if t.Len == nil {
+			if !top {
+				return true
+			}
+			return p.hasPointer(f, t.Elt, false)
+		}
+		return p.hasPointer(f, t.Elt, top)
+	case *ast.StructType:
+		for _, field := range t.Fields.List {
+			if p.hasPointer(f, field.Type, top) {
+				return true
+			}
+		}
+		return false
+	case *ast.StarExpr: // Pointer type.
+		if !top {
+			return true
+		}
+		return p.hasPointer(f, t.X, false)
+	case *ast.FuncType, *ast.InterfaceType, *ast.MapType, *ast.ChanType:
+		return true
+	case *ast.Ident:
+		// TODO: Handle types defined within function.
+		for _, d := range p.Decl {
+			gd, ok := d.(*ast.GenDecl)
+			if !ok || gd.Tok != token.TYPE {
+				continue
+			}
+			for _, spec := range gd.Specs {
+				ts, ok := spec.(*ast.TypeSpec)
+				if !ok {
+					continue
+				}
+				if ts.Name.Name == t.Name {
+					return p.hasPointer(f, ts.Type, top)
+				}
+			}
+		}
+		if def := typedef[t.Name]; def != nil {
+			return p.hasPointer(f, def.Go, top)
+		}
+		if t.Name == "string" {
+			return !top
+		}
+		if t.Name == "error" {
+			return true
+		}
+		if goTypes[t.Name] != nil {
+			return false
+		}
+		// We can't figure out the type.  Conservative
+		// approach is to assume it has a pointer.
+		return true
+	case *ast.SelectorExpr:
+		if l, ok := t.X.(*ast.Ident); !ok || l.Name != "C" {
+			// Type defined in a different package.
+			// Conservative approach is to assume it has a
+			// pointer.
+			return true
+		}
+		if f == nil {
+			// Conservative approach: assume pointer.
+			return true
+		}
+		name := f.Name[t.Sel.Name]
+		if name != nil && name.Kind == "type" && name.Type != nil && name.Type.Go != nil {
+			return p.hasPointer(f, name.Type.Go, top)
+		}
+		// We can't figure out the type.  Conservative
+		// approach is to assume it has a pointer.
+		return true
+	default:
+		error_(t.Pos(), "could not understand type %s", gofmt(t))
+		return true
+	}
+}
+
+// checkAddrArgs tries to add arguments to the call of
+// _cgoCheckPointer when the argument is an address expression.  We
+// pass true to mean that the argument is an address operation of
+// something other than a slice index, which means that it's only
+// necessary to check the specific element pointed to, not the entire
+// object.  This is for &s.f, where f is a field in a struct.  We can
+// pass a slice or array, meaning that we should check the entire
+// slice or array but need not check any other part of the object.
+// This is for &s.a[i], where we need to check all of a.  However, we
+// only pass the slice or array if we can refer to it without side
+// effects.
+func (p *Package) checkAddrArgs(f *File, args []ast.Expr, x ast.Expr) []ast.Expr {
+	// Strip type conversions.
+	for {
+		c, ok := x.(*ast.CallExpr)
+		if !ok || len(c.Args) != 1 || !p.isType(c.Fun) {
+			break
+		}
+		x = c.Args[0]
+	}
+	u, ok := x.(*ast.UnaryExpr)
+	if !ok || u.Op != token.AND {
+		return args
+	}
+	index, ok := u.X.(*ast.IndexExpr)
+	if !ok {
+		// This is the address of something that is not an
+		// index expression.  We only need to examine the
+		// single value to which it points.
+		// TODO: what if true is shadowed?
+		return append(args, ast.NewIdent("true"))
+	}
+	if !p.hasSideEffects(f, index.X) {
+		// Examine the entire slice.
+		return append(args, index.X)
+	}
+	// Treat the pointer as unknown.
+	return args
+}
+
+// hasSideEffects returns whether the expression x has any side
+// effects.  x is an expression, not a statement, so the only side
+// effect is a function call.
+func (p *Package) hasSideEffects(f *File, x ast.Expr) bool {
+	found := false
+	f.walk(x, "expr",
+		func(f *File, x interface{}, context string) {
+			switch x.(type) {
+			case *ast.CallExpr:
+				found = true
+			}
+		})
+	return found
+}
+
+// isType returns whether the expression is definitely a type.
+// This is conservative--it returns false for an unknown identifier.
+func (p *Package) isType(t ast.Expr) bool {
+	switch t := t.(type) {
+	case *ast.SelectorExpr:
+		if t.Sel.Name != "Pointer" {
+			return false
+		}
+		id, ok := t.X.(*ast.Ident)
+		if !ok {
+			return false
+		}
+		return id.Name == "unsafe"
+	case *ast.Ident:
+		// TODO: This ignores shadowing.
+		switch t.Name {
+		case "unsafe.Pointer", "bool", "byte",
+			"complex64", "complex128",
+			"error",
+			"float32", "float64",
+			"int", "int8", "int16", "int32", "int64",
+			"rune", "string",
+			"uint", "uint8", "uint16", "uint32", "uint64", "uintptr":
+
+			return true
+		}
+	case *ast.StarExpr:
+		return p.isType(t.X)
+	case *ast.ArrayType, *ast.StructType, *ast.FuncType, *ast.InterfaceType,
+		*ast.MapType, *ast.ChanType:
+
+		return true
+	}
+	return false
+}
+
+// unsafeCheckPointerName is given the Go version of a C type.  If the
+// type uses unsafe.Pointer, we arrange to build a version of
+// _cgoCheckPointer that returns that type.  This avoids using a type
+// assertion to unsafe.Pointer in our copy of user code.  We return
+// the name of the _cgoCheckPointer function we are going to build, or
+// the empty string if the type does not use unsafe.Pointer.
+func (p *Package) unsafeCheckPointerName(t ast.Expr) string {
+	if !p.hasUnsafePointer(t) {
+		return ""
+	}
+	var buf bytes.Buffer
+	conf.Fprint(&buf, fset, t)
+	s := buf.String()
+	for i, t := range p.CgoChecks {
+		if s == t {
+			return p.unsafeCheckPointerNameIndex(i)
+		}
+	}
+	p.CgoChecks = append(p.CgoChecks, s)
+	return p.unsafeCheckPointerNameIndex(len(p.CgoChecks) - 1)
+}
+
+// hasUnsafePointer returns whether the Go type t uses unsafe.Pointer.
+// t is the Go version of a C type, so we don't need to handle every case.
+// We only care about direct references, not references via typedefs.
+func (p *Package) hasUnsafePointer(t ast.Expr) bool {
+	switch t := t.(type) {
+	case *ast.Ident:
+		// We don't see a SelectorExpr for unsafe.Pointer;
+		// this is created by code in this file.
+		return t.Name == "unsafe.Pointer"
+	case *ast.ArrayType:
+		return p.hasUnsafePointer(t.Elt)
+	case *ast.StructType:
+		for _, f := range t.Fields.List {
+			if p.hasUnsafePointer(f.Type) {
+				return true
+			}
+		}
+	case *ast.StarExpr: // Pointer type.
+		return p.hasUnsafePointer(t.X)
+	}
+	return false
+}
+
+// unsafeCheckPointerNameIndex returns the name to use for a
+// _cgoCheckPointer variant based on the index in the CgoChecks slice.
+func (p *Package) unsafeCheckPointerNameIndex(i int) string {
+	return fmt.Sprintf("_cgoCheckPointer%d", i)
+}
+
 // rewriteRef rewrites all the C.xxx references in f.AST to refer to the
 // Go equivalents, now that we have figured out the meaning of all
 // the xxx.  In *godefs mode, rewriteRef replaces the names
@@ -612,6 +938,10 @@ func (p *Package) rewriteRef(f *File) {
 			if r.Name.Kind != "func" {
 				if r.Name.Kind == "type" {
 					r.Context = "type"
+					if r.Name.Type == nil {
+						error_(r.Pos(), "invalid conversion to C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
+						break
+					}
 					expr = r.Name.Type.Go
 					break
 				}
@@ -663,6 +993,10 @@ func (p *Package) rewriteRef(f *File) {
 				}
 			} else if r.Name.Kind == "type" {
 				// Okay - might be new(T)
+				if r.Name.Type == nil {
+					error_(r.Pos(), "expression C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
+					break
+				}
 				expr = r.Name.Type.Go
 			} else if r.Name.Kind == "var" {
 				expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
@@ -1028,12 +1362,12 @@ var dwarfToName = map[string]string{
 	"long unsigned int":      "ulong",
 	"unsigned int":           "uint",
 	"short unsigned int":     "ushort",
+	"unsigned short":         "ushort", // Used by Clang; issue 13129.
 	"short int":              "short",
 	"long long int":          "longlong",
 	"long long unsigned int": "ulonglong",
 	"signed char":            "schar",
-	"float complex":          "complexfloat",
-	"double complex":         "complexdouble",
+	"unsigned char":          "uchar",
 }
 
 const signedDelta = 64
@@ -1224,6 +1558,11 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
 			t.Go = c.int32
 		case 8:
 			t.Go = c.int64
+		case 16:
+			t.Go = &ast.ArrayType{
+				Len: c.intExpr(t.Size),
+				Elt: c.uint8,
+			}
 		}
 		if t.Align = t.Size; t.Align >= c.ptrSize {
 			t.Align = c.ptrSize
@@ -1381,6 +1720,11 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
 			t.Go = c.uint32
 		case 8:
 			t.Go = c.uint64
+		case 16:
+			t.Go = &ast.ArrayType{
+				Len: c.intExpr(t.Size),
+				Elt: c.uint8,
+			}
 		}
 		if t.Align = t.Size; t.Align >= c.ptrSize {
 			t.Align = c.ptrSize
@@ -1393,7 +1737,7 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
 	}
 
 	switch dtype.(type) {
-	case *dwarf.AddrType, *dwarf.BoolType, *dwarf.CharType, *dwarf.IntType, *dwarf.FloatType, *dwarf.UcharType, *dwarf.UintType:
+	case *dwarf.AddrType, *dwarf.BoolType, *dwarf.CharType, *dwarf.ComplexType, *dwarf.IntType, *dwarf.FloatType, *dwarf.UcharType, *dwarf.UintType:
 		s := dtype.Common().Name
 		if s != "" {
 			if ss, ok := dwarfToName[s]; ok {
diff --git a/src/cmd/cgo/godefs.go b/src/cmd/cgo/godefs.go
index 1b0ece2..aff616e 100644
--- a/src/cmd/cgo/godefs.go
+++ b/src/cmd/cgo/godefs.go
@@ -11,6 +11,7 @@ import (
 	"go/printer"
 	"go/token"
 	"os"
+	"path/filepath"
 	"strings"
 )
 
@@ -19,7 +20,7 @@ func (p *Package) godefs(f *File, srcfile string) string {
 	var buf bytes.Buffer
 
 	fmt.Fprintf(&buf, "// Created by cgo -godefs - DO NOT EDIT\n")
-	fmt.Fprintf(&buf, "// %s\n", strings.Join(os.Args, " "))
+	fmt.Fprintf(&buf, "// %s %s\n", filepath.Base(os.Args[0]), strings.Join(os.Args[1:], " "))
 	fmt.Fprintf(&buf, "\n")
 
 	override := make(map[string]string)
diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go
index 02d297c..0906ceb 100644
--- a/src/cmd/cgo/main.go
+++ b/src/cmd/cgo/main.go
@@ -42,6 +42,7 @@ type Package struct {
 	GoFiles     []string // list of Go files
 	GccFiles    []string // list of gcc output files
 	Preamble    string   // collected preamble for _cgo_export.h
+	CgoChecks   []string // see unsafeCheckPointerName
 }
 
 // A File collects information about a single Go input file.
@@ -51,6 +52,7 @@ type File struct {
 	Package  string              // Package name
 	Preamble string              // C preamble (doc comment on import "C")
 	Ref      []*Ref              // all references to C.xxx in AST
+	Calls    []*ast.CallExpr     // all calls to C.xxx in AST
 	ExpFunc  []*ExpFunc          // exported functions for this file
 	Name     map[string]*Name    // map from Go name to Name
 }
@@ -132,25 +134,29 @@ func usage() {
 }
 
 var ptrSizeMap = map[string]int64{
-	"386":     4,
-	"amd64":   8,
-	"arm":     4,
-	"arm64":   8,
-	"ppc64":   8,
-	"ppc64le": 8,
-	"s390":    4,
-	"s390x":   8,
+	"386":      4,
+	"amd64":    8,
+	"arm":      4,
+	"arm64":    8,
+	"mips64":   8,
+	"mips64le": 8,
+	"ppc64":    8,
+	"ppc64le":  8,
+	"s390":     4,
+	"s390x":    8,
 }
 
 var intSizeMap = map[string]int64{
-	"386":     4,
-	"amd64":   8,
-	"arm":     4,
-	"arm64":   8,
-	"ppc64":   8,
-	"ppc64le": 8,
-	"s390":    4,
-	"s390x":   4,
+	"386":      4,
+	"amd64":    8,
+	"arm":      4,
+	"arm64":    8,
+	"mips64":   8,
+	"mips64le": 8,
+	"ppc64":    8,
+	"ppc64le":  8,
+	"s390":     4,
+	"s390x":    4,
 }
 
 var cPrefix string
@@ -279,11 +285,7 @@ func main() {
 		if nerrors > 0 {
 			os.Exit(2)
 		}
-		pkg := f.Package
-		if dir := os.Getenv("CGOPKGPATH"); dir != "" {
-			pkg = filepath.Join(dir, pkg)
-		}
-		p.PackagePath = pkg
+		p.PackagePath = f.Package
 		p.Record(f)
 		if *godefs {
 			os.Stdout.WriteString(p.godefs(f, input))
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index 90a7441..ca0ec0a 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -103,11 +103,19 @@ func (p *Package) writeDefs() {
 	}
 
 	if *gccgo {
+		fmt.Fprint(fgo2, gccgoGoProlog)
 		fmt.Fprint(fc, p.cPrologGccgo())
 	} else {
 		fmt.Fprint(fgo2, goProlog)
 	}
 
+	for i, t := range p.CgoChecks {
+		n := p.unsafeCheckPointerNameIndex(i)
+		fmt.Fprintf(fgo2, "\nfunc %s(p interface{}, args ...interface{}) %s {\n", n, t)
+		fmt.Fprintf(fgo2, "\treturn _cgoCheckPointer(p, args...).(%s)\n", t)
+		fmt.Fprintf(fgo2, "}\n")
+	}
+
 	gccgoSymbolPrefix := p.gccgoSymbolPrefix()
 
 	cVars := make(map[string]bool)
@@ -693,7 +701,7 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
 		}
 		fntype := fn.Type
 		forFieldList(fntype.Params,
-			func(i int, atype ast.Expr) {
+			func(i int, aname string, atype ast.Expr) {
 				t := p.cgoType(atype)
 				if off%t.Align != 0 {
 					pad := t.Align - off%t.Align
@@ -711,7 +719,7 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
 			npad++
 		}
 		forFieldList(fntype.Results,
-			func(i int, atype ast.Expr) {
+			func(i int, aname string, atype ast.Expr) {
 				t := p.cgoType(atype)
 				if off%t.Align != 0 {
 					pad := t.Align - off%t.Align
@@ -744,8 +752,12 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
 			fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName)
 			fmt.Fprintf(fgcch, "struct %s_return {\n", exp.ExpName)
 			forFieldList(fntype.Results,
-				func(i int, atype ast.Expr) {
-					fmt.Fprintf(fgcch, "\t%s r%d;\n", p.cgoType(atype).C, i)
+				func(i int, aname string, atype ast.Expr) {
+					fmt.Fprintf(fgcch, "\t%s r%d;", p.cgoType(atype).C, i)
+					if len(aname) > 0 {
+						fmt.Fprintf(fgcch, " /* %s */", aname)
+					}
+					fmt.Fprint(fgcch, "\n")
 				})
 			fmt.Fprintf(fgcch, "};\n")
 			gccResult = "struct " + exp.ExpName + "_return"
@@ -758,7 +770,7 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
 			s += " recv"
 		}
 		forFieldList(fntype.Params,
-			func(i int, atype ast.Expr) {
+			func(i int, aname string, atype ast.Expr) {
 				if i > 0 || fn.Recv != nil {
 					s += ", "
 				}
@@ -783,7 +795,7 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
 			fmt.Fprintf(fgcc, "\ta.recv = recv;\n")
 		}
 		forFieldList(fntype.Params,
-			func(i int, atype ast.Expr) {
+			func(i int, aname string, atype ast.Expr) {
 				fmt.Fprintf(fgcc, "\ta.p%d = p%d;\n", i, i)
 			})
 		fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &a, %d);\n", cPrefix, exp.ExpName, off)
@@ -792,7 +804,7 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
 				fmt.Fprintf(fgcc, "\treturn a.r0;\n")
 			} else {
 				forFieldList(fntype.Results,
-					func(i int, atype ast.Expr) {
+					func(i int, aname string, atype ast.Expr) {
 						fmt.Fprintf(fgcc, "\tr.r%d = a.r%d;\n", i, i)
 					})
 				fmt.Fprintf(fgcc, "\treturn r;\n")
@@ -800,17 +812,18 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
 		}
 		fmt.Fprintf(fgcc, "}\n")
 
-		// Build the wrapper function compiled by gc.
-		goname := exp.Func.Name.Name
+		// Build the wrapper function compiled by cmd/compile.
+		goname := "_cgoexpwrap" + cPrefix + "_"
 		if fn.Recv != nil {
-			goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname
+			goname += fn.Recv.List[0].Names[0].Name + "_"
 		}
-		fmt.Fprintf(fgo2, "//go:cgo_export_dynamic %s\n", goname)
+		goname += exp.Func.Name.Name
+		fmt.Fprintf(fgo2, "//go:cgo_export_dynamic %s\n", exp.ExpName)
 		fmt.Fprintf(fgo2, "//go:linkname _cgoexp%s_%s _cgoexp%s_%s\n", cPrefix, exp.ExpName, cPrefix, exp.ExpName)
 		fmt.Fprintf(fgo2, "//go:cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
 		fmt.Fprintf(fgo2, "//go:nosplit\n") // no split stack, so no use of m or g
 		fmt.Fprintf(fgo2, "//go:norace\n")  // must not have race detector calls inserted
-		fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a unsafe.Pointer, n int32) {", cPrefix, exp.ExpName)
+		fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a unsafe.Pointer, n int32) {\n", cPrefix, exp.ExpName)
 		fmt.Fprintf(fgo2, "\tfn := %s\n", goname)
 		// The indirect here is converting from a Go function pointer to a C function pointer.
 		fmt.Fprintf(fgo2, "\t_cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n));\n")
@@ -818,44 +831,75 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
 
 		fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName)
 
-		// Calling a function with a receiver from C requires
-		// a Go wrapper function.
+		// This code uses printer.Fprint, not conf.Fprint,
+		// because we don't want //line comments in the middle
+		// of the function types.
+		fmt.Fprintf(fgo2, "\n")
+		fmt.Fprintf(fgo2, "func %s(", goname)
+		comma := false
 		if fn.Recv != nil {
-			fmt.Fprintf(fgo2, "func %s(recv ", goname)
-			conf.Fprint(fgo2, fset, fn.Recv.List[0].Type)
-			forFieldList(fntype.Params,
-				func(i int, atype ast.Expr) {
-					fmt.Fprintf(fgo2, ", p%d ", i)
-					conf.Fprint(fgo2, fset, atype)
-				})
-			fmt.Fprintf(fgo2, ")")
-			if gccResult != "void" {
-				fmt.Fprint(fgo2, " (")
-				forFieldList(fntype.Results,
-					func(i int, atype ast.Expr) {
-						if i > 0 {
-							fmt.Fprint(fgo2, ", ")
-						}
-						conf.Fprint(fgo2, fset, atype)
-					})
-				fmt.Fprint(fgo2, ")")
-			}
-			fmt.Fprint(fgo2, " {\n")
-			fmt.Fprint(fgo2, "\t")
-			if gccResult != "void" {
-				fmt.Fprint(fgo2, "return ")
-			}
-			fmt.Fprintf(fgo2, "recv.%s(", exp.Func.Name)
-			forFieldList(fntype.Params,
-				func(i int, atype ast.Expr) {
+			fmt.Fprintf(fgo2, "recv ")
+			printer.Fprint(fgo2, fset, fn.Recv.List[0].Type)
+			comma = true
+		}
+		forFieldList(fntype.Params,
+			func(i int, aname string, atype ast.Expr) {
+				if comma {
+					fmt.Fprintf(fgo2, ", ")
+				}
+				fmt.Fprintf(fgo2, "p%d ", i)
+				printer.Fprint(fgo2, fset, atype)
+				comma = true
+			})
+		fmt.Fprintf(fgo2, ")")
+		if gccResult != "void" {
+			fmt.Fprint(fgo2, " (")
+			forFieldList(fntype.Results,
+				func(i int, aname string, atype ast.Expr) {
 					if i > 0 {
 						fmt.Fprint(fgo2, ", ")
 					}
-					fmt.Fprintf(fgo2, "p%d", i)
+					fmt.Fprintf(fgo2, "r%d ", i)
+					printer.Fprint(fgo2, fset, atype)
 				})
-			fmt.Fprint(fgo2, ")\n")
-			fmt.Fprint(fgo2, "}\n")
+			fmt.Fprint(fgo2, ")")
 		}
+		fmt.Fprint(fgo2, " {\n")
+		if gccResult == "void" {
+			fmt.Fprint(fgo2, "\t")
+		} else {
+			// Verify that any results don't contain any
+			// Go pointers.
+			addedDefer := false
+			forFieldList(fntype.Results,
+				func(i int, aname string, atype ast.Expr) {
+					if !p.hasPointer(nil, atype, false) {
+						return
+					}
+					if !addedDefer {
+						fmt.Fprint(fgo2, "\tdefer func() {\n")
+						addedDefer = true
+					}
+					fmt.Fprintf(fgo2, "\t\t_cgoCheckResult(r%d)\n", i)
+				})
+			if addedDefer {
+				fmt.Fprint(fgo2, "\t}()\n")
+			}
+			fmt.Fprint(fgo2, "\treturn ")
+		}
+		if fn.Recv != nil {
+			fmt.Fprintf(fgo2, "recv.")
+		}
+		fmt.Fprintf(fgo2, "%s(", exp.Func.Name)
+		forFieldList(fntype.Params,
+			func(i int, aname string, atype ast.Expr) {
+				if i > 0 {
+					fmt.Fprint(fgo2, ", ")
+				}
+				fmt.Fprintf(fgo2, "p%d", i)
+			})
+		fmt.Fprint(fgo2, ")\n")
+		fmt.Fprint(fgo2, "}\n")
 	}
 
 	fmt.Fprintf(fgcch, "%s", gccExportHeaderEpilog)
@@ -879,13 +923,13 @@ func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
 		cdeclBuf := new(bytes.Buffer)
 		resultCount := 0
 		forFieldList(fntype.Results,
-			func(i int, atype ast.Expr) { resultCount++ })
+			func(i int, aname string, atype ast.Expr) { resultCount++ })
 		switch resultCount {
 		case 0:
 			fmt.Fprintf(cdeclBuf, "void")
 		case 1:
 			forFieldList(fntype.Results,
-				func(i int, atype ast.Expr) {
+				func(i int, aname string, atype ast.Expr) {
 					t := p.cgoType(atype)
 					fmt.Fprintf(cdeclBuf, "%s", t.C)
 				})
@@ -894,9 +938,13 @@ func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
 			fmt.Fprintf(fgcch, "\n/* Return type for %s */\n", exp.ExpName)
 			fmt.Fprintf(fgcch, "struct %s_result {\n", exp.ExpName)
 			forFieldList(fntype.Results,
-				func(i int, atype ast.Expr) {
+				func(i int, aname string, atype ast.Expr) {
 					t := p.cgoType(atype)
-					fmt.Fprintf(fgcch, "\t%s r%d;\n", t.C, i)
+					fmt.Fprintf(fgcch, "\t%s r%d;", t.C, i)
+					if len(aname) > 0 {
+						fmt.Fprintf(fgcch, " /* %s */", aname)
+					}
+					fmt.Fprint(fgcch, "\n")
 				})
 			fmt.Fprintf(fgcch, "};\n")
 			fmt.Fprintf(cdeclBuf, "struct %s_result", exp.ExpName)
@@ -911,7 +959,7 @@ func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
 		}
 		// Function parameters.
 		forFieldList(fntype.Params,
-			func(i int, atype ast.Expr) {
+			func(i int, aname string, atype ast.Expr) {
 				if i > 0 || fn.Recv != nil {
 					fmt.Fprintf(cdeclBuf, ", ")
 				}
@@ -925,23 +973,15 @@ func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
 			fmt.Fprintf(fgcch, "\n%s", exp.Doc)
 		}
 
+		fmt.Fprintf(fgcch, "extern %s %s %s;\n", cRet, exp.ExpName, cParams)
+
 		// We need to use a name that will be exported by the
 		// Go code; otherwise gccgo will make it static and we
 		// will not be able to link against it from the C
 		// code.
 		goName := "Cgoexp_" + exp.ExpName
-		fmt.Fprintf(fgcch, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, goName)
-		fmt.Fprint(fgcch, "\n")
-
-		// Use a #define so that the C code that includes
-		// cgo_export.h will be able to refer to the Go
-		// function using the expected name.
-		fmt.Fprintf(fgcch, "#define %s %s\n", exp.ExpName, goName)
-
-		// Use a #undef in _cgo_export.c so that we ignore the
-		// #define from cgo_export.h, since here we are
-		// defining the real function.
-		fmt.Fprintf(fgcc, "#undef %s\n", exp.ExpName)
+		fmt.Fprintf(fgcc, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, goName)
+		fmt.Fprint(fgcc, "\n")
 
 		fmt.Fprint(fgcc, "\n")
 		fmt.Fprintf(fgcc, "%s %s %s {\n", cRet, exp.ExpName, cParams)
@@ -956,7 +996,7 @@ func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
 			fmt.Fprint(fgcc, "recv")
 		}
 		forFieldList(fntype.Params,
-			func(i int, atype ast.Expr) {
+			func(i int, aname string, atype ast.Expr) {
 				if i > 0 || fn.Recv != nil {
 					fmt.Fprintf(fgcc, ", ")
 				}
@@ -982,7 +1022,7 @@ func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
 			printer.Fprint(fgo2, fset, fn.Recv.List[0].Type)
 		}
 		forFieldList(fntype.Params,
-			func(i int, atype ast.Expr) {
+			func(i int, aname string, atype ast.Expr) {
 				if i > 0 || fn.Recv != nil {
 					fmt.Fprintf(fgo2, ", ")
 				}
@@ -993,7 +1033,7 @@ func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
 		if resultCount > 0 {
 			fmt.Fprintf(fgo2, " (")
 			forFieldList(fntype.Results,
-				func(i int, atype ast.Expr) {
+				func(i int, aname string, atype ast.Expr) {
 					if i > 0 {
 						fmt.Fprint(fgo2, ", ")
 					}
@@ -1013,7 +1053,7 @@ func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
 		}
 		fmt.Fprintf(fgo2, "%s(", exp.Func.Name)
 		forFieldList(fntype.Params,
-			func(i int, atype ast.Expr) {
+			func(i int, aname string, atype ast.Expr) {
 				if i > 0 {
 					fmt.Fprint(fgo2, ", ")
 				}
@@ -1071,19 +1111,19 @@ func (p *Package) gccgoSymbolPrefix() string {
 }
 
 // Call a function for each entry in an ast.FieldList, passing the
-// index into the list and the type.
-func forFieldList(fl *ast.FieldList, fn func(int, ast.Expr)) {
+// index into the list, the name if any, and the type.
+func forFieldList(fl *ast.FieldList, fn func(int, string, ast.Expr)) {
 	if fl == nil {
 		return
 	}
 	i := 0
 	for _, r := range fl.List {
 		if r.Names == nil {
-			fn(i, r.Type)
+			fn(i, "", r.Type)
 			i++
 		} else {
-			for range r.Names {
-				fn(i, r.Type)
+			for _, n := range r.Names {
+				fn(i, n.Name, r.Type)
 				i++
 			}
 		}
@@ -1193,9 +1233,11 @@ func (p *Package) cgoType(e ast.Expr) *Type {
 }
 
 const gccProlog = `
-// Usual nonsense: if x and y are not equal, the type will be invalid
-// (have a negative array count) and an inscrutable error will come
-// out of the compiler and hopefully mention "name".
+/*
+  If x and y are not equal, the type will be invalid
+  (have a negative array count) and an inscrutable error will come
+  out of the compiler and hopefully mention "name".
+*/
 #define __cgo_compile_assert_eq(x, y, name) typedef char name[(x-y)*(x-y)*-2+1];
 
 // Check at compile time that the sizes we use match our expectations.
@@ -1239,6 +1281,18 @@ func _cgo_runtime_cmalloc(uintptr) unsafe.Pointer
 
 //go:linkname _cgo_runtime_cgocallback runtime.cgocallback
 func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr)
+
+//go:linkname _cgoCheckPointer runtime.cgoCheckPointer
+func _cgoCheckPointer(interface{}, ...interface{}) interface{}
+
+//go:linkname _cgoCheckResult runtime.cgoCheckResult
+func _cgoCheckResult(interface{})
+`
+
+const gccgoGoProlog = `
+func _cgoCheckPointer(interface{}, ...interface{}) interface{}
+
+func _cgoCheckResult(interface{})
 `
 
 const goStringDef = `
@@ -1293,7 +1347,8 @@ var builtinDefs = map[string]string{
 }
 
 func (p *Package) cPrologGccgo() string {
-	return strings.Replace(cPrologGccgo, "PREFIX", cPrefix, -1)
+	return strings.Replace(strings.Replace(cPrologGccgo, "PREFIX", cPrefix, -1),
+		"GCCGOSYMBOLPREF", p.gccgoSymbolPrefix(), -1)
 }
 
 const cPrologGccgo = `
@@ -1348,6 +1403,39 @@ void *_cgoPREFIX_Cfunc__CMalloc(size_t n) {
                 runtime_throw("runtime: C malloc failed");
         return p;
 }
+
+struct __go_type_descriptor;
+typedef struct __go_empty_interface {
+	const struct __go_type_descriptor *__type_descriptor;
+	void *__object;
+} Eface;
+
+extern Eface runtimeCgoCheckPointer(Eface, Slice)
+	__asm__("runtime.cgoCheckPointer")
+	__attribute__((weak));
+
+extern Eface localCgoCheckPointer(Eface, Slice)
+	__asm__("GCCGOSYMBOLPREF._cgoCheckPointer");
+
+Eface localCgoCheckPointer(Eface ptr, Slice args) {
+	if(runtimeCgoCheckPointer) {
+		return runtimeCgoCheckPointer(ptr, args);
+	}
+	return ptr;
+}
+
+extern void runtimeCgoCheckResult(Eface)
+	__asm__("runtime.cgoCheckResult")
+	__attribute__((weak));
+
+extern void localCgoCheckResult(Eface)
+	__asm__("GCCGOSYMBOLPREF._cgoCheckResult");
+
+void localCgoCheckResult(Eface val) {
+	if(runtimeCgoCheckResult) {
+		runtimeCgoCheckResult(val);
+	}
+}
 `
 
 func (p *Package) gccExportHeaderProlog() string {
@@ -1373,14 +1461,16 @@ typedef GoUintGOINTBITS GoUint;
 typedef __SIZE_TYPE__ GoUintptr;
 typedef float GoFloat32;
 typedef double GoFloat64;
-typedef __complex float GoComplex64;
-typedef __complex double GoComplex128;
+typedef float _Complex GoComplex64;
+typedef double _Complex GoComplex128;
 
-// static assertion to make sure the file is being used on architecture
-// at least with matching size of GoInt.
+/*
+  static assertion to make sure the file is being used on architecture
+  at least with matching size of GoInt.
+*/
 typedef char _check_for_GOINTBITS_bit_pointer_matching_GoInt[sizeof(void*)==GOINTBITS/8 ? 1:-1];
 
-typedef struct { char *p; GoInt n; } GoString;
+typedef struct { const char *p; GoInt n; } GoString;
 typedef void *GoMap;
 typedef void *GoChan;
 typedef struct { void *t; void *v; } GoInterface;
diff --git a/src/cmd/compile/doc.go b/src/cmd/compile/doc.go
index e362657..2b45e5b 100644
--- a/src/cmd/compile/doc.go
+++ b/src/cmd/compile/doc.go
@@ -66,6 +66,8 @@ Flags:
 		Write memory profile for the compilation to file.
 	-memprofilerate rate
 		Set runtime.MemProfileRate for the compilation to rate.
+	-msan
+		Insert calls to C/C++ memory sanitizer.
 	-nolocalimports
 		Disallow local (relative) imports.
 	-o file
@@ -77,6 +79,8 @@ Flags:
 		Write a package (archive) file rather than an object file
 	-race
 		Compile with race detector enabled.
+	-trimpath prefix
+		Remove prefix from recorded source file paths.
 	-u
 		Disallow importing packages not marked as safe; implies -nolocalimports.
 
@@ -107,7 +111,7 @@ The //line directive is an historical special case; all other directives are of
 The //go:noescape directive specifies that the next declaration in the file, which
 must be a func without a body (meaning that it has an implementation not written
 in Go) does not allow any of the pointers passed as arguments to escape into the
-heap or into the values returned from the function. This information can be used as
+heap or into the values returned from the function. This information can be used
 during the compiler's escape analysis of Go code calling the function.
 
 	//go:nosplit
diff --git a/src/cmd/compile/internal/amd64/cgen.go b/src/cmd/compile/internal/amd64/cgen.go
index 71f8f88..4b00003 100644
--- a/src/cmd/compile/internal/amd64/cgen.go
+++ b/src/cmd/compile/internal/amd64/cgen.go
@@ -80,17 +80,27 @@ func blockcopy(n, ns *gc.Node, osrc, odst, w int64) {
 		gins(x86.ACLD, nil, nil)
 	} else {
 		// normal direction
-		if q > 128 || (gc.Nacl && q >= 4) {
+		if q > 128 || (gc.Nacl && q >= 4) || (obj.Getgoos() == "plan9" && q >= 4) {
 			gconreg(movptr, q, x86.REG_CX)
 			gins(x86.AREP, nil, nil)   // repeat
 			gins(x86.AMOVSQ, nil, nil) // MOVQ *(SI)+,*(DI)+
 		} else if q >= 4 {
+			var oldx0 gc.Node
+			var x0 gc.Node
+			savex(x86.REG_X0, &x0, &oldx0, nil, gc.Types[gc.TFLOAT64])
+
 			p := gins(obj.ADUFFCOPY, nil, nil)
 			p.To.Type = obj.TYPE_ADDR
 			p.To.Sym = gc.Linksym(gc.Pkglookup("duffcopy", gc.Runtimepkg))
 
-			// 14 and 128 = magic constants: see ../../runtime/asm_amd64.s
-			p.To.Offset = 14 * (128 - q)
+			// 64 blocks taking 14 bytes each
+			// see ../../../../runtime/mkduff.go
+			p.To.Offset = 14 * (64 - q/2)
+			restx(&x0, &oldx0)
+
+			if q%2 != 0 {
+				gins(x86.AMOVSQ, nil, nil) // MOVQ *(SI)+,*(DI)+
+			}
 		} else if !gc.Nacl && c == 0 {
 			// We don't need the MOVSQ side-effect of updating SI and DI,
 			// and issuing a sequence of MOVQs directly is faster.
diff --git a/src/cmd/compile/internal/amd64/galign.go b/src/cmd/compile/internal/amd64/galign.go
index 79bf94a..9837ea6 100644
--- a/src/cmd/compile/internal/amd64/galign.go
+++ b/src/cmd/compile/internal/amd64/galign.go
@@ -39,9 +39,9 @@ var (
  * int, uint, and uintptr
  */
 var typedefs = []gc.Typedef{
-	gc.Typedef{"int", gc.TINT, gc.TINT64},
-	gc.Typedef{"uint", gc.TUINT, gc.TUINT64},
-	gc.Typedef{"uintptr", gc.TUINTPTR, gc.TUINT64},
+	{"int", gc.TINT, gc.TINT64},
+	{"uint", gc.TUINT, gc.TUINT64},
+	{"uintptr", gc.TUINTPTR, gc.TUINT64},
 }
 
 func betypeinit() {
diff --git a/src/cmd/compile/internal/amd64/ggen.go b/src/cmd/compile/internal/amd64/ggen.go
index 65cf694..84c3d5d 100644
--- a/src/cmd/compile/internal/amd64/ggen.go
+++ b/src/cmd/compile/internal/amd64/ggen.go
@@ -28,6 +28,7 @@ func defframe(ptxt *obj.Prog) {
 	hi := int64(0)
 	lo := hi
 	ax := uint32(0)
+	x0 := uint32(0)
 
 	// iterate through declarations - they are sorted in decreasing xoffset order.
 	for l := gc.Curfn.Func.Dcl; l != nil; l = l.Next {
@@ -36,10 +37,10 @@ func defframe(ptxt *obj.Prog) {
 			continue
 		}
 		if n.Class != gc.PAUTO {
-			gc.Fatal("needzero class %d", n.Class)
+			gc.Fatalf("needzero class %d", n.Class)
 		}
 		if n.Type.Width%int64(gc.Widthptr) != 0 || n.Xoffset%int64(gc.Widthptr) != 0 || n.Type.Width == 0 {
-			gc.Fatal("var %v has size %d offset %d", gc.Nconv(n, obj.FmtLong), int(n.Type.Width), int(n.Xoffset))
+			gc.Fatalf("var %v has size %d offset %d", gc.Nconv(n, obj.FmtLong), int(n.Type.Width), int(n.Xoffset))
 		}
 
 		if lo != hi && n.Xoffset+n.Type.Width >= lo-int64(2*gc.Widthreg) {
@@ -50,7 +51,7 @@ func defframe(ptxt *obj.Prog) {
 		}
 
 		// zero old range
-		p = zerorange(p, int64(frame), lo, hi, &ax)
+		p = zerorange(p, int64(frame), lo, hi, &ax, &x0)
 
 		// set new range
 		hi = n.Xoffset + n.Type.Width
@@ -59,88 +60,104 @@ func defframe(ptxt *obj.Prog) {
 	}
 
 	// zero final range
-	zerorange(p, int64(frame), lo, hi, &ax)
+	zerorange(p, int64(frame), lo, hi, &ax, &x0)
 }
 
-// DUFFZERO consists of repeated blocks of 4 MOVs + ADD,
-// with 4 STOSQs at the very end.
-// The trailing STOSQs prevent the need for a DI preadjustment
-// for small numbers of words to clear.
+// DUFFZERO consists of repeated blocks of 4 MOVUPSs + ADD,
 // See runtime/mkduff.go.
 const (
-	dzBlocks    = 31 // number of MOV/ADD blocks
+	dzBlocks    = 16 // number of MOV/ADD blocks
 	dzBlockLen  = 4  // number of clears per block
 	dzBlockSize = 19 // size of instructions in a single block
 	dzMovSize   = 4  // size of single MOV instruction w/ offset
 	dzAddSize   = 4  // size of single ADD instruction
-	dzDIStep    = 8  // number of bytes cleared by each MOV instruction
+	dzClearStep = 16 // number of bytes cleared by each MOV instruction
 
-	dzTailLen  = 4 // number of final STOSQ instructions
-	dzTailSize = 2 // size of single STOSQ instruction
-
-	dzSize = dzBlocks*dzBlockSize + dzTailLen*dzTailSize // total size of DUFFZERO routine
+	dzClearLen = dzClearStep * dzBlockLen // bytes cleared by one block
+	dzSize     = dzBlocks * dzBlockSize
 )
 
-// duffzeroDI returns the pre-adjustment to DI for a call to DUFFZERO.
-// q is the number of words to zero.
-func dzDI(q int64) int64 {
-	if q < dzTailLen {
-		return 0
-	}
-	q -= dzTailLen
-	if q%dzBlockLen == 0 {
-		return 0
-	}
-	return -dzDIStep * (dzBlockLen - q%dzBlockLen)
-}
-
 // dzOff returns the offset for a jump into DUFFZERO.
-// q is the number of words to zero.
-func dzOff(q int64) int64 {
+// b is the number of bytes to zero.
+func dzOff(b int64) int64 {
 	off := int64(dzSize)
-	if q < dzTailLen {
-		return off - q*dzTailSize
-	}
-	off -= dzTailLen * dzTailSize
-	q -= dzTailLen
-	blocks, steps := q/dzBlockLen, q%dzBlockLen
-	off -= dzBlockSize * blocks
-	if steps > 0 {
-		off -= dzAddSize + dzMovSize*steps
+	off -= b / dzClearLen * dzBlockSize
+	tailLen := b % dzClearLen
+	if tailLen >= dzClearStep {
+		off -= dzAddSize + dzMovSize*(tailLen/dzClearStep)
 	}
 	return off
 }
 
-func zerorange(p *obj.Prog, frame int64, lo int64, hi int64, ax *uint32) *obj.Prog {
+// duffzeroDI returns the pre-adjustment to DI for a call to DUFFZERO.
+// b is the number of bytes to zero.
+func dzDI(b int64) int64 {
+	tailLen := b % dzClearLen
+	if tailLen < dzClearStep {
+		return 0
+	}
+	tailSteps := tailLen / dzClearStep
+	return -dzClearStep * (dzBlockLen - tailSteps)
+}
+
+func zerorange(p *obj.Prog, frame int64, lo int64, hi int64, ax *uint32, x0 *uint32) *obj.Prog {
 	cnt := hi - lo
 	if cnt == 0 {
 		return p
 	}
-	if *ax == 0 {
-		p = appendpp(p, x86.AMOVQ, obj.TYPE_CONST, 0, 0, obj.TYPE_REG, x86.REG_AX, 0)
-		*ax = 1
-	}
 
 	if cnt%int64(gc.Widthreg) != 0 {
 		// should only happen with nacl
 		if cnt%int64(gc.Widthptr) != 0 {
-			gc.Fatal("zerorange count not a multiple of widthptr %d", cnt)
+			gc.Fatalf("zerorange count not a multiple of widthptr %d", cnt)
+		}
+		if *ax == 0 {
+			p = appendpp(p, x86.AMOVQ, obj.TYPE_CONST, 0, 0, obj.TYPE_REG, x86.REG_AX, 0)
+			*ax = 1
 		}
 		p = appendpp(p, x86.AMOVL, obj.TYPE_REG, x86.REG_AX, 0, obj.TYPE_MEM, x86.REG_SP, frame+lo)
 		lo += int64(gc.Widthptr)
 		cnt -= int64(gc.Widthptr)
 	}
 
-	if cnt <= int64(4*gc.Widthreg) {
-		for i := int64(0); i < cnt; i += int64(gc.Widthreg) {
-			p = appendpp(p, x86.AMOVQ, obj.TYPE_REG, x86.REG_AX, 0, obj.TYPE_MEM, x86.REG_SP, frame+lo+i)
+	if cnt == 8 {
+		if *ax == 0 {
+			p = appendpp(p, x86.AMOVQ, obj.TYPE_CONST, 0, 0, obj.TYPE_REG, x86.REG_AX, 0)
+			*ax = 1
+		}
+		p = appendpp(p, x86.AMOVQ, obj.TYPE_REG, x86.REG_AX, 0, obj.TYPE_MEM, x86.REG_SP, frame+lo)
+	} else if cnt <= int64(8*gc.Widthreg) {
+		if *x0 == 0 {
+			p = appendpp(p, x86.AXORPS, obj.TYPE_REG, x86.REG_X0, 0, obj.TYPE_REG, x86.REG_X0, 0)
+			*x0 = 1
+		}
+
+		for i := int64(0); i < cnt/16; i++ {
+			p = appendpp(p, x86.AMOVUPS, obj.TYPE_REG, x86.REG_X0, 0, obj.TYPE_MEM, x86.REG_SP, frame+lo+i*16)
+		}
+
+		if cnt%16 != 0 {
+			p = appendpp(p, x86.AMOVUPS, obj.TYPE_REG, x86.REG_X0, 0, obj.TYPE_MEM, x86.REG_SP, frame+lo+cnt-int64(16))
 		}
 	} else if !gc.Nacl && (cnt <= int64(128*gc.Widthreg)) {
-		q := cnt / int64(gc.Widthreg)
-		p = appendpp(p, leaptr, obj.TYPE_MEM, x86.REG_SP, frame+lo+dzDI(q), obj.TYPE_REG, x86.REG_DI, 0)
-		p = appendpp(p, obj.ADUFFZERO, obj.TYPE_NONE, 0, 0, obj.TYPE_ADDR, 0, dzOff(q))
+		if *x0 == 0 {
+			p = appendpp(p, x86.AXORPS, obj.TYPE_REG, x86.REG_X0, 0, obj.TYPE_REG, x86.REG_X0, 0)
+			*x0 = 1
+		}
+
+		p = appendpp(p, leaptr, obj.TYPE_MEM, x86.REG_SP, frame+lo+dzDI(cnt), obj.TYPE_REG, x86.REG_DI, 0)
+		p = appendpp(p, obj.ADUFFZERO, obj.TYPE_NONE, 0, 0, obj.TYPE_ADDR, 0, dzOff(cnt))
 		p.To.Sym = gc.Linksym(gc.Pkglookup("duffzero", gc.Runtimepkg))
+
+		if cnt%16 != 0 {
+			p = appendpp(p, x86.AMOVUPS, obj.TYPE_REG, x86.REG_X0, 0, obj.TYPE_MEM, x86.REG_DI, -int64(8))
+		}
 	} else {
+		if *ax == 0 {
+			p = appendpp(p, x86.AMOVQ, obj.TYPE_CONST, 0, 0, obj.TYPE_REG, x86.REG_AX, 0)
+			*ax = 1
+		}
+
 		p = appendpp(p, x86.AMOVQ, obj.TYPE_CONST, 0, cnt/int64(gc.Widthreg), obj.TYPE_REG, x86.REG_CX, 0)
 		p = appendpp(p, leaptr, obj.TYPE_MEM, x86.REG_SP, frame+lo, obj.TYPE_REG, x86.REG_DI, 0)
 		p = appendpp(p, x86.AREP, obj.TYPE_NONE, 0, 0, obj.TYPE_NONE, 0, 0)
@@ -175,7 +192,7 @@ var panicdiv *gc.Node
  *	res = nl % nr
  * according to op.
  */
-func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+func dodiv(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	// Have to be careful about handling
 	// most negative int divided by -1 correctly.
 	// The hardware will trap.
@@ -187,13 +204,13 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	t := nl.Type
 
 	t0 := t
-	check := 0
+	check := false
 	if gc.Issigned[t.Etype] {
-		check = 1
+		check = true
 		if gc.Isconst(nl, gc.CTINT) && nl.Int() != -(1<<uint64(t.Width*8-1)) {
-			check = 0
+			check = false
 		} else if gc.Isconst(nr, gc.CTINT) && nr.Int() != -1 {
-			check = 0
+			check = false
 		}
 	}
 
@@ -203,7 +220,7 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 		} else {
 			t = gc.Types[gc.TUINT32]
 		}
-		check = 0
+		check = false
 	}
 
 	a := optoas(op, t)
@@ -252,7 +269,7 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	}
 
 	var p2 *obj.Prog
-	if check != 0 {
+	if check {
 		gc.Nodconst(&n4, t, -1)
 		gins(optoas(gc.OCMP, t), &n3, &n4)
 		p1 := gc.Gbranch(optoas(gc.ONE, t), nil, +1)
@@ -289,7 +306,7 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 		gmove(&dx, res)
 	}
 	restx(&dx, &olddx)
-	if check != 0 {
+	if check {
 		gc.Patch(p2, gc.Pc)
 	}
 	restx(&ax, &oldax)
@@ -318,7 +335,8 @@ func savex(dr int, x *gc.Node, oldx *gc.Node, res *gc.Node, t *gc.Type) {
 		x.Type = gc.Types[gc.TINT64]
 		gmove(x, oldx)
 		x.Type = t
-		oldx.Etype = r // squirrel away old r value
+		// TODO(marvin): Fix Node.EType type union.
+		oldx.Etype = gc.EType(r) // squirrel away old r value
 		gc.SetReg(dr, 1)
 	}
 }
@@ -340,33 +358,32 @@ func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	t := nl.Type
 	a := optoas(gc.OHMUL, t)
 	if nl.Ullman < nr.Ullman {
-		tmp := nl
-		nl = nr
-		nr = tmp
+		nl, nr = nr, nl
 	}
 
 	var n1 gc.Node
 	gc.Cgenr(nl, &n1, res)
 	var n2 gc.Node
 	gc.Cgenr(nr, &n2, nil)
-	var ax gc.Node
-	gc.Nodreg(&ax, t, x86.REG_AX)
+	var ax, oldax, dx, olddx gc.Node
+	savex(x86.REG_AX, &ax, &oldax, res, gc.Types[gc.TUINT64])
+	savex(x86.REG_DX, &dx, &olddx, res, gc.Types[gc.TUINT64])
 	gmove(&n1, &ax)
 	gins(a, &n2, nil)
 	gc.Regfree(&n2)
 	gc.Regfree(&n1)
 
-	var dx gc.Node
 	if t.Width == 1 {
 		// byte multiply behaves differently.
-		gc.Nodreg(&ax, t, x86.REG_AH)
-
-		gc.Nodreg(&dx, t, x86.REG_DX)
-		gmove(&ax, &dx)
+		var byteAH, byteDX gc.Node
+		gc.Nodreg(&byteAH, t, x86.REG_AH)
+		gc.Nodreg(&byteDX, t, x86.REG_DX)
+		gmove(&byteAH, &byteDX)
 	}
-
-	gc.Nodreg(&dx, t, x86.REG_DX)
 	gmove(&dx, res)
+
+	restx(&ax, &oldax)
+	restx(&dx, &olddx)
 }
 
 /*
@@ -374,7 +391,7 @@ func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
  *	res = nl << nr
  *	res = nl >> nr
  */
-func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+func cgen_shift(op gc.Op, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	a := optoas(op, nl.Type)
 
 	if nr.Op == gc.OLITERAL {
@@ -493,16 +510,14 @@ func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
  * there is no 2-operand byte multiply instruction so
  * we do a full-width multiplication and truncate afterwards.
  */
-func cgen_bmul(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) bool {
+func cgen_bmul(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) bool {
 	if optoas(op, nl.Type) != x86.AIMULB {
 		return false
 	}
 
 	// largest ullman on left.
 	if nl.Ullman < nr.Ullman {
-		tmp := nl
-		nl = nr
-		nr = tmp
+		nl, nr = nr, nl
 	}
 
 	// generate operands in "8-bit" registers.
@@ -541,116 +556,150 @@ func clearfat(nl *gc.Node) {
 		gc.Dump("\nclearfat", nl)
 	}
 
-	w := nl.Type.Width
-
 	// Avoid taking the address for simple enough types.
 	if gc.Componentgen(nil, nl) {
 		return
 	}
 
-	c := w % 8 // bytes
-	q := w / 8 // quads
+	w := nl.Type.Width
 
-	if q < 4 {
-		// Write sequence of MOV 0, off(base) instead of using STOSQ.
-		// The hope is that although the code will be slightly longer,
-		// the MOVs will have no dependencies and pipeline better
-		// than the unrolled STOSQ loop.
-		// NOTE: Must use agen, not igen, so that optimizer sees address
-		// being taken. We are not writing on field boundaries.
+	if w > 1024 || (gc.Nacl && w >= 64) {
+		var oldn1 gc.Node
 		var n1 gc.Node
-		gc.Agenr(nl, &n1, nil)
-
-		n1.Op = gc.OINDREG
-		var z gc.Node
-		gc.Nodconst(&z, gc.Types[gc.TUINT64], 0)
-		for {
-			tmp14 := q
-			q--
-			if tmp14 <= 0 {
-				break
-			}
-			n1.Type = z.Type
-			gins(x86.AMOVQ, &z, &n1)
-			n1.Xoffset += 8
-		}
+		savex(x86.REG_DI, &n1, &oldn1, nil, gc.Types[gc.Tptr])
+		gc.Agen(nl, &n1)
 
-		if c >= 4 {
-			gc.Nodconst(&z, gc.Types[gc.TUINT32], 0)
-			n1.Type = z.Type
-			gins(x86.AMOVL, &z, &n1)
-			n1.Xoffset += 4
-			c -= 4
-		}
+		var ax gc.Node
+		var oldax gc.Node
+		savex(x86.REG_AX, &ax, &oldax, nil, gc.Types[gc.Tptr])
+		gconreg(x86.AMOVL, 0, x86.REG_AX)
+		gconreg(movptr, w/8, x86.REG_CX)
 
-		gc.Nodconst(&z, gc.Types[gc.TUINT8], 0)
-		for {
-			tmp15 := c
-			c--
-			if tmp15 <= 0 {
-				break
-			}
-			n1.Type = z.Type
-			gins(x86.AMOVB, &z, &n1)
-			n1.Xoffset++
+		gins(x86.AREP, nil, nil)   // repeat
+		gins(x86.ASTOSQ, nil, nil) // STOQ AL,*(DI)+
+
+		if w%8 != 0 {
+			n1.Op = gc.OINDREG
+			clearfat_tail(&n1, w%8)
 		}
 
-		gc.Regfree(&n1)
+		restx(&n1, &oldn1)
+		restx(&ax, &oldax)
 		return
 	}
 
-	var oldn1 gc.Node
-	var n1 gc.Node
-	savex(x86.REG_DI, &n1, &oldn1, nil, gc.Types[gc.Tptr])
-	gc.Agen(nl, &n1)
+	if w >= 64 {
+		var oldn1 gc.Node
+		var n1 gc.Node
+		savex(x86.REG_DI, &n1, &oldn1, nil, gc.Types[gc.Tptr])
+		gc.Agen(nl, &n1)
 
-	var ax gc.Node
-	var oldax gc.Node
-	savex(x86.REG_AX, &ax, &oldax, nil, gc.Types[gc.Tptr])
-	gconreg(x86.AMOVL, 0, x86.REG_AX)
+		var vec_zero gc.Node
+		var old_x0 gc.Node
+		savex(x86.REG_X0, &vec_zero, &old_x0, nil, gc.Types[gc.TFLOAT64])
+		gins(x86.AXORPS, &vec_zero, &vec_zero)
 
-	if q > 128 || gc.Nacl {
-		gconreg(movptr, q, x86.REG_CX)
-		gins(x86.AREP, nil, nil)   // repeat
-		gins(x86.ASTOSQ, nil, nil) // STOQ AL,*(DI)+
-	} else {
-		if di := dzDI(q); di != 0 {
+		if di := dzDI(w); di != 0 {
 			gconreg(addptr, di, x86.REG_DI)
 		}
 		p := gins(obj.ADUFFZERO, nil, nil)
 		p.To.Type = obj.TYPE_ADDR
 		p.To.Sym = gc.Linksym(gc.Pkglookup("duffzero", gc.Runtimepkg))
-		p.To.Offset = dzOff(q)
-	}
-
-	z := ax
-	di := n1
-	if w >= 8 && c >= 4 {
-		di.Op = gc.OINDREG
-		z.Type = gc.Types[gc.TINT64]
-		di.Type = z.Type
-		p := gins(x86.AMOVQ, &z, &di)
-		p.To.Scale = 1
-		p.To.Offset = c - 8
-	} else if c >= 4 {
-		di.Op = gc.OINDREG
-		z.Type = gc.Types[gc.TINT32]
-		di.Type = z.Type
-		gins(x86.AMOVL, &z, &di)
-		if c > 4 {
-			p := gins(x86.AMOVL, &z, &di)
-			p.To.Scale = 1
-			p.To.Offset = c - 4
+		p.To.Offset = dzOff(w)
+
+		if w%16 != 0 {
+			n1.Op = gc.OINDREG
+			n1.Xoffset -= 16 - w%16
+			gins(x86.AMOVUPS, &vec_zero, &n1)
 		}
-	} else {
-		for c > 0 {
-			gins(x86.ASTOSB, nil, nil) // STOB AL,*(DI)+
-			c--
+
+		restx(&vec_zero, &old_x0)
+		restx(&n1, &oldn1)
+		return
+	}
+
+	// NOTE: Must use agen, not igen, so that optimizer sees address
+	// being taken. We are not writing on field boundaries.
+	var n1 gc.Node
+	gc.Agenr(nl, &n1, nil)
+	n1.Op = gc.OINDREG
+
+	clearfat_tail(&n1, w)
+
+	gc.Regfree(&n1)
+}
+
+func clearfat_tail(n1 *gc.Node, b int64) {
+	if b >= 16 {
+		var vec_zero gc.Node
+		gc.Regalloc(&vec_zero, gc.Types[gc.TFLOAT64], nil)
+		gins(x86.AXORPS, &vec_zero, &vec_zero)
+
+		for b >= 16 {
+			gins(x86.AMOVUPS, &vec_zero, n1)
+			n1.Xoffset += 16
+			b -= 16
 		}
+
+		// MOVUPS X0, off(base) is a few bytes shorter than MOV 0, off(base)
+		if b != 0 {
+			n1.Xoffset -= 16 - b
+			gins(x86.AMOVUPS, &vec_zero, n1)
+		}
+
+		gc.Regfree(&vec_zero)
+		return
+	}
+
+	// Write sequence of MOV 0, off(base) instead of using STOSQ.
+	// The hope is that although the code will be slightly longer,
+	// the MOVs will have no dependencies and pipeline better
+	// than the unrolled STOSQ loop.
+	var z gc.Node
+	gc.Nodconst(&z, gc.Types[gc.TUINT64], 0)
+	if b >= 8 {
+		n1.Type = z.Type
+		gins(x86.AMOVQ, &z, n1)
+		n1.Xoffset += 8
+		b -= 8
+
+		if b != 0 {
+			n1.Xoffset -= 8 - b
+			gins(x86.AMOVQ, &z, n1)
+		}
+		return
+	}
+
+	if b >= 4 {
+		gc.Nodconst(&z, gc.Types[gc.TUINT32], 0)
+		n1.Type = z.Type
+		gins(x86.AMOVL, &z, n1)
+		n1.Xoffset += 4
+		b -= 4
+
+		if b != 0 {
+			n1.Xoffset -= 4 - b
+			gins(x86.AMOVL, &z, n1)
+		}
+		return
+	}
+
+	if b >= 2 {
+		gc.Nodconst(&z, gc.Types[gc.TUINT16], 0)
+		n1.Type = z.Type
+		gins(x86.AMOVW, &z, n1)
+		n1.Xoffset += 2
+		b -= 2
+	}
+
+	gc.Nodconst(&z, gc.Types[gc.TUINT8], 0)
+	for b > 0 {
+		n1.Type = z.Type
+		gins(x86.AMOVB, &z, n1)
+		n1.Xoffset++
+		b--
 	}
 
-	restx(&n1, &oldn1)
-	restx(&ax, &oldax)
 }
 
 // Called after regopt and peep have run.
diff --git a/src/cmd/compile/internal/amd64/gsubr.go b/src/cmd/compile/internal/amd64/gsubr.go
index a8e4170..003b0ad 100644
--- a/src/cmd/compile/internal/amd64/gsubr.go
+++ b/src/cmd/compile/internal/amd64/gsubr.go
@@ -100,7 +100,7 @@ func ginscon(as int, c int64, n2 *gc.Node) {
 	gins(as, &n1, n2)
 }
 
-func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+func ginscmp(op gc.Op, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
 	if gc.Isint[t.Etype] && n1.Op == gc.OLITERAL && gc.Smallintconst(n1) && n2.Op != gc.OLITERAL {
 		// Reverse comparison to place constant last.
 		op = gc.Brrev(op)
@@ -108,7 +108,15 @@ func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
 	}
 	// General case.
 	var r1, r2, g1, g2 gc.Node
-	if n1.Op == gc.ONAME && n1.Class&gc.PHEAP == 0 || n1.Op == gc.OINDREG {
+
+	// A special case to make write barriers more efficient.
+	// Comparing the first field of a named struct can be done directly.
+	base := n1
+	if n1.Op == gc.ODOT && n1.Left.Type.Etype == gc.TSTRUCT && n1.Left.Type.Type.Sym == n1.Right.Sym {
+		base = n1.Left
+	}
+
+	if base.Op == gc.ONAME && base.Class&gc.PHEAP == 0 || n1.Op == gc.OINDREG {
 		r1 = *n1
 	} else {
 		gc.Regalloc(&r1, t, n1)
@@ -221,7 +229,7 @@ func gmove(f *gc.Node, t *gc.Node) {
 
 	switch uint32(ft)<<16 | uint32(tt) {
 	default:
-		gc.Fatal("gmove %v -> %v", gc.Tconv(f.Type, obj.FmtLong), gc.Tconv(t.Type, obj.FmtLong))
+		gc.Fatalf("gmove %v -> %v", gc.Tconv(f.Type, obj.FmtLong), gc.Tconv(t.Type, obj.FmtLong))
 
 		/*
 		 * integer copy and truncate
@@ -621,7 +629,7 @@ func gins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
 
 	case x86.ALEAQ:
 		if f != nil && gc.Isconst(f, gc.CTNIL) {
-			gc.Fatal("gins LEAQ nil %v", f.Type)
+			gc.Fatalf("gins LEAQ nil %v", f.Type)
 		}
 	}
 
@@ -651,11 +659,11 @@ func gins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
 	if w != 0 && ((f != nil && p.From.Width < int64(w)) || (t != nil && p.To.Width > int64(w))) {
 		gc.Dump("f", f)
 		gc.Dump("t", t)
-		gc.Fatal("bad width: %v (%d, %d)\n", p, p.From.Width, p.To.Width)
+		gc.Fatalf("bad width: %v (%d, %d)\n", p, p.From.Width, p.To.Width)
 	}
 
 	if p.To.Type == obj.TYPE_ADDR && w > 0 {
-		gc.Fatal("bad use of addr: %v", p)
+		gc.Fatalf("bad use of addr: %v", p)
 	}
 
 	return p
@@ -673,514 +681,547 @@ func ginsnop() {
 /*
  * return Axxx for Oxxx on type t.
  */
-func optoas(op int, t *gc.Type) int {
+func optoas(op gc.Op, t *gc.Type) int {
 	if t == nil {
-		gc.Fatal("optoas: t is nil")
+		gc.Fatalf("optoas: t is nil")
 	}
 
+	// avoid constant conversions in switches below
+	const (
+		OMINUS_  = uint32(gc.OMINUS) << 16
+		OLSH_    = uint32(gc.OLSH) << 16
+		ORSH_    = uint32(gc.ORSH) << 16
+		OADD_    = uint32(gc.OADD) << 16
+		OSUB_    = uint32(gc.OSUB) << 16
+		OMUL_    = uint32(gc.OMUL) << 16
+		ODIV_    = uint32(gc.ODIV) << 16
+		OMOD_    = uint32(gc.OMOD) << 16
+		OOR_     = uint32(gc.OOR) << 16
+		OAND_    = uint32(gc.OAND) << 16
+		OXOR_    = uint32(gc.OXOR) << 16
+		OEQ_     = uint32(gc.OEQ) << 16
+		ONE_     = uint32(gc.ONE) << 16
+		OLT_     = uint32(gc.OLT) << 16
+		OLE_     = uint32(gc.OLE) << 16
+		OGE_     = uint32(gc.OGE) << 16
+		OGT_     = uint32(gc.OGT) << 16
+		OCMP_    = uint32(gc.OCMP) << 16
+		OPS_     = uint32(gc.OPS) << 16
+		OPC_     = uint32(gc.OPC) << 16
+		OAS_     = uint32(gc.OAS) << 16
+		OHMUL_   = uint32(gc.OHMUL) << 16
+		OSQRT_   = uint32(gc.OSQRT) << 16
+		OADDR_   = uint32(gc.OADDR) << 16
+		OINC_    = uint32(gc.OINC) << 16
+		ODEC_    = uint32(gc.ODEC) << 16
+		OLROT_   = uint32(gc.OLROT) << 16
+		ORROTC_  = uint32(gc.ORROTC) << 16
+		OEXTEND_ = uint32(gc.OEXTEND) << 16
+	)
+
 	a := obj.AXXX
 	switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) {
 	default:
-		gc.Fatal("optoas: no entry %v-%v", gc.Oconv(int(op), 0), t)
+		gc.Fatalf("optoas: no entry %v-%v", gc.Oconv(int(op), 0), t)
 
-	case gc.OADDR<<16 | gc.TPTR32:
+	case OADDR_ | gc.TPTR32:
 		a = x86.ALEAL
 
-	case gc.OADDR<<16 | gc.TPTR64:
+	case OADDR_ | gc.TPTR64:
 		a = x86.ALEAQ
 
-	case gc.OEQ<<16 | gc.TBOOL,
-		gc.OEQ<<16 | gc.TINT8,
-		gc.OEQ<<16 | gc.TUINT8,
-		gc.OEQ<<16 | gc.TINT16,
-		gc.OEQ<<16 | gc.TUINT16,
-		gc.OEQ<<16 | gc.TINT32,
-		gc.OEQ<<16 | gc.TUINT32,
-		gc.OEQ<<16 | gc.TINT64,
-		gc.OEQ<<16 | gc.TUINT64,
-		gc.OEQ<<16 | gc.TPTR32,
-		gc.OEQ<<16 | gc.TPTR64,
-		gc.OEQ<<16 | gc.TFLOAT32,
-		gc.OEQ<<16 | gc.TFLOAT64:
+	case OEQ_ | gc.TBOOL,
+		OEQ_ | gc.TINT8,
+		OEQ_ | gc.TUINT8,
+		OEQ_ | gc.TINT16,
+		OEQ_ | gc.TUINT16,
+		OEQ_ | gc.TINT32,
+		OEQ_ | gc.TUINT32,
+		OEQ_ | gc.TINT64,
+		OEQ_ | gc.TUINT64,
+		OEQ_ | gc.TPTR32,
+		OEQ_ | gc.TPTR64,
+		OEQ_ | gc.TFLOAT32,
+		OEQ_ | gc.TFLOAT64:
 		a = x86.AJEQ
 
-	case gc.ONE<<16 | gc.TBOOL,
-		gc.ONE<<16 | gc.TINT8,
-		gc.ONE<<16 | gc.TUINT8,
-		gc.ONE<<16 | gc.TINT16,
-		gc.ONE<<16 | gc.TUINT16,
-		gc.ONE<<16 | gc.TINT32,
-		gc.ONE<<16 | gc.TUINT32,
-		gc.ONE<<16 | gc.TINT64,
-		gc.ONE<<16 | gc.TUINT64,
-		gc.ONE<<16 | gc.TPTR32,
-		gc.ONE<<16 | gc.TPTR64,
-		gc.ONE<<16 | gc.TFLOAT32,
-		gc.ONE<<16 | gc.TFLOAT64:
+	case ONE_ | gc.TBOOL,
+		ONE_ | gc.TINT8,
+		ONE_ | gc.TUINT8,
+		ONE_ | gc.TINT16,
+		ONE_ | gc.TUINT16,
+		ONE_ | gc.TINT32,
+		ONE_ | gc.TUINT32,
+		ONE_ | gc.TINT64,
+		ONE_ | gc.TUINT64,
+		ONE_ | gc.TPTR32,
+		ONE_ | gc.TPTR64,
+		ONE_ | gc.TFLOAT32,
+		ONE_ | gc.TFLOAT64:
 		a = x86.AJNE
 
-	case gc.OPS<<16 | gc.TBOOL,
-		gc.OPS<<16 | gc.TINT8,
-		gc.OPS<<16 | gc.TUINT8,
-		gc.OPS<<16 | gc.TINT16,
-		gc.OPS<<16 | gc.TUINT16,
-		gc.OPS<<16 | gc.TINT32,
-		gc.OPS<<16 | gc.TUINT32,
-		gc.OPS<<16 | gc.TINT64,
-		gc.OPS<<16 | gc.TUINT64,
-		gc.OPS<<16 | gc.TPTR32,
-		gc.OPS<<16 | gc.TPTR64,
-		gc.OPS<<16 | gc.TFLOAT32,
-		gc.OPS<<16 | gc.TFLOAT64:
+	case OPS_ | gc.TBOOL,
+		OPS_ | gc.TINT8,
+		OPS_ | gc.TUINT8,
+		OPS_ | gc.TINT16,
+		OPS_ | gc.TUINT16,
+		OPS_ | gc.TINT32,
+		OPS_ | gc.TUINT32,
+		OPS_ | gc.TINT64,
+		OPS_ | gc.TUINT64,
+		OPS_ | gc.TPTR32,
+		OPS_ | gc.TPTR64,
+		OPS_ | gc.TFLOAT32,
+		OPS_ | gc.TFLOAT64:
 		a = x86.AJPS
 
-	case gc.OPC<<16 | gc.TBOOL,
-		gc.OPC<<16 | gc.TINT8,
-		gc.OPC<<16 | gc.TUINT8,
-		gc.OPC<<16 | gc.TINT16,
-		gc.OPC<<16 | gc.TUINT16,
-		gc.OPC<<16 | gc.TINT32,
-		gc.OPC<<16 | gc.TUINT32,
-		gc.OPC<<16 | gc.TINT64,
-		gc.OPC<<16 | gc.TUINT64,
-		gc.OPC<<16 | gc.TPTR32,
-		gc.OPC<<16 | gc.TPTR64,
-		gc.OPC<<16 | gc.TFLOAT32,
-		gc.OPC<<16 | gc.TFLOAT64:
+	case OPC_ | gc.TBOOL,
+		OPC_ | gc.TINT8,
+		OPC_ | gc.TUINT8,
+		OPC_ | gc.TINT16,
+		OPC_ | gc.TUINT16,
+		OPC_ | gc.TINT32,
+		OPC_ | gc.TUINT32,
+		OPC_ | gc.TINT64,
+		OPC_ | gc.TUINT64,
+		OPC_ | gc.TPTR32,
+		OPC_ | gc.TPTR64,
+		OPC_ | gc.TFLOAT32,
+		OPC_ | gc.TFLOAT64:
 		a = x86.AJPC
 
-	case gc.OLT<<16 | gc.TINT8,
-		gc.OLT<<16 | gc.TINT16,
-		gc.OLT<<16 | gc.TINT32,
-		gc.OLT<<16 | gc.TINT64:
+	case OLT_ | gc.TINT8,
+		OLT_ | gc.TINT16,
+		OLT_ | gc.TINT32,
+		OLT_ | gc.TINT64:
 		a = x86.AJLT
 
-	case gc.OLT<<16 | gc.TUINT8,
-		gc.OLT<<16 | gc.TUINT16,
-		gc.OLT<<16 | gc.TUINT32,
-		gc.OLT<<16 | gc.TUINT64:
+	case OLT_ | gc.TUINT8,
+		OLT_ | gc.TUINT16,
+		OLT_ | gc.TUINT32,
+		OLT_ | gc.TUINT64:
 		a = x86.AJCS
 
-	case gc.OLE<<16 | gc.TINT8,
-		gc.OLE<<16 | gc.TINT16,
-		gc.OLE<<16 | gc.TINT32,
-		gc.OLE<<16 | gc.TINT64:
+	case OLE_ | gc.TINT8,
+		OLE_ | gc.TINT16,
+		OLE_ | gc.TINT32,
+		OLE_ | gc.TINT64:
 		a = x86.AJLE
 
-	case gc.OLE<<16 | gc.TUINT8,
-		gc.OLE<<16 | gc.TUINT16,
-		gc.OLE<<16 | gc.TUINT32,
-		gc.OLE<<16 | gc.TUINT64:
+	case OLE_ | gc.TUINT8,
+		OLE_ | gc.TUINT16,
+		OLE_ | gc.TUINT32,
+		OLE_ | gc.TUINT64:
 		a = x86.AJLS
 
-	case gc.OGT<<16 | gc.TINT8,
-		gc.OGT<<16 | gc.TINT16,
-		gc.OGT<<16 | gc.TINT32,
-		gc.OGT<<16 | gc.TINT64:
+	case OGT_ | gc.TINT8,
+		OGT_ | gc.TINT16,
+		OGT_ | gc.TINT32,
+		OGT_ | gc.TINT64:
 		a = x86.AJGT
 
-	case gc.OGT<<16 | gc.TUINT8,
-		gc.OGT<<16 | gc.TUINT16,
-		gc.OGT<<16 | gc.TUINT32,
-		gc.OGT<<16 | gc.TUINT64,
-		gc.OLT<<16 | gc.TFLOAT32,
-		gc.OLT<<16 | gc.TFLOAT64:
+	case OGT_ | gc.TUINT8,
+		OGT_ | gc.TUINT16,
+		OGT_ | gc.TUINT32,
+		OGT_ | gc.TUINT64,
+		OLT_ | gc.TFLOAT32,
+		OLT_ | gc.TFLOAT64:
 		a = x86.AJHI
 
-	case gc.OGE<<16 | gc.TINT8,
-		gc.OGE<<16 | gc.TINT16,
-		gc.OGE<<16 | gc.TINT32,
-		gc.OGE<<16 | gc.TINT64:
+	case OGE_ | gc.TINT8,
+		OGE_ | gc.TINT16,
+		OGE_ | gc.TINT32,
+		OGE_ | gc.TINT64:
 		a = x86.AJGE
 
-	case gc.OGE<<16 | gc.TUINT8,
-		gc.OGE<<16 | gc.TUINT16,
-		gc.OGE<<16 | gc.TUINT32,
-		gc.OGE<<16 | gc.TUINT64,
-		gc.OLE<<16 | gc.TFLOAT32,
-		gc.OLE<<16 | gc.TFLOAT64:
+	case OGE_ | gc.TUINT8,
+		OGE_ | gc.TUINT16,
+		OGE_ | gc.TUINT32,
+		OGE_ | gc.TUINT64,
+		OLE_ | gc.TFLOAT32,
+		OLE_ | gc.TFLOAT64:
 		a = x86.AJCC
 
-	case gc.OCMP<<16 | gc.TBOOL,
-		gc.OCMP<<16 | gc.TINT8,
-		gc.OCMP<<16 | gc.TUINT8:
+	case OCMP_ | gc.TBOOL,
+		OCMP_ | gc.TINT8,
+		OCMP_ | gc.TUINT8:
 		a = x86.ACMPB
 
-	case gc.OCMP<<16 | gc.TINT16,
-		gc.OCMP<<16 | gc.TUINT16:
+	case OCMP_ | gc.TINT16,
+		OCMP_ | gc.TUINT16:
 		a = x86.ACMPW
 
-	case gc.OCMP<<16 | gc.TINT32,
-		gc.OCMP<<16 | gc.TUINT32,
-		gc.OCMP<<16 | gc.TPTR32:
+	case OCMP_ | gc.TINT32,
+		OCMP_ | gc.TUINT32,
+		OCMP_ | gc.TPTR32:
 		a = x86.ACMPL
 
-	case gc.OCMP<<16 | gc.TINT64,
-		gc.OCMP<<16 | gc.TUINT64,
-		gc.OCMP<<16 | gc.TPTR64:
+	case OCMP_ | gc.TINT64,
+		OCMP_ | gc.TUINT64,
+		OCMP_ | gc.TPTR64:
 		a = x86.ACMPQ
 
-	case gc.OCMP<<16 | gc.TFLOAT32:
+	case OCMP_ | gc.TFLOAT32:
 		a = x86.AUCOMISS
 
-	case gc.OCMP<<16 | gc.TFLOAT64:
+	case OCMP_ | gc.TFLOAT64:
 		a = x86.AUCOMISD
 
-	case gc.OAS<<16 | gc.TBOOL,
-		gc.OAS<<16 | gc.TINT8,
-		gc.OAS<<16 | gc.TUINT8:
+	case OAS_ | gc.TBOOL,
+		OAS_ | gc.TINT8,
+		OAS_ | gc.TUINT8:
 		a = x86.AMOVB
 
-	case gc.OAS<<16 | gc.TINT16,
-		gc.OAS<<16 | gc.TUINT16:
+	case OAS_ | gc.TINT16,
+		OAS_ | gc.TUINT16:
 		a = x86.AMOVW
 
-	case gc.OAS<<16 | gc.TINT32,
-		gc.OAS<<16 | gc.TUINT32,
-		gc.OAS<<16 | gc.TPTR32:
+	case OAS_ | gc.TINT32,
+		OAS_ | gc.TUINT32,
+		OAS_ | gc.TPTR32:
 		a = x86.AMOVL
 
-	case gc.OAS<<16 | gc.TINT64,
-		gc.OAS<<16 | gc.TUINT64,
-		gc.OAS<<16 | gc.TPTR64:
+	case OAS_ | gc.TINT64,
+		OAS_ | gc.TUINT64,
+		OAS_ | gc.TPTR64:
 		a = x86.AMOVQ
 
-	case gc.OAS<<16 | gc.TFLOAT32:
+	case OAS_ | gc.TFLOAT32:
 		a = x86.AMOVSS
 
-	case gc.OAS<<16 | gc.TFLOAT64:
+	case OAS_ | gc.TFLOAT64:
 		a = x86.AMOVSD
 
-	case gc.OADD<<16 | gc.TINT8,
-		gc.OADD<<16 | gc.TUINT8:
+	case OADD_ | gc.TINT8,
+		OADD_ | gc.TUINT8:
 		a = x86.AADDB
 
-	case gc.OADD<<16 | gc.TINT16,
-		gc.OADD<<16 | gc.TUINT16:
+	case OADD_ | gc.TINT16,
+		OADD_ | gc.TUINT16:
 		a = x86.AADDW
 
-	case gc.OADD<<16 | gc.TINT32,
-		gc.OADD<<16 | gc.TUINT32,
-		gc.OADD<<16 | gc.TPTR32:
+	case OADD_ | gc.TINT32,
+		OADD_ | gc.TUINT32,
+		OADD_ | gc.TPTR32:
 		a = x86.AADDL
 
-	case gc.OADD<<16 | gc.TINT64,
-		gc.OADD<<16 | gc.TUINT64,
-		gc.OADD<<16 | gc.TPTR64:
+	case OADD_ | gc.TINT64,
+		OADD_ | gc.TUINT64,
+		OADD_ | gc.TPTR64:
 		a = x86.AADDQ
 
-	case gc.OADD<<16 | gc.TFLOAT32:
+	case OADD_ | gc.TFLOAT32:
 		a = x86.AADDSS
 
-	case gc.OADD<<16 | gc.TFLOAT64:
+	case OADD_ | gc.TFLOAT64:
 		a = x86.AADDSD
 
-	case gc.OSUB<<16 | gc.TINT8,
-		gc.OSUB<<16 | gc.TUINT8:
+	case OSUB_ | gc.TINT8,
+		OSUB_ | gc.TUINT8:
 		a = x86.ASUBB
 
-	case gc.OSUB<<16 | gc.TINT16,
-		gc.OSUB<<16 | gc.TUINT16:
+	case OSUB_ | gc.TINT16,
+		OSUB_ | gc.TUINT16:
 		a = x86.ASUBW
 
-	case gc.OSUB<<16 | gc.TINT32,
-		gc.OSUB<<16 | gc.TUINT32,
-		gc.OSUB<<16 | gc.TPTR32:
+	case OSUB_ | gc.TINT32,
+		OSUB_ | gc.TUINT32,
+		OSUB_ | gc.TPTR32:
 		a = x86.ASUBL
 
-	case gc.OSUB<<16 | gc.TINT64,
-		gc.OSUB<<16 | gc.TUINT64,
-		gc.OSUB<<16 | gc.TPTR64:
+	case OSUB_ | gc.TINT64,
+		OSUB_ | gc.TUINT64,
+		OSUB_ | gc.TPTR64:
 		a = x86.ASUBQ
 
-	case gc.OSUB<<16 | gc.TFLOAT32:
+	case OSUB_ | gc.TFLOAT32:
 		a = x86.ASUBSS
 
-	case gc.OSUB<<16 | gc.TFLOAT64:
+	case OSUB_ | gc.TFLOAT64:
 		a = x86.ASUBSD
 
-	case gc.OINC<<16 | gc.TINT8,
-		gc.OINC<<16 | gc.TUINT8:
+	case OINC_ | gc.TINT8,
+		OINC_ | gc.TUINT8:
 		a = x86.AINCB
 
-	case gc.OINC<<16 | gc.TINT16,
-		gc.OINC<<16 | gc.TUINT16:
+	case OINC_ | gc.TINT16,
+		OINC_ | gc.TUINT16:
 		a = x86.AINCW
 
-	case gc.OINC<<16 | gc.TINT32,
-		gc.OINC<<16 | gc.TUINT32,
-		gc.OINC<<16 | gc.TPTR32:
+	case OINC_ | gc.TINT32,
+		OINC_ | gc.TUINT32,
+		OINC_ | gc.TPTR32:
 		a = x86.AINCL
 
-	case gc.OINC<<16 | gc.TINT64,
-		gc.OINC<<16 | gc.TUINT64,
-		gc.OINC<<16 | gc.TPTR64:
+	case OINC_ | gc.TINT64,
+		OINC_ | gc.TUINT64,
+		OINC_ | gc.TPTR64:
 		a = x86.AINCQ
 
-	case gc.ODEC<<16 | gc.TINT8,
-		gc.ODEC<<16 | gc.TUINT8:
+	case ODEC_ | gc.TINT8,
+		ODEC_ | gc.TUINT8:
 		a = x86.ADECB
 
-	case gc.ODEC<<16 | gc.TINT16,
-		gc.ODEC<<16 | gc.TUINT16:
+	case ODEC_ | gc.TINT16,
+		ODEC_ | gc.TUINT16:
 		a = x86.ADECW
 
-	case gc.ODEC<<16 | gc.TINT32,
-		gc.ODEC<<16 | gc.TUINT32,
-		gc.ODEC<<16 | gc.TPTR32:
+	case ODEC_ | gc.TINT32,
+		ODEC_ | gc.TUINT32,
+		ODEC_ | gc.TPTR32:
 		a = x86.ADECL
 
-	case gc.ODEC<<16 | gc.TINT64,
-		gc.ODEC<<16 | gc.TUINT64,
-		gc.ODEC<<16 | gc.TPTR64:
+	case ODEC_ | gc.TINT64,
+		ODEC_ | gc.TUINT64,
+		ODEC_ | gc.TPTR64:
 		a = x86.ADECQ
 
-	case gc.OMINUS<<16 | gc.TINT8,
-		gc.OMINUS<<16 | gc.TUINT8:
+	case OMINUS_ | gc.TINT8,
+		OMINUS_ | gc.TUINT8:
 		a = x86.ANEGB
 
-	case gc.OMINUS<<16 | gc.TINT16,
-		gc.OMINUS<<16 | gc.TUINT16:
+	case OMINUS_ | gc.TINT16,
+		OMINUS_ | gc.TUINT16:
 		a = x86.ANEGW
 
-	case gc.OMINUS<<16 | gc.TINT32,
-		gc.OMINUS<<16 | gc.TUINT32,
-		gc.OMINUS<<16 | gc.TPTR32:
+	case OMINUS_ | gc.TINT32,
+		OMINUS_ | gc.TUINT32,
+		OMINUS_ | gc.TPTR32:
 		a = x86.ANEGL
 
-	case gc.OMINUS<<16 | gc.TINT64,
-		gc.OMINUS<<16 | gc.TUINT64,
-		gc.OMINUS<<16 | gc.TPTR64:
+	case OMINUS_ | gc.TINT64,
+		OMINUS_ | gc.TUINT64,
+		OMINUS_ | gc.TPTR64:
 		a = x86.ANEGQ
 
-	case gc.OAND<<16 | gc.TBOOL,
-		gc.OAND<<16 | gc.TINT8,
-		gc.OAND<<16 | gc.TUINT8:
+	case OAND_ | gc.TBOOL,
+		OAND_ | gc.TINT8,
+		OAND_ | gc.TUINT8:
 		a = x86.AANDB
 
-	case gc.OAND<<16 | gc.TINT16,
-		gc.OAND<<16 | gc.TUINT16:
+	case OAND_ | gc.TINT16,
+		OAND_ | gc.TUINT16:
 		a = x86.AANDW
 
-	case gc.OAND<<16 | gc.TINT32,
-		gc.OAND<<16 | gc.TUINT32,
-		gc.OAND<<16 | gc.TPTR32:
+	case OAND_ | gc.TINT32,
+		OAND_ | gc.TUINT32,
+		OAND_ | gc.TPTR32:
 		a = x86.AANDL
 
-	case gc.OAND<<16 | gc.TINT64,
-		gc.OAND<<16 | gc.TUINT64,
-		gc.OAND<<16 | gc.TPTR64:
+	case OAND_ | gc.TINT64,
+		OAND_ | gc.TUINT64,
+		OAND_ | gc.TPTR64:
 		a = x86.AANDQ
 
-	case gc.OOR<<16 | gc.TBOOL,
-		gc.OOR<<16 | gc.TINT8,
-		gc.OOR<<16 | gc.TUINT8:
+	case OOR_ | gc.TBOOL,
+		OOR_ | gc.TINT8,
+		OOR_ | gc.TUINT8:
 		a = x86.AORB
 
-	case gc.OOR<<16 | gc.TINT16,
-		gc.OOR<<16 | gc.TUINT16:
+	case OOR_ | gc.TINT16,
+		OOR_ | gc.TUINT16:
 		a = x86.AORW
 
-	case gc.OOR<<16 | gc.TINT32,
-		gc.OOR<<16 | gc.TUINT32,
-		gc.OOR<<16 | gc.TPTR32:
+	case OOR_ | gc.TINT32,
+		OOR_ | gc.TUINT32,
+		OOR_ | gc.TPTR32:
 		a = x86.AORL
 
-	case gc.OOR<<16 | gc.TINT64,
-		gc.OOR<<16 | gc.TUINT64,
-		gc.OOR<<16 | gc.TPTR64:
+	case OOR_ | gc.TINT64,
+		OOR_ | gc.TUINT64,
+		OOR_ | gc.TPTR64:
 		a = x86.AORQ
 
-	case gc.OXOR<<16 | gc.TINT8,
-		gc.OXOR<<16 | gc.TUINT8:
+	case OXOR_ | gc.TINT8,
+		OXOR_ | gc.TUINT8:
 		a = x86.AXORB
 
-	case gc.OXOR<<16 | gc.TINT16,
-		gc.OXOR<<16 | gc.TUINT16:
+	case OXOR_ | gc.TINT16,
+		OXOR_ | gc.TUINT16:
 		a = x86.AXORW
 
-	case gc.OXOR<<16 | gc.TINT32,
-		gc.OXOR<<16 | gc.TUINT32,
-		gc.OXOR<<16 | gc.TPTR32:
+	case OXOR_ | gc.TINT32,
+		OXOR_ | gc.TUINT32,
+		OXOR_ | gc.TPTR32:
 		a = x86.AXORL
 
-	case gc.OXOR<<16 | gc.TINT64,
-		gc.OXOR<<16 | gc.TUINT64,
-		gc.OXOR<<16 | gc.TPTR64:
+	case OXOR_ | gc.TINT64,
+		OXOR_ | gc.TUINT64,
+		OXOR_ | gc.TPTR64:
 		a = x86.AXORQ
 
-	case gc.OLROT<<16 | gc.TINT8,
-		gc.OLROT<<16 | gc.TUINT8:
+	case OLROT_ | gc.TINT8,
+		OLROT_ | gc.TUINT8:
 		a = x86.AROLB
 
-	case gc.OLROT<<16 | gc.TINT16,
-		gc.OLROT<<16 | gc.TUINT16:
+	case OLROT_ | gc.TINT16,
+		OLROT_ | gc.TUINT16:
 		a = x86.AROLW
 
-	case gc.OLROT<<16 | gc.TINT32,
-		gc.OLROT<<16 | gc.TUINT32,
-		gc.OLROT<<16 | gc.TPTR32:
+	case OLROT_ | gc.TINT32,
+		OLROT_ | gc.TUINT32,
+		OLROT_ | gc.TPTR32:
 		a = x86.AROLL
 
-	case gc.OLROT<<16 | gc.TINT64,
-		gc.OLROT<<16 | gc.TUINT64,
-		gc.OLROT<<16 | gc.TPTR64:
+	case OLROT_ | gc.TINT64,
+		OLROT_ | gc.TUINT64,
+		OLROT_ | gc.TPTR64:
 		a = x86.AROLQ
 
-	case gc.OLSH<<16 | gc.TINT8,
-		gc.OLSH<<16 | gc.TUINT8:
+	case OLSH_ | gc.TINT8,
+		OLSH_ | gc.TUINT8:
 		a = x86.ASHLB
 
-	case gc.OLSH<<16 | gc.TINT16,
-		gc.OLSH<<16 | gc.TUINT16:
+	case OLSH_ | gc.TINT16,
+		OLSH_ | gc.TUINT16:
 		a = x86.ASHLW
 
-	case gc.OLSH<<16 | gc.TINT32,
-		gc.OLSH<<16 | gc.TUINT32,
-		gc.OLSH<<16 | gc.TPTR32:
+	case OLSH_ | gc.TINT32,
+		OLSH_ | gc.TUINT32,
+		OLSH_ | gc.TPTR32:
 		a = x86.ASHLL
 
-	case gc.OLSH<<16 | gc.TINT64,
-		gc.OLSH<<16 | gc.TUINT64,
-		gc.OLSH<<16 | gc.TPTR64:
+	case OLSH_ | gc.TINT64,
+		OLSH_ | gc.TUINT64,
+		OLSH_ | gc.TPTR64:
 		a = x86.ASHLQ
 
-	case gc.ORSH<<16 | gc.TUINT8:
+	case ORSH_ | gc.TUINT8:
 		a = x86.ASHRB
 
-	case gc.ORSH<<16 | gc.TUINT16:
+	case ORSH_ | gc.TUINT16:
 		a = x86.ASHRW
 
-	case gc.ORSH<<16 | gc.TUINT32,
-		gc.ORSH<<16 | gc.TPTR32:
+	case ORSH_ | gc.TUINT32,
+		ORSH_ | gc.TPTR32:
 		a = x86.ASHRL
 
-	case gc.ORSH<<16 | gc.TUINT64,
-		gc.ORSH<<16 | gc.TPTR64:
+	case ORSH_ | gc.TUINT64,
+		ORSH_ | gc.TPTR64:
 		a = x86.ASHRQ
 
-	case gc.ORSH<<16 | gc.TINT8:
+	case ORSH_ | gc.TINT8:
 		a = x86.ASARB
 
-	case gc.ORSH<<16 | gc.TINT16:
+	case ORSH_ | gc.TINT16:
 		a = x86.ASARW
 
-	case gc.ORSH<<16 | gc.TINT32:
+	case ORSH_ | gc.TINT32:
 		a = x86.ASARL
 
-	case gc.ORSH<<16 | gc.TINT64:
+	case ORSH_ | gc.TINT64:
 		a = x86.ASARQ
 
-	case gc.ORROTC<<16 | gc.TINT8,
-		gc.ORROTC<<16 | gc.TUINT8:
+	case ORROTC_ | gc.TINT8,
+		ORROTC_ | gc.TUINT8:
 		a = x86.ARCRB
 
-	case gc.ORROTC<<16 | gc.TINT16,
-		gc.ORROTC<<16 | gc.TUINT16:
+	case ORROTC_ | gc.TINT16,
+		ORROTC_ | gc.TUINT16:
 		a = x86.ARCRW
 
-	case gc.ORROTC<<16 | gc.TINT32,
-		gc.ORROTC<<16 | gc.TUINT32:
+	case ORROTC_ | gc.TINT32,
+		ORROTC_ | gc.TUINT32:
 		a = x86.ARCRL
 
-	case gc.ORROTC<<16 | gc.TINT64,
-		gc.ORROTC<<16 | gc.TUINT64:
+	case ORROTC_ | gc.TINT64,
+		ORROTC_ | gc.TUINT64:
 		a = x86.ARCRQ
 
-	case gc.OHMUL<<16 | gc.TINT8,
-		gc.OMUL<<16 | gc.TINT8,
-		gc.OMUL<<16 | gc.TUINT8:
+	case OHMUL_ | gc.TINT8,
+		OMUL_ | gc.TINT8,
+		OMUL_ | gc.TUINT8:
 		a = x86.AIMULB
 
-	case gc.OHMUL<<16 | gc.TINT16,
-		gc.OMUL<<16 | gc.TINT16,
-		gc.OMUL<<16 | gc.TUINT16:
+	case OHMUL_ | gc.TINT16,
+		OMUL_ | gc.TINT16,
+		OMUL_ | gc.TUINT16:
 		a = x86.AIMULW
 
-	case gc.OHMUL<<16 | gc.TINT32,
-		gc.OMUL<<16 | gc.TINT32,
-		gc.OMUL<<16 | gc.TUINT32,
-		gc.OMUL<<16 | gc.TPTR32:
+	case OHMUL_ | gc.TINT32,
+		OMUL_ | gc.TINT32,
+		OMUL_ | gc.TUINT32,
+		OMUL_ | gc.TPTR32:
 		a = x86.AIMULL
 
-	case gc.OHMUL<<16 | gc.TINT64,
-		gc.OMUL<<16 | gc.TINT64,
-		gc.OMUL<<16 | gc.TUINT64,
-		gc.OMUL<<16 | gc.TPTR64:
+	case OHMUL_ | gc.TINT64,
+		OMUL_ | gc.TINT64,
+		OMUL_ | gc.TUINT64,
+		OMUL_ | gc.TPTR64:
 		a = x86.AIMULQ
 
-	case gc.OHMUL<<16 | gc.TUINT8:
+	case OHMUL_ | gc.TUINT8:
 		a = x86.AMULB
 
-	case gc.OHMUL<<16 | gc.TUINT16:
+	case OHMUL_ | gc.TUINT16:
 		a = x86.AMULW
 
-	case gc.OHMUL<<16 | gc.TUINT32,
-		gc.OHMUL<<16 | gc.TPTR32:
+	case OHMUL_ | gc.TUINT32,
+		OHMUL_ | gc.TPTR32:
 		a = x86.AMULL
 
-	case gc.OHMUL<<16 | gc.TUINT64,
-		gc.OHMUL<<16 | gc.TPTR64:
+	case OHMUL_ | gc.TUINT64,
+		OHMUL_ | gc.TPTR64:
 		a = x86.AMULQ
 
-	case gc.OMUL<<16 | gc.TFLOAT32:
+	case OMUL_ | gc.TFLOAT32:
 		a = x86.AMULSS
 
-	case gc.OMUL<<16 | gc.TFLOAT64:
+	case OMUL_ | gc.TFLOAT64:
 		a = x86.AMULSD
 
-	case gc.ODIV<<16 | gc.TINT8,
-		gc.OMOD<<16 | gc.TINT8:
+	case ODIV_ | gc.TINT8,
+		OMOD_ | gc.TINT8:
 		a = x86.AIDIVB
 
-	case gc.ODIV<<16 | gc.TUINT8,
-		gc.OMOD<<16 | gc.TUINT8:
+	case ODIV_ | gc.TUINT8,
+		OMOD_ | gc.TUINT8:
 		a = x86.ADIVB
 
-	case gc.ODIV<<16 | gc.TINT16,
-		gc.OMOD<<16 | gc.TINT16:
+	case ODIV_ | gc.TINT16,
+		OMOD_ | gc.TINT16:
 		a = x86.AIDIVW
 
-	case gc.ODIV<<16 | gc.TUINT16,
-		gc.OMOD<<16 | gc.TUINT16:
+	case ODIV_ | gc.TUINT16,
+		OMOD_ | gc.TUINT16:
 		a = x86.ADIVW
 
-	case gc.ODIV<<16 | gc.TINT32,
-		gc.OMOD<<16 | gc.TINT32:
+	case ODIV_ | gc.TINT32,
+		OMOD_ | gc.TINT32:
 		a = x86.AIDIVL
 
-	case gc.ODIV<<16 | gc.TUINT32,
-		gc.ODIV<<16 | gc.TPTR32,
-		gc.OMOD<<16 | gc.TUINT32,
-		gc.OMOD<<16 | gc.TPTR32:
+	case ODIV_ | gc.TUINT32,
+		ODIV_ | gc.TPTR32,
+		OMOD_ | gc.TUINT32,
+		OMOD_ | gc.TPTR32:
 		a = x86.ADIVL
 
-	case gc.ODIV<<16 | gc.TINT64,
-		gc.OMOD<<16 | gc.TINT64:
+	case ODIV_ | gc.TINT64,
+		OMOD_ | gc.TINT64:
 		a = x86.AIDIVQ
 
-	case gc.ODIV<<16 | gc.TUINT64,
-		gc.ODIV<<16 | gc.TPTR64,
-		gc.OMOD<<16 | gc.TUINT64,
-		gc.OMOD<<16 | gc.TPTR64:
+	case ODIV_ | gc.TUINT64,
+		ODIV_ | gc.TPTR64,
+		OMOD_ | gc.TUINT64,
+		OMOD_ | gc.TPTR64:
 		a = x86.ADIVQ
 
-	case gc.OEXTEND<<16 | gc.TINT16:
+	case OEXTEND_ | gc.TINT16:
 		a = x86.ACWD
 
-	case gc.OEXTEND<<16 | gc.TINT32:
+	case OEXTEND_ | gc.TINT32:
 		a = x86.ACDQ
 
-	case gc.OEXTEND<<16 | gc.TINT64:
+	case OEXTEND_ | gc.TINT64:
 		a = x86.ACQO
 
-	case gc.ODIV<<16 | gc.TFLOAT32:
+	case ODIV_ | gc.TFLOAT32:
 		a = x86.ADIVSS
 
-	case gc.ODIV<<16 | gc.TFLOAT64:
+	case ODIV_ | gc.TFLOAT64:
 		a = x86.ADIVSD
 
-	case gc.OSQRT<<16 | gc.TFLOAT64:
+	case OSQRT_ | gc.TFLOAT64:
 		a = x86.ASQRTSD
 	}
 
@@ -1223,7 +1264,7 @@ func jmptoset(jmp int) int {
 	case x86.AJPS:
 		return x86.ASETPS
 	}
-	gc.Fatal("jmptoset: no entry for %v", gc.Oconv(jmp, 0))
+	gc.Fatalf("jmptoset: no entry for %v", gc.Oconv(jmp, 0))
 	panic("unreachable")
 }
 
@@ -1359,7 +1400,7 @@ func sudoaddable(as int, n *gc.Node, a *obj.Addr) bool {
 
 		for i := 1; i < o; i++ {
 			if oary[i] >= 0 {
-				gc.Fatal("can't happen")
+				gc.Fatalf("can't happen")
 			}
 			gins(movptr, &n1, reg)
 			gc.Cgen_checknil(reg)
diff --git a/src/cmd/compile/internal/amd64/peep.go b/src/cmd/compile/internal/amd64/peep.go
index 19db68e..452f954 100644
--- a/src/cmd/compile/internal/amd64/peep.go
+++ b/src/cmd/compile/internal/amd64/peep.go
@@ -823,6 +823,10 @@ func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
 		return 2
 	}
 
+	if (p.Info.Reguse|p.Info.Regset)&FtoB(int(v.Reg)) != 0 {
+		return 2
+	}
+
 	if p.Info.Flags&gc.LeftAddr != 0 {
 		if copyas(&p.From, v) {
 			return 2
@@ -873,10 +877,10 @@ func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
  */
 func copyas(a *obj.Addr, v *obj.Addr) bool {
 	if x86.REG_AL <= a.Reg && a.Reg <= x86.REG_R15B {
-		gc.Fatal("use of byte register")
+		gc.Fatalf("use of byte register")
 	}
 	if x86.REG_AL <= v.Reg && v.Reg <= x86.REG_R15B {
-		gc.Fatal("use of byte register")
+		gc.Fatalf("use of byte register")
 	}
 
 	if a.Type != v.Type || a.Name != v.Name || a.Reg != v.Reg {
diff --git a/src/cmd/compile/internal/amd64/prog.go b/src/cmd/compile/internal/amd64/prog.go
index 00918c8..b3724b4 100644
--- a/src/cmd/compile/internal/amd64/prog.go
+++ b/src/cmd/compile/internal/amd64/prog.go
@@ -25,227 +25,230 @@ const (
 //
 // The table is formatted for 8-space tabs.
 var progtable = [x86.ALAST]obj.ProgInfo{
-	obj.ATYPE:     {gc.Pseudo | gc.Skip, 0, 0, 0},
-	obj.ATEXT:     {gc.Pseudo, 0, 0, 0},
-	obj.AFUNCDATA: {gc.Pseudo, 0, 0, 0},
-	obj.APCDATA:   {gc.Pseudo, 0, 0, 0},
-	obj.AUNDEF:    {gc.Break, 0, 0, 0},
-	obj.AUSEFIELD: {gc.OK, 0, 0, 0},
-	obj.ACHECKNIL: {gc.LeftRead, 0, 0, 0},
-	obj.AVARDEF:   {gc.Pseudo | gc.RightWrite, 0, 0, 0},
-	obj.AVARKILL:  {gc.Pseudo | gc.RightWrite, 0, 0, 0},
+	obj.ATYPE:     {Flags: gc.Pseudo | gc.Skip},
+	obj.ATEXT:     {Flags: gc.Pseudo},
+	obj.AFUNCDATA: {Flags: gc.Pseudo},
+	obj.APCDATA:   {Flags: gc.Pseudo},
+	obj.AUNDEF:    {Flags: gc.Break},
+	obj.AUSEFIELD: {Flags: gc.OK},
+	obj.ACHECKNIL: {Flags: gc.LeftRead},
+	obj.AVARDEF:   {Flags: gc.Pseudo | gc.RightWrite},
+	obj.AVARKILL:  {Flags: gc.Pseudo | gc.RightWrite},
+	obj.AVARLIVE:  {Flags: gc.Pseudo | gc.LeftRead},
 
 	// NOP is an internal no-op that also stands
 	// for USED and SET annotations, not the Intel opcode.
-	obj.ANOP:       {gc.LeftRead | gc.RightWrite, 0, 0, 0},
-	x86.AADCL:      {gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.AADCQ:      {gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.AADCW:      {gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.AADDB:      {gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AADDL:      {gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AADDW:      {gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AADDQ:      {gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AADDSD:     {gc.SizeD | gc.LeftRead | RightRdwr, 0, 0, 0},
-	x86.AADDSS:     {gc.SizeF | gc.LeftRead | RightRdwr, 0, 0, 0},
-	x86.AANDB:      {gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AANDL:      {gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AANDQ:      {gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AANDW:      {gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	obj.ACALL:      {gc.RightAddr | gc.Call | gc.KillCarry, 0, 0, 0},
-	x86.ACDQ:       {gc.OK, AX, AX | DX, 0},
-	x86.ACQO:       {gc.OK, AX, AX | DX, 0},
-	x86.ACWD:       {gc.OK, AX, AX | DX, 0},
-	x86.ACLD:       {gc.OK, 0, 0, 0},
-	x86.ASTD:       {gc.OK, 0, 0, 0},
-	x86.ACMPB:      {gc.SizeB | gc.LeftRead | gc.RightRead | gc.SetCarry, 0, 0, 0},
-	x86.ACMPL:      {gc.SizeL | gc.LeftRead | gc.RightRead | gc.SetCarry, 0, 0, 0},
-	x86.ACMPQ:      {gc.SizeQ | gc.LeftRead | gc.RightRead | gc.SetCarry, 0, 0, 0},
-	x86.ACMPW:      {gc.SizeW | gc.LeftRead | gc.RightRead | gc.SetCarry, 0, 0, 0},
-	x86.ACOMISD:    {gc.SizeD | gc.LeftRead | gc.RightRead | gc.SetCarry, 0, 0, 0},
-	x86.ACOMISS:    {gc.SizeF | gc.LeftRead | gc.RightRead | gc.SetCarry, 0, 0, 0},
-	x86.ACVTSD2SL:  {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ACVTSD2SQ:  {gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ACVTSD2SS:  {gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ACVTSL2SD:  {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ACVTSL2SS:  {gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ACVTSQ2SD:  {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ACVTSQ2SS:  {gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ACVTSS2SD:  {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ACVTSS2SL:  {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ACVTSS2SQ:  {gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ACVTTSD2SL: {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ACVTTSD2SQ: {gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ACVTTSS2SL: {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ACVTTSS2SQ: {gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ADECB:      {gc.SizeB | RightRdwr, 0, 0, 0},
-	x86.ADECL:      {gc.SizeL | RightRdwr, 0, 0, 0},
-	x86.ADECQ:      {gc.SizeQ | RightRdwr, 0, 0, 0},
-	x86.ADECW:      {gc.SizeW | RightRdwr, 0, 0, 0},
-	x86.ADIVB:      {gc.SizeB | gc.LeftRead | gc.SetCarry, AX, AX, 0},
-	x86.ADIVL:      {gc.SizeL | gc.LeftRead | gc.SetCarry, AX | DX, AX | DX, 0},
-	x86.ADIVQ:      {gc.SizeQ | gc.LeftRead | gc.SetCarry, AX | DX, AX | DX, 0},
-	x86.ADIVW:      {gc.SizeW | gc.LeftRead | gc.SetCarry, AX | DX, AX | DX, 0},
-	x86.ADIVSD:     {gc.SizeD | gc.LeftRead | RightRdwr, 0, 0, 0},
-	x86.ADIVSS:     {gc.SizeF | gc.LeftRead | RightRdwr, 0, 0, 0},
-	x86.AIDIVB:     {gc.SizeB | gc.LeftRead | gc.SetCarry, AX, AX, 0},
-	x86.AIDIVL:     {gc.SizeL | gc.LeftRead | gc.SetCarry, AX | DX, AX | DX, 0},
-	x86.AIDIVQ:     {gc.SizeQ | gc.LeftRead | gc.SetCarry, AX | DX, AX | DX, 0},
-	x86.AIDIVW:     {gc.SizeW | gc.LeftRead | gc.SetCarry, AX | DX, AX | DX, 0},
-	x86.AIMULB:     {gc.SizeB | gc.LeftRead | gc.SetCarry, AX, AX, 0},
-	x86.AIMULL:     {gc.SizeL | gc.LeftRead | gc.ImulAXDX | gc.SetCarry, 0, 0, 0},
-	x86.AIMULQ:     {gc.SizeQ | gc.LeftRead | gc.ImulAXDX | gc.SetCarry, 0, 0, 0},
-	x86.AIMULW:     {gc.SizeW | gc.LeftRead | gc.ImulAXDX | gc.SetCarry, 0, 0, 0},
-	x86.AINCB:      {gc.SizeB | RightRdwr, 0, 0, 0},
-	x86.AINCL:      {gc.SizeL | RightRdwr, 0, 0, 0},
-	x86.AINCQ:      {gc.SizeQ | RightRdwr, 0, 0, 0},
-	x86.AINCW:      {gc.SizeW | RightRdwr, 0, 0, 0},
-	x86.AJCC:       {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJCS:       {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJEQ:       {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJGE:       {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJGT:       {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJHI:       {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJLE:       {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJLS:       {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJLT:       {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJMI:       {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJNE:       {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJOC:       {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJOS:       {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJPC:       {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJPL:       {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJPS:       {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	obj.AJMP:       {gc.Jump | gc.Break | gc.KillCarry, 0, 0, 0},
-	x86.ALEAL:      {gc.LeftAddr | gc.RightWrite, 0, 0, 0},
-	x86.ALEAQ:      {gc.LeftAddr | gc.RightWrite, 0, 0, 0},
-	x86.AMOVBLSX:   {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.AMOVBLZX:   {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.AMOVBQSX:   {gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.AMOVBQZX:   {gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.AMOVBWSX:   {gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.AMOVBWZX:   {gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.AMOVLQSX:   {gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.AMOVLQZX:   {gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.AMOVWLSX:   {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.AMOVWLZX:   {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.AMOVWQSX:   {gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.AMOVWQZX:   {gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.AMOVQL:     {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.AMOVB:      {gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
-	x86.AMOVL:      {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
-	x86.AMOVQ:      {gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
-	x86.AMOVW:      {gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
-	x86.AMOVSB:     {gc.OK, DI | SI, DI | SI, 0},
-	x86.AMOVSL:     {gc.OK, DI | SI, DI | SI, 0},
-	x86.AMOVSQ:     {gc.OK, DI | SI, DI | SI, 0},
-	x86.AMOVSW:     {gc.OK, DI | SI, DI | SI, 0},
-	obj.ADUFFCOPY:  {gc.OK, DI | SI, DI | SI | CX, 0},
-	x86.AMOVSD:     {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
-	x86.AMOVSS:     {gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
+	obj.ANOP:       {Flags: gc.LeftRead | gc.RightWrite},
+	x86.AADCL:      {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry},
+	x86.AADCQ:      {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry},
+	x86.AADCW:      {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry},
+	x86.AADDB:      {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AADDL:      {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AADDW:      {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AADDQ:      {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AADDSD:     {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
+	x86.AADDSS:     {Flags: gc.SizeF | gc.LeftRead | RightRdwr},
+	x86.AANDB:      {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AANDL:      {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AANDQ:      {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AANDW:      {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry},
+	obj.ACALL:      {Flags: gc.RightAddr | gc.Call | gc.KillCarry},
+	x86.ACDQ:       {Flags: gc.OK, Reguse: AX, Regset: AX | DX},
+	x86.ACQO:       {Flags: gc.OK, Reguse: AX, Regset: AX | DX},
+	x86.ACWD:       {Flags: gc.OK, Reguse: AX, Regset: AX | DX},
+	x86.ACLD:       {Flags: gc.OK},
+	x86.ASTD:       {Flags: gc.OK},
+	x86.ACMPB:      {Flags: gc.SizeB | gc.LeftRead | gc.RightRead | gc.SetCarry},
+	x86.ACMPL:      {Flags: gc.SizeL | gc.LeftRead | gc.RightRead | gc.SetCarry},
+	x86.ACMPQ:      {Flags: gc.SizeQ | gc.LeftRead | gc.RightRead | gc.SetCarry},
+	x86.ACMPW:      {Flags: gc.SizeW | gc.LeftRead | gc.RightRead | gc.SetCarry},
+	x86.ACOMISD:    {Flags: gc.SizeD | gc.LeftRead | gc.RightRead | gc.SetCarry},
+	x86.ACOMISS:    {Flags: gc.SizeF | gc.LeftRead | gc.RightRead | gc.SetCarry},
+	x86.ACVTSD2SL:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ACVTSD2SQ:  {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ACVTSD2SS:  {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ACVTSL2SD:  {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ACVTSL2SS:  {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ACVTSQ2SD:  {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ACVTSQ2SS:  {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ACVTSS2SD:  {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ACVTSS2SL:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ACVTSS2SQ:  {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ACVTTSD2SL: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ACVTTSD2SQ: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ACVTTSS2SL: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ACVTTSS2SQ: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ADECB:      {Flags: gc.SizeB | RightRdwr},
+	x86.ADECL:      {Flags: gc.SizeL | RightRdwr},
+	x86.ADECQ:      {Flags: gc.SizeQ | RightRdwr},
+	x86.ADECW:      {Flags: gc.SizeW | RightRdwr},
+	x86.ADIVB:      {Flags: gc.SizeB | gc.LeftRead | gc.SetCarry, Reguse: AX, Regset: AX},
+	x86.ADIVL:      {Flags: gc.SizeL | gc.LeftRead | gc.SetCarry, Reguse: AX | DX, Regset: AX | DX},
+	x86.ADIVQ:      {Flags: gc.SizeQ | gc.LeftRead | gc.SetCarry, Reguse: AX | DX, Regset: AX | DX},
+	x86.ADIVW:      {Flags: gc.SizeW | gc.LeftRead | gc.SetCarry, Reguse: AX | DX, Regset: AX | DX},
+	x86.ADIVSD:     {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
+	x86.ADIVSS:     {Flags: gc.SizeF | gc.LeftRead | RightRdwr},
+	x86.AIDIVB:     {Flags: gc.SizeB | gc.LeftRead | gc.SetCarry, Reguse: AX, Regset: AX},
+	x86.AIDIVL:     {Flags: gc.SizeL | gc.LeftRead | gc.SetCarry, Reguse: AX | DX, Regset: AX | DX},
+	x86.AIDIVQ:     {Flags: gc.SizeQ | gc.LeftRead | gc.SetCarry, Reguse: AX | DX, Regset: AX | DX},
+	x86.AIDIVW:     {Flags: gc.SizeW | gc.LeftRead | gc.SetCarry, Reguse: AX | DX, Regset: AX | DX},
+	x86.AIMULB:     {Flags: gc.SizeB | gc.LeftRead | gc.SetCarry, Reguse: AX, Regset: AX},
+	x86.AIMULL:     {Flags: gc.SizeL | gc.LeftRead | gc.ImulAXDX | gc.SetCarry},
+	x86.AIMULQ:     {Flags: gc.SizeQ | gc.LeftRead | gc.ImulAXDX | gc.SetCarry},
+	x86.AIMULW:     {Flags: gc.SizeW | gc.LeftRead | gc.ImulAXDX | gc.SetCarry},
+	x86.AINCB:      {Flags: gc.SizeB | RightRdwr},
+	x86.AINCL:      {Flags: gc.SizeL | RightRdwr},
+	x86.AINCQ:      {Flags: gc.SizeQ | RightRdwr},
+	x86.AINCW:      {Flags: gc.SizeW | RightRdwr},
+	x86.AJCC:       {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJCS:       {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJEQ:       {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJGE:       {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJGT:       {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJHI:       {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJLE:       {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJLS:       {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJLT:       {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJMI:       {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJNE:       {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJOC:       {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJOS:       {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJPC:       {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJPL:       {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJPS:       {Flags: gc.Cjmp | gc.UseCarry},
+	obj.AJMP:       {Flags: gc.Jump | gc.Break | gc.KillCarry},
+	x86.ALEAL:      {Flags: gc.LeftAddr | gc.RightWrite},
+	x86.ALEAQ:      {Flags: gc.LeftAddr | gc.RightWrite},
+	x86.AMOVBLSX:   {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.AMOVBLZX:   {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.AMOVBQSX:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.AMOVBQZX:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.AMOVBWSX:   {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.AMOVBWZX:   {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.AMOVLQSX:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.AMOVLQZX:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.AMOVWLSX:   {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.AMOVWLZX:   {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.AMOVWQSX:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.AMOVWQZX:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.AMOVQL:     {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.AMOVB:      {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move},
+	x86.AMOVL:      {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move},
+	x86.AMOVQ:      {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move},
+	x86.AMOVW:      {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move},
+	x86.AMOVUPS:    {Flags: gc.LeftRead | gc.RightWrite | gc.Move},
+	x86.AMOVSB:     {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI},
+	x86.AMOVSL:     {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI},
+	x86.AMOVSQ:     {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI},
+	x86.AMOVSW:     {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI},
+	obj.ADUFFCOPY:  {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI | X0},
+	x86.AMOVSD:     {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
+	x86.AMOVSS:     {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move},
 
 	// We use MOVAPD as a faster synonym for MOVSD.
-	x86.AMOVAPD:   {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
-	x86.AMULB:     {gc.SizeB | gc.LeftRead | gc.SetCarry, AX, AX, 0},
-	x86.AMULL:     {gc.SizeL | gc.LeftRead | gc.SetCarry, AX, AX | DX, 0},
-	x86.AMULQ:     {gc.SizeQ | gc.LeftRead | gc.SetCarry, AX, AX | DX, 0},
-	x86.AMULW:     {gc.SizeW | gc.LeftRead | gc.SetCarry, AX, AX | DX, 0},
-	x86.AMULSD:    {gc.SizeD | gc.LeftRead | RightRdwr, 0, 0, 0},
-	x86.AMULSS:    {gc.SizeF | gc.LeftRead | RightRdwr, 0, 0, 0},
-	x86.ANEGB:     {gc.SizeB | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.ANEGL:     {gc.SizeL | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.ANEGQ:     {gc.SizeQ | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.ANEGW:     {gc.SizeW | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.ANOTB:     {gc.SizeB | RightRdwr, 0, 0, 0},
-	x86.ANOTL:     {gc.SizeL | RightRdwr, 0, 0, 0},
-	x86.ANOTQ:     {gc.SizeQ | RightRdwr, 0, 0, 0},
-	x86.ANOTW:     {gc.SizeW | RightRdwr, 0, 0, 0},
-	x86.AORB:      {gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AORL:      {gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AORQ:      {gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AORW:      {gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.APOPQ:     {gc.SizeQ | gc.RightWrite, 0, 0, 0},
-	x86.APUSHQ:    {gc.SizeQ | gc.LeftRead, 0, 0, 0},
-	x86.ARCLB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.ARCLL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.ARCLQ:     {gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.ARCLW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.ARCRB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.ARCRL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.ARCRQ:     {gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.ARCRW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.AREP:      {gc.OK, CX, CX, 0},
-	x86.AREPN:     {gc.OK, CX, CX, 0},
-	obj.ARET:      {gc.Break | gc.KillCarry, 0, 0, 0},
-	x86.AROLB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.AROLL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.AROLQ:     {gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.AROLW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ARORB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ARORL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ARORQ:     {gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ARORW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASALB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASALL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASALQ:     {gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASALW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASARB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASARL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASARQ:     {gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASARW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASBBB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.ASBBL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.ASBBQ:     {gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.ASBBW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.ASETCC:    {gc.SizeB | gc.RightWrite | gc.UseCarry, 0, 0, 0},
-	x86.ASETCS:    {gc.SizeB | gc.RightWrite | gc.UseCarry, 0, 0, 0},
-	x86.ASETEQ:    {gc.SizeB | gc.RightWrite | gc.UseCarry, 0, 0, 0},
-	x86.ASETGE:    {gc.SizeB | gc.RightWrite | gc.UseCarry, 0, 0, 0},
-	x86.ASETGT:    {gc.SizeB | gc.RightWrite | gc.UseCarry, 0, 0, 0},
-	x86.ASETHI:    {gc.SizeB | gc.RightWrite | gc.UseCarry, 0, 0, 0},
-	x86.ASETLE:    {gc.SizeB | gc.RightWrite | gc.UseCarry, 0, 0, 0},
-	x86.ASETLS:    {gc.SizeB | gc.RightWrite | gc.UseCarry, 0, 0, 0},
-	x86.ASETLT:    {gc.SizeB | gc.RightWrite | gc.UseCarry, 0, 0, 0},
-	x86.ASETMI:    {gc.SizeB | gc.RightWrite | gc.UseCarry, 0, 0, 0},
-	x86.ASETNE:    {gc.SizeB | gc.RightWrite | gc.UseCarry, 0, 0, 0},
-	x86.ASETOC:    {gc.SizeB | gc.RightWrite | gc.UseCarry, 0, 0, 0},
-	x86.ASETOS:    {gc.SizeB | gc.RightWrite | gc.UseCarry, 0, 0, 0},
-	x86.ASETPC:    {gc.SizeB | gc.RightWrite | gc.UseCarry, 0, 0, 0},
-	x86.ASETPL:    {gc.SizeB | gc.RightWrite | gc.UseCarry, 0, 0, 0},
-	x86.ASETPS:    {gc.SizeB | gc.RightWrite | gc.UseCarry, 0, 0, 0},
-	x86.ASHLB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASHLL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASHLQ:     {gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASHLW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASHRB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASHRL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASHRQ:     {gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASHRW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASQRTSD:   {gc.SizeD | gc.LeftRead | RightRdwr, 0, 0, 0},
-	x86.ASTOSB:    {gc.OK, AX | DI, DI, 0},
-	x86.ASTOSL:    {gc.OK, AX | DI, DI, 0},
-	x86.ASTOSQ:    {gc.OK, AX | DI, DI, 0},
-	x86.ASTOSW:    {gc.OK, AX | DI, DI, 0},
-	obj.ADUFFZERO: {gc.OK, AX | DI, DI, 0},
-	x86.ASUBB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.ASUBL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.ASUBQ:     {gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.ASUBW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.ASUBSD:    {gc.SizeD | gc.LeftRead | RightRdwr, 0, 0, 0},
-	x86.ASUBSS:    {gc.SizeF | gc.LeftRead | RightRdwr, 0, 0, 0},
-	x86.ATESTB:    {gc.SizeB | gc.LeftRead | gc.RightRead | gc.SetCarry, 0, 0, 0},
-	x86.ATESTL:    {gc.SizeL | gc.LeftRead | gc.RightRead | gc.SetCarry, 0, 0, 0},
-	x86.ATESTQ:    {gc.SizeQ | gc.LeftRead | gc.RightRead | gc.SetCarry, 0, 0, 0},
-	x86.ATESTW:    {gc.SizeW | gc.LeftRead | gc.RightRead | gc.SetCarry, 0, 0, 0},
-	x86.AUCOMISD:  {gc.SizeD | gc.LeftRead | gc.RightRead, 0, 0, 0},
-	x86.AUCOMISS:  {gc.SizeF | gc.LeftRead | gc.RightRead, 0, 0, 0},
-	x86.AXCHGB:    {gc.SizeB | LeftRdwr | RightRdwr, 0, 0, 0},
-	x86.AXCHGL:    {gc.SizeL | LeftRdwr | RightRdwr, 0, 0, 0},
-	x86.AXCHGQ:    {gc.SizeQ | LeftRdwr | RightRdwr, 0, 0, 0},
-	x86.AXCHGW:    {gc.SizeW | LeftRdwr | RightRdwr, 0, 0, 0},
-	x86.AXORB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AXORL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AXORQ:     {gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AXORW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
+	x86.AMOVAPD:   {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
+	x86.AMULB:     {Flags: gc.SizeB | gc.LeftRead | gc.SetCarry, Reguse: AX, Regset: AX},
+	x86.AMULL:     {Flags: gc.SizeL | gc.LeftRead | gc.SetCarry, Reguse: AX, Regset: AX | DX},
+	x86.AMULQ:     {Flags: gc.SizeQ | gc.LeftRead | gc.SetCarry, Reguse: AX, Regset: AX | DX},
+	x86.AMULW:     {Flags: gc.SizeW | gc.LeftRead | gc.SetCarry, Reguse: AX, Regset: AX | DX},
+	x86.AMULSD:    {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
+	x86.AMULSS:    {Flags: gc.SizeF | gc.LeftRead | RightRdwr},
+	x86.ANEGB:     {Flags: gc.SizeB | RightRdwr | gc.SetCarry},
+	x86.ANEGL:     {Flags: gc.SizeL | RightRdwr | gc.SetCarry},
+	x86.ANEGQ:     {Flags: gc.SizeQ | RightRdwr | gc.SetCarry},
+	x86.ANEGW:     {Flags: gc.SizeW | RightRdwr | gc.SetCarry},
+	x86.ANOTB:     {Flags: gc.SizeB | RightRdwr},
+	x86.ANOTL:     {Flags: gc.SizeL | RightRdwr},
+	x86.ANOTQ:     {Flags: gc.SizeQ | RightRdwr},
+	x86.ANOTW:     {Flags: gc.SizeW | RightRdwr},
+	x86.AORB:      {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AORL:      {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AORQ:      {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AORW:      {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.APOPQ:     {Flags: gc.SizeQ | gc.RightWrite},
+	x86.APUSHQ:    {Flags: gc.SizeQ | gc.LeftRead},
+	x86.ARCLB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
+	x86.ARCLL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
+	x86.ARCLQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
+	x86.ARCLW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
+	x86.ARCRB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
+	x86.ARCRL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
+	x86.ARCRQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
+	x86.ARCRW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
+	x86.AREP:      {Flags: gc.OK, Reguse: CX, Regset: CX},
+	x86.AREPN:     {Flags: gc.OK, Reguse: CX, Regset: CX},
+	obj.ARET:      {Flags: gc.Break | gc.KillCarry},
+	x86.AROLB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.AROLL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.AROLQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.AROLW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ARORB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ARORL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ARORQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ARORW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASALB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASALL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASALQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASALW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASARB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASARL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASARQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASARW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASBBB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry},
+	x86.ASBBL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry},
+	x86.ASBBQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry},
+	x86.ASBBW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry},
+	x86.ASETCC:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
+	x86.ASETCS:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
+	x86.ASETEQ:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
+	x86.ASETGE:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
+	x86.ASETGT:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
+	x86.ASETHI:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
+	x86.ASETLE:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
+	x86.ASETLS:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
+	x86.ASETLT:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
+	x86.ASETMI:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
+	x86.ASETNE:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
+	x86.ASETOC:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
+	x86.ASETOS:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
+	x86.ASETPC:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
+	x86.ASETPL:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
+	x86.ASETPS:    {Flags: gc.SizeB | gc.RightWrite | gc.UseCarry},
+	x86.ASHLB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASHLL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASHLQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASHLW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASHRB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASHRL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASHRQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASHRW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASQRTSD:   {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
+	x86.ASTOSB:    {Flags: gc.OK, Reguse: AX | DI, Regset: DI},
+	x86.ASTOSL:    {Flags: gc.OK, Reguse: AX | DI, Regset: DI},
+	x86.ASTOSQ:    {Flags: gc.OK, Reguse: AX | DI, Regset: DI},
+	x86.ASTOSW:    {Flags: gc.OK, Reguse: AX | DI, Regset: DI},
+	obj.ADUFFZERO: {Flags: gc.OK, Reguse: X0 | DI, Regset: DI},
+	x86.ASUBB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.ASUBL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.ASUBQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.ASUBW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.ASUBSD:    {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
+	x86.ASUBSS:    {Flags: gc.SizeF | gc.LeftRead | RightRdwr},
+	x86.ATESTB:    {Flags: gc.SizeB | gc.LeftRead | gc.RightRead | gc.SetCarry},
+	x86.ATESTL:    {Flags: gc.SizeL | gc.LeftRead | gc.RightRead | gc.SetCarry},
+	x86.ATESTQ:    {Flags: gc.SizeQ | gc.LeftRead | gc.RightRead | gc.SetCarry},
+	x86.ATESTW:    {Flags: gc.SizeW | gc.LeftRead | gc.RightRead | gc.SetCarry},
+	x86.AUCOMISD:  {Flags: gc.SizeD | gc.LeftRead | gc.RightRead},
+	x86.AUCOMISS:  {Flags: gc.SizeF | gc.LeftRead | gc.RightRead},
+	x86.AXCHGB:    {Flags: gc.SizeB | LeftRdwr | RightRdwr},
+	x86.AXCHGL:    {Flags: gc.SizeL | LeftRdwr | RightRdwr},
+	x86.AXCHGQ:    {Flags: gc.SizeQ | LeftRdwr | RightRdwr},
+	x86.AXCHGW:    {Flags: gc.SizeW | LeftRdwr | RightRdwr},
+	x86.AXORB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AXORL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AXORQ:     {Flags: gc.SizeQ | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AXORW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AXORPS:    {Flags: gc.LeftRead | RightRdwr},
 }
 
 func progflags(p *obj.Prog) uint32 {
@@ -264,7 +267,7 @@ func proginfo(p *obj.Prog) {
 	info := &p.Info
 	*info = progtable[p.As]
 	if info.Flags == 0 {
-		gc.Fatal("unknown instruction %v", p)
+		gc.Fatalf("unknown instruction %v", p)
 	}
 
 	if (info.Flags&gc.ShiftCX != 0) && p.From.Type != obj.TYPE_CONST {
diff --git a/src/cmd/compile/internal/amd64/reg.go b/src/cmd/compile/internal/amd64/reg.go
index 8fab639..60822fb 100644
--- a/src/cmd/compile/internal/amd64/reg.go
+++ b/src/cmd/compile/internal/amd64/reg.go
@@ -107,6 +107,7 @@ const (
 	DI  = 1 << (x86.REG_DI - x86.REG_AX)
 	SI  = 1 << (x86.REG_SI - x86.REG_AX)
 	R15 = 1 << (x86.REG_R15 - x86.REG_AX)
+	X0  = 1 << 16
 )
 
 func RtoB(r int) uint64 {
diff --git a/src/cmd/compile/internal/arm/cgen.go b/src/cmd/compile/internal/arm/cgen.go
index 8ea6c5f..289da5d 100644
--- a/src/cmd/compile/internal/arm/cgen.go
+++ b/src/cmd/compile/internal/arm/cgen.go
@@ -63,7 +63,7 @@ func blockcopy(n, res *gc.Node, osrc, odst, w int64) {
 	var op int
 	switch align {
 	default:
-		gc.Fatal("sgen: invalid alignment %d for %v", align, n.Type)
+		gc.Fatalf("sgen: invalid alignment %d for %v", align, n.Type)
 
 	case 1:
 		op = arm.AMOVB
@@ -76,12 +76,12 @@ func blockcopy(n, res *gc.Node, osrc, odst, w int64) {
 	}
 
 	if w%int64(align) != 0 {
-		gc.Fatal("sgen: unaligned size %d (align=%d) for %v", w, align, n.Type)
+		gc.Fatalf("sgen: unaligned size %d (align=%d) for %v", w, align, n.Type)
 	}
 	c := int32(w / int64(align))
 
 	if osrc%int64(align) != 0 || odst%int64(align) != 0 {
-		gc.Fatal("sgen: unaligned offset src %d or dst %d (align %d)", osrc, odst, align)
+		gc.Fatalf("sgen: unaligned offset src %d or dst %d (align %d)", osrc, odst, align)
 	}
 
 	// if we are copying forward on the stack and
@@ -205,12 +205,7 @@ func blockcopy(n, res *gc.Node, osrc, odst, w int64) {
 		gc.Regfree(&nend)
 	} else {
 		var p *obj.Prog
-		for {
-			tmp14 := c
-			c--
-			if tmp14 <= 0 {
-				break
-			}
+		for ; c > 0; c-- {
 			p = gins(op, &src, &tmp)
 			p.From.Type = obj.TYPE_MEM
 			p.From.Offset = int64(dir)
diff --git a/src/cmd/compile/internal/arm/cgen64.go b/src/cmd/compile/internal/arm/cgen64.go
index cc969b8..d46d5a8 100644
--- a/src/cmd/compile/internal/arm/cgen64.go
+++ b/src/cmd/compile/internal/arm/cgen64.go
@@ -19,7 +19,7 @@ func cgen64(n *gc.Node, res *gc.Node) {
 	if res.Op != gc.OINDREG && res.Op != gc.ONAME {
 		gc.Dump("n", n)
 		gc.Dump("res", res)
-		gc.Fatal("cgen64 %v of %v", gc.Oconv(int(n.Op), 0), gc.Oconv(int(res.Op), 0))
+		gc.Fatalf("cgen64 %v of %v", gc.Oconv(int(n.Op), 0), gc.Oconv(int(res.Op), 0))
 	}
 
 	l := n.Left
@@ -35,7 +35,7 @@ func cgen64(n *gc.Node, res *gc.Node) {
 	split64(l, &lo1, &hi1)
 	switch n.Op {
 	default:
-		gc.Fatal("cgen64 %v", gc.Oconv(int(n.Op), 0))
+		gc.Fatalf("cgen64 %v", gc.Oconv(int(n.Op), 0))
 
 	case gc.OMINUS:
 		var lo2 gc.Node
@@ -129,7 +129,7 @@ func cgen64(n *gc.Node, res *gc.Node) {
 	// Do op.  Leave result in ah:al.
 	switch n.Op {
 	default:
-		gc.Fatal("cgen64: not implemented: %v\n", n)
+		gc.Fatalf("cgen64: not implemented: %v\n", n)
 
 		// TODO: Constants
 	case gc.OADD:
@@ -741,9 +741,9 @@ func cgen64(n *gc.Node, res *gc.Node) {
 		gins(arm.AMOVW, &lo1, &al)
 		gins(arm.AMOVW, &hi1, &ah)
 		gins(arm.AMOVW, &lo2, &n1)
-		gins(optoas(int(n.Op), lo1.Type), &n1, &al)
+		gins(optoas(n.Op, lo1.Type), &n1, &al)
 		gins(arm.AMOVW, &hi2, &n1)
-		gins(optoas(int(n.Op), lo1.Type), &n1, &ah)
+		gins(optoas(n.Op, lo1.Type), &n1, &ah)
 		gc.Regfree(&n1)
 	}
 
@@ -767,7 +767,7 @@ func cgen64(n *gc.Node, res *gc.Node) {
  * generate comparison of nl, nr, both 64-bit.
  * nl is memory; nr is constant or memory.
  */
-func cmp64(nl *gc.Node, nr *gc.Node, op int, likely int, to *obj.Prog) {
+func cmp64(nl *gc.Node, nr *gc.Node, op gc.Op, likely int, to *obj.Prog) {
 	var lo1 gc.Node
 	var hi1 gc.Node
 	var lo2 gc.Node
@@ -793,7 +793,7 @@ func cmp64(nl *gc.Node, nr *gc.Node, op int, likely int, to *obj.Prog) {
 	var br *obj.Prog
 	switch op {
 	default:
-		gc.Fatal("cmp64 %v %v", gc.Oconv(int(op), 0), t)
+		gc.Fatalf("cmp64 %v %v", gc.Oconv(int(op), 0), t)
 
 		// cmp hi
 	// bne L
diff --git a/src/cmd/compile/internal/arm/galign.go b/src/cmd/compile/internal/arm/galign.go
index 60a39d3..58c7f7b 100644
--- a/src/cmd/compile/internal/arm/galign.go
+++ b/src/cmd/compile/internal/arm/galign.go
@@ -26,9 +26,9 @@ var MAXWIDTH int64 = (1 << 32) - 1
  * int, uint, and uintptr
  */
 var typedefs = []gc.Typedef{
-	gc.Typedef{"int", gc.TINT, gc.TINT32},
-	gc.Typedef{"uint", gc.TUINT, gc.TUINT32},
-	gc.Typedef{"uintptr", gc.TUINTPTR, gc.TUINT32},
+	{"int", gc.TINT, gc.TINT32},
+	{"uint", gc.TUINT, gc.TUINT32},
+	{"uintptr", gc.TUINTPTR, gc.TUINT32},
 }
 
 func betypeinit() {
diff --git a/src/cmd/compile/internal/arm/ggen.go b/src/cmd/compile/internal/arm/ggen.go
index 2d19d75..517b4f4 100644
--- a/src/cmd/compile/internal/arm/ggen.go
+++ b/src/cmd/compile/internal/arm/ggen.go
@@ -34,10 +34,10 @@ func defframe(ptxt *obj.Prog) {
 			continue
 		}
 		if n.Class != gc.PAUTO {
-			gc.Fatal("needzero class %d", n.Class)
+			gc.Fatalf("needzero class %d", n.Class)
 		}
 		if n.Type.Width%int64(gc.Widthptr) != 0 || n.Xoffset%int64(gc.Widthptr) != 0 || n.Type.Width == 0 {
-			gc.Fatal("var %v has size %d offset %d", gc.Nconv(n, obj.FmtLong), int(n.Type.Width), int(n.Xoffset))
+			gc.Fatalf("var %v has size %d offset %d", gc.Nconv(n, obj.FmtLong), int(n.Type.Width), int(n.Xoffset))
 		}
 		if lo != hi && n.Xoffset+n.Type.Width >= lo-int64(2*gc.Widthptr) {
 			// merge with range we already have
@@ -120,9 +120,7 @@ func appendpp(p *obj.Prog, as int, ftype int, freg int, foffset int32, ttype int
  */
 func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	if nl.Ullman < nr.Ullman {
-		tmp := nl
-		nl = nr
-		nr = tmp
+		nl, nr = nr, nl
 	}
 
 	t := nl.Type
@@ -162,7 +160,7 @@ func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
 		p.To.Offset = int64(n2.Reg)
 
 	default:
-		gc.Fatal("cgen_hmul %v", t)
+		gc.Fatalf("cgen_hmul %v", t)
 	}
 
 	gc.Cgen(&n1, res)
@@ -175,9 +173,9 @@ func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
  *	res = nl << nr
  *	res = nl >> nr
  */
-func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+func cgen_shift(op gc.Op, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	if nl.Type.Width > 4 {
-		gc.Fatal("cgen_shift %v", nl.Type)
+		gc.Fatalf("cgen_shift %v", nl.Type)
 	}
 
 	w := int(nl.Type.Width * 8)
@@ -429,7 +427,7 @@ func expandchecks(firstp *obj.Prog) {
 			gc.Warnl(int(p.Lineno), "generated nil check")
 		}
 		if p.From.Type != obj.TYPE_REG {
-			gc.Fatal("invalid nil check %v", p)
+			gc.Fatalf("invalid nil check %v", p)
 		}
 		reg = int(p.From.Reg)
 
@@ -479,7 +477,7 @@ func ginscon(as int, c int64, n *gc.Node) {
 	gc.Regfree(&n2)
 }
 
-func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+func ginscmp(op gc.Op, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
 	if gc.Isint[t.Etype] && n1.Op == gc.OLITERAL && n1.Int() == 0 && n2.Op != gc.OLITERAL {
 		op = gc.Brrev(op)
 		n1, n2 = n2, n1
diff --git a/src/cmd/compile/internal/arm/gsubr.go b/src/cmd/compile/internal/arm/gsubr.go
index a0a7ba2..108d78a 100644
--- a/src/cmd/compile/internal/arm/gsubr.go
+++ b/src/cmd/compile/internal/arm/gsubr.go
@@ -66,11 +66,11 @@ var nsclean int
  */
 func split64(n *gc.Node, lo *gc.Node, hi *gc.Node) {
 	if !gc.Is64(n.Type) {
-		gc.Fatal("split64 %v", n.Type)
+		gc.Fatalf("split64 %v", n.Type)
 	}
 
 	if nsclean >= len(sclean) {
-		gc.Fatal("split64 clean")
+		gc.Fatalf("split64 clean")
 	}
 	sclean[nsclean].Op = gc.OEMPTY
 	nsclean++
@@ -125,7 +125,7 @@ func split64(n *gc.Node, lo *gc.Node, hi *gc.Node) {
 
 func splitclean() {
 	if nsclean <= 0 {
-		gc.Fatal("splitclean")
+		gc.Fatalf("splitclean")
 	}
 	nsclean--
 	if sclean[nsclean].Op != gc.OEMPTY {
@@ -204,7 +204,7 @@ func gmove(f *gc.Node, t *gc.Node) {
 	switch uint32(ft)<<16 | uint32(tt) {
 	default:
 		// should not happen
-		gc.Fatal("gmove %v -> %v", f, t)
+		gc.Fatalf("gmove %v -> %v", f, t)
 		return
 
 		/*
@@ -546,7 +546,7 @@ func gmove(f *gc.Node, t *gc.Node) {
 
 	case gc.TUINT64<<16 | gc.TFLOAT32,
 		gc.TUINT64<<16 | gc.TFLOAT64:
-		gc.Fatal("gmove UINT64, TFLOAT not implemented")
+		gc.Fatalf("gmove UINT64, TFLOAT not implemented")
 		return
 
 		/*
@@ -641,7 +641,7 @@ func gins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
 	//	int32 v;
 
 	if f != nil && f.Op == gc.OINDEX {
-		gc.Fatal("gins OINDEX not implemented")
+		gc.Fatalf("gins OINDEX not implemented")
 	}
 
 	//		gc.Regalloc(&nod, &regnode, Z);
@@ -651,7 +651,7 @@ func gins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
 	//		idx.reg = nod.reg;
 	//		gc.Regfree(&nod);
 	if t != nil && t.Op == gc.OINDEX {
-		gc.Fatal("gins OINDEX not implemented")
+		gc.Fatalf("gins OINDEX not implemented")
 	}
 
 	//		gc.Regalloc(&nod, &regnode, Z);
@@ -677,7 +677,7 @@ func gins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
 				/* generate a comparison
 				TODO(kaib): one of the args can actually be a small constant. relax the constraint and fix call sites.
 				*/
-				gc.Fatal("bad operands to gcmp")
+				gc.Fatalf("bad operands to gcmp")
 			}
 			p.From = p.To
 			p.To = obj.Addr{}
@@ -686,22 +686,22 @@ func gins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
 
 	case arm.AMULU:
 		if f != nil && f.Op != gc.OREGISTER {
-			gc.Fatal("bad operands to mul")
+			gc.Fatalf("bad operands to mul")
 		}
 
 	case arm.AMOVW:
 		if (p.From.Type == obj.TYPE_MEM || p.From.Type == obj.TYPE_ADDR || p.From.Type == obj.TYPE_CONST) && (p.To.Type == obj.TYPE_MEM || p.To.Type == obj.TYPE_ADDR) {
-			gc.Fatal("gins double memory")
+			gc.Fatalf("gins double memory")
 		}
 
 	case arm.AADD:
 		if p.To.Type == obj.TYPE_MEM {
-			gc.Fatal("gins arith to mem")
+			gc.Fatalf("gins arith to mem")
 		}
 
 	case arm.ARSB:
 		if p.From.Type == obj.TYPE_NONE {
-			gc.Fatal("rsb with no from")
+			gc.Fatalf("rsb with no from")
 		}
 	}
 
@@ -719,9 +719,9 @@ func raddr(n *gc.Node, p *obj.Prog) {
 	gc.Naddr(&a, n)
 	if a.Type != obj.TYPE_REG {
 		if n != nil {
-			gc.Fatal("bad in raddr: %v", gc.Oconv(int(n.Op), 0))
+			gc.Fatalf("bad in raddr: %v", gc.Oconv(int(n.Op), 0))
 		} else {
-			gc.Fatal("bad in raddr: <null>")
+			gc.Fatalf("bad in raddr: <null>")
 		}
 		p.Reg = 0
 	} else {
@@ -734,7 +734,7 @@ func raddr(n *gc.Node, p *obj.Prog) {
  */
 func gshift(as int, lhs *gc.Node, stype int32, sval int32, rhs *gc.Node) *obj.Prog {
 	if sval <= 0 || sval > 32 {
-		gc.Fatal("bad shift value: %d", sval)
+		gc.Fatalf("bad shift value: %d", sval)
 	}
 
 	sval = sval & 0x1f
@@ -757,15 +757,40 @@ func gregshift(as int, lhs *gc.Node, stype int32, reg *gc.Node, rhs *gc.Node) *o
 /*
  * return Axxx for Oxxx on type t.
  */
-func optoas(op int, t *gc.Type) int {
+func optoas(op gc.Op, t *gc.Type) int {
 	if t == nil {
-		gc.Fatal("optoas: t is nil")
+		gc.Fatalf("optoas: t is nil")
 	}
 
+	// avoid constant conversions in switches below
+	const (
+		OMINUS_ = uint32(gc.OMINUS) << 16
+		OLSH_   = uint32(gc.OLSH) << 16
+		ORSH_   = uint32(gc.ORSH) << 16
+		OADD_   = uint32(gc.OADD) << 16
+		OSUB_   = uint32(gc.OSUB) << 16
+		OMUL_   = uint32(gc.OMUL) << 16
+		ODIV_   = uint32(gc.ODIV) << 16
+		OMOD_   = uint32(gc.OMOD) << 16
+		OOR_    = uint32(gc.OOR) << 16
+		OAND_   = uint32(gc.OAND) << 16
+		OXOR_   = uint32(gc.OXOR) << 16
+		OEQ_    = uint32(gc.OEQ) << 16
+		ONE_    = uint32(gc.ONE) << 16
+		OLT_    = uint32(gc.OLT) << 16
+		OLE_    = uint32(gc.OLE) << 16
+		OGE_    = uint32(gc.OGE) << 16
+		OGT_    = uint32(gc.OGT) << 16
+		OCMP_   = uint32(gc.OCMP) << 16
+		OPS_    = uint32(gc.OPS) << 16
+		OAS_    = uint32(gc.OAS) << 16
+		OSQRT_  = uint32(gc.OSQRT) << 16
+	)
+
 	a := obj.AXXX
 	switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) {
 	default:
-		gc.Fatal("optoas: no entry %v-%v etype %v simtype %v", gc.Oconv(int(op), 0), t, gc.Types[t.Etype], gc.Types[gc.Simtype[t.Etype]])
+		gc.Fatalf("optoas: no entry %v-%v etype %v simtype %v", gc.Oconv(int(op), 0), t, gc.Types[t.Etype], gc.Types[gc.Simtype[t.Etype]])
 
 		/*	case CASE(OADDR, TPTR32):
 				a = ALEAL;
@@ -776,261 +801,261 @@ func optoas(op int, t *gc.Type) int {
 				break;
 		*/
 	// TODO(kaib): make sure the conditional branches work on all edge cases
-	case gc.OEQ<<16 | gc.TBOOL,
-		gc.OEQ<<16 | gc.TINT8,
-		gc.OEQ<<16 | gc.TUINT8,
-		gc.OEQ<<16 | gc.TINT16,
-		gc.OEQ<<16 | gc.TUINT16,
-		gc.OEQ<<16 | gc.TINT32,
-		gc.OEQ<<16 | gc.TUINT32,
-		gc.OEQ<<16 | gc.TINT64,
-		gc.OEQ<<16 | gc.TUINT64,
-		gc.OEQ<<16 | gc.TPTR32,
-		gc.OEQ<<16 | gc.TPTR64,
-		gc.OEQ<<16 | gc.TFLOAT32,
-		gc.OEQ<<16 | gc.TFLOAT64:
+	case OEQ_ | gc.TBOOL,
+		OEQ_ | gc.TINT8,
+		OEQ_ | gc.TUINT8,
+		OEQ_ | gc.TINT16,
+		OEQ_ | gc.TUINT16,
+		OEQ_ | gc.TINT32,
+		OEQ_ | gc.TUINT32,
+		OEQ_ | gc.TINT64,
+		OEQ_ | gc.TUINT64,
+		OEQ_ | gc.TPTR32,
+		OEQ_ | gc.TPTR64,
+		OEQ_ | gc.TFLOAT32,
+		OEQ_ | gc.TFLOAT64:
 		a = arm.ABEQ
 
-	case gc.ONE<<16 | gc.TBOOL,
-		gc.ONE<<16 | gc.TINT8,
-		gc.ONE<<16 | gc.TUINT8,
-		gc.ONE<<16 | gc.TINT16,
-		gc.ONE<<16 | gc.TUINT16,
-		gc.ONE<<16 | gc.TINT32,
-		gc.ONE<<16 | gc.TUINT32,
-		gc.ONE<<16 | gc.TINT64,
-		gc.ONE<<16 | gc.TUINT64,
-		gc.ONE<<16 | gc.TPTR32,
-		gc.ONE<<16 | gc.TPTR64,
-		gc.ONE<<16 | gc.TFLOAT32,
-		gc.ONE<<16 | gc.TFLOAT64:
+	case ONE_ | gc.TBOOL,
+		ONE_ | gc.TINT8,
+		ONE_ | gc.TUINT8,
+		ONE_ | gc.TINT16,
+		ONE_ | gc.TUINT16,
+		ONE_ | gc.TINT32,
+		ONE_ | gc.TUINT32,
+		ONE_ | gc.TINT64,
+		ONE_ | gc.TUINT64,
+		ONE_ | gc.TPTR32,
+		ONE_ | gc.TPTR64,
+		ONE_ | gc.TFLOAT32,
+		ONE_ | gc.TFLOAT64:
 		a = arm.ABNE
 
-	case gc.OLT<<16 | gc.TINT8,
-		gc.OLT<<16 | gc.TINT16,
-		gc.OLT<<16 | gc.TINT32,
-		gc.OLT<<16 | gc.TINT64,
-		gc.OLT<<16 | gc.TFLOAT32,
-		gc.OLT<<16 | gc.TFLOAT64:
+	case OLT_ | gc.TINT8,
+		OLT_ | gc.TINT16,
+		OLT_ | gc.TINT32,
+		OLT_ | gc.TINT64,
+		OLT_ | gc.TFLOAT32,
+		OLT_ | gc.TFLOAT64:
 		a = arm.ABLT
 
-	case gc.OLT<<16 | gc.TUINT8,
-		gc.OLT<<16 | gc.TUINT16,
-		gc.OLT<<16 | gc.TUINT32,
-		gc.OLT<<16 | gc.TUINT64:
+	case OLT_ | gc.TUINT8,
+		OLT_ | gc.TUINT16,
+		OLT_ | gc.TUINT32,
+		OLT_ | gc.TUINT64:
 		a = arm.ABLO
 
-	case gc.OLE<<16 | gc.TINT8,
-		gc.OLE<<16 | gc.TINT16,
-		gc.OLE<<16 | gc.TINT32,
-		gc.OLE<<16 | gc.TINT64,
-		gc.OLE<<16 | gc.TFLOAT32,
-		gc.OLE<<16 | gc.TFLOAT64:
+	case OLE_ | gc.TINT8,
+		OLE_ | gc.TINT16,
+		OLE_ | gc.TINT32,
+		OLE_ | gc.TINT64,
+		OLE_ | gc.TFLOAT32,
+		OLE_ | gc.TFLOAT64:
 		a = arm.ABLE
 
-	case gc.OLE<<16 | gc.TUINT8,
-		gc.OLE<<16 | gc.TUINT16,
-		gc.OLE<<16 | gc.TUINT32,
-		gc.OLE<<16 | gc.TUINT64:
+	case OLE_ | gc.TUINT8,
+		OLE_ | gc.TUINT16,
+		OLE_ | gc.TUINT32,
+		OLE_ | gc.TUINT64:
 		a = arm.ABLS
 
-	case gc.OGT<<16 | gc.TINT8,
-		gc.OGT<<16 | gc.TINT16,
-		gc.OGT<<16 | gc.TINT32,
-		gc.OGT<<16 | gc.TINT64,
-		gc.OGT<<16 | gc.TFLOAT32,
-		gc.OGT<<16 | gc.TFLOAT64:
+	case OGT_ | gc.TINT8,
+		OGT_ | gc.TINT16,
+		OGT_ | gc.TINT32,
+		OGT_ | gc.TINT64,
+		OGT_ | gc.TFLOAT32,
+		OGT_ | gc.TFLOAT64:
 		a = arm.ABGT
 
-	case gc.OGT<<16 | gc.TUINT8,
-		gc.OGT<<16 | gc.TUINT16,
-		gc.OGT<<16 | gc.TUINT32,
-		gc.OGT<<16 | gc.TUINT64:
+	case OGT_ | gc.TUINT8,
+		OGT_ | gc.TUINT16,
+		OGT_ | gc.TUINT32,
+		OGT_ | gc.TUINT64:
 		a = arm.ABHI
 
-	case gc.OGE<<16 | gc.TINT8,
-		gc.OGE<<16 | gc.TINT16,
-		gc.OGE<<16 | gc.TINT32,
-		gc.OGE<<16 | gc.TINT64,
-		gc.OGE<<16 | gc.TFLOAT32,
-		gc.OGE<<16 | gc.TFLOAT64:
+	case OGE_ | gc.TINT8,
+		OGE_ | gc.TINT16,
+		OGE_ | gc.TINT32,
+		OGE_ | gc.TINT64,
+		OGE_ | gc.TFLOAT32,
+		OGE_ | gc.TFLOAT64:
 		a = arm.ABGE
 
-	case gc.OGE<<16 | gc.TUINT8,
-		gc.OGE<<16 | gc.TUINT16,
-		gc.OGE<<16 | gc.TUINT32,
-		gc.OGE<<16 | gc.TUINT64:
+	case OGE_ | gc.TUINT8,
+		OGE_ | gc.TUINT16,
+		OGE_ | gc.TUINT32,
+		OGE_ | gc.TUINT64:
 		a = arm.ABHS
 
-	case gc.OCMP<<16 | gc.TBOOL,
-		gc.OCMP<<16 | gc.TINT8,
-		gc.OCMP<<16 | gc.TUINT8,
-		gc.OCMP<<16 | gc.TINT16,
-		gc.OCMP<<16 | gc.TUINT16,
-		gc.OCMP<<16 | gc.TINT32,
-		gc.OCMP<<16 | gc.TUINT32,
-		gc.OCMP<<16 | gc.TPTR32:
+	case OCMP_ | gc.TBOOL,
+		OCMP_ | gc.TINT8,
+		OCMP_ | gc.TUINT8,
+		OCMP_ | gc.TINT16,
+		OCMP_ | gc.TUINT16,
+		OCMP_ | gc.TINT32,
+		OCMP_ | gc.TUINT32,
+		OCMP_ | gc.TPTR32:
 		a = arm.ACMP
 
-	case gc.OCMP<<16 | gc.TFLOAT32:
+	case OCMP_ | gc.TFLOAT32:
 		a = arm.ACMPF
 
-	case gc.OCMP<<16 | gc.TFLOAT64:
+	case OCMP_ | gc.TFLOAT64:
 		a = arm.ACMPD
 
-	case gc.OPS<<16 | gc.TFLOAT32,
-		gc.OPS<<16 | gc.TFLOAT64:
+	case OPS_ | gc.TFLOAT32,
+		OPS_ | gc.TFLOAT64:
 		a = arm.ABVS
 
-	case gc.OAS<<16 | gc.TBOOL:
+	case OAS_ | gc.TBOOL:
 		a = arm.AMOVB
 
-	case gc.OAS<<16 | gc.TINT8:
+	case OAS_ | gc.TINT8:
 		a = arm.AMOVBS
 
-	case gc.OAS<<16 | gc.TUINT8:
+	case OAS_ | gc.TUINT8:
 		a = arm.AMOVBU
 
-	case gc.OAS<<16 | gc.TINT16:
+	case OAS_ | gc.TINT16:
 		a = arm.AMOVHS
 
-	case gc.OAS<<16 | gc.TUINT16:
+	case OAS_ | gc.TUINT16:
 		a = arm.AMOVHU
 
-	case gc.OAS<<16 | gc.TINT32,
-		gc.OAS<<16 | gc.TUINT32,
-		gc.OAS<<16 | gc.TPTR32:
+	case OAS_ | gc.TINT32,
+		OAS_ | gc.TUINT32,
+		OAS_ | gc.TPTR32:
 		a = arm.AMOVW
 
-	case gc.OAS<<16 | gc.TFLOAT32:
+	case OAS_ | gc.TFLOAT32:
 		a = arm.AMOVF
 
-	case gc.OAS<<16 | gc.TFLOAT64:
+	case OAS_ | gc.TFLOAT64:
 		a = arm.AMOVD
 
-	case gc.OADD<<16 | gc.TINT8,
-		gc.OADD<<16 | gc.TUINT8,
-		gc.OADD<<16 | gc.TINT16,
-		gc.OADD<<16 | gc.TUINT16,
-		gc.OADD<<16 | gc.TINT32,
-		gc.OADD<<16 | gc.TUINT32,
-		gc.OADD<<16 | gc.TPTR32:
+	case OADD_ | gc.TINT8,
+		OADD_ | gc.TUINT8,
+		OADD_ | gc.TINT16,
+		OADD_ | gc.TUINT16,
+		OADD_ | gc.TINT32,
+		OADD_ | gc.TUINT32,
+		OADD_ | gc.TPTR32:
 		a = arm.AADD
 
-	case gc.OADD<<16 | gc.TFLOAT32:
+	case OADD_ | gc.TFLOAT32:
 		a = arm.AADDF
 
-	case gc.OADD<<16 | gc.TFLOAT64:
+	case OADD_ | gc.TFLOAT64:
 		a = arm.AADDD
 
-	case gc.OSUB<<16 | gc.TINT8,
-		gc.OSUB<<16 | gc.TUINT8,
-		gc.OSUB<<16 | gc.TINT16,
-		gc.OSUB<<16 | gc.TUINT16,
-		gc.OSUB<<16 | gc.TINT32,
-		gc.OSUB<<16 | gc.TUINT32,
-		gc.OSUB<<16 | gc.TPTR32:
+	case OSUB_ | gc.TINT8,
+		OSUB_ | gc.TUINT8,
+		OSUB_ | gc.TINT16,
+		OSUB_ | gc.TUINT16,
+		OSUB_ | gc.TINT32,
+		OSUB_ | gc.TUINT32,
+		OSUB_ | gc.TPTR32:
 		a = arm.ASUB
 
-	case gc.OSUB<<16 | gc.TFLOAT32:
+	case OSUB_ | gc.TFLOAT32:
 		a = arm.ASUBF
 
-	case gc.OSUB<<16 | gc.TFLOAT64:
+	case OSUB_ | gc.TFLOAT64:
 		a = arm.ASUBD
 
-	case gc.OMINUS<<16 | gc.TINT8,
-		gc.OMINUS<<16 | gc.TUINT8,
-		gc.OMINUS<<16 | gc.TINT16,
-		gc.OMINUS<<16 | gc.TUINT16,
-		gc.OMINUS<<16 | gc.TINT32,
-		gc.OMINUS<<16 | gc.TUINT32,
-		gc.OMINUS<<16 | gc.TPTR32:
+	case OMINUS_ | gc.TINT8,
+		OMINUS_ | gc.TUINT8,
+		OMINUS_ | gc.TINT16,
+		OMINUS_ | gc.TUINT16,
+		OMINUS_ | gc.TINT32,
+		OMINUS_ | gc.TUINT32,
+		OMINUS_ | gc.TPTR32:
 		a = arm.ARSB
 
-	case gc.OAND<<16 | gc.TINT8,
-		gc.OAND<<16 | gc.TUINT8,
-		gc.OAND<<16 | gc.TINT16,
-		gc.OAND<<16 | gc.TUINT16,
-		gc.OAND<<16 | gc.TINT32,
-		gc.OAND<<16 | gc.TUINT32,
-		gc.OAND<<16 | gc.TPTR32:
+	case OAND_ | gc.TINT8,
+		OAND_ | gc.TUINT8,
+		OAND_ | gc.TINT16,
+		OAND_ | gc.TUINT16,
+		OAND_ | gc.TINT32,
+		OAND_ | gc.TUINT32,
+		OAND_ | gc.TPTR32:
 		a = arm.AAND
 
-	case gc.OOR<<16 | gc.TINT8,
-		gc.OOR<<16 | gc.TUINT8,
-		gc.OOR<<16 | gc.TINT16,
-		gc.OOR<<16 | gc.TUINT16,
-		gc.OOR<<16 | gc.TINT32,
-		gc.OOR<<16 | gc.TUINT32,
-		gc.OOR<<16 | gc.TPTR32:
+	case OOR_ | gc.TINT8,
+		OOR_ | gc.TUINT8,
+		OOR_ | gc.TINT16,
+		OOR_ | gc.TUINT16,
+		OOR_ | gc.TINT32,
+		OOR_ | gc.TUINT32,
+		OOR_ | gc.TPTR32:
 		a = arm.AORR
 
-	case gc.OXOR<<16 | gc.TINT8,
-		gc.OXOR<<16 | gc.TUINT8,
-		gc.OXOR<<16 | gc.TINT16,
-		gc.OXOR<<16 | gc.TUINT16,
-		gc.OXOR<<16 | gc.TINT32,
-		gc.OXOR<<16 | gc.TUINT32,
-		gc.OXOR<<16 | gc.TPTR32:
+	case OXOR_ | gc.TINT8,
+		OXOR_ | gc.TUINT8,
+		OXOR_ | gc.TINT16,
+		OXOR_ | gc.TUINT16,
+		OXOR_ | gc.TINT32,
+		OXOR_ | gc.TUINT32,
+		OXOR_ | gc.TPTR32:
 		a = arm.AEOR
 
-	case gc.OLSH<<16 | gc.TINT8,
-		gc.OLSH<<16 | gc.TUINT8,
-		gc.OLSH<<16 | gc.TINT16,
-		gc.OLSH<<16 | gc.TUINT16,
-		gc.OLSH<<16 | gc.TINT32,
-		gc.OLSH<<16 | gc.TUINT32,
-		gc.OLSH<<16 | gc.TPTR32:
+	case OLSH_ | gc.TINT8,
+		OLSH_ | gc.TUINT8,
+		OLSH_ | gc.TINT16,
+		OLSH_ | gc.TUINT16,
+		OLSH_ | gc.TINT32,
+		OLSH_ | gc.TUINT32,
+		OLSH_ | gc.TPTR32:
 		a = arm.ASLL
 
-	case gc.ORSH<<16 | gc.TUINT8,
-		gc.ORSH<<16 | gc.TUINT16,
-		gc.ORSH<<16 | gc.TUINT32,
-		gc.ORSH<<16 | gc.TPTR32:
+	case ORSH_ | gc.TUINT8,
+		ORSH_ | gc.TUINT16,
+		ORSH_ | gc.TUINT32,
+		ORSH_ | gc.TPTR32:
 		a = arm.ASRL
 
-	case gc.ORSH<<16 | gc.TINT8,
-		gc.ORSH<<16 | gc.TINT16,
-		gc.ORSH<<16 | gc.TINT32:
+	case ORSH_ | gc.TINT8,
+		ORSH_ | gc.TINT16,
+		ORSH_ | gc.TINT32:
 		a = arm.ASRA
 
-	case gc.OMUL<<16 | gc.TUINT8,
-		gc.OMUL<<16 | gc.TUINT16,
-		gc.OMUL<<16 | gc.TUINT32,
-		gc.OMUL<<16 | gc.TPTR32:
+	case OMUL_ | gc.TUINT8,
+		OMUL_ | gc.TUINT16,
+		OMUL_ | gc.TUINT32,
+		OMUL_ | gc.TPTR32:
 		a = arm.AMULU
 
-	case gc.OMUL<<16 | gc.TINT8,
-		gc.OMUL<<16 | gc.TINT16,
-		gc.OMUL<<16 | gc.TINT32:
+	case OMUL_ | gc.TINT8,
+		OMUL_ | gc.TINT16,
+		OMUL_ | gc.TINT32:
 		a = arm.AMUL
 
-	case gc.OMUL<<16 | gc.TFLOAT32:
+	case OMUL_ | gc.TFLOAT32:
 		a = arm.AMULF
 
-	case gc.OMUL<<16 | gc.TFLOAT64:
+	case OMUL_ | gc.TFLOAT64:
 		a = arm.AMULD
 
-	case gc.ODIV<<16 | gc.TUINT8,
-		gc.ODIV<<16 | gc.TUINT16,
-		gc.ODIV<<16 | gc.TUINT32,
-		gc.ODIV<<16 | gc.TPTR32:
+	case ODIV_ | gc.TUINT8,
+		ODIV_ | gc.TUINT16,
+		ODIV_ | gc.TUINT32,
+		ODIV_ | gc.TPTR32:
 		a = arm.ADIVU
 
-	case gc.ODIV<<16 | gc.TINT8,
-		gc.ODIV<<16 | gc.TINT16,
-		gc.ODIV<<16 | gc.TINT32:
+	case ODIV_ | gc.TINT8,
+		ODIV_ | gc.TINT16,
+		ODIV_ | gc.TINT32:
 		a = arm.ADIV
 
-	case gc.OMOD<<16 | gc.TUINT8,
-		gc.OMOD<<16 | gc.TUINT16,
-		gc.OMOD<<16 | gc.TUINT32,
-		gc.OMOD<<16 | gc.TPTR32:
+	case OMOD_ | gc.TUINT8,
+		OMOD_ | gc.TUINT16,
+		OMOD_ | gc.TUINT32,
+		OMOD_ | gc.TPTR32:
 		a = arm.AMODU
 
-	case gc.OMOD<<16 | gc.TINT8,
-		gc.OMOD<<16 | gc.TINT16,
-		gc.OMOD<<16 | gc.TINT32:
+	case OMOD_ | gc.TINT8,
+		OMOD_ | gc.TINT16,
+		OMOD_ | gc.TINT32:
 		a = arm.AMOD
 
 		//	case CASE(OEXTEND, TINT16):
@@ -1045,13 +1070,13 @@ func optoas(op int, t *gc.Type) int {
 	//		a = ACQO;
 	//		break;
 
-	case gc.ODIV<<16 | gc.TFLOAT32:
+	case ODIV_ | gc.TFLOAT32:
 		a = arm.ADIVF
 
-	case gc.ODIV<<16 | gc.TFLOAT64:
+	case ODIV_ | gc.TFLOAT64:
 		a = arm.ADIVD
 
-	case gc.OSQRT<<16 | gc.TFLOAT64:
+	case OSQRT_ | gc.TFLOAT64:
 		a = arm.ASQRTD
 	}
 
@@ -1188,7 +1213,7 @@ func sudoaddable(as int, n *gc.Node, a *obj.Addr) bool {
 
 		for i := 1; i < o; i++ {
 			if oary[i] >= 0 {
-				gc.Fatal("can't happen")
+				gc.Fatalf("can't happen")
 			}
 			gins(arm.AMOVW, &n1, reg)
 			gc.Cgen_checknil(reg)
diff --git a/src/cmd/compile/internal/arm/peep.go b/src/cmd/compile/internal/arm/peep.go
index 66eba41..bc49ebc 100644
--- a/src/cmd/compile/internal/arm/peep.go
+++ b/src/cmd/compile/internal/arm/peep.go
@@ -1198,7 +1198,6 @@ func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
 		arm.ACMPD,
 		arm.ACMP,
 		arm.ACMN,
-		arm.ACASE,
 		arm.ATST:
 		/* read,, */
 		if s != nil {
@@ -1366,7 +1365,9 @@ func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
 	case obj.APCDATA,
 		obj.AFUNCDATA,
 		obj.AVARDEF,
-		obj.AVARKILL:
+		obj.AVARKILL,
+		obj.AVARLIVE,
+		obj.AUSEFIELD:
 		return 0
 	}
 }
@@ -1560,9 +1561,7 @@ func predicable(p *obj.Prog) bool {
 		obj.ADATA,
 		obj.AGLOBL,
 		obj.ATEXT,
-		arm.AWORD,
-		arm.ABCASE,
-		arm.ACASE:
+		arm.AWORD:
 		return false
 	}
 
diff --git a/src/cmd/compile/internal/arm/prog.go b/src/cmd/compile/internal/arm/prog.go
index cdf9d29..81be77a 100644
--- a/src/cmd/compile/internal/arm/prog.go
+++ b/src/cmd/compile/internal/arm/prog.go
@@ -24,121 +24,122 @@ const (
 //
 // The table is formatted for 8-space tabs.
 var progtable = [arm.ALAST]obj.ProgInfo{
-	obj.ATYPE:     {gc.Pseudo | gc.Skip, 0, 0, 0},
-	obj.ATEXT:     {gc.Pseudo, 0, 0, 0},
-	obj.AFUNCDATA: {gc.Pseudo, 0, 0, 0},
-	obj.APCDATA:   {gc.Pseudo, 0, 0, 0},
-	obj.AUNDEF:    {gc.Break, 0, 0, 0},
-	obj.AUSEFIELD: {gc.OK, 0, 0, 0},
-	obj.ACHECKNIL: {gc.LeftRead, 0, 0, 0},
-	obj.AVARDEF:   {gc.Pseudo | gc.RightWrite, 0, 0, 0},
-	obj.AVARKILL:  {gc.Pseudo | gc.RightWrite, 0, 0, 0},
+	obj.ATYPE:     {Flags: gc.Pseudo | gc.Skip},
+	obj.ATEXT:     {Flags: gc.Pseudo},
+	obj.AFUNCDATA: {Flags: gc.Pseudo},
+	obj.APCDATA:   {Flags: gc.Pseudo},
+	obj.AUNDEF:    {Flags: gc.Break},
+	obj.AUSEFIELD: {Flags: gc.OK},
+	obj.ACHECKNIL: {Flags: gc.LeftRead},
+	obj.AVARDEF:   {Flags: gc.Pseudo | gc.RightWrite},
+	obj.AVARKILL:  {Flags: gc.Pseudo | gc.RightWrite},
+	obj.AVARLIVE:  {Flags: gc.Pseudo | gc.LeftRead},
 
 	// NOP is an internal no-op that also stands
 	// for USED and SET annotations, not the Intel opcode.
-	obj.ANOP: {gc.LeftRead | gc.RightWrite, 0, 0, 0},
+	obj.ANOP: {Flags: gc.LeftRead | gc.RightWrite},
 
 	// Integer.
-	arm.AADC:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm.AADD:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm.AAND:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm.ABIC:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm.ACMN:    {gc.SizeL | gc.LeftRead | gc.RightRead, 0, 0, 0},
-	arm.ACMP:    {gc.SizeL | gc.LeftRead | gc.RightRead, 0, 0, 0},
-	arm.ADIVU:   {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm.ADIV:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm.AEOR:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm.AMODU:   {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm.AMOD:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm.AMULALU: {gc.SizeL | gc.LeftRead | gc.RegRead | RightRdwr, 0, 0, 0},
-	arm.AMULAL:  {gc.SizeL | gc.LeftRead | gc.RegRead | RightRdwr, 0, 0, 0},
-	arm.AMULA:   {gc.SizeL | gc.LeftRead | gc.RegRead | RightRdwr, 0, 0, 0},
-	arm.AMULU:   {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm.AMUL:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm.AMULL:   {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm.AMULLU:  {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm.AMVN:    {gc.SizeL | gc.LeftRead | gc.RightWrite, 0, 0, 0},
-	arm.AORR:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm.ARSB:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm.ARSC:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm.ASBC:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm.ASLL:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm.ASRA:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm.ASRL:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm.ASUB:    {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm.ATEQ:    {gc.SizeL | gc.LeftRead | gc.RightRead, 0, 0, 0},
-	arm.ATST:    {gc.SizeL | gc.LeftRead | gc.RightRead, 0, 0, 0},
+	arm.AADC:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm.AADD:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm.AAND:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm.ABIC:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm.ACMN:    {Flags: gc.SizeL | gc.LeftRead | gc.RightRead},
+	arm.ACMP:    {Flags: gc.SizeL | gc.LeftRead | gc.RightRead},
+	arm.ADIVU:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm.ADIV:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm.AEOR:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm.AMODU:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm.AMOD:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm.AMULALU: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | RightRdwr},
+	arm.AMULAL:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | RightRdwr},
+	arm.AMULA:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | RightRdwr},
+	arm.AMULU:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm.AMUL:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm.AMULL:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm.AMULLU:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm.AMVN:    {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite},
+	arm.AORR:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm.ARSB:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm.ARSC:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm.ASBC:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm.ASLL:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm.ASRA:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm.ASRL:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm.ASUB:    {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm.ATEQ:    {Flags: gc.SizeL | gc.LeftRead | gc.RightRead},
+	arm.ATST:    {Flags: gc.SizeL | gc.LeftRead | gc.RightRead},
 
 	// Floating point.
-	arm.AADDD:  {gc.SizeD | gc.LeftRead | RightRdwr, 0, 0, 0},
-	arm.AADDF:  {gc.SizeF | gc.LeftRead | RightRdwr, 0, 0, 0},
-	arm.ACMPD:  {gc.SizeD | gc.LeftRead | gc.RightRead, 0, 0, 0},
-	arm.ACMPF:  {gc.SizeF | gc.LeftRead | gc.RightRead, 0, 0, 0},
-	arm.ADIVD:  {gc.SizeD | gc.LeftRead | RightRdwr, 0, 0, 0},
-	arm.ADIVF:  {gc.SizeF | gc.LeftRead | RightRdwr, 0, 0, 0},
-	arm.AMULD:  {gc.SizeD | gc.LeftRead | RightRdwr, 0, 0, 0},
-	arm.AMULF:  {gc.SizeF | gc.LeftRead | RightRdwr, 0, 0, 0},
-	arm.ASUBD:  {gc.SizeD | gc.LeftRead | RightRdwr, 0, 0, 0},
-	arm.ASUBF:  {gc.SizeF | gc.LeftRead | RightRdwr, 0, 0, 0},
-	arm.ASQRTD: {gc.SizeD | gc.LeftRead | RightRdwr, 0, 0, 0},
+	arm.AADDD:  {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
+	arm.AADDF:  {Flags: gc.SizeF | gc.LeftRead | RightRdwr},
+	arm.ACMPD:  {Flags: gc.SizeD | gc.LeftRead | gc.RightRead},
+	arm.ACMPF:  {Flags: gc.SizeF | gc.LeftRead | gc.RightRead},
+	arm.ADIVD:  {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
+	arm.ADIVF:  {Flags: gc.SizeF | gc.LeftRead | RightRdwr},
+	arm.AMULD:  {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
+	arm.AMULF:  {Flags: gc.SizeF | gc.LeftRead | RightRdwr},
+	arm.ASUBD:  {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
+	arm.ASUBF:  {Flags: gc.SizeF | gc.LeftRead | RightRdwr},
+	arm.ASQRTD: {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
 
 	// Conversions.
-	arm.AMOVWD: {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm.AMOVWF: {gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm.AMOVDF: {gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm.AMOVDW: {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm.AMOVFD: {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm.AMOVFW: {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
+	arm.AMOVWD: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm.AMOVWF: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm.AMOVDF: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm.AMOVDW: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm.AMOVFD: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm.AMOVFW: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
 
 	// Moves.
-	arm.AMOVB: {gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
-	arm.AMOVD: {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
-	arm.AMOVF: {gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
-	arm.AMOVH: {gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
-	arm.AMOVW: {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
+	arm.AMOVB: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move},
+	arm.AMOVD: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
+	arm.AMOVF: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move},
+	arm.AMOVH: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move},
+	arm.AMOVW: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move},
 
 	// In addtion, duffzero reads R0,R1 and writes R1.  This fact is
 	// encoded in peep.c
-	obj.ADUFFZERO: {gc.Call, 0, 0, 0},
+	obj.ADUFFZERO: {Flags: gc.Call},
 
 	// In addtion, duffcopy reads R1,R2 and writes R0,R1,R2.  This fact is
 	// encoded in peep.c
-	obj.ADUFFCOPY: {gc.Call, 0, 0, 0},
+	obj.ADUFFCOPY: {Flags: gc.Call},
 
 	// These should be split into the two different conversions instead
 	// of overloading the one.
-	arm.AMOVBS: {gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm.AMOVBU: {gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm.AMOVHS: {gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm.AMOVHU: {gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
+	arm.AMOVBS: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm.AMOVBU: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm.AMOVHS: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm.AMOVHU: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Conv},
 
 	// Jumps.
-	arm.AB:   {gc.Jump | gc.Break, 0, 0, 0},
-	arm.ABL:  {gc.Call, 0, 0, 0},
-	arm.ABEQ: {gc.Cjmp, 0, 0, 0},
-	arm.ABNE: {gc.Cjmp, 0, 0, 0},
-	arm.ABCS: {gc.Cjmp, 0, 0, 0},
-	arm.ABHS: {gc.Cjmp, 0, 0, 0},
-	arm.ABCC: {gc.Cjmp, 0, 0, 0},
-	arm.ABLO: {gc.Cjmp, 0, 0, 0},
-	arm.ABMI: {gc.Cjmp, 0, 0, 0},
-	arm.ABPL: {gc.Cjmp, 0, 0, 0},
-	arm.ABVS: {gc.Cjmp, 0, 0, 0},
-	arm.ABVC: {gc.Cjmp, 0, 0, 0},
-	arm.ABHI: {gc.Cjmp, 0, 0, 0},
-	arm.ABLS: {gc.Cjmp, 0, 0, 0},
-	arm.ABGE: {gc.Cjmp, 0, 0, 0},
-	arm.ABLT: {gc.Cjmp, 0, 0, 0},
-	arm.ABGT: {gc.Cjmp, 0, 0, 0},
-	arm.ABLE: {gc.Cjmp, 0, 0, 0},
-	obj.ARET: {gc.Break, 0, 0, 0},
+	arm.AB:   {Flags: gc.Jump | gc.Break},
+	arm.ABL:  {Flags: gc.Call},
+	arm.ABEQ: {Flags: gc.Cjmp},
+	arm.ABNE: {Flags: gc.Cjmp},
+	arm.ABCS: {Flags: gc.Cjmp},
+	arm.ABHS: {Flags: gc.Cjmp},
+	arm.ABCC: {Flags: gc.Cjmp},
+	arm.ABLO: {Flags: gc.Cjmp},
+	arm.ABMI: {Flags: gc.Cjmp},
+	arm.ABPL: {Flags: gc.Cjmp},
+	arm.ABVS: {Flags: gc.Cjmp},
+	arm.ABVC: {Flags: gc.Cjmp},
+	arm.ABHI: {Flags: gc.Cjmp},
+	arm.ABLS: {Flags: gc.Cjmp},
+	arm.ABGE: {Flags: gc.Cjmp},
+	arm.ABLT: {Flags: gc.Cjmp},
+	arm.ABGT: {Flags: gc.Cjmp},
+	arm.ABLE: {Flags: gc.Cjmp},
+	obj.ARET: {Flags: gc.Break},
 }
 
 func proginfo(p *obj.Prog) {
 	info := &p.Info
 	*info = progtable[p.As]
 	if info.Flags == 0 {
-		gc.Fatal("unknown instruction %v", p)
+		gc.Fatalf("unknown instruction %v", p)
 	}
 
 	if p.From.Type == obj.TYPE_ADDR && p.From.Sym != nil && (info.Flags&gc.LeftRead != 0) {
diff --git a/src/cmd/compile/internal/arm64/cgen.go b/src/cmd/compile/internal/arm64/cgen.go
index 30326d7..a7f1c18 100644
--- a/src/cmd/compile/internal/arm64/cgen.go
+++ b/src/cmd/compile/internal/arm64/cgen.go
@@ -20,7 +20,7 @@ func blockcopy(n, res *gc.Node, osrc, odst, w int64) {
 	var op int
 	switch align {
 	default:
-		gc.Fatal("sgen: invalid alignment %d for %v", align, n.Type)
+		gc.Fatalf("sgen: invalid alignment %d for %v", align, n.Type)
 
 	case 1:
 		op = arm64.AMOVB
@@ -36,12 +36,12 @@ func blockcopy(n, res *gc.Node, osrc, odst, w int64) {
 	}
 
 	if w%int64(align) != 0 {
-		gc.Fatal("sgen: unaligned size %d (align=%d) for %v", w, align, n.Type)
+		gc.Fatalf("sgen: unaligned size %d (align=%d) for %v", w, align, n.Type)
 	}
 	c := int32(w / int64(align))
 
 	if osrc%int64(align) != 0 || odst%int64(align) != 0 {
-		gc.Fatal("sgen: unaligned offset src %d or dst %d (align %d)", osrc, odst, align)
+		gc.Fatalf("sgen: unaligned offset src %d or dst %d (align %d)", osrc, odst, align)
 	}
 
 	// if we are copying forward on the stack and
@@ -132,13 +132,7 @@ func blockcopy(n, res *gc.Node, osrc, odst, w int64) {
 		// ADDs.  That will produce shorter, more
 		// pipeline-able code.
 		var p *obj.Prog
-		for {
-			tmp14 := c
-			c--
-			if tmp14 <= 0 {
-				break
-			}
-
+		for ; c > 0; c-- {
 			p = gins(op, &src, &tmp)
 			p.From.Type = obj.TYPE_MEM
 			p.From.Offset = int64(dir)
diff --git a/src/cmd/compile/internal/arm64/galign.go b/src/cmd/compile/internal/arm64/galign.go
index 38def8f..d61fd3c 100644
--- a/src/cmd/compile/internal/arm64/galign.go
+++ b/src/cmd/compile/internal/arm64/galign.go
@@ -26,9 +26,9 @@ var MAXWIDTH int64 = 1 << 50
  * int, uint, and uintptr
  */
 var typedefs = []gc.Typedef{
-	gc.Typedef{"int", gc.TINT, gc.TINT64},
-	gc.Typedef{"uint", gc.TUINT, gc.TUINT64},
-	gc.Typedef{"uintptr", gc.TUINTPTR, gc.TUINT64},
+	{"int", gc.TINT, gc.TINT64},
+	{"uint", gc.TUINT, gc.TUINT64},
+	{"uintptr", gc.TUINTPTR, gc.TUINT64},
 }
 
 func betypeinit() {
diff --git a/src/cmd/compile/internal/arm64/ggen.go b/src/cmd/compile/internal/arm64/ggen.go
index cba4d99..c495bbc 100644
--- a/src/cmd/compile/internal/arm64/ggen.go
+++ b/src/cmd/compile/internal/arm64/ggen.go
@@ -43,10 +43,10 @@ func defframe(ptxt *obj.Prog) {
 			continue
 		}
 		if n.Class != gc.PAUTO {
-			gc.Fatal("needzero class %d", n.Class)
+			gc.Fatalf("needzero class %d", n.Class)
 		}
 		if n.Type.Width%int64(gc.Widthptr) != 0 || n.Xoffset%int64(gc.Widthptr) != 0 || n.Type.Width == 0 {
-			gc.Fatal("var %v has size %d offset %d", gc.Nconv(n, obj.FmtLong), int(n.Type.Width), int(n.Xoffset))
+			gc.Fatalf("var %v has size %d offset %d", gc.Nconv(n, obj.FmtLong), int(n.Type.Width), int(n.Xoffset))
 		}
 
 		if lo != hi && n.Xoffset+n.Type.Width >= lo-int64(2*gc.Widthreg) {
@@ -140,7 +140,7 @@ var panicdiv *gc.Node
  *	res = nl % nr
  * according to op.
  */
-func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+func dodiv(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	// Have to be careful about handling
 	// most negative int divided by -1 correctly.
 	// The hardware will generate undefined result.
@@ -151,13 +151,13 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	t := nl.Type
 
 	t0 := t
-	check := 0
+	check := false
 	if gc.Issigned[t.Etype] {
-		check = 1
+		check = true
 		if gc.Isconst(nl, gc.CTINT) && nl.Int() != -(1<<uint64(t.Width*8-1)) {
-			check = 0
+			check = false
 		} else if gc.Isconst(nr, gc.CTINT) && nr.Int() != -1 {
-			check = 0
+			check = false
 		}
 	}
 
@@ -167,7 +167,7 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 		} else {
 			t = gc.Types[gc.TUINT64]
 		}
-		check = 0
+		check = false
 	}
 
 	a := optoas(gc.ODIV, t)
@@ -206,7 +206,7 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	gc.Patch(p1, gc.Pc)
 
 	var p2 *obj.Prog
-	if check != 0 {
+	if check {
 		var nm1 gc.Node
 		gc.Nodconst(&nm1, t, -1)
 		gcmp(optoas(gc.OCMP, t), &tr, &nm1)
@@ -250,7 +250,7 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	}
 
 	gc.Regfree(&tl)
-	if check != 0 {
+	if check {
 		gc.Patch(p2, gc.Pc)
 	}
 }
@@ -262,9 +262,7 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	// largest ullman on left.
 	if nl.Ullman < nr.Ullman {
-		tmp := (*gc.Node)(nl)
-		nl = nr
-		nr = tmp
+		nl, nr = nr, nl
 	}
 
 	t := (*gc.Type)(nl.Type)
@@ -299,7 +297,7 @@ func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
 		}
 
 	default:
-		gc.Fatal("cgen_hmul %v", t)
+		gc.Fatalf("cgen_hmul %v", t)
 	}
 
 	gc.Cgen(&n1, res)
@@ -312,7 +310,7 @@ func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
  *	res = nl << nr
  *	res = nl >> nr
  */
-func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+func cgen_shift(op gc.Op, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	a := int(optoas(op, nl.Type))
 
 	if nr.Op == gc.OLITERAL {
@@ -499,7 +497,7 @@ func expandchecks(firstp *obj.Prog) {
 			gc.Warnl(int(p.Lineno), "generated nil check")
 		}
 		if p.From.Type != obj.TYPE_REG {
-			gc.Fatal("invalid nil check %v\n", p)
+			gc.Fatalf("invalid nil check %v\n", p)
 		}
 
 		// check is
diff --git a/src/cmd/compile/internal/arm64/gsubr.go b/src/cmd/compile/internal/arm64/gsubr.go
index 0a14654..c0aa45e 100644
--- a/src/cmd/compile/internal/arm64/gsubr.go
+++ b/src/cmd/compile/internal/arm64/gsubr.go
@@ -84,7 +84,7 @@ func ginscon2(as int, n2 *gc.Node, c int64) {
 
 	switch as {
 	default:
-		gc.Fatal("ginscon2")
+		gc.Fatalf("ginscon2")
 
 	case arm64.ACMP:
 		if -arm64.BIG <= c && c <= arm64.BIG {
@@ -102,7 +102,7 @@ func ginscon2(as int, n2 *gc.Node, c int64) {
 	gc.Regfree(&ntmp)
 }
 
-func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+func ginscmp(op gc.Op, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
 	if gc.Isint[t.Etype] && n1.Op == gc.OLITERAL && n2.Op != gc.OLITERAL {
 		// Reverse comparison to place constant last.
 		op = gc.Brrev(op)
@@ -214,7 +214,7 @@ func gmove(f *gc.Node, t *gc.Node) {
 
 	switch uint32(ft)<<16 | uint32(tt) {
 	default:
-		gc.Fatal("gmove %v -> %v", gc.Tconv(f.Type, obj.FmtLong), gc.Tconv(t.Type, obj.FmtLong))
+		gc.Fatalf("gmove %v -> %v", gc.Tconv(f.Type, obj.FmtLong), gc.Tconv(t.Type, obj.FmtLong))
 
 		/*
 		 * integer copy and truncate
@@ -467,30 +467,18 @@ hard:
 	return
 }
 
-func intLiteral(n *gc.Node) (x int64, ok bool) {
-	switch {
-	case n == nil:
-		return
-	case gc.Isconst(n, gc.CTINT):
-		return n.Int(), true
-	case gc.Isconst(n, gc.CTBOOL):
-		return int64(obj.Bool2int(n.Bool())), true
-	}
-	return
-}
-
 // gins is called by the front end.
 // 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 {
+		if x, ok := f.IntLiteral(); ok {
 			ginscon(as, x, t)
 			return nil // caller must not use
 		}
 	}
 	if as == arm64.ACMP {
-		if x, ok := intLiteral(t); ok {
+		if x, ok := t.IntLiteral(); ok {
 			ginscon2(as, f, x)
 			return nil // caller must not use
 		}
@@ -514,7 +502,7 @@ func rawgins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
 	case arm64.ACMP, arm64.AFCMPS, arm64.AFCMPD:
 		if t != nil {
 			if f.Op != gc.OREGISTER {
-				gc.Fatal("bad operands to gcmp")
+				gc.Fatalf("bad operands to gcmp")
 			}
 			p.From = p.To
 			p.To = obj.Addr{}
@@ -527,12 +515,12 @@ func rawgins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
 	case arm64.AAND, arm64.AMUL:
 		if p.From.Type == obj.TYPE_CONST {
 			gc.Debug['h'] = 1
-			gc.Fatal("bad inst: %v", p)
+			gc.Fatalf("bad inst: %v", p)
 		}
 	case arm64.ACMP:
 		if p.From.Type == obj.TYPE_MEM || p.To.Type == obj.TYPE_MEM {
 			gc.Debug['h'] = 1
-			gc.Fatal("bad inst: %v", p)
+			gc.Fatalf("bad inst: %v", p)
 		}
 	}
 
@@ -564,7 +552,7 @@ func rawgins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
 	if w != 0 && ((f != nil && p.From.Width < int64(w)) || (t != nil && p.To.Type != obj.TYPE_REG && p.To.Width > int64(w))) {
 		gc.Dump("f", f)
 		gc.Dump("t", t)
-		gc.Fatal("bad width: %v (%d, %d)\n", p, p.From.Width, p.To.Width)
+		gc.Fatalf("bad width: %v (%d, %d)\n", p, p.From.Width, p.To.Width)
 	}
 
 	return p
@@ -579,9 +567,9 @@ func raddr(n *gc.Node, p *obj.Prog) {
 	gc.Naddr(&a, n)
 	if a.Type != obj.TYPE_REG {
 		if n != nil {
-			gc.Fatal("bad in raddr: %v", gc.Oconv(int(n.Op), 0))
+			gc.Fatalf("bad in raddr: %v", gc.Oconv(int(n.Op), 0))
 		} else {
-			gc.Fatal("bad in raddr: <null>")
+			gc.Fatalf("bad in raddr: <null>")
 		}
 		p.Reg = 0
 	} else {
@@ -591,7 +579,7 @@ func raddr(n *gc.Node, p *obj.Prog) {
 
 func gcmp(as int, lhs *gc.Node, rhs *gc.Node) *obj.Prog {
 	if lhs.Op != gc.OREGISTER {
-		gc.Fatal("bad operands to gcmp: %v %v", gc.Oconv(int(lhs.Op), 0), gc.Oconv(int(rhs.Op), 0))
+		gc.Fatalf("bad operands to gcmp: %v %v", gc.Oconv(int(lhs.Op), 0), gc.Oconv(int(rhs.Op), 0))
 	}
 
 	p := rawgins(as, rhs, nil)
@@ -602,240 +590,264 @@ func gcmp(as int, lhs *gc.Node, rhs *gc.Node) *obj.Prog {
 /*
  * return Axxx for Oxxx on type t.
  */
-func optoas(op int, t *gc.Type) int {
+func optoas(op gc.Op, t *gc.Type) int {
 	if t == nil {
-		gc.Fatal("optoas: t is nil")
+		gc.Fatalf("optoas: t is nil")
 	}
 
+	// avoid constant conversions in switches below
+	const (
+		OMINUS_ = uint32(gc.OMINUS) << 16
+		OLSH_   = uint32(gc.OLSH) << 16
+		ORSH_   = uint32(gc.ORSH) << 16
+		OADD_   = uint32(gc.OADD) << 16
+		OSUB_   = uint32(gc.OSUB) << 16
+		OMUL_   = uint32(gc.OMUL) << 16
+		ODIV_   = uint32(gc.ODIV) << 16
+		OOR_    = uint32(gc.OOR) << 16
+		OAND_   = uint32(gc.OAND) << 16
+		OXOR_   = uint32(gc.OXOR) << 16
+		OEQ_    = uint32(gc.OEQ) << 16
+		ONE_    = uint32(gc.ONE) << 16
+		OLT_    = uint32(gc.OLT) << 16
+		OLE_    = uint32(gc.OLE) << 16
+		OGE_    = uint32(gc.OGE) << 16
+		OGT_    = uint32(gc.OGT) << 16
+		OCMP_   = uint32(gc.OCMP) << 16
+		OAS_    = uint32(gc.OAS) << 16
+		OHMUL_  = uint32(gc.OHMUL) << 16
+		OSQRT_  = uint32(gc.OSQRT) << 16
+	)
+
 	a := int(obj.AXXX)
 	switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) {
 	default:
-		gc.Fatal("optoas: no entry for op=%v type=%v", gc.Oconv(int(op), 0), t)
-
-	case gc.OEQ<<16 | gc.TBOOL,
-		gc.OEQ<<16 | gc.TINT8,
-		gc.OEQ<<16 | gc.TUINT8,
-		gc.OEQ<<16 | gc.TINT16,
-		gc.OEQ<<16 | gc.TUINT16,
-		gc.OEQ<<16 | gc.TINT32,
-		gc.OEQ<<16 | gc.TUINT32,
-		gc.OEQ<<16 | gc.TINT64,
-		gc.OEQ<<16 | gc.TUINT64,
-		gc.OEQ<<16 | gc.TPTR32,
-		gc.OEQ<<16 | gc.TPTR64,
-		gc.OEQ<<16 | gc.TFLOAT32,
-		gc.OEQ<<16 | gc.TFLOAT64:
+		gc.Fatalf("optoas: no entry for op=%v type=%v", gc.Oconv(int(op), 0), t)
+
+	case OEQ_ | gc.TBOOL,
+		OEQ_ | gc.TINT8,
+		OEQ_ | gc.TUINT8,
+		OEQ_ | gc.TINT16,
+		OEQ_ | gc.TUINT16,
+		OEQ_ | gc.TINT32,
+		OEQ_ | gc.TUINT32,
+		OEQ_ | gc.TINT64,
+		OEQ_ | gc.TUINT64,
+		OEQ_ | gc.TPTR32,
+		OEQ_ | gc.TPTR64,
+		OEQ_ | gc.TFLOAT32,
+		OEQ_ | gc.TFLOAT64:
 		a = arm64.ABEQ
 
-	case gc.ONE<<16 | gc.TBOOL,
-		gc.ONE<<16 | gc.TINT8,
-		gc.ONE<<16 | gc.TUINT8,
-		gc.ONE<<16 | gc.TINT16,
-		gc.ONE<<16 | gc.TUINT16,
-		gc.ONE<<16 | gc.TINT32,
-		gc.ONE<<16 | gc.TUINT32,
-		gc.ONE<<16 | gc.TINT64,
-		gc.ONE<<16 | gc.TUINT64,
-		gc.ONE<<16 | gc.TPTR32,
-		gc.ONE<<16 | gc.TPTR64,
-		gc.ONE<<16 | gc.TFLOAT32,
-		gc.ONE<<16 | gc.TFLOAT64:
+	case ONE_ | gc.TBOOL,
+		ONE_ | gc.TINT8,
+		ONE_ | gc.TUINT8,
+		ONE_ | gc.TINT16,
+		ONE_ | gc.TUINT16,
+		ONE_ | gc.TINT32,
+		ONE_ | gc.TUINT32,
+		ONE_ | gc.TINT64,
+		ONE_ | gc.TUINT64,
+		ONE_ | gc.TPTR32,
+		ONE_ | gc.TPTR64,
+		ONE_ | gc.TFLOAT32,
+		ONE_ | gc.TFLOAT64:
 		a = arm64.ABNE
 
-	case gc.OLT<<16 | gc.TINT8,
-		gc.OLT<<16 | gc.TINT16,
-		gc.OLT<<16 | gc.TINT32,
-		gc.OLT<<16 | gc.TINT64:
+	case OLT_ | gc.TINT8,
+		OLT_ | gc.TINT16,
+		OLT_ | gc.TINT32,
+		OLT_ | gc.TINT64:
 		a = arm64.ABLT
 
-	case gc.OLT<<16 | gc.TUINT8,
-		gc.OLT<<16 | gc.TUINT16,
-		gc.OLT<<16 | gc.TUINT32,
-		gc.OLT<<16 | gc.TUINT64,
-		gc.OLT<<16 | gc.TFLOAT32,
-		gc.OLT<<16 | gc.TFLOAT64:
+	case OLT_ | gc.TUINT8,
+		OLT_ | gc.TUINT16,
+		OLT_ | gc.TUINT32,
+		OLT_ | gc.TUINT64,
+		OLT_ | gc.TFLOAT32,
+		OLT_ | gc.TFLOAT64:
 		a = arm64.ABLO
 
-	case gc.OLE<<16 | gc.TINT8,
-		gc.OLE<<16 | gc.TINT16,
-		gc.OLE<<16 | gc.TINT32,
-		gc.OLE<<16 | gc.TINT64:
+	case OLE_ | gc.TINT8,
+		OLE_ | gc.TINT16,
+		OLE_ | gc.TINT32,
+		OLE_ | gc.TINT64:
 		a = arm64.ABLE
 
-	case gc.OLE<<16 | gc.TUINT8,
-		gc.OLE<<16 | gc.TUINT16,
-		gc.OLE<<16 | gc.TUINT32,
-		gc.OLE<<16 | gc.TUINT64,
-		gc.OLE<<16 | gc.TFLOAT32,
-		gc.OLE<<16 | gc.TFLOAT64:
+	case OLE_ | gc.TUINT8,
+		OLE_ | gc.TUINT16,
+		OLE_ | gc.TUINT32,
+		OLE_ | gc.TUINT64,
+		OLE_ | gc.TFLOAT32,
+		OLE_ | gc.TFLOAT64:
 		a = arm64.ABLS
 
-	case gc.OGT<<16 | gc.TINT8,
-		gc.OGT<<16 | gc.TINT16,
-		gc.OGT<<16 | gc.TINT32,
-		gc.OGT<<16 | gc.TINT64,
-		gc.OGT<<16 | gc.TFLOAT32,
-		gc.OGT<<16 | gc.TFLOAT64:
+	case OGT_ | gc.TINT8,
+		OGT_ | gc.TINT16,
+		OGT_ | gc.TINT32,
+		OGT_ | gc.TINT64,
+		OGT_ | gc.TFLOAT32,
+		OGT_ | gc.TFLOAT64:
 		a = arm64.ABGT
 
-	case gc.OGT<<16 | gc.TUINT8,
-		gc.OGT<<16 | gc.TUINT16,
-		gc.OGT<<16 | gc.TUINT32,
-		gc.OGT<<16 | gc.TUINT64:
+	case OGT_ | gc.TUINT8,
+		OGT_ | gc.TUINT16,
+		OGT_ | gc.TUINT32,
+		OGT_ | gc.TUINT64:
 		a = arm64.ABHI
 
-	case gc.OGE<<16 | gc.TINT8,
-		gc.OGE<<16 | gc.TINT16,
-		gc.OGE<<16 | gc.TINT32,
-		gc.OGE<<16 | gc.TINT64,
-		gc.OGE<<16 | gc.TFLOAT32,
-		gc.OGE<<16 | gc.TFLOAT64:
+	case OGE_ | gc.TINT8,
+		OGE_ | gc.TINT16,
+		OGE_ | gc.TINT32,
+		OGE_ | gc.TINT64,
+		OGE_ | gc.TFLOAT32,
+		OGE_ | gc.TFLOAT64:
 		a = arm64.ABGE
 
-	case gc.OGE<<16 | gc.TUINT8,
-		gc.OGE<<16 | gc.TUINT16,
-		gc.OGE<<16 | gc.TUINT32,
-		gc.OGE<<16 | gc.TUINT64:
+	case OGE_ | gc.TUINT8,
+		OGE_ | gc.TUINT16,
+		OGE_ | gc.TUINT32,
+		OGE_ | gc.TUINT64:
 		a = arm64.ABHS
 
-	case gc.OCMP<<16 | gc.TBOOL,
-		gc.OCMP<<16 | gc.TINT8,
-		gc.OCMP<<16 | gc.TINT16,
-		gc.OCMP<<16 | gc.TINT32,
-		gc.OCMP<<16 | gc.TPTR32,
-		gc.OCMP<<16 | gc.TINT64,
-		gc.OCMP<<16 | gc.TUINT8,
-		gc.OCMP<<16 | gc.TUINT16,
-		gc.OCMP<<16 | gc.TUINT32,
-		gc.OCMP<<16 | gc.TUINT64,
-		gc.OCMP<<16 | gc.TPTR64:
+	case OCMP_ | gc.TBOOL,
+		OCMP_ | gc.TINT8,
+		OCMP_ | gc.TINT16,
+		OCMP_ | gc.TINT32,
+		OCMP_ | gc.TPTR32,
+		OCMP_ | gc.TINT64,
+		OCMP_ | gc.TUINT8,
+		OCMP_ | gc.TUINT16,
+		OCMP_ | gc.TUINT32,
+		OCMP_ | gc.TUINT64,
+		OCMP_ | gc.TPTR64:
 		a = arm64.ACMP
 
-	case gc.OCMP<<16 | gc.TFLOAT32:
+	case OCMP_ | gc.TFLOAT32:
 		a = arm64.AFCMPS
 
-	case gc.OCMP<<16 | gc.TFLOAT64:
+	case OCMP_ | gc.TFLOAT64:
 		a = arm64.AFCMPD
 
-	case gc.OAS<<16 | gc.TBOOL,
-		gc.OAS<<16 | gc.TINT8:
+	case OAS_ | gc.TBOOL,
+		OAS_ | gc.TINT8:
 		a = arm64.AMOVB
 
-	case gc.OAS<<16 | gc.TUINT8:
+	case OAS_ | gc.TUINT8:
 		a = arm64.AMOVBU
 
-	case gc.OAS<<16 | gc.TINT16:
+	case OAS_ | gc.TINT16:
 		a = arm64.AMOVH
 
-	case gc.OAS<<16 | gc.TUINT16:
+	case OAS_ | gc.TUINT16:
 		a = arm64.AMOVHU
 
-	case gc.OAS<<16 | gc.TINT32:
+	case OAS_ | gc.TINT32:
 		a = arm64.AMOVW
 
-	case gc.OAS<<16 | gc.TUINT32,
-		gc.OAS<<16 | gc.TPTR32:
+	case OAS_ | gc.TUINT32,
+		OAS_ | gc.TPTR32:
 		a = arm64.AMOVWU
 
-	case gc.OAS<<16 | gc.TINT64,
-		gc.OAS<<16 | gc.TUINT64,
-		gc.OAS<<16 | gc.TPTR64:
+	case OAS_ | gc.TINT64,
+		OAS_ | gc.TUINT64,
+		OAS_ | gc.TPTR64:
 		a = arm64.AMOVD
 
-	case gc.OAS<<16 | gc.TFLOAT32:
+	case OAS_ | gc.TFLOAT32:
 		a = arm64.AFMOVS
 
-	case gc.OAS<<16 | gc.TFLOAT64:
+	case OAS_ | gc.TFLOAT64:
 		a = arm64.AFMOVD
 
-	case gc.OADD<<16 | gc.TINT8,
-		gc.OADD<<16 | gc.TUINT8,
-		gc.OADD<<16 | gc.TINT16,
-		gc.OADD<<16 | gc.TUINT16,
-		gc.OADD<<16 | gc.TINT32,
-		gc.OADD<<16 | gc.TUINT32,
-		gc.OADD<<16 | gc.TPTR32,
-		gc.OADD<<16 | gc.TINT64,
-		gc.OADD<<16 | gc.TUINT64,
-		gc.OADD<<16 | gc.TPTR64:
+	case OADD_ | gc.TINT8,
+		OADD_ | gc.TUINT8,
+		OADD_ | gc.TINT16,
+		OADD_ | gc.TUINT16,
+		OADD_ | gc.TINT32,
+		OADD_ | gc.TUINT32,
+		OADD_ | gc.TPTR32,
+		OADD_ | gc.TINT64,
+		OADD_ | gc.TUINT64,
+		OADD_ | gc.TPTR64:
 		a = arm64.AADD
 
-	case gc.OADD<<16 | gc.TFLOAT32:
+	case OADD_ | gc.TFLOAT32:
 		a = arm64.AFADDS
 
-	case gc.OADD<<16 | gc.TFLOAT64:
+	case OADD_ | gc.TFLOAT64:
 		a = arm64.AFADDD
 
-	case gc.OSUB<<16 | gc.TINT8,
-		gc.OSUB<<16 | gc.TUINT8,
-		gc.OSUB<<16 | gc.TINT16,
-		gc.OSUB<<16 | gc.TUINT16,
-		gc.OSUB<<16 | gc.TINT32,
-		gc.OSUB<<16 | gc.TUINT32,
-		gc.OSUB<<16 | gc.TPTR32,
-		gc.OSUB<<16 | gc.TINT64,
-		gc.OSUB<<16 | gc.TUINT64,
-		gc.OSUB<<16 | gc.TPTR64:
+	case OSUB_ | gc.TINT8,
+		OSUB_ | gc.TUINT8,
+		OSUB_ | gc.TINT16,
+		OSUB_ | gc.TUINT16,
+		OSUB_ | gc.TINT32,
+		OSUB_ | gc.TUINT32,
+		OSUB_ | gc.TPTR32,
+		OSUB_ | gc.TINT64,
+		OSUB_ | gc.TUINT64,
+		OSUB_ | gc.TPTR64:
 		a = arm64.ASUB
 
-	case gc.OSUB<<16 | gc.TFLOAT32:
+	case OSUB_ | gc.TFLOAT32:
 		a = arm64.AFSUBS
 
-	case gc.OSUB<<16 | gc.TFLOAT64:
+	case OSUB_ | gc.TFLOAT64:
 		a = arm64.AFSUBD
 
-	case gc.OMINUS<<16 | gc.TINT8,
-		gc.OMINUS<<16 | gc.TUINT8,
-		gc.OMINUS<<16 | gc.TINT16,
-		gc.OMINUS<<16 | gc.TUINT16,
-		gc.OMINUS<<16 | gc.TINT32,
-		gc.OMINUS<<16 | gc.TUINT32,
-		gc.OMINUS<<16 | gc.TPTR32,
-		gc.OMINUS<<16 | gc.TINT64,
-		gc.OMINUS<<16 | gc.TUINT64,
-		gc.OMINUS<<16 | gc.TPTR64:
+	case OMINUS_ | gc.TINT8,
+		OMINUS_ | gc.TUINT8,
+		OMINUS_ | gc.TINT16,
+		OMINUS_ | gc.TUINT16,
+		OMINUS_ | gc.TINT32,
+		OMINUS_ | gc.TUINT32,
+		OMINUS_ | gc.TPTR32,
+		OMINUS_ | gc.TINT64,
+		OMINUS_ | gc.TUINT64,
+		OMINUS_ | gc.TPTR64:
 		a = arm64.ANEG
 
-	case gc.OMINUS<<16 | gc.TFLOAT32:
+	case OMINUS_ | gc.TFLOAT32:
 		a = arm64.AFNEGS
 
-	case gc.OMINUS<<16 | gc.TFLOAT64:
+	case OMINUS_ | gc.TFLOAT64:
 		a = arm64.AFNEGD
 
-	case gc.OAND<<16 | gc.TINT8,
-		gc.OAND<<16 | gc.TUINT8,
-		gc.OAND<<16 | gc.TINT16,
-		gc.OAND<<16 | gc.TUINT16,
-		gc.OAND<<16 | gc.TINT32,
-		gc.OAND<<16 | gc.TUINT32,
-		gc.OAND<<16 | gc.TPTR32,
-		gc.OAND<<16 | gc.TINT64,
-		gc.OAND<<16 | gc.TUINT64,
-		gc.OAND<<16 | gc.TPTR64:
+	case OAND_ | gc.TINT8,
+		OAND_ | gc.TUINT8,
+		OAND_ | gc.TINT16,
+		OAND_ | gc.TUINT16,
+		OAND_ | gc.TINT32,
+		OAND_ | gc.TUINT32,
+		OAND_ | gc.TPTR32,
+		OAND_ | gc.TINT64,
+		OAND_ | gc.TUINT64,
+		OAND_ | gc.TPTR64:
 		a = arm64.AAND
 
-	case gc.OOR<<16 | gc.TINT8,
-		gc.OOR<<16 | gc.TUINT8,
-		gc.OOR<<16 | gc.TINT16,
-		gc.OOR<<16 | gc.TUINT16,
-		gc.OOR<<16 | gc.TINT32,
-		gc.OOR<<16 | gc.TUINT32,
-		gc.OOR<<16 | gc.TPTR32,
-		gc.OOR<<16 | gc.TINT64,
-		gc.OOR<<16 | gc.TUINT64,
-		gc.OOR<<16 | gc.TPTR64:
+	case OOR_ | gc.TINT8,
+		OOR_ | gc.TUINT8,
+		OOR_ | gc.TINT16,
+		OOR_ | gc.TUINT16,
+		OOR_ | gc.TINT32,
+		OOR_ | gc.TUINT32,
+		OOR_ | gc.TPTR32,
+		OOR_ | gc.TINT64,
+		OOR_ | gc.TUINT64,
+		OOR_ | gc.TPTR64:
 		a = arm64.AORR
 
-	case gc.OXOR<<16 | gc.TINT8,
-		gc.OXOR<<16 | gc.TUINT8,
-		gc.OXOR<<16 | gc.TINT16,
-		gc.OXOR<<16 | gc.TUINT16,
-		gc.OXOR<<16 | gc.TINT32,
-		gc.OXOR<<16 | gc.TUINT32,
-		gc.OXOR<<16 | gc.TPTR32,
-		gc.OXOR<<16 | gc.TINT64,
-		gc.OXOR<<16 | gc.TUINT64,
-		gc.OXOR<<16 | gc.TPTR64:
+	case OXOR_ | gc.TINT8,
+		OXOR_ | gc.TUINT8,
+		OXOR_ | gc.TINT16,
+		OXOR_ | gc.TUINT16,
+		OXOR_ | gc.TINT32,
+		OXOR_ | gc.TUINT32,
+		OXOR_ | gc.TPTR32,
+		OXOR_ | gc.TINT64,
+		OXOR_ | gc.TUINT64,
+		OXOR_ | gc.TPTR64:
 		a = arm64.AEOR
 
 		// TODO(minux): handle rotates
@@ -852,30 +864,30 @@ func optoas(op int, t *gc.Type) int {
 	//	a = 0//???; RLDC?
 	//	break;
 
-	case gc.OLSH<<16 | gc.TINT8,
-		gc.OLSH<<16 | gc.TUINT8,
-		gc.OLSH<<16 | gc.TINT16,
-		gc.OLSH<<16 | gc.TUINT16,
-		gc.OLSH<<16 | gc.TINT32,
-		gc.OLSH<<16 | gc.TUINT32,
-		gc.OLSH<<16 | gc.TPTR32,
-		gc.OLSH<<16 | gc.TINT64,
-		gc.OLSH<<16 | gc.TUINT64,
-		gc.OLSH<<16 | gc.TPTR64:
+	case OLSH_ | gc.TINT8,
+		OLSH_ | gc.TUINT8,
+		OLSH_ | gc.TINT16,
+		OLSH_ | gc.TUINT16,
+		OLSH_ | gc.TINT32,
+		OLSH_ | gc.TUINT32,
+		OLSH_ | gc.TPTR32,
+		OLSH_ | gc.TINT64,
+		OLSH_ | gc.TUINT64,
+		OLSH_ | gc.TPTR64:
 		a = arm64.ALSL
 
-	case gc.ORSH<<16 | gc.TUINT8,
-		gc.ORSH<<16 | gc.TUINT16,
-		gc.ORSH<<16 | gc.TUINT32,
-		gc.ORSH<<16 | gc.TPTR32,
-		gc.ORSH<<16 | gc.TUINT64,
-		gc.ORSH<<16 | gc.TPTR64:
+	case ORSH_ | gc.TUINT8,
+		ORSH_ | gc.TUINT16,
+		ORSH_ | gc.TUINT32,
+		ORSH_ | gc.TPTR32,
+		ORSH_ | gc.TUINT64,
+		ORSH_ | gc.TPTR64:
 		a = arm64.ALSR
 
-	case gc.ORSH<<16 | gc.TINT8,
-		gc.ORSH<<16 | gc.TINT16,
-		gc.ORSH<<16 | gc.TINT32,
-		gc.ORSH<<16 | gc.TINT64:
+	case ORSH_ | gc.TINT8,
+		ORSH_ | gc.TINT16,
+		ORSH_ | gc.TINT32,
+		ORSH_ | gc.TINT64:
 		a = arm64.AASR
 
 		// TODO(minux): handle rotates
@@ -890,59 +902,59 @@ func optoas(op int, t *gc.Type) int {
 	//	a = 0//??? RLDC??
 	//	break;
 
-	case gc.OHMUL<<16 | gc.TINT64:
+	case OHMUL_ | gc.TINT64:
 		a = arm64.ASMULH
 
-	case gc.OHMUL<<16 | gc.TUINT64,
-		gc.OHMUL<<16 | gc.TPTR64:
+	case OHMUL_ | gc.TUINT64,
+		OHMUL_ | gc.TPTR64:
 		a = arm64.AUMULH
 
-	case gc.OMUL<<16 | gc.TINT8,
-		gc.OMUL<<16 | gc.TINT16,
-		gc.OMUL<<16 | gc.TINT32:
+	case OMUL_ | gc.TINT8,
+		OMUL_ | gc.TINT16,
+		OMUL_ | gc.TINT32:
 		a = arm64.ASMULL
 
-	case gc.OMUL<<16 | gc.TINT64:
+	case OMUL_ | gc.TINT64:
 		a = arm64.AMUL
 
-	case gc.OMUL<<16 | gc.TUINT8,
-		gc.OMUL<<16 | gc.TUINT16,
-		gc.OMUL<<16 | gc.TUINT32,
-		gc.OMUL<<16 | gc.TPTR32:
+	case OMUL_ | gc.TUINT8,
+		OMUL_ | gc.TUINT16,
+		OMUL_ | gc.TUINT32,
+		OMUL_ | gc.TPTR32:
 		// don't use word multiply, the high 32-bit are undefined.
 		a = arm64.AUMULL
 
-	case gc.OMUL<<16 | gc.TUINT64,
-		gc.OMUL<<16 | gc.TPTR64:
+	case OMUL_ | gc.TUINT64,
+		OMUL_ | gc.TPTR64:
 		a = arm64.AMUL // for 64-bit multiplies, signedness doesn't matter.
 
-	case gc.OMUL<<16 | gc.TFLOAT32:
+	case OMUL_ | gc.TFLOAT32:
 		a = arm64.AFMULS
 
-	case gc.OMUL<<16 | gc.TFLOAT64:
+	case OMUL_ | gc.TFLOAT64:
 		a = arm64.AFMULD
 
-	case gc.ODIV<<16 | gc.TINT8,
-		gc.ODIV<<16 | gc.TINT16,
-		gc.ODIV<<16 | gc.TINT32,
-		gc.ODIV<<16 | gc.TINT64:
+	case ODIV_ | gc.TINT8,
+		ODIV_ | gc.TINT16,
+		ODIV_ | gc.TINT32,
+		ODIV_ | gc.TINT64:
 		a = arm64.ASDIV
 
-	case gc.ODIV<<16 | gc.TUINT8,
-		gc.ODIV<<16 | gc.TUINT16,
-		gc.ODIV<<16 | gc.TUINT32,
-		gc.ODIV<<16 | gc.TPTR32,
-		gc.ODIV<<16 | gc.TUINT64,
-		gc.ODIV<<16 | gc.TPTR64:
+	case ODIV_ | gc.TUINT8,
+		ODIV_ | gc.TUINT16,
+		ODIV_ | gc.TUINT32,
+		ODIV_ | gc.TPTR32,
+		ODIV_ | gc.TUINT64,
+		ODIV_ | gc.TPTR64:
 		a = arm64.AUDIV
 
-	case gc.ODIV<<16 | gc.TFLOAT32:
+	case ODIV_ | gc.TFLOAT32:
 		a = arm64.AFDIVS
 
-	case gc.ODIV<<16 | gc.TFLOAT64:
+	case ODIV_ | gc.TFLOAT64:
 		a = arm64.AFDIVD
 
-	case gc.OSQRT<<16 | gc.TFLOAT64:
+	case OSQRT_ | gc.TFLOAT64:
 		a = arm64.AFSQRTD
 	}
 
diff --git a/src/cmd/compile/internal/arm64/peep.go b/src/cmd/compile/internal/arm64/peep.go
index 387a30e..daa626f 100644
--- a/src/cmd/compile/internal/arm64/peep.go
+++ b/src/cmd/compile/internal/arm64/peep.go
@@ -710,7 +710,9 @@ func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
 		obj.APCDATA,
 		obj.AFUNCDATA,
 		obj.AVARDEF,
-		obj.AVARKILL:
+		obj.AVARKILL,
+		obj.AVARLIVE,
+		obj.AUSEFIELD:
 		return 0
 	}
 }
diff --git a/src/cmd/compile/internal/arm64/prog.go b/src/cmd/compile/internal/arm64/prog.go
index 1106e78..a8e8bc5 100644
--- a/src/cmd/compile/internal/arm64/prog.go
+++ b/src/cmd/compile/internal/arm64/prog.go
@@ -25,115 +25,116 @@ const (
 //
 // The table is formatted for 8-space tabs.
 var progtable = [arm64.ALAST]obj.ProgInfo{
-	obj.ATYPE:     {gc.Pseudo | gc.Skip, 0, 0, 0},
-	obj.ATEXT:     {gc.Pseudo, 0, 0, 0},
-	obj.AFUNCDATA: {gc.Pseudo, 0, 0, 0},
-	obj.APCDATA:   {gc.Pseudo, 0, 0, 0},
-	obj.AUNDEF:    {gc.Break, 0, 0, 0},
-	obj.AUSEFIELD: {gc.OK, 0, 0, 0},
-	obj.ACHECKNIL: {gc.LeftRead, 0, 0, 0},
-	obj.AVARDEF:   {gc.Pseudo | gc.RightWrite, 0, 0, 0},
-	obj.AVARKILL:  {gc.Pseudo | gc.RightWrite, 0, 0, 0},
+	obj.ATYPE:     {Flags: gc.Pseudo | gc.Skip},
+	obj.ATEXT:     {Flags: gc.Pseudo},
+	obj.AFUNCDATA: {Flags: gc.Pseudo},
+	obj.APCDATA:   {Flags: gc.Pseudo},
+	obj.AUNDEF:    {Flags: gc.Break},
+	obj.AUSEFIELD: {Flags: gc.OK},
+	obj.ACHECKNIL: {Flags: gc.LeftRead},
+	obj.AVARDEF:   {Flags: gc.Pseudo | gc.RightWrite},
+	obj.AVARKILL:  {Flags: gc.Pseudo | gc.RightWrite},
+	obj.AVARLIVE:  {Flags: gc.Pseudo | gc.LeftRead},
 
 	// NOP is an internal no-op that also stands
 	// for USED and SET annotations, not the Power opcode.
-	obj.ANOP:    {gc.LeftRead | gc.RightWrite, 0, 0, 0},
-	arm64.AHINT: {gc.OK, 0, 0, 0},
+	obj.ANOP:    {Flags: gc.LeftRead | gc.RightWrite},
+	arm64.AHINT: {Flags: gc.OK},
 
 	// Integer
-	arm64.AADD:   {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.ASUB:   {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.ANEG:   {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.AAND:   {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.AORR:   {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.AEOR:   {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.AMUL:   {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.ASMULL: {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.AUMULL: {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.ASMULH: {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.AUMULH: {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.ASDIV:  {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.AUDIV:  {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.ALSL:   {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.ALSR:   {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.AASR:   {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.ACMP:   {gc.SizeQ | gc.LeftRead | gc.RegRead, 0, 0, 0},
+	arm64.AADD:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.ASUB:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.ANEG:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.AAND:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.AORR:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.AEOR:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.AMUL:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.ASMULL: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.AUMULL: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.ASMULH: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.AUMULH: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.ASDIV:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.AUDIV:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.ALSL:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.ALSR:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.AASR:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.ACMP:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead},
 
 	// Floating point.
-	arm64.AFADDD:  {gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.AFADDS:  {gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.AFSUBD:  {gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.AFSUBS:  {gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.AFNEGD:  {gc.SizeD | gc.LeftRead | gc.RightWrite, 0, 0, 0},
-	arm64.AFNEGS:  {gc.SizeF | gc.LeftRead | gc.RightWrite, 0, 0, 0},
-	arm64.AFSQRTD: {gc.SizeD | gc.LeftRead | gc.RightWrite, 0, 0, 0},
-	arm64.AFMULD:  {gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.AFMULS:  {gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.AFDIVD:  {gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.AFDIVS:  {gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	arm64.AFCMPD:  {gc.SizeD | gc.LeftRead | gc.RegRead, 0, 0, 0},
-	arm64.AFCMPS:  {gc.SizeF | gc.LeftRead | gc.RegRead, 0, 0, 0},
+	arm64.AFADDD:  {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.AFADDS:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.AFSUBD:  {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.AFSUBS:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.AFNEGD:  {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite},
+	arm64.AFNEGS:  {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite},
+	arm64.AFSQRTD: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite},
+	arm64.AFMULD:  {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.AFMULS:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.AFDIVD:  {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.AFDIVS:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	arm64.AFCMPD:  {Flags: gc.SizeD | gc.LeftRead | gc.RegRead},
+	arm64.AFCMPS:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead},
 
 	// float -> integer
-	arm64.AFCVTZSD:  {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm64.AFCVTZSS:  {gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm64.AFCVTZSDW: {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm64.AFCVTZSSW: {gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm64.AFCVTZUD:  {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm64.AFCVTZUS:  {gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm64.AFCVTZUDW: {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm64.AFCVTZUSW: {gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
+	arm64.AFCVTZSD:  {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm64.AFCVTZSS:  {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm64.AFCVTZSDW: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm64.AFCVTZSSW: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm64.AFCVTZUD:  {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm64.AFCVTZUS:  {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm64.AFCVTZUDW: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm64.AFCVTZUSW: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
 
 	// float -> float
-	arm64.AFCVTSD: {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm64.AFCVTDS: {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
+	arm64.AFCVTSD: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm64.AFCVTDS: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
 
 	// integer -> float
-	arm64.ASCVTFD:  {gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm64.ASCVTFS:  {gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm64.ASCVTFWD: {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm64.ASCVTFWS: {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm64.AUCVTFD:  {gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm64.AUCVTFS:  {gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm64.AUCVTFWD: {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	arm64.AUCVTFWS: {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
+	arm64.ASCVTFD:  {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm64.ASCVTFS:  {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm64.ASCVTFWD: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm64.ASCVTFWS: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm64.AUCVTFD:  {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm64.AUCVTFS:  {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm64.AUCVTFWD: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	arm64.AUCVTFWS: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
 
 	// Moves
-	arm64.AMOVB:  {gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
-	arm64.AMOVBU: {gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
-	arm64.AMOVH:  {gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
-	arm64.AMOVHU: {gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
-	arm64.AMOVW:  {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
-	arm64.AMOVWU: {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
-	arm64.AMOVD:  {gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
-	arm64.AFMOVS: {gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
-	arm64.AFMOVD: {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
+	arm64.AMOVB:  {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+	arm64.AMOVBU: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+	arm64.AMOVH:  {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+	arm64.AMOVHU: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+	arm64.AMOVW:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+	arm64.AMOVWU: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+	arm64.AMOVD:  {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move},
+	arm64.AFMOVS: {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+	arm64.AFMOVD: {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
 
 	// Jumps
-	arm64.AB:      {gc.Jump | gc.Break, 0, 0, 0},
-	arm64.ABL:     {gc.Call, 0, 0, 0},
-	arm64.ABEQ:    {gc.Cjmp, 0, 0, 0},
-	arm64.ABNE:    {gc.Cjmp, 0, 0, 0},
-	arm64.ABGE:    {gc.Cjmp, 0, 0, 0},
-	arm64.ABLT:    {gc.Cjmp, 0, 0, 0},
-	arm64.ABGT:    {gc.Cjmp, 0, 0, 0},
-	arm64.ABLE:    {gc.Cjmp, 0, 0, 0},
-	arm64.ABLO:    {gc.Cjmp, 0, 0, 0},
-	arm64.ABLS:    {gc.Cjmp, 0, 0, 0},
-	arm64.ABHI:    {gc.Cjmp, 0, 0, 0},
-	arm64.ABHS:    {gc.Cjmp, 0, 0, 0},
-	arm64.ACBZ:    {gc.Cjmp, 0, 0, 0},
-	arm64.ACBNZ:   {gc.Cjmp, 0, 0, 0},
-	obj.ARET:      {gc.Break, 0, 0, 0},
-	obj.ADUFFZERO: {gc.Call, 0, 0, 0},
-	obj.ADUFFCOPY: {gc.Call, 0, 0, 0},
+	arm64.AB:      {Flags: gc.Jump | gc.Break},
+	arm64.ABL:     {Flags: gc.Call},
+	arm64.ABEQ:    {Flags: gc.Cjmp},
+	arm64.ABNE:    {Flags: gc.Cjmp},
+	arm64.ABGE:    {Flags: gc.Cjmp},
+	arm64.ABLT:    {Flags: gc.Cjmp},
+	arm64.ABGT:    {Flags: gc.Cjmp},
+	arm64.ABLE:    {Flags: gc.Cjmp},
+	arm64.ABLO:    {Flags: gc.Cjmp},
+	arm64.ABLS:    {Flags: gc.Cjmp},
+	arm64.ABHI:    {Flags: gc.Cjmp},
+	arm64.ABHS:    {Flags: gc.Cjmp},
+	arm64.ACBZ:    {Flags: gc.Cjmp},
+	arm64.ACBNZ:   {Flags: gc.Cjmp},
+	obj.ARET:      {Flags: gc.Break},
+	obj.ADUFFZERO: {Flags: gc.Call},
+	obj.ADUFFCOPY: {Flags: gc.Call},
 }
 
 func proginfo(p *obj.Prog) {
 	info := &p.Info
 	*info = progtable[p.As]
 	if info.Flags == 0 {
-		gc.Fatal("proginfo: unknown instruction %v", p)
+		gc.Fatalf("proginfo: unknown instruction %v", p)
 	}
 
 	if (info.Flags&gc.RegRead != 0) && p.Reg == 0 {
diff --git a/src/cmd/compile/internal/big/decimal.go b/src/cmd/compile/internal/big/decimal.go
index 2595e5f..2c0c9da 100644
--- a/src/cmd/compile/internal/big/decimal.go
+++ b/src/cmd/compile/internal/big/decimal.go
@@ -20,7 +20,7 @@
 package big
 
 // A decimal represents an unsigned floating-point number in decimal representation.
-// The value of a non-zero decimal x is x.mant * 10 ** x.exp with 0.5 <= x.mant < 1,
+// The value of a non-zero decimal d is d.mant * 10**d.exp with 0.5 <= d.mant < 1,
 // with the most-significant mantissa digit at index 0. For the zero decimal, the
 // mantissa length and exponent are 0.
 // The zero value for decimal represents a ready-to-use 0.0.
@@ -29,6 +29,14 @@ type decimal struct {
 	exp  int    // exponent
 }
 
+// at returns the i'th mantissa digit, starting with the most significant digit at 0.
+func (d *decimal) at(i int) byte {
+	if 0 <= i && i < len(d.mant) {
+		return d.mant[i]
+	}
+	return '0'
+}
+
 // Maximum shift amount that can be done in one pass without overflow.
 // A Word has _W bits and (1<<maxShift - 1)*10 + 9 must fit into Word.
 const maxShift = _W - 4
@@ -72,7 +80,7 @@ func (x *decimal) init(m nat, shift int) {
 	}
 
 	// Convert mantissa into decimal representation.
-	s := m.decimalString() // TODO(gri) avoid string conversion here
+	s := m.utoa(10)
 	n := len(s)
 	x.exp = n
 	// Trim trailing zeros; instead the exponent is tracking
@@ -92,12 +100,6 @@ func (x *decimal) init(m nat, shift int) {
 	}
 }
 
-// Possibly optimization: The current implementation of nat.string takes
-// a charset argument. When a right shift is needed, we could provide
-// "\x00\x01...\x09" instead of "012..9" (as in nat.decimalString) and
-// avoid the repeated +'0' and -'0' operations in decimal.shr (and do a
-// single +'0' pass at the end).
-
 // shr implements x >> s, for s <= maxShift.
 func shr(x *decimal, s uint) {
 	// Division by 1<<s using shift-and-subtract algorithm.
diff --git a/src/cmd/compile/internal/big/decimal_test.go b/src/cmd/compile/internal/big/decimal_test.go
index 81e022a..15bdb18 100644
--- a/src/cmd/compile/internal/big/decimal_test.go
+++ b/src/cmd/compile/internal/big/decimal_test.go
@@ -104,3 +104,13 @@ func TestDecimalRounding(t *testing.T) {
 		}
 	}
 }
+
+func BenchmarkDecimalConversion(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for shift := -100; shift <= +100; shift++ {
+			var d decimal
+			d.init(natOne, shift)
+			d.String()
+		}
+	}
+}
diff --git a/src/cmd/compile/internal/big/example_test.go b/src/cmd/compile/internal/big/example_test.go
index cb91bc2..8a71a08 100644
--- a/src/cmd/compile/internal/big/example_test.go
+++ b/src/cmd/compile/internal/big/example_test.go
@@ -8,6 +8,7 @@ import (
 	"cmd/compile/internal/big"
 	"fmt"
 	"log"
+	"math"
 )
 
 func ExampleRat_SetString() {
@@ -49,3 +50,79 @@ func ExampleInt_Scan() {
 	}
 	// Output: 18446744073709551617
 }
+
+// This example demonstrates how to use big.Int to compute the smallest
+// Fibonacci number with 100 decimal digits and to test whether it is prime.
+func Example_fibonacci() {
+	// Initialize two big ints with the first two numbers in the sequence.
+	a := big.NewInt(0)
+	b := big.NewInt(1)
+
+	// Initialize limit as 10^99, the smallest integer with 100 digits.
+	var limit big.Int
+	limit.Exp(big.NewInt(10), big.NewInt(99), nil)
+
+	// Loop while a is smaller than 1e100.
+	for a.Cmp(&limit) < 0 {
+		// Compute the next Fibonacci number, storing it in a.
+		a.Add(a, b)
+		// Swap a and b so that b is the next number in the sequence.
+		a, b = b, a
+	}
+	fmt.Println(a) // 100-digit Fibonacci number
+
+	// Test a for primality.
+	// (ProbablyPrimes' argument sets the number of Miller-Rabin
+	// rounds to be performed. 20 is a good value.)
+	fmt.Println(a.ProbablyPrime(20))
+
+	// Output:
+	// 1344719667586153181419716641724567886890850696275767987106294472017884974410332069524504824747437757
+	// false
+}
+
+// This example shows how to use big.Float to compute the square root of 2 with
+// a precision of 200 bits, and how to print the result as a decimal number.
+func Example_sqrt2() {
+	// We'll do computations with 200 bits of precision in the mantissa.
+	const prec = 200
+
+	// Compute the square root of 2 using Newton's Method. We start with
+	// an initial estimate for sqrt(2), and then iterate:
+	//     x_{n+1} = 1/2 * ( x_n + (2.0 / x_n) )
+
+	// Since Newton's Method doubles the number of correct digits at each
+	// iteration, we need at least log_2(prec) steps.
+	steps := int(math.Log2(prec))
+
+	// Initialize values we need for the computation.
+	two := new(big.Float).SetPrec(prec).SetInt64(2)
+	half := new(big.Float).SetPrec(prec).SetFloat64(0.5)
+
+	// Use 1 as the initial estimate.
+	x := new(big.Float).SetPrec(prec).SetInt64(1)
+
+	// We use t as a temporary variable. There's no need to set its precision
+	// since big.Float values with unset (== 0) precision automatically assume
+	// the largest precision of the arguments when used as the result (receiver)
+	// of a big.Float operation.
+	t := new(big.Float)
+
+	// Iterate.
+	for i := 0; i <= steps; i++ {
+		t.Quo(two, x)  // t = 2.0 / x_n
+		t.Add(x, t)    // t = x_n + (2.0 / x_n)
+		x.Mul(half, t) // x_{n+1} = 0.5 * t
+	}
+
+	// We can use the usual fmt.Printf verbs since big.Float implements fmt.Formatter
+	fmt.Printf("sqrt(2) = %.50f\n", x)
+
+	// Print the error between 2 and x*x.
+	t.Mul(x, x) // t = x*x
+	fmt.Printf("error = %e\n", t.Sub(two, t))
+
+	// Output:
+	// sqrt(2) = 1.41421356237309504880168872420969807856967187537695
+	// error = 0.000000e+00
+}
diff --git a/src/cmd/compile/internal/big/float.go b/src/cmd/compile/internal/big/float.go
index d7aa895..b1c748c 100644
--- a/src/cmd/compile/internal/big/float.go
+++ b/src/cmd/compile/internal/big/float.go
@@ -124,7 +124,7 @@ const (
 // rounding error is described by the Float's Accuracy.
 type RoundingMode byte
 
-// The following rounding modes are supported.
+// These constants define supported rounding modes.
 const (
 	ToNearestEven RoundingMode = iota // == IEEE 754-2008 roundTiesToEven
 	ToNearestAway                     // == IEEE 754-2008 roundTiesToAway
@@ -298,7 +298,7 @@ func (z *Float) setExpAndRound(exp int64, sbit uint) {
 // not require 0.5 <= |mant| < 1.0. Specifically:
 //
 //	mant := new(Float)
-//	new(Float).SetMantExp(mant, x.SetMantExp(mant)).Cmp(x).Eql() is true
+//	new(Float).SetMantExp(mant, x.MantExp(mant)).Cmp(x) == 0
 //
 // Special cases are:
 //
@@ -1123,7 +1123,7 @@ func (x *Float) Int(z *Int) (*Int, Accuracy) {
 
 // Rat returns the rational number corresponding to x;
 // or nil if x is an infinity.
-// The result is Exact is x is not an Inf.
+// The result is Exact if x is not an Inf.
 // If a non-nil *Rat argument z is provided, Rat stores
 // the result in z instead of allocating a new Rat.
 func (x *Float) Rat(z *Rat) (*Rat, Accuracy) {
@@ -1272,7 +1272,7 @@ func (z *Float) usub(x, y *Float) {
 		ex = ey
 	}
 
-	// operands may have cancelled each other out
+	// operands may have canceled each other out
 	if len(z.mant) == 0 {
 		z.acc = Exact
 		z.form = zero
diff --git a/src/cmd/compile/internal/big/floatconv.go b/src/cmd/compile/internal/big/floatconv.go
index 4a070ca..37d5c06 100644
--- a/src/cmd/compile/internal/big/floatconv.go
+++ b/src/cmd/compile/internal/big/floatconv.go
@@ -72,37 +72,46 @@ func (z *Float) scan(r io.ByteScanner, base int) (f *Float, b int, err error) {
 	// ebase**exp. Finally, mantissa normalization (shift left) requires
 	// a correcting multiplication by 2**(-shiftcount). Multiplications
 	// are commutative, so we can apply them in any order as long as there
-	// is no loss of precision. We only have powers of 2 and 10; keep
-	// track via separate exponents exp2 and exp10.
+	// is no loss of precision. We only have powers of 2 and 10, and
+	// we split powers of 10 into the product of the same powers of
+	// 2 and 5. This reduces the size of the multiplication factor
+	// needed for base-10 exponents.
 
-	// normalize mantissa and get initial binary exponent
-	var exp2 = int64(len(z.mant))*_W - fnorm(z.mant)
+	// normalize mantissa and determine initial exponent contributions
+	exp2 := int64(len(z.mant))*_W - fnorm(z.mant)
+	exp5 := int64(0)
 
 	// determine binary or decimal exponent contribution of decimal point
-	var exp10 int64
 	if fcount < 0 {
 		// The mantissa has a "decimal" point ddd.dddd; and
 		// -fcount is the number of digits to the right of '.'.
 		// Adjust relevant exponent accodingly.
+		d := int64(fcount)
 		switch b {
-		case 16:
-			fcount *= 4 // hexadecimal digits are 4 bits each
-			fallthrough
+		case 10:
+			exp5 = d
+			fallthrough // 10**e == 5**e * 2**e
 		case 2:
-			exp2 += int64(fcount)
-		default: // b == 10
-			exp10 = int64(fcount)
+			exp2 += d
+		case 16:
+			exp2 += d * 4 // hexadecimal digits are 4 bits each
+		default:
+			panic("unexpected mantissa base")
 		}
-		// we don't need fcount anymore
+		// fcount consumed - not needed anymore
 	}
 
 	// take actual exponent into account
-	if ebase == 2 {
+	switch ebase {
+	case 10:
+		exp5 += exp
+		fallthrough
+	case 2:
 		exp2 += exp
-	} else { // ebase == 10
-		exp10 += exp
+	default:
+		panic("unexpected exponent base")
 	}
-	// we don't need exp anymore
+	// exp consumed - not needed anymore
 
 	// apply 2**exp2
 	if MinExp <= exp2 && exp2 <= MaxExp {
@@ -115,49 +124,76 @@ func (z *Float) scan(r io.ByteScanner, base int) (f *Float, b int, err error) {
 		return
 	}
 
-	if exp10 == 0 {
-		// no decimal exponent to consider
+	if exp5 == 0 {
+		// no decimal exponent contribution
 		z.round(0)
 		return
 	}
-	// exp10 != 0
+	// exp5 != 0
 
-	// apply 10**exp10
+	// apply 5**exp5
 	p := new(Float).SetPrec(z.Prec() + 64) // use more bits for p -- TODO(gri) what is the right number?
-	if exp10 < 0 {
-		z.uquo(z, p.pow10(-exp10))
+	if exp5 < 0 {
+		z.Quo(z, p.pow5(uint64(-exp5)))
 	} else {
-		z.umul(z, p.pow10(exp10))
+		z.Mul(z, p.pow5(uint64(exp5)))
 	}
 
 	return
 }
 
-// These powers of 10 can be represented exactly as a float64.
-var pow10tab = [...]float64{
-	1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
-	1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+// These powers of 5 fit into a uint64.
+//
+//	for p, q := uint64(0), uint64(1); p < q; p, q = q, q*5 {
+//		fmt.Println(q)
+//	}
+//
+var pow5tab = [...]uint64{
+	1,
+	5,
+	25,
+	125,
+	625,
+	3125,
+	15625,
+	78125,
+	390625,
+	1953125,
+	9765625,
+	48828125,
+	244140625,
+	1220703125,
+	6103515625,
+	30517578125,
+	152587890625,
+	762939453125,
+	3814697265625,
+	19073486328125,
+	95367431640625,
+	476837158203125,
+	2384185791015625,
+	11920928955078125,
+	59604644775390625,
+	298023223876953125,
+	1490116119384765625,
+	7450580596923828125,
 }
 
-// pow10 sets z to 10**n and returns z.
+// pow5 sets z to 5**n and returns z.
 // n must not be negative.
-func (z *Float) pow10(n int64) *Float {
-	if n < 0 {
-		panic("pow10 called with negative argument")
-	}
-
-	const m = int64(len(pow10tab) - 1)
+func (z *Float) pow5(n uint64) *Float {
+	const m = uint64(len(pow5tab) - 1)
 	if n <= m {
-		return z.SetFloat64(pow10tab[n])
+		return z.SetUint64(pow5tab[n])
 	}
 	// n > m
 
-	z.SetFloat64(pow10tab[m])
+	z.SetUint64(pow5tab[m])
 	n -= m
 
 	// use more bits for f than for z
 	// TODO(gri) what is the right number?
-	f := new(Float).SetPrec(z.Prec() + 64).SetInt64(10)
+	f := new(Float).SetPrec(z.Prec() + 64).SetUint64(5)
 
 	for n > 0 {
 		if n&1 != 0 {
diff --git a/src/cmd/compile/internal/big/floatconv_test.go b/src/cmd/compile/internal/big/floatconv_test.go
index 4f23953..b6f9993 100644
--- a/src/cmd/compile/internal/big/floatconv_test.go
+++ b/src/cmd/compile/internal/big/floatconv_test.go
@@ -139,6 +139,8 @@ func TestFloatSetFloat64String(t *testing.T) {
 	}
 }
 
+func fdiv(a, b float64) float64 { return a / b }
+
 const (
 	below1e23 = 99999999999999974834176
 	above1e23 = 100000000000000008388608
@@ -187,11 +189,11 @@ func TestFloat64Text(t *testing.T) {
 		{1, 'e', 5, "1.00000e+00"},
 		{1, 'f', 5, "1.00000"},
 		{1, 'g', 5, "1"},
-		// {1, 'g', -1, "1"},
-		// {20, 'g', -1, "20"},
-		// {1234567.8, 'g', -1, "1.2345678e+06"},
-		// {200000, 'g', -1, "200000"},
-		// {2000000, 'g', -1, "2e+06"},
+		{1, 'g', -1, "1"},
+		{20, 'g', -1, "20"},
+		{1234567.8, 'g', -1, "1.2345678e+06"},
+		{200000, 'g', -1, "200000"},
+		{2000000, 'g', -1, "2e+06"},
 
 		// g conversion and zero suppression
 		{400, 'g', 2, "4e+02"},
@@ -207,22 +209,22 @@ func TestFloat64Text(t *testing.T) {
 		{0, 'e', 5, "0.00000e+00"},
 		{0, 'f', 5, "0.00000"},
 		{0, 'g', 5, "0"},
-		// {0, 'g', -1, "0"},
+		{0, 'g', -1, "0"},
 
 		{-1, 'e', 5, "-1.00000e+00"},
 		{-1, 'f', 5, "-1.00000"},
 		{-1, 'g', 5, "-1"},
-		// {-1, 'g', -1, "-1"},
+		{-1, 'g', -1, "-1"},
 
 		{12, 'e', 5, "1.20000e+01"},
 		{12, 'f', 5, "12.00000"},
 		{12, 'g', 5, "12"},
-		// {12, 'g', -1, "12"},
+		{12, 'g', -1, "12"},
 
 		{123456700, 'e', 5, "1.23457e+08"},
 		{123456700, 'f', 5, "123456700.00000"},
 		{123456700, 'g', 5, "1.2346e+08"},
-		// {123456700, 'g', -1, "1.234567e+08"},
+		{123456700, 'g', -1, "1.234567e+08"},
 
 		{1.2345e6, 'e', 5, "1.23450e+06"},
 		{1.2345e6, 'f', 5, "1234500.00000"},
@@ -232,36 +234,38 @@ func TestFloat64Text(t *testing.T) {
 		{1e23, 'f', 17, "99999999999999991611392.00000000000000000"},
 		{1e23, 'g', 17, "9.9999999999999992e+22"},
 
-		// {1e23, 'e', -1, "1e+23"},
-		// {1e23, 'f', -1, "100000000000000000000000"},
-		// {1e23, 'g', -1, "1e+23"},
+		{1e23, 'e', -1, "1e+23"},
+		{1e23, 'f', -1, "100000000000000000000000"},
+		{1e23, 'g', -1, "1e+23"},
 
 		{below1e23, 'e', 17, "9.99999999999999748e+22"},
 		{below1e23, 'f', 17, "99999999999999974834176.00000000000000000"},
 		{below1e23, 'g', 17, "9.9999999999999975e+22"},
 
-		// {below1e23, 'e', -1, "9.999999999999997e+22"},
-		// {below1e23, 'f', -1, "99999999999999970000000"},
-		// {below1e23, 'g', -1, "9.999999999999997e+22"},
+		{below1e23, 'e', -1, "9.999999999999997e+22"},
+		{below1e23, 'f', -1, "99999999999999970000000"},
+		{below1e23, 'g', -1, "9.999999999999997e+22"},
 
 		{above1e23, 'e', 17, "1.00000000000000008e+23"},
 		{above1e23, 'f', 17, "100000000000000008388608.00000000000000000"},
-		// {above1e23, 'g', 17, "1.0000000000000001e+23"},
+		{above1e23, 'g', 17, "1.0000000000000001e+23"},
 
-		// {above1e23, 'e', -1, "1.0000000000000001e+23"},
-		// {above1e23, 'f', -1, "100000000000000010000000"},
-		// {above1e23, 'g', -1, "1.0000000000000001e+23"},
+		{above1e23, 'e', -1, "1.0000000000000001e+23"},
+		{above1e23, 'f', -1, "100000000000000010000000"},
+		{above1e23, 'g', -1, "1.0000000000000001e+23"},
 
-		// {fdiv(5e-304, 1e20), 'g', -1, "5e-324"},
-		// {fdiv(-5e-304, 1e20), 'g', -1, "-5e-324"},
+		{5e-304 / 1e20, 'g', -1, "5e-324"},
+		{-5e-304 / 1e20, 'g', -1, "-5e-324"},
+		{fdiv(5e-304, 1e20), 'g', -1, "5e-324"},   // avoid constant arithmetic
+		{fdiv(-5e-304, 1e20), 'g', -1, "-5e-324"}, // avoid constant arithmetic
 
-		// {32, 'g', -1, "32"},
-		// {32, 'g', 0, "3e+01"},
+		{32, 'g', -1, "32"},
+		{32, 'g', 0, "3e+01"},
 
-		// {100, 'x', -1, "%x"},
+		{100, 'x', -1, "%x"},
 
-		// {math.NaN(), 'g', -1, "NaN"},
-		// {-math.NaN(), 'g', -1, "NaN"},
+		// {math.NaN(), 'g', -1, "NaN"},  // Float doesn't support NaNs
+		// {-math.NaN(), 'g', -1, "NaN"}, // Float doesn't support NaNs
 		{math.Inf(0), 'g', -1, "+Inf"},
 		{math.Inf(-1), 'g', -1, "-Inf"},
 		{-math.Inf(0), 'g', -1, "-Inf"},
@@ -279,18 +283,24 @@ func TestFloat64Text(t *testing.T) {
 		{1.5, 'f', 0, "2"},
 
 		// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
-		// {2.2250738585072012e-308, 'g', -1, "2.2250738585072014e-308"},
+		{2.2250738585072012e-308, 'g', -1, "2.2250738585072014e-308"},
 		// http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
-		// {2.2250738585072011e-308, 'g', -1, "2.225073858507201e-308"},
+		{2.2250738585072011e-308, 'g', -1, "2.225073858507201e-308"},
 
 		// Issue 2625.
 		{383260575764816448, 'f', 0, "383260575764816448"},
-		// {383260575764816448, 'g', -1, "3.8326057576481645e+17"},
+		{383260575764816448, 'g', -1, "3.8326057576481645e+17"},
 	} {
-		f := new(Float).SetFloat64(test.x)
+		// The test cases are from the strconv package which tests float64 values.
+		// When formatting values with prec = -1 (shortest representation),
+		// the actually available mantissa precision matters.
+		// For denormalized values, that precision is < 53 (SetFloat64 default).
+		// Compute and set the actual precision explicitly.
+		f := new(Float).SetPrec(actualPrec(test.x)).SetFloat64(test.x)
 		got := f.Text(test.format, test.prec)
 		if got != test.want {
 			t.Errorf("%v: got %s; want %s", test, got, test.want)
+			continue
 		}
 
 		if test.format == 'b' && test.x == 0 {
@@ -308,6 +318,15 @@ func TestFloat64Text(t *testing.T) {
 	}
 }
 
+// actualPrec returns the number of actually used mantissa bits.
+func actualPrec(x float64) uint {
+	if bits := math.Float64bits(x); x != 0 && bits&(0x7ff<<52) == 0 {
+		// x is denormalized
+		return 64 - nlz64(bits&(1<<52-1))
+	}
+	return 53
+}
+
 func TestFloatText(t *testing.T) {
 	for _, test := range []struct {
 		x      string
@@ -367,9 +386,19 @@ func TestFloatText(t *testing.T) {
 
 		// make sure "stupid" exponents don't stall the machine
 		{"1e1000000", 64, 'p', 0, "0x.88b3a28a05eade3ap+3321929"},
-		{"1e1000000000", 64, 'p', 0, "0x.ecc5f45aa573d3p+1538481529"},
+		{"1e646456992", 64, 'p', 0, "0x.e883a0c5c8c7c42ap+2147483644"},
+		{"1e646456993", 64, 'p', 0, "+Inf"},
+		{"1e1000000000", 64, 'p', 0, "+Inf"},
 		{"1e-1000000", 64, 'p', 0, "0x.efb4542cc8ca418ap-3321928"},
-		{"1e-1000000000", 64, 'p', 0, "0x.8a64dd983a4c7dabp-1538481528"},
+		{"1e-646456993", 64, 'p', 0, "0x.e17c8956983d9d59p-2147483647"},
+		{"1e-646456994", 64, 'p', 0, "0"},
+		{"1e-1000000000", 64, 'p', 0, "0"},
+
+		// minimum and maximum values
+		{"1p2147483646", 64, 'p', 0, "0x.8p+2147483647"},
+		{"0x.8p2147483647", 64, 'p', 0, "0x.8p+2147483647"},
+		{"0x.8p-2147483647", 64, 'p', 0, "0x.8p-2147483647"},
+		{"1p-2147483649", 64, 'p', 0, "0x.8p-2147483648"},
 
 		// TODO(gri) need tests for actual large Floats
 
@@ -438,9 +467,6 @@ func TestFloatFormat(t *testing.T) {
 		value  interface{} // float32, float64, or string (== 512bit *Float)
 		want   string
 	}{
-		// TODO(gri) uncomment the disabled 'g'/'G' formats
-		// 	     below once (*Float).Text supports prec < 0
-
 		// from fmt/fmt_test.go
 		{"%+.3e", 0.0, "+0.000e+00"},
 		{"%+.3e", 1.0, "+1.000e+00"},
@@ -471,9 +497,9 @@ func TestFloatFormat(t *testing.T) {
 		{"%f", 1234.5678e-8, "0.000012"},
 		{"%f", -7.0, "-7.000000"},
 		{"%f", -1e-9, "-0.000000"},
-		// {"%g", 1234.5678e3, "1.2345678e+06"},
-		// {"%g", float32(1234.5678e3), "1.2345678e+06"},
-		// {"%g", 1234.5678e-8, "1.2345678e-05"},
+		{"%g", 1234.5678e3, "1.2345678e+06"},
+		{"%g", float32(1234.5678e3), "1.2345678e+06"},
+		{"%g", 1234.5678e-8, "1.2345678e-05"},
 		{"%g", -7.0, "-7"},
 		{"%g", -1e-9, "-1e-09"},
 		{"%g", float32(-1e-9), "-1e-09"},
@@ -482,9 +508,9 @@ func TestFloatFormat(t *testing.T) {
 		{"%E", 1234.5678e-8, "1.234568E-05"},
 		{"%E", -7.0, "-7.000000E+00"},
 		{"%E", -1e-9, "-1.000000E-09"},
-		// {"%G", 1234.5678e3, "1.2345678E+06"},
-		// {"%G", float32(1234.5678e3), "1.2345678E+06"},
-		// {"%G", 1234.5678e-8, "1.2345678E-05"},
+		{"%G", 1234.5678e3, "1.2345678E+06"},
+		{"%G", float32(1234.5678e3), "1.2345678E+06"},
+		{"%G", 1234.5678e-8, "1.2345678E-05"},
 		{"%G", -7.0, "-7"},
 		{"%G", -1e-9, "-1E-09"},
 		{"%G", float32(-1e-9), "-1E-09"},
@@ -500,9 +526,9 @@ func TestFloatFormat(t *testing.T) {
 		{"%-20f", 1.23456789e3, "1234.567890         "},
 		{"%20.8f", 1.23456789e3, "       1234.56789000"},
 		{"%20.8f", 1.23456789e-3, "          0.00123457"},
-		// {"%g", 1.23456789e3, "1234.56789"},
-		// {"%g", 1.23456789e-3, "0.00123456789"},
-		// {"%g", 1.23456789e20, "1.23456789e+20"},
+		{"%g", 1.23456789e3, "1234.56789"},
+		{"%g", 1.23456789e-3, "0.00123456789"},
+		{"%g", 1.23456789e20, "1.23456789e+20"},
 		{"%20e", math.Inf(1), "                +Inf"},
 		{"%-20f", math.Inf(-1), "-Inf                "},
 
@@ -541,7 +567,6 @@ func TestFloatFormat(t *testing.T) {
 		{"%v", -1e-9, "-1e-09"},
 		{"%v", float32(-1e-9), "-1e-09"},
 		{"%010v", 0.0, "0000000000"},
-		{"%010v", 0.0, "0000000000"},
 
 		// *Float cases
 		{"%.20f", "1e-20", "0.00000000000000000001"},
@@ -571,3 +596,67 @@ func TestFloatFormat(t *testing.T) {
 		}
 	}
 }
+
+func BenchmarkParseFloatSmallExp(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, s := range []string{
+			"1e0",
+			"1e-1",
+			"1e-2",
+			"1e-3",
+			"1e-4",
+			"1e-5",
+			"1e-10",
+			"1e-20",
+			"1e-50",
+			"1e1",
+			"1e2",
+			"1e3",
+			"1e4",
+			"1e5",
+			"1e10",
+			"1e20",
+			"1e50",
+		} {
+			var x Float
+			_, _, err := x.Parse(s, 0)
+			if err != nil {
+				b.Fatalf("%s: %v", s, err)
+			}
+		}
+	}
+}
+
+func BenchmarkParseFloatLargeExp(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, s := range []string{
+			"1e0",
+			"1e-10",
+			"1e-20",
+			"1e-30",
+			"1e-40",
+			"1e-50",
+			"1e-100",
+			"1e-500",
+			"1e-1000",
+			"1e-5000",
+			"1e-10000",
+			"1e10",
+			"1e20",
+			"1e30",
+			"1e40",
+			"1e50",
+			"1e100",
+			"1e500",
+			"1e1000",
+			"1e5000",
+			"1e10000",
+		} {
+			var x Float
+			_, _, err := x.Parse(s, 0)
+			if err != nil {
+				b.Fatalf("%s: %v", s, err)
+			}
+		}
+	}
+}
diff --git a/src/cmd/compile/internal/big/floatexample_test.go b/src/cmd/compile/internal/big/floatexample_test.go
index 6fd291c..83c6bda 100644
--- a/src/cmd/compile/internal/big/floatexample_test.go
+++ b/src/cmd/compile/internal/big/floatexample_test.go
@@ -109,3 +109,33 @@ func ExampleFloat_Cmp() {
 	// +Inf   1.2    1
 	// +Inf  +Inf    0
 }
+
+func ExampleRoundingMode() {
+	operands := []float64{2.6, 2.5, 2.1, -2.1, -2.5, -2.6}
+
+	fmt.Print("   x")
+	for mode := big.ToNearestEven; mode <= big.ToPositiveInf; mode++ {
+		fmt.Printf("  %s", mode)
+	}
+	fmt.Println()
+
+	for _, f64 := range operands {
+		fmt.Printf("%4g", f64)
+		for mode := big.ToNearestEven; mode <= big.ToPositiveInf; mode++ {
+			// sample operands above require 2 bits to represent mantissa
+			// set binary precision to 2 to round them to integer values
+			f := new(big.Float).SetPrec(2).SetMode(mode).SetFloat64(f64)
+			fmt.Printf("  %*g", len(mode.String()), f)
+		}
+		fmt.Println()
+	}
+
+	// Output:
+	//    x  ToNearestEven  ToNearestAway  ToZero  AwayFromZero  ToNegativeInf  ToPositiveInf
+	//  2.6              3              3       2             3              2              3
+	//  2.5              2              3       2             3              2              3
+	//  2.1              2              2       2             3              2              3
+	// -2.1             -2             -2      -2            -3             -3             -2
+	// -2.5             -2             -3      -2            -3             -3             -2
+	// -2.6             -3             -3      -2            -3             -3             -2
+}
diff --git a/src/cmd/compile/internal/big/ftoa.go b/src/cmd/compile/internal/big/ftoa.go
index 5c5f2ce..c5cdb5e 100644
--- a/src/cmd/compile/internal/big/ftoa.go
+++ b/src/cmd/compile/internal/big/ftoa.go
@@ -9,9 +9,9 @@
 package big
 
 import (
+	"bytes"
 	"fmt"
 	"strconv"
-	"strings"
 )
 
 // Text converts the floating-point number x to a string according
@@ -37,16 +37,16 @@ import (
 // printed by the 'e', 'E', 'f', 'g', and 'G' formats. For 'e', 'E', and 'f'
 // it is the number of digits after the decimal point. For 'g' and 'G' it is
 // the total number of digits. A negative precision selects the smallest
-// number of digits necessary to identify the value x uniquely.
+// number of decimal digits necessary to identify the value x uniquely using
+// x.Prec() mantissa bits.
 // The prec value is ignored for the 'b' or 'p' format.
-//
-// BUG(gri) Float.Text does not accept negative precisions (issue #10991).
 func (x *Float) Text(format byte, prec int) string {
 	const extra = 10 // TODO(gri) determine a good/better value here
 	return string(x.Append(make([]byte, 0, prec+extra), format, prec))
 }
 
 // String formats x like x.Text('g', 10).
+// (String must be called explicitly, Float.Format does not support %s verb.)
 func (x *Float) String() string {
 	return x.Text('g', 10)
 }
@@ -83,6 +83,7 @@ func (x *Float) Append(buf []byte, fmt byte, prec int) []byte {
 	// 1) convert Float to multiprecision decimal
 	var d decimal // == 0.0
 	if x.form == finite {
+		// x != 0
 		d.init(x.mant, int(x.exp)-x.mant.bitLen())
 	}
 
@@ -90,9 +91,7 @@ func (x *Float) Append(buf []byte, fmt byte, prec int) []byte {
 	shortest := false
 	if prec < 0 {
 		shortest = true
-		panic("unimplemented")
-		// TODO(gri) complete this
-		// roundShortest(&d, f.mant, int(f.exp))
+		roundShortest(&d, x)
 		// Precision for shortest representation mode.
 		switch fmt {
 		case 'e', 'E':
@@ -158,6 +157,80 @@ func (x *Float) Append(buf []byte, fmt byte, prec int) []byte {
 	return append(buf, '%', fmt)
 }
 
+func roundShortest(d *decimal, x *Float) {
+	// if the mantissa is zero, the number is zero - stop now
+	if len(d.mant) == 0 {
+		return
+	}
+
+	// Approach: All numbers in the interval [x - 1/2ulp, x + 1/2ulp]
+	// (possibly exclusive) round to x for the given precision of x.
+	// Compute the lower and upper bound in decimal form and find the
+	// shortest decimal number d such that lower <= d <= upper.
+
+	// TODO(gri) strconv/ftoa.do describes a shortcut in some cases.
+	// See if we can use it (in adjusted form) here as well.
+
+	// 1) Compute normalized mantissa mant and exponent exp for x such
+	// that the lsb of mant corresponds to 1/2 ulp for the precision of
+	// x (i.e., for mant we want x.prec + 1 bits).
+	mant := nat(nil).set(x.mant)
+	exp := int(x.exp) - mant.bitLen()
+	s := mant.bitLen() - int(x.prec+1)
+	switch {
+	case s < 0:
+		mant = mant.shl(mant, uint(-s))
+	case s > 0:
+		mant = mant.shr(mant, uint(+s))
+	}
+	exp += s
+	// x = mant * 2**exp with lsb(mant) == 1/2 ulp of x.prec
+
+	// 2) Compute lower bound by subtracting 1/2 ulp.
+	var lower decimal
+	var tmp nat
+	lower.init(tmp.sub(mant, natOne), exp)
+
+	// 3) Compute upper bound by adding 1/2 ulp.
+	var upper decimal
+	upper.init(tmp.add(mant, natOne), exp)
+
+	// The upper and lower bounds are possible outputs only if
+	// the original mantissa is even, so that ToNearestEven rounding
+	// would round to the original mantissa and not the neighbors.
+	inclusive := mant[0]&2 == 0 // test bit 1 since original mantissa was shifted by 1
+
+	// Now we can figure out the minimum number of digits required.
+	// Walk along until d has distinguished itself from upper and lower.
+	for i, m := range d.mant {
+		l := lower.at(i)
+		u := upper.at(i)
+
+		// Okay to round down (truncate) if lower has a different digit
+		// or if lower is inclusive and is exactly the result of rounding
+		// down (i.e., and we have reached the final digit of lower).
+		okdown := l != m || inclusive && i+1 == len(lower.mant)
+
+		// Okay to round up if upper has a different digit and either upper
+		// is inclusive or upper is bigger than the result of rounding up.
+		okup := m != u && (inclusive || m+1 < u || i+1 < len(upper.mant))
+
+		// If it's okay to do either, then round to the nearest one.
+		// If it's okay to do only one, do it.
+		switch {
+		case okdown && okup:
+			d.round(i + 1)
+			return
+		case okdown:
+			d.roundDown(i + 1)
+			return
+		case okup:
+			d.roundUp(i + 1)
+			return
+		}
+	}
+}
+
 // %e: d.ddddde±dd
 func fmtE(buf []byte, fmt byte, prec int, d decimal) []byte {
 	// first digit
@@ -219,11 +292,7 @@ func fmtF(buf []byte, prec int, d decimal) []byte {
 	if prec > 0 {
 		buf = append(buf, '.')
 		for i := 0; i < prec; i++ {
-			ch := byte('0')
-			if j := d.exp + i; 0 <= j && j < len(d.mant) {
-				ch = d.mant[j]
-			}
-			buf = append(buf, ch)
+			buf = append(buf, d.at(d.exp+i))
 		}
 	}
 
@@ -255,7 +324,7 @@ func (x *Float) fmtB(buf []byte) []byte {
 		m = nat(nil).shr(m, uint(w-x.prec))
 	}
 
-	buf = append(buf, m.decimalString()...)
+	buf = append(buf, m.utoa(10)...)
 	buf = append(buf, 'p')
 	e := int64(x.exp) - int64(x.prec)
 	if e >= 0 {
@@ -289,7 +358,7 @@ func (x *Float) fmtP(buf []byte) []byte {
 	m = m[i:]
 
 	buf = append(buf, "0x."...)
-	buf = append(buf, strings.TrimRight(m.hexString(), "0")...)
+	buf = append(buf, bytes.TrimRight(m.utoa(16), "0")...)
 	buf = append(buf, 'p')
 	if x.exp >= 0 {
 		buf = append(buf, '+')
@@ -314,10 +383,6 @@ func min(x, y int) int {
 // '+' and ' ' for sign control, '0' for space or zero padding,
 // and '-' for left or right justification. See the fmt package
 // for details.
-//
-// BUG(gri) A missing precision for the 'g' format, or a negative
-//          (via '*') precision is not yet supported. Instead the
-//          default precision (6) is used in that case (issue #10991).
 func (x *Float) Format(s fmt.State, format rune) {
 	prec, hasPrec := s.Precision()
 	if !hasPrec {
@@ -336,8 +401,7 @@ func (x *Float) Format(s fmt.State, format rune) {
 		fallthrough
 	case 'g', 'G':
 		if !hasPrec {
-			// TODO(gri) uncomment once (*Float).Text handles prec < 0
-			// prec = -1 // default precision for 'g', 'G'
+			prec = -1 // default precision for 'g', 'G'
 		}
 	default:
 		fmt.Fprintf(s, "%%!%c(*big.Float=%s)", format, x.String())
diff --git a/src/cmd/compile/internal/big/int.go b/src/cmd/compile/internal/big/int.go
index 5e31253..67ab704 100644
--- a/src/cmd/compile/internal/big/int.go
+++ b/src/cmd/compile/internal/big/int.go
@@ -273,7 +273,7 @@ func (z *Int) Mod(x, y *Int) *Int {
 // DivMod implements Euclidean division and modulus (unlike Go):
 //
 //	q = x div y  such that
-//	m = x - y*q  with 0 <= m < |q|
+//	m = x - y*q  with 0 <= m < |y|
 //
 // (See Raymond T. Boute, ``The Euclidean definition of the functions
 // div and mod''. ACM Transactions on Programming Languages and
@@ -500,15 +500,17 @@ func (z *Int) binaryGCD(a, b *Int) *Int {
 	// use one Euclidean iteration to ensure that u and v are approx. the same size
 	switch {
 	case len(a.abs) > len(b.abs):
-		u.Set(b)
+		// must set v before u since u may be alias for a or b (was issue #11284)
 		v.Rem(a, b)
+		u.Set(b)
 	case len(a.abs) < len(b.abs):
-		u.Set(a)
 		v.Rem(b, a)
-	default:
 		u.Set(a)
+	default:
 		v.Set(b)
+		u.Set(a)
 	}
+	// a, b must not be used anymore (may be aliases with u)
 
 	// v might be 0 now
 	if len(v.abs) == 0 {
@@ -549,8 +551,11 @@ func (z *Int) binaryGCD(a, b *Int) *Int {
 }
 
 // ProbablyPrime performs n Miller-Rabin tests to check whether x is prime.
-// If it returns true, x is prime with probability 1 - 1/4^n.
-// If it returns false, x is not prime. n must be > 0.
+// If x is prime, it returns true.
+// If x is not prime, it returns false with probability at least 1 - ¼ⁿ.
+//
+// It is not suitable for judging primes that an adversary may have crafted
+// to fool this test.
 func (x *Int) ProbablyPrime(n int) bool {
 	if n <= 0 {
 		panic("non-positive n for ProbablyPrime")
@@ -638,23 +643,23 @@ func Jacobi(x, y *Int) int {
 	}
 }
 
-// ModSqrt sets z to a square root of x mod p if such a square root exists, and
-// returns z. The modulus p must be an odd prime. If x is not a square mod p,
-// ModSqrt leaves z unchanged and returns nil. This function panics if p is
-// not an odd integer.
-func (z *Int) ModSqrt(x, p *Int) *Int {
-	switch Jacobi(x, p) {
-	case -1:
-		return nil // x is not a square mod p
-	case 0:
-		return z.SetInt64(0) // sqrt(0) mod p = 0
-	case 1:
-		break
-	}
-	if x.neg || x.Cmp(p) >= 0 { // ensure 0 <= x < p
-		x = new(Int).Mod(x, p)
-	}
+// modSqrt3Mod4 uses the identity
+//      (a^((p+1)/4))^2  mod p
+//   == u^(p+1)          mod p
+//   == u^2              mod p
+// to calculate the square root of any quadratic residue mod p quickly for 3
+// mod 4 primes.
+func (z *Int) modSqrt3Mod4Prime(x, p *Int) *Int {
+	z.Set(p)         // z = p
+	z.Add(z, intOne) // z = p + 1
+	z.Rsh(z, 2)      // z = (p + 1) / 4
+	z.Exp(x, z, p)   // z = x^z mod p
+	return z
+}
 
+// modSqrtTonelliShanks uses the Tonelli-Shanks algorithm to find the square
+// root of a quadratic residue modulo any prime.
+func (z *Int) modSqrtTonelliShanks(x, p *Int) *Int {
 	// Break p-1 into s*2^e such that s is odd.
 	var s Int
 	s.Sub(p, intOne)
@@ -701,6 +706,31 @@ func (z *Int) ModSqrt(x, p *Int) *Int {
 	}
 }
 
+// ModSqrt sets z to a square root of x mod p if such a square root exists, and
+// returns z. The modulus p must be an odd prime. If x is not a square mod p,
+// ModSqrt leaves z unchanged and returns nil. This function panics if p is
+// not an odd integer.
+func (z *Int) ModSqrt(x, p *Int) *Int {
+	switch Jacobi(x, p) {
+	case -1:
+		return nil // x is not a square mod p
+	case 0:
+		return z.SetInt64(0) // sqrt(0) mod p = 0
+	case 1:
+		break
+	}
+	if x.neg || x.Cmp(p) >= 0 { // ensure 0 <= x < p
+		x = new(Int).Mod(x, p)
+	}
+
+	// Check whether p is 3 mod 4, and if so, use the faster algorithm.
+	if len(p.abs) > 0 && p.abs[0]%4 == 3 {
+		return z.modSqrt3Mod4Prime(x, p)
+	}
+	// Otherwise, use Tonelli-Shanks.
+	return z.modSqrtTonelliShanks(x, p)
+}
+
 // Lsh sets z = x << n and returns z.
 func (z *Int) Lsh(x *Int, n uint) *Int {
 	z.abs = z.abs.shl(x.abs, n)
@@ -902,65 +932,3 @@ func (z *Int) Not(x *Int) *Int {
 	z.neg = true // z cannot be zero if x is positive
 	return z
 }
-
-// Gob codec version. Permits backward-compatible changes to the encoding.
-const intGobVersion byte = 1
-
-// GobEncode implements the gob.GobEncoder interface.
-func (x *Int) GobEncode() ([]byte, error) {
-	if x == nil {
-		return nil, nil
-	}
-	buf := make([]byte, 1+len(x.abs)*_S) // extra byte for version and sign bit
-	i := x.abs.bytes(buf) - 1            // i >= 0
-	b := intGobVersion << 1              // make space for sign bit
-	if x.neg {
-		b |= 1
-	}
-	buf[i] = b
-	return buf[i:], nil
-}
-
-// GobDecode implements the gob.GobDecoder interface.
-func (z *Int) GobDecode(buf []byte) error {
-	if len(buf) == 0 {
-		// Other side sent a nil or default value.
-		*z = Int{}
-		return nil
-	}
-	b := buf[0]
-	if b>>1 != intGobVersion {
-		return fmt.Errorf("Int.GobDecode: encoding version %d not supported", b>>1)
-	}
-	z.neg = b&1 != 0
-	z.abs = z.abs.setBytes(buf[1:])
-	return nil
-}
-
-// MarshalJSON implements the json.Marshaler interface.
-func (z *Int) MarshalJSON() ([]byte, error) {
-	// TODO(gri): get rid of the []byte/string conversions
-	return []byte(z.String()), nil
-}
-
-// UnmarshalJSON implements the json.Unmarshaler interface.
-func (z *Int) UnmarshalJSON(text []byte) error {
-	// TODO(gri): get rid of the []byte/string conversions
-	if _, ok := z.SetString(string(text), 0); !ok {
-		return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Int", text)
-	}
-	return nil
-}
-
-// MarshalText implements the encoding.TextMarshaler interface.
-func (z *Int) MarshalText() (text []byte, err error) {
-	return []byte(z.String()), nil
-}
-
-// UnmarshalText implements the encoding.TextUnmarshaler interface.
-func (z *Int) UnmarshalText(text []byte) error {
-	if _, ok := z.SetString(string(text), 0); !ok {
-		return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Int", text)
-	}
-	return nil
-}
diff --git a/src/cmd/compile/internal/big/int_test.go b/src/cmd/compile/internal/big/int_test.go
index 16eed9a..45a3765 100644
--- a/src/cmd/compile/internal/big/int_test.go
+++ b/src/cmd/compile/internal/big/int_test.go
@@ -6,10 +6,7 @@ package big
 
 import (
 	"bytes"
-	"encoding/gob"
 	"encoding/hex"
-	"encoding/json"
-	"encoding/xml"
 	"fmt"
 	"math/rand"
 	"testing"
@@ -387,6 +384,11 @@ func TestSetBytes(t *testing.T) {
 }
 
 func checkBytes(b []byte) bool {
+	// trim leading zero bytes since Bytes() won't return them
+	// (was issue 12231)
+	for len(b) > 0 && b[0] == 0 {
+		b = b[1:]
+	}
 	b2 := new(Int).SetBytes(b).Bytes()
 	return bytes.Equal(b, b2)
 }
@@ -542,6 +544,9 @@ var expTests = []struct {
 	{"0x8000000000000000", "1000", "6719", "1603"},
 	{"0x8000000000000000", "1000000", "6719", "3199"},
 	{"0x8000000000000000", "-1000000", "6719", "1"},
+
+	{"0xffffffffffffffffffffffffffffffff", "0x12345678123456781234567812345678123456789", "0x01112222333344445555666677778889", "0x36168FA1DB3AAE6C8CE647E137F97A"},
+
 	{
 		"2938462938472983472983659726349017249287491026512746239764525612965293865296239471239874193284792387498274256129746192347",
 		"298472983472983471903246121093472394872319615612417471234712061",
@@ -550,11 +555,23 @@ var expTests = []struct {
 	},
 	// test case for issue 8822
 	{
+		"110012891183630896460173593721179634992505463752690475427779280061032468766887567357609056806046466243531968695727526232851404087554203740493176464281852700795553727635031156460546028675936629238941409408374795071949342675328316945655164667650254349023483145256274185156465881609558628390220513536530529470731360847807427297278748034576438481974995482975700269269275025056342970795272990042677697807685656954599452355868926270591788849987729893975050612063954555915037716775009312694775035 [...]
+		"0xB08FFB20760FFED58FADA86DFEF71AD72AA0FA763219618FE022C197E54708BB1191C66470250FCE8879487507CEE41381CA4D932F81C2B3F1AB20B539D50DCD",
+		"0xAC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E37 [...]
+		"214842521977763024996399388837777103219931130979872010505011829095813593576185795667465563725893853616836105247305090413288550665149633855225708948390358847130516401714741865487135466864767613064364341464751401562843891818086750165768458333404948482836810888865842197505544080605567694866280290287207273932931116788263564804554339092335205041120744013761330771504712375494741491902420104695390064495966115766125739557543490423291306311282346379247864665857034884605402284774408534933920862 [...]
+	},
+	{
 		"-0x1BCE04427D8032319A89E5C4136456671AC620883F2C4139E57F91307C485AD2D6204F4F87A58262652DB5DBBAC72B0613E51B835E7153BEC6068F5C8D696B74DBD18FEC316AEF73985CF0475663208EB46B4F17DD9DA55367B03323E5491A70997B90C059FB34809E6EE55BCFBD5F2F52233BFE62E6AA9E4E26A1D4C2439883D14F2633D55D8AA66A1ACD5595E778AC3A280517F1157989E70C1A437B849F1877B779CC3CDDEDE2DAA6594A6C66D181A00A5F777EE60596D8773998F6E988DEAE4CCA60E4DDCF9590543C89F74F603259FCAD71660D30294FBBE6490300F78A9D63FA660DC9417B8B9DDA28BEB3977B621B98 [...]
 		"0xB08FFB20760FFED58FADA86DFEF71AD72AA0FA763219618FE022C197E54708BB1191C66470250FCE8879487507CEE41381CA4D932F81C2B3F1AB20B539D50DCD",
 		"0xAC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E37 [...]
 		"214842521977763024996399388837777103219931130979872010505011829095813593576185795667465563725893853616836105247305090413288550665149633855225708948390358847130516401714741865487135466864767613064364341464751401562843891818086750165768458333404948482836810888865842197505544080605567694866280290287207273932931116788263564804554339092335205041120744013761330771504712375494741491902420104695390064495966115766125739557543490423291306311282346379247864665857034884605402284774408534933920862 [...]
 	},
+
+	// test cases for issue 13907
+	{"0xffffffff00000001", "0xffffffff00000001", "0xffffffff00000001", "0"},
+	{"0xffffffffffffffff00000001", "0xffffffffffffffff00000001", "0xffffffffffffffff00000001", "0"},
+	{"0xffffffffffffffffffffffff00000001", "0xffffffffffffffffffffffff00000001", "0xffffffffffffffffffffffff00000001", "0"},
+	{"0xffffffffffffffffffffffffffffffff00000001", "0xffffffffffffffffffffffffffffffff00000001", "0xffffffffffffffffffffffffffffffff00000001", "0"},
 }
 
 func TestExp(t *testing.T) {
@@ -582,7 +599,7 @@ func TestExp(t *testing.T) {
 			t.Errorf("#%d: %v is not normalized", i, *z1)
 		}
 		if z1.Cmp(out) != 0 {
-			t.Errorf("#%d: got %s want %s", i, z1, out)
+			t.Errorf("#%d: got %x want %x", i, z1, out)
 		}
 
 		if m == nil {
@@ -591,7 +608,7 @@ func TestExp(t *testing.T) {
 			m = &Int{abs: nat{}} // m != nil && len(m.abs) == 0
 			z2 := new(Int).Exp(x, y, m)
 			if z2.Cmp(z1) != 0 {
-				t.Errorf("#%d: got %s want %s", i, z2, z1)
+				t.Errorf("#%d: got %x want %x", i, z2, z1)
 			}
 		}
 	}
@@ -662,6 +679,21 @@ func testGcd(t *testing.T, d, x, y, a, b *Int) {
 	if D.Cmp(d) != 0 {
 		t.Errorf("binaryGcd(%s, %s): got d = %s, want %s", a, b, D, d)
 	}
+
+	// check results in presence of aliasing (issue #11284)
+	a2 := new(Int).Set(a)
+	b2 := new(Int).Set(b)
+	a2.binaryGCD(a2, b2) // result is same as 1st argument
+	if a2.Cmp(d) != 0 {
+		t.Errorf("binaryGcd(%s, %s): got d = %s, want %s", a, b, a2, d)
+	}
+
+	a2 = new(Int).Set(a)
+	b2 = new(Int).Set(b)
+	b2.binaryGCD(a2, b2) // result is same as 2nd argument
+	if b2.Cmp(d) != 0 {
+		t.Errorf("binaryGcd(%s, %s): got d = %s, want %s", a, b, b2, d)
+	}
 }
 
 func TestGcd(t *testing.T) {
@@ -678,7 +710,9 @@ func TestGcd(t *testing.T) {
 		testGcd(t, d, x, y, a, b)
 	}
 
-	quick.Check(checkGcd, nil)
+	if err := quick.Check(checkGcd, nil); err != nil {
+		t.Error(err)
+	}
 }
 
 var primes = []string{
@@ -1165,6 +1199,53 @@ func BenchmarkBitsetNegOrig(b *testing.B) {
 	}
 }
 
+// tri generates the trinomial 2**(n*2) - 2**n - 1, which is always 3 mod 4 and
+// 7 mod 8, so that 2 is always a quadratic residue.
+func tri(n uint) *Int {
+	x := NewInt(1)
+	x.Lsh(x, n)
+	x2 := new(Int).Lsh(x, n)
+	x2.Sub(x2, x)
+	x2.Sub(x2, intOne)
+	return x2
+}
+
+func BenchmarkModSqrt225_Tonelli(b *testing.B) {
+	p := tri(225)
+	x := NewInt(2)
+	for i := 0; i < b.N; i++ {
+		x.SetUint64(2)
+		x.modSqrtTonelliShanks(x, p)
+	}
+}
+
+func BenchmarkModSqrt224_3Mod4(b *testing.B) {
+	p := tri(225)
+	x := new(Int).SetUint64(2)
+	for i := 0; i < b.N; i++ {
+		x.SetUint64(2)
+		x.modSqrt3Mod4Prime(x, p)
+	}
+}
+
+func BenchmarkModSqrt5430_Tonelli(b *testing.B) {
+	p := tri(5430)
+	x := new(Int).SetUint64(2)
+	for i := 0; i < b.N; i++ {
+		x.SetUint64(2)
+		x.modSqrtTonelliShanks(x, p)
+	}
+}
+
+func BenchmarkModSqrt5430_3Mod4(b *testing.B) {
+	p := tri(5430)
+	x := new(Int).SetUint64(2)
+	for i := 0; i < b.N; i++ {
+		x.SetUint64(2)
+		x.modSqrt3Mod4Prime(x, p)
+	}
+}
+
 func TestBitwise(t *testing.T) {
 	x := new(Int)
 	y := new(Int)
@@ -1303,6 +1384,14 @@ func TestModSqrt(t *testing.T) {
 				t.Errorf("#%d: failed (sqrt(e) = %s)", i, &sqrt)
 			}
 		}
+
+		if testing.Short() && i > 2 {
+			break
+		}
+	}
+
+	if testing.Short() {
+		return
 	}
 
 	// exhaustive test for small values
@@ -1386,138 +1475,6 @@ func TestJacobiPanic(t *testing.T) {
 	panic(failureMsg)
 }
 
-var encodingTests = []string{
-	"-539345864568634858364538753846587364875430589374589",
-	"-678645873",
-	"-100",
-	"-2",
-	"-1",
-	"0",
-	"1",
-	"2",
-	"10",
-	"42",
-	"1234567890",
-	"298472983472983471903246121093472394872319615612417471234712061",
-}
-
-func TestIntGobEncoding(t *testing.T) {
-	var medium bytes.Buffer
-	enc := gob.NewEncoder(&medium)
-	dec := gob.NewDecoder(&medium)
-	for _, test := range encodingTests {
-		medium.Reset() // empty buffer for each test case (in case of failures)
-		var tx Int
-		tx.SetString(test, 10)
-		if err := enc.Encode(&tx); err != nil {
-			t.Errorf("encoding of %s failed: %s", &tx, err)
-		}
-		var rx Int
-		if err := dec.Decode(&rx); err != nil {
-			t.Errorf("decoding of %s failed: %s", &tx, err)
-		}
-		if rx.Cmp(&tx) != 0 {
-			t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx)
-		}
-	}
-}
-
-// Sending a nil Int pointer (inside a slice) on a round trip through gob should yield a zero.
-// TODO: top-level nils.
-func TestGobEncodingNilIntInSlice(t *testing.T) {
-	buf := new(bytes.Buffer)
-	enc := gob.NewEncoder(buf)
-	dec := gob.NewDecoder(buf)
-
-	var in = make([]*Int, 1)
-	err := enc.Encode(&in)
-	if err != nil {
-		t.Errorf("gob encode failed: %q", err)
-	}
-	var out []*Int
-	err = dec.Decode(&out)
-	if err != nil {
-		t.Fatalf("gob decode failed: %q", err)
-	}
-	if len(out) != 1 {
-		t.Fatalf("wrong len; want 1 got %d", len(out))
-	}
-	var zero Int
-	if out[0].Cmp(&zero) != 0 {
-		t.Errorf("transmission of (*Int)(nill) failed: got %s want 0", out)
-	}
-}
-
-func TestIntJSONEncoding(t *testing.T) {
-	for _, test := range encodingTests {
-		var tx Int
-		tx.SetString(test, 10)
-		b, err := json.Marshal(&tx)
-		if err != nil {
-			t.Errorf("marshaling of %s failed: %s", &tx, err)
-		}
-		var rx Int
-		if err := json.Unmarshal(b, &rx); err != nil {
-			t.Errorf("unmarshaling of %s failed: %s", &tx, err)
-		}
-		if rx.Cmp(&tx) != 0 {
-			t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx)
-		}
-	}
-}
-
-var intVals = []string{
-	"-141592653589793238462643383279502884197169399375105820974944592307816406286",
-	"-1415926535897932384626433832795028841971",
-	"-141592653589793",
-	"-1",
-	"0",
-	"1",
-	"141592653589793",
-	"1415926535897932384626433832795028841971",
-	"141592653589793238462643383279502884197169399375105820974944592307816406286",
-}
-
-func TestIntJSONEncodingTextMarshaller(t *testing.T) {
-	for _, num := range intVals {
-		var tx Int
-		tx.SetString(num, 0)
-		b, err := json.Marshal(&tx)
-		if err != nil {
-			t.Errorf("marshaling of %s failed: %s", &tx, err)
-			continue
-		}
-		var rx Int
-		if err := json.Unmarshal(b, &rx); err != nil {
-			t.Errorf("unmarshaling of %s failed: %s", &tx, err)
-			continue
-		}
-		if rx.Cmp(&tx) != 0 {
-			t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx)
-		}
-	}
-}
-
-func TestIntXMLEncodingTextMarshaller(t *testing.T) {
-	for _, num := range intVals {
-		var tx Int
-		tx.SetString(num, 0)
-		b, err := xml.Marshal(&tx)
-		if err != nil {
-			t.Errorf("marshaling of %s failed: %s", &tx, err)
-			continue
-		}
-		var rx Int
-		if err := xml.Unmarshal(b, &rx); err != nil {
-			t.Errorf("unmarshaling of %s failed: %s", &tx, err)
-			continue
-		}
-		if rx.Cmp(&tx) != 0 {
-			t.Errorf("XML encoding of %s failed: got %s want %s", &tx, &rx, &tx)
-		}
-	}
-}
-
 func TestIssue2607(t *testing.T) {
 	// This code sequence used to hang.
 	n := NewInt(10)
diff --git a/src/cmd/compile/internal/big/intconv.go b/src/cmd/compile/internal/big/intconv.go
index 9c68a22..56a75f8 100644
--- a/src/cmd/compile/internal/big/intconv.go
+++ b/src/cmd/compile/internal/big/intconv.go
@@ -12,30 +12,34 @@ import (
 	"io"
 )
 
-func (x *Int) String() string {
-	switch {
-	case x == nil:
+// TODO(gri) Should rename itoa to utoa (there's no sign). That
+// would permit the introduction of itoa which is like utoa but
+// reserves a byte for a possible sign that's passed in. That
+// would permit Int.Text to be implemented w/o the need for
+// string copy if the number is negative.
+
+// Text returns the string representation of x in the given base.
+// Base must be between 2 and 36, inclusive. The result uses the
+// lower-case letters 'a' to 'z' for digit values >= 10. No base
+// prefix (such as "0x") is added to the string.
+func (x *Int) Text(base int) string {
+	if x == nil {
 		return "<nil>"
-	case x.neg:
-		return "-" + x.abs.decimalString()
 	}
-	return x.abs.decimalString()
+	return string(x.abs.itoa(x.neg, base))
 }
 
-func charset(ch rune) string {
-	switch ch {
-	case 'b':
-		return lowercaseDigits[0:2]
-	case 'o':
-		return lowercaseDigits[0:8]
-	case 'd', 's', 'v':
-		return lowercaseDigits[0:10]
-	case 'x':
-		return lowercaseDigits[0:16]
-	case 'X':
-		return uppercaseDigits[0:16]
+// Append appends the string representation of x, as generated by
+// x.Text(base), to buf and returns the extended buffer.
+func (x *Int) Append(buf []byte, base int) []byte {
+	if x == nil {
+		return append(buf, "<nil>"...)
 	}
-	return "" // unknown format
+	return append(buf, x.abs.itoa(x.neg, base)...)
+}
+
+func (x *Int) String() string {
+	return x.Text(10)
 }
 
 // write count copies of text to s
@@ -60,15 +64,24 @@ func writeMultiple(s fmt.State, text string, count int) {
 // right justification.
 //
 func (x *Int) Format(s fmt.State, ch rune) {
-	cs := charset(ch)
-
-	// special cases
-	switch {
-	case cs == "":
+	// determine base
+	var base int
+	switch ch {
+	case 'b':
+		base = 2
+	case 'o':
+		base = 8
+	case 'd', 's', 'v':
+		base = 10
+	case 'x', 'X':
+		base = 16
+	default:
 		// unknown format
 		fmt.Fprintf(s, "%%!%c(big.Int=%s)", ch, x.String())
 		return
-	case x == nil:
+	}
+
+	if x == nil {
 		fmt.Fprint(s, "<nil>")
 		return
 	}
@@ -97,35 +110,42 @@ func (x *Int) Format(s fmt.State, ch rune) {
 		}
 	}
 
-	// determine digits with base set by len(cs) and digit characters from cs
-	digits := x.abs.string(cs)
+	digits := x.abs.utoa(base)
+	if ch == 'X' {
+		// faster than bytes.ToUpper
+		for i, d := range digits {
+			if 'a' <= d && d <= 'z' {
+				digits[i] = 'A' + (d - 'a')
+			}
+		}
+	}
 
 	// number of characters for the three classes of number padding
-	var left int   // space characters to left of digits for right justification ("%8d")
-	var zeroes int // zero characters (actually cs[0]) as left-most digits ("%.8d")
-	var right int  // space characters to right of digits for left justification ("%-8d")
+	var left int  // space characters to left of digits for right justification ("%8d")
+	var zeros int // zero characters (actually cs[0]) as left-most digits ("%.8d")
+	var right int // space characters to right of digits for left justification ("%-8d")
 
 	// determine number padding from precision: the least number of digits to output
 	precision, precisionSet := s.Precision()
 	if precisionSet {
 		switch {
 		case len(digits) < precision:
-			zeroes = precision - len(digits) // count of zero padding
-		case digits == "0" && precision == 0:
+			zeros = precision - len(digits) // count of zero padding
+		case len(digits) == 1 && digits[0] == '0' && precision == 0:
 			return // print nothing if zero value (x == 0) and zero precision ("." or ".0")
 		}
 	}
 
 	// determine field pad from width: the least number of characters to output
-	length := len(sign) + len(prefix) + zeroes + len(digits)
+	length := len(sign) + len(prefix) + zeros + len(digits)
 	if width, widthSet := s.Width(); widthSet && length < width { // pad as specified
 		switch d := width - length; {
 		case s.Flag('-'):
 			// pad on the right with spaces; supersedes '0' when both specified
 			right = d
 		case s.Flag('0') && !precisionSet:
-			// pad with zeroes unless precision also specified
-			zeroes = d
+			// pad with zeros unless precision also specified
+			zeros = d
 		default:
 			// pad on the left with spaces
 			left = d
@@ -136,8 +156,8 @@ func (x *Int) Format(s fmt.State, ch rune) {
 	writeMultiple(s, " ", left)
 	writeMultiple(s, sign, 1)
 	writeMultiple(s, prefix, 1)
-	writeMultiple(s, "0", zeroes)
-	writeMultiple(s, digits, 1)
+	writeMultiple(s, "0", zeros)
+	s.Write(digits)
 	writeMultiple(s, " ", right)
 }
 
diff --git a/src/cmd/compile/internal/big/intconv_test.go b/src/cmd/compile/internal/big/intconv_test.go
index 2deb84b..5142081 100644
--- a/src/cmd/compile/internal/big/intconv_test.go
+++ b/src/cmd/compile/internal/big/intconv_test.go
@@ -17,19 +17,19 @@ var stringTests = []struct {
 	val  int64
 	ok   bool
 }{
-	{in: "", ok: false},
-	{in: "a", ok: false},
-	{in: "z", ok: false},
-	{in: "+", ok: false},
-	{in: "-", ok: false},
-	{in: "0b", ok: false},
-	{in: "0x", ok: false},
-	{in: "2", base: 2, ok: false},
-	{in: "0b2", base: 0, ok: false},
-	{in: "08", ok: false},
-	{in: "8", base: 8, ok: false},
-	{in: "0xg", base: 0, ok: false},
-	{in: "g", base: 16, ok: false},
+	{in: ""},
+	{in: "a"},
+	{in: "z"},
+	{in: "+"},
+	{in: "-"},
+	{in: "0b"},
+	{in: "0x"},
+	{in: "2", base: 2},
+	{in: "0b2", base: 0},
+	{in: "08"},
+	{in: "8", base: 8},
+	{in: "0xg", base: 0},
+	{in: "g", base: 16},
 	{"0", "0", 0, 0, true},
 	{"0", "0", 10, 0, true},
 	{"0", "0", 16, 0, true},
@@ -41,7 +41,7 @@ var stringTests = []struct {
 	{"-10", "-10", 16, -16, true},
 	{"+10", "10", 16, 16, true},
 	{"0x10", "16", 0, 16, true},
-	{in: "0x10", base: 16, ok: false},
+	{in: "0x10", base: 16},
 	{"-0x10", "-16", 0, -16, true},
 	{"+0x10", "16", 0, 16, true},
 	{"00", "0", 0, 0, true},
@@ -58,6 +58,57 @@ var stringTests = []struct {
 	{"1001010111", "1001010111", 2, 0x257, true},
 }
 
+func TestIntText(t *testing.T) {
+	z := new(Int)
+	for _, test := range stringTests {
+		if !test.ok {
+			continue
+		}
+
+		_, ok := z.SetString(test.in, test.base)
+		if !ok {
+			t.Errorf("%v: failed to parse", test)
+			continue
+		}
+
+		base := test.base
+		if base == 0 {
+			base = 10
+		}
+
+		if got := z.Text(base); got != test.out {
+			t.Errorf("%v: got %s; want %s", test, got, test.out)
+		}
+	}
+}
+
+func TestAppendText(t *testing.T) {
+	z := new(Int)
+	var buf []byte
+	for _, test := range stringTests {
+		if !test.ok {
+			continue
+		}
+
+		_, ok := z.SetString(test.in, test.base)
+		if !ok {
+			t.Errorf("%v: failed to parse", test)
+			continue
+		}
+
+		base := test.base
+		if base == 0 {
+			base = 10
+		}
+
+		i := len(buf)
+		buf = z.Append(buf, base)
+		if got := string(buf[i:]); got != test.out {
+			t.Errorf("%v: got %s; want %s", test, got, test.out)
+		}
+	}
+}
+
 func format(base int) string {
 	switch base {
 	case 2:
@@ -79,15 +130,13 @@ func TestGetString(t *testing.T) {
 		z.SetInt64(test.val)
 
 		if test.base == 10 {
-			s := z.String()
-			if s != test.out {
-				t.Errorf("#%da got %s; want %s", i, s, test.out)
+			if got := z.String(); got != test.out {
+				t.Errorf("#%da got %s; want %s", i, got, test.out)
 			}
 		}
 
-		s := fmt.Sprintf(format(test.base), z)
-		if s != test.out {
-			t.Errorf("#%db got %s; want %s", i, s, test.out)
+		if got := fmt.Sprintf(format(test.base), z); got != test.out {
+			t.Errorf("#%db got %s; want %s", i, got, test.out)
 		}
 	}
 }
diff --git a/src/cmd/compile/internal/big/nat.go b/src/cmd/compile/internal/big/nat.go
index 6545bc1..79cf6e0 100644
--- a/src/cmd/compile/internal/big/nat.go
+++ b/src/cmd/compile/internal/big/nat.go
@@ -2,31 +2,11 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Package big implements multi-precision arithmetic (big numbers).
-// The following numeric types are supported:
-//
-//   Int    signed integers
-//   Rat    rational numbers
-//   Float  floating-point numbers
-//
-// Methods are typically of the form:
-//
-//   func (z *T) Unary(x *T) *T        // z = op x
-//   func (z *T) Binary(x, y *T) *T    // z = x op y
-//   func (x *T) M() T1                // v = x.M()
-//
-// with T one of Int, Rat, or Float. For unary and binary operations, the
-// result is the receiver (usually named z in that case); if it is one of
-// the operands x or y it may be overwritten (and its memory reused).
-// To enable chaining of operations, the result is also returned. Methods
-// returning a result other than *Int, *Rat, or *Float take an operand as
-// the receiver (usually named x in that case).
-//
-package big
+// This file implements unsigned multi-precision integers (natural
+// numbers). They are the building blocks for the implementation
+// of signed integers, rationals, and floating-point numbers.
 
-// This file contains operations on unsigned multi-precision integers.
-// These are the building blocks for the operations on signed integers
-// and rationals.
+package big
 
 import "math/rand"
 
@@ -216,29 +196,42 @@ func basicMul(z, x, y nat) {
 	}
 }
 
-// montgomery computes x*y*2^(-n*_W) mod m,
-// assuming k = -1/m mod 2^_W.
+// montgomery computes z mod m = x*y*2**(-n*_W) mod m,
+// assuming k = -1/m mod 2**_W.
 // z is used for storing the result which is returned;
 // z must not alias x, y or m.
+// See Gueron, "Efficient Software Implementations of Modular Exponentiation".
+// https://eprint.iacr.org/2011/239.pdf
+// In the terminology of that paper, this is an "Almost Montgomery Multiplication":
+// x and y are required to satisfy 0 <= z < 2**(n*_W) and then the result
+// z is guaranteed to satisfy 0 <= z < 2**(n*_W), but it may not be < m.
 func (z nat) montgomery(x, y, m nat, k Word, n int) nat {
-	var c1, c2 Word
+	// This code assumes x, y, m are all the same length, n.
+	// (required by addMulVVW and the for loop).
+	// It also assumes that x, y are already reduced mod m,
+	// or else the result will not be properly reduced.
+	if len(x) != n || len(y) != n || len(m) != n {
+		panic("math/big: mismatched montgomery number lengths")
+	}
 	z = z.make(n)
 	z.clear()
+	var c Word
 	for i := 0; i < n; i++ {
 		d := y[i]
-		c1 += addMulVVW(z, x, d)
+		c2 := addMulVVW(z, x, d)
 		t := z[0] * k
-		c2 = addMulVVW(z, m, t)
-
+		c3 := addMulVVW(z, m, t)
 		copy(z, z[1:])
-		z[n-1] = c1 + c2
-		if z[n-1] < c1 {
-			c1 = 1
+		cx := c + c2
+		cy := cx + c3
+		z[n-1] = cy
+		if cx < c2 || cy < c3 {
+			c = 1
 		} else {
-			c1 = 0
+			c = 0
 		}
 	}
-	if c1 != 0 {
+	if c != 0 {
 		subVV(z, z, m)
 	}
 	return z
@@ -1063,26 +1056,22 @@ func (z nat) expNNWindowed(x, y, m nat) nat {
 // expNNMontgomery calculates x**y mod m using a fixed, 4-bit window.
 // Uses Montgomery representation.
 func (z nat) expNNMontgomery(x, y, m nat) nat {
-	var zz, one, rr, RR nat
-
 	numWords := len(m)
 
 	// We want the lengths of x and m to be equal.
+	// It is OK if x >= m as long as len(x) == len(m).
 	if len(x) > numWords {
-		_, rr = rr.div(rr, x, m)
-	} else if len(x) < numWords {
-		rr = rr.make(numWords)
-		rr.clear()
-		for i := range x {
-			rr[i] = x[i]
-		}
-	} else {
-		rr = x
+		_, x = nat(nil).div(nil, x, m)
+		// Note: now len(x) <= numWords, not guaranteed ==.
+	}
+	if len(x) < numWords {
+		rr := make(nat, numWords)
+		copy(rr, x)
+		x = rr
 	}
-	x = rr
 
 	// Ideally the precomputations would be performed outside, and reused
-	// k0 = -mˆ-1 mod 2ˆ_W. Algorithm from: Dumas, J.G. "On Newton–Raphson
+	// k0 = -m**-1 mod 2**_W. Algorithm from: Dumas, J.G. "On Newton–Raphson
 	// Iteration for Multiplicative Inverses Modulo Prime Powers".
 	k0 := 2 - m[0]
 	t := m[0] - 1
@@ -1092,9 +1081,9 @@ func (z nat) expNNMontgomery(x, y, m nat) nat {
 	}
 	k0 = -k0
 
-	// RR = 2ˆ(2*_W*len(m)) mod m
-	RR = RR.setWord(1)
-	zz = zz.shl(RR, uint(2*numWords*_W))
+	// RR = 2**(2*_W*len(m)) mod m
+	RR := nat(nil).setWord(1)
+	zz := nat(nil).shl(RR, uint(2*numWords*_W))
 	_, RR = RR.div(RR, zz, m)
 	if len(RR) < numWords {
 		zz = zz.make(numWords)
@@ -1102,8 +1091,7 @@ func (z nat) expNNMontgomery(x, y, m nat) nat {
 		RR = zz
 	}
 	// one = 1, with equal length to that of m
-	one = one.make(numWords)
-	one.clear()
+	one := make(nat, numWords)
 	one[0] = 1
 
 	const n = 4
@@ -1138,12 +1126,32 @@ func (z nat) expNNMontgomery(x, y, m nat) nat {
 	}
 	// convert to regular number
 	zz = zz.montgomery(z, one, m, k0, numWords)
+
+	// One last reduction, just in case.
+	// See golang.org/issue/13907.
+	if zz.cmp(m) >= 0 {
+		// Common case is m has high bit set; in that case,
+		// since zz is the same length as m, there can be just
+		// one multiple of m to remove. Just subtract.
+		// We think that the subtract should be sufficient in general,
+		// so do that unconditionally, but double-check,
+		// in case our beliefs are wrong.
+		// The div is not expected to be reached.
+		zz = zz.sub(zz, m)
+		if zz.cmp(m) >= 0 {
+			_, zz = nat(nil).div(nil, zz, m)
+		}
+	}
+
 	return zz.norm()
 }
 
-// probablyPrime performs reps Miller-Rabin tests to check whether n is prime.
-// If it returns true, n is prime with probability 1 - 1/4^reps.
-// If it returns false, n is not prime.
+// probablyPrime performs n Miller-Rabin tests to check whether x is prime.
+// If x is prime, it returns true.
+// If x is not prime, it returns false with probability at least 1 - ¼ⁿ.
+//
+// It is not suitable for judging primes that an adversary may have crafted
+// to fool this test.
 func (n nat) probablyPrime(reps int) bool {
 	if len(n) == 0 {
 		return false
diff --git a/src/cmd/compile/internal/big/nat_test.go b/src/cmd/compile/internal/big/nat_test.go
index 7ac3cb8..563ccb3 100644
--- a/src/cmd/compile/internal/big/nat_test.go
+++ b/src/cmd/compile/internal/big/nat_test.go
@@ -158,7 +158,7 @@ var mulRangesN = []struct {
 
 func TestMulRangeN(t *testing.T) {
 	for i, r := range mulRangesN {
-		prod := nat(nil).mulRange(r.a, r.b).decimalString()
+		prod := string(nat(nil).mulRange(r.a, r.b).utoa(10))
 		if prod != r.prod {
 			t.Errorf("#%d: got %s; want %s", i, prod, r.prod)
 		}
@@ -326,7 +326,7 @@ func TestTrailingZeroBits(t *testing.T) {
 	for i := uint(0); i <= 3*_W; i++ {
 		n := y.trailingZeroBits()
 		if n != i {
-			t.Errorf("got 0x%s.trailingZeroBits() = %d; want %d", y.hexString(), n, i)
+			t.Errorf("got 0x%s.trailingZeroBits() = %d; want %d", y.utoa(16), n, i)
 		}
 		y = y.shl(y, 1)
 	}
@@ -341,25 +341,57 @@ var montgomeryTests = []struct {
 		"0xffffffffffffffffffffffffffffffffffffffffffffffffe",
 		"0xffffffffffffffffffffffffffffffffffffffffffffffffe",
 		"0xfffffffffffffffffffffffffffffffffffffffffffffffff",
-		0x0000000000000000,
-		"0xffffffffffffffffffffffffffffffffffffffffff",
-		"0xffffffffffffffffffffffffffffffffff",
+		1,
+		"0x1000000000000000000000000000000000000000000",
+		"0x10000000000000000000000000000000000",
 	},
 	{
-		"0x0000000080000000",
-		"0x00000000ffffffff",
+		"0x000000000ffffff5",
+		"0x000000000ffffff0",
 		"0x0000000010000001",
 		0xff0000000fffffff,
-		"0x0000000088000000",
-		"0x0000000007800001",
+		"0x000000000bfffff4",
+		"0x0000000003400001",
+	},
+	{
+		"0x0000000080000000",
+		"0x00000000ffffffff",
+		"0x1000000000000001",
+		0xfffffffffffffff,
+		"0x0800000008000001",
+		"0x0800000008000001",
+	},
+	{
+		"0x0000000080000000",
+		"0x0000000080000000",
+		"0xffffffff00000001",
+		0xfffffffeffffffff,
+		"0xbfffffff40000001",
+		"0xbfffffff40000001",
+	},
+	{
+		"0x0000000080000000",
+		"0x0000000080000000",
+		"0x00ffffff00000001",
+		0xfffffeffffffff,
+		"0xbfffff40000001",
+		"0xbfffff40000001",
+	},
+	{
+		"0x0000000080000000",
+		"0x0000000080000000",
+		"0x0000ffff00000001",
+		0xfffeffffffff,
+		"0xbfff40000001",
+		"0xbfff40000001",
 	},
 	{
-		"0xffffffffffffffffffffffffffffffff00000000000022222223333333333444444444",
-		"0xffffffffffffffffffffffffffffffff999999999999999aaabbbbbbbbcccccccccccc",
+		"0x3321ffffffffffffffffffffffffffff00000000000022222623333333332bbbb888c0",
+		"0x3321ffffffffffffffffffffffffffff00000000000022222623333333332bbbb888c0",
 		"0x33377fffffffffffffffffffffffffffffffffffffffffffff0000000000022222eee1",
 		0xdecc8f1249812adf,
-		"0x22bb05b6d95eaaeca2bb7c05e51f807bce9064b5fbad177161695e4558f9474e91cd79",
-		"0x14beb58d230f85b6d95eaaeca2bb7c05e51f807bce9064b5fb45669afa695f228e48cd",
+		"0x04eb0e11d72329dc0915f86784820fc403275bf2f6620a20e0dd344c5cd0875e50deb5",
+		"0x0d7144739a7d8e11d72329dc0915f86784820fc403275bf2f61ed96f35dd34dbb3d6a0",
 	},
 	{
 		"0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff00000000000022222223333333333444444444",
@@ -372,10 +404,27 @@ var montgomeryTests = []struct {
 }
 
 func TestMontgomery(t *testing.T) {
+	one := NewInt(1)
+	_B := new(Int).Lsh(one, _W)
 	for i, test := range montgomeryTests {
 		x := natFromString(test.x)
 		y := natFromString(test.y)
 		m := natFromString(test.m)
+		for len(x) < len(m) {
+			x = append(x, 0)
+		}
+		for len(y) < len(m) {
+			y = append(y, 0)
+		}
+
+		if x.cmp(m) > 0 {
+			_, r := nat(nil).div(nil, x, m)
+			t.Errorf("#%d: x > m (0x%s > 0x%s; use 0x%s)", i, x.utoa(16), m.utoa(16), r.utoa(16))
+		}
+		if y.cmp(m) > 0 {
+			_, r := nat(nil).div(nil, x, m)
+			t.Errorf("#%d: y > m (0x%s > 0x%s; use 0x%s)", i, y.utoa(16), m.utoa(16), r.utoa(16))
+		}
 
 		var out nat
 		if _W == 32 {
@@ -384,11 +433,31 @@ func TestMontgomery(t *testing.T) {
 			out = natFromString(test.out64)
 		}
 
-		k0 := Word(test.k0 & _M) // mask k0 to ensure that it fits for 32-bit systems.
+		// t.Logf("#%d: len=%d\n", i, len(m))
+
+		// check output in table
+		xi := &Int{abs: x}
+		yi := &Int{abs: y}
+		mi := &Int{abs: m}
+		p := new(Int).Mod(new(Int).Mul(xi, new(Int).Mul(yi, new(Int).ModInverse(new(Int).Lsh(one, uint(len(m))*_W), mi))), mi)
+		if out.cmp(p.abs.norm()) != 0 {
+			t.Errorf("#%d: out in table=0x%s, computed=0x%s", i, out.utoa(16), p.abs.norm().utoa(16))
+		}
+
+		// check k0 in table
+		k := new(Int).Mod(&Int{abs: m}, _B)
+		k = new(Int).Sub(_B, k)
+		k = new(Int).Mod(k, _B)
+		k0 := Word(new(Int).ModInverse(k, _B).Uint64())
+		if k0 != Word(test.k0) {
+			t.Errorf("#%d: k0 in table=%#x, computed=%#x\n", i, test.k0, k0)
+		}
+
+		// check montgomery with correct k0 produces correct output
 		z := nat(nil).montgomery(x, y, m, k0, len(m))
 		z = z.norm()
 		if z.cmp(out) != 0 {
-			t.Errorf("#%d got %s want %s", i, z.decimalString(), out.decimalString())
+			t.Errorf("#%d: got 0x%s want 0x%s", i, z.utoa(16), out.utoa(16))
 		}
 	}
 }
@@ -414,6 +483,12 @@ var expNNTests = []struct {
 		"29834729834729834729347290846729561262544958723956495615629569234729836259263598127342374289365912465901365498236492183464",
 		"23537740700184054162508175125554701713153216681790245129157191391322321508055833908509185839069455749219131480588829346291",
 	},
+	{
+		"11521922904531591643048817447554701904414021819823889996244743037378330903763518501116638828335352811871131385129455853417360623007349090150042001944696604737499160174391019030572483602867266711107136838523916077674888297896995042968746762200926853379",
+		"426343618817810911523",
+		"444747819283133684179",
+		"42",
+	},
 }
 
 func TestExpNN(t *testing.T) {
@@ -429,7 +504,7 @@ func TestExpNN(t *testing.T) {
 
 		z := nat(nil).expNN(x, y, m)
 		if z.cmp(out) != 0 {
-			t.Errorf("#%d got %s want %s", i, z.decimalString(), out.decimalString())
+			t.Errorf("#%d got %s want %s", i, z.utoa(10), out.utoa(10))
 		}
 	}
 }
@@ -486,7 +561,7 @@ var fiboNums = []string{
 func TestFibo(t *testing.T) {
 	for i, want := range fiboNums {
 		n := i * 10
-		got := fibo(n).decimalString()
+		got := string(fibo(n).utoa(10))
 		if got != want {
 			t.Errorf("fibo(%d) failed: got %s want %s", n, got, want)
 		}
diff --git a/src/cmd/compile/internal/big/natconv.go b/src/cmd/compile/internal/big/natconv.go
index 022dcfe..d2ce667 100644
--- a/src/cmd/compile/internal/big/natconv.go
+++ b/src/cmd/compile/internal/big/natconv.go
@@ -14,6 +14,11 @@ import (
 	"sync"
 )
 
+const digits = "0123456789abcdefghijklmnopqrstuvwxyz"
+
+// Note: MaxBase = len(digits), but it must remain a rune constant
+//       for API compatibility.
+
 // MaxBase is the largest number base accepted for string conversions.
 const MaxBase = 'z' - 'a' + 10 + 1
 
@@ -229,56 +234,45 @@ func (z nat) scan(r io.ByteScanner, base int, fracOk bool) (res nat, b, count in
 	return
 }
 
-// Character sets for string conversion.
-const (
-	lowercaseDigits = "0123456789abcdefghijklmnopqrstuvwxyz"
-	uppercaseDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-)
-
-// decimalString returns a decimal representation of x.
-// It calls x.string with the charset "0123456789".
-func (x nat) decimalString() string {
-	return x.string(lowercaseDigits[:10])
+// utoa converts x to an ASCII representation in the given base;
+// base must be between 2 and MaxBase, inclusive.
+func (x nat) utoa(base int) []byte {
+	return x.itoa(false, base)
 }
 
-// hexString returns a hexadecimal representation of x.
-// It calls x.string with the charset "0123456789abcdef".
-func (x nat) hexString() string {
-	return x.string(lowercaseDigits[:16])
-}
+// itoa is like utoa but it prepends a '-' if neg && x != 0.
+func (x nat) itoa(neg bool, base int) []byte {
+	if base < 2 || base > MaxBase {
+		panic("invalid base")
+	}
 
-// string converts x to a string using digits from a charset; a digit with
-// value d is represented by charset[d]. The conversion base is determined
-// by len(charset), which must be >= 2 and <= 256.
-func (x nat) string(charset string) string {
-	b := Word(len(charset))
-
-	// special cases
-	switch {
-	case b < 2 || b > 256:
-		panic("invalid character set length")
-	case len(x) == 0:
-		return string(charset[0])
+	// x == 0
+	if len(x) == 0 {
+		return []byte("0")
 	}
+	// len(x) > 0
 
 	// allocate buffer for conversion
-	i := int(float64(x.bitLen())/math.Log2(float64(b))) + 1 // off by one at most
+	i := int(float64(x.bitLen())/math.Log2(float64(base))) + 1 // off by 1 at most
+	if neg {
+		i++
+	}
 	s := make([]byte, i)
 
 	// convert power of two and non power of two bases separately
-	if b == b&-b {
-		// shift is base-b digit size in bits
+	if b := Word(base); b == b&-b {
+		// shift is base b digit size in bits
 		shift := trailingZeroBits(b) // shift > 0 because b >= 2
-		mask := Word(1)<<shift - 1
-		w := x[0]
+		mask := Word(1<<shift - 1)
+		w := x[0]         // current word
 		nbits := uint(_W) // number of unprocessed bits in w
 
-		// convert less-significant words
+		// convert less-significant words (include leading zeros)
 		for k := 1; k < len(x); k++ {
 			// convert full digits
 			for nbits >= shift {
 				i--
-				s[i] = charset[w&mask]
+				s[i] = digits[w&mask]
 				w >>= shift
 				nbits -= shift
 			}
@@ -289,10 +283,10 @@ func (x nat) string(charset string) string {
 				w = x[k]
 				nbits = _W
 			} else {
-				// partial digit in current (k-1) and next (k) word
+				// partial digit in current word w (== x[k-1]) and next word x[k]
 				w |= x[k] << nbits
 				i--
-				s[i] = charset[w&mask]
+				s[i] = digits[w&mask]
 
 				// advance
 				w = x[k] >> (shift - nbits)
@@ -300,12 +294,11 @@ func (x nat) string(charset string) string {
 			}
 		}
 
-		// convert digits of most-significant word (omit leading zeros)
-		for nbits >= 0 && w != 0 {
+		// convert digits of most-significant word w (omit leading zeros)
+		for w != 0 {
 			i--
-			s[i] = charset[w&mask]
+			s[i] = digits[w&mask]
 			w >>= shift
-			nbits -= shift
 		}
 
 	} else {
@@ -319,18 +312,23 @@ func (x nat) string(charset string) string {
 		q := nat(nil).set(x)
 
 		// convert q to string s in base b
-		q.convertWords(s, charset, b, ndigits, bb, table)
+		q.convertWords(s, b, ndigits, bb, table)
 
 		// strip leading zeros
 		// (x != 0; thus s must contain at least one non-zero digit
 		// and the loop will terminate)
 		i = 0
-		for zero := charset[0]; s[i] == zero; {
+		for s[i] == '0' {
 			i++
 		}
 	}
 
-	return string(s[i:])
+	if neg {
+		i--
+		s[i] = '-'
+	}
+
+	return s[i:]
 }
 
 // Convert words of q to base b digits in s. If q is large, it is recursively "split in half"
@@ -349,7 +347,7 @@ func (x nat) string(charset string) string {
 // ~30x for 20000 digits. Use nat_test.go's BenchmarkLeafSize tests to optimize leafSize for
 // specific hardware.
 //
-func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word, table []divisor) {
+func (q nat) convertWords(s []byte, b Word, ndigits int, bb Word, table []divisor) {
 	// split larger blocks recursively
 	if table != nil {
 		// len(q) > leafSize > 0
@@ -374,8 +372,8 @@ func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word
 
 			// convert subblocks and collect results in s[:h] and s[h:]
 			h := len(s) - table[index].ndigits
-			r.convertWords(s[h:], charset, b, ndigits, bb, table[0:index])
-			s = s[:h] // == q.convertWords(s, charset, b, ndigits, bb, table[0:index+1])
+			r.convertWords(s[h:], b, ndigits, bb, table[0:index])
+			s = s[:h] // == q.convertWords(s, b, ndigits, bb, table[0:index+1])
 		}
 	}
 
@@ -393,7 +391,7 @@ func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word
 				// this appears to be faster for BenchmarkString10000Base10
 				// and smaller strings (but a bit slower for larger ones)
 				t := r / 10
-				s[i] = charset[r-t<<3-t-t] // TODO(gri) replace w/ t*10 once compiler produces better code
+				s[i] = '0' + byte(r-t<<3-t-t) // TODO(gri) replace w/ t*10 once compiler produces better code
 				r = t
 			}
 		}
@@ -403,17 +401,16 @@ func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word
 			q, r = q.divW(q, bb)
 			for j := 0; j < ndigits && i > 0; j++ {
 				i--
-				s[i] = charset[r%b]
+				s[i] = digits[r%b]
 				r /= b
 			}
 		}
 	}
 
-	// prepend high-order zeroes
-	zero := charset[0]
-	for i > 0 { // while need more leading zeroes
+	// prepend high-order zeros
+	for i > 0 { // while need more leading zeros
 		i--
-		s[i] = zero
+		s[i] = '0'
 	}
 }
 
@@ -425,7 +422,7 @@ var leafSize int = 8 // number of Word-size binary values treat as a monolithic
 
 type divisor struct {
 	bbb     nat // divisor
-	nbits   int // bit length of divisor (discounting leading zeroes) ~= log2(bbb)
+	nbits   int // bit length of divisor (discounting leading zeros) ~= log2(bbb)
 	ndigits int // digit length of divisor in terms of output base digits
 }
 
diff --git a/src/cmd/compile/internal/big/natconv_test.go b/src/cmd/compile/internal/big/natconv_test.go
index f321fbc..028e5a8 100644
--- a/src/cmd/compile/internal/big/natconv_test.go
+++ b/src/cmd/compile/internal/big/natconv_test.go
@@ -5,20 +5,19 @@
 package big
 
 import (
+	"bytes"
 	"io"
 	"strings"
 	"testing"
 )
 
-func toString(x nat, charset string) string {
-	base := len(charset)
-
+func itoa(x nat, base int) []byte {
 	// special cases
 	switch {
 	case base < 2:
 		panic("illegal base")
 	case len(x) == 0:
-		return string(charset[0])
+		return []byte("0")
 	}
 
 	// allocate buffer for conversion
@@ -33,54 +32,53 @@ func toString(x nat, charset string) string {
 		i--
 		var r Word
 		q, r = q.divW(q, Word(base))
-		s[i] = charset[r]
+		s[i] = digits[r]
 	}
 
-	return string(s[i:])
+	return s[i:]
 }
 
 var strTests = []struct {
 	x nat    // nat value to be converted
-	c string // conversion charset
+	b int    // conversion base
 	s string // expected result
 }{
-	{nil, "01", "0"},
-	{nat{1}, "01", "1"},
-	{nat{0xc5}, "01", "11000101"},
-	{nat{03271}, lowercaseDigits[:8], "3271"},
-	{nat{10}, lowercaseDigits[:10], "10"},
-	{nat{1234567890}, uppercaseDigits[:10], "1234567890"},
-	{nat{0xdeadbeef}, lowercaseDigits[:16], "deadbeef"},
-	{nat{0xdeadbeef}, uppercaseDigits[:16], "DEADBEEF"},
-	{nat{0x229be7}, lowercaseDigits[:17], "1a2b3c"},
-	{nat{0x309663e6}, uppercaseDigits[:32], "O9COV6"},
+	{nil, 2, "0"},
+	{nat{1}, 2, "1"},
+	{nat{0xc5}, 2, "11000101"},
+	{nat{03271}, 8, "3271"},
+	{nat{10}, 10, "10"},
+	{nat{1234567890}, 10, "1234567890"},
+	{nat{0xdeadbeef}, 16, "deadbeef"},
+	{nat{0x229be7}, 17, "1a2b3c"},
+	{nat{0x309663e6}, 32, "o9cov6"},
 }
 
 func TestString(t *testing.T) {
-	// test invalid character set explicitly
+	// test invalid base explicitly
 	var panicStr string
 	func() {
 		defer func() {
 			panicStr = recover().(string)
 		}()
-		natOne.string("0")
+		natOne.utoa(1)
 	}()
-	if panicStr != "invalid character set length" {
-		t.Errorf("expected panic for invalid character set")
+	if panicStr != "invalid base" {
+		t.Errorf("expected panic for invalid base")
 	}
 
 	for _, a := range strTests {
-		s := a.x.string(a.c)
+		s := string(a.x.utoa(a.b))
 		if s != a.s {
 			t.Errorf("string%+v\n\tgot s = %s; want %s", a, s, a.s)
 		}
 
-		x, b, _, err := nat(nil).scan(strings.NewReader(a.s), len(a.c), false)
+		x, b, _, err := nat(nil).scan(strings.NewReader(a.s), a.b, false)
 		if x.cmp(a.x) != 0 {
 			t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x)
 		}
-		if b != len(a.c) {
-			t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, len(a.c))
+		if b != a.b {
+			t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, a.b)
 		}
 		if err != nil {
 			t.Errorf("scan%+v\n\tgot error = %s", a, err)
@@ -236,7 +234,7 @@ func TestScanPi(t *testing.T) {
 	if err != nil {
 		t.Errorf("scanning pi: %s", err)
 	}
-	if s := z.decimalString(); s != pi {
+	if s := string(z.utoa(10)); s != pi {
 		t.Errorf("scanning pi: got %s", s)
 	}
 }
@@ -265,12 +263,12 @@ func BenchmarkScanPi(b *testing.B) {
 func BenchmarkStringPiParallel(b *testing.B) {
 	var x nat
 	x, _, _, _ = x.scan(strings.NewReader(pi), 0, false)
-	if x.decimalString() != pi {
+	if string(x.utoa(10)) != pi {
 		panic("benchmark incorrect: conversion failed")
 	}
 	b.RunParallel(func(pb *testing.PB) {
 		for pb.Next() {
-			x.decimalString()
+			x.utoa(10)
 		}
 	})
 }
@@ -304,15 +302,14 @@ func ScanHelper(b *testing.B, base int, x, y Word) {
 	var z nat
 	z = z.expWW(x, y)
 
-	var s string
-	s = z.string(lowercaseDigits[:base])
-	if t := toString(z, lowercaseDigits[:base]); t != s {
+	s := z.utoa(base)
+	if t := itoa(z, base); !bytes.Equal(s, t) {
 		b.Fatalf("scanning: got %s; want %s", s, t)
 	}
 	b.StartTimer()
 
 	for i := 0; i < b.N; i++ {
-		z.scan(strings.NewReader(s), base, false)
+		z.scan(bytes.NewReader(s), base, false)
 	}
 }
 
@@ -344,11 +341,11 @@ func StringHelper(b *testing.B, base int, x, y Word) {
 	b.StopTimer()
 	var z nat
 	z = z.expWW(x, y)
-	z.string(lowercaseDigits[:base]) // warm divisor cache
+	z.utoa(base) // warm divisor cache
 	b.StartTimer()
 
 	for i := 0; i < b.N; i++ {
-		_ = z.string(lowercaseDigits[:base])
+		_ = z.utoa(base)
 	}
 }
 
@@ -372,7 +369,7 @@ func BenchmarkLeafSize16(b *testing.B) { LeafSizeHelper(b, 10, 16) }
 func BenchmarkLeafSize32(b *testing.B) { LeafSizeHelper(b, 10, 32) } // try some large lengths
 func BenchmarkLeafSize64(b *testing.B) { LeafSizeHelper(b, 10, 64) }
 
-func LeafSizeHelper(b *testing.B, base Word, size int) {
+func LeafSizeHelper(b *testing.B, base, size int) {
 	b.StopTimer()
 	originalLeafSize := leafSize
 	resetTable(cacheBase10.table[:])
@@ -382,12 +379,12 @@ func LeafSizeHelper(b *testing.B, base Word, size int) {
 	for d := 1; d <= 10000; d *= 10 {
 		b.StopTimer()
 		var z nat
-		z = z.expWW(base, Word(d))           // build target number
-		_ = z.string(lowercaseDigits[:base]) // warm divisor cache
+		z = z.expWW(Word(base), Word(d)) // build target number
+		_ = z.utoa(base)                 // warm divisor cache
 		b.StartTimer()
 
 		for i := 0; i < b.N; i++ {
-			_ = z.string(lowercaseDigits[:base])
+			_ = z.utoa(base)
 		}
 	}
 
@@ -408,13 +405,13 @@ func resetTable(table []divisor) {
 }
 
 func TestStringPowers(t *testing.T) {
-	var b, p Word
-	for b = 2; b <= 16; b++ {
+	var p Word
+	for b := 2; b <= 16; b++ {
 		for p = 0; p <= 512; p++ {
-			x := nat(nil).expWW(b, p)
-			xs := x.string(lowercaseDigits[:b])
-			xs2 := toString(x, lowercaseDigits[:b])
-			if xs != xs2 {
+			x := nat(nil).expWW(Word(b), p)
+			xs := x.utoa(b)
+			xs2 := itoa(x, b)
+			if !bytes.Equal(xs, xs2) {
 				t.Errorf("failed at %d ** %d in base %d: %s != %s", b, p, b, xs, xs2)
 			}
 		}
diff --git a/src/cmd/compile/internal/big/rat.go b/src/cmd/compile/internal/big/rat.go
index fb16f18..2cd9ed0 100644
--- a/src/cmd/compile/internal/big/rat.go
+++ b/src/cmd/compile/internal/big/rat.go
@@ -7,8 +7,6 @@
 package big
 
 import (
-	"encoding/binary"
-	"errors"
 	"fmt"
 	"math"
 )
@@ -510,61 +508,3 @@ func (z *Rat) Quo(x, y *Rat) *Rat {
 	z.a.neg = a.neg != b.neg
 	return z.norm()
 }
-
-// Gob codec version. Permits backward-compatible changes to the encoding.
-const ratGobVersion byte = 1
-
-// GobEncode implements the gob.GobEncoder interface.
-func (x *Rat) GobEncode() ([]byte, error) {
-	if x == nil {
-		return nil, nil
-	}
-	buf := make([]byte, 1+4+(len(x.a.abs)+len(x.b.abs))*_S) // extra bytes for version and sign bit (1), and numerator length (4)
-	i := x.b.abs.bytes(buf)
-	j := x.a.abs.bytes(buf[:i])
-	n := i - j
-	if int(uint32(n)) != n {
-		// this should never happen
-		return nil, errors.New("Rat.GobEncode: numerator too large")
-	}
-	binary.BigEndian.PutUint32(buf[j-4:j], uint32(n))
-	j -= 1 + 4
-	b := ratGobVersion << 1 // make space for sign bit
-	if x.a.neg {
-		b |= 1
-	}
-	buf[j] = b
-	return buf[j:], nil
-}
-
-// GobDecode implements the gob.GobDecoder interface.
-func (z *Rat) GobDecode(buf []byte) error {
-	if len(buf) == 0 {
-		// Other side sent a nil or default value.
-		*z = Rat{}
-		return nil
-	}
-	b := buf[0]
-	if b>>1 != ratGobVersion {
-		return fmt.Errorf("Rat.GobDecode: encoding version %d not supported", b>>1)
-	}
-	const j = 1 + 4
-	i := j + binary.BigEndian.Uint32(buf[j-4:j])
-	z.a.neg = b&1 != 0
-	z.a.abs = z.a.abs.setBytes(buf[j:i])
-	z.b.abs = z.b.abs.setBytes(buf[i:])
-	return nil
-}
-
-// MarshalText implements the encoding.TextMarshaler interface.
-func (r *Rat) MarshalText() (text []byte, err error) {
-	return []byte(r.RatString()), nil
-}
-
-// UnmarshalText implements the encoding.TextUnmarshaler interface.
-func (r *Rat) UnmarshalText(text []byte) error {
-	if _, ok := r.SetString(string(text)); !ok {
-		return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Rat", text)
-	}
-	return nil
-}
diff --git a/src/cmd/compile/internal/big/rat_test.go b/src/cmd/compile/internal/big/rat_test.go
index 012d0c4..3a06fca 100644
--- a/src/cmd/compile/internal/big/rat_test.go
+++ b/src/cmd/compile/internal/big/rat_test.go
@@ -5,10 +5,6 @@
 package big
 
 import (
-	"bytes"
-	"encoding/gob"
-	"encoding/json"
-	"encoding/xml"
 	"math"
 	"testing"
 )
@@ -280,116 +276,6 @@ func TestRatSetFrac64Rat(t *testing.T) {
 	}
 }
 
-func TestRatGobEncoding(t *testing.T) {
-	var medium bytes.Buffer
-	enc := gob.NewEncoder(&medium)
-	dec := gob.NewDecoder(&medium)
-	for _, test := range encodingTests {
-		medium.Reset() // empty buffer for each test case (in case of failures)
-		var tx Rat
-		tx.SetString(test + ".14159265")
-		if err := enc.Encode(&tx); err != nil {
-			t.Errorf("encoding of %s failed: %s", &tx, err)
-		}
-		var rx Rat
-		if err := dec.Decode(&rx); err != nil {
-			t.Errorf("decoding of %s failed: %s", &tx, err)
-		}
-		if rx.Cmp(&tx) != 0 {
-			t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx)
-		}
-	}
-}
-
-// Sending a nil Rat pointer (inside a slice) on a round trip through gob should yield a zero.
-// TODO: top-level nils.
-func TestGobEncodingNilRatInSlice(t *testing.T) {
-	buf := new(bytes.Buffer)
-	enc := gob.NewEncoder(buf)
-	dec := gob.NewDecoder(buf)
-
-	var in = make([]*Rat, 1)
-	err := enc.Encode(&in)
-	if err != nil {
-		t.Errorf("gob encode failed: %q", err)
-	}
-	var out []*Rat
-	err = dec.Decode(&out)
-	if err != nil {
-		t.Fatalf("gob decode failed: %q", err)
-	}
-	if len(out) != 1 {
-		t.Fatalf("wrong len; want 1 got %d", len(out))
-	}
-	var zero Rat
-	if out[0].Cmp(&zero) != 0 {
-		t.Errorf("transmission of (*Int)(nill) failed: got %s want 0", out)
-	}
-}
-
-var ratNums = []string{
-	"-141592653589793238462643383279502884197169399375105820974944592307816406286",
-	"-1415926535897932384626433832795028841971",
-	"-141592653589793",
-	"-1",
-	"0",
-	"1",
-	"141592653589793",
-	"1415926535897932384626433832795028841971",
-	"141592653589793238462643383279502884197169399375105820974944592307816406286",
-}
-
-var ratDenoms = []string{
-	"1",
-	"718281828459045",
-	"7182818284590452353602874713526624977572",
-	"718281828459045235360287471352662497757247093699959574966967627724076630353",
-}
-
-func TestRatJSONEncoding(t *testing.T) {
-	for _, num := range ratNums {
-		for _, denom := range ratDenoms {
-			var tx Rat
-			tx.SetString(num + "/" + denom)
-			b, err := json.Marshal(&tx)
-			if err != nil {
-				t.Errorf("marshaling of %s failed: %s", &tx, err)
-				continue
-			}
-			var rx Rat
-			if err := json.Unmarshal(b, &rx); err != nil {
-				t.Errorf("unmarshaling of %s failed: %s", &tx, err)
-				continue
-			}
-			if rx.Cmp(&tx) != 0 {
-				t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx)
-			}
-		}
-	}
-}
-
-func TestRatXMLEncoding(t *testing.T) {
-	for _, num := range ratNums {
-		for _, denom := range ratDenoms {
-			var tx Rat
-			tx.SetString(num + "/" + denom)
-			b, err := xml.Marshal(&tx)
-			if err != nil {
-				t.Errorf("marshaling of %s failed: %s", &tx, err)
-				continue
-			}
-			var rx Rat
-			if err := xml.Unmarshal(b, &rx); err != nil {
-				t.Errorf("unmarshaling of %s failed: %s", &tx, err)
-				continue
-			}
-			if rx.Cmp(&tx) != 0 {
-				t.Errorf("XML encoding of %s failed: got %s want %s", &tx, &rx, &tx)
-			}
-		}
-	}
-}
-
 func TestIssue2379(t *testing.T) {
 	// 1) no aliasing
 	q := NewRat(3, 2)
diff --git a/src/cmd/compile/internal/big/ratconv.go b/src/cmd/compile/internal/big/ratconv.go
index 778077b..4566ff4 100644
--- a/src/cmd/compile/internal/big/ratconv.go
+++ b/src/cmd/compile/internal/big/ratconv.go
@@ -188,11 +188,15 @@ func scanExponent(r io.ByteScanner, binExpOk bool) (exp int64, base int, err err
 
 // String returns a string representation of x in the form "a/b" (even if b == 1).
 func (x *Rat) String() string {
-	s := "/1"
+	var buf []byte
+	buf = x.a.Append(buf, 10)
+	buf = append(buf, '/')
 	if len(x.b.abs) != 0 {
-		s = "/" + x.b.abs.decimalString()
+		buf = x.b.Append(buf, 10)
+	} else {
+		buf = append(buf, '1')
 	}
-	return x.a.String() + s
+	return string(buf)
 }
 
 // RatString returns a string representation of x in the form "a/b" if b != 1,
@@ -205,14 +209,20 @@ func (x *Rat) RatString() string {
 }
 
 // FloatString returns a string representation of x in decimal form with prec
-// digits of precision after the decimal point and the last digit rounded.
+// digits of precision after the decimal point. The last digit is rounded to
+// nearest, with halves rounded away from zero.
 func (x *Rat) FloatString(prec int) string {
+	var buf []byte
+
 	if x.IsInt() {
-		s := x.a.String()
+		buf = x.a.Append(buf, 10)
 		if prec > 0 {
-			s += "." + strings.Repeat("0", prec)
+			buf = append(buf, '.')
+			for i := prec; i > 0; i-- {
+				buf = append(buf, '0')
+			}
 		}
-		return s
+		return string(buf)
 	}
 	// x.b.abs != 0
 
@@ -236,16 +246,19 @@ func (x *Rat) FloatString(prec int) string {
 		}
 	}
 
-	s := q.decimalString()
 	if x.a.neg {
-		s = "-" + s
+		buf = append(buf, '-')
 	}
+	buf = append(buf, q.utoa(10)...) // itoa ignores sign if q == 0
 
 	if prec > 0 {
-		rs := r.decimalString()
-		leadingZeros := prec - len(rs)
-		s += "." + strings.Repeat("0", leadingZeros) + rs
+		buf = append(buf, '.')
+		rs := r.utoa(10)
+		for i := prec - len(rs); i > 0; i-- {
+			buf = append(buf, '0')
+		}
+		buf = append(buf, rs...)
 	}
 
-	return s
+	return string(buf)
 }
diff --git a/src/cmd/compile/internal/big/ratconv_test.go b/src/cmd/compile/internal/big/ratconv_test.go
index 16b3a19..da2fdab 100644
--- a/src/cmd/compile/internal/big/ratconv_test.go
+++ b/src/cmd/compile/internal/big/ratconv_test.go
@@ -113,6 +113,8 @@ var floatStringTests = []struct {
 	{"1", 0, "1"},
 	{"1", 2, "1.00"},
 	{"-1", 0, "-1"},
+	{"0.05", 1, "0.1"},
+	{"-0.05", 1, "-0.1"},
 	{".25", 2, "0.25"},
 	{".25", 1, "0.3"},
 	{".25", 3, "0.250"},
diff --git a/src/cmd/compile/internal/gc/align.go b/src/cmd/compile/internal/gc/align.go
index 60c59fc..812a8cb 100644
--- a/src/cmd/compile/internal/gc/align.go
+++ b/src/cmd/compile/internal/gc/align.go
@@ -6,17 +6,13 @@ package gc
 
 import "cmd/internal/obj"
 
-/*
- * machine size and rounding
- * alignment is dictated around
- * the size of a pointer, set in betypeinit
- * (see ../6g/galign.c).
- */
+// machine size and rounding alignment is dictated around
+// the size of a pointer, set in betypeinit (see ../amd64/galign.go).
 var defercalc int
 
 func Rnd(o int64, r int64) int64 {
 	if r < 1 || r > 8 || r&(r-1) != 0 {
-		Fatal("rnd %d", r)
+		Fatalf("rnd %d", r)
 	}
 	return (o + r - 1) &^ (r - 1)
 }
@@ -25,7 +21,7 @@ func offmod(t *Type) {
 	o := int32(0)
 	for f := t.Type; f != nil; f = f.Down {
 		if f.Etype != TFIELD {
-			Fatal("offmod: not TFIELD: %v", Tconv(f, obj.FmtLong))
+			Fatalf("offmod: not TFIELD: %v", Tconv(f, obj.FmtLong))
 		}
 		f.Width = int64(o)
 		o += int32(Widthptr)
@@ -46,7 +42,7 @@ func widstruct(errtype *Type, t *Type, o int64, flag int) int64 {
 	var w int64
 	for f := t.Type; f != nil; f = f.Down {
 		if f.Etype != TFIELD {
-			Fatal("widstruct: not TFIELD: %v", Tconv(f, obj.FmtLong))
+			Fatalf("widstruct: not TFIELD: %v", Tconv(f, obj.FmtLong))
 		}
 		if f.Type == nil {
 			// broken field, just skip it so that other valid fields
@@ -59,7 +55,7 @@ func widstruct(errtype *Type, t *Type, o int64, flag int) int64 {
 			maxalign = int32(f.Type.Align)
 		}
 		if f.Type.Width < 0 {
-			Fatal("invalid width %d", f.Type.Width)
+			Fatalf("invalid width %d", f.Type.Width)
 		}
 		w = f.Type.Width
 		if f.Type.Align > 0 {
@@ -68,7 +64,7 @@ func widstruct(errtype *Type, t *Type, o int64, flag int) int64 {
 		f.Width = o // really offset for TFIELD
 		if f.Nname != nil {
 			// this same stackparam logic is in addrescapes
-			// in typecheck.c.  usually addrescapes runs after
+			// in typecheck.go.  usually addrescapes runs after
 			// widstruct, in which case we could drop this,
 			// but function closure functions are the exception.
 			if f.Nname.Name.Param.Stackparam != nil {
@@ -111,7 +107,7 @@ func widstruct(errtype *Type, t *Type, o int64, flag int) int64 {
 
 func dowidth(t *Type) {
 	if Widthptr == 0 {
-		Fatal("dowidth without betypeinit")
+		Fatalf("dowidth without betypeinit")
 	}
 
 	if t == nil {
@@ -121,7 +117,7 @@ func dowidth(t *Type) {
 	if t.Width > 0 {
 		if t.Align == 0 {
 			// See issue 11354
-			Fatal("zero alignment with nonzero size %v", t)
+			Fatalf("zero alignment with nonzero size %v", t)
 		}
 		return
 	}
@@ -129,8 +125,8 @@ func dowidth(t *Type) {
 	if t.Width == -2 {
 		lno := int(lineno)
 		lineno = int32(t.Lineno)
-		if t.Broke == 0 {
-			t.Broke = 1
+		if !t.Broke {
+			t.Broke = true
 			Yyerror("invalid recursive type %v", t)
 		}
 
@@ -141,7 +137,7 @@ func dowidth(t *Type) {
 
 	// break infinite recursion if the broken recursive type
 	// is referenced again
-	if t.Broke != 0 && t.Width == 0 {
+	if t.Broke && t.Width == 0 {
 		return
 	}
 
@@ -153,24 +149,24 @@ func dowidth(t *Type) {
 	t.Width = -2
 	t.Align = 0
 
-	et := int32(t.Etype)
+	et := t.Etype
 	switch et {
 	case TFUNC, TCHAN, TMAP, TSTRING:
 		break
 
-		/* simtype == 0 during bootstrap */
+	// simtype == 0 during bootstrap
 	default:
 		if Simtype[t.Etype] != 0 {
-			et = int32(Simtype[t.Etype])
+			et = Simtype[t.Etype]
 		}
 	}
 
 	w := int64(0)
 	switch et {
 	default:
-		Fatal("dowidth: unknown type: %v", t)
+		Fatalf("dowidth: unknown type: %v", t)
 
-		/* compiler-specific stuff */
+	// compiler-specific stuff
 	case TINT8, TUINT8, TBOOL:
 		// bool is int8
 		w = 1
@@ -233,21 +229,21 @@ func dowidth(t *Type) {
 		checkwidth(t.Down)
 
 	case TFORW: // should have been filled in
-		if t.Broke == 0 {
+		if !t.Broke {
 			Yyerror("invalid recursive type %v", t)
 		}
 		w = 1 // anything will do
 
-		// dummy type; should be replaced before use.
+	// dummy type; should be replaced before use.
 	case TANY:
 		if Debug['A'] == 0 {
-			Fatal("dowidth any")
+			Fatalf("dowidth any")
 		}
 		w = 1 // anything will do
 
 	case TSTRING:
 		if sizeof_String == 0 {
-			Fatal("early dowidth string")
+			Fatalf("early dowidth string")
 		}
 		w = int64(sizeof_String)
 		t.Align = uint8(Widthptr)
@@ -272,21 +268,21 @@ func dowidth(t *Type) {
 			checkwidth(t.Type)
 			t.Align = uint8(Widthptr)
 		} else if t.Bound == -100 {
-			if t.Broke == 0 {
+			if !t.Broke {
 				Yyerror("use of [...] array outside of array literal")
-				t.Broke = 1
+				t.Broke = true
 			}
 		} else {
-			Fatal("dowidth %v", t) // probably [...]T
+			Fatalf("dowidth %v", t) // probably [...]T
 		}
 
 	case TSTRUCT:
-		if t.Funarg != 0 {
-			Fatal("dowidth fn struct %v", t)
+		if t.Funarg {
+			Fatalf("dowidth fn struct %v", t)
 		}
 		w = widstruct(t, t, 0, 1)
 
-		// make fake type to check later to
+	// make fake type to check later to
 	// trigger function argument computation.
 	case TFUNC:
 		t1 := typ(TFUNCARGS)
@@ -297,7 +293,7 @@ func dowidth(t *Type) {
 		// width of func type is pointer
 		w = int64(Widthptr)
 
-		// function is 3 cated structures;
+	// function is 3 cated structures;
 	// compute their widths as side-effect.
 	case TFUNCARGS:
 		t1 := t.Type
@@ -319,7 +315,7 @@ func dowidth(t *Type) {
 	t.Width = w
 	if t.Align == 0 {
 		if w > 8 || w&(w-1) != 0 {
-			Fatal("invalid alignment for %v", t)
+			Fatalf("invalid alignment for %v", t)
 		}
 		t.Align = uint8(w)
 	}
@@ -333,23 +329,21 @@ func dowidth(t *Type) {
 	}
 }
 
-/*
- * when a type's width should be known, we call checkwidth
- * to compute it.  during a declaration like
- *
- *	type T *struct { next T }
- *
- * it is necessary to defer the calculation of the struct width
- * until after T has been initialized to be a pointer to that struct.
- * similarly, during import processing structs may be used
- * before their definition.  in those situations, calling
- * defercheckwidth() stops width calculations until
- * resumecheckwidth() is called, at which point all the
- * checkwidths that were deferred are executed.
- * dowidth should only be called when the type's size
- * is needed immediately.  checkwidth makes sure the
- * size is evaluated eventually.
- */
+// when a type's width should be known, we call checkwidth
+// to compute it.  during a declaration like
+//
+//	type T *struct { next T }
+//
+// it is necessary to defer the calculation of the struct width
+// until after T has been initialized to be a pointer to that struct.
+// similarly, during import processing structs may be used
+// before their definition.  in those situations, calling
+// defercheckwidth() stops width calculations until
+// resumecheckwidth() is called, at which point all the
+// checkwidths that were deferred are executed.
+// dowidth should only be called when the type's size
+// is needed immediately.  checkwidth makes sure the
+// size is evaluated eventually.
 type TypeList struct {
 	t    *Type
 	next *TypeList
@@ -366,8 +360,8 @@ func checkwidth(t *Type) {
 
 	// function arg structs should not be checked
 	// outside of the enclosing function.
-	if t.Funarg != 0 {
-		Fatal("checkwidth %v", t)
+	if t.Funarg {
+		Fatalf("checkwidth %v", t)
 	}
 
 	if defercalc == 0 {
@@ -375,10 +369,10 @@ func checkwidth(t *Type) {
 		return
 	}
 
-	if t.Deferwidth != 0 {
+	if t.Deferwidth {
 		return
 	}
-	t.Deferwidth = 1
+	t.Deferwidth = true
 
 	l := tlfree
 	if l != nil {
@@ -395,17 +389,17 @@ func checkwidth(t *Type) {
 func defercheckwidth() {
 	// we get out of sync on syntax errors, so don't be pedantic.
 	if defercalc != 0 && nerrors == 0 {
-		Fatal("defercheckwidth")
+		Fatalf("defercheckwidth")
 	}
 	defercalc = 1
 }
 
 func resumecheckwidth() {
 	if defercalc == 0 {
-		Fatal("resumecheckwidth")
+		Fatalf("resumecheckwidth")
 	}
 	for l := tlq; l != nil; l = tlq {
-		l.t.Deferwidth = 0
+		l.t.Deferwidth = false
 		tlq = l.next
 		dowidth(l.t)
 		l.next = tlfree
@@ -419,11 +413,11 @@ var itable *Type // distinguished *byte
 
 func typeinit() {
 	if Widthptr == 0 {
-		Fatal("typeinit before betypeinit")
+		Fatalf("typeinit before betypeinit")
 	}
 
-	for i := 0; i < NTYPE; i++ {
-		Simtype[i] = uint8(i)
+	for et := EType(0); et < NTYPE; et++ {
+		Simtype[et] = et
 	}
 
 	Types[TPTR32] = typ(TPTR32)
@@ -445,8 +439,8 @@ func typeinit() {
 		Tptr = TPTR64
 	}
 
-	for i := TINT8; i <= TUINT64; i++ {
-		Isint[i] = true
+	for et := TINT8; et <= TUINT64; et++ {
+		Isint[et] = true
 	}
 	Isint[TINT] = true
 	Isint[TUINT] = true
@@ -469,39 +463,37 @@ func typeinit() {
 	Issigned[TINT32] = true
 	Issigned[TINT64] = true
 
-	/*
-	 * initialize okfor
-	 */
-	for i := 0; i < NTYPE; i++ {
-		if Isint[i] || i == TIDEAL {
-			okforeq[i] = true
-			okforcmp[i] = true
-			okforarith[i] = true
-			okforadd[i] = true
-			okforand[i] = true
-			okforconst[i] = true
-			issimple[i] = true
-			Minintval[i] = new(Mpint)
-			Maxintval[i] = new(Mpint)
+	// initialize okfor
+	for et := EType(0); et < NTYPE; et++ {
+		if Isint[et] || et == TIDEAL {
+			okforeq[et] = true
+			okforcmp[et] = true
+			okforarith[et] = true
+			okforadd[et] = true
+			okforand[et] = true
+			okforconst[et] = true
+			issimple[et] = true
+			Minintval[et] = new(Mpint)
+			Maxintval[et] = new(Mpint)
 		}
 
-		if Isfloat[i] {
-			okforeq[i] = true
-			okforcmp[i] = true
-			okforadd[i] = true
-			okforarith[i] = true
-			okforconst[i] = true
-			issimple[i] = true
-			minfltval[i] = newMpflt()
-			maxfltval[i] = newMpflt()
+		if Isfloat[et] {
+			okforeq[et] = true
+			okforcmp[et] = true
+			okforadd[et] = true
+			okforarith[et] = true
+			okforconst[et] = true
+			issimple[et] = true
+			minfltval[et] = newMpflt()
+			maxfltval[et] = newMpflt()
 		}
 
-		if Iscomplex[i] {
-			okforeq[i] = true
-			okforadd[i] = true
-			okforarith[i] = true
-			okforconst[i] = true
-			issimple[i] = true
+		if Iscomplex[et] {
+			okforeq[et] = true
+			okforadd[et] = true
+			okforarith[et] = true
+			okforconst[et] = true
+			issimple[et] = true
 		}
 	}
 
@@ -599,10 +591,10 @@ func typeinit() {
 	mpatofix(Maxintval[TUINT32], "0xffffffff")
 	mpatofix(Maxintval[TUINT64], "0xffffffffffffffff")
 
-	/* f is valid float if min < f < max.  (min and max are not themselves valid.) */
-	mpatoflt(maxfltval[TFLOAT32], "33554431p103") /* 2^24-1 p (127-23) + 1/2 ulp*/
+	// f is valid float if min < f < max.  (min and max are not themselves valid.)
+	mpatoflt(maxfltval[TFLOAT32], "33554431p103") // 2^24-1 p (127-23) + 1/2 ulp
 	mpatoflt(minfltval[TFLOAT32], "-33554431p103")
-	mpatoflt(maxfltval[TFLOAT64], "18014398509481983p970") /* 2^53-1 p (1023-52) + 1/2 ulp */
+	mpatoflt(maxfltval[TFLOAT64], "18014398509481983p970") // 2^53-1 p (1023-52) + 1/2 ulp
 	mpatoflt(minfltval[TFLOAT64], "-18014398509481983p970")
 
 	maxfltval[TCOMPLEX64] = maxfltval[TFLOAT32]
@@ -610,40 +602,36 @@ func typeinit() {
 	maxfltval[TCOMPLEX128] = maxfltval[TFLOAT64]
 	minfltval[TCOMPLEX128] = minfltval[TFLOAT64]
 
-	/* for walk to use in error messages */
+	// for walk to use in error messages
 	Types[TFUNC] = functype(nil, nil, nil)
 
-	/* types used in front end */
+	// types used in front end
 	// types[TNIL] got set early in lexinit
 	Types[TIDEAL] = typ(TIDEAL)
 
 	Types[TINTER] = typ(TINTER)
 
-	/* simple aliases */
-	Simtype[TMAP] = uint8(Tptr)
+	// simple aliases
+	Simtype[TMAP] = Tptr
 
-	Simtype[TCHAN] = uint8(Tptr)
-	Simtype[TFUNC] = uint8(Tptr)
-	Simtype[TUNSAFEPTR] = uint8(Tptr)
+	Simtype[TCHAN] = Tptr
+	Simtype[TFUNC] = Tptr
+	Simtype[TUNSAFEPTR] = Tptr
 
-	/* pick up the backend thearch.typedefs */
-	var s1 *Sym
-	var etype int
-	var sameas int
-	var s *Sym
+	// pick up the backend thearch.typedefs
 	for i = range Thearch.Typedefs {
-		s = Lookup(Thearch.Typedefs[i].Name)
-		s1 = Pkglookup(Thearch.Typedefs[i].Name, builtinpkg)
+		s := Lookup(Thearch.Typedefs[i].Name)
+		s1 := Pkglookup(Thearch.Typedefs[i].Name, builtinpkg)
 
-		etype = Thearch.Typedefs[i].Etype
-		if etype < 0 || etype >= len(Types) {
-			Fatal("typeinit: %s bad etype", s.Name)
+		etype := Thearch.Typedefs[i].Etype
+		if int(etype) >= len(Types) {
+			Fatalf("typeinit: %s bad etype", s.Name)
 		}
-		sameas = Thearch.Typedefs[i].Sameas
-		if sameas < 0 || sameas >= len(Types) {
-			Fatal("typeinit: %s bad sameas", s.Name)
+		sameas := Thearch.Typedefs[i].Sameas
+		if int(sameas) >= len(Types) {
+			Fatalf("typeinit: %s bad sameas", s.Name)
 		}
-		Simtype[etype] = uint8(sameas)
+		Simtype[etype] = sameas
 		minfltval[etype] = minfltval[sameas]
 		maxfltval[etype] = maxfltval[sameas]
 		Minintval[etype] = Minintval[sameas]
@@ -651,7 +639,7 @@ func typeinit() {
 
 		t = Types[etype]
 		if t != nil {
-			Fatal("typeinit: %s already defined", s.Name)
+			Fatalf("typeinit: %s already defined", s.Name)
 		}
 
 		t = typ(etype)
@@ -678,9 +666,7 @@ func typeinit() {
 	itable.Type = Types[TUINT8]
 }
 
-/*
- * compute total size of f's in/out arguments.
- */
+// compute total size of f's in/out arguments.
 func Argsize(t *Type) int {
 	var save Iter
 	var x int64
@@ -707,7 +693,7 @@ func Argsize(t *Type) int {
 
 	w = (w + int64(Widthptr) - 1) &^ (int64(Widthptr) - 1)
 	if int64(int(w)) != w {
-		Fatal("argsize too big")
+		Fatalf("argsize too big")
 	}
 	return int(w)
 }
diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go
new file mode 100644
index 0000000..b49f0fb
--- /dev/null
+++ b/src/cmd/compile/internal/gc/bexport.go
@@ -0,0 +1,1041 @@
+// Copyright 2015 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.
+
+// Binary package export.
+// Based loosely on x/tools/go/importer.
+// (see fmt.go, go.y as "documentation" for how to use/setup data structures)
+//
+// Use "-newexport" flag to enable.
+
+// TODO(gri):
+// - inlined functions
+
+/*
+Export data encoding:
+
+The export data is a serialized description of the graph of exported
+objects: constants, types, variables, and functions. Only types can
+be re-exported and so we need to know which package they are coming
+from. Therefore, packages are also part of the export graph.
+
+The roots of the graph are the list of constants, variables, functions,
+and eventually types. Types are written last because most of them will
+be written as part of other objects which will reduce the number of
+types that need to be written separately.
+
+The graph is serialized in in-order fashion, starting with the roots.
+Each object in the graph is serialized by writing its fields sequentially.
+If the field is a pointer to another object, that object is serialized,
+recursively. Otherwise the field is written. Non-pointer fields are all
+encoded as either an integer or string value.
+
+Only packages and types may be referred to more than once. When getting
+to a package or type that was not serialized before, a number (index) is
+assigned to it, starting at 0. In this case, the encoding starts with an
+integer tag with a value < 0. The tag value indicates the kind of object
+(package or type) that follows and that this is the first time that we
+see this object. If the package or tag was already serialized, the encoding
+starts with the respective package or type index >= 0. An importer can
+trivially determine if a package or type needs to be read in for the first
+time (tag < 0) and entered into the respective package or type table, or
+if the package or type was seen already (index >= 0), in which case the
+index is the table index where the respective object can be found.
+
+Before exporting or importing, the type tables are populated with the
+predeclared types (int, string, error, unsafe.Pointer, etc.). This way
+they are automatically encoded with a known and fixed type index.
+
+Encoding format:
+
+The export data starts with a single byte indicating the encoding format
+(compact, or with debugging information), followed by a version string
+(so we can evolve the encoding if need be), the name of the imported
+package, and a string containing platform-specific information for that
+package.
+
+After this header, the lists of objects follow. After the objects, platform-
+specific data may be found which is not used strictly for type checking.
+
+The encoding of objects is straight-forward: Constants, variables, and
+functions start with their name, type, and possibly a value. Named types
+record their name and package so that they can be canonicalized: If the
+same type was imported before via another import, the importer must use
+the previously imported type pointer so that we have exactly one version
+(i.e., one pointer) for each named type (and read but discard the current
+type encoding). Unnamed types simply encode their respective fields.
+
+In the encoding, all lists (of objects, struct fields, methods, parameter
+names, but also the bytes of a string, etc.) start with an integer which
+is the length of the list. This permits an importer to allocate the right
+amount of space to hold the list without the need to grow it later.
+
+All integer values use a variable-length encoding for compact representation.
+
+If debugFormat is set, each integer and string value is preceeded by a marker
+and position information in the encoding. This mechanism permits an importer
+to recognize immediately when it is out of sync. The importer recognizes this
+mode automatically (i.e., it can import export data produced with debugging
+support even if debugFormat is not set at the time of import). Using this mode
+will massively increase the size of the export data (by a factor of 2 to 3)
+and is only recommended for debugging.
+
+The exporter and importer are completely symmetric in implementation: For
+each encoding routine there is the matching and symmetric decoding routine.
+This symmetry makes it very easy to change or extend the format: If a new
+field needs to be encoded, a symmetric change can be made to exporter and
+importer.
+*/
+
+package gc
+
+import (
+	"bytes"
+	"cmd/compile/internal/big"
+	"cmd/internal/obj"
+	"encoding/binary"
+	"fmt"
+	"sort"
+	"strings"
+)
+
+// debugging support
+const (
+	debugFormat = false // use debugging format for export data (emits a lot of additional data)
+)
+
+const exportVersion = "v0"
+
+// Set forceNewExport to force the use of the new export format - for testing on the build dashboard.
+// TODO(gri) remove eventually
+const forceNewExport = false
+
+// Export writes the export data for localpkg to out and returns the number of bytes written.
+func Export(out *obj.Biobuf, trace bool) int {
+	p := exporter{
+		out:      out,
+		pkgIndex: make(map[*Pkg]int),
+		typIndex: make(map[*Type]int),
+		trace:    trace,
+	}
+
+	// write low-level encoding format
+	var format byte = 'c' // compact
+	if debugFormat {
+		format = 'd'
+	}
+	p.byte(format)
+
+	// --- generic export data ---
+
+	if p.trace {
+		p.tracef("\n--- generic export data ---\n")
+		if p.indent != 0 {
+			Fatalf("incorrect indentation %d", p.indent)
+		}
+	}
+
+	p.string(exportVersion)
+	if p.trace {
+		p.tracef("\n")
+	}
+
+	// populate type map with predeclared "known" types
+	predecl := predeclared()
+	for index, typ := range predecl {
+		p.typIndex[typ] = index
+	}
+	if len(p.typIndex) != len(predecl) {
+		Fatalf("duplicate entries in type map?")
+	}
+
+	// write package data
+	if localpkg.Path != "" {
+		Fatalf("local package path not empty: %q", localpkg.Path)
+	}
+	p.pkg(localpkg)
+
+	// write compiler-specific flags
+	// go.y:import_safety
+	{
+		var flags string
+		if safemode != 0 {
+			flags = "safe"
+		}
+		p.string(flags)
+	}
+
+	if p.trace {
+		p.tracef("\n")
+	}
+
+	// collect objects to export
+	var consts, vars, funcs []*Sym
+	var types []*Type
+	for _, n := range exportlist {
+		sym := n.Sym
+		// TODO(gri) Closures appear marked as exported.
+		// Investigate and determine if we need this.
+		if sym.Flags&SymExported != 0 {
+			continue
+		}
+		sym.Flags |= SymExported
+
+		// TODO(gri) Closures have dots in their names;
+		// e.g., TestFloatZeroValue.func1 in math/big tests.
+		// We may not need this eventually. See also comment
+		// on sym.Flags&SymExported test above.
+		if strings.Contains(sym.Name, ".") {
+			Fatalf("unexpected export symbol: %v", sym)
+		}
+
+		if sym.Flags&SymExport != 0 {
+			if sym.Def == nil {
+				Fatalf("unknown export symbol: %v", sym)
+			}
+			switch n := sym.Def; n.Op {
+			case OLITERAL:
+				// constant
+				typecheck(&n, Erv)
+				if n == nil || n.Op != OLITERAL {
+					Fatalf("dumpexportconst: oconst nil: %v", sym)
+				}
+				consts = append(consts, sym)
+
+			case ONAME:
+				// variable or function
+				typecheck(&n, Erv|Ecall)
+				if n == nil || n.Type == nil {
+					Fatalf("variable/function exported but not defined: %v", sym)
+				}
+				if n.Type.Etype == TFUNC && n.Class == PFUNC {
+					funcs = append(funcs, sym)
+				} else {
+					vars = append(vars, sym)
+				}
+
+			case OTYPE:
+				// named type
+				t := n.Type
+				if t.Etype == TFORW {
+					Fatalf("export of incomplete type %v", sym)
+				}
+				types = append(types, t)
+
+			default:
+				Fatalf("unexpected export symbol: %v %v", Oconv(int(n.Op), 0), sym)
+			}
+		}
+	}
+	exportlist = nil // match export.go use of exportlist
+
+	// for reproducible output
+	sort.Sort(symByName(consts))
+	sort.Sort(symByName(vars))
+	sort.Sort(symByName(funcs))
+	// sort types later when we have fewer types left
+
+	// write consts
+	p.int(len(consts))
+	for _, sym := range consts {
+		n := sym.Def
+		typ := n.Type // may or may not be specified
+		// Untyped (ideal) constants get their own type. This decouples
+		// the constant type from the encoding of the constant value.
+		if typ == nil || isideal(typ) {
+			typ = untype(n.Val().Ctype())
+		}
+
+		p.string(sym.Name)
+		p.typ(typ)
+		p.value(n.Val())
+	}
+
+	// write vars
+	p.int(len(vars))
+	for _, sym := range vars {
+		p.string(sym.Name)
+		p.typ(sym.Def.Type)
+	}
+
+	// write funcs
+	p.int(len(funcs))
+	for _, sym := range funcs {
+		p.string(sym.Name)
+		// The type can only be a signature for functions. However, by always
+		// writing the complete type specification (rather than just a signature)
+		// we keep the option open of sharing common signatures across multiple
+		// functions as a means to further compress the export data.
+		p.typ(sym.Def.Type)
+		p.int(p.collectInlined(sym.Def))
+	}
+
+	// determine which types are still left to write and sort them
+	i := 0
+	for _, t := range types {
+		if _, ok := p.typIndex[t]; !ok {
+			types[i] = t
+			i++
+		}
+	}
+	types = types[:i]
+	sort.Sort(typByName(types))
+
+	// write types
+	p.int(len(types))
+	for _, t := range types {
+		// Writing a type may further reduce the number of types
+		// that are left to be written, but at this point we don't
+		// care.
+		p.typ(t)
+	}
+
+	if p.trace {
+		p.tracef("\n")
+	}
+
+	// --- compiler-specific export data ---
+
+	if p.trace {
+		p.tracef("\n--- compiler specific export data ---\n")
+		if p.indent != 0 {
+			Fatalf("incorrect indentation")
+		}
+	}
+
+	// write inlined function bodies
+	p.int(len(p.inlined))
+	for i, f := range p.inlined {
+		p.body(i, f)
+	}
+
+	if p.trace {
+		p.tracef("\n")
+	}
+
+	// --- end of export data ---
+
+	return p.written
+}
+
+type symByName []*Sym
+
+func (a symByName) Len() int           { return len(a) }
+func (a symByName) Less(i, j int) bool { return a[i].Name < a[j].Name }
+func (a symByName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+
+type typByName []*Type
+
+func (a typByName) Len() int           { return len(a) }
+func (a typByName) Less(i, j int) bool { return a[i].Sym.Name < a[j].Sym.Name }
+func (a typByName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+
+type exporter struct {
+	out      *obj.Biobuf
+	pkgIndex map[*Pkg]int
+	typIndex map[*Type]int
+	inlined  []*Func
+
+	written int // bytes written
+	indent  int // for p.trace
+	trace   bool
+}
+
+func (p *exporter) pkg(pkg *Pkg) {
+	if pkg == nil {
+		Fatalf("unexpected nil pkg")
+	}
+
+	// if we saw the package before, write its index (>= 0)
+	if i, ok := p.pkgIndex[pkg]; ok {
+		p.index('P', i)
+		return
+	}
+
+	// otherwise, remember the package, write the package tag (< 0) and package data
+	if p.trace {
+		p.tracef("P%d = { ", len(p.pkgIndex))
+		defer p.tracef("} ")
+	}
+	p.pkgIndex[pkg] = len(p.pkgIndex)
+
+	p.tag(packageTag)
+	p.string(pkg.Name)
+	p.string(pkg.Path)
+}
+
+func (p *exporter) typ(t *Type) {
+	if t == nil {
+		Fatalf("nil type")
+	}
+
+	// Possible optimization: Anonymous pointer types *T where
+	// T is a named type are common. We could canonicalize all
+	// such types *T to a single type PT = *T. This would lead
+	// to at most one *T entry in typIndex, and all future *T's
+	// would be encoded as the respective index directly. Would
+	// save 1 byte (pointerTag) per *T and reduce the typIndex
+	// size (at the cost of a canonicalization map). We can do
+	// this later, without encoding format change.
+
+	// if we saw the type before, write its index (>= 0)
+	if i, ok := p.typIndex[t]; ok {
+		p.index('T', i)
+		return
+	}
+
+	// otherwise, remember the type, write the type tag (< 0) and type data
+	if p.trace {
+		p.tracef("T%d = {>\n", len(p.typIndex))
+		defer p.tracef("<\n} ")
+	}
+	p.typIndex[t] = len(p.typIndex)
+
+	// pick off named types
+	if sym := t.Sym; sym != nil {
+		// Fields should be exported by p.field().
+		if t.Etype == TFIELD {
+			Fatalf("printing a field/parameter with wrong function")
+		}
+		// Predeclared types should have been found in the type map.
+		if t.Orig == t {
+			Fatalf("predeclared type missing from type map?")
+		}
+		// TODO(gri) The assertion below seems incorrect (crashes during all.bash).
+		// Investigate.
+		/*
+			// we expect the respective definition to point to us
+			if sym.Def.Type != t {
+				Fatalf("type definition doesn't point to us?")
+			}
+		*/
+
+		p.tag(namedTag)
+		p.qualifiedName(sym)
+
+		// write underlying type
+		p.typ(t.Orig)
+
+		// interfaces don't have associated methods
+		if t.Orig.Etype == TINTER {
+			return
+		}
+
+		// sort methods for reproducible export format
+		// TODO(gri) Determine if they are already sorted
+		// in which case we can drop this step.
+		var methods []*Type
+		for m := t.Method; m != nil; m = m.Down {
+			methods = append(methods, m)
+		}
+		sort.Sort(methodbyname(methods))
+		p.int(len(methods))
+
+		if p.trace && t.Method != nil {
+			p.tracef("associated methods {>\n")
+		}
+
+		for _, m := range methods {
+			p.string(m.Sym.Name)
+			p.paramList(getthisx(m.Type))
+			p.paramList(getinargx(m.Type))
+			p.paramList(getoutargx(m.Type))
+			p.int(p.collectInlined(m.Type.Nname))
+
+			if p.trace && m.Down != nil {
+				p.tracef("\n")
+			}
+		}
+
+		if p.trace && t.Method != nil {
+			p.tracef("<\n} ")
+		}
+
+		return
+	}
+
+	// otherwise we have a type literal
+	switch t.Etype {
+	case TARRAY:
+		// TODO(gri) define named constant for the -100
+		if t.Bound >= 0 || t.Bound == -100 {
+			p.tag(arrayTag)
+			p.int64(t.Bound)
+		} else {
+			p.tag(sliceTag)
+		}
+		p.typ(t.Type)
+
+	case T_old_DARRAY:
+		// see p.param use of T_old_DARRAY
+		p.tag(dddTag)
+		p.typ(t.Type)
+
+	case TSTRUCT:
+		p.tag(structTag)
+		p.fieldList(t)
+
+	case TPTR32, TPTR64: // could use Tptr but these are constants
+		p.tag(pointerTag)
+		p.typ(t.Type)
+
+	case TFUNC:
+		p.tag(signatureTag)
+		p.paramList(getinargx(t))
+		p.paramList(getoutargx(t))
+
+	case TINTER:
+		p.tag(interfaceTag)
+
+		// gc doesn't separate between embedded interfaces
+		// and methods declared explicitly with an interface
+		p.int(0) // no embedded interfaces
+		p.methodList(t)
+
+	case TMAP:
+		p.tag(mapTag)
+		p.typ(t.Down) // key
+		p.typ(t.Type) // val
+
+	case TCHAN:
+		p.tag(chanTag)
+		p.int(int(t.Chan))
+		p.typ(t.Type)
+
+	default:
+		Fatalf("unexpected type: %s (Etype = %d)", Tconv(t, 0), t.Etype)
+	}
+}
+
+func (p *exporter) qualifiedName(sym *Sym) {
+	p.string(sym.Name)
+	p.pkg(sym.Pkg)
+}
+
+func (p *exporter) fieldList(t *Type) {
+	if p.trace && t.Type != nil {
+		p.tracef("fields {>\n")
+		defer p.tracef("<\n} ")
+	}
+
+	p.int(countfield(t))
+	for f := t.Type; f != nil; f = f.Down {
+		p.field(f)
+		if p.trace && f.Down != nil {
+			p.tracef("\n")
+		}
+	}
+}
+
+func (p *exporter) field(f *Type) {
+	if f.Etype != TFIELD {
+		Fatalf("field expected")
+	}
+
+	p.fieldName(f)
+	p.typ(f.Type)
+	p.note(f.Note)
+}
+
+func (p *exporter) note(n *string) {
+	var s string
+	if n != nil {
+		s = *n
+	}
+	p.string(s)
+}
+
+func (p *exporter) methodList(t *Type) {
+	if p.trace && t.Type != nil {
+		p.tracef("methods {>\n")
+		defer p.tracef("<\n} ")
+	}
+
+	p.int(countfield(t))
+	for m := t.Type; m != nil; m = m.Down {
+		p.method(m)
+		if p.trace && m.Down != nil {
+			p.tracef("\n")
+		}
+	}
+}
+
+func (p *exporter) method(m *Type) {
+	if m.Etype != TFIELD {
+		Fatalf("method expected")
+	}
+
+	p.fieldName(m)
+	// TODO(gri) For functions signatures, we use p.typ() to export
+	// so we could share the same type with multiple functions. Do
+	// the same here, or never try to do this for functions.
+	p.paramList(getinargx(m.Type))
+	p.paramList(getoutargx(m.Type))
+}
+
+// fieldName is like qualifiedName but it doesn't record the package
+// for blank (_) or exported names.
+func (p *exporter) fieldName(t *Type) {
+	sym := t.Sym
+
+	var name string
+	if t.Embedded == 0 {
+		name = sym.Name
+	} else if bname := basetypeName(t); bname != "" && !exportname(bname) {
+		// anonymous field with unexported base type name: use "?" as field name
+		// (bname != "" per spec, but we are conservative in case of errors)
+		name = "?"
+	}
+
+	p.string(name)
+	if name == "?" || name != "_" && name != "" && !exportname(name) {
+		p.pkg(sym.Pkg)
+	}
+}
+
+func basetypeName(t *Type) string {
+	s := t.Sym
+	if s == nil && Isptr[t.Etype] {
+		s = t.Type.Sym // deref
+	}
+	if s != nil {
+		return s.Name
+	}
+	return ""
+}
+
+func (p *exporter) paramList(params *Type) {
+	if params.Etype != TSTRUCT || !params.Funarg {
+		Fatalf("parameter list expected")
+	}
+
+	// use negative length to indicate unnamed parameters
+	// (look at the first parameter only since either all
+	// names are present or all are absent)
+	n := countfield(params)
+	if n > 0 && parName(params.Type) == "" {
+		n = -n
+	}
+	p.int(n)
+	for q := params.Type; q != nil; q = q.Down {
+		p.param(q, n)
+	}
+}
+
+func (p *exporter) param(q *Type, n int) {
+	if q.Etype != TFIELD {
+		Fatalf("parameter expected")
+	}
+	t := q.Type
+	if q.Isddd {
+		// create a fake type to encode ... just for the p.typ call
+		// (T_old_DARRAY is not used anywhere else in the compiler,
+		// we use it here to communicate between p.param and p.typ.)
+		t = &Type{Etype: T_old_DARRAY, Type: t.Type}
+	}
+	p.typ(t)
+	if n > 0 {
+		p.string(parName(q))
+	}
+	// TODO(gri) This is compiler-specific (escape info).
+	// Move into compiler-specific section eventually?
+	// (Not having escape info causes tests to fail, e.g. runtime GCInfoTest)
+	p.note(q.Note)
+}
+
+func parName(q *Type) string {
+	if q.Sym == nil {
+		return ""
+	}
+	name := q.Sym.Name
+	// undo gc-internal name mangling - we just need the source name
+	if len(name) > 0 && name[0] == '~' {
+		// name is ~b%d or ~r%d
+		switch name[1] {
+		case 'b':
+			return "_"
+		case 'r':
+			return ""
+		default:
+			Fatalf("unexpected parameter name: %s", name)
+		}
+	}
+	// undo gc-internal name specialization
+	if i := strings.Index(name, "·"); i > 0 {
+		name = name[:i] // cut off numbering
+	}
+	return name
+}
+
+func (p *exporter) value(x Val) {
+	if p.trace {
+		p.tracef("= ")
+	}
+
+	switch x := x.U.(type) {
+	case bool:
+		tag := falseTag
+		if x {
+			tag = trueTag
+		}
+		p.tag(tag)
+
+	case *Mpint:
+		if Mpcmpfixfix(Minintval[TINT64], x) <= 0 && Mpcmpfixfix(x, Maxintval[TINT64]) <= 0 {
+			// common case: x fits into an int64 - use compact encoding
+			p.tag(int64Tag)
+			p.int64(Mpgetfix(x))
+			return
+		}
+		// uncommon case: large x - use float encoding
+		// (powers of 2 will be encoded efficiently with exponent)
+		p.tag(floatTag)
+		f := newMpflt()
+		Mpmovefixflt(f, x)
+		p.float(f)
+
+	case *Mpflt:
+		p.tag(floatTag)
+		p.float(x)
+
+	case *Mpcplx:
+		p.tag(complexTag)
+		p.float(&x.Real)
+		p.float(&x.Imag)
+
+	case string:
+		p.tag(stringTag)
+		p.string(x)
+
+	default:
+		Fatalf("unexpected value %v (%T)", x, x)
+	}
+}
+
+func (p *exporter) float(x *Mpflt) {
+	// extract sign (there is no -0)
+	f := &x.Val
+	sign := f.Sign()
+	if sign == 0 {
+		// x == 0
+		p.int(0)
+		return
+	}
+	// x != 0
+
+	// extract exponent such that 0.5 <= m < 1.0
+	var m big.Float
+	exp := f.MantExp(&m)
+
+	// extract mantissa as *big.Int
+	// - set exponent large enough so mant satisfies mant.IsInt()
+	// - get *big.Int from mant
+	m.SetMantExp(&m, int(m.MinPrec()))
+	mant, acc := m.Int(nil)
+	if acc != big.Exact {
+		Fatalf("internal error")
+	}
+
+	p.int(sign)
+	p.int(exp)
+	p.string(string(mant.Bytes()))
+}
+
+// ----------------------------------------------------------------------------
+// Inlined function bodies
+
+// TODO(gri) This section is incomplete. At the moment nothing meaningful
+// is written out for exported functions with inlined function bodies.
+
+func (p *exporter) collectInlined(n *Node) int {
+	if n != nil && n.Func != nil && n.Func.Inl != nil {
+		// when lazily typechecking inlined bodies, some re-exported ones may not have been typechecked yet.
+		// currently that can leave unresolved ONONAMEs in import-dot-ed packages in the wrong package
+		if Debug['l'] < 2 {
+			typecheckinl(n)
+		}
+		p.inlined = append(p.inlined, n.Func)
+		return len(p.inlined) - 1 // index >= 0 => inlined
+	}
+	return -1 // index < 0 => not inlined
+}
+
+func (p *exporter) body(i int, f *Func) {
+	p.int(i)
+	p.block(f.Inl)
+}
+
+func (p *exporter) block(list *NodeList) {
+	p.int(count(list))
+	for q := list; q != nil; q = q.Next {
+		p.stmt(q.N)
+	}
+}
+
+func (p *exporter) stmt(n *Node) {
+	// TODO(gri) do something sensible here
+	p.string("body")
+}
+
+// ----------------------------------------------------------------------------
+// Low-level encoders
+
+func (p *exporter) index(marker byte, index int) {
+	if index < 0 {
+		Fatalf("invalid index < 0")
+	}
+	if debugFormat {
+		p.marker('t')
+	}
+	if p.trace {
+		p.tracef("%c%d ", marker, index)
+	}
+	p.rawInt64(int64(index))
+}
+
+func (p *exporter) tag(tag int) {
+	if tag >= 0 {
+		Fatalf("invalid tag >= 0")
+	}
+	if debugFormat {
+		p.marker('t')
+	}
+	if p.trace {
+		p.tracef("%s ", tagString[-tag])
+	}
+	p.rawInt64(int64(tag))
+}
+
+func (p *exporter) int(x int) {
+	p.int64(int64(x))
+}
+
+func (p *exporter) int64(x int64) {
+	if debugFormat {
+		p.marker('i')
+	}
+	if p.trace {
+		p.tracef("%d ", x)
+	}
+	p.rawInt64(x)
+}
+
+func (p *exporter) string(s string) {
+	if debugFormat {
+		p.marker('s')
+	}
+	if p.trace {
+		p.tracef("%q ", s)
+	}
+	p.rawInt64(int64(len(s)))
+	for i := 0; i < len(s); i++ {
+		p.byte(s[i])
+	}
+}
+
+// marker emits a marker byte and position information which makes
+// it easy for a reader to detect if it is "out of sync". Used for
+// debugFormat format only.
+func (p *exporter) marker(m byte) {
+	p.byte(m)
+	p.rawInt64(int64(p.written))
+}
+
+// rawInt64 should only be used by low-level encoders
+func (p *exporter) rawInt64(x int64) {
+	var tmp [binary.MaxVarintLen64]byte
+	n := binary.PutVarint(tmp[:], x)
+	for i := 0; i < n; i++ {
+		p.byte(tmp[i])
+	}
+}
+
+// byte is the bottleneck interface to write to p.out.
+// byte escapes b as follows (any encoding does that
+// hides '$'):
+//
+//	'$'  => '|' 'S'
+//	'|'  => '|' '|'
+//
+// Necessary so other tools can find the end of the
+// export data by searching for "$$".
+func (p *exporter) byte(b byte) {
+	switch b {
+	case '$':
+		// write '$' as '|' 'S'
+		b = 'S'
+		fallthrough
+	case '|':
+		// write '|' as '|' '|'
+		obj.Bputc(p.out, '|')
+		p.written++
+	}
+	obj.Bputc(p.out, b)
+	p.written++
+}
+
+// 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 {
+		var buf bytes.Buffer
+		for i := 0; i < len(format); i++ {
+			// no need to deal with runes
+			ch := format[i]
+			switch ch {
+			case '>':
+				p.indent++
+				continue
+			case '<':
+				p.indent--
+				continue
+			}
+			buf.WriteByte(ch)
+			if ch == '\n' {
+				for j := p.indent; j > 0; j-- {
+					buf.WriteString(".  ")
+				}
+			}
+		}
+		format = buf.String()
+	}
+	fmt.Printf(format, args...)
+}
+
+// ----------------------------------------------------------------------------
+// Export format
+
+// Tags. Must be < 0.
+const (
+	// Packages
+	packageTag = -(iota + 1)
+
+	// Types
+	namedTag
+	arrayTag
+	sliceTag
+	dddTag
+	structTag
+	pointerTag
+	signatureTag
+	interfaceTag
+	mapTag
+	chanTag
+
+	// Values
+	falseTag
+	trueTag
+	int64Tag
+	floatTag
+	fractionTag // not used by gc
+	complexTag
+	stringTag
+)
+
+// Debugging support.
+// (tagString is only used when tracing is enabled)
+var tagString = [...]string{
+	// Packages:
+	-packageTag: "package",
+
+	// Types:
+	-namedTag:     "named type",
+	-arrayTag:     "array",
+	-sliceTag:     "slice",
+	-dddTag:       "ddd",
+	-structTag:    "struct",
+	-pointerTag:   "pointer",
+	-signatureTag: "signature",
+	-interfaceTag: "interface",
+	-mapTag:       "map",
+	-chanTag:      "chan",
+
+	// Values:
+	-falseTag:    "false",
+	-trueTag:     "true",
+	-int64Tag:    "int64",
+	-floatTag:    "float",
+	-fractionTag: "fraction",
+	-complexTag:  "complex",
+	-stringTag:   "string",
+}
+
+// untype returns the "pseudo" untyped type for a Ctype (import/export use only).
+// (we can't use an pre-initialized array because we must be sure all types are
+// set up)
+func untype(ctype Ctype) *Type {
+	switch ctype {
+	case CTINT:
+		return idealint
+	case CTRUNE:
+		return idealrune
+	case CTFLT:
+		return idealfloat
+	case CTCPLX:
+		return idealcomplex
+	case CTSTR:
+		return idealstring
+	case CTBOOL:
+		return idealbool
+	case CTNIL:
+		return Types[TNIL]
+	}
+	Fatalf("unknown Ctype")
+	return nil
+}
+
+var (
+	idealint     = typ(TIDEAL)
+	idealrune    = typ(TIDEAL)
+	idealfloat   = typ(TIDEAL)
+	idealcomplex = typ(TIDEAL)
+)
+
+var predecl []*Type // initialized lazily
+
+func predeclared() []*Type {
+	if predecl == nil {
+		// initialize lazily to be sure that all
+		// elements have been initialized before
+		predecl = []*Type{
+			// basic types
+			Types[TBOOL],
+			Types[TINT],
+			Types[TINT8],
+			Types[TINT16],
+			Types[TINT32],
+			Types[TINT64],
+			Types[TUINT],
+			Types[TUINT8],
+			Types[TUINT16],
+			Types[TUINT32],
+			Types[TUINT64],
+			Types[TUINTPTR],
+			Types[TFLOAT32],
+			Types[TFLOAT64],
+			Types[TCOMPLEX64],
+			Types[TCOMPLEX128],
+			Types[TSTRING],
+
+			// aliases
+			bytetype,
+			runetype,
+
+			// error
+			errortype,
+
+			// untyped types
+			untype(CTBOOL),
+			untype(CTINT),
+			untype(CTRUNE),
+			untype(CTFLT),
+			untype(CTCPLX),
+			untype(CTSTR),
+			untype(CTNIL),
+
+			// package unsafe
+			Types[TUNSAFEPTR],
+		}
+	}
+	return predecl
+}
diff --git a/src/cmd/compile/internal/gc/bimport.go b/src/cmd/compile/internal/gc/bimport.go
new file mode 100644
index 0000000..731f31b
--- /dev/null
+++ b/src/cmd/compile/internal/gc/bimport.go
@@ -0,0 +1,634 @@
+// Copyright 2015 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.
+
+// Binary package import.
+// Based loosely on x/tools/go/importer.
+
+package gc
+
+import (
+	"cmd/compile/internal/big"
+	"cmd/internal/obj"
+	"encoding/binary"
+)
+
+// The overall structure of Import is symmetric to Export: For each
+// export method in bexport.go there is a matching and symmetric method
+// in bimport.go. Changing the export format requires making symmetric
+// changes to bimport.go and bexport.go.
+
+// Import populates importpkg from the serialized package data.
+func Import(in *obj.Biobuf) {
+	p := importer{in: in}
+	p.buf = p.bufarray[:]
+
+	// read low-level encoding format
+	switch format := p.byte(); format {
+	case 'c':
+		// compact format - nothing to do
+	case 'd':
+		p.debugFormat = true
+	default:
+		Fatalf("invalid encoding format in export data: got %q; want 'c' or 'd'", format)
+	}
+
+	// --- generic export data ---
+
+	if v := p.string(); v != exportVersion {
+		Fatalf("unknown export data version: %s", v)
+	}
+
+	// populate typList with predeclared "known" types
+	p.typList = append(p.typList, predeclared()...)
+
+	// read package data
+	p.pkg()
+	if p.pkgList[0] != importpkg {
+		Fatalf("imported package not found in pkgList[0]")
+	}
+
+	// read compiler-specific flags
+	importpkg.Safe = p.string() == "safe"
+
+	// defer some type-checking until all types are read in completely
+	// (go.y:import_there)
+	tcok := typecheckok
+	typecheckok = true
+	defercheckwidth()
+
+	// read consts
+	for i := p.int(); i > 0; i-- {
+		sym := p.localname()
+		typ := p.typ()
+		val := p.value(typ)
+		if isideal(typ) {
+			// canonicalize ideal types
+			typ = Types[TIDEAL]
+		}
+		importconst(sym, typ, nodlit(val))
+	}
+
+	// read vars
+	for i := p.int(); i > 0; i-- {
+		sym := p.localname()
+		typ := p.typ()
+		importvar(sym, typ)
+	}
+
+	// read funcs
+	for i := p.int(); i > 0; i-- {
+		// go.y:hidden_fndcl
+		sym := p.localname()
+		typ := p.typ()
+		// TODO(gri) fix this
+		p.int() // read and discard index of inlined function body for now
+
+		importsym(sym, ONAME)
+		if sym.Def != nil && sym.Def.Op == ONAME && !Eqtype(typ, sym.Def.Type) {
+			Fatalf("inconsistent definition for func %v during import\n\t%v\n\t%v", sym, sym.Def.Type, typ)
+		}
+
+		n := newfuncname(sym)
+		n.Type = typ
+		declare(n, PFUNC)
+		funchdr(n)
+
+		// go.y:hidden_import
+		n.Func.Inl = nil
+		funcbody(n)
+		importlist = append(importlist, n) // TODO(gri) do this only if body is inlineable?
+	}
+
+	// read types
+	for i := p.int(); i > 0; i-- {
+		// name is parsed as part of named type
+		p.typ()
+	}
+
+	// --- compiler-specific export data ---
+
+	for i := p.int(); i > 0; i-- {
+		p.body()
+	}
+
+	// --- end of export data ---
+
+	typecheckok = tcok
+	resumecheckwidth()
+
+	testdclstack() // debugging only
+}
+
+type importer struct {
+	in       *obj.Biobuf
+	buf      []byte   // for reading strings
+	bufarray [64]byte // initial underlying array for buf, large enough to avoid allocation when compiling std lib
+	pkgList  []*Pkg
+	typList  []*Type
+
+	debugFormat bool
+	read        int // bytes read
+}
+
+func (p *importer) pkg() *Pkg {
+	// if the package was seen before, i is its index (>= 0)
+	i := p.tagOrIndex()
+	if i >= 0 {
+		return p.pkgList[i]
+	}
+
+	// otherwise, i is the package tag (< 0)
+	if i != packageTag {
+		Fatalf("expected package tag, found tag = %d", i)
+	}
+
+	// read package data
+	name := p.string()
+	path := p.string()
+
+	// we should never see an empty package name
+	if name == "" {
+		Fatalf("empty package name in import")
+	}
+
+	// we should never see a bad import path
+	if isbadimport(path) {
+		Fatalf("bad path in import: %q", path)
+	}
+
+	// an empty path denotes the package we are currently importing
+	pkg := importpkg
+	if path != "" {
+		pkg = mkpkg(path)
+	}
+	if pkg.Name == "" {
+		pkg.Name = name
+	} else if pkg.Name != name {
+		Fatalf("inconsistent package names: got %s; want %s (path = %s)", pkg.Name, name, path)
+	}
+	p.pkgList = append(p.pkgList, pkg)
+
+	return pkg
+}
+
+func (p *importer) localname() *Sym {
+	// go.y:hidden_importsym
+	name := p.string()
+	if name == "" {
+		Fatalf("unexpected anonymous name")
+	}
+	structpkg = importpkg // go.y:hidden_pkg_importsym
+	return importpkg.Lookup(name)
+}
+
+func (p *importer) newtyp(etype EType) *Type {
+	t := typ(etype)
+	p.typList = append(p.typList, t)
+	return t
+}
+
+func (p *importer) typ() *Type {
+	// if the type was seen before, i is its index (>= 0)
+	i := p.tagOrIndex()
+	if i >= 0 {
+		return p.typList[i]
+	}
+
+	// otherwise, i is the type tag (< 0)
+	var t *Type
+	switch i {
+	case namedTag:
+		// go.y:hidden_importsym
+		tsym := p.qualifiedName()
+
+		// go.y:hidden_pkgtype
+		t = pkgtype(tsym)
+		importsym(tsym, OTYPE)
+		p.typList = append(p.typList, t)
+
+		// read underlying type
+		// go.y:hidden_type
+		t0 := p.typ()
+		importtype(t, t0) // go.y:hidden_import
+
+		// interfaces don't have associated methods
+		if t0.Etype == TINTER {
+			break
+		}
+
+		// read associated methods
+		for i := p.int(); i > 0; i-- {
+			// go.y:hidden_fndcl
+			name := p.string()
+			recv := p.paramList() // TODO(gri) do we need a full param list for the receiver?
+			params := p.paramList()
+			result := p.paramList()
+			// TODO(gri) fix this
+			p.int() // read and discard index of inlined function body for now
+
+			pkg := localpkg
+			if !exportname(name) {
+				pkg = tsym.Pkg
+			}
+			sym := pkg.Lookup(name)
+
+			n := methodname1(newname(sym), recv.N.Right)
+			n.Type = functype(recv.N, params, result)
+			checkwidth(n.Type)
+			// addmethod uses the global variable structpkg to verify consistency
+			{
+				saved := structpkg
+				structpkg = tsym.Pkg
+				addmethod(sym, n.Type, false, nointerface)
+				structpkg = saved
+			}
+			nointerface = false
+			funchdr(n)
+
+			// (comment from go.y)
+			// inl.C's inlnode in on a dotmeth node expects to find the inlineable body as
+			// (dotmeth's type).Nname.Inl, and dotmeth's type has been pulled
+			// out by typecheck's lookdot as this $$.ttype.  So by providing
+			// this back link here we avoid special casing there.
+			n.Type.Nname = n
+
+			// go.y:hidden_import
+			n.Func.Inl = nil
+			funcbody(n)
+			importlist = append(importlist, n) // TODO(gri) do this only if body is inlineable?
+		}
+
+	case arrayTag, sliceTag:
+		t = p.newtyp(TARRAY)
+		t.Bound = -1
+		if i == arrayTag {
+			t.Bound = p.int64()
+		}
+		t.Type = p.typ()
+
+	case dddTag:
+		t = p.newtyp(T_old_DARRAY)
+		t.Bound = -1
+		t.Type = p.typ()
+
+	case structTag:
+		t = p.newtyp(TSTRUCT)
+		tostruct0(t, p.fieldList())
+
+	case pointerTag:
+		t = p.newtyp(Tptr)
+		t.Type = p.typ()
+
+	case signatureTag:
+		t = p.newtyp(TFUNC)
+		params := p.paramList()
+		result := p.paramList()
+		functype0(t, nil, params, result)
+
+	case interfaceTag:
+		t = p.newtyp(TINTER)
+		if p.int() != 0 {
+			Fatalf("unexpected embedded interface")
+		}
+		tointerface0(t, p.methodList())
+
+	case mapTag:
+		t = p.newtyp(TMAP)
+		t.Down = p.typ() // key
+		t.Type = p.typ() // val
+
+	case chanTag:
+		t = p.newtyp(TCHAN)
+		t.Chan = uint8(p.int())
+		t.Type = p.typ()
+
+	default:
+		Fatalf("unexpected type (tag = %d)", i)
+	}
+
+	if t == nil {
+		Fatalf("nil type (type tag = %d)", i)
+	}
+
+	return t
+}
+
+func (p *importer) qualifiedName() *Sym {
+	name := p.string()
+	pkg := p.pkg()
+	return pkg.Lookup(name)
+}
+
+// go.y:hidden_structdcl_list
+func (p *importer) fieldList() *NodeList {
+	i := p.int()
+	if i == 0 {
+		return nil
+	}
+	n := list1(p.field())
+	for i--; i > 0; i-- {
+		n = list(n, p.field())
+	}
+	return n
+}
+
+// go.y:hidden_structdcl
+func (p *importer) field() *Node {
+	sym := p.fieldName()
+	typ := p.typ()
+	note := p.note()
+
+	var n *Node
+	if sym.Name != "" {
+		n = Nod(ODCLFIELD, newname(sym), typenod(typ))
+	} else {
+		// anonymous field - typ must be T or *T and T must be a type name
+		s := typ.Sym
+		if s == nil && Isptr[typ.Etype] {
+			s = typ.Type.Sym // deref
+		}
+		pkg := importpkg
+		if sym != nil {
+			pkg = sym.Pkg
+		}
+		n = embedded(s, pkg)
+		n.Right = typenod(typ)
+	}
+	n.SetVal(note)
+
+	return n
+}
+
+func (p *importer) note() (v Val) {
+	if s := p.string(); s != "" {
+		v.U = s
+	}
+	return
+}
+
+// go.y:hidden_interfacedcl_list
+func (p *importer) methodList() *NodeList {
+	i := p.int()
+	if i == 0 {
+		return nil
+	}
+	n := list1(p.method())
+	for i--; i > 0; i-- {
+		n = list(n, p.method())
+	}
+	return n
+}
+
+// go.y:hidden_interfacedcl
+func (p *importer) method() *Node {
+	sym := p.fieldName()
+	params := p.paramList()
+	result := p.paramList()
+	return Nod(ODCLFIELD, newname(sym), typenod(functype(fakethis(), params, result)))
+}
+
+// go.y:sym,hidden_importsym
+func (p *importer) fieldName() *Sym {
+	name := p.string()
+	pkg := localpkg
+	if name == "_" {
+		// During imports, unqualified non-exported identifiers are from builtinpkg
+		// (see go.y:sym). The binary exporter only exports blank as a non-exported
+		// identifier without qualification.
+		pkg = builtinpkg
+	} else if name == "?" || name != "" && !exportname(name) {
+		if name == "?" {
+			name = ""
+		}
+		pkg = p.pkg()
+	}
+	return pkg.Lookup(name)
+}
+
+// go.y:ohidden_funarg_list
+func (p *importer) paramList() *NodeList {
+	i := p.int()
+	if i == 0 {
+		return nil
+	}
+	// negative length indicates unnamed parameters
+	named := true
+	if i < 0 {
+		i = -i
+		named = false
+	}
+	// i > 0
+	n := list1(p.param(named))
+	i--
+	for ; i > 0; i-- {
+		n = list(n, p.param(named))
+	}
+	return n
+}
+
+// go.y:hidden_funarg
+func (p *importer) param(named bool) *Node {
+	typ := p.typ()
+
+	isddd := false
+	if typ.Etype == T_old_DARRAY {
+		// T_old_DARRAY indicates ... type
+		typ.Etype = TARRAY
+		isddd = true
+	}
+
+	n := Nod(ODCLFIELD, nil, typenod(typ))
+	n.Isddd = isddd
+
+	if named {
+		name := p.string()
+		if name == "" {
+			Fatalf("expected named parameter")
+		}
+		// The parameter package doesn't matter; it's never consulted.
+		// We use the builtinpkg per go.y:sym (line 1181).
+		n.Left = newname(builtinpkg.Lookup(name))
+	}
+
+	// TODO(gri) This is compiler-specific (escape info).
+	// Move into compiler-specific section eventually?
+	n.SetVal(p.note())
+
+	return n
+}
+
+func (p *importer) value(typ *Type) (x Val) {
+	switch tag := p.tagOrIndex(); tag {
+	case falseTag:
+		x.U = false
+	case trueTag:
+		x.U = true
+	case int64Tag:
+		u := new(Mpint)
+		Mpmovecfix(u, p.int64())
+		u.Rune = typ == idealrune
+		x.U = u
+	case floatTag:
+		f := newMpflt()
+		p.float(f)
+		if typ == idealint || Isint[typ.Etype] {
+			// uncommon case: large int encoded as float
+			u := new(Mpint)
+			mpmovefltfix(u, f)
+			x.U = u
+			break
+		}
+		x.U = f
+	case complexTag:
+		u := new(Mpcplx)
+		p.float(&u.Real)
+		p.float(&u.Imag)
+		x.U = u
+	case stringTag:
+		x.U = p.string()
+	default:
+		Fatalf("unexpected value tag %d", tag)
+	}
+
+	// verify ideal type
+	if isideal(typ) && untype(x.Ctype()) != typ {
+		Fatalf("value %v and type %v don't match", x, typ)
+	}
+
+	return
+}
+
+func (p *importer) float(x *Mpflt) {
+	sign := p.int()
+	if sign == 0 {
+		Mpmovecflt(x, 0)
+		return
+	}
+
+	exp := p.int()
+	mant := new(big.Int).SetBytes([]byte(p.string()))
+
+	m := x.Val.SetInt(mant)
+	m.SetMantExp(m, exp-mant.BitLen())
+	if sign < 0 {
+		m.Neg(m)
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Inlined function bodies
+
+func (p *importer) body() {
+	p.int()
+	p.block()
+}
+
+func (p *importer) block() {
+	for i := p.int(); i > 0; i-- {
+		p.stmt()
+	}
+}
+
+func (p *importer) stmt() {
+	// TODO(gri) do something sensible here
+	p.string()
+}
+
+// ----------------------------------------------------------------------------
+// Low-level decoders
+
+func (p *importer) tagOrIndex() int {
+	if p.debugFormat {
+		p.marker('t')
+	}
+
+	return int(p.rawInt64())
+}
+
+func (p *importer) int() int {
+	x := p.int64()
+	if int64(int(x)) != x {
+		Fatalf("exported integer too large")
+	}
+	return int(x)
+}
+
+func (p *importer) int64() int64 {
+	if p.debugFormat {
+		p.marker('i')
+	}
+
+	return p.rawInt64()
+}
+
+func (p *importer) string() string {
+	if p.debugFormat {
+		p.marker('s')
+	}
+
+	if n := int(p.rawInt64()); n > 0 {
+		if cap(p.buf) < n {
+			p.buf = make([]byte, n)
+		} else {
+			p.buf = p.buf[:n]
+		}
+		for i := 0; i < n; i++ {
+			p.buf[i] = p.byte()
+		}
+		return string(p.buf)
+	}
+
+	return ""
+}
+
+func (p *importer) marker(want byte) {
+	if got := p.byte(); got != want {
+		Fatalf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read)
+	}
+
+	pos := p.read
+	if n := int(p.rawInt64()); n != pos {
+		Fatalf("incorrect position: got %d; want %d", n, pos)
+	}
+}
+
+// rawInt64 should only be used by low-level decoders
+func (p *importer) rawInt64() int64 {
+	i, err := binary.ReadVarint(p)
+	if err != nil {
+		Fatalf("read error: %v", err)
+	}
+	return i
+}
+
+// needed for binary.ReadVarint in rawInt64
+func (p *importer) ReadByte() (byte, error) {
+	return p.byte(), nil
+}
+
+// byte is the bottleneck interface for reading from p.in.
+// It unescapes '|' 'S' to '$' and '|' '|' to '|'.
+func (p *importer) byte() byte {
+	c := obj.Bgetc(p.in)
+	p.read++
+	if c < 0 {
+		Fatalf("read error")
+	}
+	if c == '|' {
+		c = obj.Bgetc(p.in)
+		p.read++
+		if c < 0 {
+			Fatalf("read error")
+		}
+		switch c {
+		case 'S':
+			c = '$'
+		case '|':
+			// nothing to do
+		default:
+			Fatalf("unexpected escape sequence in export data")
+		}
+	}
+	return byte(c)
+}
diff --git a/src/cmd/compile/internal/gc/builtin.go b/src/cmd/compile/internal/gc/builtin.go
index f09dd56..4199fb3 100644
--- a/src/cmd/compile/internal/gc/builtin.go
+++ b/src/cmd/compile/internal/gc/builtin.go
@@ -4,7 +4,6 @@ package gc
 
 const runtimeimport = "" +
 	"package runtime\n" +
-	"import runtime \"runtime\"\n" +
 	"func @\"\".newobject (@\"\".typ·2 *byte) (? *any)\n" +
 	"func @\"\".panicindex ()\n" +
 	"func @\"\".panicslice ()\n" +
@@ -87,7 +86,7 @@ const runtimeimport = "" +
 	"func @\"\".chanrecv2 (@\"\".chanType·2 *byte, @\"\".hchan·3 <-chan any, @\"\".elem·4 *any) (? bool)\n" +
 	"func @\"\".chansend1 (@\"\".chanType·1 *byte, @\"\".hchan·2 chan<- any, @\"\".elem·3 *any)\n" +
 	"func @\"\".closechan (@\"\".hchan·1 any)\n" +
-	"var @\"\".writeBarrierEnabled bool\n" +
+	"var @\"\".writeBarrier struct { @\"\".enabled bool; @\"\".needed bool; @\"\".cgo bool }\n" +
 	"func @\"\".writebarrierptr (@\"\".dst·1 *any, @\"\".src·2 any)\n" +
 	"func @\"\".writebarrierstring (@\"\".dst·1 *any, @\"\".src·2 any)\n" +
 	"func @\"\".writebarrierslice (@\"\".dst·1 *any, @\"\".src·2 any)\n" +
@@ -155,12 +154,13 @@ const runtimeimport = "" +
 	"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" +
 	"\n" +
 	"$$\n"
 
 const unsafeimport = "" +
 	"package unsafe\n" +
-	"import runtime \"runtime\"\n" +
 	"type @\"\".Pointer uintptr\n" +
 	"func @\"\".Offsetof (? any) (? uintptr)\n" +
 	"func @\"\".Sizeof (? any) (? uintptr)\n" +
diff --git a/src/cmd/compile/internal/gc/builtin/runtime.go b/src/cmd/compile/internal/gc/builtin/runtime.go
index 6210f10..a50fc2e 100644
--- a/src/cmd/compile/internal/gc/builtin/runtime.go
+++ b/src/cmd/compile/internal/gc/builtin/runtime.go
@@ -108,7 +108,11 @@ func chanrecv2(chanType *byte, hchan <-chan any, elem *any) bool
 func chansend1(chanType *byte, hchan chan<- any, elem *any)
 func closechan(hchan any)
 
-var writeBarrierEnabled bool
+var writeBarrier struct {
+	enabled bool
+	needed  bool
+	cgo     bool
+}
 
 func writebarrierptr(dst *any, src any)
 func writebarrierstring(dst *any, src any)
@@ -193,3 +197,7 @@ func raceread(uintptr)
 func racewrite(uintptr)
 func racereadrange(addr, size uintptr)
 func racewriterange(addr, size uintptr)
+
+// memory sanitizer
+func msanread(addr, size uintptr)
+func msanwrite(addr, size uintptr)
diff --git a/src/cmd/compile/internal/gc/bv.go b/src/cmd/compile/internal/gc/bv.go
index 2b988e6..c19ec81 100644
--- a/src/cmd/compile/internal/gc/bv.go
+++ b/src/cmd/compile/internal/gc/bv.go
@@ -56,7 +56,7 @@ func (b *bulkBvec) next() Bvec {
 	return out
 }
 
-/* difference */
+// difference
 func bvandnot(dst Bvec, src1 Bvec, src2 Bvec) {
 	for i, x := range src1.b {
 		dst.b[i] = x &^ src2.b[i]
@@ -65,7 +65,7 @@ func bvandnot(dst Bvec, src1 Bvec, src2 Bvec) {
 
 func bvcmp(bv1 Bvec, bv2 Bvec) int {
 	if bv1.n != bv2.n {
-		Fatal("bvequal: lengths %d and %d are not equal", bv1.n, bv2.n)
+		Fatalf("bvequal: lengths %d and %d are not equal", bv1.n, bv2.n)
 	}
 	for i, x := range bv1.b {
 		if x != bv2.b[i] {
@@ -98,7 +98,7 @@ func bvconcat(src1 Bvec, src2 Bvec) Bvec {
 
 func bvget(bv Bvec, i int32) int {
 	if i < 0 || i >= bv.n {
-		Fatal("bvget: index %d is out of bounds with length %d\n", i, bv.n)
+		Fatalf("bvget: index %d is out of bounds with length %d\n", i, bv.n)
 	}
 	return int((bv.b[i>>WORDSHIFT] >> uint(i&WORDMASK)) & 1)
 }
@@ -151,14 +151,14 @@ func bvnot(bv Bvec) {
 	}
 }
 
-/* union */
+// union
 func bvor(dst Bvec, src1 Bvec, src2 Bvec) {
 	for i, x := range src1.b {
 		dst.b[i] = x | src2.b[i]
 	}
 }
 
-/* intersection */
+// intersection
 func bvand(dst Bvec, src1 Bvec, src2 Bvec) {
 	for i, x := range src1.b {
 		dst.b[i] = x & src2.b[i]
@@ -174,7 +174,7 @@ func bvprint(bv Bvec) {
 
 func bvreset(bv Bvec, i int32) {
 	if i < 0 || i >= bv.n {
-		Fatal("bvreset: index %d is out of bounds with length %d\n", i, bv.n)
+		Fatalf("bvreset: index %d is out of bounds with length %d\n", i, bv.n)
 	}
 	mask := uint32(^(1 << uint(i%WORDBITS)))
 	bv.b[i/WORDBITS] &= mask
@@ -188,7 +188,7 @@ func bvresetall(bv Bvec) {
 
 func bvset(bv Bvec, i int32) {
 	if i < 0 || i >= bv.n {
-		Fatal("bvset: index %d is out of bounds with length %d\n", i, bv.n)
+		Fatalf("bvset: index %d is out of bounds with length %d\n", i, bv.n)
 	}
 	mask := uint32(1 << uint(i%WORDBITS))
 	bv.b[i/WORDBITS] |= mask
diff --git a/src/cmd/compile/internal/gc/cgen.go b/src/cmd/compile/internal/gc/cgen.go
index b6a3e5b..6456240 100644
--- a/src/cmd/compile/internal/gc/cgen.go
+++ b/src/cmd/compile/internal/gc/cgen.go
@@ -6,15 +6,14 @@ package gc
 
 import (
 	"cmd/internal/obj"
+	"cmd/internal/obj/ppc64"
 	"fmt"
 )
 
-/*
- * generate:
- *	res = n;
- * simplifies and calls Thearch.Gmove.
- * if wb is true, need to emit write barriers.
- */
+// generate:
+//	res = n;
+// simplifies and calls Thearch.Gmove.
+// if wb is true, need to emit write barriers.
 func Cgen(n, res *Node) {
 	cgen_wb(n, res, false)
 }
@@ -34,7 +33,7 @@ func cgen_wb(n, res *Node, wb bool) {
 	}
 
 	if res == nil || res.Type == nil {
-		Fatal("cgen: res nil")
+		Fatalf("cgen: res nil")
 	}
 
 	for n.Op == OCONVNOP {
@@ -68,7 +67,7 @@ func cgen_wb(n, res *Node, wb bool) {
 
 	if n.Ullman >= UINF {
 		if n.Op == OINDREG {
-			Fatal("cgen: this is going to miscompile")
+			Fatalf("cgen: this is going to miscompile")
 		}
 		if res.Ullman >= UINF {
 			var n1 Node
@@ -81,7 +80,7 @@ func cgen_wb(n, res *Node, wb bool) {
 
 	if Isfat(n.Type) {
 		if n.Type.Width < 0 {
-			Fatal("forgot to compute width for %v", n.Type)
+			Fatalf("forgot to compute width for %v", n.Type)
 		}
 		sgen_wb(n, res, n.Type.Width, wb)
 		return
@@ -103,7 +102,7 @@ func cgen_wb(n, res *Node, wb bool) {
 			if n1.Ullman > res.Ullman {
 				Dump("n1", &n1)
 				Dump("res", res)
-				Fatal("loop in cgen")
+				Fatalf("loop in cgen")
 			}
 
 			cgen_wb(&n1, res, wb)
@@ -190,8 +189,8 @@ func cgen_wb(n, res *Node, wb bool) {
 	}
 
 	if wb {
-		if int(Simtype[res.Type.Etype]) != Tptr {
-			Fatal("cgen_wb of type %v", res.Type)
+		if Simtype[res.Type.Etype] != Tptr {
+			Fatalf("cgen_wb of type %v", res.Type)
 		}
 		if n.Ullman >= UINF {
 			var n1 Node
@@ -253,7 +252,7 @@ func cgen_wb(n, res *Node, wb bool) {
 		return
 	}
 
-	if Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9' {
+	if Ctxt.Arch.Thechar == '0' || Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9' {
 		// if both are addressable, move
 		if n.Addable {
 			if n.Op == OREGISTER || res.Op == OREGISTER {
@@ -362,7 +361,7 @@ func cgen_wb(n, res *Node, wb bool) {
 	default:
 		Dump("cgen", n)
 		Dump("cgen-res", res)
-		Fatal("cgen: unknown op %v", Nconv(n, obj.FmtShort|obj.FmtSign))
+		Fatalf("cgen: unknown op %v", Nconv(n, obj.FmtShort|obj.FmtSign))
 
 	case OOROR, OANDAND,
 		OEQ, ONE,
@@ -397,7 +396,7 @@ func cgen_wb(n, res *Node, wb bool) {
 			goto sbop
 		}
 
-		a := Thearch.Optoas(int(n.Op), nl.Type)
+		a := Thearch.Optoas(n.Op, nl.Type)
 		// unary
 		var n1 Node
 		Regalloc(&n1, nl.Type, res)
@@ -434,15 +433,15 @@ func cgen_wb(n, res *Node, wb bool) {
 		OXOR,
 		OADD,
 		OMUL:
-		if n.Op == OMUL && Thearch.Cgen_bmul != nil && Thearch.Cgen_bmul(int(n.Op), nl, nr, res) {
+		if n.Op == OMUL && Thearch.Cgen_bmul != nil && Thearch.Cgen_bmul(n.Op, nl, nr, res) {
 			break
 		}
-		a = Thearch.Optoas(int(n.Op), nl.Type)
+		a = Thearch.Optoas(n.Op, nl.Type)
 		goto sbop
 
 		// asymmetric binary
 	case OSUB:
-		a = Thearch.Optoas(int(n.Op), nl.Type)
+		a = Thearch.Optoas(n.Op, nl.Type)
 		goto abop
 
 	case OHMUL:
@@ -593,7 +592,7 @@ func cgen_wb(n, res *Node, wb bool) {
 			break
 		}
 
-		Fatal("cgen: OLEN: unknown type %v", Tconv(nl.Type, obj.FmtLong))
+		Fatalf("cgen: OLEN: unknown type %v", Tconv(nl.Type, obj.FmtLong))
 
 	case OCAP:
 		if Istype(nl.Type, TCHAN) {
@@ -631,7 +630,7 @@ func cgen_wb(n, res *Node, wb bool) {
 			break
 		}
 
-		Fatal("cgen: OCAP: unknown type %v", Tconv(nl.Type, obj.FmtLong))
+		Fatalf("cgen: OCAP: unknown type %v", Tconv(nl.Type, obj.FmtLong))
 
 	case OADDR:
 		if n.Bounded { // let race detector avoid nil checks
@@ -656,7 +655,7 @@ func cgen_wb(n, res *Node, wb bool) {
 
 	case OMOD, ODIV:
 		if Isfloat[n.Type.Etype] || Thearch.Dodiv == nil {
-			a = Thearch.Optoas(int(n.Op), nl.Type)
+			a = Thearch.Optoas(n.Op, nl.Type)
 			goto abop
 		}
 
@@ -664,7 +663,7 @@ func cgen_wb(n, res *Node, wb bool) {
 			var n1 Node
 			Regalloc(&n1, nl.Type, res)
 			Cgen(nl, &n1)
-			cgen_div(int(n.Op), &n1, nr, res)
+			cgen_div(n.Op, &n1, nr, res)
 			Regfree(&n1)
 		} else {
 			var n2 Node
@@ -675,39 +674,35 @@ func cgen_wb(n, res *Node, wb bool) {
 				n2 = *nr
 			}
 
-			cgen_div(int(n.Op), nl, &n2, res)
+			cgen_div(n.Op, nl, &n2, res)
 			if n2.Op != OLITERAL {
 				Regfree(&n2)
 			}
 		}
 
 	case OLSH, ORSH, OLROT:
-		Thearch.Cgen_shift(int(n.Op), n.Bounded, nl, nr, res)
+		Thearch.Cgen_shift(n.Op, n.Bounded, nl, nr, res)
 	}
 
 	return
 
-	/*
-	 * put simplest on right - we'll generate into left
-	 * and then adjust it using the computation of right.
-	 * constants and variables have the same ullman
-	 * count, so look for constants specially.
-	 *
-	 * an integer constant we can use as an immediate
-	 * is simpler than a variable - we can use the immediate
-	 * in the adjustment instruction directly - so it goes
-	 * on the right.
-	 *
-	 * other constants, like big integers or floating point
-	 * constants, require a mov into a register, so those
-	 * might as well go on the left, so we can reuse that
-	 * register for the computation.
-	 */
+	// put simplest on right - we'll generate into left
+	// and then adjust it using the computation of right.
+	// constants and variables have the same ullman
+	// count, so look for constants specially.
+	//
+	// an integer constant we can use as an immediate
+	// is simpler than a variable - we can use the immediate
+	// in the adjustment instruction directly - so it goes
+	// on the right.
+	//
+	// other constants, like big integers or floating point
+	// constants, require a mov into a register, so those
+	// might as well go on the left, so we can reuse that
+	// register for the computation.
 sbop: // symmetric binary
 	if nl.Ullman < nr.Ullman || (nl.Ullman == nr.Ullman && (Smallintconst(nl) || (nr.Op == OLITERAL && !Smallintconst(nr)))) {
-		r := nl
-		nl = nr
-		nr = r
+		nl, nr = nr, nl
 	}
 
 abop: // asymmetric binary
@@ -757,14 +752,14 @@ abop: // asymmetric binary
 		Regalloc(&n1, nl.Type, res)
 		Cgen(nl, &n1)
 
-		if Smallintconst(nr) && 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' { // TODO(rsc): Check opcode for arm
 			n2 = *nr
 		} else {
 			Regalloc(&n2, nr.Type, nil)
 			Cgen(nr, &n2)
 		}
 	} else {
-		if Smallintconst(nr) && 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' { // TODO(rsc): Check opcode for arm
 			n2 = *nr
 		} else {
 			Regalloc(&n2, nr.Type, res)
@@ -785,8 +780,13 @@ abop: // asymmetric binary
 var sys_wbptr *Node
 
 func cgen_wbptr(n, res *Node) {
-	if Curfn != nil && Curfn.Func.Nowritebarrier {
-		Yyerror("write barrier prohibited")
+	if Curfn != nil {
+		if Curfn.Func.Nowritebarrier {
+			Yyerror("write barrier prohibited")
+		}
+		if Curfn.Func.WBLineno == 0 {
+			Curfn.Func.WBLineno = lineno
+		}
 	}
 	if Debug_wb > 0 {
 		Warn("write barrier")
@@ -801,7 +801,9 @@ func cgen_wbptr(n, res *Node) {
 		Cgenr(n, &src, nil)
 	}
 
-	wbEnabled := syslook("writeBarrierEnabled", 0)
+	wbVar := syslook("writeBarrier", 0)
+	wbEnabled := Nod(ODOT, wbVar, newname(wbVar.Type.Type.Sym))
+	wbEnabled = typecheck(&wbEnabled, Erv)
 	pbr := Thearch.Ginscmp(ONE, Types[TUINT8], wbEnabled, Nodintconst(0), -1)
 	Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &src, &dst)
 	pjmp := Gbranch(obj.AJMP, nil, 0)
@@ -812,10 +814,7 @@ func cgen_wbptr(n, res *Node) {
 	a := &p.To
 	a.Type = obj.TYPE_MEM
 	a.Reg = int16(Thearch.REGSP)
-	a.Offset = 0
-	if HasLinkRegister() {
-		a.Offset += int64(Widthptr)
-	}
+	a.Offset = Ctxt.FixedFrameSize()
 	p2 := Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &src, nil)
 	p2.To = p.To
 	p2.To.Offset += int64(Widthptr)
@@ -831,8 +830,13 @@ func cgen_wbptr(n, res *Node) {
 }
 
 func cgen_wbfat(n, res *Node) {
-	if Curfn != nil && Curfn.Func.Nowritebarrier {
-		Yyerror("write barrier prohibited")
+	if Curfn != nil {
+		if Curfn.Func.Nowritebarrier {
+			Yyerror("write barrier prohibited")
+		}
+		if Curfn.Func.WBLineno == 0 {
+			Curfn.Func.WBLineno = lineno
+		}
 	}
 	if Debug_wb > 0 {
 		Warn("write barrier")
@@ -851,10 +855,7 @@ func cgen_wbfat(n, res *Node) {
 	a := &p.To
 	a.Type = obj.TYPE_MEM
 	a.Reg = int16(Thearch.REGSP)
-	a.Offset = 0
-	if HasLinkRegister() {
-		a.Offset += int64(Widthptr)
-	}
+	a.Offset = Ctxt.FixedFrameSize()
 	if needType {
 		a.Offset += int64(Widthptr)
 	}
@@ -917,18 +918,16 @@ func Mfree(n *Node) {
 	}
 }
 
-/*
- * allocate a register (reusing res if possible) and generate
- *  a = n
- * The caller must call Regfree(a).
- */
+// allocate a register (reusing res if possible) and generate
+//	a = n
+// The caller must call Regfree(a).
 func Cgenr(n *Node, a *Node, res *Node) {
 	if Debug['g'] != 0 {
 		Dump("cgenr-n", n)
 	}
 
 	if Isfat(n.Type) {
-		Fatal("cgenr on fat node")
+		Fatalf("cgenr on fat node")
 	}
 
 	if n.Addable {
@@ -957,12 +956,10 @@ func Cgenr(n *Node, a *Node, res *Node) {
 	}
 }
 
-/*
- * allocate a register (reusing res if possible) and generate
- * a = &n
- * The caller must call Regfree(a).
- * The generated code checks that the result is not nil.
- */
+// allocate a register (reusing res if possible) and generate
+//	a = &n
+// The caller must call Regfree(a).
+// The generated code checks that the result is not nil.
 func Agenr(n *Node, a *Node, res *Node) {
 	if Debug['g'] != 0 {
 		Dump("\nagenr-n", n)
@@ -1034,7 +1031,7 @@ func Agenr(n *Node, a *Node, res *Node) {
 			// constant index
 			if Isconst(nr, CTINT) {
 				if Isconst(nl, CTSTR) {
-					Fatal("constant string constant index")
+					Fatalf("constant string constant index")
 				}
 				v := uint64(Mpgetfix(nr.Val().U.(*Mpint)))
 				var n2 Node
@@ -1186,7 +1183,7 @@ func Agenr(n *Node, a *Node, res *Node) {
 			// constant index
 			if Isconst(nr, CTINT) {
 				if Isconst(nl, CTSTR) {
-					Fatal("constant string constant index") // front end should handle
+					Fatalf("constant string constant index") // front end should handle
 				}
 				v := uint64(Mpgetfix(nr.Val().U.(*Mpint)))
 				if Isslice(nl.Type) || nl.Type.Etype == TSTRING {
@@ -1376,7 +1373,7 @@ func Agenr(n *Node, a *Node, res *Node) {
 	index:
 		if Isconst(nr, CTINT) {
 			if Isconst(nl, CTSTR) {
-				Fatal("constant string constant index") // front end should handle
+				Fatalf("constant string constant index") // front end should handle
 			}
 			v := uint64(Mpgetfix(nr.Val().U.(*Mpint)))
 			if Isslice(nl.Type) || nl.Type.Etype == TSTRING {
@@ -1476,11 +1473,9 @@ func log2(n uint64) int {
 	return x
 }
 
-/*
- * generate:
- *	res = &n;
- * The generated code checks that the result is not nil.
- */
+// generate:
+//	res = &n;
+// The generated code checks that the result is not nil.
 func Agen(n *Node, res *Node) {
 	if Debug['g'] != 0 {
 		Dump("\nagen-res", res)
@@ -1529,7 +1524,7 @@ func Agen(n *Node, res *Node) {
 
 	if n.Addable {
 		if n.Op == OREGISTER {
-			Fatal("agen OREGISTER")
+			Fatalf("agen OREGISTER")
 		}
 		var n1 Node
 		n1.Op = OADDR
@@ -1546,7 +1541,7 @@ func Agen(n *Node, res *Node) {
 
 	switch n.Op {
 	default:
-		Fatal("agen: unknown op %v", Nconv(n, obj.FmtShort|obj.FmtSign))
+		Fatalf("agen: unknown op %v", Nconv(n, obj.FmtShort|obj.FmtSign))
 
 	case OCALLMETH:
 		cgen_callmeth(n, 0)
@@ -1576,13 +1571,13 @@ func Agen(n *Node, res *Node) {
 		// should only get here with names in this func.
 		if n.Name.Funcdepth > 0 && n.Name.Funcdepth != Funcdepth {
 			Dump("bad agen", n)
-			Fatal("agen: bad ONAME funcdepth %d != %d", n.Name.Funcdepth, Funcdepth)
+			Fatalf("agen: bad ONAME funcdepth %d != %d", n.Name.Funcdepth, Funcdepth)
 		}
 
 		// should only get here for heap vars or paramref
 		if n.Class&PHEAP == 0 && n.Class != PPARAMREF {
 			Dump("bad agen", n)
-			Fatal("agen: bad ONAME class %#x", n.Class)
+			Fatalf("agen: bad ONAME class %#x", n.Class)
 		}
 
 		Cgen(n.Name.Heapaddr, res)
@@ -1688,10 +1683,7 @@ func Igen(n *Node, a *Node, res *Node) {
 		a.Op = OINDREG
 		a.Reg = int16(Thearch.REGSP)
 		a.Addable = true
-		a.Xoffset = fp.Width
-		if HasLinkRegister() {
-			a.Xoffset += int64(Ctxt.Arch.Ptrsize)
-		}
+		a.Xoffset = fp.Width + Ctxt.FixedFrameSize()
 		a.Type = n.Type
 		return
 
@@ -1800,7 +1792,7 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
 	}
 
 	if n.Type.Etype != TBOOL {
-		Fatal("bgen: bad type %v for %v", n.Type, Oconv(int(n.Op), 0))
+		Fatalf("bgen: bad type %v for %v", n.Type, Oconv(int(n.Op), 0))
 	}
 
 	for n.Op == OCONVNOP {
@@ -1840,8 +1832,8 @@ 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.
 			switch Ctxt.Arch.Thechar {
-			case '5', '7', '9':
-				Fatal("genval 5g, 7g, 9g ONAMES not fully implemented")
+			case '0', '5', '7', '9':
+				Fatalf("genval 0g, 5g, 7g, 9g ONAMES not fully implemented")
 			}
 			Cgen(n, res)
 			if !wantTrue {
@@ -1850,7 +1842,7 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
 			return
 		}
 
-		if n.Addable && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' {
+		if n.Addable && Ctxt.Arch.Thechar != '0' && Ctxt.Arch.Thechar != '5' && Ctxt.Arch.Thechar != '7' && Ctxt.Arch.Thechar != '9' {
 			// no need for a temporary
 			bgenNonZero(n, nil, wantTrue, likely, to)
 			return
@@ -1865,7 +1857,7 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
 	case OLITERAL:
 		// n is a constant.
 		if !Isconst(n, CTBOOL) {
-			Fatal("bgen: non-bool const %v\n", Nconv(n, obj.FmtLong))
+			Fatalf("bgen: non-bool const %v\n", Nconv(n, obj.FmtLong))
 		}
 		if genval {
 			Cgen(Nodbool(wantTrue == n.Val().U.(bool)), res)
@@ -1923,7 +1915,7 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
 	// n.Op is one of OEQ, ONE, OLT, OGT, OLE, OGE
 	nl := n.Left
 	nr := n.Right
-	a := int(n.Op)
+	op := n.Op
 
 	if !wantTrue {
 		if Isfloat[nr.Type.Etype] {
@@ -1946,19 +1938,19 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
 			return
 		}
 
-		a = Brcom(a)
+		op = Brcom(op)
 	}
 	wantTrue = true
 
 	// make simplest on right
 	if nl.Op == OLITERAL || (nl.Ullman < nr.Ullman && nl.Ullman < UINF) {
-		a = Brrev(a)
+		op = Brrev(op)
 		nl, nr = nr, nl
 	}
 
 	if Isslice(nl.Type) || Isinter(nl.Type) {
 		// front end should only leave cmp to literal nil
-		if (a != OEQ && a != ONE) || nr.Op != OLITERAL {
+		if (op != OEQ && op != ONE) || nr.Op != OLITERAL {
 			if Isslice(nl.Type) {
 				Yyerror("illegal slice comparison")
 			} else {
@@ -1977,13 +1969,13 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
 		Regalloc(&tmp, ptr.Type, &ptr)
 		Cgen(&ptr, &tmp)
 		Regfree(&ptr)
-		bgenNonZero(&tmp, res, a == OEQ != wantTrue, likely, to)
+		bgenNonZero(&tmp, res, op == OEQ != wantTrue, likely, to)
 		Regfree(&tmp)
 		return
 	}
 
 	if Iscomplex[nl.Type.Etype] {
-		complexbool(a, nl, nr, res, wantTrue, likely, to)
+		complexbool(op, nl, nr, res, wantTrue, likely, to)
 		return
 	}
 
@@ -1999,7 +1991,7 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
 		if !nr.Addable {
 			nr = CgenTemp(nr)
 		}
-		Thearch.Cmp64(nl, nr, a, likely, to)
+		Thearch.Cmp64(nl, nr, op, likely, to)
 		return
 	}
 
@@ -2034,9 +2026,9 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
 		Cgen(nl, &n1)
 		nl = &n1
 
-		if Smallintconst(nr) && Ctxt.Arch.Thechar != '9' {
+		if Smallintconst(nr) && Ctxt.Arch.Thechar != '0' && Ctxt.Arch.Thechar != '9' {
 			Thearch.Gins(Thearch.Optoas(OCMP, nr.Type), nl, nr)
-			bins(nr.Type, res, a, likely, to)
+			bins(nr.Type, res, op, likely, to)
 			return
 		}
 
@@ -2054,9 +2046,16 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
 	l, r := nl, nr
 
 	// On x86, only < and <= work right with NaN; reverse if needed
-	if Ctxt.Arch.Thechar == '6' && Isfloat[nl.Type.Etype] && (a == OGT || a == OGE) {
+	if Ctxt.Arch.Thechar == '6' && Isfloat[nl.Type.Etype] && (op == OGT || op == OGE) {
 		l, r = r, l
-		a = Brrev(a)
+		op = Brrev(op)
+	}
+
+	// MIPS does not have CMP instruction
+	if Ctxt.Arch.Thechar == '0' {
+		p := Thearch.Ginscmp(op, nr.Type, l, r, likely)
+		Patch(p, to)
+		return
 	}
 
 	// Do the comparison.
@@ -2068,15 +2067,15 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
 		switch Ctxt.Arch.Thechar {
 		case '5':
 			if genval {
-				Fatal("genval 5g Isfloat special cases not implemented")
+				Fatalf("genval 5g Isfloat special cases not implemented")
 			}
 			switch n.Op {
 			case ONE:
 				Patch(Gbranch(Thearch.Optoas(OPS, nr.Type), nr.Type, likely), to)
-				Patch(Gbranch(Thearch.Optoas(a, nr.Type), nr.Type, likely), to)
+				Patch(Gbranch(Thearch.Optoas(op, nr.Type), nr.Type, likely), to)
 			default:
 				p := Gbranch(Thearch.Optoas(OPS, nr.Type), nr.Type, -likely)
-				Patch(Gbranch(Thearch.Optoas(a, nr.Type), nr.Type, likely), to)
+				Patch(Gbranch(Thearch.Optoas(op, nr.Type), nr.Type, likely), to)
 				Patch(p, Pc)
 			}
 			return
@@ -2116,18 +2115,18 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
 			}
 		case '7', '9':
 			if genval {
-				Fatal("genval 7g, 9g Isfloat special cases not implemented")
+				Fatalf("genval 7g, 9g Isfloat special cases not implemented")
 			}
 			switch n.Op {
 			// On arm64 and ppc64, <= and >= mishandle NaN. Must decompose into < or > and =.
 			// TODO(josh): Convert a <= b to b > a instead?
 			case OLE, OGE:
-				if a == OLE {
-					a = OLT
+				if op == OLE {
+					op = OLT
 				} else {
-					a = OGT
+					op = OGT
 				}
-				Patch(Gbranch(Thearch.Optoas(a, nr.Type), nr.Type, likely), to)
+				Patch(Gbranch(Thearch.Optoas(op, nr.Type), nr.Type, likely), to)
 				Patch(Gbranch(Thearch.Optoas(OEQ, nr.Type), nr.Type, likely), to)
 				return
 			}
@@ -2135,26 +2134,35 @@ func bgenx(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
 	}
 
 	// Not a special case. Insert the conditional jump or value gen.
-	bins(nr.Type, res, a, likely, to)
+	bins(nr.Type, res, op, likely, to)
 }
 
 func bgenNonZero(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
 	// TODO: Optimize on systems that can compare to zero easily.
-	a := ONE
+	var op Op = ONE
 	if !wantTrue {
-		a = OEQ
+		op = OEQ
+	}
+
+	// MIPS does not have CMP instruction
+	if Thearch.Thechar == '0' {
+		p := Gbranch(Thearch.Optoas(op, n.Type), n.Type, likely)
+		Naddr(&p.From, n)
+		Patch(p, to)
+		return
 	}
+
 	var zero Node
 	Nodconst(&zero, n.Type, 0)
 	Thearch.Gins(Thearch.Optoas(OCMP, n.Type), n, &zero)
-	bins(n.Type, res, a, likely, to)
+	bins(n.Type, res, op, likely, to)
 }
 
 // bins inserts an instruction to handle the result of a compare.
 // If res is non-nil, it inserts appropriate value generation instructions.
 // If res is nil, it inserts a branch to to.
-func bins(typ *Type, res *Node, a, likely int, to *obj.Prog) {
-	a = Thearch.Optoas(a, typ)
+func bins(typ *Type, res *Node, op Op, likely int, to *obj.Prog) {
+	a := Thearch.Optoas(op, typ)
 	if res != nil {
 		// value gen
 		Thearch.Ginsboolval(a, res)
@@ -2221,11 +2229,7 @@ func stkof(n *Node) int64 {
 		var flist Iter
 		t = Structfirst(&flist, Getoutarg(t))
 		if t != nil {
-			w := t.Width
-			if HasLinkRegister() {
-				w += int64(Ctxt.Arch.Ptrsize)
-			}
-			return w
+			return t.Width + Ctxt.FixedFrameSize()
 		}
 	}
 
@@ -2234,11 +2238,9 @@ func stkof(n *Node) int64 {
 	return -1000 // not on stack
 }
 
-/*
- * block copy:
- *	memmove(&ns, &n, w);
- * if wb is true, needs write barrier.
- */
+// block copy:
+//	memmove(&ns, &n, w);
+// if wb is true, needs write barrier.
 func sgen_wb(n *Node, ns *Node, w int64, wb bool) {
 	if Debug['g'] != 0 {
 		op := "sgen"
@@ -2251,11 +2253,11 @@ func sgen_wb(n *Node, ns *Node, w int64, wb bool) {
 	}
 
 	if n.Ullman >= UINF && ns.Ullman >= UINF {
-		Fatal("sgen UINF")
+		Fatalf("sgen UINF")
 	}
 
 	if w < 0 {
-		Fatal("sgen copy %d", w)
+		Fatalf("sgen copy %d", w)
 	}
 
 	// If copying .args, that's all the results, so record definition sites
@@ -2316,15 +2318,13 @@ func sgen_wb(n *Node, ns *Node, w int64, wb bool) {
 	Thearch.Blockcopy(n, ns, osrc, odst, w)
 }
 
-/*
- * generate:
- *	call f
- *	proc=-1	normal call but no return
- *	proc=0	normal call
- *	proc=1	goroutine run in new proc
- *	proc=2	defer call save away stack
-  *	proc=3	normal call to C pointer (not Go func value)
-*/
+// generate:
+//	call f
+//	proc=-1	normal call but no return
+//	proc=0	normal call
+//	proc=1	goroutine run in new proc
+//	proc=2	defer call save away stack
+//	proc=3	normal call to C pointer (not Go func value)
 func Ginscall(f *Node, proc int) {
 	if f.Type != nil {
 		extra := int32(0)
@@ -2336,21 +2336,45 @@ func Ginscall(f *Node, proc int) {
 
 	switch proc {
 	default:
-		Fatal("Ginscall: bad proc %d", proc)
+		Fatalf("Ginscall: bad proc %d", proc)
 
 	case 0, // normal call
 		-1: // normal call but no return
 		if f.Op == ONAME && f.Class == PFUNC {
 			if f == Deferreturn {
-				// Deferred calls will appear to be returning to
-				// the CALL deferreturn(SB) that we are about to emit.
-				// However, the stack trace code will show the line
-				// of the instruction byte before the return PC.
-				// To avoid that being an unrelated instruction,
-				// insert an actual hardware NOP that will have the right line number.
-				// This is different from obj.ANOP, which is a virtual no-op
-				// that doesn't make it into the instruction stream.
+				// Deferred calls will appear to be returning to the CALL
+				// deferreturn(SB) that we are about to emit. However, the
+				// stack scanning code will think that the instruction
+				// before the CALL is executing. To avoid the scanning
+				// code making bad assumptions (both cosmetic such as
+				// showing the wrong line number and fatal, such as being
+				// confused over whether a stack slot contains a pointer
+				// or a scalar) insert an actual hardware NOP that will
+				// have the right line number. This is different from
+				// obj.ANOP, which is a virtual no-op that doesn't make it
+				// into the instruction stream.
 				Thearch.Ginsnop()
+
+				if Thearch.Thechar == '9' {
+					// On ppc64, when compiling Go into position
+					// independent code on ppc64le we insert an
+					// instruction to reload the TOC pointer from the
+					// stack as well. See the long comment near
+					// jmpdefer in runtime/asm_ppc64.s for why.
+					// If the MOVD is not needed, insert a hardware NOP
+					// so that the same number of instructions are used
+					// on ppc64 in both shared and non-shared modes.
+					if Ctxt.Flag_shared != 0 {
+						p := Thearch.Gins(ppc64.AMOVD, nil, nil)
+						p.From.Type = obj.TYPE_MEM
+						p.From.Offset = 24
+						p.From.Reg = ppc64.REGSP
+						p.To.Type = obj.TYPE_REG
+						p.To.Reg = ppc64.REG_R2
+					} else {
+						Thearch.Ginsnop()
+					}
+				}
 			}
 
 			p := Thearch.Gins(obj.ACALL, nil, f)
@@ -2381,17 +2405,11 @@ func Ginscall(f *Node, proc int) {
 		// size of arguments at 0(SP)
 		stk.Op = OINDREG
 		stk.Reg = int16(Thearch.REGSP)
-		stk.Xoffset = 0
-		if HasLinkRegister() {
-			stk.Xoffset += int64(Ctxt.Arch.Ptrsize)
-		}
+		stk.Xoffset = Ctxt.FixedFrameSize()
 		Thearch.Ginscon(Thearch.Optoas(OAS, Types[TINT32]), int64(Argsize(f.Type)), &stk)
 
 		// FuncVal* at 8(SP)
-		stk.Xoffset = int64(Widthptr)
-		if HasLinkRegister() {
-			stk.Xoffset += int64(Ctxt.Arch.Ptrsize)
-		}
+		stk.Xoffset = int64(Widthptr) + Ctxt.FixedFrameSize()
 
 		var reg Node
 		Nodreg(&reg, Types[Tptr], Thearch.REGCALLX2)
@@ -2401,8 +2419,8 @@ func Ginscall(f *Node, proc int) {
 		if proc == 1 {
 			Ginscall(Newproc, 0)
 		} else {
-			if Hasdefer == 0 {
-				Fatal("hasdefer=0 but has defer")
+			if !hasdefer {
+				Fatalf("hasdefer=0 but has defer")
 			}
 			Ginscall(Deferproc, 0)
 		}
@@ -2416,19 +2434,17 @@ func Ginscall(f *Node, proc int) {
 	}
 }
 
-/*
- * n is call to interface method.
- * generate res = n.
- */
+// n is call to interface method.
+// generate res = n.
 func cgen_callinter(n *Node, res *Node, proc int) {
 	i := n.Left
 	if i.Op != ODOTINTER {
-		Fatal("cgen_callinter: not ODOTINTER %v", Oconv(int(i.Op), 0))
+		Fatalf("cgen_callinter: not ODOTINTER %v", Oconv(int(i.Op), 0))
 	}
 
 	f := i.Right // field
 	if f.Op != ONAME {
-		Fatal("cgen_callinter: not ONAME %v", Oconv(int(f.Op), 0))
+		Fatalf("cgen_callinter: not ONAME %v", Oconv(int(f.Op), 0))
 	}
 
 	i = i.Left // interface
@@ -2449,10 +2465,7 @@ func cgen_callinter(n *Node, res *Node, proc int) {
 
 	var nodsp Node
 	Nodindreg(&nodsp, Types[Tptr], Thearch.REGSP)
-	nodsp.Xoffset = 0
-	if HasLinkRegister() {
-		nodsp.Xoffset += int64(Ctxt.Arch.Ptrsize)
-	}
+	nodsp.Xoffset = Ctxt.FixedFrameSize()
 	if proc != 0 {
 		nodsp.Xoffset += 2 * int64(Widthptr) // leave room for size & fn
 	}
@@ -2471,7 +2484,7 @@ func cgen_callinter(n *Node, res *Node, proc int) {
 	var nodr Node
 	Regalloc(&nodr, Types[Tptr], &nodo)
 	if n.Left.Xoffset == BADWIDTH {
-		Fatal("cgen_callinter: badwidth")
+		Fatalf("cgen_callinter: badwidth")
 	}
 	Cgen_checknil(&nodo) // in case offset is huge
 	nodo.Op = OINDREG
@@ -2492,12 +2505,10 @@ func cgen_callinter(n *Node, res *Node, proc int) {
 	Regfree(&nodo)
 }
 
-/*
- * generate function call;
- *	proc=0	normal call
- *	proc=1	goroutine run in new proc
- *	proc=2	defer call save away stack
- */
+// generate function call;
+//	proc=0	normal call
+//	proc=1	goroutine run in new proc
+//	proc=2	defer call save away stack
 func cgen_call(n *Node, proc int) {
 	if n == nil {
 		return
@@ -2543,16 +2554,9 @@ func cgen_call(n *Node, proc int) {
 	Ginscall(n.Left, proc)
 }
 
-func HasLinkRegister() bool {
-	c := Ctxt.Arch.Thechar
-	return c != '6' && c != '8'
-}
-
-/*
- * call to n has already been generated.
- * generate:
- *	res = return value from call.
- */
+// call to n has already been generated.
+// generate:
+//	res = return value from call.
 func cgen_callret(n *Node, res *Node) {
 	t := n.Left.Type
 	if t.Etype == TPTR32 || t.Etype == TPTR64 {
@@ -2562,7 +2566,7 @@ func cgen_callret(n *Node, res *Node) {
 	var flist Iter
 	fp := Structfirst(&flist, Getoutarg(t))
 	if fp == nil {
-		Fatal("cgen_callret: nil")
+		Fatalf("cgen_callret: nil")
 	}
 
 	var nod Node
@@ -2570,19 +2574,14 @@ func cgen_callret(n *Node, res *Node) {
 	nod.Reg = int16(Thearch.REGSP)
 	nod.Addable = true
 
-	nod.Xoffset = fp.Width
-	if HasLinkRegister() {
-		nod.Xoffset += int64(Ctxt.Arch.Ptrsize)
-	}
+	nod.Xoffset = fp.Width + Ctxt.FixedFrameSize()
 	nod.Type = fp.Type
 	Cgen_as(res, &nod)
 }
 
-/*
- * call to n has already been generated.
- * generate:
- *	res = &return value from call.
- */
+// call to n has already been generated.
+// generate:
+//	res = &return value from call.
 func cgen_aret(n *Node, res *Node) {
 	t := n.Left.Type
 	if Isptr[t.Etype] {
@@ -2592,17 +2591,14 @@ func cgen_aret(n *Node, res *Node) {
 	var flist Iter
 	fp := Structfirst(&flist, Getoutarg(t))
 	if fp == nil {
-		Fatal("cgen_aret: nil")
+		Fatalf("cgen_aret: nil")
 	}
 
 	var nod1 Node
 	nod1.Op = OINDREG
 	nod1.Reg = int16(Thearch.REGSP)
 	nod1.Addable = true
-	nod1.Xoffset = fp.Width
-	if HasLinkRegister() {
-		nod1.Xoffset += int64(Ctxt.Arch.Ptrsize)
-	}
+	nod1.Xoffset = fp.Width + Ctxt.FixedFrameSize()
 	nod1.Type = fp.Type
 
 	if res.Op != OREGISTER {
@@ -2616,15 +2612,13 @@ func cgen_aret(n *Node, res *Node) {
 	}
 }
 
-/*
- * generate return.
- * n->left is assignments to return values.
- */
+// generate return.
+// n->left is assignments to return values.
 func cgen_ret(n *Node) {
 	if n != nil {
 		Genlist(n.List) // copy out args
 	}
-	if Hasdefer != 0 {
+	if hasdefer {
 		Ginscall(Deferreturn, 0)
 	}
 	Genlist(Curfn.Func.Exit)
@@ -2636,19 +2630,17 @@ func cgen_ret(n *Node) {
 	}
 }
 
-/*
- * generate division according to op, one of:
- *	res = nl / nr
- *	res = nl % nr
- */
-func cgen_div(op int, nl *Node, nr *Node, res *Node) {
+// generate division according to op, one of:
+//	res = nl / nr
+//	res = nl % nr
+func cgen_div(op Op, nl *Node, nr *Node, res *Node) {
 	var w int
 
 	// TODO(rsc): arm64 needs to support the relevant instructions
 	// in peep and optoas in order to enable this.
 	// TODO(rsc): ppc64 needs to support the relevant instructions
 	// in peep and optoas in order to enable this.
-	if nr.Op != OLITERAL || Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9' {
+	if nr.Op != OLITERAL || Ctxt.Arch.Thechar == '0' || Ctxt.Arch.Thechar == '7' || Ctxt.Arch.Thechar == '9' {
 		goto longdiv
 	}
 	w = int(nl.Type.Width * 8)
@@ -2814,11 +2806,11 @@ func cgen_append(n, res *Node) {
 	if res.Op != ONAME && !samesafeexpr(res, n.List.N) {
 		Dump("cgen_append-n", n)
 		Dump("cgen_append-res", res)
-		Fatal("append not lowered")
+		Fatalf("append not lowered")
 	}
 	for l := n.List; l != nil; l = l.Next {
 		if l.N.Ullman >= UINF {
-			Fatal("append with function call arguments")
+			Fatalf("append with function call arguments")
 		}
 	}
 
@@ -2860,10 +2852,7 @@ func cgen_append(n, res *Node) {
 	arg.Op = OINDREG
 	arg.Reg = int16(Thearch.REGSP)
 	arg.Addable = true
-	arg.Xoffset = 0
-	if HasLinkRegister() {
-		arg.Xoffset = int64(Ctxt.Arch.Ptrsize)
-	}
+	arg.Xoffset = Ctxt.FixedFrameSize()
 	arg.Type = Ptrto(Types[TUINT8])
 	Cgen(typename(res.Type), &arg)
 	arg.Xoffset += int64(Widthptr)
@@ -3261,7 +3250,7 @@ func cgen_slice(n, res *Node, wb bool) {
 		// but it will be represented in 32 bits.
 		if Ctxt.Arch.Regsize == 4 && Is64(n1.Type) {
 			if mpcmpfixc(n1.Val().U.(*Mpint), 1<<31) >= 0 {
-				Fatal("missed slice out of bounds check")
+				Fatalf("missed slice out of bounds check")
 			}
 			var tmp Node
 			Nodconst(&tmp, indexRegType, Mpgetfix(n1.Val().U.(*Mpint)))
diff --git a/src/cmd/compile/internal/gc/closure.go b/src/cmd/compile/internal/gc/closure.go
index a0dfa0b..df3e31a 100644
--- a/src/cmd/compile/internal/gc/closure.go
+++ b/src/cmd/compile/internal/gc/closure.go
@@ -9,9 +9,7 @@ import (
 	"fmt"
 )
 
-/*
- * function literals aka closures
- */
+// function literals aka closures
 func closurehdr(ntype *Node) {
 	var name *Node
 	var a *Node
@@ -87,7 +85,7 @@ func typecheckclosure(func_ *Node, top int) {
 		if !n.Name.Captured {
 			n.Name.Captured = true
 			if n.Name.Decldepth == 0 {
-				Fatal("typecheckclosure: var %v does not have decldepth assigned", Nconv(n, obj.FmtShort))
+				Fatalf("typecheckclosure: var %v does not have decldepth assigned", Nconv(n, obj.FmtShort))
 			}
 
 			// Ignore assignments to the variable in straightline code
@@ -172,17 +170,15 @@ func closurename(n *Node) *Sym {
 		n.Func.Outerfunc.Func.Closgen++
 		gen = n.Func.Outerfunc.Func.Closgen
 	} else {
-		Fatal("closurename called for %v", Nconv(n, obj.FmtShort))
+		Fatalf("closurename called for %v", Nconv(n, obj.FmtShort))
 	}
 	n.Sym = Lookupf("%s.%s%d", outer, prefix, gen)
 	return n.Sym
 }
 
 func makeclosure(func_ *Node) *Node {
-	/*
-	 * wrap body in external function
-	 * that begins by reading closure parameters.
-	 */
+	// wrap body in external function
+	// that begins by reading closure parameters.
 	xtype := Nod(OTFUNC, nil, nil)
 
 	xtype.List = func_.List
@@ -204,7 +200,7 @@ func makeclosure(func_ *Node) *Node {
 	xfunc.Nbody = func_.Nbody
 	xfunc.Func.Dcl = concat(func_.Func.Dcl, xfunc.Func.Dcl)
 	if xfunc.Nbody == nil {
-		Fatal("empty body - won't generate any code")
+		Fatalf("empty body - won't generate any code")
 	}
 	typecheck(&xfunc, Etop)
 
@@ -322,7 +318,7 @@ func transformclosure(xfunc *Node) {
 				continue
 			}
 			fld = typ(TFIELD)
-			fld.Funarg = 1
+			fld.Funarg = true
 			if v.Name.Byval {
 				// If v is captured by value, we merely downgrade it to PPARAM.
 				v.Class = PPARAM
@@ -355,7 +351,7 @@ func transformclosure(xfunc *Node) {
 
 		// Recalculate param offsets.
 		if f.Type.Width > 0 {
-			Fatal("transformclosure: width is already calculated")
+			Fatalf("transformclosure: width is already calculated")
 		}
 		dowidth(f.Type)
 		xfunc.Type = f.Type // update type of ODCLFUNC
@@ -491,7 +487,7 @@ func typecheckpartialcall(fn *Node, sym *Node) {
 		break
 
 	default:
-		Fatal("invalid typecheckpartialcall")
+		Fatalf("invalid typecheckpartialcall")
 	}
 
 	// Create top-level function.
@@ -518,7 +514,7 @@ func makepartialcall(fn *Node, t0 *Type, meth *Node) *Node {
 		basetype = basetype.Type
 	}
 	if basetype.Etype != TINTER && basetype.Sym == nil {
-		Fatal("missing base type for %v", rcvrtype)
+		Fatalf("missing base type for %v", rcvrtype)
 	}
 
 	var spkg *Pkg
diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go
index 5095e5e..795b53d 100644
--- a/src/cmd/compile/internal/gc/const.go
+++ b/src/cmd/compile/internal/gc/const.go
@@ -10,11 +10,24 @@ import (
 	"strings"
 )
 
+// IntLiteral returns the Node's literal value as an interger.
+func (n *Node) IntLiteral() (x int64, ok bool) {
+	switch {
+	case n == nil:
+		return
+	case Isconst(n, CTINT):
+		return n.Int(), true
+	case Isconst(n, CTBOOL):
+		return int64(obj.Bool2int(n.Bool())), true
+	}
+	return
+}
+
 // Int returns n as an int.
 // n must be an integer constant.
 func (n *Node) Int() int64 {
 	if !Isconst(n, CTINT) {
-		Fatal("Int(%v)", n)
+		Fatalf("Int(%v)", n)
 	}
 	return Mpgetfix(n.Val().U.(*Mpint))
 }
@@ -23,7 +36,7 @@ func (n *Node) Int() int64 {
 // n must be an integer constant.
 func (n *Node) SetInt(i int64) {
 	if !Isconst(n, CTINT) {
-		Fatal("SetInt(%v)", n)
+		Fatalf("SetInt(%v)", n)
 	}
 	Mpmovecfix(n.Val().U.(*Mpint), i)
 }
@@ -32,7 +45,7 @@ func (n *Node) SetInt(i int64) {
 // n must be an integer constant.
 func (n *Node) SetBigInt(x *big.Int) {
 	if !Isconst(n, CTINT) {
-		Fatal("SetBigInt(%v)", n)
+		Fatalf("SetBigInt(%v)", n)
 	}
 	n.Val().U.(*Mpint).Val.Set(x)
 }
@@ -41,15 +54,13 @@ func (n *Node) SetBigInt(x *big.Int) {
 // n must be an boolean constant.
 func (n *Node) Bool() bool {
 	if !Isconst(n, CTBOOL) {
-		Fatal("Int(%v)", n)
+		Fatalf("Int(%v)", n)
 	}
 	return n.Val().U.(bool)
 }
 
-/*
- * truncate float literal fv to 32-bit or 64-bit precision
- * according to type; return truncated value.
- */
+// truncate float literal fv to 32-bit or 64-bit precision
+// according to type; return truncated value.
 func truncfltlit(oldv *Mpflt, t *Type) *Mpflt {
 	if t == nil {
 		return oldv
@@ -77,19 +88,15 @@ func truncfltlit(oldv *Mpflt, t *Type) *Mpflt {
 	return fv
 }
 
-/*
- * convert n, if literal, to type t.
- * implicit conversion.
- */
+// convert n, if literal, to type t.
+// implicit conversion.
 func Convlit(np **Node, t *Type) {
 	convlit1(np, t, false)
 }
 
-/*
- * convert n, if literal, to type t.
- * return a new node if necessary
- * (if n is a named constant, can't edit n->type directly).
- */
+// convert n, if literal, to type t.
+// return a new node if necessary
+//(if n is a named constant, can't edit n->type directly).
 func convlit1(np **Node, t *Type, explicit bool) {
 	n := *np
 	if n == nil || t == nil || n.Type == nil || isideal(t) || n.Type == t {
@@ -242,7 +249,7 @@ func convlit1(np **Node, t *Type, explicit bool) {
 		if n.Type.Etype == TUNSAFEPTR && t.Etype != TUINTPTR {
 			goto bad
 		}
-		ct := int(n.Val().Ctype())
+		ct := n.Val().Ctype()
 		if Isint[et] {
 			switch ct {
 			default:
@@ -252,7 +259,6 @@ func convlit1(np **Node, t *Type, explicit bool) {
 				n.SetVal(toint(n.Val()))
 				fallthrough
 
-				// flowthrough
 			case CTINT:
 				overflow(n.Val(), t)
 			}
@@ -265,7 +271,6 @@ func convlit1(np **Node, t *Type, explicit bool) {
 				n.SetVal(toflt(n.Val()))
 				fallthrough
 
-				// flowthrough
 			case CTFLT:
 				n.SetVal(Val{truncfltlit(n.Val().U.(*Mpflt), t)})
 			}
@@ -276,6 +281,7 @@ func convlit1(np **Node, t *Type, explicit bool) {
 
 			case CTFLT, CTINT, CTRUNE:
 				n.SetVal(tocplx(n.Val()))
+				fallthrough
 
 			case CTCPLX:
 				overflow(n.Val(), t)
@@ -292,7 +298,7 @@ func convlit1(np **Node, t *Type, explicit bool) {
 
 bad:
 	if n.Diag == 0 {
-		if t.Broke == 0 {
+		if !t.Broke {
 			Yyerror("cannot convert %v to type %v", n, t)
 		}
 		n.Diag = 1
@@ -373,8 +379,13 @@ func toint(v Val) Val {
 
 	case CTFLT:
 		i := new(Mpint)
-		if mpmovefltfix(i, v.U.(*Mpflt)) < 0 {
-			Yyerror("constant %v truncated to integer", Fconv(v.U.(*Mpflt), obj.FmtSharp))
+		if f := v.U.(*Mpflt); mpmovefltfix(i, f) < 0 {
+			msg := "constant %v truncated to integer"
+			// provide better error message if mpmovefltfix failed because f was too large
+			if f.Val.IsInt() {
+				msg = "constant %v overflows integer"
+			}
+			Yyerror(msg, Fconv(f, obj.FmtSharp))
 		}
 		v.U = i
 
@@ -396,7 +407,7 @@ func doesoverflow(v Val, t *Type) bool {
 	switch v.Ctype() {
 	case CTINT, CTRUNE:
 		if !Isint[t.Etype] {
-			Fatal("overflow: %v integer constant", t)
+			Fatalf("overflow: %v integer constant", t)
 		}
 		if Mpcmpfixfix(v.U.(*Mpint), Minintval[t.Etype]) < 0 || Mpcmpfixfix(v.U.(*Mpint), Maxintval[t.Etype]) > 0 {
 			return true
@@ -404,7 +415,7 @@ func doesoverflow(v Val, t *Type) bool {
 
 	case CTFLT:
 		if !Isfloat[t.Etype] {
-			Fatal("overflow: %v floating-point constant", t)
+			Fatalf("overflow: %v floating-point constant", t)
 		}
 		if mpcmpfltflt(v.U.(*Mpflt), minfltval[t.Etype]) <= 0 || mpcmpfltflt(v.U.(*Mpflt), maxfltval[t.Etype]) >= 0 {
 			return true
@@ -412,7 +423,7 @@ func doesoverflow(v Val, t *Type) bool {
 
 	case CTCPLX:
 		if !Iscomplex[t.Etype] {
-			Fatal("overflow: %v complex constant", t)
+			Fatalf("overflow: %v complex constant", t)
 		}
 		if mpcmpfltflt(&v.U.(*Mpcplx).Real, minfltval[t.Etype]) <= 0 || mpcmpfltflt(&v.U.(*Mpcplx).Real, maxfltval[t.Etype]) >= 0 || mpcmpfltflt(&v.U.(*Mpcplx).Imag, minfltval[t.Etype]) <= 0 || mpcmpfltflt(&v.U.(*Mpcplx).Imag, maxfltval[t.Etype]) >= 0 {
 			return true
@@ -434,19 +445,8 @@ func overflow(v Val, t *Type) {
 		return
 	}
 
-	if !doesoverflow(v, t) {
-		return
-	}
-
-	switch v.Ctype() {
-	case CTINT, CTRUNE:
-		Yyerror("constant %v overflows %v", v.U.(*Mpint), t)
-
-	case CTFLT:
-		Yyerror("constant %v overflows %v", Fconv(v.U.(*Mpflt), obj.FmtSharp), t)
-
-	case CTCPLX:
-		Yyerror("constant %v overflows %v", Fconv(v.U.(*Mpflt), obj.FmtSharp), t)
+	if doesoverflow(v, t) {
+		Yyerror("constant %s overflows %v", Vconv(v, 0), t)
 	}
 }
 
@@ -472,14 +472,14 @@ func tostr(v Val) Val {
 	return v
 }
 
-func consttype(n *Node) int {
+func consttype(n *Node) Ctype {
 	if n == nil || n.Op != OLITERAL {
 		return -1
 	}
-	return int(n.Val().Ctype())
+	return n.Val().Ctype()
 }
 
-func Isconst(n *Node, ct int) bool {
+func Isconst(n *Node, ct Ctype) bool {
 	t := consttype(n)
 
 	// If the caller is asking for CTINT, allow CTRUNE too.
@@ -499,9 +499,7 @@ func saveorig(n *Node) *Node {
 	return n.Orig
 }
 
-/*
- * if n is constant, rewrite as OLITERAL node.
- */
+// if n is constant, rewrite as OLITERAL node.
 func evconst(n *Node) {
 	// pick off just the opcodes that can be
 	// constant evaluated.
@@ -594,12 +592,49 @@ func evconst(n *Node) {
 		wl = TIDEAL
 	}
 
+	// avoid constant conversions in switches below
+	const (
+		CTINT_         = uint32(CTINT)
+		CTRUNE_        = uint32(CTRUNE)
+		CTFLT_         = uint32(CTFLT)
+		CTCPLX_        = uint32(CTCPLX)
+		CTSTR_         = uint32(CTSTR)
+		CTBOOL_        = uint32(CTBOOL)
+		CTNIL_         = uint32(CTNIL)
+		OCONV_         = uint32(OCONV) << 16
+		OARRAYBYTESTR_ = uint32(OARRAYBYTESTR) << 16
+		OPLUS_         = uint32(OPLUS) << 16
+		OMINUS_        = uint32(OMINUS) << 16
+		OCOM_          = uint32(OCOM) << 16
+		ONOT_          = uint32(ONOT) << 16
+		OLSH_          = uint32(OLSH) << 16
+		ORSH_          = uint32(ORSH) << 16
+		OADD_          = uint32(OADD) << 16
+		OSUB_          = uint32(OSUB) << 16
+		OMUL_          = uint32(OMUL) << 16
+		ODIV_          = uint32(ODIV) << 16
+		OMOD_          = uint32(OMOD) << 16
+		OOR_           = uint32(OOR) << 16
+		OAND_          = uint32(OAND) << 16
+		OANDNOT_       = uint32(OANDNOT) << 16
+		OXOR_          = uint32(OXOR) << 16
+		OEQ_           = uint32(OEQ) << 16
+		ONE_           = uint32(ONE) << 16
+		OLT_           = uint32(OLT) << 16
+		OLE_           = uint32(OLE) << 16
+		OGE_           = uint32(OGE) << 16
+		OGT_           = uint32(OGT) << 16
+		OOROR_         = uint32(OOROR) << 16
+		OANDAND_       = uint32(OANDAND) << 16
+	)
+
 	nr := n.Right
 	var rv Val
 	var lno int
 	var wr int
 	var v Val
 	var norig *Node
+	var nn *Node
 	if nr == nil {
 		// copy numeric value to avoid modifying
 		// nl, in case someone still refers to it (e.g. iota).
@@ -615,11 +650,10 @@ func evconst(n *Node) {
 				Yyerror("illegal constant expression %v %v", Oconv(int(n.Op), 0), nl.Type)
 				n.Diag = 1
 			}
-
 			return
 
-		case OCONV<<16 | CTNIL,
-			OARRAYBYTESTR<<16 | CTNIL:
+		case OCONV_ | CTNIL_,
+			OARRAYBYTESTR_ | CTNIL_:
 			if n.Type.Etype == TSTRING {
 				v = tostr(v)
 				nl.Type = n.Type
@@ -628,24 +662,25 @@ func evconst(n *Node) {
 			fallthrough
 
 			// fall through
-		case OCONV<<16 | CTINT,
-			OCONV<<16 | CTRUNE,
-			OCONV<<16 | CTFLT,
-			OCONV<<16 | CTSTR:
+		case OCONV_ | CTINT_,
+			OCONV_ | CTRUNE_,
+			OCONV_ | CTFLT_,
+			OCONV_ | CTSTR_,
+			OCONV_ | CTBOOL_:
 			convlit1(&nl, n.Type, true)
 
 			v = nl.Val()
 
-		case OPLUS<<16 | CTINT,
-			OPLUS<<16 | CTRUNE:
+		case OPLUS_ | CTINT_,
+			OPLUS_ | CTRUNE_:
 			break
 
-		case OMINUS<<16 | CTINT,
-			OMINUS<<16 | CTRUNE:
+		case OMINUS_ | CTINT_,
+			OMINUS_ | CTRUNE_:
 			mpnegfix(v.U.(*Mpint))
 
-		case OCOM<<16 | CTINT,
-			OCOM<<16 | CTRUNE:
+		case OCOM_ | CTINT_,
+			OCOM_ | CTRUNE_:
 			et := Txxx
 			if nl.Type != nil {
 				et = int(nl.Type.Etype)
@@ -671,20 +706,20 @@ func evconst(n *Node) {
 
 			mpxorfixfix(v.U.(*Mpint), &b)
 
-		case OPLUS<<16 | CTFLT:
+		case OPLUS_ | CTFLT_:
 			break
 
-		case OMINUS<<16 | CTFLT:
+		case OMINUS_ | CTFLT_:
 			mpnegflt(v.U.(*Mpflt))
 
-		case OPLUS<<16 | CTCPLX:
+		case OPLUS_ | CTCPLX_:
 			break
 
-		case OMINUS<<16 | CTCPLX:
+		case OMINUS_ | CTCPLX_:
 			mpnegflt(&v.U.(*Mpcplx).Real)
 			mpnegflt(&v.U.(*Mpcplx).Imag)
 
-		case ONOT<<16 | CTBOOL:
+		case ONOT_ | CTBOOL_:
 			if !v.U.(bool) {
 				goto settrue
 			}
@@ -787,7 +822,7 @@ func evconst(n *Node) {
 		if (v.Ctype() == 0 || rv.Ctype() == 0) && nerrors > 0 {
 			return
 		}
-		Fatal("constant type mismatch %v(%d) %v(%d)", nl.Type, v.Ctype(), nr.Type, rv.Ctype())
+		Fatalf("constant type mismatch %v(%d) %v(%d)", nl.Type, v.Ctype(), nr.Type, rv.Ctype())
 	}
 
 	// run op
@@ -795,20 +830,20 @@ func evconst(n *Node) {
 	default:
 		goto illegal
 
-	case OADD<<16 | CTINT,
-		OADD<<16 | CTRUNE:
+	case OADD_ | CTINT_,
+		OADD_ | CTRUNE_:
 		mpaddfixfix(v.U.(*Mpint), rv.U.(*Mpint), 0)
 
-	case OSUB<<16 | CTINT,
-		OSUB<<16 | CTRUNE:
+	case OSUB_ | CTINT_,
+		OSUB_ | CTRUNE_:
 		mpsubfixfix(v.U.(*Mpint), rv.U.(*Mpint))
 
-	case OMUL<<16 | CTINT,
-		OMUL<<16 | CTRUNE:
+	case OMUL_ | CTINT_,
+		OMUL_ | CTRUNE_:
 		mpmulfixfix(v.U.(*Mpint), rv.U.(*Mpint))
 
-	case ODIV<<16 | CTINT,
-		ODIV<<16 | CTRUNE:
+	case ODIV_ | CTINT_,
+		ODIV_ | CTRUNE_:
 		if mpcmpfixc(rv.U.(*Mpint), 0) == 0 {
 			Yyerror("division by zero")
 			mpsetovf(v.U.(*Mpint))
@@ -817,8 +852,8 @@ func evconst(n *Node) {
 
 		mpdivfixfix(v.U.(*Mpint), rv.U.(*Mpint))
 
-	case OMOD<<16 | CTINT,
-		OMOD<<16 | CTRUNE:
+	case OMOD_ | CTINT_,
+		OMOD_ | CTRUNE_:
 		if mpcmpfixc(rv.U.(*Mpint), 0) == 0 {
 			Yyerror("division by zero")
 			mpsetovf(v.U.(*Mpint))
@@ -827,40 +862,40 @@ func evconst(n *Node) {
 
 		mpmodfixfix(v.U.(*Mpint), rv.U.(*Mpint))
 
-	case OLSH<<16 | CTINT,
-		OLSH<<16 | CTRUNE:
+	case OLSH_ | CTINT_,
+		OLSH_ | CTRUNE_:
 		mplshfixfix(v.U.(*Mpint), rv.U.(*Mpint))
 
-	case ORSH<<16 | CTINT,
-		ORSH<<16 | CTRUNE:
+	case ORSH_ | CTINT_,
+		ORSH_ | CTRUNE_:
 		mprshfixfix(v.U.(*Mpint), rv.U.(*Mpint))
 
-	case OOR<<16 | CTINT,
-		OOR<<16 | CTRUNE:
+	case OOR_ | CTINT_,
+		OOR_ | CTRUNE_:
 		mporfixfix(v.U.(*Mpint), rv.U.(*Mpint))
 
-	case OAND<<16 | CTINT,
-		OAND<<16 | CTRUNE:
+	case OAND_ | CTINT_,
+		OAND_ | CTRUNE_:
 		mpandfixfix(v.U.(*Mpint), rv.U.(*Mpint))
 
-	case OANDNOT<<16 | CTINT,
-		OANDNOT<<16 | CTRUNE:
+	case OANDNOT_ | CTINT_,
+		OANDNOT_ | CTRUNE_:
 		mpandnotfixfix(v.U.(*Mpint), rv.U.(*Mpint))
 
-	case OXOR<<16 | CTINT,
-		OXOR<<16 | CTRUNE:
+	case OXOR_ | CTINT_,
+		OXOR_ | CTRUNE_:
 		mpxorfixfix(v.U.(*Mpint), rv.U.(*Mpint))
 
-	case OADD<<16 | CTFLT:
+	case OADD_ | CTFLT_:
 		mpaddfltflt(v.U.(*Mpflt), rv.U.(*Mpflt))
 
-	case OSUB<<16 | CTFLT:
+	case OSUB_ | CTFLT_:
 		mpsubfltflt(v.U.(*Mpflt), rv.U.(*Mpflt))
 
-	case OMUL<<16 | CTFLT:
+	case OMUL_ | CTFLT_:
 		mpmulfltflt(v.U.(*Mpflt), rv.U.(*Mpflt))
 
-	case ODIV<<16 | CTFLT:
+	case ODIV_ | CTFLT_:
 		if mpcmpfltc(rv.U.(*Mpflt), 0) == 0 {
 			Yyerror("division by zero")
 			Mpmovecflt(v.U.(*Mpflt), 1.0)
@@ -871,7 +906,7 @@ func evconst(n *Node) {
 
 		// The default case above would print 'ideal % ideal',
 	// which is not quite an ideal error.
-	case OMOD<<16 | CTFLT:
+	case OMOD_ | CTFLT_:
 		if n.Diag == 0 {
 			Yyerror("illegal constant expression: floating-point %% operation")
 			n.Diag = 1
@@ -879,18 +914,18 @@ func evconst(n *Node) {
 
 		return
 
-	case OADD<<16 | CTCPLX:
+	case OADD_ | CTCPLX_:
 		mpaddfltflt(&v.U.(*Mpcplx).Real, &rv.U.(*Mpcplx).Real)
 		mpaddfltflt(&v.U.(*Mpcplx).Imag, &rv.U.(*Mpcplx).Imag)
 
-	case OSUB<<16 | CTCPLX:
+	case OSUB_ | CTCPLX_:
 		mpsubfltflt(&v.U.(*Mpcplx).Real, &rv.U.(*Mpcplx).Real)
 		mpsubfltflt(&v.U.(*Mpcplx).Imag, &rv.U.(*Mpcplx).Imag)
 
-	case OMUL<<16 | CTCPLX:
+	case OMUL_ | CTCPLX_:
 		cmplxmpy(v.U.(*Mpcplx), rv.U.(*Mpcplx))
 
-	case ODIV<<16 | CTCPLX:
+	case ODIV_ | CTCPLX_:
 		if mpcmpfltc(&rv.U.(*Mpcplx).Real, 0) == 0 && mpcmpfltc(&rv.U.(*Mpcplx).Imag, 0) == 0 {
 			Yyerror("complex division by zero")
 			Mpmovecflt(&rv.U.(*Mpcplx).Real, 1.0)
@@ -900,157 +935,157 @@ func evconst(n *Node) {
 
 		cmplxdiv(v.U.(*Mpcplx), rv.U.(*Mpcplx))
 
-	case OEQ<<16 | CTNIL:
+	case OEQ_ | CTNIL_:
 		goto settrue
 
-	case ONE<<16 | CTNIL:
+	case ONE_ | CTNIL_:
 		goto setfalse
 
-	case OEQ<<16 | CTINT,
-		OEQ<<16 | CTRUNE:
+	case OEQ_ | CTINT_,
+		OEQ_ | CTRUNE_:
 		if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) == 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case ONE<<16 | CTINT,
-		ONE<<16 | CTRUNE:
+	case ONE_ | CTINT_,
+		ONE_ | CTRUNE_:
 		if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) != 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OLT<<16 | CTINT,
-		OLT<<16 | CTRUNE:
+	case OLT_ | CTINT_,
+		OLT_ | CTRUNE_:
 		if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) < 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OLE<<16 | CTINT,
-		OLE<<16 | CTRUNE:
+	case OLE_ | CTINT_,
+		OLE_ | CTRUNE_:
 		if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) <= 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OGE<<16 | CTINT,
-		OGE<<16 | CTRUNE:
+	case OGE_ | CTINT_,
+		OGE_ | CTRUNE_:
 		if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) >= 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OGT<<16 | CTINT,
-		OGT<<16 | CTRUNE:
+	case OGT_ | CTINT_,
+		OGT_ | CTRUNE_:
 		if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) > 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OEQ<<16 | CTFLT:
+	case OEQ_ | CTFLT_:
 		if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) == 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case ONE<<16 | CTFLT:
+	case ONE_ | CTFLT_:
 		if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) != 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OLT<<16 | CTFLT:
+	case OLT_ | CTFLT_:
 		if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) < 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OLE<<16 | CTFLT:
+	case OLE_ | CTFLT_:
 		if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) <= 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OGE<<16 | CTFLT:
+	case OGE_ | CTFLT_:
 		if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) >= 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OGT<<16 | CTFLT:
+	case OGT_ | CTFLT_:
 		if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) > 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OEQ<<16 | CTCPLX:
+	case OEQ_ | CTCPLX_:
 		if mpcmpfltflt(&v.U.(*Mpcplx).Real, &rv.U.(*Mpcplx).Real) == 0 && mpcmpfltflt(&v.U.(*Mpcplx).Imag, &rv.U.(*Mpcplx).Imag) == 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case ONE<<16 | CTCPLX:
+	case ONE_ | CTCPLX_:
 		if mpcmpfltflt(&v.U.(*Mpcplx).Real, &rv.U.(*Mpcplx).Real) != 0 || mpcmpfltflt(&v.U.(*Mpcplx).Imag, &rv.U.(*Mpcplx).Imag) != 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OEQ<<16 | CTSTR:
-		if cmpslit(nl, nr) == 0 {
+	case OEQ_ | CTSTR_:
+		if strlit(nl) == strlit(nr) {
 			goto settrue
 		}
 		goto setfalse
 
-	case ONE<<16 | CTSTR:
-		if cmpslit(nl, nr) != 0 {
+	case ONE_ | CTSTR_:
+		if strlit(nl) != strlit(nr) {
 			goto settrue
 		}
 		goto setfalse
 
-	case OLT<<16 | CTSTR:
-		if cmpslit(nl, nr) < 0 {
+	case OLT_ | CTSTR_:
+		if strlit(nl) < strlit(nr) {
 			goto settrue
 		}
 		goto setfalse
 
-	case OLE<<16 | CTSTR:
-		if cmpslit(nl, nr) <= 0 {
+	case OLE_ | CTSTR_:
+		if strlit(nl) <= strlit(nr) {
 			goto settrue
 		}
 		goto setfalse
 
-	case OGE<<16 | CTSTR:
-		if cmpslit(nl, nr) >= 0 {
+	case OGE_ | CTSTR_:
+		if strlit(nl) >= strlit(nr) {
 			goto settrue
 		}
 		goto setfalse
 
-	case OGT<<16 | CTSTR:
-		if cmpslit(nl, nr) > 0 {
+	case OGT_ | CTSTR_:
+		if strlit(nl) > strlit(nr) {
 			goto settrue
 		}
 		goto setfalse
 
-	case OOROR<<16 | CTBOOL:
+	case OOROR_ | CTBOOL_:
 		if v.U.(bool) || rv.U.(bool) {
 			goto settrue
 		}
 		goto setfalse
 
-	case OANDAND<<16 | CTBOOL:
+	case OANDAND_ | CTBOOL_:
 		if v.U.(bool) && rv.U.(bool) {
 			goto settrue
 		}
 		goto setfalse
 
-	case OEQ<<16 | CTBOOL:
+	case OEQ_ | CTBOOL_:
 		if v.U.(bool) == rv.U.(bool) {
 			goto settrue
 		}
 		goto setfalse
 
-	case ONE<<16 | CTBOOL:
+	case ONE_ | CTBOOL_:
 		if v.U.(bool) != rv.U.(bool) {
 			goto settrue
 		}
@@ -1081,15 +1116,21 @@ ret:
 	return
 
 settrue:
-	norig = saveorig(n)
-	*n = *Nodbool(true)
-	n.Orig = norig
+	nn = Nodbool(true)
+	nn.Orig = saveorig(n)
+	if !iscmp[n.Op] {
+		nn.Type = nl.Type
+	}
+	*n = *nn
 	return
 
 setfalse:
-	norig = saveorig(n)
-	*n = *Nodbool(false)
-	n.Orig = norig
+	nn = Nodbool(false)
+	nn.Orig = saveorig(n)
+	if !iscmp[n.Op] {
+		nn.Type = nl.Type
+	}
+	*n = *nn
 	return
 
 illegal:
@@ -1097,8 +1138,6 @@ illegal:
 		Yyerror("illegal constant expression: %v %v %v", nl.Type, Oconv(int(n.Op), 0), nr.Type)
 		n.Diag = 1
 	}
-
-	return
 }
 
 func nodlit(v Val) *Node {
@@ -1106,7 +1145,7 @@ func nodlit(v Val) *Node {
 	n.SetVal(v)
 	switch v.Ctype() {
 	default:
-		Fatal("nodlit ctype %d", v.Ctype())
+		Fatalf("nodlit ctype %d", v.Ctype())
 
 	case CTSTR:
 		n.Type = idealstring
@@ -1134,7 +1173,7 @@ func nodcplxlit(r Val, i Val) *Node {
 	n.SetVal(Val{c})
 
 	if r.Ctype() != CTFLT || i.Ctype() != CTFLT {
-		Fatal("nodcplxlit ctype %d/%d", r.Ctype(), i.Ctype())
+		Fatalf("nodcplxlit ctype %d/%d", r.Ctype(), i.Ctype())
 	}
 
 	mpmovefltflt(&c.Real, r.U.(*Mpflt))
@@ -1144,7 +1183,7 @@ func nodcplxlit(r Val, i Val) *Node {
 
 // idealkind returns a constant kind like consttype
 // but for an arbitrary "ideal" (untyped constant) expression.
-func idealkind(n *Node) int {
+func idealkind(n *Node) Ctype {
 	if n == nil || !isideal(n.Type) {
 		return CTxxx
 	}
@@ -1154,7 +1193,7 @@ func idealkind(n *Node) int {
 		return CTxxx
 
 	case OLITERAL:
-		return int(n.Val().Ctype())
+		return n.Val().Ctype()
 
 		// numeric kinds.
 	case OADD,
@@ -1249,7 +1288,7 @@ func defaultlit(np **Node, t *Type) {
 		Yyerror("defaultlit: unknown literal: %v", n)
 
 	case CTxxx:
-		Fatal("defaultlit: idealkind is CTxxx: %v", Nconv(n, obj.FmtSign))
+		Fatalf("defaultlit: idealkind is CTxxx: %v", Nconv(n, obj.FmtSign))
 
 	case CTBOOL:
 		t1 := Types[TBOOL]
@@ -1306,12 +1345,10 @@ num:
 	return
 }
 
-/*
- * defaultlit on both nodes simultaneously;
- * if they're both ideal going in they better
- * get the same type going out.
- * force means must assign concrete (non-ideal) type.
- */
+// defaultlit on both nodes simultaneously;
+// if they're both ideal going in they better
+// get the same type going out.
+// force means must assign concrete (non-ideal) type.
 func defaultlit2(lp **Node, rp **Node, force int) {
 	l := *lp
 	r := *rp
@@ -1360,8 +1397,9 @@ func defaultlit2(lp **Node, rp **Node, force int) {
 	Convlit(rp, Types[TINT])
 }
 
-func cmpslit(l, r *Node) int {
-	return stringsCompare(l.Val().U.(string), r.Val().U.(string))
+// strlit returns the value of a literal string Node as a string.
+func strlit(n *Node) string {
+	return n.Val().U.(string)
 }
 
 func Smallintconst(n *Node) bool {
@@ -1411,11 +1449,9 @@ func nonnegconst(n *Node) int {
 	return -1
 }
 
-/*
- * convert x to type et and back to int64
- * for sign extension and truncation.
- */
-func iconv(x int64, et int) int64 {
+// convert x to type et and back to int64
+// for sign extension and truncation.
+func iconv(x int64, et EType) int64 {
 	switch et {
 	case TINT8:
 		x = int64(int8(x))
@@ -1458,7 +1494,7 @@ func (n *Node) Convconst(con *Node, t *Type) {
 		var i int64
 		switch n.Val().Ctype() {
 		default:
-			Fatal("convconst ctype=%d %v", n.Val().Ctype(), Tconv(t, obj.FmtLong))
+			Fatalf("convconst ctype=%d %v", n.Val().Ctype(), Tconv(t, obj.FmtLong))
 
 		case CTINT, CTRUNE:
 			i = Mpgetfix(n.Val().U.(*Mpint))
@@ -1478,7 +1514,7 @@ func (n *Node) Convconst(con *Node, t *Type) {
 	if Isfloat[tt] {
 		con.SetVal(toflt(con.Val()))
 		if con.Val().Ctype() != CTFLT {
-			Fatal("convconst ctype=%d %v", con.Val().Ctype(), t)
+			Fatalf("convconst ctype=%d %v", con.Val().Ctype(), t)
 		}
 		if tt == TFLOAT32 {
 			con.SetVal(Val{truncfltlit(con.Val().U.(*Mpflt), t)})
@@ -1495,7 +1531,7 @@ func (n *Node) Convconst(con *Node, t *Type) {
 		return
 	}
 
-	Fatal("convconst %v constant", Tconv(t, obj.FmtLong))
+	Fatalf("convconst %v constant", Tconv(t, obj.FmtLong))
 }
 
 // complex multiply v *= rv
diff --git a/src/cmd/compile/internal/gc/cplx.go b/src/cmd/compile/internal/gc/cplx.go
index 1643f26..b692456 100644
--- a/src/cmd/compile/internal/gc/cplx.go
+++ b/src/cmd/compile/internal/gc/cplx.go
@@ -14,7 +14,7 @@ func overlap_cplx(f *Node, t *Node) bool {
 	return f.Op == OINDREG && t.Op == OINDREG && f.Xoffset+f.Type.Width >= t.Xoffset && t.Xoffset+t.Type.Width >= f.Xoffset
 }
 
-func complexbool(op int, nl, nr, res *Node, wantTrue bool, likely int, to *obj.Prog) {
+func complexbool(op Op, nl, nr, res *Node, wantTrue bool, likely int, to *obj.Prog) {
 	// make both sides addable in ullman order
 	if nr != nil {
 		if nl.Ullman > nr.Ullman && !nl.Addable {
@@ -81,7 +81,7 @@ func complexbool(op int, nl, nr, res *Node, wantTrue bool, likely int, to *obj.P
 // break addable nc-complex into nr-real and ni-imaginary
 func subnode(nr *Node, ni *Node, nc *Node) {
 	if !nc.Addable {
-		Fatal("subnode not addable")
+		Fatalf("subnode not addable")
 	}
 
 	tc := Simsimtype(nc.Type)
@@ -130,7 +130,7 @@ func complexminus(nl *Node, res *Node) {
 // build and execute tree
 //	real(res) = real(nl) op real(nr)
 //	imag(res) = imag(nl) op imag(nr)
-func complexadd(op int, nl *Node, nr *Node, res *Node) {
+func complexadd(op Op, nl *Node, nr *Node, res *Node) {
 	var n1 Node
 	var n2 Node
 	var n3 Node
@@ -143,14 +143,14 @@ func complexadd(op int, nl *Node, nr *Node, res *Node) {
 	subnode(&n5, &n6, res)
 
 	var ra Node
-	ra.Op = uint8(op)
+	ra.Op = op
 	ra.Left = &n1
 	ra.Right = &n3
 	ra.Type = n1.Type
 	Cgen(&ra, &n5)
 
 	ra = Node{}
-	ra.Op = uint8(op)
+	ra.Op = op
 	ra.Left = &n2
 	ra.Right = &n4
 	ra.Type = n2.Type
@@ -230,7 +230,7 @@ func nodfconst(n *Node, t *Type, fval *Mpflt) {
 	n.Type = t
 
 	if !Isfloat[t.Etype] {
-		Fatal("nodfconst: bad type %v", t)
+		Fatalf("nodfconst: bad type %v", t)
 	}
 }
 
@@ -288,22 +288,15 @@ func Complexmove(f *Node, t *Node) {
 	}
 
 	if !t.Addable {
-		Fatal("complexmove: to not addable")
+		Fatalf("complexmove: to not addable")
 	}
 
 	ft := Simsimtype(f.Type)
 	tt := Simsimtype(t.Type)
-	switch uint32(ft)<<16 | uint32(tt) {
-	default:
-		Fatal("complexmove: unknown conversion: %v -> %v\n", f.Type, t.Type)
-
-		// complex to complex move/convert.
+	// complex to complex move/convert.
 	// make f addable.
 	// also use temporary if possible stack overlap.
-	case TCOMPLEX64<<16 | TCOMPLEX64,
-		TCOMPLEX64<<16 | TCOMPLEX128,
-		TCOMPLEX128<<16 | TCOMPLEX64,
-		TCOMPLEX128<<16 | TCOMPLEX128:
+	if (ft == TCOMPLEX64 || ft == TCOMPLEX128) && (tt == TCOMPLEX64 || tt == TCOMPLEX128) {
 		if !f.Addable || overlap_cplx(f, t) {
 			var tmp Node
 			Tempname(&tmp, f.Type)
@@ -320,6 +313,8 @@ func Complexmove(f *Node, t *Node) {
 
 		Cgen(&n1, &n3)
 		Cgen(&n2, &n4)
+	} else {
+		Fatalf("complexmove: unknown conversion: %v -> %v\n", f.Type, t.Type)
 	}
 }
 
@@ -403,7 +398,7 @@ func Complexgen(n *Node, res *Node) {
 	switch n.Op {
 	default:
 		Dump("complexgen: unknown op", n)
-		Fatal("complexgen: unknown op %v", Oconv(int(n.Op), 0))
+		Fatalf("complexgen: unknown op %v", Oconv(int(n.Op), 0))
 
 	case ODOT,
 		ODOTPTR,
@@ -462,7 +457,7 @@ func Complexgen(n *Node, res *Node) {
 
 	switch n.Op {
 	default:
-		Fatal("complexgen: unknown op %v", Oconv(int(n.Op), 0))
+		Fatalf("complexgen: unknown op %v", Oconv(int(n.Op), 0))
 
 	case OCONV:
 		Complexmove(nl, res)
@@ -471,7 +466,7 @@ func Complexgen(n *Node, res *Node) {
 		complexminus(nl, res)
 
 	case OADD, OSUB:
-		complexadd(int(n.Op), nl, nr, res)
+		complexadd(n.Op, nl, nr, res)
 
 	case OMUL:
 		complexmul(nl, nr, res)
diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go
index c8864f3..fc47a39 100644
--- a/src/cmd/compile/internal/gc/dcl.go
+++ b/src/cmd/compile/internal/gc/dcl.go
@@ -23,9 +23,7 @@ func dflag() bool {
 	return true
 }
 
-/*
- * declaration stack & operations
- */
+// declaration stack & operations
 func dcopy(a *Sym, b *Sym) {
 	a.Pkg = b.Pkg
 	a.Name = b.Name
@@ -73,22 +71,12 @@ func popdcl() {
 	}
 
 	if d == nil {
-		Fatal("popdcl: no mark")
+		Fatalf("popdcl: no mark")
 	}
 	dclstack = d.Link
 	block = d.Block
 }
 
-func poptodcl() {
-	// pop the old marker and push a new one
-	// (cannot reuse the existing one)
-	// because we use the markers to identify blocks
-	// for the goto restriction checks.
-	popdcl()
-
-	markdcl()
-}
-
 func markdcl() {
 	d := push()
 	d.Name = "" // used as a mark in fifo
@@ -159,13 +147,11 @@ func redeclare(s *Sym, where string) {
 
 var vargen int
 
-/*
- * declare individual names - var, typ, const
- */
+// declare individual names - var, typ, const
 
 var declare_typegen int
 
-func declare(n *Node, ctxt uint8) {
+func declare(n *Node, ctxt Class) {
 	if ctxt == PDISCARD {
 		return
 	}
@@ -182,7 +168,7 @@ func declare(n *Node, ctxt uint8) {
 	s := n.Sym
 
 	// kludgy: typecheckok means we're past parsing.  Eg genwrapper may declare out of package names later.
-	if importpkg == nil && typecheckok == 0 && s.Pkg != localpkg {
+	if importpkg == nil && !typecheckok && s.Pkg != localpkg {
 		Yyerror("cannot declare name %v", s)
 	}
 
@@ -192,13 +178,13 @@ func declare(n *Node, ctxt uint8) {
 
 	gen := 0
 	if ctxt == PEXTERN {
-		externdcl = list(externdcl, n)
+		externdcl = append(externdcl, n)
 		if dflag() {
 			fmt.Printf("\t%v global decl %v %p\n", Ctxt.Line(int(lineno)), s, n)
 		}
 	} else {
 		if Curfn == nil && ctxt == PAUTO {
-			Fatal("automatic outside function")
+			Fatalf("automatic outside function")
 		}
 		if Curfn != nil {
 			Curfn.Func.Dcl = list(Curfn.Func.Dcl, n)
@@ -231,14 +217,14 @@ func declare(n *Node, ctxt uint8) {
 	s.Def = n
 	n.Name.Vargen = int32(gen)
 	n.Name.Funcdepth = Funcdepth
-	n.Class = uint8(ctxt)
+	n.Class = ctxt
 
 	autoexport(n, ctxt)
 }
 
-func addvar(n *Node, t *Type, ctxt uint8) {
+func addvar(n *Node, t *Type, ctxt Class) {
 	if n == nil || n.Sym == nil || (n.Op != ONAME && n.Op != ONONAME) || t == nil {
-		Fatal("addvar: n=%v t=%v nil", n, t)
+		Fatalf("addvar: n=%v t=%v nil", n, t)
 	}
 
 	n.Op = ONAME
@@ -246,10 +232,8 @@ func addvar(n *Node, t *Type, ctxt uint8) {
 	n.Type = t
 }
 
-/*
- * declare variables from grammar
- * new_name_list (type | [type] = expr_list)
- */
+// declare variables from grammar
+// new_name_list (type | [type] = expr_list)
 func variter(vl *NodeList, t *Node, el *NodeList) *NodeList {
 	var init *NodeList
 	doexpr := el != nil
@@ -312,10 +296,8 @@ func variter(vl *NodeList, t *Node, el *NodeList) *NodeList {
 	return init
 }
 
-/*
- * declare constants from grammar
- * new_name_list [[type] = expr_list]
- */
+// declare constants from grammar
+// new_name_list [[type] = expr_list]
 func constiter(vl *NodeList, t *Node, cl *NodeList) *NodeList {
 	lno := int32(0) // default is to leave line number alone in listtreecopy
 	if cl == nil {
@@ -360,13 +342,11 @@ func constiter(vl *NodeList, t *Node, cl *NodeList) *NodeList {
 	return vv
 }
 
-/*
- * this generates a new name node,
- * typically for labels or other one-off names.
- */
+// this generates a new name node,
+// typically for labels or other one-off names.
 func newname(s *Sym) *Node {
 	if s == nil {
-		Fatal("newname nil")
+		Fatalf("newname nil")
 	}
 
 	n := Nod(ONAME, nil, nil)
@@ -387,10 +367,8 @@ func newfuncname(s *Sym) *Node {
 	return n
 }
 
-/*
- * this generates a new name node for a name
- * being declared.
- */
+// this generates a new name node for a name
+// being declared.
 func dclname(s *Sym) *Node {
 	n := newname(s)
 	n.Op = ONONAME // caller will correct it
@@ -410,12 +388,10 @@ func typenod(t *Type) *Node {
 	return t.Nod
 }
 
-/*
- * this will return an old name
- * that has already been pushed on the
- * declaration list. a diagnostic is
- * generated if no name has been defined.
- */
+// this will return an old name
+// that has already been pushed on the
+// declaration list. a diagnostic is
+// generated if no name has been defined.
 func oldname(s *Sym) *Node {
 	n := s.Def
 	if n == nil {
@@ -460,9 +436,7 @@ func oldname(s *Sym) *Node {
 	return n
 }
 
-/*
- * := declarations
- */
+// := declarations
 func colasname(n *Node) bool {
 	switch n.Op {
 	case ONAME,
@@ -542,13 +516,11 @@ func colas(left *NodeList, right *NodeList, lno int32) *Node {
 	return as
 }
 
-/*
- * declare the arguments in an
- * interface field declaration.
- */
+// declare the arguments in an
+// interface field declaration.
 func ifacedcl(n *Node) {
 	if n.Op != ODCLFIELD || n.Right == nil {
-		Fatal("ifacedcl")
+		Fatalf("ifacedcl")
 	}
 
 	if isblank(n.Left) {
@@ -573,16 +545,14 @@ func ifacedcl(n *Node) {
 	funcbody(n)
 }
 
-/*
- * declare the function proper
- * and declare the arguments.
- * called in extern-declaration context
- * returns in auto-declaration context.
- */
+// declare the function proper
+// and declare the arguments.
+// called in extern-declaration context
+// returns in auto-declaration context.
 func funchdr(n *Node) {
 	// change the declaration context from extern to auto
 	if Funcdepth == 0 && dclcontext != PEXTERN {
-		Fatal("funchdr: dclcontext")
+		Fatalf("funchdr: dclcontext")
 	}
 
 	if importpkg == nil && n.Func.Nname != nil {
@@ -607,7 +577,7 @@ func funchdr(n *Node) {
 
 func funcargs(nt *Node) {
 	if nt.Op != OTFUNC {
-		Fatal("funcargs %v", Oconv(int(nt.Op), 0))
+		Fatalf("funcargs %v", Oconv(int(nt.Op), 0))
 	}
 
 	// re-start the variable generation number
@@ -621,7 +591,7 @@ func funcargs(nt *Node) {
 	if nt.Left != nil {
 		n := nt.Left
 		if n.Op != ODCLFIELD {
-			Fatal("funcargs receiver %v", Oconv(int(n.Op), 0))
+			Fatalf("funcargs receiver %v", Oconv(int(n.Op), 0))
 		}
 		if n.Left != nil {
 			n.Left.Op = ONAME
@@ -638,7 +608,7 @@ func funcargs(nt *Node) {
 	for l := nt.List; l != nil; l = l.Next {
 		n = l.N
 		if n.Op != ODCLFIELD {
-			Fatal("funcargs in %v", Oconv(int(n.Op), 0))
+			Fatalf("funcargs in %v", Oconv(int(n.Op), 0))
 		}
 		if n.Left != nil {
 			n.Left.Op = ONAME
@@ -659,7 +629,7 @@ func funcargs(nt *Node) {
 		n = l.N
 
 		if n.Op != ODCLFIELD {
-			Fatal("funcargs out %v", Oconv(int(n.Op), 0))
+			Fatalf("funcargs out %v", Oconv(int(n.Op), 0))
 		}
 
 		if n.Left == nil {
@@ -698,14 +668,12 @@ func funcargs(nt *Node) {
 	}
 }
 
-/*
- * Same as funcargs, except run over an already constructed TFUNC.
- * This happens during import, where the hidden_fndcl rule has
- * used functype directly to parse the function's type.
- */
+// Same as funcargs, except run over an already constructed TFUNC.
+// This happens during import, where the hidden_fndcl rule has
+// used functype directly to parse the function's type.
 func funcargs2(t *Type) {
 	if t.Etype != TFUNC {
-		Fatal("funcargs2 %v", t)
+		Fatalf("funcargs2 %v", t)
 	}
 
 	if t.Thistuple != 0 {
@@ -745,15 +713,13 @@ func funcargs2(t *Type) {
 	}
 }
 
-/*
- * finish the body.
- * called in auto-declaration context.
- * returns in extern-declaration context.
- */
+// finish the body.
+// called in auto-declaration context.
+// returns in extern-declaration context.
 func funcbody(n *Node) {
 	// change the declaration context from auto to extern
 	if dclcontext != PAUTO {
-		Fatal("funcbody: dclcontext")
+		Fatalf("funcbody: dclcontext")
 	}
 	popdcl()
 	Funcdepth--
@@ -764,9 +730,7 @@ func funcbody(n *Node) {
 	}
 }
 
-/*
- * new type being defined with name s.
- */
+// new type being defined with name s.
 func typedcl0(s *Sym) *Node {
 	n := newname(s)
 	n.Op = OTYPE
@@ -774,21 +738,17 @@ func typedcl0(s *Sym) *Node {
 	return n
 }
 
-/*
- * node n, which was returned by typedcl0
- * is being declared to have uncompiled type t.
- * return the ODCLTYPE node to use.
- */
+// node n, which was returned by typedcl0
+// is being declared to have uncompiled type t.
+// return the ODCLTYPE node to use.
 func typedcl1(n *Node, t *Node, local bool) *Node {
 	n.Name.Param.Ntype = t
 	n.Local = local
 	return Nod(ODCLTYPE, n, nil)
 }
 
-/*
- * structs, functions, and methods.
- * they don't belong here, but where do they belong?
- */
+// structs, functions, and methods.
+// they don't belong here, but where do they belong?
 func checkembeddedtype(t *Type) {
 	if t == nil {
 		return
@@ -813,7 +773,7 @@ func structfield(n *Node) *Type {
 	lineno = n.Lineno
 
 	if n.Op != ODCLFIELD {
-		Fatal("structfield: oops %v\n", n)
+		Fatalf("structfield: oops %v\n", n)
 	}
 
 	f := typ(TFIELD)
@@ -834,7 +794,7 @@ func structfield(n *Node) *Type {
 
 	f.Type = n.Type
 	if f.Type == nil {
-		f.Broke = 1
+		f.Broke = true
 	}
 
 	switch n.Val().Ctype() {
@@ -879,48 +839,51 @@ func checkdupfields(t *Type, what string) {
 	lineno = int32(lno)
 }
 
-/*
- * convert a parsed id/type list into
- * a type for struct/interface/arglist
- */
+// convert a parsed id/type list into
+// a type for struct/interface/arglist
 func tostruct(l *NodeList) *Type {
-	var f *Type
 	t := typ(TSTRUCT)
+	tostruct0(t, l)
+	return t
+}
+
+func tostruct0(t *Type, l *NodeList) {
+	if t == nil || t.Etype != TSTRUCT {
+		Fatalf("struct expected")
+	}
 
 	for tp := &t.Type; l != nil; l = l.Next {
-		f = structfield(l.N)
+		f := structfield(l.N)
 
 		*tp = f
 		tp = &f.Down
 	}
 
-	for f := t.Type; f != nil && t.Broke == 0; f = f.Down {
-		if f.Broke != 0 {
-			t.Broke = 1
+	for f := t.Type; f != nil && !t.Broke; f = f.Down {
+		if f.Broke {
+			t.Broke = true
 		}
 	}
 
 	uniqgen++
 	checkdupfields(t.Type, "field")
 
-	if t.Broke == 0 {
+	if !t.Broke {
 		checkwidth(t)
 	}
-
-	return t
 }
 
 func tofunargs(l *NodeList) *Type {
 	var f *Type
 
 	t := typ(TSTRUCT)
-	t.Funarg = 1
+	t.Funarg = true
 
 	for tp := &t.Type; l != nil; l = l.Next {
 		f = structfield(l.N)
-		f.Funarg = 1
+		f.Funarg = true
 
-		// esc.c needs to find f given a PPARAM to add the tag.
+		// esc.go needs to find f given a PPARAM to add the tag.
 		if l.N.Left != nil && l.N.Left.Class == PPARAM {
 			l.N.Left.Name.Param.Field = f
 		}
@@ -929,9 +892,9 @@ func tofunargs(l *NodeList) *Type {
 		tp = &f.Down
 	}
 
-	for f := t.Type; f != nil && t.Broke == 0; f = f.Down {
-		if f.Broke != 0 {
-			t.Broke = 1
+	for f := t.Type; f != nil && !t.Broke; f = f.Down {
+		if f.Broke {
+			t.Broke = true
 		}
 	}
 
@@ -943,7 +906,7 @@ func interfacefield(n *Node) *Type {
 	lineno = n.Lineno
 
 	if n.Op != ODCLFIELD {
-		Fatal("interfacefield: oops %v\n", n)
+		Fatalf("interfacefield: oops %v\n", n)
 	}
 
 	if n.Val().Ctype() != CTxxx {
@@ -984,11 +947,11 @@ func interfacefield(n *Node) *Type {
 
 				case TFORW:
 					Yyerror("interface type loop involving %v", n.Type)
-					f.Broke = 1
+					f.Broke = true
 
 				default:
 					Yyerror("interface contains embedded non-interface %v", n.Type)
-					f.Broke = 1
+					f.Broke = true
 				}
 			}
 		}
@@ -998,7 +961,7 @@ func interfacefield(n *Node) *Type {
 
 	f.Type = n.Type
 	if f.Type == nil {
-		f.Broke = 1
+		f.Broke = true
 	}
 
 	lineno = int32(lno)
@@ -1006,18 +969,23 @@ func interfacefield(n *Node) *Type {
 }
 
 func tointerface(l *NodeList) *Type {
-	var f *Type
-	var t1 *Type
-
 	t := typ(TINTER)
+	tointerface0(t, l)
+	return t
+}
+
+func tointerface0(t *Type, l *NodeList) *Type {
+	if t == nil || t.Etype != TINTER {
+		Fatalf("interface expected")
+	}
 
 	tp := &t.Type
 	for ; l != nil; l = l.Next {
-		f = interfacefield(l.N)
+		f := interfacefield(l.N)
 
 		if l.N.Left == nil && f.Type.Etype == TINTER {
 			// embedded interface, inline methods
-			for t1 = f.Type.Type; t1 != nil; t1 = t1.Down {
+			for t1 := f.Type.Type; t1 != nil; t1 = t1.Down {
 				f = typ(TFIELD)
 				f.Type = t1.Type
 				f.Broke = t1.Broke
@@ -1034,9 +1002,9 @@ func tointerface(l *NodeList) *Type {
 		}
 	}
 
-	for f := t.Type; f != nil && t.Broke == 0; f = f.Down {
-		if f.Broke != 0 {
-			t.Broke = 1
+	for f := t.Type; f != nil && !t.Broke; f = f.Down {
+		if f.Broke {
+			t.Broke = true
 		}
 	}
 
@@ -1075,9 +1043,7 @@ func embedded(s *Sym, pkg *Pkg) *Node {
 	return n
 }
 
-/*
- * check that the list of declarations is either all anonymous or all named
- */
+// check that the list of declarations is either all anonymous or all named
 func findtype(l *NodeList) *Node {
 	for ; l != nil; l = l.Next {
 		if l.N.Op == OKEY {
@@ -1142,7 +1108,7 @@ func checkarglist(all *NodeList, input int) *NodeList {
 		// declarations, which are parsed by rules that don't
 		// use checkargs, but can happen for func literals in
 		// the inline bodies.
-		// TODO(rsc) this can go when typefmt case TFIELD in exportmode fmt.c prints _ instead of ?
+		// TODO(rsc) this can go when typefmt case TFIELD in exportmode fmt.go prints _ instead of ?
 		if importpkg != nil && n.Sym == nil {
 			n = nil
 		}
@@ -1182,12 +1148,9 @@ func fakethis() *Node {
 	return n
 }
 
-/*
- * Is this field a method on an interface?
- * Those methods have an anonymous
- * *struct{} as the receiver.
- * (See fakethis above.)
- */
+// Is this field a method on an interface?
+// Those methods have an anonymous *struct{} as the receiver.
+// (See fakethis above.)
 func isifacemethod(f *Type) bool {
 	rcvr := getthisx(f).Type
 	if rcvr.Sym != nil {
@@ -1204,12 +1167,17 @@ func isifacemethod(f *Type) bool {
 	return true
 }
 
-/*
- * turn a parsed function declaration
- * into a type
- */
+// turn a parsed function declaration into a type
 func functype(this *Node, in *NodeList, out *NodeList) *Type {
 	t := typ(TFUNC)
+	functype0(t, this, in, out)
+	return t
+}
+
+func functype0(t *Type, this *Node, in *NodeList, out *NodeList) {
+	if t == nil || t.Etype != TFUNC {
+		Fatalf("function type expected")
+	}
 
 	var rcvr *NodeList
 	if this != nil {
@@ -1224,8 +1192,8 @@ func functype(this *Node, in *NodeList, out *NodeList) *Type {
 	checkdupfields(t.Type.Down.Type, "argument")
 	checkdupfields(t.Type.Down.Down.Type, "argument")
 
-	if t.Type.Broke != 0 || t.Type.Down.Broke != 0 || t.Type.Down.Down.Broke != 0 {
-		t.Broke = 1
+	if t.Type.Broke || t.Type.Down.Broke || t.Type.Down.Down.Broke {
+		t.Broke = true
 	}
 
 	if this != nil {
@@ -1233,15 +1201,13 @@ func functype(this *Node, in *NodeList, out *NodeList) *Type {
 	}
 	t.Outtuple = count(out)
 	t.Intuple = count(in)
-	t.Outnamed = 0
+	t.Outnamed = false
 	if t.Outtuple > 0 && out.N.Left != nil && out.N.Left.Orig != nil {
 		s := out.N.Left.Orig.Sym
 		if s != nil && (s.Name[0] != '~' || s.Name[1] != 'r') { // ~r%d is the name invented for an unnamed result
-			t.Outnamed = 1
+			t.Outnamed = true
 		}
 	}
-
-	return t
 }
 
 var methodsym_toppkg *Pkg
@@ -1349,14 +1315,12 @@ func methodname1(n *Node, t *Node) *Node {
 	return n
 }
 
-/*
- * add a method, declared as a function,
- * n is fieldname, pa is base type, t is function type
- */
+// add a method, declared as a function,
+// n is fieldname, pa is base type, t is function type
 func addmethod(sf *Sym, t *Type, local bool, nointerface bool) {
 	// get field sym
 	if sf == nil {
-		Fatal("no method symbol")
+		Fatalf("no method symbol")
 	}
 
 	// get parent type sym
@@ -1383,7 +1347,7 @@ func addmethod(sf *Sym, t *Type, local bool, nointerface bool) {
 				t = t.Type
 			}
 
-			if t.Broke != 0 { // rely on typecheck having complained before
+			if t.Broke { // rely on typecheck having complained before
 				return
 			}
 			if t.Sym == nil {
@@ -1410,6 +1374,15 @@ func addmethod(sf *Sym, t *Type, local bool, nointerface bool) {
 	}
 
 	pa = f
+	if local && !pa.Local {
+		Yyerror("cannot define new methods on non-local type %v", pa)
+		return
+	}
+
+	if isblanksym(sf) {
+		return
+	}
+
 	if pa.Etype == TSTRUCT {
 		for f := pa.Type; f != nil; f = f.Down {
 			if f.Sym == sf {
@@ -1419,13 +1392,6 @@ func addmethod(sf *Sym, t *Type, local bool, nointerface bool) {
 		}
 	}
 
-	if local && !pa.Local {
-		// defining method on non-local type.
-		Yyerror("cannot define new methods on non-local type %v", pa)
-
-		return
-	}
-
 	n := Nod(ODCLFIELD, newname(sf), nil)
 	n.Type = t
 
@@ -1433,7 +1399,7 @@ func addmethod(sf *Sym, t *Type, local bool, nointerface bool) {
 	for f := pa.Method; f != nil; f = f.Down {
 		d = f
 		if f.Etype != TFIELD {
-			Fatal("addmethod: not TFIELD: %v", Tconv(f, obj.FmtLong))
+			Fatalf("addmethod: not TFIELD: %v", Tconv(f, obj.FmtLong))
 		}
 		if sf.Name != f.Sym.Name {
 			continue
@@ -1449,7 +1415,7 @@ func addmethod(sf *Sym, t *Type, local bool, nointerface bool) {
 
 	// during import unexported method names should be in the type's package
 	if importpkg != nil && f.Sym != nil && !exportname(f.Sym.Name) && f.Sym.Pkg != structpkg {
-		Fatal("imported method name %v in wrong package %s\n", Sconv(f.Sym, obj.FmtSign), structpkg.Name)
+		Fatalf("imported method name %v in wrong package %s\n", Sconv(f.Sym, obj.FmtSign), structpkg.Name)
 	}
 
 	if d == nil {
@@ -1466,7 +1432,7 @@ func funccompile(n *Node) {
 
 	if n.Type == nil {
 		if nerrors == 0 {
-			Fatal("funccompile missing type")
+			Fatalf("funccompile missing type")
 		}
 		return
 	}
@@ -1475,7 +1441,7 @@ func funccompile(n *Node) {
 	checkwidth(n.Type)
 
 	if Curfn != nil {
-		Fatal("funccompile %v inside %v", n.Func.Nname.Sym, Curfn.Func.Nname.Sym)
+		Fatalf("funccompile %v inside %v", n.Func.Nname.Sym, Curfn.Func.Nname.Sym)
 	}
 
 	Stksize = 0
@@ -1509,5 +1475,121 @@ func makefuncsym(s *Sym) {
 	s1 := funcsym(s)
 	s1.Def = newfuncname(s1)
 	s1.Def.Func.Shortname = newname(s)
-	funcsyms = list(funcsyms, s1.Def)
+	funcsyms = append(funcsyms, s1.Def)
+}
+
+type nowritebarrierrecChecker struct {
+	curfn  *Node
+	stable bool
+
+	// best maps from the ODCLFUNC of each visited function that
+	// recursively invokes a write barrier to the called function
+	// on the shortest path to a write barrier.
+	best map[*Node]nowritebarrierrecCall
+}
+
+type nowritebarrierrecCall struct {
+	target *Node
+	depth  int
+	lineno int32
+}
+
+func checknowritebarrierrec() {
+	c := nowritebarrierrecChecker{
+		best: make(map[*Node]nowritebarrierrecCall),
+	}
+	visitBottomUp(xtop, func(list []*Node, recursive bool) {
+		// Functions with write barriers have depth 0.
+		for _, n := range list {
+			if n.Func.WBLineno != 0 {
+				c.best[n] = nowritebarrierrecCall{target: nil, depth: 0, lineno: n.Func.WBLineno}
+			}
+		}
+
+		// Propagate write barrier depth up from callees. In
+		// the recursive case, we have to update this at most
+		// len(list) times and can stop when we an iteration
+		// that doesn't change anything.
+		for _ = range list {
+			c.stable = false
+			for _, n := range list {
+				if n.Func.WBLineno == 0 {
+					c.curfn = n
+					c.visitcodelist(n.Nbody)
+				}
+			}
+			if c.stable {
+				break
+			}
+		}
+
+		// Check nowritebarrierrec functions.
+		for _, n := range list {
+			if !n.Func.Nowritebarrierrec {
+				continue
+			}
+			call, hasWB := c.best[n]
+			if !hasWB {
+				continue
+			}
+
+			// Build the error message in reverse.
+			err := ""
+			for call.target != nil {
+				err = fmt.Sprintf("\n\t%v: called by %v%s", Ctxt.Line(int(call.lineno)), n.Func.Nname, err)
+				n = call.target
+				call = c.best[n]
+			}
+			err = fmt.Sprintf("write barrier prohibited by caller; %v%s", n.Func.Nname, err)
+			yyerrorl(int(n.Func.WBLineno), err)
+		}
+	})
+}
+
+func (c *nowritebarrierrecChecker) visitcodelist(l *NodeList) {
+	for ; l != nil; l = l.Next {
+		c.visitcode(l.N)
+	}
+}
+
+func (c *nowritebarrierrecChecker) visitcode(n *Node) {
+	if n == nil {
+		return
+	}
+
+	if n.Op == OCALLFUNC || n.Op == OCALLMETH {
+		c.visitcall(n)
+	}
+
+	c.visitcodelist(n.Ninit)
+	c.visitcode(n.Left)
+	c.visitcode(n.Right)
+	c.visitcodelist(n.List)
+	c.visitcodelist(n.Nbody)
+	c.visitcodelist(n.Rlist)
+}
+
+func (c *nowritebarrierrecChecker) visitcall(n *Node) {
+	fn := n.Left
+	if n.Op == OCALLMETH {
+		fn = n.Left.Right.Sym.Def
+	}
+	if fn == nil || fn.Op != ONAME || fn.Class != PFUNC || fn.Name.Defn == nil {
+		return
+	}
+	if (compiling_runtime != 0 || fn.Sym.Pkg == Runtimepkg) && fn.Sym.Name == "allocm" {
+		return
+	}
+	defn := fn.Name.Defn
+
+	fnbest, ok := c.best[defn]
+	if !ok {
+		return
+	}
+	best, ok := c.best[c.curfn]
+	if ok && fnbest.depth+1 >= best.depth {
+		return
+	}
+	c.best[c.curfn] = nowritebarrierrecCall{target: defn, depth: fnbest.depth + 1, lineno: n.Lineno}
+	c.stable = false
 }
diff --git a/src/cmd/compile/internal/gc/esc.go b/src/cmd/compile/internal/gc/esc.go
index 4c4455f..ff983e7 100644
--- a/src/cmd/compile/internal/gc/esc.go
+++ b/src/cmd/compile/internal/gc/esc.go
@@ -7,6 +7,7 @@ package gc
 import (
 	"cmd/internal/obj"
 	"fmt"
+	"strconv"
 	"strings"
 )
 
@@ -34,10 +35,10 @@ import (
 // when analyzing a set of mutually recursive functions.
 
 type bottomUpVisitor struct {
-	analyze  func(*NodeList, bool)
+	analyze  func([]*Node, bool)
 	visitgen uint32
 	nodeID   map[*Node]uint32
-	stack    *NodeList
+	stack    []*Node
 }
 
 // visitBottomUp invokes analyze on the ODCLFUNC nodes listed in list.
@@ -53,7 +54,7 @@ type bottomUpVisitor struct {
 // If recursive is false, the list consists of only a single function and its closures.
 // If recursive is true, the list may still contain only a single function,
 // if that function is itself recursive.
-func visitBottomUp(list *NodeList, analyze func(list *NodeList, recursive bool)) {
+func visitBottomUp(list *NodeList, analyze func(list []*Node, recursive bool)) {
 	var v bottomUpVisitor
 	v.analyze = analyze
 	v.nodeID = make(map[*Node]uint32)
@@ -76,10 +77,7 @@ func (v *bottomUpVisitor) visit(n *Node) uint32 {
 	v.visitgen++
 	min := v.visitgen
 
-	l := new(NodeList)
-	l.Next = v.stack
-	l.N = n
-	v.stack = l
+	v.stack = append(v.stack, n)
 	min = v.visitcodelist(n.Nbody, min)
 	if (min == id || min == id+1) && n.Func.FCurfn == nil {
 		// This node is the root of a strongly connected component.
@@ -93,17 +91,19 @@ func (v *bottomUpVisitor) visit(n *Node) uint32 {
 		// Remove connected component from stack.
 		// Mark walkgen so that future visits return a large number
 		// so as not to affect the caller's min.
-		block := v.stack
 
-		var l *NodeList
-		for l = v.stack; l.N != n; l = l.Next {
-			v.nodeID[l.N] = ^uint32(0)
+		var i int
+		for i = len(v.stack) - 1; i >= 0; i-- {
+			x := v.stack[i]
+			if x == n {
+				break
+			}
+			v.nodeID[x] = ^uint32(0)
 		}
 		v.nodeID[n] = ^uint32(0)
-		v.stack = l.Next
-		l.Next = nil
-
+		block := v.stack[i:]
 		// Run escape analysis on this set of functions.
+		v.stack = v.stack[:i]
 		v.analyze(block, recursive)
 	}
 
@@ -249,17 +249,6 @@ func satInc8(x int8) int8 {
 	return x + 1
 }
 
-func satAdd8(x, y int8) int8 {
-	z := x + y
-	if x^y < 0 || x^z >= 0 {
-		return z
-	}
-	if x < 0 {
-		return -128
-	}
-	return 127
-}
-
 func min8(a, b int8) int8 {
 	if a < b {
 		return a
@@ -310,12 +299,13 @@ func (l Level) guaranteedDereference() int {
 }
 
 type NodeEscState struct {
-	Curfn        *Node
-	Escflowsrc   *NodeList // flow(this, src)
-	Escretval    *NodeList // on OCALLxxx, list of dummy return values
-	Escloopdepth int32     // -1: global, 0: return variables, 1:function top level, increased inside function for every loop or label to mark scopes
-	Esclevel     Level
-	Walkgen      uint32
+	Curfn             *Node
+	Escflowsrc        *NodeList // flow(this, src)
+	Escretval         *NodeList // on OCALLxxx, list of dummy return values
+	Escloopdepth      int32     // -1: global, 0: return variables, 1:function top level, increased inside function for every loop or label to mark scopes
+	Esclevel          Level
+	Walkgen           uint32
+	Maxextraloopdepth int32
 }
 
 func (e *EscState) nodeEscState(n *Node) *NodeEscState {
@@ -323,7 +313,7 @@ func (e *EscState) nodeEscState(n *Node) *NodeEscState {
 		return nE
 	}
 	if n.Opt() != nil {
-		Fatal("nodeEscState: opt in use (%T)", n.Opt())
+		Fatalf("nodeEscState: opt in use (%T)", n.Opt())
 	}
 	nE := new(NodeEscState)
 	nE.Curfn = Curfn
@@ -334,7 +324,7 @@ func (e *EscState) nodeEscState(n *Node) *NodeEscState {
 
 func (e *EscState) track(n *Node) {
 	if Curfn == nil {
-		Fatal("EscState.track: Curfn nil")
+		Fatalf("EscState.track: Curfn nil")
 	}
 	n.Esc = EscNone // until proven otherwise
 	nE := e.nodeEscState(n)
@@ -368,7 +358,7 @@ func escMax(e, etype uint16) uint16 {
 	if e&EscMask >= EscScope {
 		// normalize
 		if e&^EscMask != 0 {
-			Fatal("Escape information had unexpected return encoding bits (w/ EscScope, EscHeap, EscNever), e&EscMask=%v", e&EscMask)
+			Fatalf("Escape information had unexpected return encoding bits (w/ EscScope, EscHeap, EscNever), e&EscMask=%v", e&EscMask)
 		}
 	}
 	if e&EscMask > etype {
@@ -386,10 +376,9 @@ func escMax(e, etype uint16) uint16 {
 // something whose address is returned -- but that implies stored into the heap,
 // hence EscHeap, which means that the details are not currently relevant. )
 const (
-	bitsPerOutputInTag = 3                                         // For each output, the number of bits for a tag
-	bitsMaskForTag     = uint16(1<<bitsPerOutputInTag) - 1         // The bit mask to extract a single tag.
-	outputsPerTag      = (16 - EscReturnBits) / bitsPerOutputInTag // The number of outputs that can be tagged.
-	maxEncodedLevel    = int(bitsMaskForTag - 1)                   // The largest level that can be stored in a tag.
+	bitsPerOutputInTag = 3                                 // For each output, the number of bits for a tag
+	bitsMaskForTag     = uint16(1<<bitsPerOutputInTag) - 1 // The bit mask to extract a single tag.
+	maxEncodedLevel    = int(bitsMaskForTag - 1)           // The largest level that can be stored in a tag.
 )
 
 type EscState struct {
@@ -425,7 +414,7 @@ func (e *EscState) curfnSym(n *Node) *Sym {
 	return funcSym(nE.Curfn)
 }
 
-func escAnalyze(all *NodeList, recursive bool) {
+func escAnalyze(all []*Node, recursive bool) {
 	var es EscState
 	e := &es
 	e.theSink.Op = ONAME
@@ -435,16 +424,16 @@ func escAnalyze(all *NodeList, recursive bool) {
 	e.nodeEscState(&e.theSink).Escloopdepth = -1
 	e.recursive = recursive
 
-	for l := all; l != nil; l = l.Next {
-		if l.N.Op == ODCLFUNC {
-			l.N.Esc = EscFuncPlanned
+	for i := len(all) - 1; i >= 0; i-- {
+		if n := all[i]; n.Op == ODCLFUNC {
+			n.Esc = EscFuncPlanned
 		}
 	}
 
 	// flow-analyze functions
-	for l := all; l != nil; l = l.Next {
-		if l.N.Op == ODCLFUNC {
-			escfunc(e, l.N)
+	for i := len(all) - 1; i >= 0; i-- {
+		if n := all[i]; n.Op == ODCLFUNC {
+			escfunc(e, n)
 		}
 	}
 
@@ -457,9 +446,9 @@ func escAnalyze(all *NodeList, recursive bool) {
 	}
 
 	// for all top level functions, tag the typenodes corresponding to the param nodes
-	for l := all; l != nil; l = l.Next {
-		if l.N.Op == ODCLFUNC {
-			esctag(e, l.N)
+	for i := len(all) - 1; i >= 0; i-- {
+		if n := all[i]; n.Op == ODCLFUNC {
+			esctag(e, n)
 		}
 	}
 
@@ -478,7 +467,7 @@ func escAnalyze(all *NodeList, recursive bool) {
 func escfunc(e *EscState, func_ *Node) {
 	//	print("escfunc %N %s\n", func->nname, e->recursive?"(recursive)":"");
 	if func_.Esc != 1 {
-		Fatal("repeat escfunc %v", func_.Func.Nname)
+		Fatalf("repeat escfunc %v", func_.Func.Nname)
 	}
 	func_.Esc = EscFuncStarted
 
@@ -549,7 +538,7 @@ func escloopdepth(e *EscState, n *Node) {
 	switch n.Op {
 	case OLABEL:
 		if n.Left == nil || n.Left.Sym == nil {
-			Fatal("esc:label without label: %v", Nconv(n, obj.FmtSign))
+			Fatalf("esc:label without label: %v", Nconv(n, obj.FmtSign))
 		}
 
 		// Walk will complain about this label being already defined, but that's not until
@@ -560,7 +549,7 @@ func escloopdepth(e *EscState, n *Node) {
 
 	case OGOTO:
 		if n.Left == nil || n.Left.Sym == nil {
-			Fatal("esc:goto without label: %v", Nconv(n, obj.FmtSign))
+			Fatalf("esc:goto without label: %v", Nconv(n, obj.FmtSign))
 		}
 
 		// If we come past one that's uninitialized, this must be a (harmless) forward jump
@@ -663,10 +652,15 @@ func esc(e *EscState, n *Node, up *Node) {
 
 		n.Left.Sym.Label = nil
 
-		// Everything but fixed array is a dereference.
 	case ORANGE:
 		if n.List != nil && n.List.Next != nil {
-			if Isfixedarray(n.Type) {
+			// Everything but fixed array is a dereference.
+
+			// If fixed array is really the address of fixed array,
+			// it is also a dereference, because it is implicitly
+			// dereferenced (see #12588)
+			if Isfixedarray(n.Type) &&
+				!(Isptr[n.Right.Type.Etype] && Eqtype(n.Right.Type.Type, n.Type)) {
 				escassign(e, n.List.Next.N, n.Right)
 			} else {
 				escassignDereference(e, n.List.Next.N, n.Right)
@@ -766,7 +760,7 @@ func esc(e *EscState, n *Node, up *Node) {
 			escassign(e, ll.N, lr.N)
 		}
 		if lr != nil || ll != nil {
-			Fatal("esc oas2func")
+			Fatalf("esc oas2func")
 		}
 
 	case ORETURN:
@@ -787,7 +781,7 @@ func esc(e *EscState, n *Node, up *Node) {
 		}
 
 		if ll != nil {
-			Fatal("esc return list")
+			Fatalf("esc return list")
 		}
 
 		// Argument could leak through recover.
@@ -863,7 +857,7 @@ func esc(e *EscState, n *Node, up *Node) {
 		var v *Node
 		for ll := n.Func.Cvars; ll != nil; ll = ll.Next {
 			v = ll.N
-			if v.Op == OXXX { // unnamed out argument; see dcl.c:/^funcargs
+			if v.Op == OXXX { // unnamed out argument; see dcl.go:/^funcargs
 				continue
 			}
 			a = v.Name.Param.Closure
@@ -949,7 +943,7 @@ func escassign(e *EscState, dst *Node, src *Node) {
 	switch dst.Op {
 	default:
 		Dump("dst", dst)
-		Fatal("escassign: unexpected dst")
+		Fatalf("escassign: unexpected dst")
 
 	case OARRAYLIT,
 		OCLOSURE,
@@ -959,6 +953,7 @@ func escassign(e *EscState, dst *Node, src *Node) {
 		OMAPLIT,
 		OSTRUCTLIT,
 		OPTRLIT,
+		ODDDARG,
 		OCALLPART:
 		break
 
@@ -1112,7 +1107,7 @@ func mktag(mask int) *string {
 		break
 
 	default:
-		Fatal("escape mktag")
+		Fatalf("escape mktag")
 	}
 
 	if mask < len(tags) && tags[mask] != "" {
@@ -1131,7 +1126,8 @@ func parsetag(note *string) uint16 {
 	if note == nil || !strings.HasPrefix(*note, "esc:") {
 		return EscUnknown
 	}
-	em := uint16(atoi((*note)[4:]))
+	n, _ := strconv.ParseInt((*note)[4:], 0, 0)
+	em := uint16(n)
 	if em == 0 {
 		return EscNone
 	}
@@ -1239,7 +1235,7 @@ func escassignfromtag(e *EscState, note *string, dsts *NodeList, src *Node) uint
 	// so there is no need to check here.
 
 	if em != 0 && dsts == nil {
-		Fatal("corrupt esc tag %q or messed up escretval list\n", note)
+		Fatalf("corrupt esc tag %q or messed up escretval list\n", note)
 	}
 	return em0
 }
@@ -1334,7 +1330,7 @@ func esccall(e *EscState, n *Node, up *Node) {
 	var fn *Node
 	switch n.Op {
 	default:
-		Fatal("esccall")
+		Fatalf("esccall")
 
 	case OCALLFUNC:
 		fn = n.Left
@@ -1357,7 +1353,7 @@ func esccall(e *EscState, n *Node, up *Node) {
 	ll := n.List
 	if n.List != nil && n.List.Next == nil {
 		a := n.List.N
-		if a.Type.Etype == TSTRUCT && a.Type.Funarg != 0 { // f(g()).
+		if a.Type.Etype == TSTRUCT && a.Type.Funarg { // f(g()).
 			ll = e.nodeEscState(a).Escretval
 		}
 	}
@@ -1394,7 +1390,7 @@ func esccall(e *EscState, n *Node, up *Node) {
 		// function in same mutually recursive group.  Incorporate into flow graph.
 		//		print("esc local fn: %N\n", fn->ntype);
 		if fn.Name.Defn.Esc == EscFuncUnknown || nE.Escretval != nil {
-			Fatal("graph inconsistency")
+			Fatalf("graph inconsistency")
 		}
 
 		// set up out list on this call node
@@ -1443,7 +1439,7 @@ func esccall(e *EscState, n *Node, up *Node) {
 
 	// Imported or completely analyzed function.  Use the escape tags.
 	if nE.Escretval != nil {
-		Fatal("esc already decorated call %v\n", Nconv(n, obj.FmtSign))
+		Fatalf("esc already decorated call %v\n", Nconv(n, obj.FmtSign))
 	}
 
 	if Debug['m'] > 2 {
@@ -1464,8 +1460,9 @@ func esccall(e *EscState, n *Node, up *Node) {
 		}
 	}
 
+	var src *Node
 	for t := getinargx(fntype).Type; ll != nil; ll = ll.Next {
-		src := ll.N
+		src = ll.N
 		if t.Isddd && !n.Isddd {
 			// Introduce ODDDARG node to represent ... allocation.
 			src = Nod(ODDDARG, nil, nil)
@@ -1506,17 +1503,17 @@ func esccall(e *EscState, n *Node, up *Node) {
 		}
 
 		if src != ll.N {
+			// This occurs when function parameter type Isddd and n not Isddd
 			break
 		}
 		t = t.Down
 	}
 
-	// "..." arguments are untracked
 	for ; ll != nil; ll = ll.Next {
-		escassign(e, &e.theSink, ll.N)
 		if Debug['m'] > 2 {
-			fmt.Printf("%v::esccall:: ... <- %v, untracked\n", Ctxt.Line(int(lineno)), Nconv(ll.N, obj.FmtShort))
+			fmt.Printf("%v::esccall:: ... <- %v\n", Ctxt.Line(int(lineno)), Nconv(ll.N, obj.FmtShort))
 		}
+		escassign(e, src, ll.N) // args to slice
 	}
 }
 
@@ -1583,7 +1580,13 @@ func funcOutputAndInput(dst, src *Node) bool {
 		src.Op == ONAME && src.Class == PPARAM && src.Name.Curfn == dst.Name.Curfn
 }
 
+const NOTALOOPDEPTH = -1
+
 func escwalk(e *EscState, level Level, dst *Node, src *Node) {
+	escwalkBody(e, level, dst, src, NOTALOOPDEPTH)
+}
+
+func escwalkBody(e *EscState, level Level, dst *Node, src *Node, extraloopdepth int32) {
 	if src.Op == OLITERAL {
 		return
 	}
@@ -1594,16 +1597,29 @@ func escwalk(e *EscState, level Level, dst *Node, src *Node) {
 		// convergence.
 		level = level.min(srcE.Esclevel)
 		if level == srcE.Esclevel {
-			return
+			// Have we been here already with an extraloopdepth,
+			// or is the extraloopdepth provided no improvement on
+			// what's already been seen?
+			if srcE.Maxextraloopdepth >= extraloopdepth || srcE.Escloopdepth >= extraloopdepth {
+				return
+			}
+			srcE.Maxextraloopdepth = extraloopdepth
 		}
+	} else { // srcE.Walkgen < e.walkgen -- first time, reset this.
+		srcE.Maxextraloopdepth = NOTALOOPDEPTH
 	}
 
 	srcE.Walkgen = e.walkgen
 	srcE.Esclevel = level
+	modSrcLoopdepth := srcE.Escloopdepth
+
+	if extraloopdepth > modSrcLoopdepth {
+		modSrcLoopdepth = extraloopdepth
+	}
 
 	if Debug['m'] > 1 {
-		fmt.Printf("escwalk: level:%d depth:%d %.*s op=%v %v(%v) scope:%v[%d]\n",
-			level, e.pdepth, e.pdepth, "\t\t\t\t\t\t\t\t\t\t", Oconv(int(src.Op), 0), Nconv(src, obj.FmtShort), Jconv(src, obj.FmtShort), e.curfnSym(src), srcE.Escloopdepth)
+		fmt.Printf("escwalk: level:%d depth:%d %.*s op=%v %v(%v) scope:%v[%d] extraloopdepth=%v\n",
+			level, e.pdepth, e.pdepth, "\t\t\t\t\t\t\t\t\t\t", Oconv(int(src.Op), 0), Nconv(src, obj.FmtShort), Jconv(src, obj.FmtShort), e.curfnSym(src), srcE.Escloopdepth, extraloopdepth)
 	}
 
 	e.pdepth++
@@ -1642,7 +1658,7 @@ func escwalk(e *EscState, level Level, dst *Node, src *Node) {
 		}
 	}
 
-	leaks = level.int() <= 0 && level.guaranteedDereference() <= 0 && dstE.Escloopdepth < srcE.Escloopdepth
+	leaks = level.int() <= 0 && level.guaranteedDereference() <= 0 && dstE.Escloopdepth < modSrcLoopdepth
 
 	switch src.Op {
 	case ONAME:
@@ -1654,7 +1670,7 @@ func escwalk(e *EscState, level Level, dst *Node, src *Node) {
 						Warnl(int(src.Lineno), "leaking param content: %v", Nconv(src, obj.FmtShort))
 					} else {
 						Warnl(int(src.Lineno), "leaking param content: %v level=%v dst.eld=%v src.eld=%v dst=%v",
-							Nconv(src, obj.FmtShort), level, dstE.Escloopdepth, srcE.Escloopdepth, Nconv(dst, obj.FmtShort))
+							Nconv(src, obj.FmtShort), level, dstE.Escloopdepth, modSrcLoopdepth, Nconv(dst, obj.FmtShort))
 					}
 				}
 			} else {
@@ -1664,7 +1680,7 @@ func escwalk(e *EscState, level Level, dst *Node, src *Node) {
 						Warnl(int(src.Lineno), "leaking param: %v", Nconv(src, obj.FmtShort))
 					} else {
 						Warnl(int(src.Lineno), "leaking param: %v level=%v dst.eld=%v src.eld=%v dst=%v",
-							Nconv(src, obj.FmtShort), level, dstE.Escloopdepth, srcE.Escloopdepth, Nconv(dst, obj.FmtShort))
+							Nconv(src, obj.FmtShort), level, dstE.Escloopdepth, modSrcLoopdepth, Nconv(dst, obj.FmtShort))
 					}
 				}
 			}
@@ -1690,18 +1706,31 @@ func escwalk(e *EscState, level Level, dst *Node, src *Node) {
 				}
 				if Debug['m'] > 1 {
 					Warnl(int(src.Lineno), "%v escapes to heap, level=%v, dst.eld=%v, src.eld=%v",
-						Nconv(p, obj.FmtShort), level, dstE.Escloopdepth, srcE.Escloopdepth)
+						Nconv(p, obj.FmtShort), level, dstE.Escloopdepth, modSrcLoopdepth)
 				} else {
 					Warnl(int(src.Lineno), "%v escapes to heap", Nconv(p, obj.FmtShort))
 				}
 			}
+			escwalkBody(e, level.dec(), dst, src.Left, modSrcLoopdepth)
+			extraloopdepth = modSrcLoopdepth // passes to recursive case, seems likely a no-op
+		} else {
+			escwalk(e, level.dec(), dst, src.Left)
 		}
 
-		escwalk(e, level.dec(), dst, src.Left)
-
 	case OAPPEND:
 		escwalk(e, level, dst, src.List.N)
 
+	case ODDDARG:
+		if leaks {
+			src.Esc = EscHeap
+			if Debug['m'] != 0 {
+				Warnl(int(src.Lineno), "%v escapes to heap", Nconv(src, obj.FmtShort))
+			}
+			extraloopdepth = modSrcLoopdepth
+		}
+		// similar to a slice arraylit and its args.
+		level = level.dec()
+
 	case OARRAYLIT:
 		if Isfixedarray(src.Type) {
 			break
@@ -1712,8 +1741,7 @@ func escwalk(e *EscState, level Level, dst *Node, src *Node) {
 
 		fallthrough
 
-	case ODDDARG,
-		OMAKECHAN,
+	case OMAKECHAN,
 		OMAKEMAP,
 		OMAKESLICE,
 		OARRAYRUNESTR,
@@ -1732,6 +1760,7 @@ func escwalk(e *EscState, level Level, dst *Node, src *Node) {
 			if Debug['m'] != 0 {
 				Warnl(int(src.Lineno), "%v escapes to heap", Nconv(src, obj.FmtShort))
 			}
+			extraloopdepth = modSrcLoopdepth
 		}
 
 	case ODOT,
@@ -1773,12 +1802,19 @@ func escwalk(e *EscState, level Level, dst *Node, src *Node) {
 recurse:
 	level = level.copy()
 	for ll := srcE.Escflowsrc; ll != nil; ll = ll.Next {
-		escwalk(e, level, dst, ll.N)
+		escwalkBody(e, level, dst, ll.N, extraloopdepth)
 	}
 
 	e.pdepth--
 }
 
+// This special tag is applied to uintptr variables
+// that we believe may hold unsafe.Pointers for
+// calls into assembly functions.
+// It is logically a constant, but using a var
+// lets us take the address below to get a *string.
+var unsafeUintptrTag = "unsafe-uintptr"
+
 func esctag(e *EscState, func_ *Node) {
 	func_.Esc = EscFuncTagged
 
@@ -1793,6 +1829,29 @@ func esctag(e *EscState, func_ *Node) {
 			}
 		}
 
+		// Assume that uintptr arguments must be held live across the call.
+		// This is most important for syscall.Syscall.
+		// See golang.org/issue/13372.
+		// This really doesn't have much to do with escape analysis per se,
+		// but we are reusing the ability to annotate an individual function
+		// argument and pass those annotations along to importing code.
+		narg := 0
+		for t := getinargx(func_.Type).Type; t != nil; t = t.Down {
+			narg++
+			if t.Type.Etype == TUINTPTR {
+				if Debug['m'] != 0 {
+					var name string
+					if t.Sym != nil {
+						name = t.Sym.Name
+					} else {
+						name = fmt.Sprintf("arg#%d", narg)
+					}
+					Warnl(int(func_.Lineno), "%v assuming %v is unsafe uintptr", funcSym(func_), name)
+				}
+				t.Note = &unsafeUintptrTag
+			}
+		}
+
 		return
 	}
 
diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go
index 66ae881..e50cf38 100644
--- a/src/cmd/compile/internal/gc/export.go
+++ b/src/cmd/compile/internal/gc/export.go
@@ -5,6 +5,7 @@
 package gc
 
 import (
+	"bytes"
 	"cmd/internal/obj"
 	"fmt"
 	"sort"
@@ -12,6 +13,20 @@ import (
 	"unicode/utf8"
 )
 
+var (
+	newexport    int // if set, use new export format
+	Debug_export int // if set, print debugging information about export data
+	exportsize   int
+)
+
+func exportf(format string, args ...interface{}) {
+	n, _ := fmt.Fprintf(bout, format, args...)
+	exportsize += n
+	if Debug_export != 0 {
+		fmt.Printf(format, args...)
+	}
+}
+
 var asmlist *NodeList
 
 // Mark n's symbol as exported
@@ -31,12 +46,12 @@ func exportsym(n *Node) {
 	if Debug['E'] != 0 {
 		fmt.Printf("export symbol %v\n", n.Sym)
 	}
-	exportlist = list(exportlist, n)
+	exportlist = append(exportlist, n)
 }
 
 func exportname(s string) bool {
-	if s[0] < utf8.RuneSelf {
-		return 'A' <= s[0] && s[0] <= 'Z'
+	if r := s[0]; r < utf8.RuneSelf {
+		return 'A' <= r && r <= 'Z'
 	}
 	r, _ := utf8.DecodeRuneInString(s)
 	return unicode.IsUpper(r)
@@ -57,7 +72,7 @@ func exportedsym(sym *Sym) bool {
 	return sym.Pkg == localpkg && exportname(sym.Name)
 }
 
-func autoexport(n *Node, ctxt uint8) {
+func autoexport(n *Node, ctxt Class) {
 	if n == nil || n.Sym == nil {
 		return
 	}
@@ -79,15 +94,15 @@ func autoexport(n *Node, ctxt uint8) {
 }
 
 func dumppkg(p *Pkg) {
-	if p == nil || p == localpkg || p.Exported != 0 || p == builtinpkg {
+	if p == nil || p == localpkg || p.Exported || p == builtinpkg {
 		return
 	}
-	p.Exported = 1
+	p.Exported = true
 	suffix := ""
-	if p.Direct == 0 {
+	if !p.Direct {
 		suffix = " // indirect"
 	}
-	fmt.Fprintf(bout, "\timport %s %q%s\n", p.Name, p.Path, suffix)
+	exportf("\timport %s %q%s\n", p.Name, p.Path, suffix)
 }
 
 // Look for anything we need for the inline body
@@ -124,11 +139,11 @@ func reexportdep(n *Node) {
 				if Debug['E'] != 0 {
 					fmt.Printf("reexport name %v\n", n.Sym)
 				}
-				exportlist = list(exportlist, n)
+				exportlist = append(exportlist, n)
 			}
 		}
 
-		// Local variables in the bodies need their type.
+	// Local variables in the bodies need their type.
 	case ODCL:
 		t := n.Left.Type
 
@@ -140,7 +155,7 @@ func reexportdep(n *Node) {
 				if Debug['E'] != 0 {
 					fmt.Printf("reexport type %v from declaration\n", t.Sym)
 				}
-				exportlist = list(exportlist, t.Sym.Def)
+				exportlist = append(exportlist, t.Sym.Def)
 			}
 		}
 
@@ -154,7 +169,7 @@ func reexportdep(n *Node) {
 				if Debug['E'] != 0 {
 					fmt.Printf("reexport literal type %v\n", t.Sym)
 				}
-				exportlist = list(exportlist, t.Sym.Def)
+				exportlist = append(exportlist, t.Sym.Def)
 			}
 		}
 		fallthrough
@@ -164,10 +179,10 @@ func reexportdep(n *Node) {
 			if Debug['E'] != 0 {
 				fmt.Printf("reexport literal/type %v\n", n.Sym)
 			}
-			exportlist = list(exportlist, n)
+			exportlist = append(exportlist, n)
 		}
 
-		// for operations that need a type when rendered, put the type on the export list.
+	// for operations that need a type when rendered, put the type on the export list.
 	case OCONV,
 		OCONVIFACE,
 		OCONVNOP,
@@ -193,7 +208,7 @@ func reexportdep(n *Node) {
 			if Debug['E'] != 0 {
 				fmt.Printf("reexport type for expression %v\n", t.Sym)
 			}
-			exportlist = list(exportlist, t.Sym.Def)
+			exportlist = append(exportlist, t.Sym.Def)
 		}
 	}
 
@@ -209,16 +224,16 @@ func dumpexportconst(s *Sym) {
 	n := s.Def
 	typecheck(&n, Erv)
 	if n == nil || n.Op != OLITERAL {
-		Fatal("dumpexportconst: oconst nil: %v", s)
+		Fatalf("dumpexportconst: oconst nil: %v", s)
 	}
 
 	t := n.Type // may or may not be specified
 	dumpexporttype(t)
 
 	if t != nil && !isideal(t) {
-		fmt.Fprintf(bout, "\tconst %v %v = %v\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtSharp), Vconv(n.Val(), obj.FmtSharp))
+		exportf("\tconst %v %v = %v\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtSharp), Vconv(n.Val(), obj.FmtSharp))
 	} else {
-		fmt.Fprintf(bout, "\tconst %v = %v\n", Sconv(s, obj.FmtSharp), Vconv(n.Val(), obj.FmtSharp))
+		exportf("\tconst %v = %v\n", Sconv(s, obj.FmtSharp), Vconv(n.Val(), obj.FmtSharp))
 	}
 }
 
@@ -242,41 +257,32 @@ func dumpexportvar(s *Sym) {
 			}
 
 			// NOTE: The space after %#S here is necessary for ld's export data parser.
-			fmt.Fprintf(bout, "\tfunc %v %v { %v }\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtShort|obj.FmtSharp), Hconv(n.Func.Inl, obj.FmtSharp))
+			exportf("\tfunc %v %v { %v }\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtShort|obj.FmtSharp), Hconv(n.Func.Inl, obj.FmtSharp|obj.FmtBody))
 
 			reexportdeplist(n.Func.Inl)
 		} else {
-			fmt.Fprintf(bout, "\tfunc %v %v\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtShort|obj.FmtSharp))
+			exportf("\tfunc %v %v\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtShort|obj.FmtSharp))
 		}
 	} else {
-		fmt.Fprintf(bout, "\tvar %v %v\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtSharp))
+		exportf("\tvar %v %v\n", Sconv(s, obj.FmtSharp), Tconv(t, obj.FmtSharp))
 	}
 }
 
+// methodbyname sorts types by symbol name.
 type methodbyname []*Type
 
-func (x methodbyname) Len() int {
-	return len(x)
-}
-
-func (x methodbyname) Swap(i, j int) {
-	x[i], x[j] = x[j], x[i]
-}
-
-func (x methodbyname) Less(i, j int) bool {
-	a := x[i]
-	b := x[j]
-	return stringsCompare(a.Sym.Name, b.Sym.Name) < 0
-}
+func (x methodbyname) Len() int           { return len(x) }
+func (x methodbyname) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
+func (x methodbyname) Less(i, j int) bool { return x[i].Sym.Name < x[j].Sym.Name }
 
 func dumpexporttype(t *Type) {
 	if t == nil {
 		return
 	}
-	if t.Printed != 0 || t == Types[t.Etype] || t == bytetype || t == runetype || t == errortype {
+	if t.Printed || t == Types[t.Etype] || t == bytetype || t == runetype || t == errortype {
 		return
 	}
-	t.Printed = 1
+	t.Printed = true
 
 	if t.Sym != nil && t.Etype != TFIELD {
 		dumppkg(t.Sym.Pkg)
@@ -289,26 +295,17 @@ func dumpexporttype(t *Type) {
 		return
 	}
 
-	n := 0
+	var m []*Type
 	for f := t.Method; f != nil; f = f.Down {
 		dumpexporttype(f)
-		n++
+		m = append(m, f)
 	}
+	sort.Sort(methodbyname(m))
 
-	m := make([]*Type, n)
-	i := 0
-	for f := t.Method; f != nil; f = f.Down {
-		m[i] = f
-		i++
-	}
-	sort.Sort(methodbyname(m[:n]))
-
-	fmt.Fprintf(bout, "\ttype %v %v\n", Sconv(t.Sym, obj.FmtSharp), Tconv(t, obj.FmtSharp|obj.FmtLong))
-	var f *Type
-	for i := 0; i < n; i++ {
-		f = m[i]
+	exportf("\ttype %v %v\n", Sconv(t.Sym, obj.FmtSharp), Tconv(t, obj.FmtSharp|obj.FmtLong))
+	for _, f := range m {
 		if f.Nointerface {
-			fmt.Fprintf(bout, "\t//go:nointerface\n")
+			exportf("\t//go:nointerface\n")
 		}
 		if f.Type.Nname != nil && f.Type.Nname.Func.Inl != nil { // nname was set by caninl
 
@@ -317,10 +314,10 @@ func dumpexporttype(t *Type) {
 			if Debug['l'] < 2 {
 				typecheckinl(f.Type.Nname)
 			}
-			fmt.Fprintf(bout, "\tfunc (%v) %v %v { %v }\n", Tconv(getthisx(f.Type).Type, obj.FmtSharp), Sconv(f.Sym, obj.FmtShort|obj.FmtByte|obj.FmtSharp), Tconv(f.Type, obj.FmtShort|obj.FmtSharp), Hconv(f.Type.Nname.Func.Inl, obj.FmtSharp))
+			exportf("\tfunc (%v) %v %v { %v }\n", Tconv(getthisx(f.Type).Type, obj.FmtSharp), Sconv(f.Sym, obj.FmtShort|obj.FmtByte|obj.FmtSharp), Tconv(f.Type, obj.FmtShort|obj.FmtSharp), Hconv(f.Type.Nname.Func.Inl, obj.FmtSharp))
 			reexportdeplist(f.Type.Nname.Func.Inl)
 		} else {
-			fmt.Fprintf(bout, "\tfunc (%v) %v %v\n", Tconv(getthisx(f.Type).Type, obj.FmtSharp), Sconv(f.Sym, obj.FmtShort|obj.FmtByte|obj.FmtSharp), Tconv(f.Type, obj.FmtShort|obj.FmtSharp))
+			exportf("\tfunc (%v) %v %v\n", Tconv(getthisx(f.Type).Type, obj.FmtSharp), Sconv(f.Sym, obj.FmtShort|obj.FmtByte|obj.FmtSharp), Tconv(f.Type, obj.FmtShort|obj.FmtSharp))
 		}
 	}
 }
@@ -359,41 +356,86 @@ func dumpsym(s *Sym) {
 }
 
 func dumpexport() {
-	lno := lineno
-
 	if buildid != "" {
-		fmt.Fprintf(bout, "build id %q\n", buildid)
-	}
-	fmt.Fprintf(bout, "\n$$\npackage %s", localpkg.Name)
-	if safemode != 0 {
-		fmt.Fprintf(bout, " safe")
-	}
-	fmt.Fprintf(bout, "\n")
+		exportf("build id %q\n", buildid)
+	}
+
+	size := 0 // size of export section without enclosing markers
+	if forceNewExport || newexport != 0 {
+		// binary export
+		// The linker also looks for the $$ marker - use char after $$ to distinguish format.
+		exportf("\n$$B\n")        // indicate binary format
+		const verifyExport = true // enable to check format changes
+		if verifyExport {
+			// save a copy of the export data
+			var copy bytes.Buffer
+			bcopy := obj.Binitw(&copy)
+			size = Export(bcopy, Debug_export != 0)
+			bcopy.Flush() // flushing to bytes.Buffer cannot fail
+			if n, err := bout.Write(copy.Bytes()); n != size || err != nil {
+				Fatalf("error writing export data: got %d bytes, want %d bytes, err = %v", n, size, err)
+			}
+			// export data must contain no '$' so that we can find the end by searching for "$$"
+			if bytes.IndexByte(copy.Bytes(), '$') >= 0 {
+				Fatalf("export data contains $")
+			}
 
-	for _, p := range pkgs {
-		if p.Direct != 0 {
-			dumppkg(p)
+			// verify that we can read the copied export data back in
+			// (use empty package map to avoid collisions)
+			savedPkgMap := pkgMap
+			savedPkgs := pkgs
+			pkgMap = make(map[string]*Pkg)
+			pkgs = nil
+			importpkg = mkpkg("")
+			Import(obj.Binitr(&copy)) // must not die
+			importpkg = nil
+			pkgs = savedPkgs
+			pkgMap = savedPkgMap
+		} else {
+			size = Export(bout, Debug_export != 0)
+		}
+		exportf("\n$$\n")
+	} else {
+		// textual export
+		lno := lineno
+
+		exportf("\n$$\n") // indicate textual format
+		exportsize = 0
+		exportf("package %s", localpkg.Name)
+		if safemode != 0 {
+			exportf(" safe")
+		}
+		exportf("\n")
+
+		for _, p := range pkgs {
+			if p.Direct {
+				dumppkg(p)
+			}
 		}
-	}
 
-	for l := exportlist; l != nil; l = l.Next {
-		lineno = l.N.Lineno
-		dumpsym(l.N.Sym)
+		// exportlist grows during iteration - cannot use range
+		for len(exportlist) > 0 {
+			n := exportlist[0]
+			exportlist = exportlist[1:]
+			lineno = n.Lineno
+			dumpsym(n.Sym)
+		}
+
+		size = exportsize
+		exportf("\n$$\n")
+		lineno = lno
 	}
 
-	fmt.Fprintf(bout, "\n$$\n")
-	lineno = lno
+	if Debug_export != 0 {
+		fmt.Printf("export data size = %d bytes\n", size)
+	}
 }
 
-/*
- * import
- */
+// import
 
-/*
- * return the sym for ss, which should match lexical
- */
-func importsym(s *Sym, op int) *Sym {
-	if s.Def != nil && int(s.Def.Op) != op {
+// return the sym for ss, which should match lexical
+func importsym(s *Sym, op Op) *Sym {
+	if s.Def != nil && s.Def.Op != op {
 		pkgstr := fmt.Sprintf("during import %q", importpkg.Path)
 		redeclare(s, pkgstr)
 	}
@@ -410,9 +452,7 @@ func importsym(s *Sym, op int) *Sym {
 	return s
 }
 
-/*
- * return the type pkg.name, forward declaring if needed
- */
+// return the type pkg.name, forward declaring if needed
 func pkgtype(s *Sym) *Type {
 	importsym(s, OTYPE)
 	if s.Def == nil || s.Def.Op != OTYPE {
@@ -529,7 +569,7 @@ func dumpasmhdr() {
 
 	b, err := obj.Bopenw(asmhdr)
 	if err != nil {
-		Fatal("%v", err)
+		Fatalf("%v", err)
 	}
 	fmt.Fprintf(b, "// generated by %cg -asmhdr from package %s\n\n", Thearch.Thechar, localpkg.Name)
 	var n *Node
@@ -545,7 +585,7 @@ func dumpasmhdr() {
 
 		case OTYPE:
 			t = n.Type
-			if t.Etype != TSTRUCT || t.Map != nil || t.Funarg != 0 {
+			if t.Etype != TSTRUCT || t.Map != nil || t.Funarg {
 				break
 			}
 			fmt.Fprintf(b, "#define %s__size %d\n", t.Sym.Name, int(t.Width))
diff --git a/src/cmd/compile/internal/gc/float_test.go b/src/cmd/compile/internal/gc/float_test.go
new file mode 100644
index 0000000..c761e96
--- /dev/null
+++ b/src/cmd/compile/internal/gc/float_test.go
@@ -0,0 +1,102 @@
+// 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
+
+import "testing"
+
+// For GO386=387, make sure fucomi* opcodes are not used
+// for comparison operations.
+// Note that this test will fail only on a Pentium MMX
+// processor (with GOARCH=386 GO386=387), as it just runs
+// some code and looks for an unimplemented instruction fault.
+
+//go:noinline
+func compare1(a, b float64) bool {
+	return a < b
+}
+
+//go:noinline
+func compare2(a, b float32) bool {
+	return a < b
+}
+
+func TestFloatCompare(t *testing.T) {
+	if !compare1(3, 5) {
+		t.Errorf("compare1 returned false")
+	}
+	if !compare2(3, 5) {
+		t.Errorf("compare2 returned false")
+	}
+}
+
+// For GO386=387, make sure fucomi* opcodes are not used
+// for float->int conversions.
+
+//go:noinline
+func cvt1(a float64) uint64 {
+	return uint64(a)
+}
+
+//go:noinline
+func cvt2(a float64) uint32 {
+	return uint32(a)
+}
+
+//go:noinline
+func cvt3(a float32) uint64 {
+	return uint64(a)
+}
+
+//go:noinline
+func cvt4(a float32) uint32 {
+	return uint32(a)
+}
+
+//go:noinline
+func cvt5(a float64) int64 {
+	return int64(a)
+}
+
+//go:noinline
+func cvt6(a float64) int32 {
+	return int32(a)
+}
+
+//go:noinline
+func cvt7(a float32) int64 {
+	return int64(a)
+}
+
+//go:noinline
+func cvt8(a float32) int32 {
+	return int32(a)
+}
+
+func TestFloatConvert(t *testing.T) {
+	if got := cvt1(3.5); got != 3 {
+		t.Errorf("cvt1 got %d, wanted 3", got)
+	}
+	if got := cvt2(3.5); got != 3 {
+		t.Errorf("cvt2 got %d, wanted 3", got)
+	}
+	if got := cvt3(3.5); got != 3 {
+		t.Errorf("cvt3 got %d, wanted 3", got)
+	}
+	if got := cvt4(3.5); got != 3 {
+		t.Errorf("cvt4 got %d, wanted 3", got)
+	}
+	if got := cvt5(3.5); got != 3 {
+		t.Errorf("cvt5 got %d, wanted 3", got)
+	}
+	if got := cvt6(3.5); got != 3 {
+		t.Errorf("cvt6 got %d, wanted 3", got)
+	}
+	if got := cvt7(3.5); got != 3 {
+		t.Errorf("cvt7 got %d, wanted 3", got)
+	}
+	if got := cvt8(3.5); got != 3 {
+		t.Errorf("cvt8 got %d, wanted 3", got)
+	}
+}
diff --git a/src/cmd/compile/internal/gc/fmt.go b/src/cmd/compile/internal/gc/fmt.go
index b40014b..d00e5a6 100644
--- a/src/cmd/compile/internal/gc/fmt.go
+++ b/src/cmd/compile/internal/gc/fmt.go
@@ -47,9 +47,9 @@ import (
 //		Flags: those of %N
 //			','  separate items with ',' instead of ';'
 //
-//   In mparith1.c:
-//      %B Mpint*	Big integers
-//	%F Mpflt*	Big floats
+//   In mparith2.go and mparith3.go:
+//		%B Mpint*	Big integers
+//		%F Mpflt*	Big floats
 //
 //   %S, %T and %N obey use the following flags to set the format mode:
 const (
@@ -63,6 +63,8 @@ var fmtmode int = FErr
 
 var fmtpkgpfx int // %uT stickyness
 
+var fmtbody bool
+
 //
 // E.g. for %S:	%+S %#S %-S	print an identifier properly qualified for debug/export/internal mode.
 //
@@ -87,8 +89,9 @@ var fmtpkgpfx int // %uT stickyness
 //	%-uT		type identifiers with package name instead of prefix (typesym, dcommontype, typehash)
 //
 
-func setfmode(flags *int) int {
-	fm := fmtmode
+func setfmode(flags *int) (fm int, fb bool) {
+	fm = fmtmode
+	fb = fmtbody
 	if *flags&obj.FmtSign != 0 {
 		fmtmode = FDbg
 	} else if *flags&obj.FmtSharp != 0 {
@@ -97,8 +100,12 @@ func setfmode(flags *int) int {
 		fmtmode = FTypeId
 	}
 
-	*flags &^= (obj.FmtSharp | obj.FmtLeft | obj.FmtSign)
-	return fm
+	if *flags&obj.FmtBody != 0 {
+		fmtbody = true
+	}
+
+	*flags &^= (obj.FmtSharp | obj.FmtLeft | obj.FmtSign | obj.FmtBody)
+	return
 }
 
 // Fmt "%L": Linenumbers
@@ -356,7 +363,7 @@ func Vconv(v Val, flag int) string {
 		return "nil"
 	}
 
-	return fmt.Sprintf("<ctype=%d>", v.Ctype)
+	return fmt.Sprintf("<ctype=%d>", v.Ctype())
 }
 
 /*
@@ -400,8 +407,8 @@ var etnames = []string{
 }
 
 // Fmt "%E": etype
-func Econv(et int, flag int) string {
-	if et >= 0 && et < len(etnames) && etnames[et] != "" {
+func Econv(et EType) string {
+	if int(et) < len(etnames) && etnames[et] != "" {
 		return etnames[et]
 	}
 	return fmt.Sprintf("E-%d", et)
@@ -412,7 +419,7 @@ func symfmt(s *Sym, flag int) string {
 	if s.Pkg != nil && flag&obj.FmtShort == 0 {
 		switch fmtmode {
 		case FErr: // This is for the user
-			if s.Pkg == localpkg {
+			if s.Pkg == builtinpkg || s.Pkg == localpkg {
 				return s.Name
 			}
 
@@ -433,7 +440,7 @@ func symfmt(s *Sym, flag int) string {
 
 		case FExp:
 			if s.Name != "" && s.Name[0] == '.' {
-				Fatal("exporting synthetic symbol %s", s.Name)
+				Fatalf("exporting synthetic symbol %s", s.Name)
 			}
 			if s.Pkg != builtinpkg {
 				return fmt.Sprintf("@%q.%s", s.Pkg.Path, s.Name)
@@ -536,7 +543,7 @@ func typefmt(t *Type, flag int) string {
 
 	if fmtmode == FDbg {
 		fmtmode = 0
-		str := Econv(int(t.Etype), 0) + "-" + typefmt(t, flag)
+		str := Econv(t.Etype) + "-" + typefmt(t, flag)
 		fmtmode = FDbg
 		return str
 	}
@@ -579,9 +586,14 @@ func typefmt(t *Type, flag int) string {
 		buf.WriteString("interface {")
 		for t1 := t.Type; t1 != nil; t1 = t1.Down {
 			buf.WriteString(" ")
-			if exportname(t1.Sym.Name) {
+			switch {
+			case t1.Sym == nil:
+				// Check first that a symbol is defined for this type.
+				// Wrong interface definitions may have types lacking a symbol.
+				break
+			case exportname(t1.Sym.Name):
 				buf.WriteString(Sconv(t1.Sym, obj.FmtShort))
-			} else {
+			default:
 				buf.WriteString(Sconv(t1.Sym, obj.FmtUnsigned))
 			}
 			buf.WriteString(Tconv(t1.Type, obj.FmtShort))
@@ -647,7 +659,7 @@ func typefmt(t *Type, flag int) string {
 		}
 
 		var buf bytes.Buffer
-		if t.Funarg != 0 {
+		if t.Funarg {
 			buf.WriteString("(")
 			if fmtmode == FTypeId || fmtmode == FErr { // no argument names on function signature, and no "noescape"/"nosplit" tags
 				for t1 := t.Type; t1 != nil; t1 = t1.Down {
@@ -704,7 +716,7 @@ func typefmt(t *Type, flag int) string {
 			}
 
 			if s != nil && t.Embedded == 0 {
-				if t.Funarg != 0 {
+				if t.Funarg {
 					name = Nconv(t.Nname, 0)
 				} else if flag&obj.FmtLong != 0 {
 					name = Sconv(s, obj.FmtShort|obj.FmtByte) // qualify non-exported names (used on structs, not on funarg)
@@ -713,7 +725,7 @@ func typefmt(t *Type, flag int) string {
 				}
 			} else if fmtmode == FExp {
 				// TODO(rsc) this breaks on the eliding of unused arguments in the backend
-				// when this is fixed, the special case in dcl.c checkarglist can go.
+				// when this is fixed, the special case in dcl.go checkarglist can go.
 				//if(t->funarg)
 				//	fmtstrcpy(fp, "_ ");
 				//else
@@ -736,7 +748,13 @@ func typefmt(t *Type, flag int) string {
 		if name != "" {
 			str = name + " " + typ
 		}
-		if flag&obj.FmtShort == 0 && t.Note != nil {
+
+		// The fmtbody flag is intended to suppress escape analysis annotations
+		// when printing a function type used in a function body.
+		// (The escape analysis tags do not apply to func vars.)
+		// But it must not suppress struct field tags.
+		// See golang.org/issue/13777 and golang.org/issue/14331.
+		if flag&obj.FmtShort == 0 && (!fmtbody || !t.Funarg) && t.Note != nil {
 			str += " " + strconv.Quote(*t.Note)
 		}
 		return str
@@ -755,15 +773,15 @@ func typefmt(t *Type, flag int) string {
 	}
 
 	if fmtmode == FExp {
-		Fatal("missing %v case during export", Econv(int(t.Etype), 0))
+		Fatalf("missing %v case during export", Econv(t.Etype))
 	}
 
 	// Don't know how to handle - fall back to detailed prints.
-	return fmt.Sprintf("%v <%v> %v", Econv(int(t.Etype), 0), t.Sym, t.Type)
+	return fmt.Sprintf("%v <%v> %v", Econv(t.Etype), t.Sym, t.Type)
 }
 
 // Statements which may be rendered with a simplestmt as init.
-func stmtwithinit(op int) bool {
+func stmtwithinit(op Op) bool {
 	switch op {
 	case OIF, OFOR, OSWITCH:
 		return true
@@ -781,13 +799,13 @@ func stmtfmt(n *Node) string {
 	// block starting with the init statements.
 
 	// if we can just say "for" n->ninit; ... then do so
-	simpleinit := n.Ninit != nil && n.Ninit.Next == nil && n.Ninit.N.Ninit == nil && stmtwithinit(int(n.Op))
+	simpleinit := n.Ninit != nil && n.Ninit.Next == nil && n.Ninit.N.Ninit == nil && stmtwithinit(n.Op)
 
 	// otherwise, print the inits as separate statements
 	complexinit := n.Ninit != nil && !simpleinit && (fmtmode != FErr)
 
 	// but if it was for if/for/switch, put in an extra surrounding block to limit the scope
-	extrablock := complexinit && stmtwithinit(int(n.Op))
+	extrablock := complexinit && stmtwithinit(n.Op)
 
 	if extrablock {
 		f += "{"
@@ -816,7 +834,7 @@ func stmtfmt(n *Node) string {
 			f += Nconv(n.Right, 0)
 		}
 
-		// Don't export "v = <N>" initializing statements, hope they're always
+	// Don't export "v = <N>" initializing statements, hope they're always
 	// preceded by the DCL which will be re-parsed and typecheck to reproduce
 	// the "v = <N>" again.
 	case OAS, OASWB:
@@ -832,7 +850,7 @@ func stmtfmt(n *Node) string {
 
 	case OASOP:
 		if n.Implicit {
-			if n.Etype == OADD {
+			if Op(n.Etype) == OADD {
 				f += fmt.Sprintf("%v++", n.Left)
 			} else {
 				f += fmt.Sprintf("%v--", n.Left)
@@ -1115,7 +1133,7 @@ func exprfmt(n *Node, prec int) string {
 		if n.Val().Ctype() == CTNIL && n.Orig != nil && n.Orig != n {
 			return exprfmt(n.Orig, prec)
 		}
-		if n.Type != nil && n.Type != Types[n.Type.Etype] && n.Type != idealbool && n.Type != idealstring {
+		if n.Type != nil && n.Type.Etype != TIDEAL && n.Type.Etype != TNIL && n.Type != idealbool && n.Type != idealstring {
 			// Need parens when type begins with what might
 			// be misinterpreted as a unary operator: * or <-.
 			if Isptr[n.Type.Etype] || (n.Type.Etype == TCHAN && n.Type.Chan == Crecv) {
@@ -1127,7 +1145,7 @@ func exprfmt(n *Node, prec int) string {
 
 		return Vconv(n.Val(), 0)
 
-		// Special case: name used as local variable in export.
+	// Special case: name used as local variable in export.
 	// _ becomes ~b%d internally; print as _ for export
 	case ONAME:
 		if (fmtmode == FExp || fmtmode == FErr) && n.Sym != nil && n.Sym.Name[0] == '~' && n.Sym.Name[1] == 'b' {
@@ -1149,7 +1167,6 @@ func exprfmt(n *Node, prec int) string {
 		}
 		fallthrough
 
-		//fallthrough
 	case OPACK, ONONAME:
 		return Sconv(n.Sym, 0)
 
@@ -1443,6 +1460,7 @@ func exprfmt(n *Node, prec int) string {
 	case OCMPSTR, OCMPIFACE:
 		var f string
 		f += exprfmt(n.Left, nprec)
+		// TODO(marvin): Fix Node.EType type union.
 		f += fmt.Sprintf(" %v ", Oconv(int(n.Etype), obj.FmtSharp))
 		f += exprfmt(n.Right, nprec+1)
 		return f
@@ -1594,12 +1612,11 @@ func Sconv(s *Sym, flag int) string {
 	}
 
 	sf := flag
-	sm := setfmode(&flag)
-	var r int
-	_ = r
+	sm, sb := setfmode(&flag)
 	str := symfmt(s, flag)
 	flag = sf
 	fmtmode = sm
+	fmtbody = sb
 	return str
 }
 
@@ -1622,7 +1639,7 @@ func Tconv(t *Type, flag int) string {
 
 	t.Trecur++
 	sf := flag
-	sm := setfmode(&flag)
+	sm, sb := setfmode(&flag)
 
 	if fmtmode == FTypeId && (sf&obj.FmtUnsigned != 0) {
 		fmtpkgpfx++
@@ -1631,8 +1648,6 @@ func Tconv(t *Type, flag int) string {
 		flag |= obj.FmtUnsigned
 	}
 
-	var r int
-	_ = r
 	str := typefmt(t, flag)
 
 	if fmtmode == FTypeId && (sf&obj.FmtUnsigned != 0) {
@@ -1640,6 +1655,7 @@ func Tconv(t *Type, flag int) string {
 	}
 
 	flag = sf
+	fmtbody = sb
 	fmtmode = sm
 	t.Trecur--
 	return str
@@ -1657,10 +1673,8 @@ func Nconv(n *Node, flag int) string {
 		return "<N>"
 	}
 	sf := flag
-	sm := setfmode(&flag)
+	sm, sb := setfmode(&flag)
 
-	var r int
-	_ = r
 	var str string
 	switch fmtmode {
 	case FErr, FExp:
@@ -1672,10 +1686,11 @@ func Nconv(n *Node, flag int) string {
 		dumpdepth--
 
 	default:
-		Fatal("unhandled %%N mode")
+		Fatalf("unhandled %%N mode")
 	}
 
 	flag = sf
+	fmtbody = sb
 	fmtmode = sm
 	return str
 }
@@ -1692,9 +1707,7 @@ func Hconv(l *NodeList, flag int) string {
 	}
 
 	sf := flag
-	sm := setfmode(&flag)
-	var r int
-	_ = r
+	sm, sb := setfmode(&flag)
 	sep := "; "
 	if fmtmode == FDbg {
 		sep = "\n"
@@ -1711,6 +1724,7 @@ func Hconv(l *NodeList, flag int) string {
 	}
 
 	flag = sf
+	fmtbody = sb
 	fmtmode = sm
 	return buf.String()
 }
diff --git a/src/cmd/compile/internal/gc/gen.go b/src/cmd/compile/internal/gc/gen.go
index 764895f..b756055 100644
--- a/src/cmd/compile/internal/gc/gen.go
+++ b/src/cmd/compile/internal/gc/gen.go
@@ -9,10 +9,8 @@ import (
 	"fmt"
 )
 
-/*
- * portable half of code generator.
- * mainly statements and control flow.
- */
+// portable half of code generator.
+// mainly statements and control flow.
 var labellist *Label
 
 var lastlabel *Label
@@ -62,7 +60,7 @@ func addrescapes(n *Node) {
 			n.Name.Param.Stackparam.Type = n.Type
 			n.Name.Param.Stackparam.Addable = true
 			if n.Xoffset == BADWIDTH {
-				Fatal("addrescapes before param assignment")
+				Fatalf("addrescapes before param assignment")
 			}
 			n.Name.Param.Stackparam.Xoffset = n.Xoffset
 			fallthrough
@@ -135,7 +133,7 @@ func newlab(n *Node) *Label {
 			lab.Def = n
 		}
 	} else {
-		lab.Use = list(lab.Use, n)
+		lab.Use = append(lab.Use, n)
 	}
 
 	return lab
@@ -211,22 +209,18 @@ func stmtlabel(n *Node) *Label {
 	return nil
 }
 
-/*
- * compile statements
- */
+// compile statements
 func Genlist(l *NodeList) {
 	for ; l != nil; l = l.Next {
 		gen(l.N)
 	}
 }
 
-/*
- * generate code to start new proc running call n.
- */
+// generate code to start new proc running call n.
 func cgen_proc(n *Node, proc int) {
 	switch n.Left.Op {
 	default:
-		Fatal("cgen_proc: unknown call %v", Oconv(int(n.Left.Op), 0))
+		Fatalf("cgen_proc: unknown call %v", Oconv(int(n.Left.Op), 0))
 
 	case OCALLMETH:
 		cgen_callmeth(n.Left, proc)
@@ -239,18 +233,16 @@ func cgen_proc(n *Node, proc int) {
 	}
 }
 
-/*
- * generate declaration.
- * have to allocate heap copy
- * for escaped variables.
- */
+// generate declaration.
+// have to allocate heap copy
+// for escaped variables.
 func cgen_dcl(n *Node) {
 	if Debug['g'] != 0 {
 		Dump("\ncgen-dcl", n)
 	}
 	if n.Op != ONAME {
 		Dump("cgen_dcl", n)
-		Fatal("cgen_dcl")
+		Fatalf("cgen_dcl")
 	}
 
 	if n.Class&PHEAP == 0 {
@@ -265,9 +257,7 @@ func cgen_dcl(n *Node) {
 	Cgen_as(n.Name.Heapaddr, prealloc[n])
 }
 
-/*
- * generate discard of value
- */
+// generate discard of value
 func cgen_discard(nr *Node) {
 	if nr == nil {
 		return
@@ -322,9 +312,7 @@ func cgen_discard(nr *Node) {
 	}
 }
 
-/*
- * clearslim generates code to zero a slim node.
- */
+// clearslim generates code to zero a slim node.
 func Clearslim(n *Node) {
 	var z Node
 	z.Op = OLITERAL
@@ -360,24 +348,20 @@ func Clearslim(n *Node) {
 		Mpmovecfix(z.Val().U.(*Mpint), 0)
 
 	default:
-		Fatal("clearslim called on type %v", n.Type)
+		Fatalf("clearslim called on type %v", n.Type)
 	}
 
 	ullmancalc(&z)
 	Cgen(&z, n)
 }
 
-/*
- * generate:
- *	res = iface{typ, data}
- * n->left is typ
- * n->right is data
- */
+// generate:
+//	res = iface{typ, data}
+// n->left is typ
+// n->right is data
 func Cgen_eface(n *Node, res *Node) {
-	/*
-	 * the right node of an eface may contain function calls that uses res as an argument,
-	 * so it's important that it is done first
-	 */
+	// the right node of an eface may contain function calls that uses res as an argument,
+	// so it's important that it is done first
 
 	tmp := temp(Types[Tptr])
 	Cgen(n.Right, tmp)
@@ -393,13 +377,11 @@ func Cgen_eface(n *Node, res *Node) {
 	Cgen(n.Left, &dst)
 }
 
-/*
- * generate one of:
- *	res, resok = x.(T)
- *	res = x.(T) (when resok == nil)
- * n.Left is x
- * n.Type is T
- */
+// generate one of:
+//	res, resok = x.(T)
+//	res = x.(T) (when resok == nil)
+// n.Left is x
+// n.Type is T
 func cgen_dottype(n *Node, res, resok *Node, wb bool) {
 	if Debug_typeassert > 0 {
 		Warn("type assertion inlined")
@@ -485,12 +467,10 @@ func cgen_dottype(n *Node, res, resok *Node, wb bool) {
 	}
 }
 
-/*
- * generate:
- *	res, resok = x.(T)
- * n.Left is x
- * n.Type is T
- */
+// generate:
+//	res, resok = x.(T)
+// n.Left is x
+// n.Type is T
 func Cgen_As2dottype(n, res, resok *Node) {
 	if Debug_typeassert > 0 {
 		Warn("type assertion inlined")
@@ -549,11 +529,9 @@ func Cgen_As2dottype(n, res, resok *Node) {
 	Patch(q, Pc)
 }
 
-/*
- * gather series of offsets
- * >=0 is direct addressed field
- * <0 is pointer to next field (+1)
- */
+// gather series of offsets
+// >=0 is direct addressed field
+// <0 is pointer to next field (+1)
 func Dotoffset(n *Node, oary []int64, nn **Node) int {
 	var i int
 
@@ -561,7 +539,7 @@ func Dotoffset(n *Node, oary []int64, nn **Node) int {
 	case ODOT:
 		if n.Xoffset == BADWIDTH {
 			Dump("bad width in dotoffset", n)
-			Fatal("bad width in dotoffset")
+			Fatalf("bad width in dotoffset")
 		}
 
 		i = Dotoffset(n.Left, oary, nn)
@@ -582,7 +560,7 @@ func Dotoffset(n *Node, oary []int64, nn **Node) int {
 	case ODOTPTR:
 		if n.Xoffset == BADWIDTH {
 			Dump("bad width in dotoffset", n)
-			Fatal("bad width in dotoffset")
+			Fatalf("bad width in dotoffset")
 		}
 
 		i = Dotoffset(n.Left, oary, nn)
@@ -602,12 +580,10 @@ func Dotoffset(n *Node, oary []int64, nn **Node) int {
 	return i
 }
 
-/*
- * make a new off the books
- */
+// make a new off the books
 func Tempname(nn *Node, t *Type) {
 	if Curfn == nil {
-		Fatal("no curfn for tempname")
+		Fatalf("no curfn for tempname")
 	}
 
 	if t == nil {
@@ -661,7 +637,7 @@ func gen(n *Node) {
 
 	switch n.Op {
 	default:
-		Fatal("gen: unknown op %v", Nconv(n, obj.FmtShort|obj.FmtSign))
+		Fatalf("gen: unknown op %v", Nconv(n, obj.FmtShort|obj.FmtSign))
 
 	case OCASE,
 		OFALL,
@@ -729,7 +705,7 @@ func gen(n *Node) {
 				break
 			}
 
-			lab.Used = 1
+			lab.Used = true
 			if lab.Breakpc == nil {
 				Yyerror("invalid break label %v", n.Left.Sym)
 				break
@@ -754,7 +730,7 @@ func gen(n *Node) {
 				break
 			}
 
-			lab.Used = 1
+			lab.Used = true
 			if lab.Continpc == nil {
 				Yyerror("invalid continue label %v", n.Left.Sym)
 				break
@@ -860,7 +836,7 @@ func gen(n *Node) {
 		Cgen_as_wb(n.Left, n.Right, true)
 
 	case OAS2DOTTYPE:
-		cgen_dottype(n.Rlist.N, n.List.N, n.List.Next.N, false)
+		cgen_dottype(n.Rlist.N, n.List.N, n.List.Next.N, needwritebarrier(n.List.N, n.Rlist.N))
 
 	case OCALLMETH:
 		cgen_callmeth(n, 0)
@@ -892,12 +868,15 @@ func gen(n *Node) {
 
 	case OVARKILL:
 		gvarkill(n.Left)
+
+	case OVARLIVE:
+		gvarlive(n.Left)
 	}
 
 ret:
 	if Anyregalloc() != wasregalloc {
 		Dump("node", n)
-		Fatal("registers left allocated")
+		Fatalf("registers left allocated")
 	}
 
 	lineno = lno
@@ -963,7 +942,7 @@ func cgen_callmeth(n *Node, proc int) {
 	l := n.Left
 
 	if l.Op != ODOTMETH {
-		Fatal("cgen_callmeth: not dotmethod: %v", l)
+		Fatalf("cgen_callmeth: not dotmethod: %v", l)
 	}
 
 	n2 := *n
@@ -986,26 +965,24 @@ func CgenTemp(n *Node) *Node {
 }
 
 func checklabels() {
-	var l *NodeList
-
 	for lab := labellist; lab != nil; lab = lab.Link {
 		if lab.Def == nil {
-			for l = lab.Use; l != nil; l = l.Next {
-				yyerrorl(int(l.N.Lineno), "label %v not defined", lab.Sym)
+			for _, n := range lab.Use {
+				yyerrorl(int(n.Lineno), "label %v not defined", lab.Sym)
 			}
 			continue
 		}
 
-		if lab.Use == nil && lab.Used == 0 {
+		if lab.Use == nil && !lab.Used {
 			yyerrorl(int(lab.Def.Lineno), "label %v defined and not used", lab.Sym)
 			continue
 		}
 
 		if lab.Gotopc != nil {
-			Fatal("label %v never resolved", lab.Sym)
+			Fatalf("label %v never resolved", lab.Sym)
 		}
-		for l = lab.Use; l != nil; l = l.Next {
-			checkgoto(l.N, lab.Def)
+		for _, n := range lab.Use {
+			checkgoto(n, lab.Def)
 		}
 	}
 }
@@ -1038,7 +1015,7 @@ func componentgen_wb(nr, nl *Node, wb bool) bool {
 	numPtr := 0
 	visitComponents(nl.Type, 0, func(t *Type, offset int64) bool {
 		n++
-		if int(Simtype[t.Etype]) == Tptr && t != itable {
+		if Simtype[t.Etype] == Tptr && t != itable {
 			numPtr++
 		}
 		return n <= maxMoves && (!wb || numPtr <= 1)
@@ -1136,7 +1113,7 @@ func componentgen_wb(nr, nl *Node, wb bool) bool {
 	nodr = *nr
 	if !cadable(nr) {
 		if nr.Ullman >= UINF && nodl.Op == OINDREG {
-			Fatal("miscompile")
+			Fatalf("miscompile")
 		}
 		Igen(nr, &nodr, nil)
 		defer Regfree(&nodr)
@@ -1155,9 +1132,9 @@ func componentgen_wb(nr, nl *Node, wb bool) bool {
 		ptrOffset int64
 	)
 	visitComponents(nl.Type, 0, func(t *Type, offset int64) bool {
-		if wb && int(Simtype[t.Etype]) == Tptr && t != itable {
+		if wb && Simtype[t.Etype] == Tptr && t != itable {
 			if ptrType != nil {
-				Fatal("componentgen_wb %v", Tconv(nl.Type, 0))
+				Fatalf("componentgen_wb %v", Tconv(nl.Type, 0))
 			}
 			ptrType = t
 			ptrOffset = offset
@@ -1197,7 +1174,7 @@ func visitComponents(t *Type, startOffset int64, f func(elem *Type, elemOffset i
 		// NOTE: Assuming little endian (signed top half at offset 4).
 		// We don't have any 32-bit big-endian systems.
 		if Thearch.Thechar != '5' && Thearch.Thechar != '8' {
-			Fatal("unknown 32-bit architecture")
+			Fatalf("unknown 32-bit architecture")
 		}
 		return f(Types[TUINT32], startOffset) &&
 			f(Types[TINT32], startOffset+4)
@@ -1220,7 +1197,6 @@ func visitComponents(t *Type, startOffset int64, f func(elem *Type, elemOffset i
 	case TINTER:
 		return f(itable, startOffset) &&
 			f(Ptrto(Types[TUINT8]), startOffset+int64(Widthptr))
-		return true
 
 	case TSTRING:
 		return f(Ptrto(Types[TUINT8]), startOffset) &&
@@ -1254,12 +1230,12 @@ func visitComponents(t *Type, startOffset int64, f func(elem *Type, elemOffset i
 			// in code introduced in CL 6932045 to fix issue #4518.
 			// But the test case in issue 4518 does not trigger this anymore,
 			// so maybe this complication is no longer needed.
-			Fatal("struct not at offset 0")
+			Fatalf("struct not at offset 0")
 		}
 
 		for field := t.Type; field != nil; field = field.Down {
 			if field.Etype != TFIELD {
-				Fatal("bad struct")
+				Fatalf("bad struct")
 			}
 			if !visitComponents(field.Type, startOffset+field.Width, f) {
 				return false
diff --git a/src/cmd/compile/internal/gc/global_test.go b/src/cmd/compile/internal/gc/global_test.go
new file mode 100644
index 0000000..6c388af
--- /dev/null
+++ b/src/cmd/compile/internal/gc/global_test.go
@@ -0,0 +1,64 @@
+// Copyright 2015 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
+
+import (
+	"bytes"
+	"internal/testenv"
+	"io/ioutil"
+	"log"
+	"os"
+	"os/exec"
+	"path"
+	"testing"
+)
+
+// Make sure "hello world" does not link in all the
+// fmt.scanf routines.  See issue 6853.
+func TestScanfRemoval(t *testing.T) {
+	testenv.MustHaveGoBuild(t)
+
+	// Make a directory to work in.
+	dir, err := ioutil.TempDir("", "issue6853a-")
+	if err != nil {
+		log.Fatalf("could not create directory: %v", err)
+	}
+	defer os.RemoveAll(dir)
+
+	// Create source.
+	src := path.Join(dir, "test.go")
+	f, err := os.Create(src)
+	if err != nil {
+		log.Fatalf("could not create source file: %v", err)
+	}
+	f.Write([]byte(`
+package main
+import "fmt"
+func main() {
+	fmt.Println("hello world")
+}
+`))
+	f.Close()
+
+	// Name of destination.
+	dst := path.Join(dir, "test")
+
+	// Compile source.
+	cmd := exec.Command("go", "build", "-o", dst, src)
+	out, err := cmd.CombinedOutput()
+	if err != nil {
+		log.Fatalf("could not build target: %v", err)
+	}
+
+	// Check destination to see if scanf code was included.
+	cmd = exec.Command("go", "tool", "nm", dst)
+	out, err = cmd.CombinedOutput()
+	if err != nil {
+		log.Fatalf("could not read target: %v", err)
+	}
+	if bytes.Index(out, []byte("scanInt")) != -1 {
+		log.Fatalf("scanf code not removed from helloworld")
+	}
+}
diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go
index 67d27bb..3146cae 100644
--- a/src/cmd/compile/internal/gc/go.go
+++ b/src/cmd/compile/internal/gc/go.go
@@ -10,8 +10,6 @@ import (
 	"cmd/internal/obj"
 )
 
-// avoid <ctype.h>
-
 // The parser's maximum stack size.
 // We have to use a #define macro here since yacc
 // or bison will check for its definition and use
@@ -95,10 +93,10 @@ type Val struct {
 
 type NilVal struct{}
 
-func (v Val) Ctype() int {
+func (v Val) Ctype() Ctype {
 	switch x := v.U.(type) {
 	default:
-		Fatal("unexpected Ctype for %T", v.U)
+		Fatalf("unexpected Ctype for %T", v.U)
 		panic("not reached")
 	case nil:
 		return 0
@@ -125,9 +123,9 @@ type Pkg struct {
 	Path     string // string literal used in import statement
 	Pathsym  *Sym
 	Prefix   string // escaped path for use in symbol table
-	Imported uint8  // export data of this package was parsed
-	Exported int8   // import line written in export data
-	Direct   int8   // imported directly
+	Imported bool   // export data of this package was parsed
+	Exported bool   // import line written in export data
+	Direct   bool   // imported directly
 	Safe     bool   // whether the package is marked as safe
 	Syms     map[string]*Sym
 }
@@ -153,20 +151,19 @@ type Sym struct {
 }
 
 type Type struct {
-	Etype       uint8
+	Etype       EType
 	Nointerface bool
-	Noalg       uint8
+	Noalg       bool
 	Chan        uint8
 	Trecur      uint8 // to detect loops
-	Printed     uint8
+	Printed     bool
 	Embedded    uint8 // TFIELD embedded type
-	Siggen      uint8
-	Funarg      uint8 // on TSTRUCT and TFIELD
-	Copyany     uint8
+	Funarg      bool  // on TSTRUCT and TFIELD
+	Copyany     bool
 	Local       bool // created in this file
-	Deferwidth  uint8
-	Broke       uint8 // broken type definition.
-	Isddd       bool  // TFIELD is ... argument
+	Deferwidth  bool
+	Broke       bool // broken type definition.
+	Isddd       bool // TFIELD is ... argument
 	Align       uint8
 	Haspointers uint8 // 0 unknown, 1 no, 2 yes
 
@@ -178,7 +175,7 @@ type Type struct {
 	Thistuple int
 	Outtuple  int
 	Intuple   int
-	Outnamed  uint8
+	Outnamed  bool
 
 	Method  *Type
 	Xmethod *Type
@@ -211,16 +208,15 @@ type Type struct {
 	Embedlineno int32 // first use of TFORW as embedded type
 
 	// for TFORW, where to copy the eventual value to
-	Copyto *NodeList
+	Copyto []*Node
 
 	Lastfn *Node // for usefield
 }
 
 type Label struct {
-	Used uint8
 	Sym  *Sym
 	Def  *Node
-	Use  *NodeList
+	Use  []*Node
 	Link *Label
 
 	// for use during gen
@@ -228,6 +224,8 @@ type Label struct {
 	Labelpc  *obj.Prog // pointer to code
 	Breakpc  *obj.Prog // pointer to code
 	Continpc *obj.Prog // pointer to code
+
+	Used bool
 }
 
 type InitEntry struct {
@@ -260,6 +258,8 @@ type Iter struct {
 	T     *Type
 }
 
+type EType uint8
+
 const (
 	Txxx = iota
 
@@ -288,7 +288,7 @@ const (
 
 	TFUNC
 	TARRAY
-	T_old_DARRAY
+	T_old_DARRAY // Doesn't seem to be used in existing code. Used now for Isddd export (see bexport.go). TODO(gri) rename.
 	TSTRUCT
 	TCHAN
 	TMAP
@@ -312,8 +312,11 @@ const (
 	NTYPE
 )
 
+// Ctype describes the constant kind of an "ideal" (untyped) constant.
+type Ctype int8
+
 const (
-	CTxxx = iota
+	CTxxx Ctype = iota
 
 	CTINT
 	CTRUNE
@@ -325,27 +328,31 @@ const (
 )
 
 const (
-	/* types of channel */
-	/* must match ../../pkg/nreflect/type.go:/Chandir */
+	// types of channel
+	// must match ../../pkg/nreflect/type.go:/Chandir
 	Cxxx  = 0
 	Crecv = 1 << 0
 	Csend = 1 << 1
 	Cboth = Crecv | Csend
 )
 
-// declaration context
+// The Class of a variable/function describes the "storage class"
+// of a variable or function. During parsing, storage classes are
+// called declaration contexts.
+type Class uint8
+
 const (
-	Pxxx      = uint8(iota)
-	PEXTERN   // global variable
-	PAUTO     // local variables
-	PPARAM    // input arguments
-	PPARAMOUT // output results
-	PPARAMREF // closure variable reference
-	PFUNC     // global function
+	Pxxx      Class = iota
+	PEXTERN         // global variable
+	PAUTO           // local variables
+	PPARAM          // input arguments
+	PPARAMOUT       // output results
+	PPARAMREF       // closure variable reference
+	PFUNC           // global function
 
 	PDISCARD // discard during parse of duplicate import
 
-	PHEAP = uint8(1 << 7) // an extra bit to identify an escaped variable
+	PHEAP = 1 << 7 // an extra bit to identify an escaped variable
 )
 
 const (
@@ -364,8 +371,8 @@ const (
 
 type Typedef struct {
 	Name   string
-	Etype  int
-	Sameas int
+	Etype  EType
+	Sameas EType
 }
 
 type Sig struct {
@@ -376,18 +383,17 @@ type Sig struct {
 	type_  *Type
 	mtype  *Type
 	offset int32
-	link   *Sig
 }
 
 type Io struct {
 	infile     string
 	bin        *obj.Biobuf
-	nlsemi     int
-	eofnl      int
+	cp         string // used for content when bin==nil
 	last       int
 	peekc      int
-	peekc1     int    // second peekc for ...
-	cp         string // used for content when bin==nil
+	peekc1     int // second peekc for ...
+	nlsemi     bool
+	eofnl      bool
 	importsafe bool
 }
 
@@ -400,10 +406,8 @@ type Idir struct {
 	dir  string
 }
 
-/*
- * argument passing to/from
- * smagic and umagic
- */
+// argument passing to/from
+// smagic and umagic
 type Magic struct {
 	W   int // input for both - width
 	S   int // output for both - shift
@@ -419,17 +423,15 @@ type Magic struct {
 	Ua int    // output - adder
 }
 
-/*
- * note this is the runtime representation
- * of the compilers arrays.
- *
- * typedef	struct
- * {				// must not move anything
- *	uchar	array[8];	// pointer to data
- *	uchar	nel[4];		// number of elements
- *	uchar	cap[4];		// allocated number of elements
- * } Array;
- */
+// note this is the runtime representation
+// of the compilers arrays.
+//
+// typedef	struct
+// {					// must not move anything
+// 	uchar	array[8];	// pointer to data
+// 	uchar	nel[4];		// number of elements
+// 	uchar	cap[4];		// allocated number of elements
+// } Array;
 var Array_array int // runtime offsetof(Array,array) - same for String
 
 var Array_nel int // runtime offsetof(Array,nel) - same for String
@@ -438,16 +440,14 @@ var Array_cap int // runtime offsetof(Array,cap)
 
 var sizeof_Array int // runtime sizeof(Array)
 
-/*
- * note this is the runtime representation
- * of the compilers strings.
- *
- * typedef	struct
- * {				// must not move anything
- *	uchar	array[8];	// pointer to data
- *	uchar	nel[4];		// number of elements
- * } String;
- */
+// note this is the runtime representation
+// of the compilers strings.
+//
+// typedef	struct
+// {					// must not move anything
+// 	uchar	array[8];	// pointer to data
+// 	uchar	nel[4];		// number of elements
+// } String;
 var sizeof_String int // runtime sizeof(String)
 
 var dotlist [10]Dlist // size is max depth of embeddeds
@@ -484,8 +484,7 @@ var nolocalimports int
 
 var lexbuf bytes.Buffer
 var strbuf bytes.Buffer
-
-var litbuf string
+var litbuf string // LLITERAL value for use in syntax error messages
 
 var Debug [256]int
 
@@ -512,6 +511,8 @@ var Runtimepkg *Pkg // package runtime
 
 var racepkg *Pkg // package runtime/race
 
+var msanpkg *Pkg // package runtime/msan
+
 var typepkg *Pkg // fake package for runtime type info (headers)
 
 var typelinkpkg *Pkg // fake package for runtime type info (data)
@@ -522,7 +523,7 @@ var unsafepkg *Pkg // package unsafe
 
 var trackpkg *Pkg // fake package for field tracking
 
-var Tptr int // either TPTR32 or TPTR64
+var Tptr EType // either TPTR32 or TPTR64
 
 var myimportpath string
 
@@ -544,7 +545,7 @@ var runetype *Type
 
 var errortype *Type
 
-var Simtype [NTYPE]uint8
+var Simtype [NTYPE]EType
 
 var (
 	Isptr     [NTYPE]bool
@@ -584,22 +585,20 @@ var maxfltval [NTYPE]*Mpflt
 
 var xtop *NodeList
 
-var externdcl *NodeList
+var externdcl []*Node
 
-var exportlist *NodeList
+var exportlist []*Node
 
-var importlist *NodeList // imported functions and methods with inlinable bodies
+var importlist []*Node // imported functions and methods with inlinable bodies
 
-var funcsyms *NodeList
+var funcsyms []*Node
 
-var dclcontext uint8 // PEXTERN/PAUTO
+var dclcontext Class // PEXTERN/PAUTO
 
 var incannedimport int
 
 var statuniqgen int // name generator for static temps
 
-var loophack int
-
 var iota_ int32
 
 var lastconst *NodeList
@@ -616,7 +615,7 @@ var blockgen int32 // max block number
 
 var block int32 // current block number
 
-var Hasdefer int // flag that curfn has defer statetment
+var hasdefer bool // flag that curfn has defer statement
 
 var Curfn *Node
 
@@ -626,19 +625,11 @@ var Widthint int
 
 var Widthreg int
 
-var typesw *Node
-
 var nblank *Node
 
-var hunk string
-
-var nhunk int32
-
-var thunk int32
-
 var Funcdepth int32
 
-var typecheckok int
+var typecheckok bool
 
 var compiling_runtime int
 
@@ -652,15 +643,23 @@ var flag_installsuffix string
 
 var flag_race int
 
+var flag_msan int
+
 var flag_largemodel int
 
+// Whether we are adding any sort of code instrumentation, such as
+// when the race detector is enabled.
+var instrumenting bool
+
 // Pending annotations for next func declaration.
 var (
-	noescape       bool
-	nosplit        bool
-	nowritebarrier bool
-	systemstack    bool
-	norace         bool
+	noescape          bool
+	noinline          bool
+	norace            bool
+	nosplit           bool
+	nowritebarrier    bool
+	nowritebarrierrec bool
+	systemstack       bool
 )
 
 var debuglive int
@@ -685,8 +684,6 @@ var nodfp *Node
 
 var Disable_checknil int
 
-var zerosize int64
-
 type Flow struct {
 	Prog   *obj.Prog // actual instruction
 	P1     *Flow     // predecessors of this instruction: p1,
@@ -701,7 +698,7 @@ type Flow struct {
 	Id     int32  // sequence number in flow graph
 	Rpo    int32  // reverse post ordering
 	Loop   uint16 // x5 for every loop
-	Refset uint8  // diagnostic generated
+	Refset bool   // diagnostic generated
 
 	Data interface{} // for use by client
 }
@@ -715,9 +712,7 @@ type Graph struct {
 	Rpo []*Flow
 }
 
-/*
- *	interface to back end
- */
+// interface to back end
 
 const (
 	// Pseudo-op, like TEXT, GLOBL, TYPE, PCDATA, FUNCDATA.
@@ -795,14 +790,14 @@ type Arch struct {
 	Bgen_float   func(*Node, bool, int, *obj.Prog) // optional
 	Cgen64       func(*Node, *Node)                // only on 32-bit systems
 	Cgenindex    func(*Node, *Node, bool) *obj.Prog
-	Cgen_bmul    func(int, *Node, *Node, *Node) bool
+	Cgen_bmul    func(Op, *Node, *Node, *Node) bool
 	Cgen_float   func(*Node, *Node) // optional
 	Cgen_hmul    func(*Node, *Node, *Node)
-	Cgen_shift   func(int, bool, *Node, *Node, *Node)
+	Cgen_shift   func(Op, bool, *Node, *Node, *Node)
 	Clearfat     func(*Node)
-	Cmp64        func(*Node, *Node, int, int, *obj.Prog) // only on 32-bit systems
+	Cmp64        func(*Node, *Node, Op, int, *obj.Prog) // only on 32-bit systems
 	Defframe     func(*obj.Prog)
-	Dodiv        func(int, *Node, *Node, *Node)
+	Dodiv        func(Op, *Node, *Node, *Node)
 	Excise       func(*Flow)
 	Expandchecks func(*obj.Prog)
 	Getg         func(*Node)
@@ -818,7 +813,7 @@ type Arch struct {
 	// function calls needed during the evaluation, and on 32-bit systems
 	// the values are guaranteed not to be 64-bit values, so no in-memory
 	// temporaries are necessary.
-	Ginscmp func(op int, t *Type, n1, n2 *Node, likely int) *obj.Prog
+	Ginscmp func(op Op, t *Type, n1, n2 *Node, likely int) *obj.Prog
 
 	// Ginsboolval inserts instructions to convert the result
 	// of a just-completed comparison to a boolean value.
@@ -847,7 +842,7 @@ type Arch struct {
 	FtoB         func(int) uint64
 	BtoR         func(uint64) int
 	BtoF         func(uint64) int
-	Optoas       func(int, *Type) int
+	Optoas       func(Op, *Type) int
 	Doregbits    func(int) uint64
 	Regnames     func(*int) []string
 	Use387       bool // should 8g use 387 FP instructions instead of sse2.
diff --git a/src/cmd/compile/internal/gc/go.y b/src/cmd/compile/internal/gc/go.y
deleted file mode 100644
index c6d1607..0000000
--- a/src/cmd/compile/internal/gc/go.y
+++ /dev/null
@@ -1,2316 +0,0 @@
-// Copyright 2009 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.
-
-/*
- * Go language grammar.
- *
- * The Go semicolon rules are:
- *
- *  1. all statements and declarations are terminated by semicolons.
- *  2. semicolons can be omitted before a closing ) or }.
- *  3. semicolons are inserted by the lexer before a newline
- *      following a specific list of tokens.
- *
- * Rules #1 and #2 are accomplished by writing the lists as
- * semicolon-separated lists with an optional trailing semicolon.
- * Rule #3 is implemented in yylex.
- */
-
-%{
-package gc
-
-import (
-	"fmt"
-	"strings"
-)
-%}
-%union	{
-	node *Node
-	list *NodeList
-	typ *Type
-	sym *Sym
-	val Val
-	i int
-}
-
-// |sed 's/.*	//' |9 fmt -l1 |sort |9 fmt -l50 | sed 's/^/%xxx		/'
-
-%token	<val>	LLITERAL
-%token	<i>	LASOP LCOLAS
-%token	<sym>	LBREAK LCASE LCHAN LCONST LCONTINUE LDDD
-%token	<sym>	LDEFAULT LDEFER LELSE LFALL LFOR LFUNC LGO LGOTO
-%token	<sym>	LIF LIMPORT LINTERFACE LMAP LNAME
-%token	<sym>	LPACKAGE LRANGE LRETURN LSELECT LSTRUCT LSWITCH
-%token	<sym>	LTYPE LVAR
-
-%token		LANDAND LANDNOT LBODY LCOMM LDEC LEQ LGE LGT
-%token		LIGNORE LINC LLE LLSH LLT LNE LOROR LRSH
-
-%type	<i>	lbrace import_here
-%type	<sym>	sym packname
-%type	<val>	oliteral
-
-%type	<node>	stmt ntype
-%type	<node>	arg_type
-%type	<node>	case caseblock
-%type	<node>	compound_stmt dotname embed expr complitexpr bare_complitexpr
-%type	<node>	expr_or_type
-%type	<node>	fndcl hidden_fndcl fnliteral
-%type	<node>	for_body for_header for_stmt if_header if_stmt non_dcl_stmt
-%type	<node>	interfacedcl keyval labelname name
-%type	<node>	name_or_type non_expr_type
-%type	<node>	new_name dcl_name oexpr typedclname
-%type	<node>	onew_name
-%type	<node>	osimple_stmt pexpr pexpr_no_paren
-%type	<node>	pseudocall range_stmt select_stmt
-%type	<node>	simple_stmt
-%type	<node>	switch_stmt uexpr
-%type	<node>	xfndcl typedcl start_complit
-
-%type	<list>	xdcl fnbody fnres loop_body dcl_name_list
-%type	<list>	new_name_list expr_list keyval_list braced_keyval_list expr_or_type_list xdcl_list
-%type	<list>	oexpr_list caseblock_list elseif elseif_list else stmt_list oarg_type_list_ocomma arg_type_list
-%type	<list>	interfacedcl_list vardcl vardcl_list structdcl structdcl_list
-%type	<list>	common_dcl constdcl constdcl1 constdcl_list typedcl_list
-
-%type	<node>	convtype comptype dotdotdot
-%type	<node>	indcl interfacetype structtype ptrtype
-%type	<node>	recvchantype non_recvchantype othertype fnret_type fntype
-
-%type	<sym>	hidden_importsym hidden_pkg_importsym
-
-%type	<node>	hidden_constant hidden_literal hidden_funarg
-%type	<node>	hidden_interfacedcl hidden_structdcl
-
-%type	<list>	hidden_funres
-%type	<list>	ohidden_funres
-%type	<list>	hidden_funarg_list ohidden_funarg_list
-%type	<list>	hidden_interfacedcl_list ohidden_interfacedcl_list
-%type	<list>	hidden_structdcl_list ohidden_structdcl_list
-
-%type	<typ>	hidden_type hidden_type_misc hidden_pkgtype
-%type	<typ>	hidden_type_func
-%type	<typ>	hidden_type_recv_chan hidden_type_non_recv_chan
-
-%left		LCOMM	/* outside the usual hierarchy; here for good error messages */
-
-%left		LOROR
-%left		LANDAND
-%left		LEQ LNE LLE LGE LLT LGT
-%left		'+' '-' '|' '^'
-%left		'*' '/' '%' '&' LLSH LRSH LANDNOT
-
-/*
- * manual override of shift/reduce conflicts.
- * the general form is that we assign a precedence
- * to the token being shifted and then introduce
- * NotToken with lower precedence or PreferToToken with higher
- * and annotate the reducing rule accordingly.
- */
-%left		NotPackage
-%left		LPACKAGE
-
-%left		NotParen
-%left		'('
-
-%left		')'
-%left		PreferToRightParen
-
-%error loadsys package LIMPORT '(' LLITERAL import_package import_there ',':
-	"unexpected comma during import block"
-
-%error loadsys package LIMPORT LNAME ';':
-	"missing import path; require quoted string"
-
-%error loadsys package imports LFUNC LNAME '(' ')' '{' LIF if_header ';':
-	"missing { after if clause"
-
-%error loadsys package imports LFUNC LNAME '(' ')' '{' LSWITCH if_header ';':
-	"missing { after switch clause"
-
-%error loadsys package imports LFUNC LNAME '(' ')' '{' LFOR for_header ';':
-	"missing { after for clause"
-
-%error loadsys package imports LFUNC LNAME '(' ')' '{' LFOR ';' LBODY:
-	"missing { after for clause"
-
-%error loadsys package imports LFUNC LNAME '(' ')' ';' '{':
-	"unexpected semicolon or newline before {"
-
-%error loadsys package imports LTYPE LNAME ';':
-	"unexpected semicolon or newline in type declaration"
-
-%error loadsys package imports LCHAN '}':
-	"unexpected } in channel type"
-
-%error loadsys package imports LCHAN ')':
-	"unexpected ) in channel type"
-
-%error loadsys package imports LCHAN ',':
-	"unexpected comma in channel type"
-
-%error loadsys package imports LFUNC LNAME '(' ')' '{' if_stmt ';' LELSE:
-	"unexpected semicolon or newline before else"
-
-%error loadsys package imports LTYPE LNAME LINTERFACE '{' LNAME ',' LNAME:
-	"name list not allowed in interface type"
-
-%error loadsys package imports LFUNC LNAME '(' ')' '{' LFOR LVAR LNAME '=' LNAME:
-	"var declaration not allowed in for initializer"
-
-%error loadsys package imports LVAR LNAME '[' ']' LNAME '{':
-	"unexpected { at end of statement"
-
-%error loadsys package imports LFUNC LNAME '(' ')' '{' LVAR LNAME '[' ']' LNAME '{':
-	"unexpected { at end of statement"
-
-%error loadsys package imports LFUNC LNAME '(' ')' '{' LDEFER LNAME ';':
-	"argument to go/defer must be function call"
-
-%error loadsys package imports LVAR LNAME '=' LNAME '{' LNAME ';':
-	"need trailing comma before newline in composite literal"
-
-%error loadsys package imports LVAR LNAME '=' comptype '{' LNAME ';':
-	"need trailing comma before newline in composite literal"
-
-%error loadsys package imports LFUNC LNAME '(' ')' '{' LFUNC LNAME:
-	"nested func not allowed"
-
-%error loadsys package imports LFUNC LNAME '(' ')' '{' LIF if_header loop_body LELSE ';':
-	"else must be followed by if or statement block"
-
-%%
-file:
-	loadsys
-	package
-	imports
-	xdcl_list
-	{
-		xtop = concat(xtop, $4);
-	}
-
-package:
-	%prec NotPackage
-	{
-		prevlineno = lineno;
-		Yyerror("package statement must be first");
-		errorexit();
-	}
-|	LPACKAGE sym ';'
-	{
-		mkpackage($2.Name);
-	}
-
-/*
- * this loads the definitions for the low-level runtime functions,
- * so that the compiler can generate calls to them,
- * but does not make the name "runtime" visible as a package.
- */
-loadsys:
-	{
-		importpkg = Runtimepkg;
-
-		if Debug['A'] != 0 {
-			cannedimports("runtime.Builtin", "package runtime\n\n$$\n\n");
-		} else {
-			cannedimports("runtime.Builtin", runtimeimport);
-		}
-		curio.importsafe = true
-	}
-	import_package
-	import_there
-	{
-		importpkg = nil;
-	}
-
-imports:
-|	imports import ';'
-
-import:
-	LIMPORT import_stmt
-|	LIMPORT '(' import_stmt_list osemi ')'
-|	LIMPORT '(' ')'
-
-import_stmt:
-	import_here import_package import_there
-	{
-		ipkg := importpkg;
-		my := importmyname;
-		importpkg = nil;
-		importmyname = nil;
-
-		if my == nil {
-			my = Lookup(ipkg.Name);
-		}
-
-		pack := Nod(OPACK, nil, nil);
-		pack.Sym = my;
-		pack.Name.Pkg = ipkg;
-		pack.Lineno = int32($1);
-
-		if strings.HasPrefix(my.Name, ".") {
-			importdot(ipkg, pack);
-			break;
-		}
-		if my.Name == "init" {
-			Yyerror("cannot import package as init - init must be a func");
-			break;
-		}
-		if my.Name == "_" {
-			break;
-		}
-		if my.Def != nil {
-			lineno = int32($1);
-			redeclare(my, "as imported package name");
-		}
-		my.Def = pack;
-		my.Lastlineno = int32($1);
-		my.Block = 1;	// at top level
-	}
-|	import_here import_there
-	{
-		// When an invalid import path is passed to importfile,
-		// it calls Yyerror and then sets up a fake import with
-		// no package statement. This allows us to test more
-		// than one invalid import statement in a single file.
-		if nerrors == 0 {
-			Fatal("phase error in import");
-		}
-	}
-
-import_stmt_list:
-	import_stmt
-|	import_stmt_list ';' import_stmt
-
-import_here:
-	LLITERAL
-	{
-		// import with original name
-		$$ = parserline();
-		importmyname = nil;
-		importfile(&$1, $$);
-	}
-|	sym LLITERAL
-	{
-		// import with given name
-		$$ = parserline();
-		importmyname = $1;
-		importfile(&$2, $$);
-	}
-|	'.' LLITERAL
-	{
-		// import into my name space
-		$$ = parserline();
-		importmyname = Lookup(".");
-		importfile(&$2, $$);
-	}
-
-import_package:
-	LPACKAGE LNAME import_safety ';'
-	{
-		if importpkg.Name == "" {
-			importpkg.Name = $2.Name;
-			numImport[$2.Name]++
-		} else if importpkg.Name != $2.Name {
-			Yyerror("conflicting names %s and %s for package %q", importpkg.Name, $2.Name, importpkg.Path);
-		}
-		importpkg.Direct = 1;
-		importpkg.Safe = curio.importsafe
-
-		if safemode != 0 && !curio.importsafe {
-			Yyerror("cannot import unsafe package %q", importpkg.Path);
-		}
-	}
-
-import_safety:
-|	LNAME
-	{
-		if $1.Name == "safe" {
-			curio.importsafe = true
-		}
-	}
-
-import_there:
-	{
-		defercheckwidth();
-	}
-	hidden_import_list '$' '$'
-	{
-		resumecheckwidth();
-		unimportfile();
-	}
-
-/*
- * declarations
- */
-xdcl:
-	{
-		Yyerror("empty top-level declaration");
-		$$ = nil;
-	}
-|	common_dcl
-|	xfndcl
-	{
-		$$ = list1($1);
-	}
-|	non_dcl_stmt
-	{
-		Yyerror("non-declaration statement outside function body");
-		$$ = nil;
-	}
-|	error
-	{
-		$$ = nil;
-	}
-
-common_dcl:
-	LVAR vardcl
-	{
-		$$ = $2;
-	}
-|	LVAR '(' vardcl_list osemi ')'
-	{
-		$$ = $3;
-	}
-|	LVAR '(' ')'
-	{
-		$$ = nil;
-	}
-|	lconst constdcl
-	{
-		$$ = $2;
-		iota_ = -100000;
-		lastconst = nil;
-	}
-|	lconst '(' constdcl osemi ')'
-	{
-		$$ = $3;
-		iota_ = -100000;
-		lastconst = nil;
-	}
-|	lconst '(' constdcl ';' constdcl_list osemi ')'
-	{
-		$$ = concat($3, $5);
-		iota_ = -100000;
-		lastconst = nil;
-	}
-|	lconst '(' ')'
-	{
-		$$ = nil;
-		iota_ = -100000;
-	}
-|	LTYPE typedcl
-	{
-		$$ = list1($2);
-	}
-|	LTYPE '(' typedcl_list osemi ')'
-	{
-		$$ = $3;
-	}
-|	LTYPE '(' ')'
-	{
-		$$ = nil;
-	}
-
-lconst:
-	LCONST
-	{
-		iota_ = 0;
-	}
-
-vardcl:
-	dcl_name_list ntype
-	{
-		$$ = variter($1, $2, nil);
-	}
-|	dcl_name_list ntype '=' expr_list
-	{
-		$$ = variter($1, $2, $4);
-	}
-|	dcl_name_list '=' expr_list
-	{
-		$$ = variter($1, nil, $3);
-	}
-
-constdcl:
-	dcl_name_list ntype '=' expr_list
-	{
-		$$ = constiter($1, $2, $4);
-	}
-|	dcl_name_list '=' expr_list
-	{
-		$$ = constiter($1, nil, $3);
-	}
-
-constdcl1:
-	constdcl
-|	dcl_name_list ntype
-	{
-		$$ = constiter($1, $2, nil);
-	}
-|	dcl_name_list
-	{
-		$$ = constiter($1, nil, nil);
-	}
-
-typedclname:
-	sym
-	{
-		// different from dclname because the name
-		// becomes visible right here, not at the end
-		// of the declaration.
-		$$ = typedcl0($1);
-	}
-
-typedcl:
-	typedclname ntype
-	{
-		$$ = typedcl1($1, $2, true);
-	}
-
-simple_stmt:
-	expr
-	{
-		$$ = $1;
-
-		// These nodes do not carry line numbers.
-		// Since a bare name used as an expression is an error,
-		// introduce a wrapper node to give the correct line.
-		switch($$.Op) {
-		case ONAME, ONONAME, OTYPE, OPACK, OLITERAL:
-			$$ = Nod(OPAREN, $$, nil);
-			$$.Implicit = true;
-			break;
-		}
-	}
-|	expr LASOP expr
-	{
-		$$ = Nod(OASOP, $1, $3);
-		$$.Etype = uint8($2);			// rathole to pass opcode
-	}
-|	expr_list '=' expr_list
-	{
-		if $1.Next == nil && $3.Next == nil {
-			// simple
-			$$ = Nod(OAS, $1.N, $3.N);
-			break;
-		}
-		// multiple
-		$$ = Nod(OAS2, nil, nil);
-		$$.List = $1;
-		$$.Rlist = $3;
-	}
-|	expr_list LCOLAS expr_list
-	{
-		if $3.N.Op == OTYPESW {
-			$$ = Nod(OTYPESW, nil, $3.N.Right);
-			if $3.Next != nil {
-				Yyerror("expr.(type) must be alone in list");
-			}
-			if $1.Next != nil {
-				Yyerror("argument count mismatch: %d = %d", count($1), 1);
-			} else if ($1.N.Op != ONAME && $1.N.Op != OTYPE && $1.N.Op != ONONAME) || isblank($1.N) {
-				Yyerror("invalid variable name %s in type switch", $1.N);
-			} else {
-				$$.Left = dclname($1.N.Sym);
-			}  // it's a colas, so must not re-use an oldname.
-			break;
-		}
-		$$ = colas($1, $3, int32($2));
-	}
-|	expr LINC
-	{
-		$$ = Nod(OASOP, $1, Nodintconst(1));
-		$$.Implicit = true;
-		$$.Etype = OADD;
-	}
-|	expr LDEC
-	{
-		$$ = Nod(OASOP, $1, Nodintconst(1));
-		$$.Implicit = true;
-		$$.Etype = OSUB;
-	}
-
-case:
-	LCASE expr_or_type_list ':'
-	{
-		var n, nn *Node
-
-		// will be converted to OCASE
-		// right will point to next case
-		// done in casebody()
-		markdcl();
-		$$ = Nod(OXCASE, nil, nil);
-		$$.List = $2;
-		if typesw != nil && typesw.Right != nil {
-			n = typesw.Right.Left
-			if n != nil {
-				// type switch - declare variable
-				nn = newname(n.Sym);
-				declare(nn, dclcontext);
-				$$.Rlist = list1(nn);
-	
-				// keep track of the instances for reporting unused
-				nn.Name.Defn = typesw.Right;
-			}
-		}
-	}
-|	LCASE expr_or_type_list '=' expr ':'
-	{
-		var n *Node
-
-		// will be converted to OCASE
-		// right will point to next case
-		// done in casebody()
-		markdcl();
-		$$ = Nod(OXCASE, nil, nil);
-		if $2.Next == nil {
-			n = Nod(OAS, $2.N, $4);
-		} else {
-			n = Nod(OAS2, nil, nil);
-			n.List = $2;
-			n.Rlist = list1($4);
-		}
-		$$.List = list1(n);
-	}
-|	LCASE expr_or_type_list LCOLAS expr ':'
-	{
-		// will be converted to OCASE
-		// right will point to next case
-		// done in casebody()
-		markdcl();
-		$$ = Nod(OXCASE, nil, nil);
-		$$.List = list1(colas($2, list1($4), int32($3)));
-	}
-|	LDEFAULT ':'
-	{
-		var n, nn *Node
-
-		markdcl();
-		$$ = Nod(OXCASE, nil, nil);
-		if typesw != nil && typesw.Right != nil {
-			n = typesw.Right.Left
-			if n != nil {
-				// type switch - declare variable
-				nn = newname(n.Sym);
-				declare(nn, dclcontext);
-				$$.Rlist = list1(nn);
-	
-				// keep track of the instances for reporting unused
-				nn.Name.Defn = typesw.Right;
-			}
-		}
-	}
-
-compound_stmt:
-	'{'
-	{
-		markdcl();
-	}
-	stmt_list '}'
-	{
-		if $3 == nil {
-			$$ = Nod(OEMPTY, nil, nil);
-		} else {
-			$$ = liststmt($3);
-		}
-		popdcl();
-	}
-
-caseblock:
-	case
-	{
-		// If the last token read by the lexer was consumed
-		// as part of the case, clear it (parser has cleared yychar).
-		// If the last token read by the lexer was the lookahead
-		// leave it alone (parser has it cached in yychar).
-		// This is so that the stmt_list action doesn't look at
-		// the case tokens if the stmt_list is empty.
-		yylast = yychar;
-		$1.Xoffset = int64(block);
-	}
-	stmt_list
-	{
-		// This is the only place in the language where a statement
-		// list is not allowed to drop the final semicolon, because
-		// it's the only place where a statement list is not followed 
-		// by a closing brace.  Handle the error for pedantry.
-
-		// Find the final token of the statement list.
-		// yylast is lookahead; yyprev is last of stmt_list
-		last := yyprev;
-
-		if last > 0 && last != ';' && yychar != '}' {
-			Yyerror("missing statement after label");
-		}
-		$$ = $1;
-		$$.Nbody = $3;
-		popdcl();
-	}
-
-caseblock_list:
-	{
-		$$ = nil;
-	}
-|	caseblock_list caseblock
-	{
-		$$ = list($1, $2);
-	}
-
-loop_body:
-	LBODY
-	{
-		markdcl();
-	}
-	stmt_list '}'
-	{
-		$$ = $3;
-		popdcl();
-	}
-
-range_stmt:
-	expr_list '=' LRANGE expr
-	{
-		$$ = Nod(ORANGE, nil, $4);
-		$$.List = $1;
-		$$.Etype = 0;	// := flag
-	}
-|	expr_list LCOLAS LRANGE expr
-	{
-		$$ = Nod(ORANGE, nil, $4);
-		$$.List = $1;
-		$$.Colas = true;
-		colasdefn($1, $$);
-	}
-|	LRANGE expr
-	{
-		$$ = Nod(ORANGE, nil, $2);
-		$$.Etype = 0; // := flag
-	}
-
-for_header:
-	osimple_stmt ';' osimple_stmt ';' osimple_stmt
-	{
-		// init ; test ; incr
-		if $5 != nil && $5.Colas {
-			Yyerror("cannot declare in the for-increment");
-		}
-		$$ = Nod(OFOR, nil, nil);
-		if $1 != nil {
-			$$.Ninit = list1($1);
-		}
-		$$.Left = $3;
-		$$.Right = $5;
-	}
-|	osimple_stmt
-	{
-		// normal test
-		$$ = Nod(OFOR, nil, nil);
-		$$.Left = $1;
-	}
-|	range_stmt
-
-for_body:
-	for_header loop_body
-	{
-		$$ = $1;
-		$$.Nbody = concat($$.Nbody, $2);
-	}
-
-for_stmt:
-	LFOR
-	{
-		markdcl();
-	}
-	for_body
-	{
-		$$ = $3;
-		popdcl();
-	}
-
-if_header:
-	osimple_stmt
-	{
-		// test
-		$$ = Nod(OIF, nil, nil);
-		$$.Left = $1;
-	}
-|	osimple_stmt ';' osimple_stmt
-	{
-		// init ; test
-		$$ = Nod(OIF, nil, nil);
-		if $1 != nil {
-			$$.Ninit = list1($1);
-		}
-		$$.Left = $3;
-	}
-
-/* IF cond body (ELSE IF cond body)* (ELSE block)? */
-if_stmt:
-	LIF
-	{
-		markdcl();
-	}
-	if_header
-	{
-		if $3.Left == nil {
-			Yyerror("missing condition in if statement");
-		}
-	}
-	loop_body
-	{
-		$3.Nbody = $5;
-	}
-	elseif_list else
-	{
-		var n *Node
-		var nn *NodeList
-
-		$$ = $3;
-		n = $3;
-		popdcl();
-		for nn = concat($7, $8); nn != nil; nn = nn.Next {
-			if nn.N.Op == OIF {
-				popdcl();
-			}
-			n.Rlist = list1(nn.N);
-			n = nn.N;
-		}
-	}
-
-elseif:
-	LELSE LIF 
-	{
-		markdcl();
-	}
-	if_header loop_body
-	{
-		if $4.Left == nil {
-			Yyerror("missing condition in if statement");
-		}
-		$4.Nbody = $5;
-		$$ = list1($4);
-	}
-
-elseif_list:
-	{
-		$$ = nil;
-	}
-|	elseif_list elseif
-	{
-		$$ = concat($1, $2);
-	}
-
-else:
-	{
-		$$ = nil;
-	}
-|	LELSE compound_stmt
-	{
-		l := &NodeList{N: $2}
-		l.End = l
-		$$ = l;
-	}
-
-switch_stmt:
-	LSWITCH
-	{
-		markdcl();
-	}
-	if_header
-	{
-		var n *Node
-		n = $3.Left;
-		if n != nil && n.Op != OTYPESW {
-			n = nil;
-		}
-		typesw = Nod(OXXX, typesw, n);
-	}
-	LBODY caseblock_list '}'
-	{
-		$$ = $3;
-		$$.Op = OSWITCH;
-		$$.List = $6;
-		typesw = typesw.Left;
-		popdcl();
-	}
-
-select_stmt:
-	LSELECT
-	{
-		typesw = Nod(OXXX, typesw, nil);
-	}
-	LBODY caseblock_list '}'
-	{
-		$$ = Nod(OSELECT, nil, nil);
-		$$.Lineno = typesw.Lineno;
-		$$.List = $4;
-		typesw = typesw.Left;
-	}
-
-/*
- * expressions
- */
-expr:
-	uexpr
-|	expr LOROR expr
-	{
-		$$ = Nod(OOROR, $1, $3);
-	}
-|	expr LANDAND expr
-	{
-		$$ = Nod(OANDAND, $1, $3);
-	}
-|	expr LEQ expr
-	{
-		$$ = Nod(OEQ, $1, $3);
-	}
-|	expr LNE expr
-	{
-		$$ = Nod(ONE, $1, $3);
-	}
-|	expr LLT expr
-	{
-		$$ = Nod(OLT, $1, $3);
-	}
-|	expr LLE expr
-	{
-		$$ = Nod(OLE, $1, $3);
-	}
-|	expr LGE expr
-	{
-		$$ = Nod(OGE, $1, $3);
-	}
-|	expr LGT expr
-	{
-		$$ = Nod(OGT, $1, $3);
-	}
-|	expr '+' expr
-	{
-		$$ = Nod(OADD, $1, $3);
-	}
-|	expr '-' expr
-	{
-		$$ = Nod(OSUB, $1, $3);
-	}
-|	expr '|' expr
-	{
-		$$ = Nod(OOR, $1, $3);
-	}
-|	expr '^' expr
-	{
-		$$ = Nod(OXOR, $1, $3);
-	}
-|	expr '*' expr
-	{
-		$$ = Nod(OMUL, $1, $3);
-	}
-|	expr '/' expr
-	{
-		$$ = Nod(ODIV, $1, $3);
-	}
-|	expr '%' expr
-	{
-		$$ = Nod(OMOD, $1, $3);
-	}
-|	expr '&' expr
-	{
-		$$ = Nod(OAND, $1, $3);
-	}
-|	expr LANDNOT expr
-	{
-		$$ = Nod(OANDNOT, $1, $3);
-	}
-|	expr LLSH expr
-	{
-		$$ = Nod(OLSH, $1, $3);
-	}
-|	expr LRSH expr
-	{
-		$$ = Nod(ORSH, $1, $3);
-	}
-	/* not an expression anymore, but left in so we can give a good error */
-|	expr LCOMM expr
-	{
-		$$ = Nod(OSEND, $1, $3);
-	}
-
-uexpr:
-	pexpr
-|	'*' uexpr
-	{
-		$$ = Nod(OIND, $2, nil);
-	}
-|	'&' uexpr
-	{
-		if $2.Op == OCOMPLIT {
-			// Special case for &T{...}: turn into (*T){...}.
-			$$ = $2;
-			$$.Right = Nod(OIND, $$.Right, nil);
-			$$.Right.Implicit = true;
-		} else {
-			$$ = Nod(OADDR, $2, nil);
-		}
-	}
-|	'+' uexpr
-	{
-		$$ = Nod(OPLUS, $2, nil);
-	}
-|	'-' uexpr
-	{
-		$$ = Nod(OMINUS, $2, nil);
-	}
-|	'!' uexpr
-	{
-		$$ = Nod(ONOT, $2, nil);
-	}
-|	'~' uexpr
-	{
-		Yyerror("the bitwise complement operator is ^");
-		$$ = Nod(OCOM, $2, nil);
-	}
-|	'^' uexpr
-	{
-		$$ = Nod(OCOM, $2, nil);
-	}
-|	LCOMM uexpr
-	{
-		$$ = Nod(ORECV, $2, nil);
-	}
-
-/*
- * call-like statements that
- * can be preceded by 'defer' and 'go'
- */
-pseudocall:
-	pexpr '(' ')'
-	{
-		$$ = Nod(OCALL, $1, nil);
-	}
-|	pexpr '(' expr_or_type_list ocomma ')'
-	{
-		$$ = Nod(OCALL, $1, nil);
-		$$.List = $3;
-	}
-|	pexpr '(' expr_or_type_list LDDD ocomma ')'
-	{
-		$$ = Nod(OCALL, $1, nil);
-		$$.List = $3;
-		$$.Isddd = true;
-	}
-
-pexpr_no_paren:
-	LLITERAL
-	{
-		$$ = nodlit($1);
-	}
-|	name
-|	pexpr '.' sym
-	{
-		if $1.Op == OPACK {
-			var s *Sym
-			s = restrictlookup($3.Name, $1.Name.Pkg);
-			$1.Used = true;
-			$$ = oldname(s);
-			break;
-		}
-		$$ = Nod(OXDOT, $1, newname($3));
-	}
-|	pexpr '.' '(' expr_or_type ')'
-	{
-		$$ = Nod(ODOTTYPE, $1, $4);
-	}
-|	pexpr '.' '(' LTYPE ')'
-	{
-		$$ = Nod(OTYPESW, nil, $1);
-	}
-|	pexpr '[' expr ']'
-	{
-		$$ = Nod(OINDEX, $1, $3);
-	}
-|	pexpr '[' oexpr ':' oexpr ']'
-	{
-		$$ = Nod(OSLICE, $1, Nod(OKEY, $3, $5));
-	}
-|	pexpr '[' oexpr ':' oexpr ':' oexpr ']'
-	{
-		if $5 == nil {
-			Yyerror("middle index required in 3-index slice");
-		}
-		if $7 == nil {
-			Yyerror("final index required in 3-index slice");
-		}
-		$$ = Nod(OSLICE3, $1, Nod(OKEY, $3, Nod(OKEY, $5, $7)));
-	}
-|	pseudocall
-|	convtype '(' expr ocomma ')'
-	{
-		// conversion
-		$$ = Nod(OCALL, $1, nil);
-		$$.List = list1($3);
-	}
-|	comptype lbrace start_complit braced_keyval_list '}'
-	{
-		$$ = $3;
-		$$.Right = $1;
-		$$.List = $4;
-		fixlbrace($2);
-	}
-|	pexpr_no_paren '{' start_complit braced_keyval_list '}'
-	{
-		$$ = $3;
-		$$.Right = $1;
-		$$.List = $4;
-	}
-|	'(' expr_or_type ')' '{' start_complit braced_keyval_list '}'
-	{
-		Yyerror("cannot parenthesize type in composite literal");
-		$$ = $5;
-		$$.Right = $2;
-		$$.List = $6;
-	}
-|	fnliteral
-
-start_complit:
-	{
-		// composite expression.
-		// make node early so we get the right line number.
-		$$ = Nod(OCOMPLIT, nil, nil);
-	}
-
-keyval:
-	complitexpr ':' complitexpr
-	{
-		$$ = Nod(OKEY, $1, $3);
-	}
-
-bare_complitexpr:
-	expr
-	{
-		// These nodes do not carry line numbers.
-		// Since a composite literal commonly spans several lines,
-		// the line number on errors may be misleading.
-		// Introduce a wrapper node to give the correct line.
-		$$ = $1;
-		switch($$.Op) {
-		case ONAME, ONONAME, OTYPE, OPACK, OLITERAL:
-			$$ = Nod(OPAREN, $$, nil);
-			$$.Implicit = true;
-		}
-	}
-|	'{' start_complit braced_keyval_list '}'
-	{
-		$$ = $2;
-		$$.List = $3;
-	}
-
-complitexpr:
-	expr
-|	'{' start_complit braced_keyval_list '}'
-	{
-		$$ = $2;
-		$$.List = $3;
-	}
-
-pexpr:
-	pexpr_no_paren
-|	'(' expr_or_type ')'
-	{
-		$$ = $2;
-		
-		// Need to know on lhs of := whether there are ( ).
-		// Don't bother with the OPAREN in other cases:
-		// it's just a waste of memory and time.
-		switch($$.Op) {
-		case ONAME, ONONAME, OPACK, OTYPE, OLITERAL, OTYPESW:
-			$$ = Nod(OPAREN, $$, nil);
-		}
-	}
-
-expr_or_type:
-	expr
-|	non_expr_type	%prec PreferToRightParen
-
-name_or_type:
-	ntype
-
-lbrace:
-	LBODY
-	{
-		$$ = LBODY;
-	}
-|	'{'
-	{
-		$$ = '{';
-	}
-
-/*
- * names and types
- *	newname is used before declared
- *	oldname is used after declared
- */
-new_name:
-	sym
-	{
-		if $1 == nil {
-			$$ = nil;
-		} else {
-			$$ = newname($1);
-		}
-	}
-
-dcl_name:
-	sym
-	{
-		$$ = dclname($1);
-	}
-
-onew_name:
-	{
-		$$ = nil;
-	}
-|	new_name
-
-sym:
-	LNAME
-	{
-		$$ = $1;
-		// during imports, unqualified non-exported identifiers are from builtinpkg
-		if importpkg != nil && !exportname($1.Name) {
-			$$ = Pkglookup($1.Name, builtinpkg);
-		}
-	}
-|	hidden_importsym
-|	'?'
-	{
-		$$ = nil;
-	}
-
-hidden_importsym:
-	'@' LLITERAL '.' LNAME
-	{
-		var p *Pkg
-
-		if $2.U.(string) == "" {
-			p = importpkg;
-		} else {
-			if isbadimport($2.U.(string)) {
-				errorexit();
-			}
-			p = mkpkg($2.U.(string));
-		}
-		$$ = Pkglookup($4.Name, p);
-	}
-|	'@' LLITERAL '.' '?'
-	{
-		var p *Pkg
-
-		if $2.U.(string) == "" {
-			p = importpkg;
-		} else {
-			if isbadimport($2.U.(string)) {
-				errorexit();
-			}
-			p = mkpkg($2.U.(string));
-		}
-		$$ = Pkglookup("?", p);
-	}
-
-name:
-	sym	%prec NotParen
-	{
-		$$ = oldname($1);
-		if $$.Name != nil && $$.Name.Pack != nil {
-			$$.Name.Pack.Used = true;
-		}
-	}
-
-labelname:
-	new_name
-
-/*
- * to avoid parsing conflicts, type is split into
- *	channel types
- *	function types
- *	parenthesized types
- *	any other type
- * the type system makes additional restrictions,
- * but those are not implemented in the grammar.
- */
-dotdotdot:
-	LDDD
-	{
-		Yyerror("final argument in variadic function missing type");
-		$$ = Nod(ODDD, typenod(typ(TINTER)), nil);
-	}
-|	LDDD ntype
-	{
-		$$ = Nod(ODDD, $2, nil);
-	}
-
-ntype:
-	recvchantype
-|	fntype
-|	othertype
-|	ptrtype
-|	dotname
-|	'(' ntype ')'
-	{
-		$$ = $2;
-	}
-
-non_expr_type:
-	recvchantype
-|	fntype
-|	othertype
-|	'*' non_expr_type
-	{
-		$$ = Nod(OIND, $2, nil);
-	}
-
-non_recvchantype:
-	fntype
-|	othertype
-|	ptrtype
-|	dotname
-|	'(' ntype ')'
-	{
-		$$ = $2;
-	}
-
-convtype:
-	fntype
-|	othertype
-
-comptype:
-	othertype
-
-fnret_type:
-	recvchantype
-|	fntype
-|	othertype
-|	ptrtype
-|	dotname
-
-dotname:
-	name
-|	name '.' sym
-	{
-		if $1.Op == OPACK {
-			var s *Sym
-			s = restrictlookup($3.Name, $1.Name.Pkg);
-			$1.Used = true;
-			$$ = oldname(s);
-			break;
-		}
-		$$ = Nod(OXDOT, $1, newname($3));
-	}
-
-othertype:
-	'[' oexpr ']' ntype
-	{
-		$$ = Nod(OTARRAY, $2, $4);
-	}
-|	'[' LDDD ']' ntype
-	{
-		// array literal of nelem
-		$$ = Nod(OTARRAY, Nod(ODDD, nil, nil), $4);
-	}
-|	LCHAN non_recvchantype
-	{
-		$$ = Nod(OTCHAN, $2, nil);
-		$$.Etype = Cboth;
-	}
-|	LCHAN LCOMM ntype
-	{
-		$$ = Nod(OTCHAN, $3, nil);
-		$$.Etype = Csend;
-	}
-|	LMAP '[' ntype ']' ntype
-	{
-		$$ = Nod(OTMAP, $3, $5);
-	}
-|	structtype
-|	interfacetype
-
-ptrtype:
-	'*' ntype
-	{
-		$$ = Nod(OIND, $2, nil);
-	}
-
-recvchantype:
-	LCOMM LCHAN ntype
-	{
-		$$ = Nod(OTCHAN, $3, nil);
-		$$.Etype = Crecv;
-	}
-
-structtype:
-	LSTRUCT lbrace structdcl_list osemi '}'
-	{
-		$$ = Nod(OTSTRUCT, nil, nil);
-		$$.List = $3;
-		fixlbrace($2);
-	}
-|	LSTRUCT lbrace '}'
-	{
-		$$ = Nod(OTSTRUCT, nil, nil);
-		fixlbrace($2);
-	}
-
-interfacetype:
-	LINTERFACE lbrace interfacedcl_list osemi '}'
-	{
-		$$ = Nod(OTINTER, nil, nil);
-		$$.List = $3;
-		fixlbrace($2);
-	}
-|	LINTERFACE lbrace '}'
-	{
-		$$ = Nod(OTINTER, nil, nil);
-		fixlbrace($2);
-	}
-
-/*
- * function stuff
- * all in one place to show how crappy it all is
- */
-xfndcl:
-	LFUNC fndcl fnbody
-	{
-		$$ = $2;
-		if $$ == nil {
-			break;
-		}
-		if noescape && $3 != nil {
-			Yyerror("can only use //go:noescape with external func implementations");
-		}
-		$$.Nbody = $3;
-		$$.Func.Endlineno = lineno;
-		$$.Noescape = noescape;
-		$$.Func.Norace = norace;
-		$$.Func.Nosplit = nosplit;
-		$$.Func.Nowritebarrier = nowritebarrier;
-		$$.Func.Systemstack = systemstack;
-		funcbody($$);
-	}
-
-fndcl:
-	sym '(' oarg_type_list_ocomma ')' fnres
-	{
-		var t *Node
-
-		$$ = nil;
-		$3 = checkarglist($3, 1);
-
-		if $1.Name == "init" {
-			$1 = renameinit();
-			if $3 != nil || $5 != nil {
-				Yyerror("func init must have no arguments and no return values");
-			}
-		}
-		if localpkg.Name == "main" && $1.Name == "main" {
-			if $3 != nil || $5 != nil {
-				Yyerror("func main must have no arguments and no return values");
-			}
-		}
-
-		t = Nod(OTFUNC, nil, nil);
-		t.List = $3;
-		t.Rlist = $5;
-
-		$$ = Nod(ODCLFUNC, nil, nil);
-		$$.Func.Nname = newfuncname($1);
-		$$.Func.Nname.Name.Defn = $$;
-		$$.Func.Nname.Name.Param.Ntype = t;		// TODO: check if nname already has an ntype
-		declare($$.Func.Nname, PFUNC);
-
-		funchdr($$);
-	}
-|	'(' oarg_type_list_ocomma ')' sym '(' oarg_type_list_ocomma ')' fnres
-	{
-		var rcvr, t *Node
-
-		$$ = nil;
-		$2 = checkarglist($2, 0);
-		$6 = checkarglist($6, 1);
-
-		if $2 == nil {
-			Yyerror("method has no receiver");
-			break;
-		}
-		if $2.Next != nil {
-			Yyerror("method has multiple receivers");
-			break;
-		}
-		rcvr = $2.N;
-		if rcvr.Op != ODCLFIELD {
-			Yyerror("bad receiver in method");
-			break;
-		}
-
-		t = Nod(OTFUNC, rcvr, nil);
-		t.List = $6;
-		t.Rlist = $8;
-
-		$$ = Nod(ODCLFUNC, nil, nil);
-		$$.Func.Shortname = newfuncname($4);
-		$$.Func.Nname = methodname1($$.Func.Shortname, rcvr.Right);
-		$$.Func.Nname.Name.Defn = $$;
-		$$.Func.Nname.Name.Param.Ntype = t;
-		$$.Func.Nname.Nointerface = nointerface;
-		declare($$.Func.Nname, PFUNC);
-
-		funchdr($$);
-	}
-
-hidden_fndcl:
-	hidden_pkg_importsym '(' ohidden_funarg_list ')' ohidden_funres
-	{
-		var s *Sym
-		var t *Type
-
-		$$ = nil;
-
-		s = $1;
-		t = functype(nil, $3, $5);
-
-		importsym(s, ONAME);
-		if s.Def != nil && s.Def.Op == ONAME {
-			if Eqtype(t, s.Def.Type) {
-				dclcontext = PDISCARD;  // since we skip funchdr below
-				break;
-			}
-			Yyerror("inconsistent definition for func %v during import\n\t%v\n\t%v", s, s.Def.Type, t);
-		}
-
-		$$ = newfuncname(s);
-		$$.Type = t;
-		declare($$, PFUNC);
-
-		funchdr($$);
-	}
-|	'(' hidden_funarg_list ')' sym '(' ohidden_funarg_list ')' ohidden_funres
-	{
-		$$ = methodname1(newname($4), $2.N.Right); 
-		$$.Type = functype($2.N, $6, $8);
-
-		checkwidth($$.Type);
-		addmethod($4, $$.Type, false, nointerface);
-		nointerface = false
-		funchdr($$);
-		
-		// inl.C's inlnode in on a dotmeth node expects to find the inlineable body as
-		// (dotmeth's type).Nname.Inl, and dotmeth's type has been pulled
-		// out by typecheck's lookdot as this $$.ttype.  So by providing
-		// this back link here we avoid special casing there.
-		$$.Type.Nname = $$;
-	}
-
-fntype:
-	LFUNC '(' oarg_type_list_ocomma ')' fnres
-	{
-		$3 = checkarglist($3, 1);
-		$$ = Nod(OTFUNC, nil, nil);
-		$$.List = $3;
-		$$.Rlist = $5;
-	}
-
-fnbody:
-	{
-		$$ = nil;
-	}
-|	'{' stmt_list '}'
-	{
-		$$ = $2;
-		if $$ == nil {
-			$$ = list1(Nod(OEMPTY, nil, nil));
-		}
-	}
-
-fnres:
-	%prec NotParen
-	{
-		$$ = nil;
-	}
-|	fnret_type
-	{
-		$$ = list1(Nod(ODCLFIELD, nil, $1));
-	}
-|	'(' oarg_type_list_ocomma ')'
-	{
-		$2 = checkarglist($2, 0);
-		$$ = $2;
-	}
-
-fnlitdcl:
-	fntype
-	{
-		closurehdr($1);
-	}
-
-fnliteral:
-	fnlitdcl lbrace stmt_list '}'
-	{
-		$$ = closurebody($3);
-		fixlbrace($2);
-	}
-|	fnlitdcl error
-	{
-		$$ = closurebody(nil);
-	}
-
-/*
- * lists of things
- * note that they are left recursive
- * to conserve yacc stack. they need to
- * be reversed to interpret correctly
- */
-xdcl_list:
-	{
-		$$ = nil;
-	}
-|	xdcl_list xdcl ';'
-	{
-		$$ = concat($1, $2);
-		if nsyntaxerrors == 0 {
-			testdclstack();
-		}
-		nointerface = false
-		noescape = false
-		norace = false
-		nosplit = false
-		nowritebarrier = false
-		systemstack = false
-	}
-
-vardcl_list:
-	vardcl
-|	vardcl_list ';' vardcl
-	{
-		$$ = concat($1, $3);
-	}
-
-constdcl_list:
-	constdcl1
-|	constdcl_list ';' constdcl1
-	{
-		$$ = concat($1, $3);
-	}
-
-typedcl_list:
-	typedcl
-	{
-		$$ = list1($1);
-	}
-|	typedcl_list ';' typedcl
-	{
-		$$ = list($1, $3);
-	}
-
-structdcl_list:
-	structdcl
-|	structdcl_list ';' structdcl
-	{
-		$$ = concat($1, $3);
-	}
-
-interfacedcl_list:
-	interfacedcl
-	{
-		$$ = list1($1);
-	}
-|	interfacedcl_list ';' interfacedcl
-	{
-		$$ = list($1, $3);
-	}
-
-structdcl:
-	new_name_list ntype oliteral
-	{
-		var l *NodeList
-
-		var n *Node
-		l = $1;
-		if l == nil || l.N.Sym.Name == "?" {
-			// ? symbol, during import (list1(nil) == nil)
-			n = $2;
-			if n.Op == OIND {
-				n = n.Left;
-			}
-			n = embedded(n.Sym, importpkg);
-			n.Right = $2;
-			n.SetVal($3)
-			$$ = list1(n);
-			break;
-		}
-
-		for l=$1; l != nil; l=l.Next {
-			l.N = Nod(ODCLFIELD, l.N, $2);
-			l.N.SetVal($3)
-		}
-	}
-|	embed oliteral
-	{
-		$1.SetVal($2)
-		$$ = list1($1);
-	}
-|	'(' embed ')' oliteral
-	{
-		$2.SetVal($4)
-		$$ = list1($2);
-		Yyerror("cannot parenthesize embedded type");
-	}
-|	'*' embed oliteral
-	{
-		$2.Right = Nod(OIND, $2.Right, nil);
-		$2.SetVal($3)
-		$$ = list1($2);
-	}
-|	'(' '*' embed ')' oliteral
-	{
-		$3.Right = Nod(OIND, $3.Right, nil);
-		$3.SetVal($5)
-		$$ = list1($3);
-		Yyerror("cannot parenthesize embedded type");
-	}
-|	'*' '(' embed ')' oliteral
-	{
-		$3.Right = Nod(OIND, $3.Right, nil);
-		$3.SetVal($5)
-		$$ = list1($3);
-		Yyerror("cannot parenthesize embedded type");
-	}
-
-packname:
-	LNAME
-	{
-		var n *Node
-
-		$$ = $1;
-		n = oldname($1);
-		if n.Name != nil && n.Name.Pack != nil {
-			n.Name.Pack.Used = true;
-		}
-	}
-|	LNAME '.' sym
-	{
-		var pkg *Pkg
-
-		if $1.Def == nil || $1.Def.Op != OPACK {
-			Yyerror("%v is not a package", $1);
-			pkg = localpkg;
-		} else {
-			$1.Def.Used = true;
-			pkg = $1.Def.Name.Pkg;
-		}
-		$$ = restrictlookup($3.Name, pkg);
-	}
-
-embed:
-	packname
-	{
-		$$ = embedded($1, localpkg);
-	}
-
-interfacedcl:
-	new_name indcl
-	{
-		$$ = Nod(ODCLFIELD, $1, $2);
-		ifacedcl($$);
-	}
-|	packname
-	{
-		$$ = Nod(ODCLFIELD, nil, oldname($1));
-	}
-|	'(' packname ')'
-	{
-		$$ = Nod(ODCLFIELD, nil, oldname($2));
-		Yyerror("cannot parenthesize embedded type");
-	}
-
-indcl:
-	'(' oarg_type_list_ocomma ')' fnres
-	{
-		// without func keyword
-		$2 = checkarglist($2, 1);
-		$$ = Nod(OTFUNC, fakethis(), nil);
-		$$.List = $2;
-		$$.Rlist = $4;
-	}
-
-/*
- * function arguments.
- */
-arg_type:
-	name_or_type
-|	sym name_or_type
-	{
-		$$ = Nod(ONONAME, nil, nil);
-		$$.Sym = $1;
-		$$ = Nod(OKEY, $$, $2);
-	}
-|	sym dotdotdot
-	{
-		$$ = Nod(ONONAME, nil, nil);
-		$$.Sym = $1;
-		$$ = Nod(OKEY, $$, $2);
-	}
-|	dotdotdot
-
-arg_type_list:
-	arg_type
-	{
-		$$ = list1($1);
-	}
-|	arg_type_list ',' arg_type
-	{
-		$$ = list($1, $3);
-	}
-
-oarg_type_list_ocomma:
-	{
-		$$ = nil;
-	}
-|	arg_type_list ocomma
-	{
-		$$ = $1;
-	}
-
-/*
- * statement
- */
-stmt:
-	{
-		$$ = nil;
-	}
-|	compound_stmt
-|	common_dcl
-	{
-		$$ = liststmt($1);
-	}
-|	non_dcl_stmt
-|	error
-	{
-		$$ = nil;
-	}
-
-non_dcl_stmt:
-	simple_stmt
-|	for_stmt
-|	switch_stmt
-|	select_stmt
-|	if_stmt
-|	labelname ':'
-	{
-		$1 = Nod(OLABEL, $1, nil);
-		$1.Sym = dclstack;  // context, for goto restrictions
-	}
-	stmt
-	{
-		var l *NodeList
-
-		$1.Name.Defn = $4;
-		l = list1($1);
-		if $4 != nil {
-			l = list(l, $4);
-		}
-		$$ = liststmt(l);
-	}
-|	LFALL
-	{
-		// will be converted to OFALL
-		$$ = Nod(OXFALL, nil, nil);
-		$$.Xoffset = int64(block);
-	}
-|	LBREAK onew_name
-	{
-		$$ = Nod(OBREAK, $2, nil);
-	}
-|	LCONTINUE onew_name
-	{
-		$$ = Nod(OCONTINUE, $2, nil);
-	}
-|	LGO pseudocall
-	{
-		$$ = Nod(OPROC, $2, nil);
-	}
-|	LDEFER pseudocall
-	{
-		$$ = Nod(ODEFER, $2, nil);
-	}
-|	LGOTO new_name
-	{
-		$$ = Nod(OGOTO, $2, nil);
-		$$.Sym = dclstack;  // context, for goto restrictions
-	}
-|	LRETURN oexpr_list
-	{
-		$$ = Nod(ORETURN, nil, nil);
-		$$.List = $2;
-		if $$.List == nil && Curfn != nil {
-			var l *NodeList
-
-			for l=Curfn.Func.Dcl; l != nil; l=l.Next {
-				if l.N.Class == PPARAM {
-					continue;
-				}
-				if l.N.Class != PPARAMOUT {
-					break;
-				}
-				if l.N.Sym.Def != l.N {
-					Yyerror("%s is shadowed during return", l.N.Sym.Name);
-				}
-			}
-		}
-	}
-
-stmt_list:
-	stmt
-	{
-		$$ = nil;
-		if $1 != nil {
-			$$ = list1($1);
-		}
-	}
-|	stmt_list ';' stmt
-	{
-		$$ = $1;
-		if $3 != nil {
-			$$ = list($$, $3);
-		}
-	}
-
-new_name_list:
-	new_name
-	{
-		$$ = list1($1);
-	}
-|	new_name_list ',' new_name
-	{
-		$$ = list($1, $3);
-	}
-
-dcl_name_list:
-	dcl_name
-	{
-		$$ = list1($1);
-	}
-|	dcl_name_list ',' dcl_name
-	{
-		$$ = list($1, $3);
-	}
-
-expr_list:
-	expr
-	{
-		$$ = list1($1);
-	}
-|	expr_list ',' expr
-	{
-		$$ = list($1, $3);
-	}
-
-expr_or_type_list:
-	expr_or_type
-	{
-		$$ = list1($1);
-	}
-|	expr_or_type_list ',' expr_or_type
-	{
-		$$ = list($1, $3);
-	}
-
-/*
- * list of combo of keyval and val
- */
-keyval_list:
-	keyval
-	{
-		$$ = list1($1);
-	}
-|	bare_complitexpr
-	{
-		$$ = list1($1);
-	}
-|	keyval_list ',' keyval
-	{
-		$$ = list($1, $3);
-	}
-|	keyval_list ',' bare_complitexpr
-	{
-		$$ = list($1, $3);
-	}
-
-braced_keyval_list:
-	{
-		$$ = nil;
-	}
-|	keyval_list ocomma
-	{
-		$$ = $1;
-	}
-
-/*
- * optional things
- */
-osemi:
-|	';'
-
-ocomma:
-|	','
-
-oexpr:
-	{
-		$$ = nil;
-	}
-|	expr
-
-oexpr_list:
-	{
-		$$ = nil;
-	}
-|	expr_list
-
-osimple_stmt:
-	{
-		$$ = nil;
-	}
-|	simple_stmt
-
-ohidden_funarg_list:
-	{
-		$$ = nil;
-	}
-|	hidden_funarg_list
-
-ohidden_structdcl_list:
-	{
-		$$ = nil;
-	}
-|	hidden_structdcl_list
-
-ohidden_interfacedcl_list:
-	{
-		$$ = nil;
-	}
-|	hidden_interfacedcl_list
-
-oliteral:
-	{
-		$$.U = nil
-	}
-|	LLITERAL
-
-/*
- * import syntax from package header
- */
-hidden_import:
-	LIMPORT LNAME LLITERAL ';'
-	{
-		importimport($2, $3.U.(string));
-	}
-|	LVAR hidden_pkg_importsym hidden_type ';'
-	{
-		importvar($2, $3);
-	}
-|	LCONST hidden_pkg_importsym '=' hidden_constant ';'
-	{
-		importconst($2, Types[TIDEAL], $4);
-	}
-|	LCONST hidden_pkg_importsym hidden_type '=' hidden_constant ';'
-	{
-		importconst($2, $3, $5);
-	}
-|	LTYPE hidden_pkgtype hidden_type ';'
-	{
-		importtype($2, $3);
-	}
-|	LFUNC hidden_fndcl fnbody ';'
-	{
-		if $2 == nil {
-			dclcontext = PEXTERN;  // since we skip the funcbody below
-			break;
-		}
-
-		$2.Func.Inl = $3;
-
-		funcbody($2);
-		importlist = list(importlist, $2);
-
-		if Debug['E'] > 0 {
-			fmt.Printf("import [%q] func %v \n", importpkg.Path, $2)
-			if Debug['m'] > 2 && $2.Func.Inl != nil {
-				fmt.Printf("inl body:%v\n", $2.Func.Inl)
-			}
-		}
-	}
-
-hidden_pkg_importsym:
-	hidden_importsym
-	{
-		$$ = $1;
-		structpkg = $$.Pkg;
-	}
-
-hidden_pkgtype:
-	hidden_pkg_importsym
-	{
-		$$ = pkgtype($1);
-		importsym($1, OTYPE);
-	}
-
-/*
- *  importing types
- */
-
-hidden_type:
-	hidden_type_misc
-|	hidden_type_recv_chan
-|	hidden_type_func
-
-hidden_type_non_recv_chan:
-	hidden_type_misc
-|	hidden_type_func
-
-hidden_type_misc:
-	hidden_importsym
-	{
-		$$ = pkgtype($1);
-	}
-|	LNAME
-	{
-		// predefined name like uint8
-		$1 = Pkglookup($1.Name, builtinpkg);
-		if $1.Def == nil || $1.Def.Op != OTYPE {
-			Yyerror("%s is not a type", $1.Name);
-			$$ = nil;
-		} else {
-			$$ = $1.Def.Type;
-		}
-	}
-|	'[' ']' hidden_type
-	{
-		$$ = aindex(nil, $3);
-	}
-|	'[' LLITERAL ']' hidden_type
-	{
-		$$ = aindex(nodlit($2), $4);
-	}
-|	LMAP '[' hidden_type ']' hidden_type
-	{
-		$$ = maptype($3, $5);
-	}
-|	LSTRUCT '{' ohidden_structdcl_list '}'
-	{
-		$$ = tostruct($3);
-	}
-|	LINTERFACE '{' ohidden_interfacedcl_list '}'
-	{
-		$$ = tointerface($3);
-	}
-|	'*' hidden_type
-	{
-		$$ = Ptrto($2);
-	}
-|	LCHAN hidden_type_non_recv_chan
-	{
-		$$ = typ(TCHAN);
-		$$.Type = $2;
-		$$.Chan = Cboth;
-	}
-|	LCHAN '(' hidden_type_recv_chan ')'
-	{
-		$$ = typ(TCHAN);
-		$$.Type = $3;
-		$$.Chan = Cboth;
-	}
-|	LCHAN LCOMM hidden_type
-	{
-		$$ = typ(TCHAN);
-		$$.Type = $3;
-		$$.Chan = Csend;
-	}
-
-hidden_type_recv_chan:
-	LCOMM LCHAN hidden_type
-	{
-		$$ = typ(TCHAN);
-		$$.Type = $3;
-		$$.Chan = Crecv;
-	}
-
-hidden_type_func:
-	LFUNC '(' ohidden_funarg_list ')' ohidden_funres
-	{
-		$$ = functype(nil, $3, $5);
-	}
-
-hidden_funarg:
-	sym hidden_type oliteral
-	{
-		$$ = Nod(ODCLFIELD, nil, typenod($2));
-		if $1 != nil {
-			$$.Left = newname($1);
-		}
-		$$.SetVal($3)
-	}
-|	sym LDDD hidden_type oliteral
-	{
-		var t *Type
-	
-		t = typ(TARRAY);
-		t.Bound = -1;
-		t.Type = $3;
-
-		$$ = Nod(ODCLFIELD, nil, typenod(t));
-		if $1 != nil {
-			$$.Left = newname($1);
-		}
-		$$.Isddd = true;
-		$$.SetVal($4)
-	}
-
-hidden_structdcl:
-	sym hidden_type oliteral
-	{
-		var s *Sym
-		var p *Pkg
-
-		if $1 != nil && $1.Name != "?" {
-			$$ = Nod(ODCLFIELD, newname($1), typenod($2));
-			$$.SetVal($3)
-		} else {
-			s = $2.Sym;
-			if s == nil && Isptr[$2.Etype] {
-				s = $2.Type.Sym;
-			}
-			p = importpkg;
-			if $1 != nil {
-				p = $1.Pkg;
-			}
-			$$ = embedded(s, p);
-			$$.Right = typenod($2);
-			$$.SetVal($3)
-		}
-	}
-
-hidden_interfacedcl:
-	sym '(' ohidden_funarg_list ')' ohidden_funres
-	{
-		$$ = Nod(ODCLFIELD, newname($1), typenod(functype(fakethis(), $3, $5)));
-	}
-|	hidden_type
-	{
-		$$ = Nod(ODCLFIELD, nil, typenod($1));
-	}
-
-ohidden_funres:
-	{
-		$$ = nil;
-	}
-|	hidden_funres
-
-hidden_funres:
-	'(' ohidden_funarg_list ')'
-	{
-		$$ = $2;
-	}
-|	hidden_type
-	{
-		$$ = list1(Nod(ODCLFIELD, nil, typenod($1)));
-	}
-
-/*
- *  importing constants
- */
-
-hidden_literal:
-	LLITERAL
-	{
-		$$ = nodlit($1);
-	}
-|	'-' LLITERAL
-	{
-		$$ = nodlit($2);
-		switch($$.Val().Ctype()){
-		case CTINT, CTRUNE:
-			mpnegfix($$.Val().U.(*Mpint));
-			break;
-		case CTFLT:
-			mpnegflt($$.Val().U.(*Mpflt));
-			break;
-		case CTCPLX:
-			mpnegflt(&$$.Val().U.(*Mpcplx).Real);
-			mpnegflt(&$$.Val().U.(*Mpcplx).Imag);
-			break;
-		default:
-			Yyerror("bad negated constant");
-		}
-	}
-|	sym
-	{
-		$$ = oldname(Pkglookup($1.Name, builtinpkg));
-		if $$.Op != OLITERAL {
-			Yyerror("bad constant %v", $$.Sym);
-		}
-	}
-
-hidden_constant:
-	hidden_literal
-|	'(' hidden_literal '+' hidden_literal ')'
-	{
-		if $2.Val().Ctype() == CTRUNE && $4.Val().Ctype() == CTINT {
-			$$ = $2;
-			mpaddfixfix($2.Val().U.(*Mpint), $4.Val().U.(*Mpint), 0);
-			break;
-		}
-		$4.Val().U.(*Mpcplx).Real = $4.Val().U.(*Mpcplx).Imag;
-		Mpmovecflt(&$4.Val().U.(*Mpcplx).Imag, 0.0);
-		$$ = nodcplxlit($2.Val(), $4.Val());
-	}
-
-hidden_import_list:
-|	hidden_import_list hidden_import
-
-hidden_funarg_list:
-	hidden_funarg
-	{
-		$$ = list1($1);
-	}
-|	hidden_funarg_list ',' hidden_funarg
-	{
-		$$ = list($1, $3);
-	}
-
-hidden_structdcl_list:
-	hidden_structdcl
-	{
-		$$ = list1($1);
-	}
-|	hidden_structdcl_list ';' hidden_structdcl
-	{
-		$$ = list($1, $3);
-	}
-
-hidden_interfacedcl_list:
-	hidden_interfacedcl
-	{
-		$$ = list1($1);
-	}
-|	hidden_interfacedcl_list ';' hidden_interfacedcl
-	{
-		$$ = list($1, $3);
-	}
-
-%%
-func fixlbrace(lbr int) {
-	// If the opening brace was an LBODY,
-	// set up for another one now that we're done.
-	// See comment in lex.C about loophack.
-	if lbr == LBODY {
-		loophack = 1
-	}
-}
diff --git a/src/cmd/compile/internal/gc/gsubr.go b/src/cmd/compile/internal/gc/gsubr.go
index 2c575f3..30bf736 100644
--- a/src/cmd/compile/internal/gc/gsubr.go
+++ b/src/cmd/compile/internal/gc/gsubr.go
@@ -43,9 +43,7 @@ var dfirst *obj.Prog
 
 var dpc *obj.Prog
 
-/*
- * Is this node a memory operand?
- */
+// Is this node a memory operand?
 func Ismem(n *Node) bool {
 	switch n.Op {
 	case OITAB,
@@ -85,9 +83,11 @@ func Gbranch(as int, t *Type, likely int) *obj.Prog {
 	p := Prog(as)
 	p.To.Type = obj.TYPE_BRANCH
 	p.To.Val = nil
-	if as != obj.AJMP && likely != 0 && Thearch.Thechar != '9' && Thearch.Thechar != '7' {
+	if as != obj.AJMP && likely != 0 && Thearch.Thechar != '9' && Thearch.Thechar != '7' && Thearch.Thechar != '0' {
 		p.From.Type = obj.TYPE_CONST
-		p.From.Offset = int64(obj.Bool2int(likely > 0))
+		if likely > 0 {
+			p.From.Offset = 1
+		}
 	}
 
 	if Debug['g'] != 0 {
@@ -102,7 +102,7 @@ func Prog(as int) *obj.Prog {
 
 	if as == obj.ADATA || as == obj.AGLOBL {
 		if ddumped != 0 {
-			Fatal("already dumped data")
+			Fatalf("already dumped data")
 		}
 		if dpc == nil {
 			dpc = Ctxt.NewProg()
@@ -132,7 +132,7 @@ func Prog(as int) *obj.Prog {
 
 func Nodreg(n *Node, t *Type, r int) {
 	if t == nil {
-		Fatal("nodreg: t nil")
+		Fatalf("nodreg: t nil")
 	}
 
 	*n = Node{}
@@ -185,7 +185,7 @@ func fixautoused(p *obj.Prog) {
 			continue
 		}
 
-		if (p.As == obj.AVARDEF || p.As == obj.AVARKILL) && p.To.Node != nil && !((p.To.Node).(*Node)).Used {
+		if (p.As == obj.AVARDEF || p.As == obj.AVARKILL || p.As == obj.AVARLIVE) && p.To.Node != nil && !((p.To.Node).(*Node)).Used {
 			// Cannot remove VARDEF instruction, because - unlike TYPE handled above -
 			// VARDEFs are interspersed with other code, and a jump might be using the
 			// VARDEF as a target. Replace with a no-op instead. A later pass will remove
@@ -310,7 +310,7 @@ func Naddr(a *obj.Addr, n *Node) {
 		a := a // copy to let escape into Ctxt.Dconv
 		Debug['h'] = 1
 		Dump("naddr", n)
-		Fatal("naddr: bad %v %v", Oconv(int(n.Op), 0), Ctxt.Dconv(a))
+		Fatalf("naddr: bad %v %v", Oconv(int(n.Op), 0), Ctxt.Dconv(a))
 
 	case OREGISTER:
 		a.Type = obj.TYPE_REG
@@ -335,7 +335,7 @@ func Naddr(a *obj.Addr, n *Node) {
 		// n->left is PHEAP ONAME for stack parameter.
 	// compute address of actual parameter on stack.
 	case OPARAM:
-		a.Etype = Simtype[n.Left.Type.Etype]
+		a.Etype = uint8(Simtype[n.Left.Type.Etype])
 
 		a.Width = n.Left.Type.Width
 		a.Offset = n.Xoffset
@@ -346,7 +346,7 @@ func Naddr(a *obj.Addr, n *Node) {
 
 	case OCLOSUREVAR:
 		if !Curfn.Func.Needctxt {
-			Fatal("closurevar without needctxt")
+			Fatalf("closurevar without needctxt")
 		}
 		a.Type = obj.TYPE_MEM
 		a.Reg = int16(Thearch.REGCTXT)
@@ -360,7 +360,7 @@ func Naddr(a *obj.Addr, n *Node) {
 	case ONAME:
 		a.Etype = 0
 		if n.Type != nil {
-			a.Etype = Simtype[n.Type.Etype]
+			a.Etype = uint8(Simtype[n.Type.Etype])
 		}
 		a.Offset = n.Xoffset
 		s := n.Sym
@@ -384,7 +384,7 @@ func Naddr(a *obj.Addr, n *Node) {
 		a.Type = obj.TYPE_MEM
 		switch n.Class {
 		default:
-			Fatal("naddr: ONAME class %v %d\n", n.Sym, n.Class)
+			Fatalf("naddr: ONAME class %v %d\n", n.Sym, n.Class)
 
 		case PEXTERN:
 			a.Name = obj.NAME_EXTERN
@@ -404,13 +404,24 @@ func Naddr(a *obj.Addr, n *Node) {
 
 		a.Sym = Linksym(s)
 
+	case ODOT:
+		// A special case to make write barriers more efficient.
+		// Taking the address of the first field of a named struct
+		// is the same as taking the address of the struct.
+		if n.Left.Type.Etype != TSTRUCT || n.Left.Type.Type.Sym != n.Right.Sym {
+			Debug['h'] = 1
+			Dump("naddr", n)
+			Fatalf("naddr: bad %v %v", Oconv(int(n.Op), 0), Ctxt.Dconv(a))
+		}
+		Naddr(a, n.Left)
+
 	case OLITERAL:
 		if Thearch.Thechar == '8' {
 			a.Width = 0
 		}
 		switch n.Val().Ctype() {
 		default:
-			Fatal("naddr: const %v", Tconv(n.Type, obj.FmtLong))
+			Fatalf("naddr: const %v", Tconv(n.Type, obj.FmtLong))
 
 		case CTFLT:
 			a.Type = obj.TYPE_FCONST
@@ -438,12 +449,12 @@ func Naddr(a *obj.Addr, n *Node) {
 	case OADDR:
 		Naddr(a, n.Left)
 		a.Etype = uint8(Tptr)
-		if Thearch.Thechar != '5' && Thearch.Thechar != '7' && Thearch.Thechar != '9' { // TODO(rsc): Do this even for arm, ppc64.
+		if Thearch.Thechar != '0' && Thearch.Thechar != '5' && Thearch.Thechar != '7' && Thearch.Thechar != '9' { // TODO(rsc): Do this even for arm, ppc64.
 			a.Width = int64(Widthptr)
 		}
 		if a.Type != obj.TYPE_MEM {
 			a := a // copy to let escape into Ctxt.Dconv
-			Fatal("naddr: OADDR %v (from %v)", Ctxt.Dconv(a), Oconv(int(n.Left.Op), 0))
+			Fatalf("naddr: OADDR %v (from %v)", Ctxt.Dconv(a), Oconv(int(n.Left.Op), 0))
 		}
 		a.Type = obj.TYPE_ADDR
 
@@ -464,7 +475,7 @@ func Naddr(a *obj.Addr, n *Node) {
 		if a.Type == obj.TYPE_CONST && a.Offset == 0 {
 			break // ptr(nil)
 		}
-		a.Etype = Simtype[Tptr]
+		a.Etype = uint8(Simtype[Tptr])
 		a.Offset += int64(Array_array)
 		a.Width = int64(Widthptr)
 
@@ -475,7 +486,7 @@ func Naddr(a *obj.Addr, n *Node) {
 		if a.Type == obj.TYPE_CONST && a.Offset == 0 {
 			break // len(nil)
 		}
-		a.Etype = Simtype[TUINT]
+		a.Etype = uint8(Simtype[TUINT])
 		a.Offset += int64(Array_nel)
 		if Thearch.Thechar != '5' { // TODO(rsc): Do this even on arm.
 			a.Width = int64(Widthint)
@@ -488,7 +499,7 @@ func Naddr(a *obj.Addr, n *Node) {
 		if a.Type == obj.TYPE_CONST && a.Offset == 0 {
 			break // cap(nil)
 		}
-		a.Etype = Simtype[TUINT]
+		a.Etype = uint8(Simtype[TUINT])
 		a.Offset += int64(Array_cap)
 		if Thearch.Thechar != '5' { // TODO(rsc): Do this even on arm.
 			a.Width = int64(Widthint)
@@ -511,17 +522,17 @@ func nodarg(t *Type, fp int) *Node {
 	var n *Node
 
 	// entire argument struct, not just one arg
-	if t.Etype == TSTRUCT && t.Funarg != 0 {
+	if t.Etype == TSTRUCT && t.Funarg {
 		n = Nod(ONAME, nil, nil)
 		n.Sym = Lookup(".args")
 		n.Type = t
 		var savet Iter
 		first := Structfirst(&savet, &t)
 		if first == nil {
-			Fatal("nodarg: bad struct")
+			Fatalf("nodarg: bad struct")
 		}
 		if first.Width == BADWIDTH {
-			Fatal("nodarg: offset not computed for %v", t)
+			Fatalf("nodarg: offset not computed for %v", t)
 		}
 		n.Xoffset = first.Width
 		n.Addable = true
@@ -529,7 +540,7 @@ func nodarg(t *Type, fp int) *Node {
 	}
 
 	if t.Etype != TFIELD {
-		Fatal("nodarg: not field %v", t)
+		Fatalf("nodarg: not field %v", t)
 	}
 
 	if fp == 1 {
@@ -547,7 +558,7 @@ func nodarg(t *Type, fp int) *Node {
 	n.Sym = t.Sym
 
 	if t.Width == BADWIDTH {
-		Fatal("nodarg: offset not computed for %v", t)
+		Fatalf("nodarg: offset not computed for %v", t)
 	}
 	n.Xoffset = t.Width
 	n.Addable = true
@@ -566,15 +577,13 @@ fp:
 		n.Op = OINDREG
 
 		n.Reg = int16(Thearch.REGSP)
-		if HasLinkRegister() {
-			n.Xoffset += int64(Ctxt.Arch.Ptrsize)
-		}
+		n.Xoffset += Ctxt.FixedFrameSize()
 
 	case 1: // input arg
 		n.Class = PPARAM
 
 	case 2: // offset output arg
-		Fatal("shouldn't be used")
+		Fatalf("shouldn't be used")
 	}
 
 	n.Typecheck = 1
@@ -583,7 +592,7 @@ fp:
 
 func Patch(p *obj.Prog, to *obj.Prog) {
 	if p.To.Type != obj.TYPE_BRANCH {
-		Fatal("patch: not a branch")
+		Fatalf("patch: not a branch")
 	}
 	p.To.Val = to
 	p.To.Offset = to.Pc
@@ -591,7 +600,7 @@ func Patch(p *obj.Prog, to *obj.Prog) {
 
 func unpatch(p *obj.Prog) *obj.Prog {
 	if p.To.Type != obj.TYPE_BRANCH {
-		Fatal("unpatch: not a branch")
+		Fatalf("unpatch: not a branch")
 	}
 	q, _ := p.To.Val.(*obj.Prog)
 	p.To.Val = nil
@@ -662,25 +671,23 @@ func Anyregalloc() bool {
 	return n > len(Thearch.ReservedRegs)
 }
 
-/*
- * allocate register of type t, leave in n.
- * if o != N, o may be reusable register.
- * caller must Regfree(n).
- */
+// allocate register of type t, leave in n.
+// if o != N, o may be reusable register.
+// caller must Regfree(n).
 func Regalloc(n *Node, t *Type, o *Node) {
 	if t == nil {
-		Fatal("regalloc: t nil")
+		Fatalf("regalloc: t nil")
 	}
-	et := int(Simtype[t.Etype])
+	et := Simtype[t.Etype]
 	if Ctxt.Arch.Regsize == 4 && (et == TINT64 || et == TUINT64) {
-		Fatal("regalloc 64bit")
+		Fatalf("regalloc 64bit")
 	}
 
 	var i int
 Switch:
 	switch et {
 	default:
-		Fatal("regalloc: unknown type %v", t)
+		Fatalf("regalloc: unknown type %v", t)
 
 	case TINT8, TUINT8, TINT16, TUINT16, TINT32, TUINT32, TINT64, TUINT64, TPTR32, TPTR64, TBOOL:
 		if o != nil && o.Op == OREGISTER {
@@ -696,7 +703,7 @@ Switch:
 		}
 		Flusherrors()
 		Regdump()
-		Fatal("out of fixed registers")
+		Fatalf("out of fixed registers")
 
 	case TFLOAT32, TFLOAT64:
 		if Thearch.Use387 {
@@ -716,7 +723,7 @@ Switch:
 		}
 		Flusherrors()
 		Regdump()
-		Fatal("out of floating registers")
+		Fatalf("out of floating registers")
 
 	case TCOMPLEX64, TCOMPLEX128:
 		Tempname(n, t)
@@ -741,7 +748,7 @@ func Regfree(n *Node) {
 		return
 	}
 	if n.Op != OREGISTER && n.Op != OINDREG {
-		Fatal("regfree: not a register")
+		Fatalf("regfree: not a register")
 	}
 	i := int(n.Reg)
 	if i == Thearch.REGSP {
@@ -752,12 +759,12 @@ func Regfree(n *Node) {
 		Thearch.FREGMIN <= i && i <= Thearch.FREGMAX:
 		// ok
 	default:
-		Fatal("regfree: reg out of range")
+		Fatalf("regfree: reg out of range")
 	}
 
 	i -= Thearch.REGMIN
 	if reg[i] <= 0 {
-		Fatal("regfree: reg not allocated")
+		Fatalf("regfree: reg not allocated")
 	}
 	reg[i]--
 	if reg[i] == 0 {
@@ -772,7 +779,7 @@ func Reginuse(r int) bool {
 		Thearch.FREGMIN <= r && r <= Thearch.FREGMAX:
 		// ok
 	default:
-		Fatal("reginuse: reg out of range")
+		Fatalf("reginuse: reg out of range")
 	}
 
 	return reg[r-Thearch.REGMIN] > 0
@@ -782,7 +789,7 @@ func Reginuse(r int) bool {
 // so that a register can be given up but then reclaimed.
 func Regrealloc(n *Node) {
 	if n.Op != OREGISTER && n.Op != OINDREG {
-		Fatal("regrealloc: not a register")
+		Fatalf("regrealloc: not a register")
 	}
 	i := int(n.Reg)
 	if i == Thearch.REGSP {
@@ -793,7 +800,7 @@ func Regrealloc(n *Node) {
 		Thearch.FREGMIN <= i && i <= Thearch.FREGMAX:
 		// ok
 	default:
-		Fatal("regrealloc: reg out of range")
+		Fatalf("regrealloc: reg out of range")
 	}
 
 	i -= Thearch.REGMIN
diff --git a/src/cmd/compile/internal/gc/init.go b/src/cmd/compile/internal/gc/init.go
index 5fbc82d..6071ab4 100644
--- a/src/cmd/compile/internal/gc/init.go
+++ b/src/cmd/compile/internal/gc/init.go
@@ -17,13 +17,11 @@ package gc
 //		a->offset += v;
 //		break;
 
-/*
- * a function named init is a special case.
- * it is called by the initialization before
- * main is run. to make it unique within a
- * package and also uncallable, the name,
- * normally "pkg.init", is altered to "pkg.init.1".
- */
+// a function named init is a special case.
+// it is called by the initialization before
+// main is run. to make it unique within a
+// package and also uncallable, the name,
+// normally "pkg.init", is altered to "pkg.init.1".
 
 var renameinit_initgen int
 
@@ -32,24 +30,22 @@ func renameinit() *Sym {
 	return Lookupf("init.%d", renameinit_initgen)
 }
 
-/*
- * hand-craft the following initialization code
- *	var initdone· uint8 				(1)
- *	func init()					(2)
- *		if initdone· != 0 {			(3)
- *			if initdone· == 2		(4)
- *				return
- *			throw();			(5)
- *		}
- *		initdone· = 1;				(6)
- *		// over all matching imported symbols
- *			<pkg>.init()			(7)
- *		{ <init stmts> }			(8)
- *		init.<n>() // if any			(9)
- *		initdone· = 2;				(10)
- *		return					(11)
- *	}
- */
+// hand-craft the following initialization code
+//	var initdone· uint8 				(1)
+//	func init()					(2)
+//		if initdone· != 0 {			(3)
+//			if initdone· == 2		(4)
+//				return
+//			throw();			(5)
+//		}
+//		initdone· = 1;				(6)
+//		// over all matching imported symbols
+//			<pkg>.init()			(7)
+//		{ <init stmts> }			(8)
+//		init.<n>() // if any			(9)
+//		initdone· = 2;				(10)
+//		return					(11)
+//	}
 func anyinit(n *NodeList) bool {
 	// are there any interesting init statements
 	for l := n; l != nil; l = l.Next {
diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go
index b2eeeed..64afd67 100644
--- a/src/cmd/compile/internal/gc/inl.go
+++ b/src/cmd/compile/internal/gc/inl.go
@@ -54,7 +54,7 @@ func fnpkg(fn *Node) *Pkg {
 			rcvr = rcvr.Type
 		}
 		if rcvr.Sym == nil {
-			Fatal("receiver with no sym: [%v] %v  (%v)", fn.Sym, Nconv(fn, obj.FmtLong), rcvr)
+			Fatalf("receiver with no sym: [%v] %v  (%v)", fn.Sym, Nconv(fn, obj.FmtLong), rcvr)
 		}
 		return rcvr.Sym.Pkg
 	}
@@ -100,10 +100,15 @@ func typecheckinl(fn *Node) {
 // fn and ->nbody will already have been typechecked.
 func caninl(fn *Node) {
 	if fn.Op != ODCLFUNC {
-		Fatal("caninl %v", fn)
+		Fatalf("caninl %v", fn)
 	}
 	if fn.Func.Nname == nil {
-		Fatal("caninl no nname %v", Nconv(fn, obj.FmtSign))
+		Fatalf("caninl no nname %v", Nconv(fn, obj.FmtSign))
+	}
+
+	// If marked "go:noinline", don't inline
+	if fn.Func.Noinline {
+		return
 	}
 
 	// If fn has no body (is defined outside of Go), cannot inline it.
@@ -112,7 +117,7 @@ func caninl(fn *Node) {
 	}
 
 	if fn.Typecheck == 0 {
-		Fatal("caninl on non-typechecked function %v", fn)
+		Fatalf("caninl on non-typechecked function %v", fn)
 	}
 
 	// can't handle ... args yet
@@ -124,13 +129,13 @@ func caninl(fn *Node) {
 		}
 	}
 
-	// Runtime package must not be race instrumented.
-	// Racewalk skips runtime package. However, some runtime code can be
+	// Runtime package must not be instrumented.
+	// Instrument skips runtime package. However, some runtime code can be
 	// inlined into other packages and instrumented there. To avoid this,
-	// we disable inlining of runtime functions in race mode.
+	// we disable inlining of runtime functions when instrumenting.
 	// The example that we observed is inlining of LockOSThread,
 	// which lead to false race reports on m contents.
-	if flag_race != 0 && myimportpath == "runtime" {
+	if instrumenting && myimportpath == "runtime" {
 		return
 	}
 
@@ -196,10 +201,10 @@ func ishairy(n *Node, budget *int) bool {
 	// Call is okay if inlinable and we have the budget for the body.
 	case OCALLMETH:
 		if n.Left.Type == nil {
-			Fatal("no function type for [%p] %v\n", n.Left, Nconv(n.Left, obj.FmtSign))
+			Fatalf("no function type for [%p] %v\n", n.Left, Nconv(n.Left, obj.FmtSign))
 		}
 		if n.Left.Type.Nname == nil {
-			Fatal("no function definition for [%p] %v\n", n.Left.Type, Tconv(n.Left.Type, obj.FmtSign))
+			Fatalf("no function definition for [%p] %v\n", n.Left.Type, Tconv(n.Left.Type, obj.FmtSign))
 		}
 		if n.Left.Type.Nname.Func.Inl != nil {
 			*budget -= int(n.Left.Type.Nname.Func.InlCost)
@@ -277,7 +282,7 @@ func inlcalls(fn *Node) {
 	Curfn = fn
 	inlnode(&fn)
 	if fn != Curfn {
-		Fatal("inlnode replaced curfn")
+		Fatalf("inlnode replaced curfn")
 	}
 	Curfn = savefn
 }
@@ -308,7 +313,7 @@ func inlconv2expr(np **Node) {
 // statements.
 func inlconv2list(n *Node) *NodeList {
 	if n.Op != OINLCALL || n.Rlist == nil {
-		Fatal("inlconv2list %v\n", Nconv(n, obj.FmtSign))
+		Fatalf("inlconv2list %v\n", Nconv(n, obj.FmtSign))
 	}
 
 	l := n.Rlist
@@ -345,7 +350,8 @@ func inlnode(np **Node) {
 	case ODEFER, OPROC:
 		switch n.Left.Op {
 		case OCALLFUNC, OCALLMETH:
-			n.Left.Etype = n.Op
+			// TODO(marvin): Fix Node.EType type union.
+			n.Left.Etype = EType(n.Op)
 		}
 		fallthrough
 
@@ -445,7 +451,8 @@ func inlnode(np **Node) {
 	// switch at the top of this function.
 	switch n.Op {
 	case OCALLFUNC, OCALLMETH:
-		if n.Etype == OPROC || n.Etype == ODEFER {
+		// TODO(marvin): Fix Node.EType type union.
+		if n.Etype == EType(OPROC) || n.Etype == EType(ODEFER) {
 			return
 		}
 	}
@@ -470,11 +477,11 @@ func inlnode(np **Node) {
 
 		// typecheck should have resolved ODOTMETH->type, whose nname points to the actual function.
 		if n.Left.Type == nil {
-			Fatal("no function type for [%p] %v\n", n.Left, Nconv(n.Left, obj.FmtSign))
+			Fatalf("no function type for [%p] %v\n", n.Left, Nconv(n.Left, obj.FmtSign))
 		}
 
 		if n.Left.Type.Nname == nil {
-			Fatal("no function definition for [%p] %v\n", n.Left.Type, Tconv(n.Left.Type, obj.FmtSign))
+			Fatalf("no function definition for [%p] %v\n", n.Left.Type, Tconv(n.Left.Type, obj.FmtSign))
 		}
 
 		mkinlcall(np, n.Left.Type.Nname, n.Isddd)
@@ -500,7 +507,7 @@ func mkinlcall(np **Node, fn *Node, isddd bool) {
 func tinlvar(t *Type) *Node {
 	if t.Nname != nil && !isblank(t.Nname) {
 		if t.Nname.Name.Inlvar == nil {
-			Fatal("missing inlvar for %v\n", t.Nname)
+			Fatalf("missing inlvar for %v\n", t.Nname)
 		}
 		return t.Nname.Name.Inlvar
 	}
@@ -600,13 +607,13 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
 		t := getthisx(fn.Type).Type
 
 		if t != nil && t.Nname != nil && !isblank(t.Nname) && t.Nname.Name.Inlvar == nil {
-			Fatal("missing inlvar for %v\n", t.Nname)
+			Fatalf("missing inlvar for %v\n", t.Nname)
 		}
 		if n.Left.Left == nil {
-			Fatal("method call without receiver: %v", Nconv(n, obj.FmtSign))
+			Fatalf("method call without receiver: %v", Nconv(n, obj.FmtSign))
 		}
 		if t == nil {
-			Fatal("method call unknown receiver type: %v", Nconv(n, obj.FmtSign))
+			Fatalf("method call unknown receiver type: %v", Nconv(n, obj.FmtSign))
 		}
 		as = Nod(OAS, tinlvar(t), n.Left.Left)
 		if as != nil {
@@ -662,17 +669,17 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
 	if fn.Type.Thistuple != 0 && n.Left.Op != ODOTMETH {
 		// non-method call to method
 		if n.List == nil {
-			Fatal("non-method call to method without first arg: %v", Nconv(n, obj.FmtSign))
+			Fatalf("non-method call to method without first arg: %v", Nconv(n, obj.FmtSign))
 		}
 
 		// append receiver inlvar to LHS.
 		t := getthisx(fn.Type).Type
 
 		if t != nil && t.Nname != nil && !isblank(t.Nname) && t.Nname.Name.Inlvar == nil {
-			Fatal("missing inlvar for %v\n", t.Nname)
+			Fatalf("missing inlvar for %v\n", t.Nname)
 		}
 		if t == nil {
-			Fatal("method call unknown receiver type: %v", Nconv(n, obj.FmtSign))
+			Fatalf("method call unknown receiver type: %v", Nconv(n, obj.FmtSign))
 		}
 		as.List = list(as.List, tinlvar(t))
 		ll = ll.Next // track argument count.
@@ -732,7 +739,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
 		}
 
 		if ll != nil || t != nil {
-			Fatal("arg count mismatch: %v  vs %v\n", Tconv(getinargx(fn.Type), obj.FmtSharp), Hconv(n.List, obj.FmtComma))
+			Fatalf("arg count mismatch: %v  vs %v\n", Tconv(getinargx(fn.Type), obj.FmtSharp), Hconv(n.List, obj.FmtComma))
 		}
 	}
 
@@ -956,7 +963,7 @@ func inlsubst(n *Node) *Node {
 	m.Ninit = nil
 
 	if n.Op == OCLOSURE {
-		Fatal("cannot inline function containing closure: %v", Nconv(n, obj.FmtSign))
+		Fatalf("cannot inline function containing closure: %v", Nconv(n, obj.FmtSign))
 	}
 
 	m.Left = inlsubst(n.Left)
diff --git a/src/cmd/compile/internal/gc/lex.go b/src/cmd/compile/internal/gc/lex.go
index 606298b..b9c2735 100644
--- a/src/cmd/compile/internal/gc/lex.go
+++ b/src/cmd/compile/internal/gc/lex.go
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:generate go tool yacc go.y
 //go:generate go run mkbuiltin.go runtime unsafe
 
 package gc
@@ -22,11 +21,7 @@ import (
 	"unicode/utf8"
 )
 
-var yyprev int
-
-var yylast int
-
-var imported_unsafe int
+var imported_unsafe bool
 
 var (
 	goos    string
@@ -58,34 +53,15 @@ var debugtab = []struct {
 	{"slice", &Debug_slice},           // print information about slice compilation
 	{"typeassert", &Debug_typeassert}, // print information about type assertion inlining
 	{"wb", &Debug_wb},                 // print information about write barriers
+	{"export", &Debug_export},         // print export data
 }
 
-// Our own isdigit, isspace, isalpha, isalnum that take care
-// of EOF and other out of range arguments.
-func yy_isdigit(c int) bool {
-	return c >= 0 && c <= 0xFF && isdigit(c)
-}
-
-func yy_isspace(c int) bool {
-	return c == ' ' || c == '\t' || c == '\n' || c == '\r'
-}
-
-func yy_isalpha(c int) bool {
-	return 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z'
-}
-
-func yy_isalnum(c int) bool {
-	return c >= 0 && c <= 0xFF && isalnum(c)
-}
-
-// Disallow use of isdigit etc.
-
 const (
 	EOF = -1
 )
 
 func usage() {
-	fmt.Printf("usage: %cg [options] file.go...\n", Thearch.Thechar)
+	fmt.Printf("usage: compile [options] file.go...\n")
 	obj.Flagprint(1)
 	Exit(2)
 }
@@ -111,7 +87,7 @@ func doversion() {
 	if p != "" {
 		sep = " "
 	}
-	fmt.Printf("%cg version %s%s%s\n", Thearch.Thechar, obj.Getgoversion(), sep, p)
+	fmt.Printf("compile version %s%s%s\n", obj.Getgoversion(), sep, p)
 	os.Exit(0)
 }
 
@@ -129,7 +105,7 @@ func Main() {
 
 	Thearch.Linkarchinit()
 	Ctxt = obj.Linknew(Thearch.Thelinkarch)
-	Ctxt.Diag = Yyerror
+	Ctxt.DiagFunc = Yyerror
 	Ctxt.Bso = &bstdout
 	bstdout = *obj.Binitw(os.Stdout)
 
@@ -220,6 +196,8 @@ func Main() {
 	obj.Flagcount("l", "disable inlining", &Debug['l'])
 	obj.Flagcount("live", "debug liveness analysis", &debuglive)
 	obj.Flagcount("m", "print optimization decisions", &Debug['m'])
+	obj.Flagcount("msan", "build code compatible with C/C++ memory sanitizer", &flag_msan)
+	obj.Flagcount("newexport", "use new export format", &newexport) // TODO(gri) remove eventually (issue 13241)
 	obj.Flagcount("nolocalimports", "reject local (relative) imports", &nolocalimports)
 	obj.Flagstr("o", "write output to `file`", &outfile)
 	obj.Flagstr("p", "set expected package import `path`", &myimportpath)
@@ -237,9 +215,15 @@ func Main() {
 	obj.Flagcount("y", "debug declarations in canned imports (with -d)", &Debug['y'])
 	var flag_shared int
 	var flag_dynlink bool
+	switch Thearch.Thechar {
+	case '5', '6', '7', '8', '9':
+		obj.Flagcount("shared", "generate code that can be linked into a shared library", &flag_shared)
+	}
 	if Thearch.Thechar == '6' {
 		obj.Flagcount("largemodel", "generate code that assumes a large memory model", &flag_largemodel)
-		obj.Flagcount("shared", "generate code that can be linked into a shared library", &flag_shared)
+	}
+	switch Thearch.Thechar {
+	case '5', '6', '7', '8', '9':
 		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)
@@ -266,6 +250,15 @@ func Main() {
 		racepkg = mkpkg("runtime/race")
 		racepkg.Name = "race"
 	}
+	if flag_msan != 0 {
+		msanpkg = mkpkg("runtime/msan")
+		msanpkg.Name = "msan"
+	}
+	if flag_race != 0 && flag_msan != 0 {
+		log.Fatal("can not use both -race and -msan")
+	} else if flag_race != 0 || flag_msan != 0 {
+		instrumenting = true
+	}
 
 	// parse -d argument
 	if debugstr != "" {
@@ -305,20 +298,24 @@ func Main() {
 
 	Thearch.Betypeinit()
 	if Widthptr == 0 {
-		Fatal("betypeinit failed")
+		Fatalf("betypeinit failed")
 	}
 
 	lexinit()
 	typeinit()
 	lexinit1()
-	// TODO(rsc): Restore yytinit?
 
 	blockgen = 1
 	dclcontext = PEXTERN
 	nerrors = 0
 	lexlineno = 1
+	const BOM = 0xFEFF
 
 	for _, infile = range flag.Args() {
+		if trace && Debug['x'] != 0 {
+			fmt.Printf("--- %s ---\n", infile)
+		}
+
 		linehistpush(infile)
 
 		curio.infile = infile
@@ -331,21 +328,21 @@ func Main() {
 
 		curio.peekc = 0
 		curio.peekc1 = 0
-		curio.nlsemi = 0
-		curio.eofnl = 0
+		curio.nlsemi = false
+		curio.eofnl = false
 		curio.last = 0
 
 		// Skip initial BOM if present.
-		if obj.Bgetrune(curio.bin) != obj.BOM {
+		if obj.Bgetrune(curio.bin) != BOM {
 			obj.Bungetrune(curio.bin)
 		}
 
 		block = 1
 		iota_ = -1000000
 
-		imported_unsafe = 0
+		imported_unsafe = false
 
-		yyparse()
+		parse_file()
 		if nsyntaxerrors != 0 {
 			errorexit()
 		}
@@ -360,7 +357,7 @@ func Main() {
 	mkpackage(localpkg.Name) // final import not used checks
 	lexfini()
 
-	typecheckok = 1
+	typecheckok = true
 	if Debug['f'] != 0 {
 		frame(1)
 	}
@@ -421,10 +418,10 @@ func Main() {
 	if Debug['l'] > 1 {
 		// Typecheck imported function bodies if debug['l'] > 1,
 		// otherwise lazily when used or re-exported.
-		for l := importlist; l != nil; l = l.Next {
-			if l.N.Func.Inl != nil {
+		for _, n := range importlist {
+			if n.Func.Inl != nil {
 				saveerrors()
-				typecheckinl(l.N)
+				typecheckinl(n)
 			}
 		}
 
@@ -435,11 +432,13 @@ func Main() {
 
 	if Debug['l'] != 0 {
 		// Find functions that can be inlined and clone them before walk expands them.
-		visitBottomUp(xtop, func(list *NodeList, recursive bool) {
-			for l := list; l != nil; l = l.Next {
-				if l.N.Op == ODCLFUNC {
-					caninl(l.N)
-					inlcalls(l.N)
+		visitBottomUp(xtop, func(list []*Node, recursive bool) {
+			// TODO: use a range statement here if the order does not matter
+			for i := len(list) - 1; i >= 0; i-- {
+				n := list[i]
+				if n.Op == ODCLFUNC {
+					caninl(n)
+					inlcalls(n)
 				}
 			}
 		})
@@ -478,10 +477,14 @@ func Main() {
 		fninit(xtop)
 	}
 
+	if compiling_runtime != 0 {
+		checknowritebarrierrec()
+	}
+
 	// Phase 9: Check external declarations.
-	for l := externdcl; l != nil; l = l.Next {
-		if l.N.Op == ONAME {
-			typecheck(&l.N, Erv)
+	for i, n := range externdcl {
+		if n.Op == ONAME {
+			typecheck(&externdcl[i], Erv)
 		}
 	}
 
@@ -536,7 +539,7 @@ func arsize(b *obj.Biobuf, name string) int {
 }
 
 func skiptopkgdef(b *obj.Biobuf) bool {
-	/* archive header */
+	// archive header
 	p := obj.Brdline(b, '\n')
 	if p == "" {
 		return false
@@ -548,7 +551,7 @@ func skiptopkgdef(b *obj.Biobuf) bool {
 		return false
 	}
 
-	/* symbol table may be first; skip it */
+	// symbol table may be first; skip it
 	sz := arsize(b, "__.GOSYMDEF")
 
 	if sz >= 0 {
@@ -557,7 +560,7 @@ func skiptopkgdef(b *obj.Biobuf) bool {
 		obj.Bseek(b, 8, 0)
 	}
 
-	/* package export block is next */
+	// package export block is next
 	sz = arsize(b, "__.PKGDEF")
 
 	if sz <= 0 {
@@ -582,7 +585,7 @@ func addidir(dir string) {
 // is this path a local name?  begins with ./ or ../ or /
 func islocalname(name string) bool {
 	return strings.HasPrefix(name, "/") ||
-		Ctxt.Windows != 0 && len(name) >= 3 && yy_isalpha(int(name[0])) && name[1] == ':' && name[2] == '/' ||
+		Ctxt.Windows != 0 && len(name) >= 3 && isAlpha(int(name[0])) && name[1] == ':' && name[2] == '/' ||
 		strings.HasPrefix(name, "./") || name == "." ||
 		strings.HasPrefix(name, "../") || name == ".."
 }
@@ -597,11 +600,11 @@ func findpkg(name string) (file string, ok bool) {
 		// if there is an array.6 in the array.a library,
 		// want to find all of array.a, not just array.6.
 		file = fmt.Sprintf("%s.a", name)
-		if obj.Access(file, 0) >= 0 {
+		if _, err := os.Stat(file); err == nil {
 			return file, true
 		}
 		file = fmt.Sprintf("%s.o", name)
-		if obj.Access(file, 0) >= 0 {
+		if _, err := os.Stat(file); err == nil {
 			return file, true
 		}
 		return "", false
@@ -610,20 +613,18 @@ func findpkg(name string) (file string, ok bool) {
 	// local imports should be canonicalized already.
 	// don't want to see "encoding/../encoding/base64"
 	// as different from "encoding/base64".
-	var q string
-	_ = q
-	if path.Clean(name) != name {
+	if q := path.Clean(name); q != name {
 		Yyerror("non-canonical import path %q (should be %q)", name, q)
 		return "", false
 	}
 
 	for p := idirs; p != nil; p = p.link {
 		file = fmt.Sprintf("%s/%s.a", p.dir, name)
-		if obj.Access(file, 0) >= 0 {
+		if _, err := os.Stat(file); err == nil {
 			return file, true
 		}
 		file = fmt.Sprintf("%s/%s.o", p.dir, name)
-		if obj.Access(file, 0) >= 0 {
+		if _, err := os.Stat(file); err == nil {
 			return file, true
 		}
 	}
@@ -637,14 +638,17 @@ func findpkg(name string) (file string, ok bool) {
 		} else if flag_race != 0 {
 			suffixsep = "_"
 			suffix = "race"
+		} else if flag_msan != 0 {
+			suffixsep = "_"
+			suffix = "msan"
 		}
 
 		file = fmt.Sprintf("%s/pkg/%s_%s%s%s/%s.a", goroot, goos, goarch, suffixsep, suffix, name)
-		if obj.Access(file, 0) >= 0 {
+		if _, err := os.Stat(file); err == nil {
 			return file, true
 		}
 		file = fmt.Sprintf("%s/pkg/%s_%s%s%s/%s.o", goroot, goos, goarch, suffixsep, suffix, name)
-		if obj.Access(file, 0) >= 0 {
+		if _, err := os.Stat(file); err == nil {
 			return file, true
 		}
 	}
@@ -657,6 +661,7 @@ func fakeimport() {
 	cannedimports("fake.o", "$$\n")
 }
 
+// TODO(gri) line argument doesn't appear to be used
 func importfile(f *Val, line int) {
 	if _, ok := f.U.(string); !ok {
 		Yyerror("import statement not a string")
@@ -689,7 +694,13 @@ func importfile(f *Val, line int) {
 		errorexit()
 	}
 
-	if f.U.(string) == "unsafe" {
+	path_ := f.U.(string)
+
+	if mapped, ok := importMap[path_]; ok {
+		path_ = mapped
+	}
+
+	if path_ == "unsafe" {
 		if safemode != 0 {
 			Yyerror("cannot import package unsafe")
 			errorexit()
@@ -697,16 +708,10 @@ func importfile(f *Val, line int) {
 
 		importpkg = mkpkg(f.U.(string))
 		cannedimports("unsafe.o", unsafeimport)
-		imported_unsafe = 1
+		imported_unsafe = true
 		return
 	}
 
-	path_ := f.U.(string)
-
-	if mapped, ok := importMap[path_]; ok {
-		path_ = mapped
-	}
-
 	if islocalname(path_) {
 		if path_[0] == '/' {
 			Yyerror("import path cannot be absolute path")
@@ -740,7 +745,7 @@ func importfile(f *Val, line int) {
 
 	// If we already saw that package, feed a dummy statement
 	// to the lexer to avoid parsing export data twice.
-	if importpkg.Imported != 0 {
+	if importpkg.Imported {
 		tag := ""
 		if importpkg.Safe {
 			tag = "safe"
@@ -751,7 +756,7 @@ func importfile(f *Val, line int) {
 		return
 	}
 
-	importpkg.Imported = 1
+	importpkg.Imported = true
 
 	var err error
 	var imp *obj.Biobuf
@@ -788,43 +793,72 @@ func importfile(f *Val, line int) {
 	// so don't record the full path.
 	linehistpragma(file[len(file)-len(path_)-2:]) // acts as #pragma lib
 
-	/*
-	 * position the input right
-	 * after $$ and return
-	 */
-	pushedio = curio
-
-	curio.bin = imp
-	curio.peekc = 0
-	curio.peekc1 = 0
-	curio.infile = file
-	curio.nlsemi = 0
-	typecheckok = 1
+	// In the importfile, if we find:
+	// $$\n  (old format): position the input right after $$\n and return
+	// $$B\n (new format): import directly, then feed the lexer a dummy statement
 
-	var c int32
+	// look for $$
+	var c int
 	for {
-		c = int32(getc())
-		if c == EOF {
-			break
-		}
-		if c != '$' {
-			continue
-		}
-		c = int32(getc())
-		if c == EOF {
+		c = obj.Bgetc(imp)
+		if c < 0 {
 			break
 		}
-		if c != '$' {
-			continue
+		if c == '$' {
+			c = obj.Bgetc(imp)
+			if c == '$' || c < 0 {
+				break
+			}
 		}
-		return
 	}
 
-	Yyerror("no import in %q", f.U.(string))
-	unimportfile()
+	// get character after $$
+	if c >= 0 {
+		c = obj.Bgetc(imp)
+	}
+
+	switch c {
+	case '\n':
+		// old export format
+		pushedio = curio
+
+		curio.bin = imp
+		curio.peekc = 0
+		curio.peekc1 = 0
+		curio.infile = file
+		curio.nlsemi = false
+		typecheckok = true
+
+		push_parser()
+
+	case 'B':
+		// new export format
+		obj.Bgetc(imp) // skip \n after $$B
+		Import(imp)
+
+		// continue as if the package was imported before (see above)
+		tag := ""
+		if importpkg.Safe {
+			tag = "safe"
+		}
+		p := fmt.Sprintf("package %s %s\n$$\n", importpkg.Name, tag)
+		cannedimports(file, p)
+		// Reset incannedimport flag (we are not truly in a
+		// canned import) - this will cause importpkg.Direct to
+		// be set via parser.import_package (was issue #13977).
+		//
+		// TODO(gri) Remove this global variable and convoluted
+		// code in the process of streamlining the import code.
+		incannedimport = 0
+
+	default:
+		Yyerror("no import in %q", f.U.(string))
+	}
 }
 
 func unimportfile() {
+	pop_parser()
+
 	if curio.bin != nil {
 		obj.Bterm(curio.bin)
 		curio.bin = nil
@@ -836,7 +870,7 @@ func unimportfile() {
 
 	pushedio.bin = nil
 	incannedimport = 0
-	typecheckok = 0
+	typecheckok = false
 }
 
 func cannedimports(file string, cp string) {
@@ -849,17 +883,46 @@ func cannedimports(file string, cp string) {
 	curio.peekc1 = 0
 	curio.infile = file
 	curio.cp = cp
-	curio.nlsemi = 0
+	curio.nlsemi = false
 	curio.importsafe = false
 
-	typecheckok = 1
+	typecheckok = true
 	incannedimport = 1
+
+	push_parser()
+}
+
+func isSpace(c int) bool {
+	return c == ' ' || c == '\t' || c == '\n' || c == '\r'
+}
+
+func isAlpha(c int) bool {
+	return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
+}
+
+func isDigit(c int) bool {
+	return '0' <= c && c <= '9'
+}
+func isAlnum(c int) bool {
+	return isAlpha(c) || isDigit(c)
+}
+
+func plan9quote(s string) string {
+	if s == "" {
+		return "''"
+	}
+	for _, c := range s {
+		if c <= ' ' || c == '\'' {
+			return "'" + strings.Replace(s, "'", "''", -1) + "'"
+		}
+	}
+	return s
 }
 
 func isfrog(c int) bool {
 	// complain about possibly invisible control characters
 	if c < ' ' {
-		return !yy_isspace(c) // exclude good white space
+		return !isSpace(c) // exclude good white space
 	}
 
 	if 0x7f <= c && c <= 0xa0 { // DEL, unicode block including unbreakable space.
@@ -868,29 +931,75 @@ func isfrog(c int) bool {
 	return false
 }
 
-type Loophack struct {
-	v    int
-	next *Loophack
+type yySymType struct {
+	sym *Sym
+	val Val
+	op  Op
 }
 
-var _yylex_lstk *Loophack
+const (
+	LLITERAL = 57346 + iota
+	LASOP
+	LCOLAS
+	LBREAK
+	LCASE
+	LCHAN
+	LCONST
+	LCONTINUE
+	LDDD
+	LDEFAULT
+	LDEFER
+	LELSE
+	LFALL
+	LFOR
+	LFUNC
+	LGO
+	LGOTO
+	LIF
+	LIMPORT
+	LINTERFACE
+	LMAP
+	LNAME
+	LPACKAGE
+	LRANGE
+	LRETURN
+	LSELECT
+	LSTRUCT
+	LSWITCH
+	LTYPE
+	LVAR
+	LANDAND
+	LANDNOT
+	LCOMM
+	LDEC
+	LEQ
+	LGE
+	LGT
+	LIGNORE
+	LINC
+	LLE
+	LLSH
+	LLT
+	LNE
+	LOROR
+	LRSH
+)
 
 func _yylex(yylval *yySymType) int32 {
 	var c1 int
+	var op Op
 	var escflag int
 	var v int64
 	var cp *bytes.Buffer
-	var rune_ uint
 	var s *Sym
-	var h *Loophack
 	var str string
 
 	prevlineno = lineno
 
 l0:
 	c := getc()
-	if yy_isspace(c) {
-		if c == '\n' && curio.nlsemi != 0 {
+	if isSpace(c) {
+		if c == '\n' && curio.nlsemi {
 			ungetc(c)
 			if Debug['x'] != 0 {
 				fmt.Printf("lex: implicit semi\n")
@@ -901,30 +1010,30 @@ l0:
 		goto l0
 	}
 
-	lineno = lexlineno /* start of token */
+	lineno = lexlineno // start of token
 
 	if c >= utf8.RuneSelf {
-		/* all multibyte runes are alpha */
+		// all multibyte runes are alpha
 		cp = &lexbuf
 		cp.Reset()
 
 		goto talph
 	}
 
-	if yy_isalpha(c) {
+	if isAlpha(c) {
 		cp = &lexbuf
 		cp.Reset()
 		goto talph
 	}
 
-	if yy_isdigit(c) {
+	if isDigit(c) {
 		cp = &lexbuf
 		cp.Reset()
 		if c != '0' {
 			for {
 				cp.WriteByte(byte(c))
 				c = getc()
-				if yy_isdigit(c) {
+				if isDigit(c) {
 					continue
 				}
 				if c == '.' {
@@ -946,7 +1055,7 @@ l0:
 			for {
 				cp.WriteByte(byte(c))
 				c = getc()
-				if yy_isdigit(c) {
+				if isDigit(c) {
 					continue
 				}
 				if c >= 'a' && c <= 'f' {
@@ -971,7 +1080,7 @@ l0:
 
 		c1 = 0
 		for {
-			if !yy_isdigit(c) {
+			if !isDigit(c) {
 				break
 			}
 			if c < '0' || c > '7' {
@@ -1009,7 +1118,7 @@ l0:
 
 	case '.':
 		c1 = getc()
-		if yy_isdigit(c1) {
+		if isDigit(c1) {
 			cp = &lexbuf
 			cp.Reset()
 			cp.WriteByte(byte(c))
@@ -1028,7 +1137,7 @@ l0:
 			c1 = '.'
 		}
 
-		/* "..." */
+		// "..."
 	case '"':
 		lexbuf.Reset()
 		lexbuf.WriteString(`"<string>"`)
@@ -1043,14 +1152,13 @@ l0:
 			if v < utf8.RuneSelf || escflag != 0 {
 				cp.WriteByte(byte(v))
 			} else {
-				rune_ = uint(v)
-				cp.WriteRune(rune(rune_))
+				cp.WriteRune(rune(v))
 			}
 		}
 
 		goto strlit
 
-		/* `...` */
+		// `...`
 	case '`':
 		lexbuf.Reset()
 		lexbuf.WriteString("`<string>`")
@@ -1076,7 +1184,7 @@ l0:
 
 		goto strlit
 
-		/* '.' */
+		// '.'
 	case '\'':
 		if escchar('\'', &escflag, &v) {
 			Yyerror("empty character literal or unescaped ' in character literal")
@@ -1101,23 +1209,23 @@ l0:
 	case '/':
 		c1 = getc()
 		if c1 == '*' {
-			nl := 0
+			nl := false
 			for {
 				c = int(getr())
 				if c == '\n' {
-					nl = 1
+					nl = true
 				}
 				for c == '*' {
 					c = int(getr())
 					if c == '/' {
-						if nl != 0 {
+						if nl {
 							ungetc('\n')
 						}
 						goto l0
 					}
 
 					if c == '\n' {
-						nl = 1
+						nl = true
 					}
 				}
 
@@ -1141,63 +1249,62 @@ l0:
 		}
 
 		if c1 == '=' {
-			c = ODIV
+			op = ODIV
 			goto asop
 		}
 
 	case ':':
 		c1 = getc()
 		if c1 == '=' {
-			c = LCOLAS
-			yylval.i = int(lexlineno)
+			c = int(LCOLAS)
 			goto lx
 		}
 
 	case '*':
 		c1 = getc()
 		if c1 == '=' {
-			c = OMUL
+			op = OMUL
 			goto asop
 		}
 
 	case '%':
 		c1 = getc()
 		if c1 == '=' {
-			c = OMOD
+			op = OMOD
 			goto asop
 		}
 
 	case '+':
 		c1 = getc()
 		if c1 == '+' {
-			c = LINC
+			c = int(LINC)
 			goto lx
 		}
 
 		if c1 == '=' {
-			c = OADD
+			op = OADD
 			goto asop
 		}
 
 	case '-':
 		c1 = getc()
 		if c1 == '-' {
-			c = LDEC
+			c = int(LDEC)
 			goto lx
 		}
 
 		if c1 == '=' {
-			c = OSUB
+			op = OSUB
 			goto asop
 		}
 
 	case '>':
 		c1 = getc()
 		if c1 == '>' {
-			c = LRSH
+			c = int(LRSH)
 			c1 = getc()
 			if c1 == '=' {
-				c = ORSH
+				op = ORSH
 				goto asop
 			}
 
@@ -1205,19 +1312,19 @@ l0:
 		}
 
 		if c1 == '=' {
-			c = LGE
+			c = int(LGE)
 			goto lx
 		}
 
-		c = LGT
+		c = int(LGT)
 
 	case '<':
 		c1 = getc()
 		if c1 == '<' {
-			c = LLSH
+			c = int(LLSH)
 			c1 = getc()
 			if c1 == '=' {
-				c = OLSH
+				op = OLSH
 				goto asop
 			}
 
@@ -1225,43 +1332,43 @@ l0:
 		}
 
 		if c1 == '=' {
-			c = LLE
+			c = int(LLE)
 			goto lx
 		}
 
 		if c1 == '-' {
-			c = LCOMM
+			c = int(LCOMM)
 			goto lx
 		}
 
-		c = LLT
+		c = int(LLT)
 
 	case '=':
 		c1 = getc()
 		if c1 == '=' {
-			c = LEQ
+			c = int(LEQ)
 			goto lx
 		}
 
 	case '!':
 		c1 = getc()
 		if c1 == '=' {
-			c = LNE
+			c = int(LNE)
 			goto lx
 		}
 
 	case '&':
 		c1 = getc()
 		if c1 == '&' {
-			c = LANDAND
+			c = int(LANDAND)
 			goto lx
 		}
 
 		if c1 == '^' {
-			c = LANDNOT
+			c = int(LANDNOT)
 			c1 = getc()
 			if c1 == '=' {
-				c = OANDNOT
+				op = OANDNOT
 				goto asop
 			}
 
@@ -1269,84 +1376,29 @@ l0:
 		}
 
 		if c1 == '=' {
-			c = OAND
+			op = OAND
 			goto asop
 		}
 
 	case '|':
 		c1 = getc()
 		if c1 == '|' {
-			c = LOROR
+			c = int(LOROR)
 			goto lx
 		}
 
 		if c1 == '=' {
-			c = OOR
+			op = OOR
 			goto asop
 		}
 
 	case '^':
 		c1 = getc()
 		if c1 == '=' {
-			c = OXOR
+			op = OXOR
 			goto asop
 		}
 
-		/*
-		 * clumsy dance:
-		 * to implement rule that disallows
-		 *	if T{1}[0] { ... }
-		 * but allows
-		 * 	if (T{1}[0]) { ... }
-		 * the block bodies for if/for/switch/select
-		 * begin with an LBODY token, not '{'.
-		 *
-		 * when we see the keyword, the next
-		 * non-parenthesized '{' becomes an LBODY.
-		 * loophack is normally 0.
-		 * a keyword makes it go up to 1.
-		 * parens push loophack onto a stack and go back to 0.
-		 * a '{' with loophack == 1 becomes LBODY and disables loophack.
-		 *
-		 * i said it was clumsy.
-		 */
-	case '(', '[':
-		if loophack != 0 || _yylex_lstk != nil {
-			h = new(Loophack)
-			if h == nil {
-				Flusherrors()
-				Yyerror("out of memory")
-				errorexit()
-			}
-
-			h.v = loophack
-			h.next = _yylex_lstk
-			_yylex_lstk = h
-			loophack = 0
-		}
-
-		goto lx
-
-	case ')', ']':
-		if _yylex_lstk != nil {
-			h = _yylex_lstk
-			loophack = h.v
-			_yylex_lstk = h.next
-		}
-
-		goto lx
-
-	case '{':
-		if loophack == 1 {
-			if Debug['x'] != 0 {
-				fmt.Printf("%v lex: LBODY\n", Ctxt.Line(int(lexlineno)))
-			}
-			loophack = 0
-			return LBODY
-		}
-
-		goto lx
-
 	default:
 		goto lx
 	}
@@ -1354,12 +1406,10 @@ l0:
 	ungetc(c1)
 
 lx:
-	if c > 0xff {
-		if Debug['x'] != 0 {
+	if Debug['x'] != 0 {
+		if c > 0xff {
 			fmt.Printf("%v lex: TOKEN %s\n", Ctxt.Line(int(lexlineno)), lexname(c))
-		}
-	} else {
-		if Debug['x'] != 0 {
+		} else {
 			fmt.Printf("%v lex: TOKEN '%c'\n", Ctxt.Line(int(lexlineno)), c)
 		}
 	}
@@ -1376,28 +1426,29 @@ lx:
 	return int32(c)
 
 asop:
-	yylval.i = c // rathole to hold which asop
+	yylval.op = op
 	if Debug['x'] != 0 {
-		fmt.Printf("lex: TOKEN ASOP %c\n", c)
+		fmt.Printf("lex: TOKEN ASOP %s=\n", goopnames[op])
 	}
 	return LASOP
 
-	/*
-	 * cp is set to lexbuf and some
-	 * prefix has been stored
-	 */
+	// cp is set to lexbuf and some
+	// prefix has been stored
 talph:
 	for {
 		if c >= utf8.RuneSelf {
 			ungetc(c)
-			rune_ = uint(getr())
+			r := rune(getr())
 
 			// 0xb7 · is used for internal names
-			if !unicode.IsLetter(rune(rune_)) && !unicode.IsDigit(rune(rune_)) && (importpkg == nil || rune_ != 0xb7) {
-				Yyerror("invalid identifier character U+%04x", rune_)
+			if !unicode.IsLetter(r) && !unicode.IsDigit(r) && (importpkg == nil || r != 0xb7) {
+				Yyerror("invalid identifier character U+%04x", r)
 			}
-			cp.WriteRune(rune(rune_))
-		} else if !yy_isalnum(c) && c != '_' {
+			if cp.Len() == 0 && unicode.IsDigit(r) {
+				Yyerror("identifier cannot begin with digit U+%04x", r)
+			}
+			cp.WriteRune(r)
+		} else if !isAlnum(c) && c != '_' {
 			break
 		} else {
 			cp.WriteByte(byte(c))
@@ -1409,12 +1460,8 @@ talph:
 	ungetc(c)
 
 	s = LookupBytes(lexbuf.Bytes())
-	switch s.Lexical {
-	case LIGNORE:
+	if s.Lexical == LIGNORE {
 		goto l0
-
-	case LFOR, LIF, LSWITCH, LSELECT:
-		loophack = 1 // see comment about loophack above
 	}
 
 	if Debug['x'] != 0 {
@@ -1445,7 +1492,7 @@ casedot:
 	for {
 		cp.WriteByte(byte(c))
 		c = getc()
-		if !yy_isdigit(c) {
+		if !isDigit(c) {
 			break
 		}
 	}
@@ -1470,10 +1517,10 @@ caseep:
 		c = getc()
 	}
 
-	if !yy_isdigit(c) {
+	if !isDigit(c) {
 		Yyerror("malformed floating point constant exponent")
 	}
-	for yy_isdigit(c) {
+	for isDigit(c) {
 		cp.WriteByte(byte(c))
 		c = getc()
 	}
@@ -1493,7 +1540,7 @@ casei:
 	mpatoflt(&yylval.val.U.(*Mpcplx).Imag, str)
 	if yylval.val.U.(*Mpcplx).Imag.Val.IsInf() {
 		Yyerror("overflow in imaginary constant")
-		Mpmovecflt(&yylval.val.U.(*Mpcplx).Real, 0.0)
+		Mpmovecflt(&yylval.val.U.(*Mpcplx).Imag, 0.0)
 	}
 
 	if Debug['x'] != 0 {
@@ -1543,19 +1590,17 @@ func internString(b []byte) string {
 
 func more(pp *string) bool {
 	p := *pp
-	for p != "" && yy_isspace(int(p[0])) {
+	for p != "" && isSpace(int(p[0])) {
 		p = p[1:]
 	}
 	*pp = p
 	return p != ""
 }
 
-/*
- * read and interpret syntax that looks like
- * //line parse.y:15
- * as a discontinuity in sequential line numbers.
- * the next line of input comes from parse.y:15
- */
+// read and interpret syntax that looks like
+// //line parse.y:15
+// as a discontinuity in sequential line numbers.
+// the next line of input comes from parse.y:15
 func getlinepragma() int {
 	var cmd, verb, name string
 
@@ -1589,7 +1634,7 @@ func getlinepragma() int {
 		}
 
 		if verb == "go:linkname" {
-			if imported_unsafe == 0 {
+			if !imported_unsafe {
 				Yyerror("//go:linkname only allowed in Go files that import \"unsafe\"")
 			}
 			f := strings.Fields(cmd)
@@ -1622,7 +1667,15 @@ func getlinepragma() int {
 			return c
 		}
 
+		if verb == "go:noinline" {
+			noinline = true
+			return c
+		}
+
 		if verb == "go:systemstack" {
+			if compiling_runtime == 0 {
+				Yyerror("//go:systemstack only allowed in runtime")
+			}
 			systemstack = true
 			return c
 		}
@@ -1634,6 +1687,15 @@ func getlinepragma() int {
 			nowritebarrier = true
 			return c
 		}
+
+		if verb == "go:nowritebarrierrec" {
+			if compiling_runtime == 0 {
+				Yyerror("//go:nowritebarrierrec only allowed in runtime")
+			}
+			nowritebarrierrec = true
+			nowritebarrier = true // Implies nowritebarrier
+			return c
+		}
 		return c
 	}
 	if c != 'l' {
@@ -1703,7 +1765,7 @@ func getimpsym(pp *string) string {
 		return ""
 	}
 	i := 0
-	for i < len(p) && !yy_isspace(int(p[i])) && p[i] != '"' {
+	for i < len(p) && !isSpace(int(p[i])) && p[i] != '"' {
 		i++
 	}
 	sym := p[:i]
@@ -1738,9 +1800,7 @@ func pragcgo(text string) {
 	verb := text[3:] // skip "go:"
 
 	if verb == "cgo_dynamic_linker" || verb == "dynlinker" {
-		var ok bool
-		var p string
-		p, ok = getquoted(&q)
+		p, ok := getquoted(&q)
 		if !ok {
 			Yyerror("usage: //go:cgo_dynamic_linker \"path\"")
 			return
@@ -1822,9 +1882,7 @@ func pragcgo(text string) {
 	}
 
 	if verb == "cgo_ldflag" {
-		var ok bool
-		var p string
-		p, ok = getquoted(&q)
+		p, ok := getquoted(&q)
 		if !ok {
 			Yyerror("usage: //go:cgo_ldflag \"arg\"")
 			return
@@ -1835,30 +1893,10 @@ func pragcgo(text string) {
 	}
 }
 
-type yy struct{}
-
-func (yy) Lex(v *yySymType) int {
-	return int(yylex(v))
-}
-
-func (yy) Error(msg string) {
-	Yyerror("%s", msg)
-}
-
-var theparser yyParser
-var parsing bool
-
-func yyparse() {
-	theparser = yyNewParser()
-	parsing = true
-	theparser.Parse(yy{})
-	parsing = false
-}
-
 func yylex(yylval *yySymType) int32 {
-	lx := int(_yylex(yylval))
+	lx := _yylex(yylval)
 
-	if curio.nlsemi != 0 && lx == EOF {
+	if curio.nlsemi && lx == EOF {
 		// Treat EOF as "end of line" for the purposes
 		// of inserting a semicolon.
 		lx = ';'
@@ -1876,17 +1914,13 @@ func yylex(yylval *yySymType) int32 {
 		')',
 		'}',
 		']':
-		curio.nlsemi = 1
+		curio.nlsemi = true
 
 	default:
-		curio.nlsemi = 0
+		curio.nlsemi = false
 	}
 
-	// Track last two tokens returned by yylex.
-	yyprev = yylast
-
-	yylast = lx
-	return int32(lx)
+	return lx
 }
 
 func getc() int {
@@ -1907,10 +1941,12 @@ func getc() int {
 	} else {
 	loop:
 		c = obj.Bgetc(curio.bin)
+		// recognize BOM (U+FEFF): UTF-8 encoding is 0xef 0xbb 0xbf
 		if c == 0xef {
 			buf, err := curio.bin.Peek(2)
 			if err != nil {
-				log.Fatalf("getc: peeking: %v", err)
+				yyerrorl(int(lexlineno), "illegal UTF-8 sequence ef % x followed by read error (%v)", string(buf), err)
+				errorexit()
 			}
 			if buf[0] == 0xbb && buf[1] == 0xbf {
 				yyerrorl(int(lexlineno), "Unicode (UTF-8) BOM in middle of file")
@@ -1934,10 +1970,10 @@ check:
 
 		// insert \n at EOF
 	case EOF:
-		if curio.eofnl != 0 || curio.last == '\n' {
+		if curio.eofnl || curio.last == '\n' {
 			return EOF
 		}
-		curio.eofnl = 1
+		curio.eofnl = true
 		c = '\n'
 		fallthrough
 
@@ -2115,10 +2151,10 @@ hex:
 var syms = []struct {
 	name    string
 	lexical int
-	etype   int
-	op      int
+	etype   EType
+	op      Op
 }{
-	/* basic types */
+	// basic types
 	{"int8", LNAME, TINT8, OXXX},
 	{"int16", LNAME, TINT16, OXXX},
 	{"int32", LNAME, TINT32, OXXX},
@@ -2181,32 +2217,22 @@ var syms = []struct {
 	{"insofaras", LIGNORE, Txxx, OXXX},
 }
 
+// lexinit initializes known symbols and the basic types.
 func lexinit() {
-	var lex int
-	var s *Sym
-	var s1 *Sym
-	var t *Type
-	var etype int
-
-	/*
-	 * initialize basic types array
-	 * initialize known symbols
-	 */
-	for i := 0; i < len(syms); i++ {
-		lex = syms[i].lexical
-		s = Lookup(syms[i].name)
-		s.Lexical = uint16(lex)
-
-		etype = syms[i].etype
-		if etype != Txxx {
-			if etype < 0 || etype >= len(Types) {
-				Fatal("lexinit: %s bad etype", s.Name)
+	for _, s := range syms {
+		lex := s.lexical
+		s1 := Lookup(s.name)
+		s1.Lexical = uint16(lex)
+
+		if etype := s.etype; etype != Txxx {
+			if int(etype) >= len(Types) {
+				Fatalf("lexinit: %s bad etype", s.name)
 			}
-			s1 = Pkglookup(syms[i].name, builtinpkg)
-			t = Types[etype]
+			s2 := Pkglookup(s.name, builtinpkg)
+			t := Types[etype]
 			if t == nil {
 				t = typ(etype)
-				t.Sym = s1
+				t.Sym = s2
 
 				if etype != TANY && etype != TSTRING {
 					dowidth(t)
@@ -2214,19 +2240,19 @@ func lexinit() {
 				Types[etype] = t
 			}
 
-			s1.Lexical = LNAME
-			s1.Def = typenod(t)
-			s1.Def.Name = new(Name)
+			s2.Lexical = LNAME
+			s2.Def = typenod(t)
+			s2.Def.Name = new(Name)
 			continue
 		}
 
-		etype = syms[i].op
-		if etype != OXXX {
-			s1 = Pkglookup(syms[i].name, builtinpkg)
-			s1.Lexical = LNAME
-			s1.Def = Nod(ONAME, nil, nil)
-			s1.Def.Sym = s1
-			s1.Def.Etype = uint8(etype)
+		// TODO(marvin): Fix Node.EType type union.
+		if etype := s.op; etype != OXXX {
+			s2 := Pkglookup(s.name, builtinpkg)
+			s2.Lexical = LNAME
+			s2.Def = Nod(ONAME, nil, nil)
+			s2.Def.Sym = s2
+			s2.Def.Etype = EType(etype)
 		}
 	}
 
@@ -2239,7 +2265,7 @@ func lexinit() {
 
 	idealbool = typ(TBOOL)
 
-	s = Pkglookup("true", builtinpkg)
+	s := Pkglookup("true", builtinpkg)
 	s.Def = Nodbool(true)
 	s.Def.Sym = Lookup("true")
 	s.Def.Name = new(Name)
@@ -2281,20 +2307,20 @@ func lexinit1() {
 
 	rcvr.Type = typ(TFIELD)
 	rcvr.Type.Type = Ptrto(typ(TSTRUCT))
-	rcvr.Funarg = 1
+	rcvr.Funarg = true
 	in := typ(TSTRUCT)
-	in.Funarg = 1
+	in.Funarg = true
 	out := typ(TSTRUCT)
 	out.Type = typ(TFIELD)
 	out.Type.Type = Types[TSTRING]
-	out.Funarg = 1
+	out.Funarg = true
 	f := typ(TFUNC)
 	*getthis(f) = rcvr
 	*Getoutarg(f) = out
 	*getinarg(f) = in
 	f.Thistuple = 1
 	f.Intuple = 0
-	f.Outnamed = 0
+	f.Outnamed = false
 	f.Outtuple = 1
 	t := typ(TINTER)
 	t.Type = typ(TFIELD)
@@ -2335,38 +2361,34 @@ func lexinit1() {
 }
 
 func lexfini() {
-	var s *Sym
-	var lex int
-	var etype int
-	var i int
-
-	for i = 0; i < len(syms); i++ {
-		lex = syms[i].lexical
+	for i := range syms {
+		lex := syms[i].lexical
 		if lex != LNAME {
 			continue
 		}
-		s = Lookup(syms[i].name)
+		s := Lookup(syms[i].name)
 		s.Lexical = uint16(lex)
 
-		etype = syms[i].etype
+		etype := syms[i].etype
 		if etype != Txxx && (etype != TANY || Debug['A'] != 0) && s.Def == nil {
 			s.Def = typenod(Types[etype])
 			s.Def.Name = new(Name)
 			s.Origpkg = builtinpkg
 		}
 
-		etype = syms[i].op
-		if etype != OXXX && s.Def == nil {
+		// TODO(marvin): Fix Node.EType type union.
+		etype = EType(syms[i].op)
+		if etype != EType(OXXX) && s.Def == nil {
 			s.Def = Nod(ONAME, nil, nil)
 			s.Def.Sym = s
-			s.Def.Etype = uint8(etype)
+			s.Def.Etype = etype
 			s.Origpkg = builtinpkg
 		}
 	}
 
 	// backend-specific builtin types (e.g. int).
-	for i = range Thearch.Typedefs {
-		s = Lookup(Thearch.Typedefs[i].Name)
+	for i := range Thearch.Typedefs {
+		s := Lookup(Thearch.Typedefs[i].Name)
 		if s.Def == nil {
 			s.Def = typenod(Types[Thearch.Typedefs[i].Etype])
 			s.Def.Name = new(Name)
@@ -2376,30 +2398,25 @@ func lexfini() {
 
 	// there's only so much table-driven we can handle.
 	// these are special cases.
-	s = Lookup("byte")
-
-	if s.Def == nil {
+	if s := Lookup("byte"); s.Def == nil {
 		s.Def = typenod(bytetype)
 		s.Def.Name = new(Name)
 		s.Origpkg = builtinpkg
 	}
 
-	s = Lookup("error")
-	if s.Def == nil {
+	if s := Lookup("error"); s.Def == nil {
 		s.Def = typenod(errortype)
 		s.Def.Name = new(Name)
 		s.Origpkg = builtinpkg
 	}
 
-	s = Lookup("rune")
-	if s.Def == nil {
+	if s := Lookup("rune"); s.Def == nil {
 		s.Def = typenod(runetype)
 		s.Def.Name = new(Name)
 		s.Origpkg = builtinpkg
 	}
 
-	s = Lookup("nil")
-	if s.Def == nil {
+	if s := Lookup("nil"); s.Def == nil {
 		var v Val
 		v.U = new(NilVal)
 		s.Def = nodlit(v)
@@ -2408,23 +2425,20 @@ func lexfini() {
 		s.Origpkg = builtinpkg
 	}
 
-	s = Lookup("iota")
-	if s.Def == nil {
+	if s := Lookup("iota"); s.Def == nil {
 		s.Def = Nod(OIOTA, nil, nil)
 		s.Def.Sym = s
 		s.Origpkg = builtinpkg
 	}
 
-	s = Lookup("true")
-	if s.Def == nil {
+	if s := Lookup("true"); s.Def == nil {
 		s.Def = Nodbool(true)
 		s.Def.Sym = s
 		s.Def.Name = new(Name)
 		s.Origpkg = builtinpkg
 	}
 
-	s = Lookup("false")
-	if s.Def == nil {
+	if s := Lookup("false"); s.Def == nil {
 		s.Def = Nodbool(false)
 		s.Def.Sym = s
 		s.Def.Name = new(Name)
@@ -2438,140 +2452,60 @@ func lexfini() {
 	nodfp.Sym = Lookup(".fp")
 }
 
-var lexn = []struct {
-	lex  int
-	name string
-}{
-	{LANDAND, "ANDAND"},
-	{LANDNOT, "ANDNOT"},
-	{LASOP, "ASOP"},
-	{LBREAK, "BREAK"},
-	{LCASE, "CASE"},
-	{LCHAN, "CHAN"},
-	{LCOLAS, "COLAS"},
-	{LCOMM, "<-"},
-	{LCONST, "CONST"},
-	{LCONTINUE, "CONTINUE"},
-	{LDDD, "..."},
-	{LDEC, "DEC"},
-	{LDEFAULT, "DEFAULT"},
-	{LDEFER, "DEFER"},
-	{LELSE, "ELSE"},
-	{LEQ, "EQ"},
-	{LFALL, "FALL"},
-	{LFOR, "FOR"},
-	{LFUNC, "FUNC"},
-	{LGE, "GE"},
-	{LGO, "GO"},
-	{LGOTO, "GOTO"},
-	{LGT, "GT"},
-	{LIF, "IF"},
-	{LIMPORT, "IMPORT"},
-	{LINC, "INC"},
-	{LINTERFACE, "INTERFACE"},
-	{LLE, "LE"},
-	{LLITERAL, "LITERAL"},
-	{LLSH, "LSH"},
-	{LLT, "LT"},
-	{LMAP, "MAP"},
-	{LNAME, "NAME"},
-	{LNE, "NE"},
-	{LOROR, "OROR"},
-	{LPACKAGE, "PACKAGE"},
-	{LRANGE, "RANGE"},
-	{LRETURN, "RETURN"},
-	{LRSH, "RSH"},
-	{LSELECT, "SELECT"},
-	{LSTRUCT, "STRUCT"},
-	{LSWITCH, "SWITCH"},
-	{LTYPE, "TYPE"},
-	{LVAR, "VAR"},
+var lexn = map[int]string{
+	LANDAND:    "ANDAND",
+	LANDNOT:    "ANDNOT",
+	LASOP:      "ASOP",
+	LBREAK:     "BREAK",
+	LCASE:      "CASE",
+	LCHAN:      "CHAN",
+	LCOLAS:     "COLAS",
+	LCOMM:      "<-",
+	LCONST:     "CONST",
+	LCONTINUE:  "CONTINUE",
+	LDDD:       "...",
+	LDEC:       "DEC",
+	LDEFAULT:   "DEFAULT",
+	LDEFER:     "DEFER",
+	LELSE:      "ELSE",
+	LEQ:        "EQ",
+	LFALL:      "FALL",
+	LFOR:       "FOR",
+	LFUNC:      "FUNC",
+	LGE:        "GE",
+	LGO:        "GO",
+	LGOTO:      "GOTO",
+	LGT:        "GT",
+	LIF:        "IF",
+	LIMPORT:    "IMPORT",
+	LINC:       "INC",
+	LINTERFACE: "INTERFACE",
+	LLE:        "LE",
+	LLITERAL:   "LITERAL",
+	LLSH:       "LSH",
+	LLT:        "LT",
+	LMAP:       "MAP",
+	LNAME:      "NAME",
+	LNE:        "NE",
+	LOROR:      "OROR",
+	LPACKAGE:   "PACKAGE",
+	LRANGE:     "RANGE",
+	LRETURN:    "RETURN",
+	LRSH:       "RSH",
+	LSELECT:    "SELECT",
+	LSTRUCT:    "STRUCT",
+	LSWITCH:    "SWITCH",
+	LTYPE:      "TYPE",
+	LVAR:       "VAR",
 }
 
 func lexname(lex int) string {
-	for i := 0; i < len(lexn); i++ {
-		if lexn[i].lex == lex {
-			return lexn[i].name
-		}
+	if s, ok := lexn[lex]; ok {
+		return s
 	}
 	return fmt.Sprintf("LEX-%d", lex)
 }
 
-var yytfix = []struct {
-	have string
-	want string
-}{
-	{"$end", "EOF"},
-	{"LASOP", "op="},
-	{"LBREAK", "break"},
-	{"LCASE", "case"},
-	{"LCHAN", "chan"},
-	{"LCOLAS", ":="},
-	{"LCONST", "const"},
-	{"LCONTINUE", "continue"},
-	{"LDDD", "..."},
-	{"LDEFAULT", "default"},
-	{"LDEFER", "defer"},
-	{"LELSE", "else"},
-	{"LFALL", "fallthrough"},
-	{"LFOR", "for"},
-	{"LFUNC", "func"},
-	{"LGO", "go"},
-	{"LGOTO", "goto"},
-	{"LIF", "if"},
-	{"LIMPORT", "import"},
-	{"LINTERFACE", "interface"},
-	{"LMAP", "map"},
-	{"LNAME", "name"},
-	{"LPACKAGE", "package"},
-	{"LRANGE", "range"},
-	{"LRETURN", "return"},
-	{"LSELECT", "select"},
-	{"LSTRUCT", "struct"},
-	{"LSWITCH", "switch"},
-	{"LTYPE", "type"},
-	{"LVAR", "var"},
-	{"LANDAND", "&&"},
-	{"LANDNOT", "&^"},
-	{"LBODY", "{"},
-	{"LCOMM", "<-"},
-	{"LDEC", "--"},
-	{"LINC", "++"},
-	{"LEQ", "=="},
-	{"LGE", ">="},
-	{"LGT", ">"},
-	{"LLE", "<="},
-	{"LLT", "<"},
-	{"LLSH", "<<"},
-	{"LRSH", ">>"},
-	{"LOROR", "||"},
-	{"LNE", "!="},
-	// spell out to avoid confusion with punctuation in error messages
-	{"';'", "semicolon or newline"},
-	{"','", "comma"},
-}
-
-func init() {
-	yyErrorVerbose = true
-
-Outer:
-	for i, s := range yyToknames {
-		// Apply yytfix if possible.
-		for _, fix := range yytfix {
-			if s == fix.have {
-				yyToknames[i] = fix.want
-				continue Outer
-			}
-		}
-
-		// Turn 'x' into x.
-		if len(s) == 3 && s[0] == '\'' && s[2] == '\'' {
-			yyToknames[i] = s[1:2]
-			continue
-		}
-	}
-}
-
 func pkgnotused(lineno int, path string, name string) {
 	// If the package was imported with a name other than the final
 	// import path element, show it explicitly in the error message.
diff --git a/src/cmd/compile/internal/gc/mkbuiltin.go b/src/cmd/compile/internal/gc/mkbuiltin.go
index ea3877f..b1e4458 100644
--- a/src/cmd/compile/internal/gc/mkbuiltin.go
+++ b/src/cmd/compile/internal/gc/mkbuiltin.go
@@ -4,8 +4,9 @@
 
 // +build ignore
 
-// Generate builtin.go from $* (runtime.go and unsafe.go).
-// Run this after changing runtime.go and unsafe.go
+// Generate builtin.go from builtin/runtime.go and builtin/unsafe.go
+// (passed as arguments on the command line by a go:generate comment).
+// 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
diff --git a/src/cmd/compile/internal/gc/mparith2.go b/src/cmd/compile/internal/gc/mparith2.go
index 2c7e517..28c3a00 100644
--- a/src/cmd/compile/internal/gc/mparith2.go
+++ b/src/cmd/compile/internal/gc/mparith2.go
@@ -31,6 +31,12 @@ func mpmovefixfix(a, b *Mpint) {
 }
 
 func mpmovefltfix(a *Mpint, b *Mpflt) int {
+	// avoid converting huge floating-point numbers to integers
+	// (2*Mpprec is large enough to permit all tests to pass)
+	if b.Val.MantExp(nil) > 2*Mpprec {
+		return -1
+	}
+
 	if _, acc := b.Val.Int(&a.Val); acc == big.Exact {
 		return 0
 	}
@@ -229,7 +235,7 @@ func mprshfixfix(a, b *Mpint) {
 	}
 
 	s := Mpgetfix(b)
-	if s < 0 || s >= Mpprec {
+	if s < 0 {
 		Yyerror("stupid shift: %d", s)
 		if a.Val.Sign() < 0 {
 			Mpmovecfix(a, -1)
diff --git a/src/cmd/compile/internal/gc/mparith3.go b/src/cmd/compile/internal/gc/mparith3.go
index bf37f2d..9bcfda7 100644
--- a/src/cmd/compile/internal/gc/mparith3.go
+++ b/src/cmd/compile/internal/gc/mparith3.go
@@ -9,7 +9,6 @@ import (
 	"cmd/internal/obj"
 	"fmt"
 	"math"
-	"strings"
 )
 
 /// implements float arihmetic
@@ -114,7 +113,7 @@ func mpgetflt(a *Mpflt) float64 {
 		Yyerror("mpgetflt ovf")
 	}
 
-	return x
+	return x + 0 // avoid -0 (should not be needed, but be conservative)
 }
 
 func mpgetflt32(a *Mpflt) float64 {
@@ -126,7 +125,7 @@ func mpgetflt32(a *Mpflt) float64 {
 		Yyerror("mpgetflt32 ovf")
 	}
 
-	return x
+	return x + 0 // avoid -0 (should not be needed, but be conservative)
 }
 
 func Mpmovecflt(a *Mpflt, c float64) {
@@ -134,6 +133,10 @@ func Mpmovecflt(a *Mpflt, c float64) {
 		fmt.Printf("\nconst %g", c)
 	}
 
+	// convert -0 to 0
+	if c == 0 {
+		c = 0
+	}
 	a.Val.SetFloat64(c)
 
 	if Mpdebug {
@@ -142,7 +145,10 @@ func Mpmovecflt(a *Mpflt, c float64) {
 }
 
 func mpnegflt(a *Mpflt) {
-	a.Val.Neg(&a.Val)
+	// avoid -0
+	if a.Val.Sign() != 0 {
+		a.Val.Neg(&a.Val)
+	}
 }
 
 //
@@ -154,30 +160,6 @@ func mpatoflt(a *Mpflt, as string) {
 		as = as[1:]
 	}
 
-	// The spec requires accepting exponents that fit in int32.
-	// Don't accept much more than that.
-	// Count digits in exponent and stop early if there are too many.
-	if i := strings.Index(as, "e"); i >= 0 {
-		i++
-		if i < len(as) && (as[i] == '-' || as[i] == '+') {
-			i++
-		}
-		for i < len(as) && as[i] == '0' {
-			i++
-		}
-		// TODO(rsc): This should be > 10, because we're supposed
-		// to accept any signed 32-bit int as an exponent.
-		// But that's not working terribly well, so we deviate from the
-		// spec in order to make sure that what we accept works.
-		// We can remove this restriction once those larger exponents work.
-		// See golang.org/issue/11326 and test/fixedbugs/issue11326*.go.
-		if len(as)-i > 8 {
-			Yyerror("malformed constant: %s (exponent too large)", as)
-			a.Val.SetUint64(0)
-			return
-		}
-	}
-
 	f, ok := a.Val.SetString(as)
 	if !ok {
 		// At the moment we lose precise error cause;
@@ -188,15 +170,20 @@ func mpatoflt(a *Mpflt, as string) {
 		// - decimal point and binary point in constant
 		// TODO(gri) use different conversion function or check separately
 		Yyerror("malformed constant: %s", as)
-		a.Val.SetUint64(0)
+		a.Val.SetFloat64(0)
 		return
 	}
 
 	if f.IsInf() {
 		Yyerror("constant too large: %s", as)
-		a.Val.SetUint64(0)
+		a.Val.SetFloat64(0)
 		return
 	}
+
+	// -0 becomes 0
+	if f.Sign() == 0 && f.Signbit() {
+		a.Val.SetFloat64(0)
+	}
 }
 
 func (f *Mpflt) String() string {
@@ -213,38 +200,52 @@ func Fconv(fvp *Mpflt, flag int) string {
 	// determine sign
 	f := &fvp.Val
 	var sign string
-	if fvp.Val.Signbit() {
+	if f.Sign() < 0 {
 		sign = "-"
 		f = new(big.Float).Abs(f)
 	} else if flag&obj.FmtSign != 0 {
 		sign = "+"
 	}
 
-	// Use fmt formatting if in float64 range (common case).
-	if x, _ := f.Float64(); !math.IsInf(x, 0) {
+	// Don't try to convert infinities (will not terminate).
+	if f.IsInf() {
+		return sign + "Inf"
+	}
+
+	// Use exact fmt formatting if in float64 range (common case):
+	// proceed if f doesn't underflow to 0 or overflow to inf.
+	if x, _ := f.Float64(); f.Sign() == 0 == (x == 0) && !math.IsInf(x, 0) {
 		return fmt.Sprintf("%s%.6g", sign, x)
 	}
 
 	// Out of float64 range. Do approximate manual to decimal
 	// conversion to avoid precise but possibly slow Float
-	// formatting. The exponent is > 0 since a negative out-
-	// of-range exponent would have underflowed and led to 0.
+	// formatting.
 	// f = mant * 2**exp
 	var mant big.Float
-	exp := float64(f.MantExp(&mant)) // 0.5 <= mant < 1.0, exp > 0
+	exp := f.MantExp(&mant) // 0.5 <= mant < 1.0
 
 	// approximate float64 mantissa m and decimal exponent d
 	// f ~ m * 10**d
-	m, _ := mant.Float64()            // 0.5 <= m < 1.0
-	d := exp * (math.Ln2 / math.Ln10) // log_10(2)
+	m, _ := mant.Float64()                     // 0.5 <= m < 1.0
+	d := float64(exp) * (math.Ln2 / math.Ln10) // log_10(2)
 
 	// adjust m for truncated (integer) decimal exponent e
 	e := int64(d)
 	m *= math.Pow(10, d-float64(e))
-	for m >= 10 {
+
+	// ensure 1 <= m < 10
+	switch {
+	case m < 1-0.5e-6:
+		// The %.6g format below rounds m to 5 digits after the
+		// decimal point. Make sure that m*10 < 10 even after
+		// rounding up: m*10 + 0.5e-5 < 10 => m < 1 - 0.5e6.
+		m *= 10
+		e--
+	case m >= 10:
 		m /= 10
 		e++
 	}
 
-	return fmt.Sprintf("%s%.5fe+%d", sign, m, e)
+	return fmt.Sprintf("%s%.6ge%+d", sign, m, e)
 }
diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go
index d2ac813..66549be 100644
--- a/src/cmd/compile/internal/gc/obj.go
+++ b/src/cmd/compile/internal/gc/obj.go
@@ -10,9 +10,7 @@ import (
 	"strconv"
 )
 
-/*
- * architecture-independent object file output
- */
+// architecture-independent object file output
 const (
 	ArhdrSize = 60
 )
@@ -72,10 +70,7 @@ func dumpobj() {
 
 	fmt.Fprintf(bout, "\n!\n")
 
-	var externs *NodeList
-	if externdcl != nil {
-		externs = externdcl.End
-	}
+	externs := len(externdcl)
 
 	dumpglobls()
 	dumptypestructs()
@@ -83,15 +78,12 @@ func dumpobj() {
 	// Dump extra globals.
 	tmp := externdcl
 
-	if externs != nil {
-		externdcl = externs.Next
+	if externdcl != nil {
+		externdcl = externdcl[externs:]
 	}
 	dumpglobls()
 	externdcl = tmp
 
-	zero := Pkglookup("zerovalue", Runtimepkg)
-	ggloblsym(zero, int32(zerosize), obj.DUPOK|obj.RODATA)
-
 	dumpdata()
 	obj.Writeobjdirect(Ctxt, bout)
 
@@ -110,17 +102,14 @@ func dumpobj() {
 }
 
 func dumpglobls() {
-	var n *Node
-
 	// add globals
-	for l := externdcl; l != nil; l = l.Next {
-		n = l.N
+	for _, n := range externdcl {
 		if n.Op != ONAME {
 			continue
 		}
 
 		if n.Type == nil {
-			Fatal("external %v nil type\n", n)
+			Fatalf("external %v nil type\n", n)
 		}
 		if n.Class == PFUNC {
 			continue
@@ -129,12 +118,10 @@ func dumpglobls() {
 			continue
 		}
 		dowidth(n.Type)
-
 		ggloblnod(n)
 	}
 
-	for l := funcsyms; l != nil; l = l.Next {
-		n = l.N
+	for _, n := range funcsyms {
 		dsymptr(n.Sym, 0, n.Sym.Def.Func.Shortname.Sym, 0)
 		ggloblsym(n.Sym, int32(Widthptr), obj.DUPOK|obj.RODATA)
 	}
@@ -190,10 +177,6 @@ func duint32(s *Sym, off int, v uint32) int {
 	return duintxx(s, off, uint64(v), 4)
 }
 
-func duint64(s *Sym, off int, v uint64) int {
-	return duintxx(s, off, v, 8)
-}
-
 func duintptr(s *Sym, off int, v uint64) int {
 	return duintxx(s, off, v, Widthptr)
 }
@@ -279,7 +262,7 @@ func slicebytes(nam *Node, s string, len int) {
 	ggloblsym(sym, int32(off), obj.NOPTR|obj.LOCAL)
 
 	if nam.Op != ONAME {
-		Fatal("slicebytes %v", nam)
+		Fatalf("slicebytes %v", nam)
 	}
 	off = int(nam.Xoffset)
 	off = dsymptr(nam.Sym, off, sym, 0)
@@ -287,25 +270,6 @@ func slicebytes(nam *Node, s string, len int) {
 	duintxx(nam.Sym, off, uint64(len), Widthint)
 }
 
-func dstringptr(s *Sym, off int, str string) int {
-	off = int(Rnd(int64(off), int64(Widthptr)))
-	p := Thearch.Gins(obj.ADATA, nil, nil)
-	p.From.Type = obj.TYPE_MEM
-	p.From.Name = obj.NAME_EXTERN
-	p.From.Sym = Linksym(s)
-	p.From.Offset = int64(off)
-	p.From3 = new(obj.Addr)
-	p.From3.Type = obj.TYPE_CONST
-	p.From3.Offset = int64(Widthptr)
-
-	Datastring(str+"\x00", &p.To) // TODO(rsc): Remove NUL
-	p.To.Type = obj.TYPE_ADDR
-	p.To.Etype = Simtype[TINT]
-	off += Widthptr
-
-	return off
-}
-
 func Datastring(s string, a *obj.Addr) {
 	_, symdata := stringsym(s)
 	a.Type = obj.TYPE_MEM
@@ -313,7 +277,7 @@ func Datastring(s string, a *obj.Addr) {
 	a.Sym = Linksym(symdata)
 	a.Node = symdata.Def
 	a.Offset = 0
-	a.Etype = Simtype[TINT]
+	a.Etype = uint8(Simtype[TINT])
 }
 
 func datagostring(sval string, a *obj.Addr) {
@@ -323,7 +287,7 @@ func datagostring(sval string, a *obj.Addr) {
 	a.Sym = Linksym(symhdr)
 	a.Node = symhdr.Def
 	a.Offset = 0
-	a.Etype = TSTRING
+	a.Etype = uint8(TSTRING)
 }
 
 func dgostringptr(s *Sym, off int, str string) int {
@@ -348,7 +312,7 @@ func dgostrlitptr(s *Sym, off int, lit *string) int {
 	p.From3.Offset = int64(Widthptr)
 	datagostring(*lit, &p.To)
 	p.To.Type = obj.TYPE_ADDR
-	p.To.Etype = Simtype[TINT]
+	p.To.Etype = uint8(Simtype[TINT])
 	off += Widthptr
 
 	return off
@@ -409,8 +373,8 @@ func gdata(nam *Node, nr *Node, wid int) {
 }
 
 func gdatacomplex(nam *Node, cval *Mpcplx) {
-	w := cplxsubtype(int(nam.Type.Etype))
-	w = int(Types[w].Width)
+	cst := cplxsubtype(nam.Type.Etype)
+	w := int(Types[cst].Width)
 
 	p := Thearch.Gins(obj.ADATA, nam, nil)
 	p.From3 = new(obj.Addr)
diff --git a/src/cmd/compile/internal/gc/opnames.go b/src/cmd/compile/internal/gc/opnames.go
index 9134bd4..0609643 100644
--- a/src/cmd/compile/internal/gc/opnames.go
+++ b/src/cmd/compile/internal/gc/opnames.go
@@ -149,6 +149,7 @@ var opnames = []string{
 	OCFUNC:           "CFUNC",
 	OCHECKNIL:        "CHECKNIL",
 	OVARKILL:         "VARKILL",
+	OVARLIVE:         "VARLIVE",
 	OREGISTER:        "REGISTER",
 	OINDREG:          "INDREG",
 	OCMP:             "CMP",
diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go
index a5cf920..a2e1228 100644
--- a/src/cmd/compile/internal/gc/order.go
+++ b/src/cmd/compile/internal/gc/order.go
@@ -182,7 +182,7 @@ func ordersafeexpr(n *Node, order *Order) *Node {
 		return a
 	}
 
-	Fatal("ordersafeexpr %v", Oconv(int(n.Op), 0))
+	Fatalf("ordersafeexpr %v", Oconv(int(n.Op), 0))
 	return nil // not reached
 }
 
@@ -243,6 +243,12 @@ func cleantempnopop(mark *NodeList, order *Order, out **NodeList) {
 	var kill *Node
 
 	for l := order.temp; l != mark; l = l.Next {
+		if l.N.Name.Keepalive {
+			l.N.Name.Keepalive = false
+			kill = Nod(OVARLIVE, l.N, nil)
+			typecheck(&kill, Etop)
+			*out = list(*out, kill)
+		}
 		kill = Nod(OVARKILL, l.N, nil)
 		typecheck(&kill, Etop)
 		*out = list(*out, kill)
@@ -336,8 +342,8 @@ func ismulticall(l *NodeList) bool {
 // Copyret emits t1, t2, ... = n, where n is a function call,
 // and then returns the list t1, t2, ....
 func copyret(n *Node, order *Order) *NodeList {
-	if n.Type.Etype != TSTRUCT || n.Type.Funarg == 0 {
-		Fatal("copyret %v %d", n.Type, n.Left.Type.Outtuple)
+	if n.Type.Etype != TSTRUCT || !n.Type.Funarg {
+		Fatalf("copyret %v %d", n.Type, n.Left.Type.Outtuple)
 	}
 
 	var l1 *NodeList
@@ -375,6 +381,28 @@ func ordercall(n *Node, order *Order) {
 	orderexpr(&n.Left, order, nil)
 	orderexpr(&n.Right, order, nil) // ODDDARG temp
 	ordercallargs(&n.List, order)
+
+	if n.Op == OCALLFUNC {
+		for l, t := n.List, getinargx(n.Left.Type).Type; l != nil && t != nil; l, t = l.Next, t.Down {
+			// Check for "unsafe-uintptr" tag provided by escape analysis.
+			// If present and the argument is really a pointer being converted
+			// to uintptr, arrange for the pointer to be kept alive until the call
+			// returns, by copying it into a temp and marking that temp
+			// still alive when we pop the temp stack.
+			if t.Note != nil && *t.Note == unsafeUintptrTag {
+				xp := &l.N
+				for (*xp).Op == OCONVNOP && !Isptr[(*xp).Type.Etype] {
+					xp = &(*xp).Left
+				}
+				x := *xp
+				if Isptr[x.Type.Etype] {
+					x = ordercopyexpr(x, x.Type, order, 0)
+					x.Name.Keepalive = true
+					*xp = x
+				}
+			}
+		}
+	}
 }
 
 // Ordermapassign appends n to order->out, introducing temporaries
@@ -396,19 +424,19 @@ func ordercall(n *Node, order *Order) {
 // contain m or k. They are usually unnecessary, but in the unnecessary
 // cases they are also typically registerizable, so not much harm done.
 // And this only applies to the multiple-assignment form.
-// We could do a more precise analysis if needed, like in walk.c.
+// We could do a more precise analysis if needed, like in walk.go.
 //
 // Ordermapassign also inserts these temporaries if needed for
 // calling writebarrierfat with a pointer to n->right.
 func ordermapassign(n *Node, order *Order) {
 	switch n.Op {
 	default:
-		Fatal("ordermapassign %v", Oconv(int(n.Op), 0))
+		Fatalf("ordermapassign %v", Oconv(int(n.Op), 0))
 
 	case OAS:
 		order.out = list(order.out, n)
 
-		// We call writebarrierfat only for values > 4 pointers long. See walk.c.
+		// We call writebarrierfat only for values > 4 pointers long. See walk.go.
 		if (n.Left.Op == OINDEXMAP || (needwritebarrier(n.Left, n.Right) && n.Left.Type.Width > int64(4*Widthptr))) && !isaddrokay(n.Right) {
 			m := n.Left
 			n.Left = ordertemp(m.Type, order, false)
@@ -434,7 +462,7 @@ func ordermapassign(n *Node, order *Order) {
 				a = Nod(OAS, m, l.N)
 				typecheck(&a, Etop)
 				post = list(post, a)
-			} else if flag_race != 0 && n.Op == OAS2FUNC && !isblank(l.N) {
+			} else if instrumenting && n.Op == OAS2FUNC && !isblank(l.N) {
 				m = l.N
 				l.N = ordertemp(m.Type, order, false)
 				a = Nod(OAS, m, l.N)
@@ -462,9 +490,9 @@ func orderstmt(n *Node, order *Order) {
 
 	switch n.Op {
 	default:
-		Fatal("orderstmt %v", Oconv(int(n.Op), 0))
+		Fatalf("orderstmt %v", Oconv(int(n.Op), 0))
 
-	case OVARKILL:
+	case OVARKILL, OVARLIVE:
 		order.out = list(order.out, n)
 
 	case OAS:
@@ -509,7 +537,8 @@ func orderstmt(n *Node, order *Order) {
 			tmp1.Etype = 0 // now an rvalue not an lvalue
 		}
 		tmp1 = ordercopyexpr(tmp1, n.Left.Type, order, 0)
-		n.Right = Nod(int(n.Etype), tmp1, n.Right)
+		// TODO(marvin): Fix Node.EType type union.
+		n.Right = Nod(Op(n.Etype), tmp1, n.Right)
 		typecheck(&n.Right, Erv)
 		orderexpr(&n.Right, order, nil)
 		n.Etype = 0
@@ -704,7 +733,7 @@ func orderstmt(n *Node, order *Order) {
 		orderexpr(&n.Right, order, nil)
 		switch n.Type.Etype {
 		default:
-			Fatal("orderstmt range %v", n.Type)
+			Fatalf("orderstmt range %v", n.Type)
 
 			// Mark []byte(str) range expression to reuse string backing storage.
 		// It is safe because the storage cannot be mutated.
@@ -756,7 +785,7 @@ func orderstmt(n *Node, order *Order) {
 		ordercallargs(&n.List, order)
 		order.out = list(order.out, n)
 
-		// Special: clean case temporaries in each block entry.
+	// Special: clean case temporaries in each block entry.
 	// Select must enter one of its blocks, so there is no
 	// need for a cleaning at the end.
 	// Doubly special: evaluation order for select is stricter
@@ -773,7 +802,7 @@ func orderstmt(n *Node, order *Order) {
 		var r *Node
 		for l := n.List; l != nil; l = l.Next {
 			if l.N.Op != OXCASE {
-				Fatal("order select case %v", Oconv(int(l.N.Op), 0))
+				Fatalf("order select case %v", Oconv(int(l.N.Op), 0))
 			}
 			r = l.N.Left
 			setlineno(l.N)
@@ -781,7 +810,7 @@ func orderstmt(n *Node, order *Order) {
 			// Append any new body prologue to ninit.
 			// The next loop will insert ninit into nbody.
 			if l.N.Ninit != nil {
-				Fatal("order select ninit")
+				Fatalf("order select ninit")
 			}
 			if r != nil {
 				switch r.Op {
@@ -795,14 +824,14 @@ func orderstmt(n *Node, order *Order) {
 				// Delete the ODCL nodes here and recreate them inside the body below.
 				case OSELRECV, OSELRECV2:
 					if r.Colas {
-						t = r.Ninit
-						if t != nil && t.N.Op == ODCL && t.N.Left == r.Left {
-							t = t.Next
+						init := r.Ninit
+						if init != nil && init.N.Op == ODCL && init.N.Left == r.Left {
+							init = init.Next
 						}
-						if t != nil && t.N.Op == ODCL && r.List != nil && t.N.Left == r.List.N {
-							t = t.Next
+						if init != nil && init.N.Op == ODCL && r.List != nil && init.N.Left == r.List.N {
+							init = init.Next
 						}
-						if t == nil {
+						if init == nil {
 							r.Ninit = nil
 						}
 					}
@@ -927,7 +956,7 @@ func orderstmt(n *Node, order *Order) {
 		orderexpr(&n.Left, order, nil)
 		for l := n.List; l != nil; l = l.Next {
 			if l.N.Op != OXCASE {
-				Fatal("order switch case %v", Oconv(int(l.N.Op), 0))
+				Fatalf("order switch case %v", Oconv(int(l.N.Op), 0))
 			}
 			orderexprlistinplace(l.N.List, order)
 			orderblock(&l.N.Nbody)
@@ -1096,7 +1125,7 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
 		OSTRARRAYBYTETMP,
 		OSTRARRAYRUNE:
 		ordercall(n, order)
-		if lhs == nil || lhs.Op != ONAME || flag_race != 0 {
+		if lhs == nil || lhs.Op != ONAME || instrumenting {
 			n = ordercopyexpr(n, n.Type, order, 0)
 		}
 
@@ -1156,7 +1185,7 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
 		// TODO(rsc): The Isfat is for consistency with componentgen and walkexpr.
 		// It needs to be removed in all three places.
 		// That would allow inlining x.(struct{*int}) the same as x.(*int).
-		if !isdirectiface(n.Type) || Isfat(n.Type) || flag_race != 0 {
+		if !isdirectiface(n.Type) || Isfat(n.Type) || instrumenting {
 			n = ordercopyexpr(n, n.Type, order, 1)
 		}
 
diff --git a/src/cmd/compile/internal/gc/parser.go b/src/cmd/compile/internal/gc/parser.go
new file mode 100644
index 0000000..054cf73
--- /dev/null
+++ b/src/cmd/compile/internal/gc/parser.go
@@ -0,0 +1,3506 @@
+// Copyright 2015 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
+
+// The recursive-descent parser is built around a slighty modified grammar
+// of Go to accomodate for the constraints imposed by strict one token look-
+// ahead, and for better error handling. Subsequent checks of the constructed
+// syntax tree restrict the language accepted by the compiler to proper Go.
+//
+// Semicolons are inserted by the lexer. The parser uses one-token look-ahead
+// to handle optional commas and semicolons before a closing ) or } .
+
+import (
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+const trace = false // if set, parse tracing can be enabled with -x
+
+// TODO(gri) Once we handle imports w/o redirecting the underlying
+// source of the lexer we can get rid of these. They are here for
+// compatibility with the existing yacc-based parser setup (issue 13242).
+var thenewparser parser // the parser in use
+var savedstate []parser // saved parser state, used during import
+
+func push_parser() {
+	// Indentation (for tracing) must be preserved across parsers
+	// since we are changing the lexer source (and parser state)
+	// under foot, in the middle of productions. This won't be
+	// needed anymore once we fix issue 13242, but neither will
+	// be the push/pop_parser functionality.
+	// (Instead we could just use a global variable indent, but
+	// but eventually indent should be parser-specific anyway.)
+	indent := thenewparser.indent
+	savedstate = append(savedstate, thenewparser)
+	thenewparser = parser{indent: indent} // preserve indentation
+	thenewparser.next()
+}
+
+func pop_parser() {
+	indent := thenewparser.indent
+	n := len(savedstate) - 1
+	thenewparser = savedstate[n]
+	thenewparser.indent = indent // preserve indentation
+	savedstate = savedstate[:n]
+}
+
+// parse_file sets up a new parser and parses a single Go source file.
+func parse_file() {
+	thenewparser = parser{}
+	thenewparser.loadsys()
+	thenewparser.next()
+	thenewparser.file()
+}
+
+// loadsys loads the definitions for the low-level runtime functions,
+// so that the compiler can generate calls to them,
+// but does not make the name "runtime" visible as a package.
+func (p *parser) loadsys() {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("loadsys")()
+	}
+
+	importpkg = Runtimepkg
+
+	if Debug['A'] != 0 {
+		cannedimports("runtime.Builtin", "package runtime\n\n$$\n\n")
+	} else {
+		cannedimports("runtime.Builtin", runtimeimport)
+	}
+	curio.importsafe = true
+
+	p.import_package()
+	p.import_there()
+
+	importpkg = nil
+}
+
+type parser struct {
+	tok    int32     // next token (one-token look-ahead)
+	op     Op        // valid if tok == LASOP
+	val    Val       // valid if tok == LLITERAL
+	sym_   *Sym      // valid if tok == LNAME
+	fnest  int       // function nesting level (for error handling)
+	xnest  int       // expression nesting level (for complit ambiguity resolution)
+	yy     yySymType // for temporary use by next
+	indent []byte    // tracing support
+}
+
+func (p *parser) next() {
+	p.tok = yylex(&p.yy)
+	p.op = p.yy.op
+	p.val = p.yy.val
+	p.sym_ = p.yy.sym
+}
+
+func (p *parser) got(tok int32) bool {
+	if p.tok == tok {
+		p.next()
+		return true
+	}
+	return false
+}
+
+func (p *parser) want(tok int32) {
+	if !p.got(tok) {
+		p.syntax_error("expecting " + tokstring(tok))
+		p.advance()
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Syntax error handling
+
+func (p *parser) syntax_error(msg string) {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("syntax_error (" + msg + ")")()
+	}
+
+	if p.tok == EOF && nerrors > 0 {
+		return // avoid meaningless follow-up errors
+	}
+
+	// add punctuation etc. as needed to msg
+	switch {
+	case msg == "":
+		// nothing to do
+	case strings.HasPrefix(msg, "in"), strings.HasPrefix(msg, "at"), strings.HasPrefix(msg, "after"):
+		msg = " " + msg
+	case strings.HasPrefix(msg, "expecting"):
+		msg = ", " + msg
+	default:
+		// plain error - we don't care about current token
+		Yyerror("syntax error: %s", msg)
+		return
+	}
+
+	// determine token string
+	var tok string
+	switch p.tok {
+	case LLITERAL:
+		tok = litbuf
+	case LNAME:
+		if p.sym_ != nil && p.sym_.Name != "" {
+			tok = p.sym_.Name
+		} else {
+			tok = "name"
+		}
+	case LASOP:
+		tok = goopnames[p.op] + "="
+	default:
+		tok = tokstring(p.tok)
+	}
+
+	Yyerror("syntax error: unexpected %s", tok+msg)
+}
+
+// Like syntax_error, but reports error at given line rather than current lexer line.
+func (p *parser) syntax_error_at(lineno int32, msg string) {
+	defer func(lineno int32) {
+		lexlineno = lineno
+	}(lexlineno)
+	lexlineno = lineno
+	p.syntax_error(msg)
+}
+
+// The stoplist contains keywords that start a statement.
+// They are good synchronization points in case of syntax
+// errors and (usually) shouldn't be skipped over.
+var stoplist = map[int32]bool{
+	LBREAK:    true,
+	LCONST:    true,
+	LCONTINUE: true,
+	LDEFER:    true,
+	LFALL:     true,
+	LFOR:      true,
+	LFUNC:     true,
+	LGO:       true,
+	LGOTO:     true,
+	LIF:       true,
+	LRETURN:   true,
+	LSELECT:   true,
+	LSWITCH:   true,
+	LTYPE:     true,
+	LVAR:      true,
+}
+
+// Advance consumes tokens until it finds a token of the stop- or followlist.
+// The stoplist is only considered if we are inside a function (p.fnest > 0).
+// The followlist is the list of valid tokens that can follow a production;
+// if it is empty, exactly one token is consumed to ensure progress.
+func (p *parser) advance(followlist ...int32) {
+	if len(followlist) == 0 {
+		p.next()
+		return
+	}
+	for p.tok != EOF {
+		if p.fnest > 0 && stoplist[p.tok] {
+			return
+		}
+		for _, follow := range followlist {
+			if p.tok == follow {
+				return
+			}
+		}
+		p.next()
+	}
+}
+
+func tokstring(tok int32) string {
+	switch tok {
+	case EOF:
+		return "EOF"
+	case ',':
+		return "comma"
+	case ';':
+		return "semicolon or newline"
+	}
+	if 0 <= tok && tok < 128 {
+		// get invisibles properly backslashed
+		s := strconv.QuoteRune(tok)
+		if n := len(s); n > 0 && s[0] == '\'' && s[n-1] == '\'' {
+			s = s[1 : n-1]
+		}
+		return s
+	}
+	if s := tokstrings[tok]; s != "" {
+		return s
+	}
+	// catchall
+	return fmt.Sprintf("tok-%v", tok)
+}
+
+var tokstrings = map[int32]string{
+	LLITERAL:   "LLITERAL",
+	LASOP:      "op=",
+	LCOLAS:     ":=",
+	LBREAK:     "break",
+	LCASE:      "case",
+	LCHAN:      "chan",
+	LCONST:     "const",
+	LCONTINUE:  "continue",
+	LDDD:       "...",
+	LDEFAULT:   "default",
+	LDEFER:     "defer",
+	LELSE:      "else",
+	LFALL:      "fallthrough",
+	LFOR:       "for",
+	LFUNC:      "func",
+	LGO:        "go",
+	LGOTO:      "goto",
+	LIF:        "if",
+	LIMPORT:    "import",
+	LINTERFACE: "interface",
+	LMAP:       "map",
+	LNAME:      "LNAME",
+	LPACKAGE:   "package",
+	LRANGE:     "range",
+	LRETURN:    "return",
+	LSELECT:    "select",
+	LSTRUCT:    "struct",
+	LSWITCH:    "switch",
+	LTYPE:      "type",
+	LVAR:       "var",
+	LANDAND:    "&&",
+	LANDNOT:    "&^",
+	LCOMM:      "<-",
+	LDEC:       "--",
+	LEQ:        "==",
+	LGE:        ">=",
+	LGT:        ">",
+	LIGNORE:    "LIGNORE", // we should never see this one
+	LINC:       "++",
+	LLE:        "<=",
+	LLSH:       "<<",
+	LLT:        "<",
+	LNE:        "!=",
+	LOROR:      "||",
+	LRSH:       ">>",
+}
+
+// usage: defer p.trace(msg)()
+func (p *parser) trace(msg string) func() {
+	fmt.Printf("%5d: %s%s (\n", lineno, p.indent, msg)
+	const tab = ". "
+	p.indent = append(p.indent, tab...)
+	return func() {
+		p.indent = p.indent[:len(p.indent)-len(tab)]
+		if x := recover(); x != nil {
+			panic(x) // skip print_trace
+		}
+		fmt.Printf("%5d: %s)\n", lineno, p.indent)
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Parsing package files
+//
+// Parse methods are annotated with matching Go productions as appropriate.
+// The annotations are intended as guidelines only since a single Go grammar
+// rule may be covered by multiple parse methods and vice versa.
+
+// SourceFile = PackageClause ";" { ImportDecl ";" } { TopLevelDecl ";" } .
+func (p *parser) file() {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("file")()
+	}
+
+	p.package_()
+	p.want(';')
+
+	for p.tok == LIMPORT {
+		p.import_()
+		p.want(';')
+	}
+
+	xtop = concat(xtop, p.xdcl_list())
+
+	p.want(EOF)
+}
+
+// PackageClause = "package" PackageName .
+// PackageName   = identifier .
+func (p *parser) package_() {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("package_")()
+	}
+
+	if p.got(LPACKAGE) {
+		mkpackage(p.sym().Name)
+	} else {
+		prevlineno = lineno // see issue #13267
+		p.syntax_error("package statement must be first")
+		errorexit()
+	}
+}
+
+// ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) .
+func (p *parser) import_() {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("import_")()
+	}
+
+	p.want(LIMPORT)
+	if p.got('(') {
+		for p.tok != EOF && p.tok != ')' {
+			p.import_stmt()
+			if !p.osemi(')') {
+				break
+			}
+		}
+		p.want(')')
+	} else {
+		p.import_stmt()
+	}
+}
+
+func (p *parser) import_stmt() {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("import_stmt")()
+	}
+
+	line := int32(p.import_here())
+	if p.tok == LPACKAGE {
+		p.import_package()
+		p.import_there()
+
+		ipkg := importpkg
+		my := importmyname
+		importpkg = nil
+		importmyname = nil
+
+		if my == nil {
+			my = Lookup(ipkg.Name)
+		}
+
+		pack := Nod(OPACK, nil, nil)
+		pack.Sym = my
+		pack.Name.Pkg = ipkg
+		pack.Lineno = line
+
+		if strings.HasPrefix(my.Name, ".") {
+			importdot(ipkg, pack)
+			return
+		}
+		if my.Name == "init" {
+			lineno = line
+			Yyerror("cannot import package as init - init must be a func")
+			return
+		}
+		if my.Name == "_" {
+			return
+		}
+		if my.Def != nil {
+			lineno = line
+			redeclare(my, "as imported package name")
+		}
+		my.Def = pack
+		my.Lastlineno = line
+		my.Block = 1 // at top level
+
+		return
+	}
+
+	p.import_there()
+	// When an invalid import path is passed to importfile,
+	// it calls Yyerror and then sets up a fake import with
+	// no package statement. This allows us to test more
+	// than one invalid import statement in a single file.
+	if nerrors == 0 {
+		Fatalf("phase error in import")
+	}
+}
+
+// ImportSpec = [ "." | PackageName ] ImportPath .
+// ImportPath = string_lit .
+//
+// import_here switches the underlying lexed source to the export data
+// of the imported package.
+func (p *parser) import_here() int {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("import_here")()
+	}
+
+	importmyname = nil
+	switch p.tok {
+	case LNAME, '@', '?':
+		// import with given name
+		importmyname = p.sym()
+
+	case '.':
+		// import into my name space
+		importmyname = Lookup(".")
+		p.next()
+	}
+
+	var path Val
+	if p.tok == LLITERAL {
+		path = p.val
+		p.next()
+	} else {
+		p.syntax_error("missing import path; require quoted string")
+		p.advance(';', ')')
+	}
+
+	line := parserline()
+	importfile(&path, line)
+	return line
+}
+
+// import_package parses the header of an imported package as exported
+// in textual format from another package.
+func (p *parser) import_package() {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("import_package")()
+	}
+
+	p.want(LPACKAGE)
+	var name string
+	if p.tok == LNAME {
+		name = p.sym_.Name
+		p.next()
+	} else {
+		p.import_error()
+	}
+
+	if p.tok == LNAME {
+		if p.sym_.Name == "safe" {
+			curio.importsafe = true
+		}
+		p.next()
+	}
+	p.want(';')
+
+	if importpkg.Name == "" {
+		importpkg.Name = name
+		numImport[name]++
+	} else if importpkg.Name != name {
+		Yyerror("conflicting names %s and %s for package %q", importpkg.Name, name, importpkg.Path)
+	}
+	if incannedimport == 0 {
+		importpkg.Direct = true
+	}
+	importpkg.Safe = curio.importsafe
+
+	if safemode != 0 && !curio.importsafe {
+		Yyerror("cannot import unsafe package %q", importpkg.Path)
+	}
+}
+
+// import_there parses the imported package definitions and then switches
+// the underlying lexed source back to the importing package.
+func (p *parser) import_there() {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("import_there")()
+	}
+
+	defercheckwidth()
+
+	p.hidden_import_list()
+	p.want('$')
+	// don't read past 2nd '$'
+	if p.tok != '$' {
+		p.import_error()
+	}
+
+	resumecheckwidth()
+	unimportfile()
+}
+
+// Declaration = ConstDecl | TypeDecl | VarDecl .
+// ConstDecl   = "const" ( ConstSpec | "(" { ConstSpec ";" } ")" ) .
+// TypeDecl    = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) .
+// VarDecl     = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) .
+func (p *parser) common_dcl() *NodeList {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("common_dcl")()
+	}
+
+	var dcl func() *NodeList
+	switch p.tok {
+	case LVAR:
+		dcl = p.vardcl
+
+	case LCONST:
+		iota_ = 0
+		dcl = p.constdcl
+
+	case LTYPE:
+		dcl = p.typedcl
+
+	default:
+		panic("unreachable")
+	}
+
+	p.next()
+	var l *NodeList
+	if p.got('(') {
+		for p.tok != EOF && p.tok != ')' {
+			l = concat(l, dcl())
+			if !p.osemi(')') {
+				break
+			}
+		}
+		p.want(')')
+	} else {
+		l = dcl()
+	}
+
+	iota_ = -100000
+	lastconst = nil
+
+	return l
+}
+
+// VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) .
+func (p *parser) vardcl() *NodeList {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("vardcl")()
+	}
+
+	names := p.dcl_name_list()
+	var typ *Node
+	var exprs *NodeList
+	if p.got('=') {
+		exprs = p.expr_list()
+	} else {
+		typ = p.ntype()
+		if p.got('=') {
+			exprs = p.expr_list()
+		}
+	}
+
+	return variter(names, typ, exprs)
+}
+
+// ConstSpec = IdentifierList [ [ Type ] "=" ExpressionList ] .
+func (p *parser) constdcl() *NodeList {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("constdcl")()
+	}
+
+	names := p.dcl_name_list()
+	var typ *Node
+	var exprs *NodeList
+	if p.tok != EOF && p.tok != ';' && p.tok != ')' {
+		typ = p.try_ntype()
+		if p.got('=') {
+			exprs = p.expr_list()
+		}
+	}
+
+	return constiter(names, typ, exprs)
+}
+
+// TypeSpec = identifier Type .
+func (p *parser) typedcl() *NodeList {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("typedcl")()
+	}
+
+	name := typedcl0(p.sym())
+
+	typ := p.try_ntype()
+	// handle case where type is missing
+	if typ == nil {
+		p.syntax_error("in type declaration")
+		p.advance(';', ')')
+	}
+
+	return list1(typedcl1(name, typ, true))
+}
+
+// SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | ShortVarDecl .
+//
+// simple_stmt may return missing_stmt if labelOk is set.
+func (p *parser) simple_stmt(labelOk, rangeOk bool) *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("simple_stmt")()
+	}
+
+	if rangeOk && p.got(LRANGE) {
+		// LRANGE expr
+		r := Nod(ORANGE, nil, p.expr())
+		r.Etype = 0 // := flag
+		return r
+	}
+
+	lhs := p.expr_list()
+
+	if count(lhs) == 1 && p.tok != '=' && p.tok != LCOLAS && p.tok != LRANGE {
+		// expr
+		lhs := lhs.N
+		switch p.tok {
+		case LASOP:
+			// expr LASOP expr
+			op := p.op
+			p.next()
+			rhs := p.expr()
+
+			stmt := Nod(OASOP, lhs, rhs)
+			stmt.Etype = EType(op) // rathole to pass opcode
+			return stmt
+
+		case LINC:
+			// expr LINC
+			p.next()
+
+			stmt := Nod(OASOP, lhs, Nodintconst(1))
+			stmt.Implicit = true
+			stmt.Etype = EType(OADD)
+			return stmt
+
+		case LDEC:
+			// expr LDEC
+			p.next()
+
+			stmt := Nod(OASOP, lhs, Nodintconst(1))
+			stmt.Implicit = true
+			stmt.Etype = EType(OSUB)
+			return stmt
+
+		case ':':
+			// labelname ':' stmt
+			if labelOk {
+				// If we have a labelname, it was parsed by operand
+				// (calling p.name()) and given an ONAME, ONONAME, OTYPE, OPACK, or OLITERAL node.
+				// We only have a labelname if there is a symbol (was issue 14006).
+				switch lhs.Op {
+				case ONAME, ONONAME, OTYPE, OPACK, OLITERAL:
+					if lhs.Sym != nil {
+						lhs = newname(lhs.Sym)
+						break
+					}
+					fallthrough
+				default:
+					p.syntax_error("expecting semicolon or newline or }")
+					// we already progressed, no need to advance
+				}
+				lhs := Nod(OLABEL, lhs, nil)
+				lhs.Sym = dclstack // context, for goto restrictions
+				p.next()           // consume ':' after making label node for correct lineno
+				return p.labeled_stmt(lhs)
+			}
+			fallthrough
+
+		default:
+			// expr
+			// Since a bare name used as an expression is an error,
+			// introduce a wrapper node where necessary to give the
+			// correct line.
+			return wrapname(lhs)
+		}
+	}
+
+	// expr_list
+	switch p.tok {
+	case '=':
+		p.next()
+		if rangeOk && p.got(LRANGE) {
+			// expr_list '=' LRANGE expr
+			r := Nod(ORANGE, nil, p.expr())
+			r.List = lhs
+			r.Etype = 0 // := flag
+			return r
+		}
+
+		// expr_list '=' expr_list
+		rhs := p.expr_list()
+
+		if lhs.Next == nil && rhs.Next == nil {
+			// simple
+			return Nod(OAS, lhs.N, rhs.N)
+		}
+		// multiple
+		stmt := Nod(OAS2, nil, nil)
+		stmt.List = lhs
+		stmt.Rlist = rhs
+		return stmt
+
+	case LCOLAS:
+		lno := lineno
+		p.next()
+
+		if rangeOk && p.got(LRANGE) {
+			// expr_list LCOLAS LRANGE expr
+			r := Nod(ORANGE, nil, p.expr())
+			r.List = lhs
+			r.Colas = true
+			colasdefn(lhs, r)
+			return r
+		}
+
+		// expr_list LCOLAS expr_list
+		rhs := p.expr_list()
+
+		if rhs.N.Op == OTYPESW {
+			ts := Nod(OTYPESW, nil, rhs.N.Right)
+			if rhs.Next != nil {
+				Yyerror("expr.(type) must be alone in list")
+			}
+			if lhs.Next != nil {
+				Yyerror("argument count mismatch: %d = %d", count(lhs), 1)
+			} else if (lhs.N.Op != ONAME && lhs.N.Op != OTYPE && lhs.N.Op != ONONAME && (lhs.N.Op != OLITERAL || lhs.N.Name == nil)) || isblank(lhs.N) {
+				Yyerror("invalid variable name %s in type switch", lhs.N)
+			} else {
+				ts.Left = dclname(lhs.N.Sym)
+			} // it's a colas, so must not re-use an oldname
+			return ts
+		}
+		return colas(lhs, rhs, int32(lno))
+
+	default:
+		p.syntax_error("expecting := or = or comma")
+		p.advance(';', '}')
+		return nil
+	}
+}
+
+// LabeledStmt = Label ":" Statement .
+// Label       = identifier .
+func (p *parser) labeled_stmt(label *Node) *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("labeled_stmt")()
+	}
+
+	var ls *Node // labeled statement
+	if p.tok != '}' && p.tok != EOF {
+		ls = p.stmt()
+		if ls == missing_stmt {
+			// report error at line of ':' token
+			p.syntax_error_at(prevlineno, "missing statement after label")
+			// we are already at the end of the labeled statement - no need to advance
+			return missing_stmt
+		}
+	}
+
+	label.Name.Defn = ls
+	l := list1(label)
+	if ls != nil {
+		l = list(l, ls)
+	}
+	return liststmt(l)
+}
+
+// case_ parses a superset of switch and select statement cases.
+// Later checks restrict the syntax to valid forms.
+//
+// ExprSwitchCase = "case" ExpressionList | "default" .
+// TypeSwitchCase = "case" TypeList | "default" .
+// TypeList       = Type { "," Type } .
+// CommCase       = "case" ( SendStmt | RecvStmt ) | "default" .
+// RecvStmt       = [ ExpressionList "=" | IdentifierList ":=" ] RecvExpr .
+// RecvExpr       = Expression .
+func (p *parser) case_(tswitch *Node) *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("case_")()
+	}
+
+	switch p.tok {
+	case LCASE:
+		p.next()
+		cases := p.expr_list() // expr_or_type_list
+		switch p.tok {
+		case ':':
+			// LCASE expr_or_type_list ':'
+
+			// will be converted to OCASE
+			// right will point to next case
+			// done in casebody()
+			markdcl() // matching popdcl in caseblock
+			stmt := Nod(OXCASE, nil, nil)
+			stmt.List = cases
+			if tswitch != nil {
+				if n := tswitch.Left; n != nil {
+					// type switch - declare variable
+					nn := newname(n.Sym)
+					declare(nn, dclcontext)
+					stmt.Rlist = list1(nn)
+
+					// keep track of the instances for reporting unused
+					nn.Name.Defn = tswitch
+				}
+			}
+
+			p.next() // consume ':' after declaring type switch var for correct lineno
+			return stmt
+
+		case '=':
+			// LCASE expr_or_type_list '=' expr ':'
+			p.next()
+			rhs := p.expr()
+
+			// will be converted to OCASE
+			// right will point to next case
+			// done in casebody()
+			markdcl() // matching popdcl in caseblock
+			stmt := Nod(OXCASE, nil, nil)
+			var n *Node
+			if cases.Next == nil {
+				n = Nod(OAS, cases.N, rhs)
+			} else {
+				n = Nod(OAS2, nil, nil)
+				n.List = cases
+				n.Rlist = list1(rhs)
+			}
+			stmt.List = list1(n)
+
+			p.want(':') // consume ':' after declaring select cases for correct lineno
+			return stmt
+
+		case LCOLAS:
+			// LCASE expr_or_type_list LCOLAS expr ':'
+			lno := lineno
+			p.next()
+			rhs := p.expr()
+
+			// will be converted to OCASE
+			// right will point to next case
+			// done in casebody()
+			markdcl() // matching popdcl in caseblock
+			stmt := Nod(OXCASE, nil, nil)
+			stmt.List = list1(colas(cases, list1(rhs), int32(lno)))
+
+			p.want(':') // consume ':' after declaring select cases for correct lineno
+			return stmt
+
+		default:
+			markdcl()                     // for matching popdcl in caseblock
+			stmt := Nod(OXCASE, nil, nil) // don't return nil
+			p.syntax_error("expecting := or = or : or comma")
+			p.advance(LCASE, LDEFAULT, '}')
+			return stmt
+		}
+
+	case LDEFAULT:
+		// LDEFAULT ':'
+		p.next()
+
+		markdcl() // matching popdcl in caseblock
+		stmt := Nod(OXCASE, nil, nil)
+		if tswitch != nil {
+			if n := tswitch.Left; n != nil {
+				// type switch - declare variable
+				nn := newname(n.Sym)
+				declare(nn, dclcontext)
+				stmt.Rlist = list1(nn)
+
+				// keep track of the instances for reporting unused
+				nn.Name.Defn = tswitch
+			}
+		}
+
+		p.want(':') // consume ':' after declaring type switch var for correct lineno
+		return stmt
+
+	default:
+		markdcl()                     // matching popdcl in caseblock
+		stmt := Nod(OXCASE, nil, nil) // don't return nil
+		p.syntax_error("expecting case or default or }")
+		p.advance(LCASE, LDEFAULT, '}')
+		return stmt
+	}
+}
+
+// Block         = "{" StatementList "}" .
+// StatementList = { Statement ";" } .
+func (p *parser) compound_stmt(else_clause bool) *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("compound_stmt")()
+	}
+
+	markdcl()
+	if p.got('{') {
+		// ok
+	} else if else_clause {
+		p.syntax_error("else must be followed by if or statement block")
+		p.advance(LNAME, '}')
+	} else {
+		panic("unreachable")
+	}
+
+	l := p.stmt_list()
+	p.want('}')
+
+	var stmt *Node
+	if l == nil {
+		stmt = Nod(OEMPTY, nil, nil)
+	} else {
+		stmt = liststmt(l)
+	}
+	popdcl()
+
+	return stmt
+}
+
+// caseblock parses a superset of switch and select clauses.
+//
+// ExprCaseClause = ExprSwitchCase ":" StatementList .
+// TypeCaseClause = TypeSwitchCase ":" StatementList .
+// CommClause     = CommCase ":" StatementList .
+func (p *parser) caseblock(tswitch *Node) *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("caseblock")()
+	}
+
+	stmt := p.case_(tswitch) // does markdcl
+	stmt.Xoffset = int64(block)
+	stmt.Nbody = p.stmt_list()
+
+	popdcl()
+
+	return stmt
+}
+
+// caseblock_list parses a superset of switch and select clause lists.
+func (p *parser) caseblock_list(tswitch *Node) (l *NodeList) {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("caseblock_list")()
+	}
+
+	if !p.got('{') {
+		p.syntax_error("missing { after switch clause")
+		p.advance(LCASE, LDEFAULT, '}')
+	}
+
+	for p.tok != EOF && p.tok != '}' {
+		l = list(l, p.caseblock(tswitch))
+	}
+	p.want('}')
+	return
+}
+
+// loop_body parses if and for statement bodies.
+func (p *parser) loop_body(context string) *NodeList {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("loop_body")()
+	}
+
+	markdcl()
+	if !p.got('{') {
+		p.syntax_error("missing { after " + context)
+		p.advance(LNAME, '}')
+	}
+
+	body := p.stmt_list()
+	popdcl()
+	p.want('}')
+
+	return body
+}
+
+// for_header parses the header portion of a for statement.
+//
+// ForStmt   = "for" [ Condition | ForClause | RangeClause ] Block .
+// Condition = Expression .
+func (p *parser) for_header() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("for_header")()
+	}
+
+	init, cond, post := p.header(true)
+
+	if init != nil || post != nil {
+		// init ; test ; incr
+		if post != nil && post.Colas {
+			Yyerror("cannot declare in the for-increment")
+		}
+		h := Nod(OFOR, nil, nil)
+		if init != nil {
+			h.Ninit = list1(init)
+		}
+		h.Left = cond
+		h.Right = post
+		return h
+	}
+
+	if cond != nil && cond.Op == ORANGE {
+		// range_stmt - handled by pexpr
+		return cond
+	}
+
+	// normal test
+	h := Nod(OFOR, nil, nil)
+	h.Left = cond
+	return h
+}
+
+func (p *parser) for_body() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("for_body")()
+	}
+
+	stmt := p.for_header()
+	body := p.loop_body("for clause")
+
+	stmt.Nbody = concat(stmt.Nbody, body)
+	return stmt
+}
+
+// ForStmt = "for" [ Condition | ForClause | RangeClause ] Block .
+func (p *parser) for_stmt() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("for_stmt")()
+	}
+
+	p.want(LFOR)
+	markdcl()
+	body := p.for_body()
+	popdcl()
+
+	return body
+}
+
+// header parses a combination of if, switch, and for statement headers:
+//
+// Header   = [ InitStmt ";" ] [ Expression ] .
+// Header   = [ InitStmt ] ";" [ Condition ] ";" [ PostStmt ] .  // for_stmt only
+// InitStmt = SimpleStmt .
+// PostStmt = SimpleStmt .
+func (p *parser) header(for_stmt bool) (init, cond, post *Node) {
+	if p.tok == '{' {
+		return
+	}
+
+	outer := p.xnest
+	p.xnest = -1
+
+	if p.tok != ';' {
+		// accept potential vardcl but complain
+		// (for test/syntax/forvar.go)
+		if for_stmt && p.tok == LVAR {
+			Yyerror("var declaration not allowed in for initializer")
+			p.next()
+		}
+		init = p.simple_stmt(false, for_stmt)
+		// If we have a range clause, we are done.
+		if for_stmt && init.Op == ORANGE {
+			cond = init
+			init = nil
+
+			p.xnest = outer
+			return
+		}
+	}
+	if p.got(';') {
+		if for_stmt {
+			if p.tok != ';' {
+				cond = p.simple_stmt(false, false)
+			}
+			p.want(';')
+			if p.tok != '{' {
+				post = p.simple_stmt(false, false)
+			}
+		} else if p.tok != '{' {
+			cond = p.simple_stmt(false, false)
+		}
+	} else {
+		cond = init
+		init = nil
+	}
+
+	p.xnest = outer
+	return
+}
+
+func (p *parser) if_header() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("if_header")()
+	}
+
+	init, cond, _ := p.header(false)
+	h := Nod(OIF, nil, nil)
+	h.Ninit = list1(init)
+	h.Left = cond
+	return h
+}
+
+// IfStmt = "if" [ SimpleStmt ";" ] Expression Block [ "else" ( IfStmt | Block ) ] .
+func (p *parser) if_stmt() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("if_stmt")()
+	}
+
+	p.want(LIF)
+
+	markdcl()
+
+	stmt := p.if_header()
+	if stmt.Left == nil {
+		Yyerror("missing condition in if statement")
+	}
+
+	stmt.Nbody = p.loop_body("if clause")
+
+	l := p.elseif_list_else() // does markdcl
+
+	n := stmt
+	popdcl()
+	for nn := l; nn != nil; nn = nn.Next {
+		if nn.N.Op == OIF {
+			popdcl()
+		}
+		n.Rlist = list1(nn.N)
+		n = nn.N
+	}
+
+	return stmt
+}
+
+func (p *parser) elseif() *NodeList {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("elseif")()
+	}
+
+	// LELSE LIF already consumed
+	markdcl() // matching popdcl in if_stmt
+
+	stmt := p.if_header()
+	if stmt.Left == nil {
+		Yyerror("missing condition in if statement")
+	}
+
+	stmt.Nbody = p.loop_body("if clause")
+
+	return list1(stmt)
+}
+
+func (p *parser) elseif_list_else() (l *NodeList) {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("elseif_list_else")()
+	}
+
+	for p.got(LELSE) {
+		if p.got(LIF) {
+			l = concat(l, p.elseif())
+		} else {
+			l = concat(l, p.else_())
+			break
+		}
+	}
+
+	return l
+}
+
+func (p *parser) else_() *NodeList {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("else")()
+	}
+
+	l := &NodeList{N: p.compound_stmt(true)}
+	l.End = l
+	return l
+
+}
+
+// switch_stmt parses both expression and type switch statements.
+//
+// SwitchStmt     = ExprSwitchStmt | TypeSwitchStmt .
+// ExprSwitchStmt = "switch" [ SimpleStmt ";" ] [ Expression ] "{" { ExprCaseClause } "}" .
+// TypeSwitchStmt = "switch" [ SimpleStmt ";" ] TypeSwitchGuard "{" { TypeCaseClause } "}" .
+func (p *parser) switch_stmt() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("switch_stmt")()
+	}
+
+	p.want(LSWITCH)
+	markdcl()
+
+	hdr := p.if_header()
+	hdr.Op = OSWITCH
+
+	tswitch := hdr.Left
+	if tswitch != nil && tswitch.Op != OTYPESW {
+		tswitch = nil
+	}
+
+	hdr.List = p.caseblock_list(tswitch)
+	popdcl()
+
+	return hdr
+}
+
+// SelectStmt = "select" "{" { CommClause } "}" .
+func (p *parser) select_stmt() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("select_stmt")()
+	}
+
+	p.want(LSELECT)
+	hdr := Nod(OSELECT, nil, nil)
+	hdr.List = p.caseblock_list(nil)
+	return hdr
+}
+
+// TODO(gri) should have lexer return this info - no need for separate lookup
+// (issue 13244)
+var prectab = map[int32]struct {
+	prec int // > 0 (0 indicates not found)
+	op   Op
+}{
+	// not an expression anymore, but left in so we can give a good error
+	// message when used in expression context
+	LCOMM: {1, OSEND},
+
+	LOROR: {2, OOROR},
+
+	LANDAND: {3, OANDAND},
+
+	LEQ: {4, OEQ},
+	LNE: {4, ONE},
+	LLE: {4, OLE},
+	LGE: {4, OGE},
+	LLT: {4, OLT},
+	LGT: {4, OGT},
+
+	'+': {5, OADD},
+	'-': {5, OSUB},
+	'|': {5, OOR},
+	'^': {5, OXOR},
+
+	'*':     {6, OMUL},
+	'/':     {6, ODIV},
+	'%':     {6, OMOD},
+	'&':     {6, OAND},
+	LLSH:    {6, OLSH},
+	LRSH:    {6, ORSH},
+	LANDNOT: {6, OANDNOT},
+}
+
+// Expression = UnaryExpr | Expression binary_op Expression .
+func (p *parser) bexpr(prec int) *Node {
+	// don't trace bexpr - only leads to overly nested trace output
+
+	x := p.uexpr()
+	t := prectab[p.tok]
+	for tprec := t.prec; tprec >= prec; tprec-- {
+		for tprec == prec {
+			p.next()
+			y := p.bexpr(t.prec + 1)
+			x = Nod(t.op, x, y)
+			t = prectab[p.tok]
+			tprec = t.prec
+		}
+	}
+	return x
+}
+
+func (p *parser) expr() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("expr")()
+	}
+
+	return p.bexpr(1)
+}
+
+func unparen(x *Node) *Node {
+	for x.Op == OPAREN {
+		x = x.Left
+	}
+	return x
+}
+
+// UnaryExpr = PrimaryExpr | unary_op UnaryExpr .
+func (p *parser) uexpr() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("uexpr")()
+	}
+
+	var op Op
+	switch p.tok {
+	case '*':
+		op = OIND
+
+	case '&':
+		p.next()
+		// uexpr may have returned a parenthesized composite literal
+		// (see comment in operand) - remove parentheses if any
+		x := unparen(p.uexpr())
+		if x.Op == OCOMPLIT {
+			// Special case for &T{...}: turn into (*T){...}.
+			x.Right = Nod(OIND, x.Right, nil)
+			x.Right.Implicit = true
+		} else {
+			x = Nod(OADDR, x, nil)
+		}
+		return x
+
+	case '+':
+		op = OPLUS
+
+	case '-':
+		op = OMINUS
+
+	case '!':
+		op = ONOT
+
+	case '~':
+		// TODO(gri) do this in the lexer instead (issue 13244)
+		p.next()
+		x := p.uexpr()
+		Yyerror("the bitwise complement operator is ^")
+		return Nod(OCOM, x, nil)
+
+	case '^':
+		op = OCOM
+
+	case LCOMM:
+		// receive op (<-x) or receive-only channel (<-chan E)
+		p.next()
+
+		// If the next token is LCHAN we still don't know if it is
+		// a channel (<-chan int) or a receive op (<-chan int(ch)).
+		// We only know once we have found the end of the uexpr.
+
+		x := p.uexpr()
+
+		// There are two cases:
+		//
+		//   <-chan...  => <-x is a channel type
+		//   <-x        => <-x is a receive operation
+		//
+		// In the first case, <- must be re-associated with
+		// the channel type parsed already:
+		//
+		//   <-(chan E)   =>  (<-chan E)
+		//   <-(chan<-E)  =>  (<-chan (<-E))
+
+		if x.Op == OTCHAN {
+			// x is a channel type => re-associate <-
+			dir := EType(Csend)
+			t := x
+			for ; t.Op == OTCHAN && dir == Csend; t = t.Left {
+				dir = t.Etype
+				if dir == Crecv {
+					// t is type <-chan E but <-<-chan E is not permitted
+					// (report same error as for "type _ <-<-chan E")
+					p.syntax_error("unexpected <-, expecting chan")
+					// already progressed, no need to advance
+				}
+				t.Etype = Crecv
+			}
+			if dir == Csend {
+				// channel dir is <- but channel element E is not a channel
+				// (report same error as for "type _ <-chan<-E")
+				p.syntax_error(fmt.Sprintf("unexpected %v, expecting chan", t))
+				// already progressed, no need to advance
+			}
+			return x
+		}
+
+		// x is not a channel type => we have a receive op
+		return Nod(ORECV, x, nil)
+
+	default:
+		return p.pexpr(false)
+	}
+
+	// simple uexpr
+	p.next()
+	return Nod(op, p.uexpr(), nil)
+}
+
+// pseudocall parses call-like statements that can be preceded by 'defer' and 'go'.
+func (p *parser) pseudocall() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("pseudocall")()
+	}
+
+	x := p.pexpr(p.tok == '(') // keep_parens so we can report error below
+	switch x.Op {
+	case OCALL:
+		return x
+	case OPAREN:
+		Yyerror("expression in go/defer must not be parenthesized")
+		// already progressed, no need to advance
+	default:
+		Yyerror("expression in go/defer must be function call")
+		// already progressed, no need to advance
+	}
+	return nil
+}
+
+// Operand     = Literal | OperandName | MethodExpr | "(" Expression ")" .
+// Literal     = BasicLit | CompositeLit | FunctionLit .
+// BasicLit    = int_lit | float_lit | imaginary_lit | rune_lit | string_lit .
+// OperandName = identifier | QualifiedIdent.
+func (p *parser) operand(keep_parens bool) *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("operand")()
+	}
+
+	switch p.tok {
+	case LLITERAL:
+		x := nodlit(p.val)
+		p.next()
+		return x
+
+	case LNAME, '@', '?':
+		return p.name()
+
+	case '(':
+		p.next()
+		p.xnest++
+		x := p.expr() // expr_or_type
+		p.xnest--
+		p.want(')')
+
+		// Optimization: Record presence of ()'s only where needed
+		// for error reporting. Don't bother in other cases; it is
+		// just a waste of memory and time.
+
+		// Parentheses are not permitted on lhs of := .
+		switch x.Op {
+		case ONAME, ONONAME, OPACK, OTYPE, OLITERAL, OTYPESW:
+			keep_parens = true
+		}
+
+		// Parentheses are not permitted around T in a composite
+		// literal T{}. If the next token is a {, assume x is a
+		// composite literal type T (it may not be, { could be
+		// the opening brace of a block, but we don't know yet).
+		if p.tok == '{' {
+			keep_parens = true
+		}
+
+		// Parentheses are also not permitted around the expression
+		// in a go/defer statement. In that case, operand is called
+		// with keep_parens set.
+		if keep_parens {
+			x = Nod(OPAREN, x, nil)
+		}
+		return x
+
+	case LFUNC:
+		t := p.ntype() // fntype
+		if p.tok == '{' {
+			// fnlitdcl
+			closurehdr(t)
+			// fnliteral
+			p.next() // consume '{'
+			p.fnest++
+			p.xnest++
+			body := p.stmt_list()
+			p.xnest--
+			p.fnest--
+			p.want('}')
+			return closurebody(body)
+		}
+		return t
+
+	case '[', LCHAN, LMAP, LSTRUCT, LINTERFACE:
+		return p.ntype() // othertype
+
+	case '{':
+		// common case: p.header is missing simple_stmt before { in if, for, switch
+		p.syntax_error("missing operand")
+		// '{' will be consumed in pexpr - no need to consume it here
+		return nil
+
+	default:
+		p.syntax_error("expecting expression")
+		p.advance()
+		return nil
+	}
+
+	// Syntactically, composite literals are operands. Because a complit
+	// type may be a qualified identifier which is handled by pexpr
+	// (together with selector expressions), complits are parsed there
+	// as well (operand is only called from pexpr).
+}
+
+// PrimaryExpr =
+// 	Operand |
+// 	Conversion |
+// 	PrimaryExpr Selector |
+// 	PrimaryExpr Index |
+// 	PrimaryExpr Slice |
+// 	PrimaryExpr TypeAssertion |
+// 	PrimaryExpr Arguments .
+//
+// Selector       = "." identifier .
+// Index          = "[" Expression "]" .
+// Slice          = "[" ( [ Expression ] ":" [ Expression ] ) |
+//                      ( [ Expression ] ":" Expression ":" Expression )
+//                  "]" .
+// TypeAssertion  = "." "(" Type ")" .
+// Arguments      = "(" [ ( ExpressionList | Type [ "," ExpressionList ] ) [ "..." ] [ "," ] ] ")" .
+func (p *parser) pexpr(keep_parens bool) *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("pexpr")()
+	}
+
+	x := p.operand(keep_parens)
+
+loop:
+	for {
+		switch p.tok {
+		case '.':
+			p.next()
+			switch p.tok {
+			case LNAME, '@', '?':
+				// pexpr '.' sym
+				x = p.new_dotname(x)
+
+			case '(':
+				p.next()
+				switch p.tok {
+				default:
+					// pexpr '.' '(' expr_or_type ')'
+					t := p.expr() // expr_or_type
+					p.want(')')
+					x = Nod(ODOTTYPE, x, t)
+
+				case LTYPE:
+					// pexpr '.' '(' LTYPE ')'
+					p.next()
+					p.want(')')
+					x = Nod(OTYPESW, nil, x)
+				}
+
+			default:
+				p.syntax_error("expecting name or (")
+				p.advance(';', '}')
+			}
+
+		case '[':
+			p.next()
+			p.xnest++
+			var index [3]*Node
+			if p.tok != ':' {
+				index[0] = p.expr()
+			}
+			ncol := 0
+			for ncol < len(index)-1 && p.got(':') {
+				ncol++
+				if p.tok != EOF && p.tok != ':' && p.tok != ']' {
+					index[ncol] = p.expr()
+				}
+			}
+			p.xnest--
+			p.want(']')
+
+			switch ncol {
+			case 0:
+				i := index[0]
+				if i == nil {
+					Yyerror("missing index in index expression")
+				}
+				x = Nod(OINDEX, x, i)
+			case 1:
+				i := index[0]
+				j := index[1]
+				x = Nod(OSLICE, x, Nod(OKEY, i, j))
+			case 2:
+				i := index[0]
+				j := index[1]
+				k := index[2]
+				if j == nil {
+					Yyerror("middle index required in 3-index slice")
+				}
+				if k == nil {
+					Yyerror("final index required in 3-index slice")
+				}
+				x = Nod(OSLICE3, x, Nod(OKEY, i, Nod(OKEY, j, k)))
+
+			default:
+				panic("unreachable")
+			}
+
+		case '(':
+			// convtype '(' expr ocomma ')'
+			args, ddd := p.arg_list()
+
+			// call or conversion
+			x = Nod(OCALL, x, nil)
+			x.List = args
+			x.Isddd = ddd
+
+		case '{':
+			// operand may have returned a parenthesized complit
+			// type; accept it but complain if we have a complit
+			t := unparen(x)
+			// determine if '{' belongs to a complit or a compound_stmt
+			complit_ok := false
+			switch t.Op {
+			case ONAME, ONONAME, OTYPE, OPACK, OXDOT, ODOT:
+				if p.xnest >= 0 {
+					// x is considered a comptype
+					complit_ok = true
+				}
+			case OTARRAY, OTSTRUCT, OTMAP:
+				// x is a comptype
+				complit_ok = true
+			}
+			if !complit_ok {
+				break loop
+			}
+			if t != x {
+				p.syntax_error("cannot parenthesize type in composite literal")
+				// already progressed, no need to advance
+			}
+			n := p.complitexpr()
+			n.Right = x
+			x = n
+
+		default:
+			break loop
+		}
+	}
+
+	return x
+}
+
+// KeyedElement = [ Key ":" ] Element .
+func (p *parser) keyval() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("keyval")()
+	}
+
+	// A composite literal commonly spans several lines,
+	// so the line number on errors may be misleading.
+	// Wrap values (but not keys!) that don't carry line
+	// numbers.
+
+	x := p.bare_complitexpr()
+
+	if p.got(':') {
+		// key ':' value
+		return Nod(OKEY, x, wrapname(p.bare_complitexpr()))
+	}
+
+	// value
+	return wrapname(x)
+}
+
+func wrapname(x *Node) *Node {
+	// These nodes do not carry line numbers.
+	// Introduce a wrapper node to give the correct line.
+	switch x.Op {
+	case ONAME, ONONAME, OTYPE, OPACK, OLITERAL:
+		x = Nod(OPAREN, x, nil)
+		x.Implicit = true
+	}
+	return x
+}
+
+// Element = Expression | LiteralValue .
+func (p *parser) bare_complitexpr() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("bare_complitexpr")()
+	}
+
+	if p.tok == '{' {
+		// '{' start_complit braced_keyval_list '}'
+		return p.complitexpr()
+	}
+
+	return p.expr()
+}
+
+// LiteralValue = "{" [ ElementList [ "," ] ] "}" .
+func (p *parser) complitexpr() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("complitexpr")()
+	}
+
+	// make node early so we get the right line number
+	n := Nod(OCOMPLIT, nil, nil)
+
+	p.want('{')
+	p.xnest++
+
+	var l *NodeList
+	for p.tok != EOF && p.tok != '}' {
+		l = list(l, p.keyval())
+		if !p.ocomma('}') {
+			break
+		}
+	}
+
+	p.xnest--
+	p.want('}')
+
+	n.List = l
+	return n
+}
+
+// names and types
+//	newname is used before declared
+//	oldname is used after declared
+func (p *parser) new_name(sym *Sym) *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("new_name")()
+	}
+
+	if sym != nil {
+		return newname(sym)
+	}
+	return nil
+}
+
+func (p *parser) dcl_name(sym *Sym) *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("dcl_name")()
+	}
+
+	if sym == nil {
+		yyerrorl(int(prevlineno), "invalid declaration")
+		return nil
+	}
+	return dclname(sym)
+}
+
+func (p *parser) onew_name() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("onew_name")()
+	}
+
+	switch p.tok {
+	case LNAME, '@', '?':
+		return p.new_name(p.sym())
+	}
+	return nil
+}
+
+func (p *parser) sym() *Sym {
+	switch p.tok {
+	case LNAME:
+		s := p.sym_
+		p.next()
+		// during imports, unqualified non-exported identifiers are from builtinpkg
+		if importpkg != nil && !exportname(s.Name) {
+			s = Pkglookup(s.Name, builtinpkg)
+		}
+		return s
+
+	case '@':
+		return p.hidden_importsym()
+
+	case '?':
+		p.next()
+		return nil
+
+	default:
+		p.syntax_error("expecting name")
+		p.advance()
+		return new(Sym)
+	}
+}
+
+func mkname(sym *Sym) *Node {
+	n := oldname(sym)
+	if n.Name != nil && n.Name.Pack != nil {
+		n.Name.Pack.Used = true
+	}
+	return n
+}
+
+func (p *parser) name() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("name")()
+	}
+
+	return mkname(p.sym())
+}
+
+// [ "..." ] Type
+func (p *parser) dotdotdot() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("dotdotdot")()
+	}
+
+	p.want(LDDD)
+	if typ := p.try_ntype(); typ != nil {
+		return Nod(ODDD, typ, nil)
+	}
+
+	Yyerror("final argument in variadic function missing type")
+	return Nod(ODDD, typenod(typ(TINTER)), nil)
+}
+
+func (p *parser) ntype() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("ntype")()
+	}
+
+	if typ := p.try_ntype(); typ != nil {
+		return typ
+	}
+
+	p.syntax_error("")
+	p.advance()
+	return nil
+}
+
+// try_ntype is like ntype but it returns nil if there was no type
+// instead of reporting an error.
+//
+// Type     = TypeName | TypeLit | "(" Type ")" .
+// TypeName = identifier | QualifiedIdent .
+// TypeLit  = ArrayType | StructType | PointerType | FunctionType | InterfaceType |
+// 	      SliceType | MapType | ChannelType .
+func (p *parser) try_ntype() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("try_ntype")()
+	}
+
+	switch p.tok {
+	case LCOMM:
+		// recvchantype
+		p.next()
+		p.want(LCHAN)
+		t := Nod(OTCHAN, p.chan_elem(), nil)
+		t.Etype = Crecv
+		return t
+
+	case LFUNC:
+		// fntype
+		p.next()
+		params := p.param_list()
+		result := p.fnres()
+		params = checkarglist(params, 1)
+		t := Nod(OTFUNC, nil, nil)
+		t.List = params
+		t.Rlist = result
+		return t
+
+	case '[':
+		// '[' oexpr ']' ntype
+		// '[' LDDD ']' ntype
+		p.next()
+		p.xnest++
+		var len *Node
+		if p.tok != ']' {
+			if p.got(LDDD) {
+				len = Nod(ODDD, nil, nil)
+			} else {
+				len = p.expr()
+			}
+		}
+		p.xnest--
+		p.want(']')
+		return Nod(OTARRAY, len, p.ntype())
+
+	case LCHAN:
+		// LCHAN non_recvchantype
+		// LCHAN LCOMM ntype
+		p.next()
+		var dir EType = Cboth
+		if p.got(LCOMM) {
+			dir = Csend
+		}
+		t := Nod(OTCHAN, p.chan_elem(), nil)
+		t.Etype = dir
+		return t
+
+	case LMAP:
+		// LMAP '[' ntype ']' ntype
+		p.next()
+		p.want('[')
+		key := p.ntype()
+		p.want(']')
+		val := p.ntype()
+		return Nod(OTMAP, key, val)
+
+	case LSTRUCT:
+		return p.structtype()
+
+	case LINTERFACE:
+		return p.interfacetype()
+
+	case '*':
+		// ptrtype
+		p.next()
+		return Nod(OIND, p.ntype(), nil)
+
+	case LNAME, '@', '?':
+		return p.dotname()
+
+	case '(':
+		p.next()
+		t := p.ntype()
+		p.want(')')
+		return t
+
+	default:
+		return nil
+	}
+}
+
+func (p *parser) chan_elem() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("chan_elem")()
+	}
+
+	if typ := p.try_ntype(); typ != nil {
+		return typ
+	}
+
+	p.syntax_error("missing channel element type")
+	// assume element type is simply absent - don't advance
+	return nil
+}
+
+func (p *parser) new_dotname(pkg *Node) *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("new_dotname")()
+	}
+
+	sel := p.sym()
+	if pkg.Op == OPACK {
+		s := restrictlookup(sel.Name, pkg.Name.Pkg)
+		pkg.Used = true
+		return oldname(s)
+	}
+	return Nod(OXDOT, pkg, newname(sel))
+
+}
+
+func (p *parser) dotname() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("dotname")()
+	}
+
+	name := p.name()
+	if p.got('.') {
+		return p.new_dotname(name)
+	}
+	return name
+}
+
+// StructType = "struct" "{" { FieldDecl ";" } "}" .
+func (p *parser) structtype() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("structtype")()
+	}
+
+	p.want(LSTRUCT)
+	p.want('{')
+	var l *NodeList
+	for p.tok != EOF && p.tok != '}' {
+		l = concat(l, p.structdcl())
+		if !p.osemi('}') {
+			break
+		}
+	}
+	p.want('}')
+
+	t := Nod(OTSTRUCT, nil, nil)
+	t.List = l
+	return t
+}
+
+// InterfaceType = "interface" "{" { MethodSpec ";" } "}" .
+func (p *parser) interfacetype() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("interfacetype")()
+	}
+
+	p.want(LINTERFACE)
+	p.want('{')
+	var l *NodeList
+	for p.tok != EOF && p.tok != '}' {
+		l = list(l, p.interfacedcl())
+		if !p.osemi('}') {
+			break
+		}
+	}
+	p.want('}')
+
+	t := Nod(OTINTER, nil, nil)
+	t.List = l
+	return t
+}
+
+// Function stuff.
+// All in one place to show how crappy it all is.
+
+func (p *parser) xfndcl() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("xfndcl")()
+	}
+
+	p.want(LFUNC)
+	f := p.fndcl()
+	body := p.fnbody()
+
+	if f == nil {
+		return nil
+	}
+	if noescape && body != nil {
+		Yyerror("can only use //go:noescape with external func implementations")
+	}
+
+	f.Nbody = body
+	f.Func.Endlineno = lineno
+	f.Noescape = noescape
+	f.Func.Norace = norace
+	f.Func.Nosplit = nosplit
+	f.Func.Noinline = noinline
+	f.Func.Nowritebarrier = nowritebarrier
+	f.Func.Nowritebarrierrec = nowritebarrierrec
+	f.Func.Systemstack = systemstack
+	funcbody(f)
+
+	return f
+}
+
+// FunctionDecl = "func" FunctionName ( Function | Signature ) .
+// FunctionName = identifier .
+// Function     = Signature FunctionBody .
+// MethodDecl   = "func" Receiver MethodName ( Function | Signature ) .
+// Receiver     = Parameters .
+func (p *parser) fndcl() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("fndcl")()
+	}
+
+	switch p.tok {
+	case LNAME, '@', '?':
+		// sym '(' oarg_type_list_ocomma ')' fnres
+		name := p.sym()
+		params := p.param_list()
+		result := p.fnres()
+
+		params = checkarglist(params, 1)
+
+		if name.Name == "init" {
+			name = renameinit()
+			if params != nil || result != nil {
+				Yyerror("func init must have no arguments and no return values")
+			}
+		}
+
+		if localpkg.Name == "main" && name.Name == "main" {
+			if params != nil || result != nil {
+				Yyerror("func main must have no arguments and no return values")
+			}
+		}
+
+		t := Nod(OTFUNC, nil, nil)
+		t.List = params
+		t.Rlist = result
+
+		f := Nod(ODCLFUNC, nil, nil)
+		f.Func.Nname = newfuncname(name)
+		f.Func.Nname.Name.Defn = f
+		f.Func.Nname.Name.Param.Ntype = t // TODO: check if nname already has an ntype
+		declare(f.Func.Nname, PFUNC)
+
+		funchdr(f)
+		return f
+
+	case '(':
+		// '(' oarg_type_list_ocomma ')' sym '(' oarg_type_list_ocomma ')' fnres
+		rparam := p.param_list()
+		name := p.sym()
+		params := p.param_list()
+		result := p.fnres()
+
+		rparam = checkarglist(rparam, 0)
+		params = checkarglist(params, 1)
+
+		if rparam == nil {
+			Yyerror("method has no receiver")
+			return nil
+		}
+
+		if rparam.Next != nil {
+			Yyerror("method has multiple receivers")
+			return nil
+		}
+
+		rcvr := rparam.N
+		if rcvr.Op != ODCLFIELD {
+			Yyerror("bad receiver in method")
+			return nil
+		}
+
+		t := Nod(OTFUNC, rcvr, nil)
+		t.List = params
+		t.Rlist = result
+
+		f := Nod(ODCLFUNC, nil, nil)
+		f.Func.Shortname = newfuncname(name)
+		f.Func.Nname = methodname1(f.Func.Shortname, rcvr.Right)
+		f.Func.Nname.Name.Defn = f
+		f.Func.Nname.Name.Param.Ntype = t
+		f.Func.Nname.Nointerface = nointerface
+		declare(f.Func.Nname, PFUNC)
+
+		funchdr(f)
+		return f
+
+	default:
+		p.syntax_error("expecting name or (")
+		p.advance('{', ';')
+		return nil
+	}
+}
+
+func (p *parser) hidden_fndcl() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("hidden_fndcl")()
+	}
+
+	switch p.tok {
+	default:
+		// hidden_pkg_importsym '(' ohidden_funarg_list ')' ohidden_funres
+		s1 := p.hidden_pkg_importsym()
+		p.want('(')
+		s3 := p.ohidden_funarg_list()
+		p.want(')')
+		s5 := p.ohidden_funres()
+
+		s := s1
+		t := functype(nil, s3, s5)
+
+		importsym(s, ONAME)
+		if s.Def != nil && s.Def.Op == ONAME {
+			if Eqtype(t, s.Def.Type) {
+				dclcontext = PDISCARD // since we skip funchdr below
+				return nil
+			}
+			Yyerror("inconsistent definition for func %v during import\n\t%v\n\t%v", s, s.Def.Type, t)
+		}
+
+		ss := newfuncname(s)
+		ss.Type = t
+		declare(ss, PFUNC)
+
+		funchdr(ss)
+		return ss
+
+	case '(':
+		// '(' hidden_funarg_list ')' sym '(' ohidden_funarg_list ')' ohidden_funres
+		p.next()
+		s2 := p.hidden_funarg_list()
+		p.want(')')
+		s4 := p.sym()
+		p.want('(')
+		s6 := p.ohidden_funarg_list()
+		p.want(')')
+		s8 := p.ohidden_funres()
+
+		ss := methodname1(newname(s4), s2.N.Right)
+		ss.Type = functype(s2.N, s6, s8)
+
+		checkwidth(ss.Type)
+		addmethod(s4, ss.Type, false, nointerface)
+		nointerface = false
+		funchdr(ss)
+
+		// inl.C's inlnode in on a dotmeth node expects to find the inlineable body as
+		// (dotmeth's type).Nname.Inl, and dotmeth's type has been pulled
+		// out by typecheck's lookdot as this $$.ttype.  So by providing
+		// this back link here we avoid special casing there.
+		ss.Type.Nname = ss
+		return ss
+	}
+}
+
+// FunctionBody = Block .
+func (p *parser) fnbody() *NodeList {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("fnbody")()
+	}
+
+	if p.got('{') {
+		p.fnest++
+		body := p.stmt_list()
+		p.fnest--
+		p.want('}')
+		if body == nil {
+			body = list1(Nod(OEMPTY, nil, nil))
+		}
+		return body
+	}
+
+	return nil
+}
+
+// Result = Parameters | Type .
+func (p *parser) fnres() *NodeList {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("fnres")()
+	}
+
+	if p.tok == '(' {
+		result := p.param_list()
+		return checkarglist(result, 0)
+	}
+
+	if result := p.try_ntype(); result != nil {
+		return list1(Nod(ODCLFIELD, nil, result))
+	}
+
+	return nil
+}
+
+// Declaration  = ConstDecl | TypeDecl | VarDecl .
+// TopLevelDecl = Declaration | FunctionDecl | MethodDecl .
+func (p *parser) xdcl_list() (l *NodeList) {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("xdcl_list")()
+	}
+
+loop:
+	for p.tok != EOF {
+		switch p.tok {
+		case LVAR, LCONST, LTYPE:
+			l = concat(l, p.common_dcl())
+
+		case LFUNC:
+			l = list(l, p.xfndcl())
+
+		default:
+			if p.tok == '{' && l != nil && l.End.N.Op == ODCLFUNC && l.End.N.Nbody == nil {
+				// opening { of function declaration on next line
+				p.syntax_error("unexpected semicolon or newline before {")
+			} else {
+				p.syntax_error("non-declaration statement outside function body")
+			}
+			p.advance(LVAR, LCONST, LTYPE, LFUNC)
+			goto loop
+		}
+
+		if nsyntaxerrors == 0 {
+			testdclstack()
+		}
+
+		noescape = false
+		noinline = false
+		nointerface = false
+		norace = false
+		nosplit = false
+		nowritebarrier = false
+		nowritebarrierrec = false
+		systemstack = false
+
+		// Consume ';' AFTER resetting the above flags since
+		// it may read the subsequent comment line which may
+		// set the flags for the next function declaration.
+		if p.tok != EOF && !p.got(';') {
+			p.syntax_error("after top level declaration")
+			p.advance(LVAR, LCONST, LTYPE, LFUNC)
+			goto loop
+		}
+	}
+	return
+}
+
+// FieldDecl      = (IdentifierList Type | AnonymousField) [ Tag ] .
+// AnonymousField = [ "*" ] TypeName .
+// Tag            = string_lit .
+func (p *parser) structdcl() *NodeList {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("structdcl")()
+	}
+
+	var sym *Sym
+	switch p.tok {
+	case LNAME:
+		sym = p.sym_
+		p.next()
+		if sym == nil {
+			panic("unreachable") // we must have a sym for LNAME
+		}
+		if p.tok == '.' || p.tok == LLITERAL || p.tok == ';' || p.tok == '}' {
+			// embed oliteral
+			field := p.embed(sym)
+			tag := p.oliteral()
+
+			field.SetVal(tag)
+			return list1(field)
+		}
+
+		// LNAME belongs to first *Sym of new_name_list
+		//
+		// during imports, unqualified non-exported identifiers are from builtinpkg
+		if importpkg != nil && !exportname(sym.Name) {
+			sym = Pkglookup(sym.Name, builtinpkg)
+			if sym == nil {
+				p.import_error()
+			}
+		}
+		fallthrough
+
+	case '@', '?':
+		// new_name_list ntype oliteral
+		fields := p.new_name_list(sym)
+		typ := p.ntype()
+		tag := p.oliteral()
+
+		if l := fields; l == nil || l.N.Sym.Name == "?" {
+			// ? symbol, during import (list1(nil) == nil)
+			n := typ
+			if n.Op == OIND {
+				n = n.Left
+			}
+			n = embedded(n.Sym, importpkg)
+			n.Right = typ
+			n.SetVal(tag)
+			return list1(n)
+		}
+
+		for l := fields; l != nil; l = l.Next {
+			l.N = Nod(ODCLFIELD, l.N, typ)
+			l.N.SetVal(tag)
+		}
+		return fields
+
+	case '(':
+		p.next()
+		if p.got('*') {
+			// '(' '*' embed ')' oliteral
+			field := p.embed(nil)
+			p.want(')')
+			tag := p.oliteral()
+
+			field.Right = Nod(OIND, field.Right, nil)
+			field.SetVal(tag)
+			Yyerror("cannot parenthesize embedded type")
+			return list1(field)
+
+		} else {
+			// '(' embed ')' oliteral
+			field := p.embed(nil)
+			p.want(')')
+			tag := p.oliteral()
+
+			field.SetVal(tag)
+			Yyerror("cannot parenthesize embedded type")
+			return list1(field)
+		}
+
+	case '*':
+		p.next()
+		if p.got('(') {
+			// '*' '(' embed ')' oliteral
+			field := p.embed(nil)
+			p.want(')')
+			tag := p.oliteral()
+
+			field.Right = Nod(OIND, field.Right, nil)
+			field.SetVal(tag)
+			Yyerror("cannot parenthesize embedded type")
+			return list1(field)
+
+		} else {
+			// '*' embed oliteral
+			field := p.embed(nil)
+			tag := p.oliteral()
+
+			field.Right = Nod(OIND, field.Right, nil)
+			field.SetVal(tag)
+			return list1(field)
+		}
+
+	default:
+		p.syntax_error("expecting field name or embedded type")
+		p.advance(';', '}')
+		return nil
+	}
+}
+
+func (p *parser) oliteral() (v Val) {
+	if p.tok == LLITERAL {
+		v = p.val
+		p.next()
+	}
+	return
+}
+
+func (p *parser) packname(name *Sym) *Sym {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("embed")()
+	}
+
+	if name != nil {
+		// LNAME was already consumed and is coming in as name
+	} else if p.tok == LNAME {
+		name = p.sym_
+		p.next()
+	} else {
+		p.syntax_error("expecting name")
+		p.advance('.', ';', '}')
+		name = new(Sym)
+	}
+
+	if p.got('.') {
+		// LNAME '.' sym
+		s := p.sym()
+
+		var pkg *Pkg
+		if name.Def == nil || name.Def.Op != OPACK {
+			Yyerror("%v is not a package", name)
+			pkg = localpkg
+		} else {
+			name.Def.Used = true
+			pkg = name.Def.Name.Pkg
+		}
+		return restrictlookup(s.Name, pkg)
+	}
+
+	// LNAME
+	if n := oldname(name); n.Name != nil && n.Name.Pack != nil {
+		n.Name.Pack.Used = true
+	}
+	return name
+}
+
+func (p *parser) embed(sym *Sym) *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("embed")()
+	}
+
+	pkgname := p.packname(sym)
+	return embedded(pkgname, localpkg)
+}
+
+// MethodSpec        = MethodName Signature | InterfaceTypeName .
+// MethodName        = identifier .
+// InterfaceTypeName = TypeName .
+func (p *parser) interfacedcl() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("interfacedcl")()
+	}
+
+	switch p.tok {
+	case LNAME:
+		sym := p.sym_
+		p.next()
+
+		// accept potential name list but complain
+		hasNameList := false
+		for p.got(',') {
+			p.sym()
+			hasNameList = true
+		}
+		if hasNameList {
+			p.syntax_error("name list not allowed in interface type")
+			// already progressed, no need to advance
+		}
+
+		if p.tok != '(' {
+			// packname
+			pname := p.packname(sym)
+			return Nod(ODCLFIELD, nil, oldname(pname))
+		}
+
+		// newname indcl
+		mname := newname(sym)
+		sig := p.indcl()
+
+		meth := Nod(ODCLFIELD, mname, sig)
+		ifacedcl(meth)
+		return meth
+
+	case '@', '?':
+		// newname indcl
+		// We arrive here when parsing an interface type declared inside
+		// an exported and inlineable function and the interface declares
+		// unexported methods (which are then package-qualified).
+		//
+		// Since the compiler always flattens embedded interfaces, we
+		// will never see an embedded package-qualified interface in export
+		// data; i.e., when we reach here we know it must be a method.
+		//
+		// See also issue 14164.
+		mname := newname(p.sym())
+		sig := p.indcl()
+
+		meth := Nod(ODCLFIELD, mname, sig)
+		ifacedcl(meth)
+		return meth
+
+	case '(':
+		p.next()
+		pname := p.packname(nil)
+		p.want(')')
+		n := Nod(ODCLFIELD, nil, oldname(pname))
+		Yyerror("cannot parenthesize embedded type")
+		return n
+
+	default:
+		p.syntax_error("")
+		p.advance(';', '}')
+		return nil
+	}
+}
+
+// MethodSpec = MethodName Signature .
+// MethodName = identifier .
+func (p *parser) indcl() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("indcl")()
+	}
+
+	params := p.param_list()
+	result := p.fnres()
+
+	// without func keyword
+	params = checkarglist(params, 1)
+	t := Nod(OTFUNC, fakethis(), nil)
+	t.List = params
+	t.Rlist = result
+
+	return t
+}
+
+// ParameterDecl = [ IdentifierList ] [ "..." ] Type .
+func (p *parser) arg_type() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("arg_type")()
+	}
+
+	switch p.tok {
+	case LNAME, '@', '?':
+		name := p.sym()
+		switch p.tok {
+		case LCOMM, LFUNC, '[', LCHAN, LMAP, LSTRUCT, LINTERFACE, '*', LNAME, '@', '?', '(':
+			// sym name_or_type
+			typ := p.ntype()
+			nn := Nod(ONONAME, nil, nil)
+			nn.Sym = name
+			return Nod(OKEY, nn, typ)
+
+		case LDDD:
+			// sym dotdotdot
+			typ := p.dotdotdot()
+			nn := Nod(ONONAME, nil, nil)
+			nn.Sym = name
+			return Nod(OKEY, nn, typ)
+
+		default:
+			// name_or_type
+			name := mkname(name)
+			// from dotname
+			if p.got('.') {
+				return p.new_dotname(name)
+			}
+			return name
+		}
+
+	case LDDD:
+		// dotdotdot
+		return p.dotdotdot()
+
+	case LCOMM, LFUNC, '[', LCHAN, LMAP, LSTRUCT, LINTERFACE, '*', '(':
+		// name_or_type
+		return p.ntype()
+
+	default:
+		p.syntax_error("expecting )")
+		p.advance(',', ')')
+		return nil
+	}
+}
+
+// Parameters    = "(" [ ParameterList [ "," ] ] ")" .
+// ParameterList = ParameterDecl { "," ParameterDecl } .
+func (p *parser) param_list() (l *NodeList) {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("param_list")()
+	}
+
+	p.want('(')
+
+	for p.tok != EOF && p.tok != ')' {
+		l = list(l, p.arg_type())
+		if !p.ocomma(')') {
+			break
+		}
+	}
+
+	p.want(')')
+	return
+}
+
+var missing_stmt = Nod(OXXX, nil, nil)
+
+// Statement =
+// 	Declaration | LabeledStmt | SimpleStmt |
+// 	GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt |
+// 	FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt |
+// 	DeferStmt .
+//
+// stmt may return missing_stmt.
+func (p *parser) stmt() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("stmt")()
+	}
+
+	switch p.tok {
+	case '{':
+		return p.compound_stmt(false)
+
+	case LVAR, LCONST, LTYPE:
+		return liststmt(p.common_dcl())
+
+	case LNAME, '@', '?', LLITERAL, LFUNC, '(', // operands
+		'[', LSTRUCT, LMAP, LCHAN, LINTERFACE, // composite types
+		'+', '-', '*', '&', '^', '~', LCOMM, '!': // unary operators
+		return p.simple_stmt(true, false)
+
+	case LFOR:
+		return p.for_stmt()
+
+	case LSWITCH:
+		return p.switch_stmt()
+
+	case LSELECT:
+		return p.select_stmt()
+
+	case LIF:
+		return p.if_stmt()
+
+	case LFALL:
+		p.next()
+		// will be converted to OFALL
+		stmt := Nod(OXFALL, nil, nil)
+		stmt.Xoffset = int64(block)
+		return stmt
+
+	case LBREAK:
+		p.next()
+		return Nod(OBREAK, p.onew_name(), nil)
+
+	case LCONTINUE:
+		p.next()
+		return Nod(OCONTINUE, p.onew_name(), nil)
+
+	case LGO:
+		p.next()
+		return Nod(OPROC, p.pseudocall(), nil)
+
+	case LDEFER:
+		p.next()
+		return Nod(ODEFER, p.pseudocall(), nil)
+
+	case LGOTO:
+		p.next()
+		stmt := Nod(OGOTO, p.new_name(p.sym()), nil)
+		stmt.Sym = dclstack // context, for goto restrictions
+		return stmt
+
+	case LRETURN:
+		p.next()
+		var results *NodeList
+		if p.tok != ';' && p.tok != '}' {
+			results = p.expr_list()
+		}
+
+		stmt := Nod(ORETURN, nil, nil)
+		stmt.List = results
+		if stmt.List == nil && Curfn != nil {
+			for l := Curfn.Func.Dcl; l != nil; l = l.Next {
+				if l.N.Class == PPARAM {
+					continue
+				}
+				if l.N.Class != PPARAMOUT {
+					break
+				}
+				if l.N.Sym.Def != l.N {
+					Yyerror("%s is shadowed during return", l.N.Sym.Name)
+				}
+			}
+		}
+
+		return stmt
+
+	case ';':
+		return nil
+
+	default:
+		return missing_stmt
+	}
+}
+
+// StatementList = { Statement ";" } .
+func (p *parser) stmt_list() (l *NodeList) {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("stmt_list")()
+	}
+
+	for p.tok != EOF && p.tok != '}' && p.tok != LCASE && p.tok != LDEFAULT {
+		s := p.stmt()
+		if s == missing_stmt {
+			break
+		}
+		l = list(l, s)
+		// customized version of osemi:
+		// ';' is optional before a closing ')' or '}'
+		if p.tok == ')' || p.tok == '}' {
+			continue
+		}
+		if !p.got(';') {
+			p.syntax_error("at end of statement")
+			p.advance(';', '}')
+		}
+	}
+	return
+}
+
+// IdentifierList = identifier { "," identifier } .
+//
+// If first != nil we have the first symbol already.
+func (p *parser) new_name_list(first *Sym) *NodeList {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("new_name_list")()
+	}
+
+	if first == nil {
+		first = p.sym() // may still be nil
+	}
+	l := list1(p.new_name(first))
+	for p.got(',') {
+		l = list(l, p.new_name(p.sym()))
+	}
+	return l
+}
+
+// IdentifierList = identifier { "," identifier } .
+func (p *parser) dcl_name_list() *NodeList {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("dcl_name_list")()
+	}
+
+	l := list1(p.dcl_name(p.sym()))
+	for p.got(',') {
+		l = list(l, p.dcl_name(p.sym()))
+	}
+	return l
+}
+
+// ExpressionList = Expression { "," Expression } .
+func (p *parser) expr_list() *NodeList {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("expr_list")()
+	}
+
+	l := list1(p.expr())
+	for p.got(',') {
+		l = list(l, p.expr())
+	}
+	return l
+}
+
+// Arguments = "(" [ ( ExpressionList | Type [ "," ExpressionList ] ) [ "..." ] [ "," ] ] ")" .
+func (p *parser) arg_list() (l *NodeList, ddd bool) {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("arg_list")()
+	}
+
+	p.want('(')
+	p.xnest++
+
+	for p.tok != EOF && p.tok != ')' && !ddd {
+		l = list(l, p.expr()) // expr_or_type
+		ddd = p.got(LDDD)
+		if !p.ocomma(')') {
+			break
+		}
+	}
+
+	p.xnest--
+	p.want(')')
+
+	return
+}
+
+// osemi parses an optional semicolon.
+func (p *parser) osemi(follow int32) bool {
+	switch p.tok {
+	case ';':
+		p.next()
+		return true
+
+	case ')', '}':
+		// semicolon is optional before ) or }
+		return true
+	}
+
+	p.syntax_error("expecting semicolon, newline, or " + tokstring(follow))
+	p.advance(follow)
+	return false
+}
+
+// ocomma parses an optional comma.
+func (p *parser) ocomma(follow int32) bool {
+	switch p.tok {
+	case ',':
+		p.next()
+		return true
+
+	case ')', '}':
+		// comma is optional before ) or }
+		return true
+	}
+
+	p.syntax_error("expecting comma or " + tokstring(follow))
+	p.advance(follow)
+	return false
+}
+
+// ----------------------------------------------------------------------------
+// Importing packages
+
+func (p *parser) import_error() {
+	p.syntax_error("in export data of imported package")
+	p.next()
+}
+
+// The methods below reflect a 1:1 translation of the original (and now defunct)
+// go.y yacc productions. They could be simplified significantly and also use better
+// variable names. However, we will be able to delete them once we enable the
+// new export format by default, so it's not worth the effort (issue 13241).
+
+func (p *parser) hidden_importsym() *Sym {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("hidden_importsym")()
+	}
+
+	p.want('@')
+	var s2 Val
+	if p.tok == LLITERAL {
+		s2 = p.val
+		p.next()
+	} else {
+		p.import_error()
+	}
+	p.want('.')
+
+	switch p.tok {
+	case LNAME:
+		s4 := p.sym_
+		p.next()
+
+		var p *Pkg
+
+		if s2.U.(string) == "" {
+			p = importpkg
+		} else {
+			if isbadimport(s2.U.(string)) {
+				errorexit()
+			}
+			p = mkpkg(s2.U.(string))
+		}
+		return Pkglookup(s4.Name, p)
+
+	case '?':
+		p.next()
+
+		var p *Pkg
+
+		if s2.U.(string) == "" {
+			p = importpkg
+		} else {
+			if isbadimport(s2.U.(string)) {
+				errorexit()
+			}
+			p = mkpkg(s2.U.(string))
+		}
+		return Pkglookup("?", p)
+
+	default:
+		p.import_error()
+		return nil
+	}
+}
+
+func (p *parser) ohidden_funarg_list() *NodeList {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("ohidden_funarg_list")()
+	}
+
+	var ss *NodeList
+	if p.tok != ')' {
+		ss = p.hidden_funarg_list()
+	}
+	return ss
+}
+
+func (p *parser) ohidden_structdcl_list() *NodeList {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("ohidden_structdcl_list")()
+	}
+
+	var ss *NodeList
+	if p.tok != '}' {
+		ss = p.hidden_structdcl_list()
+	}
+	return ss
+}
+
+func (p *parser) ohidden_interfacedcl_list() *NodeList {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("ohidden_interfacedcl_list")()
+	}
+
+	var ss *NodeList
+	if p.tok != '}' {
+		ss = p.hidden_interfacedcl_list()
+	}
+	return ss
+}
+
+// import syntax from package header
+func (p *parser) hidden_import() {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("hidden_import")()
+	}
+
+	switch p.tok {
+	case LIMPORT:
+		// LIMPORT LNAME LLITERAL ';'
+		p.next()
+		var s2 *Sym
+		if p.tok == LNAME {
+			s2 = p.sym_
+			p.next()
+		} else {
+			p.import_error()
+		}
+		var s3 Val
+		if p.tok == LLITERAL {
+			s3 = p.val
+			p.next()
+		} else {
+			p.import_error()
+		}
+		p.want(';')
+
+		importimport(s2, s3.U.(string))
+
+	case LVAR:
+		// LVAR hidden_pkg_importsym hidden_type ';'
+		p.next()
+		s2 := p.hidden_pkg_importsym()
+		s3 := p.hidden_type()
+		p.want(';')
+
+		importvar(s2, s3)
+
+	case LCONST:
+		// LCONST hidden_pkg_importsym '=' hidden_constant ';'
+		// LCONST hidden_pkg_importsym hidden_type '=' hidden_constant ';'
+		p.next()
+		s2 := p.hidden_pkg_importsym()
+		var s3 *Type = Types[TIDEAL]
+		if p.tok != '=' {
+			s3 = p.hidden_type()
+		}
+		p.want('=')
+		s4 := p.hidden_constant()
+		p.want(';')
+
+		importconst(s2, s3, s4)
+
+	case LTYPE:
+		// LTYPE hidden_pkgtype hidden_type ';'
+		p.next()
+		s2 := p.hidden_pkgtype()
+		s3 := p.hidden_type()
+		p.want(';')
+
+		importtype(s2, s3)
+
+	case LFUNC:
+		// LFUNC hidden_fndcl fnbody ';'
+		p.next()
+		s2 := p.hidden_fndcl()
+		s3 := p.fnbody()
+		p.want(';')
+
+		if s2 == nil {
+			dclcontext = PEXTERN // since we skip the funcbody below
+			return
+		}
+
+		s2.Func.Inl = s3
+
+		funcbody(s2)
+		importlist = append(importlist, s2)
+
+		if Debug['E'] > 0 {
+			fmt.Printf("import [%q] func %v \n", importpkg.Path, s2)
+			if Debug['m'] > 2 && s2.Func.Inl != nil {
+				fmt.Printf("inl body:%v\n", s2.Func.Inl)
+			}
+		}
+
+	default:
+		p.import_error()
+	}
+}
+
+func (p *parser) hidden_pkg_importsym() *Sym {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("hidden_pkg_importsym")()
+	}
+
+	s1 := p.hidden_importsym()
+
+	ss := s1
+	structpkg = ss.Pkg
+
+	return ss
+}
+
+func (p *parser) hidden_pkgtype() *Type {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("hidden_pkgtype")()
+	}
+
+	s1 := p.hidden_pkg_importsym()
+
+	ss := pkgtype(s1)
+	importsym(s1, OTYPE)
+
+	return ss
+}
+
+// ----------------------------------------------------------------------------
+// Importing types
+
+func (p *parser) hidden_type() *Type {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("hidden_type")()
+	}
+
+	switch p.tok {
+	default:
+		return p.hidden_type_misc()
+	case LCOMM:
+		return p.hidden_type_recv_chan()
+	case LFUNC:
+		return p.hidden_type_func()
+	}
+}
+
+func (p *parser) hidden_type_non_recv_chan() *Type {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("hidden_type_non_recv_chan")()
+	}
+
+	switch p.tok {
+	default:
+		return p.hidden_type_misc()
+	case LFUNC:
+		return p.hidden_type_func()
+	}
+}
+
+func (p *parser) hidden_type_misc() *Type {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("hidden_type_misc")()
+	}
+
+	switch p.tok {
+	case '@':
+		// hidden_importsym
+		s1 := p.hidden_importsym()
+		return pkgtype(s1)
+
+	case LNAME:
+		// LNAME
+		s1 := p.sym_
+		p.next()
+
+		// predefined name like uint8
+		s1 = Pkglookup(s1.Name, builtinpkg)
+		if s1.Def == nil || s1.Def.Op != OTYPE {
+			Yyerror("%s is not a type", s1.Name)
+			return nil
+		} else {
+			return s1.Def.Type
+		}
+
+	case '[':
+		// '[' ']' hidden_type
+		// '[' LLITERAL ']' hidden_type
+		p.next()
+		var s2 *Node
+		if p.tok == LLITERAL {
+			s2 = nodlit(p.val)
+			p.next()
+		}
+		p.want(']')
+		s4 := p.hidden_type()
+
+		return aindex(s2, s4)
+
+	case LMAP:
+		// LMAP '[' hidden_type ']' hidden_type
+		p.next()
+		p.want('[')
+		s3 := p.hidden_type()
+		p.want(']')
+		s5 := p.hidden_type()
+
+		return maptype(s3, s5)
+
+	case LSTRUCT:
+		// LSTRUCT '{' ohidden_structdcl_list '}'
+		p.next()
+		p.want('{')
+		s3 := p.ohidden_structdcl_list()
+		p.want('}')
+
+		return tostruct(s3)
+
+	case LINTERFACE:
+		// LINTERFACE '{' ohidden_interfacedcl_list '}'
+		p.next()
+		p.want('{')
+		s3 := p.ohidden_interfacedcl_list()
+		p.want('}')
+
+		return tointerface(s3)
+
+	case '*':
+		// '*' hidden_type
+		p.next()
+		s2 := p.hidden_type()
+		return Ptrto(s2)
+
+	case LCHAN:
+		p.next()
+		switch p.tok {
+		default:
+			// LCHAN hidden_type_non_recv_chan
+			s2 := p.hidden_type_non_recv_chan()
+			ss := typ(TCHAN)
+			ss.Type = s2
+			ss.Chan = Cboth
+			return ss
+
+		case '(':
+			// LCHAN '(' hidden_type_recv_chan ')'
+			p.next()
+			s3 := p.hidden_type_recv_chan()
+			p.want(')')
+			ss := typ(TCHAN)
+			ss.Type = s3
+			ss.Chan = Cboth
+			return ss
+
+		case LCOMM:
+			// LCHAN hidden_type
+			p.next()
+			s3 := p.hidden_type()
+			ss := typ(TCHAN)
+			ss.Type = s3
+			ss.Chan = Csend
+			return ss
+		}
+
+	default:
+		p.import_error()
+		return nil
+	}
+}
+
+func (p *parser) hidden_type_recv_chan() *Type {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("hidden_type_recv_chan")()
+	}
+
+	p.want(LCOMM)
+	p.want(LCHAN)
+	s3 := p.hidden_type()
+
+	ss := typ(TCHAN)
+	ss.Type = s3
+	ss.Chan = Crecv
+	return ss
+}
+
+func (p *parser) hidden_type_func() *Type {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("hidden_type_func")()
+	}
+
+	p.want(LFUNC)
+	p.want('(')
+	s3 := p.ohidden_funarg_list()
+	p.want(')')
+	s5 := p.ohidden_funres()
+
+	return functype(nil, s3, s5)
+}
+
+func (p *parser) hidden_funarg() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("hidden_funarg")()
+	}
+
+	s1 := p.sym()
+	switch p.tok {
+	default:
+		s2 := p.hidden_type()
+		s3 := p.oliteral()
+
+		ss := Nod(ODCLFIELD, nil, typenod(s2))
+		if s1 != nil {
+			ss.Left = newname(s1)
+		}
+		ss.SetVal(s3)
+		return ss
+
+	case LDDD:
+		p.next()
+		s3 := p.hidden_type()
+		s4 := p.oliteral()
+
+		var t *Type
+
+		t = typ(TARRAY)
+		t.Bound = -1
+		t.Type = s3
+
+		ss := Nod(ODCLFIELD, nil, typenod(t))
+		if s1 != nil {
+			ss.Left = newname(s1)
+		}
+		ss.Isddd = true
+		ss.SetVal(s4)
+
+		return ss
+	}
+}
+
+func (p *parser) hidden_structdcl() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("hidden_structdcl")()
+	}
+
+	s1 := p.sym()
+	s2 := p.hidden_type()
+	s3 := p.oliteral()
+
+	var s *Sym
+	var pkg *Pkg
+
+	var ss *Node
+	if s1 != nil && s1.Name != "?" {
+		ss = Nod(ODCLFIELD, newname(s1), typenod(s2))
+		ss.SetVal(s3)
+	} else {
+		s = s2.Sym
+		if s == nil && Isptr[s2.Etype] {
+			s = s2.Type.Sym
+		}
+		pkg = importpkg
+		if s1 != nil {
+			pkg = s1.Pkg
+		}
+		ss = embedded(s, pkg)
+		ss.Right = typenod(s2)
+		ss.SetVal(s3)
+	}
+
+	return ss
+}
+
+func (p *parser) hidden_interfacedcl() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("hidden_interfacedcl")()
+	}
+
+	// The original (now defunct) grammar in go.y accepted both a method
+	// or an (embedded) type:
+	//
+	// hidden_interfacedcl:
+	// 	sym '(' ohidden_funarg_list ')' ohidden_funres
+	// 	{
+	// 		$$ = Nod(ODCLFIELD, newname($1), typenod(functype(fakethis(), $3, $5)));
+	// 	}
+	// |	hidden_type
+	// 	{
+	// 		$$ = Nod(ODCLFIELD, nil, typenod($1));
+	// 	}
+	//
+	// But the current textual export code only exports (inlined) methods,
+	// even if the methods came from embedded interfaces. Furthermore, in
+	// the original grammar, hidden_type may also start with a sym (LNAME
+	// or '@'), complicating matters further. Since we never have embedded
+	// types, only parse methods here.
+
+	s1 := p.sym()
+	p.want('(')
+	s3 := p.ohidden_funarg_list()
+	p.want(')')
+	s5 := p.ohidden_funres()
+
+	return Nod(ODCLFIELD, newname(s1), typenod(functype(fakethis(), s3, s5)))
+}
+
+func (p *parser) ohidden_funres() *NodeList {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("ohidden_funres")()
+	}
+
+	switch p.tok {
+	default:
+		return nil
+
+	case '(', '@', LNAME, '[', LMAP, LSTRUCT, LINTERFACE, '*', LCHAN, LCOMM, LFUNC:
+		return p.hidden_funres()
+	}
+}
+
+func (p *parser) hidden_funres() *NodeList {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("hidden_funres")()
+	}
+
+	switch p.tok {
+	case '(':
+		p.next()
+		s2 := p.ohidden_funarg_list()
+		p.want(')')
+		return s2
+
+	default:
+		s1 := p.hidden_type()
+		return list1(Nod(ODCLFIELD, nil, typenod(s1)))
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Importing constants
+
+func (p *parser) hidden_literal() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("hidden_literal")()
+	}
+
+	switch p.tok {
+	case LLITERAL:
+		ss := nodlit(p.val)
+		p.next()
+		return ss
+
+	case '-':
+		p.next()
+		if p.tok == LLITERAL {
+			ss := nodlit(p.val)
+			p.next()
+			switch ss.Val().Ctype() {
+			case CTINT, CTRUNE:
+				mpnegfix(ss.Val().U.(*Mpint))
+				break
+			case CTFLT:
+				mpnegflt(ss.Val().U.(*Mpflt))
+				break
+			case CTCPLX:
+				mpnegflt(&ss.Val().U.(*Mpcplx).Real)
+				mpnegflt(&ss.Val().U.(*Mpcplx).Imag)
+				break
+			default:
+				Yyerror("bad negated constant")
+			}
+			return ss
+		} else {
+			p.import_error()
+			return nil
+		}
+
+	case LNAME, '@', '?':
+		s1 := p.sym()
+		ss := oldname(Pkglookup(s1.Name, builtinpkg))
+		if ss.Op != OLITERAL {
+			Yyerror("bad constant %v", ss.Sym)
+		}
+		return ss
+
+	default:
+		p.import_error()
+		return nil
+	}
+}
+
+func (p *parser) hidden_constant() *Node {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("hidden_constant")()
+	}
+
+	switch p.tok {
+	default:
+		return p.hidden_literal()
+	case '(':
+		p.next()
+		s2 := p.hidden_literal()
+		p.want('+')
+		s4 := p.hidden_literal()
+		p.want(')')
+
+		if s2.Val().Ctype() == CTRUNE && s4.Val().Ctype() == CTINT {
+			ss := s2
+			mpaddfixfix(s2.Val().U.(*Mpint), s4.Val().U.(*Mpint), 0)
+			return ss
+		}
+		s4.Val().U.(*Mpcplx).Real = s4.Val().U.(*Mpcplx).Imag
+		Mpmovecflt(&s4.Val().U.(*Mpcplx).Imag, 0.0)
+		return nodcplxlit(s2.Val(), s4.Val())
+	}
+}
+
+func (p *parser) hidden_import_list() {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("hidden_import_list")()
+	}
+
+	for p.tok != '$' {
+		p.hidden_import()
+	}
+}
+
+func (p *parser) hidden_funarg_list() *NodeList {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("hidden_funarg_list")()
+	}
+
+	s1 := p.hidden_funarg()
+	ss := list1(s1)
+	for p.got(',') {
+		s3 := p.hidden_funarg()
+		ss = list(ss, s3)
+	}
+	return ss
+}
+
+func (p *parser) hidden_structdcl_list() *NodeList {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("hidden_structdcl_list")()
+	}
+
+	s1 := p.hidden_structdcl()
+	ss := list1(s1)
+	for p.got(';') {
+		s3 := p.hidden_structdcl()
+		ss = list(ss, s3)
+	}
+	return ss
+}
+
+func (p *parser) hidden_interfacedcl_list() *NodeList {
+	if trace && Debug['x'] != 0 {
+		defer p.trace("hidden_interfacedcl_list")()
+	}
+
+	s1 := p.hidden_interfacedcl()
+	ss := list1(s1)
+	for p.got(';') {
+		s3 := p.hidden_interfacedcl()
+		ss = list(ss, s3)
+	}
+	return ss
+}
diff --git a/src/cmd/compile/internal/gc/pgen.go b/src/cmd/compile/internal/gc/pgen.go
index 47cb8b1..ffc0ab9 100644
--- a/src/cmd/compile/internal/gc/pgen.go
+++ b/src/cmd/compile/internal/gc/pgen.go
@@ -85,7 +85,7 @@ func makefuncdatasym(namefmt string, funcdatakind int64) *Sym {
 
 func gvardefx(n *Node, as int) {
 	if n == nil {
-		Fatal("gvardef nil")
+		Fatalf("gvardef nil")
 	}
 	if n.Op != ONAME {
 		Yyerror("gvardef %v; %v", Oconv(int(n.Op), obj.FmtSharp), n)
@@ -94,7 +94,11 @@ func gvardefx(n *Node, as int) {
 
 	switch n.Class {
 	case PAUTO, PPARAM, PPARAMOUT:
-		Thearch.Gins(as, nil, n)
+		if as == obj.AVARLIVE {
+			Thearch.Gins(as, n, nil)
+		} else {
+			Thearch.Gins(as, nil, n)
+		}
 	}
 }
 
@@ -106,13 +110,17 @@ func gvarkill(n *Node) {
 	gvardefx(n, obj.AVARKILL)
 }
 
+func gvarlive(n *Node) {
+	gvardefx(n, obj.AVARLIVE)
+}
+
 func removevardef(firstp *obj.Prog) {
 	for p := firstp; p != nil; p = p.Link {
-		for p.Link != nil && (p.Link.As == obj.AVARDEF || p.Link.As == obj.AVARKILL) {
+		for p.Link != nil && (p.Link.As == obj.AVARDEF || p.Link.As == obj.AVARKILL || p.Link.As == obj.AVARLIVE) {
 			p.Link = p.Link.Link
 		}
 		if p.To.Type == obj.TYPE_BRANCH {
-			for p.To.Val.(*obj.Prog) != nil && (p.To.Val.(*obj.Prog).As == obj.AVARDEF || p.To.Val.(*obj.Prog).As == obj.AVARKILL) {
+			for p.To.Val.(*obj.Prog) != nil && (p.To.Val.(*obj.Prog).As == obj.AVARDEF || p.To.Val.(*obj.Prog).As == obj.AVARKILL || p.To.Val.(*obj.Prog).As == obj.AVARLIVE) {
 				p.To.Val = p.To.Val.(*obj.Prog).Link
 			}
 		}
@@ -122,13 +130,16 @@ func removevardef(firstp *obj.Prog) {
 func gcsymdup(s *Sym) {
 	ls := Linksym(s)
 	if len(ls.R) > 0 {
-		Fatal("cannot rosymdup %s with relocations", ls.Name)
+		Fatalf("cannot rosymdup %s with relocations", ls.Name)
 	}
 	ls.Name = fmt.Sprintf("gclocals·%x", md5.Sum(ls.P))
 	ls.Dupok = 1
 }
 
 func emitptrargsmap() {
+	if Curfn.Func.Nname.Sym.Name == "_" {
+		return
+	}
 	sym := Lookup(fmt.Sprintf("%s.args_stackmap", Curfn.Func.Nname.Sym.Name))
 
 	nptr := int(Curfn.Type.Argwid / int64(Widthptr))
@@ -164,6 +175,8 @@ func emitptrargsmap() {
 	ggloblsym(sym, int32(off), obj.RODATA|obj.LOCAL)
 }
 
+// cmpstackvarlt reports whether the stack variable a sorts before b.
+//
 // Sort the list of stack variables. Autos after anything else,
 // within autos, unused after used, within used, things with
 // pointers first, zeroed things first, and then decreasing size.
@@ -172,48 +185,48 @@ func emitptrargsmap() {
 // really means, in memory, things with pointers needing zeroing at
 // the top of the stack and increasing in size.
 // Non-autos sort on offset.
-func cmpstackvar(a *Node, b *Node) int {
+func cmpstackvarlt(a, b *Node) bool {
 	if a.Class != b.Class {
 		if a.Class == PAUTO {
-			return +1
+			return false
 		}
-		return -1
+		return true
 	}
 
 	if a.Class != PAUTO {
 		if a.Xoffset < b.Xoffset {
-			return -1
+			return true
 		}
 		if a.Xoffset > b.Xoffset {
-			return +1
+			return false
 		}
-		return 0
+		return false
 	}
 
 	if a.Used != b.Used {
-		return obj.Bool2int(b.Used) - obj.Bool2int(a.Used)
+		return a.Used
 	}
 
-	ap := obj.Bool2int(haspointers(a.Type))
-	bp := obj.Bool2int(haspointers(b.Type))
+	ap := haspointers(a.Type)
+	bp := haspointers(b.Type)
 	if ap != bp {
-		return bp - ap
+		return ap
 	}
 
-	ap = obj.Bool2int(a.Name.Needzero)
-	bp = obj.Bool2int(b.Name.Needzero)
+	ap = a.Name.Needzero
+	bp = b.Name.Needzero
 	if ap != bp {
-		return bp - ap
+		return ap
 	}
 
 	if a.Type.Width < b.Type.Width {
-		return +1
+		return false
 	}
 	if a.Type.Width > b.Type.Width {
-		return -1
+		return true
 	}
 
-	return stringsCompare(a.Sym.Name, b.Sym.Name)
+	return a.Sym.Name < b.Sym.Name
 }
 
 // stkdelta records the stack offset delta for a node
@@ -239,7 +252,7 @@ func allocauto(ptxt *obj.Prog) {
 
 	markautoused(ptxt)
 
-	listsort(&Curfn.Func.Dcl, cmpstackvar)
+	listsort(&Curfn.Func.Dcl, cmpstackvarlt)
 
 	// Unused autos are at the end, chop 'em off.
 	ll := Curfn.Func.Dcl
@@ -273,14 +286,14 @@ func allocauto(ptxt *obj.Prog) {
 		dowidth(n.Type)
 		w = n.Type.Width
 		if w >= Thearch.MAXWIDTH || w < 0 {
-			Fatal("bad width")
+			Fatalf("bad width")
 		}
 		Stksize += w
 		Stksize = Rnd(Stksize, int64(n.Type.Align))
 		if haspointers(n.Type) {
 			stkptrsize = Stksize
 		}
-		if Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
+		if Thearch.Thechar == '0' || Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
 			Stksize = Rnd(Stksize, int64(Widthptr))
 		}
 		if Stksize >= 1<<31 {
@@ -314,10 +327,10 @@ func Cgen_checknil(n *Node) {
 	// Ideally we wouldn't see any integer types here, but we do.
 	if n.Type == nil || (!Isptr[n.Type.Etype] && !Isint[n.Type.Etype] && n.Type.Etype != TUNSAFEPTR) {
 		Dump("checknil", n)
-		Fatal("bad checknil")
+		Fatalf("bad checknil")
 	}
 
-	if ((Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9') && n.Op != OREGISTER) || !n.Addable || n.Op == OLITERAL {
+	if ((Thearch.Thechar == '0' || Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9') && n.Op != OREGISTER) || !n.Addable || n.Op == OLITERAL {
 		var reg Node
 		Regalloc(&reg, Types[Tptr], n)
 		Cgen(n, &reg)
@@ -371,7 +384,7 @@ func compile(fn *Node) {
 	// set up domain for labels
 	clearlabels()
 
-	if Curfn.Type.Outnamed != 0 {
+	if Curfn.Type.Outnamed {
 		// add clearing of the output parameters
 		var save Iter
 		t := Structfirst(&save, Getoutarg(Curfn.Type))
@@ -392,13 +405,13 @@ func compile(fn *Node) {
 		goto ret
 	}
 
-	Hasdefer = 0
+	hasdefer = false
 	walk(Curfn)
 	if nerrors != 0 {
 		goto ret
 	}
-	if flag_race != 0 {
-		racewalk(Curfn)
+	if instrumenting {
+		instrument(Curfn)
 	}
 	if nerrors != 0 {
 		goto ret
@@ -487,7 +500,7 @@ func compile(fn *Node) {
 	// TODO: Determine when the final cgen_ret can be omitted. Perhaps always?
 	cgen_ret(nil)
 
-	if Hasdefer != 0 {
+	if hasdefer {
 		// deferreturn pretends to have one uintptr argument.
 		// Reserve space for it so stack scanner is happy.
 		if Maxarg < int64(Widthptr) {
diff --git a/src/cmd/compile/internal/gc/pgen_test.go b/src/cmd/compile/internal/gc/pgen_test.go
new file mode 100644
index 0000000..ebc9101
--- /dev/null
+++ b/src/cmd/compile/internal/gc/pgen_test.go
@@ -0,0 +1,176 @@
+// Copyright 2015 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
+
+import (
+	"reflect"
+	"testing"
+)
+
+// Test all code paths for cmpstackvarlt.
+func TestCmpstackvar(t *testing.T) {
+	testdata := []struct {
+		a, b Node
+		lt   bool
+	}{
+		{
+			Node{Class: PAUTO},
+			Node{Class: PFUNC},
+			false,
+		},
+		{
+			Node{Class: PFUNC},
+			Node{Class: PAUTO},
+			true,
+		},
+		{
+			Node{Class: PFUNC, Xoffset: 0},
+			Node{Class: PFUNC, Xoffset: 10},
+			true,
+		},
+		{
+			Node{Class: PFUNC, Xoffset: 20},
+			Node{Class: PFUNC, Xoffset: 10},
+			false,
+		},
+		{
+			Node{Class: PFUNC, Xoffset: 10},
+			Node{Class: PFUNC, Xoffset: 10},
+			false,
+		},
+		{
+			Node{Class: PAUTO, Used: true},
+			Node{Class: PAUTO, Used: false},
+			true,
+		},
+		{
+			Node{Class: PAUTO, Used: false},
+			Node{Class: PAUTO, Used: true},
+			false,
+		},
+		{
+			Node{Class: PAUTO, Type: &Type{Haspointers: 1}}, // haspointers -> false
+			Node{Class: PAUTO, Type: &Type{Haspointers: 2}}, // haspointers -> true
+			false,
+		},
+		{
+			Node{Class: PAUTO, Type: &Type{Haspointers: 2}}, // haspointers -> true
+			Node{Class: PAUTO, Type: &Type{Haspointers: 1}}, // haspointers -> false
+			true,
+		},
+		{
+			Node{Class: PAUTO, Type: &Type{}, Name: &Name{Needzero: true}},
+			Node{Class: PAUTO, Type: &Type{}, Name: &Name{Needzero: false}},
+			true,
+		},
+		{
+			Node{Class: PAUTO, Type: &Type{}, Name: &Name{Needzero: false}},
+			Node{Class: PAUTO, Type: &Type{}, Name: &Name{Needzero: true}},
+			false,
+		},
+		{
+			Node{Class: PAUTO, Type: &Type{Width: 1}, Name: &Name{}},
+			Node{Class: PAUTO, Type: &Type{Width: 2}, Name: &Name{}},
+			false,
+		},
+		{
+			Node{Class: PAUTO, Type: &Type{Width: 2}, Name: &Name{}},
+			Node{Class: PAUTO, Type: &Type{Width: 1}, Name: &Name{}},
+			true,
+		},
+		{
+			Node{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "abc"}},
+			Node{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "xyz"}},
+			true,
+		},
+		{
+			Node{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "abc"}},
+			Node{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "abc"}},
+			false,
+		},
+		{
+			Node{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "xyz"}},
+			Node{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "abc"}},
+			false,
+		},
+	}
+	for _, d := range testdata {
+		got := cmpstackvarlt(&d.a, &d.b)
+		if got != d.lt {
+			t.Errorf("want %#v < %#v", d.a, d.b)
+		}
+	}
+}
+
+func slice2nodelist(s []*Node) *NodeList {
+	var nl *NodeList
+	for _, n := range s {
+		nl = list(nl, n)
+	}
+	return nl
+}
+
+func nodelist2slice(nl *NodeList) []*Node {
+	var s []*Node
+	for l := nl; l != nil; l = l.Next {
+		s = append(s, l.N)
+	}
+	return s
+}
+
+func TestListsort(t *testing.T) {
+	inp := []*Node{
+		{Class: PFUNC, Type: &Type{}, Name: &Name{}, Sym: &Sym{}},
+		{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{}},
+		{Class: PFUNC, Xoffset: 0, Type: &Type{}, Name: &Name{}, Sym: &Sym{}},
+		{Class: PFUNC, Xoffset: 10, Type: &Type{}, Name: &Name{}, Sym: &Sym{}},
+		{Class: PFUNC, Xoffset: 20, Type: &Type{}, Name: &Name{}, Sym: &Sym{}},
+		{Class: PAUTO, Used: true, Type: &Type{}, Name: &Name{}, Sym: &Sym{}},
+		{Class: PAUTO, Type: &Type{Haspointers: 1}, Name: &Name{}, Sym: &Sym{}}, // haspointers -> false
+		{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{}},
+		{Class: PAUTO, Type: &Type{}, Name: &Name{Needzero: true}, Sym: &Sym{}},
+		{Class: PAUTO, Type: &Type{Width: 1}, Name: &Name{}, Sym: &Sym{}},
+		{Class: PAUTO, Type: &Type{Width: 2}, Name: &Name{}, Sym: &Sym{}},
+		{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "abc"}},
+		{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "xyz"}},
+	}
+	want := []*Node{
+		{Class: PFUNC, Type: &Type{}, Name: &Name{}, Sym: &Sym{}},
+		{Class: PFUNC, Xoffset: 0, Type: &Type{}, Name: &Name{}, Sym: &Sym{}},
+		{Class: PFUNC, Xoffset: 10, Type: &Type{}, Name: &Name{}, Sym: &Sym{}},
+		{Class: PFUNC, Xoffset: 20, Type: &Type{}, Name: &Name{}, Sym: &Sym{}},
+		{Class: PAUTO, Used: true, Type: &Type{}, Name: &Name{}, Sym: &Sym{}},
+		{Class: PAUTO, Type: &Type{}, Name: &Name{Needzero: true}, Sym: &Sym{}},
+		{Class: PAUTO, Type: &Type{Width: 2}, Name: &Name{}, Sym: &Sym{}},
+		{Class: PAUTO, Type: &Type{Width: 1}, Name: &Name{}, Sym: &Sym{}},
+		{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{}},
+		{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{}},
+		{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "abc"}},
+		{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "xyz"}},
+		{Class: PAUTO, Type: &Type{Haspointers: 1}, Name: &Name{}, Sym: &Sym{}}, // haspointers -> false
+	}
+	// haspointers updates Type.Haspointers as a side effect, so
+	// exercise this function on all inputs so that reflect.DeepEqual
+	// doesn't produce false positives.
+	for i := range want {
+		haspointers(want[i].Type)
+		haspointers(inp[i].Type)
+	}
+
+	nl := slice2nodelist(inp)
+	listsort(&nl, cmpstackvarlt)
+	got := nodelist2slice(nl)
+	if !reflect.DeepEqual(want, got) {
+		t.Error("listsort failed")
+		for i := range got {
+			g := got[i]
+			w := want[i]
+			eq := reflect.DeepEqual(w, g)
+			if !eq {
+				t.Log(i, w, g)
+			}
+		}
+	}
+}
diff --git a/src/cmd/compile/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go
index efaf69f..feb66f6 100644
--- a/src/cmd/compile/internal/gc/plive.go
+++ b/src/cmd/compile/internal/gc/plive.go
@@ -92,18 +92,10 @@ type Liveness struct {
 	livepointers     []Bvec
 }
 
-func xmalloc(size uint32) interface{} {
-	result := (interface{})(make([]byte, size))
-	if result == nil {
-		Fatal("malloc failed")
-	}
-	return result
-}
-
 // Constructs a new basic block containing a single instruction.
 func newblock(prog *obj.Prog) *BasicBlock {
 	if prog == nil {
-		Fatal("newblock: prog cannot be nil")
+		Fatalf("newblock: prog cannot be nil")
 	}
 	result := new(BasicBlock)
 	result.rpo = -1
@@ -115,21 +107,14 @@ func newblock(prog *obj.Prog) *BasicBlock {
 	return result
 }
 
-// Frees a basic block and all of its leaf data structures.
-func freeblock(bb *BasicBlock) {
-	if bb == nil {
-		Fatal("freeblock: cannot free nil")
-	}
-}
-
 // Adds an edge between two basic blocks by making from a predecessor of to and
 // to a successor of from.
 func addedge(from *BasicBlock, to *BasicBlock) {
 	if from == nil {
-		Fatal("addedge: from is nil")
+		Fatalf("addedge: from is nil")
 	}
 	if to == nil {
-		Fatal("addedge: to is nil")
+		Fatalf("addedge: to is nil")
 	}
 	from.succ = append(from.succ, to)
 	to.pred = append(to.pred, from)
@@ -290,10 +275,10 @@ func (x blockrpocmp) Less(i, j int) bool { return x[i].rpo < x[j].rpo }
 // is a call to a specific package qualified function name.
 func iscall(prog *obj.Prog, name *obj.LSym) bool {
 	if prog == nil {
-		Fatal("iscall: prog is nil")
+		Fatalf("iscall: prog is nil")
 	}
 	if name == nil {
-		Fatal("iscall: function name is nil")
+		Fatalf("iscall: function name is nil")
 	}
 	if prog.As != obj.ACALL {
 		return false
@@ -363,14 +348,14 @@ func addselectgosucc(selectgo *BasicBlock) {
 	pred := selectgo
 	for {
 		if len(pred.pred) == 0 {
-			Fatal("selectgo does not have a newselect")
+			Fatalf("selectgo does not have a newselect")
 		}
 		pred = pred.pred[0]
 		if blockany(pred, isselectcommcasecall) {
 			// A select comm case block should have exactly one
 			// successor.
 			if len(pred.succ) != 1 {
-				Fatal("select comm case has too many successors")
+				Fatalf("select comm case has too many successors")
 			}
 			succ = pred.succ[0]
 
@@ -379,7 +364,7 @@ func addselectgosucc(selectgo *BasicBlock) {
 			// and the branch should lead to the select case
 			// statements block.
 			if len(succ.succ) != 2 {
-				Fatal("select comm case successor has too many successors")
+				Fatalf("select comm case successor has too many successors")
 			}
 
 			// Add the block as a successor of the selectgo block.
@@ -429,7 +414,7 @@ func newcfg(firstp *obj.Prog) []*BasicBlock {
 		Thearch.Proginfo(p)
 		if p.To.Type == obj.TYPE_BRANCH {
 			if p.To.Val == nil {
-				Fatal("prog branch to nil")
+				Fatalf("prog branch to nil")
 			}
 			if p.To.Val.(*obj.Prog).Opt == nil {
 				p.To.Val.(*obj.Prog).Opt = newblock(p.To.Val.(*obj.Prog))
@@ -524,7 +509,7 @@ func newcfg(firstp *obj.Prog) []*BasicBlock {
 	if bb.rpo == -1 {
 		fmt.Printf("newcfg: unreachable basic block for %v\n", bb.last)
 		printcfg(cfg)
-		Fatal("newcfg: invalid control flow graph")
+		Fatalf("newcfg: invalid control flow graph")
 	}
 
 	return cfg
@@ -626,7 +611,7 @@ func progeffects(prog *obj.Prog, vars []*Node, uevar Bvec, varkill Bvec, avarini
 					goto Next
 				}
 				if pos >= int32(len(vars)) || vars[pos] != from.Node {
-					Fatal("bad bookkeeping in liveness %v %d", Nconv(from.Node.(*Node), 0), pos)
+					Fatalf("bad bookkeeping in liveness %v %d", Nconv(from.Node.(*Node), 0), pos)
 				}
 				if ((from.Node).(*Node)).Addrtaken {
 					bvset(avarinit, pos)
@@ -655,7 +640,7 @@ Next:
 					return
 				}
 				if pos >= int32(len(vars)) || vars[pos] != to.Node {
-					Fatal("bad bookkeeping in liveness %v %d", Nconv(to.Node.(*Node), 0), pos)
+					Fatalf("bad bookkeeping in liveness %v %d", Nconv(to.Node.(*Node), 0), pos)
 				}
 				if ((to.Node).(*Node)).Addrtaken {
 					if prog.As != obj.AVARKILL {
@@ -718,7 +703,7 @@ func newliveness(fn *Node, ptxt *obj.Prog, cfg []*BasicBlock, vars []*Node) *Liv
 // Frees the liveness structure and all of its leaf data structures.
 func freeliveness(lv *Liveness) {
 	if lv == nil {
-		Fatal("freeliveness: cannot free nil")
+		Fatalf("freeliveness: cannot free nil")
 	}
 }
 
@@ -821,7 +806,7 @@ func checkauto(fn *Node, p *obj.Prog, n *Node) {
 		return
 	}
 
-	fmt.Printf("checkauto %v: %v (%p; class=%d) not found in %v\n", Curfn, n, n, n.Class, p)
+	fmt.Printf("checkauto %v: %v (%p; class=%d) not found in %p %v\n", funcSym(Curfn), n, n, n.Class, p, p)
 	for l := fn.Func.Dcl; l != nil; l = l.Next {
 		fmt.Printf("\t%v (%p; class=%d)\n", l.N, l.N, l.N.Class)
 	}
@@ -833,7 +818,7 @@ func checkparam(fn *Node, p *obj.Prog, n *Node) {
 		return
 	}
 	var a *Node
-	var class uint8
+	var class Class
 	for l := fn.Func.Dcl; l != nil; l = l.Next {
 		a = l.N
 		class = a.Class &^ PHEAP
@@ -890,7 +875,7 @@ func checkptxt(fn *Node, firstp *obj.Prog) {
 // accounts for 40% of the 6g execution time.
 func onebitwalktype1(t *Type, xoffset *int64, bv Bvec) {
 	if t.Align > 0 && *xoffset&int64(t.Align-1) != 0 {
-		Fatal("onebitwalktype1: invalid initial alignment, %v", t)
+		Fatalf("onebitwalktype1: invalid initial alignment, %v", t)
 	}
 
 	switch t.Etype {
@@ -919,7 +904,7 @@ func onebitwalktype1(t *Type, xoffset *int64, bv Bvec) {
 		TCHAN,
 		TMAP:
 		if *xoffset&int64(Widthptr-1) != 0 {
-			Fatal("onebitwalktype1: invalid alignment, %v", t)
+			Fatalf("onebitwalktype1: invalid alignment, %v", t)
 		}
 		bvset(bv, int32(*xoffset/int64(Widthptr))) // pointer
 		*xoffset += t.Width
@@ -927,7 +912,7 @@ func onebitwalktype1(t *Type, xoffset *int64, bv Bvec) {
 	case TSTRING:
 		// struct { byte *str; intgo len; }
 		if *xoffset&int64(Widthptr-1) != 0 {
-			Fatal("onebitwalktype1: invalid alignment, %v", t)
+			Fatalf("onebitwalktype1: invalid alignment, %v", t)
 		}
 		bvset(bv, int32(*xoffset/int64(Widthptr))) //pointer in first slot
 		*xoffset += t.Width
@@ -937,7 +922,7 @@ func onebitwalktype1(t *Type, xoffset *int64, bv Bvec) {
 		// or, when isnilinter(t)==true:
 		// struct { Type *type; void *data; }
 		if *xoffset&int64(Widthptr-1) != 0 {
-			Fatal("onebitwalktype1: invalid alignment, %v", t)
+			Fatalf("onebitwalktype1: invalid alignment, %v", t)
 		}
 		bvset(bv, int32(*xoffset/int64(Widthptr)))   // pointer in first slot
 		bvset(bv, int32(*xoffset/int64(Widthptr)+1)) // pointer in second slot
@@ -947,12 +932,12 @@ func onebitwalktype1(t *Type, xoffset *int64, bv Bvec) {
 		// The value of t->bound is -1 for slices types and >=0 for
 		// for fixed array types.  All other values are invalid.
 		if t.Bound < -1 {
-			Fatal("onebitwalktype1: invalid bound, %v", t)
+			Fatalf("onebitwalktype1: invalid bound, %v", t)
 		}
 		if Isslice(t) {
 			// struct { byte *array; uintgo len; uintgo cap; }
 			if *xoffset&int64(Widthptr-1) != 0 {
-				Fatal("onebitwalktype1: invalid TARRAY alignment, %v", t)
+				Fatalf("onebitwalktype1: invalid TARRAY alignment, %v", t)
 			}
 			bvset(bv, int32(*xoffset/int64(Widthptr))) // pointer in first slot (BitsPointer)
 			*xoffset += t.Width
@@ -975,7 +960,7 @@ func onebitwalktype1(t *Type, xoffset *int64, bv Bvec) {
 		*xoffset += t.Width - o
 
 	default:
-		Fatal("onebitwalktype1: unexpected type, %v", t)
+		Fatalf("onebitwalktype1: unexpected type, %v", t)
 	}
 }
 
@@ -1346,7 +1331,7 @@ func livenessepilogue(lv *Liveness) {
 		if pos < 0 {
 			// the first block we encounter should have the ATEXT so
 			// at no point should pos ever be less than zero.
-			Fatal("livenessepilogue")
+			Fatalf("livenessepilogue")
 		}
 
 		bvcopy(livein, bb.liveout)
@@ -1441,7 +1426,14 @@ func livenessepilogue(lv *Liveness) {
 						// the PCDATA must begin one instruction early too.
 						// The instruction before a call to deferreturn is always a
 						// no-op, to keep PC-specific data unambiguous.
-						splicebefore(lv, bb, newpcdataprog(p.Opt.(*obj.Prog), pos), p.Opt.(*obj.Prog))
+						prev := p.Opt.(*obj.Prog)
+						if Ctxt.Arch.Thechar == '9' {
+							// On ppc64 there is an additional instruction
+							// (another no-op or reload of toc pointer) before
+							// the call.
+							prev = prev.Opt.(*obj.Prog)
+						}
+						splicebefore(lv, bb, newpcdataprog(prev, pos), prev)
 					} else {
 						splicebefore(lv, bb, newpcdataprog(p, pos), p)
 					}
@@ -1685,15 +1677,13 @@ func livenessprintdebug(lv *Liveness) {
 				for j = 0; j < len(lv.vars); j++ {
 					n = lv.vars[j]
 					if islive(n, args, locals) {
-						tmp9 := printed
-						printed++
-						if tmp9 != 0 {
+						if printed != 0 {
 							fmt.Printf(",")
 						}
 						fmt.Printf("%v", n)
+						printed++
 					}
 				}
-
 				fmt.Printf("\n")
 			}
 
diff --git a/src/cmd/compile/internal/gc/popt.go b/src/cmd/compile/internal/gc/popt.go
index 4fc562c..4d71ab6 100644
--- a/src/cmd/compile/internal/gc/popt.go
+++ b/src/cmd/compile/internal/gc/popt.go
@@ -88,7 +88,7 @@ func Noreturn(p *obj.Prog) bool {
 // longer and more difficult to follow during debugging.
 // Remove them.
 
-/* what instruction does a JMP to p eventually land on? */
+// what instruction does a JMP to p eventually land on?
 func chasejmp(p *obj.Prog, jmploop *int) *obj.Prog {
 	n := 0
 	for p != nil && p.As == obj.AJMP && p.To.Type == obj.TYPE_BRANCH {
@@ -104,14 +104,12 @@ func chasejmp(p *obj.Prog, jmploop *int) *obj.Prog {
 	return p
 }
 
-/*
- * reuse reg pointer for mark/sweep state.
- * leave reg==nil at end because alive==nil.
- */
+// reuse reg pointer for mark/sweep state.
+// leave reg==nil at end because alive==nil.
 var alive interface{} = nil
 var dead interface{} = 1
 
-/* mark all code reachable from firstp as alive */
+// mark all code reachable from firstp as alive
 func mark(firstp *obj.Prog) {
 	for p := firstp; p != nil; p = p.Link {
 		if p.Opt != dead {
@@ -306,11 +304,11 @@ func Flowstart(firstp *obj.Prog, newData func() interface{}) *Graph {
 
 		if p.To.Type == obj.TYPE_BRANCH {
 			if p.To.Val == nil {
-				Fatal("pnil %v", p)
+				Fatalf("pnil %v", p)
 			}
 			f1 = p.To.Val.(*obj.Prog).Opt.(*Flow)
 			if f1 == nil {
-				Fatal("fnil %v / %v", p, p.To.Val.(*obj.Prog))
+				Fatalf("fnil %v / %v", p, p.To.Val.(*obj.Prog))
 			}
 			if f1 == f {
 				//fatal("self loop %v", p);
@@ -335,21 +333,19 @@ func Flowend(graph *Graph) {
 	}
 }
 
-/*
- * find looping structure
- *
- * 1) find reverse postordering
- * 2) find approximate dominators,
- *	the actual dominators if the flow graph is reducible
- *	otherwise, dominators plus some other non-dominators.
- *	See Matthew S. Hecht and Jeffrey D. Ullman,
- *	"Analysis of a Simple Algorithm for Global Data Flow Problems",
- *	Conf.  Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
- *	Oct. 1-3, 1973, pp.  207-217.
- * 3) find all nodes with a predecessor dominated by the current node.
- *	such a node is a loop head.
- *	recursively, all preds with a greater rpo number are in the loop
- */
+// find looping structure
+//
+// 1) find reverse postordering
+// 2) find approximate dominators,
+//	the actual dominators if the flow graph is reducible
+//	otherwise, dominators plus some other non-dominators.
+//	See Matthew S. Hecht and Jeffrey D. Ullman,
+//	"Analysis of a Simple Algorithm for Global Data Flow Problems",
+//	Conf.  Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
+//	Oct. 1-3, 1973, pp.  207-217.
+// 3) find all nodes with a predecessor dominated by the current node.
+//	such a node is a loop head.
+//	recursively, all preds with a greater rpo number are in the loop
 func postorder(r *Flow, rpo2r []*Flow, n int32) int32 {
 	r.Rpo = 1
 	r1 := r.S1
@@ -380,7 +376,7 @@ func rpolca(idom []int32, rpo1 int32, rpo2 int32) int32 {
 		for rpo1 < rpo2 {
 			t = idom[rpo2]
 			if t >= rpo2 {
-				Fatal("bad idom")
+				Fatalf("bad idom")
 			}
 			rpo2 = t
 		}
@@ -435,7 +431,7 @@ func flowrpo(g *Graph) {
 	d := postorder(g.Start, rpo2r, 0)
 	nr := int32(g.Num)
 	if d > nr {
-		Fatal("too many reg nodes %d %d", d, nr)
+		Fatalf("too many reg nodes %d %d", d, nr)
 	}
 	nr = d
 	var r1 *Flow
@@ -523,20 +519,15 @@ type TempVar struct {
 	merge   *TempVar // merge var with this one
 	start   int64    // smallest Prog.pc in live range
 	end     int64    // largest Prog.pc in live range
-	addr    uint8    // address taken - no accurate end
-	removed uint8    // removed from program
+	addr    bool     // address taken - no accurate end
+	removed bool     // removed from program
 }
 
+// startcmp sorts TempVars by start, then id, then symbol name.
 type startcmp []*TempVar
 
-func (x startcmp) Len() int {
-	return len(x)
-}
-
-func (x startcmp) Swap(i, j int) {
-	x[i], x[j] = x[j], x[i]
-}
-
+func (x startcmp) Len() int      { return len(x) }
+func (x startcmp) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
 func (x startcmp) Less(i, j int) bool {
 	a := x[i]
 	b := x[j]
@@ -556,7 +547,7 @@ func (x startcmp) Less(i, j int) bool {
 		return int(a.def.Id-b.def.Id) < 0
 	}
 	if a.node != b.node {
-		return stringsCompare(a.node.Sym.Name, b.node.Sym.Name) < 0
+		return a.node.Sym.Name < b.node.Sym.Name
 	}
 	return false
 }
@@ -577,22 +568,11 @@ func mergetemp(firstp *obj.Prog) {
 	}
 
 	// Build list of all mergeable variables.
-	nvar := 0
+	var vars []*TempVar
 	for l := Curfn.Func.Dcl; l != nil; l = l.Next {
-		if canmerge(l.N) {
-			nvar++
-		}
-	}
-
-	var_ := make([]TempVar, nvar)
-	nvar = 0
-	var n *Node
-	var v *TempVar
-	for l := Curfn.Func.Dcl; l != nil; l = l.Next {
-		n = l.N
-		if canmerge(n) {
-			v = &var_[nvar]
-			nvar++
+		if n := l.N; canmerge(n) {
+			v := &TempVar{}
+			vars = append(vars, v)
 			n.SetOpt(v)
 			v.node = n
 		}
@@ -605,10 +585,10 @@ func mergetemp(firstp *obj.Prog) {
 	for f := g.Start; f != nil; f = f.Link {
 		p := f.Prog
 		if p.From.Node != nil && ((p.From.Node).(*Node)).Opt() != nil && p.To.Node != nil && ((p.To.Node).(*Node)).Opt() != nil {
-			Fatal("double node %v", p)
+			Fatalf("double node %v", p)
 		}
-		v = nil
-		n, _ = p.From.Node.(*Node)
+		var v *TempVar
+		n, _ := p.From.Node.(*Node)
 		if n != nil {
 			v, _ = n.Opt().(*TempVar)
 		}
@@ -625,7 +605,7 @@ func mergetemp(firstp *obj.Prog) {
 			f.Data = v.use
 			v.use = f
 			if n == p.From.Node && (p.Info.Flags&LeftAddr != 0) {
-				v.addr = 1
+				v.addr = true
 			}
 		}
 	}
@@ -637,9 +617,8 @@ func mergetemp(firstp *obj.Prog) {
 	nkill := 0
 
 	// Special case.
-	for i := 0; i < len(var_); i++ {
-		v = &var_[i]
-		if v.addr != 0 {
+	for _, v := range vars {
+		if v.addr {
 			continue
 		}
 
@@ -650,12 +629,12 @@ func mergetemp(firstp *obj.Prog) {
 			if p.To.Node == v.node && (p.Info.Flags&RightWrite != 0) && p.Info.Flags&RightRead == 0 {
 				p.As = obj.ANOP
 				p.To = obj.Addr{}
-				v.removed = 1
+				v.removed = true
 				if debugmerge > 0 && Debug['v'] != 0 {
 					fmt.Printf("drop write-only %v\n", v.node.Sym)
 				}
 			} else {
-				Fatal("temp used and not set: %v", p)
+				Fatalf("temp used and not set: %v", p)
 			}
 			nkill++
 			continue
@@ -673,7 +652,7 @@ func mergetemp(firstp *obj.Prog) {
 			if p.From.Node == v.node && p1.To.Node == v.node && (p.Info.Flags&Move != 0) && (p.Info.Flags|p1.Info.Flags)&(LeftAddr|RightAddr) == 0 && p.Info.Flags&SizeAny == p1.Info.Flags&SizeAny {
 				p1.From = p.From
 				Thearch.Excise(f)
-				v.removed = 1
+				v.removed = true
 				if debugmerge > 0 && Debug['v'] != 0 {
 					fmt.Printf("drop immediate-use %v\n", v.node.Sym)
 				}
@@ -687,29 +666,25 @@ func mergetemp(firstp *obj.Prog) {
 	// Traverse live range of each variable to set start, end.
 	// Each flood uses a new value of gen so that we don't have
 	// to clear all the r->active words after each variable.
-	gen := int32(0)
+	gen := uint32(0)
 
-	for i := 0; i < len(var_); i++ {
-		v = &var_[i]
+	for _, v := range vars {
 		gen++
 		for f := v.use; f != nil; f = f.Data.(*Flow) {
-			mergewalk(v, f, uint32(gen))
+			mergewalk(v, f, gen)
 		}
-		if v.addr != 0 {
+		if v.addr {
 			gen++
 			for f := v.use; f != nil; f = f.Data.(*Flow) {
-				varkillwalk(v, f, uint32(gen))
+				varkillwalk(v, f, gen)
 			}
 		}
 	}
 
 	// Sort variables by start.
-	bystart := make([]*TempVar, len(var_))
-
-	for i := 0; i < len(var_); i++ {
-		bystart[i] = &var_[i]
-	}
-	sort.Sort(startcmp(bystart[:len(var_)]))
+	bystart := make([]*TempVar, len(vars))
+	copy(bystart, vars)
+	sort.Sort(startcmp(bystart))
 
 	// List of in-use variables, sorted by end, so that the ones that
 	// will last the longest are the earliest ones in the array.
@@ -717,40 +692,35 @@ func mergetemp(firstp *obj.Prog) {
 	// In theory we should use a sorted tree so that insertions are
 	// guaranteed O(log n) and then the loop is guaranteed O(n log n).
 	// In practice, it doesn't really matter.
-	inuse := make([]*TempVar, len(var_))
+	inuse := make([]*TempVar, len(bystart))
 
 	ninuse := 0
-	nfree := len(var_)
-	var t *Type
-	var v1 *TempVar
-	var j int
-	for i := 0; i < len(var_); i++ {
-		v = bystart[i]
+	nfree := len(bystart)
+	for _, v := range bystart {
 		if debugmerge > 0 && Debug['v'] != 0 {
-			fmt.Printf("consider %v: removed=%d\n", Nconv(v.node, obj.FmtSharp), v.removed)
+			fmt.Printf("consider %v: removed=%t\n", Nconv(v.node, obj.FmtSharp), v.removed)
 		}
 
-		if v.removed != 0 {
+		if v.removed {
 			continue
 		}
 
 		// Expire no longer in use.
 		for ninuse > 0 && inuse[ninuse-1].end < v.start {
 			ninuse--
-			v1 = inuse[ninuse]
 			nfree--
-			inuse[nfree] = v1
+			inuse[nfree] = inuse[ninuse]
 		}
 
 		if debugmerge > 0 && Debug['v'] != 0 {
-			fmt.Printf("consider %v: removed=%d nfree=%d nvar=%d\n", Nconv(v.node, obj.FmtSharp), v.removed, nfree, len(var_))
+			fmt.Printf("consider %v: removed=%t nfree=%d nvar=%d\n", Nconv(v.node, obj.FmtSharp), v.removed, nfree, len(bystart))
 		}
 
 		// Find old temp to reuse if possible.
-		t = v.node.Type
+		t := v.node.Type
 
-		for j = nfree; j < len(var_); j++ {
-			v1 = inuse[j]
+		for j := nfree; j < len(inuse); j++ {
+			v1 := inuse[j]
 			if debugmerge > 0 && Debug['v'] != 0 {
 				fmt.Printf("consider %v: maybe %v: type=%v,%v addrtaken=%v,%v\n", Nconv(v.node, obj.FmtSharp), Nconv(v1.node, obj.FmtSharp), t, v1.node.Type, v.node.Addrtaken, v1.node.Addrtaken)
 			}
@@ -774,7 +744,7 @@ func mergetemp(firstp *obj.Prog) {
 		}
 
 		// Sort v into inuse.
-		j = ninuse
+		j := ninuse
 		ninuse++
 
 		for j > 0 && inuse[j-1].end < v.end {
@@ -786,16 +756,14 @@ func mergetemp(firstp *obj.Prog) {
 	}
 
 	if debugmerge > 0 && Debug['v'] != 0 {
-		fmt.Printf("%v [%d - %d]\n", Curfn.Func.Nname.Sym, len(var_), nkill)
-		var v *TempVar
-		for i := 0; i < len(var_); i++ {
-			v = &var_[i]
+		fmt.Printf("%v [%d - %d]\n", Curfn.Func.Nname.Sym, len(vars), nkill)
+		for _, v := range vars {
 			fmt.Printf("var %v %v %d-%d", Nconv(v.node, obj.FmtSharp), v.node.Type, v.start, v.end)
-			if v.addr != 0 {
-				fmt.Printf(" addr=1")
+			if v.addr {
+				fmt.Printf(" addr=true")
 			}
-			if v.removed != 0 {
-				fmt.Printf(" dead=1")
+			if v.removed {
+				fmt.Printf(" removed=true")
 			}
 			if v.merge != nil {
 				fmt.Printf(" merge %v", Nconv(v.merge.node, obj.FmtSharp))
@@ -814,16 +782,16 @@ func mergetemp(firstp *obj.Prog) {
 	// Update node references to use merged temporaries.
 	for f := g.Start; f != nil; f = f.Link {
 		p := f.Prog
-		n, _ = p.From.Node.(*Node)
+		n, _ := p.From.Node.(*Node)
 		if n != nil {
-			v, _ = n.Opt().(*TempVar)
+			v, _ := n.Opt().(*TempVar)
 			if v != nil && v.merge != nil {
 				p.From.Node = v.merge.node
 			}
 		}
 		n, _ = p.To.Node.(*Node)
 		if n != nil {
-			v, _ = n.Opt().(*TempVar)
+			v, _ := n.Opt().(*TempVar)
 			if v != nil && v.merge != nil {
 				p.To.Node = v.merge.node
 			}
@@ -831,17 +799,16 @@ func mergetemp(firstp *obj.Prog) {
 	}
 
 	// Delete merged nodes from declaration list.
-	var l *NodeList
 	for lp := &Curfn.Func.Dcl; ; {
-		l = *lp
+		l := *lp
 		if l == nil {
 			break
 		}
 
 		Curfn.Func.Dcl.End = l
-		n = l.N
-		v, _ = n.Opt().(*TempVar)
-		if v != nil && (v.merge != nil || v.removed != 0) {
+		n := l.N
+		v, _ := n.Opt().(*TempVar)
+		if v != nil && (v.merge != nil || v.removed) {
 			*lp = l.Next
 			continue
 		}
@@ -850,8 +817,8 @@ func mergetemp(firstp *obj.Prog) {
 	}
 
 	// Clear aux structures.
-	for i := 0; i < len(var_); i++ {
-		var_[i].node.SetOpt(nil)
+	for _, v := range vars {
+		v.node.SetOpt(nil)
 	}
 
 	Flowend(g)
@@ -932,7 +899,7 @@ func nilopt(firstp *obj.Prog) {
 		return
 	}
 
-	if Debug_checknil > 1 { /* || strcmp(curfn->nname->sym->name, "f1") == 0 */
+	if Debug_checknil > 1 { // || strcmp(curfn->nname->sym->name, "f1") == 0
 		Dumpit("nilopt", g.Start, 0)
 	}
 
diff --git a/src/cmd/compile/internal/gc/racewalk.go b/src/cmd/compile/internal/gc/racewalk.go
index f53e8ec..8a6eba3 100644
--- a/src/cmd/compile/internal/gc/racewalk.go
+++ b/src/cmd/compile/internal/gc/racewalk.go
@@ -9,13 +9,20 @@ import (
 	"strings"
 )
 
-// The racewalk pass modifies the code tree for the function as follows:
+// The instrument pass modifies the code tree for instrumentation.
+//
+// For flag_race it modifies the function as follows:
 //
 // 1. It inserts a call to racefuncenter at the beginning of each function.
 // 2. It inserts a call to racefuncexit at the end of each function.
 // 3. It inserts a call to raceread before each memory read.
 // 4. It inserts a call to racewrite before each memory write.
 //
+// For flag_msan:
+//
+// 1. It inserts a call to msanread before each memory read.
+// 2. It inserts a call to msanwrite before each memory write.
+//
 // The rewriting is not yet complete. Certain nodes are not rewritten
 // but should be.
 
@@ -24,16 +31,16 @@ import (
 
 // Do not instrument the following packages at all,
 // at best instrumentation would cause infinite recursion.
-var omit_pkgs = []string{"runtime", "runtime/race"}
+var omit_pkgs = []string{"runtime/internal/atomic", "runtime/internal/sys", "runtime", "runtime/race", "runtime/msan"}
 
 // Only insert racefuncenter/racefuncexit into the following packages.
 // Memory accesses in the packages are either uninteresting or will cause false positives.
-var noinst_pkgs = []string{"sync", "sync/atomic"}
+var norace_inst_pkgs = []string{"sync", "sync/atomic"}
 
 func ispkgin(pkgs []string) bool {
 	if myimportpath != "" {
-		for i := 0; i < len(pkgs); i++ {
-			if myimportpath == pkgs[i] {
+		for _, p := range pkgs {
+			if myimportpath == p {
 				return true
 			}
 		}
@@ -42,43 +49,35 @@ func ispkgin(pkgs []string) bool {
 	return false
 }
 
-// TODO(rsc): Remove. Put //go:norace on forkAndExecInChild instead.
-func isforkfunc(fn *Node) bool {
-	// Special case for syscall.forkAndExecInChild.
-	// In the child, this function must not acquire any locks, because
-	// they might have been locked at the time of the fork.  This means
-	// no rescheduling, no malloc calls, and no new stack segments.
-	// Race instrumentation does all of the above.
-	return myimportpath != "" && myimportpath == "syscall" && fn.Func.Nname.Sym.Name == "forkAndExecInChild"
-}
-
-func racewalk(fn *Node) {
-	if ispkgin(omit_pkgs) || isforkfunc(fn) || fn.Func.Norace {
+func instrument(fn *Node) {
+	if ispkgin(omit_pkgs) || fn.Func.Norace {
 		return
 	}
 
-	if !ispkgin(noinst_pkgs) {
-		racewalklist(fn.Nbody, nil)
+	if flag_race == 0 || !ispkgin(norace_inst_pkgs) {
+		instrumentlist(fn.Nbody, nil)
 
 		// nothing interesting for race detector in fn->enter
-		racewalklist(fn.Func.Exit, nil)
+		instrumentlist(fn.Func.Exit, nil)
 	}
 
-	// nodpc is the PC of the caller as extracted by
-	// getcallerpc. We use -widthptr(FP) for x86.
-	// BUG: this will not work on arm.
-	nodpc := Nod(OXXX, nil, nil)
-
-	*nodpc = *nodfp
-	nodpc.Type = Types[TUINTPTR]
-	nodpc.Xoffset = int64(-Widthptr)
-	nd := mkcall("racefuncenter", nil, nil, nodpc)
-	fn.Func.Enter = concat(list1(nd), fn.Func.Enter)
-	nd = mkcall("racefuncexit", nil, nil)
-	fn.Func.Exit = list(fn.Func.Exit, nd)
+	if flag_race != 0 {
+		// nodpc is the PC of the caller as extracted by
+		// getcallerpc. We use -widthptr(FP) for x86.
+		// BUG: this will not work on arm.
+		nodpc := Nod(OXXX, nil, nil)
+
+		*nodpc = *nodfp
+		nodpc.Type = Types[TUINTPTR]
+		nodpc.Xoffset = int64(-Widthptr)
+		nd := mkcall("racefuncenter", nil, nil, nodpc)
+		fn.Func.Enter = concat(list1(nd), fn.Func.Enter)
+		nd = mkcall("racefuncexit", nil, nil)
+		fn.Func.Exit = list(fn.Func.Exit, nd)
+	}
 
 	if Debug['W'] != 0 {
-		s := fmt.Sprintf("after racewalk %v", fn.Func.Nname.Sym)
+		s := fmt.Sprintf("after instrument %v", fn.Func.Nname.Sym)
 		dumplist(s, fn.Nbody)
 		s = fmt.Sprintf("enter %v", fn.Func.Nname.Sym)
 		dumplist(s, fn.Func.Enter)
@@ -87,12 +86,12 @@ func racewalk(fn *Node) {
 	}
 }
 
-func racewalklist(l *NodeList, init **NodeList) {
+func instrumentlist(l *NodeList, init **NodeList) {
 	var instr *NodeList
 
 	for ; l != nil; l = l.Next {
 		instr = nil
-		racewalknode(&l.N, &instr, 0, 0)
+		instrumentnode(&l.N, &instr, 0, 0)
 		if init == nil {
 			l.N.Ninit = concat(l.N.Ninit, instr)
 		} else {
@@ -104,7 +103,7 @@ func racewalklist(l *NodeList, init **NodeList) {
 // walkexpr and walkstmt combined
 // walks the tree and adds calls to the
 // instrumentation code to top-level (statement) nodes' init
-func racewalknode(np **Node, init **NodeList, wr int, skip int) {
+func instrumentnode(np **Node, init **NodeList, wr int, skip int) {
 	n := *np
 
 	if n == nil {
@@ -112,39 +111,39 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
 	}
 
 	if Debug['w'] > 1 {
-		Dump("racewalk-before", n)
+		Dump("instrument-before", n)
 	}
 	setlineno(n)
 	if init == nil {
-		Fatal("racewalk: bad init list")
+		Fatalf("instrument: bad init list")
 	}
 	if init == &n.Ninit {
 		// If init == &n->ninit and n->ninit is non-nil,
-		// racewalknode might append it to itself.
+		// instrumentnode might append it to itself.
 		// nil it out and handle it separately before putting it back.
 		l := n.Ninit
 
 		n.Ninit = nil
-		racewalklist(l, nil)
-		racewalknode(&n, &l, wr, skip) // recurse with nil n->ninit
+		instrumentlist(l, nil)
+		instrumentnode(&n, &l, wr, skip) // recurse with nil n->ninit
 		appendinit(&n, l)
 		*np = n
 		return
 	}
 
-	racewalklist(n.Ninit, nil)
+	instrumentlist(n.Ninit, nil)
 
 	switch n.Op {
 	default:
-		Fatal("racewalk: unknown node type %v", Oconv(int(n.Op), 0))
+		Fatalf("instrument: unknown node type %v", Oconv(int(n.Op), 0))
 
 	case OAS, OASWB, OAS2FUNC:
-		racewalknode(&n.Left, init, 1, 0)
-		racewalknode(&n.Right, init, 0, 0)
+		instrumentnode(&n.Left, init, 1, 0)
+		instrumentnode(&n.Right, init, 0, 0)
 		goto ret
 
 		// can't matter
-	case OCFUNC, OVARKILL:
+	case OCFUNC, OVARKILL, OVARLIVE:
 		goto ret
 
 	case OBLOCK:
@@ -152,7 +151,7 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
 		for l := n.List; l != nil; l = l.Next {
 			switch l.N.Op {
 			case OCALLFUNC, OCALLMETH, OCALLINTER:
-				racewalknode(&l.N, &out, 0, 0)
+				instrumentnode(&l.N, &l.N.Ninit, 0, 0)
 				out = list(out, l.N)
 				// Scan past OAS nodes copying results off stack.
 				// Those must not be instrumented, because the
@@ -164,7 +163,7 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
 					out = list(out, l.N)
 				}
 			default:
-				racewalknode(&l.N, &out, 0, 0)
+				instrumentnode(&l.N, &out, 0, 0)
 				out = list(out, l.N)
 			}
 		}
@@ -172,22 +171,22 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
 		goto ret
 
 	case ODEFER:
-		racewalknode(&n.Left, init, 0, 0)
+		instrumentnode(&n.Left, init, 0, 0)
 		goto ret
 
 	case OPROC:
-		racewalknode(&n.Left, init, 0, 0)
+		instrumentnode(&n.Left, init, 0, 0)
 		goto ret
 
 	case OCALLINTER:
-		racewalknode(&n.Left, init, 0, 0)
+		instrumentnode(&n.Left, init, 0, 0)
 		goto ret
 
 		// Instrument dst argument of runtime.writebarrier* calls
 	// as we do not instrument runtime code.
 	// typedslicecopy is instrumented in runtime.
 	case OCALLFUNC:
-		racewalknode(&n.Left, init, 0, 0)
+		instrumentnode(&n.Left, init, 0, 0)
 		goto ret
 
 	case ONOT,
@@ -197,32 +196,32 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
 		OIMAG,
 		OCOM,
 		OSQRT:
-		racewalknode(&n.Left, init, wr, 0)
+		instrumentnode(&n.Left, init, wr, 0)
 		goto ret
 
 	case ODOTINTER:
-		racewalknode(&n.Left, init, 0, 0)
+		instrumentnode(&n.Left, init, 0, 0)
 		goto ret
 
 	case ODOT:
-		racewalknode(&n.Left, init, 0, 1)
+		instrumentnode(&n.Left, init, 0, 1)
 		callinstr(&n, init, wr, skip)
 		goto ret
 
 	case ODOTPTR: // dst = (*x).f with implicit *; otherwise it's ODOT+OIND
-		racewalknode(&n.Left, init, 0, 0)
+		instrumentnode(&n.Left, init, 0, 0)
 
 		callinstr(&n, init, wr, skip)
 		goto ret
 
 	case OIND: // *p
-		racewalknode(&n.Left, init, 0, 0)
+		instrumentnode(&n.Left, init, 0, 0)
 
 		callinstr(&n, init, wr, skip)
 		goto ret
 
 	case OSPTR, OLEN, OCAP:
-		racewalknode(&n.Left, init, 0, 0)
+		instrumentnode(&n.Left, init, 0, 0)
 		if Istype(n.Left.Type, TMAP) {
 			n1 := Nod(OCONVNOP, n.Left, nil)
 			n1.Type = Ptrto(Types[TUINT8])
@@ -251,18 +250,18 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
 		OGT,
 		OADD,
 		OCOMPLEX:
-		racewalknode(&n.Left, init, wr, 0)
-		racewalknode(&n.Right, init, wr, 0)
+		instrumentnode(&n.Left, init, wr, 0)
+		instrumentnode(&n.Right, init, wr, 0)
 		goto ret
 
 	case OANDAND, OOROR:
-		racewalknode(&n.Left, init, wr, 0)
+		instrumentnode(&n.Left, init, wr, 0)
 
 		// walk has ensured the node has moved to a location where
 		// side effects are safe.
 		// n->right may not be executed,
 		// so instrumentation goes to n->right->ninit, not init.
-		racewalknode(&n.Right, &n.Right.Ninit, wr, 0)
+		instrumentnode(&n.Right, &n.Right.Ninit, wr, 0)
 
 		goto ret
 
@@ -271,57 +270,57 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
 		goto ret
 
 	case OCONV:
-		racewalknode(&n.Left, init, wr, 0)
+		instrumentnode(&n.Left, init, wr, 0)
 		goto ret
 
 	case OCONVNOP:
-		racewalknode(&n.Left, init, wr, 0)
+		instrumentnode(&n.Left, init, wr, 0)
 		goto ret
 
 	case ODIV, OMOD:
-		racewalknode(&n.Left, init, wr, 0)
-		racewalknode(&n.Right, init, wr, 0)
+		instrumentnode(&n.Left, init, wr, 0)
+		instrumentnode(&n.Right, init, wr, 0)
 		goto ret
 
 	case OINDEX:
 		if !Isfixedarray(n.Left.Type) {
-			racewalknode(&n.Left, init, 0, 0)
+			instrumentnode(&n.Left, init, 0, 0)
 		} else if !islvalue(n.Left) {
 			// index of unaddressable array, like Map[k][i].
-			racewalknode(&n.Left, init, wr, 0)
+			instrumentnode(&n.Left, init, wr, 0)
 
-			racewalknode(&n.Right, init, 0, 0)
+			instrumentnode(&n.Right, init, 0, 0)
 			goto ret
 		}
 
-		racewalknode(&n.Right, init, 0, 0)
+		instrumentnode(&n.Right, init, 0, 0)
 		if n.Left.Type.Etype != TSTRING {
 			callinstr(&n, init, wr, skip)
 		}
 		goto ret
 
 	case OSLICE, OSLICEARR, OSLICE3, OSLICE3ARR, OSLICESTR:
-		racewalknode(&n.Left, init, 0, 0)
-		racewalknode(&n.Right, init, 0, 0)
+		instrumentnode(&n.Left, init, 0, 0)
+		instrumentnode(&n.Right, init, 0, 0)
 		goto ret
 
 	case OKEY:
-		racewalknode(&n.Left, init, 0, 0)
-		racewalknode(&n.Right, init, 0, 0)
+		instrumentnode(&n.Left, init, 0, 0)
+		instrumentnode(&n.Right, init, 0, 0)
 		goto ret
 
 	case OADDR:
-		racewalknode(&n.Left, init, 0, 1)
+		instrumentnode(&n.Left, init, 0, 1)
 		goto ret
 
 		// n->left is Type* which is not interesting.
 	case OEFACE:
-		racewalknode(&n.Right, init, 0, 0)
+		instrumentnode(&n.Right, init, 0, 0)
 
 		goto ret
 
 	case OITAB:
-		racewalknode(&n.Left, init, 0, 0)
+		instrumentnode(&n.Left, init, 0, 0)
 		goto ret
 
 		// should not appear in AST by now
@@ -365,31 +364,31 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
 		OAS2RECV,
 		OAS2MAPR,
 		OASOP:
-		Yyerror("racewalk: %v must be lowered by now", Oconv(int(n.Op), 0))
+		Yyerror("instrument: %v must be lowered by now", Oconv(int(n.Op), 0))
 
 		goto ret
 
 		// impossible nodes: only appear in backend.
 	case ORROTC, OEXTEND:
-		Yyerror("racewalk: %v cannot exist now", Oconv(int(n.Op), 0))
+		Yyerror("instrument: %v cannot exist now", Oconv(int(n.Op), 0))
 		goto ret
 
 	case OGETG:
-		Yyerror("racewalk: OGETG can happen only in runtime which we don't instrument")
+		Yyerror("instrument: OGETG can happen only in runtime which we don't instrument")
 		goto ret
 
 	case OFOR:
 		if n.Left != nil {
-			racewalknode(&n.Left, &n.Left.Ninit, 0, 0)
+			instrumentnode(&n.Left, &n.Left.Ninit, 0, 0)
 		}
 		if n.Right != nil {
-			racewalknode(&n.Right, &n.Right.Ninit, 0, 0)
+			instrumentnode(&n.Right, &n.Right.Ninit, 0, 0)
 		}
 		goto ret
 
 	case OIF, OSWITCH:
 		if n.Left != nil {
-			racewalknode(&n.Left, &n.Left.Ninit, 0, 0)
+			instrumentnode(&n.Left, &n.Left.Ninit, 0, 0)
 		}
 		goto ret
 
@@ -426,16 +425,17 @@ func racewalknode(np **Node, init **NodeList, wr int, skip int) {
 
 ret:
 	if n.Op != OBLOCK { // OBLOCK is handled above in a special way.
-		racewalklist(n.List, init)
+		instrumentlist(n.List, init)
 	}
-	racewalklist(n.Nbody, nil)
-	racewalklist(n.Rlist, nil)
+	instrumentlist(n.Nbody, nil)
+	instrumentlist(n.Rlist, nil)
 	*np = n
 }
 
 func isartificial(n *Node) bool {
 	// compiler-emitted artificial things that we do not want to instrument,
-	// cant' possibly participate in a data race.
+	// can't possibly participate in a data race.
+	// can't be seen by C/C++ and therefore irrelevant for msan.
 	if n.Op == ONAME && n.Sym != nil && n.Sym.Name != "" {
 		if n.Sym.Name == "_" {
 			return true
@@ -497,13 +497,31 @@ func callinstr(np **Node, init **NodeList, wr int, skip int) bool {
 		n = treecopy(n, 0)
 		makeaddable(n)
 		var f *Node
-		if t.Etype == TSTRUCT || Isfixedarray(t) {
+		if flag_msan != 0 {
+			name := "msanread"
+			if wr != 0 {
+				name = "msanwrite"
+			}
+			// dowidth may not have been called for PEXTERN.
+			dowidth(t)
+			w := t.Width
+			if w == BADWIDTH {
+				Fatalf("instrument: %v badwidth", t)
+			}
+			f = mkcall(name, nil, init, uintptraddr(n), Nodintconst(w))
+		} else if flag_race != 0 && (t.Etype == TSTRUCT || Isfixedarray(t)) {
 			name := "racereadrange"
 			if wr != 0 {
 				name = "racewriterange"
 			}
-			f = mkcall(name, nil, init, uintptraddr(n), Nodintconst(t.Width))
-		} else {
+			// dowidth may not have been called for PEXTERN.
+			dowidth(t)
+			w := t.Width
+			if w == BADWIDTH {
+				Fatalf("instrument: %v badwidth", t)
+			}
+			f = mkcall(name, nil, init, uintptraddr(n), Nodintconst(w))
+		} else if flag_race != 0 {
 			name := "raceread"
 			if wr != 0 {
 				name = "racewrite"
diff --git a/src/cmd/compile/internal/gc/range.go b/src/cmd/compile/internal/gc/range.go
index 26f05d9..4386bcf 100644
--- a/src/cmd/compile/internal/gc/range.go
+++ b/src/cmd/compile/internal/gc/range.go
@@ -6,9 +6,7 @@ package gc
 
 import "cmd/internal/obj"
 
-/*
- * range
- */
+// range
 func typecheckrange(n *Node) {
 	var toomany int
 	var why string
@@ -165,89 +163,12 @@ func walkrange(n *Node) {
 	var init *NodeList
 	switch t.Etype {
 	default:
-		Fatal("walkrange")
-
-		// Lower n into runtime·memclr if possible, for
-	// fast zeroing of slices and arrays (issue 5373).
-	// Look for instances of
-	//
-	// for i := range a {
-	// 	a[i] = zero
-	// }
-	//
-	// in which the evaluation of a is side-effect-free.
+		Fatalf("walkrange")
+
 	case TARRAY:
-		if Debug['N'] == 0 {
-			if flag_race == 0 {
-				if v1 != nil {
-					if v2 == nil {
-						if n.Nbody != nil {
-							if n.Nbody.N != nil { // at least one statement in body
-								if n.Nbody.Next == nil { // at most one statement in body
-									tmp := n.Nbody.N // first statement of body
-									if tmp.Op == OAS {
-										if tmp.Left.Op == OINDEX {
-											if samesafeexpr(tmp.Left.Left, a) {
-												if samesafeexpr(tmp.Left.Right, v1) {
-													if t.Type.Width > 0 {
-														if iszero(tmp.Right) {
-															// Convert to
-															// if len(a) != 0 {
-															// 	hp = &a[0]
-															// 	hn = len(a)*sizeof(elem(a))
-															// 	memclr(hp, hn)
-															// 	i = len(a) - 1
-															// }
-															n.Op = OIF
-
-															n.Nbody = nil
-															n.Left = Nod(ONE, Nod(OLEN, a, nil), Nodintconst(0))
-
-															// hp = &a[0]
-															hp := temp(Ptrto(Types[TUINT8]))
-
-															tmp := Nod(OINDEX, a, Nodintconst(0))
-															tmp.Bounded = true
-															tmp = Nod(OADDR, tmp, nil)
-															tmp = Nod(OCONVNOP, tmp, nil)
-															tmp.Type = Ptrto(Types[TUINT8])
-															n.Nbody = list(n.Nbody, Nod(OAS, hp, tmp))
-
-															// hn = len(a) * sizeof(elem(a))
-															hn := temp(Types[TUINTPTR])
-
-															tmp = Nod(OLEN, a, nil)
-															tmp = Nod(OMUL, tmp, Nodintconst(t.Type.Width))
-															tmp = conv(tmp, Types[TUINTPTR])
-															n.Nbody = list(n.Nbody, Nod(OAS, hn, tmp))
-
-															// memclr(hp, hn)
-															fn := mkcall("memclr", nil, nil, hp, hn)
-
-															n.Nbody = list(n.Nbody, fn)
-
-															// i = len(a) - 1
-															v1 = Nod(OAS, v1, Nod(OSUB, Nod(OLEN, a, nil), Nodintconst(1)))
-
-															n.Nbody = list(n.Nbody, v1)
-
-															typecheck(&n.Left, Erv)
-															typechecklist(n.Nbody, Etop)
-															walkstmt(&n)
-															lineno = int32(lno)
-															return
-														}
-													}
-												}
-											}
-										}
-									}
-								}
-							}
-						}
-					}
-				}
-			}
+		if memclrrange(n, v1, v2, a) {
+			lineno = int32(lno)
+			return
 		}
 
 		// orderstmt arranged for a copy of the array/slice variable if needed.
@@ -404,3 +325,82 @@ func walkrange(n *Node) {
 
 	lineno = int32(lno)
 }
+
+// Lower n into runtime·memclr if possible, for
+// fast zeroing of slices and arrays (issue 5373).
+// Look for instances of
+//
+// for i := range a {
+// 	a[i] = zero
+// }
+//
+// in which the evaluation of a is side-effect-free.
+//
+// Parameters are as in walkrange: "for v1, v2 = range a".
+func memclrrange(n, v1, v2, a *Node) bool {
+	if Debug['N'] != 0 || instrumenting {
+		return false
+	}
+	if v1 == nil || v2 != nil {
+		return false
+	}
+	if n.Nbody == nil || n.Nbody.N == nil || n.Nbody.Next != nil {
+		return false
+	}
+	stmt := n.Nbody.N // only stmt in body
+	if stmt.Op != OAS || stmt.Left.Op != OINDEX {
+		return false
+	}
+	if !samesafeexpr(stmt.Left.Left, a) || !samesafeexpr(stmt.Left.Right, v1) {
+		return false
+	}
+	elemsize := n.Type.Type.Width
+	if elemsize <= 0 || !iszero(stmt.Right) {
+		return false
+	}
+
+	// Convert to
+	// if len(a) != 0 {
+	// 	hp = &a[0]
+	// 	hn = len(a)*sizeof(elem(a))
+	// 	memclr(hp, hn)
+	// 	i = len(a) - 1
+	// }
+	n.Op = OIF
+
+	n.Nbody = nil
+	n.Left = Nod(ONE, Nod(OLEN, a, nil), Nodintconst(0))
+
+	// hp = &a[0]
+	hp := temp(Ptrto(Types[TUINT8]))
+
+	tmp := Nod(OINDEX, a, Nodintconst(0))
+	tmp.Bounded = true
+	tmp = Nod(OADDR, tmp, nil)
+	tmp = Nod(OCONVNOP, tmp, nil)
+	tmp.Type = Ptrto(Types[TUINT8])
+	n.Nbody = list(n.Nbody, Nod(OAS, hp, tmp))
+
+	// hn = len(a) * sizeof(elem(a))
+	hn := temp(Types[TUINTPTR])
+
+	tmp = Nod(OLEN, a, nil)
+	tmp = Nod(OMUL, tmp, Nodintconst(elemsize))
+	tmp = conv(tmp, Types[TUINTPTR])
+	n.Nbody = list(n.Nbody, Nod(OAS, hn, tmp))
+
+	// memclr(hp, hn)
+	fn := mkcall("memclr", nil, nil, hp, hn)
+
+	n.Nbody = list(n.Nbody, fn)
+
+	// i = len(a) - 1
+	v1 = Nod(OAS, v1, Nod(OSUB, Nod(OLEN, a, nil), Nodintconst(1)))
+
+	n.Nbody = list(n.Nbody, v1)
+
+	typecheck(&n.Left, Erv)
+	typechecklist(n.Nbody, Etop)
+	walkstmt(&n)
+	return true
+}
diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go
index 1ac4a03..264955c 100644
--- a/src/cmd/compile/internal/gc/reflect.go
+++ b/src/cmd/compile/internal/gc/reflect.go
@@ -9,100 +9,36 @@ import (
 	"cmd/internal/obj"
 	"fmt"
 	"os"
+	"sort"
 )
 
-/*
- * runtime interface and reflection data structures
- */
+// runtime interface and reflection data structures
 var signatlist *NodeList
 
-func sigcmp(a *Sig, b *Sig) int {
-	i := stringsCompare(a.name, b.name)
-	if i != 0 {
-		return i
+// byMethodNameAndPackagePath sorts method signatures by name, then package path.
+type byMethodNameAndPackagePath []*Sig
+
+func (x byMethodNameAndPackagePath) Len() int      { return len(x) }
+func (x byMethodNameAndPackagePath) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+func (x byMethodNameAndPackagePath) Less(i, j int) bool {
+	return siglt(x[i], x[j])
+}
+
+// siglt reports whether a < b
+func siglt(a, b *Sig) bool {
+	if a.name != b.name {
+		return a.name < b.name
 	}
 	if a.pkg == b.pkg {
-		return 0
+		return false
 	}
 	if a.pkg == nil {
-		return -1
+		return true
 	}
 	if b.pkg == nil {
-		return +1
-	}
-	return stringsCompare(a.pkg.Path, b.pkg.Path)
-}
-
-func lsort(l *Sig, f func(*Sig, *Sig) int) *Sig {
-	if l == nil || l.link == nil {
-		return l
-	}
-
-	l1 := l
-	l2 := l
-	for {
-		l2 = l2.link
-		if l2 == nil {
-			break
-		}
-		l2 = l2.link
-		if l2 == nil {
-			break
-		}
-		l1 = l1.link
-	}
-
-	l2 = l1.link
-	l1.link = nil
-	l1 = lsort(l, f)
-	l2 = lsort(l2, f)
-
-	/* set up lead element */
-	if f(l1, l2) < 0 {
-		l = l1
-		l1 = l1.link
-	} else {
-		l = l2
-		l2 = l2.link
-	}
-
-	le := l
-
-	for {
-		if l1 == nil {
-			for l2 != nil {
-				le.link = l2
-				le = l2
-				l2 = l2.link
-			}
-
-			le.link = nil
-			break
-		}
-
-		if l2 == nil {
-			for l1 != nil {
-				le.link = l1
-				le = l1
-				l1 = l1.link
-			}
-
-			break
-		}
-
-		if f(l1, l2) < 0 {
-			le.link = l1
-			le = l1
-			l1 = l1.link
-		} else {
-			le.link = l2
-			le = l2
-			l2 = l2.link
-		}
+		return false
 	}
-
-	le.link = nil
-	return l
+	return a.pkg.Path < b.pkg.Path
 }
 
 // Builds a type representing a Bucket structure for
@@ -192,7 +128,7 @@ func mapbucket(t *Type) *Type {
 	field = append(field, ovf)
 
 	// link up fields
-	bucket.Noalg = 1
+	bucket.Noalg = true
 	bucket.Local = t.Local
 	bucket.Type = field[0]
 	for n := int32(0); n < int32(len(field)-1); n++ {
@@ -232,7 +168,7 @@ func hmap(t *Type) *Type {
 	field[7] = makefield("overflow", Types[TUNSAFEPTR])
 
 	h := typ(TSTRUCT)
-	h.Noalg = 1
+	h.Noalg = true
 	h.Local = t.Local
 	h.Type = field[0]
 	for n := int32(0); n < int32(len(field)-1); n++ {
@@ -284,7 +220,7 @@ func hiter(t *Type) *Type {
 	// build iterator struct holding the above fields
 	i := typ(TSTRUCT)
 
-	i.Noalg = 1
+	i.Noalg = true
 	i.Type = field[0]
 	for n := int32(0); n < int32(len(field)-1); n++ {
 		field[n].Down = field[n+1]
@@ -299,10 +235,8 @@ func hiter(t *Type) *Type {
 	return i
 }
 
-/*
- * f is method type, with receiver.
- * return function type, receiver as first argument (or not).
- */
+// f is method type, with receiver.
+// return function type, receiver as first argument (or not).
 func methodfunc(f *Type, receiver *Type) *Type {
 	var in *NodeList
 	if receiver != nil {
@@ -335,11 +269,9 @@ func methodfunc(f *Type, receiver *Type) *Type {
 	return t
 }
 
-/*
- * return methods of non-interface type t, sorted by name.
- * generates stub functions as needed.
- */
-func methods(t *Type) *Sig {
+// methods returns the methods of the non-interface type t, sorted by name.
+// Generates stub functions as needed.
+func methods(t *Type) []*Sig {
 	// method type
 	mt := methtype(t, 0)
 
@@ -357,26 +289,22 @@ func methods(t *Type) *Sig {
 
 	// make list of methods for t,
 	// generating code if necessary.
-	var a *Sig
-
-	var this *Type
-	var b *Sig
-	var method *Sym
+	var ms []*Sig
 	for f := mt.Xmethod; f != nil; f = f.Down {
 		if f.Etype != TFIELD {
-			Fatal("methods: not field %v", f)
+			Fatalf("methods: not field %v", f)
 		}
 		if f.Type.Etype != TFUNC || f.Type.Thistuple == 0 {
-			Fatal("non-method on %v method %v %v\n", mt, f.Sym, f)
+			Fatalf("non-method on %v method %v %v\n", mt, f.Sym, f)
 		}
 		if getthisx(f.Type).Type == nil {
-			Fatal("receiver with no type on %v method %v %v\n", mt, f.Sym, f)
+			Fatalf("receiver with no type on %v method %v %v\n", mt, f.Sym, f)
 		}
 		if f.Nointerface {
 			continue
 		}
 
-		method = f.Sym
+		method := f.Sym
 		if method == nil {
 			continue
 		}
@@ -385,7 +313,7 @@ func methods(t *Type) *Sig {
 		// if pointer receiver but non-pointer t and
 		// this is not an embedded pointer inside a struct,
 		// method does not apply.
-		this = getthisx(f.Type).Type.Type
+		this := getthisx(f.Type).Type.Type
 
 		if Isptr[this.Etype] && this.Type == t {
 			continue
@@ -394,85 +322,77 @@ func methods(t *Type) *Sig {
 			continue
 		}
 
-		b = new(Sig)
-		b.link = a
-		a = b
+		var sig Sig
+		ms = append(ms, &sig)
 
-		a.name = method.Name
+		sig.name = method.Name
 		if !exportname(method.Name) {
 			if method.Pkg == nil {
-				Fatal("methods: missing package")
+				Fatalf("methods: missing package")
 			}
-			a.pkg = method.Pkg
+			sig.pkg = method.Pkg
 		}
 
-		a.isym = methodsym(method, it, 1)
-		a.tsym = methodsym(method, t, 0)
-		a.type_ = methodfunc(f.Type, t)
-		a.mtype = methodfunc(f.Type, nil)
+		sig.isym = methodsym(method, it, 1)
+		sig.tsym = methodsym(method, t, 0)
+		sig.type_ = methodfunc(f.Type, t)
+		sig.mtype = methodfunc(f.Type, nil)
 
-		if a.isym.Flags&SymSiggen == 0 {
-			a.isym.Flags |= SymSiggen
+		if sig.isym.Flags&SymSiggen == 0 {
+			sig.isym.Flags |= SymSiggen
 			if !Eqtype(this, it) || this.Width < Types[Tptr].Width {
 				compiling_wrappers = 1
-				genwrapper(it, f, a.isym, 1)
+				genwrapper(it, f, sig.isym, 1)
 				compiling_wrappers = 0
 			}
 		}
 
-		if a.tsym.Flags&SymSiggen == 0 {
-			a.tsym.Flags |= SymSiggen
+		if sig.tsym.Flags&SymSiggen == 0 {
+			sig.tsym.Flags |= SymSiggen
 			if !Eqtype(this, t) {
 				compiling_wrappers = 1
-				genwrapper(t, f, a.tsym, 0)
+				genwrapper(t, f, sig.tsym, 0)
 				compiling_wrappers = 0
 			}
 		}
 	}
 
-	return lsort(a, sigcmp)
+	sort.Sort(byMethodNameAndPackagePath(ms))
+	return ms
 }
 
-/*
- * return methods of interface type t, sorted by name.
- */
-func imethods(t *Type) *Sig {
-	var a *Sig
-	var method *Sym
-	var isym *Sym
-
-	var all *Sig
-	var last *Sig
+// imethods returns the methods of the interface type t, sorted by name.
+func imethods(t *Type) []*Sig {
+	var methods []*Sig
 	for f := t.Type; f != nil; f = f.Down {
 		if f.Etype != TFIELD {
-			Fatal("imethods: not field")
+			Fatalf("imethods: not field")
 		}
 		if f.Type.Etype != TFUNC || f.Sym == nil {
 			continue
 		}
-		method = f.Sym
-		a = new(Sig)
-		a.name = method.Name
+		method := f.Sym
+		var sig = Sig{
+			name: method.Name,
+		}
 		if !exportname(method.Name) {
 			if method.Pkg == nil {
-				Fatal("imethods: missing package")
+				Fatalf("imethods: missing package")
 			}
-			a.pkg = method.Pkg
+			sig.pkg = method.Pkg
 		}
 
-		a.mtype = f.Type
-		a.offset = 0
-		a.type_ = methodfunc(f.Type, nil)
+		sig.mtype = f.Type
+		sig.offset = 0
+		sig.type_ = methodfunc(f.Type, nil)
 
-		if last != nil && sigcmp(last, a) >= 0 {
-			Fatal("sigcmp vs sortinter %s %s", last.name, a.name)
-		}
-		if last == nil {
-			all = a
-		} else {
-			last.link = a
+		if n := len(methods); n > 0 {
+			last := methods[n-1]
+			if !(siglt(last, &sig)) {
+				Fatalf("sigcmp vs sortinter %s %s", last.name, sig.name)
+			}
 		}
-		last = a
+		methods = append(methods, &sig)
 
 		// Compiler can only refer to wrappers for non-blank methods.
 		if isblanksym(method) {
@@ -483,7 +403,7 @@ func imethods(t *Type) *Sig {
 		// IfaceType.Method is not in the reflect data.
 		// Generate the method body, so that compiled
 		// code can refer to it.
-		isym = methodsym(method, t, 0)
+		isym := methodsym(method, t, 0)
 
 		if isym.Flags&SymSiggen == 0 {
 			isym.Flags |= SymSiggen
@@ -491,7 +411,7 @@ func imethods(t *Type) *Sig {
 		}
 	}
 
-	return all
+	return methods
 }
 
 var dimportpath_gopkg *Pkg
@@ -553,13 +473,11 @@ func dgopkgpath(s *Sym, ot int, pkg *Pkg) int {
 	return dsymptr(s, ot, pkg.Pathsym, 0)
 }
 
-/*
- * uncommonType
- * ../../runtime/type.go:/uncommonType
- */
+// uncommonType
+// ../../runtime/type.go:/uncommonType
 func dextratype(sym *Sym, off int, t *Type, ptroff int) int {
 	m := methods(t)
-	if t.Sym == nil && m == nil {
+	if t.Sym == nil && len(m) == 0 {
 		return off
 	}
 
@@ -568,10 +486,8 @@ func dextratype(sym *Sym, off int, t *Type, ptroff int) int {
 
 	dsymptr(sym, ptroff, sym, off)
 
-	n := 0
-	for a := m; a != nil; a = a.link {
+	for _, a := range m {
 		dtypesym(a.type_)
-		n++
 	}
 
 	ot := off
@@ -591,11 +507,12 @@ func dextratype(sym *Sym, off int, t *Type, ptroff int) int {
 	// slice header
 	ot = dsymptr(s, ot, s, ot+Widthptr+2*Widthint)
 
+	n := len(m)
 	ot = duintxx(s, ot, uint64(n), Widthint)
 	ot = duintxx(s, ot, uint64(n), Widthint)
 
 	// methods
-	for a := m; a != nil; a = a.link {
+	for _, a := range m {
 		// method
 		// ../../runtime/type.go:/method
 		ot = dgostringptr(s, ot, a.name)
@@ -707,7 +624,7 @@ func haspointers(t *Type) bool {
 		ret = true
 
 	case TFIELD:
-		Fatal("haspointers: unexpected type, %v", t)
+		Fatalf("haspointers: unexpected type, %v", t)
 	}
 
 	t.Haspointers = 1 + uint8(obj.Bool2int(ret))
@@ -758,21 +675,19 @@ func typeptrdata(t *Type) int64 {
 		return lastPtrField.Width + typeptrdata(lastPtrField.Type)
 
 	default:
-		Fatal("typeptrdata: unexpected type, %v", t)
+		Fatalf("typeptrdata: unexpected type, %v", t)
 		return 0
 	}
 }
 
-/*
- * commonType
- * ../../runtime/type.go:/commonType
- */
+// commonType
+// ../../runtime/type.go:/commonType
 
 var dcommontype_algarray *Sym
 
 func dcommontype(s *Sym, ot int, t *Type) int {
 	if ot != 0 {
-		Fatal("dcommontype %d", ot)
+		Fatalf("dcommontype %d", ot)
 	}
 
 	sizeofAlg := 2 * Widthptr
@@ -794,20 +709,8 @@ func dcommontype(s *Sym, ot int, t *Type) int {
 		sptr = weaktypesym(tptr)
 	}
 
-	// All (non-reflect-allocated) Types share the same zero object.
-	// Each place in the compiler where a pointer to the zero object
-	// might be returned by a runtime call (map access return value,
-	// 2-arg type cast) declares the size of the zerovalue it needs.
-	// The linker magically takes the max of all the sizes.
-	zero := Pkglookup("zerovalue", Runtimepkg)
-
 	gcsym, useGCProg, ptrdata := dgcsym(t)
 
-	// We use size 0 here so we get the pointer to the zero value,
-	// but don't allocate space for the zero value unless we need it.
-	// TODO: how do we get this symbol into bss?  We really want
-	// a read-only bss, but I don't think such a thing exists.
-
 	// ../../pkg/reflect/type.go:/^type.commonType
 	// actual type structure
 	//	type commonType struct {
@@ -823,7 +726,6 @@ func dcommontype(s *Sym, ot int, t *Type) int {
 	//		string        *string
 	//		*extraType
 	//		ptrToThis     *Type
-	//		zero          unsafe.Pointer
 	//	}
 	ot = duintptr(s, ot, uint64(t.Width))
 	ot = duintptr(s, ot, uint64(ptrdata))
@@ -838,7 +740,7 @@ func dcommontype(s *Sym, ot int, t *Type) int {
 		i = 1
 	}
 	if i&(i-1) != 0 {
-		Fatal("invalid alignment %d for %v", t.Align, t)
+		Fatalf("invalid alignment %d for %v", t.Align, t)
 	}
 	ot = duint8(s, ot, t.Align) // align
 	ot = duint8(s, ot, t.Align) // fieldAlign
@@ -876,7 +778,6 @@ func dcommontype(s *Sym, ot int, t *Type) int {
 	ot += Widthptr
 
 	ot = dsymptr(s, ot, sptr, 0) // ptrto type
-	ot = dsymptr(s, ot, zero, 0) // ptr to zero value
 	return ot
 }
 
@@ -918,7 +819,7 @@ func typesymprefix(prefix string, t *Type) *Sym {
 
 func typenamesym(t *Type) *Sym {
 	if t == nil || (Isptr[t.Etype] && t.Type == nil) || isideal(t) {
-		Fatal("typename %v", t)
+		Fatalf("typename %v", t)
 	}
 	s := typesym(t)
 	if s.Def == nil {
@@ -957,10 +858,8 @@ func weaktypesym(t *Type) *Sym {
 	return s
 }
 
-/*
- * Returns 1 if t has a reflexive equality operator.
- * That is, if x==x for all x of type t.
- */
+// isreflexive reports whether t has a reflexive equality operator.
+// That is, if x==x for all x of type t.
 func isreflexive(t *Type) bool {
 	switch t.Etype {
 	case TBOOL,
@@ -991,7 +890,7 @@ func isreflexive(t *Type) bool {
 
 	case TARRAY:
 		if Isslice(t) {
-			Fatal("slice can't be a map key: %v", t)
+			Fatalf("slice can't be a map key: %v", t)
 		}
 		return isreflexive(t.Type)
 
@@ -1001,15 +900,64 @@ func isreflexive(t *Type) bool {
 				return false
 			}
 		}
-
 		return true
 
 	default:
-		Fatal("bad type for map key: %v", t)
+		Fatalf("bad type for map key: %v", t)
 		return false
 	}
 }
 
+// needkeyupdate reports whether map updates with t as a key
+// need the key to be updated.
+func needkeyupdate(t *Type) bool {
+	switch t.Etype {
+	case TBOOL,
+		TINT,
+		TUINT,
+		TINT8,
+		TUINT8,
+		TINT16,
+		TUINT16,
+		TINT32,
+		TUINT32,
+		TINT64,
+		TUINT64,
+		TUINTPTR,
+		TPTR32,
+		TPTR64,
+		TUNSAFEPTR,
+		TCHAN:
+		return false
+
+	case TFLOAT32, // floats can be +0/-0
+		TFLOAT64,
+		TCOMPLEX64,
+		TCOMPLEX128,
+		TINTER,
+		TSTRING: // strings might have smaller backing stores
+		return true
+
+	case TARRAY:
+		if Isslice(t) {
+			Fatalf("slice can't be a map key: %v", t)
+		}
+		return needkeyupdate(t.Type)
+
+	case TSTRUCT:
+		for t1 := t.Type; t1 != nil; t1 = t1.Down {
+			if needkeyupdate(t1.Type) {
+				return true
+			}
+		}
+		return false
+
+	default:
+		Fatalf("bad type for map key: %v", t)
+		return true
+	}
+}
+
 func dtypesym(t *Type) *Sym {
 	// Replace byte, rune aliases with real type.
 	// They've been separate internally to make error messages
@@ -1019,7 +967,7 @@ func dtypesym(t *Type) *Sym {
 	}
 
 	if isideal(t) {
-		Fatal("dtypesym %v", t)
+		Fatalf("dtypesym %v", t)
 	}
 
 	s := typesym(t)
@@ -1041,7 +989,7 @@ func dtypesym(t *Type) *Sym {
 		dupok = obj.DUPOK
 	}
 
-	if compiling_runtime != 0 && (tbase == Types[tbase.Etype] || tbase == bytetype || tbase == runetype || tbase == errortype) { // int, float, etc
+	if myimportpath == "runtime" && (tbase == Types[tbase.Etype] || tbase == bytetype || tbase == runetype || tbase == errortype) { // int, float, etc
 		goto ok
 	}
 
@@ -1059,7 +1007,7 @@ ok:
 	switch t.Etype {
 	default:
 		ot = dcommontype(s, ot, t)
-		xt = ot - 3*Widthptr
+		xt = ot - 2*Widthptr
 
 	case TARRAY:
 		if t.Bound >= 0 {
@@ -1071,7 +1019,7 @@ ok:
 			t2.Bound = -1 // slice
 			s2 := dtypesym(t2)
 			ot = dcommontype(s, ot, t)
-			xt = ot - 3*Widthptr
+			xt = ot - 2*Widthptr
 			ot = dsymptr(s, ot, s1, 0)
 			ot = dsymptr(s, ot, s2, 0)
 			ot = duintptr(s, ot, uint64(t.Bound))
@@ -1080,16 +1028,16 @@ ok:
 			s1 := dtypesym(t.Type)
 
 			ot = dcommontype(s, ot, t)
-			xt = ot - 3*Widthptr
+			xt = ot - 2*Widthptr
 			ot = dsymptr(s, ot, s1, 0)
 		}
 
-		// ../../runtime/type.go:/ChanType
+	// ../../runtime/type.go:/ChanType
 	case TCHAN:
 		s1 := dtypesym(t.Type)
 
 		ot = dcommontype(s, ot, t)
-		xt = ot - 3*Widthptr
+		xt = ot - 2*Widthptr
 		ot = dsymptr(s, ot, s1, 0)
 		ot = duintptr(s, ot, uint64(t.Chan))
 
@@ -1108,7 +1056,7 @@ ok:
 		}
 
 		ot = dcommontype(s, ot, t)
-		xt = ot - 3*Widthptr
+		xt = ot - 2*Widthptr
 		ot = duint8(s, ot, uint8(obj.Bool2int(isddd)))
 
 		// two slice headers: in and out.
@@ -1138,28 +1086,27 @@ ok:
 
 	case TINTER:
 		m := imethods(t)
-		n := 0
-		for a := m; a != nil; a = a.link {
+		n := len(m)
+		for _, a := range m {
 			dtypesym(a.type_)
-			n++
 		}
 
-		// ../../runtime/type.go:/InterfaceType
+		// ../../../runtime/type.go:/InterfaceType
 		ot = dcommontype(s, ot, t)
 
-		xt = ot - 3*Widthptr
+		xt = ot - 2*Widthptr
 		ot = dsymptr(s, ot, s, ot+Widthptr+2*Widthint)
 		ot = duintxx(s, ot, uint64(n), Widthint)
 		ot = duintxx(s, ot, uint64(n), Widthint)
-		for a := m; a != nil; a = a.link {
-			// ../../runtime/type.go:/imethod
+		for _, a := range m {
+			// ../../../runtime/type.go:/imethod
 			ot = dgostringptr(s, ot, a.name)
 
 			ot = dgopkgpath(s, ot, a.pkg)
 			ot = dsymptr(s, ot, dtypesym(a.type_), 0)
 		}
 
-		// ../../runtime/type.go:/MapType
+	// ../../../runtime/type.go:/MapType
 	case TMAP:
 		s1 := dtypesym(t.Down)
 
@@ -1167,7 +1114,7 @@ ok:
 		s3 := dtypesym(mapbucket(t))
 		s4 := dtypesym(hmap(t))
 		ot = dcommontype(s, ot, t)
-		xt = ot - 3*Widthptr
+		xt = ot - 2*Widthptr
 		ot = dsymptr(s, ot, s1, 0)
 		ot = dsymptr(s, ot, s2, 0)
 		ot = dsymptr(s, ot, s3, 0)
@@ -1190,6 +1137,7 @@ ok:
 
 		ot = duint16(s, ot, uint16(mapbucket(t).Width))
 		ot = duint8(s, ot, uint8(obj.Bool2int(isreflexive(t.Down))))
+		ot = duint8(s, ot, uint8(obj.Bool2int(needkeyupdate(t.Down))))
 
 	case TPTR32, TPTR64:
 		if t.Type.Etype == TANY {
@@ -1203,10 +1151,10 @@ ok:
 		s1 := dtypesym(t.Type)
 
 		ot = dcommontype(s, ot, t)
-		xt = ot - 3*Widthptr
+		xt = ot - 2*Widthptr
 		ot = dsymptr(s, ot, s1, 0)
 
-		// ../../runtime/type.go:/StructType
+	// ../../runtime/type.go:/StructType
 	// for security, only the exported fields.
 	case TSTRUCT:
 		n := 0
@@ -1217,7 +1165,7 @@ ok:
 		}
 
 		ot = dcommontype(s, ot, t)
-		xt = ot - 3*Widthptr
+		xt = ot - 2*Widthptr
 		ot = dsymptr(s, ot, s, ot+Widthptr+2*Widthint)
 		ot = duintxx(s, ot, uint64(n), Widthint)
 		ot = duintxx(s, ot, uint64(n), Widthint)
@@ -1232,7 +1180,8 @@ ok:
 				}
 			} else {
 				ot = dgostringptr(s, ot, "")
-				if t1.Type.Sym != nil && t1.Type.Sym.Pkg == builtinpkg {
+				if t1.Type.Sym != nil &&
+					(t1.Type.Sym.Pkg == builtinpkg || !exportname(t1.Type.Sym.Name)) {
 					ot = dgopkgpath(s, ot, localpkg)
 				} else {
 					ot = dgostringptr(s, ot, "")
@@ -1283,8 +1232,7 @@ func dumptypestructs() {
 	var n *Node
 
 	// copy types from externdcl list to signatlist
-	for l := externdcl; l != nil; l = l.Next {
-		n = l.N
+	for _, n := range externdcl {
 		if n.Op != OTYPE {
 			continue
 		}
@@ -1307,7 +1255,7 @@ func dumptypestructs() {
 
 	// generate import strings for imported packages
 	for _, p := range pkgs {
-		if p.Direct != 0 {
+		if p.Direct {
 			dimportpath(p)
 		}
 	}
@@ -1318,8 +1266,8 @@ func dumptypestructs() {
 	// so this is as good as any.
 	// another possible choice would be package main,
 	// but using runtime means fewer copies in .6 files.
-	if compiling_runtime != 0 {
-		for i := 1; i <= TBOOL; i++ {
+	if myimportpath == "runtime" {
+		for i := EType(1); i <= TBOOL; i++ {
 			dtypesym(Ptrto(Types[i]))
 		}
 		dtypesym(Ptrto(Types[TSTRING]))
@@ -1337,6 +1285,9 @@ func dumptypestructs() {
 		if flag_race != 0 {
 			dimportpath(racepkg)
 		}
+		if flag_msan != 0 {
+			dimportpath(msanpkg)
+		}
 		dimportpath(mkpkg("main"))
 	}
 }
@@ -1505,7 +1456,7 @@ func fillptrmask(t *Type, ptrmask []byte) {
 func dgcprog(t *Type) (*Sym, int64) {
 	dowidth(t)
 	if t.Width == BADWIDTH {
-		Fatal("dgcprog: %v badwidth", t)
+		Fatalf("dgcprog: %v badwidth", t)
 	}
 	sym := typesymprefix(".gcprog", t)
 	var p GCProg
@@ -1514,7 +1465,7 @@ func dgcprog(t *Type) (*Sym, int64) {
 	offset := p.w.BitIndex() * int64(Widthptr)
 	p.end()
 	if ptrdata := typeptrdata(t); offset < ptrdata || offset > t.Width {
-		Fatal("dgcprog: %v: offset=%d but ptrdata=%d size=%d", t, offset, ptrdata, t.Width)
+		Fatalf("dgcprog: %v: offset=%d but ptrdata=%d size=%d", t, offset, ptrdata, t.Width)
 	}
 	return sym, offset
 }
@@ -1561,7 +1512,7 @@ func (p *GCProg) emit(t *Type, offset int64) {
 	}
 	switch t.Etype {
 	default:
-		Fatal("GCProg.emit: unexpected type %v", t)
+		Fatalf("GCProg.emit: unexpected type %v", t)
 
 	case TSTRING:
 		p.w.Ptr(offset / int64(Widthptr))
@@ -1577,7 +1528,7 @@ func (p *GCProg) emit(t *Type, offset int64) {
 		}
 		if t.Bound == 0 {
 			// should have been handled by haspointers check above
-			Fatal("GCProg.emit: empty array")
+			Fatalf("GCProg.emit: empty array")
 		}
 
 		// Flatten array-of-array-of-array to just a big array by multiplying counts.
diff --git a/src/cmd/compile/internal/gc/reflect_test.go b/src/cmd/compile/internal/gc/reflect_test.go
new file mode 100644
index 0000000..9e39933
--- /dev/null
+++ b/src/cmd/compile/internal/gc/reflect_test.go
@@ -0,0 +1,47 @@
+// Copyright 2015 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
+
+import (
+	"reflect"
+	"sort"
+	"testing"
+)
+
+func TestSortingByMethodNameAndPackagePath(t *testing.T) {
+	data := []*Sig{
+		&Sig{name: "b", pkg: &Pkg{Path: "abc"}},
+		&Sig{name: "b", pkg: nil},
+		&Sig{name: "c", pkg: nil},
+		&Sig{name: "c", pkg: &Pkg{Path: "uvw"}},
+		&Sig{name: "c", pkg: nil},
+		&Sig{name: "b", pkg: &Pkg{Path: "xyz"}},
+		&Sig{name: "a", pkg: &Pkg{Path: "abc"}},
+		&Sig{name: "b", pkg: nil},
+	}
+	want := []*Sig{
+		&Sig{name: "a", pkg: &Pkg{Path: "abc"}},
+		&Sig{name: "b", pkg: nil},
+		&Sig{name: "b", pkg: nil},
+		&Sig{name: "b", pkg: &Pkg{Path: "abc"}},
+		&Sig{name: "b", pkg: &Pkg{Path: "xyz"}},
+		&Sig{name: "c", pkg: nil},
+		&Sig{name: "c", pkg: nil},
+		&Sig{name: "c", pkg: &Pkg{Path: "uvw"}},
+	}
+	if len(data) != len(want) {
+		t.Fatal("want and data must match")
+	}
+	if reflect.DeepEqual(data, want) {
+		t.Fatal("data must be shuffled")
+	}
+	sort.Sort(byMethodNameAndPackagePath(data))
+	if !reflect.DeepEqual(data, want) {
+		t.Logf("want: %#v", want)
+		t.Logf("data: %#v", data)
+		t.Errorf("sorting failed")
+	}
+
+}
diff --git a/src/cmd/compile/internal/gc/reg.go b/src/cmd/compile/internal/gc/reg.go
index 0fa0535..14dc03b 100644
--- a/src/cmd/compile/internal/gc/reg.go
+++ b/src/cmd/compile/internal/gc/reg.go
@@ -48,7 +48,7 @@ type Var struct {
 	width      int
 	id         int // index in vars
 	name       int8
-	etype      int8
+	etype      EType
 	addr       int8
 }
 
@@ -170,7 +170,7 @@ func setaddrs(bit Bits) {
 
 	for bany(&bit) {
 		// convert each bit to a variable
-		i = bnum(bit)
+		i = bnum(&bit)
 
 		node = vars[i].node
 		n = int(vars[i].name)
@@ -218,10 +218,8 @@ func walkvardef(n *Node, f *Flow, active int) {
 	}
 }
 
-/*
- * add mov b,rn
- * just after r
- */
+// add mov b,rn
+// just after r
 func addmove(r *Flow, bn int, rn int, f int) {
 	p1 := Ctxt.NewProg()
 	Clearp(p1)
@@ -251,7 +249,7 @@ func addmove(r *Flow, bn int, rn int, f int) {
 	p1.As = int16(Thearch.Optoas(OAS, Types[uint8(v.etype)]))
 
 	// TODO(rsc): Remove special case here.
-	if (Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9') && v.etype == TBOOL {
+	if (Thearch.Thechar == '0' || Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9') && v.etype == TBOOL {
 		p1.As = int16(Thearch.Optoas(OAS, Types[TUINT8]))
 	}
 	p1.From.Type = obj.TYPE_REG
@@ -282,9 +280,7 @@ func overlap_reg(o1 int64, w1 int, o2 int64, w2 int) bool {
 }
 
 func mkvar(f *Flow, a *obj.Addr) Bits {
-	/*
-	 * mark registers used
-	 */
+	// mark registers used
 	if a.Type == obj.TYPE_NONE {
 		return zbits
 	}
@@ -306,7 +302,7 @@ func mkvar(f *Flow, a *obj.Addr) Bits {
 		// TODO(rsc): Remove special case here.
 	case obj.TYPE_ADDR:
 		var bit Bits
-		if Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
+		if Thearch.Thechar == '0' || Thearch.Thechar == '5' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
 			goto memcase
 		}
 		a.Type = obj.TYPE_MEM
@@ -351,16 +347,16 @@ func mkvar(f *Flow, a *obj.Addr) Bits {
 	}
 	node = node.Orig
 	if node.Orig != node {
-		Fatal("%v: bad node", Ctxt.Dconv(a))
+		Fatalf("%v: bad node", Ctxt.Dconv(a))
 	}
 	if node.Sym == nil || node.Sym.Name[0] == '.' {
 		return zbits
 	}
-	et := int(a.Etype)
+	et := EType(a.Etype)
 	o := a.Offset
 	w := a.Width
 	if w < 0 {
-		Fatal("bad width %d for %v", w, Ctxt.Dconv(a))
+		Fatalf("bad width %d for %v", w, Ctxt.Dconv(a))
 	}
 
 	flag := 0
@@ -369,7 +365,7 @@ func mkvar(f *Flow, a *obj.Addr) Bits {
 		v = &vars[i]
 		if v.node == node && int(v.name) == n {
 			if v.offset == o {
-				if int(v.etype) == et {
+				if v.etype == et {
 					if int64(v.width) == w {
 						// TODO(rsc): Remove special case for arm here.
 						if flag == 0 || Thearch.Thechar != '5' {
@@ -396,7 +392,7 @@ func mkvar(f *Flow, a *obj.Addr) Bits {
 
 	if nvar >= NVAR {
 		if Debug['w'] > 1 && node != nil {
-			Fatal("variable not optimized: %v", Nconv(node, obj.FmtSharp))
+			Fatalf("variable not optimized: %v", Nconv(node, obj.FmtSharp))
 		}
 		if Debug['v'] > 0 {
 			Warn("variable not optimized: %v", Nconv(node, obj.FmtSharp))
@@ -423,7 +419,7 @@ func mkvar(f *Flow, a *obj.Addr) Bits {
 	v.id = i
 	v.offset = o
 	v.name = int8(n)
-	v.etype = int8(et)
+	v.etype = et
 	v.width = int(w)
 	v.addr = int8(flag) // funny punning
 	v.node = node
@@ -460,7 +456,7 @@ func mkvar(f *Flow, a *obj.Addr) Bits {
 	}
 
 	// Treat values with their address taken as live at calls,
-	// because the garbage collector's liveness analysis in ../gc/plive.c does.
+	// because the garbage collector's liveness analysis in plive.go does.
 	// These must be consistent or else we will elide stores and the garbage
 	// collector will see uninitialized data.
 	// The typical case where our own analysis is out of sync is when the
@@ -473,7 +469,7 @@ func mkvar(f *Flow, a *obj.Addr) Bits {
 	// sets addrtaken, even though it ends up not being actually shared.
 	// If we were better about _ elision, _ = &x would suffice too.
 	// The broader := in a closure problem is mentioned in a comment in
-	// closure.c:/^typecheckclosure and dcl.c:/^oldname.
+	// closure.go:/^typecheckclosure and dcl.go:/^oldname.
 	if node.Addrtaken {
 		v.addr = 1
 	}
@@ -486,12 +482,12 @@ func mkvar(f *Flow, a *obj.Addr) Bits {
 	//
 	// Disable registerization for results if using defer, because the deferred func
 	// might recover and return, causing the current values to be used.
-	if node.Class == PEXTERN || (Hasdefer != 0 && node.Class == PPARAMOUT) {
+	if node.Class == PEXTERN || (hasdefer && node.Class == PPARAMOUT) {
 		v.addr = 1
 	}
 
 	if Debug['R'] != 0 {
-		fmt.Printf("bit=%2d et=%v w=%d+%d %v %v flag=%d\n", i, Econv(int(et), 0), o, w, Nconv(node, obj.FmtSharp), Ctxt.Dconv(a), v.addr)
+		fmt.Printf("bit=%2d et=%v w=%d+%d %v %v flag=%d\n", i, Econv(et), o, w, Nconv(node, obj.FmtSharp), Ctxt.Dconv(a), v.addr)
 	}
 	Ostats.Nvar++
 
@@ -655,7 +651,7 @@ func allreg(b uint64, r *Rgn) uint64 {
 	r.regno = 0
 	switch v.etype {
 	default:
-		Fatal("unknown etype %d/%v", Bitno(b), Econv(int(v.etype), 0))
+		Fatalf("unknown etype %d/%v", Bitno(b), Econv(v.etype))
 
 	case TINT8,
 		TUINT8,
@@ -1036,11 +1032,9 @@ func Dumpit(str string, r0 *Flow, isreg int) {
 func regopt(firstp *obj.Prog) {
 	mergetemp(firstp)
 
-	/*
-	 * control flow is more complicated in generated go code
-	 * than in generated c code.  define pseudo-variables for
-	 * registers, so we have complete register usage information.
-	 */
+	// control flow is more complicated in generated go code
+	// than in generated c code.  define pseudo-variables for
+	// registers, so we have complete register usage information.
 	var nreg int
 	regnames := Thearch.Regnames(&nreg)
 
@@ -1063,12 +1057,10 @@ func regopt(firstp *obj.Prog) {
 	ivar = zbits
 	ovar = zbits
 
-	/*
-	 * pass 1
-	 * build aux data structure
-	 * allocate pcs
-	 * find use and set of variables
-	 */
+	// pass 1
+	// build aux data structure
+	// allocate pcs
+	// find use and set of variables
 	g := Flowstart(firstp, func() interface{} { return new(Reg) })
 	if g == nil {
 		for i := 0; i < nvar; i++ {
@@ -1081,6 +1073,9 @@ func regopt(firstp *obj.Prog) {
 
 	for f := firstf; f != nil; f = f.Link {
 		p := f.Prog
+		// AVARLIVE must be considered a use, do not skip it.
+		// Otherwise the variable will be optimized away,
+		// and the whole point of AVARLIVE is to keep it on the stack.
 		if p.As == obj.AVARDEF || p.As == obj.AVARKILL {
 			continue
 		}
@@ -1120,7 +1115,7 @@ func regopt(firstp *obj.Prog) {
 		// Currently we never generate three register forms.
 		// If we do, this will need to change.
 		if p.From3Type() != obj.TYPE_NONE {
-			Fatal("regopt not implemented for from3")
+			Fatalf("regopt not implemented for from3")
 		}
 
 		bit = mkvar(f, &p.To)
@@ -1151,7 +1146,7 @@ func regopt(firstp *obj.Prog) {
 		}
 
 		if Debug['R'] != 0 && Debug['v'] != 0 {
-			fmt.Printf("bit=%2d addr=%d et=%v w=%-2d s=%v + %d\n", i, v.addr, Econv(int(v.etype), 0), v.width, v.node, v.offset)
+			fmt.Printf("bit=%2d addr=%d et=%v w=%-2d s=%v + %d\n", i, v.addr, Econv(v.etype), v.width, v.node, v.offset)
 		}
 	}
 
@@ -1159,23 +1154,19 @@ func regopt(firstp *obj.Prog) {
 		Dumpit("pass1", firstf, 1)
 	}
 
-	/*
-	 * pass 2
-	 * find looping structure
-	 */
+	// pass 2
+	// find looping structure
 	flowrpo(g)
 
 	if Debug['R'] != 0 && Debug['v'] != 0 {
 		Dumpit("pass2", firstf, 1)
 	}
 
-	/*
-	 * pass 2.5
-	 * iterate propagating fat vardef covering forward
-	 * r->act records vars with a VARDEF since the last CALL.
-	 * (r->act will be reused in pass 5 for something else,
-	 * but we'll be done with it by then.)
-	 */
+	// pass 2.5
+	// iterate propagating fat vardef covering forward
+	// r->act records vars with a VARDEF since the last CALL.
+	// (r->act will be reused in pass 5 for something else,
+	// but we'll be done with it by then.)
 	active := 0
 
 	for f := firstf; f != nil; f = f.Link {
@@ -1192,11 +1183,9 @@ func regopt(firstp *obj.Prog) {
 		}
 	}
 
-	/*
-	 * pass 3
-	 * iterate propagating usage
-	 * 	back until flow graph is complete
-	 */
+	// pass 3
+	// iterate propagating usage
+	// 	back until flow graph is complete
 	var f1 *Flow
 	var i int
 	var f *Flow
@@ -1212,7 +1201,7 @@ loop1:
 		}
 	}
 
-	/* pick up unreachable code */
+	// pick up unreachable code
 loop11:
 	i = 0
 
@@ -1235,11 +1224,9 @@ loop11:
 		Dumpit("pass3", firstf, 1)
 	}
 
-	/*
-	 * pass 4
-	 * iterate propagating register/variable synchrony
-	 * 	forward until graph is complete
-	 */
+	// pass 4
+	// iterate propagating register/variable synchrony
+	// 	forward until graph is complete
 loop2:
 	change = 0
 
@@ -1255,10 +1242,8 @@ loop2:
 		Dumpit("pass4", firstf, 1)
 	}
 
-	/*
-	 * pass 4.5
-	 * move register pseudo-variables into regu.
-	 */
+	// pass 4.5
+	// move register pseudo-variables into regu.
 	mask := uint64((1 << uint(nreg)) - 1)
 	for f := firstf; f != nil; f = f.Link {
 		r := f.Data.(*Reg)
@@ -1278,23 +1263,21 @@ loop2:
 		Dumpit("pass4.5", firstf, 1)
 	}
 
-	/*
-	 * pass 5
-	 * isolate regions
-	 * calculate costs (paint1)
-	 */
+	// pass 5
+	// isolate regions
+	// calculate costs (paint1)
 	var bit Bits
 	if f := firstf; f != nil {
 		r := f.Data.(*Reg)
 		for z := 0; z < BITS; z++ {
 			bit.b[z] = (r.refahead.b[z] | r.calahead.b[z]) &^ (externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z])
 		}
-		if bany(&bit) && f.Refset == 0 {
+		if bany(&bit) && !f.Refset {
 			// should never happen - all variables are preset
 			if Debug['w'] != 0 {
 				fmt.Printf("%v: used and not set: %v\n", f.Prog.Line(), &bit)
 			}
-			f.Refset = 1
+			f.Refset = true
 		}
 	}
 
@@ -1309,11 +1292,11 @@ loop2:
 		for z := 0; z < BITS; z++ {
 			bit.b[z] = r.set.b[z] &^ (r.refahead.b[z] | r.calahead.b[z] | addrs.b[z])
 		}
-		if bany(&bit) && f.Refset == 0 {
+		if bany(&bit) && !f.Refset {
 			if Debug['w'] != 0 {
 				fmt.Printf("%v: set and not used: %v\n", f.Prog.Line(), &bit)
 			}
-			f.Refset = 1
+			f.Refset = true
 			Thearch.Excise(f)
 		}
 
@@ -1321,7 +1304,7 @@ loop2:
 			bit.b[z] = LOAD(r, z) &^ (r.act.b[z] | addrs.b[z])
 		}
 		for bany(&bit) {
-			i = bnum(bit)
+			i = bnum(&bit)
 			change = 0
 			paint1(f, i)
 			biclr(&bit, uint(i))
@@ -1358,11 +1341,9 @@ loop2:
 		Dumpit("pass5", firstf, 1)
 	}
 
-	/*
-	 * pass 6
-	 * determine used registers (paint2)
-	 * replace code (paint3)
-	 */
+	// pass 6
+	// determine used registers (paint2)
+	// replace code (paint3)
 	if Debug['R'] != 0 && Debug['v'] != 0 {
 		fmt.Printf("\nregisterizing\n")
 	}
@@ -1379,16 +1360,14 @@ loop2:
 		if rgp.regno != 0 {
 			if Debug['R'] != 0 && Debug['v'] != 0 {
 				v := &vars[rgp.varno]
-				fmt.Printf("registerize %v+%d (bit=%2d et=%v) in %v usedreg=%#x vreg=%#x\n", v.node, v.offset, rgp.varno, Econv(int(v.etype), 0), obj.Rconv(int(rgp.regno)), usedreg, vreg)
+				fmt.Printf("registerize %v+%d (bit=%2d et=%v) in %v usedreg=%#x vreg=%#x\n", v.node, v.offset, rgp.varno, Econv(v.etype), obj.Rconv(int(rgp.regno)), usedreg, vreg)
 			}
 
 			paint3(rgp.enter, int(rgp.varno), vreg, int(rgp.regno))
 		}
 	}
 
-	/*
-	 * free aux structures. peep allocates new ones.
-	 */
+	// free aux structures. peep allocates new ones.
 	for i := 0; i < nvar; i++ {
 		vars[i].node.SetOpt(nil)
 	}
@@ -1404,17 +1383,13 @@ loop2:
 		firstf = nil
 	}
 
-	/*
-	 * pass 7
-	 * peep-hole on basic block
-	 */
+	// pass 7
+	// peep-hole on basic block
 	if Debug['R'] == 0 || Debug['P'] != 0 {
 		Thearch.Peep(firstp)
 	}
 
-	/*
-	 * eliminate nops
-	 */
+	// eliminate nops
 	for p := firstp; p != nil; p = p.Link {
 		for p.Link != nil && p.Link.As == obj.ANOP {
 			p.Link = p.Link.Link
@@ -1465,14 +1440,14 @@ func bany(a *Bits) bool {
 }
 
 // bnum reports the lowest index of a 1 bit in a.
-func bnum(a Bits) int {
+func bnum(a *Bits) int {
 	for i, x := range &a.b { // & to avoid making a copy of a.b
 		if x != 0 {
 			return 64*i + Bitno(x)
 		}
 	}
 
-	Fatal("bad in bnum")
+	Fatalf("bad in bnum")
 	return 0
 }
 
@@ -1499,10 +1474,10 @@ func biclr(a *Bits, n uint) {
 }
 
 // Bitno reports the lowest index of a 1 bit in b.
-// It calls Fatal if there is no 1 bit.
+// It calls Fatalf if there is no 1 bit.
 func Bitno(b uint64) int {
 	if b == 0 {
-		Fatal("bad in bitno")
+		Fatalf("bad in bitno")
 	}
 	n := 0
 	if b&(1<<32-1) == 0 {
@@ -1541,7 +1516,7 @@ func (bits Bits) String() string {
 	var buf bytes.Buffer
 	sep := ""
 	for bany(&bits) {
-		i := bnum(bits)
+		i := bnum(&bits)
 		buf.WriteString(sep)
 		sep = " "
 		v := &vars[i]
diff --git a/src/cmd/compile/internal/gc/select.go b/src/cmd/compile/internal/gc/select.go
index db20778..e770c8f 100644
--- a/src/cmd/compile/internal/gc/select.go
+++ b/src/cmd/compile/internal/gc/select.go
@@ -4,9 +4,7 @@
 
 package gc
 
-/*
- * select
- */
+// select
 func typecheckselect(sel *Node) {
 	var ncase *Node
 	var n *Node
@@ -20,7 +18,7 @@ func typecheckselect(sel *Node) {
 		ncase = l.N
 		setlineno(ncase)
 		if ncase.Op != OXCASE {
-			Fatal("typecheckselect %v", Oconv(int(ncase.Op), 0))
+			Fatalf("typecheckselect %v", Oconv(int(ncase.Op), 0))
 		}
 
 		if ncase.List == nil {
@@ -90,7 +88,7 @@ func typecheckselect(sel *Node) {
 
 func walkselect(sel *Node) {
 	if sel.List == nil && sel.Xoffset != 0 {
-		Fatal("double walkselect") // already rewrote
+		Fatalf("double walkselect") // already rewrote
 	}
 
 	lno := int(setlineno(sel))
@@ -109,7 +107,7 @@ func walkselect(sel *Node) {
 	}
 
 	// optimization: one-case select: single op.
-	// TODO(rsc): Reenable optimization once order.c can handle it.
+	// TODO(rsc): Reenable optimization once order.go can handle it.
 	// golang.org/issue/7672.
 	if i == 1 {
 		cas := sel.List.N
@@ -122,7 +120,7 @@ func walkselect(sel *Node) {
 			var ch *Node
 			switch n.Op {
 			default:
-				Fatal("select %v", Oconv(int(n.Op), 0))
+				Fatalf("select %v", Oconv(int(n.Op), 0))
 
 				// ok already
 			case OSEND:
@@ -218,7 +216,7 @@ func walkselect(sel *Node) {
 		r.Ninit = cas.Ninit
 		switch n.Op {
 		default:
-			Fatal("select %v", Oconv(int(n.Op), 0))
+			Fatalf("select %v", Oconv(int(n.Op), 0))
 
 			// if selectnbsend(c, v) { body } else { default body }
 		case OSEND:
@@ -284,7 +282,7 @@ func walkselect(sel *Node) {
 		} else {
 			switch n.Op {
 			default:
-				Fatal("select %v", Oconv(int(n.Op), 0))
+				Fatalf("select %v", Oconv(int(n.Op), 0))
 
 				// selectsend(sel *byte, hchan *chan any, elem *any) (selected bool);
 			case OSEND:
@@ -335,7 +333,7 @@ func selecttype(size int32) *Type {
 	sudog.List = list(sudog.List, Nod(ODCLFIELD, newname(Lookup("nrelease")), typenod(Types[TINT32])))
 	sudog.List = list(sudog.List, Nod(ODCLFIELD, newname(Lookup("waitlink")), typenod(Ptrto(Types[TUINT8]))))
 	typecheck(&sudog, Etype)
-	sudog.Type.Noalg = 1
+	sudog.Type.Noalg = true
 	sudog.Type.Local = true
 
 	scase := Nod(OTSTRUCT, nil, nil)
@@ -347,7 +345,7 @@ func selecttype(size int32) *Type {
 	scase.List = list(scase.List, Nod(ODCLFIELD, newname(Lookup("receivedp")), typenod(Ptrto(Types[TUINT8]))))
 	scase.List = list(scase.List, Nod(ODCLFIELD, newname(Lookup("releasetime")), typenod(Types[TUINT64])))
 	typecheck(&scase, Etype)
-	scase.Type.Noalg = 1
+	scase.Type.Noalg = true
 	scase.Type.Local = true
 
 	sel := Nod(OTSTRUCT, nil, nil)
@@ -362,7 +360,7 @@ func selecttype(size int32) *Type {
 	arr = Nod(OTARRAY, Nodintconst(int64(size)), typenod(Types[TUINT16]))
 	sel.List = list(sel.List, Nod(ODCLFIELD, newname(Lookup("pollorderarr")), arr))
 	typecheck(&sel, Etype)
-	sel.Type.Noalg = 1
+	sel.Type.Noalg = true
 	sel.Type.Local = true
 
 	return sel.Type
diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go
index 0ced4ef..b7f7ea0 100644
--- a/src/cmd/compile/internal/gc/sinit.go
+++ b/src/cmd/compile/internal/gc/sinit.go
@@ -9,9 +9,7 @@ import (
 	"fmt"
 )
 
-/*
- * static initialization
- */
+// static initialization
 const (
 	InitNotStarted = 0
 	InitDone       = 1
@@ -19,7 +17,7 @@ const (
 )
 
 var (
-	initlist  *NodeList
+	initlist  []*Node
 	initplans map[*Node]*InitPlan
 	inittemps = make(map[*Node]*Node)
 )
@@ -47,15 +45,12 @@ func init1(n *Node, out **NodeList) {
 	}
 	switch n.Class {
 	case PEXTERN, PFUNC:
-		break
-
 	default:
 		if isblank(n) && n.Name.Curfn == nil && n.Name.Defn != nil && n.Name.Defn.Initorder == InitNotStarted {
 			// blank names initialization is part of init() but not
 			// when they are inside a function.
 			break
 		}
-
 		return
 	}
 
@@ -72,90 +67,43 @@ func init1(n *Node, out **NodeList) {
 		// Conversely, if there exists an initialization cycle involving
 		// a variable in the program, the tree walk will reach a cycle
 		// involving that variable.
-		var nv *Node
 		if n.Class != PFUNC {
-			nv = n
-			goto foundinitloop
+			foundinitloop(n, n)
 		}
 
-		for l := initlist; l.N != n; l = l.Next {
-			if l.N.Class != PFUNC {
-				nv = l.N
-				goto foundinitloop
+		for i := len(initlist) - 1; i >= 0; i-- {
+			x := initlist[i]
+			if x == n {
+				break
+			}
+			if x.Class != PFUNC {
+				foundinitloop(n, x)
 			}
 		}
 
 		// The loop involves only functions, ok.
 		return
-
-		// if there have already been errors printed,
-		// those errors probably confused us and
-		// there might not be a loop.  let the user
-		// fix those first.
-	foundinitloop:
-		Flusherrors()
-
-		if nerrors > 0 {
-			errorexit()
-		}
-
-		// There is a loop involving nv. We know about
-		// n and initlist = n1 <- ... <- nv <- ... <- n <- ...
-		fmt.Printf("%v: initialization loop:\n", nv.Line())
-
-		// Build back pointers in initlist.
-		for l := initlist; l != nil; l = l.Next {
-			if l.Next != nil {
-				l.Next.End = l
-			}
-		}
-
-		// Print nv -> ... -> n1 -> n.
-		var l *NodeList
-		for l = initlist; l.N != nv; l = l.Next {
-		}
-		for ; l != nil; l = l.End {
-			fmt.Printf("\t%v %v refers to\n", l.N.Line(), l.N.Sym)
-		}
-
-		// Print n -> ... -> nv.
-		for l = initlist; l.N != n; l = l.Next {
-		}
-		for ; l.N != nv; l = l.End {
-			fmt.Printf("\t%v %v refers to\n", l.N.Line(), l.N.Sym)
-		}
-		fmt.Printf("\t%v %v\n", nv.Line(), nv.Sym)
-		errorexit()
 	}
 
 	// reached a new unvisited node.
 	n.Initorder = InitPending
-
-	l := new(NodeList)
-	if l == nil {
-		Flusherrors()
-		Yyerror("out of memory")
-		errorexit()
-	}
-
-	l.Next = initlist
-	l.N = n
-	l.End = nil
-	initlist = l
+	initlist = append(initlist, n)
 
 	// make sure that everything n depends on is initialized.
 	// n->defn is an assignment to n
 	if defn := n.Name.Defn; defn != nil {
 		switch defn.Op {
 		default:
-			goto bad
+			Dump("defn", defn)
+			Fatalf("init1: bad defn")
 
 		case ODCLFUNC:
 			init2list(defn.Nbody, out)
 
 		case OAS:
 			if defn.Left != n {
-				goto bad
+				Dump("defn", defn)
+				Fatalf("init1: bad defn")
 			}
 			if isblank(defn.Left) && candiscard(defn.Right) {
 				defn.Op = OEMPTY
@@ -176,10 +124,10 @@ func init1(n *Node, out **NodeList) {
 			}
 
 		case OAS2FUNC, OAS2MAPR, OAS2DOTTYPE, OAS2RECV:
-			if defn.Initorder != InitNotStarted {
+			if defn.Initorder == InitDone {
 				break
 			}
-			defn.Initorder = InitDone
+			defn.Initorder = InitPending
 			for l := defn.Rlist; l != nil; l = l.Next {
 				init1(l.N, out)
 			}
@@ -187,21 +135,55 @@ func init1(n *Node, out **NodeList) {
 				Dump("nonstatic", defn)
 			}
 			*out = list(*out, defn)
+			defn.Initorder = InitDone
 		}
 	}
 
-	l = initlist
-	initlist = l.Next
-	if l.N != n {
-		Fatal("bad initlist")
+	last := len(initlist) - 1
+	if initlist[last] != n {
+		Fatalf("bad initlist %v", initlist)
 	}
+	initlist[last] = nil // allow GC
+	initlist = initlist[:last]
 
 	n.Initorder = InitDone
 	return
+}
+
+// foundinitloop prints an init loop error and exits.
+func foundinitloop(node, visited *Node) {
+	// If there have already been errors printed,
+	// those errors probably confused us and
+	// there might not be a loop. Let the user
+	// fix those first.
+	Flusherrors()
+	if nerrors > 0 {
+		errorexit()
+	}
+
+	// Find the index of node and visited in the initlist.
+	var nodeindex, visitedindex int
+	for ; initlist[nodeindex] != node; nodeindex++ {
+	}
+	for ; initlist[visitedindex] != visited; visitedindex++ {
+	}
+
+	// There is a loop involving visited. We know about node and
+	// initlist = n1 <- ... <- visited <- ... <- node <- ...
+	fmt.Printf("%v: initialization loop:\n", visited.Line())
+
+	// Print visited -> ... -> n1 -> node.
+	for _, n := range initlist[visitedindex:] {
+		fmt.Printf("\t%v %v refers to\n", n.Line(), n.Sym)
+	}
+
+	// Print node -> ... -> visited.
+	for _, n := range initlist[nodeindex:visitedindex] {
+		fmt.Printf("\t%v %v refers to\n", n.Line(), n.Sym)
+	}
 
-bad:
-	Dump("defn", n.Name.Defn)
-	Fatal("init1: bad defn")
+	fmt.Printf("\t%v %v\n", visited.Line(), visited.Sym)
+	errorexit()
 }
 
 // recurse over n, doing init1 everywhere.
@@ -211,7 +193,7 @@ func init2(n *Node, out **NodeList) {
 	}
 
 	if n.Op == ONAME && n.Ninit != nil {
-		Fatal("name %v with ninit: %v\n", n.Sym, Nconv(n, obj.FmtSign))
+		Fatalf("name %v with ninit: %v\n", n.Sym, Nconv(n, obj.FmtSign))
 	}
 
 	init1(n, out)
@@ -265,13 +247,11 @@ func initfix(l *NodeList) *NodeList {
 	return lout
 }
 
-/*
- * compilation of top-level (static) assignments
- * into DATA statements if at all possible.
- */
+// compilation of top-level (static) assignments
+// into DATA statements if at all possible.
 func staticinit(n *Node, out **NodeList) bool {
 	if n.Op != ONAME || n.Class != PEXTERN || n.Name.Defn == nil || n.Name.Defn.Op != OAS {
-		Fatal("staticinit")
+		Fatalf("staticinit")
 	}
 
 	lineno = n.Lineno
@@ -346,13 +326,13 @@ func staticcopy(l *Node, r *Node, out **NodeList) bool {
 			// copy slice
 			a := inittemps[r]
 
-			n1 := *l
-			n1.Xoffset = l.Xoffset + int64(Array_array)
-			gdata(&n1, Nod(OADDR, a, nil), Widthptr)
-			n1.Xoffset = l.Xoffset + int64(Array_nel)
-			gdata(&n1, r.Right, Widthint)
-			n1.Xoffset = l.Xoffset + int64(Array_cap)
-			gdata(&n1, r.Right, Widthint)
+			n := *l
+			n.Xoffset = l.Xoffset + int64(Array_array)
+			gdata(&n, Nod(OADDR, a, nil), Widthptr)
+			n.Xoffset = l.Xoffset + int64(Array_nel)
+			gdata(&n, r.Right, Widthint)
+			n.Xoffset = l.Xoffset + int64(Array_cap)
+			gdata(&n, r.Right, Widthint)
 			return true
 		}
 		fallthrough
@@ -361,24 +341,21 @@ func staticcopy(l *Node, r *Node, out **NodeList) bool {
 	case OSTRUCTLIT:
 		p := initplans[r]
 
-		n1 := *l
-		var e *InitEntry
-		var ll *Node
-		var rr *Node
-		for i := 0; i < len(p.E); i++ {
-			e = &p.E[i]
-			n1.Xoffset = l.Xoffset + e.Xoffset
-			n1.Type = e.Expr.Type
+		n := *l
+		for i := range p.E {
+			e := &p.E[i]
+			n.Xoffset = l.Xoffset + e.Xoffset
+			n.Type = e.Expr.Type
 			if e.Expr.Op == OLITERAL {
-				gdata(&n1, e.Expr, int(n1.Type.Width))
+				gdata(&n, e.Expr, int(n.Type.Width))
 			} else {
-				ll = Nod(OXXX, nil, nil)
-				*ll = n1
+				ll := Nod(OXXX, nil, nil)
+				*ll = n
 				ll.Orig = ll // completely separate copy
 				if !staticassign(ll, e.Expr, out) {
 					// Requires computation, but we're
 					// copying someone else's computation.
-					rr = Nod(OXXX, nil, nil)
+					rr := Nod(OXXX, nil, nil)
 
 					*rr = *orig
 					rr.Orig = rr // completely separate copy
@@ -397,17 +374,11 @@ func staticcopy(l *Node, r *Node, out **NodeList) bool {
 }
 
 func staticassign(l *Node, r *Node, out **NodeList) bool {
-	var n1 Node
-
 	for r.Op == OCONVNOP {
 		r = r.Left
 	}
 
 	switch r.Op {
-	//dump("not static", r);
-	default:
-		break
-
 	case ONAME:
 		return staticcopy(l, r, out)
 
@@ -421,21 +392,17 @@ func staticassign(l *Node, r *Node, out **NodeList) bool {
 	case OADDR:
 		var nam Node
 		if stataddr(&nam, r.Left) {
-			n1 := *r
-			n1.Left = &nam
-			gdata(l, &n1, int(l.Type.Width))
+			n := *r
+			n.Left = &nam
+			gdata(l, &n, int(l.Type.Width))
 			return true
 		}
 		fallthrough
 
 	case OPTRLIT:
 		switch r.Left.Op {
-		//dump("not static ptrlit", r);
-		default:
-			break
-
-			// Init pointer.
 		case OARRAYLIT, OMAPLIT, OSTRUCTLIT:
+			// Init pointer.
 			a := staticname(r.Left.Type, 1)
 
 			inittemps[r] = a
@@ -447,6 +414,7 @@ func staticassign(l *Node, r *Node, out **NodeList) bool {
 			}
 			return true
 		}
+		//dump("not static ptrlit", r);
 
 	case OSTRARRAYBYTE:
 		if l.Class == PEXTERN && r.Left.Op == OLITERAL {
@@ -465,37 +433,34 @@ func staticassign(l *Node, r *Node, out **NodeList) bool {
 			ta.Bound = Mpgetfix(r.Right.Val().U.(*Mpint))
 			a := staticname(ta, 1)
 			inittemps[r] = a
-			n1 = *l
-			n1.Xoffset = l.Xoffset + int64(Array_array)
-			gdata(&n1, Nod(OADDR, a, nil), Widthptr)
-			n1.Xoffset = l.Xoffset + int64(Array_nel)
-			gdata(&n1, r.Right, Widthint)
-			n1.Xoffset = l.Xoffset + int64(Array_cap)
-			gdata(&n1, r.Right, Widthint)
+			n := *l
+			n.Xoffset = l.Xoffset + int64(Array_array)
+			gdata(&n, Nod(OADDR, a, nil), Widthptr)
+			n.Xoffset = l.Xoffset + int64(Array_nel)
+			gdata(&n, r.Right, Widthint)
+			n.Xoffset = l.Xoffset + int64(Array_cap)
+			gdata(&n, r.Right, Widthint)
 
 			// Fall through to init underlying array.
 			l = a
 		}
 		fallthrough
 
-		// fall through
 	case OSTRUCTLIT:
 		initplan(r)
 
 		p := initplans[r]
-		n1 = *l
-		var e *InitEntry
-		var a *Node
-		for i := 0; i < len(p.E); i++ {
-			e = &p.E[i]
-			n1.Xoffset = l.Xoffset + e.Xoffset
-			n1.Type = e.Expr.Type
+		n := *l
+		for i := range p.E {
+			e := &p.E[i]
+			n.Xoffset = l.Xoffset + e.Xoffset
+			n.Type = e.Expr.Type
 			if e.Expr.Op == OLITERAL {
-				gdata(&n1, e.Expr, int(n1.Type.Width))
+				gdata(&n, e.Expr, int(n.Type.Width))
 			} else {
 				setlineno(e.Expr)
-				a = Nod(OXXX, nil, nil)
-				*a = n1
+				a := Nod(OXXX, nil, nil)
+				*a = n
 				a.Orig = a // completely separate copy
 				if !staticassign(a, e.Expr, out) {
 					*out = list(*out, Nod(OAS, a, e.Expr))
@@ -505,21 +470,29 @@ func staticassign(l *Node, r *Node, out **NodeList) bool {
 
 		return true
 
-		// TODO: Table-driven map insert.
 	case OMAPLIT:
+		// TODO: Table-driven map insert.
 		break
+
+	case OCLOSURE:
+		if r.Func.Cvars == nil {
+			// Closures with no captured variables are globals,
+			// so the assignment can be done at link time.
+			n := *l
+			gdata(&n, r.Func.Closure.Func.Nname, Widthptr)
+			return true
+		}
 	}
 
+	//dump("not static", r);
 	return false
 }
 
-/*
- * from here down is the walk analysis
- * of composite literals.
- * most of the work is to generate
- * data statements for the constant
- * part of the composite literal.
- */
+// from here down is the walk analysis
+// of composite literals.
+// most of the work is to generate
+// data statements for the constant
+// part of the composite literal.
 func staticname(t *Type, ctxt int) *Node {
 	n := newname(Lookupf("statictmp_%.4d", statuniqgen))
 	statuniqgen++
@@ -586,9 +559,8 @@ func getdyn(n *Node, top int) int {
 		break
 	}
 
-	var value *Node
 	for nl := n.List; nl != nil; nl = nl.Next {
-		value = nl.N.Right
+		value := nl.N.Right
 		mode |= getdyn(value, 0)
 		if mode == MODEDYNAM|MODECONST {
 			break
@@ -599,18 +571,15 @@ func getdyn(n *Node, top int) int {
 }
 
 func structlit(ctxt int, pass int, n *Node, var_ *Node, init **NodeList) {
-	var r *Node
-	var a *Node
-	var index *Node
-	var value *Node
-
 	for nl := n.List; nl != nil; nl = nl.Next {
-		r = nl.N
+		r := nl.N
 		if r.Op != OKEY {
-			Fatal("structlit: rhs not OKEY: %v", r)
+			Fatalf("structlit: rhs not OKEY: %v", r)
 		}
-		index = r.Left
-		value = r.Right
+		index := r.Left
+		value := r.Right
+
+		var a *Node
 
 		switch value.Op {
 		case OARRAYLIT:
@@ -654,7 +623,7 @@ func structlit(ctxt int, pass int, n *Node, var_ *Node, init **NodeList) {
 		if pass == 1 {
 			walkexpr(&a, init) // add any assignments in r to top
 			if a.Op != OAS {
-				Fatal("structlit: not as")
+				Fatalf("structlit: not as")
 			}
 			a.Dodata = 2
 		} else {
@@ -667,18 +636,15 @@ func structlit(ctxt int, pass int, n *Node, var_ *Node, init **NodeList) {
 }
 
 func arraylit(ctxt int, pass int, n *Node, var_ *Node, init **NodeList) {
-	var r *Node
-	var a *Node
-	var index *Node
-	var value *Node
-
 	for l := n.List; l != nil; l = l.Next {
-		r = l.N
+		r := l.N
 		if r.Op != OKEY {
-			Fatal("arraylit: rhs not OKEY: %v", r)
+			Fatalf("arraylit: rhs not OKEY: %v", r)
 		}
-		index = r.Left
-		value = r.Right
+		index := r.Left
+		value := r.Right
+
+		var a *Node
 
 		switch value.Op {
 		case OARRAYLIT:
@@ -722,7 +688,7 @@ func arraylit(ctxt int, pass int, n *Node, var_ *Node, init **NodeList) {
 		if pass == 1 {
 			walkexpr(&a, init)
 			if a.Op != OAS {
-				Fatal("arraylit: not as")
+				Fatalf("arraylit: not as")
 			}
 			a.Dodata = 2
 		} else {
@@ -796,7 +762,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init **NodeList) {
 	// set auto to point at new temp or heap (3 assign)
 	var a *Node
 	if x := prealloc[n]; x != nil {
-		// temp allocated during order.c for dddarg
+		// temp allocated during order.go for dddarg
 		x.Type = t
 
 		if vstat == nil {
@@ -845,17 +811,14 @@ func slicelit(ctxt int, n *Node, var_ *Node, init **NodeList) {
 	*init = list(*init, a)
 
 	// put dynamics into slice (6)
-	var value *Node
-	var r *Node
-	var index *Node
 	for l := n.List; l != nil; l = l.Next {
-		r = l.N
+		r := l.N
 		if r.Op != OKEY {
-			Fatal("slicelit: rhs not OKEY: %v", r)
+			Fatalf("slicelit: rhs not OKEY: %v", r)
 		}
-		index = r.Left
-		value = r.Right
-		a = Nod(OINDEX, var_, index)
+		index := r.Left
+		value := r.Right
+		a := Nod(OINDEX, var_, index)
 		a.Bounded = true
 
 		// TODO need to check bounds?
@@ -889,10 +852,6 @@ func slicelit(ctxt int, n *Node, var_ *Node, init **NodeList) {
 }
 
 func maplit(ctxt int, n *Node, var_ *Node, init **NodeList) {
-	var r *Node
-	var index *Node
-	var value *Node
-
 	ctxt = 0
 
 	// make the map var
@@ -906,13 +865,12 @@ func maplit(ctxt int, n *Node, var_ *Node, init **NodeList) {
 	b := int64(0)
 
 	for l := n.List; l != nil; l = l.Next {
-		r = l.N
-
+		r := l.N
 		if r.Op != OKEY {
-			Fatal("maplit: rhs not OKEY: %v", r)
+			Fatalf("maplit: rhs not OKEY: %v", r)
 		}
-		index = r.Left
-		value = r.Right
+		index := r.Left
+		value := r.Right
 
 		if isliteral(index) && isliteral(value) {
 			b++
@@ -953,17 +911,14 @@ func maplit(ctxt int, n *Node, var_ *Node, init **NodeList) {
 		vstat := staticname(t, ctxt)
 
 		b := int64(0)
-		var index *Node
-		var r *Node
-		var value *Node
 		for l := n.List; l != nil; l = l.Next {
-			r = l.N
+			r := l.N
 
 			if r.Op != OKEY {
-				Fatal("maplit: rhs not OKEY: %v", r)
+				Fatalf("maplit: rhs not OKEY: %v", r)
 			}
-			index = r.Left
-			value = r.Right
+			index := r.Left
+			value := r.Right
 
 			if isliteral(index) && isliteral(value) {
 				// build vstat[b].a = key;
@@ -998,13 +953,13 @@ func maplit(ctxt int, n *Node, var_ *Node, init **NodeList) {
 		// for i = 0; i < len(vstat); i++ {
 		//	map[vstat[i].a] = vstat[i].b
 		// }
-		index = temp(Types[TINT])
+		index := temp(Types[TINT])
 
 		a = Nod(OINDEX, vstat, index)
 		a.Bounded = true
 		a = Nod(ODOT, a, newname(symb))
 
-		r = Nod(OINDEX, vstat, index)
+		r := Nod(OINDEX, vstat, index)
 		r.Bounded = true
 		r = Nod(ODOT, r, newname(syma))
 		r = Nod(OINDEX, var_, r)
@@ -1028,13 +983,13 @@ func maplit(ctxt int, n *Node, var_ *Node, init **NodeList) {
 
 	var val *Node
 	for l := n.List; l != nil; l = l.Next {
-		r = l.N
+		r := l.N
 
 		if r.Op != OKEY {
-			Fatal("maplit: rhs not OKEY: %v", r)
+			Fatalf("maplit: rhs not OKEY: %v", r)
 		}
-		index = r.Left
-		value = r.Right
+		index := r.Left
+		value := r.Right
 
 		if isliteral(index) && isliteral(value) {
 			continue
@@ -1083,11 +1038,11 @@ func anylit(ctxt int, n *Node, var_ *Node, init **NodeList) {
 	t := n.Type
 	switch n.Op {
 	default:
-		Fatal("anylit: not lit")
+		Fatalf("anylit: not lit")
 
 	case OPTRLIT:
 		if !Isptr[t.Etype] {
-			Fatal("anylit: not ptr")
+			Fatalf("anylit: not ptr")
 		}
 
 		var r *Node
@@ -1113,7 +1068,7 @@ func anylit(ctxt int, n *Node, var_ *Node, init **NodeList) {
 
 	case OSTRUCTLIT:
 		if t.Etype != TSTRUCT {
-			Fatal("anylit: not struct")
+			Fatalf("anylit: not struct")
 		}
 
 		if simplename(var_) && count(n.List) > 4 {
@@ -1153,7 +1108,7 @@ func anylit(ctxt int, n *Node, var_ *Node, init **NodeList) {
 
 	case OARRAYLIT:
 		if t.Etype != TARRAY {
-			Fatal("anylit: not array")
+			Fatalf("anylit: not array")
 		}
 		if t.Bound < 0 {
 			slicelit(ctxt, n, var_, init)
@@ -1197,7 +1152,7 @@ func anylit(ctxt int, n *Node, var_ *Node, init **NodeList) {
 
 	case OMAPLIT:
 		if t.Etype != TMAP {
-			Fatal("anylit: not map")
+			Fatalf("anylit: not map")
 		}
 		maplit(ctxt, n, var_, init)
 	}
@@ -1304,34 +1259,31 @@ func initplan(n *Node) {
 	initplans[n] = p
 	switch n.Op {
 	default:
-		Fatal("initplan")
+		Fatalf("initplan")
 
 	case OARRAYLIT:
-		var a *Node
 		for l := n.List; l != nil; l = l.Next {
-			a = l.N
+			a := l.N
 			if a.Op != OKEY || !Smallintconst(a.Left) {
-				Fatal("initplan arraylit")
+				Fatalf("initplan arraylit")
 			}
 			addvalue(p, n.Type.Type.Width*Mpgetfix(a.Left.Val().U.(*Mpint)), nil, a.Right)
 		}
 
 	case OSTRUCTLIT:
-		var a *Node
 		for l := n.List; l != nil; l = l.Next {
-			a = l.N
+			a := l.N
 			if a.Op != OKEY || a.Left.Type == nil {
-				Fatal("initplan structlit")
+				Fatalf("initplan structlit")
 			}
 			addvalue(p, a.Left.Type.Width, nil, a.Right)
 		}
 
 	case OMAPLIT:
-		var a *Node
 		for l := n.List; l != nil; l = l.Next {
-			a = l.N
+			a := l.N
 			if a.Op != OKEY {
-				Fatal("initplan maplit")
+				Fatalf("initplan maplit")
 			}
 			addvalue(p, -1, a.Left, a.Right)
 		}
@@ -1349,13 +1301,11 @@ func addvalue(p *InitPlan, xoffset int64, key *Node, n *Node) {
 	if isvaluelit(n) {
 		initplan(n)
 		q := initplans[n]
-		var e *InitEntry
-		for i := 0; i < len(q.E); i++ {
-			e = entry(p)
-			*e = q.E[i]
+		for _, qe := range q.E {
+			e := entry(p)
+			*e = qe
 			e.Xoffset += xoffset
 		}
-
 		return
 	}
 
@@ -1377,7 +1327,7 @@ func iszero(n *Node) bool {
 		switch n.Val().Ctype() {
 		default:
 			Dump("unexpected literal", n)
-			Fatal("iszero")
+			Fatalf("iszero")
 
 		case CTNIL:
 			return true
@@ -1544,7 +1494,7 @@ func gen_as_init(n *Node) bool {
 no:
 	if n.Dodata == 2 {
 		Dump("\ngen_as_init", n)
-		Fatal("gen_as_init couldnt make data statement")
+		Fatalf("gen_as_init couldnt make data statement")
 	}
 
 	return false
diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go
index 866d8e1..0d25ddf 100644
--- a/src/cmd/compile/internal/gc/subr.go
+++ b/src/cmd/compile/internal/gc/subr.go
@@ -34,10 +34,6 @@ func errorexit() {
 }
 
 func parserline() int {
-	if parsing && theparser.Lookahead() > 0 {
-		// parser has one symbol lookahead
-		return int(prevlineno)
-	}
 	return int(lineno)
 }
 
@@ -59,26 +55,21 @@ func adderr(line int, format string, args ...interface{}) {
 	})
 }
 
+// errcmp sorts errors by line, then seq, then message.
 type errcmp []Error
 
-func (x errcmp) Len() int {
-	return len(x)
-}
-
-func (x errcmp) Swap(i, j int) {
-	x[i], x[j] = x[j], x[i]
-}
-
+func (x errcmp) Len() int      { return len(x) }
+func (x errcmp) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
 func (x errcmp) Less(i, j int) bool {
 	a := &x[i]
 	b := &x[j]
 	if a.lineno != b.lineno {
-		return a.lineno-b.lineno < 0
+		return a.lineno < b.lineno
 	}
 	if a.seq != b.seq {
-		return a.seq-b.seq < 0
+		return a.seq < b.seq
 	}
-	return stringsCompare(a.msg, b.msg) < 0
+	return a.msg < b.msg
 }
 
 func Flusherrors() {
@@ -86,7 +77,7 @@ func Flusherrors() {
 	if len(errors) == 0 {
 		return
 	}
-	sort.Sort(errcmp(errors[:len(errors)]))
+	sort.Sort(errcmp(errors))
 	for i := 0; i < len(errors); i++ {
 		if i == 0 || errors[i].msg != errors[i-1].msg {
 			fmt.Printf("%s", errors[i].msg)
@@ -127,7 +118,7 @@ func Yyerror(format string, args ...interface{}) {
 
 		// An unexpected EOF caused a syntax error. Use the previous
 		// line number since getc generated a fake newline character.
-		if curio.eofnl != 0 {
+		if curio.eofnl {
 			lexlineno = prevlineno
 		}
 
@@ -143,16 +134,6 @@ func Yyerror(format string, args ...interface{}) {
 			return
 		}
 
-		// The grammar has { and LBRACE but both show up as {.
-		// Rewrite syntax error referring to "{ or {" to say just "{".
-		// The grammar has ? and @ but only for reading imports.
-		// Silence them in ordinary errors.
-		msg = strings.Replace(msg, "{ or {", "{", -1)
-		msg = strings.Replace(msg, " or ?", "", -1)
-		msg = strings.Replace(msg, " or @", "", -1)
-
-		msg = strings.Replace(msg, "LLITERAL", litbuf, -1)
-
 		yyerrorl(int(lexlineno), "%s", msg)
 		return
 	}
@@ -181,7 +162,7 @@ func Warnl(line int, fmt_ string, args ...interface{}) {
 	}
 }
 
-func Fatal(fmt_ string, args ...interface{}) {
+func Fatalf(fmt_ string, args ...interface{}) {
 	Flusherrors()
 
 	fmt.Printf("%v: internal compiler error: ", Ctxt.Line(int(lineno)))
@@ -339,7 +320,7 @@ func importdot(opkg *Pkg, pack *Node) {
 		s1.Block = s.Block
 		if s1.Def.Name == nil {
 			Dump("s1def", s1.Def)
-			Fatal("missing Name")
+			Fatalf("missing Name")
 		}
 		s1.Def.Name.Pack = pack
 		s1.Origpkg = opkg
@@ -352,26 +333,9 @@ func importdot(opkg *Pkg, pack *Node) {
 	}
 }
 
-func gethunk() {
-	nh := int32(NHUNK)
-	if thunk >= 10*NHUNK {
-		nh = 10 * NHUNK
-	}
-	h := string(make([]byte, nh))
-	if h == "" {
-		Flusherrors()
-		Yyerror("out of memory")
-		errorexit()
-	}
-
-	hunk = h
-	nhunk = nh
-	thunk += nh
-}
-
-func Nod(op int, nleft *Node, nright *Node) *Node {
+func Nod(op Op, nleft *Node, nright *Node) *Node {
 	n := new(Node)
-	n.Op = uint8(op)
+	n.Op = op
 	n.Left = nleft
 	n.Right = nright
 	n.Lineno = int32(parserline())
@@ -404,7 +368,7 @@ func saveorignode(n *Node) {
 	if n.Orig != nil {
 		return
 	}
-	norig := Nod(int(n.Op), nil, nil)
+	norig := Nod(n.Op, nil, nil)
 	*norig = *n
 	n.Orig = norig
 }
@@ -414,7 +378,7 @@ func saveorignode(n *Node) {
 // the last field, total gives the size of the enclosing struct.
 func ispaddedfield(t *Type, total int64) bool {
 	if t.Etype != TFIELD {
-		Fatal("ispaddedfield called non-field %v", t)
+		Fatalf("ispaddedfield called non-field %v", t)
 	}
 	if t.Down == nil {
 		return t.Width+t.Type.Width != total
@@ -426,10 +390,10 @@ func algtype1(t *Type, bad **Type) int {
 	if bad != nil {
 		*bad = nil
 	}
-	if t.Broke != 0 {
+	if t.Broke {
 		return AMEM
 	}
-	if t.Noalg != 0 {
+	if t.Noalg {
 		return ANOEQ
 	}
 
@@ -530,7 +494,7 @@ func algtype1(t *Type, bad **Type) int {
 		return ret
 	}
 
-	Fatal("algtype1: unexpected type %v", t)
+	Fatalf("algtype1: unexpected type %v", t)
 	return 0
 }
 
@@ -568,11 +532,11 @@ func maptype(key *Type, val *Type) *Type {
 	if key != nil {
 		var bad *Type
 		atype := algtype1(key, &bad)
-		var mtype int
+		var mtype EType
 		if bad == nil {
-			mtype = int(key.Etype)
+			mtype = key.Etype
 		} else {
-			mtype = int(bad.Etype)
+			mtype = bad.Etype
 		}
 		switch mtype {
 		default:
@@ -603,25 +567,20 @@ func maptype(key *Type, val *Type) *Type {
 	return t
 }
 
-func typ(et int) *Type {
+func typ(et EType) *Type {
 	t := new(Type)
-	t.Etype = uint8(et)
+	t.Etype = et
 	t.Width = BADWIDTH
 	t.Lineno = int(lineno)
 	t.Orig = t
 	return t
 }
 
+// methcmp sorts by symbol, then by package path for unexported symbols.
 type methcmp []*Type
 
-func (x methcmp) Len() int {
-	return len(x)
-}
-
-func (x methcmp) Swap(i, j int) {
-	x[i], x[j] = x[j], x[i]
-}
-
+func (x methcmp) Len() int      { return len(x) }
+func (x methcmp) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
 func (x methcmp) Less(i, j int) bool {
 	a := x[i]
 	b := x[j]
@@ -632,16 +591,14 @@ func (x methcmp) Less(i, j int) bool {
 		return true
 	}
 	if b.Sym == nil {
-		return 1 < 0
+		return false
 	}
-	k := stringsCompare(a.Sym.Name, b.Sym.Name)
-	if k != 0 {
-		return k < 0
+	if a.Sym.Name != b.Sym.Name {
+		return a.Sym.Name < b.Sym.Name
 	}
 	if !exportname(a.Sym.Name) {
-		k := stringsCompare(a.Sym.Pkg.Path, b.Sym.Pkg.Path)
-		if k != 0 {
-			return k < 0
+		if a.Sym.Pkg.Path != b.Sym.Pkg.Path {
+			return a.Sym.Pkg.Path < b.Sym.Pkg.Path
 		}
 	}
 
@@ -653,29 +610,19 @@ func sortinter(t *Type) *Type {
 		return t
 	}
 
-	i := 0
+	var a []*Type
 	for f := t.Type; f != nil; f = f.Down {
-		i++
-	}
-	a := make([]*Type, i)
-	i = 0
-	var f *Type
-	for f = t.Type; f != nil; f = f.Down {
-		a[i] = f
-		i++
+		a = append(a, f)
 	}
-	sort.Sort(methcmp(a[:i]))
-	for {
-		tmp11 := i
-		i--
-		if tmp11 <= 0 {
-			break
-		}
-		a[i].Down = f
-		f = a[i]
+	sort.Sort(methcmp(a))
+
+	n := len(a) // n > 0 due to initial conditions.
+	for i := 0; i < n-1; i++ {
+		a[i].Down = a[i+1]
 	}
+	a[n-1].Down = nil
 
-	t.Type = f
+	t.Type = a[0]
 	return t
 }
 
@@ -709,7 +656,7 @@ func Nodconst(n *Node, t *Type, v int64) {
 	n.Type = t
 
 	if Isfloat[t.Etype] {
-		Fatal("nodconst: bad type %v", t)
+		Fatalf("nodconst: bad type %v", t)
 	}
 }
 
@@ -775,7 +722,7 @@ func treecopy(n *Node, lineno int32) *Node {
 		}
 		if m.Name != nil && n.Op != ODCLFIELD {
 			Dump("treecopy", n)
-			Fatal("treecopy Name")
+			Fatalf("treecopy Name")
 		}
 
 	case ONONAME:
@@ -803,20 +750,14 @@ func treecopy(n *Node, lineno int32) *Node {
 	return m
 }
 
+// isnil reports whether n represents the universal untyped zero value "nil".
 func isnil(n *Node) bool {
-	if n == nil {
-		return false
-	}
-	if n.Op != OLITERAL {
-		return false
-	}
-	if n.Val().Ctype() != CTNIL {
-		return false
-	}
-	return true
+	// Check n.Orig because constant propagation may produce typed nil constants,
+	// which don't exist in the Go spec.
+	return Isconst(n.Orig, CTNIL)
 }
 
-func isptrto(t *Type, et int) bool {
+func isptrto(t *Type, et EType) bool {
 	if t == nil {
 		return false
 	}
@@ -827,14 +768,14 @@ func isptrto(t *Type, et int) bool {
 	if t == nil {
 		return false
 	}
-	if int(t.Etype) != et {
+	if t.Etype != et {
 		return false
 	}
 	return true
 }
 
-func Istype(t *Type, et int) bool {
-	return t != nil && int(t.Etype) == et
+func Istype(t *Type, et EType) bool {
+	return t != nil && t.Etype == et
 }
 
 func Isfixedarray(t *Type) bool {
@@ -885,10 +826,8 @@ func isideal(t *Type) bool {
 	return false
 }
 
-/*
- * given receiver of type t (t == r or t == *r)
- * return type to hang methods off (r).
- */
+// given receiver of type t (t == r or t == *r)
+// return type to hang methods off (r).
 func methtype(t *Type, mustname int) *Type {
 	if t == nil {
 		return nil
@@ -929,7 +868,7 @@ func methtype(t *Type, mustname int) *Type {
 	return t
 }
 
-func cplxsubtype(et int) int {
+func cplxsubtype(et EType) EType {
 	switch et {
 	case TCOMPLEX64:
 		return TFLOAT32
@@ -938,7 +877,7 @@ func cplxsubtype(et int) int {
 		return TFLOAT64
 	}
 
-	Fatal("cplxsubtype: %v\n", Econv(int(et), 0))
+	Fatalf("cplxsubtype: %v\n", Econv(et))
 	return 0
 }
 
@@ -1010,7 +949,7 @@ func eqtype1(t1 *Type, t2 *Type, assumed_equal *TypePairList) bool {
 		t2 = t2.Type
 		for ; t1 != nil && t2 != nil; t1, t2 = t1.Down, t2.Down {
 			if t1.Etype != TFIELD || t2.Etype != TFIELD {
-				Fatal("struct/interface missing field: %v %v", t1, t2)
+				Fatalf("struct/interface missing field: %v %v", t1, t2)
 			}
 			if t1.Sym != t2.Sym || t1.Embedded != t2.Embedded || !eqtype1(t1.Type, t2.Type, &l) || !eqnote(t1.Note, t2.Note) {
 				return false
@@ -1028,7 +967,7 @@ func eqtype1(t1 *Type, t2 *Type, assumed_equal *TypePairList) bool {
 		t2 = t2.Type
 		for ; t1 != nil && t2 != nil; t1, t2 = t1.Down, t2.Down {
 			if t1.Etype != TSTRUCT || t2.Etype != TSTRUCT {
-				Fatal("func missing struct: %v %v", t1, t2)
+				Fatalf("func missing struct: %v %v", t1, t2)
 			}
 
 			// Loop over fields in structs, ignoring argument names.
@@ -1036,7 +975,7 @@ func eqtype1(t1 *Type, t2 *Type, assumed_equal *TypePairList) bool {
 			tb := t2.Type
 			for ; ta != nil && tb != nil; ta, tb = ta.Down, tb.Down {
 				if ta.Etype != TFIELD || tb.Etype != TFIELD {
-					Fatal("func struct missing field: %v %v", ta, tb)
+					Fatalf("func struct missing field: %v %v", ta, tb)
 				}
 				if ta.Isddd != tb.Isddd || !eqtype1(ta.Type, tb.Type, &l) {
 					return false
@@ -1095,7 +1034,7 @@ func eqtypenoname(t1 *Type, t2 *Type) bool {
 // Is type src assignment compatible to type dst?
 // If so, return op code to use in conversion.
 // If not, return 0.
-func assignop(src *Type, dst *Type, why *string) int {
+func assignop(src *Type, dst *Type, why *string) Op {
 	if why != nil {
 		*why = ""
 	}
@@ -1138,7 +1077,7 @@ func assignop(src *Type, dst *Type, why *string) int {
 		}
 
 		// we'll have complained about this method anyway, suppress spurious messages.
-		if have != nil && have.Sym == missing.Sym && (have.Type.Broke != 0 || missing.Type.Broke != 0) {
+		if have != nil && have.Sym == missing.Sym && (have.Type.Broke || missing.Type.Broke) {
 			return OCONVIFACE
 		}
 
@@ -1219,7 +1158,7 @@ func assignop(src *Type, dst *Type, why *string) int {
 // Can we convert a value of type src to a value of type dst?
 // If so, return op code to use in conversion (maybe OCONVNOP).
 // If not, return 0.
-func convertop(src *Type, dst *Type, why *string) int {
+func convertop(src *Type, dst *Type, why *string) Op {
 	if why != nil {
 		*why = ""
 	}
@@ -1322,7 +1261,7 @@ func assignconv(n *Node, t *Type, context string) *Node {
 
 // Convert node n for assignment to type t.
 func assignconvfn(n *Node, t *Type, context func() string) *Node {
-	if n == nil || n.Type == nil || n.Type.Broke != 0 {
+	if n == nil || n.Type == nil || n.Type.Broke {
 		return n
 	}
 
@@ -1378,7 +1317,7 @@ func substArgTypes(n *Node, types ...*Type) {
 	}
 	substAny(&n.Type, &types)
 	if len(types) > 0 {
-		Fatal("substArgTypes: too many argument types")
+		Fatalf("substArgTypes: too many argument types")
 	}
 }
 
@@ -1390,9 +1329,9 @@ func substAny(tp **Type, types *[]*Type) {
 		if t == nil {
 			return
 		}
-		if t.Etype == TANY && t.Copyany != 0 {
+		if t.Etype == TANY && t.Copyany {
 			if len(*types) == 0 {
-				Fatal("substArgTypes: not enough argument types")
+				Fatalf("substArgTypes: not enough argument types")
 			}
 			*tp = (*types)[0]
 			*types = (*types)[1:]
@@ -1422,9 +1361,7 @@ func substAny(tp **Type, types *[]*Type) {
 	}
 }
 
-/*
- * Is this a 64-bit type?
- */
+// Is this a 64-bit type?
 func Is64(t *Type) bool {
 	if t == nil {
 		return false
@@ -1437,12 +1374,10 @@ func Is64(t *Type) bool {
 	return false
 }
 
-/*
- * Is a conversion between t1 and t2 a no-op?
- */
+// Is a conversion between t1 and t2 a no-op?
 func Noconv(t1 *Type, t2 *Type) bool {
-	e1 := int(Simtype[t1.Etype])
-	e2 := int(Simtype[t2.Etype])
+	e1 := Simtype[t1.Etype]
+	e2 := Simtype[t2.Etype]
 
 	switch e1 {
 	case TINT8, TUINT8:
@@ -1491,7 +1426,7 @@ func deep(t *Type) *Type {
 
 	case TANY:
 		nt = shallow(t)
-		nt.Copyany = 1
+		nt.Copyany = true
 
 	case TPTR32, TPTR64, TCHAN, TARRAY:
 		nt = shallow(t)
@@ -1526,7 +1461,7 @@ func deep(t *Type) *Type {
 func syslook(name string, copy int) *Node {
 	s := Pkglookup(name, Runtimepkg)
 	if s == nil || s.Def == nil {
-		Fatal("syslook: can't find runtime.%s", name)
+		Fatalf("syslook: can't find runtime.%s", name)
 	}
 
 	if copy == 0 {
@@ -1540,18 +1475,16 @@ func syslook(name string, copy int) *Node {
 	return n
 }
 
-/*
- * compute a hash value for type t.
- * if t is a method type, ignore the receiver
- * so that the hash can be used in interface checks.
- * %T already contains
- * all the necessary logic to generate a representation
- * of the type that completely describes it.
- * using smprint here avoids duplicating that code.
- * using md5 here is overkill, but i got tired of
- * accidental collisions making the runtime think
- * two types are equal when they really aren't.
- */
+// compute a hash value for type t.
+// if t is a method type, ignore the receiver
+// so that the hash can be used in interface checks.
+// %T already contains
+// all the necessary logic to generate a representation
+// of the type that completely describes it.
+// using smprint here avoids duplicating that code.
+// using md5 here is overkill, but i got tired of
+// accidental collisions making the runtime think
+// two types are equal when they really aren't.
 func typehash(t *Type) uint32 {
 	var p string
 
@@ -1600,7 +1533,7 @@ func ptrto1(t *Type) *Type {
 // The returned struct must not be modified.
 func Ptrto(t *Type) *Type {
 	if Tptr == 0 {
-		Fatal("ptrto: no tptr")
+		Fatalf("ptrto: no tptr")
 	}
 	// Reduce allocations by pre-creating common cases.
 	if !initPtrtoDone {
@@ -1623,42 +1556,39 @@ func Ptrto(t *Type) *Type {
 }
 
 func frame(context int) {
-	var l *NodeList
-
 	if context != 0 {
 		fmt.Printf("--- external frame ---\n")
-		l = externdcl
-	} else if Curfn != nil {
-		fmt.Printf("--- %v frame ---\n", Curfn.Func.Nname.Sym)
-		l = Curfn.Func.Dcl
-	} else {
+		for _, n := range externdcl {
+			printframenode(n)
+		}
 		return
 	}
 
-	var n *Node
-	var w int64
-	for ; l != nil; l = l.Next {
-		n = l.N
-		w = -1
-		if n.Type != nil {
-			w = n.Type.Width
+	if Curfn != nil {
+		fmt.Printf("--- %v frame ---\n", Curfn.Func.Nname.Sym)
+		for l := Curfn.Func.Dcl; l != nil; l = l.Next {
+			printframenode(l.N)
 		}
-		switch n.Op {
-		case ONAME:
-			fmt.Printf("%v %v G%d %v width=%d\n", Oconv(int(n.Op), 0), n.Sym, n.Name.Vargen, n.Type, w)
+	}
+}
 
-		case OTYPE:
-			fmt.Printf("%v %v width=%d\n", Oconv(int(n.Op), 0), n.Type, w)
-		}
+func printframenode(n *Node) {
+	w := int64(-1)
+	if n.Type != nil {
+		w = n.Type.Width
+	}
+	switch n.Op {
+	case ONAME:
+		fmt.Printf("%v %v G%d %v width=%d\n", Oconv(int(n.Op), 0), n.Sym, n.Name.Vargen, n.Type, w)
+	case OTYPE:
+		fmt.Printf("%v %v width=%d\n", Oconv(int(n.Op), 0), n.Type, w)
 	}
 }
 
-/*
- * calculate sethi/ullman number
- * roughly how many registers needed to
- * compile a node. used to compile the
- * hardest side first to minimize registers.
- */
+// calculate sethi/ullman number
+// roughly how many registers needed to
+// compile a node. used to compile the
+// hardest side first to minimize registers.
 func ullmancalc(n *Node) {
 	if n == nil {
 		return
@@ -1683,9 +1613,9 @@ func ullmancalc(n *Node) {
 		ul = UINF
 		goto out
 
-		// hard with race detector
+		// hard with instrumented code
 	case OANDAND, OOROR:
-		if flag_race != 0 {
+		if instrumenting {
 			ul = UINF
 			goto out
 		}
@@ -1713,7 +1643,7 @@ out:
 	n.Ullman = uint8(ul)
 }
 
-func badtype(o int, tl *Type, tr *Type) {
+func badtype(op Op, tl *Type, tr *Type) {
 	fmt_ := ""
 	if tl != nil {
 		fmt_ += fmt.Sprintf("\n\t%v", tl)
@@ -1732,12 +1662,10 @@ func badtype(o int, tl *Type, tr *Type) {
 	}
 
 	s := fmt_
-	Yyerror("illegal types for operand: %v%s", Oconv(int(o), 0), s)
+	Yyerror("illegal types for operand: %v%s", Oconv(int(op), 0), s)
 }
 
-/*
- * iterator to walk a structure declaration
- */
+// iterator to walk a structure declaration
 func Structfirst(s *Iter, nn **Type) *Type {
 	var t *Type
 
@@ -1760,14 +1688,14 @@ func Structfirst(s *Iter, nn **Type) *Type {
 	}
 
 	if t.Etype != TFIELD {
-		Fatal("structfirst: not field %v", t)
+		Fatalf("structfirst: not field %v", t)
 	}
 
 	s.T = t
 	return t
 
 bad:
-	Fatal("structfirst: not struct %v", n)
+	Fatalf("structfirst: not struct %v", n)
 
 	return nil
 }
@@ -1780,7 +1708,7 @@ func structnext(s *Iter) *Type {
 	}
 
 	if t.Etype != TFIELD {
-		Fatal("structnext: not struct %v", n)
+		Fatalf("structnext: not struct %v", n)
 
 		return nil
 	}
@@ -1789,9 +1717,7 @@ func structnext(s *Iter) *Type {
 	return t
 }
 
-/*
- * iterator to this and inargs in a function
- */
+// iterator to this and inargs in a function
 func funcfirst(s *Iter, t *Type) *Type {
 	var fp *Type
 
@@ -1814,7 +1740,7 @@ func funcfirst(s *Iter, t *Type) *Type {
 	return fp
 
 bad:
-	Fatal("funcfirst: not func %v", t)
+	Fatalf("funcfirst: not func %v", t)
 	return nil
 }
 
@@ -1830,21 +1756,21 @@ func funcnext(s *Iter) *Type {
 
 func getthis(t *Type) **Type {
 	if t.Etype != TFUNC {
-		Fatal("getthis: not a func %v", t)
+		Fatalf("getthis: not a func %v", t)
 	}
 	return &t.Type
 }
 
 func Getoutarg(t *Type) **Type {
 	if t.Etype != TFUNC {
-		Fatal("getoutarg: not a func %v", t)
+		Fatalf("getoutarg: not a func %v", t)
 	}
 	return &t.Type.Down
 }
 
 func getinarg(t *Type) **Type {
 	if t.Etype != TFUNC {
-		Fatal("getinarg: not a func %v", t)
+		Fatalf("getinarg: not a func %v", t)
 	}
 	return &t.Type.Down.Down
 }
@@ -1863,8 +1789,8 @@ func getinargx(t *Type) *Type {
 
 // Brcom returns !(op).
 // For example, Brcom(==) is !=.
-func Brcom(a int) int {
-	switch a {
+func Brcom(op Op) Op {
+	switch op {
 	case OEQ:
 		return ONE
 	case ONE:
@@ -1878,14 +1804,14 @@ func Brcom(a int) int {
 	case OGE:
 		return OLT
 	}
-	Fatal("brcom: no com for %v\n", Oconv(a, 0))
-	return a
+	Fatalf("brcom: no com for %v\n", Oconv(int(op), 0))
+	return op
 }
 
 // Brrev returns reverse(op).
 // For example, Brrev(<) is >.
-func Brrev(a int) int {
-	switch a {
+func Brrev(op Op) Op {
+	switch op {
 	case OEQ:
 		return OEQ
 	case ONE:
@@ -1899,14 +1825,12 @@ func Brrev(a int) int {
 	case OGE:
 		return OLE
 	}
-	Fatal("brrev: no rev for %v\n", Oconv(a, 0))
-	return a
+	Fatalf("brrev: no rev for %v\n", Oconv(int(op), 0))
+	return op
 }
 
-/*
- * return side effect-free n, appending side effects to init.
- * result is assignable if n is.
- */
+// return side effect-free n, appending side effects to init.
+// result is assignable if n is.
 func safeexpr(n *Node, init **NodeList) *Node {
 	if n == nil {
 		return nil
@@ -1961,7 +1885,7 @@ func safeexpr(n *Node, init **NodeList) *Node {
 
 	// make a copy; must not be used as an lvalue
 	if islvalue(n) {
-		Fatal("missing lvalue case in safeexpr: %v", n)
+		Fatalf("missing lvalue case in safeexpr: %v", n)
 	}
 	return cheapexpr(n, init)
 }
@@ -1975,10 +1899,8 @@ func copyexpr(n *Node, t *Type, init **NodeList) *Node {
 	return l
 }
 
-/*
- * return side-effect free and cheap n, appending side effects to init.
- * result may not be assignable.
- */
+// return side-effect free and cheap n, appending side effects to init.
+// result may not be assignable.
 func cheapexpr(n *Node, init **NodeList) *Node {
 	switch n.Op {
 	case ONAME, OLITERAL:
@@ -1988,42 +1910,25 @@ func cheapexpr(n *Node, init **NodeList) *Node {
 	return copyexpr(n, n.Type, init)
 }
 
-/*
- * return n in a local variable of type t if it is not already.
- * the value is guaranteed not to change except by direct
- * assignment to it.
- */
-func localexpr(n *Node, t *Type, init **NodeList) *Node {
-	if n.Op == ONAME && (!n.Addrtaken || strings.HasPrefix(n.Sym.Name, "autotmp_")) && (n.Class == PAUTO || n.Class == PPARAM || n.Class == PPARAMOUT) && convertop(n.Type, t, nil) == OCONVNOP {
-		return n
-	}
-
-	return copyexpr(n, t, init)
-}
-
 func Setmaxarg(t *Type, extra int32) {
 	dowidth(t)
 	w := t.Argwid
 	if w >= Thearch.MAXWIDTH {
-		Fatal("bad argwid %v", t)
+		Fatalf("bad argwid %v", t)
 	}
 	w += int64(extra)
 	if w >= Thearch.MAXWIDTH {
-		Fatal("bad argwid %d + %v", extra, t)
+		Fatalf("bad argwid %d + %v", extra, t)
 	}
 	if w > Maxarg {
 		Maxarg = w
 	}
 }
 
-/*
- * unicode-aware case-insensitive strcmp
- */
+// unicode-aware case-insensitive strcmp
 
-/*
- * code to resolve elided DOTs
- * in embedded types
- */
+// code to resolve elided DOTs
+// in embedded types
 
 // search depth 0 --
 // return count of fields+methods
@@ -2156,29 +2061,27 @@ func adddot(n *Node) *Node {
 	return n
 }
 
-/*
- * code to help generate trampoline
- * functions for methods on embedded
- * subtypes.
- * these are approx the same as
- * the corresponding adddot routines
- * except that they expect to be called
- * with unique tasks and they return
- * the actual methods.
- */
+// code to help generate trampoline
+// functions for methods on embedded
+// subtypes.
+// these are approx the same as
+// the corresponding adddot routines
+// except that they expect to be called
+// with unique tasks and they return
+// the actual methods.
 type Symlink struct {
 	field     *Type
-	good      uint8
-	followptr uint8
 	link      *Symlink
+	good      bool
+	followptr bool
 }
 
 var slist *Symlink
 
-func expand0(t *Type, followptr int) {
+func expand0(t *Type, followptr bool) {
 	u := t
 	if Isptr[u.Etype] {
-		followptr = 1
+		followptr = true
 		u = u.Type
 	}
 
@@ -2192,7 +2095,7 @@ func expand0(t *Type, followptr int) {
 			sl = new(Symlink)
 			sl.field = f
 			sl.link = slist
-			sl.followptr = uint8(followptr)
+			sl.followptr = followptr
 			slist = sl
 		}
 
@@ -2210,13 +2113,13 @@ func expand0(t *Type, followptr int) {
 			sl = new(Symlink)
 			sl.field = f
 			sl.link = slist
-			sl.followptr = uint8(followptr)
+			sl.followptr = followptr
 			slist = sl
 		}
 	}
 }
 
-func expand1(t *Type, d int, followptr int) {
+func expand1(t *Type, d int, followptr bool) {
 	if t.Trecur != 0 {
 		return
 	}
@@ -2231,7 +2134,7 @@ func expand1(t *Type, d int, followptr int) {
 
 	u := t
 	if Isptr[u.Etype] {
-		followptr = 1
+		followptr = true
 		u = u.Type
 	}
 
@@ -2268,7 +2171,7 @@ func expandmeth(t *Type) {
 	// generate all reachable methods
 	slist = nil
 
-	expand1(t, len(dotlist)-1, 0)
+	expand1(t, len(dotlist)-1, false)
 
 	// check each method to be uniquely reachable
 	var c int
@@ -2283,7 +2186,7 @@ func expandmeth(t *Type) {
 			if c == 1 {
 				// addot1 may have dug out arbitrary fields, we only want methods.
 				if f.Type.Etype == TFUNC && f.Type.Thistuple > 0 {
-					sl.good = 1
+					sl.good = true
 					sl.field = f
 				}
 			}
@@ -2298,13 +2201,13 @@ func expandmeth(t *Type) {
 
 	t.Xmethod = t.Method
 	for sl := slist; sl != nil; sl = sl.link {
-		if sl.good != 0 {
+		if sl.good {
 			// add it to the base type method list
 			f = typ(TFIELD)
 
 			*f = *sl.field
 			f.Embedded = 1 // needs a trampoline
-			if sl.followptr != 0 {
+			if sl.followptr {
 				f.Embedded = 2
 			}
 			f.Down = t.Xmethod
@@ -2313,9 +2216,7 @@ func expandmeth(t *Type) {
 	}
 }
 
-/*
- * Given funarg struct list, return list of ODCLFIELD Node fn args.
- */
+// Given funarg struct list, return list of ODCLFIELD Node fn args.
 func structargs(tl **Type, mustname int) *NodeList {
 	var savet Iter
 	var a *Node
@@ -2346,29 +2247,27 @@ func structargs(tl **Type, mustname int) *NodeList {
 	return args
 }
 
-/*
- * Generate a wrapper function to convert from
- * a receiver of type T to a receiver of type U.
- * That is,
- *
- *	func (t T) M() {
- *		...
- *	}
- *
- * already exists; this function generates
- *
- *	func (u U) M() {
- *		u.M()
- *	}
- *
- * where the types T and U are such that u.M() is valid
- * and calls the T.M method.
- * The resulting function is for use in method tables.
- *
- *	rcvr - U
- *	method - M func (t T)(), a TFIELD type struct
- *	newnam - the eventual mangled name of this function
- */
+// Generate a wrapper function to convert from
+// a receiver of type T to a receiver of type U.
+// That is,
+//
+//	func (t T) M() {
+//		...
+//	}
+//
+// already exists; this function generates
+//
+//	func (u U) M() {
+//		u.M()
+//	}
+//
+// where the types T and U are such that u.M() is valid
+// and calls the T.M method.
+// The resulting function is for use in method tables.
+//
+//	rcvr - U
+//	method - M func (t T)(), a TFIELD type struct
+//	newnam - the eventual mangled name of this function
 
 var genwrapper_linehistdone int = 0
 
@@ -2458,7 +2357,7 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
 	dot := adddot(Nod(OXDOT, this.Left, newname(method.Sym)))
 
 	// generate call
-	if flag_race == 0 && Isptr[rcvr.Etype] && Isptr[methodrcvr.Etype] && method.Embedded != 0 && !isifacemethod(method.Type) {
+	if !instrumenting && Isptr[rcvr.Etype] && Isptr[methodrcvr.Etype] && method.Embedded != 0 && !isifacemethod(method.Type) {
 		// generate tail call: adjust pointer receiver and jump to embedded method.
 		dot = dot.Left // skip final .M
 		if !Isptr[dotlist[0].field.Type.Etype] {
@@ -2499,7 +2398,7 @@ func genwrapper(rcvr *Type, method *Type, newnam *Sym, iface int) {
 	typechecklist(fn.Nbody, Etop)
 
 	inlcalls(fn)
-	escAnalyze(list1(fn), false)
+	escAnalyze([]*Node{fn}, false)
 
 	Curfn = nil
 	funccompile(fn)
@@ -2526,7 +2425,7 @@ func hashfor(t *Type) *Node {
 	a := algtype1(t, nil)
 	switch a {
 	case AMEM:
-		Fatal("hashfor with AMEM type")
+		Fatalf("hashfor with AMEM type")
 
 	case AINTER:
 		sym = Pkglookup("interhash", Runtimepkg)
@@ -2564,9 +2463,7 @@ func hashfor(t *Type) *Node {
 	return n
 }
 
-/*
- * Generate a helper function to compute the hash of a value of type t.
- */
+// Generate a helper function to compute the hash of a value of type t.
 func genhash(sym *Sym, t *Type) {
 	if Debug['r'] != 0 {
 		fmt.Printf("genhash %v %v\n", sym, t)
@@ -2601,11 +2498,11 @@ func genhash(sym *Sym, t *Type) {
 	// so t must be either an array or a struct.
 	switch t.Etype {
 	default:
-		Fatal("genhash %v", t)
+		Fatalf("genhash %v", t)
 
 	case TARRAY:
 		if Isslice(t) {
-			Fatal("genhash %v", t)
+			Fatalf("genhash %v", t)
 		}
 
 		// An array of pure memory would be handled by the
@@ -2621,21 +2518,6 @@ func genhash(sym *Sym, t *Type) {
 		colasdefn(n.List, n)
 		ni = n.List.N
 
-		// TODO: with aeshash we don't need these shift/mul parts
-
-		// h = h<<3 | h>>61
-		n.Nbody = list(n.Nbody, Nod(OAS, nh, Nod(OOR, Nod(OLSH, nh, Nodintconst(3)), Nod(ORSH, nh, Nodintconst(int64(Widthptr)*8-3)))))
-
-		// h *= mul
-		// Same multipliers as in runtime.memhash.
-		var mul int64
-		if Widthptr == 4 {
-			mul = 3267000013
-		} else {
-			mul = 23344194077549503
-		}
-		n.Nbody = list(n.Nbody, Nod(OAS, nh, Nod(OMUL, nh, Nodintconst(mul))))
-
 		// h = hashel(&p[i], h)
 		call := Nod(OCALL, hashel, nil)
 
@@ -2816,9 +2698,7 @@ func eqmem(p *Node, q *Node, field *Node, size int64) *Node {
 	return nif
 }
 
-/*
- * Generate a helper function to check equality of two values of type t.
- */
+// Generate a helper function to check equality of two values of type t.
 func geneq(sym *Sym, t *Type) {
 	if Debug['r'] != 0 {
 		fmt.Printf("geneq %v %v\n", sym, t)
@@ -2852,11 +2732,11 @@ func geneq(sym *Sym, t *Type) {
 	// so t must be either an array or a struct.
 	switch t.Etype {
 	default:
-		Fatal("geneq %v", t)
+		Fatalf("geneq %v", t)
 
 	case TARRAY:
 		if Isslice(t) {
-			Fatal("geneq %v", t)
+			Fatalf("geneq %v", t)
 		}
 
 		// An array of pure memory would be handled by the
@@ -2973,8 +2853,8 @@ func geneq(sym *Sym, t *Type) {
 	safemode = old_safemode
 }
 
-func ifacelookdot(s *Sym, t *Type, followptr *int, ignorecase int) *Type {
-	*followptr = 0
+func ifacelookdot(s *Sym, t *Type, followptr *bool, ignorecase int) *Type {
+	*followptr = false
 
 	if t == nil {
 		return nil
@@ -2993,7 +2873,7 @@ func ifacelookdot(s *Sym, t *Type, followptr *int, ignorecase int) *Type {
 		if c == 1 {
 			for i = 0; i < d; i++ {
 				if Isptr[dotlist[i].field.Type.Etype] {
-					*followptr = 1
+					*followptr = true
 					break
 				}
 			}
@@ -3051,9 +2931,12 @@ func implements(t *Type, iface *Type, m **Type, samename **Type, ptr *int) bool
 	}
 	var tm *Type
 	var imtype *Type
-	var followptr int
+	var followptr bool
 	var rcvr *Type
 	for im := iface.Type; im != nil; im = im.Down {
+		if im.Broke {
+			continue
+		}
 		imtype = methodfunc(im.Type, nil)
 		tm = ifacelookdot(im.Sym, t, &followptr, 0)
 		if tm == nil || tm.Nointerface || !Eqtype(methodfunc(tm.Type, nil), imtype) {
@@ -3070,7 +2953,7 @@ func implements(t *Type, iface *Type, m **Type, samename **Type, ptr *int) bool
 		// the method does not exist for value types.
 		rcvr = getthisx(tm.Type).Type.Type
 
-		if Isptr[rcvr.Etype] && !Isptr[t0.Etype] && followptr == 0 && !isifacemethod(tm.Type) {
+		if Isptr[rcvr.Etype] && !Isptr[t0.Etype] && !followptr && !isifacemethod(tm.Type) {
 			if false && Debug['r'] != 0 {
 				Yyerror("interface pointer mismatch")
 			}
@@ -3085,17 +2968,15 @@ func implements(t *Type, iface *Type, m **Type, samename **Type, ptr *int) bool
 	return true
 }
 
-/*
- * even simpler simtype; get rid of ptr, bool.
- * assuming that the front end has rejected
- * all the invalid conversions (like ptr -> bool)
- */
-func Simsimtype(t *Type) int {
+// even simpler simtype; get rid of ptr, bool.
+// assuming that the front end has rejected
+// all the invalid conversions (like ptr -> bool)
+func Simsimtype(t *Type) EType {
 	if t == nil {
 		return 0
 	}
 
-	et := int(Simtype[t.Etype])
+	et := Simtype[t.Etype]
 	switch et {
 	case TPTR32:
 		et = TUINT32
@@ -3127,9 +3008,7 @@ func liststmt(l *NodeList) *Node {
 	return n
 }
 
-/*
- * return nelem of list
- */
+// return nelem of list
 func structcount(t *Type) int {
 	var s Iter
 
@@ -3140,11 +3019,9 @@ func structcount(t *Type) int {
 	return v
 }
 
-/*
- * return power of 2 of the constant
- * operand. -1 if it is not a power of 2.
- * 1000+ if it is a -(power of 2)
- */
+// return power of 2 of the constant
+// operand. -1 if it is not a power of 2.
+// 1000+ if it is a -(power of 2)
 func powtwo(n *Node) int {
 	if n == nil || n.Op != OLITERAL || n.Type == nil {
 		return -1
@@ -3178,12 +3055,10 @@ func powtwo(n *Node) int {
 	return -1
 }
 
-/*
- * return the unsigned type for
- * a signed integer type.
- * returns T if input is not a
- * signed integer type.
- */
+// return the unsigned type for
+// a signed integer type.
+// returns T if input is not a
+// signed integer type.
 func tounsigned(t *Type) *Type {
 	// this is types[et+1], but not sure
 	// that this relation is immutable
@@ -3211,10 +3086,8 @@ func tounsigned(t *Type) *Type {
 	return t
 }
 
-/*
- * magic number for signed division
- * see hacker's delight chapter 10
- */
+// magic number for signed division
+// see hacker's delight chapter 10
 func Smagic(m *Magic) {
 	var mask uint64
 
@@ -3308,10 +3181,8 @@ func Smagic(m *Magic) {
 	m.S = p - m.W
 }
 
-/*
- * magic number for unsigned division
- * see hacker's delight chapter 10
- */
+// magic number for unsigned division
+// see hacker's delight chapter 10
 func Umagic(m *Magic) {
 	var mask uint64
 
@@ -3418,16 +3289,13 @@ func ngotype(n *Node) *Sym {
 	return nil
 }
 
-/*
- * Convert raw string to the prefix that will be used in the symbol
- * table.  All control characters, space, '%' and '"', as well as
- * non-7-bit clean bytes turn into %xx.  The period needs escaping
- * only in the last segment of the path, and it makes for happier
- * users if we escape that as little as possible.
- *
- * If you edit this, edit ../ld/lib.c:/^pathtoprefix too.
- * If you edit this, edit ../../debug/goobj/read.go:/importPathToPrefix too.
- */
+// Convert raw string to the prefix that will be used in the symbol
+// table.  All control characters, space, '%' and '"', as well as
+// non-7-bit clean bytes turn into %xx.  The period needs escaping
+// only in the last segment of the path, and it makes for happier
+// users if we escape that as little as possible.
+//
+// If you edit this, edit ../../debug/goobj/read.go:/importPathToPrefix too.
 func pathtoprefix(s string) string {
 	slash := strings.LastIndex(s, "/")
 	for i := 0; i < len(s); i++ {
@@ -3497,17 +3365,13 @@ func isbadimport(path string) bool {
 		return true
 	}
 
-	for i := 0; i < len(reservedimports); i++ {
-		if path == reservedimports[i] {
+	for _, ri := range reservedimports {
+		if path == ri {
 			Yyerror("import path %q is reserved and cannot be used", path)
 			return true
 		}
 	}
 
-	var s string
-	_ = s
-	var r uint
-	_ = r
 	for _, r := range path {
 		if r == utf8.RuneError {
 			Yyerror("import path contains invalid UTF-8 sequence: %q", path)
@@ -3549,10 +3413,8 @@ func checknil(x *Node, init **NodeList) {
 	*init = list(*init, n)
 }
 
-/*
- * Can this type be stored directly in an interface word?
- * Yes, if the representation is a single pointer.
- */
+// Can this type be stored directly in an interface word?
+// Yes, if the representation is a single pointer.
 func isdirectiface(t *Type) bool {
 	switch t.Etype {
 	case TPTR32,
diff --git a/src/cmd/compile/internal/gc/swt.go b/src/cmd/compile/internal/gc/swt.go
index f34b1c6..f0433f3 100644
--- a/src/cmd/compile/internal/gc/swt.go
+++ b/src/cmd/compile/internal/gc/swt.go
@@ -6,7 +6,6 @@ package gc
 
 import (
 	"cmd/internal/obj"
-	"fmt"
 	"sort"
 	"strconv"
 )
@@ -138,8 +137,10 @@ func typecheckswitch(n *Node) {
 						} else {
 							Yyerror("invalid case %v in switch (mismatched types %v and bool)", ll.N, ll.N.Type)
 						}
-					case nilonly != "" && !Isconst(ll.N, CTNIL):
+					case nilonly != "" && !isnil(ll.N):
 						Yyerror("invalid case %v in switch (can only compare %s %v to nil)", ll.N, nilonly, n.Left)
+					case Isinter(t) && !Isinter(ll.N.Type) && algtype1(ll.N.Type, nil) == ANOEQ:
+						Yyerror("invalid case %v in switch (incomparable type)", Nconv(ll.N, obj.FmtLong))
 					}
 
 				// type switch
@@ -153,9 +154,9 @@ func typecheckswitch(n *Node) {
 						// reset to original type
 						ll.N = n.Left.Right
 					case ll.N.Type.Etype != TINTER && t.Etype == TINTER && !implements(ll.N.Type, t, &missing, &have, &ptr):
-						if have != nil && missing.Broke == 0 && have.Broke == 0 {
+						if have != nil && !missing.Broke && !have.Broke {
 							Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (wrong type for %v method)\n\thave %v%v\n\twant %v%v", Nconv(n.Left.Right, obj.FmtLong), ll.N.Type, missing.Sym, have.Sym, Tconv(have.Type, obj.FmtShort), missing.Sym, Tconv(missing.Type, obj.FmtShort))
-						} else if missing.Broke == 0 {
+						} else if !missing.Broke {
 							Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (missing %v method)", Nconv(n.Left.Right, obj.FmtLong), ll.N.Type, missing.Sym)
 						}
 					}
@@ -348,7 +349,7 @@ func casebody(sw *Node, typeswvar *Node) {
 		n := l.N
 		setlineno(n)
 		if n.Op != OXCASE {
-			Fatal("casebody %v", Oconv(int(n.Op), 0))
+			Fatalf("casebody %v", Oconv(int(n.Op), 0))
 		}
 		n.Op = OCASE
 		needvar := count(n.List) != 1 || n.List.N.Op == OLITERAL
@@ -679,7 +680,7 @@ func (s *typeSwitch) walkCases(cc []*caseClause) *Node {
 		for _, c := range cc {
 			n := c.node
 			if c.typ != caseKindTypeConst {
-				Fatal("typeSwitch walkCases")
+				Fatalf("typeSwitch walkCases")
 			}
 			a := Nod(OIF, nil, nil)
 			a.Left = Nod(OEQ, s.hashname, Nodintconst(int64(c.hash)))
@@ -745,11 +746,11 @@ func exprcmp(c1, c2 *caseClause) int {
 	n2 := c2.node.Left
 
 	// sort by type (for switches on interface)
-	ct := int(n1.Val().Ctype())
-	if ct > int(n2.Val().Ctype()) {
+	ct := n1.Val().Ctype()
+	if ct > n2.Val().Ctype() {
 		return +1
 	}
-	if ct < int(n2.Val().Ctype()) {
+	if ct < n2.Val().Ctype() {
 		return -1
 	}
 	if !Eqtype(n1.Type, n2.Type) {
@@ -779,7 +780,13 @@ func exprcmp(c1, c2 *caseClause) int {
 		if len(a) > len(b) {
 			return +1
 		}
-		return stringsCompare(a, b)
+		if a == b {
+			return 0
+		}
+		if a < b {
+			return -1
+		}
+		return +1
 	}
 
 	return 0
@@ -806,43 +813,3 @@ func (x caseClauseByType) Less(i, j int) bool {
 	// sort by ordinal
 	return c1.ordinal < c2.ordinal
 }
-
-func dumpcase(cc []*caseClause) {
-	for _, c := range cc {
-		switch c.typ {
-		case caseKindDefault:
-			fmt.Printf("case-default\n")
-			fmt.Printf("\tord=%d\n", c.ordinal)
-
-		case caseKindExprConst:
-			fmt.Printf("case-exprconst\n")
-			fmt.Printf("\tord=%d\n", c.ordinal)
-
-		case caseKindExprVar:
-			fmt.Printf("case-exprvar\n")
-			fmt.Printf("\tord=%d\n", c.ordinal)
-			fmt.Printf("\top=%v\n", Oconv(int(c.node.Left.Op), 0))
-
-		case caseKindTypeNil:
-			fmt.Printf("case-typenil\n")
-			fmt.Printf("\tord=%d\n", c.ordinal)
-
-		case caseKindTypeConst:
-			fmt.Printf("case-typeconst\n")
-			fmt.Printf("\tord=%d\n", c.ordinal)
-			fmt.Printf("\thash=%x\n", c.hash)
-
-		case caseKindTypeVar:
-			fmt.Printf("case-typevar\n")
-			fmt.Printf("\tord=%d\n", c.ordinal)
-
-		default:
-			fmt.Printf("case-???\n")
-			fmt.Printf("\tord=%d\n", c.ordinal)
-			fmt.Printf("\top=%v\n", Oconv(int(c.node.Left.Op), 0))
-			fmt.Printf("\thash=%x\n", c.hash)
-		}
-	}
-
-	fmt.Printf("\n")
-}
diff --git a/src/cmd/compile/internal/gc/swt_test.go b/src/cmd/compile/internal/gc/swt_test.go
new file mode 100644
index 0000000..c1ee895
--- /dev/null
+++ b/src/cmd/compile/internal/gc/swt_test.go
@@ -0,0 +1,144 @@
+// Copyright 2015 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
+
+import (
+	"cmd/compile/internal/big"
+	"testing"
+)
+
+func TestExprcmp(t *testing.T) {
+	testdata := []struct {
+		a, b caseClause
+		want int
+	}{
+		// Non-constants.
+		{
+			caseClause{node: Nod(OXXX, nil, nil), typ: caseKindExprVar},
+			caseClause{node: Nod(OXXX, nil, nil), typ: caseKindExprConst},
+			+1,
+		},
+		{
+			caseClause{node: Nod(OXXX, nil, nil), typ: caseKindExprConst},
+			caseClause{node: Nod(OXXX, nil, nil), typ: caseKindExprVar},
+			-1,
+		},
+		// Type switches
+		{
+			caseClause{node: Nod(OXXX, Nodintconst(0), nil), typ: caseKindExprConst},
+			caseClause{node: Nod(OXXX, Nodbool(true), nil), typ: caseKindExprConst},
+			-1,
+		},
+		{
+			caseClause{node: Nod(OXXX, Nodbool(true), nil), typ: caseKindExprConst},
+			caseClause{node: Nod(OXXX, Nodintconst(1), nil), typ: caseKindExprConst},
+			+1,
+		},
+		{
+			caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TBOOL, Vargen: 1}}, nil), typ: caseKindExprConst},
+			caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TINT, Vargen: 0}}, nil), typ: caseKindExprConst},
+			+1,
+		},
+		{
+			caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TBOOL, Vargen: 1}}, nil), typ: caseKindExprConst},
+			caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TINT, Vargen: 1}}, nil), typ: caseKindExprConst},
+			-1,
+		},
+		{
+			caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TBOOL, Vargen: 0}}, nil), typ: caseKindExprConst},
+			caseClause{node: Nod(OXXX, &Node{Type: &Type{Etype: TINT, Vargen: 1}}, nil), typ: caseKindExprConst},
+			-1,
+		},
+		// Constant values.
+		// CTFLT
+		{
+			caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.1)}}), nil), typ: caseKindExprConst},
+			caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.2)}}), nil), typ: caseKindExprConst},
+			-1,
+		},
+		{
+			caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.1)}}), nil), typ: caseKindExprConst},
+			caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.1)}}), nil), typ: caseKindExprConst},
+			0,
+		},
+		{
+			caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.2)}}), nil), typ: caseKindExprConst},
+			caseClause{node: Nod(OXXX, nodlit(Val{&Mpflt{Val: *big.NewFloat(0.1)}}), nil), typ: caseKindExprConst},
+			+1,
+		},
+		// CTINT
+		{
+			caseClause{node: Nod(OXXX, Nodintconst(0), nil), typ: caseKindExprConst},
+			caseClause{node: Nod(OXXX, Nodintconst(1), nil), typ: caseKindExprConst},
+			-1,
+		},
+		{
+			caseClause{node: Nod(OXXX, Nodintconst(1), nil), typ: caseKindExprConst},
+			caseClause{node: Nod(OXXX, Nodintconst(1), nil), typ: caseKindExprConst},
+			0,
+		},
+		{
+			caseClause{node: Nod(OXXX, Nodintconst(1), nil), typ: caseKindExprConst},
+			caseClause{node: Nod(OXXX, Nodintconst(0), nil), typ: caseKindExprConst},
+			+1,
+		},
+		// CTRUNE
+		{
+			caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('a'), Rune: true}}), nil), typ: caseKindExprConst},
+			caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('b'), Rune: true}}), nil), typ: caseKindExprConst},
+			-1,
+		},
+		{
+			caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('b'), Rune: true}}), nil), typ: caseKindExprConst},
+			caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('b'), Rune: true}}), nil), typ: caseKindExprConst},
+			0,
+		},
+		{
+			caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('b'), Rune: true}}), nil), typ: caseKindExprConst},
+			caseClause{node: Nod(OXXX, nodlit(Val{&Mpint{Val: *big.NewInt('a'), Rune: true}}), nil), typ: caseKindExprConst},
+			+1,
+		},
+		// CTSTR
+		{
+			caseClause{node: Nod(OXXX, nodlit(Val{"ab"}), nil), typ: caseKindExprConst},
+			caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), typ: caseKindExprConst},
+			-1,
+		},
+		{
+			caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), typ: caseKindExprConst},
+			caseClause{node: Nod(OXXX, nodlit(Val{"xyz"}), nil), typ: caseKindExprConst},
+			-1,
+		},
+		{
+			caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), typ: caseKindExprConst},
+			caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), typ: caseKindExprConst},
+			0,
+		},
+		{
+			caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), typ: caseKindExprConst},
+			caseClause{node: Nod(OXXX, nodlit(Val{"ab"}), nil), typ: caseKindExprConst},
+			+1,
+		},
+		{
+			caseClause{node: Nod(OXXX, nodlit(Val{"xyz"}), nil), typ: caseKindExprConst},
+			caseClause{node: Nod(OXXX, nodlit(Val{"abc"}), nil), typ: caseKindExprConst},
+			+1,
+		},
+		// Everything else should compare equal.
+		{
+			caseClause{node: Nod(OXXX, nodnil(), nil), typ: caseKindExprConst},
+			caseClause{node: Nod(OXXX, nodnil(), nil), typ: caseKindExprConst},
+			0,
+		},
+	}
+	for i, d := range testdata {
+		got := exprcmp(&d.a, &d.b)
+		if d.want != got {
+			t.Errorf("%d: exprcmp(a, b) = %d; want %d", i, got, d.want)
+			t.Logf("\ta = caseClause{node: %#v, typ: %#v}", d.a.node, d.a.typ)
+			t.Logf("\tb = caseClause{node: %#v, typ: %#v}", d.b.node, d.b.typ)
+		}
+	}
+}
diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go
index 7f03a4e..a11b37e 100644
--- a/src/cmd/compile/internal/gc/syntax.go
+++ b/src/cmd/compile/internal/gc/syntax.go
@@ -42,13 +42,13 @@ type Node struct {
 
 	Esc uint16 // EscXXX
 
-	Op          uint8
+	Op          Op
 	Nointerface bool
 	Ullman      uint8 // sethi/ullman number
 	Addable     bool  // addressable
-	Etype       uint8 // op for OASOP, etype for OTYPE, exclam for export, 6g saved reg
+	Etype       EType // op for OASOP, etype for OTYPE, exclam for export, 6g saved reg
 	Bounded     bool  // bounds check unnecessary
-	Class       uint8 // PPARAM, PAUTO, PEXTERN, etc
+	Class       Class // PPARAM, PAUTO, PEXTERN, etc
 	Embedded    uint8 // ODCLFIELD embedded type
 	Colas       bool  // OAS resulting from :=
 	Diag        uint8 // already printed error about this
@@ -81,7 +81,7 @@ func (n *Node) SetVal(v Val) {
 	if n.hasVal == -1 {
 		Debug['h'] = 1
 		Dump("have Opt", n)
-		Fatal("have Opt")
+		Fatalf("have Opt")
 	}
 	n.hasVal = +1
 	n.E = v.U
@@ -104,7 +104,7 @@ func (n *Node) SetOpt(x interface{}) {
 	if n.hasVal == +1 {
 		Debug['h'] = 1
 		Dump("have Val", n)
-		Fatal("have Val")
+		Fatalf("have Val")
 	}
 	n.hasVal = -1
 	n.E = x
@@ -128,6 +128,7 @@ type Name struct {
 	Captured  bool // is the variable captured by a closure
 	Byval     bool // is the variable captured by value or by reference
 	Needzero  bool // if it contains pointers, needs to be zeroed on function entry
+	Keepalive bool // mark value live across unknown assembly call
 }
 
 type Param struct {
@@ -169,18 +170,24 @@ type Func struct {
 
 	Endlineno int32
 
-	Norace         bool // func must not have race detector annotations
-	Nosplit        bool // func should not execute on separate stack
-	Nowritebarrier bool // emit compiler error instead of write barrier
-	Dupok          bool // duplicate definitions ok
-	Wrapper        bool // is method wrapper
-	Needctxt       bool // function uses context register (has closure variables)
-	Systemstack    bool // must run on system stack
+	Norace            bool // func must not have race detector annotations
+	Nosplit           bool // func should not execute on separate stack
+	Noinline          bool // func should not be inlined
+	Nowritebarrier    bool // emit compiler error instead of write barrier
+	Nowritebarrierrec bool // error on write barrier in this or recursive callees
+	Dupok             bool // duplicate definitions ok
+	Wrapper           bool // is method wrapper
+	Needctxt          bool // function uses context register (has closure variables)
+	Systemstack       bool // must run on system stack
+
+	WBLineno int32 // line number of first write barrier
 }
 
+type Op uint8
+
 // Node ops.
 const (
-	OXXX = iota
+	OXXX = Op(iota)
 
 	// names
 	ONAME    // var, const or func name
@@ -336,6 +343,7 @@ const (
 	OCFUNC      // reference to c function pointer (not go func value)
 	OCHECKNIL   // emit code to ensure pointer/interface not nil
 	OVARKILL    // variable is dead
+	OVARLIVE    // variable is alive
 
 	// thearch-specific registers
 	OREGISTER // a register, such as AX.
@@ -409,9 +417,10 @@ func list(l *NodeList, n *Node) *NodeList {
 	return concat(l, list1(n))
 }
 
-// listsort sorts *l in place according to the 3-way comparison function f.
+// listsort sorts *l in place according to the comparison function lt.
+// The algorithm expects lt(a, b) to be equivalent to a < b.
 // The algorithm is mergesort, so it is guaranteed to be O(n log n).
-func listsort(l **NodeList, f func(*Node, *Node) int) {
+func listsort(l **NodeList, lt func(*Node, *Node) bool) {
 	if *l == nil || (*l).Next == nil {
 		return
 	}
@@ -436,10 +445,10 @@ func listsort(l **NodeList, f func(*Node, *Node) int) {
 	(*l).End = l1
 
 	l1 = *l
-	listsort(&l1, f)
-	listsort(&l2, f)
+	listsort(&l1, lt)
+	listsort(&l2, lt)
 
-	if f(l1.N, l2.N) < 0 {
+	if lt(l1.N, l2.N) {
 		*l = l1
 	} else {
 		*l = l2
@@ -451,7 +460,7 @@ func listsort(l **NodeList, f func(*Node, *Node) int) {
 
 	var le *NodeList
 	for (l1 != nil) && (l2 != nil) {
-		for (l1.Next != nil) && f(l1.Next.N, l2.N) < 0 {
+		for (l1.Next != nil) && lt(l1.Next.N, l2.N) {
 			l1 = l1.Next
 		}
 
diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go
index e5ae967..f74bb33 100644
--- a/src/cmd/compile/internal/gc/typecheck.go
+++ b/src/cmd/compile/internal/gc/typecheck.go
@@ -11,18 +11,14 @@ import (
 	"strings"
 )
 
-/*
- * type check the whole tree of an expression.
- * calculates expression types.
- * evaluates compile time constants.
- * marks variables that escape the local frame.
- * rewrites n->op to be more specific in some cases.
- */
-var typecheckdefstack *NodeList
-
-/*
- * resolve ONONAME to definition, if any.
- */
+// type check the whole tree of an expression.
+// calculates expression types.
+// evaluates compile time constants.
+// marks variables that escape the local frame.
+// rewrites n->op to be more specific in some cases.
+var typecheckdefstack []*Node
+
+// resolve ONONAME to definition, if any.
 func resolve(n *Node) *Node {
 	if n != nil && n.Op == ONONAME && n.Sym != nil {
 		r := n.Sym.Def
@@ -79,8 +75,8 @@ func typekind(t *Type) string {
 	if Isslice(t) {
 		return "slice"
 	}
-	et := int(t.Etype)
-	if 0 <= et && et < len(_typekind) {
+	et := t.Etype
+	if int(et) < len(_typekind) {
 		s := _typekind[et]
 		if s != "" {
 			return s
@@ -89,37 +85,30 @@ func typekind(t *Type) string {
 	return fmt.Sprintf("etype=%d", et)
 }
 
-/*
- * sprint_depchain prints a dependency chain
- * of nodes into fmt.
- * It is used by typecheck in the case of OLITERAL nodes
- * to print constant definition loops.
- */
-func sprint_depchain(fmt_ *string, stack *NodeList, cur *Node, first *Node) {
-	for l := stack; l != nil; l = l.Next {
-		if l.N.Op == cur.Op {
-			if l.N != first {
-				sprint_depchain(fmt_, l.Next, l.N, first)
+// sprint_depchain prints a dependency chain of nodes into fmt.
+// It is used by typecheck in the case of OLITERAL nodes
+// to print constant definition loops.
+func sprint_depchain(fmt_ *string, stack []*Node, cur *Node, first *Node) {
+	for i := len(stack) - 1; i >= 0; i-- {
+		if n := stack[i]; n.Op == cur.Op {
+			if n != first {
+				sprint_depchain(fmt_, stack[:i], n, first)
 			}
-			*fmt_ += fmt.Sprintf("\n\t%v: %v uses %v", l.N.Line(), l.N, cur)
+			*fmt_ += fmt.Sprintf("\n\t%v: %v uses %v", n.Line(), n, cur)
 			return
 		}
 	}
 }
 
-/*
- * type check node *np.
- * replaces *np with a new pointer in some cases.
- * returns the final value of *np as a convenience.
- */
-
-var typecheck_tcstack *NodeList
-var typecheck_tcfree *NodeList
+var typecheck_tcstack []*Node
 
+// typecheck type checks node *np.
+// It replaces *np with a new pointer in some cases.
+// It returns the final value of *np as a convenience.
 func typecheck(np **Node, top int) *Node {
 	// cannot type check until all the source has been parsed
-	if typecheckok == 0 {
-		Fatal("early typecheck")
+	if !typecheckok {
+		Fatalf("early typecheck")
 	}
 
 	n := *np
@@ -168,16 +157,15 @@ func typecheck(np **Node, top int) *Node {
 				Yyerror("%v is not a type", n)
 				break
 			}
-
-			fmt_ = ""
 			sprint_depchain(&fmt_, typecheck_tcstack, n, n)
 			yyerrorl(int(n.Lineno), "constant definition loop%s", fmt_)
 		}
 
 		if nsavederrors+nerrors == 0 {
 			fmt_ = ""
-			for l := typecheck_tcstack; l != nil; l = l.Next {
-				fmt_ += fmt.Sprintf("\n\t%v %v", l.N.Line(), l.N)
+			for i := len(typecheck_tcstack) - 1; i >= 0; i-- {
+				x := typecheck_tcstack[i]
+				fmt_ += fmt.Sprintf("\n\t%v %v", x.Line(), x)
 			}
 			Yyerror("typechecking loop involving %v%s", n, fmt_)
 		}
@@ -188,35 +176,21 @@ func typecheck(np **Node, top int) *Node {
 
 	n.Typecheck = 2
 
-	var l *NodeList
-	if typecheck_tcfree != nil {
-		l = typecheck_tcfree
-		typecheck_tcfree = l.Next
-	} else {
-		l = new(NodeList)
-	}
-	l.Next = typecheck_tcstack
-	l.N = n
-	typecheck_tcstack = l
-
+	typecheck_tcstack = append(typecheck_tcstack, n)
 	typecheck1(&n, top)
 	*np = n
+
 	n.Typecheck = 1
 
-	if typecheck_tcstack != l {
-		Fatal("typecheck stack out of sync")
-	}
-	typecheck_tcstack = l.Next
-	l.Next = typecheck_tcfree
-	typecheck_tcfree = l
+	last := len(typecheck_tcstack) - 1
+	typecheck_tcstack[last] = nil
+	typecheck_tcstack = typecheck_tcstack[:last]
 
 	lineno = int32(lno)
 	return n
 }
 
-/*
- * does n contain a call or receive operation?
- */
+// does n contain a call or receive operation?
 func callrecv(n *Node) bool {
 	if n == nil {
 		return false
@@ -293,11 +267,9 @@ OpSwitch:
 	default:
 		Dump("typecheck", n)
 
-		Fatal("typecheck %v", Oconv(int(n.Op), 0))
+		Fatalf("typecheck %v", Oconv(int(n.Op), 0))
 
-		/*
-		 * names
-		 */
+	// names
 	case OLITERAL:
 		ok |= Erv
 
@@ -347,9 +319,7 @@ OpSwitch:
 	case ODDD:
 		break
 
-		/*
-		 * types (OIND is with exprs)
-		 */
+	// types (OIND is with exprs)
 	case OTYPE:
 		ok |= Etype
 
@@ -368,7 +338,7 @@ OpSwitch:
 		} else if l.Op == ODDD {
 			t.Bound = -100 // to be filled in
 			if top&Ecomplit == 0 && n.Diag == 0 {
-				t.Broke = 1
+				t.Broke = true
 				n.Diag = 1
 				Yyerror("use of [...] array outside of array literal")
 			}
@@ -440,7 +410,8 @@ OpSwitch:
 		}
 		t := typ(TCHAN)
 		t.Type = l.Type
-		t.Chan = n.Etype
+		// TODO(marvin): Fix Node.EType type union.
+		t.Chan = uint8(n.Etype)
 		n.Op = OTYPE
 		n.Type = t
 		n.Left = nil
@@ -450,7 +421,7 @@ OpSwitch:
 		ok |= Etype
 		n.Op = OTYPE
 		n.Type = tostruct(n.List)
-		if n.Type == nil || n.Type.Broke != 0 {
+		if n.Type == nil || n.Type.Broke {
 			n.Type = nil
 			return
 		}
@@ -474,9 +445,7 @@ OpSwitch:
 			return
 		}
 
-		/*
-		 * type or expr
-		 */
+	// type or expr
 	case OIND:
 		ntop := Erv | Etype
 
@@ -512,9 +481,7 @@ OpSwitch:
 		n.Type = t.Type
 		break OpSwitch
 
-		/*
-		 * arithmetic exprs
-		 */
+	// arithmetic exprs
 	case OASOP,
 		OADD,
 		OAND,
@@ -537,7 +504,7 @@ OpSwitch:
 		OSUB,
 		OXOR:
 		var l *Node
-		var op int
+		var op Op
 		var r *Node
 		if n.Op == OASOP {
 			ok |= Etop
@@ -548,7 +515,8 @@ OpSwitch:
 				n.Type = nil
 				return
 			}
-			op = int(n.Etype)
+			// TODO(marvin): Fix Node.EType type union.
+			op = Op(n.Etype)
 		} else {
 			ok |= Erv
 			l = typecheck(&n.Left, Erv|top&Eiota)
@@ -557,7 +525,7 @@ OpSwitch:
 				n.Type = nil
 				return
 			}
-			op = int(n.Op)
+			op = n.Op
 		}
 		if op == OLSH || op == ORSH {
 			defaultlit(&r, Types[TUINT])
@@ -596,11 +564,11 @@ OpSwitch:
 		if t.Etype == TIDEAL {
 			t = r.Type
 		}
-		et := int(t.Etype)
+		et := t.Etype
 		if et == TIDEAL {
 			et = TINT
 		}
-		aop := 0
+		var aop Op = OXXX
 		if iscmp[n.Op] && t.Etype != TIDEAL && !Eqtype(l.Type, r.Type) {
 			// comparison is okay as long as one side is
 			// assignable to the other.  convert so they have
@@ -653,7 +621,7 @@ OpSwitch:
 			}
 
 		converted:
-			et = int(t.Etype)
+			et = t.Etype
 		}
 
 		if t.Etype != TIDEAL && !Eqtype(l.Type, r.Type) {
@@ -719,23 +687,12 @@ OpSwitch:
 				n.Left = l
 				n.Right = r
 			}
-		} else if n.Op == OANDAND || n.Op == OOROR {
-			if l.Type == r.Type {
-				t = l.Type
-			} else if l.Type == idealbool {
-				t = r.Type
-			} else if r.Type == idealbool {
-				t = l.Type
-			}
-		} else
-		// non-comparison operators on ideal bools should make them lose their ideal-ness
-		if t == idealbool {
-			t = Types[TBOOL]
 		}
 
 		if et == TSTRING {
 			if iscmp[n.Op] {
-				n.Etype = n.Op
+				// TODO(marvin): Fix Node.EType type union.
+				n.Etype = EType(n.Op)
 				n.Op = OCMPSTR
 			} else if n.Op == OADD {
 				// create OADDSTR node with list of strings in x + y + z + (w + v) + ...
@@ -765,7 +722,8 @@ OpSwitch:
 			} else if r.Op == OLITERAL && r.Val().Ctype() == CTNIL {
 			} else // leave alone for back end
 			if Isinter(r.Type) == Isinter(l.Type) {
-				n.Etype = n.Op
+				// TODO(marvin): Fix Node.EType type union.
+				n.Etype = EType(n.Op)
 				n.Op = OCMPIFACE
 			}
 		}
@@ -798,9 +756,7 @@ OpSwitch:
 		n.Type = t
 		break OpSwitch
 
-		/*
-		 * exprs
-		 */
+	// exprs
 	case OADDR:
 		ok |= Erv
 
@@ -820,7 +776,7 @@ OpSwitch:
 		}
 
 		if l.Orig != l && l.Op == ONAME {
-			Fatal("found non-orig name node %v", l)
+			Fatalf("found non-orig name node %v", l)
 		}
 		l.Addrtaken = true
 		if l.Name != nil && l.Name.Param != nil && l.Name.Param.Closure != nil {
@@ -1046,11 +1002,11 @@ OpSwitch:
 				break
 			}
 
-			if Isconst(n.Right, CTINT) {
+			if !n.Bounded && Isconst(n.Right, CTINT) {
 				x := Mpgetfix(n.Right.Val().U.(*Mpint))
 				if x < 0 {
 					Yyerror("invalid %s index %v (index must be non-negative)", why, n.Right)
-				} else if Isfixedarray(t) && t.Bound > 0 && x >= t.Bound {
+				} else if Isfixedarray(t) && x >= t.Bound {
 					Yyerror("invalid array index %v (out of bounds for %d-element array)", n.Right, t.Bound)
 				} else if Isconst(n.Left, CTSTR) && x >= int64(len(n.Left.Val().U.(string))) {
 					Yyerror("invalid string index %v (out of bounds for %d-byte string)", n.Right, len(n.Left.Val().U.(string)))
@@ -1180,16 +1136,16 @@ OpSwitch:
 		}
 
 		lo := n.Right.Left
-		if lo != nil && checksliceindex(l, lo, tp) < 0 {
+		if lo != nil && !checksliceindex(l, lo, tp) {
 			n.Type = nil
 			return
 		}
 		hi := n.Right.Right
-		if hi != nil && checksliceindex(l, hi, tp) < 0 {
+		if hi != nil && !checksliceindex(l, hi, tp) {
 			n.Type = nil
 			return
 		}
-		if checksliceconst(lo, hi) < 0 {
+		if !checksliceconst(lo, hi) {
 			n.Type = nil
 			return
 		}
@@ -1247,29 +1203,27 @@ OpSwitch:
 		}
 
 		lo := n.Right.Left
-		if lo != nil && checksliceindex(l, lo, tp) < 0 {
+		if lo != nil && !checksliceindex(l, lo, tp) {
 			n.Type = nil
 			return
 		}
 		mid := n.Right.Right.Left
-		if mid != nil && checksliceindex(l, mid, tp) < 0 {
+		if mid != nil && !checksliceindex(l, mid, tp) {
 			n.Type = nil
 			return
 		}
 		hi := n.Right.Right.Right
-		if hi != nil && checksliceindex(l, hi, tp) < 0 {
+		if hi != nil && !checksliceindex(l, hi, tp) {
 			n.Type = nil
 			return
 		}
-		if checksliceconst(lo, hi) < 0 || checksliceconst(lo, mid) < 0 || checksliceconst(mid, hi) < 0 {
+		if !checksliceconst(lo, hi) || !checksliceconst(lo, mid) || !checksliceconst(mid, hi) {
 			n.Type = nil
 			return
 		}
 		break OpSwitch
 
-		/*
-		 * call and call like
-		 */
+	// call and call like
 	case OCALL:
 		l := n.Left
 
@@ -1289,12 +1243,14 @@ OpSwitch:
 		n.Diag |= n.Left.Diag
 		l = n.Left
 		if l.Op == ONAME && l.Etype != 0 {
-			if n.Isddd && l.Etype != OAPPEND {
+			// TODO(marvin): Fix Node.EType type union.
+			if n.Isddd && Op(l.Etype) != OAPPEND {
 				Yyerror("invalid use of ... with builtin %v", l)
 			}
 
 			// builtin: OLEN, OCAP, etc.
-			n.Op = l.Etype
+			// TODO(marvin): Fix Node.EType type union.
+			n.Op = Op(l.Etype)
 
 			n.Left = n.Right
 			n.Right = nil
@@ -1306,7 +1262,7 @@ OpSwitch:
 		l = n.Left
 		if l.Op == OTYPE {
 			if n.Isddd || l.Type.Bound == -100 {
-				if l.Type.Broke == 0 {
+				if !l.Type.Broke {
 					Yyerror("invalid use of ... in type conversion to %v", l.Type)
 				}
 				n.Diag = 1
@@ -1320,7 +1276,7 @@ OpSwitch:
 
 			n.Op = OCONV
 			n.Type = l.Type
-			if onearg(n, "conversion to %v", l.Type) < 0 {
+			if !onearg(n, "conversion to %v", l.Type) {
 				n.Type = nil
 				return
 			}
@@ -1354,7 +1310,7 @@ OpSwitch:
 			tp := getthisx(t).Type.Type
 
 			if l.Left == nil || !Eqtype(l.Left.Type, tp) {
-				Fatal("method receiver")
+				Fatalf("method receiver")
 			}
 
 		default:
@@ -1408,7 +1364,7 @@ OpSwitch:
 
 	case OCAP, OLEN, OREAL, OIMAG:
 		ok |= Erv
-		if onearg(n, "%v", Oconv(int(n.Op), 0)) < 0 {
+		if !onearg(n, "%v", Oconv(int(n.Op), 0)) {
 			n.Type = nil
 			return
 		}
@@ -1446,7 +1402,7 @@ OpSwitch:
 				n.Orig = r
 			}
 
-			n.Type = Types[cplxsubtype(int(t.Etype))]
+			n.Type = Types[cplxsubtype(t.Etype)]
 			break OpSwitch
 		}
 
@@ -1504,7 +1460,7 @@ OpSwitch:
 			l = t.Nname
 			r = t.Down.Nname
 		} else {
-			if twoarg(n) < 0 {
+			if !twoarg(n) {
 				n.Type = nil
 				return
 			}
@@ -1558,7 +1514,7 @@ OpSwitch:
 		break OpSwitch
 
 	case OCLOSE:
-		if onearg(n, "%v", Oconv(int(n.Op), 0)) < 0 {
+		if !onearg(n, "%v", Oconv(int(n.Op), 0)) {
 			n.Type = nil
 			return
 		}
@@ -1641,7 +1597,7 @@ OpSwitch:
 
 		// Unpack multiple-return result before type-checking.
 		var funarg *Type
-		if Istype(t, TSTRUCT) && t.Funarg != 0 {
+		if Istype(t, TSTRUCT) && t.Funarg {
 			funarg = t
 			t = t.Type.Type
 		}
@@ -1771,9 +1727,9 @@ OpSwitch:
 			return
 		}
 		var why string
-		n.Op = uint8(convertop(t, n.Type, &why))
-		if (n.Op) == 0 {
-			if n.Diag == 0 && n.Type.Broke == 0 {
+		n.Op = convertop(t, n.Type, &why)
+		if n.Op == 0 {
+			if n.Diag == 0 && !n.Type.Broke {
 				Yyerror("cannot convert %v to type %v%s", Nconv(n.Left, obj.FmtLong), n.Type, why)
 				n.Diag = 1
 			}
@@ -1783,7 +1739,7 @@ OpSwitch:
 
 		switch n.Op {
 		case OCONVNOP:
-			if n.Left.Op == OLITERAL && n.Type != Types[TBOOL] {
+			if n.Left.Op == OLITERAL {
 				r := Nod(OXXX, nil, nil)
 				n.Op = OCONV
 				n.Orig = r
@@ -1857,9 +1813,7 @@ OpSwitch:
 				n.Type = nil
 				return
 			}
-			et := obj.Bool2int(checkmake(t, "len", l) < 0)
-			et |= obj.Bool2int(r != nil && checkmake(t, "cap", r) < 0)
-			if et != 0 {
+			if !checkmake(t, "len", l) || r != nil && !checkmake(t, "cap", r) {
 				n.Type = nil
 				return
 			}
@@ -1883,7 +1837,7 @@ OpSwitch:
 					n.Type = nil
 					return
 				}
-				if checkmake(t, "size", l) < 0 {
+				if !checkmake(t, "size", l) {
 					n.Type = nil
 					return
 				}
@@ -1904,7 +1858,7 @@ OpSwitch:
 					n.Type = nil
 					return
 				}
-				if checkmake(t, "buffer", l) < 0 {
+				if !checkmake(t, "buffer", l) {
 					n.Type = nil
 					return
 				}
@@ -1967,7 +1921,7 @@ OpSwitch:
 
 	case OPANIC:
 		ok |= Etop
-		if onearg(n, "panic") < 0 {
+		if !onearg(n, "panic") {
 			n.Type = nil
 			return
 		}
@@ -2008,7 +1962,7 @@ OpSwitch:
 			return
 		}
 		if t.Etype != TINTER {
-			Fatal("OITAB of %v", t)
+			Fatalf("OITAB of %v", t)
 		}
 		n.Type = Ptrto(Types[TUINTPTR])
 		break OpSwitch
@@ -2022,7 +1976,7 @@ OpSwitch:
 			return
 		}
 		if !Isslice(t) && t.Etype != TSTRING {
-			Fatal("OSPTR of %v", t)
+			Fatalf("OSPTR of %v", t)
 		}
 		if t.Etype == TSTRING {
 			n.Type = Ptrto(Types[TUINT8])
@@ -2046,9 +2000,7 @@ OpSwitch:
 		typecheck(&n.Left, Erv)
 		break OpSwitch
 
-		/*
-		 * statements
-		 */
+	// statements
 	case OAS:
 		ok |= Etop
 
@@ -2071,7 +2023,8 @@ OpSwitch:
 		OEMPTY,
 		OGOTO,
 		OXFALL,
-		OVARKILL:
+		OVARKILL,
+		OVARLIVE:
 		ok |= Etop
 		break OpSwitch
 
@@ -2137,7 +2090,7 @@ OpSwitch:
 			return
 		}
 
-		if Curfn.Type.Outnamed != 0 && n.List == nil {
+		if Curfn.Type.Outnamed && n.List == nil {
 			break OpSwitch
 		}
 		typecheckaste(ORETURN, nil, false, getoutargx(Curfn.Type), n.List, func() string { return "return argument" })
@@ -2193,7 +2146,7 @@ OpSwitch:
 	}
 
 	t := n.Type
-	if t != nil && t.Funarg == 0 && n.Op != OTYPE {
+	if t != nil && !t.Funarg && n.Op != OTYPE {
 		switch t.Etype {
 		case TFUNC, // might have TANY; wait until its called
 			TANY,
@@ -2248,42 +2201,42 @@ OpSwitch:
 	*/
 }
 
-func checksliceindex(l *Node, r *Node, tp *Type) int {
+func checksliceindex(l *Node, r *Node, tp *Type) bool {
 	t := r.Type
 	if t == nil {
-		return -1
+		return false
 	}
 	if !Isint[t.Etype] {
 		Yyerror("invalid slice index %v (type %v)", r, t)
-		return -1
+		return false
 	}
 
 	if r.Op == OLITERAL {
 		if Mpgetfix(r.Val().U.(*Mpint)) < 0 {
 			Yyerror("invalid slice index %v (index must be non-negative)", r)
-			return -1
+			return false
 		} else if tp != nil && tp.Bound > 0 && Mpgetfix(r.Val().U.(*Mpint)) > tp.Bound {
 			Yyerror("invalid slice index %v (out of bounds for %d-element array)", r, tp.Bound)
-			return -1
+			return false
 		} else if Isconst(l, CTSTR) && Mpgetfix(r.Val().U.(*Mpint)) > int64(len(l.Val().U.(string))) {
 			Yyerror("invalid slice index %v (out of bounds for %d-byte string)", r, len(l.Val().U.(string)))
-			return -1
+			return false
 		} else if Mpcmpfixfix(r.Val().U.(*Mpint), Maxintval[TINT]) > 0 {
 			Yyerror("invalid slice index %v (index too large)", r)
-			return -1
+			return false
 		}
 	}
 
-	return 0
+	return true
 }
 
-func checksliceconst(lo *Node, hi *Node) int {
+func checksliceconst(lo *Node, hi *Node) bool {
 	if lo != nil && hi != nil && lo.Op == OLITERAL && hi.Op == OLITERAL && Mpcmpfixfix(lo.Val().U.(*Mpint), hi.Val().U.(*Mpint)) > 0 {
 		Yyerror("invalid slice index: %v > %v", lo, hi)
-		return -1
+		return false
 	}
 
-	return 0
+	return true
 }
 
 func checkdefergo(n *Node) {
@@ -2327,7 +2280,7 @@ func checkdefergo(n *Node) {
 
 	// type is broken or missing, most likely a method call on a broken type
 	// we will warn about the broken type elsewhere. no need to emit a potentially confusing error
-	if n.Left.Type == nil || n.Left.Type.Broke != 0 {
+	if n.Left.Type == nil || n.Left.Type.Broke {
 		return
 	}
 
@@ -2361,14 +2314,14 @@ func implicitstar(nn **Node) {
 	*nn = n
 }
 
-func onearg(n *Node, f string, args ...interface{}) int {
+func onearg(n *Node, f string, args ...interface{}) bool {
 	if n.Left != nil {
-		return 0
+		return true
 	}
 	if n.List == nil {
 		p := fmt.Sprintf(f, args...)
 		Yyerror("missing argument to %s: %v", p, n)
-		return -1
+		return false
 	}
 
 	if n.List.Next != nil {
@@ -2376,39 +2329,39 @@ func onearg(n *Node, f string, args ...interface{}) int {
 		Yyerror("too many arguments to %s: %v", p, n)
 		n.Left = n.List.N
 		n.List = nil
-		return -1
+		return false
 	}
 
 	n.Left = n.List.N
 	n.List = nil
-	return 0
+	return true
 }
 
-func twoarg(n *Node) int {
+func twoarg(n *Node) bool {
 	if n.Left != nil {
-		return 0
+		return true
 	}
 	if n.List == nil {
 		Yyerror("missing argument to %v - %v", Oconv(int(n.Op), 0), n)
-		return -1
+		return false
 	}
 
 	n.Left = n.List.N
 	if n.List.Next == nil {
 		Yyerror("missing argument to %v - %v", Oconv(int(n.Op), 0), n)
 		n.List = nil
-		return -1
+		return false
 	}
 
 	if n.List.Next.Next != nil {
 		Yyerror("too many arguments to %v - %v", Oconv(int(n.Op), 0), n)
 		n.List = nil
-		return -1
+		return false
 	}
 
 	n.Right = n.List.Next.N
 	n.List = nil
-	return 0
+	return true
 }
 
 func lookdot1(errnode *Node, s *Sym, t *Type, f *Type, dostrcmp int) *Type {
@@ -2484,7 +2437,7 @@ func looktypedot(n *Node, t *Type, dostrcmp int) bool {
 }
 
 func derefall(t *Type) *Type {
-	for t != nil && int(t.Etype) == Tptr {
+	for t != nil && t.Etype == Tptr {
 		t = t.Type
 	}
 	return t
@@ -2527,7 +2480,7 @@ func lookdot(n *Node, t *Type, dostrcmp int) *Type {
 			Yyerror("%v is both field and method", n.Right.Sym)
 		}
 		if f1.Width == BADWIDTH {
-			Fatal("lookdot badwidth %v %p", f1, f1)
+			Fatalf("lookdot badwidth %v %p", f1, f1)
 		}
 		n.Xoffset = f1.Width
 		n.Type = f1.Type
@@ -2556,20 +2509,20 @@ func lookdot(n *Node, t *Type, dostrcmp int) *Type {
 		dowidth(tt)
 		rcvr := getthisx(f2.Type).Type.Type
 		if !Eqtype(rcvr, tt) {
-			if int(rcvr.Etype) == Tptr && Eqtype(rcvr.Type, tt) {
+			if rcvr.Etype == Tptr && Eqtype(rcvr.Type, tt) {
 				checklvalue(n.Left, "call pointer method on")
 				n.Left = Nod(OADDR, n.Left, nil)
 				n.Left.Implicit = true
 				typecheck(&n.Left, Etype|Erv)
-			} else if int(tt.Etype) == Tptr && int(rcvr.Etype) != Tptr && Eqtype(tt.Type, rcvr) {
+			} else if tt.Etype == Tptr && rcvr.Etype != Tptr && Eqtype(tt.Type, rcvr) {
 				n.Left = Nod(OIND, n.Left, nil)
 				n.Left.Implicit = true
 				typecheck(&n.Left, Etype|Erv)
-			} else if int(tt.Etype) == Tptr && int(tt.Type.Etype) == Tptr && Eqtype(derefall(tt), derefall(rcvr)) {
+			} else if tt.Etype == Tptr && tt.Type.Etype == Tptr && Eqtype(derefall(tt), derefall(rcvr)) {
 				Yyerror("calling method %v with receiver %v requires explicit dereference", n.Right, Nconv(n.Left, obj.FmtLong))
-				for int(tt.Etype) == Tptr {
+				for tt.Etype == Tptr {
 					// Stop one level early for method with pointer receiver.
-					if int(rcvr.Etype) == Tptr && int(tt.Type.Etype) != Tptr {
+					if rcvr.Etype == Tptr && tt.Type.Etype != Tptr {
 						break
 					}
 					n.Left = Nod(OIND, n.Left, nil)
@@ -2578,7 +2531,7 @@ func lookdot(n *Node, t *Type, dostrcmp int) *Type {
 					tt = tt.Type
 				}
 			} else {
-				Fatal("method mismatch: %v for %v", rcvr, tt)
+				Fatalf("method mismatch: %v for %v", rcvr, tt)
 			}
 		}
 
@@ -2627,6 +2580,8 @@ func hasddd(t *Type) bool {
 	return false
 }
 
+// downcount is the same as countfield
+// TODO decide if we want both (for semantic reasons)
 func downcount(t *Type) int {
 	n := 0
 	for tl := t.Type; tl != nil; tl = tl.Down {
@@ -2636,10 +2591,8 @@ func downcount(t *Type) int {
 	return n
 }
 
-/*
- * typecheck assignment: type list = expression list
- */
-func typecheckaste(op int, call *Node, isddd bool, tstruct *Type, nl *NodeList, desc func() string) {
+// typecheck assignment: type list = expression list
+func typecheckaste(op Op, call *Node, isddd bool, tstruct *Type, nl *NodeList, desc func() string) {
 	var t *Type
 	var n *Node
 	var n1 int
@@ -2647,7 +2600,7 @@ func typecheckaste(op int, call *Node, isddd bool, tstruct *Type, nl *NodeList,
 
 	lno := int(lineno)
 
-	if tstruct.Broke != 0 {
+	if tstruct.Broke {
 		goto out
 	}
 
@@ -2655,7 +2608,7 @@ func typecheckaste(op int, call *Node, isddd bool, tstruct *Type, nl *NodeList,
 	if nl != nil && nl.Next == nil {
 		n = nl.N
 		if n.Type != nil {
-			if n.Type.Etype == TSTRUCT && n.Type.Funarg != 0 {
+			if n.Type.Etype == TSTRUCT && n.Type.Funarg {
 				if !hasddd(tstruct) {
 					n1 := downcount(tstruct)
 					n2 := downcount(n.Type)
@@ -2815,12 +2768,10 @@ toomany:
 	goto out
 }
 
-/*
- * type check composite
- */
+// type check composite
 func fielddup(n *Node, hash map[string]bool) {
 	if n.Op != ONAME {
-		Fatal("fielddup: not ONAME")
+		Fatalf("fielddup: not ONAME")
 	}
 	name := n.Sym.Name
 	if hash[name] {
@@ -2869,25 +2820,25 @@ func keydup(n *Node, hash map[uint32][]*Node) {
 	for _, a := range hash[h] {
 		cmp.Op = OEQ
 		cmp.Left = n
-		b := uint32(0)
+		b := false
 		if a.Op == OCONVIFACE && orign.Op == OCONVIFACE {
 			if Eqtype(a.Left.Type, n.Type) {
 				cmp.Right = a.Left
 				evconst(&cmp)
 				if cmp.Op == OLITERAL {
 					// Sometimes evconst fails.  See issue 12536.
-					b = uint32(obj.Bool2int(cmp.Val().U.(bool)))
+					b = cmp.Val().U.(bool)
 				}
 			}
 		} else if Eqtype(a.Type, n.Type) {
 			cmp.Right = a
 			evconst(&cmp)
 			if cmp.Op == OLITERAL {
-				b = uint32(obj.Bool2int(cmp.Val().U.(bool)))
+				b = cmp.Val().U.(bool)
 			}
 		}
 
-		if b != 0 {
+		if b {
 			Yyerror("duplicate key %v in map literal", n)
 			return
 		}
@@ -2898,7 +2849,7 @@ func keydup(n *Node, hash map[uint32][]*Node) {
 
 func indexdup(n *Node, hash map[int64]*Node) {
 	if n.Op != OLITERAL {
-		Fatal("indexdup: not OLITERAL")
+		Fatalf("indexdup: not OLITERAL")
 	}
 
 	v := Mpgetfix(n.Val().U.(*Mpint))
@@ -2959,12 +2910,12 @@ func typecheckcomplit(np **Node) {
 	}
 
 	// Save original node (including n->right)
-	norig := Nod(int(n.Op), nil, nil)
+	norig := Nod(n.Op, nil, nil)
 
 	*norig = *n
 
 	setlineno(n.Right)
-	l := typecheck(&n.Right, Etype|Ecomplit) /* sic */
+	l := typecheck(&n.Right, Etype|Ecomplit) // sic
 	t := l.Type
 	if t == nil {
 		n.Type = nil
@@ -3009,9 +2960,8 @@ func typecheckcomplit(np **Node) {
 		}
 		length := int64(0)
 		i := 0
-		var l *Node
 		for ll := n.List; ll != nil; ll = ll.Next {
-			l = ll.N
+			l := ll.N
 			setlineno(l)
 			if l.Op != OKEY {
 				l = Nod(OKEY, Nodintconst(int64(i)), l)
@@ -3024,7 +2974,7 @@ func typecheckcomplit(np **Node) {
 			evconst(l.Left)
 			i = nonnegconst(l.Left)
 			if i < 0 && l.Left.Diag == 0 {
-				Yyerror("array index must be non-negative integer constant")
+				Yyerror("index must be non-negative integer constant")
 				l.Left.Diag = 1
 				i = -(1 << 30) // stay negative for a while
 			}
@@ -3046,7 +2996,7 @@ func typecheckcomplit(np **Node) {
 			pushtype(r, t.Type)
 			typecheck(&r, Erv)
 			defaultlit(&r, t.Type)
-			l.Right = assignconv(r, t.Type, "array element")
+			l.Right = assignconv(r, t.Type, "array or slice literal")
 		}
 
 		if t.Bound == -100 {
@@ -3098,11 +3048,10 @@ func typecheckcomplit(np **Node) {
 				setlineno(ll.N)
 				typecheck(&ll.N, Erv)
 				if f == nil {
-					tmp12 := bad
-					bad++
-					if tmp12 == 0 {
+					if bad == 0 {
 						Yyerror("too many values in struct initializer")
 					}
+					bad++
 					continue
 				}
 
@@ -3135,11 +3084,10 @@ func typecheckcomplit(np **Node) {
 				l = ll.N
 				setlineno(l)
 				if l.Op != OKEY {
-					tmp13 := bad
-					bad++
-					if tmp13 == 0 {
+					if bad == 0 {
 						Yyerror("mixture of field:value and value initializers")
 					}
+					bad++
 					typecheck(&ll.N, Erv)
 					continue
 				}
@@ -3202,9 +3150,7 @@ func typecheckcomplit(np **Node) {
 	return
 }
 
-/*
- * lvalue etc
- */
+// lvalue etc
 func islvalue(n *Node) bool {
 	switch n.Op {
 	case OINDEX:
@@ -3303,11 +3249,9 @@ func samesafeexpr(l *Node, r *Node) bool {
 	return false
 }
 
-/*
- * type check assignment.
- * if this assignment is the definition of a var on the left side,
- * fill in the var's type.
- */
+// type check assignment.
+// if this assignment is the definition of a var on the left side,
+// fill in the var's type.
 func typecheckas(n *Node) {
 	// delicate little dance.
 	// the definition of n may refer to this assignment
@@ -3402,7 +3346,7 @@ func typecheckas2(n *Node) {
 		}
 		switch r.Op {
 		case OCALLMETH, OCALLINTER, OCALLFUNC:
-			if r.Type.Etype != TSTRUCT || r.Type.Funarg == 0 {
+			if r.Type.Etype != TSTRUCT || !r.Type.Funarg {
 				break
 			}
 			cr = structcount(r.Type)
@@ -3476,9 +3420,7 @@ out:
 	}
 }
 
-/*
- * type check function definition
- */
+// type check function definition
 func typecheckfunc(n *Node) {
 	typecheck(&n.Func.Nname, Erv|Easgn)
 	t := n.Func.Nname.Type
@@ -3488,7 +3430,7 @@ func typecheckfunc(n *Node) {
 	n.Type = t
 	t.Nname = n.Func.Nname
 	rcvr := getthisx(t).Type
-	if rcvr != nil && n.Func.Shortname != nil && !isblank(n.Func.Shortname) {
+	if rcvr != nil && n.Func.Shortname != nil {
 		addmethod(n.Func.Shortname.Sym, t, true, n.Func.Nname.Nointerface)
 	}
 
@@ -3502,7 +3444,7 @@ func typecheckfunc(n *Node) {
 func stringtoarraylit(np **Node) {
 	n := *np
 	if n.Left.Op != OLITERAL || n.Left.Val().Ctype() != CTSTR {
-		Fatal("stringtoarraylit %v", n)
+		Fatalf("stringtoarraylit %v", n)
 	}
 
 	s := n.Left.Val().U.(string)
@@ -3566,7 +3508,7 @@ var mapqueue *NodeList
 func copytype(n *Node, t *Type) {
 	if t.Etype == TFORW {
 		// This type isn't computed yet; when it is, update n.
-		t.Copyto = list(t.Copyto, n)
+		t.Copyto = append(t.Copyto, n)
 
 		return
 	}
@@ -3583,17 +3525,16 @@ func copytype(n *Node, t *Type) {
 	if n.Name != nil {
 		t.Vargen = n.Name.Vargen
 	}
-	t.Siggen = 0
 	t.Method = nil
 	t.Xmethod = nil
 	t.Nod = nil
-	t.Printed = 0
-	t.Deferwidth = 0
+	t.Printed = false
+	t.Deferwidth = false
 	t.Copyto = nil
 
 	// Update nodes waiting on this type.
-	for ; l != nil; l = l.Next {
-		copytype(l.N, t)
+	for _, n := range l {
+		copytype(n, t)
 	}
 
 	// Double-check use of type as embedded type.
@@ -3702,19 +3643,16 @@ func typecheckdef(n *Node) *Node {
 		return n
 	}
 
-	l := new(NodeList)
-	l.N = n
-	l.Next = typecheckdefstack
-	typecheckdefstack = l
-
+	typecheckdefstack = append(typecheckdefstack, n)
 	if n.Walkdef == 2 {
 		Flusherrors()
 		fmt.Printf("typecheckdef loop:")
-		for l := typecheckdefstack; l != nil; l = l.Next {
-			fmt.Printf(" %v", l.N.Sym)
+		for i := len(typecheckdefstack) - 1; i >= 0; i-- {
+			n := typecheckdefstack[i]
+			fmt.Printf(" %v", n.Sym)
 		}
 		fmt.Printf("\n")
-		Fatal("typecheckdef loop")
+		Fatalf("typecheckdef loop")
 	}
 
 	n.Walkdef = 2
@@ -3725,7 +3663,7 @@ func typecheckdef(n *Node) *Node {
 
 	switch n.Op {
 	default:
-		Fatal("typecheckdef %v", Oconv(int(n.Op), 0))
+		Fatalf("typecheckdef %v", Oconv(int(n.Op), 0))
 
 		// not really syms
 	case OGOTO, OLABEL:
@@ -3808,7 +3746,7 @@ func typecheckdef(n *Node) *Node {
 				break
 			}
 
-			Fatal("var without type, init: %v", n.Sym)
+			Fatalf("var without type, init: %v", n.Sym)
 		}
 
 		if n.Name.Defn.Op == ONAME {
@@ -3831,7 +3769,7 @@ func typecheckdef(n *Node) *Node {
 		if n.Type.Etype == TFORW && nerrors > nerrors0 {
 			// Something went wrong during type-checking,
 			// but it was reported. Silence future errors.
-			n.Type.Broke = 1
+			n.Type.Broke = true
 		}
 
 		if Curfn != nil {
@@ -3845,39 +3783,40 @@ func typecheckdef(n *Node) *Node {
 
 ret:
 	if n.Op != OLITERAL && n.Type != nil && isideal(n.Type) {
-		Fatal("got %v for %v", n.Type, n)
+		Fatalf("got %v for %v", n.Type, n)
 	}
-	if typecheckdefstack.N != n {
-		Fatal("typecheckdefstack mismatch")
+	last := len(typecheckdefstack) - 1
+	if typecheckdefstack[last] != n {
+		Fatalf("typecheckdefstack mismatch")
 	}
-	l = typecheckdefstack
-	typecheckdefstack = l.Next
+	typecheckdefstack[last] = nil
+	typecheckdefstack = typecheckdefstack[:last]
 
 	lineno = int32(lno)
 	n.Walkdef = 1
 	return n
 }
 
-func checkmake(t *Type, arg string, n *Node) int {
+func checkmake(t *Type, arg string, n *Node) bool {
 	if n.Op == OLITERAL {
 		switch n.Val().Ctype() {
 		case CTINT, CTRUNE, CTFLT, CTCPLX:
 			n.SetVal(toint(n.Val()))
 			if mpcmpfixc(n.Val().U.(*Mpint), 0) < 0 {
 				Yyerror("negative %s argument in make(%v)", arg, t)
-				return -1
+				return false
 			}
 
 			if Mpcmpfixfix(n.Val().U.(*Mpint), Maxintval[TINT]) > 0 {
 				Yyerror("%s argument too large in make(%v)", arg, t)
-				return -1
+				return false
 			}
 
 			// Delay defaultlit until after we've checked range, to avoid
 			// a redundant "constant NNN overflows int" error.
 			defaultlit(&n, Types[TINT])
 
-			return 0
+			return true
 
 		default:
 			break
@@ -3886,13 +3825,13 @@ func checkmake(t *Type, arg string, n *Node) int {
 
 	if !Isint[n.Type.Etype] && n.Type.Etype != TIDEAL {
 		Yyerror("non-integer %s argument in make(%v) - %v", arg, t, n.Type)
-		return -1
+		return false
 	}
 
 	// Defaultlit still necessary for non-constant: n might be 1<<k.
 	defaultlit(&n, Types[TINT])
 
-	return 0
+	return true
 }
 
 func markbreak(n *Node, implicit *Node) {
diff --git a/src/cmd/compile/internal/gc/unsafe.go b/src/cmd/compile/internal/gc/unsafe.go
index a01765b..8884374 100644
--- a/src/cmd/compile/internal/gc/unsafe.go
+++ b/src/cmd/compile/internal/gc/unsafe.go
@@ -6,13 +6,11 @@ package gc
 
 import "cmd/internal/obj"
 
-/*
- * look for
- *	unsafe.Sizeof
- *	unsafe.Offsetof
- *	unsafe.Alignof
- * rewrite with a constant
- */
+// look for
+//	unsafe.Sizeof
+//	unsafe.Offsetof
+//	unsafe.Alignof
+// rewrite with a constant
 func unsafenmagic(nn *Node) *Node {
 	fn := nn.Left
 	args := nn.List
@@ -89,7 +87,7 @@ func unsafenmagic(nn *Node) *Node {
 
 			default:
 				Dump("unsafenmagic", r)
-				Fatal("impossible %v node after dot insertion", Oconv(int(r1.Op), obj.FmtSharp))
+				Fatalf("impossible %v node after dot insertion", Oconv(int(r1.Op), obj.FmtSharp))
 				goto bad
 			}
 		}
diff --git a/src/cmd/compile/internal/gc/util.go b/src/cmd/compile/internal/gc/util.go
index c59af06..7ed3b39 100644
--- a/src/cmd/compile/internal/gc/util.go
+++ b/src/cmd/compile/internal/gc/util.go
@@ -4,55 +4,12 @@ import (
 	"os"
 	"runtime"
 	"runtime/pprof"
-	"strconv"
-	"strings"
 )
 
 func (n *Node) Line() string {
 	return Ctxt.LineHist.LineString(int(n.Lineno))
 }
 
-func atoi(s string) int {
-	// NOTE: Not strconv.Atoi, accepts hex and octal prefixes.
-	n, _ := strconv.ParseInt(s, 0, 0)
-	return int(n)
-}
-
-func isalnum(c int) bool {
-	return isalpha(c) || isdigit(c)
-}
-
-func isalpha(c int) bool {
-	return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
-}
-
-func isdigit(c int) bool {
-	return '0' <= c && c <= '9'
-}
-
-func plan9quote(s string) string {
-	if s == "" {
-		return "'" + strings.Replace(s, "'", "''", -1) + "'"
-	}
-	for i := 0; i < len(s); i++ {
-		if s[i] <= ' ' || s[i] == '\'' {
-			return "'" + strings.Replace(s, "'", "''", -1) + "'"
-		}
-	}
-	return s
-}
-
-// strings.Compare, introduced in Go 1.5.
-func stringsCompare(a, b string) int {
-	if a == b {
-		return 0
-	}
-	if a < b {
-		return -1
-	}
-	return +1
-}
-
 var atExitFuncs []func()
 
 func AtExit(f func()) {
@@ -78,10 +35,10 @@ func startProfile() {
 	if cpuprofile != "" {
 		f, err := os.Create(cpuprofile)
 		if err != nil {
-			Fatal("%v", err)
+			Fatalf("%v", err)
 		}
 		if err := pprof.StartCPUProfile(f); err != nil {
-			Fatal("%v", err)
+			Fatalf("%v", err)
 		}
 		AtExit(pprof.StopCPUProfile)
 	}
@@ -91,12 +48,12 @@ func startProfile() {
 		}
 		f, err := os.Create(memprofile)
 		if err != nil {
-			Fatal("%v", err)
+			Fatalf("%v", err)
 		}
 		AtExit(func() {
 			runtime.GC() // profile all outstanding allocations
 			if err := pprof.WriteHeapProfile(f); err != nil {
-				Fatal("%v", err)
+				Fatalf("%v", err)
 			}
 		})
 	}
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index af3e1cc..e008317 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -182,7 +182,7 @@ func walkstmt(np **Node) {
 		ORECOVER,
 		OGETG:
 		if n.Typecheck == 0 {
-			Fatal("missing typecheck: %v", Nconv(n, obj.FmtSign))
+			Fatalf("missing typecheck: %v", Nconv(n, obj.FmtSign))
 		}
 		init := n.Ninit
 		n.Ninit = nil
@@ -196,7 +196,7 @@ func walkstmt(np **Node) {
 	// the value received.
 	case ORECV:
 		if n.Typecheck == 0 {
-			Fatal("missing typecheck: %v", Nconv(n, obj.FmtSign))
+			Fatalf("missing typecheck: %v", Nconv(n, obj.FmtSign))
 		}
 		init := n.Ninit
 		n.Ninit = nil
@@ -216,7 +216,8 @@ func walkstmt(np **Node) {
 		ODCLCONST,
 		ODCLTYPE,
 		OCHECKNIL,
-		OVARKILL:
+		OVARKILL,
+		OVARLIVE:
 		break
 
 	case OBLOCK:
@@ -231,13 +232,13 @@ func walkstmt(np **Node) {
 		walkstmt(&n.Right)
 
 	case ODEFER:
-		Hasdefer = 1
+		hasdefer = true
 		switch n.Left.Op {
 		case OPRINT, OPRINTN:
 			walkprintfunc(&n.Left, &n.Ninit)
 
 		case OCOPY:
-			n.Left = copyany(n.Left, &n.Ninit, 1)
+			n.Left = copyany(n.Left, &n.Ninit, true)
 
 		default:
 			walkexpr(&n.Left, &n.Ninit)
@@ -269,7 +270,7 @@ func walkstmt(np **Node) {
 			walkprintfunc(&n.Left, &n.Ninit)
 
 		case OCOPY:
-			n.Left = copyany(n.Left, &n.Ninit, 1)
+			n.Left = copyany(n.Left, &n.Ninit, true)
 
 		default:
 			walkexpr(&n.Left, &n.Ninit)
@@ -283,12 +284,12 @@ func walkstmt(np **Node) {
 		if n.List == nil {
 			break
 		}
-		if (Curfn.Type.Outnamed != 0 && count(n.List) > 1) || paramoutheap(Curfn) {
+		if (Curfn.Type.Outnamed && count(n.List) > 1) || paramoutheap(Curfn) {
 			// assign to the function out parameters,
 			// so that reorder3 can fix up conflicts
 			var rl *NodeList
 
-			var cl uint8
+			var cl Class
 			for ll := Curfn.Func.Dcl; ll != nil; ll = ll.Next {
 				cl = ll.N.Class &^ PHEAP
 				if cl == PAUTO {
@@ -299,6 +300,12 @@ func walkstmt(np **Node) {
 				}
 			}
 
+			if got, want := count(n.List), count(rl); got != want {
+				// order should have rewritten multi-value function calls
+				// with explicit OAS2FUNC nodes.
+				Fatalf("expected %v return arguments, have %v", want, got)
+			}
+
 			if samelist(rl, n.List) {
 				// special return in disguise
 				n.List = nil
@@ -306,26 +313,18 @@ func walkstmt(np **Node) {
 				break
 			}
 
-			if count(n.List) == 1 && count(rl) > 1 {
-				// OAS2FUNC in disguise
-				f := n.List.N
-
-				if f.Op != OCALLFUNC && f.Op != OCALLMETH && f.Op != OCALLINTER {
-					Fatal("expected return of call, have %v", f)
-				}
-				n.List = concat(list1(f), ascompatet(int(n.Op), rl, &f.Type, 0, &n.Ninit))
-				break
-			}
-
 			// move function calls out, to make reorder3's job easier.
 			walkexprlistsafe(n.List, &n.Ninit)
 
-			ll := ascompatee(int(n.Op), rl, n.List, &n.Ninit)
+			ll := ascompatee(n.Op, rl, n.List, &n.Ninit)
 			n.List = reorder3(ll)
+			for lr := n.List; lr != nil; lr = lr.Next {
+				lr.N = applywritebarrier(lr.N, &n.Ninit)
+			}
 			break
 		}
 
-		ll := ascompatte(int(n.Op), nil, false, Getoutarg(Curfn.Type), n.List, 1, &n.Ninit)
+		ll := ascompatte(n.Op, nil, false, Getoutarg(Curfn.Type), n.List, 1, &n.Ninit)
 		n.List = ll
 
 	case ORETJMP:
@@ -346,7 +345,7 @@ func walkstmt(np **Node) {
 	}
 
 	if n.Op == ONAME {
-		Fatal("walkstmt ended up with name: %v", Nconv(n, obj.FmtSign))
+		Fatalf("walkstmt ended up with name: %v", Nconv(n, obj.FmtSign))
 	}
 
 	*np = n
@@ -366,13 +365,11 @@ func isSmallMakeSlice(n *Node) bool {
 	return Smallintconst(l) && Smallintconst(r) && (t.Type.Width == 0 || Mpgetfix(r.Val().U.(*Mpint)) < (1<<16)/t.Type.Width)
 }
 
-/*
- * walk the whole tree of the body of an
- * expression or simple statement.
- * the types expressions are calculated.
- * compile-time constants are evaluated.
- * complex side effects like statements are appended to init
- */
+// walk the whole tree of the body of an
+// expression or simple statement.
+// the types expressions are calculated.
+// compile-time constants are evaluated.
+// complex side effects like statements are appended to init
 func walkexprlist(l *NodeList, init **NodeList) {
 	for ; l != nil; l = l.Next {
 		walkexpr(&l.N, init)
@@ -404,7 +401,7 @@ func walkexpr(np **Node, init **NodeList) {
 		// not okay to use n->ninit when walking n,
 		// because we might replace n with some other node
 		// and would lose the init list.
-		Fatal("walkexpr init == &n->ninit")
+		Fatalf("walkexpr init == &n->ninit")
 	}
 
 	if n.Ninit != nil {
@@ -427,13 +424,14 @@ func walkexpr(np **Node, init **NodeList) {
 	}
 
 	if n.Typecheck != 1 {
-		Fatal("missed typecheck: %v\n", Nconv(n, obj.FmtSign))
+		Fatalf("missed typecheck: %v\n", Nconv(n, obj.FmtSign))
 	}
 
+opswitch:
 	switch n.Op {
 	default:
 		Dump("walk", n)
-		Fatal("walkexpr: switch 1 unknown op %v", Nconv(n, obj.FmtShort|obj.FmtSign))
+		Fatalf("walkexpr: switch 1 unknown op %v", Nconv(n, obj.FmtShort|obj.FmtSign))
 
 	case OTYPE,
 		ONONAME,
@@ -441,7 +439,6 @@ func walkexpr(np **Node, init **NodeList) {
 		OEMPTY,
 		OPARAM,
 		OGETG:
-		goto ret
 
 	case ONOT,
 		OMINUS,
@@ -452,16 +449,13 @@ func walkexpr(np **Node, init **NodeList) {
 		ODOTMETH,
 		ODOTINTER:
 		walkexpr(&n.Left, init)
-		goto ret
 
 	case OIND:
 		walkexpr(&n.Left, init)
-		goto ret
 
 	case ODOT:
 		usefield(n)
 		walkexpr(&n.Left, init)
-		goto ret
 
 	case ODOTPTR:
 		usefield(n)
@@ -473,16 +467,13 @@ func walkexpr(np **Node, init **NodeList) {
 		}
 
 		walkexpr(&n.Left, init)
-		goto ret
 
 	case OEFACE:
 		walkexpr(&n.Left, init)
 		walkexpr(&n.Right, init)
-		goto ret
 
 	case OSPTR, OITAB:
 		walkexpr(&n.Left, init)
-		goto ret
 
 	case OLEN, OCAP:
 		walkexpr(&n.Left, init)
@@ -500,8 +491,6 @@ func walkexpr(np **Node, init **NodeList) {
 			n.Typecheck = 1
 		}
 
-		goto ret
-
 	case OLSH, ORSH:
 		walkexpr(&n.Left, init)
 		walkexpr(&n.Right, init)
@@ -510,7 +499,6 @@ func walkexpr(np **Node, init **NodeList) {
 		if Debug['m'] != 0 && n.Etype != 0 && !Isconst(n.Right, CTINT) {
 			Warn("shift bounds check elided")
 		}
-		goto ret
 
 		// Use results from call expression as arguments for complex.
 	case OAND,
@@ -530,13 +518,11 @@ func walkexpr(np **Node, init **NodeList) {
 
 		walkexpr(&n.Left, init)
 		walkexpr(&n.Right, init)
-		goto ret
 
 	case OOR, OXOR:
 		walkexpr(&n.Left, init)
 		walkexpr(&n.Right, init)
 		walkrotate(&n)
-		goto ret
 
 	case OEQ, ONE:
 		walkexpr(&n.Left, init)
@@ -552,7 +538,6 @@ func walkexpr(np **Node, init **NodeList) {
 		safemode = 0
 		walkcompare(&n, init)
 		safemode = old_safemode
-		goto ret
 
 	case OANDAND, OOROR:
 		walkexpr(&n.Left, init)
@@ -564,45 +549,37 @@ func walkexpr(np **Node, init **NodeList) {
 
 		walkexpr(&n.Right, &ll)
 		addinit(&n.Right, ll)
-		goto ret
 
 	case OPRINT, OPRINTN:
 		walkexprlist(n.List, init)
 		n = walkprint(n, init)
-		goto ret
 
 	case OPANIC:
 		n = mkcall("gopanic", nil, init, n.Left)
-		goto ret
 
 	case ORECOVER:
 		n = mkcall("gorecover", n.Type, init, Nod(OADDR, nodfp, nil))
-		goto ret
 
 	case OLITERAL:
 		n.Addable = true
-		goto ret
 
 	case OCLOSUREVAR, OCFUNC:
 		n.Addable = true
-		goto ret
 
 	case ONAME:
 		if n.Class&PHEAP == 0 && n.Class != PPARAMREF {
 			n.Addable = true
 		}
-		goto ret
 
 	case OCALLINTER:
 		t := n.Left.Type
 		if n.List != nil && n.List.N.Op == OAS {
-			goto ret
+			break
 		}
 		walkexpr(&n.Left, init)
 		walkexprlist(n.List, init)
-		ll := ascompatte(int(n.Op), n, n.Isddd, getinarg(t), n.List, 0, init)
+		ll := ascompatte(n.Op, n, n.Isddd, getinarg(t), n.List, 0, init)
 		n.List = reorder1(ll)
-		goto ret
 
 	case OCALLFUNC:
 		if n.Left.Op == OCLOSURE {
@@ -632,7 +609,7 @@ func walkexpr(np **Node, init **NodeList) {
 
 		t := n.Left.Type
 		if n.List != nil && n.List.N.Op == OAS {
-			goto ret
+			break
 		}
 
 		walkexpr(&n.Left, init)
@@ -644,28 +621,26 @@ func walkexpr(np **Node, init **NodeList) {
 				n.Op = OSQRT
 				n.Left = n.List.N
 				n.List = nil
-				goto ret
+				break opswitch
 			}
 		}
 
-		ll := ascompatte(int(n.Op), n, n.Isddd, getinarg(t), n.List, 0, init)
+		ll := ascompatte(n.Op, n, n.Isddd, getinarg(t), n.List, 0, init)
 		n.List = reorder1(ll)
-		goto ret
 
 	case OCALLMETH:
 		t := n.Left.Type
 		if n.List != nil && n.List.N.Op == OAS {
-			goto ret
+			break
 		}
 		walkexpr(&n.Left, init)
 		walkexprlist(n.List, init)
-		ll := ascompatte(int(n.Op), n, false, getthis(t), list1(n.Left.Left), 0, init)
-		lr := ascompatte(int(n.Op), n, n.Isddd, getinarg(t), n.List, 0, init)
+		ll := ascompatte(n.Op, n, false, getthis(t), list1(n.Left.Left), 0, init)
+		lr := ascompatte(n.Op, n, n.Isddd, getinarg(t), n.List, 0, init)
 		ll = concat(ll, lr)
 		n.Left.Left = nil
 		ullmancalc(n.Left)
 		n.List = reorder1(ll)
-		goto ret
 
 	case OAS:
 		*init = concat(*init, n.Ninit)
@@ -675,11 +650,11 @@ func walkexpr(np **Node, init **NodeList) {
 		n.Left = safeexpr(n.Left, init)
 
 		if oaslit(n, init) {
-			goto ret
+			break
 		}
 
-		if n.Right == nil || iszero(n.Right) && flag_race == 0 {
-			goto ret
+		if n.Right == nil || iszero(n.Right) && !instrumenting {
+			break
 		}
 
 		switch n.Right.Op {
@@ -690,7 +665,7 @@ func walkexpr(np **Node, init **NodeList) {
 			// TODO(rsc): The Isfat is for consistency with componentgen and orderexpr.
 			// It needs to be removed in all three places.
 			// That would allow inlining x.(struct{*int}) the same as x.(*int).
-			if isdirectiface(n.Right.Type) && !Isfat(n.Right.Type) && flag_race == 0 {
+			if isdirectiface(n.Right.Type) && !Isfat(n.Right.Type) && !instrumenting {
 				// handled directly during cgen
 				walkexpr(&n.Right, init)
 				break
@@ -713,7 +688,7 @@ func walkexpr(np **Node, init **NodeList) {
 
 			n = mkcall1(fn, nil, init, typename(r.Type), r.Left, n1)
 			walkexpr(&n, init)
-			goto ret
+			break opswitch
 
 		case ORECV:
 			// x = <-c; n.Left is x, n.Right.Left is c.
@@ -724,7 +699,7 @@ func walkexpr(np **Node, init **NodeList) {
 			r := n.Right.Left // the channel
 			n = mkcall1(chanfn("chanrecv1", 2, r.Type), nil, init, typename(r.Type), r, n1)
 			walkexpr(&n, init)
-			goto ret
+			break opswitch
 
 		case OAPPEND:
 			// x = append(...)
@@ -738,7 +713,7 @@ func walkexpr(np **Node, init **NodeList) {
 			if r.Op == OAPPEND {
 				// Left in place for back end.
 				// Do not add a new write barrier.
-				goto ret
+				break opswitch
 			}
 			// Otherwise, lowered for race detector.
 			// Treat as ordinary assignment.
@@ -751,8 +726,6 @@ func walkexpr(np **Node, init **NodeList) {
 			n = applywritebarrier(n, init)
 		}
 
-		goto ret
-
 	case OAS2:
 		*init = concat(*init, n.Ninit)
 		n.Ninit = nil
@@ -764,7 +737,6 @@ func walkexpr(np **Node, init **NodeList) {
 			lr.N = applywritebarrier(lr.N, init)
 		}
 		n = liststmt(ll)
-		goto ret
 
 		// a,b,... = fn()
 	case OAS2FUNC:
@@ -775,12 +747,11 @@ func walkexpr(np **Node, init **NodeList) {
 		walkexprlistsafe(n.List, init)
 		walkexpr(&r, init)
 
-		ll := ascompatet(int(n.Op), n.List, &r.Type, 0, init)
+		ll := ascompatet(n.Op, n.List, &r.Type, 0, init)
 		for lr := ll; lr != nil; lr = lr.Next {
 			lr.N = applywritebarrier(lr.N, init)
 		}
 		n = liststmt(concat(list1(r), ll))
-		goto ret
 
 		// x, y = <-c
 	// orderstmt made sure x is addressable.
@@ -802,7 +773,6 @@ func walkexpr(np **Node, init **NodeList) {
 		r = mkcall1(fn, n.List.Next.N.Type, init, typename(r.Left.Type), r.Left, n1)
 		n = Nod(OAS, n.List.Next.N, r)
 		typecheck(&n, Etop)
-		goto ret
 
 		// a,b = m[i];
 	case OAS2MAPR:
@@ -816,14 +786,12 @@ func walkexpr(np **Node, init **NodeList) {
 		t := r.Left.Type
 		p := ""
 		if t.Type.Width <= 128 { // Check ../../runtime/hashmap.go:maxValueSize before changing.
-			switch Simsimtype(t.Down) {
-			case TINT32, TUINT32:
+			switch algtype(t.Down) {
+			case AMEM32:
 				p = "mapaccess2_fast32"
-
-			case TINT64, TUINT64:
+			case AMEM64:
 				p = "mapaccess2_fast64"
-
-			case TSTRING:
+			case ASTRING:
 				p = "mapaccess2_faststr"
 			}
 		}
@@ -872,13 +840,7 @@ func walkexpr(np **Node, init **NodeList) {
 		typecheck(&n, Etop)
 		walkexpr(&n, init)
 
-		// mapaccess needs a zero value to be at least this big.
-		if zerosize < t.Type.Width {
-			zerosize = t.Type.Width
-		}
-
 		// TODO: ptr is always non-nil, so disable nil check for this OIND op.
-		goto ret
 
 	case ODELETE:
 		*init = concat(*init, n.Ninit)
@@ -893,18 +855,17 @@ func walkexpr(np **Node, init **NodeList) {
 
 		t := map_.Type
 		n = mkcall1(mapfndel("mapdelete", t), nil, init, typename(t), map_, key)
-		goto ret
 
 	case OAS2DOTTYPE:
 		e := n.Rlist.N // i.(T)
 		// TODO(rsc): The Isfat is for consistency with componentgen and orderexpr.
 		// It needs to be removed in all three places.
 		// That would allow inlining x.(struct{*int}) the same as x.(*int).
-		if isdirectiface(e.Type) && !Isfat(e.Type) && flag_race == 0 {
+		if isdirectiface(e.Type) && !Isfat(e.Type) && !instrumenting {
 			// handled directly during gen.
 			walkexprlistsafe(n.List, init)
 			walkexpr(&e.Left, init)
-			goto ret
+			break
 		}
 
 		// res, ok = i.(T)
@@ -948,7 +909,7 @@ func walkexpr(np **Node, init **NodeList) {
 				}
 				n = Nod(OAS, ok, fast)
 				typecheck(&n, Etop)
-				goto ret
+				break
 			}
 		}
 
@@ -969,14 +930,12 @@ func walkexpr(np **Node, init **NodeList) {
 		call := mkcall1(fn, oktype, init, typename(t), from, resptr)
 		n = Nod(OAS, ok, call)
 		typecheck(&n, Etop)
-		goto ret
 
 	case ODOTTYPE, ODOTTYPE2:
 		if !isdirectiface(n.Type) || Isfat(n.Type) {
-			Fatal("walkexpr ODOTTYPE") // should see inside OAS only
+			Fatalf("walkexpr ODOTTYPE") // should see inside OAS only
 		}
 		walkexpr(&n.Left, init)
-		goto ret
 
 	case OCONVIFACE:
 		walkexpr(&n.Left, init)
@@ -987,7 +946,7 @@ func walkexpr(np **Node, init **NodeList) {
 			l.Type = n.Type
 			l.Typecheck = n.Typecheck
 			n = l
-			goto ret
+			break
 		}
 
 		// Build name of function: convI2E etc.
@@ -1020,16 +979,15 @@ func walkexpr(np **Node, init **NodeList) {
 			ll = list(ll, l)
 
 			if isdirectiface(n.Left.Type) {
-				/* For pointer types, we can make a special form of optimization
-				 *
-				 * These statements are put onto the expression init list:
-				 * 	Itab *tab = atomicloadtype(&cache);
-				 * 	if(tab == nil)
-				 * 		tab = typ2Itab(type, itype, &cache);
-				 *
-				 * The CONVIFACE expression is replaced with this:
-				 * 	OEFACE{tab, ptr};
-				 */
+				// For pointer types, we can make a special form of optimization
+				//
+				// These statements are put onto the expression init list:
+				// 	Itab *tab = atomicloadtype(&cache);
+				// 	if(tab == nil)
+				// 		tab = typ2Itab(type, itype, &cache);
+				//
+				// The CONVIFACE expression is replaced with this:
+				// 	OEFACE{tab, ptr};
 				l := temp(Ptrto(Types[TUINT8]))
 
 				n1 := Nod(OAS, l, sym.Def)
@@ -1053,7 +1011,7 @@ func walkexpr(np **Node, init **NodeList) {
 				l.Typecheck = n.Typecheck
 				l.Type = n.Type
 				n = l
-				goto ret
+				break
 			}
 		}
 
@@ -1095,37 +1053,35 @@ func walkexpr(np **Node, init **NodeList) {
 		n.List = ll
 		typecheck(&n, Erv)
 		walkexpr(&n, init)
-		goto ret
 
 	case OCONV, OCONVNOP:
 		if Thearch.Thechar == '5' {
 			if Isfloat[n.Left.Type.Etype] {
 				if n.Type.Etype == TINT64 {
 					n = mkcall("float64toint64", n.Type, init, conv(n.Left, Types[TFLOAT64]))
-					goto ret
+					break
 				}
 
 				if n.Type.Etype == TUINT64 {
 					n = mkcall("float64touint64", n.Type, init, conv(n.Left, Types[TFLOAT64]))
-					goto ret
+					break
 				}
 			}
 
 			if Isfloat[n.Type.Etype] {
 				if n.Left.Type.Etype == TINT64 {
 					n = mkcall("int64tofloat64", n.Type, init, conv(n.Left, Types[TINT64]))
-					goto ret
+					break
 				}
 
 				if n.Left.Type.Etype == TUINT64 {
 					n = mkcall("uint64tofloat64", n.Type, init, conv(n.Left, Types[TUINT64]))
-					goto ret
+					break
 				}
 			}
 		}
 
 		walkexpr(&n.Left, init)
-		goto ret
 
 	case OANDNOT:
 		walkexpr(&n.Left, init)
@@ -1133,46 +1089,40 @@ func walkexpr(np **Node, init **NodeList) {
 		n.Right = Nod(OCOM, n.Right, nil)
 		typecheck(&n.Right, Erv)
 		walkexpr(&n.Right, init)
-		goto ret
 
 	case OMUL:
 		walkexpr(&n.Left, init)
 		walkexpr(&n.Right, init)
 		walkmul(&n, init)
-		goto ret
 
 	case ODIV, OMOD:
 		walkexpr(&n.Left, init)
 		walkexpr(&n.Right, init)
 
-		/*
-		 * rewrite complex div into function call.
-		 */
-		et := int(n.Left.Type.Etype)
+		// rewrite complex div into function call.
+		et := n.Left.Type.Etype
 
 		if Iscomplex[et] && n.Op == ODIV {
 			t := n.Type
 			n = mkcall("complex128div", Types[TCOMPLEX128], init, conv(n.Left, Types[TCOMPLEX128]), conv(n.Right, Types[TCOMPLEX128]))
 			n = conv(n, t)
-			goto ret
+			break
 		}
 
 		// Nothing to do for float divisions.
 		if Isfloat[et] {
-			goto ret
+			break
 		}
 
 		// Try rewriting as shifts or magic multiplies.
 		walkdiv(&n, init)
 
-		/*
-		 * rewrite 64-bit div and mod into function calls
-		 * on 32-bit architectures.
-		 */
+		// rewrite 64-bit div and mod into function calls
+		// on 32-bit architectures.
 		switch n.Op {
 		case OMOD, ODIV:
 			if Widthreg >= 8 || (et != TUINT64 && et != TINT64) {
-				goto ret
+				break opswitch
 			}
 			var fn string
 			if et == TINT64 {
@@ -1186,13 +1136,8 @@ func walkexpr(np **Node, init **NodeList) {
 				fn += "mod"
 			}
 			n = mkcall(fn, n.Type, init, conv(n.Left, Types[et]), conv(n.Right, Types[et]))
-
-		default:
-			break
 		}
 
-		goto ret
-
 	case OINDEX:
 		walkexpr(&n.Left, init)
 
@@ -1205,7 +1150,7 @@ func walkexpr(np **Node, init **NodeList) {
 		// if range of type cannot exceed static array bound,
 		// disable bounds check.
 		if n.Bounded {
-			goto ret
+			break
 		}
 		t := n.Left.Type
 		if t != nil && Isptr[t.Etype] {
@@ -1244,11 +1189,10 @@ func walkexpr(np **Node, init **NodeList) {
 				Yyerror("index out of bounds")
 			}
 		}
-		goto ret
 
 	case OINDEXMAP:
 		if n.Etype == 1 {
-			goto ret
+			break
 		}
 		walkexpr(&n.Left, init)
 		walkexpr(&n.Right, init)
@@ -1256,14 +1200,12 @@ func walkexpr(np **Node, init **NodeList) {
 		t := n.Left.Type
 		p := ""
 		if t.Type.Width <= 128 { // Check ../../runtime/hashmap.go:maxValueSize before changing.
-			switch Simsimtype(t.Down) {
-			case TINT32, TUINT32:
+			switch algtype(t.Down) {
+			case AMEM32:
 				p = "mapaccess1_fast32"
-
-			case TINT64, TUINT64:
+			case AMEM64:
 				p = "mapaccess1_fast64"
-
-			case TSTRING:
+			case ASTRING:
 				p = "mapaccess1_faststr"
 			}
 		}
@@ -1285,14 +1227,8 @@ func walkexpr(np **Node, init **NodeList) {
 		n.Type = t.Type
 		n.Typecheck = 1
 
-		// mapaccess needs a zero value to be at least this big.
-		if zerosize < t.Type.Width {
-			zerosize = t.Type.Width
-		}
-		goto ret
-
 	case ORECV:
-		Fatal("walkexpr ORECV") // should see inside OAS only
+		Fatalf("walkexpr ORECV") // should see inside OAS only
 
 	case OSLICE, OSLICEARR, OSLICESTR:
 		walkexpr(&n.Left, init)
@@ -1303,7 +1239,6 @@ func walkexpr(np **Node, init **NodeList) {
 		}
 		walkexpr(&n.Right.Right, init)
 		n = reduceSlice(n)
-		goto ret
 
 	case OSLICE3, OSLICE3ARR:
 		walkexpr(&n.Left, init)
@@ -1325,18 +1260,15 @@ func walkexpr(np **Node, init **NodeList) {
 				n.Op = OSLICEARR
 			}
 			n = reduceSlice(n)
-			goto ret
 		}
-		goto ret
 
 	case OADDR:
 		walkexpr(&n.Left, init)
-		goto ret
 
 	case ONEW:
 		if n.Esc == EscNone {
 			if n.Type.Type.Width >= 1<<16 {
-				Fatal("large ONEW with EscNone: %v", n)
+				Fatalf("large ONEW with EscNone: %v", n)
 			}
 			r := temp(n.Type.Type)
 			r = Nod(OAS, r, nil) // zero temp
@@ -1349,33 +1281,34 @@ func walkexpr(np **Node, init **NodeList) {
 			n = callnew(n.Type.Type)
 		}
 
-		goto ret
-
 		// If one argument to the comparison is an empty string,
 	// comparing the lengths instead will yield the same result
 	// without the function call.
 	case OCMPSTR:
 		if (Isconst(n.Left, CTSTR) && len(n.Left.Val().U.(string)) == 0) || (Isconst(n.Right, CTSTR) && len(n.Right.Val().U.(string)) == 0) {
-			r := Nod(int(n.Etype), Nod(OLEN, n.Left, nil), Nod(OLEN, n.Right, nil))
+			// TODO(marvin): Fix Node.EType type union.
+			r := Nod(Op(n.Etype), Nod(OLEN, n.Left, nil), Nod(OLEN, n.Right, nil))
 			typecheck(&r, Erv)
 			walkexpr(&r, init)
 			r.Type = n.Type
 			n = r
-			goto ret
+			break
 		}
 
 		// s + "badgerbadgerbadger" == "badgerbadgerbadger"
-		if (n.Etype == OEQ || n.Etype == ONE) && Isconst(n.Right, CTSTR) && n.Left.Op == OADDSTR && count(n.Left.List) == 2 && Isconst(n.Left.List.Next.N, CTSTR) && cmpslit(n.Right, n.Left.List.Next.N) == 0 {
-			r := Nod(int(n.Etype), Nod(OLEN, n.Left.List.N, nil), Nodintconst(0))
+		if (Op(n.Etype) == OEQ || Op(n.Etype) == ONE) && Isconst(n.Right, CTSTR) && n.Left.Op == OADDSTR && count(n.Left.List) == 2 && Isconst(n.Left.List.Next.N, CTSTR) && strlit(n.Right) == strlit(n.Left.List.Next.N) {
+			// TODO(marvin): Fix Node.EType type union.
+			r := Nod(Op(n.Etype), Nod(OLEN, n.Left.List.N, nil), Nodintconst(0))
 			typecheck(&r, Erv)
 			walkexpr(&r, init)
 			r.Type = n.Type
 			n = r
-			goto ret
+			break
 		}
 
 		var r *Node
-		if n.Etype == OEQ || n.Etype == ONE {
+		// TODO(marvin): Fix Node.EType type union.
+		if Op(n.Etype) == OEQ || Op(n.Etype) == ONE {
 			// prepare for rewrite below
 			n.Left = cheapexpr(n.Left, init)
 
@@ -1385,7 +1318,8 @@ func walkexpr(np **Node, init **NodeList) {
 
 			// quick check of len before full compare for == or !=
 			// eqstring assumes that the lengths are equal
-			if n.Etype == OEQ {
+			// TODO(marvin): Fix Node.EType type union.
+			if Op(n.Etype) == OEQ {
 				// len(left) == len(right) && eqstring(left, right)
 				r = Nod(OANDAND, Nod(OEQ, Nod(OLEN, n.Left, nil), Nod(OLEN, n.Right, nil)), r)
 			} else {
@@ -1401,28 +1335,26 @@ func walkexpr(np **Node, init **NodeList) {
 			// sys_cmpstring(s1, s2) :: 0
 			r = mkcall("cmpstring", Types[TINT], init, conv(n.Left, Types[TSTRING]), conv(n.Right, Types[TSTRING]))
 
-			r = Nod(int(n.Etype), r, Nodintconst(0))
+			// TODO(marvin): Fix Node.EType type union.
+			r = Nod(Op(n.Etype), r, Nodintconst(0))
 		}
 
 		typecheck(&r, Erv)
 		if n.Type.Etype != TBOOL {
-			Fatal("cmp %v", n.Type)
+			Fatalf("cmp %v", n.Type)
 		}
 		r.Type = n.Type
 		n = r
-		goto ret
 
 	case OADDSTR:
 		n = addstr(n, init)
-		goto ret
 
 	case OAPPEND:
 		// order should make sure we only see OAS(node, OAPPEND), which we handle above.
-		Fatal("append outside assignment")
+		Fatalf("append outside assignment")
 
 	case OCOPY:
-		n = copyany(n, init, flag_race)
-		goto ret
+		n = copyany(n, init, instrumenting)
 
 		// cannot use chanfn - closechan takes any, not chan any
 	case OCLOSE:
@@ -1430,11 +1362,9 @@ func walkexpr(np **Node, init **NodeList) {
 
 		substArgTypes(fn, n.Left.Type)
 		n = mkcall1(fn, nil, init, n.Left)
-		goto ret
 
 	case OMAKECHAN:
 		n = mkcall1(chanfn("makechan", 1, n.Type), n.Type, init, typename(n.Type), conv(n.Left, Types[TINT64]))
-		goto ret
 
 	case OMAKEMAP:
 		t := n.Type
@@ -1465,7 +1395,6 @@ func walkexpr(np **Node, init **NodeList) {
 
 		substArgTypes(fn, hmap(t), mapbucket(t), t.Down, t.Type)
 		n = mkcall1(fn, n.Type, init, typename(n.Type), conv(n.Left, Types[TINT64]), a, r)
-		goto ret
 
 	case OMAKESLICE:
 		l := n.Left
@@ -1477,7 +1406,7 @@ func walkexpr(np **Node, init **NodeList) {
 		t := n.Type
 		if n.Esc == EscNone {
 			if !isSmallMakeSlice(n) {
-				Fatal("non-small OMAKESLICE with EscNone: %v", n)
+				Fatalf("non-small OMAKESLICE with EscNone: %v", n)
 			}
 			// var arr [r]T
 			// n = arr[:l]
@@ -1499,8 +1428,6 @@ func walkexpr(np **Node, init **NodeList) {
 			n = mkcall1(fn, n.Type, init, typename(n.Type), conv(l, Types[TINT64]), conv(r, Types[TINT64]))
 		}
 
-		goto ret
-
 	case ORUNESTR:
 		a := nodnil()
 		if n.Esc == EscNone {
@@ -1512,8 +1439,6 @@ func walkexpr(np **Node, init **NodeList) {
 		// intstring(*[4]byte, rune)
 		n = mkcall("intstring", n.Type, init, a, conv(n.Left, Types[TINT64]))
 
-		goto ret
-
 	case OARRAYBYTESTR:
 		a := nodnil()
 		if n.Esc == EscNone {
@@ -1526,14 +1451,10 @@ func walkexpr(np **Node, init **NodeList) {
 		// slicebytetostring(*[32]byte, []byte) string;
 		n = mkcall("slicebytetostring", n.Type, init, a, n.Left)
 
-		goto ret
-
 		// slicebytetostringtmp([]byte) string;
 	case OARRAYBYTESTRTMP:
 		n = mkcall("slicebytetostringtmp", n.Type, init, n.Left)
 
-		goto ret
-
 		// slicerunetostring(*[32]byte, []rune) string;
 	case OARRAYRUNESTR:
 		a := nodnil()
@@ -1546,7 +1467,6 @@ func walkexpr(np **Node, init **NodeList) {
 		}
 
 		n = mkcall("slicerunetostring", n.Type, init, a, n.Left)
-		goto ret
 
 		// stringtoslicebyte(*32[byte], string) []byte;
 	case OSTRARRAYBYTE:
@@ -1560,14 +1480,11 @@ func walkexpr(np **Node, init **NodeList) {
 		}
 
 		n = mkcall("stringtoslicebyte", n.Type, init, a, conv(n.Left, Types[TSTRING]))
-		goto ret
 
 		// stringtoslicebytetmp(string) []byte;
 	case OSTRARRAYBYTETMP:
 		n = mkcall("stringtoslicebytetmp", n.Type, init, conv(n.Left, Types[TSTRING]))
 
-		goto ret
-
 		// stringtoslicerune(*[32]rune, string) []rune
 	case OSTRARRAYRUNE:
 		a := nodnil()
@@ -1580,12 +1497,11 @@ func walkexpr(np **Node, init **NodeList) {
 		}
 
 		n = mkcall("stringtoslicerune", n.Type, init, a, n.Left)
-		goto ret
 
 		// ifaceeq(i1 any-1, i2 any-2) (ret bool);
 	case OCMPIFACE:
 		if !Eqtype(n.Left.Type, n.Right.Type) {
-			Fatal("ifaceeq %v %v %v", Oconv(int(n.Op), 0), n.Left.Type, n.Right.Type)
+			Fatalf("ifaceeq %v %v %v", Oconv(int(n.Op), 0), n.Left.Type, n.Right.Type)
 		}
 		var fn *Node
 		if isnilinter(n.Left.Type) {
@@ -1598,12 +1514,14 @@ func walkexpr(np **Node, init **NodeList) {
 		n.Left = cheapexpr(n.Left, init)
 		substArgTypes(fn, n.Right.Type, n.Left.Type)
 		r := mkcall1(fn, n.Type, init, n.Left, n.Right)
-		if n.Etype == ONE {
+		// TODO(marvin): Fix Node.EType type union.
+		if Op(n.Etype) == ONE {
 			r = Nod(ONOT, r, nil)
 		}
 
 		// check itable/type before full compare.
-		if n.Etype == OEQ {
+		// TODO(marvin): Fix Node.EType type union.
+		if Op(n.Etype) == OEQ {
 			r = Nod(OANDAND, Nod(OEQ, Nod(OITAB, n.Left, nil), Nod(OITAB, n.Right, nil)), r)
 		} else {
 			r = Nod(OOROR, Nod(ONE, Nod(OITAB, n.Left, nil), Nod(OITAB, n.Right, nil)), r)
@@ -1612,13 +1530,11 @@ func walkexpr(np **Node, init **NodeList) {
 		walkexpr(&r, init)
 		r.Type = n.Type
 		n = r
-		goto ret
 
 	case OARRAYLIT, OMAPLIT, OSTRUCTLIT, OPTRLIT:
 		var_ := temp(n.Type)
 		anylit(0, n, var_, init)
 		n = var_
-		goto ret
 
 	case OSEND:
 		n1 := n.Right
@@ -1626,25 +1542,19 @@ func walkexpr(np **Node, init **NodeList) {
 		walkexpr(&n1, init)
 		n1 = Nod(OADDR, n1, nil)
 		n = mkcall1(chanfn("chansend1", 2, n.Left.Type), nil, init, typename(n.Left.Type), n.Left, n1)
-		goto ret
 
 	case OCLOSURE:
 		n = walkclosure(n, init)
-		goto ret
 
 	case OCALLPART:
 		n = walkpartialcall(n, init)
-		goto ret
 	}
 
-	Fatal("missing switch %v", Oconv(int(n.Op), 0))
-
 	// Expressions that are constant at run time but not
 	// considered const by the language spec are not turned into
 	// constants until walk. For example, if n is y%1 == 0, the
 	// walk of y%1 may have replaced it by 0.
 	// Check whether n with its updated args is itself now a constant.
-ret:
 	t := n.Type
 
 	evconst(n)
@@ -1679,7 +1589,7 @@ func reduceSlice(n *Node) *Node {
 	return n
 }
 
-func ascompatee1(op int, l *Node, r *Node, init **NodeList) *Node {
+func ascompatee1(op Op, l *Node, r *Node, init **NodeList) *Node {
 	// convas will turn map assigns into function calls,
 	// making it impossible for reorder3 to work.
 	n := Nod(OAS, l, r)
@@ -1691,12 +1601,10 @@ func ascompatee1(op int, l *Node, r *Node, init **NodeList) *Node {
 	return convas(n, init)
 }
 
-func ascompatee(op int, nl *NodeList, nr *NodeList, init **NodeList) *NodeList {
-	/*
-	 * check assign expression list to
-	 * a expression list. called in
-	 *	expr-list = expr-list
-	 */
+func ascompatee(op Op, nl *NodeList, nr *NodeList, init **NodeList) *NodeList {
+	// check assign expression list to
+	// a expression list. called in
+	//	expr-list = expr-list
 
 	// ensure order of evaluation for function calls
 	for ll := nl; ll != nil; ll = ll.Next {
@@ -1724,12 +1632,10 @@ func ascompatee(op int, nl *NodeList, nr *NodeList, init **NodeList) *NodeList {
 	return nn
 }
 
-/*
- * l is an lv and rt is the type of an rv
- * return 1 if this implies a function call
- * evaluating the lv or a function call
- * in the conversion of the types
- */
+// l is an lv and rt is the type of an rv
+// return 1 if this implies a function call
+// evaluating the lv or a function call
+// in the conversion of the types
 func fncall(l *Node, rt *Type) bool {
 	if l.Ullman >= UINF || l.Op == OINDEXMAP {
 		return true
@@ -1744,18 +1650,16 @@ func fncall(l *Node, rt *Type) bool {
 	return true
 }
 
-func ascompatet(op int, nl *NodeList, nr **Type, fp int, init **NodeList) *NodeList {
+func ascompatet(op Op, nl *NodeList, nr **Type, fp int, init **NodeList) *NodeList {
 	var l *Node
 	var tmp *Node
 	var a *Node
 	var ll *NodeList
 	var saver Iter
 
-	/*
-	 * check assign type list to
-	 * a expression list. called in
-	 *	expr-list = func()
-	 */
+	// check assign type list to
+	// a expression list. called in
+	//	expr-list = func()
 	r := Structfirst(&saver, nr)
 
 	var nn *NodeList
@@ -1800,14 +1704,12 @@ func ascompatet(op int, nl *NodeList, nr **Type, fp int, init **NodeList) *NodeL
 	}
 
 	if ucount != 0 {
-		Fatal("ascompatet: too many function calls evaluating parameters")
+		Fatalf("ascompatet: too many function calls evaluating parameters")
 	}
 	return concat(nn, mm)
 }
 
-/*
-* package all the arguments that match a ... T parameter into a []T.
- */
+// package all the arguments that match a ... T parameter into a []T.
 func mkdotargslice(lr0 *NodeList, nn *NodeList, l *Type, fp int, init **NodeList, ddd *Node) *NodeList {
 	esc := uint16(EscUnknown)
 	if ddd != nil {
@@ -1831,7 +1733,7 @@ func mkdotargslice(lr0 *NodeList, nn *NodeList, l *Type, fp int, init **NodeList
 		n.Esc = esc
 		typecheck(&n, Erv)
 		if n.Type == nil {
-			Fatal("mkdotargslice: typecheck failed")
+			Fatalf("mkdotargslice: typecheck failed")
 		}
 		walkexpr(&n, init)
 	}
@@ -1841,9 +1743,7 @@ func mkdotargslice(lr0 *NodeList, nn *NodeList, l *Type, fp int, init **NodeList
 	return nn
 }
 
-/*
- * helpers for shape errors
- */
+// helpers for shape errors
 func dumptypes(nl **Type, what string) string {
 	var savel Iter
 
@@ -1887,13 +1787,11 @@ func dumpnodetypes(l *NodeList, what string) string {
 	return fmt_
 }
 
-/*
- * check assign expression list to
- * a type list. called in
- *	return expr-list
- *	func(expr-list)
- */
-func ascompatte(op int, call *Node, isddd bool, nl **Type, lr *NodeList, fp int, init **NodeList) *NodeList {
+// check assign expression list to
+// a type list. called in
+//	return expr-list
+//	func(expr-list)
+func ascompatte(op Op, call *Node, isddd bool, nl **Type, lr *NodeList, fp int, init **NodeList) *NodeList {
 	var savel Iter
 
 	lr0 := lr
@@ -1909,7 +1807,7 @@ func ascompatte(op int, call *Node, isddd bool, nl **Type, lr *NodeList, fp int,
 	var l2 string
 	var ll *Type
 	var l1 string
-	if r != nil && lr.Next == nil && r.Type.Etype == TSTRUCT && r.Type.Funarg != 0 {
+	if r != nil && lr.Next == nil && r.Type.Etype == TSTRUCT && r.Type.Funarg {
 		// optimization - can do block copy
 		if eqtypenoname(r.Type, *nl) {
 			a := nodarg(*nl, fp)
@@ -2006,9 +1904,9 @@ func walkprint(nn *Node, init **NodeList) *Node {
 	var n *Node
 	var on *Node
 	var t *Type
-	var et int
+	var et EType
 
-	op := int(nn.Op)
+	op := nn.Op
 	all := nn.List
 	var calls *NodeList
 	notfirst := false
@@ -2049,7 +1947,7 @@ func walkprint(nn *Node, init **NodeList) *Node {
 		}
 
 		t = n.Type
-		et = int(n.Type.Etype)
+		et = n.Type.Etype
 		if Isinter(n.Type) {
 			if isnilinter(n.Type) {
 				on = syslook("printeface", 1)
@@ -2234,8 +2132,6 @@ func needwritebarrier(l *Node, r *Node) bool {
 
 // TODO(rsc): Perhaps componentgen should run before this.
 
-var applywritebarrier_bv Bvec
-
 func applywritebarrier(n *Node, init **NodeList) *Node {
 	if n.Left != nil && n.Right != nil && needwritebarrier(n.Left, n.Right) {
 		if Debug_wb > 1 {
@@ -2249,7 +2145,7 @@ func applywritebarrier(n *Node, init **NodeList) *Node {
 
 func convas(n *Node, init **NodeList) *Node {
 	if n.Op != OAS {
-		Fatal("convas: not OAS %v", Oconv(int(n.Op), 0))
+		Fatalf("convas: not OAS %v", Oconv(int(n.Op), 0))
 	}
 
 	n.Typecheck = 1
@@ -2297,14 +2193,12 @@ out:
 	return n
 }
 
-/*
- * from ascompat[te]
- * evaluating actual function arguments.
- *	f(a,b)
- * if there is exactly one function expr,
- * then it is done first. otherwise must
- * make temp variables
- */
+// from ascompat[te]
+// evaluating actual function arguments.
+//	f(a,b)
+// if there is exactly one function expr,
+// then it is done first. otherwise must
+// make temp variables
 func reorder1(all *NodeList) *NodeList {
 	var n *Node
 
@@ -2361,14 +2255,12 @@ func reorder1(all *NodeList) *NodeList {
 	return concat(g, r)
 }
 
-/*
- * from ascompat[ee]
- *	a,b = c,d
- * simultaneous assignment. there cannot
- * be later use of an earlier lvalue.
- *
- * function calls have been removed.
- */
+// from ascompat[ee]
+//	a,b = c,d
+// simultaneous assignment. there cannot
+// be later use of an earlier lvalue.
+//
+// function calls have been removed.
 func reorder3(all *NodeList) *NodeList {
 	var l *Node
 
@@ -2400,7 +2292,7 @@ func reorder3(all *NodeList) *NodeList {
 
 		switch l.Op {
 		default:
-			Fatal("reorder3 unexpected lvalue %v", Oconv(int(l.Op), obj.FmtSharp))
+			Fatalf("reorder3 unexpected lvalue %v", Oconv(int(l.Op), obj.FmtSharp))
 
 		case ONAME:
 			break
@@ -2424,12 +2316,10 @@ func reorder3(all *NodeList) *NodeList {
 	return concat(early, all)
 }
 
-/*
- * if the evaluation of *np would be affected by the
- * assignments in all up to but not including stop,
- * copy into a temporary during *early and
- * replace *np with that temp.
- */
+// if the evaluation of *np would be affected by the
+// assignments in all up to but not including stop,
+// copy into a temporary during *early and
+// replace *np with that temp.
 func reorder3save(np **Node, all *NodeList, stop *NodeList, early **NodeList) {
 	n := *np
 	if !aliased(n, all, stop) {
@@ -2443,14 +2333,12 @@ func reorder3save(np **Node, all *NodeList, stop *NodeList, early **NodeList) {
 	*np = q.Left
 }
 
-/*
- * what's the outer value that a write to n affects?
- * outer value means containing struct or array.
- */
+// what's the outer value that a write to n affects?
+// outer value means containing struct or array.
 func outervalue(n *Node) *Node {
 	for {
 		if n.Op == OXDOT {
-			Fatal("OXDOT in walk")
+			Fatalf("OXDOT in walk")
 		}
 		if n.Op == ODOT || n.Op == OPAREN || n.Op == OCONVNOP {
 			n = n.Left
@@ -2468,10 +2356,8 @@ func outervalue(n *Node) *Node {
 	return n
 }
 
-/*
- * Is it possible that the computation of n might be
- * affected by writes in as up to but not including stop?
- */
+// Is it possible that the computation of n might be
+// affected by writes in as up to but not including stop?
 func aliased(n *Node, all *NodeList, stop *NodeList) bool {
 	if n == nil {
 		return false
@@ -2532,11 +2418,9 @@ func aliased(n *Node, all *NodeList, stop *NodeList) bool {
 	return true
 }
 
-/*
- * does the evaluation of n only refer to variables
- * whose addresses have not been taken?
- * (and no other memory)
- */
+// does the evaluation of n only refer to variables
+// whose addresses have not been taken?
+// (and no other memory)
 func varexpr(n *Node) bool {
 	if n == nil {
 		return true
@@ -2585,9 +2469,7 @@ func varexpr(n *Node) bool {
 	return false
 }
 
-/*
- * is the name l mentioned in r?
- */
+// is the name l mentioned in r?
 func vmatch2(l *Node, r *Node) bool {
 	if r == nil {
 		return false
@@ -2615,14 +2497,10 @@ func vmatch2(l *Node, r *Node) bool {
 	return false
 }
 
-/*
- * is any name mentioned in l also mentioned in r?
- * called by sinit.go
- */
+// is any name mentioned in l also mentioned in r?
+// called by sinit.go
 func vmatch1(l *Node, r *Node) bool {
-	/*
-	 * isolate all left sides
-	 */
+	// isolate all left sides
 	if l == nil || r == nil {
 		return false
 	}
@@ -2660,11 +2538,9 @@ func vmatch1(l *Node, r *Node) bool {
 	return false
 }
 
-/*
- * walk through argin parameters.
- * generate and return code to allocate
- * copies of escaped parameters to the heap.
- */
+// walk through argin parameters.
+// generate and return code to allocate
+// copies of escaped parameters to the heap.
 func paramstoheap(argin **Type, out int) *NodeList {
 	var savet Iter
 	var v *Node
@@ -2710,9 +2586,7 @@ func paramstoheap(argin **Type, out int) *NodeList {
 	return nn
 }
 
-/*
- * walk through argout parameters copying back to stack
- */
+// walk through argout parameters copying back to stack
 func returnsfromheap(argin **Type) *NodeList {
 	var savet Iter
 	var v *Node
@@ -2729,11 +2603,9 @@ func returnsfromheap(argin **Type) *NodeList {
 	return nn
 }
 
-/*
- * take care of migrating any function in/out args
- * between the stack and the heap.  adds code to
- * curfn's before and after lists.
- */
+// take care of migrating any function in/out args
+// between the stack and the heap.  adds code to
+// curfn's before and after lists.
 func heapmoves() {
 	lno := lineno
 	lineno = Curfn.Lineno
@@ -2748,7 +2620,7 @@ func heapmoves() {
 
 func vmkcall(fn *Node, t *Type, init **NodeList, va []*Node) *Node {
 	if fn.Type == nil || fn.Type.Etype != TFUNC {
-		Fatal("mkcall %v %v", fn, fn.Type)
+		Fatalf("mkcall %v %v", fn, fn.Type)
 	}
 
 	var args *NodeList
@@ -2789,12 +2661,12 @@ func conv(n *Node, t *Type) *Node {
 
 func chanfn(name string, n int, t *Type) *Node {
 	if t.Etype != TCHAN {
-		Fatal("chanfn %v", t)
+		Fatalf("chanfn %v", t)
 	}
 	fn := syslook(name, 1)
 	switch n {
 	default:
-		Fatal("chanfn %d", n)
+		Fatalf("chanfn %d", n)
 	case 1:
 		substArgTypes(fn, t.Type)
 	case 2:
@@ -2805,7 +2677,7 @@ func chanfn(name string, n int, t *Type) *Node {
 
 func mapfn(name string, t *Type) *Node {
 	if t.Etype != TMAP {
-		Fatal("mapfn %v", t)
+		Fatalf("mapfn %v", t)
 	}
 	fn := syslook(name, 1)
 	substArgTypes(fn, t.Down, t.Type, t.Down, t.Type)
@@ -2814,7 +2686,7 @@ func mapfn(name string, t *Type) *Node {
 
 func mapfndel(name string, t *Type) *Node {
 	if t.Etype != TMAP {
-		Fatal("mapfn %v", t)
+		Fatalf("mapfn %v", t)
 	}
 	fn := syslook(name, 1)
 	substArgTypes(fn, t.Down, t.Type, t.Down)
@@ -2949,7 +2821,7 @@ func appendslice(n *Node, init **NodeList) *Node {
 		substArgTypes(fn, l1.Type, l2.Type)
 		nt := mkcall1(fn, Types[TINT], &l, typename(l1.Type.Type), nptr1, nptr2)
 		l = list(l, nt)
-	} else if flag_race != 0 {
+	} else if instrumenting {
 		// rely on runtime to instrument copy.
 		// copy(s[len(l1):len(l1)+len(l2)], l2)
 		nptr1 := Nod(OSLICE, s, Nod(OKEY, Nod(OLEN, l1, nil), Nod(OADD, Nod(OLEN, l1, nil), Nod(OLEN, l2, nil))))
@@ -3048,8 +2920,8 @@ func walkappend(n *Node, init **NodeList, dst *Node) *Node {
 	}
 
 	// General case, with no function calls left as arguments.
-	// Leave for gen, except that race detector requires old form
-	if flag_race == 0 {
+	// Leave for gen, except that instrumentation requires old form.
+	if !instrumenting {
 		return n
 	}
 
@@ -3102,13 +2974,13 @@ func walkappend(n *Node, init **NodeList, dst *Node) *Node {
 //
 // Also works if b is a string.
 //
-func copyany(n *Node, init **NodeList, runtimecall int) *Node {
+func copyany(n *Node, init **NodeList, runtimecall bool) *Node {
 	if haspointers(n.Left.Type.Type) {
 		fn := writebarrierfn("typedslicecopy", n.Left.Type, n.Right.Type)
 		return mkcall1(fn, n.Type, init, typename(n.Left.Type.Type), n.Left, n.Right)
 	}
 
-	if runtimecall != 0 {
+	if runtimecall {
 		var fn *Node
 		if n.Right.Type.Etype == TSTRING {
 			fn = syslook("slicestringcopy", 1)
@@ -3165,7 +3037,7 @@ func eqfor(t *Type, needsize *int) *Node {
 	a := algtype1(t, nil)
 
 	if a != AMEM && a != -1 {
-		Fatal("eqfor %v", t)
+		Fatalf("eqfor %v", t)
 	}
 
 	if a == AMEM {
@@ -3277,7 +3149,7 @@ func walkcompare(np **Node, init **NodeList) {
 	}
 
 	if !islvalue(cmpl) || !islvalue(cmpr) {
-		Fatal("arguments of comparison must be lvalues - %v %v", cmpl, cmpr)
+		Fatalf("arguments of comparison must be lvalues - %v %v", cmpl, cmpr)
 	}
 
 	l = temp(Ptrto(t))
@@ -3292,7 +3164,7 @@ func walkcompare(np **Node, init **NodeList) {
 	typecheck(&a, Etop)
 	*init = list(*init, a)
 
-	andor := OANDAND
+	var andor Op = OANDAND
 	if n.Op == ONE {
 		andor = OOROR
 	}
@@ -3306,7 +3178,7 @@ func walkcompare(np **Node, init **NodeList) {
 		for i := 0; int64(i) < t.Bound; i++ {
 			li = Nod(OINDEX, l, Nodintconst(int64(i)))
 			ri = Nod(OINDEX, r, Nodintconst(int64(i)))
-			a = Nod(int(n.Op), li, ri)
+			a = Nod(n.Op, li, ri)
 			if expr == nil {
 				expr = a
 			} else {
@@ -3332,7 +3204,7 @@ func walkcompare(np **Node, init **NodeList) {
 			}
 			li = Nod(OXDOT, l, newname(t1.Sym))
 			ri = Nod(OXDOT, r, newname(t1.Sym))
-			a = Nod(int(n.Op), li, ri)
+			a = Nod(n.Op, li, ri)
 			if expr == nil {
 				expr = a
 			} else {
@@ -3413,7 +3285,7 @@ func samecheap(a *Node, b *Node) bool {
 }
 
 func walkrotate(np **Node) {
-	if Thearch.Thechar == '7' || Thearch.Thechar == '9' {
+	if Thearch.Thechar == '0' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
 		return
 	}
 
@@ -3466,9 +3338,7 @@ func walkrotate(np **Node) {
 	return
 }
 
-/*
- * walkmul rewrites integer multiplication by powers of two as shifts.
- */
+// walkmul rewrites integer multiplication by powers of two as shifts.
 func walkmul(np **Node, init **NodeList) {
 	n := *np
 	if !Isint[n.Type.Etype] {
@@ -3537,15 +3407,13 @@ ret:
 	*np = n
 }
 
-/*
- * walkdiv rewrites division by a constant as less expensive
- * operations.
- */
+// walkdiv rewrites division by a constant as less expensive
+// operations.
 func walkdiv(np **Node, init **NodeList) {
 	// if >= 0, nr is 1<<pow // 1 if nr is negative.
 
 	// TODO(minux)
-	if Thearch.Thechar == '7' || Thearch.Thechar == '9' {
+	if Thearch.Thechar == '0' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
 		return
 	}
 
@@ -3868,7 +3736,7 @@ func usefield(n *Node) {
 
 	switch n.Op {
 	default:
-		Fatal("usefield %v", Oconv(int(n.Op), 0))
+		Fatalf("usefield %v", Oconv(int(n.Op), 0))
 
 	case ODOT, ODOTPTR:
 		break
@@ -3880,7 +3748,7 @@ func usefield(n *Node) {
 	}
 	field := dotField[typeSym{t.Orig, n.Right.Sym}]
 	if field == nil {
-		Fatal("usefield %v %v without paramfld", n.Left.Type, n.Right.Sym)
+		Fatalf("usefield %v %v without paramfld", n.Left.Type, n.Right.Sym)
 	}
 	if field.Note == nil || !strings.Contains(*field.Note, "go:\"track\"") {
 		return
@@ -4051,7 +3919,7 @@ func walkprintfunc(np **Node, init **NodeList) {
 	Curfn = nil
 	funchdr(fn)
 
-	a = Nod(int(n.Op), nil, nil)
+	a = Nod(n.Op, nil, nil)
 	a.List = printargs
 	typecheck(&a, Etop)
 	walkstmt(&a)
diff --git a/src/cmd/compile/internal/gc/y.go b/src/cmd/compile/internal/gc/y.go
deleted file mode 100644
index 2b61c07..0000000
--- a/src/cmd/compile/internal/gc/y.go
+++ /dev/null
@@ -1,3526 +0,0 @@
-//line go.y:21
-package gc
-
-import __yyfmt__ "fmt"
-
-//line go.y:21
-import (
-	"fmt"
-	"strings"
-)
-
-//line go.y:28
-type yySymType struct {
-	yys  int
-	node *Node
-	list *NodeList
-	typ  *Type
-	sym  *Sym
-	val  Val
-	i    int
-}
-
-const LLITERAL = 57346
-const LASOP = 57347
-const LCOLAS = 57348
-const LBREAK = 57349
-const LCASE = 57350
-const LCHAN = 57351
-const LCONST = 57352
-const LCONTINUE = 57353
-const LDDD = 57354
-const LDEFAULT = 57355
-const LDEFER = 57356
-const LELSE = 57357
-const LFALL = 57358
-const LFOR = 57359
-const LFUNC = 57360
-const LGO = 57361
-const LGOTO = 57362
-const LIF = 57363
-const LIMPORT = 57364
-const LINTERFACE = 57365
-const LMAP = 57366
-const LNAME = 57367
-const LPACKAGE = 57368
-const LRANGE = 57369
-const LRETURN = 57370
-const LSELECT = 57371
-const LSTRUCT = 57372
-const LSWITCH = 57373
-const LTYPE = 57374
-const LVAR = 57375
-const LANDAND = 57376
-const LANDNOT = 57377
-const LBODY = 57378
-const LCOMM = 57379
-const LDEC = 57380
-const LEQ = 57381
-const LGE = 57382
-const LGT = 57383
-const LIGNORE = 57384
-const LINC = 57385
-const LLE = 57386
-const LLSH = 57387
-const LLT = 57388
-const LNE = 57389
-const LOROR = 57390
-const LRSH = 57391
-const NotPackage = 57392
-const NotParen = 57393
-const PreferToRightParen = 57394
-
-var yyToknames = [...]string{
-	"$end",
-	"error",
-	"$unk",
-	"LLITERAL",
-	"LASOP",
-	"LCOLAS",
-	"LBREAK",
-	"LCASE",
-	"LCHAN",
-	"LCONST",
-	"LCONTINUE",
-	"LDDD",
-	"LDEFAULT",
-	"LDEFER",
-	"LELSE",
-	"LFALL",
-	"LFOR",
-	"LFUNC",
-	"LGO",
-	"LGOTO",
-	"LIF",
-	"LIMPORT",
-	"LINTERFACE",
-	"LMAP",
-	"LNAME",
-	"LPACKAGE",
-	"LRANGE",
-	"LRETURN",
-	"LSELECT",
-	"LSTRUCT",
-	"LSWITCH",
-	"LTYPE",
-	"LVAR",
-	"LANDAND",
-	"LANDNOT",
-	"LBODY",
-	"LCOMM",
-	"LDEC",
-	"LEQ",
-	"LGE",
-	"LGT",
-	"LIGNORE",
-	"LINC",
-	"LLE",
-	"LLSH",
-	"LLT",
-	"LNE",
-	"LOROR",
-	"LRSH",
-	"'+'",
-	"'-'",
-	"'|'",
-	"'^'",
-	"'*'",
-	"'/'",
-	"'%'",
-	"'&'",
-	"NotPackage",
-	"NotParen",
-	"'('",
-	"')'",
-	"PreferToRightParen",
-	"';'",
-	"'.'",
-	"'$'",
-	"'='",
-	"':'",
-	"'{'",
-	"'}'",
-	"'!'",
-	"'~'",
-	"'['",
-	"']'",
-	"'?'",
-	"'@'",
-	"','",
-}
-var yyStatenames = [...]string{}
-
-const yyEofCode = 1
-const yyErrCode = 2
-const yyMaxDepth = 200
-
-//line go.y:2308
-func fixlbrace(lbr int) {
-	// If the opening brace was an LBODY,
-	// set up for another one now that we're done.
-	// See comment in lex.C about loophack.
-	if lbr == LBODY {
-		loophack = 1
-	}
-}
-
-//line yacctab:1
-var yyExca = [...]int{
-	-1, 1,
-	1, -1,
-	-2, 0,
-	-1, 17,
-	1, 1,
-	63, 23,
-	-2, 0,
-	-1, 48,
-	6, 276,
-	66, 276,
-	76, 276,
-	-2, 49,
-	-1, 56,
-	67, 153,
-	-2, 162,
-	-1, 74,
-	60, 181,
-	-2, 215,
-	-1, 75,
-	60, 182,
-	-2, 183,
-	-1, 121,
-	60, 134,
-	64, 134,
-	68, 134,
-	72, 134,
-	-2, 266,
-	-1, 125,
-	60, 134,
-	64, 134,
-	68, 134,
-	72, 134,
-	-2, 267,
-	-1, 176,
-	2, 215,
-	36, 215,
-	60, 181,
-	68, 215,
-	-2, 173,
-	-1, 177,
-	36, 183,
-	60, 182,
-	68, 183,
-	-2, 174,
-	-1, 184,
-	63, 251,
-	69, 251,
-	-2, 0,
-	-1, 242,
-	63, 251,
-	69, 251,
-	-2, 0,
-	-1, 252,
-	8, 251,
-	13, 251,
-	63, 251,
-	69, 251,
-	-2, 0,
-	-1, 325,
-	4, 236,
-	63, 236,
-	69, 236,
-	-2, 157,
-	-1, 403,
-	67, 144,
-	-2, 142,
-	-1, 408,
-	36, 176,
-	60, 176,
-	68, 176,
-	-2, 167,
-	-1, 409,
-	36, 177,
-	60, 177,
-	68, 177,
-	-2, 168,
-	-1, 410,
-	36, 178,
-	60, 178,
-	68, 178,
-	-2, 169,
-	-1, 411,
-	36, 179,
-	60, 179,
-	68, 179,
-	-2, 170,
-	-1, 417,
-	8, 251,
-	13, 251,
-	63, 251,
-	69, 251,
-	-2, 0,
-	-1, 418,
-	63, 251,
-	69, 251,
-	-2, 0,
-	-1, 498,
-	63, 251,
-	69, 251,
-	-2, 0,
-	-1, 553,
-	60, 157,
-	-2, 318,
-	-1, 554,
-	60, 158,
-	-2, 317,
-	-1, 579,
-	8, 251,
-	13, 251,
-	63, 251,
-	69, 251,
-	-2, 0,
-	-1, 593,
-	36, 180,
-	60, 180,
-	68, 180,
-	-2, 171,
-	-1, 632,
-	67, 145,
-	-2, 143,
-}
-
-const yyNprod = 352
-const yyPrivate = 57344
-
-var yyTokenNames []string
-var yyStates []string
-
-const yyLast = 2321
-
-var yyAct = [...]int{
-
-	74, 304, 381, 291, 487, 611, 459, 285, 546, 229,
-	398, 467, 34, 296, 75, 302, 402, 550, 290, 186,
-	286, 479, 458, 356, 400, 401, 389, 338, 103, 318,
-	328, 245, 303, 339, 324, 243, 337, 468, 101, 374,
-	109, 104, 248, 85, 14, 246, 241, 174, 480, 212,
-	6, 181, 325, 155, 470, 469, 325, 385, 332, 517,
-	108, 627, 414, 373, 13, 208, 585, 11, 176, 461,
-	470, 172, 584, 461, 652, 600, 230, 219, 392, 191,
-	106, 322, 177, 542, 226, 322, 423, 321, 193, 88,
-	10, 321, 13, 192, 10, 310, 317, 309, 154, 160,
-	447, 12, 13, 161, 227, 12, 13, 446, 198, 227,
-	10, 162, 227, 320, 209, 227, 462, 384, 228, 663,
-	462, 626, 625, 228, 55, 460, 228, 155, 184, 228,
-	203, 628, 205, 633, 199, 200, 108, 632, 204, 12,
-	13, 222, 393, 12, 13, 86, 214, 216, 218, 90,
-	604, 239, 175, 10, 449, 194, 233, 88, 153, 12,
-	13, 176, 661, 213, 213, 213, 213, 288, 155, 282,
-	282, 601, 282, 537, 417, 177, 445, 280, 10, 176,
-	621, 528, 295, 163, 164, 165, 166, 167, 168, 169,
-	170, 227, 417, 177, 417, 301, 227, 227, 594, 227,
-	485, 88, 12, 13, 185, 228, 417, 524, 48, 308,
-	228, 228, 416, 228, 202, 347, 516, 90, 472, 448,
-	405, 428, 10, 242, 349, 171, 298, 12, 13, 345,
-	343, 341, 227, 581, 507, 330, 344, 507, 182, 508,
-	519, 397, 508, 348, 116, 175, 228, 367, 227, 334,
-	464, 227, 227, 360, 227, 129, 325, 355, 371, 210,
-	346, 90, 228, 175, 353, 228, 228, 362, 228, 182,
-	183, 12, 13, 54, 435, 314, 173, 10, 342, 358,
-	340, 13, 340, 340, 91, 379, 188, 378, 325, 380,
-	376, 331, 365, 375, 176, 623, 369, 394, 505, 417,
-	408, 183, 610, 163, 170, 12, 13, 605, 177, 410,
-	227, 227, 415, 238, 409, 118, 118, 602, 575, 126,
-	227, 569, 559, 331, 228, 228, 12, 13, 466, 465,
-	391, 444, 327, 443, 228, 437, 425, 12, 13, 254,
-	413, 388, 255, 256, 257, 258, 259, 260, 261, 262,
-	263, 264, 265, 266, 267, 268, 269, 270, 271, 272,
-	273, 274, 129, 129, 277, 227, 440, 383, 370, 173,
-	366, 294, 359, 491, 227, 424, 411, 442, 175, 228,
-	10, 455, 493, 333, 454, 436, 100, 492, 228, 300,
-	99, 84, 10, 509, 176, 481, 282, 512, 474, 20,
-	657, 282, 656, 655, 499, 495, 614, 227, 177, 503,
-	654, 484, 10, 227, 340, 340, 234, 515, 520, 521,
-	646, 228, 620, 617, 227, 340, 608, 228, 221, 12,
-	13, 607, 511, 129, 526, 430, 433, 69, 228, 518,
-	227, 12, 13, 598, 597, 129, 596, 293, 96, 494,
-	525, 593, 583, 563, 228, 529, 98, 490, 540, 532,
-	94, 12, 13, 523, 514, 513, 510, 560, 538, 558,
-	97, 95, 330, 323, 329, 539, 497, 496, 175, 483,
-	555, 477, 227, 476, 10, 473, 441, 562, 432, 421,
-	227, 372, 297, 386, 565, 615, 228, 491, 491, 606,
-	571, 573, 173, 92, 228, 403, 493, 493, 176, 10,
-	403, 492, 492, 340, 574, 340, 197, 554, 10, 114,
-	457, 340, 177, 434, 340, 572, 580, 439, 10, 578,
-	354, 591, 592, 12, 13, 253, 588, 568, 251, 180,
-	340, 197, 586, 587, 110, 533, 197, 609, 535, 197,
-	432, 348, 197, 107, 117, 382, 70, 502, 12, 13,
-	287, 7, 5, 102, 432, 211, 24, 12, 13, 129,
-	16, 19, 227, 494, 494, 651, 129, 12, 13, 431,
-	456, 490, 490, 364, 429, 561, 228, 335, 282, 207,
-	206, 618, 175, 129, 129, 624, 622, 120, 481, 491,
-	121, 125, 173, 636, 631, 630, 188, 619, 493, 21,
-	340, 638, 305, 492, 642, 340, 643, 306, 641, 336,
-	57, 351, 352, 640, 93, 644, 252, 645, 197, 176,
-	26, 340, 512, 197, 197, 28, 197, 76, 158, 387,
-	157, 666, 653, 177, 582, 390, 159, 491, 530, 156,
-	498, 658, 579, 662, 418, 534, 493, 31, 22, 15,
-	664, 492, 23, 665, 122, 122, 201, 18, 340, 197,
-	668, 3, 123, 554, 667, 494, 340, 8, 9, 282,
-	4, 2, 1, 490, 451, 197, 215, 544, 197, 197,
-	56, 197, 89, 566, 545, 548, 549, 612, 488, 323,
-	249, 531, 189, 105, 105, 112, 115, 80, 81, 576,
-	577, 329, 438, 175, 119, 119, 173, 72, 119, 71,
-	237, 478, 340, 494, 149, 340, 403, 316, 589, 403,
-	403, 490, 220, 326, 150, 244, 649, 197, 151, 141,
-	142, 143, 144, 145, 146, 147, 148, 197, 197, 629,
-	650, 127, 17, 450, 595, 399, 319, 197, 25, 89,
-	27, 36, 37, 78, 471, 281, 49, 66, 111, 39,
-	38, 35, 124, 279, 278, 105, 149, 83, 79, 10,
-	105, 73, 217, 112, 82, 113, 150, 247, 504, 616,
-	151, 232, 506, 87, 188, 145, 146, 147, 148, 0,
-	0, 0, 197, 0, 223, 0, 0, 0, 196, 235,
-	197, 197, 240, 128, 231, 0, 0, 0, 634, 635,
-	236, 0, 0, 0, 0, 639, 77, 0, 12, 13,
-	225, 0, 0, 0, 292, 647, 648, 173, 0, 0,
-	403, 0, 0, 0, 197, 0, 0, 0, 0, 0,
-	197, 0, 541, 0, 543, 0, 552, 56, 0, 0,
-	556, 197, 0, 557, 0, 0, 0, 347, 0, 0,
-	0, 0, 119, 119, 0, 0, 349, 197, 0, 567,
-	0, 345, 343, 341, 0, 0, 0, 0, 344, 0,
-	0, 311, 357, 0, 0, 348, 312, 313, 105, 315,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 346, 0, 0, 56, 0, 0, 613, 197,
-	275, 276, 0, 283, 247, 56, 247, 197, 0, 0,
-	342, 0, 363, 13, 197, 197, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 599,
-	0, 377, 134, 149, 603, 152, 0, 135, 139, 140,
-	0, 0, 138, 150, 137, 136, 133, 151, 141, 142,
-	143, 144, 145, 146, 147, 148, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 422, 0, 0,
-	0, 361, 0, 0, 414, 0, 0, 0, 0, 0,
-	407, 0, 0, 368, 0, 0, 89, 637, 0, 197,
-	419, 420, 552, 0, 0, 0, 0, 0, 0, 347,
-	426, 0, 0, 463, 0, 0, 0, 357, 349, 0,
-	0, 0, 105, 345, 343, 341, 197, 0, 0, 105,
-	344, 0, 0, 112, 0, 486, 247, 348, 0, 0,
-	0, 0, 0, 0, 0, 0, 134, 149, 0, 152,
-	0, 135, 139, 140, 346, 407, 138, 150, 137, 136,
-	133, 151, 141, 142, 143, 144, 145, 146, 147, 148,
-	0, 0, 342, 0, 197, 13, 0, 0, 0, 0,
-	56, 56, 0, 0, 0, 396, 0, 0, 119, 0,
-	119, 0, 0, 0, 0, 0, 0, 311, 536, 0,
-	119, 0, 247, 522, 0, 0, 0, 0, 0, 0,
-	0, 547, 551, 0, 527, 0, 0, 475, 0, 0,
-	357, 0, 0, 463, 482, 0, 0, 463, 0, 0,
-	0, 0, 564, 357, 0, 0, 0, 0, 0, 0,
-	0, 275, 276, 0, 0, 0, 0, 0, 307, 0,
-	68, 0, 247, 41, 0, 78, 47, 42, 0, 0,
-	44, 56, 40, 50, 124, 43, 45, 53, 0, 83,
-	79, 10, 570, 0, 46, 52, 82, 51, 32, 30,
-	0, 0, 0, 65, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 60, 61, 0, 64,
-	58, 0, 0, 59, 0, 0, 67, 0, 0, 0,
-	0, 0, 0, 0, 308, 0, 62, 63, 77, 0,
-	12, 13, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 29, 105, 68, 247, 0, 41, 0, 78, 47,
-	42, 0, 56, 44, 0, 40, 50, 33, 43, 45,
-	53, 0, 83, 79, 10, 0, 0, 46, 52, 82,
-	51, 32, 30, 0, 0, 547, 65, 0, 551, 357,
-	0, 0, 463, 0, 0, 0, 357, 0, 357, 60,
-	61, 0, 64, 58, 0, 0, 59, 0, 68, 67,
-	0, 0, 0, 78, 0, 0, 0, 0, 0, 62,
-	63, 77, 124, 12, 13, 0, 0, 83, 79, 10,
-	68, 0, 0, 0, 82, 78, 0, 0, 0, 0,
-	0, 65, 0, 0, 124, 0, 0, 0, 0, 83,
-	79, 10, 0, 0, 60, 61, 82, 64, 58, 0,
-	0, 59, 0, 68, 67, 0, 0, 0, 78, 0,
-	0, 0, 404, 0, 62, 63, 77, 124, 12, 13,
-	0, 0, 83, 79, 10, 0, 67, 0, 0, 82,
-	0, 0, 0, 0, 0, 0, 65, 0, 77, 0,
-	12, 13, 0, 0, 0, 0, 0, 0, 0, 60,
-	61, 0, 64, 58, 0, 0, 59, 0, 68, 67,
-	0, 0, 0, 78, 0, 0, 0, 590, 0, 62,
-	63, 77, 124, 12, 13, 0, 0, 83, 79, 10,
-	0, 501, 0, 0, 82, 0, 0, 0, 0, 0,
-	0, 65, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 60, 61, 0, 64, 58, 0,
-	0, 59, 0, 68, 67, 0, 0, 0, 78, 0,
-	0, 0, 0, 0, 62, 63, 77, 124, 12, 13,
-	0, 0, 83, 79, 10, 0, 500, 0, 0, 82,
-	0, 0, 0, 0, 0, 0, 65, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 60,
-	61, 0, 64, 58, 0, 0, 59, 0, 68, 67,
-	0, 0, 0, 78, 0, 0, 0, 78, 0, 62,
-	63, 77, 124, 12, 13, 0, 124, 83, 79, 10,
-	0, 83, 79, 10, 82, 0, 395, 0, 82, 0,
-	0, 179, 0, 0, 0, 232, 0, 0, 0, 0,
-	0, 68, 0, 0, 60, 61, 78, 64, 178, 0,
-	0, 59, 196, 0, 67, 124, 0, 0, 489, 0,
-	83, 79, 10, 0, 62, 63, 77, 82, 12, 13,
-	77, 0, 12, 13, 179, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 60, 61, 0,
-	64, 178, 0, 0, 59, 0, 68, 67, 289, 0,
-	0, 78, 0, 0, 0, 0, 0, 62, 63, 77,
-	124, 12, 13, 0, 0, 83, 79, 10, 0, 284,
-	0, 0, 82, 0, 0, 0, 0, 0, 0, 65,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 68,
-	0, 0, 60, 61, 78, 64, 58, 187, 0, 59,
-	0, 0, 67, 124, 0, 0, 0, 0, 83, 79,
-	10, 0, 62, 63, 77, 82, 12, 13, 0, 0,
-	0, 0, 65, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 68, 0, 0, 60, 61, 78, 64, 58,
-	0, 0, 59, 0, 0, 67, 124, 0, 0, 0,
-	0, 83, 79, 10, 0, 62, 63, 77, 82, 12,
-	13, 0, 0, 0, 0, 65, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 68, 0, 0, 60, 61,
-	78, 64, 58, 0, 0, 59, 0, 0, 67, 124,
-	0, 0, 0, 0, 83, 79, 10, 0, 62, 63,
-	77, 82, 12, 13, 0, 0, 0, 0, 179, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 68, 0,
-	0, 60, 61, 299, 64, 178, 0, 0, 59, 0,
-	0, 67, 124, 0, 0, 0, 0, 83, 79, 10,
-	0, 62, 63, 77, 82, 12, 13, 0, 0, 0,
-	0, 65, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 60, 61, 78, 64, 58, 0,
-	0, 59, 0, 0, 67, 124, 0, 0, 0, 0,
-	83, 79, 10, 0, 62, 63, 77, 82, 12, 13,
-	0, 78, 0, 0, 232, 0, 0, 0, 0, 0,
-	124, 0, 0, 0, 0, 83, 79, 10, 0, 0,
-	0, 196, 82, 0, 0, 0, 0, 231, 0, 232,
-	0, 0, 0, 224, 0, 0, 0, 0, 0, 77,
-	0, 12, 13, 225, 0, 0, 196, 0, 0, 0,
-	0, 0, 231, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 77, 0, 12, 13, 427, 134,
-	149, 0, 152, 0, 135, 139, 140, 0, 0, 138,
-	150, 137, 136, 133, 151, 141, 142, 143, 144, 145,
-	146, 147, 148, 134, 149, 0, 152, 0, 135, 139,
-	140, 0, 660, 138, 150, 137, 136, 133, 151, 141,
-	142, 143, 144, 145, 146, 147, 148, 0, 78, 0,
-	0, 250, 78, 0, 0, 0, 659, 124, 0, 0,
-	0, 124, 83, 79, 10, 0, 83, 79, 10, 82,
-	0, 0, 0, 82, 299, 0, 232, 0, 0, 0,
-	232, 0, 0, 124, 0, 0, 0, 0, 83, 79,
-	10, 0, 0, 196, 0, 82, 0, 196, 0, 231,
-	0, 0, 232, 231, 0, 0, 0, 78, 0, 0,
-	0, 77, 0, 12, 13, 77, 124, 12, 13, 196,
-	0, 83, 79, 10, 0, 231, 0, 0, 82, 78,
-	0, 0, 0, 347, 0, 406, 0, 77, 124, 12,
-	13, 0, 349, 83, 79, 10, 0, 345, 343, 553,
-	82, 0, 196, 0, 344, 0, 0, 190, 412, 0,
-	0, 348, 0, 0, 0, 0, 0, 0, 0, 0,
-	77, 0, 12, 13, 196, 0, 0, 0, 346, 0,
-	195, 0, 0, 0, 0, 0, 0, 0, 347, 0,
-	0, 0, 77, 0, 12, 13, 342, 349, 12, 13,
-	0, 0, 345, 343, 341, 0, 0, 0, 347, 344,
-	0, 0, 0, 0, 0, 0, 453, 349, 0, 0,
-	0, 0, 345, 343, 341, 0, 0, 0, 0, 344,
-	0, 0, 0, 346, 0, 0, 348, 0, 0, 452,
-	0, 0, 0, 130, 0, 0, 0, 0, 0, 0,
-	0, 342, 0, 346, 13, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 350, 0, 0, 0, 0,
-	0, 342, 134, 149, 13, 152, 132, 135, 139, 140,
-	0, 131, 138, 150, 137, 136, 133, 151, 141, 142,
-	143, 144, 145, 146, 147, 148, 134, 149, 0, 152,
-	0, 135, 139, 140, 0, 0, 138, 150, 137, 136,
-	133, 151, 141, 142, 143, 144, 145, 146, 147, 148,
-	134, 149, 0, 0, 0, 135, 139, 140, 0, 0,
-	138, 150, 137, 136, 133, 151, 141, 142, 143, 144,
-	145, 146, 147, 148, 134, 149, 0, 0, 0, 135,
-	139, 140, 0, 0, 138, 150, 137, 136, 0, 151,
-	141, 142, 143, 144, 145, 146, 147, 148, 149, 0,
-	0, 0, 135, 139, 140, 0, 0, 138, 150, 137,
-	136, 0, 151, 141, 142, 143, 144, 145, 146, 147,
-	148,
-}
-var yyPact = [...]int{
-
-	-1000, -1000, 536, 535, -1000, 128, -1000, 545, 549, 336,
-	-1000, -1000, -1000, 605, -1000, -1000, 541, 1239, 328, 85,
-	-1000, 220, 438, 327, -1000, 323, -1000, -1000, -1000, -1000,
-	503, 493, 484, 459, -1000, -1000, -1000, -1000, -1000, 177,
-	-1000, 128, 128, 1316, 1316, 128, 1698, -1000, 2168, 92,
-	-1000, -1000, -1000, -1000, -1000, -1000, -1000, 39, 1698, 1698,
-	1698, 1698, 1698, 1698, 1698, 1698, 157, 1741, -1000, -1000,
-	-1000, 479, 233, -1000, -1000, -1000, 202, 1655, 2050, 36,
-	-1000, -1000, 233, 233, -1000, -1000, 153, 535, -1000, 586,
-	585, 40, 194, -1000, 540, -11, -11, -11, 17, -1000,
-	-1000, -1000, 367, 1827, -1000, -1000, -1000, 355, 754, -1000,
-	252, 1973, -1000, 155, 1969, 478, -1000, -1000, -1000, -1000,
-	-1000, -1000, 39, -1000, 475, -1000, -1000, -1000, -23, 2192,
-	1698, -1000, -1000, 1698, 1698, 1698, 1698, 1698, 1698, 1698,
-	1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698, 1698,
-	1698, 1698, 1698, 1698, 1698, 1698, 1612, 1698, 524, 1698,
-	1557, 387, 1698, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
-	-1000, -1000, 431, 2192, -1000, -1000, -1000, -1000, 1741, 1784,
-	1698, -1000, -1000, -1000, 1156, -1000, 24, 22, 2192, -1000,
-	1973, -1000, -1000, -1000, -1000, 1973, 1973, 211, 1973, 27,
-	263, 320, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
-	-1000, 583, 1010, -1000, 2129, 1010, -1000, 155, 470, 128,
-	309, -1000, -1000, 187, 1698, 128, -1000, -1000, -1000, -1000,
-	-1000, 1973, 574, 307, -1000, 181, 1698, 305, -1000, -1000,
-	-1000, -1000, 1156, 430, -13, -1000, -1000, 1969, -1000, -1000,
-	1973, 1969, 1156, 1969, 2192, 2240, 2263, 689, 689, 689,
-	689, 689, 689, 741, 741, 741, 741, -1000, -1000, -1000,
-	-1000, -1000, -1000, -1000, 2216, -23, -23, 2192, -1000, 519,
-	304, -1000, -1000, 51, 1698, -1000, 278, -1000, -1000, -1000,
-	66, -1000, -1000, 1514, 1022, 174, 1294, 152, -1000, 2028,
-	918, 1294, 143, -1000, -1000, -1000, -1000, -1000, -1000, 1973,
-	1973, -1000, 428, -1000, 128, 13, 273, -1000, -1000, 1852,
-	580, 525, 463, -1000, -1000, 210, 272, -1000, -1000, 467,
-	-1000, 539, 425, 197, -1000, 270, 268, -1000, -1000, -1000,
-	-1000, -1000, 103, 28, 151, 86, 1010, 2109, 571, 460,
-	65, 184, 266, 265, 128, -6, -1000, 206, 424, 128,
-	1698, -23, -1000, 422, 1973, 420, 128, 1698, -23, 418,
-	128, 131, 1518, 1969, -1000, -1000, -1000, -1000, 416, -1000,
-	415, -1000, -1000, 1698, 1459, 1404, 2192, 521, 1698, 229,
-	519, 405, -14, 1741, 404, 403, -1000, 1698, 147, -17,
-	-1000, -1000, 173, 2192, -1000, -1000, 1995, -1000, -1000, -1000,
-	-1000, -1000, 1973, 402, -1000, 138, -1000, 1156, 1156, -1000,
-	-1000, -1000, -1000, 1973, 112, 31, 580, 128, -1000, -1000,
-	398, 539, 210, 580, 539, 128, 104, 231, -1000, 1969,
-	397, -1000, -1000, -1000, -1000, 1010, 10, 1010, 128, 2054,
-	-1000, -1000, 514, 1010, -1000, -1000, 1010, 128, 259, -1000,
-	69, -1000, 581, -1000, 65, -1000, -1000, 392, -22, 128,
-	128, 580, 1010, -1000, -1000, -23, -1000, -1000, 258, -1000,
-	-1000, 754, -23, -1000, -1000, -1000, 440, -1000, -1000, 1969,
-	-1000, -1000, -1000, -1000, -1000, -1000, 1518, 1518, 1156, 255,
-	1698, 1698, -1000, -1000, -1000, -1000, -1000, 1741, 166, -1000,
-	-1000, 391, -1000, -1000, -1000, -1, -1000, 1294, -1000, 1349,
-	1294, 1294, 390, -1000, -1000, -1000, 129, -1000, -1000, -1000,
-	-1000, -1000, 580, 385, -1000, 383, -1000, -1000, -1000, 382,
-	-1000, -1000, 1010, 2, 102, 254, -1000, 1010, 81, 244,
-	-1000, 439, -1000, -1000, -1000, 370, -1000, -1000, 365, -1000,
-	497, -1000, 239, 858, 435, -1000, -1000, 580, 362, 128,
-	181, 1969, 361, -1000, 111, 1698, 2192, 2192, 226, 1156,
-	55, -1000, -1000, -1000, -1000, 1698, -1000, -1000, -1000, 2192,
-	-1000, 68, 64, -1000, -1000, -1000, 580, 580, 1518, -1000,
-	1010, -1000, 128, 580, -1000, 2054, 128, -1000, 858, 69,
-	-1000, -1000, -1000, 128, -1000, 128, -1000, -1000, -1000, 359,
-	-1000, -1000, -1000, -1000, 236, -1000, 1698, 1698, 1741, 560,
-	1, 1294, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000,
-	-1000, 349, -1000, 342, 341, 339, 1518, 1919, 1895, -1000,
-	-1000, 141, -1000, 50, 858, -1000, -1000, 858, -1000, -1000,
-	-1000, -1000, -1000, -1000, -1000, -1000, 1698, 519, -1000,
-}
-var yyPgo = [...]int{
-
-	0, 51, 793, 672, 34, 221, 32, 700, 31, 792,
-	788, 1, 76, 113, 208, 16, 25, 3, 785, 782,
-	781, 774, 773, 771, 7, 770, 617, 30, 24, 769,
-	437, 45, 47, 273, 41, 19, 768, 554, 20, 620,
-	767, 556, 765, 762, 12, 761, 124, 760, 40, 13,
-	758, 46, 4, 2, 28, 756, 766, 755, 10, 18,
-	752, 751, 26, 750, 749, 736, 15, 35, 735, 733,
-	38, 732, 29, 727, 612, 48, 21, 721, 720, 719,
-	717, 42, 712, 708, 707, 9, 84, 702, 14, 698,
-	0, 67, 49, 22, 6, 23, 17, 8, 697, 5,
-	37, 11, 696, 695, 694, 687, 406, 36, 686, 33,
-	27, 684, 682, 681, 680, 677, 671, 50, 44, 667,
-	43, 666, 58, 662, 659, 658, 657, 654, 652, 650,
-	649, 646, 645, 644, 641, 640, 639, 638, 39, 637,
-	626, 624,
-}
-var yyR1 = [...]int{
-
-	0, 112, 114, 114, 116, 113, 115, 115, 119, 119,
-	119, 120, 120, 121, 121, 2, 2, 2, 117, 123,
-	123, 124, 118, 50, 50, 50, 50, 50, 74, 74,
-	74, 74, 74, 74, 74, 74, 74, 74, 126, 70,
-	70, 70, 75, 75, 76, 76, 76, 36, 48, 44,
-	44, 44, 44, 44, 44, 9, 9, 9, 9, 127,
-	11, 128, 10, 62, 62, 129, 53, 42, 42, 42,
-	22, 22, 22, 21, 130, 23, 24, 24, 131, 132,
-	133, 25, 134, 63, 64, 64, 65, 65, 135, 136,
-	45, 137, 43, 14, 14, 14, 14, 14, 14, 14,
-	14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-	14, 14, 14, 14, 46, 46, 46, 46, 46, 46,
-	46, 46, 46, 41, 41, 41, 40, 40, 40, 40,
-	40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
-	49, 28, 16, 16, 15, 15, 39, 39, 17, 17,
-	31, 1, 1, 33, 34, 37, 37, 3, 3, 3,
-	91, 91, 30, 29, 81, 81, 7, 7, 7, 7,
-	7, 7, 32, 32, 32, 32, 87, 87, 87, 87,
-	87, 79, 79, 80, 89, 89, 89, 89, 89, 12,
-	12, 88, 88, 88, 88, 88, 88, 88, 85, 86,
-	84, 84, 83, 83, 47, 18, 18, 19, 19, 90,
-	51, 51, 52, 52, 52, 139, 20, 20, 60, 60,
-	71, 71, 77, 77, 78, 78, 73, 73, 69, 69,
-	72, 72, 72, 72, 72, 72, 4, 4, 13, 27,
-	27, 27, 82, 8, 8, 8, 8, 68, 68, 67,
-	67, 6, 6, 6, 6, 6, 26, 26, 26, 26,
-	26, 140, 26, 26, 26, 26, 26, 26, 26, 26,
-	66, 66, 55, 55, 54, 54, 56, 56, 59, 59,
-	57, 57, 57, 57, 58, 58, 122, 122, 138, 138,
-	35, 35, 61, 61, 38, 38, 101, 101, 105, 105,
-	103, 103, 5, 5, 141, 141, 141, 141, 141, 141,
-	92, 108, 106, 106, 106, 111, 111, 107, 107, 107,
-	107, 107, 107, 107, 107, 107, 107, 107, 110, 109,
-	95, 95, 97, 96, 96, 99, 99, 98, 98, 94,
-	94, 94, 93, 93, 125, 125, 100, 100, 104, 104,
-	102, 102,
-}
-var yyR2 = [...]int{
-
-	0, 4, 0, 3, 0, 3, 0, 3, 2, 5,
-	3, 3, 2, 1, 3, 1, 2, 2, 4, 0,
-	1, 0, 4, 0, 1, 1, 1, 1, 2, 5,
-	3, 2, 5, 7, 3, 2, 5, 3, 1, 2,
-	4, 3, 4, 3, 1, 2, 1, 1, 2, 1,
-	3, 3, 3, 2, 2, 3, 5, 5, 2, 0,
-	4, 0, 3, 0, 2, 0, 4, 4, 4, 2,
-	5, 1, 1, 2, 0, 3, 1, 3, 0, 0,
-	0, 8, 0, 5, 0, 2, 0, 2, 0, 0,
-	7, 0, 5, 1, 3, 3, 3, 3, 3, 3,
-	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-	3, 3, 3, 3, 1, 2, 2, 2, 2, 2,
-	2, 2, 2, 3, 5, 6, 1, 1, 3, 5,
-	5, 4, 6, 8, 1, 5, 5, 5, 7, 1,
-	0, 3, 1, 4, 1, 4, 1, 3, 1, 1,
-	1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
-	4, 4, 1, 1, 1, 2, 1, 1, 1, 1,
-	1, 3, 1, 1, 1, 2, 1, 1, 1, 1,
-	3, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-	3, 4, 4, 2, 3, 5, 1, 1, 2, 3,
-	5, 3, 5, 3, 3, 5, 8, 5, 8, 5,
-	0, 3, 0, 1, 3, 1, 4, 2, 0, 3,
-	1, 3, 1, 3, 1, 3, 1, 3, 1, 3,
-	3, 2, 4, 3, 5, 5, 1, 3, 1, 2,
-	1, 3, 4, 1, 2, 2, 1, 1, 3, 0,
-	2, 0, 1, 1, 1, 1, 1, 1, 1, 1,
-	1, 0, 4, 1, 2, 2, 2, 2, 2, 2,
-	1, 3, 1, 3, 1, 3, 1, 3, 1, 3,
-	1, 1, 3, 3, 0, 2, 0, 1, 0, 1,
-	0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
-	0, 1, 0, 1, 4, 4, 5, 6, 4, 4,
-	1, 1, 1, 1, 1, 1, 1, 1, 1, 3,
-	4, 5, 4, 4, 2, 2, 4, 3, 3, 5,
-	3, 4, 3, 5, 1, 0, 1, 3, 1, 1,
-	2, 1, 1, 5, 0, 2, 1, 3, 1, 3,
-	1, 3,
-}
-var yyChk = [...]int{
-
-	-1000, -112, -113, -116, -114, 26, -117, 26, -115, -3,
-	25, -91, 74, 75, -118, -124, 25, -60, -119, 22,
-	63, 4, -125, -123, 25, -50, -74, -47, -26, 2,
-	33, -126, 32, 18, -44, -23, -45, -43, -25, -29,
-	16, 7, 11, 19, 14, 20, 28, 10, -14, -56,
-	17, 31, 29, 21, -33, -46, -3, -39, 54, 57,
-	50, 51, 70, 71, 53, 37, -40, 60, 4, -30,
-	-41, -79, -80, -20, -90, -88, -139, 72, 9, 24,
-	-84, -83, 30, 23, 63, -120, 60, -2, 4, -3,
-	64, 64, 65, -141, 22, 33, 10, 32, 18, 63,
-	63, -70, 60, -54, -34, -3, -75, 60, -54, -48,
-	60, -36, -3, -18, 60, -3, 67, -37, -33, -3,
-	-37, -41, -39, -3, 18, -41, -33, -61, -56, -14,
-	5, 43, 38, 48, 34, 39, 47, 46, 44, 40,
-	41, 50, 51, 52, 53, 54, 55, 56, 57, 35,
-	45, 49, 37, 66, 6, 76, -130, -135, -137, -131,
-	60, 64, 72, -46, -46, -46, -46, -46, -46, -46,
-	-46, 68, -17, -14, -32, -86, -90, -88, 54, 37,
-	60, -1, 36, 68, -1, 2, -35, 12, -14, -87,
-	37, -90, -88, -85, -12, 60, 54, -30, 72, -1,
-	-1, -121, 61, -120, -117, -118, 4, 4, 25, 74,
-	65, 25, -92, -91, -92, -108, -92, -19, -92, 60,
-	-71, 61, -70, -7, 66, 76, -86, -90, -88, -85,
-	-12, 60, 37, -75, 61, -7, 66, -78, 61, -48,
-	-7, -51, 68, -67, -68, -8, -31, -3, -81, -7,
-	12, 60, -140, 60, -14, -14, -14, -14, -14, -14,
-	-14, -14, -14, -14, -14, -14, -14, -14, -14, -14,
-	-14, -14, -14, -14, -14, -56, -56, -14, -21, -22,
-	-38, -42, -44, -56, 27, -24, -38, 36, -24, 61,
-	-59, -17, -3, 60, -14, -35, -49, 61, -32, 9,
-	-14, -49, -66, -6, -11, -74, -26, 2, 68, 73,
-	73, -7, -7, -7, 64, -7, -73, 69, -72, -55,
-	-13, 60, 54, -33, -4, 25, -69, 69, -27, -33,
-	-4, 60, -122, 63, -118, 4, -106, -107, -110, -109,
-	-91, 25, 72, 24, 30, 23, 54, 9, 37, 18,
-	66, -106, -106, -51, 60, -100, -95, -3, -122, 63,
-	66, -56, -34, -7, 9, -122, 63, 66, -56, -122,
-	63, -66, 61, 76, -138, -31, -81, -7, -67, -6,
-	-67, -53, 36, 63, 66, 6, -14, -136, 63, -62,
-	-132, -138, 12, 76, -17, 32, 73, 67, -58, -57,
-	-28, -16, -15, -14, 68, 68, 37, -7, -90, -88,
-	-85, -12, 60, -138, 76, -58, 69, 63, -127, -7,
-	-7, 61, -3, 73, -122, 63, -7, 76, -5, 4,
-	-13, 54, 25, -13, 60, 64, -122, 63, -82, 60,
-	-4, 61, -120, 63, 63, 73, 4, 72, 68, 68,
-	-106, -111, 60, 37, -107, -109, 9, 60, -93, -94,
-	60, 4, 51, -3, 66, 63, 63, -101, -100, 61,
-	76, -106, 12, 61, -70, -56, 61, 61, -77, -76,
-	-75, -54, -56, 61, -48, 69, -3, -52, -89, 60,
-	-86, -90, -88, -85, -12, -8, 61, 61, -129, -38,
-	27, 27, 36, -38, -10, 69, -9, 8, 13, -53,
-	61, -138, -17, 61, 61, -35, 69, 76, -138, 67,
-	-49, -49, -7, 61, 69, -6, -66, -7, 69, -72,
-	-5, -33, 61, -13, -5, -13, -3, 69, -27, -67,
-	61, -106, 73, -106, -105, -104, -97, -3, -103, -102,
-	-96, -3, -106, 25, -91, -110, -106, -106, -101, 63,
-	-94, 4, -93, 61, -3, -95, -5, -106, -122, 63,
-	-7, 60, -67, -52, -66, 63, -14, -14, -62, -128,
-	-59, 67, -133, 61, 73, 67, -28, -16, -15, -14,
-	68, -58, -58, 61, 69, -5, 61, 61, 61, -106,
-	73, 69, 63, -106, 69, 63, 60, 61, 61, 50,
-	63, -99, -98, 60, -106, 60, -5, 61, -76, -67,
-	61, 69, -38, 69, -66, 67, 66, 6, 76, -64,
-	-35, -49, 69, 69, -5, -5, -52, -106, -97, -5,
-	-96, -101, -99, -94, -101, -101, 61, -14, -14, -65,
-	-63, 15, 73, -58, 61, 61, 61, 61, -52, 67,
-	67, 21, -11, 69, -99, -99, -134, -24, -53,
-}
-var yyDef = [...]int{
-
-	4, -2, 2, 0, 6, 0, 21, 0, 218, 0,
-	157, 158, 159, 0, 5, 344, 19, -2, 0, 0,
-	3, 0, 0, 0, 20, 0, 24, 25, 26, 27,
-	0, 0, 0, 0, 256, 257, 258, 259, 260, 0,
-	263, 155, 155, 0, 0, 0, 292, 38, -2, 0,
-	74, 88, 91, 78, 163, 93, -2, 114, 0, 0,
-	0, 0, 0, 0, 0, 0, 146, 0, 126, 127,
-	134, 0, 0, 139, -2, -2, 0, 290, 0, 0,
-	196, 197, 0, 0, 7, 8, 0, 21, 15, 0,
-	0, 0, 0, 345, 0, 0, 0, 0, 0, 18,
-	219, 28, 0, 0, 274, 154, 31, 0, 0, 35,
-	0, 0, 47, 210, 249, 0, 261, 264, 156, 153,
-	265, -2, 0, 162, 0, -2, 268, 269, 293, 276,
-	0, 53, 54, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 294, 294, 0, 294,
-	0, 0, 290, 115, 116, 117, 118, 119, 120, 121,
-	122, 140, 0, 148, 149, 172, -2, -2, 0, 0,
-	0, 140, 151, 152, -2, 217, 0, 0, 291, 193,
-	0, 176, 177, 178, 179, 0, 0, 189, 0, 0,
-	0, 286, 10, 13, 21, 12, 16, 17, 160, 161,
-	22, 0, 0, 310, 0, 0, 311, 210, 0, 0,
-	286, 30, 220, 39, 0, 0, 166, 167, 168, 169,
-	170, 0, 0, 286, 34, 0, 0, 286, 37, 224,
-	48, 204, -2, 0, 288, 247, 243, 162, 246, 150,
-	164, 249, -2, 249, 50, 94, 95, 96, 97, 98,
-	99, 100, 101, 102, 103, 104, 105, 106, 107, 108,
-	109, 110, 111, 112, 113, 51, 52, 277, 75, 0,
-	71, 72, 295, 0, 0, 89, 76, 63, 79, 123,
-	288, 278, 128, 0, 291, 0, 284, 147, 175, 0,
-	288, 284, 0, 270, 252, 253, 254, 255, 59, 0,
-	0, 194, 0, 198, 0, 0, 286, 201, 226, 0,
-	302, 0, 0, 272, 238, -2, 286, 203, 228, 0,
-	240, 0, 0, 287, 11, 0, 0, 312, 313, 314,
-	317, 318, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 296, 0, 346, 0, 0, 287,
-	0, 41, 275, 0, 0, 0, 287, 0, 43, 0,
-	287, 0, 212, 289, 250, 244, 245, 165, 0, 262,
-	0, 73, 65, 294, 0, 0, 69, 0, 294, 0,
-	0, 0, 288, 289, 0, 0, 131, 290, 0, 288,
-	280, 281, 0, -2, 140, 140, 0, 199, -2, -2,
-	-2, -2, 0, 0, 289, 0, 216, -2, -2, 191,
-	192, 180, 190, 0, 0, 287, 302, 0, 231, 303,
-	0, 0, 236, 302, 0, 0, 0, 287, 239, 249,
-	0, 9, 14, 304, 305, 0, 0, 0, 298, 300,
-	324, 325, 0, 0, 315, 316, 0, 296, 0, 342,
-	0, 339, 0, 341, 0, 308, 309, 0, 297, 0,
-	0, 302, 0, 29, 221, 40, 171, 32, 286, 222,
-	44, 46, 42, 36, 225, 211, 162, 209, 213, 249,
-	184, 185, 186, 187, 188, 248, 212, 212, -2, 0,
-	0, 0, 63, 77, 64, 92, 61, 0, 0, 80,
-	124, 0, 279, 129, 130, 0, 137, 289, 285, 0,
-	284, 284, 0, 135, 136, 271, 0, 195, 200, 227,
-	230, 273, 302, 0, 233, 0, 237, 202, 229, 0,
-	241, 319, 0, 0, 0, 299, 348, 0, 0, 301,
-	350, 0, 334, -2, -2, 0, 327, 328, 0, 306,
-	0, 340, 0, 335, 0, 347, 330, 302, 0, 287,
-	45, 249, 0, 205, 0, 294, 67, 68, 0, -2,
-	0, 58, 84, 125, 132, 290, 282, 283, 141, 144,
-	140, 0, 0, -2, 60, 232, 302, 302, 212, 320,
-	0, 322, 0, 302, 323, 0, 296, 326, 335, 0,
-	307, 207, 336, 296, 338, 296, 331, 33, 223, 0,
-	214, 66, 70, 90, 62, 55, 0, 0, 0, 86,
-	0, 284, -2, 138, 234, 235, 242, 321, 349, 332,
-	351, 0, 329, 0, 0, 0, 212, 0, 0, 81,
-	85, 0, 133, 0, 335, 343, 337, 335, 206, 56,
-	57, 82, 87, 145, 333, 208, 294, 0, 83,
-}
-var yyTok1 = [...]int{
-
-	1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-	3, 3, 3, 70, 3, 3, 65, 56, 57, 3,
-	60, 61, 54, 50, 76, 51, 64, 55, 3, 3,
-	3, 3, 3, 3, 3, 3, 3, 3, 67, 63,
-	3, 66, 3, 74, 75, 3, 3, 3, 3, 3,
-	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-	3, 72, 3, 73, 53, 3, 3, 3, 3, 3,
-	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-	3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-	3, 3, 3, 68, 52, 69, 71,
-}
-var yyTok2 = [...]int{
-
-	2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
-	12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
-	22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
-	32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
-	42, 43, 44, 45, 46, 47, 48, 49, 58, 59,
-	62,
-}
-var yyTok3 = [...]int{
-	0,
-}
-
-var yyErrorMessages = [...]struct {
-	state int
-	token int
-	msg   string
-}{
-	{332, 76, "unexpected comma during import block"},
-	{89, 63, "missing import path; require quoted string"},
-	{390, 63, "missing { after if clause"},
-	{387, 63, "missing { after switch clause"},
-	{279, 63, "missing { after for clause"},
-	{499, 36, "missing { after for clause"},
-	{17, 68, "unexpected semicolon or newline before {"},
-	{111, 63, "unexpected semicolon or newline in type declaration"},
-	{78, 69, "unexpected } in channel type"},
-	{78, 61, "unexpected ) in channel type"},
-	{78, 76, "unexpected comma in channel type"},
-	{417, 15, "unexpected semicolon or newline before else"},
-	{329, 76, "name list not allowed in interface type"},
-	{279, 33, "var declaration not allowed in for initializer"},
-	{25, 68, "unexpected { at end of statement"},
-	{371, 68, "unexpected { at end of statement"},
-	{122, 63, "argument to go/defer must be function call"},
-	{398, 63, "need trailing comma before newline in composite literal"},
-	{415, 63, "need trailing comma before newline in composite literal"},
-	{124, 25, "nested func not allowed"},
-	{651, 63, "else must be followed by if or statement block"},
-}
-
-//line yaccpar:1
-
-/*	parser for yacc output	*/
-
-var (
-	yyDebug        = 0
-	yyErrorVerbose = false
-)
-
-type yyLexer interface {
-	Lex(lval *yySymType) int
-	Error(s string)
-}
-
-type yyParser interface {
-	Parse(yyLexer) int
-	Lookahead() int
-}
-
-type yyParserImpl struct {
-	lookahead func() int
-}
-
-func (p *yyParserImpl) Lookahead() int {
-	return p.lookahead()
-}
-
-func yyNewParser() yyParser {
-	p := &yyParserImpl{
-		lookahead: func() int { return -1 },
-	}
-	return p
-}
-
-const yyFlag = -1000
-
-func yyTokname(c int) string {
-	if c >= 1 && c-1 < len(yyToknames) {
-		if yyToknames[c-1] != "" {
-			return yyToknames[c-1]
-		}
-	}
-	return __yyfmt__.Sprintf("tok-%v", c)
-}
-
-func yyStatname(s int) string {
-	if s >= 0 && s < len(yyStatenames) {
-		if yyStatenames[s] != "" {
-			return yyStatenames[s]
-		}
-	}
-	return __yyfmt__.Sprintf("state-%v", s)
-}
-
-func yyErrorMessage(state, lookAhead int) string {
-	const TOKSTART = 4
-
-	if !yyErrorVerbose {
-		return "syntax error"
-	}
-
-	for _, e := range yyErrorMessages {
-		if e.state == state && e.token == lookAhead {
-			return "syntax error: " + e.msg
-		}
-	}
-
-	res := "syntax error: unexpected " + yyTokname(lookAhead)
-
-	// To match Bison, suggest at most four expected tokens.
-	expected := make([]int, 0, 4)
-
-	// Look for shiftable tokens.
-	base := yyPact[state]
-	for tok := TOKSTART; tok-1 < len(yyToknames); tok++ {
-		if n := base + tok; n >= 0 && n < yyLast && yyChk[yyAct[n]] == tok {
-			if len(expected) == cap(expected) {
-				return res
-			}
-			expected = append(expected, tok)
-		}
-	}
-
-	if yyDef[state] == -2 {
-		i := 0
-		for yyExca[i] != -1 || yyExca[i+1] != state {
-			i += 2
-		}
-
-		// Look for tokens that we accept or reduce.
-		for i += 2; yyExca[i] >= 0; i += 2 {
-			tok := yyExca[i]
-			if tok < TOKSTART || yyExca[i+1] == 0 {
-				continue
-			}
-			if len(expected) == cap(expected) {
-				return res
-			}
-			expected = append(expected, tok)
-		}
-
-		// If the default action is to accept or reduce, give up.
-		if yyExca[i+1] != 0 {
-			return res
-		}
-	}
-
-	for i, tok := range expected {
-		if i == 0 {
-			res += ", expecting "
-		} else {
-			res += " or "
-		}
-		res += yyTokname(tok)
-	}
-	return res
-}
-
-func yylex1(lex yyLexer, lval *yySymType) (char, token int) {
-	token = 0
-	char = lex.Lex(lval)
-	if char <= 0 {
-		token = yyTok1[0]
-		goto out
-	}
-	if char < len(yyTok1) {
-		token = yyTok1[char]
-		goto out
-	}
-	if char >= yyPrivate {
-		if char < yyPrivate+len(yyTok2) {
-			token = yyTok2[char-yyPrivate]
-			goto out
-		}
-	}
-	for i := 0; i < len(yyTok3); i += 2 {
-		token = yyTok3[i+0]
-		if token == char {
-			token = yyTok3[i+1]
-			goto out
-		}
-	}
-
-out:
-	if token == 0 {
-		token = yyTok2[1] /* unknown char */
-	}
-	if yyDebug >= 3 {
-		__yyfmt__.Printf("lex %s(%d)\n", yyTokname(token), uint(char))
-	}
-	return char, token
-}
-
-func yyParse(yylex yyLexer) int {
-	return yyNewParser().Parse(yylex)
-}
-
-func (yyrcvr *yyParserImpl) Parse(yylex yyLexer) int {
-	var yyn int
-	var yylval yySymType
-	var yyVAL yySymType
-	var yyDollar []yySymType
-	yyS := make([]yySymType, yyMaxDepth)
-
-	Nerrs := 0   /* number of errors */
-	Errflag := 0 /* error recovery flag */
-	yystate := 0
-	yychar := -1
-	yytoken := -1 // yychar translated into internal numbering
-	yyrcvr.lookahead = func() int { return yychar }
-	defer func() {
-		// Make sure we report no lookahead when not parsing.
-		yystate = -1
-		yychar = -1
-		yytoken = -1
-	}()
-	yyp := -1
-	goto yystack
-
-ret0:
-	return 0
-
-ret1:
-	return 1
-
-yystack:
-	/* put a state and value onto the stack */
-	if yyDebug >= 4 {
-		__yyfmt__.Printf("char %v in %v\n", yyTokname(yytoken), yyStatname(yystate))
-	}
-
-	yyp++
-	if yyp >= len(yyS) {
-		nyys := make([]yySymType, len(yyS)*2)
-		copy(nyys, yyS)
-		yyS = nyys
-	}
-	yyS[yyp] = yyVAL
-	yyS[yyp].yys = yystate
-
-yynewstate:
-	yyn = yyPact[yystate]
-	if yyn <= yyFlag {
-		goto yydefault /* simple state */
-	}
-	if yychar < 0 {
-		yychar, yytoken = yylex1(yylex, &yylval)
-	}
-	yyn += yytoken
-	if yyn < 0 || yyn >= yyLast {
-		goto yydefault
-	}
-	yyn = yyAct[yyn]
-	if yyChk[yyn] == yytoken { /* valid shift */
-		yychar = -1
-		yytoken = -1
-		yyVAL = yylval
-		yystate = yyn
-		if Errflag > 0 {
-			Errflag--
-		}
-		goto yystack
-	}
-
-yydefault:
-	/* default state action */
-	yyn = yyDef[yystate]
-	if yyn == -2 {
-		if yychar < 0 {
-			yychar, yytoken = yylex1(yylex, &yylval)
-		}
-
-		/* look through exception table */
-		xi := 0
-		for {
-			if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate {
-				break
-			}
-			xi += 2
-		}
-		for xi += 2; ; xi += 2 {
-			yyn = yyExca[xi+0]
-			if yyn < 0 || yyn == yytoken {
-				break
-			}
-		}
-		yyn = yyExca[xi+1]
-		if yyn < 0 {
-			goto ret0
-		}
-	}
-	if yyn == 0 {
-		/* error ... attempt to resume parsing */
-		switch Errflag {
-		case 0: /* brand new error */
-			yylex.Error(yyErrorMessage(yystate, yytoken))
-			Nerrs++
-			if yyDebug >= 1 {
-				__yyfmt__.Printf("%s", yyStatname(yystate))
-				__yyfmt__.Printf(" saw %s\n", yyTokname(yytoken))
-			}
-			fallthrough
-
-		case 1, 2: /* incompletely recovered error ... try again */
-			Errflag = 3
-
-			/* find a state where "error" is a legal shift action */
-			for yyp >= 0 {
-				yyn = yyPact[yyS[yyp].yys] + yyErrCode
-				if yyn >= 0 && yyn < yyLast {
-					yystate = yyAct[yyn] /* simulate a shift of "error" */
-					if yyChk[yystate] == yyErrCode {
-						goto yystack
-					}
-				}
-
-				/* the current p has no shift on "error", pop stack */
-				if yyDebug >= 2 {
-					__yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys)
-				}
-				yyp--
-			}
-			/* there is no state on the stack with an error shift ... abort */
-			goto ret1
-
-		case 3: /* no shift yet; clobber input char */
-			if yyDebug >= 2 {
-				__yyfmt__.Printf("error recovery discards %s\n", yyTokname(yytoken))
-			}
-			if yytoken == yyEofCode {
-				goto ret1
-			}
-			yychar = -1
-			yytoken = -1
-			goto yynewstate /* try again in the same state */
-		}
-	}
-
-	/* reduction by production yyn */
-	if yyDebug >= 2 {
-		__yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate))
-	}
-
-	yynt := yyn
-	yypt := yyp
-	_ = yypt // guard against "declared and not used"
-
-	yyp -= yyR2[yyn]
-	// yyp is now the index of $0. Perform the default action. Iff the
-	// reduced production is ε, $1 is possibly out of range.
-	if yyp+1 >= len(yyS) {
-		nyys := make([]yySymType, len(yyS)*2)
-		copy(nyys, yyS)
-		yyS = nyys
-	}
-	yyVAL = yyS[yyp+1]
-
-	/* consult goto table to find next state */
-	yyn = yyR1[yyn]
-	yyg := yyPgo[yyn]
-	yyj := yyg + yyS[yyp].yys + 1
-
-	if yyj >= yyLast {
-		yystate = yyAct[yyg]
-	} else {
-		yystate = yyAct[yyj]
-		if yyChk[yystate] != -yyn {
-			yystate = yyAct[yyg]
-		}
-	}
-	// dummy call; replaced with literal code
-	switch yynt {
-
-	case 1:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:189
-		{
-			xtop = concat(xtop, yyDollar[4].list)
-		}
-	case 2:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:195
-		{
-			prevlineno = lineno
-			Yyerror("package statement must be first")
-			errorexit()
-		}
-	case 3:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:201
-		{
-			mkpackage(yyDollar[2].sym.Name)
-		}
-	case 4:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:211
-		{
-			importpkg = Runtimepkg
-
-			if Debug['A'] != 0 {
-				cannedimports("runtime.Builtin", "package runtime\n\n$$\n\n")
-			} else {
-				cannedimports("runtime.Builtin", runtimeimport)
-			}
-			curio.importsafe = true
-		}
-	case 5:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:223
-		{
-			importpkg = nil
-		}
-	case 11:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:237
-		{
-			ipkg := importpkg
-			my := importmyname
-			importpkg = nil
-			importmyname = nil
-
-			if my == nil {
-				my = Lookup(ipkg.Name)
-			}
-
-			pack := Nod(OPACK, nil, nil)
-			pack.Sym = my
-			pack.Name.Pkg = ipkg
-			pack.Lineno = int32(yyDollar[1].i)
-
-			if strings.HasPrefix(my.Name, ".") {
-				importdot(ipkg, pack)
-				break
-			}
-			if my.Name == "init" {
-				Yyerror("cannot import package as init - init must be a func")
-				break
-			}
-			if my.Name == "_" {
-				break
-			}
-			if my.Def != nil {
-				lineno = int32(yyDollar[1].i)
-				redeclare(my, "as imported package name")
-			}
-			my.Def = pack
-			my.Lastlineno = int32(yyDollar[1].i)
-			my.Block = 1 // at top level
-		}
-	case 12:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:272
-		{
-			// When an invalid import path is passed to importfile,
-			// it calls Yyerror and then sets up a fake import with
-			// no package statement. This allows us to test more
-			// than one invalid import statement in a single file.
-			if nerrors == 0 {
-				Fatal("phase error in import")
-			}
-		}
-	case 15:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:288
-		{
-			// import with original name
-			yyVAL.i = parserline()
-			importmyname = nil
-			importfile(&yyDollar[1].val, yyVAL.i)
-		}
-	case 16:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:295
-		{
-			// import with given name
-			yyVAL.i = parserline()
-			importmyname = yyDollar[1].sym
-			importfile(&yyDollar[2].val, yyVAL.i)
-		}
-	case 17:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:302
-		{
-			// import into my name space
-			yyVAL.i = parserline()
-			importmyname = Lookup(".")
-			importfile(&yyDollar[2].val, yyVAL.i)
-		}
-	case 18:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:311
-		{
-			if importpkg.Name == "" {
-				importpkg.Name = yyDollar[2].sym.Name
-				numImport[yyDollar[2].sym.Name]++
-			} else if importpkg.Name != yyDollar[2].sym.Name {
-				Yyerror("conflicting names %s and %s for package %q", importpkg.Name, yyDollar[2].sym.Name, importpkg.Path)
-			}
-			importpkg.Direct = 1
-			importpkg.Safe = curio.importsafe
-
-			if safemode != 0 && !curio.importsafe {
-				Yyerror("cannot import unsafe package %q", importpkg.Path)
-			}
-		}
-	case 20:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:328
-		{
-			if yyDollar[1].sym.Name == "safe" {
-				curio.importsafe = true
-			}
-		}
-	case 21:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:335
-		{
-			defercheckwidth()
-		}
-	case 22:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:339
-		{
-			resumecheckwidth()
-			unimportfile()
-		}
-	case 23:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:348
-		{
-			Yyerror("empty top-level declaration")
-			yyVAL.list = nil
-		}
-	case 25:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:354
-		{
-			yyVAL.list = list1(yyDollar[1].node)
-		}
-	case 26:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:358
-		{
-			Yyerror("non-declaration statement outside function body")
-			yyVAL.list = nil
-		}
-	case 27:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:363
-		{
-			yyVAL.list = nil
-		}
-	case 28:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:369
-		{
-			yyVAL.list = yyDollar[2].list
-		}
-	case 29:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:373
-		{
-			yyVAL.list = yyDollar[3].list
-		}
-	case 30:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:377
-		{
-			yyVAL.list = nil
-		}
-	case 31:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:381
-		{
-			yyVAL.list = yyDollar[2].list
-			iota_ = -100000
-			lastconst = nil
-		}
-	case 32:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:387
-		{
-			yyVAL.list = yyDollar[3].list
-			iota_ = -100000
-			lastconst = nil
-		}
-	case 33:
-		yyDollar = yyS[yypt-7 : yypt+1]
-		//line go.y:393
-		{
-			yyVAL.list = concat(yyDollar[3].list, yyDollar[5].list)
-			iota_ = -100000
-			lastconst = nil
-		}
-	case 34:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:399
-		{
-			yyVAL.list = nil
-			iota_ = -100000
-		}
-	case 35:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:404
-		{
-			yyVAL.list = list1(yyDollar[2].node)
-		}
-	case 36:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:408
-		{
-			yyVAL.list = yyDollar[3].list
-		}
-	case 37:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:412
-		{
-			yyVAL.list = nil
-		}
-	case 38:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:418
-		{
-			iota_ = 0
-		}
-	case 39:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:424
-		{
-			yyVAL.list = variter(yyDollar[1].list, yyDollar[2].node, nil)
-		}
-	case 40:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:428
-		{
-			yyVAL.list = variter(yyDollar[1].list, yyDollar[2].node, yyDollar[4].list)
-		}
-	case 41:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:432
-		{
-			yyVAL.list = variter(yyDollar[1].list, nil, yyDollar[3].list)
-		}
-	case 42:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:438
-		{
-			yyVAL.list = constiter(yyDollar[1].list, yyDollar[2].node, yyDollar[4].list)
-		}
-	case 43:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:442
-		{
-			yyVAL.list = constiter(yyDollar[1].list, nil, yyDollar[3].list)
-		}
-	case 45:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:449
-		{
-			yyVAL.list = constiter(yyDollar[1].list, yyDollar[2].node, nil)
-		}
-	case 46:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:453
-		{
-			yyVAL.list = constiter(yyDollar[1].list, nil, nil)
-		}
-	case 47:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:459
-		{
-			// different from dclname because the name
-			// becomes visible right here, not at the end
-			// of the declaration.
-			yyVAL.node = typedcl0(yyDollar[1].sym)
-		}
-	case 48:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:468
-		{
-			yyVAL.node = typedcl1(yyDollar[1].node, yyDollar[2].node, true)
-		}
-	case 49:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:474
-		{
-			yyVAL.node = yyDollar[1].node
-
-			// These nodes do not carry line numbers.
-			// Since a bare name used as an expression is an error,
-			// introduce a wrapper node to give the correct line.
-			switch yyVAL.node.Op {
-			case ONAME, ONONAME, OTYPE, OPACK, OLITERAL:
-				yyVAL.node = Nod(OPAREN, yyVAL.node, nil)
-				yyVAL.node.Implicit = true
-				break
-			}
-		}
-	case 50:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:488
-		{
-			yyVAL.node = Nod(OASOP, yyDollar[1].node, yyDollar[3].node)
-			yyVAL.node.Etype = uint8(yyDollar[2].i) // rathole to pass opcode
-		}
-	case 51:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:493
-		{
-			if yyDollar[1].list.Next == nil && yyDollar[3].list.Next == nil {
-				// simple
-				yyVAL.node = Nod(OAS, yyDollar[1].list.N, yyDollar[3].list.N)
-				break
-			}
-			// multiple
-			yyVAL.node = Nod(OAS2, nil, nil)
-			yyVAL.node.List = yyDollar[1].list
-			yyVAL.node.Rlist = yyDollar[3].list
-		}
-	case 52:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:505
-		{
-			if yyDollar[3].list.N.Op == OTYPESW {
-				yyVAL.node = Nod(OTYPESW, nil, yyDollar[3].list.N.Right)
-				if yyDollar[3].list.Next != nil {
-					Yyerror("expr.(type) must be alone in list")
-				}
-				if yyDollar[1].list.Next != nil {
-					Yyerror("argument count mismatch: %d = %d", count(yyDollar[1].list), 1)
-				} else if (yyDollar[1].list.N.Op != ONAME && yyDollar[1].list.N.Op != OTYPE && yyDollar[1].list.N.Op != ONONAME) || isblank(yyDollar[1].list.N) {
-					Yyerror("invalid variable name %s in type switch", yyDollar[1].list.N)
-				} else {
-					yyVAL.node.Left = dclname(yyDollar[1].list.N.Sym)
-				} // it's a colas, so must not re-use an oldname.
-				break
-			}
-			yyVAL.node = colas(yyDollar[1].list, yyDollar[3].list, int32(yyDollar[2].i))
-		}
-	case 53:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:523
-		{
-			yyVAL.node = Nod(OASOP, yyDollar[1].node, Nodintconst(1))
-			yyVAL.node.Implicit = true
-			yyVAL.node.Etype = OADD
-		}
-	case 54:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:529
-		{
-			yyVAL.node = Nod(OASOP, yyDollar[1].node, Nodintconst(1))
-			yyVAL.node.Implicit = true
-			yyVAL.node.Etype = OSUB
-		}
-	case 55:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:537
-		{
-			var n, nn *Node
-
-			// will be converted to OCASE
-			// right will point to next case
-			// done in casebody()
-			markdcl()
-			yyVAL.node = Nod(OXCASE, nil, nil)
-			yyVAL.node.List = yyDollar[2].list
-			if typesw != nil && typesw.Right != nil {
-				n = typesw.Right.Left
-				if n != nil {
-					// type switch - declare variable
-					nn = newname(n.Sym)
-					declare(nn, dclcontext)
-					yyVAL.node.Rlist = list1(nn)
-
-					// keep track of the instances for reporting unused
-					nn.Name.Defn = typesw.Right
-				}
-			}
-		}
-	case 56:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:560
-		{
-			var n *Node
-
-			// will be converted to OCASE
-			// right will point to next case
-			// done in casebody()
-			markdcl()
-			yyVAL.node = Nod(OXCASE, nil, nil)
-			if yyDollar[2].list.Next == nil {
-				n = Nod(OAS, yyDollar[2].list.N, yyDollar[4].node)
-			} else {
-				n = Nod(OAS2, nil, nil)
-				n.List = yyDollar[2].list
-				n.Rlist = list1(yyDollar[4].node)
-			}
-			yyVAL.node.List = list1(n)
-		}
-	case 57:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:578
-		{
-			// will be converted to OCASE
-			// right will point to next case
-			// done in casebody()
-			markdcl()
-			yyVAL.node = Nod(OXCASE, nil, nil)
-			yyVAL.node.List = list1(colas(yyDollar[2].list, list1(yyDollar[4].node), int32(yyDollar[3].i)))
-		}
-	case 58:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:587
-		{
-			var n, nn *Node
-
-			markdcl()
-			yyVAL.node = Nod(OXCASE, nil, nil)
-			if typesw != nil && typesw.Right != nil {
-				n = typesw.Right.Left
-				if n != nil {
-					// type switch - declare variable
-					nn = newname(n.Sym)
-					declare(nn, dclcontext)
-					yyVAL.node.Rlist = list1(nn)
-
-					// keep track of the instances for reporting unused
-					nn.Name.Defn = typesw.Right
-				}
-			}
-		}
-	case 59:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:608
-		{
-			markdcl()
-		}
-	case 60:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:612
-		{
-			if yyDollar[3].list == nil {
-				yyVAL.node = Nod(OEMPTY, nil, nil)
-			} else {
-				yyVAL.node = liststmt(yyDollar[3].list)
-			}
-			popdcl()
-		}
-	case 61:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:623
-		{
-			// If the last token read by the lexer was consumed
-			// as part of the case, clear it (parser has cleared yychar).
-			// If the last token read by the lexer was the lookahead
-			// leave it alone (parser has it cached in yychar).
-			// This is so that the stmt_list action doesn't look at
-			// the case tokens if the stmt_list is empty.
-			yylast = yychar
-			yyDollar[1].node.Xoffset = int64(block)
-		}
-	case 62:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:634
-		{
-			// This is the only place in the language where a statement
-			// list is not allowed to drop the final semicolon, because
-			// it's the only place where a statement list is not followed
-			// by a closing brace.  Handle the error for pedantry.
-
-			// Find the final token of the statement list.
-			// yylast is lookahead; yyprev is last of stmt_list
-			last := yyprev
-
-			if last > 0 && last != ';' && yychar != '}' {
-				Yyerror("missing statement after label")
-			}
-			yyVAL.node = yyDollar[1].node
-			yyVAL.node.Nbody = yyDollar[3].list
-			popdcl()
-		}
-	case 63:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:653
-		{
-			yyVAL.list = nil
-		}
-	case 64:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:657
-		{
-			yyVAL.list = list(yyDollar[1].list, yyDollar[2].node)
-		}
-	case 65:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:663
-		{
-			markdcl()
-		}
-	case 66:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:667
-		{
-			yyVAL.list = yyDollar[3].list
-			popdcl()
-		}
-	case 67:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:674
-		{
-			yyVAL.node = Nod(ORANGE, nil, yyDollar[4].node)
-			yyVAL.node.List = yyDollar[1].list
-			yyVAL.node.Etype = 0 // := flag
-		}
-	case 68:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:680
-		{
-			yyVAL.node = Nod(ORANGE, nil, yyDollar[4].node)
-			yyVAL.node.List = yyDollar[1].list
-			yyVAL.node.Colas = true
-			colasdefn(yyDollar[1].list, yyVAL.node)
-		}
-	case 69:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:687
-		{
-			yyVAL.node = Nod(ORANGE, nil, yyDollar[2].node)
-			yyVAL.node.Etype = 0 // := flag
-		}
-	case 70:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:694
-		{
-			// init ; test ; incr
-			if yyDollar[5].node != nil && yyDollar[5].node.Colas {
-				Yyerror("cannot declare in the for-increment")
-			}
-			yyVAL.node = Nod(OFOR, nil, nil)
-			if yyDollar[1].node != nil {
-				yyVAL.node.Ninit = list1(yyDollar[1].node)
-			}
-			yyVAL.node.Left = yyDollar[3].node
-			yyVAL.node.Right = yyDollar[5].node
-		}
-	case 71:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:707
-		{
-			// normal test
-			yyVAL.node = Nod(OFOR, nil, nil)
-			yyVAL.node.Left = yyDollar[1].node
-		}
-	case 73:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:716
-		{
-			yyVAL.node = yyDollar[1].node
-			yyVAL.node.Nbody = concat(yyVAL.node.Nbody, yyDollar[2].list)
-		}
-	case 74:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:723
-		{
-			markdcl()
-		}
-	case 75:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:727
-		{
-			yyVAL.node = yyDollar[3].node
-			popdcl()
-		}
-	case 76:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:734
-		{
-			// test
-			yyVAL.node = Nod(OIF, nil, nil)
-			yyVAL.node.Left = yyDollar[1].node
-		}
-	case 77:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:740
-		{
-			// init ; test
-			yyVAL.node = Nod(OIF, nil, nil)
-			if yyDollar[1].node != nil {
-				yyVAL.node.Ninit = list1(yyDollar[1].node)
-			}
-			yyVAL.node.Left = yyDollar[3].node
-		}
-	case 78:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:752
-		{
-			markdcl()
-		}
-	case 79:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:756
-		{
-			if yyDollar[3].node.Left == nil {
-				Yyerror("missing condition in if statement")
-			}
-		}
-	case 80:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:762
-		{
-			yyDollar[3].node.Nbody = yyDollar[5].list
-		}
-	case 81:
-		yyDollar = yyS[yypt-8 : yypt+1]
-		//line go.y:766
-		{
-			var n *Node
-			var nn *NodeList
-
-			yyVAL.node = yyDollar[3].node
-			n = yyDollar[3].node
-			popdcl()
-			for nn = concat(yyDollar[7].list, yyDollar[8].list); nn != nil; nn = nn.Next {
-				if nn.N.Op == OIF {
-					popdcl()
-				}
-				n.Rlist = list1(nn.N)
-				n = nn.N
-			}
-		}
-	case 82:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:784
-		{
-			markdcl()
-		}
-	case 83:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:788
-		{
-			if yyDollar[4].node.Left == nil {
-				Yyerror("missing condition in if statement")
-			}
-			yyDollar[4].node.Nbody = yyDollar[5].list
-			yyVAL.list = list1(yyDollar[4].node)
-		}
-	case 84:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:797
-		{
-			yyVAL.list = nil
-		}
-	case 85:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:801
-		{
-			yyVAL.list = concat(yyDollar[1].list, yyDollar[2].list)
-		}
-	case 86:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:806
-		{
-			yyVAL.list = nil
-		}
-	case 87:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:810
-		{
-			l := &NodeList{N: yyDollar[2].node}
-			l.End = l
-			yyVAL.list = l
-		}
-	case 88:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:818
-		{
-			markdcl()
-		}
-	case 89:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:822
-		{
-			var n *Node
-			n = yyDollar[3].node.Left
-			if n != nil && n.Op != OTYPESW {
-				n = nil
-			}
-			typesw = Nod(OXXX, typesw, n)
-		}
-	case 90:
-		yyDollar = yyS[yypt-7 : yypt+1]
-		//line go.y:831
-		{
-			yyVAL.node = yyDollar[3].node
-			yyVAL.node.Op = OSWITCH
-			yyVAL.node.List = yyDollar[6].list
-			typesw = typesw.Left
-			popdcl()
-		}
-	case 91:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:841
-		{
-			typesw = Nod(OXXX, typesw, nil)
-		}
-	case 92:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:845
-		{
-			yyVAL.node = Nod(OSELECT, nil, nil)
-			yyVAL.node.Lineno = typesw.Lineno
-			yyVAL.node.List = yyDollar[4].list
-			typesw = typesw.Left
-		}
-	case 94:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:858
-		{
-			yyVAL.node = Nod(OOROR, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 95:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:862
-		{
-			yyVAL.node = Nod(OANDAND, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 96:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:866
-		{
-			yyVAL.node = Nod(OEQ, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 97:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:870
-		{
-			yyVAL.node = Nod(ONE, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 98:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:874
-		{
-			yyVAL.node = Nod(OLT, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 99:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:878
-		{
-			yyVAL.node = Nod(OLE, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 100:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:882
-		{
-			yyVAL.node = Nod(OGE, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 101:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:886
-		{
-			yyVAL.node = Nod(OGT, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 102:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:890
-		{
-			yyVAL.node = Nod(OADD, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 103:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:894
-		{
-			yyVAL.node = Nod(OSUB, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 104:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:898
-		{
-			yyVAL.node = Nod(OOR, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 105:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:902
-		{
-			yyVAL.node = Nod(OXOR, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 106:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:906
-		{
-			yyVAL.node = Nod(OMUL, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 107:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:910
-		{
-			yyVAL.node = Nod(ODIV, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 108:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:914
-		{
-			yyVAL.node = Nod(OMOD, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 109:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:918
-		{
-			yyVAL.node = Nod(OAND, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 110:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:922
-		{
-			yyVAL.node = Nod(OANDNOT, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 111:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:926
-		{
-			yyVAL.node = Nod(OLSH, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 112:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:930
-		{
-			yyVAL.node = Nod(ORSH, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 113:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:935
-		{
-			yyVAL.node = Nod(OSEND, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 115:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:942
-		{
-			yyVAL.node = Nod(OIND, yyDollar[2].node, nil)
-		}
-	case 116:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:946
-		{
-			if yyDollar[2].node.Op == OCOMPLIT {
-				// Special case for &T{...}: turn into (*T){...}.
-				yyVAL.node = yyDollar[2].node
-				yyVAL.node.Right = Nod(OIND, yyVAL.node.Right, nil)
-				yyVAL.node.Right.Implicit = true
-			} else {
-				yyVAL.node = Nod(OADDR, yyDollar[2].node, nil)
-			}
-		}
-	case 117:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:957
-		{
-			yyVAL.node = Nod(OPLUS, yyDollar[2].node, nil)
-		}
-	case 118:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:961
-		{
-			yyVAL.node = Nod(OMINUS, yyDollar[2].node, nil)
-		}
-	case 119:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:965
-		{
-			yyVAL.node = Nod(ONOT, yyDollar[2].node, nil)
-		}
-	case 120:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:969
-		{
-			Yyerror("the bitwise complement operator is ^")
-			yyVAL.node = Nod(OCOM, yyDollar[2].node, nil)
-		}
-	case 121:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:974
-		{
-			yyVAL.node = Nod(OCOM, yyDollar[2].node, nil)
-		}
-	case 122:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:978
-		{
-			yyVAL.node = Nod(ORECV, yyDollar[2].node, nil)
-		}
-	case 123:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:988
-		{
-			yyVAL.node = Nod(OCALL, yyDollar[1].node, nil)
-		}
-	case 124:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:992
-		{
-			yyVAL.node = Nod(OCALL, yyDollar[1].node, nil)
-			yyVAL.node.List = yyDollar[3].list
-		}
-	case 125:
-		yyDollar = yyS[yypt-6 : yypt+1]
-		//line go.y:997
-		{
-			yyVAL.node = Nod(OCALL, yyDollar[1].node, nil)
-			yyVAL.node.List = yyDollar[3].list
-			yyVAL.node.Isddd = true
-		}
-	case 126:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1005
-		{
-			yyVAL.node = nodlit(yyDollar[1].val)
-		}
-	case 128:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1010
-		{
-			if yyDollar[1].node.Op == OPACK {
-				var s *Sym
-				s = restrictlookup(yyDollar[3].sym.Name, yyDollar[1].node.Name.Pkg)
-				yyDollar[1].node.Used = true
-				yyVAL.node = oldname(s)
-				break
-			}
-			yyVAL.node = Nod(OXDOT, yyDollar[1].node, newname(yyDollar[3].sym))
-		}
-	case 129:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:1021
-		{
-			yyVAL.node = Nod(ODOTTYPE, yyDollar[1].node, yyDollar[4].node)
-		}
-	case 130:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:1025
-		{
-			yyVAL.node = Nod(OTYPESW, nil, yyDollar[1].node)
-		}
-	case 131:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:1029
-		{
-			yyVAL.node = Nod(OINDEX, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 132:
-		yyDollar = yyS[yypt-6 : yypt+1]
-		//line go.y:1033
-		{
-			yyVAL.node = Nod(OSLICE, yyDollar[1].node, Nod(OKEY, yyDollar[3].node, yyDollar[5].node))
-		}
-	case 133:
-		yyDollar = yyS[yypt-8 : yypt+1]
-		//line go.y:1037
-		{
-			if yyDollar[5].node == nil {
-				Yyerror("middle index required in 3-index slice")
-			}
-			if yyDollar[7].node == nil {
-				Yyerror("final index required in 3-index slice")
-			}
-			yyVAL.node = Nod(OSLICE3, yyDollar[1].node, Nod(OKEY, yyDollar[3].node, Nod(OKEY, yyDollar[5].node, yyDollar[7].node)))
-		}
-	case 135:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:1048
-		{
-			// conversion
-			yyVAL.node = Nod(OCALL, yyDollar[1].node, nil)
-			yyVAL.node.List = list1(yyDollar[3].node)
-		}
-	case 136:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:1054
-		{
-			yyVAL.node = yyDollar[3].node
-			yyVAL.node.Right = yyDollar[1].node
-			yyVAL.node.List = yyDollar[4].list
-			fixlbrace(yyDollar[2].i)
-		}
-	case 137:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:1061
-		{
-			yyVAL.node = yyDollar[3].node
-			yyVAL.node.Right = yyDollar[1].node
-			yyVAL.node.List = yyDollar[4].list
-		}
-	case 138:
-		yyDollar = yyS[yypt-7 : yypt+1]
-		//line go.y:1067
-		{
-			Yyerror("cannot parenthesize type in composite literal")
-			yyVAL.node = yyDollar[5].node
-			yyVAL.node.Right = yyDollar[2].node
-			yyVAL.node.List = yyDollar[6].list
-		}
-	case 140:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:1076
-		{
-			// composite expression.
-			// make node early so we get the right line number.
-			yyVAL.node = Nod(OCOMPLIT, nil, nil)
-		}
-	case 141:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1084
-		{
-			yyVAL.node = Nod(OKEY, yyDollar[1].node, yyDollar[3].node)
-		}
-	case 142:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1090
-		{
-			// These nodes do not carry line numbers.
-			// Since a composite literal commonly spans several lines,
-			// the line number on errors may be misleading.
-			// Introduce a wrapper node to give the correct line.
-			yyVAL.node = yyDollar[1].node
-			switch yyVAL.node.Op {
-			case ONAME, ONONAME, OTYPE, OPACK, OLITERAL:
-				yyVAL.node = Nod(OPAREN, yyVAL.node, nil)
-				yyVAL.node.Implicit = true
-			}
-		}
-	case 143:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:1103
-		{
-			yyVAL.node = yyDollar[2].node
-			yyVAL.node.List = yyDollar[3].list
-		}
-	case 145:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:1111
-		{
-			yyVAL.node = yyDollar[2].node
-			yyVAL.node.List = yyDollar[3].list
-		}
-	case 147:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1119
-		{
-			yyVAL.node = yyDollar[2].node
-
-			// Need to know on lhs of := whether there are ( ).
-			// Don't bother with the OPAREN in other cases:
-			// it's just a waste of memory and time.
-			switch yyVAL.node.Op {
-			case ONAME, ONONAME, OPACK, OTYPE, OLITERAL, OTYPESW:
-				yyVAL.node = Nod(OPAREN, yyVAL.node, nil)
-			}
-		}
-	case 151:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1140
-		{
-			yyVAL.i = LBODY
-		}
-	case 152:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1144
-		{
-			yyVAL.i = '{'
-		}
-	case 153:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1155
-		{
-			if yyDollar[1].sym == nil {
-				yyVAL.node = nil
-			} else {
-				yyVAL.node = newname(yyDollar[1].sym)
-			}
-		}
-	case 154:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1165
-		{
-			yyVAL.node = dclname(yyDollar[1].sym)
-		}
-	case 155:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:1170
-		{
-			yyVAL.node = nil
-		}
-	case 157:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1177
-		{
-			yyVAL.sym = yyDollar[1].sym
-			// during imports, unqualified non-exported identifiers are from builtinpkg
-			if importpkg != nil && !exportname(yyDollar[1].sym.Name) {
-				yyVAL.sym = Pkglookup(yyDollar[1].sym.Name, builtinpkg)
-			}
-		}
-	case 159:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1186
-		{
-			yyVAL.sym = nil
-		}
-	case 160:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:1192
-		{
-			var p *Pkg
-
-			if yyDollar[2].val.U.(string) == "" {
-				p = importpkg
-			} else {
-				if isbadimport(yyDollar[2].val.U.(string)) {
-					errorexit()
-				}
-				p = mkpkg(yyDollar[2].val.U.(string))
-			}
-			yyVAL.sym = Pkglookup(yyDollar[4].sym.Name, p)
-		}
-	case 161:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:1206
-		{
-			var p *Pkg
-
-			if yyDollar[2].val.U.(string) == "" {
-				p = importpkg
-			} else {
-				if isbadimport(yyDollar[2].val.U.(string)) {
-					errorexit()
-				}
-				p = mkpkg(yyDollar[2].val.U.(string))
-			}
-			yyVAL.sym = Pkglookup("?", p)
-		}
-	case 162:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1222
-		{
-			yyVAL.node = oldname(yyDollar[1].sym)
-			if yyVAL.node.Name != nil && yyVAL.node.Name.Pack != nil {
-				yyVAL.node.Name.Pack.Used = true
-			}
-		}
-	case 164:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1243
-		{
-			Yyerror("final argument in variadic function missing type")
-			yyVAL.node = Nod(ODDD, typenod(typ(TINTER)), nil)
-		}
-	case 165:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:1248
-		{
-			yyVAL.node = Nod(ODDD, yyDollar[2].node, nil)
-		}
-	case 171:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1259
-		{
-			yyVAL.node = yyDollar[2].node
-		}
-	case 175:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:1268
-		{
-			yyVAL.node = Nod(OIND, yyDollar[2].node, nil)
-		}
-	case 180:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1278
-		{
-			yyVAL.node = yyDollar[2].node
-		}
-	case 190:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1299
-		{
-			if yyDollar[1].node.Op == OPACK {
-				var s *Sym
-				s = restrictlookup(yyDollar[3].sym.Name, yyDollar[1].node.Name.Pkg)
-				yyDollar[1].node.Used = true
-				yyVAL.node = oldname(s)
-				break
-			}
-			yyVAL.node = Nod(OXDOT, yyDollar[1].node, newname(yyDollar[3].sym))
-		}
-	case 191:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:1312
-		{
-			yyVAL.node = Nod(OTARRAY, yyDollar[2].node, yyDollar[4].node)
-		}
-	case 192:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:1316
-		{
-			// array literal of nelem
-			yyVAL.node = Nod(OTARRAY, Nod(ODDD, nil, nil), yyDollar[4].node)
-		}
-	case 193:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:1321
-		{
-			yyVAL.node = Nod(OTCHAN, yyDollar[2].node, nil)
-			yyVAL.node.Etype = Cboth
-		}
-	case 194:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1326
-		{
-			yyVAL.node = Nod(OTCHAN, yyDollar[3].node, nil)
-			yyVAL.node.Etype = Csend
-		}
-	case 195:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:1331
-		{
-			yyVAL.node = Nod(OTMAP, yyDollar[3].node, yyDollar[5].node)
-		}
-	case 198:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:1339
-		{
-			yyVAL.node = Nod(OIND, yyDollar[2].node, nil)
-		}
-	case 199:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1345
-		{
-			yyVAL.node = Nod(OTCHAN, yyDollar[3].node, nil)
-			yyVAL.node.Etype = Crecv
-		}
-	case 200:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:1352
-		{
-			yyVAL.node = Nod(OTSTRUCT, nil, nil)
-			yyVAL.node.List = yyDollar[3].list
-			fixlbrace(yyDollar[2].i)
-		}
-	case 201:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1358
-		{
-			yyVAL.node = Nod(OTSTRUCT, nil, nil)
-			fixlbrace(yyDollar[2].i)
-		}
-	case 202:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:1365
-		{
-			yyVAL.node = Nod(OTINTER, nil, nil)
-			yyVAL.node.List = yyDollar[3].list
-			fixlbrace(yyDollar[2].i)
-		}
-	case 203:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1371
-		{
-			yyVAL.node = Nod(OTINTER, nil, nil)
-			fixlbrace(yyDollar[2].i)
-		}
-	case 204:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1382
-		{
-			yyVAL.node = yyDollar[2].node
-			if yyVAL.node == nil {
-				break
-			}
-			if noescape && yyDollar[3].list != nil {
-				Yyerror("can only use //go:noescape with external func implementations")
-			}
-			yyVAL.node.Nbody = yyDollar[3].list
-			yyVAL.node.Func.Endlineno = lineno
-			yyVAL.node.Noescape = noescape
-			yyVAL.node.Func.Norace = norace
-			yyVAL.node.Func.Nosplit = nosplit
-			yyVAL.node.Func.Nowritebarrier = nowritebarrier
-			yyVAL.node.Func.Systemstack = systemstack
-			funcbody(yyVAL.node)
-		}
-	case 205:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:1402
-		{
-			var t *Node
-
-			yyVAL.node = nil
-			yyDollar[3].list = checkarglist(yyDollar[3].list, 1)
-
-			if yyDollar[1].sym.Name == "init" {
-				yyDollar[1].sym = renameinit()
-				if yyDollar[3].list != nil || yyDollar[5].list != nil {
-					Yyerror("func init must have no arguments and no return values")
-				}
-			}
-			if localpkg.Name == "main" && yyDollar[1].sym.Name == "main" {
-				if yyDollar[3].list != nil || yyDollar[5].list != nil {
-					Yyerror("func main must have no arguments and no return values")
-				}
-			}
-
-			t = Nod(OTFUNC, nil, nil)
-			t.List = yyDollar[3].list
-			t.Rlist = yyDollar[5].list
-
-			yyVAL.node = Nod(ODCLFUNC, nil, nil)
-			yyVAL.node.Func.Nname = newfuncname(yyDollar[1].sym)
-			yyVAL.node.Func.Nname.Name.Defn = yyVAL.node
-			yyVAL.node.Func.Nname.Name.Param.Ntype = t // TODO: check if nname already has an ntype
-			declare(yyVAL.node.Func.Nname, PFUNC)
-
-			funchdr(yyVAL.node)
-		}
-	case 206:
-		yyDollar = yyS[yypt-8 : yypt+1]
-		//line go.y:1433
-		{
-			var rcvr, t *Node
-
-			yyVAL.node = nil
-			yyDollar[2].list = checkarglist(yyDollar[2].list, 0)
-			yyDollar[6].list = checkarglist(yyDollar[6].list, 1)
-
-			if yyDollar[2].list == nil {
-				Yyerror("method has no receiver")
-				break
-			}
-			if yyDollar[2].list.Next != nil {
-				Yyerror("method has multiple receivers")
-				break
-			}
-			rcvr = yyDollar[2].list.N
-			if rcvr.Op != ODCLFIELD {
-				Yyerror("bad receiver in method")
-				break
-			}
-
-			t = Nod(OTFUNC, rcvr, nil)
-			t.List = yyDollar[6].list
-			t.Rlist = yyDollar[8].list
-
-			yyVAL.node = Nod(ODCLFUNC, nil, nil)
-			yyVAL.node.Func.Shortname = newfuncname(yyDollar[4].sym)
-			yyVAL.node.Func.Nname = methodname1(yyVAL.node.Func.Shortname, rcvr.Right)
-			yyVAL.node.Func.Nname.Name.Defn = yyVAL.node
-			yyVAL.node.Func.Nname.Name.Param.Ntype = t
-			yyVAL.node.Func.Nname.Nointerface = nointerface
-			declare(yyVAL.node.Func.Nname, PFUNC)
-
-			funchdr(yyVAL.node)
-		}
-	case 207:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:1471
-		{
-			var s *Sym
-			var t *Type
-
-			yyVAL.node = nil
-
-			s = yyDollar[1].sym
-			t = functype(nil, yyDollar[3].list, yyDollar[5].list)
-
-			importsym(s, ONAME)
-			if s.Def != nil && s.Def.Op == ONAME {
-				if Eqtype(t, s.Def.Type) {
-					dclcontext = PDISCARD // since we skip funchdr below
-					break
-				}
-				Yyerror("inconsistent definition for func %v during import\n\t%v\n\t%v", s, s.Def.Type, t)
-			}
-
-			yyVAL.node = newfuncname(s)
-			yyVAL.node.Type = t
-			declare(yyVAL.node, PFUNC)
-
-			funchdr(yyVAL.node)
-		}
-	case 208:
-		yyDollar = yyS[yypt-8 : yypt+1]
-		//line go.y:1496
-		{
-			yyVAL.node = methodname1(newname(yyDollar[4].sym), yyDollar[2].list.N.Right)
-			yyVAL.node.Type = functype(yyDollar[2].list.N, yyDollar[6].list, yyDollar[8].list)
-
-			checkwidth(yyVAL.node.Type)
-			addmethod(yyDollar[4].sym, yyVAL.node.Type, false, nointerface)
-			nointerface = false
-			funchdr(yyVAL.node)
-
-			// inl.C's inlnode in on a dotmeth node expects to find the inlineable body as
-			// (dotmeth's type).Nname.Inl, and dotmeth's type has been pulled
-			// out by typecheck's lookdot as this $$.ttype.  So by providing
-			// this back link here we avoid special casing there.
-			yyVAL.node.Type.Nname = yyVAL.node
-		}
-	case 209:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:1514
-		{
-			yyDollar[3].list = checkarglist(yyDollar[3].list, 1)
-			yyVAL.node = Nod(OTFUNC, nil, nil)
-			yyVAL.node.List = yyDollar[3].list
-			yyVAL.node.Rlist = yyDollar[5].list
-		}
-	case 210:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:1522
-		{
-			yyVAL.list = nil
-		}
-	case 211:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1526
-		{
-			yyVAL.list = yyDollar[2].list
-			if yyVAL.list == nil {
-				yyVAL.list = list1(Nod(OEMPTY, nil, nil))
-			}
-		}
-	case 212:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:1535
-		{
-			yyVAL.list = nil
-		}
-	case 213:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1539
-		{
-			yyVAL.list = list1(Nod(ODCLFIELD, nil, yyDollar[1].node))
-		}
-	case 214:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1543
-		{
-			yyDollar[2].list = checkarglist(yyDollar[2].list, 0)
-			yyVAL.list = yyDollar[2].list
-		}
-	case 215:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1550
-		{
-			closurehdr(yyDollar[1].node)
-		}
-	case 216:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:1556
-		{
-			yyVAL.node = closurebody(yyDollar[3].list)
-			fixlbrace(yyDollar[2].i)
-		}
-	case 217:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:1561
-		{
-			yyVAL.node = closurebody(nil)
-		}
-	case 218:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:1572
-		{
-			yyVAL.list = nil
-		}
-	case 219:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1576
-		{
-			yyVAL.list = concat(yyDollar[1].list, yyDollar[2].list)
-			if nsyntaxerrors == 0 {
-				testdclstack()
-			}
-			nointerface = false
-			noescape = false
-			norace = false
-			nosplit = false
-			nowritebarrier = false
-			systemstack = false
-		}
-	case 221:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1592
-		{
-			yyVAL.list = concat(yyDollar[1].list, yyDollar[3].list)
-		}
-	case 223:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1599
-		{
-			yyVAL.list = concat(yyDollar[1].list, yyDollar[3].list)
-		}
-	case 224:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1605
-		{
-			yyVAL.list = list1(yyDollar[1].node)
-		}
-	case 225:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1609
-		{
-			yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
-		}
-	case 227:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1616
-		{
-			yyVAL.list = concat(yyDollar[1].list, yyDollar[3].list)
-		}
-	case 228:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1622
-		{
-			yyVAL.list = list1(yyDollar[1].node)
-		}
-	case 229:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1626
-		{
-			yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
-		}
-	case 230:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1632
-		{
-			var l *NodeList
-
-			var n *Node
-			l = yyDollar[1].list
-			if l == nil || l.N.Sym.Name == "?" {
-				// ? symbol, during import (list1(nil) == nil)
-				n = yyDollar[2].node
-				if n.Op == OIND {
-					n = n.Left
-				}
-				n = embedded(n.Sym, importpkg)
-				n.Right = yyDollar[2].node
-				n.SetVal(yyDollar[3].val)
-				yyVAL.list = list1(n)
-				break
-			}
-
-			for l = yyDollar[1].list; l != nil; l = l.Next {
-				l.N = Nod(ODCLFIELD, l.N, yyDollar[2].node)
-				l.N.SetVal(yyDollar[3].val)
-			}
-		}
-	case 231:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:1656
-		{
-			yyDollar[1].node.SetVal(yyDollar[2].val)
-			yyVAL.list = list1(yyDollar[1].node)
-		}
-	case 232:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:1661
-		{
-			yyDollar[2].node.SetVal(yyDollar[4].val)
-			yyVAL.list = list1(yyDollar[2].node)
-			Yyerror("cannot parenthesize embedded type")
-		}
-	case 233:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1667
-		{
-			yyDollar[2].node.Right = Nod(OIND, yyDollar[2].node.Right, nil)
-			yyDollar[2].node.SetVal(yyDollar[3].val)
-			yyVAL.list = list1(yyDollar[2].node)
-		}
-	case 234:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:1673
-		{
-			yyDollar[3].node.Right = Nod(OIND, yyDollar[3].node.Right, nil)
-			yyDollar[3].node.SetVal(yyDollar[5].val)
-			yyVAL.list = list1(yyDollar[3].node)
-			Yyerror("cannot parenthesize embedded type")
-		}
-	case 235:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:1680
-		{
-			yyDollar[3].node.Right = Nod(OIND, yyDollar[3].node.Right, nil)
-			yyDollar[3].node.SetVal(yyDollar[5].val)
-			yyVAL.list = list1(yyDollar[3].node)
-			Yyerror("cannot parenthesize embedded type")
-		}
-	case 236:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1689
-		{
-			var n *Node
-
-			yyVAL.sym = yyDollar[1].sym
-			n = oldname(yyDollar[1].sym)
-			if n.Name != nil && n.Name.Pack != nil {
-				n.Name.Pack.Used = true
-			}
-		}
-	case 237:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1699
-		{
-			var pkg *Pkg
-
-			if yyDollar[1].sym.Def == nil || yyDollar[1].sym.Def.Op != OPACK {
-				Yyerror("%v is not a package", yyDollar[1].sym)
-				pkg = localpkg
-			} else {
-				yyDollar[1].sym.Def.Used = true
-				pkg = yyDollar[1].sym.Def.Name.Pkg
-			}
-			yyVAL.sym = restrictlookup(yyDollar[3].sym.Name, pkg)
-		}
-	case 238:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1714
-		{
-			yyVAL.node = embedded(yyDollar[1].sym, localpkg)
-		}
-	case 239:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:1720
-		{
-			yyVAL.node = Nod(ODCLFIELD, yyDollar[1].node, yyDollar[2].node)
-			ifacedcl(yyVAL.node)
-		}
-	case 240:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1725
-		{
-			yyVAL.node = Nod(ODCLFIELD, nil, oldname(yyDollar[1].sym))
-		}
-	case 241:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1729
-		{
-			yyVAL.node = Nod(ODCLFIELD, nil, oldname(yyDollar[2].sym))
-			Yyerror("cannot parenthesize embedded type")
-		}
-	case 242:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:1736
-		{
-			// without func keyword
-			yyDollar[2].list = checkarglist(yyDollar[2].list, 1)
-			yyVAL.node = Nod(OTFUNC, fakethis(), nil)
-			yyVAL.node.List = yyDollar[2].list
-			yyVAL.node.Rlist = yyDollar[4].list
-		}
-	case 244:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:1750
-		{
-			yyVAL.node = Nod(ONONAME, nil, nil)
-			yyVAL.node.Sym = yyDollar[1].sym
-			yyVAL.node = Nod(OKEY, yyVAL.node, yyDollar[2].node)
-		}
-	case 245:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:1756
-		{
-			yyVAL.node = Nod(ONONAME, nil, nil)
-			yyVAL.node.Sym = yyDollar[1].sym
-			yyVAL.node = Nod(OKEY, yyVAL.node, yyDollar[2].node)
-		}
-	case 247:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1765
-		{
-			yyVAL.list = list1(yyDollar[1].node)
-		}
-	case 248:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1769
-		{
-			yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
-		}
-	case 249:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:1774
-		{
-			yyVAL.list = nil
-		}
-	case 250:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:1778
-		{
-			yyVAL.list = yyDollar[1].list
-		}
-	case 251:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:1786
-		{
-			yyVAL.node = nil
-		}
-	case 253:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1791
-		{
-			yyVAL.node = liststmt(yyDollar[1].list)
-		}
-	case 255:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1796
-		{
-			yyVAL.node = nil
-		}
-	case 261:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:1807
-		{
-			yyDollar[1].node = Nod(OLABEL, yyDollar[1].node, nil)
-			yyDollar[1].node.Sym = dclstack // context, for goto restrictions
-		}
-	case 262:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:1812
-		{
-			var l *NodeList
-
-			yyDollar[1].node.Name.Defn = yyDollar[4].node
-			l = list1(yyDollar[1].node)
-			if yyDollar[4].node != nil {
-				l = list(l, yyDollar[4].node)
-			}
-			yyVAL.node = liststmt(l)
-		}
-	case 263:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1823
-		{
-			// will be converted to OFALL
-			yyVAL.node = Nod(OXFALL, nil, nil)
-			yyVAL.node.Xoffset = int64(block)
-		}
-	case 264:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:1829
-		{
-			yyVAL.node = Nod(OBREAK, yyDollar[2].node, nil)
-		}
-	case 265:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:1833
-		{
-			yyVAL.node = Nod(OCONTINUE, yyDollar[2].node, nil)
-		}
-	case 266:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:1837
-		{
-			yyVAL.node = Nod(OPROC, yyDollar[2].node, nil)
-		}
-	case 267:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:1841
-		{
-			yyVAL.node = Nod(ODEFER, yyDollar[2].node, nil)
-		}
-	case 268:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:1845
-		{
-			yyVAL.node = Nod(OGOTO, yyDollar[2].node, nil)
-			yyVAL.node.Sym = dclstack // context, for goto restrictions
-		}
-	case 269:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:1850
-		{
-			yyVAL.node = Nod(ORETURN, nil, nil)
-			yyVAL.node.List = yyDollar[2].list
-			if yyVAL.node.List == nil && Curfn != nil {
-				var l *NodeList
-
-				for l = Curfn.Func.Dcl; l != nil; l = l.Next {
-					if l.N.Class == PPARAM {
-						continue
-					}
-					if l.N.Class != PPARAMOUT {
-						break
-					}
-					if l.N.Sym.Def != l.N {
-						Yyerror("%s is shadowed during return", l.N.Sym.Name)
-					}
-				}
-			}
-		}
-	case 270:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1872
-		{
-			yyVAL.list = nil
-			if yyDollar[1].node != nil {
-				yyVAL.list = list1(yyDollar[1].node)
-			}
-		}
-	case 271:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1879
-		{
-			yyVAL.list = yyDollar[1].list
-			if yyDollar[3].node != nil {
-				yyVAL.list = list(yyVAL.list, yyDollar[3].node)
-			}
-		}
-	case 272:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1888
-		{
-			yyVAL.list = list1(yyDollar[1].node)
-		}
-	case 273:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1892
-		{
-			yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
-		}
-	case 274:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1898
-		{
-			yyVAL.list = list1(yyDollar[1].node)
-		}
-	case 275:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1902
-		{
-			yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
-		}
-	case 276:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1908
-		{
-			yyVAL.list = list1(yyDollar[1].node)
-		}
-	case 277:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1912
-		{
-			yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
-		}
-	case 278:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1918
-		{
-			yyVAL.list = list1(yyDollar[1].node)
-		}
-	case 279:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1922
-		{
-			yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
-		}
-	case 280:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1931
-		{
-			yyVAL.list = list1(yyDollar[1].node)
-		}
-	case 281:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:1935
-		{
-			yyVAL.list = list1(yyDollar[1].node)
-		}
-	case 282:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1939
-		{
-			yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
-		}
-	case 283:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:1943
-		{
-			yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
-		}
-	case 284:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:1948
-		{
-			yyVAL.list = nil
-		}
-	case 285:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:1952
-		{
-			yyVAL.list = yyDollar[1].list
-		}
-	case 290:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:1966
-		{
-			yyVAL.node = nil
-		}
-	case 292:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:1972
-		{
-			yyVAL.list = nil
-		}
-	case 294:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:1978
-		{
-			yyVAL.node = nil
-		}
-	case 296:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:1984
-		{
-			yyVAL.list = nil
-		}
-	case 298:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:1990
-		{
-			yyVAL.list = nil
-		}
-	case 300:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:1996
-		{
-			yyVAL.list = nil
-		}
-	case 302:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:2002
-		{
-			yyVAL.val.U = nil
-		}
-	case 304:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:2012
-		{
-			importimport(yyDollar[2].sym, yyDollar[3].val.U.(string))
-		}
-	case 305:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:2016
-		{
-			importvar(yyDollar[2].sym, yyDollar[3].typ)
-		}
-	case 306:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:2020
-		{
-			importconst(yyDollar[2].sym, Types[TIDEAL], yyDollar[4].node)
-		}
-	case 307:
-		yyDollar = yyS[yypt-6 : yypt+1]
-		//line go.y:2024
-		{
-			importconst(yyDollar[2].sym, yyDollar[3].typ, yyDollar[5].node)
-		}
-	case 308:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:2028
-		{
-			importtype(yyDollar[2].typ, yyDollar[3].typ)
-		}
-	case 309:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:2032
-		{
-			if yyDollar[2].node == nil {
-				dclcontext = PEXTERN // since we skip the funcbody below
-				break
-			}
-
-			yyDollar[2].node.Func.Inl = yyDollar[3].list
-
-			funcbody(yyDollar[2].node)
-			importlist = list(importlist, yyDollar[2].node)
-
-			if Debug['E'] > 0 {
-				fmt.Printf("import [%q] func %v \n", importpkg.Path, yyDollar[2].node)
-				if Debug['m'] > 2 && yyDollar[2].node.Func.Inl != nil {
-					fmt.Printf("inl body:%v\n", yyDollar[2].node.Func.Inl)
-				}
-			}
-		}
-	case 310:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:2053
-		{
-			yyVAL.sym = yyDollar[1].sym
-			structpkg = yyVAL.sym.Pkg
-		}
-	case 311:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:2060
-		{
-			yyVAL.typ = pkgtype(yyDollar[1].sym)
-			importsym(yyDollar[1].sym, OTYPE)
-		}
-	case 317:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:2080
-		{
-			yyVAL.typ = pkgtype(yyDollar[1].sym)
-		}
-	case 318:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:2084
-		{
-			// predefined name like uint8
-			yyDollar[1].sym = Pkglookup(yyDollar[1].sym.Name, builtinpkg)
-			if yyDollar[1].sym.Def == nil || yyDollar[1].sym.Def.Op != OTYPE {
-				Yyerror("%s is not a type", yyDollar[1].sym.Name)
-				yyVAL.typ = nil
-			} else {
-				yyVAL.typ = yyDollar[1].sym.Def.Type
-			}
-		}
-	case 319:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:2095
-		{
-			yyVAL.typ = aindex(nil, yyDollar[3].typ)
-		}
-	case 320:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:2099
-		{
-			yyVAL.typ = aindex(nodlit(yyDollar[2].val), yyDollar[4].typ)
-		}
-	case 321:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:2103
-		{
-			yyVAL.typ = maptype(yyDollar[3].typ, yyDollar[5].typ)
-		}
-	case 322:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:2107
-		{
-			yyVAL.typ = tostruct(yyDollar[3].list)
-		}
-	case 323:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:2111
-		{
-			yyVAL.typ = tointerface(yyDollar[3].list)
-		}
-	case 324:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:2115
-		{
-			yyVAL.typ = Ptrto(yyDollar[2].typ)
-		}
-	case 325:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:2119
-		{
-			yyVAL.typ = typ(TCHAN)
-			yyVAL.typ.Type = yyDollar[2].typ
-			yyVAL.typ.Chan = Cboth
-		}
-	case 326:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:2125
-		{
-			yyVAL.typ = typ(TCHAN)
-			yyVAL.typ.Type = yyDollar[3].typ
-			yyVAL.typ.Chan = Cboth
-		}
-	case 327:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:2131
-		{
-			yyVAL.typ = typ(TCHAN)
-			yyVAL.typ.Type = yyDollar[3].typ
-			yyVAL.typ.Chan = Csend
-		}
-	case 328:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:2139
-		{
-			yyVAL.typ = typ(TCHAN)
-			yyVAL.typ.Type = yyDollar[3].typ
-			yyVAL.typ.Chan = Crecv
-		}
-	case 329:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:2147
-		{
-			yyVAL.typ = functype(nil, yyDollar[3].list, yyDollar[5].list)
-		}
-	case 330:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:2153
-		{
-			yyVAL.node = Nod(ODCLFIELD, nil, typenod(yyDollar[2].typ))
-			if yyDollar[1].sym != nil {
-				yyVAL.node.Left = newname(yyDollar[1].sym)
-			}
-			yyVAL.node.SetVal(yyDollar[3].val)
-		}
-	case 331:
-		yyDollar = yyS[yypt-4 : yypt+1]
-		//line go.y:2161
-		{
-			var t *Type
-
-			t = typ(TARRAY)
-			t.Bound = -1
-			t.Type = yyDollar[3].typ
-
-			yyVAL.node = Nod(ODCLFIELD, nil, typenod(t))
-			if yyDollar[1].sym != nil {
-				yyVAL.node.Left = newname(yyDollar[1].sym)
-			}
-			yyVAL.node.Isddd = true
-			yyVAL.node.SetVal(yyDollar[4].val)
-		}
-	case 332:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:2178
-		{
-			var s *Sym
-			var p *Pkg
-
-			if yyDollar[1].sym != nil && yyDollar[1].sym.Name != "?" {
-				yyVAL.node = Nod(ODCLFIELD, newname(yyDollar[1].sym), typenod(yyDollar[2].typ))
-				yyVAL.node.SetVal(yyDollar[3].val)
-			} else {
-				s = yyDollar[2].typ.Sym
-				if s == nil && Isptr[yyDollar[2].typ.Etype] {
-					s = yyDollar[2].typ.Type.Sym
-				}
-				p = importpkg
-				if yyDollar[1].sym != nil {
-					p = yyDollar[1].sym.Pkg
-				}
-				yyVAL.node = embedded(s, p)
-				yyVAL.node.Right = typenod(yyDollar[2].typ)
-				yyVAL.node.SetVal(yyDollar[3].val)
-			}
-		}
-	case 333:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:2202
-		{
-			yyVAL.node = Nod(ODCLFIELD, newname(yyDollar[1].sym), typenod(functype(fakethis(), yyDollar[3].list, yyDollar[5].list)))
-		}
-	case 334:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:2206
-		{
-			yyVAL.node = Nod(ODCLFIELD, nil, typenod(yyDollar[1].typ))
-		}
-	case 335:
-		yyDollar = yyS[yypt-0 : yypt+1]
-		//line go.y:2211
-		{
-			yyVAL.list = nil
-		}
-	case 337:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:2218
-		{
-			yyVAL.list = yyDollar[2].list
-		}
-	case 338:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:2222
-		{
-			yyVAL.list = list1(Nod(ODCLFIELD, nil, typenod(yyDollar[1].typ)))
-		}
-	case 339:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:2232
-		{
-			yyVAL.node = nodlit(yyDollar[1].val)
-		}
-	case 340:
-		yyDollar = yyS[yypt-2 : yypt+1]
-		//line go.y:2236
-		{
-			yyVAL.node = nodlit(yyDollar[2].val)
-			switch yyVAL.node.Val().Ctype() {
-			case CTINT, CTRUNE:
-				mpnegfix(yyVAL.node.Val().U.(*Mpint))
-				break
-			case CTFLT:
-				mpnegflt(yyVAL.node.Val().U.(*Mpflt))
-				break
-			case CTCPLX:
-				mpnegflt(&yyVAL.node.Val().U.(*Mpcplx).Real)
-				mpnegflt(&yyVAL.node.Val().U.(*Mpcplx).Imag)
-				break
-			default:
-				Yyerror("bad negated constant")
-			}
-		}
-	case 341:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:2254
-		{
-			yyVAL.node = oldname(Pkglookup(yyDollar[1].sym.Name, builtinpkg))
-			if yyVAL.node.Op != OLITERAL {
-				Yyerror("bad constant %v", yyVAL.node.Sym)
-			}
-		}
-	case 343:
-		yyDollar = yyS[yypt-5 : yypt+1]
-		//line go.y:2264
-		{
-			if yyDollar[2].node.Val().Ctype() == CTRUNE && yyDollar[4].node.Val().Ctype() == CTINT {
-				yyVAL.node = yyDollar[2].node
-				mpaddfixfix(yyDollar[2].node.Val().U.(*Mpint), yyDollar[4].node.Val().U.(*Mpint), 0)
-				break
-			}
-			yyDollar[4].node.Val().U.(*Mpcplx).Real = yyDollar[4].node.Val().U.(*Mpcplx).Imag
-			Mpmovecflt(&yyDollar[4].node.Val().U.(*Mpcplx).Imag, 0.0)
-			yyVAL.node = nodcplxlit(yyDollar[2].node.Val(), yyDollar[4].node.Val())
-		}
-	case 346:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:2280
-		{
-			yyVAL.list = list1(yyDollar[1].node)
-		}
-	case 347:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:2284
-		{
-			yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
-		}
-	case 348:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:2290
-		{
-			yyVAL.list = list1(yyDollar[1].node)
-		}
-	case 349:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:2294
-		{
-			yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
-		}
-	case 350:
-		yyDollar = yyS[yypt-1 : yypt+1]
-		//line go.y:2300
-		{
-			yyVAL.list = list1(yyDollar[1].node)
-		}
-	case 351:
-		yyDollar = yyS[yypt-3 : yypt+1]
-		//line go.y:2304
-		{
-			yyVAL.list = list(yyDollar[1].list, yyDollar[3].node)
-		}
-	}
-	goto yystack /* stack new state and value */
-}
diff --git a/src/cmd/compile/internal/mips64/cgen.go b/src/cmd/compile/internal/mips64/cgen.go
new file mode 100644
index 0000000..434bfc7
--- /dev/null
+++ b/src/cmd/compile/internal/mips64/cgen.go
@@ -0,0 +1,157 @@
+// Copyright 2009 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 mips64
+
+import (
+	"cmd/compile/internal/gc"
+	"cmd/internal/obj"
+	"cmd/internal/obj/mips"
+)
+
+func blockcopy(n, res *gc.Node, osrc, odst, w int64) {
+	// determine alignment.
+	// want to avoid unaligned access, so have to use
+	// smaller operations for less aligned types.
+	// for example moving [4]byte must use 4 MOVB not 1 MOVW.
+	align := int(n.Type.Align)
+
+	var op int
+	switch align {
+	default:
+		gc.Fatalf("sgen: invalid alignment %d for %v", align, n.Type)
+
+	case 1:
+		op = mips.AMOVB
+
+	case 2:
+		op = mips.AMOVH
+
+	case 4:
+		op = mips.AMOVW
+
+	case 8:
+		op = mips.AMOVV
+	}
+
+	if w%int64(align) != 0 {
+		gc.Fatalf("sgen: unaligned size %d (align=%d) for %v", w, align, n.Type)
+	}
+	c := int32(w / int64(align))
+
+	// if we are copying forward on the stack and
+	// the src and dst overlap, then reverse direction
+	dir := align
+
+	if osrc < odst && int64(odst) < int64(osrc)+w {
+		dir = -dir
+	}
+
+	var dst gc.Node
+	var src gc.Node
+	if n.Ullman >= res.Ullman {
+		gc.Agenr(n, &dst, res) // temporarily use dst
+		gc.Regalloc(&src, gc.Types[gc.Tptr], nil)
+		gins(mips.AMOVV, &dst, &src)
+		if res.Op == gc.ONAME {
+			gc.Gvardef(res)
+		}
+		gc.Agen(res, &dst)
+	} else {
+		if res.Op == gc.ONAME {
+			gc.Gvardef(res)
+		}
+		gc.Agenr(res, &dst, res)
+		gc.Agenr(n, &src, nil)
+	}
+
+	var tmp gc.Node
+	gc.Regalloc(&tmp, gc.Types[gc.Tptr], nil)
+
+	// set up end marker
+	var nend gc.Node
+
+	// move src and dest to the end of block if necessary
+	if dir < 0 {
+		if c >= 4 {
+			gc.Regalloc(&nend, gc.Types[gc.Tptr], nil)
+			gins(mips.AMOVV, &src, &nend)
+		}
+
+		p := gins(mips.AADDV, nil, &src)
+		p.From.Type = obj.TYPE_CONST
+		p.From.Offset = w
+
+		p = gins(mips.AADDV, nil, &dst)
+		p.From.Type = obj.TYPE_CONST
+		p.From.Offset = w
+	} else {
+		p := gins(mips.AADDV, nil, &src)
+		p.From.Type = obj.TYPE_CONST
+		p.From.Offset = int64(-dir)
+
+		p = gins(mips.AADDV, nil, &dst)
+		p.From.Type = obj.TYPE_CONST
+		p.From.Offset = int64(-dir)
+
+		if c >= 4 {
+			gc.Regalloc(&nend, gc.Types[gc.Tptr], nil)
+			p := gins(mips.AMOVV, &src, &nend)
+			p.From.Type = obj.TYPE_ADDR
+			p.From.Offset = w
+		}
+	}
+
+	// move
+	// TODO: enable duffcopy for larger copies.
+	if c >= 4 {
+		p := gins(op, &src, &tmp)
+		p.From.Type = obj.TYPE_MEM
+		p.From.Offset = int64(dir)
+		ploop := p
+
+		p = gins(mips.AADDV, nil, &src)
+		p.From.Type = obj.TYPE_CONST
+		p.From.Offset = int64(dir)
+
+		p = gins(op, &tmp, &dst)
+		p.To.Type = obj.TYPE_MEM
+		p.To.Offset = int64(dir)
+
+		p = gins(mips.AADDV, nil, &dst)
+		p.From.Type = obj.TYPE_CONST
+		p.From.Offset = int64(dir)
+
+		gc.Patch(ginsbranch(mips.ABNE, nil, &src, &nend, 0), ploop)
+		gc.Regfree(&nend)
+	} else {
+		// TODO: Instead of generating ADDV $-8,R8; ADDV
+		// $-8,R7; n*(MOVV 8(R8),R9; ADDV $8,R8; MOVV R9,8(R7);
+		// ADDV $8,R7;) just generate the offsets directly and
+		// eliminate the ADDs.  That will produce shorter, more
+		// pipeline-able code.
+		var p *obj.Prog
+		for ; c > 0; c-- {
+			p = gins(op, &src, &tmp)
+			p.From.Type = obj.TYPE_MEM
+			p.From.Offset = int64(dir)
+
+			p = gins(mips.AADDV, nil, &src)
+			p.From.Type = obj.TYPE_CONST
+			p.From.Offset = int64(dir)
+
+			p = gins(op, &tmp, &dst)
+			p.To.Type = obj.TYPE_MEM
+			p.To.Offset = int64(dir)
+
+			p = gins(mips.AADDV, nil, &dst)
+			p.From.Type = obj.TYPE_CONST
+			p.From.Offset = int64(dir)
+		}
+	}
+
+	gc.Regfree(&dst)
+	gc.Regfree(&src)
+	gc.Regfree(&tmp)
+}
diff --git a/src/cmd/compile/internal/mips64/galign.go b/src/cmd/compile/internal/mips64/galign.go
new file mode 100644
index 0000000..00ffe17
--- /dev/null
+++ b/src/cmd/compile/internal/mips64/galign.go
@@ -0,0 +1,100 @@
+// Copyright 2009 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 mips64
+
+import (
+	"cmd/compile/internal/gc"
+	"cmd/internal/obj"
+	"cmd/internal/obj/mips"
+)
+
+var thechar int = '0'
+
+var thestring string = "mips64"
+
+var thelinkarch *obj.LinkArch
+
+func linkarchinit() {
+	thestring = obj.Getgoarch()
+	gc.Thearch.Thestring = thestring
+	if thestring == "mips64le" {
+		thelinkarch = &mips.Linkmips64le
+	} else {
+		thelinkarch = &mips.Linkmips64
+	}
+	gc.Thearch.Thelinkarch = thelinkarch
+}
+
+var MAXWIDTH int64 = 1 << 50
+
+/*
+ * go declares several platform-specific type aliases:
+ * int, uint, and uintptr
+ */
+var typedefs = []gc.Typedef{
+	{"int", gc.TINT, gc.TINT64},
+	{"uint", gc.TUINT, gc.TUINT64},
+	{"uintptr", gc.TUINTPTR, gc.TUINT64},
+}
+
+func betypeinit() {
+	gc.Widthptr = 8
+	gc.Widthint = 8
+	gc.Widthreg = 8
+}
+
+func Main() {
+	gc.Thearch.Thechar = thechar
+	gc.Thearch.Thestring = thestring
+	gc.Thearch.Thelinkarch = thelinkarch
+	gc.Thearch.Typedefs = typedefs
+	gc.Thearch.REGSP = mips.REGSP
+	gc.Thearch.REGCTXT = mips.REGCTXT
+	gc.Thearch.REGCALLX = mips.REG_R1
+	gc.Thearch.REGCALLX2 = mips.REG_R2
+	gc.Thearch.REGRETURN = mips.REGRET
+	gc.Thearch.REGMIN = mips.REG_R0
+	gc.Thearch.REGMAX = mips.REG_R31
+	gc.Thearch.FREGMIN = mips.REG_F0
+	gc.Thearch.FREGMAX = mips.REG_F31
+	gc.Thearch.MAXWIDTH = MAXWIDTH
+	gc.Thearch.ReservedRegs = resvd
+
+	gc.Thearch.Betypeinit = betypeinit
+	gc.Thearch.Cgen_hmul = cgen_hmul
+	gc.Thearch.Cgen_shift = cgen_shift
+	gc.Thearch.Clearfat = clearfat
+	gc.Thearch.Defframe = defframe
+	gc.Thearch.Dodiv = dodiv
+	gc.Thearch.Excise = excise
+	gc.Thearch.Expandchecks = expandchecks
+	gc.Thearch.Getg = getg
+	gc.Thearch.Gins = gins
+	gc.Thearch.Ginscmp = ginscmp
+	gc.Thearch.Ginscon = ginscon
+	gc.Thearch.Ginsnop = ginsnop
+	gc.Thearch.Gmove = gmove
+	gc.Thearch.Linkarchinit = linkarchinit
+	gc.Thearch.Peep = peep
+	gc.Thearch.Proginfo = proginfo
+	gc.Thearch.Regtyp = regtyp
+	gc.Thearch.Sameaddr = sameaddr
+	gc.Thearch.Smallindir = smallindir
+	gc.Thearch.Stackaddr = stackaddr
+	gc.Thearch.Blockcopy = blockcopy
+	gc.Thearch.Sudoaddable = sudoaddable
+	gc.Thearch.Sudoclean = sudoclean
+	gc.Thearch.Excludedregs = excludedregs
+	gc.Thearch.RtoB = RtoB
+	gc.Thearch.FtoB = RtoB
+	gc.Thearch.BtoR = BtoR
+	gc.Thearch.BtoF = BtoF
+	gc.Thearch.Optoas = optoas
+	gc.Thearch.Doregbits = doregbits
+	gc.Thearch.Regnames = regnames
+
+	gc.Main()
+	gc.Exit(0)
+}
diff --git a/src/cmd/compile/internal/mips64/ggen.go b/src/cmd/compile/internal/mips64/ggen.go
new file mode 100644
index 0000000..8c285a2
--- /dev/null
+++ b/src/cmd/compile/internal/mips64/ggen.go
@@ -0,0 +1,494 @@
+// Copyright 2009 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 mips64
+
+import (
+	"cmd/compile/internal/gc"
+	"cmd/internal/obj"
+	"cmd/internal/obj/mips"
+	"fmt"
+)
+
+func defframe(ptxt *obj.Prog) {
+	var n *gc.Node
+
+	// fill in argument size, stack size
+	ptxt.To.Type = obj.TYPE_TEXTSIZE
+
+	ptxt.To.Val = int32(gc.Rnd(gc.Curfn.Type.Argwid, int64(gc.Widthptr)))
+	frame := uint32(gc.Rnd(gc.Stksize+gc.Maxarg, int64(gc.Widthreg)))
+	ptxt.To.Offset = int64(frame)
+
+	// insert code to zero ambiguously live variables
+	// so that the garbage collector only sees initialized values
+	// when it looks for pointers.
+	p := ptxt
+
+	hi := int64(0)
+	lo := hi
+
+	// iterate through declarations - they are sorted in decreasing xoffset order.
+	for l := gc.Curfn.Func.Dcl; l != nil; l = l.Next {
+		n = l.N
+		if !n.Name.Needzero {
+			continue
+		}
+		if n.Class != gc.PAUTO {
+			gc.Fatalf("needzero class %d", n.Class)
+		}
+		if n.Type.Width%int64(gc.Widthptr) != 0 || n.Xoffset%int64(gc.Widthptr) != 0 || n.Type.Width == 0 {
+			gc.Fatalf("var %v has size %d offset %d", gc.Nconv(n, obj.FmtLong), int(n.Type.Width), int(n.Xoffset))
+		}
+
+		if lo != hi && n.Xoffset+n.Type.Width >= lo-int64(2*gc.Widthreg) {
+			// merge with range we already have
+			lo = n.Xoffset
+
+			continue
+		}
+
+		// zero old range
+		p = zerorange(p, int64(frame), lo, hi)
+
+		// set new range
+		hi = n.Xoffset + n.Type.Width
+
+		lo = n.Xoffset
+	}
+
+	// zero final range
+	zerorange(p, int64(frame), lo, hi)
+}
+
+func zerorange(p *obj.Prog, frame int64, lo int64, hi int64) *obj.Prog {
+	cnt := hi - lo
+	if cnt == 0 {
+		return p
+	}
+	if cnt < int64(4*gc.Widthptr) {
+		for i := int64(0); i < cnt; i += int64(gc.Widthptr) {
+			p = appendpp(p, mips.AMOVV, obj.TYPE_REG, mips.REGZERO, 0, obj.TYPE_MEM, mips.REGSP, 8+frame+lo+i)
+		}
+		// TODO(dfc): https://golang.org/issue/12108
+		// If DUFFZERO is used inside a tail call (see genwrapper) it will
+		// overwrite the link register.
+	} else if false && cnt <= int64(128*gc.Widthptr) {
+		p = appendpp(p, mips.AADDV, obj.TYPE_CONST, 0, 8+frame+lo-8, obj.TYPE_REG, mips.REGRT1, 0)
+		p.Reg = mips.REGSP
+		p = appendpp(p, obj.ADUFFZERO, obj.TYPE_NONE, 0, 0, obj.TYPE_MEM, 0, 0)
+		f := gc.Sysfunc("duffzero")
+		gc.Naddr(&p.To, f)
+		gc.Afunclit(&p.To, f)
+		p.To.Offset = 8 * (128 - cnt/int64(gc.Widthptr))
+	} else {
+		//	ADDV	$(8+frame+lo-8), SP, r1
+		//	ADDV	$cnt, r1, r2
+		// loop:
+		//	MOVV	R0, (Widthptr)r1
+		//	ADDV	$Widthptr, r1
+		//	BNE		r1, r2, loop
+		p = appendpp(p, mips.AADDV, obj.TYPE_CONST, 0, 8+frame+lo-8, obj.TYPE_REG, mips.REGRT1, 0)
+		p.Reg = mips.REGSP
+		p = appendpp(p, mips.AADDV, obj.TYPE_CONST, 0, cnt, obj.TYPE_REG, mips.REGRT2, 0)
+		p.Reg = mips.REGRT1
+		p = appendpp(p, mips.AMOVV, obj.TYPE_REG, mips.REGZERO, 0, obj.TYPE_MEM, mips.REGRT1, int64(gc.Widthptr))
+		p1 := p
+		p = appendpp(p, mips.AADDV, obj.TYPE_CONST, 0, int64(gc.Widthptr), obj.TYPE_REG, mips.REGRT1, 0)
+		p = appendpp(p, mips.ABNE, obj.TYPE_REG, mips.REGRT1, 0, obj.TYPE_BRANCH, 0, 0)
+		p.Reg = mips.REGRT2
+		gc.Patch(p, p1)
+	}
+
+	return p
+}
+
+func appendpp(p *obj.Prog, as int, ftype int, freg int, foffset int64, ttype int, treg int, toffset int64) *obj.Prog {
+	q := gc.Ctxt.NewProg()
+	gc.Clearp(q)
+	q.As = int16(as)
+	q.Lineno = p.Lineno
+	q.From.Type = int16(ftype)
+	q.From.Reg = int16(freg)
+	q.From.Offset = foffset
+	q.To.Type = int16(ttype)
+	q.To.Reg = int16(treg)
+	q.To.Offset = toffset
+	q.Link = p.Link
+	p.Link = q
+	return q
+}
+
+func ginsnop() {
+	var reg gc.Node
+	gc.Nodreg(&reg, gc.Types[gc.TINT], mips.REG_R0)
+	gins(mips.ANOR, &reg, &reg)
+}
+
+var panicdiv *gc.Node
+
+/*
+ * generate division.
+ * generates one of:
+ *	res = nl / nr
+ *	res = nl % nr
+ * according to op.
+ */
+func dodiv(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+	t := nl.Type
+
+	t0 := t
+
+	if t.Width < 8 {
+		if gc.Issigned[t.Etype] {
+			t = gc.Types[gc.TINT64]
+		} else {
+			t = gc.Types[gc.TUINT64]
+		}
+	}
+
+	a := optoas(gc.ODIV, t)
+
+	var tl gc.Node
+	gc.Regalloc(&tl, t0, nil)
+	var tr gc.Node
+	gc.Regalloc(&tr, t0, nil)
+	if nl.Ullman >= nr.Ullman {
+		gc.Cgen(nl, &tl)
+		gc.Cgen(nr, &tr)
+	} else {
+		gc.Cgen(nr, &tr)
+		gc.Cgen(nl, &tl)
+	}
+
+	if t != t0 {
+		// Convert
+		tl2 := tl
+
+		tr2 := tr
+		tl.Type = t
+		tr.Type = t
+		gmove(&tl2, &tl)
+		gmove(&tr2, &tr)
+	}
+
+	// Handle divide-by-zero panic.
+	p1 := ginsbranch(mips.ABNE, nil, &tr, nil, 0)
+	if panicdiv == nil {
+		panicdiv = gc.Sysfunc("panicdivide")
+	}
+	gc.Ginscall(panicdiv, -1)
+	gc.Patch(p1, gc.Pc)
+
+	gins3(a, &tr, &tl, nil)
+	gc.Regfree(&tr)
+	if op == gc.ODIV {
+		var lo gc.Node
+		gc.Nodreg(&lo, gc.Types[gc.TUINT64], mips.REG_LO)
+		gins(mips.AMOVV, &lo, &tl)
+	} else { // remainder in REG_HI
+		var hi gc.Node
+		gc.Nodreg(&hi, gc.Types[gc.TUINT64], mips.REG_HI)
+		gins(mips.AMOVV, &hi, &tl)
+	}
+	gmove(&tl, res)
+	gc.Regfree(&tl)
+}
+
+/*
+ * generate high multiply:
+ *   res = (nl*nr) >> width
+ */
+func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
+	// largest ullman on left.
+	if nl.Ullman < nr.Ullman {
+		nl, nr = nr, nl
+	}
+
+	t := (*gc.Type)(nl.Type)
+	w := int(int(t.Width * 8))
+	var n1 gc.Node
+	gc.Cgenr(nl, &n1, res)
+	var n2 gc.Node
+	gc.Cgenr(nr, &n2, nil)
+	switch gc.Simtype[t.Etype] {
+	case gc.TINT8,
+		gc.TINT16,
+		gc.TINT32:
+		gins3(optoas(gc.OMUL, t), &n2, &n1, nil)
+		var lo gc.Node
+		gc.Nodreg(&lo, gc.Types[gc.TUINT64], mips.REG_LO)
+		gins(mips.AMOVV, &lo, &n1)
+		p := (*obj.Prog)(gins(mips.ASRAV, nil, &n1))
+		p.From.Type = obj.TYPE_CONST
+		p.From.Offset = int64(w)
+
+	case gc.TUINT8,
+		gc.TUINT16,
+		gc.TUINT32:
+		gins3(optoas(gc.OMUL, t), &n2, &n1, nil)
+		var lo gc.Node
+		gc.Nodreg(&lo, gc.Types[gc.TUINT64], mips.REG_LO)
+		gins(mips.AMOVV, &lo, &n1)
+		p := (*obj.Prog)(gins(mips.ASRLV, nil, &n1))
+		p.From.Type = obj.TYPE_CONST
+		p.From.Offset = int64(w)
+
+	case gc.TINT64,
+		gc.TUINT64:
+		if gc.Issigned[t.Etype] {
+			gins3(mips.AMULV, &n2, &n1, nil)
+		} else {
+			gins3(mips.AMULVU, &n2, &n1, nil)
+		}
+		var hi gc.Node
+		gc.Nodreg(&hi, gc.Types[gc.TUINT64], mips.REG_HI)
+		gins(mips.AMOVV, &hi, &n1)
+
+	default:
+		gc.Fatalf("cgen_hmul %v", t)
+	}
+
+	gc.Cgen(&n1, res)
+	gc.Regfree(&n1)
+	gc.Regfree(&n2)
+}
+
+/*
+ * generate shift according to op, one of:
+ *	res = nl << nr
+ *	res = nl >> nr
+ */
+func cgen_shift(op gc.Op, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+	a := int(optoas(op, nl.Type))
+
+	if nr.Op == gc.OLITERAL {
+		var n1 gc.Node
+		gc.Regalloc(&n1, nl.Type, res)
+		gc.Cgen(nl, &n1)
+		sc := uint64(nr.Int())
+		if sc >= uint64(nl.Type.Width*8) {
+			// large shift gets 2 shifts by width-1
+			var n3 gc.Node
+			gc.Nodconst(&n3, gc.Types[gc.TUINT32], nl.Type.Width*8-1)
+
+			gins(a, &n3, &n1)
+			gins(a, &n3, &n1)
+		} else {
+			gins(a, nr, &n1)
+		}
+		gmove(&n1, res)
+		gc.Regfree(&n1)
+		return
+	}
+
+	if nl.Ullman >= gc.UINF {
+		var n4 gc.Node
+		gc.Tempname(&n4, nl.Type)
+		gc.Cgen(nl, &n4)
+		nl = &n4
+	}
+
+	if nr.Ullman >= gc.UINF {
+		var n5 gc.Node
+		gc.Tempname(&n5, nr.Type)
+		gc.Cgen(nr, &n5)
+		nr = &n5
+	}
+
+	// Allow either uint32 or uint64 as shift type,
+	// to avoid unnecessary conversion from uint32 to uint64
+	// just to do the comparison.
+	tcount := gc.Types[gc.Simtype[nr.Type.Etype]]
+
+	if tcount.Etype < gc.TUINT32 {
+		tcount = gc.Types[gc.TUINT32]
+	}
+
+	var n1 gc.Node
+	gc.Regalloc(&n1, nr.Type, nil) // to hold the shift type in CX
+	var n3 gc.Node
+	gc.Regalloc(&n3, tcount, &n1) // to clear high bits of CX
+
+	var n2 gc.Node
+	gc.Regalloc(&n2, nl.Type, res)
+
+	if nl.Ullman >= nr.Ullman {
+		gc.Cgen(nl, &n2)
+		gc.Cgen(nr, &n1)
+		gmove(&n1, &n3)
+	} else {
+		gc.Cgen(nr, &n1)
+		gmove(&n1, &n3)
+		gc.Cgen(nl, &n2)
+	}
+
+	gc.Regfree(&n3)
+
+	// test and fix up large shifts
+	if !bounded {
+		var rtmp gc.Node
+		gc.Nodreg(&rtmp, tcount, mips.REGTMP)
+		gc.Nodconst(&n3, tcount, nl.Type.Width*8)
+		gins3(mips.ASGTU, &n3, &n1, &rtmp)
+		p1 := ginsbranch(mips.ABNE, nil, &rtmp, nil, 0)
+		if op == gc.ORSH && gc.Issigned[nl.Type.Etype] {
+			gc.Nodconst(&n3, gc.Types[gc.TUINT32], nl.Type.Width*8-1)
+			gins(a, &n3, &n2)
+		} else {
+			gc.Nodconst(&n3, nl.Type, 0)
+			gmove(&n3, &n2)
+		}
+
+		gc.Patch(p1, gc.Pc)
+	}
+
+	gins(a, &n1, &n2)
+
+	gmove(&n2, res)
+
+	gc.Regfree(&n1)
+	gc.Regfree(&n2)
+}
+
+func clearfat(nl *gc.Node) {
+	/* clear a fat object */
+	if gc.Debug['g'] != 0 {
+		fmt.Printf("clearfat %v (%v, size: %d)\n", nl, nl.Type, nl.Type.Width)
+	}
+
+	w := uint64(uint64(nl.Type.Width))
+
+	// Avoid taking the address for simple enough types.
+	if gc.Componentgen(nil, nl) {
+		return
+	}
+
+	c := uint64(w % 8) // bytes
+	q := uint64(w / 8) // dwords
+
+	if gc.Reginuse(mips.REGRT1) {
+		gc.Fatalf("%v in use during clearfat", obj.Rconv(mips.REGRT1))
+	}
+
+	var r0 gc.Node
+	gc.Nodreg(&r0, gc.Types[gc.TUINT64], mips.REGZERO)
+	var dst gc.Node
+	gc.Nodreg(&dst, gc.Types[gc.Tptr], mips.REGRT1)
+	gc.Regrealloc(&dst)
+	gc.Agen(nl, &dst)
+
+	var boff uint64
+	if q > 128 {
+		p := gins(mips.ASUBV, nil, &dst)
+		p.From.Type = obj.TYPE_CONST
+		p.From.Offset = 8
+
+		var end gc.Node
+		gc.Regalloc(&end, gc.Types[gc.Tptr], nil)
+		p = gins(mips.AMOVV, &dst, &end)
+		p.From.Type = obj.TYPE_ADDR
+		p.From.Offset = int64(q * 8)
+
+		p = gins(mips.AMOVV, &r0, &dst)
+		p.To.Type = obj.TYPE_MEM
+		p.To.Offset = 8
+		pl := (*obj.Prog)(p)
+
+		p = gins(mips.AADDV, nil, &dst)
+		p.From.Type = obj.TYPE_CONST
+		p.From.Offset = 8
+
+		gc.Patch(ginsbranch(mips.ABNE, nil, &dst, &end, 0), pl)
+
+		gc.Regfree(&end)
+
+		// The loop leaves R1 on the last zeroed dword
+		boff = 8
+		// TODO(dfc): https://golang.org/issue/12108
+		// If DUFFZERO is used inside a tail call (see genwrapper) it will
+		// overwrite the link register.
+	} else if false && q >= 4 {
+		p := gins(mips.ASUBV, nil, &dst)
+		p.From.Type = obj.TYPE_CONST
+		p.From.Offset = 8
+		f := (*gc.Node)(gc.Sysfunc("duffzero"))
+		p = gins(obj.ADUFFZERO, nil, f)
+		gc.Afunclit(&p.To, f)
+
+		// 8 and 128 = magic constants: see ../../runtime/asm_mips64x.s
+		p.To.Offset = int64(8 * (128 - q))
+
+		// duffzero leaves R1 on the last zeroed dword
+		boff = 8
+	} else {
+		var p *obj.Prog
+		for t := uint64(0); t < q; t++ {
+			p = gins(mips.AMOVV, &r0, &dst)
+			p.To.Type = obj.TYPE_MEM
+			p.To.Offset = int64(8 * t)
+		}
+
+		boff = 8 * q
+	}
+
+	var p *obj.Prog
+	for t := uint64(0); t < c; t++ {
+		p = gins(mips.AMOVB, &r0, &dst)
+		p.To.Type = obj.TYPE_MEM
+		p.To.Offset = int64(t + boff)
+	}
+
+	gc.Regfree(&dst)
+}
+
+// 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
+
+	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)
+		}
+		if p.As != obj.ACHECKNIL {
+			continue
+		}
+		if gc.Debug_checknil != 0 && p.Lineno > 1 { // p->lineno==1 in generated wrappers
+			gc.Warnl(int(p.Lineno), "generated nil check")
+		}
+		if p.From.Type != obj.TYPE_REG {
+			gc.Fatalf("invalid nil check %v\n", p)
+		}
+
+		// check is
+		//	BNE arg, 2(PC)
+		//	MOVV R0, 0(R0)
+		p1 = gc.Ctxt.NewProg()
+		gc.Clearp(p1)
+		p1.Link = p.Link
+		p.Link = p1
+		p1.Lineno = p.Lineno
+		p1.Pc = 9999
+
+		p.As = mips.ABNE
+		p.To.Type = obj.TYPE_BRANCH
+		p.To.Val = p1.Link
+
+		// crash by write to memory address 0.
+		p1.As = mips.AMOVV
+		p1.From.Type = obj.TYPE_REG
+		p1.From.Reg = mips.REGZERO
+		p1.To.Type = obj.TYPE_MEM
+		p1.To.Reg = mips.REGZERO
+		p1.To.Offset = 0
+	}
+}
+
+// res = runtime.getg()
+func getg(res *gc.Node) {
+	var n1 gc.Node
+	gc.Nodreg(&n1, res.Type, mips.REGG)
+	gmove(&n1, res)
+}
diff --git a/src/cmd/compile/internal/mips64/gsubr.go b/src/cmd/compile/internal/mips64/gsubr.go
new file mode 100644
index 0000000..d2065d9
--- /dev/null
+++ b/src/cmd/compile/internal/mips64/gsubr.go
@@ -0,0 +1,1063 @@
+// Derived from Inferno utils/6c/txt.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6c/txt.c
+//
+//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//	Portions Copyright © 1995-1997 C H Forsyth (forsyth at terzarima.net)
+//	Portions Copyright © 1997-1999 Vita Nuova Limited
+//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+//	Portions Copyright © 2004,2006 Bruce Ellis
+//	Portions Copyright © 2005-2007 C H Forsyth (forsyth at terzarima.net)
+//	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package mips64
+
+import (
+	"cmd/compile/internal/big"
+	"cmd/compile/internal/gc"
+	"cmd/internal/obj"
+	"cmd/internal/obj/mips"
+	"fmt"
+)
+
+var resvd = []int{
+	mips.REGZERO,
+	mips.REGSP,   // reserved for SP
+	mips.REGLINK, // reserved for link
+	mips.REGG,
+	mips.REGTMP,
+	mips.REG_R26, // kernel
+	mips.REG_R27, // kernel
+	mips.FREGZERO,
+	mips.FREGHALF,
+	mips.FREGONE,
+	mips.FREGTWO,
+}
+
+/*
+ * generate
+ *	as $c, n
+ */
+func ginscon(as int, c int64, n2 *gc.Node) {
+	var n1 gc.Node
+
+	gc.Nodconst(&n1, gc.Types[gc.TINT64], c)
+
+	if as != mips.AMOVV && (c < -mips.BIG || c > mips.BIG) || n2.Op != gc.OREGISTER || as == mips.AMUL || as == mips.AMULU || as == mips.AMULV || as == mips.AMULVU {
+		// cannot have more than 16-bit of immediate in ADD, etc.
+		// instead, MOV into register first.
+		var ntmp gc.Node
+		gc.Regalloc(&ntmp, gc.Types[gc.TINT64], nil)
+
+		rawgins(mips.AMOVV, &n1, &ntmp)
+		rawgins(as, &ntmp, n2)
+		gc.Regfree(&ntmp)
+		return
+	}
+
+	rawgins(as, &n1, n2)
+}
+
+// generate branch
+// n1, n2 are registers
+func ginsbranch(as int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+	p := gc.Gbranch(as, t, likely)
+	gc.Naddr(&p.From, n1)
+	if n2 != nil {
+		p.Reg = n2.Reg
+	}
+	return p
+}
+
+func ginscmp(op gc.Op, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+	if !gc.Isfloat[t.Etype] && (op == gc.OLT || op == gc.OGE) {
+		// swap nodes to fit SGT instruction
+		n1, n2 = n2, n1
+	}
+	if gc.Isfloat[t.Etype] && (op == gc.OLT || op == gc.OLE) {
+		// swap nodes to fit CMPGT, CMPGE instructions and reverse relation
+		n1, n2 = n2, n1
+		if op == gc.OLT {
+			op = gc.OGT
+		} else {
+			op = gc.OGE
+		}
+	}
+
+	var r1, r2, g1, g2 gc.Node
+	gc.Regalloc(&r1, t, n1)
+	gc.Regalloc(&g1, n1.Type, &r1)
+	gc.Cgen(n1, &g1)
+	gmove(&g1, &r1)
+
+	gc.Regalloc(&r2, t, n2)
+	gc.Regalloc(&g2, n1.Type, &r2)
+	gc.Cgen(n2, &g2)
+	gmove(&g2, &r2)
+
+	var p *obj.Prog
+	var ntmp gc.Node
+	gc.Nodreg(&ntmp, gc.Types[gc.TINT], mips.REGTMP)
+
+	switch gc.Simtype[t.Etype] {
+	case gc.TINT8,
+		gc.TINT16,
+		gc.TINT32,
+		gc.TINT64:
+		if op == gc.OEQ || op == gc.ONE {
+			p = ginsbranch(optoas(op, t), nil, &r1, &r2, likely)
+		} else {
+			gins3(mips.ASGT, &r1, &r2, &ntmp)
+
+			p = ginsbranch(optoas(op, t), nil, &ntmp, nil, likely)
+		}
+
+	case gc.TBOOL,
+		gc.TUINT8,
+		gc.TUINT16,
+		gc.TUINT32,
+		gc.TUINT64,
+		gc.TPTR32,
+		gc.TPTR64:
+		if op == gc.OEQ || op == gc.ONE {
+			p = ginsbranch(optoas(op, t), nil, &r1, &r2, likely)
+		} else {
+			gins3(mips.ASGTU, &r1, &r2, &ntmp)
+
+			p = ginsbranch(optoas(op, t), nil, &ntmp, nil, likely)
+		}
+
+	case gc.TFLOAT32:
+		switch op {
+		default:
+			gc.Fatalf("ginscmp: no entry for op=%v type=%v", gc.Oconv(int(op), 0), t)
+
+		case gc.OEQ,
+			gc.ONE:
+			gins3(mips.ACMPEQF, &r1, &r2, nil)
+
+		case gc.OGE:
+			gins3(mips.ACMPGEF, &r1, &r2, nil)
+
+		case gc.OGT:
+			gins3(mips.ACMPGTF, &r1, &r2, nil)
+		}
+		p = gc.Gbranch(optoas(op, t), nil, likely)
+
+	case gc.TFLOAT64:
+		switch op {
+		default:
+			gc.Fatalf("ginscmp: no entry for op=%v type=%v", gc.Oconv(int(op), 0), t)
+
+		case gc.OEQ,
+			gc.ONE:
+			gins3(mips.ACMPEQD, &r1, &r2, nil)
+
+		case gc.OGE:
+			gins3(mips.ACMPGED, &r1, &r2, nil)
+
+		case gc.OGT:
+			gins3(mips.ACMPGTD, &r1, &r2, nil)
+		}
+		p = gc.Gbranch(optoas(op, t), nil, likely)
+	}
+
+	gc.Regfree(&g2)
+	gc.Regfree(&r2)
+	gc.Regfree(&g1)
+	gc.Regfree(&r1)
+
+	return p
+}
+
+// set up nodes representing 2^63
+var (
+	bigi         gc.Node
+	bigf         gc.Node
+	bignodes_did bool
+)
+
+func bignodes() {
+	if bignodes_did {
+		return
+	}
+	bignodes_did = true
+
+	var i big.Int
+	i.SetInt64(1)
+	i.Lsh(&i, 63)
+
+	gc.Nodconst(&bigi, gc.Types[gc.TUINT64], 0)
+	bigi.SetBigInt(&i)
+
+	bigi.Convconst(&bigf, gc.Types[gc.TFLOAT64])
+}
+
+/*
+ * generate move:
+ *	t = f
+ * hard part is conversions.
+ */
+func gmove(f *gc.Node, t *gc.Node) {
+	if gc.Debug['M'] != 0 {
+		fmt.Printf("gmove %v -> %v\n", gc.Nconv(f, obj.FmtLong), gc.Nconv(t, obj.FmtLong))
+	}
+
+	ft := int(gc.Simsimtype(f.Type))
+	tt := int(gc.Simsimtype(t.Type))
+	cvt := (*gc.Type)(t.Type)
+
+	if gc.Iscomplex[ft] || gc.Iscomplex[tt] {
+		gc.Complexmove(f, t)
+		return
+	}
+
+	// cannot have two memory operands
+	var r2 gc.Node
+	var r1 gc.Node
+	var a int
+	if gc.Ismem(f) && gc.Ismem(t) {
+		goto hard
+	}
+
+	// convert constant to desired type
+	if f.Op == gc.OLITERAL {
+		var con gc.Node
+		switch tt {
+		default:
+			f.Convconst(&con, t.Type)
+
+		case gc.TINT32,
+			gc.TINT16,
+			gc.TINT8:
+			var con gc.Node
+			f.Convconst(&con, gc.Types[gc.TINT64])
+			var r1 gc.Node
+			gc.Regalloc(&r1, con.Type, t)
+			gins(mips.AMOVV, &con, &r1)
+			gmove(&r1, t)
+			gc.Regfree(&r1)
+			return
+
+		case gc.TUINT32,
+			gc.TUINT16,
+			gc.TUINT8:
+			var con gc.Node
+			f.Convconst(&con, gc.Types[gc.TUINT64])
+			var r1 gc.Node
+			gc.Regalloc(&r1, con.Type, t)
+			gins(mips.AMOVV, &con, &r1)
+			gmove(&r1, t)
+			gc.Regfree(&r1)
+			return
+		}
+
+		f = &con
+		ft = tt // so big switch will choose a simple mov
+
+		// constants can't move directly to memory.
+		if gc.Ismem(t) {
+			goto hard
+		}
+	}
+
+	// value -> value copy, first operand in memory.
+	// any floating point operand requires register
+	// src, so goto hard to copy to register first.
+	if gc.Ismem(f) && ft != tt && (gc.Isfloat[ft] || gc.Isfloat[tt]) {
+		cvt = gc.Types[ft]
+		goto hard
+	}
+
+	// value -> value copy, only one memory operand.
+	// figure out the instruction to use.
+	// break out of switch for one-instruction gins.
+	// goto rdst for "destination must be register".
+	// goto hard for "convert to cvt type first".
+	// otherwise handle and return.
+
+	switch uint32(ft)<<16 | uint32(tt) {
+	default:
+		gc.Fatalf("gmove %v -> %v", gc.Tconv(f.Type, obj.FmtLong), gc.Tconv(t.Type, obj.FmtLong))
+
+		/*
+		 * integer copy and truncate
+		 */
+	case gc.TINT8<<16 | gc.TINT8, // same size
+		gc.TUINT8<<16 | gc.TINT8,
+		gc.TINT16<<16 | gc.TINT8, // truncate
+		gc.TUINT16<<16 | gc.TINT8,
+		gc.TINT32<<16 | gc.TINT8,
+		gc.TUINT32<<16 | gc.TINT8,
+		gc.TINT64<<16 | gc.TINT8,
+		gc.TUINT64<<16 | gc.TINT8:
+		a = mips.AMOVB
+
+	case gc.TINT8<<16 | gc.TUINT8, // same size
+		gc.TUINT8<<16 | gc.TUINT8,
+		gc.TINT16<<16 | gc.TUINT8, // truncate
+		gc.TUINT16<<16 | gc.TUINT8,
+		gc.TINT32<<16 | gc.TUINT8,
+		gc.TUINT32<<16 | gc.TUINT8,
+		gc.TINT64<<16 | gc.TUINT8,
+		gc.TUINT64<<16 | gc.TUINT8:
+		a = mips.AMOVBU
+
+	case gc.TINT16<<16 | gc.TINT16, // same size
+		gc.TUINT16<<16 | gc.TINT16,
+		gc.TINT32<<16 | gc.TINT16, // truncate
+		gc.TUINT32<<16 | gc.TINT16,
+		gc.TINT64<<16 | gc.TINT16,
+		gc.TUINT64<<16 | gc.TINT16:
+		a = mips.AMOVH
+
+	case gc.TINT16<<16 | gc.TUINT16, // same size
+		gc.TUINT16<<16 | gc.TUINT16,
+		gc.TINT32<<16 | gc.TUINT16, // truncate
+		gc.TUINT32<<16 | gc.TUINT16,
+		gc.TINT64<<16 | gc.TUINT16,
+		gc.TUINT64<<16 | gc.TUINT16:
+		a = mips.AMOVHU
+
+	case gc.TINT32<<16 | gc.TINT32, // same size
+		gc.TUINT32<<16 | gc.TINT32,
+		gc.TINT64<<16 | gc.TINT32, // truncate
+		gc.TUINT64<<16 | gc.TINT32:
+		a = mips.AMOVW
+
+	case gc.TINT32<<16 | gc.TUINT32, // same size
+		gc.TUINT32<<16 | gc.TUINT32,
+		gc.TINT64<<16 | gc.TUINT32, // truncate
+		gc.TUINT64<<16 | gc.TUINT32:
+		a = mips.AMOVWU
+
+	case gc.TINT64<<16 | gc.TINT64, // same size
+		gc.TINT64<<16 | gc.TUINT64,
+		gc.TUINT64<<16 | gc.TINT64,
+		gc.TUINT64<<16 | gc.TUINT64:
+		a = mips.AMOVV
+
+		/*
+		 * integer up-conversions
+		 */
+	case gc.TINT8<<16 | gc.TINT16, // sign extend int8
+		gc.TINT8<<16 | gc.TUINT16,
+		gc.TINT8<<16 | gc.TINT32,
+		gc.TINT8<<16 | gc.TUINT32,
+		gc.TINT8<<16 | gc.TINT64,
+		gc.TINT8<<16 | gc.TUINT64:
+		a = mips.AMOVB
+
+		goto rdst
+
+	case gc.TUINT8<<16 | gc.TINT16, // zero extend uint8
+		gc.TUINT8<<16 | gc.TUINT16,
+		gc.TUINT8<<16 | gc.TINT32,
+		gc.TUINT8<<16 | gc.TUINT32,
+		gc.TUINT8<<16 | gc.TINT64,
+		gc.TUINT8<<16 | gc.TUINT64:
+		a = mips.AMOVBU
+
+		goto rdst
+
+	case gc.TINT16<<16 | gc.TINT32, // sign extend int16
+		gc.TINT16<<16 | gc.TUINT32,
+		gc.TINT16<<16 | gc.TINT64,
+		gc.TINT16<<16 | gc.TUINT64:
+		a = mips.AMOVH
+
+		goto rdst
+
+	case gc.TUINT16<<16 | gc.TINT32, // zero extend uint16
+		gc.TUINT16<<16 | gc.TUINT32,
+		gc.TUINT16<<16 | gc.TINT64,
+		gc.TUINT16<<16 | gc.TUINT64:
+		a = mips.AMOVHU
+
+		goto rdst
+
+	case gc.TINT32<<16 | gc.TINT64, // sign extend int32
+		gc.TINT32<<16 | gc.TUINT64:
+		a = mips.AMOVW
+
+		goto rdst
+
+	case gc.TUINT32<<16 | gc.TINT64, // zero extend uint32
+		gc.TUINT32<<16 | gc.TUINT64:
+		a = mips.AMOVWU
+
+		goto rdst
+
+		//warn("gmove: convert float to int not implemented: %N -> %N\n", f, t);
+	//return;
+	// algorithm is:
+	//	if small enough, use native float64 -> int64 conversion.
+	//	otherwise, subtract 2^63, convert, and add it back.
+	/*
+	* float to integer
+	 */
+	case gc.TFLOAT32<<16 | gc.TINT32,
+		gc.TFLOAT64<<16 | gc.TINT32,
+		gc.TFLOAT32<<16 | gc.TINT64,
+		gc.TFLOAT64<<16 | gc.TINT64,
+		gc.TFLOAT32<<16 | gc.TINT16,
+		gc.TFLOAT32<<16 | gc.TINT8,
+		gc.TFLOAT32<<16 | gc.TUINT16,
+		gc.TFLOAT32<<16 | gc.TUINT8,
+		gc.TFLOAT64<<16 | gc.TINT16,
+		gc.TFLOAT64<<16 | gc.TINT8,
+		gc.TFLOAT64<<16 | gc.TUINT16,
+		gc.TFLOAT64<<16 | gc.TUINT8,
+		gc.TFLOAT32<<16 | gc.TUINT32,
+		gc.TFLOAT64<<16 | gc.TUINT32,
+		gc.TFLOAT32<<16 | gc.TUINT64,
+		gc.TFLOAT64<<16 | gc.TUINT64:
+		bignodes()
+
+		gc.Regalloc(&r1, gc.Types[gc.TFLOAT64], nil)
+		gmove(f, &r1)
+		if tt == gc.TUINT64 {
+			gc.Regalloc(&r2, gc.Types[gc.TFLOAT64], nil)
+			gmove(&bigf, &r2)
+			gins3(mips.ACMPGED, &r1, &r2, nil)
+			p1 := gc.Gbranch(mips.ABFPF, nil, 0)
+			gins(mips.ASUBD, &r2, &r1)
+			gc.Patch(p1, gc.Pc)
+			gc.Regfree(&r2)
+		}
+
+		gc.Regalloc(&r2, gc.Types[gc.TINT64], t)
+		gins(mips.ATRUNCDV, &r1, &r1)
+		gins(mips.AMOVV, &r1, &r2)
+		gc.Regfree(&r1)
+
+		if tt == gc.TUINT64 {
+			p1 := gc.Gbranch(mips.ABFPF, nil, 0) // use FCR0 here again
+			gc.Nodreg(&r1, gc.Types[gc.TINT64], mips.REGTMP)
+			gmove(&bigi, &r1)
+			gins(mips.AADDVU, &r1, &r2)
+			gc.Patch(p1, gc.Pc)
+		}
+
+		gmove(&r2, t)
+		gc.Regfree(&r2)
+		return
+
+		//warn("gmove: convert int to float not implemented: %N -> %N\n", f, t);
+	//return;
+	// algorithm is:
+	//	if small enough, use native int64 -> float64 conversion.
+	//	otherwise, halve (rounding to odd?), convert, and double.
+	/*
+	 * integer to float
+	 */
+	case gc.TINT32<<16 | gc.TFLOAT32,
+		gc.TINT32<<16 | gc.TFLOAT64,
+		gc.TINT64<<16 | gc.TFLOAT32,
+		gc.TINT64<<16 | gc.TFLOAT64,
+		gc.TINT16<<16 | gc.TFLOAT32,
+		gc.TINT16<<16 | gc.TFLOAT64,
+		gc.TINT8<<16 | gc.TFLOAT32,
+		gc.TINT8<<16 | gc.TFLOAT64,
+		gc.TUINT16<<16 | gc.TFLOAT32,
+		gc.TUINT16<<16 | gc.TFLOAT64,
+		gc.TUINT8<<16 | gc.TFLOAT32,
+		gc.TUINT8<<16 | gc.TFLOAT64,
+		gc.TUINT32<<16 | gc.TFLOAT32,
+		gc.TUINT32<<16 | gc.TFLOAT64,
+		gc.TUINT64<<16 | gc.TFLOAT32,
+		gc.TUINT64<<16 | gc.TFLOAT64:
+		bignodes()
+
+		var rtmp gc.Node
+		gc.Regalloc(&r1, gc.Types[gc.TINT64], nil)
+		gmove(f, &r1)
+		if ft == gc.TUINT64 {
+			gc.Nodreg(&rtmp, gc.Types[gc.TUINT64], mips.REGTMP)
+			gmove(&bigi, &rtmp)
+			gins(mips.AAND, &r1, &rtmp)
+			p1 := ginsbranch(mips.ABEQ, nil, &rtmp, nil, 0)
+			p2 := gins(mips.ASRLV, nil, &r1)
+			p2.From.Type = obj.TYPE_CONST
+			p2.From.Offset = 1
+			gc.Patch(p1, gc.Pc)
+		}
+
+		gc.Regalloc(&r2, gc.Types[gc.TFLOAT64], t)
+		gins(mips.AMOVV, &r1, &r2)
+		gins(mips.AMOVVD, &r2, &r2)
+		gc.Regfree(&r1)
+
+		if ft == gc.TUINT64 {
+			p1 := ginsbranch(mips.ABEQ, nil, &rtmp, nil, 0)
+			gc.Nodreg(&r1, gc.Types[gc.TFLOAT64], mips.FREGTWO)
+			gins(mips.AMULD, &r1, &r2)
+			gc.Patch(p1, gc.Pc)
+		}
+
+		gmove(&r2, t)
+		gc.Regfree(&r2)
+		return
+
+		/*
+		 * float to float
+		 */
+	case gc.TFLOAT32<<16 | gc.TFLOAT32:
+		a = mips.AMOVF
+
+	case gc.TFLOAT64<<16 | gc.TFLOAT64:
+		a = mips.AMOVD
+
+	case gc.TFLOAT32<<16 | gc.TFLOAT64:
+		a = mips.AMOVFD
+		goto rdst
+
+	case gc.TFLOAT64<<16 | gc.TFLOAT32:
+		a = mips.AMOVDF
+		goto rdst
+	}
+
+	gins(a, f, t)
+	return
+
+	// requires register destination
+rdst:
+	{
+		gc.Regalloc(&r1, t.Type, t)
+
+		gins(a, f, &r1)
+		gmove(&r1, t)
+		gc.Regfree(&r1)
+		return
+	}
+
+	// requires register intermediate
+hard:
+	gc.Regalloc(&r1, cvt, t)
+
+	gmove(f, &r1)
+	gmove(&r1, t)
+	gc.Regfree(&r1)
+	return
+}
+
+// gins is called by the front end.
+// 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 := f.IntLiteral(); ok {
+			ginscon(as, x, t)
+			return nil // caller must not use
+		}
+	}
+	return rawgins(as, f, t)
+}
+
+/*
+ * generate one instruction:
+ *	as f, r, t
+ * r must be register, if not nil
+ */
+func gins3(as int, f, r, t *gc.Node) *obj.Prog {
+	p := rawgins(as, f, t)
+	if r != nil {
+		p.Reg = r.Reg
+	}
+	return p
+}
+
+/*
+ * generate one instruction:
+ *	as f, t
+ */
+func rawgins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
+	// TODO(austin): Add self-move test like in 6g (but be careful
+	// of truncation moves)
+
+	p := gc.Prog(as)
+	gc.Naddr(&p.From, f)
+	gc.Naddr(&p.To, t)
+
+	switch as {
+	case obj.ACALL:
+		if p.To.Type == obj.TYPE_REG {
+			// Allow front end to emit CALL REG, and rewrite into CALL (REG).
+			p.From = obj.Addr{}
+			p.To.Type = obj.TYPE_MEM
+			p.To.Offset = 0
+
+			if gc.Debug['g'] != 0 {
+				fmt.Printf("%v\n", p)
+			}
+
+			return p
+		}
+
+	// Bad things the front end has done to us. Crash to find call stack.
+	case mips.AAND:
+		if p.From.Type == obj.TYPE_CONST {
+			gc.Debug['h'] = 1
+			gc.Fatalf("bad inst: %v", p)
+		}
+	case mips.ASGT, mips.ASGTU:
+		if p.From.Type == obj.TYPE_MEM || p.To.Type == obj.TYPE_MEM {
+			gc.Debug['h'] = 1
+			gc.Fatalf("bad inst: %v", p)
+		}
+
+	// Special cases
+	case mips.AMUL, mips.AMULU, mips.AMULV, mips.AMULVU:
+		if p.From.Type == obj.TYPE_CONST {
+			gc.Debug['h'] = 1
+			gc.Fatalf("bad inst: %v", p)
+		}
+
+		pp := gc.Prog(mips.AMOVV)
+		pp.From.Type = obj.TYPE_REG
+		pp.From.Reg = mips.REG_LO
+		pp.To = p.To
+
+		p.Reg = p.To.Reg
+		p.To = obj.Addr{}
+
+	case mips.ASUBVU:
+		// unary
+		if f == nil {
+			p.From = p.To
+			p.Reg = mips.REGZERO
+		}
+	}
+
+	if gc.Debug['g'] != 0 {
+		fmt.Printf("%v\n", p)
+	}
+
+	w := int32(0)
+	switch as {
+	case mips.AMOVB,
+		mips.AMOVBU:
+		w = 1
+
+	case mips.AMOVH,
+		mips.AMOVHU:
+		w = 2
+
+	case mips.AMOVW,
+		mips.AMOVWU:
+		w = 4
+
+	case mips.AMOVV:
+		if p.From.Type == obj.TYPE_CONST || p.From.Type == obj.TYPE_ADDR {
+			break
+		}
+		w = 8
+	}
+
+	if w != 0 && ((f != nil && p.From.Width < int64(w)) || (t != nil && p.To.Type != obj.TYPE_REG && p.To.Width > int64(w))) {
+		gc.Dump("f", f)
+		gc.Dump("t", t)
+		gc.Fatalf("bad width: %v (%d, %d)\n", p, p.From.Width, p.To.Width)
+	}
+
+	return p
+}
+
+/*
+ * return Axxx for Oxxx on type t.
+ */
+func optoas(op gc.Op, t *gc.Type) int {
+	if t == nil {
+		gc.Fatalf("optoas: t is nil")
+	}
+
+	// avoid constant conversions in switches below
+	const (
+		OMINUS_ = uint32(gc.OMINUS) << 16
+		OLSH_   = uint32(gc.OLSH) << 16
+		ORSH_   = uint32(gc.ORSH) << 16
+		OADD_   = uint32(gc.OADD) << 16
+		OSUB_   = uint32(gc.OSUB) << 16
+		OMUL_   = uint32(gc.OMUL) << 16
+		ODIV_   = uint32(gc.ODIV) << 16
+		OOR_    = uint32(gc.OOR) << 16
+		OAND_   = uint32(gc.OAND) << 16
+		OXOR_   = uint32(gc.OXOR) << 16
+		OEQ_    = uint32(gc.OEQ) << 16
+		ONE_    = uint32(gc.ONE) << 16
+		OLT_    = uint32(gc.OLT) << 16
+		OLE_    = uint32(gc.OLE) << 16
+		OGE_    = uint32(gc.OGE) << 16
+		OGT_    = uint32(gc.OGT) << 16
+		OCMP_   = uint32(gc.OCMP) << 16
+		OAS_    = uint32(gc.OAS) << 16
+		OHMUL_  = uint32(gc.OHMUL) << 16
+	)
+
+	a := int(obj.AXXX)
+	switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) {
+	default:
+		gc.Fatalf("optoas: no entry for op=%v type=%v", gc.Oconv(int(op), 0), t)
+
+	case OEQ_ | gc.TBOOL,
+		OEQ_ | gc.TINT8,
+		OEQ_ | gc.TUINT8,
+		OEQ_ | gc.TINT16,
+		OEQ_ | gc.TUINT16,
+		OEQ_ | gc.TINT32,
+		OEQ_ | gc.TUINT32,
+		OEQ_ | gc.TINT64,
+		OEQ_ | gc.TUINT64,
+		OEQ_ | gc.TPTR32,
+		OEQ_ | gc.TPTR64:
+		a = mips.ABEQ
+
+	case OEQ_ | gc.TFLOAT32, // ACMPEQF
+		OEQ_ | gc.TFLOAT64: // ACMPEQD
+		a = mips.ABFPT
+
+	case ONE_ | gc.TBOOL,
+		ONE_ | gc.TINT8,
+		ONE_ | gc.TUINT8,
+		ONE_ | gc.TINT16,
+		ONE_ | gc.TUINT16,
+		ONE_ | gc.TINT32,
+		ONE_ | gc.TUINT32,
+		ONE_ | gc.TINT64,
+		ONE_ | gc.TUINT64,
+		ONE_ | gc.TPTR32,
+		ONE_ | gc.TPTR64:
+		a = mips.ABNE
+
+	case ONE_ | gc.TFLOAT32, // ACMPEQF
+		ONE_ | gc.TFLOAT64: // ACMPEQD
+		a = mips.ABFPF
+
+	case OLT_ | gc.TINT8, // ASGT
+		OLT_ | gc.TINT16,
+		OLT_ | gc.TINT32,
+		OLT_ | gc.TINT64,
+		OLT_ | gc.TUINT8, // ASGTU
+		OLT_ | gc.TUINT16,
+		OLT_ | gc.TUINT32,
+		OLT_ | gc.TUINT64:
+		a = mips.ABNE
+
+	case OLT_ | gc.TFLOAT32, // ACMPGEF
+		OLT_ | gc.TFLOAT64: // ACMPGED
+		a = mips.ABFPT
+
+	case OLE_ | gc.TINT8, // ASGT
+		OLE_ | gc.TINT16,
+		OLE_ | gc.TINT32,
+		OLE_ | gc.TINT64,
+		OLE_ | gc.TUINT8, // ASGTU
+		OLE_ | gc.TUINT16,
+		OLE_ | gc.TUINT32,
+		OLE_ | gc.TUINT64:
+		a = mips.ABEQ
+
+	case OLE_ | gc.TFLOAT32, // ACMPGTF
+		OLE_ | gc.TFLOAT64: // ACMPGTD
+		a = mips.ABFPT
+
+	case OGT_ | gc.TINT8, // ASGT
+		OGT_ | gc.TINT16,
+		OGT_ | gc.TINT32,
+		OGT_ | gc.TINT64,
+		OGT_ | gc.TUINT8, // ASGTU
+		OGT_ | gc.TUINT16,
+		OGT_ | gc.TUINT32,
+		OGT_ | gc.TUINT64:
+		a = mips.ABNE
+
+	case OGT_ | gc.TFLOAT32, // ACMPGTF
+		OGT_ | gc.TFLOAT64: // ACMPGTD
+		a = mips.ABFPT
+
+	case OGE_ | gc.TINT8, // ASGT
+		OGE_ | gc.TINT16,
+		OGE_ | gc.TINT32,
+		OGE_ | gc.TINT64,
+		OGE_ | gc.TUINT8, // ASGTU
+		OGE_ | gc.TUINT16,
+		OGE_ | gc.TUINT32,
+		OGE_ | gc.TUINT64:
+		a = mips.ABEQ
+
+	case OGE_ | gc.TFLOAT32, // ACMPGEF
+		OGE_ | gc.TFLOAT64: // ACMPGED
+		a = mips.ABFPT
+
+	case OAS_ | gc.TBOOL,
+		OAS_ | gc.TINT8:
+		a = mips.AMOVB
+
+	case OAS_ | gc.TUINT8:
+		a = mips.AMOVBU
+
+	case OAS_ | gc.TINT16:
+		a = mips.AMOVH
+
+	case OAS_ | gc.TUINT16:
+		a = mips.AMOVHU
+
+	case OAS_ | gc.TINT32:
+		a = mips.AMOVW
+
+	case OAS_ | gc.TUINT32,
+		OAS_ | gc.TPTR32:
+		a = mips.AMOVWU
+
+	case OAS_ | gc.TINT64,
+		OAS_ | gc.TUINT64,
+		OAS_ | gc.TPTR64:
+		a = mips.AMOVV
+
+	case OAS_ | gc.TFLOAT32:
+		a = mips.AMOVF
+
+	case OAS_ | gc.TFLOAT64:
+		a = mips.AMOVD
+
+	case OADD_ | gc.TINT8,
+		OADD_ | gc.TUINT8,
+		OADD_ | gc.TINT16,
+		OADD_ | gc.TUINT16,
+		OADD_ | gc.TINT32,
+		OADD_ | gc.TUINT32,
+		OADD_ | gc.TPTR32:
+		a = mips.AADDU
+
+	case OADD_ | gc.TINT64,
+		OADD_ | gc.TUINT64,
+		OADD_ | gc.TPTR64:
+		a = mips.AADDVU
+
+	case OADD_ | gc.TFLOAT32:
+		a = mips.AADDF
+
+	case OADD_ | gc.TFLOAT64:
+		a = mips.AADDD
+
+	case OSUB_ | gc.TINT8,
+		OSUB_ | gc.TUINT8,
+		OSUB_ | gc.TINT16,
+		OSUB_ | gc.TUINT16,
+		OSUB_ | gc.TINT32,
+		OSUB_ | gc.TUINT32,
+		OSUB_ | gc.TPTR32:
+		a = mips.ASUBU
+
+	case OSUB_ | gc.TINT64,
+		OSUB_ | gc.TUINT64,
+		OSUB_ | gc.TPTR64:
+		a = mips.ASUBVU
+
+	case OSUB_ | gc.TFLOAT32:
+		a = mips.ASUBF
+
+	case OSUB_ | gc.TFLOAT64:
+		a = mips.ASUBD
+
+	case OMINUS_ | gc.TINT8,
+		OMINUS_ | gc.TUINT8,
+		OMINUS_ | gc.TINT16,
+		OMINUS_ | gc.TUINT16,
+		OMINUS_ | gc.TINT32,
+		OMINUS_ | gc.TUINT32,
+		OMINUS_ | gc.TPTR32,
+		OMINUS_ | gc.TINT64,
+		OMINUS_ | gc.TUINT64,
+		OMINUS_ | gc.TPTR64:
+		a = mips.ASUBVU
+
+	case OAND_ | gc.TINT8,
+		OAND_ | gc.TUINT8,
+		OAND_ | gc.TINT16,
+		OAND_ | gc.TUINT16,
+		OAND_ | gc.TINT32,
+		OAND_ | gc.TUINT32,
+		OAND_ | gc.TPTR32,
+		OAND_ | gc.TINT64,
+		OAND_ | gc.TUINT64,
+		OAND_ | gc.TPTR64:
+		a = mips.AAND
+
+	case OOR_ | gc.TINT8,
+		OOR_ | gc.TUINT8,
+		OOR_ | gc.TINT16,
+		OOR_ | gc.TUINT16,
+		OOR_ | gc.TINT32,
+		OOR_ | gc.TUINT32,
+		OOR_ | gc.TPTR32,
+		OOR_ | gc.TINT64,
+		OOR_ | gc.TUINT64,
+		OOR_ | gc.TPTR64:
+		a = mips.AOR
+
+	case OXOR_ | gc.TINT8,
+		OXOR_ | gc.TUINT8,
+		OXOR_ | gc.TINT16,
+		OXOR_ | gc.TUINT16,
+		OXOR_ | gc.TINT32,
+		OXOR_ | gc.TUINT32,
+		OXOR_ | gc.TPTR32,
+		OXOR_ | gc.TINT64,
+		OXOR_ | gc.TUINT64,
+		OXOR_ | gc.TPTR64:
+		a = mips.AXOR
+
+		// TODO(minux): handle rotates
+	//case CASE(OLROT, TINT8):
+	//case CASE(OLROT, TUINT8):
+	//case CASE(OLROT, TINT16):
+	//case CASE(OLROT, TUINT16):
+	//case CASE(OLROT, TINT32):
+	//case CASE(OLROT, TUINT32):
+	//case CASE(OLROT, TPTR32):
+	//case CASE(OLROT, TINT64):
+	//case CASE(OLROT, TUINT64):
+	//case CASE(OLROT, TPTR64):
+	//	a = 0//???; RLDC?
+	//	break;
+
+	case OLSH_ | gc.TINT8,
+		OLSH_ | gc.TUINT8,
+		OLSH_ | gc.TINT16,
+		OLSH_ | gc.TUINT16,
+		OLSH_ | gc.TINT32,
+		OLSH_ | gc.TUINT32,
+		OLSH_ | gc.TPTR32,
+		OLSH_ | gc.TINT64,
+		OLSH_ | gc.TUINT64,
+		OLSH_ | gc.TPTR64:
+		a = mips.ASLLV
+
+	case ORSH_ | gc.TUINT8,
+		ORSH_ | gc.TUINT16,
+		ORSH_ | gc.TUINT32,
+		ORSH_ | gc.TPTR32,
+		ORSH_ | gc.TUINT64,
+		ORSH_ | gc.TPTR64:
+		a = mips.ASRLV
+
+	case ORSH_ | gc.TINT8,
+		ORSH_ | gc.TINT16,
+		ORSH_ | gc.TINT32,
+		ORSH_ | gc.TINT64:
+		a = mips.ASRAV
+
+		// TODO(minux): handle rotates
+	//case CASE(ORROTC, TINT8):
+	//case CASE(ORROTC, TUINT8):
+	//case CASE(ORROTC, TINT16):
+	//case CASE(ORROTC, TUINT16):
+	//case CASE(ORROTC, TINT32):
+	//case CASE(ORROTC, TUINT32):
+	//case CASE(ORROTC, TINT64):
+	//case CASE(ORROTC, TUINT64):
+	//	a = 0//??? RLDC??
+	//	break;
+
+	case OHMUL_ | gc.TINT64:
+		a = mips.AMULV
+
+	case OHMUL_ | gc.TUINT64,
+		OHMUL_ | gc.TPTR64:
+		a = mips.AMULVU
+
+	case OMUL_ | gc.TINT8,
+		OMUL_ | gc.TINT16,
+		OMUL_ | gc.TINT32,
+		OMUL_ | gc.TINT64:
+		a = mips.AMULV
+
+	case OMUL_ | gc.TUINT8,
+		OMUL_ | gc.TUINT16,
+		OMUL_ | gc.TUINT32,
+		OMUL_ | gc.TPTR32,
+		OMUL_ | gc.TUINT64,
+		OMUL_ | gc.TPTR64:
+		a = mips.AMULVU
+
+	case OMUL_ | gc.TFLOAT32:
+		a = mips.AMULF
+
+	case OMUL_ | gc.TFLOAT64:
+		a = mips.AMULD
+
+	case ODIV_ | gc.TINT8,
+		ODIV_ | gc.TINT16,
+		ODIV_ | gc.TINT32,
+		ODIV_ | gc.TINT64:
+		a = mips.ADIVV
+
+	case ODIV_ | gc.TUINT8,
+		ODIV_ | gc.TUINT16,
+		ODIV_ | gc.TUINT32,
+		ODIV_ | gc.TPTR32,
+		ODIV_ | gc.TUINT64,
+		ODIV_ | gc.TPTR64:
+		a = mips.ADIVVU
+
+	case ODIV_ | gc.TFLOAT32:
+		a = mips.ADIVF
+
+	case ODIV_ | gc.TFLOAT64:
+		a = mips.ADIVD
+	}
+
+	return a
+}
+
+const (
+	ODynam   = 1 << 0
+	OAddable = 1 << 1
+)
+
+func xgen(n *gc.Node, a *gc.Node, o int) bool {
+	// TODO(minux)
+
+	return -1 != 0 /*TypeKind(100016)*/
+}
+
+func sudoclean() {
+	return
+}
+
+/*
+ * 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(minux)
+
+	*a = obj.Addr{}
+	return false
+}
diff --git a/src/cmd/compile/internal/mips64/peep.go b/src/cmd/compile/internal/mips64/peep.go
new file mode 100644
index 0000000..f97be60
--- /dev/null
+++ b/src/cmd/compile/internal/mips64/peep.go
@@ -0,0 +1,788 @@
+// Derived from Inferno utils/6c/peep.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6c/peep.c
+//
+//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//	Portions Copyright © 1995-1997 C H Forsyth (forsyth at terzarima.net)
+//	Portions Copyright © 1997-1999 Vita Nuova Limited
+//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+//	Portions Copyright © 2004,2006 Bruce Ellis
+//	Portions Copyright © 2005-2007 C H Forsyth (forsyth at terzarima.net)
+//	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package mips64
+
+import (
+	"cmd/compile/internal/gc"
+	"cmd/internal/obj"
+	"cmd/internal/obj/mips"
+	"fmt"
+)
+
+var gactive uint32
+
+func peep(firstp *obj.Prog) {
+	g := (*gc.Graph)(gc.Flowstart(firstp, nil))
+	if g == nil {
+		return
+	}
+	gactive = 0
+
+	var p *obj.Prog
+	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
+
+		// 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 == mips.AMOVV || p.As == mips.AMOVF || p.As == mips.AMOVD {
+			if regtyp(&p.To) {
+				// Try to eliminate reg->reg moves
+				if regtyp(&p.From) {
+					if isfreg(&p.From) == isfreg(&p.To) {
+						if 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 && !isfreg(&p.To) {
+						p.From.Type = obj.TYPE_REG
+						p.From.Reg = mips.REGZERO
+						if copyprop(r) {
+							excise(r)
+							t++
+						} else if subprop(r) && copyprop(r) {
+							excise(r)
+							t++
+						}
+					}
+				}
+			}
+		}
+	}
+
+	if t != 0 {
+		goto loop1
+	}
+
+	/*
+	 * 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
+		switch p.As {
+		default:
+			continue
+
+		case mips.AMOVH,
+			mips.AMOVHU,
+			mips.AMOVB,
+			mips.AMOVBU,
+			mips.AMOVW,
+			mips.AMOVWU:
+			if p.To.Type != obj.TYPE_REG {
+				continue
+			}
+		}
+
+		r1 = r.Link
+		if r1 == nil {
+			continue
+		}
+		p1 = r1.Prog
+		if p1.As != p.As {
+			continue
+		}
+		if p1.From.Type != obj.TYPE_REG || p1.From.Reg != p.To.Reg {
+			continue
+		}
+		if p1.To.Type != obj.TYPE_REG || p1.To.Reg != p.To.Reg {
+			continue
+		}
+		excise(r1)
+	}
+
+	gc.Flowend(g)
+}
+
+func excise(r *gc.Flow) {
+	p := (*obj.Prog)(r.Prog)
+	if gc.Debug['P'] != 0 && gc.Debug['v'] != 0 {
+		fmt.Printf("%v ===delete===\n", p)
+	}
+	obj.Nopout(p)
+	gc.Ostats.Ndelmov++
+}
+
+/*
+ * regzer returns 1 if a's value is 0 (a is R0 or $0)
+ */
+func regzer(a *obj.Addr) int {
+	if a.Type == obj.TYPE_CONST || a.Type == obj.TYPE_ADDR {
+		if a.Sym == nil && a.Reg == 0 {
+			if a.Offset == 0 {
+				return 1
+			}
+		}
+	}
+	if a.Type == obj.TYPE_REG {
+		if a.Reg == mips.REGZERO {
+			return 1
+		}
+	}
+	return 0
+}
+
+func regtyp(a *obj.Addr) bool {
+	// TODO(rsc): Floating point register exclusions?
+	return a.Type == obj.TYPE_REG && mips.REG_R0 <= a.Reg && a.Reg <= mips.REG_F31 && a.Reg != mips.REGZERO
+}
+
+func isfreg(a *obj.Addr) bool {
+	return mips.REG_F0 <= a.Reg && a.Reg <= mips.REG_F31
+}
+
+/*
+ * the idea is to substitute
+ * one register for another
+ * from one MOV to another
+ *	MOV	a, R1
+ *	ADD	b, R1	/ no use of R2
+ *	MOV	R1, R2
+ * would be converted to
+ *	MOV	a, R2
+ *	ADD	b, R2
+ *	MOV	R2, R1
+ * hopefully, then the former or latter MOV
+ * will be eliminated by copy propagation.
+ *
+ * r0 (the argument, not the register) is the MOV at the end of the
+ * above sequences.  This returns 1 if it modified any instructions.
+ */
+func subprop(r0 *gc.Flow) bool {
+	p := (*obj.Prog)(r0.Prog)
+	v1 := (*obj.Addr)(&p.From)
+	if !regtyp(v1) {
+		return false
+	}
+	v2 := (*obj.Addr)(&p.To)
+	if !regtyp(v2) {
+		return false
+	}
+	for r := gc.Uniqp(r0); r != nil; r = gc.Uniqp(r) {
+		if gc.Uniqs(r) == nil {
+			break
+		}
+		p = r.Prog
+		if p.As == obj.AVARDEF || p.As == obj.AVARKILL {
+			continue
+		}
+		if p.Info.Flags&gc.Call != 0 {
+			return false
+		}
+
+		if p.Info.Flags&(gc.RightRead|gc.RightWrite) == gc.RightWrite {
+			if p.To.Type == v1.Type {
+				if p.To.Reg == v1.Reg {
+					copysub(&p.To, v1, v2, 1)
+					if gc.Debug['P'] != 0 {
+						fmt.Printf("gotit: %v->%v\n%v", gc.Ctxt.Dconv(v1), gc.Ctxt.Dconv(v2), r.Prog)
+						if p.From.Type == v2.Type {
+							fmt.Printf(" excise")
+						}
+						fmt.Printf("\n")
+					}
+
+					for r = gc.Uniqs(r); r != r0; r = gc.Uniqs(r) {
+						p = r.Prog
+						copysub(&p.From, v1, v2, 1)
+						copysub1(p, v1, v2, 1)
+						copysub(&p.To, v1, v2, 1)
+						if gc.Debug['P'] != 0 {
+							fmt.Printf("%v\n", r.Prog)
+						}
+					}
+
+					t := int(int(v1.Reg))
+					v1.Reg = v2.Reg
+					v2.Reg = int16(t)
+					if gc.Debug['P'] != 0 {
+						fmt.Printf("%v last\n", r.Prog)
+					}
+					return true
+				}
+			}
+		}
+
+		if copyau(&p.From, v2) || copyau1(p, v2) || copyau(&p.To, v2) {
+			break
+		}
+		if copysub(&p.From, v1, v2, 0) != 0 || copysub1(p, v1, v2, 0) != 0 || copysub(&p.To, v1, v2, 0) != 0 {
+			break
+		}
+	}
+
+	return false
+}
+
+/*
+ * The idea is to remove redundant copies.
+ *	v1->v2	F=0
+ *	(use v2	s/v2/v1/)*
+ *	set v1	F=1
+ *	use v2	return fail (v1->v2 move must remain)
+ *	-----------------
+ *	v1->v2	F=0
+ *	(use v2	s/v2/v1/)*
+ *	set v1	F=1
+ *	set v2	return success (caller can remove v1->v2 move)
+ */
+func copyprop(r0 *gc.Flow) bool {
+	p := (*obj.Prog)(r0.Prog)
+	v1 := (*obj.Addr)(&p.From)
+	v2 := (*obj.Addr)(&p.To)
+	if copyas(v1, v2) {
+		if gc.Debug['P'] != 0 {
+			fmt.Printf("eliminating self-move: %v\n", r0.Prog)
+		}
+		return true
+	}
+
+	gactive++
+	if gc.Debug['P'] != 0 {
+		fmt.Printf("trying to eliminate %v->%v move from:\n%v\n", gc.Ctxt.Dconv(v1), gc.Ctxt.Dconv(v2), r0.Prog)
+	}
+	return copy1(v1, v2, r0.S1, 0)
+}
+
+// copy1 replaces uses of v2 with v1 starting at r and returns 1 if
+// all uses were rewritten.
+func copy1(v1 *obj.Addr, v2 *obj.Addr, r *gc.Flow, f int) bool {
+	if uint32(r.Active) == gactive {
+		if gc.Debug['P'] != 0 {
+			fmt.Printf("act set; return 1\n")
+		}
+		return true
+	}
+
+	r.Active = int32(gactive)
+	if gc.Debug['P'] != 0 {
+		fmt.Printf("copy1 replace %v with %v f=%d\n", gc.Ctxt.Dconv(v2), gc.Ctxt.Dconv(v1), f)
+	}
+	var t int
+	var p *obj.Prog
+	for ; r != nil; r = r.S1 {
+		p = r.Prog
+		if gc.Debug['P'] != 0 {
+			fmt.Printf("%v", p)
+		}
+		if f == 0 && gc.Uniqp(r) == nil {
+			// Multiple predecessors; conservatively
+			// assume v1 was set on other path
+			f = 1
+
+			if gc.Debug['P'] != 0 {
+				fmt.Printf("; merge; f=%d", f)
+			}
+		}
+
+		t = copyu(p, v2, nil)
+		switch t {
+		case 2: /* rar, can't split */
+			if gc.Debug['P'] != 0 {
+				fmt.Printf("; %v rar; return 0\n", gc.Ctxt.Dconv(v2))
+			}
+			return false
+
+		case 3: /* set */
+			if gc.Debug['P'] != 0 {
+				fmt.Printf("; %v set; return 1\n", gc.Ctxt.Dconv(v2))
+			}
+			return true
+
+		case 1, /* used, substitute */
+			4: /* use and set */
+			if f != 0 {
+				if gc.Debug['P'] == 0 {
+					return false
+				}
+				if t == 4 {
+					fmt.Printf("; %v used+set and f=%d; return 0\n", gc.Ctxt.Dconv(v2), f)
+				} else {
+					fmt.Printf("; %v used and f=%d; return 0\n", gc.Ctxt.Dconv(v2), f)
+				}
+				return false
+			}
+
+			if copyu(p, v2, v1) != 0 {
+				if gc.Debug['P'] != 0 {
+					fmt.Printf("; sub fail; return 0\n")
+				}
+				return false
+			}
+
+			if gc.Debug['P'] != 0 {
+				fmt.Printf("; sub %v->%v\n => %v", gc.Ctxt.Dconv(v2), gc.Ctxt.Dconv(v1), p)
+			}
+			if t == 4 {
+				if gc.Debug['P'] != 0 {
+					fmt.Printf("; %v used+set; return 1\n", gc.Ctxt.Dconv(v2))
+				}
+				return true
+			}
+		}
+
+		if f == 0 {
+			t = copyu(p, v1, nil)
+			if f == 0 && (t == 2 || t == 3 || t == 4) {
+				f = 1
+				if gc.Debug['P'] != 0 {
+					fmt.Printf("; %v set and !f; f=%d", gc.Ctxt.Dconv(v1), f)
+				}
+			}
+		}
+
+		if gc.Debug['P'] != 0 {
+			fmt.Printf("\n")
+		}
+		if r.S2 != nil {
+			if !copy1(v1, v2, r.S2, f) {
+				return false
+			}
+		}
+	}
+
+	return true
+}
+
+// If s==nil, copyu returns the set/use of v in p; otherwise, it
+// modifies p to replace reads of v with reads of s and returns 0 for
+// success or non-zero for failure.
+//
+// If s==nil, copy returns one of the following values:
+// 	1 if v only used
+//	2 if v is set and used in one address (read-alter-rewrite;
+// 	  can't substitute)
+//	3 if v is only set
+//	4 if v is set in one address and used in another (so addresses
+// 	  can be rewritten independently)
+//	0 otherwise (not touched)
+func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
+	if p.From3Type() != obj.TYPE_NONE {
+		// never generates a from3
+		fmt.Printf("copyu: from3 (%v) not implemented\n", gc.Ctxt.Dconv(p.From3))
+	}
+
+	switch p.As {
+	default:
+		fmt.Printf("copyu: can't find %v\n", obj.Aconv(int(p.As)))
+		return 2
+
+	case obj.ANOP, /* read p->from, write p->to */
+		mips.AMOVV,
+		mips.AMOVF,
+		mips.AMOVD,
+		mips.AMOVH,
+		mips.AMOVHU,
+		mips.AMOVB,
+		mips.AMOVBU,
+		mips.AMOVW,
+		mips.AMOVWU,
+		mips.AMOVFD,
+		mips.AMOVDF,
+		mips.AMOVDW,
+		mips.AMOVWD,
+		mips.AMOVFW,
+		mips.AMOVWF,
+		mips.AMOVDV,
+		mips.AMOVVD,
+		mips.AMOVFV,
+		mips.AMOVVF,
+		mips.ATRUNCFV,
+		mips.ATRUNCDV,
+		mips.ATRUNCFW,
+		mips.ATRUNCDW:
+		if s != nil {
+			if copysub(&p.From, v, s, 1) != 0 {
+				return 1
+			}
+
+			// Update only indirect uses of v in p->to
+			if !copyas(&p.To, v) {
+				if copysub(&p.To, v, s, 1) != 0 {
+					return 1
+				}
+			}
+			return 0
+		}
+
+		if copyas(&p.To, v) {
+			// Fix up implicit from
+			if p.From.Type == obj.TYPE_NONE {
+				p.From = p.To
+			}
+			if copyau(&p.From, v) {
+				return 4
+			}
+			return 3
+		}
+
+		if copyau(&p.From, v) {
+			return 1
+		}
+		if copyau(&p.To, v) {
+			// p->to only indirectly uses v
+			return 1
+		}
+
+		return 0
+
+	case mips.ASGT, /* read p->from, read p->reg, write p->to */
+		mips.ASGTU,
+
+		mips.AADD,
+		mips.AADDU,
+		mips.ASUB,
+		mips.ASUBU,
+		mips.ASLL,
+		mips.ASRL,
+		mips.ASRA,
+		mips.AOR,
+		mips.ANOR,
+		mips.AAND,
+		mips.AXOR,
+
+		mips.AADDV,
+		mips.AADDVU,
+		mips.ASUBV,
+		mips.ASUBVU,
+		mips.ASLLV,
+		mips.ASRLV,
+		mips.ASRAV,
+
+		mips.AADDF,
+		mips.AADDD,
+		mips.ASUBF,
+		mips.ASUBD,
+		mips.AMULF,
+		mips.AMULD,
+		mips.ADIVF,
+		mips.ADIVD:
+		if s != nil {
+			if copysub(&p.From, v, s, 1) != 0 {
+				return 1
+			}
+			if copysub1(p, v, s, 1) != 0 {
+				return 1
+			}
+
+			// Update only indirect uses of v in p->to
+			if !copyas(&p.To, v) {
+				if copysub(&p.To, v, s, 1) != 0 {
+					return 1
+				}
+			}
+			return 0
+		}
+
+		if copyas(&p.To, v) {
+			if p.Reg == 0 {
+				// Fix up implicit reg (e.g., ADD
+				// R3,R4 -> ADD R3,R4,R4) so we can
+				// update reg and to separately.
+				p.Reg = p.To.Reg
+			}
+
+			if copyau(&p.From, v) {
+				return 4
+			}
+			if copyau1(p, v) {
+				return 4
+			}
+			return 3
+		}
+
+		if copyau(&p.From, v) {
+			return 1
+		}
+		if copyau1(p, v) {
+			return 1
+		}
+		if copyau(&p.To, v) {
+			return 1
+		}
+		return 0
+
+	case obj.ACHECKNIL, /* read p->from */
+		mips.ABEQ, /* read p->from, read p->reg */
+		mips.ABNE,
+		mips.ABGTZ,
+		mips.ABGEZ,
+		mips.ABLTZ,
+		mips.ABLEZ,
+
+		mips.ACMPEQD,
+		mips.ACMPEQF,
+		mips.ACMPGED,
+		mips.ACMPGEF,
+		mips.ACMPGTD,
+		mips.ACMPGTF,
+		mips.ABFPF,
+		mips.ABFPT,
+
+		mips.AMUL,
+		mips.AMULU,
+		mips.ADIV,
+		mips.ADIVU,
+		mips.AMULV,
+		mips.AMULVU,
+		mips.ADIVV,
+		mips.ADIVVU:
+		if s != nil {
+			if copysub(&p.From, v, s, 1) != 0 {
+				return 1
+			}
+			return copysub1(p, v, s, 1)
+		}
+
+		if copyau(&p.From, v) {
+			return 1
+		}
+		if copyau1(p, v) {
+			return 1
+		}
+		return 0
+
+	case mips.AJMP: /* read p->to */
+		if s != nil {
+			if copysub(&p.To, v, s, 1) != 0 {
+				return 1
+			}
+			return 0
+		}
+
+		if copyau(&p.To, v) {
+			return 1
+		}
+		return 0
+
+	case mips.ARET: /* funny */
+		if s != nil {
+			return 0
+		}
+
+		// All registers die at this point, so claim
+		// everything is set (and not used).
+		return 3
+
+	case mips.AJAL: /* funny */
+		if v.Type == obj.TYPE_REG {
+			// TODO(rsc): REG_R0 and REG_F0 used to be
+			// (when register numbers started at 0) exregoffset and exfregoffset,
+			// which are unset entirely.
+			// It's strange that this handles R0 and F0 differently from the other
+			// registers. Possible failure to optimize?
+			if mips.REG_R0 < v.Reg && v.Reg <= mips.REG_R31 {
+				return 2
+			}
+			if v.Reg == mips.REGARG {
+				return 2
+			}
+			if mips.REG_F0 < v.Reg && v.Reg <= mips.REG_F31 {
+				return 2
+			}
+		}
+
+		if p.From.Type == obj.TYPE_REG && v.Type == obj.TYPE_REG && p.From.Reg == v.Reg {
+			return 2
+		}
+
+		if s != nil {
+			if copysub(&p.To, v, s, 1) != 0 {
+				return 1
+			}
+			return 0
+		}
+
+		if copyau(&p.To, v) {
+			return 4
+		}
+		return 3
+
+	// R0 is zero, used by DUFFZERO, cannot be substituted.
+	// R1 is ptr to memory, used and set, cannot be substituted.
+	case obj.ADUFFZERO:
+		if v.Type == obj.TYPE_REG {
+			if v.Reg == 0 {
+				return 1
+			}
+			if v.Reg == 1 {
+				return 2
+			}
+		}
+
+		return 0
+
+	// R1, R2 are ptr to src, dst, used and set, cannot be substituted.
+	// R3 is scratch, set by DUFFCOPY, cannot be substituted.
+	case obj.ADUFFCOPY:
+		if v.Type == obj.TYPE_REG {
+			if v.Reg == 1 || v.Reg == 2 {
+				return 2
+			}
+			if v.Reg == 3 {
+				return 3
+			}
+		}
+
+		return 0
+
+	case obj.ATEXT: /* funny */
+		if v.Type == obj.TYPE_REG {
+			if v.Reg == mips.REGARG {
+				return 3
+			}
+		}
+		return 0
+
+	case obj.APCDATA,
+		obj.AFUNCDATA,
+		obj.AVARDEF,
+		obj.AVARKILL,
+		obj.AVARLIVE,
+		obj.AUSEFIELD:
+		return 0
+	}
+}
+
+// copyas returns 1 if a and v address the same register.
+//
+// If a is the from operand, this means this operation reads the
+// register in v.  If a is the to operand, this means this operation
+// writes the register in v.
+func copyas(a *obj.Addr, v *obj.Addr) bool {
+	if regtyp(v) {
+		if a.Type == v.Type {
+			if a.Reg == v.Reg {
+				return true
+			}
+		}
+	}
+	return false
+}
+
+// copyau returns 1 if a either directly or indirectly addresses the
+// same register as v.
+//
+// If a is the from operand, this means this operation reads the
+// register in v.  If a is the to operand, this means the operation
+// either reads or writes the register in v (if !copyas(a, v), then
+// the operation reads the register in v).
+func copyau(a *obj.Addr, v *obj.Addr) bool {
+	if copyas(a, v) {
+		return true
+	}
+	if v.Type == obj.TYPE_REG {
+		if a.Type == obj.TYPE_MEM || (a.Type == obj.TYPE_ADDR && a.Reg != 0) {
+			if v.Reg == a.Reg {
+				return true
+			}
+		}
+	}
+	return false
+}
+
+// copyau1 returns 1 if p->reg references the same register as v and v
+// is a direct reference.
+func copyau1(p *obj.Prog, v *obj.Addr) bool {
+	if regtyp(v) && v.Reg != 0 {
+		if p.Reg == v.Reg {
+			return true
+		}
+	}
+	return false
+}
+
+// copysub replaces v with s in a if f!=0 or indicates it if could if f==0.
+// Returns 1 on failure to substitute (it always succeeds on mips).
+func copysub(a *obj.Addr, v *obj.Addr, s *obj.Addr, f int) int {
+	if f != 0 {
+		if copyau(a, v) {
+			a.Reg = s.Reg
+		}
+	}
+	return 0
+}
+
+// copysub1 replaces v with s in p1->reg if f!=0 or indicates if it could if f==0.
+// Returns 1 on failure to substitute (it always succeeds on mips).
+func copysub1(p1 *obj.Prog, v *obj.Addr, s *obj.Addr, f int) int {
+	if f != 0 {
+		if copyau1(p1, v) {
+			p1.Reg = s.Reg
+		}
+	}
+	return 0
+}
+
+func sameaddr(a *obj.Addr, v *obj.Addr) bool {
+	if a.Type != v.Type {
+		return false
+	}
+	if regtyp(v) && a.Reg == v.Reg {
+		return true
+	}
+	if v.Type == obj.NAME_AUTO || v.Type == obj.NAME_PARAM {
+		if v.Offset == a.Offset {
+			return true
+		}
+	}
+	return false
+}
+
+func smallindir(a *obj.Addr, reg *obj.Addr) bool {
+	return reg.Type == obj.TYPE_REG && a.Type == obj.TYPE_MEM && a.Reg == reg.Reg && 0 <= a.Offset && a.Offset < 4096
+}
+
+func stackaddr(a *obj.Addr) bool {
+	return a.Type == obj.TYPE_REG && a.Reg == mips.REGSP
+}
diff --git a/src/cmd/compile/internal/mips64/prog.go b/src/cmd/compile/internal/mips64/prog.go
new file mode 100644
index 0000000..b07c7fe
--- /dev/null
+++ b/src/cmd/compile/internal/mips64/prog.go
@@ -0,0 +1,174 @@
+// 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 mips64
+
+import (
+	"cmd/compile/internal/gc"
+	"cmd/internal/obj"
+	"cmd/internal/obj/mips"
+)
+
+const (
+	LeftRdwr  uint32 = gc.LeftRead | gc.LeftWrite
+	RightRdwr uint32 = gc.RightRead | gc.RightWrite
+)
+
+// This table gives the basic information about instruction
+// generated by the compiler and processed in the optimizer.
+// See opt.h for bit definitions.
+//
+// Instructions not generated need not be listed.
+// As an exception to that rule, we typically write down all the
+// size variants of an operation even if we just use a subset.
+//
+// The table is formatted for 8-space tabs.
+var progtable = [mips.ALAST]obj.ProgInfo{
+	obj.ATYPE:     {Flags: gc.Pseudo | gc.Skip},
+	obj.ATEXT:     {Flags: gc.Pseudo},
+	obj.AFUNCDATA: {Flags: gc.Pseudo},
+	obj.APCDATA:   {Flags: gc.Pseudo},
+	obj.AUNDEF:    {Flags: gc.Break},
+	obj.AUSEFIELD: {Flags: gc.OK},
+	obj.ACHECKNIL: {Flags: gc.LeftRead},
+	obj.AVARDEF:   {Flags: gc.Pseudo | gc.RightWrite},
+	obj.AVARKILL:  {Flags: gc.Pseudo | gc.RightWrite},
+	obj.AVARLIVE:  {Flags: gc.Pseudo | gc.LeftRead},
+
+	// NOP is an internal no-op that also stands
+	// for USED and SET annotations, not the MIPS opcode.
+	obj.ANOP: {Flags: gc.LeftRead | gc.RightWrite},
+
+	// Integer
+	mips.AADD:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.AADDU:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.AADDV:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.AADDVU: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.ASUB:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.ASUBU:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.ASUBV:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.ASUBVU: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.AAND:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.AOR:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.AXOR:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.ANOR:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.AMUL:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
+	mips.AMULU:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
+	mips.AMULV:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead},
+	mips.AMULVU: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead},
+	mips.ADIV:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
+	mips.ADIVU:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
+	mips.ADIVV:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead},
+	mips.ADIVVU: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead},
+	mips.AREM:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
+	mips.AREMU:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead},
+	mips.AREMV:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead},
+	mips.AREMVU: {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead},
+	mips.ASLL:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.ASLLV:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.ASRA:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.ASRAV:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.ASRL:   {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.ASRLV:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.ASGT:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.ASGTU:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+
+	// Floating point.
+	mips.AADDF:    {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.AADDD:    {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.ASUBF:    {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.ASUBD:    {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.AMULF:    {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.AMULD:    {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.ADIVF:    {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.ADIVD:    {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	mips.AABSF:    {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite},
+	mips.AABSD:    {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite},
+	mips.ANEGF:    {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite},
+	mips.ANEGD:    {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite},
+	mips.ACMPEQF:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead},
+	mips.ACMPEQD:  {Flags: gc.SizeD | gc.LeftRead | gc.RegRead},
+	mips.ACMPGTF:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead},
+	mips.ACMPGTD:  {Flags: gc.SizeD | gc.LeftRead | gc.RegRead},
+	mips.ACMPGEF:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead},
+	mips.ACMPGED:  {Flags: gc.SizeD | gc.LeftRead | gc.RegRead},
+	mips.AMOVFD:   {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+	mips.AMOVDF:   {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
+	mips.AMOVFW:   {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	mips.AMOVWF:   {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
+	mips.AMOVDW:   {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	mips.AMOVWD:   {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+	mips.AMOVFV:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+	mips.AMOVVF:   {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
+	mips.AMOVDV:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+	mips.AMOVVD:   {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+	mips.ATRUNCFW: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	mips.ATRUNCDW: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	mips.ATRUNCFV: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+	mips.ATRUNCDV: {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Conv},
+
+	// Moves
+	mips.AMOVB:  {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+	mips.AMOVBU: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+	mips.AMOVH:  {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+	mips.AMOVHU: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+	mips.AMOVW:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+	mips.AMOVWU: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+	mips.AMOVV:  {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move},
+	mips.AMOVF:  {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+	mips.AMOVD:  {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
+
+	// Jumps
+	mips.AJMP:     {Flags: gc.Jump | gc.Break},
+	mips.AJAL:     {Flags: gc.Call},
+	mips.ABEQ:     {Flags: gc.Cjmp},
+	mips.ABNE:     {Flags: gc.Cjmp},
+	mips.ABGEZ:    {Flags: gc.Cjmp},
+	mips.ABLTZ:    {Flags: gc.Cjmp},
+	mips.ABGTZ:    {Flags: gc.Cjmp},
+	mips.ABLEZ:    {Flags: gc.Cjmp},
+	mips.ABFPF:    {Flags: gc.Cjmp},
+	mips.ABFPT:    {Flags: gc.Cjmp},
+	mips.ARET:     {Flags: gc.Break},
+	obj.ADUFFZERO: {Flags: gc.Call},
+	obj.ADUFFCOPY: {Flags: gc.Call},
+}
+
+func proginfo(p *obj.Prog) {
+	info := &p.Info
+	*info = progtable[p.As]
+	if info.Flags == 0 {
+		gc.Fatalf("proginfo: unknown instruction %v", p)
+	}
+
+	if (info.Flags&gc.RegRead != 0) && p.Reg == 0 {
+		info.Flags &^= gc.RegRead
+		info.Flags |= gc.RightRead /*CanRegRead |*/
+	}
+
+	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 (p.To.Type == obj.TYPE_MEM || p.To.Type == obj.TYPE_ADDR) && p.To.Reg != 0 {
+		info.Regindex |= RtoB(int(p.To.Reg))
+	}
+
+	if p.From.Type == obj.TYPE_ADDR && p.From.Sym != nil && (info.Flags&gc.LeftRead != 0) {
+		info.Flags &^= gc.LeftRead
+		info.Flags |= gc.LeftAddr
+	}
+
+	if p.As == obj.ADUFFZERO {
+		info.Reguse |= 1<<0 | RtoB(mips.REGRT1)
+		info.Regset |= RtoB(mips.REGRT1)
+	}
+
+	if p.As == obj.ADUFFCOPY {
+		// TODO(austin) Revisit when duffcopy is implemented
+		info.Reguse |= RtoB(mips.REGRT1) | RtoB(mips.REGRT2) | RtoB(mips.REG_R3)
+
+		info.Regset |= RtoB(mips.REGRT1) | RtoB(mips.REGRT2)
+	}
+}
diff --git a/src/cmd/compile/internal/mips64/reg.go b/src/cmd/compile/internal/mips64/reg.go
new file mode 100644
index 0000000..5c46588
--- /dev/null
+++ b/src/cmd/compile/internal/mips64/reg.go
@@ -0,0 +1,162 @@
+// Derived from Inferno utils/6c/reg.c
+// http://code.google.com/p/inferno-os/source/browse/utils/6c/reg.c
+//
+//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//	Portions Copyright © 1995-1997 C H Forsyth (forsyth at terzarima.net)
+//	Portions Copyright © 1997-1999 Vita Nuova Limited
+//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+//	Portions Copyright © 2004,2006 Bruce Ellis
+//	Portions Copyright © 2005-2007 C H Forsyth (forsyth at terzarima.net)
+//	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package mips64
+
+import "cmd/internal/obj/mips"
+import "cmd/compile/internal/gc"
+
+const (
+	NREGVAR = 64 /* 32 general + 32 floating */
+)
+
+var regname = []string{
+	".R0",
+	".R1",
+	".R2",
+	".R3",
+	".R4",
+	".R5",
+	".R6",
+	".R7",
+	".R8",
+	".R9",
+	".R10",
+	".R11",
+	".R12",
+	".R13",
+	".R14",
+	".R15",
+	".R16",
+	".R17",
+	".R18",
+	".R19",
+	".R20",
+	".R21",
+	".R22",
+	".R23",
+	".R24",
+	".R25",
+	".R26",
+	".R27",
+	".R28",
+	".R29",
+	".R30",
+	".R31",
+	".F0",
+	".F1",
+	".F2",
+	".F3",
+	".F4",
+	".F5",
+	".F6",
+	".F7",
+	".F8",
+	".F9",
+	".F10",
+	".F11",
+	".F12",
+	".F13",
+	".F14",
+	".F15",
+	".F16",
+	".F17",
+	".F18",
+	".F19",
+	".F20",
+	".F21",
+	".F22",
+	".F23",
+	".F24",
+	".F25",
+	".F26",
+	".F27",
+	".F28",
+	".F29",
+	".F30",
+	".F31",
+}
+
+func regnames(n *int) []string {
+	*n = NREGVAR
+	return regname
+}
+
+func excludedregs() uint64 {
+	// Exclude registers with fixed functions
+	regbits := uint64(1<<0 | RtoB(mips.REGSP) | RtoB(mips.REGG) | RtoB(mips.REGTMP) | RtoB(mips.REGLINK) | RtoB(mips.REG_R26) | RtoB(mips.REG_R27))
+
+	// Also exclude floating point registers with fixed constants
+	regbits |= RtoB(mips.FREGZERO) | RtoB(mips.FREGHALF) | RtoB(mips.FREGONE) | RtoB(mips.FREGTWO)
+
+	return regbits
+}
+
+func doregbits(r int) uint64 {
+	return 0
+}
+
+/*
+ * track register variables including external registers:
+ *	bit	reg
+ *	0	R0
+ *	1	R1
+ *	...	...
+ *	31	R31
+ *	32+0	F0
+ *	32+1	F1
+ *	...	...
+ *	32+31	F31
+ */
+func RtoB(r int) uint64 {
+	if r > mips.REG_R0 && r <= mips.REG_R31 {
+		return 1 << uint(r-mips.REG_R0)
+	}
+	if r >= mips.REG_F0 && r <= mips.REG_F31 {
+		return 1 << uint(32+r-mips.REG_F0)
+	}
+	return 0
+}
+
+func BtoR(b uint64) int {
+	b &= 0xffffffff
+	if b == 0 {
+		return 0
+	}
+	return gc.Bitno(b) + mips.REG_R0
+}
+
+func BtoF(b uint64) int {
+	b >>= 32
+	if b == 0 {
+		return 0
+	}
+	return gc.Bitno(b) + mips.REG_F0
+}
diff --git a/src/cmd/compile/internal/ppc64/cgen.go b/src/cmd/compile/internal/ppc64/cgen.go
index 37dd6ce..740e64c 100644
--- a/src/cmd/compile/internal/ppc64/cgen.go
+++ b/src/cmd/compile/internal/ppc64/cgen.go
@@ -20,7 +20,7 @@ func blockcopy(n, res *gc.Node, osrc, odst, w int64) {
 	var op int
 	switch align {
 	default:
-		gc.Fatal("sgen: invalid alignment %d for %v", align, n.Type)
+		gc.Fatalf("sgen: invalid alignment %d for %v", align, n.Type)
 
 	case 1:
 		op = ppc64.AMOVBU
@@ -36,7 +36,7 @@ func blockcopy(n, res *gc.Node, osrc, odst, w int64) {
 	}
 
 	if w%int64(align) != 0 {
-		gc.Fatal("sgen: unaligned size %d (align=%d) for %v", w, align, n.Type)
+		gc.Fatalf("sgen: unaligned size %d (align=%d) for %v", w, align, n.Type)
 	}
 	c := int32(w / int64(align))
 
@@ -126,13 +126,7 @@ func blockcopy(n, res *gc.Node, osrc, odst, w int64) {
 		// ADDs.  That will produce shorter, more
 		// pipeline-able code.
 		var p *obj.Prog
-		for {
-			tmp14 := c
-			c--
-			if tmp14 <= 0 {
-				break
-			}
-
+		for ; c > 0; c-- {
 			p = gins(op, &src, &tmp)
 			p.From.Type = obj.TYPE_MEM
 			p.From.Offset = int64(dir)
diff --git a/src/cmd/compile/internal/ppc64/galign.go b/src/cmd/compile/internal/ppc64/galign.go
index 73aef6f..2bd49fd 100644
--- a/src/cmd/compile/internal/ppc64/galign.go
+++ b/src/cmd/compile/internal/ppc64/galign.go
@@ -34,15 +34,20 @@ var MAXWIDTH int64 = 1 << 50
  * int, uint, and uintptr
  */
 var typedefs = []gc.Typedef{
-	gc.Typedef{"int", gc.TINT, gc.TINT64},
-	gc.Typedef{"uint", gc.TUINT, gc.TUINT64},
-	gc.Typedef{"uintptr", gc.TUINTPTR, gc.TUINT64},
+	{"int", gc.TINT, gc.TINT64},
+	{"uint", gc.TUINT, gc.TUINT64},
+	{"uintptr", gc.TUINTPTR, gc.TUINT64},
 }
 
 func betypeinit() {
 	gc.Widthptr = 8
 	gc.Widthint = 8
 	gc.Widthreg = 8
+
+	if gc.Ctxt.Flag_shared != 0 {
+		gc.Thearch.ReservedRegs = append(gc.Thearch.ReservedRegs, ppc64.REG_R2)
+		gc.Thearch.ReservedRegs = append(gc.Thearch.ReservedRegs, ppc64.REG_R12)
+	}
 }
 
 func Main() {
diff --git a/src/cmd/compile/internal/ppc64/ggen.go b/src/cmd/compile/internal/ppc64/ggen.go
index 5b282eb..28fcecf 100644
--- a/src/cmd/compile/internal/ppc64/ggen.go
+++ b/src/cmd/compile/internal/ppc64/ggen.go
@@ -36,10 +36,10 @@ func defframe(ptxt *obj.Prog) {
 			continue
 		}
 		if n.Class != gc.PAUTO {
-			gc.Fatal("needzero class %d", n.Class)
+			gc.Fatalf("needzero class %d", n.Class)
 		}
 		if n.Type.Width%int64(gc.Widthptr) != 0 || n.Xoffset%int64(gc.Widthptr) != 0 || n.Type.Width == 0 {
-			gc.Fatal("var %v has size %d offset %d", gc.Nconv(n, obj.FmtLong), int(n.Type.Width), int(n.Xoffset))
+			gc.Fatalf("var %v has size %d offset %d", gc.Nconv(n, obj.FmtLong), int(n.Type.Width), int(n.Xoffset))
 		}
 
 		if lo != hi && n.Xoffset+n.Type.Width >= lo-int64(2*gc.Widthreg) {
@@ -69,13 +69,10 @@ func zerorange(p *obj.Prog, frame int64, lo int64, hi int64) *obj.Prog {
 	}
 	if cnt < int64(4*gc.Widthptr) {
 		for i := int64(0); i < cnt; i += int64(gc.Widthptr) {
-			p = appendpp(p, ppc64.AMOVD, obj.TYPE_REG, ppc64.REGZERO, 0, obj.TYPE_MEM, ppc64.REGSP, 8+frame+lo+i)
+			p = appendpp(p, ppc64.AMOVD, obj.TYPE_REG, ppc64.REGZERO, 0, obj.TYPE_MEM, ppc64.REGSP, gc.Ctxt.FixedFrameSize()+frame+lo+i)
 		}
-		// TODO(dfc): https://golang.org/issue/12108
-		// If DUFFZERO is used inside a tail call (see genwrapper) it will
-		// overwrite the link register.
-	} else if false && cnt <= int64(128*gc.Widthptr) {
-		p = appendpp(p, ppc64.AADD, obj.TYPE_CONST, 0, 8+frame+lo-8, obj.TYPE_REG, ppc64.REGRT1, 0)
+	} else if cnt <= int64(128*gc.Widthptr) {
+		p = appendpp(p, ppc64.AADD, obj.TYPE_CONST, 0, gc.Ctxt.FixedFrameSize()+frame+lo-8, obj.TYPE_REG, ppc64.REGRT1, 0)
 		p.Reg = ppc64.REGSP
 		p = appendpp(p, obj.ADUFFZERO, obj.TYPE_NONE, 0, 0, obj.TYPE_MEM, 0, 0)
 		f := gc.Sysfunc("duffzero")
@@ -83,7 +80,7 @@ func zerorange(p *obj.Prog, frame int64, lo int64, hi int64) *obj.Prog {
 		gc.Afunclit(&p.To, f)
 		p.To.Offset = 4 * (128 - cnt/int64(gc.Widthptr))
 	} else {
-		p = appendpp(p, ppc64.AMOVD, obj.TYPE_CONST, 0, 8+frame+lo-8, obj.TYPE_REG, ppc64.REGTMP, 0)
+		p = appendpp(p, ppc64.AMOVD, obj.TYPE_CONST, 0, gc.Ctxt.FixedFrameSize()+frame+lo-8, obj.TYPE_REG, ppc64.REGTMP, 0)
 		p = appendpp(p, ppc64.AADD, obj.TYPE_REG, ppc64.REGTMP, 0, obj.TYPE_REG, ppc64.REGRT1, 0)
 		p.Reg = ppc64.REGSP
 		p = appendpp(p, ppc64.AMOVD, obj.TYPE_CONST, 0, cnt, obj.TYPE_REG, ppc64.REGTMP, 0)
@@ -130,7 +127,7 @@ var panicdiv *gc.Node
  *	res = nl % nr
  * according to op.
  */
-func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+func dodiv(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	// Have to be careful about handling
 	// most negative int divided by -1 correctly.
 	// The hardware will generate undefined result.
@@ -141,13 +138,13 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	t := nl.Type
 
 	t0 := t
-	check := 0
+	check := false
 	if gc.Issigned[t.Etype] {
-		check = 1
+		check = true
 		if gc.Isconst(nl, gc.CTINT) && nl.Int() != -(1<<uint64(t.Width*8-1)) {
-			check = 0
+			check = false
 		} else if gc.Isconst(nr, gc.CTINT) && nr.Int() != -1 {
-			check = 0
+			check = false
 		}
 	}
 
@@ -157,7 +154,7 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 		} else {
 			t = gc.Types[gc.TUINT64]
 		}
-		check = 0
+		check = false
 	}
 
 	a := optoas(gc.ODIV, t)
@@ -198,7 +195,7 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	gc.Patch(p1, gc.Pc)
 
 	var p2 *obj.Prog
-	if check != 0 {
+	if check {
 		var nm1 gc.Node
 		gc.Nodconst(&nm1, t, -1)
 		gins(optoas(gc.OCMP, t), &tr, &nm1)
@@ -242,7 +239,7 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	}
 
 	gc.Regfree(&tl)
-	if check != 0 {
+	if check {
 		gc.Patch(p2, gc.Pc)
 	}
 }
@@ -254,9 +251,7 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	// largest ullman on left.
 	if nl.Ullman < nr.Ullman {
-		tmp := (*gc.Node)(nl)
-		nl = nr
-		nr = tmp
+		nl, nr = nr, nl
 	}
 
 	t := (*gc.Type)(nl.Type)
@@ -291,7 +286,7 @@ func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
 		}
 
 	default:
-		gc.Fatal("cgen_hmul %v", t)
+		gc.Fatalf("cgen_hmul %v", t)
 	}
 
 	gc.Cgen(&n1, res)
@@ -304,7 +299,7 @@ func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
  *	res = nl << nr
  *	res = nl >> nr
  */
-func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+func cgen_shift(op gc.Op, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	a := int(optoas(op, nl.Type))
 
 	if nr.Op == gc.OLITERAL {
@@ -411,7 +406,7 @@ func clearfat(nl *gc.Node) {
 	q := uint64(w / 8) // dwords
 
 	if gc.Reginuse(ppc64.REGRT1) {
-		gc.Fatal("%v in use during clearfat", obj.Rconv(ppc64.REGRT1))
+		gc.Fatalf("%v in use during clearfat", obj.Rconv(ppc64.REGRT1))
 	}
 
 	var r0 gc.Node
@@ -445,10 +440,7 @@ func clearfat(nl *gc.Node) {
 
 		// The loop leaves R3 on the last zeroed dword
 		boff = 8
-		// TODO(dfc): https://golang.org/issue/12108
-		// If DUFFZERO is used inside a tail call (see genwrapper) it will
-		// overwrite the link register.
-	} else if false && q >= 4 {
+	} else if q >= 4 {
 		p := gins(ppc64.ASUB, nil, &dst)
 		p.From.Type = obj.TYPE_CONST
 		p.From.Offset = 8
@@ -499,7 +491,7 @@ func expandchecks(firstp *obj.Prog) {
 			gc.Warnl(int(p.Lineno), "generated nil check")
 		}
 		if p.From.Type != obj.TYPE_REG {
-			gc.Fatal("invalid nil check %v\n", p)
+			gc.Fatalf("invalid nil check %v\n", p)
 		}
 
 		/*
diff --git a/src/cmd/compile/internal/ppc64/gsubr.go b/src/cmd/compile/internal/ppc64/gsubr.go
index 2501972..534ea62 100644
--- a/src/cmd/compile/internal/ppc64/gsubr.go
+++ b/src/cmd/compile/internal/ppc64/gsubr.go
@@ -93,7 +93,7 @@ func ginscon2(as int, n2 *gc.Node, c int64) {
 
 	switch as {
 	default:
-		gc.Fatal("ginscon2")
+		gc.Fatalf("ginscon2")
 
 	case ppc64.ACMP:
 		if -ppc64.BIG <= c && c <= ppc64.BIG {
@@ -117,7 +117,7 @@ func ginscon2(as int, n2 *gc.Node, c int64) {
 	gc.Regfree(&ntmp)
 }
 
-func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+func ginscmp(op gc.Op, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
 	if gc.Isint[t.Etype] && n1.Op == gc.OLITERAL && n2.Op != gc.OLITERAL {
 		// Reverse comparison to place constant last.
 		op = gc.Brrev(op)
@@ -261,7 +261,7 @@ func gmove(f *gc.Node, t *gc.Node) {
 
 	switch uint32(ft)<<16 | uint32(tt) {
 	default:
-		gc.Fatal("gmove %v -> %v", gc.Tconv(f.Type, obj.FmtLong), gc.Tconv(t.Type, obj.FmtLong))
+		gc.Fatalf("gmove %v -> %v", gc.Tconv(f.Type, obj.FmtLong), gc.Tconv(t.Type, obj.FmtLong))
 
 		/*
 		 * integer copy and truncate
@@ -545,30 +545,18 @@ hard:
 	return
 }
 
-func intLiteral(n *gc.Node) (x int64, ok bool) {
-	switch {
-	case n == nil:
-		return
-	case gc.Isconst(n, gc.CTINT):
-		return n.Int(), true
-	case gc.Isconst(n, gc.CTBOOL):
-		return int64(obj.Bool2int(n.Bool())), true
-	}
-	return
-}
-
 // gins is called by the front end.
 // 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 {
+		if x, ok := f.IntLiteral(); ok {
 			ginscon(as, x, t)
 			return nil // caller must not use
 		}
 	}
 	if as == ppc64.ACMP || as == ppc64.ACMPU {
-		if x, ok := intLiteral(t); ok {
+		if x, ok := t.IntLiteral(); ok {
 			ginscon2(as, f, x)
 			return nil // caller must not use
 		}
@@ -592,6 +580,18 @@ func rawgins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
 	case obj.ACALL:
 		if p.To.Type == obj.TYPE_REG && p.To.Reg != ppc64.REG_CTR {
 			// Allow front end to emit CALL REG, and rewrite into MOV REG, CTR; CALL CTR.
+			if gc.Ctxt.Flag_shared != 0 {
+				// Make sure function pointer is in R12 as well when
+				// compiling Go into PIC.
+				// TODO(mwhudson): it would obviously be better to
+				// change the register allocation to put the value in
+				// R12 already, but I don't know how to do that.
+				q := gc.Prog(as)
+				q.As = ppc64.AMOVD
+				q.From = p.To
+				q.To.Type = obj.TYPE_REG
+				q.To.Reg = ppc64.REG_R12
+			}
 			pp := gc.Prog(as)
 			pp.From = p.From
 			pp.To.Type = obj.TYPE_REG
@@ -602,6 +602,19 @@ func rawgins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
 			p.To.Type = obj.TYPE_REG
 			p.To.Reg = ppc64.REG_CTR
 
+			if gc.Ctxt.Flag_shared != 0 {
+				// When compiling Go into PIC, the function we just
+				// called via pointer might have been implemented in
+				// a separate module and so overwritten the TOC
+				// pointer in R2; reload it.
+				q := gc.Prog(ppc64.AMOVD)
+				q.From.Type = obj.TYPE_MEM
+				q.From.Offset = 24
+				q.From.Reg = ppc64.REGSP
+				q.To.Type = obj.TYPE_REG
+				q.To.Reg = ppc64.REG_R2
+			}
+
 			if gc.Debug['g'] != 0 {
 				fmt.Printf("%v\n", p)
 				fmt.Printf("%v\n", pp)
@@ -614,12 +627,12 @@ func rawgins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
 	case ppc64.AAND, ppc64.AMULLD:
 		if p.From.Type == obj.TYPE_CONST {
 			gc.Debug['h'] = 1
-			gc.Fatal("bad inst: %v", p)
+			gc.Fatalf("bad inst: %v", p)
 		}
 	case ppc64.ACMP, ppc64.ACMPU:
 		if p.From.Type == obj.TYPE_MEM || p.To.Type == obj.TYPE_MEM {
 			gc.Debug['h'] = 1
-			gc.Fatal("bad inst: %v", p)
+			gc.Fatalf("bad inst: %v", p)
 		}
 	}
 
@@ -658,7 +671,7 @@ func rawgins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
 	if w != 0 && ((f != nil && p.From.Width < int64(w)) || (t != nil && p.To.Type != obj.TYPE_REG && p.To.Width > int64(w))) {
 		gc.Dump("f", f)
 		gc.Dump("t", t)
-		gc.Fatal("bad width: %v (%d, %d)\n", p, p.From.Width, p.To.Width)
+		gc.Fatalf("bad width: %v (%d, %d)\n", p, p.From.Width, p.To.Width)
 	}
 
 	return p
@@ -667,229 +680,252 @@ func rawgins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
 /*
  * return Axxx for Oxxx on type t.
  */
-func optoas(op int, t *gc.Type) int {
+func optoas(op gc.Op, t *gc.Type) int {
 	if t == nil {
-		gc.Fatal("optoas: t is nil")
+		gc.Fatalf("optoas: t is nil")
 	}
 
+	// avoid constant conversions in switches below
+	const (
+		OMINUS_ = uint32(gc.OMINUS) << 16
+		OLSH_   = uint32(gc.OLSH) << 16
+		ORSH_   = uint32(gc.ORSH) << 16
+		OADD_   = uint32(gc.OADD) << 16
+		OSUB_   = uint32(gc.OSUB) << 16
+		OMUL_   = uint32(gc.OMUL) << 16
+		ODIV_   = uint32(gc.ODIV) << 16
+		OOR_    = uint32(gc.OOR) << 16
+		OAND_   = uint32(gc.OAND) << 16
+		OXOR_   = uint32(gc.OXOR) << 16
+		OEQ_    = uint32(gc.OEQ) << 16
+		ONE_    = uint32(gc.ONE) << 16
+		OLT_    = uint32(gc.OLT) << 16
+		OLE_    = uint32(gc.OLE) << 16
+		OGE_    = uint32(gc.OGE) << 16
+		OGT_    = uint32(gc.OGT) << 16
+		OCMP_   = uint32(gc.OCMP) << 16
+		OAS_    = uint32(gc.OAS) << 16
+		OHMUL_  = uint32(gc.OHMUL) << 16
+	)
+
 	a := int(obj.AXXX)
 	switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) {
 	default:
-		gc.Fatal("optoas: no entry for op=%v type=%v", gc.Oconv(int(op), 0), t)
-
-	case gc.OEQ<<16 | gc.TBOOL,
-		gc.OEQ<<16 | gc.TINT8,
-		gc.OEQ<<16 | gc.TUINT8,
-		gc.OEQ<<16 | gc.TINT16,
-		gc.OEQ<<16 | gc.TUINT16,
-		gc.OEQ<<16 | gc.TINT32,
-		gc.OEQ<<16 | gc.TUINT32,
-		gc.OEQ<<16 | gc.TINT64,
-		gc.OEQ<<16 | gc.TUINT64,
-		gc.OEQ<<16 | gc.TPTR32,
-		gc.OEQ<<16 | gc.TPTR64,
-		gc.OEQ<<16 | gc.TFLOAT32,
-		gc.OEQ<<16 | gc.TFLOAT64:
+		gc.Fatalf("optoas: no entry for op=%v type=%v", gc.Oconv(int(op), 0), t)
+
+	case OEQ_ | gc.TBOOL,
+		OEQ_ | gc.TINT8,
+		OEQ_ | gc.TUINT8,
+		OEQ_ | gc.TINT16,
+		OEQ_ | gc.TUINT16,
+		OEQ_ | gc.TINT32,
+		OEQ_ | gc.TUINT32,
+		OEQ_ | gc.TINT64,
+		OEQ_ | gc.TUINT64,
+		OEQ_ | gc.TPTR32,
+		OEQ_ | gc.TPTR64,
+		OEQ_ | gc.TFLOAT32,
+		OEQ_ | gc.TFLOAT64:
 		a = ppc64.ABEQ
 
-	case gc.ONE<<16 | gc.TBOOL,
-		gc.ONE<<16 | gc.TINT8,
-		gc.ONE<<16 | gc.TUINT8,
-		gc.ONE<<16 | gc.TINT16,
-		gc.ONE<<16 | gc.TUINT16,
-		gc.ONE<<16 | gc.TINT32,
-		gc.ONE<<16 | gc.TUINT32,
-		gc.ONE<<16 | gc.TINT64,
-		gc.ONE<<16 | gc.TUINT64,
-		gc.ONE<<16 | gc.TPTR32,
-		gc.ONE<<16 | gc.TPTR64,
-		gc.ONE<<16 | gc.TFLOAT32,
-		gc.ONE<<16 | gc.TFLOAT64:
+	case ONE_ | gc.TBOOL,
+		ONE_ | gc.TINT8,
+		ONE_ | gc.TUINT8,
+		ONE_ | gc.TINT16,
+		ONE_ | gc.TUINT16,
+		ONE_ | gc.TINT32,
+		ONE_ | gc.TUINT32,
+		ONE_ | gc.TINT64,
+		ONE_ | gc.TUINT64,
+		ONE_ | gc.TPTR32,
+		ONE_ | gc.TPTR64,
+		ONE_ | gc.TFLOAT32,
+		ONE_ | gc.TFLOAT64:
 		a = ppc64.ABNE
 
-	case gc.OLT<<16 | gc.TINT8, // ACMP
-		gc.OLT<<16 | gc.TINT16,
-		gc.OLT<<16 | gc.TINT32,
-		gc.OLT<<16 | gc.TINT64,
-		gc.OLT<<16 | gc.TUINT8,
+	case OLT_ | gc.TINT8, // ACMP
+		OLT_ | gc.TINT16,
+		OLT_ | gc.TINT32,
+		OLT_ | gc.TINT64,
+		OLT_ | gc.TUINT8,
 		// ACMPU
-		gc.OLT<<16 | gc.TUINT16,
-		gc.OLT<<16 | gc.TUINT32,
-		gc.OLT<<16 | gc.TUINT64,
-		gc.OLT<<16 | gc.TFLOAT32,
+		OLT_ | gc.TUINT16,
+		OLT_ | gc.TUINT32,
+		OLT_ | gc.TUINT64,
+		OLT_ | gc.TFLOAT32,
 		// AFCMPU
-		gc.OLT<<16 | gc.TFLOAT64:
+		OLT_ | gc.TFLOAT64:
 		a = ppc64.ABLT
 
-	case gc.OLE<<16 | gc.TINT8, // ACMP
-		gc.OLE<<16 | gc.TINT16,
-		gc.OLE<<16 | gc.TINT32,
-		gc.OLE<<16 | gc.TINT64,
-		gc.OLE<<16 | gc.TUINT8,
+	case OLE_ | gc.TINT8, // ACMP
+		OLE_ | gc.TINT16,
+		OLE_ | gc.TINT32,
+		OLE_ | gc.TINT64,
+		OLE_ | gc.TUINT8,
 		// ACMPU
-		gc.OLE<<16 | gc.TUINT16,
-		gc.OLE<<16 | gc.TUINT32,
-		gc.OLE<<16 | gc.TUINT64:
+		OLE_ | gc.TUINT16,
+		OLE_ | gc.TUINT32,
+		OLE_ | gc.TUINT64:
 		// No OLE for floats, because it mishandles NaN.
 		// Front end must reverse comparison or use OLT and OEQ together.
 		a = ppc64.ABLE
 
-	case gc.OGT<<16 | gc.TINT8,
-		gc.OGT<<16 | gc.TINT16,
-		gc.OGT<<16 | gc.TINT32,
-		gc.OGT<<16 | gc.TINT64,
-		gc.OGT<<16 | gc.TUINT8,
-		gc.OGT<<16 | gc.TUINT16,
-		gc.OGT<<16 | gc.TUINT32,
-		gc.OGT<<16 | gc.TUINT64,
-		gc.OGT<<16 | gc.TFLOAT32,
-		gc.OGT<<16 | gc.TFLOAT64:
+	case OGT_ | gc.TINT8,
+		OGT_ | gc.TINT16,
+		OGT_ | gc.TINT32,
+		OGT_ | gc.TINT64,
+		OGT_ | gc.TUINT8,
+		OGT_ | gc.TUINT16,
+		OGT_ | gc.TUINT32,
+		OGT_ | gc.TUINT64,
+		OGT_ | gc.TFLOAT32,
+		OGT_ | gc.TFLOAT64:
 		a = ppc64.ABGT
 
-	case gc.OGE<<16 | gc.TINT8,
-		gc.OGE<<16 | gc.TINT16,
-		gc.OGE<<16 | gc.TINT32,
-		gc.OGE<<16 | gc.TINT64,
-		gc.OGE<<16 | gc.TUINT8,
-		gc.OGE<<16 | gc.TUINT16,
-		gc.OGE<<16 | gc.TUINT32,
-		gc.OGE<<16 | gc.TUINT64:
+	case OGE_ | gc.TINT8,
+		OGE_ | gc.TINT16,
+		OGE_ | gc.TINT32,
+		OGE_ | gc.TINT64,
+		OGE_ | gc.TUINT8,
+		OGE_ | gc.TUINT16,
+		OGE_ | gc.TUINT32,
+		OGE_ | gc.TUINT64:
 		// No OGE for floats, because it mishandles NaN.
 		// Front end must reverse comparison or use OLT and OEQ together.
 		a = ppc64.ABGE
 
-	case gc.OCMP<<16 | gc.TBOOL,
-		gc.OCMP<<16 | gc.TINT8,
-		gc.OCMP<<16 | gc.TINT16,
-		gc.OCMP<<16 | gc.TINT32,
-		gc.OCMP<<16 | gc.TPTR32,
-		gc.OCMP<<16 | gc.TINT64:
+	case OCMP_ | gc.TBOOL,
+		OCMP_ | gc.TINT8,
+		OCMP_ | gc.TINT16,
+		OCMP_ | gc.TINT32,
+		OCMP_ | gc.TPTR32,
+		OCMP_ | gc.TINT64:
 		a = ppc64.ACMP
 
-	case gc.OCMP<<16 | gc.TUINT8,
-		gc.OCMP<<16 | gc.TUINT16,
-		gc.OCMP<<16 | gc.TUINT32,
-		gc.OCMP<<16 | gc.TUINT64,
-		gc.OCMP<<16 | gc.TPTR64:
+	case OCMP_ | gc.TUINT8,
+		OCMP_ | gc.TUINT16,
+		OCMP_ | gc.TUINT32,
+		OCMP_ | gc.TUINT64,
+		OCMP_ | gc.TPTR64:
 		a = ppc64.ACMPU
 
-	case gc.OCMP<<16 | gc.TFLOAT32,
-		gc.OCMP<<16 | gc.TFLOAT64:
+	case OCMP_ | gc.TFLOAT32,
+		OCMP_ | gc.TFLOAT64:
 		a = ppc64.AFCMPU
 
-	case gc.OAS<<16 | gc.TBOOL,
-		gc.OAS<<16 | gc.TINT8:
+	case OAS_ | gc.TBOOL,
+		OAS_ | gc.TINT8:
 		a = ppc64.AMOVB
 
-	case gc.OAS<<16 | gc.TUINT8:
+	case OAS_ | gc.TUINT8:
 		a = ppc64.AMOVBZ
 
-	case gc.OAS<<16 | gc.TINT16:
+	case OAS_ | gc.TINT16:
 		a = ppc64.AMOVH
 
-	case gc.OAS<<16 | gc.TUINT16:
+	case OAS_ | gc.TUINT16:
 		a = ppc64.AMOVHZ
 
-	case gc.OAS<<16 | gc.TINT32:
+	case OAS_ | gc.TINT32:
 		a = ppc64.AMOVW
 
-	case gc.OAS<<16 | gc.TUINT32,
-		gc.OAS<<16 | gc.TPTR32:
+	case OAS_ | gc.TUINT32,
+		OAS_ | gc.TPTR32:
 		a = ppc64.AMOVWZ
 
-	case gc.OAS<<16 | gc.TINT64,
-		gc.OAS<<16 | gc.TUINT64,
-		gc.OAS<<16 | gc.TPTR64:
+	case OAS_ | gc.TINT64,
+		OAS_ | gc.TUINT64,
+		OAS_ | gc.TPTR64:
 		a = ppc64.AMOVD
 
-	case gc.OAS<<16 | gc.TFLOAT32:
+	case OAS_ | gc.TFLOAT32:
 		a = ppc64.AFMOVS
 
-	case gc.OAS<<16 | gc.TFLOAT64:
+	case OAS_ | gc.TFLOAT64:
 		a = ppc64.AFMOVD
 
-	case gc.OADD<<16 | gc.TINT8,
-		gc.OADD<<16 | gc.TUINT8,
-		gc.OADD<<16 | gc.TINT16,
-		gc.OADD<<16 | gc.TUINT16,
-		gc.OADD<<16 | gc.TINT32,
-		gc.OADD<<16 | gc.TUINT32,
-		gc.OADD<<16 | gc.TPTR32,
-		gc.OADD<<16 | gc.TINT64,
-		gc.OADD<<16 | gc.TUINT64,
-		gc.OADD<<16 | gc.TPTR64:
+	case OADD_ | gc.TINT8,
+		OADD_ | gc.TUINT8,
+		OADD_ | gc.TINT16,
+		OADD_ | gc.TUINT16,
+		OADD_ | gc.TINT32,
+		OADD_ | gc.TUINT32,
+		OADD_ | gc.TPTR32,
+		OADD_ | gc.TINT64,
+		OADD_ | gc.TUINT64,
+		OADD_ | gc.TPTR64:
 		a = ppc64.AADD
 
-	case gc.OADD<<16 | gc.TFLOAT32:
+	case OADD_ | gc.TFLOAT32:
 		a = ppc64.AFADDS
 
-	case gc.OADD<<16 | gc.TFLOAT64:
+	case OADD_ | gc.TFLOAT64:
 		a = ppc64.AFADD
 
-	case gc.OSUB<<16 | gc.TINT8,
-		gc.OSUB<<16 | gc.TUINT8,
-		gc.OSUB<<16 | gc.TINT16,
-		gc.OSUB<<16 | gc.TUINT16,
-		gc.OSUB<<16 | gc.TINT32,
-		gc.OSUB<<16 | gc.TUINT32,
-		gc.OSUB<<16 | gc.TPTR32,
-		gc.OSUB<<16 | gc.TINT64,
-		gc.OSUB<<16 | gc.TUINT64,
-		gc.OSUB<<16 | gc.TPTR64:
+	case OSUB_ | gc.TINT8,
+		OSUB_ | gc.TUINT8,
+		OSUB_ | gc.TINT16,
+		OSUB_ | gc.TUINT16,
+		OSUB_ | gc.TINT32,
+		OSUB_ | gc.TUINT32,
+		OSUB_ | gc.TPTR32,
+		OSUB_ | gc.TINT64,
+		OSUB_ | gc.TUINT64,
+		OSUB_ | gc.TPTR64:
 		a = ppc64.ASUB
 
-	case gc.OSUB<<16 | gc.TFLOAT32:
+	case OSUB_ | gc.TFLOAT32:
 		a = ppc64.AFSUBS
 
-	case gc.OSUB<<16 | gc.TFLOAT64:
+	case OSUB_ | gc.TFLOAT64:
 		a = ppc64.AFSUB
 
-	case gc.OMINUS<<16 | gc.TINT8,
-		gc.OMINUS<<16 | gc.TUINT8,
-		gc.OMINUS<<16 | gc.TINT16,
-		gc.OMINUS<<16 | gc.TUINT16,
-		gc.OMINUS<<16 | gc.TINT32,
-		gc.OMINUS<<16 | gc.TUINT32,
-		gc.OMINUS<<16 | gc.TPTR32,
-		gc.OMINUS<<16 | gc.TINT64,
-		gc.OMINUS<<16 | gc.TUINT64,
-		gc.OMINUS<<16 | gc.TPTR64:
+	case OMINUS_ | gc.TINT8,
+		OMINUS_ | gc.TUINT8,
+		OMINUS_ | gc.TINT16,
+		OMINUS_ | gc.TUINT16,
+		OMINUS_ | gc.TINT32,
+		OMINUS_ | gc.TUINT32,
+		OMINUS_ | gc.TPTR32,
+		OMINUS_ | gc.TINT64,
+		OMINUS_ | gc.TUINT64,
+		OMINUS_ | gc.TPTR64:
 		a = ppc64.ANEG
 
-	case gc.OAND<<16 | gc.TINT8,
-		gc.OAND<<16 | gc.TUINT8,
-		gc.OAND<<16 | gc.TINT16,
-		gc.OAND<<16 | gc.TUINT16,
-		gc.OAND<<16 | gc.TINT32,
-		gc.OAND<<16 | gc.TUINT32,
-		gc.OAND<<16 | gc.TPTR32,
-		gc.OAND<<16 | gc.TINT64,
-		gc.OAND<<16 | gc.TUINT64,
-		gc.OAND<<16 | gc.TPTR64:
+	case OAND_ | gc.TINT8,
+		OAND_ | gc.TUINT8,
+		OAND_ | gc.TINT16,
+		OAND_ | gc.TUINT16,
+		OAND_ | gc.TINT32,
+		OAND_ | gc.TUINT32,
+		OAND_ | gc.TPTR32,
+		OAND_ | gc.TINT64,
+		OAND_ | gc.TUINT64,
+		OAND_ | gc.TPTR64:
 		a = ppc64.AAND
 
-	case gc.OOR<<16 | gc.TINT8,
-		gc.OOR<<16 | gc.TUINT8,
-		gc.OOR<<16 | gc.TINT16,
-		gc.OOR<<16 | gc.TUINT16,
-		gc.OOR<<16 | gc.TINT32,
-		gc.OOR<<16 | gc.TUINT32,
-		gc.OOR<<16 | gc.TPTR32,
-		gc.OOR<<16 | gc.TINT64,
-		gc.OOR<<16 | gc.TUINT64,
-		gc.OOR<<16 | gc.TPTR64:
+	case OOR_ | gc.TINT8,
+		OOR_ | gc.TUINT8,
+		OOR_ | gc.TINT16,
+		OOR_ | gc.TUINT16,
+		OOR_ | gc.TINT32,
+		OOR_ | gc.TUINT32,
+		OOR_ | gc.TPTR32,
+		OOR_ | gc.TINT64,
+		OOR_ | gc.TUINT64,
+		OOR_ | gc.TPTR64:
 		a = ppc64.AOR
 
-	case gc.OXOR<<16 | gc.TINT8,
-		gc.OXOR<<16 | gc.TUINT8,
-		gc.OXOR<<16 | gc.TINT16,
-		gc.OXOR<<16 | gc.TUINT16,
-		gc.OXOR<<16 | gc.TINT32,
-		gc.OXOR<<16 | gc.TUINT32,
-		gc.OXOR<<16 | gc.TPTR32,
-		gc.OXOR<<16 | gc.TINT64,
-		gc.OXOR<<16 | gc.TUINT64,
-		gc.OXOR<<16 | gc.TPTR64:
+	case OXOR_ | gc.TINT8,
+		OXOR_ | gc.TUINT8,
+		OXOR_ | gc.TINT16,
+		OXOR_ | gc.TUINT16,
+		OXOR_ | gc.TINT32,
+		OXOR_ | gc.TUINT32,
+		OXOR_ | gc.TPTR32,
+		OXOR_ | gc.TINT64,
+		OXOR_ | gc.TUINT64,
+		OXOR_ | gc.TPTR64:
 		a = ppc64.AXOR
 
 		// TODO(minux): handle rotates
@@ -906,30 +942,30 @@ func optoas(op int, t *gc.Type) int {
 	//	a = 0//???; RLDC?
 	//	break;
 
-	case gc.OLSH<<16 | gc.TINT8,
-		gc.OLSH<<16 | gc.TUINT8,
-		gc.OLSH<<16 | gc.TINT16,
-		gc.OLSH<<16 | gc.TUINT16,
-		gc.OLSH<<16 | gc.TINT32,
-		gc.OLSH<<16 | gc.TUINT32,
-		gc.OLSH<<16 | gc.TPTR32,
-		gc.OLSH<<16 | gc.TINT64,
-		gc.OLSH<<16 | gc.TUINT64,
-		gc.OLSH<<16 | gc.TPTR64:
+	case OLSH_ | gc.TINT8,
+		OLSH_ | gc.TUINT8,
+		OLSH_ | gc.TINT16,
+		OLSH_ | gc.TUINT16,
+		OLSH_ | gc.TINT32,
+		OLSH_ | gc.TUINT32,
+		OLSH_ | gc.TPTR32,
+		OLSH_ | gc.TINT64,
+		OLSH_ | gc.TUINT64,
+		OLSH_ | gc.TPTR64:
 		a = ppc64.ASLD
 
-	case gc.ORSH<<16 | gc.TUINT8,
-		gc.ORSH<<16 | gc.TUINT16,
-		gc.ORSH<<16 | gc.TUINT32,
-		gc.ORSH<<16 | gc.TPTR32,
-		gc.ORSH<<16 | gc.TUINT64,
-		gc.ORSH<<16 | gc.TPTR64:
+	case ORSH_ | gc.TUINT8,
+		ORSH_ | gc.TUINT16,
+		ORSH_ | gc.TUINT32,
+		ORSH_ | gc.TPTR32,
+		ORSH_ | gc.TUINT64,
+		ORSH_ | gc.TPTR64:
 		a = ppc64.ASRD
 
-	case gc.ORSH<<16 | gc.TINT8,
-		gc.ORSH<<16 | gc.TINT16,
-		gc.ORSH<<16 | gc.TINT32,
-		gc.ORSH<<16 | gc.TINT64:
+	case ORSH_ | gc.TINT8,
+		ORSH_ | gc.TINT16,
+		ORSH_ | gc.TINT32,
+		ORSH_ | gc.TINT64:
 		a = ppc64.ASRAD
 
 		// TODO(minux): handle rotates
@@ -944,53 +980,53 @@ func optoas(op int, t *gc.Type) int {
 	//	a = 0//??? RLDC??
 	//	break;
 
-	case gc.OHMUL<<16 | gc.TINT64:
+	case OHMUL_ | gc.TINT64:
 		a = ppc64.AMULHD
 
-	case gc.OHMUL<<16 | gc.TUINT64,
-		gc.OHMUL<<16 | gc.TPTR64:
+	case OHMUL_ | gc.TUINT64,
+		OHMUL_ | gc.TPTR64:
 		a = ppc64.AMULHDU
 
-	case gc.OMUL<<16 | gc.TINT8,
-		gc.OMUL<<16 | gc.TINT16,
-		gc.OMUL<<16 | gc.TINT32,
-		gc.OMUL<<16 | gc.TINT64:
+	case OMUL_ | gc.TINT8,
+		OMUL_ | gc.TINT16,
+		OMUL_ | gc.TINT32,
+		OMUL_ | gc.TINT64:
 		a = ppc64.AMULLD
 
-	case gc.OMUL<<16 | gc.TUINT8,
-		gc.OMUL<<16 | gc.TUINT16,
-		gc.OMUL<<16 | gc.TUINT32,
-		gc.OMUL<<16 | gc.TPTR32,
+	case OMUL_ | gc.TUINT8,
+		OMUL_ | gc.TUINT16,
+		OMUL_ | gc.TUINT32,
+		OMUL_ | gc.TPTR32,
 		// don't use word multiply, the high 32-bit are undefined.
-		gc.OMUL<<16 | gc.TUINT64,
-		gc.OMUL<<16 | gc.TPTR64:
+		OMUL_ | gc.TUINT64,
+		OMUL_ | gc.TPTR64:
 		// for 64-bit multiplies, signedness doesn't matter.
 		a = ppc64.AMULLD
 
-	case gc.OMUL<<16 | gc.TFLOAT32:
+	case OMUL_ | gc.TFLOAT32:
 		a = ppc64.AFMULS
 
-	case gc.OMUL<<16 | gc.TFLOAT64:
+	case OMUL_ | gc.TFLOAT64:
 		a = ppc64.AFMUL
 
-	case gc.ODIV<<16 | gc.TINT8,
-		gc.ODIV<<16 | gc.TINT16,
-		gc.ODIV<<16 | gc.TINT32,
-		gc.ODIV<<16 | gc.TINT64:
+	case ODIV_ | gc.TINT8,
+		ODIV_ | gc.TINT16,
+		ODIV_ | gc.TINT32,
+		ODIV_ | gc.TINT64:
 		a = ppc64.ADIVD
 
-	case gc.ODIV<<16 | gc.TUINT8,
-		gc.ODIV<<16 | gc.TUINT16,
-		gc.ODIV<<16 | gc.TUINT32,
-		gc.ODIV<<16 | gc.TPTR32,
-		gc.ODIV<<16 | gc.TUINT64,
-		gc.ODIV<<16 | gc.TPTR64:
+	case ODIV_ | gc.TUINT8,
+		ODIV_ | gc.TUINT16,
+		ODIV_ | gc.TUINT32,
+		ODIV_ | gc.TPTR32,
+		ODIV_ | gc.TUINT64,
+		ODIV_ | gc.TPTR64:
 		a = ppc64.ADIVDU
 
-	case gc.ODIV<<16 | gc.TFLOAT32:
+	case ODIV_ | gc.TFLOAT32:
 		a = ppc64.AFDIVS
 
-	case gc.ODIV<<16 | gc.TFLOAT64:
+	case ODIV_ | gc.TFLOAT64:
 		a = ppc64.AFDIV
 	}
 
diff --git a/src/cmd/compile/internal/ppc64/peep.go b/src/cmd/compile/internal/ppc64/peep.go
index 9c3f1ed..1ff3109 100644
--- a/src/cmd/compile/internal/ppc64/peep.go
+++ b/src/cmd/compile/internal/ppc64/peep.go
@@ -952,7 +952,9 @@ func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
 	case obj.APCDATA,
 		obj.AFUNCDATA,
 		obj.AVARDEF,
-		obj.AVARKILL:
+		obj.AVARKILL,
+		obj.AVARLIVE,
+		obj.AUSEFIELD:
 		return 0
 	}
 }
diff --git a/src/cmd/compile/internal/ppc64/prog.go b/src/cmd/compile/internal/ppc64/prog.go
index 328b2ce..6b48256 100644
--- a/src/cmd/compile/internal/ppc64/prog.go
+++ b/src/cmd/compile/internal/ppc64/prog.go
@@ -25,83 +25,84 @@ const (
 //
 // The table is formatted for 8-space tabs.
 var progtable = [ppc64.ALAST]obj.ProgInfo{
-	obj.ATYPE:     {gc.Pseudo | gc.Skip, 0, 0, 0},
-	obj.ATEXT:     {gc.Pseudo, 0, 0, 0},
-	obj.AFUNCDATA: {gc.Pseudo, 0, 0, 0},
-	obj.APCDATA:   {gc.Pseudo, 0, 0, 0},
-	obj.AUNDEF:    {gc.Break, 0, 0, 0},
-	obj.AUSEFIELD: {gc.OK, 0, 0, 0},
-	obj.ACHECKNIL: {gc.LeftRead, 0, 0, 0},
-	obj.AVARDEF:   {gc.Pseudo | gc.RightWrite, 0, 0, 0},
-	obj.AVARKILL:  {gc.Pseudo | gc.RightWrite, 0, 0, 0},
+	obj.ATYPE:     {Flags: gc.Pseudo | gc.Skip},
+	obj.ATEXT:     {Flags: gc.Pseudo},
+	obj.AFUNCDATA: {Flags: gc.Pseudo},
+	obj.APCDATA:   {Flags: gc.Pseudo},
+	obj.AUNDEF:    {Flags: gc.Break},
+	obj.AUSEFIELD: {Flags: gc.OK},
+	obj.ACHECKNIL: {Flags: gc.LeftRead},
+	obj.AVARDEF:   {Flags: gc.Pseudo | gc.RightWrite},
+	obj.AVARKILL:  {Flags: gc.Pseudo | gc.RightWrite},
+	obj.AVARLIVE:  {Flags: gc.Pseudo | gc.LeftRead},
 
 	// NOP is an internal no-op that also stands
 	// for USED and SET annotations, not the Power opcode.
-	obj.ANOP: {gc.LeftRead | gc.RightWrite, 0, 0, 0},
+	obj.ANOP: {Flags: gc.LeftRead | gc.RightWrite},
 
 	// Integer
-	ppc64.AADD:    {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.ASUB:    {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.ANEG:    {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.AAND:    {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.AOR:     {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.AXOR:    {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.AMULLD:  {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.AMULLW:  {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.AMULHD:  {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.AMULHDU: {gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.ADIVD:   {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.ADIVDU:  {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.ASLD:    {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.ASRD:    {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.ASRAD:   {gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.ACMP:    {gc.SizeQ | gc.LeftRead | gc.RightRead, 0, 0, 0},
-	ppc64.ACMPU:   {gc.SizeQ | gc.LeftRead | gc.RightRead, 0, 0, 0},
-	ppc64.ATD:     {gc.SizeQ | gc.RightRead, 0, 0, 0},
+	ppc64.AADD:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.ASUB:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.ANEG:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.AAND:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.AOR:     {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.AXOR:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.AMULLD:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.AMULLW:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.AMULHD:  {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.AMULHDU: {Flags: gc.SizeL | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.ADIVD:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.ADIVDU:  {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.ASLD:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.ASRD:    {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.ASRAD:   {Flags: gc.SizeQ | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.ACMP:    {Flags: gc.SizeQ | gc.LeftRead | gc.RightRead},
+	ppc64.ACMPU:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightRead},
+	ppc64.ATD:     {Flags: gc.SizeQ | gc.RightRead},
 
 	// Floating point.
-	ppc64.AFADD:   {gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.AFADDS:  {gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.AFSUB:   {gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.AFSUBS:  {gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.AFMUL:   {gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.AFMULS:  {gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.AFDIV:   {gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.AFDIVS:  {gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.AFCTIDZ: {gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.AFCFID:  {gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite, 0, 0, 0},
-	ppc64.AFCMPU:  {gc.SizeD | gc.LeftRead | gc.RightRead, 0, 0, 0},
-	ppc64.AFRSP:   {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
+	ppc64.AFADD:   {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.AFADDS:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.AFSUB:   {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.AFSUBS:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.AFMUL:   {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.AFMULS:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.AFDIV:   {Flags: gc.SizeD | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.AFDIVS:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.AFCTIDZ: {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.AFCFID:  {Flags: gc.SizeF | gc.LeftRead | gc.RegRead | gc.RightWrite},
+	ppc64.AFCMPU:  {Flags: gc.SizeD | gc.LeftRead | gc.RightRead},
+	ppc64.AFRSP:   {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
 
 	// Moves
-	ppc64.AMOVB:  {gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
-	ppc64.AMOVBU: {gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc, 0, 0, 0},
-	ppc64.AMOVBZ: {gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
-	ppc64.AMOVH:  {gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
-	ppc64.AMOVHU: {gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc, 0, 0, 0},
-	ppc64.AMOVHZ: {gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
-	ppc64.AMOVW:  {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
+	ppc64.AMOVB:  {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+	ppc64.AMOVBU: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc},
+	ppc64.AMOVBZ: {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+	ppc64.AMOVH:  {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+	ppc64.AMOVHU: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc},
+	ppc64.AMOVHZ: {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+	ppc64.AMOVW:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
 
 	// there is no AMOVWU.
-	ppc64.AMOVWZU: {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc, 0, 0, 0},
-	ppc64.AMOVWZ:  {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
-	ppc64.AMOVD:   {gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
-	ppc64.AMOVDU:  {gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move | gc.PostInc, 0, 0, 0},
-	ppc64.AFMOVS:  {gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv, 0, 0, 0},
-	ppc64.AFMOVD:  {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
+	ppc64.AMOVWZU: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv | gc.PostInc},
+	ppc64.AMOVWZ:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+	ppc64.AMOVD:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move},
+	ppc64.AMOVDU:  {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.Move | gc.PostInc},
+	ppc64.AFMOVS:  {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move | gc.Conv},
+	ppc64.AFMOVD:  {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
 
 	// Jumps
-	ppc64.ABR:     {gc.Jump | gc.Break, 0, 0, 0},
-	ppc64.ABL:     {gc.Call, 0, 0, 0},
-	ppc64.ABEQ:    {gc.Cjmp, 0, 0, 0},
-	ppc64.ABNE:    {gc.Cjmp, 0, 0, 0},
-	ppc64.ABGE:    {gc.Cjmp, 0, 0, 0},
-	ppc64.ABLT:    {gc.Cjmp, 0, 0, 0},
-	ppc64.ABGT:    {gc.Cjmp, 0, 0, 0},
-	ppc64.ABLE:    {gc.Cjmp, 0, 0, 0},
-	obj.ARET:      {gc.Break, 0, 0, 0},
-	obj.ADUFFZERO: {gc.Call, 0, 0, 0},
-	obj.ADUFFCOPY: {gc.Call, 0, 0, 0},
+	ppc64.ABR:     {Flags: gc.Jump | gc.Break},
+	ppc64.ABL:     {Flags: gc.Call},
+	ppc64.ABEQ:    {Flags: gc.Cjmp},
+	ppc64.ABNE:    {Flags: gc.Cjmp},
+	ppc64.ABGE:    {Flags: gc.Cjmp},
+	ppc64.ABLT:    {Flags: gc.Cjmp},
+	ppc64.ABGT:    {Flags: gc.Cjmp},
+	ppc64.ABLE:    {Flags: gc.Cjmp},
+	obj.ARET:      {Flags: gc.Break},
+	obj.ADUFFZERO: {Flags: gc.Call},
+	obj.ADUFFCOPY: {Flags: gc.Call},
 }
 
 var initproginfo_initialized int
@@ -139,7 +140,7 @@ func proginfo(p *obj.Prog) {
 	info := &p.Info
 	*info = progtable[p.As]
 	if info.Flags == 0 {
-		gc.Fatal("proginfo: unknown instruction %v", p)
+		gc.Fatalf("proginfo: unknown instruction %v", p)
 	}
 
 	if (info.Flags&gc.RegRead != 0) && p.Reg == 0 {
@@ -183,89 +184,89 @@ func proginfo(p *obj.Prog) {
 // for the "base" form of each instruction.  On the first call to
 // as2variant or variant2as, we'll add the variants to the table.
 var varianttable = [ppc64.ALAST][4]int{
-	ppc64.AADD:     [4]int{ppc64.AADD, ppc64.AADDCC, ppc64.AADDV, ppc64.AADDVCC},
-	ppc64.AADDC:    [4]int{ppc64.AADDC, ppc64.AADDCCC, ppc64.AADDCV, ppc64.AADDCVCC},
-	ppc64.AADDE:    [4]int{ppc64.AADDE, ppc64.AADDECC, ppc64.AADDEV, ppc64.AADDEVCC},
-	ppc64.AADDME:   [4]int{ppc64.AADDME, ppc64.AADDMECC, ppc64.AADDMEV, ppc64.AADDMEVCC},
-	ppc64.AADDZE:   [4]int{ppc64.AADDZE, ppc64.AADDZECC, ppc64.AADDZEV, ppc64.AADDZEVCC},
-	ppc64.AAND:     [4]int{ppc64.AAND, ppc64.AANDCC, 0, 0},
-	ppc64.AANDN:    [4]int{ppc64.AANDN, ppc64.AANDNCC, 0, 0},
-	ppc64.ACNTLZD:  [4]int{ppc64.ACNTLZD, ppc64.ACNTLZDCC, 0, 0},
-	ppc64.ACNTLZW:  [4]int{ppc64.ACNTLZW, ppc64.ACNTLZWCC, 0, 0},
-	ppc64.ADIVD:    [4]int{ppc64.ADIVD, ppc64.ADIVDCC, ppc64.ADIVDV, ppc64.ADIVDVCC},
-	ppc64.ADIVDU:   [4]int{ppc64.ADIVDU, ppc64.ADIVDUCC, ppc64.ADIVDUV, ppc64.ADIVDUVCC},
-	ppc64.ADIVW:    [4]int{ppc64.ADIVW, ppc64.ADIVWCC, ppc64.ADIVWV, ppc64.ADIVWVCC},
-	ppc64.ADIVWU:   [4]int{ppc64.ADIVWU, ppc64.ADIVWUCC, ppc64.ADIVWUV, ppc64.ADIVWUVCC},
-	ppc64.AEQV:     [4]int{ppc64.AEQV, ppc64.AEQVCC, 0, 0},
-	ppc64.AEXTSB:   [4]int{ppc64.AEXTSB, ppc64.AEXTSBCC, 0, 0},
-	ppc64.AEXTSH:   [4]int{ppc64.AEXTSH, ppc64.AEXTSHCC, 0, 0},
-	ppc64.AEXTSW:   [4]int{ppc64.AEXTSW, ppc64.AEXTSWCC, 0, 0},
-	ppc64.AFABS:    [4]int{ppc64.AFABS, ppc64.AFABSCC, 0, 0},
-	ppc64.AFADD:    [4]int{ppc64.AFADD, ppc64.AFADDCC, 0, 0},
-	ppc64.AFADDS:   [4]int{ppc64.AFADDS, ppc64.AFADDSCC, 0, 0},
-	ppc64.AFCFID:   [4]int{ppc64.AFCFID, ppc64.AFCFIDCC, 0, 0},
-	ppc64.AFCTID:   [4]int{ppc64.AFCTID, ppc64.AFCTIDCC, 0, 0},
-	ppc64.AFCTIDZ:  [4]int{ppc64.AFCTIDZ, ppc64.AFCTIDZCC, 0, 0},
-	ppc64.AFCTIW:   [4]int{ppc64.AFCTIW, ppc64.AFCTIWCC, 0, 0},
-	ppc64.AFCTIWZ:  [4]int{ppc64.AFCTIWZ, ppc64.AFCTIWZCC, 0, 0},
-	ppc64.AFDIV:    [4]int{ppc64.AFDIV, ppc64.AFDIVCC, 0, 0},
-	ppc64.AFDIVS:   [4]int{ppc64.AFDIVS, ppc64.AFDIVSCC, 0, 0},
-	ppc64.AFMADD:   [4]int{ppc64.AFMADD, ppc64.AFMADDCC, 0, 0},
-	ppc64.AFMADDS:  [4]int{ppc64.AFMADDS, ppc64.AFMADDSCC, 0, 0},
-	ppc64.AFMOVD:   [4]int{ppc64.AFMOVD, ppc64.AFMOVDCC, 0, 0},
-	ppc64.AFMSUB:   [4]int{ppc64.AFMSUB, ppc64.AFMSUBCC, 0, 0},
-	ppc64.AFMSUBS:  [4]int{ppc64.AFMSUBS, ppc64.AFMSUBSCC, 0, 0},
-	ppc64.AFMUL:    [4]int{ppc64.AFMUL, ppc64.AFMULCC, 0, 0},
-	ppc64.AFMULS:   [4]int{ppc64.AFMULS, ppc64.AFMULSCC, 0, 0},
-	ppc64.AFNABS:   [4]int{ppc64.AFNABS, ppc64.AFNABSCC, 0, 0},
-	ppc64.AFNEG:    [4]int{ppc64.AFNEG, ppc64.AFNEGCC, 0, 0},
-	ppc64.AFNMADD:  [4]int{ppc64.AFNMADD, ppc64.AFNMADDCC, 0, 0},
-	ppc64.AFNMADDS: [4]int{ppc64.AFNMADDS, ppc64.AFNMADDSCC, 0, 0},
-	ppc64.AFNMSUB:  [4]int{ppc64.AFNMSUB, ppc64.AFNMSUBCC, 0, 0},
-	ppc64.AFNMSUBS: [4]int{ppc64.AFNMSUBS, ppc64.AFNMSUBSCC, 0, 0},
-	ppc64.AFRES:    [4]int{ppc64.AFRES, ppc64.AFRESCC, 0, 0},
-	ppc64.AFRSP:    [4]int{ppc64.AFRSP, ppc64.AFRSPCC, 0, 0},
-	ppc64.AFRSQRTE: [4]int{ppc64.AFRSQRTE, ppc64.AFRSQRTECC, 0, 0},
-	ppc64.AFSEL:    [4]int{ppc64.AFSEL, ppc64.AFSELCC, 0, 0},
-	ppc64.AFSQRT:   [4]int{ppc64.AFSQRT, ppc64.AFSQRTCC, 0, 0},
-	ppc64.AFSQRTS:  [4]int{ppc64.AFSQRTS, ppc64.AFSQRTSCC, 0, 0},
-	ppc64.AFSUB:    [4]int{ppc64.AFSUB, ppc64.AFSUBCC, 0, 0},
-	ppc64.AFSUBS:   [4]int{ppc64.AFSUBS, ppc64.AFSUBSCC, 0, 0},
-	ppc64.AMTFSB0:  [4]int{ppc64.AMTFSB0, ppc64.AMTFSB0CC, 0, 0},
-	ppc64.AMTFSB1:  [4]int{ppc64.AMTFSB1, ppc64.AMTFSB1CC, 0, 0},
-	ppc64.AMULHD:   [4]int{ppc64.AMULHD, ppc64.AMULHDCC, 0, 0},
-	ppc64.AMULHDU:  [4]int{ppc64.AMULHDU, ppc64.AMULHDUCC, 0, 0},
-	ppc64.AMULHW:   [4]int{ppc64.AMULHW, ppc64.AMULHWCC, 0, 0},
-	ppc64.AMULHWU:  [4]int{ppc64.AMULHWU, ppc64.AMULHWUCC, 0, 0},
-	ppc64.AMULLD:   [4]int{ppc64.AMULLD, ppc64.AMULLDCC, ppc64.AMULLDV, ppc64.AMULLDVCC},
-	ppc64.AMULLW:   [4]int{ppc64.AMULLW, ppc64.AMULLWCC, ppc64.AMULLWV, ppc64.AMULLWVCC},
-	ppc64.ANAND:    [4]int{ppc64.ANAND, ppc64.ANANDCC, 0, 0},
-	ppc64.ANEG:     [4]int{ppc64.ANEG, ppc64.ANEGCC, ppc64.ANEGV, ppc64.ANEGVCC},
-	ppc64.ANOR:     [4]int{ppc64.ANOR, ppc64.ANORCC, 0, 0},
-	ppc64.AOR:      [4]int{ppc64.AOR, ppc64.AORCC, 0, 0},
-	ppc64.AORN:     [4]int{ppc64.AORN, ppc64.AORNCC, 0, 0},
-	ppc64.AREM:     [4]int{ppc64.AREM, ppc64.AREMCC, ppc64.AREMV, ppc64.AREMVCC},
-	ppc64.AREMD:    [4]int{ppc64.AREMD, ppc64.AREMDCC, ppc64.AREMDV, ppc64.AREMDVCC},
-	ppc64.AREMDU:   [4]int{ppc64.AREMDU, ppc64.AREMDUCC, ppc64.AREMDUV, ppc64.AREMDUVCC},
-	ppc64.AREMU:    [4]int{ppc64.AREMU, ppc64.AREMUCC, ppc64.AREMUV, ppc64.AREMUVCC},
-	ppc64.ARLDC:    [4]int{ppc64.ARLDC, ppc64.ARLDCCC, 0, 0},
-	ppc64.ARLDCL:   [4]int{ppc64.ARLDCL, ppc64.ARLDCLCC, 0, 0},
-	ppc64.ARLDCR:   [4]int{ppc64.ARLDCR, ppc64.ARLDCRCC, 0, 0},
-	ppc64.ARLDMI:   [4]int{ppc64.ARLDMI, ppc64.ARLDMICC, 0, 0},
-	ppc64.ARLWMI:   [4]int{ppc64.ARLWMI, ppc64.ARLWMICC, 0, 0},
-	ppc64.ARLWNM:   [4]int{ppc64.ARLWNM, ppc64.ARLWNMCC, 0, 0},
-	ppc64.ASLD:     [4]int{ppc64.ASLD, ppc64.ASLDCC, 0, 0},
-	ppc64.ASLW:     [4]int{ppc64.ASLW, ppc64.ASLWCC, 0, 0},
-	ppc64.ASRAD:    [4]int{ppc64.ASRAD, ppc64.ASRADCC, 0, 0},
-	ppc64.ASRAW:    [4]int{ppc64.ASRAW, ppc64.ASRAWCC, 0, 0},
-	ppc64.ASRD:     [4]int{ppc64.ASRD, ppc64.ASRDCC, 0, 0},
-	ppc64.ASRW:     [4]int{ppc64.ASRW, ppc64.ASRWCC, 0, 0},
-	ppc64.ASUB:     [4]int{ppc64.ASUB, ppc64.ASUBCC, ppc64.ASUBV, ppc64.ASUBVCC},
-	ppc64.ASUBC:    [4]int{ppc64.ASUBC, ppc64.ASUBCCC, ppc64.ASUBCV, ppc64.ASUBCVCC},
-	ppc64.ASUBE:    [4]int{ppc64.ASUBE, ppc64.ASUBECC, ppc64.ASUBEV, ppc64.ASUBEVCC},
-	ppc64.ASUBME:   [4]int{ppc64.ASUBME, ppc64.ASUBMECC, ppc64.ASUBMEV, ppc64.ASUBMEVCC},
-	ppc64.ASUBZE:   [4]int{ppc64.ASUBZE, ppc64.ASUBZECC, ppc64.ASUBZEV, ppc64.ASUBZEVCC},
-	ppc64.AXOR:     [4]int{ppc64.AXOR, ppc64.AXORCC, 0, 0},
+	ppc64.AADD:     {ppc64.AADD, ppc64.AADDCC, ppc64.AADDV, ppc64.AADDVCC},
+	ppc64.AADDC:    {ppc64.AADDC, ppc64.AADDCCC, ppc64.AADDCV, ppc64.AADDCVCC},
+	ppc64.AADDE:    {ppc64.AADDE, ppc64.AADDECC, ppc64.AADDEV, ppc64.AADDEVCC},
+	ppc64.AADDME:   {ppc64.AADDME, ppc64.AADDMECC, ppc64.AADDMEV, ppc64.AADDMEVCC},
+	ppc64.AADDZE:   {ppc64.AADDZE, ppc64.AADDZECC, ppc64.AADDZEV, ppc64.AADDZEVCC},
+	ppc64.AAND:     {ppc64.AAND, ppc64.AANDCC, 0, 0},
+	ppc64.AANDN:    {ppc64.AANDN, ppc64.AANDNCC, 0, 0},
+	ppc64.ACNTLZD:  {ppc64.ACNTLZD, ppc64.ACNTLZDCC, 0, 0},
+	ppc64.ACNTLZW:  {ppc64.ACNTLZW, ppc64.ACNTLZWCC, 0, 0},
+	ppc64.ADIVD:    {ppc64.ADIVD, ppc64.ADIVDCC, ppc64.ADIVDV, ppc64.ADIVDVCC},
+	ppc64.ADIVDU:   {ppc64.ADIVDU, ppc64.ADIVDUCC, ppc64.ADIVDUV, ppc64.ADIVDUVCC},
+	ppc64.ADIVW:    {ppc64.ADIVW, ppc64.ADIVWCC, ppc64.ADIVWV, ppc64.ADIVWVCC},
+	ppc64.ADIVWU:   {ppc64.ADIVWU, ppc64.ADIVWUCC, ppc64.ADIVWUV, ppc64.ADIVWUVCC},
+	ppc64.AEQV:     {ppc64.AEQV, ppc64.AEQVCC, 0, 0},
+	ppc64.AEXTSB:   {ppc64.AEXTSB, ppc64.AEXTSBCC, 0, 0},
+	ppc64.AEXTSH:   {ppc64.AEXTSH, ppc64.AEXTSHCC, 0, 0},
+	ppc64.AEXTSW:   {ppc64.AEXTSW, ppc64.AEXTSWCC, 0, 0},
+	ppc64.AFABS:    {ppc64.AFABS, ppc64.AFABSCC, 0, 0},
+	ppc64.AFADD:    {ppc64.AFADD, ppc64.AFADDCC, 0, 0},
+	ppc64.AFADDS:   {ppc64.AFADDS, ppc64.AFADDSCC, 0, 0},
+	ppc64.AFCFID:   {ppc64.AFCFID, ppc64.AFCFIDCC, 0, 0},
+	ppc64.AFCTID:   {ppc64.AFCTID, ppc64.AFCTIDCC, 0, 0},
+	ppc64.AFCTIDZ:  {ppc64.AFCTIDZ, ppc64.AFCTIDZCC, 0, 0},
+	ppc64.AFCTIW:   {ppc64.AFCTIW, ppc64.AFCTIWCC, 0, 0},
+	ppc64.AFCTIWZ:  {ppc64.AFCTIWZ, ppc64.AFCTIWZCC, 0, 0},
+	ppc64.AFDIV:    {ppc64.AFDIV, ppc64.AFDIVCC, 0, 0},
+	ppc64.AFDIVS:   {ppc64.AFDIVS, ppc64.AFDIVSCC, 0, 0},
+	ppc64.AFMADD:   {ppc64.AFMADD, ppc64.AFMADDCC, 0, 0},
+	ppc64.AFMADDS:  {ppc64.AFMADDS, ppc64.AFMADDSCC, 0, 0},
+	ppc64.AFMOVD:   {ppc64.AFMOVD, ppc64.AFMOVDCC, 0, 0},
+	ppc64.AFMSUB:   {ppc64.AFMSUB, ppc64.AFMSUBCC, 0, 0},
+	ppc64.AFMSUBS:  {ppc64.AFMSUBS, ppc64.AFMSUBSCC, 0, 0},
+	ppc64.AFMUL:    {ppc64.AFMUL, ppc64.AFMULCC, 0, 0},
+	ppc64.AFMULS:   {ppc64.AFMULS, ppc64.AFMULSCC, 0, 0},
+	ppc64.AFNABS:   {ppc64.AFNABS, ppc64.AFNABSCC, 0, 0},
+	ppc64.AFNEG:    {ppc64.AFNEG, ppc64.AFNEGCC, 0, 0},
+	ppc64.AFNMADD:  {ppc64.AFNMADD, ppc64.AFNMADDCC, 0, 0},
+	ppc64.AFNMADDS: {ppc64.AFNMADDS, ppc64.AFNMADDSCC, 0, 0},
+	ppc64.AFNMSUB:  {ppc64.AFNMSUB, ppc64.AFNMSUBCC, 0, 0},
+	ppc64.AFNMSUBS: {ppc64.AFNMSUBS, ppc64.AFNMSUBSCC, 0, 0},
+	ppc64.AFRES:    {ppc64.AFRES, ppc64.AFRESCC, 0, 0},
+	ppc64.AFRSP:    {ppc64.AFRSP, ppc64.AFRSPCC, 0, 0},
+	ppc64.AFRSQRTE: {ppc64.AFRSQRTE, ppc64.AFRSQRTECC, 0, 0},
+	ppc64.AFSEL:    {ppc64.AFSEL, ppc64.AFSELCC, 0, 0},
+	ppc64.AFSQRT:   {ppc64.AFSQRT, ppc64.AFSQRTCC, 0, 0},
+	ppc64.AFSQRTS:  {ppc64.AFSQRTS, ppc64.AFSQRTSCC, 0, 0},
+	ppc64.AFSUB:    {ppc64.AFSUB, ppc64.AFSUBCC, 0, 0},
+	ppc64.AFSUBS:   {ppc64.AFSUBS, ppc64.AFSUBSCC, 0, 0},
+	ppc64.AMTFSB0:  {ppc64.AMTFSB0, ppc64.AMTFSB0CC, 0, 0},
+	ppc64.AMTFSB1:  {ppc64.AMTFSB1, ppc64.AMTFSB1CC, 0, 0},
+	ppc64.AMULHD:   {ppc64.AMULHD, ppc64.AMULHDCC, 0, 0},
+	ppc64.AMULHDU:  {ppc64.AMULHDU, ppc64.AMULHDUCC, 0, 0},
+	ppc64.AMULHW:   {ppc64.AMULHW, ppc64.AMULHWCC, 0, 0},
+	ppc64.AMULHWU:  {ppc64.AMULHWU, ppc64.AMULHWUCC, 0, 0},
+	ppc64.AMULLD:   {ppc64.AMULLD, ppc64.AMULLDCC, ppc64.AMULLDV, ppc64.AMULLDVCC},
+	ppc64.AMULLW:   {ppc64.AMULLW, ppc64.AMULLWCC, ppc64.AMULLWV, ppc64.AMULLWVCC},
+	ppc64.ANAND:    {ppc64.ANAND, ppc64.ANANDCC, 0, 0},
+	ppc64.ANEG:     {ppc64.ANEG, ppc64.ANEGCC, ppc64.ANEGV, ppc64.ANEGVCC},
+	ppc64.ANOR:     {ppc64.ANOR, ppc64.ANORCC, 0, 0},
+	ppc64.AOR:      {ppc64.AOR, ppc64.AORCC, 0, 0},
+	ppc64.AORN:     {ppc64.AORN, ppc64.AORNCC, 0, 0},
+	ppc64.AREM:     {ppc64.AREM, ppc64.AREMCC, ppc64.AREMV, ppc64.AREMVCC},
+	ppc64.AREMD:    {ppc64.AREMD, ppc64.AREMDCC, ppc64.AREMDV, ppc64.AREMDVCC},
+	ppc64.AREMDU:   {ppc64.AREMDU, ppc64.AREMDUCC, ppc64.AREMDUV, ppc64.AREMDUVCC},
+	ppc64.AREMU:    {ppc64.AREMU, ppc64.AREMUCC, ppc64.AREMUV, ppc64.AREMUVCC},
+	ppc64.ARLDC:    {ppc64.ARLDC, ppc64.ARLDCCC, 0, 0},
+	ppc64.ARLDCL:   {ppc64.ARLDCL, ppc64.ARLDCLCC, 0, 0},
+	ppc64.ARLDCR:   {ppc64.ARLDCR, ppc64.ARLDCRCC, 0, 0},
+	ppc64.ARLDMI:   {ppc64.ARLDMI, ppc64.ARLDMICC, 0, 0},
+	ppc64.ARLWMI:   {ppc64.ARLWMI, ppc64.ARLWMICC, 0, 0},
+	ppc64.ARLWNM:   {ppc64.ARLWNM, ppc64.ARLWNMCC, 0, 0},
+	ppc64.ASLD:     {ppc64.ASLD, ppc64.ASLDCC, 0, 0},
+	ppc64.ASLW:     {ppc64.ASLW, ppc64.ASLWCC, 0, 0},
+	ppc64.ASRAD:    {ppc64.ASRAD, ppc64.ASRADCC, 0, 0},
+	ppc64.ASRAW:    {ppc64.ASRAW, ppc64.ASRAWCC, 0, 0},
+	ppc64.ASRD:     {ppc64.ASRD, ppc64.ASRDCC, 0, 0},
+	ppc64.ASRW:     {ppc64.ASRW, ppc64.ASRWCC, 0, 0},
+	ppc64.ASUB:     {ppc64.ASUB, ppc64.ASUBCC, ppc64.ASUBV, ppc64.ASUBVCC},
+	ppc64.ASUBC:    {ppc64.ASUBC, ppc64.ASUBCCC, ppc64.ASUBCV, ppc64.ASUBCVCC},
+	ppc64.ASUBE:    {ppc64.ASUBE, ppc64.ASUBECC, ppc64.ASUBEV, ppc64.ASUBEVCC},
+	ppc64.ASUBME:   {ppc64.ASUBME, ppc64.ASUBMECC, ppc64.ASUBMEV, ppc64.ASUBMEVCC},
+	ppc64.ASUBZE:   {ppc64.ASUBZE, ppc64.ASUBZECC, ppc64.ASUBZEV, ppc64.ASUBZEVCC},
+	ppc64.AXOR:     {ppc64.AXOR, ppc64.AXORCC, 0, 0},
 }
 
 var initvariants_initialized int
@@ -302,7 +303,7 @@ func as2variant(as int) int {
 			return i
 		}
 	}
-	gc.Fatal("as2variant: instruction %v is not a variant of itself", obj.Aconv(as))
+	gc.Fatalf("as2variant: instruction %v is not a variant of itself", obj.Aconv(as))
 	return 0
 }
 
diff --git a/src/cmd/compile/internal/ppc64/reg.go b/src/cmd/compile/internal/ppc64/reg.go
index a301836..da3f34a 100644
--- a/src/cmd/compile/internal/ppc64/reg.go
+++ b/src/cmd/compile/internal/ppc64/reg.go
@@ -113,6 +113,12 @@ func excludedregs() uint64 {
 	// Exclude registers with fixed functions
 	regbits := uint64(1<<0 | RtoB(ppc64.REGSP) | RtoB(ppc64.REGG) | RtoB(ppc64.REGTLS) | RtoB(ppc64.REGTMP))
 
+	if gc.Ctxt.Flag_shared != 0 {
+		// When compiling Go into PIC, R2 is reserved to be the TOC pointer
+		// and R12 so that calls via function pointer can stomp on it.
+		regbits |= RtoB(ppc64.REG_R2)
+		regbits |= RtoB(ppc64.REG_R12)
+	}
 	// Also exclude floating point registers with fixed constants
 	regbits |= RtoB(ppc64.REG_F27) | RtoB(ppc64.REG_F28) | RtoB(ppc64.REG_F29) | RtoB(ppc64.REG_F30) | RtoB(ppc64.REG_F31)
 
diff --git a/src/cmd/compile/internal/x86/cgen64.go b/src/cmd/compile/internal/x86/cgen64.go
index 0b061ff..7e40a32 100644
--- a/src/cmd/compile/internal/x86/cgen64.go
+++ b/src/cmd/compile/internal/x86/cgen64.go
@@ -19,12 +19,12 @@ func cgen64(n *gc.Node, res *gc.Node) {
 	if res.Op != gc.OINDREG && res.Op != gc.ONAME {
 		gc.Dump("n", n)
 		gc.Dump("res", res)
-		gc.Fatal("cgen64 %v of %v", gc.Oconv(int(n.Op), 0), gc.Oconv(int(res.Op), 0))
+		gc.Fatalf("cgen64 %v of %v", gc.Oconv(int(n.Op), 0), gc.Oconv(int(res.Op), 0))
 	}
 
 	switch n.Op {
 	default:
-		gc.Fatal("cgen64 %v", gc.Oconv(int(n.Op), 0))
+		gc.Fatalf("cgen64 %v", gc.Oconv(int(n.Op), 0))
 
 	case gc.OMINUS:
 		gc.Cgen(n.Left, res)
@@ -113,19 +113,18 @@ func cgen64(n *gc.Node, res *gc.Node) {
 		gins(x86.ASUBL, &lo2, &ax)
 		gins(x86.ASBBL, &hi2, &dx)
 
-		// let's call the next two EX and FX.
 	case gc.OMUL:
-		var ex gc.Node
+		// let's call the next three EX, FX and GX
+		var ex, fx, gx gc.Node
 		gc.Regalloc(&ex, gc.Types[gc.TPTR32], nil)
-
-		var fx gc.Node
 		gc.Regalloc(&fx, gc.Types[gc.TPTR32], nil)
+		gc.Regalloc(&gx, gc.Types[gc.TPTR32], nil)
 
-		// load args into DX:AX and EX:CX.
+		// load args into DX:AX and EX:GX.
 		gins(x86.AMOVL, &lo1, &ax)
 
 		gins(x86.AMOVL, &hi1, &dx)
-		gins(x86.AMOVL, &lo2, &cx)
+		gins(x86.AMOVL, &lo2, &gx)
 		gins(x86.AMOVL, &hi2, &ex)
 
 		// if DX and EX are zero, use 32 x 32 -> 64 unsigned multiply.
@@ -133,25 +132,26 @@ func cgen64(n *gc.Node, res *gc.Node) {
 
 		gins(x86.AORL, &ex, &fx)
 		p1 := gc.Gbranch(x86.AJNE, nil, 0)
-		gins(x86.AMULL, &cx, nil) // implicit &ax
+		gins(x86.AMULL, &gx, nil) // implicit &ax
 		p2 := gc.Gbranch(obj.AJMP, nil, 0)
 		gc.Patch(p1, gc.Pc)
 
 		// full 64x64 -> 64, from 32x32 -> 64.
-		gins(x86.AIMULL, &cx, &dx)
+		gins(x86.AIMULL, &gx, &dx)
 
 		gins(x86.AMOVL, &ax, &fx)
 		gins(x86.AIMULL, &ex, &fx)
 		gins(x86.AADDL, &dx, &fx)
-		gins(x86.AMOVL, &cx, &dx)
+		gins(x86.AMOVL, &gx, &dx)
 		gins(x86.AMULL, &dx, nil) // implicit &ax
 		gins(x86.AADDL, &fx, &dx)
 		gc.Patch(p2, gc.Pc)
 
 		gc.Regfree(&ex)
 		gc.Regfree(&fx)
+		gc.Regfree(&gx)
 
-		// We only rotate by a constant c in [0,64).
+	// We only rotate by a constant c in [0,64).
 	// if c >= 32:
 	//	lo, hi = hi, lo
 	//	c -= 32
@@ -486,8 +486,8 @@ func cgen64(n *gc.Node, res *gc.Node) {
 
 		gins(x86.AMOVL, &lo1, &ax)
 		gins(x86.AMOVL, &hi1, &dx)
-		gins(optoas(int(n.Op), lo1.Type), &lo2, &ax)
-		gins(optoas(int(n.Op), lo1.Type), &hi2, &dx)
+		gins(optoas(n.Op, lo1.Type), &lo2, &ax)
+		gins(optoas(n.Op, lo1.Type), &hi2, &dx)
 	}
 
 	if gc.Is64(r.Type) {
@@ -505,7 +505,7 @@ func cgen64(n *gc.Node, res *gc.Node) {
  * generate comparison of nl, nr, both 64-bit.
  * nl is memory; nr is constant or memory.
  */
-func cmp64(nl *gc.Node, nr *gc.Node, op int, likely int, to *obj.Prog) {
+func cmp64(nl *gc.Node, nr *gc.Node, op gc.Op, likely int, to *obj.Prog) {
 	var lo1 gc.Node
 	var hi1 gc.Node
 	var lo2 gc.Node
@@ -531,7 +531,7 @@ func cmp64(nl *gc.Node, nr *gc.Node, op int, likely int, to *obj.Prog) {
 	var br *obj.Prog
 	switch op {
 	default:
-		gc.Fatal("cmp64 %v %v", gc.Oconv(int(op), 0), t)
+		gc.Fatalf("cmp64 %v %v", gc.Oconv(int(op), 0), t)
 
 		// cmp hi
 	// jne L
diff --git a/src/cmd/compile/internal/x86/galign.go b/src/cmd/compile/internal/x86/galign.go
index 2b602e1..2535e3e 100644
--- a/src/cmd/compile/internal/x86/galign.go
+++ b/src/cmd/compile/internal/x86/galign.go
@@ -28,9 +28,9 @@ var MAXWIDTH int64 = (1 << 32) - 1
  * int, uint, and uintptr
  */
 var typedefs = []gc.Typedef{
-	gc.Typedef{"int", gc.TINT, gc.TINT32},
-	gc.Typedef{"uint", gc.TUINT, gc.TUINT32},
-	gc.Typedef{"uintptr", gc.TUINTPTR, gc.TUINT32},
+	{"int", gc.TINT, gc.TINT32},
+	{"uint", gc.TUINT, gc.TUINT32},
+	{"uintptr", gc.TUINTPTR, gc.TUINT32},
 }
 
 func betypeinit() {
diff --git a/src/cmd/compile/internal/x86/ggen.go b/src/cmd/compile/internal/x86/ggen.go
index ae9881d..139b199 100644
--- a/src/cmd/compile/internal/x86/ggen.go
+++ b/src/cmd/compile/internal/x86/ggen.go
@@ -34,10 +34,10 @@ func defframe(ptxt *obj.Prog) {
 			continue
 		}
 		if n.Class != gc.PAUTO {
-			gc.Fatal("needzero class %d", n.Class)
+			gc.Fatalf("needzero class %d", n.Class)
 		}
 		if n.Type.Width%int64(gc.Widthptr) != 0 || n.Xoffset%int64(gc.Widthptr) != 0 || n.Type.Width == 0 {
-			gc.Fatal("var %v has size %d offset %d", gc.Nconv(n, obj.FmtLong), int(n.Type.Width), int(n.Xoffset))
+			gc.Fatalf("var %v has size %d offset %d", gc.Nconv(n, obj.FmtLong), int(n.Type.Width), int(n.Xoffset))
 		}
 		if lo != hi && n.Xoffset+n.Type.Width == lo-int64(2*gc.Widthptr) {
 			// merge with range we already have
@@ -133,24 +133,14 @@ func clearfat(nl *gc.Node) {
 		n1.Op = gc.OINDREG
 		var z gc.Node
 		gc.Nodconst(&z, gc.Types[gc.TUINT64], 0)
-		for {
-			tmp14 := q
-			q--
-			if tmp14 <= 0 {
-				break
-			}
+		for ; q > 0; q-- {
 			n1.Type = z.Type
 			gins(x86.AMOVL, &z, &n1)
 			n1.Xoffset += 4
 		}
 
 		gc.Nodconst(&z, gc.Types[gc.TUINT8], 0)
-		for {
-			tmp15 := c
-			c--
-			if tmp15 <= 0 {
-				break
-			}
+		for ; c > 0; c-- {
 			n1.Type = z.Type
 			gins(x86.AMOVB, &z, &n1)
 			n1.Xoffset++
@@ -201,7 +191,7 @@ var panicdiv *gc.Node
  *	res = nl % nr
  * according to op.
  */
-func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node, ax *gc.Node, dx *gc.Node) {
+func dodiv(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node, ax *gc.Node, dx *gc.Node) {
 	// Have to be careful about handling
 	// most negative int divided by -1 correctly.
 	// The hardware will trap.
@@ -213,13 +203,13 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node, ax *gc.Node, dx *gc.N
 	t := nl.Type
 
 	t0 := t
-	check := 0
+	check := false
 	if gc.Issigned[t.Etype] {
-		check = 1
+		check = true
 		if gc.Isconst(nl, gc.CTINT) && nl.Int() != -1<<uint64(t.Width*8-1) {
-			check = 0
+			check = false
 		} else if gc.Isconst(nr, gc.CTINT) && nr.Int() != -1 {
-			check = 0
+			check = false
 		}
 	}
 
@@ -229,7 +219,7 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node, ax *gc.Node, dx *gc.N
 		} else {
 			t = gc.Types[gc.TUINT32]
 		}
-		check = 0
+		check = false
 	}
 
 	var t1 gc.Node
@@ -278,7 +268,7 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node, ax *gc.Node, dx *gc.N
 		gc.Patch(p1, gc.Pc)
 	}
 
-	if check != 0 {
+	if check {
 		gc.Nodconst(&n4, t, -1)
 		gins(optoas(gc.OCMP, t), &n1, &n4)
 		p1 := gc.Gbranch(optoas(gc.ONE, t), nil, +1)
@@ -313,7 +303,7 @@ func dodiv(op int, nl *gc.Node, nr *gc.Node, res *gc.Node, ax *gc.Node, dx *gc.N
 	} else {
 		gmove(dx, res)
 	}
-	if check != 0 {
+	if check {
 		gc.Patch(p2, gc.Pc)
 	}
 }
@@ -348,9 +338,9 @@ func restx(x *gc.Node, oldx *gc.Node) {
  *	res = nl / nr
  *	res = nl % nr
  */
-func cgen_div(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+func cgen_div(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	if gc.Is64(nl.Type) {
-		gc.Fatal("cgen_div %v", nl.Type)
+		gc.Fatalf("cgen_div %v", nl.Type)
 	}
 
 	var t *gc.Type
@@ -375,9 +365,9 @@ func cgen_div(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) {
  *	res = nl << nr
  *	res = nl >> nr
  */
-func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
+func cgen_shift(op gc.Op, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	if nl.Type.Width > 4 {
-		gc.Fatal("cgen_shift %v", nl.Type)
+		gc.Fatalf("cgen_shift %v", nl.Type)
 	}
 
 	w := int(nl.Type.Width * 8)
@@ -499,7 +489,7 @@ func cgen_shift(op int, bounded bool, nl *gc.Node, nr *gc.Node, res *gc.Node) {
  * there is no 2-operand byte multiply instruction so
  * we do a full-width multiplication and truncate afterwards.
  */
-func cgen_bmul(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) bool {
+func cgen_bmul(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) bool {
 	if optoas(op, nl.Type) != x86.AIMULB {
 		return false
 	}
@@ -513,9 +503,7 @@ func cgen_bmul(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) bool {
 
 	// largest ullman on left.
 	if nl.Ullman < nr.Ullman {
-		tmp := nl
-		nl = nr
-		nr = tmp
+		nl, nr = nr, nl
 	}
 
 	var nt gc.Node
@@ -543,24 +531,21 @@ func cgen_bmul(op int, nl *gc.Node, nr *gc.Node, res *gc.Node) bool {
 func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
 	var n1 gc.Node
 	var n2 gc.Node
-	var ax gc.Node
-	var dx gc.Node
 
 	t := nl.Type
 	a := optoas(gc.OHMUL, t)
 
 	// gen nl in n1.
 	gc.Tempname(&n1, t)
-
 	gc.Cgen(nl, &n1)
 
 	// gen nr in n2.
 	gc.Regalloc(&n2, t, res)
-
 	gc.Cgen(nr, &n2)
 
-	// multiply.
-	gc.Nodreg(&ax, t, x86.REG_AX)
+	var ax, oldax, dx, olddx gc.Node
+	savex(x86.REG_AX, &ax, &oldax, res, gc.Types[gc.TUINT32])
+	savex(x86.REG_DX, &dx, &olddx, res, gc.Types[gc.TUINT32])
 
 	gmove(&n2, &ax)
 	gins(a, &n1, nil)
@@ -568,14 +553,16 @@ func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
 
 	if t.Width == 1 {
 		// byte multiply behaves differently.
-		gc.Nodreg(&ax, t, x86.REG_AH)
-
-		gc.Nodreg(&dx, t, x86.REG_DX)
-		gmove(&ax, &dx)
+		var byteAH, byteDX gc.Node
+		gc.Nodreg(&byteAH, t, x86.REG_AH)
+		gc.Nodreg(&byteDX, t, x86.REG_DX)
+		gmove(&byteAH, &byteDX)
 	}
 
-	gc.Nodreg(&dx, t, x86.REG_DX)
 	gmove(&dx, res)
+
+	restx(&ax, &oldax)
+	restx(&dx, &olddx)
 }
 
 /*
@@ -640,18 +627,18 @@ func cgen_float387(n *gc.Node, res *gc.Node) {
 		if nl.Ullman >= nr.Ullman {
 			gc.Cgen(nl, &f0)
 			if nr.Addable {
-				gins(foptoas(int(n.Op), n.Type, 0), nr, &f0)
+				gins(foptoas(n.Op, n.Type, 0), nr, &f0)
 			} else {
 				gc.Cgen(nr, &f0)
-				gins(foptoas(int(n.Op), n.Type, Fpop), &f0, &f1)
+				gins(foptoas(n.Op, n.Type, Fpop), &f0, &f1)
 			}
 		} else {
 			gc.Cgen(nr, &f0)
 			if nl.Addable {
-				gins(foptoas(int(n.Op), n.Type, Frev), nl, &f0)
+				gins(foptoas(n.Op, n.Type, Frev), nl, &f0)
 			} else {
 				gc.Cgen(nl, &f0)
-				gins(foptoas(int(n.Op), n.Type, Frev|Fpop), &f0, &f1)
+				gins(foptoas(n.Op, n.Type, Frev|Fpop), &f0, &f1)
 			}
 		}
 
@@ -663,7 +650,7 @@ func cgen_float387(n *gc.Node, res *gc.Node) {
 	gc.Cgen(nl, &f0)
 
 	if n.Op != gc.OCONV && n.Op != gc.OPLUS {
-		gins(foptoas(int(n.Op), n.Type, 0), nil, nil)
+		gins(foptoas(n.Op, n.Type, 0), nil, nil)
 	}
 	gmove(&f0, res)
 	return
@@ -677,7 +664,7 @@ func cgen_floatsse(n *gc.Node, res *gc.Node) {
 	switch n.Op {
 	default:
 		gc.Dump("cgen_floatsse", n)
-		gc.Fatal("cgen_floatsse %v", gc.Oconv(int(n.Op), 0))
+		gc.Fatalf("cgen_floatsse %v", gc.Oconv(int(n.Op), 0))
 		return
 
 	case gc.OMINUS,
@@ -690,7 +677,7 @@ func cgen_floatsse(n *gc.Node, res *gc.Node) {
 		// symmetric binary
 	case gc.OADD,
 		gc.OMUL:
-		a = foptoas(int(n.Op), nl.Type, 0)
+		a = foptoas(n.Op, nl.Type, 0)
 
 		goto sbop
 
@@ -698,16 +685,14 @@ func cgen_floatsse(n *gc.Node, res *gc.Node) {
 	case gc.OSUB,
 		gc.OMOD,
 		gc.ODIV:
-		a = foptoas(int(n.Op), nl.Type, 0)
+		a = foptoas(n.Op, nl.Type, 0)
 
 		goto abop
 	}
 
 sbop: // symmetric binary
 	if nl.Ullman < nr.Ullman || nl.Op == gc.OLITERAL {
-		r := nl
-		nl = nr
-		nr = r
+		nl, nr = nr, nl
 	}
 
 abop: // asymmetric binary
@@ -743,7 +728,7 @@ abop: // asymmetric binary
 func bgen_float(n *gc.Node, wantTrue bool, likely int, to *obj.Prog) {
 	nl := n.Left
 	nr := n.Right
-	a := int(n.Op)
+	op := n.Op
 	if !wantTrue {
 		// brcom is not valid on floats when NaN is involved.
 		p1 := gc.Gbranch(obj.AJMP, nil, 0)
@@ -759,11 +744,11 @@ func bgen_float(n *gc.Node, wantTrue bool, likely int, to *obj.Prog) {
 	}
 
 	if gc.Thearch.Use387 {
-		a = gc.Brrev(a) // because the args are stacked
-		if a == gc.OGE || a == gc.OGT {
+		op = gc.Brrev(op) // because the args are stacked
+		if op == gc.OGE || op == gc.OGT {
 			// only < and <= work right with NaN; reverse if needed
 			nl, nr = nr, nl
-			a = gc.Brrev(a)
+			op = gc.Brrev(op)
 		}
 
 		var ax, n2, tmp gc.Node
@@ -779,9 +764,7 @@ func bgen_float(n *gc.Node, wantTrue bool, likely int, to *obj.Prog) {
 				gc.Cgen(nr, &tmp)
 				gc.Cgen(nl, &tmp)
 			}
-
-			gins(x86.AFUCOMIP, &tmp, &n2)
-			gins(x86.AFMOVDP, &tmp, &tmp) // annoying pop but still better than STSW+SAHF
+			gins(x86.AFUCOMPP, &tmp, &n2)
 		} else {
 			// TODO(rsc): The moves back and forth to memory
 			// here are for truncating the value to 32 bits.
@@ -798,9 +781,9 @@ func bgen_float(n *gc.Node, wantTrue bool, likely int, to *obj.Prog) {
 			gc.Cgen(nl, &t2)
 			gmove(&t2, &tmp)
 			gins(x86.AFCOMFP, &t1, &tmp)
-			gins(x86.AFSTSW, nil, &ax)
-			gins(x86.ASAHF, nil, nil)
 		}
+		gins(x86.AFSTSW, nil, &ax)
+		gins(x86.ASAHF, nil, nil)
 	} else {
 		// Not 387
 		if !nl.Addable {
@@ -822,10 +805,10 @@ func bgen_float(n *gc.Node, wantTrue bool, likely int, to *obj.Prog) {
 			nl = &n3
 		}
 
-		if a == gc.OGE || a == gc.OGT {
-			// only < and <= work right with NaN; reverse if needed
+		if op == gc.OGE || op == gc.OGT {
+			// only < and <= work right with NopN; reverse if needed
 			nl, nr = nr, nl
-			a = gc.Brrev(a)
+			op = gc.Brrev(op)
 		}
 
 		gins(foptoas(gc.OCMP, nr.Type, 0), nl, nr)
@@ -835,7 +818,7 @@ func bgen_float(n *gc.Node, wantTrue bool, likely int, to *obj.Prog) {
 		gc.Regfree(nr)
 	}
 
-	switch a {
+	switch op {
 	case gc.OEQ:
 		// neither NE nor P
 		p1 := gc.Gbranch(x86.AJNE, nil, -likely)
@@ -848,7 +831,7 @@ func bgen_float(n *gc.Node, wantTrue bool, likely int, to *obj.Prog) {
 		gc.Patch(gc.Gbranch(x86.AJNE, nil, likely), to)
 		gc.Patch(gc.Gbranch(x86.AJPS, nil, likely), to)
 	default:
-		gc.Patch(gc.Gbranch(optoas(a, nr.Type), nil, likely), to)
+		gc.Patch(gc.Gbranch(optoas(op, nr.Type), nil, likely), to)
 	}
 }
 
diff --git a/src/cmd/compile/internal/x86/gsubr.go b/src/cmd/compile/internal/x86/gsubr.go
index 7593d04..9859571 100644
--- a/src/cmd/compile/internal/x86/gsubr.go
+++ b/src/cmd/compile/internal/x86/gsubr.go
@@ -53,402 +53,443 @@ const (
 /*
  * return Axxx for Oxxx on type t.
  */
-func optoas(op int, t *gc.Type) int {
+func optoas(op gc.Op, t *gc.Type) int {
 	if t == nil {
-		gc.Fatal("optoas: t is nil")
+		gc.Fatalf("optoas: t is nil")
 	}
 
+	// avoid constant conversions in switches below
+	const (
+		OMINUS_  = uint32(gc.OMINUS) << 16
+		OLSH_    = uint32(gc.OLSH) << 16
+		ORSH_    = uint32(gc.ORSH) << 16
+		OADD_    = uint32(gc.OADD) << 16
+		OSUB_    = uint32(gc.OSUB) << 16
+		OMUL_    = uint32(gc.OMUL) << 16
+		ODIV_    = uint32(gc.ODIV) << 16
+		OMOD_    = uint32(gc.OMOD) << 16
+		OOR_     = uint32(gc.OOR) << 16
+		OAND_    = uint32(gc.OAND) << 16
+		OXOR_    = uint32(gc.OXOR) << 16
+		OEQ_     = uint32(gc.OEQ) << 16
+		ONE_     = uint32(gc.ONE) << 16
+		OLT_     = uint32(gc.OLT) << 16
+		OLE_     = uint32(gc.OLE) << 16
+		OGE_     = uint32(gc.OGE) << 16
+		OGT_     = uint32(gc.OGT) << 16
+		OCMP_    = uint32(gc.OCMP) << 16
+		OAS_     = uint32(gc.OAS) << 16
+		OHMUL_   = uint32(gc.OHMUL) << 16
+		OADDR_   = uint32(gc.OADDR) << 16
+		OINC_    = uint32(gc.OINC) << 16
+		ODEC_    = uint32(gc.ODEC) << 16
+		OLROT_   = uint32(gc.OLROT) << 16
+		OEXTEND_ = uint32(gc.OEXTEND) << 16
+		OCOM_    = uint32(gc.OCOM) << 16
+	)
+
 	a := obj.AXXX
 	switch uint32(op)<<16 | uint32(gc.Simtype[t.Etype]) {
 	default:
-		gc.Fatal("optoas: no entry %v-%v", gc.Oconv(int(op), 0), t)
+		gc.Fatalf("optoas: no entry %v-%v", gc.Oconv(int(op), 0), t)
 
-	case gc.OADDR<<16 | gc.TPTR32:
+	case OADDR_ | gc.TPTR32:
 		a = x86.ALEAL
 
-	case gc.OEQ<<16 | gc.TBOOL,
-		gc.OEQ<<16 | gc.TINT8,
-		gc.OEQ<<16 | gc.TUINT8,
-		gc.OEQ<<16 | gc.TINT16,
-		gc.OEQ<<16 | gc.TUINT16,
-		gc.OEQ<<16 | gc.TINT32,
-		gc.OEQ<<16 | gc.TUINT32,
-		gc.OEQ<<16 | gc.TINT64,
-		gc.OEQ<<16 | gc.TUINT64,
-		gc.OEQ<<16 | gc.TPTR32,
-		gc.OEQ<<16 | gc.TPTR64,
-		gc.OEQ<<16 | gc.TFLOAT32,
-		gc.OEQ<<16 | gc.TFLOAT64:
+	case OEQ_ | gc.TBOOL,
+		OEQ_ | gc.TINT8,
+		OEQ_ | gc.TUINT8,
+		OEQ_ | gc.TINT16,
+		OEQ_ | gc.TUINT16,
+		OEQ_ | gc.TINT32,
+		OEQ_ | gc.TUINT32,
+		OEQ_ | gc.TINT64,
+		OEQ_ | gc.TUINT64,
+		OEQ_ | gc.TPTR32,
+		OEQ_ | gc.TPTR64,
+		OEQ_ | gc.TFLOAT32,
+		OEQ_ | gc.TFLOAT64:
 		a = x86.AJEQ
 
-	case gc.ONE<<16 | gc.TBOOL,
-		gc.ONE<<16 | gc.TINT8,
-		gc.ONE<<16 | gc.TUINT8,
-		gc.ONE<<16 | gc.TINT16,
-		gc.ONE<<16 | gc.TUINT16,
-		gc.ONE<<16 | gc.TINT32,
-		gc.ONE<<16 | gc.TUINT32,
-		gc.ONE<<16 | gc.TINT64,
-		gc.ONE<<16 | gc.TUINT64,
-		gc.ONE<<16 | gc.TPTR32,
-		gc.ONE<<16 | gc.TPTR64,
-		gc.ONE<<16 | gc.TFLOAT32,
-		gc.ONE<<16 | gc.TFLOAT64:
+	case ONE_ | gc.TBOOL,
+		ONE_ | gc.TINT8,
+		ONE_ | gc.TUINT8,
+		ONE_ | gc.TINT16,
+		ONE_ | gc.TUINT16,
+		ONE_ | gc.TINT32,
+		ONE_ | gc.TUINT32,
+		ONE_ | gc.TINT64,
+		ONE_ | gc.TUINT64,
+		ONE_ | gc.TPTR32,
+		ONE_ | gc.TPTR64,
+		ONE_ | gc.TFLOAT32,
+		ONE_ | gc.TFLOAT64:
 		a = x86.AJNE
 
-	case gc.OLT<<16 | gc.TINT8,
-		gc.OLT<<16 | gc.TINT16,
-		gc.OLT<<16 | gc.TINT32,
-		gc.OLT<<16 | gc.TINT64:
+	case OLT_ | gc.TINT8,
+		OLT_ | gc.TINT16,
+		OLT_ | gc.TINT32,
+		OLT_ | gc.TINT64:
 		a = x86.AJLT
 
-	case gc.OLT<<16 | gc.TUINT8,
-		gc.OLT<<16 | gc.TUINT16,
-		gc.OLT<<16 | gc.TUINT32,
-		gc.OLT<<16 | gc.TUINT64:
+	case OLT_ | gc.TUINT8,
+		OLT_ | gc.TUINT16,
+		OLT_ | gc.TUINT32,
+		OLT_ | gc.TUINT64:
 		a = x86.AJCS
 
-	case gc.OLE<<16 | gc.TINT8,
-		gc.OLE<<16 | gc.TINT16,
-		gc.OLE<<16 | gc.TINT32,
-		gc.OLE<<16 | gc.TINT64:
+	case OLE_ | gc.TINT8,
+		OLE_ | gc.TINT16,
+		OLE_ | gc.TINT32,
+		OLE_ | gc.TINT64:
 		a = x86.AJLE
 
-	case gc.OLE<<16 | gc.TUINT8,
-		gc.OLE<<16 | gc.TUINT16,
-		gc.OLE<<16 | gc.TUINT32,
-		gc.OLE<<16 | gc.TUINT64:
+	case OLE_ | gc.TUINT8,
+		OLE_ | gc.TUINT16,
+		OLE_ | gc.TUINT32,
+		OLE_ | gc.TUINT64:
 		a = x86.AJLS
 
-	case gc.OGT<<16 | gc.TINT8,
-		gc.OGT<<16 | gc.TINT16,
-		gc.OGT<<16 | gc.TINT32,
-		gc.OGT<<16 | gc.TINT64:
+	case OGT_ | gc.TINT8,
+		OGT_ | gc.TINT16,
+		OGT_ | gc.TINT32,
+		OGT_ | gc.TINT64:
 		a = x86.AJGT
 
-	case gc.OGT<<16 | gc.TUINT8,
-		gc.OGT<<16 | gc.TUINT16,
-		gc.OGT<<16 | gc.TUINT32,
-		gc.OGT<<16 | gc.TUINT64,
-		gc.OLT<<16 | gc.TFLOAT32,
-		gc.OLT<<16 | gc.TFLOAT64:
+	case OGT_ | gc.TUINT8,
+		OGT_ | gc.TUINT16,
+		OGT_ | gc.TUINT32,
+		OGT_ | gc.TUINT64,
+		OLT_ | gc.TFLOAT32,
+		OLT_ | gc.TFLOAT64:
 		a = x86.AJHI
 
-	case gc.OGE<<16 | gc.TINT8,
-		gc.OGE<<16 | gc.TINT16,
-		gc.OGE<<16 | gc.TINT32,
-		gc.OGE<<16 | gc.TINT64:
+	case OGE_ | gc.TINT8,
+		OGE_ | gc.TINT16,
+		OGE_ | gc.TINT32,
+		OGE_ | gc.TINT64:
 		a = x86.AJGE
 
-	case gc.OGE<<16 | gc.TUINT8,
-		gc.OGE<<16 | gc.TUINT16,
-		gc.OGE<<16 | gc.TUINT32,
-		gc.OGE<<16 | gc.TUINT64,
-		gc.OLE<<16 | gc.TFLOAT32,
-		gc.OLE<<16 | gc.TFLOAT64:
+	case OGE_ | gc.TUINT8,
+		OGE_ | gc.TUINT16,
+		OGE_ | gc.TUINT32,
+		OGE_ | gc.TUINT64,
+		OLE_ | gc.TFLOAT32,
+		OLE_ | gc.TFLOAT64:
 		a = x86.AJCC
 
-	case gc.OCMP<<16 | gc.TBOOL,
-		gc.OCMP<<16 | gc.TINT8,
-		gc.OCMP<<16 | gc.TUINT8:
+	case OCMP_ | gc.TBOOL,
+		OCMP_ | gc.TINT8,
+		OCMP_ | gc.TUINT8:
 		a = x86.ACMPB
 
-	case gc.OCMP<<16 | gc.TINT16,
-		gc.OCMP<<16 | gc.TUINT16:
+	case OCMP_ | gc.TINT16,
+		OCMP_ | gc.TUINT16:
 		a = x86.ACMPW
 
-	case gc.OCMP<<16 | gc.TINT32,
-		gc.OCMP<<16 | gc.TUINT32,
-		gc.OCMP<<16 | gc.TPTR32:
+	case OCMP_ | gc.TINT32,
+		OCMP_ | gc.TUINT32,
+		OCMP_ | gc.TPTR32:
 		a = x86.ACMPL
 
-	case gc.OAS<<16 | gc.TBOOL,
-		gc.OAS<<16 | gc.TINT8,
-		gc.OAS<<16 | gc.TUINT8:
+	case OAS_ | gc.TBOOL,
+		OAS_ | gc.TINT8,
+		OAS_ | gc.TUINT8:
 		a = x86.AMOVB
 
-	case gc.OAS<<16 | gc.TINT16,
-		gc.OAS<<16 | gc.TUINT16:
+	case OAS_ | gc.TINT16,
+		OAS_ | gc.TUINT16:
 		a = x86.AMOVW
 
-	case gc.OAS<<16 | gc.TINT32,
-		gc.OAS<<16 | gc.TUINT32,
-		gc.OAS<<16 | gc.TPTR32:
+	case OAS_ | gc.TINT32,
+		OAS_ | gc.TUINT32,
+		OAS_ | gc.TPTR32:
 		a = x86.AMOVL
 
-	case gc.OAS<<16 | gc.TFLOAT32:
+	case OAS_ | gc.TFLOAT32:
 		a = x86.AMOVSS
 
-	case gc.OAS<<16 | gc.TFLOAT64:
+	case OAS_ | gc.TFLOAT64:
 		a = x86.AMOVSD
 
-	case gc.OADD<<16 | gc.TINT8,
-		gc.OADD<<16 | gc.TUINT8:
+	case OADD_ | gc.TINT8,
+		OADD_ | gc.TUINT8:
 		a = x86.AADDB
 
-	case gc.OADD<<16 | gc.TINT16,
-		gc.OADD<<16 | gc.TUINT16:
+	case OADD_ | gc.TINT16,
+		OADD_ | gc.TUINT16:
 		a = x86.AADDW
 
-	case gc.OADD<<16 | gc.TINT32,
-		gc.OADD<<16 | gc.TUINT32,
-		gc.OADD<<16 | gc.TPTR32:
+	case OADD_ | gc.TINT32,
+		OADD_ | gc.TUINT32,
+		OADD_ | gc.TPTR32:
 		a = x86.AADDL
 
-	case gc.OSUB<<16 | gc.TINT8,
-		gc.OSUB<<16 | gc.TUINT8:
+	case OSUB_ | gc.TINT8,
+		OSUB_ | gc.TUINT8:
 		a = x86.ASUBB
 
-	case gc.OSUB<<16 | gc.TINT16,
-		gc.OSUB<<16 | gc.TUINT16:
+	case OSUB_ | gc.TINT16,
+		OSUB_ | gc.TUINT16:
 		a = x86.ASUBW
 
-	case gc.OSUB<<16 | gc.TINT32,
-		gc.OSUB<<16 | gc.TUINT32,
-		gc.OSUB<<16 | gc.TPTR32:
+	case OSUB_ | gc.TINT32,
+		OSUB_ | gc.TUINT32,
+		OSUB_ | gc.TPTR32:
 		a = x86.ASUBL
 
-	case gc.OINC<<16 | gc.TINT8,
-		gc.OINC<<16 | gc.TUINT8:
+	case OINC_ | gc.TINT8,
+		OINC_ | gc.TUINT8:
 		a = x86.AINCB
 
-	case gc.OINC<<16 | gc.TINT16,
-		gc.OINC<<16 | gc.TUINT16:
+	case OINC_ | gc.TINT16,
+		OINC_ | gc.TUINT16:
 		a = x86.AINCW
 
-	case gc.OINC<<16 | gc.TINT32,
-		gc.OINC<<16 | gc.TUINT32,
-		gc.OINC<<16 | gc.TPTR32:
+	case OINC_ | gc.TINT32,
+		OINC_ | gc.TUINT32,
+		OINC_ | gc.TPTR32:
 		a = x86.AINCL
 
-	case gc.ODEC<<16 | gc.TINT8,
-		gc.ODEC<<16 | gc.TUINT8:
+	case ODEC_ | gc.TINT8,
+		ODEC_ | gc.TUINT8:
 		a = x86.ADECB
 
-	case gc.ODEC<<16 | gc.TINT16,
-		gc.ODEC<<16 | gc.TUINT16:
+	case ODEC_ | gc.TINT16,
+		ODEC_ | gc.TUINT16:
 		a = x86.ADECW
 
-	case gc.ODEC<<16 | gc.TINT32,
-		gc.ODEC<<16 | gc.TUINT32,
-		gc.ODEC<<16 | gc.TPTR32:
+	case ODEC_ | gc.TINT32,
+		ODEC_ | gc.TUINT32,
+		ODEC_ | gc.TPTR32:
 		a = x86.ADECL
 
-	case gc.OCOM<<16 | gc.TINT8,
-		gc.OCOM<<16 | gc.TUINT8:
+	case OCOM_ | gc.TINT8,
+		OCOM_ | gc.TUINT8:
 		a = x86.ANOTB
 
-	case gc.OCOM<<16 | gc.TINT16,
-		gc.OCOM<<16 | gc.TUINT16:
+	case OCOM_ | gc.TINT16,
+		OCOM_ | gc.TUINT16:
 		a = x86.ANOTW
 
-	case gc.OCOM<<16 | gc.TINT32,
-		gc.OCOM<<16 | gc.TUINT32,
-		gc.OCOM<<16 | gc.TPTR32:
+	case OCOM_ | gc.TINT32,
+		OCOM_ | gc.TUINT32,
+		OCOM_ | gc.TPTR32:
 		a = x86.ANOTL
 
-	case gc.OMINUS<<16 | gc.TINT8,
-		gc.OMINUS<<16 | gc.TUINT8:
+	case OMINUS_ | gc.TINT8,
+		OMINUS_ | gc.TUINT8:
 		a = x86.ANEGB
 
-	case gc.OMINUS<<16 | gc.TINT16,
-		gc.OMINUS<<16 | gc.TUINT16:
+	case OMINUS_ | gc.TINT16,
+		OMINUS_ | gc.TUINT16:
 		a = x86.ANEGW
 
-	case gc.OMINUS<<16 | gc.TINT32,
-		gc.OMINUS<<16 | gc.TUINT32,
-		gc.OMINUS<<16 | gc.TPTR32:
+	case OMINUS_ | gc.TINT32,
+		OMINUS_ | gc.TUINT32,
+		OMINUS_ | gc.TPTR32:
 		a = x86.ANEGL
 
-	case gc.OAND<<16 | gc.TINT8,
-		gc.OAND<<16 | gc.TUINT8:
+	case OAND_ | gc.TINT8,
+		OAND_ | gc.TUINT8:
 		a = x86.AANDB
 
-	case gc.OAND<<16 | gc.TINT16,
-		gc.OAND<<16 | gc.TUINT16:
+	case OAND_ | gc.TINT16,
+		OAND_ | gc.TUINT16:
 		a = x86.AANDW
 
-	case gc.OAND<<16 | gc.TINT32,
-		gc.OAND<<16 | gc.TUINT32,
-		gc.OAND<<16 | gc.TPTR32:
+	case OAND_ | gc.TINT32,
+		OAND_ | gc.TUINT32,
+		OAND_ | gc.TPTR32:
 		a = x86.AANDL
 
-	case gc.OOR<<16 | gc.TINT8,
-		gc.OOR<<16 | gc.TUINT8:
+	case OOR_ | gc.TINT8,
+		OOR_ | gc.TUINT8:
 		a = x86.AORB
 
-	case gc.OOR<<16 | gc.TINT16,
-		gc.OOR<<16 | gc.TUINT16:
+	case OOR_ | gc.TINT16,
+		OOR_ | gc.TUINT16:
 		a = x86.AORW
 
-	case gc.OOR<<16 | gc.TINT32,
-		gc.OOR<<16 | gc.TUINT32,
-		gc.OOR<<16 | gc.TPTR32:
+	case OOR_ | gc.TINT32,
+		OOR_ | gc.TUINT32,
+		OOR_ | gc.TPTR32:
 		a = x86.AORL
 
-	case gc.OXOR<<16 | gc.TINT8,
-		gc.OXOR<<16 | gc.TUINT8:
+	case OXOR_ | gc.TINT8,
+		OXOR_ | gc.TUINT8:
 		a = x86.AXORB
 
-	case gc.OXOR<<16 | gc.TINT16,
-		gc.OXOR<<16 | gc.TUINT16:
+	case OXOR_ | gc.TINT16,
+		OXOR_ | gc.TUINT16:
 		a = x86.AXORW
 
-	case gc.OXOR<<16 | gc.TINT32,
-		gc.OXOR<<16 | gc.TUINT32,
-		gc.OXOR<<16 | gc.TPTR32:
+	case OXOR_ | gc.TINT32,
+		OXOR_ | gc.TUINT32,
+		OXOR_ | gc.TPTR32:
 		a = x86.AXORL
 
-	case gc.OLROT<<16 | gc.TINT8,
-		gc.OLROT<<16 | gc.TUINT8:
+	case OLROT_ | gc.TINT8,
+		OLROT_ | gc.TUINT8:
 		a = x86.AROLB
 
-	case gc.OLROT<<16 | gc.TINT16,
-		gc.OLROT<<16 | gc.TUINT16:
+	case OLROT_ | gc.TINT16,
+		OLROT_ | gc.TUINT16:
 		a = x86.AROLW
 
-	case gc.OLROT<<16 | gc.TINT32,
-		gc.OLROT<<16 | gc.TUINT32,
-		gc.OLROT<<16 | gc.TPTR32:
+	case OLROT_ | gc.TINT32,
+		OLROT_ | gc.TUINT32,
+		OLROT_ | gc.TPTR32:
 		a = x86.AROLL
 
-	case gc.OLSH<<16 | gc.TINT8,
-		gc.OLSH<<16 | gc.TUINT8:
+	case OLSH_ | gc.TINT8,
+		OLSH_ | gc.TUINT8:
 		a = x86.ASHLB
 
-	case gc.OLSH<<16 | gc.TINT16,
-		gc.OLSH<<16 | gc.TUINT16:
+	case OLSH_ | gc.TINT16,
+		OLSH_ | gc.TUINT16:
 		a = x86.ASHLW
 
-	case gc.OLSH<<16 | gc.TINT32,
-		gc.OLSH<<16 | gc.TUINT32,
-		gc.OLSH<<16 | gc.TPTR32:
+	case OLSH_ | gc.TINT32,
+		OLSH_ | gc.TUINT32,
+		OLSH_ | gc.TPTR32:
 		a = x86.ASHLL
 
-	case gc.ORSH<<16 | gc.TUINT8:
+	case ORSH_ | gc.TUINT8:
 		a = x86.ASHRB
 
-	case gc.ORSH<<16 | gc.TUINT16:
+	case ORSH_ | gc.TUINT16:
 		a = x86.ASHRW
 
-	case gc.ORSH<<16 | gc.TUINT32,
-		gc.ORSH<<16 | gc.TPTR32:
+	case ORSH_ | gc.TUINT32,
+		ORSH_ | gc.TPTR32:
 		a = x86.ASHRL
 
-	case gc.ORSH<<16 | gc.TINT8:
+	case ORSH_ | gc.TINT8:
 		a = x86.ASARB
 
-	case gc.ORSH<<16 | gc.TINT16:
+	case ORSH_ | gc.TINT16:
 		a = x86.ASARW
 
-	case gc.ORSH<<16 | gc.TINT32:
+	case ORSH_ | gc.TINT32:
 		a = x86.ASARL
 
-	case gc.OHMUL<<16 | gc.TINT8,
-		gc.OMUL<<16 | gc.TINT8,
-		gc.OMUL<<16 | gc.TUINT8:
+	case OHMUL_ | gc.TINT8,
+		OMUL_ | gc.TINT8,
+		OMUL_ | gc.TUINT8:
 		a = x86.AIMULB
 
-	case gc.OHMUL<<16 | gc.TINT16,
-		gc.OMUL<<16 | gc.TINT16,
-		gc.OMUL<<16 | gc.TUINT16:
+	case OHMUL_ | gc.TINT16,
+		OMUL_ | gc.TINT16,
+		OMUL_ | gc.TUINT16:
 		a = x86.AIMULW
 
-	case gc.OHMUL<<16 | gc.TINT32,
-		gc.OMUL<<16 | gc.TINT32,
-		gc.OMUL<<16 | gc.TUINT32,
-		gc.OMUL<<16 | gc.TPTR32:
+	case OHMUL_ | gc.TINT32,
+		OMUL_ | gc.TINT32,
+		OMUL_ | gc.TUINT32,
+		OMUL_ | gc.TPTR32:
 		a = x86.AIMULL
 
-	case gc.OHMUL<<16 | gc.TUINT8:
+	case OHMUL_ | gc.TUINT8:
 		a = x86.AMULB
 
-	case gc.OHMUL<<16 | gc.TUINT16:
+	case OHMUL_ | gc.TUINT16:
 		a = x86.AMULW
 
-	case gc.OHMUL<<16 | gc.TUINT32,
-		gc.OHMUL<<16 | gc.TPTR32:
+	case OHMUL_ | gc.TUINT32,
+		OHMUL_ | gc.TPTR32:
 		a = x86.AMULL
 
-	case gc.ODIV<<16 | gc.TINT8,
-		gc.OMOD<<16 | gc.TINT8:
+	case ODIV_ | gc.TINT8,
+		OMOD_ | gc.TINT8:
 		a = x86.AIDIVB
 
-	case gc.ODIV<<16 | gc.TUINT8,
-		gc.OMOD<<16 | gc.TUINT8:
+	case ODIV_ | gc.TUINT8,
+		OMOD_ | gc.TUINT8:
 		a = x86.ADIVB
 
-	case gc.ODIV<<16 | gc.TINT16,
-		gc.OMOD<<16 | gc.TINT16:
+	case ODIV_ | gc.TINT16,
+		OMOD_ | gc.TINT16:
 		a = x86.AIDIVW
 
-	case gc.ODIV<<16 | gc.TUINT16,
-		gc.OMOD<<16 | gc.TUINT16:
+	case ODIV_ | gc.TUINT16,
+		OMOD_ | gc.TUINT16:
 		a = x86.ADIVW
 
-	case gc.ODIV<<16 | gc.TINT32,
-		gc.OMOD<<16 | gc.TINT32:
+	case ODIV_ | gc.TINT32,
+		OMOD_ | gc.TINT32:
 		a = x86.AIDIVL
 
-	case gc.ODIV<<16 | gc.TUINT32,
-		gc.ODIV<<16 | gc.TPTR32,
-		gc.OMOD<<16 | gc.TUINT32,
-		gc.OMOD<<16 | gc.TPTR32:
+	case ODIV_ | gc.TUINT32,
+		ODIV_ | gc.TPTR32,
+		OMOD_ | gc.TUINT32,
+		OMOD_ | gc.TPTR32:
 		a = x86.ADIVL
 
-	case gc.OEXTEND<<16 | gc.TINT16:
+	case OEXTEND_ | gc.TINT16:
 		a = x86.ACWD
 
-	case gc.OEXTEND<<16 | gc.TINT32:
+	case OEXTEND_ | gc.TINT32:
 		a = x86.ACDQ
 	}
 
 	return a
 }
 
-func foptoas(op int, t *gc.Type, flg int) int {
+func foptoas(op gc.Op, t *gc.Type, flg int) int {
 	a := obj.AXXX
-	et := int(gc.Simtype[t.Etype])
+	et := gc.Simtype[t.Etype]
+
+	// avoid constant conversions in switches below
+	const (
+		OCMP_   = uint32(gc.OCMP) << 16
+		OAS_    = uint32(gc.OAS) << 16
+		OADD_   = uint32(gc.OADD) << 16
+		OSUB_   = uint32(gc.OSUB) << 16
+		OMUL_   = uint32(gc.OMUL) << 16
+		ODIV_   = uint32(gc.ODIV) << 16
+		OMINUS_ = uint32(gc.OMINUS) << 16
+	)
 
 	if !gc.Thearch.Use387 {
 		switch uint32(op)<<16 | uint32(et) {
 		default:
-			gc.Fatal("foptoas-sse: no entry %v-%v", gc.Oconv(int(op), 0), t)
+			gc.Fatalf("foptoas-sse: no entry %v-%v", gc.Oconv(int(op), 0), t)
 
-		case gc.OCMP<<16 | gc.TFLOAT32:
+		case OCMP_ | gc.TFLOAT32:
 			a = x86.AUCOMISS
 
-		case gc.OCMP<<16 | gc.TFLOAT64:
+		case OCMP_ | gc.TFLOAT64:
 			a = x86.AUCOMISD
 
-		case gc.OAS<<16 | gc.TFLOAT32:
+		case OAS_ | gc.TFLOAT32:
 			a = x86.AMOVSS
 
-		case gc.OAS<<16 | gc.TFLOAT64:
+		case OAS_ | gc.TFLOAT64:
 			a = x86.AMOVSD
 
-		case gc.OADD<<16 | gc.TFLOAT32:
+		case OADD_ | gc.TFLOAT32:
 			a = x86.AADDSS
 
-		case gc.OADD<<16 | gc.TFLOAT64:
+		case OADD_ | gc.TFLOAT64:
 			a = x86.AADDSD
 
-		case gc.OSUB<<16 | gc.TFLOAT32:
+		case OSUB_ | gc.TFLOAT32:
 			a = x86.ASUBSS
 
-		case gc.OSUB<<16 | gc.TFLOAT64:
+		case OSUB_ | gc.TFLOAT64:
 			a = x86.ASUBSD
 
-		case gc.OMUL<<16 | gc.TFLOAT32:
+		case OMUL_ | gc.TFLOAT32:
 			a = x86.AMULSS
 
-		case gc.OMUL<<16 | gc.TFLOAT64:
+		case OMUL_ | gc.TFLOAT64:
 			a = x86.AMULSD
 
-		case gc.ODIV<<16 | gc.TFLOAT32:
+		case ODIV_ | gc.TFLOAT32:
 			a = x86.ADIVSS
 
-		case gc.ODIV<<16 | gc.TFLOAT64:
+		case ODIV_ | gc.TFLOAT64:
 			a = x86.ADIVSD
 		}
 
@@ -470,83 +511,83 @@ func foptoas(op int, t *gc.Type, flg int) int {
 	}
 
 	switch uint32(op)<<16 | (uint32(et)<<8 | uint32(flg)) {
-	case gc.OADD<<16 | (gc.TFLOAT32<<8 | 0):
+	case OADD_ | (gc.TFLOAT32<<8 | 0):
 		return x86.AFADDF
 
-	case gc.OADD<<16 | (gc.TFLOAT64<<8 | 0):
+	case OADD_ | (gc.TFLOAT64<<8 | 0):
 		return x86.AFADDD
 
-	case gc.OADD<<16 | (gc.TFLOAT64<<8 | Fpop):
+	case OADD_ | (gc.TFLOAT64<<8 | Fpop):
 		return x86.AFADDDP
 
-	case gc.OSUB<<16 | (gc.TFLOAT32<<8 | 0):
+	case OSUB_ | (gc.TFLOAT32<<8 | 0):
 		return x86.AFSUBF
 
-	case gc.OSUB<<16 | (gc.TFLOAT32<<8 | Frev):
+	case OSUB_ | (gc.TFLOAT32<<8 | Frev):
 		return x86.AFSUBRF
 
-	case gc.OSUB<<16 | (gc.TFLOAT64<<8 | 0):
+	case OSUB_ | (gc.TFLOAT64<<8 | 0):
 		return x86.AFSUBD
 
-	case gc.OSUB<<16 | (gc.TFLOAT64<<8 | Frev):
+	case OSUB_ | (gc.TFLOAT64<<8 | Frev):
 		return x86.AFSUBRD
 
-	case gc.OSUB<<16 | (gc.TFLOAT64<<8 | Fpop):
+	case OSUB_ | (gc.TFLOAT64<<8 | Fpop):
 		return x86.AFSUBDP
 
-	case gc.OSUB<<16 | (gc.TFLOAT64<<8 | (Fpop | Frev)):
+	case OSUB_ | (gc.TFLOAT64<<8 | (Fpop | Frev)):
 		return x86.AFSUBRDP
 
-	case gc.OMUL<<16 | (gc.TFLOAT32<<8 | 0):
+	case OMUL_ | (gc.TFLOAT32<<8 | 0):
 		return x86.AFMULF
 
-	case gc.OMUL<<16 | (gc.TFLOAT64<<8 | 0):
+	case OMUL_ | (gc.TFLOAT64<<8 | 0):
 		return x86.AFMULD
 
-	case gc.OMUL<<16 | (gc.TFLOAT64<<8 | Fpop):
+	case OMUL_ | (gc.TFLOAT64<<8 | Fpop):
 		return x86.AFMULDP
 
-	case gc.ODIV<<16 | (gc.TFLOAT32<<8 | 0):
+	case ODIV_ | (gc.TFLOAT32<<8 | 0):
 		return x86.AFDIVF
 
-	case gc.ODIV<<16 | (gc.TFLOAT32<<8 | Frev):
+	case ODIV_ | (gc.TFLOAT32<<8 | Frev):
 		return x86.AFDIVRF
 
-	case gc.ODIV<<16 | (gc.TFLOAT64<<8 | 0):
+	case ODIV_ | (gc.TFLOAT64<<8 | 0):
 		return x86.AFDIVD
 
-	case gc.ODIV<<16 | (gc.TFLOAT64<<8 | Frev):
+	case ODIV_ | (gc.TFLOAT64<<8 | Frev):
 		return x86.AFDIVRD
 
-	case gc.ODIV<<16 | (gc.TFLOAT64<<8 | Fpop):
+	case ODIV_ | (gc.TFLOAT64<<8 | Fpop):
 		return x86.AFDIVDP
 
-	case gc.ODIV<<16 | (gc.TFLOAT64<<8 | (Fpop | Frev)):
+	case ODIV_ | (gc.TFLOAT64<<8 | (Fpop | Frev)):
 		return x86.AFDIVRDP
 
-	case gc.OCMP<<16 | (gc.TFLOAT32<<8 | 0):
+	case OCMP_ | (gc.TFLOAT32<<8 | 0):
 		return x86.AFCOMF
 
-	case gc.OCMP<<16 | (gc.TFLOAT32<<8 | Fpop):
+	case OCMP_ | (gc.TFLOAT32<<8 | Fpop):
 		return x86.AFCOMFP
 
-	case gc.OCMP<<16 | (gc.TFLOAT64<<8 | 0):
+	case OCMP_ | (gc.TFLOAT64<<8 | 0):
 		return x86.AFCOMD
 
-	case gc.OCMP<<16 | (gc.TFLOAT64<<8 | Fpop):
+	case OCMP_ | (gc.TFLOAT64<<8 | Fpop):
 		return x86.AFCOMDP
 
-	case gc.OCMP<<16 | (gc.TFLOAT64<<8 | Fpop2):
+	case OCMP_ | (gc.TFLOAT64<<8 | Fpop2):
 		return x86.AFCOMDPP
 
-	case gc.OMINUS<<16 | (gc.TFLOAT32<<8 | 0):
+	case OMINUS_ | (gc.TFLOAT32<<8 | 0):
 		return x86.AFCHS
 
-	case gc.OMINUS<<16 | (gc.TFLOAT64<<8 | 0):
+	case OMINUS_ | (gc.TFLOAT64<<8 | 0):
 		return x86.AFCHS
 	}
 
-	gc.Fatal("foptoas %v %v %#x", gc.Oconv(int(op), 0), t, flg)
+	gc.Fatalf("foptoas %v %v %#x", gc.Oconv(int(op), 0), t, flg)
 	return 0
 }
 
@@ -583,8 +624,8 @@ func ginscon(as int, c int64, n2 *gc.Node) {
 	gins(as, &n1, n2)
 }
 
-func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
-	if gc.Isint[t.Etype] || int(t.Etype) == gc.Tptr {
+func ginscmp(op gc.Op, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
+	if gc.Isint[t.Etype] || t.Etype == gc.Tptr {
 		if (n1.Op == gc.OLITERAL || n1.Op == gc.OADDR && n1.Left.Op == gc.ONAME) && n2.Op != gc.OLITERAL {
 			// Reverse comparison to place constant (including address constant) last.
 			op = gc.Brrev(op)
@@ -594,7 +635,15 @@ func ginscmp(op int, t *gc.Type, n1, n2 *gc.Node, likely int) *obj.Prog {
 
 	// General case.
 	var r1, r2, g1, g2 gc.Node
-	if n1.Op == gc.ONAME && n1.Class&gc.PHEAP == 0 || n1.Op == gc.OINDREG {
+
+	// A special case to make write barriers more efficient.
+	// Comparing the first field of a named struct can be done directly.
+	base := n1
+	if n1.Op == gc.ODOT && n1.Left.Type.Etype == gc.TSTRUCT && n1.Left.Type.Type.Sym == n1.Right.Sym {
+		base = n1.Left
+	}
+
+	if base.Op == gc.ONAME && base.Class&gc.PHEAP == 0 || n1.Op == gc.OINDREG {
 		r1 = *n1
 	} else {
 		gc.Regalloc(&r1, t, n1)
@@ -655,11 +704,11 @@ var nsclean int
  */
 func split64(n *gc.Node, lo *gc.Node, hi *gc.Node) {
 	if !gc.Is64(n.Type) {
-		gc.Fatal("split64 %v", n.Type)
+		gc.Fatalf("split64 %v", n.Type)
 	}
 
 	if nsclean >= len(sclean) {
-		gc.Fatal("split64 clean")
+		gc.Fatalf("split64 clean")
 	}
 	sclean[nsclean].Op = gc.OEMPTY
 	nsclean++
@@ -714,7 +763,7 @@ func split64(n *gc.Node, lo *gc.Node, hi *gc.Node) {
 
 func splitclean() {
 	if nsclean <= 0 {
-		gc.Fatal("splitclean")
+		gc.Fatalf("splitclean")
 	}
 	nsclean--
 	if sclean[nsclean].Op != gc.OEMPTY {
@@ -805,7 +854,7 @@ func gmove(f *gc.Node, t *gc.Node) {
 	switch uint32(ft)<<16 | uint32(tt) {
 	default:
 		// should not happen
-		gc.Fatal("gmove %v -> %v", f, t)
+		gc.Fatalf("gmove %v -> %v", f, t)
 		return
 
 		/*
@@ -911,15 +960,13 @@ func gmove(f *gc.Node, t *gc.Node) {
 		} else {
 			// Implementation of conversion-free x = y for int64 or uint64 x.
 			// This is generated by the code that copies small values out of closures,
-			// and that code has DX live, so avoid DX and use CX instead.
+			// and that code has DX live, so avoid DX and just use AX twice.
 			var r1 gc.Node
 			gc.Nodreg(&r1, gc.Types[gc.TUINT32], x86.REG_AX)
-			var r2 gc.Node
-			gc.Nodreg(&r2, gc.Types[gc.TUINT32], x86.REG_CX)
 			gins(x86.AMOVL, &flo, &r1)
-			gins(x86.AMOVL, &fhi, &r2)
 			gins(x86.AMOVL, &r1, &tlo)
-			gins(x86.AMOVL, &r2, &thi)
+			gins(x86.AMOVL, &fhi, &r1)
+			gins(x86.AMOVL, &r1, &thi)
 		}
 
 		splitclean()
@@ -1151,14 +1198,17 @@ func floatmove(f *gc.Node, t *gc.Node) {
 
 		// if 0 > v { answer = 0 }
 		gins(x86.AFMOVD, &zerof, &f0)
-
-		gins(x86.AFUCOMIP, &f0, &f1)
+		gins(x86.AFUCOMP, &f0, &f1)
+		gins(x86.AFSTSW, nil, &ax)
+		gins(x86.ASAHF, nil, nil)
 		p1 := gc.Gbranch(optoas(gc.OGT, gc.Types[tt]), nil, 0)
 
 		// if 1<<64 <= v { answer = 0 too }
 		gins(x86.AFMOVD, &two64f, &f0)
 
-		gins(x86.AFUCOMIP, &f0, &f1)
+		gins(x86.AFUCOMP, &f0, &f1)
+		gins(x86.AFSTSW, nil, &ax)
+		gins(x86.ASAHF, nil, nil)
 		p2 := gc.Gbranch(optoas(gc.OGT, gc.Types[tt]), nil, 0)
 		gc.Patch(p1, gc.Pc)
 		gins(x86.AFMOVVP, &f0, t) // don't care about t, but will pop the stack
@@ -1188,7 +1238,9 @@ func floatmove(f *gc.Node, t *gc.Node) {
 		// actual work
 		gins(x86.AFMOVD, &two63f, &f0)
 
-		gins(x86.AFUCOMIP, &f0, &f1)
+		gins(x86.AFUCOMP, &f0, &f1)
+		gins(x86.AFSTSW, nil, &ax)
+		gins(x86.ASAHF, nil, nil)
 		p2 = gc.Gbranch(optoas(gc.OLE, gc.Types[tt]), nil, 0)
 		gins(x86.AFMOVVP, &f0, t)
 		p3 := gc.Gbranch(obj.AJMP, nil, 0)
@@ -1372,7 +1424,7 @@ func floatmove_387(f *gc.Node, t *gc.Node) {
 		gmove(f, &t1)
 		switch tt {
 		default:
-			gc.Fatal("gmove %v", t)
+			gc.Fatalf("gmove %v", t)
 
 		case gc.TINT8:
 			gins(x86.ACMPL, &t1, ncon(-0x80&(1<<32-1)))
@@ -1483,7 +1535,7 @@ func floatmove_387(f *gc.Node, t *gc.Node) {
 		}
 		if gc.Ismem(t) {
 			if f.Op != gc.OREGISTER || f.Reg != x86.REG_F0 {
-				gc.Fatal("gmove %v", f)
+				gc.Fatalf("gmove %v", f)
 			}
 			a = x86.AFMOVFP
 			if ft == gc.TFLOAT64 {
@@ -1551,7 +1603,7 @@ hardmem:
 
 	// should not happen
 fatal:
-	gc.Fatal("gmove %v -> %v", gc.Nconv(f, obj.FmtLong), gc.Nconv(t, obj.FmtLong))
+	gc.Fatalf("gmove %v -> %v", gc.Nconv(f, obj.FmtLong), gc.Nconv(t, obj.FmtLong))
 
 	return
 }
@@ -1567,7 +1619,7 @@ func floatmove_sse(f *gc.Node, t *gc.Node) {
 	switch uint32(ft)<<16 | uint32(tt) {
 	// should not happen
 	default:
-		gc.Fatal("gmove %v -> %v", f, t)
+		gc.Fatalf("gmove %v -> %v", f, t)
 
 		return
 
@@ -1703,13 +1755,13 @@ func samaddr(f *gc.Node, t *gc.Node) bool {
  */
 func gins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
 	if as == x86.AFMOVF && f != nil && f.Op == gc.OREGISTER && t != nil && t.Op == gc.OREGISTER {
-		gc.Fatal("gins MOVF reg, reg")
+		gc.Fatalf("gins MOVF reg, reg")
 	}
 	if as == x86.ACVTSD2SS && f != nil && f.Op == gc.OLITERAL {
-		gc.Fatal("gins CVTSD2SS const")
+		gc.Fatalf("gins CVTSD2SS const")
 	}
 	if as == x86.AMOVSD && t != nil && t.Op == gc.OREGISTER && t.Reg == x86.REG_F0 {
-		gc.Fatal("gins MOVSD into F0")
+		gc.Fatalf("gins MOVSD into F0")
 	}
 
 	if as == x86.AMOVL && f != nil && f.Op == gc.OADDR && f.Left.Op == gc.ONAME && f.Left.Class != gc.PEXTERN && f.Left.Class != gc.PFUNC {
@@ -1731,7 +1783,7 @@ func gins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
 
 	case x86.ALEAL:
 		if f != nil && gc.Isconst(f, gc.CTNIL) {
-			gc.Fatal("gins LEAL nil %v", f.Type)
+			gc.Fatalf("gins LEAL nil %v", f.Type)
 		}
 	}
 
@@ -1758,11 +1810,11 @@ func gins(as int, f *gc.Node, t *gc.Node) *obj.Prog {
 	if true && w != 0 && f != nil && (p.From.Width > int64(w) || p.To.Width > int64(w)) {
 		gc.Dump("bad width from:", f)
 		gc.Dump("bad width to:", t)
-		gc.Fatal("bad width: %v (%d, %d)\n", p, p.From.Width, p.To.Width)
+		gc.Fatalf("bad width: %v (%d, %d)\n", p, p.From.Width, p.To.Width)
 	}
 
 	if p.To.Type == obj.TYPE_ADDR && w > 0 {
-		gc.Fatal("bad use of addr: %v", p)
+		gc.Fatalf("bad use of addr: %v", p)
 	}
 
 	return p
diff --git a/src/cmd/compile/internal/x86/peep.go b/src/cmd/compile/internal/x86/peep.go
index 8b50eab..63e64cb 100644
--- a/src/cmd/compile/internal/x86/peep.go
+++ b/src/cmd/compile/internal/x86/peep.go
@@ -660,10 +660,10 @@ func copyu(p *obj.Prog, v *obj.Addr, s *obj.Addr) int {
  */
 func copyas(a *obj.Addr, v *obj.Addr) bool {
 	if x86.REG_AL <= a.Reg && a.Reg <= x86.REG_BL {
-		gc.Fatal("use of byte register")
+		gc.Fatalf("use of byte register")
 	}
 	if x86.REG_AL <= v.Reg && v.Reg <= x86.REG_BL {
-		gc.Fatal("use of byte register")
+		gc.Fatalf("use of byte register")
 	}
 
 	if a.Type != v.Type || a.Name != v.Name || a.Reg != v.Reg {
diff --git a/src/cmd/compile/internal/x86/prog.go b/src/cmd/compile/internal/x86/prog.go
index f96a1aa..ccac290 100644
--- a/src/cmd/compile/internal/x86/prog.go
+++ b/src/cmd/compile/internal/x86/prog.go
@@ -31,236 +31,241 @@ var (
 //
 // The table is formatted for 8-space tabs.
 var progtable = [x86.ALAST]obj.ProgInfo{
-	obj.ATYPE:     {gc.Pseudo | gc.Skip, 0, 0, 0},
-	obj.ATEXT:     {gc.Pseudo, 0, 0, 0},
-	obj.AFUNCDATA: {gc.Pseudo, 0, 0, 0},
-	obj.APCDATA:   {gc.Pseudo, 0, 0, 0},
-	obj.AUNDEF:    {gc.Break, 0, 0, 0},
-	obj.AUSEFIELD: {gc.OK, 0, 0, 0},
-	obj.ACHECKNIL: {gc.LeftRead, 0, 0, 0},
-	obj.AVARDEF:   {gc.Pseudo | gc.RightWrite, 0, 0, 0},
-	obj.AVARKILL:  {gc.Pseudo | gc.RightWrite, 0, 0, 0},
+	obj.ATYPE:     {Flags: gc.Pseudo | gc.Skip},
+	obj.ATEXT:     {Flags: gc.Pseudo},
+	obj.AFUNCDATA: {Flags: gc.Pseudo},
+	obj.APCDATA:   {Flags: gc.Pseudo},
+	obj.AUNDEF:    {Flags: gc.Break},
+	obj.AUSEFIELD: {Flags: gc.OK},
+	obj.ACHECKNIL: {Flags: gc.LeftRead},
+	obj.AVARDEF:   {Flags: gc.Pseudo | gc.RightWrite},
+	obj.AVARKILL:  {Flags: gc.Pseudo | gc.RightWrite},
+	obj.AVARLIVE:  {Flags: gc.Pseudo | gc.LeftRead},
 
 	// NOP is an internal no-op that also stands
 	// for USED and SET annotations, not the Intel opcode.
-	obj.ANOP:       {gc.LeftRead | gc.RightWrite, 0, 0, 0},
-	x86.AADCL:      {gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.AADCW:      {gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.AADDB:      {gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AADDL:      {gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AADDW:      {gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AADDSD:     {gc.SizeD | gc.LeftRead | RightRdwr, 0, 0, 0},
-	x86.AADDSS:     {gc.SizeF | gc.LeftRead | RightRdwr, 0, 0, 0},
-	x86.AANDB:      {gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AANDL:      {gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AANDW:      {gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	obj.ACALL:      {gc.RightAddr | gc.Call | gc.KillCarry, 0, 0, 0},
-	x86.ACDQ:       {gc.OK, AX, AX | DX, 0},
-	x86.ACWD:       {gc.OK, AX, AX | DX, 0},
-	x86.ACLD:       {gc.OK, 0, 0, 0},
-	x86.ASTD:       {gc.OK, 0, 0, 0},
-	x86.ACMPB:      {gc.SizeB | gc.LeftRead | gc.RightRead | gc.SetCarry, 0, 0, 0},
-	x86.ACMPL:      {gc.SizeL | gc.LeftRead | gc.RightRead | gc.SetCarry, 0, 0, 0},
-	x86.ACMPW:      {gc.SizeW | gc.LeftRead | gc.RightRead | gc.SetCarry, 0, 0, 0},
-	x86.ACOMISD:    {gc.SizeD | gc.LeftRead | gc.RightRead | gc.SetCarry, 0, 0, 0},
-	x86.ACOMISS:    {gc.SizeF | gc.LeftRead | gc.RightRead | gc.SetCarry, 0, 0, 0},
-	x86.ACVTSD2SL:  {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ACVTSD2SS:  {gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ACVTSL2SD:  {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ACVTSL2SS:  {gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ACVTSS2SD:  {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ACVTSS2SL:  {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ACVTTSD2SL: {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ACVTTSS2SL: {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.ADECB:      {gc.SizeB | RightRdwr, 0, 0, 0},
-	x86.ADECL:      {gc.SizeL | RightRdwr, 0, 0, 0},
-	x86.ADECW:      {gc.SizeW | RightRdwr, 0, 0, 0},
-	x86.ADIVB:      {gc.SizeB | gc.LeftRead | gc.SetCarry, AX, AX, 0},
-	x86.ADIVL:      {gc.SizeL | gc.LeftRead | gc.SetCarry, AX | DX, AX | DX, 0},
-	x86.ADIVW:      {gc.SizeW | gc.LeftRead | gc.SetCarry, AX | DX, AX | DX, 0},
-	x86.ADIVSD:     {gc.SizeD | gc.LeftRead | RightRdwr, 0, 0, 0},
-	x86.ADIVSS:     {gc.SizeF | gc.LeftRead | RightRdwr, 0, 0, 0},
-	x86.AFLDCW:     {gc.SizeW | gc.LeftAddr, 0, 0, 0},
-	x86.AFSTCW:     {gc.SizeW | gc.RightAddr, 0, 0, 0},
-	x86.AFSTSW:     {gc.SizeW | gc.RightAddr | gc.RightWrite, 0, 0, 0},
-	x86.AFADDD:     {gc.SizeD | gc.LeftAddr | RightRdwr, 0, 0, 0},
-	x86.AFADDDP:    {gc.SizeD | gc.LeftAddr | RightRdwr, 0, 0, 0},
-	x86.AFADDF:     {gc.SizeF | gc.LeftAddr | RightRdwr, 0, 0, 0},
-	x86.AFCOMD:     {gc.SizeD | gc.LeftAddr | gc.RightRead, 0, 0, 0},
-	x86.AFCOMDP:    {gc.SizeD | gc.LeftAddr | gc.RightRead, 0, 0, 0},
-	x86.AFCOMDPP:   {gc.SizeD | gc.LeftAddr | gc.RightRead, 0, 0, 0},
-	x86.AFCOMF:     {gc.SizeF | gc.LeftAddr | gc.RightRead, 0, 0, 0},
-	x86.AFCOMFP:    {gc.SizeF | gc.LeftAddr | gc.RightRead, 0, 0, 0},
-	x86.AFUCOMIP:   {gc.SizeF | gc.LeftAddr | gc.RightRead, 0, 0, 0},
-	x86.AFCHS:      {gc.SizeD | RightRdwr, 0, 0, 0}, // also SizeF
+	obj.ANOP:       {Flags: gc.LeftRead | gc.RightWrite},
+	x86.AADCL:      {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry},
+	x86.AADCW:      {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry},
+	x86.AADDB:      {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AADDL:      {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AADDW:      {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AADDSD:     {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
+	x86.AADDSS:     {Flags: gc.SizeF | gc.LeftRead | RightRdwr},
+	x86.AANDB:      {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AANDL:      {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AANDW:      {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry},
+	obj.ACALL:      {Flags: gc.RightAddr | gc.Call | gc.KillCarry},
+	x86.ACDQ:       {Flags: gc.OK, Reguse: AX, Regset: AX | DX},
+	x86.ACWD:       {Flags: gc.OK, Reguse: AX, Regset: AX | DX},
+	x86.ACLD:       {Flags: gc.OK},
+	x86.ASTD:       {Flags: gc.OK},
+	x86.ACMPB:      {Flags: gc.SizeB | gc.LeftRead | gc.RightRead | gc.SetCarry},
+	x86.ACMPL:      {Flags: gc.SizeL | gc.LeftRead | gc.RightRead | gc.SetCarry},
+	x86.ACMPW:      {Flags: gc.SizeW | gc.LeftRead | gc.RightRead | gc.SetCarry},
+	x86.ACOMISD:    {Flags: gc.SizeD | gc.LeftRead | gc.RightRead | gc.SetCarry},
+	x86.ACOMISS:    {Flags: gc.SizeF | gc.LeftRead | gc.RightRead | gc.SetCarry},
+	x86.ACVTSD2SL:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ACVTSD2SS:  {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ACVTSL2SD:  {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ACVTSL2SS:  {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ACVTSS2SD:  {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ACVTSS2SL:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ACVTTSD2SL: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ACVTTSS2SL: {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.ADECB:      {Flags: gc.SizeB | RightRdwr},
+	x86.ADECL:      {Flags: gc.SizeL | RightRdwr},
+	x86.ADECW:      {Flags: gc.SizeW | RightRdwr},
+	x86.ADIVB:      {Flags: gc.SizeB | gc.LeftRead | gc.SetCarry, Reguse: AX, Regset: AX},
+	x86.ADIVL:      {Flags: gc.SizeL | gc.LeftRead | gc.SetCarry, Reguse: AX | DX, Regset: AX | DX},
+	x86.ADIVW:      {Flags: gc.SizeW | gc.LeftRead | gc.SetCarry, Reguse: AX | DX, Regset: AX | DX},
+	x86.ADIVSD:     {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
+	x86.ADIVSS:     {Flags: gc.SizeF | gc.LeftRead | RightRdwr},
+	x86.AFLDCW:     {Flags: gc.SizeW | gc.LeftAddr},
+	x86.AFSTCW:     {Flags: gc.SizeW | gc.RightAddr},
+	x86.AFSTSW:     {Flags: gc.SizeW | gc.RightAddr | gc.RightWrite},
+	x86.AFADDD:     {Flags: gc.SizeD | gc.LeftAddr | RightRdwr},
+	x86.AFADDDP:    {Flags: gc.SizeD | gc.LeftAddr | RightRdwr},
+	x86.AFADDF:     {Flags: gc.SizeF | gc.LeftAddr | RightRdwr},
+	x86.AFCOMD:     {Flags: gc.SizeD | gc.LeftAddr | gc.RightRead},
+	x86.AFCOMDP:    {Flags: gc.SizeD | gc.LeftAddr | gc.RightRead},
+	x86.AFCOMDPP:   {Flags: gc.SizeD | gc.LeftAddr | gc.RightRead},
+	x86.AFCOMF:     {Flags: gc.SizeF | gc.LeftAddr | gc.RightRead},
+	x86.AFCOMFP:    {Flags: gc.SizeF | gc.LeftAddr | gc.RightRead},
+	// NOTE(khr): don't use FUCOMI* instructions, not available
+	// on Pentium MMX.  See issue 13923.
+	//x86.AFUCOMIP:   {Flags: gc.SizeF | gc.LeftAddr | gc.RightRead},
+	x86.AFUCOMP:  {Flags: gc.SizeD | gc.LeftRead | gc.RightRead},
+	x86.AFUCOMPP: {Flags: gc.SizeD | gc.LeftRead | gc.RightRead},
+	x86.AFCHS:    {Flags: gc.SizeD | RightRdwr}, // also SizeF
 
-	x86.AFDIVDP:  {gc.SizeD | gc.LeftAddr | RightRdwr, 0, 0, 0},
-	x86.AFDIVF:   {gc.SizeF | gc.LeftAddr | RightRdwr, 0, 0, 0},
-	x86.AFDIVD:   {gc.SizeD | gc.LeftAddr | RightRdwr, 0, 0, 0},
-	x86.AFDIVRDP: {gc.SizeD | gc.LeftAddr | RightRdwr, 0, 0, 0},
-	x86.AFDIVRF:  {gc.SizeF | gc.LeftAddr | RightRdwr, 0, 0, 0},
-	x86.AFDIVRD:  {gc.SizeD | gc.LeftAddr | RightRdwr, 0, 0, 0},
-	x86.AFXCHD:   {gc.SizeD | LeftRdwr | RightRdwr, 0, 0, 0},
-	x86.AFSUBD:   {gc.SizeD | gc.LeftAddr | RightRdwr, 0, 0, 0},
-	x86.AFSUBDP:  {gc.SizeD | gc.LeftAddr | RightRdwr, 0, 0, 0},
-	x86.AFSUBF:   {gc.SizeF | gc.LeftAddr | RightRdwr, 0, 0, 0},
-	x86.AFSUBRD:  {gc.SizeD | gc.LeftAddr | RightRdwr, 0, 0, 0},
-	x86.AFSUBRDP: {gc.SizeD | gc.LeftAddr | RightRdwr, 0, 0, 0},
-	x86.AFSUBRF:  {gc.SizeF | gc.LeftAddr | RightRdwr, 0, 0, 0},
-	x86.AFMOVD:   {gc.SizeD | gc.LeftAddr | gc.RightWrite, 0, 0, 0},
-	x86.AFMOVF:   {gc.SizeF | gc.LeftAddr | gc.RightWrite, 0, 0, 0},
-	x86.AFMOVL:   {gc.SizeL | gc.LeftAddr | gc.RightWrite, 0, 0, 0},
-	x86.AFMOVW:   {gc.SizeW | gc.LeftAddr | gc.RightWrite, 0, 0, 0},
-	x86.AFMOVV:   {gc.SizeQ | gc.LeftAddr | gc.RightWrite, 0, 0, 0},
+	x86.AFDIVDP:  {Flags: gc.SizeD | gc.LeftAddr | RightRdwr},
+	x86.AFDIVF:   {Flags: gc.SizeF | gc.LeftAddr | RightRdwr},
+	x86.AFDIVD:   {Flags: gc.SizeD | gc.LeftAddr | RightRdwr},
+	x86.AFDIVRDP: {Flags: gc.SizeD | gc.LeftAddr | RightRdwr},
+	x86.AFDIVRF:  {Flags: gc.SizeF | gc.LeftAddr | RightRdwr},
+	x86.AFDIVRD:  {Flags: gc.SizeD | gc.LeftAddr | RightRdwr},
+	x86.AFXCHD:   {Flags: gc.SizeD | LeftRdwr | RightRdwr},
+	x86.AFSUBD:   {Flags: gc.SizeD | gc.LeftAddr | RightRdwr},
+	x86.AFSUBDP:  {Flags: gc.SizeD | gc.LeftAddr | RightRdwr},
+	x86.AFSUBF:   {Flags: gc.SizeF | gc.LeftAddr | RightRdwr},
+	x86.AFSUBRD:  {Flags: gc.SizeD | gc.LeftAddr | RightRdwr},
+	x86.AFSUBRDP: {Flags: gc.SizeD | gc.LeftAddr | RightRdwr},
+	x86.AFSUBRF:  {Flags: gc.SizeF | gc.LeftAddr | RightRdwr},
+	x86.AFMOVD:   {Flags: gc.SizeD | gc.LeftAddr | gc.RightWrite},
+	x86.AFMOVF:   {Flags: gc.SizeF | gc.LeftAddr | gc.RightWrite},
+	x86.AFMOVL:   {Flags: gc.SizeL | gc.LeftAddr | gc.RightWrite},
+	x86.AFMOVW:   {Flags: gc.SizeW | gc.LeftAddr | gc.RightWrite},
+	x86.AFMOVV:   {Flags: gc.SizeQ | gc.LeftAddr | gc.RightWrite},
 
 	// These instructions are marked as RightAddr
 	// so that the register optimizer does not try to replace the
 	// memory references with integer register references.
 	// But they do not use the previous value at the address, so
 	// we also mark them RightWrite.
-	x86.AFMOVDP:   {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.RightAddr, 0, 0, 0},
-	x86.AFMOVFP:   {gc.SizeF | gc.LeftRead | gc.RightWrite | gc.RightAddr, 0, 0, 0},
-	x86.AFMOVLP:   {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.RightAddr, 0, 0, 0},
-	x86.AFMOVWP:   {gc.SizeW | gc.LeftRead | gc.RightWrite | gc.RightAddr, 0, 0, 0},
-	x86.AFMOVVP:   {gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.RightAddr, 0, 0, 0},
-	x86.AFMULD:    {gc.SizeD | gc.LeftAddr | RightRdwr, 0, 0, 0},
-	x86.AFMULDP:   {gc.SizeD | gc.LeftAddr | RightRdwr, 0, 0, 0},
-	x86.AFMULF:    {gc.SizeF | gc.LeftAddr | RightRdwr, 0, 0, 0},
-	x86.AIDIVB:    {gc.SizeB | gc.LeftRead | gc.SetCarry, AX, AX, 0},
-	x86.AIDIVL:    {gc.SizeL | gc.LeftRead | gc.SetCarry, AX | DX, AX | DX, 0},
-	x86.AIDIVW:    {gc.SizeW | gc.LeftRead | gc.SetCarry, AX | DX, AX | DX, 0},
-	x86.AIMULB:    {gc.SizeB | gc.LeftRead | gc.SetCarry, AX, AX, 0},
-	x86.AIMULL:    {gc.SizeL | gc.LeftRead | gc.ImulAXDX | gc.SetCarry, 0, 0, 0},
-	x86.AIMULW:    {gc.SizeW | gc.LeftRead | gc.ImulAXDX | gc.SetCarry, 0, 0, 0},
-	x86.AINCB:     {gc.SizeB | RightRdwr, 0, 0, 0},
-	x86.AINCL:     {gc.SizeL | RightRdwr, 0, 0, 0},
-	x86.AINCW:     {gc.SizeW | RightRdwr, 0, 0, 0},
-	x86.AJCC:      {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJCS:      {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJEQ:      {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJGE:      {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJGT:      {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJHI:      {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJLE:      {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJLS:      {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJLT:      {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJMI:      {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJNE:      {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJOC:      {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJOS:      {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJPC:      {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJPL:      {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	x86.AJPS:      {gc.Cjmp | gc.UseCarry, 0, 0, 0},
-	obj.AJMP:      {gc.Jump | gc.Break | gc.KillCarry, 0, 0, 0},
-	x86.ALEAL:     {gc.LeftAddr | gc.RightWrite, 0, 0, 0},
-	x86.AMOVBLSX:  {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.AMOVBLZX:  {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.AMOVBWSX:  {gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.AMOVBWZX:  {gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.AMOVWLSX:  {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.AMOVWLZX:  {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv, 0, 0, 0},
-	x86.AMOVB:     {gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
-	x86.AMOVL:     {gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
-	x86.AMOVW:     {gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
-	x86.AMOVSB:    {gc.OK, DI | SI, DI | SI, 0},
-	x86.AMOVSL:    {gc.OK, DI | SI, DI | SI, 0},
-	x86.AMOVSW:    {gc.OK, DI | SI, DI | SI, 0},
-	obj.ADUFFCOPY: {gc.OK, DI | SI, DI | SI | CX, 0},
-	x86.AMOVSD:    {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
-	x86.AMOVSS:    {gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
+	x86.AFMOVDP:   {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.RightAddr},
+	x86.AFMOVFP:   {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.RightAddr},
+	x86.AFMOVLP:   {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.RightAddr},
+	x86.AFMOVWP:   {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.RightAddr},
+	x86.AFMOVVP:   {Flags: gc.SizeQ | gc.LeftRead | gc.RightWrite | gc.RightAddr},
+	x86.AFMULD:    {Flags: gc.SizeD | gc.LeftAddr | RightRdwr},
+	x86.AFMULDP:   {Flags: gc.SizeD | gc.LeftAddr | RightRdwr},
+	x86.AFMULF:    {Flags: gc.SizeF | gc.LeftAddr | RightRdwr},
+	x86.AIDIVB:    {Flags: gc.SizeB | gc.LeftRead | gc.SetCarry, Reguse: AX, Regset: AX},
+	x86.AIDIVL:    {Flags: gc.SizeL | gc.LeftRead | gc.SetCarry, Reguse: AX | DX, Regset: AX | DX},
+	x86.AIDIVW:    {Flags: gc.SizeW | gc.LeftRead | gc.SetCarry, Reguse: AX | DX, Regset: AX | DX},
+	x86.AIMULB:    {Flags: gc.SizeB | gc.LeftRead | gc.SetCarry, Reguse: AX, Regset: AX},
+	x86.AIMULL:    {Flags: gc.SizeL | gc.LeftRead | gc.ImulAXDX | gc.SetCarry},
+	x86.AIMULW:    {Flags: gc.SizeW | gc.LeftRead | gc.ImulAXDX | gc.SetCarry},
+	x86.AINCB:     {Flags: gc.SizeB | RightRdwr},
+	x86.AINCL:     {Flags: gc.SizeL | RightRdwr},
+	x86.AINCW:     {Flags: gc.SizeW | RightRdwr},
+	x86.AJCC:      {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJCS:      {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJEQ:      {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJGE:      {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJGT:      {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJHI:      {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJLE:      {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJLS:      {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJLT:      {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJMI:      {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJNE:      {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJOC:      {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJOS:      {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJPC:      {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJPL:      {Flags: gc.Cjmp | gc.UseCarry},
+	x86.AJPS:      {Flags: gc.Cjmp | gc.UseCarry},
+	obj.AJMP:      {Flags: gc.Jump | gc.Break | gc.KillCarry},
+	x86.ALEAL:     {Flags: gc.LeftAddr | gc.RightWrite},
+	x86.AMOVBLSX:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.AMOVBLZX:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.AMOVBWSX:  {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.AMOVBWZX:  {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.AMOVWLSX:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.AMOVWLZX:  {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Conv},
+	x86.AMOVB:     {Flags: gc.SizeB | gc.LeftRead | gc.RightWrite | gc.Move},
+	x86.AMOVL:     {Flags: gc.SizeL | gc.LeftRead | gc.RightWrite | gc.Move},
+	x86.AMOVW:     {Flags: gc.SizeW | gc.LeftRead | gc.RightWrite | gc.Move},
+	x86.AMOVSB:    {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI},
+	x86.AMOVSL:    {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI},
+	x86.AMOVSW:    {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI},
+	obj.ADUFFCOPY: {Flags: gc.OK, Reguse: DI | SI, Regset: DI | SI | CX},
+	x86.AMOVSD:    {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
+	x86.AMOVSS:    {Flags: gc.SizeF | gc.LeftRead | gc.RightWrite | gc.Move},
 
 	// We use MOVAPD as a faster synonym for MOVSD.
-	x86.AMOVAPD:   {gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move, 0, 0, 0},
-	x86.AMULB:     {gc.SizeB | gc.LeftRead | gc.SetCarry, AX, AX, 0},
-	x86.AMULL:     {gc.SizeL | gc.LeftRead | gc.SetCarry, AX, AX | DX, 0},
-	x86.AMULW:     {gc.SizeW | gc.LeftRead | gc.SetCarry, AX, AX | DX, 0},
-	x86.AMULSD:    {gc.SizeD | gc.LeftRead | RightRdwr, 0, 0, 0},
-	x86.AMULSS:    {gc.SizeF | gc.LeftRead | RightRdwr, 0, 0, 0},
-	x86.ANEGB:     {gc.SizeB | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.ANEGL:     {gc.SizeL | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.ANEGW:     {gc.SizeW | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.ANOTB:     {gc.SizeB | RightRdwr, 0, 0, 0},
-	x86.ANOTL:     {gc.SizeL | RightRdwr, 0, 0, 0},
-	x86.ANOTW:     {gc.SizeW | RightRdwr, 0, 0, 0},
-	x86.AORB:      {gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AORL:      {gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AORW:      {gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.APOPL:     {gc.SizeL | gc.RightWrite, 0, 0, 0},
-	x86.APUSHL:    {gc.SizeL | gc.LeftRead, 0, 0, 0},
-	x86.ARCLB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.ARCLL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.ARCLW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.ARCRB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.ARCRL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.ARCRW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.AREP:      {gc.OK, CX, CX, 0},
-	x86.AREPN:     {gc.OK, CX, CX, 0},
-	obj.ARET:      {gc.Break | gc.KillCarry, 0, 0, 0},
-	x86.AROLB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.AROLL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.AROLW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ARORB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ARORL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ARORW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASAHF:     {gc.OK, AX, AX, 0},
-	x86.ASALB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASALL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASALW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASARB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASARL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASARW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASBBB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.ASBBL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.ASBBW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry, 0, 0, 0},
-	x86.ASETCC:    {gc.SizeB | RightRdwr | gc.UseCarry, 0, 0, 0},
-	x86.ASETCS:    {gc.SizeB | RightRdwr | gc.UseCarry, 0, 0, 0},
-	x86.ASETEQ:    {gc.SizeB | RightRdwr | gc.UseCarry, 0, 0, 0},
-	x86.ASETGE:    {gc.SizeB | RightRdwr | gc.UseCarry, 0, 0, 0},
-	x86.ASETGT:    {gc.SizeB | RightRdwr | gc.UseCarry, 0, 0, 0},
-	x86.ASETHI:    {gc.SizeB | RightRdwr | gc.UseCarry, 0, 0, 0},
-	x86.ASETLE:    {gc.SizeB | RightRdwr | gc.UseCarry, 0, 0, 0},
-	x86.ASETLS:    {gc.SizeB | RightRdwr | gc.UseCarry, 0, 0, 0},
-	x86.ASETLT:    {gc.SizeB | RightRdwr | gc.UseCarry, 0, 0, 0},
-	x86.ASETMI:    {gc.SizeB | RightRdwr | gc.UseCarry, 0, 0, 0},
-	x86.ASETNE:    {gc.SizeB | RightRdwr | gc.UseCarry, 0, 0, 0},
-	x86.ASETOC:    {gc.SizeB | RightRdwr | gc.UseCarry, 0, 0, 0},
-	x86.ASETOS:    {gc.SizeB | RightRdwr | gc.UseCarry, 0, 0, 0},
-	x86.ASETPC:    {gc.SizeB | RightRdwr | gc.UseCarry, 0, 0, 0},
-	x86.ASETPL:    {gc.SizeB | RightRdwr | gc.UseCarry, 0, 0, 0},
-	x86.ASETPS:    {gc.SizeB | RightRdwr | gc.UseCarry, 0, 0, 0},
-	x86.ASHLB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASHLL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASHLW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASHRB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASHRL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASHRW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry, 0, 0, 0},
-	x86.ASTOSB:    {gc.OK, AX | DI, DI, 0},
-	x86.ASTOSL:    {gc.OK, AX | DI, DI, 0},
-	x86.ASTOSW:    {gc.OK, AX | DI, DI, 0},
-	obj.ADUFFZERO: {gc.OK, AX | DI, DI, 0},
-	x86.ASUBB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.ASUBL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.ASUBW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.ASUBSD:    {gc.SizeD | gc.LeftRead | RightRdwr, 0, 0, 0},
-	x86.ASUBSS:    {gc.SizeF | gc.LeftRead | RightRdwr, 0, 0, 0},
-	x86.ATESTB:    {gc.SizeB | gc.LeftRead | gc.RightRead | gc.SetCarry, 0, 0, 0},
-	x86.ATESTL:    {gc.SizeL | gc.LeftRead | gc.RightRead | gc.SetCarry, 0, 0, 0},
-	x86.ATESTW:    {gc.SizeW | gc.LeftRead | gc.RightRead | gc.SetCarry, 0, 0, 0},
-	x86.AUCOMISD:  {gc.SizeD | gc.LeftRead | gc.RightRead, 0, 0, 0},
-	x86.AUCOMISS:  {gc.SizeF | gc.LeftRead | gc.RightRead, 0, 0, 0},
-	x86.AXCHGB:    {gc.SizeB | LeftRdwr | RightRdwr, 0, 0, 0},
-	x86.AXCHGL:    {gc.SizeL | LeftRdwr | RightRdwr, 0, 0, 0},
-	x86.AXCHGW:    {gc.SizeW | LeftRdwr | RightRdwr, 0, 0, 0},
-	x86.AXORB:     {gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AXORL:     {gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
-	x86.AXORW:     {gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry, 0, 0, 0},
+	x86.AMOVAPD:   {Flags: gc.SizeD | gc.LeftRead | gc.RightWrite | gc.Move},
+	x86.AMULB:     {Flags: gc.SizeB | gc.LeftRead | gc.SetCarry, Reguse: AX, Regset: AX},
+	x86.AMULL:     {Flags: gc.SizeL | gc.LeftRead | gc.SetCarry, Reguse: AX, Regset: AX | DX},
+	x86.AMULW:     {Flags: gc.SizeW | gc.LeftRead | gc.SetCarry, Reguse: AX, Regset: AX | DX},
+	x86.AMULSD:    {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
+	x86.AMULSS:    {Flags: gc.SizeF | gc.LeftRead | RightRdwr},
+	x86.ANEGB:     {Flags: gc.SizeB | RightRdwr | gc.SetCarry},
+	x86.ANEGL:     {Flags: gc.SizeL | RightRdwr | gc.SetCarry},
+	x86.ANEGW:     {Flags: gc.SizeW | RightRdwr | gc.SetCarry},
+	x86.ANOTB:     {Flags: gc.SizeB | RightRdwr},
+	x86.ANOTL:     {Flags: gc.SizeL | RightRdwr},
+	x86.ANOTW:     {Flags: gc.SizeW | RightRdwr},
+	x86.AORB:      {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AORL:      {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AORW:      {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.APOPL:     {Flags: gc.SizeL | gc.RightWrite},
+	x86.APUSHL:    {Flags: gc.SizeL | gc.LeftRead},
+	x86.ARCLB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
+	x86.ARCLL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
+	x86.ARCLW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
+	x86.ARCRB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
+	x86.ARCRL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
+	x86.ARCRW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry | gc.UseCarry},
+	x86.AREP:      {Flags: gc.OK, Reguse: CX, Regset: CX},
+	x86.AREPN:     {Flags: gc.OK, Reguse: CX, Regset: CX},
+	obj.ARET:      {Flags: gc.Break | gc.KillCarry},
+	x86.AROLB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.AROLL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.AROLW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ARORB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ARORL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ARORW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASAHF:     {Flags: gc.OK, Reguse: AX, Regset: AX},
+	x86.ASALB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASALL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASALW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASARB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASARL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASARW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASBBB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry},
+	x86.ASBBL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry},
+	x86.ASBBW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry | gc.UseCarry},
+	x86.ASETCC:    {Flags: gc.SizeB | RightRdwr | gc.UseCarry},
+	x86.ASETCS:    {Flags: gc.SizeB | RightRdwr | gc.UseCarry},
+	x86.ASETEQ:    {Flags: gc.SizeB | RightRdwr | gc.UseCarry},
+	x86.ASETGE:    {Flags: gc.SizeB | RightRdwr | gc.UseCarry},
+	x86.ASETGT:    {Flags: gc.SizeB | RightRdwr | gc.UseCarry},
+	x86.ASETHI:    {Flags: gc.SizeB | RightRdwr | gc.UseCarry},
+	x86.ASETLE:    {Flags: gc.SizeB | RightRdwr | gc.UseCarry},
+	x86.ASETLS:    {Flags: gc.SizeB | RightRdwr | gc.UseCarry},
+	x86.ASETLT:    {Flags: gc.SizeB | RightRdwr | gc.UseCarry},
+	x86.ASETMI:    {Flags: gc.SizeB | RightRdwr | gc.UseCarry},
+	x86.ASETNE:    {Flags: gc.SizeB | RightRdwr | gc.UseCarry},
+	x86.ASETOC:    {Flags: gc.SizeB | RightRdwr | gc.UseCarry},
+	x86.ASETOS:    {Flags: gc.SizeB | RightRdwr | gc.UseCarry},
+	x86.ASETPC:    {Flags: gc.SizeB | RightRdwr | gc.UseCarry},
+	x86.ASETPL:    {Flags: gc.SizeB | RightRdwr | gc.UseCarry},
+	x86.ASETPS:    {Flags: gc.SizeB | RightRdwr | gc.UseCarry},
+	x86.ASHLB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASHLL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASHLW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASHRB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASHRL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASHRW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.ShiftCX | gc.SetCarry},
+	x86.ASTOSB:    {Flags: gc.OK, Reguse: AX | DI, Regset: DI},
+	x86.ASTOSL:    {Flags: gc.OK, Reguse: AX | DI, Regset: DI},
+	x86.ASTOSW:    {Flags: gc.OK, Reguse: AX | DI, Regset: DI},
+	obj.ADUFFZERO: {Flags: gc.OK, Reguse: AX | DI, Regset: DI},
+	x86.ASUBB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.ASUBL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.ASUBW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.ASUBSD:    {Flags: gc.SizeD | gc.LeftRead | RightRdwr},
+	x86.ASUBSS:    {Flags: gc.SizeF | gc.LeftRead | RightRdwr},
+	x86.ATESTB:    {Flags: gc.SizeB | gc.LeftRead | gc.RightRead | gc.SetCarry},
+	x86.ATESTL:    {Flags: gc.SizeL | gc.LeftRead | gc.RightRead | gc.SetCarry},
+	x86.ATESTW:    {Flags: gc.SizeW | gc.LeftRead | gc.RightRead | gc.SetCarry},
+	x86.AUCOMISD:  {Flags: gc.SizeD | gc.LeftRead | gc.RightRead},
+	x86.AUCOMISS:  {Flags: gc.SizeF | gc.LeftRead | gc.RightRead},
+	x86.AXCHGB:    {Flags: gc.SizeB | LeftRdwr | RightRdwr},
+	x86.AXCHGL:    {Flags: gc.SizeL | LeftRdwr | RightRdwr},
+	x86.AXCHGW:    {Flags: gc.SizeW | LeftRdwr | RightRdwr},
+	x86.AXORB:     {Flags: gc.SizeB | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AXORL:     {Flags: gc.SizeL | gc.LeftRead | RightRdwr | gc.SetCarry},
+	x86.AXORW:     {Flags: gc.SizeW | gc.LeftRead | RightRdwr | gc.SetCarry},
 }
 
 func proginfo(p *obj.Prog) {
 	info := &p.Info
 	*info = progtable[p.As]
 	if info.Flags == 0 {
-		gc.Fatal("unknown instruction %v", p)
+		gc.Fatalf("unknown instruction %v", p)
 	}
 
 	if (info.Flags&gc.ShiftCX != 0) && p.From.Type != obj.TYPE_CONST {
diff --git a/src/cmd/compile/internal/x86/reg.go b/src/cmd/compile/internal/x86/reg.go
index b3a5fdf..76d90b8 100644
--- a/src/cmd/compile/internal/x86/reg.go
+++ b/src/cmd/compile/internal/x86/reg.go
@@ -62,7 +62,11 @@ func regnames(n *int) []string {
 }
 
 func excludedregs() uint64 {
-	return RtoB(x86.REG_SP)
+	if gc.Ctxt.Flag_shared != 0 {
+		return RtoB(x86.REG_SP) | RtoB(x86.REG_CX)
+	} else {
+		return RtoB(x86.REG_SP)
+	}
 }
 
 func doregbits(r int) uint64 {
diff --git a/src/cmd/compile/main.go b/src/cmd/compile/main.go
index 7b69c34..3d11f51 100644
--- a/src/cmd/compile/main.go
+++ b/src/cmd/compile/main.go
@@ -8,14 +8,20 @@ import (
 	"cmd/compile/internal/amd64"
 	"cmd/compile/internal/arm"
 	"cmd/compile/internal/arm64"
+	"cmd/compile/internal/mips64"
 	"cmd/compile/internal/ppc64"
 	"cmd/compile/internal/x86"
 	"cmd/internal/obj"
 	"fmt"
+	"log"
 	"os"
 )
 
 func main() {
+	// disable timestamps for reproducible output
+	log.SetFlags(0)
+	log.SetPrefix("compile: ")
+
 	switch obj.Getgoarch() {
 	default:
 		fmt.Fprintf(os.Stderr, "compile: unknown architecture %q\n", obj.Getgoarch())
@@ -28,6 +34,8 @@ func main() {
 		arm.Main()
 	case "arm64":
 		arm64.Main()
+	case "mips64", "mips64le":
+		mips64.Main()
 	case "ppc64", "ppc64le":
 		ppc64.Main()
 	}
diff --git a/src/cmd/cover/html.go b/src/cmd/cover/html.go
index bb0a495..d0ac447 100644
--- a/src/cmd/cover/html.go
+++ b/src/cmd/cover/html.go
@@ -258,21 +258,35 @@ const tmplHTML = `
 		</div>
 		<div id="content">
 		{{range $i, $f := .Files}}
-		<pre class="file" id="file{{$i}}" {{if $i}}style="display: none"{{end}}>{{$f.Body}}</pre>
+		<pre class="file" id="file{{$i}}" style="display: none">{{$f.Body}}</pre>
 		{{end}}
 		</div>
 	</body>
 	<script>
 	(function() {
 		var files = document.getElementById('files');
-		var visible = document.getElementById('file0');
+		var visible;
 		files.addEventListener('change', onChange, false);
-		function onChange() {
-			visible.style.display = 'none';
-			visible = document.getElementById(files.value);
+		function select(part) {
+			if (visible)
+				visible.style.display = 'none';
+			visible = document.getElementById(part);
+			if (!visible)
+				return;
+			files.value = part;
 			visible.style.display = 'block';
+			location.hash = part;
+		}
+		function onChange() {
+			select(files.value);
 			window.scrollTo(0, 0);
 		}
+		if (location.hash != "") {
+			select(location.hash.substr(1));
+		}
+		if (!visible) {
+			select("file0");
+		}
 	})();
 	</script>
 </html>
diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go
index 1658e16..39a88cc 100644
--- a/src/cmd/dist/build.go
+++ b/src/cmd/dist/build.go
@@ -11,7 +11,9 @@ import (
 	"os"
 	"os/exec"
 	"path/filepath"
+	"sort"
 	"strings"
+	"sync"
 )
 
 // Initialization for any invocation.
@@ -42,8 +44,7 @@ var (
 	rebuildall       bool
 	defaultclang     bool
 
-	sflag bool // build static binaries
-	vflag int  // verbosity
+	vflag int // verbosity
 )
 
 // The known architectures.
@@ -53,6 +54,8 @@ var okgoarch = []string{
 	"amd64p32",
 	"arm",
 	"arm64",
+	"mips64",
+	"mips64le",
 	"ppc64",
 	"ppc64le",
 }
@@ -319,18 +322,15 @@ func findgoversion() string {
 
 // isGitRepo reports whether the working directory is inside a Git repository.
 func isGitRepo() bool {
-	p := ".git"
-	for {
-		fi, err := os.Stat(p)
-		if os.IsNotExist(err) {
-			p = filepath.Join("..", p)
-			continue
-		}
-		if err != nil || !fi.IsDir() {
-			return false
-		}
-		return true
-	}
+	// NB: simply checking the exit code of `git rev-parse --git-dir` would
+	// suffice here, but that requires deviating from the infrastructure
+	// provided by `run`.
+	gitDir := chomp(run(goroot, 0, "git", "rev-parse", "--git-dir"))
+	if !filepath.IsAbs(gitDir) {
+		gitDir = filepath.Join(goroot, gitDir)
+	}
+	fi, err := os.Stat(gitDir)
+	return err == nil && fi.IsDir()
 }
 
 /*
@@ -460,7 +460,7 @@ var deptab = []struct {
 	{"cmd/go", []string{
 		"zdefaultcc.go",
 	}},
-	{"runtime", []string{
+	{"runtime/internal/sys", []string{
 		"zversion.go",
 	}},
 }
@@ -487,9 +487,20 @@ var gentab = []struct {
 	{"anames9.c", nil},
 }
 
+// installed maps from a dir name (as given to install) to a chan
+// closed when the dir's package is installed.
+var installed = make(map[string]chan struct{})
+
 // install installs the library, package, or binary associated with dir,
 // which is relative to $GOROOT/src.
 func install(dir string) {
+	if ch, ok := installed[dir]; ok {
+		defer close(ch)
+	}
+	for _, dep := range builddeps[dir] {
+		<-installed[dep]
+	}
+
 	if vflag > 0 {
 		if goos != gohostos || goarch != gohostarch {
 			errprintf("%s (%s/%s)\n", dir, goos, goarch)
@@ -498,6 +509,9 @@ func install(dir string) {
 		}
 	}
 
+	workdir := pathf("%s/%s", workdir, dir)
+	xmkdirall(workdir)
+
 	var clean []string
 	defer func() {
 		for _, name := range clean {
@@ -603,13 +617,15 @@ func install(dir string) {
 	}
 
 	// For package runtime, copy some files into the work space.
-	if dir == "runtime" {
+	if dir == "runtime" || strings.HasPrefix(dir, "runtime/internal/") {
 		xmkdirall(pathf("%s/pkg/include", goroot))
 		// For use by assembly and C files.
 		copyfile(pathf("%s/pkg/include/textflag.h", goroot),
 			pathf("%s/src/runtime/textflag.h", goroot), 0)
 		copyfile(pathf("%s/pkg/include/funcdata.h", goroot),
 			pathf("%s/src/runtime/funcdata.h", goroot), 0)
+		copyfile(pathf("%s/pkg/include/asm_ppc64x.h", goroot),
+			pathf("%s/src/runtime/asm_ppc64x.h", goroot), 0)
 	}
 
 	// Generate any missing files; regenerate existing ones.
@@ -673,6 +689,7 @@ func install(dir string) {
 	run(path, CheckExit|ShowOutput, compile...)
 
 	// Compile the files.
+	var wg sync.WaitGroup
 	for _, p := range files {
 		if !strings.HasSuffix(p, ".s") {
 			continue
@@ -695,14 +712,14 @@ func install(dir string) {
 		// Change the last character of the output file (which was c or s).
 		b = b[:len(b)-1] + "o"
 		compile = append(compile, "-o", b, p)
-		bgrun(path, compile...)
+		bgrun(&wg, path, compile...)
 
 		link = append(link, b)
 		if doclean {
 			clean = append(clean, b)
 		}
 	}
-	bgwait()
+	bgwait(&wg)
 
 	if ispackcmd {
 		xremove(link[targ])
@@ -839,63 +856,19 @@ func dopack(dst, src string, extra []string) {
 	writefile(bdst.String(), dst, 0)
 }
 
-// buildorder records the order of builds for the 'go bootstrap' command.
-// The Go packages and commands must be in dependency order,
-// maintained by hand, but the order doesn't change often.
-var buildorder = []string{
-	// Go libraries and programs for bootstrap.
-	"runtime",
-	"errors",
-	"sync/atomic",
-	"sync",
-	"internal/singleflight",
-	"io",
-	"unicode",
-	"unicode/utf8",
-	"unicode/utf16",
-	"bytes",
-	"math",
-	"strings",
-	"strconv",
-	"bufio",
-	"sort",
-	"container/heap",
-	"encoding/base64",
-	"syscall",
-	"internal/syscall/windows/registry",
-	"time",
-	"internal/syscall/windows",
-	"os",
-	"reflect",
-	"fmt",
-	"encoding",
-	"encoding/binary",
-	"encoding/json",
-	"flag",
-	"path/filepath",
-	"path",
-	"io/ioutil",
-	"log",
-	"regexp/syntax",
-	"regexp",
-	"go/token",
-	"go/scanner",
-	"go/ast",
-	"go/parser",
-	"os/exec",
-	"os/signal",
-	"net/url",
-	"text/template/parse",
-	"text/template",
-	"go/doc",
-	"go/build",
-	"hash",
-	"crypto",
-	"crypto/sha1",
-	"debug/dwarf",
-	"debug/elf",
-	"debug/macho",
-	"cmd/go",
+// builddeps records the build dependencies for the 'go bootstrap' command.
+// It is a map[string][]string and generated by mkdeps.bash into deps.go.
+
+// buildlist is the list of directories being built, sorted by name.
+var buildlist = makeBuildlist()
+
+func makeBuildlist() []string {
+	var all []string
+	for dir := range builddeps {
+		all = append(all, dir)
+	}
+	sort.Strings(all)
+	return all
 }
 
 var runtimegen = []string{
@@ -904,7 +877,7 @@ var runtimegen = []string{
 }
 
 func clean() {
-	for _, name := range buildorder {
+	for _, name := range buildlist {
 		path := pathf("%s/src/%s", goroot, name)
 		// Remove generated files.
 		for _, elem := range xreaddir(path) {
@@ -933,6 +906,8 @@ func clean() {
 		// Remove installed packages and tools.
 		xremoveall(pathf("%s/pkg/%s_%s", goroot, gohostos, gohostarch))
 		xremoveall(pathf("%s/pkg/%s_%s", goroot, goos, goarch))
+		xremoveall(pathf("%s/pkg/%s_%s_race", goroot, gohostos, gohostarch))
+		xremoveall(pathf("%s/pkg/%s_%s_race", goroot, goos, goarch))
 		xremoveall(tooldir)
 
 		// Remove cached version info.
@@ -1005,7 +980,6 @@ func cmdenv() {
 // stopping at having installed the go_bootstrap command.
 func cmdbootstrap() {
 	flag.BoolVar(&rebuildall, "a", rebuildall, "rebuild all")
-	flag.BoolVar(&sflag, "s", sflag, "build static binaries")
 	xflagparse(0)
 
 	if isdir(pathf("%s/src/pkg", goroot)) {
@@ -1045,19 +1019,30 @@ func cmdbootstrap() {
 	// than in a standard release like Go 1.4, so don't do this rebuild by default.
 	if false {
 		xprintf("##### Building Go toolchain using itself.\n")
-		for _, dir := range buildorder {
-			if dir == "cmd/go" {
-				break
-			}
-			install(dir)
+		for _, dir := range buildlist {
+			installed[dir] = make(chan struct{})
+		}
+		var wg sync.WaitGroup
+		for _, dir := range builddeps["cmd/go"] {
+			wg.Add(1)
+			dir := dir
+			go func() {
+				defer wg.Done()
+				install(dir)
+			}()
 		}
+		wg.Wait()
 		xprintf("\n")
 	}
 
 	xprintf("##### Building go_bootstrap for host, %s/%s.\n", gohostos, gohostarch)
-	for _, dir := range buildorder {
-		install(dir)
+	for _, dir := range buildlist {
+		installed[dir] = make(chan struct{})
 	}
+	for _, dir := range buildlist {
+		go install(dir)
+	}
+	<-installed["cmd/go"]
 
 	goos = oldgoos
 	goarch = oldgoarch
@@ -1066,6 +1051,7 @@ func cmdbootstrap() {
 
 	// Build runtime for actual goos/goarch too.
 	if goos != gohostos || goarch != gohostarch {
+		installed["runtime"] = make(chan struct{})
 		install("runtime")
 	}
 }
@@ -1113,11 +1099,15 @@ func checkCC() {
 	if !needCC() {
 		return
 	}
-	if _, err := exec.Command(defaultcc, "--help").Output(); err != nil {
+	if output, err := exec.Command(defaultcc, "--help").CombinedOutput(); err != nil {
+		outputHdr := ""
+		if len(output) > 0 {
+			outputHdr = "\nCommand output:\n\n"
+		}
 		fatal("cannot invoke C compiler %q: %v\n\n"+
 			"Go needs a system C compiler for use with cgo.\n"+
 			"To set a C compiler, export CC=the-compiler.\n"+
-			"To disable cgo, export CGO_ENABLED=0.\n", defaultcc, err)
+			"To disable cgo, export CGO_ENABLED=0.\n%s%s", defaultcc, err, outputHdr, output)
 	}
 }
 
@@ -1141,7 +1131,6 @@ func defaulttarg() string {
 
 // Install installs the list of packages named on the command line.
 func cmdinstall() {
-	flag.BoolVar(&sflag, "s", sflag, "build static binaries")
 	xflagparse(-1)
 
 	if flag.NArg() == 0 {
diff --git a/src/cmd/dist/buildruntime.go b/src/cmd/dist/buildruntime.go
index 4e9bede..6e80221 100644
--- a/src/cmd/dist/buildruntime.go
+++ b/src/cmd/dist/buildruntime.go
@@ -16,24 +16,22 @@ import (
 
 // mkzversion writes zversion.go:
 //
-//	package runtime
-//	const defaultGoroot = <goroot>
-//	const theVersion = <version>
-//	const goexperiment = <goexperiment>
-//	const stackGuardMultiplier = <multiplier value>
-//	const buildVersion = <build version>
+//	package sys
+//	const DefaultGoroot = <goroot>
+//	const TheVersion = <version>
+//	const Goexperiment = <goexperiment>
+//	const StackGuardMultiplier = <multiplier value>
 //
 func mkzversion(dir, file string) {
 	out := fmt.Sprintf(
 		"// auto generated by go tool dist\n"+
 			"\n"+
-			"package runtime\n"+
+			"package sys\n"+
 			"\n"+
-			"const defaultGoroot = `%s`\n"+
-			"const theVersion = `%s`\n"+
-			"const goexperiment = `%s`\n"+
-			"const stackGuardMultiplier = %d\n"+
-			"var buildVersion = theVersion\n", goroot_final, findgoversion(), os.Getenv("GOEXPERIMENT"), stackGuardMultiplier())
+			"const DefaultGoroot = `%s`\n"+
+			"const TheVersion = `%s`\n"+
+			"const Goexperiment = `%s`\n"+
+			"const StackGuardMultiplier = %d\n\n", goroot_final, findgoversion(), os.Getenv("GOEXPERIMENT"), stackGuardMultiplier())
 
 	writefile(out, file, writeSkipSame)
 }
diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go
index 8a55b5d..20d9535 100644
--- a/src/cmd/dist/buildtool.go
+++ b/src/cmd/dist/buildtool.go
@@ -34,12 +34,14 @@ var bootstrapDirs = []string{
 	"compile/internal/arm64",
 	"compile/internal/big",
 	"compile/internal/gc",
+	"compile/internal/mips64",
 	"compile/internal/ppc64",
 	"compile/internal/x86",
 	"internal/gcprog",
 	"internal/obj",
 	"internal/obj/arm",
 	"internal/obj/arm64",
+	"internal/obj/mips",
 	"internal/obj/ppc64",
 	"internal/obj/x86",
 	"link",
@@ -47,6 +49,7 @@ var bootstrapDirs = []string{
 	"link/internal/arm",
 	"link/internal/arm64",
 	"link/internal/ld",
+	"link/internal/mips64",
 	"link/internal/ppc64",
 	"link/internal/x86",
 }
diff --git a/src/cmd/dist/deps.go b/src/cmd/dist/deps.go
new file mode 100644
index 0000000..9fd9817
--- /dev/null
+++ b/src/cmd/dist/deps.go
@@ -0,0 +1,64 @@
+// generated by mkdeps.bash
+
+package main
+
+var builddeps = map[string][]string{
+	"bufio":                             {"bytes", "errors", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "unicode", "unicode/utf8"},
+	"bytes":                             {"errors", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "unicode", "unicode/utf8"},
+	"compress/flate":                    {"bufio", "bytes", "errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"compress/zlib":                     {"bufio", "bytes", "compress/flate", "errors", "fmt", "hash", "hash/adler32", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"container/heap":                    {"runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort"},
+	"crypto":                            {"errors", "hash", "internal/race", "io", "math", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "unicode/utf8"},
+	"crypto/sha1":                       {"crypto", "errors", "hash", "internal/race", "io", "math", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "unicode/utf8"},
+	"debug/dwarf":                       {"encoding/binary", "errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"debug/elf":                         {"bufio", "bytes", "compress/flate", "compress/zlib", "debug/dwarf", "encoding/binary", "errors", "fmt", "hash", "hash/adler32", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"debug/macho":                       {"bytes", "debug/dwarf", "encoding/binary", "errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"encoding":                          {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
+	"encoding/base64":                   {"errors", "internal/race", "io", "math", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "unicode/utf8"},
+	"encoding/binary":                   {"errors", "internal/race", "io", "math", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "unicode/utf8"},
+	"encoding/json":                     {"bytes", "encoding", "encoding/base64", "errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"errors":                            {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
+	"flag":                              {"errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+	"fmt":                               {"errors", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+	"go/ast":                            {"bytes", "errors", "fmt", "go/scanner", "go/token", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"go/build":                          {"bufio", "bytes", "errors", "fmt", "go/ast", "go/doc", "go/parser", "go/scanner", "go/token", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "log", "math", "net/url", "os", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse [...]
+	"go/doc":                            {"bytes", "errors", "fmt", "go/ast", "go/scanner", "go/token", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "math", "net/url", "os", "path", "path/filepath", "reflect", "regexp", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template", "text/template/parse", "time", "unicode", "unicode/utf16",  [...]
+	"go/parser":                         {"bytes", "errors", "fmt", "go/ast", "go/scanner", "go/token", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "math", "os", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"go/scanner":                        {"bytes", "errors", "fmt", "go/token", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"go/token":                          {"errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+	"hash":                              {"errors", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic"},
+	"hash/adler32":                      {"errors", "hash", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic"},
+	"internal/race":                     {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
+	"internal/singleflight":             {"internal/race", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic"},
+	"internal/syscall/windows":          {"errors", "internal/race", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "syscall", "unicode/utf16"},
+	"internal/syscall/windows/registry": {"errors", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "syscall", "unicode/utf16"},
+	"io":                      {"errors", "internal/race", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic"},
+	"io/ioutil":               {"bytes", "errors", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path/filepath", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"log":                     {"errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+	"math":                    {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
+	"net/url":                 {"bytes", "errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"os":                      {"errors", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+	"os/exec":                 {"bytes", "errors", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "path/filepath", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"os/signal":               {"errors", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "os", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "syscall", "time", "unicode/utf16", "unicode/utf8"},
+	"path":                    {"errors", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strings", "sync", "sync/atomic", "unicode", "unicode/utf8"},
+	"path/filepath":           {"errors", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "os", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"reflect":                 {"errors", "internal/race", "math", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "sync", "sync/atomic", "unicode/utf8"},
+	"regexp":                  {"bytes", "errors", "internal/race", "io", "math", "regexp/syntax", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "unicode", "unicode/utf8"},
+	"regexp/syntax":           {"bytes", "errors", "internal/race", "io", "math", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "unicode", "unicode/utf8"},
+	"runtime":                 {"runtime/internal/atomic", "runtime/internal/sys"},
+	"runtime/internal/atomic": {"runtime/internal/sys"},
+	"runtime/internal/sys":    {},
+	"sort":                    {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
+	"strconv":                 {"errors", "math", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "unicode/utf8"},
+	"strings":                 {"errors", "internal/race", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "unicode", "unicode/utf8"},
+	"sync":                    {"internal/race", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync/atomic"},
+	"sync/atomic":             {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
+	"syscall":                 {"errors", "internal/race", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "unicode/utf16"},
+	"text/template":           {"bytes", "errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "math", "net/url", "os", "path/filepath", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sort", "strconv", "strings", "sync", "sync/atomic", "syscall", "text/template/parse", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"text/template/parse":     {"bytes", "errors", "fmt", "internal/race", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "math", "os", "reflect", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "strconv", "strings", "sync", "sync/atomic", "syscall", "time", "unicode", "unicode/utf16", "unicode/utf8"},
+	"time":                    {"errors", "internal/race", "internal/syscall/windows/registry", "io", "runtime", "runtime/internal/atomic", "runtime/internal/sys", "sync", "sync/atomic", "syscall", "unicode/utf16"},
+	"unicode":                 {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
+	"unicode/utf16":           {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
+	"unicode/utf8":            {"runtime", "runtime/internal/atomic", "runtime/internal/sys"},
+	"cmd/go":                  {"bufio", "bytes", "compress/flate", "compress/zlib", "container/heap", "crypto", "crypto/sha1", "debug/dwarf", "debug/elf", "debug/macho", "encoding", "encoding/base64", "encoding/binary", "encoding/json", "errors", "flag", "fmt", "go/ast", "go/build", "go/doc", "go/parser", "go/scanner", "go/token", "hash", "hash/adler32", "internal/race", "internal/singleflight", "internal/syscall/windows", "internal/syscall/windows/registry", "io", "io/ioutil", "log", "mat [...]
+}
diff --git a/src/cmd/dist/mkdeps.bash b/src/cmd/dist/mkdeps.bash
new file mode 100755
index 0000000..71d3c37
--- /dev/null
+++ b/src/cmd/dist/mkdeps.bash
@@ -0,0 +1,47 @@
+#!/bin/bash
+# Copyright 2015 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.
+
+set -e
+
+# We need to test enough GOOS/GOARCH combinations to pick up all the
+# package dependencies.
+gooslist="windows linux darwin solaris"
+goarchlist="386 amd64 arm arm64 ppc64"
+
+echo NOTE: errors about loading internal/syscall/windows are ok
+
+deps_of() {
+	for goos in $gooslist
+	do
+		for goarch in $goarchlist
+		do
+			GOOS=$goos GOARCH=$goarch go list -tags cmd_go_bootstrap -f '{{range .Deps}}{{$.ImportPath}} {{.}}
+{{end}}' $*
+		done
+	done | sort -u | grep . | grep -v ' unsafe$'
+}
+
+all="$(deps_of cmd/go | awk '{print $2}') cmd/go"
+deps_of $all >tmp.all.deps
+
+(
+	echo '// generated by mkdeps.bash'
+	echo
+	echo 'package main'
+	echo
+	echo 'var builddeps = map[string][]string{'
+	for pkg in $all
+	do
+		echo -n "\"$pkg\": {"
+		for dep in $(awk -v pkg=$pkg '$1==pkg {print $2}' tmp.all.deps)
+		do
+			echo -n "\"$dep\","
+		done
+		echo '},'
+	done
+	echo '}'
+) |gofmt >deps.go
+
+rm -f tmp.all.deps
diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go
old mode 100755
new mode 100644
index d0e6346..36c829d
--- a/src/cmd/dist/test.go
+++ b/src/cmd/dist/test.go
@@ -16,13 +16,16 @@ import (
 	"regexp"
 	"strconv"
 	"strings"
+	"sync"
 	"time"
 )
 
 func cmdtest() {
 	var t tester
+	var noRebuild bool
 	flag.BoolVar(&t.listMode, "list", false, "list available tests")
-	flag.BoolVar(&t.noRebuild, "no-rebuild", false, "don't rebuild std and cmd packages")
+	flag.BoolVar(&t.rebuild, "rebuild", false, "rebuild everything first")
+	flag.BoolVar(&noRebuild, "no-rebuild", false, "overrides -rebuild (historical dreg)")
 	flag.BoolVar(&t.keepGoing, "k", false, "keep going even when error occurred")
 	flag.BoolVar(&t.race, "race", false, "run in race builder mode (different set of tests)")
 	flag.StringVar(&t.banner, "banner", "##### ", "banner prefix; blank means no section banners")
@@ -30,20 +33,25 @@ func cmdtest() {
 		"run only those tests matching the regular expression; empty means to run all. "+
 			"Special exception: if the string begins with '!', the match is inverted.")
 	xflagparse(-1) // any number of args
+	if noRebuild {
+		t.rebuild = false
+	}
 	t.run()
 }
 
 // tester executes cmdtest.
 type tester struct {
-	race      bool
-	listMode  bool
-	noRebuild bool
-	keepGoing bool
-	runRxStr  string
-	runRx     *regexp.Regexp
-	runRxWant bool     // want runRx to match (true) or not match (false)
-	runNames  []string // tests to run, exclusive with runRx; empty means all
-	banner    string   // prefix, or "" for none
+	race        bool
+	listMode    bool
+	rebuild     bool
+	failed      bool
+	keepGoing   bool
+	runRxStr    string
+	runRx       *regexp.Regexp
+	runRxWant   bool     // want runRx to match (true) or not match (false)
+	runNames    []string // tests to run, exclusive with runRx; empty means all
+	banner      string   // prefix, or "" for none
+	lastHeading string   // last dir heading printed
 
 	goroot     string
 	goarch     string
@@ -56,6 +64,17 @@ type tester struct {
 
 	tests        []distTest
 	timeoutScale int
+
+	worklist []*work
+}
+
+type work struct {
+	dt    *distTest
+	cmd   *exec.Cmd
+	start chan bool
+	out   []byte
+	err   error
+	end   chan bool
 }
 
 // A distTest is a test run by dist test.
@@ -63,7 +82,7 @@ type tester struct {
 type distTest struct {
 	name    string // unique test name; may be filtered with -run flag
 	heading string // group section; this header is printed before the test is run.
-	fn      func() error
+	fn      func(*distTest) error
 }
 
 func mustEnv(k string) string {
@@ -96,7 +115,7 @@ func (t *tester) run() {
 		}
 	}
 
-	if !t.noRebuild {
+	if t.rebuild {
 		t.out("Building packages and commands.")
 		cmd := exec.Command("go", "install", "-a", "-v", "std", "cmd")
 		cmd.Stdout = os.Stdout
@@ -169,22 +188,15 @@ func (t *tester) run() {
 		}
 	}
 
-	var lastHeading string
-	ok := true
 	for _, dt := range t.tests {
 		if !t.shouldRunTest(dt.name) {
 			t.partial = true
 			continue
 		}
-		if dt.heading != "" && lastHeading != dt.heading {
-			lastHeading = dt.heading
-			t.out(dt.heading)
-		}
-		if vflag > 0 {
-			fmt.Printf("# go tool dist test -run=^%s$\n", dt.name)
-		}
-		if err := dt.fn(); err != nil {
-			ok = false
+		dt := dt // dt used in background after this iteration
+		if err := dt.fn(&dt); err != nil {
+			t.runPending(&dt) // in case that hasn't been done yet
+			t.failed = true
 			if t.keepGoing {
 				log.Printf("Failed: %v", err)
 			} else {
@@ -192,7 +204,8 @@ func (t *tester) run() {
 			}
 		}
 	}
-	if !ok {
+	t.runPending(nil)
+	if t.failed {
 		fmt.Println("\nFAILED")
 		os.Exit(1)
 	} else if t.partial {
@@ -250,10 +263,11 @@ func (t *tester) registerStdTest(pkg string) {
 	t.tests = append(t.tests, distTest{
 		name:    testName,
 		heading: "Testing packages.",
-		fn: func() error {
+		fn: func(dt *distTest) error {
 			if ranGoTest {
 				return nil
 			}
+			t.runPending(dt)
 			ranGoTest = true
 			args := []string{
 				"test",
@@ -282,10 +296,11 @@ func (t *tester) registerRaceBenchTest(pkg string) {
 	t.tests = append(t.tests, distTest{
 		name:    testName,
 		heading: "Running benchmarks briefly.",
-		fn: func() error {
+		fn: func(dt *distTest) error {
 			if ranGoBench {
 				return nil
 			}
+			t.runPending(dt)
 			ranGoBench = true
 			args := []string{
 				"test",
@@ -321,7 +336,11 @@ func (t *tester) registerTests() {
 	} else {
 		// Use a format string to only list packages and commands that have tests.
 		const format = "{{if (or .TestGoFiles .XTestGoFiles)}}{{.ImportPath}}{{end}}"
-		cmd := exec.Command("go", "list", "-f", format, "std")
+		cmd := exec.Command("go", "list", "-f", format)
+		if t.race {
+			cmd.Args = append(cmd.Args, "-tags", "race")
+		}
+		cmd.Args = append(cmd.Args, "std")
 		if !t.race {
 			cmd.Args = append(cmd.Args, "cmd")
 		}
@@ -349,21 +368,58 @@ func (t *tester) registerTests() {
 	t.tests = append(t.tests, distTest{
 		name:    testName,
 		heading: "GOMAXPROCS=2 runtime -cpu=1,2,4",
-		fn: func() error {
-			cmd := t.dirCmd("src", "go", "test", "-short", t.timeout(300), t.tags(), "runtime", "-cpu=1,2,4")
+		fn: func(dt *distTest) error {
+			cmd := t.addCmd(dt, "src", "go", "test", "-short", t.timeout(300), t.tags(), "runtime", "-cpu=1,2,4")
 			// We set GOMAXPROCS=2 in addition to -cpu=1,2,4 in order to test runtime bootstrap code,
 			// creation of first goroutines and first garbage collections in the parallel setting.
 			cmd.Env = mergeEnvLists([]string{"GOMAXPROCS=2"}, os.Environ())
-			return cmd.Run()
+			return nil
 		},
 	})
 
+	// Test that internal linking of standard packages does not
+	// require libgcc.  This ensures that we can install a Go
+	// release on a system that does not have a C compiler
+	// installed and still build Go programs (that don't use cgo).
+	for _, pkg := range cgoPackages {
+
+		// Internal linking is not currently supported on Dragonfly.
+		if t.goos == "dragonfly" {
+			break
+		}
+
+		// ARM libgcc may be Thumb, which internal linking does not support.
+		if t.goarch == "arm" {
+			break
+		}
+
+		// Darwin/Android ARM64 fails with internal linking.
+		if (t.goos == "darwin" || t.goos == "android") && t.goarch == "arm64" {
+			break
+		}
+
+		pkg := pkg
+		var run string
+		if pkg == "net" {
+			run = "TestTCPStress"
+		}
+		t.tests = append(t.tests, distTest{
+			name:    "nolibgcc:" + pkg,
+			heading: "Testing without libgcc.",
+			fn: func(dt *distTest) error {
+				t.addCmd(dt, "src", "go", "test", "-short", "-ldflags=-linkmode=internal -libgcc=none", t.tags(), pkg, "-run="+run)
+				return nil
+			},
+		})
+	}
+
 	// sync tests
 	t.tests = append(t.tests, distTest{
 		name:    "sync_cpu",
 		heading: "sync -cpu=10",
-		fn: func() error {
-			return t.dirCmd("src", "go", "test", "sync", "-short", t.timeout(120), t.tags(), "-cpu=10").Run()
+		fn: func(dt *distTest) error {
+			t.addCmd(dt, "src", "go", "test", "sync", "-short", t.timeout(120), t.tags(), "-cpu=10")
+			return nil
 		},
 	})
 
@@ -372,17 +428,17 @@ func (t *tester) registerTests() {
 		t.tests = append(t.tests, distTest{
 			name:    "cgo_stdio",
 			heading: "../misc/cgo/stdio",
-			fn: func() error {
-				return t.dirCmd("misc/cgo/stdio",
-					"go", "run", filepath.Join(os.Getenv("GOROOT"), "test/run.go"), "-", ".").Run()
+			fn: func(dt *distTest) error {
+				t.addCmd(dt, "misc/cgo/stdio", "go", "run", filepath.Join(os.Getenv("GOROOT"), "test/run.go"), "-", ".")
+				return nil
 			},
 		})
 		t.tests = append(t.tests, distTest{
 			name:    "cgo_life",
 			heading: "../misc/cgo/life",
-			fn: func() error {
-				return t.dirCmd("misc/cgo/life",
-					"go", "run", filepath.Join(os.Getenv("GOROOT"), "test/run.go"), "-", ".").Run()
+			fn: func(dt *distTest) error {
+				t.addCmd(dt, "misc/cgo/life", "go", "run", filepath.Join(os.Getenv("GOROOT"), "test/run.go"), "-", ".")
+				return nil
 			},
 		})
 	}
@@ -414,15 +470,15 @@ func (t *tester) registerTests() {
 			t.tests = append(t.tests, distTest{
 				name:    "testso",
 				heading: "../misc/cgo/testso",
-				fn: func() error {
-					return t.cgoTestSO("misc/cgo/testso")
+				fn: func(dt *distTest) error {
+					return t.cgoTestSO(dt, "misc/cgo/testso")
 				},
 			})
 			t.tests = append(t.tests, distTest{
 				name:    "testsovar",
 				heading: "../misc/cgo/testsovar",
-				fn: func() error {
-					return t.cgoTestSO("misc/cgo/testsovar")
+				fn: func(dt *distTest) error {
+					return t.cgoTestSO(dt, "misc/cgo/testsovar")
 				},
 			})
 		}
@@ -438,6 +494,9 @@ func (t *tester) registerTests() {
 		if t.gohostos == "linux" && t.goarch == "amd64" {
 			t.registerTest("testasan", "../misc/cgo/testasan", "go", "run", "main.go")
 		}
+		if t.gohostos == "linux" && t.goarch == "amd64" {
+			t.registerTest("testsanitizers", "../misc/cgo/testsanitizers", "./test.bash")
+		}
 		if t.hasBash() && t.goos != "android" && !t.iOS() && t.gohostos != "windows" {
 			t.registerTest("cgo_errors", "../misc/cgo/errors", "./test.bash")
 		}
@@ -445,14 +504,17 @@ func (t *tester) registerTests() {
 			t.registerTest("testsigfwd", "../misc/cgo/testsigfwd", "go", "run", "main.go")
 		}
 	}
-	if t.hasBash() && t.goos != "nacl" && t.goos != "android" && !t.iOS() {
+
+	// Doc tests only run on builders.
+	// They find problems approximately never.
+	if t.hasBash() && t.goos != "nacl" && t.goos != "android" && !t.iOS() && os.Getenv("GO_BUILDER_NAME") != "" {
 		t.registerTest("doc_progs", "../doc/progs", "time", "go", "run", "run.go")
 		t.registerTest("wiki", "../doc/articles/wiki", "./test.bash")
 		t.registerTest("codewalk", "../doc/codewalk", "time", "./run")
-		t.registerTest("shootout", "../test/bench/shootout", "time", "./timing.sh", "-test")
 	}
+
 	if t.goos != "android" && !t.iOS() {
-		t.registerTest("bench_go1", "../test/bench/go1", "go", "test")
+		t.registerTest("bench_go1", "../test/bench/go1", "go", "test", t.timeout(600))
 	}
 	if t.goos != "android" && !t.iOS() {
 		const nShards = 5
@@ -461,7 +523,7 @@ func (t *tester) registerTests() {
 			t.tests = append(t.tests, distTest{
 				name:    fmt.Sprintf("test:%d_%d", shard, nShards),
 				heading: "../test",
-				fn:      func() error { return t.testDirTest(shard, nShards) },
+				fn:      func(dt *distTest) error { return t.testDirTest(dt, shard, nShards) },
 			})
 		}
 	}
@@ -469,8 +531,9 @@ func (t *tester) registerTests() {
 		t.tests = append(t.tests, distTest{
 			name:    "api",
 			heading: "API check",
-			fn: func() error {
-				return t.dirCmd("src", "go", "run", filepath.Join(t.goroot, "src/cmd/api/run.go")).Run()
+			fn: func(dt *distTest) error {
+				t.addCmd(dt, "src", "go", "run", filepath.Join(t.goroot, "src/cmd/api/run.go"))
+				return nil
 			},
 		})
 	}
@@ -487,7 +550,7 @@ func (t *tester) isRegisteredTestName(testName string) bool {
 	return false
 }
 
-func (t *tester) registerTest(name, dirBanner, bin string, args ...string) {
+func (t *tester) registerTest1(seq bool, name, dirBanner, bin string, args ...string) {
 	if bin == "time" && !t.haveTime {
 		bin, args = args[0], args[1:]
 	}
@@ -497,19 +560,37 @@ func (t *tester) registerTest(name, dirBanner, bin string, args ...string) {
 	t.tests = append(t.tests, distTest{
 		name:    name,
 		heading: dirBanner,
-		fn: func() error {
-			return t.dirCmd(filepath.Join(t.goroot, "src", dirBanner), bin, args...).Run()
+		fn: func(dt *distTest) error {
+			if seq {
+				t.runPending(dt)
+				return t.dirCmd(filepath.Join(t.goroot, "src", dirBanner), bin, args...).Run()
+			}
+			t.addCmd(dt, filepath.Join(t.goroot, "src", dirBanner), bin, args...)
+			return nil
 		},
 	})
 }
 
-func (t *tester) dirCmd(dir string, bin string, args ...string) *exec.Cmd {
+func (t *tester) registerTest(name, dirBanner, bin string, args ...string) {
+	t.registerTest1(false, name, dirBanner, bin, args...)
+}
+
+func (t *tester) registerSeqTest(name, dirBanner, bin string, args ...string) {
+	t.registerTest1(true, name, dirBanner, bin, args...)
+}
+
+func (t *tester) bgDirCmd(dir, bin string, args ...string) *exec.Cmd {
 	cmd := exec.Command(bin, args...)
 	if filepath.IsAbs(dir) {
 		cmd.Dir = dir
 	} else {
 		cmd.Dir = filepath.Join(t.goroot, dir)
 	}
+	return cmd
+}
+
+func (t *tester) dirCmd(dir, bin string, args ...string) *exec.Cmd {
+	cmd := t.bgDirCmd(dir, bin, args...)
 	cmd.Stdout = os.Stdout
 	cmd.Stderr = os.Stderr
 	if vflag > 1 {
@@ -518,6 +599,15 @@ func (t *tester) dirCmd(dir string, bin string, args ...string) *exec.Cmd {
 	return cmd
 }
 
+func (t *tester) addCmd(dt *distTest, dir, bin string, args ...string) *exec.Cmd {
+	w := &work{
+		dt:  dt,
+		cmd: t.bgDirCmd(dir, bin, args...),
+	}
+	t.worklist = append(t.worklist, w)
+	return w.cmd
+}
+
 func (t *tester) iOS() bool {
 	return t.goos == "darwin" && (t.goarch == "arm" || t.goarch == "arm64")
 }
@@ -536,7 +626,7 @@ func (t *tester) extLink() bool {
 		"darwin-arm", "darwin-arm64",
 		"dragonfly-386", "dragonfly-amd64",
 		"freebsd-386", "freebsd-amd64", "freebsd-arm",
-		"linux-386", "linux-amd64", "linux-arm", "linux-arm64",
+		"linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le",
 		"netbsd-386", "netbsd-amd64",
 		"openbsd-386", "openbsd-amd64",
 		"windows-386", "windows-amd64":
@@ -562,21 +652,22 @@ func (t *tester) supportedBuildmode(mode string) bool {
 			return false
 		}
 		switch pair {
-		case "darwin-amd64", "darwin-arm", "darwin-arm64",
+		case "darwin-386", "darwin-amd64", "darwin-arm", "darwin-arm64",
 			"linux-amd64", "linux-386":
 			return true
 		}
 		return false
 	case "c-shared":
-		// TODO(hyangah): add linux-386.
 		switch pair {
-		case "linux-amd64", "darwin-amd64", "android-arm":
+		case "linux-386", "linux-amd64", "linux-arm", "linux-arm64",
+			"darwin-amd64", "darwin-386",
+			"android-arm", "android-arm64", "android-386":
 			return true
 		}
 		return false
 	case "shared":
 		switch pair {
-		case "linux-amd64":
+		case "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le":
 			return true
 		}
 		return false
@@ -586,7 +677,7 @@ func (t *tester) supportedBuildmode(mode string) bool {
 	}
 }
 
-func (t *tester) cgoTest() error {
+func (t *tester) cgoTest(dt *distTest) error {
 	env := mergeEnvLists([]string{"GOTRACEBACK=2"}, os.Environ())
 
 	if t.goos == "android" || t.iOS() {
@@ -595,19 +686,13 @@ func (t *tester) cgoTest() error {
 		return cmd.Run()
 	}
 
-	cmd := t.dirCmd("misc/cgo/test", "go", "test", t.tags(), "-ldflags", "-linkmode=auto")
+	cmd := t.addCmd(dt, "misc/cgo/test", "go", "test", t.tags(), "-ldflags", "-linkmode=auto")
 	cmd.Env = env
-	if err := cmd.Run(); err != nil {
-		return err
-	}
 
 	if t.gohostos != "dragonfly" {
 		// linkmode=internal fails on dragonfly since errno is a TLS relocation.
-		cmd := t.dirCmd("misc/cgo/test", "go", "test", "-ldflags", "-linkmode=internal")
+		cmd := t.addCmd(dt, "misc/cgo/test", "go", "test", "-ldflags", "-linkmode=internal")
 		cmd.Env = env
-		if err := cmd.Run(); err != nil {
-			return err
-		}
 	}
 
 	pair := t.gohostos + "-" + t.goarch
@@ -619,37 +704,24 @@ func (t *tester) cgoTest() error {
 		if !t.extLink() {
 			break
 		}
-		cmd := t.dirCmd("misc/cgo/test", "go", "test", "-ldflags", "-linkmode=external")
+		cmd := t.addCmd(dt, "misc/cgo/test", "go", "test", "-ldflags", "-linkmode=external")
 		cmd.Env = env
-		if err := cmd.Run(); err != nil {
-			return err
-		}
-		cmd = t.dirCmd("misc/cgo/test", "go", "test", "-ldflags", "-linkmode=external -s")
+		cmd = t.addCmd(dt, "misc/cgo/test", "go", "test", "-ldflags", "-linkmode=external -s")
 		cmd.Env = env
-		if err := cmd.Run(); err != nil {
-			return err
-		}
 	case "android-arm",
 		"dragonfly-386", "dragonfly-amd64",
 		"freebsd-386", "freebsd-amd64", "freebsd-arm",
 		"linux-386", "linux-amd64", "linux-arm",
 		"netbsd-386", "netbsd-amd64":
 
-		cmd := t.dirCmd("misc/cgo/test", "go", "test", "-ldflags", "-linkmode=external")
+		cmd := t.addCmd(dt, "misc/cgo/test", "go", "test", "-ldflags", "-linkmode=external")
 		cmd.Env = env
-		if err := cmd.Run(); err != nil {
-			return err
-		}
-		cmd = t.dirCmd("misc/cgo/testtls", "go", "test", "-ldflags", "-linkmode=auto")
+
+		cmd = t.addCmd(dt, "misc/cgo/testtls", "go", "test", "-ldflags", "-linkmode=auto")
 		cmd.Env = env
-		if err := cmd.Run(); err != nil {
-			return err
-		}
-		cmd = t.dirCmd("misc/cgo/testtls", "go", "test", "-ldflags", "-linkmode=external")
+
+		cmd = t.addCmd(dt, "misc/cgo/testtls", "go", "test", "-ldflags", "-linkmode=external")
 		cmd.Env = env
-		if err := cmd.Run(); err != nil {
-			return err
-		}
 
 		switch pair {
 		case "netbsd-386", "netbsd-amd64":
@@ -669,29 +741,17 @@ func (t *tester) cgoTest() error {
 			if err := cmd.Run(); err != nil {
 				fmt.Println("No support for static linking found (lacks libc.a?), skip cgo static linking test.")
 			} else {
-				cmd = t.dirCmd("misc/cgo/testtls", "go", "test", "-ldflags", `-linkmode=external -extldflags "-static -pthread"`)
+				cmd = t.addCmd(dt, "misc/cgo/testtls", "go", "test", "-ldflags", `-linkmode=external -extldflags "-static -pthread"`)
 				cmd.Env = env
-				if err := cmd.Run(); err != nil {
-					return err
-				}
 
-				cmd = t.dirCmd("misc/cgo/nocgo", "go", "test")
+				cmd = t.addCmd(dt, "misc/cgo/nocgo", "go", "test")
 				cmd.Env = env
-				if err := cmd.Run(); err != nil {
-					return err
-				}
 
-				cmd = t.dirCmd("misc/cgo/nocgo", "go", "test", "-ldflags", `-linkmode=external`)
+				cmd = t.addCmd(dt, "misc/cgo/nocgo", "go", "test", "-ldflags", `-linkmode=external`)
 				cmd.Env = env
-				if err := cmd.Run(); err != nil {
-					return err
-				}
 
-				cmd = t.dirCmd("misc/cgo/nocgo", "go", "test", "-ldflags", `-linkmode=external -extldflags "-static -pthread"`)
+				cmd = t.addCmd(dt, "misc/cgo/nocgo", "go", "test", "-ldflags", `-linkmode=external -extldflags "-static -pthread"`)
 				cmd.Env = env
-				if err := cmd.Run(); err != nil {
-					return err
-				}
 			}
 
 			if pair != "freebsd-amd64" { // clang -pie fails to link misc/cgo/test
@@ -702,21 +762,15 @@ func (t *tester) cgoTest() error {
 				if err := cmd.Run(); err != nil {
 					fmt.Println("No support for -pie found, skip cgo PIE test.")
 				} else {
-					cmd = t.dirCmd("misc/cgo/test", "go", "test", "-ldflags", `-linkmode=external -extldflags "-pie"`)
+					cmd = t.addCmd(dt, "misc/cgo/test", "go", "test", "-ldflags", `-linkmode=external -extldflags "-pie"`)
 					cmd.Env = env
-					if err := cmd.Run(); err != nil {
-						return fmt.Errorf("pie cgo/test: %v", err)
-					}
-					cmd = t.dirCmd("misc/cgo/testtls", "go", "test", "-ldflags", `-linkmode=external -extldflags "-pie"`)
+
+					cmd = t.addCmd(dt, "misc/cgo/testtls", "go", "test", "-ldflags", `-linkmode=external -extldflags "-pie"`)
 					cmd.Env = env
-					if err := cmd.Run(); err != nil {
-						return fmt.Errorf("pie cgo/testtls: %v", err)
-					}
-					cmd = t.dirCmd("misc/cgo/nocgo", "go", "test", "-ldflags", `-linkmode=external -extldflags "-pie"`)
+
+					cmd = t.addCmd(dt, "misc/cgo/nocgo", "go", "test", "-ldflags", `-linkmode=external -extldflags "-pie"`)
 					cmd.Env = env
-					if err := cmd.Run(); err != nil {
-						return fmt.Errorf("pie cgo/nocgo: %v", err)
-					}
+
 				}
 			}
 		}
@@ -725,19 +779,97 @@ func (t *tester) cgoTest() error {
 	return nil
 }
 
+// run pending test commands, in parallel, emitting headers as appropriate.
+// When finished, emit header for nextTest, which is going to run after the
+// pending commands are done (and runPending returns).
+// A test should call runPending if it wants to make sure that it is not
+// running in parallel with earlier tests, or if it has some other reason
+// for needing the earlier tests to be done.
+func (t *tester) runPending(nextTest *distTest) {
+	worklist := t.worklist
+	t.worklist = nil
+	for _, w := range worklist {
+		w.start = make(chan bool)
+		w.end = make(chan bool)
+		go func(w *work) {
+			if !<-w.start {
+				w.out = []byte(fmt.Sprintf("skipped due to earlier error\n"))
+			} else {
+				w.out, w.err = w.cmd.CombinedOutput()
+			}
+			w.end <- true
+		}(w)
+	}
+
+	started := 0
+	ended := 0
+	var last *distTest
+	for ended < len(worklist) {
+		for started < len(worklist) && started-ended < maxbg {
+			//println("start", started)
+			w := worklist[started]
+			started++
+			w.start <- !t.failed || t.keepGoing
+		}
+		w := worklist[ended]
+		dt := w.dt
+		if dt.heading != "" && t.lastHeading != dt.heading {
+			t.lastHeading = dt.heading
+			t.out(dt.heading)
+		}
+		if dt != last {
+			// Assumes all the entries for a single dt are in one worklist.
+			last = w.dt
+			if vflag > 0 {
+				fmt.Printf("# go tool dist test -run=^%s$\n", dt.name)
+			}
+		}
+		if vflag > 1 {
+			errprintf("%s\n", strings.Join(w.cmd.Args, " "))
+		}
+		//println("wait", ended)
+		ended++
+		<-w.end
+		os.Stdout.Write(w.out)
+		if w.err != nil {
+			log.Printf("Failed: %v", w.err)
+			t.failed = true
+		}
+	}
+	if t.failed && !t.keepGoing {
+		log.Fatal("FAILED")
+	}
+
+	if dt := nextTest; dt != nil {
+		if dt.heading != "" && t.lastHeading != dt.heading {
+			t.lastHeading = dt.heading
+			t.out(dt.heading)
+		}
+		if vflag > 0 {
+			fmt.Printf("# go tool dist test -run=^%s$\n", dt.name)
+		}
+	}
+}
+
 func (t *tester) cgoTestSOSupported() bool {
 	if t.goos == "android" || t.iOS() {
 		// No exec facility on Android or iOS.
 		return false
 	}
-	if t.goarch == "ppc64le" || t.goarch == "ppc64" {
+	if t.goarch == "ppc64" {
 		// External linking not implemented on ppc64 (issue #8912).
 		return false
 	}
+	if t.goarch == "mips64le" || t.goarch == "mips64" {
+		// External linking not implemented on mips64.
+		return false
+	}
 	return true
 }
 
-func (t *tester) cgoTestSO(testpath string) error {
+func (t *tester) cgoTestSO(dt *distTest, testpath string) error {
+	t.runPending(dt)
+
 	dir := filepath.Join(t.goroot, testpath)
 
 	// build shared object
@@ -785,6 +917,12 @@ func (t *tester) cgoTestSO(testpath string) error {
 			s = "DYLD_LIBRARY_PATH"
 		}
 		cmd.Env = mergeEnvLists([]string{s + "=."}, os.Environ())
+
+		// On FreeBSD 64-bit architectures, the 32-bit linker looks for
+		// different environment variables.
+		if t.goos == "freebsd" && t.gohostarch == "386" {
+			cmd.Env = mergeEnvLists([]string{"LD_32_LIBRARY_PATH=."}, cmd.Env)
+		}
 	}
 	return cmd.Run()
 }
@@ -805,46 +943,56 @@ func (t *tester) raceDetectorSupported() bool {
 	return false
 }
 
-func (t *tester) raceTest() error {
-	if err := t.dirCmd("src", "go", "test", "-race", "-i", "runtime/race", "flag", "os/exec").Run(); err != nil {
-		return err
-	}
-	if err := t.dirCmd("src", "go", "test", "-race", "-run=Output", "runtime/race").Run(); err != nil {
-		return err
-	}
-	if err := t.dirCmd("src", "go", "test", "-race", "-short", "flag", "os/exec").Run(); err != nil {
-		return err
-	}
+func (t *tester) raceTest(dt *distTest) error {
+	t.addCmd(dt, "src", "go", "test", "-race", "-i", "runtime/race", "flag", "os/exec")
+	t.addCmd(dt, "src", "go", "test", "-race", "-run=Output", "runtime/race")
+	t.addCmd(dt, "src", "go", "test", "-race", "-short", "-run=TestParse|TestEcho", "flag", "os/exec")
+	// We don't want the following line, because it
+	// slows down all.bash (by 10 seconds on my laptop).
+	// The race builder should catch any error here, but doesn't.
+	// TODO(iant): Figure out how to catch this.
+	// t.addCmd(dt, "src", "go", "test", "-race", "-run=TestParallelTest", "cmd/go")
 	if t.cgoEnabled {
 		env := mergeEnvLists([]string{"GOTRACEBACK=2"}, os.Environ())
-		cmd := t.dirCmd("misc/cgo/test", "go", "test", "-race", "-short")
+		cmd := t.addCmd(dt, "misc/cgo/test", "go", "test", "-race", "-short")
 		cmd.Env = env
-		if err := cmd.Run(); err != nil {
-			return err
-		}
 	}
 	if t.extLink() {
 		// Test with external linking; see issue 9133.
-		if err := t.dirCmd("src", "go", "test", "-race", "-short", "-ldflags=-linkmode=external", "flag", "os/exec").Run(); err != nil {
-			return err
-		}
+		t.addCmd(dt, "src", "go", "test", "-race", "-short", "-ldflags=-linkmode=external", "-run=TestParse|TestEcho", "flag", "os/exec")
 	}
 	return nil
 }
 
-func (t *tester) testDirTest(shard, shards int) error {
-	const runExe = "runtest.exe" // named exe for Windows, but harmless elsewhere
-	cmd := t.dirCmd("test", "go", "build", "-o", runExe, "run.go")
-	cmd.Env = mergeEnvLists([]string{"GOOS=" + t.gohostos, "GOARCH=" + t.gohostarch, "GOMAXPROCS="}, os.Environ())
-	if err := cmd.Run(); err != nil {
-		return err
+var runtest struct {
+	sync.Once
+	exe string
+	err error
+}
+
+func (t *tester) testDirTest(dt *distTest, shard, shards int) error {
+	runtest.Do(func() {
+		const exe = "runtest.exe" // named exe for Windows, but harmless elsewhere
+		cmd := t.dirCmd("test", "go", "build", "-o", exe, "run.go")
+		cmd.Env = mergeEnvLists([]string{"GOOS=" + t.gohostos, "GOARCH=" + t.gohostarch, "GOMAXPROCS="}, os.Environ())
+		runtest.exe = filepath.Join(cmd.Dir, exe)
+		if err := cmd.Run(); err != nil {
+			runtest.err = err
+			return
+		}
+		xatexit(func() {
+			os.Remove(runtest.exe)
+		})
+	})
+	if runtest.err != nil {
+		return runtest.err
 	}
-	absExe := filepath.Join(cmd.Dir, runExe)
-	defer os.Remove(absExe)
-	return t.dirCmd("test", absExe,
+
+	t.addCmd(dt, "test", runtest.exe,
 		fmt.Sprintf("--shard=%d", shard),
 		fmt.Sprintf("--shards=%d", shards),
-	).Run()
+	)
+	return nil
 }
 
 // mergeEnvLists merges the two environment lists such that
@@ -864,3 +1012,10 @@ NextVar:
 	}
 	return out
 }
+
+// cgoPackages is the standard packages that use cgo.
+var cgoPackages = []string{
+	"crypto/x509",
+	"net",
+	"os/user",
+}
diff --git a/src/cmd/dist/util.go b/src/cmd/dist/util.go
index f13210f..1b5d1f9 100644
--- a/src/cmd/dist/util.go
+++ b/src/cmd/dist/util.go
@@ -6,6 +6,8 @@ package main
 
 import (
 	"bytes"
+	"debug/elf"
+	"encoding/binary"
 	"fmt"
 	"io/ioutil"
 	"os"
@@ -16,7 +18,6 @@ import (
 	"strconv"
 	"strings"
 	"sync"
-	"sync/atomic"
 	"time"
 )
 
@@ -72,8 +73,8 @@ const (
 var outputLock sync.Mutex
 
 // run runs the command line cmd in dir.
-// If mode has ShowOutput set, run collects cmd's output and returns it as a string;
-// otherwise, run prints cmd's output to standard output after the command finishes.
+// If mode has ShowOutput set and Background unset, run passes cmd's output to
+// stdout/stderr directly. Otherwise, run returns cmd's output as a string.
 // If mode has CheckExit set and the command fails, run calls fatal.
 // If mode has Background set, this command is being run as a
 // Background job. Only bgrun should use the Background mode,
@@ -109,7 +110,9 @@ func run(dir string, mode int, cmd ...string) string {
 		}
 		outputLock.Unlock()
 		if mode&Background != 0 {
-			bgdied.Done()
+			// Prevent fatal from waiting on our own goroutine's
+			// bghelper to exit:
+			bghelpers.Done()
 		}
 		fatal("FAILED: %v: %v", strings.Join(cmd, " "), err)
 	}
@@ -130,62 +133,60 @@ var (
 	bgwork = make(chan func(), 1e5)
 	bgdone = make(chan struct{}, 1e5)
 
-	bgdied sync.WaitGroup
-	nwork  int32
-	ndone  int32
+	bghelpers sync.WaitGroup
 
-	dying  = make(chan bool)
-	nfatal int32
+	dieOnce sync.Once // guards close of dying
+	dying   = make(chan struct{})
 )
 
 func bginit() {
-	bgdied.Add(maxbg)
+	bghelpers.Add(maxbg)
 	for i := 0; i < maxbg; i++ {
 		go bghelper()
 	}
 }
 
 func bghelper() {
+	defer bghelpers.Done()
 	for {
-		w := <-bgwork
-		w()
-
-		// Stop if we're dying.
-		if atomic.LoadInt32(&nfatal) > 0 {
-			bgdied.Done()
+		select {
+		case <-dying:
 			return
+		case w := <-bgwork:
+			// Dying takes precedence over doing more work.
+			select {
+			case <-dying:
+				return
+			default:
+				w()
+			}
 		}
 	}
 }
 
 // bgrun is like run but runs the command in the background.
 // CheckExit|ShowOutput mode is implied (since output cannot be returned).
-func bgrun(dir string, cmd ...string) {
+// bgrun adds 1 to wg immediately, and calls Done when the work completes.
+func bgrun(wg *sync.WaitGroup, dir string, cmd ...string) {
+	wg.Add(1)
 	bgwork <- func() {
+		defer wg.Done()
 		run(dir, CheckExit|ShowOutput|Background, cmd...)
 	}
 }
 
 // bgwait waits for pending bgruns to finish.
 // bgwait must be called from only a single goroutine at a time.
-func bgwait() {
-	var wg sync.WaitGroup
-	wg.Add(maxbg)
-	done := make(chan bool)
-	for i := 0; i < maxbg; i++ {
-		bgwork <- func() {
-			wg.Done()
-
-			// Hold up bg goroutine until either the wait finishes
-			// or the program starts dying due to a call to fatal.
-			select {
-			case <-dying:
-			case <-done:
-			}
-		}
+func bgwait(wg *sync.WaitGroup) {
+	done := make(chan struct{})
+	go func() {
+		wg.Wait()
+		close(done)
+	}()
+	select {
+	case <-done:
+	case <-dying:
 	}
-	wg.Wait()
-	close(done)
 }
 
 // xgetwd returns the current directory.
@@ -355,16 +356,12 @@ func xworkdir() string {
 func fatal(format string, args ...interface{}) {
 	fmt.Fprintf(os.Stderr, "go tool dist: %s\n", fmt.Sprintf(format, args...))
 
+	dieOnce.Do(func() { close(dying) })
+
 	// Wait for background goroutines to finish,
 	// so that exit handler that removes the work directory
 	// is not fighting with active writes or open files.
-	if atomic.AddInt32(&nfatal, 1) == 1 {
-		close(dying)
-	}
-	for i := 0; i < maxbg; i++ {
-		bgwork <- func() {} // wake up workers so they notice nfatal > 0
-	}
-	bgdied.Wait()
+	bghelpers.Wait()
 
 	xexit(2)
 }
@@ -404,9 +401,11 @@ func main() {
 	switch gohostos {
 	case "darwin":
 		// Even on 64-bit platform, darwin uname -m prints i386.
-		if strings.Contains(run("", CheckExit, "sysctl", "machdep.cpu.extfeatures"), "EM64T") {
-			gohostarch = "amd64"
-		}
+		// We don't support any of the OS X versions that run on 32-bit-only hardware anymore.
+		gohostarch = "amd64"
+	case "freebsd":
+		// Since FreeBSD 10 gcc is no longer part of the base system.
+		defaultclang = true
 	case "solaris":
 		// Even on 64-bit platform, solaris uname -m prints i86pc.
 		out := run("", CheckExit, "isainfo", "-n")
@@ -443,6 +442,16 @@ func main() {
 			gohostarch = "ppc64le"
 		case strings.Contains(out, "ppc64"):
 			gohostarch = "ppc64"
+		case strings.Contains(out, "mips64"):
+			file, err := elf.Open(os.Args[0])
+			if err != nil {
+				fatal("failed to open %s to determine endianness: %v", os.Args[0], err)
+			}
+			if file.FileHeader.ByteOrder == binary.BigEndian {
+				gohostarch = "mips64"
+			} else {
+				gohostarch = "mips64le"
+			}
 		case gohostos == "darwin":
 			if strings.Contains(run("", CheckExit, "uname", "-v"), "RELEASE_ARM_") {
 				gohostarch = "arm"
@@ -452,7 +461,7 @@ func main() {
 		}
 	}
 
-	if gohostarch == "arm" {
+	if gohostarch == "arm" || gohostarch == "mips64" || gohostarch == "mips64le" {
 		maxbg = min(maxbg, runtime.NumCPU())
 	}
 	bginit()
@@ -480,6 +489,14 @@ func main() {
 		}
 	}
 
+	if len(os.Args) > 1 && os.Args[1] == "-check-goarm" {
+		useVFPv1() // might fail with SIGILL
+		println("VFPv1 OK.")
+		useVFPv3() // might fail with SIGILL
+		println("VFPv3 OK.")
+		os.Exit(0)
+	}
+
 	xinit()
 	xmain()
 	xexit(0)
@@ -515,40 +532,21 @@ func xgetgoarm() string {
 		// OpenBSD currently only supports softfloat.
 		return "5"
 	}
-	if goos != "linux" {
-		// All other arm platforms that we support
-		// require ARMv7.
+
+	// Try to exec ourselves in a mode to detect VFP support.
+	// Seeing how far it gets determines which instructions failed.
+	// The test is OS-agnostic.
+	out := run("", 0, os.Args[0], "-check-goarm")
+	v1ok := strings.Contains(out, "VFPv1 OK.")
+	v3ok := strings.Contains(out, "VFPv3 OK.")
+
+	if v1ok && v3ok {
 		return "7"
 	}
-	cpuinfo := readfile("/proc/cpuinfo")
-	goarm := "5"
-	for _, line := range splitlines(cpuinfo) {
-		line := strings.SplitN(line, ":", 2)
-		if len(line) < 2 {
-			continue
-		}
-		if strings.TrimSpace(line[0]) != "Features" {
-			continue
-		}
-		features := splitfields(line[1])
-		sort.Strings(features) // so vfpv3 sorts after vfp
-
-		// Infer GOARM value from the vfp features available
-		// on this host. Values of GOARM detected are:
-		// 5: no vfp support was found
-		// 6: vfp (v1) support was detected, but no higher
-		// 7: vfpv3 support was detected.
-		// This matches the assertions in runtime.checkarm.
-		for _, f := range features {
-			switch f {
-			case "vfp":
-				goarm = "6"
-			case "vfpv3":
-				goarm = "7"
-			}
-		}
+	if v1ok {
+		return "6"
 	}
-	return goarm
+	return "5"
 }
 
 func min(a, b int) int {
diff --git a/src/cmd/dist/util_gc.go b/src/cmd/dist/util_gc.go
index 9f6cfd0..81e52b6 100644
--- a/src/cmd/dist/util_gc.go
+++ b/src/cmd/dist/util_gc.go
@@ -17,3 +17,11 @@ func cansse2() bool {
 	cpuid(&info, 1)
 	return info[3]&(1<<26) != 0 // SSE2
 }
+
+// useVFPv1 tries to execute one VFPv1 instruction on ARM.
+// It will crash the current process if VFPv1 is missing.
+func useVFPv1()
+
+// useVFPv3 tries to execute one VFPv3 instruction on ARM.
+// It will crash the current process if VFPv3 is missing.
+func useVFPv3()
diff --git a/src/cmd/dist/util_gccgo.go b/src/cmd/dist/util_gccgo.go
index 14ac70b..18e328f 100644
--- a/src/cmd/dist/util_gccgo.go
+++ b/src/cmd/dist/util_gccgo.go
@@ -18,3 +18,7 @@ int supports_sse2() {
 import "C"
 
 func cansse2() bool { return C.supports_sse2() != 0 }
+
+func useVFPv1() {}
+
+func useVFPv3() {}
diff --git a/src/cmd/dist/vfp_arm.s b/src/cmd/dist/vfp_arm.s
new file mode 100644
index 0000000..647c439
--- /dev/null
+++ b/src/cmd/dist/vfp_arm.s
@@ -0,0 +1,17 @@
+// Copyright 2015 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.
+
+// +build gc,arm
+
+#include "textflag.h"
+
+// try to run "vmov.f64 d0, d0" instruction
+TEXT ·useVFPv1(SB),NOSPLIT,$0
+	WORD $0xeeb00b40	// vmov.f64 d0, d0
+	RET
+
+// try to run VFPv3-only "vmov.f64 d0, #112" instruction
+TEXT ·useVFPv3(SB),NOSPLIT,$0
+	WORD $0xeeb70b00	// vmov.f64 d0, #112
+	RET
diff --git a/src/cmd/dist/vfp_default.s b/src/cmd/dist/vfp_default.s
new file mode 100644
index 0000000..5cf9997
--- /dev/null
+++ b/src/cmd/dist/vfp_default.s
@@ -0,0 +1,13 @@
+// Copyright 2015 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.
+
+// +build !arm,gc
+
+#include "textflag.h"
+
+TEXT ·useVFPv1(SB),NOSPLIT,$0
+	RET
+
+TEXT ·useVFPv3(SB),NOSPLIT,$0
+	RET
diff --git a/src/cmd/doc/dirs.go b/src/cmd/doc/dirs.go
new file mode 100644
index 0000000..2982eee
--- /dev/null
+++ b/src/cmd/doc/dirs.go
@@ -0,0 +1,115 @@
+// Copyright 2015 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 (
+	"go/build"
+	"log"
+	"os"
+	"path"
+	"path/filepath"
+	"strings"
+)
+
+// Dirs is a structure for scanning the directory tree.
+// Its Next method returns the next Go source directory it finds.
+// Although it can be used to scan the tree multiple times, it
+// only walks the tree once, caching the data it finds.
+type Dirs struct {
+	scan   chan string // directories generated by walk.
+	paths  []string    // Cache of known paths.
+	offset int         // Counter for Next.
+}
+
+var dirs Dirs
+
+func init() {
+	dirs.paths = make([]string, 0, 1000)
+	dirs.scan = make(chan string)
+	go dirs.walk()
+}
+
+// Reset puts the scan back at the beginning.
+func (d *Dirs) Reset() {
+	d.offset = 0
+}
+
+// Next returns the next directory in the scan. The boolean
+// is false when the scan is done.
+func (d *Dirs) Next() (string, bool) {
+	if d.offset < len(d.paths) {
+		path := d.paths[d.offset]
+		d.offset++
+		return path, true
+	}
+	path, ok := <-d.scan
+	if !ok {
+		return "", false
+	}
+	d.paths = append(d.paths, path)
+	d.offset++
+	return path, ok
+}
+
+// walk walks the trees in GOROOT and GOPATH.
+func (d *Dirs) walk() {
+	d.bfsWalkRoot(build.Default.GOROOT)
+	for _, root := range splitGopath() {
+		d.bfsWalkRoot(root)
+	}
+	close(d.scan)
+}
+
+// bfsWalkRoot walks a single directory hierarchy in breadth-first lexical order.
+// Each Go source directory it finds is delivered on d.scan.
+func (d *Dirs) bfsWalkRoot(root string) {
+	root = path.Join(root, "src")
+
+	// this is the queue of directories to examine in this pass.
+	this := []string{}
+	// next is the queue of directories to examine in the next pass.
+	next := []string{root}
+
+	for len(next) > 0 {
+		this, next = next, this[0:0]
+		for _, dir := range this {
+			fd, err := os.Open(dir)
+			if err != nil {
+				log.Printf("error opening %s: %v", dir, err)
+				return // TODO? There may be entry before the error.
+			}
+			entries, err := fd.Readdir(0)
+			fd.Close()
+			if err != nil {
+				log.Printf("error reading %s: %v", dir, err)
+				return // TODO? There may be entry before the error.
+			}
+			hasGoFiles := false
+			for _, entry := range entries {
+				name := entry.Name()
+				// For plain files, remember if this directory contains any .go
+				// source files, but ignore them otherwise.
+				if !entry.IsDir() {
+					if !hasGoFiles && strings.HasSuffix(name, ".go") {
+						hasGoFiles = true
+					}
+					continue
+				}
+				// Entry is a directory.
+				// No .git or other dot nonsense please.
+				if strings.HasPrefix(name, ".") {
+					continue
+				}
+				// Remember this (fully qualified) directory for the next pass.
+				next = append(next, filepath.Join(dir, name))
+			}
+			if hasGoFiles {
+				// It's a candidate.
+				d.scan <- dir
+			}
+		}
+
+	}
+}
diff --git a/src/cmd/doc/doc_test.go b/src/cmd/doc/doc_test.go
index b97cc76..ed1d0e7 100644
--- a/src/cmd/doc/doc_test.go
+++ b/src/cmd/doc/doc_test.go
@@ -7,13 +7,21 @@ package main
 import (
 	"bytes"
 	"flag"
-	"os"
-	"os/exec"
 	"regexp"
 	"runtime"
+	"strings"
 	"testing"
 )
 
+func maybeSkip(t *testing.T) {
+	if strings.HasPrefix(runtime.GOOS, "nacl") {
+		t.Skip("nacl does not have a full file tree")
+	}
+	if runtime.GOOS == "darwin" && strings.HasPrefix(runtime.GOARCH, "arm") {
+		t.Skip("darwin/arm does not have a full file tree")
+	}
+}
+
 const (
 	dataDir = "testdata"
 	binary  = "testdoc"
@@ -54,6 +62,7 @@ var tests = []test{
 			`Package comment`,
 			`const ExportedConstant = 1`,                            // Simple constant.
 			`const ConstOne = 1`,                                    // First entry in constant block.
+			`const ConstFive ...`,                                   // From block starting with unexported constant.
 			`var ExportedVariable = 1`,                              // Simple variable.
 			`var VarOne = 1`,                                        // First entry in variable block.
 			`func ExportedFunc\(a int\) bool`,                       // Function.
@@ -73,6 +82,7 @@ var tests = []test{
 			`Comment before VarOne`,             // No comment for first entry in variable block.
 			`ConstTwo = 2`,                      // No second entry in constant block.
 			`VarTwo = 2`,                        // No second entry in variable block.
+			`VarFive = 5`,                       // From block starting with unexported variable.
 			`type unexportedType`,               // No unexported type.
 			`unexportedTypedConstant`,           // No unexported typed constant.
 			`Field`,                             // No fields.
@@ -209,7 +219,8 @@ var tests = []test{
 		[]string{
 			`Comment about exported type`, // Include comment.
 			`type ExportedType struct`,    // Type definition.
-			`Comment before exported field.*\n.*ExportedField +int`,
+			`Comment before exported field.*\n.*ExportedField +int` +
+				`.*Comment on line with exported field.`,
 			`Has unexported fields`,
 			`func \(ExportedType\) ExportedMethod\(a int\) bool`,
 			`const ExportedTypedConstant ExportedType = iota`, // Must include associated constant.
@@ -253,6 +264,40 @@ var tests = []test{
 		nil,
 	},
 
+	// Interface.
+	{
+		"type",
+		[]string{p, `ExportedInterface`},
+		[]string{
+			`Comment about exported interface`, // Include comment.
+			`type ExportedInterface interface`, // Interface definition.
+			`Comment before exported method.*\n.*ExportedMethod\(\)` +
+				`.*Comment on line with exported method`,
+			`Has unexported methods`,
+		},
+		[]string{
+			`unexportedField`,               // No unexported field.
+			`Comment about exported method`, // No comment about exported method.
+			`unexportedMethod`,              // No unexported method.
+			`unexportedTypedConstant`,       // No unexported constant.
+		},
+	},
+	// Interface -u with unexported methods.
+	{
+		"type with unexported methods and -u",
+		[]string{"-u", p, `ExportedInterface`},
+		[]string{
+			`Comment about exported interface`, // Include comment.
+			`type ExportedInterface interface`, // Interface definition.
+			`Comment before exported method.*\n.*ExportedMethod\(\)` +
+				`.*Comment on line with exported method`,
+			`unexportedMethod\(\).*Comment on line with unexported method.`,
+		},
+		[]string{
+			`Has unexported methods`,
+		},
+	},
+
 	// Method.
 	{
 		"method",
@@ -299,9 +344,7 @@ var tests = []test{
 }
 
 func TestDoc(t *testing.T) {
-	if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
-		t.Skip("TODO: on darwin/arm, test fails: no such package cmd/doc/testdata")
-	}
+	maybeSkip(t)
 	for _, test := range tests {
 		var b bytes.Buffer
 		var flagSet flag.FlagSet
@@ -337,12 +380,89 @@ func TestDoc(t *testing.T) {
 	}
 }
 
-// run runs the command, but calls t.Fatal if there is an error.
-func run(c *exec.Cmd, t *testing.T) []byte {
-	output, err := c.CombinedOutput()
-	if err != nil {
-		os.Stdout.Write(output)
-		t.Fatal(err)
+// Test the code to try multiple packages. Our test case is
+//	go doc rand.Float64
+// This needs to find math/rand.Float64; however crypto/rand, which doesn't
+// have the symbol, usually appears first in the directory listing.
+func TestMultiplePackages(t *testing.T) {
+	if testing.Short() {
+		t.Skip("scanning file system takes too long")
+	}
+	maybeSkip(t)
+	var b bytes.Buffer // We don't care about the output.
+	// Make sure crypto/rand does not have the symbol.
+	{
+		var flagSet flag.FlagSet
+		err := do(&b, &flagSet, []string{"crypto/rand.float64"})
+		if err == nil {
+			t.Errorf("expected error from crypto/rand.float64")
+		} else if !strings.Contains(err.Error(), "no symbol float64") {
+			t.Errorf("unexpected error %q from crypto/rand.float64", err)
+		}
+	}
+	// Make sure math/rand does have the symbol.
+	{
+		var flagSet flag.FlagSet
+		err := do(&b, &flagSet, []string{"math/rand.float64"})
+		if err != nil {
+			t.Errorf("unexpected error %q from math/rand.float64", err)
+		}
+	}
+	// Try the shorthand.
+	{
+		var flagSet flag.FlagSet
+		err := do(&b, &flagSet, []string{"rand.float64"})
+		if err != nil {
+			t.Errorf("unexpected error %q from rand.float64", err)
+		}
+	}
+	// Now try a missing symbol. We should see both packages in the error.
+	{
+		var flagSet flag.FlagSet
+		err := do(&b, &flagSet, []string{"rand.doesnotexit"})
+		if err == nil {
+			t.Errorf("expected error from rand.doesnotexit")
+		} else {
+			errStr := err.Error()
+			if !strings.Contains(errStr, "no symbol") {
+				t.Errorf("error %q should contain 'no symbol", errStr)
+			}
+			if !strings.Contains(errStr, "crypto/rand") {
+				t.Errorf("error %q should contain crypto/rand", errStr)
+			}
+			if !strings.Contains(errStr, "math/rand") {
+				t.Errorf("error %q should contain math/rand", errStr)
+			}
+		}
+	}
+}
+
+type trimTest struct {
+	path   string
+	prefix string
+	result string
+	ok     bool
+}
+
+var trimTests = []trimTest{
+	{"", "", "", true},
+	{"/usr/gopher", "/usr/gopher", "/usr/gopher", true},
+	{"/usr/gopher/bar", "/usr/gopher", "bar", true},
+	{"/usr/gopher", "/usr/gopher", "/usr/gopher", true},
+	{"/usr/gopherflakes", "/usr/gopher", "/usr/gopherflakes", false},
+	{"/usr/gopher/bar", "/usr/zot", "/usr/gopher/bar", false},
+}
+
+func TestTrim(t *testing.T) {
+	for _, test := range trimTests {
+		result, ok := trim(test.path, test.prefix)
+		if ok != test.ok {
+			t.Errorf("%s %s expected %t got %t", test.path, test.prefix, test.ok, ok)
+			continue
+		}
+		if result != test.result {
+			t.Errorf("%s %s expected %q got %q", test.path, test.prefix, test.result, result)
+			continue
+		}
 	}
-	return output
 }
diff --git a/src/cmd/doc/main.go b/src/cmd/doc/main.go
index dda6aec..df1890f 100644
--- a/src/cmd/doc/main.go
+++ b/src/cmd/doc/main.go
@@ -11,10 +11,12 @@
 // One argument:
 //	go doc <pkg>
 //	go doc <sym>[.<method>]
-//	go doc [<pkg>].<sym>[.<method>]
+//	go doc [<pkg>.]<sym>[.<method>]
+//	go doc [<pkg>.][<sym>.]<method>
 // The first item in this list that succeeds is the one whose documentation
 // is printed. If there is a symbol but no package, the package in the current
-// directory is chosen.
+// directory is chosen. However, if the argument begins with a capital
+// letter it is always assumed to be a symbol in the current directory.
 //
 // Two arguments:
 //	go doc <pkg> <sym>[.<method>]
@@ -30,13 +32,13 @@
 package main
 
 import (
+	"bytes"
 	"flag"
 	"fmt"
 	"go/build"
 	"io"
 	"log"
 	"os"
-	"path"
 	"path/filepath"
 	"strings"
 	"unicode"
@@ -82,32 +84,72 @@ func do(writer io.Writer, flagSet *flag.FlagSet, args []string) (err error) {
 	flagSet.BoolVar(&matchCase, "c", false, "symbol matching honors case (paths not affected)")
 	flagSet.BoolVar(&showCmd, "cmd", false, "show symbols with package docs even if package is a command")
 	flagSet.Parse(args)
-	buildPackage, userPath, symbol := parseArgs(flagSet.Args())
-	symbol, method := parseSymbol(symbol)
-	pkg := parsePackage(writer, buildPackage, userPath)
-	defer func() {
-		pkg.flush()
-		e := recover()
-		if e == nil {
-			return
+	var paths []string
+	var symbol, method string
+	// Loop until something is printed.
+	dirs.Reset()
+	for i := 0; ; i++ {
+		buildPackage, userPath, sym, more := parseArgs(flagSet.Args())
+		if i > 0 && !more { // Ignore the "more" bit on the first iteration.
+			return failMessage(paths, symbol, method)
 		}
-		pkgError, ok := e.(PackageError)
-		if ok {
-			err = pkgError
+		symbol, method = parseSymbol(sym)
+		pkg := parsePackage(writer, buildPackage, userPath)
+		paths = append(paths, pkg.prettyPath())
+
+		defer func() {
+			pkg.flush()
+			e := recover()
+			if e == nil {
+				return
+			}
+			pkgError, ok := e.(PackageError)
+			if ok {
+				err = pkgError
+				return
+			}
+			panic(e)
+		}()
+
+		// The builtin package needs special treatment: its symbols are lower
+		// case but we want to see them, always.
+		if pkg.build.ImportPath == "builtin" {
+			unexported = true
+		}
+
+		switch {
+		case symbol == "":
+			pkg.packageDoc() // The package exists, so we got some output.
 			return
+		case method == "":
+			if pkg.symbolDoc(symbol) {
+				return
+			}
+		default:
+			if pkg.methodDoc(symbol, method) {
+				return
+			}
 		}
-		panic(e)
-	}()
-	switch {
-	case symbol == "":
-		pkg.packageDoc()
-		return
-	case method == "":
-		pkg.symbolDoc(symbol)
-	default:
-		pkg.methodDoc(symbol, method)
 	}
-	return nil
+}
+
+// failMessage creates a nicely formatted error message when there is no result to show.
+func failMessage(paths []string, symbol, method string) error {
+	var b bytes.Buffer
+	if len(paths) > 1 {
+		b.WriteString("s")
+	}
+	b.WriteString(" ")
+	for i, path := range paths {
+		if i > 0 {
+			b.WriteString(", ")
+		}
+		b.WriteString(path)
+	}
+	if method == "" {
+		return fmt.Errorf("no symbol %s in package%s", symbol, &b)
+	}
+	return fmt.Errorf("no method %s.%s in package%s", symbol, method, &b)
 }
 
 // parseArgs analyzes the arguments (if any) and returns the package
@@ -115,13 +157,19 @@ func do(writer io.Writer, flagSet *flag.FlagSet, args []string) (err error) {
 // the path (or "" if it's the current package) and the symbol
 // (possibly with a .method) within that package.
 // parseSymbol is used to analyze the symbol itself.
-func parseArgs(args []string) (*build.Package, string, string) {
+// The boolean final argument reports whether it is possible that
+// there may be more directories worth looking at. It will only
+// be true if the package path is a partial match for some directory
+// and there may be more matches. For example, if the argument
+// is rand.Float64, we must scan both crypto/rand and math/rand
+// to find the symbol, and the first call will return crypto/rand, true.
+func parseArgs(args []string) (pkg *build.Package, path, symbol string, more bool) {
 	switch len(args) {
 	default:
 		usage()
 	case 0:
 		// Easy: current directory.
-		return importDir(pwd()), "", ""
+		return importDir(pwd()), "", "", false
 	case 1:
 		// Done below.
 	case 2:
@@ -130,7 +178,7 @@ func parseArgs(args []string) (*build.Package, string, string) {
 		if err != nil {
 			log.Fatalf("%s", err)
 		}
-		return pkg, args[0], args[1]
+		return pkg, args[0], args[1], false
 	}
 	// Usual case: one argument.
 	arg := args[0]
@@ -140,7 +188,7 @@ func parseArgs(args []string) (*build.Package, string, string) {
 	// package paths as their prefix.
 	pkg, err := build.Import(arg, "", build.ImportComment)
 	if err == nil {
-		return pkg, arg, ""
+		return pkg, arg, "", false
 	}
 	// Another disambiguator: If the symbol starts with an upper
 	// case letter, it can only be a symbol in the current directory.
@@ -149,7 +197,7 @@ func parseArgs(args []string) (*build.Package, string, string) {
 	if isUpper(arg) {
 		pkg, err := build.ImportDir(".", build.ImportComment)
 		if err == nil {
-			return pkg, "", arg
+			return pkg, "", arg, false
 		}
 	}
 	// If it has a slash, it must be a package path but there is a symbol.
@@ -175,21 +223,23 @@ func parseArgs(args []string) (*build.Package, string, string) {
 		// Have we identified a package already?
 		pkg, err := build.Import(arg[0:period], "", build.ImportComment)
 		if err == nil {
-			return pkg, arg[0:period], symbol
+			return pkg, arg[0:period], symbol, false
 		}
 		// See if we have the basename or tail of a package, as in json for encoding/json
 		// or ivy/value for robpike.io/ivy/value.
-		path := findPackage(arg[0:period])
-		if path != "" {
-			return importDir(path), arg[0:period], symbol
+		// Launch findPackage as a goroutine so it can return multiple paths if required.
+		path, ok := findPackage(arg[0:period])
+		if ok {
+			return importDir(path), arg[0:period], symbol, true
 		}
+		dirs.Reset() // Next iteration of for loop must scan all the directories again.
 	}
 	// If it has a slash, we've failed.
 	if slash >= 0 {
 		log.Fatalf("no such package %s", arg[0:period])
 	}
 	// Guess it's a symbol in the current directory.
-	return importDir(pwd()), "", arg
+	return importDir(pwd()), "", arg, false
 }
 
 // importDir is just an error-catching wrapper for build.ImportDir.
@@ -250,26 +300,22 @@ func isUpper(name string) bool {
 	return unicode.IsUpper(ch)
 }
 
-// findPackage returns the full file name path specified by the
-// (perhaps partial) package path pkg.
-func findPackage(pkg string) string {
-	if pkg == "" {
-		return ""
-	}
-	if isUpper(pkg) {
-		return "" // Upper case symbol cannot be a package name.
-	}
-	path := pathFor(build.Default.GOROOT, pkg)
-	if path != "" {
-		return path
+// findPackage returns the full file name path that first matches the
+// (perhaps partial) package path pkg. The boolean reports if any match was found.
+func findPackage(pkg string) (string, bool) {
+	if pkg == "" || isUpper(pkg) { // Upper case symbol cannot be a package name.
+		return "", false
 	}
-	for _, root := range splitGopath() {
-		path = pathFor(root, pkg)
-		if path != "" {
-			return path
+	pkgString := filepath.Clean(string(filepath.Separator) + pkg)
+	for {
+		path, ok := dirs.Next()
+		if !ok {
+			return "", false
+		}
+		if strings.HasSuffix(path, pkgString) {
+			return path, true
 		}
 	}
-	return ""
 }
 
 // splitGopath splits $GOPATH into a list of roots.
@@ -277,73 +323,6 @@ func splitGopath() []string {
 	return filepath.SplitList(build.Default.GOPATH)
 }
 
-// pathsFor recursively walks the tree at root looking for possible directories for the package:
-// those whose package path is pkg or which have a proper suffix pkg.
-func pathFor(root, pkg string) (result string) {
-	root = path.Join(root, "src")
-	slashDot := string(filepath.Separator) + "."
-	// We put a slash on the pkg so can use simple string comparison below
-	// yet avoid inadvertent matches, like /foobar matching bar.
-	pkgString := filepath.Clean(string(filepath.Separator) + pkg)
-
-	// We use panic/defer to short-circuit processing at the first match.
-	// A nil panic reports that the path has been found.
-	defer func() {
-		err := recover()
-		if err != nil {
-			panic(err)
-		}
-	}()
-
-	visit := func(pathName string, f os.FileInfo, err error) error {
-		if err != nil {
-			return nil
-		}
-		// One package per directory. Ignore the files themselves.
-		if !f.IsDir() {
-			return nil
-		}
-		// No .git or other dot nonsense please.
-		if strings.Contains(pathName, slashDot) {
-			return filepath.SkipDir
-		}
-		// Is the tail of the path correct?
-		if strings.HasSuffix(pathName, pkgString) && hasGoFiles(pathName) {
-			result = pathName
-			panic(nil)
-		}
-		return nil
-	}
-
-	filepath.Walk(root, visit)
-	return "" // Call to panic above sets the real value.
-}
-
-// hasGoFiles tests whether the directory contains at least one file with ".go"
-// extension
-func hasGoFiles(path string) bool {
-	dir, err := os.Open(path)
-	if err != nil {
-		// ignore unreadable directories
-		return false
-	}
-	defer dir.Close()
-
-	names, err := dir.Readdirnames(0)
-	if err != nil {
-		// ignore unreadable directories
-		return false
-	}
-
-	for _, name := range names {
-		if strings.HasSuffix(name, ".go") {
-			return true
-		}
-	}
-
-	return false
-}
-
 // pwd returns the current directory.
 func pwd() string {
 	wd, err := os.Getwd()
diff --git a/src/cmd/doc/pkg.go b/src/cmd/doc/pkg.go
index 569c7a3..0b07f7c 100644
--- a/src/cmd/doc/pkg.go
+++ b/src/cmd/doc/pkg.go
@@ -16,6 +16,8 @@ import (
 	"io"
 	"log"
 	"os"
+	"path/filepath"
+	"strings"
 	"unicode"
 	"unicode/utf8"
 )
@@ -46,6 +48,51 @@ func (p PackageError) Error() string {
 	return string(p)
 }
 
+// prettyPath returns a version of the package path that is suitable for an
+// error message. It obeys the import comment if present. Also, since
+// pkg.build.ImportPath is sometimes the unhelpful "" or ".", it looks for a
+// directory name in GOROOT or GOPATH if that happens.
+func (pkg *Package) prettyPath() string {
+	path := pkg.build.ImportComment
+	if path == "" {
+		path = pkg.build.ImportPath
+	}
+	if path != "." && path != "" {
+		return path
+	}
+	// Convert the source directory into a more useful path.
+	// Also convert everything to slash-separated paths for uniform handling.
+	path = filepath.Clean(filepath.ToSlash(pkg.build.Dir))
+	// Can we find a decent prefix?
+	goroot := filepath.Join(build.Default.GOROOT, "src")
+	if p, ok := trim(path, filepath.ToSlash(goroot)); ok {
+		return p
+	}
+	for _, gopath := range splitGopath() {
+		if p, ok := trim(path, filepath.ToSlash(gopath)); ok {
+			return p
+		}
+	}
+	return path
+}
+
+// trim trims the directory prefix from the path, paying attention
+// to the path separator. If they are the same string or the prefix
+// is not present the original is returned. The boolean reports whether
+// the prefix is present. That path and prefix have slashes for separators.
+func trim(path, prefix string) (string, bool) {
+	if !strings.HasPrefix(path, prefix) {
+		return path, false
+	}
+	if path == prefix {
+		return path, true
+	}
+	if path[len(prefix)] == '/' {
+		return path[len(prefix)+1:], true
+	}
+	return path, false // Textual prefix but not a path prefix.
+}
+
 // pkg.Fatalf is like log.Fatalf, but panics so it can be recovered in the
 // main do function, so it doesn't cause an exit. Allows testing to work
 // without running a subprocess. The log prefix will be added when
@@ -140,10 +187,12 @@ func (pkg *Package) emit(comment string, node ast.Node) {
 			log.Fatal(err)
 		}
 		if comment != "" {
-			pkg.newlines(2) // Guarantee blank line before comment.
+			pkg.newlines(1)
 			doc.ToText(&pkg.buf, comment, "    ", indent, indentedWidth)
+			pkg.newlines(2) // Blank line after comment to separate from next item.
+		} else {
+			pkg.newlines(1)
 		}
-		pkg.newlines(1)
 	}
 }
 
@@ -218,7 +267,7 @@ func (pkg *Package) packageDoc() {
 		return
 	}
 
-	pkg.newlines(1)
+	pkg.newlines(2) // Guarantee blank line before the components.
 	pkg.valueSummary(pkg.doc.Consts)
 	pkg.valueSummary(pkg.doc.Vars)
 	pkg.funcSummary(pkg.doc.Funcs)
@@ -257,18 +306,7 @@ func (pkg *Package) packageClause(checkUserPath bool) {
 // valueSummary prints a one-line summary for each set of values and constants.
 func (pkg *Package) valueSummary(values []*doc.Value) {
 	for _, value := range values {
-		// Only print first item in spec, show ... to stand for the rest.
-		spec := value.Decl.Specs[0].(*ast.ValueSpec) // Must succeed.
-		exported := true
-		for _, name := range spec.Names {
-			if !isExported(name.Name) {
-				exported = false
-				break
-			}
-		}
-		if exported {
-			pkg.oneLineValueGenDecl(value.Decl)
-		}
+		pkg.oneLineValueGenDecl(value.Decl)
 	}
 }
 
@@ -355,7 +393,7 @@ func (pkg *Package) findTypeSpec(decl *ast.GenDecl, symbol string) *ast.TypeSpec
 // symbolDoc prints the docs for symbol. There may be multiple matches.
 // If symbol matches a type, output includes its methods factories and associated constants.
 // If there is no top-level symbol, symbolDoc looks for methods that match.
-func (pkg *Package) symbolDoc(symbol string) {
+func (pkg *Package) symbolDoc(symbol string) bool {
 	defer pkg.flush()
 	found := false
 	// Functions.
@@ -424,9 +462,10 @@ func (pkg *Package) symbolDoc(symbol string) {
 	if !found {
 		// See if there are methods.
 		if !pkg.printMethodDoc("", symbol) {
-			log.Printf("symbol %s not present in package %s installed in %q", symbol, pkg.name, pkg.build.ImportPath)
+			return false
 		}
 	}
+	return true
 }
 
 // trimUnexportedElems modifies spec in place to elide unexported fields from
@@ -465,13 +504,16 @@ func trimUnexportedFields(fields *ast.FieldList, what string) *ast.FieldList {
 		return fields
 	}
 	unexportedField := &ast.Field{
-		Type: ast.NewIdent(""), // Hack: printer will treat this as a field with a named type.
+		Type: &ast.Ident{
+			// Hack: printer will treat this as a field with a named type.
+			// Setting Name and NamePos to ("", fields.Closing-1) ensures that
+			// when Pos and End are called on this field, they return the
+			// position right before closing '}' character.
+			Name:    "",
+			NamePos: fields.Closing - 1,
+		},
 		Comment: &ast.CommentGroup{
-			List: []*ast.Comment{
-				&ast.Comment{
-					Text: fmt.Sprintf("// Has unexported %s.\n", what),
-				},
-			},
+			List: []*ast.Comment{{Text: fmt.Sprintf("// Has unexported %s.\n", what)}},
 		},
 	}
 	return &ast.FieldList{
@@ -508,11 +550,9 @@ func (pkg *Package) printMethodDoc(symbol, method string) bool {
 }
 
 // methodDoc prints the docs for matches of symbol.method.
-func (pkg *Package) methodDoc(symbol, method string) {
+func (pkg *Package) methodDoc(symbol, method string) bool {
 	defer pkg.flush()
-	if !pkg.printMethodDoc(symbol, method) {
-		pkg.Fatalf("no method %s.%s in package %s installed in %q", symbol, method, pkg.name, pkg.build.ImportPath)
-	}
+	return pkg.printMethodDoc(symbol, method)
 }
 
 // match reports whether the user's symbol matches the program's.
diff --git a/src/cmd/doc/testdata/pkg.go b/src/cmd/doc/testdata/pkg.go
index ebefb50..3e7acee 100644
--- a/src/cmd/doc/testdata/pkg.go
+++ b/src/cmd/doc/testdata/pkg.go
@@ -21,6 +21,13 @@ const (
 	constThree = 3 // Comment on line with constThree.
 )
 
+// Const block where first entry is unexported.
+const (
+	constFour = iota
+	ConstFive
+	ConstSix
+)
+
 // Variables
 
 // Comment about exported variable.
@@ -37,6 +44,13 @@ var (
 	varThree = 3 // Comment on line with varThree.
 )
 
+// Var block where first entry is unexported.
+var (
+	varFour = 4
+	VarFive = 5
+	varSix  = 6
+)
+
 // Comment about exported function.
 func ExportedFunc(a int) bool
 
@@ -46,7 +60,7 @@ func internalFunc(a int) bool
 // Comment about exported type.
 type ExportedType struct {
 	// Comment before exported field.
-	ExportedField   int
+	ExportedField   int // Comment on line with exported field.
 	unexportedField int // Comment on line with unexported field.
 }
 
@@ -73,6 +87,13 @@ func ExportedTypeConstructor() *ExportedType {
 
 const unexportedTypedConstant ExportedType = 1 // In a separate section to test -u.
 
+// Comment about exported interface.
+type ExportedInterface interface {
+	// Comment before exported method.
+	ExportedMethod()   // Comment on line with exported method.
+	unexportedMethod() // Comment on line with unexported method.
+}
+
 // Comment about unexported type.
 type unexportedType int
 
diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go
index 1134997..c81bd40 100644
--- a/src/cmd/go/alldocs.go
+++ b/src/cmd/go/alldocs.go
@@ -84,12 +84,17 @@ and test commands:
 	-n
 		print the commands but do not run them.
 	-p n
-		the number of builds that can be run in parallel.
+		the number of programs, such as build commands or
+		test binaries, that can be run in parallel.
 		The default is the number of CPUs available, except
 		on darwin/arm which defaults to 1.
 	-race
 		enable data race detection.
 		Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
+	-msan
+		enable interoperation with memory sanitizer.
+		Supported only on linux/amd64,
+		and only with Clang/LLVM as the host C compiler.
 	-v
 		print the names of packages as they are compiled.
 	-work
@@ -112,13 +117,14 @@ and test commands:
 		a suffix to use in the name of the package installation directory,
 		in order to keep output separate from default builds.
 		If using the -race flag, the install suffix is automatically set to race
-		or, if set explicitly, has _race appended to it.  Using a -buildmode
-		option that requires non-default compile flags has a similar effect.
+		or, if set explicitly, has _race appended to it.  Likewise for the -msan
+		flag.  Using a -buildmode option that requires non-default compile flags
+		has a similar effect.
 	-ldflags 'flag list'
 		arguments to pass on each go tool link invocation.
 	-linkshared
 		link against shared libraries previously created with
-		-buildmode=shared
+		-buildmode=shared.
 	-pkgdir dir
 		install and load all packages from dir instead of the usual locations.
 		For example, when building with a non-standard configuration,
@@ -225,12 +231,17 @@ which is schematically one of these:
 
 	go doc <pkg>
 	go doc <sym>[.<method>]
-	go doc [<pkg>].<sym>[.<method>]
+	go doc [<pkg>.]<sym>[.<method>]
+	go doc [<pkg>.][<sym>.]<method>
 
-The first item in this list matched by the argument is the one whose
-documentation is printed. (See the examples below.) For packages, the order of
-scanning is determined lexically, but the GOROOT tree is always scanned before
-GOPATH.
+The first item in this list matched by the argument is the one whose documentation
+is printed. (See the examples below.) However, if the argument starts with a capital
+letter it is assumed to identify a symbol or method in the current directory.
+
+For packages, the order of scanning is determined lexically in breadth-first order.
+That is, the package presented is the one that matches the search and is nearest
+the root and lexically first at its level of the hierarchy.  The GOROOT tree is
+always scanned in its entirety before GOPATH.
 
 If there is no package specified or matched, the package in the current
 directory is selected, so "go doc Foo" shows the documentation for symbol Foo in
@@ -278,6 +289,14 @@ Examples:
 	go doc text/template new # Two arguments
 		Show documentation for text/template's New function.
 
+	At least in the current tree, these invocations all print the
+	documentation for json.Decoder's Decode method:
+
+	go doc json.Decoder.Decode
+	go doc json.decoder.decode
+	go doc json.decode
+	cd go/src/encoding/json; go doc decode
+
 Flags:
 	-c
 		Respect case when matching symbols.
@@ -344,7 +363,7 @@ Generate Go files by processing source
 
 Usage:
 
-	go generate [-run regexp] [file.go... | packages]
+	go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]
 
 Generate runs commands described by directives within existing
 files. Those commands can run any process but the intent is to
@@ -436,12 +455,14 @@ Go generate accepts one specific flag:
 		any trailing spaces and final newline) matches the
 		expression.
 
-It also accepts the standard build flags -v, -n, and -x.
+It also accepts the standard build flags including -v, -n, and -x.
 The -v flag prints the names of packages and files as they are
 processed.
 The -n flag prints commands that would be executed.
 The -x flag prints commands as they are executed.
 
+For more about build flags, see 'go help build'.
+
 For more about specifying packages, see 'go help packages'.
 
 
@@ -477,16 +498,22 @@ missing packages but does not use it to look for updates to existing packages.
 
 Get also accepts build flags to control the installation. See 'go help build'.
 
+When checking out a new package, get creates the target directory
+GOPATH/src/<import-path>. If the GOPATH contains multiple entries,
+get uses the first one. See 'go help gopath'.
+
 When checking out or updating a package, get looks for a branch or tag
 that matches the locally installed version of Go. The most important
 rule is that if the local installation is running version "go1", get
 searches for a branch or tag named "go1". If no such version exists it
 retrieves the most recent version of the package.
 
-If the vendoring experiment is enabled (see 'go help gopath'),
-then when go get checks out or updates a Git repository,
+Unless vendoring support is disabled (see 'go help gopath'),
+when go get checks out or updates a Git repository,
 it also updates any git submodules referenced by the repository.
 
+Get never checks out or updates code stored in vendor directories.
+
 For more about specifying packages, see 'go help packages'.
 
 For more about how 'go get' finds source code to
@@ -577,6 +604,14 @@ syntax of package template.  The default output is equivalent to -f
         XTestImports []string // imports from XTestGoFiles
     }
 
+The error information, if any, is
+
+    type PackageError struct {
+        ImportStack   []string // shortest path from package named on command line to this one
+        Pos           string   // position of error (if present, file:line:col)
+        Err           string   // the error itself
+    }
+
 The template function "join" calls strings.Join.
 
 The template function "context" returns the build context, defined as:
@@ -643,7 +678,7 @@ Test packages
 
 Usage:
 
-	go test [-c] [-i] [build and test flags] [packages] [flags for test binary]
+	go test [build/test flags] [packages] [build/test flags & test binary flags]
 
 'Go test' automates testing the packages named by the import paths.
 It prints a summary of the test results in the format:
@@ -673,10 +708,16 @@ non-test installation.
 
 In addition to the build flags, the flags handled by 'go test' itself are:
 
+	-args
+	    Pass the remainder of the command line (everything after -args)
+	    to the test binary, uninterpreted and unchanged.
+	    Because this flag consumes the remainder of the command line,
+	    the package list (if present) must appear before this flag.
+
 	-c
-		Compile the test binary to pkg.test but do not run it
-		(where pkg is the last element of the package's import path).
-		The file name can be changed with the -o flag.
+	    Compile the test binary to pkg.test but do not run it
+	    (where pkg is the last element of the package's import path).
+	    The file name can be changed with the -o flag.
 
 	-exec xprog
 	    Run the test binary using xprog. The behavior is the same as
@@ -687,17 +728,12 @@ In addition to the build flags, the flags handled by 'go test' itself are:
 	    Do not run the test.
 
 	-o file
-		Compile the test binary to the named file.
-		The test still runs (unless -c or -i is specified).
+	    Compile the test binary to the named file.
+	    The test still runs (unless -c or -i is specified).
 
 The test binary also accepts flags that control execution of the test; these
 flags are also accessible by 'go test'. See 'go help testflag' for details.
 
-If the test binary needs any other flags, they should be presented after the
-package names. The go tool treats as a flag the first argument that begins with
-a minus sign that it does not recognize itself; that argument and all subsequent
-arguments are passed as arguments to the test binary.
-
 For more about build flags, see 'go help build'.
 For more about specifying packages, see 'go help packages'.
 
@@ -804,6 +840,11 @@ are:
 		Build the listed main packages and everything they import into
 		executables. Packages not named main are ignored.
 
+	-buildmode=pie
+		Build the listed main packages and everything they import into
+		position independent executables (PIE). Packages not named
+		main are ignored.
+
 
 File types
 
@@ -875,7 +916,7 @@ DIR/bin/quux, not DIR/bin/foo/quux.  The "foo/" prefix is stripped
 so that you can add DIR/bin to your PATH to get at the
 installed commands.  If the GOBIN environment variable is
 set, commands are installed to the directory it names instead
-of DIR/bin.
+of DIR/bin. GOBIN must be an absolute path.
 
 Here's an example directory layout:
 
@@ -933,13 +974,10 @@ See https://golang.org/s/go14internal for details.
 
 Vendor Directories
 
-Go 1.5 includes experimental support for using local copies
-of external dependencies to satisfy imports of those dependencies,
-often referred to as vendoring. Setting the environment variable
-GO15VENDOREXPERIMENT=1 enables that experimental support.
+Go 1.6 includes support for using local copies of external dependencies
+to satisfy imports of those dependencies, often referred to as vendoring.
 
-When the vendor experiment is enabled,
-code below a directory named "vendor" is importable only
+Code below a directory named "vendor" is importable only
 by code in the directory tree rooted at the parent of "vendor",
 and only using an import path that omits the prefix up to and
 including the vendor element.
@@ -977,12 +1015,18 @@ top-level "crash/bang".
 Code in vendor directories is not subject to import path
 checking (see 'go help importpath').
 
-When the vendor experiment is enabled, 'go get' checks out
-submodules when checking out or updating a git repository
-(see 'go help get').
+When 'go get' checks out or updates a git repository, it now also
+updates submodules.
+
+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.
 
-The vendoring semantics are an experiment, and they may change
-in future releases. Once settled, they will be on by default.
+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.
 
@@ -1051,7 +1095,7 @@ Special-purpose environment variables:
 		File names in stack traces are rewritten from GOROOT to
 		GOROOT_FINAL.
 	GO15VENDOREXPERIMENT
-		Set to 1 to enable the Go 1.5 vendoring experiment.
+		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.
@@ -1227,10 +1271,10 @@ unless it is being referred to by that import path. In this way, import comments
 let package authors make sure the custom import path is used and not a
 direct path to the underlying code hosting site.
 
-If the vendoring experiment is enabled (see 'go help gopath'),
-then import path checking is disabled for code found within vendor trees.
-This makes it possible to copy code into alternate locations in vendor trees
-without needing to update import comments.
+If vendoring is enabled (see 'go help gopath'), then import path checking is
+disabled for code found within vendor trees. This makes it possible to copy
+code into alternate locations in vendor trees without needing to update import
+comments.
 
 See https://golang.org/s/go14customimport for details.
 
@@ -1286,6 +1330,14 @@ internally at Google all begin with 'google', and paths
 denoting remote repositories begin with the path to the code,
 such as 'github.com/user/repo'.
 
+Packages in a program need not have unique package names,
+but there are two reserved package names with special meaning.
+The name main indicates a command, not a library.
+Commands are built into binaries and cannot be imported.
+The name documentation indicates documentation for
+a non-Go program in the directory. Files in package documentation
+are ignored by the go command.
+
 As a special case, if the package list is a list of .go files from a
 single directory, the command is applied to a single synthesized
 package made up of exactly those files, ignoring any build constraints
@@ -1391,6 +1443,10 @@ control the execution of any test:
 	    Allow parallel execution of test functions that call t.Parallel.
 	    The value of this flag is the maximum number of tests to run
 	    simultaneously; by default, it is set to the value of GOMAXPROCS.
+	    Note that -parallel only applies within a single test binary.
+	    The 'go test' command may run tests for different packages
+	    in parallel as well, according to the setting of the -p flag
+	    (see 'go help build').
 
 	-run regexp
 	    Run only those tests and examples matching the regular
@@ -1414,25 +1470,63 @@ control the execution of any test:
 	    Verbose output: log all tests as they are run. Also print all
 	    text from Log and Logf calls even if the test succeeds.
 
-The test binary, called pkg.test where pkg is the name of the
-directory containing the package sources, can be invoked directly
-after building it with 'go test -c'. When invoking the test binary
-directly, each of the standard flag names must be prefixed with 'test.',
-as in -test.run=TestMyFunc or -test.v.
+Each of these flags is also recognized with an optional 'test.' prefix,
+as in -test.v. When invoking the generated test binary (the result of
+'go test -c') directly, however, the prefix is mandatory.
+
+The 'go test' command rewrites or removes recognized flags,
+as appropriate, both before and after the optional package list,
+before invoking the test binary.
 
-When running 'go test', flags not listed above are passed through
-unaltered. For instance, the command
+For instance, the command
 
-	go test -x -v -cpuprofile=prof.out -dir=testdata -update
+	go test -v -myflag testdata -cpuprofile=prof.out -x
 
 will compile the test binary and then run it as
 
-	pkg.test -test.v -test.cpuprofile=prof.out -dir=testdata -update
+	pkg.test -test.v -myflag testdata -test.cpuprofile=prof.out
+
+(The -x flag is removed because it applies only to the go command's
+execution, not to the test itself.)
 
 The test flags that generate profiles (other than for coverage) also
 leave the test binary in pkg.test for use when analyzing the profiles.
 
-Flags not recognized by 'go test' must be placed after any specified packages.
+When 'go test' runs a test binary, it does so from within the
+corresponding package's source code directory. Depending on the test,
+it may be necessary to do the same when invoking a generated test
+binary directly.
+
+The command-line package list, if present, must appear before any
+flag not known to the go test command. Continuing the example above,
+the package list would have to appear before -myflag, but could appear
+on either side of -v.
+
+To keep an argument for a test binary from being interpreted as a
+known flag or a package name, use -args (see 'go help test') which
+passes the remainder of the command line through to the test binary
+uninterpreted and unaltered.
+
+For instance, the command
+
+	go test -v -args -x -v
+
+will compile the test binary and then run it as
+
+	pkg.test -test.v -x -v
+
+Similarly,
+
+	go test -args math
+
+will compile the test binary and then run it as
+
+	pkg.test math
+
+In the first example, the -x and the second -v are passed through to the
+test binary unchanged and with no effect on the go command itself.
+In the second example, the argument math is passed through to the test
+binary, instead of being interpreted as the package list.
 
 
 Description of testing functions
diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go
index 0b14725..f2a2a60 100644
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -63,12 +63,17 @@ and test commands:
 	-n
 		print the commands but do not run them.
 	-p n
-		the number of builds that can be run in parallel.
+		the number of programs, such as build commands or
+		test binaries, that can be run in parallel.
 		The default is the number of CPUs available, except
 		on darwin/arm which defaults to 1.
 	-race
 		enable data race detection.
 		Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
+	-msan
+		enable interoperation with memory sanitizer.
+		Supported only on linux/amd64,
+		and only with Clang/LLVM as the host C compiler.
 	-v
 		print the names of packages as they are compiled.
 	-work
@@ -91,13 +96,14 @@ and test commands:
 		a suffix to use in the name of the package installation directory,
 		in order to keep output separate from default builds.
 		If using the -race flag, the install suffix is automatically set to race
-		or, if set explicitly, has _race appended to it.  Using a -buildmode
-		option that requires non-default compile flags has a similar effect.
+		or, if set explicitly, has _race appended to it.  Likewise for the -msan
+		flag.  Using a -buildmode option that requires non-default compile flags
+		has a similar effect.
 	-ldflags 'flag list'
 		arguments to pass on each go tool link invocation.
 	-linkshared
 		link against shared libraries previously created with
-		-buildmode=shared
+		-buildmode=shared.
 	-pkgdir dir
 		install and load all packages from dir instead of the usual locations.
 		For example, when building with a non-standard configuration,
@@ -166,6 +172,7 @@ var buildGcflags []string    // -gcflags flag
 var buildLdflags []string    // -ldflags flag
 var buildGccgoflags []string // -gccgoflags flag
 var buildRace bool           // -race flag
+var buildMSan bool           // -msan flag
 var buildToolExec []string   // -toolexec flag
 var buildBuildmode string    // -buildmode flag
 var buildLinkshared bool     // -linkshared flag
@@ -225,6 +232,7 @@ func addBuildFlags(cmd *Command) {
 	cmd.Flag.BoolVar(&buildLinkshared, "linkshared", false, "")
 	cmd.Flag.StringVar(&buildPkgdir, "pkgdir", "", "")
 	cmd.Flag.BoolVar(&buildRace, "race", false, "")
+	cmd.Flag.BoolVar(&buildMSan, "msan", false, "")
 	cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "")
 	cmd.Flag.Var((*stringsFlag)(&buildToolExec), "toolexec", "")
 	cmd.Flag.BoolVar(&buildWork, "work", false, "")
@@ -344,29 +352,46 @@ func buildModeInit() {
 			codegenArg = "-fPIC"
 		} else {
 			switch platform {
-			case "linux/amd64":
+			case "linux/amd64", "linux/arm", "linux/arm64", "linux/386",
+				"android/amd64", "android/arm", "android/arm64", "android/386":
 				codegenArg = "-shared"
-			case "linux/arm":
-				buildAsmflags = append(buildAsmflags, "-shared")
-			case "darwin/amd64":
-			case "android/arm":
+			case "darwin/amd64", "darwin/386":
 			default:
 				fatalf("-buildmode=c-shared not supported on %s\n", platform)
 			}
 		}
 		ldBuildmode = "c-shared"
 	case "default":
-		ldBuildmode = "exe"
+		switch platform {
+		case "android/arm", "android/arm64", "android/amd64", "android/386":
+			codegenArg = "-shared"
+			ldBuildmode = "pie"
+		default:
+			ldBuildmode = "exe"
+		}
 	case "exe":
 		pkgsFilter = pkgsMain
 		ldBuildmode = "exe"
+	case "pie":
+		if gccgo {
+			fatalf("-buildmode=pie not supported by gccgo")
+		} else {
+			switch platform {
+			case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le",
+				"android/amd64", "android/arm", "android/arm64", "android/386":
+				codegenArg = "-shared"
+			default:
+				fatalf("-buildmode=pie not supported on %s\n", platform)
+			}
+		}
+		ldBuildmode = "pie"
 	case "shared":
 		pkgsFilter = pkgsNotMain
 		if gccgo {
 			codegenArg = "-fPIC"
 		} else {
 			switch platform {
-			case "linux/amd64":
+			case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le":
 			default:
 				fatalf("-buildmode=shared not supported on %s\n", platform)
 			}
@@ -383,9 +408,11 @@ func buildModeInit() {
 		if gccgo {
 			codegenArg = "-fPIC"
 		} else {
-			if platform != "linux/amd64" {
-				fmt.Fprintf(os.Stderr, "go %s: -linkshared is only supported on linux/amd64\n", flag.Args()[0])
-				os.Exit(2)
+			switch platform {
+			case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le":
+				buildAsmflags = append(buildAsmflags, "-D=GOBUILDMODE_shared=1")
+			default:
+				fatalf("-linkshared not supported on %s\n", platform)
 			}
 			codegenArg = "-dynlink"
 			// TODO(mwhudson): remove -w when that gets fixed in linker.
@@ -407,7 +434,7 @@ func buildModeInit() {
 }
 
 func runBuild(cmd *Command, args []string) {
-	raceInit()
+	instrumentInit()
 	buildModeInit()
 	var b builder
 	b.init()
@@ -455,7 +482,12 @@ func runBuild(cmd *Command, args []string) {
 
 	var a *action
 	if buildBuildmode == "shared" {
-		a = b.libaction(libname(args), pkgsFilter(packages(args)), modeBuild, depMode)
+		pkgs := pkgsFilter(packages(args))
+		if libName, err := libname(args, pkgs); err != nil {
+			fatalf("%s", err.Error())
+		} else {
+			a = b.libaction(libName, pkgs, modeBuild, depMode)
+		}
 	} else {
 		a = &action{}
 		for _, p := range pkgsFilter(packages(args)) {
@@ -479,32 +511,73 @@ See also: go build, go get, go clean.
 	`,
 }
 
+// isMetaPackage checks if name is a reserved package name that expands to multiple packages
+func isMetaPackage(name string) bool {
+	return name == "std" || name == "cmd" || name == "all"
+}
+
 // libname returns the filename to use for the shared library when using
 // -buildmode=shared.  The rules we use are:
-//  1) Drop any trailing "/..."s if present
-//  2) Change / to -
-//  3) Join arguments with ,
-// So std -> libstd.so
-//    a b/... -> liba,b.so
-//    gopkg.in/tomb.v2 -> libgopkg.in-tomb.v2.so
-func libname(args []string) string {
+// Use arguments for special 'meta' packages:
+//	std --> libstd.so
+//	std cmd --> libstd,cmd.so
+// A single non-meta argument with trailing "/..." is special cased:
+//	foo/... --> libfoo.so
+//	(A relative path like "./..."  expands the "." first)
+// Use import paths for other cases, changing '/' to '-':
+//	somelib --> libsubdir-somelib.so
+//	./ or ../ --> libsubdir-somelib.so
+//	gopkg.in/tomb.v2 -> libgopkg.in-tomb.v2.so
+//	a/... b/... ---> liba/c,b/d.so - all matching import paths
+// Name parts are joined with ','.
+func libname(args []string, pkgs []*Package) (string, error) {
 	var libname string
-	for _, arg := range args {
-		arg = strings.TrimSuffix(arg, "/...")
-		arg = strings.Replace(arg, "/", "-", -1)
+	appendName := func(arg string) {
 		if libname == "" {
 			libname = arg
 		} else {
 			libname += "," + arg
 		}
 	}
+	var haveNonMeta bool
+	for _, arg := range args {
+		if isMetaPackage(arg) {
+			appendName(arg)
+		} else {
+			haveNonMeta = true
+		}
+	}
+	if len(libname) == 0 { // non-meta packages only. use import paths
+		if len(args) == 1 && strings.HasSuffix(args[0], "/...") {
+			// Special case of "foo/..." as mentioned above.
+			arg := strings.TrimSuffix(args[0], "/...")
+			if build.IsLocalImport(arg) {
+				cwd, _ := os.Getwd()
+				bp, _ := buildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly)
+				if bp.ImportPath != "" && bp.ImportPath != "." {
+					arg = bp.ImportPath
+				}
+			}
+			appendName(strings.Replace(arg, "/", "-", -1))
+		} else {
+			for _, pkg := range pkgs {
+				appendName(strings.Replace(pkg.ImportPath, "/", "-", -1))
+			}
+		}
+	} else if haveNonMeta { // have both meta package and a non-meta one
+		return "", errors.New("mixing of meta and non-meta packages is not allowed")
+	}
 	// TODO(mwhudson): Needs to change for platforms that use different naming
 	// conventions...
-	return "lib" + libname + ".so"
+	return "lib" + libname + ".so", nil
 }
 
 func runInstall(cmd *Command, args []string) {
-	raceInit()
+	if gobin != "" && !filepath.IsAbs(gobin) {
+		fatalf("cannot install, GOBIN must be an absolute path")
+	}
+
+	instrumentInit()
 	buildModeInit()
 	pkgs := pkgsFilter(packagesForBuild(args))
 
@@ -529,7 +602,11 @@ func runInstall(cmd *Command, args []string) {
 	b.init()
 	var a *action
 	if buildBuildmode == "shared" {
-		a = b.libaction(libname(args), pkgs, modeInstall, modeInstall)
+		if libName, err := libname(args, pkgs); err != nil {
+			fatalf("%s", err.Error())
+		} else {
+			a = b.libaction(libName, pkgs, modeInstall, modeInstall)
+		}
 	} else {
 		a = &action{}
 		var tools []*action
@@ -590,6 +667,7 @@ var (
 	goarch    string
 	goos      string
 	exeSuffix string
+	gopath    []string
 )
 
 func init() {
@@ -598,6 +676,7 @@ func init() {
 	if goos == "windows" {
 		exeSuffix = ".exe"
 	}
+	gopath = filepath.SplitList(buildContext.GOPATH)
 }
 
 // A builder holds global state about a build.
@@ -746,7 +825,9 @@ func goFilesPackage(gofiles []string) *Package {
 	pkg := new(Package)
 	pkg.local = true
 	pkg.cmdline = true
+	stk.push("main")
 	pkg.load(&stk, bp, err)
+	stk.pop()
 	pkg.localPrefix = dirToImportPath(dir)
 	pkg.ImportPath = "command-line-arguments"
 	pkg.target = ""
@@ -804,15 +885,17 @@ func readpkglist(shlibpath string) (pkgs []*Package) {
 
 // action returns the action for applying the given operation (mode) to the package.
 // depMode is the action to use when building dependencies.
-// action never looks for p in a shared library.
+// action never looks for p in a shared library, but may find p's dependencies in a
+// shared library if buildLinkshared is true.
 func (b *builder) action(mode buildMode, depMode buildMode, p *Package) *action {
-	return b.action1(mode, depMode, p, false)
+	return b.action1(mode, depMode, p, false, "")
 }
 
 // action1 returns the action for applying the given operation (mode) to the package.
 // depMode is the action to use when building dependencies.
 // action1 will look for p in a shared library if lookshared is true.
-func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, lookshared bool) *action {
+// forShlib is the shared library that p will become part of, if any.
+func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, lookshared bool, forShlib string) *action {
 	shlib := ""
 	if lookshared {
 		shlib = p.Shlib
@@ -844,13 +927,23 @@ func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, looksha
 	b.actionCache[key] = a
 
 	for _, p1 := range p.imports {
-		ls := buildLinkshared
-		// If p1 is part of the same shared library as p, we need the action
-		// that builds p here, not the shared libary or we get action loops.
-		if p1.Shlib == p.Shlib {
-			ls = false
+		if forShlib != "" {
+			// p is part of a shared library.
+			if p1.Shlib != "" && p1.Shlib != forShlib {
+				// p1 is explicitly part of a different shared library.
+				// Put the action for that shared library into a.deps.
+				a.deps = append(a.deps, b.action1(depMode, depMode, p1, true, p1.Shlib))
+			} else {
+				// p1 is (implicitly or not) part of this shared library.
+				// Put the action for p1 into a.deps.
+				a.deps = append(a.deps, b.action1(depMode, depMode, p1, false, forShlib))
+			}
+		} else {
+			// p is not part of a shared library.
+			// If p1 is in a shared library, put the action for that into
+			// a.deps, otherwise put the action for p1 into a.deps.
+			a.deps = append(a.deps, b.action1(depMode, depMode, p1, buildLinkshared, p1.Shlib))
 		}
-		a.deps = append(a.deps, b.action1(depMode, depMode, p1, ls))
 	}
 
 	// If we are not doing a cross-build, then record the binary we'll
@@ -858,7 +951,7 @@ func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, looksha
 	// using cgo, to make sure we do not overwrite the binary while
 	// a package is using it.  If this is a cross-build, then the cgo we
 	// are writing is not the cgo we need to use.
-	if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace {
+	if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace && !buildMSan {
 		if (len(p.CgoFiles) > 0 || p.Standard && p.ImportPath == "runtime/cgo") && !buildLinkshared && buildBuildmode != "shared" {
 			var stk importStack
 			p1 := loadPackage("cmd/cgo", &stk)
@@ -906,18 +999,27 @@ func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, looksha
 	switch mode {
 	case modeInstall:
 		a.f = (*builder).install
-		a.deps = []*action{b.action1(modeBuild, depMode, p, lookshared)}
+		a.deps = []*action{b.action1(modeBuild, depMode, p, lookshared, forShlib)}
 		a.target = a.p.target
 
 		// Install header for cgo in c-archive and c-shared modes.
 		if p.usesCgo() && (buildBuildmode == "c-archive" || buildBuildmode == "c-shared") {
+			hdrTarget := a.target[:len(a.target)-len(filepath.Ext(a.target))] + ".h"
+			if buildContext.Compiler == "gccgo" {
+				// For the header file, remove the "lib"
+				// added by go/build, so we generate pkg.h
+				// rather than libpkg.h.
+				dir, file := filepath.Split(hdrTarget)
+				file = strings.TrimPrefix(file, "lib")
+				hdrTarget = filepath.Join(dir, file)
+			}
 			ah := &action{
 				p:      a.p,
 				deps:   []*action{a.deps[0]},
 				f:      (*builder).installHeader,
 				pkgdir: a.pkgdir,
 				objdir: a.objdir,
-				target: a.target[:len(a.target)-len(filepath.Ext(a.target))] + ".h",
+				target: hdrTarget,
 			}
 			a.deps = append(a.deps, ah)
 		}
@@ -953,7 +1055,11 @@ func (b *builder) action1(mode buildMode, depMode buildMode, p *Package, looksha
 
 func (b *builder) libaction(libname string, pkgs []*Package, mode, depMode buildMode) *action {
 	a := &action{}
-	if mode == modeBuild {
+	switch mode {
+	default:
+		fatalf("unrecognized mode %v", mode)
+
+	case modeBuild:
 		a.f = (*builder).linkShared
 		a.target = filepath.Join(b.work, libname)
 		for _, p := range pkgs {
@@ -962,14 +1068,15 @@ func (b *builder) libaction(libname string, pkgs []*Package, mode, depMode build
 			}
 			a.deps = append(a.deps, b.action(depMode, depMode, p))
 		}
-	} else if mode == modeInstall {
+
+	case modeInstall:
 		// Currently build mode shared forces external linking mode, and
-		// external linking mode forces an import of runtime/cgo. So if it
-		// was not passed on the command line and it is not present in
-		// another shared library, add it here.
-		seencgo := false
+		// external linking mode forces an import of runtime/cgo (and
+		// math on arm). So if it was not passed on the command line and
+		// it is not present in another shared library, add it here.
 		_, gccgo := buildToolchain.(gccgoToolchain)
 		if !gccgo {
+			seencgo := false
 			for _, p := range pkgs {
 				seencgo = seencgo || (p.Standard && p.ImportPath == "runtime/cgo")
 			}
@@ -989,6 +1096,28 @@ func (b *builder) libaction(libname string, pkgs []*Package, mode, depMode build
 					pkgs = append(pkgs, p)
 				}
 			}
+			if goarch == "arm" {
+				seenmath := false
+				for _, p := range pkgs {
+					seenmath = seenmath || (p.Standard && p.ImportPath == "math")
+				}
+				if !seenmath {
+					var stk importStack
+					p := loadPackage("math", &stk)
+					if p.Error != nil {
+						fatalf("load math: %v", p.Error)
+					}
+					computeStale(p)
+					// If math is in another shared library, then that's
+					// also the shared library that contains runtime, so
+					// something will depend on it and so math's staleness
+					// will be checked when processing that library.
+					if p.Shlib == "" || p.Shlib == libname {
+						pkgs = append([]*Package{}, pkgs...)
+						pkgs = append(pkgs, p)
+					}
+				}
+			}
 		}
 
 		// Figure out where the library will go.
@@ -1021,7 +1150,7 @@ func (b *builder) libaction(libname string, pkgs []*Package, mode, depMode build
 			if err != nil || lstat.ModTime().After(built) {
 				stale = true
 			}
-			a.deps = append(a.deps, b.action(depMode, depMode, p))
+			a.deps = append(a.deps, b.action1(depMode, depMode, p, false, a.target))
 		}
 
 		if stale {
@@ -1039,8 +1168,6 @@ func (b *builder) libaction(libname string, pkgs []*Package, mode, depMode build
 				shlibnameaction.deps = append(shlibnameaction.deps, buildAction)
 			}
 		}
-	} else {
-		fatalf("unregonized mode %v", mode)
 	}
 	return a
 }
@@ -1231,17 +1358,11 @@ func (b *builder) build(a *action) (err error) {
 		// different sections of the bootstrap script have to
 		// be merged, the banners give patch something
 		// to use to find its context.
-		fmt.Printf("\n#\n# %s\n#\n\n", a.p.ImportPath)
+		b.print("\n#\n# " + a.p.ImportPath + "\n#\n\n")
 	}
 
 	if buildV {
-		fmt.Fprintf(os.Stderr, "%s\n", a.p.ImportPath)
-	}
-
-	if a.p.Standard && a.p.ImportPath == "runtime" && buildContext.Compiler == "gc" &&
-		(!hasString(a.p.GoFiles, "zgoos_"+buildContext.GOOS+".go") ||
-			!hasString(a.p.GoFiles, "zgoarch_"+buildContext.GOARCH+".go")) {
-		return fmt.Errorf("%s/%s must be bootstrapped using make%v", buildContext.GOOS, buildContext.GOARCH, defaultSuffix())
+		b.print(a.p.ImportPath + "\n")
 	}
 
 	// Make build directory.
@@ -1385,17 +1506,17 @@ func (b *builder) build(a *action) (err error) {
 		switch {
 		case strings.HasSuffix(name, _goos_goarch):
 			targ := file[:len(name)-len(_goos_goarch)] + "_GOOS_GOARCH." + ext
-			if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0644, true); err != nil {
+			if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666, true); err != nil {
 				return err
 			}
 		case strings.HasSuffix(name, _goarch):
 			targ := file[:len(name)-len(_goarch)] + "_GOARCH." + ext
-			if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0644, true); err != nil {
+			if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666, true); err != nil {
 				return err
 			}
 		case strings.HasSuffix(name, _goos):
 			targ := file[:len(name)-len(_goos)] + "_GOOS." + ext
-			if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0644, true); err != nil {
+			if err := b.copyFile(a, obj+targ, filepath.Join(a.p.Dir, file), 0666, true); err != nil {
 				return err
 			}
 		}
@@ -1484,7 +1605,7 @@ func (b *builder) getPkgConfigFlags(p *Package) (cflags, ldflags []string, err e
 
 func (b *builder) installShlibname(a *action) error {
 	a1 := a.deps[0]
-	err := ioutil.WriteFile(a.target, []byte(filepath.Base(a1.target)+"\n"), 0644)
+	err := ioutil.WriteFile(a.target, []byte(filepath.Base(a1.target)+"\n"), 0666)
 	if err != nil {
 		return err
 	}
@@ -1508,12 +1629,12 @@ func (b *builder) install(a *action) (err error) {
 		}
 	}()
 	a1 := a.deps[0]
-	perm := os.FileMode(0644)
+	perm := os.FileMode(0666)
 	if a1.link {
 		switch buildBuildmode {
 		case "c-archive", "c-shared":
 		default:
-			perm = 0755
+			perm = 0777
 		}
 	}
 
@@ -1565,6 +1686,22 @@ func (b *builder) includeArgs(flag string, all []*action) []string {
 	inc = append(inc, flag, b.work)
 
 	// Finally, look in the installed package directories for each action.
+	// First add the package dirs corresponding to GOPATH entries
+	// in the original GOPATH order.
+	need := map[string]*build.Package{}
+	for _, a1 := range all {
+		if a1.p != nil && a1.pkgdir == a1.p.build.PkgRoot {
+			need[a1.p.build.Root] = a1.p.build
+		}
+	}
+	for _, root := range gopath {
+		if p := need[root]; p != nil && !incMap[p.PkgRoot] {
+			incMap[p.PkgRoot] = true
+			inc = append(inc, flag, p.PkgTargetRoot)
+		}
+	}
+
+	// Then add anything that's left.
 	for _, a1 := range all {
 		if a1.p == nil {
 			continue
@@ -1587,7 +1724,25 @@ func (b *builder) moveOrCopyFile(a *action, dst, src string, perm os.FileMode, f
 
 	// If we can update the mode and rename to the dst, do it.
 	// Otherwise fall back to standard copy.
-	if err := os.Chmod(src, perm); err == nil {
+
+	// The perm argument is meant to be adjusted according to umask,
+	// but we don't know what the umask is.
+	// Create a dummy file to find out.
+	// This avoids build tags and works even on systems like Plan 9
+	// where the file mask computation incorporates other information.
+	mode := perm
+	f, err := os.OpenFile(filepath.Clean(dst)+"-go-tmp-umask", os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm)
+	if err == nil {
+		fi, err := f.Stat()
+		if err == nil {
+			mode = fi.Mode() & 0777
+		}
+		name := f.Name()
+		f.Close()
+		os.Remove(name)
+	}
+
+	if err := os.Chmod(src, mode); err == nil {
 		if err := os.Rename(src, dst); err == nil {
 			if buildX {
 				b.showcmd("", "mv %s %s", src, dst)
@@ -1621,7 +1776,7 @@ func (b *builder) copyFile(a *action, dst, src string, perm os.FileMode, force b
 		if fi.IsDir() {
 			return fmt.Errorf("build output %q already exists and is a directory", dst)
 		}
-		if !force && !isObject(dst) {
+		if !force && fi.Mode().IsRegular() && !isObject(dst) {
 			return fmt.Errorf("build output %q already exists and is not an object file", dst)
 		}
 	}
@@ -1633,7 +1788,7 @@ func (b *builder) copyFile(a *action, dst, src string, perm os.FileMode, force b
 		}
 	}
 
-	os.Remove(dst)
+	mayberemovefile(dst)
 	df, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm)
 	if err != nil && toolIsWindows {
 		// Windows does not allow deletion of a binary file
@@ -1652,7 +1807,7 @@ func (b *builder) copyFile(a *action, dst, src string, perm os.FileMode, force b
 	_, err = io.Copy(df, sf)
 	df.Close()
 	if err != nil {
-		os.Remove(dst)
+		mayberemovefile(dst)
 		return fmt.Errorf("copying %s to %s: %v", src, dst, err)
 	}
 	return nil
@@ -1674,7 +1829,7 @@ func (b *builder) installHeader(a *action) error {
 		}
 	}
 
-	return b.moveOrCopyFile(a, a.target, src, 0644, true)
+	return b.moveOrCopyFile(a, a.target, src, 0666, true)
 }
 
 // cover runs, in effect,
@@ -1699,6 +1854,7 @@ var objectMagic = [][]byte{
 	{0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00},      // PE (Windows) as generated by 6l/8l and gcc
 	{0x00, 0x00, 0x01, 0xEB},                  // Plan 9 i386
 	{0x00, 0x00, 0x8a, 0x97},                  // Plan 9 amd64
+	{0x00, 0x00, 0x06, 0x47},                  // Plan 9 arm
 }
 
 func isObject(s string) bool {
@@ -1717,6 +1873,16 @@ func isObject(s string) bool {
 	return false
 }
 
+// mayberemovefile removes a file only if it is a regular file
+// When running as a user with sufficient privileges, we may delete
+// even device files, for example, which is not intended.
+func mayberemovefile(s string) {
+	if fi, err := os.Lstat(s); err == nil && !fi.Mode().IsRegular() {
+		return
+	}
+	os.Remove(s)
+}
+
 // fmtcmd formats a command in the manner of fmt.Sprintf but also:
 //
 //	If dir is non-empty and the script is not in dir right now,
@@ -2095,7 +2261,7 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool,
 	if p.Name == "main" {
 		gcargs[1] = "main"
 	}
-	if p.Standard && p.ImportPath == "runtime" {
+	if p.Standard && (p.ImportPath == "runtime" || strings.HasPrefix(p.ImportPath, "runtime/internal")) {
 		// runtime compiles with a special gc flag to emit
 		// additional reflect type data.
 		gcargs = append(gcargs, "-+")
@@ -2192,33 +2358,26 @@ func (gcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []s
 	for _, f := range ofiles {
 		absOfiles = append(absOfiles, mkAbs(objDir, f))
 	}
-	cmd := "c"
 	absAfile := mkAbs(objDir, afile)
-	appending := false
-	if _, err := os.Stat(absAfile); err == nil {
-		appending = true
-		cmd = "r"
-	}
 
-	cmdline := stringList("pack", cmd, absAfile, absOfiles)
+	// The archive file should have been created by the compiler.
+	// Since it used to not work that way, verify.
+	if _, err := os.Stat(absAfile); err != nil {
+		fatalf("os.Stat of archive file failed: %v", err)
+	}
 
-	if appending {
-		if buildN || buildX {
-			b.showcmd(p.Dir, "%s # internal", joinUnambiguously(cmdline))
-		}
-		if buildN {
-			return nil
-		}
-		if err := packInternal(b, absAfile, absOfiles); err != nil {
-			b.showOutput(p.Dir, p.ImportPath, err.Error()+"\n")
-			return errPrintedOutput
-		}
+	if buildN || buildX {
+		cmdline := stringList("pack", "r", absAfile, absOfiles)
+		b.showcmd(p.Dir, "%s # internal", joinUnambiguously(cmdline))
+	}
+	if buildN {
 		return nil
 	}
-
-	// Need actual pack.
-	cmdline[0] = tool("pack")
-	return b.run(p.Dir, p.ImportPath, nil, buildToolExec, cmdline)
+	if err := packInternal(b, absAfile, absOfiles); err != nil {
+		b.showOutput(p.Dir, p.ImportPath, err.Error()+"\n")
+		return errPrintedOutput
+	}
+	return nil
 }
 
 func packInternal(b *builder, afile string, ofiles []string) error {
@@ -2429,11 +2588,11 @@ func (tools gccgoToolchain) asm(b *builder, p *Package, obj, ofile, sfile string
 	sfile = mkAbs(p.Dir, sfile)
 	defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch}
 	if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" {
-		defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`)
+		defs = append(defs, `-D`, `GOPKGPATH=`+pkgpath)
 	}
 	defs = tools.maybePIC(defs)
 	defs = append(defs, b.gccArchArgs()...)
-	return b.run(p.Dir, p.ImportPath, nil, tools.compiler(), "-I", obj, "-o", ofile, defs, sfile)
+	return b.run(p.Dir, p.ImportPath, nil, tools.compiler(), "-xassembler-with-cpp", "-I", obj, "-c", "-o", ofile, defs, sfile)
 }
 
 func (gccgoToolchain) pkgpath(basedir string, p *Package) string {
@@ -2448,7 +2607,7 @@ func (gccgoToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles
 	for _, f := range ofiles {
 		absOfiles = append(absOfiles, mkAbs(objDir, f))
 	}
-	return b.run(p.Dir, p.ImportPath, nil, "ar", "cru", mkAbs(objDir, afile), absOfiles)
+	return b.run(p.Dir, p.ImportPath, nil, "ar", "rc", mkAbs(objDir, afile), absOfiles)
 }
 
 func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions []*action, mainpkg string, ofiles []string) error {
@@ -2539,17 +2698,9 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
 		}
 	}
 
-	switch ldBuildmode {
-	case "c-archive", "c-shared":
-		ldflags = append(ldflags, "-Wl,--whole-archive")
-	}
-
+	ldflags = append(ldflags, "-Wl,--whole-archive")
 	ldflags = append(ldflags, afiles...)
-
-	switch ldBuildmode {
-	case "c-archive", "c-shared":
-		ldflags = append(ldflags, "-Wl,--no-whole-archive")
-	}
+	ldflags = append(ldflags, "-Wl,--no-whole-archive")
 
 	ldflags = append(ldflags, cgoldflags...)
 	ldflags = append(ldflags, envList("CGO_LDFLAGS", "")...)
@@ -2591,6 +2742,10 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
 		// libffi.
 		ldflags = append(ldflags, "-Wl,-r", "-nostdlib", "-Wl,--whole-archive", "-lgolibbegin", "-Wl,--no-whole-archive")
 
+		if b.gccSupportsNoPie() {
+			ldflags = append(ldflags, "-no-pie")
+		}
+
 		// We are creating an object file, so we don't want a build ID.
 		ldflags = b.disableBuildID(ldflags)
 
@@ -2598,7 +2753,7 @@ func (tools gccgoToolchain) ld(b *builder, root *action, out string, allactions
 		out = out + ".o"
 
 	case "c-shared":
-		ldflags = append(ldflags, "-shared", "-nostdlib", "-Wl,--whole-archive", "-lgolibbegin", "-Wl,--no-whole-archive", "-lgo", "-lgcc_s", "-lgcc")
+		ldflags = append(ldflags, "-shared", "-nostdlib", "-Wl,--whole-archive", "-lgolibbegin", "-Wl,--no-whole-archive", "-lgo", "-lgcc_s", "-lgcc", "-lc", "-lgcc")
 
 	default:
 		fatalf("-buildmode=%s not supported for gccgo", ldBuildmode)
@@ -2696,43 +2851,6 @@ func gccgoCleanPkgpath(p *Package) string {
 	return strings.Map(clean, gccgoPkgpath(p))
 }
 
-// libgcc returns the filename for libgcc, as determined by invoking gcc with
-// the -print-libgcc-file-name option.
-func (b *builder) libgcc(p *Package) (string, error) {
-	var buf bytes.Buffer
-
-	gccCmd := b.gccCmd(p.Dir)
-
-	prev := b.print
-	if buildN {
-		// In -n mode we temporarily swap out the builder's
-		// print function to capture the command-line. This
-		// let's us assign it to $LIBGCC and produce a valid
-		// buildscript for cgo packages.
-		b.print = func(a ...interface{}) (int, error) {
-			return fmt.Fprint(&buf, a...)
-		}
-	}
-	f, err := b.runOut(p.Dir, p.ImportPath, nil, gccCmd, "-print-libgcc-file-name")
-	if err != nil {
-		return "", fmt.Errorf("gcc -print-libgcc-file-name: %v (%s)", err, f)
-	}
-	if buildN {
-		s := fmt.Sprintf("LIBGCC=$(%s)\n", buf.Next(buf.Len()-1))
-		b.print = prev
-		b.print(s)
-		return "$LIBGCC", nil
-	}
-
-	// The compiler might not be able to find libgcc, and in that case,
-	// it will simply return "libgcc.a", which is of no use to us.
-	if !filepath.IsAbs(string(f)) {
-		return "", nil
-	}
-
-	return strings.Trim(string(f), "\r\n"), nil
-}
-
 // gcc runs the gcc C compiler to create an object from a single C file.
 func (b *builder) gcc(p *Package, out string, flags []string, cfile string) error {
 	return b.ccompile(p, out, flags, cfile, b.gccCmd(p.Dir))
@@ -2819,6 +2937,36 @@ func (b *builder) ccompilerCmd(envvar, defcmd, objdir string) []string {
 	return a
 }
 
+// On systems with PIE (position independent executables) enabled by default,
+// -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
+	}
+	src := filepath.Join(b.work, "trivial.c")
+	if err := ioutil.WriteFile(src, []byte{}, 0666); err != nil {
+		return false
+	}
+	cmdArgs := b.gccCmd(b.work)
+	cmdArgs = append(cmdArgs, "-no-pie", "-c", "trivial.c")
+	if buildN || buildX {
+		b.showcmd(b.work, "%s", joinUnambiguously(cmdArgs))
+		if buildN {
+			return false
+		}
+	}
+	cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
+	cmd.Dir = b.work
+	cmd.Env = envForDir(cmd.Dir, os.Environ())
+	out, err := cmd.CombinedOutput()
+	return err == nil && !bytes.Contains(out, []byte("unrecognized"))
+}
+
 // gccArchArgs returns arguments to pass to gcc based on the architecture.
 func (b *builder) gccArchArgs() []string {
 	switch goarch {
@@ -2858,12 +3006,6 @@ func (b *builder) cflags(p *Package, def bool) (cppflags, cflags, cxxflags, ldfl
 
 var cgoRe = regexp.MustCompile(`[/\\:]`)
 
-var (
-	cgoLibGccFile     string
-	cgoLibGccErr      error
-	cgoLibGccFileOnce sync.Once
-)
-
 func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofiles, gccfiles, gxxfiles, mfiles []string) (outGo, outObj []string, err error) {
 	cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoLDFLAGS := b.cflags(p, true)
 	_, cgoexeCFLAGS, _, _ := b.cflags(p, false)
@@ -2874,11 +3016,16 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofi
 		cgoLDFLAGS = append(cgoLDFLAGS, "-lobjc")
 	}
 
+	if buildMSan && p.ImportPath != "runtime/cgo" {
+		cgoCFLAGS = append([]string{"-fsanitize=memory"}, cgoCFLAGS...)
+		cgoLDFLAGS = append([]string{"-fsanitize=memory"}, cgoLDFLAGS...)
+	}
+
 	// Allows including _cgo_export.h from .[ch] files in the package.
 	cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", obj)
 
 	// cgo
-	// TODO: CGOPKGPATH, CGO_FLAGS?
+	// TODO: CGO_FLAGS?
 	gofiles := []string{obj + "_cgo_gotypes.go"}
 	cfiles := []string{"_cgo_main.c", "_cgo_export.c"}
 	for _, fn := range cgofiles {
@@ -2894,7 +3041,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofi
 	if p.Standard && p.ImportPath == "runtime/cgo" {
 		cgoflags = append(cgoflags, "-import_runtime_cgo=false")
 	}
-	if p.Standard && (p.ImportPath == "runtime/race" || p.ImportPath == "runtime/cgo") {
+	if p.Standard && (p.ImportPath == "runtime/race" || p.ImportPath == "runtime/msan" || p.ImportPath == "runtime/cgo") {
 		cgoflags = append(cgoflags, "-import_syscall=false")
 	}
 
@@ -2946,7 +3093,9 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofi
 	var linkobj []string
 
 	var bareLDFLAGS []string
-	// filter out -lsomelib, -l somelib, *.{so,dll,dylib}, and (on Darwin) -framework X
+	// When linking relocatable objects, various flags need to be
+	// filtered out as they are inapplicable and can cause some linkers
+	// to fail.
 	for i := 0; i < len(cgoLDFLAGS); i++ {
 		f := cgoLDFLAGS[i]
 		switch {
@@ -2962,7 +3111,6 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofi
 		case strings.HasSuffix(f, ".dylib"),
 			strings.HasSuffix(f, ".so"),
 			strings.HasSuffix(f, ".dll"):
-			continue
 		// Remove any -fsanitize=foo flags.
 		// Otherwise the compiler driver thinks that we are doing final link
 		// and links sanitizer runtime into the object file. But we are not doing
@@ -2971,27 +3119,27 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofi
 		// See issue 8788 for details.
 		case strings.HasPrefix(f, "-fsanitize="):
 			continue
+		// runpath flags not applicable unless building a shared
+		// object or executable; see issue 12115 for details.  This
+		// is necessary as Go currently does not offer a way to
+		// specify the set of LDFLAGS that only apply to shared
+		// objects.
+		case strings.HasPrefix(f, "-Wl,-rpath"):
+			if f == "-Wl,-rpath" || f == "-Wl,-rpath-link" {
+				// Skip following argument to -rpath* too.
+				i++
+			}
 		default:
 			bareLDFLAGS = append(bareLDFLAGS, f)
 		}
 	}
 
-	cgoLibGccFileOnce.Do(func() {
-		cgoLibGccFile, cgoLibGccErr = b.libgcc(p)
-	})
-	if cgoLibGccFile == "" && cgoLibGccErr != nil {
-		return nil, nil, err
-	}
-
 	var staticLibs []string
 	if goos == "windows" {
-		// libmingw32 and libmingwex might also use libgcc, so libgcc must come last,
-		// and they also have some inter-dependencies, so must use linker groups.
+		// libmingw32 and libmingwex have some inter-dependencies,
+		// so must use linker groups.
 		staticLibs = []string{"-Wl,--start-group", "-lmingwex", "-lmingw32", "-Wl,--end-group"}
 	}
-	if cgoLibGccFile != "" {
-		staticLibs = append(staticLibs, cgoLibGccFile)
-	}
 
 	cflags := stringList(cgoCPPFLAGS, cgoCFLAGS)
 	for _, cfile := range cfiles {
@@ -3037,7 +3185,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofi
 
 	linkobj = append(linkobj, p.SysoFiles...)
 	dynobj := obj + "_cgo_.o"
-	pie := goarch == "arm" && (goos == "linux" || goos == "android")
+	pie := (goarch == "arm" && goos == "linux") || goos == "android"
 	if pie { // we need to use -pie for Linux/ARM to get accurate imported sym
 		cgoLDFLAGS = append(cgoLDFLAGS, "-pie")
 	}
@@ -3075,6 +3223,10 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofi
 	}
 	ldflags := stringList(bareLDFLAGS, "-Wl,-r", "-nostdlib", staticLibs)
 
+	if b.gccSupportsNoPie() {
+		ldflags = append(ldflags, "-no-pie")
+	}
+
 	// We are creating an object file, so we don't want a build ID.
 	ldflags = b.disableBuildID(ldflags)
 
@@ -3209,7 +3361,7 @@ func (b *builder) swigIntSize(obj string) (intsize string, err error) {
 		return "$INTBITS", nil
 	}
 	src := filepath.Join(b.work, "swig_intsize.go")
-	if err = ioutil.WriteFile(src, []byte(swigIntSizeCode), 0644); err != nil {
+	if err = ioutil.WriteFile(src, []byte(swigIntSizeCode), 0666); err != nil {
 		return
 	}
 	srcs := []string{src}
@@ -3331,32 +3483,38 @@ func (q *actionQueue) pop() *action {
 	return heap.Pop(q).(*action)
 }
 
-func raceInit() {
-	if !buildRace {
+func instrumentInit() {
+	if !buildRace && !buildMSan {
 		return
 	}
+	if buildRace && buildMSan {
+		fmt.Fprintf(os.Stderr, "go %s: may not use -race and -msan simultaneously", flag.Args()[0])
+		os.Exit(2)
+	}
 	if goarch != "amd64" || goos != "linux" && goos != "freebsd" && goos != "darwin" && goos != "windows" {
-		fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
+		fmt.Fprintf(os.Stderr, "go %s: -race and -msan are only supported on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
+		os.Exit(2)
+	}
+	if !buildContext.CgoEnabled {
+		fmt.Fprintf(os.Stderr, "go %s: -race requires cgo; enable cgo by setting CGO_ENABLED=1\n", flag.Args()[0])
 		os.Exit(2)
 	}
-	buildGcflags = append(buildGcflags, "-race")
-	buildLdflags = append(buildLdflags, "-race")
+	if buildRace {
+		buildGcflags = append(buildGcflags, "-race")
+		buildLdflags = append(buildLdflags, "-race")
+	} else {
+		buildGcflags = append(buildGcflags, "-msan")
+		buildLdflags = append(buildLdflags, "-msan")
+	}
 	if buildContext.InstallSuffix != "" {
 		buildContext.InstallSuffix += "_"
 	}
-	buildContext.InstallSuffix += "race"
-	buildContext.BuildTags = append(buildContext.BuildTags, "race")
-}
 
-// defaultSuffix returns file extension used for command files in
-// current os environment.
-func defaultSuffix() string {
-	switch runtime.GOOS {
-	case "windows":
-		return ".bat"
-	case "plan9":
-		return ".rc"
-	default:
-		return ".bash"
+	if buildRace {
+		buildContext.InstallSuffix += "race"
+		buildContext.BuildTags = append(buildContext.BuildTags, "race")
+	} else {
+		buildContext.InstallSuffix += "msan"
+		buildContext.BuildTags = append(buildContext.BuildTags, "msan")
 	}
 }
diff --git a/src/cmd/go/discovery.go b/src/cmd/go/discovery.go
index b9f4279..f6992e9 100644
--- a/src/cmd/go/discovery.go
+++ b/src/cmd/go/discovery.go
@@ -41,9 +41,9 @@ func parseMetaGoImports(r io.Reader) (imports []metaImport, err error) {
 	d.Strict = false
 	var t xml.Token
 	for {
-		t, err = d.Token()
+		t, err = d.RawToken()
 		if err != nil {
-			if err == io.EOF {
+			if err == io.EOF || len(imports) > 0 {
 				err = nil
 			}
 			return
diff --git a/src/cmd/go/doc.go b/src/cmd/go/doc.go
index 4a07dfe..9b8b8df 100644
--- a/src/cmd/go/doc.go
+++ b/src/cmd/go/doc.go
@@ -32,12 +32,17 @@ which is schematically one of these:
 
 	go doc <pkg>
 	go doc <sym>[.<method>]
-	go doc [<pkg>].<sym>[.<method>]
+	go doc [<pkg>.]<sym>[.<method>]
+	go doc [<pkg>.][<sym>.]<method>
 
-The first item in this list matched by the argument is the one whose
-documentation is printed. (See the examples below.) For packages, the order of
-scanning is determined lexically, but the GOROOT tree is always scanned before
-GOPATH.
+The first item in this list matched by the argument is the one whose documentation
+is printed. (See the examples below.) However, if the argument starts with a capital
+letter it is assumed to identify a symbol or method in the current directory.
+
+For packages, the order of scanning is determined lexically in breadth-first order.
+That is, the package presented is the one that matches the search and is nearest
+the root and lexically first at its level of the hierarchy.  The GOROOT tree is
+always scanned in its entirety before GOPATH.
 
 If there is no package specified or matched, the package in the current
 directory is selected, so "go doc Foo" shows the documentation for symbol Foo in
@@ -85,6 +90,14 @@ Examples:
 	go doc text/template new # Two arguments
 		Show documentation for text/template's New function.
 
+	At least in the current tree, these invocations all print the
+	documentation for json.Decoder's Decode method:
+
+	go doc json.Decoder.Decode
+	go doc json.decoder.decode
+	go doc json.decode
+	cd go/src/encoding/json; go doc decode
+
 Flags:
 	-c
 		Respect case when matching symbols.
diff --git a/src/cmd/go/env.go b/src/cmd/go/env.go
index 600acca..24f6127 100644
--- a/src/cmd/go/env.go
+++ b/src/cmd/go/env.go
@@ -33,6 +33,11 @@ func mkEnv() []envVar {
 	var b builder
 	b.init()
 
+	vendorExpValue := "0"
+	if go15VendorExperiment {
+		vendorExpValue = "1"
+	}
+
 	env := []envVar{
 		{"GOARCH", goarch},
 		{"GOBIN", gobin},
@@ -44,7 +49,7 @@ func mkEnv() []envVar {
 		{"GORACE", os.Getenv("GORACE")},
 		{"GOROOT", goroot},
 		{"GOTOOLDIR", toolDir},
-		{"GO15VENDOREXPERIMENT", os.Getenv("GO15VENDOREXPERIMENT")},
+		{"GO15VENDOREXPERIMENT", vendorExpValue},
 
 		// disable escape codes in clang errors
 		{"TERM", "dumb"},
diff --git a/src/cmd/go/generate.go b/src/cmd/go/generate.go
index efdc229..cb54018 100644
--- a/src/cmd/go/generate.go
+++ b/src/cmd/go/generate.go
@@ -22,7 +22,7 @@ import (
 
 var cmdGenerate = &Command{
 	Run:       runGenerate,
-	UsageLine: "generate [-run regexp] [file.go... | packages]",
+	UsageLine: "generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]",
 	Short:     "generate Go files by processing source",
 	Long: `
 Generate runs commands described by directives within existing
@@ -115,12 +115,14 @@ Go generate accepts one specific flag:
 		any trailing spaces and final newline) matches the
 		expression.
 
-It also accepts the standard build flags -v, -n, and -x.
+It also accepts the standard build flags including -v, -n, and -x.
 The -v flag prints the names of packages and files as they are
 processed.
 The -n flag prints commands that would be executed.
 The -x flag prints commands as they are executed.
 
+For more about build flags, see 'go help build'.
+
 For more about specifying packages, see 'go help packages'.
 	`,
 }
@@ -179,6 +181,7 @@ type Generator struct {
 	pkg      string
 	commands map[string][]string
 	lineNum  int // current line number.
+	env      []string
 }
 
 // run runs the generators in the current file.
@@ -242,6 +245,7 @@ func (g *Generator) run() (ok bool) {
 			}
 		}
 
+		g.setEnv()
 		words := g.split(string(buf))
 		if len(words) == 0 {
 			g.errorf("no arguments to directive")
@@ -269,6 +273,19 @@ func isGoGenerate(buf []byte) bool {
 	return bytes.HasPrefix(buf, []byte("//go:generate ")) || bytes.HasPrefix(buf, []byte("//go:generate\t"))
 }
 
+// setEnv sets the extra environment variables used when executing a
+// single go:generate command.
+func (g *Generator) setEnv() {
+	g.env = []string{
+		"GOARCH=" + runtime.GOARCH,
+		"GOOS=" + runtime.GOOS,
+		"GOFILE=" + g.file,
+		"GOLINE=" + strconv.Itoa(g.lineNum),
+		"GOPACKAGE=" + g.pkg,
+		"DOLLAR=" + "$",
+	}
+}
+
 // split breaks the line into words, evaluating quoted
 // strings and evaluating environment variables.
 // The initial //go:generate element is present in line.
@@ -345,22 +362,13 @@ func (g *Generator) errorf(format string, args ...interface{}) {
 // expandVar expands the $XXX invocation in word. It is called
 // by os.Expand.
 func (g *Generator) expandVar(word string) string {
-	switch word {
-	case "GOARCH":
-		return buildContext.GOARCH
-	case "GOOS":
-		return buildContext.GOOS
-	case "GOFILE":
-		return g.file
-	case "GOLINE":
-		return fmt.Sprint(g.lineNum)
-	case "GOPACKAGE":
-		return g.pkg
-	case "DOLLAR":
-		return "$"
-	default:
-		return os.Getenv(word)
+	w := word + "="
+	for _, e := range g.env {
+		if strings.HasPrefix(e, w) {
+			return e[len(w):]
+		}
 	}
+	return os.Getenv(word)
 }
 
 // identLength returns the length of the identifier beginning the string.
@@ -396,13 +404,7 @@ func (g *Generator) exec(words []string) {
 	cmd.Stderr = os.Stderr
 	// Run the command in the package directory.
 	cmd.Dir = g.dir
-	env := []string{
-		"GOARCH=" + runtime.GOARCH,
-		"GOOS=" + runtime.GOOS,
-		"GOFILE=" + g.file,
-		"GOPACKAGE=" + g.pkg,
-	}
-	cmd.Env = mergeEnvLists(env, origEnv)
+	cmd.Env = mergeEnvLists(g.env, origEnv)
 	err := cmd.Run()
 	if err != nil {
 		g.errorf("running %q: %s", words[0], err)
diff --git a/src/cmd/go/generate_test.go b/src/cmd/go/generate_test.go
index 169d71c..ba06692 100644
--- a/src/cmd/go/generate_test.go
+++ b/src/cmd/go/generate_test.go
@@ -39,6 +39,7 @@ func TestGenerateCommandParse(t *testing.T) {
 		pkg:      "sys",
 		commands: make(map[string][]string),
 	}
+	g.setEnv()
 	g.setShorthand([]string{"-command", "yacc", "go", "tool", "yacc"})
 	for _, test := range splitTests {
 		// First with newlines.
diff --git a/src/cmd/go/get.go b/src/cmd/go/get.go
index e95201a..a298049 100644
--- a/src/cmd/go/get.go
+++ b/src/cmd/go/get.go
@@ -45,16 +45,22 @@ missing packages but does not use it to look for updates to existing packages.
 
 Get also accepts build flags to control the installation. See 'go help build'.
 
+When checking out a new package, get creates the target directory 
+GOPATH/src/<import-path>. If the GOPATH contains multiple entries,
+get uses the first one. See 'go help gopath'.
+
 When checking out or updating a package, get looks for a branch or tag
 that matches the locally installed version of Go. The most important
 rule is that if the local installation is running version "go1", get
 searches for a branch or tag named "go1". If no such version exists it
 retrieves the most recent version of the package.
 
-If the vendoring experiment is enabled (see 'go help gopath'),
-then when go get checks out or updates a Git repository,
+Unless vendoring support is disabled (see 'go help gopath'),
+when go get checks out or updates a Git repository,
 it also updates any git submodules referenced by the repository.
 
+Get never checks out or updates code stored in vendor directories.
+
 For more about specifying packages, see 'go help packages'.
 
 For more about how 'go get' finds source code to
@@ -84,8 +90,12 @@ func runGet(cmd *Command, args []string) {
 	// Disable any prompting for passwords by Git.
 	// Only has an effect for 2.3.0 or later, but avoiding
 	// the prompt in earlier versions is just too hard.
-	// See golang.org/issue/9341.
-	os.Setenv("GIT_TERMINAL_PROMPT", "0")
+	// If user has explicitly set GIT_TERMINAL_PROMPT=1, keep
+	// prompting.
+	// See golang.org/issue/9341 and golang.org/issue/12706.
+	if os.Getenv("GIT_TERMINAL_PROMPT") == "" {
+		os.Setenv("GIT_TERMINAL_PROMPT", "0")
+	}
 
 	// Phase 1.  Download/update.
 	var stk importStack
diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go
index 77b2628..39e0f3e 100644
--- a/src/cmd/go/go_test.go
+++ b/src/cmd/go/go_test.go
@@ -10,6 +10,7 @@ import (
 	"fmt"
 	"go/build"
 	"go/format"
+	"internal/race"
 	"internal/testenv"
 	"io"
 	"io/ioutil"
@@ -31,8 +32,7 @@ var (
 
 	exeSuffix string // ".exe" on Windows
 
-	builder             = testenv.Builder()
-	skipExternalBuilder = false // skip external tests on this builder
+	skipExternal = false // skip external tests
 )
 
 func init() {
@@ -44,14 +44,21 @@ func init() {
 		case "arm", "arm64":
 			canRun = false
 		}
-	}
-
-	if strings.HasPrefix(builder+"-", "freebsd-arm-") {
-		skipExternalBuilder = true
-		canRun = false
-	}
-
-	switch runtime.GOOS {
+	case "linux":
+		switch runtime.GOARCH {
+		case "arm":
+			// many linux/arm machines are too slow to run
+			// the full set of external tests.
+			skipExternal = true
+		}
+	case "freebsd":
+		switch runtime.GOARCH {
+		case "arm":
+			// many freebsd/arm machines are too slow to run
+			// the full set of external tests.
+			skipExternal = true
+			canRun = false
+		}
 	case "windows":
 		exeSuffix = ".exe"
 	}
@@ -63,7 +70,11 @@ func TestMain(m *testing.M) {
 	flag.Parse()
 
 	if canRun {
-		out, err := exec.Command("go", "build", "-tags", "testgo", "-o", "testgo"+exeSuffix).CombinedOutput()
+		args := []string{"build", "-tags", "testgo", "-o", "testgo" + exeSuffix}
+		if race.Enabled {
+			args = append(args, "-race")
+		}
+		out, err := exec.Command("go", args...).CombinedOutput()
 		if err != nil {
 			fmt.Fprintf(os.Stderr, "building testgo failed: %v\n%s", err, out)
 			os.Exit(2)
@@ -83,8 +94,6 @@ func TestMain(m *testing.M) {
 		case "linux", "darwin", "freebsd", "windows":
 			canRace = canCgo && runtime.GOARCH == "amd64"
 		}
-
-		measureTick("./testgo" + exeSuffix)
 	}
 
 	// Don't let these environment variables confuse the test.
@@ -103,24 +112,8 @@ func TestMain(m *testing.M) {
 // The length of an mtime tick on this system.  This is an estimate of
 // how long we need to sleep to ensure that the mtime of two files is
 // different.
-var mtimeTick time.Duration
-
-// measureTick sets mtimeTick by looking at the rounding of the mtime
-// of a file.
-func measureTick(path string) {
-	st, err := os.Stat(path)
-	if err != nil {
-		// Default to one second, the most conservative value.
-		mtimeTick = time.Second
-		return
-	}
-	mtime := st.ModTime()
-	t := time.Microsecond
-	for mtime.Round(t).Equal(mtime) && t < time.Second {
-		t *= 10
-	}
-	mtimeTick = t
-}
+// We used to try to be clever but that didn't always work (see golang.org/issue/12205).
+var mtimeTick time.Duration = 1 * time.Second
 
 // Manage a single run of the testgo binary.
 type testgoData struct {
@@ -138,8 +131,8 @@ type testgoData struct {
 func testgo(t *testing.T) *testgoData {
 	testenv.MustHaveGoBuild(t)
 
-	if skipExternalBuilder {
-		t.Skip("skipping external tests on %s builder", builder)
+	if skipExternal {
+		t.Skip("skipping external tests on %s/%s", runtime.GOOS, runtime.GOARCH)
 	}
 
 	return &testgoData{t: t}
@@ -452,7 +445,7 @@ func (tg *testgoData) grepCountBoth(match string) int {
 // removed if it exists.
 func (tg *testgoData) creatingTemp(path string) {
 	if filepath.IsAbs(path) && !strings.HasPrefix(path, tg.tempdir) {
-		tg.t.Fatal("internal testsuite error: creatingTemp(%q) with absolute path not in temporary directory", path)
+		tg.t.Fatalf("internal testsuite error: creatingTemp(%q) with absolute path not in temporary directory", path)
 	}
 	// If we have changed the working directory, make sure we have
 	// an absolute path, because we are going to change directory
@@ -669,19 +662,122 @@ func TestGoBuildDashAInDevBranch(t *testing.T) {
 	tg.setenv("TESTGO_IS_GO_RELEASE", "0")
 	tg.run("build", "-v", "-a", "math")
 	tg.grepStderr("runtime", "testgo build -a math in dev branch DID NOT build runtime, but should have")
+
+	// Everything is out of date. Rebuild to leave things in a better state.
+	tg.run("install", "std")
 }
 
-func TestGoBuilDashAInReleaseBranch(t *testing.T) {
+func TestGoBuildDashAInReleaseBranch(t *testing.T) {
 	if testing.Short() {
 		t.Skip("don't rebuild the standard library in short mode")
 	}
 
 	tg := testgo(t)
 	defer tg.cleanup()
-	tg.run("install", "math") // should be up to date already but just in case
+	tg.run("install", "math", "net/http") // should be up to date already but just in case
 	tg.setenv("TESTGO_IS_GO_RELEASE", "1")
-	tg.run("build", "-v", "-a", "math")
-	tg.grepStderr("runtime", "testgo build -a math in dev branch did not build runtime, but should have")
+	tg.run("install", "-v", "-a", "math")
+	tg.grepStderr("runtime", "testgo build -a math in release branch DID NOT build runtime, but should have")
+
+	// Now runtime.a is updated (newer mtime), so everything would look stale if not for being a release.
+	tg.run("build", "-v", "net/http")
+	tg.grepStderrNot("strconv", "testgo build -v net/http in release branch with newer runtime.a DID build strconv but should not have")
+	tg.grepStderrNot("golang.org/x/net/http2/hpack", "testgo build -v net/http in release branch with newer runtime.a DID build .../golang.org/x/net/http2/hpack but should not have")
+	tg.grepStderrNot("net/http", "testgo build -v net/http in release branch with newer runtime.a DID build net/http but should not have")
+
+	// Everything is out of date. Rebuild to leave things in a better state.
+	tg.run("install", "std")
+}
+
+func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
+	if testing.Short() {
+		t.Skip("don't rebuild the standard library in short mode")
+	}
+
+	tg := testgo(t)
+	defer tg.cleanup()
+
+	addNL := func(name string) (restore func()) {
+		data, err := ioutil.ReadFile(name)
+		if err != nil {
+			t.Fatal(err)
+		}
+		old := data
+		data = append(data, '\n')
+		if err := ioutil.WriteFile(name, append(data, '\n'), 0666); err != nil {
+			t.Fatal(err)
+		}
+		tg.sleep()
+		return func() {
+			if err := ioutil.WriteFile(name, old, 0666); err != nil {
+				t.Fatal(err)
+			}
+		}
+	}
+
+	tg.setenv("TESTGO_IS_GO_RELEASE", "1")
+
+	tg.tempFile("d1/src/p1/p1.go", `package p1`)
+	tg.setenv("GOPATH", tg.path("d1"))
+	tg.run("install", "-a", "p1")
+	tg.wantNotStale("p1", "./testgo list claims p1 is stale, incorrectly")
+	tg.sleep()
+
+	// Changing mtime and content of runtime/internal/sys/sys.go
+	// should have no effect: we're in a release, which doesn't rebuild
+	// for general mtime or content changes.
+	sys := runtime.GOROOT() + "/src/runtime/internal/sys/sys.go"
+	restore := addNL(sys)
+	defer restore()
+	tg.wantNotStale("p1", "./testgo list claims p1 is stale, incorrectly, after updating runtime/internal/sys/sys.go")
+	restore()
+	tg.wantNotStale("p1", "./testgo list claims p1 is stale, incorrectly, after restoring runtime/internal/sys/sys.go")
+
+	// But changing runtime/internal/sys/zversion.go should have an effect:
+	// that's how we tell when we flip from one release to another.
+	zversion := runtime.GOROOT() + "/src/runtime/internal/sys/zversion.go"
+	restore = addNL(zversion)
+	defer restore()
+	tg.wantStale("p1", "./testgo list claims p1 is NOT stale, incorrectly, after changing to new release")
+	restore()
+	tg.wantNotStale("p1", "./testgo list claims p1 is stale, incorrectly, after changing back to old release")
+	addNL(zversion)
+	tg.wantStale("p1", "./testgo list claims p1 is NOT stale, incorrectly, after changing again to new release")
+	tg.run("install", "p1")
+	tg.wantNotStale("p1", "./testgo list claims p1 is stale after building with new release")
+
+	// Restore to "old" release.
+	restore()
+	tg.wantStale("p1", "./testgo list claims p1 is NOT stale, incorrectly, after changing to old release after new build")
+	tg.run("install", "p1")
+	tg.wantNotStale("p1", "./testgo list claims p1 is stale after building with old release")
+
+	// Everything is out of date. Rebuild to leave things in a better state.
+	tg.run("install", "std")
+}
+
+func TestGoListStandard(t *testing.T) {
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.cd(runtime.GOROOT() + "/src")
+	tg.run("list", "-f", "{{if not .Standard}}{{.ImportPath}}{{end}}", "./...")
+	stdout := tg.getStdout()
+	for _, line := range strings.Split(stdout, "\n") {
+		if strings.HasPrefix(line, "_/") && strings.HasSuffix(line, "/src") {
+			// $GOROOT/src shows up if there are any .go files there.
+			// We don't care.
+			continue
+		}
+		if line == "" {
+			continue
+		}
+		t.Errorf("package in GOROOT not listed as standard: %v", line)
+	}
+
+	// Similarly, expanding std should include some of our vendored code.
+	tg.run("list", "std", "cmd")
+	tg.grepStdout("golang.org/x/net/http2/hpack", "list std cmd did not mention vendored hpack")
+	tg.grepStdout("golang.org/x/arch/x86/x86asm", "list std cmd did not mention vendored x86asm")
 }
 
 func TestGoInstallCleansUpAfterGoBuild(t *testing.T) {
@@ -737,8 +833,8 @@ func TestGoInstallRebuildsStalePackagesInOtherGOPATH(t *testing.T) {
 	sep := string(filepath.ListSeparator)
 	tg.setenv("GOPATH", tg.path("d1")+sep+tg.path("d2"))
 	tg.run("install", "p1")
-	tg.wantNotStale("p1", "./testgo list mypkg claims p1 is stale, incorrectly")
-	tg.wantNotStale("p2", "./testgo list mypkg claims p2 is stale, incorrectly")
+	tg.wantNotStale("p1", "./testgo list claims p1 is stale, incorrectly")
+	tg.wantNotStale("p2", "./testgo list claims p2 is stale, incorrectly")
 	tg.sleep()
 	if f, err := os.OpenFile(tg.path("d2/src/p2/p2.go"), os.O_WRONLY|os.O_APPEND, 0); err != nil {
 		t.Fatal(err)
@@ -747,12 +843,12 @@ func TestGoInstallRebuildsStalePackagesInOtherGOPATH(t *testing.T) {
 	} else {
 		tg.must(f.Close())
 	}
-	tg.wantStale("p2", "./testgo list mypkg claims p2 is NOT stale, incorrectly")
-	tg.wantStale("p1", "./testgo list mypkg claims p1 is NOT stale, incorrectly")
+	tg.wantStale("p2", "./testgo list claims p2 is NOT stale, incorrectly")
+	tg.wantStale("p1", "./testgo list claims p1 is NOT stale, incorrectly")
 
 	tg.run("install", "p1")
-	tg.wantNotStale("p2", "./testgo list mypkg claims p2 is stale after reinstall, incorrectly")
-	tg.wantNotStale("p1", "./testgo list mypkg claims p1 is stale after reinstall, incorrectly")
+	tg.wantNotStale("p2", "./testgo list claims p2 is stale after reinstall, incorrectly")
+	tg.wantNotStale("p1", "./testgo list claims p1 is stale after reinstall, incorrectly")
 }
 
 func TestGoInstallDetectsRemovedFiles(t *testing.T) {
@@ -775,6 +871,28 @@ func TestGoInstallDetectsRemovedFiles(t *testing.T) {
 	tg.wantStale("mypkg", "./testgo list mypkg claims mypkg is NOT stale after removing y.go; should be stale")
 }
 
+func TestWildcardMatchesSyntaxErrorDirs(t *testing.T) {
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.tempFile("src/mypkg/x.go", `package mypkg`)
+	tg.tempFile("src/mypkg/y.go", `pkg mypackage`)
+	tg.setenv("GOPATH", tg.path("."))
+	tg.cd(tg.path("src/mypkg"))
+	tg.runFail("list", "./...")
+	tg.runFail("build", "./...")
+	tg.runFail("install", "./...")
+}
+
+func TestGoListWithTags(t *testing.T) {
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.tempFile("src/mypkg/x.go", "// +build thetag\n\npackage mypkg\n")
+	tg.setenv("GOPATH", tg.path("."))
+	tg.cd(tg.path("./src"))
+	tg.run("list", "-tags=thetag", "./my...")
+	tg.grepStdout("mypkg", "did not find mypkg")
+}
+
 func TestGoInstallErrorOnCrossCompileToBin(t *testing.T) {
 	if testing.Short() {
 		t.Skip("don't install into GOROOT in short mode")
@@ -951,6 +1069,16 @@ func TestInternalPackagesOutsideGOROOTAreRespected(t *testing.T) {
 	tg.grepBoth("use of internal package not allowed", "wrote error message for testdata/testinternal2")
 }
 
+func TestRunInternal(t *testing.T) {
+	tg := testgo(t)
+	defer tg.cleanup()
+	dir := filepath.Join(tg.pwd(), "testdata")
+	tg.setenv("GOPATH", dir)
+	tg.run("run", filepath.Join(dir, "src/run/good.go"))
+	tg.runFail("run", filepath.Join(dir, "src/run/bad.go"))
+	tg.grepStderr("use of internal package not allowed", "unexpected error for run/bad.go")
+}
+
 func testMove(t *testing.T, vcs, url, base, config string) {
 	testenv.MustHaveExternalNetwork(t)
 
@@ -1053,7 +1181,6 @@ func TestImportCommentConflict(t *testing.T) {
 // cmd/go: custom import path checking should not apply to github.com/xxx/yyy.
 func TestIssue10952(t *testing.T) {
 	testenv.MustHaveExternalNetwork(t)
-
 	if _, err := exec.LookPath("git"); err != nil {
 		t.Skip("skipping because git binary not found")
 	}
@@ -1071,6 +1198,34 @@ func TestIssue10952(t *testing.T) {
 	tg.run("get", "-d", "-u", importPath)
 }
 
+func TestGetGitDefaultBranch(t *testing.T) {
+	testenv.MustHaveExternalNetwork(t)
+	if _, err := exec.LookPath("git"); err != nil {
+		t.Skip("skipping because git binary not found")
+	}
+
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.parallel()
+	tg.tempDir("src")
+	tg.setenv("GOPATH", tg.path("."))
+
+	// This repo has two branches, master and another-branch.
+	// The another-branch is the default that you get from 'git clone'.
+	// The go get command variants should not override this.
+	const importPath = "github.com/rsc/go-get-default-branch"
+
+	tg.run("get", "-d", importPath)
+	repoDir := tg.path("src/" + importPath)
+	defer tg.resetReadOnlyFlagAll(repoDir)
+	tg.runGit(repoDir, "branch", "--contains", "HEAD")
+	tg.grepStdout(`\* another-branch`, "not on correct default branch")
+
+	tg.run("get", "-d", "-u", importPath)
+	tg.runGit(repoDir, "branch", "--contains", "HEAD")
+	tg.grepStdout(`\* another-branch`, "not on correct default branch")
+}
+
 func TestDisallowedCSourceFiles(t *testing.T) {
 	tg := testgo(t)
 	defer tg.cleanup()
@@ -1139,6 +1294,15 @@ func TestInstallFailsWithNoBuildableFiles(t *testing.T) {
 	tg.grepStderr("no buildable Go source files", "go install cgotest did not report 'no buildable Go Source files'")
 }
 
+func TestRelativeGOBINFail(t *testing.T) {
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.tempFile("triv.go", `package main; func main() {}`)
+	tg.setenv("GOBIN", ".")
+	tg.runFail("install")
+	tg.grepStderr("cannot install, GOBIN must be an absolute path", "go install must fail if $GOBIN is a relative path")
+}
+
 // Test that without $GOBIN set, binaries get installed
 // into the GOPATH bin directory.
 func TestInstallIntoGOPATH(t *testing.T) {
@@ -1150,9 +1314,21 @@ func TestInstallIntoGOPATH(t *testing.T) {
 	tg.wantExecutable("testdata/bin/go-cmd-test"+exeSuffix, "go install go-cmd-test did not write to testdata/bin/go-cmd-test")
 }
 
+// Issue 12407
+func TestBuildOutputToDevNull(t *testing.T) {
+	if runtime.GOOS == "plan9" {
+		t.Skip("skipping because /dev/null is a regular file on plan9")
+	}
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+	tg.run("build", "-o", os.DevNull, "go-cmd-test")
+}
+
 func TestPackageMainTestImportsArchiveNotBinary(t *testing.T) {
 	tg := testgo(t)
 	defer tg.cleanup()
+	tg.parallel()
 	gobin := filepath.Join(tg.pwd(), "testdata", "bin")
 	tg.creatingTemp(gobin)
 	tg.setenv("GOBIN", gobin)
@@ -1165,6 +1341,17 @@ func TestPackageMainTestImportsArchiveNotBinary(t *testing.T) {
 	tg.run("test", "main_test")
 }
 
+// Issue 12690
+func TestPackageNotStaleWithTrailingSlash(t *testing.T) {
+	tg := testgo(t)
+	defer tg.cleanup()
+	goroot := runtime.GOROOT()
+	tg.setenv("GOROOT", goroot+"/")
+	tg.wantNotStale("runtime", "with trailing slash in GOROOT, runtime listed as stale")
+	tg.wantNotStale("os", "with trailing slash in GOROOT, os listed as stale")
+	tg.wantNotStale("io", "with trailing slash in GOROOT, io listed as stale")
+}
+
 // With $GOBIN set, binaries get installed to $GOBIN.
 func TestInstallIntoGOBIN(t *testing.T) {
 	tg := testgo(t)
@@ -1357,6 +1544,18 @@ func TestGoListCmdOnlyShowsCommands(t *testing.T) {
 	}
 }
 
+func TestGoListDedupsPackages(t *testing.T) {
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+	tg.run("list", "xtestonly", "./testdata/src/xtestonly/...")
+	got := strings.TrimSpace(tg.getStdout())
+	const want = "xtestonly"
+	if got != want {
+		t.Errorf("got %q; want %q", got, want)
+	}
+}
+
 // Issue 4096. Validate the output of unsuccessful go install foo/quxx.
 func TestUnsuccessfulGoInstallShouldMentionMissingPackage(t *testing.T) {
 	tg := testgo(t)
@@ -1499,7 +1698,7 @@ func TestGoTestDashOWritesBinary(t *testing.T) {
 }
 
 // Issue 4568.
-func TestSymlinksDoNotConfuseGoList(t *testing.T) {
+func TestSymlinksList(t *testing.T) {
 	switch runtime.GOOS {
 	case "plan9", "windows":
 		t.Skipf("skipping symlink test on %s", runtime.GOOS)
@@ -1518,6 +1717,58 @@ func TestSymlinksDoNotConfuseGoList(t *testing.T) {
 	}
 }
 
+// Issue 14054.
+func TestSymlinksVendor(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9", "windows":
+		t.Skipf("skipping symlink test on %s", runtime.GOOS)
+	}
+
+	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")
+	tg.must(os.Symlink(tg.path("gopath/src/dir1"), tg.path("symdir1")))
+	tg.setenv("GOPATH", tg.path("gopath"))
+	tg.cd(tg.path("symdir1"))
+	tg.run("list", "-f", "{{.Root}}", ".")
+	if strings.TrimSpace(tg.getStdout()) != tg.path("gopath") {
+		t.Error("list confused by symlinks")
+	}
+
+	// All of these should succeed, not die in vendor-handling code.
+	tg.run("run", "p.go")
+	tg.run("build")
+	tg.run("install")
+}
+
+func TestSymlinksInternal(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9", "windows":
+		t.Skipf("skipping symlink test on %s", runtime.GOOS)
+	}
+
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.tempDir("gopath/src/dir1/internal/v")
+	tg.tempFile("gopath/src/dir1/p.go", "package main\nimport _ `dir1/internal/v`\nfunc main(){}")
+	tg.tempFile("gopath/src/dir1/internal/v/v.go", "package v")
+	tg.must(os.Symlink(tg.path("gopath/src/dir1"), tg.path("symdir1")))
+	tg.setenv("GOPATH", tg.path("gopath"))
+	tg.cd(tg.path("symdir1"))
+	tg.run("list", "-f", "{{.Root}}", ".")
+	if strings.TrimSpace(tg.getStdout()) != tg.path("gopath") {
+		t.Error("list confused by symlinks")
+	}
+
+	// All of these should succeed, not die in internal-handling code.
+	tg.run("run", "p.go")
+	tg.run("build")
+	tg.run("install")
+}
+
 // Issue 4515.
 func TestInstallWithTags(t *testing.T) {
 	tg := testgo(t)
@@ -1833,6 +2084,9 @@ func TestIssue6480(t *testing.T) {
 
 // cmd/cgo: undefined reference when linking a C-library using gccgo
 func TestIssue7573(t *testing.T) {
+	if !canCgo {
+		t.Skip("skipping because cgo not enabled")
+	}
 	if _, err := exec.LookPath("gccgo"); err != nil {
 		t.Skip("skipping because no gccgo compiler found")
 	}
@@ -1931,6 +2185,13 @@ func TestGoTestFooTestWorks(t *testing.T) {
 	tg.run("test", "testdata/standalone_test.go")
 }
 
+func TestGoTestFlagsAfterPackage(t *testing.T) {
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.run("test", "testdata/flag_test.go", "-v", "-args", "-v=7") // Two distinct -v flags.
+	tg.run("test", "-v", "testdata/flag_test.go", "-args", "-v=7") // Two distinct -v flags.
+}
+
 func TestGoTestXtestonlyWorks(t *testing.T) {
 	tg := testgo(t)
 	defer tg.cleanup()
@@ -1991,6 +2252,21 @@ func TestGoGenerateRunFlag(t *testing.T) {
 	tg.grepStdoutNot("no", "go generate -run yes ./testdata/generate/test4.go selected no")
 }
 
+func TestGoGenerateEnv(t *testing.T) {
+	switch runtime.GOOS {
+	case "plan9", "windows":
+		t.Skipf("skipping because %s does not have the env command", runtime.GOOS)
+	}
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.parallel()
+	tg.tempFile("env.go", "package main\n\n//go:generate env")
+	tg.run("generate", tg.path("env.go"))
+	for _, v := range []string{"GOARCH", "GOOS", "GOFILE", "GOLINE", "GOPACKAGE", "DOLLAR"} {
+		tg.grepStdout("^"+v+"=", "go generate environment missing "+v)
+	}
+}
+
 func TestGoGetCustomDomainWildcard(t *testing.T) {
 	testenv.MustHaveExternalNetwork(t)
 
@@ -2051,6 +2327,17 @@ func TestGoGetRscIoToolstash(t *testing.T) {
 	tg.run("get", "./toolstash")
 }
 
+// Issue 13037: Was not parsing <meta> tags in 404 served over HTTPS
+func TestGoGetHTTPS404(t *testing.T) {
+	testenv.MustHaveExternalNetwork(t)
+
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.tempDir("src")
+	tg.setenv("GOPATH", tg.path("."))
+	tg.run("get", "bazil.org/fuse/fs/fstestutil")
+}
+
 // Test that you can not import a main package.
 func TestIssue4210(t *testing.T) {
 	tg := testgo(t)
@@ -2128,7 +2415,11 @@ func TestGoGetInsecureCustomDomain(t *testing.T) {
 }
 
 func TestIssue10193(t *testing.T) {
+	t.Skip("depends on code.google.com")
 	testenv.MustHaveExternalNetwork(t)
+	if _, err := exec.LookPath("hg"); err != nil {
+		t.Skip("skipping because hg binary not found")
+	}
 
 	tg := testgo(t)
 	defer tg.cleanup()
@@ -2199,7 +2490,7 @@ func TestGoTestImportErrorStack(t *testing.T) {
 	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
 	tg.runFail("test", "testdep/p1")
 	if !strings.Contains(tg.stderr.String(), out) {
-		t.Fatal("did not give full import stack:\n\n%s", tg.stderr.String())
+		t.Fatalf("did not give full import stack:\n\n%s", tg.stderr.String())
 	}
 }
 
@@ -2279,6 +2570,59 @@ func TestGoInstallShadowedGOPATH(t *testing.T) {
 	tg.grepStderr("no install location for.*gopath2.src.test: hidden by .*gopath1.src.test", "missing error")
 }
 
+func TestGoBuildGOPATHOrder(t *testing.T) {
+	// golang.org/issue/14176#issuecomment-179895769
+	// golang.org/issue/14192
+	// -I arguments to compiler could end up not in GOPATH order,
+	// leading to unexpected import resolution in the compiler.
+	// This is still not a complete fix (see golang.org/issue/14271 and next test)
+	// but it is clearly OK and enough to fix both of the two reported
+	// instances of the underlying problem. It will have to do for now.
+
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.makeTempdir()
+	tg.setenv("GOPATH", tg.path("p1")+string(filepath.ListSeparator)+tg.path("p2"))
+
+	tg.tempFile("p1/src/foo/foo.go", "package foo\n")
+	tg.tempFile("p2/src/baz/baz.go", "package baz\n")
+	tg.tempFile("p2/pkg/"+runtime.GOOS+"_"+runtime.GOARCH+"/foo.a", "bad\n")
+	tg.tempFile("p1/src/bar/bar.go", `
+		package bar
+		import _ "baz"
+		import _ "foo"
+	`)
+
+	tg.run("install", "-x", "bar")
+}
+
+func TestGoBuildGOPATHOrderBroken(t *testing.T) {
+	// This test is known not to work.
+	// See golang.org/issue/14271.
+	t.Skip("golang.org/issue/14271")
+
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.makeTempdir()
+
+	tg.tempFile("p1/src/foo/foo.go", "package foo\n")
+	tg.tempFile("p2/src/baz/baz.go", "package baz\n")
+	tg.tempFile("p1/pkg/"+runtime.GOOS+"_"+runtime.GOARCH+"/baz.a", "bad\n")
+	tg.tempFile("p2/pkg/"+runtime.GOOS+"_"+runtime.GOARCH+"/foo.a", "bad\n")
+	tg.tempFile("p1/src/bar/bar.go", `
+		package bar
+		import _ "baz"
+		import _ "foo"
+	`)
+
+	colon := string(filepath.ListSeparator)
+	tg.setenv("GOPATH", tg.path("p1")+colon+tg.path("p2"))
+	tg.run("install", "-x", "bar")
+
+	tg.setenv("GOPATH", tg.path("p2")+colon+tg.path("p1"))
+	tg.run("install", "-x", "bar")
+}
+
 func TestIssue11709(t *testing.T) {
 	tg := testgo(t)
 	defer tg.cleanup()
@@ -2387,3 +2731,31 @@ func TestGoBuildARM(t *testing.T) {
 	tg.run("build", "hello.go")
 	tg.grepStderrNot("unable to find math.a", "did not build math.a correctly")
 }
+
+func TestIssue13655(t *testing.T) {
+	tg := testgo(t)
+	defer tg.cleanup()
+	for _, pkg := range []string{"runtime", "runtime/internal/atomic"} {
+		tg.run("list", "-f", "{{.Deps}}", pkg)
+		tg.grepStdout("runtime/internal/sys", "did not find required dependency of "+pkg+" on runtime/internal/sys")
+	}
+}
+
+// For issue 14337.
+func TestParallelTest(t *testing.T) {
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.makeTempdir()
+	const testSrc = `package package_test
+		import (
+			"testing"
+		)
+		func TestTest(t *testing.T) {
+		}`
+	tg.tempFile("src/p1/p1_test.go", strings.Replace(testSrc, "package_test", "p1_test", 1))
+	tg.tempFile("src/p2/p2_test.go", strings.Replace(testSrc, "package_test", "p2_test", 1))
+	tg.tempFile("src/p3/p3_test.go", strings.Replace(testSrc, "package_test", "p3_test", 1))
+	tg.tempFile("src/p4/p4_test.go", strings.Replace(testSrc, "package_test", "p4_test", 1))
+	tg.setenv("GOPATH", tg.path("."))
+	tg.run("test", "-p=4", "p1", "p2", "p3", "p4")
+}
diff --git a/src/cmd/go/go_unix_test.go b/src/cmd/go/go_unix_test.go
new file mode 100644
index 0000000..0d85859
--- /dev/null
+++ b/src/cmd/go/go_unix_test.go
@@ -0,0 +1,31 @@
+// Copyright 2015 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd solaris
+
+package main_test
+
+import (
+	"os"
+	"syscall"
+	"testing"
+)
+
+func TestGoBuildUmask(t *testing.T) {
+	// Do not use tg.parallel; avoid other tests seeing umask manipulation.
+	mask := syscall.Umask(0077) // prohibit low bits
+	defer syscall.Umask(mask)
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.tempFile("x.go", `package main; func main() {}`)
+	tg.creatingTemp("x")
+	tg.run("build", tg.path("x.go"))
+	fi, err := os.Stat("x")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if mode := fi.Mode(); mode&0077 != 0 {
+		t.Fatalf("wrote x with mode=%v, wanted no 0077 bits", mode)
+	}
+}
diff --git a/src/cmd/go/help.go b/src/cmd/go/help.go
index 5dff267..d8e7efe 100644
--- a/src/cmd/go/help.go
+++ b/src/cmd/go/help.go
@@ -79,6 +79,14 @@ internally at Google all begin with 'google', and paths
 denoting remote repositories begin with the path to the code,
 such as 'github.com/user/repo'.
 
+Packages in a program need not have unique package names,
+but there are two reserved package names with special meaning.
+The name main indicates a command, not a library.
+Commands are built into binaries and cannot be imported.
+The name documentation indicates documentation for
+a non-Go program in the directory. Files in package documentation
+are ignored by the go command.
+
 As a special case, if the package list is a list of .go files from a
 single directory, the command is applied to a single synthesized
 package made up of exactly those files, ignoring any build constraints
@@ -261,10 +269,10 @@ unless it is being referred to by that import path. In this way, import comments
 let package authors make sure the custom import path is used and not a
 direct path to the underlying code hosting site.
 
-If the vendoring experiment is enabled (see 'go help gopath'),
-then import path checking is disabled for code found within vendor trees.
-This makes it possible to copy code into alternate locations in vendor trees
-without needing to update import comments.
+If vendoring is enabled (see 'go help gopath'), then import path checking is
+disabled for code found within vendor trees. This makes it possible to copy
+code into alternate locations in vendor trees without needing to update import
+comments.
 
 See https://golang.org/s/go14customimport for details.
 	`,
@@ -307,7 +315,7 @@ DIR/bin/quux, not DIR/bin/foo/quux.  The "foo/" prefix is stripped
 so that you can add DIR/bin to your PATH to get at the
 installed commands.  If the GOBIN environment variable is
 set, commands are installed to the directory it names instead
-of DIR/bin.
+of DIR/bin. GOBIN must be an absolute path.
 
 Here's an example directory layout:
 
@@ -365,13 +373,10 @@ See https://golang.org/s/go14internal for details.
 
 Vendor Directories
 
-Go 1.5 includes experimental support for using local copies
-of external dependencies to satisfy imports of those dependencies,
-often referred to as vendoring. Setting the environment variable
-GO15VENDOREXPERIMENT=1 enables that experimental support.
+Go 1.6 includes support for using local copies of external dependencies
+to satisfy imports of those dependencies, often referred to as vendoring.
 
-When the vendor experiment is enabled,
-code below a directory named "vendor" is importable only
+Code below a directory named "vendor" is importable only
 by code in the directory tree rooted at the parent of "vendor",
 and only using an import path that omits the prefix up to and
 including the vendor element.
@@ -409,12 +414,18 @@ top-level "crash/bang".
 Code in vendor directories is not subject to import path
 checking (see 'go help importpath').
 
-When the vendor experiment is enabled, 'go get' checks out
-submodules when checking out or updating a git repository
-(see 'go help get').
+When 'go get' checks out or updates a git repository, it now also
+updates submodules.
+
+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.
 
-The vendoring semantics are an experiment, and they may change
-in future releases. Once settled, they will be on by default.
+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.
 	`,
@@ -487,7 +498,7 @@ Special-purpose environment variables:
 		File names in stack traces are rewritten from GOROOT to
 		GOROOT_FINAL.
 	GO15VENDOREXPERIMENT
-		Set to 1 to enable the Go 1.5 vendoring experiment.
+		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.
@@ -570,5 +581,10 @@ are:
 	-buildmode=exe
 		Build the listed main packages and everything they import into
 		executables. Packages not named main are ignored.
+
+	-buildmode=pie
+		Build the listed main packages and everything they import into
+		position independent executables (PIE). Packages not named
+		main are ignored.
 `,
 }
diff --git a/src/cmd/go/http.go b/src/cmd/go/http.go
index 7979c41..3a6f19d 100644
--- a/src/cmd/go/http.go
+++ b/src/cmd/go/http.go
@@ -12,6 +12,7 @@
 package main
 
 import (
+	"crypto/tls"
 	"fmt"
 	"io"
 	"io/ioutil"
@@ -24,8 +25,17 @@ import (
 // httpClient is the default HTTP client, but a variable so it can be
 // changed by tests, without modifying http.DefaultClient.
 var httpClient = http.DefaultClient
-var impatientHTTPClient = &http.Client{
+
+// impatientInsecureHTTPClient is used in -insecure mode,
+// when we're connecting to https servers that might not be there
+// or might be using self-signed certificates.
+var impatientInsecureHTTPClient = &http.Client{
 	Timeout: time.Duration(5 * time.Second),
+	Transport: &http.Transport{
+		TLSClientConfig: &tls.Config{
+			InsecureSkipVerify: true,
+		},
+	},
 }
 
 type httpError struct {
@@ -71,7 +81,7 @@ func httpsOrHTTP(importPath string, security securityMode) (urlStr string, body
 			log.Printf("Fetching %s", urlStr)
 		}
 		if security == insecure && scheme == "https" { // fail earlier
-			res, err = impatientHTTPClient.Get(urlStr)
+			res, err = impatientInsecureHTTPClient.Get(urlStr)
 		} else {
 			res, err = httpClient.Get(urlStr)
 		}
@@ -83,16 +93,12 @@ func httpsOrHTTP(importPath string, security securityMode) (urlStr string, body
 		}
 	}
 	urlStr, res, err := fetch("https")
-	if err != nil || res.StatusCode != 200 {
+	if err != nil {
 		if buildV {
-			if err != nil {
-				log.Printf("https fetch failed.")
-			} else {
-				log.Printf("ignoring https fetch with status code %d", res.StatusCode)
-			}
+			log.Printf("https fetch failed: %v", err)
 		}
-		closeBody(res)
 		if security == insecure {
+			closeBody(res)
 			urlStr, res, err = fetch("http")
 		}
 	}
diff --git a/src/cmd/go/list.go b/src/cmd/go/list.go
index 35c7cc4..8f741a6 100644
--- a/src/cmd/go/list.go
+++ b/src/cmd/go/list.go
@@ -78,6 +78,14 @@ syntax of package template.  The default output is equivalent to -f
         XTestImports []string // imports from XTestGoFiles
     }
 
+The error information, if any, is
+
+    type PackageError struct {
+        ImportStack   []string // shortest path from package named on command line to this one
+        Pos           string   // position of error (if present, file:line:col)
+        Err           string   // the error itself
+    }
+
 The template function "join" calls strings.Join.
 
 The template function "context" returns the build context, defined as:
diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go
index 8ebde89..f9b979d 100644
--- a/src/cmd/go/main.go
+++ b/src/cmd/go/main.go
@@ -285,8 +285,8 @@ func printUsage(w io.Writer) {
 func usage() {
 	// special case "go test -h"
 	if len(os.Args) > 1 && os.Args[1] == "test" {
-		os.Stdout.WriteString(testUsage + "\n\n" +
-			strings.TrimSpace(testFlag1) + "\n\n" +
+		os.Stderr.WriteString(testUsage + "\n\n" +
+			strings.TrimSpace(testFlag1) + "\n\n\t" +
 			strings.TrimSpace(testFlag2) + "\n")
 		os.Exit(2)
 	}
@@ -353,7 +353,7 @@ func importPathsNoDotExpansion(args []string) []string {
 		} else {
 			a = path.Clean(a)
 		}
-		if a == "all" || a == "std" || a == "cmd" {
+		if isMetaPackage(a) {
 			out = append(out, allPackages(a)...)
 			continue
 		}
@@ -454,7 +454,9 @@ func envForDir(dir string, base []string) []string {
 
 // mergeEnvLists merges the two environment lists such that
 // variables with the same name in "in" replace those in "out".
+// This always returns a newly allocated slice.
 func mergeEnvLists(in, out []string) []string {
+	out = append([]string(nil), out...)
 NextVar:
 	for _, inkv := range in {
 		k := strings.SplitAfterN(inkv, "=", 2)[0]
@@ -524,6 +526,15 @@ func hasFilePathPrefix(s, prefix string) bool {
 	}
 }
 
+// expandPath returns the symlink-expanded form of path.
+func expandPath(p string) string {
+	x, err := filepath.EvalSymlinks(p)
+	if err == nil {
+		return x
+	}
+	return p
+}
+
 // treeCanMatchPattern(pattern)(name) reports whether
 // name or children of name can possibly match pattern.
 // Pattern is the same limited glob accepted by matchPattern.
@@ -554,7 +565,7 @@ func allPackages(pattern string) []string {
 func matchPackages(pattern string) []string {
 	match := func(string) bool { return true }
 	treeCanMatch := func(string) bool { return true }
-	if pattern != "all" && pattern != "std" && pattern != "cmd" {
+	if !isMetaPackage(pattern) {
 		match = matchPattern(pattern)
 		treeCanMatch = treeCanMatchPattern(pattern)
 	}
@@ -588,10 +599,9 @@ func matchPackages(pattern string) []string {
 			}
 
 			name := filepath.ToSlash(path[len(src):])
-			if pattern == "std" && (strings.Contains(name, ".") || name == "cmd") {
+			if pattern == "std" && (!isStandardImportPath(name) || name == "cmd") {
 				// The name "std" is only the standard library.
-				// If the name has a dot, assume it's a domain name for go get,
-				// and if the name is cmd, it's the root of the command tree.
+				// If the name is cmd, it's the root of the command tree.
 				return filepath.SkipDir
 			}
 			if !treeCanMatch(name) {
@@ -674,7 +684,14 @@ func matchPackagesInFS(pattern string) []string {
 		if !match(name) {
 			return nil
 		}
-		if _, err = build.ImportDir(path, 0); err != nil {
+
+		// We keep the directory if we can import it, or if we can't import it
+		// due to invalid Go source files. This means that directories containing
+		// parse errors will be built (and fail) instead of being silently skipped
+		// as not matching the pattern. Go 1.5 and earlier skipped, but that
+		// behavior means people miss serious mistakes.
+		// See golang.org/issue/11407.
+		if p, err := buildContext.ImportDir(path, 0); err != nil && (p == nil || len(p.InvalidGoFiles) == 0) {
 			if _, noGo := err.(*build.NoGoError); !noGo {
 				log.Print(err)
 			}
diff --git a/src/cmd/go/note.go b/src/cmd/go/note.go
index c7346a5..f846eeb 100644
--- a/src/cmd/go/note.go
+++ b/src/cmd/go/note.go
@@ -121,15 +121,26 @@ func readELFGoBuildID(filename string, f *os.File, data []byte) (buildid string,
 				return "", err
 			}
 		}
-		nameSize := ef.ByteOrder.Uint32(note)
-		valSize := ef.ByteOrder.Uint32(note[4:])
-		tag := ef.ByteOrder.Uint32(note[8:])
-		name := note[12:16]
-		if nameSize != 4 || 16+valSize > uint32(len(note)) || tag != elfGoBuildIDTag || !bytes.Equal(name, elfGoNote) {
-			continue
-		}
 
-		return string(note[16 : 16+valSize]), nil
+		filesz := p.Filesz
+		for filesz >= 16 {
+			nameSize := ef.ByteOrder.Uint32(note)
+			valSize := ef.ByteOrder.Uint32(note[4:])
+			tag := ef.ByteOrder.Uint32(note[8:])
+			name := note[12:16]
+			if nameSize == 4 && 16+valSize <= uint32(len(note)) && tag == elfGoBuildIDTag && bytes.Equal(name, elfGoNote) {
+				return string(note[16 : 16+valSize]), nil
+			}
+
+			nameSize = (nameSize + 3) &^ 3
+			valSize = (valSize + 3) &^ 3
+			notesz := uint64(12 + nameSize + valSize)
+			if filesz <= notesz {
+				break
+			}
+			filesz -= notesz
+			note = note[notesz:]
+		}
 	}
 
 	// No note. Treat as successful but build ID empty.
diff --git a/src/cmd/go/note_test.go b/src/cmd/go/note_test.go
index 31c83c7..811734b 100644
--- a/src/cmd/go/note_test.go
+++ b/src/cmd/go/note_test.go
@@ -6,6 +6,7 @@ package main_test
 
 import (
 	main "cmd/go"
+	"go/build"
 	"runtime"
 	"testing"
 )
@@ -28,9 +29,6 @@ func TestNoteReading2K(t *testing.T) {
 }
 
 func testNoteReading(t *testing.T) {
-	if runtime.GOOS == "dragonfly" {
-		t.Skipf("TestNoteReading is broken on dragonfly - golang.org/issue/13364", runtime.GOOS)
-	}
 	tg := testgo(t)
 	defer tg.cleanup()
 	tg.tempFile("hello.go", `package main; func main() { print("hello, world\n") }`)
@@ -44,23 +42,25 @@ func testNoteReading(t *testing.T) {
 		t.Fatalf("buildID in hello binary = %q, want %q", id, buildID)
 	}
 
-	if runtime.GOOS == "linux" && runtime.GOARCH == "ppc64le" {
-		t.Skipf("skipping - golang.org/issue/11184")
+	switch {
+	case !build.Default.CgoEnabled:
+		t.Skipf("skipping - no cgo, so assuming external linking not available")
+	case runtime.GOOS == "linux" && (runtime.GOARCH == "ppc64le" || runtime.GOARCH == "ppc64"):
+		t.Skipf("skipping - external linking not supported, golang.org/issue/11184")
+	case runtime.GOOS == "linux" && (runtime.GOARCH == "mips64le" || runtime.GOARCH == "mips64"):
+		t.Skipf("skipping - external linking not supported, golang.org/issue/12560")
+	case runtime.GOOS == "openbsd" && runtime.GOARCH == "arm":
+		t.Skipf("skipping - external linking not supported, golang.org/issue/10619")
+	case runtime.GOOS == "plan9":
+		t.Skipf("skipping - external linking not supported")
 	}
 
-	switch runtime.GOOS {
-	case "plan9":
-		// no external linking
-		t.Logf("no external linking - skipping linkmode=external test")
-
-	default:
-		tg.run("build", "-ldflags", "-buildid="+buildID+" -linkmode=external", "-o", tg.path("hello.exe"), tg.path("hello.go"))
-		id, err := main.ReadBuildIDFromBinary(tg.path("hello.exe"))
-		if err != nil {
-			t.Fatalf("reading build ID from hello binary (linkmode=external): %v", err)
-		}
-		if id != buildID {
-			t.Fatalf("buildID in hello binary = %q, want %q (linkmode=external)", id, buildID)
-		}
+	tg.run("build", "-ldflags", "-buildid="+buildID+" -linkmode=external", "-o", tg.path("hello.exe"), tg.path("hello.go"))
+	id, err = main.ReadBuildIDFromBinary(tg.path("hello.exe"))
+	if err != nil {
+		t.Fatalf("reading build ID from hello binary (linkmode=external): %v", err)
+	}
+	if id != buildID {
+		t.Fatalf("buildID in hello binary = %q, want %q (linkmode=external)", id, buildID)
 	}
 }
diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go
index e1d1ed4..0c0cf07 100644
--- a/src/cmd/go/pkg.go
+++ b/src/cmd/go/pkg.go
@@ -118,7 +118,7 @@ func (p *Package) vendored(imports []string) []string {
 	seen := make(map[string]bool)
 	var all []string
 	for _, path := range imports {
-		path, _ = vendoredImportPath(p, path)
+		path = vendoredImportPath(p, path)
 		if !seen[path] {
 			seen[path] = true
 			all = append(all, path)
@@ -153,7 +153,7 @@ func (p *Package) copyBuild(pp *build.Package) {
 	p.ConflictDir = pp.ConflictDir
 	// TODO? Target
 	p.Goroot = pp.Goroot
-	p.Standard = p.Goroot && p.ImportPath != "" && !strings.Contains(p.ImportPath, ".")
+	p.Standard = p.Goroot && p.ImportPath != "" && isStandardImportPath(p.ImportPath)
 	p.GoFiles = pp.GoFiles
 	p.CgoFiles = pp.CgoFiles
 	p.IgnoredGoFiles = pp.IgnoredGoFiles
@@ -177,6 +177,19 @@ func (p *Package) copyBuild(pp *build.Package) {
 	p.XTestImports = pp.XTestImports
 }
 
+// isStandardImportPath reports whether $GOROOT/src/path should be considered
+// part of the standard distribution. For historical reasons we allow people to add
+// their own code to $GOROOT instead of using $GOPATH, but we assume that
+// code will start with a domain name (dot in the first element).
+func isStandardImportPath(path string) bool {
+	i := strings.Index(path, "/")
+	if i < 0 {
+		i = len(path)
+	}
+	elem := path[:i]
+	return !strings.Contains(elem, ".")
+}
+
 // A PackageError describes an error loading information about a package.
 type PackageError struct {
 	ImportStack   []string // shortest path from package named on command line to this one
@@ -250,11 +263,14 @@ func reloadPackage(arg string, stk *importStack) *Package {
 	return loadPackage(arg, stk)
 }
 
-// The Go 1.5 vendoring experiment is enabled by setting GO15VENDOREXPERIMENT=1.
+// 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.
-var go15VendorExperiment = os.Getenv("GO15VENDOREXPERIMENT") == "1"
+// 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
@@ -310,11 +326,14 @@ func loadImport(path, srcDir string, parent *Package, stk *importStack, importPo
 	importPath := path
 	origPath := path
 	isLocal := build.IsLocalImport(path)
-	var vendorSearch []string
 	if isLocal {
 		importPath = dirToImportPath(filepath.Join(srcDir, path))
 	} else if mode&useVendor != 0 {
-		path, vendorSearch = vendoredImportPath(parent, path)
+		// We do our own vendor resolution, because we want to
+		// find out the key to use in packageCache without the
+		// overhead of repeated calls to buildContext.Import.
+		// The code is also needed in a few other places anyway.
+		path = vendoredImportPath(parent, path)
 		importPath = path
 	}
 
@@ -341,29 +360,12 @@ 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.
-	bp, err := buildContext.Import(path, srcDir, build.ImportComment)
-
-	// If we got an error from go/build about package not found,
-	// it contains the directories from $GOROOT and $GOPATH that
-	// were searched. Add to that message the vendor directories
-	// that were searched.
-	if err != nil && len(vendorSearch) > 0 {
-		// NOTE(rsc): The direct text manipulation here is fairly awful,
-		// but it avoids defining new go/build API (an exported error type)
-		// late in the Go 1.5 release cycle. If this turns out to be a more general
-		// problem we could define a real error type when the decision can be
-		// considered more carefully.
-		text := err.Error()
-		if strings.Contains(text, "cannot find package \"") && strings.Contains(text, "\" in any of:\n\t") {
-			old := strings.SplitAfter(text, "\n")
-			lines := []string{old[0]}
-			for _, dir := range vendorSearch {
-				lines = append(lines, "\t"+dir+" (vendor tree)\n")
-			}
-			lines = append(lines, old[1:]...)
-			err = errors.New(strings.Join(lines, ""))
-		}
+	buildMode := build.ImportComment
+	if !go15VendorExperiment || mode&useVendor == 0 || path != origPath {
+		// Not vendoring, or we already found the vendored path.
+		buildMode |= build.IgnoreVendor
 	}
+	bp, err := buildContext.Import(path, srcDir, buildMode)
 	bp.ImportPath = importPath
 	if gobin != "" {
 		bp.BinDir = gobin
@@ -373,7 +375,7 @@ func loadImport(path, srcDir string, parent *Package, stk *importStack, importPo
 		err = fmt.Errorf("code in directory %s expects import %q", bp.Dir, bp.ImportComment)
 	}
 	p.load(stk, bp, err)
-	if p.Error != nil && len(importPos) > 0 {
+	if p.Error != nil && p.Error.Pos == "" && len(importPos) > 0 {
 		pos := importPos[0]
 		pos.Filename = shortPath(pos.Filename)
 		p.Error.Pos = pos.String()
@@ -407,20 +409,24 @@ func isDir(path string) bool {
 
 // vendoredImportPath returns the expansion of path when it appears in parent.
 // If parent is x/y/z, then path might expand to x/y/z/vendor/path, x/y/vendor/path,
-// x/vendor/path, vendor/path, or else stay x/y/z if none of those exist.
+// 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.
-// If no expansion is found, vendoredImportPath also returns a list of vendor directories
-// it searched along the way, to help prepare a useful error message should path turn
-// out not to exist.
-func vendoredImportPath(parent *Package, path string) (found string, searched []string) {
+func vendoredImportPath(parent *Package, path string) (found string) {
 	if parent == nil || parent.Root == "" || !go15VendorExperiment {
-		return path, nil
+		return path
 	}
+
 	dir := filepath.Clean(parent.Dir)
 	root := filepath.Join(parent.Root, "src")
+	if !hasFilePathPrefix(dir, root) {
+		// Look for symlinks before reporting error.
+		dir = expandPath(dir)
+		root = expandPath(root)
+	}
 	if !hasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator {
 		fatalf("invalid vendoredImportPath: dir=%q root=%q separator=%q", dir, root, string(filepath.Separator))
 	}
+
 	vpath := "vendor/" + path
 	for i := len(dir); i >= len(root); i-- {
 		if i < len(dir) && dir[i] != filepath.Separator {
@@ -434,7 +440,7 @@ func vendoredImportPath(parent *Package, path string) (found string, searched []
 			continue
 		}
 		targ := filepath.Join(dir[:i], vpath)
-		if isDir(targ) {
+		if isDir(targ) && hasGoFiles(targ) {
 			// We started with parent's dir c:\gopath\src\foo\bar\baz\quux\xyzzy.
 			// We know the import path for parent's dir.
 			// We chopped off some number of path elements and
@@ -449,14 +455,26 @@ func vendoredImportPath(parent *Package, path string) (found string, searched []
 				// and found c:\gopath\src\vendor\path.
 				// We chopped \foo\bar (length 8) but the import path is "foo/bar" (length 7).
 				// Use "vendor/path" without any prefix.
-				return vpath, nil
+				return vpath
 			}
-			return parent.ImportPath[:len(parent.ImportPath)-chopped] + "/" + vpath, nil
+			return parent.ImportPath[:len(parent.ImportPath)-chopped] + "/" + vpath
+		}
+	}
+	return path
+}
+
+// hasGoFiles reports whether dir contains any files with names ending in .go.
+// For a vendor check we must exclude directories that contain no .go files.
+// Otherwise it is not possible to vendor just a/b/c and still import the
+// non-vendored a/b. See golang.org/issue/13832.
+func hasGoFiles(dir string) bool {
+	fis, _ := ioutil.ReadDir(dir)
+	for _, fi := range fis {
+		if !fi.IsDir() && strings.HasSuffix(fi.Name(), ".go") {
+			return true
 		}
-		// Note the existence of a vendor directory in case path is not found anywhere.
-		searched = append(searched, targ)
 	}
-	return path, searched
+	return false
 }
 
 // reusePackage reuses package p to satisfy the import at the top
@@ -518,7 +536,14 @@ func disallowInternal(srcDir string, p *Package, stk *importStack) *Package {
 		i-- // rewind over slash in ".../internal"
 	}
 	parent := p.Dir[:i+len(p.Dir)-len(p.ImportPath)]
-	if hasPathPrefix(filepath.ToSlash(srcDir), filepath.ToSlash(parent)) {
+	if hasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {
+		return p
+	}
+
+	// Look for symlinks before reporting error.
+	srcDir = expandPath(srcDir)
+	parent = expandPath(parent)
+	if hasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {
 		return p
 	}
 
@@ -615,7 +640,14 @@ func disallowVendorVisibility(srcDir string, p *Package, stk *importStack) *Pack
 		return p
 	}
 	parent := p.Dir[:truncateTo]
-	if hasPathPrefix(filepath.ToSlash(srcDir), filepath.ToSlash(parent)) {
+	if hasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {
+		return p
+	}
+
+	// Look for symlinks before reporting error.
+	srcDir = expandPath(srcDir)
+	parent = expandPath(parent)
+	if hasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {
 		return p
 	}
 
@@ -708,6 +740,7 @@ func expandScanner(err error) error {
 
 var raceExclude = map[string]bool{
 	"runtime/race": true,
+	"runtime/msan": true,
 	"runtime/cgo":  true,
 	"cmd/cgo":      true,
 	"syscall":      true,
@@ -721,6 +754,7 @@ var cgoExclude = map[string]bool{
 var cgoSyscallExclude = map[string]bool{
 	"runtime/cgo":  true,
 	"runtime/race": true,
+	"runtime/msan": true,
 }
 
 // load populates p using information from bp, err, which should
@@ -821,27 +855,40 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
 		importPaths = append(importPaths, "syscall")
 	}
 
-	// Currently build mode c-shared, or -linkshared, forces
+	// Currently build modes c-shared, pie, and -linkshared force
 	// external linking mode, and external linking mode forces an
 	// import of runtime/cgo.
-	if p.Name == "main" && !p.Goroot && (buildBuildmode == "c-shared" || buildLinkshared) {
+	if p.Name == "main" && !p.Goroot && (buildBuildmode == "c-shared" || buildBuildmode == "pie" || buildLinkshared) {
 		importPaths = append(importPaths, "runtime/cgo")
 	}
 
-	// Everything depends on runtime, except runtime and unsafe.
-	if !p.Standard || (p.ImportPath != "runtime" && p.ImportPath != "unsafe") {
+	// Everything depends on runtime, except runtime, its internal
+	// subpackages, and unsafe.
+	if !p.Standard || (p.ImportPath != "runtime" && !strings.HasPrefix(p.ImportPath, "runtime/internal/") && p.ImportPath != "unsafe") {
 		importPaths = append(importPaths, "runtime")
 		// When race detection enabled everything depends on runtime/race.
 		// Exclude certain packages to avoid circular dependencies.
 		if buildRace && (!p.Standard || !raceExclude[p.ImportPath]) {
 			importPaths = append(importPaths, "runtime/race")
 		}
+		// MSan uses runtime/msan.
+		if buildMSan && (!p.Standard || !raceExclude[p.ImportPath]) {
+			importPaths = append(importPaths, "runtime/msan")
+		}
 		// On ARM with GOARM=5, everything depends on math for the link.
 		if p.Name == "main" && goarch == "arm" {
 			importPaths = append(importPaths, "math")
 		}
 	}
 
+	// Runtime and its internal packages depend on runtime/internal/sys,
+	// so that they pick up the generated zversion.go file.
+	// This can be an issue particularly for runtime/internal/atomic;
+	// see issue 13655.
+	if p.Standard && (p.ImportPath == "runtime" || strings.HasPrefix(p.ImportPath, "runtime/internal/")) && p.ImportPath != "runtime/internal/sys" {
+		importPaths = append(importPaths, "runtime/internal/sys")
+	}
+
 	// Build list of full paths to all Go files in the package,
 	// for use by commands like go fmt.
 	p.gofiles = stringList(p.GoFiles, p.CgoFiles, p.TestGoFiles, p.XTestGoFiles)
@@ -920,6 +967,17 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
 				}
 			}
 		}
+		if p.Standard && p.Error == nil && !p1.Standard && p1.Error == nil {
+			p.Error = &PackageError{
+				ImportStack: stk.copy(),
+				Err:         fmt.Sprintf("non-standard import %q in standard package %q", path, p.ImportPath),
+			}
+			pos := p.build.ImportPos[path]
+			if len(pos) > 0 {
+				p.Error.Pos = pos[0].String()
+			}
+		}
+
 		path = p1.ImportPath
 		importPaths[i] = path
 		if i < len(p.Imports) {
@@ -1484,11 +1542,14 @@ func computeBuildID(p *Package) {
 		fmt.Fprintf(h, "file %s\n", file)
 	}
 
-	// Include the content of runtime/zversion.go in the hash
+	// Include the content of runtime/internal/sys/zversion.go in the hash
 	// for package runtime. This will give package runtime a
 	// different build ID in each Go release.
-	if p.Standard && p.ImportPath == "runtime" {
-		data, _ := ioutil.ReadFile(filepath.Join(p.Dir, "zversion.go"))
+	if p.Standard && p.ImportPath == "runtime/internal/sys" {
+		data, err := ioutil.ReadFile(filepath.Join(p.Dir, "zversion.go"))
+		if err != nil {
+			fatalf("go: %s", err)
+		}
 		fmt.Fprintf(h, "zversion %q\n", string(data))
 	}
 
@@ -1602,15 +1663,24 @@ func packagesAndErrors(args []string) []*Package {
 	}
 
 	args = importPaths(args)
-	var pkgs []*Package
-	var stk importStack
-	var set = make(map[string]bool)
+	var (
+		pkgs    []*Package
+		stk     importStack
+		seenArg = make(map[string]bool)
+		seenPkg = make(map[*Package]bool)
+	)
 
 	for _, arg := range args {
-		if !set[arg] {
-			pkgs = append(pkgs, loadPackage(arg, &stk))
-			set[arg] = true
+		if seenArg[arg] {
+			continue
 		}
+		seenArg[arg] = true
+		pkg := loadPackage(arg, &stk)
+		if seenPkg[pkg] {
+			continue
+		}
+		seenPkg[pkg] = true
+		pkgs = append(pkgs, pkg)
 	}
 	computeStale(pkgs...)
 
diff --git a/src/cmd/go/pkg_test.go b/src/cmd/go/pkg_test.go
index 06b9f0a..1e7ca2c 100644
--- a/src/cmd/go/pkg_test.go
+++ b/src/cmd/go/pkg_test.go
@@ -5,6 +5,9 @@
 package main
 
 import (
+	"io/ioutil"
+	"os"
+	"path/filepath"
 	"reflect"
 	"strings"
 	"testing"
@@ -57,6 +60,15 @@ var parseMetaGoImportsTests = []struct {
 		<body>`,
 		[]metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}},
 	},
+	{
+		`<!doctype html><meta name="go-import" content="foo/bar git https://github.com/rsc/foo/bar">`,
+		[]metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}},
+	},
+	{
+		// XML doesn't like <div style=position:relative>.
+		`<!doctype html><title>Page Not Found</title><meta name=go-import content="chitin.io/chitin git https://github.com/chitin-io/chitin"><div style=position:relative>DRAFT</div>`,
+		[]metaImport{{"chitin.io/chitin", "git", "https://github.com/chitin-io/chitin"}},
+	},
 }
 
 func TestParseMetaGoImports(t *testing.T) {
@@ -71,3 +83,109 @@ func TestParseMetaGoImports(t *testing.T) {
 		}
 	}
 }
+
+func TestSharedLibName(t *testing.T) {
+	// TODO(avdva) - make these values platform-specific
+	prefix := "lib"
+	suffix := ".so"
+	testData := []struct {
+		args      []string
+		pkgs      []*Package
+		expected  string
+		expectErr bool
+		rootedAt  string
+	}{
+		{
+			args:     []string{"std"},
+			pkgs:     []*Package{},
+			expected: "std",
+		},
+		{
+			args:     []string{"std", "cmd"},
+			pkgs:     []*Package{},
+			expected: "std,cmd",
+		},
+		{
+			args:     []string{},
+			pkgs:     []*Package{&Package{ImportPath: "gopkg.in/somelib"}},
+			expected: "gopkg.in-somelib",
+		},
+		{
+			args:     []string{"./..."},
+			pkgs:     []*Package{&Package{ImportPath: "somelib"}},
+			expected: "somelib",
+			rootedAt: "somelib",
+		},
+		{
+			args:     []string{"../somelib", "../somelib"},
+			pkgs:     []*Package{&Package{ImportPath: "somelib"}},
+			expected: "somelib",
+		},
+		{
+			args:     []string{"../lib1", "../lib2"},
+			pkgs:     []*Package{&Package{ImportPath: "gopkg.in/lib1"}, &Package{ImportPath: "gopkg.in/lib2"}},
+			expected: "gopkg.in-lib1,gopkg.in-lib2",
+		},
+		{
+			args: []string{"./..."},
+			pkgs: []*Package{
+				&Package{ImportPath: "gopkg.in/dir/lib1"},
+				&Package{ImportPath: "gopkg.in/lib2"},
+				&Package{ImportPath: "gopkg.in/lib3"},
+			},
+			expected: "gopkg.in",
+			rootedAt: "gopkg.in",
+		},
+		{
+			args:      []string{"std", "../lib2"},
+			pkgs:      []*Package{},
+			expectErr: true,
+		},
+		{
+			args:      []string{"all", "./"},
+			pkgs:      []*Package{},
+			expectErr: true,
+		},
+		{
+			args:      []string{"cmd", "fmt"},
+			pkgs:      []*Package{},
+			expectErr: true,
+		},
+	}
+	for _, data := range testData {
+		func() {
+			if data.rootedAt != "" {
+				tmpGopath, err := ioutil.TempDir("", "gopath")
+				if err != nil {
+					t.Fatal(err)
+				}
+				oldGopath := buildContext.GOPATH
+				defer func() {
+					os.RemoveAll(tmpGopath)
+					buildContext.GOPATH = oldGopath
+					os.Chdir(cwd)
+				}()
+				root := filepath.Join(tmpGopath, "src", data.rootedAt)
+				err = os.MkdirAll(root, 0755)
+				if err != nil {
+					t.Fatal(err)
+				}
+				buildContext.GOPATH = tmpGopath
+				os.Chdir(root)
+			}
+			computed, err := libname(data.args, data.pkgs)
+			if err != nil {
+				if !data.expectErr {
+					t.Errorf("libname returned an error %q, expected a name", err.Error())
+				}
+			} else if data.expectErr {
+				t.Errorf("libname returned %q, expected an error", computed)
+			} else {
+				expected := prefix + data.expected + suffix
+				if expected != computed {
+					t.Errorf("libname returned %q, expected %q", computed, expected)
+				}
+			}
+		}()
+	}
+}
diff --git a/src/cmd/go/run.go b/src/cmd/go/run.go
index f6da373..bf10f4f 100644
--- a/src/cmd/go/run.go
+++ b/src/cmd/go/run.go
@@ -64,7 +64,7 @@ func printStderr(args ...interface{}) (int, error) {
 }
 
 func runRun(cmd *Command, args []string) {
-	raceInit()
+	instrumentInit()
 	buildModeInit()
 	var b builder
 	b.init()
@@ -89,8 +89,18 @@ func runRun(cmd *Command, args []string) {
 		fatalf("%s", p.Error)
 	}
 	p.omitDWARF = true
-	for _, err := range p.DepsErrors {
-		errorf("%s", err)
+	if len(p.DepsErrors) > 0 {
+		// Since these are errors in dependencies,
+		// the same error might show up multiple times,
+		// once in each package that depends on it.
+		// Only print each once.
+		printed := map[*PackageError]bool{}
+		for _, err := range p.DepsErrors {
+			if !printed[err] {
+				printed[err] = true
+				errorf("%s", err)
+			}
+		}
 	}
 	exitIfErrors()
 	if p.Name != "main" {
diff --git a/src/cmd/go/test.go b/src/cmd/go/test.go
index ba1ab82..995ba14 100644
--- a/src/cmd/go/test.go
+++ b/src/cmd/go/test.go
@@ -13,7 +13,6 @@ import (
 	"go/doc"
 	"go/parser"
 	"go/token"
-	"log"
 	"os"
 	"os/exec"
 	"path"
@@ -33,7 +32,7 @@ func init() {
 	cmdTest.Run = runTest
 }
 
-const testUsage = "test [-c] [-i] [build and test flags] [packages] [flags for test binary]"
+const testUsage = "test [build/test flags] [packages] [build/test flags & test binary flags]"
 
 var cmdTest = &Command{
 	CustomFlags: true,
@@ -68,11 +67,6 @@ non-test installation.
 
 ` + strings.TrimSpace(testFlag1) + ` See 'go help testflag' for details.
 
-If the test binary needs any other flags, they should be presented after the
-package names. The go tool treats as a flag the first argument that begins with
-a minus sign that it does not recognize itself; that argument and all subsequent
-arguments are passed as arguments to the test binary.
-
 For more about build flags, see 'go help build'.
 For more about specifying packages, see 'go help packages'.
 
@@ -83,10 +77,16 @@ See also: go build, go vet.
 const testFlag1 = `
 In addition to the build flags, the flags handled by 'go test' itself are:
 
+	-args
+	    Pass the remainder of the command line (everything after -args)
+	    to the test binary, uninterpreted and unchanged.
+	    Because this flag consumes the remainder of the command line,
+	    the package list (if present) must appear before this flag.
+
 	-c
-		Compile the test binary to pkg.test but do not run it
-		(where pkg is the last element of the package's import path).
-		The file name can be changed with the -o flag.
+	    Compile the test binary to pkg.test but do not run it
+	    (where pkg is the last element of the package's import path).
+	    The file name can be changed with the -o flag.
 
 	-exec xprog
 	    Run the test binary using xprog. The behavior is the same as
@@ -97,8 +97,8 @@ In addition to the build flags, the flags handled by 'go test' itself are:
 	    Do not run the test.
 
 	-o file
-		Compile the test binary to the named file.
-		The test still runs (unless -c or -i is specified).
+	    Compile the test binary to the named file.
+	    The test still runs (unless -c or -i is specified).
 
 The test binary also accepts flags that control execution of the test; these
 flags are also accessible by 'go test'.
@@ -207,6 +207,10 @@ const testFlag2 = `
 	    Allow parallel execution of test functions that call t.Parallel.
 	    The value of this flag is the maximum number of tests to run
 	    simultaneously; by default, it is set to the value of GOMAXPROCS.
+	    Note that -parallel only applies within a single test binary.
+	    The 'go test' command may run tests for different packages
+	    in parallel as well, according to the setting of the -p flag
+	    (see 'go help build').
 
 	-run regexp
 	    Run only those tests and examples matching the regular
@@ -230,25 +234,63 @@ const testFlag2 = `
 	    Verbose output: log all tests as they are run. Also print all
 	    text from Log and Logf calls even if the test succeeds.
 
-The test binary, called pkg.test where pkg is the name of the
-directory containing the package sources, can be invoked directly
-after building it with 'go test -c'. When invoking the test binary
-directly, each of the standard flag names must be prefixed with 'test.',
-as in -test.run=TestMyFunc or -test.v.
+Each of these flags is also recognized with an optional 'test.' prefix,
+as in -test.v. When invoking the generated test binary (the result of
+'go test -c') directly, however, the prefix is mandatory.
+
+The 'go test' command rewrites or removes recognized flags,
+as appropriate, both before and after the optional package list,
+before invoking the test binary.
 
-When running 'go test', flags not listed above are passed through
-unaltered. For instance, the command
+For instance, the command
 
-	go test -x -v -cpuprofile=prof.out -dir=testdata -update
+	go test -v -myflag testdata -cpuprofile=prof.out -x
 
 will compile the test binary and then run it as
 
-	pkg.test -test.v -test.cpuprofile=prof.out -dir=testdata -update
+	pkg.test -test.v -myflag testdata -test.cpuprofile=prof.out
+
+(The -x flag is removed because it applies only to the go command's
+execution, not to the test itself.)
 
 The test flags that generate profiles (other than for coverage) also
 leave the test binary in pkg.test for use when analyzing the profiles.
 
-Flags not recognized by 'go test' must be placed after any specified packages.
+When 'go test' runs a test binary, it does so from within the 
+corresponding package's source code directory. Depending on the test,
+it may be necessary to do the same when invoking a generated test
+binary directly.
+
+The command-line package list, if present, must appear before any
+flag not known to the go test command. Continuing the example above,
+the package list would have to appear before -myflag, but could appear
+on either side of -v.
+
+To keep an argument for a test binary from being interpreted as a
+known flag or a package name, use -args (see 'go help test') which
+passes the remainder of the command line through to the test binary
+uninterpreted and unaltered.
+
+For instance, the command
+
+	go test -v -args -x -v
+
+will compile the test binary and then run it as
+
+	pkg.test -test.v -x -v
+
+Similarly,
+
+	go test -args math
+
+will compile the test binary and then run it as
+
+	pkg.test math
+
+In the first example, the -x and the second -v are passed through to the
+test binary unchanged and with no effect on the go command itself.
+In the second example, the argument math is passed through to the test
+binary, instead of being interpreted as the package list.
 `
 
 var helpTestfunc = &Command{
@@ -328,7 +370,7 @@ func runTest(cmd *Command, args []string) {
 
 	findExecCmd() // initialize cached result
 
-	raceInit()
+	instrumentInit()
 	buildModeInit()
 	pkgs := packagesForBuild(pkgArgs)
 	if len(pkgs) == 0 {
@@ -396,7 +438,7 @@ func runTest(cmd *Command, args []string) {
 		if deps["C"] {
 			delete(deps, "C")
 			deps["runtime/cgo"] = true
-			if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace {
+			if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace && !buildMSan {
 				deps["cmd/cgo"] = true
 			}
 		}
@@ -439,7 +481,7 @@ func runTest(cmd *Command, args []string) {
 		}
 		for _, p := range testCoverPkgs {
 			if !used[p.ImportPath] {
-				log.Printf("warning: no packages being tested depend on %s", p.ImportPath)
+				fmt.Fprintf(os.Stderr, "warning: no packages being tested depend on %s\n", p.ImportPath)
 			}
 		}
 
@@ -544,6 +586,9 @@ func runTest(cmd *Command, args []string) {
 		if buildRace {
 			extraOpts = "-race "
 		}
+		if buildMSan {
+			extraOpts = "-msan "
+		}
 		fmt.Fprintf(os.Stderr, "installing these packages with 'go test %s-i%s' will speed future tests.\n\n", extraOpts, args)
 	}
 
@@ -817,10 +862,12 @@ func (b *builder) test(p *Package) (buildAction, runAction, printAction *action,
 		}
 	}
 
-	// writeTestmain writes _testmain.go. This must happen after recompileForTest,
-	// because recompileForTest modifies XXX.
-	if err := writeTestmain(filepath.Join(testDir, "_testmain.go"), t); err != nil {
-		return nil, nil, nil, err
+	if !buildN {
+		// writeTestmain writes _testmain.go. This must happen after recompileForTest,
+		// because recompileForTest modifies XXX.
+		if err := writeTestmain(filepath.Join(testDir, "_testmain.go"), t); err != nil {
+			return nil, nil, nil, err
+		}
 	}
 
 	computeStale(pmain)
diff --git a/src/cmd/go/testdata/flag_test.go b/src/cmd/go/testdata/flag_test.go
new file mode 100644
index 0000000..ddf613d
--- /dev/null
+++ b/src/cmd/go/testdata/flag_test.go
@@ -0,0 +1,16 @@
+package flag_test
+
+import (
+	"flag"
+	"log"
+	"testing"
+)
+
+var v = flag.Int("v", 0, "v flag")
+
+// Run this as go test pkg -v=7
+func TestVFlagIsSet(t *testing.T) {
+	if *v != 7 {
+		log.Fatal("v flag not set")
+	}
+}
diff --git a/src/cmd/go/testdata/src/run/bad.go b/src/cmd/go/testdata/src/run/bad.go
new file mode 100644
index 0000000..c1cc3ac
--- /dev/null
+++ b/src/cmd/go/testdata/src/run/bad.go
@@ -0,0 +1,5 @@
+package main
+
+import _ "run/subdir/internal/private"
+
+func main() {}
diff --git a/src/cmd/go/testdata/src/run/good.go b/src/cmd/go/testdata/src/run/good.go
new file mode 100644
index 0000000..0b67dce
--- /dev/null
+++ b/src/cmd/go/testdata/src/run/good.go
@@ -0,0 +1,5 @@
+package main
+
+import _ "run/internal"
+
+func main() {}
diff --git a/src/cmd/go/testdata/src/run/internal/internal.go b/src/cmd/go/testdata/src/run/internal/internal.go
new file mode 100644
index 0000000..5bf0569
--- /dev/null
+++ b/src/cmd/go/testdata/src/run/internal/internal.go
@@ -0,0 +1 @@
+package internal
diff --git a/src/cmd/go/testdata/src/run/subdir/internal/private/private.go b/src/cmd/go/testdata/src/run/subdir/internal/private/private.go
new file mode 100644
index 0000000..735e4dc
--- /dev/null
+++ b/src/cmd/go/testdata/src/run/subdir/internal/private/private.go
@@ -0,0 +1 @@
+package private
diff --git a/src/cmd/go/testdata/src/vend/dir1/dir1.go b/src/cmd/go/testdata/src/vend/dir1/dir1.go
new file mode 100644
index 0000000..b719ead
--- /dev/null
+++ b/src/cmd/go/testdata/src/vend/dir1/dir1.go
@@ -0,0 +1 @@
+package dir1
diff --git a/src/cmd/go/testdata/src/vend/hello/hello_test.go b/src/cmd/go/testdata/src/vend/hello/hello_test.go
index 5e72ada..7190f59 100644
--- a/src/cmd/go/testdata/src/vend/hello/hello_test.go
+++ b/src/cmd/go/testdata/src/vend/hello/hello_test.go
@@ -7,6 +7,6 @@ import (
 
 func TestMsgInternal(t *testing.T) {
 	if strings.Msg != "hello, world" {
-		t.Fatal("unexpected msg: %v", strings.Msg)
+		t.Fatalf("unexpected msg: %v", strings.Msg)
 	}
 }
diff --git a/src/cmd/go/testdata/src/vend/hello/hellox_test.go b/src/cmd/go/testdata/src/vend/hello/hellox_test.go
index 96e6049..3f2165b 100644
--- a/src/cmd/go/testdata/src/vend/hello/hellox_test.go
+++ b/src/cmd/go/testdata/src/vend/hello/hellox_test.go
@@ -7,6 +7,6 @@ import (
 
 func TestMsgExternal(t *testing.T) {
 	if strings.Msg != "hello, world" {
-		t.Fatal("unexpected msg: %v", strings.Msg)
+		t.Fatalf("unexpected msg: %v", strings.Msg)
 	}
 }
diff --git a/src/cmd/go/testdata/src/vend/vendor/vend/dir1/dir2/dir2.go b/src/cmd/go/testdata/src/vend/vendor/vend/dir1/dir2/dir2.go
new file mode 100644
index 0000000..6fe35e9
--- /dev/null
+++ b/src/cmd/go/testdata/src/vend/vendor/vend/dir1/dir2/dir2.go
@@ -0,0 +1 @@
+package dir2
diff --git a/src/cmd/go/testdata/src/vend/x/x.go b/src/cmd/go/testdata/src/vend/x/x.go
index ae526eb..bdcde57 100644
--- a/src/cmd/go/testdata/src/vend/x/x.go
+++ b/src/cmd/go/testdata/src/vend/x/x.go
@@ -3,3 +3,5 @@ package x
 import _ "p"
 import _ "q"
 import _ "r"
+import _ "vend/dir1"      // not vendored
+import _ "vend/dir1/dir2" // vendored
diff --git a/src/cmd/go/testflag.go b/src/cmd/go/testflag.go
index 1f3e3d3..873df1f 100644
--- a/src/cmd/go/testflag.go
+++ b/src/cmd/go/testflag.go
@@ -87,6 +87,7 @@ func init() {
 func testFlags(args []string) (packageNames, passToTest []string) {
 	inPkg := false
 	outputDir := ""
+	var explicitArgs []string
 	for i := 0; i < len(args); i++ {
 		if !strings.HasPrefix(args[i], "-") {
 			if !inPkg && packageNames == nil {
@@ -114,6 +115,12 @@ func testFlags(args []string) (packageNames, passToTest []string) {
 				// make non-nil: we have seen the empty package list
 				packageNames = []string{}
 			}
+			if args[i] == "-args" || args[i] == "--args" {
+				// -args or --args signals that everything that follows
+				// should be passed to the test.
+				explicitArgs = args[i+1:]
+				break
+			}
 			passToTest = append(passToTest, args[i])
 			continue
 		}
@@ -191,6 +198,8 @@ func testFlags(args []string) (packageNames, passToTest []string) {
 		}
 		passToTest = append(passToTest, "-test.outputdir", dir)
 	}
+
+	passToTest = append(passToTest, explicitArgs...)
 	return
 }
 
diff --git a/src/cmd/go/tool.go b/src/cmd/go/tool.go
index 937ca1f..9ff0dcf 100644
--- a/src/cmd/go/tool.go
+++ b/src/cmd/go/tool.go
@@ -98,6 +98,7 @@ func runTool(cmd *Command, args []string) {
 		fmt.Printf("%s\n", cmd)
 		return
 	}
+	args[0] = toolPath // in case the tool wants to re-exec itself, e.g. cmd/dist
 	toolCmd := &exec.Cmd{
 		Path:   toolPath,
 		Args:   args,
diff --git a/src/cmd/go/vcs.go b/src/cmd/go/vcs.go
index 28a7540..342edee 100644
--- a/src/cmd/go/vcs.go
+++ b/src/cmd/go/vcs.go
@@ -122,7 +122,7 @@ var vcsGit = &vcsCmd{
 	name: "Git",
 	cmd:  "git",
 
-	createCmd:   []string{"clone {repo} {dir}", "--git-dir={dir}/.git submodule update --init --recursive"},
+	createCmd:   []string{"clone {repo} {dir}", "-go-internal-cd {dir} submodule update --init --recursive"},
 	downloadCmd: []string{"pull --ff-only", "submodule update --init --recursive"},
 
 	tagCmd: []tagCmd{
@@ -137,8 +137,9 @@ var vcsGit = &vcsCmd{
 	// both createCmd and downloadCmd update the working dir.
 	// No need to do more here. We used to 'checkout master'
 	// but that doesn't work if the default branch is not named master.
+	// DO NOT add 'checkout master' here.
 	// See golang.org/issue/9032.
-	tagSyncDefault: []string{"checkout master", "submodule update --init --recursive"},
+	tagSyncDefault: []string{"submodule update --init --recursive"},
 
 	scheme:     []string{"git", "https", "http", "git+ssh", "ssh"},
 	pingCmd:    "ls-remote {scheme}://{repo}",
@@ -334,6 +335,15 @@ func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool)
 		args[i] = expand(m, arg)
 	}
 
+	if len(args) >= 2 && args[0] == "-go-internal-cd" {
+		if filepath.IsAbs(args[1]) {
+			dir = args[1]
+		} else {
+			dir = filepath.Join(dir, args[1])
+		}
+		args = args[2:]
+	}
+
 	_, err := exec.LookPath(v.cmd)
 	if err != nil {
 		fmt.Fprintf(os.Stderr,
@@ -385,9 +395,6 @@ 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 {
-	if err := v.fixDetachedHead(dir); err != nil {
-		return err
-	}
 	for _, cmd := range v.downloadCmd {
 		if !go15VendorExperiment && strings.Contains(cmd, "submodule") {
 			continue
@@ -399,30 +406,6 @@ func (v *vcsCmd) download(dir string) error {
 	return nil
 }
 
-// fixDetachedHead switches a Git repository in dir from a detached head to the master branch.
-// Go versions before 1.2 downloaded Git repositories in an unfortunate way
-// that resulted in the working tree state being on a detached head.
-// That meant the repository was not usable for normal Git operations.
-// Go 1.2 fixed that, but we can't pull into a detached head, so if this is
-// a Git repository we check for being on a detached head and switch to the
-// real branch, almost always called "master".
-// TODO(dsymonds): Consider removing this for Go 1.3.
-func (v *vcsCmd) fixDetachedHead(dir string) error {
-	if v != vcsGit {
-		return nil
-	}
-
-	// "git symbolic-ref HEAD" succeeds iff we are not on a detached head.
-	if err := v.runVerboseOnly(dir, "symbolic-ref HEAD"); err == nil {
-		// not on a detached head
-		return nil
-	}
-	if buildV {
-		log.Printf("%s on detached head; repairing", dir)
-	}
-	return v.run(dir, "checkout master")
-}
-
 // tags returns the list of available tags for the repo in dir.
 func (v *vcsCmd) tags(dir string) ([]string, error) {
 	var tags []string
@@ -567,16 +550,8 @@ func repoRootForImportPath(importPath string, security securityMode) (*repoRoot,
 			lookup = lookup[:i]
 		}
 		rr, err = repoRootForImportDynamic(lookup, security)
-
-		// repoRootForImportDynamic returns error detail
-		// that is irrelevant if the user didn't intend to use a
-		// dynamic import in the first place.
-		// Squelch it.
 		if err != nil {
-			if buildV {
-				log.Printf("import %q: %v", importPath, err)
-			}
-			err = fmt.Errorf("unrecognized import path %q", importPath)
+			err = fmt.Errorf("unrecognized import path %q (%v)", importPath, err)
 		}
 	}
 	if err != nil {
@@ -891,7 +866,7 @@ var vcsPaths = []*vcsPath{
 	// General syntax for any server.
 	// Must be last.
 	{
-		re:   `^(?P<root>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?/[A-Za-z0-9_.\-/]*?)\.(?P<vcs>bzr|git|hg|svn))(/[A-Za-z0-9_.\-]+)*$`,
+		re:   `^(?P<root>(?P<repo>([a-z0-9.\-]+\.)+[a-z0-9.\-]+(:[0-9]+)?(/~?[A-Za-z0-9_.\-]+)+?)\.(?P<vcs>bzr|git|hg|svn))(/~?[A-Za-z0-9_.\-]+)*$`,
 		ping: true,
 	},
 }
diff --git a/src/cmd/go/vcs_test.go b/src/cmd/go/vcs_test.go
index f5d5e4f..a90c206 100644
--- a/src/cmd/go/vcs_test.go
+++ b/src/cmd/go/vcs_test.go
@@ -18,14 +18,14 @@ func TestRepoRootForImportPath(t *testing.T) {
 		path string
 		want *repoRoot
 	}{
-		{
+		/*{
 			"code.google.com/p/go",
 			&repoRoot{
 				vcs:  vcsHg,
 				repo: "https://code.google.com/p/go",
 			},
 		},
-		/*{
+		{
 		        "code.google.com/r/go",
 		        &repoRoot{
 		                vcs:  vcsHg,
diff --git a/src/cmd/go/vendor_test.go b/src/cmd/go/vendor_test.go
index 1e8cf9c..006a8c9 100644
--- a/src/cmd/go/vendor_test.go
+++ b/src/cmd/go/vendor_test.go
@@ -24,12 +24,14 @@ func TestVendorImports(t *testing.T) {
 	tg.run("list", "-f", "{{.ImportPath}} {{.Imports}}", "vend/...")
 	want := `
 		vend [vend/vendor/p r]
+		vend/dir1 []
 		vend/hello [fmt vend/vendor/strings]
 		vend/subdir [vend/vendor/p r]
 		vend/vendor/p []
 		vend/vendor/q []
 		vend/vendor/strings []
-		vend/x [vend/x/vendor/p vend/vendor/q vend/x/vendor/r]
+		vend/vendor/vend/dir1/dir2 []
+		vend/x [vend/x/vendor/p vend/vendor/q vend/x/vendor/r vend/dir1 vend/vendor/vend/dir1/dir2]
 		vend/x/invalid [vend/x/invalid/vendor/foo]
 		vend/x/vendor/p []
 		vend/x/vendor/p/p [notfound]
@@ -45,6 +47,14 @@ func TestVendorImports(t *testing.T) {
 	}
 }
 
+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")
+}
+
 func TestVendorRun(t *testing.T) {
 	tg := testgo(t)
 	defer tg.cleanup()
@@ -102,7 +112,7 @@ func TestVendorImportError(t *testing.T) {
 
 	re := regexp.MustCompile(`cannot find package "notfound" in any of:
 	.*[\\/]testdata[\\/]src[\\/]vend[\\/]x[\\/]vendor[\\/]notfound \(vendor tree\)
-	.*[\\/]testdata[\\/]src[\\/]vend[\\/]vendor[\\/]notfound \(vendor tree\)
+	.*[\\/]testdata[\\/]src[\\/]vend[\\/]vendor[\\/]notfound
 	.*[\\/]src[\\/]notfound \(from \$GOROOT\)
 	.*[\\/]testdata[\\/]src[\\/]notfound \(from \$GOPATH\)`)
 
@@ -187,6 +197,18 @@ func TestVendorGetUpdate(t *testing.T) {
 	tg.run("get", "-u", "github.com/rsc/go-get-issue-11864")
 }
 
+func TestGetSubmodules(t *testing.T) {
+	testenv.MustHaveExternalNetwork(t)
+
+	tg := testgo(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")
+}
+
 func TestVendorCache(t *testing.T) {
 	tg := testgo(t)
 	defer tg.cleanup()
diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go
index b2805ac..cfebeff 100644
--- a/src/cmd/gofmt/gofmt.go
+++ b/src/cmd/gofmt/gofmt.go
@@ -13,7 +13,6 @@ import (
 	"go/printer"
 	"go/scanner"
 	"go/token"
-	"internal/format"
 	"io"
 	"io/ioutil"
 	"os"
@@ -88,7 +87,7 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error
 		return err
 	}
 
-	file, sourceAdj, indentAdj, err := format.Parse(fileSet, filename, src, stdin)
+	file, sourceAdj, indentAdj, err := parse(fileSet, filename, src, stdin)
 	if err != nil {
 		return err
 	}
@@ -107,7 +106,7 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error
 		simplify(file)
 	}
 
-	res, err := format.Format(fileSet, file, sourceAdj, indentAdj, src, printer.Config{Mode: printerMode, Tabwidth: tabWidth})
+	res, err := format(fileSet, file, sourceAdj, indentAdj, src, printer.Config{Mode: printerMode, Tabwidth: tabWidth})
 	if err != nil {
 		return err
 	}
diff --git a/src/cmd/gofmt/internal.go b/src/cmd/gofmt/internal.go
new file mode 100644
index 0000000..f764b10
--- /dev/null
+++ b/src/cmd/gofmt/internal.go
@@ -0,0 +1,176 @@
+// Copyright 2015 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.
+
+// TODO(gri): This file and the file src/go/format/internal.go are
+// the same (but for this comment and the package name). Do not modify
+// one without the other. Determine if we can factor out functionality
+// in a public API. See also #11844 for context.
+
+package main
+
+import (
+	"bytes"
+	"go/ast"
+	"go/parser"
+	"go/printer"
+	"go/token"
+	"strings"
+)
+
+// parse parses src, which was read from the named file,
+// as a Go source file, declaration, or statement list.
+func parse(fset *token.FileSet, filename string, src []byte, fragmentOk bool) (
+	file *ast.File,
+	sourceAdj func(src []byte, indent int) []byte,
+	indentAdj int,
+	err error,
+) {
+	// Try as whole source file.
+	file, err = parser.ParseFile(fset, filename, src, parserMode)
+	// If there's no error, return.  If the error is that the source file didn't begin with a
+	// package line and source fragments are ok, fall through to
+	// try as a source fragment.  Stop and return on any other error.
+	if err == nil || !fragmentOk || !strings.Contains(err.Error(), "expected 'package'") {
+		return
+	}
+
+	// If this is a declaration list, make it a source file
+	// by inserting a package clause.
+	// Insert using a ;, not a newline, so that the line numbers
+	// in psrc match the ones in src.
+	psrc := append([]byte("package p;"), src...)
+	file, err = parser.ParseFile(fset, filename, psrc, parserMode)
+	if err == nil {
+		sourceAdj = func(src []byte, indent int) []byte {
+			// Remove the package clause.
+			// Gofmt has turned the ; into a \n.
+			src = src[indent+len("package p\n"):]
+			return bytes.TrimSpace(src)
+		}
+		return
+	}
+	// If the error is that the source file didn't begin with a
+	// declaration, fall through to try as a statement list.
+	// Stop and return on any other error.
+	if !strings.Contains(err.Error(), "expected declaration") {
+		return
+	}
+
+	// If this is a statement list, make it a source file
+	// by inserting a package clause and turning the list
+	// into a function body.  This handles expressions too.
+	// Insert using a ;, not a newline, so that the line numbers
+	// in fsrc match the ones in src. Add an extra '\n' before the '}'
+	// to make sure comments are flushed before the '}'.
+	fsrc := append(append([]byte("package p; func _() {"), src...), '\n', '\n', '}')
+	file, err = parser.ParseFile(fset, filename, fsrc, parserMode)
+	if err == nil {
+		sourceAdj = func(src []byte, indent int) []byte {
+			// Cap adjusted indent to zero.
+			if indent < 0 {
+				indent = 0
+			}
+			// Remove the wrapping.
+			// Gofmt has turned the ; into a \n\n.
+			// There will be two non-blank lines with indent, hence 2*indent.
+			src = src[2*indent+len("package p\n\nfunc _() {"):]
+			// Remove only the "}\n" suffix: remaining whitespaces will be trimmed anyway
+			src = src[:len(src)-len("}\n")]
+			return bytes.TrimSpace(src)
+		}
+		// Gofmt has also indented the function body one level.
+		// Adjust that with indentAdj.
+		indentAdj = -1
+	}
+
+	// Succeeded, or out of options.
+	return
+}
+
+// format formats the given package file originally obtained from src
+// and adjusts the result based on the original source via sourceAdj
+// and indentAdj.
+func format(
+	fset *token.FileSet,
+	file *ast.File,
+	sourceAdj func(src []byte, indent int) []byte,
+	indentAdj int,
+	src []byte,
+	cfg printer.Config,
+) ([]byte, error) {
+	if sourceAdj == nil {
+		// Complete source file.
+		var buf bytes.Buffer
+		err := cfg.Fprint(&buf, fset, file)
+		if err != nil {
+			return nil, err
+		}
+		return buf.Bytes(), nil
+	}
+
+	// Partial source file.
+	// Determine and prepend leading space.
+	i, j := 0, 0
+	for j < len(src) && isSpace(src[j]) {
+		if src[j] == '\n' {
+			i = j + 1 // byte offset of last line in leading space
+		}
+		j++
+	}
+	var res []byte
+	res = append(res, src[:i]...)
+
+	// Determine and prepend indentation of first code line.
+	// Spaces are ignored unless there are no tabs,
+	// in which case spaces count as one tab.
+	indent := 0
+	hasSpace := false
+	for _, b := range src[i:j] {
+		switch b {
+		case ' ':
+			hasSpace = true
+		case '\t':
+			indent++
+		}
+	}
+	if indent == 0 && hasSpace {
+		indent = 1
+	}
+	for i := 0; i < indent; i++ {
+		res = append(res, '\t')
+	}
+
+	// Format the source.
+	// Write it without any leading and trailing space.
+	cfg.Indent = indent + indentAdj
+	var buf bytes.Buffer
+	err := cfg.Fprint(&buf, fset, file)
+	if err != nil {
+		return nil, err
+	}
+	out := sourceAdj(buf.Bytes(), cfg.Indent)
+
+	// If the adjusted output is empty, the source
+	// was empty but (possibly) for white space.
+	// The result is the incoming source.
+	if len(out) == 0 {
+		return src, nil
+	}
+
+	// Otherwise, append output to leading space.
+	res = append(res, out...)
+
+	// Determine and append trailing space.
+	i = len(src)
+	for i > 0 && isSpace(src[i-1]) {
+		i--
+	}
+	return append(res, src[i:]...), nil
+}
+
+// isSpace reports whether the byte is a space character.
+// isSpace defines a space as being among the following bytes: ' ', '\t', '\n' and '\r'.
+func isSpace(b byte) bool {
+	return b == ' ' || b == '\t' || b == '\n' || b == '\r'
+}
diff --git a/src/cmd/gofmt/long_test.go b/src/cmd/gofmt/long_test.go
index df9a878..237b860 100644
--- a/src/cmd/gofmt/long_test.go
+++ b/src/cmd/gofmt/long_test.go
@@ -15,7 +15,6 @@ import (
 	"go/ast"
 	"go/printer"
 	"go/token"
-	"internal/format"
 	"io"
 	"os"
 	"path/filepath"
@@ -33,7 +32,7 @@ var (
 )
 
 func gofmt(fset *token.FileSet, filename string, src *bytes.Buffer) error {
-	f, _, _, err := format.Parse(fset, filename, src.Bytes(), false)
+	f, _, _, err := parse(fset, filename, src.Bytes(), false)
 	if err != nil {
 		return err
 	}
@@ -61,7 +60,7 @@ func testFile(t *testing.T, b1, b2 *bytes.Buffer, filename string) {
 
 	// exclude files w/ syntax errors (typically test cases)
 	fset := token.NewFileSet()
-	if _, _, _, err = format.Parse(fset, filename, b1.Bytes(), false); err != nil {
+	if _, _, _, err = parse(fset, filename, b1.Bytes(), false); err != nil {
 		if *verbose {
 			fmt.Fprintf(os.Stderr, "ignoring %s\n", err)
 		}
diff --git a/src/cmd/gofmt/testdata/old.golden b/src/cmd/gofmt/testdata/old.golden
deleted file mode 100644
index 95a0b72..0000000
--- a/src/cmd/gofmt/testdata/old.golden
+++ /dev/null
@@ -1,9 +0,0 @@
-package P
-
-func f() {
-	if x {
-		y
-	} else {
-		z
-	}
-}
diff --git a/src/cmd/gofmt/testdata/old.input b/src/cmd/gofmt/testdata/old.input
deleted file mode 100644
index e24eed2..0000000
--- a/src/cmd/gofmt/testdata/old.input
+++ /dev/null
@@ -1,8 +0,0 @@
-package P
-
-func f() {
-	if x {
-		y
-	} else
-		z
-}
diff --git a/src/cmd/internal/goobj/read.go b/src/cmd/internal/goobj/read.go
index 1b0c964..7fdaf55 100644
--- a/src/cmd/internal/goobj/read.go
+++ b/src/cmd/internal/goobj/read.go
@@ -564,7 +564,9 @@ func (r *objReader) parseObject(prefix []byte) error {
 	var c1, c2, c3 byte
 	for {
 		c1, c2, c3 = c2, c3, r.readByte()
-		if c3 == 0 { // NUL or EOF, either is bad
+		// The new export format can contain 0 bytes.
+		// Don't consider them errors, only look for r.err != nil.
+		if r.err != nil {
 			return errCorruptObject
 		}
 		if c1 == '\n' && c2 == '!' && c3 == '\n' {
diff --git a/src/cmd/internal/obj/ar.go b/src/cmd/internal/obj/ar.go
index 7cbeafd..56bb959 100644
--- a/src/cmd/internal/obj/ar.go
+++ b/src/cmd/internal/obj/ar.go
@@ -4,36 +4,6 @@
 
 package obj
 
-// Inferno utils/include/ar.h
-// http://code.google.com/p/inferno-os/source/browse/utils/include/ar.h
-//
-//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//	Portions Copyright © 1995-1997 C H Forsyth (forsyth at terzarima.net)
-//	Portions Copyright © 1997-1999 Vita Nuova Limited
-//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//	Portions Copyright © 2004,2006 Bruce Ellis
-//	Portions Copyright © 2005-2007 C H Forsyth (forsyth at terzarima.net)
-//	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
 type ar_hdr struct {
 	name string
 	date string
diff --git a/src/cmd/internal/obj/arm/a.out.go b/src/cmd/internal/obj/arm/a.out.go
index 1cb561d..ca166e1 100644
--- a/src/cmd/internal/obj/arm/a.out.go
+++ b/src/cmd/internal/obj/arm/a.out.go
@@ -155,6 +155,16 @@ const (
 	C_HREG
 
 	C_ADDR /* reference to relocatable address */
+
+	// TLS "var" in local exec mode: will become a constant offset from
+	// thread local base that is ultimately chosen by the program linker.
+	C_TLS_LE
+
+	// TLS "var" in initial exec mode: will become a memory address (chosen
+	// by the program linker) that the dynamic linker will fill with the
+	// offset from the thread local base.
+	C_TLS_IE
+
 	C_TEXTSIZE
 
 	C_GOK
@@ -251,8 +261,6 @@ const (
 	AMULA
 
 	AWORD
-	ABCASE
-	ACASE
 
 	AMULL
 	AMULAL
diff --git a/src/cmd/internal/obj/arm/anames.go b/src/cmd/internal/obj/arm/anames.go
index 1a924f0..0ef68a6 100644
--- a/src/cmd/internal/obj/arm/anames.go
+++ b/src/cmd/internal/obj/arm/anames.go
@@ -82,8 +82,6 @@ var Anames = []string{
 	"SWI",
 	"MULA",
 	"WORD",
-	"BCASE",
-	"CASE",
 	"MULL",
 	"MULAL",
 	"MULLU",
diff --git a/src/cmd/internal/obj/arm/anames5.go b/src/cmd/internal/obj/arm/anames5.go
index 2e3a1f9..7fdd962 100644
--- a/src/cmd/internal/obj/arm/anames5.go
+++ b/src/cmd/internal/obj/arm/anames5.go
@@ -9,6 +9,7 @@ var cnames5 = []string{
 	"REG",
 	"REGREG",
 	"REGREG2",
+	"REGLIST",
 	"SHIFT",
 	"FREG",
 	"PSR",
@@ -41,6 +42,8 @@ var cnames5 = []string{
 	"SP",
 	"HREG",
 	"ADDR",
+	"C_TLS_LE",
+	"C_TLS_IE",
 	"TEXTSIZE",
 	"GOK",
 	"NCLASS",
diff --git a/src/cmd/internal/obj/arm/asm5.go b/src/cmd/internal/obj/arm/asm5.go
index 610637c..d75a163 100644
--- a/src/cmd/internal/obj/arm/asm5.go
+++ b/src/cmd/internal/obj/arm/asm5.go
@@ -67,199 +67,201 @@ const (
 var optab = []Optab{
 	/* struct Optab:
 	OPCODE,	from, prog->reg, to,		 type,size,param,flag */
-	Optab{obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0},
-	Optab{AADD, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0},
-	Optab{AADD, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
-	Optab{AMOVW, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
-	Optab{AMVN, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
-	Optab{ACMP, C_REG, C_REG, C_NONE, 1, 4, 0, 0, 0},
-	Optab{AADD, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0},
-	Optab{AADD, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
-	Optab{AMOVW, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
-	Optab{AMVN, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
-	Optab{ACMP, C_RCON, C_REG, C_NONE, 2, 4, 0, 0, 0},
-	Optab{AADD, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0},
-	Optab{AADD, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0},
-	Optab{AMVN, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0},
-	Optab{ACMP, C_SHIFT, C_REG, C_NONE, 3, 4, 0, 0, 0},
-	Optab{AMOVW, C_RACON, C_NONE, C_REG, 4, 4, REGSP, 0, 0},
-	Optab{AB, C_NONE, C_NONE, C_SBRA, 5, 4, 0, LPOOL, 0},
-	Optab{ABL, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
-	Optab{ABX, C_NONE, C_NONE, C_SBRA, 74, 20, 0, 0, 0},
-	Optab{ABEQ, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
-	Optab{ABEQ, C_RCON, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // prediction hinted form, hint ignored
-
-	Optab{AB, C_NONE, C_NONE, C_ROREG, 6, 4, 0, LPOOL, 0},
-	Optab{ABL, C_NONE, C_NONE, C_ROREG, 7, 4, 0, 0, 0},
-	Optab{ABL, C_REG, C_NONE, C_ROREG, 7, 4, 0, 0, 0},
-	Optab{ABX, C_NONE, C_NONE, C_ROREG, 75, 12, 0, 0, 0},
-	Optab{ABXRET, C_NONE, C_NONE, C_ROREG, 76, 4, 0, 0, 0},
-	Optab{ASLL, C_RCON, C_REG, C_REG, 8, 4, 0, 0, 0},
-	Optab{ASLL, C_RCON, C_NONE, C_REG, 8, 4, 0, 0, 0},
-	Optab{ASLL, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0},
-	Optab{ASLL, C_REG, C_REG, C_REG, 9, 4, 0, 0, 0},
-	Optab{ASWI, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
-	Optab{ASWI, C_NONE, C_NONE, C_LOREG, 10, 4, 0, 0, 0},
-	Optab{ASWI, C_NONE, C_NONE, C_LCON, 10, 4, 0, 0, 0},
-	Optab{AWORD, C_NONE, C_NONE, C_LCON, 11, 4, 0, 0, 0},
-	Optab{AWORD, C_NONE, C_NONE, C_LCONADDR, 11, 4, 0, 0, 0},
-	Optab{AWORD, C_NONE, C_NONE, C_ADDR, 11, 4, 0, 0, 0},
-	Optab{AMOVW, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0},
-	Optab{AMOVW, C_LCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0},
-	Optab{AMOVW, C_LCONADDR, C_NONE, C_REG, 12, 4, 0, LFROM | LPCREL, 4},
-	Optab{AADD, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0},
-	Optab{AADD, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
-	Optab{AMVN, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
-	Optab{ACMP, C_NCON, C_REG, C_NONE, 13, 8, 0, 0, 0},
-	Optab{AADD, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0},
-	Optab{AADD, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0},
-	Optab{AMVN, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0},
-	Optab{ACMP, C_LCON, C_REG, C_NONE, 13, 8, 0, LFROM, 0},
-	Optab{AMOVB, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
-	Optab{AMOVBS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0},
-	Optab{AMOVBU, C_REG, C_NONE, C_REG, 58, 4, 0, 0, 0},
-	Optab{AMOVH, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
-	Optab{AMOVHS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0},
-	Optab{AMOVHU, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0},
-	Optab{AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
-	Optab{AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0},
-	Optab{ADIV, C_REG, C_REG, C_REG, 16, 4, 0, 0, 0},
-	Optab{ADIV, C_REG, C_NONE, C_REG, 16, 4, 0, 0, 0},
-	Optab{AMULL, C_REG, C_REG, C_REGREG, 17, 4, 0, 0, 0},
-	Optab{AMULA, C_REG, C_REG, C_REGREG2, 17, 4, 0, 0, 0},
-	Optab{AMOVW, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
-	Optab{AMOVW, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
-	Optab{AMOVB, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
-	Optab{AMOVB, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
-	Optab{AMOVBS, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
-	Optab{AMOVBS, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
-	Optab{AMOVBU, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
-	Optab{AMOVBU, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
-	Optab{AMOVW, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
-	Optab{AMOVW, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0},
-	Optab{AMOVBU, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
-	Optab{AMOVBU, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0},
-	Optab{AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
-	Optab{AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
-	Optab{AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
-	Optab{AMOVB, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
-	Optab{AMOVB, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
-	Optab{AMOVB, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
-	Optab{AMOVBS, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
-	Optab{AMOVBS, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
-	Optab{AMOVBS, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
-	Optab{AMOVBU, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
-	Optab{AMOVBU, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
-	Optab{AMOVBU, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
-	Optab{AMOVW, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
-	Optab{AMOVW, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
-	Optab{AMOVW, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4},
-	Optab{AMOVBU, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
-	Optab{AMOVBU, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
-	Optab{AMOVBU, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4},
-	Optab{AMOVW, C_LACON, C_NONE, C_REG, 34, 8, REGSP, LFROM, 0},
-	Optab{AMOVW, C_PSR, C_NONE, C_REG, 35, 4, 0, 0, 0},
-	Optab{AMOVW, C_REG, C_NONE, C_PSR, 36, 4, 0, 0, 0},
-	Optab{AMOVW, C_RCON, C_NONE, C_PSR, 37, 4, 0, 0, 0},
-	Optab{AMOVM, C_REGLIST, C_NONE, C_SOREG, 38, 4, 0, 0, 0},
-	Optab{AMOVM, C_SOREG, C_NONE, C_REGLIST, 39, 4, 0, 0, 0},
-	Optab{ASWPW, C_SOREG, C_REG, C_REG, 40, 4, 0, 0, 0},
-	Optab{ARFE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0},
-	Optab{AMOVF, C_FREG, C_NONE, C_FAUTO, 50, 4, REGSP, 0, 0},
-	Optab{AMOVF, C_FREG, C_NONE, C_FOREG, 50, 4, 0, 0, 0},
-	Optab{AMOVF, C_FAUTO, C_NONE, C_FREG, 51, 4, REGSP, 0, 0},
-	Optab{AMOVF, C_FOREG, C_NONE, C_FREG, 51, 4, 0, 0, 0},
-	Optab{AMOVF, C_FREG, C_NONE, C_LAUTO, 52, 12, REGSP, LTO, 0},
-	Optab{AMOVF, C_FREG, C_NONE, C_LOREG, 52, 12, 0, LTO, 0},
-	Optab{AMOVF, C_LAUTO, C_NONE, C_FREG, 53, 12, REGSP, LFROM, 0},
-	Optab{AMOVF, C_LOREG, C_NONE, C_FREG, 53, 12, 0, LFROM, 0},
-	Optab{AMOVF, C_FREG, C_NONE, C_ADDR, 68, 8, 0, LTO | LPCREL, 4},
-	Optab{AMOVF, C_ADDR, C_NONE, C_FREG, 69, 8, 0, LFROM | LPCREL, 4},
-	Optab{AADDF, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0},
-	Optab{AADDF, C_FREG, C_REG, C_FREG, 54, 4, 0, 0, 0},
-	Optab{AMOVF, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0},
-	Optab{AMOVW, C_REG, C_NONE, C_FCR, 56, 4, 0, 0, 0},
-	Optab{AMOVW, C_FCR, C_NONE, C_REG, 57, 4, 0, 0, 0},
-	Optab{AMOVW, C_SHIFT, C_NONE, C_REG, 59, 4, 0, 0, 0},
-	Optab{AMOVBU, C_SHIFT, C_NONE, C_REG, 59, 4, 0, 0, 0},
-	Optab{AMOVB, C_SHIFT, C_NONE, C_REG, 60, 4, 0, 0, 0},
-	Optab{AMOVBS, C_SHIFT, C_NONE, C_REG, 60, 4, 0, 0, 0},
-	Optab{AMOVW, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0},
-	Optab{AMOVB, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0},
-	Optab{AMOVBS, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0},
-	Optab{AMOVBU, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0},
-	Optab{ACASE, C_REG, C_NONE, C_NONE, 62, 4, 0, LPCREL, 8},
-	Optab{ABCASE, C_NONE, C_NONE, C_SBRA, 63, 4, 0, LPCREL, 0},
-	Optab{AMOVH, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0},
-	Optab{AMOVH, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0},
-	Optab{AMOVHS, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0},
-	Optab{AMOVHS, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0},
-	Optab{AMOVHU, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0},
-	Optab{AMOVHU, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0},
-	Optab{AMOVB, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
-	Optab{AMOVB, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
-	Optab{AMOVBS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
-	Optab{AMOVBS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
-	Optab{AMOVH, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
-	Optab{AMOVH, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
-	Optab{AMOVHS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
-	Optab{AMOVHS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
-	Optab{AMOVHU, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
-	Optab{AMOVHU, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
-	Optab{AMOVH, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0},
-	Optab{AMOVH, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0},
-	Optab{AMOVH, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4},
-	Optab{AMOVHS, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0},
-	Optab{AMOVHS, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0},
-	Optab{AMOVHS, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4},
-	Optab{AMOVHU, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0},
-	Optab{AMOVHU, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0},
-	Optab{AMOVHU, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4},
-	Optab{AMOVB, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
-	Optab{AMOVB, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
-	Optab{AMOVB, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
-	Optab{AMOVBS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
-	Optab{AMOVBS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
-	Optab{AMOVBS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
-	Optab{AMOVH, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
-	Optab{AMOVH, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
-	Optab{AMOVH, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
-	Optab{AMOVHS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
-	Optab{AMOVHS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
-	Optab{AMOVHS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
-	Optab{AMOVHU, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
-	Optab{AMOVHU, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
-	Optab{AMOVHU, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
-	Optab{ALDREX, C_SOREG, C_NONE, C_REG, 77, 4, 0, 0, 0},
-	Optab{ASTREX, C_SOREG, C_REG, C_REG, 78, 4, 0, 0, 0},
-	Optab{AMOVF, C_ZFCON, C_NONE, C_FREG, 80, 8, 0, 0, 0},
-	Optab{AMOVF, C_SFCON, C_NONE, C_FREG, 81, 4, 0, 0, 0},
-	Optab{ACMPF, C_FREG, C_REG, C_NONE, 82, 8, 0, 0, 0},
-	Optab{ACMPF, C_FREG, C_NONE, C_NONE, 83, 8, 0, 0, 0},
-	Optab{AMOVFW, C_FREG, C_NONE, C_FREG, 84, 4, 0, 0, 0},
-	Optab{AMOVWF, C_FREG, C_NONE, C_FREG, 85, 4, 0, 0, 0},
-	Optab{AMOVFW, C_FREG, C_NONE, C_REG, 86, 8, 0, 0, 0},
-	Optab{AMOVWF, C_REG, C_NONE, C_FREG, 87, 8, 0, 0, 0},
-	Optab{AMOVW, C_REG, C_NONE, C_FREG, 88, 4, 0, 0, 0},
-	Optab{AMOVW, C_FREG, C_NONE, C_REG, 89, 4, 0, 0, 0},
-	Optab{ATST, C_REG, C_NONE, C_NONE, 90, 4, 0, 0, 0},
-	Optab{ALDREXD, C_SOREG, C_NONE, C_REG, 91, 4, 0, 0, 0},
-	Optab{ASTREXD, C_SOREG, C_REG, C_REG, 92, 4, 0, 0, 0},
-	Optab{APLD, C_SOREG, C_NONE, C_NONE, 95, 4, 0, 0, 0},
-	Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, 96, 4, 0, 0, 0},
-	Optab{ACLZ, C_REG, C_NONE, C_REG, 97, 4, 0, 0, 0},
-	Optab{AMULWT, C_REG, C_REG, C_REG, 98, 4, 0, 0, 0},
-	Optab{AMULAWT, C_REG, C_REG, C_REGREG2, 99, 4, 0, 0, 0},
-	Optab{obj.AUSEFIELD, C_ADDR, C_NONE, C_NONE, 0, 0, 0, 0, 0},
-	Optab{obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0, 0, 0},
-	Optab{obj.AFUNCDATA, C_LCON, C_NONE, C_ADDR, 0, 0, 0, 0, 0},
-	Optab{obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
-	Optab{obj.ADUFFZERO, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as ABL
-	Optab{obj.ADUFFCOPY, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as ABL
-
-	Optab{ADATABUNDLE, C_NONE, C_NONE, C_NONE, 100, 4, 0, 0, 0},
-	Optab{ADATABUNDLEEND, C_NONE, C_NONE, C_NONE, 100, 0, 0, 0, 0},
-	Optab{obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0},
+	{obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0},
+	{AADD, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0},
+	{AADD, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
+	{AMOVW, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
+	{AMVN, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
+	{ACMP, C_REG, C_REG, C_NONE, 1, 4, 0, 0, 0},
+	{AADD, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0},
+	{AADD, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
+	{AMOVW, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
+	{AMVN, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0},
+	{ACMP, C_RCON, C_REG, C_NONE, 2, 4, 0, 0, 0},
+	{AADD, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0},
+	{AADD, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0},
+	{AMVN, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0},
+	{ACMP, C_SHIFT, C_REG, C_NONE, 3, 4, 0, 0, 0},
+	{AMOVW, C_RACON, C_NONE, C_REG, 4, 4, REGSP, 0, 0},
+	{AB, C_NONE, C_NONE, C_SBRA, 5, 4, 0, LPOOL, 0},
+	{ABL, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
+	{ABX, C_NONE, C_NONE, C_SBRA, 74, 20, 0, 0, 0},
+	{ABEQ, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
+	{ABEQ, C_RCON, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // prediction hinted form, hint ignored
+
+	{AB, C_NONE, C_NONE, C_ROREG, 6, 4, 0, LPOOL, 0},
+	{ABL, C_NONE, C_NONE, C_ROREG, 7, 4, 0, 0, 0},
+	{ABL, C_REG, C_NONE, C_ROREG, 7, 4, 0, 0, 0},
+	{ABX, C_NONE, C_NONE, C_ROREG, 75, 12, 0, 0, 0},
+	{ABXRET, C_NONE, C_NONE, C_ROREG, 76, 4, 0, 0, 0},
+	{ASLL, C_RCON, C_REG, C_REG, 8, 4, 0, 0, 0},
+	{ASLL, C_RCON, C_NONE, C_REG, 8, 4, 0, 0, 0},
+	{ASLL, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0},
+	{ASLL, C_REG, C_REG, C_REG, 9, 4, 0, 0, 0},
+	{ASWI, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
+	{ASWI, C_NONE, C_NONE, C_LOREG, 10, 4, 0, 0, 0},
+	{ASWI, C_NONE, C_NONE, C_LCON, 10, 4, 0, 0, 0},
+	{AWORD, C_NONE, C_NONE, C_LCON, 11, 4, 0, 0, 0},
+	{AWORD, C_NONE, C_NONE, C_LCONADDR, 11, 4, 0, 0, 0},
+	{AWORD, C_NONE, C_NONE, C_ADDR, 11, 4, 0, 0, 0},
+	{AWORD, C_NONE, C_NONE, C_TLS_LE, 103, 4, 0, 0, 0},
+	{AWORD, C_NONE, C_NONE, C_TLS_IE, 104, 4, 0, 0, 0},
+	{AMOVW, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0},
+	{AMOVW, C_LCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0},
+	{AMOVW, C_LCONADDR, C_NONE, C_REG, 12, 4, 0, LFROM | LPCREL, 4},
+	{AADD, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0},
+	{AADD, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
+	{AMVN, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0},
+	{ACMP, C_NCON, C_REG, C_NONE, 13, 8, 0, 0, 0},
+	{AADD, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0},
+	{AADD, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0},
+	{AMVN, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0},
+	{ACMP, C_LCON, C_REG, C_NONE, 13, 8, 0, LFROM, 0},
+	{AMOVB, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
+	{AMOVBS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0},
+	{AMOVBU, C_REG, C_NONE, C_REG, 58, 4, 0, 0, 0},
+	{AMOVH, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
+	{AMOVHS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0},
+	{AMOVHU, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0},
+	{AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
+	{AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0},
+	{ADIV, C_REG, C_REG, C_REG, 16, 4, 0, 0, 0},
+	{ADIV, C_REG, C_NONE, C_REG, 16, 4, 0, 0, 0},
+	{AMULL, C_REG, C_REG, C_REGREG, 17, 4, 0, 0, 0},
+	{AMULA, C_REG, C_REG, C_REGREG2, 17, 4, 0, 0, 0},
+	{AMOVW, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
+	{AMOVW, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
+	{AMOVB, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
+	{AMOVB, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
+	{AMOVBS, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
+	{AMOVBS, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
+	{AMOVBU, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0},
+	{AMOVBU, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0},
+	{AMOVW, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
+	{AMOVW, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0},
+	{AMOVBU, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
+	{AMOVBU, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0},
+	{AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
+	{AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
+	{AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
+	{AMOVB, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
+	{AMOVB, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
+	{AMOVB, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
+	{AMOVBS, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
+	{AMOVBS, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
+	{AMOVBS, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
+	{AMOVBU, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
+	{AMOVBU, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
+	{AMOVBU, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4},
+	{AMOVW, C_TLS_LE, C_NONE, C_REG, 101, 4, 0, LFROM, 0},
+	{AMOVW, C_TLS_IE, C_NONE, C_REG, 102, 8, 0, LFROM, 0},
+	{AMOVW, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
+	{AMOVW, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
+	{AMOVW, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4},
+	{AMOVBU, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
+	{AMOVBU, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
+	{AMOVBU, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4},
+	{AMOVW, C_LACON, C_NONE, C_REG, 34, 8, REGSP, LFROM, 0},
+	{AMOVW, C_PSR, C_NONE, C_REG, 35, 4, 0, 0, 0},
+	{AMOVW, C_REG, C_NONE, C_PSR, 36, 4, 0, 0, 0},
+	{AMOVW, C_RCON, C_NONE, C_PSR, 37, 4, 0, 0, 0},
+	{AMOVM, C_REGLIST, C_NONE, C_SOREG, 38, 4, 0, 0, 0},
+	{AMOVM, C_SOREG, C_NONE, C_REGLIST, 39, 4, 0, 0, 0},
+	{ASWPW, C_SOREG, C_REG, C_REG, 40, 4, 0, 0, 0},
+	{ARFE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0},
+	{AMOVF, C_FREG, C_NONE, C_FAUTO, 50, 4, REGSP, 0, 0},
+	{AMOVF, C_FREG, C_NONE, C_FOREG, 50, 4, 0, 0, 0},
+	{AMOVF, C_FAUTO, C_NONE, C_FREG, 51, 4, REGSP, 0, 0},
+	{AMOVF, C_FOREG, C_NONE, C_FREG, 51, 4, 0, 0, 0},
+	{AMOVF, C_FREG, C_NONE, C_LAUTO, 52, 12, REGSP, LTO, 0},
+	{AMOVF, C_FREG, C_NONE, C_LOREG, 52, 12, 0, LTO, 0},
+	{AMOVF, C_LAUTO, C_NONE, C_FREG, 53, 12, REGSP, LFROM, 0},
+	{AMOVF, C_LOREG, C_NONE, C_FREG, 53, 12, 0, LFROM, 0},
+	{AMOVF, C_FREG, C_NONE, C_ADDR, 68, 8, 0, LTO | LPCREL, 4},
+	{AMOVF, C_ADDR, C_NONE, C_FREG, 69, 8, 0, LFROM | LPCREL, 4},
+	{AADDF, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0},
+	{AADDF, C_FREG, C_REG, C_FREG, 54, 4, 0, 0, 0},
+	{AMOVF, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0},
+	{AMOVW, C_REG, C_NONE, C_FCR, 56, 4, 0, 0, 0},
+	{AMOVW, C_FCR, C_NONE, C_REG, 57, 4, 0, 0, 0},
+	{AMOVW, C_SHIFT, C_NONE, C_REG, 59, 4, 0, 0, 0},
+	{AMOVBU, C_SHIFT, C_NONE, C_REG, 59, 4, 0, 0, 0},
+	{AMOVB, C_SHIFT, C_NONE, C_REG, 60, 4, 0, 0, 0},
+	{AMOVBS, C_SHIFT, C_NONE, C_REG, 60, 4, 0, 0, 0},
+	{AMOVW, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0},
+	{AMOVB, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0},
+	{AMOVBS, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0},
+	{AMOVBU, C_REG, C_NONE, C_SHIFT, 61, 4, 0, 0, 0},
+	{AMOVH, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0},
+	{AMOVH, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0},
+	{AMOVHS, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0},
+	{AMOVHS, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0},
+	{AMOVHU, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0},
+	{AMOVHU, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0},
+	{AMOVB, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
+	{AMOVB, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
+	{AMOVBS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
+	{AMOVBS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
+	{AMOVH, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
+	{AMOVH, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
+	{AMOVHS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
+	{AMOVHS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
+	{AMOVHU, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0},
+	{AMOVHU, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0},
+	{AMOVH, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0},
+	{AMOVH, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0},
+	{AMOVH, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4},
+	{AMOVHS, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0},
+	{AMOVHS, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0},
+	{AMOVHS, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4},
+	{AMOVHU, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0},
+	{AMOVHU, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0},
+	{AMOVHU, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4},
+	{AMOVB, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
+	{AMOVB, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
+	{AMOVB, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
+	{AMOVBS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
+	{AMOVBS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
+	{AMOVBS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
+	{AMOVH, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
+	{AMOVH, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
+	{AMOVH, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
+	{AMOVHS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
+	{AMOVHS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
+	{AMOVHS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
+	{AMOVHU, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0},
+	{AMOVHU, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0},
+	{AMOVHU, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4},
+	{ALDREX, C_SOREG, C_NONE, C_REG, 77, 4, 0, 0, 0},
+	{ASTREX, C_SOREG, C_REG, C_REG, 78, 4, 0, 0, 0},
+	{AMOVF, C_ZFCON, C_NONE, C_FREG, 80, 8, 0, 0, 0},
+	{AMOVF, C_SFCON, C_NONE, C_FREG, 81, 4, 0, 0, 0},
+	{ACMPF, C_FREG, C_REG, C_NONE, 82, 8, 0, 0, 0},
+	{ACMPF, C_FREG, C_NONE, C_NONE, 83, 8, 0, 0, 0},
+	{AMOVFW, C_FREG, C_NONE, C_FREG, 84, 4, 0, 0, 0},
+	{AMOVWF, C_FREG, C_NONE, C_FREG, 85, 4, 0, 0, 0},
+	{AMOVFW, C_FREG, C_NONE, C_REG, 86, 8, 0, 0, 0},
+	{AMOVWF, C_REG, C_NONE, C_FREG, 87, 8, 0, 0, 0},
+	{AMOVW, C_REG, C_NONE, C_FREG, 88, 4, 0, 0, 0},
+	{AMOVW, C_FREG, C_NONE, C_REG, 89, 4, 0, 0, 0},
+	{ATST, C_REG, C_NONE, C_NONE, 90, 4, 0, 0, 0},
+	{ALDREXD, C_SOREG, C_NONE, C_REG, 91, 4, 0, 0, 0},
+	{ASTREXD, C_SOREG, C_REG, C_REG, 92, 4, 0, 0, 0},
+	{APLD, C_SOREG, C_NONE, C_NONE, 95, 4, 0, 0, 0},
+	{obj.AUNDEF, C_NONE, C_NONE, C_NONE, 96, 4, 0, 0, 0},
+	{ACLZ, C_REG, C_NONE, C_REG, 97, 4, 0, 0, 0},
+	{AMULWT, C_REG, C_REG, C_REG, 98, 4, 0, 0, 0},
+	{AMULAWT, C_REG, C_REG, C_REGREG2, 99, 4, 0, 0, 0},
+	{obj.AUSEFIELD, C_ADDR, C_NONE, C_NONE, 0, 0, 0, 0, 0},
+	{obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0, 0, 0},
+	{obj.AFUNCDATA, C_LCON, C_NONE, C_ADDR, 0, 0, 0, 0, 0},
+	{obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
+	{obj.ADUFFZERO, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as ABL
+	{obj.ADUFFCOPY, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as ABL
+
+	{ADATABUNDLE, C_NONE, C_NONE, C_NONE, 100, 4, 0, 0, 0},
+	{ADATABUNDLEEND, C_NONE, C_NONE, C_NONE, 100, 0, 0, 0, 0},
+	{obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0},
 }
 
 var pool struct {
@@ -274,25 +276,6 @@ var xcmp [C_GOK + 1][C_GOK + 1]uint8
 
 var deferreturn *obj.LSym
 
-/* size of a case statement including jump table */
-func casesz(ctxt *obj.Link, p *obj.Prog) int32 {
-	var jt int = 0
-	var n int32 = 0
-	var o *Optab
-
-	for ; p != nil; p = p.Link {
-		if p.As == ABCASE {
-			jt = 1
-		} else if jt != 0 {
-			break
-		}
-		o = oplook(ctxt, p)
-		n += int32(o.size)
-	}
-
-	return n
-}
-
 // Note about encoding: Prog.scond holds the condition encoding,
 // but XOR'ed with C_SCOND_XOR, so that C_SCOND_NONE == 0.
 // The code that shifts the value << 28 has the responsibility
@@ -625,16 +608,13 @@ func span5(ctxt *obj.Link, cursym *obj.LSym) {
 		// must check literal pool here in case p generates many instructions
 		if ctxt.Blitrl != nil {
 			i = m
-			if p.As == ACASE {
-				i = int(casesz(ctxt, p))
-			}
 			if checkpool(ctxt, op, i) {
 				p = op
 				continue
 			}
 		}
 
-		if m == 0 && (p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != ADATABUNDLEEND && p.As != obj.ANOP) {
+		if m == 0 && (p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != ADATABUNDLEEND && p.As != obj.ANOP && p.As != obj.AUSEFIELD) {
 			ctxt.Diag("zero-width instruction\n%v", p)
 			continue
 		}
@@ -730,7 +710,7 @@ func span5(ctxt *obj.Link, cursym *obj.LSym) {
 			if m/4 > len(out) {
 				ctxt.Diag("instruction size too large: %d > %d", m/4, len(out))
 			}
-			if m == 0 && (p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != ADATABUNDLEEND && p.As != obj.ANOP) {
+			if m == 0 && (p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != ADATABUNDLEEND && p.As != obj.ANOP && p.As != obj.AUSEFIELD) {
 				if p.As == obj.ATEXT {
 					ctxt.Autosize = int32(p.To.Offset + 4)
 					continue
@@ -759,9 +739,6 @@ func span5(ctxt *obj.Link, cursym *obj.LSym) {
 	 * code references to be relocated too, and then
 	 * perhaps we'd be able to parallelize the span loop above.
 	 */
-	if ctxt.Tlsg == nil {
-		ctxt.Tlsg = obj.Linklookup(ctxt, "runtime.tlsg", 0)
-	}
 
 	p = cursym.Text
 	ctxt.Autosize = int32(p.To.Offset + 4)
@@ -1004,6 +981,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
 		return C_NONE
 
 	case obj.TYPE_REG:
+		ctxt.Instoffset = 0
 		if REG_R0 <= a.Reg && a.Reg <= REG_R15 {
 			return C_REG
 		}
@@ -1033,6 +1011,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
 	case obj.TYPE_MEM:
 		switch a.Name {
 		case obj.NAME_EXTERN,
+			obj.NAME_GOTREF,
 			obj.NAME_STATIC:
 			if a.Sym == nil || a.Sym.Name == "" {
 				fmt.Printf("null sym external\n")
@@ -1040,6 +1019,14 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
 			}
 
 			ctxt.Instoffset = 0 // s.b. unused but just in case
+			if a.Sym.Type == obj.STLSBSS {
+				if ctxt.Flag_shared != 0 {
+					return C_TLS_IE
+				} else {
+					return C_TLS_LE
+				}
+			}
+
 			return C_ADDR
 
 		case obj.NAME_AUTO:
@@ -1145,6 +1132,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
 			return C_LCON
 
 		case obj.NAME_EXTERN,
+			obj.NAME_GOTREF,
 			obj.NAME_STATIC:
 			s := a.Sym
 			if s == nil {
@@ -1442,8 +1430,6 @@ func buildop(ctxt *obj.Link) {
 			ARFE,
 			obj.ATEXT,
 			obj.AUSEFIELD,
-			ACASE,
-			ABCASE,
 			obj.ATYPE:
 			break
 
@@ -1575,7 +1561,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
 		o1 |= (uint32(p.To.Reg) & 15) << 12
 
 	case 5: /* bra s */
-		o1 = opbra(ctxt, int(p.As), int(p.Scond))
+		o1 = opbra(ctxt, p, int(p.As), int(p.Scond))
 
 		v := int32(-8)
 		if p.To.Sym != nil {
@@ -1606,7 +1592,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
 		aclass(ctxt, &p.To)
 
 		if ctxt.Instoffset != 0 {
-			ctxt.Diag("%v: doesn't support BL offset(REG) where offset != 0", p)
+			ctxt.Diag("%v: doesn't support BL offset(REG) with non-zero offset %d", p, ctxt.Instoffset)
 		}
 		o1 = oprrr(ctxt, ABL, int(p.Scond))
 		o1 |= (uint32(p.To.Reg) & 15) << 0
@@ -1660,20 +1646,12 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
 			rel.Sym = p.To.Sym
 			rel.Add = p.To.Offset
 
-			// runtime.tlsg is special.
-			// Its "address" is the offset from the TLS thread pointer
-			// to the thread-local g and m pointers.
-			// Emit a TLS relocation instead of a standard one if its
-			// type is not explicitly set by runtime. This assumes that
-			// all references to runtime.tlsg should be accompanied with
-			// its type declaration if necessary.
-			if rel.Sym == ctxt.Tlsg && ctxt.Tlsg.Type == 0 {
-				rel.Type = obj.R_TLS
-				if ctxt.Flag_shared != 0 {
-					rel.Add += ctxt.Pc - p.Rel.Pc - 8 - int64(rel.Siz)
+			if ctxt.Flag_shared != 0 {
+				if p.To.Name == obj.NAME_GOTREF {
+					rel.Type = obj.R_GOTPCREL
+				} else {
+					rel.Type = obj.R_PCREL
 				}
-			} else if ctxt.Flag_shared != 0 {
-				rel.Type = obj.R_PCREL
 				rel.Add += ctxt.Pc - p.Rel.Pc - 8
 			} else {
 				rel.Type = obj.R_ADDR
@@ -2035,39 +2013,6 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
 			o1 |= 1 << 22
 		}
 
-	case 62: /* case R -> movw	R<<2(PC),PC */
-		if o.flag&LPCREL != 0 {
-			o1 = oprrr(ctxt, AADD, int(p.Scond)) | uint32(immrot(1)) | (uint32(p.From.Reg)&15)<<16 | (REGTMP&15)<<12
-			o2 = olrr(ctxt, REGTMP&15, REGPC, REGTMP, int(p.Scond))
-			o2 |= 2 << 7
-			o3 = oprrr(ctxt, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGPC&15)<<12
-		} else {
-			o1 = olrr(ctxt, int(p.From.Reg)&15, REGPC, REGPC, int(p.Scond))
-			o1 |= 2 << 7
-		}
-
-	case 63: /* bcase */
-		if p.Pcond != nil {
-			rel := obj.Addrel(ctxt.Cursym)
-			rel.Off = int32(ctxt.Pc)
-			rel.Siz = 4
-			if p.To.Sym != nil && p.To.Sym.Type != 0 {
-				rel.Sym = p.To.Sym
-				rel.Add = p.To.Offset
-			} else {
-				rel.Sym = ctxt.Cursym
-				rel.Add = p.Pcond.Pc
-			}
-
-			if o.flag&LPCREL != 0 {
-				rel.Type = obj.R_PCREL
-				rel.Add += ctxt.Pc - p.Rel.Pc - 16 + int64(rel.Siz)
-			} else {
-				rel.Type = obj.R_ADDR
-			}
-			o1 = 0
-		}
-
 		/* reloc ops */
 	case 64: /* mov/movb/movbu R,addr */
 		o1 = omvl(ctxt, p, &p.To, REGTMP)
@@ -2096,6 +2041,50 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
 			o2 = oprrr(ctxt, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
 		}
 
+	case 101: /* movw tlsvar,R, local exec*/
+		if p.Scond&C_SCOND != C_SCOND_NONE {
+			ctxt.Diag("conditional tls")
+		}
+		o1 = omvl(ctxt, p, &p.From, int(p.To.Reg))
+
+	case 102: /* movw tlsvar,R, initial exec*/
+		if p.Scond&C_SCOND != C_SCOND_NONE {
+			ctxt.Diag("conditional tls")
+		}
+		o1 = omvl(ctxt, p, &p.From, int(p.To.Reg))
+		o2 = olrr(ctxt, int(p.To.Reg)&15, (REGPC & 15), int(p.To.Reg), int(p.Scond))
+
+	case 103: /* word tlsvar, local exec */
+		if p.To.Sym == nil {
+			ctxt.Diag("nil sym in tls %v", p)
+		}
+		if p.To.Offset != 0 {
+			ctxt.Diag("offset against tls var in %v", p)
+		}
+		// This case happens with words generated in the PC stream as part of
+		// the literal pool.
+		rel := obj.Addrel(ctxt.Cursym)
+
+		rel.Off = int32(ctxt.Pc)
+		rel.Siz = 4
+		rel.Sym = p.To.Sym
+		rel.Type = obj.R_TLS_LE
+		o1 = 0
+
+	case 104: /* word tlsvar, initial exec */
+		if p.To.Sym == nil {
+			ctxt.Diag("nil sym in tls %v", p)
+		}
+		if p.To.Offset != 0 {
+			ctxt.Diag("offset against tls var in %v", p)
+		}
+		rel := obj.Addrel(ctxt.Cursym)
+		rel.Off = int32(ctxt.Pc)
+		rel.Siz = 4
+		rel.Sym = p.To.Sym
+		rel.Type = obj.R_TLS_IE
+		rel.Add = ctxt.Pc - p.Rel.Pc - 8 - int64(rel.Siz)
+
 	case 68: /* floating point store -> ADDR */
 		o1 = omvl(ctxt, p, &p.To, REGTMP)
 
@@ -2605,9 +2594,9 @@ func oprrr(ctxt *obj.Link, a int, sc int) uint32 {
 	return 0
 }
 
-func opbra(ctxt *obj.Link, a int, sc int) uint32 {
+func opbra(ctxt *obj.Link, p *obj.Prog, a int, sc int) uint32 {
 	if sc&(C_SBIT|C_PBIT|C_WBIT) != 0 {
-		ctxt.Diag(".nil/.nil/.W on bra instruction")
+		ctxt.Diag("%v: .nil/.nil/.W on bra instruction", p)
 	}
 	sc &= C_SCOND
 	sc ^= C_SCOND_XOR
@@ -2615,7 +2604,7 @@ func opbra(ctxt *obj.Link, a int, sc int) uint32 {
 		return uint32(sc)<<28 | 0x5<<25 | 0x1<<24
 	}
 	if sc != 0xe {
-		ctxt.Diag(".COND on bcond instruction")
+		ctxt.Diag("%v: .COND on bcond instruction", p)
 	}
 	switch a {
 	case ABEQ:
@@ -2748,7 +2737,7 @@ func olhrr(ctxt *obj.Link, i int, b int, r int, sc int) uint32 {
 
 func ofsr(ctxt *obj.Link, a int, r int, v int32, b int, sc int, p *obj.Prog) uint32 {
 	if sc&C_SBIT != 0 {
-		ctxt.Diag(".nil on FLDR/FSTR instruction")
+		ctxt.Diag(".nil on FLDR/FSTR instruction: %v", p)
 	}
 	o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
 	if sc&C_PBIT == 0 {
diff --git a/src/cmd/internal/obj/arm/obj5.go b/src/cmd/internal/obj/arm/obj5.go
index 3ecf6bc..19a70e1 100644
--- a/src/cmd/internal/obj/arm/obj5.go
+++ b/src/cmd/internal/obj/arm/obj5.go
@@ -130,23 +130,122 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
 		}
 	}
 
-	if ctxt.Flag_shared != 0 {
-		// Shared libraries use R_ARM_TLS_IE32 instead of
-		// R_ARM_TLS_LE32, replacing the link time constant TLS offset in
-		// runtime.tlsg with an address to a GOT entry containing the
-		// offset. Rewrite $runtime.tlsg(SB) to runtime.tlsg(SB) to
-		// compensate.
-		if ctxt.Tlsg == nil {
-			ctxt.Tlsg = obj.Linklookup(ctxt, "runtime.tlsg", 0)
+	if ctxt.Flag_dynlink {
+		rewriteToUseGot(ctxt, p)
+	}
+}
+
+// Rewrite p, if necessary, to access global data via the global offset table.
+func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog) {
+	if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
+		//     ADUFFxxx $offset
+		// becomes
+		//     MOVW runtime.duffxxx at GOT, R9
+		//     ADD $offset, R9
+		//     CALL (R9)
+		var sym *obj.LSym
+		if p.As == obj.ADUFFZERO {
+			sym = obj.Linklookup(ctxt, "runtime.duffzero", 0)
+		} else {
+			sym = obj.Linklookup(ctxt, "runtime.duffcopy", 0)
 		}
+		offset := p.To.Offset
+		p.As = AMOVW
+		p.From.Type = obj.TYPE_MEM
+		p.From.Name = obj.NAME_GOTREF
+		p.From.Sym = sym
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = REG_R9
+		p.To.Name = obj.NAME_NONE
+		p.To.Offset = 0
+		p.To.Sym = nil
+		p1 := obj.Appendp(ctxt, p)
+		p1.As = AADD
+		p1.From.Type = obj.TYPE_CONST
+		p1.From.Offset = offset
+		p1.To.Type = obj.TYPE_REG
+		p1.To.Reg = REG_R9
+		p2 := obj.Appendp(ctxt, p1)
+		p2.As = obj.ACALL
+		p2.To.Type = obj.TYPE_MEM
+		p2.To.Reg = REG_R9
+		return
+	}
 
-		if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && p.From.Sym == ctxt.Tlsg {
-			p.From.Type = obj.TYPE_MEM
+	// We only care about global data: NAME_EXTERN means a global
+	// symbol in the Go sense, and p.Sym.Local is true for a few
+	// internally defined symbols.
+	if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
+		// MOVW $sym, Rx becomes MOVW sym at GOT, Rx
+		// MOVW $sym+<off>, Rx becomes MOVW sym at GOT, Rx; ADD <off>, Rx
+		if p.As != AMOVW {
+			ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p)
 		}
-		if p.To.Type == obj.TYPE_ADDR && p.To.Name == obj.NAME_EXTERN && p.To.Sym == ctxt.Tlsg {
-			p.To.Type = obj.TYPE_MEM
+		if p.To.Type != obj.TYPE_REG {
+			ctxt.Diag("do not know how to handle LEAQ-type insn to non-register in %v with -dynlink", p)
+		}
+		p.From.Type = obj.TYPE_MEM
+		p.From.Name = obj.NAME_GOTREF
+		if p.From.Offset != 0 {
+			q := obj.Appendp(ctxt, p)
+			q.As = AADD
+			q.From.Type = obj.TYPE_CONST
+			q.From.Offset = p.From.Offset
+			q.To = p.To
+			p.From.Offset = 0
+		}
+	}
+	if p.From3 != nil && p.From3.Name == obj.NAME_EXTERN {
+		ctxt.Diag("don't know how to handle %v with -dynlink", p)
+	}
+	var source *obj.Addr
+	// MOVx sym, Ry becomes MOVW sym at GOT, R9; MOVx (R9), Ry
+	// MOVx Ry, sym becomes MOVW sym at GOT, R9; MOVx Ry, (R9)
+	// An addition may be inserted between the two MOVs if there is an offset.
+	if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
+		if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
+			ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
 		}
+		source = &p.From
+	} else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
+		source = &p.To
+	} else {
+		return
 	}
+	if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
+		return
+	}
+	if source.Sym.Type == obj.STLSBSS {
+		return
+	}
+	if source.Type != obj.TYPE_MEM {
+		ctxt.Diag("don't know how to handle %v with -dynlink", p)
+	}
+	p1 := obj.Appendp(ctxt, p)
+	p2 := obj.Appendp(ctxt, p1)
+
+	p1.As = AMOVW
+	p1.From.Type = obj.TYPE_MEM
+	p1.From.Sym = source.Sym
+	p1.From.Name = obj.NAME_GOTREF
+	p1.To.Type = obj.TYPE_REG
+	p1.To.Reg = REG_R9
+
+	p2.As = p.As
+	p2.From = p.From
+	p2.To = p.To
+	if p.From.Name == obj.NAME_EXTERN {
+		p2.From.Reg = REG_R9
+		p2.From.Name = obj.NAME_NONE
+		p2.From.Sym = nil
+	} else if p.To.Name == obj.NAME_EXTERN {
+		p2.To.Reg = REG_R9
+		p2.To.Name = obj.NAME_NONE
+		p2.To.Sym = nil
+	} else {
+		return
+	}
+	obj.Nopout(p)
 }
 
 // Prog.mark
@@ -156,17 +255,6 @@ const (
 	LEAF  = 1 << 2
 )
 
-func linkcase(casep *obj.Prog) {
-	for p := casep; p != nil; p = p.Link {
-		if p.As == ABCASE {
-			for ; p != nil && p.As == ABCASE; p = p.Link {
-				p.Rel = casep
-			}
-			break
-		}
-	}
-}
-
 func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
 	autosize := int32(0)
 
@@ -186,65 +274,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
 	cursym.Locals = autoffset
 	cursym.Args = p.To.Val.(int32)
 
-	if ctxt.Debugzerostack != 0 {
-		if autoffset != 0 && p.From3.Offset&obj.NOSPLIT == 0 {
-			// MOVW $4(R13), R1
-			p = obj.Appendp(ctxt, p)
-
-			p.As = AMOVW
-			p.From.Type = obj.TYPE_ADDR
-			p.From.Reg = REG_R13
-			p.From.Offset = 4
-			p.To.Type = obj.TYPE_REG
-			p.To.Reg = REG_R1
-
-			// MOVW $n(R13), R2
-			p = obj.Appendp(ctxt, p)
-
-			p.As = AMOVW
-			p.From.Type = obj.TYPE_ADDR
-			p.From.Reg = REG_R13
-			p.From.Offset = 4 + int64(autoffset)
-			p.To.Type = obj.TYPE_REG
-			p.To.Reg = REG_R2
-
-			// MOVW $0, R3
-			p = obj.Appendp(ctxt, p)
-
-			p.As = AMOVW
-			p.From.Type = obj.TYPE_CONST
-			p.From.Offset = 0
-			p.To.Type = obj.TYPE_REG
-			p.To.Reg = REG_R3
-
-			// L:
-			//	MOVW.nil R3, 0(R1) +4
-			//	CMP R1, R2
-			//	BNE L
-			pl := obj.Appendp(ctxt, p)
-			p := pl
-
-			p.As = AMOVW
-			p.From.Type = obj.TYPE_REG
-			p.From.Reg = REG_R3
-			p.To.Type = obj.TYPE_MEM
-			p.To.Reg = REG_R1
-			p.To.Offset = 4
-			p.Scond |= C_PBIT
-
-			p = obj.Appendp(ctxt, p)
-			p.As = ACMP
-			p.From.Type = obj.TYPE_REG
-			p.From.Reg = REG_R1
-			p.Reg = REG_R2
-
-			p = obj.Appendp(ctxt, p)
-			p.As = ABNE
-			p.To.Type = obj.TYPE_BRANCH
-			p.Pcond = pl
-		}
-	}
-
 	/*
 	 * find leaf subroutines
 	 * strip NOPs
@@ -255,11 +284,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
 	var q *obj.Prog
 	for p := cursym.Text; p != nil; p = p.Link {
 		switch p.As {
-		case ACASE:
-			if ctxt.Flag_shared != 0 {
-				linkcase(p)
-			}
-
 		case obj.ATEXT:
 			p.Mark |= LEAF
 
@@ -289,8 +313,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
 			cursym.Text.Mark &^= LEAF
 			fallthrough
 
-		case ABCASE,
-			AB,
+		case AB,
 			ABEQ,
 			ABNE,
 			ABCS,
@@ -780,8 +803,12 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
 	for last = ctxt.Cursym.Text; last.Link != nil; last = last.Link {
 	}
 
+	spfix := obj.Appendp(ctxt, last)
+	spfix.As = obj.ANOP
+	spfix.Spadj = -framesize
+
 	// MOVW	LR, R3
-	movw := obj.Appendp(ctxt, last)
+	movw := obj.Appendp(ctxt, spfix)
 	movw.As = AMOVW
 	movw.From.Type = obj.TYPE_REG
 	movw.From.Reg = REGLINK
@@ -808,6 +835,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
 	b.As = obj.AJMP
 	b.To.Type = obj.TYPE_BRANCH
 	b.Pcond = ctxt.Cursym.Text.Link
+	b.Spadj = +framesize
 
 	return bls
 }
@@ -973,7 +1001,7 @@ loop:
 	if p.Pcond != nil {
 		if a != ABL && a != ABX && p.Link != nil {
 			q = obj.Brchain(ctxt, p.Link)
-			if a != obj.ATEXT && a != ABCASE {
+			if a != obj.ATEXT {
 				if q != nil && (q.Mark&FOLL != 0) {
 					p.As = int16(relinv(a))
 					p.Link = p.Pcond
diff --git a/src/cmd/internal/obj/arm64/a.out.go b/src/cmd/internal/obj/arm64/a.out.go
index 67b37aa..f459483 100644
--- a/src/cmd/internal/obj/arm64/a.out.go
+++ b/src/cmd/internal/obj/arm64/a.out.go
@@ -321,6 +321,19 @@ const (
 	C_LOREG
 
 	C_ADDR // TODO(aram): explain difference from C_VCONADDR
+
+	// The GOT slot for a symbol in -dynlink mode.
+	C_GOTADDR
+
+	// TLS "var" in local exec mode: will become a constant offset from
+	// thread local base that is ultimately chosen by the program linker.
+	C_TLS_LE
+
+	// TLS "var" in initial exec mode: will become a memory address (chosen
+	// by the program linker) that the dynamic linker will fill with the
+	// offset from the thread local base.
+	C_TLS_IE
+
 	C_ROFF // register offset (including register extended)
 
 	C_GOK
@@ -642,17 +655,8 @@ const (
 	AUCVTFS
 	AUCVTFWD
 	AUCVTFWS
-	AHISTORY
-	ANAME
 	AWORD
-	ADYNT
-	AINIT
-	ABCASE
-	ACASE
 	ADWORD
-	ASIGNAME
-	AGOK
-	AEND
 	AFCSELS
 	AFCSELD
 	AFMAXS
diff --git a/src/cmd/internal/obj/arm64/anames.go b/src/cmd/internal/obj/arm64/anames.go
index 2845418..4ee4043 100644
--- a/src/cmd/internal/obj/arm64/anames.go
+++ b/src/cmd/internal/obj/arm64/anames.go
@@ -312,17 +312,8 @@ var Anames = []string{
 	"UCVTFS",
 	"UCVTFWD",
 	"UCVTFWS",
-	"HISTORY",
-	"NAME",
 	"WORD",
-	"DYNT",
-	"INIT",
-	"BCASE",
-	"CASE",
 	"DWORD",
-	"SIGNAME",
-	"GOK",
-	"END",
 	"FCSELS",
 	"FCSELD",
 	"FMAXS",
diff --git a/src/cmd/internal/obj/arm64/anames7.go b/src/cmd/internal/obj/arm64/anames7.go
index 3ff429f..2d17d17 100644
--- a/src/cmd/internal/obj/arm64/anames7.go
+++ b/src/cmd/internal/obj/arm64/anames7.go
@@ -55,6 +55,9 @@ var cnames7 = []string{
 	"UOREG64K",
 	"LOREG",
 	"ADDR",
+	"GOTADDR",
+	"TLS_LE",
+	"TLS_IE",
 	"ROFF",
 	"GOK",
 	"TEXTSIZE",
diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go
index ab0f7ae..162acd2 100644
--- a/src/cmd/internal/obj/arm64/asm7.go
+++ b/src/cmd/internal/obj/arm64/asm7.go
@@ -147,7 +147,6 @@ func OPBIT(x uint32) uint32 {
 const (
 	LFROM = 1 << 0
 	LTO   = 1 << 1
-	LPOOL = 1 << 2
 )
 
 var optab = []Optab{
@@ -271,6 +270,9 @@ var optab = []Optab{
 	{AMOVH, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
 	{AMOVW, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
 	{AMOVD, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
+	{AMOVD, C_GOTADDR, C_NONE, C_REG, 71, 8, 0, 0, 0},
+	{AMOVD, C_TLS_LE, C_NONE, C_REG, 69, 4, 0, 0, 0},
+	{AMOVD, C_TLS_IE, C_NONE, C_REG, 70, 8, 0, 0, 0},
 	{AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
 	{AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0},
 	{AMADD, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
@@ -468,8 +470,6 @@ var optab = []Optab{
 	{AFCCMPS, C_COND, C_REG, C_VCON, 57, 4, 0, 0, 0},
 	{AFCSELD, C_COND, C_REG, C_FREG, 18, 4, 0, 0, 0},
 	{AFCVTSD, C_FREG, C_NONE, C_FREG, 29, 4, 0, 0, 0},
-	{ACASE, C_REG, C_NONE, C_REG, 62, 4 * 4, 0, 0, 0},
-	{ABCASE, C_NONE, C_NONE, C_SBRA, 63, 4, 0, 0, 0},
 	{ACLREX, C_NONE, C_NONE, C_VCON, 38, 4, 0, 0, 0},
 	{ACLREX, C_NONE, C_NONE, C_NONE, 38, 4, 0, 0, 0},
 	{ACBZ, C_REG, C_NONE, C_SBRA, 39, 4, 0, 0, 0},
@@ -536,9 +536,9 @@ func span7(ctxt *obj.Link, cursym *obj.LSym) {
 		buildop(ctxt)
 	}
 
-	bflag := 0
-	c := int32(0)
-	p.Pc = int64(c)
+	bflag := 1
+	c := int64(0)
+	p.Pc = c
 	var m int
 	var o *Optab
 	for p = p.Link; p != nil; p = p.Link {
@@ -546,11 +546,11 @@ func span7(ctxt *obj.Link, cursym *obj.LSym) {
 		if p.As == ADWORD && (c&7) != 0 {
 			c += 4
 		}
-		p.Pc = int64(c)
+		p.Pc = c
 		o = oplook(ctxt, p)
 		m = int(o.size)
 		if m == 0 {
-			if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA {
+			if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.AUSEFIELD {
 				ctxt.Diag("zero-width instruction\n%v", p)
 			}
 			continue
@@ -568,13 +568,13 @@ func span7(ctxt *obj.Link, cursym *obj.LSym) {
 		if p.As == AB || p.As == obj.ARET || p.As == AERET { /* TODO: other unconditional operations */
 			checkpool(ctxt, p, 0)
 		}
-		c += int32(m)
+		c += int64(m)
 		if ctxt.Blitrl != nil {
 			checkpool(ctxt, p, 1)
 		}
 	}
 
-	cursym.Size = int64(c)
+	cursym.Size = c
 
 	/*
 	 * if any procedure is large enough to
@@ -583,60 +583,57 @@ func span7(ctxt *obj.Link, cursym *obj.LSym) {
 	 * around jmps to fix. this is rare.
 	 */
 	for bflag != 0 {
+		if ctxt.Debugvlog != 0 {
+			fmt.Fprintf(ctxt.Bso, "%5.2f span1\n", obj.Cputime())
+		}
 		bflag = 0
 		c = 0
-		for p = cursym.Text; p != nil; p = p.Link {
+		for p = cursym.Text.Link; p != nil; p = p.Link {
 			if p.As == ADWORD && (c&7) != 0 {
 				c += 4
 			}
-			p.Pc = int64(c)
+			p.Pc = c
 			o = oplook(ctxt, p)
 
-			/* very large branches
-			if(o->type == 6 && p->cond) {
-				otxt = p->cond->pc - c;
-				if(otxt < 0)
-					otxt = -otxt;
-				if(otxt >= (1L<<17) - 10) {
-					q = ctxt->arch->prg();
-					q->link = p->link;
-					p->link = q;
-					q->as = AB;
-					q->to.type = obj.TYPE_BRANCH;
-					q->cond = p->cond;
-					p->cond = q;
-					q = ctxt->arch->prg();
-					q->link = p->link;
-					p->link = q;
-					q->as = AB;
-					q->to.type = obj.TYPE_BRANCH;
-					q->cond = q->link->link;
-					bflag = 1;
+			/* very large branches */
+			if o.type_ == 7 && p.Pcond != nil {
+				otxt := p.Pcond.Pc - c
+				if otxt <= -(1<<18)+10 || otxt >= (1<<18)-10 {
+					q := ctxt.NewProg()
+					q.Link = p.Link
+					p.Link = q
+					q.As = AB
+					q.To.Type = obj.TYPE_BRANCH
+					q.Pcond = p.Pcond
+					p.Pcond = q
+					q = ctxt.NewProg()
+					q.Link = p.Link
+					p.Link = q
+					q.As = AB
+					q.To.Type = obj.TYPE_BRANCH
+					q.Pcond = q.Link.Link
+					bflag = 1
 				}
 			}
-			*/
 			m = int(o.size)
 
 			if m == 0 {
-				if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA {
+				if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.AUSEFIELD {
 					ctxt.Diag("zero-width instruction\n%v", p)
 				}
 				continue
 			}
 
-			c += int32(m)
+			c += int64(m)
 		}
 	}
 
 	c += -c & (FuncAlign - 1)
-	cursym.Size = int64(c)
+	cursym.Size = c
 
 	/*
 	 * lay out the code, emitting code and data relocations.
 	 */
-	if ctxt.Tlsg == nil {
-		ctxt.Tlsg = obj.Linklookup(ctxt, "runtime.tlsg", 0)
-	}
 	obj.Symgrow(ctxt, cursym, cursym.Size)
 	bp := cursym.P
 	psz := int32(0)
@@ -676,7 +673,7 @@ func span7(ctxt *obj.Link, cursym *obj.LSym) {
  * drop the pool now, and branch round it.
  */
 func checkpool(ctxt *obj.Link, p *obj.Prog, skip int) {
-	if pool.size >= 0xffff0 || !(ispcdisp(int32(p.Pc+4+int64(pool.size)-int64(pool.start)+8)) != 0) {
+	if pool.size >= 0xffff0 || !ispcdisp(int32(p.Pc+4+int64(pool.size)-int64(pool.start)+8)) {
 		flushpool(ctxt, p, skip)
 	} else if p.Link == nil {
 		flushpool(ctxt, p, 2)
@@ -696,7 +693,7 @@ func flushpool(ctxt *obj.Link, p *obj.Prog, skip int) {
 			q.Link = ctxt.Blitrl
 			q.Lineno = p.Lineno
 			ctxt.Blitrl = q
-		} else if p.Pc+int64(pool.size)-int64(pool.start) < 1024*1024 {
+		} else if p.Pc+int64(pool.size)-int64(pool.start) < maxPCDisp {
 			return
 		}
 
@@ -829,27 +826,33 @@ func regoff(ctxt *obj.Link, a *obj.Addr) uint32 {
 	return uint32(ctxt.Instoffset)
 }
 
-func ispcdisp(v int32) int {
-	/* pc-relative addressing will reach? */
-	return obj.Bool2int(v >= -0xfffff && v <= 0xfffff && (v&3) == 0)
+// Maximum PC-relative displacement.
+// The actual limit is ±2²⁰, but we are conservative
+// to avoid needing to recompute the literal pool flush points
+// as span-dependent jumps are enlarged.
+const maxPCDisp = 512 * 1024
+
+// ispcdisp reports whether v is a valid PC-relative displacement.
+func ispcdisp(v int32) bool {
+	return -maxPCDisp < v && v < maxPCDisp && v&3 == 0
 }
 
-func isaddcon(v int64) int {
+func isaddcon(v int64) bool {
 	/* uimm12 or uimm24? */
 	if v < 0 {
-		return 0
+		return false
 	}
 	if (v & 0xFFF) == 0 {
 		v >>= 12
 	}
-	return obj.Bool2int(v <= 0xFFF)
+	return v <= 0xFFF
 }
 
-func isbitcon(v uint64) int {
+func isbitcon(v uint64) bool {
 	/*  fancy bimm32 or bimm64? */
 	// TODO(aram):
-	return 0
-	// return obj.Bool2int(findmask(v) != nil || (v>>32) == 0 && findmask(v|(v<<32)) != nil)
+	return false
+	// return findmask(v) != nil || (v>>32) == 0 && findmask(v|(v<<32)) != nil
 }
 
 func autoclass(l int64) int {
@@ -974,10 +977,20 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
 			}
 			ctxt.Instoffset = a.Offset
 			if a.Sym != nil { // use relocation
+				if a.Sym.Type == obj.STLSBSS {
+					if ctxt.Flag_shared != 0 {
+						return C_TLS_IE
+					} else {
+						return C_TLS_LE
+					}
+				}
 				return C_ADDR
 			}
 			return C_LEXT
 
+		case obj.NAME_GOTREF:
+			return C_GOTADDR
+
 		case obj.NAME_AUTO:
 			ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
 			return autoclass(ctxt.Instoffset)
@@ -1010,11 +1023,11 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
 			if v == 0 {
 				return C_ZCON
 			}
-			if isaddcon(v) != 0 {
+			if isaddcon(v) {
 				if v <= 0xFFF {
 					return C_ADDCON0
 				}
-				if isbitcon(uint64(v)) != 0 {
+				if isbitcon(uint64(v)) {
 					return C_ABCON
 				}
 				return C_ADDCON
@@ -1022,7 +1035,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
 
 			t := movcon(v)
 			if t >= 0 {
-				if isbitcon(uint64(v)) != 0 {
+				if isbitcon(uint64(v)) {
 					return C_MBCON
 				}
 				return C_MOVCON
@@ -1030,13 +1043,13 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
 
 			t = movcon(^v)
 			if t >= 0 {
-				if isbitcon(uint64(v)) != 0 {
+				if isbitcon(uint64(v)) {
 					return C_MBCON
 				}
 				return C_MOVCON
 			}
 
-			if isbitcon(uint64(v)) != 0 {
+			if isbitcon(uint64(v)) {
 				return C_BITCON
 			}
 
@@ -1047,10 +1060,12 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
 
 		case obj.NAME_EXTERN,
 			obj.NAME_STATIC:
-			s := a.Sym
-			if s == nil {
+			if a.Sym == nil {
 				break
 			}
+			if a.Sym.Type == obj.STLSBSS {
+				ctxt.Diag("taking address of TLS variable is not supported")
+			}
 			ctxt.Instoffset = a.Offset
 			return C_VCONADDR
 
@@ -1065,7 +1080,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
 		return C_GOK
 
 	aconsize:
-		if isaddcon(ctxt.Instoffset) != 0 {
+		if isaddcon(ctxt.Instoffset) {
 			return C_AACON
 		}
 		return C_LACON
@@ -1570,8 +1585,6 @@ func buildop(ctxt *obj.Link) {
 			ADWORD,
 			obj.ARET,
 			obj.ATEXT,
-			ACASE,
-			ABCASE,
 			ASTP,
 			ALDP:
 			break
@@ -1801,7 +1814,6 @@ func SYSARG4(op1 int, Cn int, Cm int, op2 int) int {
 }
 
 func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
-	var lastcase *obj.Prog
 	o1 := uint32(0)
 	o2 := uint32(0)
 	o3 := uint32(0)
@@ -1899,7 +1911,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
 		rel.Off = int32(ctxt.Pc)
 		rel.Siz = 4
 		rel.Sym = p.To.Sym
-		rel.Add = int64(o1) | (p.To.Offset>>2)&0x3ffffff
+		rel.Add = p.To.Offset
 		rel.Type = obj.R_CALLARM64
 
 	case 6: /* b ,O(R); bl ,O(R) */
@@ -2188,14 +2200,14 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
 	case 24: /* mov/mvn Rs,Rd -> add $0,Rs,Rd or orr Rs,ZR,Rd */
 		rf := int(p.From.Reg)
 		rt := int(p.To.Reg)
-		s := obj.Bool2int(rf == REGSP || rt == REGSP)
+		s := rf == REGSP || rt == REGSP
 		if p.As == AMVN || p.As == AMVNW {
-			if s != 0 {
+			if s {
 				ctxt.Diag("illegal SP reference\n%v", p)
 			}
 			o1 = oprrr(ctxt, int(p.As))
 			o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
-		} else if s != 0 {
+		} else if s {
 			o1 = opirr(ctxt, int(p.As))
 			o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
 		} else {
@@ -2699,28 +2711,6 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
 
 		o1 = ADR(0, uint32(d), uint32(p.To.Reg))
 
-	case 62: /* case Rv, Rt -> adr tab, Rt; movw Rt[R<<2], Rl; add Rt, Rl; br (Rl) */
-		// adr 4(pc), Rt
-		o1 = ADR(0, 4*4, uint32(p.To.Reg))
-		// movw Rt[Rv<<2], REGTMP
-		o2 = (2 << 30) | (7 << 27) | (2 << 22) | (1 << 21) | (3 << 13) | (1 << 12) | (2 << 10) | (uint32(p.From.Reg&31) << 16) | (uint32(p.To.Reg&31) << 5) | REGTMP&31
-		// add Rt, REGTMP
-		o3 = oprrr(ctxt, AADD) | (uint32(p.To.Reg) << 16) | (REGTMP << 5) | REGTMP
-		// br (REGTMP)
-		o4 = (0x6b << 25) | (0x1F << 16) | (REGTMP & 31 << 5)
-		lastcase = p
-
-	case 63: /* bcase */
-		if lastcase == nil {
-			ctxt.Diag("missing CASE\n%v", p)
-			break
-		}
-
-		if p.Pcond != nil {
-			o1 = uint32(p.Pcond.Pc - (lastcase.Pc + 4*4))
-			ctxt.Diag("FIXME: some relocation needed in bcase\n%v", p)
-		}
-
 		/* reloc ops */
 	case 64: /* movT R,addr -> adrp + add + movT R, (REGTMP) */
 		o1 = ADR(1, 0, REGTMP)
@@ -2784,6 +2774,41 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
 		rel.Add = p.From.Offset
 		rel.Type = obj.R_ADDRARM64
 
+	case 69: /* LE model movd $tlsvar, reg -> movz reg, 0 + reloc */
+		o1 = opirr(ctxt, AMOVZ)
+		o1 |= uint32(p.To.Reg & 31)
+		rel := obj.Addrel(ctxt.Cursym)
+		rel.Off = int32(ctxt.Pc)
+		rel.Siz = 4
+		rel.Sym = p.From.Sym
+		rel.Type = obj.R_ARM64_TLS_LE
+		if p.From.Offset != 0 {
+			ctxt.Diag("invalid offset on MOVW $tlsvar")
+		}
+
+	case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */
+		o1 = ADR(1, 0, REGTMP)
+		o2 = olsr12u(ctxt, int32(opldr12(ctxt, AMOVD)), 0, REGTMP, int(p.To.Reg))
+		rel := obj.Addrel(ctxt.Cursym)
+		rel.Off = int32(ctxt.Pc)
+		rel.Siz = 8
+		rel.Sym = p.From.Sym
+		rel.Add = 0
+		rel.Type = obj.R_ARM64_TLS_IE
+		if p.From.Offset != 0 {
+			ctxt.Diag("invalid offset on MOVW $tlsvar")
+		}
+
+	case 71: /* movd sym at GOT, reg -> adrp REGTMP, #0; ldr reg, [REGTMP, #0] + relocs */
+		o1 = ADR(1, 0, REGTMP)
+		o2 = olsr12u(ctxt, int32(opldr12(ctxt, AMOVD)), 0, REGTMP, int(p.To.Reg))
+		rel := obj.Addrel(ctxt.Cursym)
+		rel.Off = int32(ctxt.Pc)
+		rel.Siz = 8
+		rel.Sym = p.From.Sym
+		rel.Add = 0
+		rel.Type = obj.R_ARM64_GOTPCREL
+
 	// This is supposed to be something that stops execution.
 	// It's not supposed to be reached, ever, but if it is, we'd
 	// like to be able to tell how we got there.  Assemble as
@@ -3635,7 +3660,8 @@ func brdist(ctxt *obj.Link, p *obj.Prog, preshift int, flen int, shift int) int6
 		v >>= uint(shift)
 		t = int64(1) << uint(flen-1)
 		if v < -t || v >= t {
-			ctxt.Diag("branch too far\n%v", p)
+			ctxt.Diag("branch too far %#x vs %#x [%p]\n%v\n%v", v, t, ctxt.Blitrl, p, p.Pcond)
+			panic("branch too far")
 		}
 	}
 
diff --git a/src/cmd/internal/obj/arm64/obj7.go b/src/cmd/internal/obj/arm64/obj7.go
index f43ce03..93c4b1a 100644
--- a/src/cmd/internal/obj/arm64/obj7.go
+++ b/src/cmd/internal/obj/arm64/obj7.go
@@ -161,8 +161,12 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
 	for last = ctxt.Cursym.Text; last.Link != nil; last = last.Link {
 	}
 
+	spfix := obj.Appendp(ctxt, last)
+	spfix.As = obj.ANOP
+	spfix.Spadj = -framesize
+
 	// MOV	LR, R3
-	movlr := obj.Appendp(ctxt, last)
+	movlr := obj.Appendp(ctxt, spfix)
 	movlr.As = AMOVD
 	movlr.From.Type = obj.TYPE_REG
 	movlr.From.Reg = REGLINK
@@ -201,6 +205,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
 	jmp.As = AB
 	jmp.To.Type = obj.TYPE_BRANCH
 	jmp.Pcond = ctxt.Cursym.Text.Link
+	jmp.Spadj = +framesize
 
 	// placeholder for bls's jump target
 	// p = obj.Appendp(ctxt, p)
@@ -250,6 +255,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
 			s.Size = 4
 			p.From.Type = obj.TYPE_MEM
 			p.From.Sym = s
+			p.From.Sym.Local = true
 			p.From.Name = obj.NAME_EXTERN
 			p.From.Offset = 0
 		}
@@ -262,6 +268,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
 			s.Size = 8
 			p.From.Type = obj.TYPE_MEM
 			p.From.Sym = s
+			p.From.Sym.Local = true
 			p.From.Name = obj.NAME_EXTERN
 			p.From.Offset = 0
 		}
@@ -287,6 +294,121 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
 
 		break
 	}
+
+	if ctxt.Flag_dynlink {
+		rewriteToUseGot(ctxt, p)
+	}
+}
+
+// Rewrite p, if necessary, to access global data via the global offset table.
+func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog) {
+	if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
+		//     ADUFFxxx $offset
+		// becomes
+		//     MOVD runtime.duffxxx at GOT, REGTMP
+		//     ADD $offset, REGTMP
+		//     CALL REGTMP
+		var sym *obj.LSym
+		if p.As == obj.ADUFFZERO {
+			sym = obj.Linklookup(ctxt, "runtime.duffzero", 0)
+		} else {
+			sym = obj.Linklookup(ctxt, "runtime.duffcopy", 0)
+		}
+		offset := p.To.Offset
+		p.As = AMOVD
+		p.From.Type = obj.TYPE_MEM
+		p.From.Name = obj.NAME_GOTREF
+		p.From.Sym = sym
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = REGTMP
+		p.To.Name = obj.NAME_NONE
+		p.To.Offset = 0
+		p.To.Sym = nil
+		p1 := obj.Appendp(ctxt, p)
+		p1.As = AADD
+		p1.From.Type = obj.TYPE_CONST
+		p1.From.Offset = offset
+		p1.To.Type = obj.TYPE_REG
+		p1.To.Reg = REGTMP
+		p2 := obj.Appendp(ctxt, p1)
+		p2.As = obj.ACALL
+		p2.To.Type = obj.TYPE_REG
+		p2.To.Reg = REGTMP
+	}
+
+	// We only care about global data: NAME_EXTERN means a global
+	// symbol in the Go sense, and p.Sym.Local is true for a few
+	// internally defined symbols.
+	if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
+		// MOVD $sym, Rx becomes MOVD sym at GOT, Rx
+		// MOVD $sym+<off>, Rx becomes MOVD sym at GOT, Rx; ADD <off>, Rx
+		if p.As != AMOVD {
+			ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p)
+		}
+		if p.To.Type != obj.TYPE_REG {
+			ctxt.Diag("do not know how to handle LEAQ-type insn to non-register in %v with -dynlink", p)
+		}
+		p.From.Type = obj.TYPE_MEM
+		p.From.Name = obj.NAME_GOTREF
+		if p.From.Offset != 0 {
+			q := obj.Appendp(ctxt, p)
+			q.As = AADD
+			q.From.Type = obj.TYPE_CONST
+			q.From.Offset = p.From.Offset
+			q.To = p.To
+			p.From.Offset = 0
+		}
+	}
+	if p.From3 != nil && p.From3.Name == obj.NAME_EXTERN {
+		ctxt.Diag("don't know how to handle %v with -dynlink", p)
+	}
+	var source *obj.Addr
+	// MOVx sym, Ry becomes MOVD sym at GOT, REGTMP; MOVx (REGTMP), Ry
+	// MOVx Ry, sym becomes MOVD sym at GOT, REGTMP; MOVD Ry, (REGTMP)
+	// An addition may be inserted between the two MOVs if there is an offset.
+	if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
+		if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
+			ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
+		}
+		source = &p.From
+	} else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
+		source = &p.To
+	} else {
+		return
+	}
+	if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
+		return
+	}
+	if source.Sym.Type == obj.STLSBSS {
+		return
+	}
+	if source.Type != obj.TYPE_MEM {
+		ctxt.Diag("don't know how to handle %v with -dynlink", p)
+	}
+	p1 := obj.Appendp(ctxt, p)
+	p2 := obj.Appendp(ctxt, p1)
+	p1.As = AMOVD
+	p1.From.Type = obj.TYPE_MEM
+	p1.From.Sym = source.Sym
+	p1.From.Name = obj.NAME_GOTREF
+	p1.To.Type = obj.TYPE_REG
+	p1.To.Reg = REGTMP
+
+	p2.As = p.As
+	p2.From = p.From
+	p2.To = p.To
+	if p.From.Name == obj.NAME_EXTERN {
+		p2.From.Reg = REGTMP
+		p2.From.Name = obj.NAME_NONE
+		p2.From.Sym = nil
+	} else if p.To.Name == obj.NAME_EXTERN {
+		p2.To.Reg = REGTMP
+		p2.To.Name = obj.NAME_NONE
+		p2.To.Sym = nil
+	} else {
+		return
+	}
+	obj.Nopout(p)
 }
 
 func follow(ctxt *obj.Link, s *obj.LSym) {
@@ -440,7 +562,7 @@ loop:
 	if p.Pcond != nil {
 		if a != ABL && p.Link != nil {
 			q = obj.Brchain(ctxt, p.Link)
-			if a != obj.ATEXT && a != ABCASE {
+			if a != obj.ATEXT {
 				if q != nil && (q.Mark&FOLL != 0) {
 					p.As = int16(relinv(a))
 					p.Link = p.Pcond
@@ -515,7 +637,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
 			ACBZW,
 			ATBZ,
 			ATBNZ,
-			ABCASE,
 			AB,
 			ABEQ,
 			ABNE,
diff --git a/src/cmd/internal/obj/data.go b/src/cmd/internal/obj/data.go
index 6e01e6e..96129fd 100644
--- a/src/cmd/internal/obj/data.go
+++ b/src/cmd/internal/obj/data.go
@@ -36,10 +36,6 @@ import (
 	"math"
 )
 
-func mangle(file string) {
-	log.Fatalf("%s: mangled input file", file)
-}
-
 func Symgrow(ctxt *Link, s *LSym, lsiz int64) {
 	siz := int(lsiz)
 	if int64(siz) != lsiz {
@@ -48,21 +44,26 @@ func Symgrow(ctxt *Link, s *LSym, lsiz int64) {
 	if len(s.P) >= siz {
 		return
 	}
+	// TODO(dfc) append cap-len at once, rather than
+	// one byte at a time.
 	for cap(s.P) < siz {
 		s.P = append(s.P[:cap(s.P)], 0)
 	}
 	s.P = s.P[:siz]
 }
 
-func savedata(ctxt *Link, s *LSym, p *Prog, pn string) {
+func savedata(ctxt *Link, s *LSym, p *Prog, file string) {
 	off := int32(p.From.Offset)
 	siz := int32(p.From3.Offset)
 	if off < 0 || siz < 0 || off >= 1<<30 || siz >= 100 {
-		mangle(pn)
+		log.Fatalf("%s: mangled input file", file)
 	}
 	if ctxt.Enforce_data_order != 0 && off < int32(len(s.P)) {
 		ctxt.Diag("data out of order (already have %d)\n%v", len(s.P), p)
 	}
+	if s.Type == SBSS || s.Type == STLSBSS {
+		ctxt.Diag("cannot supply data for BSS var")
+	}
 	Symgrow(ctxt, s, int64(off+siz))
 
 	switch int(p.To.Type) {
@@ -139,130 +140,3 @@ func Setuintxx(ctxt *Link, s *LSym, off int64, v uint64, wid int64) int64 {
 
 	return off + wid
 }
-
-func adduintxx(ctxt *Link, s *LSym, v uint64, wid int) int64 {
-	off := s.Size
-	Setuintxx(ctxt, s, off, v, int64(wid))
-	return off
-}
-
-func adduint8(ctxt *Link, s *LSym, v uint8) int64 {
-	return adduintxx(ctxt, s, uint64(v), 1)
-}
-
-func adduint16(ctxt *Link, s *LSym, v uint16) int64 {
-	return adduintxx(ctxt, s, uint64(v), 2)
-}
-
-func Adduint32(ctxt *Link, s *LSym, v uint32) int64 {
-	return adduintxx(ctxt, s, uint64(v), 4)
-}
-
-func Adduint64(ctxt *Link, s *LSym, v uint64) int64 {
-	return adduintxx(ctxt, s, v, 8)
-}
-
-func setuint8(ctxt *Link, s *LSym, r int64, v uint8) int64 {
-	return Setuintxx(ctxt, s, r, uint64(v), 1)
-}
-
-func setuint16(ctxt *Link, s *LSym, r int64, v uint16) int64 {
-	return Setuintxx(ctxt, s, r, uint64(v), 2)
-}
-
-func setuint32(ctxt *Link, s *LSym, r int64, v uint32) int64 {
-	return Setuintxx(ctxt, s, r, uint64(v), 4)
-}
-
-func setuint64(ctxt *Link, s *LSym, r int64, v uint64) int64 {
-	return Setuintxx(ctxt, s, r, v, 8)
-}
-
-func addaddrplus(ctxt *Link, s *LSym, t *LSym, add int64) int64 {
-	if s.Type == 0 {
-		s.Type = SDATA
-	}
-	i := s.Size
-	s.Size += int64(ctxt.Arch.Ptrsize)
-	Symgrow(ctxt, s, s.Size)
-	r := Addrel(s)
-	r.Sym = t
-	r.Off = int32(i)
-	r.Siz = uint8(ctxt.Arch.Ptrsize)
-	r.Type = R_ADDR
-	r.Add = add
-	return i + int64(r.Siz)
-}
-
-func addpcrelplus(ctxt *Link, s *LSym, t *LSym, add int64) int64 {
-	if s.Type == 0 {
-		s.Type = SDATA
-	}
-	i := s.Size
-	s.Size += 4
-	Symgrow(ctxt, s, s.Size)
-	r := Addrel(s)
-	r.Sym = t
-	r.Off = int32(i)
-	r.Add = add
-	r.Type = R_PCREL
-	r.Siz = 4
-	return i + int64(r.Siz)
-}
-
-func addaddr(ctxt *Link, s *LSym, t *LSym) int64 {
-	return addaddrplus(ctxt, s, t, 0)
-}
-
-func setaddrplus(ctxt *Link, s *LSym, off int64, t *LSym, add int64) int64 {
-	if s.Type == 0 {
-		s.Type = SDATA
-	}
-	if off+int64(ctxt.Arch.Ptrsize) > s.Size {
-		s.Size = off + int64(ctxt.Arch.Ptrsize)
-		Symgrow(ctxt, s, s.Size)
-	}
-
-	r := Addrel(s)
-	r.Sym = t
-	r.Off = int32(off)
-	r.Siz = uint8(ctxt.Arch.Ptrsize)
-	r.Type = R_ADDR
-	r.Add = add
-	return off + int64(r.Siz)
-}
-
-func setaddr(ctxt *Link, s *LSym, off int64, t *LSym) int64 {
-	return setaddrplus(ctxt, s, off, t, 0)
-}
-
-func addsize(ctxt *Link, s *LSym, t *LSym) int64 {
-	if s.Type == 0 {
-		s.Type = SDATA
-	}
-	i := s.Size
-	s.Size += int64(ctxt.Arch.Ptrsize)
-	Symgrow(ctxt, s, s.Size)
-	r := Addrel(s)
-	r.Sym = t
-	r.Off = int32(i)
-	r.Siz = uint8(ctxt.Arch.Ptrsize)
-	r.Type = R_SIZE
-	return i + int64(r.Siz)
-}
-
-func addaddrplus4(ctxt *Link, s *LSym, t *LSym, add int64) int64 {
-	if s.Type == 0 {
-		s.Type = SDATA
-	}
-	i := s.Size
-	s.Size += 4
-	Symgrow(ctxt, s, s.Size)
-	r := Addrel(s)
-	r.Sym = t
-	r.Off = int32(i)
-	r.Siz = 4
-	r.Type = R_ADDR
-	r.Add = add
-	return i + int64(r.Siz)
-}
diff --git a/src/cmd/internal/obj/fmt.go b/src/cmd/internal/obj/fmt.go
index 1268f42..f98bc6d 100644
--- a/src/cmd/internal/obj/fmt.go
+++ b/src/cmd/internal/obj/fmt.go
@@ -17,18 +17,12 @@ package obj
 const (
 	FmtWidth = 1 << iota
 	FmtLeft
-	FmtPrec
 	FmtSharp
-	FmtSpace
 	FmtSign
-	FmtApost
-	FmtZero
 	FmtUnsigned
 	FmtShort
 	FmtLong
-	FmtVLong
 	FmtComma
 	FmtByte
-	FmtLDouble
-	FmtFlag
+	FmtBody // for printing export bodies
 )
diff --git a/src/cmd/internal/obj/funcdata.go b/src/cmd/internal/obj/funcdata.go
index 44cba7a..5291302 100644
--- a/src/cmd/internal/obj/funcdata.go
+++ b/src/cmd/internal/obj/funcdata.go
@@ -1,39 +1,9 @@
-// Inferno utils/5c/list.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5c/list.c
-//
-//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//	Portions Copyright © 1995-1997 C H Forsyth (forsyth at terzarima.net)
-//	Portions Copyright © 1997-1999 Vita Nuova Limited
-//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//	Portions Copyright © 2004,2006 Bruce Ellis
-//	Portions Copyright © 2005-2007 C H Forsyth (forsyth at terzarima.net)
-//	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package obj
-
 // Copyright 2013 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 obj
+
 // This file defines the IDs for PCDATA and FUNCDATA instructions
 // in Go binaries. It is included by assembly sources, so it must
 // be written using #defines.
@@ -74,6 +44,5 @@ const (
 	PCDATA_StackMapIndex       = 0
 	FUNCDATA_ArgsPointerMaps   = 0
 	FUNCDATA_LocalsPointerMaps = 1
-	FUNCDATA_DeadValueMaps     = 2
 	ArgsSizeUnknown            = -0x80000000
 )
diff --git a/src/cmd/internal/obj/libc.go b/src/cmd/internal/obj/libc.go
deleted file mode 100644
index b200b26..0000000
--- a/src/cmd/internal/obj/libc.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2015 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 obj
-
-const (
-	AEXIST = 0
-	BOM    = 0xFEFF
-)
-
-var GOEXPERIMENT string
diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go
index 688c278..762a49e 100644
--- a/src/cmd/internal/obj/link.go
+++ b/src/cmd/internal/obj/link.go
@@ -247,10 +247,11 @@ func (p *Prog) From3Offset() int64 {
 // by clients such as the compiler. The exact meaning of this
 // data is up to the client and is not interpreted by the cmd/internal/obj/... packages.
 type ProgInfo struct {
-	Flags    uint32 // flag bits
-	Reguse   uint64 // registers implicitly used by this instruction
-	Regset   uint64 // registers implicitly set by this instruction
-	Regindex uint64 // registers used by addressing mode
+	_        struct{} // to prevent unkeyed literals. Trailing zero-sized field will take space.
+	Flags    uint32   // flag bits
+	Reguse   uint64   // registers implicitly used by this instruction
+	Regset   uint64   // registers implicitly set by this instruction
+	Regindex uint64   // registers used by addressing mode
 }
 
 // Prog.as opcodes.
@@ -281,6 +282,7 @@ const (
 	AUSEFIELD
 	AVARDEF
 	AVARKILL
+	AVARLIVE
 	A_ARCHSPECIFIC
 )
 
@@ -333,6 +335,7 @@ const (
 	Sxxx = iota
 	STEXT
 	SELFRXSECT
+
 	STYPE
 	SSTRING
 	SGOSTRING
@@ -340,6 +343,25 @@ const (
 	SGCBITS
 	SRODATA
 	SFUNCTAB
+
+	// Types STYPE-SFUNCTAB above are written to the .rodata section by default.
+	// When linking a shared object, some conceptually "read only" types need to
+	// be written to by relocations and putting them in a section called
+	// ".rodata" interacts poorly with the system linkers. The GNU linkers
+	// support this situation by arranging for sections of the name
+	// ".data.rel.ro.XXX" to be mprotected read only by the dynamic linker after
+	// relocations have applied, so when the Go linker is creating a shared
+	// object it checks all objects of the above types and bumps any object that
+	// has a relocation to it to the corresponding type below, which are then
+	// written to sections with appropriate magic names.
+	STYPERELRO
+	SSTRINGRELRO
+	SGOSTRINGRELRO
+	SGOFUNCRELRO
+	SGCBITSRELRO
+	SRODATARELRO
+	SFUNCTABRELRO
+
 	STYPELINK
 	SSYMTAB
 	SPCLNTAB
@@ -383,33 +405,39 @@ type Reloc struct {
 // Reloc.type
 const (
 	R_ADDR = 1 + iota
+	// R_ADDRPOWER relocates a pair of "D-form" instructions (instructions with 16-bit
+	// immediates in the low half of the instruction word), usually addis followed by
+	// another add or a load, inserting the "high adjusted" 16 bits of the address of
+	// the referenced symbol into the immediate field of the first instruction and the
+	// low 16 bits into that of the second instruction.
 	R_ADDRPOWER
+	// R_ADDRARM64 relocates an adrp, add pair to compute the address of the
+	// referenced symbol.
 	R_ADDRARM64
+	// R_ADDRMIPS (only used on mips64) resolves to a 32-bit external address,
+	// by loading the address into a register with two instructions (lui, ori).
+	R_ADDRMIPS
 	R_SIZE
 	R_CALL
 	R_CALLARM
 	R_CALLARM64
 	R_CALLIND
 	R_CALLPOWER
+	// R_CALLMIPS (only used on mips64) resolves to non-PC-relative target address
+	// of a CALL (JAL) instruction, by encoding the address into the instruction.
+	R_CALLMIPS
 	R_CONST
 	R_PCREL
-	// R_TLS (only used on arm currently, and not on android and darwin where tlsg is
-	// a regular variable) resolves to data needed to access the thread-local g. It is
-	// interpreted differently depending on toolchain flags to implement either the
-	// "local exec" or "inital exec" model for tls access.
-	// TODO(mwhudson): change to use R_TLS_LE or R_TLS_IE as appropriate, not having
-	// R_TLS do double duty.
-	R_TLS
-	// R_TLS_LE (only used on 386 and amd64 currently) resolves to the offset of the
-	// thread-local g from the thread local base and is used to implement the "local
-	// exec" model for tls access (r.Sym is not set by the compiler for this case but
-	// is set to Tlsg in the linker when externally linking).
+	// R_TLS_LE, used on 386, amd64, and ARM, resolves to the offset of the
+	// thread-local symbol from the thread local base and is used to implement the
+	// "local exec" model for tls access (r.Sym is not set on intel platforms but is
+	// set to a TLS symbol -- runtime.tlsg -- in the linker when externally linking).
 	R_TLS_LE
-	// R_TLS_IE (only used on 386 and amd64 currently) resolves to the PC-relative
-	// offset to a GOT slot containing the offset the thread-local g from the thread
-	// local base and is used to implemented the "initial exec" model for tls access
-	// (r.Sym is not set by the compiler for this case but is set to Tlsg in the
-	// linker when externally linking).
+	// R_TLS_IE, used 386, amd64, and ARM resolves to the PC-relative offset to a GOT
+	// slot containing the offset from the thread-local symbol from the thread local
+	// base and is used to implemented the "initial exec" model for tls access (r.Sym
+	// is not set on intel platforms but is set to a TLS symbol -- runtime.tlsg -- in
+	// the linker when externally linking).
 	R_TLS_IE
 	R_GOTOFF
 	R_PLT0
@@ -418,6 +446,81 @@ const (
 	R_USEFIELD
 	R_POWER_TOC
 	R_GOTPCREL
+	// R_JMPMIPS (only used on mips64) resolves to non-PC-relative target address
+	// of a JMP instruction, by encoding the address into the instruction.
+	// The stack nosplit check ignores this since it is not a function call.
+	R_JMPMIPS
+
+	// Platform dependent relocations. Architectures with fixed width instructions
+	// have the inherent issue that a 32-bit (or 64-bit!) displacement cannot be
+	// stuffed into a 32-bit instruction, so an address needs to be spread across
+	// several instructions, and in turn this requires a sequence of relocations, each
+	// updating a part of an instruction.  This leads to relocation codes that are
+	// inherently processor specific.
+
+	// Arm64.
+
+	// Set a MOV[NZ] immediate field to bits [15:0] of the offset from the thread
+	// local base to the thread local variable defined by the referenced (thread
+	// local) symbol. Error if the offset does not fit into 16 bits.
+	R_ARM64_TLS_LE
+
+	// Relocates an ADRP; LD64 instruction sequence to load the offset between
+	// the thread local base and the thread local variable defined by the
+	// referenced (thread local) symbol from the GOT.
+	R_ARM64_TLS_IE
+
+	// R_ARM64_GOTPCREL relocates an adrp, ld64 pair to compute the address of the GOT
+	// slot of the referenced symbol.
+	R_ARM64_GOTPCREL
+
+	// PPC64.
+
+	// R_POWER_TLS_LE is used to implement the "local exec" model for tls
+	// access. It resolves to the offset of the thread-local symbol from the
+	// thread pointer (R13) and inserts this value into the low 16 bits of an
+	// instruction word.
+	R_POWER_TLS_LE
+
+	// R_POWER_TLS_IE is used to implement the "initial exec" model for tls access. It
+	// relocates a D-form, DS-form instruction sequence like R_ADDRPOWER_DS. It
+	// inserts to the offset of GOT slot for the thread-local symbol from the TOC (the
+	// GOT slot is filled by the dynamic linker with the offset of the thread-local
+	// symbol from the thread pointer (R13)).
+	R_POWER_TLS_IE
+
+	// R_POWER_TLS marks an X-form instruction such as "MOVD 0(R13)(R31*1), g" as
+	// accessing a particular thread-local symbol. It does not affect code generation
+	// but is used by the system linker when relaxing "initial exec" model code to
+	// "local exec" model code.
+	R_POWER_TLS
+
+	// R_ADDRPOWER_DS is similar to R_ADDRPOWER above, but assumes the second
+	// instruction is a "DS-form" instruction, which has an immediate field occupying
+	// bits [15:2] of the instruction word. Bits [15:2] of the address of the
+	// relocated symbol are inserted into this field; it is an error if the last two
+	// bits of the address are not 0.
+	R_ADDRPOWER_DS
+
+	// R_ADDRPOWER_PCREL relocates a D-form, DS-form instruction sequence like
+	// R_ADDRPOWER_DS but inserts the offset of the GOT slot for the referenced symbol
+	// from the TOC rather than the symbol's address.
+	R_ADDRPOWER_GOT
+
+	// R_ADDRPOWER_PCREL relocates two D-form instructions like R_ADDRPOWER, but
+	// inserts the displacement from the place being relocated to the address of the
+	// the relocated symbol instead of just its address.
+	R_ADDRPOWER_PCREL
+
+	// R_ADDRPOWER_TOCREL relocates two D-form instructions like R_ADDRPOWER, but
+	// inserts the offset from the TOC to the address of the the relocated symbol
+	// rather than the symbol's address.
+	R_ADDRPOWER_TOCREL
+
+	// R_ADDRPOWER_TOCREL relocates a D-form, DS-form instruction sequence like
+	// 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
 )
 
 type Auto struct {
@@ -465,7 +568,6 @@ type Link struct {
 	Arch               *LinkArch
 	Debugasm           int32
 	Debugvlog          int32
-	Debugzerostack     int32
 	Debugdivmod        int32
 	Debugpcln          int32
 	Flag_shared        int32
@@ -485,13 +587,13 @@ type Link struct {
 	Sym_divu           *LSym
 	Sym_mod            *LSym
 	Sym_modu           *LSym
-	Tlsg               *LSym
 	Plan9privates      *LSym
 	Curp               *Prog
 	Printp             *Prog
 	Blitrl             *Prog
 	Elitrl             *Prog
 	Rexflag            int
+	Vexflag            int
 	Rep                int
 	Repn               int
 	Lock               int
@@ -502,13 +604,41 @@ type Link struct {
 	Autosize           int32
 	Armsize            int32
 	Pc                 int64
-	Tlsoffset          int
-	Diag               func(string, ...interface{})
+	DiagFunc           func(string, ...interface{})
 	Mode               int
 	Cursym             *LSym
 	Version            int
 	Textp              *LSym
 	Etextp             *LSym
+	Errors             int
+
+	// state for writing objects
+	Text  *LSym
+	Data  *LSym
+	Etext *LSym
+	Edata *LSym
+}
+
+func (ctxt *Link) Diag(format string, args ...interface{}) {
+	ctxt.Errors++
+	ctxt.DiagFunc(format, args...)
+}
+
+// The smallest possible offset from the hardware stack pointer to a local
+// variable on the stack. Architectures that use a link register save its value
+// on the stack in the function prologue and so always have a pointer between
+// the hardware stack pointer and the local variable area.
+func (ctxt *Link) FixedFrameSize() int64 {
+	switch ctxt.Arch.Thechar {
+	case '6', '8':
+		return 0
+	case '9':
+		// PIC code on ppc64le requires 32 bytes of stack, and it's easier to
+		// just use that much stack always on ppc64x.
+		return int64(4 * ctxt.Arch.Ptrsize)
+	default:
+		return int64(ctxt.Arch.Ptrsize)
+	}
 }
 
 type SymVer struct {
diff --git a/src/cmd/internal/obj/mgc0.go b/src/cmd/internal/obj/mgc0.go
deleted file mode 100644
index a385d60..0000000
--- a/src/cmd/internal/obj/mgc0.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2013 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 obj
-
-// Garbage collector liveness bitmap generation.
-
-// The command line flag -live causes this code to print debug information.
-// The levels are:
-//
-//	-live (aka -live=1): print liveness lists as code warnings at safe points
-//	-live=2: print an assembly listing with liveness annotations
-//	-live=3: print information during each computation phase (much chattier)
-//
-// Each level includes the earlier output as well.
-
-// Copyright 2012 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.
-
-// Used by cmd/gc.
-
-const (
-	InsData = 1 + iota
-	InsArray
-	InsArrayEnd
-	InsEnd
-	MaxGCMask = 65536
-)
diff --git a/src/cmd/internal/obj/mips/a.out.go b/src/cmd/internal/obj/mips/a.out.go
new file mode 100644
index 0000000..282cb79
--- /dev/null
+++ b/src/cmd/internal/obj/mips/a.out.go
@@ -0,0 +1,376 @@
+// cmd/9c/9.out.h from Vita Nuova.
+//
+//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//	Portions Copyright © 1995-1997 C H Forsyth (forsyth at terzarima.net)
+//	Portions Copyright © 1997-1999 Vita Nuova Limited
+//	Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+//	Portions Copyright © 2004,2006 Bruce Ellis
+//	Portions Copyright © 2005-2007 C H Forsyth (forsyth at terzarima.net)
+//	Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
+//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package mips
+
+import "cmd/internal/obj"
+
+//go:generate go run ../stringer.go -i $GOFILE -o anames.go -p mips
+
+/*
+ * mips 64
+ */
+const (
+	NSNAME = 8
+	NSYM   = 50
+	NREG   = 32 /* number of general registers */
+	NFREG  = 32 /* number of floating point registers */
+)
+
+const (
+	REG_R0 = obj.RBaseMIPS64 + iota
+	REG_R1
+	REG_R2
+	REG_R3
+	REG_R4
+	REG_R5
+	REG_R6
+	REG_R7
+	REG_R8
+	REG_R9
+	REG_R10
+	REG_R11
+	REG_R12
+	REG_R13
+	REG_R14
+	REG_R15
+	REG_R16
+	REG_R17
+	REG_R18
+	REG_R19
+	REG_R20
+	REG_R21
+	REG_R22
+	REG_R23
+	REG_R24
+	REG_R25
+	REG_R26
+	REG_R27
+	REG_R28
+	REG_R29
+	REG_R30
+	REG_R31
+
+	REG_F0
+	REG_F1
+	REG_F2
+	REG_F3
+	REG_F4
+	REG_F5
+	REG_F6
+	REG_F7
+	REG_F8
+	REG_F9
+	REG_F10
+	REG_F11
+	REG_F12
+	REG_F13
+	REG_F14
+	REG_F15
+	REG_F16
+	REG_F17
+	REG_F18
+	REG_F19
+	REG_F20
+	REG_F21
+	REG_F22
+	REG_F23
+	REG_F24
+	REG_F25
+	REG_F26
+	REG_F27
+	REG_F28
+	REG_F29
+	REG_F30
+	REG_F31
+
+	REG_HI
+	REG_LO
+
+	// co-processor 0 control registers
+	REG_M0
+	REG_M1
+	REG_M2
+	REG_M3
+	REG_M4
+	REG_M5
+	REG_M6
+	REG_M7
+	REG_M8
+	REG_M9
+	REG_M10
+	REG_M11
+	REG_M12
+	REG_M13
+	REG_M14
+	REG_M15
+	REG_M16
+	REG_M17
+	REG_M18
+	REG_M19
+	REG_M20
+	REG_M21
+	REG_M22
+	REG_M23
+	REG_M24
+	REG_M25
+	REG_M26
+	REG_M27
+	REG_M28
+	REG_M29
+	REG_M30
+	REG_M31
+
+	// FPU control registers
+	REG_FCR0
+	REG_FCR1
+	REG_FCR2
+	REG_FCR3
+	REG_FCR4
+	REG_FCR5
+	REG_FCR6
+	REG_FCR7
+	REG_FCR8
+	REG_FCR9
+	REG_FCR10
+	REG_FCR11
+	REG_FCR12
+	REG_FCR13
+	REG_FCR14
+	REG_FCR15
+	REG_FCR16
+	REG_FCR17
+	REG_FCR18
+	REG_FCR19
+	REG_FCR20
+	REG_FCR21
+	REG_FCR22
+	REG_FCR23
+	REG_FCR24
+	REG_FCR25
+	REG_FCR26
+	REG_FCR27
+	REG_FCR28
+	REG_FCR29
+	REG_FCR30
+	REG_FCR31
+
+	REG_LAST = REG_FCR31 // the last defined register
+
+	REG_SPECIAL = REG_M0
+
+	REGZERO  = REG_R0 /* set to zero */
+	REGSP    = REG_R29
+	REGSB    = REG_R30
+	REGLINK  = REG_R31
+	REGRET   = REG_R1
+	REGARG   = -1      /* -1 disables passing the first argument in register */
+	REGRT1   = REG_R1  /* reserved for runtime, duffzero and duffcopy */
+	REGRT2   = REG_R2  /* reserved for runtime, duffcopy */
+	REGCTXT  = REG_R22 /* context for closures */
+	REGG     = REG_R30 /* G */
+	REGTMP   = REG_R28 /* used by the linker */
+	FREGRET  = REG_F0
+	FREGZERO = REG_F24 /* both float and double */
+	FREGHALF = REG_F26 /* double */
+	FREGONE  = REG_F28 /* double */
+	FREGTWO  = REG_F30 /* double */
+)
+
+const (
+	BIG = 32766
+)
+
+const (
+	/* mark flags */
+	FOLL    = 1 << 0
+	LABEL   = 1 << 1
+	LEAF    = 1 << 2
+	SYNC    = 1 << 3
+	BRANCH  = 1 << 4
+	LOAD    = 1 << 5
+	FCMP    = 1 << 6
+	NOSCHED = 1 << 7
+
+	NSCHED = 20
+)
+
+const (
+	C_NONE = iota
+	C_REG
+	C_FREG
+	C_FCREG
+	C_MREG /* special processor register */
+	C_HI
+	C_LO
+	C_ZCON
+	C_SCON /* 16 bit signed */
+	C_UCON /* 32 bit signed, low 16 bits 0 */
+	C_ADD0CON
+	C_AND0CON
+	C_ADDCON /* -0x8000 <= v < 0 */
+	C_ANDCON /* 0 < v <= 0xFFFF */
+	C_LCON   /* other 32 */
+	C_DCON   /* other 64 (could subdivide further) */
+	C_SACON  /* $n(REG) where n <= int16 */
+	C_SECON
+	C_LACON /* $n(REG) where int16 < n <= int32 */
+	C_LECON
+	C_DACON /* $n(REG) where int32 < n */
+	C_SBRA
+	C_LBRA
+	C_SAUTO
+	C_LAUTO
+	C_SEXT
+	C_LEXT
+	C_ZOREG
+	C_SOREG
+	C_LOREG
+	C_GOK
+	C_ADDR
+	C_TEXTSIZE
+
+	C_NCLASS /* must be the last */
+)
+
+const (
+	AABSD = obj.ABaseMIPS64 + obj.A_ARCHSPECIFIC + iota
+	AABSF
+	AABSW
+	AADD
+	AADDD
+	AADDF
+	AADDU
+	AADDW
+	AAND
+	ABEQ
+	ABFPF
+	ABFPT
+	ABGEZ
+	ABGEZAL
+	ABGTZ
+	ABLEZ
+	ABLTZ
+	ABLTZAL
+	ABNE
+	ABREAK
+	ACMPEQD
+	ACMPEQF
+	ACMPGED
+	ACMPGEF
+	ACMPGTD
+	ACMPGTF
+	ADIV
+	ADIVD
+	ADIVF
+	ADIVU
+	ADIVW
+	AGOK
+	AMOVB
+	AMOVBU
+	AMOVD
+	AMOVDF
+	AMOVDW
+	AMOVF
+	AMOVFD
+	AMOVFW
+	AMOVH
+	AMOVHU
+	AMOVW
+	AMOVWD
+	AMOVWF
+	AMOVWL
+	AMOVWR
+	AMUL
+	AMULD
+	AMULF
+	AMULU
+	AMULW
+	ANEGD
+	ANEGF
+	ANEGW
+	ANOR
+	AOR
+	AREM
+	AREMU
+	ARFE
+	ASGT
+	ASGTU
+	ASLL
+	ASRA
+	ASRL
+	ASUB
+	ASUBD
+	ASUBF
+	ASUBU
+	ASUBW
+	ASYSCALL
+	ATLBP
+	ATLBR
+	ATLBWI
+	ATLBWR
+	AWORD
+	AXOR
+
+	/* 64-bit */
+	AMOVV
+	AMOVVL
+	AMOVVR
+	ASLLV
+	ASRAV
+	ASRLV
+	ADIVV
+	ADIVVU
+	AREMV
+	AREMVU
+	AMULV
+	AMULVU
+	AADDV
+	AADDVU
+	ASUBV
+	ASUBVU
+
+	/* 64-bit FP */
+	ATRUNCFV
+	ATRUNCDV
+	ATRUNCFW
+	ATRUNCDW
+	AMOVWU
+	AMOVFV
+	AMOVDV
+	AMOVVF
+	AMOVVD
+
+	ALAST
+
+	// aliases
+	AJMP = obj.AJMP
+	AJAL = obj.ACALL
+	ARET = obj.ARET
+)
diff --git a/src/cmd/internal/obj/mips/anames.go b/src/cmd/internal/obj/mips/anames.go
new file mode 100644
index 0000000..a943e50
--- /dev/null
+++ b/src/cmd/internal/obj/mips/anames.go
@@ -0,0 +1,112 @@
+// Generated by stringer -i a.out.go -o anames.go -p mips
+// Do not edit.
+
+package mips
+
+import "cmd/internal/obj"
+
+var Anames = []string{
+	obj.A_ARCHSPECIFIC: "ABSD",
+	"ABSF",
+	"ABSW",
+	"ADD",
+	"ADDD",
+	"ADDF",
+	"ADDU",
+	"ADDW",
+	"AND",
+	"BEQ",
+	"BFPF",
+	"BFPT",
+	"BGEZ",
+	"BGEZAL",
+	"BGTZ",
+	"BLEZ",
+	"BLTZ",
+	"BLTZAL",
+	"BNE",
+	"BREAK",
+	"CMPEQD",
+	"CMPEQF",
+	"CMPGED",
+	"CMPGEF",
+	"CMPGTD",
+	"CMPGTF",
+	"DIV",
+	"DIVD",
+	"DIVF",
+	"DIVU",
+	"DIVW",
+	"GOK",
+	"MOVB",
+	"MOVBU",
+	"MOVD",
+	"MOVDF",
+	"MOVDW",
+	"MOVF",
+	"MOVFD",
+	"MOVFW",
+	"MOVH",
+	"MOVHU",
+	"MOVW",
+	"MOVWD",
+	"MOVWF",
+	"MOVWL",
+	"MOVWR",
+	"MUL",
+	"MULD",
+	"MULF",
+	"MULU",
+	"MULW",
+	"NEGD",
+	"NEGF",
+	"NEGW",
+	"NOR",
+	"OR",
+	"REM",
+	"REMU",
+	"RFE",
+	"SGT",
+	"SGTU",
+	"SLL",
+	"SRA",
+	"SRL",
+	"SUB",
+	"SUBD",
+	"SUBF",
+	"SUBU",
+	"SUBW",
+	"SYSCALL",
+	"TLBP",
+	"TLBR",
+	"TLBWI",
+	"TLBWR",
+	"WORD",
+	"XOR",
+	"MOVV",
+	"MOVVL",
+	"MOVVR",
+	"SLLV",
+	"SRAV",
+	"SRLV",
+	"DIVV",
+	"DIVVU",
+	"REMV",
+	"REMVU",
+	"MULV",
+	"MULVU",
+	"ADDV",
+	"ADDVU",
+	"SUBV",
+	"SUBVU",
+	"TRUNCFV",
+	"TRUNCDV",
+	"TRUNCFW",
+	"TRUNCDW",
+	"MOVWU",
+	"MOVFV",
+	"MOVDV",
+	"MOVVF",
+	"MOVVD",
+	"LAST",
+}
diff --git a/src/cmd/internal/obj/mips/anames0.go b/src/cmd/internal/obj/mips/anames0.go
new file mode 100644
index 0000000..7f342e6
--- /dev/null
+++ b/src/cmd/internal/obj/mips/anames0.go
@@ -0,0 +1,38 @@
+package mips
+
+var cnames0 = []string{
+	"NONE",
+	"REG",
+	"FREG",
+	"FCREG",
+	"MREG",
+	"HI",
+	"LO",
+	"ZCON",
+	"SCON",
+	"UCON",
+	"ADD0CON",
+	"AND0CON",
+	"ADDCON",
+	"ANDCON",
+	"LCON",
+	"DCON",
+	"SACON",
+	"SECON",
+	"LACON",
+	"LECON",
+	"DACON",
+	"SBRA",
+	"LBRA",
+	"SAUTO",
+	"LAUTO",
+	"SEXT",
+	"LEXT",
+	"ZOREG",
+	"SOREG",
+	"LOREG",
+	"GOK",
+	"ADDR",
+	"TEXTSIZE",
+	"NCLASS",
+}
diff --git a/src/cmd/internal/obj/mips/asm0.go b/src/cmd/internal/obj/mips/asm0.go
new file mode 100644
index 0000000..63df672
--- /dev/null
+++ b/src/cmd/internal/obj/mips/asm0.go
@@ -0,0 +1,1733 @@
+// cmd/9l/optab.c, cmd/9l/asmout.c from Vita Nuova.
+//
+//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//	Portions Copyright © 1995-1997 C H Forsyth (forsyth at terzarima.net)
+//	Portions Copyright © 1997-1999 Vita Nuova Limited
+//	Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+//	Portions Copyright © 2004,2006 Bruce Ellis
+//	Portions Copyright © 2005-2007 C H Forsyth (forsyth at terzarima.net)
+//	Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
+//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package mips
+
+import (
+	"cmd/internal/obj"
+	"fmt"
+	"log"
+	"sort"
+)
+
+// Instruction layout.
+
+const (
+	FuncAlign = 8
+)
+
+const (
+	r0iszero = 1
+)
+
+type Optab struct {
+	as    int16
+	a1    uint8
+	a2    uint8
+	a3    uint8
+	type_ int8
+	size  int8
+	param int16
+}
+
+var optab = []Optab{
+	{obj.ATEXT, C_LEXT, C_NONE, C_TEXTSIZE, 0, 0, 0},
+	{obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0},
+
+	{AMOVW, C_REG, C_NONE, C_REG, 14, 8, 0},
+	{AMOVV, C_REG, C_NONE, C_REG, 1, 4, 0},
+	{AMOVB, C_REG, C_NONE, C_REG, 12, 8, 0},
+	{AMOVBU, C_REG, C_NONE, C_REG, 13, 4, 0},
+	{AMOVWU, C_REG, C_NONE, C_REG, 14, 8, 0},
+
+	{ASUB, C_REG, C_REG, C_REG, 2, 4, 0},
+	{AADD, C_REG, C_REG, C_REG, 2, 4, 0},
+	{AAND, C_REG, C_REG, C_REG, 2, 4, 0},
+	{ASUB, C_REG, C_NONE, C_REG, 2, 4, 0},
+	{AADD, C_REG, C_NONE, C_REG, 2, 4, 0},
+	{AAND, C_REG, C_NONE, C_REG, 2, 4, 0},
+
+	{ASLL, C_REG, C_NONE, C_REG, 9, 4, 0},
+	{ASLL, C_REG, C_REG, C_REG, 9, 4, 0},
+
+	{AADDF, C_FREG, C_NONE, C_FREG, 32, 4, 0},
+	{AADDF, C_FREG, C_REG, C_FREG, 32, 4, 0},
+	{ACMPEQF, C_FREG, C_REG, C_NONE, 32, 4, 0},
+	{AABSF, C_FREG, C_NONE, C_FREG, 33, 4, 0},
+	{AMOVF, C_FREG, C_NONE, C_FREG, 33, 4, 0},
+	{AMOVD, C_FREG, C_NONE, C_FREG, 33, 4, 0},
+
+	{AMOVW, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
+	{AMOVWU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
+	{AMOVV, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
+	{AMOVB, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
+	{AMOVBU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
+	{AMOVWL, C_REG, C_NONE, C_SEXT, 7, 4, REGSB},
+	{AMOVW, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
+	{AMOVWU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
+	{AMOVV, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
+	{AMOVB, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
+	{AMOVBU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
+	{AMOVWL, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
+	{AMOVW, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
+	{AMOVWU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
+	{AMOVV, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
+	{AMOVB, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
+	{AMOVBU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
+	{AMOVWL, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
+
+	{AMOVW, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
+	{AMOVWU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
+	{AMOVV, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
+	{AMOVB, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
+	{AMOVBU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
+	{AMOVWL, C_SEXT, C_NONE, C_REG, 8, 4, REGSB},
+	{AMOVW, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
+	{AMOVWU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
+	{AMOVV, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
+	{AMOVB, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
+	{AMOVBU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
+	{AMOVWL, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP},
+	{AMOVW, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
+	{AMOVWU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
+	{AMOVV, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
+	{AMOVB, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
+	{AMOVBU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
+	{AMOVWL, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO},
+
+	{AMOVW, C_REG, C_NONE, C_LEXT, 35, 16, REGSB},
+	{AMOVWU, C_REG, C_NONE, C_LEXT, 35, 16, REGSB},
+	{AMOVV, C_REG, C_NONE, C_LEXT, 35, 16, REGSB},
+	{AMOVB, C_REG, C_NONE, C_LEXT, 35, 16, REGSB},
+	{AMOVBU, C_REG, C_NONE, C_LEXT, 35, 16, REGSB},
+	{AMOVW, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP},
+	{AMOVWU, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP},
+	{AMOVV, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP},
+	{AMOVB, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP},
+	{AMOVBU, C_REG, C_NONE, C_LAUTO, 35, 16, REGSP},
+	{AMOVW, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO},
+	{AMOVWU, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO},
+	{AMOVV, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO},
+	{AMOVB, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO},
+	{AMOVBU, C_REG, C_NONE, C_LOREG, 35, 16, REGZERO},
+	{AMOVW, C_REG, C_NONE, C_ADDR, 50, 12, 0},
+	{AMOVWU, C_REG, C_NONE, C_ADDR, 50, 12, 0},
+	{AMOVV, C_REG, C_NONE, C_ADDR, 50, 12, 0},
+	{AMOVB, C_REG, C_NONE, C_ADDR, 50, 12, 0},
+	{AMOVBU, C_REG, C_NONE, C_ADDR, 50, 12, 0},
+
+	{AMOVW, C_LEXT, C_NONE, C_REG, 36, 16, REGSB},
+	{AMOVWU, C_LEXT, C_NONE, C_REG, 36, 16, REGSB},
+	{AMOVV, C_LEXT, C_NONE, C_REG, 36, 16, REGSB},
+	{AMOVB, C_LEXT, C_NONE, C_REG, 36, 16, REGSB},
+	{AMOVBU, C_LEXT, C_NONE, C_REG, 36, 16, REGSB},
+	{AMOVW, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP},
+	{AMOVWU, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP},
+	{AMOVV, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP},
+	{AMOVB, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP},
+	{AMOVBU, C_LAUTO, C_NONE, C_REG, 36, 16, REGSP},
+	{AMOVW, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO},
+	{AMOVWU, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO},
+	{AMOVV, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO},
+	{AMOVB, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO},
+	{AMOVBU, C_LOREG, C_NONE, C_REG, 36, 16, REGZERO},
+	{AMOVW, C_ADDR, C_NONE, C_REG, 51, 12, 0},
+	{AMOVWU, C_ADDR, C_NONE, C_REG, 51, 12, 0},
+	{AMOVV, C_ADDR, C_NONE, C_REG, 51, 12, 0},
+	{AMOVB, C_ADDR, C_NONE, C_REG, 51, 12, 0},
+	{AMOVBU, C_ADDR, C_NONE, C_REG, 51, 12, 0},
+
+	{AMOVW, C_SECON, C_NONE, C_REG, 3, 4, REGSB},
+	{AMOVV, C_SECON, C_NONE, C_REG, 3, 4, REGSB},
+	{AMOVW, C_SACON, C_NONE, C_REG, 3, 4, REGSP},
+	{AMOVV, C_SACON, C_NONE, C_REG, 3, 4, REGSP},
+	{AMOVW, C_LECON, C_NONE, C_REG, 26, 12, REGSB},
+	{AMOVV, C_LECON, C_NONE, C_REG, 26, 12, REGSB},
+	{AMOVW, C_LACON, C_NONE, C_REG, 26, 12, REGSP},
+	{AMOVV, C_LACON, C_NONE, C_REG, 26, 12, REGSP},
+	{AMOVW, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO},
+	{AMOVV, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO},
+	{AMOVW, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO},
+	{AMOVV, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO},
+
+	{AMOVW, C_UCON, C_NONE, C_REG, 24, 4, 0},
+	{AMOVV, C_UCON, C_NONE, C_REG, 24, 4, 0},
+	{AMOVW, C_LCON, C_NONE, C_REG, 19, 8, 0},
+	{AMOVV, C_LCON, C_NONE, C_REG, 19, 8, 0},
+
+	{AMOVW, C_HI, C_NONE, C_REG, 20, 4, 0},
+	{AMOVV, C_HI, C_NONE, C_REG, 20, 4, 0},
+	{AMOVW, C_LO, C_NONE, C_REG, 20, 4, 0},
+	{AMOVV, C_LO, C_NONE, C_REG, 20, 4, 0},
+	{AMOVW, C_REG, C_NONE, C_HI, 21, 4, 0},
+	{AMOVV, C_REG, C_NONE, C_HI, 21, 4, 0},
+	{AMOVW, C_REG, C_NONE, C_LO, 21, 4, 0},
+	{AMOVV, C_REG, C_NONE, C_LO, 21, 4, 0},
+
+	{AMUL, C_REG, C_REG, C_NONE, 22, 4, 0},
+
+	{AADD, C_ADD0CON, C_REG, C_REG, 4, 4, 0},
+	{AADD, C_ADD0CON, C_NONE, C_REG, 4, 4, 0},
+	{AADD, C_ANDCON, C_REG, C_REG, 10, 8, 0},
+	{AADD, C_ANDCON, C_NONE, C_REG, 10, 8, 0},
+
+	{AAND, C_AND0CON, C_REG, C_REG, 4, 4, 0},
+	{AAND, C_AND0CON, C_NONE, C_REG, 4, 4, 0},
+	{AAND, C_ADDCON, C_REG, C_REG, 10, 8, 0},
+	{AAND, C_ADDCON, C_NONE, C_REG, 10, 8, 0},
+
+	{AADD, C_UCON, C_REG, C_REG, 25, 8, 0},
+	{AADD, C_UCON, C_NONE, C_REG, 25, 8, 0},
+	{AAND, C_UCON, C_REG, C_REG, 25, 8, 0},
+	{AAND, C_UCON, C_NONE, C_REG, 25, 8, 0},
+
+	{AADD, C_LCON, C_NONE, C_REG, 23, 12, 0},
+	{AAND, C_LCON, C_NONE, C_REG, 23, 12, 0},
+	{AADD, C_LCON, C_REG, C_REG, 23, 12, 0},
+	{AAND, C_LCON, C_REG, C_REG, 23, 12, 0},
+
+	{ASLL, C_SCON, C_REG, C_REG, 16, 4, 0},
+	{ASLL, C_SCON, C_NONE, C_REG, 16, 4, 0},
+
+	{ASYSCALL, C_NONE, C_NONE, C_NONE, 5, 4, 0},
+
+	{ABEQ, C_REG, C_REG, C_SBRA, 6, 4, 0},
+	{ABEQ, C_REG, C_NONE, C_SBRA, 6, 4, 0},
+	{ABLEZ, C_REG, C_NONE, C_SBRA, 6, 4, 0},
+	{ABFPT, C_NONE, C_NONE, C_SBRA, 6, 8, 0},
+
+	{AJMP, C_NONE, C_NONE, C_LBRA, 11, 4, 0},
+	{AJAL, C_NONE, C_NONE, C_LBRA, 11, 4, 0},
+
+	{AJMP, C_NONE, C_NONE, C_ZOREG, 18, 4, REGZERO},
+	{AJAL, C_NONE, C_NONE, C_ZOREG, 18, 4, REGLINK},
+
+	{AMOVW, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB},
+	{AMOVF, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB},
+	{AMOVD, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB},
+	{AMOVW, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP},
+	{AMOVF, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP},
+	{AMOVD, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP},
+	{AMOVW, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO},
+	{AMOVF, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO},
+	{AMOVD, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO},
+
+	{AMOVW, C_LEXT, C_NONE, C_FREG, 27, 16, REGSB},
+	{AMOVF, C_LEXT, C_NONE, C_FREG, 27, 16, REGSB},
+	{AMOVD, C_LEXT, C_NONE, C_FREG, 27, 16, REGSB},
+	{AMOVW, C_LAUTO, C_NONE, C_FREG, 27, 16, REGSP},
+	{AMOVF, C_LAUTO, C_NONE, C_FREG, 27, 16, REGSP},
+	{AMOVD, C_LAUTO, C_NONE, C_FREG, 27, 16, REGSP},
+	{AMOVW, C_LOREG, C_NONE, C_FREG, 27, 16, REGZERO},
+	{AMOVF, C_LOREG, C_NONE, C_FREG, 27, 16, REGZERO},
+	{AMOVD, C_LOREG, C_NONE, C_FREG, 27, 16, REGZERO},
+	{AMOVF, C_ADDR, C_NONE, C_FREG, 51, 12, 0},
+	{AMOVD, C_ADDR, C_NONE, C_FREG, 51, 12, 0},
+
+	{AMOVW, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB},
+	{AMOVF, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB},
+	{AMOVD, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB},
+	{AMOVW, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP},
+	{AMOVF, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP},
+	{AMOVD, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP},
+	{AMOVW, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO},
+	{AMOVF, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO},
+	{AMOVD, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO},
+
+	{AMOVW, C_FREG, C_NONE, C_LEXT, 28, 16, REGSB},
+	{AMOVF, C_FREG, C_NONE, C_LEXT, 28, 16, REGSB},
+	{AMOVD, C_FREG, C_NONE, C_LEXT, 28, 16, REGSB},
+	{AMOVW, C_FREG, C_NONE, C_LAUTO, 28, 16, REGSP},
+	{AMOVF, C_FREG, C_NONE, C_LAUTO, 28, 16, REGSP},
+	{AMOVD, C_FREG, C_NONE, C_LAUTO, 28, 16, REGSP},
+	{AMOVW, C_FREG, C_NONE, C_LOREG, 28, 16, REGZERO},
+	{AMOVF, C_FREG, C_NONE, C_LOREG, 28, 16, REGZERO},
+	{AMOVD, C_FREG, C_NONE, C_LOREG, 28, 16, REGZERO},
+	{AMOVF, C_FREG, C_NONE, C_ADDR, 50, 12, 0},
+	{AMOVD, C_FREG, C_NONE, C_ADDR, 50, 12, 0},
+
+	{AMOVW, C_REG, C_NONE, C_FREG, 30, 4, 0},
+	{AMOVW, C_FREG, C_NONE, C_REG, 31, 4, 0},
+	{AMOVV, C_REG, C_NONE, C_FREG, 47, 4, 0},
+	{AMOVV, C_FREG, C_NONE, C_REG, 48, 4, 0},
+
+	{AMOVW, C_ADDCON, C_NONE, C_FREG, 34, 8, 0},
+	{AMOVW, C_ANDCON, C_NONE, C_FREG, 34, 8, 0},
+	{AMOVW, C_UCON, C_NONE, C_FREG, 35, 8, 0},
+	{AMOVW, C_LCON, C_NONE, C_FREG, 36, 12, 0},
+
+	{AMOVW, C_REG, C_NONE, C_MREG, 37, 4, 0},
+	{AMOVV, C_REG, C_NONE, C_MREG, 37, 4, 0},
+	{AMOVW, C_MREG, C_NONE, C_REG, 38, 4, 0},
+	{AMOVV, C_MREG, C_NONE, C_REG, 38, 4, 0},
+
+	{AWORD, C_LCON, C_NONE, C_NONE, 40, 4, 0},
+
+	{AMOVW, C_REG, C_NONE, C_FCREG, 41, 8, 0},
+	{AMOVV, C_REG, C_NONE, C_FCREG, 41, 8, 0},
+	{AMOVW, C_FCREG, C_NONE, C_REG, 42, 4, 0},
+	{AMOVV, C_FCREG, C_NONE, C_REG, 42, 4, 0},
+
+	{ABREAK, C_REG, C_NONE, C_SEXT, 7, 4, REGSB}, /* really CACHE instruction */
+	{ABREAK, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP},
+	{ABREAK, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO},
+	{ABREAK, C_NONE, C_NONE, C_NONE, 5, 4, 0},
+
+	{obj.AUNDEF, C_NONE, C_NONE, C_NONE, 49, 4, 0},
+	{obj.AUSEFIELD, C_ADDR, C_NONE, C_NONE, 0, 0, 0},
+	{obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0},
+	{obj.AFUNCDATA, C_SCON, C_NONE, C_ADDR, 0, 0, 0},
+	{obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0},
+	{obj.ADUFFZERO, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as AJMP
+	{obj.ADUFFCOPY, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as AJMP
+
+	{obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0},
+}
+
+type Oprang struct {
+	start []Optab
+	stop  []Optab
+}
+
+var oprange [ALAST & obj.AMask]Oprang
+
+var xcmp [C_NCLASS][C_NCLASS]uint8
+
+func span0(ctxt *obj.Link, cursym *obj.LSym) {
+	p := cursym.Text
+	if p == nil || p.Link == nil { // handle external functions and ELF section symbols
+		return
+	}
+	ctxt.Cursym = cursym
+	ctxt.Autosize = int32(p.To.Offset + 8)
+
+	if oprange[AOR&obj.AMask].start == nil {
+		buildop(ctxt)
+	}
+
+	c := int64(0)
+	p.Pc = c
+
+	var m int
+	var o *Optab
+	for p = p.Link; p != nil; p = p.Link {
+		ctxt.Curp = p
+		p.Pc = c
+		o = oplook(ctxt, p)
+		m = int(o.size)
+		if m == 0 {
+			if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.AUSEFIELD {
+				ctxt.Diag("zero-width instruction\n%v", p)
+			}
+			continue
+		}
+
+		c += int64(m)
+	}
+
+	cursym.Size = c
+
+	/*
+	 * if any procedure is large enough to
+	 * generate a large SBRA branch, then
+	 * generate extra passes putting branches
+	 * around jmps to fix. this is rare.
+	 */
+	bflag := 1
+
+	var otxt int64
+	var q *obj.Prog
+	for bflag != 0 {
+		if ctxt.Debugvlog != 0 {
+			fmt.Fprintf(ctxt.Bso, "%5.2f span1\n", obj.Cputime())
+		}
+		bflag = 0
+		c = 0
+		for p = cursym.Text.Link; p != nil; p = p.Link {
+			p.Pc = c
+			o = oplook(ctxt, p)
+
+			// very large conditional branches
+			if o.type_ == 6 && p.Pcond != nil {
+				otxt = p.Pcond.Pc - c
+				if otxt < -(1<<17)+10 || otxt >= (1<<17)-10 {
+					q = ctxt.NewProg()
+					q.Link = p.Link
+					p.Link = q
+					q.As = AJMP
+					q.Lineno = p.Lineno
+					q.To.Type = obj.TYPE_BRANCH
+					q.Pcond = p.Pcond
+					p.Pcond = q
+					q = ctxt.NewProg()
+					q.Link = p.Link
+					p.Link = q
+					q.As = AJMP
+					q.Lineno = p.Lineno
+					q.To.Type = obj.TYPE_BRANCH
+					q.Pcond = q.Link.Link
+
+					addnop(ctxt, p.Link)
+					addnop(ctxt, p)
+					bflag = 1
+				}
+			}
+
+			m = int(o.size)
+			if m == 0 {
+				if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.AUSEFIELD {
+					ctxt.Diag("zero-width instruction\n%v", p)
+				}
+				continue
+			}
+
+			c += int64(m)
+		}
+
+		cursym.Size = c
+	}
+
+	c += -c & (FuncAlign - 1)
+	cursym.Size = c
+
+	/*
+	 * lay out the code, emitting code and data relocations.
+	 */
+
+	obj.Symgrow(ctxt, cursym, cursym.Size)
+
+	bp := cursym.P
+	var i int32
+	var out [4]uint32
+	for p := cursym.Text.Link; p != nil; p = p.Link {
+		ctxt.Pc = p.Pc
+		ctxt.Curp = p
+		o = oplook(ctxt, p)
+		if int(o.size) > 4*len(out) {
+			log.Fatalf("out array in span0 is too small, need at least %d for %v", o.size/4, p)
+		}
+		asmout(ctxt, p, o, out[:])
+		for i = 0; i < int32(o.size/4); i++ {
+			ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
+			bp = bp[4:]
+		}
+	}
+}
+
+func isint32(v int64) bool {
+	return int64(int32(v)) == v
+}
+
+func isuint32(v uint64) bool {
+	return uint64(uint32(v)) == v
+}
+
+func aclass(ctxt *obj.Link, a *obj.Addr) int {
+	switch a.Type {
+	case obj.TYPE_NONE:
+		return C_NONE
+
+	case obj.TYPE_REG:
+		if REG_R0 <= a.Reg && a.Reg <= REG_R31 {
+			return C_REG
+		}
+		if REG_F0 <= a.Reg && a.Reg <= REG_F31 {
+			return C_FREG
+		}
+		if REG_M0 <= a.Reg && a.Reg <= REG_M31 {
+			return C_MREG
+		}
+		if REG_FCR0 <= a.Reg && a.Reg <= REG_FCR31 {
+			return C_FCREG
+		}
+		if a.Reg == REG_LO {
+			return C_LO
+		}
+		if a.Reg == REG_HI {
+			return C_HI
+		}
+		return C_GOK
+
+	case obj.TYPE_MEM:
+		switch a.Name {
+		case obj.NAME_EXTERN,
+			obj.NAME_STATIC:
+			if a.Sym == nil {
+				break
+			}
+			ctxt.Instoffset = a.Offset
+			if a.Sym != nil { // use relocation
+				return C_ADDR
+			}
+			return C_LEXT
+
+		case obj.NAME_AUTO:
+			ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
+			if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
+				return C_SAUTO
+			}
+			return C_LAUTO
+
+		case obj.NAME_PARAM:
+			ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8
+			if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
+				return C_SAUTO
+			}
+			return C_LAUTO
+
+		case obj.NAME_NONE:
+			ctxt.Instoffset = a.Offset
+			if ctxt.Instoffset == 0 {
+				return C_ZOREG
+			}
+			if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
+				return C_SOREG
+			}
+			return C_LOREG
+		}
+
+		return C_GOK
+
+	case obj.TYPE_TEXTSIZE:
+		return C_TEXTSIZE
+
+	case obj.TYPE_CONST,
+		obj.TYPE_ADDR:
+		switch a.Name {
+		case obj.NAME_NONE:
+			ctxt.Instoffset = a.Offset
+			if a.Reg != 0 {
+				if -BIG <= ctxt.Instoffset && ctxt.Instoffset <= BIG {
+					return C_SACON
+				}
+				if isint32(ctxt.Instoffset) {
+					return C_LACON
+				}
+				return C_DACON
+			}
+
+			goto consize
+
+		case obj.NAME_EXTERN,
+			obj.NAME_STATIC:
+			s := a.Sym
+			if s == nil {
+				break
+			}
+			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:
+			ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
+			if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
+				return C_SACON
+			}
+			return C_LACON
+
+		case obj.NAME_PARAM:
+			ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8
+			if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
+				return C_SACON
+			}
+			return C_LACON
+		}
+
+		return C_GOK
+
+	consize:
+		if ctxt.Instoffset >= 0 {
+			if ctxt.Instoffset == 0 {
+				return C_ZCON
+			}
+			if ctxt.Instoffset <= 0x7fff {
+				return C_SCON
+			}
+			if ctxt.Instoffset <= 0xffff {
+				return C_ANDCON
+			}
+			if ctxt.Instoffset&0xffff == 0 && isuint32(uint64(ctxt.Instoffset)) { /* && (instoffset & (1<<31)) == 0) */
+				return C_UCON
+			}
+			if isint32(ctxt.Instoffset) || isuint32(uint64(ctxt.Instoffset)) {
+				return C_LCON
+			}
+			return C_LCON // C_DCON
+		}
+
+		if ctxt.Instoffset >= -0x8000 {
+			return C_ADDCON
+		}
+		if ctxt.Instoffset&0xffff == 0 && isint32(ctxt.Instoffset) {
+			return C_UCON
+		}
+		if isint32(ctxt.Instoffset) {
+			return C_LCON
+		}
+		return C_LCON // C_DCON
+
+	case obj.TYPE_BRANCH:
+		return C_SBRA
+	}
+
+	return C_GOK
+}
+
+func prasm(p *obj.Prog) {
+	fmt.Printf("%v\n", p)
+}
+
+func oplook(ctxt *obj.Link, p *obj.Prog) *Optab {
+	if oprange[AOR&obj.AMask].start == nil {
+		buildop(ctxt)
+	}
+
+	a1 := int(p.Optab)
+	if a1 != 0 {
+		return &optab[a1-1:][0]
+	}
+	a1 = int(p.From.Class)
+	if a1 == 0 {
+		a1 = aclass(ctxt, &p.From) + 1
+		p.From.Class = int8(a1)
+	}
+
+	a1--
+	a3 := int(p.To.Class)
+	if a3 == 0 {
+		a3 = aclass(ctxt, &p.To) + 1
+		p.To.Class = int8(a3)
+	}
+
+	a3--
+	a2 := C_NONE
+	if p.Reg != 0 {
+		a2 = C_REG
+	}
+
+	//print("oplook %P %d %d %d\n", p, a1, a2, a3);
+	r0 := p.As & obj.AMask
+
+	o := oprange[r0].start
+	if o == nil {
+		o = oprange[r0].stop /* just generate an error */
+	}
+	e := oprange[r0].stop
+	c1 := xcmp[a1][:]
+	c3 := xcmp[a3][:]
+	for ; -cap(o) < -cap(e); o = o[1:] {
+		if int(o[0].a2) == a2 {
+			if c1[o[0].a1] != 0 {
+				if c3[o[0].a3] != 0 {
+					p.Optab = uint16((-cap(o) + cap(optab)) + 1)
+					return &o[0]
+				}
+			}
+		}
+	}
+
+	ctxt.Diag("illegal combination %v %v %v %v", obj.Aconv(int(p.As)), DRconv(a1), DRconv(a2), DRconv(a3))
+	prasm(p)
+	if o == nil {
+		o = optab
+	}
+	return &o[0]
+}
+
+func cmp(a int, b int) bool {
+	if a == b {
+		return true
+	}
+	switch a {
+	case C_LCON:
+		if b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON {
+			return true
+		}
+
+	case C_ADD0CON:
+		if b == C_ADDCON {
+			return true
+		}
+		fallthrough
+
+	case C_ADDCON:
+		if b == C_ZCON || b == C_SCON {
+			return true
+		}
+
+	case C_AND0CON:
+		if b == C_ANDCON {
+			return true
+		}
+		fallthrough
+
+	case C_ANDCON:
+		if b == C_ZCON || b == C_SCON {
+			return true
+		}
+
+	case C_UCON:
+		if b == C_ZCON {
+			return true
+		}
+
+	case C_SCON:
+		if b == C_ZCON {
+			return true
+		}
+
+	case C_LACON:
+		if b == C_SACON {
+			return true
+		}
+
+	case C_LBRA:
+		if b == C_SBRA {
+			return true
+		}
+
+	case C_LEXT:
+		if b == C_SEXT {
+			return true
+		}
+
+	case C_LAUTO:
+		if b == C_SAUTO {
+			return true
+		}
+
+	case C_REG:
+		if b == C_ZCON {
+			return r0iszero != 0 /*TypeKind(100016)*/
+		}
+
+	case C_LOREG:
+		if b == C_ZOREG || b == C_SOREG {
+			return true
+		}
+
+	case C_SOREG:
+		if b == C_ZOREG {
+			return true
+		}
+	}
+
+	return false
+}
+
+type ocmp []Optab
+
+func (x ocmp) Len() int {
+	return len(x)
+}
+
+func (x ocmp) Swap(i, j int) {
+	x[i], x[j] = x[j], x[i]
+}
+
+func (x ocmp) Less(i, j int) bool {
+	p1 := &x[i]
+	p2 := &x[j]
+	n := int(p1.as) - int(p2.as)
+	if n != 0 {
+		return n < 0
+	}
+	n = int(p1.a1) - int(p2.a1)
+	if n != 0 {
+		return n < 0
+	}
+	n = int(p1.a2) - int(p2.a2)
+	if n != 0 {
+		return n < 0
+	}
+	n = int(p1.a3) - int(p2.a3)
+	if n != 0 {
+		return n < 0
+	}
+	return false
+}
+func opset(a, b0 int16) {
+	oprange[a&obj.AMask] = oprange[b0]
+}
+
+func buildop(ctxt *obj.Link) {
+	var n int
+
+	for i := 0; i < C_NCLASS; i++ {
+		for n = 0; n < C_NCLASS; n++ {
+			if cmp(n, i) {
+				xcmp[i][n] = 1
+			}
+		}
+	}
+	for n = 0; optab[n].as != obj.AXXX; n++ {
+	}
+	sort.Sort(ocmp(optab[:n]))
+	for i := 0; i < n; i++ {
+		r := optab[i].as
+		r0 := r & obj.AMask
+		oprange[r0].start = optab[i:]
+		for optab[i].as == r {
+			i++
+		}
+		oprange[r0].stop = optab[i:]
+		i--
+
+		switch r {
+		default:
+			ctxt.Diag("unknown op in build: %v", obj.Aconv(int(r)))
+			log.Fatalf("bad code")
+
+		case AABSF:
+			opset(AMOVFD, r0)
+			opset(AMOVDF, r0)
+			opset(AMOVWF, r0)
+			opset(AMOVFW, r0)
+			opset(AMOVWD, r0)
+			opset(AMOVDW, r0)
+			opset(ANEGF, r0)
+			opset(ANEGD, r0)
+			opset(AABSD, r0)
+			opset(ATRUNCDW, r0)
+			opset(ATRUNCFW, r0)
+			opset(ATRUNCDV, r0)
+			opset(ATRUNCFV, r0)
+			opset(AMOVVF, r0)
+			opset(AMOVFV, r0)
+			opset(AMOVVD, r0)
+			opset(AMOVDV, r0)
+
+		case AADD:
+			opset(ASGT, r0)
+			opset(ASGTU, r0)
+			opset(AADDU, r0)
+			opset(AADDV, r0)
+			opset(AADDVU, r0)
+
+		case AADDF:
+			opset(ADIVF, r0)
+			opset(ADIVD, r0)
+			opset(AMULF, r0)
+			opset(AMULD, r0)
+			opset(ASUBF, r0)
+			opset(ASUBD, r0)
+			opset(AADDD, r0)
+
+		case AAND:
+			opset(AOR, r0)
+			opset(AXOR, r0)
+
+		case ABEQ:
+			opset(ABNE, r0)
+
+		case ABLEZ:
+			opset(ABGEZ, r0)
+			opset(ABGEZAL, r0)
+			opset(ABLTZ, r0)
+			opset(ABLTZAL, r0)
+			opset(ABGTZ, r0)
+
+		case AMOVB:
+			opset(AMOVH, r0)
+
+		case AMOVBU:
+			opset(AMOVHU, r0)
+
+		case AMUL:
+			opset(AREM, r0)
+			opset(AREMU, r0)
+			opset(ADIVU, r0)
+			opset(AMULU, r0)
+			opset(ADIV, r0)
+			opset(ADIVV, r0)
+			opset(ADIVVU, r0)
+			opset(AMULV, r0)
+			opset(AMULVU, r0)
+			opset(AREMV, r0)
+			opset(AREMVU, r0)
+
+		case ASLL:
+			opset(ASRL, r0)
+			opset(ASRA, r0)
+			opset(ASLLV, r0)
+			opset(ASRAV, r0)
+			opset(ASRLV, r0)
+
+		case ASUB:
+			opset(ASUBU, r0)
+			opset(ASUBV, r0)
+			opset(ASUBVU, r0)
+			opset(ANOR, r0)
+
+		case ASYSCALL:
+			opset(ATLBP, r0)
+			opset(ATLBR, r0)
+			opset(ATLBWI, r0)
+			opset(ATLBWR, r0)
+
+		case ACMPEQF:
+			opset(ACMPGTF, r0)
+			opset(ACMPGTD, r0)
+			opset(ACMPGEF, r0)
+			opset(ACMPGED, r0)
+			opset(ACMPEQD, r0)
+
+		case ABFPT:
+			opset(ABFPF, r0)
+
+		case AMOVWL:
+			opset(AMOVWR, r0)
+			opset(AMOVVR, r0)
+			opset(AMOVVL, r0)
+
+		case AMOVW,
+			AMOVD,
+			AMOVF,
+			AMOVV,
+			ABREAK,
+			ARFE,
+			AJAL,
+			AJMP,
+			AMOVWU,
+			AWORD,
+			obj.ANOP,
+			obj.ATEXT,
+			obj.AUNDEF,
+			obj.AUSEFIELD,
+			obj.AFUNCDATA,
+			obj.APCDATA,
+			obj.ADUFFZERO,
+			obj.ADUFFCOPY:
+			break
+		}
+	}
+}
+
+func OP(x uint32, y uint32) uint32 {
+	return x<<3 | y<<0
+}
+
+func SP(x uint32, y uint32) uint32 {
+	return x<<29 | y<<26
+}
+
+func BCOND(x uint32, y uint32) uint32 {
+	return x<<19 | y<<16
+}
+
+func MMU(x uint32, y uint32) uint32 {
+	return SP(2, 0) | 16<<21 | x<<3 | y<<0
+}
+
+func FPF(x uint32, y uint32) uint32 {
+	return SP(2, 1) | 16<<21 | x<<3 | y<<0
+}
+
+func FPD(x uint32, y uint32) uint32 {
+	return SP(2, 1) | 17<<21 | x<<3 | y<<0
+}
+
+func FPW(x uint32, y uint32) uint32 {
+	return SP(2, 1) | 20<<21 | x<<3 | y<<0
+}
+
+func FPV(x uint32, y uint32) uint32 {
+	return SP(2, 1) | 21<<21 | x<<3 | y<<0
+}
+
+func OP_RRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
+	return op | (r1&31)<<16 | (r2&31)<<21 | (r3&31)<<11
+}
+
+func OP_IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
+	return op | i&0xFFFF | (r2&31)<<21 | (r3&31)<<16
+}
+
+func OP_SRR(op uint32, s uint32, r2 uint32, r3 uint32) uint32 {
+	return op | (s&31)<<6 | (r2&31)<<16 | (r3&31)<<11
+}
+
+func OP_FRRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
+	return op | (r1&31)<<16 | (r2&31)<<11 | (r3&31)<<6
+}
+
+func OP_JMP(op uint32, i uint32) uint32 {
+	return op | i&0x3FFFFFF
+}
+
+func oclass(a *obj.Addr) int {
+	return int(a.Class) - 1
+}
+
+func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
+	o1 := uint32(0)
+	o2 := uint32(0)
+	o3 := uint32(0)
+	o4 := uint32(0)
+
+	switch o.type_ {
+	default:
+		ctxt.Diag("unknown type %d %v", o.type_)
+		prasm(p)
+
+	case 0: /* pseudo ops */
+		break
+
+	case 1: /* mov r1,r2 ==> OR r1,r0,r2 */
+		o1 = OP_RRR(oprrr(ctxt, AOR), uint32(p.From.Reg), uint32(REGZERO), uint32(p.To.Reg))
+
+	case 2: /* add/sub r1,[r2],r3 */
+		r := int(p.Reg)
+
+		if r == 0 {
+			r = int(p.To.Reg)
+		}
+		o1 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
+
+	case 3: /* mov $soreg, r ==> or/add $i,o,r */
+		v := regoff(ctxt, &p.From)
+
+		r := int(p.From.Reg)
+		if r == 0 {
+			r = int(o.param)
+		}
+		a := AADDVU
+		if o.a1 == C_ANDCON {
+			a = AOR
+		}
+
+		o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(r), uint32(p.To.Reg))
+
+	case 4: /* add $scon,[r1],r2 */
+		v := regoff(ctxt, &p.From)
+
+		r := int(p.Reg)
+		if r == 0 {
+			r = int(p.To.Reg)
+		}
+
+		o1 = OP_IRR(opirr(ctxt, int(p.As)), uint32(v), uint32(r), uint32(p.To.Reg))
+
+	case 5: /* syscall */
+		o1 = uint32(oprrr(ctxt, int(p.As)))
+
+	case 6: /* beq r1,[r2],sbra */
+		v := int32(0)
+		if p.Pcond == nil {
+			v = int32(-4) >> 2
+		} else {
+			v = int32(p.Pcond.Pc-p.Pc-4) >> 2
+		}
+		if (v<<16)>>16 != v {
+			ctxt.Diag("short branch too far\n%v", p)
+		}
+		o1 = OP_IRR(opirr(ctxt, int(p.As)), uint32(v), uint32(p.From.Reg), uint32(p.Reg))
+		// for ABFPT and ABFPF only: always fill delay slot with 0
+		// see comments in func preprocess for details.
+		o2 = 0
+
+	case 7: /* mov r, soreg ==> sw o(r) */
+		r := int(p.To.Reg)
+		if r == 0 {
+			r = int(o.param)
+		}
+		v := regoff(ctxt, &p.To)
+		o1 = OP_IRR(opirr(ctxt, int(p.As)), uint32(v), uint32(r), uint32(p.From.Reg))
+
+	case 8: /* mov soreg, r ==> lw o(r) */
+		r := int(p.From.Reg)
+		if r == 0 {
+			r = int(o.param)
+		}
+		v := regoff(ctxt, &p.From)
+		o1 = OP_IRR(opirr(ctxt, int(p.As)+ALAST), uint32(v), uint32(r), uint32(p.To.Reg))
+
+	case 9: /* sll r1,[r2],r3 */
+		r := int(p.Reg)
+
+		if r == 0 {
+			r = int(p.To.Reg)
+		}
+		o1 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg))
+
+	case 10: /* add $con,[r1],r2 ==> mov $con, t; add t,[r1],r2 */
+		v := regoff(ctxt, &p.From)
+		a := AOR
+		if v < 0 {
+			a = AADDU
+		}
+		o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(0), uint32(REGTMP))
+		r := int(p.Reg)
+		if r == 0 {
+			r = int(p.To.Reg)
+		}
+		o2 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
+
+	case 11: /* jmp lbra */
+		v := int32(0)
+		if aclass(ctxt, &p.To) == C_SBRA && p.To.Sym == nil && p.As == AJMP {
+			// use PC-relative branch for short branches
+			// BEQ	R0, R0, sbra
+			if p.Pcond == nil {
+				v = int32(-4) >> 2
+			} else {
+				v = int32(p.Pcond.Pc-p.Pc-4) >> 2
+			}
+			if (v<<16)>>16 == v {
+				o1 = OP_IRR(opirr(ctxt, ABEQ), uint32(v), uint32(REGZERO), uint32(REGZERO))
+				break
+			}
+		}
+		if p.Pcond == nil {
+			v = int32(p.Pc) >> 2
+		} else {
+			v = int32(p.Pcond.Pc) >> 2
+		}
+		o1 = OP_JMP(opirr(ctxt, int(p.As)), uint32(v))
+		if p.To.Sym == nil {
+			p.To.Sym = ctxt.Cursym.Text.From.Sym
+			p.To.Offset = p.Pcond.Pc
+		}
+		rel := obj.Addrel(ctxt.Cursym)
+		rel.Off = int32(ctxt.Pc)
+		rel.Siz = 4
+		rel.Sym = p.To.Sym
+		rel.Add = p.To.Offset
+		if p.As == AJAL {
+			rel.Type = obj.R_CALLMIPS
+		} else {
+			rel.Type = obj.R_JMPMIPS
+		}
+
+	case 12: /* movbs r,r */
+		v := 16
+		if p.As == AMOVB {
+			v = 24
+		}
+		o1 = OP_SRR(opirr(ctxt, ASLL), uint32(v), uint32(p.From.Reg), uint32(p.To.Reg))
+		o2 = OP_SRR(opirr(ctxt, ASRA), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
+
+	case 13: /* movbu r,r */
+		if p.As == AMOVBU {
+			o1 = OP_IRR(opirr(ctxt, AAND), uint32(0xff), uint32(p.From.Reg), uint32(p.To.Reg))
+		} else {
+			o1 = OP_IRR(opirr(ctxt, AAND), uint32(0xffff), uint32(p.From.Reg), uint32(p.To.Reg))
+		}
+
+	case 14: /* movwu r,r */
+		o1 = OP_SRR(opirr(ctxt, ASLLV+ALAST), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
+		if p.As == AMOVWU {
+			o2 = OP_SRR(opirr(ctxt, ASRLV+ALAST), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
+		} else {
+			o2 = OP_SRR(opirr(ctxt, ASRAV+ALAST), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
+		}
+
+	case 16: /* sll $c,[r1],r2 */
+		v := regoff(ctxt, &p.From)
+		r := int(p.Reg)
+		if r == 0 {
+			r = int(p.To.Reg)
+		}
+
+		/* OP_SRR will use only the low 5 bits of the shift value */
+		if v >= 32 && vshift(p.As) {
+			o1 = OP_SRR(opirr(ctxt, int(p.As)+ALAST), uint32(v-32), uint32(r), uint32(p.To.Reg))
+		} else {
+			o1 = OP_SRR(opirr(ctxt, int(p.As)), uint32(v), uint32(r), uint32(p.To.Reg))
+		}
+
+	case 18: /* jmp [r1],0(r2) */
+		r := int(p.Reg)
+		if r == 0 {
+			r = int(o.param)
+		}
+		o1 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(0), uint32(p.To.Reg), uint32(r))
+		rel := obj.Addrel(ctxt.Cursym)
+		rel.Off = int32(ctxt.Pc)
+		rel.Siz = 0
+		rel.Type = obj.R_CALLIND
+
+	case 19: /* mov $lcon,r ==> lu+or */
+		v := regoff(ctxt, &p.From)
+		o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
+		o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
+		if p.From.Sym != nil {
+			rel := obj.Addrel(ctxt.Cursym)
+			rel.Off = int32(ctxt.Pc)
+			rel.Siz = 8
+			rel.Sym = p.From.Sym
+			rel.Add = p.From.Offset
+			rel.Type = obj.R_ADDRMIPS
+		}
+
+	case 20: /* mov lo/hi,r */
+		a := OP(2, 0) /* mfhi */
+		if p.From.Reg == REG_LO {
+			a = OP(2, 2) /* mflo */
+		}
+		o1 = OP_RRR(a, uint32(REGZERO), uint32(REGZERO), uint32(p.To.Reg))
+
+	case 21: /* mov r,lo/hi */
+		a := OP(2, 1) /* mthi */
+		if p.To.Reg == REG_LO {
+			a = OP(2, 3) /* mtlo */
+		}
+		o1 = OP_RRR(a, uint32(REGZERO), uint32(p.From.Reg), uint32(REGZERO))
+
+	case 22: /* mul r1,r2 */
+		o1 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(p.From.Reg), uint32(p.Reg), uint32(REGZERO))
+
+	case 23: /* add $lcon,r1,r2 ==> lu+or+add */
+		v := regoff(ctxt, &p.From)
+		o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
+		o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
+		r := int(p.Reg)
+		if r == 0 {
+			r = int(p.To.Reg)
+		}
+		o3 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
+
+	case 24: /* mov $ucon,r ==> lu r */
+		v := regoff(ctxt, &p.From)
+		o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
+
+	case 25: /* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */
+		v := regoff(ctxt, &p.From)
+		o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
+		r := int(p.Reg)
+		if r == 0 {
+			r = int(p.To.Reg)
+		}
+		o2 = OP_RRR(oprrr(ctxt, int(p.As)), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
+
+	case 26: /* mov $lsext/auto/oreg,r ==> lu+or+add */
+		v := regoff(ctxt, &p.From)
+		o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
+		o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
+		r := int(p.From.Reg)
+		if r == 0 {
+			r = int(o.param)
+		}
+		o3 = OP_RRR(oprrr(ctxt, AADDVU), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
+
+	case 27: /* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */
+		v := regoff(ctxt, &p.From)
+		r := int(p.From.Reg)
+		if r == 0 {
+			r = int(o.param)
+		}
+		a := AMOVF + ALAST
+		if p.As == AMOVD {
+			a = AMOVD + ALAST
+		}
+		switch o.size {
+		case 16:
+			o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
+			o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
+			o3 = OP_RRR(opirr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP))
+			o4 = OP_IRR(opirr(ctxt, a), uint32(0), uint32(r), uint32(p.To.Reg))
+
+		case 4:
+			o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(r), uint32(p.To.Reg))
+		}
+
+	case 28: /* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */
+		v := regoff(ctxt, &p.To)
+		r := int(p.To.Reg)
+		if r == 0 {
+			r = int(o.param)
+		}
+		a := AMOVF
+		if p.As == AMOVD {
+			a = AMOVD
+		}
+		switch o.size {
+		case 16:
+			o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
+			o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
+			o3 = OP_RRR(opirr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP))
+			o4 = OP_IRR(opirr(ctxt, a), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
+
+		case 4:
+			o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(r), uint32(p.From.Reg))
+		}
+
+	case 30: /* movw r,fr */
+		a := SP(2, 1) | (4 << 21) /* mtc1 */
+		o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
+
+	case 31: /* movw fr,r */
+		a := SP(2, 1) | (0 << 21) /* mtc1 */
+		o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
+
+	case 32: /* fadd fr1,[fr2],fr3 */
+		r := int(p.Reg)
+		if r == 0 {
+			r = int(p.To.Reg)
+		}
+		o1 = OP_FRRR(oprrr(ctxt, int(p.As)), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
+
+	case 33: /* fabs fr1, fr3 */
+		o1 = OP_FRRR(oprrr(ctxt, int(p.As)), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
+
+	case 34: /* mov $con,fr ==> or/add $i,t; mov t,fr */
+		v := regoff(ctxt, &p.From)
+		a := AADDU
+		if o.a1 == C_ANDCON {
+			a = AOR
+		}
+		o1 = OP_IRR(opirr(ctxt, a), uint32(v), uint32(0), uint32(REGTMP))
+		o2 = OP_RRR(SP(2, 1)|(4<<21), uint32(REGTMP), uint32(0), uint32(p.To.Reg)) /* mtc1 */
+
+	case 35: /* mov r,lext/auto/oreg ==> sw o(r) */
+		v := regoff(ctxt, &p.To)
+		r := int(p.To.Reg)
+		if r == 0 {
+			r = int(o.param)
+		}
+		o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
+		o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
+		o3 = OP_RRR(oprrr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP))
+		o4 = OP_IRR(opirr(ctxt, int(p.As)), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
+
+	case 36: /* mov lext/auto/oreg,r ==> lw o(r30) */
+		v := regoff(ctxt, &p.From)
+		r := int(p.From.Reg)
+		if r == 0 {
+			r = int(o.param)
+		}
+		o1 = OP_IRR(opirr(ctxt, ALAST), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
+		o2 = OP_IRR(opirr(ctxt, AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
+		o3 = OP_RRR(oprrr(ctxt, AADDVU), uint32(r), uint32(REGTMP), uint32(REGTMP))
+		o4 = OP_IRR(opirr(ctxt, int(p.As)+ALAST), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
+
+	case 37: /* movw r,mr */
+		a := SP(2, 0) | (4 << 21) /* mtc0 */
+		if p.As == AMOVV {
+			a = SP(2, 0) | (5 << 21) /* dmtc0 */
+		}
+		o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
+
+	case 38: /* movw mr,r */
+		a := SP(2, 0) | (0 << 21) /* mfc0 */
+		if p.As == AMOVV {
+			a = SP(2, 0) | (1 << 21) /* dmfc0 */
+		}
+		o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
+
+	case 40: /* word */
+		o1 = uint32(regoff(ctxt, &p.From))
+
+	case 41: /* movw f,fcr */
+		o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(REGZERO), uint32(0), uint32(p.To.Reg))    /* mfcc1 */
+		o2 = OP_RRR(SP(2, 1)|(6<<21), uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) /* mtcc1 */
+
+	case 42: /* movw fcr,r */
+		o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) /* mfcc1 */
+
+	case 47: /* movv r,fr */
+		a := SP(2, 1) | (5 << 21) /* dmtc1 */
+		o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
+
+	case 48: /* movv fr,r */
+		a := SP(2, 1) | (1 << 21) /* dmtc1 */
+		o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
+
+	case 49: /* undef */
+		o1 = 8 /* JMP (R0) */
+
+	/* relocation operations */
+	case 50: /* mov r,addr ==> lu + or + sw (REGTMP) */
+		o1 = OP_IRR(opirr(ctxt, ALAST), uint32(0), uint32(REGZERO), uint32(REGTMP))
+		o2 = OP_IRR(opirr(ctxt, AOR), uint32(0), uint32(REGTMP), uint32(REGTMP))
+		rel := obj.Addrel(ctxt.Cursym)
+		rel.Off = int32(ctxt.Pc)
+		rel.Siz = 8
+		rel.Sym = p.To.Sym
+		rel.Add = p.To.Offset
+		rel.Type = obj.R_ADDRMIPS
+		o3 = OP_IRR(opirr(ctxt, int(p.As)), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
+
+	case 51: /* mov addr,r ==> lu + or + lw (REGTMP) */
+		o1 = OP_IRR(opirr(ctxt, ALAST), uint32(0), uint32(REGZERO), uint32(REGTMP))
+		o2 = OP_IRR(opirr(ctxt, AOR), uint32(0), uint32(REGTMP), uint32(REGTMP))
+		rel := obj.Addrel(ctxt.Cursym)
+		rel.Off = int32(ctxt.Pc)
+		rel.Siz = 8
+		rel.Sym = p.From.Sym
+		rel.Add = p.From.Offset
+		rel.Type = obj.R_ADDRMIPS
+		o3 = OP_IRR(opirr(ctxt, int(p.As)+ALAST), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
+	}
+
+	out[0] = o1
+	out[1] = o2
+	out[2] = o3
+	out[3] = o4
+	return
+}
+
+func vregoff(ctxt *obj.Link, a *obj.Addr) int64 {
+	ctxt.Instoffset = 0
+	aclass(ctxt, a)
+	return ctxt.Instoffset
+}
+
+func regoff(ctxt *obj.Link, a *obj.Addr) int32 {
+	return int32(vregoff(ctxt, a))
+}
+
+func oprrr(ctxt *obj.Link, a int) uint32 {
+	switch a {
+	case AADD:
+		return OP(4, 0)
+	case AADDU:
+		return OP(4, 1)
+	case ASGT:
+		return OP(5, 2)
+	case ASGTU:
+		return OP(5, 3)
+	case AAND:
+		return OP(4, 4)
+	case AOR:
+		return OP(4, 5)
+	case AXOR:
+		return OP(4, 6)
+	case ASUB:
+		return OP(4, 2)
+	case ASUBU:
+		return OP(4, 3)
+	case ANOR:
+		return OP(4, 7)
+	case ASLL:
+		return OP(0, 4)
+	case ASRL:
+		return OP(0, 6)
+	case ASRA:
+		return OP(0, 7)
+	case ASLLV:
+		return OP(2, 4)
+	case ASRLV:
+		return OP(2, 6)
+	case ASRAV:
+		return OP(2, 7)
+	case AADDV:
+		return OP(5, 4)
+	case AADDVU:
+		return OP(5, 5)
+	case ASUBV:
+		return OP(5, 6)
+	case ASUBVU:
+		return OP(5, 7)
+	case AREM,
+		ADIV:
+		return OP(3, 2)
+	case AREMU,
+		ADIVU:
+		return OP(3, 3)
+	case AMUL:
+		return OP(3, 0)
+	case AMULU:
+		return OP(3, 1)
+	case AREMV,
+		ADIVV:
+		return OP(3, 6)
+	case AREMVU,
+		ADIVVU:
+		return OP(3, 7)
+	case AMULV:
+		return OP(3, 4)
+	case AMULVU:
+		return OP(3, 5)
+
+	case AJMP:
+		return OP(1, 0)
+	case AJAL:
+		return OP(1, 1)
+
+	case ABREAK:
+		return OP(1, 5)
+	case ASYSCALL:
+		return OP(1, 4)
+	case ATLBP:
+		return MMU(1, 0)
+	case ATLBR:
+		return MMU(0, 1)
+	case ATLBWI:
+		return MMU(0, 2)
+	case ATLBWR:
+		return MMU(0, 6)
+	case ARFE:
+		return MMU(2, 0)
+
+	case ADIVF:
+		return FPF(0, 3)
+	case ADIVD:
+		return FPD(0, 3)
+	case AMULF:
+		return FPF(0, 2)
+	case AMULD:
+		return FPD(0, 2)
+	case ASUBF:
+		return FPF(0, 1)
+	case ASUBD:
+		return FPD(0, 1)
+	case AADDF:
+		return FPF(0, 0)
+	case AADDD:
+		return FPD(0, 0)
+	case ATRUNCFV:
+		return FPF(1, 1)
+	case ATRUNCDV:
+		return FPD(1, 1)
+	case ATRUNCFW:
+		return FPF(1, 5)
+	case ATRUNCDW:
+		return FPD(1, 5)
+	case AMOVFV:
+		return FPF(4, 5)
+	case AMOVDV:
+		return FPD(4, 5)
+	case AMOVVF:
+		return FPV(4, 0)
+	case AMOVVD:
+		return FPV(4, 1)
+	case AMOVFW:
+		return FPF(4, 4)
+	case AMOVDW:
+		return FPD(4, 4)
+	case AMOVWF:
+		return FPW(4, 0)
+	case AMOVDF:
+		return FPD(4, 0)
+	case AMOVWD:
+		return FPW(4, 1)
+	case AMOVFD:
+		return FPF(4, 1)
+	case AABSF:
+		return FPF(0, 5)
+	case AABSD:
+		return FPD(0, 5)
+	case AMOVF:
+		return FPF(0, 6)
+	case AMOVD:
+		return FPD(0, 6)
+	case ANEGF:
+		return FPF(0, 7)
+	case ANEGD:
+		return FPD(0, 7)
+	case ACMPEQF:
+		return FPF(6, 2)
+	case ACMPEQD:
+		return FPD(6, 2)
+	case ACMPGTF:
+		return FPF(7, 4)
+	case ACMPGTD:
+		return FPD(7, 4)
+	case ACMPGEF:
+		return FPF(7, 6)
+	case ACMPGED:
+		return FPD(7, 6)
+	}
+
+	if a >= ALAST {
+		ctxt.Diag("bad rrr opcode %v+ALAST", obj.Aconv(a-ALAST))
+	} else {
+		ctxt.Diag("bad rrr opcode %v", obj.Aconv(a))
+	}
+	return 0
+}
+
+func opirr(ctxt *obj.Link, a int) uint32 {
+	switch a {
+	case AADD:
+		return SP(1, 0)
+	case AADDU:
+		return SP(1, 1)
+	case ASGT:
+		return SP(1, 2)
+	case ASGTU:
+		return SP(1, 3)
+	case AAND:
+		return SP(1, 4)
+	case AOR:
+		return SP(1, 5)
+	case AXOR:
+		return SP(1, 6)
+	case ALAST:
+		return SP(1, 7) /* lui */
+	case ASLL:
+		return OP(0, 0)
+	case ASRL:
+		return OP(0, 2)
+	case ASRA:
+		return OP(0, 3)
+	case AADDV:
+		return SP(3, 0)
+	case AADDVU:
+		return SP(3, 1)
+
+	case AJMP:
+		return SP(0, 2)
+	case AJAL,
+		obj.ADUFFZERO,
+		obj.ADUFFCOPY:
+		return SP(0, 3)
+	case ABEQ:
+		return SP(0, 4)
+	case ABEQ + ALAST:
+		return SP(2, 4) /* likely */
+	case ABNE:
+		return SP(0, 5)
+	case ABNE + ALAST:
+		return SP(2, 5) /* likely */
+	case ABGEZ:
+		return SP(0, 1) | BCOND(0, 1)
+	case ABGEZ + ALAST:
+		return SP(0, 1) | BCOND(0, 3) /* likely */
+	case ABGEZAL:
+		return SP(0, 1) | BCOND(2, 1)
+	case ABGEZAL + ALAST:
+		return SP(0, 1) | BCOND(2, 3) /* likely */
+	case ABGTZ:
+		return SP(0, 7)
+	case ABGTZ + ALAST:
+		return SP(2, 7) /* likely */
+	case ABLEZ:
+		return SP(0, 6)
+	case ABLEZ + ALAST:
+		return SP(2, 6) /* likely */
+	case ABLTZ:
+		return SP(0, 1) | BCOND(0, 0)
+	case ABLTZ + ALAST:
+		return SP(0, 1) | BCOND(0, 2) /* likely */
+	case ABLTZAL:
+		return SP(0, 1) | BCOND(2, 0)
+	case ABLTZAL + ALAST:
+		return SP(0, 1) | BCOND(2, 2) /* likely */
+	case ABFPT:
+		return SP(2, 1) | (257 << 16)
+	case ABFPT + ALAST:
+		return SP(2, 1) | (259 << 16) /* likely */
+	case ABFPF:
+		return SP(2, 1) | (256 << 16)
+	case ABFPF + ALAST:
+		return SP(2, 1) | (258 << 16) /* likely */
+
+	case AMOVB,
+		AMOVBU:
+		return SP(5, 0)
+	case AMOVH,
+		AMOVHU:
+		return SP(5, 1)
+	case AMOVW,
+		AMOVWU:
+		return SP(5, 3)
+	case AMOVV:
+		return SP(7, 7)
+	case AMOVF:
+		return SP(7, 1)
+	case AMOVD:
+		return SP(7, 5)
+	case AMOVWL:
+		return SP(5, 2)
+	case AMOVWR:
+		return SP(5, 6)
+	case AMOVVL:
+		return SP(5, 4)
+	case AMOVVR:
+		return SP(5, 5)
+
+	case ABREAK:
+		return SP(5, 7)
+
+	case AMOVWL + ALAST:
+		return SP(4, 2)
+	case AMOVWR + ALAST:
+		return SP(4, 6)
+	case AMOVVL + ALAST:
+		return SP(3, 2)
+	case AMOVVR + ALAST:
+		return SP(3, 3)
+	case AMOVB + ALAST:
+		return SP(4, 0)
+	case AMOVBU + ALAST:
+		return SP(4, 4)
+	case AMOVH + ALAST:
+		return SP(4, 1)
+	case AMOVHU + ALAST:
+		return SP(4, 5)
+	case AMOVW + ALAST:
+		return SP(4, 3)
+	case AMOVWU + ALAST:
+		return SP(4, 7)
+	case AMOVV + ALAST:
+		return SP(6, 7)
+	case AMOVF + ALAST:
+		return SP(6, 1)
+	case AMOVD + ALAST:
+		return SP(6, 5)
+
+	case ASLLV:
+		return OP(7, 0)
+	case ASRLV:
+		return OP(7, 2)
+	case ASRAV:
+		return OP(7, 3)
+	case ASLLV + ALAST:
+		return OP(7, 4)
+	case ASRLV + ALAST:
+		return OP(7, 6)
+	case ASRAV + ALAST:
+		return OP(7, 7)
+	}
+
+	if a >= ALAST {
+		ctxt.Diag("bad irr opcode %v+ALAST", obj.Aconv(a-ALAST))
+	} else {
+		ctxt.Diag("bad irr opcode %v", obj.Aconv(a))
+	}
+	return 0
+}
+
+func vshift(a int16) bool {
+	switch a {
+	case ASLLV,
+		ASRLV,
+		ASRAV:
+		return true
+	}
+	return false
+}
diff --git a/src/cmd/internal/obj/mips/list0.go b/src/cmd/internal/obj/mips/list0.go
new file mode 100644
index 0000000..40dc460
--- /dev/null
+++ b/src/cmd/internal/obj/mips/list0.go
@@ -0,0 +1,80 @@
+// cmd/9l/list.c from Vita Nuova.
+//
+//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//	Portions Copyright © 1995-1997 C H Forsyth (forsyth at terzarima.net)
+//	Portions Copyright © 1997-1999 Vita Nuova Limited
+//	Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+//	Portions Copyright © 2004,2006 Bruce Ellis
+//	Portions Copyright © 2005-2007 C H Forsyth (forsyth at terzarima.net)
+//	Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
+//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package mips
+
+import (
+	"cmd/internal/obj"
+	"fmt"
+)
+
+func init() {
+	obj.RegisterRegister(obj.RBaseMIPS64, REG_LAST&^1023+1024, Rconv)
+	obj.RegisterOpcode(obj.ABaseMIPS64, Anames)
+}
+
+func Rconv(r int) string {
+	if r == 0 {
+		return "NONE"
+	}
+	if r == REGG {
+		// Special case.
+		return "g"
+	}
+	if REG_R0 <= r && r <= REG_R31 {
+		return fmt.Sprintf("R%d", r-REG_R0)
+	}
+	if REG_F0 <= r && r <= REG_F31 {
+		return fmt.Sprintf("F%d", r-REG_F0)
+	}
+	if REG_M0 <= r && r <= REG_M31 {
+		return fmt.Sprintf("M%d", r-REG_M0)
+	}
+	if REG_FCR0 <= r && r <= REG_FCR31 {
+		return fmt.Sprintf("FCR%d", r-REG_FCR0)
+	}
+	if r == REG_HI {
+		return "HI"
+	}
+	if r == REG_LO {
+		return "LO"
+	}
+
+	return fmt.Sprintf("Rgok(%d)", r-obj.RBaseMIPS64)
+}
+
+func DRconv(a int) string {
+	s := "C_??"
+	if a >= C_NONE && a <= C_NCLASS {
+		s = cnames0[a]
+	}
+	var fp string
+	fp += s
+	return fp
+}
diff --git a/src/cmd/internal/obj/mips/obj0.go b/src/cmd/internal/obj/mips/obj0.go
new file mode 100644
index 0000000..a3ccad2
--- /dev/null
+++ b/src/cmd/internal/obj/mips/obj0.go
@@ -0,0 +1,1497 @@
+// cmd/9l/noop.c, cmd/9l/pass.c, cmd/9l/span.c from Vita Nuova.
+//
+//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//	Portions Copyright © 1995-1997 C H Forsyth (forsyth at terzarima.net)
+//	Portions Copyright © 1997-1999 Vita Nuova Limited
+//	Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+//	Portions Copyright © 2004,2006 Bruce Ellis
+//	Portions Copyright © 2005-2007 C H Forsyth (forsyth at terzarima.net)
+//	Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
+//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package mips
+
+import (
+	"cmd/internal/obj"
+	"encoding/binary"
+	"fmt"
+	"math"
+)
+
+func progedit(ctxt *obj.Link, p *obj.Prog) {
+	p.From.Class = 0
+	p.To.Class = 0
+
+	// Rewrite JMP/JAL to symbol as TYPE_BRANCH.
+	switch p.As {
+	case AJMP,
+		AJAL,
+		ARET,
+		obj.ADUFFZERO,
+		obj.ADUFFCOPY:
+		if p.To.Sym != nil {
+			p.To.Type = obj.TYPE_BRANCH
+		}
+	}
+
+	// Rewrite float constants to values stored in memory.
+	switch p.As {
+	case AMOVF:
+		if p.From.Type == obj.TYPE_FCONST {
+			f32 := float32(p.From.Val.(float64))
+			i32 := math.Float32bits(f32)
+			literal := fmt.Sprintf("$f32.%08x", i32)
+			s := obj.Linklookup(ctxt, literal, 0)
+			s.Size = 4
+			p.From.Type = obj.TYPE_MEM
+			p.From.Sym = s
+			p.From.Name = obj.NAME_EXTERN
+			p.From.Offset = 0
+		}
+
+	case AMOVD:
+		if p.From.Type == obj.TYPE_FCONST {
+			i64 := math.Float64bits(p.From.Val.(float64))
+			literal := fmt.Sprintf("$f64.%016x", i64)
+			s := obj.Linklookup(ctxt, literal, 0)
+			s.Size = 8
+			p.From.Type = obj.TYPE_MEM
+			p.From.Sym = s
+			p.From.Name = obj.NAME_EXTERN
+			p.From.Offset = 0
+		}
+
+		// Put >32-bit constants in memory and load them
+	case AMOVV:
+		if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE && p.From.Reg == 0 && int64(int32(p.From.Offset)) != p.From.Offset {
+			literal := fmt.Sprintf("$i64.%016x", uint64(p.From.Offset))
+			s := obj.Linklookup(ctxt, literal, 0)
+			s.Size = 8
+			p.From.Type = obj.TYPE_MEM
+			p.From.Sym = s
+			p.From.Name = obj.NAME_EXTERN
+			p.From.Offset = 0
+		}
+	}
+
+	// Rewrite SUB constants into ADD.
+	switch p.As {
+	case ASUB:
+		if p.From.Type == obj.TYPE_CONST {
+			p.From.Offset = -p.From.Offset
+			p.As = AADD
+		}
+
+	case ASUBU:
+		if p.From.Type == obj.TYPE_CONST {
+			p.From.Offset = -p.From.Offset
+			p.As = AADDU
+		}
+
+	case ASUBV:
+		if p.From.Type == obj.TYPE_CONST {
+			p.From.Offset = -p.From.Offset
+			p.As = AADDV
+		}
+
+	case ASUBVU:
+		if p.From.Type == obj.TYPE_CONST {
+			p.From.Offset = -p.From.Offset
+			p.As = AADDVU
+		}
+	}
+}
+
+func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
+	// TODO(minux): add morestack short-cuts with small fixed frame-size.
+	ctxt.Cursym = cursym
+
+	// a switch for enabling/disabling instruction scheduling
+	nosched := true
+
+	if cursym.Text == nil || cursym.Text.Link == nil {
+		return
+	}
+
+	p := cursym.Text
+	textstksiz := p.To.Offset
+
+	cursym.Args = p.To.Val.(int32)
+	cursym.Locals = int32(textstksiz)
+
+	/*
+	 * find leaf subroutines
+	 * strip NOPs
+	 * expand RET
+	 * expand BECOME pseudo
+	 */
+	if ctxt.Debugvlog != 0 {
+		fmt.Fprintf(ctxt.Bso, "%5.2f noops\n", obj.Cputime())
+	}
+	ctxt.Bso.Flush()
+
+	var q *obj.Prog
+	var q1 *obj.Prog
+	for p := cursym.Text; p != nil; p = p.Link {
+		switch p.As {
+		/* too hard, just leave alone */
+		case obj.ATEXT:
+			q = p
+
+			p.Mark |= LABEL | LEAF | SYNC
+			if p.Link != nil {
+				p.Link.Mark |= LABEL
+			}
+
+		/* too hard, just leave alone */
+		case AMOVW,
+			AMOVV:
+			q = p
+			if p.To.Type == obj.TYPE_REG && p.To.Reg >= REG_SPECIAL {
+				p.Mark |= LABEL | SYNC
+				break
+			}
+			if p.From.Type == obj.TYPE_REG && p.From.Reg >= REG_SPECIAL {
+				p.Mark |= LABEL | SYNC
+			}
+
+		/* too hard, just leave alone */
+		case ASYSCALL,
+			AWORD,
+			ATLBWR,
+			ATLBWI,
+			ATLBP,
+			ATLBR:
+			q = p
+			p.Mark |= LABEL | SYNC
+
+		case ANOR:
+			q = p
+			if p.To.Type == obj.TYPE_REG {
+				if p.To.Reg == REGZERO {
+					p.Mark |= LABEL | SYNC
+				}
+			}
+
+		case ABGEZAL,
+			ABLTZAL,
+			AJAL,
+			obj.ADUFFZERO,
+			obj.ADUFFCOPY:
+			cursym.Text.Mark &^= LEAF
+			fallthrough
+
+		case AJMP,
+			ABEQ,
+			ABGEZ,
+			ABGTZ,
+			ABLEZ,
+			ABLTZ,
+			ABNE,
+			ABFPT, ABFPF:
+			if p.As == ABFPT || p.As == ABFPF {
+				// We don't treat ABFPT and ABFPF as branches here,
+				// so that we will always fill nop (0x0) in their
+				// delay slot during assembly.
+				// This is to workaround a kernel FPU emulator bug
+				// where it uses the user stack to simulate the
+				// instruction in the delay slot if it's not 0x0,
+				// and somehow that leads to SIGSEGV when the kernel
+				// jump to the stack.
+				p.Mark |= SYNC
+			} else {
+				p.Mark |= BRANCH
+			}
+			q = p
+			q1 = p.Pcond
+			if q1 != nil {
+				for q1.As == obj.ANOP {
+					q1 = q1.Link
+					p.Pcond = q1
+				}
+
+				if q1.Mark&LEAF == 0 {
+					q1.Mark |= LABEL
+				}
+			}
+			//else {
+			//	p.Mark |= LABEL
+			//}
+			q1 = p.Link
+			if q1 != nil {
+				q1.Mark |= LABEL
+			}
+			continue
+
+		case ARET:
+			q = p
+			if p.Link != nil {
+				p.Link.Mark |= LABEL
+			}
+			continue
+
+		case obj.ANOP:
+			q1 = p.Link
+			q.Link = q1 /* q is non-nop */
+			q1.Mark |= p.Mark
+			continue
+
+		default:
+			q = p
+			continue
+		}
+	}
+
+	autosize := int32(0)
+	var o int
+	var p1 *obj.Prog
+	var p2 *obj.Prog
+	for p := cursym.Text; p != nil; p = p.Link {
+		o = int(p.As)
+		switch o {
+		case obj.ATEXT:
+			autosize = int32(textstksiz + 8)
+			if (p.Mark&LEAF != 0) && autosize <= 8 {
+				autosize = 0
+			} else if autosize&4 != 0 {
+				autosize += 4
+			}
+			p.To.Offset = int64(autosize) - 8
+
+			if p.From3.Offset&obj.NOSPLIT == 0 {
+				p = stacksplit(ctxt, p, autosize) // emit split check
+			}
+
+			q = p
+
+			if autosize != 0 {
+				q = obj.Appendp(ctxt, p)
+				q.As = AADDV
+				q.Lineno = p.Lineno
+				q.From.Type = obj.TYPE_CONST
+				q.From.Offset = int64(-autosize)
+				q.To.Type = obj.TYPE_REG
+				q.To.Reg = REGSP
+				q.Spadj = +autosize
+			} else if cursym.Text.Mark&LEAF == 0 {
+				if cursym.Text.From3.Offset&obj.NOSPLIT != 0 {
+					if ctxt.Debugvlog != 0 {
+						fmt.Fprintf(ctxt.Bso, "save suppressed in: %s\n", cursym.Name)
+						ctxt.Bso.Flush()
+					}
+
+					cursym.Text.Mark |= LEAF
+				}
+			}
+
+			if cursym.Text.Mark&LEAF != 0 {
+				cursym.Leaf = 1
+				break
+			}
+
+			q = obj.Appendp(ctxt, q)
+			q.As = AMOVV
+			q.Lineno = p.Lineno
+			q.From.Type = obj.TYPE_REG
+			q.From.Reg = REGLINK
+			q.To.Type = obj.TYPE_MEM
+			q.To.Offset = int64(0)
+			q.To.Reg = REGSP
+
+			if cursym.Text.From3.Offset&obj.WRAPPER != 0 {
+				// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
+				//
+				//	MOVV	g_panic(g), R1
+				//	BEQ		R1, end
+				//	MOVV	panic_argp(R1), R2
+				//	ADDV	$(autosize+8), R29, R3
+				//	BNE		R2, R3, end
+				//	ADDV	$8, R29, R2
+				//	MOVV	R2, panic_argp(R1)
+				// end:
+				//	NOP
+				//
+				// The NOP is needed to give the jumps somewhere to land.
+				// It is a liblink NOP, not an mips NOP: it encodes to 0 instruction bytes.
+
+				q = obj.Appendp(ctxt, q)
+
+				q.As = AMOVV
+				q.From.Type = obj.TYPE_MEM
+				q.From.Reg = REGG
+				q.From.Offset = 4 * int64(ctxt.Arch.Ptrsize) // G.panic
+				q.To.Type = obj.TYPE_REG
+				q.To.Reg = REG_R1
+
+				q = obj.Appendp(ctxt, q)
+				q.As = ABEQ
+				q.From.Type = obj.TYPE_REG
+				q.From.Reg = REG_R1
+				q.To.Type = obj.TYPE_BRANCH
+				q.Mark |= BRANCH
+				p1 = q
+
+				q = obj.Appendp(ctxt, q)
+				q.As = AMOVV
+				q.From.Type = obj.TYPE_MEM
+				q.From.Reg = REG_R1
+				q.From.Offset = 0 // Panic.argp
+				q.To.Type = obj.TYPE_REG
+				q.To.Reg = REG_R2
+
+				q = obj.Appendp(ctxt, q)
+				q.As = AADDV
+				q.From.Type = obj.TYPE_CONST
+				q.From.Offset = int64(autosize) + 8
+				q.Reg = REGSP
+				q.To.Type = obj.TYPE_REG
+				q.To.Reg = REG_R3
+
+				q = obj.Appendp(ctxt, q)
+				q.As = ABNE
+				q.From.Type = obj.TYPE_REG
+				q.From.Reg = REG_R2
+				q.Reg = REG_R3
+				q.To.Type = obj.TYPE_BRANCH
+				q.Mark |= BRANCH
+				p2 = q
+
+				q = obj.Appendp(ctxt, q)
+				q.As = AADDV
+				q.From.Type = obj.TYPE_CONST
+				q.From.Offset = 8
+				q.Reg = REGSP
+				q.To.Type = obj.TYPE_REG
+				q.To.Reg = REG_R2
+
+				q = obj.Appendp(ctxt, q)
+				q.As = AMOVV
+				q.From.Type = obj.TYPE_REG
+				q.From.Reg = REG_R2
+				q.To.Type = obj.TYPE_MEM
+				q.To.Reg = REG_R1
+				q.To.Offset = 0 // Panic.argp
+
+				q = obj.Appendp(ctxt, q)
+
+				q.As = obj.ANOP
+				p1.Pcond = q
+				p2.Pcond = q
+			}
+
+		case ARET:
+			if p.From.Type == obj.TYPE_CONST {
+				ctxt.Diag("using BECOME (%v) is not supported!", p)
+				break
+			}
+
+			if p.To.Sym != nil { // retjmp
+				p.As = AJMP
+				p.To.Type = obj.TYPE_BRANCH
+				break
+			}
+
+			if cursym.Text.Mark&LEAF != 0 {
+				if autosize == 0 {
+					p.As = AJMP
+					p.From = obj.Addr{}
+					p.To.Type = obj.TYPE_MEM
+					p.To.Offset = 0
+					p.To.Reg = REGLINK
+					p.Mark |= BRANCH
+					break
+				}
+
+				p.As = AADDV
+				p.From.Type = obj.TYPE_CONST
+				p.From.Offset = int64(autosize)
+				p.To.Type = obj.TYPE_REG
+				p.To.Reg = REGSP
+				p.Spadj = -autosize
+
+				q = ctxt.NewProg()
+				q.As = AJMP
+				q.Lineno = p.Lineno
+				q.To.Type = obj.TYPE_MEM
+				q.To.Offset = 0
+				q.To.Reg = REGLINK
+				q.Mark |= BRANCH
+				q.Spadj = +autosize
+
+				q.Link = p.Link
+				p.Link = q
+				break
+			}
+
+			p.As = AMOVV
+			p.From.Type = obj.TYPE_MEM
+			p.From.Offset = 0
+			p.From.Reg = REGSP
+			p.To.Type = obj.TYPE_REG
+			p.To.Reg = REG_R4
+
+			if false {
+				// Debug bad returns
+				q = ctxt.NewProg()
+
+				q.As = AMOVV
+				q.Lineno = p.Lineno
+				q.From.Type = obj.TYPE_MEM
+				q.From.Offset = 0
+				q.From.Reg = REG_R4
+				q.To.Type = obj.TYPE_REG
+				q.To.Reg = REGTMP
+
+				q.Link = p.Link
+				p.Link = q
+				p = q
+			}
+
+			if autosize != 0 {
+				q = ctxt.NewProg()
+				q.As = AADDV
+				q.Lineno = p.Lineno
+				q.From.Type = obj.TYPE_CONST
+				q.From.Offset = int64(autosize)
+				q.To.Type = obj.TYPE_REG
+				q.To.Reg = REGSP
+				q.Spadj = -autosize
+
+				q.Link = p.Link
+				p.Link = q
+			}
+
+			q1 = ctxt.NewProg()
+			q1.As = AJMP
+			q1.Lineno = p.Lineno
+			q1.To.Type = obj.TYPE_MEM
+			q1.To.Offset = 0
+			q1.To.Reg = REG_R4
+			q1.Mark |= BRANCH
+			q1.Spadj = +autosize
+
+			q1.Link = q.Link
+			q.Link = q1
+
+		case AADDV,
+			AADDVU:
+			if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST {
+				p.Spadj = int32(-p.From.Offset)
+			}
+		}
+	}
+
+	if nosched {
+		// if we don't do instruction scheduling, simply add
+		// NOP after each branch instruction.
+		for p = cursym.Text; p != nil; p = p.Link {
+			if p.Mark&BRANCH != 0 {
+				addnop(ctxt, p)
+			}
+		}
+		return
+	}
+
+	// instruction scheduling
+	q = nil          // p - 1
+	q1 = cursym.Text // top of block
+	o = 0            // count of instructions
+	for p = cursym.Text; p != nil; p = p1 {
+		p1 = p.Link
+		o++
+		if p.Mark&NOSCHED != 0 {
+			if q1 != p {
+				sched(ctxt, q1, q)
+			}
+			for ; p != nil; p = p.Link {
+				if p.Mark&NOSCHED == 0 {
+					break
+				}
+				q = p
+			}
+			p1 = p
+			q1 = p
+			o = 0
+			continue
+		}
+		if p.Mark&(LABEL|SYNC) != 0 {
+			if q1 != p {
+				sched(ctxt, q1, q)
+			}
+			q1 = p
+			o = 1
+		}
+		if p.Mark&(BRANCH|SYNC) != 0 {
+			sched(ctxt, q1, p)
+			q1 = p1
+			o = 0
+		}
+		if o >= NSCHED {
+			sched(ctxt, q1, p)
+			q1 = p1
+			o = 0
+		}
+		q = p
+	}
+}
+
+func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
+	// MOVV	g_stackguard(g), R1
+	p = obj.Appendp(ctxt, p)
+
+	p.As = AMOVV
+	p.From.Type = obj.TYPE_MEM
+	p.From.Reg = REGG
+	p.From.Offset = 2 * int64(ctxt.Arch.Ptrsize) // G.stackguard0
+	if ctxt.Cursym.Cfunc != 0 {
+		p.From.Offset = 3 * int64(ctxt.Arch.Ptrsize) // G.stackguard1
+	}
+	p.To.Type = obj.TYPE_REG
+	p.To.Reg = REG_R1
+
+	var q *obj.Prog
+	if framesize <= obj.StackSmall {
+		// small stack: SP < stackguard
+		//	AGTU	SP, stackguard, R1
+		p = obj.Appendp(ctxt, p)
+
+		p.As = ASGTU
+		p.From.Type = obj.TYPE_REG
+		p.From.Reg = REGSP
+		p.Reg = REG_R1
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = REG_R1
+	} else if framesize <= obj.StackBig {
+		// large stack: SP-framesize < stackguard-StackSmall
+		//	ADDV	$-framesize, SP, R2
+		//	SGTU	R2, stackguard, R1
+		p = obj.Appendp(ctxt, p)
+
+		p.As = AADDV
+		p.From.Type = obj.TYPE_CONST
+		p.From.Offset = int64(-framesize)
+		p.Reg = REGSP
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = REG_R2
+
+		p = obj.Appendp(ctxt, p)
+		p.As = ASGTU
+		p.From.Type = obj.TYPE_REG
+		p.From.Reg = REG_R2
+		p.Reg = REG_R1
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = REG_R1
+	} else {
+		// Such a large stack we need to protect against wraparound.
+		// If SP is close to zero:
+		//	SP-stackguard+StackGuard <= framesize + (StackGuard-StackSmall)
+		// The +StackGuard on both sides is required to keep the left side positive:
+		// SP is allowed to be slightly below stackguard. See stack.h.
+		//
+		// Preemption sets stackguard to StackPreempt, a very large value.
+		// That breaks the math above, so we have to check for that explicitly.
+		//	// stackguard is R1
+		//	MOVV	$StackPreempt, R2
+		//	BEQ	R1, R2, label-of-call-to-morestack
+		//	ADDV	$StackGuard, SP, R2
+		//	SUBVU	R1, R2
+		//	MOVV	$(framesize+(StackGuard-StackSmall)), R1
+		//	SGTU	R2, R1, R1
+		p = obj.Appendp(ctxt, p)
+
+		p.As = AMOVV
+		p.From.Type = obj.TYPE_CONST
+		p.From.Offset = obj.StackPreempt
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = REG_R2
+
+		p = obj.Appendp(ctxt, p)
+		q = p
+		p.As = ABEQ
+		p.From.Type = obj.TYPE_REG
+		p.From.Reg = REG_R1
+		p.Reg = REG_R2
+		p.To.Type = obj.TYPE_BRANCH
+		p.Mark |= BRANCH
+
+		p = obj.Appendp(ctxt, p)
+		p.As = AADDV
+		p.From.Type = obj.TYPE_CONST
+		p.From.Offset = obj.StackGuard
+		p.Reg = REGSP
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = REG_R2
+
+		p = obj.Appendp(ctxt, p)
+		p.As = ASUBVU
+		p.From.Type = obj.TYPE_REG
+		p.From.Reg = REG_R1
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = REG_R2
+
+		p = obj.Appendp(ctxt, p)
+		p.As = AMOVV
+		p.From.Type = obj.TYPE_CONST
+		p.From.Offset = int64(framesize) + obj.StackGuard - obj.StackSmall
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = REG_R1
+
+		p = obj.Appendp(ctxt, p)
+		p.As = ASGTU
+		p.From.Type = obj.TYPE_REG
+		p.From.Reg = REG_R2
+		p.Reg = REG_R1
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = REG_R1
+	}
+
+	// q1: BNE	R1, done
+	p = obj.Appendp(ctxt, p)
+	q1 := p
+
+	p.As = ABNE
+	p.From.Type = obj.TYPE_REG
+	p.From.Reg = REG_R1
+	p.To.Type = obj.TYPE_BRANCH
+	p.Mark |= BRANCH
+
+	// MOVV	LINK, R3
+	p = obj.Appendp(ctxt, p)
+
+	p.As = AMOVV
+	p.From.Type = obj.TYPE_REG
+	p.From.Reg = REGLINK
+	p.To.Type = obj.TYPE_REG
+	p.To.Reg = REG_R3
+	if q != nil {
+		q.Pcond = p
+		p.Mark |= LABEL
+	}
+
+	// JAL	runtime.morestack(SB)
+	p = obj.Appendp(ctxt, p)
+
+	p.As = AJAL
+	p.To.Type = obj.TYPE_BRANCH
+	if ctxt.Cursym.Cfunc != 0 {
+		p.To.Sym = obj.Linklookup(ctxt, "runtime.morestackc", 0)
+	} else if ctxt.Cursym.Text.From3.Offset&obj.NEEDCTXT == 0 {
+		p.To.Sym = obj.Linklookup(ctxt, "runtime.morestack_noctxt", 0)
+	} else {
+		p.To.Sym = obj.Linklookup(ctxt, "runtime.morestack", 0)
+	}
+	p.Mark |= BRANCH
+
+	// JMP	start
+	p = obj.Appendp(ctxt, p)
+
+	p.As = AJMP
+	p.To.Type = obj.TYPE_BRANCH
+	p.Pcond = ctxt.Cursym.Text.Link
+	p.Mark |= BRANCH
+
+	// placeholder for q1's jump target
+	p = obj.Appendp(ctxt, p)
+
+	p.As = obj.ANOP // zero-width place holder
+	q1.Pcond = p
+
+	return p
+}
+
+func addnop(ctxt *obj.Link, p *obj.Prog) {
+	q := ctxt.NewProg()
+	// we want to use the canonical NOP (SLL $0,R0,R0) here,
+	// however, as the assembler will always replace $0
+	// as R0, we have to resort to manually encode the SLL
+	// instruction as WORD $0.
+	q.As = AWORD
+	q.Lineno = p.Lineno
+	q.From.Type = obj.TYPE_CONST
+	q.From.Name = obj.NAME_NONE
+	q.From.Offset = 0
+
+	q.Link = p.Link
+	p.Link = q
+}
+
+const (
+	E_HILO  = 1 << 0
+	E_FCR   = 1 << 1
+	E_MCR   = 1 << 2
+	E_MEM   = 1 << 3
+	E_MEMSP = 1 << 4 /* uses offset and size */
+	E_MEMSB = 1 << 5 /* uses offset and size */
+	ANYMEM  = E_MEM | E_MEMSP | E_MEMSB
+	//DELAY = LOAD|BRANCH|FCMP
+	DELAY = BRANCH /* only schedule branch */
+)
+
+type Dep struct {
+	ireg uint32
+	freg uint32
+	cc   uint32
+}
+
+type Sch struct {
+	p       obj.Prog
+	set     Dep
+	used    Dep
+	soffset int32
+	size    uint8
+	nop     uint8
+	comp    bool
+}
+
+func sched(ctxt *obj.Link, p0, pe *obj.Prog) {
+	var sch [NSCHED]Sch
+
+	/*
+	 * build side structure
+	 */
+	s := sch[:]
+	for p := p0; ; p = p.Link {
+		s[0].p = *p
+		markregused(ctxt, &s[0])
+		if p == pe {
+			break
+		}
+		s = s[1:]
+	}
+	se := s
+
+	for i := cap(sch) - cap(se); i >= 0; i-- {
+		s = sch[i:]
+		if s[0].p.Mark&DELAY == 0 {
+			continue
+		}
+		if -cap(s) < -cap(se) {
+			if !conflict(&s[0], &s[1]) {
+				continue
+			}
+		}
+
+		var t []Sch
+		var j int
+		for j = cap(sch) - cap(s) - 1; j >= 0; j-- {
+			t = sch[j:]
+			if t[0].comp {
+				if s[0].p.Mark&BRANCH != 0 {
+					goto no2
+				}
+			}
+			if t[0].p.Mark&DELAY != 0 {
+				if -cap(s) >= -cap(se) || conflict(&t[0], &s[1]) {
+					goto no2
+				}
+			}
+			for u := t[1:]; -cap(u) <= -cap(s); u = u[1:] {
+				if depend(ctxt, &u[0], &t[0]) {
+					goto no2
+				}
+			}
+			goto out2
+		no2:
+		}
+
+		if s[0].p.Mark&BRANCH != 0 {
+			s[0].nop = 1
+		}
+		continue
+
+	out2:
+		// t[0] is the instruction being moved to fill the delay
+		stmp := t[0]
+		copy(t[:i-j], t[1:i-j+1])
+		s[0] = stmp
+
+		if t[i-j-1].p.Mark&BRANCH != 0 {
+			// t[i-j] is being put into a branch delay slot
+			// combine its Spadj with the branch instruction
+			t[i-j-1].p.Spadj += t[i-j].p.Spadj
+			t[i-j].p.Spadj = 0
+		}
+
+		i--
+	}
+
+	/*
+	 * put it all back
+	 */
+	var p *obj.Prog
+	var q *obj.Prog
+	for s, p = sch[:], p0; -cap(s) <= -cap(se); s, p = s[1:], q {
+		q = p.Link
+		if q != s[0].p.Link {
+			*p = s[0].p
+			p.Link = q
+		}
+		for s[0].nop != 0 {
+			s[0].nop--
+			addnop(ctxt, p)
+		}
+	}
+}
+
+func markregused(ctxt *obj.Link, s *Sch) {
+	p := &s.p
+	s.comp = compound(ctxt, p)
+	s.nop = 0
+	if s.comp {
+		s.set.ireg |= 1 << (REGTMP - REG_R0)
+		s.used.ireg |= 1 << (REGTMP - REG_R0)
+	}
+
+	ar := 0  /* dest is really reference */
+	ad := 0  /* source/dest is really address */
+	ld := 0  /* opcode is load instruction */
+	sz := 20 /* size of load/store for overlap computation */
+
+	/*
+	 * flags based on opcode
+	 */
+	switch p.As {
+	case obj.ATEXT:
+		ctxt.Autosize = int32(p.To.Offset + 8)
+		ad = 1
+
+	case AJAL:
+		c := p.Reg
+		if c == 0 {
+			c = REGLINK
+		}
+		s.set.ireg |= 1 << uint(c-REG_R0)
+		ar = 1
+		ad = 1
+
+	case ABGEZAL,
+		ABLTZAL:
+		s.set.ireg |= 1 << (REGLINK - REG_R0)
+		fallthrough
+	case ABEQ,
+		ABGEZ,
+		ABGTZ,
+		ABLEZ,
+		ABLTZ,
+		ABNE:
+		ar = 1
+		ad = 1
+
+	case ABFPT,
+		ABFPF:
+		ad = 1
+		s.used.cc |= E_FCR
+
+	case ACMPEQD,
+		ACMPEQF,
+		ACMPGED,
+		ACMPGEF,
+		ACMPGTD,
+		ACMPGTF:
+		ar = 1
+		s.set.cc |= E_FCR
+		p.Mark |= FCMP
+
+	case AJMP:
+		ar = 1
+		ad = 1
+
+	case AMOVB,
+		AMOVBU:
+		sz = 1
+		ld = 1
+
+	case AMOVH,
+		AMOVHU:
+		sz = 2
+		ld = 1
+
+	case AMOVF,
+		AMOVW,
+		AMOVWL,
+		AMOVWR:
+		sz = 4
+		ld = 1
+
+	case AMOVD,
+		AMOVV,
+		AMOVVL,
+		AMOVVR:
+		sz = 8
+		ld = 1
+
+	case ADIV,
+		ADIVU,
+		AMUL,
+		AMULU,
+		AREM,
+		AREMU,
+		ADIVV,
+		ADIVVU,
+		AMULV,
+		AMULVU,
+		AREMV,
+		AREMVU:
+		s.set.cc = E_HILO
+		fallthrough
+	case AADD,
+		AADDU,
+		AADDV,
+		AADDVU,
+		AAND,
+		ANOR,
+		AOR,
+		ASGT,
+		ASGTU,
+		ASLL,
+		ASRA,
+		ASRL,
+		ASLLV,
+		ASRAV,
+		ASRLV,
+		ASUB,
+		ASUBU,
+		ASUBV,
+		ASUBVU,
+		AXOR,
+
+		AADDD,
+		AADDF,
+		AADDW,
+		ASUBD,
+		ASUBF,
+		ASUBW,
+		AMULF,
+		AMULD,
+		AMULW,
+		ADIVF,
+		ADIVD,
+		ADIVW:
+		if p.Reg == 0 {
+			if p.To.Type == obj.TYPE_REG {
+				p.Reg = p.To.Reg
+			}
+			//if(p->reg == NREG)
+			//	print("botch %P\n", p);
+		}
+	}
+
+	/*
+	 * flags based on 'to' field
+	 */
+	c := int(p.To.Class)
+	if c == 0 {
+		c = aclass(ctxt, &p.To) + 1
+		p.To.Class = int8(c)
+	}
+	c--
+	switch c {
+	default:
+		fmt.Printf("unknown class %d %v\n", c, p)
+
+	case C_ZCON,
+		C_SCON,
+		C_ADD0CON,
+		C_AND0CON,
+		C_ADDCON,
+		C_ANDCON,
+		C_UCON,
+		C_LCON,
+		C_NONE,
+		C_SBRA,
+		C_LBRA,
+		C_ADDR,
+		C_TEXTSIZE:
+		break
+
+	case C_HI,
+		C_LO:
+		s.set.cc |= E_HILO
+
+	case C_FCREG:
+		s.set.cc |= E_FCR
+
+	case C_MREG:
+		s.set.cc |= E_MCR
+
+	case C_ZOREG,
+		C_SOREG,
+		C_LOREG:
+		c = int(p.To.Reg)
+		s.used.ireg |= 1 << uint(c-REG_R0)
+		if ad != 0 {
+			break
+		}
+		s.size = uint8(sz)
+		s.soffset = regoff(ctxt, &p.To)
+
+		m := uint32(ANYMEM)
+		if c == REGSB {
+			m = E_MEMSB
+		}
+		if c == REGSP {
+			m = E_MEMSP
+		}
+
+		if ar != 0 {
+			s.used.cc |= m
+		} else {
+			s.set.cc |= m
+		}
+
+	case C_SACON,
+		C_LACON:
+		s.used.ireg |= 1 << (REGSP - REG_R0)
+
+	case C_SECON,
+		C_LECON:
+		s.used.ireg |= 1 << (REGSB - REG_R0)
+
+	case C_REG:
+		if ar != 0 {
+			s.used.ireg |= 1 << uint(p.To.Reg-REG_R0)
+		} else {
+			s.set.ireg |= 1 << uint(p.To.Reg-REG_R0)
+		}
+
+	case C_FREG:
+		if ar != 0 {
+			s.used.freg |= 1 << uint(p.To.Reg-REG_F0)
+		} else {
+			s.set.freg |= 1 << uint(p.To.Reg-REG_F0)
+		}
+		if ld != 0 && p.From.Type == obj.TYPE_REG {
+			p.Mark |= LOAD
+		}
+
+	case C_SAUTO,
+		C_LAUTO:
+		s.used.ireg |= 1 << (REGSP - REG_R0)
+		if ad != 0 {
+			break
+		}
+		s.size = uint8(sz)
+		s.soffset = regoff(ctxt, &p.To)
+
+		if ar != 0 {
+			s.used.cc |= E_MEMSP
+		} else {
+			s.set.cc |= E_MEMSP
+		}
+
+	case C_SEXT,
+		C_LEXT:
+		s.used.ireg |= 1 << (REGSB - REG_R0)
+		if ad != 0 {
+			break
+		}
+		s.size = uint8(sz)
+		s.soffset = regoff(ctxt, &p.To)
+
+		if ar != 0 {
+			s.used.cc |= E_MEMSB
+		} else {
+			s.set.cc |= E_MEMSB
+		}
+	}
+
+	/*
+	 * flags based on 'from' field
+	 */
+	c = int(p.From.Class)
+	if c == 0 {
+		c = aclass(ctxt, &p.From) + 1
+		p.From.Class = int8(c)
+	}
+	c--
+	switch c {
+	default:
+		fmt.Printf("unknown class %d %v\n", c, p)
+
+	case C_ZCON,
+		C_SCON,
+		C_ADD0CON,
+		C_AND0CON,
+		C_ADDCON,
+		C_ANDCON,
+		C_UCON,
+		C_LCON,
+		C_NONE,
+		C_SBRA,
+		C_LBRA,
+		C_ADDR,
+		C_TEXTSIZE:
+		break
+
+	case C_HI,
+		C_LO:
+		s.used.cc |= E_HILO
+
+	case C_FCREG:
+		s.used.cc |= E_FCR
+
+	case C_MREG:
+		s.used.cc |= E_MCR
+
+	case C_ZOREG,
+		C_SOREG,
+		C_LOREG:
+		c = int(p.From.Reg)
+		s.used.ireg |= 1 << uint(c-REG_R0)
+		if ld != 0 {
+			p.Mark |= LOAD
+		}
+		s.size = uint8(sz)
+		s.soffset = regoff(ctxt, &p.From)
+
+		m := uint32(ANYMEM)
+		if c == REGSB {
+			m = E_MEMSB
+		}
+		if c == REGSP {
+			m = E_MEMSP
+		}
+
+		s.used.cc |= m
+
+	case C_SACON,
+		C_LACON:
+		c = int(p.From.Reg)
+		if c == 0 {
+			c = REGSP
+		}
+		s.used.ireg |= 1 << uint(c-REG_R0)
+
+	case C_SECON,
+		C_LECON:
+		s.used.ireg |= 1 << (REGSB - REG_R0)
+
+	case C_REG:
+		s.used.ireg |= 1 << uint(p.From.Reg-REG_R0)
+
+	case C_FREG:
+		s.used.freg |= 1 << uint(p.From.Reg-REG_F0)
+		if ld != 0 && p.To.Type == obj.TYPE_REG {
+			p.Mark |= LOAD
+		}
+
+	case C_SAUTO,
+		C_LAUTO:
+		s.used.ireg |= 1 << (REGSP - REG_R0)
+		if ld != 0 {
+			p.Mark |= LOAD
+		}
+		if ad != 0 {
+			break
+		}
+		s.size = uint8(sz)
+		s.soffset = regoff(ctxt, &p.From)
+
+		s.used.cc |= E_MEMSP
+
+	case C_SEXT:
+	case C_LEXT:
+		s.used.ireg |= 1 << (REGSB - REG_R0)
+		if ld != 0 {
+			p.Mark |= LOAD
+		}
+		if ad != 0 {
+			break
+		}
+		s.size = uint8(sz)
+		s.soffset = regoff(ctxt, &p.From)
+
+		s.used.cc |= E_MEMSB
+	}
+
+	c = int(p.Reg)
+	if c != 0 {
+		if REG_F0 <= c && c <= REG_F31 {
+			s.used.freg |= 1 << uint(c-REG_F0)
+		} else {
+			s.used.ireg |= 1 << uint(c-REG_R0)
+		}
+	}
+	s.set.ireg &^= (1 << (REGZERO - REG_R0)) /* R0 cant be set */
+}
+
+/*
+ * test to see if 2 instrictions can be
+ * interchanged without changing semantics
+ */
+func depend(ctxt *obj.Link, sa, sb *Sch) bool {
+	if sa.set.ireg&(sb.set.ireg|sb.used.ireg) != 0 {
+		return true
+	}
+	if sb.set.ireg&sa.used.ireg != 0 {
+		return true
+	}
+
+	if sa.set.freg&(sb.set.freg|sb.used.freg) != 0 {
+		return true
+	}
+	if sb.set.freg&sa.used.freg != 0 {
+		return true
+	}
+
+	/*
+	 * special case.
+	 * loads from same address cannot pass.
+	 * this is for hardware fifo's and the like
+	 */
+	if sa.used.cc&sb.used.cc&E_MEM != 0 {
+		if sa.p.Reg == sb.p.Reg {
+			if regoff(ctxt, &sa.p.From) == regoff(ctxt, &sb.p.From) {
+				return true
+			}
+		}
+	}
+
+	x := (sa.set.cc & (sb.set.cc | sb.used.cc)) | (sb.set.cc & sa.used.cc)
+	if x != 0 {
+		/*
+		 * allow SB and SP to pass each other.
+		 * allow SB to pass SB iff doffsets are ok
+		 * anything else conflicts
+		 */
+		if x != E_MEMSP && x != E_MEMSB {
+			return true
+		}
+		x = sa.set.cc | sb.set.cc | sa.used.cc | sb.used.cc
+		if x&E_MEM != 0 {
+			return true
+		}
+		if offoverlap(sa, sb) {
+			return true
+		}
+	}
+
+	return false
+}
+
+func offoverlap(sa, sb *Sch) bool {
+	if sa.soffset < sb.soffset {
+		if sa.soffset+int32(sa.size) > sb.soffset {
+			return true
+		}
+		return false
+	}
+	if sb.soffset+int32(sb.size) > sa.soffset {
+		return true
+	}
+	return false
+}
+
+/*
+ * test 2 adjacent instructions
+ * and find out if inserted instructions
+ * are desired to prevent stalls.
+ */
+func conflict(sa, sb *Sch) bool {
+	if sa.set.ireg&sb.used.ireg != 0 {
+		return true
+	}
+	if sa.set.freg&sb.used.freg != 0 {
+		return true
+	}
+	if sa.set.cc&sb.used.cc != 0 {
+		return true
+	}
+	return false
+}
+
+func compound(ctxt *obj.Link, p *obj.Prog) bool {
+	o := oplook(ctxt, p)
+	if o.size != 4 {
+		return true
+	}
+	if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSB {
+		return true
+	}
+	return false
+}
+
+func follow(ctxt *obj.Link, s *obj.LSym) {
+	ctxt.Cursym = s
+
+	firstp := ctxt.NewProg()
+	lastp := firstp
+	xfol(ctxt, s.Text, &lastp)
+	lastp.Link = nil
+	s.Text = firstp.Link
+}
+
+func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
+	var q *obj.Prog
+	var r *obj.Prog
+	var a int
+	var i int
+
+loop:
+	if p == nil {
+		return
+	}
+	a = int(p.As)
+	if a == AJMP {
+		q = p.Pcond
+		if (p.Mark&NOSCHED != 0) || q != nil && (q.Mark&NOSCHED != 0) {
+			p.Mark |= FOLL
+			(*last).Link = p
+			*last = p
+			p = p.Link
+			xfol(ctxt, p, last)
+			p = q
+			if p != nil && p.Mark&FOLL == 0 {
+				goto loop
+			}
+			return
+		}
+
+		if q != nil {
+			p.Mark |= FOLL
+			p = q
+			if p.Mark&FOLL == 0 {
+				goto loop
+			}
+		}
+	}
+
+	if p.Mark&FOLL != 0 {
+		i = 0
+		q = p
+		for ; i < 4; i, q = i+1, q.Link {
+			if q == *last || (q.Mark&NOSCHED != 0) {
+				break
+			}
+			a = int(q.As)
+			if a == obj.ANOP {
+				i--
+				continue
+			}
+
+			if a == AJMP || a == ARET || a == ARFE {
+				goto copy
+			}
+			if q.Pcond == nil || (q.Pcond.Mark&FOLL != 0) {
+				continue
+			}
+			if a != ABEQ && a != ABNE {
+				continue
+			}
+
+		copy:
+			for {
+				r = ctxt.NewProg()
+				*r = *p
+				if r.Mark&FOLL == 0 {
+					fmt.Printf("cant happen 1\n")
+				}
+				r.Mark |= FOLL
+				if p != q {
+					p = p.Link
+					(*last).Link = r
+					*last = r
+					continue
+				}
+
+				(*last).Link = r
+				*last = r
+				if a == AJMP || a == ARET || a == ARFE {
+					return
+				}
+				r.As = ABNE
+				if a == ABNE {
+					r.As = ABEQ
+				}
+				r.Pcond = p.Link
+				r.Link = p.Pcond
+				if r.Link.Mark&FOLL == 0 {
+					xfol(ctxt, r.Link, last)
+				}
+				if r.Pcond.Mark&FOLL == 0 {
+					fmt.Printf("cant happen 2\n")
+				}
+				return
+			}
+		}
+
+		a = AJMP
+		q = ctxt.NewProg()
+		q.As = int16(a)
+		q.Lineno = p.Lineno
+		q.To.Type = obj.TYPE_BRANCH
+		q.To.Offset = p.Pc
+		q.Pcond = p
+		p = q
+	}
+
+	p.Mark |= FOLL
+	(*last).Link = p
+	*last = p
+	if a == AJMP || a == ARET || a == ARFE {
+		if p.Mark&NOSCHED != 0 {
+			p = p.Link
+			goto loop
+		}
+
+		return
+	}
+
+	if p.Pcond != nil {
+		if a != AJAL && p.Link != nil {
+			xfol(ctxt, p.Link, last)
+			p = p.Pcond
+			if p == nil || (p.Mark&FOLL != 0) {
+				return
+			}
+			goto loop
+		}
+	}
+
+	p = p.Link
+	goto loop
+}
+
+var Linkmips64 = obj.LinkArch{
+	ByteOrder:  binary.BigEndian,
+	Name:       "mips64",
+	Thechar:    '0',
+	Preprocess: preprocess,
+	Assemble:   span0,
+	Follow:     follow,
+	Progedit:   progedit,
+	Minlc:      4,
+	Ptrsize:    8,
+	Regsize:    8,
+}
+
+var Linkmips64le = obj.LinkArch{
+	ByteOrder:  binary.LittleEndian,
+	Name:       "mips64le",
+	Thechar:    '0',
+	Preprocess: preprocess,
+	Assemble:   span0,
+	Follow:     follow,
+	Progedit:   progedit,
+	Minlc:      4,
+	Ptrsize:    8,
+	Regsize:    8,
+}
diff --git a/src/cmd/internal/obj/obj.go b/src/cmd/internal/obj/obj.go
index af3290d..30ab549 100644
--- a/src/cmd/internal/obj/obj.go
+++ b/src/cmd/internal/obj/obj.go
@@ -74,15 +74,15 @@ func (h *LineHist) setFile(stk *LineStack, file string) {
 		abs = filepath.Join(h.Dir, file)
 	}
 
-	// Remove leading TrimPathPrefix, or else rewrite $GOROOT to $GOROOT_FINAL.
+	// Remove leading TrimPathPrefix, or else rewrite $GOROOT to literal $GOROOT.
 	if h.TrimPathPrefix != "" && hasPathPrefix(abs, h.TrimPathPrefix) {
 		if abs == h.TrimPathPrefix {
 			abs = ""
 		} else {
 			abs = abs[len(h.TrimPathPrefix)+1:]
 		}
-	} else if h.GOROOT_FINAL != "" && h.GOROOT_FINAL != h.GOROOT && hasPathPrefix(abs, h.GOROOT) {
-		abs = h.GOROOT_FINAL + abs[len(h.GOROOT):]
+	} else if hasPathPrefix(abs, h.GOROOT) {
+		abs = "$GOROOT" + abs[len(h.GOROOT):]
 	}
 	if abs == "" {
 		abs = "??"
diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go
index c5f4820..8d4a506 100644
--- a/src/cmd/internal/obj/objfile.go
+++ b/src/cmd/internal/obj/objfile.go
@@ -107,12 +107,15 @@ import (
 	"strings"
 )
 
-var outfile string
-
 // The Go and C compilers, and the assembler, call writeobj to write
 // out a Go object file.  The linker does not call this; the linker
 // does not write out object files.
 func Writeobjdirect(ctxt *Link, b *Biobuf) {
+	Flushplist(ctxt)
+	Writeobjfile(ctxt, b)
+}
+
+func Flushplist(ctxt *Link) {
 	var flag int
 	var s *LSym
 	var p *Prog
@@ -121,13 +124,11 @@ func Writeobjdirect(ctxt *Link, b *Biobuf) {
 
 	// Build list of symbols, and assign instructions to lists.
 	// Ignore ctxt->plist boundaries. There are no guarantees there,
-	// and the C compilers and assemblers just use one big list.
-	var text *LSym
-
+	// and the assemblers just use one big list.
 	var curtext *LSym
-	var data *LSym
+	var text *LSym
 	var etext *LSym
-	var edata *LSym
+
 	for pl := ctxt.Plist; pl != nil; pl = pl.Link {
 		for p = pl.Firstpc; p != nil; p = plink {
 			if ctxt.Debugasm != 0 && ctxt.Debugvlog != 0 {
@@ -176,10 +177,10 @@ func Writeobjdirect(ctxt *Link, b *Biobuf) {
 					log.Fatalf("symbol %s listed multiple times", s.Name)
 				}
 				s.Onlist = 1
-				if data == nil {
-					data = s
+				if ctxt.Data == nil {
+					ctxt.Data = s
 				} else {
-					edata.Next = s
+					ctxt.Edata.Next = s
 				}
 				s.Next = nil
 				s.Size = p.To.Offset
@@ -194,8 +195,10 @@ func Writeobjdirect(ctxt *Link, b *Biobuf) {
 					s.Type = SRODATA
 				} else if flag&NOPTR != 0 {
 					s.Type = SNOPTRBSS
+				} else if flag&TLSBSS != 0 {
+					s.Type = STLSBSS
 				}
-				edata = s
+				ctxt.Edata = s
 				continue
 			}
 
@@ -298,6 +301,17 @@ func Writeobjdirect(ctxt *Link, b *Biobuf) {
 		linkpcln(ctxt, s)
 	}
 
+	// Add to running list in ctxt.
+	if ctxt.Etext == nil {
+		ctxt.Text = text
+	} else {
+		ctxt.Etext.Next = text
+	}
+	ctxt.Etext = etext
+	ctxt.Plist = nil
+}
+
+func Writeobjfile(ctxt *Link, b *Biobuf) {
 	// Emit header.
 	Bputc(b, 0)
 
@@ -312,10 +326,10 @@ func Writeobjdirect(ctxt *Link, b *Biobuf) {
 	wrstring(b, "")
 
 	// Emit symbols.
-	for s := text; s != nil; s = s.Next {
+	for s := ctxt.Text; s != nil; s = s.Next {
 		writesym(ctxt, b, s)
 	}
-	for s := data; s != nil; s = s.Next {
+	for s := ctxt.Data; s != nil; s = s.Next {
 		writesym(ctxt, b, s)
 	}
 
diff --git a/src/cmd/internal/obj/ppc64/a.out.go b/src/cmd/internal/obj/ppc64/a.out.go
index 3028b6c..4f6cdcd 100644
--- a/src/cmd/internal/obj/ppc64/a.out.go
+++ b/src/cmd/internal/obj/ppc64/a.out.go
@@ -205,6 +205,7 @@ const (
 	C_DACON /* $n(REG) where int32 < n */
 	C_SBRA
 	C_LBRA
+	C_LBRAPIC
 	C_SAUTO
 	C_LAUTO
 	C_SEXT
@@ -220,6 +221,9 @@ const (
 	C_ANY
 	C_GOK
 	C_ADDR
+	C_GOTADDR
+	C_TLS_LE
+	C_TLS_IE
 	C_TEXTSIZE
 
 	C_NCLASS /* must be the last */
diff --git a/src/cmd/internal/obj/ppc64/anames9.go b/src/cmd/internal/obj/ppc64/anames9.go
index b48e516..d7140b1 100644
--- a/src/cmd/internal/obj/ppc64/anames9.go
+++ b/src/cmd/internal/obj/ppc64/anames9.go
@@ -35,6 +35,9 @@ var cnames9 = []string{
 	"ANY",
 	"GOK",
 	"ADDR",
+	"GOTADDR",
+	"TLS_LE",
+	"TLS_IE",
 	"TEXTSIZE",
 	"NCLASS",
 }
diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go
index f074d90..90224c3 100644
--- a/src/cmd/internal/obj/ppc64/asm9.go
+++ b/src/cmd/internal/obj/ppc64/asm9.go
@@ -59,342 +59,348 @@ type Optab struct {
 }
 
 var optab = []Optab{
-	Optab{obj.ATEXT, C_LEXT, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0},
-	Optab{obj.ATEXT, C_LEXT, C_NONE, C_LCON, C_TEXTSIZE, 0, 0, 0},
-	Optab{obj.ATEXT, C_ADDR, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0},
-	Optab{obj.ATEXT, C_ADDR, C_NONE, C_LCON, C_TEXTSIZE, 0, 0, 0},
+	{obj.ATEXT, C_LEXT, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0},
+	{obj.ATEXT, C_LEXT, C_NONE, C_LCON, C_TEXTSIZE, 0, 0, 0},
+	{obj.ATEXT, C_ADDR, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0},
+	{obj.ATEXT, C_ADDR, C_NONE, C_LCON, C_TEXTSIZE, 0, 0, 0},
 	/* move register */
-	Optab{AMOVD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0},
-	Optab{AMOVB, C_REG, C_NONE, C_NONE, C_REG, 12, 4, 0},
-	Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_REG, 13, 4, 0},
-	Optab{AMOVW, C_REG, C_NONE, C_NONE, C_REG, 12, 4, 0},
-	Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_REG, 13, 4, 0},
-	Optab{AADD, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0},
-	Optab{AADD, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
-	Optab{AADD, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
-	Optab{AADD, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
-	Optab{AADD, C_UCON, C_REG, C_NONE, C_REG, 20, 4, 0},
-	Optab{AADD, C_UCON, C_NONE, C_NONE, C_REG, 20, 4, 0},
-	Optab{AADD, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0},
-	Optab{AADD, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0},
-	Optab{AADDC, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0},
-	Optab{AADDC, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
-	Optab{AADDC, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
-	Optab{AADDC, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
-	Optab{AADDC, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0},
-	Optab{AADDC, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0},
-	Optab{AAND, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0}, /* logical, no literal */
-	Optab{AAND, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
-	Optab{AANDCC, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
-	Optab{AANDCC, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
-	Optab{AANDCC, C_ANDCON, C_NONE, C_NONE, C_REG, 58, 4, 0},
-	Optab{AANDCC, C_ANDCON, C_REG, C_NONE, C_REG, 58, 4, 0},
-	Optab{AANDCC, C_UCON, C_NONE, C_NONE, C_REG, 59, 4, 0},
-	Optab{AANDCC, C_UCON, C_REG, C_NONE, C_REG, 59, 4, 0},
-	Optab{AANDCC, C_LCON, C_NONE, C_NONE, C_REG, 23, 12, 0},
-	Optab{AANDCC, C_LCON, C_REG, C_NONE, C_REG, 23, 12, 0},
-	Optab{AMULLW, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0},
-	Optab{AMULLW, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
-	Optab{AMULLW, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
-	Optab{AMULLW, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
-	Optab{AMULLW, C_ANDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
-	Optab{AMULLW, C_ANDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
-	Optab{AMULLW, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0},
-	Optab{AMULLW, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0},
-	Optab{ASUBC, C_REG, C_REG, C_NONE, C_REG, 10, 4, 0},
-	Optab{ASUBC, C_REG, C_NONE, C_NONE, C_REG, 10, 4, 0},
-	Optab{ASUBC, C_REG, C_NONE, C_ADDCON, C_REG, 27, 4, 0},
-	Optab{ASUBC, C_REG, C_NONE, C_LCON, C_REG, 28, 12, 0},
-	Optab{AOR, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0}, /* logical, literal not cc (or/xor) */
-	Optab{AOR, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
-	Optab{AOR, C_ANDCON, C_NONE, C_NONE, C_REG, 58, 4, 0},
-	Optab{AOR, C_ANDCON, C_REG, C_NONE, C_REG, 58, 4, 0},
-	Optab{AOR, C_UCON, C_NONE, C_NONE, C_REG, 59, 4, 0},
-	Optab{AOR, C_UCON, C_REG, C_NONE, C_REG, 59, 4, 0},
-	Optab{AOR, C_LCON, C_NONE, C_NONE, C_REG, 23, 12, 0},
-	Optab{AOR, C_LCON, C_REG, C_NONE, C_REG, 23, 12, 0},
-	Optab{ADIVW, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0}, /* op r1[,r2],r3 */
-	Optab{ADIVW, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
-	Optab{ASUB, C_REG, C_REG, C_NONE, C_REG, 10, 4, 0}, /* op r2[,r1],r3 */
-	Optab{ASUB, C_REG, C_NONE, C_NONE, C_REG, 10, 4, 0},
-	Optab{ASLW, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
-	Optab{ASLW, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
-	Optab{ASLD, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
-	Optab{ASLD, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
-	Optab{ASLD, C_SCON, C_REG, C_NONE, C_REG, 25, 4, 0},
-	Optab{ASLD, C_SCON, C_NONE, C_NONE, C_REG, 25, 4, 0},
-	Optab{ASLW, C_SCON, C_REG, C_NONE, C_REG, 57, 4, 0},
-	Optab{ASLW, C_SCON, C_NONE, C_NONE, C_REG, 57, 4, 0},
-	Optab{ASRAW, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
-	Optab{ASRAW, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
-	Optab{ASRAW, C_SCON, C_REG, C_NONE, C_REG, 56, 4, 0},
-	Optab{ASRAW, C_SCON, C_NONE, C_NONE, C_REG, 56, 4, 0},
-	Optab{ASRAD, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
-	Optab{ASRAD, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
-	Optab{ASRAD, C_SCON, C_REG, C_NONE, C_REG, 56, 4, 0},
-	Optab{ASRAD, C_SCON, C_NONE, C_NONE, C_REG, 56, 4, 0},
-	Optab{ARLWMI, C_SCON, C_REG, C_LCON, C_REG, 62, 4, 0},
-	Optab{ARLWMI, C_REG, C_REG, C_LCON, C_REG, 63, 4, 0},
-	Optab{ARLDMI, C_SCON, C_REG, C_LCON, C_REG, 30, 4, 0},
-	Optab{ARLDC, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0},
-	Optab{ARLDCL, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0},
-	Optab{ARLDCL, C_REG, C_REG, C_LCON, C_REG, 14, 4, 0},
-	Optab{ARLDCL, C_REG, C_NONE, C_LCON, C_REG, 14, 4, 0},
-	Optab{AFADD, C_FREG, C_NONE, C_NONE, C_FREG, 2, 4, 0},
-	Optab{AFADD, C_FREG, C_REG, C_NONE, C_FREG, 2, 4, 0},
-	Optab{AFABS, C_FREG, C_NONE, C_NONE, C_FREG, 33, 4, 0},
-	Optab{AFABS, C_NONE, C_NONE, C_NONE, C_FREG, 33, 4, 0},
-	Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, 33, 4, 0},
-	Optab{AFMADD, C_FREG, C_REG, C_FREG, C_FREG, 34, 4, 0},
-	Optab{AFMUL, C_FREG, C_NONE, C_NONE, C_FREG, 32, 4, 0},
-	Optab{AFMUL, C_FREG, C_REG, C_NONE, C_FREG, 32, 4, 0},
+	{AMOVD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0},
+	{AMOVB, C_REG, C_NONE, C_NONE, C_REG, 12, 4, 0},
+	{AMOVBZ, C_REG, C_NONE, C_NONE, C_REG, 13, 4, 0},
+	{AMOVW, C_REG, C_NONE, C_NONE, C_REG, 12, 4, 0},
+	{AMOVWZ, C_REG, C_NONE, C_NONE, C_REG, 13, 4, 0},
+	{AADD, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0},
+	{AADD, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
+	{AADD, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
+	{AADD, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
+	{AADD, C_UCON, C_REG, C_NONE, C_REG, 20, 4, 0},
+	{AADD, C_UCON, C_NONE, C_NONE, C_REG, 20, 4, 0},
+	{AADD, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0},
+	{AADD, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0},
+	{AADDC, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0},
+	{AADDC, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
+	{AADDC, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
+	{AADDC, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
+	{AADDC, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0},
+	{AADDC, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0},
+	{AAND, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0}, /* logical, no literal */
+	{AAND, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
+	{AANDCC, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
+	{AANDCC, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
+	{AANDCC, C_ANDCON, C_NONE, C_NONE, C_REG, 58, 4, 0},
+	{AANDCC, C_ANDCON, C_REG, C_NONE, C_REG, 58, 4, 0},
+	{AANDCC, C_UCON, C_NONE, C_NONE, C_REG, 59, 4, 0},
+	{AANDCC, C_UCON, C_REG, C_NONE, C_REG, 59, 4, 0},
+	{AANDCC, C_LCON, C_NONE, C_NONE, C_REG, 23, 12, 0},
+	{AANDCC, C_LCON, C_REG, C_NONE, C_REG, 23, 12, 0},
+	{AMULLW, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0},
+	{AMULLW, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
+	{AMULLW, C_ADDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
+	{AMULLW, C_ADDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
+	{AMULLW, C_ANDCON, C_REG, C_NONE, C_REG, 4, 4, 0},
+	{AMULLW, C_ANDCON, C_NONE, C_NONE, C_REG, 4, 4, 0},
+	{AMULLW, C_LCON, C_REG, C_NONE, C_REG, 22, 12, 0},
+	{AMULLW, C_LCON, C_NONE, C_NONE, C_REG, 22, 12, 0},
+	{ASUBC, C_REG, C_REG, C_NONE, C_REG, 10, 4, 0},
+	{ASUBC, C_REG, C_NONE, C_NONE, C_REG, 10, 4, 0},
+	{ASUBC, C_REG, C_NONE, C_ADDCON, C_REG, 27, 4, 0},
+	{ASUBC, C_REG, C_NONE, C_LCON, C_REG, 28, 12, 0},
+	{AOR, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0}, /* logical, literal not cc (or/xor) */
+	{AOR, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
+	{AOR, C_ANDCON, C_NONE, C_NONE, C_REG, 58, 4, 0},
+	{AOR, C_ANDCON, C_REG, C_NONE, C_REG, 58, 4, 0},
+	{AOR, C_UCON, C_NONE, C_NONE, C_REG, 59, 4, 0},
+	{AOR, C_UCON, C_REG, C_NONE, C_REG, 59, 4, 0},
+	{AOR, C_LCON, C_NONE, C_NONE, C_REG, 23, 12, 0},
+	{AOR, C_LCON, C_REG, C_NONE, C_REG, 23, 12, 0},
+	{ADIVW, C_REG, C_REG, C_NONE, C_REG, 2, 4, 0}, /* op r1[,r2],r3 */
+	{ADIVW, C_REG, C_NONE, C_NONE, C_REG, 2, 4, 0},
+	{ASUB, C_REG, C_REG, C_NONE, C_REG, 10, 4, 0}, /* op r2[,r1],r3 */
+	{ASUB, C_REG, C_NONE, C_NONE, C_REG, 10, 4, 0},
+	{ASLW, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
+	{ASLW, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
+	{ASLD, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
+	{ASLD, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
+	{ASLD, C_SCON, C_REG, C_NONE, C_REG, 25, 4, 0},
+	{ASLD, C_SCON, C_NONE, C_NONE, C_REG, 25, 4, 0},
+	{ASLW, C_SCON, C_REG, C_NONE, C_REG, 57, 4, 0},
+	{ASLW, C_SCON, C_NONE, C_NONE, C_REG, 57, 4, 0},
+	{ASRAW, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
+	{ASRAW, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
+	{ASRAW, C_SCON, C_REG, C_NONE, C_REG, 56, 4, 0},
+	{ASRAW, C_SCON, C_NONE, C_NONE, C_REG, 56, 4, 0},
+	{ASRAD, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0},
+	{ASRAD, C_REG, C_REG, C_NONE, C_REG, 6, 4, 0},
+	{ASRAD, C_SCON, C_REG, C_NONE, C_REG, 56, 4, 0},
+	{ASRAD, C_SCON, C_NONE, C_NONE, C_REG, 56, 4, 0},
+	{ARLWMI, C_SCON, C_REG, C_LCON, C_REG, 62, 4, 0},
+	{ARLWMI, C_REG, C_REG, C_LCON, C_REG, 63, 4, 0},
+	{ARLDMI, C_SCON, C_REG, C_LCON, C_REG, 30, 4, 0},
+	{ARLDC, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0},
+	{ARLDCL, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0},
+	{ARLDCL, C_REG, C_REG, C_LCON, C_REG, 14, 4, 0},
+	{ARLDCL, C_REG, C_NONE, C_LCON, C_REG, 14, 4, 0},
+	{AFADD, C_FREG, C_NONE, C_NONE, C_FREG, 2, 4, 0},
+	{AFADD, C_FREG, C_REG, C_NONE, C_FREG, 2, 4, 0},
+	{AFABS, C_FREG, C_NONE, C_NONE, C_FREG, 33, 4, 0},
+	{AFABS, C_NONE, C_NONE, C_NONE, C_FREG, 33, 4, 0},
+	{AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, 33, 4, 0},
+	{AFMADD, C_FREG, C_REG, C_FREG, C_FREG, 34, 4, 0},
+	{AFMUL, C_FREG, C_NONE, C_NONE, C_FREG, 32, 4, 0},
+	{AFMUL, C_FREG, C_REG, C_NONE, C_FREG, 32, 4, 0},
 
 	/* store, short offset */
-	Optab{AMOVD, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
-	Optab{AMOVW, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
-	Optab{AMOVWZ, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
-	Optab{AMOVBZ, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
-	Optab{AMOVBZU, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
-	Optab{AMOVB, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
-	Optab{AMOVBU, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
-	Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
-	Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
-	Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
-	Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
-	Optab{AMOVB, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
-	Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
-	Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
-	Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
-	Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
-	Optab{AMOVB, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
-	Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
-	Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
-	Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
-	Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
-	Optab{AMOVBZU, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
-	Optab{AMOVB, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
-	Optab{AMOVBU, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+	{AMOVD, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
+	{AMOVW, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
+	{AMOVWZ, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
+	{AMOVBZ, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
+	{AMOVBZU, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
+	{AMOVB, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
+	{AMOVBU, C_REG, C_REG, C_NONE, C_ZOREG, 7, 4, REGZERO},
+	{AMOVD, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
+	{AMOVW, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
+	{AMOVWZ, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
+	{AMOVBZ, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
+	{AMOVB, C_REG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
+	{AMOVD, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
+	{AMOVW, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
+	{AMOVWZ, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
+	{AMOVBZ, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
+	{AMOVB, C_REG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
+	{AMOVD, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+	{AMOVW, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+	{AMOVWZ, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+	{AMOVBZ, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+	{AMOVBZU, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+	{AMOVB, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+	{AMOVBU, C_REG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
 
 	/* load, short offset */
-	Optab{AMOVD, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
-	Optab{AMOVW, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
-	Optab{AMOVWZ, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
-	Optab{AMOVBZ, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
-	Optab{AMOVBZU, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
-	Optab{AMOVB, C_ZOREG, C_REG, C_NONE, C_REG, 9, 8, REGZERO},
-	Optab{AMOVBU, C_ZOREG, C_REG, C_NONE, C_REG, 9, 8, REGZERO},
-	Optab{AMOVD, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
-	Optab{AMOVW, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
-	Optab{AMOVWZ, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
-	Optab{AMOVBZ, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
-	Optab{AMOVB, C_SEXT, C_NONE, C_NONE, C_REG, 9, 8, REGSB},
-	Optab{AMOVD, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
-	Optab{AMOVW, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
-	Optab{AMOVWZ, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
-	Optab{AMOVBZ, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
-	Optab{AMOVB, C_SAUTO, C_NONE, C_NONE, C_REG, 9, 8, REGSP},
-	Optab{AMOVD, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
-	Optab{AMOVW, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
-	Optab{AMOVWZ, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
-	Optab{AMOVBZ, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
-	Optab{AMOVBZU, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
-	Optab{AMOVB, C_SOREG, C_NONE, C_NONE, C_REG, 9, 8, REGZERO},
-	Optab{AMOVBU, C_SOREG, C_NONE, C_NONE, C_REG, 9, 8, REGZERO},
+	{AMOVD, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
+	{AMOVW, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
+	{AMOVWZ, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
+	{AMOVBZ, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
+	{AMOVBZU, C_ZOREG, C_REG, C_NONE, C_REG, 8, 4, REGZERO},
+	{AMOVB, C_ZOREG, C_REG, C_NONE, C_REG, 9, 8, REGZERO},
+	{AMOVBU, C_ZOREG, C_REG, C_NONE, C_REG, 9, 8, REGZERO},
+	{AMOVD, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
+	{AMOVW, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
+	{AMOVWZ, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
+	{AMOVBZ, C_SEXT, C_NONE, C_NONE, C_REG, 8, 4, REGSB},
+	{AMOVB, C_SEXT, C_NONE, C_NONE, C_REG, 9, 8, REGSB},
+	{AMOVD, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
+	{AMOVW, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
+	{AMOVWZ, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
+	{AMOVBZ, C_SAUTO, C_NONE, C_NONE, C_REG, 8, 4, REGSP},
+	{AMOVB, C_SAUTO, C_NONE, C_NONE, C_REG, 9, 8, REGSP},
+	{AMOVD, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
+	{AMOVW, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
+	{AMOVWZ, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
+	{AMOVBZ, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
+	{AMOVBZU, C_SOREG, C_NONE, C_NONE, C_REG, 8, 4, REGZERO},
+	{AMOVB, C_SOREG, C_NONE, C_NONE, C_REG, 9, 8, REGZERO},
+	{AMOVBU, C_SOREG, C_NONE, C_NONE, C_REG, 9, 8, REGZERO},
 
 	/* store, long offset */
-	Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
-	Optab{AMOVW, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
-	Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
-	Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
-	Optab{AMOVB, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
-	Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
-	Optab{AMOVW, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
-	Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
-	Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
-	Optab{AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
-	Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
-	Optab{AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
-	Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
-	Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
-	Optab{AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
-	Optab{AMOVD, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
-	Optab{AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
-	Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
-	Optab{AMOVBZ, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
-	Optab{AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
+	{AMOVD, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
+	{AMOVW, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
+	{AMOVWZ, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
+	{AMOVBZ, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
+	{AMOVB, C_REG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
+	{AMOVD, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
+	{AMOVW, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
+	{AMOVWZ, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
+	{AMOVBZ, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
+	{AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
+	{AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
+	{AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
+	{AMOVWZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
+	{AMOVBZ, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
+	{AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
+	{AMOVD, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
+	{AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
+	{AMOVWZ, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
+	{AMOVBZ, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
+	{AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
 
 	/* load, long offset */
-	Optab{AMOVD, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
-	Optab{AMOVW, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
-	Optab{AMOVWZ, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
-	Optab{AMOVBZ, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
-	Optab{AMOVB, C_LEXT, C_NONE, C_NONE, C_REG, 37, 12, REGSB},
-	Optab{AMOVD, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
-	Optab{AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
-	Optab{AMOVWZ, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
-	Optab{AMOVBZ, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
-	Optab{AMOVB, C_LAUTO, C_NONE, C_NONE, C_REG, 37, 12, REGSP},
-	Optab{AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
-	Optab{AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
-	Optab{AMOVWZ, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
-	Optab{AMOVBZ, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
-	Optab{AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 37, 12, REGZERO},
-	Optab{AMOVD, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
-	Optab{AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
-	Optab{AMOVWZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
-	Optab{AMOVBZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
-	Optab{AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, 76, 12, 0},
+	{AMOVD, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
+	{AMOVW, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
+	{AMOVWZ, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
+	{AMOVBZ, C_LEXT, C_NONE, C_NONE, C_REG, 36, 8, REGSB},
+	{AMOVB, C_LEXT, C_NONE, C_NONE, C_REG, 37, 12, REGSB},
+	{AMOVD, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
+	{AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
+	{AMOVWZ, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
+	{AMOVBZ, C_LAUTO, C_NONE, C_NONE, C_REG, 36, 8, REGSP},
+	{AMOVB, C_LAUTO, C_NONE, C_NONE, C_REG, 37, 12, REGSP},
+	{AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
+	{AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
+	{AMOVWZ, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
+	{AMOVBZ, C_LOREG, C_NONE, C_NONE, C_REG, 36, 8, REGZERO},
+	{AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 37, 12, REGZERO},
+	{AMOVD, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
+	{AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
+	{AMOVWZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
+	{AMOVBZ, C_ADDR, C_NONE, C_NONE, C_REG, 75, 8, 0},
+	{AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, 76, 12, 0},
+
+	{AMOVD, C_TLS_LE, C_NONE, C_NONE, C_REG, 79, 4, 0},
+	{AMOVD, C_TLS_IE, C_NONE, C_NONE, C_REG, 80, 8, 0},
+
+	{AMOVD, C_GOTADDR, C_NONE, C_NONE, C_REG, 81, 8, 0},
 
 	/* load constant */
-	Optab{AMOVD, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB},
-	Optab{AMOVD, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
-	Optab{AMOVD, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB},
-	Optab{AMOVD, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP},
-	Optab{AMOVD, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
-	Optab{AMOVW, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB}, /* TO DO: check */
-	Optab{AMOVW, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
-	Optab{AMOVW, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB},
-	Optab{AMOVW, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP},
-	Optab{AMOVW, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
-	Optab{AMOVWZ, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB}, /* TO DO: check */
-	Optab{AMOVWZ, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
-	Optab{AMOVWZ, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB},
-	Optab{AMOVWZ, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP},
-	Optab{AMOVWZ, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
+	{AMOVD, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB},
+	{AMOVD, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
+	{AMOVD, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB},
+	{AMOVD, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP},
+	{AMOVD, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
+	{AMOVW, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB}, /* TO DO: check */
+	{AMOVW, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
+	{AMOVW, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB},
+	{AMOVW, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP},
+	{AMOVW, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
+	{AMOVWZ, C_SECON, C_NONE, C_NONE, C_REG, 3, 4, REGSB}, /* TO DO: check */
+	{AMOVWZ, C_SACON, C_NONE, C_NONE, C_REG, 3, 4, REGSP},
+	{AMOVWZ, C_LECON, C_NONE, C_NONE, C_REG, 26, 8, REGSB},
+	{AMOVWZ, C_LACON, C_NONE, C_NONE, C_REG, 26, 8, REGSP},
+	{AMOVWZ, C_ADDCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
 
 	/* load unsigned/long constants (TO DO: check) */
-	Optab{AMOVD, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
-	Optab{AMOVD, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0},
-	Optab{AMOVW, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
-	Optab{AMOVW, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0},
-	Optab{AMOVWZ, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
-	Optab{AMOVWZ, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0},
-	Optab{AMOVHBR, C_ZOREG, C_REG, C_NONE, C_REG, 45, 4, 0},
-	Optab{AMOVHBR, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0},
-	Optab{AMOVHBR, C_REG, C_REG, C_NONE, C_ZOREG, 44, 4, 0},
-	Optab{AMOVHBR, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0},
-	Optab{ASYSCALL, C_NONE, C_NONE, C_NONE, C_NONE, 5, 4, 0},
-	Optab{ASYSCALL, C_REG, C_NONE, C_NONE, C_NONE, 77, 12, 0},
-	Optab{ASYSCALL, C_SCON, C_NONE, C_NONE, C_NONE, 77, 12, 0},
-	Optab{ABEQ, C_NONE, C_NONE, C_NONE, C_SBRA, 16, 4, 0},
-	Optab{ABEQ, C_CREG, C_NONE, C_NONE, C_SBRA, 16, 4, 0},
-	Optab{ABR, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0},
-	Optab{ABC, C_SCON, C_REG, C_NONE, C_SBRA, 16, 4, 0},
-	Optab{ABC, C_SCON, C_REG, C_NONE, C_LBRA, 17, 4, 0},
-	Optab{ABR, C_NONE, C_NONE, C_NONE, C_LR, 18, 4, 0},
-	Optab{ABR, C_NONE, C_NONE, C_NONE, C_CTR, 18, 4, 0},
-	Optab{ABR, C_REG, C_NONE, C_NONE, C_CTR, 18, 4, 0},
-	Optab{ABR, C_NONE, C_NONE, C_NONE, C_ZOREG, 15, 8, 0},
-	Optab{ABC, C_NONE, C_REG, C_NONE, C_LR, 18, 4, 0},
-	Optab{ABC, C_NONE, C_REG, C_NONE, C_CTR, 18, 4, 0},
-	Optab{ABC, C_SCON, C_REG, C_NONE, C_LR, 18, 4, 0},
-	Optab{ABC, C_SCON, C_REG, C_NONE, C_CTR, 18, 4, 0},
-	Optab{ABC, C_NONE, C_NONE, C_NONE, C_ZOREG, 15, 8, 0},
-	Optab{AFMOVD, C_SEXT, C_NONE, C_NONE, C_FREG, 8, 4, REGSB},
-	Optab{AFMOVD, C_SAUTO, C_NONE, C_NONE, C_FREG, 8, 4, REGSP},
-	Optab{AFMOVD, C_SOREG, C_NONE, C_NONE, C_FREG, 8, 4, REGZERO},
-	Optab{AFMOVD, C_LEXT, C_NONE, C_NONE, C_FREG, 36, 8, REGSB},
-	Optab{AFMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, 36, 8, REGSP},
-	Optab{AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 36, 8, REGZERO},
-	Optab{AFMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, 75, 8, 0},
-	Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
-	Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
-	Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
-	Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
-	Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
-	Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
-	Optab{AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
-	Optab{ASYNC, C_NONE, C_NONE, C_NONE, C_NONE, 46, 4, 0},
-	Optab{AWORD, C_LCON, C_NONE, C_NONE, C_NONE, 40, 4, 0},
-	Optab{ADWORD, C_LCON, C_NONE, C_NONE, C_NONE, 31, 8, 0},
-	Optab{ADWORD, C_DCON, C_NONE, C_NONE, C_NONE, 31, 8, 0},
-	Optab{AADDME, C_REG, C_NONE, C_NONE, C_REG, 47, 4, 0},
-	Optab{AEXTSB, C_REG, C_NONE, C_NONE, C_REG, 48, 4, 0},
-	Optab{AEXTSB, C_NONE, C_NONE, C_NONE, C_REG, 48, 4, 0},
-	Optab{ANEG, C_REG, C_NONE, C_NONE, C_REG, 47, 4, 0},
-	Optab{ANEG, C_NONE, C_NONE, C_NONE, C_REG, 47, 4, 0},
-	Optab{AREM, C_REG, C_NONE, C_NONE, C_REG, 50, 12, 0},
-	Optab{AREM, C_REG, C_REG, C_NONE, C_REG, 50, 12, 0},
-	Optab{AREMU, C_REG, C_NONE, C_NONE, C_REG, 50, 16, 0},
-	Optab{AREMU, C_REG, C_REG, C_NONE, C_REG, 50, 16, 0},
-	Optab{AREMD, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0},
-	Optab{AREMD, C_REG, C_REG, C_NONE, C_REG, 51, 12, 0},
-	Optab{AREMDU, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0},
-	Optab{AREMDU, C_REG, C_REG, C_NONE, C_REG, 51, 12, 0},
-	Optab{AMTFSB0, C_SCON, C_NONE, C_NONE, C_NONE, 52, 4, 0},
-	Optab{AMOVFL, C_FPSCR, C_NONE, C_NONE, C_FREG, 53, 4, 0},
-	Optab{AMOVFL, C_FREG, C_NONE, C_NONE, C_FPSCR, 64, 4, 0},
-	Optab{AMOVFL, C_FREG, C_NONE, C_LCON, C_FPSCR, 64, 4, 0},
-	Optab{AMOVFL, C_LCON, C_NONE, C_NONE, C_FPSCR, 65, 4, 0},
-	Optab{AMOVD, C_MSR, C_NONE, C_NONE, C_REG, 54, 4, 0},  /* mfmsr */
-	Optab{AMOVD, C_REG, C_NONE, C_NONE, C_MSR, 54, 4, 0},  /* mtmsrd */
-	Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_MSR, 54, 4, 0}, /* mtmsr */
+	{AMOVD, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
+	{AMOVD, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0},
+	{AMOVW, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
+	{AMOVW, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0},
+	{AMOVWZ, C_UCON, C_NONE, C_NONE, C_REG, 3, 4, REGZERO},
+	{AMOVWZ, C_LCON, C_NONE, C_NONE, C_REG, 19, 8, 0},
+	{AMOVHBR, C_ZOREG, C_REG, C_NONE, C_REG, 45, 4, 0},
+	{AMOVHBR, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0},
+	{AMOVHBR, C_REG, C_REG, C_NONE, C_ZOREG, 44, 4, 0},
+	{AMOVHBR, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0},
+	{ASYSCALL, C_NONE, C_NONE, C_NONE, C_NONE, 5, 4, 0},
+	{ASYSCALL, C_REG, C_NONE, C_NONE, C_NONE, 77, 12, 0},
+	{ASYSCALL, C_SCON, C_NONE, C_NONE, C_NONE, 77, 12, 0},
+	{ABEQ, C_NONE, C_NONE, C_NONE, C_SBRA, 16, 4, 0},
+	{ABEQ, C_CREG, C_NONE, C_NONE, C_SBRA, 16, 4, 0},
+	{ABR, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0},
+	{ABR, C_NONE, C_NONE, C_NONE, C_LBRAPIC, 11, 8, 0},
+	{ABC, C_SCON, C_REG, C_NONE, C_SBRA, 16, 4, 0},
+	{ABC, C_SCON, C_REG, C_NONE, C_LBRA, 17, 4, 0},
+	{ABR, C_NONE, C_NONE, C_NONE, C_LR, 18, 4, 0},
+	{ABR, C_NONE, C_NONE, C_NONE, C_CTR, 18, 4, 0},
+	{ABR, C_REG, C_NONE, C_NONE, C_CTR, 18, 4, 0},
+	{ABR, C_NONE, C_NONE, C_NONE, C_ZOREG, 15, 8, 0},
+	{ABC, C_NONE, C_REG, C_NONE, C_LR, 18, 4, 0},
+	{ABC, C_NONE, C_REG, C_NONE, C_CTR, 18, 4, 0},
+	{ABC, C_SCON, C_REG, C_NONE, C_LR, 18, 4, 0},
+	{ABC, C_SCON, C_REG, C_NONE, C_CTR, 18, 4, 0},
+	{ABC, C_NONE, C_NONE, C_NONE, C_ZOREG, 15, 8, 0},
+	{AFMOVD, C_SEXT, C_NONE, C_NONE, C_FREG, 8, 4, REGSB},
+	{AFMOVD, C_SAUTO, C_NONE, C_NONE, C_FREG, 8, 4, REGSP},
+	{AFMOVD, C_SOREG, C_NONE, C_NONE, C_FREG, 8, 4, REGZERO},
+	{AFMOVD, C_LEXT, C_NONE, C_NONE, C_FREG, 36, 8, REGSB},
+	{AFMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, 36, 8, REGSP},
+	{AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 36, 8, REGZERO},
+	{AFMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, 75, 8, 0},
+	{AFMOVD, C_FREG, C_NONE, C_NONE, C_SEXT, 7, 4, REGSB},
+	{AFMOVD, C_FREG, C_NONE, C_NONE, C_SAUTO, 7, 4, REGSP},
+	{AFMOVD, C_FREG, C_NONE, C_NONE, C_SOREG, 7, 4, REGZERO},
+	{AFMOVD, C_FREG, C_NONE, C_NONE, C_LEXT, 35, 8, REGSB},
+	{AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, 35, 8, REGSP},
+	{AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 35, 8, REGZERO},
+	{AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, 74, 8, 0},
+	{ASYNC, C_NONE, C_NONE, C_NONE, C_NONE, 46, 4, 0},
+	{AWORD, C_LCON, C_NONE, C_NONE, C_NONE, 40, 4, 0},
+	{ADWORD, C_LCON, C_NONE, C_NONE, C_NONE, 31, 8, 0},
+	{ADWORD, C_DCON, C_NONE, C_NONE, C_NONE, 31, 8, 0},
+	{AADDME, C_REG, C_NONE, C_NONE, C_REG, 47, 4, 0},
+	{AEXTSB, C_REG, C_NONE, C_NONE, C_REG, 48, 4, 0},
+	{AEXTSB, C_NONE, C_NONE, C_NONE, C_REG, 48, 4, 0},
+	{ANEG, C_REG, C_NONE, C_NONE, C_REG, 47, 4, 0},
+	{ANEG, C_NONE, C_NONE, C_NONE, C_REG, 47, 4, 0},
+	{AREM, C_REG, C_NONE, C_NONE, C_REG, 50, 12, 0},
+	{AREM, C_REG, C_REG, C_NONE, C_REG, 50, 12, 0},
+	{AREMU, C_REG, C_NONE, C_NONE, C_REG, 50, 16, 0},
+	{AREMU, C_REG, C_REG, C_NONE, C_REG, 50, 16, 0},
+	{AREMD, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0},
+	{AREMD, C_REG, C_REG, C_NONE, C_REG, 51, 12, 0},
+	{AREMDU, C_REG, C_NONE, C_NONE, C_REG, 51, 12, 0},
+	{AREMDU, C_REG, C_REG, C_NONE, C_REG, 51, 12, 0},
+	{AMTFSB0, C_SCON, C_NONE, C_NONE, C_NONE, 52, 4, 0},
+	{AMOVFL, C_FPSCR, C_NONE, C_NONE, C_FREG, 53, 4, 0},
+	{AMOVFL, C_FREG, C_NONE, C_NONE, C_FPSCR, 64, 4, 0},
+	{AMOVFL, C_FREG, C_NONE, C_LCON, C_FPSCR, 64, 4, 0},
+	{AMOVFL, C_LCON, C_NONE, C_NONE, C_FPSCR, 65, 4, 0},
+	{AMOVD, C_MSR, C_NONE, C_NONE, C_REG, 54, 4, 0},  /* mfmsr */
+	{AMOVD, C_REG, C_NONE, C_NONE, C_MSR, 54, 4, 0},  /* mtmsrd */
+	{AMOVWZ, C_REG, C_NONE, C_NONE, C_MSR, 54, 4, 0}, /* mtmsr */
 
 	/* 64-bit special registers */
-	Optab{AMOVD, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0},
-	Optab{AMOVD, C_REG, C_NONE, C_NONE, C_LR, 66, 4, 0},
-	Optab{AMOVD, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0},
-	Optab{AMOVD, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0},
-	Optab{AMOVD, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0},
-	Optab{AMOVD, C_LR, C_NONE, C_NONE, C_REG, 66, 4, 0},
-	Optab{AMOVD, C_CTR, C_NONE, C_NONE, C_REG, 66, 4, 0},
-	Optab{AMOVD, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0},
+	{AMOVD, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0},
+	{AMOVD, C_REG, C_NONE, C_NONE, C_LR, 66, 4, 0},
+	{AMOVD, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0},
+	{AMOVD, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0},
+	{AMOVD, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0},
+	{AMOVD, C_LR, C_NONE, C_NONE, C_REG, 66, 4, 0},
+	{AMOVD, C_CTR, C_NONE, C_NONE, C_REG, 66, 4, 0},
+	{AMOVD, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0},
 
 	/* 32-bit special registers (gloss over sign-extension or not?) */
-	Optab{AMOVW, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0},
-	Optab{AMOVW, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0},
-	Optab{AMOVW, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0},
-	Optab{AMOVW, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0},
-	Optab{AMOVW, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0},
-	Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0},
-	Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0},
-	Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0},
-	Optab{AMOVWZ, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0},
-	Optab{AMOVWZ, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0},
-	Optab{AMOVFL, C_FPSCR, C_NONE, C_NONE, C_CREG, 73, 4, 0},
-	Optab{AMOVFL, C_CREG, C_NONE, C_NONE, C_CREG, 67, 4, 0},
-	Optab{AMOVW, C_CREG, C_NONE, C_NONE, C_REG, 68, 4, 0},
-	Optab{AMOVWZ, C_CREG, C_NONE, C_NONE, C_REG, 68, 4, 0},
-	Optab{AMOVFL, C_REG, C_NONE, C_LCON, C_CREG, 69, 4, 0},
-	Optab{AMOVFL, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0},
-	Optab{AMOVW, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0},
-	Optab{AMOVWZ, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0},
-	Optab{ACMP, C_REG, C_NONE, C_NONE, C_REG, 70, 4, 0},
-	Optab{ACMP, C_REG, C_REG, C_NONE, C_REG, 70, 4, 0},
-	Optab{ACMP, C_REG, C_NONE, C_NONE, C_ADDCON, 71, 4, 0},
-	Optab{ACMP, C_REG, C_REG, C_NONE, C_ADDCON, 71, 4, 0},
-	Optab{ACMPU, C_REG, C_NONE, C_NONE, C_REG, 70, 4, 0},
-	Optab{ACMPU, C_REG, C_REG, C_NONE, C_REG, 70, 4, 0},
-	Optab{ACMPU, C_REG, C_NONE, C_NONE, C_ANDCON, 71, 4, 0},
-	Optab{ACMPU, C_REG, C_REG, C_NONE, C_ANDCON, 71, 4, 0},
-	Optab{AFCMPO, C_FREG, C_NONE, C_NONE, C_FREG, 70, 4, 0},
-	Optab{AFCMPO, C_FREG, C_REG, C_NONE, C_FREG, 70, 4, 0},
-	Optab{ATW, C_LCON, C_REG, C_NONE, C_REG, 60, 4, 0},
-	Optab{ATW, C_LCON, C_REG, C_NONE, C_ADDCON, 61, 4, 0},
-	Optab{ADCBF, C_ZOREG, C_NONE, C_NONE, C_NONE, 43, 4, 0},
-	Optab{ADCBF, C_ZOREG, C_REG, C_NONE, C_NONE, 43, 4, 0},
-	Optab{AECOWX, C_REG, C_REG, C_NONE, C_ZOREG, 44, 4, 0},
-	Optab{AECIWX, C_ZOREG, C_REG, C_NONE, C_REG, 45, 4, 0},
-	Optab{AECOWX, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0},
-	Optab{AECIWX, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0},
-	Optab{AEIEIO, C_NONE, C_NONE, C_NONE, C_NONE, 46, 4, 0},
-	Optab{ATLBIE, C_REG, C_NONE, C_NONE, C_NONE, 49, 4, 0},
-	Optab{ATLBIE, C_SCON, C_NONE, C_NONE, C_REG, 49, 4, 0},
-	Optab{ASLBMFEE, C_REG, C_NONE, C_NONE, C_REG, 55, 4, 0},
-	Optab{ASLBMTE, C_REG, C_NONE, C_NONE, C_REG, 55, 4, 0},
-	Optab{ASTSW, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0},
-	Optab{ASTSW, C_REG, C_NONE, C_LCON, C_ZOREG, 41, 4, 0},
-	Optab{ALSW, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0},
-	Optab{ALSW, C_ZOREG, C_NONE, C_LCON, C_REG, 42, 4, 0},
-	Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 78, 4, 0},
-	Optab{obj.AUSEFIELD, C_ADDR, C_NONE, C_NONE, C_NONE, 0, 0, 0},
-	Optab{obj.APCDATA, C_LCON, C_NONE, C_NONE, C_LCON, 0, 0, 0},
-	Optab{obj.AFUNCDATA, C_SCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0},
-	Optab{obj.ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0},
-	Optab{obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as ABR/ABL
-	Optab{obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as ABR/ABL
-
-	Optab{obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0},
+	{AMOVW, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0},
+	{AMOVW, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0},
+	{AMOVW, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0},
+	{AMOVW, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0},
+	{AMOVW, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0},
+	{AMOVWZ, C_REG, C_NONE, C_NONE, C_SPR, 66, 4, 0},
+	{AMOVWZ, C_REG, C_NONE, C_NONE, C_CTR, 66, 4, 0},
+	{AMOVWZ, C_REG, C_NONE, C_NONE, C_XER, 66, 4, 0},
+	{AMOVWZ, C_SPR, C_NONE, C_NONE, C_REG, 66, 4, 0},
+	{AMOVWZ, C_XER, C_NONE, C_NONE, C_REG, 66, 4, 0},
+	{AMOVFL, C_FPSCR, C_NONE, C_NONE, C_CREG, 73, 4, 0},
+	{AMOVFL, C_CREG, C_NONE, C_NONE, C_CREG, 67, 4, 0},
+	{AMOVW, C_CREG, C_NONE, C_NONE, C_REG, 68, 4, 0},
+	{AMOVWZ, C_CREG, C_NONE, C_NONE, C_REG, 68, 4, 0},
+	{AMOVFL, C_REG, C_NONE, C_LCON, C_CREG, 69, 4, 0},
+	{AMOVFL, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0},
+	{AMOVW, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0},
+	{AMOVWZ, C_REG, C_NONE, C_NONE, C_CREG, 69, 4, 0},
+	{ACMP, C_REG, C_NONE, C_NONE, C_REG, 70, 4, 0},
+	{ACMP, C_REG, C_REG, C_NONE, C_REG, 70, 4, 0},
+	{ACMP, C_REG, C_NONE, C_NONE, C_ADDCON, 71, 4, 0},
+	{ACMP, C_REG, C_REG, C_NONE, C_ADDCON, 71, 4, 0},
+	{ACMPU, C_REG, C_NONE, C_NONE, C_REG, 70, 4, 0},
+	{ACMPU, C_REG, C_REG, C_NONE, C_REG, 70, 4, 0},
+	{ACMPU, C_REG, C_NONE, C_NONE, C_ANDCON, 71, 4, 0},
+	{ACMPU, C_REG, C_REG, C_NONE, C_ANDCON, 71, 4, 0},
+	{AFCMPO, C_FREG, C_NONE, C_NONE, C_FREG, 70, 4, 0},
+	{AFCMPO, C_FREG, C_REG, C_NONE, C_FREG, 70, 4, 0},
+	{ATW, C_LCON, C_REG, C_NONE, C_REG, 60, 4, 0},
+	{ATW, C_LCON, C_REG, C_NONE, C_ADDCON, 61, 4, 0},
+	{ADCBF, C_ZOREG, C_NONE, C_NONE, C_NONE, 43, 4, 0},
+	{ADCBF, C_ZOREG, C_REG, C_NONE, C_NONE, 43, 4, 0},
+	{AECOWX, C_REG, C_REG, C_NONE, C_ZOREG, 44, 4, 0},
+	{AECIWX, C_ZOREG, C_REG, C_NONE, C_REG, 45, 4, 0},
+	{AECOWX, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0},
+	{AECIWX, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0},
+	{AEIEIO, C_NONE, C_NONE, C_NONE, C_NONE, 46, 4, 0},
+	{ATLBIE, C_REG, C_NONE, C_NONE, C_NONE, 49, 4, 0},
+	{ATLBIE, C_SCON, C_NONE, C_NONE, C_REG, 49, 4, 0},
+	{ASLBMFEE, C_REG, C_NONE, C_NONE, C_REG, 55, 4, 0},
+	{ASLBMTE, C_REG, C_NONE, C_NONE, C_REG, 55, 4, 0},
+	{ASTSW, C_REG, C_NONE, C_NONE, C_ZOREG, 44, 4, 0},
+	{ASTSW, C_REG, C_NONE, C_LCON, C_ZOREG, 41, 4, 0},
+	{ALSW, C_ZOREG, C_NONE, C_NONE, C_REG, 45, 4, 0},
+	{ALSW, C_ZOREG, C_NONE, C_LCON, C_REG, 42, 4, 0},
+	{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 78, 4, 0},
+	{obj.AUSEFIELD, C_ADDR, C_NONE, C_NONE, C_NONE, 0, 0, 0},
+	{obj.APCDATA, C_LCON, C_NONE, C_NONE, C_LCON, 0, 0, 0},
+	{obj.AFUNCDATA, C_SCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0},
+	{obj.ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0},
+	{obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as ABR/ABL
+	{obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_LBRA, 11, 4, 0}, // same as ABR/ABL
+
+	{obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0},
 }
 
 type Oprang struct {
@@ -412,7 +418,7 @@ func span9(ctxt *obj.Link, cursym *obj.LSym) {
 		return
 	}
 	ctxt.Cursym = cursym
-	ctxt.Autosize = int32(p.To.Offset + 8)
+	ctxt.Autosize = int32(p.To.Offset)
 
 	if oprange[AANDN&obj.AMask].start == nil {
 		buildop(ctxt)
@@ -429,7 +435,7 @@ func span9(ctxt *obj.Link, cursym *obj.LSym) {
 		o = oplook(ctxt, p)
 		m = int(o.size)
 		if m == 0 {
-			if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA {
+			if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.AUSEFIELD {
 				ctxt.Diag("zero-width instruction\n%v", p)
 			}
 			continue
@@ -486,7 +492,7 @@ func span9(ctxt *obj.Link, cursym *obj.LSym) {
 
 			m = int(o.size)
 			if m == 0 {
-				if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA {
+				if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.AUSEFIELD {
 					ctxt.Diag("zero-width instruction\n%v", p)
 				}
 				continue
@@ -504,9 +510,6 @@ func span9(ctxt *obj.Link, cursym *obj.LSym) {
 	/*
 	 * lay out the code, emitting code and data relocations.
 	 */
-	if ctxt.Tlsg == nil {
-		ctxt.Tlsg = obj.Linklookup(ctxt, "runtime.tlsg", 0)
-	}
 
 	obj.Symgrow(ctxt, cursym, cursym.Size)
 
@@ -586,10 +589,20 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
 			}
 			ctxt.Instoffset = a.Offset
 			if a.Sym != nil { // use relocation
+				if a.Sym.Type == obj.STLSBSS {
+					if ctxt.Flag_shared != 0 {
+						return C_TLS_IE
+					} else {
+						return C_TLS_LE
+					}
+				}
 				return C_ADDR
 			}
 			return C_LEXT
 
+		case obj.NAME_GOTREF:
+			return C_GOTADDR
+
 		case obj.NAME_AUTO:
 			ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset
 			if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
@@ -598,7 +611,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
 			return C_LAUTO
 
 		case obj.NAME_PARAM:
-			ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8
+			ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + ctxt.FixedFrameSize()
 			if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
 				return C_SAUTO
 			}
@@ -661,7 +674,7 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
 			return C_LACON
 
 		case obj.NAME_PARAM:
-			ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + 8
+			ctxt.Instoffset = int64(ctxt.Autosize) + a.Offset + ctxt.FixedFrameSize()
 			if ctxt.Instoffset >= -BIG && ctxt.Instoffset < BIG {
 				return C_SACON
 			}
@@ -702,6 +715,9 @@ func aclass(ctxt *obj.Link, a *obj.Addr) int {
 		return C_DCON
 
 	case obj.TYPE_BRANCH:
+		if a.Sym != nil && ctxt.Flag_dynlink {
+			return C_LBRAPIC
+		}
 		return C_SBRA
 	}
 
@@ -1375,14 +1391,73 @@ func oclass(a *obj.Addr) int {
 	return int(a.Class) - 1
 }
 
-// add R_ADDRPOWER relocation to symbol s for the two instructions o1 and o2.
-func addaddrreloc(ctxt *obj.Link, s *obj.LSym, o1 *uint32, o2 *uint32) {
+const (
+	D_FORM = iota
+	DS_FORM
+)
+
+// opform returns the form (D_FORM or DS_FORM) of an instruction. Used to decide on
+// which relocation to use with a load or store and only supports the needed
+// instructions.
+func opform(ctxt *obj.Link, insn int32) int {
+	switch uint32(insn) {
+	default:
+		ctxt.Diag("bad insn in loadform: %x", insn)
+	case OPVCC(58, 0, 0, 0), // ld
+		OPVCC(58, 0, 0, 0) | 1<<1, // lwa
+		OPVCC(62, 0, 0, 0):        // std
+		return DS_FORM
+	case OP_ADDI, // add
+		OPVCC(32, 0, 0, 0), // lwz
+		OPVCC(42, 0, 0, 0), // lha
+		OPVCC(40, 0, 0, 0), // lhz
+		OPVCC(34, 0, 0, 0), // lbz
+		OPVCC(50, 0, 0, 0), // lfd
+		OPVCC(48, 0, 0, 0), // lfs
+		OPVCC(36, 0, 0, 0), // stw
+		OPVCC(44, 0, 0, 0), // sth
+		OPVCC(38, 0, 0, 0), // stb
+		OPVCC(54, 0, 0, 0), // stfd
+		OPVCC(52, 0, 0, 0): // stfs
+		return D_FORM
+	}
+	return 0
+}
+
+// Encode instructions and create relocation for accessing s+d according to the
+// instruction op with source or destination (as appropriate) register reg.
+func symbolAccess(ctxt *obj.Link, s *obj.LSym, d int64, reg int16, op int32) (o1, o2 uint32) {
+	var base uint32
+	form := opform(ctxt, op)
+	if ctxt.Flag_shared != 0 {
+		base = REG_R2
+	} else {
+		base = REG_R0
+	}
+	o1 = AOP_IRR(OP_ADDIS, REGTMP, base, 0)
+	o2 = AOP_IRR(uint32(op), uint32(reg), REGTMP, 0)
 	rel := obj.Addrel(ctxt.Cursym)
 	rel.Off = int32(ctxt.Pc)
 	rel.Siz = 8
 	rel.Sym = s
-	rel.Add = int64(uint64(*o1)<<32 | uint64(uint32(*o2)))
-	rel.Type = obj.R_ADDRPOWER
+	rel.Add = d
+	if ctxt.Flag_shared != 0 {
+		switch form {
+		case D_FORM:
+			rel.Type = obj.R_ADDRPOWER_TOCREL
+		case DS_FORM:
+			rel.Type = obj.R_ADDRPOWER_TOCREL_DS
+		}
+
+	} else {
+		switch form {
+		case D_FORM:
+			rel.Type = obj.R_ADDRPOWER
+		case DS_FORM:
+			rel.Type = obj.R_ADDRPOWER_DS
+		}
+	}
+	return
 }
 
 /*
@@ -1587,6 +1662,18 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
 			if v != 0 {
 				ctxt.Diag("illegal indexed instruction\n%v", p)
 			}
+			if ctxt.Flag_shared != 0 && r == REG_R13 {
+				rel := obj.Addrel(ctxt.Cursym)
+				rel.Off = int32(ctxt.Pc)
+				rel.Siz = 4
+				// This (and the matching part in the load case
+				// below) are the only places in the ppc64 toolchain
+				// that knows the name of the tls variable. Possibly
+				// we could add some assembly syntax so that the name
+				// of the variable does not have to be assumed.
+				rel.Sym = obj.Linklookup(ctxt, "runtime.tls_g", 0)
+				rel.Type = obj.R_POWER_TLS
+			}
 			o1 = AOP_RRR(uint32(opstorex(ctxt, int(p.As))), uint32(p.From.Reg), uint32(p.To.Index), uint32(r))
 		} else {
 			if int32(int16(v)) != v {
@@ -1606,6 +1693,13 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
 			if v != 0 {
 				ctxt.Diag("illegal indexed instruction\n%v", p)
 			}
+			if ctxt.Flag_shared != 0 && r == REG_R13 {
+				rel := obj.Addrel(ctxt.Cursym)
+				rel.Off = int32(ctxt.Pc)
+				rel.Siz = 4
+				rel.Sym = obj.Linklookup(ctxt, "runtime.tls_g", 0)
+				rel.Type = obj.R_POWER_TLS
+			}
 			o1 = AOP_RRR(uint32(oploadx(ctxt, int(p.As))), uint32(p.To.Reg), uint32(p.From.Index), uint32(r))
 		} else {
 			if int32(int16(v)) != v {
@@ -1669,6 +1763,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
 			rel.Add = int64(v)
 			rel.Type = obj.R_CALLPOWER
 		}
+		o2 = 0x60000000 // nop, sometimes overwritten by ld r2, 24(r1) when dynamic linking
 
 	case 12: /* movb r,r (extsb); movw r,r (extsw) */
 		if p.To.Reg == REGZERO && p.From.Type == obj.TYPE_CONST {
@@ -1808,9 +1903,7 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
 			o1 = loadu32(int(p.To.Reg), d)
 			o2 = LOP_IRR(OP_ORI, uint32(p.To.Reg), uint32(p.To.Reg), uint32(int32(d)))
 		} else {
-			o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(int32(d))))
-			o2 = AOP_IRR(OP_ADDI, uint32(p.To.Reg), REGTMP, uint32(d))
-			addaddrreloc(ctxt, p.From.Sym, &o1, &o2)
+			o1, o2 = symbolAccess(ctxt, p.From.Sym, d, p.To.Reg, OP_ADDI)
 		}
 
 	//if(dlm) reloc(&p->from, p->pc, 0);
@@ -2372,33 +2465,62 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
 		o1 = 0 /* "An instruction consisting entirely of binary 0s is guaranteed
 		   always to be an illegal instruction."  */
 
-		/* relocation operations */
+	/* relocation operations */
 	case 74:
-		v := regoff(ctxt, &p.To)
-
-		o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(v)))
-		o2 = AOP_IRR(uint32(opstore(ctxt, int(p.As))), uint32(p.From.Reg), REGTMP, uint32(v))
-		addaddrreloc(ctxt, p.To.Sym, &o1, &o2)
+		v := vregoff(ctxt, &p.To)
+		o1, o2 = symbolAccess(ctxt, p.To.Sym, v, p.From.Reg, opstore(ctxt, int(p.As)))
 
 	//if(dlm) reloc(&p->to, p->pc, 1);
 
 	case 75:
-		v := regoff(ctxt, &p.From)
-		o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(v)))
-		o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v))
-		addaddrreloc(ctxt, p.From.Sym, &o1, &o2)
+		v := vregoff(ctxt, &p.From)
+		o1, o2 = symbolAccess(ctxt, p.From.Sym, v, p.To.Reg, opload(ctxt, int(p.As)))
 
 	//if(dlm) reloc(&p->from, p->pc, 1);
 
 	case 76:
-		v := regoff(ctxt, &p.From)
-		o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, uint32(high16adjusted(v)))
-		o2 = AOP_IRR(uint32(opload(ctxt, int(p.As))), uint32(p.To.Reg), REGTMP, uint32(v))
-		addaddrreloc(ctxt, p.From.Sym, &o1, &o2)
+		v := vregoff(ctxt, &p.From)
+		o1, o2 = symbolAccess(ctxt, p.From.Sym, v, p.To.Reg, opload(ctxt, int(p.As)))
 		o3 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
 
 		//if(dlm) reloc(&p->from, p->pc, 1);
 
+	case 79:
+		if p.From.Offset != 0 {
+			ctxt.Diag("invalid offset against tls var %v", p)
+		}
+		o1 = AOP_IRR(OP_ADDI, uint32(p.To.Reg), REGZERO, 0)
+		rel := obj.Addrel(ctxt.Cursym)
+		rel.Off = int32(ctxt.Pc)
+		rel.Siz = 4
+		rel.Sym = p.From.Sym
+		rel.Type = obj.R_POWER_TLS_LE
+
+	case 80:
+		if p.From.Offset != 0 {
+			ctxt.Diag("invalid offset against tls var %v", p)
+		}
+		o1 = AOP_IRR(OP_ADDIS, uint32(p.To.Reg), REG_R2, 0)
+		o2 = AOP_IRR(uint32(opload(ctxt, AMOVD)), uint32(p.To.Reg), uint32(p.To.Reg), 0)
+		rel := obj.Addrel(ctxt.Cursym)
+		rel.Off = int32(ctxt.Pc)
+		rel.Siz = 8
+		rel.Sym = p.From.Sym
+		rel.Type = obj.R_POWER_TLS_IE
+
+	case 81:
+		v := vregoff(ctxt, &p.To)
+		if v != 0 {
+			ctxt.Diag("invalid offset against GOT slot %v", p)
+		}
+
+		o1 = AOP_IRR(OP_ADDIS, uint32(p.To.Reg), REG_R2, 0)
+		o2 = AOP_IRR(uint32(opload(ctxt, AMOVD)), uint32(p.To.Reg), uint32(p.To.Reg), 0)
+		rel := obj.Addrel(ctxt.Cursym)
+		rel.Off = int32(ctxt.Pc)
+		rel.Siz = 8
+		rel.Sym = p.From.Sym
+		rel.Type = obj.R_ADDRPOWER_GOT
 	}
 
 	out[0] = o1
diff --git a/src/cmd/internal/obj/ppc64/obj9.go b/src/cmd/internal/obj/ppc64/obj9.go
index 1eddc6f..11be4d7 100644
--- a/src/cmd/internal/obj/ppc64/obj9.go
+++ b/src/cmd/internal/obj/ppc64/obj9.go
@@ -63,6 +63,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
 			s.Size = 4
 			p.From.Type = obj.TYPE_MEM
 			p.From.Sym = s
+			p.From.Sym.Local = true
 			p.From.Name = obj.NAME_EXTERN
 			p.From.Offset = 0
 		}
@@ -75,6 +76,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
 			s.Size = 8
 			p.From.Type = obj.TYPE_MEM
 			p.From.Sym = s
+			p.From.Sym.Local = true
 			p.From.Name = obj.NAME_EXTERN
 			p.From.Offset = 0
 		}
@@ -87,6 +89,7 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
 			s.Size = 8
 			p.From.Type = obj.TYPE_MEM
 			p.From.Sym = s
+			p.From.Sym.Local = true
 			p.From.Name = obj.NAME_EXTERN
 			p.From.Offset = 0
 		}
@@ -112,6 +115,130 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
 			p.As = AADD
 		}
 	}
+	if ctxt.Flag_dynlink {
+		rewriteToUseGot(ctxt, p)
+	}
+}
+
+// Rewrite p, if necessary, to access global data via the global offset table.
+func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog) {
+	if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
+		//     ADUFFxxx $offset
+		// becomes
+		//     MOVD runtime.duffxxx at GOT, R12
+		//     ADD $offset, R12
+		//     MOVD R12, CTR
+		//     BL (CTR)
+		var sym *obj.LSym
+		if p.As == obj.ADUFFZERO {
+			sym = obj.Linklookup(ctxt, "runtime.duffzero", 0)
+		} else {
+			sym = obj.Linklookup(ctxt, "runtime.duffcopy", 0)
+		}
+		offset := p.To.Offset
+		p.As = AMOVD
+		p.From.Type = obj.TYPE_MEM
+		p.From.Name = obj.NAME_GOTREF
+		p.From.Sym = sym
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = REG_R12
+		p.To.Name = obj.NAME_NONE
+		p.To.Offset = 0
+		p.To.Sym = nil
+		p1 := obj.Appendp(ctxt, p)
+		p1.As = AADD
+		p1.From.Type = obj.TYPE_CONST
+		p1.From.Offset = offset
+		p1.To.Type = obj.TYPE_REG
+		p1.To.Reg = REG_R12
+		p2 := obj.Appendp(ctxt, p1)
+		p2.As = AMOVD
+		p2.From.Type = obj.TYPE_REG
+		p2.From.Reg = REG_R12
+		p2.To.Type = obj.TYPE_REG
+		p2.To.Reg = REG_CTR
+		p3 := obj.Appendp(ctxt, p2)
+		p3.As = obj.ACALL
+		p3.From.Type = obj.TYPE_REG
+		p3.From.Reg = REG_R12
+		p3.To.Type = obj.TYPE_REG
+		p3.To.Reg = REG_CTR
+	}
+
+	// We only care about global data: NAME_EXTERN means a global
+	// symbol in the Go sense, and p.Sym.Local is true for a few
+	// internally defined symbols.
+	if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
+		// MOVD $sym, Rx becomes MOVD sym at GOT, Rx
+		// MOVD $sym+<off>, Rx becomes MOVD sym at GOT, Rx; ADD <off>, Rx
+		if p.As != AMOVD {
+			ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p)
+		}
+		if p.To.Type != obj.TYPE_REG {
+			ctxt.Diag("do not know how to handle LEAQ-type insn to non-register in %v with -dynlink", p)
+		}
+		p.From.Type = obj.TYPE_MEM
+		p.From.Name = obj.NAME_GOTREF
+		if p.From.Offset != 0 {
+			q := obj.Appendp(ctxt, p)
+			q.As = AADD
+			q.From.Type = obj.TYPE_CONST
+			q.From.Offset = p.From.Offset
+			q.To = p.To
+			p.From.Offset = 0
+		}
+	}
+	if p.From3 != nil && p.From3.Name == obj.NAME_EXTERN {
+		ctxt.Diag("don't know how to handle %v with -dynlink", p)
+	}
+	var source *obj.Addr
+	// MOVx sym, Ry becomes MOVD sym at GOT, REGTMP; MOVx (REGTMP), Ry
+	// MOVx Ry, sym becomes MOVD sym at GOT, REGTMP; MOVx Ry, (REGTMP)
+	// An addition may be inserted between the two MOVs if there is an offset.
+	if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
+		if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
+			ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
+		}
+		source = &p.From
+	} else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
+		source = &p.To
+	} else {
+		return
+	}
+	if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
+		return
+	}
+	if source.Sym.Type == obj.STLSBSS {
+		return
+	}
+	if source.Type != obj.TYPE_MEM {
+		ctxt.Diag("don't know how to handle %v with -dynlink", p)
+	}
+	p1 := obj.Appendp(ctxt, p)
+	p2 := obj.Appendp(ctxt, p1)
+
+	p1.As = AMOVD
+	p1.From.Type = obj.TYPE_MEM
+	p1.From.Sym = source.Sym
+	p1.From.Name = obj.NAME_GOTREF
+	p1.To.Type = obj.TYPE_REG
+	p1.To.Reg = REGTMP
+
+	p2.As = p.As
+	p2.From = p.From
+	p2.To = p.To
+	if p.From.Name == obj.NAME_EXTERN {
+		p2.From.Reg = REGTMP
+		p2.From.Name = obj.NAME_NONE
+		p2.From.Sym = nil
+	} else if p.To.Name == obj.NAME_EXTERN {
+		p2.To.Reg = REGTMP
+		p2.To.Name = obj.NAME_NONE
+		p2.To.Sym = nil
+	} else {
+		return
+	}
+	obj.Nopout(p)
 }
 
 func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
@@ -124,6 +251,19 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
 
 	p := cursym.Text
 	textstksiz := p.To.Offset
+	if textstksiz == -8 {
+		// Compatibility hack.
+		p.From3.Offset |= obj.NOFRAME
+		textstksiz = 0
+	}
+	if textstksiz%8 != 0 {
+		ctxt.Diag("frame size %d not a multiple of 8", textstksiz)
+	}
+	if p.From3.Offset&obj.NOFRAME != 0 {
+		if textstksiz != 0 {
+			ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", textstksiz)
+		}
+	}
 
 	cursym.Args = p.To.Val.(int32)
 	cursym.Locals = int32(textstksiz)
@@ -314,27 +454,71 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
 		case obj.ATEXT:
 			mov = AMOVD
 			aoffset = 0
-			autosize = int32(textstksiz + 8)
-			if (p.Mark&LEAF != 0) && autosize <= 8 {
-				autosize = 0
-			} else if autosize&4 != 0 {
-				autosize += 4
+			autosize = int32(textstksiz)
+
+			if p.Mark&LEAF != 0 && autosize == 0 && p.From3.Offset&obj.NOFRAME == 0 {
+				// A leaf function with no locals has no frame.
+				p.From3.Offset |= obj.NOFRAME
 			}
-			p.To.Offset = int64(autosize) - 8
 
-			if p.From3.Offset&obj.NOSPLIT == 0 {
-				p = stacksplit(ctxt, p, autosize) // emit split check
+			if p.From3.Offset&obj.NOFRAME == 0 {
+				// If there is a stack frame at all, it includes
+				// space to save the LR.
+				autosize += int32(ctxt.FixedFrameSize())
 			}
 
+			p.To.Offset = int64(autosize)
+
 			q = p
 
+			if ctxt.Flag_shared != 0 && cursym.Name != "runtime.duffzero" && cursym.Name != "runtime.duffcopy" && cursym.Name != "runtime.stackBarrier" {
+				// When compiling Go into PIC, all functions must start
+				// with instructions to load the TOC pointer into r2:
+				//
+				//	addis r2, r12, .TOC.-func at ha
+				//	addi r2, r2, .TOC.-func at l+4
+				//
+				// We could probably skip this prologue in some situations
+				// but it's a bit subtle. However, it is both safe and
+				// necessary to leave the prologue off duffzero and
+				// duffcopy as we rely on being able to jump to a specific
+				// instruction offset for them, and stackBarrier is only
+				// ever called from an overwritten LR-save slot on the
+				// stack (when r12 will not be remotely the right thing)
+				// but fortunately does not access global data.
+				//
+				// These are AWORDS because there is no (afaict) way to
+				// generate the addis instruction except as part of the
+				// load of a large constant, and in that case there is no
+				// way to use r12 as the source.
+				q = obj.Appendp(ctxt, q)
+				q.As = AWORD
+				q.Lineno = p.Lineno
+				q.From.Type = obj.TYPE_CONST
+				q.From.Offset = 0x3c4c0000
+				q = obj.Appendp(ctxt, q)
+				q.As = AWORD
+				q.Lineno = p.Lineno
+				q.From.Type = obj.TYPE_CONST
+				q.From.Offset = 0x38420000
+				rel := obj.Addrel(ctxt.Cursym)
+				rel.Off = 0
+				rel.Siz = 8
+				rel.Sym = obj.Linklookup(ctxt, ".TOC.", 0)
+				rel.Type = obj.R_ADDRPOWER_PCREL
+			}
+
+			if cursym.Text.From3.Offset&obj.NOSPLIT == 0 {
+				q = stacksplit(ctxt, q, autosize) // emit split check
+			}
+
 			if autosize != 0 {
 				/* use MOVDU to adjust R1 when saving R31, if autosize is small */
 				if cursym.Text.Mark&LEAF == 0 && autosize >= -BIG && autosize <= BIG {
 					mov = AMOVDU
 					aoffset = int(-autosize)
 				} else {
-					q = obj.Appendp(ctxt, p)
+					q = obj.Appendp(ctxt, q)
 					q.As = AADD
 					q.Lineno = p.Lineno
 					q.From.Type = obj.TYPE_CONST
@@ -344,11 +528,9 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
 					q.Spadj = +autosize
 				}
 			} else if cursym.Text.Mark&LEAF == 0 {
-				if ctxt.Debugvlog != 0 {
-					fmt.Fprintf(ctxt.Bso, "save suppressed in: %s\n", cursym.Name)
-					ctxt.Bso.Flush()
-				}
-
+				// A very few functions that do not return to their caller
+				// (e.g. gogo) are not identified as leaves but still have
+				// no frame.
 				cursym.Text.Mark |= LEAF
 			}
 
@@ -377,6 +559,17 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
 				q.Spadj = int32(-aoffset)
 			}
 
+			if ctxt.Flag_shared != 0 {
+				q = obj.Appendp(ctxt, q)
+				q.As = AMOVD
+				q.Lineno = p.Lineno
+				q.From.Type = obj.TYPE_REG
+				q.From.Reg = REG_R2
+				q.To.Type = obj.TYPE_MEM
+				q.To.Reg = REGSP
+				q.To.Offset = 24
+			}
+
 			if cursym.Text.From3.Offset&obj.WRAPPER != 0 {
 				// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
 				//
@@ -427,7 +620,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
 				q = obj.Appendp(ctxt, q)
 				q.As = AADD
 				q.From.Type = obj.TYPE_CONST
-				q.From.Offset = int64(autosize) + 8
+				q.From.Offset = int64(autosize) + ctxt.FixedFrameSize()
 				q.Reg = REGSP
 				q.To.Type = obj.TYPE_REG
 				q.To.Reg = REG_R5
@@ -447,7 +640,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
 				q = obj.Appendp(ctxt, q)
 				q.As = AADD
 				q.From.Type = obj.TYPE_CONST
-				q.From.Offset = 8
+				q.From.Offset = ctxt.FixedFrameSize()
 				q.Reg = REGSP
 				q.To.Type = obj.TYPE_REG
 				q.To.Reg = REG_R6
@@ -473,18 +666,19 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
 				break
 			}
 
-			if p.To.Sym != nil { // retjmp
-				p.As = ABR
-				p.To.Type = obj.TYPE_BRANCH
-				break
-			}
+			retTarget := p.To.Sym
 
 			if cursym.Text.Mark&LEAF != 0 {
 				if autosize == 0 {
 					p.As = ABR
 					p.From = obj.Addr{}
-					p.To.Type = obj.TYPE_REG
-					p.To.Reg = REG_LR
+					if retTarget == nil {
+						p.To.Type = obj.TYPE_REG
+						p.To.Reg = REG_LR
+					} else {
+						p.To.Type = obj.TYPE_BRANCH
+						p.To.Sym = retTarget
+					}
 					p.Mark |= BRANCH
 					break
 				}
@@ -562,14 +756,18 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
 			q1 = ctxt.NewProg()
 			q1.As = ABR
 			q1.Lineno = p.Lineno
-			q1.To.Type = obj.TYPE_REG
-			q1.To.Reg = REG_LR
+			if retTarget == nil {
+				q1.To.Type = obj.TYPE_REG
+				q1.To.Reg = REG_LR
+			} else {
+				q1.To.Type = obj.TYPE_BRANCH
+				q1.To.Sym = retTarget
+			}
 			q1.Mark |= BRANCH
 			q1.Spadj = +autosize
 
 			q1.Link = q.Link
 			q.Link = q1
-
 		case AADD:
 			if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.From.Type == obj.TYPE_CONST {
 				p.Spadj = int32(-p.From.Offset)
@@ -745,19 +943,62 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
 		q.Pcond = p
 	}
 
-	// BL	runtime.morestack(SB)
-	p = obj.Appendp(ctxt, p)
-
-	p.As = ABL
-	p.To.Type = obj.TYPE_BRANCH
+	var morestacksym *obj.LSym
 	if ctxt.Cursym.Cfunc != 0 {
-		p.To.Sym = obj.Linklookup(ctxt, "runtime.morestackc", 0)
+		morestacksym = obj.Linklookup(ctxt, "runtime.morestackc", 0)
 	} else if ctxt.Cursym.Text.From3.Offset&obj.NEEDCTXT == 0 {
-		p.To.Sym = obj.Linklookup(ctxt, "runtime.morestack_noctxt", 0)
+		morestacksym = obj.Linklookup(ctxt, "runtime.morestack_noctxt", 0)
 	} else {
-		p.To.Sym = obj.Linklookup(ctxt, "runtime.morestack", 0)
+		morestacksym = obj.Linklookup(ctxt, "runtime.morestack", 0)
 	}
 
+	if ctxt.Flag_dynlink {
+		// Avoid calling morestack via a PLT when dynamically linking.  The
+		// PLT stubs generated by the system linker on ppc64le when "std r2,
+		// 24(r1)" to save the TOC pointer in their callers stack
+		// frame. Unfortunately (and necessarily) morestack is called before
+		// the function that calls it sets up its frame and so the PLT ends
+		// up smashing the saved TOC pointer for its caller's caller.
+		//
+		// According to the ABI documentation there is a mechanism to avoid
+		// the TOC save that the PLT stub does (put a R_PPC64_TOCSAVE
+		// relocation on the nop after the call to morestack) but at the time
+		// of writing it is not supported at all by gold and my attempt to
+		// use it with ld.bfd caused an internal linker error. So this hack
+		// seems preferable.
+
+		// MOVD $runtime.morestack(SB), R12
+		p = obj.Appendp(ctxt, p)
+		p.As = AMOVD
+		p.From.Type = obj.TYPE_MEM
+		p.From.Sym = morestacksym
+		p.From.Name = obj.NAME_GOTREF
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = REG_R12
+
+		// MOVD R12, CTR
+		p = obj.Appendp(ctxt, p)
+		p.As = AMOVD
+		p.From.Type = obj.TYPE_REG
+		p.From.Reg = REG_R12
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = REG_CTR
+
+		// BL CTR
+		p = obj.Appendp(ctxt, p)
+		p.As = obj.ACALL
+		p.From.Type = obj.TYPE_REG
+		p.From.Reg = REG_R12
+		p.To.Type = obj.TYPE_REG
+		p.To.Reg = REG_CTR
+	} else {
+		// BL	runtime.morestack(SB)
+		p = obj.Appendp(ctxt, p)
+
+		p.As = ABL
+		p.To.Type = obj.TYPE_BRANCH
+		p.To.Sym = morestacksym
+	}
 	// BR	start
 	p = obj.Appendp(ctxt, p)
 
diff --git a/src/cmd/internal/obj/stack.go b/src/cmd/internal/obj/stack.go
index 87698b3..80f6c6c 100644
--- a/src/cmd/internal/obj/stack.go
+++ b/src/cmd/internal/obj/stack.go
@@ -2,36 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Inferno utils/5l/span.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5l/span.c
-//
-//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
-//	Portions Copyright © 1995-1997 C H Forsyth (forsyth at terzarima.net)
-//	Portions Copyright © 1997-1999 Vita Nuova Limited
-//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-//	Portions Copyright © 2004,2006 Bruce Ellis
-//	Portions Copyright © 2005-2007 C H Forsyth (forsyth at terzarima.net)
-//	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
 package obj
 
 // For the linkers. Must match Go definitions.
@@ -41,7 +11,7 @@ const (
 	STACKSYSTEM = 0
 	StackSystem = STACKSYSTEM
 	StackBig    = 4096
-	StackGuard  = 640*stackGuardMultiplier + StackSystem
+	StackGuard  = 720*stackGuardMultiplier + StackSystem
 	StackSmall  = 128
 	StackLimit  = StackGuard - StackSystem - StackSmall
 )
diff --git a/src/cmd/internal/obj/sym.go b/src/cmd/internal/obj/sym.go
index 37bb40b..dd5297e 100644
--- a/src/cmd/internal/obj/sym.go
+++ b/src/cmd/internal/obj/sym.go
@@ -105,74 +105,9 @@ func Linknew(arch *LinkArch) *Link {
 		log.Fatalf("unknown goos %s", Getgoos())
 	}
 
-	// Record thread-local storage offset.
-	// TODO(rsc): Move tlsoffset back into the linker.
-	switch ctxt.Headtype {
-	default:
-		log.Fatalf("unknown thread-local storage offset for %s", Headstr(ctxt.Headtype))
-
-	case Hplan9, Hwindows:
-		break
-
-		/*
-		 * ELF uses TLS offset negative from FS.
-		 * Translate 0(FS) and 8(FS) into -16(FS) and -8(FS).
-		 * Known to low-level assembly in package runtime and runtime/cgo.
-		 */
-	case Hlinux,
-		Hfreebsd,
-		Hnetbsd,
-		Hopenbsd,
-		Hdragonfly,
-		Hsolaris:
-		ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize
-
-	case Hnacl:
-		switch ctxt.Arch.Thechar {
-		default:
-			log.Fatalf("unknown thread-local storage offset for nacl/%s", ctxt.Arch.Name)
-
-		case '5':
-			ctxt.Tlsoffset = 0
-
-		case '6':
-			ctxt.Tlsoffset = 0
-
-		case '8':
-			ctxt.Tlsoffset = -8
-		}
-
-		/*
-		 * OS X system constants - offset from 0(GS) to our TLS.
-		 * Explained in ../../runtime/cgo/gcc_darwin_*.c.
-		 */
-	case Hdarwin:
-		switch ctxt.Arch.Thechar {
-		default:
-			log.Fatalf("unknown thread-local storage offset for darwin/%s", ctxt.Arch.Name)
-
-		case '5':
-			ctxt.Tlsoffset = 0 // dummy value, not needed
-
-		case '6':
-			ctxt.Tlsoffset = 0x8a0
-
-		case '7':
-			ctxt.Tlsoffset = 0 // dummy value, not needed
-
-		case '8':
-			ctxt.Tlsoffset = 0x468
-		}
-	}
-
 	// On arm, record goarm.
 	if ctxt.Arch.Thechar == '5' {
-		p := Getgoarm()
-		if p != "" {
-			ctxt.Goarm = int32(Atoi(p))
-		} else {
-			ctxt.Goarm = 6
-		}
+		ctxt.Goarm = Getgoarm()
 	}
 
 	return ctxt
diff --git a/src/cmd/internal/obj/textflag.go b/src/cmd/internal/obj/textflag.go
index dbd1bc8..3d3b3b8 100644
--- a/src/cmd/internal/obj/textflag.go
+++ b/src/cmd/internal/obj/textflag.go
@@ -35,4 +35,13 @@ const (
 
 	// When passed to ggloblsym, causes Local to be set to true on the LSym it creates.
 	LOCAL = 128
+
+	// Allocate a word of thread local storage and store the offset from the
+	// thread local base to the thread local storage in this variable.
+	TLSBSS = 256
+
+	// Do not insert instructions to allocate a stack frame for this function.
+	// Only valid on functions that declare a frame size of 0.
+	// TODO(mwhudson): only implemented for ppc64x at present.
+	NOFRAME = 512
 )
diff --git a/src/cmd/internal/obj/util.go b/src/cmd/internal/obj/util.go
index 3c3fc88..5103299 100644
--- a/src/cmd/internal/obj/util.go
+++ b/src/cmd/internal/obj/util.go
@@ -11,7 +11,6 @@ import (
 	"io"
 	"log"
 	"os"
-	"strconv"
 	"strings"
 	"time"
 )
@@ -54,6 +53,10 @@ func Binitw(w io.Writer) *Biobuf {
 	return &Biobuf{w: bufio.NewWriter(w)}
 }
 
+func Binitr(r io.Reader) *Biobuf {
+	return &Biobuf{r: bufio.NewReader(r)}
+}
+
 func (b *Biobuf) Write(p []byte) (int, error) {
 	return b.w.Write(p)
 }
@@ -166,17 +169,6 @@ func Brdstr(b *Biobuf, delim int, cut int) string {
 	return s
 }
 
-func Access(name string, mode int) int {
-	if mode != 0 {
-		panic("bad access")
-	}
-	_, err := os.Stat(name)
-	if err != nil {
-		return -1
-	}
-	return 0
-}
-
 func Blinelen(b *Biobuf) int {
 	return b.linelen
 }
@@ -212,10 +204,14 @@ func Getgoos() string {
 	return envOr("GOOS", defaultGOOS)
 }
 
-func Getgoarm() string {
+func Getgoarm() int32 {
 	switch v := envOr("GOARM", defaultGOARM); v {
-	case "5", "6", "7":
-		return v
+	case "5":
+		return 5
+	case "6":
+		return 6
+	case "7":
+		return 7
 	}
 	// Fail here, rather than validate at multiple call sites.
 	log.Fatalf("Invalid GOARM value. Must be 5, 6, or 7.")
@@ -235,11 +231,6 @@ func Getgoversion() string {
 	return version
 }
 
-func Atoi(s string) int {
-	i, _ := strconv.Atoi(s)
-	return i
-}
-
 func (p *Prog) Line() string {
 	return p.Ctxt.LineHist.LineString(int(p.Lineno))
 }
@@ -470,13 +461,25 @@ func Mconv(a *Addr) string {
 		}
 
 	case NAME_EXTERN:
-		str = fmt.Sprintf("%s%s(SB)", a.Sym.Name, offConv(a.Offset))
+		if a.Sym != nil {
+			str = fmt.Sprintf("%s%s(SB)", a.Sym.Name, offConv(a.Offset))
+		} else {
+			str = fmt.Sprintf("%s(SB)", offConv(a.Offset))
+		}
 
 	case NAME_GOTREF:
-		str = fmt.Sprintf("%s%s at GOT(SB)", a.Sym.Name, offConv(a.Offset))
+		if a.Sym != nil {
+			str = fmt.Sprintf("%s%s at GOT(SB)", a.Sym.Name, offConv(a.Offset))
+		} else {
+			str = fmt.Sprintf("%s at GOT(SB)", offConv(a.Offset))
+		}
 
 	case NAME_STATIC:
-		str = fmt.Sprintf("%s<>%s(SB)", a.Sym.Name, offConv(a.Offset))
+		if a.Sym != nil {
+			str = fmt.Sprintf("%s<>%s(SB)", a.Sym.Name, offConv(a.Offset))
+		} else {
+			str = fmt.Sprintf("<>%s(SB)", offConv(a.Offset))
+		}
 
 	case NAME_AUTO:
 		if a.Sym != nil {
@@ -521,11 +524,12 @@ var regSpace []regSet
 const (
 	// Because of masking operations in the encodings, each register
 	// space should start at 0 modulo some power of 2.
-	RBase386   = 1 * 1024
-	RBaseAMD64 = 2 * 1024
-	RBaseARM   = 3 * 1024
-	RBasePPC64 = 4 * 1024 // range [4k, 8k)
-	RBaseARM64 = 8 * 1024 // range [8k, 12k)
+	RBase386    = 1 * 1024
+	RBaseAMD64  = 2 * 1024
+	RBaseARM    = 3 * 1024
+	RBasePPC64  = 4 * 1024  // range [4k, 8k)
+	RBaseARM64  = 8 * 1024  // range [8k, 13k)
+	RBaseMIPS64 = 13 * 1024 // range [13k, 14k)
 )
 
 // RegisterRegister binds a pretty-printer (Rconv) for register
@@ -585,6 +589,7 @@ const (
 	ABaseAMD64
 	ABasePPC64
 	ABaseARM64
+	ABaseMIPS64
 	AMask = 1<<12 - 1 // AND with this to use the opcode as an array index.
 )
 
@@ -603,7 +608,7 @@ func RegisterOpcode(lo int, Anames []string) {
 }
 
 func Aconv(a int) string {
-	if a < A_ARCHSPECIFIC {
+	if 0 <= a && a < len(Anames) {
 		return Anames[a]
 	}
 	for i := range aSpace {
@@ -635,6 +640,7 @@ var Anames = []string{
 	"USEFIELD",
 	"VARDEF",
 	"VARKILL",
+	"VARLIVE",
 }
 
 func Bool2int(b bool) int {
diff --git a/src/cmd/internal/obj/x86/a.out.go b/src/cmd/internal/obj/x86/a.out.go
index c7f46e1..12eaa90 100644
--- a/src/cmd/internal/obj/x86/a.out.go
+++ b/src/cmd/internal/obj/x86/a.out.go
@@ -89,7 +89,11 @@ const (
 	ADIVL
 	ADIVW
 	AENTER
+	AHADDPD
+	AHADDPS
 	AHLT
+	AHSUBPD
+	AHSUBPS
 	AIDIVB
 	AIDIVL
 	AIDIVW
@@ -181,6 +185,9 @@ const (
 	APAUSE
 	APOPAL
 	APOPAW
+	APOPCNTW
+	APOPCNTL
+	APOPCNTQ
 	APOPFL
 	APOPFW
 	APOPL
@@ -500,16 +507,29 @@ const (
 	AXADDQ
 	AXCHGQ
 	AXORQ
+	AXGETBV
 
 	// media
 	AADDPD
 	AADDPS
 	AADDSD
 	AADDSS
+	AANDNL
+	AANDNQ
 	AANDNPD
 	AANDNPS
 	AANDPD
 	AANDPS
+	ABEXTRL
+	ABEXTRQ
+	ABLSIL
+	ABLSIQ
+	ABLSMSKL
+	ABLSMSKQ
+	ABLSRL
+	ABLSRQ
+	ABZHIL
+	ABZHIQ
 	ACMPPD
 	ACMPPS
 	ACMPSD
@@ -547,6 +567,7 @@ const (
 	AFXRSTOR64
 	AFXSAVE
 	AFXSAVE64
+	ALDDQU
 	ALDMXCSR
 	AMASKMOVOU
 	AMASKMOVQ
@@ -583,6 +604,8 @@ const (
 	AMULPS
 	AMULSD
 	AMULSS
+	AMULXL
+	AMULXQ
 	AORPD
 	AORPS
 	APACKSSLW
@@ -596,15 +619,15 @@ const (
 	APADDUSB
 	APADDUSW
 	APADDW
+	APAND
 	APANDB
 	APANDL
+	APANDN
 	APANDSB
 	APANDSW
 	APANDUSB
 	APANDUSW
 	APANDW
-	APAND
-	APANDN
 	APAVGB
 	APAVGW
 	APCMPEQB
@@ -613,6 +636,13 @@ const (
 	APCMPGTB
 	APCMPGTL
 	APCMPGTW
+	APDEPL
+	APDEPQ
+	APEXTL
+	APEXTQ
+	APEXTRB
+	APEXTRD
+	APEXTRQ
 	APEXTRW
 	APFACC
 	APFADD
@@ -625,41 +655,63 @@ const (
 	APFNACC
 	APFPNACC
 	APFRCP
-	APFRCPIT1
 	APFRCPI2T
+	APFRCPIT1
 	APFRSQIT1
 	APFRSQRT
 	APFSUB
 	APFSUBR
-	APINSRW
+	APHADDD
+	APHADDSW
+	APHADDW
+	APHMINPOSUW
+	APHSUBD
+	APHSUBSW
+	APHSUBW
+	APINSRB
 	APINSRD
 	APINSRQ
+	APINSRW
 	APMADDWL
 	APMAXSW
 	APMAXUB
 	APMINSW
 	APMINUB
 	APMOVMSKB
+	APMOVSXBD
+	APMOVSXBQ
+	APMOVSXBW
+	APMOVSXDQ
+	APMOVSXWD
+	APMOVSXWQ
+	APMOVZXBD
+	APMOVZXBQ
+	APMOVZXBW
+	APMOVZXDQ
+	APMOVZXWD
+	APMOVZXWQ
+	APMULDQ
 	APMULHRW
 	APMULHUW
 	APMULHW
+	APMULLD
 	APMULLW
 	APMULULQ
 	APOR
 	APSADBW
+	APSHUFB
 	APSHUFHW
 	APSHUFL
 	APSHUFLW
 	APSHUFW
-	APSHUFB
-	APSLLO
 	APSLLL
+	APSLLO
 	APSLLQ
 	APSLLW
 	APSRAL
 	APSRAW
-	APSRLO
 	APSRLL
+	APSRLO
 	APSRLQ
 	APSRLW
 	APSUBB
@@ -684,6 +736,12 @@ const (
 	ARCPSS
 	ARSQRTPS
 	ARSQRTSS
+	ASARXL
+	ASARXQ
+	ASHLXL
+	ASHLXQ
+	ASHRXL
+	ASHRXQ
 	ASHUFPD
 	ASHUFPS
 	ASQRTPD
@@ -734,9 +792,25 @@ const (
 	AAESIMC
 	AAESKEYGENASSIST
 
+	AROUNDPS
+	AROUNDSS
+	AROUNDPD
+	AROUNDSD
+
 	APSHUFD
 	APCLMULQDQ
 
+	AVZEROUPPER
+	AVMOVDQU
+	AVMOVNTDQ
+	AVMOVDQA
+	AVPCMPEQB
+	AVPXOR
+	AVPMOVMSKB
+	AVPAND
+	AVPTEST
+	AVPBROADCASTB
+
 	// from 386
 	AJCXZW
 	AFCMOVCC
@@ -752,6 +826,14 @@ const (
 	AFUCOMI
 	AFUCOMIP
 
+	// TSX
+	AXACQUIRE
+	AXRELEASE
+	AXBEGIN
+	AXEND
+	AXABORT
+	AXTEST
+
 	ALAST
 )
 
@@ -834,6 +916,23 @@ const (
 	REG_X14
 	REG_X15
 
+	REG_Y0
+	REG_Y1
+	REG_Y2
+	REG_Y3
+	REG_Y4
+	REG_Y5
+	REG_Y6
+	REG_Y7
+	REG_Y8
+	REG_Y9
+	REG_Y10
+	REG_Y11
+	REG_Y12
+	REG_Y13
+	REG_Y14
+	REG_Y15
+
 	REG_CS
 	REG_SS
 	REG_DS
@@ -894,7 +993,6 @@ const (
 	REGRET   = REG_AX
 	FREGRET  = REG_X0
 	REGSP    = REG_SP
-	REGTMP   = REG_DI
 	REGCTXT  = REG_DX
 	REGEXT   = REG_R15     /* compiler allocates external registers R15 down */
 	FREGMIN  = REG_X0 + 5  /* first register variable */
diff --git a/src/cmd/internal/obj/x86/anames.go b/src/cmd/internal/obj/x86/anames.go
index 7f7708c..1875eae 100644
--- a/src/cmd/internal/obj/x86/anames.go
+++ b/src/cmd/internal/obj/x86/anames.go
@@ -57,7 +57,11 @@ var Anames = []string{
 	"DIVL",
 	"DIVW",
 	"ENTER",
+	"HADDPD",
+	"HADDPS",
 	"HLT",
+	"HSUBPD",
+	"HSUBPS",
 	"IDIVB",
 	"IDIVL",
 	"IDIVW",
@@ -149,6 +153,9 @@ var Anames = []string{
 	"PAUSE",
 	"POPAL",
 	"POPAW",
+	"POPCNTW",
+	"POPCNTL",
+	"POPCNTQ",
 	"POPFL",
 	"POPFW",
 	"POPL",
@@ -451,14 +458,27 @@ var Anames = []string{
 	"XADDQ",
 	"XCHGQ",
 	"XORQ",
+	"XGETBV",
 	"ADDPD",
 	"ADDPS",
 	"ADDSD",
 	"ADDSS",
+	"ANDNL",
+	"ANDNQ",
 	"ANDNPD",
 	"ANDNPS",
 	"ANDPD",
 	"ANDPS",
+	"BEXTRL",
+	"BEXTRQ",
+	"BLSIL",
+	"BLSIQ",
+	"BLSMSKL",
+	"BLSMSKQ",
+	"BLSRL",
+	"BLSRQ",
+	"BZHIL",
+	"BZHIQ",
 	"CMPPD",
 	"CMPPS",
 	"CMPSD",
@@ -496,6 +516,7 @@ var Anames = []string{
 	"FXRSTOR64",
 	"FXSAVE",
 	"FXSAVE64",
+	"LDDQU",
 	"LDMXCSR",
 	"MASKMOVOU",
 	"MASKMOVQ",
@@ -532,6 +553,8 @@ var Anames = []string{
 	"MULPS",
 	"MULSD",
 	"MULSS",
+	"MULXL",
+	"MULXQ",
 	"ORPD",
 	"ORPS",
 	"PACKSSLW",
@@ -545,15 +568,15 @@ var Anames = []string{
 	"PADDUSB",
 	"PADDUSW",
 	"PADDW",
+	"PAND",
 	"PANDB",
 	"PANDL",
+	"PANDN",
 	"PANDSB",
 	"PANDSW",
 	"PANDUSB",
 	"PANDUSW",
 	"PANDW",
-	"PAND",
-	"PANDN",
 	"PAVGB",
 	"PAVGW",
 	"PCMPEQB",
@@ -562,6 +585,13 @@ var Anames = []string{
 	"PCMPGTB",
 	"PCMPGTL",
 	"PCMPGTW",
+	"PDEPL",
+	"PDEPQ",
+	"PEXTL",
+	"PEXTQ",
+	"PEXTRB",
+	"PEXTRD",
+	"PEXTRQ",
 	"PEXTRW",
 	"PFACC",
 	"PFADD",
@@ -574,41 +604,63 @@ var Anames = []string{
 	"PFNACC",
 	"PFPNACC",
 	"PFRCP",
-	"PFRCPIT1",
 	"PFRCPI2T",
+	"PFRCPIT1",
 	"PFRSQIT1",
 	"PFRSQRT",
 	"PFSUB",
 	"PFSUBR",
-	"PINSRW",
+	"PHADDD",
+	"PHADDSW",
+	"PHADDW",
+	"PHMINPOSUW",
+	"PHSUBD",
+	"PHSUBSW",
+	"PHSUBW",
+	"PINSRB",
 	"PINSRD",
 	"PINSRQ",
+	"PINSRW",
 	"PMADDWL",
 	"PMAXSW",
 	"PMAXUB",
 	"PMINSW",
 	"PMINUB",
 	"PMOVMSKB",
+	"PMOVSXBD",
+	"PMOVSXBQ",
+	"PMOVSXBW",
+	"PMOVSXDQ",
+	"PMOVSXWD",
+	"PMOVSXWQ",
+	"PMOVZXBD",
+	"PMOVZXBQ",
+	"PMOVZXBW",
+	"PMOVZXDQ",
+	"PMOVZXWD",
+	"PMOVZXWQ",
+	"PMULDQ",
 	"PMULHRW",
 	"PMULHUW",
 	"PMULHW",
+	"PMULLD",
 	"PMULLW",
 	"PMULULQ",
 	"POR",
 	"PSADBW",
+	"PSHUFB",
 	"PSHUFHW",
 	"PSHUFL",
 	"PSHUFLW",
 	"PSHUFW",
-	"PSHUFB",
-	"PSLLO",
 	"PSLLL",
+	"PSLLO",
 	"PSLLQ",
 	"PSLLW",
 	"PSRAL",
 	"PSRAW",
-	"PSRLO",
 	"PSRLL",
+	"PSRLO",
 	"PSRLQ",
 	"PSRLW",
 	"PSUBB",
@@ -633,6 +685,12 @@ var Anames = []string{
 	"RCPSS",
 	"RSQRTPS",
 	"RSQRTSS",
+	"SARXL",
+	"SARXQ",
+	"SHLXL",
+	"SHLXQ",
+	"SHRXL",
+	"SHRXQ",
 	"SHUFPD",
 	"SHUFPS",
 	"SQRTPD",
@@ -677,8 +735,22 @@ var Anames = []string{
 	"AESDECLAST",
 	"AESIMC",
 	"AESKEYGENASSIST",
+	"ROUNDPS",
+	"ROUNDSS",
+	"ROUNDPD",
+	"ROUNDSD",
 	"PSHUFD",
 	"PCLMULQDQ",
+	"VZEROUPPER",
+	"VMOVDQU",
+	"VMOVNTDQ",
+	"VMOVDQA",
+	"VPCMPEQB",
+	"VPXOR",
+	"VPMOVMSKB",
+	"VPAND",
+	"VPTEST",
+	"VPBROADCASTB",
 	"JCXZW",
 	"FCMOVCC",
 	"FCMOVCS",
@@ -692,5 +764,11 @@ var Anames = []string{
 	"FCOMIP",
 	"FUCOMI",
 	"FUCOMIP",
+	"XACQUIRE",
+	"XRELEASE",
+	"XBEGIN",
+	"XEND",
+	"XABORT",
+	"XTEST",
 	"LAST",
 }
diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go
index 7a69dc8..4ed1d87 100644
--- a/src/cmd/internal/obj/x86/asm6.go
+++ b/src/cmd/internal/obj/x86/asm6.go
@@ -40,8 +40,6 @@ import (
 // Instruction layout.
 
 const (
-	MaxAlign = 32 // max data alignment
-
 	// Loop alignment constants:
 	// want to align loop entry to LoopAlign-byte boundary,
 	// and willing to insert at most MaxLoopPad bytes of NOP to do so.
@@ -150,6 +148,8 @@ const (
 	Ymm
 	Yxr
 	Yxm
+	Yyr
+	Yym
 	Ytls
 	Ytextsize
 	Yindir
@@ -175,7 +175,6 @@ const (
 	Zil_rp
 	Ziq_rp
 	Zilo_m
-	Ziqo_m
 	Zjmp
 	Zjmpcon
 	Zloop
@@ -189,6 +188,7 @@ const (
 	Zm_r_xm_nr
 	Zr_m_xm_nr
 	Zibm_r /* mmx1,mmx2/mem64,imm8 */
+	Zibr_m
 	Zmb_r
 	Zaut_r
 	Zo_m
@@ -205,34 +205,106 @@ const (
 	Zil_rr
 	Zclr
 	Zbyte
+	Zvex_rm_v_r
+	Zvex_r_v_rm
+	Zvex_v_rm_r
 	Zmax
 )
 
 const (
-	Px  = 0
-	Px1 = 1    // symbolic; exact value doesn't matter
-	P32 = 0x32 /* 32-bit only */
-	Pe  = 0x66 /* operand escape */
-	Pm  = 0x0f /* 2byte opcode escape */
-	Pq  = 0xff /* both escapes: 66 0f */
-	Pb  = 0xfe /* byte operands */
-	Pf2 = 0xf2 /* xmm escape 1: f2 0f */
-	Pf3 = 0xf3 /* xmm escape 2: f3 0f */
-	Pq3 = 0x67 /* xmm escape 3: 66 48 0f */
-	Pw  = 0x48 /* Rex.w */
-	Pw8 = 0x90 // symbolic; exact value doesn't matter
-	Py  = 0x80 /* defaults to 64-bit mode */
-	Py1 = 0x81 // symbolic; exact value doesn't matter
-	Py3 = 0x83 // symbolic; exact value doesn't matter
-
-	Rxf = 1 << 9 /* internal flag for Rxr on from */
-	Rxt = 1 << 8 /* internal flag for Rxr on to */
+	Px   = 0
+	Px1  = 1    // symbolic; exact value doesn't matter
+	P32  = 0x32 /* 32-bit only */
+	Pe   = 0x66 /* operand escape */
+	Pm   = 0x0f /* 2byte opcode escape */
+	Pq   = 0xff /* both escapes: 66 0f */
+	Pb   = 0xfe /* byte operands */
+	Pf2  = 0xf2 /* xmm escape 1: f2 0f */
+	Pf3  = 0xf3 /* xmm escape 2: f3 0f */
+	Pef3 = 0xf5 /* xmm escape 2 with 16-bit prefix: 66 f3 0f */
+	Pq3  = 0x67 /* xmm escape 3: 66 48 0f */
+	Pq4  = 0x68 /* xmm escape 4: 66 0F 38 */
+	Pfw  = 0xf4 /* Pf3 with Rex.w: f3 48 0f */
+	Pw   = 0x48 /* Rex.w */
+	Pw8  = 0x90 // symbolic; exact value doesn't matter
+	Py   = 0x80 /* defaults to 64-bit mode */
+	Py1  = 0x81 // symbolic; exact value doesn't matter
+	Py3  = 0x83 // symbolic; exact value doesn't matter
+	Pvex = 0x84 // symbolic: exact value doesn't matter
+
 	Rxw = 1 << 3 /* =1, 64-bit operand size */
 	Rxr = 1 << 2 /* extend modrm reg */
 	Rxx = 1 << 1 /* extend sib index */
 	Rxb = 1 << 0 /* extend modrm r/m, sib base, or opcode reg */
+)
 
-	Maxand = 10 /* in -a output width of the byte codes */
+const (
+	// Encoding for VEX prefix in tables.
+	// The P, L, and W fields are chosen to match
+	// their eventual locations in the VEX prefix bytes.
+
+	// P field - 2 bits
+	vex66 = 1 << 0
+	vexF3 = 2 << 0
+	vexF2 = 3 << 0
+	// L field - 1 bit
+	vexLZ  = 0 << 2
+	vexLIG = 0 << 2
+	vex128 = 0 << 2
+	vex256 = 1 << 2
+	// W field - 1 bit
+	vexWIG = 0 << 7
+	vexW0  = 0 << 7
+	vexW1  = 1 << 7
+	// M field - 5 bits, but mostly reserved; we can store up to 4
+	vex0F   = 1 << 3
+	vex0F38 = 2 << 3
+	vex0F3A = 3 << 3
+
+	// Combinations used in the manual.
+	VEX_128_0F_WIG      = vex128 | vex0F | vexWIG
+	VEX_128_66_0F_W0    = vex128 | vex66 | vex0F | vexW0
+	VEX_128_66_0F_W1    = vex128 | vex66 | vex0F | vexW1
+	VEX_128_66_0F_WIG   = vex128 | vex66 | vex0F | vexWIG
+	VEX_128_66_0F38_W0  = vex128 | vex66 | vex0F38 | vexW0
+	VEX_128_66_0F38_W1  = vex128 | vex66 | vex0F38 | vexW1
+	VEX_128_66_0F38_WIG = vex128 | vex66 | vex0F38 | vexWIG
+	VEX_128_66_0F3A_W0  = vex128 | vex66 | vex0F3A | vexW0
+	VEX_128_66_0F3A_W1  = vex128 | vex66 | vex0F3A | vexW1
+	VEX_128_66_0F3A_WIG = vex128 | vex66 | vex0F3A | vexWIG
+	VEX_128_F2_0F_WIG   = vex128 | vexF2 | vex0F | vexWIG
+	VEX_128_F3_0F_WIG   = vex128 | vexF3 | vex0F | vexWIG
+	VEX_256_66_0F_WIG   = vex256 | vex66 | vex0F | vexWIG
+	VEX_256_66_0F38_W0  = vex256 | vex66 | vex0F38 | vexW0
+	VEX_256_66_0F38_W1  = vex256 | vex66 | vex0F38 | vexW1
+	VEX_256_66_0F38_WIG = vex256 | vex66 | vex0F38 | vexWIG
+	VEX_256_66_0F3A_W0  = vex256 | vex66 | vex0F3A | vexW0
+	VEX_256_66_0F3A_W1  = vex256 | vex66 | vex0F3A | vexW1
+	VEX_256_66_0F3A_WIG = vex256 | vex66 | vex0F3A | vexWIG
+	VEX_256_F2_0F_WIG   = vex256 | vexF2 | vex0F | vexWIG
+	VEX_256_F3_0F_WIG   = vex256 | vexF3 | vex0F | vexWIG
+	VEX_LIG_0F_WIG      = vexLIG | vex0F | vexWIG
+	VEX_LIG_66_0F_WIG   = vexLIG | vex66 | vex0F | vexWIG
+	VEX_LIG_66_0F38_W0  = vexLIG | vex66 | vex0F38 | vexW0
+	VEX_LIG_66_0F38_W1  = vexLIG | vex66 | vex0F38 | vexW1
+	VEX_LIG_66_0F3A_WIG = vexLIG | vex66 | vex0F3A | vexWIG
+	VEX_LIG_F2_0F_W0    = vexLIG | vexF2 | vex0F | vexW0
+	VEX_LIG_F2_0F_W1    = vexLIG | vexF2 | vex0F | vexW1
+	VEX_LIG_F2_0F_WIG   = vexLIG | vexF2 | vex0F | vexWIG
+	VEX_LIG_F3_0F_W0    = vexLIG | vexF3 | vex0F | vexW0
+	VEX_LIG_F3_0F_W1    = vexLIG | vexF3 | vex0F | vexW1
+	VEX_LIG_F3_0F_WIG   = vexLIG | vexF3 | vex0F | vexWIG
+	VEX_LZ_0F_WIG       = vexLZ | vex0F | vexWIG
+	VEX_LZ_0F38_W0      = vexLZ | vex0F38 | vexW0
+	VEX_LZ_0F38_W1      = vexLZ | vex0F38 | vexW1
+	VEX_LZ_66_0F38_W0   = vexLZ | vex66 | vex0F38 | vexW0
+	VEX_LZ_66_0F38_W1   = vexLZ | vex66 | vex0F38 | vexW1
+	VEX_LZ_F2_0F38_W0   = vexLZ | vexF2 | vex0F38 | vexW0
+	VEX_LZ_F2_0F38_W1   = vexLZ | vexF2 | vex0F38 | vexW1
+	VEX_LZ_F2_0F3A_W0   = vexLZ | vexF2 | vex0F3A | vexW0
+	VEX_LZ_F2_0F3A_W1   = vexLZ | vexF2 | vex0F3A | vexW1
+	VEX_LZ_F3_0F38_W0   = vexLZ | vexF3 | vex0F38 | vexW0
+	VEX_LZ_F3_0F38_W1   = vexLZ | vexF3 | vex0F38 | vexW1
 )
 
 var ycover [Ymax * Ymax]uint8
@@ -245,11 +317,6 @@ var ynone = []ytab{
 	{Ynone, Ynone, Ynone, Zlit, 1},
 }
 
-var ysahf = []ytab{
-	{Ynone, Ynone, Ynone, Zlit, 2},
-	{Ynone, Ynone, Ynone, Zlit, 1},
-}
-
 var ytext = []ytab{
 	{Ymb, Ynone, Ytextsize, Zpseudo, 0},
 	{Ymb, Yi32, Ytextsize, Zpseudo, 1},
@@ -610,6 +677,10 @@ var yxm = []ytab{
 	{Yxm, Ynone, Yxr, Zm_r_xm, 1},
 }
 
+var yxm_q4 = []ytab{
+	{Yxm, Ynone, Yxr, Zm_r, 1},
+}
+
 var yxcvm1 = []ytab{
 	{Yxm, Ynone, Yxr, Zm_r_xm, 2},
 	{Yxm, Ynone, Ymr, Zm_r_xm, 2},
@@ -707,6 +778,10 @@ var yextrw = []ytab{
 	{Yu8, Yxr, Yrl, Zibm_r, 2},
 }
 
+var yextr = []ytab{
+	{Yu8, Yxr, Ymm, Zibr_m, 3},
+}
+
 var yinsrw = []ytab{
 	{Yu8, Yml, Yxr, Zibm_r, 2},
 }
@@ -740,6 +815,89 @@ var yaes2 = []ytab{
 	{Yu8, Yxm, Yxr, Zibm_r, 2},
 }
 
+var yxbegin = []ytab{
+	{Ynone, Ynone, Ybr, Zjmp, 1},
+}
+
+var yxabort = []ytab{
+	{Yu8, Ynone, Ynone, Zib_, 1},
+}
+
+var ylddqu = []ytab{
+	{Ym, Ynone, Yxr, Zm_r, 1},
+}
+
+// VEX instructions that come in two forms:
+//	VTHING xmm2/m128, xmmV, xmm1
+//	VTHING ymm2/m256, ymmV, ymm1
+// The opcode array in the corresponding Optab entry
+// should contain the (VEX prefixes, opcode byte) pair
+// for each of the two forms.
+// For example, the entries for VPXOR are:
+//
+//	VPXOR xmm2/m128, xmmV, xmm1
+//	VEX.NDS.128.66.0F.WIG EF /r
+//
+//	VPXOR ymm2/m256, ymmV, ymm1
+//	VEX.NDS.256.66.0F.WIG EF /r
+//
+// The NDS/NDD/DDS part can be dropped, producing this
+// Optab entry:
+//
+//	{AVPXOR, yvex_xy3, Pvex, [23]uint8{VEX_128_66_0F_WIG, 0xEF, VEX_256_66_0F_WIG, 0xEF}}
+//
+var yvex_xy3 = []ytab{
+	{Yxm, Yxr, Yxr, Zvex_rm_v_r, 2},
+	{Yym, Yyr, Yyr, Zvex_rm_v_r, 2},
+}
+
+var yvex_r3 = []ytab{
+	{Yml, Yrl, Yrl, Zvex_rm_v_r, 2},
+	{Yml, Yrl, Yrl, Zvex_rm_v_r, 2},
+}
+
+var yvex_vmr3 = []ytab{
+	{Yrl, Yml, Yrl, Zvex_v_rm_r, 2},
+	{Yrl, Yml, Yrl, Zvex_v_rm_r, 2},
+}
+
+var yvex_xy2 = []ytab{
+	{Yxm, Ynone, Yxr, Zvex_rm_v_r, 2},
+	{Yym, Ynone, Yyr, Zvex_rm_v_r, 2},
+}
+
+var yvex_xyr2 = []ytab{
+	{Yxr, Ynone, Yrl, Zvex_rm_v_r, 2},
+	{Yyr, Ynone, Yrl, Zvex_rm_v_r, 2},
+}
+
+var yvex_vmovdqa = []ytab{
+	{Yxm, Ynone, Yxr, Zvex_rm_v_r, 2},
+	{Yxr, Ynone, Yxm, Zvex_r_v_rm, 2},
+	{Yym, Ynone, Yyr, Zvex_rm_v_r, 2},
+	{Yyr, Ynone, Yym, Zvex_r_v_rm, 2},
+}
+
+var yvex_vmovntdq = []ytab{
+	{Yxr, Ynone, Ym, Zvex_r_v_rm, 2},
+	{Yyr, Ynone, Ym, Zvex_r_v_rm, 2},
+}
+
+var yvex_vpbroadcast = []ytab{
+	{Yxm, Ynone, Yxr, Zvex_rm_v_r, 2},
+	{Yxm, Ynone, Yyr, Zvex_rm_v_r, 2},
+}
+
+var yvex_xxmyxm = []ytab{
+	{Yxr, Ynone, Yxm, Zvex_r_v_rm, 2},
+	{Yyr, Ynone, Yxm, Zvex_r_v_rm, 2},
+}
+
+var ymmxmm0f38 = []ytab{
+	{Ymm, Ynone, Ymr, Zlitm_r, 3},
+	{Yxm, Ynone, Yxr, Zlitm_r, 5},
+}
+
 /*
  * You are doasm, holding in your hand a Prog* with p->as set to, say, ACRC32,
  * and p->from and p->to as operands (Addr*).  The linker scans optab to find
@@ -801,704 +959,779 @@ var yaes2 = []ytab{
 var optab =
 /*	as, ytab, andproto, opcode */
 []Optab{
-	Optab{obj.AXXX, nil, 0, [23]uint8{}},
-	Optab{AAAA, ynone, P32, [23]uint8{0x37}},
-	Optab{AAAD, ynone, P32, [23]uint8{0xd5, 0x0a}},
-	Optab{AAAM, ynone, P32, [23]uint8{0xd4, 0x0a}},
-	Optab{AAAS, ynone, P32, [23]uint8{0x3f}},
-	Optab{AADCB, yxorb, Pb, [23]uint8{0x14, 0x80, 02, 0x10, 0x10}},
-	Optab{AADCL, yxorl, Px, [23]uint8{0x83, 02, 0x15, 0x81, 02, 0x11, 0x13}},
-	Optab{AADCQ, yxorl, Pw, [23]uint8{0x83, 02, 0x15, 0x81, 02, 0x11, 0x13}},
-	Optab{AADCW, yxorl, Pe, [23]uint8{0x83, 02, 0x15, 0x81, 02, 0x11, 0x13}},
-	Optab{AADDB, yxorb, Pb, [23]uint8{0x04, 0x80, 00, 0x00, 0x02}},
-	Optab{AADDL, yaddl, Px, [23]uint8{0x83, 00, 0x05, 0x81, 00, 0x01, 0x03}},
-	Optab{AADDPD, yxm, Pq, [23]uint8{0x58}},
-	Optab{AADDPS, yxm, Pm, [23]uint8{0x58}},
-	Optab{AADDQ, yaddl, Pw, [23]uint8{0x83, 00, 0x05, 0x81, 00, 0x01, 0x03}},
-	Optab{AADDSD, yxm, Pf2, [23]uint8{0x58}},
-	Optab{AADDSS, yxm, Pf3, [23]uint8{0x58}},
-	Optab{AADDW, yaddl, Pe, [23]uint8{0x83, 00, 0x05, 0x81, 00, 0x01, 0x03}},
-	Optab{AADJSP, nil, 0, [23]uint8{}},
-	Optab{AANDB, yxorb, Pb, [23]uint8{0x24, 0x80, 04, 0x20, 0x22}},
-	Optab{AANDL, yxorl, Px, [23]uint8{0x83, 04, 0x25, 0x81, 04, 0x21, 0x23}},
-	Optab{AANDNPD, yxm, Pq, [23]uint8{0x55}},
-	Optab{AANDNPS, yxm, Pm, [23]uint8{0x55}},
-	Optab{AANDPD, yxm, Pq, [23]uint8{0x54}},
-	Optab{AANDPS, yxm, Pq, [23]uint8{0x54}},
-	Optab{AANDQ, yxorl, Pw, [23]uint8{0x83, 04, 0x25, 0x81, 04, 0x21, 0x23}},
-	Optab{AANDW, yxorl, Pe, [23]uint8{0x83, 04, 0x25, 0x81, 04, 0x21, 0x23}},
-	Optab{AARPL, yrl_ml, P32, [23]uint8{0x63}},
-	Optab{ABOUNDL, yrl_m, P32, [23]uint8{0x62}},
-	Optab{ABOUNDW, yrl_m, Pe, [23]uint8{0x62}},
-	Optab{ABSFL, yml_rl, Pm, [23]uint8{0xbc}},
-	Optab{ABSFQ, yml_rl, Pw, [23]uint8{0x0f, 0xbc}},
-	Optab{ABSFW, yml_rl, Pq, [23]uint8{0xbc}},
-	Optab{ABSRL, yml_rl, Pm, [23]uint8{0xbd}},
-	Optab{ABSRQ, yml_rl, Pw, [23]uint8{0x0f, 0xbd}},
-	Optab{ABSRW, yml_rl, Pq, [23]uint8{0xbd}},
-	Optab{ABSWAPL, ybswap, Px, [23]uint8{0x0f, 0xc8}},
-	Optab{ABSWAPQ, ybswap, Pw, [23]uint8{0x0f, 0xc8}},
-	Optab{ABTCL, ybtl, Pm, [23]uint8{0xba, 07, 0xbb}},
-	Optab{ABTCQ, ybtl, Pw, [23]uint8{0x0f, 0xba, 07, 0x0f, 0xbb}},
-	Optab{ABTCW, ybtl, Pq, [23]uint8{0xba, 07, 0xbb}},
-	Optab{ABTL, ybtl, Pm, [23]uint8{0xba, 04, 0xa3}},
-	Optab{ABTQ, ybtl, Pw, [23]uint8{0x0f, 0xba, 04, 0x0f, 0xa3}},
-	Optab{ABTRL, ybtl, Pm, [23]uint8{0xba, 06, 0xb3}},
-	Optab{ABTRQ, ybtl, Pw, [23]uint8{0x0f, 0xba, 06, 0x0f, 0xb3}},
-	Optab{ABTRW, ybtl, Pq, [23]uint8{0xba, 06, 0xb3}},
-	Optab{ABTSL, ybtl, Pm, [23]uint8{0xba, 05, 0xab}},
-	Optab{ABTSQ, ybtl, Pw, [23]uint8{0x0f, 0xba, 05, 0x0f, 0xab}},
-	Optab{ABTSW, ybtl, Pq, [23]uint8{0xba, 05, 0xab}},
-	Optab{ABTW, ybtl, Pq, [23]uint8{0xba, 04, 0xa3}},
-	Optab{ABYTE, ybyte, Px, [23]uint8{1}},
-	Optab{obj.ACALL, ycall, Px, [23]uint8{0xff, 02, 0xff, 0x15, 0xe8}},
-	Optab{ACDQ, ynone, Px, [23]uint8{0x99}},
-	Optab{ACLC, ynone, Px, [23]uint8{0xf8}},
-	Optab{ACLD, ynone, Px, [23]uint8{0xfc}},
-	Optab{ACLI, ynone, Px, [23]uint8{0xfa}},
-	Optab{ACLTS, ynone, Pm, [23]uint8{0x06}},
-	Optab{ACMC, ynone, Px, [23]uint8{0xf5}},
-	Optab{ACMOVLCC, yml_rl, Pm, [23]uint8{0x43}},
-	Optab{ACMOVLCS, yml_rl, Pm, [23]uint8{0x42}},
-	Optab{ACMOVLEQ, yml_rl, Pm, [23]uint8{0x44}},
-	Optab{ACMOVLGE, yml_rl, Pm, [23]uint8{0x4d}},
-	Optab{ACMOVLGT, yml_rl, Pm, [23]uint8{0x4f}},
-	Optab{ACMOVLHI, yml_rl, Pm, [23]uint8{0x47}},
-	Optab{ACMOVLLE, yml_rl, Pm, [23]uint8{0x4e}},
-	Optab{ACMOVLLS, yml_rl, Pm, [23]uint8{0x46}},
-	Optab{ACMOVLLT, yml_rl, Pm, [23]uint8{0x4c}},
-	Optab{ACMOVLMI, yml_rl, Pm, [23]uint8{0x48}},
-	Optab{ACMOVLNE, yml_rl, Pm, [23]uint8{0x45}},
-	Optab{ACMOVLOC, yml_rl, Pm, [23]uint8{0x41}},
-	Optab{ACMOVLOS, yml_rl, Pm, [23]uint8{0x40}},
-	Optab{ACMOVLPC, yml_rl, Pm, [23]uint8{0x4b}},
-	Optab{ACMOVLPL, yml_rl, Pm, [23]uint8{0x49}},
-	Optab{ACMOVLPS, yml_rl, Pm, [23]uint8{0x4a}},
-	Optab{ACMOVQCC, yml_rl, Pw, [23]uint8{0x0f, 0x43}},
-	Optab{ACMOVQCS, yml_rl, Pw, [23]uint8{0x0f, 0x42}},
-	Optab{ACMOVQEQ, yml_rl, Pw, [23]uint8{0x0f, 0x44}},
-	Optab{ACMOVQGE, yml_rl, Pw, [23]uint8{0x0f, 0x4d}},
-	Optab{ACMOVQGT, yml_rl, Pw, [23]uint8{0x0f, 0x4f}},
-	Optab{ACMOVQHI, yml_rl, Pw, [23]uint8{0x0f, 0x47}},
-	Optab{ACMOVQLE, yml_rl, Pw, [23]uint8{0x0f, 0x4e}},
-	Optab{ACMOVQLS, yml_rl, Pw, [23]uint8{0x0f, 0x46}},
-	Optab{ACMOVQLT, yml_rl, Pw, [23]uint8{0x0f, 0x4c}},
-	Optab{ACMOVQMI, yml_rl, Pw, [23]uint8{0x0f, 0x48}},
-	Optab{ACMOVQNE, yml_rl, Pw, [23]uint8{0x0f, 0x45}},
-	Optab{ACMOVQOC, yml_rl, Pw, [23]uint8{0x0f, 0x41}},
-	Optab{ACMOVQOS, yml_rl, Pw, [23]uint8{0x0f, 0x40}},
-	Optab{ACMOVQPC, yml_rl, Pw, [23]uint8{0x0f, 0x4b}},
-	Optab{ACMOVQPL, yml_rl, Pw, [23]uint8{0x0f, 0x49}},
-	Optab{ACMOVQPS, yml_rl, Pw, [23]uint8{0x0f, 0x4a}},
-	Optab{ACMOVWCC, yml_rl, Pq, [23]uint8{0x43}},
-	Optab{ACMOVWCS, yml_rl, Pq, [23]uint8{0x42}},
-	Optab{ACMOVWEQ, yml_rl, Pq, [23]uint8{0x44}},
-	Optab{ACMOVWGE, yml_rl, Pq, [23]uint8{0x4d}},
-	Optab{ACMOVWGT, yml_rl, Pq, [23]uint8{0x4f}},
-	Optab{ACMOVWHI, yml_rl, Pq, [23]uint8{0x47}},
-	Optab{ACMOVWLE, yml_rl, Pq, [23]uint8{0x4e}},
-	Optab{ACMOVWLS, yml_rl, Pq, [23]uint8{0x46}},
-	Optab{ACMOVWLT, yml_rl, Pq, [23]uint8{0x4c}},
-	Optab{ACMOVWMI, yml_rl, Pq, [23]uint8{0x48}},
-	Optab{ACMOVWNE, yml_rl, Pq, [23]uint8{0x45}},
-	Optab{ACMOVWOC, yml_rl, Pq, [23]uint8{0x41}},
-	Optab{ACMOVWOS, yml_rl, Pq, [23]uint8{0x40}},
-	Optab{ACMOVWPC, yml_rl, Pq, [23]uint8{0x4b}},
-	Optab{ACMOVWPL, yml_rl, Pq, [23]uint8{0x49}},
-	Optab{ACMOVWPS, yml_rl, Pq, [23]uint8{0x4a}},
-	Optab{ACMPB, ycmpb, Pb, [23]uint8{0x3c, 0x80, 07, 0x38, 0x3a}},
-	Optab{ACMPL, ycmpl, Px, [23]uint8{0x83, 07, 0x3d, 0x81, 07, 0x39, 0x3b}},
-	Optab{ACMPPD, yxcmpi, Px, [23]uint8{Pe, 0xc2}},
-	Optab{ACMPPS, yxcmpi, Pm, [23]uint8{0xc2, 0}},
-	Optab{ACMPQ, ycmpl, Pw, [23]uint8{0x83, 07, 0x3d, 0x81, 07, 0x39, 0x3b}},
-	Optab{ACMPSB, ynone, Pb, [23]uint8{0xa6}},
-	Optab{ACMPSD, yxcmpi, Px, [23]uint8{Pf2, 0xc2}},
-	Optab{ACMPSL, ynone, Px, [23]uint8{0xa7}},
-	Optab{ACMPSQ, ynone, Pw, [23]uint8{0xa7}},
-	Optab{ACMPSS, yxcmpi, Px, [23]uint8{Pf3, 0xc2}},
-	Optab{ACMPSW, ynone, Pe, [23]uint8{0xa7}},
-	Optab{ACMPW, ycmpl, Pe, [23]uint8{0x83, 07, 0x3d, 0x81, 07, 0x39, 0x3b}},
-	Optab{ACOMISD, yxcmp, Pe, [23]uint8{0x2f}},
-	Optab{ACOMISS, yxcmp, Pm, [23]uint8{0x2f}},
-	Optab{ACPUID, ynone, Pm, [23]uint8{0xa2}},
-	Optab{ACVTPL2PD, yxcvm2, Px, [23]uint8{Pf3, 0xe6, Pe, 0x2a}},
-	Optab{ACVTPL2PS, yxcvm2, Pm, [23]uint8{0x5b, 0, 0x2a, 0}},
-	Optab{ACVTPD2PL, yxcvm1, Px, [23]uint8{Pf2, 0xe6, Pe, 0x2d}},
-	Optab{ACVTPD2PS, yxm, Pe, [23]uint8{0x5a}},
-	Optab{ACVTPS2PL, yxcvm1, Px, [23]uint8{Pe, 0x5b, Pm, 0x2d}},
-	Optab{ACVTPS2PD, yxm, Pm, [23]uint8{0x5a}},
-	Optab{API2FW, ymfp, Px, [23]uint8{0x0c}},
-	Optab{ACVTSD2SL, yxcvfl, Pf2, [23]uint8{0x2d}},
-	Optab{ACVTSD2SQ, yxcvfq, Pw, [23]uint8{Pf2, 0x2d}},
-	Optab{ACVTSD2SS, yxm, Pf2, [23]uint8{0x5a}},
-	Optab{ACVTSL2SD, yxcvlf, Pf2, [23]uint8{0x2a}},
-	Optab{ACVTSQ2SD, yxcvqf, Pw, [23]uint8{Pf2, 0x2a}},
-	Optab{ACVTSL2SS, yxcvlf, Pf3, [23]uint8{0x2a}},
-	Optab{ACVTSQ2SS, yxcvqf, Pw, [23]uint8{Pf3, 0x2a}},
-	Optab{ACVTSS2SD, yxm, Pf3, [23]uint8{0x5a}},
-	Optab{ACVTSS2SL, yxcvfl, Pf3, [23]uint8{0x2d}},
-	Optab{ACVTSS2SQ, yxcvfq, Pw, [23]uint8{Pf3, 0x2d}},
-	Optab{ACVTTPD2PL, yxcvm1, Px, [23]uint8{Pe, 0xe6, Pe, 0x2c}},
-	Optab{ACVTTPS2PL, yxcvm1, Px, [23]uint8{Pf3, 0x5b, Pm, 0x2c}},
-	Optab{ACVTTSD2SL, yxcvfl, Pf2, [23]uint8{0x2c}},
-	Optab{ACVTTSD2SQ, yxcvfq, Pw, [23]uint8{Pf2, 0x2c}},
-	Optab{ACVTTSS2SL, yxcvfl, Pf3, [23]uint8{0x2c}},
-	Optab{ACVTTSS2SQ, yxcvfq, Pw, [23]uint8{Pf3, 0x2c}},
-	Optab{ACWD, ynone, Pe, [23]uint8{0x99}},
-	Optab{ACQO, ynone, Pw, [23]uint8{0x99}},
-	Optab{ADAA, ynone, P32, [23]uint8{0x27}},
-	Optab{ADAS, ynone, P32, [23]uint8{0x2f}},
-	Optab{obj.ADATA, nil, 0, [23]uint8{}},
-	Optab{ADECB, yincb, Pb, [23]uint8{0xfe, 01}},
-	Optab{ADECL, yincl, Px1, [23]uint8{0x48, 0xff, 01}},
-	Optab{ADECQ, yincq, Pw, [23]uint8{0xff, 01}},
-	Optab{ADECW, yincw, Pe, [23]uint8{0xff, 01}},
-	Optab{ADIVB, ydivb, Pb, [23]uint8{0xf6, 06}},
-	Optab{ADIVL, ydivl, Px, [23]uint8{0xf7, 06}},
-	Optab{ADIVPD, yxm, Pe, [23]uint8{0x5e}},
-	Optab{ADIVPS, yxm, Pm, [23]uint8{0x5e}},
-	Optab{ADIVQ, ydivl, Pw, [23]uint8{0xf7, 06}},
-	Optab{ADIVSD, yxm, Pf2, [23]uint8{0x5e}},
-	Optab{ADIVSS, yxm, Pf3, [23]uint8{0x5e}},
-	Optab{ADIVW, ydivl, Pe, [23]uint8{0xf7, 06}},
-	Optab{AEMMS, ynone, Pm, [23]uint8{0x77}},
-	Optab{AENTER, nil, 0, [23]uint8{}}, /* botch */
-	Optab{AFXRSTOR, ysvrs, Pm, [23]uint8{0xae, 01, 0xae, 01}},
-	Optab{AFXSAVE, ysvrs, Pm, [23]uint8{0xae, 00, 0xae, 00}},
-	Optab{AFXRSTOR64, ysvrs, Pw, [23]uint8{0x0f, 0xae, 01, 0x0f, 0xae, 01}},
-	Optab{AFXSAVE64, ysvrs, Pw, [23]uint8{0x0f, 0xae, 00, 0x0f, 0xae, 00}},
-	Optab{obj.AGLOBL, nil, 0, [23]uint8{}},
-	Optab{AHLT, ynone, Px, [23]uint8{0xf4}},
-	Optab{AIDIVB, ydivb, Pb, [23]uint8{0xf6, 07}},
-	Optab{AIDIVL, ydivl, Px, [23]uint8{0xf7, 07}},
-	Optab{AIDIVQ, ydivl, Pw, [23]uint8{0xf7, 07}},
-	Optab{AIDIVW, ydivl, Pe, [23]uint8{0xf7, 07}},
-	Optab{AIMULB, ydivb, Pb, [23]uint8{0xf6, 05}},
-	Optab{AIMULL, yimul, Px, [23]uint8{0xf7, 05, 0x6b, 0x69, Pm, 0xaf}},
-	Optab{AIMULQ, yimul, Pw, [23]uint8{0xf7, 05, 0x6b, 0x69, Pm, 0xaf}},
-	Optab{AIMULW, yimul, Pe, [23]uint8{0xf7, 05, 0x6b, 0x69, Pm, 0xaf}},
-	Optab{AIMUL3Q, yimul3, Pw, [23]uint8{0x6b, 00}},
-	Optab{AINB, yin, Pb, [23]uint8{0xe4, 0xec}},
-	Optab{AINCB, yincb, Pb, [23]uint8{0xfe, 00}},
-	Optab{AINCL, yincl, Px1, [23]uint8{0x40, 0xff, 00}},
-	Optab{AINCQ, yincq, Pw, [23]uint8{0xff, 00}},
-	Optab{AINCW, yincw, Pe, [23]uint8{0xff, 00}},
-	Optab{AINL, yin, Px, [23]uint8{0xe5, 0xed}},
-	Optab{AINSB, ynone, Pb, [23]uint8{0x6c}},
-	Optab{AINSL, ynone, Px, [23]uint8{0x6d}},
-	Optab{AINSW, ynone, Pe, [23]uint8{0x6d}},
-	Optab{AINT, yint, Px, [23]uint8{0xcd}},
-	Optab{AINTO, ynone, P32, [23]uint8{0xce}},
-	Optab{AINW, yin, Pe, [23]uint8{0xe5, 0xed}},
-	Optab{AIRETL, ynone, Px, [23]uint8{0xcf}},
-	Optab{AIRETQ, ynone, Pw, [23]uint8{0xcf}},
-	Optab{AIRETW, ynone, Pe, [23]uint8{0xcf}},
-	Optab{AJCC, yjcond, Px, [23]uint8{0x73, 0x83, 00}},
-	Optab{AJCS, yjcond, Px, [23]uint8{0x72, 0x82}},
-	Optab{AJCXZL, yloop, Px, [23]uint8{0xe3}},
-	Optab{AJCXZW, yloop, Px, [23]uint8{0xe3}},
-	Optab{AJCXZQ, yloop, Px, [23]uint8{0xe3}},
-	Optab{AJEQ, yjcond, Px, [23]uint8{0x74, 0x84}},
-	Optab{AJGE, yjcond, Px, [23]uint8{0x7d, 0x8d}},
-	Optab{AJGT, yjcond, Px, [23]uint8{0x7f, 0x8f}},
-	Optab{AJHI, yjcond, Px, [23]uint8{0x77, 0x87}},
-	Optab{AJLE, yjcond, Px, [23]uint8{0x7e, 0x8e}},
-	Optab{AJLS, yjcond, Px, [23]uint8{0x76, 0x86}},
-	Optab{AJLT, yjcond, Px, [23]uint8{0x7c, 0x8c}},
-	Optab{AJMI, yjcond, Px, [23]uint8{0x78, 0x88}},
-	Optab{obj.AJMP, yjmp, Px, [23]uint8{0xff, 04, 0xeb, 0xe9}},
-	Optab{AJNE, yjcond, Px, [23]uint8{0x75, 0x85}},
-	Optab{AJOC, yjcond, Px, [23]uint8{0x71, 0x81, 00}},
-	Optab{AJOS, yjcond, Px, [23]uint8{0x70, 0x80, 00}},
-	Optab{AJPC, yjcond, Px, [23]uint8{0x7b, 0x8b}},
-	Optab{AJPL, yjcond, Px, [23]uint8{0x79, 0x89}},
-	Optab{AJPS, yjcond, Px, [23]uint8{0x7a, 0x8a}},
-	Optab{ALAHF, ynone, Px, [23]uint8{0x9f}},
-	Optab{ALARL, yml_rl, Pm, [23]uint8{0x02}},
-	Optab{ALARW, yml_rl, Pq, [23]uint8{0x02}},
-	Optab{ALDMXCSR, ysvrs, Pm, [23]uint8{0xae, 02, 0xae, 02}},
-	Optab{ALEAL, ym_rl, Px, [23]uint8{0x8d}},
-	Optab{ALEAQ, ym_rl, Pw, [23]uint8{0x8d}},
-	Optab{ALEAVEL, ynone, P32, [23]uint8{0xc9}},
-	Optab{ALEAVEQ, ynone, Py, [23]uint8{0xc9}},
-	Optab{ALEAVEW, ynone, Pe, [23]uint8{0xc9}},
-	Optab{ALEAW, ym_rl, Pe, [23]uint8{0x8d}},
-	Optab{ALOCK, ynone, Px, [23]uint8{0xf0}},
-	Optab{ALODSB, ynone, Pb, [23]uint8{0xac}},
-	Optab{ALODSL, ynone, Px, [23]uint8{0xad}},
-	Optab{ALODSQ, ynone, Pw, [23]uint8{0xad}},
-	Optab{ALODSW, ynone, Pe, [23]uint8{0xad}},
-	Optab{ALONG, ybyte, Px, [23]uint8{4}},
-	Optab{ALOOP, yloop, Px, [23]uint8{0xe2}},
-	Optab{ALOOPEQ, yloop, Px, [23]uint8{0xe1}},
-	Optab{ALOOPNE, yloop, Px, [23]uint8{0xe0}},
-	Optab{ALSLL, yml_rl, Pm, [23]uint8{0x03}},
-	Optab{ALSLW, yml_rl, Pq, [23]uint8{0x03}},
-	Optab{AMASKMOVOU, yxr, Pe, [23]uint8{0xf7}},
-	Optab{AMASKMOVQ, ymr, Pm, [23]uint8{0xf7}},
-	Optab{AMAXPD, yxm, Pe, [23]uint8{0x5f}},
-	Optab{AMAXPS, yxm, Pm, [23]uint8{0x5f}},
-	Optab{AMAXSD, yxm, Pf2, [23]uint8{0x5f}},
-	Optab{AMAXSS, yxm, Pf3, [23]uint8{0x5f}},
-	Optab{AMINPD, yxm, Pe, [23]uint8{0x5d}},
-	Optab{AMINPS, yxm, Pm, [23]uint8{0x5d}},
-	Optab{AMINSD, yxm, Pf2, [23]uint8{0x5d}},
-	Optab{AMINSS, yxm, Pf3, [23]uint8{0x5d}},
-	Optab{AMOVAPD, yxmov, Pe, [23]uint8{0x28, 0x29}},
-	Optab{AMOVAPS, yxmov, Pm, [23]uint8{0x28, 0x29}},
-	Optab{AMOVB, ymovb, Pb, [23]uint8{0x88, 0x8a, 0xb0, 0xc6, 00}},
-	Optab{AMOVBLSX, ymb_rl, Pm, [23]uint8{0xbe}},
-	Optab{AMOVBLZX, ymb_rl, Pm, [23]uint8{0xb6}},
-	Optab{AMOVBQSX, ymb_rl, Pw, [23]uint8{0x0f, 0xbe}},
-	Optab{AMOVBQZX, ymb_rl, Pm, [23]uint8{0xb6}},
-	Optab{AMOVBWSX, ymb_rl, Pq, [23]uint8{0xbe}},
-	Optab{AMOVBWZX, ymb_rl, Pq, [23]uint8{0xb6}},
-	Optab{AMOVO, yxmov, Pe, [23]uint8{0x6f, 0x7f}},
-	Optab{AMOVOU, yxmov, Pf3, [23]uint8{0x6f, 0x7f}},
-	Optab{AMOVHLPS, yxr, Pm, [23]uint8{0x12}},
-	Optab{AMOVHPD, yxmov, Pe, [23]uint8{0x16, 0x17}},
-	Optab{AMOVHPS, yxmov, Pm, [23]uint8{0x16, 0x17}},
-	Optab{AMOVL, ymovl, Px, [23]uint8{0x89, 0x8b, 0x31, 0xb8, 0xc7, 00, 0x6e, 0x7e, Pe, 0x6e, Pe, 0x7e, 0}},
-	Optab{AMOVLHPS, yxr, Pm, [23]uint8{0x16}},
-	Optab{AMOVLPD, yxmov, Pe, [23]uint8{0x12, 0x13}},
-	Optab{AMOVLPS, yxmov, Pm, [23]uint8{0x12, 0x13}},
-	Optab{AMOVLQSX, yml_rl, Pw, [23]uint8{0x63}},
-	Optab{AMOVLQZX, yml_rl, Px, [23]uint8{0x8b}},
-	Optab{AMOVMSKPD, yxrrl, Pq, [23]uint8{0x50}},
-	Optab{AMOVMSKPS, yxrrl, Pm, [23]uint8{0x50}},
-	Optab{AMOVNTO, yxr_ml, Pe, [23]uint8{0xe7}},
-	Optab{AMOVNTPD, yxr_ml, Pe, [23]uint8{0x2b}},
-	Optab{AMOVNTPS, yxr_ml, Pm, [23]uint8{0x2b}},
-	Optab{AMOVNTQ, ymr_ml, Pm, [23]uint8{0xe7}},
-	Optab{AMOVQ, ymovq, Pw8, [23]uint8{0x6f, 0x7f, Pf2, 0xd6, Pf3, 0x7e, Pe, 0xd6, 0x89, 0x8b, 0x31, 0xc7, 00, 0xb8, 0xc7, 00, 0x6e, 0x7e, Pe, 0x6e, Pe, 0x7e, 0}},
-	Optab{AMOVQOZX, ymrxr, Pf3, [23]uint8{0xd6, 0x7e}},
-	Optab{AMOVSB, ynone, Pb, [23]uint8{0xa4}},
-	Optab{AMOVSD, yxmov, Pf2, [23]uint8{0x10, 0x11}},
-	Optab{AMOVSL, ynone, Px, [23]uint8{0xa5}},
-	Optab{AMOVSQ, ynone, Pw, [23]uint8{0xa5}},
-	Optab{AMOVSS, yxmov, Pf3, [23]uint8{0x10, 0x11}},
-	Optab{AMOVSW, ynone, Pe, [23]uint8{0xa5}},
-	Optab{AMOVUPD, yxmov, Pe, [23]uint8{0x10, 0x11}},
-	Optab{AMOVUPS, yxmov, Pm, [23]uint8{0x10, 0x11}},
-	Optab{AMOVW, ymovw, Pe, [23]uint8{0x89, 0x8b, 0x31, 0xb8, 0xc7, 00, 0}},
-	Optab{AMOVWLSX, yml_rl, Pm, [23]uint8{0xbf}},
-	Optab{AMOVWLZX, yml_rl, Pm, [23]uint8{0xb7}},
-	Optab{AMOVWQSX, yml_rl, Pw, [23]uint8{0x0f, 0xbf}},
-	Optab{AMOVWQZX, yml_rl, Pw, [23]uint8{0x0f, 0xb7}},
-	Optab{AMULB, ydivb, Pb, [23]uint8{0xf6, 04}},
-	Optab{AMULL, ydivl, Px, [23]uint8{0xf7, 04}},
-	Optab{AMULPD, yxm, Pe, [23]uint8{0x59}},
-	Optab{AMULPS, yxm, Ym, [23]uint8{0x59}},
-	Optab{AMULQ, ydivl, Pw, [23]uint8{0xf7, 04}},
-	Optab{AMULSD, yxm, Pf2, [23]uint8{0x59}},
-	Optab{AMULSS, yxm, Pf3, [23]uint8{0x59}},
-	Optab{AMULW, ydivl, Pe, [23]uint8{0xf7, 04}},
-	Optab{ANEGB, yscond, Pb, [23]uint8{0xf6, 03}},
-	Optab{ANEGL, yscond, Px, [23]uint8{0xf7, 03}},
-	Optab{ANEGQ, yscond, Pw, [23]uint8{0xf7, 03}},
-	Optab{ANEGW, yscond, Pe, [23]uint8{0xf7, 03}},
-	Optab{obj.ANOP, ynop, Px, [23]uint8{0, 0}},
-	Optab{ANOTB, yscond, Pb, [23]uint8{0xf6, 02}},
-	Optab{ANOTL, yscond, Px, [23]uint8{0xf7, 02}}, // TODO(rsc): yscond is wrong here.
-	Optab{ANOTQ, yscond, Pw, [23]uint8{0xf7, 02}},
-	Optab{ANOTW, yscond, Pe, [23]uint8{0xf7, 02}},
-	Optab{AORB, yxorb, Pb, [23]uint8{0x0c, 0x80, 01, 0x08, 0x0a}},
-	Optab{AORL, yxorl, Px, [23]uint8{0x83, 01, 0x0d, 0x81, 01, 0x09, 0x0b}},
-	Optab{AORPD, yxm, Pq, [23]uint8{0x56}},
-	Optab{AORPS, yxm, Pm, [23]uint8{0x56}},
-	Optab{AORQ, yxorl, Pw, [23]uint8{0x83, 01, 0x0d, 0x81, 01, 0x09, 0x0b}},
-	Optab{AORW, yxorl, Pe, [23]uint8{0x83, 01, 0x0d, 0x81, 01, 0x09, 0x0b}},
-	Optab{AOUTB, yin, Pb, [23]uint8{0xe6, 0xee}},
-	Optab{AOUTL, yin, Px, [23]uint8{0xe7, 0xef}},
-	Optab{AOUTSB, ynone, Pb, [23]uint8{0x6e}},
-	Optab{AOUTSL, ynone, Px, [23]uint8{0x6f}},
-	Optab{AOUTSW, ynone, Pe, [23]uint8{0x6f}},
-	Optab{AOUTW, yin, Pe, [23]uint8{0xe7, 0xef}},
-	Optab{APACKSSLW, ymm, Py1, [23]uint8{0x6b, Pe, 0x6b}},
-	Optab{APACKSSWB, ymm, Py1, [23]uint8{0x63, Pe, 0x63}},
-	Optab{APACKUSWB, ymm, Py1, [23]uint8{0x67, Pe, 0x67}},
-	Optab{APADDB, ymm, Py1, [23]uint8{0xfc, Pe, 0xfc}},
-	Optab{APADDL, ymm, Py1, [23]uint8{0xfe, Pe, 0xfe}},
-	Optab{APADDQ, yxm, Pe, [23]uint8{0xd4}},
-	Optab{APADDSB, ymm, Py1, [23]uint8{0xec, Pe, 0xec}},
-	Optab{APADDSW, ymm, Py1, [23]uint8{0xed, Pe, 0xed}},
-	Optab{APADDUSB, ymm, Py1, [23]uint8{0xdc, Pe, 0xdc}},
-	Optab{APADDUSW, ymm, Py1, [23]uint8{0xdd, Pe, 0xdd}},
-	Optab{APADDW, ymm, Py1, [23]uint8{0xfd, Pe, 0xfd}},
-	Optab{APAND, ymm, Py1, [23]uint8{0xdb, Pe, 0xdb}},
-	Optab{APANDN, ymm, Py1, [23]uint8{0xdf, Pe, 0xdf}},
-	Optab{APAUSE, ynone, Px, [23]uint8{0xf3, 0x90}},
-	Optab{APAVGB, ymm, Py1, [23]uint8{0xe0, Pe, 0xe0}},
-	Optab{APAVGW, ymm, Py1, [23]uint8{0xe3, Pe, 0xe3}},
-	Optab{APCMPEQB, ymm, Py1, [23]uint8{0x74, Pe, 0x74}},
-	Optab{APCMPEQL, ymm, Py1, [23]uint8{0x76, Pe, 0x76}},
-	Optab{APCMPEQW, ymm, Py1, [23]uint8{0x75, Pe, 0x75}},
-	Optab{APCMPGTB, ymm, Py1, [23]uint8{0x64, Pe, 0x64}},
-	Optab{APCMPGTL, ymm, Py1, [23]uint8{0x66, Pe, 0x66}},
-	Optab{APCMPGTW, ymm, Py1, [23]uint8{0x65, Pe, 0x65}},
-	Optab{APEXTRW, yextrw, Pq, [23]uint8{0xc5, 00}},
-	Optab{APF2IL, ymfp, Px, [23]uint8{0x1d}},
-	Optab{APF2IW, ymfp, Px, [23]uint8{0x1c}},
-	Optab{API2FL, ymfp, Px, [23]uint8{0x0d}},
-	Optab{APFACC, ymfp, Px, [23]uint8{0xae}},
-	Optab{APFADD, ymfp, Px, [23]uint8{0x9e}},
-	Optab{APFCMPEQ, ymfp, Px, [23]uint8{0xb0}},
-	Optab{APFCMPGE, ymfp, Px, [23]uint8{0x90}},
-	Optab{APFCMPGT, ymfp, Px, [23]uint8{0xa0}},
-	Optab{APFMAX, ymfp, Px, [23]uint8{0xa4}},
-	Optab{APFMIN, ymfp, Px, [23]uint8{0x94}},
-	Optab{APFMUL, ymfp, Px, [23]uint8{0xb4}},
-	Optab{APFNACC, ymfp, Px, [23]uint8{0x8a}},
-	Optab{APFPNACC, ymfp, Px, [23]uint8{0x8e}},
-	Optab{APFRCP, ymfp, Px, [23]uint8{0x96}},
-	Optab{APFRCPIT1, ymfp, Px, [23]uint8{0xa6}},
-	Optab{APFRCPI2T, ymfp, Px, [23]uint8{0xb6}},
-	Optab{APFRSQIT1, ymfp, Px, [23]uint8{0xa7}},
-	Optab{APFRSQRT, ymfp, Px, [23]uint8{0x97}},
-	Optab{APFSUB, ymfp, Px, [23]uint8{0x9a}},
-	Optab{APFSUBR, ymfp, Px, [23]uint8{0xaa}},
-	Optab{APINSRW, yinsrw, Pq, [23]uint8{0xc4, 00}},
-	Optab{APINSRD, yinsr, Pq, [23]uint8{0x3a, 0x22, 00}},
-	Optab{APINSRQ, yinsr, Pq3, [23]uint8{0x3a, 0x22, 00}},
-	Optab{APMADDWL, ymm, Py1, [23]uint8{0xf5, Pe, 0xf5}},
-	Optab{APMAXSW, yxm, Pe, [23]uint8{0xee}},
-	Optab{APMAXUB, yxm, Pe, [23]uint8{0xde}},
-	Optab{APMINSW, yxm, Pe, [23]uint8{0xea}},
-	Optab{APMINUB, yxm, Pe, [23]uint8{0xda}},
-	Optab{APMOVMSKB, ymskb, Px, [23]uint8{Pe, 0xd7, 0xd7}},
-	Optab{APMULHRW, ymfp, Px, [23]uint8{0xb7}},
-	Optab{APMULHUW, ymm, Py1, [23]uint8{0xe4, Pe, 0xe4}},
-	Optab{APMULHW, ymm, Py1, [23]uint8{0xe5, Pe, 0xe5}},
-	Optab{APMULLW, ymm, Py1, [23]uint8{0xd5, Pe, 0xd5}},
-	Optab{APMULULQ, ymm, Py1, [23]uint8{0xf4, Pe, 0xf4}},
-	Optab{APOPAL, ynone, P32, [23]uint8{0x61}},
-	Optab{APOPAW, ynone, Pe, [23]uint8{0x61}},
-	Optab{APOPFL, ynone, P32, [23]uint8{0x9d}},
-	Optab{APOPFQ, ynone, Py, [23]uint8{0x9d}},
-	Optab{APOPFW, ynone, Pe, [23]uint8{0x9d}},
-	Optab{APOPL, ypopl, P32, [23]uint8{0x58, 0x8f, 00}},
-	Optab{APOPQ, ypopl, Py, [23]uint8{0x58, 0x8f, 00}},
-	Optab{APOPW, ypopl, Pe, [23]uint8{0x58, 0x8f, 00}},
-	Optab{APOR, ymm, Py1, [23]uint8{0xeb, Pe, 0xeb}},
-	Optab{APSADBW, yxm, Pq, [23]uint8{0xf6}},
-	Optab{APSHUFHW, yxshuf, Pf3, [23]uint8{0x70, 00}},
-	Optab{APSHUFL, yxshuf, Pq, [23]uint8{0x70, 00}},
-	Optab{APSHUFLW, yxshuf, Pf2, [23]uint8{0x70, 00}},
-	Optab{APSHUFW, ymshuf, Pm, [23]uint8{0x70, 00}},
-	Optab{APSHUFB, ymshufb, Pq, [23]uint8{0x38, 0x00}},
-	Optab{APSLLO, ypsdq, Pq, [23]uint8{0x73, 07}},
-	Optab{APSLLL, yps, Py3, [23]uint8{0xf2, 0x72, 06, Pe, 0xf2, Pe, 0x72, 06}},
-	Optab{APSLLQ, yps, Py3, [23]uint8{0xf3, 0x73, 06, Pe, 0xf3, Pe, 0x73, 06}},
-	Optab{APSLLW, yps, Py3, [23]uint8{0xf1, 0x71, 06, Pe, 0xf1, Pe, 0x71, 06}},
-	Optab{APSRAL, yps, Py3, [23]uint8{0xe2, 0x72, 04, Pe, 0xe2, Pe, 0x72, 04}},
-	Optab{APSRAW, yps, Py3, [23]uint8{0xe1, 0x71, 04, Pe, 0xe1, Pe, 0x71, 04}},
-	Optab{APSRLO, ypsdq, Pq, [23]uint8{0x73, 03}},
-	Optab{APSRLL, yps, Py3, [23]uint8{0xd2, 0x72, 02, Pe, 0xd2, Pe, 0x72, 02}},
-	Optab{APSRLQ, yps, Py3, [23]uint8{0xd3, 0x73, 02, Pe, 0xd3, Pe, 0x73, 02}},
-	Optab{APSRLW, yps, Py3, [23]uint8{0xd1, 0x71, 02, Pe, 0xe1, Pe, 0x71, 02}},
-	Optab{APSUBB, yxm, Pe, [23]uint8{0xf8}},
-	Optab{APSUBL, yxm, Pe, [23]uint8{0xfa}},
-	Optab{APSUBQ, yxm, Pe, [23]uint8{0xfb}},
-	Optab{APSUBSB, yxm, Pe, [23]uint8{0xe8}},
-	Optab{APSUBSW, yxm, Pe, [23]uint8{0xe9}},
-	Optab{APSUBUSB, yxm, Pe, [23]uint8{0xd8}},
-	Optab{APSUBUSW, yxm, Pe, [23]uint8{0xd9}},
-	Optab{APSUBW, yxm, Pe, [23]uint8{0xf9}},
-	Optab{APSWAPL, ymfp, Px, [23]uint8{0xbb}},
-	Optab{APUNPCKHBW, ymm, Py1, [23]uint8{0x68, Pe, 0x68}},
-	Optab{APUNPCKHLQ, ymm, Py1, [23]uint8{0x6a, Pe, 0x6a}},
-	Optab{APUNPCKHQDQ, yxm, Pe, [23]uint8{0x6d}},
-	Optab{APUNPCKHWL, ymm, Py1, [23]uint8{0x69, Pe, 0x69}},
-	Optab{APUNPCKLBW, ymm, Py1, [23]uint8{0x60, Pe, 0x60}},
-	Optab{APUNPCKLLQ, ymm, Py1, [23]uint8{0x62, Pe, 0x62}},
-	Optab{APUNPCKLQDQ, yxm, Pe, [23]uint8{0x6c}},
-	Optab{APUNPCKLWL, ymm, Py1, [23]uint8{0x61, Pe, 0x61}},
-	Optab{APUSHAL, ynone, P32, [23]uint8{0x60}},
-	Optab{APUSHAW, ynone, Pe, [23]uint8{0x60}},
-	Optab{APUSHFL, ynone, P32, [23]uint8{0x9c}},
-	Optab{APUSHFQ, ynone, Py, [23]uint8{0x9c}},
-	Optab{APUSHFW, ynone, Pe, [23]uint8{0x9c}},
-	Optab{APUSHL, ypushl, P32, [23]uint8{0x50, 0xff, 06, 0x6a, 0x68}},
-	Optab{APUSHQ, ypushl, Py, [23]uint8{0x50, 0xff, 06, 0x6a, 0x68}},
-	Optab{APUSHW, ypushl, Pe, [23]uint8{0x50, 0xff, 06, 0x6a, 0x68}},
-	Optab{APXOR, ymm, Py1, [23]uint8{0xef, Pe, 0xef}},
-	Optab{AQUAD, ybyte, Px, [23]uint8{8}},
-	Optab{ARCLB, yshb, Pb, [23]uint8{0xd0, 02, 0xc0, 02, 0xd2, 02}},
-	Optab{ARCLL, yshl, Px, [23]uint8{0xd1, 02, 0xc1, 02, 0xd3, 02, 0xd3, 02}},
-	Optab{ARCLQ, yshl, Pw, [23]uint8{0xd1, 02, 0xc1, 02, 0xd3, 02, 0xd3, 02}},
-	Optab{ARCLW, yshl, Pe, [23]uint8{0xd1, 02, 0xc1, 02, 0xd3, 02, 0xd3, 02}},
-	Optab{ARCPPS, yxm, Pm, [23]uint8{0x53}},
-	Optab{ARCPSS, yxm, Pf3, [23]uint8{0x53}},
-	Optab{ARCRB, yshb, Pb, [23]uint8{0xd0, 03, 0xc0, 03, 0xd2, 03}},
-	Optab{ARCRL, yshl, Px, [23]uint8{0xd1, 03, 0xc1, 03, 0xd3, 03, 0xd3, 03}},
-	Optab{ARCRQ, yshl, Pw, [23]uint8{0xd1, 03, 0xc1, 03, 0xd3, 03, 0xd3, 03}},
-	Optab{ARCRW, yshl, Pe, [23]uint8{0xd1, 03, 0xc1, 03, 0xd3, 03, 0xd3, 03}},
-	Optab{AREP, ynone, Px, [23]uint8{0xf3}},
-	Optab{AREPN, ynone, Px, [23]uint8{0xf2}},
-	Optab{obj.ARET, ynone, Px, [23]uint8{0xc3}},
-	Optab{ARETFW, yret, Pe, [23]uint8{0xcb, 0xca}},
-	Optab{ARETFL, yret, Px, [23]uint8{0xcb, 0xca}},
-	Optab{ARETFQ, yret, Pw, [23]uint8{0xcb, 0xca}},
-	Optab{AROLB, yshb, Pb, [23]uint8{0xd0, 00, 0xc0, 00, 0xd2, 00}},
-	Optab{AROLL, yshl, Px, [23]uint8{0xd1, 00, 0xc1, 00, 0xd3, 00, 0xd3, 00}},
-	Optab{AROLQ, yshl, Pw, [23]uint8{0xd1, 00, 0xc1, 00, 0xd3, 00, 0xd3, 00}},
-	Optab{AROLW, yshl, Pe, [23]uint8{0xd1, 00, 0xc1, 00, 0xd3, 00, 0xd3, 00}},
-	Optab{ARORB, yshb, Pb, [23]uint8{0xd0, 01, 0xc0, 01, 0xd2, 01}},
-	Optab{ARORL, yshl, Px, [23]uint8{0xd1, 01, 0xc1, 01, 0xd3, 01, 0xd3, 01}},
-	Optab{ARORQ, yshl, Pw, [23]uint8{0xd1, 01, 0xc1, 01, 0xd3, 01, 0xd3, 01}},
-	Optab{ARORW, yshl, Pe, [23]uint8{0xd1, 01, 0xc1, 01, 0xd3, 01, 0xd3, 01}},
-	Optab{ARSQRTPS, yxm, Pm, [23]uint8{0x52}},
-	Optab{ARSQRTSS, yxm, Pf3, [23]uint8{0x52}},
-	Optab{ASAHF, ynone, Px1, [23]uint8{0x9e, 00, 0x86, 0xe0, 0x50, 0x9d}}, /* XCHGB AH,AL; PUSH AX; POPFL */
-	Optab{ASALB, yshb, Pb, [23]uint8{0xd0, 04, 0xc0, 04, 0xd2, 04}},
-	Optab{ASALL, yshl, Px, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
-	Optab{ASALQ, yshl, Pw, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
-	Optab{ASALW, yshl, Pe, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
-	Optab{ASARB, yshb, Pb, [23]uint8{0xd0, 07, 0xc0, 07, 0xd2, 07}},
-	Optab{ASARL, yshl, Px, [23]uint8{0xd1, 07, 0xc1, 07, 0xd3, 07, 0xd3, 07}},
-	Optab{ASARQ, yshl, Pw, [23]uint8{0xd1, 07, 0xc1, 07, 0xd3, 07, 0xd3, 07}},
-	Optab{ASARW, yshl, Pe, [23]uint8{0xd1, 07, 0xc1, 07, 0xd3, 07, 0xd3, 07}},
-	Optab{ASBBB, yxorb, Pb, [23]uint8{0x1c, 0x80, 03, 0x18, 0x1a}},
-	Optab{ASBBL, yxorl, Px, [23]uint8{0x83, 03, 0x1d, 0x81, 03, 0x19, 0x1b}},
-	Optab{ASBBQ, yxorl, Pw, [23]uint8{0x83, 03, 0x1d, 0x81, 03, 0x19, 0x1b}},
-	Optab{ASBBW, yxorl, Pe, [23]uint8{0x83, 03, 0x1d, 0x81, 03, 0x19, 0x1b}},
-	Optab{ASCASB, ynone, Pb, [23]uint8{0xae}},
-	Optab{ASCASL, ynone, Px, [23]uint8{0xaf}},
-	Optab{ASCASQ, ynone, Pw, [23]uint8{0xaf}},
-	Optab{ASCASW, ynone, Pe, [23]uint8{0xaf}},
-	Optab{ASETCC, yscond, Pb, [23]uint8{0x0f, 0x93, 00}},
-	Optab{ASETCS, yscond, Pb, [23]uint8{0x0f, 0x92, 00}},
-	Optab{ASETEQ, yscond, Pb, [23]uint8{0x0f, 0x94, 00}},
-	Optab{ASETGE, yscond, Pb, [23]uint8{0x0f, 0x9d, 00}},
-	Optab{ASETGT, yscond, Pb, [23]uint8{0x0f, 0x9f, 00}},
-	Optab{ASETHI, yscond, Pb, [23]uint8{0x0f, 0x97, 00}},
-	Optab{ASETLE, yscond, Pb, [23]uint8{0x0f, 0x9e, 00}},
-	Optab{ASETLS, yscond, Pb, [23]uint8{0x0f, 0x96, 00}},
-	Optab{ASETLT, yscond, Pb, [23]uint8{0x0f, 0x9c, 00}},
-	Optab{ASETMI, yscond, Pb, [23]uint8{0x0f, 0x98, 00}},
-	Optab{ASETNE, yscond, Pb, [23]uint8{0x0f, 0x95, 00}},
-	Optab{ASETOC, yscond, Pb, [23]uint8{0x0f, 0x91, 00}},
-	Optab{ASETOS, yscond, Pb, [23]uint8{0x0f, 0x90, 00}},
-	Optab{ASETPC, yscond, Pb, [23]uint8{0x0f, 0x9b, 00}},
-	Optab{ASETPL, yscond, Pb, [23]uint8{0x0f, 0x99, 00}},
-	Optab{ASETPS, yscond, Pb, [23]uint8{0x0f, 0x9a, 00}},
-	Optab{ASHLB, yshb, Pb, [23]uint8{0xd0, 04, 0xc0, 04, 0xd2, 04}},
-	Optab{ASHLL, yshl, Px, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
-	Optab{ASHLQ, yshl, Pw, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
-	Optab{ASHLW, yshl, Pe, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
-	Optab{ASHRB, yshb, Pb, [23]uint8{0xd0, 05, 0xc0, 05, 0xd2, 05}},
-	Optab{ASHRL, yshl, Px, [23]uint8{0xd1, 05, 0xc1, 05, 0xd3, 05, 0xd3, 05}},
-	Optab{ASHRQ, yshl, Pw, [23]uint8{0xd1, 05, 0xc1, 05, 0xd3, 05, 0xd3, 05}},
-	Optab{ASHRW, yshl, Pe, [23]uint8{0xd1, 05, 0xc1, 05, 0xd3, 05, 0xd3, 05}},
-	Optab{ASHUFPD, yxshuf, Pq, [23]uint8{0xc6, 00}},
-	Optab{ASHUFPS, yxshuf, Pm, [23]uint8{0xc6, 00}},
-	Optab{ASQRTPD, yxm, Pe, [23]uint8{0x51}},
-	Optab{ASQRTPS, yxm, Pm, [23]uint8{0x51}},
-	Optab{ASQRTSD, yxm, Pf2, [23]uint8{0x51}},
-	Optab{ASQRTSS, yxm, Pf3, [23]uint8{0x51}},
-	Optab{ASTC, ynone, Px, [23]uint8{0xf9}},
-	Optab{ASTD, ynone, Px, [23]uint8{0xfd}},
-	Optab{ASTI, ynone, Px, [23]uint8{0xfb}},
-	Optab{ASTMXCSR, ysvrs, Pm, [23]uint8{0xae, 03, 0xae, 03}},
-	Optab{ASTOSB, ynone, Pb, [23]uint8{0xaa}},
-	Optab{ASTOSL, ynone, Px, [23]uint8{0xab}},
-	Optab{ASTOSQ, ynone, Pw, [23]uint8{0xab}},
-	Optab{ASTOSW, ynone, Pe, [23]uint8{0xab}},
-	Optab{ASUBB, yxorb, Pb, [23]uint8{0x2c, 0x80, 05, 0x28, 0x2a}},
-	Optab{ASUBL, yaddl, Px, [23]uint8{0x83, 05, 0x2d, 0x81, 05, 0x29, 0x2b}},
-	Optab{ASUBPD, yxm, Pe, [23]uint8{0x5c}},
-	Optab{ASUBPS, yxm, Pm, [23]uint8{0x5c}},
-	Optab{ASUBQ, yaddl, Pw, [23]uint8{0x83, 05, 0x2d, 0x81, 05, 0x29, 0x2b}},
-	Optab{ASUBSD, yxm, Pf2, [23]uint8{0x5c}},
-	Optab{ASUBSS, yxm, Pf3, [23]uint8{0x5c}},
-	Optab{ASUBW, yaddl, Pe, [23]uint8{0x83, 05, 0x2d, 0x81, 05, 0x29, 0x2b}},
-	Optab{ASWAPGS, ynone, Pm, [23]uint8{0x01, 0xf8}},
-	Optab{ASYSCALL, ynone, Px, [23]uint8{0x0f, 0x05}}, /* fast syscall */
-	Optab{ATESTB, ytestb, Pb, [23]uint8{0xa8, 0xf6, 00, 0x84, 0x84}},
-	Optab{ATESTL, ytestl, Px, [23]uint8{0xa9, 0xf7, 00, 0x85, 0x85}},
-	Optab{ATESTQ, ytestl, Pw, [23]uint8{0xa9, 0xf7, 00, 0x85, 0x85}},
-	Optab{ATESTW, ytestl, Pe, [23]uint8{0xa9, 0xf7, 00, 0x85, 0x85}},
-	Optab{obj.ATEXT, ytext, Px, [23]uint8{}},
-	Optab{AUCOMISD, yxcmp, Pe, [23]uint8{0x2e}},
-	Optab{AUCOMISS, yxcmp, Pm, [23]uint8{0x2e}},
-	Optab{AUNPCKHPD, yxm, Pe, [23]uint8{0x15}},
-	Optab{AUNPCKHPS, yxm, Pm, [23]uint8{0x15}},
-	Optab{AUNPCKLPD, yxm, Pe, [23]uint8{0x14}},
-	Optab{AUNPCKLPS, yxm, Pm, [23]uint8{0x14}},
-	Optab{AVERR, ydivl, Pm, [23]uint8{0x00, 04}},
-	Optab{AVERW, ydivl, Pm, [23]uint8{0x00, 05}},
-	Optab{AWAIT, ynone, Px, [23]uint8{0x9b}},
-	Optab{AWORD, ybyte, Px, [23]uint8{2}},
-	Optab{AXCHGB, yml_mb, Pb, [23]uint8{0x86, 0x86}},
-	Optab{AXCHGL, yxchg, Px, [23]uint8{0x90, 0x90, 0x87, 0x87}},
-	Optab{AXCHGQ, yxchg, Pw, [23]uint8{0x90, 0x90, 0x87, 0x87}},
-	Optab{AXCHGW, yxchg, Pe, [23]uint8{0x90, 0x90, 0x87, 0x87}},
-	Optab{AXLAT, ynone, Px, [23]uint8{0xd7}},
-	Optab{AXORB, yxorb, Pb, [23]uint8{0x34, 0x80, 06, 0x30, 0x32}},
-	Optab{AXORL, yxorl, Px, [23]uint8{0x83, 06, 0x35, 0x81, 06, 0x31, 0x33}},
-	Optab{AXORPD, yxm, Pe, [23]uint8{0x57}},
-	Optab{AXORPS, yxm, Pm, [23]uint8{0x57}},
-	Optab{AXORQ, yxorl, Pw, [23]uint8{0x83, 06, 0x35, 0x81, 06, 0x31, 0x33}},
-	Optab{AXORW, yxorl, Pe, [23]uint8{0x83, 06, 0x35, 0x81, 06, 0x31, 0x33}},
-	Optab{AFMOVB, yfmvx, Px, [23]uint8{0xdf, 04}},
-	Optab{AFMOVBP, yfmvp, Px, [23]uint8{0xdf, 06}},
-	Optab{AFMOVD, yfmvd, Px, [23]uint8{0xdd, 00, 0xdd, 02, 0xd9, 00, 0xdd, 02}},
-	Optab{AFMOVDP, yfmvdp, Px, [23]uint8{0xdd, 03, 0xdd, 03}},
-	Optab{AFMOVF, yfmvf, Px, [23]uint8{0xd9, 00, 0xd9, 02}},
-	Optab{AFMOVFP, yfmvp, Px, [23]uint8{0xd9, 03}},
-	Optab{AFMOVL, yfmvf, Px, [23]uint8{0xdb, 00, 0xdb, 02}},
-	Optab{AFMOVLP, yfmvp, Px, [23]uint8{0xdb, 03}},
-	Optab{AFMOVV, yfmvx, Px, [23]uint8{0xdf, 05}},
-	Optab{AFMOVVP, yfmvp, Px, [23]uint8{0xdf, 07}},
-	Optab{AFMOVW, yfmvf, Px, [23]uint8{0xdf, 00, 0xdf, 02}},
-	Optab{AFMOVWP, yfmvp, Px, [23]uint8{0xdf, 03}},
-	Optab{AFMOVX, yfmvx, Px, [23]uint8{0xdb, 05}},
-	Optab{AFMOVXP, yfmvp, Px, [23]uint8{0xdb, 07}},
-	Optab{AFCMOVCC, yfcmv, Px, [23]uint8{0xdb, 00}},
-	Optab{AFCMOVCS, yfcmv, Px, [23]uint8{0xda, 00}},
-	Optab{AFCMOVEQ, yfcmv, Px, [23]uint8{0xda, 01}},
-	Optab{AFCMOVHI, yfcmv, Px, [23]uint8{0xdb, 02}},
-	Optab{AFCMOVLS, yfcmv, Px, [23]uint8{0xda, 02}},
-	Optab{AFCMOVNE, yfcmv, Px, [23]uint8{0xdb, 01}},
-	Optab{AFCMOVNU, yfcmv, Px, [23]uint8{0xdb, 03}},
-	Optab{AFCMOVUN, yfcmv, Px, [23]uint8{0xda, 03}},
-	Optab{AFCOMB, nil, 0, [23]uint8{}},
-	Optab{AFCOMBP, nil, 0, [23]uint8{}},
-	Optab{AFCOMD, yfadd, Px, [23]uint8{0xdc, 02, 0xd8, 02, 0xdc, 02}},  /* botch */
-	Optab{AFCOMDP, yfadd, Px, [23]uint8{0xdc, 03, 0xd8, 03, 0xdc, 03}}, /* botch */
-	Optab{AFCOMDPP, ycompp, Px, [23]uint8{0xde, 03}},
-	Optab{AFCOMF, yfmvx, Px, [23]uint8{0xd8, 02}},
-	Optab{AFCOMFP, yfmvx, Px, [23]uint8{0xd8, 03}},
-	Optab{AFCOMI, yfmvx, Px, [23]uint8{0xdb, 06}},
-	Optab{AFCOMIP, yfmvx, Px, [23]uint8{0xdf, 06}},
-	Optab{AFCOML, yfmvx, Px, [23]uint8{0xda, 02}},
-	Optab{AFCOMLP, yfmvx, Px, [23]uint8{0xda, 03}},
-	Optab{AFCOMW, yfmvx, Px, [23]uint8{0xde, 02}},
-	Optab{AFCOMWP, yfmvx, Px, [23]uint8{0xde, 03}},
-	Optab{AFUCOM, ycompp, Px, [23]uint8{0xdd, 04}},
-	Optab{AFUCOMI, ycompp, Px, [23]uint8{0xdb, 05}},
-	Optab{AFUCOMIP, ycompp, Px, [23]uint8{0xdf, 05}},
-	Optab{AFUCOMP, ycompp, Px, [23]uint8{0xdd, 05}},
-	Optab{AFUCOMPP, ycompp, Px, [23]uint8{0xda, 13}},
-	Optab{AFADDDP, yfaddp, Px, [23]uint8{0xde, 00}},
-	Optab{AFADDW, yfmvx, Px, [23]uint8{0xde, 00}},
-	Optab{AFADDL, yfmvx, Px, [23]uint8{0xda, 00}},
-	Optab{AFADDF, yfmvx, Px, [23]uint8{0xd8, 00}},
-	Optab{AFADDD, yfadd, Px, [23]uint8{0xdc, 00, 0xd8, 00, 0xdc, 00}},
-	Optab{AFMULDP, yfaddp, Px, [23]uint8{0xde, 01}},
-	Optab{AFMULW, yfmvx, Px, [23]uint8{0xde, 01}},
-	Optab{AFMULL, yfmvx, Px, [23]uint8{0xda, 01}},
-	Optab{AFMULF, yfmvx, Px, [23]uint8{0xd8, 01}},
-	Optab{AFMULD, yfadd, Px, [23]uint8{0xdc, 01, 0xd8, 01, 0xdc, 01}},
-	Optab{AFSUBDP, yfaddp, Px, [23]uint8{0xde, 05}},
-	Optab{AFSUBW, yfmvx, Px, [23]uint8{0xde, 04}},
-	Optab{AFSUBL, yfmvx, Px, [23]uint8{0xda, 04}},
-	Optab{AFSUBF, yfmvx, Px, [23]uint8{0xd8, 04}},
-	Optab{AFSUBD, yfadd, Px, [23]uint8{0xdc, 04, 0xd8, 04, 0xdc, 05}},
-	Optab{AFSUBRDP, yfaddp, Px, [23]uint8{0xde, 04}},
-	Optab{AFSUBRW, yfmvx, Px, [23]uint8{0xde, 05}},
-	Optab{AFSUBRL, yfmvx, Px, [23]uint8{0xda, 05}},
-	Optab{AFSUBRF, yfmvx, Px, [23]uint8{0xd8, 05}},
-	Optab{AFSUBRD, yfadd, Px, [23]uint8{0xdc, 05, 0xd8, 05, 0xdc, 04}},
-	Optab{AFDIVDP, yfaddp, Px, [23]uint8{0xde, 07}},
-	Optab{AFDIVW, yfmvx, Px, [23]uint8{0xde, 06}},
-	Optab{AFDIVL, yfmvx, Px, [23]uint8{0xda, 06}},
-	Optab{AFDIVF, yfmvx, Px, [23]uint8{0xd8, 06}},
-	Optab{AFDIVD, yfadd, Px, [23]uint8{0xdc, 06, 0xd8, 06, 0xdc, 07}},
-	Optab{AFDIVRDP, yfaddp, Px, [23]uint8{0xde, 06}},
-	Optab{AFDIVRW, yfmvx, Px, [23]uint8{0xde, 07}},
-	Optab{AFDIVRL, yfmvx, Px, [23]uint8{0xda, 07}},
-	Optab{AFDIVRF, yfmvx, Px, [23]uint8{0xd8, 07}},
-	Optab{AFDIVRD, yfadd, Px, [23]uint8{0xdc, 07, 0xd8, 07, 0xdc, 06}},
-	Optab{AFXCHD, yfxch, Px, [23]uint8{0xd9, 01, 0xd9, 01}},
-	Optab{AFFREE, nil, 0, [23]uint8{}},
-	Optab{AFLDCW, ystcw, Px, [23]uint8{0xd9, 05, 0xd9, 05}},
-	Optab{AFLDENV, ystcw, Px, [23]uint8{0xd9, 04, 0xd9, 04}},
-	Optab{AFRSTOR, ysvrs, Px, [23]uint8{0xdd, 04, 0xdd, 04}},
-	Optab{AFSAVE, ysvrs, Px, [23]uint8{0xdd, 06, 0xdd, 06}},
-	Optab{AFSTCW, ystcw, Px, [23]uint8{0xd9, 07, 0xd9, 07}},
-	Optab{AFSTENV, ystcw, Px, [23]uint8{0xd9, 06, 0xd9, 06}},
-	Optab{AFSTSW, ystsw, Px, [23]uint8{0xdd, 07, 0xdf, 0xe0}},
-	Optab{AF2XM1, ynone, Px, [23]uint8{0xd9, 0xf0}},
-	Optab{AFABS, ynone, Px, [23]uint8{0xd9, 0xe1}},
-	Optab{AFCHS, ynone, Px, [23]uint8{0xd9, 0xe0}},
-	Optab{AFCLEX, ynone, Px, [23]uint8{0xdb, 0xe2}},
-	Optab{AFCOS, ynone, Px, [23]uint8{0xd9, 0xff}},
-	Optab{AFDECSTP, ynone, Px, [23]uint8{0xd9, 0xf6}},
-	Optab{AFINCSTP, ynone, Px, [23]uint8{0xd9, 0xf7}},
-	Optab{AFINIT, ynone, Px, [23]uint8{0xdb, 0xe3}},
-	Optab{AFLD1, ynone, Px, [23]uint8{0xd9, 0xe8}},
-	Optab{AFLDL2E, ynone, Px, [23]uint8{0xd9, 0xea}},
-	Optab{AFLDL2T, ynone, Px, [23]uint8{0xd9, 0xe9}},
-	Optab{AFLDLG2, ynone, Px, [23]uint8{0xd9, 0xec}},
-	Optab{AFLDLN2, ynone, Px, [23]uint8{0xd9, 0xed}},
-	Optab{AFLDPI, ynone, Px, [23]uint8{0xd9, 0xeb}},
-	Optab{AFLDZ, ynone, Px, [23]uint8{0xd9, 0xee}},
-	Optab{AFNOP, ynone, Px, [23]uint8{0xd9, 0xd0}},
-	Optab{AFPATAN, ynone, Px, [23]uint8{0xd9, 0xf3}},
-	Optab{AFPREM, ynone, Px, [23]uint8{0xd9, 0xf8}},
-	Optab{AFPREM1, ynone, Px, [23]uint8{0xd9, 0xf5}},
-	Optab{AFPTAN, ynone, Px, [23]uint8{0xd9, 0xf2}},
-	Optab{AFRNDINT, ynone, Px, [23]uint8{0xd9, 0xfc}},
-	Optab{AFSCALE, ynone, Px, [23]uint8{0xd9, 0xfd}},
-	Optab{AFSIN, ynone, Px, [23]uint8{0xd9, 0xfe}},
-	Optab{AFSINCOS, ynone, Px, [23]uint8{0xd9, 0xfb}},
-	Optab{AFSQRT, ynone, Px, [23]uint8{0xd9, 0xfa}},
-	Optab{AFTST, ynone, Px, [23]uint8{0xd9, 0xe4}},
-	Optab{AFXAM, ynone, Px, [23]uint8{0xd9, 0xe5}},
-	Optab{AFXTRACT, ynone, Px, [23]uint8{0xd9, 0xf4}},
-	Optab{AFYL2X, ynone, Px, [23]uint8{0xd9, 0xf1}},
-	Optab{AFYL2XP1, ynone, Px, [23]uint8{0xd9, 0xf9}},
-	Optab{ACMPXCHGB, yrb_mb, Pb, [23]uint8{0x0f, 0xb0}},
-	Optab{ACMPXCHGL, yrl_ml, Px, [23]uint8{0x0f, 0xb1}},
-	Optab{ACMPXCHGW, yrl_ml, Pe, [23]uint8{0x0f, 0xb1}},
-	Optab{ACMPXCHGQ, yrl_ml, Pw, [23]uint8{0x0f, 0xb1}},
-	Optab{ACMPXCHG8B, yscond, Pm, [23]uint8{0xc7, 01}},
-	Optab{AINVD, ynone, Pm, [23]uint8{0x08}},
-	Optab{AINVLPG, ymbs, Pm, [23]uint8{0x01, 07}},
-	Optab{ALFENCE, ynone, Pm, [23]uint8{0xae, 0xe8}},
-	Optab{AMFENCE, ynone, Pm, [23]uint8{0xae, 0xf0}},
-	Optab{AMOVNTIL, yrl_ml, Pm, [23]uint8{0xc3}},
-	Optab{AMOVNTIQ, yrl_ml, Pw, [23]uint8{0x0f, 0xc3}},
-	Optab{ARDMSR, ynone, Pm, [23]uint8{0x32}},
-	Optab{ARDPMC, ynone, Pm, [23]uint8{0x33}},
-	Optab{ARDTSC, ynone, Pm, [23]uint8{0x31}},
-	Optab{ARSM, ynone, Pm, [23]uint8{0xaa}},
-	Optab{ASFENCE, ynone, Pm, [23]uint8{0xae, 0xf8}},
-	Optab{ASYSRET, ynone, Pm, [23]uint8{0x07}},
-	Optab{AWBINVD, ynone, Pm, [23]uint8{0x09}},
-	Optab{AWRMSR, ynone, Pm, [23]uint8{0x30}},
-	Optab{AXADDB, yrb_mb, Pb, [23]uint8{0x0f, 0xc0}},
-	Optab{AXADDL, yrl_ml, Px, [23]uint8{0x0f, 0xc1}},
-	Optab{AXADDQ, yrl_ml, Pw, [23]uint8{0x0f, 0xc1}},
-	Optab{AXADDW, yrl_ml, Pe, [23]uint8{0x0f, 0xc1}},
-	Optab{ACRC32B, ycrc32l, Px, [23]uint8{0xf2, 0x0f, 0x38, 0xf0, 0}},
-	Optab{ACRC32Q, ycrc32l, Pw, [23]uint8{0xf2, 0x0f, 0x38, 0xf1, 0}},
-	Optab{APREFETCHT0, yprefetch, Pm, [23]uint8{0x18, 01}},
-	Optab{APREFETCHT1, yprefetch, Pm, [23]uint8{0x18, 02}},
-	Optab{APREFETCHT2, yprefetch, Pm, [23]uint8{0x18, 03}},
-	Optab{APREFETCHNTA, yprefetch, Pm, [23]uint8{0x18, 00}},
-	Optab{AMOVQL, yrl_ml, Px, [23]uint8{0x89}},
-	Optab{obj.AUNDEF, ynone, Px, [23]uint8{0x0f, 0x0b}},
-	Optab{AAESENC, yaes, Pq, [23]uint8{0x38, 0xdc, 0}},
-	Optab{AAESENCLAST, yaes, Pq, [23]uint8{0x38, 0xdd, 0}},
-	Optab{AAESDEC, yaes, Pq, [23]uint8{0x38, 0xde, 0}},
-	Optab{AAESDECLAST, yaes, Pq, [23]uint8{0x38, 0xdf, 0}},
-	Optab{AAESIMC, yaes, Pq, [23]uint8{0x38, 0xdb, 0}},
-	Optab{AAESKEYGENASSIST, yaes2, Pq, [23]uint8{0x3a, 0xdf, 0}},
-	Optab{APSHUFD, yxshuf, Pq, [23]uint8{0x70, 0}},
-	Optab{APCLMULQDQ, yxshuf, Pq, [23]uint8{0x3a, 0x44, 0}},
-	Optab{obj.AUSEFIELD, ynop, Px, [23]uint8{0, 0}},
-	Optab{obj.ATYPE, nil, 0, [23]uint8{}},
-	Optab{obj.AFUNCDATA, yfuncdata, Px, [23]uint8{0, 0}},
-	Optab{obj.APCDATA, ypcdata, Px, [23]uint8{0, 0}},
-	Optab{obj.ACHECKNIL, nil, 0, [23]uint8{}},
-	Optab{obj.AVARDEF, nil, 0, [23]uint8{}},
-	Optab{obj.AVARKILL, nil, 0, [23]uint8{}},
-	Optab{obj.ADUFFCOPY, yduff, Px, [23]uint8{0xe8}},
-	Optab{obj.ADUFFZERO, yduff, Px, [23]uint8{0xe8}},
-	Optab{obj.AEND, nil, 0, [23]uint8{}},
-	Optab{0, nil, 0, [23]uint8{}},
+	{obj.AXXX, nil, 0, [23]uint8{}},
+	{AAAA, ynone, P32, [23]uint8{0x37}},
+	{AAAD, ynone, P32, [23]uint8{0xd5, 0x0a}},
+	{AAAM, ynone, P32, [23]uint8{0xd4, 0x0a}},
+	{AAAS, ynone, P32, [23]uint8{0x3f}},
+	{AADCB, yxorb, Pb, [23]uint8{0x14, 0x80, 02, 0x10, 0x10}},
+	{AADCL, yxorl, Px, [23]uint8{0x83, 02, 0x15, 0x81, 02, 0x11, 0x13}},
+	{AADCQ, yxorl, Pw, [23]uint8{0x83, 02, 0x15, 0x81, 02, 0x11, 0x13}},
+	{AADCW, yxorl, Pe, [23]uint8{0x83, 02, 0x15, 0x81, 02, 0x11, 0x13}},
+	{AADDB, yxorb, Pb, [23]uint8{0x04, 0x80, 00, 0x00, 0x02}},
+	{AADDL, yaddl, Px, [23]uint8{0x83, 00, 0x05, 0x81, 00, 0x01, 0x03}},
+	{AADDPD, yxm, Pq, [23]uint8{0x58}},
+	{AADDPS, yxm, Pm, [23]uint8{0x58}},
+	{AADDQ, yaddl, Pw, [23]uint8{0x83, 00, 0x05, 0x81, 00, 0x01, 0x03}},
+	{AADDSD, yxm, Pf2, [23]uint8{0x58}},
+	{AADDSS, yxm, Pf3, [23]uint8{0x58}},
+	{AADDW, yaddl, Pe, [23]uint8{0x83, 00, 0x05, 0x81, 00, 0x01, 0x03}},
+	{AADJSP, nil, 0, [23]uint8{}},
+	{AANDB, yxorb, Pb, [23]uint8{0x24, 0x80, 04, 0x20, 0x22}},
+	{AANDL, yxorl, Px, [23]uint8{0x83, 04, 0x25, 0x81, 04, 0x21, 0x23}},
+	{AANDNPD, yxm, Pq, [23]uint8{0x55}},
+	{AANDNPS, yxm, Pm, [23]uint8{0x55}},
+	{AANDPD, yxm, Pq, [23]uint8{0x54}},
+	{AANDPS, yxm, Pq, [23]uint8{0x54}},
+	{AANDQ, yxorl, Pw, [23]uint8{0x83, 04, 0x25, 0x81, 04, 0x21, 0x23}},
+	{AANDW, yxorl, Pe, [23]uint8{0x83, 04, 0x25, 0x81, 04, 0x21, 0x23}},
+	{AARPL, yrl_ml, P32, [23]uint8{0x63}},
+	{ABOUNDL, yrl_m, P32, [23]uint8{0x62}},
+	{ABOUNDW, yrl_m, Pe, [23]uint8{0x62}},
+	{ABSFL, yml_rl, Pm, [23]uint8{0xbc}},
+	{ABSFQ, yml_rl, Pw, [23]uint8{0x0f, 0xbc}},
+	{ABSFW, yml_rl, Pq, [23]uint8{0xbc}},
+	{ABSRL, yml_rl, Pm, [23]uint8{0xbd}},
+	{ABSRQ, yml_rl, Pw, [23]uint8{0x0f, 0xbd}},
+	{ABSRW, yml_rl, Pq, [23]uint8{0xbd}},
+	{ABSWAPL, ybswap, Px, [23]uint8{0x0f, 0xc8}},
+	{ABSWAPQ, ybswap, Pw, [23]uint8{0x0f, 0xc8}},
+	{ABTCL, ybtl, Pm, [23]uint8{0xba, 07, 0xbb}},
+	{ABTCQ, ybtl, Pw, [23]uint8{0x0f, 0xba, 07, 0x0f, 0xbb}},
+	{ABTCW, ybtl, Pq, [23]uint8{0xba, 07, 0xbb}},
+	{ABTL, ybtl, Pm, [23]uint8{0xba, 04, 0xa3}},
+	{ABTQ, ybtl, Pw, [23]uint8{0x0f, 0xba, 04, 0x0f, 0xa3}},
+	{ABTRL, ybtl, Pm, [23]uint8{0xba, 06, 0xb3}},
+	{ABTRQ, ybtl, Pw, [23]uint8{0x0f, 0xba, 06, 0x0f, 0xb3}},
+	{ABTRW, ybtl, Pq, [23]uint8{0xba, 06, 0xb3}},
+	{ABTSL, ybtl, Pm, [23]uint8{0xba, 05, 0xab}},
+	{ABTSQ, ybtl, Pw, [23]uint8{0x0f, 0xba, 05, 0x0f, 0xab}},
+	{ABTSW, ybtl, Pq, [23]uint8{0xba, 05, 0xab}},
+	{ABTW, ybtl, Pq, [23]uint8{0xba, 04, 0xa3}},
+	{ABYTE, ybyte, Px, [23]uint8{1}},
+	{obj.ACALL, ycall, Px, [23]uint8{0xff, 02, 0xff, 0x15, 0xe8}},
+	{ACDQ, ynone, Px, [23]uint8{0x99}},
+	{ACLC, ynone, Px, [23]uint8{0xf8}},
+	{ACLD, ynone, Px, [23]uint8{0xfc}},
+	{ACLI, ynone, Px, [23]uint8{0xfa}},
+	{ACLTS, ynone, Pm, [23]uint8{0x06}},
+	{ACMC, ynone, Px, [23]uint8{0xf5}},
+	{ACMOVLCC, yml_rl, Pm, [23]uint8{0x43}},
+	{ACMOVLCS, yml_rl, Pm, [23]uint8{0x42}},
+	{ACMOVLEQ, yml_rl, Pm, [23]uint8{0x44}},
+	{ACMOVLGE, yml_rl, Pm, [23]uint8{0x4d}},
+	{ACMOVLGT, yml_rl, Pm, [23]uint8{0x4f}},
+	{ACMOVLHI, yml_rl, Pm, [23]uint8{0x47}},
+	{ACMOVLLE, yml_rl, Pm, [23]uint8{0x4e}},
+	{ACMOVLLS, yml_rl, Pm, [23]uint8{0x46}},
+	{ACMOVLLT, yml_rl, Pm, [23]uint8{0x4c}},
+	{ACMOVLMI, yml_rl, Pm, [23]uint8{0x48}},
+	{ACMOVLNE, yml_rl, Pm, [23]uint8{0x45}},
+	{ACMOVLOC, yml_rl, Pm, [23]uint8{0x41}},
+	{ACMOVLOS, yml_rl, Pm, [23]uint8{0x40}},
+	{ACMOVLPC, yml_rl, Pm, [23]uint8{0x4b}},
+	{ACMOVLPL, yml_rl, Pm, [23]uint8{0x49}},
+	{ACMOVLPS, yml_rl, Pm, [23]uint8{0x4a}},
+	{ACMOVQCC, yml_rl, Pw, [23]uint8{0x0f, 0x43}},
+	{ACMOVQCS, yml_rl, Pw, [23]uint8{0x0f, 0x42}},
+	{ACMOVQEQ, yml_rl, Pw, [23]uint8{0x0f, 0x44}},
+	{ACMOVQGE, yml_rl, Pw, [23]uint8{0x0f, 0x4d}},
+	{ACMOVQGT, yml_rl, Pw, [23]uint8{0x0f, 0x4f}},
+	{ACMOVQHI, yml_rl, Pw, [23]uint8{0x0f, 0x47}},
+	{ACMOVQLE, yml_rl, Pw, [23]uint8{0x0f, 0x4e}},
+	{ACMOVQLS, yml_rl, Pw, [23]uint8{0x0f, 0x46}},
+	{ACMOVQLT, yml_rl, Pw, [23]uint8{0x0f, 0x4c}},
+	{ACMOVQMI, yml_rl, Pw, [23]uint8{0x0f, 0x48}},
+	{ACMOVQNE, yml_rl, Pw, [23]uint8{0x0f, 0x45}},
+	{ACMOVQOC, yml_rl, Pw, [23]uint8{0x0f, 0x41}},
+	{ACMOVQOS, yml_rl, Pw, [23]uint8{0x0f, 0x40}},
+	{ACMOVQPC, yml_rl, Pw, [23]uint8{0x0f, 0x4b}},
+	{ACMOVQPL, yml_rl, Pw, [23]uint8{0x0f, 0x49}},
+	{ACMOVQPS, yml_rl, Pw, [23]uint8{0x0f, 0x4a}},
+	{ACMOVWCC, yml_rl, Pq, [23]uint8{0x43}},
+	{ACMOVWCS, yml_rl, Pq, [23]uint8{0x42}},
+	{ACMOVWEQ, yml_rl, Pq, [23]uint8{0x44}},
+	{ACMOVWGE, yml_rl, Pq, [23]uint8{0x4d}},
+	{ACMOVWGT, yml_rl, Pq, [23]uint8{0x4f}},
+	{ACMOVWHI, yml_rl, Pq, [23]uint8{0x47}},
+	{ACMOVWLE, yml_rl, Pq, [23]uint8{0x4e}},
+	{ACMOVWLS, yml_rl, Pq, [23]uint8{0x46}},
+	{ACMOVWLT, yml_rl, Pq, [23]uint8{0x4c}},
+	{ACMOVWMI, yml_rl, Pq, [23]uint8{0x48}},
+	{ACMOVWNE, yml_rl, Pq, [23]uint8{0x45}},
+	{ACMOVWOC, yml_rl, Pq, [23]uint8{0x41}},
+	{ACMOVWOS, yml_rl, Pq, [23]uint8{0x40}},
+	{ACMOVWPC, yml_rl, Pq, [23]uint8{0x4b}},
+	{ACMOVWPL, yml_rl, Pq, [23]uint8{0x49}},
+	{ACMOVWPS, yml_rl, Pq, [23]uint8{0x4a}},
+	{ACMPB, ycmpb, Pb, [23]uint8{0x3c, 0x80, 07, 0x38, 0x3a}},
+	{ACMPL, ycmpl, Px, [23]uint8{0x83, 07, 0x3d, 0x81, 07, 0x39, 0x3b}},
+	{ACMPPD, yxcmpi, Px, [23]uint8{Pe, 0xc2}},
+	{ACMPPS, yxcmpi, Pm, [23]uint8{0xc2, 0}},
+	{ACMPQ, ycmpl, Pw, [23]uint8{0x83, 07, 0x3d, 0x81, 07, 0x39, 0x3b}},
+	{ACMPSB, ynone, Pb, [23]uint8{0xa6}},
+	{ACMPSD, yxcmpi, Px, [23]uint8{Pf2, 0xc2}},
+	{ACMPSL, ynone, Px, [23]uint8{0xa7}},
+	{ACMPSQ, ynone, Pw, [23]uint8{0xa7}},
+	{ACMPSS, yxcmpi, Px, [23]uint8{Pf3, 0xc2}},
+	{ACMPSW, ynone, Pe, [23]uint8{0xa7}},
+	{ACMPW, ycmpl, Pe, [23]uint8{0x83, 07, 0x3d, 0x81, 07, 0x39, 0x3b}},
+	{ACOMISD, yxcmp, Pe, [23]uint8{0x2f}},
+	{ACOMISS, yxcmp, Pm, [23]uint8{0x2f}},
+	{ACPUID, ynone, Pm, [23]uint8{0xa2}},
+	{ACVTPL2PD, yxcvm2, Px, [23]uint8{Pf3, 0xe6, Pe, 0x2a}},
+	{ACVTPL2PS, yxcvm2, Pm, [23]uint8{0x5b, 0, 0x2a, 0}},
+	{ACVTPD2PL, yxcvm1, Px, [23]uint8{Pf2, 0xe6, Pe, 0x2d}},
+	{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}},
+	{ACVTSL2SD, yxcvlf, Pf2, [23]uint8{0x2a}},
+	{ACVTSQ2SD, yxcvqf, Pw, [23]uint8{Pf2, 0x2a}},
+	{ACVTSL2SS, yxcvlf, Pf3, [23]uint8{0x2a}},
+	{ACVTSQ2SS, yxcvqf, Pw, [23]uint8{Pf3, 0x2a}},
+	{ACVTSS2SD, yxm, Pf3, [23]uint8{0x5a}},
+	{ACVTSS2SL, yxcvfl, Pf3, [23]uint8{0x2d}},
+	{ACVTSS2SQ, yxcvfq, Pw, [23]uint8{Pf3, 0x2d}},
+	{ACVTTPD2PL, yxcvm1, Px, [23]uint8{Pe, 0xe6, Pe, 0x2c}},
+	{ACVTTPS2PL, yxcvm1, Px, [23]uint8{Pf3, 0x5b, Pm, 0x2c}},
+	{ACVTTSD2SL, yxcvfl, Pf2, [23]uint8{0x2c}},
+	{ACVTTSD2SQ, yxcvfq, Pw, [23]uint8{Pf2, 0x2c}},
+	{ACVTTSS2SL, yxcvfl, Pf3, [23]uint8{0x2c}},
+	{ACVTTSS2SQ, yxcvfq, Pw, [23]uint8{Pf3, 0x2c}},
+	{ACWD, ynone, Pe, [23]uint8{0x99}},
+	{ACQO, ynone, Pw, [23]uint8{0x99}},
+	{ADAA, ynone, P32, [23]uint8{0x27}},
+	{ADAS, ynone, P32, [23]uint8{0x2f}},
+	{obj.ADATA, nil, 0, [23]uint8{}},
+	{ADECB, yincb, Pb, [23]uint8{0xfe, 01}},
+	{ADECL, yincl, Px1, [23]uint8{0x48, 0xff, 01}},
+	{ADECQ, yincq, Pw, [23]uint8{0xff, 01}},
+	{ADECW, yincw, Pe, [23]uint8{0xff, 01}},
+	{ADIVB, ydivb, Pb, [23]uint8{0xf6, 06}},
+	{ADIVL, ydivl, Px, [23]uint8{0xf7, 06}},
+	{ADIVPD, yxm, Pe, [23]uint8{0x5e}},
+	{ADIVPS, yxm, Pm, [23]uint8{0x5e}},
+	{ADIVQ, ydivl, Pw, [23]uint8{0xf7, 06}},
+	{ADIVSD, yxm, Pf2, [23]uint8{0x5e}},
+	{ADIVSS, yxm, Pf3, [23]uint8{0x5e}},
+	{ADIVW, ydivl, Pe, [23]uint8{0xf7, 06}},
+	{AEMMS, ynone, Pm, [23]uint8{0x77}},
+	{AENTER, nil, 0, [23]uint8{}}, /* botch */
+	{AFXRSTOR, ysvrs, Pm, [23]uint8{0xae, 01, 0xae, 01}},
+	{AFXSAVE, ysvrs, Pm, [23]uint8{0xae, 00, 0xae, 00}},
+	{AFXRSTOR64, ysvrs, Pw, [23]uint8{0x0f, 0xae, 01, 0x0f, 0xae, 01}},
+	{AFXSAVE64, ysvrs, Pw, [23]uint8{0x0f, 0xae, 00, 0x0f, 0xae, 00}},
+	{obj.AGLOBL, nil, 0, [23]uint8{}},
+	{AHLT, ynone, Px, [23]uint8{0xf4}},
+	{AIDIVB, ydivb, Pb, [23]uint8{0xf6, 07}},
+	{AIDIVL, ydivl, Px, [23]uint8{0xf7, 07}},
+	{AIDIVQ, ydivl, Pw, [23]uint8{0xf7, 07}},
+	{AIDIVW, ydivl, Pe, [23]uint8{0xf7, 07}},
+	{AIMULB, ydivb, Pb, [23]uint8{0xf6, 05}},
+	{AIMULL, yimul, Px, [23]uint8{0xf7, 05, 0x6b, 0x69, Pm, 0xaf}},
+	{AIMULQ, yimul, Pw, [23]uint8{0xf7, 05, 0x6b, 0x69, Pm, 0xaf}},
+	{AIMULW, yimul, Pe, [23]uint8{0xf7, 05, 0x6b, 0x69, Pm, 0xaf}},
+	{AIMUL3Q, yimul3, Pw, [23]uint8{0x6b, 00}},
+	{AINB, yin, Pb, [23]uint8{0xe4, 0xec}},
+	{AINCB, yincb, Pb, [23]uint8{0xfe, 00}},
+	{AINCL, yincl, Px1, [23]uint8{0x40, 0xff, 00}},
+	{AINCQ, yincq, Pw, [23]uint8{0xff, 00}},
+	{AINCW, yincw, Pe, [23]uint8{0xff, 00}},
+	{AINL, yin, Px, [23]uint8{0xe5, 0xed}},
+	{AINSB, ynone, Pb, [23]uint8{0x6c}},
+	{AINSL, ynone, Px, [23]uint8{0x6d}},
+	{AINSW, ynone, Pe, [23]uint8{0x6d}},
+	{AINT, yint, Px, [23]uint8{0xcd}},
+	{AINTO, ynone, P32, [23]uint8{0xce}},
+	{AINW, yin, Pe, [23]uint8{0xe5, 0xed}},
+	{AIRETL, ynone, Px, [23]uint8{0xcf}},
+	{AIRETQ, ynone, Pw, [23]uint8{0xcf}},
+	{AIRETW, ynone, Pe, [23]uint8{0xcf}},
+	{AJCC, yjcond, Px, [23]uint8{0x73, 0x83, 00}},
+	{AJCS, yjcond, Px, [23]uint8{0x72, 0x82}},
+	{AJCXZL, yloop, Px, [23]uint8{0xe3}},
+	{AJCXZW, yloop, Px, [23]uint8{0xe3}},
+	{AJCXZQ, yloop, Px, [23]uint8{0xe3}},
+	{AJEQ, yjcond, Px, [23]uint8{0x74, 0x84}},
+	{AJGE, yjcond, Px, [23]uint8{0x7d, 0x8d}},
+	{AJGT, yjcond, Px, [23]uint8{0x7f, 0x8f}},
+	{AJHI, yjcond, Px, [23]uint8{0x77, 0x87}},
+	{AJLE, yjcond, Px, [23]uint8{0x7e, 0x8e}},
+	{AJLS, yjcond, Px, [23]uint8{0x76, 0x86}},
+	{AJLT, yjcond, Px, [23]uint8{0x7c, 0x8c}},
+	{AJMI, yjcond, Px, [23]uint8{0x78, 0x88}},
+	{obj.AJMP, yjmp, Px, [23]uint8{0xff, 04, 0xeb, 0xe9}},
+	{AJNE, yjcond, Px, [23]uint8{0x75, 0x85}},
+	{AJOC, yjcond, Px, [23]uint8{0x71, 0x81, 00}},
+	{AJOS, yjcond, Px, [23]uint8{0x70, 0x80, 00}},
+	{AJPC, yjcond, Px, [23]uint8{0x7b, 0x8b}},
+	{AJPL, yjcond, Px, [23]uint8{0x79, 0x89}},
+	{AJPS, yjcond, Px, [23]uint8{0x7a, 0x8a}},
+	{AHADDPD, yxm, Pq, [23]uint8{0x7c}},
+	{AHADDPS, yxm, Pf2, [23]uint8{0x7c}},
+	{AHSUBPD, yxm, Pq, [23]uint8{0x7d}},
+	{AHSUBPS, yxm, Pf2, [23]uint8{0x7d}},
+	{ALAHF, ynone, Px, [23]uint8{0x9f}},
+	{ALARL, yml_rl, Pm, [23]uint8{0x02}},
+	{ALARW, yml_rl, Pq, [23]uint8{0x02}},
+	{ALDDQU, ylddqu, Pf2, [23]uint8{0xf0}},
+	{ALDMXCSR, ysvrs, Pm, [23]uint8{0xae, 02, 0xae, 02}},
+	{ALEAL, ym_rl, Px, [23]uint8{0x8d}},
+	{ALEAQ, ym_rl, Pw, [23]uint8{0x8d}},
+	{ALEAVEL, ynone, P32, [23]uint8{0xc9}},
+	{ALEAVEQ, ynone, Py, [23]uint8{0xc9}},
+	{ALEAVEW, ynone, Pe, [23]uint8{0xc9}},
+	{ALEAW, ym_rl, Pe, [23]uint8{0x8d}},
+	{ALOCK, ynone, Px, [23]uint8{0xf0}},
+	{ALODSB, ynone, Pb, [23]uint8{0xac}},
+	{ALODSL, ynone, Px, [23]uint8{0xad}},
+	{ALODSQ, ynone, Pw, [23]uint8{0xad}},
+	{ALODSW, ynone, Pe, [23]uint8{0xad}},
+	{ALONG, ybyte, Px, [23]uint8{4}},
+	{ALOOP, yloop, Px, [23]uint8{0xe2}},
+	{ALOOPEQ, yloop, Px, [23]uint8{0xe1}},
+	{ALOOPNE, yloop, Px, [23]uint8{0xe0}},
+	{ALSLL, yml_rl, Pm, [23]uint8{0x03}},
+	{ALSLW, yml_rl, Pq, [23]uint8{0x03}},
+	{AMASKMOVOU, yxr, Pe, [23]uint8{0xf7}},
+	{AMASKMOVQ, ymr, Pm, [23]uint8{0xf7}},
+	{AMAXPD, yxm, Pe, [23]uint8{0x5f}},
+	{AMAXPS, yxm, Pm, [23]uint8{0x5f}},
+	{AMAXSD, yxm, Pf2, [23]uint8{0x5f}},
+	{AMAXSS, yxm, Pf3, [23]uint8{0x5f}},
+	{AMINPD, yxm, Pe, [23]uint8{0x5d}},
+	{AMINPS, yxm, Pm, [23]uint8{0x5d}},
+	{AMINSD, yxm, Pf2, [23]uint8{0x5d}},
+	{AMINSS, yxm, Pf3, [23]uint8{0x5d}},
+	{AMOVAPD, yxmov, Pe, [23]uint8{0x28, 0x29}},
+	{AMOVAPS, yxmov, Pm, [23]uint8{0x28, 0x29}},
+	{AMOVB, ymovb, Pb, [23]uint8{0x88, 0x8a, 0xb0, 0xc6, 00}},
+	{AMOVBLSX, ymb_rl, Pm, [23]uint8{0xbe}},
+	{AMOVBLZX, ymb_rl, Pm, [23]uint8{0xb6}},
+	{AMOVBQSX, ymb_rl, Pw, [23]uint8{0x0f, 0xbe}},
+	{AMOVBQZX, ymb_rl, Pm, [23]uint8{0xb6}},
+	{AMOVBWSX, ymb_rl, Pq, [23]uint8{0xbe}},
+	{AMOVBWZX, ymb_rl, Pq, [23]uint8{0xb6}},
+	{AMOVO, yxmov, Pe, [23]uint8{0x6f, 0x7f}},
+	{AMOVOU, yxmov, Pf3, [23]uint8{0x6f, 0x7f}},
+	{AMOVHLPS, yxr, Pm, [23]uint8{0x12}},
+	{AMOVHPD, yxmov, Pe, [23]uint8{0x16, 0x17}},
+	{AMOVHPS, yxmov, Pm, [23]uint8{0x16, 0x17}},
+	{AMOVL, ymovl, Px, [23]uint8{0x89, 0x8b, 0x31, 0xb8, 0xc7, 00, 0x6e, 0x7e, Pe, 0x6e, Pe, 0x7e, 0}},
+	{AMOVLHPS, yxr, Pm, [23]uint8{0x16}},
+	{AMOVLPD, yxmov, Pe, [23]uint8{0x12, 0x13}},
+	{AMOVLPS, yxmov, Pm, [23]uint8{0x12, 0x13}},
+	{AMOVLQSX, yml_rl, Pw, [23]uint8{0x63}},
+	{AMOVLQZX, yml_rl, Px, [23]uint8{0x8b}},
+	{AMOVMSKPD, yxrrl, Pq, [23]uint8{0x50}},
+	{AMOVMSKPS, yxrrl, Pm, [23]uint8{0x50}},
+	{AMOVNTO, yxr_ml, Pe, [23]uint8{0xe7}},
+	{AMOVNTPD, yxr_ml, Pe, [23]uint8{0x2b}},
+	{AMOVNTPS, yxr_ml, Pm, [23]uint8{0x2b}},
+	{AMOVNTQ, ymr_ml, Pm, [23]uint8{0xe7}},
+	{AMOVQ, ymovq, Pw8, [23]uint8{0x6f, 0x7f, Pf2, 0xd6, Pf3, 0x7e, Pe, 0xd6, 0x89, 0x8b, 0x31, 0xc7, 00, 0xb8, 0xc7, 00, 0x6e, 0x7e, Pe, 0x6e, Pe, 0x7e, 0}},
+	{AMOVQOZX, ymrxr, Pf3, [23]uint8{0xd6, 0x7e}},
+	{AMOVSB, ynone, Pb, [23]uint8{0xa4}},
+	{AMOVSD, yxmov, Pf2, [23]uint8{0x10, 0x11}},
+	{AMOVSL, ynone, Px, [23]uint8{0xa5}},
+	{AMOVSQ, ynone, Pw, [23]uint8{0xa5}},
+	{AMOVSS, yxmov, Pf3, [23]uint8{0x10, 0x11}},
+	{AMOVSW, ynone, Pe, [23]uint8{0xa5}},
+	{AMOVUPD, yxmov, Pe, [23]uint8{0x10, 0x11}},
+	{AMOVUPS, yxmov, Pm, [23]uint8{0x10, 0x11}},
+	{AMOVW, ymovw, Pe, [23]uint8{0x89, 0x8b, 0x31, 0xb8, 0xc7, 00, 0}},
+	{AMOVWLSX, yml_rl, Pm, [23]uint8{0xbf}},
+	{AMOVWLZX, yml_rl, Pm, [23]uint8{0xb7}},
+	{AMOVWQSX, yml_rl, Pw, [23]uint8{0x0f, 0xbf}},
+	{AMOVWQZX, yml_rl, Pw, [23]uint8{0x0f, 0xb7}},
+	{AMULB, ydivb, Pb, [23]uint8{0xf6, 04}},
+	{AMULL, ydivl, Px, [23]uint8{0xf7, 04}},
+	{AMULPD, yxm, Pe, [23]uint8{0x59}},
+	{AMULPS, yxm, Ym, [23]uint8{0x59}},
+	{AMULQ, ydivl, Pw, [23]uint8{0xf7, 04}},
+	{AMULSD, yxm, Pf2, [23]uint8{0x59}},
+	{AMULSS, yxm, Pf3, [23]uint8{0x59}},
+	{AMULW, ydivl, Pe, [23]uint8{0xf7, 04}},
+	{ANEGB, yscond, Pb, [23]uint8{0xf6, 03}},
+	{ANEGL, yscond, Px, [23]uint8{0xf7, 03}},
+	{ANEGQ, yscond, Pw, [23]uint8{0xf7, 03}},
+	{ANEGW, yscond, Pe, [23]uint8{0xf7, 03}},
+	{obj.ANOP, ynop, Px, [23]uint8{0, 0}},
+	{ANOTB, yscond, Pb, [23]uint8{0xf6, 02}},
+	{ANOTL, yscond, Px, [23]uint8{0xf7, 02}}, // TODO(rsc): yscond is wrong here.
+	{ANOTQ, yscond, Pw, [23]uint8{0xf7, 02}},
+	{ANOTW, yscond, Pe, [23]uint8{0xf7, 02}},
+	{AORB, yxorb, Pb, [23]uint8{0x0c, 0x80, 01, 0x08, 0x0a}},
+	{AORL, yxorl, Px, [23]uint8{0x83, 01, 0x0d, 0x81, 01, 0x09, 0x0b}},
+	{AORPD, yxm, Pq, [23]uint8{0x56}},
+	{AORPS, yxm, Pm, [23]uint8{0x56}},
+	{AORQ, yxorl, Pw, [23]uint8{0x83, 01, 0x0d, 0x81, 01, 0x09, 0x0b}},
+	{AORW, yxorl, Pe, [23]uint8{0x83, 01, 0x0d, 0x81, 01, 0x09, 0x0b}},
+	{AOUTB, yin, Pb, [23]uint8{0xe6, 0xee}},
+	{AOUTL, yin, Px, [23]uint8{0xe7, 0xef}},
+	{AOUTSB, ynone, Pb, [23]uint8{0x6e}},
+	{AOUTSL, ynone, Px, [23]uint8{0x6f}},
+	{AOUTSW, ynone, Pe, [23]uint8{0x6f}},
+	{AOUTW, yin, Pe, [23]uint8{0xe7, 0xef}},
+	{APACKSSLW, ymm, Py1, [23]uint8{0x6b, Pe, 0x6b}},
+	{APACKSSWB, ymm, Py1, [23]uint8{0x63, Pe, 0x63}},
+	{APACKUSWB, ymm, Py1, [23]uint8{0x67, Pe, 0x67}},
+	{APADDB, ymm, Py1, [23]uint8{0xfc, Pe, 0xfc}},
+	{APADDL, ymm, Py1, [23]uint8{0xfe, Pe, 0xfe}},
+	{APADDQ, yxm, Pe, [23]uint8{0xd4}},
+	{APADDSB, ymm, Py1, [23]uint8{0xec, Pe, 0xec}},
+	{APADDSW, ymm, Py1, [23]uint8{0xed, Pe, 0xed}},
+	{APADDUSB, ymm, Py1, [23]uint8{0xdc, Pe, 0xdc}},
+	{APADDUSW, ymm, Py1, [23]uint8{0xdd, Pe, 0xdd}},
+	{APADDW, ymm, Py1, [23]uint8{0xfd, Pe, 0xfd}},
+	{APAND, ymm, Py1, [23]uint8{0xdb, Pe, 0xdb}},
+	{APANDN, ymm, Py1, [23]uint8{0xdf, Pe, 0xdf}},
+	{APAUSE, ynone, Px, [23]uint8{0xf3, 0x90}},
+	{APAVGB, ymm, Py1, [23]uint8{0xe0, Pe, 0xe0}},
+	{APAVGW, ymm, Py1, [23]uint8{0xe3, Pe, 0xe3}},
+	{APCMPEQB, ymm, Py1, [23]uint8{0x74, Pe, 0x74}},
+	{APCMPEQL, ymm, Py1, [23]uint8{0x76, Pe, 0x76}},
+	{APCMPEQW, ymm, Py1, [23]uint8{0x75, Pe, 0x75}},
+	{APCMPGTB, ymm, Py1, [23]uint8{0x64, Pe, 0x64}},
+	{APCMPGTL, ymm, Py1, [23]uint8{0x66, Pe, 0x66}},
+	{APCMPGTW, ymm, Py1, [23]uint8{0x65, Pe, 0x65}},
+	{APEXTRW, yextrw, Pq, [23]uint8{0xc5, 00}},
+	{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}},
+	{APHMINPOSUW, yxm_q4, Pq4, [23]uint8{0x41}},
+	{APHSUBD, yxm_q4, Pq4, [23]uint8{0x06}},
+	{APHSUBSW, yxm_q4, Pq4, [23]uint8{0x07}},
+	{APHSUBW, yxm_q4, Pq4, [23]uint8{0x05}},
+	{APINSRW, yinsrw, Pq, [23]uint8{0xc4, 00}},
+	{APINSRB, yinsr, Pq, [23]uint8{0x3a, 0x20, 00}},
+	{APINSRD, yinsr, Pq, [23]uint8{0x3a, 0x22, 00}},
+	{APINSRQ, yinsr, Pq3, [23]uint8{0x3a, 0x22, 00}},
+	{APMADDWL, ymm, Py1, [23]uint8{0xf5, Pe, 0xf5}},
+	{APMAXSW, yxm, Pe, [23]uint8{0xee}},
+	{APMAXUB, yxm, Pe, [23]uint8{0xde}},
+	{APMINSW, yxm, Pe, [23]uint8{0xea}},
+	{APMINUB, yxm, Pe, [23]uint8{0xda}},
+	{APMOVMSKB, ymskb, Px, [23]uint8{Pe, 0xd7, 0xd7}},
+	{APMOVSXBD, yxm_q4, Pq4, [23]uint8{0x21}},
+	{APMOVSXBQ, yxm_q4, Pq4, [23]uint8{0x22}},
+	{APMOVSXBW, yxm_q4, Pq4, [23]uint8{0x20}},
+	{APMOVSXDQ, yxm_q4, Pq4, [23]uint8{0x25}},
+	{APMOVSXWD, yxm_q4, Pq4, [23]uint8{0x23}},
+	{APMOVSXWQ, yxm_q4, Pq4, [23]uint8{0x24}},
+	{APMOVZXBD, yxm_q4, Pq4, [23]uint8{0x31}},
+	{APMOVZXBQ, yxm_q4, Pq4, [23]uint8{0x32}},
+	{APMOVZXBW, yxm_q4, Pq4, [23]uint8{0x30}},
+	{APMOVZXDQ, yxm_q4, Pq4, [23]uint8{0x35}},
+	{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}},
+	{APMULLW, ymm, Py1, [23]uint8{0xd5, Pe, 0xd5}},
+	{APMULULQ, ymm, Py1, [23]uint8{0xf4, Pe, 0xf4}},
+	{APOPAL, ynone, P32, [23]uint8{0x61}},
+	{APOPAW, ynone, Pe, [23]uint8{0x61}},
+	{APOPCNTW, yml_rl, Pef3, [23]uint8{0xb8}},
+	{APOPCNTL, yml_rl, Pf3, [23]uint8{0xb8}},
+	{APOPCNTQ, yml_rl, Pfw, [23]uint8{0xb8}},
+	{APOPFL, ynone, P32, [23]uint8{0x9d}},
+	{APOPFQ, ynone, Py, [23]uint8{0x9d}},
+	{APOPFW, ynone, Pe, [23]uint8{0x9d}},
+	{APOPL, ypopl, P32, [23]uint8{0x58, 0x8f, 00}},
+	{APOPQ, ypopl, Py, [23]uint8{0x58, 0x8f, 00}},
+	{APOPW, ypopl, Pe, [23]uint8{0x58, 0x8f, 00}},
+	{APOR, ymm, Py1, [23]uint8{0xeb, Pe, 0xeb}},
+	{APSADBW, yxm, Pq, [23]uint8{0xf6}},
+	{APSHUFHW, yxshuf, Pf3, [23]uint8{0x70, 00}},
+	{APSHUFL, yxshuf, Pq, [23]uint8{0x70, 00}},
+	{APSHUFLW, yxshuf, Pf2, [23]uint8{0x70, 00}},
+	{APSHUFW, ymshuf, Pm, [23]uint8{0x70, 00}},
+	{APSHUFB, ymshufb, Pq, [23]uint8{0x38, 0x00}},
+	{APSLLO, ypsdq, Pq, [23]uint8{0x73, 07}},
+	{APSLLL, yps, Py3, [23]uint8{0xf2, 0x72, 06, Pe, 0xf2, Pe, 0x72, 06}},
+	{APSLLQ, yps, Py3, [23]uint8{0xf3, 0x73, 06, Pe, 0xf3, Pe, 0x73, 06}},
+	{APSLLW, yps, Py3, [23]uint8{0xf1, 0x71, 06, Pe, 0xf1, Pe, 0x71, 06}},
+	{APSRAL, yps, Py3, [23]uint8{0xe2, 0x72, 04, Pe, 0xe2, Pe, 0x72, 04}},
+	{APSRAW, yps, Py3, [23]uint8{0xe1, 0x71, 04, Pe, 0xe1, Pe, 0x71, 04}},
+	{APSRLO, ypsdq, Pq, [23]uint8{0x73, 03}},
+	{APSRLL, yps, Py3, [23]uint8{0xd2, 0x72, 02, Pe, 0xd2, Pe, 0x72, 02}},
+	{APSRLQ, yps, Py3, [23]uint8{0xd3, 0x73, 02, Pe, 0xd3, Pe, 0x73, 02}},
+	{APSRLW, yps, Py3, [23]uint8{0xd1, 0x71, 02, Pe, 0xd1, Pe, 0x71, 02}},
+	{APSUBB, yxm, Pe, [23]uint8{0xf8}},
+	{APSUBL, yxm, Pe, [23]uint8{0xfa}},
+	{APSUBQ, yxm, Pe, [23]uint8{0xfb}},
+	{APSUBSB, yxm, Pe, [23]uint8{0xe8}},
+	{APSUBSW, yxm, Pe, [23]uint8{0xe9}},
+	{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}},
+	{APUNPCKHWL, ymm, Py1, [23]uint8{0x69, Pe, 0x69}},
+	{APUNPCKLBW, ymm, Py1, [23]uint8{0x60, Pe, 0x60}},
+	{APUNPCKLLQ, ymm, Py1, [23]uint8{0x62, Pe, 0x62}},
+	{APUNPCKLQDQ, yxm, Pe, [23]uint8{0x6c}},
+	{APUNPCKLWL, ymm, Py1, [23]uint8{0x61, Pe, 0x61}},
+	{APUSHAL, ynone, P32, [23]uint8{0x60}},
+	{APUSHAW, ynone, Pe, [23]uint8{0x60}},
+	{APUSHFL, ynone, P32, [23]uint8{0x9c}},
+	{APUSHFQ, ynone, Py, [23]uint8{0x9c}},
+	{APUSHFW, ynone, Pe, [23]uint8{0x9c}},
+	{APUSHL, ypushl, P32, [23]uint8{0x50, 0xff, 06, 0x6a, 0x68}},
+	{APUSHQ, ypushl, Py, [23]uint8{0x50, 0xff, 06, 0x6a, 0x68}},
+	{APUSHW, ypushl, Pe, [23]uint8{0x50, 0xff, 06, 0x6a, 0x68}},
+	{APXOR, ymm, Py1, [23]uint8{0xef, Pe, 0xef}},
+	{AQUAD, ybyte, Px, [23]uint8{8}},
+	{ARCLB, yshb, Pb, [23]uint8{0xd0, 02, 0xc0, 02, 0xd2, 02}},
+	{ARCLL, yshl, Px, [23]uint8{0xd1, 02, 0xc1, 02, 0xd3, 02, 0xd3, 02}},
+	{ARCLQ, yshl, Pw, [23]uint8{0xd1, 02, 0xc1, 02, 0xd3, 02, 0xd3, 02}},
+	{ARCLW, yshl, Pe, [23]uint8{0xd1, 02, 0xc1, 02, 0xd3, 02, 0xd3, 02}},
+	{ARCPPS, yxm, Pm, [23]uint8{0x53}},
+	{ARCPSS, yxm, Pf3, [23]uint8{0x53}},
+	{ARCRB, yshb, Pb, [23]uint8{0xd0, 03, 0xc0, 03, 0xd2, 03}},
+	{ARCRL, yshl, Px, [23]uint8{0xd1, 03, 0xc1, 03, 0xd3, 03, 0xd3, 03}},
+	{ARCRQ, yshl, Pw, [23]uint8{0xd1, 03, 0xc1, 03, 0xd3, 03, 0xd3, 03}},
+	{ARCRW, yshl, Pe, [23]uint8{0xd1, 03, 0xc1, 03, 0xd3, 03, 0xd3, 03}},
+	{AREP, ynone, Px, [23]uint8{0xf3}},
+	{AREPN, ynone, Px, [23]uint8{0xf2}},
+	{obj.ARET, ynone, Px, [23]uint8{0xc3}},
+	{ARETFW, yret, Pe, [23]uint8{0xcb, 0xca}},
+	{ARETFL, yret, Px, [23]uint8{0xcb, 0xca}},
+	{ARETFQ, yret, Pw, [23]uint8{0xcb, 0xca}},
+	{AROLB, yshb, Pb, [23]uint8{0xd0, 00, 0xc0, 00, 0xd2, 00}},
+	{AROLL, yshl, Px, [23]uint8{0xd1, 00, 0xc1, 00, 0xd3, 00, 0xd3, 00}},
+	{AROLQ, yshl, Pw, [23]uint8{0xd1, 00, 0xc1, 00, 0xd3, 00, 0xd3, 00}},
+	{AROLW, yshl, Pe, [23]uint8{0xd1, 00, 0xc1, 00, 0xd3, 00, 0xd3, 00}},
+	{ARORB, yshb, Pb, [23]uint8{0xd0, 01, 0xc0, 01, 0xd2, 01}},
+	{ARORL, yshl, Px, [23]uint8{0xd1, 01, 0xc1, 01, 0xd3, 01, 0xd3, 01}},
+	{ARORQ, yshl, Pw, [23]uint8{0xd1, 01, 0xc1, 01, 0xd3, 01, 0xd3, 01}},
+	{ARORW, yshl, Pe, [23]uint8{0xd1, 01, 0xc1, 01, 0xd3, 01, 0xd3, 01}},
+	{ARSQRTPS, yxm, Pm, [23]uint8{0x52}},
+	{ARSQRTSS, yxm, Pf3, [23]uint8{0x52}},
+	{ASAHF, ynone, Px1, [23]uint8{0x9e, 00, 0x86, 0xe0, 0x50, 0x9d}}, /* XCHGB AH,AL; PUSH AX; POPFL */
+	{ASALB, yshb, Pb, [23]uint8{0xd0, 04, 0xc0, 04, 0xd2, 04}},
+	{ASALL, yshl, Px, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+	{ASALQ, yshl, Pw, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+	{ASALW, yshl, Pe, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+	{ASARB, yshb, Pb, [23]uint8{0xd0, 07, 0xc0, 07, 0xd2, 07}},
+	{ASARL, yshl, Px, [23]uint8{0xd1, 07, 0xc1, 07, 0xd3, 07, 0xd3, 07}},
+	{ASARQ, yshl, Pw, [23]uint8{0xd1, 07, 0xc1, 07, 0xd3, 07, 0xd3, 07}},
+	{ASARW, yshl, Pe, [23]uint8{0xd1, 07, 0xc1, 07, 0xd3, 07, 0xd3, 07}},
+	{ASBBB, yxorb, Pb, [23]uint8{0x1c, 0x80, 03, 0x18, 0x1a}},
+	{ASBBL, yxorl, Px, [23]uint8{0x83, 03, 0x1d, 0x81, 03, 0x19, 0x1b}},
+	{ASBBQ, yxorl, Pw, [23]uint8{0x83, 03, 0x1d, 0x81, 03, 0x19, 0x1b}},
+	{ASBBW, yxorl, Pe, [23]uint8{0x83, 03, 0x1d, 0x81, 03, 0x19, 0x1b}},
+	{ASCASB, ynone, Pb, [23]uint8{0xae}},
+	{ASCASL, ynone, Px, [23]uint8{0xaf}},
+	{ASCASQ, ynone, Pw, [23]uint8{0xaf}},
+	{ASCASW, ynone, Pe, [23]uint8{0xaf}},
+	{ASETCC, yscond, Pb, [23]uint8{0x0f, 0x93, 00}},
+	{ASETCS, yscond, Pb, [23]uint8{0x0f, 0x92, 00}},
+	{ASETEQ, yscond, Pb, [23]uint8{0x0f, 0x94, 00}},
+	{ASETGE, yscond, Pb, [23]uint8{0x0f, 0x9d, 00}},
+	{ASETGT, yscond, Pb, [23]uint8{0x0f, 0x9f, 00}},
+	{ASETHI, yscond, Pb, [23]uint8{0x0f, 0x97, 00}},
+	{ASETLE, yscond, Pb, [23]uint8{0x0f, 0x9e, 00}},
+	{ASETLS, yscond, Pb, [23]uint8{0x0f, 0x96, 00}},
+	{ASETLT, yscond, Pb, [23]uint8{0x0f, 0x9c, 00}},
+	{ASETMI, yscond, Pb, [23]uint8{0x0f, 0x98, 00}},
+	{ASETNE, yscond, Pb, [23]uint8{0x0f, 0x95, 00}},
+	{ASETOC, yscond, Pb, [23]uint8{0x0f, 0x91, 00}},
+	{ASETOS, yscond, Pb, [23]uint8{0x0f, 0x90, 00}},
+	{ASETPC, yscond, Pb, [23]uint8{0x0f, 0x9b, 00}},
+	{ASETPL, yscond, Pb, [23]uint8{0x0f, 0x99, 00}},
+	{ASETPS, yscond, Pb, [23]uint8{0x0f, 0x9a, 00}},
+	{ASHLB, yshb, Pb, [23]uint8{0xd0, 04, 0xc0, 04, 0xd2, 04}},
+	{ASHLL, yshl, Px, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+	{ASHLQ, yshl, Pw, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+	{ASHLW, yshl, Pe, [23]uint8{0xd1, 04, 0xc1, 04, 0xd3, 04, 0xd3, 04}},
+	{ASHRB, yshb, Pb, [23]uint8{0xd0, 05, 0xc0, 05, 0xd2, 05}},
+	{ASHRL, yshl, Px, [23]uint8{0xd1, 05, 0xc1, 05, 0xd3, 05, 0xd3, 05}},
+	{ASHRQ, yshl, Pw, [23]uint8{0xd1, 05, 0xc1, 05, 0xd3, 05, 0xd3, 05}},
+	{ASHRW, yshl, Pe, [23]uint8{0xd1, 05, 0xc1, 05, 0xd3, 05, 0xd3, 05}},
+	{ASHUFPD, yxshuf, Pq, [23]uint8{0xc6, 00}},
+	{ASHUFPS, yxshuf, Pm, [23]uint8{0xc6, 00}},
+	{ASQRTPD, yxm, Pe, [23]uint8{0x51}},
+	{ASQRTPS, yxm, Pm, [23]uint8{0x51}},
+	{ASQRTSD, yxm, Pf2, [23]uint8{0x51}},
+	{ASQRTSS, yxm, Pf3, [23]uint8{0x51}},
+	{ASTC, ynone, Px, [23]uint8{0xf9}},
+	{ASTD, ynone, Px, [23]uint8{0xfd}},
+	{ASTI, ynone, Px, [23]uint8{0xfb}},
+	{ASTMXCSR, ysvrs, Pm, [23]uint8{0xae, 03, 0xae, 03}},
+	{ASTOSB, ynone, Pb, [23]uint8{0xaa}},
+	{ASTOSL, ynone, Px, [23]uint8{0xab}},
+	{ASTOSQ, ynone, Pw, [23]uint8{0xab}},
+	{ASTOSW, ynone, Pe, [23]uint8{0xab}},
+	{ASUBB, yxorb, Pb, [23]uint8{0x2c, 0x80, 05, 0x28, 0x2a}},
+	{ASUBL, yaddl, Px, [23]uint8{0x83, 05, 0x2d, 0x81, 05, 0x29, 0x2b}},
+	{ASUBPD, yxm, Pe, [23]uint8{0x5c}},
+	{ASUBPS, yxm, Pm, [23]uint8{0x5c}},
+	{ASUBQ, yaddl, Pw, [23]uint8{0x83, 05, 0x2d, 0x81, 05, 0x29, 0x2b}},
+	{ASUBSD, yxm, Pf2, [23]uint8{0x5c}},
+	{ASUBSS, yxm, Pf3, [23]uint8{0x5c}},
+	{ASUBW, yaddl, Pe, [23]uint8{0x83, 05, 0x2d, 0x81, 05, 0x29, 0x2b}},
+	{ASWAPGS, ynone, Pm, [23]uint8{0x01, 0xf8}},
+	{ASYSCALL, ynone, Px, [23]uint8{0x0f, 0x05}}, /* fast syscall */
+	{ATESTB, ytestb, Pb, [23]uint8{0xa8, 0xf6, 00, 0x84, 0x84}},
+	{ATESTL, ytestl, Px, [23]uint8{0xa9, 0xf7, 00, 0x85, 0x85}},
+	{ATESTQ, ytestl, Pw, [23]uint8{0xa9, 0xf7, 00, 0x85, 0x85}},
+	{ATESTW, ytestl, Pe, [23]uint8{0xa9, 0xf7, 00, 0x85, 0x85}},
+	{obj.ATEXT, ytext, Px, [23]uint8{}},
+	{AUCOMISD, yxcmp, Pe, [23]uint8{0x2e}},
+	{AUCOMISS, yxcmp, Pm, [23]uint8{0x2e}},
+	{AUNPCKHPD, yxm, Pe, [23]uint8{0x15}},
+	{AUNPCKHPS, yxm, Pm, [23]uint8{0x15}},
+	{AUNPCKLPD, yxm, Pe, [23]uint8{0x14}},
+	{AUNPCKLPS, yxm, Pm, [23]uint8{0x14}},
+	{AVERR, ydivl, Pm, [23]uint8{0x00, 04}},
+	{AVERW, ydivl, Pm, [23]uint8{0x00, 05}},
+	{AWAIT, ynone, Px, [23]uint8{0x9b}},
+	{AWORD, ybyte, Px, [23]uint8{2}},
+	{AXCHGB, yml_mb, Pb, [23]uint8{0x86, 0x86}},
+	{AXCHGL, yxchg, Px, [23]uint8{0x90, 0x90, 0x87, 0x87}},
+	{AXCHGQ, yxchg, Pw, [23]uint8{0x90, 0x90, 0x87, 0x87}},
+	{AXCHGW, yxchg, Pe, [23]uint8{0x90, 0x90, 0x87, 0x87}},
+	{AXLAT, ynone, Px, [23]uint8{0xd7}},
+	{AXORB, yxorb, Pb, [23]uint8{0x34, 0x80, 06, 0x30, 0x32}},
+	{AXORL, yxorl, Px, [23]uint8{0x83, 06, 0x35, 0x81, 06, 0x31, 0x33}},
+	{AXORPD, yxm, Pe, [23]uint8{0x57}},
+	{AXORPS, yxm, Pm, [23]uint8{0x57}},
+	{AXORQ, yxorl, Pw, [23]uint8{0x83, 06, 0x35, 0x81, 06, 0x31, 0x33}},
+	{AXORW, yxorl, Pe, [23]uint8{0x83, 06, 0x35, 0x81, 06, 0x31, 0x33}},
+	{AFMOVB, yfmvx, Px, [23]uint8{0xdf, 04}},
+	{AFMOVBP, yfmvp, Px, [23]uint8{0xdf, 06}},
+	{AFMOVD, yfmvd, Px, [23]uint8{0xdd, 00, 0xdd, 02, 0xd9, 00, 0xdd, 02}},
+	{AFMOVDP, yfmvdp, Px, [23]uint8{0xdd, 03, 0xdd, 03}},
+	{AFMOVF, yfmvf, Px, [23]uint8{0xd9, 00, 0xd9, 02}},
+	{AFMOVFP, yfmvp, Px, [23]uint8{0xd9, 03}},
+	{AFMOVL, yfmvf, Px, [23]uint8{0xdb, 00, 0xdb, 02}},
+	{AFMOVLP, yfmvp, Px, [23]uint8{0xdb, 03}},
+	{AFMOVV, yfmvx, Px, [23]uint8{0xdf, 05}},
+	{AFMOVVP, yfmvp, Px, [23]uint8{0xdf, 07}},
+	{AFMOVW, yfmvf, Px, [23]uint8{0xdf, 00, 0xdf, 02}},
+	{AFMOVWP, yfmvp, Px, [23]uint8{0xdf, 03}},
+	{AFMOVX, yfmvx, Px, [23]uint8{0xdb, 05}},
+	{AFMOVXP, yfmvp, Px, [23]uint8{0xdb, 07}},
+	{AFCMOVCC, yfcmv, Px, [23]uint8{0xdb, 00}},
+	{AFCMOVCS, yfcmv, Px, [23]uint8{0xda, 00}},
+	{AFCMOVEQ, yfcmv, Px, [23]uint8{0xda, 01}},
+	{AFCMOVHI, yfcmv, Px, [23]uint8{0xdb, 02}},
+	{AFCMOVLS, yfcmv, Px, [23]uint8{0xda, 02}},
+	{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}},
+	{AFCOMF, yfmvx, Px, [23]uint8{0xd8, 02}},
+	{AFCOMFP, yfmvx, Px, [23]uint8{0xd8, 03}},
+	{AFCOMI, yfmvx, Px, [23]uint8{0xdb, 06}},
+	{AFCOMIP, yfmvx, Px, [23]uint8{0xdf, 06}},
+	{AFCOML, yfmvx, Px, [23]uint8{0xda, 02}},
+	{AFCOMLP, yfmvx, Px, [23]uint8{0xda, 03}},
+	{AFCOMW, yfmvx, Px, [23]uint8{0xde, 02}},
+	{AFCOMWP, yfmvx, Px, [23]uint8{0xde, 03}},
+	{AFUCOM, ycompp, Px, [23]uint8{0xdd, 04}},
+	{AFUCOMI, ycompp, Px, [23]uint8{0xdb, 05}},
+	{AFUCOMIP, ycompp, Px, [23]uint8{0xdf, 05}},
+	{AFUCOMP, ycompp, Px, [23]uint8{0xdd, 05}},
+	{AFUCOMPP, ycompp, Px, [23]uint8{0xda, 13}},
+	{AFADDDP, yfaddp, Px, [23]uint8{0xde, 00}},
+	{AFADDW, yfmvx, Px, [23]uint8{0xde, 00}},
+	{AFADDL, yfmvx, Px, [23]uint8{0xda, 00}},
+	{AFADDF, yfmvx, Px, [23]uint8{0xd8, 00}},
+	{AFADDD, yfadd, Px, [23]uint8{0xdc, 00, 0xd8, 00, 0xdc, 00}},
+	{AFMULDP, yfaddp, Px, [23]uint8{0xde, 01}},
+	{AFMULW, yfmvx, Px, [23]uint8{0xde, 01}},
+	{AFMULL, yfmvx, Px, [23]uint8{0xda, 01}},
+	{AFMULF, yfmvx, Px, [23]uint8{0xd8, 01}},
+	{AFMULD, yfadd, Px, [23]uint8{0xdc, 01, 0xd8, 01, 0xdc, 01}},
+	{AFSUBDP, yfaddp, Px, [23]uint8{0xde, 05}},
+	{AFSUBW, yfmvx, Px, [23]uint8{0xde, 04}},
+	{AFSUBL, yfmvx, Px, [23]uint8{0xda, 04}},
+	{AFSUBF, yfmvx, Px, [23]uint8{0xd8, 04}},
+	{AFSUBD, yfadd, Px, [23]uint8{0xdc, 04, 0xd8, 04, 0xdc, 05}},
+	{AFSUBRDP, yfaddp, Px, [23]uint8{0xde, 04}},
+	{AFSUBRW, yfmvx, Px, [23]uint8{0xde, 05}},
+	{AFSUBRL, yfmvx, Px, [23]uint8{0xda, 05}},
+	{AFSUBRF, yfmvx, Px, [23]uint8{0xd8, 05}},
+	{AFSUBRD, yfadd, Px, [23]uint8{0xdc, 05, 0xd8, 05, 0xdc, 04}},
+	{AFDIVDP, yfaddp, Px, [23]uint8{0xde, 07}},
+	{AFDIVW, yfmvx, Px, [23]uint8{0xde, 06}},
+	{AFDIVL, yfmvx, Px, [23]uint8{0xda, 06}},
+	{AFDIVF, yfmvx, Px, [23]uint8{0xd8, 06}},
+	{AFDIVD, yfadd, Px, [23]uint8{0xdc, 06, 0xd8, 06, 0xdc, 07}},
+	{AFDIVRDP, yfaddp, Px, [23]uint8{0xde, 06}},
+	{AFDIVRW, yfmvx, Px, [23]uint8{0xde, 07}},
+	{AFDIVRL, yfmvx, Px, [23]uint8{0xda, 07}},
+	{AFDIVRF, yfmvx, Px, [23]uint8{0xd8, 07}},
+	{AFDIVRD, yfadd, Px, [23]uint8{0xdc, 07, 0xd8, 07, 0xdc, 06}},
+	{AFXCHD, yfxch, Px, [23]uint8{0xd9, 01, 0xd9, 01}},
+	{AFFREE, nil, 0, [23]uint8{}},
+	{AFLDCW, ystcw, Px, [23]uint8{0xd9, 05, 0xd9, 05}},
+	{AFLDENV, ystcw, Px, [23]uint8{0xd9, 04, 0xd9, 04}},
+	{AFRSTOR, ysvrs, Px, [23]uint8{0xdd, 04, 0xdd, 04}},
+	{AFSAVE, ysvrs, Px, [23]uint8{0xdd, 06, 0xdd, 06}},
+	{AFSTCW, ystcw, Px, [23]uint8{0xd9, 07, 0xd9, 07}},
+	{AFSTENV, ystcw, Px, [23]uint8{0xd9, 06, 0xd9, 06}},
+	{AFSTSW, ystsw, Px, [23]uint8{0xdd, 07, 0xdf, 0xe0}},
+	{AF2XM1, ynone, Px, [23]uint8{0xd9, 0xf0}},
+	{AFABS, ynone, Px, [23]uint8{0xd9, 0xe1}},
+	{AFCHS, ynone, Px, [23]uint8{0xd9, 0xe0}},
+	{AFCLEX, ynone, Px, [23]uint8{0xdb, 0xe2}},
+	{AFCOS, ynone, Px, [23]uint8{0xd9, 0xff}},
+	{AFDECSTP, ynone, Px, [23]uint8{0xd9, 0xf6}},
+	{AFINCSTP, ynone, Px, [23]uint8{0xd9, 0xf7}},
+	{AFINIT, ynone, Px, [23]uint8{0xdb, 0xe3}},
+	{AFLD1, ynone, Px, [23]uint8{0xd9, 0xe8}},
+	{AFLDL2E, ynone, Px, [23]uint8{0xd9, 0xea}},
+	{AFLDL2T, ynone, Px, [23]uint8{0xd9, 0xe9}},
+	{AFLDLG2, ynone, Px, [23]uint8{0xd9, 0xec}},
+	{AFLDLN2, ynone, Px, [23]uint8{0xd9, 0xed}},
+	{AFLDPI, ynone, Px, [23]uint8{0xd9, 0xeb}},
+	{AFLDZ, ynone, Px, [23]uint8{0xd9, 0xee}},
+	{AFNOP, ynone, Px, [23]uint8{0xd9, 0xd0}},
+	{AFPATAN, ynone, Px, [23]uint8{0xd9, 0xf3}},
+	{AFPREM, ynone, Px, [23]uint8{0xd9, 0xf8}},
+	{AFPREM1, ynone, Px, [23]uint8{0xd9, 0xf5}},
+	{AFPTAN, ynone, Px, [23]uint8{0xd9, 0xf2}},
+	{AFRNDINT, ynone, Px, [23]uint8{0xd9, 0xfc}},
+	{AFSCALE, ynone, Px, [23]uint8{0xd9, 0xfd}},
+	{AFSIN, ynone, Px, [23]uint8{0xd9, 0xfe}},
+	{AFSINCOS, ynone, Px, [23]uint8{0xd9, 0xfb}},
+	{AFSQRT, ynone, Px, [23]uint8{0xd9, 0xfa}},
+	{AFTST, ynone, Px, [23]uint8{0xd9, 0xe4}},
+	{AFXAM, ynone, Px, [23]uint8{0xd9, 0xe5}},
+	{AFXTRACT, ynone, Px, [23]uint8{0xd9, 0xf4}},
+	{AFYL2X, ynone, Px, [23]uint8{0xd9, 0xf1}},
+	{AFYL2XP1, ynone, Px, [23]uint8{0xd9, 0xf9}},
+	{ACMPXCHGB, yrb_mb, Pb, [23]uint8{0x0f, 0xb0}},
+	{ACMPXCHGL, yrl_ml, Px, [23]uint8{0x0f, 0xb1}},
+	{ACMPXCHGW, yrl_ml, Pe, [23]uint8{0x0f, 0xb1}},
+	{ACMPXCHGQ, yrl_ml, Pw, [23]uint8{0x0f, 0xb1}},
+	{ACMPXCHG8B, yscond, Pm, [23]uint8{0xc7, 01}},
+	{AINVD, ynone, Pm, [23]uint8{0x08}},
+	{AINVLPG, ymbs, Pm, [23]uint8{0x01, 07}},
+	{ALFENCE, ynone, Pm, [23]uint8{0xae, 0xe8}},
+	{AMFENCE, ynone, Pm, [23]uint8{0xae, 0xf0}},
+	{AMOVNTIL, yrl_ml, Pm, [23]uint8{0xc3}},
+	{AMOVNTIQ, yrl_ml, Pw, [23]uint8{0x0f, 0xc3}},
+	{ARDMSR, ynone, Pm, [23]uint8{0x32}},
+	{ARDPMC, ynone, Pm, [23]uint8{0x33}},
+	{ARDTSC, ynone, Pm, [23]uint8{0x31}},
+	{ARSM, ynone, Pm, [23]uint8{0xaa}},
+	{ASFENCE, ynone, Pm, [23]uint8{0xae, 0xf8}},
+	{ASYSRET, ynone, Pm, [23]uint8{0x07}},
+	{AWBINVD, ynone, Pm, [23]uint8{0x09}},
+	{AWRMSR, ynone, Pm, [23]uint8{0x30}},
+	{AXADDB, yrb_mb, Pb, [23]uint8{0x0f, 0xc0}},
+	{AXADDL, yrl_ml, Px, [23]uint8{0x0f, 0xc1}},
+	{AXADDQ, yrl_ml, Pw, [23]uint8{0x0f, 0xc1}},
+	{AXADDW, yrl_ml, Pe, [23]uint8{0x0f, 0xc1}},
+	{ACRC32B, ycrc32l, Px, [23]uint8{0xf2, 0x0f, 0x38, 0xf0, 0}},
+	{ACRC32Q, ycrc32l, Pw, [23]uint8{0xf2, 0x0f, 0x38, 0xf1, 0}},
+	{APREFETCHT0, yprefetch, Pm, [23]uint8{0x18, 01}},
+	{APREFETCHT1, yprefetch, Pm, [23]uint8{0x18, 02}},
+	{APREFETCHT2, yprefetch, Pm, [23]uint8{0x18, 03}},
+	{APREFETCHNTA, yprefetch, Pm, [23]uint8{0x18, 00}},
+	{AMOVQL, yrl_ml, Px, [23]uint8{0x89}},
+	{obj.AUNDEF, ynone, Px, [23]uint8{0x0f, 0x0b}},
+	{AAESENC, yaes, Pq, [23]uint8{0x38, 0xdc, 0}},
+	{AAESENCLAST, yaes, Pq, [23]uint8{0x38, 0xdd, 0}},
+	{AAESDEC, yaes, Pq, [23]uint8{0x38, 0xde, 0}},
+	{AAESDECLAST, yaes, Pq, [23]uint8{0x38, 0xdf, 0}},
+	{AAESIMC, yaes, Pq, [23]uint8{0x38, 0xdb, 0}},
+	{AAESKEYGENASSIST, yaes2, Pq, [23]uint8{0x3a, 0xdf, 0}},
+	{AROUNDPD, yaes2, Pq, [23]uint8{0x3a, 0x09, 0}},
+	{AROUNDPS, yaes2, Pq, [23]uint8{0x3a, 0x08, 0}},
+	{AROUNDSD, yaes2, Pq, [23]uint8{0x3a, 0x0b, 0}},
+	{AROUNDSS, yaes2, Pq, [23]uint8{0x3a, 0x0a, 0}},
+	{APSHUFD, yxshuf, Pq, [23]uint8{0x70, 0}},
+	{APCLMULQDQ, yxshuf, Pq, [23]uint8{0x3a, 0x44, 0}},
+
+	{AANDNL, yvex_r3, Pvex, [23]uint8{VEX_LZ_0F38_W0, 0xF2}},
+	{AANDNQ, yvex_r3, Pvex, [23]uint8{VEX_LZ_0F38_W1, 0xF2}},
+	{ABEXTRL, yvex_vmr3, Pvex, [23]uint8{VEX_LZ_0F38_W0, 0xF7}},
+	{ABEXTRQ, yvex_vmr3, Pvex, [23]uint8{VEX_LZ_0F38_W1, 0xF7}},
+	{ABZHIL, yvex_vmr3, Pvex, [23]uint8{VEX_LZ_0F38_W0, 0xF5}},
+	{ABZHIQ, yvex_vmr3, Pvex, [23]uint8{VEX_LZ_0F38_W1, 0xF5}},
+	{AMULXL, yvex_r3, Pvex, [23]uint8{VEX_LZ_F2_0F38_W0, 0xF6}},
+	{AMULXQ, yvex_r3, Pvex, [23]uint8{VEX_LZ_F2_0F38_W1, 0xF6}},
+	{APDEPL, yvex_r3, Pvex, [23]uint8{VEX_LZ_F2_0F38_W0, 0xF5}},
+	{APDEPQ, yvex_r3, Pvex, [23]uint8{VEX_LZ_F2_0F38_W1, 0xF5}},
+	{APEXTL, yvex_r3, Pvex, [23]uint8{VEX_LZ_F3_0F38_W0, 0xF5}},
+	{APEXTQ, yvex_r3, Pvex, [23]uint8{VEX_LZ_F3_0F38_W1, 0xF5}},
+	{ASARXL, yvex_vmr3, Pvex, [23]uint8{VEX_LZ_F3_0F38_W0, 0xF7}},
+	{ASARXQ, yvex_vmr3, Pvex, [23]uint8{VEX_LZ_F3_0F38_W1, 0xF7}},
+	{ASHLXL, yvex_vmr3, Pvex, [23]uint8{VEX_LZ_66_0F38_W0, 0xF7}},
+	{ASHLXQ, yvex_vmr3, Pvex, [23]uint8{VEX_LZ_66_0F38_W1, 0xF7}},
+	{ASHRXL, yvex_vmr3, Pvex, [23]uint8{VEX_LZ_F2_0F38_W0, 0xF7}},
+	{ASHRXQ, yvex_vmr3, Pvex, [23]uint8{VEX_LZ_F2_0F38_W1, 0xF7}},
+
+	{AVZEROUPPER, ynone, Px, [23]uint8{0xc5, 0xf8, 0x77}},
+	{AVMOVDQU, yvex_vmovdqa, Pvex, [23]uint8{VEX_128_F3_0F_WIG, 0x6F, VEX_128_F3_0F_WIG, 0x7F, VEX_256_F3_0F_WIG, 0x6F, VEX_256_F3_0F_WIG, 0x7F}},
+	{AVMOVDQA, yvex_vmovdqa, Pvex, [23]uint8{VEX_128_66_0F_WIG, 0x6F, VEX_128_66_0F_WIG, 0x7F, VEX_256_66_0F_WIG, 0x6F, VEX_256_66_0F_WIG, 0x7F}},
+	{AVMOVNTDQ, yvex_vmovntdq, Pvex, [23]uint8{VEX_128_66_0F_WIG, 0xE7, VEX_256_66_0F_WIG, 0xE7}},
+	{AVPCMPEQB, yvex_xy3, Pvex, [23]uint8{VEX_128_66_0F_WIG, 0x74, VEX_256_66_0F_WIG, 0x74}},
+	{AVPXOR, yvex_xy3, Pvex, [23]uint8{VEX_128_66_0F_WIG, 0xEF, VEX_256_66_0F_WIG, 0xEF}},
+	{AVPMOVMSKB, yvex_xyr2, Pvex, [23]uint8{VEX_128_66_0F_WIG, 0xD7, VEX_256_66_0F_WIG, 0xD7}},
+	{AVPAND, yvex_xy3, Pvex, [23]uint8{VEX_128_66_0F_WIG, 0xDB, VEX_256_66_0F_WIG, 0xDB}},
+	{AVPBROADCASTB, yvex_vpbroadcast, Pvex, [23]uint8{VEX_128_66_0F38_W0, 0x78, VEX_256_66_0F38_W0, 0x78}},
+	{AVPTEST, yvex_xy2, Pvex, [23]uint8{VEX_128_66_0F38_WIG, 0x17, VEX_256_66_0F38_WIG, 0x17}},
+
+	{AXACQUIRE, ynone, Px, [23]uint8{0xf2}},
+	{AXRELEASE, ynone, Px, [23]uint8{0xf3}},
+	{AXBEGIN, yxbegin, Px, [23]uint8{0xc7, 0xf8}},
+	{AXABORT, yxabort, Px, [23]uint8{0xc6, 0xf8}},
+	{AXEND, ynone, Px, [23]uint8{0x0f, 01, 0xd5}},
+	{AXTEST, ynone, Px, [23]uint8{0x0f, 01, 0xd6}},
+	{AXGETBV, ynone, Pm, [23]uint8{01, 0xd0}},
+	{obj.AUSEFIELD, ynop, Px, [23]uint8{0, 0}},
+	{obj.ATYPE, nil, 0, [23]uint8{}},
+	{obj.AFUNCDATA, yfuncdata, Px, [23]uint8{0, 0}},
+	{obj.APCDATA, ypcdata, Px, [23]uint8{0, 0}},
+	{obj.ACHECKNIL, nil, 0, [23]uint8{}},
+	{obj.AVARDEF, nil, 0, [23]uint8{}},
+	{obj.AVARKILL, nil, 0, [23]uint8{}},
+	{obj.ADUFFCOPY, yduff, Px, [23]uint8{0xe8}},
+	{obj.ADUFFZERO, yduff, Px, [23]uint8{0xe8}},
+	{obj.AEND, nil, 0, [23]uint8{}},
+	{0, nil, 0, [23]uint8{}},
 }
 
 var opindex [(ALAST + 1) & obj.AMask]*Optab
@@ -1517,15 +1750,15 @@ func isextern(s *obj.LSym) bool {
 // constructed by hand and disassembled with gdb to verify.
 // see http://www.agner.org/optimize/optimizing_assembly.pdf for discussion.
 var nop = [][16]uint8{
-	[16]uint8{0x90},
-	[16]uint8{0x66, 0x90},
-	[16]uint8{0x0F, 0x1F, 0x00},
-	[16]uint8{0x0F, 0x1F, 0x40, 0x00},
-	[16]uint8{0x0F, 0x1F, 0x44, 0x00, 0x00},
-	[16]uint8{0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00},
-	[16]uint8{0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00},
-	[16]uint8{0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
-	[16]uint8{0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x90},
+	{0x66, 0x90},
+	{0x0F, 0x1F, 0x00},
+	{0x0F, 0x1F, 0x40, 0x00},
+	{0x0F, 0x1F, 0x44, 0x00, 0x00},
+	{0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00},
+	{0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00},
+	{0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
+	{0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
 }
 
 // Native Client rejects the repeated 0x66 prefix.
@@ -1627,6 +1860,7 @@ func span6(ctxt *obj.Link, s *obj.LSym) {
 	var loop int32
 	var m int
 	var p *obj.Prog
+	errors := ctxt.Errors
 	for {
 		loop = 0
 		for i = 0; i < len(s.R); i++ {
@@ -1698,7 +1932,7 @@ func span6(ctxt *obj.Link, s *obj.LSym) {
 						q.Back ^= 2
 					}
 
-					if q.As == AJCXZL {
+					if q.As == AJCXZL || q.As == AXBEGIN {
 						s.P[q.Pc+2] = byte(v)
 					} else {
 						s.P[q.Pc+1] = byte(v)
@@ -1739,13 +1973,25 @@ func span6(ctxt *obj.Link, s *obj.LSym) {
 		if loop == 0 {
 			break
 		}
+		if ctxt.Errors > errors {
+			return
+		}
 	}
 
 	if ctxt.Headtype == obj.Hnacl {
 		c = naclpad(ctxt, s, c, -c&31)
 	}
 
-	c += -c & (FuncAlign - 1)
+	// Pad functions with trap instruction, to catch invalid jumps
+	if c&(FuncAlign-1) != 0 {
+		v = -c & (FuncAlign - 1)
+		obj.Symgrow(ctxt, s, int64(c)+int64(v))
+		for i := c; i < c+v; i++ {
+			// 0xCC is INT $3 - breakpoint instruction
+			s.P[i] = uint8(0xCC)
+		}
+		c += v
+	}
 	s.Size = int64(c)
 
 	if false { /* debug['a'] > 1 */
@@ -1862,6 +2108,9 @@ func instinit() {
 	ycover[Ym*Ymax+Yxm] = 1
 	ycover[Yxr*Ymax+Yxm] = 1
 
+	ycover[Ym*Ymax+Yym] = 1
+	ycover[Yyr*Ymax+Yym] = 1
+
 	for i := 0; i < MAXREG; i++ {
 		reg[i] = -1
 		if i >= REG_AL && i <= REG_R15B {
@@ -1896,6 +2145,12 @@ func instinit() {
 				regrex[i] = Rxr | Rxx | Rxb
 			}
 		}
+		if i >= REG_Y0 && i <= REG_Y0+15 {
+			reg[i] = (i - REG_Y0) & 7
+			if i >= REG_Y0+8 {
+				regrex[i] = Rxr | Rxx | Rxb
+			}
+		}
 
 		if i >= REG_CR+8 && i <= REG_CR+15 {
 			regrex[i] = Rxr
@@ -1903,6 +2158,8 @@ func instinit() {
 	}
 }
 
+var isAndroid = (obj.Getgoos() == "android")
+
 func prefixof(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) int {
 	if a.Reg < REG_CS && a.Index < REG_CS { // fast path
 		return 0
@@ -1934,6 +2191,9 @@ func prefixof(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) int {
 			if p.Mode == 32 {
 				switch ctxt.Headtype {
 				default:
+					if isAndroid {
+						return 0x65 // GS
+					}
 					log.Fatalf("unknown TLS base register for %s", obj.Headstr(ctxt.Headtype))
 
 				case obj.Hdarwin,
@@ -1950,6 +2210,10 @@ func prefixof(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) int {
 				log.Fatalf("unknown TLS base register for %s", obj.Headstr(ctxt.Headtype))
 
 			case obj.Hlinux:
+				if isAndroid {
+					return 0x64 // FS
+				}
+
 				if ctxt.Flag_shared != 0 {
 					log.Fatalf("unknown TLS base register for linux with -shared")
 				} else {
@@ -1970,6 +2234,21 @@ func prefixof(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) int {
 	}
 
 	if p.Mode == 32 {
+		if a.Index == REG_TLS && ctxt.Flag_shared != 0 {
+			// When building for inclusion into a shared library, an instruction of the form
+			//     MOVL 0(CX)(TLS*1), AX
+			// becomes
+			//     mov %gs:(%ecx), %eax
+			// which assumes that the correct TLS offset has been loaded into %ecx (today
+			// there is only one TLS variable -- g -- so this is OK). When not building for
+			// a shared library the instruction it becomes
+			//     mov 0x0(%ecx), $eax
+			// and a R_TLS_LE relocation, and so does not require a prefix.
+			if a.Offset != 0 {
+				ctxt.Diag("cannot handle non-0 offsets to TLS")
+			}
+			return 0x65 // GS
+		}
 		return 0
 	}
 
@@ -2023,14 +2302,22 @@ func oclass(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) int {
 		return Yxxx
 
 	case obj.TYPE_MEM:
+		if a.Name != obj.NAME_NONE {
+			if ctxt.Asmode == 64 && (a.Reg != REG_NONE || a.Index != REG_NONE || a.Scale != 0) {
+				return Yxxx
+			}
+		}
 		return Ym
 
 	case obj.TYPE_ADDR:
 		switch a.Name {
+		case obj.NAME_GOTREF:
+			ctxt.Diag("unexpected TYPE_ADDR with NAME_GOTREF")
+			return Yxxx
+
 		case obj.NAME_EXTERN,
-			obj.NAME_GOTREF,
 			obj.NAME_STATIC:
-			if a.Sym != nil && isextern(a.Sym) || p.Mode == 32 {
+			if a.Sym != nil && isextern(a.Sym) || (p.Mode == 32 && ctxt.Flag_shared == 0) {
 				return Yi32
 			}
 			return Yiauto // use pc-relative addressing
@@ -2201,6 +2488,24 @@ func oclass(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) int {
 		REG_X0 + 15:
 		return Yxr
 
+	case REG_Y0 + 0,
+		REG_Y0 + 1,
+		REG_Y0 + 2,
+		REG_Y0 + 3,
+		REG_Y0 + 4,
+		REG_Y0 + 5,
+		REG_Y0 + 6,
+		REG_Y0 + 7,
+		REG_Y0 + 8,
+		REG_Y0 + 9,
+		REG_Y0 + 10,
+		REG_Y0 + 11,
+		REG_Y0 + 12,
+		REG_Y0 + 13,
+		REG_Y0 + 14,
+		REG_Y0 + 15:
+		return Yyr
+
 	case REG_CS:
 		return Ycs
 	case REG_SS:
@@ -2449,7 +2754,7 @@ func vaddr(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r *obj.Reloc) int64 {
 		if a.Name == obj.NAME_GOTREF {
 			r.Siz = 4
 			r.Type = obj.R_GOTPCREL
-		} else if isextern(s) || p.Mode != 64 {
+		} else if isextern(s) || (p.Mode != 64 && ctxt.Flag_shared == 0) {
 			r.Siz = 4
 			r.Type = obj.R_ADDR
 		} else {
@@ -2470,10 +2775,12 @@ func vaddr(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r *obj.Reloc) int64 {
 			log.Fatalf("reloc")
 		}
 
-		r.Type = obj.R_TLS_LE
-		r.Siz = 4
-		r.Off = -1 // caller must fill in
-		r.Add = a.Offset
+		if ctxt.Flag_shared == 0 || isAndroid {
+			r.Type = obj.R_TLS_LE
+			r.Siz = 4
+			r.Off = -1 // caller must fill in
+			r.Add = a.Offset
+		}
 		return 0
 	}
 
@@ -2499,7 +2806,7 @@ func asmandsz(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int, rex int, m64 int)
 		goto bad
 
 	case obj.TYPE_REG:
-		if a.Reg < REG_AL || REG_X0+15 < a.Reg {
+		if a.Reg < REG_AL || REG_Y0+15 < a.Reg {
 			goto bad
 		}
 		if v != 0 {
@@ -2524,7 +2831,11 @@ func asmandsz(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int, rex int, m64 int)
 			if !isextern(a.Sym) && p.Mode == 64 {
 				goto bad
 			}
-			base = REG_NONE
+			if p.Mode == 32 && ctxt.Flag_shared != 0 {
+				base = REG_CX
+			} else {
+				base = REG_NONE
+			}
 			v = int32(vaddr(ctxt, p, a, &rel))
 
 		case obj.NAME_AUTO,
@@ -2570,7 +2881,11 @@ func asmandsz(ctxt *obj.Link, p *obj.Prog, a *obj.Addr, r int, rex int, m64 int)
 		if a.Sym == nil {
 			ctxt.Diag("bad addr: %v", p)
 		}
-		base = REG_NONE
+		if p.Mode == 32 && ctxt.Flag_shared != 0 {
+			base = REG_CX
+		} else {
+			base = REG_NONE
+		}
 		v = int32(vaddr(ctxt, p, a, &rel))
 
 	case obj.NAME_AUTO,
@@ -2702,112 +3017,112 @@ const (
 
 var ymovtab = []Movtab{
 	/* push */
-	Movtab{APUSHL, Ycs, Ynone, Ynone, 0, [4]uint8{0x0e, E, 0, 0}},
-	Movtab{APUSHL, Yss, Ynone, Ynone, 0, [4]uint8{0x16, E, 0, 0}},
-	Movtab{APUSHL, Yds, Ynone, Ynone, 0, [4]uint8{0x1e, E, 0, 0}},
-	Movtab{APUSHL, Yes, Ynone, Ynone, 0, [4]uint8{0x06, E, 0, 0}},
-	Movtab{APUSHL, Yfs, Ynone, Ynone, 0, [4]uint8{0x0f, 0xa0, E, 0}},
-	Movtab{APUSHL, Ygs, Ynone, Ynone, 0, [4]uint8{0x0f, 0xa8, E, 0}},
-	Movtab{APUSHQ, Yfs, Ynone, Ynone, 0, [4]uint8{0x0f, 0xa0, E, 0}},
-	Movtab{APUSHQ, Ygs, Ynone, Ynone, 0, [4]uint8{0x0f, 0xa8, E, 0}},
-	Movtab{APUSHW, Ycs, Ynone, Ynone, 0, [4]uint8{Pe, 0x0e, E, 0}},
-	Movtab{APUSHW, Yss, Ynone, Ynone, 0, [4]uint8{Pe, 0x16, E, 0}},
-	Movtab{APUSHW, Yds, Ynone, Ynone, 0, [4]uint8{Pe, 0x1e, E, 0}},
-	Movtab{APUSHW, Yes, Ynone, Ynone, 0, [4]uint8{Pe, 0x06, E, 0}},
-	Movtab{APUSHW, Yfs, Ynone, Ynone, 0, [4]uint8{Pe, 0x0f, 0xa0, E}},
-	Movtab{APUSHW, Ygs, Ynone, Ynone, 0, [4]uint8{Pe, 0x0f, 0xa8, E}},
+	{APUSHL, Ycs, Ynone, Ynone, 0, [4]uint8{0x0e, E, 0, 0}},
+	{APUSHL, Yss, Ynone, Ynone, 0, [4]uint8{0x16, E, 0, 0}},
+	{APUSHL, Yds, Ynone, Ynone, 0, [4]uint8{0x1e, E, 0, 0}},
+	{APUSHL, Yes, Ynone, Ynone, 0, [4]uint8{0x06, E, 0, 0}},
+	{APUSHL, Yfs, Ynone, Ynone, 0, [4]uint8{0x0f, 0xa0, E, 0}},
+	{APUSHL, Ygs, Ynone, Ynone, 0, [4]uint8{0x0f, 0xa8, E, 0}},
+	{APUSHQ, Yfs, Ynone, Ynone, 0, [4]uint8{0x0f, 0xa0, E, 0}},
+	{APUSHQ, Ygs, Ynone, Ynone, 0, [4]uint8{0x0f, 0xa8, E, 0}},
+	{APUSHW, Ycs, Ynone, Ynone, 0, [4]uint8{Pe, 0x0e, E, 0}},
+	{APUSHW, Yss, Ynone, Ynone, 0, [4]uint8{Pe, 0x16, E, 0}},
+	{APUSHW, Yds, Ynone, Ynone, 0, [4]uint8{Pe, 0x1e, E, 0}},
+	{APUSHW, Yes, Ynone, Ynone, 0, [4]uint8{Pe, 0x06, E, 0}},
+	{APUSHW, Yfs, Ynone, Ynone, 0, [4]uint8{Pe, 0x0f, 0xa0, E}},
+	{APUSHW, Ygs, Ynone, Ynone, 0, [4]uint8{Pe, 0x0f, 0xa8, E}},
 
 	/* pop */
-	Movtab{APOPL, Ynone, Ynone, Yds, 0, [4]uint8{0x1f, E, 0, 0}},
-	Movtab{APOPL, Ynone, Ynone, Yes, 0, [4]uint8{0x07, E, 0, 0}},
-	Movtab{APOPL, Ynone, Ynone, Yss, 0, [4]uint8{0x17, E, 0, 0}},
-	Movtab{APOPL, Ynone, Ynone, Yfs, 0, [4]uint8{0x0f, 0xa1, E, 0}},
-	Movtab{APOPL, Ynone, Ynone, Ygs, 0, [4]uint8{0x0f, 0xa9, E, 0}},
-	Movtab{APOPQ, Ynone, Ynone, Yfs, 0, [4]uint8{0x0f, 0xa1, E, 0}},
-	Movtab{APOPQ, Ynone, Ynone, Ygs, 0, [4]uint8{0x0f, 0xa9, E, 0}},
-	Movtab{APOPW, Ynone, Ynone, Yds, 0, [4]uint8{Pe, 0x1f, E, 0}},
-	Movtab{APOPW, Ynone, Ynone, Yes, 0, [4]uint8{Pe, 0x07, E, 0}},
-	Movtab{APOPW, Ynone, Ynone, Yss, 0, [4]uint8{Pe, 0x17, E, 0}},
-	Movtab{APOPW, Ynone, Ynone, Yfs, 0, [4]uint8{Pe, 0x0f, 0xa1, E}},
-	Movtab{APOPW, Ynone, Ynone, Ygs, 0, [4]uint8{Pe, 0x0f, 0xa9, E}},
+	{APOPL, Ynone, Ynone, Yds, 0, [4]uint8{0x1f, E, 0, 0}},
+	{APOPL, Ynone, Ynone, Yes, 0, [4]uint8{0x07, E, 0, 0}},
+	{APOPL, Ynone, Ynone, Yss, 0, [4]uint8{0x17, E, 0, 0}},
+	{APOPL, Ynone, Ynone, Yfs, 0, [4]uint8{0x0f, 0xa1, E, 0}},
+	{APOPL, Ynone, Ynone, Ygs, 0, [4]uint8{0x0f, 0xa9, E, 0}},
+	{APOPQ, Ynone, Ynone, Yfs, 0, [4]uint8{0x0f, 0xa1, E, 0}},
+	{APOPQ, Ynone, Ynone, Ygs, 0, [4]uint8{0x0f, 0xa9, E, 0}},
+	{APOPW, Ynone, Ynone, Yds, 0, [4]uint8{Pe, 0x1f, E, 0}},
+	{APOPW, Ynone, Ynone, Yes, 0, [4]uint8{Pe, 0x07, E, 0}},
+	{APOPW, Ynone, Ynone, Yss, 0, [4]uint8{Pe, 0x17, E, 0}},
+	{APOPW, Ynone, Ynone, Yfs, 0, [4]uint8{Pe, 0x0f, 0xa1, E}},
+	{APOPW, Ynone, Ynone, Ygs, 0, [4]uint8{Pe, 0x0f, 0xa9, E}},
 
 	/* mov seg */
-	Movtab{AMOVW, Yes, Ynone, Yml, 1, [4]uint8{0x8c, 0, 0, 0}},
-	Movtab{AMOVW, Ycs, Ynone, Yml, 1, [4]uint8{0x8c, 1, 0, 0}},
-	Movtab{AMOVW, Yss, Ynone, Yml, 1, [4]uint8{0x8c, 2, 0, 0}},
-	Movtab{AMOVW, Yds, Ynone, Yml, 1, [4]uint8{0x8c, 3, 0, 0}},
-	Movtab{AMOVW, Yfs, Ynone, Yml, 1, [4]uint8{0x8c, 4, 0, 0}},
-	Movtab{AMOVW, Ygs, Ynone, Yml, 1, [4]uint8{0x8c, 5, 0, 0}},
-	Movtab{AMOVW, Yml, Ynone, Yes, 2, [4]uint8{0x8e, 0, 0, 0}},
-	Movtab{AMOVW, Yml, Ynone, Ycs, 2, [4]uint8{0x8e, 1, 0, 0}},
-	Movtab{AMOVW, Yml, Ynone, Yss, 2, [4]uint8{0x8e, 2, 0, 0}},
-	Movtab{AMOVW, Yml, Ynone, Yds, 2, [4]uint8{0x8e, 3, 0, 0}},
-	Movtab{AMOVW, Yml, Ynone, Yfs, 2, [4]uint8{0x8e, 4, 0, 0}},
-	Movtab{AMOVW, Yml, Ynone, Ygs, 2, [4]uint8{0x8e, 5, 0, 0}},
+	{AMOVW, Yes, Ynone, Yml, 1, [4]uint8{0x8c, 0, 0, 0}},
+	{AMOVW, Ycs, Ynone, Yml, 1, [4]uint8{0x8c, 1, 0, 0}},
+	{AMOVW, Yss, Ynone, Yml, 1, [4]uint8{0x8c, 2, 0, 0}},
+	{AMOVW, Yds, Ynone, Yml, 1, [4]uint8{0x8c, 3, 0, 0}},
+	{AMOVW, Yfs, Ynone, Yml, 1, [4]uint8{0x8c, 4, 0, 0}},
+	{AMOVW, Ygs, Ynone, Yml, 1, [4]uint8{0x8c, 5, 0, 0}},
+	{AMOVW, Yml, Ynone, Yes, 2, [4]uint8{0x8e, 0, 0, 0}},
+	{AMOVW, Yml, Ynone, Ycs, 2, [4]uint8{0x8e, 1, 0, 0}},
+	{AMOVW, Yml, Ynone, Yss, 2, [4]uint8{0x8e, 2, 0, 0}},
+	{AMOVW, Yml, Ynone, Yds, 2, [4]uint8{0x8e, 3, 0, 0}},
+	{AMOVW, Yml, Ynone, Yfs, 2, [4]uint8{0x8e, 4, 0, 0}},
+	{AMOVW, Yml, Ynone, Ygs, 2, [4]uint8{0x8e, 5, 0, 0}},
 
 	/* mov cr */
-	Movtab{AMOVL, Ycr0, Ynone, Yml, 3, [4]uint8{0x0f, 0x20, 0, 0}},
-	Movtab{AMOVL, Ycr2, Ynone, Yml, 3, [4]uint8{0x0f, 0x20, 2, 0}},
-	Movtab{AMOVL, Ycr3, Ynone, Yml, 3, [4]uint8{0x0f, 0x20, 3, 0}},
-	Movtab{AMOVL, Ycr4, Ynone, Yml, 3, [4]uint8{0x0f, 0x20, 4, 0}},
-	Movtab{AMOVL, Ycr8, Ynone, Yml, 3, [4]uint8{0x0f, 0x20, 8, 0}},
-	Movtab{AMOVQ, Ycr0, Ynone, Yml, 3, [4]uint8{0x0f, 0x20, 0, 0}},
-	Movtab{AMOVQ, Ycr2, Ynone, Yml, 3, [4]uint8{0x0f, 0x20, 2, 0}},
-	Movtab{AMOVQ, Ycr3, Ynone, Yml, 3, [4]uint8{0x0f, 0x20, 3, 0}},
-	Movtab{AMOVQ, Ycr4, Ynone, Yml, 3, [4]uint8{0x0f, 0x20, 4, 0}},
-	Movtab{AMOVQ, Ycr8, Ynone, Yml, 3, [4]uint8{0x0f, 0x20, 8, 0}},
-	Movtab{AMOVL, Yml, Ynone, Ycr0, 4, [4]uint8{0x0f, 0x22, 0, 0}},
-	Movtab{AMOVL, Yml, Ynone, Ycr2, 4, [4]uint8{0x0f, 0x22, 2, 0}},
-	Movtab{AMOVL, Yml, Ynone, Ycr3, 4, [4]uint8{0x0f, 0x22, 3, 0}},
-	Movtab{AMOVL, Yml, Ynone, Ycr4, 4, [4]uint8{0x0f, 0x22, 4, 0}},
-	Movtab{AMOVL, Yml, Ynone, Ycr8, 4, [4]uint8{0x0f, 0x22, 8, 0}},
-	Movtab{AMOVQ, Yml, Ynone, Ycr0, 4, [4]uint8{0x0f, 0x22, 0, 0}},
-	Movtab{AMOVQ, Yml, Ynone, Ycr2, 4, [4]uint8{0x0f, 0x22, 2, 0}},
-	Movtab{AMOVQ, Yml, Ynone, Ycr3, 4, [4]uint8{0x0f, 0x22, 3, 0}},
-	Movtab{AMOVQ, Yml, Ynone, Ycr4, 4, [4]uint8{0x0f, 0x22, 4, 0}},
-	Movtab{AMOVQ, Yml, Ynone, Ycr8, 4, [4]uint8{0x0f, 0x22, 8, 0}},
+	{AMOVL, Ycr0, Ynone, Yml, 3, [4]uint8{0x0f, 0x20, 0, 0}},
+	{AMOVL, Ycr2, Ynone, Yml, 3, [4]uint8{0x0f, 0x20, 2, 0}},
+	{AMOVL, Ycr3, Ynone, Yml, 3, [4]uint8{0x0f, 0x20, 3, 0}},
+	{AMOVL, Ycr4, Ynone, Yml, 3, [4]uint8{0x0f, 0x20, 4, 0}},
+	{AMOVL, Ycr8, Ynone, Yml, 3, [4]uint8{0x0f, 0x20, 8, 0}},
+	{AMOVQ, Ycr0, Ynone, Yml, 3, [4]uint8{0x0f, 0x20, 0, 0}},
+	{AMOVQ, Ycr2, Ynone, Yml, 3, [4]uint8{0x0f, 0x20, 2, 0}},
+	{AMOVQ, Ycr3, Ynone, Yml, 3, [4]uint8{0x0f, 0x20, 3, 0}},
+	{AMOVQ, Ycr4, Ynone, Yml, 3, [4]uint8{0x0f, 0x20, 4, 0}},
+	{AMOVQ, Ycr8, Ynone, Yml, 3, [4]uint8{0x0f, 0x20, 8, 0}},
+	{AMOVL, Yml, Ynone, Ycr0, 4, [4]uint8{0x0f, 0x22, 0, 0}},
+	{AMOVL, Yml, Ynone, Ycr2, 4, [4]uint8{0x0f, 0x22, 2, 0}},
+	{AMOVL, Yml, Ynone, Ycr3, 4, [4]uint8{0x0f, 0x22, 3, 0}},
+	{AMOVL, Yml, Ynone, Ycr4, 4, [4]uint8{0x0f, 0x22, 4, 0}},
+	{AMOVL, Yml, Ynone, Ycr8, 4, [4]uint8{0x0f, 0x22, 8, 0}},
+	{AMOVQ, Yml, Ynone, Ycr0, 4, [4]uint8{0x0f, 0x22, 0, 0}},
+	{AMOVQ, Yml, Ynone, Ycr2, 4, [4]uint8{0x0f, 0x22, 2, 0}},
+	{AMOVQ, Yml, Ynone, Ycr3, 4, [4]uint8{0x0f, 0x22, 3, 0}},
+	{AMOVQ, Yml, Ynone, Ycr4, 4, [4]uint8{0x0f, 0x22, 4, 0}},
+	{AMOVQ, Yml, Ynone, Ycr8, 4, [4]uint8{0x0f, 0x22, 8, 0}},
 
 	/* mov dr */
-	Movtab{AMOVL, Ydr0, Ynone, Yml, 3, [4]uint8{0x0f, 0x21, 0, 0}},
-	Movtab{AMOVL, Ydr6, Ynone, Yml, 3, [4]uint8{0x0f, 0x21, 6, 0}},
-	Movtab{AMOVL, Ydr7, Ynone, Yml, 3, [4]uint8{0x0f, 0x21, 7, 0}},
-	Movtab{AMOVQ, Ydr0, Ynone, Yml, 3, [4]uint8{0x0f, 0x21, 0, 0}},
-	Movtab{AMOVQ, Ydr6, Ynone, Yml, 3, [4]uint8{0x0f, 0x21, 6, 0}},
-	Movtab{AMOVQ, Ydr7, Ynone, Yml, 3, [4]uint8{0x0f, 0x21, 7, 0}},
-	Movtab{AMOVL, Yml, Ynone, Ydr0, 4, [4]uint8{0x0f, 0x23, 0, 0}},
-	Movtab{AMOVL, Yml, Ynone, Ydr6, 4, [4]uint8{0x0f, 0x23, 6, 0}},
-	Movtab{AMOVL, Yml, Ynone, Ydr7, 4, [4]uint8{0x0f, 0x23, 7, 0}},
-	Movtab{AMOVQ, Yml, Ynone, Ydr0, 4, [4]uint8{0x0f, 0x23, 0, 0}},
-	Movtab{AMOVQ, Yml, Ynone, Ydr6, 4, [4]uint8{0x0f, 0x23, 6, 0}},
-	Movtab{AMOVQ, Yml, Ynone, Ydr7, 4, [4]uint8{0x0f, 0x23, 7, 0}},
+	{AMOVL, Ydr0, Ynone, Yml, 3, [4]uint8{0x0f, 0x21, 0, 0}},
+	{AMOVL, Ydr6, Ynone, Yml, 3, [4]uint8{0x0f, 0x21, 6, 0}},
+	{AMOVL, Ydr7, Ynone, Yml, 3, [4]uint8{0x0f, 0x21, 7, 0}},
+	{AMOVQ, Ydr0, Ynone, Yml, 3, [4]uint8{0x0f, 0x21, 0, 0}},
+	{AMOVQ, Ydr6, Ynone, Yml, 3, [4]uint8{0x0f, 0x21, 6, 0}},
+	{AMOVQ, Ydr7, Ynone, Yml, 3, [4]uint8{0x0f, 0x21, 7, 0}},
+	{AMOVL, Yml, Ynone, Ydr0, 4, [4]uint8{0x0f, 0x23, 0, 0}},
+	{AMOVL, Yml, Ynone, Ydr6, 4, [4]uint8{0x0f, 0x23, 6, 0}},
+	{AMOVL, Yml, Ynone, Ydr7, 4, [4]uint8{0x0f, 0x23, 7, 0}},
+	{AMOVQ, Yml, Ynone, Ydr0, 4, [4]uint8{0x0f, 0x23, 0, 0}},
+	{AMOVQ, Yml, Ynone, Ydr6, 4, [4]uint8{0x0f, 0x23, 6, 0}},
+	{AMOVQ, Yml, Ynone, Ydr7, 4, [4]uint8{0x0f, 0x23, 7, 0}},
 
 	/* mov tr */
-	Movtab{AMOVL, Ytr6, Ynone, Yml, 3, [4]uint8{0x0f, 0x24, 6, 0}},
-	Movtab{AMOVL, Ytr7, Ynone, Yml, 3, [4]uint8{0x0f, 0x24, 7, 0}},
-	Movtab{AMOVL, Yml, Ynone, Ytr6, 4, [4]uint8{0x0f, 0x26, 6, E}},
-	Movtab{AMOVL, Yml, Ynone, Ytr7, 4, [4]uint8{0x0f, 0x26, 7, E}},
+	{AMOVL, Ytr6, Ynone, Yml, 3, [4]uint8{0x0f, 0x24, 6, 0}},
+	{AMOVL, Ytr7, Ynone, Yml, 3, [4]uint8{0x0f, 0x24, 7, 0}},
+	{AMOVL, Yml, Ynone, Ytr6, 4, [4]uint8{0x0f, 0x26, 6, E}},
+	{AMOVL, Yml, Ynone, Ytr7, 4, [4]uint8{0x0f, 0x26, 7, E}},
 
 	/* lgdt, sgdt, lidt, sidt */
-	Movtab{AMOVL, Ym, Ynone, Ygdtr, 4, [4]uint8{0x0f, 0x01, 2, 0}},
-	Movtab{AMOVL, Ygdtr, Ynone, Ym, 3, [4]uint8{0x0f, 0x01, 0, 0}},
-	Movtab{AMOVL, Ym, Ynone, Yidtr, 4, [4]uint8{0x0f, 0x01, 3, 0}},
-	Movtab{AMOVL, Yidtr, Ynone, Ym, 3, [4]uint8{0x0f, 0x01, 1, 0}},
-	Movtab{AMOVQ, Ym, Ynone, Ygdtr, 4, [4]uint8{0x0f, 0x01, 2, 0}},
-	Movtab{AMOVQ, Ygdtr, Ynone, Ym, 3, [4]uint8{0x0f, 0x01, 0, 0}},
-	Movtab{AMOVQ, Ym, Ynone, Yidtr, 4, [4]uint8{0x0f, 0x01, 3, 0}},
-	Movtab{AMOVQ, Yidtr, Ynone, Ym, 3, [4]uint8{0x0f, 0x01, 1, 0}},
+	{AMOVL, Ym, Ynone, Ygdtr, 4, [4]uint8{0x0f, 0x01, 2, 0}},
+	{AMOVL, Ygdtr, Ynone, Ym, 3, [4]uint8{0x0f, 0x01, 0, 0}},
+	{AMOVL, Ym, Ynone, Yidtr, 4, [4]uint8{0x0f, 0x01, 3, 0}},
+	{AMOVL, Yidtr, Ynone, Ym, 3, [4]uint8{0x0f, 0x01, 1, 0}},
+	{AMOVQ, Ym, Ynone, Ygdtr, 4, [4]uint8{0x0f, 0x01, 2, 0}},
+	{AMOVQ, Ygdtr, Ynone, Ym, 3, [4]uint8{0x0f, 0x01, 0, 0}},
+	{AMOVQ, Ym, Ynone, Yidtr, 4, [4]uint8{0x0f, 0x01, 3, 0}},
+	{AMOVQ, Yidtr, Ynone, Ym, 3, [4]uint8{0x0f, 0x01, 1, 0}},
 
 	/* lldt, sldt */
-	Movtab{AMOVW, Yml, Ynone, Yldtr, 4, [4]uint8{0x0f, 0x00, 2, 0}},
-	Movtab{AMOVW, Yldtr, Ynone, Yml, 3, [4]uint8{0x0f, 0x00, 0, 0}},
+	{AMOVW, Yml, Ynone, Yldtr, 4, [4]uint8{0x0f, 0x00, 2, 0}},
+	{AMOVW, Yldtr, Ynone, Yml, 3, [4]uint8{0x0f, 0x00, 0, 0}},
 
 	/* lmsw, smsw */
-	Movtab{AMOVW, Yml, Ynone, Ymsw, 4, [4]uint8{0x0f, 0x01, 6, 0}},
-	Movtab{AMOVW, Ymsw, Ynone, Yml, 3, [4]uint8{0x0f, 0x01, 4, 0}},
+	{AMOVW, Yml, Ynone, Ymsw, 4, [4]uint8{0x0f, 0x01, 6, 0}},
+	{AMOVW, Ymsw, Ynone, Yml, 3, [4]uint8{0x0f, 0x01, 4, 0}},
 
 	/* ltr, str */
-	Movtab{AMOVW, Yml, Ynone, Ytask, 4, [4]uint8{0x0f, 0x00, 3, 0}},
-	Movtab{AMOVW, Ytask, Ynone, Yml, 3, [4]uint8{0x0f, 0x00, 1, 0}},
+	{AMOVW, Yml, Ynone, Ytask, 4, [4]uint8{0x0f, 0x00, 3, 0}},
+	{AMOVW, Ytask, Ynone, Yml, 3, [4]uint8{0x0f, 0x00, 1, 0}},
 
 	/* load full pointer - unsupported
 	Movtab{AMOVL, Yml, Ycol, 5, [4]uint8{0, 0, 0, 0}},
@@ -2815,29 +3130,29 @@ var ymovtab = []Movtab{
 	*/
 
 	/* double shift */
-	Movtab{ASHLL, Yi8, Yrl, Yml, 6, [4]uint8{0xa4, 0xa5, 0, 0}},
-	Movtab{ASHLL, Ycl, Yrl, Yml, 6, [4]uint8{0xa4, 0xa5, 0, 0}},
-	Movtab{ASHLL, Ycx, Yrl, Yml, 6, [4]uint8{0xa4, 0xa5, 0, 0}},
-	Movtab{ASHRL, Yi8, Yrl, Yml, 6, [4]uint8{0xac, 0xad, 0, 0}},
-	Movtab{ASHRL, Ycl, Yrl, Yml, 6, [4]uint8{0xac, 0xad, 0, 0}},
-	Movtab{ASHRL, Ycx, Yrl, Yml, 6, [4]uint8{0xac, 0xad, 0, 0}},
-	Movtab{ASHLQ, Yi8, Yrl, Yml, 6, [4]uint8{Pw, 0xa4, 0xa5, 0}},
-	Movtab{ASHLQ, Ycl, Yrl, Yml, 6, [4]uint8{Pw, 0xa4, 0xa5, 0}},
-	Movtab{ASHLQ, Ycx, Yrl, Yml, 6, [4]uint8{Pw, 0xa4, 0xa5, 0}},
-	Movtab{ASHRQ, Yi8, Yrl, Yml, 6, [4]uint8{Pw, 0xac, 0xad, 0}},
-	Movtab{ASHRQ, Ycl, Yrl, Yml, 6, [4]uint8{Pw, 0xac, 0xad, 0}},
-	Movtab{ASHRQ, Ycx, Yrl, Yml, 6, [4]uint8{Pw, 0xac, 0xad, 0}},
-	Movtab{ASHLW, Yi8, Yrl, Yml, 6, [4]uint8{Pe, 0xa4, 0xa5, 0}},
-	Movtab{ASHLW, Ycl, Yrl, Yml, 6, [4]uint8{Pe, 0xa4, 0xa5, 0}},
-	Movtab{ASHLW, Ycx, Yrl, Yml, 6, [4]uint8{Pe, 0xa4, 0xa5, 0}},
-	Movtab{ASHRW, Yi8, Yrl, Yml, 6, [4]uint8{Pe, 0xac, 0xad, 0}},
-	Movtab{ASHRW, Ycl, Yrl, Yml, 6, [4]uint8{Pe, 0xac, 0xad, 0}},
-	Movtab{ASHRW, Ycx, Yrl, Yml, 6, [4]uint8{Pe, 0xac, 0xad, 0}},
+	{ASHLL, Yi8, Yrl, Yml, 6, [4]uint8{0xa4, 0xa5, 0, 0}},
+	{ASHLL, Ycl, Yrl, Yml, 6, [4]uint8{0xa4, 0xa5, 0, 0}},
+	{ASHLL, Ycx, Yrl, Yml, 6, [4]uint8{0xa4, 0xa5, 0, 0}},
+	{ASHRL, Yi8, Yrl, Yml, 6, [4]uint8{0xac, 0xad, 0, 0}},
+	{ASHRL, Ycl, Yrl, Yml, 6, [4]uint8{0xac, 0xad, 0, 0}},
+	{ASHRL, Ycx, Yrl, Yml, 6, [4]uint8{0xac, 0xad, 0, 0}},
+	{ASHLQ, Yi8, Yrl, Yml, 6, [4]uint8{Pw, 0xa4, 0xa5, 0}},
+	{ASHLQ, Ycl, Yrl, Yml, 6, [4]uint8{Pw, 0xa4, 0xa5, 0}},
+	{ASHLQ, Ycx, Yrl, Yml, 6, [4]uint8{Pw, 0xa4, 0xa5, 0}},
+	{ASHRQ, Yi8, Yrl, Yml, 6, [4]uint8{Pw, 0xac, 0xad, 0}},
+	{ASHRQ, Ycl, Yrl, Yml, 6, [4]uint8{Pw, 0xac, 0xad, 0}},
+	{ASHRQ, Ycx, Yrl, Yml, 6, [4]uint8{Pw, 0xac, 0xad, 0}},
+	{ASHLW, Yi8, Yrl, Yml, 6, [4]uint8{Pe, 0xa4, 0xa5, 0}},
+	{ASHLW, Ycl, Yrl, Yml, 6, [4]uint8{Pe, 0xa4, 0xa5, 0}},
+	{ASHLW, Ycx, Yrl, Yml, 6, [4]uint8{Pe, 0xa4, 0xa5, 0}},
+	{ASHRW, Yi8, Yrl, Yml, 6, [4]uint8{Pe, 0xac, 0xad, 0}},
+	{ASHRW, Ycl, Yrl, Yml, 6, [4]uint8{Pe, 0xac, 0xad, 0}},
+	{ASHRW, Ycx, Yrl, Yml, 6, [4]uint8{Pe, 0xac, 0xad, 0}},
 
 	/* load TLS base */
-	Movtab{AMOVL, Ytls, Ynone, Yrl, 7, [4]uint8{0, 0, 0, 0}},
-	Movtab{AMOVQ, Ytls, Ynone, Yrl, 7, [4]uint8{0, 0, 0, 0}},
-	Movtab{0, 0, 0, 0, 0, [4]uint8{}},
+	{AMOVL, Ytls, Ynone, Yrl, 7, [4]uint8{0, 0, 0, 0}},
+	{AMOVQ, Ytls, Ynone, Yrl, 7, [4]uint8{0, 0, 0, 0}},
+	{0, 0, 0, 0, 0, [4]uint8{}},
 }
 
 func isax(a *obj.Addr) bool {
@@ -2919,6 +3234,42 @@ var bpduff2 = []byte{
 	0x48, 0x8b, 0x6d, 0x00, // MOVQ 0(BP), BP
 }
 
+// Emit VEX prefix and opcode byte.
+// The three addresses are the r/m, vvvv, and reg fields.
+// The reg and rm arguments appear in the same order as the
+// arguments to asmand, which typically follows the call to asmvex.
+// The final two arguments are the VEX prefix (see encoding above)
+// and the opcode byte.
+// For details about vex prefix see:
+// https://en.wikipedia.org/wiki/VEX_prefix#Technical_description
+func asmvex(ctxt *obj.Link, rm, v, r *obj.Addr, vex, opcode uint8) {
+	ctxt.Vexflag = 1
+	rexR := regrex[r.Reg] & Rxr
+	rexB := regrex[rm.Reg] & Rxb
+	rexX := regrex[rm.Index] & Rxx
+	vexM := (vex >> 3) & 0xF
+	vexWLP := vex & 0x87
+	vexV := byte(0)
+	if v != nil {
+		vexV = byte(reg[v.Reg]|(regrex[v.Reg]&Rxr)<<1) & 0xF
+	}
+	vexV ^= 0xF
+	if vexM == 1 && (rexX|rexB) == 0 && vex&vexW1 == 0 {
+		// Can use 2-byte encoding.
+		ctxt.Andptr[0] = 0xc5
+		ctxt.Andptr[1] = byte(rexR<<5) ^ 0x80 | vexV<<3 | vexWLP
+		ctxt.Andptr = ctxt.Andptr[2:]
+	} else {
+		// Must use 3-byte encoding.
+		ctxt.Andptr[0] = 0xc4
+		ctxt.Andptr[1] = (byte(rexR|rexX|rexB) << 5) ^ 0xE0 | vexM
+		ctxt.Andptr[2] = vexV<<3 | vexWLP
+		ctxt.Andptr = ctxt.Andptr[3:]
+	}
+	ctxt.Andptr[0] = opcode
+	ctxt.Andptr = ctxt.Andptr[1:]
+}
+
 func doasm(ctxt *obj.Link, p *obj.Prog) {
 	ctxt.Curp = p // TODO
 
@@ -3013,15 +3364,19 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
 				ctxt.Andptr[0] = Pm
 				ctxt.Andptr = ctxt.Andptr[1:]
 
-			case Pq3: /* 16 bit escape, Rex.w, and opcode escape */
+			case Pq3: /* 16 bit escape and opcode escape + REX.W */
+				ctxt.Rexflag |= Pw
 				ctxt.Andptr[0] = Pe
 				ctxt.Andptr = ctxt.Andptr[1:]
-
-				ctxt.Andptr[0] = Pw
-				ctxt.Andptr = ctxt.Andptr[1:]
 				ctxt.Andptr[0] = Pm
 				ctxt.Andptr = ctxt.Andptr[1:]
 
+			case Pq4: /*  66 0F 38 */
+				ctxt.Andptr[0] = 0x66
+				ctxt.Andptr[1] = 0x0F
+				ctxt.Andptr[2] = 0x38
+				ctxt.Andptr = ctxt.Andptr[3:]
+
 			case Pf2, /* xmm opcode escape */
 				Pf3:
 				ctxt.Andptr[0] = byte(o.prefix)
@@ -3030,6 +3385,21 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
 				ctxt.Andptr[0] = Pm
 				ctxt.Andptr = ctxt.Andptr[1:]
 
+			case Pef3:
+				ctxt.Andptr[0] = Pe
+				ctxt.Andptr = ctxt.Andptr[1:]
+				ctxt.Andptr[0] = Pf3
+				ctxt.Andptr = ctxt.Andptr[1:]
+				ctxt.Andptr[0] = Pm
+				ctxt.Andptr = ctxt.Andptr[1:]
+
+			case Pfw: /* xmm opcode escape + REX.W */
+				ctxt.Rexflag |= Pw
+				ctxt.Andptr[0] = Pf3
+				ctxt.Andptr = ctxt.Andptr[1:]
+				ctxt.Andptr[0] = Pm
+				ctxt.Andptr = ctxt.Andptr[1:]
+
 			case Pm: /* opcode escape */
 				ctxt.Andptr[0] = Pm
 				ctxt.Andptr = ctxt.Andptr[1:]
@@ -3172,7 +3542,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
 				ctxt.Andptr[0] = byte(op)
 				ctxt.Andptr = ctxt.Andptr[1:]
 
-			case Zibm_r:
+			case Zibm_r, Zibr_m:
 				for {
 					tmp1 := z
 					z++
@@ -3183,7 +3553,11 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
 					ctxt.Andptr[0] = byte(op)
 					ctxt.Andptr = ctxt.Andptr[1:]
 				}
-				asmand(ctxt, p, p.From3, &p.To)
+				if yt.zcase == Zibr_m {
+					asmand(ctxt, p, &p.To, p.From3)
+				} else {
+					asmand(ctxt, p, p.From3, &p.To)
+				}
 				ctxt.Andptr[0] = byte(p.From.Offset)
 				ctxt.Andptr = ctxt.Andptr[1:]
 
@@ -3207,6 +3581,18 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
 				ctxt.Andptr = ctxt.Andptr[1:]
 				asmand(ctxt, p, &p.To, &p.From)
 
+			case Zvex_rm_v_r:
+				asmvex(ctxt, &p.From, p.From3, &p.To, o.op[z], o.op[z+1])
+				asmand(ctxt, p, &p.From, &p.To)
+
+			case Zvex_v_rm_r:
+				asmvex(ctxt, p.From3, &p.From, &p.To, o.op[z], o.op[z+1])
+				asmand(ctxt, p, p.From3, &p.To)
+
+			case Zvex_r_v_rm:
+				asmvex(ctxt, &p.To, p.From3, &p.From, o.op[z], o.op[z+1])
+				asmand(ctxt, p, &p.To, &p.From)
+
 			case Zr_m_xm:
 				mediaop(ctxt, o, op, int(yt.zoffset), z)
 				asmand(ctxt, p, &p.To, &p.From)
@@ -3261,6 +3647,10 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
 				}
 				ctxt.Andptr[0] = byte(op)
 				ctxt.Andptr = ctxt.Andptr[1:]
+				if p.As == AXABORT {
+					ctxt.Andptr[0] = byte(o.op[z+1])
+					ctxt.Andptr = ctxt.Andptr[1:]
+				}
 				ctxt.Andptr[0] = byte(vaddr(ctxt, p, a, nil))
 				ctxt.Andptr = ctxt.Andptr[1:]
 
@@ -3482,6 +3872,10 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
 
 			// TODO: jump across functions needs reloc
 			case Zbr, Zjmp, Zloop:
+				if p.As == AXBEGIN {
+					ctxt.Andptr[0] = byte(op)
+					ctxt.Andptr = ctxt.Andptr[1:]
+				}
 				if p.To.Sym != nil {
 					if yt.zcase != Zjmp {
 						ctxt.Diag("branch to ATEXT")
@@ -3512,7 +3906,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
 
 				if p.Back&1 != 0 {
 					v = q.Pc - (p.Pc + 2)
-					if v >= -128 {
+					if v >= -128 && p.As != AXBEGIN {
 						if p.As == AJCXZL {
 							ctxt.Andptr[0] = 0x67
 							ctxt.Andptr = ctxt.Andptr[1:]
@@ -3525,6 +3919,9 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
 						ctxt.Diag("loop too far: %v", p)
 					} else {
 						v -= 5 - 2
+						if p.As == AXBEGIN {
+							v--
+						}
 						if yt.zcase == Zbr {
 							ctxt.Andptr[0] = 0x0f
 							ctxt.Andptr = ctxt.Andptr[1:]
@@ -3550,7 +3947,7 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
 				p.Forwd = q.Rel
 
 				q.Rel = p
-				if p.Back&2 != 0 { // short
+				if p.Back&2 != 0 && p.As != AXBEGIN { // short
 					if p.As == AJCXZL {
 						ctxt.Andptr[0] = 0x67
 						ctxt.Andptr = ctxt.Andptr[1:]
@@ -3780,20 +4177,52 @@ func doasm(ctxt *obj.Link, p *obj.Prog) {
 
 						case obj.Hlinux,
 							obj.Hnacl:
-							// ELF TLS base is 0(GS).
-							pp.From = p.From
-
-							pp.From.Type = obj.TYPE_MEM
-							pp.From.Reg = REG_GS
-							pp.From.Offset = 0
-							pp.From.Index = REG_NONE
-							pp.From.Scale = 0
-							ctxt.Andptr[0] = 0x65
-							ctxt.Andptr = ctxt.Andptr[1:] // GS
-							ctxt.Andptr[0] = 0x8B
-							ctxt.Andptr = ctxt.Andptr[1:]
-							asmand(ctxt, p, &pp.From, &p.To)
-
+							if ctxt.Flag_shared != 0 {
+								// Note that this is not generating the same insns as the other cases.
+								//     MOV TLS, R_to
+								// becomes
+								//     call __x86.get_pc_thunk.cx
+								//     movl (gotpc + g at gotntpoff)(%ecx),$R_To
+								// which is encoded as
+								//     call __x86.get_pc_thunk.cx
+								//     movq 0(%ecx), R_to
+								// and R_CALL & R_TLS_IE relocs. This all assumes the only tls variable we access
+								// is g, which we can't check here, but will when we assemble the second
+								// instruction.
+								ctxt.Andptr[0] = 0xe8
+								ctxt.Andptr = ctxt.Andptr[1:]
+								r = obj.Addrel(ctxt.Cursym)
+								r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+								r.Type = obj.R_CALL
+								r.Siz = 4
+								r.Sym = obj.Linklookup(ctxt, "__x86.get_pc_thunk.cx", 0)
+								put4(ctxt, 0)
+
+								ctxt.Andptr[0] = 0x8B
+								ctxt.Andptr = ctxt.Andptr[1:]
+								ctxt.Andptr[0] = byte(2<<6 | reg[REG_CX] | (reg[p.To.Reg] << 3))
+								ctxt.Andptr = ctxt.Andptr[1:]
+								r = obj.Addrel(ctxt.Cursym)
+								r.Off = int32(p.Pc + int64(-cap(ctxt.Andptr)+cap(ctxt.And[:])))
+								r.Type = obj.R_TLS_IE
+								r.Siz = 4
+								r.Add = 2
+								put4(ctxt, 0)
+							} else {
+								// ELF TLS base is 0(GS).
+								pp.From = p.From
+
+								pp.From.Type = obj.TYPE_MEM
+								pp.From.Reg = REG_GS
+								pp.From.Offset = 0
+								pp.From.Index = REG_NONE
+								pp.From.Scale = 0
+								ctxt.Andptr[0] = 0x65
+								ctxt.Andptr = ctxt.Andptr[1:] // GS
+								ctxt.Andptr[0] = 0x8B
+								ctxt.Andptr = ctxt.Andptr[1:]
+								asmand(ctxt, p, &pp.From, &p.To)
+							}
 						case obj.Hplan9:
 							if ctxt.Plan9privates == nil {
 								ctxt.Plan9privates = obj.Linklookup(ctxt, "_privates", 0)
@@ -4021,7 +4450,8 @@ bad:
 		}
 	}
 
-	ctxt.Diag("doasm: notfound ft=%d tt=%d %v %d %d", p.Ft, p.Tt, p, oclass(ctxt, p, &p.From), oclass(ctxt, p, &p.To))
+	ctxt.Diag("invalid instruction: %v", p)
+	//	ctxt.Diag("doasm: notfound ft=%d tt=%d %v %d %d", p.Ft, p.Tt, p, oclass(ctxt, p, &p.From), oclass(ctxt, p, &p.To))
 	return
 }
 
@@ -4315,10 +4745,11 @@ func asmins(ctxt *obj.Link, p *obj.Prog) {
 	}
 
 	ctxt.Rexflag = 0
+	ctxt.Vexflag = 0
 	and0 := ctxt.Andptr
 	ctxt.Asmode = int(p.Mode)
 	doasm(ctxt, p)
-	if ctxt.Rexflag != 0 {
+	if ctxt.Rexflag != 0 && ctxt.Vexflag == 0 {
 		/*
 		 * as befits the whole approach of the architecture,
 		 * the rex prefix must appear before the first opcode byte
@@ -4355,15 +4786,28 @@ func asmins(ctxt *obj.Link, p *obj.Prog) {
 			r.Off++
 		}
 		if r.Type == obj.R_PCREL {
-			// PC-relative addressing is relative to the end of the instruction,
-			// but the relocations applied by the linker are relative to the end
-			// of the relocation. Because immediate instruction
-			// arguments can follow the PC-relative memory reference in the
-			// instruction encoding, the two may not coincide. In this case,
-			// adjust addend so that linker can keep relocating relative to the
-			// end of the relocation.
-			r.Add -= p.Pc + int64(n) - (int64(r.Off) + int64(r.Siz))
+			if p.Mode == 64 || p.As == obj.AJMP || p.As == obj.ACALL {
+				// PC-relative addressing is relative to the end of the instruction,
+				// but the relocations applied by the linker are relative to the end
+				// of the relocation. Because immediate instruction
+				// arguments can follow the PC-relative memory reference in the
+				// instruction encoding, the two may not coincide. In this case,
+				// adjust addend so that linker can keep relocating relative to the
+				// end of the relocation.
+				r.Add -= p.Pc + int64(n) - (int64(r.Off) + int64(r.Siz))
+			} else if p.Mode == 32 {
+				// On 386 PC-relative addressing (for non-call/jmp instructions)
+				// assumes that the previous instruction loaded the PC of the end
+				// of that instruction into CX, so the adjustment is relative to
+				// that.
+				r.Add += int64(r.Off) - p.Pc + int64(r.Siz)
+			}
 		}
+		if r.Type == obj.R_GOTPCREL && p.Mode == 32 {
+			// On 386, R_GOTPCREL makes the same assumptions as R_PCREL.
+			r.Add += int64(r.Off) - p.Pc + int64(r.Siz)
+		}
+
 	}
 
 	if p.Mode == 64 && ctxt.Headtype == obj.Hnacl && p.As != ACMPL && p.As != ACMPQ && p.To.Type == obj.TYPE_REG {
diff --git a/src/cmd/internal/obj/x86/list6.go b/src/cmd/internal/obj/x86/list6.go
index fc79b90..0284bbf 100644
--- a/src/cmd/internal/obj/x86/list6.go
+++ b/src/cmd/internal/obj/x86/list6.go
@@ -104,6 +104,22 @@ var Register = []string{
 	"X13",
 	"X14",
 	"X15",
+	"Y0",
+	"Y1",
+	"Y2",
+	"Y3",
+	"Y4",
+	"Y5",
+	"Y6",
+	"Y7",
+	"Y8",
+	"Y9",
+	"Y10",
+	"Y11",
+	"Y12",
+	"Y13",
+	"Y14",
+	"Y15",
 	"CS", /* [D_CS] */
 	"SS",
 	"DS",
diff --git a/src/cmd/internal/obj/x86/obj6.go b/src/cmd/internal/obj/x86/obj6.go
index fa9c474..55ddfe1 100644
--- a/src/cmd/internal/obj/x86/obj6.go
+++ b/src/cmd/internal/obj/x86/obj6.go
@@ -39,6 +39,16 @@ import (
 )
 
 func canuse1insntls(ctxt *obj.Link) bool {
+	if isAndroid {
+		// For android, we use a disgusting hack that assumes
+		// the thread-local storage slot for g is allocated
+		// using pthread_key_create with a fixed offset
+		// (see src/runtime/cgo/gcc_android_amd64.c).
+		// This makes access to the TLS storage (for g) doable
+		// with 1 instruction.
+		return true
+	}
+
 	if ctxt.Arch.Regsize == 4 {
 		switch ctxt.Headtype {
 		case obj.Hlinux,
@@ -298,7 +308,36 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
 		}
 	}
 
-	if ctxt.Flag_dynlink && (p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO) {
+	if ctxt.Flag_dynlink {
+		rewriteToUseGot(ctxt, p)
+	}
+
+	if ctxt.Flag_shared != 0 && p.Mode == 32 {
+		rewriteToPcrel(ctxt, p)
+	}
+}
+
+// Rewrite p, if necessary, to access global data via the global offset table.
+func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog) {
+	var add, lea, mov, reg int16
+	if p.Mode == 64 {
+		add = AADDQ
+		lea = ALEAQ
+		mov = AMOVQ
+		reg = REG_R15
+	} else {
+		add = AADDL
+		lea = ALEAL
+		mov = AMOVL
+		reg = REG_CX
+	}
+
+	if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
+		//     ADUFFxxx $offset
+		// becomes
+		//     $MOV runtime.duffxxx at GOT, $reg
+		//     $ADD $offset, $reg
+		//     CALL $reg
 		var sym *obj.LSym
 		if p.As == obj.ADUFFZERO {
 			sym = obj.Linklookup(ctxt, "runtime.duffzero", 0)
@@ -306,100 +345,215 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
 			sym = obj.Linklookup(ctxt, "runtime.duffcopy", 0)
 		}
 		offset := p.To.Offset
-		p.As = AMOVQ
+		p.As = mov
 		p.From.Type = obj.TYPE_MEM
 		p.From.Name = obj.NAME_GOTREF
 		p.From.Sym = sym
 		p.To.Type = obj.TYPE_REG
-		p.To.Reg = REG_R15
+		p.To.Reg = reg
 		p.To.Offset = 0
 		p.To.Sym = nil
 		p1 := obj.Appendp(ctxt, p)
-		p1.As = AADDQ
+		p1.As = add
 		p1.From.Type = obj.TYPE_CONST
 		p1.From.Offset = offset
 		p1.To.Type = obj.TYPE_REG
-		p1.To.Reg = REG_R15
+		p1.To.Reg = reg
 		p2 := obj.Appendp(ctxt, p1)
 		p2.As = obj.ACALL
 		p2.To.Type = obj.TYPE_REG
-		p2.To.Reg = REG_R15
+		p2.To.Reg = reg
 	}
 
-	if ctxt.Flag_dynlink {
-		if p.As == ALEAQ && p.From.Type == obj.TYPE_MEM && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
-			p.As = AMOVQ
-			p.From.Type = obj.TYPE_ADDR
-		}
-		if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
-			if p.As != AMOVQ {
-				ctxt.Diag("do not know how to handle TYPE_ADDR in %v with -dynlink", p)
-			}
-			if p.To.Type != obj.TYPE_REG {
-				ctxt.Diag("do not know how to handle LEAQ-type insn to non-register in %v with -dynlink", p)
-			}
-			p.From.Type = obj.TYPE_MEM
-			p.From.Name = obj.NAME_GOTREF
-			if p.From.Offset != 0 {
-				q := obj.Appendp(ctxt, p)
-				q.As = AADDQ
-				q.From.Type = obj.TYPE_CONST
-				q.From.Offset = p.From.Offset
-				q.To = p.To
-				p.From.Offset = 0
+	// We only care about global data: NAME_EXTERN means a global
+	// symbol in the Go sense, and p.Sym.Local is true for a few
+	// internally defined symbols.
+	if p.As == lea && p.From.Type == obj.TYPE_MEM && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
+		// $LEA sym, Rx becomes $MOV $sym, Rx which will be rewritten below
+		p.As = mov
+		p.From.Type = obj.TYPE_ADDR
+	}
+	if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
+		// $MOV $sym, Rx becomes $MOV sym at GOT, Rx
+		// $MOV $sym+<off>, Rx becomes $MOV sym at GOT, Rx; $ADD <off>, Rx
+		// On 386 only, more complicated things like PUSHL $sym become $MOV sym at GOT, CX; PUSHL CX
+		cmplxdest := false
+		pAs := p.As
+		var dest obj.Addr
+		if p.To.Type != obj.TYPE_REG || pAs != mov {
+			if p.Mode == 64 {
+				ctxt.Diag("do not know how to handle LEA-type insn to non-register in %v with -dynlink", p)
 			}
+			cmplxdest = true
+			dest = p.To
+			p.As = mov
+			p.To.Type = obj.TYPE_REG
+			p.To.Reg = REG_CX
+			p.To.Sym = nil
+			p.To.Name = obj.NAME_NONE
 		}
-		if p.From3 != nil && p.From3.Name == obj.NAME_EXTERN {
-			ctxt.Diag("don't know how to handle %v with -dynlink", p)
+		p.From.Type = obj.TYPE_MEM
+		p.From.Name = obj.NAME_GOTREF
+		q := p
+		if p.From.Offset != 0 {
+			q = obj.Appendp(ctxt, p)
+			q.As = add
+			q.From.Type = obj.TYPE_CONST
+			q.From.Offset = p.From.Offset
+			q.To = p.To
+			p.From.Offset = 0
 		}
-		var source *obj.Addr
-		if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
-			if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
-				ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
-			}
-			source = &p.From
-		} else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
-			source = &p.To
-		} else {
-			return
+		if cmplxdest {
+			q = obj.Appendp(ctxt, q)
+			q.As = pAs
+			q.To = dest
+			q.From.Type = obj.TYPE_REG
+			q.From.Reg = REG_CX
 		}
-		if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
-			return
+	}
+	if p.From3 != nil && p.From3.Name == obj.NAME_EXTERN {
+		ctxt.Diag("don't know how to handle %v with -dynlink", p)
+	}
+	var source *obj.Addr
+	// MOVx sym, Ry becomes $MOV sym at GOT, R15; MOVx (R15), Ry
+	// MOVx Ry, sym becomes $MOV sym at GOT, R15; MOVx Ry, (R15)
+	// An addition may be inserted between the two MOVs if there is an offset.
+	if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local {
+		if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
+			ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
 		}
-		if source.Type != obj.TYPE_MEM {
-			ctxt.Diag("don't know how to handle %v with -dynlink", p)
+		source = &p.From
+	} else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local {
+		source = &p.To
+	} else {
+		return
+	}
+	if p.As == obj.ACALL {
+		// When dynlinking on 386, almost any call might end up being a call
+		// to a PLT, so make sure the GOT pointer is loaded into BX.
+		// RegTo2 is set on the replacement call insn to stop it being
+		// processed when it is in turn passed to progedit.
+		if p.Mode == 64 || (p.To.Sym != nil && p.To.Sym.Local) || p.RegTo2 != 0 {
+			return
 		}
 		p1 := obj.Appendp(ctxt, p)
 		p2 := obj.Appendp(ctxt, p1)
 
-		p1.As = AMOVQ
+		p1.As = ALEAL
 		p1.From.Type = obj.TYPE_MEM
-		p1.From.Sym = source.Sym
-		p1.From.Name = obj.NAME_GOTREF
+		p1.From.Name = obj.NAME_STATIC
+		p1.From.Sym = obj.Linklookup(ctxt, "_GLOBAL_OFFSET_TABLE_", 0)
 		p1.To.Type = obj.TYPE_REG
-		p1.To.Reg = REG_R15
+		p1.To.Reg = REG_BX
 
 		p2.As = p.As
+		p2.Scond = p.Scond
 		p2.From = p.From
+		p2.From3 = p.From3
+		p2.Reg = p.Reg
 		p2.To = p.To
-		if p.From.Name == obj.NAME_EXTERN {
-			p2.From.Reg = REG_R15
-			p2.From.Name = obj.NAME_NONE
-			p2.From.Sym = nil
-		} else if p.To.Name == obj.NAME_EXTERN {
-			p2.To.Reg = REG_R15
-			p2.To.Name = obj.NAME_NONE
-			p2.To.Sym = nil
-		} else {
-			return
+		// p.To.Type was set to TYPE_BRANCH above, but that makes checkaddr
+		// in ../pass.go complain, so set it back to TYPE_MEM here, until p2
+		// itself gets passed to progedit.
+		p2.To.Type = obj.TYPE_MEM
+		p2.RegTo2 = 1
+
+		obj.Nopout(p)
+		return
+
+	}
+	if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ARET || p.As == obj.AJMP {
+		return
+	}
+	if source.Type != obj.TYPE_MEM {
+		ctxt.Diag("don't know how to handle %v with -dynlink", p)
+	}
+	p1 := obj.Appendp(ctxt, p)
+	p2 := obj.Appendp(ctxt, p1)
+
+	p1.As = mov
+	p1.From.Type = obj.TYPE_MEM
+	p1.From.Sym = source.Sym
+	p1.From.Name = obj.NAME_GOTREF
+	p1.To.Type = obj.TYPE_REG
+	p1.To.Reg = reg
+
+	p2.As = p.As
+	p2.From = p.From
+	p2.To = p.To
+	if p.From.Name == obj.NAME_EXTERN {
+		p2.From.Reg = reg
+		p2.From.Name = obj.NAME_NONE
+		p2.From.Sym = nil
+	} else if p.To.Name == obj.NAME_EXTERN {
+		p2.To.Reg = reg
+		p2.To.Name = obj.NAME_NONE
+		p2.To.Sym = nil
+	} else {
+		return
+	}
+	obj.Nopout(p)
+}
+
+func rewriteToPcrel(ctxt *obj.Link, p *obj.Prog) {
+	// RegTo2 is set on the instructions we insert here so they don't get
+	// processed twice.
+	if p.RegTo2 != 0 {
+		return
+	}
+	if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
+		return
+	}
+	// Any Prog (aside from the above special cases) with an Addr with Name ==
+	// NAME_EXTERN, NAME_STATIC or NAME_GOTREF has a CALL __x86.get_pc_thunk.cx
+	// inserted before it.
+	isName := func(a *obj.Addr) bool {
+		if a.Sym == nil || (a.Type != obj.TYPE_MEM && a.Type != obj.TYPE_ADDR) || a.Reg != 0 {
+			return false
+		}
+		if a.Sym.Type == obj.STLSBSS {
+			return false
+		}
+		return a.Name == obj.NAME_EXTERN || a.Name == obj.NAME_STATIC || a.Name == obj.NAME_GOTREF
+	}
+
+	if isName(&p.From) && p.From.Type == obj.TYPE_ADDR {
+		// Handle things like "MOVL $sym, (SP)" or "PUSHL $sym" by rewriting
+		// to "MOVL $sym, CX; MOVL CX, (SP)" or "MOVL $sym, CX; PUSHL CX"
+		// respectively.
+		if p.To.Type != obj.TYPE_REG {
+			q := obj.Appendp(ctxt, p)
+			q.As = p.As
+			q.From.Type = obj.TYPE_REG
+			q.From.Reg = REG_CX
+			q.To = p.To
+			p.As = AMOVL
+			p.To.Type = obj.TYPE_REG
+			p.To.Reg = REG_CX
+			p.To.Sym = nil
+			p.To.Name = obj.NAME_NONE
 		}
-		l := p.Link
-		l2 := p2.Link
-		*p = *p1
-		*p1 = *p2
-		p.Link = l
-		p1.Link = l2
 	}
+
+	if !isName(&p.From) && !isName(&p.To) && (p.From3 == nil || !isName(p.From3)) {
+		return
+	}
+	q := obj.Appendp(ctxt, p)
+	q.RegTo2 = 1
+	r := obj.Appendp(ctxt, q)
+	r.RegTo2 = 1
+	q.As = obj.ACALL
+	q.To.Sym = obj.Linklookup(ctxt, "__x86.get_pc_thunk.cx", 0)
+	q.To.Type = obj.TYPE_MEM
+	q.To.Name = obj.NAME_EXTERN
+	q.To.Sym.Local = true
+	r.As = p.As
+	r.Scond = p.Scond
+	r.From = p.From
+	r.From3 = p.From3
+	r.Reg = p.Reg
+	r.To = p.To
+	obj.Nopout(p)
 }
 
 func nacladdr(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) {
@@ -435,10 +589,6 @@ func nacladdr(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) {
 }
 
 func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
-	if ctxt.Tlsg == nil {
-		ctxt.Tlsg = obj.Linklookup(ctxt, "runtime.tlsg", 0)
-	}
-
 	if ctxt.Headtype == obj.Hplan9 && ctxt.Plan9privates == nil {
 		ctxt.Plan9privates = obj.Linklookup(ctxt, "_privates", 0)
 	}
@@ -657,51 +807,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
 		p2.Pcond = p
 	}
 
-	if ctxt.Debugzerostack != 0 && autoffset != 0 && cursym.Text.From3.Offset&obj.NOSPLIT == 0 {
-		// 6l -Z means zero the stack frame on entry.
-		// This slows down function calls but can help avoid
-		// false positives in garbage collection.
-		p = obj.Appendp(ctxt, p)
-
-		p.As = AMOVQ
-		p.From.Type = obj.TYPE_REG
-		p.From.Reg = REG_SP
-		p.To.Type = obj.TYPE_REG
-		p.To.Reg = REG_DI
-		if p.Mode == 32 {
-			p.As = AMOVL
-		}
-
-		p = obj.Appendp(ctxt, p)
-		p.As = AMOVQ
-		p.From.Type = obj.TYPE_CONST
-		p.From.Offset = int64(autoffset) / int64(ctxt.Arch.Regsize)
-		p.To.Type = obj.TYPE_REG
-		p.To.Reg = REG_CX
-		if p.Mode == 32 {
-			p.As = AMOVL
-		}
-
-		p = obj.Appendp(ctxt, p)
-		p.As = AMOVQ
-		p.From.Type = obj.TYPE_CONST
-		p.From.Offset = 0
-		p.To.Type = obj.TYPE_REG
-		p.To.Reg = REG_AX
-		if p.Mode == 32 {
-			p.As = AMOVL
-		}
-
-		p = obj.Appendp(ctxt, p)
-		p.As = AREP
-
-		p = obj.Appendp(ctxt, p)
-		p.As = ASTOSQ
-		if p.Mode == 32 {
-			p.As = ASTOSL
-		}
-	}
-
 	var a int
 	var pcsize int
 	for ; p != nil; p = p.Link {
@@ -975,7 +1080,11 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32, textarg int32) *ob
 	for last = ctxt.Cursym.Text; last.Link != nil; last = last.Link {
 	}
 
-	call := obj.Appendp(ctxt, last)
+	spfix := obj.Appendp(ctxt, last)
+	spfix.As = obj.ANOP
+	spfix.Spadj = -framesize
+
+	call := obj.Appendp(ctxt, spfix)
 	call.Lineno = ctxt.Cursym.Text.Lineno
 	call.Mode = ctxt.Cursym.Text.Mode
 	call.As = obj.ACALL
@@ -993,6 +1102,7 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32, textarg int32) *ob
 	jmp.As = obj.AJMP
 	jmp.To.Type = obj.TYPE_BRANCH
 	jmp.Pcond = ctxt.Cursym.Text.Link
+	jmp.Spadj = +framesize
 
 	jls.Pcond = call
 	if q1 != nil {
diff --git a/src/cmd/internal/obj/x86/obj6_test.go b/src/cmd/internal/obj/x86/obj6_test.go
index 6302107..5fa1d3b 100644
--- a/src/cmd/internal/obj/x86/obj6_test.go
+++ b/src/cmd/internal/obj/x86/obj6_test.go
@@ -24,13 +24,13 @@ LEAQ name+10(SB), AX -> MOVQ name at GOT(SB), AX; ADDQ $10, AX
 MOVQ $name(SB), AX -> MOVQ name at GOT(SB), AX
 MOVQ $name+10(SB), AX -> MOVQ name at GOT(SB), AX; ADDQ $10, AX
 
-MOVQ name(SB), AX -> MOVQ name at GOT(SB), R15; MOVQ (R15), AX
-MOVQ name+10(SB), AX -> MOVQ name at GOT(SB), R15; MOVQ 10(R15), AX
+MOVQ name(SB), AX -> NOP; MOVQ name at GOT(SB), R15; MOVQ (R15), AX
+MOVQ name+10(SB), AX -> NOP; MOVQ name at GOT(SB), R15; MOVQ 10(R15), AX
 
-CMPQ name(SB), $0 -> MOVQ name at GOT(SB), R15; CMPQ (R15), $0
+CMPQ name(SB), $0 -> NOP; MOVQ name at GOT(SB), R15; CMPQ (R15), $0
 
-MOVQ $1, name(SB) -> MOVQ name at GOT(SB), R15; MOVQ $1, (R15)
-MOVQ $1, name+10(SB) -> MOVQ name at GOT(SB), R15; MOVQ $1, 10(R15)
+MOVQ $1, name(SB) -> NOP; MOVQ name at GOT(SB), R15; MOVQ $1, (R15)
+MOVQ $1, name+10(SB) -> NOP; MOVQ name at GOT(SB), R15; MOVQ $1, 10(R15)
 `
 
 type ParsedTestData struct {
@@ -150,6 +150,13 @@ func parseOutput(t *testing.T, td *ParsedTestData, asmout []byte) {
 func TestDynlink(t *testing.T) {
 	testenv.MustHaveGoBuild(t)
 
+	if os.Getenv("GOHOSTARCH") != "" {
+		// TODO: make this work? It was failing due to the
+		// GOARCH= filtering above and skipping is easiest for
+		// now.
+		t.Skip("skipping when GOHOSTARCH is set")
+	}
+
 	testdata := parseTestData(t)
 	asmout := asmOutput(t, testdata.input)
 	parseOutput(t, testdata, asmout)
diff --git a/src/cmd/internal/objfile/disasm.go b/src/cmd/internal/objfile/disasm.go
index 9838ce2..f038883 100644
--- a/src/cmd/internal/objfile/disasm.go
+++ b/src/cmd/internal/objfile/disasm.go
@@ -15,8 +15,8 @@ import (
 	"strings"
 	"text/tabwriter"
 
-	"cmd/internal/rsc.io/arm/armasm"
-	"cmd/internal/rsc.io/x86/x86asm"
+	"cmd/internal/unvendor/golang.org/x/arch/arm/armasm"
+	"cmd/internal/unvendor/golang.org/x/arch/x86/x86asm"
 )
 
 // Disasm is a disassembler for a given File.
@@ -195,7 +195,7 @@ func disasm_x86(code []byte, pc uint64, lookup lookupFunc, arch int) (string, in
 		size = 1
 		text = "?"
 	} else {
-		text = x86asm.Plan9Syntax(inst, pc, lookup)
+		text = x86asm.GoSyntax(inst, pc, lookup)
 	}
 	return text, size
 }
@@ -228,7 +228,7 @@ func disasm_arm(code []byte, pc uint64, lookup lookupFunc) (string, int) {
 		size = 4
 		text = "?"
 	} else {
-		text = armasm.Plan9Syntax(inst, pc, lookup, textReader{code, pc})
+		text = armasm.GoSyntax(inst, pc, lookup, textReader{code, pc})
 	}
 	return text, size
 }
diff --git a/src/cmd/internal/rsc.io/arm/armasm/decode_test.go b/src/cmd/internal/rsc.io/arm/armasm/decode_test.go
deleted file mode 100644
index 25a345a..0000000
--- a/src/cmd/internal/rsc.io/arm/armasm/decode_test.go
+++ /dev/null
@@ -1,69 +0,0 @@
-// 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 armasm
-
-import (
-	"encoding/hex"
-	"io/ioutil"
-	"strconv"
-	"strings"
-	"testing"
-)
-
-func TestDecode(t *testing.T) {
-	data, err := ioutil.ReadFile("testdata/decode.txt")
-	if err != nil {
-		t.Fatal(err)
-	}
-	all := string(data)
-	for strings.Contains(all, "\t\t") {
-		all = strings.Replace(all, "\t\t", "\t", -1)
-	}
-	for _, line := range strings.Split(all, "\n") {
-		line = strings.TrimSpace(line)
-		if line == "" || strings.HasPrefix(line, "#") {
-			continue
-		}
-		f := strings.SplitN(line, "\t", 4)
-		i := strings.Index(f[0], "|")
-		if i < 0 {
-			t.Errorf("parsing %q: missing | separator", f[0])
-			continue
-		}
-		if i%2 != 0 {
-			t.Errorf("parsing %q: misaligned | separator", f[0])
-		}
-		size := i / 2
-		code, err := hex.DecodeString(f[0][:i] + f[0][i+1:])
-		if err != nil {
-			t.Errorf("parsing %q: %v", f[0], err)
-			continue
-		}
-		mode, err := strconv.Atoi(f[1])
-		if err != nil {
-			t.Errorf("invalid mode %q in: %s", f[1], line)
-			continue
-		}
-		syntax, asm := f[2], f[3]
-		inst, err := Decode(code, Mode(mode))
-		var out string
-		if err != nil {
-			out = "error: " + err.Error()
-		} else {
-			switch syntax {
-			case "gnu":
-				out = GNUSyntax(inst)
-			case "plan9":
-				out = Plan9Syntax(inst, 0, nil, nil)
-			default:
-				t.Errorf("unknown syntax %q", syntax)
-				continue
-			}
-		}
-		if out != asm || inst.Len != size {
-			t.Errorf("Decode(%s) [%s] = %s, %d, want %s, %d", f[0], syntax, out, inst.Len, asm, size)
-		}
-	}
-}
diff --git a/src/cmd/internal/rsc.io/arm/armasm/ext_test.go b/src/cmd/internal/rsc.io/arm/armasm/ext_test.go
deleted file mode 100644
index aa87cf9..0000000
--- a/src/cmd/internal/rsc.io/arm/armasm/ext_test.go
+++ /dev/null
@@ -1,614 +0,0 @@
-// 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.
-
-// Support for testing against external disassembler program.
-// Copied and simplified from rsc.io/x86/x86asm/ext_test.go.
-
-package armasm
-
-import (
-	"bufio"
-	"bytes"
-	"encoding/hex"
-	"flag"
-	"fmt"
-	"io/ioutil"
-	"log"
-	"math/rand"
-	"os"
-	"os/exec"
-	"regexp"
-	"runtime"
-	"strings"
-	"testing"
-	"time"
-)
-
-var (
-	printTests = flag.Bool("printtests", false, "print test cases that exercise new code paths")
-	dumpTest   = flag.Bool("dump", false, "dump all encodings")
-	mismatch   = flag.Bool("mismatch", false, "log allowed mismatches")
-	longTest   = flag.Bool("long", false, "long test")
-	keep       = flag.Bool("keep", false, "keep object files around")
-	debug      = false
-)
-
-// A ExtInst represents a single decoded instruction parsed
-// from an external disassembler's output.
-type ExtInst struct {
-	addr uint32
-	enc  [4]byte
-	nenc int
-	text string
-}
-
-func (r ExtInst) String() string {
-	return fmt.Sprintf("%#x: % x: %s", r.addr, r.enc, r.text)
-}
-
-// An ExtDis is a connection between an external disassembler and a test.
-type ExtDis struct {
-	Arch     Mode
-	Dec      chan ExtInst
-	File     *os.File
-	Size     int
-	KeepFile bool
-	Cmd      *exec.Cmd
-}
-
-// Run runs the given command - the external disassembler - and returns
-// a buffered reader of its standard output.
-func (ext *ExtDis) Run(cmd ...string) (*bufio.Reader, error) {
-	if *keep {
-		log.Printf("%s\n", strings.Join(cmd, " "))
-	}
-	ext.Cmd = exec.Command(cmd[0], cmd[1:]...)
-	out, err := ext.Cmd.StdoutPipe()
-	if err != nil {
-		return nil, fmt.Errorf("stdoutpipe: %v", err)
-	}
-	if err := ext.Cmd.Start(); err != nil {
-		return nil, fmt.Errorf("exec: %v", err)
-	}
-
-	b := bufio.NewReaderSize(out, 1<<20)
-	return b, nil
-}
-
-// Wait waits for the command started with Run to exit.
-func (ext *ExtDis) Wait() error {
-	return ext.Cmd.Wait()
-}
-
-// testExtDis tests a set of byte sequences against an external disassembler.
-// The disassembler is expected to produce the given syntax and be run
-// in the given architecture mode (16, 32, or 64-bit).
-// The extdis function must start the external disassembler
-// and then parse its output, sending the parsed instructions on ext.Dec.
-// The generate function calls its argument f once for each byte sequence
-// to be tested. The generate function itself will be called twice, and it must
-// make the same sequence of calls to f each time.
-// When a disassembly does not match the internal decoding,
-// allowedMismatch determines whether this mismatch should be
-// allowed, or else considered an error.
-func testExtDis(
-	t *testing.T,
-	syntax string,
-	arch Mode,
-	extdis func(ext *ExtDis) error,
-	generate func(f func([]byte)),
-	allowedMismatch func(text string, size int, inst *Inst, dec ExtInst) bool,
-) {
-	start := time.Now()
-	ext := &ExtDis{
-		Dec:  make(chan ExtInst),
-		Arch: arch,
-	}
-	errc := make(chan error)
-
-	// First pass: write instructions to input file for external disassembler.
-	file, f, size, err := writeInst(generate)
-	if err != nil {
-		t.Fatal(err)
-	}
-	ext.Size = size
-	ext.File = f
-	defer func() {
-		f.Close()
-		if !*keep {
-			os.Remove(file)
-		}
-	}()
-
-	// Second pass: compare disassembly against our decodings.
-	var (
-		totalTests  = 0
-		totalSkips  = 0
-		totalErrors = 0
-
-		errors = make([]string, 0, 100) // sampled errors, at most cap
-	)
-	go func() {
-		errc <- extdis(ext)
-	}()
-	generate(func(enc []byte) {
-		dec, ok := <-ext.Dec
-		if !ok {
-			t.Errorf("decoding stream ended early")
-			return
-		}
-		inst, text := disasm(syntax, arch, pad(enc))
-		totalTests++
-		if *dumpTest {
-			fmt.Printf("%x -> %s [%d]\n", enc[:len(enc)], dec.text, dec.nenc)
-		}
-		if text != dec.text || inst.Len != dec.nenc {
-			suffix := ""
-			if allowedMismatch(text, size, &inst, dec) {
-				totalSkips++
-				if !*mismatch {
-					return
-				}
-				suffix += " (allowed mismatch)"
-			}
-			totalErrors++
-			if len(errors) >= cap(errors) {
-				j := rand.Intn(totalErrors)
-				if j >= cap(errors) {
-					return
-				}
-				errors = append(errors[:j], errors[j+1:]...)
-			}
-			errors = append(errors, fmt.Sprintf("decode(%x) = %q, %d, want %q, %d%s", enc, text, inst.Len, dec.text, dec.nenc, suffix))
-		}
-	})
-
-	if *mismatch {
-		totalErrors -= totalSkips
-	}
-
-	for _, b := range errors {
-		t.Log(b)
-	}
-
-	if totalErrors > 0 {
-		t.Fail()
-	}
-	t.Logf("%d test cases, %d expected mismatches, %d failures; %.0f cases/second", totalTests, totalSkips, totalErrors, float64(totalTests)/time.Since(start).Seconds())
-
-	if err := <-errc; err != nil {
-		t.Fatal("external disassembler: %v", err)
-	}
-
-}
-
-const start = 0x8000 // start address of text
-
-// writeInst writes the generated byte sequences to a new file
-// starting at offset start. That file is intended to be the input to
-// the external disassembler.
-func writeInst(generate func(func([]byte))) (file string, f *os.File, size int, err error) {
-	f, err = ioutil.TempFile("", "armasm")
-	if err != nil {
-		return
-	}
-
-	file = f.Name()
-
-	f.Seek(start, 0)
-	w := bufio.NewWriter(f)
-	defer w.Flush()
-	size = 0
-	generate(func(x []byte) {
-		if len(x) > 4 {
-			x = x[:4]
-		}
-		if debug {
-			fmt.Printf("%#x: %x%x\n", start+size, x, zeros[len(x):])
-		}
-		w.Write(x)
-		w.Write(zeros[len(x):])
-		size += len(zeros)
-	})
-	return file, f, size, nil
-}
-
-var zeros = []byte{0, 0, 0, 0}
-
-// pad pads the code sequence with pops.
-func pad(enc []byte) []byte {
-	if len(enc) < 4 {
-		enc = append(enc[:len(enc):len(enc)], zeros[:4-len(enc)]...)
-	}
-	return enc
-}
-
-// disasm returns the decoded instruction and text
-// for the given source bytes, using the given syntax and mode.
-func disasm(syntax string, mode Mode, src []byte) (inst Inst, text string) {
-	// If printTests is set, we record the coverage value
-	// before and after, and we write out the inputs for which
-	// coverage went up, in the format expected in testdata/decode.text.
-	// This produces a fairly small set of test cases that exercise nearly
-	// all the code.
-	var cover float64
-	if *printTests {
-		cover -= coverage()
-	}
-
-	inst, err := Decode(src, mode)
-	if err != nil {
-		text = "error: " + err.Error()
-	} else {
-		text = inst.String()
-		switch syntax {
-		//case "arm":
-		//	text = ARMSyntax(inst)
-		case "gnu":
-			text = GNUSyntax(inst)
-		//case "plan9":
-		//	text = Plan9Syntax(inst, 0, nil)
-		default:
-			text = "error: unknown syntax " + syntax
-		}
-	}
-
-	if *printTests {
-		cover += coverage()
-		if cover > 0 {
-			max := len(src)
-			if max > 4 && inst.Len <= 4 {
-				max = 4
-			}
-			fmt.Printf("%x|%x\t%d\t%s\t%s\n", src[:inst.Len], src[inst.Len:max], mode, syntax, text)
-		}
-	}
-
-	return
-}
-
-// coverage returns a floating point number denoting the
-// test coverage until now. The number increases when new code paths are exercised,
-// both in the Go program and in the decoder byte code.
-func coverage() float64 {
-	/*
-		testing.Coverage is not in the main distribution.
-		The implementation, which must go in package testing, is:
-
-		// Coverage reports the current code coverage as a fraction in the range [0, 1].
-		func Coverage() float64 {
-			var n, d int64
-			for _, counters := range cover.Counters {
-				for _, c := range counters {
-					if c > 0 {
-						n++
-					}
-					d++
-				}
-			}
-			if d == 0 {
-				return 0
-			}
-			return float64(n) / float64(d)
-		}
-	*/
-
-	var f float64
-	f += testing.Coverage()
-	f += decodeCoverage()
-	return f
-}
-
-func decodeCoverage() float64 {
-	n := 0
-	for _, t := range decoderCover {
-		if t {
-			n++
-		}
-	}
-	return float64(1+n) / float64(1+len(decoderCover))
-}
-
-// Helpers for writing disassembler output parsers.
-
-// hasPrefix reports whether any of the space-separated words in the text s
-// begins with any of the given prefixes.
-func hasPrefix(s string, prefixes ...string) bool {
-	for _, prefix := range prefixes {
-		for s := s; s != ""; {
-			if strings.HasPrefix(s, prefix) {
-				return true
-			}
-			i := strings.Index(s, " ")
-			if i < 0 {
-				break
-			}
-			s = s[i+1:]
-		}
-	}
-	return false
-}
-
-// contains reports whether the text s contains any of the given substrings.
-func contains(s string, substrings ...string) bool {
-	for _, sub := range substrings {
-		if strings.Contains(s, sub) {
-			return true
-		}
-	}
-	return false
-}
-
-// isHex reports whether b is a hexadecimal character (0-9A-Fa-f).
-func isHex(b byte) bool { return b == '0' || unhex[b] > 0 }
-
-// parseHex parses the hexadecimal byte dump in hex,
-// appending the parsed bytes to raw and returning the updated slice.
-// The returned bool signals whether any invalid hex was found.
-// Spaces and tabs between bytes are okay but any other non-hex is not.
-func parseHex(hex []byte, raw []byte) ([]byte, bool) {
-	hex = trimSpace(hex)
-	for j := 0; j < len(hex); {
-		for hex[j] == ' ' || hex[j] == '\t' {
-			j++
-		}
-		if j >= len(hex) {
-			break
-		}
-		if j+2 > len(hex) || !isHex(hex[j]) || !isHex(hex[j+1]) {
-			return nil, false
-		}
-		raw = append(raw, unhex[hex[j]]<<4|unhex[hex[j+1]])
-		j += 2
-	}
-	return raw, true
-}
-
-var unhex = [256]byte{
-	'0': 0,
-	'1': 1,
-	'2': 2,
-	'3': 3,
-	'4': 4,
-	'5': 5,
-	'6': 6,
-	'7': 7,
-	'8': 8,
-	'9': 9,
-	'A': 10,
-	'B': 11,
-	'C': 12,
-	'D': 13,
-	'E': 14,
-	'F': 15,
-	'a': 10,
-	'b': 11,
-	'c': 12,
-	'd': 13,
-	'e': 14,
-	'f': 15,
-}
-
-// index is like bytes.Index(s, []byte(t)) but avoids the allocation.
-func index(s []byte, t string) int {
-	i := 0
-	for {
-		j := bytes.IndexByte(s[i:], t[0])
-		if j < 0 {
-			return -1
-		}
-		i = i + j
-		if i+len(t) > len(s) {
-			return -1
-		}
-		for k := 1; k < len(t); k++ {
-			if s[i+k] != t[k] {
-				goto nomatch
-			}
-		}
-		return i
-	nomatch:
-		i++
-	}
-}
-
-// fixSpace rewrites runs of spaces, tabs, and newline characters into single spaces in s.
-// If s must be rewritten, it is rewritten in place.
-func fixSpace(s []byte) []byte {
-	s = trimSpace(s)
-	for i := 0; i < len(s); i++ {
-		if s[i] == '\t' || s[i] == '\n' || i > 0 && s[i] == ' ' && s[i-1] == ' ' {
-			goto Fix
-		}
-	}
-	return s
-
-Fix:
-	b := s
-	w := 0
-	for i := 0; i < len(s); i++ {
-		c := s[i]
-		if c == '\t' || c == '\n' {
-			c = ' '
-		}
-		if c == ' ' && w > 0 && b[w-1] == ' ' {
-			continue
-		}
-		b[w] = c
-		w++
-	}
-	if w > 0 && b[w-1] == ' ' {
-		w--
-	}
-	return b[:w]
-}
-
-// trimSpace trims leading and trailing space from s, returning a subslice of s.
-func trimSpace(s []byte) []byte {
-	j := len(s)
-	for j > 0 && (s[j-1] == ' ' || s[j-1] == '\t' || s[j-1] == '\n') {
-		j--
-	}
-	i := 0
-	for i < j && (s[i] == ' ' || s[i] == '\t') {
-		i++
-	}
-	return s[i:j]
-}
-
-// pcrel matches instructions using relative addressing mode.
-var (
-	pcrel = regexp.MustCompile(`^((?:.* )?(?:b|bl)x?(?:eq|ne|cs|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le)?) 0x([0-9a-f]+)$`)
-)
-
-// Generators.
-//
-// The test cases are described as functions that invoke a callback repeatedly,
-// with a new input sequence each time. These helpers make writing those
-// a little easier.
-
-// condCases generates conditional instructions.
-func condCases(t *testing.T) func(func([]byte)) {
-	return func(try func([]byte)) {
-		// All the strides are relatively prime to 2 and therefore to 2²⁸,
-		// so we will not repeat any instructions until we have tried all 2²⁸.
-		// Using a stride other than 1 is meant to visit the instructions in a
-		// pseudorandom order, which gives better variety in the set of
-		// test cases chosen by -printtests.
-		stride := uint32(10007)
-		n := 1 << 28 / 7
-		if testing.Short() {
-			stride = 100003
-			n = 1 << 28 / 1001
-		} else if *longTest {
-			stride = 200000033
-			n = 1 << 28
-		}
-		x := uint32(0)
-		for i := 0; i < n; i++ {
-			enc := (x%15)<<28 | x&(1<<28-1)
-			try([]byte{byte(enc), byte(enc >> 8), byte(enc >> 16), byte(enc >> 24)})
-			x += stride
-		}
-	}
-}
-
-// uncondCases generates unconditional instructions.
-func uncondCases(t *testing.T) func(func([]byte)) {
-	return func(try func([]byte)) {
-		condCases(t)(func(enc []byte) {
-			enc[3] |= 0xF0
-			try(enc)
-		})
-	}
-}
-
-func countBits(x uint32) int {
-	n := 0
-	for ; x != 0; x >>= 1 {
-		n += int(x & 1)
-	}
-	return n
-}
-
-func expandBits(x, m uint32) uint32 {
-	var out uint32
-	for i := uint(0); i < 32; i++ {
-		out >>= 1
-		if m&1 != 0 {
-			out |= (x & 1) << 31
-			x >>= 1
-		}
-		m >>= 1
-	}
-	return out
-}
-
-func tryCondMask(mask, val uint32, try func([]byte)) {
-	n := countBits(^mask)
-	bits := uint32(0)
-	for i := 0; i < 1<<uint(n); i++ {
-		bits += 848251 // arbitrary prime
-		x := val | expandBits(bits, ^mask) | uint32(i)%15<<28
-		try([]byte{byte(x), byte(x >> 8), byte(x >> 16), byte(x >> 24)})
-	}
-}
-
-// vfpCases generates VFP instructions.
-func vfpCases(t *testing.T) func(func([]byte)) {
-	const (
-		vfpmask uint32 = 0xFF00FE10
-		vfp     uint32 = 0x0E009A00
-	)
-	return func(try func([]byte)) {
-		tryCondMask(0xff00fe10, 0x0e009a00, try) // standard VFP instruction space
-		tryCondMask(0xffc00f7f, 0x0e000b10, try) // VFP MOV core reg to/from float64 half
-		tryCondMask(0xffe00f7f, 0x0e000a10, try) // VFP MOV core reg to/from float32
-		tryCondMask(0xffef0fff, 0x0ee10a10, try) // VFP MOV core reg to/from cond codes
-	}
-}
-
-// hexCases generates the cases written in hexadecimal in the encoded string.
-// Spaces in 'encoded' separate entire test cases, not individual bytes.
-func hexCases(t *testing.T, encoded string) func(func([]byte)) {
-	return func(try func([]byte)) {
-		for _, x := range strings.Fields(encoded) {
-			src, err := hex.DecodeString(x)
-			if err != nil {
-				t.Errorf("parsing %q: %v", x, err)
-			}
-			try(src)
-		}
-	}
-}
-
-// testdataCases generates the test cases recorded in testdata/decode.txt.
-// It only uses the inputs; it ignores the answers recorded in that file.
-func testdataCases(t *testing.T) func(func([]byte)) {
-	var codes [][]byte
-	data, err := ioutil.ReadFile("testdata/decode.txt")
-	if err != nil {
-		t.Fatal(err)
-	}
-	for _, line := range strings.Split(string(data), "\n") {
-		line = strings.TrimSpace(line)
-		if line == "" || strings.HasPrefix(line, "#") {
-			continue
-		}
-		f := strings.Fields(line)[0]
-		i := strings.Index(f, "|")
-		if i < 0 {
-			t.Errorf("parsing %q: missing | separator", f)
-			continue
-		}
-		if i%2 != 0 {
-			t.Errorf("parsing %q: misaligned | separator", f)
-		}
-		code, err := hex.DecodeString(f[:i] + f[i+1:])
-		if err != nil {
-			t.Errorf("parsing %q: %v", f, err)
-			continue
-		}
-		codes = append(codes, code)
-	}
-
-	return func(try func([]byte)) {
-		for _, code := range codes {
-			try(code)
-		}
-	}
-}
-
-func caller(skip int) string {
-	pc, _, _, _ := runtime.Caller(skip)
-	f := runtime.FuncForPC(pc)
-	name := "?"
-	if f != nil {
-		name = f.Name()
-		if i := strings.LastIndex(name, "."); i >= 0 {
-			name = name[i+1:]
-		}
-	}
-	return name
-}
diff --git a/src/cmd/internal/rsc.io/arm/armasm/objdump_test.go b/src/cmd/internal/rsc.io/arm/armasm/objdump_test.go
deleted file mode 100644
index 00a00e7..0000000
--- a/src/cmd/internal/rsc.io/arm/armasm/objdump_test.go
+++ /dev/null
@@ -1,258 +0,0 @@
-// 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 armasm
-
-import (
-	"encoding/binary"
-	"strings"
-	"testing"
-)
-
-func TestObjdumpARMTestdata(t *testing.T) { testObjdumpARM(t, testdataCases(t)) }
-func TestObjdumpARMManual(t *testing.T)   { testObjdumpARM(t, hexCases(t, objdumpManualTests)) }
-func TestObjdumpARMCond(t *testing.T)     { testObjdumpARM(t, condCases(t)) }
-func TestObjdumpARMUncond(t *testing.T)   { testObjdumpARM(t, uncondCases(t)) }
-func TestObjdumpARMVFP(t *testing.T)      { testObjdumpARM(t, vfpCases(t)) }
-
-// objdumpManualTests holds test cases that will be run by TestObjdumpARMManual.
-// If you are debugging a few cases that turned up in a longer run, it can be useful
-// to list them here and then use -run=Manual, particularly with tracing enabled.
-// Note that these are byte sequences, so they must be reversed from the usual
-// word presentation.
-var objdumpManualTests = `
-00000000
-`
-
-// allowedMismatchObjdump reports whether the mismatch between text and dec
-// should be allowed by the test.
-func allowedMismatchObjdump(text string, size int, inst *Inst, dec ExtInst) bool {
-	if hasPrefix(text, "error:") {
-		if hasPrefix(dec.text, unsupported...) || strings.Contains(dec.text, "invalid:") || strings.HasSuffix(dec.text, "^") || strings.Contains(dec.text, "f16.f64") || strings.Contains(dec.text, "f64.f16") {
-			return true
-		}
-		// word 4320F02C: libopcodes says 'nopmi {44}'.
-		if hasPrefix(dec.text, "nop") && strings.Contains(dec.text, "{") {
-			return true
-		}
-	}
-
-	if hasPrefix(dec.text, "error:") && text == "undef" && inst.Enc == 0xf7fabcfd {
-		return true
-	}
-
-	// word 00f02053: libopcodes says 'noppl {0}'.
-	if hasPrefix(dec.text, "nop") && hasPrefix(text, "nop") && dec.text == text+" {0}" {
-		return true
-	}
-
-	// word F57FF04F. we say 'dsb #15', libopcodes says 'dsb sy'.
-	if hasPrefix(text, "dsb") && hasPrefix(dec.text, "dsb") {
-		return true
-	}
-	// word F57FF06F. we say 'isb #15', libopcodes says 'isb sy'.
-	if hasPrefix(text, "isb") && hasPrefix(dec.text, "isb") {
-		return true
-	}
-	// word F57FF053. we say 'dmb #3', libopcodes says 'dmb osh'.
-	if hasPrefix(text, "dmb") && hasPrefix(dec.text, "dmb") {
-		return true
-	}
-
-	// word 992D0000. push/stmdb with no registers (undefined).
-	// we say 'stmdbls sp!, {}', libopcodes says 'pushls {}'.
-	if hasPrefix(text, "stmdb") && hasPrefix(dec.text, "push") && strings.Contains(text, "{}") && strings.Contains(dec.text, "{}") {
-		return true
-	}
-
-	// word 28BD0000. pop/ldm with no registers (undefined).
-	// we say 'ldmcs sp!, {}', libopcodes says 'popcs {}'.
-	if hasPrefix(text, "ldm") && hasPrefix(dec.text, "pop") && strings.Contains(text, "{}") && strings.Contains(dec.text, "{}") {
-		return true
-	}
-
-	// word 014640F0.
-	// libopcodes emits #-0 for negative zero; we don't.
-	if strings.Replace(dec.text, "#-0", "#0", -1) == text || strings.Replace(dec.text, ", #-0", "", -1) == text {
-		return true
-	}
-
-	// word 91EF90F0. we say 'strdls r9, [pc, #0]!' but libopcodes says 'strdls r9, [pc]'.
-	// word D16F60F0. we say 'strdle r6, [pc, #0]!' but libopcodes says 'strdle r6, [pc, #-0]'.
-	if strings.Replace(text, ", #0]!", "]", -1) == strings.Replace(dec.text, ", #-0]", "]", -1) {
-		return true
-	}
-
-	// word 510F4000. we say apsr, libopcodes says CPSR.
-	if strings.Replace(dec.text, "CPSR", "apsr", -1) == text {
-		return true
-	}
-
-	// word 06A4B059.
-	// for ssat and usat, libopcodes decodes asr #0 as asr #0 but the manual seems to say it should be asr #32.
-	// There is never an asr #0.
-	if strings.Replace(dec.text, ", asr #0", ", asr #32", -1) == text {
-		return true
-	}
-
-	if len(dec.enc) >= 4 {
-		raw := binary.LittleEndian.Uint32(dec.enc[:4])
-
-		// word 21FFF0B5.
-		// the manual is clear that this is pre-indexed mode (with !) but libopcodes generates post-index (without !).
-		if raw&0x01200000 == 0x01200000 && strings.Replace(text, "!", "", -1) == dec.text {
-			return true
-		}
-
-		// word C100543E: libopcodes says tst, but no evidence for that.
-		if strings.HasPrefix(dec.text, "tst") && raw&0x0ff00000 != 0x03100000 && raw&0x0ff00000 != 0x01100000 {
-			return true
-		}
-
-		// word C3203CE8: libopcodes says teq, but no evidence for that.
-		if strings.HasPrefix(dec.text, "teq") && raw&0x0ff00000 != 0x03300000 && raw&0x0ff00000 != 0x01300000 {
-			return true
-		}
-
-		// word D14C552E: libopcodes says cmp but no evidence for that.
-		if strings.HasPrefix(dec.text, "cmp") && raw&0x0ff00000 != 0x03500000 && raw&0x0ff00000 != 0x01500000 {
-			return true
-		}
-
-		// word 2166AA4A: libopcodes says cmn but no evidence for that.
-		if strings.HasPrefix(dec.text, "cmn") && raw&0x0ff00000 != 0x03700000 && raw&0x0ff00000 != 0x01700000 {
-			return true
-		}
-
-		// word E70AEEEF: libopcodes says str but no evidence for that.
-		if strings.HasPrefix(dec.text, "str") && len(dec.text) >= 5 && (dec.text[3] == ' ' || dec.text[5] == ' ') && raw&0x0e500018 != 0x06000000 && raw&0x0e500000 != 0x0400000 {
-			return true
-		}
-
-		// word B0AF48F4: libopcodes says strd but P=0,W=1 which is unpredictable.
-		if hasPrefix(dec.text, "ldr", "str") && raw&0x01200000 == 0x00200000 {
-			return true
-		}
-
-		// word B6CC1C76: libopcodes inexplicably says 'uxtab16lt r1, ip, r6, ROR #24' instead of 'uxtab16lt r1, ip, r6, ror #24'
-		if strings.ToLower(dec.text) == text {
-			return true
-		}
-
-		// word F410FDA1: libopcodes says PLDW but the manual is clear that PLDW is F5/F7, not F4.
-		// word F7D0FB17: libopcodes says PLDW but the manual is clear that PLDW has 0x10 clear
-		if hasPrefix(dec.text, "pld") && raw&0xfd000010 != 0xf5000000 {
-			return true
-		}
-
-		// word F650FE14: libopcodes says PLI but the manual is clear that PLI has 0x10 clear
-		if hasPrefix(dec.text, "pli") && raw&0xff000010 != 0xf6000000 {
-			return true
-		}
-	}
-
-	return false
-}
-
-// Instructions known to libopcodes (or xed) but not to us.
-// Most of these are floating point coprocessor instructions.
-var unsupported = strings.Fields(`
-	abs
-	acs
-	adf
-	aes
-	asn
-	atn
-	cdp
-	cf
-	cmf
-	cnf
-	cos
-	cps
-	crc32
-	dvf
-	eret
-	exp
-	fadd
-	fcmp
-	fcpy
-	fcvt
-	fdiv
-	fdv
-	fix
-	fld
-	flt
-	fmac
-	fmd
-	fml
-	fmr
-	fms
-	fmul
-	fmx
-	fneg
-	fnm
-	frd
-	fsit
-	fsq
-	fst
-	fsu
-	fto
-	fui
-	hlt
-	hvc
-	lda
-	ldc
-	ldf
-	lfm
-	lgn
-	log
-	mar
-	mcr
-	mcrr
-	mia
-	mnf
-	mra
-	mrc
-	mrrc
-	mrs
-	msr
-	msr
-	muf
-	mvf
-	nrm
-	pol
-	pow
-	rdf
-	rfc
-	rfe
-	rfs
-	rmf
-	rnd
-	rpw
-	rsf
-	sdiv
-	sev
-	sfm
-	sha1
-	sha256
-	sin
-	smc
-	sqt
-	srs
-	stc
-	stf
-	stl
-	suf
-	tan
-	udf
-	udiv
-	urd
-	vfma
-	vfms
-	vfnma
-	vfnms
-	vrint
-	wfc
-	wfs
-`)
diff --git a/src/cmd/internal/rsc.io/arm/armasm/objdumpext_test.go b/src/cmd/internal/rsc.io/arm/armasm/objdumpext_test.go
deleted file mode 100644
index d88c67f..0000000
--- a/src/cmd/internal/rsc.io/arm/armasm/objdumpext_test.go
+++ /dev/null
@@ -1,260 +0,0 @@
-// 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.
-
-// Copied and simplified from rsc.io/x86/x86asm/objdumpext_test.go.
-
-package armasm
-
-import (
-	"bytes"
-	"debug/elf"
-	"encoding/binary"
-	"fmt"
-	"io"
-	"log"
-	"os"
-	"strconv"
-	"strings"
-	"testing"
-)
-
-const objdumpPath = "/usr/local/bin/arm-linux-elf-objdump"
-
-func testObjdumpARM(t *testing.T, generate func(func([]byte))) {
-	testObjdumpArch(t, generate, ModeARM)
-}
-
-func testObjdumpArch(t *testing.T, generate func(func([]byte)), arch Mode) {
-	if testing.Short() {
-		t.Skip("skipping objdump test in short mode")
-	}
-
-	if _, err := os.Stat(objdumpPath); err != nil {
-		t.Fatal(err)
-	}
-
-	testExtDis(t, "gnu", arch, objdump, generate, allowedMismatchObjdump)
-}
-
-func objdump(ext *ExtDis) error {
-	// File already written with instructions; add ELF header.
-	if ext.Arch == ModeARM {
-		if err := writeELF32(ext.File, ext.Size); err != nil {
-			return err
-		}
-	} else {
-		panic("unknown arch")
-	}
-
-	b, err := ext.Run(objdumpPath, "-d", "-z", ext.File.Name())
-	if err != nil {
-		return err
-	}
-
-	var (
-		nmatch  int
-		reading bool
-		next    uint32 = start
-		addr    uint32
-		encbuf  [4]byte
-		enc     []byte
-		text    string
-	)
-	flush := func() {
-		if addr == next {
-			if m := pcrel.FindStringSubmatch(text); m != nil {
-				targ, _ := strconv.ParseUint(m[2], 16, 64)
-				text = fmt.Sprintf("%s .%+#x", m[1], int32(uint32(targ)-addr-uint32(len(enc))))
-			}
-			if strings.HasPrefix(text, "stmia") {
-				text = "stm" + text[5:]
-			}
-			if strings.HasPrefix(text, "stmfd") {
-				text = "stmdb" + text[5:]
-			}
-			if strings.HasPrefix(text, "ldmfd") {
-				text = "ldm" + text[5:]
-			}
-			text = strings.Replace(text, "#0.0", "#0", -1)
-			if text == "undefined" && len(enc) == 4 {
-				text = "error: unknown instruction"
-				enc = nil
-			}
-			if len(enc) == 4 {
-				// prints as word but we want to record bytes
-				enc[0], enc[3] = enc[3], enc[0]
-				enc[1], enc[2] = enc[2], enc[1]
-			}
-			ext.Dec <- ExtInst{addr, encbuf, len(enc), text}
-			encbuf = [4]byte{}
-			enc = nil
-			next += 4
-		}
-	}
-	var textangle = []byte("<.text>:")
-	for {
-		line, err := b.ReadSlice('\n')
-		if err != nil {
-			if err == io.EOF {
-				break
-			}
-			return fmt.Errorf("reading objdump output: %v", err)
-		}
-		if bytes.Contains(line, textangle) {
-			reading = true
-			continue
-		}
-		if !reading {
-			continue
-		}
-		if debug {
-			os.Stdout.Write(line)
-		}
-		if enc1 := parseContinuation(line, encbuf[:len(enc)]); enc1 != nil {
-			enc = enc1
-			continue
-		}
-		flush()
-		nmatch++
-		addr, enc, text = parseLine(line, encbuf[:0])
-		if addr > next {
-			return fmt.Errorf("address out of sync expected <= %#x at %q in:\n%s", next, line, line)
-		}
-	}
-	flush()
-	if next != start+uint32(ext.Size) {
-		return fmt.Errorf("not enough results found [%d %d]", next, start+ext.Size)
-	}
-	if err := ext.Wait(); err != nil {
-		return fmt.Errorf("exec: %v", err)
-	}
-
-	return nil
-}
-
-var (
-	undefined      = []byte("<UNDEFINED>")
-	unpredictable  = []byte("<UNPREDICTABLE>")
-	illegalShifter = []byte("<illegal shifter operand>")
-)
-
-func parseLine(line []byte, encstart []byte) (addr uint32, enc []byte, text string) {
-	oline := line
-	i := index(line, ":\t")
-	if i < 0 {
-		log.Fatalf("cannot parse disassembly: %q", oline)
-	}
-	x, err := strconv.ParseUint(string(trimSpace(line[:i])), 16, 32)
-	if err != nil {
-		log.Fatalf("cannot parse disassembly: %q", oline)
-	}
-	addr = uint32(x)
-	line = line[i+2:]
-	i = bytes.IndexByte(line, '\t')
-	if i < 0 {
-		log.Fatalf("cannot parse disassembly: %q", oline)
-	}
-	enc, ok := parseHex(line[:i], encstart)
-	if !ok {
-		log.Fatalf("cannot parse disassembly: %q", oline)
-	}
-	line = trimSpace(line[i:])
-	if bytes.Contains(line, undefined) {
-		text = "undefined"
-		return
-	}
-	if bytes.Contains(line, illegalShifter) {
-		text = "undefined"
-		return
-	}
-	if false && bytes.Contains(line, unpredictable) {
-		text = "unpredictable"
-		return
-	}
-	if i := bytes.IndexByte(line, ';'); i >= 0 {
-		line = trimSpace(line[:i])
-	}
-	text = string(fixSpace(line))
-	return
-}
-
-func parseContinuation(line []byte, enc []byte) []byte {
-	i := index(line, ":\t")
-	if i < 0 {
-		return nil
-	}
-	line = line[i+1:]
-	enc, _ = parseHex(line, enc)
-	return enc
-}
-
-// writeELF32 writes an ELF32 header to the file,
-// describing a text segment that starts at start
-// and extends for size bytes.
-func writeELF32(f *os.File, size int) error {
-	f.Seek(0, 0)
-	var hdr elf.Header32
-	var prog elf.Prog32
-	var sect elf.Section32
-	var buf bytes.Buffer
-	binary.Write(&buf, binary.LittleEndian, &hdr)
-	off1 := buf.Len()
-	binary.Write(&buf, binary.LittleEndian, &prog)
-	off2 := buf.Len()
-	binary.Write(&buf, binary.LittleEndian, &sect)
-	off3 := buf.Len()
-	buf.Reset()
-	data := byte(elf.ELFDATA2LSB)
-	hdr = elf.Header32{
-		Ident:     [16]byte{0x7F, 'E', 'L', 'F', 1, data, 1},
-		Type:      2,
-		Machine:   uint16(elf.EM_ARM),
-		Version:   1,
-		Entry:     start,
-		Phoff:     uint32(off1),
-		Shoff:     uint32(off2),
-		Flags:     0x05000002,
-		Ehsize:    uint16(off1),
-		Phentsize: uint16(off2 - off1),
-		Phnum:     1,
-		Shentsize: uint16(off3 - off2),
-		Shnum:     3,
-		Shstrndx:  2,
-	}
-	binary.Write(&buf, binary.LittleEndian, &hdr)
-	prog = elf.Prog32{
-		Type:   1,
-		Off:    start,
-		Vaddr:  start,
-		Paddr:  start,
-		Filesz: uint32(size),
-		Memsz:  uint32(size),
-		Flags:  5,
-		Align:  start,
-	}
-	binary.Write(&buf, binary.LittleEndian, &prog)
-	binary.Write(&buf, binary.LittleEndian, &sect) // NULL section
-	sect = elf.Section32{
-		Name:      1,
-		Type:      uint32(elf.SHT_PROGBITS),
-		Addr:      start,
-		Off:       start,
-		Size:      uint32(size),
-		Flags:     uint32(elf.SHF_ALLOC | elf.SHF_EXECINSTR),
-		Addralign: 4,
-	}
-	binary.Write(&buf, binary.LittleEndian, &sect) // .text
-	sect = elf.Section32{
-		Name:      uint32(len("\x00.text\x00")),
-		Type:      uint32(elf.SHT_STRTAB),
-		Addr:      0,
-		Off:       uint32(off2 + (off3-off2)*3),
-		Size:      uint32(len("\x00.text\x00.shstrtab\x00")),
-		Addralign: 1,
-	}
-	binary.Write(&buf, binary.LittleEndian, &sect)
-	buf.WriteString("\x00.text\x00.shstrtab\x00")
-	f.Write(buf.Bytes())
-	return nil
-}
diff --git a/src/cmd/internal/rsc.io/arm/armasm/plan9x.go b/src/cmd/internal/rsc.io/arm/armasm/plan9x.go
deleted file mode 100644
index 952c519..0000000
--- a/src/cmd/internal/rsc.io/arm/armasm/plan9x.go
+++ /dev/null
@@ -1,211 +0,0 @@
-// 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 armasm
-
-import (
-	"bytes"
-	"encoding/binary"
-	"fmt"
-	"io"
-	"strings"
-)
-
-// Plan9Syntax returns the Go assembler syntax for the instruction.
-// The syntax was originally defined by Plan 9.
-// The pc is the program counter of the instruction, used for expanding
-// PC-relative addresses into absolute ones.
-// The symname function queries the symbol table for the program
-// being disassembled. Given a target address it returns the name and base
-// address of the symbol containing the target, if any; otherwise it returns "", 0.
-// The reader r should read from the text segment using text addresses
-// as offsets; it is used to display pc-relative loads as constant loads.
-func Plan9Syntax(inst Inst, pc uint64, symname func(uint64) (string, uint64), text io.ReaderAt) string {
-	if symname == nil {
-		symname = func(uint64) (string, uint64) { return "", 0 }
-	}
-
-	var args []string
-	for _, a := range inst.Args {
-		if a == nil {
-			break
-		}
-		args = append(args, plan9Arg(&inst, pc, symname, a))
-	}
-
-	op := inst.Op.String()
-
-	switch inst.Op &^ 15 {
-	case LDR_EQ, LDRB_EQ, LDRH_EQ:
-		// Check for RET
-		reg, _ := inst.Args[0].(Reg)
-		mem, _ := inst.Args[1].(Mem)
-		if inst.Op&^15 == LDR_EQ && reg == R15 && mem.Base == SP && mem.Sign == 0 && mem.Mode == AddrPostIndex {
-			return fmt.Sprintf("RET%s #%d", op[3:], mem.Offset)
-		}
-
-		// Check for PC-relative load.
-		if mem.Base == PC && mem.Sign == 0 && mem.Mode == AddrOffset && text != nil {
-			addr := uint32(pc) + 8 + uint32(mem.Offset)
-			buf := make([]byte, 4)
-			switch inst.Op &^ 15 {
-			case LDRB_EQ:
-				if _, err := text.ReadAt(buf[:1], int64(addr)); err != nil {
-					break
-				}
-				args[1] = fmt.Sprintf("$%#x", buf[0])
-
-			case LDRH_EQ:
-				if _, err := text.ReadAt(buf[:2], int64(addr)); err != nil {
-					break
-				}
-				args[1] = fmt.Sprintf("$%#x", binary.LittleEndian.Uint16(buf))
-
-			case LDR_EQ:
-				if _, err := text.ReadAt(buf, int64(addr)); err != nil {
-					break
-				}
-				x := binary.LittleEndian.Uint32(buf)
-				if s, base := symname(uint64(x)); s != "" && uint64(x) == base {
-					args[1] = fmt.Sprintf("$%s(SB)", s)
-				} else {
-					args[1] = fmt.Sprintf("$%#x", x)
-				}
-			}
-		}
-	}
-
-	// Move addressing mode into opcode suffix.
-	suffix := ""
-	switch inst.Op &^ 15 {
-	case LDR_EQ, LDRB_EQ, LDRH_EQ, STR_EQ, STRB_EQ, STRH_EQ:
-		mem, _ := inst.Args[1].(Mem)
-		switch mem.Mode {
-		case AddrOffset, AddrLDM:
-			// no suffix
-		case AddrPreIndex, AddrLDM_WB:
-			suffix = ".W"
-		case AddrPostIndex:
-			suffix = ".P"
-		}
-		off := ""
-		if mem.Offset != 0 {
-			off = fmt.Sprintf("%#x", mem.Offset)
-		}
-		base := fmt.Sprintf("(R%d)", int(mem.Base))
-		index := ""
-		if mem.Sign != 0 {
-			sign := ""
-			if mem.Sign < 0 {
-				sign = ""
-			}
-			shift := ""
-			if mem.Count != 0 {
-				shift = fmt.Sprintf("%s%d", plan9Shift[mem.Shift], mem.Count)
-			}
-			index = fmt.Sprintf("(%sR%d%s)", sign, int(mem.Index), shift)
-		}
-		args[1] = off + base + index
-	}
-
-	// Reverse args, placing dest last.
-	for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
-		args[i], args[j] = args[j], args[i]
-	}
-
-	switch inst.Op &^ 15 {
-	case MOV_EQ:
-		op = "MOVW" + op[3:]
-
-	case LDR_EQ:
-		op = "MOVW" + op[3:] + suffix
-	case LDRB_EQ:
-		op = "MOVB" + op[4:] + suffix
-	case LDRH_EQ:
-		op = "MOVH" + op[4:] + suffix
-
-	case STR_EQ:
-		op = "MOVW" + op[3:] + suffix
-		args[0], args[1] = args[1], args[0]
-	case STRB_EQ:
-		op = "MOVB" + op[4:] + suffix
-		args[0], args[1] = args[1], args[0]
-	case STRH_EQ:
-		op = "MOVH" + op[4:] + suffix
-		args[0], args[1] = args[1], args[0]
-	}
-
-	if args != nil {
-		op += " " + strings.Join(args, ", ")
-	}
-
-	return op
-}
-
-// assembler syntax for the various shifts.
-// @x> is a lie; the assembler uses @> 0
-// instead of @x> 1, but i wanted to be clear that it
-// was a different operation (rotate right extended, not rotate right).
-var plan9Shift = []string{"<<", ">>", "->", "@>", "@x>"}
-
-func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string {
-	switch a := arg.(type) {
-	case Endian:
-
-	case Imm:
-		return fmt.Sprintf("$%d", int(a))
-
-	case Mem:
-
-	case PCRel:
-		addr := uint32(pc) + 8 + uint32(a)
-		if s, base := symname(uint64(addr)); s != "" && uint64(addr) == base {
-			return fmt.Sprintf("%s(SB)", s)
-		}
-		return fmt.Sprintf("%#x", addr)
-
-	case Reg:
-		if a < 16 {
-			return fmt.Sprintf("R%d", int(a))
-		}
-
-	case RegList:
-		var buf bytes.Buffer
-		start := -2
-		end := -2
-		fmt.Fprintf(&buf, "[")
-		flush := func() {
-			if start >= 0 {
-				if buf.Len() > 1 {
-					fmt.Fprintf(&buf, ",")
-				}
-				if start == end {
-					fmt.Fprintf(&buf, "R%d", start)
-				} else {
-					fmt.Fprintf(&buf, "R%d-R%d", start, end)
-				}
-			}
-		}
-		for i := 0; i < 16; i++ {
-			if a&(1<<uint(i)) != 0 {
-				if i == end+1 {
-					end++
-					continue
-				}
-				start = i
-				end = i
-			}
-		}
-		flush()
-		fmt.Fprintf(&buf, "]")
-		return buf.String()
-
-	case RegShift:
-		return fmt.Sprintf("R%d%s$%d", int(a.Reg), plan9Shift[a.Shift], int(a.Count))
-
-	case RegShiftReg:
-		return fmt.Sprintf("R%d%sR%d", int(a.Reg), plan9Shift[a.Shift], int(a.RegCount))
-	}
-	return strings.ToUpper(arg.String())
-}
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/decode.go b/src/cmd/internal/rsc.io/x86/x86asm/decode.go
deleted file mode 100644
index 91e8876..0000000
--- a/src/cmd/internal/rsc.io/x86/x86asm/decode.go
+++ /dev/null
@@ -1,1616 +0,0 @@
-// 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.
-
-// Table-driven decoding of x86 instructions.
-
-package x86asm
-
-import (
-	"encoding/binary"
-	"errors"
-	"fmt"
-	"runtime"
-)
-
-// Set trace to true to cause the decoder to print the PC sequence
-// of the executed instruction codes. This is typically only useful
-// when you are running a test of a single input case.
-const trace = false
-
-// A decodeOp is a single instruction in the decoder bytecode program.
-//
-// The decodeOps correspond to consuming and conditionally branching
-// on input bytes, consuming additional fields, and then interpreting
-// consumed data as instruction arguments. The names of the xRead and xArg
-// operations are taken from the Intel manual conventions, for example
-// Volume 2, Section 3.1.1, page 487 of
-// http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf
-//
-// The actual decoding program is generated by ../x86map.
-//
-// TODO(rsc): We may be able to merge various of the memory operands
-// since we don't care about, say, the distinction between m80dec and m80bcd.
-// Similarly, mm and mm1 have identical meaning, as do xmm and xmm1.
-
-type decodeOp uint16
-
-const (
-	xFail  decodeOp = iota // invalid instruction (return)
-	xMatch                 // completed match
-	xJump                  // jump to pc
-
-	xCondByte     // switch on instruction byte value
-	xCondSlashR   // read and switch on instruction /r value
-	xCondPrefix   // switch on presence of instruction prefix
-	xCondIs64     // switch on 64-bit processor mode
-	xCondDataSize // switch on operand size
-	xCondAddrSize // switch on address size
-	xCondIsMem    // switch on memory vs register argument
-
-	xSetOp // set instruction opcode
-
-	xReadSlashR // read /r
-	xReadIb     // read ib
-	xReadIw     // read iw
-	xReadId     // read id
-	xReadIo     // read io
-	xReadCb     // read cb
-	xReadCw     // read cw
-	xReadCd     // read cd
-	xReadCp     // read cp
-	xReadCm     // read cm
-
-	xArg1            // arg 1
-	xArg3            // arg 3
-	xArgAL           // arg AL
-	xArgAX           // arg AX
-	xArgCL           // arg CL
-	xArgCR0dashCR7   // arg CR0-CR7
-	xArgCS           // arg CS
-	xArgDR0dashDR7   // arg DR0-DR7
-	xArgDS           // arg DS
-	xArgDX           // arg DX
-	xArgEAX          // arg EAX
-	xArgEDX          // arg EDX
-	xArgES           // arg ES
-	xArgFS           // arg FS
-	xArgGS           // arg GS
-	xArgImm16        // arg imm16
-	xArgImm32        // arg imm32
-	xArgImm64        // arg imm64
-	xArgImm8         // arg imm8
-	xArgImm8u        // arg imm8 but record as unsigned
-	xArgImm16u       // arg imm8 but record as unsigned
-	xArgM            // arg m
-	xArgM128         // arg m128
-	xArgM1428byte    // arg m14/28byte
-	xArgM16          // arg m16
-	xArgM16and16     // arg m16&16
-	xArgM16and32     // arg m16&32
-	xArgM16and64     // arg m16&64
-	xArgM16colon16   // arg m16:16
-	xArgM16colon32   // arg m16:32
-	xArgM16colon64   // arg m16:64
-	xArgM16int       // arg m16int
-	xArgM2byte       // arg m2byte
-	xArgM32          // arg m32
-	xArgM32and32     // arg m32&32
-	xArgM32fp        // arg m32fp
-	xArgM32int       // arg m32int
-	xArgM512byte     // arg m512byte
-	xArgM64          // arg m64
-	xArgM64fp        // arg m64fp
-	xArgM64int       // arg m64int
-	xArgM8           // arg m8
-	xArgM80bcd       // arg m80bcd
-	xArgM80dec       // arg m80dec
-	xArgM80fp        // arg m80fp
-	xArgM94108byte   // arg m94/108byte
-	xArgMm           // arg mm
-	xArgMm1          // arg mm1
-	xArgMm2          // arg mm2
-	xArgMm2M64       // arg mm2/m64
-	xArgMmM32        // arg mm/m32
-	xArgMmM64        // arg mm/m64
-	xArgMem          // arg mem
-	xArgMoffs16      // arg moffs16
-	xArgMoffs32      // arg moffs32
-	xArgMoffs64      // arg moffs64
-	xArgMoffs8       // arg moffs8
-	xArgPtr16colon16 // arg ptr16:16
-	xArgPtr16colon32 // arg ptr16:32
-	xArgR16          // arg r16
-	xArgR16op        // arg r16 with +rw in opcode
-	xArgR32          // arg r32
-	xArgR32M16       // arg r32/m16
-	xArgR32M8        // arg r32/m8
-	xArgR32op        // arg r32 with +rd in opcode
-	xArgR64          // arg r64
-	xArgR64M16       // arg r64/m16
-	xArgR64op        // arg r64 with +rd in opcode
-	xArgR8           // arg r8
-	xArgR8op         // arg r8 with +rb in opcode
-	xArgRAX          // arg RAX
-	xArgRDX          // arg RDX
-	xArgRM           // arg r/m
-	xArgRM16         // arg r/m16
-	xArgRM32         // arg r/m32
-	xArgRM64         // arg r/m64
-	xArgRM8          // arg r/m8
-	xArgReg          // arg reg
-	xArgRegM16       // arg reg/m16
-	xArgRegM32       // arg reg/m32
-	xArgRegM8        // arg reg/m8
-	xArgRel16        // arg rel16
-	xArgRel32        // arg rel32
-	xArgRel8         // arg rel8
-	xArgSS           // arg SS
-	xArgST           // arg ST, aka ST(0)
-	xArgSTi          // arg ST(i) with +i in opcode
-	xArgSreg         // arg Sreg
-	xArgTR0dashTR7   // arg TR0-TR7
-	xArgXmm          // arg xmm
-	xArgXMM0         // arg <XMM0>
-	xArgXmm1         // arg xmm1
-	xArgXmm2         // arg xmm2
-	xArgXmm2M128     // arg xmm2/m128
-	xArgXmm2M16      // arg xmm2/m16
-	xArgXmm2M32      // arg xmm2/m32
-	xArgXmm2M64      // arg xmm2/m64
-	xArgXmmM128      // arg xmm/m128
-	xArgXmmM32       // arg xmm/m32
-	xArgXmmM64       // arg xmm/m64
-	xArgRmf16        // arg r/m16 but force mod=3
-	xArgRmf32        // arg r/m32 but force mod=3
-	xArgRmf64        // arg r/m64 but force mod=3
-)
-
-// instPrefix returns an Inst describing just one prefix byte.
-// It is only used if there is a prefix followed by an unintelligible
-// or invalid instruction byte sequence.
-func instPrefix(b byte, mode int) (Inst, error) {
-	// When tracing it is useful to see what called instPrefix to report an error.
-	if trace {
-		_, file, line, _ := runtime.Caller(1)
-		fmt.Printf("%s:%d\n", file, line)
-	}
-	p := Prefix(b)
-	switch p {
-	case PrefixDataSize:
-		if mode == 16 {
-			p = PrefixData32
-		} else {
-			p = PrefixData16
-		}
-	case PrefixAddrSize:
-		if mode == 32 {
-			p = PrefixAddr16
-		} else {
-			p = PrefixAddr32
-		}
-	}
-	// Note: using composite literal with Prefix key confuses 'bundle' tool.
-	inst := Inst{Len: 1}
-	inst.Prefix = Prefixes{p}
-	return inst, nil
-}
-
-// truncated reports a truncated instruction.
-// For now we use instPrefix but perhaps later we will return
-// a specific error here.
-func truncated(src []byte, mode int) (Inst, error) {
-	//	return Inst{}, len(src), ErrTruncated
-	return instPrefix(src[0], mode) // too long
-}
-
-// These are the errors returned by Decode.
-var (
-	ErrInvalidMode  = errors.New("invalid x86 mode in Decode")
-	ErrTruncated    = errors.New("truncated instruction")
-	ErrUnrecognized = errors.New("unrecognized instruction")
-)
-
-// decoderCover records coverage information for which parts
-// of the byte code have been executed.
-// TODO(rsc): This is for testing. Only use this if a flag is given.
-var decoderCover []bool
-
-// Decode decodes the leading bytes in src as a single instruction.
-// The mode arguments specifies the assumed processor mode:
-// 16, 32, or 64 for 16-, 32-, and 64-bit execution modes.
-func Decode(src []byte, mode int) (inst Inst, err error) {
-	return decode1(src, mode, false)
-}
-
-// decode1 is the implementation of Decode but takes an extra
-// gnuCompat flag to cause it to change its behavior to mimic
-// bugs (or at least unique features) of GNU libopcodes as used
-// by objdump. We don't believe that logic is the right thing to do
-// in general, but when testing against libopcodes it simplifies the
-// comparison if we adjust a few small pieces of logic.
-// The affected logic is in the conditional branch for "mandatory" prefixes,
-// case xCondPrefix.
-func decode1(src []byte, mode int, gnuCompat bool) (Inst, error) {
-	switch mode {
-	case 16, 32, 64:
-		// ok
-		// TODO(rsc): 64-bit mode not tested, probably not working.
-	default:
-		return Inst{}, ErrInvalidMode
-	}
-
-	// Maximum instruction size is 15 bytes.
-	// If we need to read more, return 'truncated instruction.
-	if len(src) > 15 {
-		src = src[:15]
-	}
-
-	var (
-		// prefix decoding information
-		pos           = 0    // position reading src
-		nprefix       = 0    // number of prefixes
-		lockIndex     = -1   // index of LOCK prefix in src and inst.Prefix
-		repIndex      = -1   // index of REP/REPN prefix in src and inst.Prefix
-		segIndex      = -1   // index of Group 2 prefix in src and inst.Prefix
-		dataSizeIndex = -1   // index of Group 3 prefix in src and inst.Prefix
-		addrSizeIndex = -1   // index of Group 4 prefix in src and inst.Prefix
-		rex           Prefix // rex byte if present (or 0)
-		rexUsed       Prefix // bits used in rex byte
-		rexIndex      = -1   // index of rex byte
-
-		addrMode = mode // address mode (width in bits)
-		dataMode = mode // operand mode (width in bits)
-
-		// decoded ModR/M fields
-		haveModrm bool
-		modrm     int
-		mod       int
-		regop     int
-		rm        int
-
-		// if ModR/M is memory reference, Mem form
-		mem     Mem
-		haveMem bool
-
-		// decoded SIB fields
-		haveSIB bool
-		sib     int
-		scale   int
-		index   int
-		base    int
-
-		// decoded immediate values
-		imm  int64
-		imm8 int8
-		immc int64
-
-		// output
-		opshift int
-		inst    Inst
-		narg    int // number of arguments written to inst
-	)
-
-	if mode == 64 {
-		dataMode = 32
-	}
-
-	// Prefixes are certainly the most complex and underspecified part of
-	// decoding x86 instructions. Although the manuals say things like
-	// up to four prefixes, one from each group, nearly everyone seems to
-	// agree that in practice as many prefixes as possible, including multiple
-	// from a particular group or repetitions of a given prefix, can be used on
-	// an instruction, provided the total instruction length including prefixes
-	// does not exceed the agreed-upon maximum of 15 bytes.
-	// Everyone also agrees that if one of these prefixes is the LOCK prefix
-	// and the instruction is not one of the instructions that can be used with
-	// the LOCK prefix or if the destination is not a memory operand,
-	// then the instruction is invalid and produces the #UD exception.
-	// However, that is the end of any semblance of agreement.
-	//
-	// What happens if prefixes are given that conflict with other prefixes?
-	// For example, the memory segment overrides CS, DS, ES, FS, GS, SS
-	// conflict with each other: only one segment can be in effect.
-	// Disassemblers seem to agree that later prefixes take priority over
-	// earlier ones. I have not taken the time to write assembly programs
-	// to check to see if the hardware agrees.
-	//
-	// What happens if prefixes are given that have no meaning for the
-	// specific instruction to which they are attached? It depends.
-	// If they really have no meaning, they are ignored. However, a future
-	// processor may assign a different meaning. As a disassembler, we
-	// don't really know whether we're seeing a meaningless prefix or one
-	// whose meaning we simply haven't been told yet.
-	//
-	// Combining the two questions, what happens when conflicting
-	// extension prefixes are given? No one seems to know for sure.
-	// For example, MOVQ is 66 0F D6 /r, MOVDQ2Q is F2 0F D6 /r,
-	// and MOVQ2DQ is F3 0F D6 /r. What is '66 F2 F3 0F D6 /r'?
-	// Which prefix wins? See the xCondPrefix prefix for more.
-	//
-	// Writing assembly test cases to divine which interpretation the
-	// CPU uses might clarify the situation, but more likely it would
-	// make the situation even less clear.
-
-	// Read non-REX prefixes.
-ReadPrefixes:
-	for ; pos < len(src); pos++ {
-		p := Prefix(src[pos])
-		switch p {
-		default:
-			nprefix = pos
-			break ReadPrefixes
-
-		// Group 1 - lock and repeat prefixes
-		// According to Intel, there should only be one from this set,
-		// but according to AMD both can be present.
-		case 0xF0:
-			if lockIndex >= 0 {
-				inst.Prefix[lockIndex] |= PrefixIgnored
-			}
-			lockIndex = pos
-		case 0xF2, 0xF3:
-			if repIndex >= 0 {
-				inst.Prefix[repIndex] |= PrefixIgnored
-			}
-			repIndex = pos
-
-		// Group 2 - segment override / branch hints
-		case 0x26, 0x2E, 0x36, 0x3E:
-			if mode == 64 {
-				p |= PrefixIgnored
-				break
-			}
-			fallthrough
-		case 0x64, 0x65:
-			if segIndex >= 0 {
-				inst.Prefix[segIndex] |= PrefixIgnored
-			}
-			segIndex = pos
-
-		// Group 3 - operand size override
-		case 0x66:
-			if mode == 16 {
-				dataMode = 32
-				p = PrefixData32
-			} else {
-				dataMode = 16
-				p = PrefixData16
-			}
-			if dataSizeIndex >= 0 {
-				inst.Prefix[dataSizeIndex] |= PrefixIgnored
-			}
-			dataSizeIndex = pos
-
-		// Group 4 - address size override
-		case 0x67:
-			if mode == 32 {
-				addrMode = 16
-				p = PrefixAddr16
-			} else {
-				addrMode = 32
-				p = PrefixAddr32
-			}
-			if addrSizeIndex >= 0 {
-				inst.Prefix[addrSizeIndex] |= PrefixIgnored
-			}
-			addrSizeIndex = pos
-		}
-
-		if pos >= len(inst.Prefix) {
-			return instPrefix(src[0], mode) // too long
-		}
-
-		inst.Prefix[pos] = p
-	}
-
-	// Read REX prefix.
-	if pos < len(src) && mode == 64 && Prefix(src[pos]).IsREX() {
-		rex = Prefix(src[pos])
-		rexIndex = pos
-		if pos >= len(inst.Prefix) {
-			return instPrefix(src[0], mode) // too long
-		}
-		inst.Prefix[pos] = rex
-		pos++
-		if rex&PrefixREXW != 0 {
-			dataMode = 64
-			if dataSizeIndex >= 0 {
-				inst.Prefix[dataSizeIndex] |= PrefixIgnored
-			}
-		}
-	}
-
-	// Decode instruction stream, interpreting decoding instructions.
-	// opshift gives the shift to use when saving the next
-	// opcode byte into inst.Opcode.
-	opshift = 24
-	if decoderCover == nil {
-		decoderCover = make([]bool, len(decoder))
-	}
-
-	// Decode loop, executing decoder program.
-	var oldPC, prevPC int
-Decode:
-	for pc := 1; ; { // TODO uint
-		oldPC = prevPC
-		prevPC = pc
-		if trace {
-			println("run", pc)
-		}
-		x := decoder[pc]
-		decoderCover[pc] = true
-		pc++
-
-		// Read and decode ModR/M if needed by opcode.
-		switch decodeOp(x) {
-		case xCondSlashR, xReadSlashR:
-			if haveModrm {
-				return Inst{Len: pos}, errInternal
-			}
-			haveModrm = true
-			if pos >= len(src) {
-				return truncated(src, mode)
-			}
-			modrm = int(src[pos])
-			pos++
-			if opshift >= 0 {
-				inst.Opcode |= uint32(modrm) << uint(opshift)
-				opshift -= 8
-			}
-			mod = modrm >> 6
-			regop = (modrm >> 3) & 07
-			rm = modrm & 07
-			if rex&PrefixREXR != 0 {
-				rexUsed |= PrefixREXR
-				regop |= 8
-			}
-			if addrMode == 16 {
-				// 16-bit modrm form
-				if mod != 3 {
-					haveMem = true
-					mem = addr16[rm]
-					if rm == 6 && mod == 0 {
-						mem.Base = 0
-					}
-
-					// Consume disp16 if present.
-					if mod == 0 && rm == 6 || mod == 2 {
-						if pos+2 > len(src) {
-							return truncated(src, mode)
-						}
-						mem.Disp = int64(binary.LittleEndian.Uint16(src[pos:]))
-						pos += 2
-					}
-
-					// Consume disp8 if present.
-					if mod == 1 {
-						if pos >= len(src) {
-							return truncated(src, mode)
-						}
-						mem.Disp = int64(int8(src[pos]))
-						pos++
-					}
-				}
-			} else {
-				haveMem = mod != 3
-
-				// 32-bit or 64-bit form
-				// Consume SIB encoding if present.
-				if rm == 4 && mod != 3 {
-					haveSIB = true
-					if pos >= len(src) {
-						return truncated(src, mode)
-					}
-					sib = int(src[pos])
-					pos++
-					if opshift >= 0 {
-						inst.Opcode |= uint32(sib) << uint(opshift)
-						opshift -= 8
-					}
-					scale = sib >> 6
-					index = (sib >> 3) & 07
-					base = sib & 07
-					if rex&PrefixREXB != 0 {
-						rexUsed |= PrefixREXB
-						base |= 8
-					}
-					if rex&PrefixREXX != 0 {
-						rexUsed |= PrefixREXX
-						index |= 8
-					}
-
-					mem.Scale = 1 << uint(scale)
-					if index == 4 {
-						// no mem.Index
-					} else {
-						mem.Index = baseRegForBits(addrMode) + Reg(index)
-					}
-					if base&7 == 5 && mod == 0 {
-						// no mem.Base
-					} else {
-						mem.Base = baseRegForBits(addrMode) + Reg(base)
-					}
-				} else {
-					if rex&PrefixREXB != 0 {
-						rexUsed |= PrefixREXB
-						rm |= 8
-					}
-					if mod == 0 && rm&7 == 5 || rm&7 == 4 {
-						// base omitted
-					} else if mod != 3 {
-						mem.Base = baseRegForBits(addrMode) + Reg(rm)
-					}
-				}
-
-				// Consume disp32 if present.
-				if mod == 0 && (rm&7 == 5 || haveSIB && base&7 == 5) || mod == 2 {
-					if pos+4 > len(src) {
-						return truncated(src, mode)
-					}
-					mem.Disp = int64(binary.LittleEndian.Uint32(src[pos:]))
-					pos += 4
-				}
-
-				// Consume disp8 if present.
-				if mod == 1 {
-					if pos >= len(src) {
-						return truncated(src, mode)
-					}
-					mem.Disp = int64(int8(src[pos]))
-					pos++
-				}
-
-				// In 64-bit, mod=0 rm=5 is PC-relative instead of just disp.
-				// See Vol 2A. Table 2-7.
-				if mode == 64 && mod == 0 && rm&7 == 5 {
-					if addrMode == 32 {
-						mem.Base = EIP
-					} else {
-						mem.Base = RIP
-					}
-				}
-			}
-
-			if segIndex >= 0 {
-				mem.Segment = prefixToSegment(inst.Prefix[segIndex])
-			}
-		}
-
-		// Execute single opcode.
-		switch decodeOp(x) {
-		default:
-			println("bad op", x, "at", pc-1, "from", oldPC)
-			return Inst{Len: pos}, errInternal
-
-		case xFail:
-			inst.Op = 0
-			break Decode
-
-		case xMatch:
-			break Decode
-
-		case xJump:
-			pc = int(decoder[pc])
-
-		// Conditional branches.
-
-		case xCondByte:
-			if pos >= len(src) {
-				return truncated(src, mode)
-			}
-			b := src[pos]
-			n := int(decoder[pc])
-			pc++
-			for i := 0; i < n; i++ {
-				xb, xpc := decoder[pc], int(decoder[pc+1])
-				pc += 2
-				if b == byte(xb) {
-					pc = xpc
-					pos++
-					if opshift >= 0 {
-						inst.Opcode |= uint32(b) << uint(opshift)
-						opshift -= 8
-					}
-					continue Decode
-				}
-			}
-			// xCondByte is the only conditional with a fall through,
-			// so that it can be used to pick off special cases before
-			// an xCondSlash. If the fallthrough instruction is xFail,
-			// advance the position so that the decoded instruction
-			// size includes the byte we just compared against.
-			if decodeOp(decoder[pc]) == xJump {
-				pc = int(decoder[pc+1])
-			}
-			if decodeOp(decoder[pc]) == xFail {
-				pos++
-			}
-
-		case xCondIs64:
-			if mode == 64 {
-				pc = int(decoder[pc+1])
-			} else {
-				pc = int(decoder[pc])
-			}
-
-		case xCondIsMem:
-			mem := haveMem
-			if !haveModrm {
-				if pos >= len(src) {
-					return instPrefix(src[0], mode) // too long
-				}
-				mem = src[pos]>>6 != 3
-			}
-			if mem {
-				pc = int(decoder[pc+1])
-			} else {
-				pc = int(decoder[pc])
-			}
-
-		case xCondDataSize:
-			switch dataMode {
-			case 16:
-				if dataSizeIndex >= 0 {
-					inst.Prefix[dataSizeIndex] |= PrefixImplicit
-				}
-				pc = int(decoder[pc])
-			case 32:
-				if dataSizeIndex >= 0 {
-					inst.Prefix[dataSizeIndex] |= PrefixImplicit
-				}
-				pc = int(decoder[pc+1])
-			case 64:
-				rexUsed |= PrefixREXW
-				pc = int(decoder[pc+2])
-			}
-
-		case xCondAddrSize:
-			switch addrMode {
-			case 16:
-				if addrSizeIndex >= 0 {
-					inst.Prefix[addrSizeIndex] |= PrefixImplicit
-				}
-				pc = int(decoder[pc])
-			case 32:
-				if addrSizeIndex >= 0 {
-					inst.Prefix[addrSizeIndex] |= PrefixImplicit
-				}
-				pc = int(decoder[pc+1])
-			case 64:
-				pc = int(decoder[pc+2])
-			}
-
-		case xCondPrefix:
-			// Conditional branch based on presence or absence of prefixes.
-			// The conflict cases here are completely undocumented and
-			// differ significantly between GNU libopcodes and Intel xed.
-			// I have not written assembly code to divine what various CPUs
-			// do, but it wouldn't surprise me if they are not consistent either.
-			//
-			// The basic idea is to switch on the presence of a prefix, so that
-			// for example:
-			//
-			//	xCondPrefix, 4
-			//	0xF3, 123,
-			//	0xF2, 234,
-			//	0x66, 345,
-			//	0, 456
-			//
-			// branch to 123 if the F3 prefix is present, 234 if the F2 prefix
-			// is present, 66 if the 345 prefix is present, and 456 otherwise.
-			// The prefixes are given in descending order so that the 0 will be last.
-			//
-			// It is unclear what should happen if multiple conditions are
-			// satisfied: what if F2 and F3 are both present, or if 66 and F2
-			// are present, or if all three are present? The one chosen becomes
-			// part of the opcode and the others do not. Perhaps the answer
-			// depends on the specific opcodes in question.
-			//
-			// The only clear example is that CRC32 is F2 0F 38 F1 /r, and
-			// it comes in 16-bit and 32-bit forms based on the 66 prefix,
-			// so 66 F2 0F 38 F1 /r should be treated as F2 taking priority,
-			// with the 66 being only an operand size override, and probably
-			// F2 66 0F 38 F1 /r should be treated the same.
-			// Perhaps that rule is specific to the case of CRC32, since no
-			// 66 0F 38 F1 instruction is defined (today) (that we know of).
-			// However, both libopcodes and xed seem to generalize this
-			// example and choose F2/F3 in preference to 66, and we
-			// do the same.
-			//
-			// Next, what if both F2 and F3 are present? Which wins?
-			// The Intel xed rule, and ours, is that the one that occurs last wins.
-			// The GNU libopcodes rule, which we implement only in gnuCompat mode,
-			// is that F3 beats F2 unless F3 has no special meaning, in which
-			// case F3 can be a modified on an F2 special meaning.
-			//
-			// Concretely,
-			//	66 0F D6 /r is MOVQ
-			//	F2 0F D6 /r is MOVDQ2Q
-			//	F3 0F D6 /r is MOVQ2DQ.
-			//
-			//	F2 66 0F D6 /r is 66 + MOVDQ2Q always.
-			//	66 F2 0F D6 /r is 66 + MOVDQ2Q always.
-			//	F3 66 0F D6 /r is 66 + MOVQ2DQ always.
-			//	66 F3 0F D6 /r is 66 + MOVQ2DQ always.
-			//	F2 F3 0F D6 /r is F2 + MOVQ2DQ always.
-			//	F3 F2 0F D6 /r is F3 + MOVQ2DQ in Intel xed, but F2 + MOVQ2DQ in GNU libopcodes.
-			//	Adding 66 anywhere in the prefix section of the
-			//	last two cases does not change the outcome.
-			//
-			// Finally, what if there is a variant in which 66 is a mandatory
-			// prefix rather than an operand size override, but we know of
-			// no corresponding F2/F3 form, and we see both F2/F3 and 66.
-			// Does F2/F3 still take priority, so that the result is an unknown
-			// instruction, or does the 66 take priority, so that the extended
-			// 66 instruction should be interpreted as having a REP/REPN prefix?
-			// Intel xed does the former and GNU libopcodes does the latter.
-			// We side with Intel xed, unless we are trying to match libopcodes
-			// more closely during the comparison-based test suite.
-			//
-			// In 64-bit mode REX.W is another valid prefix to test for, but
-			// there is less ambiguity about that. When present, REX.W is
-			// always the first entry in the table.
-			n := int(decoder[pc])
-			pc++
-			sawF3 := false
-			for j := 0; j < n; j++ {
-				prefix := Prefix(decoder[pc+2*j])
-				if prefix.IsREX() {
-					rexUsed |= prefix
-					if rex&prefix == prefix {
-						pc = int(decoder[pc+2*j+1])
-						continue Decode
-					}
-					continue
-				}
-				ok := false
-				if prefix == 0 {
-					ok = true
-				} else if prefix.IsREX() {
-					rexUsed |= prefix
-					if rex&prefix == prefix {
-						ok = true
-					}
-				} else {
-					if prefix == 0xF3 {
-						sawF3 = true
-					}
-					switch prefix {
-					case PrefixLOCK:
-						if lockIndex >= 0 {
-							inst.Prefix[lockIndex] |= PrefixImplicit
-							ok = true
-						}
-					case PrefixREP, PrefixREPN:
-						if repIndex >= 0 && inst.Prefix[repIndex]&0xFF == prefix {
-							inst.Prefix[repIndex] |= PrefixImplicit
-							ok = true
-						}
-						if gnuCompat && !ok && prefix == 0xF3 && repIndex >= 0 && (j+1 >= n || decoder[pc+2*(j+1)] != 0xF2) {
-							// Check to see if earlier prefix F3 is present.
-							for i := repIndex - 1; i >= 0; i-- {
-								if inst.Prefix[i]&0xFF == prefix {
-									inst.Prefix[i] |= PrefixImplicit
-									ok = true
-								}
-							}
-						}
-						if gnuCompat && !ok && prefix == 0xF2 && repIndex >= 0 && !sawF3 && inst.Prefix[repIndex]&0xFF == 0xF3 {
-							// Check to see if earlier prefix F2 is present.
-							for i := repIndex - 1; i >= 0; i-- {
-								if inst.Prefix[i]&0xFF == prefix {
-									inst.Prefix[i] |= PrefixImplicit
-									ok = true
-								}
-							}
-						}
-					case PrefixCS, PrefixDS, PrefixES, PrefixFS, PrefixGS, PrefixSS:
-						if segIndex >= 0 && inst.Prefix[segIndex]&0xFF == prefix {
-							inst.Prefix[segIndex] |= PrefixImplicit
-							ok = true
-						}
-					case PrefixDataSize:
-						// Looking for 66 mandatory prefix.
-						// The F2/F3 mandatory prefixes take priority when both are present.
-						// If we got this far in the xCondPrefix table and an F2/F3 is present,
-						// it means the table didn't have any entry for that prefix. But if 66 has
-						// special meaning, perhaps F2/F3 have special meaning that we don't know.
-						// Intel xed works this way, treating the F2/F3 as inhibiting the 66.
-						// GNU libopcodes allows the 66 to match. We do what Intel xed does
-						// except in gnuCompat mode.
-						if repIndex >= 0 && !gnuCompat {
-							inst.Op = 0
-							break Decode
-						}
-						if dataSizeIndex >= 0 {
-							inst.Prefix[dataSizeIndex] |= PrefixImplicit
-							ok = true
-						}
-					case PrefixAddrSize:
-						if addrSizeIndex >= 0 {
-							inst.Prefix[addrSizeIndex] |= PrefixImplicit
-							ok = true
-						}
-					}
-				}
-				if ok {
-					pc = int(decoder[pc+2*j+1])
-					continue Decode
-				}
-			}
-			inst.Op = 0
-			break Decode
-
-		case xCondSlashR:
-			pc = int(decoder[pc+regop&7])
-
-		// Input.
-
-		case xReadSlashR:
-			// done above
-
-		case xReadIb:
-			if pos >= len(src) {
-				return truncated(src, mode)
-			}
-			imm8 = int8(src[pos])
-			pos++
-
-		case xReadIw:
-			if pos+2 > len(src) {
-				return truncated(src, mode)
-			}
-			imm = int64(binary.LittleEndian.Uint16(src[pos:]))
-			pos += 2
-
-		case xReadId:
-			if pos+4 > len(src) {
-				return truncated(src, mode)
-			}
-			imm = int64(binary.LittleEndian.Uint32(src[pos:]))
-			pos += 4
-
-		case xReadIo:
-			if pos+8 > len(src) {
-				return truncated(src, mode)
-			}
-			imm = int64(binary.LittleEndian.Uint64(src[pos:]))
-			pos += 8
-
-		case xReadCb:
-			if pos >= len(src) {
-				return truncated(src, mode)
-			}
-			immc = int64(src[pos])
-			pos++
-
-		case xReadCw:
-			if pos+2 > len(src) {
-				return truncated(src, mode)
-			}
-			immc = int64(binary.LittleEndian.Uint16(src[pos:]))
-			pos += 2
-
-		case xReadCm:
-			if addrMode == 16 {
-				if pos+2 > len(src) {
-					return truncated(src, mode)
-				}
-				immc = int64(binary.LittleEndian.Uint16(src[pos:]))
-				pos += 2
-			} else if addrMode == 32 {
-				if pos+4 > len(src) {
-					return truncated(src, mode)
-				}
-				immc = int64(binary.LittleEndian.Uint32(src[pos:]))
-				pos += 4
-			} else {
-				if pos+8 > len(src) {
-					return truncated(src, mode)
-				}
-				immc = int64(binary.LittleEndian.Uint64(src[pos:]))
-				pos += 8
-			}
-		case xReadCd:
-			if pos+4 > len(src) {
-				return truncated(src, mode)
-			}
-			immc = int64(binary.LittleEndian.Uint32(src[pos:]))
-			pos += 4
-
-		case xReadCp:
-			if pos+6 > len(src) {
-				return truncated(src, mode)
-			}
-			w := binary.LittleEndian.Uint32(src[pos:])
-			w2 := binary.LittleEndian.Uint16(src[pos+4:])
-			immc = int64(w2)<<32 | int64(w)
-			pos += 6
-
-		// Output.
-
-		case xSetOp:
-			inst.Op = Op(decoder[pc])
-			pc++
-
-		case xArg1,
-			xArg3,
-			xArgAL,
-			xArgAX,
-			xArgCL,
-			xArgCS,
-			xArgDS,
-			xArgDX,
-			xArgEAX,
-			xArgEDX,
-			xArgES,
-			xArgFS,
-			xArgGS,
-			xArgRAX,
-			xArgRDX,
-			xArgSS,
-			xArgST,
-			xArgXMM0:
-			inst.Args[narg] = fixedArg[x]
-			narg++
-
-		case xArgImm8:
-			inst.Args[narg] = Imm(imm8)
-			narg++
-
-		case xArgImm8u:
-			inst.Args[narg] = Imm(uint8(imm8))
-			narg++
-
-		case xArgImm16:
-			inst.Args[narg] = Imm(int16(imm))
-			narg++
-
-		case xArgImm16u:
-			inst.Args[narg] = Imm(uint16(imm))
-			narg++
-
-		case xArgImm32:
-			inst.Args[narg] = Imm(int32(imm))
-			narg++
-
-		case xArgImm64:
-			inst.Args[narg] = Imm(imm)
-			narg++
-
-		case xArgM,
-			xArgM128,
-			xArgM1428byte,
-			xArgM16,
-			xArgM16and16,
-			xArgM16and32,
-			xArgM16and64,
-			xArgM16colon16,
-			xArgM16colon32,
-			xArgM16colon64,
-			xArgM16int,
-			xArgM2byte,
-			xArgM32,
-			xArgM32and32,
-			xArgM32fp,
-			xArgM32int,
-			xArgM512byte,
-			xArgM64,
-			xArgM64fp,
-			xArgM64int,
-			xArgM8,
-			xArgM80bcd,
-			xArgM80dec,
-			xArgM80fp,
-			xArgM94108byte,
-			xArgMem:
-			if !haveMem {
-				inst.Op = 0
-				break Decode
-			}
-			inst.Args[narg] = mem
-			inst.MemBytes = int(memBytes[decodeOp(x)])
-			narg++
-
-		case xArgPtr16colon16:
-			inst.Args[narg] = Imm(immc >> 16)
-			inst.Args[narg+1] = Imm(immc & (1<<16 - 1))
-			narg += 2
-
-		case xArgPtr16colon32:
-			inst.Args[narg] = Imm(immc >> 32)
-			inst.Args[narg+1] = Imm(immc & (1<<32 - 1))
-			narg += 2
-
-		case xArgMoffs8, xArgMoffs16, xArgMoffs32, xArgMoffs64:
-			// TODO(rsc): Can address be 64 bits?
-			mem = Mem{Disp: int64(immc)}
-			if segIndex >= 0 {
-				mem.Segment = prefixToSegment(inst.Prefix[segIndex])
-				inst.Prefix[segIndex] |= PrefixImplicit
-			}
-			inst.Args[narg] = mem
-			inst.MemBytes = int(memBytes[decodeOp(x)])
-			narg++
-
-		case xArgR8, xArgR16, xArgR32, xArgR64, xArgXmm, xArgXmm1, xArgDR0dashDR7:
-			base := baseReg[x]
-			index := Reg(regop)
-			if rex != 0 && base == AL && index >= 4 {
-				rexUsed |= PrefixREX
-				index -= 4
-				base = SPB
-			}
-			inst.Args[narg] = base + index
-			narg++
-
-		case xArgMm, xArgMm1, xArgTR0dashTR7:
-			inst.Args[narg] = baseReg[x] + Reg(regop&7)
-			narg++
-
-		case xArgCR0dashCR7:
-			// AMD documents an extension that the LOCK prefix
-			// can be used in place of a REX prefix in order to access
-			// CR8 from 32-bit mode. The LOCK prefix is allowed in
-			// all modes, provided the corresponding CPUID bit is set.
-			if lockIndex >= 0 {
-				inst.Prefix[lockIndex] |= PrefixImplicit
-				regop += 8
-			}
-			inst.Args[narg] = CR0 + Reg(regop)
-			narg++
-
-		case xArgSreg:
-			regop &= 7
-			if regop >= 6 {
-				inst.Op = 0
-				break Decode
-			}
-			inst.Args[narg] = ES + Reg(regop)
-			narg++
-
-		case xArgRmf16, xArgRmf32, xArgRmf64:
-			base := baseReg[x]
-			index := Reg(modrm & 07)
-			if rex&PrefixREXB != 0 {
-				rexUsed |= PrefixREXB
-				index += 8
-			}
-			inst.Args[narg] = base + index
-			narg++
-
-		case xArgR8op, xArgR16op, xArgR32op, xArgR64op, xArgSTi:
-			n := inst.Opcode >> uint(opshift+8) & 07
-			base := baseReg[x]
-			index := Reg(n)
-			if rex&PrefixREXB != 0 && decodeOp(x) != xArgSTi {
-				rexUsed |= PrefixREXB
-				index += 8
-			}
-			if rex != 0 && base == AL && index >= 4 {
-				rexUsed |= PrefixREX
-				index -= 4
-				base = SPB
-			}
-			inst.Args[narg] = base + index
-			narg++
-
-		case xArgRM8, xArgRM16, xArgRM32, xArgRM64, xArgR32M16, xArgR32M8, xArgR64M16,
-			xArgMmM32, xArgMmM64, xArgMm2M64,
-			xArgXmm2M16, xArgXmm2M32, xArgXmm2M64, xArgXmmM64, xArgXmmM128, xArgXmmM32, xArgXmm2M128:
-			if haveMem {
-				inst.Args[narg] = mem
-				inst.MemBytes = int(memBytes[decodeOp(x)])
-			} else {
-				base := baseReg[x]
-				index := Reg(rm)
-				switch decodeOp(x) {
-				case xArgMmM32, xArgMmM64, xArgMm2M64:
-					// There are only 8 MMX registers, so these ignore the REX.X bit.
-					index &= 7
-				case xArgRM8:
-					if rex != 0 && index >= 4 {
-						rexUsed |= PrefixREX
-						index -= 4
-						base = SPB
-					}
-				}
-				inst.Args[narg] = base + index
-			}
-			narg++
-
-		case xArgMm2: // register only; TODO(rsc): Handle with tag modrm_regonly tag
-			if haveMem {
-				inst.Op = 0
-				break Decode
-			}
-			inst.Args[narg] = baseReg[x] + Reg(rm&7)
-			narg++
-
-		case xArgXmm2: // register only; TODO(rsc): Handle with tag modrm_regonly tag
-			if haveMem {
-				inst.Op = 0
-				break Decode
-			}
-			inst.Args[narg] = baseReg[x] + Reg(rm)
-			narg++
-
-		case xArgRel8:
-			inst.Args[narg] = Rel(int8(immc))
-			narg++
-
-		case xArgRel16:
-			inst.Args[narg] = Rel(int16(immc))
-			narg++
-
-		case xArgRel32:
-			inst.Args[narg] = Rel(int32(immc))
-			narg++
-		}
-	}
-
-	if inst.Op == 0 {
-		// Invalid instruction.
-		if nprefix > 0 {
-			return instPrefix(src[0], mode) // invalid instruction
-		}
-		return Inst{Len: pos}, ErrUnrecognized
-	}
-
-	// Matched! Hooray!
-
-	// 90 decodes as XCHG EAX, EAX but is NOP.
-	// 66 90 decodes as XCHG AX, AX and is NOP too.
-	// 48 90 decodes as XCHG RAX, RAX and is NOP too.
-	// 43 90 decodes as XCHG R8D, EAX and is *not* NOP.
-	// F3 90 decodes as REP XCHG EAX, EAX but is PAUSE.
-	// It's all too special to handle in the decoding tables, at least for now.
-	if inst.Op == XCHG && inst.Opcode>>24 == 0x90 {
-		if inst.Args[0] == RAX || inst.Args[0] == EAX || inst.Args[0] == AX {
-			inst.Op = NOP
-			if dataSizeIndex >= 0 {
-				inst.Prefix[dataSizeIndex] &^= PrefixImplicit
-			}
-			inst.Args[0] = nil
-			inst.Args[1] = nil
-		}
-		if repIndex >= 0 && inst.Prefix[repIndex] == 0xF3 {
-			inst.Prefix[repIndex] |= PrefixImplicit
-			inst.Op = PAUSE
-			inst.Args[0] = nil
-			inst.Args[1] = nil
-		} else if gnuCompat {
-			for i := nprefix - 1; i >= 0; i-- {
-				if inst.Prefix[i]&0xFF == 0xF3 {
-					inst.Prefix[i] |= PrefixImplicit
-					inst.Op = PAUSE
-					inst.Args[0] = nil
-					inst.Args[1] = nil
-					break
-				}
-			}
-		}
-	}
-
-	// defaultSeg returns the default segment for an implicit
-	// memory reference: the final override if present, or else DS.
-	defaultSeg := func() Reg {
-		if segIndex >= 0 {
-			inst.Prefix[segIndex] |= PrefixImplicit
-			return prefixToSegment(inst.Prefix[segIndex])
-		}
-		return DS
-	}
-
-	// Add implicit arguments not present in the tables.
-	// Normally we shy away from making implicit arguments explicit,
-	// following the Intel manuals, but adding the arguments seems
-	// the best way to express the effect of the segment override prefixes.
-	// TODO(rsc): Perhaps add these to the tables and
-	// create bytecode instructions for them.
-	usedAddrSize := false
-	switch inst.Op {
-	case INSB, INSW, INSD:
-		inst.Args[0] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}
-		inst.Args[1] = DX
-		usedAddrSize = true
-
-	case OUTSB, OUTSW, OUTSD:
-		inst.Args[0] = DX
-		inst.Args[1] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX}
-		usedAddrSize = true
-
-	case MOVSB, MOVSW, MOVSD, MOVSQ:
-		inst.Args[0] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}
-		inst.Args[1] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX}
-		usedAddrSize = true
-
-	case CMPSB, CMPSW, CMPSD, CMPSQ:
-		inst.Args[0] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX}
-		inst.Args[1] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}
-		usedAddrSize = true
-
-	case LODSB, LODSW, LODSD, LODSQ:
-		switch inst.Op {
-		case LODSB:
-			inst.Args[0] = AL
-		case LODSW:
-			inst.Args[0] = AX
-		case LODSD:
-			inst.Args[0] = EAX
-		case LODSQ:
-			inst.Args[0] = RAX
-		}
-		inst.Args[1] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX}
-		usedAddrSize = true
-
-	case STOSB, STOSW, STOSD, STOSQ:
-		inst.Args[0] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}
-		switch inst.Op {
-		case STOSB:
-			inst.Args[1] = AL
-		case STOSW:
-			inst.Args[1] = AX
-		case STOSD:
-			inst.Args[1] = EAX
-		case STOSQ:
-			inst.Args[1] = RAX
-		}
-		usedAddrSize = true
-
-	case SCASB, SCASW, SCASD, SCASQ:
-		inst.Args[1] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}
-		switch inst.Op {
-		case SCASB:
-			inst.Args[0] = AL
-		case SCASW:
-			inst.Args[0] = AX
-		case SCASD:
-			inst.Args[0] = EAX
-		case SCASQ:
-			inst.Args[0] = RAX
-		}
-		usedAddrSize = true
-
-	case XLATB:
-		inst.Args[0] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + BX - AX}
-		usedAddrSize = true
-	}
-
-	// If we used the address size annotation to construct the
-	// argument list, mark that prefix as implicit: it doesn't need
-	// to be shown when printing the instruction.
-	if haveMem || usedAddrSize {
-		if addrSizeIndex >= 0 {
-			inst.Prefix[addrSizeIndex] |= PrefixImplicit
-		}
-	}
-
-	// Similarly, if there's some memory operand, the segment
-	// will be shown there and doesn't need to be shown as an
-	// explicit prefix.
-	if haveMem {
-		if segIndex >= 0 {
-			inst.Prefix[segIndex] |= PrefixImplicit
-		}
-	}
-
-	// Branch predict prefixes are overloaded segment prefixes,
-	// since segment prefixes don't make sense on conditional jumps.
-	// Rewrite final instance to prediction prefix.
-	// The set of instructions to which the prefixes apply (other then the
-	// Jcc conditional jumps) is not 100% clear from the manuals, but
-	// the disassemblers seem to agree about the LOOP and JCXZ instructions,
-	// so we'll follow along.
-	// TODO(rsc): Perhaps this instruction class should be derived from the CSV.
-	if isCondJmp[inst.Op] || isLoop[inst.Op] || inst.Op == JCXZ || inst.Op == JECXZ || inst.Op == JRCXZ {
-	PredictLoop:
-		for i := nprefix - 1; i >= 0; i-- {
-			p := inst.Prefix[i]
-			switch p & 0xFF {
-			case PrefixCS:
-				inst.Prefix[i] = PrefixPN
-				break PredictLoop
-			case PrefixDS:
-				inst.Prefix[i] = PrefixPT
-				break PredictLoop
-			}
-		}
-	}
-
-	// The BND prefix is part of the Intel Memory Protection Extensions (MPX).
-	// A REPN applied to certain control transfers is a BND prefix to bound
-	// the range of possible destinations. There's surprisingly little documentation
-	// about this, so we just do what libopcodes and xed agree on.
-	// In particular, it's unclear why a REPN applied to LOOP or JCXZ instructions
-	// does not turn into a BND.
-	// TODO(rsc): Perhaps this instruction class should be derived from the CSV.
-	if isCondJmp[inst.Op] || inst.Op == JMP || inst.Op == CALL || inst.Op == RET {
-		for i := nprefix - 1; i >= 0; i-- {
-			p := inst.Prefix[i]
-			if p&^PrefixIgnored == PrefixREPN {
-				inst.Prefix[i] = PrefixBND
-				break
-			}
-		}
-	}
-
-	// The LOCK prefix only applies to certain instructions, and then only
-	// to instances of the instruction with a memory destination.
-	// Other uses of LOCK are invalid and cause a processor exception,
-	// in contrast to the "just ignore it" spirit applied to all other prefixes.
-	// Mark invalid lock prefixes.
-	hasLock := false
-	if lockIndex >= 0 && inst.Prefix[lockIndex]&PrefixImplicit == 0 {
-		switch inst.Op {
-		// TODO(rsc): Perhaps this instruction class should be derived from the CSV.
-		case ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCHG8B, CMPXCHG16B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, XCHG:
-			if isMem(inst.Args[0]) {
-				hasLock = true
-				break
-			}
-			fallthrough
-		default:
-			inst.Prefix[lockIndex] |= PrefixInvalid
-		}
-	}
-
-	// In certain cases, all of which require a memory destination,
-	// the REPN and REP prefixes are interpreted as XACQUIRE and XRELEASE
-	// from the Intel Transactional Synchroniation Extensions (TSX).
-	//
-	// The specific rules are:
-	// (1) Any instruction with a valid LOCK prefix can have XACQUIRE or XRELEASE.
-	// (2) Any XCHG, which always has an implicit LOCK, can have XACQUIRE or XRELEASE.
-	// (3) Any 0x88-, 0x89-, 0xC6-, or 0xC7-opcode MOV can have XRELEASE.
-	if isMem(inst.Args[0]) {
-		if inst.Op == XCHG {
-			hasLock = true
-		}
-
-		for i := len(inst.Prefix) - 1; i >= 0; i-- {
-			p := inst.Prefix[i] &^ PrefixIgnored
-			switch p {
-			case PrefixREPN:
-				if hasLock {
-					inst.Prefix[i] = inst.Prefix[i]&PrefixIgnored | PrefixXACQUIRE
-				}
-
-			case PrefixREP:
-				if hasLock {
-					inst.Prefix[i] = inst.Prefix[i]&PrefixIgnored | PrefixXRELEASE
-				}
-
-				if inst.Op == MOV {
-					op := (inst.Opcode >> 24) &^ 1
-					if op == 0x88 || op == 0xC6 {
-						inst.Prefix[i] = inst.Prefix[i]&PrefixIgnored | PrefixXRELEASE
-					}
-				}
-			}
-		}
-	}
-
-	// If REP is used on a non-REP-able instruction, mark the prefix as ignored.
-	if repIndex >= 0 {
-		switch inst.Prefix[repIndex] {
-		case PrefixREP, PrefixREPN:
-			switch inst.Op {
-			// According to the manuals, the REP/REPE prefix applies to all of these,
-			// while the REPN applies only to some of them. However, both libopcodes
-			// and xed show both prefixes explicitly for all instructions, so we do the same.
-			// TODO(rsc): Perhaps this instruction class should be derived from the CSV.
-			case INSB, INSW, INSD,
-				MOVSB, MOVSW, MOVSD, MOVSQ,
-				OUTSB, OUTSW, OUTSD,
-				LODSB, LODSW, LODSD, LODSQ,
-				CMPSB, CMPSW, CMPSD, CMPSQ,
-				SCASB, SCASW, SCASD, SCASQ,
-				STOSB, STOSW, STOSD, STOSQ:
-				// ok
-			default:
-				inst.Prefix[repIndex] |= PrefixIgnored
-			}
-		}
-	}
-
-	// If REX was present, mark implicit if all the 1 bits were consumed.
-	if rexIndex >= 0 {
-		if rexUsed != 0 {
-			rexUsed |= PrefixREX
-		}
-		if rex&^rexUsed == 0 {
-			inst.Prefix[rexIndex] |= PrefixImplicit
-		}
-	}
-
-	inst.DataSize = dataMode
-	inst.AddrSize = addrMode
-	inst.Mode = mode
-	inst.Len = pos
-	return inst, nil
-}
-
-var errInternal = errors.New("internal error")
-
-// addr16 records the eight 16-bit addressing modes.
-var addr16 = [8]Mem{
-	{Base: BX, Scale: 1, Index: SI},
-	{Base: BX, Scale: 1, Index: DI},
-	{Base: BP, Scale: 1, Index: SI},
-	{Base: BP, Scale: 1, Index: DI},
-	{Base: SI},
-	{Base: DI},
-	{Base: BP},
-	{Base: BX},
-}
-
-// baseReg returns the base register for a given register size in bits.
-func baseRegForBits(bits int) Reg {
-	switch bits {
-	case 8:
-		return AL
-	case 16:
-		return AX
-	case 32:
-		return EAX
-	case 64:
-		return RAX
-	}
-	return 0
-}
-
-// baseReg records the base register for argument types that specify
-// a range of registers indexed by op, regop, or rm.
-var baseReg = [...]Reg{
-	xArgDR0dashDR7: DR0,
-	xArgMm1:        M0,
-	xArgMm2:        M0,
-	xArgMm2M64:     M0,
-	xArgMm:         M0,
-	xArgMmM32:      M0,
-	xArgMmM64:      M0,
-	xArgR16:        AX,
-	xArgR16op:      AX,
-	xArgR32:        EAX,
-	xArgR32M16:     EAX,
-	xArgR32M8:      EAX,
-	xArgR32op:      EAX,
-	xArgR64:        RAX,
-	xArgR64M16:     RAX,
-	xArgR64op:      RAX,
-	xArgR8:         AL,
-	xArgR8op:       AL,
-	xArgRM16:       AX,
-	xArgRM32:       EAX,
-	xArgRM64:       RAX,
-	xArgRM8:        AL,
-	xArgRmf16:      AX,
-	xArgRmf32:      EAX,
-	xArgRmf64:      RAX,
-	xArgSTi:        F0,
-	xArgTR0dashTR7: TR0,
-	xArgXmm1:       X0,
-	xArgXmm2:       X0,
-	xArgXmm2M128:   X0,
-	xArgXmm2M16:    X0,
-	xArgXmm2M32:    X0,
-	xArgXmm2M64:    X0,
-	xArgXmm:        X0,
-	xArgXmmM128:    X0,
-	xArgXmmM32:     X0,
-	xArgXmmM64:     X0,
-}
-
-// prefixToSegment returns the segment register
-// corresponding to a particular segment prefix.
-func prefixToSegment(p Prefix) Reg {
-	switch p &^ PrefixImplicit {
-	case PrefixCS:
-		return CS
-	case PrefixDS:
-		return DS
-	case PrefixES:
-		return ES
-	case PrefixFS:
-		return FS
-	case PrefixGS:
-		return GS
-	case PrefixSS:
-		return SS
-	}
-	return 0
-}
-
-// fixedArg records the fixed arguments corresponding to the given bytecodes.
-var fixedArg = [...]Arg{
-	xArg1:    Imm(1),
-	xArg3:    Imm(3),
-	xArgAL:   AL,
-	xArgAX:   AX,
-	xArgDX:   DX,
-	xArgEAX:  EAX,
-	xArgEDX:  EDX,
-	xArgRAX:  RAX,
-	xArgRDX:  RDX,
-	xArgCL:   CL,
-	xArgCS:   CS,
-	xArgDS:   DS,
-	xArgES:   ES,
-	xArgFS:   FS,
-	xArgGS:   GS,
-	xArgSS:   SS,
-	xArgST:   F0,
-	xArgXMM0: X0,
-}
-
-// memBytes records the size of the memory pointed at
-// by a memory argument of the given form.
-var memBytes = [...]int8{
-	xArgM128:       128 / 8,
-	xArgM16:        16 / 8,
-	xArgM16and16:   (16 + 16) / 8,
-	xArgM16colon16: (16 + 16) / 8,
-	xArgM16colon32: (16 + 32) / 8,
-	xArgM16int:     16 / 8,
-	xArgM2byte:     2,
-	xArgM32:        32 / 8,
-	xArgM32and32:   (32 + 32) / 8,
-	xArgM32fp:      32 / 8,
-	xArgM32int:     32 / 8,
-	xArgM64:        64 / 8,
-	xArgM64fp:      64 / 8,
-	xArgM64int:     64 / 8,
-	xArgMm2M64:     64 / 8,
-	xArgMmM32:      32 / 8,
-	xArgMmM64:      64 / 8,
-	xArgMoffs16:    16 / 8,
-	xArgMoffs32:    32 / 8,
-	xArgMoffs64:    64 / 8,
-	xArgMoffs8:     8 / 8,
-	xArgR32M16:     16 / 8,
-	xArgR32M8:      8 / 8,
-	xArgR64M16:     16 / 8,
-	xArgRM16:       16 / 8,
-	xArgRM32:       32 / 8,
-	xArgRM64:       64 / 8,
-	xArgRM8:        8 / 8,
-	xArgXmm2M128:   128 / 8,
-	xArgXmm2M16:    16 / 8,
-	xArgXmm2M32:    32 / 8,
-	xArgXmm2M64:    64 / 8,
-	xArgXmm:        128 / 8,
-	xArgXmmM128:    128 / 8,
-	xArgXmmM32:     32 / 8,
-	xArgXmmM64:     64 / 8,
-}
-
-// isCondJmp records the conditional jumps.
-var isCondJmp = [maxOp + 1]bool{
-	JA:  true,
-	JAE: true,
-	JB:  true,
-	JBE: true,
-	JE:  true,
-	JG:  true,
-	JGE: true,
-	JL:  true,
-	JLE: true,
-	JNE: true,
-	JNO: true,
-	JNP: true,
-	JNS: true,
-	JO:  true,
-	JP:  true,
-	JS:  true,
-}
-
-// isLoop records the loop operators.
-var isLoop = [maxOp + 1]bool{
-	LOOP:   true,
-	LOOPE:  true,
-	LOOPNE: true,
-	JECXZ:  true,
-	JRCXZ:  true,
-}
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/decode_test.go b/src/cmd/internal/rsc.io/x86/x86asm/decode_test.go
deleted file mode 100644
index fb28458..0000000
--- a/src/cmd/internal/rsc.io/x86/x86asm/decode_test.go
+++ /dev/null
@@ -1,71 +0,0 @@
-// 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 x86asm
-
-import (
-	"encoding/hex"
-	"io/ioutil"
-	"strconv"
-	"strings"
-	"testing"
-)
-
-func TestDecode(t *testing.T) {
-	data, err := ioutil.ReadFile("testdata/decode.txt")
-	if err != nil {
-		t.Fatal(err)
-	}
-	all := string(data)
-	for strings.Contains(all, "\t\t") {
-		all = strings.Replace(all, "\t\t", "\t", -1)
-	}
-	for _, line := range strings.Split(all, "\n") {
-		line = strings.TrimSpace(line)
-		if line == "" || strings.HasPrefix(line, "#") {
-			continue
-		}
-		f := strings.SplitN(line, "\t", 4)
-		i := strings.Index(f[0], "|")
-		if i < 0 {
-			t.Errorf("parsing %q: missing | separator", f[0])
-			continue
-		}
-		if i%2 != 0 {
-			t.Errorf("parsing %q: misaligned | separator", f[0])
-		}
-		size := i / 2
-		code, err := hex.DecodeString(f[0][:i] + f[0][i+1:])
-		if err != nil {
-			t.Errorf("parsing %q: %v", f[0], err)
-			continue
-		}
-		mode, err := strconv.Atoi(f[1])
-		if err != nil {
-			t.Errorf("invalid mode %q in: %s", f[1], line)
-			continue
-		}
-		syntax, asm := f[2], f[3]
-		inst, err := Decode(code, mode)
-		var out string
-		if err != nil {
-			out = "error: " + err.Error()
-		} else {
-			switch syntax {
-			case "gnu":
-				out = GNUSyntax(inst)
-			case "intel":
-				out = IntelSyntax(inst)
-			case "plan9":
-				out = Plan9Syntax(inst, 0, nil)
-			default:
-				t.Errorf("unknown syntax %q", syntax)
-				continue
-			}
-		}
-		if out != asm || inst.Len != size {
-			t.Errorf("Decode(%s) [%s] = %s, %d, want %s, %d", f[0], syntax, out, inst.Len, asm, size)
-		}
-	}
-}
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/ext_test.go b/src/cmd/internal/rsc.io/x86/x86asm/ext_test.go
deleted file mode 100644
index bb56c0d..0000000
--- a/src/cmd/internal/rsc.io/x86/x86asm/ext_test.go
+++ /dev/null
@@ -1,811 +0,0 @@
-// 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.
-
-// Support for testing against external disassembler program.
-
-package x86asm
-
-import (
-	"bufio"
-	"bytes"
-	"encoding/hex"
-	"flag"
-	"fmt"
-	"io/ioutil"
-	"log"
-	"math/rand"
-	"os"
-	"os/exec"
-	"regexp"
-	"runtime"
-	"strings"
-	"testing"
-	"time"
-)
-
-var (
-	printTests = flag.Bool("printtests", false, "print test cases that exercise new code paths")
-	dumpTest   = flag.Bool("dump", false, "dump all encodings")
-	mismatch   = flag.Bool("mismatch", false, "log allowed mismatches")
-	longTest   = flag.Bool("long", false, "long test")
-	keep       = flag.Bool("keep", false, "keep object files around")
-	debug      = false
-)
-
-// A ExtInst represents a single decoded instruction parsed
-// from an external disassembler's output.
-type ExtInst struct {
-	addr uint32
-	enc  [32]byte
-	nenc int
-	text string
-}
-
-func (r ExtInst) String() string {
-	return fmt.Sprintf("%#x: % x: %s", r.addr, r.enc, r.text)
-}
-
-// An ExtDis is a connection between an external disassembler and a test.
-type ExtDis struct {
-	Arch     int
-	Dec      chan ExtInst
-	File     *os.File
-	Size     int
-	KeepFile bool
-	Cmd      *exec.Cmd
-}
-
-// Run runs the given command - the external disassembler - and returns
-// a buffered reader of its standard output.
-func (ext *ExtDis) Run(cmd ...string) (*bufio.Reader, error) {
-	if *keep {
-		log.Printf("%s\n", strings.Join(cmd, " "))
-	}
-	ext.Cmd = exec.Command(cmd[0], cmd[1:]...)
-	out, err := ext.Cmd.StdoutPipe()
-	if err != nil {
-		return nil, fmt.Errorf("stdoutpipe: %v", err)
-	}
-	if err := ext.Cmd.Start(); err != nil {
-		return nil, fmt.Errorf("exec: %v", err)
-	}
-
-	b := bufio.NewReaderSize(out, 1<<20)
-	return b, nil
-}
-
-// Wait waits for the command started with Run to exit.
-func (ext *ExtDis) Wait() error {
-	return ext.Cmd.Wait()
-}
-
-// testExtDis tests a set of byte sequences against an external disassembler.
-// The disassembler is expected to produce the given syntax and be run
-// in the given architecture mode (16, 32, or 64-bit).
-// The extdis function must start the external disassembler
-// and then parse its output, sending the parsed instructions on ext.Dec.
-// The generate function calls its argument f once for each byte sequence
-// to be tested. The generate function itself will be called twice, and it must
-// make the same sequence of calls to f each time.
-// When a disassembly does not match the internal decoding,
-// allowedMismatch determines whether this mismatch should be
-// allowed, or else considered an error.
-func testExtDis(
-	t *testing.T,
-	syntax string,
-	arch int,
-	extdis func(ext *ExtDis) error,
-	generate func(f func([]byte)),
-	allowedMismatch func(text string, size int, inst *Inst, dec ExtInst) bool,
-) {
-	start := time.Now()
-	ext := &ExtDis{
-		Dec:  make(chan ExtInst),
-		Arch: arch,
-	}
-	errc := make(chan error)
-
-	// First pass: write instructions to input file for external disassembler.
-	file, f, size, err := writeInst(generate)
-	if err != nil {
-		t.Fatal(err)
-	}
-	ext.Size = size
-	ext.File = f
-	defer func() {
-		f.Close()
-		if !*keep {
-			os.Remove(file)
-		}
-	}()
-
-	// Second pass: compare disassembly against our decodings.
-	var (
-		totalTests  = 0
-		totalSkips  = 0
-		totalErrors = 0
-
-		errors = make([]string, 0, 100) // sampled errors, at most cap
-	)
-	go func() {
-		errc <- extdis(ext)
-	}()
-	generate(func(enc []byte) {
-		dec, ok := <-ext.Dec
-		if !ok {
-			t.Errorf("decoding stream ended early")
-			return
-		}
-		inst, text := disasm(syntax, arch, pad(enc))
-		totalTests++
-		if *dumpTest {
-			fmt.Printf("%x -> %s [%d]\n", enc[:len(enc)], dec.text, dec.nenc)
-		}
-		if text != dec.text || inst.Len != dec.nenc {
-			suffix := ""
-			if allowedMismatch(text, size, &inst, dec) {
-				totalSkips++
-				if !*mismatch {
-					return
-				}
-				suffix += " (allowed mismatch)"
-			}
-			totalErrors++
-			if len(errors) >= cap(errors) {
-				j := rand.Intn(totalErrors)
-				if j >= cap(errors) {
-					return
-				}
-				errors = append(errors[:j], errors[j+1:]...)
-			}
-			errors = append(errors, fmt.Sprintf("decode(%x) = %q, %d, want %q, %d%s", enc, text, inst.Len, dec.text, dec.nenc, suffix))
-		}
-	})
-
-	if *mismatch {
-		totalErrors -= totalSkips
-	}
-
-	for _, b := range errors {
-		t.Log(b)
-	}
-
-	if totalErrors > 0 {
-		t.Fail()
-	}
-	t.Logf("%d test cases, %d expected mismatches, %d failures; %.0f cases/second", totalTests, totalSkips, totalErrors, float64(totalTests)/time.Since(start).Seconds())
-
-	if err := <-errc; err != nil {
-		t.Fatal("external disassembler: %v", err)
-	}
-
-}
-
-const start = 0x8000 // start address of text
-
-// writeInst writes the generated byte sequences to a new file
-// starting at offset start. That file is intended to be the input to
-// the external disassembler.
-func writeInst(generate func(func([]byte))) (file string, f *os.File, size int, err error) {
-	f, err = ioutil.TempFile("", "x86map")
-	if err != nil {
-		return
-	}
-
-	file = f.Name()
-
-	f.Seek(start, 0)
-	w := bufio.NewWriter(f)
-	defer w.Flush()
-	size = 0
-	generate(func(x []byte) {
-		if len(x) > 16 {
-			x = x[:16]
-		}
-		if debug {
-			fmt.Printf("%#x: %x%x\n", start+size, x, pops[len(x):])
-		}
-		w.Write(x)
-		w.Write(pops[len(x):])
-		size += len(pops)
-	})
-	return file, f, size, nil
-}
-
-// 0x5F is a single-byte pop instruction.
-// We pad the bytes we want decoded with enough 0x5Fs
-// that no matter what state the instruction stream is in
-// after reading our bytes, the pops will get us back to
-// a forced instruction boundary.
-var pops = []byte{
-	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
-	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
-	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
-	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
-}
-
-// pad pads the code sequence with pops.
-func pad(enc []byte) []byte {
-	return append(enc[:len(enc):len(enc)], pops...)
-}
-
-// disasm returns the decoded instruction and text
-// for the given source bytes, using the given syntax and mode.
-func disasm(syntax string, mode int, src []byte) (inst Inst, text string) {
-	// If printTests is set, we record the coverage value
-	// before and after, and we write out the inputs for which
-	// coverage went up, in the format expected in testdata/decode.text.
-	// This produces a fairly small set of test cases that exercise nearly
-	// all the code.
-	var cover float64
-	if *printTests {
-		cover -= coverage()
-	}
-
-	inst, err := decode1(src, mode, syntax == "gnu")
-	if err != nil {
-		text = "error: " + err.Error()
-	} else {
-		switch syntax {
-		case "gnu":
-			text = GNUSyntax(inst)
-		case "intel":
-			text = IntelSyntax(inst)
-		case "plan9":
-			text = Plan9Syntax(inst, 0, nil)
-		default:
-			text = "error: unknown syntax " + syntax
-		}
-	}
-
-	if *printTests {
-		cover += coverage()
-		if cover > 0 {
-			max := len(src)
-			if max > 16 && inst.Len <= 16 {
-				max = 16
-			}
-			fmt.Printf("%x|%x\t%d\t%s\t%s\n", src[:inst.Len], src[inst.Len:max], mode, syntax, text)
-		}
-	}
-
-	return
-}
-
-// coverage returns a floating point number denoting the
-// test coverage until now. The number increases when new code paths are exercised,
-// both in the Go program and in the decoder byte code.
-func coverage() float64 {
-	/*
-		testing.Coverage is not in the main distribution.
-		The implementation, which must go in package testing, is:
-
-		// Coverage reports the current code coverage as a fraction in the range [0, 1].
-		func Coverage() float64 {
-			var n, d int64
-			for _, counters := range cover.Counters {
-				for _, c := range counters {
-					if c > 0 {
-						n++
-					}
-					d++
-				}
-			}
-			if d == 0 {
-				return 0
-			}
-			return float64(n) / float64(d)
-		}
-	*/
-
-	var f float64
-	// f += testing.Coverage()
-	f += decodeCoverage()
-	return f
-}
-
-func decodeCoverage() float64 {
-	n := 0
-	for _, t := range decoderCover {
-		if t {
-			n++
-		}
-	}
-	return float64(1+n) / float64(1+len(decoderCover))
-}
-
-// Helpers for writing disassembler output parsers.
-
-// isPrefix reports whether text is the name of an instruction prefix.
-func isPrefix(text string) bool {
-	return prefixByte[text] > 0
-}
-
-// prefixByte maps instruction prefix text to actual prefix byte values.
-var prefixByte = map[string]byte{
-	"es":       0x26,
-	"cs":       0x2e,
-	"ss":       0x36,
-	"ds":       0x3e,
-	"fs":       0x64,
-	"gs":       0x65,
-	"data16":   0x66,
-	"addr16":   0x67,
-	"lock":     0xf0,
-	"repn":     0xf2,
-	"repne":    0xf2,
-	"rep":      0xf3,
-	"repe":     0xf3,
-	"xacquire": 0xf2,
-	"xrelease": 0xf3,
-	"bnd":      0xf2,
-	"addr32":   0x66,
-	"data32":   0x67,
-}
-
-// hasPrefix reports whether any of the space-separated words in the text s
-// begins with any of the given prefixes.
-func hasPrefix(s string, prefixes ...string) bool {
-	for _, prefix := range prefixes {
-		for s := s; s != ""; {
-			if strings.HasPrefix(s, prefix) {
-				return true
-			}
-			i := strings.Index(s, " ")
-			if i < 0 {
-				break
-			}
-			s = s[i+1:]
-		}
-	}
-	return false
-}
-
-// contains reports whether the text s contains any of the given substrings.
-func contains(s string, substrings ...string) bool {
-	for _, sub := range substrings {
-		if strings.Contains(s, sub) {
-			return true
-		}
-	}
-	return false
-}
-
-// isHex reports whether b is a hexadecimal character (0-9A-Fa-f).
-func isHex(b byte) bool { return b == '0' || unhex[b] > 0 }
-
-// parseHex parses the hexadecimal byte dump in hex,
-// appending the parsed bytes to raw and returning the updated slice.
-// The returned bool signals whether any invalid hex was found.
-// Spaces and tabs between bytes are okay but any other non-hex is not.
-func parseHex(hex []byte, raw []byte) ([]byte, bool) {
-	hex = trimSpace(hex)
-	for j := 0; j < len(hex); {
-		for hex[j] == ' ' || hex[j] == '\t' {
-			j++
-		}
-		if j >= len(hex) {
-			break
-		}
-		if j+2 > len(hex) || !isHex(hex[j]) || !isHex(hex[j+1]) {
-			return nil, false
-		}
-		raw = append(raw, unhex[hex[j]]<<4|unhex[hex[j+1]])
-		j += 2
-	}
-	return raw, true
-}
-
-var unhex = [256]byte{
-	'0': 0,
-	'1': 1,
-	'2': 2,
-	'3': 3,
-	'4': 4,
-	'5': 5,
-	'6': 6,
-	'7': 7,
-	'8': 8,
-	'9': 9,
-	'A': 10,
-	'B': 11,
-	'C': 12,
-	'D': 13,
-	'E': 14,
-	'F': 15,
-	'a': 10,
-	'b': 11,
-	'c': 12,
-	'd': 13,
-	'e': 14,
-	'f': 15,
-}
-
-// index is like bytes.Index(s, []byte(t)) but avoids the allocation.
-func index(s []byte, t string) int {
-	i := 0
-	for {
-		j := bytes.IndexByte(s[i:], t[0])
-		if j < 0 {
-			return -1
-		}
-		i = i + j
-		if i+len(t) > len(s) {
-			return -1
-		}
-		for k := 1; k < len(t); k++ {
-			if s[i+k] != t[k] {
-				goto nomatch
-			}
-		}
-		return i
-	nomatch:
-		i++
-	}
-}
-
-// fixSpace rewrites runs of spaces, tabs, and newline characters into single spaces in s.
-// If s must be rewritten, it is rewritten in place.
-func fixSpace(s []byte) []byte {
-	s = trimSpace(s)
-	for i := 0; i < len(s); i++ {
-		if s[i] == '\t' || s[i] == '\n' || i > 0 && s[i] == ' ' && s[i-1] == ' ' {
-			goto Fix
-		}
-	}
-	return s
-
-Fix:
-	b := s
-	w := 0
-	for i := 0; i < len(s); i++ {
-		c := s[i]
-		if c == '\t' || c == '\n' {
-			c = ' '
-		}
-		if c == ' ' && w > 0 && b[w-1] == ' ' {
-			continue
-		}
-		b[w] = c
-		w++
-	}
-	if w > 0 && b[w-1] == ' ' {
-		w--
-	}
-	return b[:w]
-}
-
-// trimSpace trims leading and trailing space from s, returning a subslice of s.
-func trimSpace(s []byte) []byte {
-	j := len(s)
-	for j > 0 && (s[j-1] == ' ' || s[j-1] == '\t' || s[j-1] == '\n') {
-		j--
-	}
-	i := 0
-	for i < j && (s[i] == ' ' || s[i] == '\t') {
-		i++
-	}
-	return s[i:j]
-}
-
-// pcrel and pcrelw match instructions using relative addressing mode.
-var (
-	pcrel  = regexp.MustCompile(`^((?:.* )?(?:j[a-z]+|call|ljmp|loopn?e?w?|xbegin)q?(?:,p[nt])?) 0x([0-9a-f]+)$`)
-	pcrelw = regexp.MustCompile(`^((?:.* )?(?:callw|jmpw|xbeginw|ljmpw)(?:,p[nt])?) 0x([0-9a-f]+)$`)
-)
-
-// Generators.
-//
-// The test cases are described as functions that invoke a callback repeatedly,
-// with a new input sequence each time. These helpers make writing those
-// a little easier.
-
-// hexCases generates the cases written in hexadecimal in the encoded string.
-// Spaces in 'encoded' separate entire test cases, not individual bytes.
-func hexCases(t *testing.T, encoded string) func(func([]byte)) {
-	return func(try func([]byte)) {
-		for _, x := range strings.Fields(encoded) {
-			src, err := hex.DecodeString(x)
-			if err != nil {
-				t.Errorf("parsing %q: %v", x, err)
-			}
-			try(src)
-		}
-	}
-}
-
-// testdataCases generates the test cases recorded in testdata/decode.txt.
-// It only uses the inputs; it ignores the answers recorded in that file.
-func testdataCases(t *testing.T) func(func([]byte)) {
-	var codes [][]byte
-	data, err := ioutil.ReadFile("testdata/decode.txt")
-	if err != nil {
-		t.Fatal(err)
-	}
-	for _, line := range strings.Split(string(data), "\n") {
-		line = strings.TrimSpace(line)
-		if line == "" || strings.HasPrefix(line, "#") {
-			continue
-		}
-		f := strings.Fields(line)[0]
-		i := strings.Index(f, "|")
-		if i < 0 {
-			t.Errorf("parsing %q: missing | separator", f)
-			continue
-		}
-		if i%2 != 0 {
-			t.Errorf("parsing %q: misaligned | separator", f)
-		}
-		code, err := hex.DecodeString(f[:i] + f[i+1:])
-		if err != nil {
-			t.Errorf("parsing %q: %v", f, err)
-			continue
-		}
-		codes = append(codes, code)
-	}
-
-	return func(try func([]byte)) {
-		for _, code := range codes {
-			try(code)
-		}
-	}
-}
-
-// manyPrefixes generates all possible 2⁹ combinations of nine chosen prefixes.
-// The relative ordering of the prefixes within the combinations varies deterministically.
-func manyPrefixes(try func([]byte)) {
-	var prefixBytes = []byte{0x66, 0x67, 0xF0, 0xF2, 0xF3, 0x3E, 0x36, 0x66, 0x67}
-	var enc []byte
-	for i := 0; i < 1<<uint(len(prefixBytes)); i++ {
-		enc = enc[:0]
-		for j, p := range prefixBytes {
-			if i&(1<<uint(j)) != 0 {
-				enc = append(enc, p)
-			}
-		}
-		if len(enc) > 0 {
-			k := i % len(enc)
-			enc[0], enc[k] = enc[k], enc[0]
-		}
-		try(enc)
-	}
-}
-
-// basicPrefixes geneartes 8 different possible prefix cases: no prefix
-// and then one each of seven different prefix bytes.
-func basicPrefixes(try func([]byte)) {
-	try(nil)
-	for _, b := range []byte{0x66, 0x67, 0xF0, 0xF2, 0xF3, 0x3E, 0x36} {
-		try([]byte{b})
-	}
-}
-
-func rexPrefixes(try func([]byte)) {
-	try(nil)
-	for _, b := range []byte{0x40, 0x48, 0x43, 0x4C} {
-		try([]byte{b})
-	}
-}
-
-// concat takes two generators and returns a generator for the
-// cross product of the two, concatenating the results from each.
-func concat(gen1, gen2 func(func([]byte))) func(func([]byte)) {
-	return func(try func([]byte)) {
-		gen1(func(enc1 []byte) {
-			gen2(func(enc2 []byte) {
-				try(append(enc1[:len(enc1):len(enc1)], enc2...))
-			})
-		})
-	}
-}
-
-// concat3 takes three generators and returns a generator for the
-// cross product of the three, concatenating the results from each.
-func concat3(gen1, gen2, gen3 func(func([]byte))) func(func([]byte)) {
-	return func(try func([]byte)) {
-		gen1(func(enc1 []byte) {
-			gen2(func(enc2 []byte) {
-				gen3(func(enc3 []byte) {
-					try(append(append(enc1[:len(enc1):len(enc1)], enc2...), enc3...))
-				})
-			})
-		})
-	}
-}
-
-// concat4 takes four generators and returns a generator for the
-// cross product of the four, concatenating the results from each.
-func concat4(gen1, gen2, gen3, gen4 func(func([]byte))) func(func([]byte)) {
-	return func(try func([]byte)) {
-		gen1(func(enc1 []byte) {
-			gen2(func(enc2 []byte) {
-				gen3(func(enc3 []byte) {
-					gen4(func(enc4 []byte) {
-						try(append(append(append(enc1[:len(enc1):len(enc1)], enc2...), enc3...), enc4...))
-					})
-				})
-			})
-		})
-	}
-}
-
-// filter generates the sequences from gen that satisfy ok.
-func filter(gen func(func([]byte)), ok func([]byte) bool) func(func([]byte)) {
-	return func(try func([]byte)) {
-		gen(func(enc []byte) {
-			if ok(enc) {
-				try(enc)
-			}
-		})
-	}
-}
-
-// enum8bit generates all possible 1-byte sequences, followed by distinctive padding.
-func enum8bit(try func([]byte)) {
-	for i := 0; i < 1<<8; i++ {
-		try([]byte{byte(i), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88})
-	}
-}
-
-// enum8bit generates all possible 2-byte sequences, followed by distinctive padding.
-func enum16bit(try func([]byte)) {
-	for i := 0; i < 1<<16; i++ {
-		try([]byte{byte(i), byte(i >> 8), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88})
-	}
-}
-
-// enum24bit generates all possible 3-byte sequences, followed by distinctive padding.
-func enum24bit(try func([]byte)) {
-	for i := 0; i < 1<<24; i++ {
-		try([]byte{byte(i), byte(i >> 8), byte(i >> 16), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88})
-	}
-}
-
-// enumModRM generates all possible modrm bytes and, for modrm values that indicate
-// a following sib byte, all possible modrm, sib combinations.
-func enumModRM(try func([]byte)) {
-	for i := 0; i < 256; i++ {
-		if (i>>3)&07 == 04 && i>>6 != 3 { // has sib
-			for j := 0; j < 256; j++ {
-				try([]byte{0, byte(i), byte(j), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}) // byte encodings
-				try([]byte{1, byte(i), byte(j), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}) // word encodings
-			}
-		} else {
-			try([]byte{0, byte(i), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}) // byte encodings
-			try([]byte{1, byte(i), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}) // word encodings
-		}
-	}
-}
-
-// fixed generates the single case b.
-// It's mainly useful to prepare an argument for concat or concat3.
-func fixed(b ...byte) func(func([]byte)) {
-	return func(try func([]byte)) {
-		try(b)
-	}
-}
-
-// testBasic runs the given test function with cases all using opcode as the initial opcode bytes.
-// It runs three phases:
-//
-// First, zero-or-one prefixes followed by opcode followed by all possible 1-byte values.
-// If in -short mode, that's all.
-//
-// Second, zero-or-one prefixes followed by opcode followed by all possible 2-byte values.
-// If not in -long mode, that's all. This phase and the next run in parallel with other tests
-// (using t.Parallel).
-//
-// Finally, opcode followed by all possible 3-byte values. The test can take a very long time
-// and prints progress messages to package log.
-func testBasic(t *testing.T, testfn func(*testing.T, func(func([]byte))), opcode ...byte) {
-	testfn(t, concat3(basicPrefixes, fixed(opcode...), enum8bit))
-	if testing.Short() {
-		return
-	}
-
-	t.Parallel()
-	testfn(t, concat3(basicPrefixes, fixed(opcode...), enum16bit))
-	if !*longTest {
-		return
-	}
-
-	name := caller(2)
-	op1 := make([]byte, len(opcode)+1)
-	copy(op1, opcode)
-	for i := 0; i < 256; i++ {
-		log.Printf("%s 24-bit: %d/256\n", name, i)
-		op1[len(opcode)] = byte(i)
-		testfn(t, concat(fixed(op1...), enum16bit))
-	}
-}
-
-func testBasicREX(t *testing.T, testfn func(*testing.T, func(func([]byte))), opcode ...byte) {
-	testfn(t, filter(concat4(basicPrefixes, rexPrefixes, fixed(opcode...), enum8bit), isValidREX))
-	if testing.Short() {
-		return
-	}
-
-	t.Parallel()
-	testfn(t, filter(concat4(basicPrefixes, rexPrefixes, fixed(opcode...), enum16bit), isValidREX))
-	if !*longTest {
-		return
-	}
-
-	name := caller(2)
-	op1 := make([]byte, len(opcode)+1)
-	copy(op1, opcode)
-	for i := 0; i < 256; i++ {
-		log.Printf("%s 24-bit: %d/256\n", name, i)
-		op1[len(opcode)] = byte(i)
-		testfn(t, filter(concat3(rexPrefixes, fixed(op1...), enum16bit), isValidREX))
-	}
-}
-
-// testPrefix runs the given test function for all many prefix possibilities
-// followed by all possible 1-byte sequences.
-//
-// If in -long mode, it then runs a test of all the prefix possibilities followed
-// by all possible 2-byte sequences.
-func testPrefix(t *testing.T, testfn func(*testing.T, func(func([]byte)))) {
-	t.Parallel()
-	testfn(t, concat(manyPrefixes, enum8bit))
-	if testing.Short() || !*longTest {
-		return
-	}
-
-	name := caller(2)
-	for i := 0; i < 256; i++ {
-		log.Printf("%s 16-bit: %d/256\n", name, i)
-		testfn(t, concat3(manyPrefixes, fixed(byte(i)), enum8bit))
-	}
-}
-
-func testPrefixREX(t *testing.T, testfn func(*testing.T, func(func([]byte)))) {
-	t.Parallel()
-	testfn(t, filter(concat3(manyPrefixes, rexPrefixes, enum8bit), isValidREX))
-	if testing.Short() || !*longTest {
-		return
-	}
-
-	name := caller(2)
-	for i := 0; i < 256; i++ {
-		log.Printf("%s 16-bit: %d/256\n", name, i)
-		testfn(t, filter(concat4(manyPrefixes, rexPrefixes, fixed(byte(i)), enum8bit), isValidREX))
-	}
-}
-
-func caller(skip int) string {
-	pc, _, _, _ := runtime.Caller(skip)
-	f := runtime.FuncForPC(pc)
-	name := "?"
-	if f != nil {
-		name = f.Name()
-		if i := strings.LastIndex(name, "."); i >= 0 {
-			name = name[i+1:]
-		}
-	}
-	return name
-}
-
-func isValidREX(x []byte) bool {
-	i := 0
-	for i < len(x) && isPrefixByte(x[i]) {
-		i++
-	}
-	if i < len(x) && Prefix(x[i]).IsREX() {
-		i++
-		if i < len(x) {
-			return !isPrefixByte(x[i]) && !Prefix(x[i]).IsREX()
-		}
-	}
-	return true
-}
-
-func isPrefixByte(b byte) bool {
-	switch b {
-	case 0x26, 0x2E, 0x36, 0x3E, 0x64, 0x65, 0x66, 0x67, 0xF0, 0xF2, 0xF3:
-		return true
-	}
-	return false
-}
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/inst.go b/src/cmd/internal/rsc.io/x86/x86asm/inst.go
deleted file mode 100644
index d4c1b6c..0000000
--- a/src/cmd/internal/rsc.io/x86/x86asm/inst.go
+++ /dev/null
@@ -1,641 +0,0 @@
-// 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 x86asm implements decoding of x86 machine code.
-package x86asm
-
-import (
-	"bytes"
-	"fmt"
-)
-
-// An Inst is a single instruction.
-type Inst struct {
-	Prefix   Prefixes // Prefixes applied to the instruction.
-	Op       Op       // Opcode mnemonic
-	Opcode   uint32   // Encoded opcode bits, left aligned (first byte is Opcode>>24, etc)
-	Args     Args     // Instruction arguments, in Intel order
-	Mode     int      // processor mode in bits: 16, 32, or 64
-	AddrSize int      // address size in bits: 16, 32, or 64
-	DataSize int      // operand size in bits: 16, 32, or 64
-	MemBytes int      // size of memory argument in bytes: 1, 2, 4, 8, 16, and so on.
-	Len      int      // length of encoded instruction in bytes
-}
-
-// Prefixes is an array of prefixes associated with a single instruction.
-// The prefixes are listed in the same order as found in the instruction:
-// each prefix byte corresponds to one slot in the array. The first zero
-// in the array marks the end of the prefixes.
-type Prefixes [14]Prefix
-
-// A Prefix represents an Intel instruction prefix.
-// The low 8 bits are the actual prefix byte encoding,
-// and the top 8 bits contain distinguishing bits and metadata.
-type Prefix uint16
-
-const (
-	// Metadata about the role of a prefix in an instruction.
-	PrefixImplicit Prefix = 0x8000 // prefix is implied by instruction text
-	PrefixIgnored  Prefix = 0x4000 // prefix is ignored: either irrelevant or overridden by a later prefix
-	PrefixInvalid  Prefix = 0x2000 // prefix makes entire instruction invalid (bad LOCK)
-
-	// Memory segment overrides.
-	PrefixES Prefix = 0x26 // ES segment override
-	PrefixCS Prefix = 0x2E // CS segment override
-	PrefixSS Prefix = 0x36 // SS segment override
-	PrefixDS Prefix = 0x3E // DS segment override
-	PrefixFS Prefix = 0x64 // FS segment override
-	PrefixGS Prefix = 0x65 // GS segment override
-
-	// Branch prediction.
-	PrefixPN Prefix = 0x12E // predict not taken (conditional branch only)
-	PrefixPT Prefix = 0x13E // predict taken (conditional branch only)
-
-	// Size attributes.
-	PrefixDataSize Prefix = 0x66 // operand size override
-	PrefixData16   Prefix = 0x166
-	PrefixData32   Prefix = 0x266
-	PrefixAddrSize Prefix = 0x67 // address size override
-	PrefixAddr16   Prefix = 0x167
-	PrefixAddr32   Prefix = 0x267
-
-	// One of a kind.
-	PrefixLOCK     Prefix = 0xF0 // lock
-	PrefixREPN     Prefix = 0xF2 // repeat not zero
-	PrefixXACQUIRE Prefix = 0x1F2
-	PrefixBND      Prefix = 0x2F2
-	PrefixREP      Prefix = 0xF3 // repeat
-	PrefixXRELEASE Prefix = 0x1F3
-
-	// The REX prefixes must be in the range [PrefixREX, PrefixREX+0x10).
-	// the other bits are set or not according to the intended use.
-	PrefixREX  Prefix = 0x40 // REX 64-bit extension prefix
-	PrefixREXW Prefix = 0x08 // extension bit W (64-bit instruction width)
-	PrefixREXR Prefix = 0x04 // extension bit R (r field in modrm)
-	PrefixREXX Prefix = 0x02 // extension bit X (index field in sib)
-	PrefixREXB Prefix = 0x01 // extension bit B (r/m field in modrm or base field in sib)
-)
-
-// IsREX reports whether p is a REX prefix byte.
-func (p Prefix) IsREX() bool {
-	return p&0xF0 == PrefixREX
-}
-
-func (p Prefix) String() string {
-	p &^= PrefixImplicit | PrefixIgnored | PrefixInvalid
-	if s := prefixNames[p]; s != "" {
-		return s
-	}
-
-	if p.IsREX() {
-		s := "REX."
-		if p&PrefixREXW != 0 {
-			s += "W"
-		}
-		if p&PrefixREXR != 0 {
-			s += "R"
-		}
-		if p&PrefixREXX != 0 {
-			s += "X"
-		}
-		if p&PrefixREXB != 0 {
-			s += "B"
-		}
-		return s
-	}
-
-	return fmt.Sprintf("Prefix(%#x)", int(p))
-}
-
-// An Op is an x86 opcode.
-type Op uint32
-
-func (op Op) String() string {
-	i := int(op)
-	if i < 0 || i >= len(opNames) || opNames[i] == "" {
-		return fmt.Sprintf("Op(%d)", i)
-	}
-	return opNames[i]
-}
-
-// An Args holds the instruction arguments.
-// If an instruction has fewer than 4 arguments,
-// the final elements in the array are nil.
-type Args [4]Arg
-
-// An Arg is a single instruction argument,
-// one of these types: Reg, Mem, Imm, Rel.
-type Arg interface {
-	String() string
-	isArg()
-}
-
-// Note that the implements of Arg that follow are all sized
-// so that on a 64-bit machine the data can be inlined in
-// the interface value instead of requiring an allocation.
-
-// A Reg is a single register.
-// The zero Reg value has no name but indicates ``no register.''
-type Reg uint8
-
-const (
-	_ Reg = iota
-
-	// 8-bit
-	AL
-	CL
-	DL
-	BL
-	AH
-	CH
-	DH
-	BH
-	SPB
-	BPB
-	SIB
-	DIB
-	R8B
-	R9B
-	R10B
-	R11B
-	R12B
-	R13B
-	R14B
-	R15B
-
-	// 16-bit
-	AX
-	CX
-	DX
-	BX
-	SP
-	BP
-	SI
-	DI
-	R8W
-	R9W
-	R10W
-	R11W
-	R12W
-	R13W
-	R14W
-	R15W
-
-	// 32-bit
-	EAX
-	ECX
-	EDX
-	EBX
-	ESP
-	EBP
-	ESI
-	EDI
-	R8L
-	R9L
-	R10L
-	R11L
-	R12L
-	R13L
-	R14L
-	R15L
-
-	// 64-bit
-	RAX
-	RCX
-	RDX
-	RBX
-	RSP
-	RBP
-	RSI
-	RDI
-	R8
-	R9
-	R10
-	R11
-	R12
-	R13
-	R14
-	R15
-
-	// Instruction pointer.
-	IP  // 16-bit
-	EIP // 32-bit
-	RIP // 64-bit
-
-	// 387 floating point registers.
-	F0
-	F1
-	F2
-	F3
-	F4
-	F5
-	F6
-	F7
-
-	// MMX registers.
-	M0
-	M1
-	M2
-	M3
-	M4
-	M5
-	M6
-	M7
-
-	// XMM registers.
-	X0
-	X1
-	X2
-	X3
-	X4
-	X5
-	X6
-	X7
-	X8
-	X9
-	X10
-	X11
-	X12
-	X13
-	X14
-	X15
-
-	// Segment registers.
-	ES
-	CS
-	SS
-	DS
-	FS
-	GS
-
-	// System registers.
-	GDTR
-	IDTR
-	LDTR
-	MSW
-	TASK
-
-	// Control registers.
-	CR0
-	CR1
-	CR2
-	CR3
-	CR4
-	CR5
-	CR6
-	CR7
-	CR8
-	CR9
-	CR10
-	CR11
-	CR12
-	CR13
-	CR14
-	CR15
-
-	// Debug registers.
-	DR0
-	DR1
-	DR2
-	DR3
-	DR4
-	DR5
-	DR6
-	DR7
-	DR8
-	DR9
-	DR10
-	DR11
-	DR12
-	DR13
-	DR14
-	DR15
-
-	// Task registers.
-	TR0
-	TR1
-	TR2
-	TR3
-	TR4
-	TR5
-	TR6
-	TR7
-)
-
-const regMax = TR7
-
-func (Reg) isArg() {}
-
-func (r Reg) String() string {
-	i := int(r)
-	if i < 0 || i >= len(regNames) || regNames[i] == "" {
-		return fmt.Sprintf("Reg(%d)", i)
-	}
-	return regNames[i]
-}
-
-// A Mem is a memory reference.
-// The general form is Segment:[Base+Scale*Index+Disp].
-type Mem struct {
-	Segment Reg
-	Base    Reg
-	Scale   uint8
-	Index   Reg
-	Disp    int64
-}
-
-func (Mem) isArg() {}
-
-func (m Mem) String() string {
-	var base, plus, scale, index, disp string
-
-	if m.Base != 0 {
-		base = m.Base.String()
-	}
-	if m.Scale != 0 {
-		if m.Base != 0 {
-			plus = "+"
-		}
-		if m.Scale > 1 {
-			scale = fmt.Sprintf("%d*", m.Scale)
-		}
-		index = m.Index.String()
-	}
-	if m.Disp != 0 || m.Base == 0 && m.Scale == 0 {
-		disp = fmt.Sprintf("%+#x", m.Disp)
-	}
-	return "[" + base + plus + scale + index + disp + "]"
-}
-
-// A Rel is an offset relative to the current instruction pointer.
-type Rel int32
-
-func (Rel) isArg() {}
-
-func (r Rel) String() string {
-	return fmt.Sprintf(".%+d", r)
-}
-
-// An Imm is an integer constant.
-type Imm int64
-
-func (Imm) isArg() {}
-
-func (i Imm) String() string {
-	return fmt.Sprintf("%#x", int64(i))
-}
-
-func (i Inst) String() string {
-	var buf bytes.Buffer
-	for _, p := range i.Prefix {
-		if p == 0 {
-			break
-		}
-		if p&PrefixImplicit != 0 {
-			continue
-		}
-		fmt.Fprintf(&buf, "%v ", p)
-	}
-	fmt.Fprintf(&buf, "%v", i.Op)
-	sep := " "
-	for _, v := range i.Args {
-		if v == nil {
-			break
-		}
-		fmt.Fprintf(&buf, "%s%v", sep, v)
-		sep = ", "
-	}
-	return buf.String()
-}
-
-func isReg(a Arg) bool {
-	_, ok := a.(Reg)
-	return ok
-}
-
-func isSegReg(a Arg) bool {
-	r, ok := a.(Reg)
-	return ok && ES <= r && r <= GS
-}
-
-func isMem(a Arg) bool {
-	_, ok := a.(Mem)
-	return ok
-}
-
-func isImm(a Arg) bool {
-	_, ok := a.(Imm)
-	return ok
-}
-
-func regBytes(a Arg) int {
-	r, ok := a.(Reg)
-	if !ok {
-		return 0
-	}
-	if AL <= r && r <= R15B {
-		return 1
-	}
-	if AX <= r && r <= R15W {
-		return 2
-	}
-	if EAX <= r && r <= R15L {
-		return 4
-	}
-	if RAX <= r && r <= R15 {
-		return 8
-	}
-	return 0
-}
-
-func isSegment(p Prefix) bool {
-	switch p {
-	case PrefixCS, PrefixDS, PrefixES, PrefixFS, PrefixGS, PrefixSS:
-		return true
-	}
-	return false
-}
-
-// The Op definitions and string list are in tables.go.
-
-var prefixNames = map[Prefix]string{
-	PrefixCS:       "CS",
-	PrefixDS:       "DS",
-	PrefixES:       "ES",
-	PrefixFS:       "FS",
-	PrefixGS:       "GS",
-	PrefixSS:       "SS",
-	PrefixLOCK:     "LOCK",
-	PrefixREP:      "REP",
-	PrefixREPN:     "REPN",
-	PrefixAddrSize: "ADDRSIZE",
-	PrefixDataSize: "DATASIZE",
-	PrefixAddr16:   "ADDR16",
-	PrefixData16:   "DATA16",
-	PrefixAddr32:   "ADDR32",
-	PrefixData32:   "DATA32",
-	PrefixBND:      "BND",
-	PrefixXACQUIRE: "XACQUIRE",
-	PrefixXRELEASE: "XRELEASE",
-	PrefixREX:      "REX",
-	PrefixPT:       "PT",
-	PrefixPN:       "PN",
-}
-
-var regNames = [...]string{
-	AL:   "AL",
-	CL:   "CL",
-	BL:   "BL",
-	DL:   "DL",
-	AH:   "AH",
-	CH:   "CH",
-	BH:   "BH",
-	DH:   "DH",
-	SPB:  "SPB",
-	BPB:  "BPB",
-	SIB:  "SIB",
-	DIB:  "DIB",
-	R8B:  "R8B",
-	R9B:  "R9B",
-	R10B: "R10B",
-	R11B: "R11B",
-	R12B: "R12B",
-	R13B: "R13B",
-	R14B: "R14B",
-	R15B: "R15B",
-	AX:   "AX",
-	CX:   "CX",
-	BX:   "BX",
-	DX:   "DX",
-	SP:   "SP",
-	BP:   "BP",
-	SI:   "SI",
-	DI:   "DI",
-	R8W:  "R8W",
-	R9W:  "R9W",
-	R10W: "R10W",
-	R11W: "R11W",
-	R12W: "R12W",
-	R13W: "R13W",
-	R14W: "R14W",
-	R15W: "R15W",
-	EAX:  "EAX",
-	ECX:  "ECX",
-	EDX:  "EDX",
-	EBX:  "EBX",
-	ESP:  "ESP",
-	EBP:  "EBP",
-	ESI:  "ESI",
-	EDI:  "EDI",
-	R8L:  "R8L",
-	R9L:  "R9L",
-	R10L: "R10L",
-	R11L: "R11L",
-	R12L: "R12L",
-	R13L: "R13L",
-	R14L: "R14L",
-	R15L: "R15L",
-	RAX:  "RAX",
-	RCX:  "RCX",
-	RDX:  "RDX",
-	RBX:  "RBX",
-	RSP:  "RSP",
-	RBP:  "RBP",
-	RSI:  "RSI",
-	RDI:  "RDI",
-	R8:   "R8",
-	R9:   "R9",
-	R10:  "R10",
-	R11:  "R11",
-	R12:  "R12",
-	R13:  "R13",
-	R14:  "R14",
-	R15:  "R15",
-	IP:   "IP",
-	EIP:  "EIP",
-	RIP:  "RIP",
-	F0:   "F0",
-	F1:   "F1",
-	F2:   "F2",
-	F3:   "F3",
-	F4:   "F4",
-	F5:   "F5",
-	F6:   "F6",
-	F7:   "F7",
-	M0:   "M0",
-	M1:   "M1",
-	M2:   "M2",
-	M3:   "M3",
-	M4:   "M4",
-	M5:   "M5",
-	M6:   "M6",
-	M7:   "M7",
-	X0:   "X0",
-	X1:   "X1",
-	X2:   "X2",
-	X3:   "X3",
-	X4:   "X4",
-	X5:   "X5",
-	X6:   "X6",
-	X7:   "X7",
-	X8:   "X8",
-	X9:   "X9",
-	X10:  "X10",
-	X11:  "X11",
-	X12:  "X12",
-	X13:  "X13",
-	X14:  "X14",
-	X15:  "X15",
-	CS:   "CS",
-	SS:   "SS",
-	DS:   "DS",
-	ES:   "ES",
-	FS:   "FS",
-	GS:   "GS",
-	GDTR: "GDTR",
-	IDTR: "IDTR",
-	LDTR: "LDTR",
-	MSW:  "MSW",
-	TASK: "TASK",
-	CR0:  "CR0",
-	CR1:  "CR1",
-	CR2:  "CR2",
-	CR3:  "CR3",
-	CR4:  "CR4",
-	CR5:  "CR5",
-	CR6:  "CR6",
-	CR7:  "CR7",
-	CR8:  "CR8",
-	CR9:  "CR9",
-	CR10: "CR10",
-	CR11: "CR11",
-	CR12: "CR12",
-	CR13: "CR13",
-	CR14: "CR14",
-	CR15: "CR15",
-	DR0:  "DR0",
-	DR1:  "DR1",
-	DR2:  "DR2",
-	DR3:  "DR3",
-	DR4:  "DR4",
-	DR5:  "DR5",
-	DR6:  "DR6",
-	DR7:  "DR7",
-	DR8:  "DR8",
-	DR9:  "DR9",
-	DR10: "DR10",
-	DR11: "DR11",
-	DR12: "DR12",
-	DR13: "DR13",
-	DR14: "DR14",
-	DR15: "DR15",
-	TR0:  "TR0",
-	TR1:  "TR1",
-	TR2:  "TR2",
-	TR3:  "TR3",
-	TR4:  "TR4",
-	TR5:  "TR5",
-	TR6:  "TR6",
-	TR7:  "TR7",
-}
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/objdump_test.go b/src/cmd/internal/rsc.io/x86/x86asm/objdump_test.go
deleted file mode 100644
index 6f72605..0000000
--- a/src/cmd/internal/rsc.io/x86/x86asm/objdump_test.go
+++ /dev/null
@@ -1,383 +0,0 @@
-// 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 x86asm
-
-import (
-	"bytes"
-	"strings"
-	"testing"
-)
-
-func TestObjdump32Manual(t *testing.T)   { testObjdump32(t, hexCases(t, objdumpManualTests)) }
-func TestObjdump32Testdata(t *testing.T) { testObjdump32(t, concat(basicPrefixes, testdataCases(t))) }
-func TestObjdump32ModRM(t *testing.T)    { testObjdump32(t, concat(basicPrefixes, enumModRM)) }
-func TestObjdump32OneByte(t *testing.T)  { testBasic(t, testObjdump32) }
-func TestObjdump320F(t *testing.T)       { testBasic(t, testObjdump32, 0x0F) }
-func TestObjdump320F38(t *testing.T)     { testBasic(t, testObjdump32, 0x0F, 0x38) }
-func TestObjdump320F3A(t *testing.T)     { testBasic(t, testObjdump32, 0x0F, 0x3A) }
-func TestObjdump32Prefix(t *testing.T)   { testPrefix(t, testObjdump32) }
-
-func TestObjdump64Manual(t *testing.T)   { testObjdump64(t, hexCases(t, objdumpManualTests)) }
-func TestObjdump64Testdata(t *testing.T) { testObjdump64(t, concat(basicPrefixes, testdataCases(t))) }
-func TestObjdump64ModRM(t *testing.T)    { testObjdump64(t, concat(basicPrefixes, enumModRM)) }
-func TestObjdump64OneByte(t *testing.T)  { testBasic(t, testObjdump64) }
-func TestObjdump640F(t *testing.T)       { testBasic(t, testObjdump64, 0x0F) }
-func TestObjdump640F38(t *testing.T)     { testBasic(t, testObjdump64, 0x0F, 0x38) }
-func TestObjdump640F3A(t *testing.T)     { testBasic(t, testObjdump64, 0x0F, 0x3A) }
-func TestObjdump64Prefix(t *testing.T)   { testPrefix(t, testObjdump64) }
-
-func TestObjdump64REXTestdata(t *testing.T) {
-	testObjdump64(t, filter(concat3(basicPrefixes, rexPrefixes, testdataCases(t)), isValidREX))
-}
-func TestObjdump64REXModRM(t *testing.T) {
-	testObjdump64(t, concat3(basicPrefixes, rexPrefixes, enumModRM))
-}
-func TestObjdump64REXOneByte(t *testing.T) { testBasicREX(t, testObjdump64) }
-func TestObjdump64REX0F(t *testing.T)      { testBasicREX(t, testObjdump64, 0x0F) }
-func TestObjdump64REX0F38(t *testing.T)    { testBasicREX(t, testObjdump64, 0x0F, 0x38) }
-func TestObjdump64REX0F3A(t *testing.T)    { testBasicREX(t, testObjdump64, 0x0F, 0x3A) }
-func TestObjdump64REXPrefix(t *testing.T)  { testPrefixREX(t, testObjdump64) }
-
-// objdumpManualTests holds test cases that will be run by TestObjdumpManual.
-// If you are debugging a few cases that turned up in a longer run, it can be useful
-// to list them here and then use -run=ObjdumpManual, particularly with tracing enabled.
-var objdumpManualTests = `
-F390
-`
-
-// allowedMismatchObjdump reports whether the mismatch between text and dec
-// should be allowed by the test.
-func allowedMismatchObjdump(text string, size int, inst *Inst, dec ExtInst) bool {
-	if size == 15 && dec.nenc == 15 && contains(text, "truncated") && contains(dec.text, "(bad)") {
-		return true
-	}
-
-	if i := strings.LastIndex(dec.text, " "); isPrefix(dec.text[i+1:]) && size == 1 && isPrefix(text) {
-		return true
-	}
-
-	if size == dec.nenc && contains(dec.text, "movupd") && contains(dec.text, "data32") {
-		s := strings.Replace(dec.text, "data32 ", "", -1)
-		if text == s {
-			return true
-		}
-	}
-
-	// Simplify our invalid instruction text.
-	if text == "error: unrecognized instruction" {
-		text = "BAD"
-	}
-
-	// Invalid instructions for which libopcodes prints %? register.
-	// FF E8 11 22 33 44:
-	// Invalid instructions for which libopcodes prints "internal disassembler error".
-	// Invalid instructions for which libopcodes prints 8087 only (e.g., DB E0)
-	// or prints 287 only (e.g., DB E4).
-	if contains(dec.text, "%?", "<internal disassembler error>", "(8087 only)", "(287 only)") {
-		dec.text = "(bad)"
-	}
-
-	// 0F 19 11, 0F 1C 11, 0F 1D 11, 0F 1E 11, 0F 1F 11: libopcodes says nop,
-	// but the Intel manuals say that the only NOP there is 0F 1F /0.
-	// Perhaps libopcodes is reporting an older encoding.
-	i := bytes.IndexByte(dec.enc[:], 0x0F)
-	if contains(dec.text, "nop") && i >= 0 && i+2 < len(dec.enc) && dec.enc[i+1]&^7 == 0x18 && (dec.enc[i+1] != 0x1F || (dec.enc[i+2]>>3)&7 != 0) {
-		dec.text = "(bad)"
-	}
-
-	// Any invalid instruction.
-	if text == "BAD" && contains(dec.text, "(bad)") {
-		return true
-	}
-
-	// Instructions libopcodes knows but we do not (e.g., 0F 19 11).
-	if (text == "BAD" || size == 1 && isPrefix(text)) && hasPrefix(dec.text, unsupported...) {
-		return true
-	}
-
-	// Instructions we know but libopcodes does not (e.g., 0F D0 11).
-	if (contains(dec.text, "(bad)") || dec.nenc == 1 && isPrefix(dec.text)) && hasPrefix(text, libopcodesUnsupported...) {
-		return true
-	}
-
-	// Libopcodes rejects F2 90 as NOP. Not sure why.
-	if (contains(dec.text, "(bad)") || dec.nenc == 1 && isPrefix(dec.text)) && inst.Opcode>>24 == 0x90 && countPrefix(inst, 0xF2) > 0 {
-		return true
-	}
-
-	// 0F 20 11, 0F 21 11, 0F 22 11, 0F 23 11, 0F 24 11:
-	// Moves into and out of some control registers seem to be unsupported by libopcodes.
-	// TODO(rsc): Are they invalid somehow?
-	if (contains(dec.text, "(bad)") || dec.nenc == 1 && isPrefix(dec.text)) && contains(text, "%cr", "%db", "%tr") {
-		return true
-	}
-
-	if contains(dec.text, "fwait") && dec.nenc == 1 && dec.enc[0] != 0x9B {
-		return true
-	}
-
-	// 9B D9 11: libopcodes reports FSTSW instead of FWAIT + FNSTSW.
-	// This is correct in that FSTSW is a pseudo-op for the pair, but it really
-	// is a pair of instructions: execution can stop between them.
-	// Our decoder chooses to separate them.
-	if (text == "fwait" || strings.HasSuffix(text, " fwait")) && dec.nenc >= len(strings.Fields(text)) && dec.enc[len(strings.Fields(text))-1] == 0x9B {
-		return true
-	}
-
-	// 0F 18 77 11:
-	// Invalid instructions for which libopcodes prints "nop/reserved".
-	// Perhaps libopcodes is reporting an older encoding.
-	if text == "BAD" && contains(dec.text, "nop/reserved") {
-		return true
-	}
-
-	// 0F C7 B0 11 22 33 44: libopcodes says vmptrld 0x44332211(%eax); we say rdrand %eax.
-	// TODO(rsc): Fix, since we are probably wrong, but we don't have vmptrld in the manual.
-	if contains(text, "rdrand") && contains(dec.text, "vmptrld", "vmxon", "vmclear") {
-		return true
-	}
-
-	// DD C8: libopcodes says FNOP but the Intel manual is clear FNOP is only D9 D0.
-	// Perhaps libopcodes is reporting an older encoding.
-	if text == "BAD" && contains(dec.text, "fnop") && (dec.enc[0] != 0xD9 || dec.enc[1] != 0xD0) {
-		return true
-	}
-
-	// 66 90: libopcodes says xchg %ax,%ax; we say 'data16 nop'.
-	// The 16-bit swap will preserve the high bits of the register,
-	// so they are the same.
-	if contains(text, "nop") && contains(dec.text, "xchg %ax,%ax") {
-		return true
-	}
-
-	// If there are multiple prefixes, allow libopcodes to use an alternate name.
-	if size == 1 && dec.nenc == 1 && prefixByte[text] > 0 && prefixByte[text] == prefixByte[dec.text] {
-		return true
-	}
-
-	// 26 9B: libopcodes reports "fwait"/1, ignoring segment prefix.
-	// https://sourceware.org/bugzilla/show_bug.cgi?id=16891
-	// F0 82: Decode="lock"/1 but libopcodes="lock (bad)"/2.
-	if size == 1 && dec.nenc >= 1 && prefixByte[text] == dec.enc[0] && contains(dec.text, "(bad)", "fwait", "fnop") {
-		return true
-	}
-
-	// libopcodes interprets 660f801122 as taking a rel16 but
-	// truncating the address at 16 bits. Not sure what is correct.
-	if contains(text, ".+0x2211", ".+0x11") && contains(dec.text, " .-") {
-		return true
-	}
-
-	// 66 F3 0F D6 C5, 66 F2 0F D6 C0: libopcodes reports use of XMM register instead of MMX register,
-	// but only when the instruction has a 66 prefix. Maybe they know something we don't.
-	if countPrefix(inst, 0x66) > 0 && contains(dec.text, "movdq2q", "movq2dq") && !contains(dec.text, "%mm") {
-		return true
-	}
-
-	// 0F 01 F8, 0F 05, 0F 07: these are 64-bit instructions but libopcodes accepts them.
-	if (text == "BAD" || size == 1 && isPrefix(text)) && contains(dec.text, "swapgs", "syscall", "sysret", "rdfsbase", "rdgsbase", "wrfsbase", "wrgsbase") {
-		return true
-	}
-
-	return false
-}
-
-// Instructions known to libopcodes (or xed) but not to us.
-// Most of these come from supplementary manuals of one form or another.
-var unsupported = strings.Fields(`
-	bndc
-	bndl
-	bndm
-	bnds
-	clac
-	clgi
-	femms
-	fldln
-	fldz
-	getsec
-	invlpga
-	kmov
-	montmul
-	pavg
-	pf2i
-	pfacc
-	pfadd
-	pfcmp
-	pfmax
-	pfmin
-	pfmul
-	pfna
-	pfpnac
-	pfrc
-	pfrs
-	pfsub
-	phadd
-	phsub
-	pi2f
-	pmulhr
-	prefetch
-	pswap
-	ptest
-	rdseed
-	sha1
-	sha256
-	skinit
-	stac
-	stgi
-	vadd
-	vand
-	vcmp
-	vcomis
-	vcvt
-	vcvt
-	vdiv
-	vhadd
-	vhsub
-	vld
-	vmax
-	vmcall
-	vmfunc
-	vmin
-	vmlaunch
-	vmload
-	vmmcall
-	vmov
-	vmov
-	vmov
-	vmptrld
-	vmptrst
-	vmread
-	vmresume
-	vmrun
-	vmsave
-	vmul
-	vmwrite
-	vmxoff
-	vor
-	vpack
-	vpadd
-	vpand
-	vpavg
-	vpcmp
-	vpcmp
-	vpins
-	vpmadd
-	vpmax
-	vpmin
-	vpmul
-	vpmul
-	vpor
-	vpsad
-	vpshuf
-	vpsll
-	vpsra
-	vpsrad
-	vpsrl
-	vpsub
-	vpunp
-	vpxor
-	vrcp
-	vrsqrt
-	vshuf
-	vsqrt
-	vsub
-	vucomis
-	vunp
-	vxor
-	vzero
-	xcrypt
-	xsha1
-	xsha256
-	xstore-rng
-	insertq
-	extrq
-	vmclear
-	invvpid
-	adox
-	vmxon
-	invept
-	adcx
-	vmclear
-	prefetchwt1
-	enclu
-	encls
-	salc
-	fstpnce
-	fdisi8087_nop
-	fsetpm287_nop
-	feni8087_nop
-	syscall
-	sysret
-`)
-
-// Instructions known to us but not to libopcodes (at least in binutils 2.24).
-var libopcodesUnsupported = strings.Fields(`
-	addsubps
-	aes
-	blend
-	cvttpd2dq
-	dpp
-	extract
-	haddps
-	hsubps
-	insert
-	invpcid
-	lddqu
-	movmsk
-	movnt
-	movq2dq
-	mps
-	pack
-	pblend
-	pclmul
-	pcmp
-	pext
-	phmin
-	pins
-	pmax
-	pmin
-	pmov
-	pmovmsk
-	pmul
-	popcnt
-	pslld
-	psllq
-	psllw
-	psrad
-	psraw
-	psrl
-	ptest
-	punpck
-	round
-	xrstor
-	xsavec
-	xsaves
-	comis
-	ucomis
-	movhps
-	movntps
-	rsqrt
-	rcpp
-	puncpck
-	bsf
-	movq2dq
-	cvttpd2dq
-	movq
-	hsubpd
-	movdqa
-	movhpd
-	addsubpd
-	movd
-	haddpd
-	cvtps2dq
-	bsr
-	cvtdq2ps
-	rdrand
-	maskmov
-	movq2dq
-	movlhps
-	movbe
-	movlpd
-`)
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/objdumpext_test.go b/src/cmd/internal/rsc.io/x86/x86asm/objdumpext_test.go
deleted file mode 100644
index 37a5513..0000000
--- a/src/cmd/internal/rsc.io/x86/x86asm/objdumpext_test.go
+++ /dev/null
@@ -1,314 +0,0 @@
-// 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 x86asm
-
-import (
-	"bytes"
-	"debug/elf"
-	"encoding/binary"
-	"fmt"
-	"io"
-	"log"
-	"os"
-	"strconv"
-	"strings"
-	"testing"
-)
-
-// Apologies for the proprietary path, but we need objdump 2.24 + some committed patches that will land in 2.25.
-const objdumpPath = "/Users/rsc/bin/objdump2"
-
-func testObjdump32(t *testing.T, generate func(func([]byte))) {
-	testObjdumpArch(t, generate, 32)
-}
-
-func testObjdump64(t *testing.T, generate func(func([]byte))) {
-	testObjdumpArch(t, generate, 64)
-}
-
-func testObjdumpArch(t *testing.T, generate func(func([]byte)), arch int) {
-	if testing.Short() {
-		t.Skip("skipping objdump test in short mode")
-	}
-
-	if _, err := os.Stat(objdumpPath); err != nil {
-		t.Fatal(err)
-	}
-
-	testExtDis(t, "gnu", arch, objdump, generate, allowedMismatchObjdump)
-}
-
-func objdump(ext *ExtDis) error {
-	// File already written with instructions; add ELF header.
-	if ext.Arch == 32 {
-		if err := writeELF32(ext.File, ext.Size); err != nil {
-			return err
-		}
-	} else {
-		if err := writeELF64(ext.File, ext.Size); err != nil {
-			return err
-		}
-	}
-
-	b, err := ext.Run(objdumpPath, "-d", "-z", ext.File.Name())
-	if err != nil {
-		return err
-	}
-
-	var (
-		nmatch  int
-		reading bool
-		next    uint32 = start
-		addr    uint32
-		encbuf  [32]byte
-		enc     []byte
-		text    string
-	)
-	flush := func() {
-		if addr == next {
-			switch text {
-			case "repz":
-				text = "rep"
-			case "repnz":
-				text = "repn"
-			default:
-				text = strings.Replace(text, "repz ", "rep ", -1)
-				text = strings.Replace(text, "repnz ", "repn ", -1)
-			}
-			if m := pcrelw.FindStringSubmatch(text); m != nil {
-				targ, _ := strconv.ParseUint(m[2], 16, 64)
-				text = fmt.Sprintf("%s .%+#x", m[1], int16(uint32(targ)-uint32(uint16(addr))-uint32(len(enc))))
-			}
-			if m := pcrel.FindStringSubmatch(text); m != nil {
-				targ, _ := strconv.ParseUint(m[2], 16, 64)
-				text = fmt.Sprintf("%s .%+#x", m[1], int32(uint32(targ)-addr-uint32(len(enc))))
-			}
-			text = strings.Replace(text, "0x0(", "(", -1)
-			text = strings.Replace(text, "%st(0)", "%st", -1)
-
-			ext.Dec <- ExtInst{addr, encbuf, len(enc), text}
-			encbuf = [32]byte{}
-			enc = nil
-			next += 32
-		}
-	}
-	var textangle = []byte("<.text>:")
-	for {
-		line, err := b.ReadSlice('\n')
-		if err != nil {
-			if err == io.EOF {
-				break
-			}
-			return fmt.Errorf("reading objdump output: %v", err)
-		}
-		if bytes.Contains(line, textangle) {
-			reading = true
-			continue
-		}
-		if !reading {
-			continue
-		}
-		if debug {
-			os.Stdout.Write(line)
-		}
-		if enc1 := parseContinuation(line, encbuf[:len(enc)]); enc1 != nil {
-			enc = enc1
-			continue
-		}
-		flush()
-		nmatch++
-		addr, enc, text = parseLine(line, encbuf[:0])
-		if addr > next {
-			return fmt.Errorf("address out of sync expected <= %#x at %q in:\n%s", next, line, line)
-		}
-	}
-	flush()
-	if next != start+uint32(ext.Size) {
-		return fmt.Errorf("not enough results found [%d %d]", next, start+ext.Size)
-	}
-	if err := ext.Wait(); err != nil {
-		return fmt.Errorf("exec: %v", err)
-	}
-
-	return nil
-}
-
-func parseLine(line []byte, encstart []byte) (addr uint32, enc []byte, text string) {
-	oline := line
-	i := index(line, ":\t")
-	if i < 0 {
-		log.Fatalf("cannot parse disassembly: %q", oline)
-	}
-	x, err := strconv.ParseUint(string(trimSpace(line[:i])), 16, 32)
-	if err != nil {
-		log.Fatalf("cannot parse disassembly: %q", oline)
-	}
-	addr = uint32(x)
-	line = line[i+2:]
-	i = bytes.IndexByte(line, '\t')
-	if i < 0 {
-		log.Fatalf("cannot parse disassembly: %q", oline)
-	}
-	enc, ok := parseHex(line[:i], encstart)
-	if !ok {
-		log.Fatalf("cannot parse disassembly: %q", oline)
-	}
-	line = trimSpace(line[i:])
-	if i := bytes.IndexByte(line, '#'); i >= 0 {
-		line = trimSpace(line[:i])
-	}
-	text = string(fixSpace(line))
-	return
-}
-
-func parseContinuation(line []byte, enc []byte) []byte {
-	i := index(line, ":\t")
-	if i < 0 {
-		return nil
-	}
-	line = line[i+1:]
-	enc, _ = parseHex(line, enc)
-	return enc
-}
-
-// writeELF32 writes an ELF32 header to the file,
-// describing a text segment that starts at start
-// and extends for size bytes.
-func writeELF32(f *os.File, size int) error {
-	f.Seek(0, 0)
-	var hdr elf.Header32
-	var prog elf.Prog32
-	var sect elf.Section32
-	var buf bytes.Buffer
-	binary.Write(&buf, binary.LittleEndian, &hdr)
-	off1 := buf.Len()
-	binary.Write(&buf, binary.LittleEndian, &prog)
-	off2 := buf.Len()
-	binary.Write(&buf, binary.LittleEndian, &sect)
-	off3 := buf.Len()
-	buf.Reset()
-	data := byte(elf.ELFDATA2LSB)
-	hdr = elf.Header32{
-		Ident:     [16]byte{0x7F, 'E', 'L', 'F', 1, data, 1},
-		Type:      2,
-		Machine:   uint16(elf.EM_386),
-		Version:   1,
-		Entry:     start,
-		Phoff:     uint32(off1),
-		Shoff:     uint32(off2),
-		Flags:     0x05000002,
-		Ehsize:    uint16(off1),
-		Phentsize: uint16(off2 - off1),
-		Phnum:     1,
-		Shentsize: uint16(off3 - off2),
-		Shnum:     3,
-		Shstrndx:  2,
-	}
-	binary.Write(&buf, binary.LittleEndian, &hdr)
-	prog = elf.Prog32{
-		Type:   1,
-		Off:    start,
-		Vaddr:  start,
-		Paddr:  start,
-		Filesz: uint32(size),
-		Memsz:  uint32(size),
-		Flags:  5,
-		Align:  start,
-	}
-	binary.Write(&buf, binary.LittleEndian, &prog)
-	binary.Write(&buf, binary.LittleEndian, &sect) // NULL section
-	sect = elf.Section32{
-		Name:      1,
-		Type:      uint32(elf.SHT_PROGBITS),
-		Addr:      start,
-		Off:       start,
-		Size:      uint32(size),
-		Flags:     uint32(elf.SHF_ALLOC | elf.SHF_EXECINSTR),
-		Addralign: 4,
-	}
-	binary.Write(&buf, binary.LittleEndian, &sect) // .text
-	sect = elf.Section32{
-		Name:      uint32(len("\x00.text\x00")),
-		Type:      uint32(elf.SHT_STRTAB),
-		Addr:      0,
-		Off:       uint32(off2 + (off3-off2)*3),
-		Size:      uint32(len("\x00.text\x00.shstrtab\x00")),
-		Addralign: 1,
-	}
-	binary.Write(&buf, binary.LittleEndian, &sect)
-	buf.WriteString("\x00.text\x00.shstrtab\x00")
-	f.Write(buf.Bytes())
-	return nil
-}
-
-// writeELF64 writes an ELF64 header to the file,
-// describing a text segment that starts at start
-// and extends for size bytes.
-func writeELF64(f *os.File, size int) error {
-	f.Seek(0, 0)
-	var hdr elf.Header64
-	var prog elf.Prog64
-	var sect elf.Section64
-	var buf bytes.Buffer
-	binary.Write(&buf, binary.LittleEndian, &hdr)
-	off1 := buf.Len()
-	binary.Write(&buf, binary.LittleEndian, &prog)
-	off2 := buf.Len()
-	binary.Write(&buf, binary.LittleEndian, &sect)
-	off3 := buf.Len()
-	buf.Reset()
-	data := byte(elf.ELFDATA2LSB)
-	hdr = elf.Header64{
-		Ident:     [16]byte{0x7F, 'E', 'L', 'F', 2, data, 1},
-		Type:      2,
-		Machine:   uint16(elf.EM_X86_64),
-		Version:   1,
-		Entry:     start,
-		Phoff:     uint64(off1),
-		Shoff:     uint64(off2),
-		Flags:     0x05000002,
-		Ehsize:    uint16(off1),
-		Phentsize: uint16(off2 - off1),
-		Phnum:     1,
-		Shentsize: uint16(off3 - off2),
-		Shnum:     3,
-		Shstrndx:  2,
-	}
-	binary.Write(&buf, binary.LittleEndian, &hdr)
-	prog = elf.Prog64{
-		Type:   1,
-		Off:    start,
-		Vaddr:  start,
-		Paddr:  start,
-		Filesz: uint64(size),
-		Memsz:  uint64(size),
-		Flags:  5,
-		Align:  start,
-	}
-	binary.Write(&buf, binary.LittleEndian, &prog)
-	binary.Write(&buf, binary.LittleEndian, &sect) // NULL section
-	sect = elf.Section64{
-		Name:      1,
-		Type:      uint32(elf.SHT_PROGBITS),
-		Addr:      start,
-		Off:       start,
-		Size:      uint64(size),
-		Flags:     uint64(elf.SHF_ALLOC | elf.SHF_EXECINSTR),
-		Addralign: 4,
-	}
-	binary.Write(&buf, binary.LittleEndian, &sect) // .text
-	sect = elf.Section64{
-		Name:      uint32(len("\x00.text\x00")),
-		Type:      uint32(elf.SHT_STRTAB),
-		Addr:      0,
-		Off:       uint64(off2 + (off3-off2)*3),
-		Size:      uint64(len("\x00.text\x00.shstrtab\x00")),
-		Addralign: 1,
-	}
-	binary.Write(&buf, binary.LittleEndian, &sect)
-	buf.WriteString("\x00.text\x00.shstrtab\x00")
-	f.Write(buf.Bytes())
-	return nil
-}
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/plan9ext_test.go b/src/cmd/internal/rsc.io/x86/x86asm/plan9ext_test.go
deleted file mode 100644
index 21f5bfd..0000000
--- a/src/cmd/internal/rsc.io/x86/x86asm/plan9ext_test.go
+++ /dev/null
@@ -1,120 +0,0 @@
-// 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 x86asm
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"log"
-	"os"
-	"strconv"
-	"testing"
-)
-
-const plan9Path = "testdata/libmach8db"
-
-func testPlan9Arch(t *testing.T, arch int, generate func(func([]byte))) {
-	if testing.Short() {
-		t.Skip("skipping libmach test in short mode")
-	}
-
-	if _, err := os.Stat(plan9Path); err != nil {
-		t.Fatal(err)
-	}
-
-	testExtDis(t, "plan9", arch, plan9, generate, allowedMismatchPlan9)
-}
-
-func testPlan932(t *testing.T, generate func(func([]byte))) {
-	testPlan9Arch(t, 32, generate)
-}
-
-func testPlan964(t *testing.T, generate func(func([]byte))) {
-	testPlan9Arch(t, 64, generate)
-}
-
-func plan9(ext *ExtDis) error {
-	flag := "-8"
-	if ext.Arch == 64 {
-		flag = "-6"
-	}
-	b, err := ext.Run(plan9Path, flag, ext.File.Name())
-	if err != nil {
-		return err
-	}
-
-	nmatch := 0
-	next := uint32(start)
-	var (
-		addr   uint32
-		encbuf [32]byte
-		enc    []byte
-		text   string
-	)
-
-	for {
-		line, err := b.ReadSlice('\n')
-		if err != nil {
-			if err == io.EOF {
-				break
-			}
-			return fmt.Errorf("reading libmach8db output: %v", err)
-		}
-		if debug {
-			os.Stdout.Write(line)
-		}
-		nmatch++
-		addr, enc, text = parseLinePlan9(line, encbuf[:0])
-		if addr > next {
-			return fmt.Errorf("address out of sync expected <= %#x at %q in:\n%s", next, line, line)
-		}
-		if addr < next {
-			continue
-		}
-		if m := pcrelw.FindStringSubmatch(text); m != nil {
-			targ, _ := strconv.ParseUint(m[2], 16, 64)
-			text = fmt.Sprintf("%s .%+#x", m[1], int16(uint32(targ)-uint32(uint16(addr))-uint32(len(enc))))
-		}
-		if m := pcrel.FindStringSubmatch(text); m != nil {
-			targ, _ := strconv.ParseUint(m[2], 16, 64)
-			text = fmt.Sprintf("%s .%+#x", m[1], int32(uint32(targ)-addr-uint32(len(enc))))
-		}
-		ext.Dec <- ExtInst{addr, encbuf, len(enc), text}
-		encbuf = [32]byte{}
-		enc = nil
-		next += 32
-	}
-	if next != start+uint32(ext.Size) {
-		return fmt.Errorf("not enough results found [%d %d]", next, start+ext.Size)
-	}
-	if err := ext.Wait(); err != nil {
-		return fmt.Errorf("exec: %v", err)
-	}
-
-	return nil
-}
-
-func parseLinePlan9(line []byte, encstart []byte) (addr uint32, enc []byte, text string) {
-	i := bytes.IndexByte(line, ' ')
-	if i < 0 || line[0] != '0' || line[1] != 'x' {
-		log.Fatalf("cannot parse disassembly: %q", line)
-	}
-	j := bytes.IndexByte(line[i+1:], ' ')
-	if j < 0 {
-		log.Fatalf("cannot parse disassembly: %q", line)
-	}
-	j += i + 1
-	x, err := strconv.ParseUint(string(trimSpace(line[2:i])), 16, 32)
-	if err != nil {
-		log.Fatalf("cannot parse disassembly: %q", line)
-	}
-	addr = uint32(x)
-	enc, ok := parseHex(line[i+1:j], encstart)
-	if !ok {
-		log.Fatalf("cannot parse disassembly: %q", line)
-	}
-	return addr, enc, string(fixSpace(line[j+1:]))
-}
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/plan9x.go b/src/cmd/internal/rsc.io/x86/x86asm/plan9x.go
deleted file mode 100644
index 5a0bd87..0000000
--- a/src/cmd/internal/rsc.io/x86/x86asm/plan9x.go
+++ /dev/null
@@ -1,346 +0,0 @@
-// 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 x86asm
-
-import (
-	"fmt"
-	"strings"
-)
-
-// Plan9Syntax returns the Go assembler syntax for the instruction.
-// The syntax was originally defined by Plan 9.
-// The pc is the program counter of the instruction, used for expanding
-// PC-relative addresses into absolute ones.
-// The symname function queries the symbol table for the program
-// being disassembled. Given a target address it returns the name and base
-// address of the symbol containing the target, if any; otherwise it returns "", 0.
-func Plan9Syntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) string {
-	if symname == nil {
-		symname = func(uint64) (string, uint64) { return "", 0 }
-	}
-	var args []string
-	for i := len(inst.Args) - 1; i >= 0; i-- {
-		a := inst.Args[i]
-		if a == nil {
-			continue
-		}
-		args = append(args, plan9Arg(&inst, pc, symname, a))
-	}
-
-	var last Prefix
-	for _, p := range inst.Prefix {
-		if p == 0 || p.IsREX() {
-			break
-		}
-		last = p
-	}
-
-	prefix := ""
-	switch last & 0xFF {
-	case 0, 0x66, 0x67:
-		// ignore
-	case PrefixREPN:
-		prefix += "REPNE "
-	default:
-		prefix += last.String() + " "
-	}
-
-	op := inst.Op.String()
-	if plan9Suffix[inst.Op] {
-		switch inst.DataSize {
-		case 8:
-			op += "B"
-		case 16:
-			op += "W"
-		case 32:
-			op += "L"
-		case 64:
-			op += "Q"
-		}
-	}
-
-	if args != nil {
-		op += " " + strings.Join(args, ", ")
-	}
-
-	return prefix + op
-}
-
-func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string {
-	switch a := arg.(type) {
-	case Reg:
-		return plan9Reg[a]
-	case Rel:
-		if pc == 0 {
-			break
-		}
-		// If the absolute address is the start of a symbol, use the name.
-		// Otherwise use the raw address, so that things like relative
-		// jumps show up as JMP 0x123 instead of JMP f+10(SB).
-		// It is usually easier to search for 0x123 than to do the mental
-		// arithmetic to find f+10.
-		addr := pc + uint64(inst.Len) + uint64(a)
-		if s, base := symname(addr); s != "" && addr == base {
-			return fmt.Sprintf("%s(SB)", s)
-		}
-		return fmt.Sprintf("%#x", addr)
-
-	case Imm:
-		if s, base := symname(uint64(a)); s != "" {
-			suffix := ""
-			if uint64(a) != base {
-				suffix = fmt.Sprintf("%+d", uint64(a)-base)
-			}
-			return fmt.Sprintf("$%s%s(SB)", s, suffix)
-		}
-		if inst.Mode == 32 {
-			return fmt.Sprintf("$%#x", uint32(a))
-		}
-		if Imm(int32(a)) == a {
-			return fmt.Sprintf("$%#x", int64(a))
-		}
-		return fmt.Sprintf("$%#x", uint64(a))
-	case Mem:
-		if a.Segment == 0 && a.Disp != 0 && a.Base == 0 && (a.Index == 0 || a.Scale == 0) {
-			if s, base := symname(uint64(a.Disp)); s != "" {
-				suffix := ""
-				if uint64(a.Disp) != base {
-					suffix = fmt.Sprintf("%+d", uint64(a.Disp)-base)
-				}
-				return fmt.Sprintf("%s%s(SB)", s, suffix)
-			}
-		}
-		s := ""
-		if a.Segment != 0 {
-			s += fmt.Sprintf("%s:", plan9Reg[a.Segment])
-		}
-		if a.Disp != 0 {
-			s += fmt.Sprintf("%#x", a.Disp)
-		} else {
-			s += "0"
-		}
-		if a.Base != 0 {
-			s += fmt.Sprintf("(%s)", plan9Reg[a.Base])
-		}
-		if a.Index != 0 && a.Scale != 0 {
-			s += fmt.Sprintf("(%s*%d)", plan9Reg[a.Index], a.Scale)
-		}
-		return s
-	}
-	return arg.String()
-}
-
-var plan9Suffix = [maxOp + 1]bool{
-	ADC:       true,
-	ADD:       true,
-	AND:       true,
-	BSF:       true,
-	BSR:       true,
-	BT:        true,
-	BTC:       true,
-	BTR:       true,
-	BTS:       true,
-	CMP:       true,
-	CMPXCHG:   true,
-	CVTSI2SD:  true,
-	CVTSI2SS:  true,
-	CVTSD2SI:  true,
-	CVTSS2SI:  true,
-	CVTTSD2SI: true,
-	CVTTSS2SI: true,
-	DEC:       true,
-	DIV:       true,
-	FLDENV:    true,
-	FRSTOR:    true,
-	IDIV:      true,
-	IMUL:      true,
-	IN:        true,
-	INC:       true,
-	LEA:       true,
-	MOV:       true,
-	MOVNTI:    true,
-	MUL:       true,
-	NEG:       true,
-	NOP:       true,
-	NOT:       true,
-	OR:        true,
-	OUT:       true,
-	POP:       true,
-	POPA:      true,
-	PUSH:      true,
-	PUSHA:     true,
-	RCL:       true,
-	RCR:       true,
-	ROL:       true,
-	ROR:       true,
-	SAR:       true,
-	SBB:       true,
-	SHL:       true,
-	SHLD:      true,
-	SHR:       true,
-	SHRD:      true,
-	SUB:       true,
-	TEST:      true,
-	XADD:      true,
-	XCHG:      true,
-	XOR:       true,
-}
-
-var plan9Reg = [...]string{
-	AL:   "AL",
-	CL:   "CL",
-	BL:   "BL",
-	DL:   "DL",
-	AH:   "AH",
-	CH:   "CH",
-	BH:   "BH",
-	DH:   "DH",
-	SPB:  "SP",
-	BPB:  "BP",
-	SIB:  "SI",
-	DIB:  "DI",
-	R8B:  "R8",
-	R9B:  "R9",
-	R10B: "R10",
-	R11B: "R11",
-	R12B: "R12",
-	R13B: "R13",
-	R14B: "R14",
-	R15B: "R15",
-	AX:   "AX",
-	CX:   "CX",
-	BX:   "BX",
-	DX:   "DX",
-	SP:   "SP",
-	BP:   "BP",
-	SI:   "SI",
-	DI:   "DI",
-	R8W:  "R8",
-	R9W:  "R9",
-	R10W: "R10",
-	R11W: "R11",
-	R12W: "R12",
-	R13W: "R13",
-	R14W: "R14",
-	R15W: "R15",
-	EAX:  "AX",
-	ECX:  "CX",
-	EDX:  "DX",
-	EBX:  "BX",
-	ESP:  "SP",
-	EBP:  "BP",
-	ESI:  "SI",
-	EDI:  "DI",
-	R8L:  "R8",
-	R9L:  "R9",
-	R10L: "R10",
-	R11L: "R11",
-	R12L: "R12",
-	R13L: "R13",
-	R14L: "R14",
-	R15L: "R15",
-	RAX:  "AX",
-	RCX:  "CX",
-	RDX:  "DX",
-	RBX:  "BX",
-	RSP:  "SP",
-	RBP:  "BP",
-	RSI:  "SI",
-	RDI:  "DI",
-	R8:   "R8",
-	R9:   "R9",
-	R10:  "R10",
-	R11:  "R11",
-	R12:  "R12",
-	R13:  "R13",
-	R14:  "R14",
-	R15:  "R15",
-	IP:   "IP",
-	EIP:  "IP",
-	RIP:  "IP",
-	F0:   "F0",
-	F1:   "F1",
-	F2:   "F2",
-	F3:   "F3",
-	F4:   "F4",
-	F5:   "F5",
-	F6:   "F6",
-	F7:   "F7",
-	M0:   "M0",
-	M1:   "M1",
-	M2:   "M2",
-	M3:   "M3",
-	M4:   "M4",
-	M5:   "M5",
-	M6:   "M6",
-	M7:   "M7",
-	X0:   "X0",
-	X1:   "X1",
-	X2:   "X2",
-	X3:   "X3",
-	X4:   "X4",
-	X5:   "X5",
-	X6:   "X6",
-	X7:   "X7",
-	X8:   "X8",
-	X9:   "X9",
-	X10:  "X10",
-	X11:  "X11",
-	X12:  "X12",
-	X13:  "X13",
-	X14:  "X14",
-	X15:  "X15",
-	CS:   "CS",
-	SS:   "SS",
-	DS:   "DS",
-	ES:   "ES",
-	FS:   "FS",
-	GS:   "GS",
-	GDTR: "GDTR",
-	IDTR: "IDTR",
-	LDTR: "LDTR",
-	MSW:  "MSW",
-	TASK: "TASK",
-	CR0:  "CR0",
-	CR1:  "CR1",
-	CR2:  "CR2",
-	CR3:  "CR3",
-	CR4:  "CR4",
-	CR5:  "CR5",
-	CR6:  "CR6",
-	CR7:  "CR7",
-	CR8:  "CR8",
-	CR9:  "CR9",
-	CR10: "CR10",
-	CR11: "CR11",
-	CR12: "CR12",
-	CR13: "CR13",
-	CR14: "CR14",
-	CR15: "CR15",
-	DR0:  "DR0",
-	DR1:  "DR1",
-	DR2:  "DR2",
-	DR3:  "DR3",
-	DR4:  "DR4",
-	DR5:  "DR5",
-	DR6:  "DR6",
-	DR7:  "DR7",
-	DR8:  "DR8",
-	DR9:  "DR9",
-	DR10: "DR10",
-	DR11: "DR11",
-	DR12: "DR12",
-	DR13: "DR13",
-	DR14: "DR14",
-	DR15: "DR15",
-	TR0:  "TR0",
-	TR1:  "TR1",
-	TR2:  "TR2",
-	TR3:  "TR3",
-	TR4:  "TR4",
-	TR5:  "TR5",
-	TR6:  "TR6",
-	TR7:  "TR7",
-}
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/xedext_test.go b/src/cmd/internal/rsc.io/x86/x86asm/xedext_test.go
deleted file mode 100644
index d7aa8e3..0000000
--- a/src/cmd/internal/rsc.io/x86/x86asm/xedext_test.go
+++ /dev/null
@@ -1,206 +0,0 @@
-package x86asm
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	"log"
-	"os"
-	"strconv"
-	"strings"
-	"testing"
-)
-
-// xed binary from Intel sde-external-6.22.0-2014-03-06.
-const xedPath = "/Users/rsc/bin/xed"
-
-func testXedArch(t *testing.T, arch int, generate func(func([]byte))) {
-	if testing.Short() {
-		t.Skip("skipping libmach test in short mode")
-	}
-
-	if _, err := os.Stat(xedPath); err != nil {
-		t.Fatal(err)
-	}
-
-	testExtDis(t, "intel", arch, xed, generate, allowedMismatchXed)
-}
-
-func testXed32(t *testing.T, generate func(func([]byte))) {
-	testXedArch(t, 32, generate)
-}
-
-func testXed64(t *testing.T, generate func(func([]byte))) {
-	testXedArch(t, 64, generate)
-}
-
-func xed(ext *ExtDis) error {
-	b, err := ext.Run(xedPath, fmt.Sprintf("-%d", ext.Arch), "-n", "1G", "-ir", ext.File.Name())
-	if err != nil {
-		return err
-	}
-
-	nmatch := 0
-	next := uint32(start)
-	var (
-		addr   uint32
-		encbuf [32]byte
-		enc    []byte
-		text   string
-	)
-
-	var xedEnd = []byte("# end of text section")
-	var xedEnd1 = []byte("# Errors")
-
-	eof := false
-	for {
-		line, err := b.ReadSlice('\n')
-		if err != nil {
-			if err == io.EOF {
-				break
-			}
-			return fmt.Errorf("reading objdump output: %v", err)
-		}
-		if debug {
-			os.Stdout.Write(line)
-		}
-		if bytes.HasPrefix(line, xedEnd) || bytes.HasPrefix(line, xedEnd1) {
-			eof = true
-		}
-		if eof {
-			continue
-		}
-		nmatch++
-		addr, enc, text = parseLineXed(line, encbuf[:0])
-		if addr > next {
-			return fmt.Errorf("address out of sync expected <= %#x at %q in:\n%s", next, line, line)
-		}
-		if addr < next {
-			continue
-		}
-		switch text {
-		case "repz":
-			text = "rep"
-		case "repnz":
-			text = "repn"
-		default:
-			text = strings.Replace(text, "repz ", "rep ", -1)
-			text = strings.Replace(text, "repnz ", "repn ", -1)
-		}
-		if m := pcrelw.FindStringSubmatch(text); m != nil {
-			targ, _ := strconv.ParseUint(m[2], 16, 64)
-			text = fmt.Sprintf("%s .%+#x", m[1], int16(uint32(targ)-uint32(uint16(addr))-uint32(len(enc))))
-		}
-		if m := pcrel.FindStringSubmatch(text); m != nil {
-			targ, _ := strconv.ParseUint(m[2], 16, 64)
-			text = fmt.Sprintf("%s .%+#x", m[1], int32(uint32(targ)-addr-uint32(len(enc))))
-		}
-		ext.Dec <- ExtInst{addr, encbuf, len(enc), text}
-		encbuf = [32]byte{}
-		enc = nil
-		next += 32
-	}
-	if next != start+uint32(ext.Size) {
-		return fmt.Errorf("not enough results found [%d %d]", next, start+ext.Size)
-	}
-	if err := ext.Wait(); err != nil {
-		return fmt.Errorf("exec: %v", err)
-	}
-
-	return nil
-}
-
-var (
-	xedInRaw    = []byte("In raw...")
-	xedDots     = []byte("...")
-	xdis        = []byte("XDIS ")
-	xedError    = []byte("ERROR: ")
-	xedNoDecode = []byte("Could not decode at offset: 0x")
-)
-
-func parseLineXed(line []byte, encstart []byte) (addr uint32, enc []byte, text string) {
-	oline := line
-	if bytes.HasPrefix(line, xedInRaw) || bytes.HasPrefix(line, xedDots) {
-		return 0, nil, ""
-	}
-	if bytes.HasPrefix(line, xedError) {
-		i := bytes.IndexByte(line[len(xedError):], ' ')
-		if i < 0 {
-			log.Fatalf("cannot parse error: %q", oline)
-		}
-		errstr := string(line[len(xedError):])
-		i = bytes.Index(line, xedNoDecode)
-		if i < 0 {
-			log.Fatalf("cannot parse error: %q", oline)
-		}
-		i += len(xedNoDecode)
-		j := bytes.IndexByte(line[i:], ' ')
-		if j < 0 {
-			log.Fatalf("cannot parse error: %q", oline)
-		}
-		x, err := strconv.ParseUint(string(trimSpace(line[i:i+j])), 16, 32)
-		if err != nil {
-			log.Fatalf("cannot parse disassembly: %q", oline)
-		}
-		addr = uint32(x)
-		return addr, nil, errstr
-	}
-
-	if !bytes.HasPrefix(line, xdis) {
-		log.Fatalf("cannot parse disassembly: %q", oline)
-	}
-
-	i := bytes.IndexByte(line, ':')
-	if i < 0 {
-		log.Fatalf("cannot parse disassembly: %q", oline)
-	}
-	x, err := strconv.ParseUint(string(trimSpace(line[len(xdis):i])), 16, 32)
-	if err != nil {
-		log.Fatalf("cannot parse disassembly: %q", oline)
-	}
-	addr = uint32(x)
-
-	// spaces
-	i++
-	for i < len(line) && line[i] == ' ' {
-		i++
-	}
-	// instruction class, spaces
-	for i < len(line) && line[i] != ' ' {
-		i++
-	}
-	for i < len(line) && line[i] == ' ' {
-		i++
-	}
-	// instruction set, spaces
-	for i < len(line) && line[i] != ' ' {
-		i++
-	}
-	for i < len(line) && line[i] == ' ' {
-		i++
-	}
-
-	// hex
-	hexStart := i
-	for i < len(line) && line[i] != ' ' {
-		i++
-	}
-	hexEnd := i
-	for i < len(line) && line[i] == ' ' {
-		i++
-	}
-
-	// text
-	textStart := i
-	for i < len(line) && line[i] != '\n' {
-		i++
-	}
-	textEnd := i
-
-	enc, ok := parseHex(line[hexStart:hexEnd], encstart)
-	if !ok {
-		log.Fatalf("cannot parse disassembly: %q", oline)
-	}
-
-	return addr, enc, string(fixSpace(line[textStart:textEnd]))
-}
diff --git a/src/cmd/internal/rsc.io/arm/armasm/Makefile b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/Makefile
similarity index 100%
rename from src/cmd/internal/rsc.io/arm/armasm/Makefile
rename to src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/Makefile
diff --git a/src/cmd/internal/rsc.io/arm/armasm/decode.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode.go
similarity index 100%
rename from src/cmd/internal/rsc.io/arm/armasm/decode.go
rename to src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode_test.go
new file mode 100644
index 0000000..e2d9127
--- /dev/null
+++ b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode_test.go
@@ -0,0 +1,69 @@
+// 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 armasm
+
+import (
+	"encoding/hex"
+	"io/ioutil"
+	"strconv"
+	"strings"
+	"testing"
+)
+
+func TestDecode(t *testing.T) {
+	data, err := ioutil.ReadFile("testdata/decode.txt")
+	if err != nil {
+		t.Fatal(err)
+	}
+	all := string(data)
+	for strings.Contains(all, "\t\t") {
+		all = strings.Replace(all, "\t\t", "\t", -1)
+	}
+	for _, line := range strings.Split(all, "\n") {
+		line = strings.TrimSpace(line)
+		if line == "" || strings.HasPrefix(line, "#") {
+			continue
+		}
+		f := strings.SplitN(line, "\t", 4)
+		i := strings.Index(f[0], "|")
+		if i < 0 {
+			t.Errorf("parsing %q: missing | separator", f[0])
+			continue
+		}
+		if i%2 != 0 {
+			t.Errorf("parsing %q: misaligned | separator", f[0])
+		}
+		size := i / 2
+		code, err := hex.DecodeString(f[0][:i] + f[0][i+1:])
+		if err != nil {
+			t.Errorf("parsing %q: %v", f[0], err)
+			continue
+		}
+		mode, err := strconv.Atoi(f[1])
+		if err != nil {
+			t.Errorf("invalid mode %q in: %s", f[1], line)
+			continue
+		}
+		syntax, asm := f[2], f[3]
+		inst, err := Decode(code, Mode(mode))
+		var out string
+		if err != nil {
+			out = "error: " + err.Error()
+		} else {
+			switch syntax {
+			case "gnu":
+				out = GNUSyntax(inst)
+			case "plan9": // [sic]
+				out = GoSyntax(inst, 0, nil, nil)
+			default:
+				t.Errorf("unknown syntax %q", syntax)
+				continue
+			}
+		}
+		if out != asm || inst.Len != size {
+			t.Errorf("Decode(%s) [%s] = %s, %d, want %s, %d", f[0], syntax, out, inst.Len, asm, size)
+		}
+	}
+}
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/ext_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/ext_test.go
new file mode 100644
index 0000000..98192b3
--- /dev/null
+++ b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/ext_test.go
@@ -0,0 +1,614 @@
+// 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.
+
+// Support for testing against external disassembler program.
+// Copied and simplified from ../../x86/x86asm/ext_test.go.
+
+package armasm
+
+import (
+	"bufio"
+	"bytes"
+	"encoding/hex"
+	"flag"
+	"fmt"
+	"io/ioutil"
+	"log"
+	"math/rand"
+	"os"
+	"os/exec"
+	"regexp"
+	"runtime"
+	"strings"
+	"testing"
+	"time"
+)
+
+var (
+	printTests = flag.Bool("printtests", false, "print test cases that exercise new code paths")
+	dumpTest   = flag.Bool("dump", false, "dump all encodings")
+	mismatch   = flag.Bool("mismatch", false, "log allowed mismatches")
+	longTest   = flag.Bool("long", false, "long test")
+	keep       = flag.Bool("keep", false, "keep object files around")
+	debug      = false
+)
+
+// A ExtInst represents a single decoded instruction parsed
+// from an external disassembler's output.
+type ExtInst struct {
+	addr uint32
+	enc  [4]byte
+	nenc int
+	text string
+}
+
+func (r ExtInst) String() string {
+	return fmt.Sprintf("%#x: % x: %s", r.addr, r.enc, r.text)
+}
+
+// An ExtDis is a connection between an external disassembler and a test.
+type ExtDis struct {
+	Arch     Mode
+	Dec      chan ExtInst
+	File     *os.File
+	Size     int
+	KeepFile bool
+	Cmd      *exec.Cmd
+}
+
+// Run runs the given command - the external disassembler - and returns
+// a buffered reader of its standard output.
+func (ext *ExtDis) Run(cmd ...string) (*bufio.Reader, error) {
+	if *keep {
+		log.Printf("%s\n", strings.Join(cmd, " "))
+	}
+	ext.Cmd = exec.Command(cmd[0], cmd[1:]...)
+	out, err := ext.Cmd.StdoutPipe()
+	if err != nil {
+		return nil, fmt.Errorf("stdoutpipe: %v", err)
+	}
+	if err := ext.Cmd.Start(); err != nil {
+		return nil, fmt.Errorf("exec: %v", err)
+	}
+
+	b := bufio.NewReaderSize(out, 1<<20)
+	return b, nil
+}
+
+// Wait waits for the command started with Run to exit.
+func (ext *ExtDis) Wait() error {
+	return ext.Cmd.Wait()
+}
+
+// testExtDis tests a set of byte sequences against an external disassembler.
+// The disassembler is expected to produce the given syntax and be run
+// in the given architecture mode (16, 32, or 64-bit).
+// The extdis function must start the external disassembler
+// and then parse its output, sending the parsed instructions on ext.Dec.
+// The generate function calls its argument f once for each byte sequence
+// to be tested. The generate function itself will be called twice, and it must
+// make the same sequence of calls to f each time.
+// When a disassembly does not match the internal decoding,
+// allowedMismatch determines whether this mismatch should be
+// allowed, or else considered an error.
+func testExtDis(
+	t *testing.T,
+	syntax string,
+	arch Mode,
+	extdis func(ext *ExtDis) error,
+	generate func(f func([]byte)),
+	allowedMismatch func(text string, size int, inst *Inst, dec ExtInst) bool,
+) {
+	start := time.Now()
+	ext := &ExtDis{
+		Dec:  make(chan ExtInst),
+		Arch: arch,
+	}
+	errc := make(chan error)
+
+	// First pass: write instructions to input file for external disassembler.
+	file, f, size, err := writeInst(generate)
+	if err != nil {
+		t.Fatal(err)
+	}
+	ext.Size = size
+	ext.File = f
+	defer func() {
+		f.Close()
+		if !*keep {
+			os.Remove(file)
+		}
+	}()
+
+	// Second pass: compare disassembly against our decodings.
+	var (
+		totalTests  = 0
+		totalSkips  = 0
+		totalErrors = 0
+
+		errors = make([]string, 0, 100) // sampled errors, at most cap
+	)
+	go func() {
+		errc <- extdis(ext)
+	}()
+	generate(func(enc []byte) {
+		dec, ok := <-ext.Dec
+		if !ok {
+			t.Errorf("decoding stream ended early")
+			return
+		}
+		inst, text := disasm(syntax, arch, pad(enc))
+		totalTests++
+		if *dumpTest {
+			fmt.Printf("%x -> %s [%d]\n", enc[:len(enc)], dec.text, dec.nenc)
+		}
+		if text != dec.text || inst.Len != dec.nenc {
+			suffix := ""
+			if allowedMismatch(text, size, &inst, dec) {
+				totalSkips++
+				if !*mismatch {
+					return
+				}
+				suffix += " (allowed mismatch)"
+			}
+			totalErrors++
+			if len(errors) >= cap(errors) {
+				j := rand.Intn(totalErrors)
+				if j >= cap(errors) {
+					return
+				}
+				errors = append(errors[:j], errors[j+1:]...)
+			}
+			errors = append(errors, fmt.Sprintf("decode(%x) = %q, %d, want %q, %d%s", enc, text, inst.Len, dec.text, dec.nenc, suffix))
+		}
+	})
+
+	if *mismatch {
+		totalErrors -= totalSkips
+	}
+
+	for _, b := range errors {
+		t.Log(b)
+	}
+
+	if totalErrors > 0 {
+		t.Fail()
+	}
+	t.Logf("%d test cases, %d expected mismatches, %d failures; %.0f cases/second", totalTests, totalSkips, totalErrors, float64(totalTests)/time.Since(start).Seconds())
+
+	if err := <-errc; err != nil {
+		t.Fatalf("external disassembler: %v", err)
+	}
+
+}
+
+const start = 0x8000 // start address of text
+
+// writeInst writes the generated byte sequences to a new file
+// starting at offset start. That file is intended to be the input to
+// the external disassembler.
+func writeInst(generate func(func([]byte))) (file string, f *os.File, size int, err error) {
+	f, err = ioutil.TempFile("", "armasm")
+	if err != nil {
+		return
+	}
+
+	file = f.Name()
+
+	f.Seek(start, 0)
+	w := bufio.NewWriter(f)
+	defer w.Flush()
+	size = 0
+	generate(func(x []byte) {
+		if len(x) > 4 {
+			x = x[:4]
+		}
+		if debug {
+			fmt.Printf("%#x: %x%x\n", start+size, x, zeros[len(x):])
+		}
+		w.Write(x)
+		w.Write(zeros[len(x):])
+		size += len(zeros)
+	})
+	return file, f, size, nil
+}
+
+var zeros = []byte{0, 0, 0, 0}
+
+// pad pads the code sequence with pops.
+func pad(enc []byte) []byte {
+	if len(enc) < 4 {
+		enc = append(enc[:len(enc):len(enc)], zeros[:4-len(enc)]...)
+	}
+	return enc
+}
+
+// disasm returns the decoded instruction and text
+// for the given source bytes, using the given syntax and mode.
+func disasm(syntax string, mode Mode, src []byte) (inst Inst, text string) {
+	// If printTests is set, we record the coverage value
+	// before and after, and we write out the inputs for which
+	// coverage went up, in the format expected in testdata/decode.text.
+	// This produces a fairly small set of test cases that exercise nearly
+	// all the code.
+	var cover float64
+	if *printTests {
+		cover -= coverage()
+	}
+
+	inst, err := Decode(src, mode)
+	if err != nil {
+		text = "error: " + err.Error()
+	} else {
+		text = inst.String()
+		switch syntax {
+		//case "arm":
+		//	text = ARMSyntax(inst)
+		case "gnu":
+			text = GNUSyntax(inst)
+		//case "plan9": // [sic]
+		//	text = GoSyntax(inst, 0, nil)
+		default:
+			text = "error: unknown syntax " + syntax
+		}
+	}
+
+	if *printTests {
+		cover += coverage()
+		if cover > 0 {
+			max := len(src)
+			if max > 4 && inst.Len <= 4 {
+				max = 4
+			}
+			fmt.Printf("%x|%x\t%d\t%s\t%s\n", src[:inst.Len], src[inst.Len:max], mode, syntax, text)
+		}
+	}
+
+	return
+}
+
+// coverage returns a floating point number denoting the
+// test coverage until now. The number increases when new code paths are exercised,
+// both in the Go program and in the decoder byte code.
+func coverage() float64 {
+	/*
+		testing.Coverage is not in the main distribution.
+		The implementation, which must go in package testing, is:
+
+		// Coverage reports the current code coverage as a fraction in the range [0, 1].
+		func Coverage() float64 {
+			var n, d int64
+			for _, counters := range cover.Counters {
+				for _, c := range counters {
+					if c > 0 {
+						n++
+					}
+					d++
+				}
+			}
+			if d == 0 {
+				return 0
+			}
+			return float64(n) / float64(d)
+		}
+	*/
+
+	var f float64
+	f += testing.Coverage()
+	f += decodeCoverage()
+	return f
+}
+
+func decodeCoverage() float64 {
+	n := 0
+	for _, t := range decoderCover {
+		if t {
+			n++
+		}
+	}
+	return float64(1+n) / float64(1+len(decoderCover))
+}
+
+// Helpers for writing disassembler output parsers.
+
+// hasPrefix reports whether any of the space-separated words in the text s
+// begins with any of the given prefixes.
+func hasPrefix(s string, prefixes ...string) bool {
+	for _, prefix := range prefixes {
+		for s := s; s != ""; {
+			if strings.HasPrefix(s, prefix) {
+				return true
+			}
+			i := strings.Index(s, " ")
+			if i < 0 {
+				break
+			}
+			s = s[i+1:]
+		}
+	}
+	return false
+}
+
+// contains reports whether the text s contains any of the given substrings.
+func contains(s string, substrings ...string) bool {
+	for _, sub := range substrings {
+		if strings.Contains(s, sub) {
+			return true
+		}
+	}
+	return false
+}
+
+// isHex reports whether b is a hexadecimal character (0-9A-Fa-f).
+func isHex(b byte) bool { return b == '0' || unhex[b] > 0 }
+
+// parseHex parses the hexadecimal byte dump in hex,
+// appending the parsed bytes to raw and returning the updated slice.
+// The returned bool signals whether any invalid hex was found.
+// Spaces and tabs between bytes are okay but any other non-hex is not.
+func parseHex(hex []byte, raw []byte) ([]byte, bool) {
+	hex = trimSpace(hex)
+	for j := 0; j < len(hex); {
+		for hex[j] == ' ' || hex[j] == '\t' {
+			j++
+		}
+		if j >= len(hex) {
+			break
+		}
+		if j+2 > len(hex) || !isHex(hex[j]) || !isHex(hex[j+1]) {
+			return nil, false
+		}
+		raw = append(raw, unhex[hex[j]]<<4|unhex[hex[j+1]])
+		j += 2
+	}
+	return raw, true
+}
+
+var unhex = [256]byte{
+	'0': 0,
+	'1': 1,
+	'2': 2,
+	'3': 3,
+	'4': 4,
+	'5': 5,
+	'6': 6,
+	'7': 7,
+	'8': 8,
+	'9': 9,
+	'A': 10,
+	'B': 11,
+	'C': 12,
+	'D': 13,
+	'E': 14,
+	'F': 15,
+	'a': 10,
+	'b': 11,
+	'c': 12,
+	'd': 13,
+	'e': 14,
+	'f': 15,
+}
+
+// index is like bytes.Index(s, []byte(t)) but avoids the allocation.
+func index(s []byte, t string) int {
+	i := 0
+	for {
+		j := bytes.IndexByte(s[i:], t[0])
+		if j < 0 {
+			return -1
+		}
+		i = i + j
+		if i+len(t) > len(s) {
+			return -1
+		}
+		for k := 1; k < len(t); k++ {
+			if s[i+k] != t[k] {
+				goto nomatch
+			}
+		}
+		return i
+	nomatch:
+		i++
+	}
+}
+
+// fixSpace rewrites runs of spaces, tabs, and newline characters into single spaces in s.
+// If s must be rewritten, it is rewritten in place.
+func fixSpace(s []byte) []byte {
+	s = trimSpace(s)
+	for i := 0; i < len(s); i++ {
+		if s[i] == '\t' || s[i] == '\n' || i > 0 && s[i] == ' ' && s[i-1] == ' ' {
+			goto Fix
+		}
+	}
+	return s
+
+Fix:
+	b := s
+	w := 0
+	for i := 0; i < len(s); i++ {
+		c := s[i]
+		if c == '\t' || c == '\n' {
+			c = ' '
+		}
+		if c == ' ' && w > 0 && b[w-1] == ' ' {
+			continue
+		}
+		b[w] = c
+		w++
+	}
+	if w > 0 && b[w-1] == ' ' {
+		w--
+	}
+	return b[:w]
+}
+
+// trimSpace trims leading and trailing space from s, returning a subslice of s.
+func trimSpace(s []byte) []byte {
+	j := len(s)
+	for j > 0 && (s[j-1] == ' ' || s[j-1] == '\t' || s[j-1] == '\n') {
+		j--
+	}
+	i := 0
+	for i < j && (s[i] == ' ' || s[i] == '\t') {
+		i++
+	}
+	return s[i:j]
+}
+
+// pcrel matches instructions using relative addressing mode.
+var (
+	pcrel = regexp.MustCompile(`^((?:.* )?(?:b|bl)x?(?:eq|ne|cs|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le)?) 0x([0-9a-f]+)$`)
+)
+
+// Generators.
+//
+// The test cases are described as functions that invoke a callback repeatedly,
+// with a new input sequence each time. These helpers make writing those
+// a little easier.
+
+// condCases generates conditional instructions.
+func condCases(t *testing.T) func(func([]byte)) {
+	return func(try func([]byte)) {
+		// All the strides are relatively prime to 2 and therefore to 2²⁸,
+		// so we will not repeat any instructions until we have tried all 2²⁸.
+		// Using a stride other than 1 is meant to visit the instructions in a
+		// pseudorandom order, which gives better variety in the set of
+		// test cases chosen by -printtests.
+		stride := uint32(10007)
+		n := 1 << 28 / 7
+		if testing.Short() {
+			stride = 100003
+			n = 1 << 28 / 1001
+		} else if *longTest {
+			stride = 200000033
+			n = 1 << 28
+		}
+		x := uint32(0)
+		for i := 0; i < n; i++ {
+			enc := (x%15)<<28 | x&(1<<28-1)
+			try([]byte{byte(enc), byte(enc >> 8), byte(enc >> 16), byte(enc >> 24)})
+			x += stride
+		}
+	}
+}
+
+// uncondCases generates unconditional instructions.
+func uncondCases(t *testing.T) func(func([]byte)) {
+	return func(try func([]byte)) {
+		condCases(t)(func(enc []byte) {
+			enc[3] |= 0xF0
+			try(enc)
+		})
+	}
+}
+
+func countBits(x uint32) int {
+	n := 0
+	for ; x != 0; x >>= 1 {
+		n += int(x & 1)
+	}
+	return n
+}
+
+func expandBits(x, m uint32) uint32 {
+	var out uint32
+	for i := uint(0); i < 32; i++ {
+		out >>= 1
+		if m&1 != 0 {
+			out |= (x & 1) << 31
+			x >>= 1
+		}
+		m >>= 1
+	}
+	return out
+}
+
+func tryCondMask(mask, val uint32, try func([]byte)) {
+	n := countBits(^mask)
+	bits := uint32(0)
+	for i := 0; i < 1<<uint(n); i++ {
+		bits += 848251 // arbitrary prime
+		x := val | expandBits(bits, ^mask) | uint32(i)%15<<28
+		try([]byte{byte(x), byte(x >> 8), byte(x >> 16), byte(x >> 24)})
+	}
+}
+
+// vfpCases generates VFP instructions.
+func vfpCases(t *testing.T) func(func([]byte)) {
+	const (
+		vfpmask uint32 = 0xFF00FE10
+		vfp     uint32 = 0x0E009A00
+	)
+	return func(try func([]byte)) {
+		tryCondMask(0xff00fe10, 0x0e009a00, try) // standard VFP instruction space
+		tryCondMask(0xffc00f7f, 0x0e000b10, try) // VFP MOV core reg to/from float64 half
+		tryCondMask(0xffe00f7f, 0x0e000a10, try) // VFP MOV core reg to/from float32
+		tryCondMask(0xffef0fff, 0x0ee10a10, try) // VFP MOV core reg to/from cond codes
+	}
+}
+
+// hexCases generates the cases written in hexadecimal in the encoded string.
+// Spaces in 'encoded' separate entire test cases, not individual bytes.
+func hexCases(t *testing.T, encoded string) func(func([]byte)) {
+	return func(try func([]byte)) {
+		for _, x := range strings.Fields(encoded) {
+			src, err := hex.DecodeString(x)
+			if err != nil {
+				t.Errorf("parsing %q: %v", x, err)
+			}
+			try(src)
+		}
+	}
+}
+
+// testdataCases generates the test cases recorded in testdata/decode.txt.
+// It only uses the inputs; it ignores the answers recorded in that file.
+func testdataCases(t *testing.T) func(func([]byte)) {
+	var codes [][]byte
+	data, err := ioutil.ReadFile("testdata/decode.txt")
+	if err != nil {
+		t.Fatal(err)
+	}
+	for _, line := range strings.Split(string(data), "\n") {
+		line = strings.TrimSpace(line)
+		if line == "" || strings.HasPrefix(line, "#") {
+			continue
+		}
+		f := strings.Fields(line)[0]
+		i := strings.Index(f, "|")
+		if i < 0 {
+			t.Errorf("parsing %q: missing | separator", f)
+			continue
+		}
+		if i%2 != 0 {
+			t.Errorf("parsing %q: misaligned | separator", f)
+		}
+		code, err := hex.DecodeString(f[:i] + f[i+1:])
+		if err != nil {
+			t.Errorf("parsing %q: %v", f, err)
+			continue
+		}
+		codes = append(codes, code)
+	}
+
+	return func(try func([]byte)) {
+		for _, code := range codes {
+			try(code)
+		}
+	}
+}
+
+func caller(skip int) string {
+	pc, _, _, _ := runtime.Caller(skip)
+	f := runtime.FuncForPC(pc)
+	name := "?"
+	if f != nil {
+		name = f.Name()
+		if i := strings.LastIndex(name, "."); i >= 0 {
+			name = name[i+1:]
+		}
+	}
+	return name
+}
diff --git a/src/cmd/internal/rsc.io/arm/armasm/gnu.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/gnu.go
similarity index 100%
rename from src/cmd/internal/rsc.io/arm/armasm/gnu.go
rename to src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/gnu.go
diff --git a/src/cmd/internal/rsc.io/arm/armasm/inst.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/inst.go
similarity index 100%
rename from src/cmd/internal/rsc.io/arm/armasm/inst.go
rename to src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/inst.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/objdump_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/objdump_test.go
new file mode 100644
index 0000000..db51902
--- /dev/null
+++ b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/objdump_test.go
@@ -0,0 +1,268 @@
+// 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 armasm
+
+import (
+	"encoding/binary"
+	"strings"
+	"testing"
+)
+
+func TestObjdumpARMTestdata(t *testing.T) { testObjdumpARM(t, testdataCases(t)) }
+func TestObjdumpARMManual(t *testing.T)   { testObjdumpARM(t, hexCases(t, objdumpManualTests)) }
+func TestObjdumpARMCond(t *testing.T)     { testObjdumpARM(t, condCases(t)) }
+func TestObjdumpARMUncond(t *testing.T)   { testObjdumpARM(t, uncondCases(t)) }
+func TestObjdumpARMVFP(t *testing.T)      { testObjdumpARM(t, vfpCases(t)) }
+
+// objdumpManualTests holds test cases that will be run by TestObjdumpARMManual.
+// If you are debugging a few cases that turned up in a longer run, it can be useful
+// to list them here and then use -run=Manual, particularly with tracing enabled.
+// Note that these are byte sequences, so they must be reversed from the usual
+// word presentation.
+var objdumpManualTests = `
+002a9b1d
+001b9bed
+020b8ded
+003a9b1d
+060b8ded
+fcde1100
+b4de1100
+bc480000
+0b008de7
+0b00ade7
+fdbcfaf7
+`
+
+// allowedMismatchObjdump reports whether the mismatch between text and dec
+// should be allowed by the test.
+func allowedMismatchObjdump(text string, size int, inst *Inst, dec ExtInst) bool {
+	if hasPrefix(text, "error:") {
+		if hasPrefix(dec.text, unsupported...) || strings.Contains(dec.text, "invalid:") || strings.HasSuffix(dec.text, "^") || strings.Contains(dec.text, "f16.f64") || strings.Contains(dec.text, "f64.f16") {
+			return true
+		}
+		// word 4320F02C: libopcodes says 'nopmi {44}'.
+		if hasPrefix(dec.text, "nop") && strings.Contains(dec.text, "{") {
+			return true
+		}
+	}
+
+	if hasPrefix(dec.text, "error:") && text == "undef" && inst.Enc == 0xf7fabcfd {
+		return true
+	}
+
+	// word 00f02053: libopcodes says 'noppl {0}'.
+	if hasPrefix(dec.text, "nop") && hasPrefix(text, "nop") && dec.text == text+" {0}" {
+		return true
+	}
+
+	// word F57FF04F. we say 'dsb #15', libopcodes says 'dsb sy'.
+	if hasPrefix(text, "dsb") && hasPrefix(dec.text, "dsb") {
+		return true
+	}
+	// word F57FF06F. we say 'isb #15', libopcodes says 'isb sy'.
+	if hasPrefix(text, "isb") && hasPrefix(dec.text, "isb") {
+		return true
+	}
+	// word F57FF053. we say 'dmb #3', libopcodes says 'dmb osh'.
+	if hasPrefix(text, "dmb") && hasPrefix(dec.text, "dmb") {
+		return true
+	}
+
+	// word 992D0000. push/stmdb with no registers (undefined).
+	// we say 'stmdbls sp!, {}', libopcodes says 'pushls {}'.
+	if hasPrefix(text, "stmdb") && hasPrefix(dec.text, "push") && strings.Contains(text, "{}") && strings.Contains(dec.text, "{}") {
+		return true
+	}
+
+	// word 28BD0000. pop/ldm with no registers (undefined).
+	// we say 'ldmcs sp!, {}', libopcodes says 'popcs {}'.
+	if hasPrefix(text, "ldm") && hasPrefix(dec.text, "pop") && strings.Contains(text, "{}") && strings.Contains(dec.text, "{}") {
+		return true
+	}
+
+	// word 014640F0.
+	// libopcodes emits #-0 for negative zero; we don't.
+	if strings.Replace(dec.text, "#-0", "#0", -1) == text || strings.Replace(dec.text, ", #-0", "", -1) == text {
+		return true
+	}
+
+	// word 91EF90F0. we say 'strdls r9, [pc, #0]!' but libopcodes says 'strdls r9, [pc]'.
+	// word D16F60F0. we say 'strdle r6, [pc, #0]!' but libopcodes says 'strdle r6, [pc, #-0]'.
+	if strings.Replace(text, ", #0]!", "]", -1) == strings.Replace(dec.text, ", #-0]", "]", -1) {
+		return true
+	}
+
+	// word 510F4000. we say apsr, libopcodes says CPSR.
+	if strings.Replace(dec.text, "CPSR", "apsr", -1) == text {
+		return true
+	}
+
+	// word 06A4B059.
+	// for ssat and usat, libopcodes decodes asr #0 as asr #0 but the manual seems to say it should be asr #32.
+	// There is never an asr #0.
+	if strings.Replace(dec.text, ", asr #0", ", asr #32", -1) == text {
+		return true
+	}
+
+	if len(dec.enc) >= 4 {
+		raw := binary.LittleEndian.Uint32(dec.enc[:4])
+
+		// word 21FFF0B5.
+		// the manual is clear that this is pre-indexed mode (with !) but libopcodes generates post-index (without !).
+		if raw&0x01200000 == 0x01200000 && strings.Replace(text, "!", "", -1) == dec.text {
+			return true
+		}
+
+		// word C100543E: libopcodes says tst, but no evidence for that.
+		if strings.HasPrefix(dec.text, "tst") && raw&0x0ff00000 != 0x03100000 && raw&0x0ff00000 != 0x01100000 {
+			return true
+		}
+
+		// word C3203CE8: libopcodes says teq, but no evidence for that.
+		if strings.HasPrefix(dec.text, "teq") && raw&0x0ff00000 != 0x03300000 && raw&0x0ff00000 != 0x01300000 {
+			return true
+		}
+
+		// word D14C552E: libopcodes says cmp but no evidence for that.
+		if strings.HasPrefix(dec.text, "cmp") && raw&0x0ff00000 != 0x03500000 && raw&0x0ff00000 != 0x01500000 {
+			return true
+		}
+
+		// word 2166AA4A: libopcodes says cmn but no evidence for that.
+		if strings.HasPrefix(dec.text, "cmn") && raw&0x0ff00000 != 0x03700000 && raw&0x0ff00000 != 0x01700000 {
+			return true
+		}
+
+		// word E70AEEEF: libopcodes says str but no evidence for that.
+		if strings.HasPrefix(dec.text, "str") && len(dec.text) >= 5 && (dec.text[3] == ' ' || dec.text[5] == ' ') && raw&0x0e500018 != 0x06000000 && raw&0x0e500000 != 0x0400000 {
+			return true
+		}
+
+		// word B0AF48F4: libopcodes says strd but P=0,W=1 which is unpredictable.
+		if hasPrefix(dec.text, "ldr", "str") && raw&0x01200000 == 0x00200000 {
+			return true
+		}
+
+		// word B6CC1C76: libopcodes inexplicably says 'uxtab16lt r1, ip, r6, ROR #24' instead of 'uxtab16lt r1, ip, r6, ror #24'
+		if strings.ToLower(dec.text) == text {
+			return true
+		}
+
+		// word F410FDA1: libopcodes says PLDW but the manual is clear that PLDW is F5/F7, not F4.
+		// word F7D0FB17: libopcodes says PLDW but the manual is clear that PLDW has 0x10 clear
+		if hasPrefix(dec.text, "pld") && raw&0xfd000010 != 0xf5000000 {
+			return true
+		}
+
+		// word F650FE14: libopcodes says PLI but the manual is clear that PLI has 0x10 clear
+		if hasPrefix(dec.text, "pli") && raw&0xff000010 != 0xf6000000 {
+			return true
+		}
+	}
+
+	return false
+}
+
+// Instructions known to libopcodes (or xed) but not to us.
+// Most of these are floating point coprocessor instructions.
+var unsupported = strings.Fields(`
+	abs
+	acs
+	adf
+	aes
+	asn
+	atn
+	cdp
+	cf
+	cmf
+	cnf
+	cos
+	cps
+	crc32
+	dvf
+	eret
+	exp
+	fadd
+	fcmp
+	fcpy
+	fcvt
+	fdiv
+	fdv
+	fix
+	fld
+	flt
+	fmac
+	fmd
+	fml
+	fmr
+	fms
+	fmul
+	fmx
+	fneg
+	fnm
+	frd
+	fsit
+	fsq
+	fst
+	fsu
+	fto
+	fui
+	hlt
+	hvc
+	lda
+	ldc
+	ldf
+	lfm
+	lgn
+	log
+	mar
+	mcr
+	mcrr
+	mia
+	mnf
+	mra
+	mrc
+	mrrc
+	mrs
+	msr
+	msr
+	muf
+	mvf
+	nrm
+	pol
+	pow
+	rdf
+	rfc
+	rfe
+	rfs
+	rmf
+	rnd
+	rpw
+	rsf
+	sdiv
+	sev
+	sfm
+	sha1
+	sha256
+	sin
+	smc
+	sqt
+	srs
+	stc
+	stf
+	stl
+	suf
+	tan
+	udf
+	udiv
+	urd
+	vfma
+	vfms
+	vfnma
+	vfnms
+	vrint
+	wfc
+	wfs
+`)
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/objdumpext_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/objdumpext_test.go
new file mode 100644
index 0000000..74fb47d
--- /dev/null
+++ b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/objdumpext_test.go
@@ -0,0 +1,259 @@
+// 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.
+
+// Copied and simplified from ../../x86/x86asm/objdumpext_test.go.
+
+package armasm
+
+import (
+	"bytes"
+	"debug/elf"
+	"encoding/binary"
+	"fmt"
+	"io"
+	"log"
+	"os"
+	"strconv"
+	"strings"
+	"testing"
+)
+
+const objdumpPath = "/usr/local/bin/arm-linux-elf-objdump"
+
+func testObjdumpARM(t *testing.T, generate func(func([]byte))) {
+	testObjdumpArch(t, generate, ModeARM)
+}
+
+func testObjdumpArch(t *testing.T, generate func(func([]byte)), arch Mode) {
+	if testing.Short() {
+		t.Skip("skipping objdump test in short mode")
+	}
+	if _, err := os.Stat(objdumpPath); err != nil {
+		t.Skip(err)
+	}
+
+	testExtDis(t, "gnu", arch, objdump, generate, allowedMismatchObjdump)
+}
+
+func objdump(ext *ExtDis) error {
+	// File already written with instructions; add ELF header.
+	if ext.Arch == ModeARM {
+		if err := writeELF32(ext.File, ext.Size); err != nil {
+			return err
+		}
+	} else {
+		panic("unknown arch")
+	}
+
+	b, err := ext.Run(objdumpPath, "-d", "-z", ext.File.Name())
+	if err != nil {
+		return err
+	}
+
+	var (
+		nmatch  int
+		reading bool
+		next    uint32 = start
+		addr    uint32
+		encbuf  [4]byte
+		enc     []byte
+		text    string
+	)
+	flush := func() {
+		if addr == next {
+			if m := pcrel.FindStringSubmatch(text); m != nil {
+				targ, _ := strconv.ParseUint(m[2], 16, 64)
+				text = fmt.Sprintf("%s .%+#x", m[1], int32(uint32(targ)-addr-uint32(len(enc))))
+			}
+			if strings.HasPrefix(text, "stmia") {
+				text = "stm" + text[5:]
+			}
+			if strings.HasPrefix(text, "stmfd") {
+				text = "stmdb" + text[5:]
+			}
+			if strings.HasPrefix(text, "ldmfd") {
+				text = "ldm" + text[5:]
+			}
+			text = strings.Replace(text, "#0.0", "#0", -1)
+			if text == "undefined" && len(enc) == 4 {
+				text = "error: unknown instruction"
+				enc = nil
+			}
+			if len(enc) == 4 {
+				// prints as word but we want to record bytes
+				enc[0], enc[3] = enc[3], enc[0]
+				enc[1], enc[2] = enc[2], enc[1]
+			}
+			ext.Dec <- ExtInst{addr, encbuf, len(enc), text}
+			encbuf = [4]byte{}
+			enc = nil
+			next += 4
+		}
+	}
+	var textangle = []byte("<.text>:")
+	for {
+		line, err := b.ReadSlice('\n')
+		if err != nil {
+			if err == io.EOF {
+				break
+			}
+			return fmt.Errorf("reading objdump output: %v", err)
+		}
+		if bytes.Contains(line, textangle) {
+			reading = true
+			continue
+		}
+		if !reading {
+			continue
+		}
+		if debug {
+			os.Stdout.Write(line)
+		}
+		if enc1 := parseContinuation(line, encbuf[:len(enc)]); enc1 != nil {
+			enc = enc1
+			continue
+		}
+		flush()
+		nmatch++
+		addr, enc, text = parseLine(line, encbuf[:0])
+		if addr > next {
+			return fmt.Errorf("address out of sync expected <= %#x at %q in:\n%s", next, line, line)
+		}
+	}
+	flush()
+	if next != start+uint32(ext.Size) {
+		return fmt.Errorf("not enough results found [%d %d]", next, start+ext.Size)
+	}
+	if err := ext.Wait(); err != nil {
+		return fmt.Errorf("exec: %v", err)
+	}
+
+	return nil
+}
+
+var (
+	undefined      = []byte("<UNDEFINED>")
+	unpredictable  = []byte("<UNPREDICTABLE>")
+	illegalShifter = []byte("<illegal shifter operand>")
+)
+
+func parseLine(line []byte, encstart []byte) (addr uint32, enc []byte, text string) {
+	oline := line
+	i := index(line, ":\t")
+	if i < 0 {
+		log.Fatalf("cannot parse disassembly: %q", oline)
+	}
+	x, err := strconv.ParseUint(string(trimSpace(line[:i])), 16, 32)
+	if err != nil {
+		log.Fatalf("cannot parse disassembly: %q", oline)
+	}
+	addr = uint32(x)
+	line = line[i+2:]
+	i = bytes.IndexByte(line, '\t')
+	if i < 0 {
+		log.Fatalf("cannot parse disassembly: %q", oline)
+	}
+	enc, ok := parseHex(line[:i], encstart)
+	if !ok {
+		log.Fatalf("cannot parse disassembly: %q", oline)
+	}
+	line = trimSpace(line[i:])
+	if bytes.Contains(line, undefined) {
+		text = "undefined"
+		return
+	}
+	if bytes.Contains(line, illegalShifter) {
+		text = "undefined"
+		return
+	}
+	if false && bytes.Contains(line, unpredictable) {
+		text = "unpredictable"
+		return
+	}
+	if i := bytes.IndexByte(line, ';'); i >= 0 {
+		line = trimSpace(line[:i])
+	}
+	text = string(fixSpace(line))
+	return
+}
+
+func parseContinuation(line []byte, enc []byte) []byte {
+	i := index(line, ":\t")
+	if i < 0 {
+		return nil
+	}
+	line = line[i+1:]
+	enc, _ = parseHex(line, enc)
+	return enc
+}
+
+// writeELF32 writes an ELF32 header to the file,
+// describing a text segment that starts at start
+// and extends for size bytes.
+func writeELF32(f *os.File, size int) error {
+	f.Seek(0, 0)
+	var hdr elf.Header32
+	var prog elf.Prog32
+	var sect elf.Section32
+	var buf bytes.Buffer
+	binary.Write(&buf, binary.LittleEndian, &hdr)
+	off1 := buf.Len()
+	binary.Write(&buf, binary.LittleEndian, &prog)
+	off2 := buf.Len()
+	binary.Write(&buf, binary.LittleEndian, &sect)
+	off3 := buf.Len()
+	buf.Reset()
+	data := byte(elf.ELFDATA2LSB)
+	hdr = elf.Header32{
+		Ident:     [16]byte{0x7F, 'E', 'L', 'F', 1, data, 1},
+		Type:      2,
+		Machine:   uint16(elf.EM_ARM),
+		Version:   1,
+		Entry:     start,
+		Phoff:     uint32(off1),
+		Shoff:     uint32(off2),
+		Flags:     0x05000002,
+		Ehsize:    uint16(off1),
+		Phentsize: uint16(off2 - off1),
+		Phnum:     1,
+		Shentsize: uint16(off3 - off2),
+		Shnum:     3,
+		Shstrndx:  2,
+	}
+	binary.Write(&buf, binary.LittleEndian, &hdr)
+	prog = elf.Prog32{
+		Type:   1,
+		Off:    start,
+		Vaddr:  start,
+		Paddr:  start,
+		Filesz: uint32(size),
+		Memsz:  uint32(size),
+		Flags:  5,
+		Align:  start,
+	}
+	binary.Write(&buf, binary.LittleEndian, &prog)
+	binary.Write(&buf, binary.LittleEndian, &sect) // NULL section
+	sect = elf.Section32{
+		Name:      1,
+		Type:      uint32(elf.SHT_PROGBITS),
+		Addr:      start,
+		Off:       start,
+		Size:      uint32(size),
+		Flags:     uint32(elf.SHF_ALLOC | elf.SHF_EXECINSTR),
+		Addralign: 4,
+	}
+	binary.Write(&buf, binary.LittleEndian, &sect) // .text
+	sect = elf.Section32{
+		Name:      uint32(len("\x00.text\x00")),
+		Type:      uint32(elf.SHT_STRTAB),
+		Addr:      0,
+		Off:       uint32(off2 + (off3-off2)*3),
+		Size:      uint32(len("\x00.text\x00.shstrtab\x00")),
+		Addralign: 1,
+	}
+	binary.Write(&buf, binary.LittleEndian, &sect)
+	buf.WriteString("\x00.text\x00.shstrtab\x00")
+	f.Write(buf.Bytes())
+	return nil
+}
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/plan9x.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/plan9x.go
new file mode 100644
index 0000000..fae0ca6
--- /dev/null
+++ b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/plan9x.go
@@ -0,0 +1,211 @@
+// 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 armasm
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"io"
+	"strings"
+)
+
+// GoSyntax returns the Go assembler syntax for the instruction.
+// The syntax was originally defined by Plan 9.
+// The pc is the program counter of the instruction, used for expanding
+// PC-relative addresses into absolute ones.
+// The symname function queries the symbol table for the program
+// being disassembled. Given a target address it returns the name and base
+// address of the symbol containing the target, if any; otherwise it returns "", 0.
+// The reader r should read from the text segment using text addresses
+// as offsets; it is used to display pc-relative loads as constant loads.
+func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64), text io.ReaderAt) string {
+	if symname == nil {
+		symname = func(uint64) (string, uint64) { return "", 0 }
+	}
+
+	var args []string
+	for _, a := range inst.Args {
+		if a == nil {
+			break
+		}
+		args = append(args, plan9Arg(&inst, pc, symname, a))
+	}
+
+	op := inst.Op.String()
+
+	switch inst.Op &^ 15 {
+	case LDR_EQ, LDRB_EQ, LDRH_EQ:
+		// Check for RET
+		reg, _ := inst.Args[0].(Reg)
+		mem, _ := inst.Args[1].(Mem)
+		if inst.Op&^15 == LDR_EQ && reg == R15 && mem.Base == SP && mem.Sign == 0 && mem.Mode == AddrPostIndex {
+			return fmt.Sprintf("RET%s #%d", op[3:], mem.Offset)
+		}
+
+		// Check for PC-relative load.
+		if mem.Base == PC && mem.Sign == 0 && mem.Mode == AddrOffset && text != nil {
+			addr := uint32(pc) + 8 + uint32(mem.Offset)
+			buf := make([]byte, 4)
+			switch inst.Op &^ 15 {
+			case LDRB_EQ:
+				if _, err := text.ReadAt(buf[:1], int64(addr)); err != nil {
+					break
+				}
+				args[1] = fmt.Sprintf("$%#x", buf[0])
+
+			case LDRH_EQ:
+				if _, err := text.ReadAt(buf[:2], int64(addr)); err != nil {
+					break
+				}
+				args[1] = fmt.Sprintf("$%#x", binary.LittleEndian.Uint16(buf))
+
+			case LDR_EQ:
+				if _, err := text.ReadAt(buf, int64(addr)); err != nil {
+					break
+				}
+				x := binary.LittleEndian.Uint32(buf)
+				if s, base := symname(uint64(x)); s != "" && uint64(x) == base {
+					args[1] = fmt.Sprintf("$%s(SB)", s)
+				} else {
+					args[1] = fmt.Sprintf("$%#x", x)
+				}
+			}
+		}
+	}
+
+	// Move addressing mode into opcode suffix.
+	suffix := ""
+	switch inst.Op &^ 15 {
+	case LDR_EQ, LDRB_EQ, LDRH_EQ, STR_EQ, STRB_EQ, STRH_EQ:
+		mem, _ := inst.Args[1].(Mem)
+		switch mem.Mode {
+		case AddrOffset, AddrLDM:
+			// no suffix
+		case AddrPreIndex, AddrLDM_WB:
+			suffix = ".W"
+		case AddrPostIndex:
+			suffix = ".P"
+		}
+		off := ""
+		if mem.Offset != 0 {
+			off = fmt.Sprintf("%#x", mem.Offset)
+		}
+		base := fmt.Sprintf("(R%d)", int(mem.Base))
+		index := ""
+		if mem.Sign != 0 {
+			sign := ""
+			if mem.Sign < 0 {
+				sign = ""
+			}
+			shift := ""
+			if mem.Count != 0 {
+				shift = fmt.Sprintf("%s%d", plan9Shift[mem.Shift], mem.Count)
+			}
+			index = fmt.Sprintf("(%sR%d%s)", sign, int(mem.Index), shift)
+		}
+		args[1] = off + base + index
+	}
+
+	// Reverse args, placing dest last.
+	for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
+		args[i], args[j] = args[j], args[i]
+	}
+
+	switch inst.Op &^ 15 {
+	case MOV_EQ:
+		op = "MOVW" + op[3:]
+
+	case LDR_EQ:
+		op = "MOVW" + op[3:] + suffix
+	case LDRB_EQ:
+		op = "MOVB" + op[4:] + suffix
+	case LDRH_EQ:
+		op = "MOVH" + op[4:] + suffix
+
+	case STR_EQ:
+		op = "MOVW" + op[3:] + suffix
+		args[0], args[1] = args[1], args[0]
+	case STRB_EQ:
+		op = "MOVB" + op[4:] + suffix
+		args[0], args[1] = args[1], args[0]
+	case STRH_EQ:
+		op = "MOVH" + op[4:] + suffix
+		args[0], args[1] = args[1], args[0]
+	}
+
+	if args != nil {
+		op += " " + strings.Join(args, ", ")
+	}
+
+	return op
+}
+
+// assembler syntax for the various shifts.
+// @x> is a lie; the assembler uses @> 0
+// instead of @x> 1, but i wanted to be clear that it
+// was a different operation (rotate right extended, not rotate right).
+var plan9Shift = []string{"<<", ">>", "->", "@>", "@x>"}
+
+func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string {
+	switch a := arg.(type) {
+	case Endian:
+
+	case Imm:
+		return fmt.Sprintf("$%d", int(a))
+
+	case Mem:
+
+	case PCRel:
+		addr := uint32(pc) + 8 + uint32(a)
+		if s, base := symname(uint64(addr)); s != "" && uint64(addr) == base {
+			return fmt.Sprintf("%s(SB)", s)
+		}
+		return fmt.Sprintf("%#x", addr)
+
+	case Reg:
+		if a < 16 {
+			return fmt.Sprintf("R%d", int(a))
+		}
+
+	case RegList:
+		var buf bytes.Buffer
+		start := -2
+		end := -2
+		fmt.Fprintf(&buf, "[")
+		flush := func() {
+			if start >= 0 {
+				if buf.Len() > 1 {
+					fmt.Fprintf(&buf, ",")
+				}
+				if start == end {
+					fmt.Fprintf(&buf, "R%d", start)
+				} else {
+					fmt.Fprintf(&buf, "R%d-R%d", start, end)
+				}
+			}
+		}
+		for i := 0; i < 16; i++ {
+			if a&(1<<uint(i)) != 0 {
+				if i == end+1 {
+					end++
+					continue
+				}
+				start = i
+				end = i
+			}
+		}
+		flush()
+		fmt.Fprintf(&buf, "]")
+		return buf.String()
+
+	case RegShift:
+		return fmt.Sprintf("R%d%s$%d", int(a.Reg), plan9Shift[a.Shift], int(a.Count))
+
+	case RegShiftReg:
+		return fmt.Sprintf("R%d%sR%d", int(a.Reg), plan9Shift[a.Shift], int(a.RegCount))
+	}
+	return strings.ToUpper(arg.String())
+}
diff --git a/src/cmd/internal/rsc.io/arm/armasm/tables.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/tables.go
similarity index 100%
rename from src/cmd/internal/rsc.io/arm/armasm/tables.go
rename to src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/tables.go
diff --git a/src/cmd/internal/rsc.io/arm/armasm/testdata/Makefile b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/testdata/Makefile
similarity index 100%
rename from src/cmd/internal/rsc.io/arm/armasm/testdata/Makefile
rename to src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/testdata/Makefile
diff --git a/src/cmd/internal/rsc.io/arm/armasm/testdata/decode.txt b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/testdata/decode.txt
similarity index 100%
rename from src/cmd/internal/rsc.io/arm/armasm/testdata/decode.txt
rename to src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/testdata/decode.txt
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/Makefile b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/Makefile
similarity index 100%
rename from src/cmd/internal/rsc.io/x86/x86asm/Makefile
rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/Makefile
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode.go
new file mode 100644
index 0000000..e4122c1
--- /dev/null
+++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode.go
@@ -0,0 +1,1646 @@
+// 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.
+
+// Table-driven decoding of x86 instructions.
+
+package x86asm
+
+import (
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"runtime"
+)
+
+// Set trace to true to cause the decoder to print the PC sequence
+// of the executed instruction codes. This is typically only useful
+// when you are running a test of a single input case.
+const trace = false
+
+// A decodeOp is a single instruction in the decoder bytecode program.
+//
+// The decodeOps correspond to consuming and conditionally branching
+// on input bytes, consuming additional fields, and then interpreting
+// consumed data as instruction arguments. The names of the xRead and xArg
+// operations are taken from the Intel manual conventions, for example
+// Volume 2, Section 3.1.1, page 487 of
+// http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf
+//
+// The actual decoding program is generated by ../x86map.
+//
+// TODO(rsc): We may be able to merge various of the memory operands
+// since we don't care about, say, the distinction between m80dec and m80bcd.
+// Similarly, mm and mm1 have identical meaning, as do xmm and xmm1.
+
+type decodeOp uint16
+
+const (
+	xFail  decodeOp = iota // invalid instruction (return)
+	xMatch                 // completed match
+	xJump                  // jump to pc
+
+	xCondByte     // switch on instruction byte value
+	xCondSlashR   // read and switch on instruction /r value
+	xCondPrefix   // switch on presence of instruction prefix
+	xCondIs64     // switch on 64-bit processor mode
+	xCondDataSize // switch on operand size
+	xCondAddrSize // switch on address size
+	xCondIsMem    // switch on memory vs register argument
+
+	xSetOp // set instruction opcode
+
+	xReadSlashR // read /r
+	xReadIb     // read ib
+	xReadIw     // read iw
+	xReadId     // read id
+	xReadIo     // read io
+	xReadCb     // read cb
+	xReadCw     // read cw
+	xReadCd     // read cd
+	xReadCp     // read cp
+	xReadCm     // read cm
+
+	xArg1            // arg 1
+	xArg3            // arg 3
+	xArgAL           // arg AL
+	xArgAX           // arg AX
+	xArgCL           // arg CL
+	xArgCR0dashCR7   // arg CR0-CR7
+	xArgCS           // arg CS
+	xArgDR0dashDR7   // arg DR0-DR7
+	xArgDS           // arg DS
+	xArgDX           // arg DX
+	xArgEAX          // arg EAX
+	xArgEDX          // arg EDX
+	xArgES           // arg ES
+	xArgFS           // arg FS
+	xArgGS           // arg GS
+	xArgImm16        // arg imm16
+	xArgImm32        // arg imm32
+	xArgImm64        // arg imm64
+	xArgImm8         // arg imm8
+	xArgImm8u        // arg imm8 but record as unsigned
+	xArgImm16u       // arg imm8 but record as unsigned
+	xArgM            // arg m
+	xArgM128         // arg m128
+	xArgM1428byte    // arg m14/28byte
+	xArgM16          // arg m16
+	xArgM16and16     // arg m16&16
+	xArgM16and32     // arg m16&32
+	xArgM16and64     // arg m16&64
+	xArgM16colon16   // arg m16:16
+	xArgM16colon32   // arg m16:32
+	xArgM16colon64   // arg m16:64
+	xArgM16int       // arg m16int
+	xArgM2byte       // arg m2byte
+	xArgM32          // arg m32
+	xArgM32and32     // arg m32&32
+	xArgM32fp        // arg m32fp
+	xArgM32int       // arg m32int
+	xArgM512byte     // arg m512byte
+	xArgM64          // arg m64
+	xArgM64fp        // arg m64fp
+	xArgM64int       // arg m64int
+	xArgM8           // arg m8
+	xArgM80bcd       // arg m80bcd
+	xArgM80dec       // arg m80dec
+	xArgM80fp        // arg m80fp
+	xArgM94108byte   // arg m94/108byte
+	xArgMm           // arg mm
+	xArgMm1          // arg mm1
+	xArgMm2          // arg mm2
+	xArgMm2M64       // arg mm2/m64
+	xArgMmM32        // arg mm/m32
+	xArgMmM64        // arg mm/m64
+	xArgMem          // arg mem
+	xArgMoffs16      // arg moffs16
+	xArgMoffs32      // arg moffs32
+	xArgMoffs64      // arg moffs64
+	xArgMoffs8       // arg moffs8
+	xArgPtr16colon16 // arg ptr16:16
+	xArgPtr16colon32 // arg ptr16:32
+	xArgR16          // arg r16
+	xArgR16op        // arg r16 with +rw in opcode
+	xArgR32          // arg r32
+	xArgR32M16       // arg r32/m16
+	xArgR32M8        // arg r32/m8
+	xArgR32op        // arg r32 with +rd in opcode
+	xArgR64          // arg r64
+	xArgR64M16       // arg r64/m16
+	xArgR64op        // arg r64 with +rd in opcode
+	xArgR8           // arg r8
+	xArgR8op         // arg r8 with +rb in opcode
+	xArgRAX          // arg RAX
+	xArgRDX          // arg RDX
+	xArgRM           // arg r/m
+	xArgRM16         // arg r/m16
+	xArgRM32         // arg r/m32
+	xArgRM64         // arg r/m64
+	xArgRM8          // arg r/m8
+	xArgReg          // arg reg
+	xArgRegM16       // arg reg/m16
+	xArgRegM32       // arg reg/m32
+	xArgRegM8        // arg reg/m8
+	xArgRel16        // arg rel16
+	xArgRel32        // arg rel32
+	xArgRel8         // arg rel8
+	xArgSS           // arg SS
+	xArgST           // arg ST, aka ST(0)
+	xArgSTi          // arg ST(i) with +i in opcode
+	xArgSreg         // arg Sreg
+	xArgTR0dashTR7   // arg TR0-TR7
+	xArgXmm          // arg xmm
+	xArgXMM0         // arg <XMM0>
+	xArgXmm1         // arg xmm1
+	xArgXmm2         // arg xmm2
+	xArgXmm2M128     // arg xmm2/m128
+	xArgXmm2M16      // arg xmm2/m16
+	xArgXmm2M32      // arg xmm2/m32
+	xArgXmm2M64      // arg xmm2/m64
+	xArgXmmM128      // arg xmm/m128
+	xArgXmmM32       // arg xmm/m32
+	xArgXmmM64       // arg xmm/m64
+	xArgRmf16        // arg r/m16 but force mod=3
+	xArgRmf32        // arg r/m32 but force mod=3
+	xArgRmf64        // arg r/m64 but force mod=3
+)
+
+// instPrefix returns an Inst describing just one prefix byte.
+// It is only used if there is a prefix followed by an unintelligible
+// or invalid instruction byte sequence.
+func instPrefix(b byte, mode int) (Inst, error) {
+	// When tracing it is useful to see what called instPrefix to report an error.
+	if trace {
+		_, file, line, _ := runtime.Caller(1)
+		fmt.Printf("%s:%d\n", file, line)
+	}
+	p := Prefix(b)
+	switch p {
+	case PrefixDataSize:
+		if mode == 16 {
+			p = PrefixData32
+		} else {
+			p = PrefixData16
+		}
+	case PrefixAddrSize:
+		if mode == 32 {
+			p = PrefixAddr16
+		} else {
+			p = PrefixAddr32
+		}
+	}
+	// Note: using composite literal with Prefix key confuses 'bundle' tool.
+	inst := Inst{Len: 1}
+	inst.Prefix = Prefixes{p}
+	return inst, nil
+}
+
+// truncated reports a truncated instruction.
+// For now we use instPrefix but perhaps later we will return
+// a specific error here.
+func truncated(src []byte, mode int) (Inst, error) {
+	//	return Inst{}, len(src), ErrTruncated
+	return instPrefix(src[0], mode) // too long
+}
+
+// These are the errors returned by Decode.
+var (
+	ErrInvalidMode  = errors.New("invalid x86 mode in Decode")
+	ErrTruncated    = errors.New("truncated instruction")
+	ErrUnrecognized = errors.New("unrecognized instruction")
+)
+
+// decoderCover records coverage information for which parts
+// of the byte code have been executed.
+// TODO(rsc): This is for testing. Only use this if a flag is given.
+var decoderCover []bool
+
+// Decode decodes the leading bytes in src as a single instruction.
+// The mode arguments specifies the assumed processor mode:
+// 16, 32, or 64 for 16-, 32-, and 64-bit execution modes.
+func Decode(src []byte, mode int) (inst Inst, err error) {
+	return decode1(src, mode, false)
+}
+
+// decode1 is the implementation of Decode but takes an extra
+// gnuCompat flag to cause it to change its behavior to mimic
+// bugs (or at least unique features) of GNU libopcodes as used
+// by objdump. We don't believe that logic is the right thing to do
+// in general, but when testing against libopcodes it simplifies the
+// comparison if we adjust a few small pieces of logic.
+// The affected logic is in the conditional branch for "mandatory" prefixes,
+// case xCondPrefix.
+func decode1(src []byte, mode int, gnuCompat bool) (Inst, error) {
+	switch mode {
+	case 16, 32, 64:
+		// ok
+		// TODO(rsc): 64-bit mode not tested, probably not working.
+	default:
+		return Inst{}, ErrInvalidMode
+	}
+
+	// Maximum instruction size is 15 bytes.
+	// If we need to read more, return 'truncated instruction.
+	if len(src) > 15 {
+		src = src[:15]
+	}
+
+	var (
+		// prefix decoding information
+		pos           = 0    // position reading src
+		nprefix       = 0    // number of prefixes
+		lockIndex     = -1   // index of LOCK prefix in src and inst.Prefix
+		repIndex      = -1   // index of REP/REPN prefix in src and inst.Prefix
+		segIndex      = -1   // index of Group 2 prefix in src and inst.Prefix
+		dataSizeIndex = -1   // index of Group 3 prefix in src and inst.Prefix
+		addrSizeIndex = -1   // index of Group 4 prefix in src and inst.Prefix
+		rex           Prefix // rex byte if present (or 0)
+		rexUsed       Prefix // bits used in rex byte
+		rexIndex      = -1   // index of rex byte
+
+		addrMode = mode // address mode (width in bits)
+		dataMode = mode // operand mode (width in bits)
+
+		// decoded ModR/M fields
+		haveModrm bool
+		modrm     int
+		mod       int
+		regop     int
+		rm        int
+
+		// if ModR/M is memory reference, Mem form
+		mem     Mem
+		haveMem bool
+
+		// decoded SIB fields
+		haveSIB bool
+		sib     int
+		scale   int
+		index   int
+		base    int
+		displen int
+		dispoff int
+
+		// decoded immediate values
+		imm     int64
+		imm8    int8
+		immc    int64
+		immcpos int
+
+		// output
+		opshift int
+		inst    Inst
+		narg    int // number of arguments written to inst
+	)
+
+	if mode == 64 {
+		dataMode = 32
+	}
+
+	// Prefixes are certainly the most complex and underspecified part of
+	// decoding x86 instructions. Although the manuals say things like
+	// up to four prefixes, one from each group, nearly everyone seems to
+	// agree that in practice as many prefixes as possible, including multiple
+	// from a particular group or repetitions of a given prefix, can be used on
+	// an instruction, provided the total instruction length including prefixes
+	// does not exceed the agreed-upon maximum of 15 bytes.
+	// Everyone also agrees that if one of these prefixes is the LOCK prefix
+	// and the instruction is not one of the instructions that can be used with
+	// the LOCK prefix or if the destination is not a memory operand,
+	// then the instruction is invalid and produces the #UD exception.
+	// However, that is the end of any semblance of agreement.
+	//
+	// What happens if prefixes are given that conflict with other prefixes?
+	// For example, the memory segment overrides CS, DS, ES, FS, GS, SS
+	// conflict with each other: only one segment can be in effect.
+	// Disassemblers seem to agree that later prefixes take priority over
+	// earlier ones. I have not taken the time to write assembly programs
+	// to check to see if the hardware agrees.
+	//
+	// What happens if prefixes are given that have no meaning for the
+	// specific instruction to which they are attached? It depends.
+	// If they really have no meaning, they are ignored. However, a future
+	// processor may assign a different meaning. As a disassembler, we
+	// don't really know whether we're seeing a meaningless prefix or one
+	// whose meaning we simply haven't been told yet.
+	//
+	// Combining the two questions, what happens when conflicting
+	// extension prefixes are given? No one seems to know for sure.
+	// For example, MOVQ is 66 0F D6 /r, MOVDQ2Q is F2 0F D6 /r,
+	// and MOVQ2DQ is F3 0F D6 /r. What is '66 F2 F3 0F D6 /r'?
+	// Which prefix wins? See the xCondPrefix prefix for more.
+	//
+	// Writing assembly test cases to divine which interpretation the
+	// CPU uses might clarify the situation, but more likely it would
+	// make the situation even less clear.
+
+	// Read non-REX prefixes.
+ReadPrefixes:
+	for ; pos < len(src); pos++ {
+		p := Prefix(src[pos])
+		switch p {
+		default:
+			nprefix = pos
+			break ReadPrefixes
+
+		// Group 1 - lock and repeat prefixes
+		// According to Intel, there should only be one from this set,
+		// but according to AMD both can be present.
+		case 0xF0:
+			if lockIndex >= 0 {
+				inst.Prefix[lockIndex] |= PrefixIgnored
+			}
+			lockIndex = pos
+		case 0xF2, 0xF3:
+			if repIndex >= 0 {
+				inst.Prefix[repIndex] |= PrefixIgnored
+			}
+			repIndex = pos
+
+		// Group 2 - segment override / branch hints
+		case 0x26, 0x2E, 0x36, 0x3E:
+			if mode == 64 {
+				p |= PrefixIgnored
+				break
+			}
+			fallthrough
+		case 0x64, 0x65:
+			if segIndex >= 0 {
+				inst.Prefix[segIndex] |= PrefixIgnored
+			}
+			segIndex = pos
+
+		// Group 3 - operand size override
+		case 0x66:
+			if mode == 16 {
+				dataMode = 32
+				p = PrefixData32
+			} else {
+				dataMode = 16
+				p = PrefixData16
+			}
+			if dataSizeIndex >= 0 {
+				inst.Prefix[dataSizeIndex] |= PrefixIgnored
+			}
+			dataSizeIndex = pos
+
+		// Group 4 - address size override
+		case 0x67:
+			if mode == 32 {
+				addrMode = 16
+				p = PrefixAddr16
+			} else {
+				addrMode = 32
+				p = PrefixAddr32
+			}
+			if addrSizeIndex >= 0 {
+				inst.Prefix[addrSizeIndex] |= PrefixIgnored
+			}
+			addrSizeIndex = pos
+		}
+
+		if pos >= len(inst.Prefix) {
+			return instPrefix(src[0], mode) // too long
+		}
+
+		inst.Prefix[pos] = p
+	}
+
+	// Read REX prefix.
+	if pos < len(src) && mode == 64 && Prefix(src[pos]).IsREX() {
+		rex = Prefix(src[pos])
+		rexIndex = pos
+		if pos >= len(inst.Prefix) {
+			return instPrefix(src[0], mode) // too long
+		}
+		inst.Prefix[pos] = rex
+		pos++
+		if rex&PrefixREXW != 0 {
+			dataMode = 64
+			if dataSizeIndex >= 0 {
+				inst.Prefix[dataSizeIndex] |= PrefixIgnored
+			}
+		}
+	}
+
+	// Decode instruction stream, interpreting decoding instructions.
+	// opshift gives the shift to use when saving the next
+	// opcode byte into inst.Opcode.
+	opshift = 24
+	if decoderCover == nil {
+		decoderCover = make([]bool, len(decoder))
+	}
+
+	// Decode loop, executing decoder program.
+	var oldPC, prevPC int
+Decode:
+	for pc := 1; ; { // TODO uint
+		oldPC = prevPC
+		prevPC = pc
+		if trace {
+			println("run", pc)
+		}
+		x := decoder[pc]
+		decoderCover[pc] = true
+		pc++
+
+		// Read and decode ModR/M if needed by opcode.
+		switch decodeOp(x) {
+		case xCondSlashR, xReadSlashR:
+			if haveModrm {
+				return Inst{Len: pos}, errInternal
+			}
+			haveModrm = true
+			if pos >= len(src) {
+				return truncated(src, mode)
+			}
+			modrm = int(src[pos])
+			pos++
+			if opshift >= 0 {
+				inst.Opcode |= uint32(modrm) << uint(opshift)
+				opshift -= 8
+			}
+			mod = modrm >> 6
+			regop = (modrm >> 3) & 07
+			rm = modrm & 07
+			if rex&PrefixREXR != 0 {
+				rexUsed |= PrefixREXR
+				regop |= 8
+			}
+			if addrMode == 16 {
+				// 16-bit modrm form
+				if mod != 3 {
+					haveMem = true
+					mem = addr16[rm]
+					if rm == 6 && mod == 0 {
+						mem.Base = 0
+					}
+
+					// Consume disp16 if present.
+					if mod == 0 && rm == 6 || mod == 2 {
+						if pos+2 > len(src) {
+							return truncated(src, mode)
+						}
+						mem.Disp = int64(binary.LittleEndian.Uint16(src[pos:]))
+						pos += 2
+					}
+
+					// Consume disp8 if present.
+					if mod == 1 {
+						if pos >= len(src) {
+							return truncated(src, mode)
+						}
+						mem.Disp = int64(int8(src[pos]))
+						pos++
+					}
+				}
+			} else {
+				haveMem = mod != 3
+
+				// 32-bit or 64-bit form
+				// Consume SIB encoding if present.
+				if rm == 4 && mod != 3 {
+					haveSIB = true
+					if pos >= len(src) {
+						return truncated(src, mode)
+					}
+					sib = int(src[pos])
+					pos++
+					if opshift >= 0 {
+						inst.Opcode |= uint32(sib) << uint(opshift)
+						opshift -= 8
+					}
+					scale = sib >> 6
+					index = (sib >> 3) & 07
+					base = sib & 07
+					if rex&PrefixREXB != 0 {
+						rexUsed |= PrefixREXB
+						base |= 8
+					}
+					if rex&PrefixREXX != 0 {
+						rexUsed |= PrefixREXX
+						index |= 8
+					}
+
+					mem.Scale = 1 << uint(scale)
+					if index == 4 {
+						// no mem.Index
+					} else {
+						mem.Index = baseRegForBits(addrMode) + Reg(index)
+					}
+					if base&7 == 5 && mod == 0 {
+						// no mem.Base
+					} else {
+						mem.Base = baseRegForBits(addrMode) + Reg(base)
+					}
+				} else {
+					if rex&PrefixREXB != 0 {
+						rexUsed |= PrefixREXB
+						rm |= 8
+					}
+					if mod == 0 && rm&7 == 5 || rm&7 == 4 {
+						// base omitted
+					} else if mod != 3 {
+						mem.Base = baseRegForBits(addrMode) + Reg(rm)
+					}
+				}
+
+				// Consume disp32 if present.
+				if mod == 0 && (rm&7 == 5 || haveSIB && base&7 == 5) || mod == 2 {
+					if pos+4 > len(src) {
+						return truncated(src, mode)
+					}
+					dispoff = pos
+					displen = 4
+					mem.Disp = int64(binary.LittleEndian.Uint32(src[pos:]))
+					pos += 4
+				}
+
+				// Consume disp8 if present.
+				if mod == 1 {
+					if pos >= len(src) {
+						return truncated(src, mode)
+					}
+					dispoff = pos
+					displen = 1
+					mem.Disp = int64(int8(src[pos]))
+					pos++
+				}
+
+				// In 64-bit, mod=0 rm=5 is PC-relative instead of just disp.
+				// See Vol 2A. Table 2-7.
+				if mode == 64 && mod == 0 && rm&7 == 5 {
+					if addrMode == 32 {
+						mem.Base = EIP
+					} else {
+						mem.Base = RIP
+					}
+				}
+			}
+
+			if segIndex >= 0 {
+				mem.Segment = prefixToSegment(inst.Prefix[segIndex])
+			}
+		}
+
+		// Execute single opcode.
+		switch decodeOp(x) {
+		default:
+			println("bad op", x, "at", pc-1, "from", oldPC)
+			return Inst{Len: pos}, errInternal
+
+		case xFail:
+			inst.Op = 0
+			break Decode
+
+		case xMatch:
+			break Decode
+
+		case xJump:
+			pc = int(decoder[pc])
+
+		// Conditional branches.
+
+		case xCondByte:
+			if pos >= len(src) {
+				return truncated(src, mode)
+			}
+			b := src[pos]
+			n := int(decoder[pc])
+			pc++
+			for i := 0; i < n; i++ {
+				xb, xpc := decoder[pc], int(decoder[pc+1])
+				pc += 2
+				if b == byte(xb) {
+					pc = xpc
+					pos++
+					if opshift >= 0 {
+						inst.Opcode |= uint32(b) << uint(opshift)
+						opshift -= 8
+					}
+					continue Decode
+				}
+			}
+			// xCondByte is the only conditional with a fall through,
+			// so that it can be used to pick off special cases before
+			// an xCondSlash. If the fallthrough instruction is xFail,
+			// advance the position so that the decoded instruction
+			// size includes the byte we just compared against.
+			if decodeOp(decoder[pc]) == xJump {
+				pc = int(decoder[pc+1])
+			}
+			if decodeOp(decoder[pc]) == xFail {
+				pos++
+			}
+
+		case xCondIs64:
+			if mode == 64 {
+				pc = int(decoder[pc+1])
+			} else {
+				pc = int(decoder[pc])
+			}
+
+		case xCondIsMem:
+			mem := haveMem
+			if !haveModrm {
+				if pos >= len(src) {
+					return instPrefix(src[0], mode) // too long
+				}
+				mem = src[pos]>>6 != 3
+			}
+			if mem {
+				pc = int(decoder[pc+1])
+			} else {
+				pc = int(decoder[pc])
+			}
+
+		case xCondDataSize:
+			switch dataMode {
+			case 16:
+				if dataSizeIndex >= 0 {
+					inst.Prefix[dataSizeIndex] |= PrefixImplicit
+				}
+				pc = int(decoder[pc])
+			case 32:
+				if dataSizeIndex >= 0 {
+					inst.Prefix[dataSizeIndex] |= PrefixImplicit
+				}
+				pc = int(decoder[pc+1])
+			case 64:
+				rexUsed |= PrefixREXW
+				pc = int(decoder[pc+2])
+			}
+
+		case xCondAddrSize:
+			switch addrMode {
+			case 16:
+				if addrSizeIndex >= 0 {
+					inst.Prefix[addrSizeIndex] |= PrefixImplicit
+				}
+				pc = int(decoder[pc])
+			case 32:
+				if addrSizeIndex >= 0 {
+					inst.Prefix[addrSizeIndex] |= PrefixImplicit
+				}
+				pc = int(decoder[pc+1])
+			case 64:
+				pc = int(decoder[pc+2])
+			}
+
+		case xCondPrefix:
+			// Conditional branch based on presence or absence of prefixes.
+			// The conflict cases here are completely undocumented and
+			// differ significantly between GNU libopcodes and Intel xed.
+			// I have not written assembly code to divine what various CPUs
+			// do, but it wouldn't surprise me if they are not consistent either.
+			//
+			// The basic idea is to switch on the presence of a prefix, so that
+			// for example:
+			//
+			//	xCondPrefix, 4
+			//	0xF3, 123,
+			//	0xF2, 234,
+			//	0x66, 345,
+			//	0, 456
+			//
+			// branch to 123 if the F3 prefix is present, 234 if the F2 prefix
+			// is present, 66 if the 345 prefix is present, and 456 otherwise.
+			// The prefixes are given in descending order so that the 0 will be last.
+			//
+			// It is unclear what should happen if multiple conditions are
+			// satisfied: what if F2 and F3 are both present, or if 66 and F2
+			// are present, or if all three are present? The one chosen becomes
+			// part of the opcode and the others do not. Perhaps the answer
+			// depends on the specific opcodes in question.
+			//
+			// The only clear example is that CRC32 is F2 0F 38 F1 /r, and
+			// it comes in 16-bit and 32-bit forms based on the 66 prefix,
+			// so 66 F2 0F 38 F1 /r should be treated as F2 taking priority,
+			// with the 66 being only an operand size override, and probably
+			// F2 66 0F 38 F1 /r should be treated the same.
+			// Perhaps that rule is specific to the case of CRC32, since no
+			// 66 0F 38 F1 instruction is defined (today) (that we know of).
+			// However, both libopcodes and xed seem to generalize this
+			// example and choose F2/F3 in preference to 66, and we
+			// do the same.
+			//
+			// Next, what if both F2 and F3 are present? Which wins?
+			// The Intel xed rule, and ours, is that the one that occurs last wins.
+			// The GNU libopcodes rule, which we implement only in gnuCompat mode,
+			// is that F3 beats F2 unless F3 has no special meaning, in which
+			// case F3 can be a modified on an F2 special meaning.
+			//
+			// Concretely,
+			//	66 0F D6 /r is MOVQ
+			//	F2 0F D6 /r is MOVDQ2Q
+			//	F3 0F D6 /r is MOVQ2DQ.
+			//
+			//	F2 66 0F D6 /r is 66 + MOVDQ2Q always.
+			//	66 F2 0F D6 /r is 66 + MOVDQ2Q always.
+			//	F3 66 0F D6 /r is 66 + MOVQ2DQ always.
+			//	66 F3 0F D6 /r is 66 + MOVQ2DQ always.
+			//	F2 F3 0F D6 /r is F2 + MOVQ2DQ always.
+			//	F3 F2 0F D6 /r is F3 + MOVQ2DQ in Intel xed, but F2 + MOVQ2DQ in GNU libopcodes.
+			//	Adding 66 anywhere in the prefix section of the
+			//	last two cases does not change the outcome.
+			//
+			// Finally, what if there is a variant in which 66 is a mandatory
+			// prefix rather than an operand size override, but we know of
+			// no corresponding F2/F3 form, and we see both F2/F3 and 66.
+			// Does F2/F3 still take priority, so that the result is an unknown
+			// instruction, or does the 66 take priority, so that the extended
+			// 66 instruction should be interpreted as having a REP/REPN prefix?
+			// Intel xed does the former and GNU libopcodes does the latter.
+			// We side with Intel xed, unless we are trying to match libopcodes
+			// more closely during the comparison-based test suite.
+			//
+			// In 64-bit mode REX.W is another valid prefix to test for, but
+			// there is less ambiguity about that. When present, REX.W is
+			// always the first entry in the table.
+			n := int(decoder[pc])
+			pc++
+			sawF3 := false
+			for j := 0; j < n; j++ {
+				prefix := Prefix(decoder[pc+2*j])
+				if prefix.IsREX() {
+					rexUsed |= prefix
+					if rex&prefix == prefix {
+						pc = int(decoder[pc+2*j+1])
+						continue Decode
+					}
+					continue
+				}
+				ok := false
+				if prefix == 0 {
+					ok = true
+				} else if prefix.IsREX() {
+					rexUsed |= prefix
+					if rex&prefix == prefix {
+						ok = true
+					}
+				} else {
+					if prefix == 0xF3 {
+						sawF3 = true
+					}
+					switch prefix {
+					case PrefixLOCK:
+						if lockIndex >= 0 {
+							inst.Prefix[lockIndex] |= PrefixImplicit
+							ok = true
+						}
+					case PrefixREP, PrefixREPN:
+						if repIndex >= 0 && inst.Prefix[repIndex]&0xFF == prefix {
+							inst.Prefix[repIndex] |= PrefixImplicit
+							ok = true
+						}
+						if gnuCompat && !ok && prefix == 0xF3 && repIndex >= 0 && (j+1 >= n || decoder[pc+2*(j+1)] != 0xF2) {
+							// Check to see if earlier prefix F3 is present.
+							for i := repIndex - 1; i >= 0; i-- {
+								if inst.Prefix[i]&0xFF == prefix {
+									inst.Prefix[i] |= PrefixImplicit
+									ok = true
+								}
+							}
+						}
+						if gnuCompat && !ok && prefix == 0xF2 && repIndex >= 0 && !sawF3 && inst.Prefix[repIndex]&0xFF == 0xF3 {
+							// Check to see if earlier prefix F2 is present.
+							for i := repIndex - 1; i >= 0; i-- {
+								if inst.Prefix[i]&0xFF == prefix {
+									inst.Prefix[i] |= PrefixImplicit
+									ok = true
+								}
+							}
+						}
+					case PrefixCS, PrefixDS, PrefixES, PrefixFS, PrefixGS, PrefixSS:
+						if segIndex >= 0 && inst.Prefix[segIndex]&0xFF == prefix {
+							inst.Prefix[segIndex] |= PrefixImplicit
+							ok = true
+						}
+					case PrefixDataSize:
+						// Looking for 66 mandatory prefix.
+						// The F2/F3 mandatory prefixes take priority when both are present.
+						// If we got this far in the xCondPrefix table and an F2/F3 is present,
+						// it means the table didn't have any entry for that prefix. But if 66 has
+						// special meaning, perhaps F2/F3 have special meaning that we don't know.
+						// Intel xed works this way, treating the F2/F3 as inhibiting the 66.
+						// GNU libopcodes allows the 66 to match. We do what Intel xed does
+						// except in gnuCompat mode.
+						if repIndex >= 0 && !gnuCompat {
+							inst.Op = 0
+							break Decode
+						}
+						if dataSizeIndex >= 0 {
+							inst.Prefix[dataSizeIndex] |= PrefixImplicit
+							ok = true
+						}
+					case PrefixAddrSize:
+						if addrSizeIndex >= 0 {
+							inst.Prefix[addrSizeIndex] |= PrefixImplicit
+							ok = true
+						}
+					}
+				}
+				if ok {
+					pc = int(decoder[pc+2*j+1])
+					continue Decode
+				}
+			}
+			inst.Op = 0
+			break Decode
+
+		case xCondSlashR:
+			pc = int(decoder[pc+regop&7])
+
+		// Input.
+
+		case xReadSlashR:
+			// done above
+
+		case xReadIb:
+			if pos >= len(src) {
+				return truncated(src, mode)
+			}
+			imm8 = int8(src[pos])
+			pos++
+
+		case xReadIw:
+			if pos+2 > len(src) {
+				return truncated(src, mode)
+			}
+			imm = int64(binary.LittleEndian.Uint16(src[pos:]))
+			pos += 2
+
+		case xReadId:
+			if pos+4 > len(src) {
+				return truncated(src, mode)
+			}
+			imm = int64(binary.LittleEndian.Uint32(src[pos:]))
+			pos += 4
+
+		case xReadIo:
+			if pos+8 > len(src) {
+				return truncated(src, mode)
+			}
+			imm = int64(binary.LittleEndian.Uint64(src[pos:]))
+			pos += 8
+
+		case xReadCb:
+			if pos >= len(src) {
+				return truncated(src, mode)
+			}
+			immcpos = pos
+			immc = int64(src[pos])
+			pos++
+
+		case xReadCw:
+			if pos+2 > len(src) {
+				return truncated(src, mode)
+			}
+			immcpos = pos
+			immc = int64(binary.LittleEndian.Uint16(src[pos:]))
+			pos += 2
+
+		case xReadCm:
+			immcpos = pos
+			if addrMode == 16 {
+				if pos+2 > len(src) {
+					return truncated(src, mode)
+				}
+				immc = int64(binary.LittleEndian.Uint16(src[pos:]))
+				pos += 2
+			} else if addrMode == 32 {
+				if pos+4 > len(src) {
+					return truncated(src, mode)
+				}
+				immc = int64(binary.LittleEndian.Uint32(src[pos:]))
+				pos += 4
+			} else {
+				if pos+8 > len(src) {
+					return truncated(src, mode)
+				}
+				immc = int64(binary.LittleEndian.Uint64(src[pos:]))
+				pos += 8
+			}
+		case xReadCd:
+			immcpos = pos
+			if pos+4 > len(src) {
+				return truncated(src, mode)
+			}
+			immc = int64(binary.LittleEndian.Uint32(src[pos:]))
+			pos += 4
+
+		case xReadCp:
+			immcpos = pos
+			if pos+6 > len(src) {
+				return truncated(src, mode)
+			}
+			w := binary.LittleEndian.Uint32(src[pos:])
+			w2 := binary.LittleEndian.Uint16(src[pos+4:])
+			immc = int64(w2)<<32 | int64(w)
+			pos += 6
+
+		// Output.
+
+		case xSetOp:
+			inst.Op = Op(decoder[pc])
+			pc++
+
+		case xArg1,
+			xArg3,
+			xArgAL,
+			xArgAX,
+			xArgCL,
+			xArgCS,
+			xArgDS,
+			xArgDX,
+			xArgEAX,
+			xArgEDX,
+			xArgES,
+			xArgFS,
+			xArgGS,
+			xArgRAX,
+			xArgRDX,
+			xArgSS,
+			xArgST,
+			xArgXMM0:
+			inst.Args[narg] = fixedArg[x]
+			narg++
+
+		case xArgImm8:
+			inst.Args[narg] = Imm(imm8)
+			narg++
+
+		case xArgImm8u:
+			inst.Args[narg] = Imm(uint8(imm8))
+			narg++
+
+		case xArgImm16:
+			inst.Args[narg] = Imm(int16(imm))
+			narg++
+
+		case xArgImm16u:
+			inst.Args[narg] = Imm(uint16(imm))
+			narg++
+
+		case xArgImm32:
+			inst.Args[narg] = Imm(int32(imm))
+			narg++
+
+		case xArgImm64:
+			inst.Args[narg] = Imm(imm)
+			narg++
+
+		case xArgM,
+			xArgM128,
+			xArgM1428byte,
+			xArgM16,
+			xArgM16and16,
+			xArgM16and32,
+			xArgM16and64,
+			xArgM16colon16,
+			xArgM16colon32,
+			xArgM16colon64,
+			xArgM16int,
+			xArgM2byte,
+			xArgM32,
+			xArgM32and32,
+			xArgM32fp,
+			xArgM32int,
+			xArgM512byte,
+			xArgM64,
+			xArgM64fp,
+			xArgM64int,
+			xArgM8,
+			xArgM80bcd,
+			xArgM80dec,
+			xArgM80fp,
+			xArgM94108byte,
+			xArgMem:
+			if !haveMem {
+				inst.Op = 0
+				break Decode
+			}
+			inst.Args[narg] = mem
+			inst.MemBytes = int(memBytes[decodeOp(x)])
+			if mem.Base == RIP {
+				inst.PCRel = displen
+				inst.PCRelOff = dispoff
+			}
+			narg++
+
+		case xArgPtr16colon16:
+			inst.Args[narg] = Imm(immc >> 16)
+			inst.Args[narg+1] = Imm(immc & (1<<16 - 1))
+			narg += 2
+
+		case xArgPtr16colon32:
+			inst.Args[narg] = Imm(immc >> 32)
+			inst.Args[narg+1] = Imm(immc & (1<<32 - 1))
+			narg += 2
+
+		case xArgMoffs8, xArgMoffs16, xArgMoffs32, xArgMoffs64:
+			// TODO(rsc): Can address be 64 bits?
+			mem = Mem{Disp: int64(immc)}
+			if segIndex >= 0 {
+				mem.Segment = prefixToSegment(inst.Prefix[segIndex])
+				inst.Prefix[segIndex] |= PrefixImplicit
+			}
+			inst.Args[narg] = mem
+			inst.MemBytes = int(memBytes[decodeOp(x)])
+			if mem.Base == RIP {
+				inst.PCRel = displen
+				inst.PCRelOff = dispoff
+			}
+			narg++
+
+		case xArgR8, xArgR16, xArgR32, xArgR64, xArgXmm, xArgXmm1, xArgDR0dashDR7:
+			base := baseReg[x]
+			index := Reg(regop)
+			if rex != 0 && base == AL && index >= 4 {
+				rexUsed |= PrefixREX
+				index -= 4
+				base = SPB
+			}
+			inst.Args[narg] = base + index
+			narg++
+
+		case xArgMm, xArgMm1, xArgTR0dashTR7:
+			inst.Args[narg] = baseReg[x] + Reg(regop&7)
+			narg++
+
+		case xArgCR0dashCR7:
+			// AMD documents an extension that the LOCK prefix
+			// can be used in place of a REX prefix in order to access
+			// CR8 from 32-bit mode. The LOCK prefix is allowed in
+			// all modes, provided the corresponding CPUID bit is set.
+			if lockIndex >= 0 {
+				inst.Prefix[lockIndex] |= PrefixImplicit
+				regop += 8
+			}
+			inst.Args[narg] = CR0 + Reg(regop)
+			narg++
+
+		case xArgSreg:
+			regop &= 7
+			if regop >= 6 {
+				inst.Op = 0
+				break Decode
+			}
+			inst.Args[narg] = ES + Reg(regop)
+			narg++
+
+		case xArgRmf16, xArgRmf32, xArgRmf64:
+			base := baseReg[x]
+			index := Reg(modrm & 07)
+			if rex&PrefixREXB != 0 {
+				rexUsed |= PrefixREXB
+				index += 8
+			}
+			inst.Args[narg] = base + index
+			narg++
+
+		case xArgR8op, xArgR16op, xArgR32op, xArgR64op, xArgSTi:
+			n := inst.Opcode >> uint(opshift+8) & 07
+			base := baseReg[x]
+			index := Reg(n)
+			if rex&PrefixREXB != 0 && decodeOp(x) != xArgSTi {
+				rexUsed |= PrefixREXB
+				index += 8
+			}
+			if rex != 0 && base == AL && index >= 4 {
+				rexUsed |= PrefixREX
+				index -= 4
+				base = SPB
+			}
+			inst.Args[narg] = base + index
+			narg++
+
+		case xArgRM8, xArgRM16, xArgRM32, xArgRM64, xArgR32M16, xArgR32M8, xArgR64M16,
+			xArgMmM32, xArgMmM64, xArgMm2M64,
+			xArgXmm2M16, xArgXmm2M32, xArgXmm2M64, xArgXmmM64, xArgXmmM128, xArgXmmM32, xArgXmm2M128:
+			if haveMem {
+				inst.Args[narg] = mem
+				inst.MemBytes = int(memBytes[decodeOp(x)])
+				if mem.Base == RIP {
+					inst.PCRel = displen
+					inst.PCRelOff = dispoff
+				}
+			} else {
+				base := baseReg[x]
+				index := Reg(rm)
+				switch decodeOp(x) {
+				case xArgMmM32, xArgMmM64, xArgMm2M64:
+					// There are only 8 MMX registers, so these ignore the REX.X bit.
+					index &= 7
+				case xArgRM8:
+					if rex != 0 && index >= 4 {
+						rexUsed |= PrefixREX
+						index -= 4
+						base = SPB
+					}
+				}
+				inst.Args[narg] = base + index
+			}
+			narg++
+
+		case xArgMm2: // register only; TODO(rsc): Handle with tag modrm_regonly tag
+			if haveMem {
+				inst.Op = 0
+				break Decode
+			}
+			inst.Args[narg] = baseReg[x] + Reg(rm&7)
+			narg++
+
+		case xArgXmm2: // register only; TODO(rsc): Handle with tag modrm_regonly tag
+			if haveMem {
+				inst.Op = 0
+				break Decode
+			}
+			inst.Args[narg] = baseReg[x] + Reg(rm)
+			narg++
+
+		case xArgRel8:
+			inst.PCRelOff = immcpos
+			inst.PCRel = 1
+			inst.Args[narg] = Rel(int8(immc))
+			narg++
+
+		case xArgRel16:
+			inst.PCRelOff = immcpos
+			inst.PCRel = 2
+			inst.Args[narg] = Rel(int16(immc))
+			narg++
+
+		case xArgRel32:
+			inst.PCRelOff = immcpos
+			inst.PCRel = 4
+			inst.Args[narg] = Rel(int32(immc))
+			narg++
+		}
+	}
+
+	if inst.Op == 0 {
+		// Invalid instruction.
+		if nprefix > 0 {
+			return instPrefix(src[0], mode) // invalid instruction
+		}
+		return Inst{Len: pos}, ErrUnrecognized
+	}
+
+	// Matched! Hooray!
+
+	// 90 decodes as XCHG EAX, EAX but is NOP.
+	// 66 90 decodes as XCHG AX, AX and is NOP too.
+	// 48 90 decodes as XCHG RAX, RAX and is NOP too.
+	// 43 90 decodes as XCHG R8D, EAX and is *not* NOP.
+	// F3 90 decodes as REP XCHG EAX, EAX but is PAUSE.
+	// It's all too special to handle in the decoding tables, at least for now.
+	if inst.Op == XCHG && inst.Opcode>>24 == 0x90 {
+		if inst.Args[0] == RAX || inst.Args[0] == EAX || inst.Args[0] == AX {
+			inst.Op = NOP
+			if dataSizeIndex >= 0 {
+				inst.Prefix[dataSizeIndex] &^= PrefixImplicit
+			}
+			inst.Args[0] = nil
+			inst.Args[1] = nil
+		}
+		if repIndex >= 0 && inst.Prefix[repIndex] == 0xF3 {
+			inst.Prefix[repIndex] |= PrefixImplicit
+			inst.Op = PAUSE
+			inst.Args[0] = nil
+			inst.Args[1] = nil
+		} else if gnuCompat {
+			for i := nprefix - 1; i >= 0; i-- {
+				if inst.Prefix[i]&0xFF == 0xF3 {
+					inst.Prefix[i] |= PrefixImplicit
+					inst.Op = PAUSE
+					inst.Args[0] = nil
+					inst.Args[1] = nil
+					break
+				}
+			}
+		}
+	}
+
+	// defaultSeg returns the default segment for an implicit
+	// memory reference: the final override if present, or else DS.
+	defaultSeg := func() Reg {
+		if segIndex >= 0 {
+			inst.Prefix[segIndex] |= PrefixImplicit
+			return prefixToSegment(inst.Prefix[segIndex])
+		}
+		return DS
+	}
+
+	// Add implicit arguments not present in the tables.
+	// Normally we shy away from making implicit arguments explicit,
+	// following the Intel manuals, but adding the arguments seems
+	// the best way to express the effect of the segment override prefixes.
+	// TODO(rsc): Perhaps add these to the tables and
+	// create bytecode instructions for them.
+	usedAddrSize := false
+	switch inst.Op {
+	case INSB, INSW, INSD:
+		inst.Args[0] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}
+		inst.Args[1] = DX
+		usedAddrSize = true
+
+	case OUTSB, OUTSW, OUTSD:
+		inst.Args[0] = DX
+		inst.Args[1] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX}
+		usedAddrSize = true
+
+	case MOVSB, MOVSW, MOVSD, MOVSQ:
+		inst.Args[0] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}
+		inst.Args[1] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX}
+		usedAddrSize = true
+
+	case CMPSB, CMPSW, CMPSD, CMPSQ:
+		inst.Args[0] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX}
+		inst.Args[1] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}
+		usedAddrSize = true
+
+	case LODSB, LODSW, LODSD, LODSQ:
+		switch inst.Op {
+		case LODSB:
+			inst.Args[0] = AL
+		case LODSW:
+			inst.Args[0] = AX
+		case LODSD:
+			inst.Args[0] = EAX
+		case LODSQ:
+			inst.Args[0] = RAX
+		}
+		inst.Args[1] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX}
+		usedAddrSize = true
+
+	case STOSB, STOSW, STOSD, STOSQ:
+		inst.Args[0] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}
+		switch inst.Op {
+		case STOSB:
+			inst.Args[1] = AL
+		case STOSW:
+			inst.Args[1] = AX
+		case STOSD:
+			inst.Args[1] = EAX
+		case STOSQ:
+			inst.Args[1] = RAX
+		}
+		usedAddrSize = true
+
+	case SCASB, SCASW, SCASD, SCASQ:
+		inst.Args[1] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}
+		switch inst.Op {
+		case SCASB:
+			inst.Args[0] = AL
+		case SCASW:
+			inst.Args[0] = AX
+		case SCASD:
+			inst.Args[0] = EAX
+		case SCASQ:
+			inst.Args[0] = RAX
+		}
+		usedAddrSize = true
+
+	case XLATB:
+		inst.Args[0] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + BX - AX}
+		usedAddrSize = true
+	}
+
+	// If we used the address size annotation to construct the
+	// argument list, mark that prefix as implicit: it doesn't need
+	// to be shown when printing the instruction.
+	if haveMem || usedAddrSize {
+		if addrSizeIndex >= 0 {
+			inst.Prefix[addrSizeIndex] |= PrefixImplicit
+		}
+	}
+
+	// Similarly, if there's some memory operand, the segment
+	// will be shown there and doesn't need to be shown as an
+	// explicit prefix.
+	if haveMem {
+		if segIndex >= 0 {
+			inst.Prefix[segIndex] |= PrefixImplicit
+		}
+	}
+
+	// Branch predict prefixes are overloaded segment prefixes,
+	// since segment prefixes don't make sense on conditional jumps.
+	// Rewrite final instance to prediction prefix.
+	// The set of instructions to which the prefixes apply (other then the
+	// Jcc conditional jumps) is not 100% clear from the manuals, but
+	// the disassemblers seem to agree about the LOOP and JCXZ instructions,
+	// so we'll follow along.
+	// TODO(rsc): Perhaps this instruction class should be derived from the CSV.
+	if isCondJmp[inst.Op] || isLoop[inst.Op] || inst.Op == JCXZ || inst.Op == JECXZ || inst.Op == JRCXZ {
+	PredictLoop:
+		for i := nprefix - 1; i >= 0; i-- {
+			p := inst.Prefix[i]
+			switch p & 0xFF {
+			case PrefixCS:
+				inst.Prefix[i] = PrefixPN
+				break PredictLoop
+			case PrefixDS:
+				inst.Prefix[i] = PrefixPT
+				break PredictLoop
+			}
+		}
+	}
+
+	// The BND prefix is part of the Intel Memory Protection Extensions (MPX).
+	// A REPN applied to certain control transfers is a BND prefix to bound
+	// the range of possible destinations. There's surprisingly little documentation
+	// about this, so we just do what libopcodes and xed agree on.
+	// In particular, it's unclear why a REPN applied to LOOP or JCXZ instructions
+	// does not turn into a BND.
+	// TODO(rsc): Perhaps this instruction class should be derived from the CSV.
+	if isCondJmp[inst.Op] || inst.Op == JMP || inst.Op == CALL || inst.Op == RET {
+		for i := nprefix - 1; i >= 0; i-- {
+			p := inst.Prefix[i]
+			if p&^PrefixIgnored == PrefixREPN {
+				inst.Prefix[i] = PrefixBND
+				break
+			}
+		}
+	}
+
+	// The LOCK prefix only applies to certain instructions, and then only
+	// to instances of the instruction with a memory destination.
+	// Other uses of LOCK are invalid and cause a processor exception,
+	// in contrast to the "just ignore it" spirit applied to all other prefixes.
+	// Mark invalid lock prefixes.
+	hasLock := false
+	if lockIndex >= 0 && inst.Prefix[lockIndex]&PrefixImplicit == 0 {
+		switch inst.Op {
+		// TODO(rsc): Perhaps this instruction class should be derived from the CSV.
+		case ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCHG8B, CMPXCHG16B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, XCHG:
+			if isMem(inst.Args[0]) {
+				hasLock = true
+				break
+			}
+			fallthrough
+		default:
+			inst.Prefix[lockIndex] |= PrefixInvalid
+		}
+	}
+
+	// In certain cases, all of which require a memory destination,
+	// the REPN and REP prefixes are interpreted as XACQUIRE and XRELEASE
+	// from the Intel Transactional Synchroniation Extensions (TSX).
+	//
+	// The specific rules are:
+	// (1) Any instruction with a valid LOCK prefix can have XACQUIRE or XRELEASE.
+	// (2) Any XCHG, which always has an implicit LOCK, can have XACQUIRE or XRELEASE.
+	// (3) Any 0x88-, 0x89-, 0xC6-, or 0xC7-opcode MOV can have XRELEASE.
+	if isMem(inst.Args[0]) {
+		if inst.Op == XCHG {
+			hasLock = true
+		}
+
+		for i := len(inst.Prefix) - 1; i >= 0; i-- {
+			p := inst.Prefix[i] &^ PrefixIgnored
+			switch p {
+			case PrefixREPN:
+				if hasLock {
+					inst.Prefix[i] = inst.Prefix[i]&PrefixIgnored | PrefixXACQUIRE
+				}
+
+			case PrefixREP:
+				if hasLock {
+					inst.Prefix[i] = inst.Prefix[i]&PrefixIgnored | PrefixXRELEASE
+				}
+
+				if inst.Op == MOV {
+					op := (inst.Opcode >> 24) &^ 1
+					if op == 0x88 || op == 0xC6 {
+						inst.Prefix[i] = inst.Prefix[i]&PrefixIgnored | PrefixXRELEASE
+					}
+				}
+			}
+		}
+	}
+
+	// If REP is used on a non-REP-able instruction, mark the prefix as ignored.
+	if repIndex >= 0 {
+		switch inst.Prefix[repIndex] {
+		case PrefixREP, PrefixREPN:
+			switch inst.Op {
+			// According to the manuals, the REP/REPE prefix applies to all of these,
+			// while the REPN applies only to some of them. However, both libopcodes
+			// and xed show both prefixes explicitly for all instructions, so we do the same.
+			// TODO(rsc): Perhaps this instruction class should be derived from the CSV.
+			case INSB, INSW, INSD,
+				MOVSB, MOVSW, MOVSD, MOVSQ,
+				OUTSB, OUTSW, OUTSD,
+				LODSB, LODSW, LODSD, LODSQ,
+				CMPSB, CMPSW, CMPSD, CMPSQ,
+				SCASB, SCASW, SCASD, SCASQ,
+				STOSB, STOSW, STOSD, STOSQ:
+				// ok
+			default:
+				inst.Prefix[repIndex] |= PrefixIgnored
+			}
+		}
+	}
+
+	// If REX was present, mark implicit if all the 1 bits were consumed.
+	if rexIndex >= 0 {
+		if rexUsed != 0 {
+			rexUsed |= PrefixREX
+		}
+		if rex&^rexUsed == 0 {
+			inst.Prefix[rexIndex] |= PrefixImplicit
+		}
+	}
+
+	inst.DataSize = dataMode
+	inst.AddrSize = addrMode
+	inst.Mode = mode
+	inst.Len = pos
+	return inst, nil
+}
+
+var errInternal = errors.New("internal error")
+
+// addr16 records the eight 16-bit addressing modes.
+var addr16 = [8]Mem{
+	{Base: BX, Scale: 1, Index: SI},
+	{Base: BX, Scale: 1, Index: DI},
+	{Base: BP, Scale: 1, Index: SI},
+	{Base: BP, Scale: 1, Index: DI},
+	{Base: SI},
+	{Base: DI},
+	{Base: BP},
+	{Base: BX},
+}
+
+// baseReg returns the base register for a given register size in bits.
+func baseRegForBits(bits int) Reg {
+	switch bits {
+	case 8:
+		return AL
+	case 16:
+		return AX
+	case 32:
+		return EAX
+	case 64:
+		return RAX
+	}
+	return 0
+}
+
+// baseReg records the base register for argument types that specify
+// a range of registers indexed by op, regop, or rm.
+var baseReg = [...]Reg{
+	xArgDR0dashDR7: DR0,
+	xArgMm1:        M0,
+	xArgMm2:        M0,
+	xArgMm2M64:     M0,
+	xArgMm:         M0,
+	xArgMmM32:      M0,
+	xArgMmM64:      M0,
+	xArgR16:        AX,
+	xArgR16op:      AX,
+	xArgR32:        EAX,
+	xArgR32M16:     EAX,
+	xArgR32M8:      EAX,
+	xArgR32op:      EAX,
+	xArgR64:        RAX,
+	xArgR64M16:     RAX,
+	xArgR64op:      RAX,
+	xArgR8:         AL,
+	xArgR8op:       AL,
+	xArgRM16:       AX,
+	xArgRM32:       EAX,
+	xArgRM64:       RAX,
+	xArgRM8:        AL,
+	xArgRmf16:      AX,
+	xArgRmf32:      EAX,
+	xArgRmf64:      RAX,
+	xArgSTi:        F0,
+	xArgTR0dashTR7: TR0,
+	xArgXmm1:       X0,
+	xArgXmm2:       X0,
+	xArgXmm2M128:   X0,
+	xArgXmm2M16:    X0,
+	xArgXmm2M32:    X0,
+	xArgXmm2M64:    X0,
+	xArgXmm:        X0,
+	xArgXmmM128:    X0,
+	xArgXmmM32:     X0,
+	xArgXmmM64:     X0,
+}
+
+// prefixToSegment returns the segment register
+// corresponding to a particular segment prefix.
+func prefixToSegment(p Prefix) Reg {
+	switch p &^ PrefixImplicit {
+	case PrefixCS:
+		return CS
+	case PrefixDS:
+		return DS
+	case PrefixES:
+		return ES
+	case PrefixFS:
+		return FS
+	case PrefixGS:
+		return GS
+	case PrefixSS:
+		return SS
+	}
+	return 0
+}
+
+// fixedArg records the fixed arguments corresponding to the given bytecodes.
+var fixedArg = [...]Arg{
+	xArg1:    Imm(1),
+	xArg3:    Imm(3),
+	xArgAL:   AL,
+	xArgAX:   AX,
+	xArgDX:   DX,
+	xArgEAX:  EAX,
+	xArgEDX:  EDX,
+	xArgRAX:  RAX,
+	xArgRDX:  RDX,
+	xArgCL:   CL,
+	xArgCS:   CS,
+	xArgDS:   DS,
+	xArgES:   ES,
+	xArgFS:   FS,
+	xArgGS:   GS,
+	xArgSS:   SS,
+	xArgST:   F0,
+	xArgXMM0: X0,
+}
+
+// memBytes records the size of the memory pointed at
+// by a memory argument of the given form.
+var memBytes = [...]int8{
+	xArgM128:       128 / 8,
+	xArgM16:        16 / 8,
+	xArgM16and16:   (16 + 16) / 8,
+	xArgM16colon16: (16 + 16) / 8,
+	xArgM16colon32: (16 + 32) / 8,
+	xArgM16int:     16 / 8,
+	xArgM2byte:     2,
+	xArgM32:        32 / 8,
+	xArgM32and32:   (32 + 32) / 8,
+	xArgM32fp:      32 / 8,
+	xArgM32int:     32 / 8,
+	xArgM64:        64 / 8,
+	xArgM64fp:      64 / 8,
+	xArgM64int:     64 / 8,
+	xArgMm2M64:     64 / 8,
+	xArgMmM32:      32 / 8,
+	xArgMmM64:      64 / 8,
+	xArgMoffs16:    16 / 8,
+	xArgMoffs32:    32 / 8,
+	xArgMoffs64:    64 / 8,
+	xArgMoffs8:     8 / 8,
+	xArgR32M16:     16 / 8,
+	xArgR32M8:      8 / 8,
+	xArgR64M16:     16 / 8,
+	xArgRM16:       16 / 8,
+	xArgRM32:       32 / 8,
+	xArgRM64:       64 / 8,
+	xArgRM8:        8 / 8,
+	xArgXmm2M128:   128 / 8,
+	xArgXmm2M16:    16 / 8,
+	xArgXmm2M32:    32 / 8,
+	xArgXmm2M64:    64 / 8,
+	xArgXmm:        128 / 8,
+	xArgXmmM128:    128 / 8,
+	xArgXmmM32:     32 / 8,
+	xArgXmmM64:     64 / 8,
+}
+
+// isCondJmp records the conditional jumps.
+var isCondJmp = [maxOp + 1]bool{
+	JA:  true,
+	JAE: true,
+	JB:  true,
+	JBE: true,
+	JE:  true,
+	JG:  true,
+	JGE: true,
+	JL:  true,
+	JLE: true,
+	JNE: true,
+	JNO: true,
+	JNP: true,
+	JNS: true,
+	JO:  true,
+	JP:  true,
+	JS:  true,
+}
+
+// isLoop records the loop operators.
+var isLoop = [maxOp + 1]bool{
+	LOOP:   true,
+	LOOPE:  true,
+	LOOPNE: true,
+	JECXZ:  true,
+	JRCXZ:  true,
+}
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode_test.go
new file mode 100644
index 0000000..b6098b8
--- /dev/null
+++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode_test.go
@@ -0,0 +1,71 @@
+// 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 x86asm
+
+import (
+	"encoding/hex"
+	"io/ioutil"
+	"strconv"
+	"strings"
+	"testing"
+)
+
+func TestDecode(t *testing.T) {
+	data, err := ioutil.ReadFile("testdata/decode.txt")
+	if err != nil {
+		t.Fatal(err)
+	}
+	all := string(data)
+	for strings.Contains(all, "\t\t") {
+		all = strings.Replace(all, "\t\t", "\t", -1)
+	}
+	for _, line := range strings.Split(all, "\n") {
+		line = strings.TrimSpace(line)
+		if line == "" || strings.HasPrefix(line, "#") {
+			continue
+		}
+		f := strings.SplitN(line, "\t", 4)
+		i := strings.Index(f[0], "|")
+		if i < 0 {
+			t.Errorf("parsing %q: missing | separator", f[0])
+			continue
+		}
+		if i%2 != 0 {
+			t.Errorf("parsing %q: misaligned | separator", f[0])
+		}
+		size := i / 2
+		code, err := hex.DecodeString(f[0][:i] + f[0][i+1:])
+		if err != nil {
+			t.Errorf("parsing %q: %v", f[0], err)
+			continue
+		}
+		mode, err := strconv.Atoi(f[1])
+		if err != nil {
+			t.Errorf("invalid mode %q in: %s", f[1], line)
+			continue
+		}
+		syntax, asm := f[2], f[3]
+		inst, err := Decode(code, mode)
+		var out string
+		if err != nil {
+			out = "error: " + err.Error()
+		} else {
+			switch syntax {
+			case "gnu":
+				out = GNUSyntax(inst)
+			case "intel":
+				out = IntelSyntax(inst)
+			case "plan9": // [sic]
+				out = GoSyntax(inst, 0, nil)
+			default:
+				t.Errorf("unknown syntax %q", syntax)
+				continue
+			}
+		}
+		if out != asm || inst.Len != size {
+			t.Errorf("Decode(%s) [%s] = %s, %d, want %s, %d", f[0], syntax, out, inst.Len, asm, size)
+		}
+	}
+}
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/ext_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/ext_test.go
new file mode 100644
index 0000000..eadfd71
--- /dev/null
+++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/ext_test.go
@@ -0,0 +1,810 @@
+// 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.
+
+// Support for testing against external disassembler program.
+
+package x86asm
+
+import (
+	"bufio"
+	"bytes"
+	"encoding/hex"
+	"flag"
+	"fmt"
+	"io/ioutil"
+	"log"
+	"math/rand"
+	"os"
+	"os/exec"
+	"regexp"
+	"runtime"
+	"strings"
+	"testing"
+	"time"
+)
+
+var (
+	printTests = flag.Bool("printtests", false, "print test cases that exercise new code paths")
+	dumpTest   = flag.Bool("dump", false, "dump all encodings")
+	mismatch   = flag.Bool("mismatch", false, "log allowed mismatches")
+	longTest   = flag.Bool("long", false, "long test")
+	keep       = flag.Bool("keep", false, "keep object files around")
+	debug      = false
+)
+
+// A ExtInst represents a single decoded instruction parsed
+// from an external disassembler's output.
+type ExtInst struct {
+	addr uint32
+	enc  [32]byte
+	nenc int
+	text string
+}
+
+func (r ExtInst) String() string {
+	return fmt.Sprintf("%#x: % x: %s", r.addr, r.enc, r.text)
+}
+
+// An ExtDis is a connection between an external disassembler and a test.
+type ExtDis struct {
+	Arch     int
+	Dec      chan ExtInst
+	File     *os.File
+	Size     int
+	KeepFile bool
+	Cmd      *exec.Cmd
+}
+
+// Run runs the given command - the external disassembler - and returns
+// a buffered reader of its standard output.
+func (ext *ExtDis) Run(cmd ...string) (*bufio.Reader, error) {
+	if *keep {
+		log.Printf("%s\n", strings.Join(cmd, " "))
+	}
+	ext.Cmd = exec.Command(cmd[0], cmd[1:]...)
+	out, err := ext.Cmd.StdoutPipe()
+	if err != nil {
+		return nil, fmt.Errorf("stdoutpipe: %v", err)
+	}
+	if err := ext.Cmd.Start(); err != nil {
+		return nil, fmt.Errorf("exec: %v", err)
+	}
+
+	b := bufio.NewReaderSize(out, 1<<20)
+	return b, nil
+}
+
+// Wait waits for the command started with Run to exit.
+func (ext *ExtDis) Wait() error {
+	return ext.Cmd.Wait()
+}
+
+// testExtDis tests a set of byte sequences against an external disassembler.
+// The disassembler is expected to produce the given syntax and be run
+// in the given architecture mode (16, 32, or 64-bit).
+// The extdis function must start the external disassembler
+// and then parse its output, sending the parsed instructions on ext.Dec.
+// The generate function calls its argument f once for each byte sequence
+// to be tested. The generate function itself will be called twice, and it must
+// make the same sequence of calls to f each time.
+// When a disassembly does not match the internal decoding,
+// allowedMismatch determines whether this mismatch should be
+// allowed, or else considered an error.
+func testExtDis(
+	t *testing.T,
+	syntax string,
+	arch int,
+	extdis func(ext *ExtDis) error,
+	generate func(f func([]byte)),
+	allowedMismatch func(text string, size int, inst *Inst, dec ExtInst) bool,
+) {
+	start := time.Now()
+	ext := &ExtDis{
+		Dec:  make(chan ExtInst),
+		Arch: arch,
+	}
+	errc := make(chan error)
+
+	// First pass: write instructions to input file for external disassembler.
+	file, f, size, err := writeInst(generate)
+	if err != nil {
+		t.Fatal(err)
+	}
+	ext.Size = size
+	ext.File = f
+	defer func() {
+		f.Close()
+		if !*keep {
+			os.Remove(file)
+		}
+	}()
+
+	// Second pass: compare disassembly against our decodings.
+	var (
+		totalTests  = 0
+		totalSkips  = 0
+		totalErrors = 0
+
+		errors = make([]string, 0, 100) // sampled errors, at most cap
+	)
+	go func() {
+		errc <- extdis(ext)
+	}()
+	generate(func(enc []byte) {
+		dec, ok := <-ext.Dec
+		if !ok {
+			t.Errorf("decoding stream ended early")
+			return
+		}
+		inst, text := disasm(syntax, arch, pad(enc))
+		totalTests++
+		if *dumpTest {
+			fmt.Printf("%x -> %s [%d]\n", enc[:len(enc)], dec.text, dec.nenc)
+		}
+		if text != dec.text || inst.Len != dec.nenc {
+			suffix := ""
+			if allowedMismatch(text, size, &inst, dec) {
+				totalSkips++
+				if !*mismatch {
+					return
+				}
+				suffix += " (allowed mismatch)"
+			}
+			totalErrors++
+			if len(errors) >= cap(errors) {
+				j := rand.Intn(totalErrors)
+				if j >= cap(errors) {
+					return
+				}
+				errors = append(errors[:j], errors[j+1:]...)
+			}
+			errors = append(errors, fmt.Sprintf("decode(%x) = %q, %d, want %q, %d%s", enc, text, inst.Len, dec.text, dec.nenc, suffix))
+		}
+	})
+
+	if *mismatch {
+		totalErrors -= totalSkips
+	}
+
+	for _, b := range errors {
+		t.Log(b)
+	}
+
+	if totalErrors > 0 {
+		t.Fail()
+	}
+	t.Logf("%d test cases, %d expected mismatches, %d failures; %.0f cases/second", totalTests, totalSkips, totalErrors, float64(totalTests)/time.Since(start).Seconds())
+
+	if err := <-errc; err != nil {
+		t.Fatalf("external disassembler: %v", err)
+	}
+}
+
+const start = 0x8000 // start address of text
+
+// writeInst writes the generated byte sequences to a new file
+// starting at offset start. That file is intended to be the input to
+// the external disassembler.
+func writeInst(generate func(func([]byte))) (file string, f *os.File, size int, err error) {
+	f, err = ioutil.TempFile("", "x86map")
+	if err != nil {
+		return
+	}
+
+	file = f.Name()
+
+	f.Seek(start, 0)
+	w := bufio.NewWriter(f)
+	defer w.Flush()
+	size = 0
+	generate(func(x []byte) {
+		if len(x) > 16 {
+			x = x[:16]
+		}
+		if debug {
+			fmt.Printf("%#x: %x%x\n", start+size, x, pops[len(x):])
+		}
+		w.Write(x)
+		w.Write(pops[len(x):])
+		size += len(pops)
+	})
+	return file, f, size, nil
+}
+
+// 0x5F is a single-byte pop instruction.
+// We pad the bytes we want decoded with enough 0x5Fs
+// that no matter what state the instruction stream is in
+// after reading our bytes, the pops will get us back to
+// a forced instruction boundary.
+var pops = []byte{
+	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
+	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
+	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
+	0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
+}
+
+// pad pads the code sequence with pops.
+func pad(enc []byte) []byte {
+	return append(enc[:len(enc):len(enc)], pops...)
+}
+
+// disasm returns the decoded instruction and text
+// for the given source bytes, using the given syntax and mode.
+func disasm(syntax string, mode int, src []byte) (inst Inst, text string) {
+	// If printTests is set, we record the coverage value
+	// before and after, and we write out the inputs for which
+	// coverage went up, in the format expected in testdata/decode.text.
+	// This produces a fairly small set of test cases that exercise nearly
+	// all the code.
+	var cover float64
+	if *printTests {
+		cover -= coverage()
+	}
+
+	inst, err := decode1(src, mode, syntax == "gnu")
+	if err != nil {
+		text = "error: " + err.Error()
+	} else {
+		switch syntax {
+		case "gnu":
+			text = GNUSyntax(inst)
+		case "intel":
+			text = IntelSyntax(inst)
+		case "plan9": // [sic]
+			text = GoSyntax(inst, 0, nil)
+		default:
+			text = "error: unknown syntax " + syntax
+		}
+	}
+
+	if *printTests {
+		cover += coverage()
+		if cover > 0 {
+			max := len(src)
+			if max > 16 && inst.Len <= 16 {
+				max = 16
+			}
+			fmt.Printf("%x|%x\t%d\t%s\t%s\n", src[:inst.Len], src[inst.Len:max], mode, syntax, text)
+		}
+	}
+
+	return
+}
+
+// coverage returns a floating point number denoting the
+// test coverage until now. The number increases when new code paths are exercised,
+// both in the Go program and in the decoder byte code.
+func coverage() float64 {
+	/*
+		testing.Coverage is not in the main distribution.
+		The implementation, which must go in package testing, is:
+
+		// Coverage reports the current code coverage as a fraction in the range [0, 1].
+		func Coverage() float64 {
+			var n, d int64
+			for _, counters := range cover.Counters {
+				for _, c := range counters {
+					if c > 0 {
+						n++
+					}
+					d++
+				}
+			}
+			if d == 0 {
+				return 0
+			}
+			return float64(n) / float64(d)
+		}
+	*/
+
+	var f float64
+	// f += testing.Coverage()
+	f += decodeCoverage()
+	return f
+}
+
+func decodeCoverage() float64 {
+	n := 0
+	for _, t := range decoderCover {
+		if t {
+			n++
+		}
+	}
+	return float64(1+n) / float64(1+len(decoderCover))
+}
+
+// Helpers for writing disassembler output parsers.
+
+// isPrefix reports whether text is the name of an instruction prefix.
+func isPrefix(text string) bool {
+	return prefixByte[text] > 0
+}
+
+// prefixByte maps instruction prefix text to actual prefix byte values.
+var prefixByte = map[string]byte{
+	"es":       0x26,
+	"cs":       0x2e,
+	"ss":       0x36,
+	"ds":       0x3e,
+	"fs":       0x64,
+	"gs":       0x65,
+	"data16":   0x66,
+	"addr16":   0x67,
+	"lock":     0xf0,
+	"repn":     0xf2,
+	"repne":    0xf2,
+	"rep":      0xf3,
+	"repe":     0xf3,
+	"xacquire": 0xf2,
+	"xrelease": 0xf3,
+	"bnd":      0xf2,
+	"addr32":   0x66,
+	"data32":   0x67,
+}
+
+// hasPrefix reports whether any of the space-separated words in the text s
+// begins with any of the given prefixes.
+func hasPrefix(s string, prefixes ...string) bool {
+	for _, prefix := range prefixes {
+		for s := s; s != ""; {
+			if strings.HasPrefix(s, prefix) {
+				return true
+			}
+			i := strings.Index(s, " ")
+			if i < 0 {
+				break
+			}
+			s = s[i+1:]
+		}
+	}
+	return false
+}
+
+// contains reports whether the text s contains any of the given substrings.
+func contains(s string, substrings ...string) bool {
+	for _, sub := range substrings {
+		if strings.Contains(s, sub) {
+			return true
+		}
+	}
+	return false
+}
+
+// isHex reports whether b is a hexadecimal character (0-9A-Fa-f).
+func isHex(b byte) bool { return b == '0' || unhex[b] > 0 }
+
+// parseHex parses the hexadecimal byte dump in hex,
+// appending the parsed bytes to raw and returning the updated slice.
+// The returned bool signals whether any invalid hex was found.
+// Spaces and tabs between bytes are okay but any other non-hex is not.
+func parseHex(hex []byte, raw []byte) ([]byte, bool) {
+	hex = trimSpace(hex)
+	for j := 0; j < len(hex); {
+		for hex[j] == ' ' || hex[j] == '\t' {
+			j++
+		}
+		if j >= len(hex) {
+			break
+		}
+		if j+2 > len(hex) || !isHex(hex[j]) || !isHex(hex[j+1]) {
+			return nil, false
+		}
+		raw = append(raw, unhex[hex[j]]<<4|unhex[hex[j+1]])
+		j += 2
+	}
+	return raw, true
+}
+
+var unhex = [256]byte{
+	'0': 0,
+	'1': 1,
+	'2': 2,
+	'3': 3,
+	'4': 4,
+	'5': 5,
+	'6': 6,
+	'7': 7,
+	'8': 8,
+	'9': 9,
+	'A': 10,
+	'B': 11,
+	'C': 12,
+	'D': 13,
+	'E': 14,
+	'F': 15,
+	'a': 10,
+	'b': 11,
+	'c': 12,
+	'd': 13,
+	'e': 14,
+	'f': 15,
+}
+
+// index is like bytes.Index(s, []byte(t)) but avoids the allocation.
+func index(s []byte, t string) int {
+	i := 0
+	for {
+		j := bytes.IndexByte(s[i:], t[0])
+		if j < 0 {
+			return -1
+		}
+		i = i + j
+		if i+len(t) > len(s) {
+			return -1
+		}
+		for k := 1; k < len(t); k++ {
+			if s[i+k] != t[k] {
+				goto nomatch
+			}
+		}
+		return i
+	nomatch:
+		i++
+	}
+}
+
+// fixSpace rewrites runs of spaces, tabs, and newline characters into single spaces in s.
+// If s must be rewritten, it is rewritten in place.
+func fixSpace(s []byte) []byte {
+	s = trimSpace(s)
+	for i := 0; i < len(s); i++ {
+		if s[i] == '\t' || s[i] == '\n' || i > 0 && s[i] == ' ' && s[i-1] == ' ' {
+			goto Fix
+		}
+	}
+	return s
+
+Fix:
+	b := s
+	w := 0
+	for i := 0; i < len(s); i++ {
+		c := s[i]
+		if c == '\t' || c == '\n' {
+			c = ' '
+		}
+		if c == ' ' && w > 0 && b[w-1] == ' ' {
+			continue
+		}
+		b[w] = c
+		w++
+	}
+	if w > 0 && b[w-1] == ' ' {
+		w--
+	}
+	return b[:w]
+}
+
+// trimSpace trims leading and trailing space from s, returning a subslice of s.
+func trimSpace(s []byte) []byte {
+	j := len(s)
+	for j > 0 && (s[j-1] == ' ' || s[j-1] == '\t' || s[j-1] == '\n') {
+		j--
+	}
+	i := 0
+	for i < j && (s[i] == ' ' || s[i] == '\t') {
+		i++
+	}
+	return s[i:j]
+}
+
+// pcrel and pcrelw match instructions using relative addressing mode.
+var (
+	pcrel  = regexp.MustCompile(`^((?:.* )?(?:j[a-z]+|call|ljmp|loopn?e?w?|xbegin)q?(?:,p[nt])?) 0x([0-9a-f]+)$`)
+	pcrelw = regexp.MustCompile(`^((?:.* )?(?:callw|jmpw|xbeginw|ljmpw)(?:,p[nt])?) 0x([0-9a-f]+)$`)
+)
+
+// Generators.
+//
+// The test cases are described as functions that invoke a callback repeatedly,
+// with a new input sequence each time. These helpers make writing those
+// a little easier.
+
+// hexCases generates the cases written in hexadecimal in the encoded string.
+// Spaces in 'encoded' separate entire test cases, not individual bytes.
+func hexCases(t *testing.T, encoded string) func(func([]byte)) {
+	return func(try func([]byte)) {
+		for _, x := range strings.Fields(encoded) {
+			src, err := hex.DecodeString(x)
+			if err != nil {
+				t.Errorf("parsing %q: %v", x, err)
+			}
+			try(src)
+		}
+	}
+}
+
+// testdataCases generates the test cases recorded in testdata/decode.txt.
+// It only uses the inputs; it ignores the answers recorded in that file.
+func testdataCases(t *testing.T) func(func([]byte)) {
+	var codes [][]byte
+	data, err := ioutil.ReadFile("testdata/decode.txt")
+	if err != nil {
+		t.Fatal(err)
+	}
+	for _, line := range strings.Split(string(data), "\n") {
+		line = strings.TrimSpace(line)
+		if line == "" || strings.HasPrefix(line, "#") {
+			continue
+		}
+		f := strings.Fields(line)[0]
+		i := strings.Index(f, "|")
+		if i < 0 {
+			t.Errorf("parsing %q: missing | separator", f)
+			continue
+		}
+		if i%2 != 0 {
+			t.Errorf("parsing %q: misaligned | separator", f)
+		}
+		code, err := hex.DecodeString(f[:i] + f[i+1:])
+		if err != nil {
+			t.Errorf("parsing %q: %v", f, err)
+			continue
+		}
+		codes = append(codes, code)
+	}
+
+	return func(try func([]byte)) {
+		for _, code := range codes {
+			try(code)
+		}
+	}
+}
+
+// manyPrefixes generates all possible 2⁹ combinations of nine chosen prefixes.
+// The relative ordering of the prefixes within the combinations varies deterministically.
+func manyPrefixes(try func([]byte)) {
+	var prefixBytes = []byte{0x66, 0x67, 0xF0, 0xF2, 0xF3, 0x3E, 0x36, 0x66, 0x67}
+	var enc []byte
+	for i := 0; i < 1<<uint(len(prefixBytes)); i++ {
+		enc = enc[:0]
+		for j, p := range prefixBytes {
+			if i&(1<<uint(j)) != 0 {
+				enc = append(enc, p)
+			}
+		}
+		if len(enc) > 0 {
+			k := i % len(enc)
+			enc[0], enc[k] = enc[k], enc[0]
+		}
+		try(enc)
+	}
+}
+
+// basicPrefixes geneartes 8 different possible prefix cases: no prefix
+// and then one each of seven different prefix bytes.
+func basicPrefixes(try func([]byte)) {
+	try(nil)
+	for _, b := range []byte{0x66, 0x67, 0xF0, 0xF2, 0xF3, 0x3E, 0x36} {
+		try([]byte{b})
+	}
+}
+
+func rexPrefixes(try func([]byte)) {
+	try(nil)
+	for _, b := range []byte{0x40, 0x48, 0x43, 0x4C} {
+		try([]byte{b})
+	}
+}
+
+// concat takes two generators and returns a generator for the
+// cross product of the two, concatenating the results from each.
+func concat(gen1, gen2 func(func([]byte))) func(func([]byte)) {
+	return func(try func([]byte)) {
+		gen1(func(enc1 []byte) {
+			gen2(func(enc2 []byte) {
+				try(append(enc1[:len(enc1):len(enc1)], enc2...))
+			})
+		})
+	}
+}
+
+// concat3 takes three generators and returns a generator for the
+// cross product of the three, concatenating the results from each.
+func concat3(gen1, gen2, gen3 func(func([]byte))) func(func([]byte)) {
+	return func(try func([]byte)) {
+		gen1(func(enc1 []byte) {
+			gen2(func(enc2 []byte) {
+				gen3(func(enc3 []byte) {
+					try(append(append(enc1[:len(enc1):len(enc1)], enc2...), enc3...))
+				})
+			})
+		})
+	}
+}
+
+// concat4 takes four generators and returns a generator for the
+// cross product of the four, concatenating the results from each.
+func concat4(gen1, gen2, gen3, gen4 func(func([]byte))) func(func([]byte)) {
+	return func(try func([]byte)) {
+		gen1(func(enc1 []byte) {
+			gen2(func(enc2 []byte) {
+				gen3(func(enc3 []byte) {
+					gen4(func(enc4 []byte) {
+						try(append(append(append(enc1[:len(enc1):len(enc1)], enc2...), enc3...), enc4...))
+					})
+				})
+			})
+		})
+	}
+}
+
+// filter generates the sequences from gen that satisfy ok.
+func filter(gen func(func([]byte)), ok func([]byte) bool) func(func([]byte)) {
+	return func(try func([]byte)) {
+		gen(func(enc []byte) {
+			if ok(enc) {
+				try(enc)
+			}
+		})
+	}
+}
+
+// enum8bit generates all possible 1-byte sequences, followed by distinctive padding.
+func enum8bit(try func([]byte)) {
+	for i := 0; i < 1<<8; i++ {
+		try([]byte{byte(i), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88})
+	}
+}
+
+// enum8bit generates all possible 2-byte sequences, followed by distinctive padding.
+func enum16bit(try func([]byte)) {
+	for i := 0; i < 1<<16; i++ {
+		try([]byte{byte(i), byte(i >> 8), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88})
+	}
+}
+
+// enum24bit generates all possible 3-byte sequences, followed by distinctive padding.
+func enum24bit(try func([]byte)) {
+	for i := 0; i < 1<<24; i++ {
+		try([]byte{byte(i), byte(i >> 8), byte(i >> 16), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88})
+	}
+}
+
+// enumModRM generates all possible modrm bytes and, for modrm values that indicate
+// a following sib byte, all possible modrm, sib combinations.
+func enumModRM(try func([]byte)) {
+	for i := 0; i < 256; i++ {
+		if (i>>3)&07 == 04 && i>>6 != 3 { // has sib
+			for j := 0; j < 256; j++ {
+				try([]byte{0, byte(i), byte(j), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}) // byte encodings
+				try([]byte{1, byte(i), byte(j), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}) // word encodings
+			}
+		} else {
+			try([]byte{0, byte(i), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}) // byte encodings
+			try([]byte{1, byte(i), 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}) // word encodings
+		}
+	}
+}
+
+// fixed generates the single case b.
+// It's mainly useful to prepare an argument for concat or concat3.
+func fixed(b ...byte) func(func([]byte)) {
+	return func(try func([]byte)) {
+		try(b)
+	}
+}
+
+// testBasic runs the given test function with cases all using opcode as the initial opcode bytes.
+// It runs three phases:
+//
+// First, zero-or-one prefixes followed by opcode followed by all possible 1-byte values.
+// If in -short mode, that's all.
+//
+// Second, zero-or-one prefixes followed by opcode followed by all possible 2-byte values.
+// If not in -long mode, that's all. This phase and the next run in parallel with other tests
+// (using t.Parallel).
+//
+// Finally, opcode followed by all possible 3-byte values. The test can take a very long time
+// and prints progress messages to package log.
+func testBasic(t *testing.T, testfn func(*testing.T, func(func([]byte))), opcode ...byte) {
+	testfn(t, concat3(basicPrefixes, fixed(opcode...), enum8bit))
+	if testing.Short() {
+		return
+	}
+
+	t.Parallel()
+	testfn(t, concat3(basicPrefixes, fixed(opcode...), enum16bit))
+	if !*longTest {
+		return
+	}
+
+	name := caller(2)
+	op1 := make([]byte, len(opcode)+1)
+	copy(op1, opcode)
+	for i := 0; i < 256; i++ {
+		log.Printf("%s 24-bit: %d/256\n", name, i)
+		op1[len(opcode)] = byte(i)
+		testfn(t, concat(fixed(op1...), enum16bit))
+	}
+}
+
+func testBasicREX(t *testing.T, testfn func(*testing.T, func(func([]byte))), opcode ...byte) {
+	testfn(t, filter(concat4(basicPrefixes, rexPrefixes, fixed(opcode...), enum8bit), isValidREX))
+	if testing.Short() {
+		return
+	}
+
+	t.Parallel()
+	testfn(t, filter(concat4(basicPrefixes, rexPrefixes, fixed(opcode...), enum16bit), isValidREX))
+	if !*longTest {
+		return
+	}
+
+	name := caller(2)
+	op1 := make([]byte, len(opcode)+1)
+	copy(op1, opcode)
+	for i := 0; i < 256; i++ {
+		log.Printf("%s 24-bit: %d/256\n", name, i)
+		op1[len(opcode)] = byte(i)
+		testfn(t, filter(concat3(rexPrefixes, fixed(op1...), enum16bit), isValidREX))
+	}
+}
+
+// testPrefix runs the given test function for all many prefix possibilities
+// followed by all possible 1-byte sequences.
+//
+// If in -long mode, it then runs a test of all the prefix possibilities followed
+// by all possible 2-byte sequences.
+func testPrefix(t *testing.T, testfn func(*testing.T, func(func([]byte)))) {
+	t.Parallel()
+	testfn(t, concat(manyPrefixes, enum8bit))
+	if testing.Short() || !*longTest {
+		return
+	}
+
+	name := caller(2)
+	for i := 0; i < 256; i++ {
+		log.Printf("%s 16-bit: %d/256\n", name, i)
+		testfn(t, concat3(manyPrefixes, fixed(byte(i)), enum8bit))
+	}
+}
+
+func testPrefixREX(t *testing.T, testfn func(*testing.T, func(func([]byte)))) {
+	t.Parallel()
+	testfn(t, filter(concat3(manyPrefixes, rexPrefixes, enum8bit), isValidREX))
+	if testing.Short() || !*longTest {
+		return
+	}
+
+	name := caller(2)
+	for i := 0; i < 256; i++ {
+		log.Printf("%s 16-bit: %d/256\n", name, i)
+		testfn(t, filter(concat4(manyPrefixes, rexPrefixes, fixed(byte(i)), enum8bit), isValidREX))
+	}
+}
+
+func caller(skip int) string {
+	pc, _, _, _ := runtime.Caller(skip)
+	f := runtime.FuncForPC(pc)
+	name := "?"
+	if f != nil {
+		name = f.Name()
+		if i := strings.LastIndex(name, "."); i >= 0 {
+			name = name[i+1:]
+		}
+	}
+	return name
+}
+
+func isValidREX(x []byte) bool {
+	i := 0
+	for i < len(x) && isPrefixByte(x[i]) {
+		i++
+	}
+	if i < len(x) && Prefix(x[i]).IsREX() {
+		i++
+		if i < len(x) {
+			return !isPrefixByte(x[i]) && !Prefix(x[i]).IsREX()
+		}
+	}
+	return true
+}
+
+func isPrefixByte(b byte) bool {
+	switch b {
+	case 0x26, 0x2E, 0x36, 0x3E, 0x64, 0x65, 0x66, 0x67, 0xF0, 0xF2, 0xF3:
+		return true
+	}
+	return false
+}
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/gnu.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/gnu.go
similarity index 100%
rename from src/cmd/internal/rsc.io/x86/x86asm/gnu.go
rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/gnu.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/inst.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/inst.go
new file mode 100644
index 0000000..ef74025
--- /dev/null
+++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/inst.go
@@ -0,0 +1,643 @@
+// 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 x86asm implements decoding of x86 machine code.
+package x86asm
+
+import (
+	"bytes"
+	"fmt"
+)
+
+// An Inst is a single instruction.
+type Inst struct {
+	Prefix   Prefixes // Prefixes applied to the instruction.
+	Op       Op       // Opcode mnemonic
+	Opcode   uint32   // Encoded opcode bits, left aligned (first byte is Opcode>>24, etc)
+	Args     Args     // Instruction arguments, in Intel order
+	Mode     int      // processor mode in bits: 16, 32, or 64
+	AddrSize int      // address size in bits: 16, 32, or 64
+	DataSize int      // operand size in bits: 16, 32, or 64
+	MemBytes int      // size of memory argument in bytes: 1, 2, 4, 8, 16, and so on.
+	Len      int      // length of encoded instruction in bytes
+	PCRel    int      // length of PC-relative address in instruction encoding
+	PCRelOff int      // index of start of PC-relative address in instruction encoding
+}
+
+// Prefixes is an array of prefixes associated with a single instruction.
+// The prefixes are listed in the same order as found in the instruction:
+// each prefix byte corresponds to one slot in the array. The first zero
+// in the array marks the end of the prefixes.
+type Prefixes [14]Prefix
+
+// A Prefix represents an Intel instruction prefix.
+// The low 8 bits are the actual prefix byte encoding,
+// and the top 8 bits contain distinguishing bits and metadata.
+type Prefix uint16
+
+const (
+	// Metadata about the role of a prefix in an instruction.
+	PrefixImplicit Prefix = 0x8000 // prefix is implied by instruction text
+	PrefixIgnored  Prefix = 0x4000 // prefix is ignored: either irrelevant or overridden by a later prefix
+	PrefixInvalid  Prefix = 0x2000 // prefix makes entire instruction invalid (bad LOCK)
+
+	// Memory segment overrides.
+	PrefixES Prefix = 0x26 // ES segment override
+	PrefixCS Prefix = 0x2E // CS segment override
+	PrefixSS Prefix = 0x36 // SS segment override
+	PrefixDS Prefix = 0x3E // DS segment override
+	PrefixFS Prefix = 0x64 // FS segment override
+	PrefixGS Prefix = 0x65 // GS segment override
+
+	// Branch prediction.
+	PrefixPN Prefix = 0x12E // predict not taken (conditional branch only)
+	PrefixPT Prefix = 0x13E // predict taken (conditional branch only)
+
+	// Size attributes.
+	PrefixDataSize Prefix = 0x66 // operand size override
+	PrefixData16   Prefix = 0x166
+	PrefixData32   Prefix = 0x266
+	PrefixAddrSize Prefix = 0x67 // address size override
+	PrefixAddr16   Prefix = 0x167
+	PrefixAddr32   Prefix = 0x267
+
+	// One of a kind.
+	PrefixLOCK     Prefix = 0xF0 // lock
+	PrefixREPN     Prefix = 0xF2 // repeat not zero
+	PrefixXACQUIRE Prefix = 0x1F2
+	PrefixBND      Prefix = 0x2F2
+	PrefixREP      Prefix = 0xF3 // repeat
+	PrefixXRELEASE Prefix = 0x1F3
+
+	// The REX prefixes must be in the range [PrefixREX, PrefixREX+0x10).
+	// the other bits are set or not according to the intended use.
+	PrefixREX  Prefix = 0x40 // REX 64-bit extension prefix
+	PrefixREXW Prefix = 0x08 // extension bit W (64-bit instruction width)
+	PrefixREXR Prefix = 0x04 // extension bit R (r field in modrm)
+	PrefixREXX Prefix = 0x02 // extension bit X (index field in sib)
+	PrefixREXB Prefix = 0x01 // extension bit B (r/m field in modrm or base field in sib)
+)
+
+// IsREX reports whether p is a REX prefix byte.
+func (p Prefix) IsREX() bool {
+	return p&0xF0 == PrefixREX
+}
+
+func (p Prefix) String() string {
+	p &^= PrefixImplicit | PrefixIgnored | PrefixInvalid
+	if s := prefixNames[p]; s != "" {
+		return s
+	}
+
+	if p.IsREX() {
+		s := "REX."
+		if p&PrefixREXW != 0 {
+			s += "W"
+		}
+		if p&PrefixREXR != 0 {
+			s += "R"
+		}
+		if p&PrefixREXX != 0 {
+			s += "X"
+		}
+		if p&PrefixREXB != 0 {
+			s += "B"
+		}
+		return s
+	}
+
+	return fmt.Sprintf("Prefix(%#x)", int(p))
+}
+
+// An Op is an x86 opcode.
+type Op uint32
+
+func (op Op) String() string {
+	i := int(op)
+	if i < 0 || i >= len(opNames) || opNames[i] == "" {
+		return fmt.Sprintf("Op(%d)", i)
+	}
+	return opNames[i]
+}
+
+// An Args holds the instruction arguments.
+// If an instruction has fewer than 4 arguments,
+// the final elements in the array are nil.
+type Args [4]Arg
+
+// An Arg is a single instruction argument,
+// one of these types: Reg, Mem, Imm, Rel.
+type Arg interface {
+	String() string
+	isArg()
+}
+
+// Note that the implements of Arg that follow are all sized
+// so that on a 64-bit machine the data can be inlined in
+// the interface value instead of requiring an allocation.
+
+// A Reg is a single register.
+// The zero Reg value has no name but indicates ``no register.''
+type Reg uint8
+
+const (
+	_ Reg = iota
+
+	// 8-bit
+	AL
+	CL
+	DL
+	BL
+	AH
+	CH
+	DH
+	BH
+	SPB
+	BPB
+	SIB
+	DIB
+	R8B
+	R9B
+	R10B
+	R11B
+	R12B
+	R13B
+	R14B
+	R15B
+
+	// 16-bit
+	AX
+	CX
+	DX
+	BX
+	SP
+	BP
+	SI
+	DI
+	R8W
+	R9W
+	R10W
+	R11W
+	R12W
+	R13W
+	R14W
+	R15W
+
+	// 32-bit
+	EAX
+	ECX
+	EDX
+	EBX
+	ESP
+	EBP
+	ESI
+	EDI
+	R8L
+	R9L
+	R10L
+	R11L
+	R12L
+	R13L
+	R14L
+	R15L
+
+	// 64-bit
+	RAX
+	RCX
+	RDX
+	RBX
+	RSP
+	RBP
+	RSI
+	RDI
+	R8
+	R9
+	R10
+	R11
+	R12
+	R13
+	R14
+	R15
+
+	// Instruction pointer.
+	IP  // 16-bit
+	EIP // 32-bit
+	RIP // 64-bit
+
+	// 387 floating point registers.
+	F0
+	F1
+	F2
+	F3
+	F4
+	F5
+	F6
+	F7
+
+	// MMX registers.
+	M0
+	M1
+	M2
+	M3
+	M4
+	M5
+	M6
+	M7
+
+	// XMM registers.
+	X0
+	X1
+	X2
+	X3
+	X4
+	X5
+	X6
+	X7
+	X8
+	X9
+	X10
+	X11
+	X12
+	X13
+	X14
+	X15
+
+	// Segment registers.
+	ES
+	CS
+	SS
+	DS
+	FS
+	GS
+
+	// System registers.
+	GDTR
+	IDTR
+	LDTR
+	MSW
+	TASK
+
+	// Control registers.
+	CR0
+	CR1
+	CR2
+	CR3
+	CR4
+	CR5
+	CR6
+	CR7
+	CR8
+	CR9
+	CR10
+	CR11
+	CR12
+	CR13
+	CR14
+	CR15
+
+	// Debug registers.
+	DR0
+	DR1
+	DR2
+	DR3
+	DR4
+	DR5
+	DR6
+	DR7
+	DR8
+	DR9
+	DR10
+	DR11
+	DR12
+	DR13
+	DR14
+	DR15
+
+	// Task registers.
+	TR0
+	TR1
+	TR2
+	TR3
+	TR4
+	TR5
+	TR6
+	TR7
+)
+
+const regMax = TR7
+
+func (Reg) isArg() {}
+
+func (r Reg) String() string {
+	i := int(r)
+	if i < 0 || i >= len(regNames) || regNames[i] == "" {
+		return fmt.Sprintf("Reg(%d)", i)
+	}
+	return regNames[i]
+}
+
+// A Mem is a memory reference.
+// The general form is Segment:[Base+Scale*Index+Disp].
+type Mem struct {
+	Segment Reg
+	Base    Reg
+	Scale   uint8
+	Index   Reg
+	Disp    int64
+}
+
+func (Mem) isArg() {}
+
+func (m Mem) String() string {
+	var base, plus, scale, index, disp string
+
+	if m.Base != 0 {
+		base = m.Base.String()
+	}
+	if m.Scale != 0 {
+		if m.Base != 0 {
+			plus = "+"
+		}
+		if m.Scale > 1 {
+			scale = fmt.Sprintf("%d*", m.Scale)
+		}
+		index = m.Index.String()
+	}
+	if m.Disp != 0 || m.Base == 0 && m.Scale == 0 {
+		disp = fmt.Sprintf("%+#x", m.Disp)
+	}
+	return "[" + base + plus + scale + index + disp + "]"
+}
+
+// A Rel is an offset relative to the current instruction pointer.
+type Rel int32
+
+func (Rel) isArg() {}
+
+func (r Rel) String() string {
+	return fmt.Sprintf(".%+d", r)
+}
+
+// An Imm is an integer constant.
+type Imm int64
+
+func (Imm) isArg() {}
+
+func (i Imm) String() string {
+	return fmt.Sprintf("%#x", int64(i))
+}
+
+func (i Inst) String() string {
+	var buf bytes.Buffer
+	for _, p := range i.Prefix {
+		if p == 0 {
+			break
+		}
+		if p&PrefixImplicit != 0 {
+			continue
+		}
+		fmt.Fprintf(&buf, "%v ", p)
+	}
+	fmt.Fprintf(&buf, "%v", i.Op)
+	sep := " "
+	for _, v := range i.Args {
+		if v == nil {
+			break
+		}
+		fmt.Fprintf(&buf, "%s%v", sep, v)
+		sep = ", "
+	}
+	return buf.String()
+}
+
+func isReg(a Arg) bool {
+	_, ok := a.(Reg)
+	return ok
+}
+
+func isSegReg(a Arg) bool {
+	r, ok := a.(Reg)
+	return ok && ES <= r && r <= GS
+}
+
+func isMem(a Arg) bool {
+	_, ok := a.(Mem)
+	return ok
+}
+
+func isImm(a Arg) bool {
+	_, ok := a.(Imm)
+	return ok
+}
+
+func regBytes(a Arg) int {
+	r, ok := a.(Reg)
+	if !ok {
+		return 0
+	}
+	if AL <= r && r <= R15B {
+		return 1
+	}
+	if AX <= r && r <= R15W {
+		return 2
+	}
+	if EAX <= r && r <= R15L {
+		return 4
+	}
+	if RAX <= r && r <= R15 {
+		return 8
+	}
+	return 0
+}
+
+func isSegment(p Prefix) bool {
+	switch p {
+	case PrefixCS, PrefixDS, PrefixES, PrefixFS, PrefixGS, PrefixSS:
+		return true
+	}
+	return false
+}
+
+// The Op definitions and string list are in tables.go.
+
+var prefixNames = map[Prefix]string{
+	PrefixCS:       "CS",
+	PrefixDS:       "DS",
+	PrefixES:       "ES",
+	PrefixFS:       "FS",
+	PrefixGS:       "GS",
+	PrefixSS:       "SS",
+	PrefixLOCK:     "LOCK",
+	PrefixREP:      "REP",
+	PrefixREPN:     "REPN",
+	PrefixAddrSize: "ADDRSIZE",
+	PrefixDataSize: "DATASIZE",
+	PrefixAddr16:   "ADDR16",
+	PrefixData16:   "DATA16",
+	PrefixAddr32:   "ADDR32",
+	PrefixData32:   "DATA32",
+	PrefixBND:      "BND",
+	PrefixXACQUIRE: "XACQUIRE",
+	PrefixXRELEASE: "XRELEASE",
+	PrefixREX:      "REX",
+	PrefixPT:       "PT",
+	PrefixPN:       "PN",
+}
+
+var regNames = [...]string{
+	AL:   "AL",
+	CL:   "CL",
+	BL:   "BL",
+	DL:   "DL",
+	AH:   "AH",
+	CH:   "CH",
+	BH:   "BH",
+	DH:   "DH",
+	SPB:  "SPB",
+	BPB:  "BPB",
+	SIB:  "SIB",
+	DIB:  "DIB",
+	R8B:  "R8B",
+	R9B:  "R9B",
+	R10B: "R10B",
+	R11B: "R11B",
+	R12B: "R12B",
+	R13B: "R13B",
+	R14B: "R14B",
+	R15B: "R15B",
+	AX:   "AX",
+	CX:   "CX",
+	BX:   "BX",
+	DX:   "DX",
+	SP:   "SP",
+	BP:   "BP",
+	SI:   "SI",
+	DI:   "DI",
+	R8W:  "R8W",
+	R9W:  "R9W",
+	R10W: "R10W",
+	R11W: "R11W",
+	R12W: "R12W",
+	R13W: "R13W",
+	R14W: "R14W",
+	R15W: "R15W",
+	EAX:  "EAX",
+	ECX:  "ECX",
+	EDX:  "EDX",
+	EBX:  "EBX",
+	ESP:  "ESP",
+	EBP:  "EBP",
+	ESI:  "ESI",
+	EDI:  "EDI",
+	R8L:  "R8L",
+	R9L:  "R9L",
+	R10L: "R10L",
+	R11L: "R11L",
+	R12L: "R12L",
+	R13L: "R13L",
+	R14L: "R14L",
+	R15L: "R15L",
+	RAX:  "RAX",
+	RCX:  "RCX",
+	RDX:  "RDX",
+	RBX:  "RBX",
+	RSP:  "RSP",
+	RBP:  "RBP",
+	RSI:  "RSI",
+	RDI:  "RDI",
+	R8:   "R8",
+	R9:   "R9",
+	R10:  "R10",
+	R11:  "R11",
+	R12:  "R12",
+	R13:  "R13",
+	R14:  "R14",
+	R15:  "R15",
+	IP:   "IP",
+	EIP:  "EIP",
+	RIP:  "RIP",
+	F0:   "F0",
+	F1:   "F1",
+	F2:   "F2",
+	F3:   "F3",
+	F4:   "F4",
+	F5:   "F5",
+	F6:   "F6",
+	F7:   "F7",
+	M0:   "M0",
+	M1:   "M1",
+	M2:   "M2",
+	M3:   "M3",
+	M4:   "M4",
+	M5:   "M5",
+	M6:   "M6",
+	M7:   "M7",
+	X0:   "X0",
+	X1:   "X1",
+	X2:   "X2",
+	X3:   "X3",
+	X4:   "X4",
+	X5:   "X5",
+	X6:   "X6",
+	X7:   "X7",
+	X8:   "X8",
+	X9:   "X9",
+	X10:  "X10",
+	X11:  "X11",
+	X12:  "X12",
+	X13:  "X13",
+	X14:  "X14",
+	X15:  "X15",
+	CS:   "CS",
+	SS:   "SS",
+	DS:   "DS",
+	ES:   "ES",
+	FS:   "FS",
+	GS:   "GS",
+	GDTR: "GDTR",
+	IDTR: "IDTR",
+	LDTR: "LDTR",
+	MSW:  "MSW",
+	TASK: "TASK",
+	CR0:  "CR0",
+	CR1:  "CR1",
+	CR2:  "CR2",
+	CR3:  "CR3",
+	CR4:  "CR4",
+	CR5:  "CR5",
+	CR6:  "CR6",
+	CR7:  "CR7",
+	CR8:  "CR8",
+	CR9:  "CR9",
+	CR10: "CR10",
+	CR11: "CR11",
+	CR12: "CR12",
+	CR13: "CR13",
+	CR14: "CR14",
+	CR15: "CR15",
+	DR0:  "DR0",
+	DR1:  "DR1",
+	DR2:  "DR2",
+	DR3:  "DR3",
+	DR4:  "DR4",
+	DR5:  "DR5",
+	DR6:  "DR6",
+	DR7:  "DR7",
+	DR8:  "DR8",
+	DR9:  "DR9",
+	DR10: "DR10",
+	DR11: "DR11",
+	DR12: "DR12",
+	DR13: "DR13",
+	DR14: "DR14",
+	DR15: "DR15",
+	TR0:  "TR0",
+	TR1:  "TR1",
+	TR2:  "TR2",
+	TR3:  "TR3",
+	TR4:  "TR4",
+	TR5:  "TR5",
+	TR6:  "TR6",
+	TR7:  "TR7",
+}
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/inst_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/inst_test.go
similarity index 100%
rename from src/cmd/internal/rsc.io/x86/x86asm/inst_test.go
rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/inst_test.go
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/intel.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/intel.go
similarity index 100%
rename from src/cmd/internal/rsc.io/x86/x86asm/intel.go
rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/intel.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/objdump_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/objdump_test.go
new file mode 100644
index 0000000..3d4e146
--- /dev/null
+++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/objdump_test.go
@@ -0,0 +1,385 @@
+// 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 x86asm
+
+import (
+	"bytes"
+	"strings"
+	"testing"
+)
+
+func TestObjdump32Manual(t *testing.T)   { testObjdump32(t, hexCases(t, objdumpManualTests)) }
+func TestObjdump32Testdata(t *testing.T) { testObjdump32(t, concat(basicPrefixes, testdataCases(t))) }
+func TestObjdump32ModRM(t *testing.T)    { testObjdump32(t, concat(basicPrefixes, enumModRM)) }
+func TestObjdump32OneByte(t *testing.T)  { testBasic(t, testObjdump32) }
+func TestObjdump320F(t *testing.T)       { testBasic(t, testObjdump32, 0x0F) }
+func TestObjdump320F38(t *testing.T)     { testBasic(t, testObjdump32, 0x0F, 0x38) }
+func TestObjdump320F3A(t *testing.T)     { testBasic(t, testObjdump32, 0x0F, 0x3A) }
+func TestObjdump32Prefix(t *testing.T)   { testPrefix(t, testObjdump32) }
+
+func TestObjdump64Manual(t *testing.T)   { testObjdump64(t, hexCases(t, objdumpManualTests)) }
+func TestObjdump64Testdata(t *testing.T) { testObjdump64(t, concat(basicPrefixes, testdataCases(t))) }
+func TestObjdump64ModRM(t *testing.T)    { testObjdump64(t, concat(basicPrefixes, enumModRM)) }
+func TestObjdump64OneByte(t *testing.T)  { testBasic(t, testObjdump64) }
+func TestObjdump640F(t *testing.T)       { testBasic(t, testObjdump64, 0x0F) }
+func TestObjdump640F38(t *testing.T)     { testBasic(t, testObjdump64, 0x0F, 0x38) }
+func TestObjdump640F3A(t *testing.T)     { testBasic(t, testObjdump64, 0x0F, 0x3A) }
+func TestObjdump64Prefix(t *testing.T)   { testPrefix(t, testObjdump64) }
+
+func TestObjdump64REXTestdata(t *testing.T) {
+	testObjdump64(t, filter(concat3(basicPrefixes, rexPrefixes, testdataCases(t)), isValidREX))
+}
+func TestObjdump64REXModRM(t *testing.T) {
+	testObjdump64(t, concat3(basicPrefixes, rexPrefixes, enumModRM))
+}
+func TestObjdump64REXOneByte(t *testing.T) { testBasicREX(t, testObjdump64) }
+func TestObjdump64REX0F(t *testing.T)      { testBasicREX(t, testObjdump64, 0x0F) }
+func TestObjdump64REX0F38(t *testing.T)    { testBasicREX(t, testObjdump64, 0x0F, 0x38) }
+func TestObjdump64REX0F3A(t *testing.T)    { testBasicREX(t, testObjdump64, 0x0F, 0x3A) }
+func TestObjdump64REXPrefix(t *testing.T)  { testPrefixREX(t, testObjdump64) }
+
+// objdumpManualTests holds test cases that will be run by TestObjdumpManual.
+// If you are debugging a few cases that turned up in a longer run, it can be useful
+// to list them here and then use -run=ObjdumpManual, particularly with tracing enabled.
+var objdumpManualTests = `
+4883FE017413
+488DFC2500000000
+488D3D00000000
+`
+
+// allowedMismatchObjdump reports whether the mismatch between text and dec
+// should be allowed by the test.
+func allowedMismatchObjdump(text string, size int, inst *Inst, dec ExtInst) bool {
+	if size == 15 && dec.nenc == 15 && contains(text, "truncated") && contains(dec.text, "(bad)") {
+		return true
+	}
+
+	if i := strings.LastIndex(dec.text, " "); isPrefix(dec.text[i+1:]) && size == 1 && isPrefix(text) {
+		return true
+	}
+
+	if size == dec.nenc && contains(dec.text, "movupd") && contains(dec.text, "data32") {
+		s := strings.Replace(dec.text, "data32 ", "", -1)
+		if text == s {
+			return true
+		}
+	}
+
+	// Simplify our invalid instruction text.
+	if text == "error: unrecognized instruction" {
+		text = "BAD"
+	}
+
+	// Invalid instructions for which libopcodes prints %? register.
+	// FF E8 11 22 33 44:
+	// Invalid instructions for which libopcodes prints "internal disassembler error".
+	// Invalid instructions for which libopcodes prints 8087 only (e.g., DB E0)
+	// or prints 287 only (e.g., DB E4).
+	if contains(dec.text, "%?", "<internal disassembler error>", "(8087 only)", "(287 only)") {
+		dec.text = "(bad)"
+	}
+
+	// 0F 19 11, 0F 1C 11, 0F 1D 11, 0F 1E 11, 0F 1F 11: libopcodes says nop,
+	// but the Intel manuals say that the only NOP there is 0F 1F /0.
+	// Perhaps libopcodes is reporting an older encoding.
+	i := bytes.IndexByte(dec.enc[:], 0x0F)
+	if contains(dec.text, "nop") && i >= 0 && i+2 < len(dec.enc) && dec.enc[i+1]&^7 == 0x18 && (dec.enc[i+1] != 0x1F || (dec.enc[i+2]>>3)&7 != 0) {
+		dec.text = "(bad)"
+	}
+
+	// Any invalid instruction.
+	if text == "BAD" && contains(dec.text, "(bad)") {
+		return true
+	}
+
+	// Instructions libopcodes knows but we do not (e.g., 0F 19 11).
+	if (text == "BAD" || size == 1 && isPrefix(text)) && hasPrefix(dec.text, unsupported...) {
+		return true
+	}
+
+	// Instructions we know but libopcodes does not (e.g., 0F D0 11).
+	if (contains(dec.text, "(bad)") || dec.nenc == 1 && isPrefix(dec.text)) && hasPrefix(text, libopcodesUnsupported...) {
+		return true
+	}
+
+	// Libopcodes rejects F2 90 as NOP. Not sure why.
+	if (contains(dec.text, "(bad)") || dec.nenc == 1 && isPrefix(dec.text)) && inst.Opcode>>24 == 0x90 && countPrefix(inst, 0xF2) > 0 {
+		return true
+	}
+
+	// 0F 20 11, 0F 21 11, 0F 22 11, 0F 23 11, 0F 24 11:
+	// Moves into and out of some control registers seem to be unsupported by libopcodes.
+	// TODO(rsc): Are they invalid somehow?
+	if (contains(dec.text, "(bad)") || dec.nenc == 1 && isPrefix(dec.text)) && contains(text, "%cr", "%db", "%tr") {
+		return true
+	}
+
+	if contains(dec.text, "fwait") && dec.nenc == 1 && dec.enc[0] != 0x9B {
+		return true
+	}
+
+	// 9B D9 11: libopcodes reports FSTSW instead of FWAIT + FNSTSW.
+	// This is correct in that FSTSW is a pseudo-op for the pair, but it really
+	// is a pair of instructions: execution can stop between them.
+	// Our decoder chooses to separate them.
+	if (text == "fwait" || strings.HasSuffix(text, " fwait")) && dec.nenc >= len(strings.Fields(text)) && dec.enc[len(strings.Fields(text))-1] == 0x9B {
+		return true
+	}
+
+	// 0F 18 77 11:
+	// Invalid instructions for which libopcodes prints "nop/reserved".
+	// Perhaps libopcodes is reporting an older encoding.
+	if text == "BAD" && contains(dec.text, "nop/reserved") {
+		return true
+	}
+
+	// 0F C7 B0 11 22 33 44: libopcodes says vmptrld 0x44332211(%eax); we say rdrand %eax.
+	// TODO(rsc): Fix, since we are probably wrong, but we don't have vmptrld in the manual.
+	if contains(text, "rdrand") && contains(dec.text, "vmptrld", "vmxon", "vmclear") {
+		return true
+	}
+
+	// DD C8: libopcodes says FNOP but the Intel manual is clear FNOP is only D9 D0.
+	// Perhaps libopcodes is reporting an older encoding.
+	if text == "BAD" && contains(dec.text, "fnop") && (dec.enc[0] != 0xD9 || dec.enc[1] != 0xD0) {
+		return true
+	}
+
+	// 66 90: libopcodes says xchg %ax,%ax; we say 'data16 nop'.
+	// The 16-bit swap will preserve the high bits of the register,
+	// so they are the same.
+	if contains(text, "nop") && contains(dec.text, "xchg %ax,%ax") {
+		return true
+	}
+
+	// If there are multiple prefixes, allow libopcodes to use an alternate name.
+	if size == 1 && dec.nenc == 1 && prefixByte[text] > 0 && prefixByte[text] == prefixByte[dec.text] {
+		return true
+	}
+
+	// 26 9B: libopcodes reports "fwait"/1, ignoring segment prefix.
+	// https://sourceware.org/bugzilla/show_bug.cgi?id=16891
+	// F0 82: Decode="lock"/1 but libopcodes="lock (bad)"/2.
+	if size == 1 && dec.nenc >= 1 && prefixByte[text] == dec.enc[0] && contains(dec.text, "(bad)", "fwait", "fnop") {
+		return true
+	}
+
+	// libopcodes interprets 660f801122 as taking a rel16 but
+	// truncating the address at 16 bits. Not sure what is correct.
+	if contains(text, ".+0x2211", ".+0x11") && contains(dec.text, " .-") {
+		return true
+	}
+
+	// 66 F3 0F D6 C5, 66 F2 0F D6 C0: libopcodes reports use of XMM register instead of MMX register,
+	// but only when the instruction has a 66 prefix. Maybe they know something we don't.
+	if countPrefix(inst, 0x66) > 0 && contains(dec.text, "movdq2q", "movq2dq") && !contains(dec.text, "%mm") {
+		return true
+	}
+
+	// 0F 01 F8, 0F 05, 0F 07: these are 64-bit instructions but libopcodes accepts them.
+	if (text == "BAD" || size == 1 && isPrefix(text)) && contains(dec.text, "swapgs", "syscall", "sysret", "rdfsbase", "rdgsbase", "wrfsbase", "wrgsbase") {
+		return true
+	}
+
+	return false
+}
+
+// Instructions known to libopcodes (or xed) but not to us.
+// Most of these come from supplementary manuals of one form or another.
+var unsupported = strings.Fields(`
+	bndc
+	bndl
+	bndm
+	bnds
+	clac
+	clgi
+	femms
+	fldln
+	fldz
+	getsec
+	invlpga
+	kmov
+	montmul
+	pavg
+	pf2i
+	pfacc
+	pfadd
+	pfcmp
+	pfmax
+	pfmin
+	pfmul
+	pfna
+	pfpnac
+	pfrc
+	pfrs
+	pfsub
+	phadd
+	phsub
+	pi2f
+	pmulhr
+	prefetch
+	pswap
+	ptest
+	rdseed
+	sha1
+	sha256
+	skinit
+	stac
+	stgi
+	vadd
+	vand
+	vcmp
+	vcomis
+	vcvt
+	vcvt
+	vdiv
+	vhadd
+	vhsub
+	vld
+	vmax
+	vmcall
+	vmfunc
+	vmin
+	vmlaunch
+	vmload
+	vmmcall
+	vmov
+	vmov
+	vmov
+	vmptrld
+	vmptrst
+	vmread
+	vmresume
+	vmrun
+	vmsave
+	vmul
+	vmwrite
+	vmxoff
+	vor
+	vpack
+	vpadd
+	vpand
+	vpavg
+	vpcmp
+	vpcmp
+	vpins
+	vpmadd
+	vpmax
+	vpmin
+	vpmul
+	vpmul
+	vpor
+	vpsad
+	vpshuf
+	vpsll
+	vpsra
+	vpsrad
+	vpsrl
+	vpsub
+	vpunp
+	vpxor
+	vrcp
+	vrsqrt
+	vshuf
+	vsqrt
+	vsub
+	vucomis
+	vunp
+	vxor
+	vzero
+	xcrypt
+	xsha1
+	xsha256
+	xstore-rng
+	insertq
+	extrq
+	vmclear
+	invvpid
+	adox
+	vmxon
+	invept
+	adcx
+	vmclear
+	prefetchwt1
+	enclu
+	encls
+	salc
+	fstpnce
+	fdisi8087_nop
+	fsetpm287_nop
+	feni8087_nop
+	syscall
+	sysret
+`)
+
+// Instructions known to us but not to libopcodes (at least in binutils 2.24).
+var libopcodesUnsupported = strings.Fields(`
+	addsubps
+	aes
+	blend
+	cvttpd2dq
+	dpp
+	extract
+	haddps
+	hsubps
+	insert
+	invpcid
+	lddqu
+	movmsk
+	movnt
+	movq2dq
+	mps
+	pack
+	pblend
+	pclmul
+	pcmp
+	pext
+	phmin
+	pins
+	pmax
+	pmin
+	pmov
+	pmovmsk
+	pmul
+	popcnt
+	pslld
+	psllq
+	psllw
+	psrad
+	psraw
+	psrl
+	ptest
+	punpck
+	round
+	xrstor
+	xsavec
+	xsaves
+	comis
+	ucomis
+	movhps
+	movntps
+	rsqrt
+	rcpp
+	puncpck
+	bsf
+	movq2dq
+	cvttpd2dq
+	movq
+	hsubpd
+	movdqa
+	movhpd
+	addsubpd
+	movd
+	haddpd
+	cvtps2dq
+	bsr
+	cvtdq2ps
+	rdrand
+	maskmov
+	movq2dq
+	movlhps
+	movbe
+	movlpd
+`)
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/objdumpext_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/objdumpext_test.go
new file mode 100644
index 0000000..f720dc6
--- /dev/null
+++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/objdumpext_test.go
@@ -0,0 +1,313 @@
+// 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 x86asm
+
+import (
+	"bytes"
+	"debug/elf"
+	"encoding/binary"
+	"fmt"
+	"io"
+	"log"
+	"os"
+	"strconv"
+	"strings"
+	"testing"
+)
+
+// Apologies for the proprietary path, but we need objdump 2.24 + some committed patches that will land in 2.25.
+const objdumpPath = "/Users/rsc/bin/objdump2"
+
+func testObjdump32(t *testing.T, generate func(func([]byte))) {
+	testObjdumpArch(t, generate, 32)
+}
+
+func testObjdump64(t *testing.T, generate func(func([]byte))) {
+	testObjdumpArch(t, generate, 64)
+}
+
+func testObjdumpArch(t *testing.T, generate func(func([]byte)), arch int) {
+	if testing.Short() {
+		t.Skip("skipping objdump test in short mode")
+	}
+	if _, err := os.Stat(objdumpPath); err != nil {
+		t.Skip(err)
+	}
+
+	testExtDis(t, "gnu", arch, objdump, generate, allowedMismatchObjdump)
+}
+
+func objdump(ext *ExtDis) error {
+	// File already written with instructions; add ELF header.
+	if ext.Arch == 32 {
+		if err := writeELF32(ext.File, ext.Size); err != nil {
+			return err
+		}
+	} else {
+		if err := writeELF64(ext.File, ext.Size); err != nil {
+			return err
+		}
+	}
+
+	b, err := ext.Run(objdumpPath, "-d", "-z", ext.File.Name())
+	if err != nil {
+		return err
+	}
+
+	var (
+		nmatch  int
+		reading bool
+		next    uint32 = start
+		addr    uint32
+		encbuf  [32]byte
+		enc     []byte
+		text    string
+	)
+	flush := func() {
+		if addr == next {
+			switch text {
+			case "repz":
+				text = "rep"
+			case "repnz":
+				text = "repn"
+			default:
+				text = strings.Replace(text, "repz ", "rep ", -1)
+				text = strings.Replace(text, "repnz ", "repn ", -1)
+			}
+			if m := pcrelw.FindStringSubmatch(text); m != nil {
+				targ, _ := strconv.ParseUint(m[2], 16, 64)
+				text = fmt.Sprintf("%s .%+#x", m[1], int16(uint32(targ)-uint32(uint16(addr))-uint32(len(enc))))
+			}
+			if m := pcrel.FindStringSubmatch(text); m != nil {
+				targ, _ := strconv.ParseUint(m[2], 16, 64)
+				text = fmt.Sprintf("%s .%+#x", m[1], int32(uint32(targ)-addr-uint32(len(enc))))
+			}
+			text = strings.Replace(text, "0x0(", "(", -1)
+			text = strings.Replace(text, "%st(0)", "%st", -1)
+
+			ext.Dec <- ExtInst{addr, encbuf, len(enc), text}
+			encbuf = [32]byte{}
+			enc = nil
+			next += 32
+		}
+	}
+	var textangle = []byte("<.text>:")
+	for {
+		line, err := b.ReadSlice('\n')
+		if err != nil {
+			if err == io.EOF {
+				break
+			}
+			return fmt.Errorf("reading objdump output: %v", err)
+		}
+		if bytes.Contains(line, textangle) {
+			reading = true
+			continue
+		}
+		if !reading {
+			continue
+		}
+		if debug {
+			os.Stdout.Write(line)
+		}
+		if enc1 := parseContinuation(line, encbuf[:len(enc)]); enc1 != nil {
+			enc = enc1
+			continue
+		}
+		flush()
+		nmatch++
+		addr, enc, text = parseLine(line, encbuf[:0])
+		if addr > next {
+			return fmt.Errorf("address out of sync expected <= %#x at %q in:\n%s", next, line, line)
+		}
+	}
+	flush()
+	if next != start+uint32(ext.Size) {
+		return fmt.Errorf("not enough results found [%d %d]", next, start+ext.Size)
+	}
+	if err := ext.Wait(); err != nil {
+		return fmt.Errorf("exec: %v", err)
+	}
+
+	return nil
+}
+
+func parseLine(line []byte, encstart []byte) (addr uint32, enc []byte, text string) {
+	oline := line
+	i := index(line, ":\t")
+	if i < 0 {
+		log.Fatalf("cannot parse disassembly: %q", oline)
+	}
+	x, err := strconv.ParseUint(string(trimSpace(line[:i])), 16, 32)
+	if err != nil {
+		log.Fatalf("cannot parse disassembly: %q", oline)
+	}
+	addr = uint32(x)
+	line = line[i+2:]
+	i = bytes.IndexByte(line, '\t')
+	if i < 0 {
+		log.Fatalf("cannot parse disassembly: %q", oline)
+	}
+	enc, ok := parseHex(line[:i], encstart)
+	if !ok {
+		log.Fatalf("cannot parse disassembly: %q", oline)
+	}
+	line = trimSpace(line[i:])
+	if i := bytes.IndexByte(line, '#'); i >= 0 {
+		line = trimSpace(line[:i])
+	}
+	text = string(fixSpace(line))
+	return
+}
+
+func parseContinuation(line []byte, enc []byte) []byte {
+	i := index(line, ":\t")
+	if i < 0 {
+		return nil
+	}
+	line = line[i+1:]
+	enc, _ = parseHex(line, enc)
+	return enc
+}
+
+// writeELF32 writes an ELF32 header to the file,
+// describing a text segment that starts at start
+// and extends for size bytes.
+func writeELF32(f *os.File, size int) error {
+	f.Seek(0, 0)
+	var hdr elf.Header32
+	var prog elf.Prog32
+	var sect elf.Section32
+	var buf bytes.Buffer
+	binary.Write(&buf, binary.LittleEndian, &hdr)
+	off1 := buf.Len()
+	binary.Write(&buf, binary.LittleEndian, &prog)
+	off2 := buf.Len()
+	binary.Write(&buf, binary.LittleEndian, &sect)
+	off3 := buf.Len()
+	buf.Reset()
+	data := byte(elf.ELFDATA2LSB)
+	hdr = elf.Header32{
+		Ident:     [16]byte{0x7F, 'E', 'L', 'F', 1, data, 1},
+		Type:      2,
+		Machine:   uint16(elf.EM_386),
+		Version:   1,
+		Entry:     start,
+		Phoff:     uint32(off1),
+		Shoff:     uint32(off2),
+		Flags:     0x05000002,
+		Ehsize:    uint16(off1),
+		Phentsize: uint16(off2 - off1),
+		Phnum:     1,
+		Shentsize: uint16(off3 - off2),
+		Shnum:     3,
+		Shstrndx:  2,
+	}
+	binary.Write(&buf, binary.LittleEndian, &hdr)
+	prog = elf.Prog32{
+		Type:   1,
+		Off:    start,
+		Vaddr:  start,
+		Paddr:  start,
+		Filesz: uint32(size),
+		Memsz:  uint32(size),
+		Flags:  5,
+		Align:  start,
+	}
+	binary.Write(&buf, binary.LittleEndian, &prog)
+	binary.Write(&buf, binary.LittleEndian, &sect) // NULL section
+	sect = elf.Section32{
+		Name:      1,
+		Type:      uint32(elf.SHT_PROGBITS),
+		Addr:      start,
+		Off:       start,
+		Size:      uint32(size),
+		Flags:     uint32(elf.SHF_ALLOC | elf.SHF_EXECINSTR),
+		Addralign: 4,
+	}
+	binary.Write(&buf, binary.LittleEndian, &sect) // .text
+	sect = elf.Section32{
+		Name:      uint32(len("\x00.text\x00")),
+		Type:      uint32(elf.SHT_STRTAB),
+		Addr:      0,
+		Off:       uint32(off2 + (off3-off2)*3),
+		Size:      uint32(len("\x00.text\x00.shstrtab\x00")),
+		Addralign: 1,
+	}
+	binary.Write(&buf, binary.LittleEndian, &sect)
+	buf.WriteString("\x00.text\x00.shstrtab\x00")
+	f.Write(buf.Bytes())
+	return nil
+}
+
+// writeELF64 writes an ELF64 header to the file,
+// describing a text segment that starts at start
+// and extends for size bytes.
+func writeELF64(f *os.File, size int) error {
+	f.Seek(0, 0)
+	var hdr elf.Header64
+	var prog elf.Prog64
+	var sect elf.Section64
+	var buf bytes.Buffer
+	binary.Write(&buf, binary.LittleEndian, &hdr)
+	off1 := buf.Len()
+	binary.Write(&buf, binary.LittleEndian, &prog)
+	off2 := buf.Len()
+	binary.Write(&buf, binary.LittleEndian, &sect)
+	off3 := buf.Len()
+	buf.Reset()
+	data := byte(elf.ELFDATA2LSB)
+	hdr = elf.Header64{
+		Ident:     [16]byte{0x7F, 'E', 'L', 'F', 2, data, 1},
+		Type:      2,
+		Machine:   uint16(elf.EM_X86_64),
+		Version:   1,
+		Entry:     start,
+		Phoff:     uint64(off1),
+		Shoff:     uint64(off2),
+		Flags:     0x05000002,
+		Ehsize:    uint16(off1),
+		Phentsize: uint16(off2 - off1),
+		Phnum:     1,
+		Shentsize: uint16(off3 - off2),
+		Shnum:     3,
+		Shstrndx:  2,
+	}
+	binary.Write(&buf, binary.LittleEndian, &hdr)
+	prog = elf.Prog64{
+		Type:   1,
+		Off:    start,
+		Vaddr:  start,
+		Paddr:  start,
+		Filesz: uint64(size),
+		Memsz:  uint64(size),
+		Flags:  5,
+		Align:  start,
+	}
+	binary.Write(&buf, binary.LittleEndian, &prog)
+	binary.Write(&buf, binary.LittleEndian, &sect) // NULL section
+	sect = elf.Section64{
+		Name:      1,
+		Type:      uint32(elf.SHT_PROGBITS),
+		Addr:      start,
+		Off:       start,
+		Size:      uint64(size),
+		Flags:     uint64(elf.SHF_ALLOC | elf.SHF_EXECINSTR),
+		Addralign: 4,
+	}
+	binary.Write(&buf, binary.LittleEndian, &sect) // .text
+	sect = elf.Section64{
+		Name:      uint32(len("\x00.text\x00")),
+		Type:      uint32(elf.SHT_STRTAB),
+		Addr:      0,
+		Off:       uint64(off2 + (off3-off2)*3),
+		Size:      uint64(len("\x00.text\x00.shstrtab\x00")),
+		Addralign: 1,
+	}
+	binary.Write(&buf, binary.LittleEndian, &sect)
+	buf.WriteString("\x00.text\x00.shstrtab\x00")
+	f.Write(buf.Bytes())
+	return nil
+}
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9ext_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9ext_test.go
new file mode 100644
index 0000000..9bd296c
--- /dev/null
+++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9ext_test.go
@@ -0,0 +1,119 @@
+// 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 x86asm
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"log"
+	"os"
+	"strconv"
+	"testing"
+)
+
+const plan9Path = "testdata/libmach8db"
+
+func testPlan9Arch(t *testing.T, arch int, generate func(func([]byte))) {
+	if testing.Short() {
+		t.Skip("skipping libmach test in short mode")
+	}
+	if _, err := os.Stat(plan9Path); err != nil {
+		t.Skip(err)
+	}
+
+	testExtDis(t, "plan9", arch, plan9, generate, allowedMismatchPlan9)
+}
+
+func testPlan932(t *testing.T, generate func(func([]byte))) {
+	testPlan9Arch(t, 32, generate)
+}
+
+func testPlan964(t *testing.T, generate func(func([]byte))) {
+	testPlan9Arch(t, 64, generate)
+}
+
+func plan9(ext *ExtDis) error {
+	flag := "-8"
+	if ext.Arch == 64 {
+		flag = "-6"
+	}
+	b, err := ext.Run(plan9Path, flag, ext.File.Name())
+	if err != nil {
+		return err
+	}
+
+	nmatch := 0
+	next := uint32(start)
+	var (
+		addr   uint32
+		encbuf [32]byte
+		enc    []byte
+		text   string
+	)
+
+	for {
+		line, err := b.ReadSlice('\n')
+		if err != nil {
+			if err == io.EOF {
+				break
+			}
+			return fmt.Errorf("reading libmach8db output: %v", err)
+		}
+		if debug {
+			os.Stdout.Write(line)
+		}
+		nmatch++
+		addr, enc, text = parseLinePlan9(line, encbuf[:0])
+		if addr > next {
+			return fmt.Errorf("address out of sync expected <= %#x at %q in:\n%s", next, line, line)
+		}
+		if addr < next {
+			continue
+		}
+		if m := pcrelw.FindStringSubmatch(text); m != nil {
+			targ, _ := strconv.ParseUint(m[2], 16, 64)
+			text = fmt.Sprintf("%s .%+#x", m[1], int16(uint32(targ)-uint32(uint16(addr))-uint32(len(enc))))
+		}
+		if m := pcrel.FindStringSubmatch(text); m != nil {
+			targ, _ := strconv.ParseUint(m[2], 16, 64)
+			text = fmt.Sprintf("%s .%+#x", m[1], int32(uint32(targ)-addr-uint32(len(enc))))
+		}
+		ext.Dec <- ExtInst{addr, encbuf, len(enc), text}
+		encbuf = [32]byte{}
+		enc = nil
+		next += 32
+	}
+	if next != start+uint32(ext.Size) {
+		return fmt.Errorf("not enough results found [%d %d]", next, start+ext.Size)
+	}
+	if err := ext.Wait(); err != nil {
+		return fmt.Errorf("exec: %v", err)
+	}
+
+	return nil
+}
+
+func parseLinePlan9(line []byte, encstart []byte) (addr uint32, enc []byte, text string) {
+	i := bytes.IndexByte(line, ' ')
+	if i < 0 || line[0] != '0' || line[1] != 'x' {
+		log.Fatalf("cannot parse disassembly: %q", line)
+	}
+	j := bytes.IndexByte(line[i+1:], ' ')
+	if j < 0 {
+		log.Fatalf("cannot parse disassembly: %q", line)
+	}
+	j += i + 1
+	x, err := strconv.ParseUint(string(trimSpace(line[2:i])), 16, 32)
+	if err != nil {
+		log.Fatalf("cannot parse disassembly: %q", line)
+	}
+	addr = uint32(x)
+	enc, ok := parseHex(line[i+1:j], encstart)
+	if !ok {
+		log.Fatalf("cannot parse disassembly: %q", line)
+	}
+	return addr, enc, string(fixSpace(line[j+1:]))
+}
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9x.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9x.go
new file mode 100644
index 0000000..afe6a92
--- /dev/null
+++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9x.go
@@ -0,0 +1,346 @@
+// 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 x86asm
+
+import (
+	"fmt"
+	"strings"
+)
+
+// GoSyntax returns the Go assembler syntax for the instruction.
+// The syntax was originally defined by Plan 9.
+// The pc is the program counter of the instruction, used for expanding
+// PC-relative addresses into absolute ones.
+// The symname function queries the symbol table for the program
+// being disassembled. Given a target address it returns the name and base
+// address of the symbol containing the target, if any; otherwise it returns "", 0.
+func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) string {
+	if symname == nil {
+		symname = func(uint64) (string, uint64) { return "", 0 }
+	}
+	var args []string
+	for i := len(inst.Args) - 1; i >= 0; i-- {
+		a := inst.Args[i]
+		if a == nil {
+			continue
+		}
+		args = append(args, plan9Arg(&inst, pc, symname, a))
+	}
+
+	var last Prefix
+	for _, p := range inst.Prefix {
+		if p == 0 || p.IsREX() {
+			break
+		}
+		last = p
+	}
+
+	prefix := ""
+	switch last & 0xFF {
+	case 0, 0x66, 0x67:
+		// ignore
+	case PrefixREPN:
+		prefix += "REPNE "
+	default:
+		prefix += last.String() + " "
+	}
+
+	op := inst.Op.String()
+	if plan9Suffix[inst.Op] {
+		switch inst.DataSize {
+		case 8:
+			op += "B"
+		case 16:
+			op += "W"
+		case 32:
+			op += "L"
+		case 64:
+			op += "Q"
+		}
+	}
+
+	if args != nil {
+		op += " " + strings.Join(args, ", ")
+	}
+
+	return prefix + op
+}
+
+func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string {
+	switch a := arg.(type) {
+	case Reg:
+		return plan9Reg[a]
+	case Rel:
+		if pc == 0 {
+			break
+		}
+		// If the absolute address is the start of a symbol, use the name.
+		// Otherwise use the raw address, so that things like relative
+		// jumps show up as JMP 0x123 instead of JMP f+10(SB).
+		// It is usually easier to search for 0x123 than to do the mental
+		// arithmetic to find f+10.
+		addr := pc + uint64(inst.Len) + uint64(a)
+		if s, base := symname(addr); s != "" && addr == base {
+			return fmt.Sprintf("%s(SB)", s)
+		}
+		return fmt.Sprintf("%#x", addr)
+
+	case Imm:
+		if s, base := symname(uint64(a)); s != "" {
+			suffix := ""
+			if uint64(a) != base {
+				suffix = fmt.Sprintf("%+d", uint64(a)-base)
+			}
+			return fmt.Sprintf("$%s%s(SB)", s, suffix)
+		}
+		if inst.Mode == 32 {
+			return fmt.Sprintf("$%#x", uint32(a))
+		}
+		if Imm(int32(a)) == a {
+			return fmt.Sprintf("$%#x", int64(a))
+		}
+		return fmt.Sprintf("$%#x", uint64(a))
+	case Mem:
+		if a.Segment == 0 && a.Disp != 0 && a.Base == 0 && (a.Index == 0 || a.Scale == 0) {
+			if s, base := symname(uint64(a.Disp)); s != "" {
+				suffix := ""
+				if uint64(a.Disp) != base {
+					suffix = fmt.Sprintf("%+d", uint64(a.Disp)-base)
+				}
+				return fmt.Sprintf("%s%s(SB)", s, suffix)
+			}
+		}
+		s := ""
+		if a.Segment != 0 {
+			s += fmt.Sprintf("%s:", plan9Reg[a.Segment])
+		}
+		if a.Disp != 0 {
+			s += fmt.Sprintf("%#x", a.Disp)
+		} else {
+			s += "0"
+		}
+		if a.Base != 0 {
+			s += fmt.Sprintf("(%s)", plan9Reg[a.Base])
+		}
+		if a.Index != 0 && a.Scale != 0 {
+			s += fmt.Sprintf("(%s*%d)", plan9Reg[a.Index], a.Scale)
+		}
+		return s
+	}
+	return arg.String()
+}
+
+var plan9Suffix = [maxOp + 1]bool{
+	ADC:       true,
+	ADD:       true,
+	AND:       true,
+	BSF:       true,
+	BSR:       true,
+	BT:        true,
+	BTC:       true,
+	BTR:       true,
+	BTS:       true,
+	CMP:       true,
+	CMPXCHG:   true,
+	CVTSI2SD:  true,
+	CVTSI2SS:  true,
+	CVTSD2SI:  true,
+	CVTSS2SI:  true,
+	CVTTSD2SI: true,
+	CVTTSS2SI: true,
+	DEC:       true,
+	DIV:       true,
+	FLDENV:    true,
+	FRSTOR:    true,
+	IDIV:      true,
+	IMUL:      true,
+	IN:        true,
+	INC:       true,
+	LEA:       true,
+	MOV:       true,
+	MOVNTI:    true,
+	MUL:       true,
+	NEG:       true,
+	NOP:       true,
+	NOT:       true,
+	OR:        true,
+	OUT:       true,
+	POP:       true,
+	POPA:      true,
+	PUSH:      true,
+	PUSHA:     true,
+	RCL:       true,
+	RCR:       true,
+	ROL:       true,
+	ROR:       true,
+	SAR:       true,
+	SBB:       true,
+	SHL:       true,
+	SHLD:      true,
+	SHR:       true,
+	SHRD:      true,
+	SUB:       true,
+	TEST:      true,
+	XADD:      true,
+	XCHG:      true,
+	XOR:       true,
+}
+
+var plan9Reg = [...]string{
+	AL:   "AL",
+	CL:   "CL",
+	BL:   "BL",
+	DL:   "DL",
+	AH:   "AH",
+	CH:   "CH",
+	BH:   "BH",
+	DH:   "DH",
+	SPB:  "SP",
+	BPB:  "BP",
+	SIB:  "SI",
+	DIB:  "DI",
+	R8B:  "R8",
+	R9B:  "R9",
+	R10B: "R10",
+	R11B: "R11",
+	R12B: "R12",
+	R13B: "R13",
+	R14B: "R14",
+	R15B: "R15",
+	AX:   "AX",
+	CX:   "CX",
+	BX:   "BX",
+	DX:   "DX",
+	SP:   "SP",
+	BP:   "BP",
+	SI:   "SI",
+	DI:   "DI",
+	R8W:  "R8",
+	R9W:  "R9",
+	R10W: "R10",
+	R11W: "R11",
+	R12W: "R12",
+	R13W: "R13",
+	R14W: "R14",
+	R15W: "R15",
+	EAX:  "AX",
+	ECX:  "CX",
+	EDX:  "DX",
+	EBX:  "BX",
+	ESP:  "SP",
+	EBP:  "BP",
+	ESI:  "SI",
+	EDI:  "DI",
+	R8L:  "R8",
+	R9L:  "R9",
+	R10L: "R10",
+	R11L: "R11",
+	R12L: "R12",
+	R13L: "R13",
+	R14L: "R14",
+	R15L: "R15",
+	RAX:  "AX",
+	RCX:  "CX",
+	RDX:  "DX",
+	RBX:  "BX",
+	RSP:  "SP",
+	RBP:  "BP",
+	RSI:  "SI",
+	RDI:  "DI",
+	R8:   "R8",
+	R9:   "R9",
+	R10:  "R10",
+	R11:  "R11",
+	R12:  "R12",
+	R13:  "R13",
+	R14:  "R14",
+	R15:  "R15",
+	IP:   "IP",
+	EIP:  "IP",
+	RIP:  "IP",
+	F0:   "F0",
+	F1:   "F1",
+	F2:   "F2",
+	F3:   "F3",
+	F4:   "F4",
+	F5:   "F5",
+	F6:   "F6",
+	F7:   "F7",
+	M0:   "M0",
+	M1:   "M1",
+	M2:   "M2",
+	M3:   "M3",
+	M4:   "M4",
+	M5:   "M5",
+	M6:   "M6",
+	M7:   "M7",
+	X0:   "X0",
+	X1:   "X1",
+	X2:   "X2",
+	X3:   "X3",
+	X4:   "X4",
+	X5:   "X5",
+	X6:   "X6",
+	X7:   "X7",
+	X8:   "X8",
+	X9:   "X9",
+	X10:  "X10",
+	X11:  "X11",
+	X12:  "X12",
+	X13:  "X13",
+	X14:  "X14",
+	X15:  "X15",
+	CS:   "CS",
+	SS:   "SS",
+	DS:   "DS",
+	ES:   "ES",
+	FS:   "FS",
+	GS:   "GS",
+	GDTR: "GDTR",
+	IDTR: "IDTR",
+	LDTR: "LDTR",
+	MSW:  "MSW",
+	TASK: "TASK",
+	CR0:  "CR0",
+	CR1:  "CR1",
+	CR2:  "CR2",
+	CR3:  "CR3",
+	CR4:  "CR4",
+	CR5:  "CR5",
+	CR6:  "CR6",
+	CR7:  "CR7",
+	CR8:  "CR8",
+	CR9:  "CR9",
+	CR10: "CR10",
+	CR11: "CR11",
+	CR12: "CR12",
+	CR13: "CR13",
+	CR14: "CR14",
+	CR15: "CR15",
+	DR0:  "DR0",
+	DR1:  "DR1",
+	DR2:  "DR2",
+	DR3:  "DR3",
+	DR4:  "DR4",
+	DR5:  "DR5",
+	DR6:  "DR6",
+	DR7:  "DR7",
+	DR8:  "DR8",
+	DR9:  "DR9",
+	DR10: "DR10",
+	DR11: "DR11",
+	DR12: "DR12",
+	DR13: "DR13",
+	DR14: "DR14",
+	DR15: "DR15",
+	TR0:  "TR0",
+	TR1:  "TR1",
+	TR2:  "TR2",
+	TR3:  "TR3",
+	TR4:  "TR4",
+	TR5:  "TR5",
+	TR6:  "TR6",
+	TR7:  "TR7",
+}
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/plan9x_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9x_test.go
similarity index 100%
rename from src/cmd/internal/rsc.io/x86/x86asm/plan9x_test.go
rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9x_test.go
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/tables.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/tables.go
similarity index 100%
rename from src/cmd/internal/rsc.io/x86/x86asm/tables.go
rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/tables.go
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/testdata/Makefile b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/Makefile
similarity index 100%
rename from src/cmd/internal/rsc.io/x86/x86asm/testdata/Makefile
rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/Makefile
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/testdata/decode.txt b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/decode.txt
similarity index 100%
rename from src/cmd/internal/rsc.io/x86/x86asm/testdata/decode.txt
rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/decode.txt
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/libmach8db.c b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/libmach8db.c
new file mode 100644
index 0000000..90ace52
--- /dev/null
+++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/libmach8db.c
@@ -0,0 +1,2075 @@
+// 9c libmach8db.c && 9l -o libmach8db libmach8db.o; rm libmach8db.o
+
+// Libmach-based disassembler for use in reference tests.
+
+// Inferno libmach/8db.c
+// http://code.google.com/p/inferno-os/source/browse/utils/libmach/8db.c
+//
+//	Copyright © 1994-1999 Lucent Technologies Inc.
+//	Power PC support Copyright © 1995-2004 C H Forsyth (forsyth at terzarima.net).
+//	Portions Copyright © 1997-1999 Vita Nuova Limited.
+//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com).
+//	Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
+//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+typedef struct Map Map;
+struct Map
+{
+	int (*get1)(Map*, uvlong, uchar*, int);
+	uchar *p;
+	uchar *ep;
+	uchar *startp;
+	uvlong startpc;
+};
+
+static int
+get1(Map *m, uvlong addr, uchar *p, int n)
+{
+	return m->get1(m, addr, p, n);
+}
+
+/*
+ * i386-specific debugger interface
+ * also amd64 extensions
+ */
+
+static	int	i386inst(Map*, uvlong, int, char, char*, int);
+//static	int	i386das(Map*, uvlong, char*, int);
+//static	int	i386instlen(Map*, uvlong);
+
+	/* I386/486 - Disassembler and related functions */
+
+/*
+ *  an instruction
+ */
+typedef struct Instr Instr;
+struct	Instr
+{
+	uchar	mem[1+1+1+1+2+1+1+4+4];		/* raw instruction */
+	uvlong	addr;		/* address of start of instruction */
+	int	n;		/* number of bytes in instruction */
+	char	*prefix;	/* instr prefix */
+	char	*segment;	/* segment override */
+	uchar	jumptype;	/* set to the operand type for jump/ret/call */
+	uchar	amd64;
+	uchar	rex;		/* REX prefix (or zero) */
+	uchar	op;
+	char	osize;		/* 'W' or 'L' (or 'Q' on amd64) */
+	char	asize;		/* address size 'W' or 'L' (or 'Q' or amd64) */
+	uchar	mod;		/* bits 6-7 of mod r/m field */
+	uchar	reg;		/* bits 3-5 of mod r/m field */
+	char	ss;		/* bits 6-7 of SIB */
+	schar	index;		/* bits 3-5 of SIB */
+	schar	base;		/* bits 0-2 of SIB */
+	char	rip;		/* RIP-relative in amd64 mode */
+	uchar	opre;		/* f2/f3 could introduce media */
+	short	seg;		/* segment of far address */
+	uint32	disp;		/* displacement */
+	uint32 	imm;		/* immediate */
+	uint32 	imm2;		/* second immediate operand */
+	uvlong	imm64;		/* big immediate */
+	char	*curr;		/* fill level in output buffer */
+	char	*end;		/* end of output buffer */
+	char	*err;		/* error message */
+};
+
+	/* 386 register (ha!) set */
+enum{
+	AX=0,
+	CX,
+	DX,
+	BX,
+	SP,
+	BP,
+	SI,
+	DI,
+
+	/* amd64 */
+	/* be careful: some unix system headers #define R8, R9, etc */
+	AMD64_R8,
+	AMD64_R9,
+	AMD64_R10,
+	AMD64_R11,
+	AMD64_R12,
+	AMD64_R13,
+	AMD64_R14,
+	AMD64_R15
+};
+
+	/* amd64 rex extension byte */
+enum{
+	REXW		= 1<<3,	/* =1, 64-bit operand size */
+	REXR		= 1<<2,	/* extend modrm reg */
+	REXX		= 1<<1,	/* extend sib index */
+	REXB		= 1<<0	/* extend modrm r/m, sib base, or opcode reg */
+};
+
+	/* Operand Format codes */
+/*
+%A	-	address size register modifier (!asize -> 'E')
+%C	-	Control register CR0/CR1/CR2
+%D	-	Debug register DR0/DR1/DR2/DR3/DR6/DR7
+%I	-	second immediate operand
+%O	-	Operand size register modifier (!osize -> 'E')
+%T	-	Test register TR6/TR7
+%S	-	size code ('W' or 'L')
+%W	-	Weird opcode: OSIZE == 'W' => "CBW"; else => "CWDE"
+%d	-	displacement 16-32 bits
+%e	-	effective address - Mod R/M value
+%f	-	floating point register F0-F7 - from Mod R/M register
+%g	-	segment register
+%i	-	immediate operand 8-32 bits
+%o	- 	register from opcode and REX.B
+%p	-	PC-relative - signed displacement in immediate field
+%r	-	Reg from Mod R/M
+%w	-	Weird opcode: OSIZE == 'W' => "CWD"; else => "CDQ"
+*/
+
+typedef struct Optable Optable;
+struct Optable
+{
+	char	operand[2];
+	void	*proto;		/* actually either (char*) or (Optable*) */
+};
+	/* Operand decoding codes */
+enum {
+	Ib = 1,			/* 8-bit immediate - (no sign extension)*/
+	Ibs,			/* 8-bit immediate (sign extended) */
+	Jbs,			/* 8-bit sign-extended immediate in jump or call */
+	Iw,			/* 16-bit immediate -> imm */
+	Iw2,			/* 16-bit immediate -> imm2 */
+	Iwd,			/* Operand-sized immediate (no sign extension)*/
+	Iwdq,			/* Operand-sized immediate, possibly 64 bits */
+	Awd,			/* Address offset */
+	Iwds,			/* Operand-sized immediate (sign extended) */
+	RM,			/* Word or int32 R/M field with register (/r) */
+	RMB,			/* Byte R/M field with register (/r) */
+	RMOP,			/* Word or int32 R/M field with op code (/digit) */
+	RMOPB,			/* Byte R/M field with op code (/digit) */
+	RMR,			/* R/M register only (mod = 11) */
+	RMM,			/* R/M memory only (mod = 0/1/2) */
+	Op_R0,			/* Base reg of Mod R/M is literal 0x00 */
+	Op_R1,			/* Base reg of Mod R/M is literal 0x01 */
+	FRMOP,			/* Floating point R/M field with opcode */
+	FRMEX,			/* Extended floating point R/M field with opcode */
+	JUMP,			/* Jump or Call flag - no operand */
+	RET,			/* Return flag - no operand */
+	OA,			/* literal 0x0a byte */
+	PTR,			/* Seg:Displacement addr (ptr16:16 or ptr16:32) */
+	AUX,			/* Multi-byte op code - Auxiliary table */
+	AUXMM,			/* multi-byte op code - auxiliary table chosen by prefix */
+	PRE,			/* Instr Prefix */
+	OPRE,			/* Instr Prefix or media op extension */
+	SEG,			/* Segment Prefix */
+	OPOVER,			/* Operand size override */
+	ADDOVER,		/* Address size override */
+};
+
+static Optable optab0F00[8]=
+{
+[0x00] =	{ 0,0,		"MOVW	LDT,%e" },
+[0x01] =	{ 0,0,		"MOVW	TR,%e" },
+[0x02] =	{ 0,0,		"MOVW	%e,LDT" },
+[0x03] =	{ 0,0,		"MOVW	%e,TR" },
+[0x04] =	{ 0,0,		"VERR	%e" },
+[0x05] =	{ 0,0,		"VERW	%e" },
+};
+
+static Optable optab0F01[8]=
+{
+[0x00] =	{ 0,0,		"MOVL	GDTR,%e" },
+[0x01] =	{ 0,0,		"MOVL	IDTR,%e" },
+[0x02] =	{ 0,0,		"MOVL	%e,GDTR" },
+[0x03] =	{ 0,0,		"MOVL	%e,IDTR" },
+[0x04] =	{ 0,0,		"MOVW	MSW,%e" },	/* word */
+[0x06] =	{ 0,0,		"MOVW	%e,MSW" },	/* word */
+[0x07] =	{ 0,0,		"INVLPG	%e" },		/* or SWAPGS */
+};
+
+static Optable optab0F01F8[1]=
+{
+[0x00] =	{ 0,0,		"SWAPGS" },
+};
+
+/* 0F71 */
+/* 0F72 */
+/* 0F73 */
+
+static Optable optab0FAE[8]=
+{
+[0x00] =	{ 0,0,		"FXSAVE	%e" },
+[0x01] =	{ 0,0,		"FXRSTOR	%e" },
+[0x02] =	{ 0,0,		"LDMXCSR	%e" },
+[0x03] =	{ 0,0,		"STMXCSR	%e" },
+[0x05] =	{ 0,0,		"LFENCE" },
+[0x06] =	{ 0,0,		"MFENCE" },
+[0x07] =	{ 0,0,		"SFENCE" },
+};
+
+/* 0F18 */
+/* 0F0D */
+
+static Optable optab0FBA[8]=
+{
+[0x04] =	{ Ib,0,		"BT%S	%i,%e" },
+[0x05] =	{ Ib,0,		"BTS%S	%i,%e" },
+[0x06] =	{ Ib,0,		"BTR%S	%i,%e" },
+[0x07] =	{ Ib,0,		"BTC%S	%i,%e" },
+};
+
+static Optable optab0F0F[256]=
+{
+[0x0c] =	{ 0,0,		"PI2FW	%m,%M" },
+[0x0d] =	{ 0,0,		"PI2L	%m,%M" },
+[0x1c] =	{ 0,0,		"PF2IW	%m,%M" },
+[0x1d] =	{ 0,0,		"PF2IL	%m,%M" },
+[0x8a] =	{ 0,0,		"PFNACC	%m,%M" },
+[0x8e] =	{ 0,0,		"PFPNACC	%m,%M" },
+[0x90] =	{ 0,0,		"PFCMPGE	%m,%M" },
+[0x94] =	{ 0,0,		"PFMIN	%m,%M" },
+[0x96] =	{ 0,0,		"PFRCP	%m,%M" },
+[0x97] =	{ 0,0,		"PFRSQRT	%m,%M" },
+[0x9a] =	{ 0,0,		"PFSUB	%m,%M" },
+[0x9e] =	{ 0,0,		"PFADD	%m,%M" },
+[0xa0] =	{ 0,0,		"PFCMPGT	%m,%M" },
+[0xa4] =	{ 0,0,		"PFMAX	%m,%M" },
+[0xa6] =	{ 0,0,		"PFRCPIT1	%m,%M" },
+[0xa7] =	{ 0,0,		"PFRSQIT1	%m,%M" },
+[0xaa] =	{ 0,0,		"PFSUBR	%m,%M" },
+[0xae] =	{ 0,0,		"PFACC	%m,%M" },
+[0xb0] =	{ 0,0,		"PFCMPEQ	%m,%M" },
+[0xb4] =	{ 0,0,		"PFMUL	%m,%M" },
+[0xb6] =	{ 0,0,		"PFRCPI2T	%m,%M" },
+[0xb7] =	{ 0,0,		"PMULHRW	%m,%M" },
+[0xbb] =	{ 0,0,		"PSWAPL	%m,%M" },
+};
+
+static Optable optab0FC7[8]=
+{
+[0x01] =	{ 0,0,		"CMPXCHG8B	%e" },
+};
+
+static Optable optab660F71[8]=
+{
+[0x02] =	{ Ib,0,		"PSRLW	%i,%X" },
+[0x04] =	{ Ib,0,		"PSRAW	%i,%X" },
+[0x06] =	{ Ib,0,		"PSLLW	%i,%X" },
+};
+
+static Optable optab660F72[8]=
+{
+[0x02] =	{ Ib,0,		"PSRLL	%i,%X" },
+[0x04] =	{ Ib,0,		"PSRAL	%i,%X" },
+[0x06] =	{ Ib,0,		"PSLLL	%i,%X" },
+};
+
+static Optable optab660F73[8]=
+{
+[0x02] =	{ Ib,0,		"PSRLQ	%i,%X" },
+[0x03] =	{ Ib,0,		"PSRLO	%i,%X" },
+[0x06] =	{ Ib,0,		"PSLLQ	%i,%X" },
+[0x07] =	{ Ib,0,		"PSLLO	%i,%X" },
+};
+
+static Optable optab660F[256]=
+{
+[0x2B] =	{ RM,0,		"MOVNTPD	%x,%e" },
+[0x2E] =	{ RM,0,		"UCOMISD	%x,%X" },
+[0x2F] =	{ RM,0,		"COMISD	%x,%X" },
+[0x5A] =	{ RM,0,		"CVTPD2PS	%x,%X" },
+[0x5B] =	{ RM,0,		"CVTPS2PL	%x,%X" },
+[0x6A] =	{ RM,0,		"PUNPCKHLQ %x,%X" },
+[0x6B] =	{ RM,0,		"PACKSSLW %x,%X" },
+[0x6C] =	{ RM,0,		"PUNPCKLQDQ %x,%X" },
+[0x6D] =	{ RM,0,		"PUNPCKHQDQ %x,%X" },
+[0x6E] =	{ RM,0,		"MOV%S	%e,%X" },
+[0x6F] =	{ RM,0,		"MOVO	%x,%X" },		/* MOVDQA */
+[0x70] =	{ RM,Ib,		"PSHUFL	%i,%x,%X" },
+[0x71] =	{ RMOP,0,		optab660F71 },
+[0x72] =	{ RMOP,0,		optab660F72 },
+[0x73] =	{ RMOP,0,		optab660F73 },
+[0x7E] =	{ RM,0,		"MOV%S	%X,%e" },
+[0x7F] =	{ RM,0,		"MOVO	%X,%x" },
+[0xC4] =	{ RM,Ib,		"PINSRW	%i,%e,%X" },
+[0xC5] =	{ RMR,Ib,		"PEXTRW	%i,%X,%e" },
+[0xD4] =	{ RM,0,		"PADDQ	%x,%X" },
+[0xD5] =	{ RM,0,		"PMULLW	%x,%X" },
+[0xD6] =	{ RM,0,		"MOVQ	%X,%x" },
+[0xE6] =	{ RM,0,		"CVTTPD2PL	%x,%X" },
+[0xE7] =	{ RM,0,		"MOVNTO	%X,%e" },
+[0xF7] =	{ RM,0,		"MASKMOVOU	%x,%X" },
+};
+
+static Optable optabF20F[256]=
+{
+[0x10] =	{ RM,0,		"MOVSD	%x,%X" },
+[0x11] =	{ RM,0,		"MOVSD	%X,%x" },
+[0x2A] =	{ RM,0,		"CVTS%S2SD	%e,%X" },
+[0x2C] =	{ RM,0,		"CVTTSD2S%S	%x,%r" },
+[0x2D] =	{ RM,0,		"CVTSD2S%S	%x,%r" },
+[0x5A] =	{ RM,0,		"CVTSD2SS	%x,%X" },
+[0x6F] =	{ RM,0,		"MOVOU	%x,%X" },
+[0x70] =	{ RM,Ib,		"PSHUFLW	%i,%x,%X" },
+[0x7F] =	{ RM,0,		"MOVOU	%X,%x" },
+[0xD6] =	{ RM,0,		"MOVQOZX	%M,%X" },
+[0xE6] =	{ RM,0,		"CVTPD2PL	%x,%X" },
+};
+
+static Optable optabF30F[256]=
+{
+[0x10] =	{ RM,0,		"MOVSS	%x,%X" },
+[0x11] =	{ RM,0,		"MOVSS	%X,%x" },
+[0x2A] =	{ RM,0,		"CVTS%S2SS	%e,%X" },
+[0x2C] =	{ RM,0,		"CVTTSS2S%S	%x,%r" },
+[0x2D] =	{ RM,0,		"CVTSS2S%S	%x,%r" },
+[0x5A] =	{ RM,0,		"CVTSS2SD	%x,%X" },
+[0x5B] =	{ RM,0,		"CVTTPS2PL	%x,%X" },
+[0x6F] =	{ RM,0,		"MOVOU	%x,%X" },
+[0x70] =	{ RM,Ib,		"PSHUFHW	%i,%x,%X" },
+[0x7E] =	{ RM,0,		"MOVQOZX	%x,%X" },
+[0x7F] =	{ RM,0,		"MOVOU	%X,%x" },
+[0xD6] =	{ RM,0,		"MOVQOZX	%m*,%X" },
+[0xE6] =	{ RM,0,		"CVTPL2PD	%x,%X" },
+};
+
+static Optable optab0F[256]=
+{
+[0x00] =	{ RMOP,0,		optab0F00 },
+[0x01] =	{ RMOP,0,		optab0F01 },
+[0x02] =	{ RM,0,		"LAR	%e,%r" },
+[0x03] =	{ RM,0,		"LSL	%e,%r" },
+[0x05] =	{ 0,0,		"SYSCALL" },
+[0x06] =	{ 0,0,		"CLTS" },
+[0x07] =	{ 0,0,		"SYSRET" },
+[0x08] =	{ 0,0,		"INVD" },
+[0x09] =	{ 0,0,		"WBINVD" },
+[0x0B] =	{ 0,0,		"UD2" },
+[0x0F] =	{ RM,AUX,		optab0F0F },		/* 3DNow! */
+[0x10] =	{ RM,0,		"MOVU%s	%x,%X" },
+[0x11] =	{ RM,0,		"MOVU%s	%X,%x" },
+[0x12] =	{ RM,0,		"MOV[H]L%s	%x,%X" },	/* TO DO: H if source is XMM */
+[0x13] =	{ RM,0,		"MOVL%s	%X,%e" },
+[0x14] =	{ RM,0,		"UNPCKL%s	%x,%X" },
+[0x15] =	{ RM,0,		"UNPCKH%s	%x,%X" },
+[0x16] =	{ RM,0,		"MOV[L]H%s	%x,%X" },	/* TO DO: L if source is XMM */
+[0x17] =	{ RM,0,		"MOVH%s	%X,%x" },
+[0x1F] =	{ RM,0,		"NOP%S	%e" },
+[0x20] =	{ RMR,0,		"MOVL	%C,%e" },
+[0x21] =	{ RMR,0,		"MOVL	%D,%e" },
+[0x22] =	{ RMR,0,		"MOVL	%e,%C" },
+[0x23] =	{ RMR,0,		"MOVL	%e,%D" },
+[0x24] =	{ RMR,0,		"MOVL	%T,%e" },
+[0x26] =	{ RMR,0,		"MOVL	%e,%T" },
+[0x28] =	{ RM,0,		"MOVA%s	%x,%X" },
+[0x29] =	{ RM,0,		"MOVA%s	%X,%x" },
+[0x2A] =	{ RM,0,		"CVTPL2%s	%m*,%X" },
+[0x2B] =	{ RM,0,		"MOVNT%s	%X,%e" },
+[0x2C] =	{ RM,0,		"CVTT%s2PL	%x,%M" },
+[0x2D] =	{ RM,0,		"CVT%s2PL	%x,%M" },
+[0x2E] =	{ RM,0,		"UCOMISS	%x,%X" },
+[0x2F] =	{ RM,0,		"COMISS	%x,%X" },
+[0x30] =	{ 0,0,		"WRMSR" },
+[0x31] =	{ 0,0,		"RDTSC" },
+[0x32] =	{ 0,0,		"RDMSR" },
+[0x33] =	{ 0,0,		"RDPMC" },
+[0x42] =	{ RM,0,		"CMOVC	%e,%r" },		/* CF */
+[0x43] =	{ RM,0,		"CMOVNC	%e,%r" },		/* ¬ CF */
+[0x44] =	{ RM,0,		"CMOVZ	%e,%r" },		/* ZF */
+[0x45] =	{ RM,0,		"CMOVNZ	%e,%r" },		/* ¬ ZF */
+[0x46] =	{ RM,0,		"CMOVBE	%e,%r" },		/* CF ∨ ZF */
+[0x47] =	{ RM,0,		"CMOVA	%e,%r" },		/* ¬CF ∧ ¬ZF */
+[0x48] =	{ RM,0,		"CMOVS	%e,%r" },		/* SF */
+[0x49] =	{ RM,0,		"CMOVNS	%e,%r" },		/* ¬ SF */
+[0x4A] =	{ RM,0,		"CMOVP	%e,%r" },		/* PF */
+[0x4B] =	{ RM,0,		"CMOVNP	%e,%r" },		/* ¬ PF */
+[0x4C] =	{ RM,0,		"CMOVLT	%e,%r" },		/* LT ≡ OF ≠ SF */
+[0x4D] =	{ RM,0,		"CMOVGE	%e,%r" },		/* GE ≡ ZF ∨ SF */
+[0x4E] =	{ RM,0,		"CMOVLE	%e,%r" },		/* LE ≡ ZF ∨ LT */
+[0x4F] =	{ RM,0,		"CMOVGT	%e,%r" },		/* GT ≡ ¬ZF ∧ GE */
+[0x50] =	{ RM,0,		"MOVMSK%s	%X,%r" },	/* TO DO: check */
+[0x51] =	{ RM,0,		"SQRT%s	%x,%X" },
+[0x52] =	{ RM,0,		"RSQRT%s	%x,%X" },
+[0x53] =	{ RM,0,		"RCP%s	%x,%X" },
+[0x54] =	{ RM,0,		"AND%s	%x,%X" },
+[0x55] =	{ RM,0,		"ANDN%s	%x,%X" },
+[0x56] =	{ RM,0,		"OR%s	%x,%X" },		/* TO DO: S/D */
+[0x57] =	{ RM,0,		"XOR%s	%x,%X" },		/* S/D */
+[0x58] =	{ RM,0,		"ADD%s	%x,%X" },		/* S/P S/D */
+[0x59] =	{ RM,0,		"MUL%s	%x,%X" },
+[0x5A] =	{ RM,0,		"CVTPS2PD	%x,%X" },
+[0x5B] =	{ RM,0,		"CVTPL2PS	%x,%X" },
+[0x5C] =	{ RM,0,		"SUB%s	%x,%X" },
+[0x5D] =	{ RM,0,		"MIN%s	%x,%X" },
+[0x5E] =	{ RM,0,		"DIV%s	%x,%X" },		/* TO DO: S/P S/D */
+[0x5F] =	{ RM,0,		"MAX%s	%x,%X" },
+[0x60] =	{ RM,0,		"PUNPCKLBW %m,%M" },
+[0x61] =	{ RM,0,		"PUNPCKLWL %m,%M" },
+[0x62] =	{ RM,0,		"PUNPCKLLQ %m,%M" },
+[0x63] =	{ RM,0,		"PACKSSWB %m,%M" },
+[0x64] =	{ RM,0,		"PCMPGTB %m,%M" },
+[0x65] =	{ RM,0,		"PCMPGTW %m,%M" },
+[0x66] =	{ RM,0,		"PCMPGTL %m,%M" },
+[0x67] =	{ RM,0,		"PACKUSWB %m,%M" },
+[0x68] =	{ RM,0,		"PUNPCKHBW %m,%M" },
+[0x69] =	{ RM,0,		"PUNPCKHWL %m,%M" },
+[0x6A] =	{ RM,0,		"PUNPCKHLQ %m,%M" },
+[0x6B] =	{ RM,0,		"PACKSSLW %m,%M" },
+[0x6E] =	{ RM,0,		"MOV%S %e,%M" },
+[0x6F] =	{ RM,0,		"MOVQ %m,%M" },
+[0x70] =	{ RM,Ib,		"PSHUFW	%i,%m,%M" },
+[0x74] =	{ RM,0,		"PCMPEQB %m,%M" },
+[0x75] =	{ RM,0,		"PCMPEQW %m,%M" },
+[0x76] =	{ RM,0,		"PCMPEQL %m,%M" },
+[0x77] =	{ 0,0,		"EMMS" },
+[0x7E] =	{ RM,0,		"MOV%S %M,%e" },
+[0x7F] =	{ RM,0,		"MOVQ %M,%m" },
+[0xAE] =	{ RMOP,0,		optab0FAE },
+[0xAA] =	{ 0,0,		"RSM" },
+[0xB0] =	{ RM,0,		"CMPXCHGB	%r,%e" },
+[0xB1] =	{ RM,0,		"CMPXCHG%S	%r,%e" },
+[0xC0] =	{ RMB,0,		"XADDB	%r,%e" },
+[0xC1] =	{ RM,0,		"XADD%S	%r,%e" },
+[0xC2] =	{ RM,Ib,		"CMP%s	%x,%X,%#i" },
+[0xC3] =	{ RM,0,		"MOVNTI%S	%r,%e" },
+[0xC6] =	{ RM,Ib,		"SHUF%s	%i,%x,%X" },
+[0xC8] =	{ 0,0,		"BSWAP	AX" },
+[0xC9] =	{ 0,0,		"BSWAP	CX" },
+[0xCA] =	{ 0,0,		"BSWAP	DX" },
+[0xCB] =	{ 0,0,		"BSWAP	BX" },
+[0xCC] =	{ 0,0,		"BSWAP	SP" },
+[0xCD] =	{ 0,0,		"BSWAP	BP" },
+[0xCE] =	{ 0,0,		"BSWAP	SI" },
+[0xCF] =	{ 0,0,		"BSWAP	DI" },
+[0xD1] =	{ RM,0,		"PSRLW %m,%M" },
+[0xD2] =	{ RM,0,		"PSRLL %m,%M" },
+[0xD3] =	{ RM,0,		"PSRLQ %m,%M" },
+[0xD5] =	{ RM,0,		"PMULLW %m,%M" },
+[0xD6] =	{ RM,0,		"MOVQOZX	%m*,%X" },
+[0xD7] =	{ RM,0,		"PMOVMSKB %m,%r" },
+[0xD8] =	{ RM,0,		"PSUBUSB %m,%M" },
+[0xD9] =	{ RM,0,		"PSUBUSW %m,%M" },
+[0xDA] =	{ RM,0,		"PMINUB %m,%M" },
+[0xDB] =	{ RM,0,		"PAND %m,%M" },
+[0xDC] =	{ RM,0,		"PADDUSB %m,%M" },
+[0xDD] =	{ RM,0,		"PADDUSW %m,%M" },
+[0xDE] =	{ RM,0,		"PMAXUB %m,%M" },
+[0xDF] =	{ RM,0,		"PANDN %m,%M" },
+[0xE0] =	{ RM,0,		"PAVGB %m,%M" },
+[0xE1] =	{ RM,0,		"PSRAW %m,%M" },
+[0xE2] =	{ RM,0,		"PSRAL %m,%M" },
+[0xE3] =	{ RM,0,		"PAVGW %m,%M" },
+[0xE4] =	{ RM,0,		"PMULHUW %m,%M" },
+[0xE5] =	{ RM,0,		"PMULHW %m,%M" },
+[0xE7] =	{ RM,0,		"MOVNTQ	%M,%e" },
+[0xE8] =	{ RM,0,		"PSUBSB %m,%M" },
+[0xE9] =	{ RM,0,		"PSUBSW %m,%M" },
+[0xEA] =	{ RM,0,		"PMINSW %m,%M" },
+[0xEB] =	{ RM,0,		"POR %m,%M" },
+[0xEC] =	{ RM,0,		"PADDSB %m,%M" },
+[0xED] =	{ RM,0,		"PADDSW %m,%M" },
+[0xEE] =	{ RM,0,		"PMAXSW %m,%M" },
+[0xEF] =	{ RM,0,		"PXOR %m,%M" },
+[0xF1] =	{ RM,0,		"PSLLW %m,%M" },
+[0xF2] =	{ RM,0,		"PSLLL %m,%M" },
+[0xF3] =	{ RM,0,		"PSLLQ %m,%M" },
+[0xF4] =	{ RM,0,		"PMULULQ	%m,%M" },
+[0xF5] =	{ RM,0,		"PMADDWL %m,%M" },
+[0xF6] =	{ RM,0,		"PSADBW %m,%M" },
+[0xF7] =	{ RMR,0,		"MASKMOVQ	%m,%M" },
+[0xF8] =	{ RM,0,		"PSUBB %m,%M" },
+[0xF9] =	{ RM,0,		"PSUBW %m,%M" },
+[0xFA] =	{ RM,0,		"PSUBL %m,%M" },
+[0xFC] =	{ RM,0,		"PADDB %m,%M" },
+[0xFD] =	{ RM,0,		"PADDW %m,%M" },
+[0xFE] =	{ RM,0,		"PADDL %m,%M" },
+
+[0x80] =	{ Iwds,0,		"JOS	%p" },
+[0x81] =	{ Iwds,0,		"JOC	%p" },
+[0x82] =	{ Iwds,0,		"JCS	%p" },
+[0x83] =	{ Iwds,0,		"JCC	%p" },
+[0x84] =	{ Iwds,0,		"JEQ	%p" },
+[0x85] =	{ Iwds,0,		"JNE	%p" },
+[0x86] =	{ Iwds,0,		"JLS	%p" },
+[0x87] =	{ Iwds,0,		"JHI	%p" },
+[0x88] =	{ Iwds,0,		"JMI	%p" },
+[0x89] =	{ Iwds,0,		"JPL	%p" },
+[0x8a] =	{ Iwds,0,		"JPS	%p" },
+[0x8b] =	{ Iwds,0,		"JPC	%p" },
+[0x8c] =	{ Iwds,0,		"JLT	%p" },
+[0x8d] =	{ Iwds,0,		"JGE	%p" },
+[0x8e] =	{ Iwds,0,		"JLE	%p" },
+[0x8f] =	{ Iwds,0,		"JGT	%p" },
+[0x90] =	{ RMB,0,		"SETOS	%e" },
+[0x91] =	{ RMB,0,		"SETOC	%e" },
+[0x92] =	{ RMB,0,		"SETCS	%e" },
+[0x93] =	{ RMB,0,		"SETCC	%e" },
+[0x94] =	{ RMB,0,		"SETEQ	%e" },
+[0x95] =	{ RMB,0,		"SETNE	%e" },
+[0x96] =	{ RMB,0,		"SETLS	%e" },
+[0x97] =	{ RMB,0,		"SETHI	%e" },
+[0x98] =	{ RMB,0,		"SETMI	%e" },
+[0x99] =	{ RMB,0,		"SETPL	%e" },
+[0x9a] =	{ RMB,0,		"SETPS	%e" },
+[0x9b] =	{ RMB,0,		"SETPC	%e" },
+[0x9c] =	{ RMB,0,		"SETLT	%e" },
+[0x9d] =	{ RMB,0,		"SETGE	%e" },
+[0x9e] =	{ RMB,0,		"SETLE	%e" },
+[0x9f] =	{ RMB,0,		"SETGT	%e" },
+[0xa0] =	{ 0,0,		"PUSHL	FS" },
+[0xa1] =	{ 0,0,		"POPL	FS" },
+[0xa2] =	{ 0,0,		"CPUID" },
+[0xa3] =	{ RM,0,		"BT%S	%r,%e" },
+[0xa4] =	{ RM,Ib,		"SHLD%S	%r,%i,%e" },
+[0xa5] =	{ RM,0,		"SHLD%S	%r,CL,%e" },
+[0xa8] =	{ 0,0,		"PUSHL	GS" },
+[0xa9] =	{ 0,0,		"POPL	GS" },
+[0xab] =	{ RM,0,		"BTS%S	%r,%e" },
+[0xac] =	{ RM,Ib,		"SHRD%S	%r,%i,%e" },
+[0xad] =	{ RM,0,		"SHRD%S	%r,CL,%e" },
+[0xaf] =	{ RM,0,		"IMUL%S	%e,%r" },
+[0xb2] =	{ RMM,0,		"LSS	%e,%r" },
+[0xb3] =	{ RM,0,		"BTR%S	%r,%e" },
+[0xb4] =	{ RMM,0,		"LFS	%e,%r" },
+[0xb5] =	{ RMM,0,		"LGS	%e,%r" },
+[0xb6] =	{ RMB,0,		"MOVBZX	%e,%R" },
+[0xb7] =	{ RM,0,		"MOVWZX	%e,%R" },
+[0xba] =	{ RMOP,0,		optab0FBA },
+[0xbb] =	{ RM,0,		"BTC%S	%e,%r" },
+[0xbc] =	{ RM,0,		"BSF%S	%e,%r" },
+[0xbd] =	{ RM,0,		"BSR%S	%e,%r" },
+[0xbe] =	{ RMB,0,		"MOVBSX	%e,%R" },
+[0xbf] =	{ RM,0,		"MOVWSX	%e,%R" },
+[0xc7] =	{ RMOP,0,		optab0FC7 },
+};
+
+static Optable optab80[8]=
+{
+[0x00] =	{ Ib,0,		"ADDB	%i,%e" },
+[0x01] =	{ Ib,0,		"ORB	%i,%e" },
+[0x02] =	{ Ib,0,		"ADCB	%i,%e" },
+[0x03] =	{ Ib,0,		"SBBB	%i,%e" },
+[0x04] =	{ Ib,0,		"ANDB	%i,%e" },
+[0x05] =	{ Ib,0,		"SUBB	%i,%e" },
+[0x06] =	{ Ib,0,		"XORB	%i,%e" },
+[0x07] =	{ Ib,0,		"CMPB	%e,%i" },
+};
+
+static Optable optab81[8]=
+{
+[0x00] =	{ Iwd,0,		"ADD%S	%i,%e" },
+[0x01] =	{ Iwd,0,		"OR%S	%i,%e" },
+[0x02] =	{ Iwd,0,		"ADC%S	%i,%e" },
+[0x03] =	{ Iwd,0,		"SBB%S	%i,%e" },
+[0x04] =	{ Iwd,0,		"AND%S	%i,%e" },
+[0x05] =	{ Iwd,0,		"SUB%S	%i,%e" },
+[0x06] =	{ Iwd,0,		"XOR%S	%i,%e" },
+[0x07] =	{ Iwd,0,		"CMP%S	%e,%i" },
+};
+
+static Optable optab83[8]=
+{
+[0x00] =	{ Ibs,0,		"ADD%S	%i,%e" },
+[0x01] =	{ Ibs,0,		"OR%S	%i,%e" },
+[0x02] =	{ Ibs,0,		"ADC%S	%i,%e" },
+[0x03] =	{ Ibs,0,		"SBB%S	%i,%e" },
+[0x04] =	{ Ibs,0,		"AND%S	%i,%e" },
+[0x05] =	{ Ibs,0,		"SUB%S	%i,%e" },
+[0x06] =	{ Ibs,0,		"XOR%S	%i,%e" },
+[0x07] =	{ Ibs,0,		"CMP%S	%e,%i" },
+};
+
+static Optable optabC0[8] =
+{
+[0x00] =	{ Ib,0,		"ROLB	%i,%e" },
+[0x01] =	{ Ib,0,		"RORB	%i,%e" },
+[0x02] =	{ Ib,0,		"RCLB	%i,%e" },
+[0x03] =	{ Ib,0,		"RCRB	%i,%e" },
+[0x04] =	{ Ib,0,		"SHLB	%i,%e" },
+[0x05] =	{ Ib,0,		"SHRB	%i,%e" },
+[0x07] =	{ Ib,0,		"SARB	%i,%e" },
+};
+
+static Optable optabC1[8] =
+{
+[0x00] =	{ Ib,0,		"ROL%S	%i,%e" },
+[0x01] =	{ Ib,0,		"ROR%S	%i,%e" },
+[0x02] =	{ Ib,0,		"RCL%S	%i,%e" },
+[0x03] =	{ Ib,0,		"RCR%S	%i,%e" },
+[0x04] =	{ Ib,0,		"SHL%S	%i,%e" },
+[0x05] =	{ Ib,0,		"SHR%S	%i,%e" },
+[0x07] =	{ Ib,0,		"SAR%S	%i,%e" },
+};
+
+static Optable optabD0[8] =
+{
+[0x00] =	{ 0,0,		"ROLB	%e" },
+[0x01] =	{ 0,0,		"RORB	%e" },
+[0x02] =	{ 0,0,		"RCLB	%e" },
+[0x03] =	{ 0,0,		"RCRB	%e" },
+[0x04] =	{ 0,0,		"SHLB	%e" },
+[0x05] =	{ 0,0,		"SHRB	%e" },
+[0x07] =	{ 0,0,		"SARB	%e" },
+};
+
+static Optable optabD1[8] =
+{
+[0x00] =	{ 0,0,		"ROL%S	%e" },
+[0x01] =	{ 0,0,		"ROR%S	%e" },
+[0x02] =	{ 0,0,		"RCL%S	%e" },
+[0x03] =	{ 0,0,		"RCR%S	%e" },
+[0x04] =	{ 0,0,		"SHL%S	%e" },
+[0x05] =	{ 0,0,		"SHR%S	%e" },
+[0x07] =	{ 0,0,		"SAR%S	%e" },
+};
+
+static Optable optabD2[8] =
+{
+[0x00] =	{ 0,0,		"ROLB	CL,%e" },
+[0x01] =	{ 0,0,		"RORB	CL,%e" },
+[0x02] =	{ 0,0,		"RCLB	CL,%e" },
+[0x03] =	{ 0,0,		"RCRB	CL,%e" },
+[0x04] =	{ 0,0,		"SHLB	CL,%e" },
+[0x05] =	{ 0,0,		"SHRB	CL,%e" },
+[0x07] =	{ 0,0,		"SARB	CL,%e" },
+};
+
+static Optable optabD3[8] =
+{
+[0x00] =	{ 0,0,		"ROL%S	CL,%e" },
+[0x01] =	{ 0,0,		"ROR%S	CL,%e" },
+[0x02] =	{ 0,0,		"RCL%S	CL,%e" },
+[0x03] =	{ 0,0,		"RCR%S	CL,%e" },
+[0x04] =	{ 0,0,		"SHL%S	CL,%e" },
+[0x05] =	{ 0,0,		"SHR%S	CL,%e" },
+[0x07] =	{ 0,0,		"SAR%S	CL,%e" },
+};
+
+static Optable optabD8[8+8] =
+{
+[0x00] =	{ 0,0,		"FADDF	%e,F0" },
+[0x01] =	{ 0,0,		"FMULF	%e,F0" },
+[0x02] =	{ 0,0,		"FCOMF	%e,F0" },
+[0x03] =	{ 0,0,		"FCOMFP	%e,F0" },
+[0x04] =	{ 0,0,		"FSUBF	%e,F0" },
+[0x05] =	{ 0,0,		"FSUBRF	%e,F0" },
+[0x06] =	{ 0,0,		"FDIVF	%e,F0" },
+[0x07] =	{ 0,0,		"FDIVRF	%e,F0" },
+[0x08] =	{ 0,0,		"FADDD	%f,F0" },
+[0x09] =	{ 0,0,		"FMULD	%f,F0" },
+[0x0a] =	{ 0,0,		"FCOMD	%f,F0" },
+[0x0b] =	{ 0,0,		"FCOMPD	%f,F0" },
+[0x0c] =	{ 0,0,		"FSUBD	%f,F0" },
+[0x0d] =	{ 0,0,		"FSUBRD	%f,F0" },
+[0x0e] =	{ 0,0,		"FDIVD	%f,F0" },
+[0x0f] =	{ 0,0,		"FDIVRD	%f,F0" },
+};
+/*
+ *	optabD9 and optabDB use the following encoding:
+ *	if (0 <= modrm <= 2) instruction = optabDx[modrm&0x07];
+ *	else instruction = optabDx[(modrm&0x3f)+8];
+ *
+ *	the instructions for MOD == 3, follow the 8 instructions
+ *	for the other MOD values stored at the front of the table.
+ */
+static Optable optabD9[64+8] =
+{
+[0x00] =	{ 0,0,		"FMOVF	%e,F0" },
+[0x02] =	{ 0,0,		"FMOVF	F0,%e" },
+[0x03] =	{ 0,0,		"FMOVFP	F0,%e" },
+[0x04] =	{ 0,0,		"FLDENV%S %e" },
+[0x05] =	{ 0,0,		"FLDCW	%e" },
+[0x06] =	{ 0,0,		"FSTENV%S %e" },
+[0x07] =	{ 0,0,		"FSTCW	%e" },
+[0x08] =	{ 0,0,		"FMOVD	F0,F0" },		/* Mod R/M = 11xx xxxx*/
+[0x09] =	{ 0,0,		"FMOVD	F1,F0" },
+[0x0a] =	{ 0,0,		"FMOVD	F2,F0" },
+[0x0b] =	{ 0,0,		"FMOVD	F3,F0" },
+[0x0c] =	{ 0,0,		"FMOVD	F4,F0" },
+[0x0d] =	{ 0,0,		"FMOVD	F5,F0" },
+[0x0e] =	{ 0,0,		"FMOVD	F6,F0" },
+[0x0f] =	{ 0,0,		"FMOVD	F7,F0" },
+[0x10] =	{ 0,0,		"FXCHD	F0,F0" },
+[0x11] =	{ 0,0,		"FXCHD	F1,F0" },
+[0x12] =	{ 0,0,		"FXCHD	F2,F0" },
+[0x13] =	{ 0,0,		"FXCHD	F3,F0" },
+[0x14] =	{ 0,0,		"FXCHD	F4,F0" },
+[0x15] =	{ 0,0,		"FXCHD	F5,F0" },
+[0x16] =	{ 0,0,		"FXCHD	F6,F0" },
+[0x17] =	{ 0,0,		"FXCHD	F7,F0" },
+[0x18] =	{ 0,0,		"FNOP" },
+[0x28] =	{ 0,0,		"FCHS" },
+[0x29] =	{ 0,0,		"FABS" },
+[0x2c] =	{ 0,0,		"FTST" },
+[0x2d] =	{ 0,0,		"FXAM" },
+[0x30] =	{ 0,0,		"FLD1" },
+[0x31] =	{ 0,0,		"FLDL2T" },
+[0x32] =	{ 0,0,		"FLDL2E" },
+[0x33] =	{ 0,0,		"FLDPI" },
+[0x34] =	{ 0,0,		"FLDLG2" },
+[0x35] =	{ 0,0,		"FLDLN2" },
+[0x36] =	{ 0,0,		"FLDZ" },
+[0x38] =	{ 0,0,		"F2XM1" },
+[0x39] =	{ 0,0,		"FYL2X" },
+[0x3a] =	{ 0,0,		"FPTAN" },
+[0x3b] =	{ 0,0,		"FPATAN" },
+[0x3c] =	{ 0,0,		"FXTRACT" },
+[0x3d] =	{ 0,0,		"FPREM1" },
+[0x3e] =	{ 0,0,		"FDECSTP" },
+[0x3f] =	{ 0,0,		"FNCSTP" },
+[0x40] =	{ 0,0,		"FPREM" },
+[0x41] =	{ 0,0,		"FYL2XP1" },
+[0x42] =	{ 0,0,		"FSQRT" },
+[0x43] =	{ 0,0,		"FSINCOS" },
+[0x44] =	{ 0,0,		"FRNDINT" },
+[0x45] =	{ 0,0,		"FSCALE" },
+[0x46] =	{ 0,0,		"FSIN" },
+[0x47] =	{ 0,0,		"FCOS" },
+};
+
+static Optable optabDA[8+8] =
+{
+[0x00] =	{ 0,0,		"FADDL	%e,F0" },
+[0x01] =	{ 0,0,		"FMULL	%e,F0" },
+[0x02] =	{ 0,0,		"FCOML	%e,F0" },
+[0x03] =	{ 0,0,		"FCOMLP	%e,F0" },
+[0x04] =	{ 0,0,		"FSUBL	%e,F0" },
+[0x05] =	{ 0,0,		"FSUBRL	%e,F0" },
+[0x06] =	{ 0,0,		"FDIVL	%e,F0" },
+[0x07] =	{ 0,0,		"FDIVRL	%e,F0" },
+[0x08] =	{ 0,0,		"FCMOVCS	%f,F0" },
+[0x09] =	{ 0,0,		"FCMOVEQ	%f,F0" },
+[0x0a] =	{ 0,0,		"FCMOVLS	%f,F0" },
+[0x0b] =	{ 0,0,		"FCMOVUN	%f,F0" },
+[0x0d] =	{ Op_R1,0,		"FUCOMPP" },
+};
+
+static Optable optabDB[8+64] =
+{
+[0x00] =	{ 0,0,		"FMOVL	%e,F0" },
+[0x02] =	{ 0,0,		"FMOVL	F0,%e" },
+[0x03] =	{ 0,0,		"FMOVLP	F0,%e" },
+[0x05] =	{ 0,0,		"FMOVX	%e,F0" },
+[0x07] =	{ 0,0,		"FMOVXP	F0,%e" },
+[0x08] =	{ 0,0,		"FCMOVCC	F0,F0" },	/* Mod R/M = 11xx xxxx*/
+[0x09] =	{ 0,0,		"FCMOVCC	F1,F0" },
+[0x0a] =	{ 0,0,		"FCMOVCC	F2,F0" },
+[0x0b] =	{ 0,0,		"FCMOVCC	F3,F0" },
+[0x0c] =	{ 0,0,		"FCMOVCC	F4,F0" },
+[0x0d] =	{ 0,0,		"FCMOVCC	F5,F0" },
+[0x0e] =	{ 0,0,		"FCMOVCC	F6,F0" },
+[0x0f] =	{ 0,0,		"FCMOVCC	F7,F0" },
+[0x10] =	{ 0,0,		"FCMOVNE	F0,F0" },
+[0x11] =	{ 0,0,		"FCMOVNE	F1,F0" },
+[0x12] =	{ 0,0,		"FCMOVNE	F2,F0" },
+[0x13] =	{ 0,0,		"FCMOVNE	F3,F0" },
+[0x14] =	{ 0,0,		"FCMOVNE	F4,F0" },
+[0x15] =	{ 0,0,		"FCMOVNE	F5,F0" },
+[0x16] =	{ 0,0,		"FCMOVNE	F6,F0" },
+[0x17] =	{ 0,0,		"FCMOVNE	F7,F0" },
+[0x18] =	{ 0,0,		"FCMOVHI	F0,F0" },
+[0x19] =	{ 0,0,		"FCMOVHI	F1,F0" },
+[0x1a] =	{ 0,0,		"FCMOVHI	F2,F0" },
+[0x1b] =	{ 0,0,		"FCMOVHI	F3,F0" },
+[0x1c] =	{ 0,0,		"FCMOVHI	F4,F0" },
+[0x1d] =	{ 0,0,		"FCMOVHI	F5,F0" },
+[0x1e] =	{ 0,0,		"FCMOVHI	F6,F0" },
+[0x1f] =	{ 0,0,		"FCMOVHI	F7,F0" },
+[0x20] =	{ 0,0,		"FCMOVNU	F0,F0" },
+[0x21] =	{ 0,0,		"FCMOVNU	F1,F0" },
+[0x22] =	{ 0,0,		"FCMOVNU	F2,F0" },
+[0x23] =	{ 0,0,		"FCMOVNU	F3,F0" },
+[0x24] =	{ 0,0,		"FCMOVNU	F4,F0" },
+[0x25] =	{ 0,0,		"FCMOVNU	F5,F0" },
+[0x26] =	{ 0,0,		"FCMOVNU	F6,F0" },
+[0x27] =	{ 0,0,		"FCMOVNU	F7,F0" },
+[0x2a] =	{ 0,0,		"FCLEX" },
+[0x2b] =	{ 0,0,		"FINIT" },
+[0x30] =	{ 0,0,		"FUCOMI	F0,F0" },
+[0x31] =	{ 0,0,		"FUCOMI	F1,F0" },
+[0x32] =	{ 0,0,		"FUCOMI	F2,F0" },
+[0x33] =	{ 0,0,		"FUCOMI	F3,F0" },
+[0x34] =	{ 0,0,		"FUCOMI	F4,F0" },
+[0x35] =	{ 0,0,		"FUCOMI	F5,F0" },
+[0x36] =	{ 0,0,		"FUCOMI	F6,F0" },
+[0x37] =	{ 0,0,		"FUCOMI	F7,F0" },
+[0x38] =	{ 0,0,		"FCOMI	F0,F0" },
+[0x39] =	{ 0,0,		"FCOMI	F1,F0" },
+[0x3a] =	{ 0,0,		"FCOMI	F2,F0" },
+[0x3b] =	{ 0,0,		"FCOMI	F3,F0" },
+[0x3c] =	{ 0,0,		"FCOMI	F4,F0" },
+[0x3d] =	{ 0,0,		"FCOMI	F5,F0" },
+[0x3e] =	{ 0,0,		"FCOMI	F6,F0" },
+[0x3f] =	{ 0,0,		"FCOMI	F7,F0" },
+};
+
+static Optable optabDC[8+8] =
+{
+[0x00] =	{ 0,0,		"FADDD	%e,F0" },
+[0x01] =	{ 0,0,		"FMULD	%e,F0" },
+[0x02] =	{ 0,0,		"FCOMD	%e,F0" },
+[0x03] =	{ 0,0,		"FCOMDP	%e,F0" },
+[0x04] =	{ 0,0,		"FSUBD	%e,F0" },
+[0x05] =	{ 0,0,		"FSUBRD	%e,F0" },
+[0x06] =	{ 0,0,		"FDIVD	%e,F0" },
+[0x07] =	{ 0,0,		"FDIVRD	%e,F0" },
+[0x08] =	{ 0,0,		"FADDD	F0,%f" },
+[0x09] =	{ 0,0,		"FMULD	F0,%f" },
+[0x0c] =	{ 0,0,		"FSUBRD	F0,%f" },
+[0x0d] =	{ 0,0,		"FSUBD	F0,%f" },
+[0x0e] =	{ 0,0,		"FDIVRD	F0,%f" },
+[0x0f] =	{ 0,0,		"FDIVD	F0,%f" },
+};
+
+static Optable optabDD[8+8] =
+{
+[0x00] =	{ 0,0,		"FMOVD	%e,F0" },
+[0x02] =	{ 0,0,		"FMOVD	F0,%e" },
+[0x03] =	{ 0,0,		"FMOVDP	F0,%e" },
+[0x04] =	{ 0,0,		"FRSTOR%S %e" },
+[0x06] =	{ 0,0,		"FSAVE%S %e" },
+[0x07] =	{ 0,0,		"FSTSW	%e" },
+[0x08] =	{ 0,0,		"FFREED	%f" },
+[0x0a] =	{ 0,0,		"FMOVD	%f,F0" },
+[0x0b] =	{ 0,0,		"FMOVDP	%f,F0" },
+[0x0c] =	{ 0,0,		"FUCOMD	%f,F0" },
+[0x0d] =	{ 0,0,		"FUCOMDP %f,F0" },
+};
+
+static Optable optabDE[8+8] =
+{
+[0x00] =	{ 0,0,		"FADDW	%e,F0" },
+[0x01] =	{ 0,0,		"FMULW	%e,F0" },
+[0x02] =	{ 0,0,		"FCOMW	%e,F0" },
+[0x03] =	{ 0,0,		"FCOMWP	%e,F0" },
+[0x04] =	{ 0,0,		"FSUBW	%e,F0" },
+[0x05] =	{ 0,0,		"FSUBRW	%e,F0" },
+[0x06] =	{ 0,0,		"FDIVW	%e,F0" },
+[0x07] =	{ 0,0,		"FDIVRW	%e,F0" },
+[0x08] =	{ 0,0,		"FADDDP	F0,%f" },
+[0x09] =	{ 0,0,		"FMULDP	F0,%f" },
+[0x0b] =	{ Op_R1,0,		"FCOMPDP" },
+[0x0c] =	{ 0,0,		"FSUBRDP F0,%f" },
+[0x0d] =	{ 0,0,		"FSUBDP	F0,%f" },
+[0x0e] =	{ 0,0,		"FDIVRDP F0,%f" },
+[0x0f] =	{ 0,0,		"FDIVDP	F0,%f" },
+};
+
+static Optable optabDF[8+8] =
+{
+[0x00] =	{ 0,0,		"FMOVW	%e,F0" },
+[0x02] =	{ 0,0,		"FMOVW	F0,%e" },
+[0x03] =	{ 0,0,		"FMOVWP	F0,%e" },
+[0x04] =	{ 0,0,		"FBLD	%e" },
+[0x05] =	{ 0,0,		"FMOVL	%e,F0" },
+[0x06] =	{ 0,0,		"FBSTP	%e" },
+[0x07] =	{ 0,0,		"FMOVLP	F0,%e" },
+[0x0c] =	{ Op_R0,0,		"FSTSW	%OAX" },
+[0x0d] =	{ 0,0,		"FUCOMIP	F0,%f" },
+[0x0e] =	{ 0,0,		"FCOMIP	F0,%f" },
+};
+
+static Optable optabF6[8] =
+{
+[0x00] =	{ Ib,0,		"TESTB	%i,%e" },
+[0x02] =	{ 0,0,		"NOTB	%e" },
+[0x03] =	{ 0,0,		"NEGB	%e" },
+[0x04] =	{ 0,0,		"MULB	AL,%e" },
+[0x05] =	{ 0,0,		"IMULB	AL,%e" },
+[0x06] =	{ 0,0,		"DIVB	AL,%e" },
+[0x07] =	{ 0,0,		"IDIVB	AL,%e" },
+};
+
+static Optable optabF7[8] =
+{
+[0x00] =	{ Iwd,0,		"TEST%S	%i,%e" },
+[0x02] =	{ 0,0,		"NOT%S	%e" },
+[0x03] =	{ 0,0,		"NEG%S	%e" },
+[0x04] =	{ 0,0,		"MUL%S	%OAX,%e" },
+[0x05] =	{ 0,0,		"IMUL%S	%OAX,%e" },
+[0x06] =	{ 0,0,		"DIV%S	%OAX,%e" },
+[0x07] =	{ 0,0,		"IDIV%S	%OAX,%e" },
+};
+
+static Optable optabFE[8] =
+{
+[0x00] =	{ 0,0,		"INCB	%e" },
+[0x01] =	{ 0,0,		"DECB	%e" },
+};
+
+static Optable optabFF[8] =
+{
+[0x00] =	{ 0,0,		"INC%S	%e" },
+[0x01] =	{ 0,0,		"DEC%S	%e" },
+[0x02] =	{ JUMP,0,		"CALL*	%e" },
+[0x03] =	{ JUMP,0,		"CALLF*	%e" },
+[0x04] =	{ JUMP,0,		"JMP*	%e" },
+[0x05] =	{ JUMP,0,		"JMPF*	%e" },
+[0x06] =	{ 0,0,		"PUSHL	%e" },
+};
+
+static Optable optable[256+2] =
+{
+[0x00] =	{ RMB,0,		"ADDB	%r,%e" },
+[0x01] =	{ RM,0,		"ADD%S	%r,%e" },
+[0x02] =	{ RMB,0,		"ADDB	%e,%r" },
+[0x03] =	{ RM,0,		"ADD%S	%e,%r" },
+[0x04] =	{ Ib,0,		"ADDB	%i,AL" },
+[0x05] =	{ Iwd,0,		"ADD%S	%i,%OAX" },
+[0x06] =	{ 0,0,		"PUSHL	ES" },
+[0x07] =	{ 0,0,		"POPL	ES" },
+[0x08] =	{ RMB,0,		"ORB	%r,%e" },
+[0x09] =	{ RM,0,		"OR%S	%r,%e" },
+[0x0a] =	{ RMB,0,		"ORB	%e,%r" },
+[0x0b] =	{ RM,0,		"OR%S	%e,%r" },
+[0x0c] =	{ Ib,0,		"ORB	%i,AL" },
+[0x0d] =	{ Iwd,0,		"OR%S	%i,%OAX" },
+[0x0e] =	{ 0,0,		"PUSHL	CS" },
+[0x0f] =	{ AUXMM,0,	optab0F },
+[0x10] =	{ RMB,0,		"ADCB	%r,%e" },
+[0x11] =	{ RM,0,		"ADC%S	%r,%e" },
+[0x12] =	{ RMB,0,		"ADCB	%e,%r" },
+[0x13] =	{ RM,0,		"ADC%S	%e,%r" },
+[0x14] =	{ Ib,0,		"ADCB	%i,AL" },
+[0x15] =	{ Iwd,0,		"ADC%S	%i,%OAX" },
+[0x16] =	{ 0,0,		"PUSHL	SS" },
+[0x17] =	{ 0,0,		"POPL	SS" },
+[0x18] =	{ RMB,0,		"SBBB	%r,%e" },
+[0x19] =	{ RM,0,		"SBB%S	%r,%e" },
+[0x1a] =	{ RMB,0,		"SBBB	%e,%r" },
+[0x1b] =	{ RM,0,		"SBB%S	%e,%r" },
+[0x1c] =	{ Ib,0,		"SBBB	%i,AL" },
+[0x1d] =	{ Iwd,0,		"SBB%S	%i,%OAX" },
+[0x1e] =	{ 0,0,		"PUSHL	DS" },
+[0x1f] =	{ 0,0,		"POPL	DS" },
+[0x20] =	{ RMB,0,		"ANDB	%r,%e" },
+[0x21] =	{ RM,0,		"AND%S	%r,%e" },
+[0x22] =	{ RMB,0,		"ANDB	%e,%r" },
+[0x23] =	{ RM,0,		"AND%S	%e,%r" },
+[0x24] =	{ Ib,0,		"ANDB	%i,AL" },
+[0x25] =	{ Iwd,0,		"AND%S	%i,%OAX" },
+[0x26] =	{ SEG,0,		"ES:" },
+[0x27] =	{ 0,0,		"DAA" },
+[0x28] =	{ RMB,0,		"SUBB	%r,%e" },
+[0x29] =	{ RM,0,		"SUB%S	%r,%e" },
+[0x2a] =	{ RMB,0,		"SUBB	%e,%r" },
+[0x2b] =	{ RM,0,		"SUB%S	%e,%r" },
+[0x2c] =	{ Ib,0,		"SUBB	%i,AL" },
+[0x2d] =	{ Iwd,0,		"SUB%S	%i,%OAX" },
+[0x2e] =	{ SEG,0,		"CS:" },
+[0x2f] =	{ 0,0,		"DAS" },
+[0x30] =	{ RMB,0,		"XORB	%r,%e" },
+[0x31] =	{ RM,0,		"XOR%S	%r,%e" },
+[0x32] =	{ RMB,0,		"XORB	%e,%r" },
+[0x33] =	{ RM,0,		"XOR%S	%e,%r" },
+[0x34] =	{ Ib,0,		"XORB	%i,AL" },
+[0x35] =	{ Iwd,0,		"XOR%S	%i,%OAX" },
+[0x36] =	{ SEG,0,		"SS:" },
+[0x37] =	{ 0,0,		"AAA" },
+[0x38] =	{ RMB,0,		"CMPB	%r,%e" },
+[0x39] =	{ RM,0,		"CMP%S	%r,%e" },
+[0x3a] =	{ RMB,0,		"CMPB	%e,%r" },
+[0x3b] =	{ RM,0,		"CMP%S	%e,%r" },
+[0x3c] =	{ Ib,0,		"CMPB	%i,AL" },
+[0x3d] =	{ Iwd,0,		"CMP%S	%i,%OAX" },
+[0x3e] =	{ SEG,0,		"DS:" },
+[0x3f] =	{ 0,0,		"AAS" },
+[0x40] =	{ 0,0,		"INC%S	%OAX" },
+[0x41] =	{ 0,0,		"INC%S	%OCX" },
+[0x42] =	{ 0,0,		"INC%S	%ODX" },
+[0x43] =	{ 0,0,		"INC%S	%OBX" },
+[0x44] =	{ 0,0,		"INC%S	%OSP" },
+[0x45] =	{ 0,0,		"INC%S	%OBP" },
+[0x46] =	{ 0,0,		"INC%S	%OSI" },
+[0x47] =	{ 0,0,		"INC%S	%ODI" },
+[0x48] =	{ 0,0,		"DEC%S	%OAX" },
+[0x49] =	{ 0,0,		"DEC%S	%OCX" },
+[0x4a] =	{ 0,0,		"DEC%S	%ODX" },
+[0x4b] =	{ 0,0,		"DEC%S	%OBX" },
+[0x4c] =	{ 0,0,		"DEC%S	%OSP" },
+[0x4d] =	{ 0,0,		"DEC%S	%OBP" },
+[0x4e] =	{ 0,0,		"DEC%S	%OSI" },
+[0x4f] =	{ 0,0,		"DEC%S	%ODI" },
+[0x50] =	{ 0,0,		"PUSH%S	%OAX" },
+[0x51] =	{ 0,0,		"PUSH%S	%OCX" },
+[0x52] =	{ 0,0,		"PUSH%S	%ODX" },
+[0x53] =	{ 0,0,		"PUSH%S	%OBX" },
+[0x54] =	{ 0,0,		"PUSH%S	%OSP" },
+[0x55] =	{ 0,0,		"PUSH%S	%OBP" },
+[0x56] =	{ 0,0,		"PUSH%S	%OSI" },
+[0x57] =	{ 0,0,		"PUSH%S	%ODI" },
+[0x58] =	{ 0,0,		"POP%S	%OAX" },
+[0x59] =	{ 0,0,		"POP%S	%OCX" },
+[0x5a] =	{ 0,0,		"POP%S	%ODX" },
+[0x5b] =	{ 0,0,		"POP%S	%OBX" },
+[0x5c] =	{ 0,0,		"POP%S	%OSP" },
+[0x5d] =	{ 0,0,		"POP%S	%OBP" },
+[0x5e] =	{ 0,0,		"POP%S	%OSI" },
+[0x5f] =	{ 0,0,		"POP%S	%ODI" },
+[0x60] =	{ 0,0,		"PUSHA%S" },
+[0x61] =	{ 0,0,		"POPA%S" },
+[0x62] =	{ RMM,0,		"BOUND	%e,%r" },
+[0x63] =	{ RM,0,		"ARPL	%r,%e" },
+[0x64] =	{ SEG,0,		"FS:" },
+[0x65] =	{ SEG,0,		"GS:" },
+[0x66] =	{ OPOVER,0,	"" },
+[0x67] =	{ ADDOVER,0,	"" },
+[0x68] =	{ Iwd,0,		"PUSH%S	%i" },
+[0x69] =	{ RM,Iwd,		"IMUL%S	%e,%i,%r" },
+[0x6a] =	{ Ib,0,		"PUSH%S	%i" },
+[0x6b] =	{ RM,Ibs,		"IMUL%S	%e,%i,%r" },
+[0x6c] =	{ 0,0,		"INSB	DX,(%ODI)" },
+[0x6d] =	{ 0,0,		"INS%S	DX,(%ODI)" },
+[0x6e] =	{ 0,0,		"OUTSB	(%ASI),DX" },
+[0x6f] =	{ 0,0,		"OUTS%S	(%ASI),DX" },
+[0x70] =	{ Jbs,0,		"JOS	%p" },
+[0x71] =	{ Jbs,0,		"JOC	%p" },
+[0x72] =	{ Jbs,0,		"JCS	%p" },
+[0x73] =	{ Jbs,0,		"JCC	%p" },
+[0x74] =	{ Jbs,0,		"JEQ	%p" },
+[0x75] =	{ Jbs,0,		"JNE	%p" },
+[0x76] =	{ Jbs,0,		"JLS	%p" },
+[0x77] =	{ Jbs,0,		"JHI	%p" },
+[0x78] =	{ Jbs,0,		"JMI	%p" },
+[0x79] =	{ Jbs,0,		"JPL	%p" },
+[0x7a] =	{ Jbs,0,		"JPS	%p" },
+[0x7b] =	{ Jbs,0,		"JPC	%p" },
+[0x7c] =	{ Jbs,0,		"JLT	%p" },
+[0x7d] =	{ Jbs,0,		"JGE	%p" },
+[0x7e] =	{ Jbs,0,		"JLE	%p" },
+[0x7f] =	{ Jbs,0,		"JGT	%p" },
+[0x80] =	{ RMOPB,0,	optab80 },
+[0x81] =	{ RMOP,0,		optab81 },
+[0x83] =	{ RMOP,0,		optab83 },
+[0x84] =	{ RMB,0,		"TESTB	%r,%e" },
+[0x85] =	{ RM,0,		"TEST%S	%r,%e" },
+[0x86] =	{ RMB,0,		"XCHGB	%r,%e" },
+[0x87] =	{ RM,0,		"XCHG%S	%r,%e" },
+[0x88] =	{ RMB,0,		"MOVB	%r,%e" },
+[0x89] =	{ RM,0,		"MOV%S	%r,%e" },
+[0x8a] =	{ RMB,0,		"MOVB	%e,%r" },
+[0x8b] =	{ RM,0,		"MOV%S	%e,%r" },
+[0x8c] =	{ RM,0,		"MOVW	%g,%e" },
+[0x8d] =	{ RM,0,		"LEA%S	%e,%r" },
+[0x8e] =	{ RM,0,		"MOVW	%e,%g" },
+[0x8f] =	{ RM,0,		"POP%S	%e" },
+[0x90] =	{ 0,0,		"NOP" },
+[0x91] =	{ 0,0,		"XCHG	%OCX,%OAX" },
+[0x92] =	{ 0,0,		"XCHG	%ODX,%OAX" },
+[0x93] =	{ 0,0,		"XCHG	%OBX,%OAX" },
+[0x94] =	{ 0,0,		"XCHG	%OSP,%OAX" },
+[0x95] =	{ 0,0,		"XCHG	%OBP,%OAX" },
+[0x96] =	{ 0,0,		"XCHG	%OSI,%OAX" },
+[0x97] =	{ 0,0,		"XCHG	%ODI,%OAX" },
+[0x98] =	{ 0,0,		"%W" },			/* miserable CBW or CWDE */
+[0x99] =	{ 0,0,		"%w" },			/* idiotic CWD or CDQ */
+[0x9a] =	{ PTR,0,		"CALL%S	%d" },
+[0x9b] =	{ 0,0,		"WAIT" },
+[0x9c] =	{ 0,0,		"PUSHF" },
+[0x9d] =	{ 0,0,		"POPF" },
+[0x9e] =	{ 0,0,		"SAHF" },
+[0x9f] =	{ 0,0,		"LAHF" },
+[0xa0] =	{ Awd,0,		"MOVB	%i,AL" },
+[0xa1] =	{ Awd,0,		"MOV%S	%i,%OAX" },
+[0xa2] =	{ Awd,0,		"MOVB	AL,%i" },
+[0xa3] =	{ Awd,0,		"MOV%S	%OAX,%i" },
+[0xa4] =	{ 0,0,		"MOVSB	(%ASI),(%ADI)" },
+[0xa5] =	{ 0,0,		"MOVS%S	(%ASI),(%ADI)" },
+[0xa6] =	{ 0,0,		"CMPSB	(%ASI),(%ADI)" },
+[0xa7] =	{ 0,0,		"CMPS%S	(%ASI),(%ADI)" },
+[0xa8] =	{ Ib,0,		"TESTB	%i,AL" },
+[0xa9] =	{ Iwd,0,		"TEST%S	%i,%OAX" },
+[0xaa] =	{ 0,0,		"STOSB	AL,(%ADI)" },
+[0xab] =	{ 0,0,		"STOS%S	%OAX,(%ADI)" },
+[0xac] =	{ 0,0,		"LODSB	(%ASI),AL" },
+[0xad] =	{ 0,0,		"LODS%S	(%ASI),%OAX" },
+[0xae] =	{ 0,0,		"SCASB	(%ADI),AL" },
+[0xaf] =	{ 0,0,		"SCAS%S	(%ADI),%OAX" },
+[0xb0] =	{ Ib,0,		"MOVB	%i,AL" },
+[0xb1] =	{ Ib,0,		"MOVB	%i,CL" },
+[0xb2] =	{ Ib,0,		"MOVB	%i,DL" },
+[0xb3] =	{ Ib,0,		"MOVB	%i,BL" },
+[0xb4] =	{ Ib,0,		"MOVB	%i,AH" },
+[0xb5] =	{ Ib,0,		"MOVB	%i,CH" },
+[0xb6] =	{ Ib,0,		"MOVB	%i,DH" },
+[0xb7] =	{ Ib,0,		"MOVB	%i,BH" },
+[0xb8] =	{ Iwdq,0,		"MOV%S	%i,%o" },
+[0xb9] =	{ Iwdq,0,		"MOV%S	%i,%o" },
+[0xba] =	{ Iwdq,0,		"MOV%S	%i,%o" },
+[0xbb] =	{ Iwdq,0,		"MOV%S	%i,%o" },
+[0xbc] =	{ Iwdq,0,		"MOV%S	%i,%o" },
+[0xbd] =	{ Iwdq,0,		"MOV%S	%i,%o" },
+[0xbe] =	{ Iwdq,0,		"MOV%S	%i,%o" },
+[0xbf] =	{ Iwdq,0,		"MOV%S	%i,%o" },
+[0xc0] =	{ RMOPB,0,	optabC0 },
+[0xc1] =	{ RMOP,0,		optabC1 },
+[0xc2] =	{ Iw,0,		"RET	%i" },
+[0xc3] =	{ RET,0,		"RET" },
+[0xc4] =	{ RM,0,		"LES	%e,%r" },
+[0xc5] =	{ RM,0,		"LDS	%e,%r" },
+[0xc6] =	{ RMB,Ib,		"MOVB	%i,%e" },
+[0xc7] =	{ RM,Iwd,		"MOV%S	%i,%e" },
+[0xc8] =	{ Iw2,Ib,		"ENTER	%i,%I" },		/* loony ENTER */
+[0xc9] =	{ RET,0,		"LEAVE" },		/* bizarre LEAVE */
+[0xca] =	{ Iw,0,		"RETF	%i" },
+[0xcb] =	{ RET,0,		"RETF" },
+[0xcc] =	{ 0,0,		"INT	3" },
+[0xcd] =	{ Ib,0,		"INTB	%i" },
+[0xce] =	{ 0,0,		"INTO" },
+[0xcf] =	{ 0,0,		"IRET" },
+[0xd0] =	{ RMOPB,0,	optabD0 },
+[0xd1] =	{ RMOP,0,		optabD1 },
+[0xd2] =	{ RMOPB,0,	optabD2 },
+[0xd3] =	{ RMOP,0,		optabD3 },
+[0xd4] =	{ OA,0,		"AAM" },
+[0xd5] =	{ OA,0,		"AAD" },
+[0xd7] =	{ 0,0,		"XLAT" },
+[0xd8] =	{ FRMOP,0,	optabD8 },
+[0xd9] =	{ FRMEX,0,	optabD9 },
+[0xda] =	{ FRMOP,0,	optabDA },
+[0xdb] =	{ FRMEX,0,	optabDB },
+[0xdc] =	{ FRMOP,0,	optabDC },
+[0xdd] =	{ FRMOP,0,	optabDD },
+[0xde] =	{ FRMOP,0,	optabDE },
+[0xdf] =	{ FRMOP,0,	optabDF },
+[0xe0] =	{ Jbs,0,		"LOOPNE	%p" },
+[0xe1] =	{ Jbs,0,		"LOOPE	%p" },
+[0xe2] =	{ Jbs,0,		"LOOP	%p" },
+[0xe3] =	{ Jbs,0,		"JCXZ	%p" },
+[0xe4] =	{ Ib,0,		"INB	%i,AL" },
+[0xe5] =	{ Ib,0,		"IN%S	%i,%OAX" },
+[0xe6] =	{ Ib,0,		"OUTB	AL,%i" },
+[0xe7] =	{ Ib,0,		"OUT%S	%OAX,%i" },
+[0xe8] =	{ Iwds,0,		"CALL	%p" },
+[0xe9] =	{ Iwds,0,		"JMP	%p" },
+[0xea] =	{ PTR,0,		"JMP	%d" },
+[0xeb] =	{ Jbs,0,		"JMP	%p" },
+[0xec] =	{ 0,0,		"INB	DX,AL" },
+[0xed] =	{ 0,0,		"IN%S	DX,%OAX" },
+[0xee] =	{ 0,0,		"OUTB	AL,DX" },
+[0xef] =	{ 0,0,		"OUT%S	%OAX,DX" },
+[0xf0] =	{ PRE,0,		"LOCK" },
+[0xf2] =	{ OPRE,0,		"REPNE" },
+[0xf3] =	{ OPRE,0,		"REP" },
+[0xf4] =	{ 0,0,		"HLT" },
+[0xf5] =	{ 0,0,		"CMC" },
+[0xf6] =	{ RMOPB,0,	optabF6 },
+[0xf7] =	{ RMOP,0,		optabF7 },
+[0xf8] =	{ 0,0,		"CLC" },
+[0xf9] =	{ 0,0,		"STC" },
+[0xfa] =	{ 0,0,		"CLI" },
+[0xfb] =	{ 0,0,		"STI" },
+[0xfc] =	{ 0,0,		"CLD" },
+[0xfd] =	{ 0,0,		"STD" },
+[0xfe] =	{ RMOPB,0,	optabFE },
+[0xff] =	{ RMOP,0,		optabFF },
+[0x100] =	{ RM,0,		"MOVLQSX	%e,%r" },
+[0x101] =	{ RM,0,		"MOVLQZX	%e,%r" },
+};
+
+/*
+ *  get a byte of the instruction
+ */
+static int
+igetc(Map *map, Instr *ip, uchar *c)
+{
+	if(ip->n+1 > sizeof(ip->mem)){
+		werrstr("instruction too long");
+		return -1;
+	}
+	if (get1(map, ip->addr+ip->n, c, 1) < 0) {
+		werrstr("can't read instruction: %r");
+		return -1;
+	}
+	ip->mem[ip->n++] = *c;
+	return 1;
+}
+
+/*
+ *  get two bytes of the instruction
+ */
+static int
+igets(Map *map, Instr *ip, ushort *sp)
+{
+	uchar c;
+	ushort s;
+
+	if (igetc(map, ip, &c) < 0)
+		return -1;
+	s = c;
+	if (igetc(map, ip, &c) < 0)
+		return -1;
+	s |= (c<<8);
+	*sp = s;
+	return 1;
+}
+
+/*
+ *  get 4 bytes of the instruction
+ */
+static int
+igetl(Map *map, Instr *ip, uint32 *lp)
+{
+	ushort s;
+	int32	l;
+
+	if (igets(map, ip, &s) < 0)
+		return -1;
+	l = s;
+	if (igets(map, ip, &s) < 0)
+		return -1;
+	l |= (s<<16);
+	*lp = l;
+	return 1;
+}
+
+/*
+ *  get 8 bytes of the instruction
+ *
+static int
+igetq(Map *map, Instr *ip, vlong *qp)
+{
+	uint32	l;
+	uvlong q;
+
+	if (igetl(map, ip, &l) < 0)
+		return -1;
+	q = l;
+	if (igetl(map, ip, &l) < 0)
+		return -1;
+	q |= ((uvlong)l<<32);
+	*qp = q;
+	return 1;
+}
+ */
+
+static int
+getdisp(Map *map, Instr *ip, int mod, int rm, int code, int pcrel)
+{
+	uchar c;
+	ushort s;
+
+	if (mod > 2)
+		return 1;
+	if (mod == 1) {
+		if (igetc(map, ip, &c) < 0)
+			return -1;
+		if (c&0x80)
+			ip->disp = c|0xffffff00;
+		else
+			ip->disp = c&0xff;
+	} else if (mod == 2 || rm == code) {
+		if (ip->asize == 'E') {
+			if (igetl(map, ip, &ip->disp) < 0)
+				return -1;
+			if (mod == 0)
+				ip->rip = pcrel;
+		} else {
+			if (igets(map, ip, &s) < 0)
+				return -1;
+			if (s&0x8000)
+				ip->disp = s|0xffff0000;
+			else
+				ip->disp = s;
+		}
+		if (mod == 0)
+			ip->base = -1;
+	}
+	return 1;
+}
+
+static int
+modrm(Map *map, Instr *ip, uchar c)
+{
+	uchar rm, mod;
+
+	mod = (c>>6)&3;
+	rm = c&7;
+	ip->mod = mod;
+	ip->base = rm;
+	ip->reg = (c>>3)&7;
+	ip->rip = 0;
+	if (mod == 3)			/* register */
+		return 1;
+	if (ip->asize == 0) {		/* 16-bit mode */
+		switch(rm) {
+		case 0:
+			ip->base = BX; ip->index = SI;
+			break;
+		case 1:
+			ip->base = BX; ip->index = DI;
+			break;
+		case 2:
+			ip->base = BP; ip->index = SI;
+			break;
+		case 3:
+			ip->base = BP; ip->index = DI;
+			break;
+		case 4:
+			ip->base = SI;
+			break;
+		case 5:
+			ip->base = DI;
+			break;
+		case 6:
+			ip->base = BP;
+			break;
+		case 7:
+			ip->base = BX;
+			break;
+		default:
+			break;
+		}
+		return getdisp(map, ip, mod, rm, 6, 0);
+	}
+	if (rm == 4) {	/* scummy sib byte */
+		if (igetc(map, ip, &c) < 0)
+			return -1;
+		ip->ss = (c>>6)&0x03;
+		ip->index = (c>>3)&0x07;
+		if (ip->index == 4)
+			ip->index = -1;
+		ip->base = c&0x07;
+		return getdisp(map, ip, mod, ip->base, 5, 0);
+	}
+	return getdisp(map, ip, mod, rm, 5, ip->amd64);
+}
+
+static char *
+_hexify(char *buf, uint32 p, int zeros)
+{
+	uint32 d;
+
+	d = p/16;
+	if(d)
+		buf = _hexify(buf, d, zeros-1);
+	else
+		while(zeros--)
+			*buf++ = '0';
+	*buf++ = "0123456789abcdef"[p&0x0f];
+	return buf;
+}
+
+static Optable *
+mkinstr(Map *map, Instr *ip, uvlong pc, int is64)
+{
+	int i, n, norex;
+	uchar c;
+	ushort s;
+	Optable *op, *obase;
+	char buf[128];
+
+	memset(ip, 0, sizeof(*ip));
+	norex = 1;
+	ip->base = -1;
+	ip->index = -1;
+	ip->osize = 'L';
+	ip->asize = 'E';
+	ip->amd64 = is64;
+	norex = 0;
+	ip->addr = pc;
+	if (igetc(map, ip, &c) < 0)
+		return 0;
+	obase = optable;
+newop:
+	if(ip->amd64 && !norex){
+		if(c >= 0x40 && c <= 0x4f) {
+			ip->rex = c;
+			if(igetc(map, ip, &c) < 0)
+				return 0;
+		}
+		if(c == 0x63){
+			if(ip->rex&REXW)
+				op = &obase[0x100];	/* MOVLQSX */
+			else
+				op = &obase[0x101];	/* MOVLQZX */
+			goto hack;
+		}
+	}
+	if(obase == optable)
+		ip->op = c;
+	op = &obase[c];
+hack:
+	if (op->proto == 0) {
+badop:
+		n = snprint(buf, sizeof(buf), "opcode: ??");
+		for (i = 0; i < ip->n && n < sizeof(buf)-3; i++, n+=2)
+			_hexify(buf+n, ip->mem[i], 1);
+		strcpy(buf+n, "??");
+		werrstr(buf);
+		return 0;
+	}
+	for(i = 0; i < 2 && op->operand[i]; i++) {
+		switch(op->operand[i]) {
+		case Ib:	/* 8-bit immediate - (no sign extension)*/
+			if (igetc(map, ip, &c) < 0)
+				return 0;
+			ip->imm = c&0xff;
+			ip->imm64 = ip->imm;
+			break;
+		case Jbs:	/* 8-bit jump immediate (sign extended) */
+			if (igetc(map, ip, &c) < 0)
+				return 0;
+			if (c&0x80)
+				ip->imm = c|0xffffff00;
+			else
+				ip->imm = c&0xff;
+			ip->imm64 = (int32)ip->imm;
+			ip->jumptype = Jbs;
+			break;
+		case Ibs:	/* 8-bit immediate (sign extended) */
+			if (igetc(map, ip, &c) < 0)
+				return 0;
+			if (c&0x80)
+				if (ip->osize == 'L')
+					ip->imm = c|0xffffff00;
+				else
+					ip->imm = c|0xff00;
+			else
+				ip->imm = c&0xff;
+			ip->imm64 = (int32)ip->imm;
+			break;
+		case Iw:	/* 16-bit immediate -> imm */
+			if (igets(map, ip, &s) < 0)
+				return 0;
+			ip->imm = s&0xffff;
+			ip->imm64 = ip->imm;
+			ip->jumptype = Iw;
+			break;
+		case Iw2:	/* 16-bit immediate -> in imm2*/
+			if (igets(map, ip, &s) < 0)
+				return 0;
+			ip->imm2 = s&0xffff;
+			break;
+		case Iwd:	/* Operand-sized immediate (no sign extension unless 64 bits)*/
+			if (ip->osize == 'L') {
+				if (igetl(map, ip, &ip->imm) < 0)
+					return 0;
+				ip->imm64 = ip->imm;
+				if(ip->rex&REXW && (ip->imm & (1<<31)) != 0)
+					ip->imm64 |= (vlong)~0 << 32;
+			} else {
+				if (igets(map, ip, &s)< 0)
+					return 0;
+				ip->imm = s&0xffff;
+				ip->imm64 = ip->imm;
+			}
+			break;
+		case Iwdq:	/* Operand-sized immediate, possibly big */
+			if (ip->osize == 'L') {
+				if (igetl(map, ip, &ip->imm) < 0)
+					return 0;
+				ip->imm64 = ip->imm;
+				if (ip->rex & REXW) {
+					uint32 l;
+					if (igetl(map, ip, &l) < 0)
+						return 0;
+					ip->imm64 |= (uvlong)l << 32;
+				}
+			} else {
+				if (igets(map, ip, &s)< 0)
+					return 0;
+				ip->imm = s&0xffff;
+			}
+			break;
+		case Awd:	/* Address-sized immediate (no sign extension)*/
+			if (ip->asize == 'E') {
+				if (igetl(map, ip, &ip->imm) < 0)
+					return 0;
+				/* TO DO: REX */
+			} else {
+				if (igets(map, ip, &s)< 0)
+					return 0;
+				ip->imm = s&0xffff;
+			}
+			break;
+		case Iwds:	/* Operand-sized immediate (sign extended) */
+			if (ip->osize == 'L') {
+				if (igetl(map, ip, &ip->imm) < 0)
+					return 0;
+			} else {
+				if (igets(map, ip, &s)< 0)
+					return 0;
+				if (s&0x8000)
+					ip->imm = s|0xffff0000;
+				else
+					ip->imm = s&0xffff;
+			}
+			ip->jumptype = Iwds;
+			break;
+		case OA:	/* literal 0x0a byte */
+			if (igetc(map, ip, &c) < 0)
+				return 0;
+			if (c != 0x0a)
+				goto badop;
+			break;
+		case Op_R0:	/* base register must be R0 */
+			if (ip->base != 0)
+				goto badop;
+			break;
+		case Op_R1:	/* base register must be R1 */
+			if (ip->base != 1)
+				goto badop;
+			break;
+		case RMB:	/* R/M field with byte register (/r)*/
+			if (igetc(map, ip, &c) < 0)
+				return 0;
+			if (modrm(map, ip, c) < 0)
+				return 0;
+			ip->osize = 'B';
+			break;
+		case RM:	/* R/M field with register (/r) */
+			if (igetc(map, ip, &c) < 0)
+				return 0;
+			if (modrm(map, ip, c) < 0)
+				return 0;
+			break;
+		case RMOPB:	/* R/M field with op code (/digit) */
+			if (igetc(map, ip, &c) < 0)
+				return 0;
+			if (modrm(map, ip, c) < 0)
+				return 0;
+			c = ip->reg;		/* secondary op code */
+			obase = (Optable*)op->proto;
+			ip->osize = 'B';
+			goto newop;
+		case RMOP:	/* R/M field with op code (/digit) */
+			if (igetc(map, ip, &c) < 0)
+				return 0;
+			if (modrm(map, ip, c) < 0)
+				return 0;
+			obase = (Optable*)op->proto;
+			if(ip->amd64 && obase == optab0F01 && c == 0xF8)
+				return optab0F01F8;
+			c = ip->reg;
+			goto newop;
+		case FRMOP:	/* FP R/M field with op code (/digit) */
+			if (igetc(map, ip, &c) < 0)
+				return 0;
+			if (modrm(map, ip, c) < 0)
+				return 0;
+			if ((c&0xc0) == 0xc0)
+				c = ip->reg+8;		/* 16 entry table */
+			else
+				c = ip->reg;
+			obase = (Optable*)op->proto;
+			goto newop;
+		case FRMEX:	/* Extended FP R/M field with op code (/digit) */
+			if (igetc(map, ip, &c) < 0)
+				return 0;
+			if (modrm(map, ip, c) < 0)
+				return 0;
+			if ((c&0xc0) == 0xc0)
+				c = (c&0x3f)+8;		/* 64-entry table */
+			else
+				c = ip->reg;
+			obase = (Optable*)op->proto;
+			goto newop;
+		case RMR:	/* R/M register only (mod = 11) */
+			if (igetc(map, ip, &c) < 0)
+				return 0;
+			if ((c&0xc0) != 0xc0) {
+				werrstr("invalid R/M register: %#x", c);
+				return 0;
+			}
+			if (modrm(map, ip, c) < 0)
+				return 0;
+			break;
+		case RMM:	/* R/M register only (mod = 11) */
+			if (igetc(map, ip, &c) < 0)
+				return 0;
+			if ((c&0xc0) == 0xc0) {
+				werrstr("invalid R/M memory mode: %#x", c);
+				return 0;
+			}
+			if (modrm(map, ip, c) < 0)
+				return 0;
+			break;
+		case PTR:	/* Seg:Displacement addr (ptr16:16 or ptr16:32) */
+			if (ip->osize == 'L') {
+				if (igetl(map, ip, &ip->disp) < 0)
+					return 0;
+			} else {
+				if (igets(map, ip, &s)< 0)
+					return 0;
+				ip->disp = s&0xffff;
+			}
+			if (igets(map, ip, (ushort*)&ip->seg) < 0)
+				return 0;
+			ip->jumptype = PTR;
+			break;
+		case AUXMM:	/* Multi-byte op code; prefix determines table selection */
+			if (igetc(map, ip, &c) < 0)
+				return 0;
+			obase = (Optable*)op->proto;
+			switch (ip->opre) {
+			case 0x66:	op = optab660F; break;
+			case 0xF2:	op = optabF20F; break;
+			case 0xF3:	op = optabF30F; break;
+			default:	op = nil; break;
+			}
+			if(op != nil && op[c].proto != nil)
+				obase = op;
+			norex = 1;	/* no more rex prefixes */
+			/* otherwise the optab entry captures it */
+			goto newop;
+		case AUX:	/* Multi-byte op code - Auxiliary table */
+			obase = (Optable*)op->proto;
+			if (igetc(map, ip, &c) < 0)
+				return 0;
+			goto newop;
+		case OPRE:	/* Instr Prefix or media op */
+			ip->opre = c;
+			/* fall through */
+		case PRE:	/* Instr Prefix */
+			ip->prefix = (char*)op->proto;
+			if (igetc(map, ip, &c) < 0)
+				return 0;
+			if (ip->opre && c == 0x0F)
+				ip->prefix = 0;
+			goto newop;
+		case SEG:	/* Segment Prefix */
+			ip->segment = (char*)op->proto;
+			if (igetc(map, ip, &c) < 0)
+				return 0;
+			goto newop;
+		case OPOVER:	/* Operand size override */
+			ip->opre = c;
+			ip->osize = 'W';
+			if (igetc(map, ip, &c) < 0)
+				return 0;
+			if (c == 0x0F)
+				ip->osize = 'L';
+			else if (ip->amd64 && (c&0xF0) == 0x40)
+				ip->osize = 'Q';
+			goto newop;
+		case ADDOVER:	/* Address size override */
+			ip->asize = 0;
+			if (igetc(map, ip, &c) < 0)
+				return 0;
+			goto newop;
+		case JUMP:	/* mark instruction as JUMP or RET */
+		case RET:
+			ip->jumptype = op->operand[i];
+			break;
+		default:
+			werrstr("bad operand type %d", op->operand[i]);
+			return 0;
+		}
+	}
+	return op;
+}
+
+static void
+bprint(Instr *ip, char *fmt, ...)
+{
+	va_list arg;
+
+	va_start(arg, fmt);
+	ip->curr = vseprint(ip->curr, ip->end, fmt, arg);
+	va_end(arg);
+}
+
+/*
+ *  if we want to call 16 bit regs AX,BX,CX,...
+ *  and 32 bit regs EAX,EBX,ECX,... then
+ *  change the defs of ANAME and ONAME to:
+ *  #define	ANAME(ip)	((ip->asize == 'E' ? "E" : "")
+ *  #define	ONAME(ip)	((ip)->osize == 'L' ? "E" : "")
+ */
+#define	ANAME(ip)	""
+#define	ONAME(ip)	""
+
+static char *reg[] =  {
+[AX] =	"AX",
+[CX] =	"CX",
+[DX] =	"DX",
+[BX] =	"BX",
+[SP] =	"SP",
+[BP] =	"BP",
+[SI] =	"SI",
+[DI] =	"DI",
+
+	/* amd64 */
+[AMD64_R8] =	"R8",
+[AMD64_R9] =	"R9",
+[AMD64_R10] =	"R10",
+[AMD64_R11] =	"R11",
+[AMD64_R12] =	"R12",
+[AMD64_R13] =	"R13",
+[AMD64_R14] =	"R14",
+[AMD64_R15] =	"R15",
+};
+
+static char *breg[] = { "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH" };
+static char *breg64[] = { "AL", "CL", "DL", "BL", "SPB", "BPB", "SIB", "DIB",
+	"R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B" };
+static char *sreg[] = { "ES", "CS", "SS", "DS", "FS", "GS" };
+
+static void
+immediate(Instr *ip, vlong val)
+{
+	// TODO: Translate known names.
+	if((ip->rex & REXW) == 0)
+		bprint(ip, "%#lux", (long)val);
+	else
+		bprint(ip, "%#llux", val);
+}
+
+static void
+pea(Instr *ip)
+{
+	int base;
+
+	base = ip->base;
+	if(base >= 0 && (ip->rex & REXB))
+		base += 8;
+
+	if (ip->mod == 3) {
+		if (ip->osize == 'B')
+			bprint(ip, (ip->rex & REXB? breg64: breg)[(uchar)ip->base]);
+		else
+			bprint(ip, "%s%s", ANAME(ip), reg[base]);
+		return;
+	}
+
+	if (ip->segment)
+		bprint(ip, ip->segment);
+	if (1) {
+		if (ip->base < 0)
+			immediate(ip, ip->disp);
+		else {
+			bprint(ip, "%#ux", ip->disp);
+			if(ip->rip)
+				bprint(ip, "(RIP)");
+			bprint(ip,"(%s%s)", ANAME(ip), reg[ip->rex&REXB? ip->base+8: ip->base]);
+		}
+	}
+	if (ip->index >= 0)
+		bprint(ip,"(%s%s*%d)", ANAME(ip), reg[ip->rex&REXX? ip->index+8: ip->index], 1<<ip->ss);
+}
+
+static void
+prinstr(Instr *ip, char *fmt)
+{
+	int sharp, i;
+	vlong v;
+
+	if (ip->prefix)
+		bprint(ip, "%s ", ip->prefix);
+	for (; *fmt && ip->curr < ip->end; fmt++) {
+		if (*fmt != '%'){
+			*ip->curr++ = *fmt;
+			continue;
+		}
+		sharp = 0;
+		if(*++fmt == '#') {
+			sharp = 1;
+			++fmt;
+		}
+		switch(*fmt){
+		case '%':
+			*ip->curr++ = '%';
+			break;
+		case 'A':
+			bprint(ip, "%s", ANAME(ip));
+			break;
+		case 'C':
+			bprint(ip, "CR%d", ip->reg);
+			break;
+		case 'D':
+			if (ip->reg < 4 || ip->reg == 6 || ip->reg == 7)
+				bprint(ip, "DR%d",ip->reg);
+			else
+				bprint(ip, "???");
+			break;
+		case 'I':
+			bprint(ip, "$");
+			immediate(ip, ip->imm2);
+			break;
+		case 'O':
+			bprint(ip,"%s", ONAME(ip));
+			break;
+		case 'o':
+			i = ip->op & 7;
+			if(ip->rex & REXB)
+				i += 8;
+			bprint(ip, "%s", reg[i]);
+			break;
+		case 'i':
+			if(!sharp)
+				bprint(ip, "$");
+			v = ip->imm;
+			if(ip->rex & REXW)
+				v = ip->imm64;
+			immediate(ip, v);
+			break;
+		case 'R':
+			bprint(ip, "%s%s", ONAME(ip), reg[ip->rex&REXR? ip->reg+8: ip->reg]);
+			break;
+		case 'S':
+			if(ip->osize == 'Q' || (ip->osize == 'L' && ip->rex & REXW))
+				bprint(ip, "Q");
+			else
+				bprint(ip, "%c", ip->osize);
+			break;
+		case 's':
+			if(ip->opre == 0 || ip->opre == 0x66)
+				bprint(ip, "P");
+			else
+				bprint(ip, "S");
+			if(ip->opre == 0xf2 || ip->opre == 0x66)
+				bprint(ip, "D");
+			else
+				bprint(ip, "S");
+			break;
+		case 'T':
+			if (ip->reg == 6 || ip->reg == 7)
+				bprint(ip, "TR%d",ip->reg);
+			else
+				bprint(ip, "???");
+			break;
+		case 'W':
+			if (ip->osize == 'Q' || (ip->osize == 'L' && ip->rex & REXW))
+				bprint(ip, "CDQE");
+			else if (ip->osize == 'L')
+				bprint(ip,"CWDE");
+			else
+				bprint(ip, "CBW");
+			break;
+		case 'd':
+			bprint(ip,"%#ux:%#ux", ip->seg, ip->disp);
+			break;
+		case 'm':
+			if (ip->mod == 3 && ip->osize != 'B') {
+				if(fmt[1] != '*'){
+					if(ip->opre != 0) {
+						bprint(ip, "X%d", ip->rex&REXB? ip->base+8: ip->base);
+						break;
+					}
+				} else
+					fmt++;
+				bprint(ip, "M%d", ip->base);
+				break;
+			}
+			pea(ip);
+			break;
+		case 'e':
+			pea(ip);
+			break;
+		case 'f':
+			bprint(ip, "F%d", ip->base);
+			break;
+		case 'g':
+			if (ip->reg < 6)
+				bprint(ip,"%s",sreg[ip->reg]);
+			else
+				bprint(ip,"???");
+			break;
+		case 'p':
+			/*
+			 * signed immediate in the uint32 ip->imm.
+			 */
+			v = (int32)ip->imm;
+			immediate(ip, v+ip->addr+ip->n);
+			break;
+		case 'r':
+			if (ip->osize == 'B')
+				bprint(ip,"%s", (ip->rex? breg64: breg)[ip->rex&REXR? ip->reg+8: ip->reg]);
+			else
+				bprint(ip, reg[ip->rex&REXR? ip->reg+8: ip->reg]);
+			break;
+		case 'w':
+			if (ip->osize == 'Q' || ip->rex & REXW)
+				bprint(ip, "CQO");
+			else if (ip->osize == 'L')
+				bprint(ip,"CDQ");
+			else
+				bprint(ip, "CWD");
+			break;
+		case 'M':
+			if(ip->opre != 0)
+				bprint(ip, "X%d", ip->rex&REXR? ip->reg+8: ip->reg);
+			else
+				bprint(ip, "M%d", ip->reg);
+			break;
+		case 'x':
+			if (ip->mod == 3 && ip->osize != 'B') {
+				bprint(ip, "X%d", ip->rex&REXB? ip->base+8: ip->base);
+				break;
+			}
+			pea(ip);
+			break;
+		case 'X':
+			bprint(ip, "X%d", ip->rex&REXR? ip->reg+8: ip->reg);
+			break;
+		default:
+			bprint(ip, "%%%c", *fmt);
+			break;
+		}
+	}
+	*ip->curr = 0;		/* there's always room for 1 byte */
+}
+
+static int
+i386inst(Map *map, uvlong pc, int is64, char modifier, char *buf, int n)
+{
+	Instr instr;
+	Optable *op;
+
+	USED(modifier);
+	op = mkinstr(map, &instr, pc, is64);
+	if (op == 0)
+		return -1;
+	instr.curr = buf;
+	instr.end = buf+n-1;
+	prinstr(&instr, op->proto);
+	return instr.n;
+}
+
+/*
+static int
+i386das(Map *map, uvlong pc, char *buf, int n)
+{
+	Instr instr;
+	int i;
+
+	if (mkinstr(map, &instr, pc) == 0) {
+		errstr(buf, n);
+		return -1;
+	}
+	for(i = 0; i < instr.n && n > 2; i++) {
+		_hexify(buf, instr.mem[i], 1);
+		buf += 2;
+		n -= 2;
+	}
+	*buf = 0;
+	return instr.n;
+}
+
+static int
+i386instlen(Map *map, uvlong pc)
+{
+	Instr i;
+
+	if (mkinstr(map, &i, pc))
+		return i.n;
+	return -1;
+}
+*/
+
+static int
+getmem(Map *m, uvlong addr, uchar *dst, int ndst)
+{
+	uchar *p;
+	
+	p = m->startp + (addr - m->startpc);
+	if(p < m->p || p >= m->ep || m->ep - p < ndst) {
+		werrstr("out of bounds");
+		return -1;
+	}
+	memmove(dst, p, ndst);
+	return ndst;
+}
+
+int
+x86disasm(uchar *p, uchar *end, uvlong pc, int is64, char *buf, int n)
+{
+	Map m;
+	
+	m.p = p;
+	m.ep = end;
+	m.startp = p;
+	m.startpc = pc;
+	m.get1 = getmem;
+	return i386inst(&m, pc, is64, 0, buf, n);
+}
+
+void
+usage(void)
+{
+	fprint(2, "usage: libmach8db file\n");
+	exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+	uchar data[10000], *p, *ep;
+	int fd, n, eof, addr, is64;
+	Biobuf bstdout;
+	char buf[1000];
+
+	fmtinstall('H', encodefmt);
+
+	is64 = 0;
+	ARGBEGIN{
+	case '8':
+		is64 = 0;
+		break;
+	case '6':
+		is64 = 1;
+		break;
+	default:
+		usage();
+	}ARGEND
+	
+	if(argc != 1)
+		usage();
+	
+	fd = open(argv[0], OREAD);
+	if(fd < 0)
+		sysfatal("open %s: %r", argv[0]);
+	
+	Binit(&bstdout, 1, OWRITE);
+	p = data;
+	ep = data;
+	eof = 0;
+	addr = 0;
+	for(;;) {
+		if(!eof && ep-p < 64) {
+			memmove(data, p, ep-p);
+			ep = data + (ep-p);
+			p = data;
+			n = readn(fd, ep, data+sizeof data-ep);
+			if(n <= 0)
+				eof = 1;
+			else
+				ep += n;
+		}
+		if(p == ep)
+			break;
+		n = x86disasm(p, ep, addr, is64, buf, sizeof buf);
+		if(n < 0) {
+			Bprint(&bstdout, "0x%x %.*H error: %r\n", addr, 1, p);
+			n = 1;
+		} else {
+			Bprint(&bstdout, "0x%x %.*H %s\n", addr, n, p, buf);
+		}
+		addr += n;
+		p += n;
+	}
+	Bflush(&bstdout);
+	exits(0);
+}
diff --git a/src/cmd/internal/rsc.io/x86/x86asm/xed_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/xed_test.go
similarity index 100%
rename from src/cmd/internal/rsc.io/x86/x86asm/xed_test.go
rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/xed_test.go
diff --git a/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/xedext_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/xedext_test.go
new file mode 100644
index 0000000..e27cdc0
--- /dev/null
+++ b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/xedext_test.go
@@ -0,0 +1,205 @@
+package x86asm
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"log"
+	"os"
+	"strconv"
+	"strings"
+	"testing"
+)
+
+// xed binary from Intel sde-external-6.22.0-2014-03-06.
+const xedPath = "/Users/rsc/bin/xed"
+
+func testXedArch(t *testing.T, arch int, generate func(func([]byte))) {
+	if testing.Short() {
+		t.Skip("skipping xed test in short mode")
+	}
+	if _, err := os.Stat(xedPath); err != nil {
+		t.Skip(err)
+	}
+
+	testExtDis(t, "intel", arch, xed, generate, allowedMismatchXed)
+}
+
+func testXed32(t *testing.T, generate func(func([]byte))) {
+	testXedArch(t, 32, generate)
+}
+
+func testXed64(t *testing.T, generate func(func([]byte))) {
+	testXedArch(t, 64, generate)
+}
+
+func xed(ext *ExtDis) error {
+	b, err := ext.Run(xedPath, fmt.Sprintf("-%d", ext.Arch), "-n", "1G", "-ir", ext.File.Name())
+	if err != nil {
+		return err
+	}
+
+	nmatch := 0
+	next := uint32(start)
+	var (
+		addr   uint32
+		encbuf [32]byte
+		enc    []byte
+		text   string
+	)
+
+	var xedEnd = []byte("# end of text section")
+	var xedEnd1 = []byte("# Errors")
+
+	eof := false
+	for {
+		line, err := b.ReadSlice('\n')
+		if err != nil {
+			if err == io.EOF {
+				break
+			}
+			return fmt.Errorf("reading objdump output: %v", err)
+		}
+		if debug {
+			os.Stdout.Write(line)
+		}
+		if bytes.HasPrefix(line, xedEnd) || bytes.HasPrefix(line, xedEnd1) {
+			eof = true
+		}
+		if eof {
+			continue
+		}
+		nmatch++
+		addr, enc, text = parseLineXed(line, encbuf[:0])
+		if addr > next {
+			return fmt.Errorf("address out of sync expected <= %#x at %q in:\n%s", next, line, line)
+		}
+		if addr < next {
+			continue
+		}
+		switch text {
+		case "repz":
+			text = "rep"
+		case "repnz":
+			text = "repn"
+		default:
+			text = strings.Replace(text, "repz ", "rep ", -1)
+			text = strings.Replace(text, "repnz ", "repn ", -1)
+		}
+		if m := pcrelw.FindStringSubmatch(text); m != nil {
+			targ, _ := strconv.ParseUint(m[2], 16, 64)
+			text = fmt.Sprintf("%s .%+#x", m[1], int16(uint32(targ)-uint32(uint16(addr))-uint32(len(enc))))
+		}
+		if m := pcrel.FindStringSubmatch(text); m != nil {
+			targ, _ := strconv.ParseUint(m[2], 16, 64)
+			text = fmt.Sprintf("%s .%+#x", m[1], int32(uint32(targ)-addr-uint32(len(enc))))
+		}
+		ext.Dec <- ExtInst{addr, encbuf, len(enc), text}
+		encbuf = [32]byte{}
+		enc = nil
+		next += 32
+	}
+	if next != start+uint32(ext.Size) {
+		return fmt.Errorf("not enough results found [%d %d]", next, start+ext.Size)
+	}
+	if err := ext.Wait(); err != nil {
+		return fmt.Errorf("exec: %v", err)
+	}
+
+	return nil
+}
+
+var (
+	xedInRaw    = []byte("In raw...")
+	xedDots     = []byte("...")
+	xdis        = []byte("XDIS ")
+	xedError    = []byte("ERROR: ")
+	xedNoDecode = []byte("Could not decode at offset: 0x")
+)
+
+func parseLineXed(line []byte, encstart []byte) (addr uint32, enc []byte, text string) {
+	oline := line
+	if bytes.HasPrefix(line, xedInRaw) || bytes.HasPrefix(line, xedDots) {
+		return 0, nil, ""
+	}
+	if bytes.HasPrefix(line, xedError) {
+		i := bytes.IndexByte(line[len(xedError):], ' ')
+		if i < 0 {
+			log.Fatalf("cannot parse error: %q", oline)
+		}
+		errstr := string(line[len(xedError):])
+		i = bytes.Index(line, xedNoDecode)
+		if i < 0 {
+			log.Fatalf("cannot parse error: %q", oline)
+		}
+		i += len(xedNoDecode)
+		j := bytes.IndexByte(line[i:], ' ')
+		if j < 0 {
+			log.Fatalf("cannot parse error: %q", oline)
+		}
+		x, err := strconv.ParseUint(string(trimSpace(line[i:i+j])), 16, 32)
+		if err != nil {
+			log.Fatalf("cannot parse disassembly: %q", oline)
+		}
+		addr = uint32(x)
+		return addr, nil, errstr
+	}
+
+	if !bytes.HasPrefix(line, xdis) {
+		log.Fatalf("cannot parse disassembly: %q", oline)
+	}
+
+	i := bytes.IndexByte(line, ':')
+	if i < 0 {
+		log.Fatalf("cannot parse disassembly: %q", oline)
+	}
+	x, err := strconv.ParseUint(string(trimSpace(line[len(xdis):i])), 16, 32)
+	if err != nil {
+		log.Fatalf("cannot parse disassembly: %q", oline)
+	}
+	addr = uint32(x)
+
+	// spaces
+	i++
+	for i < len(line) && line[i] == ' ' {
+		i++
+	}
+	// instruction class, spaces
+	for i < len(line) && line[i] != ' ' {
+		i++
+	}
+	for i < len(line) && line[i] == ' ' {
+		i++
+	}
+	// instruction set, spaces
+	for i < len(line) && line[i] != ' ' {
+		i++
+	}
+	for i < len(line) && line[i] == ' ' {
+		i++
+	}
+
+	// hex
+	hexStart := i
+	for i < len(line) && line[i] != ' ' {
+		i++
+	}
+	hexEnd := i
+	for i < len(line) && line[i] == ' ' {
+		i++
+	}
+
+	// text
+	textStart := i
+	for i < len(line) && line[i] != '\n' {
+		i++
+	}
+	textEnd := i
+
+	enc, ok := parseHex(line[hexStart:hexEnd], encstart)
+	if !ok {
+		log.Fatalf("cannot parse disassembly: %q", oline)
+	}
+
+	return addr, enc, string(fixSpace(line[textStart:textEnd]))
+}
diff --git a/src/cmd/internal/unvendor/vendor.json b/src/cmd/internal/unvendor/vendor.json
new file mode 100644
index 0000000..565498f
--- /dev/null
+++ b/src/cmd/internal/unvendor/vendor.json
@@ -0,0 +1,16 @@
+{
+	"package": [
+		{
+			"canonical": "golang.org/x/arch/x86/x86asm",
+			"local": "golang.org/x/arch/x86/x86asm",
+			"revision": "ad6a463afcf9bd5b38c81fa9ba612dae11859d40",
+			"revisionTime": "2015-08-28T15:42:14Z"
+		},
+		{
+			"canonical": "golang.org/x/arch/arm/armasm",
+			"local": "golang.org/x/arch/arm/armasm",
+			"revision": "ad6a463afcf9bd5b38c81fa9ba612dae11859d40",
+			"revisionTime": "2015-08-28T15:42:14Z"
+		}
+	]
+}
diff --git a/src/cmd/link/doc.go b/src/cmd/link/doc.go
index 479988e..ffaead7 100644
--- a/src/cmd/link/doc.go
+++ b/src/cmd/link/doc.go
@@ -52,6 +52,9 @@ Flags:
 		The dynamic header is on by default, even without any
 		references to dynamic libraries, because many common
 		system tools now assume the presence of the header.
+	-extar ar
+		Set the external archive program (default "ar").
+		Used only for -buildmode=c-archive.
 	-extld linker
 		Set the external linker (default "clang" or "gcc").
 	-extldflags flags
@@ -63,6 +66,12 @@ Flags:
 	-installsuffix suffix
 		Look for packages in $GOROOT/pkg/$GOOS_$GOARCH_suffix
 		instead of $GOROOT/pkg/$GOOS_$GOARCH.
+	-libgcc file
+		Set name of compiler support library.
+		This is only used in internal link mode.
+		If not set, default value comes from running the compiler,
+		which may be set by the -extld option.
+		Set to "none" to use no support library.
 	-linkmode mode
 		Set link mode (internal, external, auto).
 		This sets the linking mode as described in cmd/cgo/doc.go.
@@ -72,6 +81,8 @@ Flags:
 		Write memory profile to file.
 	-memprofilerate rate
 		Set runtime.MemProfileRate to rate.
+	-msan
+		Link with C/C++ memory sanitizer support.
 	-o file
 		Write output to file (default a.out, or a.out.exe on Windows).
 	-r dir1:dir2:...
diff --git a/src/cmd/link/internal/amd64/asm.go b/src/cmd/link/internal/amd64/asm.go
index 4eb2092..fa785c2 100644
--- a/src/cmd/link/internal/amd64/asm.go
+++ b/src/cmd/link/internal/amd64/asm.go
@@ -42,8 +42,6 @@ func PADDR(x uint32) uint32 {
 	return x &^ 0x80000000
 }
 
-var zeroes string
-
 func Addcall(ctxt *ld.Link, s *ld.LSym, t *ld.LSym) int64 {
 	s.Reachable = true
 	i := s.Size
@@ -81,7 +79,7 @@ func gentext() {
 	//    0:	48 8d 3d 00 00 00 00 	lea    0x0(%rip),%rdi        # 7 <local.dso_init+0x7>
 	// 			3: R_X86_64_PC32	runtime.firstmoduledata-0x4
 	o(0x48, 0x8d, 0x3d)
-	ld.Addpcrelplus(ld.Ctxt, initfunc, ld.Linklookup(ld.Ctxt, "runtime.firstmoduledata", 0), 0)
+	ld.Addpcrelplus(ld.Ctxt, initfunc, ld.Ctxt.Moduledata, 0)
 	//    7:	e8 00 00 00 00       	callq  c <local.dso_init+0xc>
 	// 			8: R_X86_64_PLT32	runtime.addmoduledata-0x4
 	o(0xe8)
@@ -325,7 +323,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
 func elfreloc1(r *ld.Reloc, sectoff int64) int {
 	ld.Thearch.Vput(uint64(sectoff))
 
-	elfsym := r.Xsym.Elfsym
+	elfsym := r.Xsym.ElfsymForReloc()
 	switch r.Type {
 	default:
 		return -1
diff --git a/src/cmd/link/internal/arm/asm.go b/src/cmd/link/internal/arm/asm.go
index a0e31a3..74c2249 100644
--- a/src/cmd/link/internal/arm/asm.go
+++ b/src/cmd/link/internal/arm/asm.go
@@ -37,7 +37,75 @@ import (
 	"log"
 )
 
+// This assembler:
+//
+//         .align 2
+// local.dso_init:
+//         ldr r0, .Lmoduledata
+// .Lloadfrom:
+//         ldr r0, [r0]
+//         b runtime.addmoduledata at plt
+// .align 2
+// .Lmoduledata:
+//         .word local.moduledata(GOT_PREL) + (. - (.Lloadfrom + 4))
+// assembles to:
+//
+// 00000000 <local.dso_init>:
+//    0:        e59f0004        ldr     r0, [pc, #4]    ; c <local.dso_init+0xc>
+//    4:        e5900000        ldr     r0, [r0]
+//    8:        eafffffe        b       0 <runtime.addmoduledata>
+//                      8: R_ARM_JUMP24 runtime.addmoduledata
+//    c:        00000004        .word   0x00000004
+//                      c: R_ARM_GOT_PREL       local.moduledata
+
 func gentext() {
+	if !ld.DynlinkingGo() {
+		return
+	}
+	addmoduledata := ld.Linklookup(ld.Ctxt, "runtime.addmoduledata", 0)
+	if addmoduledata.Type == obj.STEXT {
+		// we're linking a module containing the runtime -> no need for
+		// an init function
+		return
+	}
+	addmoduledata.Reachable = true
+	initfunc := ld.Linklookup(ld.Ctxt, "go.link.addmoduledata", 0)
+	initfunc.Type = obj.STEXT
+	initfunc.Local = true
+	initfunc.Reachable = true
+	o := func(op uint32) {
+		ld.Adduint32(ld.Ctxt, initfunc, op)
+	}
+	o(0xe59f0004)
+	o(0xe08f0000)
+
+	o(0xeafffffe)
+	rel := ld.Addrel(initfunc)
+	rel.Off = 8
+	rel.Siz = 4
+	rel.Sym = ld.Linklookup(ld.Ctxt, "runtime.addmoduledata", 0)
+	rel.Type = obj.R_CALLARM
+	rel.Add = 0xeafffffe // vomit
+
+	o(0x00000000)
+	rel = ld.Addrel(initfunc)
+	rel.Off = 12
+	rel.Siz = 4
+	rel.Sym = ld.Ctxt.Moduledata
+	rel.Type = obj.R_PCREL
+	rel.Add = 4
+
+	if ld.Ctxt.Etextp != nil {
+		ld.Ctxt.Etextp.Next = initfunc
+	} else {
+		ld.Ctxt.Textp = initfunc
+	}
+	ld.Ctxt.Etextp = initfunc
+	initarray_entry := ld.Linklookup(ld.Ctxt, "go.link.addmoduledatainit", 0)
+	initarray_entry.Reachable = true
+	initarray_entry.Local = true
+	initarray_entry.Type = obj.SINITARR
+	ld.Addaddr(ld.Ctxt, initarray_entry, initfunc)
 }
 
 // Preserve highest 8 bits of a, and do addition to lower 24-bit
@@ -193,7 +261,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
 func elfreloc1(r *ld.Reloc, sectoff int64) int {
 	ld.Thearch.Lput(uint32(sectoff))
 
-	elfsym := r.Xsym.Elfsym
+	elfsym := r.Xsym.ElfsymForReloc()
 	switch r.Type {
 	default:
 		return -1
@@ -223,13 +291,15 @@ func elfreloc1(r *ld.Reloc, sectoff int64) int {
 			return -1
 		}
 
-	case obj.R_TLS:
+	case obj.R_TLS_LE:
+		ld.Thearch.Lput(ld.R_ARM_TLS_LE32 | uint32(elfsym)<<8)
+
+	case obj.R_TLS_IE:
+		ld.Thearch.Lput(ld.R_ARM_TLS_IE32 | uint32(elfsym)<<8)
+
+	case obj.R_GOTPCREL:
 		if r.Siz == 4 {
-			if ld.Buildmode == ld.BuildmodeCShared {
-				ld.Thearch.Lput(ld.R_ARM_TLS_IE32 | uint32(elfsym)<<8)
-			} else {
-				ld.Thearch.Lput(ld.R_ARM_TLS_LE32 | uint32(elfsym)<<8)
-			}
+			ld.Thearch.Lput(ld.R_ARM_GOT_PREL | uint32(elfsym)<<8)
 		} else {
 			return -1
 		}
@@ -339,7 +409,7 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
 				rs = rs.Outer
 			}
 
-			if rs.Type != obj.SHOSTOBJ && rs.Sect == nil {
+			if rs.Type != obj.SHOSTOBJ && rs.Type != obj.SDYNIMPORT && rs.Sect == nil {
 				ld.Diag("missing section for %s", rs.Name)
 			}
 			r.Xsym = rs
@@ -619,14 +689,14 @@ func asmb() {
 	switch ld.HEADTYPE {
 	default:
 	case obj.Hplan9: /* plan 9 */
-		ld.Thearch.Lput(0x647)                      /* magic */
-		ld.Thearch.Lput(uint32(ld.Segtext.Filelen)) /* sizes */
-		ld.Thearch.Lput(uint32(ld.Segdata.Filelen))
-		ld.Thearch.Lput(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
-		ld.Thearch.Lput(uint32(ld.Symsize))      /* nsyms */
-		ld.Thearch.Lput(uint32(ld.Entryvalue())) /* va of entry */
-		ld.Thearch.Lput(0)
-		ld.Thearch.Lput(uint32(ld.Lcsize))
+		ld.Lputb(0x647)                      /* magic */
+		ld.Lputb(uint32(ld.Segtext.Filelen)) /* sizes */
+		ld.Lputb(uint32(ld.Segdata.Filelen))
+		ld.Lputb(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
+		ld.Lputb(uint32(ld.Symsize))      /* nsyms */
+		ld.Lputb(uint32(ld.Entryvalue())) /* va of entry */
+		ld.Lputb(0)
+		ld.Lputb(uint32(ld.Lcsize))
 
 	case obj.Hlinux,
 		obj.Hfreebsd,
diff --git a/src/cmd/link/internal/arm/l.go b/src/cmd/link/internal/arm/l.go
index 4973772..b6de5a0 100644
--- a/src/cmd/link/internal/arm/l.go
+++ b/src/cmd/link/internal/arm/l.go
@@ -64,9 +64,6 @@ package arm
 
 const (
 	thechar   = '5'
-	PtrSize   = 4
-	IntSize   = 4
-	RegSize   = 4
 	MaxAlign  = 8 // max data alignment
 	FuncAlign = 4 // single-instruction alignment
 	MINLC     = 4
diff --git a/src/cmd/link/internal/arm/obj.go b/src/cmd/link/internal/arm/obj.go
index 14fe7a6..10eb723 100644
--- a/src/cmd/link/internal/arm/obj.go
+++ b/src/cmd/link/internal/arm/obj.go
@@ -86,6 +86,10 @@ func archinit() {
 		ld.Linkmode = ld.LinkInternal
 	}
 
+	if ld.Buildmode == ld.BuildmodeCArchive || ld.Buildmode == ld.BuildmodeCShared || ld.DynlinkingGo() {
+		ld.Linkmode = ld.LinkExternal
+	}
+
 	switch ld.HEADTYPE {
 	default:
 		if ld.Linkmode == ld.LinkAuto {
@@ -169,10 +173,4 @@ func archinit() {
 	if ld.INITDAT != 0 && ld.INITRND != 0 {
 		fmt.Printf("warning: -D0x%x is ignored because of -R0x%x\n", uint64(ld.INITDAT), uint32(ld.INITRND))
 	}
-
-	// embed goarm to runtime.goarm
-	s := ld.Linklookup(ld.Ctxt, "runtime.goarm", 0)
-
-	s.Type = obj.SRODATA
-	ld.Adduint8(ld.Ctxt, s, uint8(ld.Ctxt.Goarm))
 }
diff --git a/src/cmd/link/internal/arm64/asm.go b/src/cmd/link/internal/arm64/asm.go
index 3aebd8a..0e5a2d0 100644
--- a/src/cmd/link/internal/arm64/asm.go
+++ b/src/cmd/link/internal/arm64/asm.go
@@ -38,7 +38,58 @@ import (
 	"log"
 )
 
-func gentext() {}
+func gentext() {
+	if !ld.DynlinkingGo() {
+		return
+	}
+	addmoduledata := ld.Linklookup(ld.Ctxt, "runtime.addmoduledata", 0)
+	if addmoduledata.Type == obj.STEXT {
+		// we're linking a module containing the runtime -> no need for
+		// an init function
+		return
+	}
+	addmoduledata.Reachable = true
+	initfunc := ld.Linklookup(ld.Ctxt, "go.link.addmoduledata", 0)
+	initfunc.Type = obj.STEXT
+	initfunc.Local = true
+	initfunc.Reachable = true
+	o := func(op uint32) {
+		ld.Adduint32(ld.Ctxt, initfunc, op)
+	}
+	// 0000000000000000 <local.dso_init>:
+	// 0:	90000000 	adrp	x0, 0 <runtime.firstmoduledata>
+	// 	0: R_AARCH64_ADR_PREL_PG_HI21	local.moduledata
+	// 4:	91000000 	add	x0, x0, #0x0
+	// 	4: R_AARCH64_ADD_ABS_LO12_NC	local.moduledata
+	o(0x90000000)
+	o(0x91000000)
+	rel := ld.Addrel(initfunc)
+	rel.Off = 0
+	rel.Siz = 8
+	rel.Sym = ld.Ctxt.Moduledata
+	rel.Type = obj.R_ADDRARM64
+
+	// 8:	14000000 	bl	0 <runtime.addmoduledata>
+	// 	8: R_AARCH64_CALL26	runtime.addmoduledata
+	o(0x14000000)
+	rel = ld.Addrel(initfunc)
+	rel.Off = 8
+	rel.Siz = 4
+	rel.Sym = ld.Linklookup(ld.Ctxt, "runtime.addmoduledata", 0)
+	rel.Type = obj.R_CALLARM64 // Really should be R_AARCH64_JUMP26 but doesn't seem to make any difference
+
+	if ld.Ctxt.Etextp != nil {
+		ld.Ctxt.Etextp.Next = initfunc
+	} else {
+		ld.Ctxt.Textp = initfunc
+	}
+	ld.Ctxt.Etextp = initfunc
+	initarray_entry := ld.Linklookup(ld.Ctxt, "go.link.addmoduledatainit", 0)
+	initarray_entry.Reachable = true
+	initarray_entry.Local = true
+	initarray_entry.Type = obj.SINITARR
+	ld.Addaddr(ld.Ctxt, initarray_entry, initfunc)
+}
 
 func adddynrela(rel *ld.LSym, s *ld.LSym, r *ld.Reloc) {
 	log.Fatalf("adddynrela not implemented")
@@ -51,7 +102,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
 func elfreloc1(r *ld.Reloc, sectoff int64) int {
 	ld.Thearch.Vput(uint64(sectoff))
 
-	elfsym := r.Xsym.Elfsym
+	elfsym := r.Xsym.ElfsymForReloc()
 	switch r.Type {
 	default:
 		return -1
@@ -73,6 +124,21 @@ func elfreloc1(r *ld.Reloc, sectoff int64) int {
 		ld.Thearch.Vput(uint64(sectoff + 4))
 		ld.Thearch.Vput(ld.R_AARCH64_ADD_ABS_LO12_NC | uint64(elfsym)<<32)
 
+	case obj.R_ARM64_TLS_LE:
+		ld.Thearch.Vput(ld.R_AARCH64_TLSLE_MOVW_TPREL_G0 | uint64(elfsym)<<32)
+
+	case obj.R_ARM64_TLS_IE:
+		ld.Thearch.Vput(ld.R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 | uint64(elfsym)<<32)
+		ld.Thearch.Vput(uint64(r.Xadd))
+		ld.Thearch.Vput(uint64(sectoff + 4))
+		ld.Thearch.Vput(ld.R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC | uint64(elfsym)<<32)
+
+	case obj.R_ARM64_GOTPCREL:
+		ld.Thearch.Vput(ld.R_AARCH64_ADR_GOT_PAGE | uint64(elfsym)<<32)
+		ld.Thearch.Vput(uint64(r.Xadd))
+		ld.Thearch.Vput(uint64(sectoff + 4))
+		ld.Thearch.Vput(ld.R_AARCH64_LD64_GOT_LO12_NC | uint64(elfsym)<<32)
+
 	case obj.R_CALLARM64:
 		if r.Siz != 4 {
 			return -1
@@ -175,6 +241,37 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
 		default:
 			return -1
 
+		case obj.R_ARM64_GOTPCREL:
+			var o1, o2 uint32
+			if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
+				o1 = uint32(*val >> 32)
+				o2 = uint32(*val)
+			} else {
+				o1 = uint32(*val)
+				o2 = uint32(*val >> 32)
+			}
+			// Any relocation against a function symbol is redirected to
+			// be against a local symbol instead (see putelfsym in
+			// symtab.go) but unfortunately the system linker was buggy
+			// when confronted with a R_AARCH64_ADR_GOT_PAGE relocation
+			// against a local symbol until May 2015
+			// (https://sourceware.org/bugzilla/show_bug.cgi?id=18270). So
+			// we convert the adrp; ld64 + R_ARM64_GOTPCREL into adrp;
+			// add + R_ADDRARM64.
+			if !(r.Sym.Version != 0 || (r.Sym.Type&obj.SHIDDEN != 0) || r.Sym.Local) && r.Sym.Type == obj.STEXT && ld.DynlinkingGo() {
+				if o2&0xffc00000 != 0xf9400000 {
+					ld.Ctxt.Diag("R_ARM64_GOTPCREL against unexpected instruction %x", o2)
+				}
+				o2 = 0x91000000 | (o2 & 0x000003ff)
+				r.Type = obj.R_ADDRARM64
+			}
+			if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
+				*val = int64(o1)<<32 | int64(o2)
+			} else {
+				*val = int64(o2)<<32 | int64(o1)
+			}
+			fallthrough
+
 		case obj.R_ADDRARM64:
 			r.Done = 0
 
@@ -186,22 +283,26 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
 				rs = rs.Outer
 			}
 
-			if rs.Type != obj.SHOSTOBJ && rs.Sect == nil {
+			if rs.Type != obj.SHOSTOBJ && rs.Type != obj.SDYNIMPORT && rs.Sect == nil {
 				ld.Diag("missing section for %s", rs.Name)
 			}
 			r.Xsym = rs
 
-			// the first instruction is always at the lower address, this is endian neutral;
-			// but note that o0 and o1 should still use the target endian.
-			o0 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off : r.Off+4])
-			o1 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off+4 : r.Off+8])
-
 			// Note: ld64 currently has a bug that any non-zero addend for BR26 relocation
 			// will make the linking fail because it thinks the code is not PIC even though
 			// the BR26 relocation should be fully resolved at link time.
 			// That is the reason why the next if block is disabled. When the bug in ld64
 			// is fixed, we can enable this block and also enable duff's device in cmd/7g.
 			if false && ld.HEADTYPE == obj.Hdarwin {
+				var o0, o1 uint32
+
+				if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
+					o0 = uint32(*val >> 32)
+					o1 = uint32(*val)
+				} else {
+					o0 = uint32(*val)
+					o1 = uint32(*val >> 32)
+				}
 				// Mach-O wants the addend to be encoded in the instruction
 				// Note that although Mach-O supports ARM64_RELOC_ADDEND, it
 				// can only encode 24-bit of signed addend, but the instructions
@@ -210,23 +311,23 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
 				o0 |= (uint32((r.Xadd>>12)&3) << 29) | (uint32((r.Xadd>>12>>2)&0x7ffff) << 5)
 				o1 |= uint32(r.Xadd&0xfff) << 10
 				r.Xadd = 0
-			}
 
-			// when laid out, the instruction order must always be o1, o2.
-			if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
-				*val = int64(o0)<<32 | int64(o1)
-			} else {
-				*val = int64(o1)<<32 | int64(o0)
+				// when laid out, the instruction order must always be o1, o2.
+				if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
+					*val = int64(o0)<<32 | int64(o1)
+				} else {
+					*val = int64(o1)<<32 | int64(o0)
+				}
 			}
 
 			return 0
 
-		case obj.R_CALLARM64:
+		case obj.R_CALLARM64,
+			obj.R_ARM64_TLS_LE,
+			obj.R_ARM64_TLS_IE:
 			r.Done = 0
 			r.Xsym = r.Sym
-			*val = int64(0xfc000000 & uint32(r.Add))
-			r.Xadd = int64((uint32(r.Add) &^ 0xfc000000) * 4)
-			r.Add = 0
+			r.Xadd = r.Add
 			return 0
 		}
 	}
@@ -246,10 +347,15 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
 			ld.Diag("program too large, address relocation distance = %d", t)
 		}
 
-		// the first instruction is always at the lower address, this is endian neutral;
-		// but note that o0 and o1 should still use the target endian.
-		o0 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off : r.Off+4])
-		o1 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off+4 : r.Off+8])
+		var o0, o1 uint32
+
+		if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
+			o0 = uint32(*val >> 32)
+			o1 = uint32(*val)
+		} else {
+			o0 = uint32(*val)
+			o1 = uint32(*val >> 32)
+		}
 
 		o0 |= (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5)
 		o1 |= uint32(t&0xfff) << 10
@@ -262,8 +368,26 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
 		}
 		return 0
 
+	case obj.R_ARM64_TLS_LE:
+		r.Done = 0
+		if ld.HEADTYPE != obj.Hlinux {
+			ld.Diag("TLS reloc on unsupported OS %s", ld.Headstr(int(ld.HEADTYPE)))
+		}
+		// The TCB is two pointers. This is not documented anywhere, but is
+		// de facto part of the ABI.
+		v := r.Sym.Value + int64(2*ld.Thearch.Ptrsize)
+		if v < 0 || v >= 32678 {
+			ld.Diag("TLS offset out of range %d", v)
+		}
+		*val |= v << 5
+		return 0
+
 	case obj.R_CALLARM64:
-		*val = int64((0xfc000000 & uint32(r.Add)) | uint32((ld.Symaddr(r.Sym)+r.Add*4-(s.Value+int64(r.Off)))/4))
+		t := (ld.Symaddr(r.Sym) + r.Add) - (s.Value + int64(r.Off))
+		if t >= 1<<27 || t < -1<<27 {
+			ld.Diag("program too large, call relocation distance = %d", t)
+		}
+		*val |= (t >> 2) & 0x03ffffff
 		return 0
 	}
 
diff --git a/src/cmd/link/internal/arm64/l.go b/src/cmd/link/internal/arm64/l.go
index 8d0d57e..62703d2 100644
--- a/src/cmd/link/internal/arm64/l.go
+++ b/src/cmd/link/internal/arm64/l.go
@@ -63,9 +63,6 @@ package arm64
 
 const (
 	thechar   = '7'
-	PtrSize   = 8
-	IntSize   = 8
-	RegSize   = 8
 	MaxAlign  = 32 // max data alignment
 	FuncAlign = 8
 	MINLC     = 4
diff --git a/src/cmd/link/internal/arm64/obj.go b/src/cmd/link/internal/arm64/obj.go
index 56f5815..ae121c2 100644
--- a/src/cmd/link/internal/arm64/obj.go
+++ b/src/cmd/link/internal/arm64/obj.go
@@ -104,6 +104,10 @@ func archinit() {
 		break
 	}
 
+	if ld.Buildmode == ld.BuildmodeCShared || ld.DynlinkingGo() {
+		ld.Linkmode = ld.LinkExternal
+	}
+
 	switch ld.HEADTYPE {
 	default:
 		ld.Exitf("unknown -H option: %v", ld.HEADTYPE)
diff --git a/src/cmd/link/internal/ld/ar.go b/src/cmd/link/internal/ld/ar.go
index 0e59016..bd14a43 100644
--- a/src/cmd/link/internal/ld/ar.go
+++ b/src/cmd/link/internal/ld/ar.go
@@ -30,15 +30,20 @@
 
 package ld
 
+import (
+	"cmd/internal/obj"
+	"encoding/binary"
+	"fmt"
+	"os"
+)
+
 const (
 	SARMAG  = 8
-	SARNAME = 16
 	SAR_HDR = 16 + 44
 )
 
 const (
-	ARMAG  = "!<arch>\n"
-	ARFMAG = "`\n"
+	ARMAG = "!<arch>\n"
 )
 
 type ArHdr struct {
@@ -50,3 +55,131 @@ type ArHdr struct {
 	size string
 	fmag string
 }
+
+// hostArchive reads an archive file holding host objects and links in
+// required objects.  The general format is the same as a Go archive
+// file, but it has an armap listing symbols and the objects that
+// define them.  This is used for the compiler support library
+// libgcc.a.
+func hostArchive(name string) {
+	f, err := obj.Bopenr(name)
+	if err != nil {
+		if os.IsNotExist(err) {
+			// It's OK if we don't have a libgcc file at all.
+			if Debug['v'] != 0 {
+				fmt.Fprintf(&Bso, "skipping libgcc file: %v\n", err)
+			}
+			return
+		}
+		Exitf("cannot open file %s: %v", name, err)
+	}
+	defer obj.Bterm(f)
+
+	magbuf := make([]byte, len(ARMAG))
+	if obj.Bread(f, magbuf) != len(magbuf) {
+		Exitf("file %s too short", name)
+	}
+
+	var arhdr ArHdr
+	l := nextar(f, obj.Boffset(f), &arhdr)
+	if l <= 0 {
+		Exitf("%s missing armap", name)
+	}
+
+	var armap archiveMap
+	if arhdr.name == "/" || arhdr.name == "/SYM64/" {
+		armap = readArmap(name, f, arhdr)
+	} else {
+		Exitf("%s missing armap", name)
+	}
+
+	loaded := make(map[uint64]bool)
+	any := true
+	for any {
+		var load []uint64
+		for s := Ctxt.Allsym; s != nil; s = s.Allsym {
+			for _, r := range s.R {
+				if r.Sym != nil && r.Sym.Type&obj.SMASK == obj.SXREF {
+					if off := armap[r.Sym.Name]; off != 0 && !loaded[off] {
+						load = append(load, off)
+						loaded[off] = true
+					}
+				}
+			}
+		}
+
+		for _, off := range load {
+			l := nextar(f, int64(off), &arhdr)
+			if l <= 0 {
+				Exitf("%s missing archive entry at offset %d", name, off)
+			}
+			pname := fmt.Sprintf("%s(%s)", name, arhdr.name)
+			l = atolwhex(arhdr.size)
+
+			h := ldobj(f, "libgcc", l, pname, name, ArchiveObj)
+			obj.Bseek(f, h.off, 0)
+			h.ld(f, h.pkg, h.length, h.pn)
+		}
+
+		any = len(load) > 0
+	}
+}
+
+// archiveMap is an archive symbol map: a mapping from symbol name to
+// offset within the archive file.
+type archiveMap map[string]uint64
+
+// readArmap reads the archive symbol map.
+func readArmap(filename string, f *obj.Biobuf, arhdr ArHdr) archiveMap {
+	is64 := arhdr.name == "/SYM64/"
+	wordSize := 4
+	if is64 {
+		wordSize = 8
+	}
+
+	l := atolwhex(arhdr.size)
+	contents := make([]byte, l)
+	if obj.Bread(f, contents) != int(l) {
+		Exitf("short read from %s", filename)
+	}
+
+	var c uint64
+	if is64 {
+		c = binary.BigEndian.Uint64(contents)
+	} else {
+		c = uint64(binary.BigEndian.Uint32(contents))
+	}
+	contents = contents[wordSize:]
+
+	ret := make(archiveMap)
+
+	names := contents[c*uint64(wordSize):]
+	for i := uint64(0); i < c; i++ {
+		n := 0
+		for names[n] != 0 {
+			n++
+		}
+		name := string(names[:n])
+		names = names[n+1:]
+
+		// For Mach-O and PE/386 files we strip a leading
+		// underscore from the symbol name.
+		if goos == "darwin" || (goos == "windows" && goarch == "386") {
+			if name[0] == '_' && len(name) > 1 {
+				name = name[1:]
+			}
+		}
+
+		var off uint64
+		if is64 {
+			off = binary.BigEndian.Uint64(contents)
+		} else {
+			off = uint64(binary.BigEndian.Uint32(contents))
+		}
+		contents = contents[wordSize:]
+
+		ret[name] = off
+	}
+
+	return ret
+}
diff --git a/src/cmd/link/internal/ld/arch.go b/src/cmd/link/internal/ld/arch.go
index 1b8e1b1..2fcfd63 100644
--- a/src/cmd/link/internal/ld/arch.go
+++ b/src/cmd/link/internal/ld/arch.go
@@ -68,3 +68,21 @@ var Linkppc64le = LinkArch{
 	Ptrsize:   8,
 	Regsize:   8,
 }
+
+var Linkmips64 = LinkArch{
+	ByteOrder: binary.BigEndian,
+	Name:      "mips64",
+	Thechar:   '0',
+	Minlc:     4,
+	Ptrsize:   8,
+	Regsize:   8,
+}
+
+var Linkmips64le = LinkArch{
+	ByteOrder: binary.LittleEndian,
+	Name:      "mips64le",
+	Thechar:   '0',
+	Minlc:     4,
+	Ptrsize:   8,
+	Regsize:   8,
+}
diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go
index 55b12e5..ca8eabb 100644
--- a/src/cmd/link/internal/ld/data.go
+++ b/src/cmd/link/internal/ld/data.go
@@ -356,34 +356,50 @@ func relocsym(s *LSym) {
 		// We need to be able to reference dynimport symbols when linking against
 		// shared libraries, and Solaris needs it always
 		if HEADTYPE != obj.Hsolaris && r.Sym != nil && r.Sym.Type == obj.SDYNIMPORT && !DynlinkingGo() {
-			Diag("unhandled relocation for %s (type %d rtype %d)", r.Sym.Name, r.Sym.Type, r.Type)
+			if !(Thearch.Thechar == '9' && Linkmode == LinkExternal && r.Sym.Name == ".TOC.") {
+				Diag("unhandled relocation for %s (type %d rtype %d)", r.Sym.Name, r.Sym.Type, r.Type)
+			}
 		}
 		if r.Sym != nil && r.Sym.Type != obj.STLSBSS && !r.Sym.Reachable {
 			Diag("unreachable sym in relocation: %s %s", s.Name, r.Sym.Name)
 		}
 
-		// Android emulates runtime.tlsg as a regular variable.
-		if r.Type == obj.R_TLS && goos == "android" {
-			r.Type = obj.R_ADDR
-		}
-
 		switch r.Type {
 		default:
-			o = 0
+			switch siz {
+			default:
+				Diag("bad reloc size %#x for %s", uint32(siz), r.Sym.Name)
+			case 1:
+				o = int64(s.P[off])
+			case 2:
+				o = int64(Ctxt.Arch.ByteOrder.Uint16(s.P[off:]))
+			case 4:
+				o = int64(Ctxt.Arch.ByteOrder.Uint32(s.P[off:]))
+			case 8:
+				o = int64(Ctxt.Arch.ByteOrder.Uint64(s.P[off:]))
+			}
 			if Thearch.Archreloc(r, s, &o) < 0 {
 				Diag("unknown reloc %d", r.Type)
 			}
 
-		case obj.R_TLS:
-			if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd {
+		case obj.R_TLS_LE:
+			isAndroidX86 := goos == "android" && (Thearch.Thechar == '6' || Thearch.Thechar == '8')
+
+			if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd && !isAndroidX86 {
 				r.Done = 0
-				r.Sym = Ctxt.Tlsg
-				r.Xsym = Ctxt.Tlsg
+				if r.Sym == nil {
+					r.Sym = Ctxt.Tlsg
+				}
+				r.Xsym = r.Sym
 				r.Xadd = r.Add
-				o = r.Add
+				o = 0
+				if Thearch.Thechar != '6' {
+					o = r.Add
+				}
 				break
 			}
-			if Linkmode == LinkInternal && Iself && Thearch.Thechar == '5' {
+
+			if Iself && Thearch.Thechar == '5' {
 				// On ELF ARM, the thread pointer is 8 bytes before
 				// the start of the thread-local data block, so add 8
 				// to the actual TLS offset (r->sym->value).
@@ -392,30 +408,7 @@ func relocsym(s *LSym) {
 				// related to the fact that our own TLS storage happens
 				// to take up 8 bytes.
 				o = 8 + r.Sym.Value
-
-				break
-			}
-
-			r.Done = 0
-			o = 0
-			if Thearch.Thechar != '6' {
-				o = r.Add
-			}
-
-		case obj.R_TLS_LE:
-			if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd {
-				r.Done = 0
-				r.Sym = Ctxt.Tlsg
-				r.Xsym = Ctxt.Tlsg
-				r.Xadd = r.Add
-				o = 0
-				if Thearch.Thechar != '6' {
-					o = r.Add
-				}
-				break
-			}
-
-			if Iself || Ctxt.Headtype == obj.Hplan9 || Ctxt.Headtype == obj.Hdarwin {
+			} else if Iself || Ctxt.Headtype == obj.Hplan9 || Ctxt.Headtype == obj.Hdarwin || isAndroidX86 {
 				o = int64(Ctxt.Tlsoffset) + r.Add
 			} else if Ctxt.Headtype == obj.Hwindows {
 				o = r.Add
@@ -424,10 +417,14 @@ func relocsym(s *LSym) {
 			}
 
 		case obj.R_TLS_IE:
-			if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd {
+			isAndroidX86 := goos == "android" && (Thearch.Thechar == '6' || Thearch.Thechar == '8')
+
+			if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd && !isAndroidX86 {
 				r.Done = 0
-				r.Sym = Ctxt.Tlsg
-				r.Xsym = Ctxt.Tlsg
+				if r.Sym == nil {
+					r.Sym = Ctxt.Tlsg
+				}
+				r.Xsym = r.Sym
 				r.Xadd = r.Add
 				o = 0
 				if Thearch.Thechar != '6' {
@@ -1196,6 +1193,31 @@ func dodata() {
 
 	*l = nil
 
+	if UseRelro() {
+		// "read only" data with relocations needs to go in its own section
+		// when building a shared library. We do this by boosting objects of
+		// type SXXX with relocations to type SXXXRELRO.
+		for s := datap; s != nil; s = s.Next {
+			if (s.Type >= obj.STYPE && s.Type <= obj.SFUNCTAB && len(s.R) > 0) || s.Type == obj.SGOSTRING {
+				s.Type += (obj.STYPERELRO - obj.STYPE)
+				if s.Outer != nil {
+					s.Outer.Type = s.Type
+				}
+			}
+		}
+		// Check that we haven't made two symbols with the same .Outer into
+		// different types (because references two symbols with non-nil Outer
+		// become references to the outer symbol + offset it's vital that the
+		// symbol and the outer end up in the same section).
+		for s := datap; s != nil; s = s.Next {
+			if s.Outer != nil && s.Outer.Type != s.Type {
+				Diag("inconsistent types for %s and its Outer %s (%d != %d)",
+					s.Name, s.Outer.Name, s.Type, s.Outer.Type)
+			}
+		}
+
+	}
+
 	datap = listsort(datap, datcmp, listnextp)
 
 	if Iself {
@@ -1390,26 +1412,25 @@ func dodata() {
 		Diag("data or bss segment too large")
 	}
 
-	if Iself && Linkmode == LinkExternal && s != nil && s.Type == obj.STLSBSS && HEADTYPE != obj.Hopenbsd {
-		sect := addsection(&Segdata, ".tbss", 06)
-		sect.Align = int32(Thearch.Ptrsize)
-		sect.Vaddr = 0
+	if s != nil && s.Type == obj.STLSBSS {
+		if Iself && (Linkmode == LinkExternal || Debug['d'] == 0) && HEADTYPE != obj.Hopenbsd {
+			sect = addsection(&Segdata, ".tbss", 06)
+			sect.Align = int32(Thearch.Ptrsize)
+			sect.Vaddr = 0
+		} else {
+			sect = nil
+		}
 		datsize = 0
+
 		for ; s != nil && s.Type == obj.STLSBSS; s = s.Next {
 			datsize = aligndatsize(datsize, s)
 			s.Sect = sect
-			s.Value = int64(uint64(datsize) - sect.Vaddr)
+			s.Value = datsize
 			growdatsize(&datsize, s)
 		}
 
-		sect.Length = uint64(datsize)
-	} else {
-		// Might be internal linking but still using cgo.
-		// In that case, the only possible STLSBSS symbol is runtime.tlsg.
-		// Give it offset 0, because it's the only thing here.
-		if s != nil && s.Type == obj.STLSBSS && s.Name == "runtime.tlsg" {
-			s.Value = 0
-			s = s.Next
+		if sect != nil {
+			sect.Length = uint64(datsize)
 		}
 	}
 
@@ -1455,12 +1476,12 @@ func dodata() {
 	/* read-only data */
 	sect = addsection(segro, ".rodata", 04)
 
-	sect.Align = maxalign(s, obj.STYPELINK-1)
+	sect.Align = maxalign(s, obj.STYPERELRO-1)
 	datsize = Rnd(datsize, int64(sect.Align))
 	sect.Vaddr = 0
 	Linklookup(Ctxt, "runtime.rodata", 0).Sect = sect
 	Linklookup(Ctxt, "runtime.erodata", 0).Sect = sect
-	for ; s != nil && s.Type < obj.STYPELINK; s = s.Next {
+	for ; s != nil && s.Type < obj.STYPERELRO; s = s.Next {
 		datsize = aligndatsize(datsize, s)
 		s.Sect = sect
 		s.Type = obj.SRODATA
@@ -1470,8 +1491,45 @@ func dodata() {
 
 	sect.Length = uint64(datsize) - sect.Vaddr
 
+	// There is some data that are conceptually read-only but are written to by
+	// relocations. On GNU systems, we can arrange for the dynamic linker to
+	// mprotect sections after relocations are applied by giving them write
+	// permissions in the object file and calling them ".data.rel.ro.FOO". We
+	// divide the .rodata section between actual .rodata and .data.rel.ro.rodata,
+	// but for the other sections that this applies to, we just write a read-only
+	// .FOO section or a read-write .data.rel.ro.FOO section depending on the
+	// situation.
+	// TODO(mwhudson): It would make sense to do this more widely, but it makes
+	// the system linker segfault on darwin.
+	relro_perms := 04
+	relro_prefix := ""
+
+	if UseRelro() {
+		relro_perms = 06
+		relro_prefix = ".data.rel.ro"
+		/* data only written by relocations */
+		sect = addsection(segro, ".data.rel.ro", 06)
+
+		sect.Align = maxalign(s, obj.STYPELINK-1)
+		datsize = Rnd(datsize, int64(sect.Align))
+		sect.Vaddr = 0
+		for ; s != nil && s.Type < obj.STYPELINK; s = s.Next {
+			datsize = aligndatsize(datsize, s)
+			if s.Outer != nil && s.Outer.Sect != nil && s.Outer.Sect != sect {
+				Diag("s.Outer (%s) in different section from s (%s)", s.Outer.Name, s.Name)
+			}
+			s.Sect = sect
+			s.Type = obj.SRODATA
+			s.Value = int64(uint64(datsize) - sect.Vaddr)
+			growdatsize(&datsize, s)
+		}
+
+		sect.Length = uint64(datsize) - sect.Vaddr
+
+	}
+
 	/* typelink */
-	sect = addsection(segro, ".typelink", 04)
+	sect = addsection(segro, relro_prefix+".typelink", relro_perms)
 
 	sect.Align = maxalign(s, obj.STYPELINK)
 	datsize = Rnd(datsize, int64(sect.Align))
@@ -1489,7 +1547,7 @@ func dodata() {
 	sect.Length = uint64(datsize) - sect.Vaddr
 
 	/* gosymtab */
-	sect = addsection(segro, ".gosymtab", 04)
+	sect = addsection(segro, relro_prefix+".gosymtab", relro_perms)
 
 	sect.Align = maxalign(s, obj.SPCLNTAB-1)
 	datsize = Rnd(datsize, int64(sect.Align))
@@ -1507,7 +1565,7 @@ func dodata() {
 	sect.Length = uint64(datsize) - sect.Vaddr
 
 	/* gopclntab */
-	sect = addsection(segro, ".gopclntab", 04)
+	sect = addsection(segro, relro_prefix+".gopclntab", relro_perms)
 
 	sect.Align = maxalign(s, obj.SELFROSECT-1)
 	datsize = Rnd(datsize, int64(sect.Align))
@@ -1679,8 +1737,11 @@ func address() {
 	var noptrbss *Section
 	var vlen int64
 	for s := Segdata.Sect; s != nil; s = s.Next {
+		if Iself && s.Name == ".tbss" {
+			continue
+		}
 		vlen = int64(s.Length)
-		if s.Next != nil {
+		if s.Next != nil && !(Iself && s.Next.Name == ".tbss") {
 			vlen = int64(s.Next.Vaddr - s.Vaddr)
 		}
 		s.Vaddr = va
@@ -1710,6 +1771,11 @@ func address() {
 		rodata = text.Next
 	}
 	typelink := rodata.Next
+	if UseRelro() {
+		// There is another section (.data.rel.ro) when building a shared
+		// object on elf systems.
+		typelink = typelink.Next
+	}
 	symtab := typelink.Next
 	pclntab := symtab.Next
 
diff --git a/src/cmd/link/internal/ld/decodesym.go b/src/cmd/link/internal/ld/decodesym.go
index c1cf4d7..52eb46b 100644
--- a/src/cmd/link/internal/ld/decodesym.go
+++ b/src/cmd/link/internal/ld/decodesym.go
@@ -47,7 +47,7 @@ func decode_inuxi(p []byte, sz int) uint64 {
 // commonsize returns the size of the common prefix for all type
 // structures (runtime._type).
 func commonsize() int {
-	return 8*Thearch.Ptrsize + 8
+	return 7*Thearch.Ptrsize + 8
 }
 
 // Type.commonType.kind
@@ -110,6 +110,14 @@ func decodetype_gcprog(s *LSym) []byte {
 }
 
 func decodetype_gcprog_shlib(s *LSym) uint64 {
+	if Thearch.Thechar == '7' {
+		for _, shlib := range Ctxt.Shlibs {
+			if shlib.Path == s.File {
+				return shlib.gcdata_addresses[s]
+			}
+		}
+		return 0
+	}
 	return decode_inuxi(s.P[2*int32(Thearch.Ptrsize)+8+1*int32(Thearch.Ptrsize):], Thearch.Ptrsize)
 }
 
diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go
index 41d820d..a96b37a 100644
--- a/src/cmd/link/internal/ld/dwarf.go
+++ b/src/cmd/link/internal/ld/dwarf.go
@@ -625,54 +625,40 @@ func walktypedef(die *DWDie) *DWDie {
 // Find child by AT_name using hashtable if available or linear scan
 // if not.
 func find(die *DWDie, name string) *DWDie {
-	var a *DWDie
-	var b *DWDie
-	var die2 *DWDie
-	var h int
-
-top:
-	if die.hash == nil {
-		for a = die.child; a != nil; a = a.link {
-			if name == getattr(a, DW_AT_name).data {
-				return a
+	var prev *DWDie
+	for ; die != prev; prev, die = die, walktypedef(die) {
+
+		if die.hash == nil {
+			for a := die.child; a != nil; a = a.link {
+				if name == getattr(a, DW_AT_name).data {
+					return a
+				}
 			}
+			continue
 		}
-		goto notfound
-	}
-
-	h = int(dwarfhashstr(name))
-	a = die.hash[h]
-
-	if a == nil {
-		goto notfound
-	}
-
-	if name == getattr(a, DW_AT_name).data {
-		return a
-	}
 
-	// Move found ones to head of the list.
-	b = a.hlink
+		h := int(dwarfhashstr(name))
+		a := die.hash[h]
 
-	for b != nil {
-		if name == getattr(b, DW_AT_name).data {
-			a.hlink = b.hlink
-			b.hlink = die.hash[h]
-			die.hash[h] = b
-			return b
+		if a == nil {
+			continue
 		}
 
-		a = b
-		b = b.hlink
-	}
+		if name == getattr(a, DW_AT_name).data {
+			return a
+		}
 
-notfound:
-	die2 = walktypedef(die)
-	if die2 != die {
-		die = die2
-		goto top
+		// Move found ones to head of the list.
+		for b := a.hlink; b != nil; b = b.hlink {
+			if name == getattr(b, DW_AT_name).data {
+				a.hlink = b.hlink
+				b.hlink = die.hash[h]
+				die.hash[h] = b
+				return b
+			}
+			a = b
+		}
 	}
-
 	return nil
 }
 
@@ -1149,15 +1135,12 @@ func defptrto(dwtype *DWDie) *DWDie {
 // DWAttr.data is copied as pointer only.  If except is one of
 // the top-level children, it will not be copied.
 func copychildrenexcept(dst *DWDie, src *DWDie, except *DWDie) {
-	var c *DWDie
-	var a *DWAttr
-
 	for src = src.child; src != nil; src = src.link {
 		if src == except {
 			continue
 		}
-		c = newdie(dst, src.abbrev, getattr(src, DW_AT_name).data.(string))
-		for a = src.attr; a != nil; a = a.link {
+		c := newdie(dst, src.abbrev, getattr(src, DW_AT_name).data.(string))
+		for a := src.attr; a != nil; a = a.link {
 			newattr(c, a.atr, int(a.cls), a.value, a.data)
 		}
 		copychildrenexcept(c, src, nil)
@@ -1187,7 +1170,7 @@ func substitutetype(structdie *DWDie, field string, dwtype *DWDie) {
 }
 
 func synthesizestringtypes(die *DWDie) {
-	prototype := walktypedef(defgotype(lookup_or_diag("type.runtime._string")))
+	prototype := walktypedef(defgotype(lookup_or_diag("type.runtime.stringStructDWARF")))
 	if prototype == nil {
 		return
 	}
@@ -1206,13 +1189,12 @@ func synthesizeslicetypes(die *DWDie) {
 		return
 	}
 
-	var elem *DWDie
 	for ; die != nil; die = die.link {
 		if die.abbrev != DW_ABRV_SLICETYPE {
 			continue
 		}
 		copychildren(die, prototype)
-		elem = getattr(die, DW_AT_go_elem).data.(*DWDie)
+		elem := getattr(die, DW_AT_go_elem).data.(*DWDie)
 		substitutetype(die, "array", defptrto(elem))
 	}
 }
@@ -1244,72 +1226,53 @@ func synthesizemaptypes(die *DWDie) {
 		return
 	}
 
-	var a *DWAttr
-	var dwh *DWDie
-	var dwhb *DWDie
-	var dwhk *DWDie
-	var dwhv *DWDie
-	var fld *DWDie
-	var indirect_key int
-	var indirect_val int
-	var keysize int
-	var keytype *DWDie
-	var t *DWDie
-	var valsize int
-	var valtype *DWDie
 	for ; die != nil; die = die.link {
 		if die.abbrev != DW_ABRV_MAPTYPE {
 			continue
 		}
 
-		keytype = walktypedef(getattr(die, DW_AT_go_key).data.(*DWDie))
-		valtype = walktypedef(getattr(die, DW_AT_go_elem).data.(*DWDie))
+		keytype := walktypedef(getattr(die, DW_AT_go_key).data.(*DWDie))
+		valtype := walktypedef(getattr(die, DW_AT_go_elem).data.(*DWDie))
 
 		// compute size info like hashmap.c does.
-		a = getattr(keytype, DW_AT_byte_size)
-
+		keysize, valsize := Thearch.Ptrsize, Thearch.Ptrsize
+		a := getattr(keytype, DW_AT_byte_size)
 		if a != nil {
 			keysize = int(a.value)
-		} else {
-			keysize = Thearch.Ptrsize
 		}
 		a = getattr(valtype, DW_AT_byte_size)
 		if a != nil {
 			valsize = int(a.value)
-		} else {
-			valsize = Thearch.Ptrsize
 		}
-		indirect_key = 0
-		indirect_val = 0
+		indirect_key, indirect_val := false, false
 		if keysize > MaxKeySize {
 			keysize = Thearch.Ptrsize
-			indirect_key = 1
+			indirect_key = true
 		}
-
 		if valsize > MaxValSize {
 			valsize = Thearch.Ptrsize
-			indirect_val = 1
+			indirect_val = true
 		}
 
 		// Construct type to represent an array of BucketSize keys
-		dwhk = newdie(&dwtypes, DW_ABRV_ARRAYTYPE, mkinternaltypename("[]key", getattr(keytype, DW_AT_name).data.(string), ""))
+		dwhk := newdie(&dwtypes, DW_ABRV_ARRAYTYPE, mkinternaltypename("[]key", getattr(keytype, DW_AT_name).data.(string), ""))
 
 		newattr(dwhk, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize*int64(keysize), 0)
-		t = keytype
-		if indirect_key != 0 {
+		t := keytype
+		if indirect_key {
 			t = defptrto(keytype)
 		}
 		newrefattr(dwhk, DW_AT_type, t)
-		fld = newdie(dwhk, DW_ABRV_ARRAYRANGE, "size")
+		fld := newdie(dwhk, DW_ABRV_ARRAYRANGE, "size")
 		newattr(fld, DW_AT_count, DW_CLS_CONSTANT, BucketSize, 0)
 		newrefattr(fld, DW_AT_type, mustFind(&dwtypes, "uintptr"))
 
 		// Construct type to represent an array of BucketSize values
-		dwhv = newdie(&dwtypes, DW_ABRV_ARRAYTYPE, mkinternaltypename("[]val", getattr(valtype, DW_AT_name).data.(string), ""))
+		dwhv := newdie(&dwtypes, DW_ABRV_ARRAYTYPE, mkinternaltypename("[]val", getattr(valtype, DW_AT_name).data.(string), ""))
 
 		newattr(dwhv, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize*int64(valsize), 0)
 		t = valtype
-		if indirect_val != 0 {
+		if indirect_val {
 			t = defptrto(valtype)
 		}
 		newrefattr(dwhv, DW_AT_type, t)
@@ -1318,7 +1281,7 @@ func synthesizemaptypes(die *DWDie) {
 		newrefattr(fld, DW_AT_type, mustFind(&dwtypes, "uintptr"))
 
 		// Construct bucket<K,V>
-		dwhb = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, mkinternaltypename("bucket", getattr(keytype, DW_AT_name).data.(string), getattr(valtype, DW_AT_name).data.(string)))
+		dwhb := newdie(&dwtypes, DW_ABRV_STRUCTTYPE, mkinternaltypename("bucket", getattr(keytype, DW_AT_name).data.(string), getattr(valtype, DW_AT_name).data.(string)))
 
 		// Copy over all fields except the field "data" from the generic bucket.
 		// "data" will be replaced with keys/values below.
@@ -1342,7 +1305,7 @@ func synthesizemaptypes(die *DWDie) {
 		newattr(dwhb, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize+BucketSize*int64(keysize)+BucketSize*int64(valsize)+int64(Thearch.Regsize), 0)
 
 		// Construct hash<K,V>
-		dwh = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, mkinternaltypename("hash", getattr(keytype, DW_AT_name).data.(string), getattr(valtype, DW_AT_name).data.(string)))
+		dwh := newdie(&dwtypes, DW_ABRV_STRUCTTYPE, mkinternaltypename("hash", getattr(keytype, DW_AT_name).data.(string), getattr(valtype, DW_AT_name).data.(string)))
 
 		copychildren(dwh, hash)
 		substitutetype(dwh, "buckets", defptrto(dwhb))
@@ -1364,26 +1327,19 @@ func synthesizechantypes(die *DWDie) {
 
 	sudogsize := int(getattr(sudog, DW_AT_byte_size).value)
 
-	var a *DWAttr
-	var dwh *DWDie
-	var dws *DWDie
-	var dww *DWDie
-	var elemsize int
-	var elemtype *DWDie
 	for ; die != nil; die = die.link {
 		if die.abbrev != DW_ABRV_CHANTYPE {
 			continue
 		}
-		elemtype = getattr(die, DW_AT_go_elem).data.(*DWDie)
-		a = getattr(elemtype, DW_AT_byte_size)
+		elemsize := Thearch.Ptrsize
+		elemtype := getattr(die, DW_AT_go_elem).data.(*DWDie)
+		a := getattr(elemtype, DW_AT_byte_size)
 		if a != nil {
 			elemsize = int(a.value)
-		} else {
-			elemsize = Thearch.Ptrsize
 		}
 
 		// sudog<T>
-		dws = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, mkinternaltypename("sudog", getattr(elemtype, DW_AT_name).data.(string), ""))
+		dws := newdie(&dwtypes, DW_ABRV_STRUCTTYPE, mkinternaltypename("sudog", getattr(elemtype, DW_AT_name).data.(string), ""))
 
 		copychildren(dws, sudog)
 		substitutetype(dws, "elem", elemtype)
@@ -1395,7 +1351,7 @@ func synthesizechantypes(die *DWDie) {
 		newattr(dws, DW_AT_byte_size, DW_CLS_CONSTANT, int64(sudogsize)+int64(elemsize), nil)
 
 		// waitq<T>
-		dww = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, mkinternaltypename("waitq", getattr(elemtype, DW_AT_name).data.(string), ""))
+		dww := newdie(&dwtypes, DW_ABRV_STRUCTTYPE, mkinternaltypename("waitq", getattr(elemtype, DW_AT_name).data.(string), ""))
 
 		copychildren(dww, waitq)
 		substitutetype(dww, "first", defptrto(dws))
@@ -1403,7 +1359,7 @@ func synthesizechantypes(die *DWDie) {
 		newattr(dww, DW_AT_byte_size, DW_CLS_CONSTANT, getattr(waitq, DW_AT_byte_size).value, nil)
 
 		// hchan<T>
-		dwh = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, mkinternaltypename("hchan", getattr(elemtype, DW_AT_name).data.(string), ""))
+		dwh := newdie(&dwtypes, DW_ABRV_STRUCTTYPE, mkinternaltypename("hchan", getattr(elemtype, DW_AT_name).data.(string), ""))
 
 		copychildren(dwh, hchan)
 		substitutetype(dwh, "recvq", dww)
@@ -1466,11 +1422,8 @@ func finddebugruntimepath(s *LSym) {
 		return
 	}
 
-	var f *LSym
-	var p string
 	for i := 0; i < s.Pcln.Nfile; i++ {
-		f = s.Pcln.File[i]
-		_ = p
+		f := s.Pcln.File[i]
 		if i := strings.Index(f.Name, "runtime/runtime.go"); i >= 0 {
 			gdbscript = f.Name[:i] + "runtime/runtime-gdb.py"
 			break
@@ -1574,7 +1527,6 @@ func writelines() {
 	var epcs *LSym
 	lineo = Cpos()
 	var dwinfo *DWDie
-
 	flushunit(dwinfo, epc, epcs, unitstart, int32(headerend-unitstart-10))
 	unitstart = Cpos()
 
@@ -1641,22 +1593,12 @@ func writelines() {
 		addrput(pc)
 	}
 
-	var a *Auto
-	var da int
-	var dt int
-	var dwfunc *DWDie
-	var dws **DWDie
-	var dwvar *DWDie
-	var n string
-	var nn string
-	var offs int64
 	var pcfile Pciter
 	var pcline Pciter
-	var varhash [HASHSIZE]*DWDie
 	for Ctxt.Cursym = Ctxt.Textp; Ctxt.Cursym != nil; Ctxt.Cursym = Ctxt.Cursym.Next {
 		s = Ctxt.Cursym
 
-		dwfunc = newdie(dwinfo, DW_ABRV_FUNCTION, s.Name)
+		dwfunc := newdie(dwinfo, DW_ABRV_FUNCTION, s.Name)
 		newattr(dwfunc, DW_AT_low_pc, DW_CLS_ADDRESS, s.Value, s)
 		epc = s.Value + s.Size
 		epcs = s
@@ -1703,10 +1645,14 @@ func writelines() {
 			epc += s.Value
 		}
 
-		da = 0
+		var (
+			dt      int
+			offs    int64
+			varhash [HASHSIZE]*DWDie
+		)
+		da := 0
 		dwfunc.hash = varhash[:] // enable indexing of children by name
-		varhash = [HASHSIZE]*DWDie{}
-		for a = s.Autom; a != nil; a = a.Link {
+		for a := s.Autom; a != nil; a = a.Link {
 			switch a.Name {
 			case obj.A_AUTO:
 				dt = DW_ABRV_AUTO
@@ -1717,10 +1663,7 @@ func writelines() {
 
 			case obj.A_PARAM:
 				dt = DW_ABRV_PARAM
-				offs = int64(a.Aoffset)
-				if haslinkregister() {
-					offs += int64(Thearch.Ptrsize)
-				}
+				offs = int64(a.Aoffset) + Ctxt.FixedFrameSize()
 
 			default:
 				continue
@@ -1729,6 +1672,7 @@ func writelines() {
 			if strings.Contains(a.Asym.Name, ".autotmp_") {
 				continue
 			}
+			var n string
 			if find(dwfunc, a.Asym.Name) != nil {
 				n = mkvarname(a.Asym.Name, da)
 			} else {
@@ -1736,12 +1680,11 @@ func writelines() {
 			}
 
 			// Drop the package prefix from locals and arguments.
-			_ = nn
 			if i := strings.LastIndex(n, "."); i >= 0 {
 				n = n[i+1:]
 			}
 
-			dwvar = newdie(dwfunc, dt, n)
+			dwvar := newdie(dwfunc, dt, n)
 			newcfaoffsetattr(dwvar, int32(offs))
 			newrefattr(dwvar, DW_AT_type, defgotype(a.Gotype))
 
@@ -1749,7 +1692,8 @@ func writelines() {
 			newattr(dwvar, DW_AT_internal_location, DW_CLS_CONSTANT, offs, nil)
 
 			dwfunc.child = dwvar.link // take dwvar out from the top of the list
-			for dws = &dwfunc.child; *dws != nil; dws = &(*dws).link {
+			dws := &dwfunc.child
+			for ; *dws != nil; dws = &(*dws).link {
 				if offs > getattr(*dws, DW_AT_internal_location).value {
 					break
 				}
@@ -1835,18 +1779,14 @@ func writeframes() {
 
 	strnput("", int(pad))
 
-	var fdeo int64
-	var fdesize int64
-	var nextpc uint32
 	var pcsp Pciter
-	var s *LSym
 	for Ctxt.Cursym = Ctxt.Textp; Ctxt.Cursym != nil; Ctxt.Cursym = Ctxt.Cursym.Next {
-		s = Ctxt.Cursym
+		s := Ctxt.Cursym
 		if s.Pcln == nil {
 			continue
 		}
 
-		fdeo = Cpos()
+		fdeo := Cpos()
 
 		// Emit a FDE, Section 6.4.1, starting wit a placeholder.
 		Thearch.Lput(0) // length, must be multiple of thearch.ptrsize
@@ -1855,7 +1795,7 @@ func writeframes() {
 		addrput(0)      // address range
 
 		for pciterinit(Ctxt, &pcsp, &s.Pcln.Pcsp); pcsp.done == 0; pciternext(&pcsp) {
-			nextpc = pcsp.nextpc
+			nextpc := pcsp.nextpc
 
 			// pciterinit goes up to the end of the function,
 			// but DWARF expects us to stop just before the end.
@@ -1873,7 +1813,7 @@ func writeframes() {
 			}
 		}
 
-		fdesize = Cpos() - fdeo - 4 // exclude the length field.
+		fdesize := Cpos() - fdeo - 4 // exclude the length field.
 		pad = Rnd(fdesize, int64(Thearch.Ptrsize)) - fdesize
 		strnput("", int(pad))
 		fdesize += pad
@@ -1917,10 +1857,8 @@ func writeinfo() {
 	}
 	arangessec.R = arangessec.R[:0]
 
-	var here int64
-	var unitstart int64
 	for compunit := dwroot.child; compunit != nil; compunit = compunit.link {
-		unitstart = Cpos()
+		unitstart := Cpos()
 
 		// Write .debug_info Compilation Unit Header (sec 7.5.1)
 		// Fields marked with (*) must be changed for 64-bit dwarf
@@ -1939,7 +1877,7 @@ func writeinfo() {
 
 		putdie(compunit)
 
-		here = Cpos()
+		here := Cpos()
 		Cseek(unitstart)
 		Thearch.Lput(uint32(here - unitstart - 4)) // exclude the length field.
 		Cseek(here)
@@ -1967,20 +1905,13 @@ func ispubtype(die *DWDie) bool {
 }
 
 func writepub(ispub func(*DWDie) bool) int64 {
-	var die *DWDie
-	var dwa *DWAttr
-	var unitstart int64
-	var unitend int64
-	var here int64
-
 	sectionstart := Cpos()
 
 	for compunit := dwroot.child; compunit != nil; compunit = compunit.link {
-		unitstart = compunit.offs - COMPUNITHEADERSIZE
+		unitend := infoo + infosize
+		unitstart := compunit.offs - COMPUNITHEADERSIZE
 		if compunit.link != nil {
 			unitend = compunit.link.offs - COMPUNITHEADERSIZE
-		} else {
-			unitend = infoo + infosize
 		}
 
 		// Write .debug_pubnames/types	Header (sec 6.1.1)
@@ -1989,18 +1920,18 @@ func writepub(ispub func(*DWDie) bool) int64 {
 		Thearch.Lput(uint32(unitstart))           // debug_info_offset (of the Comp unit Header)
 		Thearch.Lput(uint32(unitend - unitstart)) // debug_info_length
 
-		for die = compunit.child; die != nil; die = die.link {
+		for die := compunit.child; die != nil; die = die.link {
 			if !ispub(die) {
 				continue
 			}
 			Thearch.Lput(uint32(die.offs - unitstart))
-			dwa = getattr(die, DW_AT_name)
+			dwa := getattr(die, DW_AT_name)
 			strnput(dwa.data.(string), int(dwa.value+1))
 		}
 
 		Thearch.Lput(0)
 
-		here = Cpos()
+		here := Cpos()
 		Cseek(sectionstart)
 		Thearch.Lput(uint32(here - sectionstart - 4)) // exclude the length field.
 		Cseek(here)
@@ -2014,19 +1945,17 @@ func writepub(ispub func(*DWDie) bool) int64 {
  *  because we need die->offs of dw_globals.
  */
 func writearanges() int64 {
-	var b *DWAttr
-	var e *DWAttr
-	var value int64
-
 	sectionstart := Cpos()
-	headersize := int(Rnd(4+2+4+1+1, int64(Thearch.Ptrsize))) // don't count unit_length field itself
+	// The first tuple is aligned to a multiple of the size of a single tuple
+	// (twice the size of an address)
+	headersize := int(Rnd(4+2+4+1+1, int64(Thearch.Ptrsize*2))) // don't count unit_length field itself
 
 	for compunit := dwroot.child; compunit != nil; compunit = compunit.link {
-		b = getattr(compunit, DW_AT_low_pc)
+		b := getattr(compunit, DW_AT_low_pc)
 		if b == nil {
 			continue
 		}
-		e = getattr(compunit, DW_AT_high_pc)
+		e := getattr(compunit, DW_AT_high_pc)
 		if e == nil {
 			continue
 		}
@@ -2035,7 +1964,7 @@ func writearanges() int64 {
 		Thearch.Lput(uint32(headersize) + 4*uint32(Thearch.Ptrsize) - 4) // unit_length (*)
 		Thearch.Wput(2)                                                  // dwarf version (appendix F)
 
-		value = compunit.offs - COMPUNITHEADERSIZE // debug_info_offset
+		value := compunit.offs - COMPUNITHEADERSIZE // debug_info_offset
 		if Linkmode == LinkExternal {
 			adddwarfrel(arangessec, infosym, sectionstart, 4, value)
 		} else {
@@ -2080,18 +2009,14 @@ func align(size int64) {
 }
 
 func writedwarfreloc(s *LSym) int64 {
-	var i int
-	var r *Reloc
-
 	start := Cpos()
 	for ri := 0; ri < len(s.R); ri++ {
-		r = &s.R[ri]
+		r := &s.R[ri]
+		i := -1
 		if Iself {
 			i = Thearch.Elfreloc1(r, int64(r.Off))
 		} else if HEADTYPE == obj.Hdarwin {
 			i = Thearch.Machoreloc1(r, int64(r.Off))
-		} else {
-			i = -1
 		}
 		if i < 0 {
 			Diag("unsupported obj reloc %d/%d to %s", r.Type, r.Siz, r.Sym.Name)
@@ -2312,7 +2237,7 @@ func dwarfaddshstrings(shstrtab *LSym) {
 	elfstrdbg[ElfStrGDBScripts] = Addstring(shstrtab, ".debug_gdb_scripts")
 	if Linkmode == LinkExternal {
 		switch Thearch.Thechar {
-		case '6', '7', '9':
+		case '0', '6', '7', '9':
 			elfstrdbg[ElfStrRelDebugInfo] = Addstring(shstrtab, ".rela.debug_info")
 			elfstrdbg[ElfStrRelDebugAranges] = Addstring(shstrtab, ".rela.debug_aranges")
 			elfstrdbg[ElfStrRelDebugLine] = Addstring(shstrtab, ".rela.debug_line")
@@ -2365,7 +2290,7 @@ func dwarfaddelfsectionsyms() {
 func dwarfaddelfrelocheader(elfstr int, shdata *ElfShdr, off int64, size int64) {
 	sh := newElfShdr(elfstrdbg[elfstr])
 	switch Thearch.Thechar {
-	case '6', '7', '9':
+	case '0', '6', '7', '9':
 		sh.type_ = SHT_RELA
 	default:
 		sh.type_ = SHT_REL
diff --git a/src/cmd/link/internal/ld/elf.go b/src/cmd/link/internal/ld/elf.go
index 9dedb0e..6d34978 100644
--- a/src/cmd/link/internal/ld/elf.go
+++ b/src/cmd/link/internal/ld/elf.go
@@ -206,6 +206,7 @@ const (
 	SHT_GNU_VERNEED      = 0x6ffffffe
 	SHT_GNU_VERSYM       = 0x6fffffff
 	SHT_LOPROC           = 0x70000000
+	SHT_ARM_ATTRIBUTES   = 0x70000003
 	SHT_HIPROC           = 0x7fffffff
 	SHT_LOUSER           = 0x80000000
 	SHT_HIUSER           = 0xffffffff
@@ -324,301 +325,328 @@ const (
  * Relocation types.
  */
 const (
-	R_X86_64_NONE              = 0
-	R_X86_64_64                = 1
-	R_X86_64_PC32              = 2
-	R_X86_64_GOT32             = 3
-	R_X86_64_PLT32             = 4
-	R_X86_64_COPY              = 5
-	R_X86_64_GLOB_DAT          = 6
-	R_X86_64_JMP_SLOT          = 7
-	R_X86_64_RELATIVE          = 8
-	R_X86_64_GOTPCREL          = 9
-	R_X86_64_32                = 10
-	R_X86_64_32S               = 11
-	R_X86_64_16                = 12
-	R_X86_64_PC16              = 13
-	R_X86_64_8                 = 14
-	R_X86_64_PC8               = 15
-	R_X86_64_DTPMOD64          = 16
-	R_X86_64_DTPOFF64          = 17
-	R_X86_64_TPOFF64           = 18
-	R_X86_64_TLSGD             = 19
-	R_X86_64_TLSLD             = 20
-	R_X86_64_DTPOFF32          = 21
-	R_X86_64_GOTTPOFF          = 22
-	R_X86_64_TPOFF32           = 23
-	R_X86_64_PC64              = 24
-	R_X86_64_GOTOFF64          = 25
-	R_X86_64_GOTPC32           = 26
-	R_X86_64_GOT64             = 27
-	R_X86_64_GOTPCREL64        = 28
-	R_X86_64_GOTPC64           = 29
-	R_X86_64_GOTPLT64          = 30
-	R_X86_64_PLTOFF64          = 31
-	R_X86_64_SIZE32            = 32
-	R_X86_64_SIZE64            = 33
-	R_X86_64_GOTPC32_TLSDEC    = 34
-	R_X86_64_TLSDESC_CALL      = 35
-	R_X86_64_TLSDESC           = 36
-	R_X86_64_IRELATIVE         = 37
-	R_X86_64_PC32_BND          = 40
-	R_X86_64_GOTPCRELX         = 41
-	R_X86_64_REX_GOTPCRELX     = 42
-	R_AARCH64_ABS64            = 257
-	R_AARCH64_ABS32            = 258
-	R_AARCH64_CALL26           = 283
-	R_AARCH64_ADR_PREL_PG_HI21 = 275
-	R_AARCH64_ADD_ABS_LO12_NC  = 277
-	R_ALPHA_NONE               = 0
-	R_ALPHA_REFLONG            = 1
-	R_ALPHA_REFQUAD            = 2
-	R_ALPHA_GPREL32            = 3
-	R_ALPHA_LITERAL            = 4
-	R_ALPHA_LITUSE             = 5
-	R_ALPHA_GPDISP             = 6
-	R_ALPHA_BRADDR             = 7
-	R_ALPHA_HINT               = 8
-	R_ALPHA_SREL16             = 9
-	R_ALPHA_SREL32             = 10
-	R_ALPHA_SREL64             = 11
-	R_ALPHA_OP_PUSH            = 12
-	R_ALPHA_OP_STORE           = 13
-	R_ALPHA_OP_PSUB            = 14
-	R_ALPHA_OP_PRSHIFT         = 15
-	R_ALPHA_GPVALUE            = 16
-	R_ALPHA_GPRELHIGH          = 17
-	R_ALPHA_GPRELLOW           = 18
-	R_ALPHA_IMMED_GP_16        = 19
-	R_ALPHA_IMMED_GP_HI32      = 20
-	R_ALPHA_IMMED_SCN_HI32     = 21
-	R_ALPHA_IMMED_BR_HI32      = 22
-	R_ALPHA_IMMED_LO32         = 23
-	R_ALPHA_COPY               = 24
-	R_ALPHA_GLOB_DAT           = 25
-	R_ALPHA_JMP_SLOT           = 26
-	R_ALPHA_RELATIVE           = 27
-	R_ARM_NONE                 = 0
-	R_ARM_PC24                 = 1
-	R_ARM_ABS32                = 2
-	R_ARM_REL32                = 3
-	R_ARM_PC13                 = 4
-	R_ARM_ABS16                = 5
-	R_ARM_ABS12                = 6
-	R_ARM_THM_ABS5             = 7
-	R_ARM_ABS8                 = 8
-	R_ARM_SBREL32              = 9
-	R_ARM_THM_PC22             = 10
-	R_ARM_THM_PC8              = 11
-	R_ARM_AMP_VCALL9           = 12
-	R_ARM_SWI24                = 13
-	R_ARM_THM_SWI8             = 14
-	R_ARM_XPC25                = 15
-	R_ARM_THM_XPC22            = 16
-	R_ARM_COPY                 = 20
-	R_ARM_GLOB_DAT             = 21
-	R_ARM_JUMP_SLOT            = 22
-	R_ARM_RELATIVE             = 23
-	R_ARM_GOTOFF               = 24
-	R_ARM_GOTPC                = 25
-	R_ARM_GOT32                = 26
-	R_ARM_PLT32                = 27
-	R_ARM_CALL                 = 28
-	R_ARM_JUMP24               = 29
-	R_ARM_V4BX                 = 40
-	R_ARM_GOT_PREL             = 96
-	R_ARM_GNU_VTENTRY          = 100
-	R_ARM_GNU_VTINHERIT        = 101
-	R_ARM_TLS_IE32             = 107
-	R_ARM_TLS_LE32             = 108
-	R_ARM_RSBREL32             = 250
-	R_ARM_THM_RPC22            = 251
-	R_ARM_RREL32               = 252
-	R_ARM_RABS32               = 253
-	R_ARM_RPC24                = 254
-	R_ARM_RBASE                = 255
-	R_386_NONE                 = 0
-	R_386_32                   = 1
-	R_386_PC32                 = 2
-	R_386_GOT32                = 3
-	R_386_PLT32                = 4
-	R_386_COPY                 = 5
-	R_386_GLOB_DAT             = 6
-	R_386_JMP_SLOT             = 7
-	R_386_RELATIVE             = 8
-	R_386_GOTOFF               = 9
-	R_386_GOTPC                = 10
-	R_386_TLS_TPOFF            = 14
-	R_386_TLS_IE               = 15
-	R_386_TLS_GOTIE            = 16
-	R_386_TLS_LE               = 17
-	R_386_TLS_GD               = 18
-	R_386_TLS_LDM              = 19
-	R_386_TLS_GD_32            = 24
-	R_386_TLS_GD_PUSH          = 25
-	R_386_TLS_GD_CALL          = 26
-	R_386_TLS_GD_POP           = 27
-	R_386_TLS_LDM_32           = 28
-	R_386_TLS_LDM_PUSH         = 29
-	R_386_TLS_LDM_CALL         = 30
-	R_386_TLS_LDM_POP          = 31
-	R_386_TLS_LDO_32           = 32
-	R_386_TLS_IE_32            = 33
-	R_386_TLS_LE_32            = 34
-	R_386_TLS_DTPMOD32         = 35
-	R_386_TLS_DTPOFF32         = 36
-	R_386_TLS_TPOFF32          = 37
-	R_386_TLS_GOTDESC          = 39
-	R_386_TLS_DESC_CALL        = 40
-	R_386_TLS_DESC             = 41
-	R_386_IRELATIVE            = 42
-	R_386_GOT32X               = 43
-	R_PPC_NONE                 = 0
-	R_PPC_ADDR32               = 1
-	R_PPC_ADDR24               = 2
-	R_PPC_ADDR16               = 3
-	R_PPC_ADDR16_LO            = 4
-	R_PPC_ADDR16_HI            = 5
-	R_PPC_ADDR16_HA            = 6
-	R_PPC_ADDR14               = 7
-	R_PPC_ADDR14_BRTAKEN       = 8
-	R_PPC_ADDR14_BRNTAKEN      = 9
-	R_PPC_REL24                = 10
-	R_PPC_REL14                = 11
-	R_PPC_REL14_BRTAKEN        = 12
-	R_PPC_REL14_BRNTAKEN       = 13
-	R_PPC_GOT16                = 14
-	R_PPC_GOT16_LO             = 15
-	R_PPC_GOT16_HI             = 16
-	R_PPC_GOT16_HA             = 17
-	R_PPC_PLTREL24             = 18
-	R_PPC_COPY                 = 19
-	R_PPC_GLOB_DAT             = 20
-	R_PPC_JMP_SLOT             = 21
-	R_PPC_RELATIVE             = 22
-	R_PPC_LOCAL24PC            = 23
-	R_PPC_UADDR32              = 24
-	R_PPC_UADDR16              = 25
-	R_PPC_REL32                = 26
-	R_PPC_PLT32                = 27
-	R_PPC_PLTREL32             = 28
-	R_PPC_PLT16_LO             = 29
-	R_PPC_PLT16_HI             = 30
-	R_PPC_PLT16_HA             = 31
-	R_PPC_SDAREL16             = 32
-	R_PPC_SECTOFF              = 33
-	R_PPC_SECTOFF_LO           = 34
-	R_PPC_SECTOFF_HI           = 35
-	R_PPC_SECTOFF_HA           = 36
-	R_PPC_TLS                  = 67
-	R_PPC_DTPMOD32             = 68
-	R_PPC_TPREL16              = 69
-	R_PPC_TPREL16_LO           = 70
-	R_PPC_TPREL16_HI           = 71
-	R_PPC_TPREL16_HA           = 72
-	R_PPC_TPREL32              = 73
-	R_PPC_DTPREL16             = 74
-	R_PPC_DTPREL16_LO          = 75
-	R_PPC_DTPREL16_HI          = 76
-	R_PPC_DTPREL16_HA          = 77
-	R_PPC_DTPREL32             = 78
-	R_PPC_GOT_TLSGD16          = 79
-	R_PPC_GOT_TLSGD16_LO       = 80
-	R_PPC_GOT_TLSGD16_HI       = 81
-	R_PPC_GOT_TLSGD16_HA       = 82
-	R_PPC_GOT_TLSLD16          = 83
-	R_PPC_GOT_TLSLD16_LO       = 84
-	R_PPC_GOT_TLSLD16_HI       = 85
-	R_PPC_GOT_TLSLD16_HA       = 86
-	R_PPC_GOT_TPREL16          = 87
-	R_PPC_GOT_TPREL16_LO       = 88
-	R_PPC_GOT_TPREL16_HI       = 89
-	R_PPC_GOT_TPREL16_HA       = 90
-	R_PPC_EMB_NADDR32          = 101
-	R_PPC_EMB_NADDR16          = 102
-	R_PPC_EMB_NADDR16_LO       = 103
-	R_PPC_EMB_NADDR16_HI       = 104
-	R_PPC_EMB_NADDR16_HA       = 105
-	R_PPC_EMB_SDAI16           = 106
-	R_PPC_EMB_SDA2I16          = 107
-	R_PPC_EMB_SDA2REL          = 108
-	R_PPC_EMB_SDA21            = 109
-	R_PPC_EMB_MRKREF           = 110
-	R_PPC_EMB_RELSEC16         = 111
-	R_PPC_EMB_RELST_LO         = 112
-	R_PPC_EMB_RELST_HI         = 113
-	R_PPC_EMB_RELST_HA         = 114
-	R_PPC_EMB_BIT_FLD          = 115
-	R_PPC_EMB_RELSDA           = 116
-	R_PPC64_REL24              = R_PPC_REL24
-	R_PPC64_JMP_SLOT           = R_PPC_JMP_SLOT
-	R_PPC64_ADDR64             = 38
-	R_PPC64_TOC16              = 47
-	R_PPC64_TOC16_LO           = 48
-	R_PPC64_TOC16_HI           = 49
-	R_PPC64_TOC16_HA           = 50
-	R_PPC64_TOC16_DS           = 63
-	R_PPC64_TOC16_LO_DS        = 64
-	R_PPC64_REL16_LO           = 250
-	R_PPC64_REL16_HI           = 251
-	R_PPC64_REL16_HA           = 252
-	R_SPARC_NONE               = 0
-	R_SPARC_8                  = 1
-	R_SPARC_16                 = 2
-	R_SPARC_32                 = 3
-	R_SPARC_DISP8              = 4
-	R_SPARC_DISP16             = 5
-	R_SPARC_DISP32             = 6
-	R_SPARC_WDISP30            = 7
-	R_SPARC_WDISP22            = 8
-	R_SPARC_HI22               = 9
-	R_SPARC_22                 = 10
-	R_SPARC_13                 = 11
-	R_SPARC_LO10               = 12
-	R_SPARC_GOT10              = 13
-	R_SPARC_GOT13              = 14
-	R_SPARC_GOT22              = 15
-	R_SPARC_PC10               = 16
-	R_SPARC_PC22               = 17
-	R_SPARC_WPLT30             = 18
-	R_SPARC_COPY               = 19
-	R_SPARC_GLOB_DAT           = 20
-	R_SPARC_JMP_SLOT           = 21
-	R_SPARC_RELATIVE           = 22
-	R_SPARC_UA32               = 23
-	R_SPARC_PLT32              = 24
-	R_SPARC_HIPLT22            = 25
-	R_SPARC_LOPLT10            = 26
-	R_SPARC_PCPLT32            = 27
-	R_SPARC_PCPLT22            = 28
-	R_SPARC_PCPLT10            = 29
-	R_SPARC_10                 = 30
-	R_SPARC_11                 = 31
-	R_SPARC_64                 = 32
-	R_SPARC_OLO10              = 33
-	R_SPARC_HH22               = 34
-	R_SPARC_HM10               = 35
-	R_SPARC_LM22               = 36
-	R_SPARC_PC_HH22            = 37
-	R_SPARC_PC_HM10            = 38
-	R_SPARC_PC_LM22            = 39
-	R_SPARC_WDISP16            = 40
-	R_SPARC_WDISP19            = 41
-	R_SPARC_GLOB_JMP           = 42
-	R_SPARC_7                  = 43
-	R_SPARC_5                  = 44
-	R_SPARC_6                  = 45
-	R_SPARC_DISP64             = 46
-	R_SPARC_PLT64              = 47
-	R_SPARC_HIX22              = 48
-	R_SPARC_LOX10              = 49
-	R_SPARC_H44                = 50
-	R_SPARC_M44                = 51
-	R_SPARC_L44                = 52
-	R_SPARC_REGISTER           = 53
-	R_SPARC_UA64               = 54
-	R_SPARC_UA16               = 55
-	ARM_MAGIC_TRAMP_NUMBER     = 0x5c000003
+	R_X86_64_NONE           = 0
+	R_X86_64_64             = 1
+	R_X86_64_PC32           = 2
+	R_X86_64_GOT32          = 3
+	R_X86_64_PLT32          = 4
+	R_X86_64_COPY           = 5
+	R_X86_64_GLOB_DAT       = 6
+	R_X86_64_JMP_SLOT       = 7
+	R_X86_64_RELATIVE       = 8
+	R_X86_64_GOTPCREL       = 9
+	R_X86_64_32             = 10
+	R_X86_64_32S            = 11
+	R_X86_64_16             = 12
+	R_X86_64_PC16           = 13
+	R_X86_64_8              = 14
+	R_X86_64_PC8            = 15
+	R_X86_64_DTPMOD64       = 16
+	R_X86_64_DTPOFF64       = 17
+	R_X86_64_TPOFF64        = 18
+	R_X86_64_TLSGD          = 19
+	R_X86_64_TLSLD          = 20
+	R_X86_64_DTPOFF32       = 21
+	R_X86_64_GOTTPOFF       = 22
+	R_X86_64_TPOFF32        = 23
+	R_X86_64_PC64           = 24
+	R_X86_64_GOTOFF64       = 25
+	R_X86_64_GOTPC32        = 26
+	R_X86_64_GOT64          = 27
+	R_X86_64_GOTPCREL64     = 28
+	R_X86_64_GOTPC64        = 29
+	R_X86_64_GOTPLT64       = 30
+	R_X86_64_PLTOFF64       = 31
+	R_X86_64_SIZE32         = 32
+	R_X86_64_SIZE64         = 33
+	R_X86_64_GOTPC32_TLSDEC = 34
+	R_X86_64_TLSDESC_CALL   = 35
+	R_X86_64_TLSDESC        = 36
+	R_X86_64_IRELATIVE      = 37
+	R_X86_64_PC32_BND       = 40
+	R_X86_64_GOTPCRELX      = 41
+	R_X86_64_REX_GOTPCRELX  = 42
+
+	R_AARCH64_ABS64                       = 257
+	R_AARCH64_ABS32                       = 258
+	R_AARCH64_CALL26                      = 283
+	R_AARCH64_ADR_PREL_PG_HI21            = 275
+	R_AARCH64_ADD_ABS_LO12_NC             = 277
+	R_AARCH64_LDST8_ABS_LO12_NC           = 278
+	R_AARCH64_LDST16_ABS_LO12_NC          = 284
+	R_AARCH64_LDST32_ABS_LO12_NC          = 285
+	R_AARCH64_LDST64_ABS_LO12_NC          = 286
+	R_AARCH64_ADR_GOT_PAGE                = 311
+	R_AARCH64_LD64_GOT_LO12_NC            = 312
+	R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21   = 541
+	R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 542
+	R_AARCH64_TLSLE_MOVW_TPREL_G0         = 547
+
+	R_ALPHA_NONE           = 0
+	R_ALPHA_REFLONG        = 1
+	R_ALPHA_REFQUAD        = 2
+	R_ALPHA_GPREL32        = 3
+	R_ALPHA_LITERAL        = 4
+	R_ALPHA_LITUSE         = 5
+	R_ALPHA_GPDISP         = 6
+	R_ALPHA_BRADDR         = 7
+	R_ALPHA_HINT           = 8
+	R_ALPHA_SREL16         = 9
+	R_ALPHA_SREL32         = 10
+	R_ALPHA_SREL64         = 11
+	R_ALPHA_OP_PUSH        = 12
+	R_ALPHA_OP_STORE       = 13
+	R_ALPHA_OP_PSUB        = 14
+	R_ALPHA_OP_PRSHIFT     = 15
+	R_ALPHA_GPVALUE        = 16
+	R_ALPHA_GPRELHIGH      = 17
+	R_ALPHA_GPRELLOW       = 18
+	R_ALPHA_IMMED_GP_16    = 19
+	R_ALPHA_IMMED_GP_HI32  = 20
+	R_ALPHA_IMMED_SCN_HI32 = 21
+	R_ALPHA_IMMED_BR_HI32  = 22
+	R_ALPHA_IMMED_LO32     = 23
+	R_ALPHA_COPY           = 24
+	R_ALPHA_GLOB_DAT       = 25
+	R_ALPHA_JMP_SLOT       = 26
+	R_ALPHA_RELATIVE       = 27
+
+	R_ARM_NONE          = 0
+	R_ARM_PC24          = 1
+	R_ARM_ABS32         = 2
+	R_ARM_REL32         = 3
+	R_ARM_PC13          = 4
+	R_ARM_ABS16         = 5
+	R_ARM_ABS12         = 6
+	R_ARM_THM_ABS5      = 7
+	R_ARM_ABS8          = 8
+	R_ARM_SBREL32       = 9
+	R_ARM_THM_PC22      = 10
+	R_ARM_THM_PC8       = 11
+	R_ARM_AMP_VCALL9    = 12
+	R_ARM_SWI24         = 13
+	R_ARM_THM_SWI8      = 14
+	R_ARM_XPC25         = 15
+	R_ARM_THM_XPC22     = 16
+	R_ARM_COPY          = 20
+	R_ARM_GLOB_DAT      = 21
+	R_ARM_JUMP_SLOT     = 22
+	R_ARM_RELATIVE      = 23
+	R_ARM_GOTOFF        = 24
+	R_ARM_GOTPC         = 25
+	R_ARM_GOT32         = 26
+	R_ARM_PLT32         = 27
+	R_ARM_CALL          = 28
+	R_ARM_JUMP24        = 29
+	R_ARM_V4BX          = 40
+	R_ARM_GOT_PREL      = 96
+	R_ARM_GNU_VTENTRY   = 100
+	R_ARM_GNU_VTINHERIT = 101
+	R_ARM_TLS_IE32      = 107
+	R_ARM_TLS_LE32      = 108
+	R_ARM_RSBREL32      = 250
+	R_ARM_THM_RPC22     = 251
+	R_ARM_RREL32        = 252
+	R_ARM_RABS32        = 253
+	R_ARM_RPC24         = 254
+	R_ARM_RBASE         = 255
+
+	R_386_NONE          = 0
+	R_386_32            = 1
+	R_386_PC32          = 2
+	R_386_GOT32         = 3
+	R_386_PLT32         = 4
+	R_386_COPY          = 5
+	R_386_GLOB_DAT      = 6
+	R_386_JMP_SLOT      = 7
+	R_386_RELATIVE      = 8
+	R_386_GOTOFF        = 9
+	R_386_GOTPC         = 10
+	R_386_TLS_TPOFF     = 14
+	R_386_TLS_IE        = 15
+	R_386_TLS_GOTIE     = 16
+	R_386_TLS_LE        = 17
+	R_386_TLS_GD        = 18
+	R_386_TLS_LDM       = 19
+	R_386_TLS_GD_32     = 24
+	R_386_TLS_GD_PUSH   = 25
+	R_386_TLS_GD_CALL   = 26
+	R_386_TLS_GD_POP    = 27
+	R_386_TLS_LDM_32    = 28
+	R_386_TLS_LDM_PUSH  = 29
+	R_386_TLS_LDM_CALL  = 30
+	R_386_TLS_LDM_POP   = 31
+	R_386_TLS_LDO_32    = 32
+	R_386_TLS_IE_32     = 33
+	R_386_TLS_LE_32     = 34
+	R_386_TLS_DTPMOD32  = 35
+	R_386_TLS_DTPOFF32  = 36
+	R_386_TLS_TPOFF32   = 37
+	R_386_TLS_GOTDESC   = 39
+	R_386_TLS_DESC_CALL = 40
+	R_386_TLS_DESC      = 41
+	R_386_IRELATIVE     = 42
+	R_386_GOT32X        = 43
+
+	R_PPC_NONE            = 0
+	R_PPC_ADDR32          = 1
+	R_PPC_ADDR24          = 2
+	R_PPC_ADDR16          = 3
+	R_PPC_ADDR16_LO       = 4
+	R_PPC_ADDR16_HI       = 5
+	R_PPC_ADDR16_HA       = 6
+	R_PPC_ADDR14          = 7
+	R_PPC_ADDR14_BRTAKEN  = 8
+	R_PPC_ADDR14_BRNTAKEN = 9
+	R_PPC_REL24           = 10
+	R_PPC_REL14           = 11
+	R_PPC_REL14_BRTAKEN   = 12
+	R_PPC_REL14_BRNTAKEN  = 13
+	R_PPC_GOT16           = 14
+	R_PPC_GOT16_LO        = 15
+	R_PPC_GOT16_HI        = 16
+	R_PPC_GOT16_HA        = 17
+	R_PPC_PLTREL24        = 18
+	R_PPC_COPY            = 19
+	R_PPC_GLOB_DAT        = 20
+	R_PPC_JMP_SLOT        = 21
+	R_PPC_RELATIVE        = 22
+	R_PPC_LOCAL24PC       = 23
+	R_PPC_UADDR32         = 24
+	R_PPC_UADDR16         = 25
+	R_PPC_REL32           = 26
+	R_PPC_PLT32           = 27
+	R_PPC_PLTREL32        = 28
+	R_PPC_PLT16_LO        = 29
+	R_PPC_PLT16_HI        = 30
+	R_PPC_PLT16_HA        = 31
+	R_PPC_SDAREL16        = 32
+	R_PPC_SECTOFF         = 33
+	R_PPC_SECTOFF_LO      = 34
+	R_PPC_SECTOFF_HI      = 35
+	R_PPC_SECTOFF_HA      = 36
+	R_PPC_TLS             = 67
+	R_PPC_DTPMOD32        = 68
+	R_PPC_TPREL16         = 69
+	R_PPC_TPREL16_LO      = 70
+	R_PPC_TPREL16_HI      = 71
+	R_PPC_TPREL16_HA      = 72
+	R_PPC_TPREL32         = 73
+	R_PPC_DTPREL16        = 74
+	R_PPC_DTPREL16_LO     = 75
+	R_PPC_DTPREL16_HI     = 76
+	R_PPC_DTPREL16_HA     = 77
+	R_PPC_DTPREL32        = 78
+	R_PPC_GOT_TLSGD16     = 79
+	R_PPC_GOT_TLSGD16_LO  = 80
+	R_PPC_GOT_TLSGD16_HI  = 81
+	R_PPC_GOT_TLSGD16_HA  = 82
+	R_PPC_GOT_TLSLD16     = 83
+	R_PPC_GOT_TLSLD16_LO  = 84
+	R_PPC_GOT_TLSLD16_HI  = 85
+	R_PPC_GOT_TLSLD16_HA  = 86
+	R_PPC_GOT_TPREL16     = 87
+	R_PPC_GOT_TPREL16_LO  = 88
+	R_PPC_GOT_TPREL16_HI  = 89
+	R_PPC_GOT_TPREL16_HA  = 90
+	R_PPC_EMB_NADDR32     = 101
+	R_PPC_EMB_NADDR16     = 102
+	R_PPC_EMB_NADDR16_LO  = 103
+	R_PPC_EMB_NADDR16_HI  = 104
+	R_PPC_EMB_NADDR16_HA  = 105
+	R_PPC_EMB_SDAI16      = 106
+	R_PPC_EMB_SDA2I16     = 107
+	R_PPC_EMB_SDA2REL     = 108
+	R_PPC_EMB_SDA21       = 109
+	R_PPC_EMB_MRKREF      = 110
+	R_PPC_EMB_RELSEC16    = 111
+	R_PPC_EMB_RELST_LO    = 112
+	R_PPC_EMB_RELST_HI    = 113
+	R_PPC_EMB_RELST_HA    = 114
+	R_PPC_EMB_BIT_FLD     = 115
+	R_PPC_EMB_RELSDA      = 116
+
+	R_PPC64_ADDR32            = R_PPC_ADDR32
+	R_PPC64_ADDR16_LO         = R_PPC_ADDR16_LO
+	R_PPC64_ADDR16_HA         = R_PPC_ADDR16_HA
+	R_PPC64_REL24             = R_PPC_REL24
+	R_PPC64_GOT16_HA          = R_PPC_GOT16_HA
+	R_PPC64_JMP_SLOT          = R_PPC_JMP_SLOT
+	R_PPC64_TPREL16           = R_PPC_TPREL16
+	R_PPC64_ADDR64            = 38
+	R_PPC64_TOC16             = 47
+	R_PPC64_TOC16_LO          = 48
+	R_PPC64_TOC16_HI          = 49
+	R_PPC64_TOC16_HA          = 50
+	R_PPC64_ADDR16_LO_DS      = 57
+	R_PPC64_GOT16_LO_DS       = 59
+	R_PPC64_TOC16_DS          = 63
+	R_PPC64_TOC16_LO_DS       = 64
+	R_PPC64_TLS               = 67
+	R_PPC64_GOT_TPREL16_LO_DS = 88
+	R_PPC64_GOT_TPREL16_HA    = 90
+	R_PPC64_REL16_LO          = 250
+	R_PPC64_REL16_HI          = 251
+	R_PPC64_REL16_HA          = 252
+
+	R_SPARC_NONE     = 0
+	R_SPARC_8        = 1
+	R_SPARC_16       = 2
+	R_SPARC_32       = 3
+	R_SPARC_DISP8    = 4
+	R_SPARC_DISP16   = 5
+	R_SPARC_DISP32   = 6
+	R_SPARC_WDISP30  = 7
+	R_SPARC_WDISP22  = 8
+	R_SPARC_HI22     = 9
+	R_SPARC_22       = 10
+	R_SPARC_13       = 11
+	R_SPARC_LO10     = 12
+	R_SPARC_GOT10    = 13
+	R_SPARC_GOT13    = 14
+	R_SPARC_GOT22    = 15
+	R_SPARC_PC10     = 16
+	R_SPARC_PC22     = 17
+	R_SPARC_WPLT30   = 18
+	R_SPARC_COPY     = 19
+	R_SPARC_GLOB_DAT = 20
+	R_SPARC_JMP_SLOT = 21
+	R_SPARC_RELATIVE = 22
+	R_SPARC_UA32     = 23
+	R_SPARC_PLT32    = 24
+	R_SPARC_HIPLT22  = 25
+	R_SPARC_LOPLT10  = 26
+	R_SPARC_PCPLT32  = 27
+	R_SPARC_PCPLT22  = 28
+	R_SPARC_PCPLT10  = 29
+	R_SPARC_10       = 30
+	R_SPARC_11       = 31
+	R_SPARC_64       = 32
+	R_SPARC_OLO10    = 33
+	R_SPARC_HH22     = 34
+	R_SPARC_HM10     = 35
+	R_SPARC_LM22     = 36
+	R_SPARC_PC_HH22  = 37
+	R_SPARC_PC_HM10  = 38
+	R_SPARC_PC_LM22  = 39
+	R_SPARC_WDISP16  = 40
+	R_SPARC_WDISP19  = 41
+	R_SPARC_GLOB_JMP = 42
+	R_SPARC_7        = 43
+	R_SPARC_5        = 44
+	R_SPARC_6        = 45
+	R_SPARC_DISP64   = 46
+	R_SPARC_PLT64    = 47
+	R_SPARC_HIX22    = 48
+	R_SPARC_LOX10    = 49
+	R_SPARC_H44      = 50
+	R_SPARC_M44      = 51
+	R_SPARC_L44      = 52
+	R_SPARC_REGISTER = 53
+	R_SPARC_UA64     = 54
+	R_SPARC_UA16     = 55
+
+	ARM_MAGIC_TRAMP_NUMBER = 0x5c000003
 )
 
 /*
@@ -783,7 +811,10 @@ func Elfinit() {
 		}
 		fallthrough
 
-	case '6', '7':
+	case '0', '6', '7':
+		if Thearch.Thechar == '0' {
+			ehdr.flags = 0x20000000 /* MIPS 3 */
+		}
 		elf64 = true
 
 		ehdr.phoff = ELF64HDRSIZE      /* Must be be ELF64HDRSIZE: first PHdr must follow ELF header */
@@ -792,11 +823,19 @@ func Elfinit() {
 		ehdr.phentsize = ELF64PHDRSIZE /* Must be ELF64PHDRSIZE */
 		ehdr.shentsize = ELF64SHDRSIZE /* Must be ELF64SHDRSIZE */
 
-		// we use EABI on both linux/arm and freebsd/arm.
+	// we use EABI on both linux/arm and freebsd/arm.
 	// 32-bit architectures
 	case '5':
 		// we use EABI on both linux/arm and freebsd/arm.
 		if HEADTYPE == obj.Hlinux || HEADTYPE == obj.Hfreebsd {
+			// We set a value here that makes no indication of which
+			// float ABI the object uses, because this is information
+			// used by the dynamic linker to compare executables and
+			// shared libraries -- so it only matters for cgo calls, and
+			// the information properly comes from the object files
+			// produced by the host C compiler. parseArmAttributes in
+			// ldelf.go reads that information and updates this field as
+			// appropriate.
 			ehdr.flags = 0x5000002 // has entry point, Version5 EABI
 		}
 		fallthrough
@@ -811,7 +850,26 @@ func Elfinit() {
 	}
 }
 
+// Make sure PT_LOAD is aligned properly and
+// that there is no gap,
+// correct ELF loaders will do this implicitly,
+// but buggy ELF loaders like the one in some
+// versions of QEMU and UPX won't.
+func fixElfPhdr(e *ElfPhdr) {
+	frag := int(e.vaddr & (e.align - 1))
+
+	e.off -= uint64(frag)
+	e.vaddr -= uint64(frag)
+	e.paddr -= uint64(frag)
+	e.filesz += uint64(frag)
+	e.memsz += uint64(frag)
+}
+
 func elf64phdr(e *ElfPhdr) {
+	if e.type_ == PT_LOAD {
+		fixElfPhdr(e)
+	}
+
 	Thearch.Lput(e.type_)
 	Thearch.Lput(e.flags)
 	Thearch.Vput(e.off)
@@ -824,16 +882,7 @@ func elf64phdr(e *ElfPhdr) {
 
 func elf32phdr(e *ElfPhdr) {
 	if e.type_ == PT_LOAD {
-		// Correct ELF loaders will do this implicitly,
-		// but buggy ELF loaders like the one in some
-		// versions of QEMU won't.
-		frag := int(e.vaddr & (e.align - 1))
-
-		e.off -= uint64(frag)
-		e.vaddr -= uint64(frag)
-		e.paddr -= uint64(frag)
-		e.filesz += uint64(frag)
-		e.memsz += uint64(frag)
+		fixElfPhdr(e)
 	}
 
 	Thearch.Lput(e.type_)
@@ -1405,7 +1454,7 @@ func elfdynhash() {
 	}
 
 	switch Thearch.Thechar {
-	case '6', '7', '9':
+	case '0', '6', '7', '9':
 		sy := Linklookup(Ctxt, ".rela.plt", 0)
 		if sy.Size > 0 {
 			Elfwritedynent(s, DT_PLTREL, DT_RELA)
@@ -1513,9 +1562,7 @@ func elfshbits(sect *Section) *ElfShdr {
 		sh.flags |= SHF_WRITE
 	}
 	if sect.Name == ".tbss" {
-		if goos != "android" {
-			sh.flags |= SHF_TLS // no TLS on android
-		}
+		sh.flags |= SHF_TLS
 		sh.type_ = SHT_NOBITS
 	}
 
@@ -1524,7 +1571,9 @@ func elfshbits(sect *Section) *ElfShdr {
 	}
 	sh.addralign = uint64(sect.Align)
 	sh.size = sect.Length
-	sh.off = sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr
+	if sect.Name != ".tbss" {
+		sh.off = sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr
+	}
 
 	return sh
 }
@@ -1545,7 +1594,7 @@ func elfshreloc(sect *Section) *ElfShdr {
 	var prefix string
 	var typ int
 	switch Thearch.Thechar {
-	case '6', '7', '9':
+	case '0', '6', '7', '9':
 		prefix = ".rela"
 		typ = SHT_RELA
 	default:
@@ -1611,7 +1660,7 @@ func elfrelocsect(sect *Section, first *LSym) {
 				continue
 			}
 
-			if r.Xsym.Elfsym == 0 {
+			if r.Xsym.ElfsymForReloc() == 0 {
 				Diag("reloc %d to non-elf symbol %s (outer=%s) %d", r.Type, r.Sym.Name, r.Xsym.Name, r.Sym.Type)
 			}
 			if Thearch.Elfreloc1(r, int64(uint64(sym.Value+int64(r.Off))-sect.Vaddr)) < 0 {
@@ -1704,31 +1753,43 @@ func doelf() {
 	}
 	Addstring(shstrtab, ".elfdata")
 	Addstring(shstrtab, ".rodata")
-	Addstring(shstrtab, ".typelink")
-	Addstring(shstrtab, ".gosymtab")
-	Addstring(shstrtab, ".gopclntab")
+	// See the comment about data.rel.ro.FOO section names in data.go.
+	relro_prefix := ""
+	if UseRelro() {
+		Addstring(shstrtab, ".data.rel.ro")
+		relro_prefix = ".data.rel.ro"
+	}
+	Addstring(shstrtab, relro_prefix+".typelink")
+	Addstring(shstrtab, relro_prefix+".gosymtab")
+	Addstring(shstrtab, relro_prefix+".gopclntab")
 
 	if Linkmode == LinkExternal {
 		Debug['d'] = 1
 
 		switch Thearch.Thechar {
-		case '6', '7', '9':
+		case '0', '6', '7', '9':
 			Addstring(shstrtab, ".rela.text")
 			Addstring(shstrtab, ".rela.rodata")
-			Addstring(shstrtab, ".rela.typelink")
-			Addstring(shstrtab, ".rela.gosymtab")
-			Addstring(shstrtab, ".rela.gopclntab")
+			Addstring(shstrtab, ".rela"+relro_prefix+".typelink")
+			Addstring(shstrtab, ".rela"+relro_prefix+".gosymtab")
+			Addstring(shstrtab, ".rela"+relro_prefix+".gopclntab")
 			Addstring(shstrtab, ".rela.noptrdata")
 			Addstring(shstrtab, ".rela.data")
+			if UseRelro() {
+				Addstring(shstrtab, ".rela.data.rel.ro")
+			}
 
 		default:
 			Addstring(shstrtab, ".rel.text")
 			Addstring(shstrtab, ".rel.rodata")
-			Addstring(shstrtab, ".rel.typelink")
-			Addstring(shstrtab, ".rel.gosymtab")
-			Addstring(shstrtab, ".rel.gopclntab")
+			Addstring(shstrtab, ".rel"+relro_prefix+".typelink")
+			Addstring(shstrtab, ".rel"+relro_prefix+".gosymtab")
+			Addstring(shstrtab, ".rel"+relro_prefix+".gopclntab")
 			Addstring(shstrtab, ".rel.noptrdata")
 			Addstring(shstrtab, ".rel.data")
+			if UseRelro() {
+				Addstring(shstrtab, ".rel.data.rel.ro")
+			}
 		}
 
 		// add a .note.GNU-stack section to mark the stack as non-executable
@@ -1752,7 +1813,7 @@ func doelf() {
 	if hasinitarr {
 		Addstring(shstrtab, ".init_array")
 		switch Thearch.Thechar {
-		case '6', '7', '9':
+		case '0', '6', '7', '9':
 			Addstring(shstrtab, ".rela.init_array")
 		default:
 			Addstring(shstrtab, ".rel.init_array")
@@ -1779,7 +1840,7 @@ func doelf() {
 		Addstring(shstrtab, ".dynsym")
 		Addstring(shstrtab, ".dynstr")
 		switch Thearch.Thechar {
-		case '6', '7', '9':
+		case '0', '6', '7', '9':
 			Addstring(shstrtab, ".rela")
 			Addstring(shstrtab, ".rela.plt")
 		default:
@@ -1797,7 +1858,7 @@ func doelf() {
 		s.Type = obj.SELFROSECT
 		s.Reachable = true
 		switch Thearch.Thechar {
-		case '6', '7', '9':
+		case '0', '6', '7', '9':
 			s.Size += ELF64SYMSIZE
 		default:
 			s.Size += ELF32SYMSIZE
@@ -1815,7 +1876,7 @@ func doelf() {
 
 		/* relocation table */
 		switch Thearch.Thechar {
-		case '6', '7', '9':
+		case '0', '6', '7', '9':
 			s = Linklookup(Ctxt, ".rela", 0)
 		default:
 			s = Linklookup(Ctxt, ".rel", 0)
@@ -1860,7 +1921,7 @@ func doelf() {
 		Thearch.Elfsetupplt()
 
 		switch Thearch.Thechar {
-		case '6', '7', '9':
+		case '0', '6', '7', '9':
 			s = Linklookup(Ctxt, ".rela.plt", 0)
 		default:
 			s = Linklookup(Ctxt, ".rel.plt", 0)
@@ -1889,7 +1950,7 @@ func doelf() {
 
 		elfwritedynentsym(s, DT_SYMTAB, Linklookup(Ctxt, ".dynsym", 0))
 		switch Thearch.Thechar {
-		case '6', '7', '9':
+		case '0', '6', '7', '9':
 			Elfwritedynent(s, DT_SYMENT, ELF64SYMSIZE)
 		default:
 			Elfwritedynent(s, DT_SYMENT, ELF32SYMSIZE)
@@ -1897,7 +1958,7 @@ func doelf() {
 		elfwritedynentsym(s, DT_STRTAB, Linklookup(Ctxt, ".dynstr", 0))
 		elfwritedynentsymsize(s, DT_STRSZ, Linklookup(Ctxt, ".dynstr", 0))
 		switch Thearch.Thechar {
-		case '6', '7', '9':
+		case '0', '6', '7', '9':
 			elfwritedynentsym(s, DT_RELA, Linklookup(Ctxt, ".rela", 0))
 			elfwritedynentsymsize(s, DT_RELASZ, Linklookup(Ctxt, ".rela", 0))
 			Elfwritedynent(s, DT_RELAENT, ELF64RELASIZE)
@@ -1996,6 +2057,8 @@ func Asmbelf(symo int64) {
 	switch Thearch.Thechar {
 	default:
 		Exitf("unknown architecture in asmbelf: %v", Thearch.Thechar)
+	case '0':
+		eh.machine = EM_MIPS
 	case '5':
 		eh.machine = EM_ARM
 	case '6':
@@ -2299,12 +2362,20 @@ func Asmbelf(symo int64) {
 		// Do not emit PT_TLS for OpenBSD since ld.so(1) does
 		// not currently support it. This is handled
 		// appropriately in runtime/cgo.
-		if Ctxt.Tlsoffset != 0 && HEADTYPE != obj.Hopenbsd {
-			ph := newElfPhdr()
-			ph.type_ = PT_TLS
-			ph.flags = PF_R
-			ph.memsz = uint64(-Ctxt.Tlsoffset)
-			ph.align = uint64(Thearch.Regsize)
+		if HEADTYPE != obj.Hopenbsd {
+			tlssize := uint64(0)
+			for sect := Segdata.Sect; sect != nil; sect = sect.Next {
+				if sect.Name == ".tbss" {
+					tlssize = sect.Length
+				}
+			}
+			if tlssize != 0 {
+				ph := newElfPhdr()
+				ph.type_ = PT_TLS
+				ph.flags = PF_R
+				ph.memsz = tlssize
+				ph.align = uint64(Thearch.Regsize)
+			}
 		}
 	}
 
@@ -2362,16 +2433,6 @@ elfobj:
 		sh.flags = 0
 	}
 
-	// generate .tbss section for dynamic internal linking (except for OpenBSD)
-	// external linking generates .tbss in data.c
-	if Linkmode == LinkInternal && Debug['d'] == 0 && HEADTYPE != obj.Hopenbsd {
-		sh := elfshname(".tbss")
-		sh.type_ = SHT_NOBITS
-		sh.addralign = uint64(Thearch.Regsize)
-		sh.size = uint64(-Ctxt.Tlsoffset)
-		sh.flags = SHF_ALLOC | SHF_TLS | SHF_WRITE
-	}
-
 	if Debug['s'] == 0 {
 		sh := elfshname(".symtab")
 		sh.type_ = SHT_SYMTAB
diff --git a/src/cmd/link/internal/ld/go.go b/src/cmd/link/internal/ld/go.go
index 80a6c6e..28f0910 100644
--- a/src/cmd/link/internal/ld/go.go
+++ b/src/cmd/link/internal/ld/go.go
@@ -11,7 +11,6 @@ import (
 	"cmd/internal/obj"
 	"fmt"
 	"os"
-	"strconv"
 	"strings"
 )
 
@@ -22,37 +21,11 @@ func expandpkg(t0 string, pkg string) string {
 	return strings.Replace(t0, `"".`, pkg+".", -1)
 }
 
-// accumulate all type information from .6 files.
-// check for inconsistencies.
-
 // TODO:
 //	generate debugging section in binary.
 //	once the dust settles, try to move some code to
 //		libmach, so that other linkers and ar can share.
 
-/*
- *	package import data
- */
-type Import struct {
-	prefix string // "type", "var", "func", "const"
-	name   string
-	def    string
-	file   string
-}
-
-// importmap records type information about imported symbols to detect inconsistencies.
-// Entries are keyed by qualified symbol name (e.g., "runtime.Callers" or "net/url.Error").
-var importmap = map[string]*Import{}
-
-func lookupImport(name string) *Import {
-	if x, ok := importmap[name]; ok {
-		return x
-	}
-	x := &Import{name: name}
-	importmap[name] = x
-	return x
-}
-
 func ldpkg(f *obj.Biobuf, pkg string, length int64, filename string, whence int) {
 	var p0, p1 int
 
@@ -68,6 +41,12 @@ func ldpkg(f *obj.Biobuf, pkg string, length int64, filename string, whence int)
 		return
 	}
 
+	// In a __.PKGDEF, we only care about the package name.
+	// Don't read all the export data.
+	if length > 1000 && whence == Pkgdef {
+		length = 1000
+	}
+
 	bdata := make([]byte, length)
 	if int64(obj.Bread(f, bdata)) != length {
 		fmt.Fprintf(os.Stderr, "%s: short pkg read %s\n", os.Args[0], filename)
@@ -87,13 +66,17 @@ func ldpkg(f *obj.Biobuf, pkg string, length int64, filename string, whence int)
 		return
 	}
 
+	// \n$$B marks the beginning of binary export data - don't skip over the B
 	p0 += 3
-	for p0 < len(data) && data[p0] != '\n' {
+	for p0 < len(data) && data[p0] != '\n' && data[p0] != 'B' {
 		p0++
 	}
 
 	// second marks end of exports / beginning of local data
-	p1 = strings.Index(data[p0:], "\n$$")
+	p1 = strings.Index(data[p0:], "\n$$\n")
+	if p1 < 0 && whence == Pkgdef {
+		p1 = len(data) - p0
+	}
 	if p1 < 0 {
 		fmt.Fprintf(os.Stderr, "%s: cannot find end of exports in %s\n", os.Args[0], filename)
 		if Debug['u'] != 0 {
@@ -103,10 +86,12 @@ func ldpkg(f *obj.Biobuf, pkg string, length int64, filename string, whence int)
 	}
 	p1 += p0
 
-	for p0 < p1 && (data[p0] == ' ' || data[p0] == '\t' || data[p0] == '\n') {
+	for p0 < p1 && data[p0] != 'B' && (data[p0] == ' ' || data[p0] == '\t' || data[p0] == '\n') {
 		p0++
 	}
-	if p0 < p1 {
+	// don't check this section if we have binary (B) export data
+	// TODO fix this eventually
+	if p0 < p1 && data[p0] != 'B' {
 		if !strings.HasPrefix(data[p0:], "package ") {
 			fmt.Fprintf(os.Stderr, "%s: bad package section in %s - %.20s\n", os.Args[0], filename, data[p0:])
 			if Debug['u'] != 0 {
@@ -138,8 +123,6 @@ func ldpkg(f *obj.Biobuf, pkg string, length int64, filename string, whence int)
 		if pkg == "main" && name != "main" {
 			Exitf("%s: not package main (package %s)", filename, name)
 		}
-
-		loadpkgdata(filename, pkg, data[p0:p1])
 	}
 
 	// __.PKGDEF has no cgo section - those are in the C compiler-generated object files.
@@ -178,195 +161,6 @@ func ldpkg(f *obj.Biobuf, pkg string, length int64, filename string, whence int)
 	}
 }
 
-func loadpkgdata(file string, pkg string, data string) {
-	var prefix string
-	var name string
-	var def string
-
-	p := data
-	for parsepkgdata(file, pkg, &p, &prefix, &name, &def) > 0 {
-		x := lookupImport(name)
-		if x.prefix == "" {
-			x.prefix = prefix
-			x.def = def
-			x.file = file
-		} else if x.prefix != prefix {
-			fmt.Fprintf(os.Stderr, "%s: conflicting definitions for %s\n", os.Args[0], name)
-			fmt.Fprintf(os.Stderr, "%s:\t%s %s ...\n", x.file, x.prefix, name)
-			fmt.Fprintf(os.Stderr, "%s:\t%s %s ...\n", file, prefix, name)
-			nerrors++
-		} else if x.def != def {
-			fmt.Fprintf(os.Stderr, "%s: conflicting definitions for %s\n", os.Args[0], name)
-			fmt.Fprintf(os.Stderr, "%s:\t%s %s %s\n", x.file, x.prefix, name, x.def)
-			fmt.Fprintf(os.Stderr, "%s:\t%s %s %s\n", file, prefix, name, def)
-			nerrors++
-		}
-	}
-}
-
-func parsepkgdata(file string, pkg string, pp *string, prefixp *string, namep *string, defp *string) int {
-	// skip white space
-	p := *pp
-
-loop:
-	for len(p) > 0 && (p[0] == ' ' || p[0] == '\t' || p[0] == '\n') {
-		p = p[1:]
-	}
-	if len(p) == 0 || strings.HasPrefix(p, "$$\n") {
-		return 0
-	}
-
-	// prefix: (var|type|func|const)
-	prefix := p
-
-	if len(p) < 7 {
-		return -1
-	}
-	if strings.HasPrefix(p, "var ") {
-		p = p[4:]
-	} else if strings.HasPrefix(p, "type ") {
-		p = p[5:]
-	} else if strings.HasPrefix(p, "func ") {
-		p = p[5:]
-	} else if strings.HasPrefix(p, "const ") {
-		p = p[6:]
-	} else if strings.HasPrefix(p, "import ") {
-		p = p[7:]
-		for len(p) > 0 && p[0] != ' ' {
-			p = p[1:]
-		}
-		p = p[1:]
-		line := p
-		for len(p) > 0 && p[0] != '\n' {
-			p = p[1:]
-		}
-		if len(p) == 0 {
-			fmt.Fprintf(os.Stderr, "%s: %s: confused in import line\n", os.Args[0], file)
-			nerrors++
-			return -1
-		}
-		line = line[:len(line)-len(p)]
-		line = strings.TrimSuffix(line, " // indirect")
-		path, err := strconv.Unquote(line)
-		if err != nil {
-			fmt.Fprintf(os.Stderr, "%s: %s: confused in import path: %q\n", os.Args[0], file, line)
-			nerrors++
-			return -1
-		}
-		p = p[1:]
-		imported(pkg, path)
-		goto loop
-	} else {
-		fmt.Fprintf(os.Stderr, "%s: %s: confused in pkg data near <<%.40s>>\n", os.Args[0], file, prefix)
-		nerrors++
-		return -1
-	}
-
-	prefix = prefix[:len(prefix)-len(p)-1]
-
-	// name: a.b followed by space
-	name := p
-
-	inquote := false
-	for len(p) > 0 {
-		if p[0] == ' ' && !inquote {
-			break
-		}
-
-		if p[0] == '\\' {
-			p = p[1:]
-		} else if p[0] == '"' {
-			inquote = !inquote
-		}
-
-		p = p[1:]
-	}
-
-	if len(p) == 0 {
-		return -1
-	}
-	name = name[:len(name)-len(p)]
-	p = p[1:]
-
-	// def: free form to new line
-	def := p
-
-	for len(p) > 0 && p[0] != '\n' {
-		p = p[1:]
-	}
-	if len(p) == 0 {
-		return -1
-	}
-	def = def[:len(def)-len(p)]
-	var defbuf *bytes.Buffer
-	p = p[1:]
-
-	// include methods on successive lines in def of named type
-	var meth string
-	for parsemethod(&p, &meth) > 0 {
-		if defbuf == nil {
-			defbuf = new(bytes.Buffer)
-			defbuf.WriteString(def)
-		}
-		defbuf.WriteString("\n\t")
-		defbuf.WriteString(meth)
-	}
-	if defbuf != nil {
-		def = defbuf.String()
-	}
-
-	name = expandpkg(name, pkg)
-	def = expandpkg(def, pkg)
-
-	// done
-	*pp = p
-
-	*prefixp = prefix
-	*namep = name
-	*defp = def
-	return 1
-}
-
-func parsemethod(pp *string, methp *string) int {
-	// skip white space
-	p := *pp
-
-	for len(p) > 0 && (p[0] == ' ' || p[0] == '\t') {
-		p = p[1:]
-	}
-	if len(p) == 0 {
-		return 0
-	}
-
-	// might be a comment about the method
-	if strings.HasPrefix(p, "//") {
-		goto useline
-	}
-
-	// if it says "func (", it's a method
-	if strings.HasPrefix(p, "func (") {
-		goto useline
-	}
-	return 0
-
-	// definition to end of line
-useline:
-	*methp = p
-
-	for len(p) > 0 && p[0] != '\n' {
-		p = p[1:]
-	}
-	if len(p) == 0 {
-		fmt.Fprintf(os.Stderr, "%s: lost end of line in method definition\n", os.Args[0])
-		*pp = ""
-		return -1
-	}
-
-	*methp = (*methp)[:len(*methp)-len(p)]
-	*pp = p[1:]
-	return 1
-}
-
 func loadcgo(file string, pkg string, p string) {
 	var next string
 	var q string
diff --git a/src/cmd/link/internal/ld/ldelf.go b/src/cmd/link/internal/ld/ldelf.go
index 7ff37ad..bea3f2d 100644
--- a/src/cmd/link/internal/ld/ldelf.go
+++ b/src/cmd/link/internal/ld/ldelf.go
@@ -5,6 +5,7 @@ import (
 	"cmd/internal/obj"
 	"encoding/binary"
 	"fmt"
+	"io"
 	"log"
 	"sort"
 	"strings"
@@ -315,6 +316,135 @@ func valuecmp(a *LSym, b *LSym) int {
 	return 0
 }
 
+const (
+	Tag_file                 = 1
+	Tag_CPU_name             = 4
+	Tag_CPU_raw_name         = 5
+	Tag_compatibility        = 32
+	Tag_nodefaults           = 64
+	Tag_also_compatible_with = 65
+	Tag_ABI_VFP_args         = 28
+)
+
+type elfAttribute struct {
+	tag  uint64
+	sval string
+	ival uint64
+}
+
+type elfAttributeList struct {
+	data []byte
+	err  error
+}
+
+func (a *elfAttributeList) string() string {
+	if a.err != nil {
+		return ""
+	}
+	nul := bytes.IndexByte(a.data, 0)
+	if nul < 0 {
+		a.err = io.EOF
+		return ""
+	}
+	s := string(a.data[:nul])
+	a.data = a.data[nul+1:]
+	return s
+}
+
+func (a *elfAttributeList) uleb128() uint64 {
+	if a.err != nil {
+		return 0
+	}
+	v, size := binary.Uvarint(a.data)
+	a.data = a.data[size:]
+	return v
+}
+
+// Read an elfAttribute from the list following the rules used on ARM systems.
+func (a *elfAttributeList) armAttr() elfAttribute {
+	attr := elfAttribute{tag: a.uleb128()}
+	switch {
+	case attr.tag == Tag_compatibility:
+		attr.ival = a.uleb128()
+		attr.sval = a.string()
+
+	case attr.tag == 64: // Tag_nodefaults has no argument
+
+	case attr.tag == 65: // Tag_also_compatible_with
+		// Not really, but we don't actually care about this tag.
+		attr.sval = a.string()
+
+	// Tag with string argument
+	case attr.tag == Tag_CPU_name || attr.tag == Tag_CPU_raw_name || (attr.tag >= 32 && attr.tag&1 != 0):
+		attr.sval = a.string()
+
+	default: // Tag with integer argument
+		attr.ival = a.uleb128()
+	}
+	return attr
+}
+
+func (a *elfAttributeList) done() bool {
+	if a.err != nil || len(a.data) == 0 {
+		return true
+	}
+	return false
+}
+
+// Look for the attribute that indicates the object uses the hard-float ABI (a
+// file-level attribute with tag Tag_VFP_arch and value 1). Unfortunately the
+// format used means that we have to parse all of the file-level attributes to
+// find the one we are looking for. This format is slightly documented in "ELF
+// for the ARM Architecture" but mostly this is derived from reading the source
+// to gold and readelf.
+func parseArmAttributes(e binary.ByteOrder, data []byte) {
+	// We assume the soft-float ABI unless we see a tag indicating otherwise.
+	if ehdr.flags == 0x5000002 {
+		ehdr.flags = 0x5000202
+	}
+	if data[0] != 'A' {
+		fmt.Fprintf(&Bso, ".ARM.attributes has unexpected format %c\n", data[0])
+		return
+	}
+	data = data[1:]
+	for len(data) != 0 {
+		sectionlength := e.Uint32(data)
+		sectiondata := data[4:sectionlength]
+		data = data[sectionlength:]
+
+		nulIndex := bytes.IndexByte(sectiondata, 0)
+		if nulIndex < 0 {
+			fmt.Fprintf(&Bso, "corrupt .ARM.attributes (section name not NUL-terminated)\n")
+			return
+		}
+		name := string(sectiondata[:nulIndex])
+		sectiondata = sectiondata[nulIndex+1:]
+
+		if name != "aeabi" {
+			continue
+		}
+		for len(sectiondata) != 0 {
+			subsectiontag, sz := binary.Uvarint(sectiondata)
+			subsectionsize := e.Uint32(sectiondata[sz:])
+			subsectiondata := sectiondata[sz+4 : subsectionsize]
+			sectiondata = sectiondata[subsectionsize:]
+
+			if subsectiontag == Tag_file {
+				attrList := elfAttributeList{data: subsectiondata}
+				for !attrList.done() {
+					attr := attrList.armAttr()
+					if attr.tag == Tag_ABI_VFP_args && attr.ival == 1 {
+						ehdr.flags = 0x5000402 // has entry point, Version5 EABI, hard-float ABI
+					}
+				}
+				if attrList.err != nil {
+					fmt.Fprintf(&Bso, "could not parse .ARM.attributes\n")
+				}
+			}
+		}
+	}
+}
+
 func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) {
 	if Debug['v'] != 0 {
 		fmt.Fprintf(&Bso, "%5.2f ldelf %s\n", obj.Cputime(), pn)
@@ -421,6 +551,12 @@ func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) {
 		Diag("%s: elf %s unimplemented", pn, Thestring)
 		return
 
+	case '0':
+		if elfobj.machine != ElfMachMips || hdr.Ident[4] != ElfClass64 {
+			Diag("%s: elf object but not mips64", pn)
+			return
+		}
+
 	case '5':
 		if e != binary.LittleEndian || elfobj.machine != ElfMachArm || hdr.Ident[4] != ElfClass32 {
 			Diag("%s: elf object but not arm", pn)
@@ -549,6 +685,12 @@ func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) {
 	// create symbols for elfmapped sections
 	for i := 0; uint(i) < elfobj.nsect; i++ {
 		sect = &elfobj.sect[i]
+		if sect.type_ == SHT_ARM_ATTRIBUTES && sect.name == ".ARM.attributes" {
+			if err = elfmap(elfobj, sect); err != nil {
+				goto bad
+			}
+			parseArmAttributes(e, sect.base[:sect.size])
+		}
 		if (sect.type_ != ElfSectProgbits && sect.type_ != ElfSectNobits) || sect.flags&ElfSectFlagAlloc == 0 {
 			continue
 		}
@@ -629,6 +771,13 @@ func ldelf(f *obj.Biobuf, pkg string, length int64, pn string) {
 			if strings.HasPrefix(sym.name, ".Linfo_string") { // clang does this
 				continue
 			}
+
+			if sym.name == "" && sym.type_ == 0 && sect.name == ".debug_str" {
+				// This reportedly happens with clang 3.7 on ARM.
+				// See issue 13139.
+				continue
+			}
+
 			Diag("%s: sym#%d: ignoring %s in section %d (type %d)", pn, i, sym.name, sym.shndx, sym.type_)
 			continue
 		}
@@ -927,7 +1076,7 @@ func readelfsym(elfobj *ElfObj, i int, sym *ElfSym, needSym int) (err error) {
 
 		case ElfSymBindWeak:
 			if needSym != 0 {
-				s = linknewsym(Ctxt, sym.name, 0)
+				s = Linklookup(Ctxt, sym.name, 0)
 				if sym.other == 2 {
 					s.Type |= obj.SHIDDEN
 				}
@@ -1010,7 +1159,8 @@ func reltype(pn string, elftype int, siz *uint8) int {
 		'8' | R_386_GOTOFF<<24,
 		'8' | R_386_GOTPC<<24,
 		'8' | R_386_GOT32X<<24,
-		'9' | R_PPC64_REL24<<24:
+		'9' | R_PPC64_REL24<<24,
+		'9' | R_PPC_REL32<<24:
 		*siz = 4
 
 	case '6' | R_X86_64_64<<24,
diff --git a/src/cmd/link/internal/ld/ldpe.go b/src/cmd/link/internal/ld/ldpe.go
index b98cf02..8439c06 100644
--- a/src/cmd/link/internal/ld/ldpe.go
+++ b/src/cmd/link/internal/ld/ldpe.go
@@ -10,6 +10,7 @@ import (
 	"fmt"
 	"log"
 	"sort"
+	"strconv"
 	"strings"
 )
 
@@ -191,8 +192,8 @@ func ldpe(f *obj.Biobuf, pkg string, length int64, pn string) {
 		if peobj.sect[i].name[0] != '/' {
 			continue
 		}
-		l = uint32(obj.Atoi(peobj.sect[i].name[1:]))
-		peobj.sect[i].name = cstring(peobj.snames[l:])
+		n, _ := strconv.Atoi(peobj.sect[i].name[1:])
+		peobj.sect[i].name = cstring(peobj.snames[n:])
 	}
 
 	// read symbols
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index a9ec3d2..bdfa056 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -46,6 +46,7 @@ import (
 	"path/filepath"
 	"runtime"
 	"strings"
+	"sync"
 )
 
 // Data layout and relocation.
@@ -142,7 +143,6 @@ var (
 // use in debuggers and such.
 
 const (
-	MAXIO   = 8192
 	MINFUNC = 16 // minimum size for a function
 )
 
@@ -175,6 +175,17 @@ func DynlinkingGo() bool {
 	return Buildmode == BuildmodeShared || Linkshared
 }
 
+// UseRelro returns whether to make use of "read only relocations" aka
+// relro.
+func UseRelro() bool {
+	switch Buildmode {
+	case BuildmodeCShared, BuildmodeShared, BuildmodePIE:
+		return Iself
+	default:
+		return false
+	}
+}
+
 var (
 	Thestring          string
 	Thelinkarch        *LinkArch
@@ -188,6 +199,7 @@ var (
 	elfglobalsymndx    int
 	flag_installsuffix string
 	flag_race          int
+	flag_msan          int
 	Buildmode          BuildMode
 	Linkshared         bool
 	tracksym           string
@@ -195,6 +207,8 @@ var (
 	tmpdir             string
 	extld              string
 	extldflags         string
+	extar              string
+	libgccfile         string
 	debug_s            int // backup old value of debug['s']
 	Ctxt               *Link
 	HEADR              int32
@@ -242,12 +256,6 @@ var coutbuf struct {
 }
 
 const (
-	// Whether to assume that the external linker is "gold"
-	// (http://sourceware.org/ml/binutils/2008-03/msg00162.html).
-	AssumeGoldLinker = 0
-)
-
-const (
 	symname = "__.GOSYMDEF"
 	pkgname = "__.PKGDEF"
 )
@@ -279,6 +287,7 @@ type BuildMode uint8
 const (
 	BuildmodeUnset BuildMode = iota
 	BuildmodeExe
+	BuildmodePIE
 	BuildmodeCArchive
 	BuildmodeCShared
 	BuildmodeShared
@@ -295,6 +304,13 @@ func (mode *BuildMode) Set(s string) error {
 		return fmt.Errorf("invalid buildmode: %q", s)
 	case "exe":
 		*mode = BuildmodeExe
+	case "pie":
+		switch goos {
+		case "android", "linux":
+		default:
+			return badmode()
+		}
+		*mode = BuildmodePIE
 	case "c-archive":
 		switch goos {
 		case "darwin", "linux":
@@ -303,12 +319,21 @@ func (mode *BuildMode) Set(s string) error {
 		}
 		*mode = BuildmodeCArchive
 	case "c-shared":
-		if goarch != "amd64" && goarch != "arm" {
+		switch goarch {
+		case "386", "amd64", "arm", "arm64":
+		default:
 			return badmode()
 		}
 		*mode = BuildmodeCShared
 	case "shared":
-		if goos != "linux" || goarch != "amd64" {
+		switch goos {
+		case "linux":
+			switch goarch {
+			case "386", "amd64", "arm", "arm64", "ppc64le":
+			default:
+				return badmode()
+			}
+		default:
 			return badmode()
 		}
 		*mode = BuildmodeShared
@@ -322,6 +347,8 @@ func (mode *BuildMode) String() string {
 		return "" // avoid showing a default in usage message
 	case BuildmodeExe:
 		return "exe"
+	case BuildmodePIE:
+		return "pie"
 	case BuildmodeCArchive:
 		return "c-archive"
 	case BuildmodeCShared:
@@ -359,6 +386,9 @@ func libinit() {
 	} else if flag_race != 0 {
 		suffixsep = "_"
 		suffix = "race"
+	} else if flag_msan != 0 {
+		suffixsep = "_"
+		suffix = "msan"
 	}
 
 	Lflag(fmt.Sprintf("%s/pkg/%s_%s%s%s", goroot, goos, goarch, suffixsep, suffix))
@@ -376,7 +406,7 @@ func libinit() {
 		switch Buildmode {
 		case BuildmodeCShared, BuildmodeCArchive:
 			INITENTRY = fmt.Sprintf("_rt0_%s_%s_lib", goarch, goos)
-		case BuildmodeExe:
+		case BuildmodeExe, BuildmodePIE:
 			INITENTRY = fmt.Sprintf("_rt0_%s_%s", goarch, goos)
 		case BuildmodeShared:
 			// No INITENTRY for -buildmode=shared
@@ -428,7 +458,7 @@ func loadinternal(name string) {
 			if Debug['v'] != 0 {
 				fmt.Fprintf(&Bso, "searching for %s.a in %s\n", name, shlibname)
 			}
-			if obj.Access(shlibname, obj.AEXIST) >= 0 {
+			if _, err := os.Stat(shlibname); err == nil {
 				addlibpath(Ctxt, "internal", "internal", "", name, shlibname)
 				found = 1
 				break
@@ -438,7 +468,7 @@ func loadinternal(name string) {
 		if Debug['v'] != 0 {
 			fmt.Fprintf(&Bso, "searching for %s.a in %s\n", name, pname)
 		}
-		if obj.Access(pname, obj.AEXIST) >= 0 {
+		if _, err := os.Stat(pname); err == nil {
 			addlibpath(Ctxt, "internal", "internal", pname, name, "")
 			found = 1
 			break
@@ -469,17 +499,27 @@ func loadlib() {
 	if flag_race != 0 {
 		loadinternal("runtime/race")
 	}
+	if flag_msan != 0 {
+		loadinternal("runtime/msan")
+	}
 
 	var i int
 	for i = 0; i < len(Ctxt.Library); i++ {
-		if Debug['v'] > 1 {
-			fmt.Fprintf(&Bso, "%5.2f autolib: %s (from %s)\n", obj.Cputime(), Ctxt.Library[i].File, Ctxt.Library[i].Objref)
-		}
 		iscgo = iscgo || Ctxt.Library[i].Pkg == "runtime/cgo"
+		if Ctxt.Library[i].Shlib == "" {
+			if Debug['v'] > 1 {
+				fmt.Fprintf(&Bso, "%5.2f autolib: %s (from %s)\n", obj.Cputime(), Ctxt.Library[i].File, Ctxt.Library[i].Objref)
+			}
+			objfile(Ctxt.Library[i])
+		}
+	}
+
+	for i = 0; i < len(Ctxt.Library); i++ {
 		if Ctxt.Library[i].Shlib != "" {
+			if Debug['v'] > 1 {
+				fmt.Fprintf(&Bso, "%5.2f autolib: %s (from %s)\n", obj.Cputime(), Ctxt.Library[i].Shlib, Ctxt.Library[i].Objref)
+			}
 			ldshlibsyms(Ctxt.Library[i].Shlib)
-		} else {
-			objfile(Ctxt.Library[i])
 		}
 	}
 
@@ -495,6 +535,12 @@ func loadlib() {
 			Linkmode = LinkExternal
 		}
 
+		// Force external linking for PIE executables, as
+		// internal linking does not support TLS_IE.
+		if Buildmode == BuildmodePIE {
+			Linkmode = LinkExternal
+		}
+
 		// cgo on Darwin must use external linking
 		// we can always use external linking, but then there will be circular
 		// dependency problems when compiling natively (external linking requires
@@ -503,6 +549,11 @@ func loadlib() {
 		if (Thearch.Thechar == '5' || Thearch.Thechar == '7') && HEADTYPE == obj.Hdarwin && iscgo {
 			Linkmode = LinkExternal
 		}
+
+		// Force external linking for msan.
+		if flag_msan != 0 {
+			Linkmode = LinkExternal
+		}
 	}
 
 	// cmd/7l doesn't support cgo internal linking
@@ -550,20 +601,47 @@ func loadlib() {
 
 	tlsg := Linklookup(Ctxt, "runtime.tlsg", 0)
 
-	// For most ports, runtime.tlsg is a placeholder symbol for TLS
-	// relocation. However, the Android and Darwin arm ports need it
-	// to be a real variable.
-	//
-	// TODO(crawshaw): android should require leaving the tlsg->type
-	// alone (as the runtime-provided SNOPTRBSS) just like darwin/arm.
-	// But some other part of the linker is expecting STLSBSS.
-	if tlsg.Type != obj.SDYNIMPORT && (goos != "darwin" || Thearch.Thechar != '5') {
+	// runtime.tlsg is used for external linking on platforms that do not define
+	// a variable to hold g in assembly (currently only intel).
+	if tlsg.Type == 0 {
 		tlsg.Type = obj.STLSBSS
+		tlsg.Size = int64(Thearch.Ptrsize)
+	} else if tlsg.Type != obj.SDYNIMPORT {
+		Diag("internal error: runtime declared tlsg variable %d", tlsg.Type)
 	}
-	tlsg.Size = int64(Thearch.Ptrsize)
 	tlsg.Reachable = true
 	Ctxt.Tlsg = tlsg
 
+	moduledata := Linklookup(Ctxt, "runtime.firstmoduledata", 0)
+	if moduledata.Type != 0 && moduledata.Type != obj.SDYNIMPORT {
+		// If the module (toolchain-speak for "executable or shared
+		// library") we are linking contains the runtime package, it
+		// will define the runtime.firstmoduledata symbol and we
+		// truncate it back to 0 bytes so we can define its entire
+		// contents in symtab.go:symtab().
+		moduledata.Size = 0
+
+		// In addition, on ARM, the runtime depends on the linker
+		// recording the value of GOARM.
+		if Thearch.Thechar == '5' {
+			s := Linklookup(Ctxt, "runtime.goarm", 0)
+
+			s.Type = obj.SRODATA
+			s.Size = 0
+			Adduint8(Ctxt, s, uint8(Ctxt.Goarm))
+		}
+	} else {
+		// If OTOH the module does not contain the runtime package,
+		// create a local symbol for the moduledata.
+		moduledata = Linklookup(Ctxt, "local.moduledata", 0)
+		moduledata.Local = true
+	}
+	// In all cases way we mark the moduledata as noptrdata to hide it from
+	// the GC.
+	moduledata.Type = obj.SNOPTRDATA
+	moduledata.Reachable = true
+	Ctxt.Moduledata = moduledata
+
 	// Now that we know the link mode, trim the dynexp list.
 	x := CgoExportDynamic
 
@@ -582,6 +660,44 @@ func loadlib() {
 	// In internal link mode, read the host object files.
 	if Linkmode == LinkInternal {
 		hostobjs()
+
+		// If we have any undefined symbols in external
+		// objects, try to read them from the libgcc file.
+		any := false
+		for s := Ctxt.Allsym; s != nil; s = s.Allsym {
+			for _, r := range s.R {
+				if r.Sym != nil && r.Sym.Type&obj.SMASK == obj.SXREF && r.Sym.Name != ".got" {
+					any = true
+					break
+				}
+			}
+		}
+		if any {
+			if libgccfile == "" {
+				if extld == "" {
+					extld = "gcc"
+				}
+				args := hostlinkArchArgs()
+				args = append(args, "--print-libgcc-file-name")
+				if Debug['v'] != 0 {
+					fmt.Fprintf(&Bso, "%s %v\n", extld, args)
+				}
+				out, err := exec.Command(extld, args...).Output()
+				if err != nil {
+					if Debug['v'] != 0 {
+						fmt.Fprintln(&Bso, "not using a libgcc file because compiler failed")
+						fmt.Fprintf(&Bso, "%v\n%s\n", err, out)
+					}
+					libgccfile = "none"
+				} else {
+					libgccfile = strings.TrimSpace(string(out))
+				}
+			}
+
+			if libgccfile != "none" {
+				hostArchive(libgccfile)
+			}
+		}
 	} else {
 		hostlinksetup()
 	}
@@ -597,8 +713,11 @@ func loadlib() {
 	// binaries, so leave it enabled on OS X (Mach-O) binaries.
 	// Also leave it enabled on Solaris which doesn't support
 	// statically linked binaries.
-	if Buildmode == BuildmodeExe && havedynamic == 0 && HEADTYPE != obj.Hdarwin && HEADTYPE != obj.Hsolaris {
-		Debug['d'] = 1
+	switch Buildmode {
+	case BuildmodeExe, BuildmodePIE:
+		if havedynamic == 0 && HEADTYPE != obj.Hdarwin && HEADTYPE != obj.Hsolaris {
+			Debug['d'] = 1
+		}
 	}
 
 	importcycles()
@@ -698,9 +817,7 @@ func objfile(lib *Library) {
 
 	off += l
 
-	if Debug['u'] != 0 {
-		ldpkg(f, pkg, atolwhex(arhdr.size), lib.File, Pkgdef)
-	}
+	ldpkg(f, pkg, atolwhex(arhdr.size), lib.File, Pkgdef)
 
 	/*
 	 * load all the object files from the archive now.
@@ -753,9 +870,10 @@ var internalpkg = []string{
 	"os/user",
 	"runtime/cgo",
 	"runtime/race",
+	"runtime/msan",
 }
 
-func ldhostobj(ld func(*obj.Biobuf, string, int64, string), f *obj.Biobuf, pkg string, length int64, pn string, file string) {
+func ldhostobj(ld func(*obj.Biobuf, string, int64, string), f *obj.Biobuf, pkg string, length int64, pn string, file string) *Hostobj {
 	isinternal := false
 	for i := 0; i < len(internalpkg); i++ {
 		if pkg == internalpkg[i] {
@@ -788,6 +906,7 @@ func ldhostobj(ld func(*obj.Biobuf, string, int64, string), f *obj.Biobuf, pkg s
 	h.file = file
 	h.off = obj.Boffset(f)
 	h.length = length
+	return h
 }
 
 func hostobjs() {
@@ -853,28 +972,41 @@ func hostlinksetup() {
 // hostobjCopy creates a copy of the object files in hostobj in a
 // temporary directory.
 func hostobjCopy() (paths []string) {
+	var wg sync.WaitGroup
+	sema := make(chan struct{}, runtime.NumCPU()) // limit open file descriptors
 	for i, h := range hostobj {
-		f, err := os.Open(h.file)
-		if err != nil {
-			Exitf("cannot reopen %s: %v", h.pn, err)
-		}
-		if _, err := f.Seek(h.off, 0); err != nil {
-			Exitf("cannot seek %s: %v", h.pn, err)
-		}
+		h := h
+		dst := fmt.Sprintf("%s/%06d.o", tmpdir, i)
+		paths = append(paths, dst)
+
+		wg.Add(1)
+		go func() {
+			sema <- struct{}{}
+			defer func() {
+				<-sema
+				wg.Done()
+			}()
+			f, err := os.Open(h.file)
+			if err != nil {
+				Exitf("cannot reopen %s: %v", h.pn, err)
+			}
+			if _, err := f.Seek(h.off, 0); err != nil {
+				Exitf("cannot seek %s: %v", h.pn, err)
+			}
 
-		p := fmt.Sprintf("%s/%06d.o", tmpdir, i)
-		paths = append(paths, p)
-		w, err := os.Create(p)
-		if err != nil {
-			Exitf("cannot create %s: %v", p, err)
-		}
-		if _, err := io.CopyN(w, f, h.length); err != nil {
-			Exitf("cannot write %s: %v", p, err)
-		}
-		if err := w.Close(); err != nil {
-			Exitf("cannot close %s: %v", p, err)
-		}
+			w, err := os.Create(dst)
+			if err != nil {
+				Exitf("cannot create %s: %v", dst, err)
+			}
+			if _, err := io.CopyN(w, f, h.length); err != nil {
+				Exitf("cannot write %s: %v", dst, err)
+			}
+			if err := w.Close(); err != nil {
+				Exitf("cannot close %s: %v", dst, err)
+			}
+		}()
 	}
+	wg.Wait()
 	return paths
 }
 
@@ -884,8 +1016,12 @@ func archive() {
 		return
 	}
 
+	if extar == "" {
+		extar = "ar"
+	}
+
 	mayberemoveoutfile()
-	argv := []string{"ar", "-q", "-c", "-s", outfile}
+	argv := []string{extar, "-q", "-c", "-s", outfile}
 	argv = append(argv, fmt.Sprintf("%s/go.o", tmpdir))
 	argv = append(argv, hostobjCopy()...)
 
@@ -913,19 +1049,7 @@ func hostlink() {
 
 	var argv []string
 	argv = append(argv, extld)
-	switch Thearch.Thechar {
-	case '8':
-		argv = append(argv, "-m32")
-
-	case '6', '9':
-		argv = append(argv, "-m64")
-
-	case '5':
-		argv = append(argv, "-marm")
-
-	case '7':
-		// nothing needed
-	}
+	argv = append(argv, hostlinkArchArgs()...)
 
 	if Debug['s'] == 0 && debug_s == 0 {
 		argv = append(argv, "-gdwarf-2")
@@ -947,35 +1071,34 @@ func hostlink() {
 		}
 	}
 
-	if Iself && AssumeGoldLinker != 0 /*TypeKind(100016)*/ {
-		argv = append(argv, "-Wl,--rosegment")
-	}
-
 	switch Buildmode {
 	case BuildmodeExe:
 		if HEADTYPE == obj.Hdarwin {
 			argv = append(argv, "-Wl,-pagezero_size,4000000")
 		}
+	case BuildmodePIE:
+		argv = append(argv, "-pie")
 	case BuildmodeCShared:
 		if HEADTYPE == obj.Hdarwin {
-			argv = append(argv, "-dynamiclib")
+			argv = append(argv, "-dynamiclib", "-Wl,-read_only_relocs,suppress")
 		} else {
+			// ELF.
 			argv = append(argv, "-Wl,-Bsymbolic")
-			argv = append(argv, "-shared")
+			if UseRelro() {
+				argv = append(argv, "-Wl,-z,relro")
+			}
+			// Pass -z nodelete to mark the shared library as
+			// non-closeable: a dlclose will do nothing.
+			argv = append(argv, "-shared", "-Wl,-z,nodelete")
 		}
 	case BuildmodeShared:
-		// TODO(mwhudson): unless you do this, dynamic relocations fill
-		// out the findfunctab table and for some reason shared libraries
-		// and the executable both define a main function and putting the
-		// address of executable's main into the shared libraries
-		// findfunctab violates the assumptions of the runtime.  TBH, I
-		// think we may well end up wanting to use -Bsymbolic here
-		// anyway.
-		argv = append(argv, "-Wl,-Bsymbolic-functions")
+		if UseRelro() {
+			argv = append(argv, "-Wl,-z,relro")
+		}
 		argv = append(argv, "-shared")
 	}
 
-	if Linkshared && Iself {
+	if Iself && DynlinkingGo() {
 		// We force all symbol resolution to be done at program startup
 		// because lazy PLT resolution can use large amounts of stack at
 		// times we cannot allow it to do so.
@@ -1095,6 +1218,10 @@ func hostlink() {
 				Ctxt.Cursym = nil
 				Exitf("%s: running dsymutil failed: %v\n%s", os.Args[0], err, out)
 			}
+			// Skip combining if `dsymutil` didn't generate a file. See #11994.
+			if _, err := os.Stat(dsym); os.IsNotExist(err) {
+				return
+			}
 			// For os.Rename to work reliably, must be in same directory as outfile.
 			combinedOutput := outfile + "~"
 			if err := machoCombineDwarf(outfile, dsym, combinedOutput); err != nil {
@@ -1110,7 +1237,26 @@ func hostlink() {
 	}
 }
 
-func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, whence int) {
+// hostlinkArchArgs returns arguments to pass to the external linker
+// based on the architecture.
+func hostlinkArchArgs() []string {
+	switch Thearch.Thechar {
+	case '8':
+		return []string{"-m32"}
+	case '6', '9':
+		return []string{"-m64"}
+	case '5':
+		return []string{"-marm"}
+	case '7':
+		// nothing needed
+	}
+	return nil
+}
+
+// ldobj loads an input object.  If it is a host object (an object
+// compiled by a non-Go compiler) it returns the Hostobj pointer.  If
+// it is a Go object, it returns nil.
+func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, whence int) *Hostobj {
 	eof := obj.Boffset(f) + length
 
 	start := obj.Boffset(f)
@@ -1122,18 +1268,15 @@ func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, when
 
 	magic := uint32(c1)<<24 | uint32(c2)<<16 | uint32(c3)<<8 | uint32(c4)
 	if magic == 0x7f454c46 { // \x7F E L F
-		ldhostobj(ldelf, f, pkg, length, pn, file)
-		return
+		return ldhostobj(ldelf, f, pkg, length, pn, file)
 	}
 
 	if magic&^1 == 0xfeedface || magic&^0x01000000 == 0xcefaedfe {
-		ldhostobj(ldmacho, f, pkg, length, pn, file)
-		return
+		return ldhostobj(ldmacho, f, pkg, length, pn, file)
 	}
 
 	if c1 == 0x4c && c2 == 0x01 || c1 == 0x64 && c2 == 0x86 {
-		ldhostobj(ldpe, f, pkg, length, pn, file)
-		return
+		return ldhostobj(ldpe, f, pkg, length, pn, file)
 	}
 
 	/* check the header */
@@ -1141,10 +1284,10 @@ func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, when
 	if line == "" {
 		if obj.Blinelen(f) > 0 {
 			Diag("%s: not an object file", pn)
-			return
+			return nil
 		}
 		Diag("truncated object file: %s", pn)
-		return
+		return nil
 	}
 
 	if !strings.HasPrefix(line, "go object ") {
@@ -1155,11 +1298,11 @@ func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, when
 		if line == Thestring {
 			// old header format: just $GOOS
 			Diag("%s: stale object file", pn)
-			return
+			return nil
 		}
 
 		Diag("%s: not an object file", pn)
-		return
+		return nil
 	}
 
 	// First, check that the basic goos, goarch, and version match.
@@ -1168,7 +1311,7 @@ func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, when
 	line = strings.TrimRight(line, "\n")
 	if !strings.HasPrefix(line[10:]+" ", t) && Debug['f'] == 0 {
 		Diag("%s: object is [%s] expected [%s]", pn, line[10:], t)
-		return
+		return nil
 	}
 
 	// Second, check that longer lines match each other exactly,
@@ -1179,7 +1322,7 @@ func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, when
 			theline = line[10:]
 		} else if theline != line[10:] {
 			Diag("%s: object is [%s] expected [%s]", pn, line[10:], theline)
-			return
+			return nil
 		}
 	}
 
@@ -1195,7 +1338,7 @@ func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, when
 		c3 = obj.Bgetc(f)
 		if c3 == obj.Beof {
 			Diag("truncated object file: %s", pn)
-			return
+			return nil
 		}
 	}
 
@@ -1206,6 +1349,7 @@ func ldobj(f *obj.Biobuf, pkg string, length int64, pn string, file string, when
 	obj.Bseek(f, import1, 0)
 
 	ldobjfile(Ctxt, f, pkg, eof-obj.Boffset(f), pn)
+	return nil
 }
 
 func readelfsymboldata(f *elf.File, sym *elf.Symbol) []byte {
@@ -1244,23 +1388,23 @@ func readnote(f *elf.File, name []byte, typ int32) ([]byte, error) {
 				if err == io.EOF {
 					break
 				}
-				return nil, fmt.Errorf("read namesize failed:", err)
+				return nil, fmt.Errorf("read namesize failed: %v", err)
 			}
 			err = binary.Read(r, f.ByteOrder, &descsize)
 			if err != nil {
-				return nil, fmt.Errorf("read descsize failed:", err)
+				return nil, fmt.Errorf("read descsize failed: %v", err)
 			}
 			err = binary.Read(r, f.ByteOrder, &noteType)
 			if err != nil {
-				return nil, fmt.Errorf("read type failed:", err)
+				return nil, fmt.Errorf("read type failed: %v", err)
 			}
 			noteName, err := readwithpad(r, namesize)
 			if err != nil {
-				return nil, fmt.Errorf("read name failed:", err)
+				return nil, fmt.Errorf("read name failed: %v", err)
 			}
 			desc, err := readwithpad(r, descsize)
 			if err != nil {
-				return nil, fmt.Errorf("read desc failed:", err)
+				return nil, fmt.Errorf("read desc failed: %v", err)
 			}
 			if string(name) == string(noteName) && typ == noteType {
 				return desc, nil
@@ -1320,23 +1464,17 @@ func ldshlibsyms(shlib string) {
 		Diag("cannot read symbols from shared library: %s", libpath)
 		return
 	}
+	gcdata_locations := make(map[uint64]*LSym)
 	for _, elfsym := range syms {
 		if elf.ST_TYPE(elfsym.Info) == elf.STT_NOTYPE || elf.ST_TYPE(elfsym.Info) == elf.STT_SECTION {
 			continue
 		}
 		lsym := Linklookup(Ctxt, elfsym.Name, 0)
-		if lsym.Type != 0 && lsym.Type != obj.SDYNIMPORT && lsym.Dupok == 0 {
-			if (lsym.Type != obj.SBSS && lsym.Type != obj.SNOPTRBSS) || len(lsym.R) != 0 || len(lsym.P) != 0 || f.Sections[elfsym.Section].Type != elf.SHT_NOBITS {
-				Diag("Found duplicate symbol %s reading from %s, first found in %s", elfsym.Name, shlib, lsym.File)
-			}
-			if lsym.Size > int64(elfsym.Size) {
-				// If the existing symbol is a BSS value that is
-				// larger than the one read from the shared library,
-				// keep references to that.  Conversely, if the
-				// version from the shared libray is larger, we want
-				// to make all references be to that.
-				continue
-			}
+		// Because loadlib above loads all .a files before loading any shared
+		// libraries, any symbols we find that duplicate symbols already
+		// loaded should be ignored (the symbols from the .a files "win").
+		if lsym.Type != 0 {
+			continue
 		}
 		lsym.Type = obj.SDYNIMPORT
 		lsym.ElfType = elf.ST_TYPE(elfsym.Info)
@@ -1348,6 +1486,32 @@ func ldshlibsyms(shlib string) {
 			// the type data.
 			if strings.HasPrefix(lsym.Name, "type.") && !strings.HasPrefix(lsym.Name, "type..") {
 				lsym.P = readelfsymboldata(f, &elfsym)
+				gcdata_locations[elfsym.Value+2*uint64(Thearch.Ptrsize)+8+1*uint64(Thearch.Ptrsize)] = lsym
+			}
+		}
+	}
+	gcdata_addresses := make(map[*LSym]uint64)
+	if Thearch.Thechar == '7' {
+		for _, sect := range f.Sections {
+			if sect.Type == elf.SHT_RELA {
+				var rela elf.Rela64
+				rdr := sect.Open()
+				for {
+					err := binary.Read(rdr, f.ByteOrder, &rela)
+					if err == io.EOF {
+						break
+					} else if err != nil {
+						Diag("reading relocation failed %v", err)
+						return
+					}
+					t := elf.R_AARCH64(rela.Info & 0xffff)
+					if t != elf.R_AARCH64_RELATIVE {
+						continue
+					}
+					if lsym, ok := gcdata_locations[rela.Off]; ok {
+						gcdata_addresses[lsym] = uint64(rela.Addend)
+					}
+				}
 			}
 		}
 	}
@@ -1379,7 +1543,7 @@ func ldshlibsyms(shlib string) {
 		Ctxt.Etextp = last
 	}
 
-	Ctxt.Shlibs = append(Ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f})
+	Ctxt.Shlibs = append(Ctxt.Shlibs, Shlib{Path: libpath, Hash: hash, Deps: deps, File: f, gcdata_addresses: gcdata_addresses})
 }
 
 func mywhatsys() {
@@ -1455,10 +1619,6 @@ func Be32(b []byte) uint32 {
 	return uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])
 }
 
-func Be64(b []byte) uint64 {
-	return uint64(Be32(b))<<32 | uint64(Be32(b[4:]))
-}
-
 type Chain struct {
 	sym   *LSym
 	up    *Chain
@@ -1471,7 +1631,7 @@ var morestack *LSym
 // allow stack checks here.
 
 func haslinkregister() bool {
-	return Thearch.Thechar == '5' || Thearch.Thechar == '9' || Thearch.Thechar == '7'
+	return Ctxt.FixedFrameSize() != 0
 }
 
 func callsize() int {
@@ -1548,7 +1708,8 @@ func stkcheck(up *Chain, depth int) int {
 		// should never be called directly.
 		// only diagnose the direct caller.
 		// TODO(mwhudson): actually think about this.
-		if depth == 1 && s.Type != obj.SXREF && !DynlinkingGo() {
+		if depth == 1 && s.Type != obj.SXREF && !DynlinkingGo() &&
+			Buildmode != BuildmodePIE && Buildmode != BuildmodeCShared {
 			Diag("call to external function %s", s.Name)
 		}
 		return -1
@@ -1579,10 +1740,7 @@ func stkcheck(up *Chain, depth int) int {
 			return 0
 		}
 		// Raise limit to allow frame.
-		limit = int(obj.StackLimit + s.Locals)
-		if haslinkregister() {
-			limit += Thearch.Regsize
-		}
+		limit = int(obj.StackLimit+s.Locals) + int(Ctxt.FixedFrameSize())
 	}
 
 	// Walk through sp adjustments in function, consuming relocs.
@@ -1606,7 +1764,7 @@ func stkcheck(up *Chain, depth int) int {
 			r = &s.R[ri]
 			switch r.Type {
 			// Direct call.
-			case obj.R_CALL, obj.R_CALLARM, obj.R_CALLARM64, obj.R_CALLPOWER:
+			case obj.R_CALL, obj.R_CALLARM, obj.R_CALLARM64, obj.R_CALLPOWER, obj.R_CALLMIPS:
 				ch.limit = int(int32(limit) - pcsp.value - int32(callsize()))
 				ch.sym = r.Sym
 				if stkcheck(&ch, depth+1) < 0 {
@@ -1670,33 +1828,6 @@ func stkprint(ch *Chain, limit int) {
 	}
 }
 
-func Yconv(s *LSym) string {
-	var fp string
-
-	if s == nil {
-		fp += fmt.Sprintf("<nil>")
-	} else {
-		fmt_ := ""
-		fmt_ += fmt.Sprintf("%s @0x%08x [%d]", s.Name, int64(s.Value), int64(s.Size))
-		for i := 0; int64(i) < s.Size; i++ {
-			if i%8 == 0 {
-				fmt_ += fmt.Sprintf("\n\t0x%04x ", i)
-			}
-			fmt_ += fmt.Sprintf("%02x ", s.P[i])
-		}
-
-		fmt_ += fmt.Sprintf("\n")
-		for i := 0; i < len(s.R); i++ {
-			fmt_ += fmt.Sprintf("\t0x%04x[%x] %d %s[%x]\n", s.R[i].Off, s.R[i].Siz, s.R[i].Type, s.R[i].Sym.Name, int64(s.R[i].Add))
-		}
-
-		str := fmt_
-		fp += str
-	}
-
-	return fp
-}
-
 func Cflush() {
 	if err := coutbuf.Writer.Flush(); err != nil {
 		Exitf("flushing %s: %v", coutbuf.f.Name(), err)
@@ -1765,7 +1896,7 @@ func genasmsym(put func(*LSym, string, int, int64, int64, int, *LSym)) {
 	}
 
 	for s := Ctxt.Allsym; s != nil; s = s.Allsym {
-		if s.Hide != 0 || (s.Name[0] == '.' && s.Version == 0 && s.Name != ".rathole") {
+		if s.Hide != 0 || ((s.Name == "" || s.Name[0] == '.') && s.Version == 0 && s.Name != ".rathole" && s.Name != ".TOC.") {
 			continue
 		}
 		switch s.Type & obj.SMASK {
@@ -1783,6 +1914,13 @@ func genasmsym(put func(*LSym, string, int, int64, int64, int, *LSym)) {
 			obj.SGOSTRING,
 			obj.SGOFUNC,
 			obj.SGCBITS,
+			obj.STYPERELRO,
+			obj.SSTRINGRELRO,
+			obj.SGOSTRINGRELRO,
+			obj.SGOFUNCRELRO,
+			obj.SGCBITSRELRO,
+			obj.SRODATARELRO,
+			obj.STYPELINK,
 			obj.SWINDOWS:
 			if !s.Reachable {
 				continue
@@ -1814,13 +1952,7 @@ func genasmsym(put func(*LSym, string, int, int64, int64, int, *LSym)) {
 
 		case obj.STLSBSS:
 			if Linkmode == LinkExternal && HEADTYPE != obj.Hopenbsd {
-				var type_ int
-				if goos == "android" {
-					type_ = 'B'
-				} else {
-					type_ = 't'
-				}
-				put(s, s.Name, type_, Symaddr(s), s.Size, int(s.Version), s.Gotype)
+				put(s, s.Name, 't', Symaddr(s), s.Size, int(s.Version), s.Gotype)
 			}
 		}
 	}
@@ -1954,7 +2086,7 @@ func callgraph() {
 			if r.Sym == nil {
 				continue
 			}
-			if (r.Type == obj.R_CALL || r.Type == obj.R_CALLARM || r.Type == obj.R_CALLPOWER) && r.Sym.Type == obj.STEXT {
+			if (r.Type == obj.R_CALL || r.Type == obj.R_CALLARM || r.Type == obj.R_CALLPOWER || r.Type == obj.R_CALLMIPS) && r.Sym.Type == obj.STEXT {
 				fmt.Fprintf(&Bso, "%s calls %s\n", s.Name, r.Sym.Name)
 			}
 		}
diff --git a/src/cmd/link/internal/ld/link.go b/src/cmd/link/internal/ld/link.go
index 33b17c5..73d23c6 100644
--- a/src/cmd/link/internal/ld/link.go
+++ b/src/cmd/link/internal/ld/link.go
@@ -63,11 +63,11 @@ type LSym struct {
 	Got         int32
 	Align       int32
 	Elfsym      int32
+	LocalElfsym int32
 	Args        int32
 	Locals      int32
 	Value       int64
 	Size        int64
-	Hash        *LSym
 	Allsym      *LSym
 	Next        *LSym
 	Sub         *LSym
@@ -93,6 +93,16 @@ func (s *LSym) String() string {
 	return fmt.Sprintf("%s<%d>", s.Name, s.Version)
 }
 
+func (s *LSym) ElfsymForReloc() int32 {
+	// If putelfsym created a local version of this symbol, use that in all
+	// relocations.
+	if s.LocalElfsym != 0 {
+		return s.LocalElfsym
+	} else {
+		return s.Elfsym
+	}
+}
+
 type Reloc struct {
 	Off     int32
 	Siz     uint8
@@ -114,38 +124,57 @@ type Auto struct {
 }
 
 type Shlib struct {
-	Path string
-	Hash []byte
-	Deps []string
-	File *elf.File
+	Path             string
+	Hash             []byte
+	Deps             []string
+	File             *elf.File
+	gcdata_addresses map[*LSym]uint64
 }
 
 type Link struct {
-	Thechar   int32
-	Thestring string
-	Goarm     int32
-	Headtype  int
-	Arch      *LinkArch
-	Debugasm  int32
-	Debugvlog int32
-	Bso       *obj.Biobuf
-	Windows   int32
-	Goroot    string
-	Hash      map[symVer]*LSym
-	Allsym    *LSym
-	Nsymbol   int32
-	Tlsg      *LSym
-	Libdir    []string
-	Library   []*Library
-	Shlibs    []Shlib
-	Tlsoffset int
-	Diag      func(string, ...interface{})
-	Cursym    *LSym
-	Version   int
-	Textp     *LSym
-	Etextp    *LSym
-	Nhistfile int32
-	Filesyms  *LSym
+	Thechar    int32
+	Thestring  string
+	Goarm      int32
+	Headtype   int
+	Arch       *LinkArch
+	Debugasm   int32
+	Debugvlog  int32
+	Bso        *obj.Biobuf
+	Windows    int32
+	Goroot     string
+	Hash       map[symVer]*LSym
+	Allsym     *LSym
+	Nsymbol    int32
+	Tlsg       *LSym
+	Libdir     []string
+	Library    []*Library
+	Shlibs     []Shlib
+	Tlsoffset  int
+	Diag       func(string, ...interface{})
+	Cursym     *LSym
+	Version    int
+	Textp      *LSym
+	Etextp     *LSym
+	Nhistfile  int32
+	Filesyms   *LSym
+	Moduledata *LSym
+}
+
+// The smallest possible offset from the hardware stack pointer to a local
+// variable on the stack. Architectures that use a link register save its value
+// on the stack in the function prologue and so always have a pointer between
+// the hardware stack pointer and the local variable area.
+func (ctxt *Link) FixedFrameSize() int64 {
+	switch ctxt.Arch.Thechar {
+	case '6', '8':
+		return 0
+	case '9':
+		// PIC code on ppc64le requires 32 bytes of stack, and it's easier to
+		// just use that much stack always on ppc64x.
+		return int64(4 * ctxt.Arch.Ptrsize)
+	default:
+		return int64(ctxt.Arch.Ptrsize)
+	}
 }
 
 type LinkArch struct {
@@ -208,10 +237,6 @@ const (
 	RV_TYPE_MASK      = RV_CHECK_OVERFLOW - 1
 )
 
-const (
-	LINKHASH = 100003
-)
-
 // Pcdata iterator.
 //	for(pciterinit(ctxt, &it, &pcd); !it.done; pciternext(&it)) { it.value holds in [it.pc, it.nextpc) }
 
diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go
index ccc8491..1c7f3a0 100644
--- a/src/cmd/link/internal/ld/macho.go
+++ b/src/cmd/link/internal/ld/macho.go
@@ -444,7 +444,7 @@ func Asmbmacho() {
 		ms = newMachoSeg("", 40)
 
 		ms.fileoffset = Segtext.Fileoff
-		if Thearch.Thechar == '5' {
+		if Thearch.Thechar == '5' || Buildmode == BuildmodeCArchive {
 			ms.filesize = Segdata.Fileoff + Segdata.Filelen - Segtext.Fileoff
 		} else {
 			ms.filesize = Segdwarf.Fileoff + Segdwarf.Filelen - Segtext.Fileoff
@@ -566,6 +566,25 @@ func Asmbmacho() {
 		}
 	}
 
+	if Linkmode == LinkInternal {
+		// For lldb, must say LC_VERSION_MIN_MACOSX or else
+		// it won't know that this Mach-O binary is from OS X
+		// (could be iOS or WatchOS intead).
+		// Go on iOS uses linkmode=external, and linkmode=external
+		// adds this itself. So we only need this code for linkmode=internal
+		// and we can assume OS X.
+		//
+		// See golang.org/issues/12941.
+		const (
+			LC_VERSION_MIN_MACOSX   = 0x24
+			LC_VERSION_MIN_IPHONEOS = 0x25
+			LC_VERSION_MIN_WATCHOS  = 0x30
+		)
+		ml := newMachoLoad(LC_VERSION_MIN_MACOSX, 2)
+		ml.data[0] = 10<<16 | 7<<8 | 0<<0 // OS X version 10.7.0
+		ml.data[1] = 10<<16 | 7<<8 | 0<<0 // SDK 10.7.0
+	}
+
 	// TODO: dwarf headers go in ms too
 	if Debug['s'] == 0 {
 		dwarfaddmachoheaders(ms)
@@ -625,10 +644,10 @@ func (x machoscmp) Less(i, j int) bool {
 	k1 := symkind(s1)
 	k2 := symkind(s2)
 	if k1 != k2 {
-		return k1-k2 < 0
+		return k1 < k2
 	}
 
-	return stringsCompare(s1.Extname, s2.Extname) < 0
+	return s1.Extname < s2.Extname
 }
 
 func machogenasmsym(put func(*LSym, string, int, int64, int64, int, *LSym)) {
diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go
index 6697762..d1e3c25 100644
--- a/src/cmd/link/internal/ld/pcln.go
+++ b/src/cmd/link/internal/ld/pcln.go
@@ -8,6 +8,8 @@ import (
 	"cmd/internal/obj"
 	"fmt"
 	"log"
+	"os"
+	"path/filepath"
 )
 
 // funcpctab writes to dst a pc-value table mapping the code in func to the values
@@ -150,6 +152,7 @@ func renumberfiles(ctxt *Link, files []*LSym, d *Pcdata) {
 			f.Value = int64(ctxt.Nhistfile)
 			f.Type = obj.SFILEPATH
 			f.Next = ctxt.Filesyms
+			f.Name = expandGoroot(f.Name)
 			ctxt.Filesyms = f
 		}
 	}
@@ -376,6 +379,18 @@ func pclntab() {
 	}
 }
 
+func expandGoroot(s string) string {
+	const n = len("$GOROOT")
+	if len(s) >= n+1 && s[:n] == "$GOROOT" && (s[n] == '/' || s[n] == '\\') {
+		root := goroot
+		if final := os.Getenv("GOROOT_FINAL"); final != "" {
+			root = final
+		}
+		return filepath.ToSlash(filepath.Join(root, s[n:]))
+	}
+	return s
+}
+
 const (
 	BUCKETSIZE    = 256 * MINFUNC
 	SUBBUCKETS    = 16
diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go
index 4a7d710..00fbb17 100644
--- a/src/cmd/link/internal/ld/pe.go
+++ b/src/cmd/link/internal/ld/pe.go
@@ -684,21 +684,11 @@ func addimports(datsect *IMAGE_SECTION_HEADER) {
 	Cseek(endoff)
 }
 
-type pescmp []*LSym
+type byExtname []*LSym
 
-func (x pescmp) Len() int {
-	return len(x)
-}
-
-func (x pescmp) Swap(i, j int) {
-	x[i], x[j] = x[j], x[i]
-}
-
-func (x pescmp) Less(i, j int) bool {
-	s1 := x[i]
-	s2 := x[j]
-	return stringsCompare(s1.Extname, s2.Extname) < 0
-}
+func (s byExtname) Len() int           { return len(s) }
+func (s byExtname) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
+func (s byExtname) Less(i, j int) bool { return s[i].Extname < s[j].Extname }
 
 func initdynexport() {
 	nexport = 0
@@ -715,7 +705,7 @@ func initdynexport() {
 		nexport++
 	}
 
-	sort.Sort(pescmp(dexport[:nexport]))
+	sort.Sort(byExtname(dexport[:nexport]))
 }
 
 func addexports() {
@@ -1227,12 +1217,17 @@ func Asmbpe() {
 	// larger size, as verified with VMMap.
 
 	// Go code would be OK with 64k stacks, but we need larger stacks for cgo.
-	// That default stack reserve size affects only the main thread,
-	// for other threads we specify stack size in runtime explicitly
+	//
+	// The default stack reserve size affects only the main
+	// thread, ctrlhandler thread, and profileloop thread. For
+	// these, it must be greater than the stack size assumed by
+	// externalthreadhandler.
+	//
+	// For other threads we specify stack size in runtime explicitly
 	// (runtime knows whether cgo is enabled or not).
-	// If you change stack reserve sizes here,
-	// change STACKSIZE in runtime/cgo/gcc_windows_{386,amd64}.c and correspondent
-	// CreateThread parameter in runtime.newosproc as well.
+	// For these, the reserve must match STACKSIZE in
+	// runtime/cgo/gcc_windows_{386,amd64}.c and the correspondent
+	// CreateThread parameter in runtime.newosproc.
 	if !iscgo {
 		oh64.SizeOfStackReserve = 0x00020000
 		oh.SizeOfStackReserve = 0x00020000
diff --git a/src/cmd/link/internal/ld/pobj.go b/src/cmd/link/internal/ld/pobj.go
index 5ce1977..808d377 100644
--- a/src/cmd/link/internal/ld/pobj.go
+++ b/src/cmd/link/internal/ld/pobj.go
@@ -83,13 +83,13 @@ func Ldmain() {
 	obj.Flagint32("R", "set address rounding `quantum`", &INITRND)
 	obj.Flagint64("T", "set text segment `address`", &INITTEXT)
 	obj.Flagfn0("V", "print version and exit", doversion)
-	obj.Flagcount("W", "disassemble input", &Debug['W'])
 	obj.Flagfn1("X", "add string value `definition` of the form importpath.name=value", addstrdata1)
 	obj.Flagcount("a", "disassemble output", &Debug['a'])
 	obj.Flagstr("buildid", "record `id` as Go toolchain build id", &buildid)
 	flag.Var(&Buildmode, "buildmode", "set build `mode`")
 	obj.Flagcount("c", "dump call graph", &Debug['c'])
 	obj.Flagcount("d", "disable dynamic executable", &Debug['d'])
+	obj.Flagstr("extar", "archive program for buildmode=c-archive", &extar)
 	obj.Flagstr("extld", "use `linker` when linking in external mode", &extld)
 	obj.Flagstr("extldflags", "pass `flags` to external linker", &extldflags)
 	obj.Flagcount("f", "ignore version mismatch", &Debug['f'])
@@ -97,8 +97,10 @@ func Ldmain() {
 	obj.Flagcount("h", "halt on error", &Debug['h'])
 	obj.Flagstr("installsuffix", "set package directory `suffix`", &flag_installsuffix)
 	obj.Flagstr("k", "set field tracking `symbol`", &tracksym)
+	obj.Flagstr("libgcc", "compiler support lib for internal linking; use \"none\" to disable", &libgccfile)
 	obj.Flagfn1("linkmode", "set link `mode` (internal, external, auto)", setlinkmode)
 	flag.BoolVar(&Linkshared, "linkshared", false, "link against installed Go shared libraries")
+	obj.Flagcount("msan", "enable MSan interface", &flag_msan)
 	obj.Flagcount("n", "dump symbol table", &Debug['n'])
 	obj.Flagstr("o", "write output to `file`", &outfile)
 	flag.Var(&rpath, "r", "set the ELF dynamic linker search `path` to dir1:dir2:...")
diff --git a/src/cmd/link/internal/ld/sym.go b/src/cmd/link/internal/ld/sym.go
index 652109d..731f3ed 100644
--- a/src/cmd/link/internal/ld/sym.go
+++ b/src/cmd/link/internal/ld/sym.go
@@ -39,10 +39,6 @@ import (
 	"strconv"
 )
 
-func yy_isalpha(c int) bool {
-	return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
-}
-
 var headers = []struct {
 	name string
 	val  int
@@ -106,7 +102,21 @@ func linknew(arch *LinkArch) *Link {
 		obj.Hopenbsd,
 		obj.Hdragonfly,
 		obj.Hsolaris:
-		ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize
+		if obj.Getgoos() == "android" {
+			switch ctxt.Arch.Thechar {
+			case '6':
+				// Android/amd64 constant - offset from 0(FS) to our TLS slot.
+				// Explained in src/runtime/cgo/gcc_android_*.c
+				ctxt.Tlsoffset = 0x1d0
+			case '8':
+				// Android/386 constant - offset from 0(GS) to our TLS slot.
+				ctxt.Tlsoffset = 0xf8
+			default:
+				ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize
+			}
+		} else {
+			ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize
+		}
 
 	case obj.Hnacl:
 		switch ctxt.Arch.Thechar {
@@ -125,7 +135,7 @@ func linknew(arch *LinkArch) *Link {
 
 		/*
 		 * OS X system constants - offset from 0(GS) to our TLS.
-		 * Explained in ../../runtime/cgo/gcc_darwin_*.c.
+		 * Explained in src/runtime/cgo/gcc_darwin_*.c.
 		 */
 	case obj.Hdarwin:
 		switch ctxt.Arch.Thechar {
@@ -148,12 +158,7 @@ func linknew(arch *LinkArch) *Link {
 
 	// On arm, record goarm.
 	if ctxt.Arch.Thechar == '5' {
-		p := obj.Getgoarm()
-		if p != "" {
-			ctxt.Goarm = int32(obj.Atoi(p))
-		} else {
-			ctxt.Goarm = 6
-		}
+		ctxt.Goarm = obj.Getgoarm()
 	}
 
 	return ctxt
diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go
index 5360ec1..3e6169e 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 {
 
 func putelfsyment(off int, addr int64, size int64, info int, shndx int, other int) {
 	switch Thearch.Thechar {
-	case '6', '7', '9':
+	case '0', '6', '7', '9':
 		Thearch.Lput(uint32(off))
 		Cput(uint8(info))
 		Cput(uint8(other))
@@ -155,11 +155,6 @@ func putelfsym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *L
 		bind = STB_LOCAL
 	}
 
-	if bind != elfbind {
-		return
-	}
-
-	off := putelfstr(s)
 	if Linkmode == LinkExternal && elfshnum != SHN_UNDEF {
 		addr -= int64(xo.Sect.Vaddr)
 	}
@@ -167,7 +162,31 @@ func putelfsym(x *LSym, s string, t int, addr int64, size int64, ver int, go_ *L
 	if x.Type&obj.SHIDDEN != 0 {
 		other = STV_HIDDEN
 	}
-	putelfsyment(off, addr, size, bind<<4|type_&0xf, elfshnum, other)
+	if (Buildmode == BuildmodePIE || DynlinkingGo()) && Thearch.Thechar == '9' && type_ == STT_FUNC && x.Name != "runtime.duffzero" && x.Name != "runtime.duffcopy" {
+		// On ppc64 the top three bits of the st_other field indicate how
+		// many instructions separate the global and local entry points. In
+		// our case it is two instructions, indicated by the value 3.
+		other |= 3 << 5
+	}
+
+	if DynlinkingGo() && bind == STB_GLOBAL && elfbind == STB_LOCAL && x.Type == obj.STEXT {
+		// When dynamically linking, we want references to functions defined
+		// in this module to always be to the function object, not to the
+		// PLT. We force this by writing an additional local symbol for every
+		// global function symbol and making all relocations against the
+		// global symbol refer to this local symbol instead (see
+		// (*LSym).ElfsymForReloc). This is approximately equivalent to the
+		// ELF linker -Bsymbolic-functions option, but that is buggy on
+		// several platforms.
+		putelfsyment(putelfstr("local."+s), addr, size, STB_LOCAL<<4|type_&0xf, elfshnum, other)
+		x.LocalElfsym = int32(numelfsym)
+		numelfsym++
+		return
+	} else if bind != elfbind {
+		return
+	}
+
+	putelfsyment(putelfstr(s), addr, size, bind<<4|type_&0xf, elfshnum, other)
 	x.Elfsym = int32(numelfsym)
 	numelfsym++
 }
@@ -350,13 +369,29 @@ func symtab() {
 
 	// pseudo-symbols to mark locations of type, string, and go string data.
 	var symtype *LSym
-	if !DynlinkingGo() {
+	var symtyperel *LSym
+	if UseRelro() && (Buildmode == BuildmodeCShared || Buildmode == BuildmodePIE) {
 		s = Linklookup(Ctxt, "type.*", 0)
 
 		s.Type = obj.STYPE
 		s.Size = 0
 		s.Reachable = true
 		symtype = s
+
+		s = Linklookup(Ctxt, "typerel.*", 0)
+
+		s.Type = obj.STYPERELRO
+		s.Size = 0
+		s.Reachable = true
+		symtyperel = s
+	} else if !DynlinkingGo() {
+		s = Linklookup(Ctxt, "type.*", 0)
+
+		s.Type = obj.STYPE
+		s.Size = 0
+		s.Reachable = true
+		symtype = s
+		symtyperel = s
 	}
 
 	s = Linklookup(Ctxt, "go.string.*", 0)
@@ -381,6 +416,7 @@ func symtab() {
 	symgcbits := s
 
 	symtypelink := Linklookup(Ctxt, "runtime.typelink", 0)
+	symtypelink.Type = obj.STYPELINK
 
 	symt = Linklookup(Ctxt, "runtime.symtab", 0)
 	symt.Local = true
@@ -400,9 +436,14 @@ func symtab() {
 		}
 
 		if strings.HasPrefix(s.Name, "type.") && !DynlinkingGo() {
-			s.Type = obj.STYPE
 			s.Hide = 1
-			s.Outer = symtype
+			if UseRelro() && len(s.R) > 0 {
+				s.Type = obj.STYPERELRO
+				s.Outer = symtyperel
+			} else {
+				s.Type = obj.STYPE
+				s.Outer = symtype
+			}
 		}
 
 		if strings.HasPrefix(s.Name, "go.typelink.") {
@@ -452,11 +493,7 @@ func symtab() {
 	// runtime to use. Any changes here must be matched by changes to
 	// the definition of moduledata in runtime/symtab.go.
 	// This code uses several global variables that are set by pcln.go:pclntab.
-	moduledata := Linklookup(Ctxt, "runtime.firstmoduledata", 0)
-	moduledata.Type = obj.SNOPTRDATA
-	moduledata.Size = 0 // truncate symbol back to 0 bytes to reinitialize
-	moduledata.Reachable = true
-	moduledata.Local = true
+	moduledata := Ctxt.Moduledata
 	// The pclntab slice
 	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0))
 	adduint(Ctxt, moduledata, uint64(Linklookup(Ctxt, "runtime.pclntab", 0).Size))
@@ -467,8 +504,8 @@ func symtab() {
 	adduint(Ctxt, moduledata, uint64(pclntabNfunc+1))
 	// The filetab slice
 	Addaddrplus(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0), int64(pclntabFiletabOffset))
-	adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile))
-	adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile))
+	adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile)+1)
+	adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile)+1)
 	// findfunctab
 	Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.findfunctab", 0))
 	// minpc, maxpc
@@ -494,7 +531,8 @@ func symtab() {
 	adduint(Ctxt, moduledata, uint64(ntypelinks))
 	if len(Ctxt.Shlibs) > 0 {
 		thismodulename := filepath.Base(outfile)
-		if Buildmode == BuildmodeExe {
+		switch Buildmode {
+		case BuildmodeExe, BuildmodePIE:
 			// When linking an executable, outfile is just "a.out". Make
 			// it something slightly more comprehensible.
 			thismodulename = "the executable"
diff --git a/src/cmd/link/internal/ld/textflag.go b/src/cmd/link/internal/ld/textflag.go
deleted file mode 100644
index 6457fda..0000000
--- a/src/cmd/link/internal/ld/textflag.go
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2013 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 ld
-
-// This file defines flags attached to various functions
-// and data objects.  The compilers, assemblers, and linker must
-// all agree on these values.
-
-const (
-	// Don't profile the marked routine.
-	//
-	// Deprecated: Not implemented, do not use.
-	NOPROF = 1
-	// It is ok for the linker to get multiple of these symbols.  It will
-	// pick one of the duplicates to use.
-	DUPOK = 2
-	// Don't insert stack check preamble.
-	NOSPLIT = 4
-	// Put this data in a read-only section.
-	RODATA = 8
-	// This data contains no pointers.
-	NOPTR = 16
-	// This is a wrapper function and should not count as disabling 'recover'.
-	WRAPPER = 32
-	// This function uses its incoming context register.
-	NEEDCTXT = 64
-)
diff --git a/src/cmd/link/internal/ld/util.go b/src/cmd/link/internal/ld/util.go
index f38f05c..2995e7f 100644
--- a/src/cmd/link/internal/ld/util.go
+++ b/src/cmd/link/internal/ld/util.go
@@ -67,24 +67,6 @@ func tokenize(s string) []string {
 	return f
 }
 
-func cutStringAtNUL(s string) string {
-	if i := strings.Index(s, "\x00"); i >= 0 {
-		s = s[:i]
-	}
-	return s
-}
-
-func Access(name string, mode int) int {
-	if mode != 0 {
-		panic("bad access")
-	}
-	_, err := os.Stat(name)
-	if err != nil {
-		return -1
-	}
-	return 0
-}
-
 // strings.Compare, introduced in Go 1.5.
 func stringsCompare(a, b string) int {
 	if a == b {
diff --git a/src/cmd/link/internal/mips64/asm.go b/src/cmd/link/internal/mips64/asm.go
new file mode 100644
index 0000000..8249c54
--- /dev/null
+++ b/src/cmd/link/internal/mips64/asm.go
@@ -0,0 +1,248 @@
+// Inferno utils/5l/asm.c
+// http://code.google.com/p/inferno-os/source/browse/utils/5l/asm.c
+//
+//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//	Portions Copyright © 1995-1997 C H Forsyth (forsyth at terzarima.net)
+//	Portions Copyright © 1997-1999 Vita Nuova Limited
+//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+//	Portions Copyright © 2004,2006 Bruce Ellis
+//	Portions Copyright © 2005-2007 C H Forsyth (forsyth at terzarima.net)
+//	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package mips64
+
+import (
+	"cmd/internal/obj"
+	"cmd/link/internal/ld"
+	"encoding/binary"
+	"fmt"
+	"log"
+)
+
+func gentext() {}
+
+func adddynrela(rel *ld.LSym, s *ld.LSym, r *ld.Reloc) {
+	log.Fatalf("adddynrela not implemented")
+}
+
+func adddynrel(s *ld.LSym, r *ld.Reloc) {
+	log.Fatalf("adddynrel not implemented")
+}
+
+func elfreloc1(r *ld.Reloc, sectoff int64) int {
+	return -1
+}
+
+func elfsetupplt() {
+	return
+}
+
+func machoreloc1(r *ld.Reloc, sectoff int64) int {
+	return -1
+}
+
+func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
+	if ld.Linkmode == ld.LinkExternal {
+		return -1
+	}
+
+	switch r.Type {
+	case obj.R_CONST:
+		*val = r.Add
+		return 0
+
+	case obj.R_GOTOFF:
+		*val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ld.Linklookup(ld.Ctxt, ".got", 0))
+		return 0
+
+	case obj.R_ADDRMIPS:
+		t := ld.Symaddr(r.Sym) + r.Add
+		if t >= 1<<32 || t < -1<<32 {
+			ld.Diag("program too large, address relocation = %v", t)
+		}
+
+		// the first instruction is always at the lower address, this is endian neutral;
+		// but note that o1 and o2 should still use the target endian.
+		o1 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off:])
+		o2 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off+4:])
+		o1 = o1&0xffff0000 | uint32(t>>16)&0xffff
+		o2 = o2&0xffff0000 | uint32(t)&0xffff
+
+		// when laid out, the instruction order must always be o1, o2.
+		if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
+			*val = int64(o1)<<32 | int64(o2)
+		} else {
+			*val = int64(o2)<<32 | int64(o1)
+		}
+		return 0
+
+	case obj.R_CALLMIPS,
+		obj.R_JMPMIPS:
+		// Low 26 bits = (S + A) >> 2
+		t := ld.Symaddr(r.Sym) + r.Add
+		o1 := ld.Thelinkarch.ByteOrder.Uint32(s.P[r.Off:])
+		*val = int64(o1&0xfc000000 | uint32(t>>2)&^0xfc000000)
+		return 0
+	}
+
+	return -1
+}
+
+func archrelocvariant(r *ld.Reloc, s *ld.LSym, t int64) int64 {
+	return -1
+}
+
+func asmb() {
+	if ld.Debug['v'] != 0 {
+		fmt.Fprintf(&ld.Bso, "%5.2f asmb\n", obj.Cputime())
+	}
+	ld.Bso.Flush()
+
+	if ld.Iself {
+		ld.Asmbelfsetup()
+	}
+
+	sect := ld.Segtext.Sect
+	ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
+	ld.Codeblk(int64(sect.Vaddr), int64(sect.Length))
+	for sect = sect.Next; sect != nil; sect = sect.Next {
+		ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
+		ld.Datblk(int64(sect.Vaddr), int64(sect.Length))
+	}
+
+	if ld.Segrodata.Filelen > 0 {
+		if ld.Debug['v'] != 0 {
+			fmt.Fprintf(&ld.Bso, "%5.2f rodatblk\n", obj.Cputime())
+		}
+		ld.Bso.Flush()
+
+		ld.Cseek(int64(ld.Segrodata.Fileoff))
+		ld.Datblk(int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
+	}
+
+	if ld.Debug['v'] != 0 {
+		fmt.Fprintf(&ld.Bso, "%5.2f datblk\n", obj.Cputime())
+	}
+	ld.Bso.Flush()
+
+	ld.Cseek(int64(ld.Segdata.Fileoff))
+	ld.Datblk(int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
+
+	/* output symbol table */
+	ld.Symsize = 0
+
+	ld.Lcsize = 0
+	symo := uint32(0)
+	if ld.Debug['s'] == 0 {
+		// TODO: rationalize
+		if ld.Debug['v'] != 0 {
+			fmt.Fprintf(&ld.Bso, "%5.2f sym\n", obj.Cputime())
+		}
+		ld.Bso.Flush()
+		switch ld.HEADTYPE {
+		default:
+			if ld.Iself {
+				symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
+				symo = uint32(ld.Rnd(int64(symo), int64(ld.INITRND)))
+			}
+
+		case obj.Hplan9:
+			symo = uint32(ld.Segdata.Fileoff + ld.Segdata.Filelen)
+		}
+
+		ld.Cseek(int64(symo))
+		switch ld.HEADTYPE {
+		default:
+			if ld.Iself {
+				if ld.Debug['v'] != 0 {
+					fmt.Fprintf(&ld.Bso, "%5.2f elfsym\n", obj.Cputime())
+				}
+				ld.Asmelfsym()
+				ld.Cflush()
+				ld.Cwrite(ld.Elfstrdat)
+
+				if ld.Debug['v'] != 0 {
+					fmt.Fprintf(&ld.Bso, "%5.2f dwarf\n", obj.Cputime())
+				}
+				ld.Dwarfemitdebugsections()
+
+				if ld.Linkmode == ld.LinkExternal {
+					ld.Elfemitreloc()
+				}
+			}
+
+		case obj.Hplan9:
+			ld.Asmplan9sym()
+			ld.Cflush()
+
+			sym := ld.Linklookup(ld.Ctxt, "pclntab", 0)
+			if sym != nil {
+				ld.Lcsize = int32(len(sym.P))
+				for i := 0; int32(i) < ld.Lcsize; i++ {
+					ld.Cput(uint8(sym.P[i]))
+				}
+
+				ld.Cflush()
+			}
+		}
+	}
+
+	ld.Ctxt.Cursym = nil
+	if ld.Debug['v'] != 0 {
+		fmt.Fprintf(&ld.Bso, "%5.2f header\n", obj.Cputime())
+	}
+	ld.Bso.Flush()
+	ld.Cseek(0)
+	switch ld.HEADTYPE {
+	default:
+	case obj.Hplan9: /* plan 9 */
+		magic := uint32(4*18*18 + 7)
+		if ld.Thestring == "mips64le" {
+			magic = uint32(4*26*26 + 7)
+		}
+		ld.Thearch.Lput(uint32(magic))              /* magic */
+		ld.Thearch.Lput(uint32(ld.Segtext.Filelen)) /* sizes */
+		ld.Thearch.Lput(uint32(ld.Segdata.Filelen))
+		ld.Thearch.Lput(uint32(ld.Segdata.Length - ld.Segdata.Filelen))
+		ld.Thearch.Lput(uint32(ld.Symsize))      /* nsyms */
+		ld.Thearch.Lput(uint32(ld.Entryvalue())) /* va of entry */
+		ld.Thearch.Lput(0)
+		ld.Thearch.Lput(uint32(ld.Lcsize))
+
+	case obj.Hlinux,
+		obj.Hfreebsd,
+		obj.Hnetbsd,
+		obj.Hopenbsd,
+		obj.Hnacl:
+		ld.Asmbelf(int64(symo))
+	}
+
+	ld.Cflush()
+	if ld.Debug['c'] != 0 {
+		fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
+		fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
+		fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
+		fmt.Printf("symsize=%d\n", ld.Symsize)
+		fmt.Printf("lcsize=%d\n", ld.Lcsize)
+		fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
+	}
+}
diff --git a/src/cmd/link/internal/mips64/l.go b/src/cmd/link/internal/mips64/l.go
new file mode 100644
index 0000000..8ea1d84
--- /dev/null
+++ b/src/cmd/link/internal/mips64/l.go
@@ -0,0 +1,75 @@
+// Inferno utils/5l/asm.c
+// http://code.google.com/p/inferno-os/source/browse/utils/5l/asm.c
+//
+//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//	Portions Copyright © 1995-1997 C H Forsyth (forsyth at terzarima.net)
+//	Portions Copyright © 1997-1999 Vita Nuova Limited
+//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+//	Portions Copyright © 2004,2006 Bruce Ellis
+//	Portions Copyright © 2005-2007 C H Forsyth (forsyth at terzarima.net)
+//	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package mips64
+
+// Writing object files.
+
+// cmd/9l/l.h from Vita Nuova.
+//
+//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//	Portions Copyright © 1995-1997 C H Forsyth (forsyth at terzarima.net)
+//	Portions Copyright © 1997-1999 Vita Nuova Limited
+//	Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
+//	Portions Copyright © 2004,2006 Bruce Ellis
+//	Portions Copyright © 2005-2007 C H Forsyth (forsyth at terzarima.net)
+//	Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
+//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+const (
+	thechar   = '0'
+	MaxAlign  = 32 // max data alignment
+	FuncAlign = 8
+	MINLC     = 4
+)
+
+/* Used by ../internal/ld/dwarf.go */
+const (
+	DWARFREGSP = 29
+	DWARFREGLR = 31
+)
diff --git a/src/cmd/link/internal/mips64/obj.go b/src/cmd/link/internal/mips64/obj.go
new file mode 100644
index 0000000..ad686e9
--- /dev/null
+++ b/src/cmd/link/internal/mips64/obj.go
@@ -0,0 +1,158 @@
+// Inferno utils/5l/obj.c
+// http://code.google.com/p/inferno-os/source/browse/utils/5l/obj.c
+//
+//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
+//	Portions Copyright © 1995-1997 C H Forsyth (forsyth at terzarima.net)
+//	Portions Copyright © 1997-1999 Vita Nuova Limited
+//	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
+//	Portions Copyright © 2004,2006 Bruce Ellis
+//	Portions Copyright © 2005-2007 C H Forsyth (forsyth at terzarima.net)
+//	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
+//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+package mips64
+
+import (
+	"cmd/internal/obj"
+	"cmd/link/internal/ld"
+	"fmt"
+	"log"
+)
+
+// Reading object files.
+
+func Main() {
+	linkarchinit()
+	ld.Ldmain()
+}
+
+func linkarchinit() {
+	ld.Thestring = obj.Getgoarch()
+	if ld.Thestring == "mips64le" {
+		ld.Thelinkarch = &ld.Linkmips64le
+	} else {
+		ld.Thelinkarch = &ld.Linkmips64
+	}
+
+	ld.Thearch.Thechar = thechar
+	ld.Thearch.Ptrsize = ld.Thelinkarch.Ptrsize
+	ld.Thearch.Intsize = ld.Thelinkarch.Ptrsize
+	ld.Thearch.Regsize = ld.Thelinkarch.Regsize
+	ld.Thearch.Funcalign = FuncAlign
+	ld.Thearch.Maxalign = MaxAlign
+	ld.Thearch.Minlc = MINLC
+	ld.Thearch.Dwarfregsp = DWARFREGSP
+	ld.Thearch.Dwarfreglr = DWARFREGLR
+
+	ld.Thearch.Adddynrel = adddynrel
+	ld.Thearch.Archinit = archinit
+	ld.Thearch.Archreloc = archreloc
+	ld.Thearch.Archrelocvariant = archrelocvariant
+	ld.Thearch.Asmb = asmb
+	ld.Thearch.Elfreloc1 = elfreloc1
+	ld.Thearch.Elfsetupplt = elfsetupplt
+	ld.Thearch.Gentext = gentext
+	ld.Thearch.Machoreloc1 = machoreloc1
+	if ld.Thelinkarch == &ld.Linkmips64le {
+		ld.Thearch.Lput = ld.Lputl
+		ld.Thearch.Wput = ld.Wputl
+		ld.Thearch.Vput = ld.Vputl
+	} else {
+		ld.Thearch.Lput = ld.Lputb
+		ld.Thearch.Wput = ld.Wputb
+		ld.Thearch.Vput = ld.Vputb
+	}
+
+	ld.Thearch.Linuxdynld = "/lib64/ld64.so.1"
+
+	ld.Thearch.Freebsddynld = "XXX"
+	ld.Thearch.Openbsddynld = "XXX"
+	ld.Thearch.Netbsddynld = "XXX"
+	ld.Thearch.Dragonflydynld = "XXX"
+	ld.Thearch.Solarisdynld = "XXX"
+}
+
+func archinit() {
+	// getgoextlinkenabled is based on GO_EXTLINK_ENABLED when
+	// Go was built; see ../../make.bash.
+	if ld.Linkmode == ld.LinkAuto && obj.Getgoextlinkenabled() == "0" {
+		ld.Linkmode = ld.LinkInternal
+	}
+
+	switch ld.HEADTYPE {
+	default:
+		if ld.Linkmode == ld.LinkAuto {
+			ld.Linkmode = ld.LinkInternal
+		}
+		if ld.Linkmode == ld.LinkExternal && obj.Getgoextlinkenabled() != "1" {
+			log.Fatalf("cannot use -linkmode=external with -H %s", ld.Headstr(int(ld.HEADTYPE)))
+		}
+	}
+
+	switch ld.HEADTYPE {
+	default:
+		ld.Exitf("unknown -H option: %v", ld.HEADTYPE)
+
+	case obj.Hplan9: /* plan 9 */
+		ld.HEADR = 32
+
+		if ld.INITTEXT == -1 {
+			ld.INITTEXT = 16*1024 + int64(ld.HEADR)
+		}
+		if ld.INITDAT == -1 {
+			ld.INITDAT = 0
+		}
+		if ld.INITRND == -1 {
+			ld.INITRND = 16 * 1024
+		}
+
+	case obj.Hlinux: /* mips64 elf */
+		ld.Elfinit()
+		ld.HEADR = ld.ELFRESERVE
+		if ld.INITTEXT == -1 {
+			ld.INITTEXT = 0x10000 + int64(ld.HEADR)
+		}
+		if ld.INITDAT == -1 {
+			ld.INITDAT = 0
+		}
+		if ld.INITRND == -1 {
+			ld.INITRND = 0x10000
+		}
+
+	case obj.Hnacl:
+		ld.Elfinit()
+		ld.HEADR = 0x10000
+		ld.Funcalign = 16
+		if ld.INITTEXT == -1 {
+			ld.INITTEXT = 0x20000
+		}
+		if ld.INITDAT == -1 {
+			ld.INITDAT = 0
+		}
+		if ld.INITRND == -1 {
+			ld.INITRND = 0x10000
+		}
+	}
+
+	if ld.INITDAT != 0 && ld.INITRND != 0 {
+		fmt.Printf("warning: -D0x%x is ignored because of -R0x%x\n", uint64(ld.INITDAT), uint32(ld.INITRND))
+	}
+}
diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go
index f070921..169accc 100644
--- a/src/cmd/link/internal/ppc64/asm.go
+++ b/src/cmd/link/internal/ppc64/asm.go
@@ -38,7 +38,7 @@ import (
 	"log"
 )
 
-func gentext() {
+func genplt() {
 	var s *ld.LSym
 	var stub *ld.LSym
 	var pprevtextp **ld.LSym
@@ -137,6 +137,84 @@ func gentext() {
 			ld.Ctxt.Arch.ByteOrder.PutUint32(s.P[r.Off+4:], o1)
 		}
 	}
+
+}
+
+func genaddmoduledata() {
+	addmoduledata := ld.Linkrlookup(ld.Ctxt, "runtime.addmoduledata", 0)
+	if addmoduledata.Type == obj.STEXT {
+		return
+	}
+	addmoduledata.Reachable = true
+	initfunc := ld.Linklookup(ld.Ctxt, "go.link.addmoduledata", 0)
+	initfunc.Type = obj.STEXT
+	initfunc.Local = true
+	initfunc.Reachable = true
+	o := func(op uint32) {
+		ld.Adduint32(ld.Ctxt, initfunc, op)
+	}
+	// addis r2, r12, .TOC.-func at ha
+	rel := ld.Addrel(initfunc)
+	rel.Off = int32(initfunc.Size)
+	rel.Siz = 8
+	rel.Sym = ld.Linklookup(ld.Ctxt, ".TOC.", 0)
+	rel.Type = obj.R_ADDRPOWER_PCREL
+	o(0x3c4c0000)
+	// addi r2, r2, .TOC.-func at l
+	o(0x38420000)
+	// mflr r31
+	o(0x7c0802a6)
+	// stdu r31, -32(r1)
+	o(0xf801ffe1)
+	// addis r3, r2, local.moduledata at got@ha
+	rel = ld.Addrel(initfunc)
+	rel.Off = int32(initfunc.Size)
+	rel.Siz = 8
+	rel.Sym = ld.Linklookup(ld.Ctxt, "local.moduledata", 0)
+	rel.Type = obj.R_ADDRPOWER_GOT
+	o(0x3c620000)
+	// ld r3, local.moduledata at got@l(r3)
+	o(0xe8630000)
+	// bl runtime.addmoduledata
+	rel = ld.Addrel(initfunc)
+	rel.Off = int32(initfunc.Size)
+	rel.Siz = 4
+	rel.Sym = addmoduledata
+	rel.Type = obj.R_CALLPOWER
+	o(0x48000001)
+	// nop
+	o(0x60000000)
+	// ld r31, 0(r1)
+	o(0xe8010000)
+	// mtlr r31
+	o(0x7c0803a6)
+	// addi r1,r1,32
+	o(0x38210020)
+	// blr
+	o(0x4e800020)
+
+	if ld.Ctxt.Etextp != nil {
+		ld.Ctxt.Etextp.Next = initfunc
+	} else {
+		ld.Ctxt.Textp = initfunc
+	}
+	ld.Ctxt.Etextp = initfunc
+
+	initarray_entry := ld.Linklookup(ld.Ctxt, "go.link.addmoduledatainit", 0)
+	initarray_entry.Reachable = true
+	initarray_entry.Local = true
+	initarray_entry.Type = obj.SINITARR
+	ld.Addaddr(ld.Ctxt, initarray_entry, initfunc)
+}
+
+func gentext() {
+	if ld.DynlinkingGo() {
+		genaddmoduledata()
+	}
+
+	if ld.Linkmode == ld.LinkInternal {
+		genplt()
+	}
 }
 
 // Construct a call stub in stub that calls symbol targ via its PLT
@@ -218,6 +296,16 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
 
 		return
 
+	case 256 + ld.R_PPC_REL32:
+		r.Type = obj.R_PCREL
+		r.Add += 4
+
+		if targ.Type == obj.SDYNIMPORT {
+			ld.Diag("unexpected R_PPC_REL32 for dyn import")
+		}
+
+		return
+
 	case 256 + ld.R_PPC64_ADDR64:
 		r.Type = obj.R_ADDR
 		if targ.Type == obj.SDYNIMPORT {
@@ -293,8 +381,82 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
 }
 
 func elfreloc1(r *ld.Reloc, sectoff int64) int {
-	// TODO(minux)
-	return -1
+	ld.Thearch.Vput(uint64(sectoff))
+
+	elfsym := r.Xsym.ElfsymForReloc()
+	switch r.Type {
+	default:
+		return -1
+
+	case obj.R_ADDR:
+		switch r.Siz {
+		case 4:
+			ld.Thearch.Vput(ld.R_PPC64_ADDR32 | uint64(elfsym)<<32)
+		case 8:
+			ld.Thearch.Vput(ld.R_PPC64_ADDR64 | uint64(elfsym)<<32)
+		default:
+			return -1
+		}
+
+	case obj.R_POWER_TLS:
+		ld.Thearch.Vput(ld.R_PPC64_TLS | uint64(elfsym)<<32)
+
+	case obj.R_POWER_TLS_LE:
+		ld.Thearch.Vput(ld.R_PPC64_TPREL16 | uint64(elfsym)<<32)
+
+	case obj.R_POWER_TLS_IE:
+		ld.Thearch.Vput(ld.R_PPC64_GOT_TPREL16_HA | uint64(elfsym)<<32)
+		ld.Thearch.Vput(uint64(r.Xadd))
+		ld.Thearch.Vput(uint64(sectoff + 4))
+		ld.Thearch.Vput(ld.R_PPC64_GOT_TPREL16_LO_DS | uint64(elfsym)<<32)
+
+	case obj.R_ADDRPOWER:
+		ld.Thearch.Vput(ld.R_PPC64_ADDR16_HA | uint64(elfsym)<<32)
+		ld.Thearch.Vput(uint64(r.Xadd))
+		ld.Thearch.Vput(uint64(sectoff + 4))
+		ld.Thearch.Vput(ld.R_PPC64_ADDR16_LO | uint64(elfsym)<<32)
+
+	case obj.R_ADDRPOWER_DS:
+		ld.Thearch.Vput(ld.R_PPC64_ADDR16_HA | uint64(elfsym)<<32)
+		ld.Thearch.Vput(uint64(r.Xadd))
+		ld.Thearch.Vput(uint64(sectoff + 4))
+		ld.Thearch.Vput(ld.R_PPC64_ADDR16_LO_DS | uint64(elfsym)<<32)
+
+	case obj.R_ADDRPOWER_GOT:
+		ld.Thearch.Vput(ld.R_PPC64_GOT16_HA | uint64(elfsym)<<32)
+		ld.Thearch.Vput(uint64(r.Xadd))
+		ld.Thearch.Vput(uint64(sectoff + 4))
+		ld.Thearch.Vput(ld.R_PPC64_GOT16_LO_DS | uint64(elfsym)<<32)
+
+	case obj.R_ADDRPOWER_PCREL:
+		ld.Thearch.Vput(ld.R_PPC64_REL16_HA | uint64(elfsym)<<32)
+		ld.Thearch.Vput(uint64(r.Xadd))
+		ld.Thearch.Vput(uint64(sectoff + 4))
+		ld.Thearch.Vput(ld.R_PPC64_REL16_LO | uint64(elfsym)<<32)
+		r.Xadd += 4
+
+	case obj.R_ADDRPOWER_TOCREL:
+		ld.Thearch.Vput(ld.R_PPC64_TOC16_HA | uint64(elfsym)<<32)
+		ld.Thearch.Vput(uint64(r.Xadd))
+		ld.Thearch.Vput(uint64(sectoff + 4))
+		ld.Thearch.Vput(ld.R_PPC64_TOC16_LO | uint64(elfsym)<<32)
+
+	case obj.R_ADDRPOWER_TOCREL_DS:
+		ld.Thearch.Vput(ld.R_PPC64_TOC16_HA | uint64(elfsym)<<32)
+		ld.Thearch.Vput(uint64(r.Xadd))
+		ld.Thearch.Vput(uint64(sectoff + 4))
+		ld.Thearch.Vput(ld.R_PPC64_TOC16_LO_DS | uint64(elfsym)<<32)
+
+	case obj.R_CALLPOWER:
+		if r.Siz != 4 {
+			return -1
+		}
+		ld.Thearch.Vput(ld.R_PPC64_REL24 | uint64(elfsym)<<32)
+
+	}
+	ld.Thearch.Vput(uint64(r.Xadd))
+
+	return 0
 }
 
 func elfsetupplt() {
@@ -330,12 +492,97 @@ func symtoc(s *ld.LSym) int64 {
 	return toc.Value
 }
 
+func archrelocaddr(r *ld.Reloc, s *ld.LSym, val *int64) int {
+	var o1, o2 uint32
+	if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
+		o1 = uint32(*val >> 32)
+		o2 = uint32(*val)
+	} else {
+		o1 = uint32(*val)
+		o2 = uint32(*val >> 32)
+	}
+
+	// We are spreading a 31-bit address across two instructions, putting the
+	// high (adjusted) part in the low 16 bits of the first instruction and the
+	// low part in the low 16 bits of the second instruction, or, in the DS case,
+	// bits 15-2 (inclusive) of the address into bits 15-2 of the second
+	// instruction (it is an error in this case if the low 2 bits of the address
+	// are non-zero).
+
+	t := ld.Symaddr(r.Sym) + r.Add
+	if t < 0 || t >= 1<<31 {
+		ld.Ctxt.Diag("relocation for %s is too big (>=2G): %d", s.Name, ld.Symaddr(r.Sym))
+	}
+	if t&0x8000 != 0 {
+		t += 0x10000
+	}
+
+	switch r.Type {
+	case obj.R_ADDRPOWER:
+		o1 |= (uint32(t) >> 16) & 0xffff
+		o2 |= uint32(t) & 0xffff
+
+	case obj.R_ADDRPOWER_DS:
+		o1 |= (uint32(t) >> 16) & 0xffff
+		if t&3 != 0 {
+			ld.Ctxt.Diag("bad DS reloc for %s: %d", s.Name, ld.Symaddr(r.Sym))
+		}
+		o2 |= uint32(t) & 0xfffc
+
+	default:
+		return -1
+	}
+
+	if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
+		*val = int64(o1)<<32 | int64(o2)
+	} else {
+		*val = int64(o2)<<32 | int64(o1)
+	}
+	return 0
+}
+
 func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
 	if ld.Linkmode == ld.LinkExternal {
-		// TODO(minux): translate R_ADDRPOWER and R_CALLPOWER into standard ELF relocations.
-		// R_ADDRPOWER corresponds to R_PPC_ADDR16_HA and R_PPC_ADDR16_LO.
-		// R_CALLPOWER corresponds to R_PPC_REL24.
-		return -1
+		switch r.Type {
+		default:
+			return -1
+
+		case obj.R_POWER_TLS, obj.R_POWER_TLS_LE, obj.R_POWER_TLS_IE:
+			r.Done = 0
+			// check Outer is nil, Type is TLSBSS?
+			r.Xadd = r.Add
+			r.Xsym = r.Sym
+			return 0
+
+		case obj.R_ADDRPOWER,
+			obj.R_ADDRPOWER_DS,
+			obj.R_ADDRPOWER_TOCREL,
+			obj.R_ADDRPOWER_TOCREL_DS,
+			obj.R_ADDRPOWER_GOT,
+			obj.R_ADDRPOWER_PCREL:
+			r.Done = 0
+
+			// set up addend for eventual relocation via outer symbol.
+			rs := r.Sym
+			r.Xadd = r.Add
+			for rs.Outer != nil {
+				r.Xadd += ld.Symaddr(rs) - ld.Symaddr(rs.Outer)
+				rs = rs.Outer
+			}
+
+			if rs.Type != obj.SHOSTOBJ && rs.Type != obj.SDYNIMPORT && rs.Sect == nil {
+				ld.Diag("missing section for %s", rs.Name)
+			}
+			r.Xsym = rs
+
+			return 0
+
+		case obj.R_CALLPOWER:
+			r.Done = 0
+			r.Xsym = r.Sym
+			r.Xadd = r.Add
+			return 0
+		}
 	}
 
 	switch r.Type {
@@ -347,42 +594,11 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
 		*val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ld.Linklookup(ld.Ctxt, ".got", 0))
 		return 0
 
-	case obj.R_ADDRPOWER:
-		// r->add is two ppc64 instructions holding an immediate 32-bit constant.
-		// We want to add r->sym's address to that constant.
-		// The encoding of the immediate x<<16 + y,
-		// where x is the low 16 bits of the first instruction and y is the low 16
-		// bits of the second. Both x and y are signed (int16, not uint16).
-		o1 := uint32(r.Add >> 32)
-		o2 := uint32(r.Add)
-		t := ld.Symaddr(r.Sym)
-		if t < 0 {
-			ld.Ctxt.Diag("relocation for %s is too big (>=2G): %d", s.Name, ld.Symaddr(r.Sym))
-		}
-
-		t += int64((o1&0xffff)<<16 + uint32(int32(o2)<<16>>16))
-		if t&0x8000 != 0 {
-			t += 0x10000
-		}
-		o1 = o1&0xffff0000 | (uint32(t)>>16)&0xffff
-		o2 = o2&0xffff0000 | uint32(t)&0xffff
-
-		// when laid out, the instruction order must always be o1, o2.
-		if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
-			*val = int64(o1)<<32 | int64(o2)
-		} else {
-			*val = int64(o2)<<32 | int64(o1)
-		}
-		return 0
+	case obj.R_ADDRPOWER, obj.R_ADDRPOWER_DS:
+		return archrelocaddr(r, s, val)
 
 	case obj.R_CALLPOWER:
 		// Bits 6 through 29 = (S + A - P) >> 2
-		var o1 uint32
-		if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
-			o1 = ld.Be32(s.P[r.Off:])
-		} else {
-			o1 = ld.Le32(s.P[r.Off:])
-		}
 
 		t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off))
 		if t&3 != 0 {
@@ -394,13 +610,25 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
 			ld.Ctxt.Diag("relocation for %s+%d is too big: %d", r.Sym.Name, r.Off, t)
 		}
 
-		*val = int64(o1&0xfc000003 | uint32(t)&^0xfc000003)
+		*val |= int64(uint32(t) &^ 0xfc000003)
 		return 0
 
 	case obj.R_POWER_TOC: // S + A - .TOC.
 		*val = ld.Symaddr(r.Sym) + r.Add - symtoc(s)
 
 		return 0
+
+	case obj.R_POWER_TLS_LE:
+		// The thread pointer points 0x7000 bytes after the start of the the
+		// thread local storage area as documented in section "3.7.2 TLS
+		// Runtime Handling" of "Power Architecture 64-Bit ELF V2 ABI
+		// Specification".
+		v := r.Sym.Value - 0x7000
+		if int64(int16(v)) != v {
+			ld.Diag("TLS offset out of range %d", v)
+		}
+		*val = (*val &^ 0xffff) | (v & 0xffff)
+		return 0
 	}
 
 	return -1
@@ -578,10 +806,8 @@ func ensureglinkresolver() *ld.LSym {
 	r.Siz = 8
 	r.Type = obj.R_ADDRPOWER
 
-	// addis r11,0,.plt at ha; addi r11,r11,.plt at l
-	r.Add = 0x3d600000<<32 | 0x396b0000
-
-	glink.Size += 8
+	ld.Adduint32(ld.Ctxt, glink, 0x3d600000) // addis r11,0,.plt at ha
+	ld.Adduint32(ld.Ctxt, glink, 0x396b0000) // addi r11,r11,.plt at l
 
 	// Load r12 = dynamic resolver address and r11 = DSO
 	// identifier from the first two doublewords of the PLT.
diff --git a/src/cmd/link/internal/ppc64/l.go b/src/cmd/link/internal/ppc64/l.go
index 1275a34..1c4a4a9 100644
--- a/src/cmd/link/internal/ppc64/l.go
+++ b/src/cmd/link/internal/ppc64/l.go
@@ -63,9 +63,6 @@ package ppc64
 
 const (
 	thechar   = '9'
-	PtrSize   = 8
-	IntSize   = 8
-	RegSize   = 8
 	MaxAlign  = 32 // max data alignment
 	FuncAlign = 8
 	MINLC     = 4
diff --git a/src/cmd/link/internal/ppc64/obj.go b/src/cmd/link/internal/ppc64/obj.go
index d663b6e..c604d3b 100644
--- a/src/cmd/link/internal/ppc64/obj.go
+++ b/src/cmd/link/internal/ppc64/obj.go
@@ -98,6 +98,20 @@ func archinit() {
 		ld.Linkmode = ld.LinkInternal
 	}
 
+	switch ld.Buildmode {
+	case ld.BuildmodePIE, ld.BuildmodeShared:
+		ld.Linkmode = ld.LinkExternal
+	}
+
+	if ld.Linkshared {
+		ld.Linkmode = ld.LinkExternal
+	}
+
+	if ld.Linkmode == ld.LinkExternal {
+		toc := ld.Linklookup(ld.Ctxt, ".TOC.", 0)
+		toc.Type = obj.SDYNIMPORT
+	}
+
 	switch ld.HEADTYPE {
 	default:
 		if ld.Linkmode == ld.LinkAuto {
@@ -106,6 +120,9 @@ func archinit() {
 		if ld.Linkmode == ld.LinkExternal && obj.Getgoextlinkenabled() != "1" {
 			log.Fatalf("cannot use -linkmode=external with -H %s", ld.Headstr(int(ld.HEADTYPE)))
 		}
+
+	case obj.Hlinux:
+		break
 	}
 
 	switch ld.HEADTYPE {
diff --git a/src/cmd/link/internal/x86/asm.go b/src/cmd/link/internal/x86/asm.go
index 6495385..830a7e6 100644
--- a/src/cmd/link/internal/x86/asm.go
+++ b/src/cmd/link/internal/x86/asm.go
@@ -37,7 +37,106 @@ import (
 	"log"
 )
 
+// Append 4 bytes to s and create a R_CALL relocation targeting t to fill them in.
+func addcall(ctxt *ld.Link, s *ld.LSym, t *ld.LSym) {
+	s.Reachable = true
+	i := s.Size
+	s.Size += 4
+	ld.Symgrow(ctxt, s, s.Size)
+	r := ld.Addrel(s)
+	r.Sym = t
+	r.Off = int32(i)
+	r.Type = obj.R_CALL
+	r.Siz = 4
+}
+
 func gentext() {
+	if !ld.DynlinkingGo() && ld.Buildmode != ld.BuildmodePIE && ld.Buildmode != ld.BuildmodeCShared {
+		return
+	}
+
+	thunkfunc := ld.Linklookup(ld.Ctxt, "__x86.get_pc_thunk.cx", 0)
+	thunkfunc.Type = obj.STEXT
+	thunkfunc.Local = true
+	thunkfunc.Reachable = true
+	o := func(op ...uint8) {
+		for _, op1 := range op {
+			ld.Adduint8(ld.Ctxt, thunkfunc, op1)
+		}
+	}
+	// 8b 0c 24	mov    (%esp),%ecx
+	o(0x8b, 0x0c, 0x24)
+	// c3		ret
+	o(0xc3)
+
+	if ld.Ctxt.Etextp != nil {
+		ld.Ctxt.Etextp.Next = thunkfunc
+	} else {
+		ld.Ctxt.Textp = thunkfunc
+	}
+	ld.Ctxt.Etextp = thunkfunc
+
+	addmoduledata := ld.Linklookup(ld.Ctxt, "runtime.addmoduledata", 0)
+	if addmoduledata.Type == obj.STEXT {
+		// we're linking a module containing the runtime -> no need for
+		// an init function
+		return
+	}
+
+	addmoduledata.Reachable = true
+
+	initfunc := ld.Linklookup(ld.Ctxt, "go.link.addmoduledata", 0)
+	initfunc.Type = obj.STEXT
+	initfunc.Local = true
+	initfunc.Reachable = true
+	o = func(op ...uint8) {
+		for _, op1 := range op {
+			ld.Adduint8(ld.Ctxt, initfunc, op1)
+		}
+	}
+
+	// go.link.addmoduledata:
+	//      53                      push %ebx
+	//      e8 00 00 00 00          call __x86.get_pc_thunk.cx + R_CALL __x86.get_pc_thunk.cx
+	//      8d 81 00 00 00 00       lea 0x0(%ecx), %eax + R_PCREL ld.Ctxt.Moduledata
+	//      8d 99 00 00 00 00       lea 0x0(%ecx), %ebx + R_GOTPC _GLOBAL_OFFSET_TABLE_
+	//      e8 00 00 00 00          call runtime.addmoduledata at plt + R_CALL runtime.addmoduledata
+	//      5b                      pop %ebx
+	//      c3                      ret
+
+	o(0x53)
+
+	o(0xe8)
+	addcall(ld.Ctxt, initfunc, ld.Linklookup(ld.Ctxt, "__x86.get_pc_thunk.cx", 0))
+
+	o(0x8d, 0x81)
+	ld.Addpcrelplus(ld.Ctxt, initfunc, ld.Ctxt.Moduledata, 6)
+
+	o(0x8d, 0x99)
+	i := initfunc.Size
+	initfunc.Size += 4
+	ld.Symgrow(ld.Ctxt, initfunc, initfunc.Size)
+	r := ld.Addrel(initfunc)
+	r.Sym = ld.Linklookup(ld.Ctxt, "_GLOBAL_OFFSET_TABLE_", 0)
+	r.Off = int32(i)
+	r.Type = obj.R_PCREL
+	r.Add = 12
+	r.Siz = 4
+
+	o(0xe8)
+	addcall(ld.Ctxt, initfunc, addmoduledata)
+
+	o(0x5b)
+
+	o(0xc3)
+
+	ld.Ctxt.Etextp.Next = initfunc
+	ld.Ctxt.Etextp = initfunc
+	initarray_entry := ld.Linklookup(ld.Ctxt, "go.link.addmoduledatainit", 0)
+	initarray_entry.Reachable = true
+	initarray_entry.Local = true
+	initarray_entry.Type = obj.SINITARR
+	ld.Addaddr(ld.Ctxt, initarray_entry, initfunc)
 }
 
 func adddynrela(rela *ld.LSym, s *ld.LSym, r *ld.Reloc) {
@@ -231,7 +330,7 @@ func adddynrel(s *ld.LSym, r *ld.Reloc) {
 func elfreloc1(r *ld.Reloc, sectoff int64) int {
 	ld.Thearch.Lput(uint32(sectoff))
 
-	elfsym := r.Xsym.Elfsym
+	elfsym := r.Xsym.ElfsymForReloc()
 	switch r.Type {
 	default:
 		return -1
@@ -243,8 +342,29 @@ func elfreloc1(r *ld.Reloc, sectoff int64) int {
 			return -1
 		}
 
-	case obj.R_CALL,
-		obj.R_PCREL:
+	case obj.R_GOTPCREL:
+		if r.Siz == 4 {
+			ld.Thearch.Lput(ld.R_386_GOTPC)
+			if r.Xsym.Name != "_GLOBAL_OFFSET_TABLE_" {
+				ld.Thearch.Lput(uint32(sectoff))
+				ld.Thearch.Lput(ld.R_386_GOT32 | uint32(elfsym)<<8)
+			}
+		} else {
+			return -1
+		}
+
+	case obj.R_CALL:
+		if r.Siz == 4 {
+			if r.Xsym.Type == obj.SDYNIMPORT {
+				ld.Thearch.Lput(ld.R_386_PLT32 | uint32(elfsym)<<8)
+			} else {
+				ld.Thearch.Lput(ld.R_386_PC32 | uint32(elfsym)<<8)
+			}
+		} else {
+			return -1
+		}
+
+	case obj.R_PCREL:
 		if r.Siz == 4 {
 			ld.Thearch.Lput(ld.R_386_PC32 | uint32(elfsym)<<8)
 		} else {
@@ -257,6 +377,15 @@ func elfreloc1(r *ld.Reloc, sectoff int64) int {
 		} else {
 			return -1
 		}
+
+	case obj.R_TLS_IE:
+		if r.Siz == 4 {
+			ld.Thearch.Lput(ld.R_386_GOTPC)
+			ld.Thearch.Lput(uint32(sectoff))
+			ld.Thearch.Lput(ld.R_386_TLS_GOTIE | uint32(elfsym)<<8)
+		} else {
+			return -1
+		}
 	}
 
 	return 0
diff --git a/src/cmd/link/internal/x86/l.go b/src/cmd/link/internal/x86/l.go
index 8a811ff..c067425 100644
--- a/src/cmd/link/internal/x86/l.go
+++ b/src/cmd/link/internal/x86/l.go
@@ -33,8 +33,6 @@ package x86
 const (
 	thechar   = '8'
 	PtrSize   = 4
-	IntSize   = 4
-	RegSize   = 4
 	MaxAlign  = 32 // max data alignment
 	FuncAlign = 16
 	MINLC     = 1
diff --git a/src/cmd/link/internal/x86/obj.go b/src/cmd/link/internal/x86/obj.go
index ee408f7..c153555 100644
--- a/src/cmd/link/internal/x86/obj.go
+++ b/src/cmd/link/internal/x86/obj.go
@@ -86,6 +86,13 @@ func archinit() {
 		ld.Linkmode = ld.LinkInternal
 	}
 
+	if ld.Buildmode == ld.BuildmodeCShared || ld.Buildmode == ld.BuildmodePIE || ld.DynlinkingGo() {
+		ld.Linkmode = ld.LinkExternal
+		got := ld.Linklookup(ld.Ctxt, "_GLOBAL_OFFSET_TABLE_", 0)
+		got.Type = obj.SDYNIMPORT
+		got.Reachable = true
+	}
+
 	switch ld.HEADTYPE {
 	default:
 		if ld.Linkmode == ld.LinkAuto {
diff --git a/src/cmd/link/main.go b/src/cmd/link/main.go
index 0e6c34e..63df8de 100644
--- a/src/cmd/link/main.go
+++ b/src/cmd/link/main.go
@@ -9,6 +9,7 @@ import (
 	"cmd/link/internal/amd64"
 	"cmd/link/internal/arm"
 	"cmd/link/internal/arm64"
+	"cmd/link/internal/mips64"
 	"cmd/link/internal/ppc64"
 	"cmd/link/internal/x86"
 	"fmt"
@@ -28,6 +29,8 @@ func main() {
 		arm.Main()
 	case "arm64":
 		arm64.Main()
+	case "mips64", "mips64le":
+		mips64.Main()
 	case "ppc64", "ppc64le":
 		ppc64.Main()
 	}
diff --git a/src/cmd/objdump/objdump_test.go b/src/cmd/objdump/objdump_test.go
index b6c339b..8ceaba0 100644
--- a/src/cmd/objdump/objdump_test.go
+++ b/src/cmd/objdump/objdump_test.go
@@ -105,6 +105,8 @@ func TestDisasm(t *testing.T) {
 		t.Skipf("skipping on %s, issue 9039", runtime.GOARCH)
 	case "arm64":
 		t.Skipf("skipping on %s, issue 10106", runtime.GOARCH)
+	case "mips64", "mips64le":
+		t.Skipf("skipping on %s, issue 12559", runtime.GOARCH)
 	}
 	testDisasm(t)
 }
@@ -119,6 +121,8 @@ func TestDisasmExtld(t *testing.T) {
 		t.Skipf("skipping on %s, no support for external linking, issue 9038", runtime.GOARCH)
 	case "arm64":
 		t.Skipf("skipping on %s, issue 10106", runtime.GOARCH)
+	case "mips64", "mips64le":
+		t.Skipf("skipping on %s, issue 12559 and 12560", runtime.GOARCH)
 	}
 	// TODO(jsing): Reenable once openbsd/arm has external linking support.
 	if runtime.GOOS == "openbsd" && runtime.GOARCH == "arm" {
diff --git a/src/cmd/pprof/internal/profile/legacy_profile.go b/src/cmd/pprof/internal/profile/legacy_profile.go
index e4c92cd..c7c047a 100644
--- a/src/cmd/pprof/internal/profile/legacy_profile.go
+++ b/src/cmd/pprof/internal/profile/legacy_profile.go
@@ -589,7 +589,7 @@ func parseHeap(b []byte) (p *Profile, err error) {
 		p.Sample = append(p.Sample, &Sample{
 			Value:    value,
 			Location: sloc,
-			NumLabel: map[string][]int64{"bytes": []int64{blocksize}},
+			NumLabel: map[string][]int64{"bytes": {blocksize}},
 		})
 	}
 
diff --git a/src/cmd/pprof/internal/report/report.go b/src/cmd/pprof/internal/report/report.go
index 586f41d..0265e23 100644
--- a/src/cmd/pprof/internal/report/report.go
+++ b/src/cmd/pprof/internal/report/report.go
@@ -1505,7 +1505,7 @@ func memoryLabel(value int64, fromUnit, toUnit string) (v float64, u string, ok
 	case "megabyte", "mb":
 		value *= 1024 * 1024
 	case "gigabyte", "gb":
-		value *= 1024 * 1024
+		value *= 1024 * 1024 * 1024
 	default:
 		return 0, "", false
 	}
diff --git a/src/cmd/pprof/pprof.go b/src/cmd/pprof/pprof.go
index 44f4f6c..2b20f1d 100644
--- a/src/cmd/pprof/pprof.go
+++ b/src/cmd/pprof/pprof.go
@@ -27,6 +27,7 @@ func main() {
 	var extraCommands map[string]*commands.Command // no added Go-specific commands
 	if err := driver.PProf(flags{}, fetch.Fetcher, symbolize, new(objTool), plugin.StandardUI(), extraCommands); err != nil {
 		fmt.Fprintf(os.Stderr, "%v\n", err)
+		os.Exit(2)
 	}
 }
 
diff --git a/src/cmd/trace/main.go b/src/cmd/trace/main.go
index 27d8699..e493be9 100644
--- a/src/cmd/trace/main.go
+++ b/src/cmd/trace/main.go
@@ -71,7 +71,7 @@ func main() {
 	}
 	// Open browser.
 	if !startBrowser("http://" + ln.Addr().String()) {
-		dief("failed to start browser\n")
+		fmt.Fprintf(os.Stderr, "Trace viewer is listening on http://%s\n", ln.Addr().String())
 	}
 
 	// Parse and symbolize trace asynchronously while browser opens.
diff --git a/src/cmd/vet/cgo.go b/src/cmd/vet/cgo.go
new file mode 100644
index 0000000..1985a86
--- /dev/null
+++ b/src/cmd/vet/cgo.go
@@ -0,0 +1,130 @@
+// Copyright 2015 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.
+
+// Check for invalid cgo pointer passing.
+// This looks for code that uses cgo to call C code passing values
+// whose types are almost always invalid according to the cgo pointer
+// sharing rules.
+// Specifically, it warns about attempts to pass a Go chan, map, func,
+// or slice to C, either directly, or via a pointer, array, or struct.
+
+package main
+
+import (
+	"go/ast"
+	"go/token"
+	"go/types"
+)
+
+func init() {
+	register("cgocall",
+		"check for types that may not be passed to cgo calls",
+		checkCgoCall,
+		callExpr)
+}
+
+func checkCgoCall(f *File, node ast.Node) {
+	x := node.(*ast.CallExpr)
+
+	// We are only looking for calls to functions imported from
+	// the "C" package.
+	sel, ok := x.Fun.(*ast.SelectorExpr)
+	if !ok {
+		return
+	}
+	id, ok := sel.X.(*ast.Ident)
+	if !ok || id.Name != "C" {
+		return
+	}
+
+	for _, arg := range x.Args {
+		if !typeOKForCgoCall(cgoBaseType(f, arg)) {
+			f.Badf(arg.Pos(), "possibly passing Go type with embedded pointer to C")
+		}
+
+		// Check for passing the address of a bad type.
+		if conv, ok := arg.(*ast.CallExpr); ok && len(conv.Args) == 1 && f.hasBasicType(conv.Fun, types.UnsafePointer) {
+			arg = conv.Args[0]
+		}
+		if u, ok := arg.(*ast.UnaryExpr); ok && u.Op == token.AND {
+			if !typeOKForCgoCall(cgoBaseType(f, u.X)) {
+				f.Badf(arg.Pos(), "possibly passing Go type with embedded pointer to C")
+			}
+		}
+	}
+}
+
+// cgoBaseType tries to look through type conversions involving
+// unsafe.Pointer to find the real type.  It converts:
+//   unsafe.Pointer(x) => x
+//   *(*unsafe.Pointer)(unsafe.Pointer(&x)) => x
+func cgoBaseType(f *File, arg ast.Expr) types.Type {
+	switch arg := arg.(type) {
+	case *ast.CallExpr:
+		if len(arg.Args) == 1 && f.hasBasicType(arg.Fun, types.UnsafePointer) {
+			return cgoBaseType(f, arg.Args[0])
+		}
+	case *ast.StarExpr:
+		call, ok := arg.X.(*ast.CallExpr)
+		if !ok || len(call.Args) != 1 {
+			break
+		}
+		// Here arg is *f(v).
+		t := f.pkg.types[call.Fun].Type
+		if t == nil {
+			break
+		}
+		ptr, ok := t.Underlying().(*types.Pointer)
+		if !ok {
+			break
+		}
+		// Here arg is *(*p)(v)
+		elem, ok := ptr.Elem().Underlying().(*types.Basic)
+		if !ok || elem.Kind() != types.UnsafePointer {
+			break
+		}
+		// Here arg is *(*unsafe.Pointer)(v)
+		call, ok = call.Args[0].(*ast.CallExpr)
+		if !ok || len(call.Args) != 1 {
+			break
+		}
+		// Here arg is *(*unsafe.Pointer)(f(v))
+		if !f.hasBasicType(call.Fun, types.UnsafePointer) {
+			break
+		}
+		// Here arg is *(*unsafe.Pointer)(unsafe.Pointer(v))
+		u, ok := call.Args[0].(*ast.UnaryExpr)
+		if !ok || u.Op != token.AND {
+			break
+		}
+		// Here arg is *(*unsafe.Pointer)(unsafe.Pointer(&v))
+		return cgoBaseType(f, u.X)
+	}
+
+	return f.pkg.types[arg].Type
+}
+
+// typeOKForCgoCall returns true if the type of arg is OK to pass to a
+// C function using cgo.  This is not true for Go types with embedded
+// pointers.
+func typeOKForCgoCall(t types.Type) bool {
+	if t == nil {
+		return true
+	}
+	switch t := t.Underlying().(type) {
+	case *types.Chan, *types.Map, *types.Signature, *types.Slice:
+		return false
+	case *types.Pointer:
+		return typeOKForCgoCall(t.Elem())
+	case *types.Array:
+		return typeOKForCgoCall(t.Elem())
+	case *types.Struct:
+		for i := 0; i < t.NumFields(); i++ {
+			if !typeOKForCgoCall(t.Field(i).Type()) {
+				return false
+			}
+		}
+	}
+	return true
+}
diff --git a/src/cmd/vet/composite.go b/src/cmd/vet/composite.go
index 80b45e2..731c793 100644
--- a/src/cmd/vet/composite.go
+++ b/src/cmd/vet/composite.go
@@ -7,7 +7,7 @@
 package main
 
 import (
-	"cmd/vet/whitelist"
+	"cmd/vet/internal/whitelist"
 	"flag"
 	"go/ast"
 	"strings"
diff --git a/src/cmd/vet/copylock.go b/src/cmd/vet/copylock.go
index 6c71061..8d8399a 100644
--- a/src/cmd/vet/copylock.go
+++ b/src/cmd/vet/copylock.go
@@ -18,7 +18,7 @@ func init() {
 	register("copylocks",
 		"check that locks are not passed by value",
 		checkCopyLocks,
-		funcDecl, rangeStmt, funcLit)
+		funcDecl, rangeStmt, funcLit, assignStmt)
 }
 
 // checkCopyLocks checks whether node might
@@ -31,6 +31,18 @@ func checkCopyLocks(f *File, node ast.Node) {
 		checkCopyLocksFunc(f, node.Name.Name, node.Recv, node.Type)
 	case *ast.FuncLit:
 		checkCopyLocksFunc(f, "func", nil, node.Type)
+	case *ast.AssignStmt:
+		checkCopyLocksAssign(f, node)
+	}
+}
+
+// checkCopyLocksAssign checks whether an assignment
+// copies a lock.
+func checkCopyLocksAssign(f *File, as *ast.AssignStmt) {
+	for _, x := range as.Lhs {
+		if path := lockPath(f.pkg.typesPkg, f.pkg.types[x].Type); path != nil {
+			f.Badf(x.Pos(), "assignment copies lock value to %v: %v", f.gofmt(x), path)
+		}
 	}
 }
 
@@ -42,7 +54,7 @@ func checkCopyLocksFunc(f *File, name string, recv *ast.FieldList, typ *ast.Func
 	if recv != nil && len(recv.List) > 0 {
 		expr := recv.List[0].Type
 		if path := lockPath(f.pkg.typesPkg, f.pkg.types[expr].Type); path != nil {
-			f.Badf(expr.Pos(), "%s passes Lock by value: %v", name, path)
+			f.Badf(expr.Pos(), "%s passes lock by value: %v", name, path)
 		}
 	}
 
@@ -50,7 +62,7 @@ func checkCopyLocksFunc(f *File, name string, recv *ast.FieldList, typ *ast.Func
 		for _, field := range typ.Params.List {
 			expr := field.Type
 			if path := lockPath(f.pkg.typesPkg, f.pkg.types[expr].Type); path != nil {
-				f.Badf(expr.Pos(), "%s passes Lock by value: %v", name, path)
+				f.Badf(expr.Pos(), "%s passes lock by value: %v", name, path)
 			}
 		}
 	}
@@ -59,7 +71,7 @@ func checkCopyLocksFunc(f *File, name string, recv *ast.FieldList, typ *ast.Func
 		for _, field := range typ.Results.List {
 			expr := field.Type
 			if path := lockPath(f.pkg.typesPkg, f.pkg.types[expr].Type); path != nil {
-				f.Badf(expr.Pos(), "%s returns Lock by value: %v", name, path)
+				f.Badf(expr.Pos(), "%s returns lock by value: %v", name, path)
 			}
 		}
 	}
@@ -100,7 +112,7 @@ func checkCopyLocksRangeVar(f *File, rtok token.Token, e ast.Expr) {
 		return
 	}
 	if path := lockPath(f.pkg.typesPkg, typ); path != nil {
-		f.Badf(e.Pos(), "range var %s copies Lock: %v", f.gofmt(e), path)
+		f.Badf(e.Pos(), "range var %s copies lock: %v", f.gofmt(e), path)
 	}
 }
 
diff --git a/src/cmd/vet/doc.go b/src/cmd/vet/doc.go
index ea4654a..53db6dd 100644
--- a/src/cmd/vet/doc.go
+++ b/src/cmd/vet/doc.go
@@ -37,50 +37,6 @@ except the printf check.
 
 Available checks:
 
-Printf family
-
-Flag: -printf
-
-Suspicious calls to functions in the Printf family, including any functions
-with these names, disregarding case:
-	Print Printf Println
-	Fprint Fprintf Fprintln
-	Sprint Sprintf Sprintln
-	Error Errorf
-	Fatal Fatalf
-	Log Logf
-	Panic Panicf Panicln
-The -printfuncs flag can be used to redefine this list.
-If the function name ends with an 'f', the function is assumed to take
-a format descriptor string in the manner of fmt.Printf. If not, vet
-complains about arguments that look like format descriptor strings.
-
-It also checks for errors such as using a Writer as the first argument of
-Printf.
-
-Methods
-
-Flag: -methods
-
-Non-standard signatures for methods with familiar names, including:
-	Format GobEncode GobDecode MarshalJSON MarshalXML
-	Peek ReadByte ReadFrom ReadRune Scan Seek
-	UnmarshalJSON UnreadByte UnreadRune WriteByte
-	WriteTo
-
-Struct tags
-
-Flag: -structtags
-
-Struct tags that do not follow the format understood by reflect.StructTag.Get.
-Well-known encoding struct tags (json, xml) used with unexported fields.
-
-Unkeyed composite literals
-
-Flag: -composites
-
-Composite struct literals that do not use the field-keyed syntax.
-
 Assembly declarations
 
 Flag: -asmdecl
@@ -111,29 +67,75 @@ Flag: -buildtags
 
 Badly formed or misplaced +build tags.
 
+Invalid uses of cgo
+
+Flag: -cgocall
+
+Detect some violations of the cgo pointer passing rules.
+
+Unkeyed composite literals
+
+Flag: -composites
+
+Composite struct literals that do not use the field-keyed syntax.
+
 Copying locks
 
 Flag: -copylocks
 
 Locks that are erroneously passed by value.
 
+Documentation examples
+
+Flag: -example
+
+Mistakes involving example tests, including examples with incorrect names or
+function signatures, or that document identifiers not in the package.
+
+Methods
+
+Flag: -methods
+
+Non-standard signatures for methods with familiar names, including:
+	Format GobEncode GobDecode MarshalJSON MarshalXML
+	Peek ReadByte ReadFrom ReadRune Scan Seek
+	UnmarshalJSON UnreadByte UnreadRune WriteByte
+	WriteTo
+
 Nil function comparison
 
 Flag: -nilfunc
 
 Comparisons between functions and nil.
 
-Range loop variables
+Printf family
 
-Flag: -rangeloops
+Flag: -printf
 
-Incorrect uses of range loop variables in closures.
+Suspicious calls to functions in the Printf family, including any functions
+with these names, disregarding case:
+	Print Printf Println
+	Fprint Fprintf Fprintln
+	Sprint Sprintf Sprintln
+	Error Errorf
+	Fatal Fatalf
+	Log Logf
+	Panic Panicf Panicln
+The -printfuncs flag can be used to redefine this list.
+If the function name ends with an 'f', the function is assumed to take
+a format descriptor string in the manner of fmt.Printf. If not, vet
+complains about arguments that look like format descriptor strings.
 
-Unreachable code
+It also checks for errors such as using a Writer as the first argument of
+Printf.
 
-Flag: -unreachable
+Struct tags
 
-Unreachable code.
+Range loop variables
+
+Flag: -rangeloops
+
+Incorrect uses of range loop variables in closures.
 
 Shadowed variables
 
@@ -141,6 +143,23 @@ Flag: -shadow=false (experimental; must be set explicitly)
 
 Variables that may have been unintentionally shadowed.
 
+Shifts
+
+Flag: -shift
+
+Shifts equal to or longer than the variable's length.
+
+Flag: -structtags
+
+Struct tags that do not follow the format understood by reflect.StructTag.Get.
+Well-known encoding struct tags (json, xml) used with unexported fields.
+
+Unreachable code
+
+Flag: -unreachable
+
+Unreachable code.
+
 Misuse of unsafe Pointers
 
 Flag: -unsafeptr
@@ -160,18 +179,12 @@ discarded.  By default, this includes functions like fmt.Errorf and
 fmt.Sprintf and methods like String and Error. The flags -unusedfuncs
 and -unusedstringmethods control the set.
 
-Shifts
-
-Flag: -shift
-
-Shifts equal to or longer than the variable's length.
-
 Other flags
 
 These flags configure the behavior of vet:
 
 	-all (default true)
-		Check everything; disabled if any explicit check is requested.
+		Enable all non-experimental checks.
 	-v
 		Verbose mode
 	-printfuncs
diff --git a/src/cmd/vet/example.go b/src/cmd/vet/example.go
new file mode 100644
index 0000000..797c3ce
--- /dev/null
+++ b/src/cmd/vet/example.go
@@ -0,0 +1,124 @@
+// Copyright 2015 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 (
+	"go/ast"
+	"go/types"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+)
+
+func init() {
+	register("example",
+		"check for common mistaken usages of documentation examples",
+		checkExample,
+		funcDecl)
+}
+
+func isExampleSuffix(s string) bool {
+	r, size := utf8.DecodeRuneInString(s)
+	return size > 0 && unicode.IsLower(r)
+}
+
+// checkExample walks the documentation example functions checking for common
+// mistakes of misnamed functions, failure to map functions to existing
+// identifiers, etc.
+func checkExample(f *File, node ast.Node) {
+	if !strings.HasSuffix(f.name, "_test.go") {
+		return
+	}
+	var (
+		pkg     = f.pkg
+		pkgName = pkg.typesPkg.Name()
+		scopes  = []*types.Scope{pkg.typesPkg.Scope()}
+		lookup  = func(name string) types.Object {
+			for _, scope := range scopes {
+				if o := scope.Lookup(name); o != nil {
+					return o
+				}
+			}
+			return nil
+		}
+	)
+	if strings.HasSuffix(pkgName, "_test") {
+		// Treat 'package foo_test' as an alias for 'package foo'.
+		var (
+			basePkg = strings.TrimSuffix(pkgName, "_test")
+			pkg     = f.pkg
+		)
+		for _, p := range pkg.typesPkg.Imports() {
+			if p.Name() == basePkg {
+				scopes = append(scopes, p.Scope())
+				break
+			}
+		}
+	}
+	fn, ok := node.(*ast.FuncDecl)
+	if !ok {
+		// Ignore non-functions.
+		return
+	}
+	var (
+		fnName = fn.Name.Name
+		report = func(format string, args ...interface{}) { f.Badf(node.Pos(), format, args...) }
+	)
+	if fn.Recv != nil || !strings.HasPrefix(fnName, "Example") {
+		// Ignore methods and types not named "Example".
+		return
+	}
+	if params := fn.Type.Params; len(params.List) != 0 {
+		report("%s should be niladic", fnName)
+	}
+	if results := fn.Type.Results; results != nil && len(results.List) != 0 {
+		report("%s should return nothing", fnName)
+	}
+	if fnName == "Example" {
+		// Nothing more to do.
+		return
+	}
+	if filesRun && !includesNonTest {
+		// The coherence checks between a test and the package it tests
+		// will report false positives if no non-test files have
+		// been provided.
+		return
+	}
+	var (
+		exName = strings.TrimPrefix(fnName, "Example")
+		elems  = strings.SplitN(exName, "_", 3)
+		ident  = elems[0]
+		obj    = lookup(ident)
+	)
+	if ident != "" && obj == nil {
+		// Check ExampleFoo and ExampleBadFoo.
+		report("%s refers to unknown identifier: %s", fnName, ident)
+		// Abort since obj is absent and no subsequent checks can be performed.
+		return
+	}
+	if elemCnt := strings.Count(exName, "_"); elemCnt == 0 {
+		// Nothing more to do.
+		return
+	}
+	mmbr := elems[1]
+	if ident == "" {
+		// Check Example_suffix and Example_BadSuffix.
+		if residual := strings.TrimPrefix(exName, "_"); !isExampleSuffix(residual) {
+			report("%s has malformed example suffix: %s", fnName, residual)
+		}
+		return
+	}
+	if !isExampleSuffix(mmbr) {
+		// Check ExampleFoo_Method and ExampleFoo_BadMethod.
+		if obj, _, _ := types.LookupFieldOrMethod(obj.Type(), true, obj.Pkg(), mmbr); obj == nil {
+			report("%s refers to unknown field or method: %s.%s", fnName, ident, mmbr)
+		}
+	}
+	if len(elems) == 3 && !isExampleSuffix(elems[2]) {
+		// Check ExampleFoo_Method_suffix and ExampleFoo_Method_Badsuffix.
+		report("%s has malformed example suffix: %s", fnName, elems[2])
+	}
+	return
+}
diff --git a/src/cmd/vet/internal/whitelist/whitelist.go b/src/cmd/vet/internal/whitelist/whitelist.go
new file mode 100644
index 0000000..b6c8585
--- /dev/null
+++ b/src/cmd/vet/internal/whitelist/whitelist.go
@@ -0,0 +1,53 @@
+// Copyright 2013 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 whitelist defines exceptions for the vet tool.
+package whitelist
+
+// UnkeyedLiteral are types that are actually slices, but
+// syntactically, we cannot tell whether the Typ in pkg.Typ{1, 2, 3}
+// is a slice or a struct, so we whitelist all the standard package
+// library's exported slice types.
+var UnkeyedLiteral = map[string]bool{
+	/*
+		find $GOROOT/src -type f | grep -v _test.go | xargs grep '^type.*\[\]' | \
+			grep -v ' map\[' | sed 's,/[^/]*go.type,,' | sed 's,.*src/,,' | \
+			sed 's, ,.,' |  sed 's, .*,,' | grep -v '\.[a-z]' | \
+			sort | awk '{ print "\"" $0 "\": true," }'
+	*/
+	"crypto/x509/pkix.RDNSequence":                  true,
+	"crypto/x509/pkix.RelativeDistinguishedNameSET": true,
+	"database/sql.RawBytes":                         true,
+	"debug/macho.LoadBytes":                         true,
+	"encoding/asn1.ObjectIdentifier":                true,
+	"encoding/asn1.RawContent":                      true,
+	"encoding/json.RawMessage":                      true,
+	"encoding/xml.CharData":                         true,
+	"encoding/xml.Comment":                          true,
+	"encoding/xml.Directive":                        true,
+	"go/scanner.ErrorList":                          true,
+	"image/color.Palette":                           true,
+	"net.HardwareAddr":                              true,
+	"net.IP":                                        true,
+	"net.IPMask":                                    true,
+	"sort.Float64Slice":                             true,
+	"sort.IntSlice":                                 true,
+	"sort.StringSlice":                              true,
+	"unicode.SpecialCase":                           true,
+
+	// These image and image/color struct types are frozen. We will never add fields to them.
+	"image/color.Alpha16": true,
+	"image/color.Alpha":   true,
+	"image/color.CMYK":    true,
+	"image/color.Gray16":  true,
+	"image/color.Gray":    true,
+	"image/color.NRGBA64": true,
+	"image/color.NRGBA":   true,
+	"image/color.RGBA64":  true,
+	"image/color.RGBA":    true,
+	"image/color.YCbCr":   true,
+	"image.Point":         true,
+	"image.Rectangle":     true,
+	"image.Uniform":       true,
+}
diff --git a/src/cmd/vet/main.go b/src/cmd/vet/main.go
index 453cfe0..23c041b 100644
--- a/src/cmd/vet/main.go
+++ b/src/cmd/vet/main.go
@@ -32,9 +32,8 @@ var (
 
 var exitCode = 0
 
-// "all" is here only for the appearance of backwards compatibility.
-// It has no effect; the triState flags do the work.
-var all = flag.Bool("all", true, "check everything; disabled if any explicit check is requested")
+// "-all" flag enables all non-experimental checks
+var all = triStateFlag("all", unset, "enable all non-experimental checks")
 
 // Flags to control which individual checks to perform.
 var report = map[string]*triState{
@@ -51,6 +50,14 @@ var experimental = map[string]bool{}
 // setTrueCount record how many flags are explicitly set to true.
 var setTrueCount int
 
+// dirsRun and filesRun indicate whether the vet is applied to directory or
+// file targets. The distinction affects which checks are run.
+var dirsRun, filesRun bool
+
+// includesNonTest indicates whether the vet is applied to non-test targets.
+// Certain checks are relevant only if they touch both test and non-test files.
+var includesNonTest bool
+
 // A triState is a boolean that knows whether it has been set to either true or false.
 // It is used to identify if a flag appears; the standard boolean flag cannot
 // distinguish missing from unset. It also satisfies flag.Value.
@@ -161,7 +168,7 @@ func Usage() {
 	fmt.Fprintf(os.Stderr, "\tvet [flags] directory...\n")
 	fmt.Fprintf(os.Stderr, "\tvet [flags] files... # Must be a single package\n")
 	fmt.Fprintf(os.Stderr, "For more information run\n")
-	fmt.Fprintf(os.Stderr, "\tgodoc golang.org/x/tools/cmd/vet\n\n")
+	fmt.Fprintf(os.Stderr, "\tgodoc cmd/vet\n\n")
 	fmt.Fprintf(os.Stderr, "Flags:\n")
 	flag.PrintDefaults()
 	os.Exit(2)
@@ -190,8 +197,9 @@ func main() {
 	flag.Parse()
 
 	// If any flag is set, we run only those checks requested.
-	// If no flags are set true, set all the non-experimental ones not explicitly set (in effect, set the "-all" flag).
-	if setTrueCount == 0 {
+	// If all flag is set true or if no flags are set true, set all the non-experimental ones
+	// not explicitly set (in effect, set the "-all" flag).
+	if setTrueCount == 0 || *all == setTrue {
 		for name, setting := range report {
 			if *setting == unset && !experimental[name] {
 				*setting = setTrue
@@ -207,8 +215,6 @@ func main() {
 	if flag.NArg() == 0 {
 		Usage()
 	}
-	dirs := false
-	files := false
 	for _, name := range flag.Args() {
 		// Is it a directory?
 		fi, err := os.Stat(name)
@@ -217,15 +223,18 @@ func main() {
 			continue
 		}
 		if fi.IsDir() {
-			dirs = true
+			dirsRun = true
 		} else {
-			files = true
+			filesRun = true
+			if !strings.HasSuffix(name, "_test.go") {
+				includesNonTest = true
+			}
 		}
 	}
-	if dirs && files {
+	if dirsRun && filesRun {
 		Usage()
 	}
-	if dirs {
+	if dirsRun {
 		for _, name := range flag.Args() {
 			walkDir(name)
 		}
diff --git a/src/cmd/vet/print.go b/src/cmd/vet/print.go
index d79b096..a16e864 100644
--- a/src/cmd/vet/print.go
+++ b/src/cmd/vet/print.go
@@ -445,6 +445,10 @@ func (f *File) okPrintfArg(call *ast.CallExpr, state *formatState) (ok bool) {
 		return false
 	}
 	arg := call.Args[argNum]
+	if f.isFunctionValue(arg) && state.verb != 'p' && state.verb != 'T' {
+		f.Badf(call.Pos(), "arg %s in printf call is a function value, not a function call", f.gofmt(arg))
+		return false
+	}
 	if !f.matchArgType(v.typ, nil, arg) {
 		typeString := ""
 		if typ := f.pkg.types[arg].Type; typ != nil {
@@ -490,6 +494,16 @@ func (f *File) recursiveStringer(e ast.Expr) bool {
 	return f.stringers[obj]
 }
 
+// isFunctionValue reports whether the expression is a function as opposed to a function call.
+// It is almost always a mistake to print a function value.
+func (f *File) isFunctionValue(e ast.Expr) bool {
+	if typ := f.pkg.types[e].Type; typ != nil {
+		_, ok := typ.(*types.Signature)
+		return ok
+	}
+	return false
+}
+
 // argCanBeChecked reports whether the specified argument is statically present;
 // it may be beyond the list of arguments or in a terminal slice... argument, which
 // means we can't see it.
@@ -579,8 +593,11 @@ func (f *File) checkPrint(call *ast.CallExpr, name string, firstArg int) {
 		}
 	}
 	for _, arg := range args {
+		if f.isFunctionValue(arg) {
+			f.Badf(call.Pos(), "arg %s in %s call is a function value, not a function call", f.gofmt(arg), name)
+		}
 		if f.recursiveStringer(arg) {
-			f.Badf(call.Pos(), "arg %s for print causes recursive call to String method", f.gofmt(arg))
+			f.Badf(call.Pos(), "arg %s in %s call causes recursive call to String method", f.gofmt(arg), name)
 		}
 	}
 }
diff --git a/src/cmd/vet/shadow.go b/src/cmd/vet/shadow.go
index 2149e70..5d0d6b5 100644
--- a/src/cmd/vet/shadow.go
+++ b/src/cmd/vet/shadow.go
@@ -155,6 +155,8 @@ func (f *File) idiomaticShortRedecl(a *ast.AssignStmt) bool {
 					return false
 				}
 			}
+		default:
+			return false
 		}
 	}
 	return true
diff --git a/src/cmd/vet/testdata/cgo.go b/src/cmd/vet/testdata/cgo.go
new file mode 100644
index 0000000..5ce6007
--- /dev/null
+++ b/src/cmd/vet/testdata/cgo.go
@@ -0,0 +1,54 @@
+// Copyright 2015 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 file contains tests for the cgo checker.
+
+package testdata
+
+// void f(void *);
+import "C"
+
+import "unsafe"
+
+func CgoTests() {
+	var c chan bool
+	C.f(*(*unsafe.Pointer)(unsafe.Pointer(&c))) // ERROR "embedded pointer"
+	C.f(unsafe.Pointer(&c))                     // ERROR "embedded pointer"
+
+	var m map[string]string
+	C.f(*(*unsafe.Pointer)(unsafe.Pointer(&m))) // ERROR "embedded pointer"
+	C.f(unsafe.Pointer(&m))                     // ERROR "embedded pointer"
+
+	var f func()
+	C.f(*(*unsafe.Pointer)(unsafe.Pointer(&f))) // ERROR "embedded pointer"
+	C.f(unsafe.Pointer(&f))                     // ERROR "embedded pointer"
+
+	var s []int
+	C.f(*(*unsafe.Pointer)(unsafe.Pointer(&s))) // ERROR "embedded pointer"
+	C.f(unsafe.Pointer(&s))                     // ERROR "embedded pointer"
+
+	var a [1][]int
+	C.f(*(*unsafe.Pointer)(unsafe.Pointer(&a))) // ERROR "embedded pointer"
+	C.f(unsafe.Pointer(&a))                     // ERROR "embedded pointer"
+
+	var st struct{ f []int }
+	C.f(*(*unsafe.Pointer)(unsafe.Pointer(&st))) // ERROR "embedded pointer"
+	C.f(unsafe.Pointer(&st))                     // ERROR "embedded pointer"
+
+	// The following cases are OK.
+	var i int
+	C.f(*(*unsafe.Pointer)(unsafe.Pointer(&i)))
+	C.f(unsafe.Pointer(&i))
+
+	C.f(*(*unsafe.Pointer)(unsafe.Pointer(&s[0])))
+	C.f(unsafe.Pointer(&s[0]))
+
+	var a2 [1]int
+	C.f(*(*unsafe.Pointer)(unsafe.Pointer(&a2)))
+	C.f(unsafe.Pointer(&a2))
+
+	var st2 struct{ i int }
+	C.f(*(*unsafe.Pointer)(unsafe.Pointer(&st2)))
+	C.f(unsafe.Pointer(&st2))
+}
diff --git a/src/cmd/vet/testdata/cgo2.go b/src/cmd/vet/testdata/cgo2.go
new file mode 100644
index 0000000..276aea9
--- /dev/null
+++ b/src/cmd/vet/testdata/cgo2.go
@@ -0,0 +1,9 @@
+// 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.
+
+// Test the cgo checker on a file that doesn't use cgo.
+
+package testdata
+
+var _ = C.f(*p(**p))
diff --git a/src/cmd/vet/testdata/copylock.go b/src/cmd/vet/testdata/copylock.go
new file mode 100644
index 0000000..03d0c33
--- /dev/null
+++ b/src/cmd/vet/testdata/copylock.go
@@ -0,0 +1,28 @@
+package testdata
+
+import "sync"
+
+func OkFunc() {
+	var x *sync.Mutex
+	p := x
+	var y sync.Mutex
+	p = &y
+}
+
+type Tlock struct {
+	once sync.Once
+}
+
+func BadFunc() {
+	var x *sync.Mutex
+	p := x
+	var y sync.Mutex
+	p = &y
+	*p = *x // ERROR "assignment copies lock value to \*p: sync.Mutex"
+
+	var t Tlock
+	var tp *Tlock
+	tp = &t
+	*tp = t // ERROR "assignment copies lock value to \*tp: testdata.Tlock contains sync.Once contains sync.Mutex"
+	t = *tp // ERROR "assignment copies lock value to t: testdata.Tlock contains sync.Once contains sync.Mutex"
+}
diff --git a/src/cmd/vet/testdata/copylock_func.go b/src/cmd/vet/testdata/copylock_func.go
index d83957f..62725d9 100644
--- a/src/cmd/vet/testdata/copylock_func.go
+++ b/src/cmd/vet/testdata/copylock_func.go
@@ -10,13 +10,13 @@ package testdata
 import "sync"
 
 func OkFunc(*sync.Mutex) {}
-func BadFunc(sync.Mutex) {} // ERROR "BadFunc passes Lock by value: sync.Mutex"
+func BadFunc(sync.Mutex) {} // ERROR "BadFunc passes lock by value: sync.Mutex"
 func OkRet() *sync.Mutex {}
-func BadRet() sync.Mutex {} // ERROR "BadRet returns Lock by value: sync.Mutex"
+func BadRet() sync.Mutex {} // ERROR "BadRet returns lock by value: sync.Mutex"
 
 var (
 	OkClosure  = func(*sync.Mutex) {}
-	BadClosure = func(sync.Mutex) {} // ERROR "func passes Lock by value: sync.Mutex"
+	BadClosure = func(sync.Mutex) {} // ERROR "func passes lock by value: sync.Mutex"
 )
 
 type EmbeddedRWMutex struct {
@@ -24,20 +24,20 @@ type EmbeddedRWMutex struct {
 }
 
 func (*EmbeddedRWMutex) OkMeth() {}
-func (EmbeddedRWMutex) BadMeth() {} // ERROR "BadMeth passes Lock by value: testdata.EmbeddedRWMutex"
+func (EmbeddedRWMutex) BadMeth() {} // ERROR "BadMeth passes lock by value: testdata.EmbeddedRWMutex"
 func OkFunc(e *EmbeddedRWMutex)  {}
-func BadFunc(EmbeddedRWMutex)    {} // ERROR "BadFunc passes Lock by value: testdata.EmbeddedRWMutex"
+func BadFunc(EmbeddedRWMutex)    {} // ERROR "BadFunc passes lock by value: testdata.EmbeddedRWMutex"
 func OkRet() *EmbeddedRWMutex    {}
-func BadRet() EmbeddedRWMutex    {} // ERROR "BadRet returns Lock by value: testdata.EmbeddedRWMutex"
+func BadRet() EmbeddedRWMutex    {} // ERROR "BadRet returns lock by value: testdata.EmbeddedRWMutex"
 
 type FieldMutex struct {
 	s sync.Mutex
 }
 
 func (*FieldMutex) OkMeth()   {}
-func (FieldMutex) BadMeth()   {} // ERROR "BadMeth passes Lock by value: testdata.FieldMutex contains sync.Mutex"
+func (FieldMutex) BadMeth()   {} // ERROR "BadMeth passes lock by value: testdata.FieldMutex contains sync.Mutex"
 func OkFunc(*FieldMutex)      {}
-func BadFunc(FieldMutex, int) {} // ERROR "BadFunc passes Lock by value: testdata.FieldMutex contains sync.Mutex"
+func BadFunc(FieldMutex, int) {} // ERROR "BadFunc passes lock by value: testdata.FieldMutex contains sync.Mutex"
 
 type L0 struct {
 	L1
@@ -52,7 +52,7 @@ type L2 struct {
 }
 
 func (*L0) Ok() {}
-func (L0) Bad() {} // ERROR "Bad passes Lock by value: testdata.L0 contains testdata.L1 contains testdata.L2"
+func (L0) Bad() {} // ERROR "Bad passes lock by value: testdata.L0 contains testdata.L1 contains testdata.L2"
 
 type EmbeddedMutexPointer struct {
 	s *sync.Mutex // safe to copy this pointer
@@ -76,7 +76,7 @@ func (*CustomLock) Lock()   {}
 func (*CustomLock) Unlock() {}
 
 func Ok(*CustomLock) {}
-func Bad(CustomLock) {} // ERROR "Bad passes Lock by value: testdata.CustomLock"
+func Bad(CustomLock) {} // ERROR "Bad passes lock by value: testdata.CustomLock"
 
 // TODO: Unfortunate cases
 
@@ -85,7 +85,7 @@ func Bad(CustomLock) {} // ERROR "Bad passes Lock by value: testdata.CustomLock"
 // sync.Mutex gets called out, but without any reference to the sync.Once.
 type LocalOnce sync.Once
 
-func (LocalOnce) Bad() {} // ERROR "Bad passes Lock by value: testdata.LocalOnce contains sync.Mutex"
+func (LocalOnce) Bad() {} // ERROR "Bad passes lock by value: testdata.LocalOnce contains sync.Mutex"
 
 // False negative:
 // LocalMutex doesn't have a Lock method.
diff --git a/src/cmd/vet/testdata/copylock_range.go b/src/cmd/vet/testdata/copylock_range.go
index f95b025..f127381 100644
--- a/src/cmd/vet/testdata/copylock_range.go
+++ b/src/cmd/vet/testdata/copylock_range.go
@@ -24,37 +24,37 @@ func rangeMutex() {
 	}
 	for i, _ := range s {
 	}
-	for _, mu = range s { // ERROR "range var mu copies Lock: sync.Mutex"
+	for _, mu = range s { // ERROR "range var mu copies lock: sync.Mutex"
 	}
-	for _, m := range s { // ERROR "range var m copies Lock: sync.Mutex"
+	for _, m := range s { // ERROR "range var m copies lock: sync.Mutex"
 	}
-	for i, mu = range s { // ERROR "range var mu copies Lock: sync.Mutex"
+	for i, mu = range s { // ERROR "range var mu copies lock: sync.Mutex"
 	}
-	for i, m := range s { // ERROR "range var m copies Lock: sync.Mutex"
+	for i, m := range s { // ERROR "range var m copies lock: sync.Mutex"
 	}
 
 	var a [3]sync.Mutex
-	for _, m := range a { // ERROR "range var m copies Lock: sync.Mutex"
+	for _, m := range a { // ERROR "range var m copies lock: sync.Mutex"
 	}
 
 	var m map[sync.Mutex]sync.Mutex
-	for k := range m { // ERROR "range var k copies Lock: sync.Mutex"
+	for k := range m { // ERROR "range var k copies lock: sync.Mutex"
 	}
-	for mu, _ = range m { // ERROR "range var mu copies Lock: sync.Mutex"
+	for mu, _ = range m { // ERROR "range var mu copies lock: sync.Mutex"
 	}
-	for k, _ := range m { // ERROR "range var k copies Lock: sync.Mutex"
+	for k, _ := range m { // ERROR "range var k copies lock: sync.Mutex"
 	}
-	for _, mu = range m { // ERROR "range var mu copies Lock: sync.Mutex"
+	for _, mu = range m { // ERROR "range var mu copies lock: sync.Mutex"
 	}
-	for _, v := range m { // ERROR "range var v copies Lock: sync.Mutex"
+	for _, v := range m { // ERROR "range var v copies lock: sync.Mutex"
 	}
 
 	var c chan sync.Mutex
 	for range c {
 	}
-	for mu = range c { // ERROR "range var mu copies Lock: sync.Mutex"
+	for mu = range c { // ERROR "range var mu copies lock: sync.Mutex"
 	}
-	for v := range c { // ERROR "range var v copies Lock: sync.Mutex"
+	for v := range c { // ERROR "range var v copies lock: sync.Mutex"
 	}
 
 	// Test non-idents in range variables
@@ -62,6 +62,6 @@ func rangeMutex() {
 		i  int
 		mu sync.Mutex
 	}
-	for t.i, t.mu = range s { // ERROR "range var t.mu copies Lock: sync.Mutex"
+	for t.i, t.mu = range s { // ERROR "range var t.mu copies lock: sync.Mutex"
 	}
 }
diff --git a/src/cmd/vet/testdata/divergent/buf.go b/src/cmd/vet/testdata/divergent/buf.go
new file mode 100644
index 0000000..0efe0f8
--- /dev/null
+++ b/src/cmd/vet/testdata/divergent/buf.go
@@ -0,0 +1,17 @@
+// Test of examples with divergent packages.
+
+// Package buf ...
+package buf
+
+// Buf is a ...
+type Buf []byte
+
+// Append ...
+func (*Buf) Append([]byte) {}
+
+func (Buf) Reset() {}
+
+func (Buf) Len() int { return 0 }
+
+// DefaultBuf is a ...
+var DefaultBuf Buf
diff --git a/src/cmd/vet/testdata/divergent/buf_test.go b/src/cmd/vet/testdata/divergent/buf_test.go
new file mode 100644
index 0000000..6b9cba3
--- /dev/null
+++ b/src/cmd/vet/testdata/divergent/buf_test.go
@@ -0,0 +1,35 @@
+// Test of examples with divergent packages.
+
+package buf_test
+
+func Example() {} // OK because is package-level.
+
+func Example_suffix() // OK because refers to suffix annotation.
+
+func Example_BadSuffix() // ERROR "Example_BadSuffix has malformed example suffix: BadSuffix"
+
+func ExampleBuf() // OK because refers to known top-level type.
+
+func ExampleBuf_Append() {} // OK because refers to known method.
+
+func ExampleBuf_Clear() {} // ERROR "ExampleBuf_Clear refers to unknown field or method: Buf.Clear"
+
+func ExampleBuf_suffix() {} // OK because refers to suffix annotation.
+
+func ExampleBuf_Append_Bad() {} // ERROR "ExampleBuf_Append_Bad has malformed example suffix: Bad"
+
+func ExampleBuf_Append_suffix() {} // OK because refers to known method with valid suffix.
+
+func ExampleDefaultBuf() {} // OK because refers to top-level identifier.
+
+func ExampleBuf_Reset() bool { return true } // ERROR "ExampleBuf_Reset should return nothing"
+
+func ExampleBuf_Len(i int) {} // ERROR "ExampleBuf_Len should be niladic"
+
+// "Puffer" is German for "Buffer".
+
+func ExamplePuffer() // ERROR "ExamplePuffer refers to unknown identifier: Puffer"
+
+func ExamplePuffer_Append() // ERROR "ExamplePuffer_Append refers to unknown identifier: Puffer"
+
+func ExamplePuffer_suffix() // ERROR "ExamplePuffer_suffix refers to unknown identifier: Puffer"
diff --git a/src/cmd/vet/testdata/examples_test.go b/src/cmd/vet/testdata/examples_test.go
new file mode 100644
index 0000000..9c53672
--- /dev/null
+++ b/src/cmd/vet/testdata/examples_test.go
@@ -0,0 +1,48 @@
+// Test of examples.
+
+package testdata
+
+// Buf is a ...
+type Buf []byte
+
+// Append ...
+func (*Buf) Append([]byte) {}
+
+func (Buf) Reset() {}
+
+func (Buf) Len() int { return 0 }
+
+// DefaultBuf is a ...
+var DefaultBuf Buf
+
+func Example() {} // OK because is package-level.
+
+func Example_goodSuffix() // OK because refers to suffix annotation.
+
+func Example_BadSuffix() // ERROR "Example_BadSuffix has malformed example suffix: BadSuffix"
+
+func ExampleBuf() // OK because refers to known top-level type.
+
+func ExampleBuf_Append() {} // OK because refers to known method.
+
+func ExampleBuf_Clear() {} // ERROR "ExampleBuf_Clear refers to unknown field or method: Buf.Clear"
+
+func ExampleBuf_suffix() {} // OK because refers to suffix annotation.
+
+func ExampleBuf_Append_Bad() {} // ERROR "ExampleBuf_Append_Bad has malformed example suffix: Bad"
+
+func ExampleBuf_Append_suffix() {} // OK because refers to known method with valid suffix.
+
+func ExampleDefaultBuf() {} // OK because refers to top-level identifier.
+
+func ExampleBuf_Reset() bool { return true } // ERROR "ExampleBuf_Reset should return nothing"
+
+func ExampleBuf_Len(i int) {} // ERROR "ExampleBuf_Len should be niladic"
+
+// "Puffer" is German for "Buffer".
+
+func ExamplePuffer() // ERROR "ExamplePuffer refers to unknown identifier: Puffer"
+
+func ExamplePuffer_Append() // ERROR "ExamplePuffer_Append refers to unknown identifier: Puffer"
+
+func ExamplePuffer_suffix() // ERROR "ExamplePuffer_suffix refers to unknown identifier: Puffer"
diff --git a/src/cmd/vet/testdata/incomplete/examples_test.go b/src/cmd/vet/testdata/incomplete/examples_test.go
new file mode 100644
index 0000000..445502b
--- /dev/null
+++ b/src/cmd/vet/testdata/incomplete/examples_test.go
@@ -0,0 +1,33 @@
+// Test of examples.
+
+package testdata
+
+func Example() {} // OK because is package-level.
+
+func Example_suffix() // OK because refers to suffix annotation.
+
+func Example_BadSuffix() // OK because non-test package was excluded.  No false positives wanted.
+
+func ExampleBuf() // OK because non-test package was excluded.  No false positives wanted.
+
+func ExampleBuf_Append() {} // OK because non-test package was excluded.  No false positives wanted.
+
+func ExampleBuf_Clear() {} // OK because non-test package was excluded.  No false positives wanted.
+
+func ExampleBuf_suffix() {} // OK because refers to suffix annotation.
+
+func ExampleBuf_Append_Bad() {} // OK because non-test package was excluded.  No false positives wanted.
+
+func ExampleBuf_Append_suffix() {} // OK because refers to known method with valid suffix.
+
+func ExampleBuf_Reset() bool { return true } // ERROR "ExampleBuf_Reset should return nothing"
+
+func ExampleBuf_Len(i int) {} // ERROR "ExampleBuf_Len should be niladic"
+
+// "Puffer" is German for "Buffer".
+
+func ExamplePuffer() // OK because non-test package was excluded.  No false positives wanted.
+
+func ExamplePuffer_Append() // OK because non-test package was excluded.  No false positives wanted.
+
+func ExamplePuffer_suffix() // OK because non-test package was excluded.  No false positives wanted.
diff --git a/src/cmd/vet/testdata/print.go b/src/cmd/vet/testdata/print.go
index 3390a31..c5faa36 100644
--- a/src/cmd/vet/testdata/print.go
+++ b/src/cmd/vet/testdata/print.go
@@ -195,6 +195,12 @@ func PrintfTests() {
 	et4.Error() // ok, not an error method.
 	var et5 errorTest5
 	et5.error() // ok, not an error method.
+	// Can't print a function.
+	Printf("%d", someFunction) // ERROR "arg someFunction in printf call is a function value, not a function call"
+	Printf("%v", someFunction) // ERROR "arg someFunction in printf call is a function value, not a function call"
+	Println(someFunction)      // ERROR "arg someFunction in Println call is a function value, not a function call"
+	Printf("%p", someFunction) // ok: maybe someone wants to see the pointer
+	Printf("%T", someFunction) // ok: maybe someone wants to see the type
 	// Bug: used to recur forever.
 	Printf("%p %x", recursiveStructV, recursiveStructV.next)
 	Printf("%p %x", recursiveStruct1V, recursiveStruct1V.next)
@@ -209,6 +215,10 @@ func PrintfTests() {
 
 }
 
+// A function we use as a function value; it has no other purpose.
+func someFunction() {
+}
+
 // Printf is used by the test so we must declare it.
 func Printf(format string, args ...interface{}) {
 	panic("don't call - testing only")
@@ -297,14 +307,14 @@ func (s recursiveStringer) String() string {
 	_ = fmt.Sprintf("%v", s)  // ERROR "arg s for printf causes recursive call to String method"
 	_ = fmt.Sprintf("%v", &s) // ERROR "arg &s for printf causes recursive call to String method"
 	_ = fmt.Sprintf("%T", s)  // ok; does not recursively call String
-	return fmt.Sprintln(s)    // ERROR "arg s for print causes recursive call to String method"
+	return fmt.Sprintln(s)    // ERROR "arg s in Sprintln call causes recursive call to String method"
 }
 
 type recursivePtrStringer int
 
 func (p *recursivePtrStringer) String() string {
 	_ = fmt.Sprintf("%v", *p)
-	return fmt.Sprintln(p) // ERROR "arg p for print causes recursive call to String method"
+	return fmt.Sprintln(p) // ERROR "arg p in Sprintln call causes recursive call to String method"
 }
 
 type Formatter bool
diff --git a/src/cmd/vet/testdata/shadow.go b/src/cmd/vet/testdata/shadow.go
index 34a6806..241109f 100644
--- a/src/cmd/vet/testdata/shadow.go
+++ b/src/cmd/vet/testdata/shadow.go
@@ -25,8 +25,9 @@ func ShadowRead(f *os.File, buf []byte) (err error) {
 		_ = i
 	}
 	if f != nil {
+		x := one()               // ERROR "declaration of x shadows declaration at testdata/shadow.go:14"
 		var _, err = f.Read(buf) // ERROR "declaration of err shadows declaration at testdata/shadow.go:13"
-		if err != nil {
+		if x == 1 && err != nil {
 			return err
 		}
 	}
@@ -52,3 +53,7 @@ func ShadowRead(f *os.File, buf []byte) (err error) {
 	_, _ = err, x
 	return
 }
+
+func one() int {
+	return 1
+}
diff --git a/src/cmd/vet/vet_test.go b/src/cmd/vet/vet_test.go
index 9aae8dd..c1026a3 100644
--- a/src/cmd/vet/vet_test.go
+++ b/src/cmd/vet/vet_test.go
@@ -6,6 +6,8 @@ package main_test
 
 import (
 	"bytes"
+	"flag"
+	"fmt"
 	"internal/testenv"
 	"os"
 	"os/exec"
@@ -19,49 +21,92 @@ const (
 	binary  = "testvet.exe"
 )
 
-// Run this shell script, but do it in Go so it can be run by "go test".
-// 	go build -o testvet
-// 	$(GOROOT)/test/errchk ./testvet -shadow -printfuncs='Warn:1,Warnf:1' testdata/*.go testdata/*.s
-// 	rm testvet
-//
-func TestVet(t *testing.T) {
-	testenv.MustHaveGoBuild(t)
+// We implement TestMain so remove the test binary when all is done.
+func TestMain(m *testing.M) {
+	flag.Parse()
+	result := m.Run()
+	os.Remove(binary)
+	os.Exit(result)
+}
 
+func MustHavePerl(t *testing.T) {
 	switch runtime.GOOS {
 	case "plan9", "windows":
-		// Plan 9 and Windows systems can't be guaranteed to have Perl and so can't run errchk.
-		t.Skipf("skipping test; no Perl on %q", runtime.GOOS)
+		t.Skipf("skipping test: perl not available on %s", runtime.GOOS)
 	}
+}
 
-	// go build
-	cmd := exec.Command("go", "build", "-o", binary)
-	run(cmd, t)
-
-	// defer removal of vet
-	defer os.Remove(binary)
+var (
+	built  = false // We have built the binary.
+	failed = false // We have failed to build the binary, don't try again.
+)
 
-	// errchk ./testvet
-	gos, err := filepath.Glob(filepath.Join(dataDir, "*.go"))
-	if err != nil {
-		t.Fatal(err)
+func Build(t *testing.T) {
+	if built {
+		return
 	}
-	asms, err := filepath.Glob(filepath.Join(dataDir, "*.s"))
+	testenv.MustHaveGoBuild(t)
+	MustHavePerl(t)
+	if failed {
+		t.Skip("cannot run on this environment")
+	}
+	cmd := exec.Command("go", "build", "-o", binary)
+	output, err := cmd.CombinedOutput()
 	if err != nil {
+		failed = true
+		fmt.Fprintf(os.Stderr, "%s\n", output)
 		t.Fatal(err)
 	}
-	files := append(gos, asms...)
+	built = true
+}
+
+func Vet(t *testing.T, files []string) {
 	errchk := filepath.Join(runtime.GOROOT(), "test", "errchk")
 	flags := []string{
 		"./" + binary,
 		"-printfuncs=Warn:1,Warnf:1",
 		"-test", // TODO: Delete once -shadow is part of -all.
 	}
-	cmd = exec.Command(errchk, append(flags, files...)...)
+	cmd := exec.Command(errchk, append(flags, files...)...)
 	if !run(cmd, t) {
 		t.Fatal("vet command failed")
 	}
 }
 
+// Run this shell script, but do it in Go so it can be run by "go test".
+// 	go build -o testvet
+// 	$(GOROOT)/test/errchk ./testvet -shadow -printfuncs='Warn:1,Warnf:1' testdata/*.go testdata/*.s
+// 	rm testvet
+//
+
+func TestVet(t *testing.T) {
+	Build(t)
+
+	// errchk ./testvet
+	gos, err := filepath.Glob(filepath.Join(dataDir, "*.go"))
+	if err != nil {
+		t.Fatal(err)
+	}
+	asms, err := filepath.Glob(filepath.Join(dataDir, "*.s"))
+	if err != nil {
+		t.Fatal(err)
+	}
+	files := append(gos, asms...)
+	Vet(t, files)
+}
+
+func TestDivergentPackagesExamples(t *testing.T) {
+	Build(t)
+	// errchk ./testvet
+	Vet(t, []string{"testdata/divergent/buf.go", "testdata/divergent/buf_test.go"})
+}
+
+func TestIncompleteExamples(t *testing.T) {
+	Build(t)
+	// errchk ./testvet
+	Vet(t, []string{"testdata/incomplete/examples_test.go"})
+}
+
 func run(c *exec.Cmd, t *testing.T) bool {
 	output, err := c.CombinedOutput()
 	os.Stderr.Write(output)
@@ -78,21 +123,13 @@ func run(c *exec.Cmd, t *testing.T) bool {
 
 // TestTags verifies that the -tags argument controls which files to check.
 func TestTags(t *testing.T) {
-	testenv.MustHaveGoBuild(t)
-
-	// go build
-	cmd := exec.Command("go", "build", "-o", binary)
-	run(cmd, t)
-
-	// defer removal of vet
-	defer os.Remove(binary)
-
+	Build(t)
 	args := []string{
 		"-tags=testtag",
 		"-v", // We're going to look at the files it examines.
 		"testdata/tagtest",
 	}
-	cmd = exec.Command("./"+binary, args...)
+	cmd := exec.Command("./"+binary, args...)
 	output, err := cmd.CombinedOutput()
 	if err != nil {
 		t.Fatal(err)
diff --git a/src/cmd/vet/whitelist/whitelist.go b/src/cmd/vet/whitelist/whitelist.go
deleted file mode 100644
index bf4b4bf..0000000
--- a/src/cmd/vet/whitelist/whitelist.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2013 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 whitelist defines exceptions for the vet tool.
-package whitelist // import "cmd/vet/whitelist"
-
-// UnkeyedLiteral are types that are actually slices, but
-// syntactically, we cannot tell whether the Typ in pkg.Typ{1, 2, 3}
-// is a slice or a struct, so we whitelist all the standard package
-// library's exported slice types.
-var UnkeyedLiteral = map[string]bool{
-	/*
-		find $GOROOT/src -type f | grep -v _test.go | xargs grep '^type.*\[\]' | \
-			grep -v ' map\[' | sed 's,/[^/]*go.type,,' | sed 's,.*src/,,' | \
-			sed 's, ,.,' |  sed 's, .*,,' | grep -v '\.[a-z]' | \
-			sort | awk '{ print "\"" $0 "\": true," }'
-	*/
-	"crypto/x509/pkix.RDNSequence":                  true,
-	"crypto/x509/pkix.RelativeDistinguishedNameSET": true,
-	"database/sql.RawBytes":                         true,
-	"debug/macho.LoadBytes":                         true,
-	"encoding/asn1.ObjectIdentifier":                true,
-	"encoding/asn1.RawContent":                      true,
-	"encoding/json.RawMessage":                      true,
-	"encoding/xml.CharData":                         true,
-	"encoding/xml.Comment":                          true,
-	"encoding/xml.Directive":                        true,
-	"go/scanner.ErrorList":                          true,
-	"image/color.Palette":                           true,
-	"net.HardwareAddr":                              true,
-	"net.IP":                                        true,
-	"net.IPMask":                                    true,
-	"sort.Float64Slice":                             true,
-	"sort.IntSlice":                                 true,
-	"sort.StringSlice":                              true,
-	"unicode.SpecialCase":                           true,
-
-	// These image and image/color struct types are frozen. We will never add fields to them.
-	"image/color.Alpha16": true,
-	"image/color.Alpha":   true,
-	"image/color.CMYK":    true,
-	"image/color.Gray16":  true,
-	"image/color.Gray":    true,
-	"image/color.NRGBA64": true,
-	"image/color.NRGBA":   true,
-	"image/color.RGBA64":  true,
-	"image/color.RGBA":    true,
-	"image/color.YCbCr":   true,
-	"image.Point":         true,
-	"image.Rectangle":     true,
-	"image.Uniform":       true,
-}
diff --git a/src/cmd/yacc/yacc.go b/src/cmd/yacc/yacc.go
index 4f83f50..4f9d13c 100644
--- a/src/cmd/yacc/yacc.go
+++ b/src/cmd/yacc/yacc.go
@@ -172,7 +172,7 @@ func init() {
 	flag.BoolVar(&lflag, "l", false, "disable line directives")
 }
 
-var stacksize = 200
+var initialstacksize = 16
 
 // communication variables between various I/O routines
 var infile string  // input file name
@@ -384,7 +384,7 @@ func setup() {
 	if flag.NArg() != 1 {
 		usage()
 	}
-	if stacksize < 1 {
+	if initialstacksize < 1 {
 		// never set so cannot happen
 		fmt.Fprintf(stderr, "yacc: stack size too small\n")
 		usage()
@@ -719,7 +719,7 @@ outer:
 	ftable.WriteRune('\n')
 	fmt.Fprintf(ftable, "const %sEofCode = 1\n", prefix)
 	fmt.Fprintf(ftable, "const %sErrCode = 2\n", prefix)
-	fmt.Fprintf(ftable, "const %sMaxDepth = %v\n", prefix, stacksize)
+	fmt.Fprintf(ftable, "const %sInitialStackSize = %v\n", prefix, initialstacksize)
 
 	//
 	// copy any postfix code
@@ -1284,8 +1284,9 @@ func dumpprod(curprod []int, max int) {
 func cpyact(curprod []int, max int) {
 
 	if !lflag {
-		fmt.Fprintf(fcode, "\n\t\t//line %v:%v\n\t\t", infile, lineno)
+		fmt.Fprintf(fcode, "\n\t\t//line %v:%v", infile, lineno)
 	}
+	fmt.Fprint(fcode, "\n\t\t")
 
 	lno := lineno
 	brac := 0
@@ -3331,18 +3332,17 @@ type $$Parser interface {
 }
 
 type $$ParserImpl struct {
-	lookahead func() int
+	lval  $$SymType
+	stack [$$InitialStackSize]$$SymType
+	char  int
 }
 
 func (p *$$ParserImpl) Lookahead() int {
-	return p.lookahead()
+	return p.char
 }
 
 func $$NewParser() $$Parser {
-	p := &$$ParserImpl{
-		lookahead: func() int { return -1 },
-	}
-	return p
+	return &$$ParserImpl{}
 }
 
 const $$Flag = -1000
@@ -3470,22 +3470,20 @@ func $$Parse($$lex $$Lexer) int {
 
 func ($$rcvr *$$ParserImpl) Parse($$lex $$Lexer) int {
 	var $$n int
-	var $$lval $$SymType
 	var $$VAL $$SymType
 	var $$Dollar []$$SymType
 	_ = $$Dollar // silence set and not used
-	$$S := make([]$$SymType, $$MaxDepth)
+	$$S := $$rcvr.stack[:]
 
 	Nerrs := 0   /* number of errors */
 	Errflag := 0 /* error recovery flag */
 	$$state := 0
-	$$char := -1
-	$$token := -1 // $$char translated into internal numbering
-	$$rcvr.lookahead = func() int { return $$char }
+	$$rcvr.char = -1
+	$$token := -1 // $$rcvr.char translated into internal numbering
 	defer func() {
 		// Make sure we report no lookahead when not parsing.
 		$$state = -1
-		$$char = -1
+		$$rcvr.char = -1
 		$$token = -1
 	}()
 	$$p := -1
@@ -3517,8 +3515,8 @@ $$newstate:
 	if $$n <= $$Flag {
 		goto $$default /* simple state */
 	}
-	if $$char < 0 {
-		$$char, $$token = $$lex1($$lex, &$$lval)
+	if $$rcvr.char < 0 {
+		$$rcvr.char, $$token = $$lex1($$lex, &$$rcvr.lval)
 	}
 	$$n += $$token
 	if $$n < 0 || $$n >= $$Last {
@@ -3526,9 +3524,9 @@ $$newstate:
 	}
 	$$n = $$Act[$$n]
 	if $$Chk[$$n] == $$token { /* valid shift */
-		$$char = -1
+		$$rcvr.char = -1
 		$$token = -1
-		$$VAL = $$lval
+		$$VAL = $$rcvr.lval
 		$$state = $$n
 		if Errflag > 0 {
 			Errflag--
@@ -3540,8 +3538,8 @@ $$default:
 	/* default state action */
 	$$n = $$Def[$$state]
 	if $$n == -2 {
-		if $$char < 0 {
-			$$char, $$token = $$lex1($$lex, &$$lval)
+		if $$rcvr.char < 0 {
+			$$rcvr.char, $$token = $$lex1($$lex, &$$rcvr.lval)
 		}
 
 		/* look through exception table */
@@ -3604,7 +3602,7 @@ $$default:
 			if $$token == $$EofCode {
 				goto ret1
 			}
-			$$char = -1
+			$$rcvr.char = -1
 			$$token = -1
 			goto $$newstate /* try again in the same state */
 		}
diff --git a/src/compress/bzip2/bit_reader.go b/src/compress/bzip2/bit_reader.go
index 32d1036..ab1d606 100644
--- a/src/compress/bzip2/bit_reader.go
+++ b/src/compress/bzip2/bit_reader.go
@@ -77,14 +77,6 @@ func (br *bitReader) ReadBit() bool {
 	return n != 0
 }
 
-func (br *bitReader) TryReadBit() (bit byte, ok bool) {
-	if br.bits > 0 {
-		br.bits--
-		return byte(br.n>>br.bits) & 1, true
-	}
-	return 0, false
-}
-
 func (br *bitReader) Err() error {
 	return br.err
 }
diff --git a/src/compress/bzip2/bzip2_test.go b/src/compress/bzip2/bzip2_test.go
index 77c50df..7293d4e 100644
--- a/src/compress/bzip2/bzip2_test.go
+++ b/src/compress/bzip2/bzip2_test.go
@@ -173,6 +173,7 @@ const rand3Hex = "1744b384d68c042371244e13500d4bfb98c6244e3d71a5b700224420b59c59
 const (
 	digits = iota
 	twain
+	random
 )
 
 var testfiles = []string{
@@ -180,8 +181,10 @@ var testfiles = []string{
 	// does not repeat, but there are only 10 possible digits, so it should be
 	// reasonably compressible.
 	digits: "testdata/e.txt.bz2",
-	// Twain is Project Gutenberg's edition of Mark Twain's classic English novel.
+	// Twain is Mark Twain's classic English novel.
 	twain: "testdata/Mark.Twain-Tom.Sawyer.txt.bz2",
+	// 16KB of random data from /dev/urandom
+	random: "testdata/random.data.bz2",
 }
 
 func benchmarkDecode(b *testing.B, testfile int) {
@@ -198,6 +201,7 @@ func benchmarkDecode(b *testing.B, testfile int) {
 
 func BenchmarkDecodeDigits(b *testing.B) { benchmarkDecode(b, digits) }
 func BenchmarkDecodeTwain(b *testing.B)  { benchmarkDecode(b, twain) }
+func BenchmarkDecodeRand(b *testing.B)   { benchmarkDecode(b, random) }
 
 func TestBufferOverrun(t *testing.T) {
 	// Tests https://golang.org/issue/5747.
diff --git a/src/compress/bzip2/huffman.go b/src/compress/bzip2/huffman.go
index 75a6223..9d574b9 100644
--- a/src/compress/bzip2/huffman.go
+++ b/src/compress/bzip2/huffman.go
@@ -38,23 +38,35 @@ func (t *huffmanTree) Decode(br *bitReader) (v uint16) {
 
 	for {
 		node := &t.nodes[nodeIndex]
-		bit, ok := br.TryReadBit()
-		if !ok && br.ReadBit() {
-			bit = 1
-		}
-		// bzip2 encodes left as a true bit.
-		if bit != 0 {
-			// left
-			if node.left == invalidNodeValue {
-				return node.leftValue
-			}
-			nodeIndex = node.left
+
+		var bit uint16
+		if br.bits > 0 {
+			// Get next bit - fast path.
+			br.bits--
+			bit = 0 - (uint16(br.n>>br.bits) & 1)
 		} else {
-			// right
-			if node.right == invalidNodeValue {
-				return node.rightValue
-			}
-			nodeIndex = node.right
+			// Get next bit - slow path.
+			// Use ReadBits to retrieve a single bit
+			// from the underling io.ByteReader.
+			bit = 0 - uint16(br.ReadBits(1))
+		}
+		// now
+		// bit = 0xffff if the next bit was 1
+		// bit = 0x0000 if the next bit was 0
+
+		// 1 means left, 0 means right.
+		//
+		// if bit == 0xffff {
+		//     nodeIndex = node.left
+		// } else {
+		//     nodeIndex = node.right
+		// }
+		nodeIndex = (bit & node.left) | (^bit & node.right)
+
+		if nodeIndex == invalidNodeValue {
+			// We found a leaf. Use the value of bit to decide
+			// whether is a left or a right value.
+			return (bit & node.leftValue) | (^bit & node.rightValue)
 		}
 	}
 }
diff --git a/src/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2 b/src/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2
index 0bd61a6..eac2b05 100644
Binary files a/src/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2 and b/src/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2 differ
diff --git a/src/compress/bzip2/testdata/random.data.bz2 b/src/compress/bzip2/testdata/random.data.bz2
new file mode 100644
index 0000000..1ef2300
Binary files /dev/null and b/src/compress/bzip2/testdata/random.data.bz2 differ
diff --git a/src/compress/flate/deflate_test.go b/src/compress/flate/deflate_test.go
index d5d6e73..72bc665 100644
--- a/src/compress/flate/deflate_test.go
+++ b/src/compress/flate/deflate_test.go
@@ -7,6 +7,7 @@ package flate
 import (
 	"bytes"
 	"fmt"
+	"internal/testenv"
 	"io"
 	"io/ioutil"
 	"reflect"
@@ -343,6 +344,9 @@ var deflateInflateStringTests = []deflateInflateStringTest{
 }
 
 func TestDeflateInflateString(t *testing.T) {
+	if testing.Short() && testenv.Builder() == "" {
+		t.Skip("skipping in short mode")
+	}
 	for _, test := range deflateInflateStringTests {
 		gold, err := ioutil.ReadFile(test.filename)
 		if err != nil {
@@ -436,7 +440,11 @@ func TestWriterReset(t *testing.T) {
 			t.Fatalf("NewWriter: %v", err)
 		}
 		buf := []byte("hello world")
-		for i := 0; i < 1024; i++ {
+		n := 1024
+		if testing.Short() {
+			n = 10
+		}
+		for i := 0; i < n; i++ {
 			w.Write(buf)
 		}
 		w.Reset(ioutil.Discard)
diff --git a/src/compress/flate/fixedhuff.go b/src/compress/flate/fixedhuff.go
deleted file mode 100644
index 7df8b9a..0000000
--- a/src/compress/flate/fixedhuff.go
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2013 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 flate
-
-// autogenerated by go run gen.go -output fixedhuff.go, DO NOT EDIT
-
-var fixedHuffmanDecoder = huffmanDecoder{
-	7,
-	[huffmanNumChunks]uint32{
-		0x1007, 0x0508, 0x0108, 0x1188, 0x1107, 0x0708, 0x0308, 0x0c09,
-		0x1087, 0x0608, 0x0208, 0x0a09, 0x0008, 0x0808, 0x0408, 0x0e09,
-		0x1047, 0x0588, 0x0188, 0x0909, 0x1147, 0x0788, 0x0388, 0x0d09,
-		0x10c7, 0x0688, 0x0288, 0x0b09, 0x0088, 0x0888, 0x0488, 0x0f09,
-		0x1027, 0x0548, 0x0148, 0x11c8, 0x1127, 0x0748, 0x0348, 0x0c89,
-		0x10a7, 0x0648, 0x0248, 0x0a89, 0x0048, 0x0848, 0x0448, 0x0e89,
-		0x1067, 0x05c8, 0x01c8, 0x0989, 0x1167, 0x07c8, 0x03c8, 0x0d89,
-		0x10e7, 0x06c8, 0x02c8, 0x0b89, 0x00c8, 0x08c8, 0x04c8, 0x0f89,
-		0x1017, 0x0528, 0x0128, 0x11a8, 0x1117, 0x0728, 0x0328, 0x0c49,
-		0x1097, 0x0628, 0x0228, 0x0a49, 0x0028, 0x0828, 0x0428, 0x0e49,
-		0x1057, 0x05a8, 0x01a8, 0x0949, 0x1157, 0x07a8, 0x03a8, 0x0d49,
-		0x10d7, 0x06a8, 0x02a8, 0x0b49, 0x00a8, 0x08a8, 0x04a8, 0x0f49,
-		0x1037, 0x0568, 0x0168, 0x11e8, 0x1137, 0x0768, 0x0368, 0x0cc9,
-		0x10b7, 0x0668, 0x0268, 0x0ac9, 0x0068, 0x0868, 0x0468, 0x0ec9,
-		0x1077, 0x05e8, 0x01e8, 0x09c9, 0x1177, 0x07e8, 0x03e8, 0x0dc9,
-		0x10f7, 0x06e8, 0x02e8, 0x0bc9, 0x00e8, 0x08e8, 0x04e8, 0x0fc9,
-		0x1007, 0x0518, 0x0118, 0x1198, 0x1107, 0x0718, 0x0318, 0x0c29,
-		0x1087, 0x0618, 0x0218, 0x0a29, 0x0018, 0x0818, 0x0418, 0x0e29,
-		0x1047, 0x0598, 0x0198, 0x0929, 0x1147, 0x0798, 0x0398, 0x0d29,
-		0x10c7, 0x0698, 0x0298, 0x0b29, 0x0098, 0x0898, 0x0498, 0x0f29,
-		0x1027, 0x0558, 0x0158, 0x11d8, 0x1127, 0x0758, 0x0358, 0x0ca9,
-		0x10a7, 0x0658, 0x0258, 0x0aa9, 0x0058, 0x0858, 0x0458, 0x0ea9,
-		0x1067, 0x05d8, 0x01d8, 0x09a9, 0x1167, 0x07d8, 0x03d8, 0x0da9,
-		0x10e7, 0x06d8, 0x02d8, 0x0ba9, 0x00d8, 0x08d8, 0x04d8, 0x0fa9,
-		0x1017, 0x0538, 0x0138, 0x11b8, 0x1117, 0x0738, 0x0338, 0x0c69,
-		0x1097, 0x0638, 0x0238, 0x0a69, 0x0038, 0x0838, 0x0438, 0x0e69,
-		0x1057, 0x05b8, 0x01b8, 0x0969, 0x1157, 0x07b8, 0x03b8, 0x0d69,
-		0x10d7, 0x06b8, 0x02b8, 0x0b69, 0x00b8, 0x08b8, 0x04b8, 0x0f69,
-		0x1037, 0x0578, 0x0178, 0x11f8, 0x1137, 0x0778, 0x0378, 0x0ce9,
-		0x10b7, 0x0678, 0x0278, 0x0ae9, 0x0078, 0x0878, 0x0478, 0x0ee9,
-		0x1077, 0x05f8, 0x01f8, 0x09e9, 0x1177, 0x07f8, 0x03f8, 0x0de9,
-		0x10f7, 0x06f8, 0x02f8, 0x0be9, 0x00f8, 0x08f8, 0x04f8, 0x0fe9,
-		0x1007, 0x0508, 0x0108, 0x1188, 0x1107, 0x0708, 0x0308, 0x0c19,
-		0x1087, 0x0608, 0x0208, 0x0a19, 0x0008, 0x0808, 0x0408, 0x0e19,
-		0x1047, 0x0588, 0x0188, 0x0919, 0x1147, 0x0788, 0x0388, 0x0d19,
-		0x10c7, 0x0688, 0x0288, 0x0b19, 0x0088, 0x0888, 0x0488, 0x0f19,
-		0x1027, 0x0548, 0x0148, 0x11c8, 0x1127, 0x0748, 0x0348, 0x0c99,
-		0x10a7, 0x0648, 0x0248, 0x0a99, 0x0048, 0x0848, 0x0448, 0x0e99,
-		0x1067, 0x05c8, 0x01c8, 0x0999, 0x1167, 0x07c8, 0x03c8, 0x0d99,
-		0x10e7, 0x06c8, 0x02c8, 0x0b99, 0x00c8, 0x08c8, 0x04c8, 0x0f99,
-		0x1017, 0x0528, 0x0128, 0x11a8, 0x1117, 0x0728, 0x0328, 0x0c59,
-		0x1097, 0x0628, 0x0228, 0x0a59, 0x0028, 0x0828, 0x0428, 0x0e59,
-		0x1057, 0x05a8, 0x01a8, 0x0959, 0x1157, 0x07a8, 0x03a8, 0x0d59,
-		0x10d7, 0x06a8, 0x02a8, 0x0b59, 0x00a8, 0x08a8, 0x04a8, 0x0f59,
-		0x1037, 0x0568, 0x0168, 0x11e8, 0x1137, 0x0768, 0x0368, 0x0cd9,
-		0x10b7, 0x0668, 0x0268, 0x0ad9, 0x0068, 0x0868, 0x0468, 0x0ed9,
-		0x1077, 0x05e8, 0x01e8, 0x09d9, 0x1177, 0x07e8, 0x03e8, 0x0dd9,
-		0x10f7, 0x06e8, 0x02e8, 0x0bd9, 0x00e8, 0x08e8, 0x04e8, 0x0fd9,
-		0x1007, 0x0518, 0x0118, 0x1198, 0x1107, 0x0718, 0x0318, 0x0c39,
-		0x1087, 0x0618, 0x0218, 0x0a39, 0x0018, 0x0818, 0x0418, 0x0e39,
-		0x1047, 0x0598, 0x0198, 0x0939, 0x1147, 0x0798, 0x0398, 0x0d39,
-		0x10c7, 0x0698, 0x0298, 0x0b39, 0x0098, 0x0898, 0x0498, 0x0f39,
-		0x1027, 0x0558, 0x0158, 0x11d8, 0x1127, 0x0758, 0x0358, 0x0cb9,
-		0x10a7, 0x0658, 0x0258, 0x0ab9, 0x0058, 0x0858, 0x0458, 0x0eb9,
-		0x1067, 0x05d8, 0x01d8, 0x09b9, 0x1167, 0x07d8, 0x03d8, 0x0db9,
-		0x10e7, 0x06d8, 0x02d8, 0x0bb9, 0x00d8, 0x08d8, 0x04d8, 0x0fb9,
-		0x1017, 0x0538, 0x0138, 0x11b8, 0x1117, 0x0738, 0x0338, 0x0c79,
-		0x1097, 0x0638, 0x0238, 0x0a79, 0x0038, 0x0838, 0x0438, 0x0e79,
-		0x1057, 0x05b8, 0x01b8, 0x0979, 0x1157, 0x07b8, 0x03b8, 0x0d79,
-		0x10d7, 0x06b8, 0x02b8, 0x0b79, 0x00b8, 0x08b8, 0x04b8, 0x0f79,
-		0x1037, 0x0578, 0x0178, 0x11f8, 0x1137, 0x0778, 0x0378, 0x0cf9,
-		0x10b7, 0x0678, 0x0278, 0x0af9, 0x0078, 0x0878, 0x0478, 0x0ef9,
-		0x1077, 0x05f8, 0x01f8, 0x09f9, 0x1177, 0x07f8, 0x03f8, 0x0df9,
-		0x10f7, 0x06f8, 0x02f8, 0x0bf9, 0x00f8, 0x08f8, 0x04f8, 0x0ff9,
-	},
-	nil, 0,
-}
diff --git a/src/compress/flate/flate_test.go b/src/compress/flate/flate_test.go
index 3f67025..341d807 100644
--- a/src/compress/flate/flate_test.go
+++ b/src/compress/flate/flate_test.go
@@ -11,7 +11,9 @@ package flate
 import (
 	"bytes"
 	"encoding/hex"
+	"io"
 	"io/ioutil"
+	"strings"
 	"testing"
 )
 
@@ -258,3 +260,15 @@ func TestStreams(t *testing.T) {
 		}
 	}
 }
+
+func TestTruncatedStreams(t *testing.T) {
+	const data = "\x00\f\x00\xf3\xffhello, world\x01\x00\x00\xff\xff"
+
+	for i := 0; i < len(data)-1; i++ {
+		r := NewReader(strings.NewReader(data[:i]))
+		_, err := io.Copy(ioutil.Discard, r)
+		if err != io.ErrUnexpectedEOF {
+			t.Errorf("io.Copy(%d) on truncated stream: got %v, want %v", i, err, io.ErrUnexpectedEOF)
+		}
+	}
+}
diff --git a/src/compress/flate/gen.go b/src/compress/flate/gen.go
deleted file mode 100644
index 154c89a..0000000
--- a/src/compress/flate/gen.go
+++ /dev/null
@@ -1,265 +0,0 @@
-// Copyright 2012 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.
-
-// +build ignore
-
-// This program generates fixedhuff.go
-// Invoke as
-//
-//	go run gen.go -output fixedhuff.go
-
-package main
-
-import (
-	"bytes"
-	"flag"
-	"fmt"
-	"go/format"
-	"io/ioutil"
-	"log"
-)
-
-var filename = flag.String("output", "fixedhuff.go", "output file name")
-
-const maxCodeLen = 16
-
-// Note: the definition of the huffmanDecoder struct is copied from
-// inflate.go, as it is private to the implementation.
-
-// chunk & 15 is number of bits
-// chunk >> 4 is value, including table link
-
-const (
-	huffmanChunkBits  = 9
-	huffmanNumChunks  = 1 << huffmanChunkBits
-	huffmanCountMask  = 15
-	huffmanValueShift = 4
-)
-
-type huffmanDecoder struct {
-	min      int                      // the minimum code length
-	chunks   [huffmanNumChunks]uint32 // chunks as described above
-	links    [][]uint32               // overflow links
-	linkMask uint32                   // mask the width of the link table
-}
-
-// Initialize Huffman decoding tables from array of code lengths.
-// Following this function, h is guaranteed to be initialized into a complete
-// tree (i.e., neither over-subscribed nor under-subscribed). The exception is a
-// degenerate case where the tree has only a single symbol with length 1. Empty
-// trees are permitted.
-func (h *huffmanDecoder) init(bits []int) bool {
-	// Sanity enables additional runtime tests during Huffman
-	// table construction.  It's intended to be used during
-	// development to supplement the currently ad-hoc unit tests.
-	const sanity = false
-
-	if h.min != 0 {
-		*h = huffmanDecoder{}
-	}
-
-	// Count number of codes of each length,
-	// compute min and max length.
-	var count [maxCodeLen]int
-	var min, max int
-	for _, n := range bits {
-		if n == 0 {
-			continue
-		}
-		if min == 0 || n < min {
-			min = n
-		}
-		if n > max {
-			max = n
-		}
-		count[n]++
-	}
-
-	// Empty tree. The decompressor.huffSym function will fail later if the tree
-	// is used. Technically, an empty tree is only valid for the HDIST tree and
-	// not the HCLEN and HLIT tree. However, a stream with an empty HCLEN tree
-	// is guaranteed to fail since it will attempt to use the tree to decode the
-	// codes for the HLIT and HDIST trees. Similarly, an empty HLIT tree is
-	// guaranteed to fail later since the compressed data section must be
-	// composed of at least one symbol (the end-of-block marker).
-	if max == 0 {
-		return true
-	}
-
-	code := 0
-	var nextcode [maxCodeLen]int
-	for i := min; i <= max; i++ {
-		code <<= 1
-		nextcode[i] = code
-		code += count[i]
-	}
-
-	// Check that the coding is complete (i.e., that we've
-	// assigned all 2-to-the-max possible bit sequences).
-	// Exception: To be compatible with zlib, we also need to
-	// accept degenerate single-code codings.  See also
-	// TestDegenerateHuffmanCoding.
-	if code != 1<<uint(max) && !(code == 1 && max == 1) {
-		return false
-	}
-
-	h.min = min
-	if max > huffmanChunkBits {
-		numLinks := 1 << (uint(max) - huffmanChunkBits)
-		h.linkMask = uint32(numLinks - 1)
-
-		// create link tables
-		link := nextcode[huffmanChunkBits+1] >> 1
-		h.links = make([][]uint32, huffmanNumChunks-link)
-		for j := uint(link); j < huffmanNumChunks; j++ {
-			reverse := int(reverseByte[j>>8]) | int(reverseByte[j&0xff])<<8
-			reverse >>= uint(16 - huffmanChunkBits)
-			off := j - uint(link)
-			if sanity && h.chunks[reverse] != 0 {
-				panic("impossible: overwriting existing chunk")
-			}
-			h.chunks[reverse] = uint32(off<<huffmanValueShift | (huffmanChunkBits + 1))
-			h.links[off] = make([]uint32, numLinks)
-		}
-	}
-
-	for i, n := range bits {
-		if n == 0 {
-			continue
-		}
-		code := nextcode[n]
-		nextcode[n]++
-		chunk := uint32(i<<huffmanValueShift | n)
-		reverse := int(reverseByte[code>>8]) | int(reverseByte[code&0xff])<<8
-		reverse >>= uint(16 - n)
-		if n <= huffmanChunkBits {
-			for off := reverse; off < len(h.chunks); off += 1 << uint(n) {
-				// We should never need to overwrite
-				// an existing chunk.  Also, 0 is
-				// never a valid chunk, because the
-				// lower 4 "count" bits should be
-				// between 1 and 15.
-				if sanity && h.chunks[off] != 0 {
-					panic("impossible: overwriting existing chunk")
-				}
-				h.chunks[off] = chunk
-			}
-		} else {
-			j := reverse & (huffmanNumChunks - 1)
-			if sanity && h.chunks[j]&huffmanCountMask != huffmanChunkBits+1 {
-				// Longer codes should have been
-				// associated with a link table above.
-				panic("impossible: not an indirect chunk")
-			}
-			value := h.chunks[j] >> huffmanValueShift
-			linktab := h.links[value]
-			reverse >>= huffmanChunkBits
-			for off := reverse; off < len(linktab); off += 1 << uint(n-huffmanChunkBits) {
-				if sanity && linktab[off] != 0 {
-					panic("impossible: overwriting existing chunk")
-				}
-				linktab[off] = chunk
-			}
-		}
-	}
-
-	if sanity {
-		// Above we've sanity checked that we never overwrote
-		// an existing entry.  Here we additionally check that
-		// we filled the tables completely.
-		for i, chunk := range h.chunks {
-			if chunk == 0 {
-				// As an exception, in the degenerate
-				// single-code case, we allow odd
-				// chunks to be missing.
-				if code == 1 && i%2 == 1 {
-					continue
-				}
-				panic("impossible: missing chunk")
-			}
-		}
-		for _, linktab := range h.links {
-			for _, chunk := range linktab {
-				if chunk == 0 {
-					panic("impossible: missing chunk")
-				}
-			}
-		}
-	}
-
-	return true
-}
-
-func main() {
-	flag.Parse()
-
-	var h huffmanDecoder
-	var bits [288]int
-	initReverseByte()
-	for i := 0; i < 144; i++ {
-		bits[i] = 8
-	}
-	for i := 144; i < 256; i++ {
-		bits[i] = 9
-	}
-	for i := 256; i < 280; i++ {
-		bits[i] = 7
-	}
-	for i := 280; i < 288; i++ {
-		bits[i] = 8
-	}
-	h.init(bits[:])
-	if h.links != nil {
-		log.Fatal("Unexpected links table in fixed Huffman decoder")
-	}
-
-	var buf bytes.Buffer
-
-	fmt.Fprintf(&buf, `// Copyright 2013 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.`+"\n\n")
-
-	fmt.Fprintln(&buf, "package flate")
-	fmt.Fprintln(&buf)
-	fmt.Fprintln(&buf, "// autogenerated by go run gen.go -output fixedhuff.go, DO NOT EDIT")
-	fmt.Fprintln(&buf)
-	fmt.Fprintln(&buf, "var fixedHuffmanDecoder = huffmanDecoder{")
-	fmt.Fprintf(&buf, "\t%d,\n", h.min)
-	fmt.Fprintln(&buf, "\t[huffmanNumChunks]uint32{")
-	for i := 0; i < huffmanNumChunks; i++ {
-		if i&7 == 0 {
-			fmt.Fprintf(&buf, "\t\t")
-		} else {
-			fmt.Fprintf(&buf, " ")
-		}
-		fmt.Fprintf(&buf, "0x%04x,", h.chunks[i])
-		if i&7 == 7 {
-			fmt.Fprintln(&buf)
-		}
-	}
-	fmt.Fprintln(&buf, "\t},")
-	fmt.Fprintln(&buf, "\tnil, 0,")
-	fmt.Fprintln(&buf, "}")
-
-	data, err := format.Source(buf.Bytes())
-	if err != nil {
-		log.Fatal(err)
-	}
-	err = ioutil.WriteFile(*filename, data, 0644)
-	if err != nil {
-		log.Fatal(err)
-	}
-}
-
-var reverseByte [256]byte
-
-func initReverseByte() {
-	for x := 0; x < 256; x++ {
-		var result byte
-		for i := uint(0); i < 8; i++ {
-			result |= byte(((x >> i) & 1) << (7 - i))
-		}
-		reverseByte[x] = result
-	}
-}
diff --git a/src/compress/flate/inflate.go b/src/compress/flate/inflate.go
index 04372de..42261e9 100644
--- a/src/compress/flate/inflate.go
+++ b/src/compress/flate/inflate.go
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:generate go run gen.go -output fixedhuff.go
-
 // Package flate implements the DEFLATE compressed data format, described in
 // RFC 1951.  The gzip and zlib packages implement access to DEFLATE-based file
 // formats.
@@ -13,6 +11,7 @@ import (
 	"bufio"
 	"io"
 	"strconv"
+	"sync"
 )
 
 const (
@@ -26,6 +25,10 @@ const (
 	numCodes   = 19 // number of codes in Huffman meta-code
 )
 
+// Initialize the fixedHuffmanDecoder only once upon first use.
+var fixedOnce sync.Once
+var fixedHuffmanDecoder huffmanDecoder
+
 // A CorruptInputError reports the presence of corrupt input at a given offset.
 type CorruptInputError int64
 
@@ -39,6 +42,8 @@ type InternalError string
 func (e InternalError) Error() string { return "flate: internal error: " + string(e) }
 
 // A ReadError reports an error encountered while reading input.
+//
+// Deprecated: No longer returned.
 type ReadError struct {
 	Offset int64 // byte offset where error occurred
 	Err    error // error returned by underlying Read
@@ -49,6 +54,8 @@ func (e *ReadError) Error() string {
 }
 
 // A WriteError reports an error encountered while writing output.
+//
+// Deprecated: No longer returned.
 type WriteError struct {
 	Offset int64 // byte offset where error occurred
 	Err    error // error returned by underlying Write
@@ -67,10 +74,6 @@ type Resetter interface {
 	Reset(r io.Reader, dict []byte) error
 }
 
-// Note that much of the implementation of huffmanDecoder is also copied
-// into gen.go (in package main) for the purpose of precomputing the
-// fixed huffman tables so they can be included statically.
-
 // The data structure for decoding Huffman tables is based on that of
 // zlib. There is a lookup table of a fixed bit width (huffmanChunkBits),
 // For codes smaller than the table width, there are multiple entries
@@ -78,12 +81,15 @@ type Resetter interface {
 // larger than the table width, the table contains a link to an overflow
 // table. The width of each entry in the link table is the maximum code
 // size minus the chunk width.
-
+//
 // Note that you can do a lookup in the table even without all bits
 // filled. Since the extra bits are zero, and the DEFLATE Huffman codes
 // have the property that shorter codes come before longer ones, the
 // bit length estimate in the result is a lower bound on the actual
 // number of bits.
+//
+// See the following:
+//	http://www.gzip.org/algorithm.txt
 
 // chunk & 15 is number of bits
 // chunk >> 4 is value, including table link
@@ -459,6 +465,14 @@ func (f *decompressor) readHuffman() error {
 		return CorruptInputError(f.roffset)
 	}
 
+	// As an optimization, we can initialize the min bits to read at a time
+	// for the HLIT tree to the length of the EOB marker since we know that
+	// every block must terminate with one. This preserves the property that
+	// we never read any extra bytes after the end of the DEFLATE stream.
+	if f.h1.min < f.bits[endBlockMarker] {
+		f.h1.min = f.bits[endBlockMarker]
+	}
+
 	return nil
 }
 
@@ -635,7 +649,10 @@ func (f *decompressor) dataBlock() {
 	nr, err := io.ReadFull(f.r, f.buf[0:4])
 	f.roffset += int64(nr)
 	if err != nil {
-		f.err = &ReadError{f.roffset, err}
+		if err == io.EOF {
+			err = io.ErrUnexpectedEOF
+		}
+		f.err = err
 		return
 	}
 	n := int(f.buf[0]) | int(f.buf[1])<<8
@@ -667,7 +684,10 @@ func (f *decompressor) copyData() {
 		m, err := io.ReadFull(f.r, f.hist[f.hp:f.hp+m])
 		f.roffset += int64(m)
 		if err != nil {
-			f.err = &ReadError{f.roffset, err}
+			if err == io.EOF {
+				err = io.ErrUnexpectedEOF
+			}
+			f.err = err
 			return
 		}
 		n -= m
@@ -760,6 +780,26 @@ func makeReader(r io.Reader) Reader {
 	return bufio.NewReader(r)
 }
 
+func fixedHuffmanDecoderInit() {
+	fixedOnce.Do(func() {
+		// These come from the RFC section 3.2.6.
+		var bits [288]int
+		for i := 0; i < 144; i++ {
+			bits[i] = 8
+		}
+		for i := 144; i < 256; i++ {
+			bits[i] = 9
+		}
+		for i := 256; i < 280; i++ {
+			bits[i] = 7
+		}
+		for i := 280; i < 288; i++ {
+			bits[i] = 8
+		}
+		fixedHuffmanDecoder.init(bits[:])
+	})
+}
+
 func (f *decompressor) Reset(r io.Reader, dict []byte) error {
 	*f = decompressor{
 		r:        makeReader(r),
@@ -783,11 +823,13 @@ func (f *decompressor) Reset(r io.Reader, dict []byte) error {
 //
 // The ReadCloser returned by NewReader also implements Resetter.
 func NewReader(r io.Reader) io.ReadCloser {
+	fixedHuffmanDecoderInit()
+
 	var f decompressor
-	f.bits = new([maxNumLit + maxNumDist]int)
-	f.codebits = new([numCodes]int)
 	f.r = makeReader(r)
 	f.hist = new([maxHist]byte)
+	f.bits = new([maxNumLit + maxNumDist]int)
+	f.codebits = new([numCodes]int)
 	f.step = (*decompressor).nextBlock
 	return &f
 }
@@ -800,6 +842,8 @@ func NewReader(r io.Reader) io.ReadCloser {
 //
 // The ReadCloser returned by NewReader also implements Resetter.
 func NewReaderDict(r io.Reader, dict []byte) io.ReadCloser {
+	fixedHuffmanDecoderInit()
+
 	var f decompressor
 	f.r = makeReader(r)
 	f.hist = new([maxHist]byte)
diff --git a/src/compress/flate/reader_test.go b/src/compress/flate/reader_test.go
index a62ef74..bd88732 100644
--- a/src/compress/flate/reader_test.go
+++ b/src/compress/flate/reader_test.go
@@ -32,7 +32,7 @@ var testfiles = []string{
 	// does not repeat, but there are only 10 possible digits, so it should be
 	// reasonably compressible.
 	digits: "../testdata/e.txt",
-	// Twain is Project Gutenberg's edition of Mark Twain's classic English novel.
+	// Twain is Mark Twain's classic English novel.
 	twain: "../testdata/Mark.Twain-Tom.Sawyer.txt",
 }
 
diff --git a/src/compress/flate/token.go b/src/compress/flate/token.go
index 4d49176..c485939 100644
--- a/src/compress/flate/token.go
+++ b/src/compress/flate/token.go
@@ -90,13 +90,11 @@ func lengthCode(len uint32) uint32 { return lengthCodes[len] }
 
 // Returns the offset code corresponding to a specific offset
 func offsetCode(off uint32) uint32 {
-	const n = uint32(len(offsetCodes))
-	switch {
-	case off < n:
+	if off < uint32(len(offsetCodes)) {
 		return offsetCodes[off]
-	case off>>7 < n:
+	}
+	if off>>7 < uint32(len(offsetCodes)) {
 		return offsetCodes[off>>7] + 14
-	default:
-		return offsetCodes[off>>14] + 28
 	}
+	return offsetCodes[off>>14] + 28
 }
diff --git a/src/compress/gzip/gunzip.go b/src/compress/gzip/gunzip.go
index 72ee55c..3d33145 100644
--- a/src/compress/gzip/gunzip.go
+++ b/src/compress/gzip/gunzip.go
@@ -43,6 +43,9 @@ var (
 
 // The gzip file stores a header giving metadata about the compressed file.
 // That header is exposed as the fields of the Writer and Reader structs.
+//
+// Strings must be UTF-8 encoded and may only contain Unicode code points
+// U+0001 through U+00FF, due to limitations of the GZIP file format.
 type Header struct {
 	Comment string    // comment
 	Extra   []byte    // "extra data"
@@ -66,7 +69,7 @@ type Header struct {
 // returned by Read as tentative until they receive the io.EOF
 // marking the end of the data.
 type Reader struct {
-	Header
+	Header       // valid after NewReader or Reader.Reset
 	r            flate.Reader
 	decompressor io.ReadCloser
 	digest       hash.Hash32
@@ -80,7 +83,10 @@ type Reader struct {
 // NewReader creates a new Reader reading the given reader.
 // If r does not also implement io.ByteReader,
 // the decompressor may read more data than necessary from r.
+//
 // It is the caller's responsibility to call Close on the Reader when done.
+//
+// The Reader.Header fields will be valid in the Reader returned.
 func NewReader(r io.Reader) (*Reader, error) {
 	z := new(Reader)
 	z.r = makeReader(r)
@@ -164,6 +170,9 @@ func (z *Reader) readString() (string, error) {
 func (z *Reader) read2() (uint32, error) {
 	_, err := io.ReadFull(z.r, z.buf[0:2])
 	if err != nil {
+		if err == io.EOF {
+			err = io.ErrUnexpectedEOF
+		}
 		return 0, err
 	}
 	return uint32(z.buf[0]) | uint32(z.buf[1])<<8, nil
@@ -172,6 +181,13 @@ func (z *Reader) read2() (uint32, error) {
 func (z *Reader) readHeader(save bool) error {
 	_, err := io.ReadFull(z.r, z.buf[0:10])
 	if err != nil {
+		// RFC1952 section 2.2 says the following:
+		//	A gzip file consists of a series of "members" (compressed data sets).
+		//
+		// Other than this, the specification does not clarify whether a
+		// "series" is defined as "one or more" or "zero or more". To err on the
+		// side of caution, Go interprets this to mean "zero or more".
+		// Thus, it is okay to return io.EOF here.
 		return err
 	}
 	if z.buf[0] != gzipID1 || z.buf[1] != gzipID2 || z.buf[2] != gzipDeflate {
@@ -193,6 +209,9 @@ func (z *Reader) readHeader(save bool) error {
 		}
 		data := make([]byte, n)
 		if _, err = io.ReadFull(z.r, data); err != nil {
+			if err == io.EOF {
+				err = io.ErrUnexpectedEOF
+			}
 			return err
 		}
 		if save {
@@ -257,6 +276,9 @@ func (z *Reader) Read(p []byte) (n int, err error) {
 
 	// Finished file; check checksum + size.
 	if _, err := io.ReadFull(z.r, z.buf[0:8]); err != nil {
+		if err == io.EOF {
+			err = io.ErrUnexpectedEOF
+		}
 		z.err = err
 		return 0, err
 	}
diff --git a/src/compress/gzip/gunzip_test.go b/src/compress/gzip/gunzip_test.go
index 0636dec..007d958 100644
--- a/src/compress/gzip/gunzip_test.go
+++ b/src/compress/gzip/gunzip_test.go
@@ -6,6 +6,7 @@ package gzip
 
 import (
 	"bytes"
+	"compress/flate"
 	"io"
 	"io/ioutil"
 	"os"
@@ -408,3 +409,34 @@ Found:
 		t.Fatalf("third reset: err=%v, want io.EOF", err)
 	}
 }
+
+func TestNilStream(t *testing.T) {
+	// Go liberally interprets RFC1952 section 2.2 to mean that a gzip file
+	// consist of zero or more members. Thus, we test that a nil stream is okay.
+	_, err := NewReader(bytes.NewReader(nil))
+	if err != io.EOF {
+		t.Fatalf("NewReader(nil) on empty stream: got %v, want io.EOF", err)
+	}
+}
+
+func TestTruncatedStreams(t *testing.T) {
+	const data = "\x1f\x8b\b\x04\x00\tn\x88\x00\xff\a\x00foo bar\xcbH\xcd\xc9\xc9\xd7Q(\xcf/\xcaI\x01\x04:r\xab\xff\f\x00\x00\x00"
+
+	// Intentionally iterate starting with at least one byte in the stream.
+	for i := 1; i < len(data)-1; i++ {
+		r, err := NewReader(strings.NewReader(data[:i]))
+		if err != nil {
+			if err != io.ErrUnexpectedEOF {
+				t.Errorf("NewReader(%d) on truncated stream: got %v, want %v", i, err, io.ErrUnexpectedEOF)
+			}
+			continue
+		}
+		_, err = io.Copy(ioutil.Discard, r)
+		if ferr, ok := err.(*flate.ReadError); ok {
+			err = ferr.Err
+		}
+		if err != io.ErrUnexpectedEOF {
+			t.Errorf("io.Copy(%d) on truncated stream: got %v, want %v", i, err, io.ErrUnexpectedEOF)
+		}
+	}
+}
diff --git a/src/compress/gzip/gzip.go b/src/compress/gzip/gzip.go
index 5131d12..4d945e4 100644
--- a/src/compress/gzip/gzip.go
+++ b/src/compress/gzip/gzip.go
@@ -25,7 +25,7 @@ const (
 // A Writer is an io.WriteCloser.
 // Writes to a Writer are compressed and written to w.
 type Writer struct {
-	Header
+	Header      // written at first call to Write, Flush, or Close
 	w           io.Writer
 	level       int
 	wroteHeader bool
@@ -44,10 +44,7 @@ type Writer struct {
 // Writes may be buffered and not flushed until Close.
 //
 // Callers that wish to set the fields in Writer.Header must do so before
-// the first call to Write or Close. The Comment and Name header fields are
-// UTF-8 strings in Go, but the underlying format requires NUL-terminated ISO
-// 8859-1 (Latin-1). NUL or non-Latin-1 runes in those strings will lead to an
-// error on Write.
+// the first call to Write, Flush, or Close.
 func NewWriter(w io.Writer) *Writer {
 	z, _ := NewWriterLevel(w, DefaultCompression)
 	return z
diff --git a/src/compress/lzw/reader.go b/src/compress/lzw/reader.go
index 1353831..9eef2b2 100644
--- a/src/compress/lzw/reader.go
+++ b/src/compress/lzw/reader.go
@@ -132,6 +132,7 @@ func (d *decoder) Read(b []byte) (int, error) {
 // litWidth is the width in bits of literal codes.
 func (d *decoder) decode() {
 	// Loop over the code stream, converting codes into decompressed bytes.
+loop:
 	for {
 		code, err := d.read(d)
 		if err != nil {
@@ -139,8 +140,7 @@ func (d *decoder) decode() {
 				err = io.ErrUnexpectedEOF
 			}
 			d.err = err
-			d.flush()
-			return
+			break
 		}
 		switch {
 		case code < d.clear:
@@ -159,9 +159,8 @@ func (d *decoder) decode() {
 			d.last = decoderInvalidCode
 			continue
 		case code == d.eof:
-			d.flush()
 			d.err = io.EOF
-			return
+			break loop
 		case code <= d.hi:
 			c, i := code, len(d.output)-1
 			if code == d.hi {
@@ -191,8 +190,7 @@ func (d *decoder) decode() {
 			}
 		default:
 			d.err = errors.New("lzw: invalid code")
-			d.flush()
-			return
+			break loop
 		}
 		d.last, d.hi = code, d.hi+1
 		if d.hi >= d.overflow {
@@ -204,13 +202,10 @@ func (d *decoder) decode() {
 			}
 		}
 		if d.o >= flushBuffer {
-			d.flush()
-			return
+			break
 		}
 	}
-}
-
-func (d *decoder) flush() {
+	// Flush pending output.
 	d.toRead = d.output[:d.o]
 	d.o = 0
 }
diff --git a/src/compress/lzw/writer_test.go b/src/compress/lzw/writer_test.go
index c20d058..66d7617 100644
--- a/src/compress/lzw/writer_test.go
+++ b/src/compress/lzw/writer_test.go
@@ -5,6 +5,7 @@
 package lzw
 
 import (
+	"internal/testenv"
 	"io"
 	"io/ioutil"
 	"os"
@@ -13,6 +14,7 @@ import (
 )
 
 var filenames = []string{
+	"../testdata/gettysburg.txt",
 	"../testdata/e.txt",
 	"../testdata/pi.txt",
 }
@@ -89,10 +91,16 @@ func TestWriter(t *testing.T) {
 	for _, filename := range filenames {
 		for _, order := range [...]Order{LSB, MSB} {
 			// The test data "2.71828 etcetera" is ASCII text requiring at least 6 bits.
-			for _, litWidth := range [...]int{6, 7, 8} {
+			for litWidth := 6; litWidth <= 8; litWidth++ {
+				if filename == "../testdata/gettysburg.txt" && litWidth == 6 {
+					continue
+				}
 				testFile(t, filename, order, litWidth)
 			}
 		}
+		if testing.Short() && testenv.Builder() == "" {
+			break
+		}
 	}
 }
 
diff --git a/src/compress/testdata/Mark.Twain-Tom.Sawyer.txt b/src/compress/testdata/Mark.Twain-Tom.Sawyer.txt
index c97da7e..c9106fd 100644
--- a/src/compress/testdata/Mark.Twain-Tom.Sawyer.txt
+++ b/src/compress/testdata/Mark.Twain-Tom.Sawyer.txt
@@ -1,27 +1,3 @@
-The Project Gutenberg EBook of The Adventures of Tom Sawyer, Complete
-by Mark Twain (Samuel Clemens)
-
-This eBook is for the use of anyone anywhere at no cost and with
-almost no restrictions whatsoever.  You may copy it, give it away or
-re-use it under the terms of the Project Gutenberg License included
-with this eBook or online at www.gutenberg.net
-
-
-Title: The Adventures of Tom Sawyer, Complete
-
-Author: Mark Twain (Samuel Clemens)
-
-Release Date: August 20, 2006 [EBook #74]
-[Last updated: May 3, 2011]
-
-Language: English
-
-
-*** START OF THIS PROJECT GUTENBERG EBOOK TOM SAWYER ***
-
-
-
-
 Produced by David Widger. The previous edition was updated by Jose
 Menendez.
 
@@ -8487,372 +8463,3 @@ prosperous and happy. Some day it may seem worth while to take up the
 story of the younger ones again and see what sort of men and women they
 turned out to be; therefore it will be wisest not to reveal any of that
 part of their lives at present.
-
-
-
-
-
-End of the Project Gutenberg EBook of The Adventures of Tom Sawyer, Complete
-by Mark Twain (Samuel Clemens)
-
-*** END OF THIS PROJECT GUTENBERG EBOOK TOM SAWYER ***
-
-***** This file should be named 74.txt or 74.zip *****
-This and all associated files of various formats will be found in:
-        http://www.gutenberg.net/7/74/
-
-Produced by David Widger. The previous edition was update by Jose
-Menendez.
-
-
-Updated editions will replace the previous one--the old editions
-will be renamed.
-
-Creating the works from public domain print editions means that no
-one owns a United States copyright in these works, so the Foundation
-(and you!) can copy and distribute it in the United States without
-permission and without paying copyright royalties.  Special rules,
-set forth in the General Terms of Use part of this license, apply to
-copying and distributing Project Gutenberg-tm electronic works to
-protect the PROJECT GUTENBERG-tm concept and trademark.  Project
-Gutenberg is a registered trademark, and may not be used if you
-charge for the eBooks, unless you receive specific permission.  If you
-do not charge anything for copies of this eBook, complying with the
-rules is very easy.  You may use this eBook for nearly any purpose
-such as creation of derivative works, reports, performances and
-research.  They may be modified and printed and given away--you may do
-practically ANYTHING with public domain eBooks.  Redistribution is
-subject to the trademark license, especially commercial
-redistribution.
-
-
-
-*** START: FULL LICENSE ***
-
-THE FULL PROJECT GUTENBERG LICENSE
-PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK
-
-To protect the Project Gutenberg-tm mission of promoting the free
-distribution of electronic works, by using or distributing this work
-(or any other work associated in any way with the phrase "Project
-Gutenberg"), you agree to comply with all the terms of the Full Project
-Gutenberg-tm License (available with this file or online at
-http://gutenberg.net/license).
-
-
-Section 1.  General Terms of Use and Redistributing Project Gutenberg-tm
-electronic works
-
-1.A.  By reading or using any part of this Project Gutenberg-tm
-electronic work, you indicate that you have read, understand, agree to
-and accept all the terms of this license and intellectual property
-(trademark/copyright) agreement.  If you do not agree to abide by all
-the terms of this agreement, you must cease using and return or destroy
-all copies of Project Gutenberg-tm electronic works in your possession.
-If you paid a fee for obtaining a copy of or access to a Project
-Gutenberg-tm electronic work and you do not agree to be bound by the
-terms of this agreement, you may obtain a refund from the person or
-entity to whom you paid the fee as set forth in paragraph 1.E.8.
-
-1.B.  "Project Gutenberg" is a registered trademark.  It may only be
-used on or associated in any way with an electronic work by people who
-agree to be bound by the terms of this agreement.  There are a few
-things that you can do with most Project Gutenberg-tm electronic works
-even without complying with the full terms of this agreement.  See
-paragraph 1.C below.  There are a lot of things you can do with Project
-Gutenberg-tm electronic works if you follow the terms of this agreement
-and help preserve free future access to Project Gutenberg-tm electronic
-works.  See paragraph 1.E below.
-
-1.C.  The Project Gutenberg Literary Archive Foundation ("the Foundation"
-or PGLAF), owns a compilation copyright in the collection of Project
-Gutenberg-tm electronic works.  Nearly all the individual works in the
-collection are in the public domain in the United States.  If an
-individual work is in the public domain in the United States and you are
-located in the United States, we do not claim a right to prevent you from
-copying, distributing, performing, displaying or creating derivative
-works based on the work as long as all references to Project Gutenberg
-are removed.  Of course, we hope that you will support the Project
-Gutenberg-tm mission of promoting free access to electronic works by
-freely sharing Project Gutenberg-tm works in compliance with the terms of
-this agreement for keeping the Project Gutenberg-tm name associated with
-the work.  You can easily comply with the terms of this agreement by
-keeping this work in the same format with its attached full Project
-Gutenberg-tm License when you share it without charge with others.
-
-1.D.  The copyright laws of the place where you are located also govern
-what you can do with this work.  Copyright laws in most countries are in
-a constant state of change.  If you are outside the United States, check
-the laws of your country in addition to the terms of this agreement
-before downloading, copying, displaying, performing, distributing or
-creating derivative works based on this work or any other Project
-Gutenberg-tm work.  The Foundation makes no representations concerning
-the copyright status of any work in any country outside the United
-States.
-
-1.E.  Unless you have removed all references to Project Gutenberg:
-
-1.E.1.  The following sentence, with active links to, or other immediate
-access to, the full Project Gutenberg-tm License must appear prominently
-whenever any copy of a Project Gutenberg-tm work (any work on which the
-phrase "Project Gutenberg" appears, or with which the phrase "Project
-Gutenberg" is associated) is accessed, displayed, performed, viewed,
-copied or distributed:
-
-This eBook is for the use of anyone anywhere at no cost and with
-almost no restrictions whatsoever.  You may copy it, give it away or
-re-use it under the terms of the Project Gutenberg License included
-with this eBook or online at www.gutenberg.net
-
-1.E.2.  If an individual Project Gutenberg-tm electronic work is derived
-from the public domain (does not contain a notice indicating that it is
-posted with permission of the copyright holder), the work can be copied
-and distributed to anyone in the United States without paying any fees
-or charges.  If you are redistributing or providing access to a work
-with the phrase "Project Gutenberg" associated with or appearing on the
-work, you must comply either with the requirements of paragraphs 1.E.1
-through 1.E.7 or obtain permission for the use of the work and the
-Project Gutenberg-tm trademark as set forth in paragraphs 1.E.8 or
-1.E.9.
-
-1.E.3.  If an individual Project Gutenberg-tm electronic work is posted
-with the permission of the copyright holder, your use and distribution
-must comply with both paragraphs 1.E.1 through 1.E.7 and any additional
-terms imposed by the copyright holder.  Additional terms will be linked
-to the Project Gutenberg-tm License for all works posted with the
-permission of the copyright holder found at the beginning of this work.
-
-1.E.4.  Do not unlink or detach or remove the full Project Gutenberg-tm
-License terms from this work, or any files containing a part of this
-work or any other work associated with Project Gutenberg-tm.
-
-1.E.5.  Do not copy, display, perform, distribute or redistribute this
-electronic work, or any part of this electronic work, without
-prominently displaying the sentence set forth in paragraph 1.E.1 with
-active links or immediate access to the full terms of the Project
-Gutenberg-tm License.
-
-1.E.6.  You may convert to and distribute this work in any binary,
-compressed, marked up, nonproprietary or proprietary form, including any
-word processing or hypertext form.  However, if you provide access to or
-distribute copies of a Project Gutenberg-tm work in a format other than
-"Plain Vanilla ASCII" or other format used in the official version
-posted on the official Project Gutenberg-tm web site (www.gutenberg.net),
-you must, at no additional cost, fee or expense to the user, provide a
-copy, a means of exporting a copy, or a means of obtaining a copy upon
-request, of the work in its original "Plain Vanilla ASCII" or other
-form.  Any alternate format must include the full Project Gutenberg-tm
-License as specified in paragraph 1.E.1.
-
-1.E.7.  Do not charge a fee for access to, viewing, displaying,
-performing, copying or distributing any Project Gutenberg-tm works
-unless you comply with paragraph 1.E.8 or 1.E.9.
-
-1.E.8.  You may charge a reasonable fee for copies of or providing
-access to or distributing Project Gutenberg-tm electronic works provided
-that
-
-- You pay a royalty fee of 20% of the gross profits you derive from
-     the use of Project Gutenberg-tm works calculated using the method
-     you already use to calculate your applicable taxes.  The fee is
-     owed to the owner of the Project Gutenberg-tm trademark, but he
-     has agreed to donate royalties under this paragraph to the
-     Project Gutenberg Literary Archive Foundation.  Royalty payments
-     must be paid within 60 days following each date on which you
-     prepare (or are legally required to prepare) your periodic tax
-     returns.  Royalty payments should be clearly marked as such and
-     sent to the Project Gutenberg Literary Archive Foundation at the
-     address specified in Section 4, "Information about donations to
-     the Project Gutenberg Literary Archive Foundation."
-
-- You provide a full refund of any money paid by a user who notifies
-     you in writing (or by e-mail) within 30 days of receipt that s/he
-     does not agree to the terms of the full Project Gutenberg-tm
-     License.  You must require such a user to return or
-     destroy all copies of the works possessed in a physical medium
-     and discontinue all use of and all access to other copies of
-     Project Gutenberg-tm works.
-
-- You provide, in accordance with paragraph 1.F.3, a full refund of any
-     money paid for a work or a replacement copy, if a defect in the
-     electronic work is discovered and reported to you within 90 days
-     of receipt of the work.
-
-- You comply with all other terms of this agreement for free
-     distribution of Project Gutenberg-tm works.
-
-1.E.9.  If you wish to charge a fee or distribute a Project Gutenberg-tm
-electronic work or group of works on different terms than are set
-forth in this agreement, you must obtain permission in writing from
-both the Project Gutenberg Literary Archive Foundation and Michael
-Hart, the owner of the Project Gutenberg-tm trademark.  Contact the
-Foundation as set forth in Section 3 below.
-
-1.F.
-
-1.F.1.  Project Gutenberg volunteers and employees expend considerable
-effort to identify, do copyright research on, transcribe and proofread
-public domain works in creating the Project Gutenberg-tm
-collection.  Despite these efforts, Project Gutenberg-tm electronic
-works, and the medium on which they may be stored, may contain
-"Defects," such as, but not limited to, incomplete, inaccurate or
-corrupt data, transcription errors, a copyright or other intellectual
-property infringement, a defective or damaged disk or other medium, a
-computer virus, or computer codes that damage or cannot be read by
-your equipment.
-
-1.F.2.  LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except for the "Right
-of Replacement or Refund" described in paragraph 1.F.3, the Project
-Gutenberg Literary Archive Foundation, the owner of the Project
-Gutenberg-tm trademark, and any other party distributing a Project
-Gutenberg-tm electronic work under this agreement, disclaim all
-liability to you for damages, costs and expenses, including legal
-fees.  YOU AGREE THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT
-LIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT EXCEPT THOSE
-PROVIDED IN PARAGRAPH F3.  YOU AGREE THAT THE FOUNDATION, THE
-TRADEMARK OWNER, AND ANY DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE
-LIABLE TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE OR
-INCIDENTAL DAMAGES EVEN IF YOU GIVE NOTICE OF THE POSSIBILITY OF SUCH
-DAMAGE.
-
-1.F.3.  LIMITED RIGHT OF REPLACEMENT OR REFUND - If you discover a
-defect in this electronic work within 90 days of receiving it, you can
-receive a refund of the money (if any) you paid for it by sending a
-written explanation to the person you received the work from.  If you
-received the work on a physical medium, you must return the medium with
-your written explanation.  The person or entity that provided you with
-the defective work may elect to provide a replacement copy in lieu of a
-refund.  If you received the work electronically, the person or entity
-providing it to you may choose to give you a second opportunity to
-receive the work electronically in lieu of a refund.  If the second copy
-is also defective, you may demand a refund in writing without further
-opportunities to fix the problem.
-
-1.F.4.  Except for the limited right of replacement or refund set forth
-in paragraph 1.F.3, this work is provided to you 'AS-IS' WITH NO OTHER
-WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
-WARRANTIES OF MERCHANTIBILITY OR FITNESS FOR ANY PURPOSE.
-
-1.F.5.  Some states do not allow disclaimers of certain implied
-warranties or the exclusion or limitation of certain types of damages.
-If any disclaimer or limitation set forth in this agreement violates the
-law of the state applicable to this agreement, the agreement shall be
-interpreted to make the maximum disclaimer or limitation permitted by
-the applicable state law.  The invalidity or unenforceability of any
-provision of this agreement shall not void the remaining provisions.
-
-1.F.6.  INDEMNITY - You agree to indemnify and hold the Foundation, the
-trademark owner, any agent or employee of the Foundation, anyone
-providing copies of Project Gutenberg-tm electronic works in accordance
-with this agreement, and any volunteers associated with the production,
-promotion and distribution of Project Gutenberg-tm electronic works,
-harmless from all liability, costs and expenses, including legal fees,
-that arise directly or indirectly from any of the following which you do
-or cause to occur: (a) distribution of this or any Project Gutenberg-tm
-work, (b) alteration, modification, or additions or deletions to any
-Project Gutenberg-tm work, and (c) any Defect you cause.
-
-
-Section  2.  Information about the Mission of Project Gutenberg-tm
-
-Project Gutenberg-tm is synonymous with the free distribution of
-electronic works in formats readable by the widest variety of computers
-including obsolete, old, middle-aged and new computers.  It exists
-because of the efforts of hundreds of volunteers and donations from
-people in all walks of life.
-
-Volunteers and financial support to provide volunteers with the
-assistance they need, is critical to reaching Project Gutenberg-tm's
-goals and ensuring that the Project Gutenberg-tm collection will
-remain freely available for generations to come.  In 2001, the Project
-Gutenberg Literary Archive Foundation was created to provide a secure
-and permanent future for Project Gutenberg-tm and future generations.
-To learn more about the Project Gutenberg Literary Archive Foundation
-and how your efforts and donations can help, see Sections 3 and 4
-and the Foundation web page at http://www.pglaf.org.
-
-
-Section 3.  Information about the Project Gutenberg Literary Archive
-Foundation
-
-The Project Gutenberg Literary Archive Foundation is a non profit
-501(c)(3) educational corporation organized under the laws of the
-state of Mississippi and granted tax exempt status by the Internal
-Revenue Service.  The Foundation's EIN or federal tax identification
-number is 64-6221541.  Its 501(c)(3) letter is posted at
-http://pglaf.org/fundraising.  Contributions to the Project Gutenberg
-Literary Archive Foundation are tax deductible to the full extent
-permitted by U.S. federal laws and your state's laws.
-
-The Foundation's principal office is located at 4557 Melan Dr. S.
-Fairbanks, AK, 99712., but its volunteers and employees are scattered
-throughout numerous locations.  Its business office is located at
-809 North 1500 West, Salt Lake City, UT 84116, (801) 596-1887, email
-business at pglaf.org.  Email contact links and up to date contact
-information can be found at the Foundation's web site and official
-page at http://pglaf.org
-
-For additional contact information:
-     Dr. Gregory B. Newby
-     Chief Executive and Director
-     gbnewby at pglaf.org
-
-
-Section 4.  Information about Donations to the Project Gutenberg
-Literary Archive Foundation
-
-Project Gutenberg-tm depends upon and cannot survive without wide
-spread public support and donations to carry out its mission of
-increasing the number of public domain and licensed works that can be
-freely distributed in machine readable form accessible by the widest
-array of equipment including outdated equipment.  Many small donations
-($1 to $5,000) are particularly important to maintaining tax exempt
-status with the IRS.
-
-The Foundation is committed to complying with the laws regulating
-charities and charitable donations in all 50 states of the United
-States.  Compliance requirements are not uniform and it takes a
-considerable effort, much paperwork and many fees to meet and keep up
-with these requirements.  We do not solicit donations in locations
-where we have not received written confirmation of compliance.  To
-SEND DONATIONS or determine the status of compliance for any
-particular state visit http://pglaf.org
-
-While we cannot and do not solicit contributions from states where we
-have not met the solicitation requirements, we know of no prohibition
-against accepting unsolicited donations from donors in such states who
-approach us with offers to donate.
-
-International donations are gratefully accepted, but we cannot make
-any statements concerning tax treatment of donations received from
-outside the United States.  U.S. laws alone swamp our small staff.
-
-Please check the Project Gutenberg Web pages for current donation
-methods and addresses.  Donations are accepted in a number of other
-ways including including checks, online payments and credit card
-donations.  To donate, please visit: http://pglaf.org/donate
-
-
-Section 5.  General Information About Project Gutenberg-tm electronic
-works.
-
-Professor Michael S. Hart is the originator of the Project Gutenberg-tm
-concept of a library of electronic works that could be freely shared
-with anyone.  For thirty years, he produced and distributed Project
-Gutenberg-tm eBooks with only a loose network of volunteer support.
-
-
-Project Gutenberg-tm eBooks are often created from several printed
-editions, all of which are confirmed as Public Domain in the U.S.
-unless a copyright notice is included.  Thus, we do not necessarily
-keep eBooks in compliance with any particular paper edition.
-
-
-Most people start at our Web site which has the main PG search facility:
-
-     http://www.gutenberg.net
-
-This Web site includes information about Project Gutenberg-tm,
-including how to make donations to the Project Gutenberg Literary
-Archive Foundation, how to help produce our new eBooks, and how to
-subscribe to our email newsletter to hear about new eBooks.
diff --git a/src/compress/testdata/gettysburg.txt b/src/compress/testdata/gettysburg.txt
new file mode 100644
index 0000000..2c9bcde
--- /dev/null
+++ b/src/compress/testdata/gettysburg.txt
@@ -0,0 +1,29 @@
+  Four score and seven years ago our fathers brought forth on
+this continent, a new nation, conceived in Liberty, and dedicated
+to the proposition that all men are created equal.
+  Now we are engaged in a great Civil War, testing whether that
+nation, or any nation so conceived and so dedicated, can long
+endure.
+  We are met on a great battle-field of that war.
+  We have come to dedicate a portion of that field, as a final
+resting place for those who here gave their lives that that
+nation might live.  It is altogether fitting and proper that
+we should do this.
+  But, in a larger sense, we can not dedicate - we can not
+consecrate - we can not hallow - this ground.
+  The brave men, living and dead, who struggled here, have
+consecrated it, far above our poor power to add or detract.
+The world will little note, nor long remember what we say here,
+but it can never forget what they did here.
+  It is for us the living, rather, to be dedicated here to the
+unfinished work which they who fought here have thus far so
+nobly advanced.  It is rather for us to be here dedicated to
+the great task remaining before us - that from these honored
+dead we take increased devotion to that cause for which they
+gave the last full measure of devotion -
+  that we here highly resolve that these dead shall not have
+died in vain - that this nation, under God, shall have a new
+birth of freedom - and that government of the people, by the
+people, for the people, shall not perish from this earth.
+
+Abraham Lincoln, November 19, 1863, Gettysburg, Pennsylvania
diff --git a/src/compress/zlib/reader.go b/src/compress/zlib/reader.go
index 816f1bf..78ea704 100644
--- a/src/compress/zlib/reader.go
+++ b/src/compress/zlib/reader.go
@@ -101,6 +101,9 @@ func (z *reader) Read(p []byte) (n int, err error) {
 
 	// Finished file; check checksum.
 	if _, err := io.ReadFull(z.r, z.scratch[0:4]); err != nil {
+		if err == io.EOF {
+			err = io.ErrUnexpectedEOF
+		}
 		z.err = err
 		return 0, err
 	}
@@ -130,6 +133,9 @@ func (z *reader) Reset(r io.Reader, dict []byte) error {
 	}
 	_, err := io.ReadFull(z.r, z.scratch[0:2])
 	if err != nil {
+		if err == io.EOF {
+			err = io.ErrUnexpectedEOF
+		}
 		return err
 	}
 	h := uint(z.scratch[0])<<8 | uint(z.scratch[1])
@@ -140,6 +146,9 @@ func (z *reader) Reset(r io.Reader, dict []byte) error {
 	if haveDict {
 		_, err = io.ReadFull(z.r, z.scratch[0:4])
 		if err != nil {
+			if err == io.EOF {
+				err = io.ErrUnexpectedEOF
+			}
 			return err
 		}
 		checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
diff --git a/src/compress/zlib/reader_test.go b/src/compress/zlib/reader_test.go
index 218ccba..449f446 100644
--- a/src/compress/zlib/reader_test.go
+++ b/src/compress/zlib/reader_test.go
@@ -23,6 +23,30 @@ type zlibTest struct {
 
 var zlibTests = []zlibTest{
 	{
+		"truncated empty",
+		"",
+		[]byte{},
+		nil,
+		io.ErrUnexpectedEOF,
+	},
+	{
+		"truncated dict",
+		"",
+		[]byte{0x78, 0xbb},
+		[]byte{0x00},
+		io.ErrUnexpectedEOF,
+	},
+	{
+		"truncated checksum",
+		"",
+		[]byte{0x78, 0xbb, 0x00, 0x01, 0x00, 0x01, 0xca, 0x48,
+			0xcd, 0xc9, 0xc9, 0xd7, 0x51, 0x28, 0xcf, 0x2f,
+			0xca, 0x49, 0x01, 0x04, 0x00, 0x00, 0xff, 0xff,
+		},
+		[]byte{0x00},
+		io.ErrUnexpectedEOF,
+	},
+	{
 		"empty",
 		"",
 		[]byte{0x78, 0x9c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01},
diff --git a/src/compress/zlib/writer_test.go b/src/compress/zlib/writer_test.go
index 71ba81a..dd94165 100644
--- a/src/compress/zlib/writer_test.go
+++ b/src/compress/zlib/writer_test.go
@@ -7,6 +7,7 @@ package zlib
 import (
 	"bytes"
 	"fmt"
+	"internal/testenv"
 	"io"
 	"io/ioutil"
 	"os"
@@ -14,6 +15,7 @@ import (
 )
 
 var filenames = []string{
+	"../testdata/gettysburg.txt",
 	"../testdata/e.txt",
 	"../testdata/pi.txt",
 }
@@ -152,22 +154,34 @@ func TestWriter(t *testing.T) {
 }
 
 func TestWriterBig(t *testing.T) {
-	for _, fn := range filenames {
+	for i, fn := range filenames {
 		testFileLevelDict(t, fn, DefaultCompression, "")
 		testFileLevelDict(t, fn, NoCompression, "")
 		for level := BestSpeed; level <= BestCompression; level++ {
 			testFileLevelDict(t, fn, level, "")
+			if level >= 1 && testing.Short() && testenv.Builder() == "" {
+				break
+			}
+		}
+		if i == 0 && testing.Short() && testenv.Builder() == "" {
+			break
 		}
 	}
 }
 
 func TestWriterDict(t *testing.T) {
 	const dictionary = "0123456789."
-	for _, fn := range filenames {
+	for i, fn := range filenames {
 		testFileLevelDict(t, fn, DefaultCompression, dictionary)
 		testFileLevelDict(t, fn, NoCompression, dictionary)
 		for level := BestSpeed; level <= BestCompression; level++ {
 			testFileLevelDict(t, fn, level, dictionary)
+			if level >= 1 && testing.Short() && testenv.Builder() == "" {
+				break
+			}
+		}
+		if i == 0 && testing.Short() && testenv.Builder() == "" {
+			break
 		}
 	}
 }
@@ -179,10 +193,11 @@ func TestWriterReset(t *testing.T) {
 		testFileLevelDictReset(t, fn, DefaultCompression, nil)
 		testFileLevelDictReset(t, fn, NoCompression, []byte(dictionary))
 		testFileLevelDictReset(t, fn, DefaultCompression, []byte(dictionary))
-		if !testing.Short() {
-			for level := BestSpeed; level <= BestCompression; level++ {
-				testFileLevelDictReset(t, fn, level, nil)
-			}
+		if testing.Short() {
+			break
+		}
+		for level := BestSpeed; level <= BestCompression; level++ {
+			testFileLevelDictReset(t, fn, level, nil)
 		}
 	}
 }
diff --git a/src/crypto/aes/aes_gcm.go b/src/crypto/aes/aes_gcm.go
new file mode 100644
index 0000000..1377578
--- /dev/null
+++ b/src/crypto/aes/aes_gcm.go
@@ -0,0 +1,172 @@
+// Copyright 2015 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.
+
+// +build amd64
+
+package aes
+
+import (
+	"crypto/cipher"
+	"crypto/subtle"
+	"errors"
+)
+
+// The following functions are defined in gcm_amd64.s.
+func hasGCMAsm() bool
+
+//go:noescape
+func aesEncBlock(dst, src *[16]byte, ks []uint32)
+
+//go:noescape
+func gcmAesInit(productTable *[256]byte, ks []uint32)
+
+//go:noescape
+func gcmAesData(productTable *[256]byte, data []byte, T *[16]byte)
+
+//go:noescape
+func gcmAesEnc(productTable *[256]byte, dst, src []byte, ctr, T *[16]byte, ks []uint32)
+
+//go:noescape
+func gcmAesDec(productTable *[256]byte, dst, src []byte, ctr, T *[16]byte, ks []uint32)
+
+//go:noescape
+func gcmAesFinish(productTable *[256]byte, tagMask, T *[16]byte, pLen, dLen uint64)
+
+const (
+	gcmBlockSize         = 16
+	gcmTagSize           = 16
+	gcmStandardNonceSize = 12
+)
+
+var errOpen = errors.New("cipher: message authentication failed")
+
+// aesCipherGCM implements crypto/cipher.gcmAble so that crypto/cipher.NewGCM
+// will use the optimised implementation in this file when possible. Instances
+// of this type only exist when hasGCMAsm returns true.
+type aesCipherGCM struct {
+	aesCipher
+}
+
+// NewGCM returns the AES cipher wrapped in Galois Counter Mode. This is only
+// called by crypto/cipher.NewGCM via the gcmAble interface.
+func (c *aesCipherGCM) NewGCM(nonceSize int) (cipher.AEAD, error) {
+	g := &gcmAsm{ks: c.enc, nonceSize: nonceSize}
+	gcmAesInit(&g.productTable, g.ks)
+	return g, nil
+}
+
+type gcmAsm struct {
+	// ks is the key schedule, the length of which depends on the size of
+	// the AES key.
+	ks []uint32
+	// productTable contains pre-computed multiples of the binary-field
+	// element used in GHASH.
+	productTable [256]byte
+	// nonceSize contains the expected size of the nonce, in bytes.
+	nonceSize int
+}
+
+func (g *gcmAsm) NonceSize() int {
+	return g.nonceSize
+}
+
+func (*gcmAsm) Overhead() int {
+	return gcmTagSize
+}
+
+// sliceForAppend takes a slice and a requested number of bytes. It returns a
+// slice with the contents of the given slice followed by that many bytes and a
+// second slice that aliases into it and contains only the extra bytes. If the
+// original slice has sufficient capacity then no allocation is performed.
+func sliceForAppend(in []byte, n int) (head, tail []byte) {
+	if total := len(in) + n; cap(in) >= total {
+		head = in[:total]
+	} else {
+		head = make([]byte, total)
+		copy(head, in)
+	}
+	tail = head[len(in):]
+	return
+}
+
+// Seal encrypts and authenticates plaintext. See the cipher.AEAD interface for
+// details.
+func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte {
+	if len(nonce) != g.nonceSize {
+		panic("cipher: incorrect nonce length given to GCM")
+	}
+
+	var counter, tagMask [gcmBlockSize]byte
+
+	if len(nonce) == gcmStandardNonceSize {
+		// Init counter to nonce||1
+		copy(counter[:], nonce)
+		counter[gcmBlockSize-1] = 1
+	} else {
+		// Otherwise counter = GHASH(nonce)
+		gcmAesData(&g.productTable, nonce, &counter)
+		gcmAesFinish(&g.productTable, &tagMask, &counter, uint64(len(nonce)), uint64(0))
+	}
+
+	aesEncBlock(&tagMask, &counter, g.ks)
+
+	var tagOut [gcmTagSize]byte
+	gcmAesData(&g.productTable, data, &tagOut)
+
+	ret, out := sliceForAppend(dst, len(plaintext)+gcmTagSize)
+	if len(plaintext) > 0 {
+		gcmAesEnc(&g.productTable, out, plaintext, &counter, &tagOut, g.ks)
+	}
+	gcmAesFinish(&g.productTable, &tagMask, &tagOut, uint64(len(plaintext)), uint64(len(data)))
+	copy(out[len(plaintext):], tagOut[:])
+
+	return ret
+}
+
+// Open authenticates and decrypts ciphertext. See the cipher.AEAD interface
+// for details.
+func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
+	if len(nonce) != g.nonceSize {
+		panic("cipher: incorrect nonce length given to GCM")
+	}
+
+	if len(ciphertext) < gcmTagSize {
+		return nil, errOpen
+	}
+	tag := ciphertext[len(ciphertext)-gcmTagSize:]
+	ciphertext = ciphertext[:len(ciphertext)-gcmTagSize]
+
+	// See GCM spec, section 7.1.
+	var counter, tagMask [gcmBlockSize]byte
+
+	if len(nonce) == gcmStandardNonceSize {
+		// Init counter to nonce||1
+		copy(counter[:], nonce)
+		counter[gcmBlockSize-1] = 1
+	} else {
+		// Otherwise counter = GHASH(nonce)
+		gcmAesData(&g.productTable, nonce, &counter)
+		gcmAesFinish(&g.productTable, &tagMask, &counter, uint64(len(nonce)), uint64(0))
+	}
+
+	aesEncBlock(&tagMask, &counter, g.ks)
+
+	var expectedTag [gcmTagSize]byte
+	gcmAesData(&g.productTable, data, &expectedTag)
+
+	ret, out := sliceForAppend(dst, len(ciphertext))
+	if len(ciphertext) > 0 {
+		gcmAesDec(&g.productTable, out, ciphertext, &counter, &expectedTag, g.ks)
+	}
+	gcmAesFinish(&g.productTable, &tagMask, &expectedTag, uint64(len(ciphertext)), uint64(len(data)))
+
+	if subtle.ConstantTimeCompare(expectedTag[:], tag) != 1 {
+		for i := range out {
+			out[i] = 0
+		}
+		return nil, errOpen
+	}
+
+	return ret, nil
+}
diff --git a/src/crypto/aes/asm_amd64.s b/src/crypto/aes/asm_amd64.s
index 6a6e6ac..b257998 100644
--- a/src/crypto/aes/asm_amd64.s
+++ b/src/crypto/aes/asm_amd64.s
@@ -217,8 +217,6 @@ Lexp_dec_loop:
 	MOVUPS X0, 16(DX)
 	RET
 
-#define PSHUFD_X0_X0_ BYTE $0x66; BYTE $0x0f; BYTE $0x70; BYTE $0xc0
-#define PSHUFD_X1_X1_ BYTE $0x66; BYTE $0x0f; BYTE $0x70; BYTE $0xc9
 TEXT _expand_key_128<>(SB),NOSPLIT,$0
 	PSHUFD $0xff, X1, X1
 	SHUFPS $0x10, X0, X4
@@ -230,8 +228,6 @@ TEXT _expand_key_128<>(SB),NOSPLIT,$0
 	ADDQ $16, BX
 	RET
 
-#define PSLLDQ_X5_ BYTE $0x66; BYTE $0x0f; BYTE $0x73; BYTE $0xfd
-#define PSHUFD_X0_X3_ BYTE $0x66; BYTE $0x0f; BYTE $0x70; BYTE $0xd8
 TEXT _expand_key_192a<>(SB),NOSPLIT,$0
 	PSHUFD $0x55, X1, X1
 	SHUFPS $0x10, X0, X4
@@ -242,7 +238,7 @@ TEXT _expand_key_192a<>(SB),NOSPLIT,$0
 
 	MOVAPS X2, X5
 	MOVAPS X2, X6
-	PSLLDQ_X5_; BYTE $0x4
+	PSLLDQ $0x4, X5
 	PSHUFD $0xff, X0, X3
 	PXOR X3, X2
 	PXOR X5, X2
@@ -264,7 +260,7 @@ TEXT _expand_key_192b<>(SB),NOSPLIT,$0
 	PXOR X1, X0
 
 	MOVAPS X2, X5
-	PSLLDQ_X5_; BYTE $0x4
+	PSLLDQ $0x4, X5
 	PSHUFD $0xff, X0, X3
 	PXOR X3, X2
 	PXOR X5, X2
diff --git a/src/crypto/aes/cipher.go b/src/crypto/aes/cipher.go
index 2c6bb0a..04d2be1 100644
--- a/src/crypto/aes/cipher.go
+++ b/src/crypto/aes/cipher.go
@@ -38,9 +38,14 @@ func NewCipher(key []byte) (cipher.Block, error) {
 	}
 
 	n := k + 28
-	c := &aesCipher{make([]uint32, n), make([]uint32, n)}
+	c := aesCipher{make([]uint32, n), make([]uint32, n)}
 	expandKey(key, c.enc, c.dec)
-	return c, nil
+
+	if hasGCMAsm() {
+		return &aesCipherGCM{c}, nil
+	}
+
+	return &c, nil
 }
 
 func (c *aesCipher) BlockSize() int { return BlockSize }
diff --git a/src/crypto/aes/cipher_generic.go b/src/crypto/aes/cipher_generic.go
index 1714e0f..32b2b3c 100644
--- a/src/crypto/aes/cipher_generic.go
+++ b/src/crypto/aes/cipher_generic.go
@@ -17,3 +17,11 @@ func decryptBlock(xk []uint32, dst, src []byte) {
 func expandKey(key []byte, enc, dec []uint32) {
 	expandKeyGo(key, enc, dec)
 }
+
+func hasGCMAsm() bool {
+	return false
+}
+
+type aesCipherGCM struct {
+	aesCipher
+}
diff --git a/src/crypto/aes/gcm_amd64.s b/src/crypto/aes/gcm_amd64.s
new file mode 100644
index 0000000..cabb028
--- /dev/null
+++ b/src/crypto/aes/gcm_amd64.s
@@ -0,0 +1,1277 @@
+// Copyright 2015 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 is an optimized implementation of AES-GCM using AES-NI and CLMUL-NI
+// The implementation uses some optimization as described in:
+// [1] Gueron, S., Kounavis, M.E.: Intel® Carry-Less Multiplication
+//     Instruction and its Usage for Computing the GCM Mode rev. 2.02
+// [2] Gueron, S., Krasnov, V.: Speeding up Counter Mode in Software and
+//     Hardware
+
+#include "textflag.h"
+
+#define B0 X0
+#define B1 X1
+#define B2 X2
+#define B3 X3
+#define B4 X4
+#define B5 X5
+#define B6 X6
+#define B7 X7
+
+#define ACC0 X8
+#define ACC1 X9
+#define ACCM X10
+
+#define T0 X11
+#define T1 X12
+#define T2 X13
+#define POLY X14
+#define BSWAP X15
+
+DATA bswapMask<>+0x00(SB)/8, $0x08090a0b0c0d0e0f
+DATA bswapMask<>+0x08(SB)/8, $0x0001020304050607
+
+DATA gcmPoly<>+0x00(SB)/8, $0x0000000000000001
+DATA gcmPoly<>+0x08(SB)/8, $0xc200000000000000
+
+DATA andMask<>+0x00(SB)/8, $0x00000000000000ff
+DATA andMask<>+0x08(SB)/8, $0x0000000000000000
+DATA andMask<>+0x10(SB)/8, $0x000000000000ffff
+DATA andMask<>+0x18(SB)/8, $0x0000000000000000
+DATA andMask<>+0x20(SB)/8, $0x0000000000ffffff
+DATA andMask<>+0x28(SB)/8, $0x0000000000000000
+DATA andMask<>+0x30(SB)/8, $0x00000000ffffffff
+DATA andMask<>+0x38(SB)/8, $0x0000000000000000
+DATA andMask<>+0x40(SB)/8, $0x000000ffffffffff
+DATA andMask<>+0x48(SB)/8, $0x0000000000000000
+DATA andMask<>+0x50(SB)/8, $0x0000ffffffffffff
+DATA andMask<>+0x58(SB)/8, $0x0000000000000000
+DATA andMask<>+0x60(SB)/8, $0x00ffffffffffffff
+DATA andMask<>+0x68(SB)/8, $0x0000000000000000
+DATA andMask<>+0x70(SB)/8, $0xffffffffffffffff
+DATA andMask<>+0x78(SB)/8, $0x0000000000000000
+DATA andMask<>+0x80(SB)/8, $0xffffffffffffffff
+DATA andMask<>+0x88(SB)/8, $0x00000000000000ff
+DATA andMask<>+0x90(SB)/8, $0xffffffffffffffff
+DATA andMask<>+0x98(SB)/8, $0x000000000000ffff
+DATA andMask<>+0xa0(SB)/8, $0xffffffffffffffff
+DATA andMask<>+0xa8(SB)/8, $0x0000000000ffffff
+DATA andMask<>+0xb0(SB)/8, $0xffffffffffffffff
+DATA andMask<>+0xb8(SB)/8, $0x00000000ffffffff
+DATA andMask<>+0xc0(SB)/8, $0xffffffffffffffff
+DATA andMask<>+0xc8(SB)/8, $0x000000ffffffffff
+DATA andMask<>+0xd0(SB)/8, $0xffffffffffffffff
+DATA andMask<>+0xd8(SB)/8, $0x0000ffffffffffff
+DATA andMask<>+0xe0(SB)/8, $0xffffffffffffffff
+DATA andMask<>+0xe8(SB)/8, $0x00ffffffffffffff
+
+GLOBL bswapMask<>(SB), (NOPTR+RODATA), $16
+GLOBL gcmPoly<>(SB), (NOPTR+RODATA), $16
+GLOBL andMask<>(SB), (NOPTR+RODATA), $240
+
+// func hasGCMAsm() bool
+// returns whether AES-NI AND CLMUL-NI are supported
+TEXT ·hasGCMAsm(SB),NOSPLIT,$0
+	XORQ AX, AX
+	INCL AX
+	CPUID
+	MOVQ CX, DX
+	SHRQ $25, CX
+	SHRQ $1, DX
+	ANDQ DX, CX
+	ANDQ $1, CX
+	MOVB CX, ret+0(FP)
+	RET
+
+// func aesEncBlock(dst, src *[16]byte, ks []uint32)
+TEXT ·aesEncBlock(SB),NOSPLIT,$0
+	MOVQ dst+0(FP), DI
+	MOVQ src+8(FP), SI
+	MOVQ ks+16(FP), DX
+	MOVQ ks+24(FP), CX
+
+	SHRQ $2, CX
+	DECQ CX
+
+	MOVOU (SI), X0
+	MOVOU (16*0)(DX), X1
+	PXOR X1, X0
+	MOVOU (16*1)(DX), X1
+	AESENC X1, X0
+	MOVOU (16*2)(DX), X1
+	AESENC X1, X0
+	MOVOU (16*3)(DX), X1
+	AESENC X1, X0
+	MOVOU (16*4)(DX), X1
+	AESENC X1, X0
+	MOVOU (16*5)(DX), X1
+	AESENC X1, X0
+	MOVOU (16*6)(DX), X1
+	AESENC X1, X0
+	MOVOU (16*7)(DX), X1
+	AESENC X1, X0
+	MOVOU (16*8)(DX), X1
+	AESENC X1, X0
+	MOVOU (16*9)(DX), X1
+	AESENC X1, X0
+	MOVOU (16*10)(DX), X1
+	CMPQ CX, $12
+	JB encLast
+	AESENC X1, X0
+	MOVOU (16*11)(DX), X1
+	AESENC X1, X0
+	MOVOU (16*12)(DX), X1
+	JE encLast
+	AESENC X1, X0
+	MOVOU (16*13)(DX), X1
+	AESENC X1, X0
+	MOVOU (16*14)(DX), X1
+
+encLast:
+	AESENCLAST X1, X0
+	MOVOU X0, (DI)
+
+	RET
+
+// func gcmAesFinish(productTable *[256]byte, tagMask, T *[16]byte, pLen, dLen uint64)
+TEXT ·gcmAesFinish(SB),NOSPLIT,$0
+#define pTbl DI
+#define tMsk SI
+#define tPtr DX
+#define plen AX
+#define dlen CX
+
+	MOVQ productTable+0(FP), pTbl
+	MOVQ tagMask+8(FP), tMsk
+	MOVQ T+16(FP), tPtr
+	MOVQ pLen+24(FP), plen
+	MOVQ dLen+32(FP), dlen
+
+	MOVOU (tPtr), ACC0
+	MOVOU (tMsk), T2
+
+	MOVOU bswapMask<>(SB), BSWAP
+	MOVOU gcmPoly<>(SB), POLY
+
+	SHLQ $3, plen
+	SHLQ $3, dlen
+
+	MOVQ plen, B0
+	PINSRQ $1, dlen, B0
+
+	PXOR ACC0, B0
+
+	MOVOU (16*14)(pTbl), ACC0
+	MOVOU (16*15)(pTbl), ACCM
+	MOVOU ACC0, ACC1
+
+	PCLMULQDQ $0x00, B0, ACC0
+	PCLMULQDQ $0x11, B0, ACC1
+	PSHUFD $78, B0, T0
+	PXOR B0, T0
+	PCLMULQDQ $0x00, T0, ACCM
+
+	PXOR ACC0, ACCM
+	PXOR ACC1, ACCM
+	MOVOU ACCM, T0
+	PSRLDQ $8, ACCM
+	PSLLDQ $8, T0
+	PXOR ACCM, ACC1
+	PXOR T0, ACC0
+
+	MOVOU POLY, T0
+	PCLMULQDQ $0x01, ACC0, T0
+	PSHUFD $78, ACC0, ACC0
+	PXOR T0, ACC0
+
+	MOVOU POLY, T0
+	PCLMULQDQ $0x01, ACC0, T0
+	PSHUFD $78, ACC0, ACC0
+	PXOR T0, ACC0
+
+	PXOR ACC1, ACC0
+
+	PSHUFB BSWAP, ACC0
+	PXOR T2, ACC0
+	MOVOU ACC0, (tPtr)
+
+	RET
+#undef pTbl
+#undef tMsk
+#undef tPtr
+#undef plen
+#undef dlen
+
+// func gcmAesInit(productTable *[256]byte, ks []uint32)
+TEXT ·gcmAesInit(SB),NOSPLIT,$0
+#define dst DI
+#define KS SI
+#define NR DX
+
+	MOVQ productTable+0(FP), dst
+	MOVQ ks+8(FP), KS
+	MOVQ ks+16(FP), NR
+
+	SHRQ $2, NR
+	DECQ NR
+
+	MOVOU bswapMask<>(SB), BSWAP
+	MOVOU gcmPoly<>(SB), POLY
+
+	// Encrypt block 0, with the AES key to generate the hash key H
+	MOVOU (16*0)(KS), B0
+	MOVOU (16*1)(KS), T0
+	AESENC T0, B0
+	MOVOU (16*2)(KS), T0
+	AESENC T0, B0
+	MOVOU (16*3)(KS), T0
+	AESENC T0, B0
+	MOVOU (16*4)(KS), T0
+	AESENC T0, B0
+	MOVOU (16*5)(KS), T0
+	AESENC T0, B0
+	MOVOU (16*6)(KS), T0
+	AESENC T0, B0
+	MOVOU (16*7)(KS), T0
+	AESENC T0, B0
+	MOVOU (16*8)(KS), T0
+	AESENC T0, B0
+	MOVOU (16*9)(KS), T0
+	AESENC T0, B0
+	MOVOU (16*10)(KS), T0
+	CMPQ NR, $12
+	JB initEncLast
+	AESENC T0, B0
+	MOVOU (16*11)(KS), T0
+	AESENC T0, B0
+	MOVOU (16*12)(KS), T0
+	JE initEncLast
+	AESENC T0, B0
+	MOVOU (16*13)(KS), T0
+	AESENC T0, B0
+	MOVOU (16*14)(KS), T0
+initEncLast:
+	AESENCLAST T0, B0
+
+	PSHUFB BSWAP, B0
+	// H * 2
+	PSHUFD $0xff, B0, T0
+	MOVOU B0, T1
+	PSRAL $31, T0
+	PAND POLY, T0
+	PSRLL $31, T1
+	PSLLDQ $4, T1
+	PSLLL $1, B0
+	PXOR T0, B0
+	PXOR T1, B0
+	// Karatsuba pre-computations
+	MOVOU B0, (16*14)(dst)
+	PSHUFD $78, B0, B1
+	PXOR B0, B1
+	MOVOU B1, (16*15)(dst)
+
+	MOVOU B0, B2
+	MOVOU B1, B3
+	// Now prepare powers of H and pre-computations for them
+	MOVQ $7, AX
+
+initLoop:
+		MOVOU B2, T0
+		MOVOU B2, T1
+		MOVOU B3, T2
+		PCLMULQDQ $0x00, B0, T0
+		PCLMULQDQ $0x11, B0, T1
+		PCLMULQDQ $0x00, B1, T2
+
+		PXOR T0, T2
+		PXOR T1, T2
+		MOVOU T2, B4
+		PSLLDQ $8, B4
+		PSRLDQ $8, T2
+		PXOR B4, T0
+		PXOR T2, T1
+
+		MOVOU POLY, B2
+		PCLMULQDQ $0x01, T0, B2
+		PSHUFD $78, T0, T0
+		PXOR B2, T0
+		MOVOU POLY, B2
+		PCLMULQDQ $0x01, T0, B2
+		PSHUFD $78, T0, T0
+		PXOR T0, B2
+		PXOR T1, B2
+
+		MOVOU B2, (16*12)(dst)
+		PSHUFD $78, B2, B3
+		PXOR B2, B3
+		MOVOU B3, (16*13)(dst)
+
+		DECQ AX
+		LEAQ (-16*2)(dst), dst
+	JNE initLoop
+
+	RET
+#undef NR
+#undef KS
+#undef dst
+
+// func gcmAesData(productTable *[256]byte, data []byte, T *[16]byte)
+TEXT ·gcmAesData(SB),NOSPLIT,$0
+#define pTbl DI
+#define aut SI
+#define tPtr CX
+#define autLen DX
+
+	MOVQ productTable+0(FP), pTbl
+	MOVQ data+8(FP), aut
+	MOVQ data+16(FP), autLen
+	MOVQ T+32(FP), tPtr
+
+	PXOR ACC0, ACC0
+	MOVOU bswapMask<>(SB), BSWAP
+	MOVOU gcmPoly<>(SB), POLY
+
+	MOVOU (16*14)(pTbl), T1
+	MOVOU (16*15)(pTbl), T2
+
+	TESTQ autLen, autLen
+	JEQ dataBail
+
+	CMPQ autLen, $13	// optimize the TLS case
+	JNE dataSinglesLoop
+
+	PXOR B0, B0
+	MOVQ (aut), B0
+	PINSRD $2, 8(aut), B0
+	PINSRB $12, 12(aut), B0
+	XORQ autLen, autLen
+	JMP dataMul
+
+dataSinglesLoop:
+
+		CMPQ autLen, $16
+		JB dataEnd
+		SUBQ $16, autLen
+
+		MOVOU (aut), B0
+dataMul:
+		PSHUFB BSWAP, B0
+		PXOR ACC0, B0
+
+		MOVOU T1, ACC0
+		MOVOU T2, ACCM
+		MOVOU T1, ACC1
+
+		PSHUFD $78, B0, T0
+		PXOR B0, T0
+		PCLMULQDQ $0x00, B0, ACC0
+		PCLMULQDQ $0x11, B0, ACC1
+		PCLMULQDQ $0x00, T0, ACCM
+
+		PXOR ACC0, ACCM
+		PXOR ACC1, ACCM
+		MOVOU ACCM, T0
+		PSRLDQ $8, ACCM
+		PSLLDQ $8, T0
+		PXOR ACCM, ACC1
+		PXOR T0, ACC0
+
+		MOVOU POLY, T0
+		PCLMULQDQ $0x01, ACC0, T0
+		PSHUFD $78, ACC0, ACC0
+		PXOR T0, ACC0
+
+		MOVOU POLY, T0
+		PCLMULQDQ $0x01, ACC0, T0
+		PSHUFD $78, ACC0, ACC0
+		PXOR T0, ACC0
+		PXOR ACC1, ACC0
+
+		LEAQ 16(aut), aut
+
+	JMP dataSinglesLoop
+
+dataEnd:
+
+	TESTQ autLen, autLen
+	JEQ dataBail
+
+	PXOR B0, B0
+	LEAQ -1(aut)(autLen*1), aut
+
+dataLoadLoop:
+
+		PSLLDQ $1, B0
+		PINSRB $0, (aut), B0
+
+		LEAQ -1(aut), aut
+		DECQ autLen
+		JNE dataLoadLoop
+
+	JMP dataMul
+
+dataBail:
+	MOVOU ACC0, (tPtr)
+	RET
+#undef pTbl
+#undef aut
+#undef tPtr
+#undef autLen
+
+// func gcmAesEnc(productTable *[256]byte, dst, src []byte, ctr, T *[16]byte, ks []uint32)
+TEXT ·gcmAesEnc(SB),0,$256-144
+#define pTbl DI
+#define ctx DX
+#define ctrPtr CX
+#define ptx SI
+#define ks AX
+#define tPtr R8
+#define ptxLen R9
+#define aluCTR R10
+#define aluTMP R11
+#define aluK R12
+#define NR R13
+
+#define increment(i) ADDL $1, aluCTR; MOVL aluCTR, aluTMP; XORL aluK, aluTMP; BSWAPL aluTMP; MOVL aluTMP, (3*4 + 8*16 + i*16)(SP)
+#define aesRnd(k) AESENC k, B0; AESENC k, B1; AESENC k, B2; AESENC k, B3; AESENC k, B4; AESENC k, B5; AESENC k, B6; AESENC k, B7
+#define aesRound(i) MOVOU (16*i)(ks), T0;AESENC T0, B0; AESENC T0, B1; AESENC T0, B2; AESENC T0, B3; AESENC T0, B4; AESENC T0, B5; AESENC T0, B6; AESENC T0, B7
+#define aesRndLast(k) AESENCLAST k, B0; AESENCLAST k, B1; AESENCLAST k, B2; AESENCLAST k, B3; AESENCLAST k, B4; AESENCLAST k, B5; AESENCLAST k, B6; AESENCLAST k, B7
+#define reduceRound(a) 	MOVOU POLY, T0;	PCLMULQDQ $0x01, a, T0; PSHUFD $78, a, a; PXOR T0, a
+#define combinedRound(i) \
+	MOVOU (16*i)(ks), T0;\
+	AESENC T0, B0;\
+	AESENC T0, B1;\
+	AESENC T0, B2;\
+	AESENC T0, B3;\
+	 MOVOU (16*(i*2))(pTbl), T1;\
+	 MOVOU T1, T2;\
+	AESENC T0, B4;\
+	AESENC T0, B5;\
+	AESENC T0, B6;\
+	AESENC T0, B7;\
+	 MOVOU (16*i)(SP), T0;\
+	 PCLMULQDQ $0x00, T0, T1;\
+	 PXOR T1, ACC0;\
+	 PSHUFD $78, T0, T1;\
+	 PCLMULQDQ $0x11, T0, T2;\
+	 PXOR T1, T0;\
+	 PXOR T2, ACC1;\
+	 MOVOU (16*(i*2+1))(pTbl), T2;\
+	 PCLMULQDQ $0x00, T2, T0;\
+	 PXOR T0, ACCM
+#define mulRound(i) \
+	MOVOU (16*i)(SP), T0;\
+	MOVOU (16*(i*2))(pTbl), T1;\
+	MOVOU T1, T2;\
+	PCLMULQDQ $0x00, T0, T1;\
+	PXOR T1, ACC0;\
+	PCLMULQDQ $0x11, T0, T2;\
+	PXOR T2, ACC1;\
+	PSHUFD $78, T0, T1;\
+	PXOR T1, T0;\
+	MOVOU (16*(i*2+1))(pTbl), T1;\
+	PCLMULQDQ $0x00, T0, T1;\
+	PXOR T1, ACCM
+
+	MOVQ productTable+0(FP), pTbl
+	MOVQ dst+8(FP), ctx
+	MOVQ src+32(FP), ptx
+	MOVQ src+40(FP), ptxLen
+	MOVQ ctr+56(FP), ctrPtr
+	MOVQ T+64(FP), tPtr
+	MOVQ KS+72(FP), ks
+	MOVQ nr+80(FP), NR
+
+	SHRQ $2, NR
+	DECQ NR
+
+	MOVOU bswapMask<>(SB), BSWAP
+	MOVOU gcmPoly<>(SB), POLY
+
+	MOVOU (tPtr), ACC0
+	PXOR ACC1, ACC1
+	PXOR ACCM, ACCM
+	MOVOU (ctrPtr), B0
+	MOVL (3*4)(ctrPtr), aluCTR
+	MOVOU (ks), T0
+	MOVL (3*4)(ks), aluK
+	BSWAPL aluCTR
+	BSWAPL aluK
+
+	PXOR B0, T0
+	MOVOU T0, (8*16 + 0*16)(SP)
+	increment(0)
+
+	CMPQ ptxLen, $128
+	JB gcmAesEncSingles
+	SUBQ $128, ptxLen
+
+	// We have at least 8 blocks to encrypt, prepare the rest of the counters
+	MOVOU T0, (8*16 + 1*16)(SP)
+	increment(1)
+	MOVOU T0, (8*16 + 2*16)(SP)
+	increment(2)
+	MOVOU T0, (8*16 + 3*16)(SP)
+	increment(3)
+	MOVOU T0, (8*16 + 4*16)(SP)
+	increment(4)
+	MOVOU T0, (8*16 + 5*16)(SP)
+	increment(5)
+	MOVOU T0, (8*16 + 6*16)(SP)
+	increment(6)
+	MOVOU T0, (8*16 + 7*16)(SP)
+	increment(7)
+
+	MOVOU (8*16 + 0*16)(SP), B0
+	MOVOU (8*16 + 1*16)(SP), B1
+	MOVOU (8*16 + 2*16)(SP), B2
+	MOVOU (8*16 + 3*16)(SP), B3
+	MOVOU (8*16 + 4*16)(SP), B4
+	MOVOU (8*16 + 5*16)(SP), B5
+	MOVOU (8*16 + 6*16)(SP), B6
+	MOVOU (8*16 + 7*16)(SP), B7
+
+	aesRound(1)
+	increment(0)
+	aesRound(2)
+	increment(1)
+	aesRound(3)
+	increment(2)
+	aesRound(4)
+	increment(3)
+	aesRound(5)
+	increment(4)
+	aesRound(6)
+	increment(5)
+	aesRound(7)
+	increment(6)
+	aesRound(8)
+	increment(7)
+	aesRound(9)
+	MOVOU (16*10)(ks), T0
+	CMPQ NR, $12
+	JB encLast1
+	aesRnd(T0)
+	aesRound(11)
+	MOVOU (16*12)(ks), T0
+	JE encLast1
+	aesRnd(T0)
+	aesRound(13)
+	MOVOU (16*14)(ks), T0
+encLast1:
+	aesRndLast(T0)
+
+	MOVOU (16*0)(ptx), T0
+	PXOR T0, B0
+	MOVOU (16*1)(ptx), T0
+	PXOR T0, B1
+	MOVOU (16*2)(ptx), T0
+	PXOR T0, B2
+	MOVOU (16*3)(ptx), T0
+	PXOR T0, B3
+	MOVOU (16*4)(ptx), T0
+	PXOR T0, B4
+	MOVOU (16*5)(ptx), T0
+	PXOR T0, B5
+	MOVOU (16*6)(ptx), T0
+	PXOR T0, B6
+	MOVOU (16*7)(ptx), T0
+	PXOR T0, B7
+
+	MOVOU B0, (16*0)(ctx)
+	PSHUFB BSWAP, B0
+	PXOR ACC0, B0
+	MOVOU B1, (16*1)(ctx)
+	PSHUFB BSWAP, B1
+	MOVOU B2, (16*2)(ctx)
+	PSHUFB BSWAP, B2
+	MOVOU B3, (16*3)(ctx)
+	PSHUFB BSWAP, B3
+	MOVOU B4, (16*4)(ctx)
+	PSHUFB BSWAP, B4
+	MOVOU B5, (16*5)(ctx)
+	PSHUFB BSWAP, B5
+	MOVOU B6, (16*6)(ctx)
+	PSHUFB BSWAP, B6
+	MOVOU B7, (16*7)(ctx)
+	PSHUFB BSWAP, B7
+
+	MOVOU B0, (16*0)(SP)
+	MOVOU B1, (16*1)(SP)
+	MOVOU B2, (16*2)(SP)
+	MOVOU B3, (16*3)(SP)
+	MOVOU B4, (16*4)(SP)
+	MOVOU B5, (16*5)(SP)
+	MOVOU B6, (16*6)(SP)
+	MOVOU B7, (16*7)(SP)
+
+	LEAQ 128(ptx), ptx
+	LEAQ 128(ctx), ctx
+
+gcmAesEncOctetsLoop:
+
+		CMPQ ptxLen, $128
+		JB gcmAesEncOctetsEnd
+		SUBQ $128, ptxLen
+
+		MOVOU (8*16 + 0*16)(SP), B0
+		MOVOU (8*16 + 1*16)(SP), B1
+		MOVOU (8*16 + 2*16)(SP), B2
+		MOVOU (8*16 + 3*16)(SP), B3
+		MOVOU (8*16 + 4*16)(SP), B4
+		MOVOU (8*16 + 5*16)(SP), B5
+		MOVOU (8*16 + 6*16)(SP), B6
+		MOVOU (8*16 + 7*16)(SP), B7
+
+		MOVOU (16*0)(SP), T0
+		PSHUFD $78, T0, T1
+		PXOR T0, T1
+
+		MOVOU (16*0)(pTbl), ACC0
+		MOVOU (16*1)(pTbl), ACCM
+		MOVOU ACC0, ACC1
+
+		PCLMULQDQ $0x00, T1, ACCM
+		PCLMULQDQ $0x00, T0, ACC0
+		PCLMULQDQ $0x11, T0, ACC1
+
+		combinedRound(1)
+		increment(0)
+		combinedRound(2)
+		increment(1)
+		combinedRound(3)
+		increment(2)
+		combinedRound(4)
+		increment(3)
+		combinedRound(5)
+		increment(4)
+		combinedRound(6)
+		increment(5)
+		combinedRound(7)
+		increment(6)
+
+		aesRound(8)
+		increment(7)
+
+		PXOR ACC0, ACCM
+		PXOR ACC1, ACCM
+		MOVOU ACCM, T0
+		PSRLDQ $8, ACCM
+		PSLLDQ $8, T0
+		PXOR ACCM, ACC1
+		PXOR T0, ACC0
+
+		reduceRound(ACC0)
+		aesRound(9)
+
+		reduceRound(ACC0)
+		PXOR ACC1, ACC0
+
+		MOVOU (16*10)(ks), T0
+		CMPQ NR, $12
+		JB encLast2
+		aesRnd(T0)
+		aesRound(11)
+		MOVOU (16*12)(ks), T0
+		JE encLast2
+		aesRnd(T0)
+		aesRound(13)
+		MOVOU (16*14)(ks), T0
+encLast2:
+		aesRndLast(T0)
+
+		MOVOU (16*0)(ptx), T0
+		PXOR T0, B0
+		MOVOU (16*1)(ptx), T0
+		PXOR T0, B1
+		MOVOU (16*2)(ptx), T0
+		PXOR T0, B2
+		MOVOU (16*3)(ptx), T0
+		PXOR T0, B3
+		MOVOU (16*4)(ptx), T0
+		PXOR T0, B4
+		MOVOU (16*5)(ptx), T0
+		PXOR T0, B5
+		MOVOU (16*6)(ptx), T0
+		PXOR T0, B6
+		MOVOU (16*7)(ptx), T0
+		PXOR T0, B7
+
+		MOVOU B0, (16*0)(ctx)
+		PSHUFB BSWAP, B0
+		PXOR ACC0, B0
+		MOVOU B1, (16*1)(ctx)
+		PSHUFB BSWAP, B1
+		MOVOU B2, (16*2)(ctx)
+		PSHUFB BSWAP, B2
+		MOVOU B3, (16*3)(ctx)
+		PSHUFB BSWAP, B3
+		MOVOU B4, (16*4)(ctx)
+		PSHUFB BSWAP, B4
+		MOVOU B5, (16*5)(ctx)
+		PSHUFB BSWAP, B5
+		MOVOU B6, (16*6)(ctx)
+		PSHUFB BSWAP, B6
+		MOVOU B7, (16*7)(ctx)
+		PSHUFB BSWAP, B7
+
+		MOVOU B0, (16*0)(SP)
+		MOVOU B1, (16*1)(SP)
+		MOVOU B2, (16*2)(SP)
+		MOVOU B3, (16*3)(SP)
+		MOVOU B4, (16*4)(SP)
+		MOVOU B5, (16*5)(SP)
+		MOVOU B6, (16*6)(SP)
+		MOVOU B7, (16*7)(SP)
+
+		LEAQ 128(ptx), ptx
+		LEAQ 128(ctx), ctx
+
+		JMP gcmAesEncOctetsLoop
+
+gcmAesEncOctetsEnd:
+
+	MOVOU (16*0)(SP), T0
+	MOVOU (16*0)(pTbl), ACC0
+	MOVOU (16*1)(pTbl), ACCM
+	MOVOU ACC0, ACC1
+	PSHUFD $78, T0, T1
+	PXOR T0, T1
+	PCLMULQDQ $0x00, T0, ACC0
+	PCLMULQDQ $0x11, T0, ACC1
+	PCLMULQDQ $0x00, T1, ACCM
+
+	mulRound(1)
+	mulRound(2)
+	mulRound(3)
+	mulRound(4)
+	mulRound(5)
+	mulRound(6)
+	mulRound(7)
+
+	PXOR ACC0, ACCM
+	PXOR ACC1, ACCM
+	MOVOU ACCM, T0
+	PSRLDQ $8, ACCM
+	PSLLDQ $8, T0
+	PXOR ACCM, ACC1
+	PXOR T0, ACC0
+
+	reduceRound(ACC0)
+	reduceRound(ACC0)
+	PXOR ACC1, ACC0
+
+	TESTQ ptxLen, ptxLen
+	JE gcmAesEncDone
+
+	SUBQ $7, aluCTR
+
+gcmAesEncSingles:
+
+	MOVOU (16*1)(ks), B1
+	MOVOU (16*2)(ks), B2
+	MOVOU (16*3)(ks), B3
+	MOVOU (16*4)(ks), B4
+	MOVOU (16*5)(ks), B5
+	MOVOU (16*6)(ks), B6
+	MOVOU (16*7)(ks), B7
+
+	MOVOU (16*14)(pTbl), T2
+
+gcmAesEncSinglesLoop:
+
+		CMPQ ptxLen, $16
+		JB gcmAesEncTail
+		SUBQ $16, ptxLen
+
+		MOVOU (8*16 + 0*16)(SP), B0
+		increment(0)
+
+		AESENC B1, B0
+		AESENC B2, B0
+		AESENC B3, B0
+		AESENC B4, B0
+		AESENC B5, B0
+		AESENC B6, B0
+		AESENC B7, B0
+		MOVOU (16*8)(ks), T0
+		AESENC T0, B0
+		MOVOU (16*9)(ks), T0
+		AESENC T0, B0
+		MOVOU (16*10)(ks), T0
+		CMPQ NR, $12
+		JB encLast3
+		AESENC T0, B0
+		MOVOU (16*11)(ks), T0
+		AESENC T0, B0
+		MOVOU (16*12)(ks), T0
+		JE encLast3
+		AESENC T0, B0
+		MOVOU (16*13)(ks), T0
+		AESENC T0, B0
+		MOVOU (16*14)(ks), T0
+encLast3:
+		AESENCLAST T0, B0
+
+		MOVOU (ptx), T0
+		PXOR T0, B0
+		MOVOU B0, (ctx)
+
+		PSHUFB BSWAP, B0
+		PXOR ACC0, B0
+
+		MOVOU T2, ACC0
+		MOVOU T2, ACC1
+		MOVOU (16*15)(pTbl), ACCM
+
+		PSHUFD $78, B0, T0
+		PXOR B0, T0
+		PCLMULQDQ $0x00, B0, ACC0
+		PCLMULQDQ $0x11, B0, ACC1
+		PCLMULQDQ $0x00, T0, ACCM
+
+		PXOR ACC0, ACCM
+		PXOR ACC1, ACCM
+		MOVOU ACCM, T0
+		PSRLDQ $8, ACCM
+		PSLLDQ $8, T0
+		PXOR ACCM, ACC1
+		PXOR T0, ACC0
+
+		reduceRound(ACC0)
+		reduceRound(ACC0)
+		PXOR ACC1, ACC0
+
+		LEAQ (16*1)(ptx), ptx
+		LEAQ (16*1)(ctx), ctx
+
+	JMP gcmAesEncSinglesLoop
+
+gcmAesEncTail:
+	TESTQ ptxLen, ptxLen
+	JE gcmAesEncDone
+
+	MOVOU (8*16 + 0*16)(SP), B0
+	AESENC B1, B0
+	AESENC B2, B0
+	AESENC B3, B0
+	AESENC B4, B0
+	AESENC B5, B0
+	AESENC B6, B0
+	AESENC B7, B0
+	MOVOU (16*8)(ks), T0
+	AESENC T0, B0
+	MOVOU (16*9)(ks), T0
+	AESENC T0, B0
+	MOVOU (16*10)(ks), T0
+	CMPQ NR, $12
+	JB encLast4
+	AESENC T0, B0
+	MOVOU (16*11)(ks), T0
+	AESENC T0, B0
+	MOVOU (16*12)(ks), T0
+	JE encLast4
+	AESENC T0, B0
+	MOVOU (16*13)(ks), T0
+	AESENC T0, B0
+	MOVOU (16*14)(ks), T0
+encLast4:
+	AESENCLAST T0, B0
+	MOVOU B0, T0
+
+	LEAQ -1(ptx)(ptxLen*1), ptx
+
+	MOVQ ptxLen, aluTMP
+	SHLQ $4, aluTMP
+
+	LEAQ andMask<>(SB), aluCTR
+	MOVOU -16(aluCTR)(aluTMP*1), T1
+
+	PXOR B0, B0
+ptxLoadLoop:
+		PSLLDQ $1, B0
+		PINSRB $0, (ptx), B0
+		LEAQ -1(ptx), ptx
+		DECQ ptxLen
+	JNE ptxLoadLoop
+
+	PXOR T0, B0
+	PAND T1, B0
+	MOVOU B0, (ctx)	// I assume there is always space, due to TAG in the end of the CT
+
+	PSHUFB BSWAP, B0
+	PXOR ACC0, B0
+
+	MOVOU T2, ACC0
+	MOVOU T2, ACC1
+	MOVOU (16*15)(pTbl), ACCM
+
+	PSHUFD $78, B0, T0
+	PXOR B0, T0
+	PCLMULQDQ $0x00, B0, ACC0
+	PCLMULQDQ $0x11, B0, ACC1
+	PCLMULQDQ $0x00, T0, ACCM
+
+	PXOR ACC0, ACCM
+	PXOR ACC1, ACCM
+	MOVOU ACCM, T0
+	PSRLDQ $8, ACCM
+	PSLLDQ $8, T0
+	PXOR ACCM, ACC1
+	PXOR T0, ACC0
+
+	reduceRound(ACC0)
+	reduceRound(ACC0)
+	PXOR ACC1, ACC0
+
+gcmAesEncDone:
+	MOVOU ACC0, (tPtr)
+	RET
+#undef increment
+
+// func gcmAesDec(productTable *[256]byte, dst, src []byte, ctr, T *[16]byte, ks []uint32)
+TEXT ·gcmAesDec(SB),0,$128-144
+#define increment(i) ADDL $1, aluCTR; MOVL aluCTR, aluTMP; XORL aluK, aluTMP; BSWAPL aluTMP; MOVL aluTMP, (3*4 + i*16)(SP)
+#define combinedDecRound(i) \
+	MOVOU (16*i)(ks), T0;\
+	AESENC T0, B0;\
+	AESENC T0, B1;\
+	AESENC T0, B2;\
+	AESENC T0, B3;\
+	MOVOU (16*(i*2))(pTbl), T1;\
+	MOVOU T1, T2;\
+	AESENC T0, B4;\
+	AESENC T0, B5;\
+	AESENC T0, B6;\
+	AESENC T0, B7;\
+	MOVOU (16*i)(ctx), T0;\
+	PSHUFB BSWAP, T0;\
+	PCLMULQDQ $0x00, T0, T1;\
+	PXOR T1, ACC0;\
+	PSHUFD $78, T0, T1;\
+	PCLMULQDQ $0x11, T0, T2;\
+	PXOR T1, T0;\
+	PXOR T2, ACC1;\
+	MOVOU (16*(i*2+1))(pTbl), T2;\
+	PCLMULQDQ $0x00, T2, T0;\
+	PXOR T0, ACCM
+
+	MOVQ productTable+0(FP), pTbl
+	MOVQ dst+8(FP), ptx
+	MOVQ src+32(FP), ctx
+	MOVQ src+40(FP), ptxLen
+	MOVQ ctr+56(FP), ctrPtr
+	MOVQ T+64(FP), tPtr
+	MOVQ KS+72(FP), ks
+	MOVQ nr+80(FP), NR
+
+	SHRQ $2, NR
+	DECQ NR
+
+	MOVOU bswapMask<>(SB), BSWAP
+	MOVOU gcmPoly<>(SB), POLY
+
+	MOVOU (tPtr), ACC0
+	PXOR ACC1, ACC1
+	PXOR ACCM, ACCM
+	MOVOU (ctrPtr), B0
+	MOVL (3*4)(ctrPtr), aluCTR
+	MOVOU (ks), T0
+	MOVL (3*4)(ks), aluK
+	BSWAPL aluCTR
+	BSWAPL aluK
+
+	PXOR B0, T0
+	MOVOU T0, (0*16)(SP)
+	increment(0)
+
+	CMPQ ptxLen, $128
+	JB gcmAesDecSingles
+
+	MOVOU T0, (1*16)(SP)
+	increment(1)
+	MOVOU T0, (2*16)(SP)
+	increment(2)
+	MOVOU T0, (3*16)(SP)
+	increment(3)
+	MOVOU T0, (4*16)(SP)
+	increment(4)
+	MOVOU T0, (5*16)(SP)
+	increment(5)
+	MOVOU T0, (6*16)(SP)
+	increment(6)
+	MOVOU T0, (7*16)(SP)
+	increment(7)
+
+gcmAesDecOctetsLoop:
+
+		CMPQ ptxLen, $128
+		JB gcmAesDecEndOctets
+		SUBQ $128, ptxLen
+
+		MOVOU (0*16)(SP), B0
+		MOVOU (1*16)(SP), B1
+		MOVOU (2*16)(SP), B2
+		MOVOU (3*16)(SP), B3
+		MOVOU (4*16)(SP), B4
+		MOVOU (5*16)(SP), B5
+		MOVOU (6*16)(SP), B6
+		MOVOU (7*16)(SP), B7
+
+		MOVOU (16*0)(ctx), T0
+		PSHUFB BSWAP, T0
+		PXOR ACC0, T0
+		PSHUFD $78, T0, T1
+		PXOR T0, T1
+
+		MOVOU (16*0)(pTbl), ACC0
+		MOVOU (16*1)(pTbl), ACCM
+		MOVOU ACC0, ACC1
+
+		PCLMULQDQ $0x00, T1, ACCM
+		PCLMULQDQ $0x00, T0, ACC0
+		PCLMULQDQ $0x11, T0, ACC1
+
+		combinedDecRound(1)
+		increment(0)
+		combinedDecRound(2)
+		increment(1)
+		combinedDecRound(3)
+		increment(2)
+		combinedDecRound(4)
+		increment(3)
+		combinedDecRound(5)
+		increment(4)
+		combinedDecRound(6)
+		increment(5)
+		combinedDecRound(7)
+		increment(6)
+
+		aesRound(8)
+		increment(7)
+
+		PXOR ACC0, ACCM
+		PXOR ACC1, ACCM
+		MOVOU ACCM, T0
+		PSRLDQ $8, ACCM
+		PSLLDQ $8, T0
+		PXOR ACCM, ACC1
+		PXOR T0, ACC0
+
+		reduceRound(ACC0)
+		aesRound(9)
+
+		reduceRound(ACC0)
+		PXOR ACC1, ACC0
+
+		MOVOU (16*10)(ks), T0
+		CMPQ NR, $12
+		JB decLast1
+		aesRnd(T0)
+		aesRound(11)
+		MOVOU (16*12)(ks), T0
+		JE decLast1
+		aesRnd(T0)
+		aesRound(13)
+		MOVOU (16*14)(ks), T0
+decLast1:
+		aesRndLast(T0)
+
+		MOVOU (16*0)(ctx), T0
+		PXOR T0, B0
+		MOVOU (16*1)(ctx), T0
+		PXOR T0, B1
+		MOVOU (16*2)(ctx), T0
+		PXOR T0, B2
+		MOVOU (16*3)(ctx), T0
+		PXOR T0, B3
+		MOVOU (16*4)(ctx), T0
+		PXOR T0, B4
+		MOVOU (16*5)(ctx), T0
+		PXOR T0, B5
+		MOVOU (16*6)(ctx), T0
+		PXOR T0, B6
+		MOVOU (16*7)(ctx), T0
+		PXOR T0, B7
+
+		MOVOU B0, (16*0)(ptx)
+		MOVOU B1, (16*1)(ptx)
+		MOVOU B2, (16*2)(ptx)
+		MOVOU B3, (16*3)(ptx)
+		MOVOU B4, (16*4)(ptx)
+		MOVOU B5, (16*5)(ptx)
+		MOVOU B6, (16*6)(ptx)
+		MOVOU B7, (16*7)(ptx)
+
+		LEAQ 128(ptx), ptx
+		LEAQ 128(ctx), ctx
+
+		JMP gcmAesDecOctetsLoop
+
+gcmAesDecEndOctets:
+
+	SUBQ $7, aluCTR
+
+gcmAesDecSingles:
+
+	MOVOU (16*1)(ks), B1
+	MOVOU (16*2)(ks), B2
+	MOVOU (16*3)(ks), B3
+	MOVOU (16*4)(ks), B4
+	MOVOU (16*5)(ks), B5
+	MOVOU (16*6)(ks), B6
+	MOVOU (16*7)(ks), B7
+
+	MOVOU (16*14)(pTbl), T2
+
+gcmAesDecSinglesLoop:
+
+		CMPQ ptxLen, $16
+		JB gcmAesDecTail
+		SUBQ $16, ptxLen
+
+		MOVOU (ctx), B0
+		MOVOU B0, T1
+		PSHUFB BSWAP, B0
+		PXOR ACC0, B0
+
+		MOVOU T2, ACC0
+		MOVOU T2, ACC1
+		MOVOU (16*15)(pTbl), ACCM
+
+		PCLMULQDQ $0x00, B0, ACC0
+		PCLMULQDQ $0x11, B0, ACC1
+		PSHUFD $78, B0, T0
+		PXOR B0, T0
+		PCLMULQDQ $0x00, T0, ACCM
+
+		PXOR ACC0, ACCM
+		PXOR ACC1, ACCM
+		MOVOU ACCM, T0
+		PSRLDQ $8, ACCM
+		PSLLDQ $8, T0
+		PXOR ACCM, ACC1
+		PXOR T0, ACC0
+
+		reduceRound(ACC0)
+		reduceRound(ACC0)
+		PXOR ACC1, ACC0
+
+		MOVOU (0*16)(SP), B0
+		increment(0)
+		AESENC B1, B0
+		AESENC B2, B0
+		AESENC B3, B0
+		AESENC B4, B0
+		AESENC B5, B0
+		AESENC B6, B0
+		AESENC B7, B0
+		MOVOU (16*8)(ks), T0
+		AESENC T0, B0
+		MOVOU (16*9)(ks), T0
+		AESENC T0, B0
+		MOVOU (16*10)(ks), T0
+		CMPQ NR, $12
+		JB decLast2
+		AESENC T0, B0
+		MOVOU (16*11)(ks), T0
+		AESENC T0, B0
+		MOVOU (16*12)(ks), T0
+		JE decLast2
+		AESENC T0, B0
+		MOVOU (16*13)(ks), T0
+		AESENC T0, B0
+		MOVOU (16*14)(ks), T0
+decLast2:
+		AESENCLAST T0, B0
+
+		PXOR T1, B0
+		MOVOU B0, (ptx)
+
+		LEAQ (16*1)(ptx), ptx
+		LEAQ (16*1)(ctx), ctx
+
+	JMP gcmAesDecSinglesLoop
+
+gcmAesDecTail:
+
+	TESTQ ptxLen, ptxLen
+	JE gcmAesDecDone
+
+	MOVQ ptxLen, aluTMP
+	SHLQ $4, aluTMP
+	LEAQ andMask<>(SB), aluCTR
+	MOVOU -16(aluCTR)(aluTMP*1), T1
+
+	MOVOU (ctx), B0	// I assume there is TAG attached to the ctx, and there is no read overflow
+	PAND T1, B0
+
+	MOVOU B0, T1
+	PSHUFB BSWAP, B0
+	PXOR ACC0, B0
+
+	MOVOU (16*14)(pTbl), ACC0
+	MOVOU (16*15)(pTbl), ACCM
+	MOVOU ACC0, ACC1
+
+	PCLMULQDQ $0x00, B0, ACC0
+	PCLMULQDQ $0x11, B0, ACC1
+	PSHUFD $78, B0, T0
+	PXOR B0, T0
+	PCLMULQDQ $0x00, T0, ACCM
+
+	PXOR ACC0, ACCM
+	PXOR ACC1, ACCM
+	MOVOU ACCM, T0
+	PSRLDQ $8, ACCM
+	PSLLDQ $8, T0
+	PXOR ACCM, ACC1
+	PXOR T0, ACC0
+
+	reduceRound(ACC0)
+	reduceRound(ACC0)
+	PXOR ACC1, ACC0
+
+	MOVOU (0*16)(SP), B0
+	increment(0)
+	AESENC B1, B0
+	AESENC B2, B0
+	AESENC B3, B0
+	AESENC B4, B0
+	AESENC B5, B0
+	AESENC B6, B0
+	AESENC B7, B0
+	MOVOU (16*8)(ks), T0
+	AESENC T0, B0
+	MOVOU (16*9)(ks), T0
+	AESENC T0, B0
+	MOVOU (16*10)(ks), T0
+	CMPQ NR, $12
+	JB decLast3
+	AESENC T0, B0
+	MOVOU (16*11)(ks), T0
+	AESENC T0, B0
+	MOVOU (16*12)(ks), T0
+	JE decLast3
+	AESENC T0, B0
+	MOVOU (16*13)(ks), T0
+	AESENC T0, B0
+	MOVOU (16*14)(ks), T0
+decLast3:
+	AESENCLAST T0, B0
+	PXOR T1, B0
+
+ptxStoreLoop:
+		PEXTRB $0, B0, (ptx)
+		PSRLDQ $1, B0
+		LEAQ 1(ptx), ptx
+		DECQ ptxLen
+
+	JNE ptxStoreLoop
+
+gcmAesDecDone:
+
+	MOVOU ACC0, (tPtr)
+	RET
diff --git a/src/crypto/cipher/benchmark_test.go b/src/crypto/cipher/benchmark_test.go
index 027b248..93c40d0 100644
--- a/src/crypto/cipher/benchmark_test.go
+++ b/src/crypto/cipher/benchmark_test.go
@@ -10,42 +10,58 @@ import (
 	"testing"
 )
 
-func BenchmarkAESGCMSeal1K(b *testing.B) {
-	buf := make([]byte, 1024)
+func benchmarkAESGCMSeal(b *testing.B, buf []byte) {
 	b.SetBytes(int64(len(buf)))
 
 	var key [16]byte
 	var nonce [12]byte
+	var ad [13]byte
 	aes, _ := aes.NewCipher(key[:])
 	aesgcm, _ := cipher.NewGCM(aes)
 	var out []byte
 
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		out = aesgcm.Seal(out[:0], nonce[:], buf, nonce[:])
+		out = aesgcm.Seal(out[:0], nonce[:], buf, ad[:])
 	}
 }
 
-func BenchmarkAESGCMOpen1K(b *testing.B) {
-	buf := make([]byte, 1024)
+func benchmarkAESGCMOpen(b *testing.B, buf []byte) {
 	b.SetBytes(int64(len(buf)))
 
 	var key [16]byte
 	var nonce [12]byte
+	var ad [13]byte
 	aes, _ := aes.NewCipher(key[:])
 	aesgcm, _ := cipher.NewGCM(aes)
 	var out []byte
-	out = aesgcm.Seal(out[:0], nonce[:], buf, nonce[:])
+	out = aesgcm.Seal(out[:0], nonce[:], buf, ad[:])
 
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		_, err := aesgcm.Open(buf[:0], nonce[:], out, nonce[:])
+		_, err := aesgcm.Open(buf[:0], nonce[:], out, ad[:])
 		if err != nil {
 			b.Errorf("Open: %v", err)
 		}
 	}
 }
 
+func BenchmarkAESGCMSeal1K(b *testing.B) {
+	benchmarkAESGCMSeal(b, make([]byte, 1024))
+}
+
+func BenchmarkAESGCMOpen1K(b *testing.B) {
+	benchmarkAESGCMOpen(b, make([]byte, 1024))
+}
+
+func BenchmarkAESGCMSeal8K(b *testing.B) {
+	benchmarkAESGCMSeal(b, make([]byte, 8*1024))
+}
+
+func BenchmarkAESGCMOpen8K(b *testing.B) {
+	benchmarkAESGCMOpen(b, make([]byte, 8*1024))
+}
+
 // If we test exactly 1K blocks, we would generate exact multiples of
 // the cipher's block size, and the cipher stream fragments would
 // always be wordsize aligned, whereas non-aligned is a more typical
diff --git a/src/crypto/cipher/ctr.go b/src/crypto/cipher/ctr.go
index 70ac40f..16baa6d 100644
--- a/src/crypto/cipher/ctr.go
+++ b/src/crypto/cipher/ctr.go
@@ -41,13 +41,10 @@ func NewCTR(block Block, iv []byte) Stream {
 
 func (x *ctr) refill() {
 	remain := len(x.out) - x.outUsed
-	if remain > x.outUsed {
-		return
-	}
 	copy(x.out, x.out[x.outUsed:])
 	x.out = x.out[:cap(x.out)]
 	bs := x.b.BlockSize()
-	for remain < len(x.out)-bs {
+	for remain <= len(x.out)-bs {
 		x.b.Encrypt(x.out[remain:], x.ctr)
 		remain += bs
 
diff --git a/src/crypto/cipher/ctr_test.go b/src/crypto/cipher/ctr_test.go
new file mode 100644
index 0000000..e5cce57
--- /dev/null
+++ b/src/crypto/cipher/ctr_test.go
@@ -0,0 +1,55 @@
+// Copyright 2015 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 cipher_test
+
+import (
+	"bytes"
+	"crypto/cipher"
+	"testing"
+)
+
+type noopBlock int
+
+func (b noopBlock) BlockSize() int        { return int(b) }
+func (noopBlock) Encrypt(dst, src []byte) { copy(dst, src) }
+func (noopBlock) Decrypt(dst, src []byte) { copy(dst, src) }
+
+func inc(b []byte) {
+	for i := len(b) - 1; i >= 0; i++ {
+		b[i]++
+		if b[i] != 0 {
+			break
+		}
+	}
+}
+
+func xor(a, b []byte) {
+	for i := range a {
+		a[i] ^= b[i]
+	}
+}
+
+func TestCTR(t *testing.T) {
+	for size := 64; size <= 1024; size *= 2 {
+		iv := make([]byte, size)
+		ctr := cipher.NewCTR(noopBlock(size), iv)
+		src := make([]byte, 1024)
+		for i := range src {
+			src[i] = 0xff
+		}
+		want := make([]byte, 1024)
+		copy(want, src)
+		counter := make([]byte, size)
+		for i := 1; i < len(want)/size; i++ {
+			inc(counter)
+			xor(want[i*size:(i+1)*size], counter)
+		}
+		dst := make([]byte, 1024)
+		ctr.XORKeyStream(dst, src)
+		if !bytes.Equal(dst, want) {
+			t.Errorf("for size %d\nhave %x\nwant %x", size, dst, want)
+		}
+	}
+}
diff --git a/src/crypto/cipher/example_test.go b/src/crypto/cipher/example_test.go
index 1cfa982..f6cc386 100644
--- a/src/crypto/cipher/example_test.go
+++ b/src/crypto/cipher/example_test.go
@@ -14,6 +14,58 @@ import (
 	"os"
 )
 
+func ExampleNewGCMEncrypter() {
+	// The key argument should be the AES key, either 16 or 32 bytes
+	// to select AES-128 or AES-256.
+	key := []byte("AES256Key-32Characters1234567890")
+	plaintext := []byte("exampleplaintext")
+
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		panic(err.Error())
+	}
+
+	// Never use more than 2^32 random nonces with a given key because of the risk of a repeat.
+	nonce := make([]byte, 12)
+	if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
+		panic(err.Error())
+	}
+
+	aesgcm, err := cipher.NewGCM(block)
+	if err != nil {
+		panic(err.Error())
+	}
+
+	ciphertext := aesgcm.Seal(nil, nonce, plaintext, nil)
+	fmt.Printf("%x\n", ciphertext)
+}
+
+func ExampleNewGCMDecrypter() {
+	// The key argument should be the AES key, either 16 or 32 bytes
+	// to select AES-128 or AES-256.
+	key := []byte("AES256Key-32Characters1234567890")
+	ciphertext, _ := hex.DecodeString("f90fbef747e7212ad7410d0eee2d965de7e890471695cddd2a5bc0ef5da1d04ad8147b62141ad6e4914aee8c512f64fba9037603d41de0d50b718bd665f019cdcd")
+
+	nonce, _ := hex.DecodeString("bb8ef84243d2ee95a41c6c57")
+
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		panic(err.Error())
+	}
+
+	aesgcm, err := cipher.NewGCM(block)
+	if err != nil {
+		panic(err.Error())
+	}
+
+	plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil)
+	if err != nil {
+		panic(err.Error())
+	}
+
+	fmt.Printf("%s\n", string(plaintext))
+}
+
 func ExampleNewCBCDecrypter() {
 	key := []byte("example key 1234")
 	ciphertext, _ := hex.DecodeString("f363f3ccdcb12bb883abf484ba77d9cd7d32b5baecb3d4b1b3e0e4beffdb3ded")
diff --git a/src/crypto/cipher/gcm.go b/src/crypto/cipher/gcm.go
index bbdf9f5..3868d71 100644
--- a/src/crypto/cipher/gcm.go
+++ b/src/crypto/cipher/gcm.go
@@ -10,14 +10,15 @@ import (
 )
 
 // AEAD is a cipher mode providing authenticated encryption with associated
-// data.
+// data. For a description of the methodology, see
+//	https://en.wikipedia.org/wiki/Authenticated_encryption
 type AEAD interface {
 	// NonceSize returns the size of the nonce that must be passed to Seal
 	// and Open.
 	NonceSize() int
 
 	// Overhead returns the maximum difference between the lengths of a
-	// plaintext and ciphertext.
+	// plaintext and its ciphertext.
 	Overhead() int
 
 	// Seal encrypts and authenticates plaintext, authenticates the
@@ -25,8 +26,9 @@ type AEAD interface {
 	// slice. The nonce must be NonceSize() bytes long and unique for all
 	// time, for a given key.
 	//
-	// The plaintext and dst may alias exactly or not at all.
-	Seal(dst, nonce, plaintext, data []byte) []byte
+	// The plaintext and dst may alias exactly or not at all. To reuse
+	// plaintext's storage for the encrypted output, use plaintext[:0] as dst.
+	Seal(dst, nonce, plaintext, additionalData []byte) []byte
 
 	// Open decrypts and authenticates ciphertext, authenticates the
 	// additional data and, if successful, appends the resulting plaintext
@@ -34,8 +36,19 @@ type AEAD interface {
 	// bytes long and both it and the additional data must match the
 	// value passed to Seal.
 	//
-	// The ciphertext and dst may alias exactly or not at all.
-	Open(dst, nonce, ciphertext, data []byte) ([]byte, error)
+	// The ciphertext and dst may alias exactly or not at all. To reuse
+	// ciphertext's storage for the decrypted output, use ciphertext[:0] as dst.
+	//
+	// Even if the function fails, the contents of dst, up to its capacity,
+	// may be overwritten.
+	Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error)
+}
+
+// gcmAble is an interface implemented by ciphers that have a specific optimized
+// implementation of GCM, like crypto/aes. NewGCM will check for this interface
+// and return the specific AEAD if found.
+type gcmAble interface {
+	NewGCM(int) (AEAD, error)
 }
 
 // gcmFieldElement represents a value in GF(2¹²⁸). In order to reflect the GCM
@@ -72,6 +85,10 @@ func NewGCM(cipher Block) (AEAD, error) {
 // cryptosystem that uses non-standard nonce lengths. All other users should use
 // NewGCM, which is faster and more resistant to misuse.
 func NewGCMWithNonceSize(cipher Block, size int) (AEAD, error) {
+	if cipher, ok := cipher.(gcmAble); ok {
+		return cipher.NewGCM(size)
+	}
+
 	if cipher.BlockSize() != gcmBlockSize {
 		return nil, errors.New("cipher: NewGCM requires 128-bit block cipher")
 	}
@@ -154,11 +171,19 @@ func (g *gcm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) {
 	var expectedTag [gcmTagSize]byte
 	g.auth(expectedTag[:], ciphertext, data, &tagMask)
 
+	ret, out := sliceForAppend(dst, len(ciphertext))
+
 	if subtle.ConstantTimeCompare(expectedTag[:], tag) != 1 {
+		// The AESNI code decrypts and authenticates concurrently, and
+		// so overwrites dst in the event of a tag mismatch. That
+		// behaviour is mimicked here in order to be consistent across
+		// platforms.
+		for i := range out {
+			out[i] = 0
+		}
 		return nil, errOpen
 	}
 
-	ret, out := sliceForAppend(dst, len(ciphertext))
 	g.counterCrypt(out, ciphertext, &counter)
 
 	return ret, nil
diff --git a/src/crypto/cipher/gcm_test.go b/src/crypto/cipher/gcm_test.go
index 81b9aa2..bb1ab3c 100644
--- a/src/crypto/cipher/gcm_test.go
+++ b/src/crypto/cipher/gcm_test.go
@@ -12,8 +12,6 @@ import (
 	"testing"
 )
 
-// AES-GCM test vectors taken from gcmEncryptExtIV128.rsp from
-// http://csrc.nist.gov/groups/STM/cavp/index.html.
 var aesGCMTests = []struct {
 	key, nonce, plaintext, ad, result string
 }{
@@ -32,6 +30,27 @@ var aesGCMTests = []struct {
 		"60d20404af527d248d893ae495707d1a",
 	},
 	{
+		"fbe3467cc254f81be8e78d765a2e6333",
+		"c6697351ff4aec29cdbaabf2",
+		"",
+		"67",
+		"3659cdc25288bf499ac736c03bfc1159",
+	},
+	{
+		"8a7f9d80d08ad0bd5a20fb689c88f9fc",
+		"88b7b27d800937fda4f47301",
+		"",
+		"50edd0503e0d7b8c91608eb5a1",
+		"ed6f65322a4740011f91d2aae22dd44e",
+	},
+	{
+		"051758e95ed4abb2cdc69bb454110e82",
+		"c99a66320db73158a35a255d",
+		"",
+		"67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339f",
+		"6ce77f1a5616c505b6aec09420234036",
+	},
+	{
 		"77be63708971c4e240d1cb79e8d77feb",
 		"e0e00f19fed7ba0136a797f3",
 		"",
@@ -130,6 +149,41 @@ var aesGCMTests = []struct {
 		"8d8c7ffc55086d539b5a8f0d1232654c",
 		"0d803ec309482f35b8e6226f2b56303239298e06b281c2d51aaba3c125",
 	},
+	{
+		"0e18a844ac5bf38e4cd72d9b0942e506",
+		"0870d4b28a2954489a0abcd5",
+		"67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b3",
+		"05eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe2f0e49e4f321549fd824ea9",
+		"cace28f4976afd72e3c5128167eb788fbf6634dda0a2f53148d00f6fa557f5e9e8f736c12e450894af56cb67f7d99e1027258c8571bd91ee3b7360e0d508aa1f382411a16115f9c05251cc326d4016f62e0eb8151c048465b0c6c8ff12558d43310e18b2cb1889eec91557ce21ba05955cf4c1d4847aadfb1b0a83f3a3b82b7efa62a5f03c5d6eda381a85dd78dbc55c",
+	},
+	{
+		"1f6c3a3bc0542aabba4ef8f6c7169e73",
+		"f3584606472b260e0dd2ebb2",
+		"67c6697351ff4aec29cdbaabf2fbe3467cc254f81be8e78d765a2e63339fc99a66320db73158a35a255d051758e95ed4abb2cdc69bb454110e827441213ddc8770e93ea141e1fc673e017e97eadc6b968f385c2aecb03bfb32af3c54ec18db5c021afe43fbfaaa3afb29d1e6053c7c9475d8be6189f95cbba8990f95b1ebf1b305eff700e9a13ae5ca0bcbd0484764bd1f231ea81c7b64c514735ac55e4b79633b706424119e09dcaad4acf21b10af3b33cde3504847155cbb6f2219ba9b7df50be11a1c7f23f829f8a41b13b5ca4ee8983238e0794d3d34bc5f4e77facb6c05ac86212baa1a55a2be70b5733b045cd33694b3afe [...]
+		"95aa82ca6c49ae90cd1668baac7aa6f2b4a8ca99b2c2372acb08cf61c9c3805e6e0328da4cd76a19edd2d3994c798b0022569ad418d1fee4d9cd45a391c601ffc92ad91501432fee150287617c13629e69fc7281cd7165a63eab49cf714bce3a75a74f76ea7e64ff81eb61fdfec39b67bf0de98c7e4e32bdf97c8c6ac75ba43c02f4b2ed7216ecf3014df000108b67cf99505b179f8ed4980a6103d1bca70dbe9bbfab0ed59801d6e5f2d6f67d3ec5168e212e2daf02c6b963c98a1f7097de0c56891a2b211b01070dd8fd8b16c2a1a4e3cfd292d2984b3561d555d16c33ddc2bcf7edde13efe520c7e2abdda44d81881c531aeee [...]
+		"55864065117e07650ca650a0f0d9ef4b02aee7c58928462fddb49045bf85355b4653fa26158210a7f3ef5b3ca48612e8b7adf5c025c1b821960af770d935df1c9a1dd25077d6b1c7f937b2e20ce981b07980880214698f3fad72fa370b3b7da257ce1d0cf352bc5304fada3e0f8927bd4e5c1abbffa563bdedcb567daa64faaed748cb361732200ba3506836a3c1c82aafa14c76dc07f6c4277ff2c61325f91fdbd6c1883e745fcaadd5a6d692eeaa5ad56eead6a9d74a595d22757ed89532a4b8831e2b9e2315baea70a9b95d228f09d491a5ed5ab7076766703457e3159bbb9b17b329525669863153079448c68cd2f200c0be9 [...]
+	},
+	{
+		"0795d80bc7f40f4d41c280271a2e4f7f",
+		"ff824c906594aff365d3cb1f",
+		"1ad4e74d127f935beee57cff920665babe7ce56227377afe570ba786193ded3412d4812453157f42fafc418c02a746c1232c234a639d49baa8f041c12e2ef540027764568ce49886e0d913e28059a3a485c6eee96337a30b28e4cd5612c2961539fa6bc5de034cbedc5fa15db844013e0bef276e27ca7a4faf47a5c1093bd643354108144454d221b3737e6cb87faac36ed131959babe44af2890cfcc4e23ffa24470e689ce0894f5407bb0c8665cff536008ad2ac6f1c9ef8289abd0bd9b72f21c597bda5210cf928c805af2dd4a464d52e36819d521f967bba5386930ab5b4cf4c71746d7e6e964673457348e9d71d170d9eb56 [...]
+		"98a47a430d8fd74dc1829a91e3481f8ed024d8ba34c9b903321b04864db333e558ae28653dffb2",
+		"3b8f91443480e647473a0a0b03d571c622b7e70e4309a02c9bb7980053010d865e6aec161354dc9f481b2cd5213e09432b57ec4e58fbd0a8549dd15c8c4e74a6529f75fad0ce5a9e20e2beeb2f91eb638bf88999968de438d2f1cedbfb0a1c81f9e8e7362c738e0fddd963692a4f4df9276b7f040979ce874cf6fa3de26da0713784bdb25e4efcb840554ef5b38b5fe8380549a496bd8e423a7456df6f4ae78a07ebe2276a8e22fc2243ec4f78abe0c99c733fd67c8c492699fa5ee2289cdd0a8d469bf883520ee74efb854bfadc7366a49ee65ca4e894e3335e2b672618d362eee12a577dd8dc2ba55c49c1fc3ad68180e9b112d [...]
+	},
+	{
+		"e2e001a36c60d2bf40d69ff5b2b1161ea218db263be16a4e",
+		"84230643130d05425826641e",
+		"adb034f3f4a7ca45e2993812d113a9821d50df151af978bccc6d3bc113e15bc0918fb385377dca1916022ce816d56a332649484043c0fc0f2d37d040182b00a9bbb42ef231f80b48fb3730110d9a4433e38c73264c703579a705b9c031b969ec6d98de9f90e9e78b21179c2eb1e061946cd4bbb844f031ecf6eaac27a4151311adf1b03eda97c9fbae66295f468af4b35faf6ba39f9d8f95873bbc2b51cf3dfec0ed3c9b850696336cc093b24a8765a936d14dd56edc6bf518272169f75e67b74ba452d0aae90416a997c8f31e2e9d54ffea296dc69462debc8347b3e1af6a2d53bdfdfda601134f98db42b609df0a08c9347590c [...]
+		"d5d7316b8fdee152942148bff007c22e4b2022c6bc7be3c18c5f2e52e004e0b5dc12206bf002bd",
+		"f2c39423ee630dfe961da81909159dba018ce09b1073a12a477108316af5b7a31f86be6a0548b572d604bd115ea737dde899e0bd7f7ac9b23e38910dc457551ecc15c814a9f46d8432a1a36097dc1afe2712d1ba0838fa88cb55d9f65a2e9bece0dbf8999562503989041a2c87d7eb80ef649769d2f4978ce5cf9664f2bd0849646aa81cb976e45e1ade2f17a8126219e917aadbb4bae5e2c4b3f57bbc7f13fcc807df7842d9727a1b389e0b749e5191482adacabd812627c6eae2c7a30caf0844ad2a22e08f39edddf0ae10413e47db433dfe3febbb5a5cec9ade21fbba1e548247579395880b747669a8eb7e2ec0c1bff7fed2d [...]
+	},
+	{
+		"5394e890d37ba55ec9d5f327f15680f6a63ef5279c79331643ad0af6d2623525",
+		"815e840b7aca7af3b324583f",
+		"8e63067cd15359f796b43c68f093f55fdf3589fc5f2fdfad5f9d156668a617f7091d73da71cdd207810e6f71a165d0809a597df9885ca6e8f9bb4e616166586b83cc45f49917fc1a256b8bc7d05c476ab5c4633e20092619c4747b26dad3915e9fd65238ee4e5213badeda8a3a22f5efe6582d0762532026c89b4ca26fdd000eb45347a2a199b55b7790e6b1b2dba19833ce9f9522c0bcea5b088ccae68dd99ae0203c81b9f1dd3181c3e2339e83ccd1526b67742b235e872bea5111772aab574ae7d904d9b6355a79178e179b5ae8edc54f61f172bf789ea9c9af21f45b783e4251421b077776808f04972a5e801723cf7814423 [...]
+		"0feccdfae8ed65fa31a0858a1c466f79e8aa658c2f3ba93c3f92158b4e30955e1c62580450beff",
+		"b69a7e17bb5af688883274550a4ded0d1aff49a0b18343f4b382f745c163f7f714c9206a32a1ff012427e19431951edd0a755e5f491b0eedfd7df68bbc6085dd2888607a2f998c3e881eb1694109250db28291e71f4ad344a125624fb92e16ea9815047cd1111cabfdc9cb8c3b4b0f40aa91d31774009781231400789ed545404af6c3f76d07ddc984a7bd8f52728159782832e298cc4d529be96d17be898efd83e44dc7b0e2efc645849fd2bba61fef0ae7be0dcab233cc4e2b7ba4e887de9c64b97f2a1818aa54371a8d629dae37975f7784e5e3cc77055ed6e975b1e5f55e6bbacdc9f295ce4ada2c16113cd5b323cf78b7dde [...]
+	},
 }
 
 func TestAESGCM(t *testing.T) {
@@ -186,3 +240,37 @@ func TestAESGCM(t *testing.T) {
 		ct[0] ^= 0x80
 	}
 }
+
+func TestTagFailureOverwrite(t *testing.T) {
+	// The AESNI GCM code decrypts and authenticates concurrently and so
+	// overwrites the output buffer before checking the authentication tag.
+	// In order to be consistent across platforms, all implementations
+	// should do this and this test checks that.
+
+	key, _ := hex.DecodeString("ab72c77b97cb5fe9a382d9fe81ffdbed")
+	nonce, _ := hex.DecodeString("54cc7dc2c37ec006bcc6d1db")
+	ciphertext, _ := hex.DecodeString("0e1bde206a07a9c2c1b65300f8c649972b4401346697138c7a4891ee59867d0c")
+
+	aes, _ := aes.NewCipher(key)
+	aesgcm, _ := cipher.NewGCM(aes)
+
+	dst := make([]byte, len(ciphertext)-16)
+	for i := range dst {
+		dst[i] = 42
+	}
+
+	result, err := aesgcm.Open(dst[:0], nonce, ciphertext, nil)
+	if err == nil {
+		t.Fatal("Bad Open still resulted in nil error.")
+	}
+
+	if result != nil {
+		t.Fatal("Failed Open returned non-nil result.")
+	}
+
+	for i := range dst {
+		if dst[i] != 0 {
+			t.Fatal("Failed Open didn't zero dst buffer")
+		}
+	}
+}
diff --git a/src/crypto/crypto.go b/src/crypto/crypto.go
index 184ea9d..a80ebd3 100644
--- a/src/crypto/crypto.go
+++ b/src/crypto/crypto.go
@@ -109,7 +109,7 @@ type Signer interface {
 	// private key.
 	Public() PublicKey
 
-	// Sign signs msg with the private key, possibly using entropy from
+	// Sign signs digest with the private key, possibly using entropy from
 	// rand. For an RSA key, the resulting signature should be either a
 	// PKCS#1 v1.5 or PSS signature (as indicated by opts). For an (EC)DSA
 	// key, it should be a DER-serialised, ASN.1 signature structure.
@@ -118,7 +118,11 @@ type Signer interface {
 	// simply pass in the hash function used as opts. Sign may also attempt
 	// to type assert opts to other types in order to obtain algorithm
 	// specific values. See the documentation in each package for details.
-	Sign(rand io.Reader, msg []byte, opts SignerOpts) (signature []byte, err error)
+	//
+	// Note that when a signature of a hash of a larger message is needed,
+	// the caller is responsible for hashing the larger message and passing
+	// the hash (as digest) and the hash function (as opts) to Sign.
+	Sign(rand io.Reader, digest []byte, opts SignerOpts) (signature []byte, err error)
 }
 
 // SignerOpts contains options for signing with a Signer.
diff --git a/src/crypto/dsa/dsa.go b/src/crypto/dsa/dsa.go
index b7565a6..28e981b 100644
--- a/src/crypto/dsa/dsa.go
+++ b/src/crypto/dsa/dsa.go
@@ -51,7 +51,7 @@ const (
 const numMRTests = 64
 
 // GenerateParameters puts a random, valid set of DSA parameters into params.
-// This function takes many seconds, even on fast machines.
+// This function can take many seconds, even on fast machines.
 func GenerateParameters(params *Parameters, rand io.Reader, sizes ParameterSizes) (err error) {
 	// This function doesn't follow FIPS 186-3 exactly in that it doesn't
 	// use a verification seed to generate the primes. The verification
diff --git a/src/crypto/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go
index 8d66477..0731f2b 100644
--- a/src/crypto/ecdsa/ecdsa.go
+++ b/src/crypto/ecdsa/ecdsa.go
@@ -27,6 +27,17 @@ import (
 	"math/big"
 )
 
+// A invertible implements fast inverse mod Curve.Params().N
+type invertible interface {
+	// Inverse returns the inverse of k in GF(P)
+	Inverse(k *big.Int) *big.Int
+}
+
+// combinedMult implements fast multiplication S1*g + S2*p (g - generator, p - arbitrary point)
+type combinedMult interface {
+	CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int)
+}
+
 const (
 	aesIV = "IV for ECDSA CTR"
 )
@@ -179,7 +190,12 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err
 				return
 			}
 
-			kInv = fermatInverse(k, N)
+			if in, ok := priv.Curve.(invertible); ok {
+				kInv = in.Inverse(k)
+			} else {
+				kInv = fermatInverse(k, N)
+			}
+
 			r, _ = priv.Curve.ScalarBaseMult(k.Bytes())
 			r.Mod(r, N)
 			if r.Sign() != 0 {
@@ -214,16 +230,29 @@ func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
 		return false
 	}
 	e := hashToInt(hash, c)
-	w := new(big.Int).ModInverse(s, N)
+
+	var w *big.Int
+	if in, ok := c.(invertible); ok {
+		w = in.Inverse(s)
+	} else {
+		w = new(big.Int).ModInverse(s, N)
+	}
 
 	u1 := e.Mul(e, w)
 	u1.Mod(u1, N)
 	u2 := w.Mul(r, w)
 	u2.Mod(u2, N)
 
-	x1, y1 := c.ScalarBaseMult(u1.Bytes())
-	x2, y2 := c.ScalarMult(pub.X, pub.Y, u2.Bytes())
-	x, y := c.Add(x1, y1, x2, y2)
+	// Check if implements S1*g + S2*p
+	var x, y *big.Int
+	if opt, ok := c.(combinedMult); ok {
+		x, y = opt.CombinedMult(pub.X, pub.Y, u1.Bytes(), u2.Bytes())
+	} else {
+		x1, y1 := c.ScalarBaseMult(u1.Bytes())
+		x2, y2 := c.ScalarMult(pub.X, pub.Y, u2.Bytes())
+		x, y = c.Add(x1, y1, x2, y2)
+	}
+
 	if x.Sign() == 0 && y.Sign() == 0 {
 		return false
 	}
diff --git a/src/crypto/ecdsa/ecdsa_test.go b/src/crypto/ecdsa/ecdsa_test.go
index 169944d..62a3fcc 100644
--- a/src/crypto/ecdsa/ecdsa_test.go
+++ b/src/crypto/ecdsa/ecdsa_test.go
@@ -42,6 +42,41 @@ func TestKeyGeneration(t *testing.T) {
 	testKeyGeneration(t, elliptic.P521(), "p521")
 }
 
+func BenchmarkSignP256(b *testing.B) {
+	b.ResetTimer()
+	p256 := elliptic.P256()
+	hashed := []byte("testing")
+	priv, _ := GenerateKey(p256, rand.Reader)
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		_, _, _ = Sign(rand.Reader, priv, hashed)
+	}
+}
+
+func BenchmarkVerifyP256(b *testing.B) {
+	b.ResetTimer()
+	p256 := elliptic.P256()
+	hashed := []byte("testing")
+	priv, _ := GenerateKey(p256, rand.Reader)
+	r, s, _ := Sign(rand.Reader, priv, hashed)
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		Verify(&priv.PublicKey, hashed, r, s)
+	}
+}
+
+func BenchmarkKeyGeneration(b *testing.B) {
+	b.ResetTimer()
+	p256 := elliptic.P256()
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		GenerateKey(p256, rand.Reader)
+	}
+}
+
 func testSignAndVerify(t *testing.T, c elliptic.Curve, tag string) {
 	priv, _ := GenerateKey(c, rand.Reader)
 
@@ -91,11 +126,11 @@ func testNonceSafety(t *testing.T, c elliptic.Curve, tag string) {
 
 	if s0.Cmp(s1) == 0 {
 		// This should never happen.
-		t.Errorf("%s: the signatures on two different messages were the same")
+		t.Errorf("%s: the signatures on two different messages were the same", tag)
 	}
 
 	if r0.Cmp(r1) == 0 {
-		t.Errorf("%s: the nonce used for two diferent messages was the same")
+		t.Errorf("%s: the nonce used for two diferent messages was the same", tag)
 	}
 }
 
@@ -126,11 +161,11 @@ func testINDCCA(t *testing.T, c elliptic.Curve, tag string) {
 	}
 
 	if s0.Cmp(s1) == 0 {
-		t.Errorf("%s: two signatures of the same message produced the same result")
+		t.Errorf("%s: two signatures of the same message produced the same result", tag)
 	}
 
 	if r0.Cmp(r1) == 0 {
-		t.Errorf("%s: two signatures of the same message produced the same nonce")
+		t.Errorf("%s: two signatures of the same message produced the same nonce", tag)
 	}
 }
 
diff --git a/src/crypto/elliptic/elliptic.go b/src/crypto/elliptic/elliptic.go
index e6b59c5..c02df45 100644
--- a/src/crypto/elliptic/elliptic.go
+++ b/src/crypto/elliptic/elliptic.go
@@ -274,7 +274,8 @@ var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f}
 // GenerateKey returns a public/private key pair. The private key is
 // generated using the given reader, which must return random data.
 func GenerateKey(curve Curve, rand io.Reader) (priv []byte, x, y *big.Int, err error) {
-	bitSize := curve.Params().BitSize
+	N := curve.Params().N
+	bitSize := N.BitLen()
 	byteLen := (bitSize + 7) >> 3
 	priv = make([]byte, byteLen)
 
@@ -289,6 +290,12 @@ func GenerateKey(curve Curve, rand io.Reader) (priv []byte, x, y *big.Int, err e
 		// This is because, in tests, rand will return all zeros and we don't
 		// want to get the point at infinity and loop forever.
 		priv[1] ^= 0x42
+
+		// If the scalar is out of range, sample another random number.
+		if new(big.Int).SetBytes(priv).Cmp(N) >= 0 {
+			continue
+		}
+
 		x, y = curve.ScalarBaseMult(priv)
 	}
 	return
diff --git a/src/crypto/elliptic/elliptic_test.go b/src/crypto/elliptic/elliptic_test.go
index 7e27913..7f3f1a2 100644
--- a/src/crypto/elliptic/elliptic_test.go
+++ b/src/crypto/elliptic/elliptic_test.go
@@ -441,6 +441,18 @@ func BenchmarkBaseMultP256(b *testing.B) {
 	}
 }
 
+func BenchmarkScalarMultP256(b *testing.B) {
+	b.ResetTimer()
+	p256 := P256()
+	_, x, y, _ := GenerateKey(p256, rand.Reader)
+	priv, _, _, _ := GenerateKey(p256, rand.Reader)
+
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		p256.ScalarMult(x, y, priv)
+	}
+}
+
 func TestMarshal(t *testing.T) {
 	p224 := P224()
 	_, x, y, err := GenerateKey(p224, rand.Reader)
diff --git a/src/crypto/elliptic/p256.go b/src/crypto/elliptic/p256.go
index 82bc7b3..5103e86 100644
--- a/src/crypto/elliptic/p256.go
+++ b/src/crypto/elliptic/p256.go
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !amd64
+
 package elliptic
 
 // This file contains a constant-time, 32-bit implementation of P256.
diff --git a/src/crypto/elliptic/p256_amd64.go b/src/crypto/elliptic/p256_amd64.go
new file mode 100644
index 0000000..586cd10
--- /dev/null
+++ b/src/crypto/elliptic/p256_amd64.go
@@ -0,0 +1,552 @@
+// Copyright 2015 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 file contains the Go wrapper for the constant-time, 64-bit assembly
+// implementation of P256. The optimizations performed here are described in
+// detail in:
+// S.Gueron and V.Krasnov, "Fast prime field elliptic-curve cryptography with
+//                          256-bit primes"
+// http://link.springer.com/article/10.1007%2Fs13389-014-0090-x
+// https://eprint.iacr.org/2013/816.pdf
+
+// +build amd64
+
+package elliptic
+
+import (
+	"math/big"
+	"sync"
+)
+
+type (
+	p256Curve struct {
+		*CurveParams
+	}
+
+	p256Point struct {
+		xyz [12]uint64
+	}
+)
+
+var (
+	p256            p256Curve
+	p256Precomputed *[37][64 * 8]uint64
+	precomputeOnce  sync.Once
+)
+
+func initP256() {
+	// See FIPS 186-3, section D.2.3
+	p256.CurveParams = &CurveParams{Name: "P-256"}
+	p256.P, _ = new(big.Int).SetString("115792089210356248762697446949407573530086143415290314195533631308867097853951", 10)
+	p256.N, _ = new(big.Int).SetString("115792089210356248762697446949407573529996955224135760342422259061068512044369", 10)
+	p256.B, _ = new(big.Int).SetString("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16)
+	p256.Gx, _ = new(big.Int).SetString("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16)
+	p256.Gy, _ = new(big.Int).SetString("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16)
+	p256.BitSize = 256
+}
+
+func (curve p256Curve) Params() *CurveParams {
+	return curve.CurveParams
+}
+
+// Functions implemented in p256_asm_amd64.s
+// Montgomery multiplication modulo P256
+func p256Mul(res, in1, in2 []uint64)
+
+// Montgomery square modulo P256
+func p256Sqr(res, in []uint64)
+
+// Montgomery multiplication by 1
+func p256FromMont(res, in []uint64)
+
+// iff cond == 1  val <- -val
+func p256NegCond(val []uint64, cond int)
+
+// if cond == 0 res <- b; else res <- a
+func p256MovCond(res, a, b []uint64, cond int)
+
+// Endianess swap
+func p256BigToLittle(res []uint64, in []byte)
+func p256LittleToBig(res []byte, in []uint64)
+
+// Constant time table access
+func p256Select(point, table []uint64, idx int)
+func p256SelectBase(point, table []uint64, idx int)
+
+// Montgomery multiplication modulo Ord(G)
+func p256OrdMul(res, in1, in2 []uint64)
+
+// Montgomery square modulo Ord(G), repeated n times
+func p256OrdSqr(res, in []uint64, n int)
+
+// Point add with in2 being affine point
+// If sign == 1 -> in2 = -in2
+// If sel == 0 -> res = in1
+// if zero == 0 -> res = in2
+func p256PointAddAffineAsm(res, in1, in2 []uint64, sign, sel, zero int)
+
+// Point add
+func p256PointAddAsm(res, in1, in2 []uint64)
+
+// Point double
+func p256PointDoubleAsm(res, in []uint64)
+
+func (curve p256Curve) Inverse(k *big.Int) *big.Int {
+	if k.Cmp(p256.N) >= 0 {
+		// This should never happen.
+		reducedK := new(big.Int).Mod(k, p256.N)
+		k = reducedK
+	}
+
+	// table will store precomputed powers of x. The four words at index
+	// 4×i store x^(i+1).
+	var table [4 * 15]uint64
+
+	x := make([]uint64, 4)
+	fromBig(x[:], k)
+	// This code operates in the Montgomery domain where R = 2^256 mod n
+	// and n is the order of the scalar field. (See initP256 for the
+	// value.) Elements in the Montgomery domain take the form a×R and
+	// multiplication of x and y in the calculates (x × y × R^-1) mod n. RR
+	// is R×R mod n thus the Montgomery multiplication x and RR gives x×R,
+	// i.e. converts x into the Montgomery domain.
+	RR := []uint64{0x83244c95be79eea2, 0x4699799c49bd6fa6, 0x2845b2392b6bec59, 0x66e12d94f3d95620}
+	p256OrdMul(table[:4], x, RR)
+
+	// Prepare the table, no need in constant time access, because the
+	// power is not a secret. (Entry 0 is never used.)
+	for i := 2; i < 16; i += 2 {
+		p256OrdSqr(table[4*(i-1):], table[4*((i/2)-1):], 1)
+		p256OrdMul(table[4*i:], table[4*(i-1):], table[:4])
+	}
+
+	x[0] = table[4*14+0] // f
+	x[1] = table[4*14+1]
+	x[2] = table[4*14+2]
+	x[3] = table[4*14+3]
+
+	p256OrdSqr(x, x, 4)
+	p256OrdMul(x, x, table[4*14:4*14+4]) // ff
+	t := make([]uint64, 4, 4)
+	t[0] = x[0]
+	t[1] = x[1]
+	t[2] = x[2]
+	t[3] = x[3]
+
+	p256OrdSqr(x, x, 8)
+	p256OrdMul(x, x, t) // ffff
+	t[0] = x[0]
+	t[1] = x[1]
+	t[2] = x[2]
+	t[3] = x[3]
+
+	p256OrdSqr(x, x, 16)
+	p256OrdMul(x, x, t) // ffffffff
+	t[0] = x[0]
+	t[1] = x[1]
+	t[2] = x[2]
+	t[3] = x[3]
+
+	p256OrdSqr(x, x, 64) // ffffffff0000000000000000
+	p256OrdMul(x, x, t)  // ffffffff00000000ffffffff
+	p256OrdSqr(x, x, 32) // ffffffff00000000ffffffff00000000
+	p256OrdMul(x, x, t)  // ffffffff00000000ffffffffffffffff
+
+	// Remaining 32 windows
+	expLo := [32]byte{0xb, 0xc, 0xe, 0x6, 0xf, 0xa, 0xa, 0xd, 0xa, 0x7, 0x1, 0x7, 0x9, 0xe, 0x8, 0x4, 0xf, 0x3, 0xb, 0x9, 0xc, 0xa, 0xc, 0x2, 0xf, 0xc, 0x6, 0x3, 0x2, 0x5, 0x4, 0xf}
+	for i := 0; i < 32; i++ {
+		p256OrdSqr(x, x, 4)
+		p256OrdMul(x, x, table[4*(expLo[i]-1):])
+	}
+
+	// Multiplying by one in the Montgomery domain converts a Montgomery
+	// value out of the domain.
+	one := []uint64{1, 0, 0, 0}
+	p256OrdMul(x, x, one)
+
+	xOut := make([]byte, 32)
+	p256LittleToBig(xOut, x)
+	return new(big.Int).SetBytes(xOut)
+}
+
+// fromBig converts a *big.Int into a format used by this code.
+func fromBig(out []uint64, big *big.Int) {
+	for i := range out {
+		out[i] = 0
+	}
+
+	for i, v := range big.Bits() {
+		out[i] = uint64(v)
+	}
+}
+
+// p256GetScalar endian-swaps the big-endian scalar value from in and writes it
+// to out. If the scalar is equal or greater than the order of the group, it's
+// reduced modulo that order.
+func p256GetScalar(out []uint64, in []byte) {
+	n := new(big.Int).SetBytes(in)
+
+	if n.Cmp(p256.N) >= 0 {
+		n.Mod(n, p256.N)
+	}
+	fromBig(out, n)
+}
+
+// p256Mul operates in a Montgomery domain with R = 2^256 mod p, where p is the
+// underlying field of the curve. (See initP256 for the value.) Thus rr here is
+// R×R mod p. See comment in Inverse about how this is used.
+var rr = []uint64{0x0000000000000003, 0xfffffffbffffffff, 0xfffffffffffffffe, 0x00000004fffffffd}
+
+func maybeReduceModP(in *big.Int) *big.Int {
+	if in.Cmp(p256.P) < 0 {
+		return in
+	}
+	return new(big.Int).Mod(in, p256.P)
+}
+
+func (curve p256Curve) CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int) {
+	scalarReversed := make([]uint64, 4)
+	var r1, r2 p256Point
+	p256GetScalar(scalarReversed, baseScalar)
+	r1.p256BaseMult(scalarReversed)
+
+	p256GetScalar(scalarReversed, scalar)
+	fromBig(r2.xyz[0:4], maybeReduceModP(bigX))
+	fromBig(r2.xyz[4:8], maybeReduceModP(bigY))
+	p256Mul(r2.xyz[0:4], r2.xyz[0:4], rr[:])
+	p256Mul(r2.xyz[4:8], r2.xyz[4:8], rr[:])
+
+	// This sets r2's Z value to 1, in the Montgomery domain.
+	r2.xyz[8] = 0x0000000000000001
+	r2.xyz[9] = 0xffffffff00000000
+	r2.xyz[10] = 0xffffffffffffffff
+	r2.xyz[11] = 0x00000000fffffffe
+
+	r2.p256ScalarMult(scalarReversed)
+	p256PointAddAsm(r1.xyz[:], r1.xyz[:], r2.xyz[:])
+	return r1.p256PointToAffine()
+}
+
+func (curve p256Curve) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
+	scalarReversed := make([]uint64, 4)
+	p256GetScalar(scalarReversed, scalar)
+
+	var r p256Point
+	r.p256BaseMult(scalarReversed)
+	return r.p256PointToAffine()
+}
+
+func (curve p256Curve) ScalarMult(bigX, bigY *big.Int, scalar []byte) (x, y *big.Int) {
+	scalarReversed := make([]uint64, 4)
+	p256GetScalar(scalarReversed, scalar)
+
+	var r p256Point
+	fromBig(r.xyz[0:4], maybeReduceModP(bigX))
+	fromBig(r.xyz[4:8], maybeReduceModP(bigY))
+	p256Mul(r.xyz[0:4], r.xyz[0:4], rr[:])
+	p256Mul(r.xyz[4:8], r.xyz[4:8], rr[:])
+	// This sets r2's Z value to 1, in the Montgomery domain.
+	r.xyz[8] = 0x0000000000000001
+	r.xyz[9] = 0xffffffff00000000
+	r.xyz[10] = 0xffffffffffffffff
+	r.xyz[11] = 0x00000000fffffffe
+
+	r.p256ScalarMult(scalarReversed)
+	return r.p256PointToAffine()
+}
+
+func (p *p256Point) p256PointToAffine() (x, y *big.Int) {
+	zInv := make([]uint64, 4)
+	zInvSq := make([]uint64, 4)
+	p256Inverse(zInv, p.xyz[8:12])
+	p256Sqr(zInvSq, zInv)
+	p256Mul(zInv, zInv, zInvSq)
+
+	p256Mul(zInvSq, p.xyz[0:4], zInvSq)
+	p256Mul(zInv, p.xyz[4:8], zInv)
+
+	p256FromMont(zInvSq, zInvSq)
+	p256FromMont(zInv, zInv)
+
+	xOut := make([]byte, 32)
+	yOut := make([]byte, 32)
+	p256LittleToBig(xOut, zInvSq)
+	p256LittleToBig(yOut, zInv)
+
+	return new(big.Int).SetBytes(xOut), new(big.Int).SetBytes(yOut)
+}
+
+// p256Inverse sets out to in^-1 mod p.
+func p256Inverse(out, in []uint64) {
+	var stack [6 * 4]uint64
+	p2 := stack[4*0 : 4*0+4]
+	p4 := stack[4*1 : 4*1+4]
+	p8 := stack[4*2 : 4*2+4]
+	p16 := stack[4*3 : 4*3+4]
+	p32 := stack[4*4 : 4*4+4]
+
+	p256Sqr(out, in)
+	p256Mul(p2, out, in) // 3*p
+
+	p256Sqr(out, p2)
+	p256Sqr(out, out)
+	p256Mul(p4, out, p2) // f*p
+
+	p256Sqr(out, p4)
+	p256Sqr(out, out)
+	p256Sqr(out, out)
+	p256Sqr(out, out)
+	p256Mul(p8, out, p4) // ff*p
+
+	p256Sqr(out, p8)
+
+	for i := 0; i < 7; i++ {
+		p256Sqr(out, out)
+	}
+	p256Mul(p16, out, p8) // ffff*p
+
+	p256Sqr(out, p16)
+	for i := 0; i < 15; i++ {
+		p256Sqr(out, out)
+	}
+	p256Mul(p32, out, p16) // ffffffff*p
+
+	p256Sqr(out, p32)
+
+	for i := 0; i < 31; i++ {
+		p256Sqr(out, out)
+	}
+	p256Mul(out, out, in)
+
+	for i := 0; i < 32*4; i++ {
+		p256Sqr(out, out)
+	}
+	p256Mul(out, out, p32)
+
+	for i := 0; i < 32; i++ {
+		p256Sqr(out, out)
+	}
+	p256Mul(out, out, p32)
+
+	for i := 0; i < 16; i++ {
+		p256Sqr(out, out)
+	}
+	p256Mul(out, out, p16)
+
+	for i := 0; i < 8; i++ {
+		p256Sqr(out, out)
+	}
+	p256Mul(out, out, p8)
+
+	p256Sqr(out, out)
+	p256Sqr(out, out)
+	p256Sqr(out, out)
+	p256Sqr(out, out)
+	p256Mul(out, out, p4)
+
+	p256Sqr(out, out)
+	p256Sqr(out, out)
+	p256Mul(out, out, p2)
+
+	p256Sqr(out, out)
+	p256Sqr(out, out)
+	p256Mul(out, out, in)
+}
+
+func (p *p256Point) p256StorePoint(r *[16 * 4 * 3]uint64, index int) {
+	copy(r[index*12:], p.xyz[:])
+}
+
+func boothW5(in uint) (int, int) {
+	var s uint = ^((in >> 5) - 1)
+	var d uint = (1 << 6) - in - 1
+	d = (d & s) | (in & (^s))
+	d = (d >> 1) + (d & 1)
+	return int(d), int(s & 1)
+}
+
+func boothW7(in uint) (int, int) {
+	var s uint = ^((in >> 7) - 1)
+	var d uint = (1 << 8) - in - 1
+	d = (d & s) | (in & (^s))
+	d = (d >> 1) + (d & 1)
+	return int(d), int(s & 1)
+}
+
+func initTable() {
+	p256Precomputed = new([37][64 * 8]uint64)
+
+	basePoint := []uint64{
+		0x79e730d418a9143c, 0x75ba95fc5fedb601, 0x79fb732b77622510, 0x18905f76a53755c6,
+		0xddf25357ce95560a, 0x8b4ab8e4ba19e45c, 0xd2e88688dd21f325, 0x8571ff1825885d85,
+		0x0000000000000001, 0xffffffff00000000, 0xffffffffffffffff, 0x00000000fffffffe,
+	}
+	t1 := make([]uint64, 12)
+	t2 := make([]uint64, 12)
+	copy(t2, basePoint)
+
+	zInv := make([]uint64, 4)
+	zInvSq := make([]uint64, 4)
+	for j := 0; j < 64; j++ {
+		copy(t1, t2)
+		for i := 0; i < 37; i++ {
+			// The window size is 7 so we need to double 7 times.
+			if i != 0 {
+				for k := 0; k < 7; k++ {
+					p256PointDoubleAsm(t1, t1)
+				}
+			}
+			// Convert the point to affine form. (Its values are
+			// still in Montgomery form however.)
+			p256Inverse(zInv, t1[8:12])
+			p256Sqr(zInvSq, zInv)
+			p256Mul(zInv, zInv, zInvSq)
+
+			p256Mul(t1[:4], t1[:4], zInvSq)
+			p256Mul(t1[4:8], t1[4:8], zInv)
+
+			copy(t1[8:12], basePoint[8:12])
+			// Update the table entry
+			copy(p256Precomputed[i][j*8:], t1[:8])
+		}
+		if j == 0 {
+			p256PointDoubleAsm(t2, basePoint)
+		} else {
+			p256PointAddAsm(t2, t2, basePoint)
+		}
+	}
+}
+
+func (p *p256Point) p256BaseMult(scalar []uint64) {
+	precomputeOnce.Do(initTable)
+
+	wvalue := (scalar[0] << 1) & 0xff
+	sel, sign := boothW7(uint(wvalue))
+	p256SelectBase(p.xyz[0:8], p256Precomputed[0][0:], sel)
+	p256NegCond(p.xyz[4:8], sign)
+
+	// (This is one, in the Montgomery domain.)
+	p.xyz[8] = 0x0000000000000001
+	p.xyz[9] = 0xffffffff00000000
+	p.xyz[10] = 0xffffffffffffffff
+	p.xyz[11] = 0x00000000fffffffe
+
+	var t0 p256Point
+	// (This is one, in the Montgomery domain.)
+	t0.xyz[8] = 0x0000000000000001
+	t0.xyz[9] = 0xffffffff00000000
+	t0.xyz[10] = 0xffffffffffffffff
+	t0.xyz[11] = 0x00000000fffffffe
+
+	index := uint(6)
+	zero := sel
+
+	for i := 1; i < 37; i++ {
+		if index < 192 {
+			wvalue = ((scalar[index/64] >> (index % 64)) + (scalar[index/64+1] << (64 - (index % 64)))) & 0xff
+		} else {
+			wvalue = (scalar[index/64] >> (index % 64)) & 0xff
+		}
+		index += 7
+		sel, sign = boothW7(uint(wvalue))
+		p256SelectBase(t0.xyz[0:8], p256Precomputed[i][0:], sel)
+		p256PointAddAffineAsm(p.xyz[0:12], p.xyz[0:12], t0.xyz[0:8], sign, sel, zero)
+		zero |= sel
+	}
+}
+
+func (p *p256Point) p256ScalarMult(scalar []uint64) {
+	// precomp is a table of precomputed points that stores powers of p
+	// from p^1 to p^16.
+	var precomp [16 * 4 * 3]uint64
+	var t0, t1, t2, t3 p256Point
+
+	// Prepare the table
+	p.p256StorePoint(&precomp, 0) // 1
+
+	p256PointDoubleAsm(t0.xyz[:], p.xyz[:])
+	p256PointDoubleAsm(t1.xyz[:], t0.xyz[:])
+	p256PointDoubleAsm(t2.xyz[:], t1.xyz[:])
+	p256PointDoubleAsm(t3.xyz[:], t2.xyz[:])
+	t0.p256StorePoint(&precomp, 1)  // 2
+	t1.p256StorePoint(&precomp, 3)  // 4
+	t2.p256StorePoint(&precomp, 7)  // 8
+	t3.p256StorePoint(&precomp, 15) // 16
+
+	p256PointAddAsm(t0.xyz[:], t0.xyz[:], p.xyz[:])
+	p256PointAddAsm(t1.xyz[:], t1.xyz[:], p.xyz[:])
+	p256PointAddAsm(t2.xyz[:], t2.xyz[:], p.xyz[:])
+	t0.p256StorePoint(&precomp, 2) // 3
+	t1.p256StorePoint(&precomp, 4) // 5
+	t2.p256StorePoint(&precomp, 8) // 9
+
+	p256PointDoubleAsm(t0.xyz[:], t0.xyz[:])
+	p256PointDoubleAsm(t1.xyz[:], t1.xyz[:])
+	t0.p256StorePoint(&precomp, 5) // 6
+	t1.p256StorePoint(&precomp, 9) // 10
+
+	p256PointAddAsm(t2.xyz[:], t0.xyz[:], p.xyz[:])
+	p256PointAddAsm(t1.xyz[:], t1.xyz[:], p.xyz[:])
+	t2.p256StorePoint(&precomp, 6)  // 7
+	t1.p256StorePoint(&precomp, 10) // 11
+
+	p256PointDoubleAsm(t0.xyz[:], t0.xyz[:])
+	p256PointDoubleAsm(t2.xyz[:], t2.xyz[:])
+	t0.p256StorePoint(&precomp, 11) // 12
+	t2.p256StorePoint(&precomp, 13) // 14
+
+	p256PointAddAsm(t0.xyz[:], t0.xyz[:], p.xyz[:])
+	p256PointAddAsm(t2.xyz[:], t2.xyz[:], p.xyz[:])
+	t0.p256StorePoint(&precomp, 12) // 13
+	t2.p256StorePoint(&precomp, 14) // 15
+
+	// Start scanning the window from top bit
+	index := uint(254)
+	var sel, sign int
+
+	wvalue := (scalar[index/64] >> (index % 64)) & 0x3f
+	sel, _ = boothW5(uint(wvalue))
+
+	p256Select(p.xyz[0:12], precomp[0:], sel)
+	zero := sel
+
+	for index > 4 {
+		index -= 5
+		p256PointDoubleAsm(p.xyz[:], p.xyz[:])
+		p256PointDoubleAsm(p.xyz[:], p.xyz[:])
+		p256PointDoubleAsm(p.xyz[:], p.xyz[:])
+		p256PointDoubleAsm(p.xyz[:], p.xyz[:])
+		p256PointDoubleAsm(p.xyz[:], p.xyz[:])
+
+		if index < 192 {
+			wvalue = ((scalar[index/64] >> (index % 64)) + (scalar[index/64+1] << (64 - (index % 64)))) & 0x3f
+		} else {
+			wvalue = (scalar[index/64] >> (index % 64)) & 0x3f
+		}
+
+		sel, sign = boothW5(uint(wvalue))
+
+		p256Select(t0.xyz[0:], precomp[0:], sel)
+		p256NegCond(t0.xyz[4:8], sign)
+		p256PointAddAsm(t1.xyz[:], p.xyz[:], t0.xyz[:])
+		p256MovCond(t1.xyz[0:12], t1.xyz[0:12], p.xyz[0:12], sel)
+		p256MovCond(p.xyz[0:12], t1.xyz[0:12], t0.xyz[0:12], zero)
+		zero |= sel
+	}
+
+	p256PointDoubleAsm(p.xyz[:], p.xyz[:])
+	p256PointDoubleAsm(p.xyz[:], p.xyz[:])
+	p256PointDoubleAsm(p.xyz[:], p.xyz[:])
+	p256PointDoubleAsm(p.xyz[:], p.xyz[:])
+	p256PointDoubleAsm(p.xyz[:], p.xyz[:])
+
+	wvalue = (scalar[0] << 1) & 0x3f
+	sel, sign = boothW5(uint(wvalue))
+
+	p256Select(t0.xyz[0:], precomp[0:], sel)
+	p256NegCond(t0.xyz[4:8], sign)
+	p256PointAddAsm(t1.xyz[:], p.xyz[:], t0.xyz[:])
+	p256MovCond(t1.xyz[0:12], t1.xyz[0:12], p.xyz[0:12], sel)
+	p256MovCond(p.xyz[0:12], t1.xyz[0:12], t0.xyz[0:12], zero)
+}
diff --git a/src/crypto/elliptic/p256_asm_amd64.s b/src/crypto/elliptic/p256_asm_amd64.s
new file mode 100644
index 0000000..6c7bde1
--- /dev/null
+++ b/src/crypto/elliptic/p256_asm_amd64.s
@@ -0,0 +1,2295 @@
+// Copyright 2015 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 file contains constant-time, 64-bit assembly implementation of
+// P256. The optimizations performed here are described in detail in:
+// S.Gueron and V.Krasnov, "Fast prime field elliptic-curve cryptography with
+//                          256-bit primes"
+// http://link.springer.com/article/10.1007%2Fs13389-014-0090-x
+// https://eprint.iacr.org/2013/816.pdf
+
+#include "textflag.h"
+
+#define res_ptr DI
+#define x_ptr SI
+#define y_ptr CX
+
+#define acc0 R8
+#define acc1 R9
+#define acc2 R10
+#define acc3 R11
+#define acc4 R12
+#define acc5 R13
+#define t0 R14
+#define t1 R15
+
+DATA p256const0<>+0x00(SB)/8, $0x00000000ffffffff
+DATA p256const1<>+0x00(SB)/8, $0xffffffff00000001
+DATA p256ordK0<>+0x00(SB)/8, $0xccd1c8aaee00bc4f
+DATA p256ord<>+0x00(SB)/8, $0xf3b9cac2fc632551
+DATA p256ord<>+0x08(SB)/8, $0xbce6faada7179e84
+DATA p256ord<>+0x10(SB)/8, $0xffffffffffffffff
+DATA p256ord<>+0x18(SB)/8, $0xffffffff00000000
+DATA p256one<>+0x00(SB)/8, $0x0000000000000001
+DATA p256one<>+0x08(SB)/8, $0xffffffff00000000
+DATA p256one<>+0x10(SB)/8, $0xffffffffffffffff
+DATA p256one<>+0x18(SB)/8, $0x00000000fffffffe
+GLOBL p256const0<>(SB), 8, $8
+GLOBL p256const1<>(SB), 8, $8
+GLOBL p256ordK0<>(SB), 8, $8
+GLOBL p256ord<>(SB), 8, $32
+GLOBL p256one<>(SB), 8, $32
+
+/* ---------------------------------------*/
+// func p256LittleToBig(res []byte, in []uint64)
+TEXT ·p256LittleToBig(SB),NOSPLIT,$0
+	JMP ·p256BigToLittle(SB)
+/* ---------------------------------------*/
+// func p256BigToLittle(res []uint64, in []byte)
+TEXT ·p256BigToLittle(SB),NOSPLIT,$0
+	MOVQ res+0(FP), res_ptr
+	MOVQ in+24(FP), x_ptr
+
+	MOVQ (8*0)(x_ptr), acc0
+	MOVQ (8*1)(x_ptr), acc1
+	MOVQ (8*2)(x_ptr), acc2
+	MOVQ (8*3)(x_ptr), acc3
+
+	BSWAPQ acc0
+	BSWAPQ acc1
+	BSWAPQ acc2
+	BSWAPQ acc3
+
+	MOVQ acc3, (8*0)(res_ptr)
+	MOVQ acc2, (8*1)(res_ptr)
+	MOVQ acc1, (8*2)(res_ptr)
+	MOVQ acc0, (8*3)(res_ptr)
+
+	RET
+/* ---------------------------------------*/
+// func p256MovCond(res, a, b []uint64, cond int)
+// If cond == 0 res=b, else res=a
+TEXT ·p256MovCond(SB),NOSPLIT,$0
+	MOVQ res+0(FP), res_ptr
+	MOVQ a+24(FP), x_ptr
+	MOVQ b+48(FP), y_ptr
+	MOVQ cond+72(FP), X12
+
+	PXOR X13, X13
+	PSHUFD $0, X12, X12
+	PCMPEQL X13, X12
+
+	MOVOU X12, X0
+	PANDN (16*0)(x_ptr), X0
+	MOVOU X12, X1
+	PANDN (16*1)(x_ptr), X1
+	MOVOU X12, X2
+	PANDN (16*2)(x_ptr), X2
+	MOVOU X12, X3
+	PANDN (16*3)(x_ptr), X3
+	MOVOU X12, X4
+	PANDN (16*4)(x_ptr), X4
+	MOVOU X12, X5
+	PANDN (16*5)(x_ptr), X5
+
+	MOVOU (16*0)(y_ptr), X6
+	MOVOU (16*1)(y_ptr), X7
+	MOVOU (16*2)(y_ptr), X8
+	MOVOU (16*3)(y_ptr), X9
+	MOVOU (16*4)(y_ptr), X10
+	MOVOU (16*5)(y_ptr), X11
+
+	PAND X12, X6
+	PAND X12, X7
+	PAND X12, X8
+	PAND X12, X9
+	PAND X12, X10
+	PAND X12, X11
+
+	PXOR X6, X0
+	PXOR X7, X1
+	PXOR X8, X2
+	PXOR X9, X3
+	PXOR X10, X4
+	PXOR X11, X5
+
+	MOVOU X0, (16*0)(res_ptr)
+	MOVOU X1, (16*1)(res_ptr)
+	MOVOU X2, (16*2)(res_ptr)
+	MOVOU X3, (16*3)(res_ptr)
+	MOVOU X4, (16*4)(res_ptr)
+	MOVOU X5, (16*5)(res_ptr)
+
+	RET
+/* ---------------------------------------*/
+// func p256NegCond(val []uint64, cond int)
+TEXT ·p256NegCond(SB),NOSPLIT,$0
+	MOVQ val+0(FP), res_ptr
+	MOVQ cond+24(FP), t0
+	// acc = poly
+	MOVQ $-1, acc0
+	MOVQ p256const0<>(SB), acc1
+	MOVQ $0, acc2
+	MOVQ p256const1<>(SB), acc3
+	// Load the original value
+	MOVQ (8*0)(res_ptr), acc5
+	MOVQ (8*1)(res_ptr), x_ptr
+	MOVQ (8*2)(res_ptr), y_ptr
+	MOVQ (8*3)(res_ptr), t1
+	// Speculatively subtract
+	SUBQ acc5, acc0
+	SBBQ x_ptr, acc1
+	SBBQ y_ptr, acc2
+	SBBQ t1, acc3
+	// If condition is 0, keep original value
+	TESTQ t0, t0
+	CMOVQEQ acc5, acc0
+	CMOVQEQ x_ptr, acc1
+	CMOVQEQ y_ptr, acc2
+	CMOVQEQ t1, acc3
+	// Store result
+	MOVQ acc0, (8*0)(res_ptr)
+	MOVQ acc1, (8*1)(res_ptr)
+	MOVQ acc2, (8*2)(res_ptr)
+	MOVQ acc3, (8*3)(res_ptr)
+
+	RET
+/* ---------------------------------------*/
+// func p256Sqr(res, in []uint64)
+TEXT ·p256Sqr(SB),NOSPLIT,$0
+	MOVQ res+0(FP), res_ptr
+	MOVQ in+24(FP), x_ptr
+	// y[1:] * y[0]
+	MOVQ (8*0)(x_ptr), t0
+
+	MOVQ (8*1)(x_ptr), AX
+	MULQ t0
+	MOVQ AX, acc1
+	MOVQ DX, acc2
+
+	MOVQ (8*2)(x_ptr), AX
+	MULQ t0
+	ADDQ AX, acc2
+	ADCQ $0, DX
+	MOVQ DX, acc3
+
+	MOVQ (8*3)(x_ptr), AX
+	MULQ t0
+	ADDQ AX, acc3
+	ADCQ $0, DX
+	MOVQ DX, acc4
+	// y[2:] * y[1]
+	MOVQ (8*1)(x_ptr), t0
+
+	MOVQ (8*2)(x_ptr), AX
+	MULQ t0
+	ADDQ AX, acc3
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ (8*3)(x_ptr), AX
+	MULQ t0
+	ADDQ t1, acc4
+	ADCQ $0, DX
+	ADDQ AX, acc4
+	ADCQ $0, DX
+	MOVQ DX, acc5
+	// y[3] * y[2]
+	MOVQ (8*2)(x_ptr), t0
+
+	MOVQ (8*3)(x_ptr), AX
+	MULQ t0
+	ADDQ AX, acc5
+	ADCQ $0, DX
+	MOVQ DX, y_ptr
+	XORQ t1, t1
+	// *2
+	ADDQ acc1, acc1
+	ADCQ acc2, acc2
+	ADCQ acc3, acc3
+	ADCQ acc4, acc4
+	ADCQ acc5, acc5
+	ADCQ y_ptr, y_ptr
+	ADCQ $0, t1
+	// Missing products
+	MOVQ (8*0)(x_ptr), AX
+	MULQ AX
+	MOVQ AX, acc0
+	MOVQ DX, t0
+
+	MOVQ (8*1)(x_ptr), AX
+	MULQ AX
+	ADDQ t0, acc1
+	ADCQ AX, acc2
+	ADCQ $0, DX
+	MOVQ DX, t0
+
+	MOVQ (8*2)(x_ptr), AX
+	MULQ AX
+	ADDQ t0, acc3
+	ADCQ AX, acc4
+	ADCQ $0, DX
+	MOVQ DX, t0
+
+	MOVQ (8*3)(x_ptr), AX
+	MULQ AX
+	ADDQ t0, acc5
+	ADCQ AX, y_ptr
+	ADCQ DX, t1
+	MOVQ t1, x_ptr
+	// First reduction step
+	MOVQ acc0, AX
+	MOVQ acc0, t1
+	SHLQ $32, acc0
+	MULQ p256const1<>(SB)
+	SHRQ $32, t1
+	ADDQ acc0, acc1
+	ADCQ t1, acc2
+	ADCQ AX, acc3
+	ADCQ $0, DX
+	MOVQ DX, acc0
+	// Second reduction step
+	MOVQ acc1, AX
+	MOVQ acc1, t1
+	SHLQ $32, acc1
+	MULQ p256const1<>(SB)
+	SHRQ $32, t1
+	ADDQ acc1, acc2
+	ADCQ t1, acc3
+	ADCQ AX, acc0
+	ADCQ $0, DX
+	MOVQ DX, acc1
+	// Third reduction step
+	MOVQ acc2, AX
+	MOVQ acc2, t1
+	SHLQ $32, acc2
+	MULQ p256const1<>(SB)
+	SHRQ $32, t1
+	ADDQ acc2, acc3
+	ADCQ t1, acc0
+	ADCQ AX, acc1
+	ADCQ $0, DX
+	MOVQ DX, acc2
+	// Last reduction step
+	XORQ t0, t0
+	MOVQ acc3, AX
+	MOVQ acc3, t1
+	SHLQ $32, acc3
+	MULQ p256const1<>(SB)
+	SHRQ $32, t1
+	ADDQ acc3, acc0
+	ADCQ t1, acc1
+	ADCQ AX, acc2
+	ADCQ $0, DX
+	MOVQ DX, acc3
+	// Add bits [511:256] of the sqr result
+	ADCQ acc4, acc0
+	ADCQ acc5, acc1
+	ADCQ y_ptr, acc2
+	ADCQ x_ptr, acc3
+	ADCQ $0, t0
+
+	MOVQ acc0, acc4
+	MOVQ acc1, acc5
+	MOVQ acc2, y_ptr
+	MOVQ acc3, t1
+	// Subtract p256
+	SUBQ $-1, acc0
+	SBBQ p256const0<>(SB) ,acc1
+	SBBQ $0, acc2
+	SBBQ p256const1<>(SB), acc3
+	SBBQ $0, t0
+
+	CMOVQCS acc4, acc0
+	CMOVQCS acc5, acc1
+	CMOVQCS y_ptr, acc2
+	CMOVQCS t1, acc3
+
+	MOVQ acc0, (8*0)(res_ptr)
+	MOVQ acc1, (8*1)(res_ptr)
+	MOVQ acc2, (8*2)(res_ptr)
+	MOVQ acc3, (8*3)(res_ptr)
+
+	RET
+/* ---------------------------------------*/
+// func p256Mul(res, in1, in2 []uint64)
+TEXT ·p256Mul(SB),NOSPLIT,$0
+	MOVQ res+0(FP), res_ptr
+	MOVQ in1+24(FP), x_ptr
+	MOVQ in2+48(FP), y_ptr
+	// x * y[0]
+	MOVQ (8*0)(y_ptr), t0
+
+	MOVQ (8*0)(x_ptr), AX
+	MULQ t0
+	MOVQ AX, acc0
+	MOVQ DX, acc1
+
+	MOVQ (8*1)(x_ptr), AX
+	MULQ t0
+	ADDQ AX, acc1
+	ADCQ $0, DX
+	MOVQ DX, acc2
+
+	MOVQ (8*2)(x_ptr), AX
+	MULQ t0
+	ADDQ AX, acc2
+	ADCQ $0, DX
+	MOVQ DX, acc3
+
+	MOVQ (8*3)(x_ptr), AX
+	MULQ t0
+	ADDQ AX, acc3
+	ADCQ $0, DX
+	MOVQ DX, acc4
+	XORQ acc5, acc5
+	// First reduction step
+	MOVQ acc0, AX
+	MOVQ acc0, t1
+	SHLQ $32, acc0
+	MULQ p256const1<>(SB)
+	SHRQ $32, t1
+	ADDQ acc0, acc1
+	ADCQ t1, acc2
+	ADCQ AX, acc3
+	ADCQ DX, acc4
+	ADCQ $0, acc5
+	XORQ acc0, acc0
+	// x * y[1]
+	MOVQ (8*1)(y_ptr), t0
+
+	MOVQ (8*0)(x_ptr), AX
+	MULQ t0
+	ADDQ AX, acc1
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ (8*1)(x_ptr), AX
+	MULQ t0
+	ADDQ t1, acc2
+	ADCQ $0, DX
+	ADDQ AX, acc2
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ (8*2)(x_ptr), AX
+	MULQ t0
+	ADDQ t1, acc3
+	ADCQ $0, DX
+	ADDQ AX, acc3
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ (8*3)(x_ptr), AX
+	MULQ t0
+	ADDQ t1, acc4
+	ADCQ $0, DX
+	ADDQ AX, acc4
+	ADCQ DX, acc5
+	ADCQ $0, acc0
+	// Second reduction step
+	MOVQ acc1, AX
+	MOVQ acc1, t1
+	SHLQ $32, acc1
+	MULQ p256const1<>(SB)
+	SHRQ $32, t1
+	ADDQ acc1, acc2
+	ADCQ t1, acc3
+	ADCQ AX, acc4
+	ADCQ DX, acc5
+	ADCQ $0, acc0
+	XORQ acc1, acc1
+	// x * y[2]
+	MOVQ (8*2)(y_ptr), t0
+
+	MOVQ (8*0)(x_ptr), AX
+	MULQ t0
+	ADDQ AX, acc2
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ (8*1)(x_ptr), AX
+	MULQ t0
+	ADDQ t1, acc3
+	ADCQ $0, DX
+	ADDQ AX, acc3
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ (8*2)(x_ptr), AX
+	MULQ t0
+	ADDQ t1, acc4
+	ADCQ $0, DX
+	ADDQ AX, acc4
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ (8*3)(x_ptr), AX
+	MULQ t0
+	ADDQ t1, acc5
+	ADCQ $0, DX
+	ADDQ AX, acc5
+	ADCQ DX, acc0
+	ADCQ $0, acc1
+	// Third reduction step
+	MOVQ acc2, AX
+	MOVQ acc2, t1
+	SHLQ $32, acc2
+	MULQ p256const1<>(SB)
+	SHRQ $32, t1
+	ADDQ acc2, acc3
+	ADCQ t1, acc4
+	ADCQ AX, acc5
+	ADCQ DX, acc0
+	ADCQ $0, acc1
+	XORQ acc2, acc2
+	// x * y[3]
+	MOVQ (8*3)(y_ptr), t0
+
+	MOVQ (8*0)(x_ptr), AX
+	MULQ t0
+	ADDQ AX, acc3
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ (8*1)(x_ptr), AX
+	MULQ t0
+	ADDQ t1, acc4
+	ADCQ $0, DX
+	ADDQ AX, acc4
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ (8*2)(x_ptr), AX
+	MULQ t0
+	ADDQ t1, acc5
+	ADCQ $0, DX
+	ADDQ AX, acc5
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ (8*3)(x_ptr), AX
+	MULQ t0
+	ADDQ t1, acc0
+	ADCQ $0, DX
+	ADDQ AX, acc0
+	ADCQ DX, acc1
+	ADCQ $0, acc2
+	// Last reduction step
+	MOVQ acc3, AX
+	MOVQ acc3, t1
+	SHLQ $32, acc3
+	MULQ p256const1<>(SB)
+	SHRQ $32, t1
+	ADDQ acc3, acc4
+	ADCQ t1, acc5
+	ADCQ AX, acc0
+	ADCQ DX, acc1
+	ADCQ $0, acc2
+	// Copy result [255:0]
+	MOVQ acc4, x_ptr
+	MOVQ acc5, acc3
+	MOVQ acc0, t0
+	MOVQ acc1, t1
+	// Subtract p256
+	SUBQ $-1, acc4
+	SBBQ p256const0<>(SB) ,acc5
+	SBBQ $0, acc0
+	SBBQ p256const1<>(SB), acc1
+	SBBQ $0, acc2
+
+	CMOVQCS x_ptr, acc4
+	CMOVQCS acc3, acc5
+	CMOVQCS t0, acc0
+	CMOVQCS t1, acc1
+
+	MOVQ acc4, (8*0)(res_ptr)
+	MOVQ acc5, (8*1)(res_ptr)
+	MOVQ acc0, (8*2)(res_ptr)
+	MOVQ acc1, (8*3)(res_ptr)
+
+	RET
+/* ---------------------------------------*/
+// func p256FromMont(res, in []uint64)
+TEXT ·p256FromMont(SB),NOSPLIT,$0
+	MOVQ res+0(FP), res_ptr
+	MOVQ in+24(FP), x_ptr
+
+	MOVQ (8*0)(x_ptr), acc0
+	MOVQ (8*1)(x_ptr), acc1
+	MOVQ (8*2)(x_ptr), acc2
+	MOVQ (8*3)(x_ptr), acc3
+	XORQ acc4, acc4
+
+	// Only reduce, no multiplications are needed
+	// First stage
+	MOVQ acc0, AX
+	MOVQ acc0, t1
+	SHLQ $32, acc0
+	MULQ p256const1<>(SB)
+	SHRQ $32, t1
+	ADDQ acc0, acc1
+	ADCQ t1, acc2
+	ADCQ AX, acc3
+	ADCQ DX, acc4
+	XORQ acc5, acc5
+	// Second stage
+	MOVQ acc1, AX
+	MOVQ acc1, t1
+	SHLQ $32, acc1
+	MULQ p256const1<>(SB)
+	SHRQ $32, t1
+	ADDQ acc1, acc2
+	ADCQ t1, acc3
+	ADCQ AX, acc4
+	ADCQ DX, acc5
+	XORQ acc0, acc0
+	// Third stage
+	MOVQ acc2, AX
+	MOVQ acc2, t1
+	SHLQ $32, acc2
+	MULQ p256const1<>(SB)
+	SHRQ $32, t1
+	ADDQ acc2, acc3
+	ADCQ t1, acc4
+	ADCQ AX, acc5
+	ADCQ DX, acc0
+	XORQ acc1, acc1
+	// Last stage
+	MOVQ acc3, AX
+	MOVQ acc3, t1
+	SHLQ $32, acc3
+	MULQ p256const1<>(SB)
+	SHRQ $32, t1
+	ADDQ acc3, acc4
+	ADCQ t1, acc5
+	ADCQ AX, acc0
+	ADCQ DX, acc1
+
+	MOVQ acc4, x_ptr
+	MOVQ acc5, acc3
+	MOVQ acc0, t0
+	MOVQ acc1, t1
+
+	SUBQ $-1, acc4
+	SBBQ p256const0<>(SB), acc5
+	SBBQ $0, acc0
+	SBBQ p256const1<>(SB), acc1
+
+	CMOVQCS x_ptr, acc4
+	CMOVQCS acc3, acc5
+	CMOVQCS t0, acc0
+	CMOVQCS t1, acc1
+
+	MOVQ acc4, (8*0)(res_ptr)
+	MOVQ acc5, (8*1)(res_ptr)
+	MOVQ acc0, (8*2)(res_ptr)
+	MOVQ acc1, (8*3)(res_ptr)
+
+	RET
+/* ---------------------------------------*/
+// Constant time point access to arbitrary point table.
+// Indexed from 1 to 15, with -1 offset
+// (index 0 is implicitly point at infinity)
+// func p256Select(point, table []uint64, idx int)
+TEXT ·p256Select(SB),NOSPLIT,$0
+	MOVQ idx+48(FP),AX
+	MOVQ table+24(FP),DI
+	MOVQ point+0(FP),DX
+
+	PXOR X15, X15	// X15 = 0
+	PCMPEQL X14, X14 // X14 = -1
+	PSUBL X14, X15   // X15 = 1
+	MOVL AX, X14
+	PSHUFD $0, X14, X14
+
+	PXOR X0, X0
+	PXOR X1, X1
+	PXOR X2, X2
+	PXOR X3, X3
+	PXOR X4, X4
+	PXOR X5, X5
+	MOVQ $16, AX
+
+	MOVOU X15, X13
+
+loop_select:
+
+		MOVOU X13, X12
+		PADDL X15, X13
+		PCMPEQL X14, X12
+
+		MOVOU (16*0)(DI), X6
+		MOVOU (16*1)(DI), X7
+		MOVOU (16*2)(DI), X8
+		MOVOU (16*3)(DI), X9
+		MOVOU (16*4)(DI), X10
+		MOVOU (16*5)(DI), X11
+		ADDQ $(16*6), DI
+
+		PAND X12, X6
+		PAND X12, X7
+		PAND X12, X8
+		PAND X12, X9
+		PAND X12, X10
+		PAND X12, X11
+
+		PXOR X6, X0
+		PXOR X7, X1
+		PXOR X8, X2
+		PXOR X9, X3
+		PXOR X10, X4
+		PXOR X11, X5
+
+		DECQ AX
+		JNE loop_select
+
+	MOVOU X0, (16*0)(DX)
+	MOVOU X1, (16*1)(DX)
+	MOVOU X2, (16*2)(DX)
+	MOVOU X3, (16*3)(DX)
+	MOVOU X4, (16*4)(DX)
+	MOVOU X5, (16*5)(DX)
+
+	RET
+/* ---------------------------------------*/
+// Constant time point access to base point table.
+// func p256SelectBase(point, table []uint64, idx int)
+TEXT ·p256SelectBase(SB),NOSPLIT,$0
+	MOVQ idx+48(FP),AX
+	MOVQ table+24(FP),DI
+	MOVQ point+0(FP),DX
+
+	PXOR X15, X15	// X15 = 0
+	PCMPEQL X14, X14 // X14 = -1
+	PSUBL X14, X15   // X15 = 1
+	MOVL AX, X14
+	PSHUFD $0, X14, X14
+
+	PXOR X0, X0
+	PXOR X1, X1
+	PXOR X2, X2
+	PXOR X3, X3
+	MOVQ $32, AX
+
+	MOVOU X15, X13
+
+loop_select_base:
+
+		MOVOU X13, X12
+		PADDL X15, X13
+		PCMPEQL X14, X12
+
+		MOVOU (16*0)(DI), X4
+		MOVOU (16*1)(DI), X5
+		MOVOU (16*2)(DI), X6
+		MOVOU (16*3)(DI), X7
+
+		MOVOU (16*4)(DI), X8
+		MOVOU (16*5)(DI), X9
+		MOVOU (16*6)(DI), X10
+		MOVOU (16*7)(DI), X11
+
+		ADDQ $(16*8), DI
+
+		PAND X12, X4
+		PAND X12, X5
+		PAND X12, X6
+		PAND X12, X7
+
+		MOVOU X13, X12
+		PADDL X15, X13
+		PCMPEQL X14, X12
+
+		PAND X12, X8
+		PAND X12, X9
+		PAND X12, X10
+		PAND X12, X11
+
+		PXOR X4, X0
+		PXOR X5, X1
+		PXOR X6, X2
+		PXOR X7, X3
+
+		PXOR X8, X0
+		PXOR X9, X1
+		PXOR X10, X2
+		PXOR X11, X3
+
+		DECQ AX
+		JNE loop_select_base
+
+	MOVOU X0, (16*0)(DX)
+	MOVOU X1, (16*1)(DX)
+	MOVOU X2, (16*2)(DX)
+	MOVOU X3, (16*3)(DX)
+
+	RET
+/* ---------------------------------------*/
+// func p256OrdMul(res, in1, in2 []uint64)
+TEXT ·p256OrdMul(SB),NOSPLIT,$0
+	MOVQ res+0(FP), res_ptr
+	MOVQ in1+24(FP), x_ptr
+	MOVQ in2+48(FP), y_ptr
+	// x * y[0]
+	MOVQ (8*0)(y_ptr), t0
+
+	MOVQ (8*0)(x_ptr), AX
+	MULQ t0
+	MOVQ AX, acc0
+	MOVQ DX, acc1
+
+	MOVQ (8*1)(x_ptr), AX
+	MULQ t0
+	ADDQ AX, acc1
+	ADCQ $0, DX
+	MOVQ DX, acc2
+
+	MOVQ (8*2)(x_ptr), AX
+	MULQ t0
+	ADDQ AX, acc2
+	ADCQ $0, DX
+	MOVQ DX, acc3
+
+	MOVQ (8*3)(x_ptr), AX
+	MULQ t0
+	ADDQ AX, acc3
+	ADCQ $0, DX
+	MOVQ DX, acc4
+	XORQ acc5, acc5
+	// First reduction step
+	MOVQ acc0, AX
+	MULQ p256ordK0<>(SB)
+	MOVQ AX, t0
+
+	MOVQ p256ord<>+0x00(SB), AX
+	MULQ t0
+	ADDQ AX, acc0
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ p256ord<>+0x08(SB), AX
+	MULQ t0
+	ADDQ t1, acc1
+	ADCQ $0, DX
+	ADDQ AX, acc1
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ p256ord<>+0x10(SB), AX
+	MULQ t0
+	ADDQ t1, acc2
+	ADCQ $0, DX
+	ADDQ AX, acc2
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ p256ord<>+0x18(SB), AX
+	MULQ t0
+	ADDQ t1, acc3
+	ADCQ $0, DX
+	ADDQ AX, acc3
+	ADCQ DX, acc4
+	ADCQ $0, acc5
+	// x * y[1]
+	MOVQ (8*1)(y_ptr), t0
+
+	MOVQ (8*0)(x_ptr), AX
+	MULQ t0
+	ADDQ AX, acc1
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ (8*1)(x_ptr), AX
+	MULQ t0
+	ADDQ t1, acc2
+	ADCQ $0, DX
+	ADDQ AX, acc2
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ (8*2)(x_ptr), AX
+	MULQ t0
+	ADDQ t1, acc3
+	ADCQ $0, DX
+	ADDQ AX, acc3
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ (8*3)(x_ptr), AX
+	MULQ t0
+	ADDQ t1, acc4
+	ADCQ $0, DX
+	ADDQ AX, acc4
+	ADCQ DX, acc5
+	ADCQ $0, acc0
+	// Second reduction step
+	MOVQ acc1, AX
+	MULQ p256ordK0<>(SB)
+	MOVQ AX, t0
+
+	MOVQ p256ord<>+0x00(SB), AX
+	MULQ t0
+	ADDQ AX, acc1
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ p256ord<>+0x08(SB), AX
+	MULQ t0
+	ADDQ t1, acc2
+	ADCQ $0, DX
+	ADDQ AX, acc2
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ p256ord<>+0x10(SB), AX
+	MULQ t0
+	ADDQ t1, acc3
+	ADCQ $0, DX
+	ADDQ AX, acc3
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ p256ord<>+0x18(SB), AX
+	MULQ t0
+	ADDQ t1, acc4
+	ADCQ $0, DX
+	ADDQ AX, acc4
+	ADCQ DX, acc5
+	ADCQ $0, acc0
+	// x * y[2]
+	MOVQ (8*2)(y_ptr), t0
+
+	MOVQ (8*0)(x_ptr), AX
+	MULQ t0
+	ADDQ AX, acc2
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ (8*1)(x_ptr), AX
+	MULQ t0
+	ADDQ t1, acc3
+	ADCQ $0, DX
+	ADDQ AX, acc3
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ (8*2)(x_ptr), AX
+	MULQ t0
+	ADDQ t1, acc4
+	ADCQ $0, DX
+	ADDQ AX, acc4
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ (8*3)(x_ptr), AX
+	MULQ t0
+	ADDQ t1, acc5
+	ADCQ $0, DX
+	ADDQ AX, acc5
+	ADCQ DX, acc0
+	ADCQ $0, acc1
+	// Third reduction step
+	MOVQ acc2, AX
+	MULQ p256ordK0<>(SB)
+	MOVQ AX, t0
+
+	MOVQ p256ord<>+0x00(SB), AX
+	MULQ t0
+	ADDQ AX, acc2
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ p256ord<>+0x08(SB), AX
+	MULQ t0
+	ADDQ t1, acc3
+	ADCQ $0, DX
+	ADDQ AX, acc3
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ p256ord<>+0x10(SB), AX
+	MULQ t0
+	ADDQ t1, acc4
+	ADCQ $0, DX
+	ADDQ AX, acc4
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ p256ord<>+0x18(SB), AX
+	MULQ t0
+	ADDQ t1, acc5
+	ADCQ $0, DX
+	ADDQ AX, acc5
+	ADCQ DX, acc0
+	ADCQ $0, acc1
+	// x * y[3]
+	MOVQ (8*3)(y_ptr), t0
+
+	MOVQ (8*0)(x_ptr), AX
+	MULQ t0
+	ADDQ AX, acc3
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ (8*1)(x_ptr), AX
+	MULQ t0
+	ADDQ t1, acc4
+	ADCQ $0, DX
+	ADDQ AX, acc4
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ (8*2)(x_ptr), AX
+	MULQ t0
+	ADDQ t1, acc5
+	ADCQ $0, DX
+	ADDQ AX, acc5
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ (8*3)(x_ptr), AX
+	MULQ t0
+	ADDQ t1, acc0
+	ADCQ $0, DX
+	ADDQ AX, acc0
+	ADCQ DX, acc1
+	ADCQ $0, acc2
+	// Last reduction step
+	MOVQ acc3, AX
+	MULQ p256ordK0<>(SB)
+	MOVQ AX, t0
+
+	MOVQ p256ord<>+0x00(SB), AX
+	MULQ t0
+	ADDQ AX, acc3
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ p256ord<>+0x08(SB), AX
+	MULQ t0
+	ADDQ t1, acc4
+	ADCQ $0, DX
+	ADDQ AX, acc4
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ p256ord<>+0x10(SB), AX
+	MULQ t0
+	ADDQ t1, acc5
+	ADCQ $0, DX
+	ADDQ AX, acc5
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ p256ord<>+0x18(SB), AX
+	MULQ t0
+	ADDQ t1, acc0
+	ADCQ $0, DX
+	ADDQ AX, acc0
+	ADCQ DX, acc1
+	ADCQ $0, acc2
+	// Copy result [255:0]
+	MOVQ acc4, x_ptr
+	MOVQ acc5, acc3
+	MOVQ acc0, t0
+	MOVQ acc1, t1
+	// Subtract p256
+	SUBQ p256ord<>+0x00(SB), acc4
+	SBBQ p256ord<>+0x08(SB) ,acc5
+	SBBQ p256ord<>+0x10(SB), acc0
+	SBBQ p256ord<>+0x18(SB), acc1
+	SBBQ $0, acc2
+
+	CMOVQCS x_ptr, acc4
+	CMOVQCS acc3, acc5
+	CMOVQCS t0, acc0
+	CMOVQCS t1, acc1
+
+	MOVQ acc4, (8*0)(res_ptr)
+	MOVQ acc5, (8*1)(res_ptr)
+	MOVQ acc0, (8*2)(res_ptr)
+	MOVQ acc1, (8*3)(res_ptr)
+
+	RET
+/* ---------------------------------------*/
+// func p256OrdSqr(res, in []uint64, n int)
+TEXT ·p256OrdSqr(SB),NOSPLIT,$0
+	MOVQ res+0(FP), res_ptr
+	MOVQ in+24(FP), x_ptr
+	MOVQ n+48(FP), BX
+
+ordSqrLoop:
+
+	// y[1:] * y[0]
+	MOVQ (8*0)(x_ptr), t0
+
+	MOVQ (8*1)(x_ptr), AX
+	MULQ t0
+	MOVQ AX, acc1
+	MOVQ DX, acc2
+
+	MOVQ (8*2)(x_ptr), AX
+	MULQ t0
+	ADDQ AX, acc2
+	ADCQ $0, DX
+	MOVQ DX, acc3
+
+	MOVQ (8*3)(x_ptr), AX
+	MULQ t0
+	ADDQ AX, acc3
+	ADCQ $0, DX
+	MOVQ DX, acc4
+	// y[2:] * y[1]
+	MOVQ (8*1)(x_ptr), t0
+
+	MOVQ (8*2)(x_ptr), AX
+	MULQ t0
+	ADDQ AX, acc3
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ (8*3)(x_ptr), AX
+	MULQ t0
+	ADDQ t1, acc4
+	ADCQ $0, DX
+	ADDQ AX, acc4
+	ADCQ $0, DX
+	MOVQ DX, acc5
+	// y[3] * y[2]
+	MOVQ (8*2)(x_ptr), t0
+
+	MOVQ (8*3)(x_ptr), AX
+	MULQ t0
+	ADDQ AX, acc5
+	ADCQ $0, DX
+	MOVQ DX, y_ptr
+	XORQ t1, t1
+	// *2
+	ADDQ acc1, acc1
+	ADCQ acc2, acc2
+	ADCQ acc3, acc3
+	ADCQ acc4, acc4
+	ADCQ acc5, acc5
+	ADCQ y_ptr, y_ptr
+	ADCQ $0, t1
+	// Missing products
+	MOVQ (8*0)(x_ptr), AX
+	MULQ AX
+	MOVQ AX, acc0
+	MOVQ DX, t0
+
+	MOVQ (8*1)(x_ptr), AX
+	MULQ AX
+	ADDQ t0, acc1
+	ADCQ AX, acc2
+	ADCQ $0, DX
+	MOVQ DX, t0
+
+	MOVQ (8*2)(x_ptr), AX
+	MULQ AX
+	ADDQ t0, acc3
+	ADCQ AX, acc4
+	ADCQ $0, DX
+	MOVQ DX, t0
+
+	MOVQ (8*3)(x_ptr), AX
+	MULQ AX
+	ADDQ t0, acc5
+	ADCQ AX, y_ptr
+	ADCQ DX, t1
+	MOVQ t1, x_ptr
+	// First reduction step
+	MOVQ acc0, AX
+	MULQ p256ordK0<>(SB)
+	MOVQ AX, t0
+
+	MOVQ p256ord<>+0x00(SB), AX
+	MULQ t0
+	ADDQ AX, acc0
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ p256ord<>+0x08(SB), AX
+	MULQ t0
+	ADDQ t1, acc1
+	ADCQ $0, DX
+	ADDQ AX, acc1
+
+	MOVQ t0, t1
+	ADCQ DX, acc2
+	ADCQ $0, t1
+	SUBQ t0, acc2
+	SBBQ $0, t1
+
+	MOVQ t0, AX
+	MOVQ t0, DX
+	MOVQ t0, acc0
+	SHLQ $32, AX
+	SHRQ $32, DX
+
+	ADDQ t1, acc3
+	ADCQ $0, acc0
+	SUBQ AX, acc3
+	SBBQ DX, acc0
+	// Second reduction step
+	MOVQ acc1, AX
+	MULQ p256ordK0<>(SB)
+	MOVQ AX, t0
+
+	MOVQ p256ord<>+0x00(SB), AX
+	MULQ t0
+	ADDQ AX, acc1
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ p256ord<>+0x08(SB), AX
+	MULQ t0
+	ADDQ t1, acc2
+	ADCQ $0, DX
+	ADDQ AX, acc2
+
+	MOVQ t0, t1
+	ADCQ DX, acc3
+	ADCQ $0, t1
+	SUBQ t0, acc3
+	SBBQ $0, t1
+
+	MOVQ t0, AX
+	MOVQ t0, DX
+	MOVQ t0, acc1
+	SHLQ $32, AX
+	SHRQ $32, DX
+
+	ADDQ t1, acc0
+	ADCQ $0, acc1
+	SUBQ AX, acc0
+	SBBQ DX, acc1
+	// Third reduction step
+	MOVQ acc2, AX
+	MULQ p256ordK0<>(SB)
+	MOVQ AX, t0
+
+	MOVQ p256ord<>+0x00(SB), AX
+	MULQ t0
+	ADDQ AX, acc2
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ p256ord<>+0x08(SB), AX
+	MULQ t0
+	ADDQ t1, acc3
+	ADCQ $0, DX
+	ADDQ AX, acc3
+
+	MOVQ t0, t1
+	ADCQ DX, acc0
+	ADCQ $0, t1
+	SUBQ t0, acc0
+	SBBQ $0, t1
+
+	MOVQ t0, AX
+	MOVQ t0, DX
+	MOVQ t0, acc2
+	SHLQ $32, AX
+	SHRQ $32, DX
+
+	ADDQ t1, acc1
+	ADCQ $0, acc2
+	SUBQ AX, acc1
+	SBBQ DX, acc2
+	// Last reduction step
+	MOVQ acc3, AX
+	MULQ p256ordK0<>(SB)
+	MOVQ AX, t0
+
+	MOVQ p256ord<>+0x00(SB), AX
+	MULQ t0
+	ADDQ AX, acc3
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ p256ord<>+0x08(SB), AX
+	MULQ t0
+	ADDQ t1, acc0
+	ADCQ $0, DX
+	ADDQ AX, acc0
+	ADCQ $0, DX
+	MOVQ DX, t1
+
+	MOVQ t0, t1
+	ADCQ DX, acc1
+	ADCQ $0, t1
+	SUBQ t0, acc1
+	SBBQ $0, t1
+
+	MOVQ t0, AX
+	MOVQ t0, DX
+	MOVQ t0, acc3
+	SHLQ $32, AX
+	SHRQ $32, DX
+
+	ADDQ t1, acc2
+	ADCQ $0, acc3
+	SUBQ AX, acc2
+	SBBQ DX, acc3
+	XORQ t0, t0
+	// Add bits [511:256] of the sqr result
+	ADCQ acc4, acc0
+	ADCQ acc5, acc1
+	ADCQ y_ptr, acc2
+	ADCQ x_ptr, acc3
+	ADCQ $0, t0
+
+	MOVQ acc0, acc4
+	MOVQ acc1, acc5
+	MOVQ acc2, y_ptr
+	MOVQ acc3, t1
+	// Subtract p256
+	SUBQ p256ord<>+0x00(SB), acc0
+	SBBQ p256ord<>+0x08(SB) ,acc1
+	SBBQ p256ord<>+0x10(SB), acc2
+	SBBQ p256ord<>+0x18(SB), acc3
+	SBBQ $0, t0
+
+	CMOVQCS acc4, acc0
+	CMOVQCS acc5, acc1
+	CMOVQCS y_ptr, acc2
+	CMOVQCS t1, acc3
+
+	MOVQ acc0, (8*0)(res_ptr)
+	MOVQ acc1, (8*1)(res_ptr)
+	MOVQ acc2, (8*2)(res_ptr)
+	MOVQ acc3, (8*3)(res_ptr)
+	MOVQ res_ptr, x_ptr
+	DECQ BX
+	JNE ordSqrLoop
+
+	RET
+/* ---------------------------------------*/
+#undef res_ptr
+#undef x_ptr
+#undef y_ptr
+
+#undef acc0
+#undef acc1
+#undef acc2
+#undef acc3
+#undef acc4
+#undef acc5
+#undef t0
+#undef t1
+/* ---------------------------------------*/
+#define mul0 AX
+#define mul1 DX
+#define acc0 BX
+#define acc1 CX
+#define acc2 R8
+#define acc3 R9
+#define acc4 R10
+#define acc5 R11
+#define acc6 R12
+#define acc7 R13
+#define t0 R14
+#define t1 R15
+#define t2 DI
+#define t3 SI
+#define hlp BP
+/* ---------------------------------------*/
+TEXT p256SubInternal(SB),NOSPLIT,$0
+	XORQ mul0, mul0
+	SUBQ t0, acc4
+	SBBQ t1, acc5
+	SBBQ t2, acc6
+	SBBQ t3, acc7
+	SBBQ $0, mul0
+
+	MOVQ acc4, acc0
+	MOVQ acc5, acc1
+	MOVQ acc6, acc2
+	MOVQ acc7, acc3
+
+	ADDQ $-1, acc4
+	ADCQ p256const0<>(SB), acc5
+	ADCQ $0, acc6
+	ADCQ p256const1<>(SB), acc7
+	ADCQ $0, mul0
+
+	CMOVQNE acc0, acc4
+	CMOVQNE acc1, acc5
+	CMOVQNE acc2, acc6
+	CMOVQNE acc3, acc7
+
+	RET
+/* ---------------------------------------*/
+TEXT p256MulInternal(SB),NOSPLIT,$0
+	MOVQ acc4, mul0
+	MULQ t0
+	MOVQ mul0, acc0
+	MOVQ mul1, acc1
+
+	MOVQ acc4, mul0
+	MULQ t1
+	ADDQ mul0, acc1
+	ADCQ $0, mul1
+	MOVQ mul1, acc2
+
+	MOVQ acc4, mul0
+	MULQ t2
+	ADDQ mul0, acc2
+	ADCQ $0, mul1
+	MOVQ mul1, acc3
+
+	MOVQ acc4, mul0
+	MULQ t3
+	ADDQ mul0, acc3
+	ADCQ $0, mul1
+	MOVQ mul1, acc4
+
+	MOVQ acc5, mul0
+	MULQ t0
+	ADDQ mul0, acc1
+	ADCQ $0, mul1
+	MOVQ mul1, hlp
+
+	MOVQ acc5, mul0
+	MULQ t1
+	ADDQ hlp, acc2
+	ADCQ $0, mul1
+	ADDQ mul0, acc2
+	ADCQ $0, mul1
+	MOVQ mul1, hlp
+
+	MOVQ acc5, mul0
+	MULQ t2
+	ADDQ hlp, acc3
+	ADCQ $0, mul1
+	ADDQ mul0, acc3
+	ADCQ $0, mul1
+	MOVQ mul1, hlp
+
+	MOVQ acc5, mul0
+	MULQ t3
+	ADDQ hlp, acc4
+	ADCQ $0, mul1
+	ADDQ mul0, acc4
+	ADCQ $0, mul1
+	MOVQ mul1, acc5
+
+	MOVQ acc6, mul0
+	MULQ t0
+	ADDQ mul0, acc2
+	ADCQ $0, mul1
+	MOVQ mul1, hlp
+
+	MOVQ acc6, mul0
+	MULQ t1
+	ADDQ hlp, acc3
+	ADCQ $0, mul1
+	ADDQ mul0, acc3
+	ADCQ $0, mul1
+	MOVQ mul1, hlp
+
+	MOVQ acc6, mul0
+	MULQ t2
+	ADDQ hlp, acc4
+	ADCQ $0, mul1
+	ADDQ mul0, acc4
+	ADCQ $0, mul1
+	MOVQ mul1, hlp
+
+	MOVQ acc6, mul0
+	MULQ t3
+	ADDQ hlp, acc5
+	ADCQ $0, mul1
+	ADDQ mul0, acc5
+	ADCQ $0, mul1
+	MOVQ mul1, acc6
+
+	MOVQ acc7, mul0
+	MULQ t0
+	ADDQ mul0, acc3
+	ADCQ $0, mul1
+	MOVQ mul1, hlp
+
+	MOVQ acc7, mul0
+	MULQ t1
+	ADDQ hlp, acc4
+	ADCQ $0, mul1
+	ADDQ mul0, acc4
+	ADCQ $0, mul1
+	MOVQ mul1, hlp
+
+	MOVQ acc7, mul0
+	MULQ t2
+	ADDQ hlp, acc5
+	ADCQ $0, mul1
+	ADDQ mul0, acc5
+	ADCQ $0, mul1
+	MOVQ mul1, hlp
+
+	MOVQ acc7, mul0
+	MULQ t3
+	ADDQ hlp, acc6
+	ADCQ $0, mul1
+	ADDQ mul0, acc6
+	ADCQ $0, mul1
+	MOVQ mul1, acc7
+	// First reduction step
+	MOVQ acc0, mul0
+	MOVQ acc0, hlp
+	SHLQ $32, acc0
+	MULQ p256const1<>(SB)
+	SHRQ $32, hlp
+	ADDQ acc0, acc1
+	ADCQ hlp, acc2
+	ADCQ mul0, acc3
+	ADCQ $0, mul1
+	MOVQ mul1, acc0
+	// Second reduction step
+	MOVQ acc1, mul0
+	MOVQ acc1, hlp
+	SHLQ $32, acc1
+	MULQ p256const1<>(SB)
+	SHRQ $32, hlp
+	ADDQ acc1, acc2
+	ADCQ hlp, acc3
+	ADCQ mul0, acc0
+	ADCQ $0, mul1
+	MOVQ mul1, acc1
+	// Third reduction step
+	MOVQ acc2, mul0
+	MOVQ acc2, hlp
+	SHLQ $32, acc2
+	MULQ p256const1<>(SB)
+	SHRQ $32, hlp
+	ADDQ acc2, acc3
+	ADCQ hlp, acc0
+	ADCQ mul0, acc1
+	ADCQ $0, mul1
+	MOVQ mul1, acc2
+	// Last reduction step
+	MOVQ acc3, mul0
+	MOVQ acc3, hlp
+	SHLQ $32, acc3
+	MULQ p256const1<>(SB)
+	SHRQ $32, hlp
+	ADDQ acc3, acc0
+	ADCQ hlp, acc1
+	ADCQ mul0, acc2
+	ADCQ $0, mul1
+	MOVQ mul1, acc3
+	BYTE $0x48; BYTE $0xc7; BYTE $0xc5; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00   // MOVQ $0, BP
+	// Add bits [511:256] of the result
+	ADCQ acc0, acc4
+	ADCQ acc1, acc5
+	ADCQ acc2, acc6
+	ADCQ acc3, acc7
+	ADCQ $0, hlp
+	// Copy result
+	MOVQ acc4, acc0
+	MOVQ acc5, acc1
+	MOVQ acc6, acc2
+	MOVQ acc7, acc3
+	// Subtract p256
+	SUBQ $-1, acc4
+	SBBQ p256const0<>(SB) ,acc5
+	SBBQ $0, acc6
+	SBBQ p256const1<>(SB), acc7
+	SBBQ $0, hlp
+	// If the result of the subtraction is negative, restore the previous result
+	CMOVQCS acc0, acc4
+	CMOVQCS acc1, acc5
+	CMOVQCS acc2, acc6
+	CMOVQCS acc3, acc7
+
+	RET
+/* ---------------------------------------*/
+TEXT p256SqrInternal(SB),NOSPLIT,$0
+
+	MOVQ acc4, mul0
+	MULQ acc5
+	MOVQ mul0, acc1
+	MOVQ mul1, acc2
+
+	MOVQ acc4, mul0
+	MULQ acc6
+	ADDQ mul0, acc2
+	ADCQ $0, mul1
+	MOVQ mul1, acc3
+
+	MOVQ acc4, mul0
+	MULQ acc7
+	ADDQ mul0, acc3
+	ADCQ $0, mul1
+	MOVQ mul1, t0
+
+	MOVQ acc5, mul0
+	MULQ acc6
+	ADDQ mul0, acc3
+	ADCQ $0, mul1
+	MOVQ mul1, hlp
+
+	MOVQ acc5, mul0
+	MULQ acc7
+	ADDQ hlp, t0
+	ADCQ $0, mul1
+	ADDQ mul0, t0
+	ADCQ $0, mul1
+	MOVQ mul1, t1
+
+	MOVQ acc6, mul0
+	MULQ acc7
+	ADDQ mul0, t1
+	ADCQ $0, mul1
+	MOVQ mul1, t2
+	XORQ t3, t3
+	// *2
+	ADDQ acc1, acc1
+	ADCQ acc2, acc2
+	ADCQ acc3, acc3
+	ADCQ t0, t0
+	ADCQ t1, t1
+	ADCQ t2, t2
+	ADCQ $0, t3
+	// Missing products
+	MOVQ acc4, mul0
+	MULQ mul0
+	MOVQ mul0, acc0
+	MOVQ DX, acc4
+
+	MOVQ acc5, mul0
+	MULQ mul0
+	ADDQ acc4, acc1
+	ADCQ mul0, acc2
+	ADCQ $0, DX
+	MOVQ DX, acc4
+
+	MOVQ acc6, mul0
+	MULQ mul0
+	ADDQ acc4, acc3
+	ADCQ mul0, t0
+	ADCQ $0, DX
+	MOVQ DX, acc4
+
+	MOVQ acc7, mul0
+	MULQ mul0
+	ADDQ acc4, t1
+	ADCQ mul0, t2
+	ADCQ DX, t3
+	// First reduction step
+	MOVQ acc0, mul0
+	MOVQ acc0, hlp
+	SHLQ $32, acc0
+	MULQ p256const1<>(SB)
+	SHRQ $32, hlp
+	ADDQ acc0, acc1
+	ADCQ hlp, acc2
+	ADCQ mul0, acc3
+	ADCQ $0, mul1
+	MOVQ mul1, acc0
+	// Second reduction step
+	MOVQ acc1, mul0
+	MOVQ acc1, hlp
+	SHLQ $32, acc1
+	MULQ p256const1<>(SB)
+	SHRQ $32, hlp
+	ADDQ acc1, acc2
+	ADCQ hlp, acc3
+	ADCQ mul0, acc0
+	ADCQ $0, mul1
+	MOVQ mul1, acc1
+	// Third reduction step
+	MOVQ acc2, mul0
+	MOVQ acc2, hlp
+	SHLQ $32, acc2
+	MULQ p256const1<>(SB)
+	SHRQ $32, hlp
+	ADDQ acc2, acc3
+	ADCQ hlp, acc0
+	ADCQ mul0, acc1
+	ADCQ $0, mul1
+	MOVQ mul1, acc2
+	// Last reduction step
+	MOVQ acc3, mul0
+	MOVQ acc3, hlp
+	SHLQ $32, acc3
+	MULQ p256const1<>(SB)
+	SHRQ $32, hlp
+	ADDQ acc3, acc0
+	ADCQ hlp, acc1
+	ADCQ mul0, acc2
+	ADCQ $0, mul1
+	MOVQ mul1, acc3
+	BYTE $0x48; BYTE $0xc7; BYTE $0xc5; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00   // MOVQ $0, BP
+	// Add bits [511:256] of the result
+	ADCQ acc0, t0
+	ADCQ acc1, t1
+	ADCQ acc2, t2
+	ADCQ acc3, t3
+	ADCQ $0, hlp
+	// Copy result
+	MOVQ t0, acc4
+	MOVQ t1, acc5
+	MOVQ t2, acc6
+	MOVQ t3, acc7
+	// Subtract p256
+	SUBQ $-1, acc4
+	SBBQ p256const0<>(SB) ,acc5
+	SBBQ $0, acc6
+	SBBQ p256const1<>(SB), acc7
+	SBBQ $0, hlp
+	// If the result of the subtraction is negative, restore the previous result
+	CMOVQCS t0, acc4
+	CMOVQCS t1, acc5
+	CMOVQCS t2, acc6
+	CMOVQCS t3, acc7
+
+	RET
+/* ---------------------------------------*/
+#define p256MulBy2Inline\
+	XORQ mul0, mul0;\
+	ADDQ acc4, acc4;\
+	ADCQ acc5, acc5;\
+	ADCQ acc6, acc6;\
+	ADCQ acc7, acc7;\
+	ADCQ $0, mul0;\
+	MOVQ acc4, t0;\
+	MOVQ acc5, t1;\
+	MOVQ acc6, t2;\
+	MOVQ acc7, t3;\
+	SUBQ $-1, t0;\
+	SBBQ p256const0<>(SB), t1;\
+	SBBQ $0, t2;\
+	SBBQ p256const1<>(SB), t3;\
+	SBBQ $0, mul0;\
+	CMOVQCS acc4, t0;\
+	CMOVQCS acc5, t1;\
+	CMOVQCS acc6, t2;\
+	CMOVQCS acc7, t3;
+/* ---------------------------------------*/
+#define p256AddInline \
+	XORQ mul0, mul0;\
+	ADDQ t0, acc4;\
+	ADCQ t1, acc5;\
+	ADCQ t2, acc6;\
+	ADCQ t3, acc7;\
+	ADCQ $0, mul0;\
+	MOVQ acc4, t0;\
+	MOVQ acc5, t1;\
+	MOVQ acc6, t2;\
+	MOVQ acc7, t3;\
+	SUBQ $-1, t0;\
+	SBBQ p256const0<>(SB), t1;\
+	SBBQ $0, t2;\
+	SBBQ p256const1<>(SB), t3;\
+	SBBQ $0, mul0;\
+	CMOVQCS acc4, t0;\
+	CMOVQCS acc5, t1;\
+	CMOVQCS acc6, t2;\
+	CMOVQCS acc7, t3;
+/* ---------------------------------------*/
+#define LDacc(src) MOVQ src(8*0), acc4; MOVQ src(8*1), acc5; MOVQ src(8*2), acc6; MOVQ src(8*3), acc7
+#define LDt(src)   MOVQ src(8*0), t0; MOVQ src(8*1), t1; MOVQ src(8*2), t2; MOVQ src(8*3), t3
+#define ST(dst)    MOVQ acc4, dst(8*0); MOVQ acc5, dst(8*1); MOVQ acc6, dst(8*2); MOVQ acc7, dst(8*3)
+#define STt(dst)   MOVQ t0, dst(8*0); MOVQ t1, dst(8*1); MOVQ t2, dst(8*2); MOVQ t3, dst(8*3)
+#define acc2t      MOVQ acc4, t0; MOVQ acc5, t1; MOVQ acc6, t2; MOVQ acc7, t3
+#define t2acc      MOVQ t0, acc4; MOVQ t1, acc5; MOVQ t2, acc6; MOVQ t3, acc7
+/* ---------------------------------------*/
+#define x1in(off) (32*0 + off)(SP)
+#define y1in(off) (32*1 + off)(SP)
+#define z1in(off) (32*2 + off)(SP)
+#define x2in(off) (32*3 + off)(SP)
+#define y2in(off) (32*4 + off)(SP)
+#define xout(off) (32*5 + off)(SP)
+#define yout(off) (32*6 + off)(SP)
+#define zout(off) (32*7 + off)(SP)
+#define s2(off)   (32*8 + off)(SP)
+#define z1sqr(off) (32*9 + off)(SP)
+#define h(off)	  (32*10 + off)(SP)
+#define r(off)	  (32*11 + off)(SP)
+#define hsqr(off) (32*12 + off)(SP)
+#define rsqr(off) (32*13 + off)(SP)
+#define hcub(off) (32*14 + off)(SP)
+#define rptr	  (32*15)(SP)
+#define sel_save  (32*15 + 8)(SP)
+#define zero_save (32*15 + 8 + 4)(SP)
+
+// func p256PointAddAffineAsm(res, in1, in2 []uint64, sign, sel, zero int)
+TEXT ·p256PointAddAffineAsm(SB),0,$512-96
+	// Move input to stack in order to free registers
+	MOVQ res+0(FP), AX
+	MOVQ in1+24(FP), BX
+	MOVQ in2+48(FP), CX
+	MOVQ sign+72(FP), DX
+	MOVQ sel+80(FP), t1
+	MOVQ zero+88(FP), t2
+
+	MOVOU (16*0)(BX), X0
+	MOVOU (16*1)(BX), X1
+	MOVOU (16*2)(BX), X2
+	MOVOU (16*3)(BX), X3
+	MOVOU (16*4)(BX), X4
+	MOVOU (16*5)(BX), X5
+
+	MOVOU X0, x1in(16*0)
+	MOVOU X1, x1in(16*1)
+	MOVOU X2, y1in(16*0)
+	MOVOU X3, y1in(16*1)
+	MOVOU X4, z1in(16*0)
+	MOVOU X5, z1in(16*1)
+
+	MOVOU (16*0)(CX), X0
+	MOVOU (16*1)(CX), X1
+
+	MOVOU X0, x2in(16*0)
+	MOVOU X1, x2in(16*1)
+	// Store pointer to result
+	MOVQ mul0, rptr
+	MOVL t1, sel_save
+	MOVL t2, zero_save
+	// Negate y2in based on sign
+	MOVQ (16*2 + 8*0)(CX), acc4
+	MOVQ (16*2 + 8*1)(CX), acc5
+	MOVQ (16*2 + 8*2)(CX), acc6
+	MOVQ (16*2 + 8*3)(CX), acc7
+	MOVQ $-1, acc0
+	MOVQ p256const0<>(SB), acc1
+	MOVQ $0, acc2
+	MOVQ p256const1<>(SB), acc3
+	XORQ mul0, mul0
+	// Speculatively subtract
+	SUBQ acc4, acc0
+	SBBQ acc5, acc1
+	SBBQ acc6, acc2
+	SBBQ acc7, acc3
+	SBBQ $0, mul0
+	MOVQ acc0, t0
+	MOVQ acc1, t1
+	MOVQ acc2, t2
+	MOVQ acc3, t3
+	// Add in case the operand was > p256
+	ADDQ $-1, acc0
+	ADCQ p256const0<>(SB), acc1
+	ADCQ $0, acc2
+	ADCQ p256const1<>(SB), acc3
+	ADCQ $0, mul0
+	CMOVQNE t0, acc0
+	CMOVQNE t1, acc1
+	CMOVQNE t2, acc2
+	CMOVQNE t3, acc3
+	// If condition is 0, keep original value
+	TESTQ DX, DX
+	CMOVQEQ acc4, acc0
+	CMOVQEQ acc5, acc1
+	CMOVQEQ acc6, acc2
+	CMOVQEQ acc7, acc3
+	// Store result
+	MOVQ acc0, y2in(8*0)
+	MOVQ acc1, y2in(8*1)
+	MOVQ acc2, y2in(8*2)
+	MOVQ acc3, y2in(8*3)
+	// Begin point add
+	LDacc (z1in)
+	CALL p256SqrInternal(SB)	// z1ˆ2
+	ST (z1sqr)
+
+	LDt (x2in)
+	CALL p256MulInternal(SB)	// x2 * z1ˆ2
+
+	LDt (x1in)
+	CALL p256SubInternal(SB)	// h = u2 - u1
+	ST (h)
+
+	LDt (z1in)
+	CALL p256MulInternal(SB)	// z3 = h * z1
+	ST (zout)
+
+	LDacc (z1sqr)
+	CALL p256MulInternal(SB)	// z1ˆ3
+
+	LDt (y2in)
+	CALL p256MulInternal(SB)	// s2 = y2 * z1ˆ3
+	ST (s2)
+
+	LDt (y1in)
+	CALL p256SubInternal(SB)	// r = s2 - s1
+	ST (r)
+
+	CALL p256SqrInternal(SB)	// rsqr = rˆ2
+	ST (rsqr)
+
+	LDacc (h)
+	CALL p256SqrInternal(SB)	// hsqr = hˆ2
+	ST (hsqr)
+
+	LDt (h)
+	CALL p256MulInternal(SB)	// hcub = hˆ3
+	ST (hcub)
+
+	LDt (y1in)
+	CALL p256MulInternal(SB)	// y1 * hˆ3
+	ST (s2)
+
+	LDacc (x1in)
+	LDt (hsqr)
+	CALL p256MulInternal(SB)	// u1 * hˆ2
+	ST (h)
+
+	p256MulBy2Inline			// u1 * hˆ2 * 2, inline
+	LDacc (rsqr)
+	CALL p256SubInternal(SB)	// rˆ2 - u1 * hˆ2 * 2
+
+	LDt (hcub)
+	CALL p256SubInternal(SB)
+	ST (xout)
+
+	MOVQ acc4, t0
+	MOVQ acc5, t1
+	MOVQ acc6, t2
+	MOVQ acc7, t3
+	LDacc (h)
+	CALL p256SubInternal(SB)
+
+	LDt (r)
+	CALL p256MulInternal(SB)
+
+	LDt (s2)
+	CALL p256SubInternal(SB)
+	ST (yout)
+	// Load stored values from stack
+	MOVQ rptr, AX
+	MOVL sel_save, BX
+	MOVL zero_save, CX
+	// The result is not valid if (sel == 0), conditional choose
+	MOVOU xout(16*0), X0
+	MOVOU xout(16*1), X1
+	MOVOU yout(16*0), X2
+	MOVOU yout(16*1), X3
+	MOVOU zout(16*0), X4
+	MOVOU zout(16*1), X5
+
+	MOVL BX, X6
+	MOVL CX, X7
+
+	PXOR X8, X8
+	PCMPEQL X9, X9
+
+	PSHUFD $0, X6, X6
+	PSHUFD $0, X7, X7
+
+	PCMPEQL X8, X6
+	PCMPEQL X8, X7
+
+	MOVOU X6, X15
+	PANDN X9, X15
+
+	MOVOU x1in(16*0), X9
+	MOVOU x1in(16*1), X10
+	MOVOU y1in(16*0), X11
+	MOVOU y1in(16*1), X12
+	MOVOU z1in(16*0), X13
+	MOVOU z1in(16*1), X14
+
+	PAND X15, X0
+	PAND X15, X1
+	PAND X15, X2
+	PAND X15, X3
+	PAND X15, X4
+	PAND X15, X5
+
+	PAND X6, X9
+	PAND X6, X10
+	PAND X6, X11
+	PAND X6, X12
+	PAND X6, X13
+	PAND X6, X14
+
+	PXOR X9, X0
+	PXOR X10, X1
+	PXOR X11, X2
+	PXOR X12, X3
+	PXOR X13, X4
+	PXOR X14, X5
+	// Similarly if zero == 0
+	PCMPEQL X9, X9
+	MOVOU X7, X15
+	PANDN X9, X15
+
+	MOVOU x2in(16*0), X9
+	MOVOU x2in(16*1), X10
+	MOVOU y2in(16*0), X11
+	MOVOU y2in(16*1), X12
+	MOVOU p256one<>+0x00(SB), X13
+	MOVOU p256one<>+0x10(SB), X14
+
+	PAND X15, X0
+	PAND X15, X1
+	PAND X15, X2
+	PAND X15, X3
+	PAND X15, X4
+	PAND X15, X5
+
+	PAND X7, X9
+	PAND X7, X10
+	PAND X7, X11
+	PAND X7, X12
+	PAND X7, X13
+	PAND X7, X14
+
+	PXOR X9, X0
+	PXOR X10, X1
+	PXOR X11, X2
+	PXOR X12, X3
+	PXOR X13, X4
+	PXOR X14, X5
+	// Finally output the result
+	MOVOU X0, (16*0)(AX)
+	MOVOU X1, (16*1)(AX)
+	MOVOU X2, (16*2)(AX)
+	MOVOU X3, (16*3)(AX)
+	MOVOU X4, (16*4)(AX)
+	MOVOU X5, (16*5)(AX)
+	MOVQ $0, rptr
+
+	RET
+#undef x1in
+#undef y1in
+#undef z1in
+#undef x2in
+#undef y2in
+#undef xout
+#undef yout
+#undef zout
+#undef s2
+#undef z1sqr
+#undef h
+#undef r
+#undef hsqr
+#undef rsqr
+#undef hcub
+#undef rptr
+#undef sel_save
+#undef zero_save
+/* ---------------------------------------*/
+#define x1in(off) (32*0 + off)(SP)
+#define y1in(off) (32*1 + off)(SP)
+#define z1in(off) (32*2 + off)(SP)
+#define x2in(off) (32*3 + off)(SP)
+#define y2in(off) (32*4 + off)(SP)
+#define z2in(off) (32*5 + off)(SP)
+
+#define xout(off) (32*6 + off)(SP)
+#define yout(off) (32*7 + off)(SP)
+#define zout(off) (32*8 + off)(SP)
+
+#define u1(off)    (32*9 + off)(SP)
+#define u2(off)    (32*10 + off)(SP)
+#define s1(off)    (32*11 + off)(SP)
+#define s2(off)    (32*12 + off)(SP)
+#define z1sqr(off) (32*13 + off)(SP)
+#define z2sqr(off) (32*14 + off)(SP)
+#define h(off)     (32*15 + off)(SP)
+#define r(off)     (32*16 + off)(SP)
+#define hsqr(off)  (32*17 + off)(SP)
+#define rsqr(off)  (32*18 + off)(SP)
+#define hcub(off)  (32*19 + off)(SP)
+#define rptr       (32*20)(SP)
+
+//func p256PointAddAsm(res, in1, in2 []uint64)
+TEXT ·p256PointAddAsm(SB),0,$672-72
+	// Move input to stack in order to free registers
+	MOVQ res+0(FP), AX
+	MOVQ in1+24(FP), BX
+	MOVQ in2+48(FP), CX
+
+	MOVOU (16*0)(BX), X0
+	MOVOU (16*1)(BX), X1
+	MOVOU (16*2)(BX), X2
+	MOVOU (16*3)(BX), X3
+	MOVOU (16*4)(BX), X4
+	MOVOU (16*5)(BX), X5
+
+	MOVOU X0, x1in(16*0)
+	MOVOU X1, x1in(16*1)
+	MOVOU X2, y1in(16*0)
+	MOVOU X3, y1in(16*1)
+	MOVOU X4, z1in(16*0)
+	MOVOU X5, z1in(16*1)
+
+	MOVOU (16*0)(CX), X0
+	MOVOU (16*1)(CX), X1
+	MOVOU (16*2)(CX), X2
+	MOVOU (16*3)(CX), X3
+	MOVOU (16*4)(CX), X4
+	MOVOU (16*5)(CX), X5
+
+	MOVOU X0, x2in(16*0)
+	MOVOU X1, x2in(16*1)
+	MOVOU X2, y2in(16*0)
+	MOVOU X3, y2in(16*1)
+	MOVOU X4, z2in(16*0)
+	MOVOU X5, z2in(16*1)
+	// Store pointer to result
+	MOVQ AX, rptr
+	// Begin point add
+	LDacc (z2in)
+	CALL p256SqrInternal(SB)	// z2ˆ2
+	ST (z2sqr)
+	LDt (z2in)
+	CALL p256MulInternal(SB)	// z2ˆ3
+	LDt (y1in)
+	CALL p256MulInternal(SB)	// s1 = z2ˆ3*y1
+	ST (s1)
+
+	LDacc (z1in)
+	CALL p256SqrInternal(SB)	// z1ˆ2
+	ST (z1sqr)
+	LDt (z1in)
+	CALL p256MulInternal(SB)	// z1ˆ3
+	LDt (y2in)
+	CALL p256MulInternal(SB)	// s2 = z1ˆ3*y2
+	ST (s2)
+
+	LDt (s1)
+	CALL p256SubInternal(SB)	// r = s2 - s1
+	ST (r)
+
+	LDacc (z2sqr)
+	LDt (x1in)
+	CALL p256MulInternal(SB)	// u1 = x1 * z2ˆ2
+	ST (u1)
+	LDacc (z1sqr)
+	LDt (x2in)
+	CALL p256MulInternal(SB)	// u2 = x2 * z1ˆ2
+	ST (u2)
+
+	LDt (u1)
+	CALL p256SubInternal(SB)	// h = u2 - u1
+	ST (h)
+
+	LDacc (r)
+	CALL p256SqrInternal(SB)	// rsqr = rˆ2
+	ST (rsqr)
+
+	LDacc (h)
+	CALL p256SqrInternal(SB)	// hsqr = hˆ2
+	ST (hsqr)
+
+	LDt (h)
+	CALL p256MulInternal(SB)	// hcub = hˆ3
+	ST (hcub)
+
+	LDt (s1)
+	CALL p256MulInternal(SB)
+	ST (s2)
+
+	LDacc (z1in)
+	LDt (z2in)
+	CALL p256MulInternal(SB)	// z1 * z2
+	LDt (h)
+	CALL p256MulInternal(SB)	// z1 * z2 * h
+	ST (zout)
+
+	LDacc (hsqr)
+	LDt (u1)
+	CALL p256MulInternal(SB)	// hˆ2 * u1
+	ST (u2)
+
+	p256MulBy2Inline	// u1 * hˆ2 * 2, inline
+	LDacc (rsqr)
+	CALL p256SubInternal(SB)	// rˆ2 - u1 * hˆ2 * 2
+
+	LDt (hcub)
+	CALL p256SubInternal(SB)
+	ST (xout)
+
+	MOVQ acc4, t0
+	MOVQ acc5, t1
+	MOVQ acc6, t2
+	MOVQ acc7, t3
+	LDacc (u2)
+	CALL p256SubInternal(SB)
+
+	LDt (r)
+	CALL p256MulInternal(SB)
+
+	LDt (s2)
+	CALL p256SubInternal(SB)
+	ST (yout)
+
+	MOVOU xout(16*0), X0
+	MOVOU xout(16*1), X1
+	MOVOU yout(16*0), X2
+	MOVOU yout(16*1), X3
+	MOVOU zout(16*0), X4
+	MOVOU zout(16*1), X5
+	// Finally output the result
+	MOVQ rptr, AX
+	MOVQ $0, rptr
+	MOVOU X0, (16*0)(AX)
+	MOVOU X1, (16*1)(AX)
+	MOVOU X2, (16*2)(AX)
+	MOVOU X3, (16*3)(AX)
+	MOVOU X4, (16*4)(AX)
+	MOVOU X5, (16*5)(AX)
+
+	RET
+#undef x1in
+#undef y1in
+#undef z1in
+#undef x2in
+#undef y2in
+#undef z2in
+#undef xout
+#undef yout
+#undef zout
+#undef s1
+#undef s2
+#undef u1
+#undef u2
+#undef z1sqr
+#undef z2sqr
+#undef h
+#undef r
+#undef hsqr
+#undef rsqr
+#undef hcub
+#undef rptr
+/* ---------------------------------------*/
+#define x(off) (32*0 + off)(SP)
+#define y(off) (32*1 + off)(SP)
+#define z(off) (32*2 + off)(SP)
+
+#define s(off)	(32*3 + off)(SP)
+#define m(off)	(32*4 + off)(SP)
+#define zsqr(off) (32*5 + off)(SP)
+#define tmp(off)  (32*6 + off)(SP)
+#define rptr	  (32*7)(SP)
+
+//func p256PointDoubleAsm(res, in []uint64)
+TEXT ·p256PointDoubleAsm(SB),NOSPLIT,$256-48
+	// Move input to stack in order to free registers
+	MOVQ res+0(FP), AX
+	MOVQ in+24(FP), BX
+
+	MOVOU (16*0)(BX), X0
+	MOVOU (16*1)(BX), X1
+	MOVOU (16*2)(BX), X2
+	MOVOU (16*3)(BX), X3
+	MOVOU (16*4)(BX), X4
+	MOVOU (16*5)(BX), X5
+
+	MOVOU X0, x(16*0)
+	MOVOU X1, x(16*1)
+	MOVOU X2, y(16*0)
+	MOVOU X3, y(16*1)
+	MOVOU X4, z(16*0)
+	MOVOU X5, z(16*1)
+	// Store pointer to result
+	MOVQ AX, rptr
+	// Begin point double
+	LDacc (z)
+	CALL p256SqrInternal(SB)
+	ST (zsqr)
+
+	LDt (x)
+	p256AddInline
+	STt (m)
+
+	LDacc (z)
+	LDt (y)
+	CALL p256MulInternal(SB)
+	p256MulBy2Inline
+	MOVQ rptr, AX
+	// Store z
+	MOVQ t0, (16*4 + 8*0)(AX)
+	MOVQ t1, (16*4 + 8*1)(AX)
+	MOVQ t2, (16*4 + 8*2)(AX)
+	MOVQ t3, (16*4 + 8*3)(AX)
+
+	LDacc (x)
+	LDt (zsqr)
+	CALL p256SubInternal(SB)
+	LDt (m)
+	CALL p256MulInternal(SB)
+	ST (m)
+	// Multiply by 3
+	p256MulBy2Inline
+	LDacc (m)
+	p256AddInline
+	STt (m)
+	////////////////////////
+	LDacc (y)
+	p256MulBy2Inline
+	t2acc
+	CALL p256SqrInternal(SB)
+	ST (s)
+	CALL p256SqrInternal(SB)
+	// Divide by 2
+	XORQ mul0, mul0
+	MOVQ acc4, t0
+	MOVQ acc5, t1
+	MOVQ acc6, t2
+	MOVQ acc7, t3
+
+	ADDQ $-1, acc4
+	ADCQ p256const0<>(SB), acc5
+	ADCQ $0, acc6
+	ADCQ p256const1<>(SB), acc7
+	ADCQ $0, mul0
+	TESTQ $1, t0
+
+	CMOVQEQ t0, acc4
+	CMOVQEQ t1, acc5
+	CMOVQEQ t2, acc6
+	CMOVQEQ t3, acc7
+	ANDQ t0, mul0
+
+	SHRQ $1, acc4:acc5
+	SHRQ $1, acc5:acc6
+	SHRQ $1, acc6:acc7
+	SHRQ $1, acc7:mul0
+	ST (y)
+	/////////////////////////
+	LDacc (x)
+	LDt (s)
+	CALL p256MulInternal(SB)
+	ST (s)
+	p256MulBy2Inline
+	STt (tmp)
+
+	LDacc (m)
+	CALL p256SqrInternal(SB)
+	LDt (tmp)
+	CALL p256SubInternal(SB)
+
+	MOVQ rptr, AX
+	// Store x
+	MOVQ acc4, (16*0 + 8*0)(AX)
+	MOVQ acc5, (16*0 + 8*1)(AX)
+	MOVQ acc6, (16*0 + 8*2)(AX)
+	MOVQ acc7, (16*0 + 8*3)(AX)
+
+	acc2t
+	LDacc (s)
+	CALL p256SubInternal(SB)
+
+	LDt (m)
+	CALL p256MulInternal(SB)
+
+	LDt (y)
+	CALL p256SubInternal(SB)
+	MOVQ rptr, AX
+	// Store y
+	MOVQ acc4, (16*2 + 8*0)(AX)
+	MOVQ acc5, (16*2 + 8*1)(AX)
+	MOVQ acc6, (16*2 + 8*2)(AX)
+	MOVQ acc7, (16*2 + 8*3)(AX)
+	///////////////////////
+	MOVQ $0, rptr
+
+	RET
+/* ---------------------------------------*/
+
diff --git a/src/crypto/hmac/hmac.go b/src/crypto/hmac/hmac.go
index e0cc1d6..3b41cde 100644
--- a/src/crypto/hmac/hmac.go
+++ b/src/crypto/hmac/hmac.go
@@ -26,8 +26,8 @@ import (
 	"hash"
 )
 
-// FIPS 198:
-// http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf
+// FIPS 198-1:
+// http://csrc.nist.gov/publications/fips/fips198-1/FIPS-198-1_final.pdf
 
 // key is zero padded to the block size of the hash function
 // ipad = 0x36 byte repeated for key length
diff --git a/src/crypto/md5/md5.go b/src/crypto/md5/md5.go
index 8c50c6d..a3550cb 100644
--- a/src/crypto/md5/md5.go
+++ b/src/crypto/md5/md5.go
@@ -62,16 +62,10 @@ func (d *digest) Write(p []byte) (nn int, err error) {
 	nn = len(p)
 	d.len += uint64(nn)
 	if d.nx > 0 {
-		n := len(p)
-		if n > chunk-d.nx {
-			n = chunk - d.nx
-		}
-		for i := 0; i < n; i++ {
-			d.x[d.nx+i] = p[i]
-		}
+		n := copy(d.x[d.nx:], p)
 		d.nx += n
 		if d.nx == chunk {
-			block(d, d.x[0:chunk])
+			block(d, d.x[:])
 			d.nx = 0
 		}
 		p = p[n:]
diff --git a/src/crypto/rsa/example_test.go b/src/crypto/rsa/example_test.go
new file mode 100644
index 0000000..1435b70
--- /dev/null
+++ b/src/crypto/rsa/example_test.go
@@ -0,0 +1,169 @@
+// 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 rsa
+
+import (
+	"crypto"
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/rand"
+	"crypto/sha256"
+	"encoding/hex"
+	"fmt"
+	"io"
+	"os"
+)
+
+// RSA is able to encrypt only a very limited amount of data. In order
+// to encrypt reasonable amounts of data a hybrid scheme is commonly
+// used: RSA is used to encrypt a key for a symmetric primitive like
+// AES-GCM.
+//
+// Before encrypting, data is “padded” by embedding it in a known
+// structure. This is done for a number of reasons, but the most
+// obvious is to ensure that the value is large enough that the
+// exponentiation is larger than the modulus. (Otherwise it could be
+// decrypted with a square-root.)
+//
+// In these designs, when using PKCS#1 v1.5, it's vitally important to
+// avoid disclosing whether the received RSA message was well-formed
+// (that is, whether the result of decrypting is a correctly padded
+// message) because this leaks secret information.
+// DecryptPKCS1v15SessionKey is designed for this situation and copies
+// the decrypted, symmetric key (if well-formed) in constant-time over
+// a buffer that contains a random key. Thus, if the RSA result isn't
+// well-formed, the implementation uses a random key in constant time.
+func ExampleDecryptPKCS1v15SessionKey() {
+	// crypto/rand.Reader is a good source of entropy for blinding the RSA
+	// operation.
+	rng := rand.Reader
+
+	// The hybrid scheme should use at least a 16-byte symmetric key. Here
+	// we read the random key that will be used if the RSA decryption isn't
+	// well-formed.
+	key := make([]byte, 32)
+	if _, err := io.ReadFull(rng, key); err != nil {
+		panic("RNG failure")
+	}
+
+	rsaCiphertext, _ := hex.DecodeString("aabbccddeeff")
+
+	if err := DecryptPKCS1v15SessionKey(rng, rsaPrivateKey, rsaCiphertext, key); err != nil {
+		// Any errors that result will be “public” – meaning that they
+		// can be determined without any secret information. (For
+		// instance, if the length of key is impossible given the RSA
+		// public key.)
+		fmt.Fprintf(os.Stderr, "Error from RSA decryption: %s\n", err)
+		return
+	}
+
+	// Given the resulting key, a symmetric scheme can be used to decrypt a
+	// larger ciphertext.
+	block, err := aes.NewCipher(key)
+	if err != nil {
+		panic("aes.NewCipher failed: " + err.Error())
+	}
+
+	// Since the key is random, using a fixed nonce is acceptable as the
+	// (key, nonce) pair will still be unique, as required.
+	var zeroNonce [12]byte
+	aead, err := cipher.NewGCM(block)
+	if err != nil {
+		panic("cipher.NewGCM failed: " + err.Error())
+	}
+	ciphertext, _ := hex.DecodeString("00112233445566")
+	plaintext, err := aead.Open(nil, zeroNonce[:], ciphertext, nil)
+	if err != nil {
+		// The RSA ciphertext was badly formed; the decryption will
+		// fail here because the AES-GCM key will be incorrect.
+		fmt.Fprintf(os.Stderr, "Error decrypting: %s\n", err)
+		return
+	}
+
+	fmt.Printf("Plaintext: %s\n", string(plaintext))
+}
+
+func ExampleSignPKCS1v15() {
+	// crypto/rand.Reader is a good source of entropy for blinding the RSA
+	// operation.
+	rng := rand.Reader
+
+	message := []byte("message to be signed")
+
+	// Only small messages can be signed directly; thus the hash of a
+	// message, rather than the message itself, is signed. This requires
+	// that the hash function be collision resistant. SHA-256 is the
+	// least-strong hash function that should be used for this at the time
+	// of writing (2016).
+	hashed := sha256.Sum256(message)
+
+	signature, err := SignPKCS1v15(rng, rsaPrivateKey, crypto.SHA256, hashed[:])
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "Error from signing: %s\n", err)
+		return
+	}
+
+	fmt.Printf("Signature: %x\n", signature)
+}
+
+func ExampleVerifyPKCS1v15() {
+	message := []byte("message to be signed")
+	signature, _ := hex.DecodeString("ad2766728615cc7a746cc553916380ca7bfa4f8983b990913bc69eb0556539a350ff0f8fe65ddfd3ebe91fe1c299c2fac135bc8c61e26be44ee259f2f80c1530")
+
+	// Only small messages can be signed directly; thus the hash of a
+	// message, rather than the message itself, is signed. This requires
+	// that the hash function be collision resistant. SHA-256 is the
+	// least-strong hash function that should be used for this at the time
+	// of writing (2016).
+	hashed := sha256.Sum256(message)
+
+	err := VerifyPKCS1v15(&rsaPrivateKey.PublicKey, crypto.SHA256, hashed[:], signature)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "Error from verification: %s\n", err)
+		return
+	}
+
+	// signature is a valid signature of message from the public key.
+}
+
+func ExampleEncryptOAEP() {
+	secretMessage := []byte("send reinforcements, we're going to advance")
+	label := []byte("orders")
+
+	// crypto/rand.Reader is a good source of entropy for randomizing the
+	// encryption function.
+	rng := rand.Reader
+
+	ciphertext, err := EncryptOAEP(sha256.New(), rng, &test2048Key.PublicKey, secretMessage, label)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "Error from encryption: %s\n", err)
+		return
+	}
+
+	// Since encryption is a randomized function, ciphertext will be
+	// different each time.
+	fmt.Printf("Ciphertext: %x\n", ciphertext)
+}
+
+func ExampleDecryptOAEP() {
+	ciphertext, _ := hex.DecodeString("4d1ee10e8f286390258c51a5e80802844c3e6358ad6690b7285218a7c7ed7fc3a4c7b950fbd04d4b0239cc060dcc7065ca6f84c1756deb71ca5685cadbb82be025e16449b905c568a19c088a1abfad54bf7ecc67a7df39943ec511091a34c0f2348d04e058fcff4d55644de3cd1d580791d4524b92f3e91695582e6e340a1c50b6c6d78e80b4e42c5b4d45e479b492de42bbd39cc642ebb80226bb5200020d501b24a37bcc2ec7f34e596b4fd6b063de4858dbf5a4e3dd18e262eda0ec2d19dbd8e890d672b63d368768360b20c0b6b8592a438fa275e5fa7f60bef0dd39673fd3989cc5 [...]
+	label := []byte("orders")
+
+	// crypto/rand.Reader is a good source of entropy for blinding the RSA
+	// operation.
+	rng := rand.Reader
+
+	plaintext, err := DecryptOAEP(sha256.New(), rng, test2048Key, ciphertext, label)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "Error from decryption: %s\n", err)
+		return
+	}
+
+	fmt.Printf("Plaintext: %s\n", string(plaintext))
+
+	// Remember that encryption only provides confidentiality. The
+	// ciphertext should be signed before authenticity is assumed and, even
+	// then, consider that messages might be reordered.
+}
diff --git a/src/crypto/rsa/pkcs1v15.go b/src/crypto/rsa/pkcs1v15.go
index 34037b0..5c5f415 100644
--- a/src/crypto/rsa/pkcs1v15.go
+++ b/src/crypto/rsa/pkcs1v15.go
@@ -26,6 +26,10 @@ type PKCS1v15DecryptOptions struct {
 
 // EncryptPKCS1v15 encrypts the given message with RSA and the padding scheme from PKCS#1 v1.5.
 // The message must be no longer than the length of the public modulus minus 11 bytes.
+//
+// The rand parameter is used as a source of entropy to ensure that encrypting
+// the same message twice doesn't result in the same ciphertext.
+//
 // WARNING: use of this function to encrypt plaintexts other than session keys
 // is dangerous. Use RSA OAEP in new protocols.
 func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, err error) {
@@ -59,6 +63,12 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) (out []byte, er
 
 // DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
 // If rand != nil, it uses RSA blinding to avoid timing side-channel attacks.
+//
+// Note that whether this function returns an error or not discloses secret
+// information. If an attacker can cause this function to run repeatedly and
+// learn whether each instance returned an error then they can decrypt and
+// forge signatures as if they had the private key. See
+// DecryptPKCS1v15SessionKey for a way of solving this problem.
 func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out []byte, err error) {
 	if err := checkPub(&priv.PublicKey); err != nil {
 		return nil, err
@@ -87,6 +97,12 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (out [
 // See ``Chosen Ciphertext Attacks Against Protocols Based on the RSA
 // Encryption Standard PKCS #1'', Daniel Bleichenbacher, Advances in Cryptology
 // (Crypto '98).
+//
+// Note that if the session key is too small then it may be possible for an
+// attacker to brute-force it. If they can do that then they can learn whether
+// a random value was used (because it'll be different for the same ciphertext)
+// and thus whether the padding was correct. This defeats the point of this
+// function. Using at least a 16-byte key will protect against this attack.
 func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) (err error) {
 	if err := checkPub(&priv.PublicKey); err != nil {
 		return err
@@ -201,6 +217,13 @@ var hashPrefixes = map[crypto.Hash][]byte{
 // Note that hashed must be the result of hashing the input message using the
 // given hash function. If hash is zero, hashed is signed directly. This isn't
 // advisable except for interoperability.
+//
+// If rand is not nil then RSA blinding will be used to avoid timing side-channel attacks.
+//
+// This function is deterministic. Thus, if the set of possible messages is
+// small, an attacker may be able to build a map from messages to signatures
+// and identify the signed messages. As ever, signatures provide authenticity,
+// not confidentiality.
 func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) (s []byte, err error) {
 	hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed))
 	if err != nil {
@@ -223,7 +246,7 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b
 	copy(em[k-hashLen:k], hashed)
 
 	m := new(big.Int).SetBytes(em)
-	c, err := decrypt(rand, priv, m)
+	c, err := decryptAndCheck(rand, priv, m)
 	if err != nil {
 		return
 	}
diff --git a/src/crypto/rsa/pkcs1v15_test.go b/src/crypto/rsa/pkcs1v15_test.go
index 8925375..47444f3 100644
--- a/src/crypto/rsa/pkcs1v15_test.go
+++ b/src/crypto/rsa/pkcs1v15_test.go
@@ -160,7 +160,7 @@ func TestEncryptPKCS1v15DecrypterSessionKey(t *testing.T) {
 		}
 
 		if test.out != "FAIL" && !bytes.Equal(plaintext, []byte(test.out)) {
-			t.Errorf("#%d: incorrect plaintext: got %x, want %x", plaintext, test.out)
+			t.Errorf("#%d: incorrect plaintext: got %x, want %x", i, plaintext, test.out)
 		}
 	}
 }
diff --git a/src/crypto/rsa/pss.go b/src/crypto/rsa/pss.go
index 0a41814..8a94589 100644
--- a/src/crypto/rsa/pss.go
+++ b/src/crypto/rsa/pss.go
@@ -198,7 +198,7 @@ func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed,
 		return
 	}
 	m := new(big.Int).SetBytes(em)
-	c, err := decrypt(rand, priv, m)
+	c, err := decryptAndCheck(rand, priv, m)
 	if err != nil {
 		return
 	}
diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go
index 1293b78..ee022b8 100644
--- a/src/crypto/rsa/rsa.go
+++ b/src/crypto/rsa/rsa.go
@@ -3,6 +3,21 @@
 // license that can be found in the LICENSE file.
 
 // Package rsa implements RSA encryption as specified in PKCS#1.
+//
+// RSA is a single, fundamental operation that is used in this package to
+// implement either public-key encryption or public-key signatures.
+//
+// The original specification for encryption and signatures with RSA is PKCS#1
+// and the terms "RSA encryption" and "RSA signatures" by default refer to
+// PKCS#1 version 1.5. However, that specification has flaws and new designs
+// should use version two, usually called by just OAEP and PSS, where
+// possible.
+//
+// Two sets of interfaces are included in this package. When a more abstract
+// interface isn't neccessary, there are functions for encrypting/decrypting
+// with v1.5/OAEP and signing/verifying with v1.5/PSS. If one needs to abstract
+// over the public-key primitive, the PrivateKey struct implements the
+// Decrypter and Signer interfaces from the crypto package.
 package rsa
 
 import (
@@ -317,6 +332,20 @@ func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int {
 }
 
 // EncryptOAEP encrypts the given message with RSA-OAEP.
+//
+// OAEP is parameterised by a hash function that is used as a random oracle.
+// Encryption and decryption of a given message must use the same hash function
+// and sha256.New() is a reasonable choice.
+//
+// The random parameter is used as a source of entropy to ensure that
+// encrypting the same message twice doesn't result in the same ciphertext.
+//
+// The label parameter may contain arbitrary data that will not be encrypted,
+// but which gives important context to the message. For example, if a given
+// public key is used to decrypt two types of messages then distinct label
+// values could be used to ensure that a ciphertext for one purpose cannot be
+// used for another by an attacker. If not required it can be empty.
+//
 // The message must be no longer than the length of the public modulus less
 // twice the hash length plus 2.
 func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) (out []byte, err error) {
@@ -506,8 +535,33 @@ func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err er
 	return
 }
 
+func decryptAndCheck(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) {
+	m, err = decrypt(random, priv, c)
+	if err != nil {
+		return nil, err
+	}
+
+	// In order to defend against errors in the CRT computation, m^e is
+	// calculated, which should match the original ciphertext.
+	check := encrypt(new(big.Int), &priv.PublicKey, m)
+	if c.Cmp(check) != 0 {
+		return nil, errors.New("rsa: internal error")
+	}
+	return m, nil
+}
+
 // DecryptOAEP decrypts ciphertext using RSA-OAEP.
-// If random != nil, DecryptOAEP uses RSA blinding to avoid timing side-channel attacks.
+
+// OAEP is parameterised by a hash function that is used as a random oracle.
+// Encryption and decryption of a given message must use the same hash function
+// and sha256.New() is a reasonable choice.
+//
+// The random parameter, if not nil, is used to blind the private-key operation
+// and avoid timing side-channel attacks. Blinding is purely internal to this
+// function – the random data need not match that used when encrypting.
+//
+// The label parameter must match the value given when encrypting. See
+// EncryptOAEP for details.
 func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) (msg []byte, err error) {
 	if err := checkPub(&priv.PublicKey); err != nil {
 		return nil, err
diff --git a/src/crypto/rsa/rsa_test.go b/src/crypto/rsa/rsa_test.go
index 4ee1c3a..6902f9a 100644
--- a/src/crypto/rsa/rsa_test.go
+++ b/src/crypto/rsa/rsa_test.go
@@ -6,8 +6,10 @@ package rsa
 
 import (
 	"bytes"
+	"crypto"
 	"crypto/rand"
 	"crypto/sha1"
+	"crypto/sha256"
 	"math/big"
 	"testing"
 )
@@ -127,9 +129,10 @@ func fromBase10(base10 string) *big.Int {
 	return i
 }
 
-func BenchmarkRSA2048Decrypt(b *testing.B) {
-	b.StopTimer()
-	priv := &PrivateKey{
+var test2048Key *PrivateKey
+
+func init() {
+	test2048Key = &PrivateKey{
 		PublicKey: PublicKey{
 			N: fromBase10("143141329312410066509980848892740206089180490326718583259883968513341242451882142519561987313334642178322264060880207369321730647542143290099799440376409121279434889726446974231909555574359107676907127784635249836678528190102594996951773131154471161103585245583079476134228977873292214788609079638271602235596905236605743290119275312896557118605046305737666092393325692108313256338401746839445536673522196709304085933216613754738851479738790869940064400252572254319777515123 [...]
 			E: 3,
@@ -140,14 +143,28 @@ func BenchmarkRSA2048Decrypt(b *testing.B) {
 			fromBase10("109348945610485453577574767652527472924289229538286649661240938988020367005475727988253438647560958573506159449538793540472829815903949343191091817779240101054552748665267574271163617694640513549693841337820602726596756351006149518830932261246698766355347898158548465400674856021497190430791824869615170301029"),
 		},
 	}
-	priv.Precompute()
+	test2048Key.Precompute()
+}
+
+func BenchmarkRSA2048Decrypt(b *testing.B) {
+	b.StopTimer()
 
 	c := fromBase10("847200279283821898946463615931697363663001383578720241812475811837235826197576436574002602461040313842598621499137901269660076151474281763279091631559434239872090371652923511981675558938337747175211697537495278362922502296209235188686151891182474518898907117209712035272736898027525208914151232189353674432482259048075109825755976632889376733486121187231896190089779387407524828643968924997231569941083009416438654431155470475511036104857114233614807777202388066478601963633 [...]
 
 	b.StartTimer()
 
 	for i := 0; i < b.N; i++ {
-		decrypt(nil, priv, c)
+		decrypt(nil, test2048Key, c)
+	}
+}
+
+func BenchmarkRSA2048Sign(b *testing.B) {
+	b.StopTimer()
+	hashed := sha256.Sum256([]byte("testing"))
+	b.StartTimer()
+
+	for i := 0; i < b.N; i++ {
+		SignPKCS1v15(rand.Reader, test2048Key, crypto.SHA256, hashed[:])
 	}
 }
 
diff --git a/src/crypto/tls/cipher_suites.go b/src/crypto/tls/cipher_suites.go
index a5fed29..869ffa5 100644
--- a/src/crypto/tls/cipher_suites.go
+++ b/src/crypto/tls/cipher_suites.go
@@ -85,6 +85,8 @@ var cipherSuites = []*cipherSuite{
 	{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
 	{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
 	{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
+	{TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, rsaKA, suiteTLS12, nil, nil, aeadAESGCM},
+	{TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
 	{TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, suiteDefaultOff, cipherRC4, macSHA1, nil},
 	{TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
 	{TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
@@ -266,6 +268,8 @@ const (
 	TLS_RSA_WITH_3DES_EDE_CBC_SHA           uint16 = 0x000a
 	TLS_RSA_WITH_AES_128_CBC_SHA            uint16 = 0x002f
 	TLS_RSA_WITH_AES_256_CBC_SHA            uint16 = 0x0035
+	TLS_RSA_WITH_AES_128_GCM_SHA256         uint16 = 0x009c
+	TLS_RSA_WITH_AES_256_GCM_SHA384         uint16 = 0x009d
 	TLS_ECDHE_ECDSA_WITH_RC4_128_SHA        uint16 = 0xc007
 	TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA    uint16 = 0xc009
 	TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA    uint16 = 0xc00a
diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go
index a3d75d6..c68ebfe 100644
--- a/src/crypto/tls/common.go
+++ b/src/crypto/tls/common.go
@@ -255,7 +255,8 @@ type Config struct {
 
 	// Certificates contains one or more certificate chains
 	// to present to the other side of the connection.
-	// Server configurations must include at least one certificate.
+	// Server configurations must include at least one certificate
+	// or else set GetCertificate.
 	Certificates []Certificate
 
 	// NameToCertificate maps from a certificate name to an element of
@@ -285,7 +286,8 @@ type Config struct {
 
 	// ServerName is used to verify the hostname on the returned
 	// certificates unless InsecureSkipVerify is given. It is also included
-	// in the client's handshake to support virtual hosting.
+	// in the client's handshake to support virtual hosting unless it is
+	// an IP address.
 	ServerName string
 
 	// ClientAuth determines the server's policy for
diff --git a/src/crypto/tls/conn.go b/src/crypto/tls/conn.go
index e3dcf15..0377568 100644
--- a/src/crypto/tls/conn.go
+++ b/src/crypto/tls/conn.go
@@ -16,6 +16,7 @@ import (
 	"io"
 	"net"
 	"sync"
+	"sync/atomic"
 	"time"
 )
 
@@ -56,6 +57,11 @@ type Conn struct {
 	input    *block       // application data waiting to be read
 	hand     bytes.Buffer // handshake data waiting to be read
 
+	// activeCall is an atomic int32; the low bit is whether Close has
+	// been called. the rest of the bits are the number of goroutines
+	// in Conn.Write.
+	activeCall int32
+
 	tmp [16]byte
 }
 
@@ -98,12 +104,13 @@ func (c *Conn) SetWriteDeadline(t time.Time) error {
 type halfConn struct {
 	sync.Mutex
 
-	err     error       // first permanent error
-	version uint16      // protocol version
-	cipher  interface{} // cipher algorithm
-	mac     macFunction
-	seq     [8]byte // 64-bit sequence number
-	bfree   *block  // list of free blocks
+	err            error       // first permanent error
+	version        uint16      // protocol version
+	cipher         interface{} // cipher algorithm
+	mac            macFunction
+	seq            [8]byte  // 64-bit sequence number
+	bfree          *block   // list of free blocks
+	additionalData [13]byte // to avoid allocs; interface method args escape
 
 	nextCipher interface{} // next encryption state
 	nextMac    macFunction // next MAC algorithm
@@ -262,14 +269,13 @@ func (hc *halfConn) decrypt(b *block) (ok bool, prefixLen int, alertValue alert)
 			nonce := payload[:8]
 			payload = payload[8:]
 
-			var additionalData [13]byte
-			copy(additionalData[:], hc.seq[:])
-			copy(additionalData[8:], b.data[:3])
+			copy(hc.additionalData[:], hc.seq[:])
+			copy(hc.additionalData[8:], b.data[:3])
 			n := len(payload) - c.Overhead()
-			additionalData[11] = byte(n >> 8)
-			additionalData[12] = byte(n)
+			hc.additionalData[11] = byte(n >> 8)
+			hc.additionalData[12] = byte(n)
 			var err error
-			payload, err = c.Open(payload[:0], nonce, payload, additionalData[:])
+			payload, err = c.Open(payload[:0], nonce, payload, hc.additionalData[:])
 			if err != nil {
 				return false, 0, alertBadRecordMAC
 			}
@@ -378,13 +384,12 @@ func (hc *halfConn) encrypt(b *block, explicitIVLen int) (bool, alert) {
 			payload := b.data[recordHeaderLen+explicitIVLen:]
 			payload = payload[:payloadLen]
 
-			var additionalData [13]byte
-			copy(additionalData[:], hc.seq[:])
-			copy(additionalData[8:], b.data[:3])
-			additionalData[11] = byte(payloadLen >> 8)
-			additionalData[12] = byte(payloadLen)
+			copy(hc.additionalData[:], hc.seq[:])
+			copy(hc.additionalData[8:], b.data[:3])
+			hc.additionalData[11] = byte(payloadLen >> 8)
+			hc.additionalData[12] = byte(payloadLen)
 
-			c.Seal(payload[:0], nonce, payload, additionalData[:])
+			c.Seal(payload[:0], nonce, payload, hc.additionalData[:])
 		case cbcMode:
 			blockSize := c.BlockSize()
 			if explicitIVLen > 0 {
@@ -507,6 +512,23 @@ func (hc *halfConn) splitBlock(b *block, n int) (*block, *block) {
 	return b, bb
 }
 
+// RecordHeaderError results when a TLS record header is invalid.
+type RecordHeaderError struct {
+	// Msg contains a human readable string that describes the error.
+	Msg string
+	// RecordHeader contains the five bytes of TLS record header that
+	// triggered the error.
+	RecordHeader [5]byte
+}
+
+func (e RecordHeaderError) Error() string { return "tls: " + e.Msg }
+
+func (c *Conn) newRecordHeaderError(msg string) (err RecordHeaderError) {
+	err.Msg = msg
+	copy(err.RecordHeader[:], c.rawInput.data)
+	return err
+}
+
 // readRecord reads the next TLS record from the connection
 // and updates the record layer state.
 // c.in.Mutex <= L; c.input == nil.
@@ -557,18 +579,20 @@ Again:
 	// an SSLv2 client.
 	if want == recordTypeHandshake && typ == 0x80 {
 		c.sendAlert(alertProtocolVersion)
-		return c.in.setErrorLocked(errors.New("tls: unsupported SSLv2 handshake received"))
+		return c.in.setErrorLocked(c.newRecordHeaderError("unsupported SSLv2 handshake received"))
 	}
 
 	vers := uint16(b.data[1])<<8 | uint16(b.data[2])
 	n := int(b.data[3])<<8 | int(b.data[4])
 	if c.haveVers && vers != c.vers {
 		c.sendAlert(alertProtocolVersion)
-		return c.in.setErrorLocked(fmt.Errorf("tls: received record with version %x when expecting version %x", vers, c.vers))
+		msg := fmt.Sprintf("received record with version %x when expecting version %x", vers, c.vers)
+		return c.in.setErrorLocked(c.newRecordHeaderError(msg))
 	}
 	if n > maxCiphertext {
 		c.sendAlert(alertRecordOverflow)
-		return c.in.setErrorLocked(fmt.Errorf("tls: oversized record received with length %d", n))
+		msg := fmt.Sprintf("oversized record received with length %d", n)
+		return c.in.setErrorLocked(c.newRecordHeaderError(msg))
 	}
 	if !c.haveVers {
 		// First message, be extra suspicious: this might not be a TLS
@@ -577,7 +601,7 @@ Again:
 		// it's probably not real.
 		if (typ != recordTypeAlert && typ != want) || vers >= 0x1000 {
 			c.sendAlert(alertUnexpectedMessage)
-			return c.in.setErrorLocked(fmt.Errorf("tls: first record does not look like a TLS handshake"))
+			return c.in.setErrorLocked(c.newRecordHeaderError("first record does not look like a TLS handshake"))
 		}
 	}
 	if err := b.readFromUntil(c.conn, recordHeaderLen+n); err != nil {
@@ -837,8 +861,22 @@ func (c *Conn) readHandshake() (interface{}, error) {
 	return m, nil
 }
 
+var errClosed = errors.New("crypto/tls: use of closed connection")
+
 // Write writes data to the connection.
 func (c *Conn) Write(b []byte) (int, error) {
+	// interlock with Close below
+	for {
+		x := atomic.LoadInt32(&c.activeCall)
+		if x&1 != 0 {
+			return 0, errClosed
+		}
+		if atomic.CompareAndSwapInt32(&c.activeCall, x, x+2) {
+			defer atomic.AddInt32(&c.activeCall, -2)
+			break
+		}
+	}
+
 	if err := c.Handshake(); err != nil {
 		return 0, err
 	}
@@ -942,6 +980,27 @@ func (c *Conn) Read(b []byte) (n int, err error) {
 
 // Close closes the connection.
 func (c *Conn) Close() error {
+	// Interlock with Conn.Write above.
+	var x int32
+	for {
+		x = atomic.LoadInt32(&c.activeCall)
+		if x&1 != 0 {
+			return errClosed
+		}
+		if atomic.CompareAndSwapInt32(&c.activeCall, x, x|1) {
+			break
+		}
+	}
+	if x != 0 {
+		// io.Writer and io.Closer should not be used concurrently.
+		// If Close is called while a Write is currently in-flight,
+		// interpret that as a sign that this Close is really just
+		// being used to break the Write and/or clean up resources and
+		// avoid sending the alertCloseNotify, which may block
+		// waiting on handshakeMutex or the c.out mutex.
+		return c.conn.Close()
+	}
+
 	var alertErr error
 
 	c.handshakeMutex.Lock()
diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go
index 0b591d7..3c996ac 100644
--- a/src/crypto/tls/handshake_client.go
+++ b/src/crypto/tls/handshake_client.go
@@ -49,13 +49,20 @@ func (c *Conn) clientHandshake() error {
 		return errors.New("tls: NextProtos values too large")
 	}
 
+	sni := c.config.ServerName
+	// IP address literals are not permitted as SNI values. See
+	// https://tools.ietf.org/html/rfc6066#section-3.
+	if net.ParseIP(sni) != nil {
+		sni = ""
+	}
+
 	hello := &clientHelloMsg{
 		vers:                c.config.maxVersion(),
 		compressionMethods:  []uint8{compressionNone},
 		random:              make([]byte, 32),
 		ocspStapling:        true,
 		scts:                true,
-		serverName:          c.config.ServerName,
+		serverName:          sni,
 		supportedCurves:     c.config.curvePreferences(),
 		supportedPoints:     []uint8{pointFormatUncompressed},
 		nextProtoNeg:        len(c.config.NextProtos) > 0,
@@ -158,10 +165,10 @@ NextCipherSuite:
 	c.vers = vers
 	c.haveVers = true
 
-	suite := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
+	suite := mutualCipherSuite(hello.cipherSuites, serverHello.cipherSuite)
 	if suite == nil {
 		c.sendAlert(alertHandshakeFailure)
-		return fmt.Errorf("tls: server selected an unsupported cipher suite")
+		return errors.New("tls: server chose an unconfigured cipher suite")
 	}
 
 	hs := &clientHandshakeState{
diff --git a/src/crypto/tls/handshake_client_test.go b/src/crypto/tls/handshake_client_test.go
index 664fe8d..f78cc46 100644
--- a/src/crypto/tls/handshake_client_test.go
+++ b/src/crypto/tls/handshake_client_test.go
@@ -19,6 +19,7 @@ import (
 	"os/exec"
 	"path/filepath"
 	"strconv"
+	"strings"
 	"testing"
 	"time"
 )
@@ -297,6 +298,22 @@ func TestHandshakeClientRSARC4(t *testing.T) {
 	runClientTestTLS12(t, test)
 }
 
+func TestHandshakeClientRSAAES128GCM(t *testing.T) {
+	test := &clientTest{
+		name:    "AES128-GCM-SHA256",
+		command: []string{"openssl", "s_server", "-cipher", "AES128-GCM-SHA256"},
+	}
+	runClientTestTLS12(t, test)
+}
+
+func TestHandshakeClientRSAAES256GCM(t *testing.T) {
+	test := &clientTest{
+		name:    "AES256-GCM-SHA384",
+		command: []string{"openssl", "s_server", "-cipher", "AES256-GCM-SHA384"},
+	}
+	runClientTestTLS12(t, test)
+}
+
 func TestHandshakeClientECDHERSAAES(t *testing.T) {
 	test := &clientTest{
 		name:    "ECDHE-RSA-AES",
@@ -600,3 +617,80 @@ func TestHandshakClientSCTs(t *testing.T) {
 	}
 	runClientTestTLS12(t, test)
 }
+
+func TestNoIPAddressesInSNI(t *testing.T) {
+	for _, ipLiteral := range []string{"1.2.3.4", "::1"} {
+		c, s := net.Pipe()
+
+		go func() {
+			client := Client(c, &Config{ServerName: ipLiteral})
+			client.Handshake()
+		}()
+
+		var header [5]byte
+		if _, err := io.ReadFull(s, header[:]); err != nil {
+			t.Fatal(err)
+		}
+		recordLen := int(header[3])<<8 | int(header[4])
+
+		record := make([]byte, recordLen)
+		if _, err := io.ReadFull(s, record[:]); err != nil {
+			t.Fatal(err)
+		}
+		s.Close()
+
+		if bytes.Index(record, []byte(ipLiteral)) != -1 {
+			t.Errorf("IP literal %q found in ClientHello: %x", ipLiteral, record)
+		}
+	}
+}
+
+func TestServerSelectingUnconfiguredCipherSuite(t *testing.T) {
+	// This checks that the server can't select a cipher suite that the
+	// client didn't offer. See #13174.
+
+	c, s := net.Pipe()
+	errChan := make(chan error, 1)
+
+	go func() {
+		client := Client(c, &Config{
+			ServerName:   "foo",
+			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
+		})
+		errChan <- client.Handshake()
+	}()
+
+	var header [5]byte
+	if _, err := io.ReadFull(s, header[:]); err != nil {
+		t.Fatal(err)
+	}
+	recordLen := int(header[3])<<8 | int(header[4])
+
+	record := make([]byte, recordLen)
+	if _, err := io.ReadFull(s, record); err != nil {
+		t.Fatal(err)
+	}
+
+	// Create a ServerHello that selects a different cipher suite than the
+	// sole one that the client offered.
+	serverHello := &serverHelloMsg{
+		vers:        VersionTLS12,
+		random:      make([]byte, 32),
+		cipherSuite: TLS_RSA_WITH_AES_256_GCM_SHA384,
+	}
+	serverHelloBytes := serverHello.marshal()
+
+	s.Write([]byte{
+		byte(recordTypeHandshake),
+		byte(VersionTLS12 >> 8),
+		byte(VersionTLS12 & 0xff),
+		byte(len(serverHelloBytes) >> 8),
+		byte(len(serverHelloBytes)),
+	})
+	s.Write(serverHelloBytes)
+	s.Close()
+
+	if err := <-errChan; !strings.Contains(err.Error(), "unconfigured cipher") {
+		t.Fatalf("Expected error about unconfigured cipher suite but got %q", err)
+	}
+}
diff --git a/src/crypto/tls/handshake_messages.go b/src/crypto/tls/handshake_messages.go
index 799a776..111ce53 100644
--- a/src/crypto/tls/handshake_messages.go
+++ b/src/crypto/tls/handshake_messages.go
@@ -763,6 +763,10 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
 				return false
 			}
 			d = d[1:]
+			if len(d) == 0 {
+				// ALPN protocols must not be empty.
+				return false
+			}
 			m.alpnProtocol = string(d)
 		case extensionSCT:
 			d := data[:length]
diff --git a/src/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go
index 20c2bd6..438fb31 100644
--- a/src/crypto/tls/handshake_server_test.go
+++ b/src/crypto/tls/handshake_server_test.go
@@ -84,7 +84,7 @@ func testClientHelloFailure(t *testing.T, serverConfig *Config, m handshakeMessa
 	s.Close()
 	if len(expectedSubStr) == 0 {
 		if err != nil && err != io.EOF {
-			t.Errorf("Got error: %s; expected to succeed", err, expectedSubStr)
+			t.Errorf("Got error: %s; expected to succeed", err)
 		}
 	} else if err == nil || !strings.Contains(err.Error(), expectedSubStr) {
 		t.Errorf("Got error: %s; expected to match substring '%s'", err, expectedSubStr)
diff --git a/src/crypto/tls/prf.go b/src/crypto/tls/prf.go
index 6127c1c..747b817 100644
--- a/src/crypto/tls/prf.go
+++ b/src/crypto/tls/prf.go
@@ -145,11 +145,12 @@ func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, labe
 // masterFromPreMasterSecret generates the master secret from the pre-master
 // secret. See http://tools.ietf.org/html/rfc5246#section-8.1
 func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte {
-	var seed [tlsRandomLength * 2]byte
-	copy(seed[0:len(clientRandom)], clientRandom)
-	copy(seed[len(clientRandom):], serverRandom)
+	seed := make([]byte, 0, len(clientRandom)+len(serverRandom))
+	seed = append(seed, clientRandom...)
+	seed = append(seed, serverRandom...)
+
 	masterSecret := make([]byte, masterSecretLength)
-	prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
+	prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed)
 	return masterSecret
 }
 
@@ -157,13 +158,13 @@ func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecr
 // secret, given the lengths of the MAC key, cipher key and IV, as defined in
 // RFC 2246, section 6.3.
 func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
-	var seed [tlsRandomLength * 2]byte
-	copy(seed[0:len(clientRandom)], serverRandom)
-	copy(seed[len(serverRandom):], clientRandom)
+	seed := make([]byte, 0, len(serverRandom)+len(clientRandom))
+	seed = append(seed, serverRandom...)
+	seed = append(seed, clientRandom...)
 
 	n := 2*macLen + 2*keyLen + 2*ivLen
 	keyMaterial := make([]byte, n)
-	prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
+	prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed)
 	clientMAC = keyMaterial[:macLen]
 	keyMaterial = keyMaterial[macLen:]
 	serverMAC = keyMaterial[:macLen]
diff --git a/src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA
index 4bad786..a62d27d 100644
--- a/src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA
+++ b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-ECDSA
@@ -1,19 +1,19 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 81 01 00 00  7d 03 03 00 00 00 00 00  |........}.......|
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 36  |...../.5.......6|
-00000050  00 05 00 05 01 00 00 00  00 00 0a 00 08 00 06 00  |................|
-00000060  17 00 18 00 19 00 0b 00  02 01 00 00 0d 00 0e 00  |................|
-00000070  0c 04 01 04 03 05 01 05  03 02 01 02 03 ff 01 00  |................|
-00000080  01 00 00 12 00 00                                 |......|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
 >>> Flow 2 (server to client)
-00000000  16 03 01 00 59 02 00 00  55 03 01 c0 e1 5c 5b 45  |....Y...U....\[E|
-00000010  70 fc a1 73 44 e7 69 b6  83 a1 71 bc 03 21 2e cc  |p..sD.i...q..!..|
-00000020  21 7a 28 20 82 6b 2f 77  7d 40 c7 20 0d e4 19 db  |!z( .k/w}@. ....|
-00000030  35 cd 75 a4 e7 e5 6c 3e  c9 d5 fe 9d c5 88 78 7b  |5.u...l>......x{|
-00000040  c4 fc 04 9a c1 10 7a 15  d9 e9 4a 95 c0 09 00 00  |......z...J.....|
+00000000  16 03 01 00 59 02 00 00  55 03 01 38 1a 94 8d 84  |....Y...U..8....|
+00000010  d7 a4 29 89 50 ad 07 97  5b c0 2c 7b 8c a6 75 0e  |..).P...[.,{..u.|
+00000020  97 51 62 10 07 87 c5 6f  0a 5f 86 20 1d ac 1d 05  |.Qb....o._. ....|
+00000030  ea 85 48 84 73 d9 07 8d  d0 81 56 99 81 10 7b 18  |..H.s.....V...{.|
+00000040  e8 5e da a9 fe cd f9 91  88 31 9b 6e c0 09 00 00  |.^.......1.n....|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  01 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
 00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
@@ -48,21 +48,21 @@
 00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
 00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
 00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
-00000270  2a 16 03 01 00 d6 0c 00  00 d2 03 00 17 41 04 01  |*............A..|
-00000280  74 83 af 3a 65 7a ad 1a  63 1f 13 82 9d f4 de 06  |t..:ez..c.......|
-00000290  4e 3a 03 81 61 72 ff f8  58 da 7b f5 81 6d 81 57  |N:..ar..X.{..m.W|
-000002a0  d9 d1 b1 6d e3 97 db 86  72 17 15 18 16 d4 ec 04  |...m....r.......|
-000002b0  32 7c 38 90 6b a4 3c e9  35 79 2d 4c 39 5e 2d 00  |2|8.k.<.5y-L9^-.|
-000002c0  8b 30 81 88 02 42 01 44  78 e1 2a bb 95 f7 45 58  |.0...B.Dx.*...EX|
-000002d0  d4 0d b6 e4 4e ff 48 b3  11 14 ee d5 6c bb 5f 0c  |....N.H.....l._.|
-000002e0  90 b6 ef bc 05 77 f6 05  42 b4 d8 a6 70 e6 8c 90  |.....w..B...p...|
-000002f0  f0 4b 3b c9 d3 4e 0c 85  65 b4 e0 fe b5 10 09 9b  |.K;..N..e.......|
-00000300  e1 08 84 ea 93 96 8e a4  02 42 01 c7 15 ee 9d 98  |.........B......|
-00000310  b7 25 eb 07 ff f6 94 7e  e7 9d a5 17 9e 37 93 40  |.%.....~.....7.@|
-00000320  4c 9f eb 6b a3 7a 57 d8  81 c6 d9 09 34 aa 96 8c  |L..k.zW.....4...|
-00000330  4d 28 2e 9f f7 0b 1c 09  e1 d1 d8 48 6e 8a 8e 9c  |M(.........Hn...|
-00000340  01 4c e7 2d 53 8f 8e 71  61 82 ff ff 16 03 01 00  |.L.-S..qa.......|
-00000350  0e 0d 00 00 06 03 01 02  40 00 00 0e 00 00 00     |........ at ......|
+00000270  2a 16 03 01 00 d5 0c 00  00 d1 03 00 17 41 04 68  |*............A.h|
+00000280  37 18 3d 57 d2 5a 39 75  1e 7f 0a 3a 47 65 36 2e  |7.=W.Z9u...:Ge6.|
+00000290  6d cb 8f aa 0f 0d 45 5e  3f 14 82 f5 8c b1 11 0a  |m.....E^?.......|
+000002a0  8f e0 bc e4 07 d3 d5 bf  2d f4 82 ba cf c9 1c 88  |........-.......|
+000002b0  33 72 a8 49 39 48 40 74  c6 96 c3 30 72 31 34 00  |3r.I9H at t...0r14.|
+000002c0  8a 30 81 87 02 41 0e 43  2d 29 81 e9 c3 07 fc 5c  |.0...A.C-).....\|
+000002d0  ad c0 51 9e 0f cf c5 77  e4 bf 00 b6 66 f9 0e c6  |..Q....w....f...|
+000002e0  40 c6 b5 49 a4 04 05 31  2c 7c 1f 24 38 80 1b 3f  |@..I...1,|.$8..?|
+000002f0  16 5f c7 4d a8 7d 98 50  7f 7d 6d ed e9 19 1d 19  |._.M.}.P.}m.....|
+00000300  7b fd ec c5 4d 18 ab 02  42 01 00 db 37 b7 fa 39  |{...M...B...7..9|
+00000310  4b 3f 16 06 eb b8 4a 22  c6 de 00 d8 a7 eb a2 9e  |K?....J"........|
+00000320  e1 6f f4 a4 32 e2 ca d0  72 3a e5 f3 14 27 a0 dd  |.o..2...r:...'..|
+00000330  c4 26 34 b3 6c a3 d0 03  90 7a 2e 0e bf 0b 63 63  |.&4.l....z....cc|
+00000340  77 66 37 dd 1a 0f 7a 90  3f c8 a9 16 03 01 00 0e  |wf7...z.?.......|
+00000350  0d 00 00 06 03 01 02 40  00 00 0e 00 00 00        |....... at ......|
 >>> Flow 3 (client to server)
 00000000  16 03 01 02 0a 0b 00 02  06 00 02 03 00 02 00 30  |...............0|
 00000010  82 01 fc 30 82 01 5e 02  09 00 9a 30 84 6c 26 35  |...0..^....0.l&5|
@@ -101,30 +101,30 @@
 00000220  51 88 35 75 71 b5 e5 54  5b 12 2e 8f 09 67 fd a7  |Q.5uq..T[....g..|
 00000230  24 20 3e b2 56 1c ce 97  28 5e f8 2b 2d 4f 9e f1  |$ >.V...(^.+-O..|
 00000240  07 9f 6c 4b 5b 83 56 e2  32 42 e9 58 b6 d7 49 a6  |..lK[.V.2B.X..I.|
-00000250  b5 68 1a 41 03 56 6b dc  5a 89 16 03 01 00 91 0f  |.h.A.Vk.Z.......|
-00000260  00 00 8d 00 8b 30 81 88  02 42 01 91 2d e9 99 a4  |.....0...B..-...|
-00000270  88 5c 03 9c ea 8b 64 07  f2 c9 e7 ad 5b a3 fb 27  |.\....d.....[..'|
-00000280  fd 19 9b 78 bd 7b 9d 0a  cc 8a 61 c5 83 33 02 29  |...x.{....a..3.)|
-00000290  c3 66 24 9d 5f bc 03 d9  2a 49 aa 59 51 83 49 72  |.f$._...*I.YQ.Ir|
-000002a0  13 be ea 82 5a 5c 09 2f  da 23 bc 18 02 42 01 0d  |....Z\./.#...B..|
-000002b0  a1 15 4d fe 18 ec 90 d5  4e 9a 75 60 05 67 10 5e  |..M.....N.u`.g.^|
-000002c0  3c 34 00 e8 18 33 8f 90  26 2e d3 a9 81 6c 43 17  |<4...3..&....lC.|
-000002d0  80 9e c5 bd 23 c9 24 96  a1 29 23 a4 13 3f ad d2  |....#.$..)#..?..|
-000002e0  45 19 0b 56 56 4b c1 f1  cc 70 c8 af 44 ff 34 96  |E..VVK...p..D.4.|
-000002f0  14 03 01 00 01 01 16 03  01 00 30 c4 0c 67 53 06  |..........0..gS.|
-00000300  49 b3 c9 5c 2e 72 f6 54  ba ad ac a8 80 55 17 01  |I..\.r.T.....U..|
-00000310  5c 44 71 7d ad 15 34 95  9a 7f 7b 95 0e 08 70 ce  |\Dq}..4...{...p.|
-00000320  5a 33 f4 3b 4e 80 06 43  70 93 17                 |Z3.;N..Cp..|
+00000250  b5 68 1a 41 03 56 6b dc  5a 89 16 03 01 00 90 0f  |.h.A.Vk.Z.......|
+00000260  00 00 8c 00 8a 30 81 87  02 41 51 c5 53 a8 0f cb  |.....0...AQ.S...|
+00000270  18 79 4a 59 53 62 17 bb  29 39 fa cd 56 6c 5c 29  |.yJYSb..)9..Vl\)|
+00000280  1f e3 bc df fb 9a 29 fa  38 1a 73 aa 4c 79 6b 1c  |......).8.s.Lyk.|
+00000290  9f 1c 8e 95 c7 11 cc df  5d e9 c7 93 ce a3 9b e6  |........].......|
+000002a0  94 17 24 3a 8e f8 9a a9  46 01 f9 02 42 01 a1 df  |..$:....F...B...|
+000002b0  c5 cc fe 8d 5b 34 fb 89  2f f5 b3 3f 75 d7 19 1b  |....[4../..?u...|
+000002c0  5e 0f 1a 2e 8f 2d 62 61  73 85 2c 03 3b 22 07 2f  |^....-bas.,.;"./|
+000002d0  6b f3 5c fb ba b2 87 54  1c ef d2 f8 82 f3 9e f8  |k.\....T........|
+000002e0  ce 1b fa ce b0 6d d0 85  f8 62 6e d6 ba 93 cc 14  |.....m...bn.....|
+000002f0  03 01 00 01 01 16 03 01  00 30 76 90 a8 a2 8d 25  |.........0v....%|
+00000300  c5 c2 ff ef 2b 76 83 2c  7a 0d 44 37 99 67 02 d3  |....+v.,z.D7.g..|
+00000310  6e 3b 28 83 21 cf f5 6a  71 61 2d 5b 24 57 b2 19  |n;(.!..jqa-[$W..|
+00000320  63 d4 e5 96 0c 0c e1 f3  3a 99                    |c.......:.|
 >>> Flow 4 (server to client)
-00000000  14 03 01 00 01 01 16 03  01 00 30 3b ba 6c 73 ec  |..........0;.ls.|
-00000010  11 5b 44 46 1d bb 31 1b  1b e8 d8 51 4f 95 b0 40  |.[DF..1....QO..@|
-00000020  87 49 33 73 40 98 61 1c  94 02 48 9b 80 d3 6c af  |.I3s at .a...H...l.|
-00000030  e2 31 63 11 a7 c8 db ed  7a a4 4d                 |.1c.....z.M|
+00000000  14 03 01 00 01 01 16 03  01 00 30 37 f0 ad 4c 11  |..........07..L.|
+00000010  6d fb 54 90 13 d2 10 93  43 d8 be 3b d0 2b 14 a5  |m.T.....C..;.+..|
+00000020  9d fb a6 5d 38 e0 f5 e9  a6 0a 8e 3d 99 a2 ec 96  |...]8......=....|
+00000030  d8 ff 90 13 03 99 33 d7  15 29 5f                 |......3..)_|
 >>> Flow 5 (client to server)
-00000000  17 03 01 00 20 2e f7 66  f0 ce 50 d7 38 7a d4 fd  |.... ..f..P.8z..|
-00000010  e3 66 b1 76 76 59 ad bc  b0 0a 75 1d f0 92 6e e3  |.f.vvY....u...n.|
-00000020  21 1d 13 dc ad 17 03 01  00 20 f1 b2 0f 3b 26 91  |!........ ...;&.|
-00000030  ed ff 9f fc 41 04 7e 47  17 02 af 0c 2b e8 b7 31  |....A.~G....+..1|
-00000040  ae 29 71 f9 a8 89 84 f3  e8 da 15 03 01 00 20 1f  |.)q........... .|
-00000050  26 64 cf 34 c1 48 6b 79  61 e2 77 57 9d 27 14 45  |&d.4.Hkya.wW.'.E|
-00000060  46 24 ad 2d 35 57 db 2b  32 03 e2 68 b0 1a 5a     |F$.-5W.+2..h..Z|
+00000000  17 03 01 00 20 f9 59 b0  e2 8b f9 2c dd 30 1b 8f  |.... .Y....,.0..|
+00000010  df 85 0f 17 88 23 5e ca  c9 d3 ca 5f 52 d4 33 e0  |.....#^...._R.3.|
+00000020  d2 62 54 17 f2 17 03 01  00 20 62 2d 28 d2 55 68  |.bT...... b-(.Uh|
+00000030  77 ab 6e c0 ac d9 cd 31  1c 38 aa 07 b3 e8 0d 89  |w.n....1.8......|
+00000040  7e e4 f3 a0 65 84 f6 b8  c8 91 15 03 01 00 20 b5  |~...e......... .|
+00000050  95 69 90 d7 32 d1 5a a5  e0 e2 6c 0a dc 00 1c 5e  |.i..2.Z...l....^|
+00000060  d2 10 2b a2 3e ae a5 b2  63 9f c4 4e 62 56 db     |..+.>...c..NbV.|
diff --git a/src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA
index 0e420a6..298cbe1 100644
--- a/src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA
+++ b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-ECDSA-RSA
@@ -1,65 +1,60 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 81 01 00 00  7d 03 03 00 00 00 00 00  |........}.......|
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 36  |...../.5.......6|
-00000050  00 05 00 05 01 00 00 00  00 00 0a 00 08 00 06 00  |................|
-00000060  17 00 18 00 19 00 0b 00  02 01 00 00 0d 00 0e 00  |................|
-00000070  0c 04 01 04 03 05 01 05  03 02 01 02 03 ff 01 00  |................|
-00000080  01 00 00 12 00 00                                 |......|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
 >>> Flow 2 (server to client)
-00000000  16 03 01 00 51 02 00 00  4d 03 01 b7 de 52 5a 07  |....Q...M....RZ.|
-00000010  43 b8 72 1d d9 6f 5c a5  70 da ee 27 b7 a9 50 9d  |C.r..o\.p..'..P.|
-00000020  e7 75 ad 61 a5 2f 69 47  2a d8 2e 20 a8 b0 64 6b  |.u.a./iG*.. ..dk|
-00000030  4d 25 ec 50 2b 8e a7 9b  0c f9 f5 3c 62 96 a3 53  |M%.P+......<b..S|
-00000040  a7 4b af 33 1e e7 f8 43  b9 be 6e e7 00 05 00 00  |.K.3...C..n.....|
-00000050  05 ff 01 00 01 00 16 03  01 02 be 0b 00 02 ba 00  |................|
-00000060  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
-00000070  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
-00000080  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
-00000090  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
-000000a0  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
-000000b0  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
-000000c0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
-000000d0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
-000000e0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
-000000f0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
-00000100  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
-00000110  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
-00000120  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
-00000130  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
-00000140  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
-00000150  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
-00000160  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
-00000170  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
-00000180  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
-00000190  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
-000001a0  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
-000001b0  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
-000001c0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
-000001d0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
-000001e0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
-000001f0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
-00000200  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
-00000210  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
-00000220  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
-00000230  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
-00000240  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
-00000250  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
-00000260  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
-00000270  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
-00000280  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
-00000290  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
-000002a0  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
-000002b0  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
-000002c0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
-000002d0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
-000002e0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
-000002f0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
-00000300  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
-00000310  6e 38 50 29 6c 90 a7 bd  d9 16 03 01 00 0e 0d 00  |n8P)l...........|
-00000320  00 06 03 01 02 40 00 00  0e 00 00 00              |..... at ......|
+00000000  16 03 01 00 51 02 00 00  4d 03 01 4e 15 d3 06 f6  |....Q...M..N....|
+00000010  ec 13 16 c5 fa 59 cf 5e  2f ad 85 b9 38 e7 7f fb  |.....Y.^/...8...|
+00000020  85 cb da eb f2 2e 17 51  a2 b0 be 20 61 e4 32 c9  |.......Q... a.2.|
+00000030  66 92 36 89 0c 0c f4 00  15 47 86 d9 e9 90 ab 2d  |f.6......G.....-|
+00000040  8f a3 e2 5e f6 44 2c 6a  1d 98 88 5c 00 05 00 00  |...^.D,j...\....|
+00000050  05 ff 01 00 01 00 16 03  01 02 71 0b 00 02 6d 00  |..........q...m.|
+00000060  02 6a 00 02 67 30 82 02  63 30 82 01 cc a0 03 02  |.j..g0..c0......|
+00000070  01 02 02 09 00 a2 73 00  0c 81 00 cb f3 30 0d 06  |......s......0..|
+00000080  09 2a 86 48 86 f7 0d 01  01 0b 05 00 30 2b 31 17  |.*.H........0+1.|
+00000090  30 15 06 03 55 04 0a 13  0e 47 6f 6f 67 6c 65 20  |0...U....Google |
+000000a0  54 45 53 54 49 4e 47 31  10 30 0e 06 03 55 04 03  |TESTING1.0...U..|
+000000b0  13 07 47 6f 20 52 6f 6f  74 30 1e 17 0d 31 35 30  |..Go Root0...150|
+000000c0  31 30 31 30 30 30 30 30  30 5a 17 0d 32 35 30 31  |101000000Z..2501|
+000000d0  30 31 30 30 30 30 30 30  5a 30 26 31 17 30 15 06  |01000000Z0&1.0..|
+000000e0  03 55 04 0a 13 0e 47 6f  6f 67 6c 65 20 54 45 53  |.U....Google TES|
+000000f0  54 49 4e 47 31 0b 30 09  06 03 55 04 03 13 02 47  |TING1.0...U....G|
+00000100  6f 30 81 9f 30 0d 06 09  2a 86 48 86 f7 0d 01 01  |o0..0...*.H.....|
+00000110  01 05 00 03 81 8d 00 30  81 89 02 81 81 00 af 87  |.......0........|
+00000120  88 f6 20 1b 95 65 6c 14  ab 44 05 af 3b 45 14 e3  |.. ..el..D..;E..|
+00000130  b7 6d fd 00 63 4d 95 7f  fe 6a 62 35 86 c0 4a f9  |.m..cM...jb5..J.|
+00000140  18 7c f6 aa 25 5e 7a 64  31 66 00 ba f4 8e 92 af  |.|..%^zd1f......|
+00000150  c7 6b d8 76 d4 f3 5f 41  cb 6e 56 15 97 1b 97 c1  |.k.v.._A.nV.....|
+00000160  3c 12 39 21 66 3d 2b 16  d1 bc db 1c c0 a7 da b7  |<.9!f=+.........|
+00000170  ca ad ba da cb d5 21 50  ec de 8d ab d1 6b 81 4b  |......!P.....k.K|
+00000180  89 02 f3 c4 be c1 6c 89  b1 44 84 bd 21 d1 04 7d  |......l..D..!..}|
+00000190  9d 16 4d f9 82 15 f6 ef  fa d6 09 47 f2 fb 02 03  |..M........G....|
+000001a0  01 00 01 a3 81 93 30 81  90 30 0e 06 03 55 1d 0f  |......0..0...U..|
+000001b0  01 01 ff 04 04 03 02 05  a0 30 1d 06 03 55 1d 25  |.........0...U.%|
+000001c0  04 16 30 14 06 08 2b 06  01 05 05 07 03 01 06 08  |..0...+.........|
+000001d0  2b 06 01 05 05 07 03 02  30 0c 06 03 55 1d 13 01  |+.......0...U...|
+000001e0  01 ff 04 02 30 00 30 19  06 03 55 1d 0e 04 12 04  |....0.0...U.....|
+000001f0  10 12 50 8d 89 6f 1b d1  dc 54 4d 6e cb 69 5e 06  |..P..o...TMn.i^.|
+00000200  f4 30 1b 06 03 55 1d 23  04 14 30 12 80 10 bf 3d  |.0...U.#..0....=|
+00000210  b6 a9 66 f2 b8 40 cf ea  b4 03 78 48 1a 41 30 19  |..f.. at ....xH.A0.|
+00000220  06 03 55 1d 11 04 12 30  10 82 0e 65 78 61 6d 70  |..U....0...examp|
+00000230  6c 65 2e 67 6f 6c 61 6e  67 30 0d 06 09 2a 86 48  |le.golang0...*.H|
+00000240  86 f7 0d 01 01 0b 05 00  03 81 81 00 92 7c af 91  |.............|..|
+00000250  55 12 18 96 59 31 a6 48  40 d5 2d d5 ee bb 02 a0  |U...Y1.H at .-.....|
+00000260  f5 c2 1e 7c 9b b3 30 7d  3c dc 76 da 4f 3d c0 fa  |...|..0}<.v.O=..|
+00000270  ae 2d 33 24 6b 03 7b 1b  67 59 11 21 b5 11 bc 77  |.-3$k.{.gY.!...w|
+00000280  b9 d9 e0 6e a8 2d 2e 35  fa 64 5f 22 3e 63 10 6b  |...n.-.5.d_">c.k|
+00000290  be ff 14 86 6d 0d f0 15  31 a8 14 38 1e 3b 84 87  |....m...1..8.;..|
+000002a0  2c cb 98 ed 51 76 b9 b1  4f dd db 9b 84 04 86 40  |,...Qv..O......@|
+000002b0  fa 51 dd ba b4 8d eb e3  46 de 46 b9 4f 86 c7 f9  |.Q......F.F.O...|
+000002c0  a4 c2 41 34 ac cc f6 ea  b0 ab 39 18 16 03 01 00  |..A4......9.....|
+000002d0  0e 0d 00 00 06 03 01 02  40 00 00 0e 00 00 00     |........ at ......|
 >>> Flow 3 (client to server)
 00000000  16 03 01 02 0a 0b 00 02  06 00 02 03 00 02 00 30  |...............0|
 00000010  82 01 fc 30 82 01 5e 02  09 00 9a 30 84 6c 26 35  |...0..^....0.l&5|
@@ -94,33 +89,33 @@
 000001e0  be e8 91 b3 da 1a f5 5d  a3 23 f5 26 8b 45 70 8d  |.......].#.&.Ep.|
 000001f0  65 62 9b 7e 01 99 3d 18  f6 10 9a 38 61 9b 2e 57  |eb.~..=....8a..W|
 00000200  e4 fa cc b1 8a ce e2 23  a0 87 f0 e1 67 51 eb 16  |.......#....gQ..|
-00000210  03 01 00 86 10 00 00 82  00 80 6d 51 f3 7f f9 3e  |..........mQ...>|
-00000220  fb 75 82 41 36 83 e8 6a  ee 2a 2e 25 90 67 4c 8e  |.u.A6..j.*.%.gL.|
-00000230  62 2f 30 81 17 e0 85 09  0c 2b b7 23 d7 b0 e2 1d  |b/0......+.#....|
-00000240  f7 3b d7 f5 a1 27 b6 ee  24 b6 1b cc 5b ea 66 0d  |.;...'..$...[.f.|
-00000250  6a f4 e5 85 f9 da 43 b4  0e 86 85 e1 f5 aa be c8  |j.....C.........|
-00000260  ce 39 4c 9c 86 00 08 c2  4b e2 c6 ec 2f f7 ce e6  |.9L.....K.../...|
-00000270  bd 77 82 6f 23 b6 e0 bd  a2 92 b7 3a ac e8 56 f1  |.w.o#......:..V.|
-00000280  af 54 5e 46 87 e9 3b 33  e7 b8 28 b7 d6 c8 90 35  |.T^F..;3..(....5|
-00000290  d4 1c 43 d1 30 6f 55 4e  0a 70 16 03 01 00 91 0f  |..C.0oUN.p......|
-000002a0  00 00 8d 00 8b 30 81 88  02 42 00 b5 1a 9d 48 90  |.....0...B....H.|
-000002b0  2f d9 1a 04 66 f7 3b 4d  d7 ae d9 1e dd 3c fa 24  |/...f.;M.....<.$|
-000002c0  0f 24 97 b2 61 46 16 d9  a0 35 f9 f7 54 45 92 fd  |.$..aF...5..TE..|
-000002d0  10 56 ab 26 d7 b5 10 80  8b 88 95 ef c6 73 1c d2  |.V.&.........s..|
-000002e0  ff e9 20 cd 18 a8 40 c4  4d 83 c2 e2 02 42 01 8c  |.. ... at .M....B..|
-000002f0  d2 13 4c cc e5 38 37 17  6c 83 d6 ad c1 dc af ec  |..L..87.l.......|
-00000300  8d 06 75 b8 08 ad 56 4a  8f b9 03 59 80 f8 81 d4  |..u...VJ...Y....|
-00000310  f3 91 89 eb 9c 27 5d e1  dc 6d ef d6 20 da e7 9c  |.....']..m.. ...|
-00000320  71 75 cb 2a f9 e4 05 46  c8 85 ca 7b 9c 97 e8 6d  |qu.*...F...{...m|
-00000330  14 03 01 00 01 01 16 03  01 00 24 9f 67 4e 22 04  |..........$.gN".|
-00000340  10 f4 28 55 3e 50 88 90  61 07 42 29 f5 9b f5 32  |..(U>P..a.B)...2|
-00000350  16 3d ea c1 8f aa a1 4c  b5 72 26 d8 32 cd 50     |.=.....L.r&.2.P|
+00000210  03 01 00 86 10 00 00 82  00 80 73 bd 73 65 92 86  |..........s.se..|
+00000220  23 41 14 79 7f d5 c1 10  ce 94 4d ad 9c c3 a9 87  |#A.y......M.....|
+00000230  b5 32 52 f8 6b 11 93 2d  9b 98 0b 8b 1d c0 f6 53  |.2R.k..-.......S|
+00000240  17 6d c7 9c 2e ae c9 6f  cc 99 23 38 37 1a 10 fe  |.m.....o..#87...|
+00000250  05 0b b5 55 0a 14 e9 60  7d 70 26 98 e2 54 d9 65  |...U...`}p&..T.e|
+00000260  cf 2e f4 53 5f 1d aa 3a  f6 33 7b eb 4c 0e b3 ff  |...S_..:.3{.L...|
+00000270  5a db 36 2a 47 f3 df f9  fc f5 31 78 83 aa 6b 52  |Z.6*G.....1x..kR|
+00000280  b7 ba 1a 96 bc fa c1 a1  a9 bb 2b f5 38 89 00 4d  |..........+.8..M|
+00000290  e5 78 13 4e a4 38 46 42  dc 16 16 03 01 00 91 0f  |.x.N.8FB........|
+000002a0  00 00 8d 00 8b 30 81 88  02 42 01 45 b9 8f b1 1f  |.....0...B.E....|
+000002b0  72 80 2c 4f 2c 65 58 db  40 7e f1 d5 14 0b cc 4c  |r.,O,eX.@~.....L|
+000002c0  8b 50 5c ee 93 45 95 3d  fe 00 5e 5e ca 13 56 8d  |.P\..E.=..^^..V.|
+000002d0  2b b3 1a 22 70 3f d2 41  cf 74 8f c3 0f 37 ba 97  |+.."p?.A.t...7..|
+000002e0  cb 29 16 77 92 df 19 35  f9 8a a0 8e 02 42 01 00  |.).w...5.....B..|
+000002f0  3f 8b ce b1 2a 01 43 e8  2c b5 27 d1 19 bc 04 b3  |?...*.C.,.'.....|
+00000300  c3 ad bf e8 12 37 57 6f  c9 01 7c 8e f4 4d 88 39  |.....7Wo..|..M.9|
+00000310  4b 00 f6 ff fd 38 39 f8  3e 7f 49 d4 6a 82 94 6a  |K....89.>.I.j..j|
+00000320  d3 f4 17 f2 a9 e0 ef 85  1e 01 85 b6 ca 89 91 ee  |................|
+00000330  14 03 01 00 01 01 16 03  01 00 24 8d 82 24 82 55  |..........$..$.U|
+00000340  c4 0e 45 8c f0 f3 e3 29  4e ff 6c ee 43 4b ca 68  |..E....)N.l.CK.h|
+00000350  2e 12 98 cf ce b6 7e fa  73 07 e1 0f aa 7f 80     |......~.s......|
 >>> Flow 4 (server to client)
-00000000  14 03 01 00 01 01 16 03  01 00 24 df 8d f1 07 6d  |..........$....m|
-00000010  63 39 fc ba b1 67 3b 68  85 b9 37 7d d3 67 19 76  |c9...g;h..7}.g.v|
-00000020  34 a4 1b 86 31 bd fe 06  72 00 d8 2b f2 65 3d     |4...1...r..+.e=|
+00000000  14 03 01 00 01 01 16 03  01 00 24 21 a3 eb a6 f5  |..........$!....|
+00000010  d0 17 38 9b 89 ec f3 39  23 33 f6 49 51 41 97 92  |..8....9#3.IQA..|
+00000020  a6 64 bd 60 68 9d 0e 45  06 2f dd ff 79 b6 50     |.d.`h..E./..y.P|
 >>> Flow 5 (client to server)
-00000000  17 03 01 00 1a 60 cc 81  4f 8b 73 b3 7f 34 bf f1  |.....`..O.s..4..|
-00000010  7c d8 32 0a ef 2a 26 f9  b8 69 84 83 48 21 ee 15  ||.2..*&..i..H!..|
-00000020  03 01 00 16 23 7a 0c 65  3a 66 1a 75 03 e4 85 3f  |....#z.e:f.u...?|
-00000030  83 cd 55 70 99 f4 44 dc  67 ba                    |..Up..D.g.|
+00000000  17 03 01 00 1a d2 72 d5  91 9d fc 6c 22 02 cc 32  |......r....l"..2|
+00000010  58 5c 8a f6 75 11 48 e1  3f e4 e5 81 29 63 62 15  |X\..u.H.?...)cb.|
+00000020  03 01 00 16 b6 9a 1f 43  d4 ae b7 16 25 ce ae b7  |.......C....%...|
+00000030  6c 37 f7 35 0a 26 7d ea  1f 80                    |l7.5.&}...|
diff --git a/src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA
index 7e33edc..ba4976d 100644
--- a/src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA
+++ b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-ECDSA
@@ -1,19 +1,19 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 81 01 00 00  7d 03 03 00 00 00 00 00  |........}.......|
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 36  |...../.5.......6|
-00000050  00 05 00 05 01 00 00 00  00 00 0a 00 08 00 06 00  |................|
-00000060  17 00 18 00 19 00 0b 00  02 01 00 00 0d 00 0e 00  |................|
-00000070  0c 04 01 04 03 05 01 05  03 02 01 02 03 ff 01 00  |................|
-00000080  01 00 00 12 00 00                                 |......|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
 >>> Flow 2 (server to client)
-00000000  16 03 01 00 59 02 00 00  55 03 01 dc a9 22 c2 a2  |....Y...U...."..|
-00000010  05 ba c4 66 9a 71 aa 0f  92 6a fc df b0 29 4d 36  |...f.q...j...)M6|
-00000020  39 2e f8 39 ed 8e f6 7f  8f 17 13 20 f8 9c f3 3d  |9..9....... ...=|
-00000030  0a 41 8f 30 c7 5d cd 17  c5 ad 1c 52 45 a3 47 8c  |.A.0.].....RE.G.|
-00000040  07 4c 48 e1 00 2b 32 38  01 c8 79 b7 c0 09 00 00  |.LH..+28..y.....|
+00000000  16 03 01 00 59 02 00 00  55 03 01 eb ed 76 6a 07  |....Y...U....vj.|
+00000010  65 02 ec 6f 93 a0 38 21  09 0d d7 bf 11 20 51 eb  |e..o..8!..... Q.|
+00000020  cc 00 08 9b 7a 98 c4 c5  02 ff c1 20 f9 1b c7 66  |....z...... ...f|
+00000030  35 40 8c 67 8d 7f d5 c8  28 f0 cb d2 f9 da af 7a  |5 at .g....(......z|
+00000040  ea 4e 42 f2 5d 44 1c cc  92 36 b1 10 c0 09 00 00  |.NB.]D...6......|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  01 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
 00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
@@ -48,20 +48,20 @@
 00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
 00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
 00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
-00000270  2a 16 03 01 00 d5 0c 00  00 d1 03 00 17 41 04 89  |*............A..|
-00000280  95 9a 90 82 59 ab 29 bf  10 06 8c 6c 0d 67 cf b1  |....Y.)....l.g..|
-00000290  66 8b 5e 43 b8 46 56 3a  8d 30 92 35 28 82 f2 38  |f.^C.FV:.0.5(..8|
-000002a0  6e 19 5d 37 f0 ab fc 78  15 6a 6a 73 ca dc a6 f2  |n.]7...x.jjs....|
-000002b0  68 5d b3 ab 6d 68 44 3b  80 d2 d9 cd 78 0a ed 00  |h]..mhD;....x...|
-000002c0  8a 30 81 87 02 42 01 80  63 4a 22 4c 8e 66 4e 25  |.0...B..cJ"L.fN%|
-000002d0  e1 86 27 81 de eb b3 a0  c4 dc dc e2 a0 94 2a b6  |..'...........*.|
-000002e0  b3 e9 e7 42 e1 1d 1a c0  43 8d a1 d6 8d 77 84 06  |...B....C....w..|
-000002f0  ba 95 99 e3 54 80 59 4e  3c fb 0c f3 b7 d3 a8 d2  |....T.YN<.......|
-00000300  ce 49 97 fb e2 79 91 93  02 41 2b 2c b7 9f 81 ea  |.I...y...A+,....|
-00000310  de 17 12 af 4d 20 bc a1  43 1d 60 a0 37 52 a2 7b  |....M ..C.`.7R.{|
-00000320  a8 4c de fd 1d fe 37 3b  00 23 61 ce d2 80 47 43  |.L....7;.#a...GC|
-00000330  b0 3a f3 1f aa c7 07 b1  68 5b d8 f3 03 a9 56 5c  |.:......h[....V\|
-00000340  63 ef 83 1d 9c 9c 8d 29  81 e9 3b 16 03 01 00 0e  |c......)..;.....|
+00000270  2a 16 03 01 00 d5 0c 00  00 d1 03 00 17 41 04 34  |*............A.4|
+00000280  47 57 64 b3 20 6d eb 17  9c 36 d4 aa 78 8b 20 26  |GWd. m...6..x. &|
+00000290  6f 22 10 79 5f 96 69 62  1d ae 9f c7 40 17 1e 30  |o".y_.ib.... at ..0|
+000002a0  10 db d1 13 51 d8 63 61  ef 8e fb 34 d6 02 95 ac  |....Q.ca...4....|
+000002b0  fb 33 72 a9 46 ff 27 b1  15 ca dd 81 8f 5a 58 00  |.3r.F.'......ZX.|
+000002c0  8a 30 81 87 02 41 5c 09  1a 87 40 f3 1a 87 84 31  |.0...A\... at ....1|
+000002d0  62 6c e5 a5 c0 3c cc ba  5d 4a 5e 65 ea e0 60 83  |bl...<..]J^e..`.|
+000002e0  fe fe 99 1d 66 4a bb 6c  0d 5e 25 64 e3 92 ce eb  |....fJ.l.^%d....|
+000002f0  15 39 42 a6 b0 98 a1 d3  79 65 c7 fc e7 c7 64 c7  |.9B.....ye....d.|
+00000300  69 9c 2f 7e 00 c1 a3 02  42 01 f2 61 91 ae 8e f6  |i./~....B..a....|
+00000310  88 99 70 55 32 4a fe 08  31 f0 8d d6 e6 1d fa a1  |..pU2J..1.......|
+00000320  76 b6 16 98 58 8e 46 30  b1 00 b6 dd 5d 70 bb e1  |v...X.F0....]p..|
+00000330  81 89 bd aa ac b5 7f 9b  d3 c0 8b 4b c3 36 00 87  |...........K.6..|
+00000340  47 0c 34 92 27 c3 aa bd  0d 7c 36 16 03 01 00 0e  |G.4.'....|6.....|
 00000350  0d 00 00 06 03 01 02 40  00 00 0e 00 00 00        |....... at ......|
 >>> Flow 3 (client to server)
 00000000  16 03 01 01 fb 0b 00 01  f7 00 01 f4 00 01 f1 30  |...............0|
@@ -101,29 +101,29 @@
 00000220  a7 24 20 3e b2 56 1c ce  97 28 5e f8 2b 2d 4f 9e  |.$ >.V...(^.+-O.|
 00000230  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
 00000240  a6 b5 68 1a 41 03 56 6b  dc 5a 89 16 03 01 00 86  |..h.A.Vk.Z......|
-00000250  0f 00 00 82 00 80 0e 80  9c 3a 6e 40 51 09 39 d4  |.........:n at Q.9.|
-00000260  40 58 10 da 7f 32 12 08  9e f0 4d 9a d7 20 a2 9c  |@X...2....M.. ..|
-00000270  b0 95 3a 33 4e f8 b1 a3  74 62 ab 51 7d 23 d4 32  |..:3N...tb.Q}#.2|
-00000280  a2 af b8 5a 3b b0 23 e4  7a f1 eb 4d b7 bb 23 d5  |...Z;.#.z..M..#.|
-00000290  a9 0d b4 81 d2 b4 45 bd  15 52 ad 58 da 92 a2 c4  |......E..R.X....|
-000002a0  30 66 87 f2 ae c5 e4 8c  fa ba a0 40 76 b8 3f 72  |0f......... at v.?r|
-000002b0  2a d9 95 2a 2d c6 05 3c  1e 2f 11 ef c5 3c 11 e4  |*..*-..<./...<..|
-000002c0  be 5a de 37 43 7f 74 52  6e ee 3c 39 cc f1 14 05  |.Z.7C.tRn.<9....|
-000002d0  2d 91 c2 3d c4 7c 14 03  01 00 01 01 16 03 01 00  |-..=.|..........|
-000002e0  30 cd 3c 92 f8 b9 36 7a  e7 8a fb 0f 2f b8 2c 7b  |0.<...6z..../.,{|
-000002f0  10 59 45 14 0a b0 6a 8c  31 b2 89 5b ac 19 dc 12  |.YE...j.1..[....|
-00000300  73 8c 8c 10 49 5a bf 9f  bc 58 82 32 11 ba c5 38  |s...IZ...X.2...8|
-00000310  ff                                                |.|
+00000250  0f 00 00 82 00 80 1e 4d  89 4e e2 82 ca 5d 31 8a  |.......M.N...]1.|
+00000260  66 c7 c2 d6 00 4d 2e 1e  94 34 61 6b 86 3d 78 60  |f....M...4ak.=x`|
+00000270  70 e1 71 93 22 df 5d 81  d3 d7 33 10 f5 01 f9 1d  |p.q.".]...3.....|
+00000280  e2 4a 91 22 67 ae 5b 2f  4c d9 43 31 35 c6 01 ad  |.J."g.[/L.C15...|
+00000290  59 86 03 a1 9b c5 ea a5  2d aa ef 46 5a a8 70 57  |Y.......-..FZ.pW|
+000002a0  50 59 ea 7a 07 32 bb a6  a1 11 33 05 d8 88 2e 42  |PY.z.2....3....B|
+000002b0  d8 7b f7 34 be 5e 5f 42  9f 6a 90 ed d7 4b c4 7e  |.{.4.^_B.j...K.~|
+000002c0  f9 5c a5 ff 28 f8 a1 f1  8f 1c e0 7a 37 a0 49 e5  |.\..(......z7.I.|
+000002d0  ce 11 46 ef 5f 06 14 03  01 00 01 01 16 03 01 00  |..F._...........|
+000002e0  30 cb 08 f0 3c d4 21 f2  3a 7d db 59 75 80 48 24  |0...<.!.:}.Yu.H$|
+000002f0  27 6f 2c 26 50 a4 7d 6c  91 d5 5d f7 c9 b4 bd 15  |'o,&P.}l..].....|
+00000300  a8 8a 12 d5 40 8c 9a 0f  56 67 66 89 dd 12 36 d8  |.... at ...Vgf...6.|
+00000310  d3                                                |.|
 >>> Flow 4 (server to client)
-00000000  14 03 01 00 01 01 16 03  01 00 30 da 45 99 fe 52  |..........0.E..R|
-00000010  4f cd d0 e6 30 19 f4 bd  80 6d 5c 8a 72 03 d3 88  |O...0....m\.r...|
-00000020  38 63 e9 c9 39 ee ab 3f  52 26 84 b0 4d cb 5c a4  |8c..9..?R&..M.\.|
-00000030  0d 51 c7 47 48 43 3a bf  89 c7 13                 |.Q.GHC:....|
+00000000  14 03 01 00 01 01 16 03  01 00 30 02 e3 be 9d 2d  |..........0....-|
+00000010  6f 2c 9a b7 b4 f1 a5 30  ec 3e ae 05 e6 02 19 2f  |o,.....0.>...../|
+00000020  a4 ac d1 6e ac de 75 4e  cc 14 e6 78 5a ea 27 7f  |...n..uN...xZ.'.|
+00000030  4e 45 c4 9d b2 da a6 ea  b7 d2 7e                 |NE........~|
 >>> Flow 5 (client to server)
-00000000  17 03 01 00 20 4d d9 1d  0d 3d 8b 73 91 b9 4e 5e  |.... M...=.s..N^|
-00000010  35 71 4f 67 79 d2 f7 39  35 ea 23 d0 6d 64 de a5  |5qOgy..95.#.md..|
-00000020  59 fb 75 1f c9 17 03 01  00 20 ba bd 3c b4 d7 be  |Y.u...... ..<...|
-00000030  24 64 68 1e 8c b2 bf 6f  78 9f ad 7f fa dd 89 a6  |$dh....ox.......|
-00000040  f9 e7 5e 70 db e9 db 3a  62 b2 15 03 01 00 20 2a  |..^p...:b..... *|
-00000050  82 f4 8b 45 fc 76 35 6c  54 48 62 2f 52 55 f2 d9  |...E.v5lTHb/RU..|
-00000060  99 b2 b5 2d 5f a0 05 ab  f1 93 58 75 4a 87 35     |...-_.....XuJ.5|
+00000000  17 03 01 00 20 e0 71 e9  54 11 6e 48 4b be a2 2a  |.... .q.T.nHK..*|
+00000010  b1 70 d2 2c 74 c0 f4 74  05 f1 d3 d6 84 29 58 f7  |.p.,t..t.....)X.|
+00000020  87 90 84 2b c8 17 03 01  00 20 b6 a2 e9 e0 f0 0d  |...+..... ......|
+00000030  d5 ef d7 32 6d cb 99 5d  a6 37 c2 6e f9 c3 8e 6f  |...2m..].7.n...o|
+00000040  76 71 d8 a6 c5 ae 4e 04  77 06 15 03 01 00 20 f2  |vq....N.w..... .|
+00000050  09 ab dc 37 90 78 3a 2a  41 ab 9b a9 c1 78 2a 64  |...7.x:*A....x*d|
+00000060  a8 3f 21 c4 bb af 76 b3  c6 2f e1 20 a3 b1 1e     |.?!...v../. ...|
diff --git a/src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA
index 9b1a553..e007870 100644
--- a/src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA
+++ b/src/crypto/tls/testdata/Client-TLSv10-ClientCert-RSA-RSA
@@ -1,65 +1,60 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 81 01 00 00  7d 03 03 00 00 00 00 00  |........}.......|
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 36  |...../.5.......6|
-00000050  00 05 00 05 01 00 00 00  00 00 0a 00 08 00 06 00  |................|
-00000060  17 00 18 00 19 00 0b 00  02 01 00 00 0d 00 0e 00  |................|
-00000070  0c 04 01 04 03 05 01 05  03 02 01 02 03 ff 01 00  |................|
-00000080  01 00 00 12 00 00                                 |......|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
 >>> Flow 2 (server to client)
-00000000  16 03 01 00 51 02 00 00  4d 03 01 90 e6 e1 c6 bd  |....Q...M.......|
-00000010  86 08 db 33 94 f3 bd 0b  2d fc e0 ba 89 a7 c5 66  |...3....-......f|
-00000020  a5 19 78 33 2b b9 c4 22  d8 e0 63 20 2e 85 53 25  |..x3+.."..c ..S%|
-00000030  f2 22 e3 ca 79 94 9e 50  00 13 da 9d 21 33 49 27  |."..y..P....!3I'|
-00000040  9b 44 c5 10 bc e8 44 01  04 31 02 81 00 05 00 00  |.D....D..1......|
-00000050  05 ff 01 00 01 00 16 03  01 02 be 0b 00 02 ba 00  |................|
-00000060  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
-00000070  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
-00000080  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
-00000090  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
-000000a0  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
-000000b0  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
-000000c0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
-000000d0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
-000000e0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
-000000f0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
-00000100  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
-00000110  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
-00000120  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
-00000130  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
-00000140  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
-00000150  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
-00000160  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
-00000170  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
-00000180  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
-00000190  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
-000001a0  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
-000001b0  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
-000001c0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
-000001d0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
-000001e0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
-000001f0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
-00000200  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
-00000210  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
-00000220  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
-00000230  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
-00000240  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
-00000250  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
-00000260  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
-00000270  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
-00000280  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
-00000290  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
-000002a0  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
-000002b0  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
-000002c0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
-000002d0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
-000002e0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
-000002f0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
-00000300  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
-00000310  6e 38 50 29 6c 90 a7 bd  d9 16 03 01 00 0e 0d 00  |n8P)l...........|
-00000320  00 06 03 01 02 40 00 00  0e 00 00 00              |..... at ......|
+00000000  16 03 01 00 51 02 00 00  4d 03 01 e5 d7 4b 56 7b  |....Q...M....KV{|
+00000010  a8 2c 07 33 fc 66 d7 79  e9 26 91 56 7d 9d 99 1d  |.,.3.f.y.&.V}...|
+00000020  b2 24 36 2c f6 78 3a e7  63 15 f6 20 9f e1 d4 07  |.$6,.x:.c.. ....|
+00000030  a9 75 3d b9 3b 8c 46 cb  a7 37 36 56 af 4e 99 cf  |.u=.;.F..76V.N..|
+00000040  90 49 e1 e9 69 25 81 0f  fd 22 48 e6 00 05 00 00  |.I..i%..."H.....|
+00000050  05 ff 01 00 01 00 16 03  01 02 71 0b 00 02 6d 00  |..........q...m.|
+00000060  02 6a 00 02 67 30 82 02  63 30 82 01 cc a0 03 02  |.j..g0..c0......|
+00000070  01 02 02 09 00 a2 73 00  0c 81 00 cb f3 30 0d 06  |......s......0..|
+00000080  09 2a 86 48 86 f7 0d 01  01 0b 05 00 30 2b 31 17  |.*.H........0+1.|
+00000090  30 15 06 03 55 04 0a 13  0e 47 6f 6f 67 6c 65 20  |0...U....Google |
+000000a0  54 45 53 54 49 4e 47 31  10 30 0e 06 03 55 04 03  |TESTING1.0...U..|
+000000b0  13 07 47 6f 20 52 6f 6f  74 30 1e 17 0d 31 35 30  |..Go Root0...150|
+000000c0  31 30 31 30 30 30 30 30  30 5a 17 0d 32 35 30 31  |101000000Z..2501|
+000000d0  30 31 30 30 30 30 30 30  5a 30 26 31 17 30 15 06  |01000000Z0&1.0..|
+000000e0  03 55 04 0a 13 0e 47 6f  6f 67 6c 65 20 54 45 53  |.U....Google TES|
+000000f0  54 49 4e 47 31 0b 30 09  06 03 55 04 03 13 02 47  |TING1.0...U....G|
+00000100  6f 30 81 9f 30 0d 06 09  2a 86 48 86 f7 0d 01 01  |o0..0...*.H.....|
+00000110  01 05 00 03 81 8d 00 30  81 89 02 81 81 00 af 87  |.......0........|
+00000120  88 f6 20 1b 95 65 6c 14  ab 44 05 af 3b 45 14 e3  |.. ..el..D..;E..|
+00000130  b7 6d fd 00 63 4d 95 7f  fe 6a 62 35 86 c0 4a f9  |.m..cM...jb5..J.|
+00000140  18 7c f6 aa 25 5e 7a 64  31 66 00 ba f4 8e 92 af  |.|..%^zd1f......|
+00000150  c7 6b d8 76 d4 f3 5f 41  cb 6e 56 15 97 1b 97 c1  |.k.v.._A.nV.....|
+00000160  3c 12 39 21 66 3d 2b 16  d1 bc db 1c c0 a7 da b7  |<.9!f=+.........|
+00000170  ca ad ba da cb d5 21 50  ec de 8d ab d1 6b 81 4b  |......!P.....k.K|
+00000180  89 02 f3 c4 be c1 6c 89  b1 44 84 bd 21 d1 04 7d  |......l..D..!..}|
+00000190  9d 16 4d f9 82 15 f6 ef  fa d6 09 47 f2 fb 02 03  |..M........G....|
+000001a0  01 00 01 a3 81 93 30 81  90 30 0e 06 03 55 1d 0f  |......0..0...U..|
+000001b0  01 01 ff 04 04 03 02 05  a0 30 1d 06 03 55 1d 25  |.........0...U.%|
+000001c0  04 16 30 14 06 08 2b 06  01 05 05 07 03 01 06 08  |..0...+.........|
+000001d0  2b 06 01 05 05 07 03 02  30 0c 06 03 55 1d 13 01  |+.......0...U...|
+000001e0  01 ff 04 02 30 00 30 19  06 03 55 1d 0e 04 12 04  |....0.0...U.....|
+000001f0  10 12 50 8d 89 6f 1b d1  dc 54 4d 6e cb 69 5e 06  |..P..o...TMn.i^.|
+00000200  f4 30 1b 06 03 55 1d 23  04 14 30 12 80 10 bf 3d  |.0...U.#..0....=|
+00000210  b6 a9 66 f2 b8 40 cf ea  b4 03 78 48 1a 41 30 19  |..f.. at ....xH.A0.|
+00000220  06 03 55 1d 11 04 12 30  10 82 0e 65 78 61 6d 70  |..U....0...examp|
+00000230  6c 65 2e 67 6f 6c 61 6e  67 30 0d 06 09 2a 86 48  |le.golang0...*.H|
+00000240  86 f7 0d 01 01 0b 05 00  03 81 81 00 92 7c af 91  |.............|..|
+00000250  55 12 18 96 59 31 a6 48  40 d5 2d d5 ee bb 02 a0  |U...Y1.H at .-.....|
+00000260  f5 c2 1e 7c 9b b3 30 7d  3c dc 76 da 4f 3d c0 fa  |...|..0}<.v.O=..|
+00000270  ae 2d 33 24 6b 03 7b 1b  67 59 11 21 b5 11 bc 77  |.-3$k.{.gY.!...w|
+00000280  b9 d9 e0 6e a8 2d 2e 35  fa 64 5f 22 3e 63 10 6b  |...n.-.5.d_">c.k|
+00000290  be ff 14 86 6d 0d f0 15  31 a8 14 38 1e 3b 84 87  |....m...1..8.;..|
+000002a0  2c cb 98 ed 51 76 b9 b1  4f dd db 9b 84 04 86 40  |,...Qv..O......@|
+000002b0  fa 51 dd ba b4 8d eb e3  46 de 46 b9 4f 86 c7 f9  |.Q......F.F.O...|
+000002c0  a4 c2 41 34 ac cc f6 ea  b0 ab 39 18 16 03 01 00  |..A4......9.....|
+000002d0  0e 0d 00 00 06 03 01 02  40 00 00 0e 00 00 00     |........ at ......|
 >>> Flow 3 (client to server)
 00000000  16 03 01 01 fb 0b 00 01  f7 00 01 f4 00 01 f1 30  |...............0|
 00000010  82 01 ed 30 82 01 58 a0  03 02 01 02 02 01 00 30  |...0..X........0|
@@ -93,33 +88,33 @@
 000001d0  8b ec ab 67 be c8 64 b0  11 50 46 58 17 6b 99 1c  |...g..d..PFX.k..|
 000001e0  d3 1d fc 06 f1 0e e5 96  a8 0c f9 78 20 b7 44 18  |...........x .D.|
 000001f0  51 8d 10 7e 4f 94 67 df  a3 4e 70 73 8e 90 91 85  |Q..~O.g..Nps....|
-00000200  16 03 01 00 86 10 00 00  82 00 80 6d 51 f3 7f f9  |...........mQ...|
-00000210  3e fb 75 82 41 36 83 e8  6a ee 2a 2e 25 90 67 4c  |>.u.A6..j.*.%.gL|
-00000220  8e 62 2f 30 81 17 e0 85  09 0c 2b b7 23 d7 b0 e2  |.b/0......+.#...|
-00000230  1d f7 3b d7 f5 a1 27 b6  ee 24 b6 1b cc 5b ea 66  |..;...'..$...[.f|
-00000240  0d 6a f4 e5 85 f9 da 43  b4 0e 86 85 e1 f5 aa be  |.j.....C........|
-00000250  c8 ce 39 4c 9c 86 00 08  c2 4b e2 c6 ec 2f f7 ce  |..9L.....K.../..|
-00000260  e6 bd 77 82 6f 23 b6 e0  bd a2 92 b7 3a ac e8 56  |..w.o#......:..V|
-00000270  f1 af 54 5e 46 87 e9 3b  33 e7 b8 28 b7 d6 c8 90  |..T^F..;3..(....|
-00000280  35 d4 1c 43 d1 30 6f 55  4e 0a 70 16 03 01 00 86  |5..C.0oUN.p.....|
-00000290  0f 00 00 82 00 80 10 19  57 14 c3 ee 2d da cb de  |........W...-...|
-000002a0  f3 70 c5 62 91 2f ad 62  dd 10 f1 65 20 a2 cf d5  |.p.b./.b...e ...|
-000002b0  cd 6d 5f e4 b3 3e 38 e8  d0 1a f7 f0 e7 7e b6 5d  |.m_..>8......~.]|
-000002c0  c3 6c ad f6 0d 05 1e 41  35 2d 04 15 3c 36 96 00  |.l.....A5-..<6..|
-000002d0  e8 02 b2 01 b8 9f 21 4b  34 85 ef 5e 4c 87 ef 49  |......!K4..^L..I|
-000002e0  df d1 9a b6 b2 bd b8 90  fd 3f 31 93 0c dc c7 18  |.........?1.....|
-000002f0  ff f6 76 bd 5b 74 76 b3  62 87 6a df ff 63 15 d5  |..v.[tv.b.j..c..|
-00000300  94 d5 fe fd 4c 12 df f1  35 07 f1 8a f1 77 7a 35  |....L...5....wz5|
-00000310  cd 99 1d 2a d7 9a 14 03  01 00 01 01 16 03 01 00  |...*............|
-00000320  24 8d db 0c 87 b5 df fd  68 de fe 46 3e e4 41 b5  |$.......h..F>.A.|
-00000330  19 64 68 3c c4 e2 2b 43  50 e4 ee 52 75 34 d3 c1  |.dh<..+CP..Ru4..|
-00000340  51 18 c0 b2 5f                                    |Q..._|
+00000200  16 03 01 00 86 10 00 00  82 00 80 73 bd 73 65 92  |...........s.se.|
+00000210  86 23 41 14 79 7f d5 c1  10 ce 94 4d ad 9c c3 a9  |.#A.y......M....|
+00000220  87 b5 32 52 f8 6b 11 93  2d 9b 98 0b 8b 1d c0 f6  |..2R.k..-.......|
+00000230  53 17 6d c7 9c 2e ae c9  6f cc 99 23 38 37 1a 10  |S.m.....o..#87..|
+00000240  fe 05 0b b5 55 0a 14 e9  60 7d 70 26 98 e2 54 d9  |....U...`}p&..T.|
+00000250  65 cf 2e f4 53 5f 1d aa  3a f6 33 7b eb 4c 0e b3  |e...S_..:.3{.L..|
+00000260  ff 5a db 36 2a 47 f3 df  f9 fc f5 31 78 83 aa 6b  |.Z.6*G.....1x..k|
+00000270  52 b7 ba 1a 96 bc fa c1  a1 a9 bb 2b f5 38 89 00  |R..........+.8..|
+00000280  4d e5 78 13 4e a4 38 46  42 dc 16 16 03 01 00 86  |M.x.N.8FB.......|
+00000290  0f 00 00 82 00 80 3d f7  ff c1 72 82 b8 90 42 a3  |......=...r...B.|
+000002a0  10 24 b5 01 44 60 98 39  e4 36 86 56 09 55 e5 73  |.$..D`.9.6.V.U.s|
+000002b0  3a d9 9d 00 ae 05 23 6f  78 4e 49 28 c1 cc 7a ff  |:.....#oxNI(..z.|
+000002c0  8f 67 92 cd 94 c0 d2 68  7f 48 ec 10 83 48 9e 02  |.g.....h.H...H..|
+000002d0  b8 10 b2 1b f0 ba 8f 5a  c8 85 d9 19 53 c2 8d 37  |.......Z....S..7|
+000002e0  8e 86 4c ca ee 0f c4 97  20 f9 a5 4e 94 b8 c5 c5  |..L..... ..N....|
+000002f0  53 0c c1 b6 e5 a1 4e d6  15 b3 6b 08 c2 25 c3 de  |S.....N...k..%..|
+00000300  e7 69 85 85 56 31 16 ad  68 7e 00 8f 1b fc f8 9f  |.i..V1..h~......|
+00000310  d7 50 87 08 0d c5 14 03  01 00 01 01 16 03 01 00  |.P..............|
+00000320  24 eb 0c f3 4f 56 04 e3  54 b0 a8 e4 bb af 3a 44  |$...OV..T.....:D|
+00000330  c7 d6 f0 24 2f fc e6 79  93 f4 4e ec c5 1f 5b 99  |...$/..y..N...[.|
+00000340  32 37 c2 f1 ad                                    |27...|
 >>> Flow 4 (server to client)
-00000000  14 03 01 00 01 01 16 03  01 00 24 0b a4 04 46 60  |..........$...F`|
-00000010  15 fb 9a 9f 47 51 6d b4  4b c6 e7 2a 1b 98 b4 8a  |....GQm.K..*....|
-00000020  8a 1a 03 cf f4 16 7d 80  70 27 e5 e8 d5 9f ad     |......}.p'.....|
+00000000  14 03 01 00 01 01 16 03  01 00 24 75 ac 09 a6 28  |..........$u...(|
+00000010  60 ce 7f 81 a2 75 86 af  84 95 dc 3f e1 07 1c 02  |`....u.....?....|
+00000020  bc 3c 90 db 1e 1a 35 06  93 60 22 69 b9 05 bb     |.<....5..`"i...|
 >>> Flow 5 (client to server)
-00000000  17 03 01 00 1a 6f 84 50  27 c7 f1 aa b0 04 7d 80  |.....o.P'.....}.|
-00000010  6d a7 20 8a 73 cf d9 de  9a d6 f5 e9 36 13 7c 15  |m. .s.......6.|.|
-00000020  03 01 00 16 e8 0b e0 a6  3b 1e 21 24 65 4e 49 b2  |........;.!$eNI.|
-00000030  2d a3 41 2b 98 23 4e d5  4b fd                    |-.A+.#N.K.|
+00000000  17 03 01 00 1a f4 67 a7  d8 0a 67 8d 3a 11 53 7e  |......g...g.:.S~|
+00000010  49 91 bf 92 85 e0 35 24  25 72 92 26 63 9b 09 15  |I.....5$%r.&c...|
+00000020  03 01 00 16 98 bb a0 ca  40 70 26 6f 2d 73 35 3d  |........ at p&o-s5=|
+00000030  90 8c ff 01 e0 b1 50 52  e3 57                    |......PR.W|
diff --git a/src/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES b/src/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES
index 937c290..929e1c6 100644
--- a/src/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES
+++ b/src/crypto/tls/testdata/Client-TLSv10-ECDHE-ECDSA-AES
@@ -1,19 +1,19 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 81 01 00 00  7d 03 03 00 00 00 00 00  |........}.......|
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 36  |...../.5.......6|
-00000050  00 05 00 05 01 00 00 00  00 00 0a 00 08 00 06 00  |................|
-00000060  17 00 18 00 19 00 0b 00  02 01 00 00 0d 00 0e 00  |................|
-00000070  0c 04 01 04 03 05 01 05  03 02 01 02 03 ff 01 00  |................|
-00000080  01 00 00 12 00 00                                 |......|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
 >>> Flow 2 (server to client)
-00000000  16 03 01 00 59 02 00 00  55 03 01 f5 8f 8d 8e ca  |....Y...U.......|
-00000010  30 6b fe 63 c9 84 57 c0  f1 c8 a5 d8 10 56 14 62  |0k.c..W......V.b|
-00000020  c8 02 b2 89 21 5c 09 67  86 d8 9b 20 dc 3f 55 54  |....!\.g... .?UT|
-00000030  33 29 47 45 d3 e0 87 1a  4b 1b 75 30 89 e0 4d 01  |3)GE....K.u0..M.|
-00000040  a1 6a 46 f7 8f 23 d6 74  fd 90 2f 53 c0 09 00 00  |.jF..#.t../S....|
+00000000  16 03 01 00 59 02 00 00  55 03 01 78 09 57 86 09  |....Y...U..x.W..|
+00000010  64 7e 35 c7 c7 b9 44 9c  09 ae f0 49 cb 1c 1f 58  |d~5...D....I...X|
+00000020  89 ef 65 16 9e 32 73 cd  4d 1b 8f 20 10 4d 5b cf  |..e..2s.M.. .M[.|
+00000030  d0 24 59 dd e8 47 c9 a2  ad 9c 98 b5 eb 16 46 6b  |.$Y..G........Fk|
+00000040  7d 33 6e 53 0a 3d 81 71  a1 bc 43 7a c0 09 00 00  |}3nS.=.q..Cz....|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  01 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
 00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
@@ -48,41 +48,41 @@
 00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
 00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
 00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
-00000270  2a 16 03 01 00 d5 0c 00  00 d1 03 00 17 41 04 22  |*............A."|
-00000280  8a 47 c6 d3 7a c4 30 a4  8e 41 11 ac b3 2d 2f 45  |.G..z.0..A...-/E|
-00000290  61 54 9b 1f 2e 03 5d 50  eb fc 5b 44 a0 a7 48 78  |aT....]P..[D..Hx|
-000002a0  ce 14 d5 39 a7 c4 ed f5  4d 8f da 9d 71 52 69 70  |...9....M...qRip|
-000002b0  7e 52 29 ad 80 8a 19 ad  4c 5d 1c f1 22 7e 1a 00  |~R).....L].."~..|
-000002c0  8a 30 81 87 02 42 00 97  8b 6d f7 87 c1 a9 a6 55  |.0...B...m.....U|
-000002d0  0f 61 c2 f2 e1 05 26 a8  83 16 1c 0b 69 3b 95 57  |.a....&.....i;.W|
-000002e0  76 5b eb 45 7a bd 6a f1  3e a0 93 49 fa 74 32 fd  |v[.Ez.j.>..I.t2.|
-000002f0  dc 20 3a bb e3 ee 6d b8  56 aa e9 d2 7d 6a ec b7  |. :...m.V...}j..|
-00000300  0a bd aa dc d7 b0 69 65  02 41 4d 19 61 16 d8 5f  |......ie.AM.a.._|
-00000310  1d c1 32 25 15 26 eb 88  5b c1 dd 9a 12 40 fa f1  |..2%.&..[.... at ..|
-00000320  81 5e 7d b8 2b 6e 60 63  1a 9e 86 cb d5 64 96 d4  |.^}.+n`c.....d..|
-00000330  75 fc 02 33 e0 66 60 b2  40 47 cf e6 6d 25 9c 83  |u..3.f`. at G..m%..|
-00000340  23 d3 4b e2 eb ac f1 56  44 f8 3f 16 03 01 00 04  |#.K....VD.?.....|
-00000350  0e 00 00 00                                       |....|
+00000270  2a 16 03 01 00 d6 0c 00  00 d2 03 00 17 41 04 51  |*............A.Q|
+00000280  39 70 43 9c 01 de 29 df  3c d0 f8 31 54 70 34 53  |9pC...).<..1Tp4S|
+00000290  0e ab e8 e0 b0 8b 21 66  63 ac a9 68 7c 92 6f f8  |......!fc..h|.o.|
+000002a0  cf a3 ba cb 6d 39 f4 5c  f5 2e ff 1d d7 1b b9 e7  |....m9.\........|
+000002b0  08 13 59 f8 64 7e 23 e0  1d 04 cf 37 47 d6 b7 00  |..Y.d~#....7G...|
+000002c0  8b 30 81 88 02 42 01 cd  1d 01 46 68 da 4c b6 0d  |.0...B....Fh.L..|
+000002d0  67 05 39 0d aa 6c c5 40  e4 5d bf 4f 2a 92 78 8d  |g.9..l. at .].O*.x.|
+000002e0  08 0e c0 07 8c 68 cc 55  4e 54 a9 9d 22 f9 a6 4a  |.....h.UNT.."..J|
+000002f0  e4 38 9f 53 4a 60 e8 eb  81 02 50 75 7e 13 31 2a  |.8.SJ`....Pu~.1*|
+00000300  ff 3e 17 cd b4 d1 d4 75  02 42 01 95 ba b6 a0 12  |.>.....u.B......|
+00000310  23 59 9f ae 1c c0 60 d2  8f 59 6b 35 ee b3 3f ac  |#Y....`..Yk5..?.|
+00000320  e4 42 9a 23 d0 f4 fd a1  3c 36 1b 31 33 76 8d f0  |.B.#....<6.13v..|
+00000330  b6 66 fd 92 9a 2a 27 8b  06 11 72 41 09 bd 27 55  |.f...*'...rA..'U|
+00000340  c7 1b a9 d1 49 5e 8f 85  dc aa 9d be 16 03 01 00  |....I^..........|
+00000350  04 0e 00 00 00                                    |.....|
 >>> Flow 3 (client to server)
 00000000  16 03 01 00 46 10 00 00  42 41 04 1e 18 37 ef 0d  |....F...BA...7..|
 00000010  19 51 88 35 75 71 b5 e5  54 5b 12 2e 8f 09 67 fd  |.Q.5uq..T[....g.|
 00000020  a7 24 20 3e b2 56 1c ce  97 28 5e f8 2b 2d 4f 9e  |.$ >.V...(^.+-O.|
 00000030  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
 00000040  a6 b5 68 1a 41 03 56 6b  dc 5a 89 14 03 01 00 01  |..h.A.Vk.Z......|
-00000050  01 16 03 01 00 30 cc 86  f1 7e 6e a8 c9 b5 02 5f  |.....0...~n...._|
-00000060  fb b2 3b ea 74 bf a8 da  e4 6a 69 50 a2 5a 78 4f  |..;.t....jiP.ZxO|
-00000070  35 e1 cc 87 c3 fb 1f 5e  f6 a4 5c 63 cc 59 12 3e  |5......^..\c.Y.>|
-00000080  07 c3 a8 d7 87 ba                                 |......|
+00000050  01 16 03 01 00 30 64 61  7f ea 98 8e e7 c9 0f ea  |.....0da........|
+00000060  0a b3 52 ba 3d 01 36 a4  47 24 7b 2d 19 b5 7e 92  |..R.=.6.G${-..~.|
+00000070  04 b7 8c 4f fc 02 5d 79  15 3e 50 72 05 3c df d2  |...O..]y.>Pr.<..|
+00000080  c6 a3 b3 c8 7c 48                                 |....|H|
 >>> Flow 4 (server to client)
-00000000  14 03 01 00 01 01 16 03  01 00 30 e8 b6 20 b9 c1  |..........0.. ..|
-00000010  07 38 38 bb 42 b2 b2 a1  c5 8d 92 62 db 67 ab fc  |.88.B......b.g..|
-00000020  f6 64 3f 71 83 1d a0 86  bb 2d e3 4f 65 d5 44 52  |.d?q.....-.Oe.DR|
-00000030  4d f5 62 80 3c af 95 87  19 7c 20                 |M.b.<....| |
+00000000  14 03 01 00 01 01 16 03  01 00 30 7d 49 8d e9 da  |..........0}I...|
+00000010  87 77 18 4d 10 63 17 ed  1f 34 7a d4 be e3 dd b6  |.w.M.c...4z.....|
+00000020  8b f3 a7 06 bc de 76 8e  04 be 8a 95 5b 24 19 ec  |......v.....[$..|
+00000030  66 55 8a 1b e0 df 0b a1  57 cb 67                 |fU......W.g|
 >>> Flow 5 (client to server)
-00000000  17 03 01 00 20 bd 65 61  28 e5 ea 1b 81 db 75 92  |.... .ea(.....u.|
-00000010  ad a7 3b 01 a3 23 0e 3b  60 10 8a 1e 04 91 fb 9e  |..;..#.;`.......|
-00000020  7a cf 1f cf 9c 17 03 01  00 20 87 9c dc ed 0d 08  |z........ ......|
-00000030  56 40 23 8b c5 2c d8 7e  42 82 3c 0a c9 f3 77 6d  |V@#..,.~B.<...wm|
-00000040  8d 9a 30 d1 9c c4 ae 04  fb b7 15 03 01 00 20 f7  |..0........... .|
-00000050  f0 12 0d e5 03 c1 80 4e  7e 21 d7 75 55 1c 91 89  |.......N~!.uU...|
-00000060  e7 e1 45 fc 7d d8 fc b1  d0 e7 dc e2 4c ba f4     |..E.}.......L..|
+00000000  17 03 01 00 20 2d a3 e5  55 13 3f 73 8e ba 41 79  |.... -..U.?s..Ay|
+00000010  65 e0 83 d5 3a ea cd e9  a8 b4 4b 3c d0 0c bf 06  |e...:.....K<....|
+00000020  75 2a 67 f2 f7 17 03 01  00 20 a0 8d 3c a2 ca b3  |u*g...... ..<...|
+00000030  f3 e5 36 dc 44 a4 3b ad  cd 03 be a9 70 a8 75 51  |..6.D.;.....p.uQ|
+00000040  0f 8e 9f 7c a7 3c 03 84  38 88 15 03 01 00 20 75  |...|.<..8..... u|
+00000050  0f db fe 48 b4 7e 04 3b  f5 5b 47 5b 0a ab 69 18  |...H.~.;.[G[..i.|
+00000060  37 bb 89 d3 a8 40 ba 53  3b 5f 6d 8b 06 ff ae     |7.... at .S;_m....|
diff --git a/src/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES b/src/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES
index f8183f1..0b481ea 100644
--- a/src/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES
+++ b/src/crypto/tls/testdata/Client-TLSv10-ECDHE-RSA-AES
@@ -1,98 +1,93 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 81 01 00 00  7d 03 03 00 00 00 00 00  |........}.......|
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 36  |...../.5.......6|
-00000050  00 05 00 05 01 00 00 00  00 00 0a 00 08 00 06 00  |................|
-00000060  17 00 18 00 19 00 0b 00  02 01 00 00 0d 00 0e 00  |................|
-00000070  0c 04 01 04 03 05 01 05  03 02 01 02 03 ff 01 00  |................|
-00000080  01 00 00 12 00 00                                 |......|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
 >>> Flow 2 (server to client)
-00000000  16 03 01 00 59 02 00 00  55 03 01 5c 69 d0 60 d6  |....Y...U..\i.`.|
-00000010  b3 f4 23 19 5e 3e 26 d8  29 ea c3 94 e4 ed 51 f6  |..#.^>&.).....Q.|
-00000020  58 a2 e3 9c 79 a1 0b 6d  29 90 32 20 23 5b 47 b1  |X...y..m).2 #[G.|
-00000030  8f 22 bc 06 aa ee f7 c3  97 ca 93 df b1 90 7d b4  |."............}.|
-00000040  8c c0 d9 54 35 ca 5b 11  98 37 84 ea c0 13 00 00  |...T5.[..7......|
+00000000  16 03 01 00 59 02 00 00  55 03 01 90 3d f6 98 16  |....Y...U...=...|
+00000010  55 0f 73 94 05 96 4c ab  ad f4 98 7a db c5 ca 26  |U.s...L....z...&|
+00000020  1b c8 d9 15 a8 79 8e 2b  10 67 54 20 b2 8e 45 24  |.....y.+.gT ..E$|
+00000030  6d 82 ec f5 30 41 2e 32  10 fa c0 76 3f 84 81 39  |m...0A.2...v?..9|
+00000040  1e 5d 98 c1 33 d9 0d 4f  21 e1 0d 47 c0 13 00 00  |.]..3..O!..G....|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
-00000060  01 02 be 0b 00 02 ba 00  02 b7 00 02 b4 30 82 02  |.............0..|
-00000070  b0 30 82 02 19 a0 03 02  01 02 02 09 00 85 b0 bb  |.0..............|
-00000080  a4 8a 7f b8 ca 30 0d 06  09 2a 86 48 86 f7 0d 01  |.....0...*.H....|
-00000090  01 05 05 00 30 45 31 0b  30 09 06 03 55 04 06 13  |....0E1.0...U...|
-000000a0  02 41 55 31 13 30 11 06  03 55 04 08 13 0a 53 6f  |.AU1.0...U....So|
-000000b0  6d 65 2d 53 74 61 74 65  31 21 30 1f 06 03 55 04  |me-State1!0...U.|
-000000c0  0a 13 18 49 6e 74 65 72  6e 65 74 20 57 69 64 67  |...Internet Widg|
-000000d0  69 74 73 20 50 74 79 20  4c 74 64 30 1e 17 0d 31  |its Pty Ltd0...1|
-000000e0  30 30 34 32 34 30 39 30  39 33 38 5a 17 0d 31 31  |00424090938Z..11|
-000000f0  30 34 32 34 30 39 30 39  33 38 5a 30 45 31 0b 30  |0424090938Z0E1.0|
-00000100  09 06 03 55 04 06 13 02  41 55 31 13 30 11 06 03  |...U....AU1.0...|
-00000110  55 04 08 13 0a 53 6f 6d  65 2d 53 74 61 74 65 31  |U....Some-State1|
-00000120  21 30 1f 06 03 55 04 0a  13 18 49 6e 74 65 72 6e  |!0...U....Intern|
-00000130  65 74 20 57 69 64 67 69  74 73 20 50 74 79 20 4c  |et Widgits Pty L|
-00000140  74 64 30 81 9f 30 0d 06  09 2a 86 48 86 f7 0d 01  |td0..0...*.H....|
-00000150  01 01 05 00 03 81 8d 00  30 81 89 02 81 81 00 bb  |........0.......|
-00000160  79 d6 f5 17 b5 e5 bf 46  10 d0 dc 69 be e6 2b 07  |y......F...i..+.|
-00000170  43 5a d0 03 2d 8a 7a 43  85 b7 14 52 e7 a5 65 4c  |CZ..-.zC...R..eL|
-00000180  2c 78 b8 23 8c b5 b4 82  e5 de 1f 95 3b 7e 62 a5  |,x.#........;~b.|
-00000190  2c a5 33 d6 fe 12 5c 7a  56 fc f5 06 bf fa 58 7b  |,.3...\zV.....X{|
-000001a0  26 3f b5 cd 04 d3 d0 c9  21 96 4a c7 f4 54 9f 5a  |&?......!.J..T.Z|
-000001b0  bf ef 42 71 00 fe 18 99  07 7f 7e 88 7d 7d f1 04  |..Bq......~.}}..|
-000001c0  39 c4 a2 2e db 51 c9 7c  e3 c0 4c 3b 32 66 01 cf  |9....Q.|..L;2f..|
-000001d0  af b1 1d b8 71 9a 1d db  db 89 6b ae da 2d 79 02  |....q.....k..-y.|
-000001e0  03 01 00 01 a3 81 a7 30  81 a4 30 1d 06 03 55 1d  |.......0..0...U.|
-000001f0  0e 04 16 04 14 b1 ad e2  85 5a cf cb 28 db 69 ce  |.........Z..(.i.|
-00000200  23 69 de d3 26 8e 18 88  39 30 75 06 03 55 1d 23  |#i..&...90u..U.#|
-00000210  04 6e 30 6c 80 14 b1 ad  e2 85 5a cf cb 28 db 69  |.n0l......Z..(.i|
-00000220  ce 23 69 de d3 26 8e 18  88 39 a1 49 a4 47 30 45  |.#i..&...9.I.G0E|
-00000230  31 0b 30 09 06 03 55 04  06 13 02 41 55 31 13 30  |1.0...U....AU1.0|
-00000240  11 06 03 55 04 08 13 0a  53 6f 6d 65 2d 53 74 61  |...U....Some-Sta|
-00000250  74 65 31 21 30 1f 06 03  55 04 0a 13 18 49 6e 74  |te1!0...U....Int|
-00000260  65 72 6e 65 74 20 57 69  64 67 69 74 73 20 50 74  |ernet Widgits Pt|
-00000270  79 20 4c 74 64 82 09 00  85 b0 bb a4 8a 7f b8 ca  |y Ltd...........|
-00000280  30 0c 06 03 55 1d 13 04  05 30 03 01 01 ff 30 0d  |0...U....0....0.|
-00000290  06 09 2a 86 48 86 f7 0d  01 01 05 05 00 03 81 81  |..*.H...........|
-000002a0  00 08 6c 45 24 c7 6b b1  59 ab 0c 52 cc f2 b0 14  |..lE$.k.Y..R....|
-000002b0  d7 87 9d 7a 64 75 b5 5a  95 66 e4 c5 2b 8e ae 12  |...zdu.Z.f..+...|
-000002c0  66 1f eb 4f 38 b3 6e 60  d3 92 fd f7 41 08 b5 25  |f..O8.n`....A..%|
-000002d0  13 b1 18 7a 24 fb 30 1d  ba ed 98 b9 17 ec e7 d7  |...z$.0.........|
-000002e0  31 59 db 95 d3 1d 78 ea  50 56 5c d5 82 5a 2d 5a  |1Y....x.PV\..Z-Z|
-000002f0  5f 33 c4 b6 d8 c9 75 90  96 8c 0f 52 98 b5 cd 98  |_3....u....R....|
-00000300  1f 89 20 5f f2 a0 1c a3  1b 96 94 dd a9 fd 57 e9  |.. _..........W.|
-00000310  70 e8 26 6d 71 99 9b 26  6e 38 50 29 6c 90 a7 bd  |p.&mq..&n8P)l...|
-00000320  d9 16 03 01 00 cb 0c 00  00 c7 03 00 17 41 04 a6  |.............A..|
-00000330  57 60 8d 63 4e 4d 3f 48  e0 5d ad 9a 9c f7 e6 8c  |W`.cNM?H.]......|
-00000340  00 18 9c eb 34 ea f0 5c  d5 77 3f af 81 a9 50 d9  |....4..\.w?...P.|
-00000350  05 cf b9 bf 88 5c 70 29  24 61 6f d8 77 11 21 57  |.....\p)$ao.w.!W|
-00000360  a0 4d e1 4b 8e 55 06 50  7f a2 30 c1 c2 b9 c6 00  |.M.K.U.P..0.....|
-00000370  80 68 7c e4 1a bc a4 1e  16 b9 3e 4a 59 39 a9 54  |.h|.......>JY9.T|
-00000380  6f c7 17 b2 f5 af b5 73  5b db cc 71 f2 1b aa dc  |o......s[..q....|
-00000390  9d 64 3c 0f 82 e6 da 1a  6b 96 19 e2 f0 15 b0 df  |.d<.....k.......|
-000003a0  8a 2d 96 09 63 52 f6 53  ef 12 d4 3b 35 b7 0b 43  |.-..cR.S...;5..C|
-000003b0  2c 6e 58 4c c8 2f b8 55  84 89 c9 39 81 7a 7a 7d  |,nXL./.U...9.zz}|
-000003c0  88 68 db eb d7 81 aa 2e  b2 25 ba 98 6c 46 b7 85  |.h.......%..lF..|
-000003d0  8a 21 17 b9 36 23 c0 84  94 af 3b 9b 04 5d ec 31  |.!..6#....;..].1|
-000003e0  f5 75 84 d8 77 d7 80 37  ae c3 5c 26 41 f6 72 af  |.u..w..7..\&A.r.|
-000003f0  88 16 03 01 00 04 0e 00  00 00                    |..........|
+00000060  01 02 71 0b 00 02 6d 00  02 6a 00 02 67 30 82 02  |..q...m..j..g0..|
+00000070  63 30 82 01 cc a0 03 02  01 02 02 09 00 a2 73 00  |c0............s.|
+00000080  0c 81 00 cb f3 30 0d 06  09 2a 86 48 86 f7 0d 01  |.....0...*.H....|
+00000090  01 0b 05 00 30 2b 31 17  30 15 06 03 55 04 0a 13  |....0+1.0...U...|
+000000a0  0e 47 6f 6f 67 6c 65 20  54 45 53 54 49 4e 47 31  |.Google TESTING1|
+000000b0  10 30 0e 06 03 55 04 03  13 07 47 6f 20 52 6f 6f  |.0...U....Go Roo|
+000000c0  74 30 1e 17 0d 31 35 30  31 30 31 30 30 30 30 30  |t0...15010100000|
+000000d0  30 5a 17 0d 32 35 30 31  30 31 30 30 30 30 30 30  |0Z..250101000000|
+000000e0  5a 30 26 31 17 30 15 06  03 55 04 0a 13 0e 47 6f  |Z0&1.0...U....Go|
+000000f0  6f 67 6c 65 20 54 45 53  54 49 4e 47 31 0b 30 09  |ogle TESTING1.0.|
+00000100  06 03 55 04 03 13 02 47  6f 30 81 9f 30 0d 06 09  |..U....Go0..0...|
+00000110  2a 86 48 86 f7 0d 01 01  01 05 00 03 81 8d 00 30  |*.H............0|
+00000120  81 89 02 81 81 00 af 87  88 f6 20 1b 95 65 6c 14  |.......... ..el.|
+00000130  ab 44 05 af 3b 45 14 e3  b7 6d fd 00 63 4d 95 7f  |.D..;E...m..cM..|
+00000140  fe 6a 62 35 86 c0 4a f9  18 7c f6 aa 25 5e 7a 64  |.jb5..J..|..%^zd|
+00000150  31 66 00 ba f4 8e 92 af  c7 6b d8 76 d4 f3 5f 41  |1f.......k.v.._A|
+00000160  cb 6e 56 15 97 1b 97 c1  3c 12 39 21 66 3d 2b 16  |.nV.....<.9!f=+.|
+00000170  d1 bc db 1c c0 a7 da b7  ca ad ba da cb d5 21 50  |..............!P|
+00000180  ec de 8d ab d1 6b 81 4b  89 02 f3 c4 be c1 6c 89  |.....k.K......l.|
+00000190  b1 44 84 bd 21 d1 04 7d  9d 16 4d f9 82 15 f6 ef  |.D..!..}..M.....|
+000001a0  fa d6 09 47 f2 fb 02 03  01 00 01 a3 81 93 30 81  |...G..........0.|
+000001b0  90 30 0e 06 03 55 1d 0f  01 01 ff 04 04 03 02 05  |.0...U..........|
+000001c0  a0 30 1d 06 03 55 1d 25  04 16 30 14 06 08 2b 06  |.0...U.%..0...+.|
+000001d0  01 05 05 07 03 01 06 08  2b 06 01 05 05 07 03 02  |........+.......|
+000001e0  30 0c 06 03 55 1d 13 01  01 ff 04 02 30 00 30 19  |0...U.......0.0.|
+000001f0  06 03 55 1d 0e 04 12 04  10 12 50 8d 89 6f 1b d1  |..U.......P..o..|
+00000200  dc 54 4d 6e cb 69 5e 06  f4 30 1b 06 03 55 1d 23  |.TMn.i^..0...U.#|
+00000210  04 14 30 12 80 10 bf 3d  b6 a9 66 f2 b8 40 cf ea  |..0....=..f.. at ..|
+00000220  b4 03 78 48 1a 41 30 19  06 03 55 1d 11 04 12 30  |..xH.A0...U....0|
+00000230  10 82 0e 65 78 61 6d 70  6c 65 2e 67 6f 6c 61 6e  |...example.golan|
+00000240  67 30 0d 06 09 2a 86 48  86 f7 0d 01 01 0b 05 00  |g0...*.H........|
+00000250  03 81 81 00 92 7c af 91  55 12 18 96 59 31 a6 48  |.....|..U...Y1.H|
+00000260  40 d5 2d d5 ee bb 02 a0  f5 c2 1e 7c 9b b3 30 7d  |@.-........|..0}|
+00000270  3c dc 76 da 4f 3d c0 fa  ae 2d 33 24 6b 03 7b 1b  |<.v.O=...-3$k.{.|
+00000280  67 59 11 21 b5 11 bc 77  b9 d9 e0 6e a8 2d 2e 35  |gY.!...w...n.-.5|
+00000290  fa 64 5f 22 3e 63 10 6b  be ff 14 86 6d 0d f0 15  |.d_">c.k....m...|
+000002a0  31 a8 14 38 1e 3b 84 87  2c cb 98 ed 51 76 b9 b1  |1..8.;..,...Qv..|
+000002b0  4f dd db 9b 84 04 86 40  fa 51 dd ba b4 8d eb e3  |O...... at .Q......|
+000002c0  46 de 46 b9 4f 86 c7 f9  a4 c2 41 34 ac cc f6 ea  |F.F.O.....A4....|
+000002d0  b0 ab 39 18 16 03 01 00  cb 0c 00 00 c7 03 00 17  |..9.............|
+000002e0  41 04 d9 ae 3f 05 64 d3  77 d9 1d b8 37 8a d4 ac  |A...?.d.w...7...|
+000002f0  51 f4 af 65 70 da c0 64  76 00 53 50 a2 d4 6c bc  |Q..ep..dv.SP..l.|
+00000300  9c 62 ab 2f 7b 02 48 fe  b2 0d 0b bb be 8f 34 55  |.b./{.H.......4U|
+00000310  fb ce ee 93 43 76 d5 ce  3b b5 79 ab 3d 74 6e 19  |....Cv..;.y.=tn.|
+00000320  a9 7d 00 80 05 cf 57 f2  f7 e0 ad 71 f1 75 d0 8b  |.}....W....q.u..|
+00000330  f5 9d 83 1a 7e 0a 71 10  d7 9e fe bd 9d 47 62 45  |....~.q......GbE|
+00000340  8d 1b 9c 33 fa 2c 5c aa  ce 9e 62 dc ad 56 ac 87  |...3.,\...b..V..|
+00000350  84 54 f5 32 87 d1 bb 8b  d9 d7 6d 3c 6c 6d b7 79  |.T.2......m<lm.y|
+00000360  05 4d 55 f1 7c ef b1 fc  e7 35 5d 41 66 60 44 4f  |.MU.|....5]Af`DO|
+00000370  f3 dd de 25 f4 73 12 c2  b6 cc 61 d5 14 5a ff 88  |...%.s....a..Z..|
+00000380  ae f5 04 62 ac 2d 10 a0  95 c1 8e fa e6 db fe 41  |...b.-.........A|
+00000390  46 98 f1 3d 2e e3 2a 5a  ea 87 26 6e 7a 4f 38 6c  |F..=..*Z..&nzO8l|
+000003a0  4b 1f 1b 56 16 03 01 00  04 0e 00 00 00           |K..V.........|
 >>> Flow 3 (client to server)
 00000000  16 03 01 00 46 10 00 00  42 41 04 1e 18 37 ef 0d  |....F...BA...7..|
 00000010  19 51 88 35 75 71 b5 e5  54 5b 12 2e 8f 09 67 fd  |.Q.5uq..T[....g.|
 00000020  a7 24 20 3e b2 56 1c ce  97 28 5e f8 2b 2d 4f 9e  |.$ >.V...(^.+-O.|
 00000030  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
 00000040  a6 b5 68 1a 41 03 56 6b  dc 5a 89 14 03 01 00 01  |..h.A.Vk.Z......|
-00000050  01 16 03 01 00 30 d2 5b  27 5a f5 64 49 31 d5 aa  |.....0.['Z.dI1..|
-00000060  a3 72 ae c9 af 0b aa 75  af ac f3 45 f4 e3 03 fa  |.r.....u...E....|
-00000070  e8 97 88 7b 51 a9 ae 61  40 c8 11 74 3e d8 9a b6  |...{Q..a at ..t>...|
-00000080  e7 6a 5e 71 84 7e                                 |.j^q.~|
+00000050  01 16 03 01 00 30 73 96  2d 54 e3 9a bc 54 f5 9e  |.....0s.-T...T..|
+00000060  e5 c7 46 35 b8 e1 d6 f6  14 95 92 f1 95 81 5a 9d  |..F5..........Z.|
+00000070  4b df cc 96 77 f2 39 60  5d 5d da 94 b0 bf a0 80  |K...w.9`]]......|
+00000080  bd 28 55 b1 6a c3                                 |.(U.j.|
 >>> Flow 4 (server to client)
-00000000  14 03 01 00 01 01 16 03  01 00 30 8d 63 fc 58 2e  |..........0.c.X.|
-00000010  50 f7 60 2c 9f 5a 8e 58  29 6c a6 3a 8d 2b a7 2b  |P.`,.Z.X)l.:.+.+|
-00000020  1c 12 8a 53 3f d5 60 79  12 c3 78 e3 aa 50 15 45  |...S?.`y..x..P.E|
-00000030  07 da 2d c7 a9 c3 45 07  48 00 78                 |..-...E.H.x|
+00000000  14 03 01 00 01 01 16 03  01 00 30 c9 46 7a 8b be  |..........0.Fz..|
+00000010  cd eb 5c 83 13 9c 9b 9f  70 84 38 3b 48 8c f4 11  |..\.....p.8;H...|
+00000020  b3 ca 10 09 38 d0 8e c8  9f 66 db b9 8a 95 15 6b  |....8....f.....k|
+00000030  5e f8 1d 39 25 75 3d f1  b9 32 a3                 |^..9%u=..2.|
 >>> Flow 5 (client to server)
-00000000  17 03 01 00 20 40 91 8d  e6 95 2f 97 c8 0c 94 5c  |.... @..../....\|
-00000010  46 a7 d3 31 82 3d dc 7e  86 5b dd df 3f 3b 5b 9c  |F..1.=.~.[..?;[.|
-00000020  d5 0d 52 5a 53 17 03 01  00 20 1d 18 da 6b e8 66  |..RZS.... ...k.f|
-00000030  ce 58 18 81 4b 69 8c f6  db 1a ee d0 78 fb f5 68  |.X..Ki......x..h|
-00000040  2c 99 48 47 65 15 2a ae  ff 4e 15 03 01 00 20 68  |,.HGe.*..N.... h|
-00000050  aa 7f 75 33 45 7a 1a 33  18 35 5a 5b 14 b0 f6 83  |..u3Ez.3.5Z[....|
-00000060  97 85 3f b2 dc 78 68 eb  43 ef 92 7f 38 bd f8     |..?..xh.C...8..|
+00000000  17 03 01 00 20 04 69 a9  01 42 f4 1a fd 5a 4e 12  |.... .i..B...ZN.|
+00000010  2b 6d cd 68 6b 94 70 b2  80 07 cf 79 a4 43 69 bf  |+m.hk.p....y.Ci.|
+00000020  27 25 b5 ae e7 17 03 01  00 20 bf 1e cd 83 64 af  |'%....... ....d.|
+00000030  6f cc 89 21 bf 16 e7 e8  86 29 f3 0a 36 ab a4 e3  |o..!.....)..6...|
+00000040  fa c0 7e 7a 78 ca 29 17  11 9c 15 03 01 00 20 94  |..~zx.)....... .|
+00000050  7a dd 17 eb fd 67 b1 cc  58 c9 c3 ae db b6 b0 a4  |z....g..X.......|
+00000060  68 15 36 ca 33 22 ec 03  fb cf 2f f5 70 d6 9d     |h.6.3"..../.p..|
diff --git a/src/crypto/tls/testdata/Client-TLSv10-RSA-RC4 b/src/crypto/tls/testdata/Client-TLSv10-RSA-RC4
index b5deaeb..57eb930 100644
--- a/src/crypto/tls/testdata/Client-TLSv10-RSA-RC4
+++ b/src/crypto/tls/testdata/Client-TLSv10-RSA-RC4
@@ -1,84 +1,79 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 81 01 00 00  7d 03 03 00 00 00 00 00  |........}.......|
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 36  |...../.5.......6|
-00000050  00 05 00 05 01 00 00 00  00 00 0a 00 08 00 06 00  |................|
-00000060  17 00 18 00 19 00 0b 00  02 01 00 00 0d 00 0e 00  |................|
-00000070  0c 04 01 04 03 05 01 05  03 02 01 02 03 ff 01 00  |................|
-00000080  01 00 00 12 00 00                                 |......|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
 >>> Flow 2 (server to client)
-00000000  16 03 01 00 51 02 00 00  4d 03 01 a9 b0 bf 24 3f  |....Q...M.....$?|
-00000010  98 c6 0f 83 23 2b b6 e4  3f d5 5b 10 9a 6f b8 63  |....#+..?.[..o.c|
-00000020  4c 3c d6 4d 05 c0 08 85  f7 72 72 20 ab 85 8c ff  |L<.M.....rr ....|
-00000030  f7 bb 95 ab 69 37 3d b6  79 cb 46 ad 4e 22 e7 c6  |....i7=.y.F.N"..|
-00000040  a5 9b 72 92 32 ff a5 f7  ed dc 30 41 00 05 00 00  |..r.2.....0A....|
-00000050  05 ff 01 00 01 00 16 03  01 02 be 0b 00 02 ba 00  |................|
-00000060  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
-00000070  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
-00000080  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
-00000090  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
-000000a0  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
-000000b0  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
-000000c0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
-000000d0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
-000000e0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
-000000f0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
-00000100  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
-00000110  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
-00000120  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
-00000130  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
-00000140  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
-00000150  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
-00000160  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
-00000170  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
-00000180  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
-00000190  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
-000001a0  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
-000001b0  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
-000001c0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
-000001d0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
-000001e0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
-000001f0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
-00000200  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
-00000210  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
-00000220  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
-00000230  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
-00000240  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
-00000250  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
-00000260  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
-00000270  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
-00000280  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
-00000290  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
-000002a0  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
-000002b0  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
-000002c0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
-000002d0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
-000002e0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
-000002f0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
-00000300  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
-00000310  6e 38 50 29 6c 90 a7 bd  d9 16 03 01 00 04 0e 00  |n8P)l...........|
-00000320  00 00                                             |..|
+00000000  16 03 01 00 51 02 00 00  4d 03 01 1c 0e e9 7a c6  |....Q...M.....z.|
+00000010  91 fe 7e 8c 6f 0b 8e cf  23 f5 07 29 10 de 05 a6  |..~.o...#..)....|
+00000020  20 72 11 65 4f 2b 45 95  96 02 62 20 43 a8 93 34  | r.eO+E...b C..4|
+00000030  e7 c0 29 d5 fb 26 f9 c2  59 37 94 dc e6 b5 c4 ed  |..)..&..Y7......|
+00000040  ae 7a d7 94 d1 f4 d8 0b  02 ad 20 1b 00 05 00 00  |.z........ .....|
+00000050  05 ff 01 00 01 00 16 03  01 02 71 0b 00 02 6d 00  |..........q...m.|
+00000060  02 6a 00 02 67 30 82 02  63 30 82 01 cc a0 03 02  |.j..g0..c0......|
+00000070  01 02 02 09 00 a2 73 00  0c 81 00 cb f3 30 0d 06  |......s......0..|
+00000080  09 2a 86 48 86 f7 0d 01  01 0b 05 00 30 2b 31 17  |.*.H........0+1.|
+00000090  30 15 06 03 55 04 0a 13  0e 47 6f 6f 67 6c 65 20  |0...U....Google |
+000000a0  54 45 53 54 49 4e 47 31  10 30 0e 06 03 55 04 03  |TESTING1.0...U..|
+000000b0  13 07 47 6f 20 52 6f 6f  74 30 1e 17 0d 31 35 30  |..Go Root0...150|
+000000c0  31 30 31 30 30 30 30 30  30 5a 17 0d 32 35 30 31  |101000000Z..2501|
+000000d0  30 31 30 30 30 30 30 30  5a 30 26 31 17 30 15 06  |01000000Z0&1.0..|
+000000e0  03 55 04 0a 13 0e 47 6f  6f 67 6c 65 20 54 45 53  |.U....Google TES|
+000000f0  54 49 4e 47 31 0b 30 09  06 03 55 04 03 13 02 47  |TING1.0...U....G|
+00000100  6f 30 81 9f 30 0d 06 09  2a 86 48 86 f7 0d 01 01  |o0..0...*.H.....|
+00000110  01 05 00 03 81 8d 00 30  81 89 02 81 81 00 af 87  |.......0........|
+00000120  88 f6 20 1b 95 65 6c 14  ab 44 05 af 3b 45 14 e3  |.. ..el..D..;E..|
+00000130  b7 6d fd 00 63 4d 95 7f  fe 6a 62 35 86 c0 4a f9  |.m..cM...jb5..J.|
+00000140  18 7c f6 aa 25 5e 7a 64  31 66 00 ba f4 8e 92 af  |.|..%^zd1f......|
+00000150  c7 6b d8 76 d4 f3 5f 41  cb 6e 56 15 97 1b 97 c1  |.k.v.._A.nV.....|
+00000160  3c 12 39 21 66 3d 2b 16  d1 bc db 1c c0 a7 da b7  |<.9!f=+.........|
+00000170  ca ad ba da cb d5 21 50  ec de 8d ab d1 6b 81 4b  |......!P.....k.K|
+00000180  89 02 f3 c4 be c1 6c 89  b1 44 84 bd 21 d1 04 7d  |......l..D..!..}|
+00000190  9d 16 4d f9 82 15 f6 ef  fa d6 09 47 f2 fb 02 03  |..M........G....|
+000001a0  01 00 01 a3 81 93 30 81  90 30 0e 06 03 55 1d 0f  |......0..0...U..|
+000001b0  01 01 ff 04 04 03 02 05  a0 30 1d 06 03 55 1d 25  |.........0...U.%|
+000001c0  04 16 30 14 06 08 2b 06  01 05 05 07 03 01 06 08  |..0...+.........|
+000001d0  2b 06 01 05 05 07 03 02  30 0c 06 03 55 1d 13 01  |+.......0...U...|
+000001e0  01 ff 04 02 30 00 30 19  06 03 55 1d 0e 04 12 04  |....0.0...U.....|
+000001f0  10 12 50 8d 89 6f 1b d1  dc 54 4d 6e cb 69 5e 06  |..P..o...TMn.i^.|
+00000200  f4 30 1b 06 03 55 1d 23  04 14 30 12 80 10 bf 3d  |.0...U.#..0....=|
+00000210  b6 a9 66 f2 b8 40 cf ea  b4 03 78 48 1a 41 30 19  |..f.. at ....xH.A0.|
+00000220  06 03 55 1d 11 04 12 30  10 82 0e 65 78 61 6d 70  |..U....0...examp|
+00000230  6c 65 2e 67 6f 6c 61 6e  67 30 0d 06 09 2a 86 48  |le.golang0...*.H|
+00000240  86 f7 0d 01 01 0b 05 00  03 81 81 00 92 7c af 91  |.............|..|
+00000250  55 12 18 96 59 31 a6 48  40 d5 2d d5 ee bb 02 a0  |U...Y1.H at .-.....|
+00000260  f5 c2 1e 7c 9b b3 30 7d  3c dc 76 da 4f 3d c0 fa  |...|..0}<.v.O=..|
+00000270  ae 2d 33 24 6b 03 7b 1b  67 59 11 21 b5 11 bc 77  |.-3$k.{.gY.!...w|
+00000280  b9 d9 e0 6e a8 2d 2e 35  fa 64 5f 22 3e 63 10 6b  |...n.-.5.d_">c.k|
+00000290  be ff 14 86 6d 0d f0 15  31 a8 14 38 1e 3b 84 87  |....m...1..8.;..|
+000002a0  2c cb 98 ed 51 76 b9 b1  4f dd db 9b 84 04 86 40  |,...Qv..O......@|
+000002b0  fa 51 dd ba b4 8d eb e3  46 de 46 b9 4f 86 c7 f9  |.Q......F.F.O...|
+000002c0  a4 c2 41 34 ac cc f6 ea  b0 ab 39 18 16 03 01 00  |..A4......9.....|
+000002d0  04 0e 00 00 00                                    |.....|
 >>> Flow 3 (client to server)
-00000000  16 03 01 00 86 10 00 00  82 00 80 6d 51 f3 7f f9  |...........mQ...|
-00000010  3e fb 75 82 41 36 83 e8  6a ee 2a 2e 25 90 67 4c  |>.u.A6..j.*.%.gL|
-00000020  8e 62 2f 30 81 17 e0 85  09 0c 2b b7 23 d7 b0 e2  |.b/0......+.#...|
-00000030  1d f7 3b d7 f5 a1 27 b6  ee 24 b6 1b cc 5b ea 66  |..;...'..$...[.f|
-00000040  0d 6a f4 e5 85 f9 da 43  b4 0e 86 85 e1 f5 aa be  |.j.....C........|
-00000050  c8 ce 39 4c 9c 86 00 08  c2 4b e2 c6 ec 2f f7 ce  |..9L.....K.../..|
-00000060  e6 bd 77 82 6f 23 b6 e0  bd a2 92 b7 3a ac e8 56  |..w.o#......:..V|
-00000070  f1 af 54 5e 46 87 e9 3b  33 e7 b8 28 b7 d6 c8 90  |..T^F..;3..(....|
-00000080  35 d4 1c 43 d1 30 6f 55  4e 0a 70 14 03 01 00 01  |5..C.0oUN.p.....|
-00000090  01 16 03 01 00 24 4d 1d  d7 8c d6 c7 65 a6 ce af  |.....$M.....e...|
-000000a0  e7 59 0d 7e dc d9 96 1c  ed 9c 57 94 84 b8 3f b5  |.Y.~......W...?.|
-000000b0  34 e1 61 a5 61 f3 5d 09  bc ff                    |4.a.a.]...|
+00000000  16 03 01 00 86 10 00 00  82 00 80 73 bd 73 65 92  |...........s.se.|
+00000010  86 23 41 14 79 7f d5 c1  10 ce 94 4d ad 9c c3 a9  |.#A.y......M....|
+00000020  87 b5 32 52 f8 6b 11 93  2d 9b 98 0b 8b 1d c0 f6  |..2R.k..-.......|
+00000030  53 17 6d c7 9c 2e ae c9  6f cc 99 23 38 37 1a 10  |S.m.....o..#87..|
+00000040  fe 05 0b b5 55 0a 14 e9  60 7d 70 26 98 e2 54 d9  |....U...`}p&..T.|
+00000050  65 cf 2e f4 53 5f 1d aa  3a f6 33 7b eb 4c 0e b3  |e...S_..:.3{.L..|
+00000060  ff 5a db 36 2a 47 f3 df  f9 fc f5 31 78 83 aa 6b  |.Z.6*G.....1x..k|
+00000070  52 b7 ba 1a 96 bc fa c1  a1 a9 bb 2b f5 38 89 00  |R..........+.8..|
+00000080  4d e5 78 13 4e a4 38 46  42 dc 16 14 03 01 00 01  |M.x.N.8FB.......|
+00000090  01 16 03 01 00 24 ae a9  da 45 6b 5e 76 57 02 62  |.....$...Ek^vW.b|
+000000a0  63 d4 1f 40 bf c9 47 27  a9 7a 24 c0 f0 e9 c2 c4  |c.. at ..G'.z$.....|
+000000b0  9c 07 84 df ae c7 66 40  d2 b0                    |......f at ..|
 >>> Flow 4 (server to client)
-00000000  14 03 01 00 01 01 16 03  01 00 24 13 81 89 61 5c  |..........$...a\|
-00000010  fb 0a 9c a1 4b db 94 6b  8b 41 6e 63 d6 aa db 88  |....K..k.Anc....|
-00000020  03 b7 b5 19 b8 12 cf 5e  17 54 79 2f 03 91 7e     |.......^.Ty/..~|
+00000000  14 03 01 00 01 01 16 03  01 00 24 e9 84 92 41 c5  |..........$...A.|
+00000010  31 e1 3c a9 78 18 d1 7b  e1 b1 0b 0a ef 18 54 19  |1.<.x..{......T.|
+00000020  7c ba c7 59 ca c8 7b 4d  c9 f4 ad d6 7b 77 fb     ||..Y..{M....{w.|
 >>> Flow 5 (client to server)
-00000000  17 03 01 00 1a b3 2b da  ce 45 ec b2 9d 3b 18 d9  |......+..E...;..|
-00000010  7a cb 99 ea ff 4d 91 b5  48 df 6f 8b 2f 85 c7 15  |z....M..H.o./...|
-00000020  03 01 00 16 19 1c 72 74  36 cf 22 0f a0 a7 18 96  |......rt6.".....|
-00000030  3a 67 cb 22 16 f1 a8 7b  57 37                    |:g."...{W7|
+00000000  17 03 01 00 1a 1a dc 95  e2 4f ec f1 f6 68 9d 15  |.........O...h..|
+00000010  56 d5 7b 06 1a f5 be bb  b1 ca b2 a6 d3 9e 28 15  |V.{...........(.|
+00000020  03 01 00 16 64 fe 4a 37  d3 32 a8 55 38 9e 0f 76  |....d.J7.2.U8..v|
+00000030  50 de e2 2e aa 77 15 2b  e5 21                    |P....w.+.!|
diff --git a/src/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES b/src/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES
index a4a2930..87fbe3f 100644
--- a/src/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES
+++ b/src/crypto/tls/testdata/Client-TLSv11-ECDHE-ECDSA-AES
@@ -1,19 +1,19 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 81 01 00 00  7d 03 03 00 00 00 00 00  |........}.......|
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 36  |...../.5.......6|
-00000050  00 05 00 05 01 00 00 00  00 00 0a 00 08 00 06 00  |................|
-00000060  17 00 18 00 19 00 0b 00  02 01 00 00 0d 00 0e 00  |................|
-00000070  0c 04 01 04 03 05 01 05  03 02 01 02 03 ff 01 00  |................|
-00000080  01 00 00 12 00 00                                 |......|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
 >>> Flow 2 (server to client)
-00000000  16 03 02 00 59 02 00 00  55 03 02 5a 52 92 23 05  |....Y...U..ZR.#.|
-00000010  58 68 b2 1e 77 a2 a8 16  e9 88 85 ea 38 b3 63 c2  |Xh..w.......8.c.|
-00000020  40 f8 de 37 3c d4 b9 51  11 2d d1 20 12 fd 95 b3  |@..7<..Q.-. ....|
-00000030  2a 54 40 c0 23 3a 4e 4e  f6 7b f8 77 04 6e e7 d7  |*T at .#:NN.{.w.n..|
-00000040  3b 9a 45 32 e0 af df aa  ff bf 78 8b c0 09 00 00  |;.E2......x.....|
+00000000  16 03 02 00 59 02 00 00  55 03 02 07 ae a6 e4 1a  |....Y...U.......|
+00000010  f7 7a 0c bc ea 21 0e 86  e3 d0 b4 2c fc d9 97 a3  |.z...!.....,....|
+00000020  8b 29 5f 59 3e a9 06 fb  ca d9 57 20 cd 45 e7 cd  |.)_Y>.....W .E..|
+00000030  6c 4c 56 cd 7c 4c 51 2c  8f 8c 67 a2 05 51 26 f5  |lLV.|LQ,..g..Q&.|
+00000040  17 cc 18 c2 a1 29 94 4b  e2 02 cc 1c c0 09 00 00  |.....).K........|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  02 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
 00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
@@ -48,21 +48,21 @@
 00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
 00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
 00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
-00000270  2a 16 03 02 00 d5 0c 00  00 d1 03 00 17 41 04 c3  |*............A..|
-00000280  55 86 65 95 83 02 4b 69  6e 95 f4 52 46 83 21 86  |U.e...Kin..RF.!.|
-00000290  9e 99 cf 81 d9 b8 20 7a  87 b3 07 48 14 04 20 d9  |...... z...H.. .|
-000002a0  6c 2e 22 5a b5 b4 ef de  15 b3 08 ef 1e 18 ea 67  |l."Z...........g|
-000002b0  eb 45 fd e1 27 43 ed 41  ea 05 7e f3 f9 ee 23 00  |.E..'C.A..~...#.|
-000002c0  8a 30 81 87 02 42 00 b0  9c 06 85 83 b2 bf 42 22  |.0...B........B"|
-000002d0  6e 57 7a 31 fe a9 d9 28  be 0a a9 80 49 a2 14 c1  |nWz1...(....I...|
-000002e0  a9 99 76 b7 f9 76 d0 3c  d3 0c c7 42 34 d7 94 a9  |..v..v.<...B4...|
-000002f0  15 66 7e 6b 83 6e b2 b4  5b 22 c9 4e a0 96 db 2b  |.f~k.n..[".N...+|
-00000300  ad 77 33 1e 4a 5c 2f 2e  02 41 26 0c 1a 5a b4 07  |.w3.J\/..A&..Z..|
-00000310  95 99 ec 0b 5b 2e bb db  0e d5 26 c4 b3 eb c2 30  |....[.....&....0|
-00000320  b0 7b c1 07 97 a0 99 3f  db 4e b0 c4 b8 bb 5e be  |.{.....?.N....^.|
-00000330  2a e4 b3 a4 5c ad d1 d7  7a 2d fb ae 73 ee 0c 1e  |*...\...z-..s...|
-00000340  3b 64 e1 74 14 bc c0 1e  8b f3 26 16 03 02 00 04  |;d.t......&.....|
-00000350  0e 00 00 00                                       |....|
+00000270  2a 16 03 02 00 d6 0c 00  00 d2 03 00 17 41 04 cd  |*............A..|
+00000280  9d 30 75 8d 98 17 b5 1b  2f 4e af ea 69 52 a1 c1  |.0u...../N..iR..|
+00000290  86 73 6a 56 54 f8 ed b6  35 e5 4e 34 a0 6f b1 85  |.sjVT...5.N4.o..|
+000002a0  95 8e be 77 c5 1a 56 9a  59 d1 69 79 ea d6 2b c7  |...w..V.Y.iy..+.|
+000002b0  c1 4a fb bc f8 98 c3 49  1c f3 ce 33 ef 98 20 00  |.J.....I...3.. .|
+000002c0  8b 30 81 88 02 42 00 8b  15 7e 3b 4f 73 b0 8e ca  |.0...B...~;Os...|
+000002d0  67 e0 7c d8 89 70 f1 b2  6b 9c 19 84 fa aa 6e 15  |g.|..p..k.....n.|
+000002e0  8b 46 95 57 d5 ac 79 f3  e8 2a e5 7a a8 1e c3 d7  |.F.W..y..*.z....|
+000002f0  0a b2 02 cd d6 32 34 2f  37 65 41 c8 61 c6 ed e5  |.....24/7eA.a...|
+00000300  d2 6f 0f e8 1a 49 b6 c7  02 42 00 d1 00 f4 05 65  |.o...I...B.....e|
+00000310  dd 43 42 db 8b 0b 95 9d  f5 62 51 e6 58 60 20 9b  |.CB......bQ.X` .|
+00000320  46 84 e6 1f 76 4a 92 42  e4 4d 77 5b 76 a5 78 a0  |F...vJ.B.Mw[v.x.|
+00000330  b0 f0 50 7d f9 4f ca 43  9d c2 50 cb 20 1c 40 52  |..P}.O.C..P. . at R|
+00000340  0f a8 c4 43 7a 9d d5 61  de 26 30 b5 16 03 02 00  |...Cz..a.&0.....|
+00000350  04 0e 00 00 00                                    |.....|
 >>> Flow 3 (client to server)
 00000000  16 03 02 00 46 10 00 00  42 41 04 1e 18 37 ef 0d  |....F...BA...7..|
 00000010  19 51 88 35 75 71 b5 e5  54 5b 12 2e 8f 09 67 fd  |.Q.5uq..T[....g.|
@@ -70,21 +70,21 @@
 00000030  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
 00000040  a6 b5 68 1a 41 03 56 6b  dc 5a 89 14 03 02 00 01  |..h.A.Vk.Z......|
 00000050  01 16 03 02 00 40 00 00  00 00 00 00 00 00 00 00  |..... at ..........|
-00000060  00 00 00 00 00 00 33 07  8a af e1 94 ef f9 08 3a  |......3........:|
-00000070  33 5f b3 e6 42 07 85 af  40 e2 8b 34 53 62 1a 10  |3_..B... at ..4Sb..|
-00000080  bb 08 7e 75 d4 21 12 2d  54 87 33 1c 4e 13 27 72  |..~u.!.-T.3.N.'r|
-00000090  3f 9e 9f cc de 47                                 |?....G|
+00000060  00 00 00 00 00 00 c0 81  e7 e8 40 f3 24 45 ed 74  |.......... at .$E.t|
+00000070  86 31 7b 39 d1 3c a2 67  99 28 06 b1 34 b6 3c a6  |.1{9.<.g.(..4.<.|
+00000080  1d ce 39 aa 56 c9 72 0d  f1 e0 c1 5a 51 a0 5d f2  |..9.V.r....ZQ.].|
+00000090  44 4d e6 d7 0e 84                                 |DM....|
 >>> Flow 4 (server to client)
-00000000  14 03 02 00 01 01 16 03  02 00 40 4f 47 0d 43 54  |.......... at OG.CT|
-00000010  50 69 3a c8 21 a6 6e 28  78 cc 01 b4 5d eb f7 2b  |Pi:.!.n(x...]..+|
-00000020  8b 7e 26 6e cf 56 98 65  ad bf 0f a0 b4 67 13 70  |.~&n.V.e.....g.p|
-00000030  de b5 b5 91 df d6 df 8c  53 c6 54 3d 5d 98 e4 25  |........S.T=]..%|
-00000040  47 a0 0f 91 c7 08 96 17  48 bd 0f                 |G.......H..|
+00000000  14 03 02 00 01 01 16 03  02 00 40 82 8d c7 e3 7b  |.......... at ....{|
+00000010  f8 9d 33 a1 c2 08 8c 24  d9 af 66 64 6e e8 61 8e  |..3....$..fdn.a.|
+00000020  3c 03 65 2d c3 64 a2 26  23 a5 25 3f a2 a4 f9 40  |<.e-.d.&#.%?...@|
+00000030  ec 9f 0e b8 57 b1 5f 84  ea 94 72 1a 3e 60 f1 dd  |....W._...r.>`..|
+00000040  af 2e 81 f7 16 de 43 85  21 51 49                 |......C.!QI|
 >>> Flow 5 (client to server)
 00000000  17 03 02 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
-00000010  00 00 00 00 00 4e fe 12  d7 4b d7 3f 86 5a 2c f6  |.....N...K.?.Z,.|
-00000020  86 03 2a bd 1a 98 d7 bb  9f 59 6c 6d 4d 57 b0 50  |..*......YlmMW.P|
-00000030  d6 97 7e d4 b6 15 03 02  00 30 00 00 00 00 00 00  |..~......0......|
-00000040  00 00 00 00 00 00 00 00  00 00 65 8b b5 ae 86 90  |..........e.....|
-00000050  00 4e 1e 3f bc ac ed 49  f4 5e 73 49 e6 d8 37 83  |.N.?...I.^sI..7.|
-00000060  cf 4f e5 7b 5e c9 1d c8  c9 dc                    |.O.{^.....|
+00000010  00 00 00 00 00 43 8f 88  82 c8 e1 55 37 76 d7 a5  |.....C.....U7v..|
+00000020  83 c6 d2 94 26 fe 30 1f  e2 24 ca d7 27 22 33 47  |....&.0..$..'"3G|
+00000030  5f a9 74 9d ad 15 03 02  00 30 00 00 00 00 00 00  |_.t......0......|
+00000040  00 00 00 00 00 00 00 00  00 00 49 8e ee 5c ec 86  |..........I..\..|
+00000050  e7 64 a7 ac 0d 5c c4 43  a6 45 a4 22 b7 3d 21 06  |.d...\.C.E.".=!.|
+00000060  11 67 08 99 9a 08 a1 7c  e0 1e                    |.g.....|..|
diff --git a/src/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES b/src/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES
index 103f1d8..7581642 100644
--- a/src/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES
+++ b/src/crypto/tls/testdata/Client-TLSv11-ECDHE-RSA-AES
@@ -1,78 +1,73 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 81 01 00 00  7d 03 03 00 00 00 00 00  |........}.......|
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 36  |...../.5.......6|
-00000050  00 05 00 05 01 00 00 00  00 00 0a 00 08 00 06 00  |................|
-00000060  17 00 18 00 19 00 0b 00  02 01 00 00 0d 00 0e 00  |................|
-00000070  0c 04 01 04 03 05 01 05  03 02 01 02 03 ff 01 00  |................|
-00000080  01 00 00 12 00 00                                 |......|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
 >>> Flow 2 (server to client)
-00000000  16 03 02 00 59 02 00 00  55 03 02 e3 ed 49 27 a3  |....Y...U....I'.|
-00000010  28 c5 8c 30 27 c2 ed 57  9b f7 37 a1 6d 2b 88 c2  |(..0'..W..7.m+..|
-00000020  df a7 2d 01 01 00 9a 09  da c2 1f 20 ee 33 87 03  |..-........ .3..|
-00000030  28 93 1c 16 99 5b b1 e0  bf 87 e8 77 4a 72 c9 92  |(....[.....wJr..|
-00000040  8a bc b2 3e 24 e1 f6 e8  f4 3f a2 24 c0 13 00 00  |...>$....?.$....|
+00000000  16 03 02 00 59 02 00 00  55 03 02 0c 74 28 d1 02  |....Y...U...t(..|
+00000010  15 8f 15 9c ec 8c 4e 34  97 d8 14 ab 0c ed 1b 38  |......N4.......8|
+00000020  af 7f e6 d3 41 db fd ad  a0 8d 4f 20 03 71 4a d6  |....A.....O .qJ.|
+00000030  32 23 57 6c e1 55 34 1d  48 6f 9d e0 9a db 15 9d  |2#Wl.U4.Ho......|
+00000040  5b 45 a7 3e 4e 98 31 7d  f5 d4 b6 36 c0 13 00 00  |[E.>N.1}...6....|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
-00000060  02 02 be 0b 00 02 ba 00  02 b7 00 02 b4 30 82 02  |.............0..|
-00000070  b0 30 82 02 19 a0 03 02  01 02 02 09 00 85 b0 bb  |.0..............|
-00000080  a4 8a 7f b8 ca 30 0d 06  09 2a 86 48 86 f7 0d 01  |.....0...*.H....|
-00000090  01 05 05 00 30 45 31 0b  30 09 06 03 55 04 06 13  |....0E1.0...U...|
-000000a0  02 41 55 31 13 30 11 06  03 55 04 08 13 0a 53 6f  |.AU1.0...U....So|
-000000b0  6d 65 2d 53 74 61 74 65  31 21 30 1f 06 03 55 04  |me-State1!0...U.|
-000000c0  0a 13 18 49 6e 74 65 72  6e 65 74 20 57 69 64 67  |...Internet Widg|
-000000d0  69 74 73 20 50 74 79 20  4c 74 64 30 1e 17 0d 31  |its Pty Ltd0...1|
-000000e0  30 30 34 32 34 30 39 30  39 33 38 5a 17 0d 31 31  |00424090938Z..11|
-000000f0  30 34 32 34 30 39 30 39  33 38 5a 30 45 31 0b 30  |0424090938Z0E1.0|
-00000100  09 06 03 55 04 06 13 02  41 55 31 13 30 11 06 03  |...U....AU1.0...|
-00000110  55 04 08 13 0a 53 6f 6d  65 2d 53 74 61 74 65 31  |U....Some-State1|
-00000120  21 30 1f 06 03 55 04 0a  13 18 49 6e 74 65 72 6e  |!0...U....Intern|
-00000130  65 74 20 57 69 64 67 69  74 73 20 50 74 79 20 4c  |et Widgits Pty L|
-00000140  74 64 30 81 9f 30 0d 06  09 2a 86 48 86 f7 0d 01  |td0..0...*.H....|
-00000150  01 01 05 00 03 81 8d 00  30 81 89 02 81 81 00 bb  |........0.......|
-00000160  79 d6 f5 17 b5 e5 bf 46  10 d0 dc 69 be e6 2b 07  |y......F...i..+.|
-00000170  43 5a d0 03 2d 8a 7a 43  85 b7 14 52 e7 a5 65 4c  |CZ..-.zC...R..eL|
-00000180  2c 78 b8 23 8c b5 b4 82  e5 de 1f 95 3b 7e 62 a5  |,x.#........;~b.|
-00000190  2c a5 33 d6 fe 12 5c 7a  56 fc f5 06 bf fa 58 7b  |,.3...\zV.....X{|
-000001a0  26 3f b5 cd 04 d3 d0 c9  21 96 4a c7 f4 54 9f 5a  |&?......!.J..T.Z|
-000001b0  bf ef 42 71 00 fe 18 99  07 7f 7e 88 7d 7d f1 04  |..Bq......~.}}..|
-000001c0  39 c4 a2 2e db 51 c9 7c  e3 c0 4c 3b 32 66 01 cf  |9....Q.|..L;2f..|
-000001d0  af b1 1d b8 71 9a 1d db  db 89 6b ae da 2d 79 02  |....q.....k..-y.|
-000001e0  03 01 00 01 a3 81 a7 30  81 a4 30 1d 06 03 55 1d  |.......0..0...U.|
-000001f0  0e 04 16 04 14 b1 ad e2  85 5a cf cb 28 db 69 ce  |.........Z..(.i.|
-00000200  23 69 de d3 26 8e 18 88  39 30 75 06 03 55 1d 23  |#i..&...90u..U.#|
-00000210  04 6e 30 6c 80 14 b1 ad  e2 85 5a cf cb 28 db 69  |.n0l......Z..(.i|
-00000220  ce 23 69 de d3 26 8e 18  88 39 a1 49 a4 47 30 45  |.#i..&...9.I.G0E|
-00000230  31 0b 30 09 06 03 55 04  06 13 02 41 55 31 13 30  |1.0...U....AU1.0|
-00000240  11 06 03 55 04 08 13 0a  53 6f 6d 65 2d 53 74 61  |...U....Some-Sta|
-00000250  74 65 31 21 30 1f 06 03  55 04 0a 13 18 49 6e 74  |te1!0...U....Int|
-00000260  65 72 6e 65 74 20 57 69  64 67 69 74 73 20 50 74  |ernet Widgits Pt|
-00000270  79 20 4c 74 64 82 09 00  85 b0 bb a4 8a 7f b8 ca  |y Ltd...........|
-00000280  30 0c 06 03 55 1d 13 04  05 30 03 01 01 ff 30 0d  |0...U....0....0.|
-00000290  06 09 2a 86 48 86 f7 0d  01 01 05 05 00 03 81 81  |..*.H...........|
-000002a0  00 08 6c 45 24 c7 6b b1  59 ab 0c 52 cc f2 b0 14  |..lE$.k.Y..R....|
-000002b0  d7 87 9d 7a 64 75 b5 5a  95 66 e4 c5 2b 8e ae 12  |...zdu.Z.f..+...|
-000002c0  66 1f eb 4f 38 b3 6e 60  d3 92 fd f7 41 08 b5 25  |f..O8.n`....A..%|
-000002d0  13 b1 18 7a 24 fb 30 1d  ba ed 98 b9 17 ec e7 d7  |...z$.0.........|
-000002e0  31 59 db 95 d3 1d 78 ea  50 56 5c d5 82 5a 2d 5a  |1Y....x.PV\..Z-Z|
-000002f0  5f 33 c4 b6 d8 c9 75 90  96 8c 0f 52 98 b5 cd 98  |_3....u....R....|
-00000300  1f 89 20 5f f2 a0 1c a3  1b 96 94 dd a9 fd 57 e9  |.. _..........W.|
-00000310  70 e8 26 6d 71 99 9b 26  6e 38 50 29 6c 90 a7 bd  |p.&mq..&n8P)l...|
-00000320  d9 16 03 02 00 cb 0c 00  00 c7 03 00 17 41 04 f7  |.............A..|
-00000330  75 c1 b9 58 a0 7d 50 48  e9 85 79 db 89 76 4c d7  |u..X.}PH..y..vL.|
-00000340  84 5b 94 9a 15 d8 92 32  74 d2 3e ce 76 5a bd 0e  |.[.....2t.>.vZ..|
-00000350  24 e7 a6 d0 77 5d 8e 3d  9f 94 7a ea 15 46 3c 5c  |$...w].=..z..F<\|
-00000360  61 28 76 4a ff 81 97 2b  3a 0c b7 aa b4 0e cb 00  |a(vJ...+:.......|
-00000370  80 19 00 a8 fe 0a ea 35  30 51 a3 77 37 08 68 10  |.......50Q.w7.h.|
-00000380  5a e9 07 2d 83 67 77 4c  3a 25 14 1c 5b c1 2e 80  |Z..-.gwL:%..[...|
-00000390  30 6d ba 26 c1 f9 c6 3e  fc 55 34 8c d2 9f 2b a6  |0m.&...>.U4...+.|
-000003a0  46 0c 9d 58 2c 9c 2b ce  6f 03 d7 49 4e df 21 ce  |F..X,.+.o..IN.!.|
-000003b0  3f 8b 19 fe 3e 71 23 51  c3 ec 30 c8 3e 3c 3c 50  |?...>q#Q..0.><<P|
-000003c0  da 08 52 c0 10 9f e3 4a  be e0 97 aa de 5e 13 22  |..R....J.....^."|
-000003d0  b2 77 ee 5d 2d d4 ff fb  7f c3 1e e7 51 fe fc 4b  |.w.]-.......Q..K|
-000003e0  56 5b 8f 50 ad cc 34 7a  a9 dd 24 0a d0 c7 b9 bf  |V[.P..4z..$.....|
-000003f0  1a 16 03 02 00 04 0e 00  00 00                    |..........|
+00000060  02 02 71 0b 00 02 6d 00  02 6a 00 02 67 30 82 02  |..q...m..j..g0..|
+00000070  63 30 82 01 cc a0 03 02  01 02 02 09 00 a2 73 00  |c0............s.|
+00000080  0c 81 00 cb f3 30 0d 06  09 2a 86 48 86 f7 0d 01  |.....0...*.H....|
+00000090  01 0b 05 00 30 2b 31 17  30 15 06 03 55 04 0a 13  |....0+1.0...U...|
+000000a0  0e 47 6f 6f 67 6c 65 20  54 45 53 54 49 4e 47 31  |.Google TESTING1|
+000000b0  10 30 0e 06 03 55 04 03  13 07 47 6f 20 52 6f 6f  |.0...U....Go Roo|
+000000c0  74 30 1e 17 0d 31 35 30  31 30 31 30 30 30 30 30  |t0...15010100000|
+000000d0  30 5a 17 0d 32 35 30 31  30 31 30 30 30 30 30 30  |0Z..250101000000|
+000000e0  5a 30 26 31 17 30 15 06  03 55 04 0a 13 0e 47 6f  |Z0&1.0...U....Go|
+000000f0  6f 67 6c 65 20 54 45 53  54 49 4e 47 31 0b 30 09  |ogle TESTING1.0.|
+00000100  06 03 55 04 03 13 02 47  6f 30 81 9f 30 0d 06 09  |..U....Go0..0...|
+00000110  2a 86 48 86 f7 0d 01 01  01 05 00 03 81 8d 00 30  |*.H............0|
+00000120  81 89 02 81 81 00 af 87  88 f6 20 1b 95 65 6c 14  |.......... ..el.|
+00000130  ab 44 05 af 3b 45 14 e3  b7 6d fd 00 63 4d 95 7f  |.D..;E...m..cM..|
+00000140  fe 6a 62 35 86 c0 4a f9  18 7c f6 aa 25 5e 7a 64  |.jb5..J..|..%^zd|
+00000150  31 66 00 ba f4 8e 92 af  c7 6b d8 76 d4 f3 5f 41  |1f.......k.v.._A|
+00000160  cb 6e 56 15 97 1b 97 c1  3c 12 39 21 66 3d 2b 16  |.nV.....<.9!f=+.|
+00000170  d1 bc db 1c c0 a7 da b7  ca ad ba da cb d5 21 50  |..............!P|
+00000180  ec de 8d ab d1 6b 81 4b  89 02 f3 c4 be c1 6c 89  |.....k.K......l.|
+00000190  b1 44 84 bd 21 d1 04 7d  9d 16 4d f9 82 15 f6 ef  |.D..!..}..M.....|
+000001a0  fa d6 09 47 f2 fb 02 03  01 00 01 a3 81 93 30 81  |...G..........0.|
+000001b0  90 30 0e 06 03 55 1d 0f  01 01 ff 04 04 03 02 05  |.0...U..........|
+000001c0  a0 30 1d 06 03 55 1d 25  04 16 30 14 06 08 2b 06  |.0...U.%..0...+.|
+000001d0  01 05 05 07 03 01 06 08  2b 06 01 05 05 07 03 02  |........+.......|
+000001e0  30 0c 06 03 55 1d 13 01  01 ff 04 02 30 00 30 19  |0...U.......0.0.|
+000001f0  06 03 55 1d 0e 04 12 04  10 12 50 8d 89 6f 1b d1  |..U.......P..o..|
+00000200  dc 54 4d 6e cb 69 5e 06  f4 30 1b 06 03 55 1d 23  |.TMn.i^..0...U.#|
+00000210  04 14 30 12 80 10 bf 3d  b6 a9 66 f2 b8 40 cf ea  |..0....=..f.. at ..|
+00000220  b4 03 78 48 1a 41 30 19  06 03 55 1d 11 04 12 30  |..xH.A0...U....0|
+00000230  10 82 0e 65 78 61 6d 70  6c 65 2e 67 6f 6c 61 6e  |...example.golan|
+00000240  67 30 0d 06 09 2a 86 48  86 f7 0d 01 01 0b 05 00  |g0...*.H........|
+00000250  03 81 81 00 92 7c af 91  55 12 18 96 59 31 a6 48  |.....|..U...Y1.H|
+00000260  40 d5 2d d5 ee bb 02 a0  f5 c2 1e 7c 9b b3 30 7d  |@.-........|..0}|
+00000270  3c dc 76 da 4f 3d c0 fa  ae 2d 33 24 6b 03 7b 1b  |<.v.O=...-3$k.{.|
+00000280  67 59 11 21 b5 11 bc 77  b9 d9 e0 6e a8 2d 2e 35  |gY.!...w...n.-.5|
+00000290  fa 64 5f 22 3e 63 10 6b  be ff 14 86 6d 0d f0 15  |.d_">c.k....m...|
+000002a0  31 a8 14 38 1e 3b 84 87  2c cb 98 ed 51 76 b9 b1  |1..8.;..,...Qv..|
+000002b0  4f dd db 9b 84 04 86 40  fa 51 dd ba b4 8d eb e3  |O...... at .Q......|
+000002c0  46 de 46 b9 4f 86 c7 f9  a4 c2 41 34 ac cc f6 ea  |F.F.O.....A4....|
+000002d0  b0 ab 39 18 16 03 02 00  cb 0c 00 00 c7 03 00 17  |..9.............|
+000002e0  41 04 2c e8 55 b8 19 d6  cd e5 c7 96 a4 aa 61 af  |A.,.U.........a.|
+000002f0  aa b2 f1 fc b3 ac 9a 90  02 d0 0a 86 61 9a c1 2e  |............a...|
+00000300  3e fd 42 0b ba 07 95 77  2b 92 a2 5b 1f 44 ad 6b  |>.B....w+..[.D.k|
+00000310  78 7a f4 b3 4b 04 d3 d5  2d eb 20 2d 73 02 4c db  |xz..K...-. -s.L.|
+00000320  7e ac 00 80 79 b0 c6 b9  a8 50 e4 bf de 97 c6 1f  |~...y....P......|
+00000330  ae 5f 89 77 6e e4 23 8c  8d 1a 49 f8 d4 92 cf 0d  |._.wn.#...I.....|
+00000340  f0 08 bd 3a 88 9c 55 46  fc be 9e 7c 70 ff 6f 70  |...:..UF...|p.op|
+00000350  7b 94 b3 7b 82 c3 58 53  f7 20 13 3c 83 6e 10 55  |{..{..XS. .<.n.U|
+00000360  9d 51 cb 53 8c 93 dc 0e  02 06 40 d4 df ce 57 e4  |.Q.S...... at ...W.|
+00000370  e0 9a ba e2 b3 9b 01 98  0e 12 ca e9 96 5b 7a f2  |.............[z.|
+00000380  b1 ac 9c 44 e7 6e 2e c6  51 63 99 68 26 93 ca e2  |...D.n..Qc.h&...|
+00000390  40 31 e5 9a 80 ce 83 8f  ca 80 90 c4 e8 ab 89 b2  |@1..............|
+000003a0  ca d6 30 a5 16 03 02 00  04 0e 00 00 00           |..0..........|
 >>> Flow 3 (client to server)
 00000000  16 03 02 00 46 10 00 00  42 41 04 1e 18 37 ef 0d  |....F...BA...7..|
 00000010  19 51 88 35 75 71 b5 e5  54 5b 12 2e 8f 09 67 fd  |.Q.5uq..T[....g.|
@@ -80,21 +75,21 @@
 00000030  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
 00000040  a6 b5 68 1a 41 03 56 6b  dc 5a 89 14 03 02 00 01  |..h.A.Vk.Z......|
 00000050  01 16 03 02 00 40 00 00  00 00 00 00 00 00 00 00  |..... at ..........|
-00000060  00 00 00 00 00 00 1e 0b  cd 40 fa 0f ed fa 55 74  |......... at ....Ut|
-00000070  4e ad 10 d1 b5 e1 41 8c  c0 93 81 38 f3 83 f1 37  |N.....A....8...7|
-00000080  6a d4 6c ea ba 5b 9e 38  d3 c1 bb 41 45 fb f0 48  |j.l..[.8...AE..H|
-00000090  c1 06 31 64 e0 65                                 |..1d.e|
+00000060  00 00 00 00 00 00 7d 87  6f 44 8f b9 92 51 5a b7  |......}.oD...QZ.|
+00000070  d2 6c 22 7f 62 a1 4e 30  61 f8 42 cd b0 05 c0 24  |.l".b.N0a.B....$|
+00000080  1f e0 49 a8 36 ce 8a 68  94 b7 37 c7 e8 d9 d8 05  |..I.6..h..7.....|
+00000090  be fb 5e 48 ba d1                                 |..^H..|
 >>> Flow 4 (server to client)
-00000000  14 03 02 00 01 01 16 03  02 00 40 17 d1 79 f8 e0  |.......... at ..y..|
-00000010  d4 40 15 85 df 4d a6 d5  60 90 1f d6 52 58 e7 ae  |. at ...M..`...RX..|
-00000020  05 eb a2 ea ed c9 be ae  b5 54 39 de 05 66 27 67  |.........T9..f'g|
-00000030  59 07 03 e7 10 f9 3f da  d8 85 8b 2f 7b 33 9f f5  |Y.....?..../{3..|
-00000040  43 50 b9 9c 6e dd 01 ae  d8 c9 1d                 |CP..n......|
+00000000  14 03 02 00 01 01 16 03  02 00 40 7d ed 01 b9 5a  |..........@}...Z|
+00000010  34 f4 e1 63 70 84 13 86  e6 4d 90 92 da 3c 9b 35  |4..cp....M...<.5|
+00000020  77 92 7f 0a fd 69 09 75  30 5b c3 2c 6e 8e d0 59  |w....i.u0[.,n..Y|
+00000030  08 08 5c c9 eb 53 45 f3  a6 12 16 f2 95 06 27 82  |..\..SE.......'.|
+00000040  6d 9b 9e 6a bb 52 79 65  ca 94 9b                 |m..j.Rye...|
 >>> Flow 5 (client to server)
 00000000  17 03 02 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
-00000010  00 00 00 00 00 65 81 63  71 55 1c 46 8a 60 46 d9  |.....e.cqU.F.`F.|
-00000020  7d 71 a2 62 b8 a8 3b 06  3d a2 f4 53 a4 46 a8 9e  |}q.b..;.=..S.F..|
-00000030  b7 89 8a 42 ce 15 03 02  00 30 00 00 00 00 00 00  |...B.....0......|
-00000040  00 00 00 00 00 00 00 00  00 00 7a 78 a4 e7 2f 40  |..........zx../@|
-00000050  df 42 9b 76 7a 45 0a 86  40 af 3c 40 c6 69 ba e1  |.B.vzE.. at .<@.i..|
-00000060  23 82 fa 44 fd 73 fc 5b  f7 b9                    |#..D.s.[..|
+00000010  00 00 00 00 00 bb 2d 28  50 1f a4 8f be 94 b9 99  |......-(P.......|
+00000020  e6 0b dd cf 50 fc 72 92  ec 1d 72 9b 27 9a 36 18  |....P.r...r.'.6.|
+00000030  3e e3 d7 cc 69 15 03 02  00 30 00 00 00 00 00 00  |>...i....0......|
+00000040  00 00 00 00 00 00 00 00  00 00 61 ca 39 3c 7e 9f  |..........a.9<~.|
+00000050  1c c8 c2 2a 42 4a d0 c4  f3 80 41 04 b4 35 d0 41  |...*BJ....A..5.A|
+00000060  3d 47 1b 16 2c 71 27 04  7c 81                    |=G..,q'.|.|
diff --git a/src/crypto/tls/testdata/Client-TLSv11-RSA-RC4 b/src/crypto/tls/testdata/Client-TLSv11-RSA-RC4
index 729391f..e5e315e 100644
--- a/src/crypto/tls/testdata/Client-TLSv11-RSA-RC4
+++ b/src/crypto/tls/testdata/Client-TLSv11-RSA-RC4
@@ -1,84 +1,79 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 81 01 00 00  7d 03 03 00 00 00 00 00  |........}.......|
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 36  |...../.5.......6|
-00000050  00 05 00 05 01 00 00 00  00 00 0a 00 08 00 06 00  |................|
-00000060  17 00 18 00 19 00 0b 00  02 01 00 00 0d 00 0e 00  |................|
-00000070  0c 04 01 04 03 05 01 05  03 02 01 02 03 ff 01 00  |................|
-00000080  01 00 00 12 00 00                                 |......|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
 >>> Flow 2 (server to client)
-00000000  16 03 02 00 51 02 00 00  4d 03 02 7e 38 ae 3c 50  |....Q...M..~8.<P|
-00000010  03 96 3d 54 2f cd 86 21  98 7f 87 43 d8 58 aa a3  |..=T/..!...C.X..|
-00000020  d5 9f e7 25 a6 ab 34 7f  10 5f 99 20 56 c5 a8 dd  |...%..4.._. V...|
-00000030  37 17 0d 51 f1 0d c4 4e  76 0f 01 26 56 c9 0c 20  |7..Q...Nv..&V.. |
-00000040  28 ef cd ac 38 ea d3 7f  6f aa 7c b8 00 05 00 00  |(...8...o.|.....|
-00000050  05 ff 01 00 01 00 16 03  02 02 be 0b 00 02 ba 00  |................|
-00000060  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
-00000070  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
-00000080  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
-00000090  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
-000000a0  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
-000000b0  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
-000000c0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
-000000d0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
-000000e0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
-000000f0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
-00000100  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
-00000110  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
-00000120  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
-00000130  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
-00000140  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
-00000150  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
-00000160  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
-00000170  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
-00000180  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
-00000190  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
-000001a0  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
-000001b0  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
-000001c0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
-000001d0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
-000001e0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
-000001f0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
-00000200  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
-00000210  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
-00000220  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
-00000230  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
-00000240  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
-00000250  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
-00000260  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
-00000270  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
-00000280  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
-00000290  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
-000002a0  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
-000002b0  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
-000002c0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
-000002d0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
-000002e0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
-000002f0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
-00000300  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
-00000310  6e 38 50 29 6c 90 a7 bd  d9 16 03 02 00 04 0e 00  |n8P)l...........|
-00000320  00 00                                             |..|
+00000000  16 03 02 00 51 02 00 00  4d 03 02 59 22 be 64 85  |....Q...M..Y".d.|
+00000010  71 af 54 70 5f a8 50 ff  68 52 a0 9e a7 79 4d 90  |q.Tp_.P.hR...yM.|
+00000020  cd bc c7 9c 4f 62 bc 4d  a6 b9 0c 20 e1 94 8f 01  |....Ob.M... ....|
+00000030  fa 7f 9e 6f 01 72 82 ef  cc 41 ed 4d 7e 76 ee e1  |...o.r...A.M~v..|
+00000040  21 34 f3 5c e0 b4 4b e2  73 37 a8 40 00 05 00 00  |!4.\..K.s7. at ....|
+00000050  05 ff 01 00 01 00 16 03  02 02 71 0b 00 02 6d 00  |..........q...m.|
+00000060  02 6a 00 02 67 30 82 02  63 30 82 01 cc a0 03 02  |.j..g0..c0......|
+00000070  01 02 02 09 00 a2 73 00  0c 81 00 cb f3 30 0d 06  |......s......0..|
+00000080  09 2a 86 48 86 f7 0d 01  01 0b 05 00 30 2b 31 17  |.*.H........0+1.|
+00000090  30 15 06 03 55 04 0a 13  0e 47 6f 6f 67 6c 65 20  |0...U....Google |
+000000a0  54 45 53 54 49 4e 47 31  10 30 0e 06 03 55 04 03  |TESTING1.0...U..|
+000000b0  13 07 47 6f 20 52 6f 6f  74 30 1e 17 0d 31 35 30  |..Go Root0...150|
+000000c0  31 30 31 30 30 30 30 30  30 5a 17 0d 32 35 30 31  |101000000Z..2501|
+000000d0  30 31 30 30 30 30 30 30  5a 30 26 31 17 30 15 06  |01000000Z0&1.0..|
+000000e0  03 55 04 0a 13 0e 47 6f  6f 67 6c 65 20 54 45 53  |.U....Google TES|
+000000f0  54 49 4e 47 31 0b 30 09  06 03 55 04 03 13 02 47  |TING1.0...U....G|
+00000100  6f 30 81 9f 30 0d 06 09  2a 86 48 86 f7 0d 01 01  |o0..0...*.H.....|
+00000110  01 05 00 03 81 8d 00 30  81 89 02 81 81 00 af 87  |.......0........|
+00000120  88 f6 20 1b 95 65 6c 14  ab 44 05 af 3b 45 14 e3  |.. ..el..D..;E..|
+00000130  b7 6d fd 00 63 4d 95 7f  fe 6a 62 35 86 c0 4a f9  |.m..cM...jb5..J.|
+00000140  18 7c f6 aa 25 5e 7a 64  31 66 00 ba f4 8e 92 af  |.|..%^zd1f......|
+00000150  c7 6b d8 76 d4 f3 5f 41  cb 6e 56 15 97 1b 97 c1  |.k.v.._A.nV.....|
+00000160  3c 12 39 21 66 3d 2b 16  d1 bc db 1c c0 a7 da b7  |<.9!f=+.........|
+00000170  ca ad ba da cb d5 21 50  ec de 8d ab d1 6b 81 4b  |......!P.....k.K|
+00000180  89 02 f3 c4 be c1 6c 89  b1 44 84 bd 21 d1 04 7d  |......l..D..!..}|
+00000190  9d 16 4d f9 82 15 f6 ef  fa d6 09 47 f2 fb 02 03  |..M........G....|
+000001a0  01 00 01 a3 81 93 30 81  90 30 0e 06 03 55 1d 0f  |......0..0...U..|
+000001b0  01 01 ff 04 04 03 02 05  a0 30 1d 06 03 55 1d 25  |.........0...U.%|
+000001c0  04 16 30 14 06 08 2b 06  01 05 05 07 03 01 06 08  |..0...+.........|
+000001d0  2b 06 01 05 05 07 03 02  30 0c 06 03 55 1d 13 01  |+.......0...U...|
+000001e0  01 ff 04 02 30 00 30 19  06 03 55 1d 0e 04 12 04  |....0.0...U.....|
+000001f0  10 12 50 8d 89 6f 1b d1  dc 54 4d 6e cb 69 5e 06  |..P..o...TMn.i^.|
+00000200  f4 30 1b 06 03 55 1d 23  04 14 30 12 80 10 bf 3d  |.0...U.#..0....=|
+00000210  b6 a9 66 f2 b8 40 cf ea  b4 03 78 48 1a 41 30 19  |..f.. at ....xH.A0.|
+00000220  06 03 55 1d 11 04 12 30  10 82 0e 65 78 61 6d 70  |..U....0...examp|
+00000230  6c 65 2e 67 6f 6c 61 6e  67 30 0d 06 09 2a 86 48  |le.golang0...*.H|
+00000240  86 f7 0d 01 01 0b 05 00  03 81 81 00 92 7c af 91  |.............|..|
+00000250  55 12 18 96 59 31 a6 48  40 d5 2d d5 ee bb 02 a0  |U...Y1.H at .-.....|
+00000260  f5 c2 1e 7c 9b b3 30 7d  3c dc 76 da 4f 3d c0 fa  |...|..0}<.v.O=..|
+00000270  ae 2d 33 24 6b 03 7b 1b  67 59 11 21 b5 11 bc 77  |.-3$k.{.gY.!...w|
+00000280  b9 d9 e0 6e a8 2d 2e 35  fa 64 5f 22 3e 63 10 6b  |...n.-.5.d_">c.k|
+00000290  be ff 14 86 6d 0d f0 15  31 a8 14 38 1e 3b 84 87  |....m...1..8.;..|
+000002a0  2c cb 98 ed 51 76 b9 b1  4f dd db 9b 84 04 86 40  |,...Qv..O......@|
+000002b0  fa 51 dd ba b4 8d eb e3  46 de 46 b9 4f 86 c7 f9  |.Q......F.F.O...|
+000002c0  a4 c2 41 34 ac cc f6 ea  b0 ab 39 18 16 03 02 00  |..A4......9.....|
+000002d0  04 0e 00 00 00                                    |.....|
 >>> Flow 3 (client to server)
-00000000  16 03 02 00 86 10 00 00  82 00 80 6d 51 f3 7f f9  |...........mQ...|
-00000010  3e fb 75 82 41 36 83 e8  6a ee 2a 2e 25 90 67 4c  |>.u.A6..j.*.%.gL|
-00000020  8e 62 2f 30 81 17 e0 85  09 0c 2b b7 23 d7 b0 e2  |.b/0......+.#...|
-00000030  1d f7 3b d7 f5 a1 27 b6  ee 24 b6 1b cc 5b ea 66  |..;...'..$...[.f|
-00000040  0d 6a f4 e5 85 f9 da 43  b4 0e 86 85 e1 f5 aa be  |.j.....C........|
-00000050  c8 ce 39 4c 9c 86 00 08  c2 4b e2 c6 ec 2f f7 ce  |..9L.....K.../..|
-00000060  e6 bd 77 82 6f 23 b6 e0  bd a2 92 b7 3a ac e8 56  |..w.o#......:..V|
-00000070  f1 af 54 5e 46 87 e9 3b  33 e7 b8 28 b7 d6 c8 90  |..T^F..;3..(....|
-00000080  35 d4 1c 43 d1 30 6f 55  4e 0a 70 14 03 02 00 01  |5..C.0oUN.p.....|
-00000090  01 16 03 02 00 24 b9 df  85 a1 6d a7 14 b5 bc f5  |.....$....m.....|
-000000a0  c2 1d 40 fc 1e 19 f2 36  2d ec 6b 59 c5 6d ae c7  |.. at ....6-.kY.m..|
-000000b0  1c ad 7e a3 5b 4d 12 e5  58 5a                    |..~.[M..XZ|
+00000000  16 03 02 00 86 10 00 00  82 00 80 73 bd 73 65 92  |...........s.se.|
+00000010  86 23 41 14 79 7f d5 c1  10 ce 94 4d ad 9c c3 a9  |.#A.y......M....|
+00000020  87 b5 32 52 f8 6b 11 93  2d 9b 98 0b 8b 1d c0 f6  |..2R.k..-.......|
+00000030  53 17 6d c7 9c 2e ae c9  6f cc 99 23 38 37 1a 10  |S.m.....o..#87..|
+00000040  fe 05 0b b5 55 0a 14 e9  60 7d 70 26 98 e2 54 d9  |....U...`}p&..T.|
+00000050  65 cf 2e f4 53 5f 1d aa  3a f6 33 7b eb 4c 0e b3  |e...S_..:.3{.L..|
+00000060  ff 5a db 36 2a 47 f3 df  f9 fc f5 31 78 83 aa 6b  |.Z.6*G.....1x..k|
+00000070  52 b7 ba 1a 96 bc fa c1  a1 a9 bb 2b f5 38 89 00  |R..........+.8..|
+00000080  4d e5 78 13 4e a4 38 46  42 dc 16 14 03 02 00 01  |M.x.N.8FB.......|
+00000090  01 16 03 02 00 24 0b 7b  3e 32 fb 94 95 66 26 a9  |.....$.{>2...f&.|
+000000a0  4c 21 5e 18 59 cb 80 57  1b 9a 89 c8 91 c5 30 1f  |L!^.Y..W......0.|
+000000b0  1a e2 80 9a 0f 03 8e 7b  4c 7d                    |.......{L}|
 >>> Flow 4 (server to client)
-00000000  14 03 02 00 01 01 16 03  02 00 24 a3 f3 22 a8 32  |..........$..".2|
-00000010  63 c3 88 5c 0f fb 2d 47  21 0d 62 e2 db aa ed ae  |c..\..-G!.b.....|
-00000020  b6 5f e3 c8 98 fc 91 5e  04 83 cf c3 21 17 ce     |._.....^....!..|
+00000000  14 03 02 00 01 01 16 03  02 00 24 06 7f be 82 45  |..........$....E|
+00000010  79 c6 67 fb d3 1e 3f ca  d9 0f 8f 81 36 cc 80 77  |y.g...?.....6..w|
+00000020  b8 48 f3 88 29 fa f1 3a  b2 d4 fd 10 e5 8c 43     |.H..)..:......C|
 >>> Flow 5 (client to server)
-00000000  17 03 02 00 1a f1 e4 46  c7 14 91 4b c6 25 fd aa  |.......F...K.%..|
-00000010  5d dd 3f 61 ac 9c 79 68  bc e6 0f a1 e4 f3 73 15  |].?a..yh......s.|
-00000020  03 02 00 16 6b 8d 23 3c  99 b4 c2 23 3c 27 fd 41  |....k.#<...#<'.A|
-00000030  cc 04 e5 fc e7 f9 d9 81  0a b8                    |..........|
+00000000  17 03 02 00 1a 29 4d a2  80 38 2c 9e 96 bb 29 8b  |.....)M..8,...).|
+00000010  22 69 ea 85 3e d8 a9 66  39 b8 58 12 ae 67 db 15  |"i..>..f9.X..g..|
+00000020  03 02 00 16 8c b2 f4 c1  35 5d 28 dc 5c bc 30 95  |........5](.\.0.|
+00000030  99 3e f6 c6 ff 4f 5c f4  85 1a                    |.>...O\...|
diff --git a/src/crypto/tls/testdata/Client-TLSv12-AES128-GCM-SHA256 b/src/crypto/tls/testdata/Client-TLSv12-AES128-GCM-SHA256
new file mode 100644
index 0000000..9e41089
--- /dev/null
+++ b/src/crypto/tls/testdata/Client-TLSv12-AES128-GCM-SHA256
@@ -0,0 +1,81 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
+00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 51 02 00 00  4d 03 03 e7 18 39 61 14  |....Q...M....9a.|
+00000010  47 69 40 34 ae 4e 58 4b  32 2d ed 2a 52 09 c5 2f  |Gi at 4.NXK2-.*R../|
+00000020  07 f6 44 0b 2b 9c 43 4b  bb 79 b6 20 48 f4 ff f1  |..D.+.CK.y. H...|
+00000030  c6 72 77 e5 3a e0 8d 08  b9 cd 8b bf e3 9b ec 41  |.rw.:..........A|
+00000040  1d d9 86 1b 35 7b 8c 04  e0 83 0d d3 00 9c 00 00  |....5{..........|
+00000050  05 ff 01 00 01 00 16 03  03 02 71 0b 00 02 6d 00  |..........q...m.|
+00000060  02 6a 00 02 67 30 82 02  63 30 82 01 cc a0 03 02  |.j..g0..c0......|
+00000070  01 02 02 09 00 a2 73 00  0c 81 00 cb f3 30 0d 06  |......s......0..|
+00000080  09 2a 86 48 86 f7 0d 01  01 0b 05 00 30 2b 31 17  |.*.H........0+1.|
+00000090  30 15 06 03 55 04 0a 13  0e 47 6f 6f 67 6c 65 20  |0...U....Google |
+000000a0  54 45 53 54 49 4e 47 31  10 30 0e 06 03 55 04 03  |TESTING1.0...U..|
+000000b0  13 07 47 6f 20 52 6f 6f  74 30 1e 17 0d 31 35 30  |..Go Root0...150|
+000000c0  31 30 31 30 30 30 30 30  30 5a 17 0d 32 35 30 31  |101000000Z..2501|
+000000d0  30 31 30 30 30 30 30 30  5a 30 26 31 17 30 15 06  |01000000Z0&1.0..|
+000000e0  03 55 04 0a 13 0e 47 6f  6f 67 6c 65 20 54 45 53  |.U....Google TES|
+000000f0  54 49 4e 47 31 0b 30 09  06 03 55 04 03 13 02 47  |TING1.0...U....G|
+00000100  6f 30 81 9f 30 0d 06 09  2a 86 48 86 f7 0d 01 01  |o0..0...*.H.....|
+00000110  01 05 00 03 81 8d 00 30  81 89 02 81 81 00 af 87  |.......0........|
+00000120  88 f6 20 1b 95 65 6c 14  ab 44 05 af 3b 45 14 e3  |.. ..el..D..;E..|
+00000130  b7 6d fd 00 63 4d 95 7f  fe 6a 62 35 86 c0 4a f9  |.m..cM...jb5..J.|
+00000140  18 7c f6 aa 25 5e 7a 64  31 66 00 ba f4 8e 92 af  |.|..%^zd1f......|
+00000150  c7 6b d8 76 d4 f3 5f 41  cb 6e 56 15 97 1b 97 c1  |.k.v.._A.nV.....|
+00000160  3c 12 39 21 66 3d 2b 16  d1 bc db 1c c0 a7 da b7  |<.9!f=+.........|
+00000170  ca ad ba da cb d5 21 50  ec de 8d ab d1 6b 81 4b  |......!P.....k.K|
+00000180  89 02 f3 c4 be c1 6c 89  b1 44 84 bd 21 d1 04 7d  |......l..D..!..}|
+00000190  9d 16 4d f9 82 15 f6 ef  fa d6 09 47 f2 fb 02 03  |..M........G....|
+000001a0  01 00 01 a3 81 93 30 81  90 30 0e 06 03 55 1d 0f  |......0..0...U..|
+000001b0  01 01 ff 04 04 03 02 05  a0 30 1d 06 03 55 1d 25  |.........0...U.%|
+000001c0  04 16 30 14 06 08 2b 06  01 05 05 07 03 01 06 08  |..0...+.........|
+000001d0  2b 06 01 05 05 07 03 02  30 0c 06 03 55 1d 13 01  |+.......0...U...|
+000001e0  01 ff 04 02 30 00 30 19  06 03 55 1d 0e 04 12 04  |....0.0...U.....|
+000001f0  10 12 50 8d 89 6f 1b d1  dc 54 4d 6e cb 69 5e 06  |..P..o...TMn.i^.|
+00000200  f4 30 1b 06 03 55 1d 23  04 14 30 12 80 10 bf 3d  |.0...U.#..0....=|
+00000210  b6 a9 66 f2 b8 40 cf ea  b4 03 78 48 1a 41 30 19  |..f.. at ....xH.A0.|
+00000220  06 03 55 1d 11 04 12 30  10 82 0e 65 78 61 6d 70  |..U....0...examp|
+00000230  6c 65 2e 67 6f 6c 61 6e  67 30 0d 06 09 2a 86 48  |le.golang0...*.H|
+00000240  86 f7 0d 01 01 0b 05 00  03 81 81 00 92 7c af 91  |.............|..|
+00000250  55 12 18 96 59 31 a6 48  40 d5 2d d5 ee bb 02 a0  |U...Y1.H at .-.....|
+00000260  f5 c2 1e 7c 9b b3 30 7d  3c dc 76 da 4f 3d c0 fa  |...|..0}<.v.O=..|
+00000270  ae 2d 33 24 6b 03 7b 1b  67 59 11 21 b5 11 bc 77  |.-3$k.{.gY.!...w|
+00000280  b9 d9 e0 6e a8 2d 2e 35  fa 64 5f 22 3e 63 10 6b  |...n.-.5.d_">c.k|
+00000290  be ff 14 86 6d 0d f0 15  31 a8 14 38 1e 3b 84 87  |....m...1..8.;..|
+000002a0  2c cb 98 ed 51 76 b9 b1  4f dd db 9b 84 04 86 40  |,...Qv..O......@|
+000002b0  fa 51 dd ba b4 8d eb e3  46 de 46 b9 4f 86 c7 f9  |.Q......F.F.O...|
+000002c0  a4 c2 41 34 ac cc f6 ea  b0 ab 39 18 16 03 03 00  |..A4......9.....|
+000002d0  04 0e 00 00 00                                    |.....|
+>>> Flow 3 (client to server)
+00000000  16 03 03 00 86 10 00 00  82 00 80 73 bd 73 65 92  |...........s.se.|
+00000010  86 23 41 14 79 7f d5 c1  10 ce 94 4d ad 9c c3 a9  |.#A.y......M....|
+00000020  87 b5 32 52 f8 6b 11 93  2d 9b 98 0b 8b 1d c0 f6  |..2R.k..-.......|
+00000030  53 17 6d c7 9c 2e ae c9  6f cc 99 23 38 37 1a 10  |S.m.....o..#87..|
+00000040  fe 05 0b b5 55 0a 14 e9  60 7d 70 26 98 e2 54 d9  |....U...`}p&..T.|
+00000050  65 cf 2e f4 53 5f 1d aa  3a f6 33 7b eb 4c 0e b3  |e...S_..:.3{.L..|
+00000060  ff 5a db 36 2a 47 f3 df  f9 fc f5 31 78 83 aa 6b  |.Z.6*G.....1x..k|
+00000070  52 b7 ba 1a 96 bc fa c1  a1 a9 bb 2b f5 38 89 00  |R..........+.8..|
+00000080  4d e5 78 13 4e a4 38 46  42 dc 16 14 03 03 00 01  |M.x.N.8FB.......|
+00000090  01 16 03 03 00 28 00 00  00 00 00 00 00 00 8a 9b  |.....(..........|
+000000a0  29 1d 64 2e ee 0d 39 d9  c5 86 b9 02 9d c3 bd 74  |).d...9........t|
+000000b0  39 9d 53 9f 1a ee 84 64  82 82 41 81 f8 2f        |9.S....d..A../|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 28 60 71 25 f9 f9  |..........(`q%..|
+00000010  89 cd f8 6f 00 a6 0e 92  f8 3e 84 08 79 6f 91 cd  |...o.....>..yo..|
+00000020  e2 62 d5 da 96 79 c3 0d  f4 34 26 bd 47 9c 30 aa  |.b...y...4&.G.0.|
+00000030  1b 5f 24                                          |._$|
+>>> Flow 5 (client to server)
+00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 44 05 c9  |.............D..|
+00000010  2b 82 55 26 ab 4b 65 b1  94 e5 8a 81 bf 44 a5 cb  |+.U&.Ke......D..|
+00000020  22 f0 0a 15 03 03 00 1a  00 00 00 00 00 00 00 02  |"...............|
+00000030  59 8d 6f 5d 30 47 4d 3e  ed aa 87 5f ca 39 44 a4  |Y.o]0GM>..._.9D.|
+00000040  9b fc                                             |..|
diff --git a/src/crypto/tls/testdata/Client-TLSv12-AES256-GCM-SHA384 b/src/crypto/tls/testdata/Client-TLSv12-AES256-GCM-SHA384
new file mode 100644
index 0000000..33fb708
--- /dev/null
+++ b/src/crypto/tls/testdata/Client-TLSv12-AES256-GCM-SHA384
@@ -0,0 +1,81 @@
+>>> Flow 1 (client to server)
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
+00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
+00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
+>>> Flow 2 (server to client)
+00000000  16 03 03 00 51 02 00 00  4d 03 03 08 e2 40 1b 1a  |....Q...M.... at ..|
+00000010  54 dc 66 60 e1 e0 8d 94  c6 dd 2c eb 95 e0 e9 2f  |T.f`......,..../|
+00000020  fb 49 17 d8 34 d7 a2 7a  1b e1 60 20 26 a3 4b 7c  |.I..4..z..` &.K||
+00000030  40 cc df 4b 9c 72 a9 e6  61 89 1e 20 b2 e5 e3 1e  |@..K.r..a.. ....|
+00000040  4e a3 b6 32 ce fc 94 0d  ab 13 74 f8 00 9d 00 00  |N..2......t.....|
+00000050  05 ff 01 00 01 00 16 03  03 02 71 0b 00 02 6d 00  |..........q...m.|
+00000060  02 6a 00 02 67 30 82 02  63 30 82 01 cc a0 03 02  |.j..g0..c0......|
+00000070  01 02 02 09 00 a2 73 00  0c 81 00 cb f3 30 0d 06  |......s......0..|
+00000080  09 2a 86 48 86 f7 0d 01  01 0b 05 00 30 2b 31 17  |.*.H........0+1.|
+00000090  30 15 06 03 55 04 0a 13  0e 47 6f 6f 67 6c 65 20  |0...U....Google |
+000000a0  54 45 53 54 49 4e 47 31  10 30 0e 06 03 55 04 03  |TESTING1.0...U..|
+000000b0  13 07 47 6f 20 52 6f 6f  74 30 1e 17 0d 31 35 30  |..Go Root0...150|
+000000c0  31 30 31 30 30 30 30 30  30 5a 17 0d 32 35 30 31  |101000000Z..2501|
+000000d0  30 31 30 30 30 30 30 30  5a 30 26 31 17 30 15 06  |01000000Z0&1.0..|
+000000e0  03 55 04 0a 13 0e 47 6f  6f 67 6c 65 20 54 45 53  |.U....Google TES|
+000000f0  54 49 4e 47 31 0b 30 09  06 03 55 04 03 13 02 47  |TING1.0...U....G|
+00000100  6f 30 81 9f 30 0d 06 09  2a 86 48 86 f7 0d 01 01  |o0..0...*.H.....|
+00000110  01 05 00 03 81 8d 00 30  81 89 02 81 81 00 af 87  |.......0........|
+00000120  88 f6 20 1b 95 65 6c 14  ab 44 05 af 3b 45 14 e3  |.. ..el..D..;E..|
+00000130  b7 6d fd 00 63 4d 95 7f  fe 6a 62 35 86 c0 4a f9  |.m..cM...jb5..J.|
+00000140  18 7c f6 aa 25 5e 7a 64  31 66 00 ba f4 8e 92 af  |.|..%^zd1f......|
+00000150  c7 6b d8 76 d4 f3 5f 41  cb 6e 56 15 97 1b 97 c1  |.k.v.._A.nV.....|
+00000160  3c 12 39 21 66 3d 2b 16  d1 bc db 1c c0 a7 da b7  |<.9!f=+.........|
+00000170  ca ad ba da cb d5 21 50  ec de 8d ab d1 6b 81 4b  |......!P.....k.K|
+00000180  89 02 f3 c4 be c1 6c 89  b1 44 84 bd 21 d1 04 7d  |......l..D..!..}|
+00000190  9d 16 4d f9 82 15 f6 ef  fa d6 09 47 f2 fb 02 03  |..M........G....|
+000001a0  01 00 01 a3 81 93 30 81  90 30 0e 06 03 55 1d 0f  |......0..0...U..|
+000001b0  01 01 ff 04 04 03 02 05  a0 30 1d 06 03 55 1d 25  |.........0...U.%|
+000001c0  04 16 30 14 06 08 2b 06  01 05 05 07 03 01 06 08  |..0...+.........|
+000001d0  2b 06 01 05 05 07 03 02  30 0c 06 03 55 1d 13 01  |+.......0...U...|
+000001e0  01 ff 04 02 30 00 30 19  06 03 55 1d 0e 04 12 04  |....0.0...U.....|
+000001f0  10 12 50 8d 89 6f 1b d1  dc 54 4d 6e cb 69 5e 06  |..P..o...TMn.i^.|
+00000200  f4 30 1b 06 03 55 1d 23  04 14 30 12 80 10 bf 3d  |.0...U.#..0....=|
+00000210  b6 a9 66 f2 b8 40 cf ea  b4 03 78 48 1a 41 30 19  |..f.. at ....xH.A0.|
+00000220  06 03 55 1d 11 04 12 30  10 82 0e 65 78 61 6d 70  |..U....0...examp|
+00000230  6c 65 2e 67 6f 6c 61 6e  67 30 0d 06 09 2a 86 48  |le.golang0...*.H|
+00000240  86 f7 0d 01 01 0b 05 00  03 81 81 00 92 7c af 91  |.............|..|
+00000250  55 12 18 96 59 31 a6 48  40 d5 2d d5 ee bb 02 a0  |U...Y1.H at .-.....|
+00000260  f5 c2 1e 7c 9b b3 30 7d  3c dc 76 da 4f 3d c0 fa  |...|..0}<.v.O=..|
+00000270  ae 2d 33 24 6b 03 7b 1b  67 59 11 21 b5 11 bc 77  |.-3$k.{.gY.!...w|
+00000280  b9 d9 e0 6e a8 2d 2e 35  fa 64 5f 22 3e 63 10 6b  |...n.-.5.d_">c.k|
+00000290  be ff 14 86 6d 0d f0 15  31 a8 14 38 1e 3b 84 87  |....m...1..8.;..|
+000002a0  2c cb 98 ed 51 76 b9 b1  4f dd db 9b 84 04 86 40  |,...Qv..O......@|
+000002b0  fa 51 dd ba b4 8d eb e3  46 de 46 b9 4f 86 c7 f9  |.Q......F.F.O...|
+000002c0  a4 c2 41 34 ac cc f6 ea  b0 ab 39 18 16 03 03 00  |..A4......9.....|
+000002d0  04 0e 00 00 00                                    |.....|
+>>> Flow 3 (client to server)
+00000000  16 03 03 00 86 10 00 00  82 00 80 73 bd 73 65 92  |...........s.se.|
+00000010  86 23 41 14 79 7f d5 c1  10 ce 94 4d ad 9c c3 a9  |.#A.y......M....|
+00000020  87 b5 32 52 f8 6b 11 93  2d 9b 98 0b 8b 1d c0 f6  |..2R.k..-.......|
+00000030  53 17 6d c7 9c 2e ae c9  6f cc 99 23 38 37 1a 10  |S.m.....o..#87..|
+00000040  fe 05 0b b5 55 0a 14 e9  60 7d 70 26 98 e2 54 d9  |....U...`}p&..T.|
+00000050  65 cf 2e f4 53 5f 1d aa  3a f6 33 7b eb 4c 0e b3  |e...S_..:.3{.L..|
+00000060  ff 5a db 36 2a 47 f3 df  f9 fc f5 31 78 83 aa 6b  |.Z.6*G.....1x..k|
+00000070  52 b7 ba 1a 96 bc fa c1  a1 a9 bb 2b f5 38 89 00  |R..........+.8..|
+00000080  4d e5 78 13 4e a4 38 46  42 dc 16 14 03 03 00 01  |M.x.N.8FB.......|
+00000090  01 16 03 03 00 28 00 00  00 00 00 00 00 00 28 9a  |.....(........(.|
+000000a0  46 23 21 fa a9 ec 6d 57  d1 27 2f 53 58 a9 00 48  |F#!...mW.'/SX..H|
+000000b0  7e 82 82 b8 23 f3 c4 a8  d3 2c a3 99 76 2e        |~...#....,..v.|
+>>> Flow 4 (server to client)
+00000000  14 03 03 00 01 01 16 03  03 00 28 0c c8 0a e1 b8  |..........(.....|
+00000010  95 b9 84 bc 0f 48 eb d4  4a a5 63 c2 92 58 8a 91  |.....H..J.c..X..|
+00000020  27 30 36 28 23 f5 50 bd  d6 a9 e9 61 54 10 f9 72  |'06(#.P....aT..r|
+00000030  98 d1 0e                                          |...|
+>>> Flow 5 (client to server)
+00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 b9 55 ce  |..............U.|
+00000010  5a ab 7e 7e 58 4f c9 5a  bc 0e 93 98 4f 87 86 98  |Z.~~XO.Z....O...|
+00000020  a6 40 7e 15 03 03 00 1a  00 00 00 00 00 00 00 02  |.@~.............|
+00000030  57 0c 6f d9 28 87 d4 a6  de 14 91 a7 79 cc 19 e5  |W.o.(.......y...|
+00000040  28 66                                             |(f|
diff --git a/src/crypto/tls/testdata/Client-TLSv12-ALPN b/src/crypto/tls/testdata/Client-TLSv12-ALPN
index 9ecb065..d7745dc 100644
--- a/src/crypto/tls/testdata/Client-TLSv12-ALPN
+++ b/src/crypto/tls/testdata/Client-TLSv12-ALPN
@@ -1,97 +1,93 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 99 01 00 00  95 03 03 00 00 00 00 00  |................|
+00000000  16 03 01 00 9d 01 00 00  99 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 4e  |...../.5.......N|
-00000050  33 74 00 00 00 05 00 05  01 00 00 00 00 00 0a 00  |3t..............|
-00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
-00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
-00000080  03 ff 01 00 01 00 00 10  00 10 00 0e 06 70 72 6f  |.............pro|
-00000090  74 6f 32 06 70 72 6f 74  6f 31 00 12 00 00        |to2.proto1....|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 4e 33 74 00 00  00 05 00 05 01 00 00 00  |...N3t..........|
+00000060  00 00 0a 00 08 00 06 00  17 00 18 00 19 00 0b 00  |................|
+00000070  02 01 00 00 0d 00 0e 00  0c 04 01 04 03 05 01 05  |................|
+00000080  03 02 01 02 03 ff 01 00  01 00 00 10 00 10 00 0e  |................|
+00000090  06 70 72 6f 74 6f 32 06  70 72 6f 74 6f 31 00 12  |.proto2.proto1..|
+000000a0  00 00                                             |..|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 66 02 00 00  62 03 03 56 83 34 0f 9e  |....f...b..V.4..|
-00000010  dd 02 1c 4f 4f 09 d0 2c  df e6 c1 d2 4a c0 6a e7  |...OO..,....J.j.|
-00000020  1e 65 51 c2 42 01 05 70  4a 6c 97 20 0f a8 fb d8  |.eQ.B..pJl. ....|
-00000030  2f 0f 75 21 17 f8 dd 63  28 4a 18 f6 b1 e5 6f 7c  |/.u!...c(J....o||
-00000040  1d 09 d4 13 bf 66 3a bd  c5 48 14 fc c0 2f 00 00  |.....f:..H.../..|
+00000000  16 03 03 00 66 02 00 00  62 03 03 a2 7d b9 7c f9  |....f...b...}.|.|
+00000010  bf fb cb b2 d5 11 c0 99  19 73 3d b4 eb 6b 39 f8  |.........s=..k9.|
+00000020  1b 7c 1d 6b 17 4d 66 a3  ed 20 5b 20 ee 87 d7 1f  |.|.k.Mf.. [ ....|
+00000030  cf 60 6c 75 12 8b de 56  f6 ca da 4a 92 76 49 43  |.`lu...V...J.vIC|
+00000040  70 18 0a e7 7b 2a 0c f3  44 a6 d8 dd c0 2f 00 00  |p...{*..D..../..|
 00000050  1a ff 01 00 01 00 00 0b  00 04 03 00 01 02 00 10  |................|
-00000060  00 09 00 07 06 70 72 6f  74 6f 31 16 03 03 02 be  |.....proto1.....|
-00000070  0b 00 02 ba 00 02 b7 00  02 b4 30 82 02 b0 30 82  |..........0...0.|
-00000080  02 19 a0 03 02 01 02 02  09 00 85 b0 bb a4 8a 7f  |................|
-00000090  b8 ca 30 0d 06 09 2a 86  48 86 f7 0d 01 01 05 05  |..0...*.H.......|
-000000a0  00 30 45 31 0b 30 09 06  03 55 04 06 13 02 41 55  |.0E1.0...U....AU|
-000000b0  31 13 30 11 06 03 55 04  08 13 0a 53 6f 6d 65 2d  |1.0...U....Some-|
-000000c0  53 74 61 74 65 31 21 30  1f 06 03 55 04 0a 13 18  |State1!0...U....|
-000000d0  49 6e 74 65 72 6e 65 74  20 57 69 64 67 69 74 73  |Internet Widgits|
-000000e0  20 50 74 79 20 4c 74 64  30 1e 17 0d 31 30 30 34  | Pty Ltd0...1004|
-000000f0  32 34 30 39 30 39 33 38  5a 17 0d 31 31 30 34 32  |24090938Z..11042|
-00000100  34 30 39 30 39 33 38 5a  30 45 31 0b 30 09 06 03  |4090938Z0E1.0...|
-00000110  55 04 06 13 02 41 55 31  13 30 11 06 03 55 04 08  |U....AU1.0...U..|
-00000120  13 0a 53 6f 6d 65 2d 53  74 61 74 65 31 21 30 1f  |..Some-State1!0.|
-00000130  06 03 55 04 0a 13 18 49  6e 74 65 72 6e 65 74 20  |..U....Internet |
-00000140  57 69 64 67 69 74 73 20  50 74 79 20 4c 74 64 30  |Widgits Pty Ltd0|
-00000150  81 9f 30 0d 06 09 2a 86  48 86 f7 0d 01 01 01 05  |..0...*.H.......|
-00000160  00 03 81 8d 00 30 81 89  02 81 81 00 bb 79 d6 f5  |.....0.......y..|
-00000170  17 b5 e5 bf 46 10 d0 dc  69 be e6 2b 07 43 5a d0  |....F...i..+.CZ.|
-00000180  03 2d 8a 7a 43 85 b7 14  52 e7 a5 65 4c 2c 78 b8  |.-.zC...R..eL,x.|
-00000190  23 8c b5 b4 82 e5 de 1f  95 3b 7e 62 a5 2c a5 33  |#........;~b.,.3|
-000001a0  d6 fe 12 5c 7a 56 fc f5  06 bf fa 58 7b 26 3f b5  |...\zV.....X{&?.|
-000001b0  cd 04 d3 d0 c9 21 96 4a  c7 f4 54 9f 5a bf ef 42  |.....!.J..T.Z..B|
-000001c0  71 00 fe 18 99 07 7f 7e  88 7d 7d f1 04 39 c4 a2  |q......~.}}..9..|
-000001d0  2e db 51 c9 7c e3 c0 4c  3b 32 66 01 cf af b1 1d  |..Q.|..L;2f.....|
-000001e0  b8 71 9a 1d db db 89 6b  ae da 2d 79 02 03 01 00  |.q.....k..-y....|
-000001f0  01 a3 81 a7 30 81 a4 30  1d 06 03 55 1d 0e 04 16  |....0..0...U....|
-00000200  04 14 b1 ad e2 85 5a cf  cb 28 db 69 ce 23 69 de  |......Z..(.i.#i.|
-00000210  d3 26 8e 18 88 39 30 75  06 03 55 1d 23 04 6e 30  |.&...90u..U.#.n0|
-00000220  6c 80 14 b1 ad e2 85 5a  cf cb 28 db 69 ce 23 69  |l......Z..(.i.#i|
-00000230  de d3 26 8e 18 88 39 a1  49 a4 47 30 45 31 0b 30  |..&...9.I.G0E1.0|
-00000240  09 06 03 55 04 06 13 02  41 55 31 13 30 11 06 03  |...U....AU1.0...|
-00000250  55 04 08 13 0a 53 6f 6d  65 2d 53 74 61 74 65 31  |U....Some-State1|
-00000260  21 30 1f 06 03 55 04 0a  13 18 49 6e 74 65 72 6e  |!0...U....Intern|
-00000270  65 74 20 57 69 64 67 69  74 73 20 50 74 79 20 4c  |et Widgits Pty L|
-00000280  74 64 82 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0c 06  |td...........0..|
-00000290  03 55 1d 13 04 05 30 03  01 01 ff 30 0d 06 09 2a  |.U....0....0...*|
-000002a0  86 48 86 f7 0d 01 01 05  05 00 03 81 81 00 08 6c  |.H.............l|
-000002b0  45 24 c7 6b b1 59 ab 0c  52 cc f2 b0 14 d7 87 9d  |E$.k.Y..R.......|
-000002c0  7a 64 75 b5 5a 95 66 e4  c5 2b 8e ae 12 66 1f eb  |zdu.Z.f..+...f..|
-000002d0  4f 38 b3 6e 60 d3 92 fd  f7 41 08 b5 25 13 b1 18  |O8.n`....A..%...|
-000002e0  7a 24 fb 30 1d ba ed 98  b9 17 ec e7 d7 31 59 db  |z$.0.........1Y.|
-000002f0  95 d3 1d 78 ea 50 56 5c  d5 82 5a 2d 5a 5f 33 c4  |...x.PV\..Z-Z_3.|
-00000300  b6 d8 c9 75 90 96 8c 0f  52 98 b5 cd 98 1f 89 20  |...u....R...... |
-00000310  5f f2 a0 1c a3 1b 96 94  dd a9 fd 57 e9 70 e8 26  |_..........W.p.&|
-00000320  6d 71 99 9b 26 6e 38 50  29 6c 90 a7 bd d9 16 03  |mq..&n8P)l......|
-00000330  03 00 cd 0c 00 00 c9 03  00 17 41 04 85 b7 f7 7c  |..........A....||
-00000340  49 4e 97 14 07 51 bc 56  2d 3f cf 1d 29 08 ac 6a  |IN...Q.V-?..)..j|
-00000350  b4 e7 0d 62 d8 fd 4d 03  29 0d f8 6c 36 6f 4d 5f  |...b..M.)..l6oM_|
-00000360  b7 5a 8e 37 3e c2 d9 dc  f4 15 52 e9 87 71 0f e5  |.Z.7>.....R..q..|
-00000370  4e a6 88 0e 54 35 e0 8b  50 91 e1 c4 04 01 00 80  |N...T5..P.......|
-00000380  51 eb f8 d6 52 ba f5 b5  0a 22 5f 91 fe f7 ee 43  |Q...R...."_....C|
-00000390  f8 af 52 b6 27 2c fc 14  e2 fb 41 61 ff 7c b9 be  |..R.',....Aa.|..|
-000003a0  f9 78 be dc 18 32 8c 4d  ef 46 c0 5a a7 91 6a 1b  |.x...2.M.F.Z..j.|
-000003b0  47 78 46 39 47 81 8a 2d  b4 cb fd bb 44 3e a7 b7  |GxF9G..-....D>..|
-000003c0  cc 4e df 17 7b 2b 38 49  fa 9d 9f 4e cd ed f2 16  |.N..{+8I...N....|
-000003d0  03 d9 68 cf c9 5a 08 32  f8 ed 02 30 54 61 f6 c0  |..h..Z.2...0Ta..|
-000003e0  f6 78 bc ad 04 9c 8e 90  7d 3d f5 35 86 aa 6e e9  |.x......}=.5..n.|
-000003f0  a2 9a d3 86 27 9f 2d 6e  ea 6e ad 82 0e aa ef 97  |....'.-n.n......|
-00000400  16 03 03 00 04 0e 00 00  00                       |.........|
+00000060  00 09 00 07 06 70 72 6f  74 6f 31 16 03 03 02 71  |.....proto1....q|
+00000070  0b 00 02 6d 00 02 6a 00  02 67 30 82 02 63 30 82  |...m..j..g0..c0.|
+00000080  01 cc a0 03 02 01 02 02  09 00 a2 73 00 0c 81 00  |...........s....|
+00000090  cb f3 30 0d 06 09 2a 86  48 86 f7 0d 01 01 0b 05  |..0...*.H.......|
+000000a0  00 30 2b 31 17 30 15 06  03 55 04 0a 13 0e 47 6f  |.0+1.0...U....Go|
+000000b0  6f 67 6c 65 20 54 45 53  54 49 4e 47 31 10 30 0e  |ogle TESTING1.0.|
+000000c0  06 03 55 04 03 13 07 47  6f 20 52 6f 6f 74 30 1e  |..U....Go Root0.|
+000000d0  17 0d 31 35 30 31 30 31  30 30 30 30 30 30 5a 17  |..150101000000Z.|
+000000e0  0d 32 35 30 31 30 31 30  30 30 30 30 30 5a 30 26  |.250101000000Z0&|
+000000f0  31 17 30 15 06 03 55 04  0a 13 0e 47 6f 6f 67 6c  |1.0...U....Googl|
+00000100  65 20 54 45 53 54 49 4e  47 31 0b 30 09 06 03 55  |e TESTING1.0...U|
+00000110  04 03 13 02 47 6f 30 81  9f 30 0d 06 09 2a 86 48  |....Go0..0...*.H|
+00000120  86 f7 0d 01 01 01 05 00  03 81 8d 00 30 81 89 02  |............0...|
+00000130  81 81 00 af 87 88 f6 20  1b 95 65 6c 14 ab 44 05  |....... ..el..D.|
+00000140  af 3b 45 14 e3 b7 6d fd  00 63 4d 95 7f fe 6a 62  |.;E...m..cM...jb|
+00000150  35 86 c0 4a f9 18 7c f6  aa 25 5e 7a 64 31 66 00  |5..J..|..%^zd1f.|
+00000160  ba f4 8e 92 af c7 6b d8  76 d4 f3 5f 41 cb 6e 56  |......k.v.._A.nV|
+00000170  15 97 1b 97 c1 3c 12 39  21 66 3d 2b 16 d1 bc db  |.....<.9!f=+....|
+00000180  1c c0 a7 da b7 ca ad ba  da cb d5 21 50 ec de 8d  |...........!P...|
+00000190  ab d1 6b 81 4b 89 02 f3  c4 be c1 6c 89 b1 44 84  |..k.K......l..D.|
+000001a0  bd 21 d1 04 7d 9d 16 4d  f9 82 15 f6 ef fa d6 09  |.!..}..M........|
+000001b0  47 f2 fb 02 03 01 00 01  a3 81 93 30 81 90 30 0e  |G..........0..0.|
+000001c0  06 03 55 1d 0f 01 01 ff  04 04 03 02 05 a0 30 1d  |..U...........0.|
+000001d0  06 03 55 1d 25 04 16 30  14 06 08 2b 06 01 05 05  |..U.%..0...+....|
+000001e0  07 03 01 06 08 2b 06 01  05 05 07 03 02 30 0c 06  |.....+.......0..|
+000001f0  03 55 1d 13 01 01 ff 04  02 30 00 30 19 06 03 55  |.U.......0.0...U|
+00000200  1d 0e 04 12 04 10 12 50  8d 89 6f 1b d1 dc 54 4d  |.......P..o...TM|
+00000210  6e cb 69 5e 06 f4 30 1b  06 03 55 1d 23 04 14 30  |n.i^..0...U.#..0|
+00000220  12 80 10 bf 3d b6 a9 66  f2 b8 40 cf ea b4 03 78  |....=..f.. at ....x|
+00000230  48 1a 41 30 19 06 03 55  1d 11 04 12 30 10 82 0e  |H.A0...U....0...|
+00000240  65 78 61 6d 70 6c 65 2e  67 6f 6c 61 6e 67 30 0d  |example.golang0.|
+00000250  06 09 2a 86 48 86 f7 0d  01 01 0b 05 00 03 81 81  |..*.H...........|
+00000260  00 92 7c af 91 55 12 18  96 59 31 a6 48 40 d5 2d  |..|..U...Y1.H at .-|
+00000270  d5 ee bb 02 a0 f5 c2 1e  7c 9b b3 30 7d 3c dc 76  |........|..0}<.v|
+00000280  da 4f 3d c0 fa ae 2d 33  24 6b 03 7b 1b 67 59 11  |.O=...-3$k.{.gY.|
+00000290  21 b5 11 bc 77 b9 d9 e0  6e a8 2d 2e 35 fa 64 5f  |!...w...n.-.5.d_|
+000002a0  22 3e 63 10 6b be ff 14  86 6d 0d f0 15 31 a8 14  |">c.k....m...1..|
+000002b0  38 1e 3b 84 87 2c cb 98  ed 51 76 b9 b1 4f dd db  |8.;..,...Qv..O..|
+000002c0  9b 84 04 86 40 fa 51 dd  ba b4 8d eb e3 46 de 46  |.... at .Q......F.F|
+000002d0  b9 4f 86 c7 f9 a4 c2 41  34 ac cc f6 ea b0 ab 39  |.O.....A4......9|
+000002e0  18 16 03 03 00 cd 0c 00  00 c9 03 00 17 41 04 41  |.............A.A|
+000002f0  a4 1f 6f ea 6d 59 68 72  1a 6d 47 c7 b4 a0 08 01  |..o.mYhr.mG.....|
+00000300  b9 b3 d8 7a 95 75 c0 58  2a d9 29 91 e7 d9 78 b2  |...z.u.X*.)...x.|
+00000310  97 1d 52 72 2d 18 cb ce  83 8a 07 f4 bd dd 7e a1  |..Rr-.........~.|
+00000320  d2 45 51 9d bf f1 bf 01  33 3a 10 94 6c 2b 99 04  |.EQ.....3:..l+..|
+00000330  01 00 80 63 8f 03 6d b4  4d f7 27 d0 1f f2 0f ff  |...c..m.M.'.....|
+00000340  af 27 c2 97 21 68 8c 32  8b 14 67 0e b5 75 3a 5b  |.'..!h.2..g..u:[|
+00000350  73 08 9a c7 fd ad 8d 50  2a de e7 d6 c5 87 7a b2  |s......P*.....z.|
+00000360  06 29 0a 09 dd d4 81 d5  a7 2b 4d 20 50 72 6f be  |.).......+M Pro.|
+00000370  35 9b c6 2d b0 1e 8f a2  cf 10 33 d4 53 0b 33 95  |5..-......3.S.3.|
+00000380  b8 a5 34 38 1b db 1e 45  07 36 3a 86 c7 f1 b1 3a  |..48...E.6:....:|
+00000390  2e 5d 82 b2 1d 3e e1 27  8f f2 f4 2c 8c c3 27 e9  |.]...>.'...,..'.|
+000003a0  f0 9a 8f 6d 20 b1 19 8e  23 d5 04 69 e4 eb 0d eb  |...m ...#..i....|
+000003b0  97 fb 71 16 03 03 00 04  0e 00 00 00              |..q.........|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 46 10 00 00  42 41 04 1e 18 37 ef 0d  |....F...BA...7..|
 00000010  19 51 88 35 75 71 b5 e5  54 5b 12 2e 8f 09 67 fd  |.Q.5uq..T[....g.|
 00000020  a7 24 20 3e b2 56 1c ce  97 28 5e f8 2b 2d 4f 9e  |.$ >.V...(^.+-O.|
 00000030  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
 00000040  a6 b5 68 1a 41 03 56 6b  dc 5a 89 14 03 03 00 01  |..h.A.Vk.Z......|
-00000050  01 16 03 03 00 28 00 00  00 00 00 00 00 00 47 18  |.....(........G.|
-00000060  39 03 93 d9 5b 27 29 70  52 68 15 79 f2 60 e6 58  |9...[')pRh.y.`.X|
-00000070  d9 98 cd ce a1 8f 4d ee  2c f0 34 9f fa 73        |......M.,.4..s|
+00000050  01 16 03 03 00 28 00 00  00 00 00 00 00 00 15 94  |.....(..........|
+00000060  6f 5b 35 9d eb 14 c8 be  23 a7 05 8c 14 86 35 a7  |o[5.....#.....5.|
+00000070  5c 91 76 4f 85 b1 09 f8  0f 58 9f ec d2 a9        |\.vO.....X....|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 28 39 76 15 70 f1  |..........(9v.p.|
-00000010  73 c9 9a 1e 76 40 bc de  de 49 be 3e 10 4d 6a 42  |s...v at ...I.>.MjB|
-00000020  1b 9b bd 07 6b 19 ff f9  2c 19 3c c8 e7 06 fa c8  |....k...,.<.....|
-00000030  3d 52 b4                                          |=R.|
+00000000  14 03 03 00 01 01 16 03  03 00 28 e7 7f 99 c9 fa  |..........(.....|
+00000010  e0 a3 e3 77 68 74 37 62  26 90 d6 be ec a1 ae 5a  |...wht7b&......Z|
+00000020  de af 10 f1 2e a0 42 f0  88 ed 89 54 04 b2 b9 eb  |......B....T....|
+00000030  b0 91 b8                                          |...|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 14 96 ec  |................|
-00000010  f4 bb ae 45 81 0c 39 10  e2 3a 91 51 04 2c 01 a8  |...E..9..:.Q.,..|
-00000020  8b a3 25 15 03 03 00 1a  00 00 00 00 00 00 00 02  |..%.............|
-00000030  fe 1a 53 01 17 ad a1 30  0a 73 17 9f 39 b4 30 ac  |..S....0.s..9.0.|
-00000040  91 ee                                             |..|
+00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 be e7 77  |...............w|
+00000010  f9 92 ac 51 d0 34 25 34  e6 35 9e ea f0 d3 89 45  |...Q.4%4.5.....E|
+00000020  84 1b 93 15 03 03 00 1a  00 00 00 00 00 00 00 02  |................|
+00000030  1a 27 54 01 c9 7c 86 4b  61 c8 98 1b d3 15 1f 93  |.'T..|.Ka.......|
+00000040  f9 42                                             |.B|
diff --git a/src/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch b/src/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch
index a22ffae..9a34e4a 100644
--- a/src/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch
+++ b/src/crypto/tls/testdata/Client-TLSv12-ALPN-NoMatch
@@ -1,96 +1,91 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 92 01 00 00  8e 03 03 00 00 00 00 00  |................|
+00000000  16 03 01 00 96 01 00 00  92 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 47  |...../.5.......G|
-00000050  33 74 00 00 00 05 00 05  01 00 00 00 00 00 0a 00  |3t..............|
-00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
-00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
-00000080  03 ff 01 00 01 00 00 10  00 09 00 07 06 70 72 6f  |.............pro|
-00000090  74 6f 33 00 12 00 00                              |to3....|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 47 33 74 00 00  00 05 00 05 01 00 00 00  |...G3t..........|
+00000060  00 00 0a 00 08 00 06 00  17 00 18 00 19 00 0b 00  |................|
+00000070  02 01 00 00 0d 00 0e 00  0c 04 01 04 03 05 01 05  |................|
+00000080  03 02 01 02 03 ff 01 00  01 00 00 10 00 09 00 07  |................|
+00000090  06 70 72 6f 74 6f 33 00  12 00 00                 |.proto3....|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 94 d7 79 73 82  |....Y...U....ys.|
-00000010  87 7c 85 6e 8a 1b 7d bf  69 c9 98 0c 44 bd f6 78  |.|.n..}.i...D..x|
-00000020  d2 80 dc d8 7d 80 bb 91  4b d4 ed 20 fe 9f 2f 7b  |....}...K.. ../{|
-00000030  f2 1a 44 36 cd ce af f1  b5 01 8a ac 18 e4 2b 23  |..D6..........+#|
-00000040  a8 ab 1a 32 23 8b 0b e2  81 a8 0a 40 c0 2f 00 00  |...2#...... at ./..|
+00000000  16 03 03 00 59 02 00 00  55 03 03 18 3d 15 59 fb  |....Y...U...=.Y.|
+00000010  0a a4 93 d7 43 50 59 7f  6c f9 64 db b5 47 cc 17  |....CPY.l.d..G..|
+00000020  8c cd 91 b5 04 02 3f c0  5d 60 b7 20 75 ed d2 e9  |......?.]`. u...|
+00000030  b6 72 2d f7 66 34 2e 2f  d2 b9 80 66 eb c3 36 f6  |.r-.f4./...f..6.|
+00000040  b2 61 77 79 a9 c2 db cd  57 5a b2 6b c0 2f 00 00  |.awy....WZ.k./..|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
-00000060  03 02 be 0b 00 02 ba 00  02 b7 00 02 b4 30 82 02  |.............0..|
-00000070  b0 30 82 02 19 a0 03 02  01 02 02 09 00 85 b0 bb  |.0..............|
-00000080  a4 8a 7f b8 ca 30 0d 06  09 2a 86 48 86 f7 0d 01  |.....0...*.H....|
-00000090  01 05 05 00 30 45 31 0b  30 09 06 03 55 04 06 13  |....0E1.0...U...|
-000000a0  02 41 55 31 13 30 11 06  03 55 04 08 13 0a 53 6f  |.AU1.0...U....So|
-000000b0  6d 65 2d 53 74 61 74 65  31 21 30 1f 06 03 55 04  |me-State1!0...U.|
-000000c0  0a 13 18 49 6e 74 65 72  6e 65 74 20 57 69 64 67  |...Internet Widg|
-000000d0  69 74 73 20 50 74 79 20  4c 74 64 30 1e 17 0d 31  |its Pty Ltd0...1|
-000000e0  30 30 34 32 34 30 39 30  39 33 38 5a 17 0d 31 31  |00424090938Z..11|
-000000f0  30 34 32 34 30 39 30 39  33 38 5a 30 45 31 0b 30  |0424090938Z0E1.0|
-00000100  09 06 03 55 04 06 13 02  41 55 31 13 30 11 06 03  |...U....AU1.0...|
-00000110  55 04 08 13 0a 53 6f 6d  65 2d 53 74 61 74 65 31  |U....Some-State1|
-00000120  21 30 1f 06 03 55 04 0a  13 18 49 6e 74 65 72 6e  |!0...U....Intern|
-00000130  65 74 20 57 69 64 67 69  74 73 20 50 74 79 20 4c  |et Widgits Pty L|
-00000140  74 64 30 81 9f 30 0d 06  09 2a 86 48 86 f7 0d 01  |td0..0...*.H....|
-00000150  01 01 05 00 03 81 8d 00  30 81 89 02 81 81 00 bb  |........0.......|
-00000160  79 d6 f5 17 b5 e5 bf 46  10 d0 dc 69 be e6 2b 07  |y......F...i..+.|
-00000170  43 5a d0 03 2d 8a 7a 43  85 b7 14 52 e7 a5 65 4c  |CZ..-.zC...R..eL|
-00000180  2c 78 b8 23 8c b5 b4 82  e5 de 1f 95 3b 7e 62 a5  |,x.#........;~b.|
-00000190  2c a5 33 d6 fe 12 5c 7a  56 fc f5 06 bf fa 58 7b  |,.3...\zV.....X{|
-000001a0  26 3f b5 cd 04 d3 d0 c9  21 96 4a c7 f4 54 9f 5a  |&?......!.J..T.Z|
-000001b0  bf ef 42 71 00 fe 18 99  07 7f 7e 88 7d 7d f1 04  |..Bq......~.}}..|
-000001c0  39 c4 a2 2e db 51 c9 7c  e3 c0 4c 3b 32 66 01 cf  |9....Q.|..L;2f..|
-000001d0  af b1 1d b8 71 9a 1d db  db 89 6b ae da 2d 79 02  |....q.....k..-y.|
-000001e0  03 01 00 01 a3 81 a7 30  81 a4 30 1d 06 03 55 1d  |.......0..0...U.|
-000001f0  0e 04 16 04 14 b1 ad e2  85 5a cf cb 28 db 69 ce  |.........Z..(.i.|
-00000200  23 69 de d3 26 8e 18 88  39 30 75 06 03 55 1d 23  |#i..&...90u..U.#|
-00000210  04 6e 30 6c 80 14 b1 ad  e2 85 5a cf cb 28 db 69  |.n0l......Z..(.i|
-00000220  ce 23 69 de d3 26 8e 18  88 39 a1 49 a4 47 30 45  |.#i..&...9.I.G0E|
-00000230  31 0b 30 09 06 03 55 04  06 13 02 41 55 31 13 30  |1.0...U....AU1.0|
-00000240  11 06 03 55 04 08 13 0a  53 6f 6d 65 2d 53 74 61  |...U....Some-Sta|
-00000250  74 65 31 21 30 1f 06 03  55 04 0a 13 18 49 6e 74  |te1!0...U....Int|
-00000260  65 72 6e 65 74 20 57 69  64 67 69 74 73 20 50 74  |ernet Widgits Pt|
-00000270  79 20 4c 74 64 82 09 00  85 b0 bb a4 8a 7f b8 ca  |y Ltd...........|
-00000280  30 0c 06 03 55 1d 13 04  05 30 03 01 01 ff 30 0d  |0...U....0....0.|
-00000290  06 09 2a 86 48 86 f7 0d  01 01 05 05 00 03 81 81  |..*.H...........|
-000002a0  00 08 6c 45 24 c7 6b b1  59 ab 0c 52 cc f2 b0 14  |..lE$.k.Y..R....|
-000002b0  d7 87 9d 7a 64 75 b5 5a  95 66 e4 c5 2b 8e ae 12  |...zdu.Z.f..+...|
-000002c0  66 1f eb 4f 38 b3 6e 60  d3 92 fd f7 41 08 b5 25  |f..O8.n`....A..%|
-000002d0  13 b1 18 7a 24 fb 30 1d  ba ed 98 b9 17 ec e7 d7  |...z$.0.........|
-000002e0  31 59 db 95 d3 1d 78 ea  50 56 5c d5 82 5a 2d 5a  |1Y....x.PV\..Z-Z|
-000002f0  5f 33 c4 b6 d8 c9 75 90  96 8c 0f 52 98 b5 cd 98  |_3....u....R....|
-00000300  1f 89 20 5f f2 a0 1c a3  1b 96 94 dd a9 fd 57 e9  |.. _..........W.|
-00000310  70 e8 26 6d 71 99 9b 26  6e 38 50 29 6c 90 a7 bd  |p.&mq..&n8P)l...|
-00000320  d9 16 03 03 00 cd 0c 00  00 c9 03 00 17 41 04 7d  |.............A.}|
-00000330  75 a5 53 0b a5 4d a6 81  e0 df c4 11 c9 b5 31 ba  |u.S..M........1.|
-00000340  9f 7b 51 04 57 c6 e0 b9  b0 bc 4f bc 71 74 8a 2e  |.{Q.W.....O.qt..|
-00000350  d1 f6 39 36 94 4e c7 d3  a7 1b 2c b5 55 04 71 01  |..96.N....,.U.q.|
-00000360  9e 2b 42 1e 8b a4 40 b2  13 4f 03 1f 51 9e 5c 04  |.+B... at ..O..Q.\.|
-00000370  01 00 80 68 05 c7 4a ca  df 00 85 2b 53 f7 4f c3  |...h..J....+S.O.|
-00000380  b4 0f e8 f7 b8 30 b7 36  56 65 7b 03 6a 72 f1 aa  |.....0.6Ve{.jr..|
-00000390  54 30 90 9e c7 dc fc 03  96 15 70 67 13 12 a4 f4  |T0........pg....|
-000003a0  42 f0 f9 a1 48 c0 44 44  77 0e ea fd cb b5 6e 19  |B...H.DDw.....n.|
-000003b0  89 94 a7 12 67 87 47 19  c3 00 2d c4 9b d4 dc 66  |....g.G...-....f|
-000003c0  fa ca d7 97 79 9b 28 7f  74 d4 37 c0 06 63 d4 9e  |....y.(.t.7..c..|
-000003d0  a1 53 16 5a 8e d7 a5 cc  90 4d 63 f9 0c 18 85 7f  |.S.Z.....Mc.....|
-000003e0  0e 35 3a 49 73 88 82 51  41 e5 2d 58 aa 38 3e bd  |.5:Is..QA.-X.8>.|
-000003f0  3d d8 da 16 03 03 00 04  0e 00 00 00              |=...........|
+00000060  03 02 71 0b 00 02 6d 00  02 6a 00 02 67 30 82 02  |..q...m..j..g0..|
+00000070  63 30 82 01 cc a0 03 02  01 02 02 09 00 a2 73 00  |c0............s.|
+00000080  0c 81 00 cb f3 30 0d 06  09 2a 86 48 86 f7 0d 01  |.....0...*.H....|
+00000090  01 0b 05 00 30 2b 31 17  30 15 06 03 55 04 0a 13  |....0+1.0...U...|
+000000a0  0e 47 6f 6f 67 6c 65 20  54 45 53 54 49 4e 47 31  |.Google TESTING1|
+000000b0  10 30 0e 06 03 55 04 03  13 07 47 6f 20 52 6f 6f  |.0...U....Go Roo|
+000000c0  74 30 1e 17 0d 31 35 30  31 30 31 30 30 30 30 30  |t0...15010100000|
+000000d0  30 5a 17 0d 32 35 30 31  30 31 30 30 30 30 30 30  |0Z..250101000000|
+000000e0  5a 30 26 31 17 30 15 06  03 55 04 0a 13 0e 47 6f  |Z0&1.0...U....Go|
+000000f0  6f 67 6c 65 20 54 45 53  54 49 4e 47 31 0b 30 09  |ogle TESTING1.0.|
+00000100  06 03 55 04 03 13 02 47  6f 30 81 9f 30 0d 06 09  |..U....Go0..0...|
+00000110  2a 86 48 86 f7 0d 01 01  01 05 00 03 81 8d 00 30  |*.H............0|
+00000120  81 89 02 81 81 00 af 87  88 f6 20 1b 95 65 6c 14  |.......... ..el.|
+00000130  ab 44 05 af 3b 45 14 e3  b7 6d fd 00 63 4d 95 7f  |.D..;E...m..cM..|
+00000140  fe 6a 62 35 86 c0 4a f9  18 7c f6 aa 25 5e 7a 64  |.jb5..J..|..%^zd|
+00000150  31 66 00 ba f4 8e 92 af  c7 6b d8 76 d4 f3 5f 41  |1f.......k.v.._A|
+00000160  cb 6e 56 15 97 1b 97 c1  3c 12 39 21 66 3d 2b 16  |.nV.....<.9!f=+.|
+00000170  d1 bc db 1c c0 a7 da b7  ca ad ba da cb d5 21 50  |..............!P|
+00000180  ec de 8d ab d1 6b 81 4b  89 02 f3 c4 be c1 6c 89  |.....k.K......l.|
+00000190  b1 44 84 bd 21 d1 04 7d  9d 16 4d f9 82 15 f6 ef  |.D..!..}..M.....|
+000001a0  fa d6 09 47 f2 fb 02 03  01 00 01 a3 81 93 30 81  |...G..........0.|
+000001b0  90 30 0e 06 03 55 1d 0f  01 01 ff 04 04 03 02 05  |.0...U..........|
+000001c0  a0 30 1d 06 03 55 1d 25  04 16 30 14 06 08 2b 06  |.0...U.%..0...+.|
+000001d0  01 05 05 07 03 01 06 08  2b 06 01 05 05 07 03 02  |........+.......|
+000001e0  30 0c 06 03 55 1d 13 01  01 ff 04 02 30 00 30 19  |0...U.......0.0.|
+000001f0  06 03 55 1d 0e 04 12 04  10 12 50 8d 89 6f 1b d1  |..U.......P..o..|
+00000200  dc 54 4d 6e cb 69 5e 06  f4 30 1b 06 03 55 1d 23  |.TMn.i^..0...U.#|
+00000210  04 14 30 12 80 10 bf 3d  b6 a9 66 f2 b8 40 cf ea  |..0....=..f.. at ..|
+00000220  b4 03 78 48 1a 41 30 19  06 03 55 1d 11 04 12 30  |..xH.A0...U....0|
+00000230  10 82 0e 65 78 61 6d 70  6c 65 2e 67 6f 6c 61 6e  |...example.golan|
+00000240  67 30 0d 06 09 2a 86 48  86 f7 0d 01 01 0b 05 00  |g0...*.H........|
+00000250  03 81 81 00 92 7c af 91  55 12 18 96 59 31 a6 48  |.....|..U...Y1.H|
+00000260  40 d5 2d d5 ee bb 02 a0  f5 c2 1e 7c 9b b3 30 7d  |@.-........|..0}|
+00000270  3c dc 76 da 4f 3d c0 fa  ae 2d 33 24 6b 03 7b 1b  |<.v.O=...-3$k.{.|
+00000280  67 59 11 21 b5 11 bc 77  b9 d9 e0 6e a8 2d 2e 35  |gY.!...w...n.-.5|
+00000290  fa 64 5f 22 3e 63 10 6b  be ff 14 86 6d 0d f0 15  |.d_">c.k....m...|
+000002a0  31 a8 14 38 1e 3b 84 87  2c cb 98 ed 51 76 b9 b1  |1..8.;..,...Qv..|
+000002b0  4f dd db 9b 84 04 86 40  fa 51 dd ba b4 8d eb e3  |O...... at .Q......|
+000002c0  46 de 46 b9 4f 86 c7 f9  a4 c2 41 34 ac cc f6 ea  |F.F.O.....A4....|
+000002d0  b0 ab 39 18 16 03 03 00  cd 0c 00 00 c9 03 00 17  |..9.............|
+000002e0  41 04 62 52 78 76 89 36  e7 b9 a6 cc df 8e f8 c3  |A.bRxv.6........|
+000002f0  52 54 b6 42 9b 68 65 65  27 91 bf 1b 0f 21 ab a9  |RT.B.hee'....!..|
+00000300  f4 00 62 dd 70 25 b8 ec  d0 3d 9b 0c 53 16 6e eb  |..b.p%...=..S.n.|
+00000310  a8 c3 1a ad a9 de ec 27  64 07 e8 9b b8 bf 5a 6c  |.......'d.....Zl|
+00000320  87 f4 04 01 00 80 05 ec  2b f7 2e a4 5e 79 85 6f  |........+...^y.o|
+00000330  64 7a b5 fb 9a e9 f1 12  ae 28 93 4b 6d 8e a0 2f  |dz.......(.Km../|
+00000340  94 bc 38 26 01 64 ab fb  03 c8 3d 17 bc b4 43 09  |..8&.d....=...C.|
+00000350  19 c8 e9 ac 60 40 67 57  71 e3 72 22 cf b1 a7 38  |....`@gWq.r"...8|
+00000360  ac 86 88 9d 47 6f 70 c9  43 82 75 b6 bf 42 4e 72  |....Gop.C.u..BNr|
+00000370  12 48 d1 2b ce 74 02 5d  30 56 66 6f 71 8f 9b 82  |.H.+.t.]0Vfoq...|
+00000380  70 3b 92 5d fb 37 d3 cf  d3 23 27 d2 d5 8d 72 22  |p;.].7...#'...r"|
+00000390  d4 b4 92 6d 64 06 d9 0b  e0 bb 34 eb bf 42 ec 6a  |...md.....4..B.j|
+000003a0  ea e3 56 68 85 a0 16 03  03 00 04 0e 00 00 00     |..Vh...........|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 46 10 00 00  42 41 04 1e 18 37 ef 0d  |....F...BA...7..|
 00000010  19 51 88 35 75 71 b5 e5  54 5b 12 2e 8f 09 67 fd  |.Q.5uq..T[....g.|
 00000020  a7 24 20 3e b2 56 1c ce  97 28 5e f8 2b 2d 4f 9e  |.$ >.V...(^.+-O.|
 00000030  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
 00000040  a6 b5 68 1a 41 03 56 6b  dc 5a 89 14 03 03 00 01  |..h.A.Vk.Z......|
-00000050  01 16 03 03 00 28 00 00  00 00 00 00 00 00 a8 da  |.....(..........|
-00000060  74 a6 d0 a5 26 86 f3 5f  89 a4 af ac 9c 1a 01 1f  |t...&.._........|
-00000070  89 8a 1c fc cf 68 3e a5  a3 20 1a b3 78 af        |.....h>.. ..x.|
+00000050  01 16 03 03 00 28 00 00  00 00 00 00 00 00 97 34  |.....(.........4|
+00000060  d5 c2 64 97 f6 a9 f5 60  bc 17 f3 d3 02 3f 42 a8  |..d....`.....?B.|
+00000070  2f ba eb c6 50 3c ec 9b  8d 3b 22 ed ec 35        |/...P<...;"..5|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 28 1a f2 a9 e8 71  |..........(....q|
-00000010  b2 a6 ca 36 4a ea 55 f6  20 03 fd f7 90 c3 af 30  |...6J.U. ......0|
-00000020  d3 29 c3 d7 1b d6 4d 3e  61 55 94 0d 4e 3e 83 1a  |.)....M>aU..N>..|
-00000030  97 dd 19                                          |...|
+00000000  14 03 03 00 01 01 16 03  03 00 28 9a e5 f5 51 5c  |..........(...Q\|
+00000010  cb be 5d a1 67 cc 55 aa  ba db e7 0a ab 96 3b 33  |..].g.U.......;3|
+00000020  5f 2c 8c 61 20 f1 0d 6e  ce 90 d8 39 27 d7 fb 68  |_,.a ..n...9'..h|
+00000030  d9 dd da                                          |...|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 94 5b 5e  |..............[^|
-00000010  51 a1 52 ee 19 78 78 ef  12 0d 9c 66 bf e2 48 cb  |Q.R..xx....f..H.|
-00000020  f6 00 1e 15 03 03 00 1a  00 00 00 00 00 00 00 02  |................|
-00000030  cd 5d 31 58 d9 5a 12 65  5b c6 7e 4e e2 04 e7 1d  |.]1X.Z.e[.~N....|
-00000040  b1 4c                                             |.L|
+00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 a8 be 7c  |...............||
+00000010  05 48 ea df 62 4a 7a 45  68 e4 dc e6 42 ff 06 f2  |.H..bJzEh...B...|
+00000020  02 33 1a 15 03 03 00 1a  00 00 00 00 00 00 00 02  |.3..............|
+00000030  66 68 f4 de da 69 b4 f9  80 9c 80 c6 46 e5 2b ae  |fh...i......F.+.|
+00000040  0e d1                                             |..|
diff --git a/src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA
index 1470ba7..4b88acf 100644
--- a/src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA
+++ b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-ECDSA
@@ -1,19 +1,19 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 81 01 00 00  7d 03 03 00 00 00 00 00  |........}.......|
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 36  |...../.5.......6|
-00000050  00 05 00 05 01 00 00 00  00 00 0a 00 08 00 06 00  |................|
-00000060  17 00 18 00 19 00 0b 00  02 01 00 00 0d 00 0e 00  |................|
-00000070  0c 04 01 04 03 05 01 05  03 02 01 02 03 ff 01 00  |................|
-00000080  01 00 00 12 00 00                                 |......|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 a5 28 60 99 bf  |....Y...U...(`..|
-00000010  c7 54 04 87 60 ad c5 32  f6 bf ed 11 47 de 4d ff  |.T..`..2....G.M.|
-00000020  99 e1 8f 88 f6 af 10 6e  29 74 0a 20 1d 39 cb e0  |.......n)t. .9..|
-00000030  a5 11 fe 8e 23 11 83 c7  a6 53 fc 97 03 9d ff 7c  |....#....S.....||
-00000040  cf 51 ba 41 64 61 38 22  5c c6 4a 04 c0 09 00 00  |.Q.Ada8"\.J.....|
+00000000  16 03 03 00 59 02 00 00  55 03 03 f0 5c 85 c8 ff  |....Y...U...\...|
+00000010  c5 57 76 99 3d 75 e6 2e  db 31 26 c0 0c 81 c5 6b  |.Wv.=u...1&....k|
+00000020  30 79 e6 72 86 77 48 01  ec 43 1a 20 f8 fd ad b5  |0y.r.wH..C. ....|
+00000030  a0 7b f3 35 27 df ad 95  f9 56 f9 79 6c a2 6c 23  |.{.5'....V.yl.l#|
+00000040  51 4c ef fc 92 fb fa 59  97 e9 63 27 c0 09 00 00  |QL.....Y..c'....|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
 00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
@@ -48,23 +48,24 @@
 00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
 00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
 00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
-00000270  2a 16 03 03 00 d7 0c 00  00 d3 03 00 17 41 04 c4  |*............A..|
-00000280  0a 40 05 84 eb 90 3c 13  d0 90 af 69 fa 5c 20 75  |. at ....<....i.\ u|
-00000290  e1 9b f2 30 f7 df cc 75  2c 35 7e 38 16 99 7d 57  |...0...u,5~8..}W|
-000002a0  6d d7 f0 93 2d 1d c8 03  89 6e 52 3b 20 e5 8a 5f  |m...-....nR; .._|
-000002b0  6d ca 6e 6a ca 51 f8 a4  dc 1d ec 3e 73 c9 72 04  |m.nj.Q.....>s.r.|
-000002c0  03 00 8a 30 81 87 02 41  37 bf 0d 1d c1 9a 37 39  |...0...A7.....79|
-000002d0  4d 4a f8 17 50 5d 4c 78  d4 25 99 9d 81 48 98 a8  |MJ..P]Lx.%...H..|
-000002e0  ff 2d 3f 98 4b 9f d8 96  2b fa 37 cc e8 66 25 0e  |.-?.K...+.7..f%.|
-000002f0  d3 5e 53 c5 3b ad 17 3f  21 ce d2 45 d8 93 95 6c  |.^S.;..?!..E...l|
-00000300  25 f9 5a 10 9f 37 c8 14  a6 02 42 00 e6 bd 9a 89  |%.Z..7....B.....|
-00000310  8e 73 40 f4 90 e6 d8 e2  98 51 10 23 fb 98 e5 47  |.s at ......Q.#...G|
-00000320  0c 2a 7a 2f 02 66 a8 20  e4 cb 4f ba 14 1d 9e 3a  |.*z/.f. ..O....:|
-00000330  2f 09 47 44 02 e0 9f 30  21 71 f0 99 09 de 23 d2  |/.GD...0!q....#.|
-00000340  f5 f0 b2 93 70 a3 8f 79  b9 4f 88 0b 35 16 03 03  |....p..y.O..5...|
-00000350  00 2e 0d 00 00 26 03 01  02 40 00 1e 06 01 06 02  |.....&... at ......|
-00000360  06 03 05 01 05 02 05 03  04 01 04 02 04 03 03 01  |................|
-00000370  03 02 03 03 02 01 02 02  02 03 00 00 0e 00 00 00  |................|
+00000270  2a 16 03 03 00 d8 0c 00  00 d4 03 00 17 41 04 51  |*............A.Q|
+00000280  1e 2e 40 c5 a1 13 15 f0  bc 8a 04 e1 9a 57 74 10  |.. at ..........Wt.|
+00000290  7e b3 17 bf 0c c9 85 9b  5f bd 6b 39 c7 a6 c0 50  |~......._.k9...P|
+000002a0  0e 5e 9b b1 8c cc 57 39  e8 0f 94 02 be 28 19 16  |.^....W9.....(..|
+000002b0  94 73 2b c1 3c a7 0f c9  e7 b0 89 ac 13 53 f9 04  |.s+.<........S..|
+000002c0  03 00 8b 30 81 88 02 42  01 1b e0 ab 94 02 aa 27  |...0...B.......'|
+000002d0  fa 7b 99 9c 68 36 d8 2d  2e e0 92 84 c7 7b 37 74  |.{..h6.-.....{7t|
+000002e0  6a ad a8 f5 50 3f 74 d5  e8 8e 5a db 31 43 c8 98  |j...P?t...Z.1C..|
+000002f0  d3 ee 61 43 80 9a 72 eb  2d 2b 21 b8 33 aa 61 0a  |..aC..r.-+!.3.a.|
+00000300  cd dc 85 88 29 26 83 ee  3c b2 02 42 00 b6 ea 34  |....)&..<..B...4|
+00000310  30 71 5c 0a 9a 6d a2 25  62 1c 3e 13 90 9c a3 b8  |0q\..m.%b.>.....|
+00000320  0d 97 a8 06 26 9e 31 50  88 9a b9 ff 12 63 a8 14  |....&.1P.....c..|
+00000330  18 f3 c2 b0 af d1 27 25  a9 ec ef 69 85 7a 72 c6  |......'%...i.zr.|
+00000340  b0 88 d2 c1 41 43 f4 69  62 25 13 eb f9 f8 16 03  |....AC.ib%......|
+00000350  03 00 2e 0d 00 00 26 03  01 02 40 00 1e 06 01 06  |......&... at .....|
+00000360  02 06 03 05 01 05 02 05  03 04 01 04 02 04 03 03  |................|
+00000370  01 03 02 03 03 02 01 02  02 02 03 00 00 0e 00 00  |................|
+00000380  00                                                |.|
 >>> Flow 3 (client to server)
 00000000  16 03 03 02 0a 0b 00 02  06 00 02 03 00 02 00 30  |...............0|
 00000010  82 01 fc 30 82 01 5e 02  09 00 9a 30 84 6c 26 35  |...0..^....0.l&5|
@@ -103,32 +104,32 @@
 00000220  51 88 35 75 71 b5 e5 54  5b 12 2e 8f 09 67 fd a7  |Q.5uq..T[....g..|
 00000230  24 20 3e b2 56 1c ce 97  28 5e f8 2b 2d 4f 9e f1  |$ >.V...(^.+-O..|
 00000240  07 9f 6c 4b 5b 83 56 e2  32 42 e9 58 b6 d7 49 a6  |..lK[.V.2B.X..I.|
-00000250  b5 68 1a 41 03 56 6b dc  5a 89 16 03 03 00 92 0f  |.h.A.Vk.Z.......|
-00000260  00 00 8e 05 03 00 8a 30  81 87 02 42 00 cc a4 ad  |.......0...B....|
-00000270  0b ff 09 40 8f 2c a6 37  72 1d f7 d2 19 74 85 ad  |... at .,.7r....t..|
-00000280  ac 33 b0 b8 5b 56 39 cf  b0 ef 46 68 94 39 4c d0  |.3..[V9...Fh.9L.|
-00000290  f4 97 32 10 99 36 c5 95  c8 14 23 37 78 46 5c a9  |..2..6....#7xF\.|
-000002a0  20 95 65 47 ff 54 02 f1  aa 1d d7 bc 39 2d 02 41  | .eG.T......9-.A|
-000002b0  2e f9 d6 8c e8 c5 a9 6f  10 4f d6 5f 4e 88 e9 71  |.......o.O._N..q|
-000002c0  23 5b 6f b8 ab 19 d3 dd  ec f3 32 e3 3b fa 41 a2  |#[o.......2.;.A.|
-000002d0  e8 ae dc 27 8d 4e 79 f4  47 ef c9 8f bf 0b 41 3b  |...'.Ny.G.....A;|
-000002e0  94 16 cb 8f 1e b5 f3 4e  6e 42 46 35 1a 0c ca 79  |.......NnBF5...y|
-000002f0  4b 14 03 03 00 01 01 16  03 03 00 40 00 00 00 00  |K.......... at ....|
-00000300  00 00 00 00 00 00 00 00  00 00 00 00 64 1c d9 9f  |............d...|
-00000310  34 ec c2 74 76 7a 9f cf  95 19 be 8d 6a 2f 25 96  |4..tvz......j/%.|
-00000320  df de 18 ca 0e c9 d4 2f  e4 b0 34 10 5b 72 7a 18  |......./..4.[rz.|
-00000330  5c 64 d7 fc 2e 1b 28 10  ae a6 31 e9              |\d....(...1.|
+00000250  b5 68 1a 41 03 56 6b dc  5a 89 16 03 03 00 93 0f  |.h.A.Vk.Z.......|
+00000260  00 00 8f 05 03 00 8b 30  81 88 02 42 00 8a 82 c2  |.......0...B....|
+00000270  c0 30 8c a1 12 c4 4a ed  d1 00 3f 2d ee bd 8e 9c  |.0....J...?-....|
+00000280  a5 a0 d9 6f 44 27 49 60  e9 75 01 ee b4 0d 87 25  |...oD'I`.u.....%|
+00000290  2a 8d 67 f1 e3 d9 49 6f  a0 34 90 76 93 52 f9 17  |*.g...Io.4.v.R..|
+000002a0  fb 1b cc d0 5a f4 50 37  9c 4c 44 b6 61 5f 02 42  |....Z.P7.LD.a_.B|
+000002b0  01 ad 85 38 e9 3a 69 35  ea 74 76 2c 09 6b ab d4  |...8.:i5.tv,.k..|
+000002c0  e0 dc d1 d5 03 41 22 8e  8b 53 98 b7 f1 b6 e9 29  |.....A"..S.....)|
+000002d0  d2 57 34 dc e0 b6 71 77  79 bd 57 61 7c 30 77 00  |.W4...qwy.Wa|0w.|
+000002e0  7a 42 2d 1f ed e8 14 da  16 33 c6 31 e4 3d 53 3a  |zB-......3.1.=S:|
+000002f0  9a 37 14 03 03 00 01 01  16 03 03 00 40 00 00 00  |.7.......... at ...|
+00000300  00 00 00 00 00 00 00 00  00 00 00 00 00 d4 fe c1  |................|
+00000310  a6 fb 21 78 21 80 af 0d  da a1 80 68 e2 9c ec 0b  |..!x!......h....|
+00000320  57 8c 2a 7e f1 11 3b 52  ea 17 00 d1 d4 14 78 c5  |W.*~..;R......x.|
+00000330  81 39 12 ad 30 98 93 1b  29 77 45 7d 00           |.9..0...)wE}.|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 40 27 6f 24 a3 0c  |..........@'o$..|
-00000010  6d d7 68 4a fb 43 b0 97  02 6c 22 7e 2f a1 f1 7a  |m.hJ.C...l"~/..z|
-00000020  37 bf 38 82 dc a0 83 24  01 4b c0 4f 15 e1 7c 4c  |7.8....$.K.O..|L|
-00000030  d4 cd b8 e2 71 af f5 20  7d f9 4a 48 4b f0 a1 f3  |....q.. }.JHK...|
-00000040  7b 02 29 18 c0 87 a5 dd  c4 73 8e                 |{.)......s.|
+00000000  14 03 03 00 01 01 16 03  03 00 40 f7 0a 50 d0 87  |.......... at ..P..|
+00000010  fb f9 be b0 6b 8d 9b a5  8b d2 56 27 67 7d 3c 51  |....k.....V'g}<Q|
+00000020  af 53 8c 7d 61 9f 12 a5  54 5d ec 56 36 31 01 73  |.S.}a...T].V61.s|
+00000030  37 cb 5f ff 36 3c 1c 4a  e3 db ec 99 bc 86 15 e4  |7._.6<.J........|
+00000040  cd 5d 87 bd d7 80 c7 b1  fe 42 9f                 |.].......B.|
 >>> Flow 5 (client to server)
 00000000  17 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
-00000010  00 00 00 00 00 bf 7a e1  23 0d d0 13 6e 96 81 6d  |......z.#...n..m|
-00000020  32 56 0f 75 7e 01 88 5f  6d e6 d6 ca ec 3c 17 e9  |2V.u~.._m....<..|
-00000030  44 a9 c0 1c a4 15 03 03  00 30 00 00 00 00 00 00  |D........0......|
-00000040  00 00 00 00 00 00 00 00  00 00 76 be 7a 77 29 01  |..........v.zw).|
-00000050  8e 13 02 66 81 43 a0 55  03 35 22 09 de ea 52 bb  |...f.C.U.5"...R.|
-00000060  51 cc c1 09 0e 9b 4d bd  94 85                    |Q.....M...|
+00000010  00 00 00 00 00 ef 81 cf  63 f1 b5 6b b2 30 6f 00  |........c..k.0o.|
+00000020  0e c0 0c 5d d4 85 76 d2  30 db 6b 14 06 e4 75 0b  |...]..v.0.k...u.|
+00000030  cf fc 72 aa 64 15 03 03  00 30 00 00 00 00 00 00  |..r.d....0......|
+00000040  00 00 00 00 00 00 00 00  00 00 ef 28 8a e7 15 51  |...........(...Q|
+00000050  0d 0d 27 4f 36 35 f6 43  28 d2 16 dc a3 35 33 3e  |..'O65.C(....53>|
+00000060  be 80 db 31 a9 89 3d 17  c2 58                    |...1..=..X|
diff --git a/src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA
index 95c5782..53f2f86 100644
--- a/src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA
+++ b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-ECDSA-RSA
@@ -1,67 +1,62 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 81 01 00 00  7d 03 03 00 00 00 00 00  |........}.......|
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 36  |...../.5.......6|
-00000050  00 05 00 05 01 00 00 00  00 00 0a 00 08 00 06 00  |................|
-00000060  17 00 18 00 19 00 0b 00  02 01 00 00 0d 00 0e 00  |................|
-00000070  0c 04 01 04 03 05 01 05  03 02 01 02 03 ff 01 00  |................|
-00000080  01 00 00 12 00 00                                 |......|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 51 02 00 00  4d 03 03 79 e8 35 e3 d2  |....Q...M..y.5..|
-00000010  c0 5e 39 d1 46 da 9c 94  56 20 e2 06 d6 9b f6 dd  |.^9.F...V ......|
-00000020  4f 7a c1 e8 34 a1 9f 8b  c2 e1 fb 20 66 9c 5a 9a  |Oz..4...... f.Z.|
-00000030  3d 22 ab 8e d8 81 03 94  68 a0 6c 72 d8 23 0b 4b  |="......h.lr.#.K|
-00000040  fe 9d c7 49 a7 7c bd fa  b5 7a 5e 5b 00 05 00 00  |...I.|...z^[....|
-00000050  05 ff 01 00 01 00 16 03  03 02 be 0b 00 02 ba 00  |................|
-00000060  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
-00000070  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
-00000080  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
-00000090  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
-000000a0  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
-000000b0  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
-000000c0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
-000000d0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
-000000e0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
-000000f0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
-00000100  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
-00000110  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
-00000120  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
-00000130  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
-00000140  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
-00000150  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
-00000160  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
-00000170  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
-00000180  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
-00000190  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
-000001a0  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
-000001b0  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
-000001c0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
-000001d0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
-000001e0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
-000001f0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
-00000200  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
-00000210  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
-00000220  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
-00000230  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
-00000240  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
-00000250  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
-00000260  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
-00000270  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
-00000280  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
-00000290  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
-000002a0  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
-000002b0  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
-000002c0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
-000002d0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
-000002e0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
-000002f0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
-00000300  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
-00000310  6e 38 50 29 6c 90 a7 bd  d9 16 03 03 00 2e 0d 00  |n8P)l...........|
-00000320  00 26 03 01 02 40 00 1e  06 01 06 02 06 03 05 01  |.&... at ..........|
-00000330  05 02 05 03 04 01 04 02  04 03 03 01 03 02 03 03  |................|
-00000340  02 01 02 02 02 03 00 00  0e 00 00 00              |............|
+00000000  16 03 03 00 51 02 00 00  4d 03 03 e8 b5 19 bd df  |....Q...M.......|
+00000010  e5 18 78 4b 01 f1 3f 7f  ab 91 05 78 98 77 50 bf  |..xK..?....x.wP.|
+00000020  60 f5 a4 76 7b 3c 40 9f  54 56 68 20 a1 99 57 a7  |`..v{<@.TVh ..W.|
+00000030  a8 46 ca 26 22 d8 bb 8d  93 12 48 ff be 8e d3 d4  |.F.&".....H.....|
+00000040  e0 fd cd ce f5 d9 a9 2e  fe d4 cd 85 00 05 00 00  |................|
+00000050  05 ff 01 00 01 00 16 03  03 02 71 0b 00 02 6d 00  |..........q...m.|
+00000060  02 6a 00 02 67 30 82 02  63 30 82 01 cc a0 03 02  |.j..g0..c0......|
+00000070  01 02 02 09 00 a2 73 00  0c 81 00 cb f3 30 0d 06  |......s......0..|
+00000080  09 2a 86 48 86 f7 0d 01  01 0b 05 00 30 2b 31 17  |.*.H........0+1.|
+00000090  30 15 06 03 55 04 0a 13  0e 47 6f 6f 67 6c 65 20  |0...U....Google |
+000000a0  54 45 53 54 49 4e 47 31  10 30 0e 06 03 55 04 03  |TESTING1.0...U..|
+000000b0  13 07 47 6f 20 52 6f 6f  74 30 1e 17 0d 31 35 30  |..Go Root0...150|
+000000c0  31 30 31 30 30 30 30 30  30 5a 17 0d 32 35 30 31  |101000000Z..2501|
+000000d0  30 31 30 30 30 30 30 30  5a 30 26 31 17 30 15 06  |01000000Z0&1.0..|
+000000e0  03 55 04 0a 13 0e 47 6f  6f 67 6c 65 20 54 45 53  |.U....Google TES|
+000000f0  54 49 4e 47 31 0b 30 09  06 03 55 04 03 13 02 47  |TING1.0...U....G|
+00000100  6f 30 81 9f 30 0d 06 09  2a 86 48 86 f7 0d 01 01  |o0..0...*.H.....|
+00000110  01 05 00 03 81 8d 00 30  81 89 02 81 81 00 af 87  |.......0........|
+00000120  88 f6 20 1b 95 65 6c 14  ab 44 05 af 3b 45 14 e3  |.. ..el..D..;E..|
+00000130  b7 6d fd 00 63 4d 95 7f  fe 6a 62 35 86 c0 4a f9  |.m..cM...jb5..J.|
+00000140  18 7c f6 aa 25 5e 7a 64  31 66 00 ba f4 8e 92 af  |.|..%^zd1f......|
+00000150  c7 6b d8 76 d4 f3 5f 41  cb 6e 56 15 97 1b 97 c1  |.k.v.._A.nV.....|
+00000160  3c 12 39 21 66 3d 2b 16  d1 bc db 1c c0 a7 da b7  |<.9!f=+.........|
+00000170  ca ad ba da cb d5 21 50  ec de 8d ab d1 6b 81 4b  |......!P.....k.K|
+00000180  89 02 f3 c4 be c1 6c 89  b1 44 84 bd 21 d1 04 7d  |......l..D..!..}|
+00000190  9d 16 4d f9 82 15 f6 ef  fa d6 09 47 f2 fb 02 03  |..M........G....|
+000001a0  01 00 01 a3 81 93 30 81  90 30 0e 06 03 55 1d 0f  |......0..0...U..|
+000001b0  01 01 ff 04 04 03 02 05  a0 30 1d 06 03 55 1d 25  |.........0...U.%|
+000001c0  04 16 30 14 06 08 2b 06  01 05 05 07 03 01 06 08  |..0...+.........|
+000001d0  2b 06 01 05 05 07 03 02  30 0c 06 03 55 1d 13 01  |+.......0...U...|
+000001e0  01 ff 04 02 30 00 30 19  06 03 55 1d 0e 04 12 04  |....0.0...U.....|
+000001f0  10 12 50 8d 89 6f 1b d1  dc 54 4d 6e cb 69 5e 06  |..P..o...TMn.i^.|
+00000200  f4 30 1b 06 03 55 1d 23  04 14 30 12 80 10 bf 3d  |.0...U.#..0....=|
+00000210  b6 a9 66 f2 b8 40 cf ea  b4 03 78 48 1a 41 30 19  |..f.. at ....xH.A0.|
+00000220  06 03 55 1d 11 04 12 30  10 82 0e 65 78 61 6d 70  |..U....0...examp|
+00000230  6c 65 2e 67 6f 6c 61 6e  67 30 0d 06 09 2a 86 48  |le.golang0...*.H|
+00000240  86 f7 0d 01 01 0b 05 00  03 81 81 00 92 7c af 91  |.............|..|
+00000250  55 12 18 96 59 31 a6 48  40 d5 2d d5 ee bb 02 a0  |U...Y1.H at .-.....|
+00000260  f5 c2 1e 7c 9b b3 30 7d  3c dc 76 da 4f 3d c0 fa  |...|..0}<.v.O=..|
+00000270  ae 2d 33 24 6b 03 7b 1b  67 59 11 21 b5 11 bc 77  |.-3$k.{.gY.!...w|
+00000280  b9 d9 e0 6e a8 2d 2e 35  fa 64 5f 22 3e 63 10 6b  |...n.-.5.d_">c.k|
+00000290  be ff 14 86 6d 0d f0 15  31 a8 14 38 1e 3b 84 87  |....m...1..8.;..|
+000002a0  2c cb 98 ed 51 76 b9 b1  4f dd db 9b 84 04 86 40  |,...Qv..O......@|
+000002b0  fa 51 dd ba b4 8d eb e3  46 de 46 b9 4f 86 c7 f9  |.Q......F.F.O...|
+000002c0  a4 c2 41 34 ac cc f6 ea  b0 ab 39 18 16 03 03 00  |..A4......9.....|
+000002d0  2e 0d 00 00 26 03 01 02  40 00 1e 06 01 06 02 06  |....&... at .......|
+000002e0  03 05 01 05 02 05 03 04  01 04 02 04 03 03 01 03  |................|
+000002f0  02 03 03 02 01 02 02 02  03 00 00 0e 00 00 00     |...............|
 >>> Flow 3 (client to server)
 00000000  16 03 03 02 0a 0b 00 02  06 00 02 03 00 02 00 30  |...............0|
 00000010  82 01 fc 30 82 01 5e 02  09 00 9a 30 84 6c 26 35  |...0..^....0.l&5|
@@ -96,33 +91,33 @@
 000001e0  be e8 91 b3 da 1a f5 5d  a3 23 f5 26 8b 45 70 8d  |.......].#.&.Ep.|
 000001f0  65 62 9b 7e 01 99 3d 18  f6 10 9a 38 61 9b 2e 57  |eb.~..=....8a..W|
 00000200  e4 fa cc b1 8a ce e2 23  a0 87 f0 e1 67 51 eb 16  |.......#....gQ..|
-00000210  03 03 00 86 10 00 00 82  00 80 6d 51 f3 7f f9 3e  |..........mQ...>|
-00000220  fb 75 82 41 36 83 e8 6a  ee 2a 2e 25 90 67 4c 8e  |.u.A6..j.*.%.gL.|
-00000230  62 2f 30 81 17 e0 85 09  0c 2b b7 23 d7 b0 e2 1d  |b/0......+.#....|
-00000240  f7 3b d7 f5 a1 27 b6 ee  24 b6 1b cc 5b ea 66 0d  |.;...'..$...[.f.|
-00000250  6a f4 e5 85 f9 da 43 b4  0e 86 85 e1 f5 aa be c8  |j.....C.........|
-00000260  ce 39 4c 9c 86 00 08 c2  4b e2 c6 ec 2f f7 ce e6  |.9L.....K.../...|
-00000270  bd 77 82 6f 23 b6 e0 bd  a2 92 b7 3a ac e8 56 f1  |.w.o#......:..V.|
-00000280  af 54 5e 46 87 e9 3b 33  e7 b8 28 b7 d6 c8 90 35  |.T^F..;3..(....5|
-00000290  d4 1c 43 d1 30 6f 55 4e  0a 70 16 03 03 00 92 0f  |..C.0oUN.p......|
-000002a0  00 00 8e 05 03 00 8a 30  81 87 02 41 19 c7 50 06  |.......0...A..P.|
-000002b0  42 82 f9 e5 ec 0b f7 65  7e b1 19 53 5f 23 ab 19  |B......e~..S_#..|
-000002c0  54 08 ec d2 a7 22 dd 83  7c 97 76 59 a5 6b f4 1d  |T...."..|.vY.k..|
-000002d0  92 86 34 2d ce 71 bb 01  d2 8a 67 0e a8 fb 51 e4  |..4-.q....g...Q.|
-000002e0  69 9c 27 23 74 b9 fd 6f  b6 5e 48 a0 cc 02 42 01  |i.'#t..o.^H...B.|
-000002f0  50 97 b7 95 14 f4 a6 f2  95 63 17 38 59 a1 51 95  |P........c.8Y.Q.|
-00000300  1e bc 99 fb fd 82 8b ab  cb 4d 8e 17 a9 f8 e9 c2  |.........M......|
-00000310  9b 93 15 02 50 e6 c2 05  54 e7 8a ec 6f 93 1f 79  |....P...T...o..y|
-00000320  8d 67 e7 2d d6 65 ab 97  fd be 20 97 bd 6b c4 fc  |.g.-.e.... ..k..|
-00000330  02 14 03 03 00 01 01 16  03 03 00 24 24 df 52 6e  |...........$$.Rn|
-00000340  c1 35 48 fe 60 77 28 69  36 fe 96 a1 72 db a2 f5  |.5H.`w(i6...r...|
-00000350  d0 b7 c3 d9 67 e5 ee f2  d9 18 bf f0 35 80 06 c2  |....g.......5...|
+00000210  03 03 00 86 10 00 00 82  00 80 73 bd 73 65 92 86  |..........s.se..|
+00000220  23 41 14 79 7f d5 c1 10  ce 94 4d ad 9c c3 a9 87  |#A.y......M.....|
+00000230  b5 32 52 f8 6b 11 93 2d  9b 98 0b 8b 1d c0 f6 53  |.2R.k..-.......S|
+00000240  17 6d c7 9c 2e ae c9 6f  cc 99 23 38 37 1a 10 fe  |.m.....o..#87...|
+00000250  05 0b b5 55 0a 14 e9 60  7d 70 26 98 e2 54 d9 65  |...U...`}p&..T.e|
+00000260  cf 2e f4 53 5f 1d aa 3a  f6 33 7b eb 4c 0e b3 ff  |...S_..:.3{.L...|
+00000270  5a db 36 2a 47 f3 df f9  fc f5 31 78 83 aa 6b 52  |Z.6*G.....1x..kR|
+00000280  b7 ba 1a 96 bc fa c1 a1  a9 bb 2b f5 38 89 00 4d  |..........+.8..M|
+00000290  e5 78 13 4e a4 38 46 42  dc 16 16 03 03 00 92 0f  |.x.N.8FB........|
+000002a0  00 00 8e 05 03 00 8a 30  81 87 02 42 01 4c f6 31  |.......0...B.L.1|
+000002b0  4f ec 64 bb ce d0 96 4d  66 f3 8d 64 78 c9 2d 47  |O.d....Mf..dx.-G|
+000002c0  39 02 88 31 49 84 7f cc  a8 af c1 17 35 fb 46 b1  |9..1I.......5.F.|
+000002d0  dc 07 58 71 13 6b 8e 71  2b 94 fd 41 7c 26 45 39  |..Xq.k.q+..A|&E9|
+000002e0  28 b1 aa f7 5b 89 04 de  84 d1 b5 d9 9f f3 02 41  |(...[..........A|
+000002f0  4e f6 2a ed 39 ee 63 68  da f5 ae 1b 4d f5 01 0f  |N.*.9.ch....M...|
+00000300  bc f7 05 d2 96 42 67 e3  8f ff 27 d5 bf c4 53 bf  |.....Bg...'...S.|
+00000310  8a d7 46 58 05 54 94 d8  73 a9 d9 38 40 5f cb 8c  |..FX.T..s..8 at _..|
+00000320  c7 d1 94 56 2a e1 61 32  29 f7 c9 c1 e8 95 30 e3  |...V*.a2).....0.|
+00000330  33 14 03 03 00 01 01 16  03 03 00 24 b1 86 d2 50  |3..........$...P|
+00000340  fc ea 68 b1 d9 3d b7 2c  fd 2c 87 f0 d4 44 2b 22  |..h..=.,.,...D+"|
+00000350  b8 47 74 77 46 14 6d 18  b3 08 9c 3a d4 a1 ba cb  |.GtwF.m....:....|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 24 40 5b dc 01 59  |..........$@[..Y|
-00000010  33 6e 61 5a 6d fc c8 a5  f5 00 9b 55 77 c5 e6 f2  |3naZm......Uw...|
-00000020  c6 5c b6 2f 94 3c 72 5b  b5 0c 3e 78 88 e6 44     |.\./.<r[..>x..D|
+00000000  14 03 03 00 01 01 16 03  03 00 24 70 c7 ee d4 d3  |..........$p....|
+00000010  d3 ad dc 5a d1 a3 01 89  4d ae 0f b9 7b 97 91 4a  |...Z....M...{..J|
+00000020  c0 5b e2 94 ef 5f 2f e0  90 1a 18 8a e8 50 9d     |.[..._/......P.|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 1a cd 2f 11  b1 3a e4 1c 31 95 9b c4  |....../..:..1...|
-00000010  37 20 9f 03 d3 45 a4 15  e1 09 1e 0c f6 5d d3 15  |7 ...E.......]..|
-00000020  03 03 00 16 d7 f6 a1 d0  ad 41 69 73 c0 40 22 f2  |.........Ais.@".|
-00000030  5f e8 c3 50 f9 35 fc 59  e0 3a                    |_..P.5.Y.:|
+00000000  17 03 03 00 1a e8 e8 00  30 71 09 61 65 55 90 c8  |........0q.aeU..|
+00000010  d6 fd 8d 5d a9 fb e6 2b  d4 45 a9 8c ea 2f 0b 15  |...]...+.E.../..|
+00000020  03 03 00 16 f2 d3 36 ce  26 42 59 1b d7 15 c5 c4  |......6.&BY.....|
+00000030  8b 0b 06 0a d0 fd 78 62  3d 39                    |......xb=9|
diff --git a/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384 b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384
index 52e3bef..9ba51f5 100644
--- a/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384
+++ b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-AES256-GCM-SHA384
@@ -1,81 +1,76 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 81 01 00 00  7d 03 03 00 00 00 00 00  |........}.......|
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 36  |...../.5.......6|
-00000050  00 05 00 05 01 00 00 00  00 00 0a 00 08 00 06 00  |................|
-00000060  17 00 18 00 19 00 0b 00  02 01 00 00 0d 00 0e 00  |................|
-00000070  0c 04 01 04 03 05 01 05  03 02 01 02 03 ff 01 00  |................|
-00000080  01 00 00 12 00 00                                 |......|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 74 fe 19 af 4b  |....Y...U..t...K|
-00000010  f3 d8 92 62 5a df 90 2c  cc 09 fd 79 45 26 cd 52  |...bZ..,...yE&.R|
-00000020  9a e6 da 16 99 fe 1d 91  79 a7 a0 20 b3 13 e9 03  |........y.. ....|
-00000030  52 23 5f f0 55 59 f1 9e  00 a7 77 97 90 ed 2b fb  |R#_.UY....w...+.|
-00000040  9c ab fe b1 db ea 16 95  95 68 b0 e9 c0 30 00 00  |.........h...0..|
+00000000  16 03 03 00 59 02 00 00  55 03 03 f5 6d a6 9a 3d  |....Y...U...m..=|
+00000010  b4 32 c7 59 b9 f7 09 bb  56 7e 06 26 02 ac eb dd  |.2.Y....V~.&....|
+00000020  78 91 e4 cd f9 f4 e7 98  7f 13 f0 20 6d d5 42 4a  |x.......... m.BJ|
+00000030  85 ac 86 9a a6 78 6d 5c  d7 ef 9d 16 dc ff 5a 41  |.....xm\......ZA|
+00000040  91 5a 54 ff ba f6 90 f4  2a 4f fd 37 c0 30 00 00  |.ZT.....*O.7.0..|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
-00000060  03 02 be 0b 00 02 ba 00  02 b7 00 02 b4 30 82 02  |.............0..|
-00000070  b0 30 82 02 19 a0 03 02  01 02 02 09 00 85 b0 bb  |.0..............|
-00000080  a4 8a 7f b8 ca 30 0d 06  09 2a 86 48 86 f7 0d 01  |.....0...*.H....|
-00000090  01 05 05 00 30 45 31 0b  30 09 06 03 55 04 06 13  |....0E1.0...U...|
-000000a0  02 41 55 31 13 30 11 06  03 55 04 08 13 0a 53 6f  |.AU1.0...U....So|
-000000b0  6d 65 2d 53 74 61 74 65  31 21 30 1f 06 03 55 04  |me-State1!0...U.|
-000000c0  0a 13 18 49 6e 74 65 72  6e 65 74 20 57 69 64 67  |...Internet Widg|
-000000d0  69 74 73 20 50 74 79 20  4c 74 64 30 1e 17 0d 31  |its Pty Ltd0...1|
-000000e0  30 30 34 32 34 30 39 30  39 33 38 5a 17 0d 31 31  |00424090938Z..11|
-000000f0  30 34 32 34 30 39 30 39  33 38 5a 30 45 31 0b 30  |0424090938Z0E1.0|
-00000100  09 06 03 55 04 06 13 02  41 55 31 13 30 11 06 03  |...U....AU1.0...|
-00000110  55 04 08 13 0a 53 6f 6d  65 2d 53 74 61 74 65 31  |U....Some-State1|
-00000120  21 30 1f 06 03 55 04 0a  13 18 49 6e 74 65 72 6e  |!0...U....Intern|
-00000130  65 74 20 57 69 64 67 69  74 73 20 50 74 79 20 4c  |et Widgits Pty L|
-00000140  74 64 30 81 9f 30 0d 06  09 2a 86 48 86 f7 0d 01  |td0..0...*.H....|
-00000150  01 01 05 00 03 81 8d 00  30 81 89 02 81 81 00 bb  |........0.......|
-00000160  79 d6 f5 17 b5 e5 bf 46  10 d0 dc 69 be e6 2b 07  |y......F...i..+.|
-00000170  43 5a d0 03 2d 8a 7a 43  85 b7 14 52 e7 a5 65 4c  |CZ..-.zC...R..eL|
-00000180  2c 78 b8 23 8c b5 b4 82  e5 de 1f 95 3b 7e 62 a5  |,x.#........;~b.|
-00000190  2c a5 33 d6 fe 12 5c 7a  56 fc f5 06 bf fa 58 7b  |,.3...\zV.....X{|
-000001a0  26 3f b5 cd 04 d3 d0 c9  21 96 4a c7 f4 54 9f 5a  |&?......!.J..T.Z|
-000001b0  bf ef 42 71 00 fe 18 99  07 7f 7e 88 7d 7d f1 04  |..Bq......~.}}..|
-000001c0  39 c4 a2 2e db 51 c9 7c  e3 c0 4c 3b 32 66 01 cf  |9....Q.|..L;2f..|
-000001d0  af b1 1d b8 71 9a 1d db  db 89 6b ae da 2d 79 02  |....q.....k..-y.|
-000001e0  03 01 00 01 a3 81 a7 30  81 a4 30 1d 06 03 55 1d  |.......0..0...U.|
-000001f0  0e 04 16 04 14 b1 ad e2  85 5a cf cb 28 db 69 ce  |.........Z..(.i.|
-00000200  23 69 de d3 26 8e 18 88  39 30 75 06 03 55 1d 23  |#i..&...90u..U.#|
-00000210  04 6e 30 6c 80 14 b1 ad  e2 85 5a cf cb 28 db 69  |.n0l......Z..(.i|
-00000220  ce 23 69 de d3 26 8e 18  88 39 a1 49 a4 47 30 45  |.#i..&...9.I.G0E|
-00000230  31 0b 30 09 06 03 55 04  06 13 02 41 55 31 13 30  |1.0...U....AU1.0|
-00000240  11 06 03 55 04 08 13 0a  53 6f 6d 65 2d 53 74 61  |...U....Some-Sta|
-00000250  74 65 31 21 30 1f 06 03  55 04 0a 13 18 49 6e 74  |te1!0...U....Int|
-00000260  65 72 6e 65 74 20 57 69  64 67 69 74 73 20 50 74  |ernet Widgits Pt|
-00000270  79 20 4c 74 64 82 09 00  85 b0 bb a4 8a 7f b8 ca  |y Ltd...........|
-00000280  30 0c 06 03 55 1d 13 04  05 30 03 01 01 ff 30 0d  |0...U....0....0.|
-00000290  06 09 2a 86 48 86 f7 0d  01 01 05 05 00 03 81 81  |..*.H...........|
-000002a0  00 08 6c 45 24 c7 6b b1  59 ab 0c 52 cc f2 b0 14  |..lE$.k.Y..R....|
-000002b0  d7 87 9d 7a 64 75 b5 5a  95 66 e4 c5 2b 8e ae 12  |...zdu.Z.f..+...|
-000002c0  66 1f eb 4f 38 b3 6e 60  d3 92 fd f7 41 08 b5 25  |f..O8.n`....A..%|
-000002d0  13 b1 18 7a 24 fb 30 1d  ba ed 98 b9 17 ec e7 d7  |...z$.0.........|
-000002e0  31 59 db 95 d3 1d 78 ea  50 56 5c d5 82 5a 2d 5a  |1Y....x.PV\..Z-Z|
-000002f0  5f 33 c4 b6 d8 c9 75 90  96 8c 0f 52 98 b5 cd 98  |_3....u....R....|
-00000300  1f 89 20 5f f2 a0 1c a3  1b 96 94 dd a9 fd 57 e9  |.. _..........W.|
-00000310  70 e8 26 6d 71 99 9b 26  6e 38 50 29 6c 90 a7 bd  |p.&mq..&n8P)l...|
-00000320  d9 16 03 03 00 cd 0c 00  00 c9 03 00 17 41 04 22  |.............A."|
-00000330  84 e9 5e 6e 35 92 a3 83  73 0a d6 0d 1a c1 4d ab  |..^n5...s.....M.|
-00000340  1f ab c2 dc 3f 53 a5 7d  38 c0 92 a4 82 e1 3c c5  |....?S.}8.....<.|
-00000350  24 60 20 a5 3b c5 65 ba  9c f1 b9 a5 b9 c2 70 73  |$` .;.e.......ps|
-00000360  19 74 a6 d1 0f 75 b4 75  e0 e8 60 20 e9 23 fe 04  |.t...u.u..` .#..|
-00000370  01 00 80 92 e0 56 3f 48  0d 10 23 48 b5 95 b6 91  |.....V?H..#H....|
-00000380  3e 8a 2e c7 02 e2 85 0e  59 c8 03 24 d9 1a 1a 25  |>.......Y..$...%|
-00000390  8e 12 bb 0b 83 ac 51 36  81 3f bc 0e be b9 3b 1d  |......Q6.?....;.|
-000003a0  67 56 21 4d 24 36 84 05  61 e7 70 60 d5 8e ae 97  |gV!M$6..a.p`....|
-000003b0  b8 3a d3 b1 94 72 52 cd  b0 0d dd 46 b1 15 3b 58  |.:...rR....F..;X|
-000003c0  c1 a4 63 2c 4c 31 f9 c7  4f 27 c1 0f f0 24 36 72  |..c,L1..O'...$6r|
-000003d0  e0 f8 51 12 86 c2 13 ed  6b 84 a8 15 c3 d0 39 55  |..Q.....k.....9U|
-000003e0  a4 60 50 88 c9 1e 60 60  aa 8d a5 31 3e 35 c3 f8  |.`P...``...1>5..|
-000003f0  2c 90 1c 16 03 03 00 2e  0d 00 00 26 03 01 02 40  |,..........&...@|
-00000400  00 1e 06 01 06 02 06 03  05 01 05 02 05 03 04 01  |................|
-00000410  04 02 04 03 03 01 03 02  03 03 02 01 02 02 02 03  |................|
-00000420  00 00 0e 00 00 00                                 |......|
+00000060  03 02 71 0b 00 02 6d 00  02 6a 00 02 67 30 82 02  |..q...m..j..g0..|
+00000070  63 30 82 01 cc a0 03 02  01 02 02 09 00 a2 73 00  |c0............s.|
+00000080  0c 81 00 cb f3 30 0d 06  09 2a 86 48 86 f7 0d 01  |.....0...*.H....|
+00000090  01 0b 05 00 30 2b 31 17  30 15 06 03 55 04 0a 13  |....0+1.0...U...|
+000000a0  0e 47 6f 6f 67 6c 65 20  54 45 53 54 49 4e 47 31  |.Google TESTING1|
+000000b0  10 30 0e 06 03 55 04 03  13 07 47 6f 20 52 6f 6f  |.0...U....Go Roo|
+000000c0  74 30 1e 17 0d 31 35 30  31 30 31 30 30 30 30 30  |t0...15010100000|
+000000d0  30 5a 17 0d 32 35 30 31  30 31 30 30 30 30 30 30  |0Z..250101000000|
+000000e0  5a 30 26 31 17 30 15 06  03 55 04 0a 13 0e 47 6f  |Z0&1.0...U....Go|
+000000f0  6f 67 6c 65 20 54 45 53  54 49 4e 47 31 0b 30 09  |ogle TESTING1.0.|
+00000100  06 03 55 04 03 13 02 47  6f 30 81 9f 30 0d 06 09  |..U....Go0..0...|
+00000110  2a 86 48 86 f7 0d 01 01  01 05 00 03 81 8d 00 30  |*.H............0|
+00000120  81 89 02 81 81 00 af 87  88 f6 20 1b 95 65 6c 14  |.......... ..el.|
+00000130  ab 44 05 af 3b 45 14 e3  b7 6d fd 00 63 4d 95 7f  |.D..;E...m..cM..|
+00000140  fe 6a 62 35 86 c0 4a f9  18 7c f6 aa 25 5e 7a 64  |.jb5..J..|..%^zd|
+00000150  31 66 00 ba f4 8e 92 af  c7 6b d8 76 d4 f3 5f 41  |1f.......k.v.._A|
+00000160  cb 6e 56 15 97 1b 97 c1  3c 12 39 21 66 3d 2b 16  |.nV.....<.9!f=+.|
+00000170  d1 bc db 1c c0 a7 da b7  ca ad ba da cb d5 21 50  |..............!P|
+00000180  ec de 8d ab d1 6b 81 4b  89 02 f3 c4 be c1 6c 89  |.....k.K......l.|
+00000190  b1 44 84 bd 21 d1 04 7d  9d 16 4d f9 82 15 f6 ef  |.D..!..}..M.....|
+000001a0  fa d6 09 47 f2 fb 02 03  01 00 01 a3 81 93 30 81  |...G..........0.|
+000001b0  90 30 0e 06 03 55 1d 0f  01 01 ff 04 04 03 02 05  |.0...U..........|
+000001c0  a0 30 1d 06 03 55 1d 25  04 16 30 14 06 08 2b 06  |.0...U.%..0...+.|
+000001d0  01 05 05 07 03 01 06 08  2b 06 01 05 05 07 03 02  |........+.......|
+000001e0  30 0c 06 03 55 1d 13 01  01 ff 04 02 30 00 30 19  |0...U.......0.0.|
+000001f0  06 03 55 1d 0e 04 12 04  10 12 50 8d 89 6f 1b d1  |..U.......P..o..|
+00000200  dc 54 4d 6e cb 69 5e 06  f4 30 1b 06 03 55 1d 23  |.TMn.i^..0...U.#|
+00000210  04 14 30 12 80 10 bf 3d  b6 a9 66 f2 b8 40 cf ea  |..0....=..f.. at ..|
+00000220  b4 03 78 48 1a 41 30 19  06 03 55 1d 11 04 12 30  |..xH.A0...U....0|
+00000230  10 82 0e 65 78 61 6d 70  6c 65 2e 67 6f 6c 61 6e  |...example.golan|
+00000240  67 30 0d 06 09 2a 86 48  86 f7 0d 01 01 0b 05 00  |g0...*.H........|
+00000250  03 81 81 00 92 7c af 91  55 12 18 96 59 31 a6 48  |.....|..U...Y1.H|
+00000260  40 d5 2d d5 ee bb 02 a0  f5 c2 1e 7c 9b b3 30 7d  |@.-........|..0}|
+00000270  3c dc 76 da 4f 3d c0 fa  ae 2d 33 24 6b 03 7b 1b  |<.v.O=...-3$k.{.|
+00000280  67 59 11 21 b5 11 bc 77  b9 d9 e0 6e a8 2d 2e 35  |gY.!...w...n.-.5|
+00000290  fa 64 5f 22 3e 63 10 6b  be ff 14 86 6d 0d f0 15  |.d_">c.k....m...|
+000002a0  31 a8 14 38 1e 3b 84 87  2c cb 98 ed 51 76 b9 b1  |1..8.;..,...Qv..|
+000002b0  4f dd db 9b 84 04 86 40  fa 51 dd ba b4 8d eb e3  |O...... at .Q......|
+000002c0  46 de 46 b9 4f 86 c7 f9  a4 c2 41 34 ac cc f6 ea  |F.F.O.....A4....|
+000002d0  b0 ab 39 18 16 03 03 00  cd 0c 00 00 c9 03 00 17  |..9.............|
+000002e0  41 04 2a 2a b7 63 a8 8e  34 67 32 18 57 6e fe 2a  |A.**.c..4g2.Wn.*|
+000002f0  51 41 41 5f 65 a3 a7 e9  d6 0b 42 7f 77 fb 40 09  |QAA_e.....B.w. at .|
+00000300  c8 7a a2 9b fd 5f 6e 2b  ce 85 f6 24 c2 8d e8 bb  |.z..._n+...$....|
+00000310  69 3e dc 51 15 6f a8 db  a4 fb 11 10 70 04 82 6a  |i>.Q.o......p..j|
+00000320  7b 81 04 01 00 80 7a a3  c9 1b e6 02 33 39 55 36  |{.....z.....39U6|
+00000330  dc f9 2d f7 00 5b 8d f4  de 7a f7 3b 1b 4c 9a 27  |..-..[...z.;.L.'|
+00000340  f6 db 3c d1 6b f8 d6 7a  20 53 33 5f 88 9f f6 73  |..<.k..z S3_...s|
+00000350  90 2f 35 9e f6 05 b5 80  96 4f c8 85 e6 72 95 ba  |./5......O...r..|
+00000360  3b 42 43 94 c3 0b db 91  ff 6b 24 c6 b1 78 de 18  |;BC......k$..x..|
+00000370  9f d5 3b 33 53 22 45 bf  cb b2 d2 77 ce 03 56 7b  |..;3S"E....w..V{|
+00000380  b7 56 b6 ec 04 64 62 04  f7 f8 52 1a 47 49 01 71  |.V...db...R.GI.q|
+00000390  29 9e ee 68 1f e9 c6 36  fb 77 4c 9a 14 90 e1 70  |)..h...6.wL....p|
+000003a0  7d 7e 77 92 a6 18 16 03  03 00 2e 0d 00 00 26 03  |}~w...........&.|
+000003b0  01 02 40 00 1e 06 01 06  02 06 03 05 01 05 02 05  |.. at .............|
+000003c0  03 04 01 04 02 04 03 03  01 03 02 03 03 02 01 02  |................|
+000003d0  02 02 03 00 00 0e 00 00  00                       |.........|
 >>> Flow 3 (client to server)
 00000000  16 03 03 01 fb 0b 00 01  f7 00 01 f4 00 01 f1 30  |...............0|
 00000010  82 01 ed 30 82 01 58 a0  03 02 01 02 02 01 00 30  |...0..X........0|
@@ -114,26 +109,26 @@
 00000220  a7 24 20 3e b2 56 1c ce  97 28 5e f8 2b 2d 4f 9e  |.$ >.V...(^.+-O.|
 00000230  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
 00000240  a6 b5 68 1a 41 03 56 6b  dc 5a 89 16 03 03 00 88  |..h.A.Vk.Z......|
-00000250  0f 00 00 84 05 01 00 80  33 bb 8e 67 64 03 e7 7e  |........3..gd..~|
-00000260  be a5 b1 bc cf 7a 07 24  01 17 c3 3d 4b 72 dd c3  |.....z.$...=Kr..|
-00000270  64 a7 36 e8 49 ab b6 87  ce d6 af 9e 07 22 76 e8  |d.6.I........"v.|
-00000280  0d 44 a3 36 c9 eb a4 49  85 cf 72 67 e8 2a a7 5b  |.D.6...I..rg.*.[|
-00000290  d3 f2 46 af 53 48 c6 13  f7 0b 5b 9c c7 4d 3e 05  |..F.SH....[..M>.|
-000002a0  3c 0f 69 a7 40 3a e8 70  04 01 1c 29 b2 42 0f 5f  |<.i.@:.p...).B._|
-000002b0  1c d5 b7 5c c2 17 07 7f  bd a2 b3 9a 95 81 51 24  |...\..........Q$|
-000002c0  54 5c 42 d6 a4 76 c0 d7  54 d2 11 54 bf fd dc a0  |T\B..v..T..T....|
-000002d0  ee 95 26 64 59 a0 fc 51  14 03 03 00 01 01 16 03  |..&dY..Q........|
-000002e0  03 00 28 00 00 00 00 00  00 00 00 af f4 8a be d9  |..(.............|
-000002f0  ff f1 44 e4 41 ab 9b b3  d8 b0 3d 3f 6b c5 1d b6  |..D.A.....=?k...|
-00000300  1d 9e 35 f5 20 f4 2a af  e8 35 77                 |..5. .*..5w|
+00000250  0f 00 00 84 05 01 00 80  45 11 dc 3c 2a fc 5f aa  |........E..<*._.|
+00000260  60 09 59 47 45 cc a7 74  e3 9d 0c c3 a4 08 b0 2a  |`.YGE..t.......*|
+00000270  44 47 cd 66 ed 94 54 8f  d7 74 fd 47 a3 90 56 69  |DG.f..T..t.G..Vi|
+00000280  5a b6 c5 b0 bd c2 16 a2  1e af 58 37 88 cb d1 4b  |Z.........X7...K|
+00000290  5c ee e6 0f 16 9b e0 d7  43 b3 e6 0a b2 90 fa 21  |\.......C......!|
+000002a0  78 95 3e 7f fc c1 b3 df  a1 bf fc eb bc e8 37 63  |x.>...........7c|
+000002b0  87 33 3e c3 9a e4 6c 0f  3d 0d 9f e8 db 2d 82 ad  |.3>...l.=....-..|
+000002c0  3c 6d f7 4a 5e 81 21 4f  19 0e 60 2d ef c1 40 8d  |<m.J^.!O..`-.. at .|
+000002d0  cb 97 4f 08 1c c0 66 e7  14 03 03 00 01 01 16 03  |..O...f.........|
+000002e0  03 00 28 00 00 00 00 00  00 00 00 8c ce 5e 94 90  |..(..........^..|
+000002f0  22 2c 8d 64 be 29 99 62  1f 95 6e 3b 51 22 9c eb  |",.d.).b..n;Q"..|
+00000300  f3 0f 24 b8 a5 84 58 70  82 71 a1                 |..$...Xp.q.|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 28 ff 0d 47 63 2b  |..........(..Gc+|
-00000010  bd 00 3a ad 82 e3 a7 b3  b0 84 4a 26 f4 30 78 20  |..:.......J&.0x |
-00000020  80 f2 2b 15 98 61 1c cb  8b 17 67 8a 11 96 aa 93  |..+..a....g.....|
-00000030  68 f7 fb                                          |h..|
+00000000  14 03 03 00 01 01 16 03  03 00 28 b1 23 11 48 69  |..........(.#.Hi|
+00000010  52 44 34 f1 9a 69 2b 79  fb 68 b4 53 d5 d7 08 08  |RD4..i+y.h.S....|
+00000020  34 95 5f 56 b2 57 eb 91  31 6c 32 25 b5 68 8a 8e  |4._V.W..1l2%.h..|
+00000030  f1 68 6e                                          |.hn|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 a6 8d 7b  |...............{|
-00000010  99 5e a2 e1 95 bb 5f e4  01 f4 0e 20 52 b4 64 4e  |.^...._.... R.dN|
-00000020  86 b1 3f 15 03 03 00 1a  00 00 00 00 00 00 00 02  |..?.............|
-00000030  61 98 eb d0 7c ac bd 00  ac 7a e1 32 20 3e 81 b6  |a...|....z.2 >..|
-00000040  9d d5                                             |..|
+00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 03 ab 9e  |................|
+00000010  f0 a6 6c f1 ea 23 20 63  42 a3 9d c6 5d 41 96 c1  |..l..# cB...]A..|
+00000020  44 b2 8b 15 03 03 00 1a  00 00 00 00 00 00 00 02  |D...............|
+00000030  e9 73 41 50 28 b0 d3 00  46 81 d6 c9 1a ca ab cd  |.sAP(...F.......|
+00000040  44 9b                                             |D.|
diff --git a/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA
index 23bf29d..4fa5e20 100644
--- a/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA
+++ b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-ECDSA
@@ -1,19 +1,19 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 81 01 00 00  7d 03 03 00 00 00 00 00  |........}.......|
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 36  |...../.5.......6|
-00000050  00 05 00 05 01 00 00 00  00 00 0a 00 08 00 06 00  |................|
-00000060  17 00 18 00 19 00 0b 00  02 01 00 00 0d 00 0e 00  |................|
-00000070  0c 04 01 04 03 05 01 05  03 02 01 02 03 ff 01 00  |................|
-00000080  01 00 00 12 00 00                                 |......|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 b3 7f 4e e7 11  |....Y...U....N..|
-00000010  6d bc 56 ec 9c a8 61 08  d6 5a 2a 42 7b f1 94 0a  |m.V...a..Z*B{...|
-00000020  29 35 8b 7e 23 a0 6c 59  23 cf 39 20 84 09 b6 5b  |)5.~#.lY#.9 ...[|
-00000030  2f 46 80 3b 26 92 fd 81  e9 24 8c e2 b8 64 a2 03  |/F.;&....$...d..|
-00000040  3a 68 c3 7b 44 f8 28 41  e2 d3 6c 7c c0 09 00 00  |:h.{D.(A..l|....|
+00000000  16 03 03 00 59 02 00 00  55 03 03 2a 01 f8 3e d1  |....Y...U..*..>.|
+00000010  52 41 2e 9a 8d 56 ff 52  3d 6a fe 65 ab 91 bb b7  |RA...V.R=j.e....|
+00000020  82 be f1 60 40 3b 80 a1  f8 dc 95 20 48 87 41 46  |...`@;..... H.AF|
+00000030  6a d2 f3 b8 d8 68 20 40  45 b7 fe 19 21 bc 84 00  |j....h @E...!...|
+00000040  5d 40 40 21 58 3e 7d fb  a7 e3 30 37 c0 09 00 00  |]@@!X>}...07....|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
 00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
@@ -48,23 +48,24 @@
 00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
 00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
 00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
-00000270  2a 16 03 03 00 d7 0c 00  00 d3 03 00 17 41 04 0f  |*............A..|
-00000280  4d b0 41 d4 dc 6b 8a 85  52 eb eb 18 4a 8f a7 e6  |M.A..k..R...J...|
-00000290  24 52 e5 86 be 57 d7 0a  e7 23 84 a8 a9 6c 96 08  |$R...W...#...l..|
-000002a0  4b f7 47 32 79 d9 df 81  f6 05 40 63 3b 14 67 3b  |K.G2y..... at c;.g;|
-000002b0  ea 01 a0 0d 43 1a 36 29  b3 51 7a e4 af 1b 67 04  |....C.6).Qz...g.|
-000002c0  03 00 8a 30 81 87 02 42  01 8e 57 8a b8 b7 5b 2f  |...0...B..W...[/|
-000002d0  9c 31 74 d8 7d 68 d7 6e  83 73 5f fb d0 cd de 66  |.1t.}h.n.s_....f|
-000002e0  60 fa 0a 0a 15 0b 30 3b  08 b6 f1 3e 4f 20 13 62  |`.....0;...>O .b|
-000002f0  b5 ff 86 81 dc 42 a1 4c  af c8 ff b3 24 81 d8 e1  |.....B.L....$...|
-00000300  d1 09 0c 32 11 92 5e dd  3f 87 02 41 76 a7 29 48  |...2..^.?..Av.)H|
-00000310  52 68 1c 72 4d d5 39 bf  fa 61 ec b2 27 ce 10 4e  |Rh.rM.9..a..'..N|
-00000320  86 12 3d 1e 04 9c 11 b7  b4 0c cf 98 9d 01 c3 93  |..=.............|
-00000330  cf 83 9e 92 9a ca fd 8f  b1 9f 1b 20 c4 fb a4 46  |........... ...F|
-00000340  60 fc fd d5 33 b0 8f b5  b5 c8 a4 70 c5 16 03 03  |`...3......p....|
-00000350  00 2e 0d 00 00 26 03 01  02 40 00 1e 06 01 06 02  |.....&... at ......|
-00000360  06 03 05 01 05 02 05 03  04 01 04 02 04 03 03 01  |................|
-00000370  03 02 03 03 02 01 02 02  02 03 00 00 0e 00 00 00  |................|
+00000270  2a 16 03 03 00 d8 0c 00  00 d4 03 00 17 41 04 00  |*............A..|
+00000280  9e 90 3a 3d 00 37 0a c0  43 92 6e bf b4 23 d9 64  |..:=.7..C.n..#.d|
+00000290  99 d2 90 9e eb 88 b6 d6  6f 15 4a 22 72 f0 bf 5e  |........o.J"r..^|
+000002a0  72 80 93 90 aa f1 d1 9c  45 c6 6e 3a f8 a9 6f fe  |r.......E.n:..o.|
+000002b0  fb 24 dc b1 4d 52 39 91  f5 48 36 06 f6 15 0e 04  |.$..MR9..H6.....|
+000002c0  03 00 8b 30 81 88 02 42  00 a9 54 74 a7 a8 d0 04  |...0...B..Tt....|
+000002d0  ae ef e4 64 38 74 21 e6  18 f0 79 b2 d7 7e 7b 0e  |...d8t!...y..~{.|
+000002e0  f6 74 75 52 f0 b8 15 3c  3d 15 52 75 9f 60 03 63  |.tuR...<=.Ru.`.c|
+000002f0  15 b8 1e b8 0e 5c 58 c7  e7 2f 6d 76 c7 c8 42 7a  |.....\X../mv..Bz|
+00000300  df 15 26 4b dc 9c 3b 4d  b3 b6 02 42 00 a5 fd bf  |..&K..;M...B....|
+00000310  a9 5d fc 87 42 24 f9 0b  7a 17 97 7c ee 45 1c 29  |.]..B$..z..|.E.)|
+00000320  3a 07 5f df 4d f2 d3 cb  fc a6 fd 84 34 2c 40 84  |:._.M.......4, at .|
+00000330  06 76 bf 43 35 d2 f6 9a  7c d6 1b 5e d8 fd 08 35  |.v.C5...|..^...5|
+00000340  1b 90 0e 24 a7 48 9d 71  ab 4a 11 92 d3 6e 16 03  |...$.H.q.J...n..|
+00000350  03 00 2e 0d 00 00 26 03  01 02 40 00 1e 06 01 06  |......&... at .....|
+00000360  02 06 03 05 01 05 02 05  03 04 01 04 02 04 03 03  |................|
+00000370  01 03 02 03 03 02 01 02  02 02 03 00 00 0e 00 00  |................|
+00000380  00                                                |.|
 >>> Flow 3 (client to server)
 00000000  16 03 03 01 fb 0b 00 01  f7 00 01 f4 00 01 f1 30  |...............0|
 00000010  82 01 ed 30 82 01 58 a0  03 02 01 02 02 01 00 30  |...0..X........0|
@@ -103,31 +104,31 @@
 00000220  a7 24 20 3e b2 56 1c ce  97 28 5e f8 2b 2d 4f 9e  |.$ >.V...(^.+-O.|
 00000230  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
 00000240  a6 b5 68 1a 41 03 56 6b  dc 5a 89 16 03 03 00 88  |..h.A.Vk.Z......|
-00000250  0f 00 00 84 05 01 00 80  02 19 16 cc 97 ad 70 20  |..............p |
-00000260  bd 64 63 dd b6 81 a0 16  b3 46 4b 42 ff 21 58 2c  |.dc......FKB.!X,|
-00000270  bb 2b 4c e1 4e d7 49 4d  5c 7c 63 32 3e ef e6 ad  |.+L.N.IM\|c2>...|
-00000280  85 3f ab b4 5c 2a 37 76  8b 28 56 08 4f 08 b9 51  |.?..\*7v.(V.O..Q|
-00000290  71 14 07 27 47 45 11 a0  03 cf 72 7d 67 ef 31 8d  |q..'GE....r}g.1.|
-000002a0  e7 db 36 76 b1 b3 f4 bf  aa 6c c4 56 94 35 71 e1  |..6v.....l.V.5q.|
-000002b0  dd 88 6d 15 90 c8 70 ad  d8 95 55 42 9b c1 45 19  |..m...p...UB..E.|
-000002c0  36 ce 87 c6 fd 94 8a d4  98 6e ec 18 d5 da 59 54  |6........n....YT|
-000002d0  80 a7 8c 90 ae 55 20 1c  14 03 03 00 01 01 16 03  |.....U .........|
+00000250  0f 00 00 84 05 01 00 80  20 ef 4b 1c d7 67 37 6e  |........ .K..g7n|
+00000260  24 12 9e e9 59 b1 6d da  e5 3e 6b 11 03 f4 96 e4  |$...Y.m..>k.....|
+00000270  2e fb 03 e1 13 af 73 4d  15 11 c1 80 e2 ed 11 c6  |......sM........|
+00000280  73 6a 96 ce d1 26 e4 bc  fe 71 c9 48 32 fd d8 70  |sj...&...q.H2..p|
+00000290  01 9d 18 7b ed a3 bd 6a  68 df 45 a0 d5 77 79 d2  |...{...jh.E..wy.|
+000002a0  5b e2 8c 96 68 95 46 8d  7d e6 b6 26 fa e1 c4 05  |[...h.F.}..&....|
+000002b0  4c d1 39 4e 35 e3 0c 1b  26 37 2e 0b 9b 0b cf f7  |L.9N5...&7......|
+000002c0  25 c3 da 27 18 70 83 18  49 ff ee ba e3 f8 70 75  |%..'.p..I.....pu|
+000002d0  e8 9b 2d 89 d7 b2 00 a5  14 03 03 00 01 01 16 03  |..-.............|
 000002e0  03 00 40 00 00 00 00 00  00 00 00 00 00 00 00 00  |.. at .............|
-000002f0  00 00 00 58 fe bc 5c ba  b2 a9 96 77 2f 95 c9 10  |...X..\....w/...|
-00000300  fd 6d fc 6a 88 8c df 82  c3 a4 3d cc 28 f4 bf 7d  |.m.j......=.(..}|
-00000310  4a f8 3d 97 36 e5 a0 76  92 94 da dd cc f5 e4 0e  |J.=.6..v........|
-00000320  7a c4 2c                                          |z.,|
+000002f0  00 00 00 d3 33 79 85 64  14 07 a6 93 74 f8 f8 55  |....3y.d....t..U|
+00000300  0f fb fc 8e 1b 4c 38 21  b6 61 c5 4b b2 d4 17 b2  |.....L8!.a.K....|
+00000310  c4 be a6 4b d6 3f a3 5f  3c ff 5f 1d 93 a2 c4 82  |...K.?._<._.....|
+00000320  96 90 eb                                          |...|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 40 81 ab 5a 66 a8  |.......... at ..Zf.|
-00000010  0f a5 d3 07 00 66 45 1f  31 a9 ef f7 a0 d9 23 46  |.....fE.1.....#F|
-00000020  f0 3e 50 18 99 e3 5a bd  eb b7 1d 81 d5 95 d5 ee  |.>P...Z.........|
-00000030  21 31 41 4b 19 92 b5 95  36 da 21 c0 4a 2a a0 1c  |!1AK....6.!.J*..|
-00000040  a3 9f 8e a0 6f 9d 37 5e  12 11 03                 |....o.7^...|
+00000000  14 03 03 00 01 01 16 03  03 00 40 80 b0 df ff b3  |.......... at .....|
+00000010  34 11 03 f5 2d fb c7 c2  38 15 df 41 97 55 0e 1d  |4...-...8..A.U..|
+00000020  36 f7 a5 35 5b 63 d7 c5  a6 fd fc a1 91 32 9d cd  |6..5[c.......2..|
+00000030  34 66 75 4c 5d 27 ee 89  ed d4 4a ec 67 b0 da e7  |4fuL]'....J.g...|
+00000040  f0 e7 36 eb db b9 22 97  74 30 cd                 |..6...".t0.|
 >>> Flow 5 (client to server)
 00000000  17 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
-00000010  00 00 00 00 00 a9 51 94  19 72 ab 9f 3e 97 5e 99  |......Q..r..>.^.|
-00000020  2c ec 13 48 3e 10 54 5f  8a 85 88 4d 1a a8 f5 ed  |,..H>.T_...M....|
-00000030  c3 4f a9 59 a3 15 03 03  00 30 00 00 00 00 00 00  |.O.Y.....0......|
-00000040  00 00 00 00 00 00 00 00  00 00 25 00 6d 2f a0 f6  |..........%.m/..|
-00000050  ce 8a 30 ba 53 da 97 c6  11 f3 d2 f3 9e 66 d6 dd  |..0.S........f..|
-00000060  19 f3 ee 07 03 d3 e6 f1  30 32                    |........02|
+00000010  00 00 00 00 00 62 24 32  e9 40 38 c8 c3 dd 07 42  |.....b$2. at 8....B|
+00000020  05 c8 7c 3d d1 27 68 00  e4 91 6c 2d 08 c1 a1 b6  |..|=.'h...l-....|
+00000030  8a 89 3d 1d c1 15 03 03  00 30 00 00 00 00 00 00  |..=......0......|
+00000040  00 00 00 00 00 00 00 00  00 00 d1 c8 bc cb cb a5  |................|
+00000050  24 1e ad c5 bf 23 92 4b  81 a6 c0 77 19 e0 46 30  |$....#.K...w..F0|
+00000060  48 51 0c cc 39 cd 4b 8d  e5 a7                    |HQ..9.K...|
diff --git a/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA
index ff79aa2..a0a9640 100644
--- a/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA
+++ b/src/crypto/tls/testdata/Client-TLSv12-ClientCert-RSA-RSA
@@ -1,67 +1,62 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 81 01 00 00  7d 03 03 00 00 00 00 00  |........}.......|
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 36  |...../.5.......6|
-00000050  00 05 00 05 01 00 00 00  00 00 0a 00 08 00 06 00  |................|
-00000060  17 00 18 00 19 00 0b 00  02 01 00 00 0d 00 0e 00  |................|
-00000070  0c 04 01 04 03 05 01 05  03 02 01 02 03 ff 01 00  |................|
-00000080  01 00 00 12 00 00                                 |......|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 51 02 00 00  4d 03 03 b3 b2 22 69 e4  |....Q...M...."i.|
-00000010  1a a1 56 94 26 0c 43 b7  89 0c 34 ce dc 5a c8 ca  |..V.&.C...4..Z..|
-00000020  e2 42 92 5c 75 9a b3 22  22 64 38 20 6d 2c 26 0b  |.B.\u..""d8 m,&.|
-00000030  34 b6 b8 20 36 e2 58 e5  ee 1f e2 9f a0 75 f6 d9  |4.. 6.X......u..|
-00000040  0c e4 39 ce 3c 8e 2e f8  e8 d1 a2 16 00 05 00 00  |..9.<...........|
-00000050  05 ff 01 00 01 00 16 03  03 02 be 0b 00 02 ba 00  |................|
-00000060  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
-00000070  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
-00000080  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
-00000090  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
-000000a0  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
-000000b0  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
-000000c0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
-000000d0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
-000000e0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
-000000f0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
-00000100  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
-00000110  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
-00000120  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
-00000130  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
-00000140  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
-00000150  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
-00000160  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
-00000170  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
-00000180  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
-00000190  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
-000001a0  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
-000001b0  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
-000001c0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
-000001d0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
-000001e0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
-000001f0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
-00000200  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
-00000210  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
-00000220  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
-00000230  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
-00000240  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
-00000250  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
-00000260  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
-00000270  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
-00000280  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
-00000290  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
-000002a0  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
-000002b0  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
-000002c0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
-000002d0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
-000002e0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
-000002f0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
-00000300  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
-00000310  6e 38 50 29 6c 90 a7 bd  d9 16 03 03 00 2e 0d 00  |n8P)l...........|
-00000320  00 26 03 01 02 40 00 1e  06 01 06 02 06 03 05 01  |.&... at ..........|
-00000330  05 02 05 03 04 01 04 02  04 03 03 01 03 02 03 03  |................|
-00000340  02 01 02 02 02 03 00 00  0e 00 00 00              |............|
+00000000  16 03 03 00 51 02 00 00  4d 03 03 60 8e 1c c9 6d  |....Q...M..`...m|
+00000010  de 9d 2a dc 6a a6 82 71  9a 3f 8f 5b 18 52 44 4e  |..*.j..q.?.[.RDN|
+00000020  4d 72 0d e7 c8 a1 b0 81  64 8c 1f 20 06 a8 17 35  |Mr......d.. ...5|
+00000030  b8 0b 96 52 30 f7 b3 d4  2a 25 94 c0 ba a8 a2 f7  |...R0...*%......|
+00000040  86 5c 18 18 3c 68 3a 71  0f bc 3f 12 00 05 00 00  |.\..<h:q..?.....|
+00000050  05 ff 01 00 01 00 16 03  03 02 71 0b 00 02 6d 00  |..........q...m.|
+00000060  02 6a 00 02 67 30 82 02  63 30 82 01 cc a0 03 02  |.j..g0..c0......|
+00000070  01 02 02 09 00 a2 73 00  0c 81 00 cb f3 30 0d 06  |......s......0..|
+00000080  09 2a 86 48 86 f7 0d 01  01 0b 05 00 30 2b 31 17  |.*.H........0+1.|
+00000090  30 15 06 03 55 04 0a 13  0e 47 6f 6f 67 6c 65 20  |0...U....Google |
+000000a0  54 45 53 54 49 4e 47 31  10 30 0e 06 03 55 04 03  |TESTING1.0...U..|
+000000b0  13 07 47 6f 20 52 6f 6f  74 30 1e 17 0d 31 35 30  |..Go Root0...150|
+000000c0  31 30 31 30 30 30 30 30  30 5a 17 0d 32 35 30 31  |101000000Z..2501|
+000000d0  30 31 30 30 30 30 30 30  5a 30 26 31 17 30 15 06  |01000000Z0&1.0..|
+000000e0  03 55 04 0a 13 0e 47 6f  6f 67 6c 65 20 54 45 53  |.U....Google TES|
+000000f0  54 49 4e 47 31 0b 30 09  06 03 55 04 03 13 02 47  |TING1.0...U....G|
+00000100  6f 30 81 9f 30 0d 06 09  2a 86 48 86 f7 0d 01 01  |o0..0...*.H.....|
+00000110  01 05 00 03 81 8d 00 30  81 89 02 81 81 00 af 87  |.......0........|
+00000120  88 f6 20 1b 95 65 6c 14  ab 44 05 af 3b 45 14 e3  |.. ..el..D..;E..|
+00000130  b7 6d fd 00 63 4d 95 7f  fe 6a 62 35 86 c0 4a f9  |.m..cM...jb5..J.|
+00000140  18 7c f6 aa 25 5e 7a 64  31 66 00 ba f4 8e 92 af  |.|..%^zd1f......|
+00000150  c7 6b d8 76 d4 f3 5f 41  cb 6e 56 15 97 1b 97 c1  |.k.v.._A.nV.....|
+00000160  3c 12 39 21 66 3d 2b 16  d1 bc db 1c c0 a7 da b7  |<.9!f=+.........|
+00000170  ca ad ba da cb d5 21 50  ec de 8d ab d1 6b 81 4b  |......!P.....k.K|
+00000180  89 02 f3 c4 be c1 6c 89  b1 44 84 bd 21 d1 04 7d  |......l..D..!..}|
+00000190  9d 16 4d f9 82 15 f6 ef  fa d6 09 47 f2 fb 02 03  |..M........G....|
+000001a0  01 00 01 a3 81 93 30 81  90 30 0e 06 03 55 1d 0f  |......0..0...U..|
+000001b0  01 01 ff 04 04 03 02 05  a0 30 1d 06 03 55 1d 25  |.........0...U.%|
+000001c0  04 16 30 14 06 08 2b 06  01 05 05 07 03 01 06 08  |..0...+.........|
+000001d0  2b 06 01 05 05 07 03 02  30 0c 06 03 55 1d 13 01  |+.......0...U...|
+000001e0  01 ff 04 02 30 00 30 19  06 03 55 1d 0e 04 12 04  |....0.0...U.....|
+000001f0  10 12 50 8d 89 6f 1b d1  dc 54 4d 6e cb 69 5e 06  |..P..o...TMn.i^.|
+00000200  f4 30 1b 06 03 55 1d 23  04 14 30 12 80 10 bf 3d  |.0...U.#..0....=|
+00000210  b6 a9 66 f2 b8 40 cf ea  b4 03 78 48 1a 41 30 19  |..f.. at ....xH.A0.|
+00000220  06 03 55 1d 11 04 12 30  10 82 0e 65 78 61 6d 70  |..U....0...examp|
+00000230  6c 65 2e 67 6f 6c 61 6e  67 30 0d 06 09 2a 86 48  |le.golang0...*.H|
+00000240  86 f7 0d 01 01 0b 05 00  03 81 81 00 92 7c af 91  |.............|..|
+00000250  55 12 18 96 59 31 a6 48  40 d5 2d d5 ee bb 02 a0  |U...Y1.H at .-.....|
+00000260  f5 c2 1e 7c 9b b3 30 7d  3c dc 76 da 4f 3d c0 fa  |...|..0}<.v.O=..|
+00000270  ae 2d 33 24 6b 03 7b 1b  67 59 11 21 b5 11 bc 77  |.-3$k.{.gY.!...w|
+00000280  b9 d9 e0 6e a8 2d 2e 35  fa 64 5f 22 3e 63 10 6b  |...n.-.5.d_">c.k|
+00000290  be ff 14 86 6d 0d f0 15  31 a8 14 38 1e 3b 84 87  |....m...1..8.;..|
+000002a0  2c cb 98 ed 51 76 b9 b1  4f dd db 9b 84 04 86 40  |,...Qv..O......@|
+000002b0  fa 51 dd ba b4 8d eb e3  46 de 46 b9 4f 86 c7 f9  |.Q......F.F.O...|
+000002c0  a4 c2 41 34 ac cc f6 ea  b0 ab 39 18 16 03 03 00  |..A4......9.....|
+000002d0  2e 0d 00 00 26 03 01 02  40 00 1e 06 01 06 02 06  |....&... at .......|
+000002e0  03 05 01 05 02 05 03 04  01 04 02 04 03 03 01 03  |................|
+000002f0  02 03 03 02 01 02 02 02  03 00 00 0e 00 00 00     |...............|
 >>> Flow 3 (client to server)
 00000000  16 03 03 01 fb 0b 00 01  f7 00 01 f4 00 01 f1 30  |...............0|
 00000010  82 01 ed 30 82 01 58 a0  03 02 01 02 02 01 00 30  |...0..X........0|
@@ -95,33 +90,33 @@
 000001d0  8b ec ab 67 be c8 64 b0  11 50 46 58 17 6b 99 1c  |...g..d..PFX.k..|
 000001e0  d3 1d fc 06 f1 0e e5 96  a8 0c f9 78 20 b7 44 18  |...........x .D.|
 000001f0  51 8d 10 7e 4f 94 67 df  a3 4e 70 73 8e 90 91 85  |Q..~O.g..Nps....|
-00000200  16 03 03 00 86 10 00 00  82 00 80 6d 51 f3 7f f9  |...........mQ...|
-00000210  3e fb 75 82 41 36 83 e8  6a ee 2a 2e 25 90 67 4c  |>.u.A6..j.*.%.gL|
-00000220  8e 62 2f 30 81 17 e0 85  09 0c 2b b7 23 d7 b0 e2  |.b/0......+.#...|
-00000230  1d f7 3b d7 f5 a1 27 b6  ee 24 b6 1b cc 5b ea 66  |..;...'..$...[.f|
-00000240  0d 6a f4 e5 85 f9 da 43  b4 0e 86 85 e1 f5 aa be  |.j.....C........|
-00000250  c8 ce 39 4c 9c 86 00 08  c2 4b e2 c6 ec 2f f7 ce  |..9L.....K.../..|
-00000260  e6 bd 77 82 6f 23 b6 e0  bd a2 92 b7 3a ac e8 56  |..w.o#......:..V|
-00000270  f1 af 54 5e 46 87 e9 3b  33 e7 b8 28 b7 d6 c8 90  |..T^F..;3..(....|
-00000280  35 d4 1c 43 d1 30 6f 55  4e 0a 70 16 03 03 00 88  |5..C.0oUN.p.....|
-00000290  0f 00 00 84 05 01 00 80  01 24 8d bb 05 61 2d 29  |.........$...a-)|
-000002a0  12 11 90 f5 57 21 be b7  29 76 55 63 94 8e 7b 4d  |....W!..)vUc..{M|
-000002b0  3b 3d 89 5b 1f b9 e1 8c  36 68 6f 31 21 50 af e4  |;=.[....6ho1!P..|
-000002c0  9f ca a5 68 55 b9 eb 36  75 3a 0c be 11 30 28 c8  |...hU..6u:...0(.|
-000002d0  8b 82 93 9a 71 37 4d 4e  4f d2 0c 2f 13 36 ad c3  |....q7MNO../.6..|
-000002e0  df 8a 1b 59 b2 f9 8b a7  74 63 75 4a f4 9d e0 6b  |...Y....tcuJ...k|
-000002f0  42 02 5a a9 6e a4 a8 24  d3 23 f7 09 ee b0 dc c4  |B.Z.n..$.#......|
-00000300  6f 87 58 72 e7 e3 87 b3  6b 15 ba 7f dd 9b 93 91  |o.Xr....k.......|
-00000310  5b 21 a0 31 31 bd 15 b5  14 03 03 00 01 01 16 03  |[!.11...........|
-00000320  03 00 24 fc 0e 7c e8 3e  8b b5 dc c9 3d 38 61 a1  |..$..|.>....=8a.|
-00000330  24 d6 77 1f 06 1f 30 32  ba dd 05 68 45 f1 4f 0d  |$.w...02...hE.O.|
-00000340  2e 24 09 ad c1 e5 b7                              |.$.....|
+00000200  16 03 03 00 86 10 00 00  82 00 80 73 bd 73 65 92  |...........s.se.|
+00000210  86 23 41 14 79 7f d5 c1  10 ce 94 4d ad 9c c3 a9  |.#A.y......M....|
+00000220  87 b5 32 52 f8 6b 11 93  2d 9b 98 0b 8b 1d c0 f6  |..2R.k..-.......|
+00000230  53 17 6d c7 9c 2e ae c9  6f cc 99 23 38 37 1a 10  |S.m.....o..#87..|
+00000240  fe 05 0b b5 55 0a 14 e9  60 7d 70 26 98 e2 54 d9  |....U...`}p&..T.|
+00000250  65 cf 2e f4 53 5f 1d aa  3a f6 33 7b eb 4c 0e b3  |e...S_..:.3{.L..|
+00000260  ff 5a db 36 2a 47 f3 df  f9 fc f5 31 78 83 aa 6b  |.Z.6*G.....1x..k|
+00000270  52 b7 ba 1a 96 bc fa c1  a1 a9 bb 2b f5 38 89 00  |R..........+.8..|
+00000280  4d e5 78 13 4e a4 38 46  42 dc 16 16 03 03 00 88  |M.x.N.8FB.......|
+00000290  0f 00 00 84 05 01 00 80  21 58 47 70 c2 2e 1c 4a  |........!XGp...J|
+000002a0  fa 97 b2 cf 8d f8 93 f4  b0 8c b3 e0 e7 33 a6 ea  |.............3..|
+000002b0  d7 fe 8e 25 e7 f3 f5 a1  8d 09 b7 0b 01 ec a1 15  |...%............|
+000002c0  5b 67 06 53 2a 7d 31 e5  a8 16 bc e3 1d ed 5a 77  |[g.S*}1.......Zw|
+000002d0  0b 78 78 c5 fc c5 62 8e  41 49 d3 ea cd 69 10 3f  |.xx...b.AI...i.?|
+000002e0  34 9e 86 df f9 9f f6 02  0c 29 c4 66 a0 45 cf 7b  |4........).f.E.{|
+000002f0  ce 51 ec 0a 26 b4 9d 3d  9e 63 5d 40 1a e8 84 4e  |.Q..&..=.c]@...N|
+00000300  24 f5 42 48 b5 3e f8 92  c4 f2 e6 5d f4 ad 67 01  |$.BH.>.....]..g.|
+00000310  f8 a7 a7 2b b5 fc be e8  14 03 03 00 01 01 16 03  |...+............|
+00000320  03 00 24 f0 ec 1d f5 39  1c d2 d2 c7 f4 1f 3b 0c  |..$....9......;.|
+00000330  cd 25 e4 8e ed c4 bb 02  9d 38 e5 a7 91 e0 ea 00  |.%.......8......|
+00000340  73 a8 9a 63 c9 e7 7d                              |s..c..}|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 24 d7 b6 b3 0a e6  |..........$.....|
-00000010  86 9a 25 e4 38 de d0 57  ff 93 0b f4 de 76 3d 00  |..%.8..W.....v=.|
-00000020  64 35 cf 70 f6 ea 74 2d  b0 71 2d 92 e2 df eb     |d5.p..t-.q-....|
+00000000  14 03 03 00 01 01 16 03  03 00 24 0b c5 7d ca a6  |..........$..}..|
+00000010  87 7f 50 7b 88 9c d9 8e  ea 78 a0 40 6b 8e 92 0b  |..P{.....x. at k...|
+00000020  78 88 97 46 ec 7c 20 5b  1f fc da 49 d8 6a be     |x..F.| [...I.j.|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 1a db bd 43  12 7c b5 83 b5 18 9d 6a  |.......C.|.....j|
-00000010  70 3f 5a eb cb d0 ba d4  03 3e a0 7b 25 f0 41 15  |p?Z......>.{%.A.|
-00000020  03 03 00 16 f8 f2 a3 27  a5 c7 25 d9 6c 08 b1 96  |.......'..%.l...|
-00000030  38 22 38 df 16 fb e2 9f  61 a3                    |8"8.....a.|
+00000000  17 03 03 00 1a 16 25 97  df 98 e4 d6 8e d1 2c 0c  |......%.......,.|
+00000010  27 74 67 e5 b7 f1 c7 58  41 5f 04 f5 e4 74 dc 15  |'tg....XA_...t..|
+00000020  03 03 00 16 df 55 01 0d  53 5b b4 36 c7 88 8d b0  |.....U..S[.6....|
+00000030  22 53 ec 87 1b 07 c7 9d  af 89                    |"S........|
diff --git a/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES
index e700e16..c9b5351 100644
--- a/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES
+++ b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES
@@ -1,19 +1,19 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 81 01 00 00  7d 03 03 00 00 00 00 00  |........}.......|
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 36  |...../.5.......6|
-00000050  00 05 00 05 01 00 00 00  00 00 0a 00 08 00 06 00  |................|
-00000060  17 00 18 00 19 00 0b 00  02 01 00 00 0d 00 0e 00  |................|
-00000070  0c 04 01 04 03 05 01 05  03 02 01 02 03 ff 01 00  |................|
-00000080  01 00 00 12 00 00                                 |......|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 21 9b eb 15 24  |....Y...U..!...$|
-00000010  46 b6 c1 85 f5 be c5 0d  e2 6b 60 bc ee 73 b1 fb  |F........k`..s..|
-00000020  34 6f f0 b8 f0 9e 1c 26  a4 4b 0f 20 cb 2b 84 a2  |4o.....&.K. .+..|
-00000030  cb a5 48 70 fe 84 25 b0  16 20 14 a1 83 21 fc f9  |..Hp..%.. ...!..|
-00000040  82 fc 9e 1a d1 3b 56 69  ab c5 0e 2c c0 09 00 00  |.....;Vi...,....|
+00000000  16 03 03 00 59 02 00 00  55 03 03 8a ae 27 5b 39  |....Y...U....'[9|
+00000010  8b c4 a6 d5 fa 9e 67 9e  6c fe 53 ed ab ec e0 04  |......g.l.S.....|
+00000020  8d 7c f8 1f d0 db 2e cb  22 4d a1 20 ee 80 5f fc  |.|......"M. .._.|
+00000030  f8 77 8a 23 23 c5 95 81  7f a6 12 f5 e0 19 91 50  |.w.##..........P|
+00000040  da 75 42 c2 eb 45 bf e2  a5 54 ed 6e c0 09 00 00  |.uB..E...T.n....|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
 00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
@@ -48,21 +48,21 @@
 00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
 00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
 00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
-00000270  2a 16 03 03 00 d8 0c 00  00 d4 03 00 17 41 04 b6  |*............A..|
-00000280  3f 37 33 68 cb 79 c0 86  f4 9d 12 ac c4 9d 8c 9b  |?73h.y..........|
-00000290  59 1c d4 a9 01 9f 2d cb  80 24 02 ec e0 ff d1 8c  |Y.....-..$......|
-000002a0  bd 82 67 3f 47 58 1a 2e  6b 61 f6 8e 4e 27 7f 49  |..g?GX..ka..N'.I|
-000002b0  b5 45 f1 0b 9a 33 ff 53  ac 65 e2 82 7a 18 5c 04  |.E...3.S.e..z.\.|
-000002c0  03 00 8b 30 81 88 02 42  00 e1 2d ff 5d e7 77 f1  |...0...B..-.].w.|
-000002d0  12 d9 e4 c2 4d cd 9c b5  ee e4 fd 21 b2 d8 53 a9  |....M......!..S.|
-000002e0  42 e7 c5 9b 51 c3 59 37  a5 08 d4 e6 29 12 c5 56  |B...Q.Y7....)..V|
-000002f0  b8 fe f0 bb 77 87 a3 ee  09 b0 8c cd 1c 39 9e b5  |....w........9..|
-00000300  d9 15 63 53 cb d7 f1 55  5b 48 02 42 01 19 10 8a  |..cS...U[H.B....|
-00000310  7a ee 95 b1 77 44 d4 a3  bf d1 f3 f1 b0 d8 c7 7e  |z...wD.........~|
-00000320  42 c0 83 04 f5 f7 9c c0  ce 6a 98 47 9d 21 29 84  |B........j.G.!).|
-00000330  c8 be 6b 67 4e fc c6 26  ec 63 df 00 33 e6 d2 f7  |..kgN..&.c..3...|
-00000340  34 93 85 9b 1b 0f e0 89  42 b6 0b 94 1b 80 16 03  |4.......B.......|
-00000350  03 00 04 0e 00 00 00                              |.......|
+00000270  2a 16 03 03 00 d7 0c 00  00 d3 03 00 17 41 04 3e  |*............A.>|
+00000280  e3 d6 d6 7b d7 ec 6f 4b  88 50 53 26 5a 2b a6 69  |...{..oK.PS&Z+.i|
+00000290  25 6f 30 a7 c3 a5 39 5c  e2 ca b6 35 a5 30 35 9a  |%o0...9\...5.05.|
+000002a0  35 8f e3 65 bd 4c 47 30  72 9a 4b 32 c4 6d 01 c9  |5..e.LG0r.K2.m..|
+000002b0  a5 91 d1 cd 0b 79 e2 04  0f a9 9c c2 72 cd 58 04  |.....y......r.X.|
+000002c0  03 00 8a 30 81 87 02 41  70 01 8c dd 0a 32 db e3  |...0...Ap....2..|
+000002d0  0b 04 9c d0 64 a1 08 06  b1 cf e3 66 79 1f c0 c1  |....d......fy...|
+000002e0  14 34 87 a6 e5 52 11 20  12 24 a5 b6 c2 50 63 86  |.4...R. .$...Pc.|
+000002f0  31 6a e3 85 7d 19 2d 3b  68 bf b7 64 20 37 c7 f9  |1j..}.-;h..d 7..|
+00000300  76 38 b5 32 84 0b f9 b6  71 02 42 01 89 e3 93 85  |v8.2....q.B.....|
+00000310  d6 16 8e 44 66 72 d6 9f  b3 b1 e9 22 ad 2e f8 49  |...Dfr....."...I|
+00000320  41 8f 80 f9 0e d4 fd de  35 67 cf 09 ba 65 f7 a1  |A.......5g...e..|
+00000330  17 a8 c0 b5 a3 cc c0 17  83 af 68 92 5b 5c a9 ce  |..........h.[\..|
+00000340  ce 11 92 93 fe 39 b9 80  19 20 f2 b6 3b 16 03 03  |.....9... ..;...|
+00000350  00 04 0e 00 00 00                                 |......|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 46 10 00 00  42 41 04 1e 18 37 ef 0d  |....F...BA...7..|
 00000010  19 51 88 35 75 71 b5 e5  54 5b 12 2e 8f 09 67 fd  |.Q.5uq..T[....g.|
@@ -70,21 +70,21 @@
 00000030  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
 00000040  a6 b5 68 1a 41 03 56 6b  dc 5a 89 14 03 03 00 01  |..h.A.Vk.Z......|
 00000050  01 16 03 03 00 40 00 00  00 00 00 00 00 00 00 00  |..... at ..........|
-00000060  00 00 00 00 00 00 50 73  9c 9f a8 d7 78 ac 06 14  |......Ps....x...|
-00000070  8f ae fc fb ef 7d 99 db  b7 c9 91 dd f2 fe da 1b  |.....}..........|
-00000080  aa 9e 7d e4 5c 2f 5f dd  74 aa fe 03 51 e7 cd 98  |..}.\/_.t...Q...|
-00000090  e9 21 19 c9 6f 59                                 |.!..oY|
+00000060  00 00 00 00 00 00 39 19  e6 fb c7 28 b4 c9 f5 ba  |......9....(....|
+00000070  a2 44 0a 74 70 18 86 1f  5f c2 3d 99 f5 d7 17 04  |.D.tp..._.=.....|
+00000080  88 07 a5 06 01 6a 2c 13  55 0b fc 82 75 b5 24 54  |.....j,.U...u.$T|
+00000090  a0 63 9e f0 ce 92                                 |.c....|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 40 47 18 b5 1b 75  |.......... at G...u|
-00000010  b8 a3 63 ab 77 d3 47 cb  14 26 b4 88 fe 15 db 22  |..c.w.G..&....."|
-00000020  76 3b 25 d3 68 8e f2 a7  d5 03 2b 82 7b b1 0f 10  |v;%.h.....+.{...|
-00000030  49 6a 3d 95 d0 4b 55 0e  14 eb bb a7 34 bb 57 b3  |Ij=..KU.....4.W.|
-00000040  5d fb 7e 15 80 5a fa f3  3a df 90                 |].~..Z..:..|
+00000000  14 03 03 00 01 01 16 03  03 00 40 15 37 89 e6 1f  |.......... at .7...|
+00000010  20 f6 91 b9 1f fb 29 e9  3e 07 ab c2 09 96 06 89  | .....).>.......|
+00000020  69 c2 dd 63 e1 24 5d cd  af 08 e2 ed df 46 45 6b  |i..c.$]......FEk|
+00000030  1e 9f 62 b6 89 27 04 3f  fc f2 77 71 23 04 24 37  |..b..'.?..wq#.$7|
+00000040  74 8a 0a 64 a8 10 e3 1c  dc 53 64                 |t..d.....Sd|
 >>> Flow 5 (client to server)
 00000000  17 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
-00000010  00 00 00 00 00 70 74 e2  60 fc 3a 7a b7 5e 16 07  |.....pt.`.:z.^..|
-00000020  22 92 07 fe 92 53 c4 43  1b 8f 94 07 84 48 2b 50  |"....S.C.....H+P|
-00000030  ab 1d 6d 49 ed 15 03 03  00 30 00 00 00 00 00 00  |..mI.....0......|
-00000040  00 00 00 00 00 00 00 00  00 00 ce a8 ba 91 0b e4  |................|
-00000050  8c 38 23 9b 8b 2c 0a 0c  63 79 61 f4 b6 25 f7 41  |.8#..,..cya..%.A|
-00000060  04 9f b0 8f e0 e5 24 44  2f e9                    |......$D/.|
+00000010  00 00 00 00 00 ae 4e e7  3a 25 9d 8f fa 06 99 49  |......N.:%.....I|
+00000020  2e b8 0f 49 d0 54 2d 06  b4 d7 4c 60 51 f1 13 11  |...I.T-...L`Q...|
+00000030  c1 b3 f5 d0 bc 15 03 03  00 30 00 00 00 00 00 00  |.........0......|
+00000040  00 00 00 00 00 00 00 00  00 00 80 de bf db 10 74  |...............t|
+00000050  da 3f d8 77 ca 37 cc f3  96 bd d3 e1 34 9c f2 0a  |.?.w.7......4...|
+00000060  70 60 5e 7c a4 7e c9 bd  89 5f                    |p`^|.~..._|
diff --git a/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM
index 607ecdc..48d822a 100644
--- a/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM
+++ b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES-GCM
@@ -1,19 +1,19 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 81 01 00 00  7d 03 03 00 00 00 00 00  |........}.......|
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 36  |...../.5.......6|
-00000050  00 05 00 05 01 00 00 00  00 00 0a 00 08 00 06 00  |................|
-00000060  17 00 18 00 19 00 0b 00  02 01 00 00 0d 00 0e 00  |................|
-00000070  0c 04 01 04 03 05 01 05  03 02 01 02 03 ff 01 00  |................|
-00000080  01 00 00 12 00 00                                 |......|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 91 8a 4f 94 29  |....Y...U....O.)|
-00000010  32 fa 66 7a 7f b8 a7 04  5c 34 b9 7e 12 83 35 1f  |2.fz....\4.~..5.|
-00000020  93 b0 af e0 9f 71 07 5e  2f d7 ca 20 52 dc 0d e7  |.....q.^/.. R...|
-00000030  f8 16 db 90 9a 78 2f 03  0b f0 ae a7 2f c6 b4 4c  |.....x/...../..L|
-00000040  62 e7 de 32 d5 68 61 f3  07 e4 60 d2 c0 2b 00 00  |b..2.ha...`..+..|
+00000000  16 03 03 00 59 02 00 00  55 03 03 42 ab c5 81 f5  |....Y...U..B....|
+00000010  c0 5b 73 64 f6 1b e0 59  30 b0 fd c5 e6 b3 57 f2  |.[sd...Y0.....W.|
+00000020  28 3f 5c d2 e8 05 7d a8  29 84 2e 20 8e 18 6b 52  |(?\...}.).. ..kR|
+00000030  1b ee 03 02 64 52 fb 24  44 4f 39 f2 d3 0f e6 9d  |....dR.$DO9.....|
+00000040  50 31 31 b3 39 9e c1 3a  b3 67 41 a0 c0 2b 00 00  |P11.9..:.gA..+..|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
 00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
@@ -48,20 +48,20 @@
 00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
 00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
 00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
-00000270  2a 16 03 03 00 d8 0c 00  00 d4 03 00 17 41 04 26  |*............A.&|
-00000280  c1 67 14 4b 9e b0 45 8c  27 bf a3 a2 78 5b 56 ad  |.g.K..E.'...x[V.|
-00000290  d1 21 56 53 df 86 e9 91  de e3 f9 5d e6 f6 5d 79  |.!VS.......]..]y|
-000002a0  11 8b 60 f9 c2 9a c6 3f  6b 72 cd 7c d7 0e 13 64  |..`....?kr.|...d|
-000002b0  af e8 9f 40 35 e6 fb 04  0c 60 aa 19 61 dd 24 04  |... at 5....`..a.$.|
-000002c0  03 00 8b 30 81 88 02 42  00 9d e1 02 5d 8b b1 45  |...0...B....]..E|
-000002d0  e5 c7 b6 94 27 df 36 31  fd 5e 47 fe c8 0f 5f 17  |....'.61.^G..._.|
-000002e0  b1 92 56 76 29 45 3d 90  be 91 6e 2c a7 b2 e1 33  |..Vv)E=...n,...3|
-000002f0  3b f9 3c bb 80 58 c2 d8  a8 59 82 16 dc 9e dd 60  |;.<..X...Y.....`|
-00000300  ff 82 b9 0c 5a ca ff f3  02 2c 02 42 00 a4 c0 d3  |....Z....,.B....|
-00000310  aa 1d 69 52 c0 06 fa 93  e8 50 da a4 2f 72 c9 4a  |..iR.....P../r.J|
-00000320  2c 43 7f 95 05 f7 7a f3  4a 2e 2d ce 13 be 80 40  |,C....z.J.-....@|
-00000330  a4 3b b2 f0 73 8d f1 d4  7b a3 ff 01 e1 58 71 31  |.;..s...{....Xq1|
-00000340  fc d8 2f b3 ef 62 2e b7  ac f5 c4 bc b8 68 16 03  |../..b.......h..|
+00000270  2a 16 03 03 00 d8 0c 00  00 d4 03 00 17 41 04 7a  |*............A.z|
+00000280  01 b4 2c 50 85 34 6e 2c  2c 52 bc fa cf 71 82 e5  |..,P.4n,,R...q..|
+00000290  98 8d b0 f1 65 5f 7d bc  c8 1b 7c 84 3e 46 45 c5  |....e_}...|.>FE.|
+000002a0  43 0e 72 e1 90 63 40 26  1c 22 dc 9a 3b b8 12 26  |C.r..c@&."..;..&|
+000002b0  a9 d6 1c e1 44 cf c7 38  db 9e 1b d0 b9 bb 06 04  |....D..8........|
+000002c0  03 00 8b 30 81 88 02 42  01 6b af f8 34 ae 89 50  |...0...B.k..4..P|
+000002d0  df 44 20 16 0b f9 ef a9  99 63 39 48 39 08 69 2d  |.D ......c9H9.i-|
+000002e0  2d 9d 8b 3a e8 8a 9c 2f  e9 d2 85 f2 d3 54 53 ec  |-..:.../.....TS.|
+000002f0  b7 18 5b b0 76 3c 38 02  85 cc 00 20 45 9d e7 ba  |..[.v<8.... E...|
+00000300  c0 3f c0 b5 1f df 64 42  fd 34 02 42 00 fa e5 dd  |.?....dB.4.B....|
+00000310  04 c4 60 60 ff 9b 95 a2  a4 b4 80 87 9f 59 b4 8e  |..``.........Y..|
+00000320  72 bf 53 8e 61 b6 df 99  9d 81 05 c5 71 a2 00 cb  |r.S.a.......q...|
+00000330  80 bd e5 2a c3 51 d0 45  2f a3 8b 6d 21 6e 6c 80  |...*.Q.E/..m!nl.|
+00000340  4e f1 28 23 6d 76 df 55  77 69 a1 be 39 05 16 03  |N.(#mv.Uwi..9...|
 00000350  03 00 04 0e 00 00 00                              |.......|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 46 10 00 00  42 41 04 1e 18 37 ef 0d  |....F...BA...7..|
@@ -69,17 +69,17 @@
 00000020  a7 24 20 3e b2 56 1c ce  97 28 5e f8 2b 2d 4f 9e  |.$ >.V...(^.+-O.|
 00000030  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
 00000040  a6 b5 68 1a 41 03 56 6b  dc 5a 89 14 03 03 00 01  |..h.A.Vk.Z......|
-00000050  01 16 03 03 00 28 00 00  00 00 00 00 00 00 83 cf  |.....(..........|
-00000060  ef 50 c2 e7 da b9 74 7f  1c e0 b8 fb dc 39 c9 98  |.P....t......9..|
-00000070  0c a3 7d 8c c6 fa 6f f2  ee 44 a0 a0 03 18        |..}...o..D....|
+00000050  01 16 03 03 00 28 00 00  00 00 00 00 00 00 94 ba  |.....(..........|
+00000060  0a c6 38 6b 65 60 95 5e  df fc 42 7e ac 9f 5a 25  |..8ke`.^..B~..Z%|
+00000070  39 0e a9 7a 61 b3 17 80  77 82 e5 80 0a af        |9..za...w.....|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 28 73 c4 48 24 3d  |..........(s.H$=|
-00000010  8f 5f f3 8c fc fd 63 be  64 39 d5 56 67 bd d7 c4  |._....c.d9.Vg...|
-00000020  0d 57 88 1a 45 a6 f3 ad  11 b2 5a 41 58 33 f3 d3  |.W..E.....ZAX3..|
-00000030  58 fa 21                                          |X.!|
+00000000  14 03 03 00 01 01 16 03  03 00 28 ef 8d ac 17 6f  |..........(....o|
+00000010  88 03 88 8f f3 d5 a0 60  28 a9 4d e8 20 ae 0c 21  |.......`(.M. ..!|
+00000020  fd d1 50 9b c3 d1 e9 cd  27 ed d7 8b 92 60 49 47  |..P.....'....`IG|
+00000030  ed 9a 74                                          |..t|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 65 5e 55  |.............e^U|
-00000010  32 be 00 77 6e 1d 8e 8f  95 33 24 3d 7a c2 b0 3f  |2..wn....3$=z..?|
-00000020  ca aa 97 15 03 03 00 1a  00 00 00 00 00 00 00 02  |................|
-00000030  b2 71 6e 42 6a 0d cf c9  ac 14 a4 b5 9c c9 71 60  |.qnBj.........q`|
-00000040  d7 c2                                             |..|
+00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 1d 4f 3c  |..............O<|
+00000010  c5 d1 39 01 46 ab 7d d1  75 59 e7 f5 cd fa 02 0b  |..9.F.}.uY......|
+00000020  dd 02 17 15 03 03 00 1a  00 00 00 00 00 00 00 02  |................|
+00000030  e9 a5 d5 0c 05 2a 82 fe  a5 6c 03 6e d0 c4 7d cb  |.....*...l.n..}.|
+00000040  32 f3                                             |2.|
diff --git a/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384 b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384
index df2f737..2a16651 100644
--- a/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384
+++ b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-ECDSA-AES256-GCM-SHA384
@@ -1,19 +1,19 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 81 01 00 00  7d 03 03 00 00 00 00 00  |........}.......|
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 36  |...../.5.......6|
-00000050  00 05 00 05 01 00 00 00  00 00 0a 00 08 00 06 00  |................|
-00000060  17 00 18 00 19 00 0b 00  02 01 00 00 0d 00 0e 00  |................|
-00000070  0c 04 01 04 03 05 01 05  03 02 01 02 03 ff 01 00  |................|
-00000080  01 00 00 12 00 00                                 |......|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 11 50 81 a7 ef  |....Y...U...P...|
-00000010  3f bd a5 a9 41 11 e6 86  b2 a3 d8 bf 29 c3 d4 f4  |?...A.......)...|
-00000020  b6 20 2d cb 94 1b 0e dd  99 d1 0b 20 78 92 23 31  |. -........ x.#1|
-00000030  e3 fc 99 67 1f fd f3 2a  fc 9c 4c 74 6e 32 e4 f8  |...g...*..Ltn2..|
-00000040  ed 6d 2e 6d ad a9 a9 bf  63 27 7e 44 c0 2c 00 00  |.m.m....c'~D.,..|
+00000000  16 03 03 00 59 02 00 00  55 03 03 ed 6d 5a 1c 89  |....Y...U...mZ..|
+00000010  a4 f3 35 0b e4 74 7e e2  05 a5 36 4d 4a 55 b3 7c  |..5..t~...6MJU.||
+00000020  a1 a6 42 a3 fc 35 8c e0  97 5b 4b 20 a1 4a 06 28  |..B..5...[K .J.(|
+00000030  4d 40 0b fc 47 d5 4d 9b  d5 43 b0 0d 0d c6 ae 30  |M at ..G.M..C.....0|
+00000040  79 59 00 d4 90 96 98 92  d2 3a 57 07 c0 2c 00 00  |yY.......:W..,..|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
 00000060  03 02 0e 0b 00 02 0a 00  02 07 00 02 04 30 82 02  |.............0..|
 00000070  00 30 82 01 62 02 09 00  b8 bf 2d 47 a0 d2 eb f4  |.0..b.....-G....|
@@ -48,20 +48,20 @@
 00000240  13 83 0d 94 06 bb d4 37  7a f6 ec 7a c9 86 2e dd  |.......7z..z....|
 00000250  d7 11 69 7f 85 7c 56 de  fb 31 78 2b e4 c7 78 0d  |..i..|V..1x+..x.|
 00000260  ae cb be 9e 4e 36 24 31  7b 6a 0f 39 95 12 07 8f  |....N6$1{j.9....|
-00000270  2a 16 03 03 00 d7 0c 00  00 d3 03 00 17 41 04 fc  |*............A..|
-00000280  e6 25 27 3c 76 10 a8 9e  d3 a4 a8 68 31 06 85 fc  |.%'<v......h1...|
-00000290  35 2a 76 b3 ad 08 c5 70  ed 3d 61 e0 29 cc 47 52  |5*v....p.=a.).GR|
-000002a0  68 21 ab 48 19 f9 28 ba  54 8c 56 8e b0 7d 55 7f  |h!.H..(.T.V..}U.|
-000002b0  75 f5 42 38 61 ff e2 06  98 1a ae fc bc a0 3a 04  |u.B8a.........:.|
-000002c0  03 00 8a 30 81 87 02 42  01 0c b2 7f c9 d3 1b 83  |...0...B........|
-000002d0  1e 24 a3 d7 1c 81 f0 02  ae ed 42 6f e9 d9 91 4d  |.$........Bo...M|
-000002e0  16 5f aa 8e 5a de 3b 00  0e e6 2d fb 05 30 f3 cf  |._..Z.;...-..0..|
-000002f0  31 a2 ec 99 87 ea 42 03  0a 57 82 e5 12 27 98 8a  |1.....B..W...'..|
-00000300  c6 56 4b 9a 0b d7 37 5f  46 50 02 41 57 61 13 3c  |.VK...7_FP.AWa.<|
-00000310  48 d0 b3 b0 d5 21 72 49  80 7b d7 ef 8f 0d a0 c5  |H....!rI.{......|
-00000320  88 a1 5d ca 61 6d fb 8b  51 15 5d e5 a2 61 c4 78  |..].am..Q.]..a.x|
-00000330  8f d9 e3 78 df 7d a0 8f  0c c0 cc 18 36 41 e6 bb  |...x.}......6A..|
-00000340  6d e3 9d 04 c2 c4 d0 66  35 45 9a 08 b2 16 03 03  |m......f5E......|
+00000270  2a 16 03 03 00 d7 0c 00  00 d3 03 00 17 41 04 89  |*............A..|
+00000280  e6 6d 6a 56 3e e5 4e 72  df 2b 41 11 de a0 c0 3e  |.mjV>.Nr.+A....>|
+00000290  22 04 9a b5 a8 d6 22 30  2a e5 bd 83 1c 7a 8e 6c  |"....."0*....z.l|
+000002a0  93 ab 8f d7 64 9e fe 89  c0 da 9a 45 7d 76 91 69  |....d......E}v.i|
+000002b0  0a 11 c5 59 26 49 ec 69  99 b3 91 a5 4b 2b 89 04  |...Y&I.i....K+..|
+000002c0  03 00 8a 30 81 87 02 42  01 17 1d ff 9a 99 76 20  |...0...B......v |
+000002d0  13 8a e1 5a a8 04 8a 1e  84 57 fd b0 95 c1 6c af  |...Z.....W....l.|
+000002e0  b2 66 13 b5 75 36 ce 86  69 67 3d dc 82 2f 06 57  |.f..u6..ig=../.W|
+000002f0  19 14 56 54 0e 8e 04 74  0b 73 49 61 92 8e d1 9a  |..VT...t.sIa....|
+00000300  b5 60 7f 65 a8 f8 99 eb  ac 56 02 41 57 a3 78 57  |.`.e.....V.AW.xW|
+00000310  8a dd fa 9c 3d 24 a0 f2  0a 74 1a 8a 8f 6c 82 55  |....=$...t...l.U|
+00000320  4c cd d8 5d 79 99 87 93  41 e7 78 f4 28 0d ef 63  |L..]y...A.x.(..c|
+00000330  fb da 8e 93 86 31 6e 3e  ca 6f 6b 1b fd 7a a3 86  |.....1n>.ok..z..|
+00000340  6e bb 17 35 90 d9 a4 df  12 d0 54 5e 25 16 03 03  |n..5......T^%...|
 00000350  00 04 0e 00 00 00                                 |......|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 46 10 00 00  42 41 04 1e 18 37 ef 0d  |....F...BA...7..|
@@ -69,17 +69,17 @@
 00000020  a7 24 20 3e b2 56 1c ce  97 28 5e f8 2b 2d 4f 9e  |.$ >.V...(^.+-O.|
 00000030  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
 00000040  a6 b5 68 1a 41 03 56 6b  dc 5a 89 14 03 03 00 01  |..h.A.Vk.Z......|
-00000050  01 16 03 03 00 28 00 00  00 00 00 00 00 00 a3 3f  |.....(.........?|
-00000060  be 65 91 cd fe 37 43 e0  ea 6f 15 9d c2 aa 6a 02  |.e...7C..o....j.|
-00000070  20 b8 bc b5 c8 9a 1c d4  c4 e5 9b 2e 39 e7        | ...........9.|
+00000050  01 16 03 03 00 28 00 00  00 00 00 00 00 00 9d e7  |.....(..........|
+00000060  31 2a 0a 46 84 fd d9 18  c2 b0 b1 31 eb 63 4d 2d  |1*.F.......1.cM-|
+00000070  ee 17 59 e6 b4 0f c6 d8  3d 8c e9 57 83 a8        |..Y.....=..W..|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 28 7c b7 1f 13 9e  |..........(|....|
-00000010  21 d2 eb db 32 fc 36 d0  53 e1 11 04 ce d0 61 33  |!...2.6.S.....a3|
-00000020  1e 30 3d 91 c3 6a 0d 98  55 f5 e0 5c ca 77 fa 72  |.0=..j..U..\.w.r|
-00000030  63 6a be                                          |cj.|
+00000000  14 03 03 00 01 01 16 03  03 00 28 e0 85 25 02 b4  |..........(..%..|
+00000010  86 32 57 70 3c 7e 6b e5  75 e0 3a 43 c8 c2 fe f8  |.2Wp<~k.u.:C....|
+00000020  2e 04 fe 73 e4 7b 2c 9a  e0 65 2e d6 53 ae f1 19  |...s.{,..e..S...|
+00000030  dd 6f 1a                                          |.o.|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 d9 db db  |................|
-00000010  4b 3a ae 5c a4 dc 96 33  ed b5 a0 70 64 1f 96 2f  |K:.\...3...pd../|
-00000020  b6 cd 1e 15 03 03 00 1a  00 00 00 00 00 00 00 02  |................|
-00000030  18 a0 d1 98 a6 71 c9 56  36 bd 1a 46 4b 5b 45 29  |.....q.V6..FK[E)|
-00000040  1f dd                                             |..|
+00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 29 b2 e6  |.............)..|
+00000010  c3 2e 72 ba cc ac d9 3b  c7 0c 1d 53 b2 30 39 71  |..r....;...S.09q|
+00000020  6e dd 79 15 03 03 00 1a  00 00 00 00 00 00 00 02  |n.y.............|
+00000030  88 c9 92 fe 6c 1f 6c fd  bd 7b fb 0a 8a b5 cc c9  |....l.l..{......|
+00000040  94 90                                             |..|
diff --git a/src/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES
index 994ebb1..29767b7 100644
--- a/src/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES
+++ b/src/crypto/tls/testdata/Client-TLSv12-ECDHE-RSA-AES
@@ -1,78 +1,73 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 81 01 00 00  7d 03 03 00 00 00 00 00  |........}.......|
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 36  |...../.5.......6|
-00000050  00 05 00 05 01 00 00 00  00 00 0a 00 08 00 06 00  |................|
-00000060  17 00 18 00 19 00 0b 00  02 01 00 00 0d 00 0e 00  |................|
-00000070  0c 04 01 04 03 05 01 05  03 02 01 02 03 ff 01 00  |................|
-00000080  01 00 00 12 00 00                                 |......|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 59 02 00 00  55 03 03 e6 ae 89 0d 22  |....Y...U......"|
-00000010  e5 e0 cd 57 a3 ca 71 4f  17 2f 64 77 f8 30 89 ef  |...W..qO./dw.0..|
-00000020  e8 19 70 ac dd 2c c5 9f  84 7d 1d 20 1c 59 3c fe  |..p..,...}. .Y<.|
-00000030  a9 ec 10 dd 38 3b 43 fe  6b 09 e5 e4 83 d9 7a 78  |....8;C.k.....zx|
-00000040  86 08 33 da 9b e1 09 d8  c9 07 34 19 c0 13 00 00  |..3.......4.....|
+00000000  16 03 03 00 59 02 00 00  55 03 03 2a 6a a8 b3 97  |....Y...U..*j...|
+00000010  d5 c8 5e b4 22 7e d0 a5  c7 46 af 89 60 44 77 5e  |..^."~...F..`Dw^|
+00000020  1a f8 3a 30 08 6d 5f 4c  61 36 c5 20 57 79 91 3e  |..:0.m_La6. Wy.>|
+00000030  1f 40 d1 f1 33 d7 a9 fb  93 eb 16 0d e1 39 e3 a3  |. at ..3........9..|
+00000040  80 e3 4f 58 a6 f8 a4 be  19 dd ef ee c0 13 00 00  |..OX............|
 00000050  0d ff 01 00 01 00 00 0b  00 04 03 00 01 02 16 03  |................|
-00000060  03 02 be 0b 00 02 ba 00  02 b7 00 02 b4 30 82 02  |.............0..|
-00000070  b0 30 82 02 19 a0 03 02  01 02 02 09 00 85 b0 bb  |.0..............|
-00000080  a4 8a 7f b8 ca 30 0d 06  09 2a 86 48 86 f7 0d 01  |.....0...*.H....|
-00000090  01 05 05 00 30 45 31 0b  30 09 06 03 55 04 06 13  |....0E1.0...U...|
-000000a0  02 41 55 31 13 30 11 06  03 55 04 08 13 0a 53 6f  |.AU1.0...U....So|
-000000b0  6d 65 2d 53 74 61 74 65  31 21 30 1f 06 03 55 04  |me-State1!0...U.|
-000000c0  0a 13 18 49 6e 74 65 72  6e 65 74 20 57 69 64 67  |...Internet Widg|
-000000d0  69 74 73 20 50 74 79 20  4c 74 64 30 1e 17 0d 31  |its Pty Ltd0...1|
-000000e0  30 30 34 32 34 30 39 30  39 33 38 5a 17 0d 31 31  |00424090938Z..11|
-000000f0  30 34 32 34 30 39 30 39  33 38 5a 30 45 31 0b 30  |0424090938Z0E1.0|
-00000100  09 06 03 55 04 06 13 02  41 55 31 13 30 11 06 03  |...U....AU1.0...|
-00000110  55 04 08 13 0a 53 6f 6d  65 2d 53 74 61 74 65 31  |U....Some-State1|
-00000120  21 30 1f 06 03 55 04 0a  13 18 49 6e 74 65 72 6e  |!0...U....Intern|
-00000130  65 74 20 57 69 64 67 69  74 73 20 50 74 79 20 4c  |et Widgits Pty L|
-00000140  74 64 30 81 9f 30 0d 06  09 2a 86 48 86 f7 0d 01  |td0..0...*.H....|
-00000150  01 01 05 00 03 81 8d 00  30 81 89 02 81 81 00 bb  |........0.......|
-00000160  79 d6 f5 17 b5 e5 bf 46  10 d0 dc 69 be e6 2b 07  |y......F...i..+.|
-00000170  43 5a d0 03 2d 8a 7a 43  85 b7 14 52 e7 a5 65 4c  |CZ..-.zC...R..eL|
-00000180  2c 78 b8 23 8c b5 b4 82  e5 de 1f 95 3b 7e 62 a5  |,x.#........;~b.|
-00000190  2c a5 33 d6 fe 12 5c 7a  56 fc f5 06 bf fa 58 7b  |,.3...\zV.....X{|
-000001a0  26 3f b5 cd 04 d3 d0 c9  21 96 4a c7 f4 54 9f 5a  |&?......!.J..T.Z|
-000001b0  bf ef 42 71 00 fe 18 99  07 7f 7e 88 7d 7d f1 04  |..Bq......~.}}..|
-000001c0  39 c4 a2 2e db 51 c9 7c  e3 c0 4c 3b 32 66 01 cf  |9....Q.|..L;2f..|
-000001d0  af b1 1d b8 71 9a 1d db  db 89 6b ae da 2d 79 02  |....q.....k..-y.|
-000001e0  03 01 00 01 a3 81 a7 30  81 a4 30 1d 06 03 55 1d  |.......0..0...U.|
-000001f0  0e 04 16 04 14 b1 ad e2  85 5a cf cb 28 db 69 ce  |.........Z..(.i.|
-00000200  23 69 de d3 26 8e 18 88  39 30 75 06 03 55 1d 23  |#i..&...90u..U.#|
-00000210  04 6e 30 6c 80 14 b1 ad  e2 85 5a cf cb 28 db 69  |.n0l......Z..(.i|
-00000220  ce 23 69 de d3 26 8e 18  88 39 a1 49 a4 47 30 45  |.#i..&...9.I.G0E|
-00000230  31 0b 30 09 06 03 55 04  06 13 02 41 55 31 13 30  |1.0...U....AU1.0|
-00000240  11 06 03 55 04 08 13 0a  53 6f 6d 65 2d 53 74 61  |...U....Some-Sta|
-00000250  74 65 31 21 30 1f 06 03  55 04 0a 13 18 49 6e 74  |te1!0...U....Int|
-00000260  65 72 6e 65 74 20 57 69  64 67 69 74 73 20 50 74  |ernet Widgits Pt|
-00000270  79 20 4c 74 64 82 09 00  85 b0 bb a4 8a 7f b8 ca  |y Ltd...........|
-00000280  30 0c 06 03 55 1d 13 04  05 30 03 01 01 ff 30 0d  |0...U....0....0.|
-00000290  06 09 2a 86 48 86 f7 0d  01 01 05 05 00 03 81 81  |..*.H...........|
-000002a0  00 08 6c 45 24 c7 6b b1  59 ab 0c 52 cc f2 b0 14  |..lE$.k.Y..R....|
-000002b0  d7 87 9d 7a 64 75 b5 5a  95 66 e4 c5 2b 8e ae 12  |...zdu.Z.f..+...|
-000002c0  66 1f eb 4f 38 b3 6e 60  d3 92 fd f7 41 08 b5 25  |f..O8.n`....A..%|
-000002d0  13 b1 18 7a 24 fb 30 1d  ba ed 98 b9 17 ec e7 d7  |...z$.0.........|
-000002e0  31 59 db 95 d3 1d 78 ea  50 56 5c d5 82 5a 2d 5a  |1Y....x.PV\..Z-Z|
-000002f0  5f 33 c4 b6 d8 c9 75 90  96 8c 0f 52 98 b5 cd 98  |_3....u....R....|
-00000300  1f 89 20 5f f2 a0 1c a3  1b 96 94 dd a9 fd 57 e9  |.. _..........W.|
-00000310  70 e8 26 6d 71 99 9b 26  6e 38 50 29 6c 90 a7 bd  |p.&mq..&n8P)l...|
-00000320  d9 16 03 03 00 cd 0c 00  00 c9 03 00 17 41 04 77  |.............A.w|
-00000330  87 a7 ad f6 f8 34 82 05  ef bb 14 6d c7 8b 7b 2a  |.....4.....m..{*|
-00000340  4d ca 41 65 58 3c 83 fa  4d ce 0c 74 46 85 fe 38  |M.AeX<..M..tF..8|
-00000350  95 80 ee 7c c2 bf f2 be  a3 c6 bf f3 aa 07 23 40  |...|..........#@|
-00000360  7e cc 74 4a 4e 2e 69 af  6b e0 42 8a fc 41 be 04  |~.tJN.i.k.B..A..|
-00000370  01 00 80 99 ed a8 3a ef  93 1b 4c 17 80 9e cc eb  |......:...L.....|
-00000380  da 39 fb c8 9a 73 e1 96  20 3e 41 fa 8b 1a b1 68  |.9...s.. >A....h|
-00000390  cd 47 bc 4b 7b 0c 14 da  87 d3 36 09 5e 37 33 88  |.G.K{.....6.^73.|
-000003a0  7f 88 07 87 46 ec e5 72  a8 59 92 07 fa 4d 02 dc  |....F..r.Y...M..|
-000003b0  bf 3a f5 e4 77 0b a6 85  ce 43 ee 1b 90 30 7f ec  |.:..w....C...0..|
-000003c0  88 79 f8 88 59 af 6b 7f  2d 88 de 92 cd c8 36 cf  |.y..Y.k.-.....6.|
-000003d0  ba b9 08 6a c4 3d d7 9a  48 50 e1 67 d0 62 a5 b3  |...j.=..HP.g.b..|
-000003e0  b0 5f 2e 16 ee 4d 7d a2  cf d9 93 19 89 b7 64 0f  |._...M}.......d.|
-000003f0  0f 8e 3d 16 03 03 00 04  0e 00 00 00              |..=.........|
+00000060  03 02 71 0b 00 02 6d 00  02 6a 00 02 67 30 82 02  |..q...m..j..g0..|
+00000070  63 30 82 01 cc a0 03 02  01 02 02 09 00 a2 73 00  |c0............s.|
+00000080  0c 81 00 cb f3 30 0d 06  09 2a 86 48 86 f7 0d 01  |.....0...*.H....|
+00000090  01 0b 05 00 30 2b 31 17  30 15 06 03 55 04 0a 13  |....0+1.0...U...|
+000000a0  0e 47 6f 6f 67 6c 65 20  54 45 53 54 49 4e 47 31  |.Google TESTING1|
+000000b0  10 30 0e 06 03 55 04 03  13 07 47 6f 20 52 6f 6f  |.0...U....Go Roo|
+000000c0  74 30 1e 17 0d 31 35 30  31 30 31 30 30 30 30 30  |t0...15010100000|
+000000d0  30 5a 17 0d 32 35 30 31  30 31 30 30 30 30 30 30  |0Z..250101000000|
+000000e0  5a 30 26 31 17 30 15 06  03 55 04 0a 13 0e 47 6f  |Z0&1.0...U....Go|
+000000f0  6f 67 6c 65 20 54 45 53  54 49 4e 47 31 0b 30 09  |ogle TESTING1.0.|
+00000100  06 03 55 04 03 13 02 47  6f 30 81 9f 30 0d 06 09  |..U....Go0..0...|
+00000110  2a 86 48 86 f7 0d 01 01  01 05 00 03 81 8d 00 30  |*.H............0|
+00000120  81 89 02 81 81 00 af 87  88 f6 20 1b 95 65 6c 14  |.......... ..el.|
+00000130  ab 44 05 af 3b 45 14 e3  b7 6d fd 00 63 4d 95 7f  |.D..;E...m..cM..|
+00000140  fe 6a 62 35 86 c0 4a f9  18 7c f6 aa 25 5e 7a 64  |.jb5..J..|..%^zd|
+00000150  31 66 00 ba f4 8e 92 af  c7 6b d8 76 d4 f3 5f 41  |1f.......k.v.._A|
+00000160  cb 6e 56 15 97 1b 97 c1  3c 12 39 21 66 3d 2b 16  |.nV.....<.9!f=+.|
+00000170  d1 bc db 1c c0 a7 da b7  ca ad ba da cb d5 21 50  |..............!P|
+00000180  ec de 8d ab d1 6b 81 4b  89 02 f3 c4 be c1 6c 89  |.....k.K......l.|
+00000190  b1 44 84 bd 21 d1 04 7d  9d 16 4d f9 82 15 f6 ef  |.D..!..}..M.....|
+000001a0  fa d6 09 47 f2 fb 02 03  01 00 01 a3 81 93 30 81  |...G..........0.|
+000001b0  90 30 0e 06 03 55 1d 0f  01 01 ff 04 04 03 02 05  |.0...U..........|
+000001c0  a0 30 1d 06 03 55 1d 25  04 16 30 14 06 08 2b 06  |.0...U.%..0...+.|
+000001d0  01 05 05 07 03 01 06 08  2b 06 01 05 05 07 03 02  |........+.......|
+000001e0  30 0c 06 03 55 1d 13 01  01 ff 04 02 30 00 30 19  |0...U.......0.0.|
+000001f0  06 03 55 1d 0e 04 12 04  10 12 50 8d 89 6f 1b d1  |..U.......P..o..|
+00000200  dc 54 4d 6e cb 69 5e 06  f4 30 1b 06 03 55 1d 23  |.TMn.i^..0...U.#|
+00000210  04 14 30 12 80 10 bf 3d  b6 a9 66 f2 b8 40 cf ea  |..0....=..f.. at ..|
+00000220  b4 03 78 48 1a 41 30 19  06 03 55 1d 11 04 12 30  |..xH.A0...U....0|
+00000230  10 82 0e 65 78 61 6d 70  6c 65 2e 67 6f 6c 61 6e  |...example.golan|
+00000240  67 30 0d 06 09 2a 86 48  86 f7 0d 01 01 0b 05 00  |g0...*.H........|
+00000250  03 81 81 00 92 7c af 91  55 12 18 96 59 31 a6 48  |.....|..U...Y1.H|
+00000260  40 d5 2d d5 ee bb 02 a0  f5 c2 1e 7c 9b b3 30 7d  |@.-........|..0}|
+00000270  3c dc 76 da 4f 3d c0 fa  ae 2d 33 24 6b 03 7b 1b  |<.v.O=...-3$k.{.|
+00000280  67 59 11 21 b5 11 bc 77  b9 d9 e0 6e a8 2d 2e 35  |gY.!...w...n.-.5|
+00000290  fa 64 5f 22 3e 63 10 6b  be ff 14 86 6d 0d f0 15  |.d_">c.k....m...|
+000002a0  31 a8 14 38 1e 3b 84 87  2c cb 98 ed 51 76 b9 b1  |1..8.;..,...Qv..|
+000002b0  4f dd db 9b 84 04 86 40  fa 51 dd ba b4 8d eb e3  |O...... at .Q......|
+000002c0  46 de 46 b9 4f 86 c7 f9  a4 c2 41 34 ac cc f6 ea  |F.F.O.....A4....|
+000002d0  b0 ab 39 18 16 03 03 00  cd 0c 00 00 c9 03 00 17  |..9.............|
+000002e0  41 04 8e c8 e8 42 7c 8a  01 c2 ff 01 cb 0b e1 20  |A....B|........ |
+000002f0  50 42 d4 3a 1b 34 ff 74  59 81 2f a2 0e 29 b2 f9  |PB.:.4.tY./..)..|
+00000300  47 cf 0d 08 97 cf aa 9f  fe f0 7f e8 f4 fd 3a fa  |G.............:.|
+00000310  a6 b6 47 32 d3 25 78 87  bf 77 cc 12 37 02 6a ad  |..G2.%x..w..7.j.|
+00000320  cf 2c 04 01 00 80 13 a1  95 17 7b 21 86 7f f2 02  |.,........{!....|
+00000330  9f ed 88 2d 1f 2c 38 96  bc fa 5a 39 85 4b 9f ff  |...-.,8...Z9.K..|
+00000340  5c 7a 02 1e 5f c9 4a 69  51 d3 83 34 9f dc 8c 39  |\z.._.JiQ..4...9|
+00000350  fe 81 76 fc c3 59 ff e2  a8 81 ca 6f f6 52 c9 44  |..v..Y.....o.R.D|
+00000360  a0 3f 5e 5e 92 20 db d9  2e 0b e3 ab 75 e7 79 f6  |.?^^. ......u.y.|
+00000370  b2 73 17 e1 94 1e 12 62  e9 b0 0f 04 e7 5d 83 ac  |.s.....b.....]..|
+00000380  71 ca a5 62 40 dd 69 b1  3f cf bb 3d c7 3e 51 6c  |q..b at .i.?..=.>Ql|
+00000390  11 f2 cf 39 f1 b5 72 bd  52 d4 3d 3c c0 90 34 c8  |...9..r.R.=<..4.|
+000003a0  4b 22 55 39 1c 2b 16 03  03 00 04 0e 00 00 00     |K"U9.+.........|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 46 10 00 00  42 41 04 1e 18 37 ef 0d  |....F...BA...7..|
 00000010  19 51 88 35 75 71 b5 e5  54 5b 12 2e 8f 09 67 fd  |.Q.5uq..T[....g.|
@@ -80,21 +75,21 @@
 00000030  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
 00000040  a6 b5 68 1a 41 03 56 6b  dc 5a 89 14 03 03 00 01  |..h.A.Vk.Z......|
 00000050  01 16 03 03 00 40 00 00  00 00 00 00 00 00 00 00  |..... at ..........|
-00000060  00 00 00 00 00 00 f2 20  58 ec f1 88 a6 26 79 9d  |....... X....&y.|
-00000070  2e 9b 02 b5 5e da e2 c1  c5 8d c8 93 6f 6d 07 4e  |....^.......om.N|
-00000080  fa dd ee cb b1 ae c7 3b  09 b2 cc 64 7a cd 98 91  |.......;...dz...|
-00000090  cb f8 3c 34 3b ed                                 |..<4;.|
+00000060  00 00 00 00 00 00 a2 6e  de ea 78 0c 4d 20 ad 1f  |.......n..x.M ..|
+00000070  1a f5 6b 15 09 f1 50 bb  cd 40 0e c7 d9 ed 7f e1  |..k...P.. at ......|
+00000080  4b bc d3 26 5d 89 b7 26  c5 6c 0e 59 6f 84 51 5d  |K..&]..&.l.Yo.Q]|
+00000090  2f 75 d8 0f 2e e8                                 |/u....|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 40 4c a1 8d bd 49  |.......... at L...I|
-00000010  33 d3 72 fb 2f 23 7e 11  29 fc d2 ff 9b 67 30 c8  |3.r./#~.)....g0.|
-00000020  be c1 bc 51 6e 92 a5 f4  9d e3 b3 f9 d2 d4 c4 a5  |...Qn...........|
-00000030  83 23 90 b3 17 00 35 18  c5 ef 8b 18 a3 cf ed 9d  |.#....5.........|
-00000040  a9 52 c9 11 0a c9 55 c2  76 df 78                 |.R....U.v.x|
+00000000  14 03 03 00 01 01 16 03  03 00 40 dd d8 e7 63 89  |.......... at ...c.|
+00000010  8e cc 3e e0 df 6d 5a 42  b3 49 1b 66 e8 79 e9 f0  |..>..mZB.I.f.y..|
+00000020  8a c3 0e 5e d7 01 ac 04  81 6a e1 60 14 60 b9 a6  |...^.....j.`.`..|
+00000030  4c a5 46 43 74 df 30 1e  f8 74 77 4c b5 42 e5 25  |L.FCt.0..twL.B.%|
+00000040  81 9d b1 04 bc 02 46 bd  b1 55 d0                 |......F..U.|
 >>> Flow 5 (client to server)
 00000000  17 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
-00000010  00 00 00 00 00 60 40 d0  bf 8f ef 05 2b 89 d7 bb  |.....`@.....+...|
-00000020  27 d0 1f b2 cf c3 ff 8e  be 69 16 a9 b3 03 e8 3c  |'........i.....<|
-00000030  30 1d 58 39 4a 15 03 03  00 30 00 00 00 00 00 00  |0.X9J....0......|
-00000040  00 00 00 00 00 00 00 00  00 00 de 61 51 a1 3c fc  |...........aQ.<.|
-00000050  1c 7b e6 f2 7d e0 aa 80  2d 9c e9 22 09 5c dd 8a  |.{..}...-..".\..|
-00000060  55 cc c4 77 34 97 05 88  98 d3                    |U..w4.....|
+00000010  00 00 00 00 00 35 49 6d  a7 3f a1 39 5d 37 8d 2e  |.....5Im.?.9]7..|
+00000020  c5 1e 90 3b f9 60 58 d3  47 e3 db 73 8b aa 6c 9e  |...;.`X.G..s..l.|
+00000030  b5 82 55 09 62 15 03 03  00 30 00 00 00 00 00 00  |..U.b....0......|
+00000040  00 00 00 00 00 00 00 00  00 00 71 b3 7b c7 d4 27  |..........q.{..'|
+00000050  f9 77 7f d0 80 25 1b 43  d0 0e 92 38 8c f3 2f 50  |.w...%.C...8../P|
+00000060  eb 96 22 fb e6 09 45 ec  7f 16                    |.."...E...|
diff --git a/src/crypto/tls/testdata/Client-TLSv12-RSA-RC4 b/src/crypto/tls/testdata/Client-TLSv12-RSA-RC4
index 73e34c0..ffdc328 100644
--- a/src/crypto/tls/testdata/Client-TLSv12-RSA-RC4
+++ b/src/crypto/tls/testdata/Client-TLSv12-RSA-RC4
@@ -1,84 +1,79 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 81 01 00 00  7d 03 03 00 00 00 00 00  |........}.......|
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 36  |...../.5.......6|
-00000050  00 05 00 05 01 00 00 00  00 00 0a 00 08 00 06 00  |................|
-00000060  17 00 18 00 19 00 0b 00  02 01 00 00 0d 00 0e 00  |................|
-00000070  0c 04 01 04 03 05 01 05  03 02 01 02 03 ff 01 00  |................|
-00000080  01 00 00 12 00 00                                 |......|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
 >>> Flow 2 (server to client)
-00000000  16 03 03 00 51 02 00 00  4d 03 03 e8 ae 4c 97 41  |....Q...M....L.A|
-00000010  78 0f 08 84 d4 4a 80 6d  a2 e1 d0 67 40 8f 01 8b  |x....J.m...g at ...|
-00000020  20 54 cb 28 16 52 04 fd  3c c2 84 20 30 96 f0 51  | T.(.R..<.. 0..Q|
-00000030  72 86 6a d8 47 b9 47 e3  a4 ad 97 77 a9 77 1a f9  |r.j.G.G....w.w..|
-00000040  ba 63 33 32 4f 43 09 1c  e1 bd 1b 3b 00 05 00 00  |.c32OC.....;....|
-00000050  05 ff 01 00 01 00 16 03  03 02 be 0b 00 02 ba 00  |................|
-00000060  02 b7 00 02 b4 30 82 02  b0 30 82 02 19 a0 03 02  |.....0...0......|
-00000070  01 02 02 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0d 06  |.............0..|
-00000080  09 2a 86 48 86 f7 0d 01  01 05 05 00 30 45 31 0b  |.*.H........0E1.|
-00000090  30 09 06 03 55 04 06 13  02 41 55 31 13 30 11 06  |0...U....AU1.0..|
-000000a0  03 55 04 08 13 0a 53 6f  6d 65 2d 53 74 61 74 65  |.U....Some-State|
-000000b0  31 21 30 1f 06 03 55 04  0a 13 18 49 6e 74 65 72  |1!0...U....Inter|
-000000c0  6e 65 74 20 57 69 64 67  69 74 73 20 50 74 79 20  |net Widgits Pty |
-000000d0  4c 74 64 30 1e 17 0d 31  30 30 34 32 34 30 39 30  |Ltd0...100424090|
-000000e0  39 33 38 5a 17 0d 31 31  30 34 32 34 30 39 30 39  |938Z..1104240909|
-000000f0  33 38 5a 30 45 31 0b 30  09 06 03 55 04 06 13 02  |38Z0E1.0...U....|
-00000100  41 55 31 13 30 11 06 03  55 04 08 13 0a 53 6f 6d  |AU1.0...U....Som|
-00000110  65 2d 53 74 61 74 65 31  21 30 1f 06 03 55 04 0a  |e-State1!0...U..|
-00000120  13 18 49 6e 74 65 72 6e  65 74 20 57 69 64 67 69  |..Internet Widgi|
-00000130  74 73 20 50 74 79 20 4c  74 64 30 81 9f 30 0d 06  |ts Pty Ltd0..0..|
-00000140  09 2a 86 48 86 f7 0d 01  01 01 05 00 03 81 8d 00  |.*.H............|
-00000150  30 81 89 02 81 81 00 bb  79 d6 f5 17 b5 e5 bf 46  |0.......y......F|
-00000160  10 d0 dc 69 be e6 2b 07  43 5a d0 03 2d 8a 7a 43  |...i..+.CZ..-.zC|
-00000170  85 b7 14 52 e7 a5 65 4c  2c 78 b8 23 8c b5 b4 82  |...R..eL,x.#....|
-00000180  e5 de 1f 95 3b 7e 62 a5  2c a5 33 d6 fe 12 5c 7a  |....;~b.,.3...\z|
-00000190  56 fc f5 06 bf fa 58 7b  26 3f b5 cd 04 d3 d0 c9  |V.....X{&?......|
-000001a0  21 96 4a c7 f4 54 9f 5a  bf ef 42 71 00 fe 18 99  |!.J..T.Z..Bq....|
-000001b0  07 7f 7e 88 7d 7d f1 04  39 c4 a2 2e db 51 c9 7c  |..~.}}..9....Q.||
-000001c0  e3 c0 4c 3b 32 66 01 cf  af b1 1d b8 71 9a 1d db  |..L;2f......q...|
-000001d0  db 89 6b ae da 2d 79 02  03 01 00 01 a3 81 a7 30  |..k..-y........0|
-000001e0  81 a4 30 1d 06 03 55 1d  0e 04 16 04 14 b1 ad e2  |..0...U.........|
-000001f0  85 5a cf cb 28 db 69 ce  23 69 de d3 26 8e 18 88  |.Z..(.i.#i..&...|
-00000200  39 30 75 06 03 55 1d 23  04 6e 30 6c 80 14 b1 ad  |90u..U.#.n0l....|
-00000210  e2 85 5a cf cb 28 db 69  ce 23 69 de d3 26 8e 18  |..Z..(.i.#i..&..|
-00000220  88 39 a1 49 a4 47 30 45  31 0b 30 09 06 03 55 04  |.9.I.G0E1.0...U.|
-00000230  06 13 02 41 55 31 13 30  11 06 03 55 04 08 13 0a  |...AU1.0...U....|
-00000240  53 6f 6d 65 2d 53 74 61  74 65 31 21 30 1f 06 03  |Some-State1!0...|
-00000250  55 04 0a 13 18 49 6e 74  65 72 6e 65 74 20 57 69  |U....Internet Wi|
-00000260  64 67 69 74 73 20 50 74  79 20 4c 74 64 82 09 00  |dgits Pty Ltd...|
-00000270  85 b0 bb a4 8a 7f b8 ca  30 0c 06 03 55 1d 13 04  |........0...U...|
-00000280  05 30 03 01 01 ff 30 0d  06 09 2a 86 48 86 f7 0d  |.0....0...*.H...|
-00000290  01 01 05 05 00 03 81 81  00 08 6c 45 24 c7 6b b1  |..........lE$.k.|
-000002a0  59 ab 0c 52 cc f2 b0 14  d7 87 9d 7a 64 75 b5 5a  |Y..R.......zdu.Z|
-000002b0  95 66 e4 c5 2b 8e ae 12  66 1f eb 4f 38 b3 6e 60  |.f..+...f..O8.n`|
-000002c0  d3 92 fd f7 41 08 b5 25  13 b1 18 7a 24 fb 30 1d  |....A..%...z$.0.|
-000002d0  ba ed 98 b9 17 ec e7 d7  31 59 db 95 d3 1d 78 ea  |........1Y....x.|
-000002e0  50 56 5c d5 82 5a 2d 5a  5f 33 c4 b6 d8 c9 75 90  |PV\..Z-Z_3....u.|
-000002f0  96 8c 0f 52 98 b5 cd 98  1f 89 20 5f f2 a0 1c a3  |...R...... _....|
-00000300  1b 96 94 dd a9 fd 57 e9  70 e8 26 6d 71 99 9b 26  |......W.p.&mq..&|
-00000310  6e 38 50 29 6c 90 a7 bd  d9 16 03 03 00 04 0e 00  |n8P)l...........|
-00000320  00 00                                             |..|
+00000000  16 03 03 00 51 02 00 00  4d 03 03 79 8f 56 ac 75  |....Q...M..y.V.u|
+00000010  4f a9 fc 2c b9 53 82 a6  b4 c8 0d 4e 50 9a 9e aa  |O..,.S.....NP...|
+00000020  8d ed 21 21 91 5d a2 cc  99 1b 68 20 0c e7 35 50  |..!!.]....h ..5P|
+00000030  67 02 70 2a 45 0d 6c 4c  46 df 75 dc 5f 6e 2f 79  |g.p*E.lLF.u._n/y|
+00000040  03 26 da 45 53 25 50 23  c0 85 3b 8c 00 05 00 00  |.&.ES%P#..;.....|
+00000050  05 ff 01 00 01 00 16 03  03 02 71 0b 00 02 6d 00  |..........q...m.|
+00000060  02 6a 00 02 67 30 82 02  63 30 82 01 cc a0 03 02  |.j..g0..c0......|
+00000070  01 02 02 09 00 a2 73 00  0c 81 00 cb f3 30 0d 06  |......s......0..|
+00000080  09 2a 86 48 86 f7 0d 01  01 0b 05 00 30 2b 31 17  |.*.H........0+1.|
+00000090  30 15 06 03 55 04 0a 13  0e 47 6f 6f 67 6c 65 20  |0...U....Google |
+000000a0  54 45 53 54 49 4e 47 31  10 30 0e 06 03 55 04 03  |TESTING1.0...U..|
+000000b0  13 07 47 6f 20 52 6f 6f  74 30 1e 17 0d 31 35 30  |..Go Root0...150|
+000000c0  31 30 31 30 30 30 30 30  30 5a 17 0d 32 35 30 31  |101000000Z..2501|
+000000d0  30 31 30 30 30 30 30 30  5a 30 26 31 17 30 15 06  |01000000Z0&1.0..|
+000000e0  03 55 04 0a 13 0e 47 6f  6f 67 6c 65 20 54 45 53  |.U....Google TES|
+000000f0  54 49 4e 47 31 0b 30 09  06 03 55 04 03 13 02 47  |TING1.0...U....G|
+00000100  6f 30 81 9f 30 0d 06 09  2a 86 48 86 f7 0d 01 01  |o0..0...*.H.....|
+00000110  01 05 00 03 81 8d 00 30  81 89 02 81 81 00 af 87  |.......0........|
+00000120  88 f6 20 1b 95 65 6c 14  ab 44 05 af 3b 45 14 e3  |.. ..el..D..;E..|
+00000130  b7 6d fd 00 63 4d 95 7f  fe 6a 62 35 86 c0 4a f9  |.m..cM...jb5..J.|
+00000140  18 7c f6 aa 25 5e 7a 64  31 66 00 ba f4 8e 92 af  |.|..%^zd1f......|
+00000150  c7 6b d8 76 d4 f3 5f 41  cb 6e 56 15 97 1b 97 c1  |.k.v.._A.nV.....|
+00000160  3c 12 39 21 66 3d 2b 16  d1 bc db 1c c0 a7 da b7  |<.9!f=+.........|
+00000170  ca ad ba da cb d5 21 50  ec de 8d ab d1 6b 81 4b  |......!P.....k.K|
+00000180  89 02 f3 c4 be c1 6c 89  b1 44 84 bd 21 d1 04 7d  |......l..D..!..}|
+00000190  9d 16 4d f9 82 15 f6 ef  fa d6 09 47 f2 fb 02 03  |..M........G....|
+000001a0  01 00 01 a3 81 93 30 81  90 30 0e 06 03 55 1d 0f  |......0..0...U..|
+000001b0  01 01 ff 04 04 03 02 05  a0 30 1d 06 03 55 1d 25  |.........0...U.%|
+000001c0  04 16 30 14 06 08 2b 06  01 05 05 07 03 01 06 08  |..0...+.........|
+000001d0  2b 06 01 05 05 07 03 02  30 0c 06 03 55 1d 13 01  |+.......0...U...|
+000001e0  01 ff 04 02 30 00 30 19  06 03 55 1d 0e 04 12 04  |....0.0...U.....|
+000001f0  10 12 50 8d 89 6f 1b d1  dc 54 4d 6e cb 69 5e 06  |..P..o...TMn.i^.|
+00000200  f4 30 1b 06 03 55 1d 23  04 14 30 12 80 10 bf 3d  |.0...U.#..0....=|
+00000210  b6 a9 66 f2 b8 40 cf ea  b4 03 78 48 1a 41 30 19  |..f.. at ....xH.A0.|
+00000220  06 03 55 1d 11 04 12 30  10 82 0e 65 78 61 6d 70  |..U....0...examp|
+00000230  6c 65 2e 67 6f 6c 61 6e  67 30 0d 06 09 2a 86 48  |le.golang0...*.H|
+00000240  86 f7 0d 01 01 0b 05 00  03 81 81 00 92 7c af 91  |.............|..|
+00000250  55 12 18 96 59 31 a6 48  40 d5 2d d5 ee bb 02 a0  |U...Y1.H at .-.....|
+00000260  f5 c2 1e 7c 9b b3 30 7d  3c dc 76 da 4f 3d c0 fa  |...|..0}<.v.O=..|
+00000270  ae 2d 33 24 6b 03 7b 1b  67 59 11 21 b5 11 bc 77  |.-3$k.{.gY.!...w|
+00000280  b9 d9 e0 6e a8 2d 2e 35  fa 64 5f 22 3e 63 10 6b  |...n.-.5.d_">c.k|
+00000290  be ff 14 86 6d 0d f0 15  31 a8 14 38 1e 3b 84 87  |....m...1..8.;..|
+000002a0  2c cb 98 ed 51 76 b9 b1  4f dd db 9b 84 04 86 40  |,...Qv..O......@|
+000002b0  fa 51 dd ba b4 8d eb e3  46 de 46 b9 4f 86 c7 f9  |.Q......F.F.O...|
+000002c0  a4 c2 41 34 ac cc f6 ea  b0 ab 39 18 16 03 03 00  |..A4......9.....|
+000002d0  04 0e 00 00 00                                    |.....|
 >>> Flow 3 (client to server)
-00000000  16 03 03 00 86 10 00 00  82 00 80 6d 51 f3 7f f9  |...........mQ...|
-00000010  3e fb 75 82 41 36 83 e8  6a ee 2a 2e 25 90 67 4c  |>.u.A6..j.*.%.gL|
-00000020  8e 62 2f 30 81 17 e0 85  09 0c 2b b7 23 d7 b0 e2  |.b/0......+.#...|
-00000030  1d f7 3b d7 f5 a1 27 b6  ee 24 b6 1b cc 5b ea 66  |..;...'..$...[.f|
-00000040  0d 6a f4 e5 85 f9 da 43  b4 0e 86 85 e1 f5 aa be  |.j.....C........|
-00000050  c8 ce 39 4c 9c 86 00 08  c2 4b e2 c6 ec 2f f7 ce  |..9L.....K.../..|
-00000060  e6 bd 77 82 6f 23 b6 e0  bd a2 92 b7 3a ac e8 56  |..w.o#......:..V|
-00000070  f1 af 54 5e 46 87 e9 3b  33 e7 b8 28 b7 d6 c8 90  |..T^F..;3..(....|
-00000080  35 d4 1c 43 d1 30 6f 55  4e 0a 70 14 03 03 00 01  |5..C.0oUN.p.....|
-00000090  01 16 03 03 00 24 54 8c  7f 71 03 7c 98 e5 97 65  |.....$T..q.|...e|
-000000a0  51 13 b2 9d 4a b8 c9 c1  e6 11 1b 50 c8 1b c0 46  |Q...J......P...F|
-000000b0  a7 cb 13 97 92 a0 51 d4  a9 e5                    |......Q...|
+00000000  16 03 03 00 86 10 00 00  82 00 80 73 bd 73 65 92  |...........s.se.|
+00000010  86 23 41 14 79 7f d5 c1  10 ce 94 4d ad 9c c3 a9  |.#A.y......M....|
+00000020  87 b5 32 52 f8 6b 11 93  2d 9b 98 0b 8b 1d c0 f6  |..2R.k..-.......|
+00000030  53 17 6d c7 9c 2e ae c9  6f cc 99 23 38 37 1a 10  |S.m.....o..#87..|
+00000040  fe 05 0b b5 55 0a 14 e9  60 7d 70 26 98 e2 54 d9  |....U...`}p&..T.|
+00000050  65 cf 2e f4 53 5f 1d aa  3a f6 33 7b eb 4c 0e b3  |e...S_..:.3{.L..|
+00000060  ff 5a db 36 2a 47 f3 df  f9 fc f5 31 78 83 aa 6b  |.Z.6*G.....1x..k|
+00000070  52 b7 ba 1a 96 bc fa c1  a1 a9 bb 2b f5 38 89 00  |R..........+.8..|
+00000080  4d e5 78 13 4e a4 38 46  42 dc 16 14 03 03 00 01  |M.x.N.8FB.......|
+00000090  01 16 03 03 00 24 72 bd  b1 13 05 73 26 c0 0b ec  |.....$r....s&...|
+000000a0  e6 39 08 6a 2d 87 00 51  58 9d e3 8d da be 60 98  |.9.j-..QX.....`.|
+000000b0  0a ee 0c 96 13 f4 e5 30  90 85                    |.......0..|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 24 37 ca ae 55 79  |..........$7..Uy|
-00000010  e7 0a 70 55 1e d1 76 61  57 46 d2 c0 d0 ed 3d 70  |..pU..vaWF....=p|
-00000020  1f 02 f2 06 5b 3e 50 ec  13 4b 67 e2 7c bd 45     |....[>P..Kg.|.E|
+00000000  14 03 03 00 01 01 16 03  03 00 24 d4 ad ab a0 01  |..........$.....|
+00000010  1b 87 9c aa c4 27 08 b5  8c 4a 7f fc 03 df a6 d6  |.....'...J......|
+00000020  f8 6c d1 61 7c d3 1f 6d  18 c3 8d 88 5c 7b cf     |.l.a|..m....\{.|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 1a c4 13 68  ec e0 38 a1 07 35 da d7  |.......h..8..5..|
-00000010  c4 6b f9 5c ed a7 8a cb  96 7a 22 7c ca a5 30 15  |.k.\.....z"|..0.|
-00000020  03 03 00 16 f7 a7 8d 41  b0 c1 4b 61 60 b0 b2 ed  |.......A..Ka`...|
-00000030  4a ab c3 54 d5 20 eb 67  b7 8f                    |J..T. .g..|
+00000000  17 03 03 00 1a 33 a8 7a  61 46 09 7b 64 e6 aa f8  |.....3.zaF.{d...|
+00000010  8a 43 d3 a9 0c e9 2e c0  89 7c 72 fb 75 50 50 15  |.C.......|r.uPP.|
+00000020  03 03 00 16 2b b9 b5 eb  f8 bd 53 20 ea 67 bc 47  |....+.....S .g.G|
+00000030  83 cf c5 6e f9 4f 9e 12  f5 1a                    |...n.O....|
diff --git a/src/crypto/tls/testdata/Client-TLSv12-SCT b/src/crypto/tls/testdata/Client-TLSv12-SCT
index 826c9f0..e6187ba 100644
--- a/src/crypto/tls/testdata/Client-TLSv12-SCT
+++ b/src/crypto/tls/testdata/Client-TLSv12-SCT
@@ -1,19 +1,19 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 81 01 00 00  7d 03 03 00 00 00 00 00  |........}.......|
+00000000  16 03 01 00 85 01 00 00  81 03 03 00 00 00 00 00  |................|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 1e c0 2f  |.............../|
+00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 22 c0 2f  |............."./|
 00000030  c0 2b c0 30 c0 2c c0 11  c0 07 c0 13 c0 09 c0 14  |.+.0.,..........|
-00000040  c0 0a 00 05 00 2f 00 35  c0 12 00 0a 01 00 00 36  |...../.5.......6|
-00000050  00 05 00 05 01 00 00 00  00 00 0a 00 08 00 06 00  |................|
-00000060  17 00 18 00 19 00 0b 00  02 01 00 00 0d 00 0e 00  |................|
-00000070  0c 04 01 04 03 05 01 05  03 02 01 02 03 ff 01 00  |................|
-00000080  01 00 00 12 00 00                                 |......|
+00000040  c0 0a 00 9c 00 9d 00 05  00 2f 00 35 c0 12 00 0a  |........./.5....|
+00000050  01 00 00 36 00 05 00 05  01 00 00 00 00 00 0a 00  |...6............|
+00000060  08 00 06 00 17 00 18 00  19 00 0b 00 02 01 00 00  |................|
+00000070  0d 00 0e 00 0c 04 01 04  03 05 01 05 03 02 01 02  |................|
+00000080  03 ff 01 00 01 00 00 12  00 00                    |..........|
 >>> Flow 2 (server to client)
-00000000  16 03 03 01 c6 02 00 01  c2 03 03 1b f6 69 c1 c2  |.............i..|
-00000010  36 77 72 32 69 95 c9 e7  db 9b 5d bd 59 ba 08 02  |6wr2i.....].Y...|
-00000020  1e 76 11 c4 8e 49 08 22  8e 8a 5a 20 44 ec d9 13  |.v...I."..Z D...|
-00000030  23 ad 05 45 48 29 00 c6  11 3d 5a 5c a1 ee 34 2b  |#..EH)...=Z\..4+|
-00000040  58 ef 34 5b 7e 42 08 84  23 66 56 ee c0 2f 00 01  |X.4[~B..#fV../..|
+00000000  16 03 03 01 c6 02 00 01  c2 03 03 5d d8 84 38 51  |...........]..8Q|
+00000010  c6 51 9e 6c d3 e0 b2 d7  81 2a 9b 1c 06 0b 11 c8  |.Q.l.....*......|
+00000020  54 90 f3 d1 66 83 7a 68  2f 65 8b 20 ac 8b 35 9a  |T...f.zh/e. ..5.|
+00000030  31 25 04 c9 89 31 27 80  8f 10 74 8e 3c 4f 20 bc  |1%...1'...t.<O .|
+00000040  3b 46 9d d0 91 f3 ca 7e  0e 59 b7 72 c0 2f 00 01  |;F.....~.Y.r./..|
 00000050  7a ff 01 00 01 00 00 0b  00 04 03 00 01 02 00 12  |z...............|
 00000060  01 69 01 67 00 75 00 a4  b9 09 90 b4 18 58 14 87  |.i.g.u.......X..|
 00000070  bb 13 a2 cc 67 70 0a 3c  35 98 04 f9 1b df b8 e3  |....gp.<5.......|
@@ -37,82 +37,77 @@
 00000190  91 bc f1 b5 40 be 1e 2e  e7 5c b4 74 27 ed 8f 9b  |.... at ....\.t'...|
 000001a0  02 e9 fa c2 4c ba a2 be  02 21 00 af 43 64 52 71  |....L....!..CdRq|
 000001b0  15 29 58 40 91 c7 08 16  96 03 a8 73 a5 65 a0 6c  |.)X at .......s.e.l|
-000001c0  b8 48 56 5a b6 29 83 64  6d 2a 9d 16 03 03 02 be  |.HVZ.).dm*......|
-000001d0  0b 00 02 ba 00 02 b7 00  02 b4 30 82 02 b0 30 82  |..........0...0.|
-000001e0  02 19 a0 03 02 01 02 02  09 00 85 b0 bb a4 8a 7f  |................|
-000001f0  b8 ca 30 0d 06 09 2a 86  48 86 f7 0d 01 01 05 05  |..0...*.H.......|
-00000200  00 30 45 31 0b 30 09 06  03 55 04 06 13 02 41 55  |.0E1.0...U....AU|
-00000210  31 13 30 11 06 03 55 04  08 13 0a 53 6f 6d 65 2d  |1.0...U....Some-|
-00000220  53 74 61 74 65 31 21 30  1f 06 03 55 04 0a 13 18  |State1!0...U....|
-00000230  49 6e 74 65 72 6e 65 74  20 57 69 64 67 69 74 73  |Internet Widgits|
-00000240  20 50 74 79 20 4c 74 64  30 1e 17 0d 31 30 30 34  | Pty Ltd0...1004|
-00000250  32 34 30 39 30 39 33 38  5a 17 0d 31 31 30 34 32  |24090938Z..11042|
-00000260  34 30 39 30 39 33 38 5a  30 45 31 0b 30 09 06 03  |4090938Z0E1.0...|
-00000270  55 04 06 13 02 41 55 31  13 30 11 06 03 55 04 08  |U....AU1.0...U..|
-00000280  13 0a 53 6f 6d 65 2d 53  74 61 74 65 31 21 30 1f  |..Some-State1!0.|
-00000290  06 03 55 04 0a 13 18 49  6e 74 65 72 6e 65 74 20  |..U....Internet |
-000002a0  57 69 64 67 69 74 73 20  50 74 79 20 4c 74 64 30  |Widgits Pty Ltd0|
-000002b0  81 9f 30 0d 06 09 2a 86  48 86 f7 0d 01 01 01 05  |..0...*.H.......|
-000002c0  00 03 81 8d 00 30 81 89  02 81 81 00 bb 79 d6 f5  |.....0.......y..|
-000002d0  17 b5 e5 bf 46 10 d0 dc  69 be e6 2b 07 43 5a d0  |....F...i..+.CZ.|
-000002e0  03 2d 8a 7a 43 85 b7 14  52 e7 a5 65 4c 2c 78 b8  |.-.zC...R..eL,x.|
-000002f0  23 8c b5 b4 82 e5 de 1f  95 3b 7e 62 a5 2c a5 33  |#........;~b.,.3|
-00000300  d6 fe 12 5c 7a 56 fc f5  06 bf fa 58 7b 26 3f b5  |...\zV.....X{&?.|
-00000310  cd 04 d3 d0 c9 21 96 4a  c7 f4 54 9f 5a bf ef 42  |.....!.J..T.Z..B|
-00000320  71 00 fe 18 99 07 7f 7e  88 7d 7d f1 04 39 c4 a2  |q......~.}}..9..|
-00000330  2e db 51 c9 7c e3 c0 4c  3b 32 66 01 cf af b1 1d  |..Q.|..L;2f.....|
-00000340  b8 71 9a 1d db db 89 6b  ae da 2d 79 02 03 01 00  |.q.....k..-y....|
-00000350  01 a3 81 a7 30 81 a4 30  1d 06 03 55 1d 0e 04 16  |....0..0...U....|
-00000360  04 14 b1 ad e2 85 5a cf  cb 28 db 69 ce 23 69 de  |......Z..(.i.#i.|
-00000370  d3 26 8e 18 88 39 30 75  06 03 55 1d 23 04 6e 30  |.&...90u..U.#.n0|
-00000380  6c 80 14 b1 ad e2 85 5a  cf cb 28 db 69 ce 23 69  |l......Z..(.i.#i|
-00000390  de d3 26 8e 18 88 39 a1  49 a4 47 30 45 31 0b 30  |..&...9.I.G0E1.0|
-000003a0  09 06 03 55 04 06 13 02  41 55 31 13 30 11 06 03  |...U....AU1.0...|
-000003b0  55 04 08 13 0a 53 6f 6d  65 2d 53 74 61 74 65 31  |U....Some-State1|
-000003c0  21 30 1f 06 03 55 04 0a  13 18 49 6e 74 65 72 6e  |!0...U....Intern|
-000003d0  65 74 20 57 69 64 67 69  74 73 20 50 74 79 20 4c  |et Widgits Pty L|
-000003e0  74 64 82 09 00 85 b0 bb  a4 8a 7f b8 ca 30 0c 06  |td...........0..|
-000003f0  03 55 1d 13 04 05 30 03  01 01 ff 30 0d 06 09 2a  |.U....0....0...*|
-00000400  86 48 86 f7 0d 01 01 05  05 00 03 81 81 00 08 6c  |.H.............l|
-00000410  45 24 c7 6b b1 59 ab 0c  52 cc f2 b0 14 d7 87 9d  |E$.k.Y..R.......|
-00000420  7a 64 75 b5 5a 95 66 e4  c5 2b 8e ae 12 66 1f eb  |zdu.Z.f..+...f..|
-00000430  4f 38 b3 6e 60 d3 92 fd  f7 41 08 b5 25 13 b1 18  |O8.n`....A..%...|
-00000440  7a 24 fb 30 1d ba ed 98  b9 17 ec e7 d7 31 59 db  |z$.0.........1Y.|
-00000450  95 d3 1d 78 ea 50 56 5c  d5 82 5a 2d 5a 5f 33 c4  |...x.PV\..Z-Z_3.|
-00000460  b6 d8 c9 75 90 96 8c 0f  52 98 b5 cd 98 1f 89 20  |...u....R...... |
-00000470  5f f2 a0 1c a3 1b 96 94  dd a9 fd 57 e9 70 e8 26  |_..........W.p.&|
-00000480  6d 71 99 9b 26 6e 38 50  29 6c 90 a7 bd d9 16 03  |mq..&n8P)l......|
-00000490  03 00 cd 0c 00 00 c9 03  00 17 41 04 d7 61 5b 05  |..........A..a[.|
-000004a0  de 22 d3 3d 00 72 a5 be  0a c1 76 94 a1 34 41 6e  |.".=.r....v..4An|
-000004b0  55 f2 74 91 d2 6f 5c 47  87 c8 4b eb ab ab 10 b9  |U.t..o\G..K.....|
-000004c0  f9 0a bc 63 03 5f 90 5b  e3 6f e1 44 97 cc bf d2  |...c._.[.o.D....|
-000004d0  e8 0d f5 9c 2e 9d 07 2c  b2 00 90 0b 04 01 00 80  |.......,........|
-000004e0  67 3d c7 73 42 b9 b2 fd  4b dd 02 57 87 95 20 75  |g=.sB...K..W.. u|
-000004f0  da c1 e7 d3 33 09 01 5d  e9 32 d7 20 7f 92 a9 dd  |....3..].2. ....|
-00000500  bb 17 c5 ee f2 07 b2 04  1d 5e 1f c2 41 66 3f 14  |.........^..Af?.|
-00000510  90 cd 84 ac 49 46 04 3e  ce 89 7d 79 42 2a 8c 56  |....IF.>..}yB*.V|
-00000520  93 d3 9c 3b 57 38 9e 91  af 62 ad 86 40 29 3d 46  |...;W8...b..@)=F|
-00000530  c7 cc f4 3f a1 7d ee 53  3d 94 1c 85 b9 1d a9 5f  |...?.}.S=......_|
-00000540  10 8e ee 38 5e 98 5d 39  31 79 83 cd f9 02 a8 a9  |...8^.]91y......|
-00000550  b8 82 21 33 40 ed 27 54  a3 6e 64 cb e9 ce dd e1  |..!3 at .'T.nd.....|
-00000560  16 03 03 00 04 0e 00 00  00                       |.........|
+000001c0  b8 48 56 5a b6 29 83 64  6d 2a 9d 16 03 03 02 71  |.HVZ.).dm*.....q|
+000001d0  0b 00 02 6d 00 02 6a 00  02 67 30 82 02 63 30 82  |...m..j..g0..c0.|
+000001e0  01 cc a0 03 02 01 02 02  09 00 a2 73 00 0c 81 00  |...........s....|
+000001f0  cb f3 30 0d 06 09 2a 86  48 86 f7 0d 01 01 0b 05  |..0...*.H.......|
+00000200  00 30 2b 31 17 30 15 06  03 55 04 0a 13 0e 47 6f  |.0+1.0...U....Go|
+00000210  6f 67 6c 65 20 54 45 53  54 49 4e 47 31 10 30 0e  |ogle TESTING1.0.|
+00000220  06 03 55 04 03 13 07 47  6f 20 52 6f 6f 74 30 1e  |..U....Go Root0.|
+00000230  17 0d 31 35 30 31 30 31  30 30 30 30 30 30 5a 17  |..150101000000Z.|
+00000240  0d 32 35 30 31 30 31 30  30 30 30 30 30 5a 30 26  |.250101000000Z0&|
+00000250  31 17 30 15 06 03 55 04  0a 13 0e 47 6f 6f 67 6c  |1.0...U....Googl|
+00000260  65 20 54 45 53 54 49 4e  47 31 0b 30 09 06 03 55  |e TESTING1.0...U|
+00000270  04 03 13 02 47 6f 30 81  9f 30 0d 06 09 2a 86 48  |....Go0..0...*.H|
+00000280  86 f7 0d 01 01 01 05 00  03 81 8d 00 30 81 89 02  |............0...|
+00000290  81 81 00 af 87 88 f6 20  1b 95 65 6c 14 ab 44 05  |....... ..el..D.|
+000002a0  af 3b 45 14 e3 b7 6d fd  00 63 4d 95 7f fe 6a 62  |.;E...m..cM...jb|
+000002b0  35 86 c0 4a f9 18 7c f6  aa 25 5e 7a 64 31 66 00  |5..J..|..%^zd1f.|
+000002c0  ba f4 8e 92 af c7 6b d8  76 d4 f3 5f 41 cb 6e 56  |......k.v.._A.nV|
+000002d0  15 97 1b 97 c1 3c 12 39  21 66 3d 2b 16 d1 bc db  |.....<.9!f=+....|
+000002e0  1c c0 a7 da b7 ca ad ba  da cb d5 21 50 ec de 8d  |...........!P...|
+000002f0  ab d1 6b 81 4b 89 02 f3  c4 be c1 6c 89 b1 44 84  |..k.K......l..D.|
+00000300  bd 21 d1 04 7d 9d 16 4d  f9 82 15 f6 ef fa d6 09  |.!..}..M........|
+00000310  47 f2 fb 02 03 01 00 01  a3 81 93 30 81 90 30 0e  |G..........0..0.|
+00000320  06 03 55 1d 0f 01 01 ff  04 04 03 02 05 a0 30 1d  |..U...........0.|
+00000330  06 03 55 1d 25 04 16 30  14 06 08 2b 06 01 05 05  |..U.%..0...+....|
+00000340  07 03 01 06 08 2b 06 01  05 05 07 03 02 30 0c 06  |.....+.......0..|
+00000350  03 55 1d 13 01 01 ff 04  02 30 00 30 19 06 03 55  |.U.......0.0...U|
+00000360  1d 0e 04 12 04 10 12 50  8d 89 6f 1b d1 dc 54 4d  |.......P..o...TM|
+00000370  6e cb 69 5e 06 f4 30 1b  06 03 55 1d 23 04 14 30  |n.i^..0...U.#..0|
+00000380  12 80 10 bf 3d b6 a9 66  f2 b8 40 cf ea b4 03 78  |....=..f.. at ....x|
+00000390  48 1a 41 30 19 06 03 55  1d 11 04 12 30 10 82 0e  |H.A0...U....0...|
+000003a0  65 78 61 6d 70 6c 65 2e  67 6f 6c 61 6e 67 30 0d  |example.golang0.|
+000003b0  06 09 2a 86 48 86 f7 0d  01 01 0b 05 00 03 81 81  |..*.H...........|
+000003c0  00 92 7c af 91 55 12 18  96 59 31 a6 48 40 d5 2d  |..|..U...Y1.H at .-|
+000003d0  d5 ee bb 02 a0 f5 c2 1e  7c 9b b3 30 7d 3c dc 76  |........|..0}<.v|
+000003e0  da 4f 3d c0 fa ae 2d 33  24 6b 03 7b 1b 67 59 11  |.O=...-3$k.{.gY.|
+000003f0  21 b5 11 bc 77 b9 d9 e0  6e a8 2d 2e 35 fa 64 5f  |!...w...n.-.5.d_|
+00000400  22 3e 63 10 6b be ff 14  86 6d 0d f0 15 31 a8 14  |">c.k....m...1..|
+00000410  38 1e 3b 84 87 2c cb 98  ed 51 76 b9 b1 4f dd db  |8.;..,...Qv..O..|
+00000420  9b 84 04 86 40 fa 51 dd  ba b4 8d eb e3 46 de 46  |.... at .Q......F.F|
+00000430  b9 4f 86 c7 f9 a4 c2 41  34 ac cc f6 ea b0 ab 39  |.O.....A4......9|
+00000440  18 16 03 03 00 cd 0c 00  00 c9 03 00 17 41 04 1e  |.............A..|
+00000450  d1 1c 5c d3 00 41 84 cd  f7 e2 78 ad b5 7d 5b f2  |..\..A....x..}[.|
+00000460  23 5b 1a 18 44 3f 86 8e  3e 52 f2 4b b6 7d 84 b4  |#[..D?..>R.K.}..|
+00000470  1d 98 83 8f 2f 58 07 92  1f 58 2a 8d 8c e3 fa b7  |..../X...X*.....|
+00000480  aa 78 7e 33 9a 64 b9 b6  cb 78 94 be 2b c3 ac 04  |.x~3.d...x..+...|
+00000490  01 00 80 65 9f 42 e3 24  5c cd 18 aa 08 8e 6b bf  |...e.B.$\.....k.|
+000004a0  39 15 2a a3 e6 42 1c 9d  6b 34 39 a2 2c 58 f5 5f  |9.*..B..k49.,X._|
+000004b0  3e fb 2a 4c 01 2b e5 20  4e f5 69 77 c1 62 8f 68  |>.*L.+. N.iw.b.h|
+000004c0  be b4 c4 77 27 c9 4a 97  6d 18 7f 45 fd c9 9e 24  |...w'.J.m..E...$|
+000004d0  19 6b d9 00 c5 52 1a 34  a3 c9 cb eb 92 fc f6 48  |.k...R.4.......H|
+000004e0  3d 89 8a ff 82 be 55 c9  92 e2 24 86 b0 99 c6 e8  |=.....U...$.....|
+000004f0  a5 4c b7 bc 5a e5 f3 81  94 ee 15 47 e7 5e 8c 66  |.L..Z......G.^.f|
+00000500  32 72 7d 81 78 61 fe 25  98 dd 07 a2 92 4c eb ed  |2r}.xa.%.....L..|
+00000510  f1 a7 17 16 03 03 00 04  0e 00 00 00              |............|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 46 10 00 00  42 41 04 1e 18 37 ef 0d  |....F...BA...7..|
 00000010  19 51 88 35 75 71 b5 e5  54 5b 12 2e 8f 09 67 fd  |.Q.5uq..T[....g.|
 00000020  a7 24 20 3e b2 56 1c ce  97 28 5e f8 2b 2d 4f 9e  |.$ >.V...(^.+-O.|
 00000030  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
 00000040  a6 b5 68 1a 41 03 56 6b  dc 5a 89 14 03 03 00 01  |..h.A.Vk.Z......|
-00000050  01 16 03 03 00 28 00 00  00 00 00 00 00 00 60 0e  |.....(........`.|
-00000060  49 99 7a 9f 28 6e 46 03  a8 fd 0e b7 ed bb 9c ba  |I.z.(nF.........|
-00000070  07 9c 4d cc 26 2b c2 70  a0 26 38 a0 f2 a0        |..M.&+.p.&8...|
+00000050  01 16 03 03 00 28 00 00  00 00 00 00 00 00 f0 4f  |.....(.........O|
+00000060  fe 22 53 9e e1 61 f4 45  4e 41 ff 5e e4 63 25 f7  |."S..a.ENA.^.c%.|
+00000070  b2 f6 0a ea 89 75 7f d4  e7 3a cc e8 c2 2c        |.....u...:...,|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 28 d2 ef 8f f4 7b  |..........(....{|
-00000010  7a 9b c8 98 a4 36 f2 be  61 46 0e af f4 6f 63 71  |z....6..aF...ocq|
-00000020  6e bd 87 ea 1b f2 95 ad  36 7d a3 52 7f b2 b6 45  |n.......6}.R...E|
-00000030  3f 0b 62                                          |?.b|
+00000000  14 03 03 00 01 01 16 03  03 00 28 ad 49 0a 66 16  |..........(.I.f.|
+00000010  6d 64 42 c2 ab 38 bf 81  3d d9 14 13 d6 69 27 81  |mdB..8..=....i'.|
+00000020  ea 5c 53 fd 6c bf 81 6c  06 81 a5 67 f2 cd ed a3  |.\S.l..l...g....|
+00000030  d4 c2 08                                          |...|
 >>> Flow 5 (client to server)
-00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 53 a1 85  |.............S..|
-00000010  ce 3c c1 64 39 80 fb db  67 ec 48 20 7f e9 82 f4  |.<.d9...g.H ....|
-00000020  2d 69 0a 15 03 03 00 1a  00 00 00 00 00 00 00 02  |-i..............|
-00000030  ab 78 11 1b 80 55 23 db  07 c5 7f c3 5e 19 d8 b3  |.x...U#.....^...|
-00000040  f8 c6                                             |..|
+00000000  17 03 03 00 1e 00 00 00  00 00 00 00 01 5c ab e3  |.............\..|
+00000010  f9 61 72 9e 44 46 1a 05  e9 00 eb 5b e0 73 22 03  |.ar.DF.....[.s".|
+00000020  9f 90 f9 15 03 03 00 1a  00 00 00 00 00 00 00 02  |................|
+00000030  04 28 a4 9d 07 79 95 40  0f f0 eb b9 5d 97 bf 87  |.(...y. at ....]...|
+00000040  4a b6                                             |J.|
diff --git a/src/crypto/tls/testdata/Server-SSLv3-RSA-3DES b/src/crypto/tls/testdata/Server-SSLv3-RSA-3DES
index 20520f5..10b7f52 100644
--- a/src/crypto/tls/testdata/Server-SSLv3-RSA-3DES
+++ b/src/crypto/tls/testdata/Server-SSLv3-RSA-3DES
@@ -1,8 +1,8 @@
 >>> Flow 1 (client to server)
-00000000  16 03 00 00 2f 01 00 00  2b 03 00 10 71 68 59 99  |..../...+...qhY.|
-00000010  9c a6 e7 36 8b 0d 03 be  f5 42 ab 7c d0 3b 76 3e  |...6.....B.|.;v>|
-00000020  46 7c 6c a3 94 09 b7 1b  0e 42 27 00 00 04 00 0a  |F|l......B'.....|
-00000030  00 ff 01 00                                       |....|
+00000000  16 03 00 00 30 01 00 00  2c 03 00 50 32 2f f9 d5  |....0...,..P2/..|
+00000010  8f 83 ac 79 0e 0b e5 65  2c 87 79 01 7d 15 73 00  |...y...e,.y.}.s.|
+00000020  46 7c dc c6 6d 70 0b f3  d2 dc de 00 00 04 00 0a  |F|..mp..........|
+00000030  00 ff 02 01 00                                    |.....|
 >>> Flow 2 (server to client)
 00000000  16 03 00 00 31 02 00 00  2d 03 00 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -49,30 +49,30 @@
 000002a0  a4 c2 41 34 ac cc f6 ea  b0 ab 39 18 16 03 00 00  |..A4......9.....|
 000002b0  04 0e 00 00 00                                    |.....|
 >>> Flow 3 (client to server)
-00000000  16 03 00 00 84 10 00 00  80 1b 62 18 c8 60 0b f7  |..........b..`..|
-00000010  4a b8 ec 98 56 eb aa 4b  d9 05 c0 f1 be b9 a5 28  |J...V..K.......(|
-00000020  62 e8 3e 25 08 9f 28 dd  08 1f 04 80 5f 10 81 cf  |b.>%..(....._...|
-00000030  aa 2f 55 cd f1 0f ec 5b  90 0a 1f 49 bc a3 96 38  |./U....[...I...8|
-00000040  c7 32 b6 0a da b3 a5 7a  76 28 82 19 30 f4 6b ae  |.2.....zv(..0.k.|
-00000050  fb 81 cc b4 ad 92 f8 c6  20 da 27 89 45 f4 43 c2  |........ .'.E.C.|
-00000060  16 7e de 29 03 dc 90 dd  3a 23 58 4c 35 be 11 a5  |.~.)....:#XL5...|
-00000070  52 18 79 13 e6 b3 2d e6  8e f5 76 60 0c c1 92 bb  |R.y...-...v`....|
-00000080  07 67 c5 24 12 1b aa d6  53 14 03 00 00 01 01 16  |.g.$....S.......|
-00000090  03 00 00 40 5f 64 da b6  24 19 07 44 32 85 f3 c0  |... at _d..$..D2...|
-000000a0  9b c6 2c ad b1 d1 0f 4b  52 20 2f ea 6f 15 80 44  |..,....KR /.o..D|
-000000b0  78 34 44 02 67 e0 2e b4  b8 df 7b 3f 21 dd 66 9b  |x4D.g.....{?!.f.|
-000000c0  e7 5f 71 ff 5f 30 fb 5b  5a 19 f0 24 f8 21 bc 7c  |._q._0.[Z..$.!.||
-000000d0  00 e1 1f e8                                       |....|
+00000000  16 03 00 00 84 10 00 00  80 48 96 89 e9 d2 e6 c6  |.........H......|
+00000010  eb 9d f8 46 dd c7 d8 01  95 57 76 1a 59 1c 79 21  |...F.....Wv.Y.y!|
+00000020  94 0b 83 b2 c9 5e c1 5f  4f 12 00 10 63 12 d3 f9  |.....^._O...c...|
+00000030  ae ae 31 18 fa b4 33 37  eb b9 23 15 55 7e cf 62  |..1...37..#.U~.b|
+00000040  20 a7 cb eb 69 35 e0 35  32 e4 0a 4c c0 33 e9 7d  | ...i5.52..L.3.}|
+00000050  f2 a8 4b e2 fe 90 62 7a  09 df c5 46 03 0c 52 7a  |..K...bz...F..Rz|
+00000060  fb 96 dd fd 55 aa e5 be  3c 35 65 03 be e1 51 0f  |....U...<5e...Q.|
+00000070  7b b3 05 6b e9 af 9b 0e  e4 ea d9 34 69 a5 c2 9a  |{..k.......4i...|
+00000080  71 a8 cc 0a 94 ef 91 14  88 14 03 00 00 01 01 16  |q...............|
+00000090  03 00 00 40 0c 34 26 4c  cf f0 d4 a0 08 b9 b7 6b  |... at .4&L.......k|
+000000a0  0a 69 55 48 91 2c 92 4c  9b e7 66 d0 b8 da 2d e7  |.iUH.,.L..f...-.|
+000000b0  89 ca f5 a4 3d 11 ff 87  22 07 c0 ed 72 9c ad 19  |....=..."...r...|
+000000c0  7d 63 2b 67 43 e3 33 76  a1 ac 69 77 55 bb 60 ba  |}c+gC.3v..iwU.`.|
+000000d0  57 00 4e 2a                                       |W.N*|
 >>> Flow 4 (server to client)
-00000000  14 03 00 00 01 01 16 03  00 00 40 48 01 fc 08 a0  |.......... at H....|
-00000010  fa 0e 63 58 25 18 06 3c  54 5c 60 ce 35 f6 ec b8  |..cX%..<T\`.5...|
-00000020  ed f8 97 c7 b0 5f 96 6b  d1 10 53 e9 23 20 44 56  |....._.k..S.# DV|
-00000030  d7 ee 11 e1 6f b7 1e fb  33 94 7f f0 78 f5 2e 02  |....o...3...x...|
-00000040  37 7a 43 cf e7 c7 52 b3  c6 8d 8e 17 03 00 00 18  |7zC...R.........|
-00000050  f7 3c 05 79 4b 55 8c d7  2c 50 82 f0 61 34 f6 c7  |.<.yKU..,P..a4..|
-00000060  f3 71 e1 76 1d f0 65 b6  17 03 00 00 28 50 ce 6c  |.q.v..e.....(P.l|
-00000070  96 97 70 88 b7 3c 74 a9  cb a3 0e ae 3a 7f 85 99  |..p..<t.....:...|
-00000080  58 36 10 7f 1a e8 f8 7d  83 75 24 7e b1 6a 8e b0  |X6.....}.u$~.j..|
-00000090  f1 cc 06 19 f7 15 03 00  00 18 2c 1d 87 1d ce 08  |..........,.....|
-000000a0  8f 10 09 6e bd fc ad e0  1d a7 47 d5 b9 8f 3e b8  |...n......G...>.|
-000000b0  b3 fa                                             |..|
+00000000  14 03 00 00 01 01 16 03  00 00 40 dd e1 34 c5 4a  |.......... at ..4.J|
+00000010  96 76 81 49 df 1b 3d 48  cc 6c b0 3b ee 77 a9 62  |.v.I..=H.l.;.w.b|
+00000020  91 b3 16 b0 e1 79 4b 2a  95 d8 54 98 7b 5e ac 0f  |.....yK*..T.{^..|
+00000030  07 3b 06 36 e1 38 dc 75  6a af f7 ce a4 b2 3f 9e  |.;.6.8.uj.....?.|
+00000040  36 b1 44 ce e9 6c 34 ba  ce 97 02 17 03 00 00 18  |6.D..l4.........|
+00000050  5b be 71 2f a1 15 2f e9  9b 83 8e f1 9b e7 5b 4a  |[.q/../.......[J|
+00000060  a1 85 13 03 c0 f2 30 0c  17 03 00 00 28 2c d9 9e  |......0.....(,..|
+00000070  f4 d2 70 2a 37 76 66 e7  f4 5c c7 55 be d8 82 49  |..p*7vf..\.U...I|
+00000080  77 e0 4f 0f 87 4b c0 b1  f3 d2 a3 63 df 62 bc ee  |w.O..K.....c.b..|
+00000090  5c c2 50 2a 96 15 03 00  00 18 8b 0a 68 8a d8 64  |\.P*........h..d|
+000000a0  4e 3f f9 ee c6 b2 21 51  03 10 6b 73 3b 8c a4 bb  |N?....!Q..ks;...|
+000000b0  6d f2                                             |m.|
diff --git a/src/crypto/tls/testdata/Server-SSLv3-RSA-AES b/src/crypto/tls/testdata/Server-SSLv3-RSA-AES
index e0fe956..e733819 100644
--- a/src/crypto/tls/testdata/Server-SSLv3-RSA-AES
+++ b/src/crypto/tls/testdata/Server-SSLv3-RSA-AES
@@ -1,8 +1,8 @@
 >>> Flow 1 (client to server)
-00000000  16 03 00 00 2f 01 00 00  2b 03 00 37 cd 49 a6 9f  |..../...+..7.I..|
-00000010  e9 19 6a 39 cd 75 ce 6c  f1 1b 96 d3 d4 f0 33 0c  |..j9.u.l......3.|
-00000020  8f 53 b2 06 c4 0e 39 86  e3 98 7e 00 00 04 00 2f  |.S....9...~..../|
-00000030  00 ff 01 00                                       |....|
+00000000  16 03 00 00 30 01 00 00  2c 03 00 36 b0 f3 52 13  |....0...,..6..R.|
+00000010  00 17 16 8f 6e 44 24 06  84 05 5b 03 e6 8a 55 ee  |....nD$...[...U.|
+00000020  75 9c a8 77 9e e0 7b 15  f9 60 6e 00 00 04 00 2f  |u..w..{..`n..../|
+00000030  00 ff 02 01 00                                    |.....|
 >>> Flow 2 (server to client)
 00000000  16 03 00 00 31 02 00 00  2d 03 00 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -49,31 +49,31 @@
 000002a0  a4 c2 41 34 ac cc f6 ea  b0 ab 39 18 16 03 00 00  |..A4......9.....|
 000002b0  04 0e 00 00 00                                    |.....|
 >>> Flow 3 (client to server)
-00000000  16 03 00 00 84 10 00 00  80 4d 3f 93 aa 84 d8 ad  |.........M?.....|
-00000010  93 2c 63 02 66 2f 96 88  b8 5c 09 1e 63 e2 e5 96  |.,c.f/...\..c...|
-00000020  26 d8 07 14 86 26 62 f4  0c 04 68 1c bf bb b1 53  |&....&b...h....S|
-00000030  97 96 43 59 4a 57 65 12  88 45 34 2b 86 2b 05 aa  |..CYJWe..E4+.+..|
-00000040  9b 2b b9 aa 13 30 5c 91  c0 9f 03 8a 96 61 dd 87  |.+...0\......a..|
-00000050  ae e3 ad 6a 7b 8a 18 23  67 c9 df ad f2 47 eb 8b  |...j{..#g....G..|
-00000060  7d 24 95 47 f1 4e b5 c6  15 b4 12 2a 42 df b3 99  |}$.G.N.....*B...|
-00000070  d1 b8 60 ce 6a cf 98 c1  13 a1 68 e6 92 ee 92 a2  |..`.j.....h.....|
-00000080  1d 2f 63 66 f3 b9 1b fc  33 14 03 00 00 01 01 16  |./cf....3.......|
-00000090  03 00 00 40 75 48 68 7d  8f f5 5a c0 cb 90 a5 9e  |... at uHh}..Z.....|
-000000a0  94 bb eb 61 b5 36 aa ce  09 7a 11 ba 22 56 2a d7  |...a.6...z.."V*.|
-000000b0  91 a3 99 73 5b c5 b2 b7  b9 92 56 c6 cb fe 13 73  |...s[.....V....s|
-000000c0  28 30 03 26 62 63 7e 8a  d2 58 c8 e7 52 03 26 67  |(0.&bc~..X..R.&g|
-000000d0  48 21 4f 21                                       |H!O!|
+00000000  16 03 00 00 84 10 00 00  80 2d 0b b1 1c 96 72 65  |.........-....re|
+00000010  e5 3b 5b 48 35 91 b8 2e  18 b5 6c 36 a4 91 10 0e  |.;[H5.....l6....|
+00000020  15 63 de fb 7e ea 44 cd  2e 2f 37 2c 88 96 30 d4  |.c..~.D../7,..0.|
+00000030  07 ff 02 9b af 84 2c 43  6c 3a 1f 75 17 4c 5e 8b  |......,Cl:.u.L^.|
+00000040  4a d9 df 68 fe ad 72 c9  0c f7 a5 0c a1 70 8b 9f  |J..h..r......p..|
+00000050  e7 8e 1d 32 61 8e 80 e5  3a 3a 61 ea 22 1a 67 e5  |...2a...::a.".g.|
+00000060  06 6a 5e 0c 65 bd c7 32  9c 13 c1 53 ad 8e f1 be  |.j^.e..2...S....|
+00000070  4d 6c 53 89 8f 9c 49 d2  85 58 04 b5 e8 53 b4 82  |MlS...I..X...S..|
+00000080  84 46 9d 70 fa 0a 34 15  1d 14 03 00 00 01 01 16  |.F.p..4.........|
+00000090  03 00 00 40 71 c7 4b ef  6b 7a f4 a2 29 dd c0 4b  |... at q.K.kz..)..K|
+000000a0  ef 04 7d ea 1c 31 16 38  ae 85 f9 89 db 2f a8 04  |..}..1.8...../..|
+000000b0  ad 61 b7 33 73 8c 31 9b  72 5a f6 8b 10 71 0c af  |.a.3s.1.rZ...q..|
+000000c0  99 89 14 63 b8 19 f8 0e  2c 0f 14 c6 d6 0a bd 4f  |...c....,......O|
+000000d0  96 59 0d 60                                       |.Y.`|
 >>> Flow 4 (server to client)
-00000000  14 03 00 00 01 01 16 03  00 00 40 84 8f 6e 80 35  |.......... at ..n.5|
-00000010  57 73 64 ef 29 bb 25 ff  5d 9d c7 55 38 b7 18 b3  |Wsd.).%.]..U8...|
-00000020  13 d1 ac 20 e0 1e f8 48  47 7a 40 2d bc a7 f2 af  |... ...HGz at -....|
-00000030  ed a6 26 48 f4 51 b4 b6  56 60 9b c3 d9 43 00 95  |..&H.Q..V`...C..|
-00000040  86 be 6c 4e 49 6b f9 10  99 51 22 17 03 00 00 20  |..lNIk...Q".... |
-00000050  d4 7e dc 50 7b c2 26 ee  79 09 84 9f d7 e0 52 b1  |.~.P{.&.y.....R.|
-00000060  e8 9c 92 30 b7 34 06 c6  e5 86 57 a1 fb 8d 06 d6  |...0.4....W.....|
-00000070  17 03 00 00 30 93 0a 3d  64 26 3d a2 74 bc 8f d1  |....0..=d&=.t...|
-00000080  16 38 d0 6b 62 eb 82 b0  9a 50 68 aa 7e f7 45 32  |.8.kb....Ph.~.E2|
-00000090  43 cb 84 2d 95 39 6c bc  c8 a0 2d aa ea fe f5 84  |C..-.9l...-.....|
-000000a0  c8 e4 8b 93 a1 15 03 00  00 20 03 7b 3e 43 1d 0a  |......... .{>C..|
-000000b0  9b 9b e3 17 0f de be 75  e5 6e 2f 5b e8 8d a8 68  |.......u.n/[...h|
-000000c0  4e f0 82 49 00 dd b6 95  b4 22                    |N..I....."|
+00000000  14 03 00 00 01 01 16 03  00 00 40 28 76 de 29 3b  |..........@(v.);|
+00000010  48 77 56 f1 e5 97 21 20  88 9c 7d 5e 02 3d bb c9  |HwV...! ..}^.=..|
+00000020  2f b1 ce 2e 65 ac 53 ea  a2 06 0e fb cf 53 28 1d  |/...e.S......S(.|
+00000030  df b3 24 48 52 7a 28 d6  9e 50 83 64 da 34 c1 f4  |..$HRz(..P.d.4..|
+00000040  c9 bf ec 42 33 c4 8a 6f  89 aa 1c 17 03 00 00 20  |...B3..o....... |
+00000050  f2 af bb 38 4f 37 58 0e  c4 2b 28 45 01 45 89 e9  |...8O7X..+(E.E..|
+00000060  31 5a 6d 8d 4d 1b 49 bd  7d 87 8a 62 e6 c8 03 43  |1Zm.M.I.}..b...C|
+00000070  17 03 00 00 30 60 ec e4  6f ec 88 33 d8 89 49 73  |....0`..o..3..Is|
+00000080  3a aa 67 ab 45 9f de c7  3f 0e 39 3d 9a 30 99 9c  |:.g.E...?.9=.0..|
+00000090  2d 10 5f f0 7d 70 10 d5  8e ca 18 91 25 e8 9d d1  |-._.}p......%...|
+000000a0  36 b0 a7 90 9b 15 03 00  00 20 63 e9 92 98 7d b1  |6........ c...}.|
+000000b0  9a 88 07 37 b2 27 99 95  b9 16 17 74 c2 42 9c dc  |...7.'.....t.B..|
+000000c0  80 32 de f4 f6 87 cb f1  87 d8                    |.2........|
diff --git a/src/crypto/tls/testdata/Server-SSLv3-RSA-RC4 b/src/crypto/tls/testdata/Server-SSLv3-RSA-RC4
index 39124c6..dce3ebe 100644
--- a/src/crypto/tls/testdata/Server-SSLv3-RSA-RC4
+++ b/src/crypto/tls/testdata/Server-SSLv3-RSA-RC4
@@ -1,8 +1,8 @@
 >>> Flow 1 (client to server)
-00000000  16 03 00 00 2f 01 00 00  2b 03 00 a7 1d 3d ed 0f  |..../...+....=..|
-00000010  2c 7b 1f f1 c8 1c a9 17  ce 69 e2 73 a2 07 d2 91  |,{.......i.s....|
-00000020  e9 27 fa 70 11 6f 18 6d  2a 25 f1 00 00 04 00 05  |.'.p.o.m*%......|
-00000030  00 ff 01 00                                       |....|
+00000000  16 03 00 00 30 01 00 00  2c 03 00 3c 64 40 96 81  |....0...,..<d at ..|
+00000010  b4 90 3d a5 bb 90 8a ba  39 73 4c cd 2d f9 4c 12  |..=.....9sL.-.L.|
+00000020  4c 6e d6 09 43 e3 eb 07  2e 52 1a 00 00 04 00 05  |Ln..C....R......|
+00000030  00 ff 02 01 00                                    |.....|
 >>> Flow 2 (server to client)
 00000000  16 03 00 00 31 02 00 00  2d 03 00 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -49,26 +49,26 @@
 000002a0  a4 c2 41 34 ac cc f6 ea  b0 ab 39 18 16 03 00 00  |..A4......9.....|
 000002b0  04 0e 00 00 00                                    |.....|
 >>> Flow 3 (client to server)
-00000000  16 03 00 00 84 10 00 00  80 25 85 a3 22 29 e4 fb  |.........%..")..|
-00000010  53 b9 a3 6b ed 70 2b 35  7f db 08 35 b8 4c 95 cd  |S..k.p+5...5.L..|
-00000020  00 ec 5e a1 2e ba e9 ac  a6 d4 ef ca 74 a0 12 1b  |..^.........t...|
-00000030  a7 ec 76 22 2c 63 71 1a  3a 50 94 ce 96 c4 d7 76  |..v",cq.:P.....v|
-00000040  1f 47 58 c7 57 98 af ea  7e 57 05 68 d3 f9 87 02  |.GX.W...~W.h....|
-00000050  35 72 35 66 08 b4 cf 48  24 15 92 d5 ba 46 8d 60  |5r5f...H$....F.`|
-00000060  5a 53 0b e4 9b 53 44 55  dc 77 d1 e4 e0 25 51 f6  |ZS...SDU.w...%Q.|
-00000070  f1 7c 96 0b 32 d4 8c 04  d3 3d e6 70 c7 d6 60 a7  |.|..2....=.p..`.|
-00000080  ae 69 22 69 41 1a 8d 12  67 14 03 00 00 01 01 16  |.i"iA...g.......|
-00000090  03 00 00 3c 32 dd 86 fd  5b 53 74 ea 01 45 5b 9e  |...<2...[St..E[.|
-000000a0  32 d0 9d 27 e8 ce 4c d5  a1 c2 d3 2e 0a e9 e5 d2  |2..'..L.........|
-000000b0  04 8c 77 a3 ff e9 8b 02  14 16 af 54 db ec c4 98  |..w........T....|
-000000c0  72 50 f7 65 fa eb ac 11  07 81 d7 fa 4e 18 34 bc  |rP.e........N.4.|
+00000000  16 03 00 00 84 10 00 00  80 00 e0 40 dd e4 0f 54  |........... at ...T|
+00000010  40 66 62 06 72 2a 7a 06  2d a9 0f 16 3b 5c 63 9b  |@fb.r*z.-...;\c.|
+00000020  95 82 9c d4 95 57 c0 37  d1 30 6a 33 e1 5a ec 93  |.....W.7.0j3.Z..|
+00000030  12 ec 2a 94 c6 9c b3 6c  a3 4f ef cd f1 80 25 a7  |..*....l.O....%.|
+00000040  54 ca 6a 6e b9 80 0b fc  f1 e9 60 a0 f5 33 24 3b  |T.jn......`..3$;|
+00000050  13 04 9a f1 8a 37 cd 11  cf 95 ae 71 ba 73 8e 00  |.....7.....q.s..|
+00000060  86 17 6a 3b d5 9e a9 04  87 fd 62 ed 4c b5 01 55  |..j;......b.L..U|
+00000070  65 a2 fb e8 1d 86 a5 58  2a ad e7 fd d3 44 2f 7d  |e......X*....D/}|
+00000080  25 b7 3b c7 75 39 5c 45  f6 14 03 00 00 01 01 16  |%.;.u9\E........|
+00000090  03 00 00 3c e6 58 15 b2  fb 0d 44 ed 43 d5 ff a8  |...<.X....D.C...|
+000000a0  41 25 83 41 46 da f6 8e  70 34 39 c6 6c 2c ea 1b  |A%.AF...p49.l,..|
+000000b0  2a 02 5c 4b e4 87 58 33  6c d0 22 2e ce 85 df 31  |*.\K..X3l."....1|
+000000c0  0d 71 4c 1a f9 9c 64 d7  87 53 eb c9 1a 0a 16 dc  |.qL...d..S......|
 >>> Flow 4 (server to client)
-00000000  14 03 00 00 01 01 16 03  00 00 3c 29 af 2c 96 3a  |..........<).,.:|
-00000010  be a0 91 a8 e4 66 6b 30  ba e2 80 fc a2 8a 09 b4  |.....fk0........|
-00000020  28 14 3b 36 c2 3b 3e 88  e2 10 da 93 af 71 9a 06  |(.;6.;>......q..|
-00000030  1c 8d 97 04 05 ec e2 69  cf 28 20 0f ec 4c a7 f3  |.......i.( ..L..|
-00000040  18 4e 6b 5b 88 9c a9 17  03 00 00 21 5e 0b b4 2d  |.Nk[.......!^..-|
-00000050  a6 b5 0b 3a 86 de 8a e7  87 f3 4c f6 74 7e 0d 16  |...:......L.t~..|
-00000060  9b fc 0c 42 6b f4 9e 15  8b 6a c5 97 88 15 03 00  |...Bk....j......|
-00000070  00 16 f0 a4 e2 16 bf 81  05 ad 1d f5 1c 89 d9 ab  |................|
-00000080  48 23 ab 96 ea 92 aa cd                           |H#......|
+00000000  14 03 00 00 01 01 16 03  00 00 3c 17 a2 5b 4a 06  |..........<..[J.|
+00000010  63 6a 4b f9 ef 66 ed 31  f6 87 75 20 8b 08 8d 5d  |cjK..f.1..u ...]|
+00000020  0f 72 87 dd 8d db 99 d5  06 42 2b a3 84 77 35 f2  |.r.......B+..w5.|
+00000030  1d 11 ae 0b 0c df ed 10  6e 23 27 93 29 65 25 f6  |........n#'.)e%.|
+00000040  60 b9 76 c8 95 2b 0c 17  03 00 00 21 df 08 e8 1f  |`.v..+.....!....|
+00000050  2f ea 5a 61 d6 d4 4a c0  c1 b5 59 bc e1 89 6e 88  |/.Za..J...Y...n.|
+00000060  bb 8d 16 db 64 87 31 6c  2d d6 c7 d2 ed 15 03 00  |....d.1l-.......|
+00000070  00 16 a9 53 32 af 7a a4  88 02 93 6b aa 95 84 4f  |...S2.z....k...O|
+00000080  17 5a 97 93 67 87 3b 07                           |.Z..g.;.|
diff --git a/src/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES b/src/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES
index f81ffc2..9314b90 100644
--- a/src/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES
+++ b/src/crypto/tls/testdata/Server-TLSv10-ECDHE-ECDSA-AES
@@ -1,13 +1,11 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 7d 01 00 00  79 03 01 65 14 3f 40 e4  |....}...y..e.?@.|
-00000010  2f 74 65 7e d0 c8 87 03  59 61 9d c3 84 5e c9 62  |/te~....Ya...^.b|
-00000020  e6 46 b8 0c 4a 5e 3f 33  43 a5 dd 00 00 04 c0 0a  |.F..J^?3C.......|
-00000030  00 ff 02 01 00 00 4b 00  0b 00 04 03 00 01 02 00  |......K.........|
-00000040  0a 00 3a 00 38 00 0e 00  0d 00 19 00 1c 00 0b 00  |..:.8...........|
-00000050  0c 00 1b 00 18 00 09 00  0a 00 1a 00 16 00 17 00  |................|
-00000060  08 00 06 00 07 00 14 00  15 00 04 00 05 00 12 00  |................|
-00000070  13 00 01 00 02 00 03 00  0f 00 10 00 11 00 0f 00  |................|
-00000080  01 01                                             |..|
+00000000  16 03 01 00 5f 01 00 00  5b 03 01 ad 87 94 6b 8a  |...._...[.....k.|
+00000010  38 9e 70 d6 94 8a 73 a9  39 d8 d7 25 ab 47 92 4c  |8.p...s.9..%.G.L|
+00000020  b1 20 8e 4d f3 7b cd 84  5e 13 c1 00 00 04 c0 0a  |. .M.{..^.......|
+00000030  00 ff 02 01 00 00 2d 00  0b 00 04 03 00 01 02 00  |......-.........|
+00000040  0a 00 1c 00 1a 00 17 00  19 00 1c 00 1b 00 18 00  |................|
+00000050  1a 00 16 00 0e 00 0d 00  0b 00 0c 00 09 00 0a 00  |................|
+00000060  0f 00 01 01                                       |....|
 >>> Flow 2 (server to client)
 00000000  16 03 01 00 31 02 00 00  2d 03 01 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -50,36 +48,36 @@
 00000260  75 71 b5 e5 54 5b 12 2e  8f 09 67 fd a7 24 20 3e  |uq..T[....g..$ >|
 00000270  b2 56 1c ce 97 28 5e f8  2b 2d 4f 9e f1 07 9f 6c  |.V...(^.+-O....l|
 00000280  4b 5b 83 56 e2 32 42 e9  58 b6 d7 49 a6 b5 68 1a  |K[.V.2B.X..I..h.|
-00000290  41 03 56 6b dc 5a 89 00  8b 30 81 88 02 42 01 3e  |A.Vk.Z...0...B.>|
-000002a0  79 81 6e 89 cd 3e 3f ec  e4 b5 75 17 28 ee fb 09  |y.n..>?...u.(...|
-000002b0  21 19 6f 3c e6 ca 1e f2  18 b6 47 f8 37 05 1c 85  |!.o<......G.7...|
-000002c0  0f a4 b8 6b 40 04 50 77  e3 05 9b 24 b8 93 e8 4d  |...k at .Pw...$...M|
-000002d0  ef 30 cd 51 90 58 a2 49  71 b3 3f b9 46 ab a9 72  |.0.Q.X.Iq.?.F..r|
-000002e0  02 42 01 58 ef 20 c1 0a  33 f8 fd 50 9e 65 f5 ef  |.B.X. ..3..P.e..|
-000002f0  f4 91 49 2d d2 de 66 2b  97 69 7d b1 d0 ef d6 91  |..I-..f+.i}.....|
-00000300  0f fc 57 2b 73 b9 49 01  33 d2 1b 5b 9a 2c 51 35  |..W+s.I.3..[.,Q5|
-00000310  0e eb 38 53 fa 20 07 84  52 b3 43 24 09 5a 32 c0  |..8S. ..R.C$.Z2.|
-00000320  32 17 34 6c 16 03 01 00  04 0e 00 00 00           |2.4l.........|
+00000290  41 03 56 6b dc 5a 89 00  8b 30 81 88 02 42 00 8b  |A.Vk.Z...0...B..|
+000002a0  48 d5 a3 a0 35 5c 31 f5  0b e8 72 7c 87 31 79 af  |H...5\1...r|.1y.|
+000002b0  7f 12 93 9a f9 df d5 44  bf 08 5a 6b 1c 68 dd 73  |.......D..Zk.h.s|
+000002c0  67 0f 32 41 45 53 bf 74  cf 91 54 e7 7a 88 41 7a  |g.2AES.t..T.z.Az|
+000002d0  15 ea 3d e3 b8 93 c0 3f  24 4c fb ee 25 f1 20 80  |..=....?$L..%. .|
+000002e0  02 42 01 ab 97 5f 8b 8d  22 71 f9 f5 a3 59 69 42  |.B..._.."q...YiB|
+000002f0  06 bd 12 f5 61 53 cb c8  a1 b4 90 87 12 94 9b f8  |....aS..........|
+00000300  b3 1d 34 d9 cd 64 20 9c  92 ec b5 72 35 01 44 3a  |..4..d ....r5.D:|
+00000310  86 e4 54 46 0d 74 1d 4e  d8 41 16 eb ac c3 8a 2f  |..TF.t.N.A...../|
+00000320  20 11 ad bc 16 03 01 00  04 0e 00 00 00           | ............|
 >>> Flow 3 (client to server)
-00000000  16 03 01 00 46 10 00 00  42 41 04 31 74 f8 f6 18  |....F...BA.1t...|
-00000010  55 6a 9b 3b 78 0a 0e f0  c9 91 aa 8e 77 39 0a 88  |Uj.;x.......w9..|
-00000020  a4 d4 f6 04 9d de 89 18  b6 50 12 72 26 9c 8f e1  |.........P.r&...|
-00000030  f0 b2 e6 df ce 3b 46 be  e9 2a 9a e3 7f d1 d5 92  |.....;F..*......|
-00000040  ff e3 ae 0a 2d a1 3b 07  f6 04 59 14 03 01 00 01  |....-.;...Y.....|
-00000050  01 16 03 01 00 30 02 4f  df 41 30 97 6f f7 18 ca  |.....0.O.A0.o...|
-00000060  05 35 17 a1 a2 a5 71 61  b1 d8 dd 9a c6 f3 54 53  |.5....qa......TS|
-00000070  84 f6 fb 93 1e 0e 9d e7  fe 35 85 9e 73 d0 2e a1  |.........5..s...|
-00000080  a7 63 d9 40 c6 ac                                 |.c. at ..|
+00000000  16 03 01 00 46 10 00 00  42 41 04 38 ca 59 61 cd  |....F...BA.8.Ya.|
+00000010  17 4a cf a8 0b 81 c6 b7  7f 52 dd 95 d7 57 9d 24  |.J.......R...W.$|
+00000020  bb b1 02 af 57 ee b9 f9  c5 a0 c3 20 44 e1 9a e4  |....W...... D...|
+00000030  83 64 7d a1 fa 9d 2e 3b  5e be 0f af ed 96 f3 09  |.d}....;^.......|
+00000040  62 a2 22 21 72 f8 84 89  8a fd 10 14 03 01 00 01  |b."!r...........|
+00000050  01 16 03 01 00 30 bd e6  23 e0 32 b8 4c ef ce 9e  |.....0..#.2.L...|
+00000060  22 a5 77 2c f1 7e 2f 8d  8b 9e a5 92 42 f9 0f 02  |".w,.~/.....B...|
+00000070  eb 2e 94 f1 6d a3 24 3f  c0 ae bb c0 c4 99 08 51  |....m.$?.......Q|
+00000080  47 28 8b 4e f9 02                                 |G(.N..|
 >>> Flow 4 (server to client)
-00000000  14 03 01 00 01 01 16 03  01 00 30 07 7e 4e 9c 19  |..........0.~N..|
-00000010  f0 35 cd 02 b7 a6 0a 1a  b1 a8 11 a3 f9 b1 35 7b  |.5............5{|
-00000020  96 7f e6 e1 00 c6 6d 9e  e6 8a bb a2 b8 bd a3 9d  |......m.........|
-00000030  05 22 1b f1 f5 28 4a 00  6e f1 71 17 03 01 00 20  |."...(J.n.q.... |
-00000040  ad c7 4c dc f4 81 1a 39  3d 86 5e 8e f5 0d a3 33  |..L....9=.^....3|
-00000050  88 32 e7 be 8b 6a 8d 44  29 7b 47 fd e5 33 01 1e  |.2...j.D){G..3..|
-00000060  17 03 01 00 30 61 47 ee  ae 89 25 ac 85 3b 8a 84  |....0aG...%..;..|
-00000070  47 61 ea 3e 4c 70 57 07  d6 f1 1c 21 cb 44 7e de  |Ga.>LpW....!.D~.|
-00000080  b5 01 9e fb fe ad bc be  74 c0 65 a0 6b c1 0c 8c  |........t.e.k...|
-00000090  2b 00 24 c6 b7 15 03 01  00 20 b7 8b 6b e5 77 ab  |+.$...... ..k.w.|
-000000a0  f6 50 9e 88 4d 56 a8 25  8d 02 db cb 68 8b 3f 62  |.P..MV.%....h.?b|
-000000b0  be aa 02 24 75 b1 e5 4b  18 c9                    |...$u..K..|
+00000000  14 03 01 00 01 01 16 03  01 00 30 11 a9 f0 95 27  |..........0....'|
+00000010  ac 0a b7 8e 0d 42 0a 2a  f8 f8 e2 4f 4f 4a 79 d1  |.....B.*...OOJy.|
+00000020  73 e6 4d 42 90 3c 06 f8  7b da 26 cc 58 be 97 f6  |s.MB.<..{.&.X...|
+00000030  41 32 fb 39 2f fa e1 bc  59 2b 45 17 03 01 00 20  |A2.9/...Y+E.... |
+00000040  93 6a a1 a6 a2 e6 be bb  be 2f 8f 0c 52 39 1c 6a  |.j......./..R9.j|
+00000050  6d 4c af 38 f7 60 8b ad  0e c7 62 0c 8b a4 42 14  |mL.8.`....b...B.|
+00000060  17 03 01 00 30 da b0 1b  ef cf 45 86 09 e9 be aa  |....0.....E.....|
+00000070  0f 71 af a3 86 d0 0f 2d  e8 76 39 9a c4 1f f5 c2  |.q.....-.v9.....|
+00000080  82 0a ee 34 0e a6 3b 19  b8 2c 10 ad fc 03 33 31  |...4..;..,....31|
+00000090  10 42 9b 6e 7b 15 03 01  00 20 ac 73 4d 4b 92 30  |.B.n{.... .sMK.0|
+000000a0  bf 4c bc 77 c1 87 d7 20  ad 82 bd 75 31 82 0d 34  |.L.w... ...u1..4|
+000000b0  cb b2 86 fd 4f 9c 84 a3  80 af                    |....O.....|
diff --git a/src/crypto/tls/testdata/Server-TLSv10-RSA-3DES b/src/crypto/tls/testdata/Server-TLSv10-RSA-3DES
index 55cb487..33e8063 100644
--- a/src/crypto/tls/testdata/Server-TLSv10-RSA-3DES
+++ b/src/crypto/tls/testdata/Server-TLSv10-RSA-3DES
@@ -1,8 +1,8 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 36 01 00 00  32 03 01 35 4a e8 32 84  |....6...2..5J.2.|
-00000010  51 68 04 7e d0 0f 43 94  c7 5d 44 d2 95 a3 12 63  |Qh.~..C..]D....c|
-00000020  77 c5 ce 78 5a 25 a3 81  df c4 6b 00 00 04 00 0a  |w..xZ%....k.....|
-00000030  00 ff 01 00 00 05 00 0f  00 01 01                 |...........|
+00000000  16 03 01 00 37 01 00 00  33 03 01 8d f4 8c 3d bd  |....7...3.....=.|
+00000010  d8 81 53 bb f5 bc 18 69  07 09 0d 05 93 4f 6f eb  |..S....i.....Oo.|
+00000020  fa fb 03 65 d4 49 a3 df  9f c3 a5 00 00 04 00 0a  |...e.I..........|
+00000030  00 ff 02 01 00 00 05 00  0f 00 01 01              |............|
 >>> Flow 2 (server to client)
 00000000  16 03 01 00 31 02 00 00  2d 03 01 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -49,26 +49,26 @@
 000002a0  a4 c2 41 34 ac cc f6 ea  b0 ab 39 18 16 03 01 00  |..A4......9.....|
 000002b0  04 0e 00 00 00                                    |.....|
 >>> Flow 3 (client to server)
-00000000  16 03 01 00 86 10 00 00  82 00 80 1f 4d 12 64 f2  |............M.d.|
-00000010  72 22 86 4a 16 05 3f d2  1b e5 ed a7 f1 19 c4 6d  |r".J..?........m|
-00000020  1d 3a 5c f6 46 8f b9 4d  9e c4 d4 19 95 0a 63 9f  |.:\.F..M......c.|
-00000030  8a 41 1f fc d5 98 45 ca  69 33 37 64 d5 c8 0e 5a  |.A....E.i37d...Z|
-00000040  12 9f 06 54 8a 61 8b 13  f0 d8 fb b9 97 fb cd 1d  |...T.a..........|
-00000050  bd 6c 88 cc 98 57 c3 66  3a 86 04 c9 b9 21 c6 f2  |.l...W.f:....!..|
-00000060  f3 43 7d 4e bf 28 d5 a2  d7 39 e0 78 cb eb b4 af  |.C}N.(...9.x....|
-00000070  21 0e ae 4c 16 9b b3 49  5f 81 02 55 59 97 d9 d2  |!..L...I_..UY...|
-00000080  c4 e2 4c be 0a a6 41 62  48 1d 66 14 03 01 00 01  |..L...AbH.f.....|
-00000090  01 16 03 01 00 28 9d e0  c3 31 82 c2 48 5d fb 47  |.....(...1..H].G|
-000000a0  85 60 d4 17 d2 4f 4d 3c  64 db e4 49 1f a9 66 93  |.`...OM<d..I..f.|
-000000b0  72 6c 32 06 a5 0c 1f db  64 6d 54 71 fd 30        |rl2.....dmTq.0|
+00000000  16 03 01 00 86 10 00 00  82 00 80 6b 00 e3 47 e3  |...........k..G.|
+00000010  0d 22 44 53 7a b9 d1 14  4e e4 47 17 a1 e2 f5 d2  |."DSz...N.G.....|
+00000020  f7 82 2f 1b e2 3a 60 aa  79 36 fa 74 05 72 66 88  |../..:`.y6.t.rf.|
+00000030  3f 6a 57 8d 10 8a a1 80  3c 74 5b 29 c3 a1 b8 57  |?jW.....<t[)...W|
+00000040  20 cc 75 fc 0e 3c 09 06  46 52 b2 ca b2 cd bf 4c  | .u..<..FR.....L|
+00000050  b3 12 2b 59 f1 41 a2 c7  4c 62 c7 61 26 2b 89 fe  |..+Y.A..Lb.a&+..|
+00000060  01 9a b6 2b b4 15 75 05  4b f8 5b 04 9a 64 cc 06  |...+..u.K.[..d..|
+00000070  6b 8c 98 6d 51 37 50 b4  69 03 5c 9a ed e3 9a 23  |k..mQ7P.i.\....#|
+00000080  a9 68 e0 56 58 f7 f4 a0  d6 b4 55 14 03 01 00 01  |.h.VX.....U.....|
+00000090  01 16 03 01 00 28 9f ac  be d9 6f ab cb 0e 45 8a  |.....(....o...E.|
+000000a0  96 71 fd 23 39 b0 02 cc  a6 5a 7a 64 e2 29 9f 18  |.q.#9....Zzd.)..|
+000000b0  dc 25 84 ee 76 56 3c cc  d9 15 34 16 67 7e        |.%..vV<...4.g~|
 >>> Flow 4 (server to client)
-00000000  14 03 01 00 01 01 16 03  01 00 28 94 66 8f ad 8f  |..........(.f...|
-00000010  9f 00 72 f6 af 51 47 67  63 df 3f dd 17 09 0a c5  |..r..QGgc.?.....|
-00000020  bf f8 4d 66 39 f9 b5 47  01 f8 e8 6d ed b4 17 39  |..Mf9..G...m...9|
-00000030  ff 0a ca 17 03 01 00 18  68 93 94 51 12 b9 17 0b  |........h..Q....|
-00000040  d1 a0 22 fc cc c4 76 1a  1e 02 c6 20 5e 74 83 4c  |.."...v.... ^t.L|
-00000050  17 03 01 00 28 08 bd 86  07 84 90 78 bd 1d 90 ce  |....(......x....|
-00000060  09 80 bb d8 de fd 39 82  4b c4 0d 06 f3 65 f5 5b  |......9.K....e.[|
-00000070  3d c3 fd 69 80 1f 51 ce  1d 98 f1 05 fa 15 03 01  |=..i..Q.........|
-00000080  00 18 ed 48 04 21 85 77  d7 b6 29 e3 25 af ea ec  |...H.!.w..).%...|
-00000090  3e 41 82 a0 ca 7d 44 79  8a 0b                    |>A...}Dy..|
+00000000  14 03 01 00 01 01 16 03  01 00 28 f4 cf 23 f8 86  |..........(..#..|
+00000010  83 df 44 af 1c 25 b1 51  84 5b 6a f3 0e 6b 47 5c  |..D..%.Q.[j..kG\|
+00000020  2a 59 67 db 42 11 f9 53  58 4e db 6f 00 b2 20 5b  |*Yg.B..SXN.o.. [|
+00000030  ae a3 43 17 03 01 00 18  df e0 22 d6 05 ab 79 c7  |..C......."...y.|
+00000040  87 8a 82 83 01 bc 06 45  36 74 4d 1c 40 96 97 5f  |.......E6tM. at .._|
+00000050  17 03 01 00 28 49 bd b7  e9 41 6b eb b1 aa 89 60  |....(I...Ak....`|
+00000060  21 91 df bf f4 7a 49 9d  54 04 4a 16 1a d1 44 9a  |!....zI.T.J...D.|
+00000070  09 6c 4f 01 3d c0 2f d5  a3 72 a3 b2 fe 15 03 01  |.lO.=./..r......|
+00000080  00 18 5c 7a de a0 ef ed  56 99 99 01 5f b4 32 b3  |..\z....V..._.2.|
+00000090  00 be c6 cc 7e bb 6f 82  7d f7                    |....~.o.}.|
diff --git a/src/crypto/tls/testdata/Server-TLSv10-RSA-AES b/src/crypto/tls/testdata/Server-TLSv10-RSA-AES
index 4671302..e51bc17 100644
--- a/src/crypto/tls/testdata/Server-TLSv10-RSA-AES
+++ b/src/crypto/tls/testdata/Server-TLSv10-RSA-AES
@@ -1,8 +1,8 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 36 01 00 00  32 03 01 8c 5a 87 31 6a  |....6...2...Z.1j|
-00000010  8c 7a d5 26 4b 94 17 27  fc a2 c0 5f b5 bc 3f 10  |.z.&K..'..._..?.|
-00000020  80 0e e0 1e 36 80 4b 91  61 77 d4 00 00 04 00 2f  |....6.K.aw...../|
-00000030  00 ff 01 00 00 05 00 0f  00 01 01                 |...........|
+00000000  16 03 01 00 37 01 00 00  33 03 01 39 72 8e 06 ed  |....7...3..9r...|
+00000010  d2 74 5c 02 74 0e 2b 7a  bd 54 ce be 17 a0 4f 1a  |.t\.t.+z.T....O.|
+00000020  c5 72 b1 e8 3e 2e 90 68  ff fc 6e 00 00 04 00 2f  |.r..>..h..n..../|
+00000030  00 ff 02 01 00 00 05 00  0f 00 01 01              |............|
 >>> Flow 2 (server to client)
 00000000  16 03 01 00 31 02 00 00  2d 03 01 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -49,29 +49,29 @@
 000002a0  a4 c2 41 34 ac cc f6 ea  b0 ab 39 18 16 03 01 00  |..A4......9.....|
 000002b0  04 0e 00 00 00                                    |.....|
 >>> Flow 3 (client to server)
-00000000  16 03 01 00 86 10 00 00  82 00 80 31 f5 2e e4 c7  |...........1....|
-00000010  f5 76 d6 f7 2d 1b 8d 4d  a9 2a 43 84 b2 0b 08 d6  |.v..-..M.*C.....|
-00000020  4d d9 9a eb 4b 01 49 6e  11 45 43 0d 31 a7 c3 66  |M...K.In.EC.1..f|
-00000030  da 1c 92 68 fb 3d 36 27  94 2f 67 ae 3d 31 a3 8f  |...h.=6'./g.=1..|
-00000040  01 5a d9 17 92 bc 20 7c  cb ae b4 ca 4c ce d4 a9  |.Z.... |....L...|
-00000050  2c 1d fe fc 3c a9 14 31  1d 65 08 d8 6e 8d ac 9d  |,...<..1.e..n...|
-00000060  21 ee 63 4a e2 da 3c 0e  b1 34 8f 6e 20 dd d4 d4  |!.cJ..<..4.n ...|
-00000070  d8 16 27 5d 02 54 e6 ec  5f 43 84 5b 21 24 ef 5d  |..'].T.._C.[!$.]|
-00000080  45 c4 2b 2c 98 7d 50 dc  0b fc 76 14 03 01 00 01  |E.+,.}P...v.....|
-00000090  01 16 03 01 00 30 ef 50  ea 3c e3 b7 a8 5b 9a d2  |.....0.P.<...[..|
-000000a0  11 69 0f d0 5e 79 c8 cb  68 4a ac 16 ef b4 de 1f  |.i..^y..hJ......|
-000000b0  21 0b 8e 91 cb 70 3f 02  bd 45 c1 34 02 e0 66 8a  |!....p?..E.4..f.|
-000000c0  00 ea 6c 5a 96 41                                 |..lZ.A|
+00000000  16 03 01 00 86 10 00 00  82 00 80 0e a2 23 fe 89  |.............#..|
+00000010  46 08 20 98 da 4d 91 a4  48 40 ab 03 df 1f 00 67  |F. ..M..H at .....g|
+00000020  f3 fb fb 22 f7 8e d6 65  2c 43 a7 f4 9c 0e 25 cc  |..."...e,C....%.|
+00000030  d9 3b b5 58 df bd 93 27  1c df 69 37 27 01 cb 0d  |.;.X...'..i7'...|
+00000040  b4 f4 a6 8d 91 fe ef dc  9a e2 09 7c 53 1a 73 6d  |...........|S.sm|
+00000050  b9 f6 89 0a 1f 94 f0 26  25 ef 73 54 20 d5 8d 77  |.......&%.sT ..w|
+00000060  36 2e e7 4c 9a f1 4a be  ae 6e b6 be 16 10 31 42  |6..L..J..n....1B|
+00000070  9e d2 49 41 2c 32 52 11  bc 85 2d fa 39 80 9b f9  |..IA,2R...-.9...|
+00000080  95 fe e8 88 2a a2 57 65  7e 38 b2 14 03 01 00 01  |....*.We~8......|
+00000090  01 16 03 01 00 30 1c 6f  91 45 16 ed 25 82 ee 5f  |.....0.o.E..%.._|
+000000a0  f9 f0 09 0c a4 ad 56 61  e5 b7 a2 05 50 02 b8 80  |......Va....P...|
+000000b0  ef 73 d1 11 3c 25 50 44  0d ba b5 7c fd 5d 7a df  |.s..<%PD...|.]z.|
+000000c0  14 62 1b 29 be 29                                 |.b.).)|
 >>> Flow 4 (server to client)
-00000000  14 03 01 00 01 01 16 03  01 00 30 99 2c 65 32 5f  |..........0.,e2_|
-00000010  53 37 d8 c2 98 87 f4 68  b6 d7 52 6a 14 c7 df 6e  |S7.....h..Rj...n|
-00000020  bb ce ae 31 d4 04 24 4d  e9 c2 39 7b 68 a7 fa 90  |...1..$M..9{h...|
-00000030  c1 30 14 a2 20 c0 8d e1  2a dc 22 17 03 01 00 20  |.0.. ...*.".... |
-00000040  41 c5 03 05 20 53 e9 fa  0a 26 38 ab 84 6a 5e 36  |A... S...&8..j^6|
-00000050  1b 03 80 2f c3 5c 0b 2c  bd 7f 79 68 bb ab 4d 70  |.../.\.,..yh..Mp|
-00000060  17 03 01 00 30 a1 04 3e  f4 a2 54 7a e7 09 0f 20  |....0..>..Tz... |
-00000070  38 f8 9e bb 1b 61 28 bf  46 e8 75 56 b4 c3 93 b9  |8....a(.F.uV....|
-00000080  8c 18 3e 8e af 9f 59 1a  96 be db 61 80 56 c6 09  |..>...Y....a.V..|
-00000090  3c 21 02 37 d2 15 03 01  00 20 13 d1 81 7d ca 04  |<!.7..... ...}..|
-000000a0  2b c3 fc fa 06 5b b4 98  59 27 0d 07 2a 39 3c 6f  |+....[..Y'..*9<o|
-000000b0  8d 64 83 17 0f ba ec 22  21 36                    |.d....."!6|
+00000000  14 03 01 00 01 01 16 03  01 00 30 5e 8c b1 dc 1f  |..........0^....|
+00000010  b3 18 85 4a 46 02 fb 34  e4 05 56 78 4c e3 34 63  |...JF..4..VxL.4c|
+00000020  06 08 b4 ee 36 e2 28 ab  c9 98 ee 26 4e 5b 5d 42  |....6.(....&N[]B|
+00000030  5f f8 e1 d1 2f 8b c8 ef  5a 65 40 17 03 01 00 20  |_.../...Ze at .... |
+00000040  e7 92 6e b1 60 b9 f8 cd  53 d3 37 5b 44 74 1c af  |..n.`...S.7[Dt..|
+00000050  90 93 13 8e 55 25 cc 9f  57 8c f3 06 f7 ba e0 f9  |....U%..W.......|
+00000060  17 03 01 00 30 fc 83 e6  4e 8c 65 8f d1 7c c7 f4  |....0...N.e..|..|
+00000070  8b 68 0d 5d da 8e 49 45  68 ea 4c e3 7f 7d 84 87  |.h.]..IEh.L..}..|
+00000080  2f 63 e0 fb 43 24 04 cd  e2 38 32 50 0a 4c 43 ce  |/c..C$...82P.LC.|
+00000090  3b 12 a5 6b 99 15 03 01  00 20 2a 42 d8 57 26 79  |;..k..... *B.W&y|
+000000a0  51 ee 79 9d b2 83 b8 49  a4 e9 a2 08 34 73 c4 f5  |Q.y....I....4s..|
+000000b0  53 21 4b 78 ec 5b ce b4  4e a0                    |S!Kx.[..N.|
diff --git a/src/crypto/tls/testdata/Server-TLSv10-RSA-RC4 b/src/crypto/tls/testdata/Server-TLSv10-RSA-RC4
index b5cb479..8d54463 100644
--- a/src/crypto/tls/testdata/Server-TLSv10-RSA-RC4
+++ b/src/crypto/tls/testdata/Server-TLSv10-RSA-RC4
@@ -1,8 +1,8 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 36 01 00 00  32 03 01 c5 fc 32 c0 09  |....6...2....2..|
-00000010  47 0b a9 f3 72 c9 6c 3a  e0 94 33 48 35 ac b9 3b  |G...r.l:..3H5..;|
-00000020  da 5f 8b 6e 0c 54 c3 16  f0 39 bd 00 00 04 00 05  |._.n.T...9......|
-00000030  00 ff 01 00 00 05 00 0f  00 01 01                 |...........|
+00000000  16 03 01 00 37 01 00 00  33 03 01 b3 82 99 50 b0  |....7...3.....P.|
+00000010  1e 7a 46 48 9d 8e 93 32  3b 01 bc 50 e9 5c eb 91  |.zFH...2;..P.\..|
+00000020  25 4b c1 ea 0a 91 c9 b3  2b 54 90 00 00 04 00 05  |%K......+T......|
+00000030  00 ff 02 01 00 00 05 00  0f 00 01 01              |............|
 >>> Flow 2 (server to client)
 00000000  16 03 01 00 31 02 00 00  2d 03 01 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -49,23 +49,23 @@
 000002a0  a4 c2 41 34 ac cc f6 ea  b0 ab 39 18 16 03 01 00  |..A4......9.....|
 000002b0  04 0e 00 00 00                                    |.....|
 >>> Flow 3 (client to server)
-00000000  16 03 01 00 86 10 00 00  82 00 80 6a ad 7f e3 26  |...........j...&|
-00000010  71 da 48 af 11 63 de 2e  e8 50 f9 6a be 04 3d 17  |q.H..c...P.j..=.|
-00000020  d1 29 fe 2c 7f b6 26 c1  7e 0b 18 1c 41 62 5c 91  |.).,..&.~...Ab\.|
-00000030  ee 26 9c 92 f5 d1 e9 29  e1 ca a7 01 6a 41 b9 00  |.&.....)....jA..|
-00000040  34 1d 5b c6 28 0e 1a 8f  32 c5 03 e7 a1 8f 89 1b  |4.[.(...2.......|
-00000050  af 13 22 2b 5b e8 76 2d  00 ac da 27 75 95 75 e7  |.."+[.v-...'u.u.|
-00000060  00 00 39 2c bf f2 01 57  e6 29 e3 26 b1 6b ae c5  |..9,...W.).&.k..|
-00000070  8d ce d2 36 b2 94 1f 9c  30 5e b2 16 3d 20 cf 4d  |...6....0^..= .M|
-00000080  88 f5 ac 4c 27 e3 f5 86  ef 9e dc 14 03 01 00 01  |...L'...........|
-00000090  01 16 03 01 00 24 48 d8  80 c4 37 22 31 99 53 30  |.....$H...7"1.S0|
-000000a0  5b 00 07 7e 87 2e 59 9a  d9 0c 42 9e dd ed da 89  |[..~..Y...B.....|
-000000b0  1a 1f cb ab 55 0c ba d9  a9 c0                    |....U.....|
+00000000  16 03 01 00 86 10 00 00  82 00 80 05 1c 93 2a 69  |..............*i|
+00000010  f7 0b 1d 59 ea ca c2 4a  b1 7c ef 22 4c 7b 31 5f  |...Y...J.|."L{1_|
+00000020  18 8d 32 b6 db 75 8c f8  45 07 27 e1 9f 3f 9d 0b  |..2..u..E.'..?..|
+00000030  02 ac 2c 3f aa bf 79 fb  d4 af 98 0c b2 c0 03 4b  |..,?..y........K|
+00000040  86 26 c3 30 f3 ea 2b 1a  ab 70 90 8d 01 2b 0e ff  |.&.0..+..p...+..|
+00000050  4c 10 9a 29 75 cb 14 bb  85 80 98 35 fb 82 e8 b5  |L..)u......5....|
+00000060  80 6f 9d e6 3b b6 14 36  bb 61 8e 18 f2 6b da 09  |.o..;..6.a...k..|
+00000070  71 9c 6d 1e c3 60 a9 c5  8b 4e 77 41 db ec 12 49  |q.m..`...NwA...I|
+00000080  a4 c2 e2 10 ce 7f 18 05  b9 74 aa 14 03 01 00 01  |.........t......|
+00000090  01 16 03 01 00 24 3d 90  d0 f6 6f 15 94 05 a0 fb  |.....$=...o.....|
+000000a0  43 83 55 b5 b1 ef e5 fd  fc 00 d3 d5 25 b4 7c 9f  |C.U.........%.|.|
+000000b0  e0 82 99 2a 6d 5a 26 7c  05 21                    |...*mZ&|.!|
 >>> Flow 4 (server to client)
-00000000  14 03 01 00 01 01 16 03  01 00 24 ae 00 c8 14 67  |..........$....g|
-00000010  4b b5 21 96 98 91 d6 27  40 9b 5e a5 86 53 56 f3  |K.!....'@.^..SV.|
-00000020  f6 dc 7e b2 49 78 4b 4d  57 7c 62 a5 f2 16 8f 17  |..~.IxKMW|b.....|
-00000030  03 01 00 21 34 e3 48 58  1c 67 fb 3a 46 28 5d a1  |...!4.HX.g.:F(].|
-00000040  19 66 58 b1 bb fb e7 17  71 07 3f 0a d0 7c c9 24  |.fX.....q.?..|.$|
-00000050  c7 ef 41 af 62 15 03 01  00 16 dd dc 16 dc 16 cc  |..A.b...........|
-00000060  0d f3 2c 29 00 c0 4f 01  68 05 92 a0 f7 ad e2 63  |..,)..O.h......c|
+00000000  14 03 01 00 01 01 16 03  01 00 24 28 d0 1f ec 1d  |..........$(....|
+00000010  9e 1d e3 80 6b 6d 3e 8b  c5 f7 9c 14 a9 0b c3 53  |....km>........S|
+00000020  fd 48 d0 b3 eb d1 49 97  97 71 e9 36 b9 e6 3a 17  |.H....I..q.6..:.|
+00000030  03 01 00 21 c3 b6 2e 02  05 86 0f 57 04 dd 88 33  |...!.......W...3|
+00000040  0a ed 1d d5 a8 0f 55 54  c5 8c 87 5b 11 b7 80 7f  |......UT...[....|
+00000050  30 79 e0 64 ee 15 03 01  00 16 b1 50 de 3d 18 05  |0y.d.......P.=..|
+00000060  2f db 37 4c db 62 f1 c8  d5 19 ca c2 fb a5 8a 37  |/.7L.b.........7|
diff --git a/src/crypto/tls/testdata/Server-TLSv11-FallbackSCSV b/src/crypto/tls/testdata/Server-TLSv11-FallbackSCSV
index 2d8dfbc..a6e2137 100644
--- a/src/crypto/tls/testdata/Server-TLSv11-FallbackSCSV
+++ b/src/crypto/tls/testdata/Server-TLSv11-FallbackSCSV
@@ -1,17 +1,17 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 d4 01 00 00  d0 03 02 74 2d da 6d 98  |...........t-.m.|
-00000010  ad 3e a5 ec 90 ea d1 5b  f0 e0 a7 45 33 d9 5e 8d  |.>.....[...E3.^.|
-00000020  0f 1d 01 16 6d 00 31 65  ed 50 88 00 00 5e c0 14  |....m.1e.P...^..|
-00000030  c0 0a 00 39 00 38 00 88  00 87 c0 0f c0 05 00 35  |...9.8.........5|
-00000040  00 84 c0 13 c0 09 00 33  00 32 00 9a 00 99 00 45  |.......3.2.....E|
-00000050  00 44 c0 0e c0 04 00 2f  00 96 00 41 00 07 c0 11  |.D...../...A....|
-00000060  c0 07 c0 0c c0 02 00 05  00 04 c0 12 c0 08 00 16  |................|
-00000070  00 13 c0 0d c0 03 00 0a  00 15 00 12 00 09 00 14  |................|
-00000080  00 11 00 08 00 06 00 03  00 ff 56 00 01 00 00 49  |..........V....I|
-00000090  00 0b 00 04 03 00 01 02  00 0a 00 34 00 32 00 0e  |...........4.2..|
-000000a0  00 0d 00 19 00 0b 00 0c  00 18 00 09 00 0a 00 16  |................|
-000000b0  00 17 00 08 00 06 00 07  00 14 00 15 00 04 00 05  |................|
-000000c0  00 12 00 13 00 01 00 02  00 03 00 0f 00 10 00 11  |................|
-000000d0  00 23 00 00 00 0f 00 01  01                       |.#.......|
+00000000  16 03 01 00 cf 01 00 00  cb 03 02 ee 33 c1 3f a6  |............3.?.|
+00000010  62 ba a6 4f c7 32 25 0f  15 66 f7 35 a2 cf c0 cd  |b..O.2%..f.5....|
+00000020  48 93 77 1c 04 1f fb 65  41 37 ca 00 00 70 c0 14  |H.w....eA7...p..|
+00000030  c0 0a 00 39 00 38 00 37  00 36 00 88 00 87 00 86  |...9.8.7.6......|
+00000040  00 85 c0 0f c0 05 00 35  00 84 c0 13 c0 09 00 33  |.......5.......3|
+00000050  00 32 00 31 00 30 00 9a  00 99 00 98 00 97 00 45  |.2.1.0.........E|
+00000060  00 44 00 43 00 42 c0 0e  c0 04 00 2f 00 96 00 41  |.D.C.B...../...A|
+00000070  00 07 c0 11 c0 07 c0 0c  c0 02 00 05 00 04 c0 12  |................|
+00000080  c0 08 00 16 00 13 00 10  00 0d c0 0d c0 03 00 0a  |................|
+00000090  00 15 00 12 00 0f 00 0c  00 09 00 ff 56 00 02 01  |............V...|
+000000a0  00 00 31 00 0b 00 04 03  00 01 02 00 0a 00 1c 00  |..1.............|
+000000b0  1a 00 17 00 19 00 1c 00  1b 00 18 00 1a 00 16 00  |................|
+000000c0  0e 00 0d 00 0b 00 0c 00  09 00 0a 00 23 00 00 00  |............#...|
+000000d0  0f 00 01 01                                       |....|
 >>> Flow 2 (server to client)
 00000000  15 03 02 00 02 02 56                              |......V|
diff --git a/src/crypto/tls/testdata/Server-TLSv11-RSA-RC4 b/src/crypto/tls/testdata/Server-TLSv11-RSA-RC4
index dc5e765..b3916f9 100644
--- a/src/crypto/tls/testdata/Server-TLSv11-RSA-RC4
+++ b/src/crypto/tls/testdata/Server-TLSv11-RSA-RC4
@@ -1,8 +1,8 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 36 01 00 00  32 03 02 ff e1 a1 04 0b  |....6...2.......|
-00000010  c2 dc fb 7d 07 61 44 9b  00 67 fe 38 73 f5 fc 4e  |...}.aD..g.8s..N|
-00000020  35 94 0a d5 c1 d0 e7 54  dc 44 1f 00 00 04 00 05  |5......T.D......|
-00000030  00 ff 01 00 00 05 00 0f  00 01 01                 |...........|
+00000000  16 03 01 00 37 01 00 00  33 03 02 95 4a cf f5 14  |....7...3...J...|
+00000010  56 9b d6 be 0c ba 0d b2  ad 65 47 d2 c6 ce 84 c9  |V........eG.....|
+00000020  f4 80 2a 4e 75 df ff 48  cf 48 9b 00 00 04 00 05  |..*Nu..H.H......|
+00000030  00 ff 02 01 00 00 05 00  0f 00 01 01              |............|
 >>> Flow 2 (server to client)
 00000000  16 03 02 00 31 02 00 00  2d 03 02 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -49,23 +49,23 @@
 000002a0  a4 c2 41 34 ac cc f6 ea  b0 ab 39 18 16 03 02 00  |..A4......9.....|
 000002b0  04 0e 00 00 00                                    |.....|
 >>> Flow 3 (client to server)
-00000000  16 03 02 00 86 10 00 00  82 00 80 4c e0 4d 6a 19  |...........L.Mj.|
-00000010  a2 72 2a 3d 41 14 a7 b3  0a 25 11 bf c9 9f cf 8c  |.r*=A....%......|
-00000020  3c 0b 01 49 aa f1 59 4b  60 ac e5 72 9b ec 20 41  |<..I..YK`..r.. A|
-00000030  2f 7e ef bf e0 fe 13 c0  1d fd 51 c5 08 c6 9a 9e  |/~........Q.....|
-00000040  74 88 c7 e3 36 99 73 fd  00 2d a2 6a bd 25 f2 d7  |t...6.s..-.j.%..|
-00000050  24 fd fd ab 0c e0 18 38  ba 7b f0 c9 c0 58 a6 d0  |$......8.{...X..|
-00000060  4e e2 59 70 aa f4 52 34  12 a0 ec a4 53 1e 8b ee  |N.Yp..R4....S...|
-00000070  3e bf a4 87 da 02 4c 95  bd 10 af e8 88 c9 ce 87  |>.....L.........|
-00000080  3c 9e 91 70 91 a0 85 18  84 e4 e0 14 03 02 00 01  |<..p............|
-00000090  01 16 03 02 00 24 c5 c0  27 71 49 ad ed 37 e6 5d  |.....$..'qI..7.]|
-000000a0  1b 78 3e 74 15 b7 61 e5  f3 af 1e d0 a2 85 b3 13  |.x>t..a.........|
-000000b0  6e 5e 9a c7 3d 47 32 4d  1b 8d                    |n^..=G2M..|
+00000000  16 03 02 00 86 10 00 00  82 00 80 19 c3 d4 f2 e4  |................|
+00000010  bf 4a 52 90 a4 65 f6 e7  29 1a 7f ef 0e a4 1e b4  |.JR..e..).......|
+00000020  c2 df b2 83 43 4a 1a f4  b6 cd 51 a5 24 62 3f e1  |....CJ....Q.$b?.|
+00000030  fb 5f 7e b1 10 08 3b 8a  ab eb 3a a3 72 ba 31 1c  |._~...;...:.r.1.|
+00000040  23 bd ef 2e 3d 13 dc 61  88 a6 af ca 80 82 5d e4  |#...=..a......].|
+00000050  d6 a2 d3 13 80 87 c6 ad  a5 13 4e f1 b6 a0 5d fa  |..........N...].|
+00000060  ed a7 0d 37 58 f1 54 38  18 f5 be db 90 9f 07 4a  |...7X.T8.......J|
+00000070  67 25 c9 8d 9d 5e 07 62  ca db 72 74 b5 bd a0 ed  |g%...^.b..rt....|
+00000080  d0 95 9f 3e cd 37 b8 96  df df 3b 14 03 02 00 01  |...>.7....;.....|
+00000090  01 16 03 02 00 24 80 53  7a 8f 23 06 a7 6b e6 be  |.....$.Sz.#..k..|
+000000a0  61 c2 1a c8 35 30 6b e2  2f 82 f3 46 ff e3 1d bd  |a...50k./..F....|
+000000b0  68 e9 a2 78 49 33 05 ca  d9 41                    |h..xI3...A|
 >>> Flow 4 (server to client)
-00000000  14 03 02 00 01 01 16 03  02 00 24 31 22 76 4d 43  |..........$1"vMC|
-00000010  7a 8a 58 2c 7d 1c 41 39  bf 08 7e 82 17 55 52 b3  |z.X,}.A9..~..UR.|
-00000020  81 bd 7a f8 3c bf 9c 2b  f0 9b 3f 65 f5 42 15 17  |..z.<..+..?e.B..|
-00000030  03 02 00 21 b1 cc e5 56  16 70 58 0b 91 3c 8c 46  |...!...V.pX..<.F|
-00000040  0e 3b b6 fe 32 5d 2e b0  8c 6a 1c a0 82 c9 43 81  |.;..2]...j....C.|
-00000050  cf 07 25 47 c9 15 03 02  00 16 53 91 04 70 ba 03  |..%G......S..p..|
-00000060  53 69 57 86 3b 2f 8b 97  37 7c b8 85 46 b6 72 42  |SiW.;/..7|..F.rB|
+00000000  14 03 02 00 01 01 16 03  02 00 24 8f 06 3e 7b 8c  |..........$..>{.|
+00000010  fb f2 3d 9e 5c a9 46 56  79 2a 3a ba ad 25 30 57  |..=.\.FVy*:..%0W|
+00000020  f9 f1 16 70 51 5d 73 7e  47 74 8d c0 84 b0 31 17  |...pQ]s~Gt....1.|
+00000030  03 02 00 21 76 09 88 df  7e f7 2f c9 3d 86 b9 30  |...!v...~./.=..0|
+00000040  b0 5c ac ea db c6 d0 d5  69 55 91 7b a1 72 0b 4d  |.\......iU.{.r.M|
+00000050  7d ae 6f aa 50 15 03 02  00 16 8c 31 73 86 1a c7  |}.o.P......1s...|
+00000060  ef 08 52 8a 7d 30 b8 00  3b 62 4d 21 7b 81 2c 76  |..R.}0..;bM!{.,v|
diff --git a/src/crypto/tls/testdata/Server-TLSv12-ALPN b/src/crypto/tls/testdata/Server-TLSv12-ALPN
index cbfeb42..df832d7 100644
--- a/src/crypto/tls/testdata/Server-TLSv12-ALPN
+++ b/src/crypto/tls/testdata/Server-TLSv12-ALPN
@@ -1,7 +1,7 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 01 4c 01 00 01  48 03 03 44 3b 24 ee 2f  |....L...H..D;$./|
-00000010  63 3d ca bd 3e c5 bf a2  24 f1 59 c3 54 dc f0 43  |c=..>...$.Y.T..C|
-00000020  15 c4 51 f2 29 ea 1b ce  2c fe af 00 00 b6 c0 30  |..Q.)...,......0|
+00000000  16 03 01 01 4d 01 00 01  49 03 03 ac 76 61 d8 20  |....M...I...va. |
+00000010  b3 c3 1d c2 3d c2 a4 b9  e2 46 a2 a1 0a 5e 08 56  |....=....F...^.V|
+00000020  4a aa 59 43 42 d6 21 9c  46 0c 21 00 00 b6 c0 30  |J.YCB.!.F.!....0|
 00000030  c0 2c c0 28 c0 24 c0 14  c0 0a 00 a5 00 a3 00 a1  |.,.(.$..........|
 00000040  00 9f 00 6b 00 6a 00 69  00 68 00 39 00 38 00 37  |...k.j.i.h.9.8.7|
 00000050  00 36 00 88 00 87 00 86  00 85 c0 32 c0 2e c0 2a  |.6.........2...*|
@@ -13,14 +13,14 @@
 000000b0  00 3c 00 2f 00 96 00 41  00 07 c0 11 c0 07 c0 0c  |.<./...A........|
 000000c0  c0 02 00 05 00 04 c0 12  c0 08 00 16 00 13 00 10  |................|
 000000d0  00 0d c0 0d c0 03 00 0a  00 15 00 12 00 0f 00 0c  |................|
-000000e0  00 09 00 ff 01 00 00 69  00 0b 00 04 03 00 01 02  |.......i........|
-000000f0  00 0a 00 1c 00 1a 00 17  00 19 00 1c 00 1b 00 18  |................|
-00000100  00 1a 00 16 00 0e 00 0d  00 0b 00 0c 00 09 00 0a  |................|
-00000110  00 23 00 00 00 0d 00 20  00 1e 06 01 06 02 06 03  |.#..... ........|
-00000120  05 01 05 02 05 03 04 01  04 02 04 03 03 01 03 02  |................|
-00000130  03 03 02 01 02 02 02 03  00 0f 00 01 01 00 10 00  |................|
-00000140  10 00 0e 06 70 72 6f 74  6f 32 06 70 72 6f 74 6f  |....proto2.proto|
-00000150  31                                                |1|
+000000e0  00 09 00 ff 02 01 00 00  69 00 0b 00 04 03 00 01  |........i.......|
+000000f0  02 00 0a 00 1c 00 1a 00  17 00 19 00 1c 00 1b 00  |................|
+00000100  18 00 1a 00 16 00 0e 00  0d 00 0b 00 0c 00 09 00  |................|
+00000110  0a 00 23 00 00 00 0d 00  20 00 1e 06 01 06 02 06  |..#..... .......|
+00000120  03 05 01 05 02 05 03 04  01 04 02 04 03 03 01 03  |................|
+00000130  02 03 03 02 01 02 02 02  03 00 0f 00 01 01 00 10  |................|
+00000140  00 10 00 0e 06 70 72 6f  74 6f 32 06 70 72 6f 74  |.....proto2.prot|
+00000150  6f 31                                             |o1|
 >>> Flow 2 (server to client)
 00000000  16 03 03 00 42 02 00 00  3e 03 03 00 00 00 00 00  |....B...>.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -70,40 +70,40 @@
 000002d0  19 51 88 35 75 71 b5 e5  54 5b 12 2e 8f 09 67 fd  |.Q.5uq..T[....g.|
 000002e0  a7 24 20 3e b2 56 1c ce  97 28 5e f8 2b 2d 4f 9e  |.$ >.V...(^.+-O.|
 000002f0  f1 07 9f 6c 4b 5b 83 56  e2 32 42 e9 58 b6 d7 49  |...lK[.V.2B.X..I|
-00000300  a6 b5 68 1a 41 03 56 6b  dc 5a 89 05 01 00 80 40  |..h.A.Vk.Z.....@|
-00000310  93 b2 1f 79 3d 56 c0 ae  94 87 c0 a7 28 ef 1d 15  |...y=V......(...|
-00000320  be 4b fb 66 e0 60 2c a3  57 ee 56 7d d6 89 b8 8e  |.K.f.`,.W.V}....|
-00000330  8f 0f 3f 1b c6 9f a4 1d  34 60 b6 9c e9 9b a9 27  |..?.....4`.....'|
-00000340  d0 45 7b 04 71 2d db 9c  67 1b d5 d4 fe 19 69 59  |.E{.q-..g.....iY|
-00000350  71 8a 35 75 33 a8 c9 f2  4d c4 8f 40 17 a7 25 53  |q.5u3...M.. at ..%S|
-00000360  57 c5 cd ee df a9 3b a3  61 ab e2 a2 ca de 5c 08  |W.....;.a.....\.|
-00000370  3d 5b a2 ef cd c8 bc 16  1f 1d 0f 83 9e b7 20 f5  |=[............ .|
-00000380  89 3f 09 ba 2e da 12 34  81 e5 2f 8d 3c 90 89 16  |.?.....4../.<...|
+00000300  a6 b5 68 1a 41 03 56 6b  dc 5a 89 05 01 00 80 aa  |..h.A.Vk.Z......|
+00000310  8c a6 e1 51 65 fc 99 37  cf 63 d8 fd 04 52 d5 50  |...Qe..7.c...R.P|
+00000320  1f 0a f5 90 58 48 19 8d  d8 0b 64 23 e4 24 56 b4  |....XH....d#.$V.|
+00000330  e5 87 0f 88 a1 7a 29 fa  88 79 99 75 6d 53 a9 50  |.....z)..y.umS.P|
+00000340  a4 9c b9 47 c2 51 87 10  b9 a5 e3 6f a9 38 b8 83  |...G.Q.....o.8..|
+00000350  0d 39 b5 28 27 5f ec 9d  a3 2d 1c 53 6b da 93 0d  |.9.('_...-.Sk...|
+00000360  cc cf 0c 27 7e d2 f0 05  d5 c0 04 dc 6d d4 2e 03  |...'~.......m...|
+00000370  a7 16 98 58 e4 8d fd 14  6b bb 0c 09 b0 16 35 9e  |...X....k.....5.|
+00000380  78 3a 29 21 b5 2f 13 37  94 ae f7 fe 54 89 c0 16  |x:)!./.7....T...|
 00000390  03 03 00 04 0e 00 00 00                           |........|
 >>> Flow 3 (client to server)
-00000000  16 03 03 00 46 10 00 00  42 41 04 8b a2 de a6 1e  |....F...BA......|
-00000010  d9 22 3c 03 4a be 49 2f  40 e3 1e e0 b4 76 7f 78  |."<.J.I/@....v.x|
-00000020  96 22 8d 8d c9 45 3b d8  7a ce e3 16 3d 37 ec 80  |."...E;.z...=7..|
-00000030  aa 3f d5 19 de c1 2c 7b  7f eb 3c fc 5d c3 52 3b  |.?....,{..<.].R;|
-00000040  d4 22 25 1c c7 1f 39 c5  23 bd 73 14 03 03 00 01  |."%...9.#.s.....|
-00000050  01 16 03 03 00 28 c8 53  0a ad c2 f6 7e 18 08 a3  |.....(.S....~...|
-00000060  29 27 20 1c 6c 1d 6c d8  8f 05 31 de e6 ab 7f 22  |)' .l.l...1...."|
-00000070  93 6a fb ef b0 f8 43 a9  d3 4f 9d 04 b5 9a        |.j....C..O....|
+00000000  16 03 03 00 46 10 00 00  42 41 04 35 ca 56 91 15  |....F...BA.5.V..|
+00000010  4f dd af 97 f2 2d fb df  54 2b 80 98 18 bb 33 54  |O....-..T+....3T|
+00000020  3f 7e 66 21 d3 81 38 f9  a4 b5 b9 a6 46 9a 52 8b  |?~f!..8.....F.R.|
+00000030  98 f7 81 1f 77 81 78 38  01 c5 3b fb 7a b7 53 e7  |....w.x8..;.z.S.|
+00000040  ae c3 4c 2e 73 f4 8e 3a  36 0d 43 14 03 03 00 01  |..L.s..:6.C.....|
+00000050  01 16 03 03 00 28 38 26  8e 03 ad 81 9b a0 41 d9  |.....(8&......A.|
+00000060  c0 11 3f 36 dc 6b ab 6c  29 dc df 02 a3 fe b0 0f  |..?6.k.l).......|
+00000070  2e b1 c6 44 39 42 d5 ef  29 30 d8 e0 f1 f9        |...D9B..)0....|
 >>> Flow 4 (server to client)
 00000000  16 03 03 00 82 04 00 00  7e 00 00 00 00 00 78 50  |........~.....xP|
 00000010  46 ad c1 db a8 38 86 7b  2b bb fd d0 c3 42 3e 00  |F....8.{+....B>.|
 00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 94  |................|
-00000030  6f ec 80 83 61 8e d9 64  ac a2 ee 3b 69 31 79 e1  |o...a..d...;i1y.|
-00000040  53 0a 92 1d aa 23 09 c2  49 02 2d 0d 1d c1 63 d6  |S....#..I.-...c.|
-00000050  21 56 c7 24 02 28 d5 f1  11 b0 e7 1b 4a 7c 55 af  |!V.$.(......J|U.|
-00000060  1b c8 32 4c 5b 33 94 b0  ed b0 2f 52 c4 52 81 ee  |..2L[3..../R.R..|
-00000070  60 6f 66 fb f5 db dd f9  1e 30 11 d4 ca 75 0e 2b  |`of......0...u.+|
-00000080  ff d0 e5 f2 68 a4 e7 14  03 03 00 01 01 16 03 03  |....h...........|
-00000090  00 28 00 00 00 00 00 00  00 00 67 3b 4a ba f3 27  |.(........g;J..'|
-000000a0  c8 45 94 68 36 5a 40 e1  dc 67 9b d4 45 58 e9 24  |.E.h6Z at ..g..EX.$|
-000000b0  31 85 3a f8 5d cb 84 8e  64 05 17 03 03 00 25 00  |1.:.]...d.....%.|
-000000c0  00 00 00 00 00 00 01 35  d9 ba 0a e2 3e fd a2 80  |.......5....>...|
-000000d0  10 0e 38 7b ad 85 85 48  6a 2a ab 2a 46 c3 59 96  |..8{...Hj*.*F.Y.|
-000000e0  fd 75 11 5d 15 03 03 00  1a 00 00 00 00 00 00 00  |.u.]............|
-000000f0  02 0b 4d a5 89 4d 86 47  14 60 27 f8 09 bc c9 4d  |..M..M.G.`'....M|
-00000100  00 31 cb                                          |.1.|
+00000030  6f ec 80 83 61 fb fb 41  b1 31 e9 71 75 43 c3 74  |o...a..A.1.quC.t|
+00000040  a1 a0 ac fb 97 b7 69 ee  a6 2f e3 a3 dd 9f de e4  |......i../......|
+00000050  80 9d d7 69 1a 2c 0b b4  02 bd ef e2 6a c1 ca 30  |...i.,......j..0|
+00000060  8b 9d 60 f9 fe 33 94 53  3a 14 a3 1a aa 5a ba ff  |..`..3.S:....Z..|
+00000070  1e 94 fd 4f e7 90 0b 09  ee 80 f3 d6 d5 c0 48 83  |...O..........H.|
+00000080  98 20 d7 a4 07 99 e0 14  03 03 00 01 01 16 03 03  |. ..............|
+00000090  00 28 00 00 00 00 00 00  00 00 0d 66 de 91 4a 97  |.(.........f..J.|
+000000a0  21 c6 d2 d7 df 68 9b 7e  f6 43 73 02 66 b3 5a d6  |!....h.~.Cs.f.Z.|
+000000b0  92 48 c2 c1 11 fc cd 1e  2e 4b 17 03 03 00 25 00  |.H.......K....%.|
+000000c0  00 00 00 00 00 00 01 72  0c 48 75 fa b2 8b 23 09  |.......r.Hu...#.|
+000000d0  be 76 36 a4 bc e0 62 ef  bd 79 8e de 6b 39 4b 55  |.v6...b..y..k9KU|
+000000e0  8d 3c ca 14 15 03 03 00  1a 00 00 00 00 00 00 00  |.<..............|
+000000f0  02 74 5f 79 31 41 4f f5  4d 02 96 bc c3 9a 85 92  |.t_y1AO.M.......|
+00000100  44 e1 76                                          |D.v|
diff --git a/src/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch b/src/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch
index af75445..35bfdc1 100644
--- a/src/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch
+++ b/src/crypto/tls/testdata/Server-TLSv12-ALPN-NoMatch
@@ -1,7 +1,7 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 01 4c 01 00 01  48 03 03 1d 1a f7 e5 ad  |....L...H.......|
-00000010  a4 5c fd 61 b4 c2 25 33  c7 b9 fc fb 2b a5 4b fe  |.\.a..%3....+.K.|
-00000020  16 84 55 4b 9f 68 73 61  b8 92 4d 00 00 b6 c0 30  |..UK.hsa..M....0|
+00000000  16 03 01 01 4d 01 00 01  49 03 03 73 f2 f2 44 4f  |....M...I..s..DO|
+00000010  87 05 77 e2 e7 07 ca c7  d4 36 37 4e d9 17 ba ff  |..w......67N....|
+00000020  b0 e1 47 65 f8 7f fd 7a  b4 85 39 00 00 b6 c0 30  |..Ge...z..9....0|
 00000030  c0 2c c0 28 c0 24 c0 14  c0 0a 00 a5 00 a3 00 a1  |.,.(.$..........|
 00000040  00 9f 00 6b 00 6a 00 69  00 68 00 39 00 38 00 37  |...k.j.i.h.9.8.7|
 00000050  00 36 00 88 00 87 00 86  00 85 c0 32 c0 2e c0 2a  |.6.........2...*|
@@ -13,14 +13,14 @@
 000000b0  00 3c 00 2f 00 96 00 41  00 07 c0 11 c0 07 c0 0c  |.<./...A........|
 000000c0  c0 02 00 05 00 04 c0 12  c0 08 00 16 00 13 00 10  |................|
 000000d0  00 0d c0 0d c0 03 00 0a  00 15 00 12 00 0f 00 0c  |................|
-000000e0  00 09 00 ff 01 00 00 69  00 0b 00 04 03 00 01 02  |.......i........|
-000000f0  00 0a 00 1c 00 1a 00 17  00 19 00 1c 00 1b 00 18  |................|
-00000100  00 1a 00 16 00 0e 00 0d  00 0b 00 0c 00 09 00 0a  |................|
-00000110  00 23 00 00 00 0d 00 20  00 1e 06 01 06 02 06 03  |.#..... ........|
-00000120  05 01 05 02 05 03 04 01  04 02 04 03 03 01 03 02  |................|
-00000130  03 03 02 01 02 02 02 03  00 0f 00 01 01 00 10 00  |................|
-00000140  10 00 0e 06 70 72 6f 74  6f 32 06 70 72 6f 74 6f  |....proto2.proto|
-00000150  31                                                |1|
+000000e0  00 09 00 ff 02 01 00 00  69 00 0b 00 04 03 00 01  |........i.......|
+000000f0  02 00 0a 00 1c 00 1a 00  17 00 19 00 1c 00 1b 00  |................|
+00000100  18 00 1a 00 16 00 0e 00  0d 00 0b 00 0c 00 09 00  |................|
+00000110  0a 00 23 00 00 00 0d 00  20 00 1e 06 01 06 02 06  |..#..... .......|
+00000120  03 05 01 05 02 05 03 04  01 04 02 04 03 03 01 03  |................|
+00000130  02 03 03 02 01 02 02 02  03 00 0f 00 01 01 00 10  |................|
+00000140  00 10 00 0e 06 70 72 6f  74 6f 32 06 70 72 6f 74  |.....proto2.prot|
+00000150  6f 31                                             |o1|
 >>> Flow 2 (server to client)
 00000000  16 03 03 00 35 02 00 00  31 03 03 00 00 00 00 00  |....5...1.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -70,39 +70,39 @@
 000002d0  09 67 fd a7 24 20 3e b2  56 1c ce 97 28 5e f8 2b  |.g..$ >.V...(^.+|
 000002e0  2d 4f 9e f1 07 9f 6c 4b  5b 83 56 e2 32 42 e9 58  |-O....lK[.V.2B.X|
 000002f0  b6 d7 49 a6 b5 68 1a 41  03 56 6b dc 5a 89 05 01  |..I..h.A.Vk.Z...|
-00000300  00 80 36 d2 96 c8 27 66  d8 bd 6c 28 29 30 b3 be  |..6...'f..l()0..|
-00000310  0a bb b2 fe 9d c3 59 47  34 cf de fe f4 ab 5d 79  |......YG4.....]y|
-00000320  24 a9 9d c9 b5 e9 50 6a  3b 96 e3 29 cb d7 37 06  |$.....Pj;..)..7.|
-00000330  19 08 88 15 29 c2 55 03  62 75 1d 35 c2 8e 25 a2  |....).U.bu.5..%.|
-00000340  86 20 bf 18 46 15 81 f2  74 4b bb dd 3d e3 a5 f6  |. ..F...tK..=...|
-00000350  28 18 41 89 c8 39 13 f9  c0 88 fd cc f0 6e 9e 3d  |(.A..9.......n.=|
-00000360  cb 29 ad 26 5b d1 e6 11  5c 64 7d b6 df d7 39 87  |.).&[...\d}...9.|
-00000370  24 df 9f 62 17 ef f2 b3  3a b3 88 a4 f0 91 ea f2  |$..b....:.......|
-00000380  5d c9 16 03 03 00 04 0e  00 00 00                 |]..........|
+00000300  00 80 97 89 a3 7f 30 d1  7b 70 26 3d a4 d5 66 2e  |......0.{p&=..f.|
+00000310  cd fc 02 f5 37 a5 cd 09  69 7a c6 2f b2 62 e8 a6  |....7...iz./.b..|
+00000320  88 e2 3a c4 0a 8c 77 ad  d3 c9 29 49 84 81 9c cd  |..:...w...)I....|
+00000330  33 44 59 2d b5 2e e7 ce  12 c5 3b 46 13 6d 4a c8  |3DY-......;F.mJ.|
+00000340  6d f6 1f e7 f1 99 13 01  ca 43 79 fa b5 78 c7 1a  |m........Cy..x..|
+00000350  7d 8f 85 dd 3b ca 56 22  c3 d0 41 11 1b 13 8c 07  |}...;.V"..A.....|
+00000360  02 75 87 7a ea 68 43 30  0b 2a 38 52 b2 8f cc ea  |.u.z.hC0.*8R....|
+00000370  a3 a3 cb 71 fb 97 cd 3e  74 d0 5b 9b bd 17 13 f0  |...q...>t.[.....|
+00000380  d9 fe 16 03 03 00 04 0e  00 00 00                 |...........|
 >>> Flow 3 (client to server)
-00000000  16 03 03 00 46 10 00 00  42 41 04 b0 22 15 73 fc  |....F...BA..".s.|
-00000010  1c fd 24 4a 36 69 8a be  ac bd 72 30 bb 6b e1 9b  |..$J6i....r0.k..|
-00000020  42 e8 56 7a 86 b1 8d cb  9c 3e 2d 63 13 57 a8 13  |B.Vz.....>-c.W..|
-00000030  71 3b a2 01 86 af f8 76  40 0b 44 4f 0a 0f 5a da  |q;.....v at .DO..Z.|
-00000040  31 36 3b 13 c0 10 6c 96  64 a7 24 14 03 03 00 01  |16;...l.d.$.....|
-00000050  01 16 03 03 00 28 10 2d  45 93 5c 37 34 d9 2a a0  |.....(.-E.\74.*.|
-00000060  b6 37 13 bc a6 1f 0c ce  2e 55 c1 ad 36 b8 60 72  |.7.......U..6.`r|
-00000070  81 cb 1a 7a 5b 26 49 ad  77 ef 62 e8 fc 00        |...z[&I.w.b...|
+00000000  16 03 03 00 46 10 00 00  42 41 04 ba 5b 0f e7 ec  |....F...BA..[...|
+00000010  8e c8 ad 51 8c c0 50 f1  8a 2a 68 32 74 d0 95 03  |...Q..P..*h2t...|
+00000020  0c 61 f1 1c 89 ed 95 5d  9a 4a 14 ee cc 14 9a 73  |.a.....].J.....s|
+00000030  f6 db 46 dd b7 47 8a 82  3d 7a b8 9f 45 d1 a2 3f  |..F..G..=z..E..?|
+00000040  f4 34 9b b6 6d 7d 41 87  c9 d5 cd 14 03 03 00 01  |.4..m}A.........|
+00000050  01 16 03 03 00 28 1e ae  f6 90 a9 91 eb 4b ca 23  |.....(.......K.#|
+00000060  6e bf 9e 67 5b 38 ab f6  d6 ee 12 aa b9 b6 d0 6e  |n..g[8.........n|
+00000070  a7 dd 45 91 34 45 78 a0  04 9e d8 85 48 48        |..E.4Ex.....HH|
 >>> Flow 4 (server to client)
 00000000  16 03 03 00 82 04 00 00  7e 00 00 00 00 00 78 50  |........~.....xP|
 00000010  46 ad c1 db a8 38 86 7b  2b bb fd d0 c3 42 3e 00  |F....8.{+....B>.|
 00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 94  |................|
-00000030  6f ec 80 83 61 05 33 d2  9d 95 89 7b 28 54 50 50  |o...a.3....{(TPP|
-00000040  b3 3c 99 5c 82 ab cf 88  24 e8 48 81 db 4a 22 79  |.<.\....$.H..J"y|
-00000050  0b fa 33 50 ed 82 a1 7c  33 0e f2 ff 6d a7 d6 88  |..3P...|3...m...|
-00000060  29 65 74 e3 27 33 94 97  66 0c 86 ce fc ca 0e 2a  |)et.'3..f......*|
-00000070  96 fa fe 19 a3 01 64 d9  4d 8e 58 95 5b 74 a6 aa  |......d.M.X.[t..|
-00000080  f4 9f c1 34 97 2d e5 14  03 03 00 01 01 16 03 03  |...4.-..........|
-00000090  00 28 00 00 00 00 00 00  00 00 4d 56 6d d5 6f cc  |.(........MVm.o.|
-000000a0  3d d4 85 32 3c 07 ea 3c  52 61 88 8e dd d5 d3 d0  |=..2<..<Ra......|
-000000b0  f9 4e 1b b1 c1 d1 67 cb  1a e8 17 03 03 00 25 00  |.N....g.......%.|
-000000c0  00 00 00 00 00 00 01 c3  43 ab 0c ab 59 30 e9 d4  |........C...Y0..|
-000000d0  eb 65 c2 7f 9a 5a 1e 09  06 a4 9d 69 bb 3f 0b 06  |.e...Z.....i.?..|
-000000e0  87 b8 09 39 15 03 03 00  1a 00 00 00 00 00 00 00  |...9............|
-000000f0  02 c2 6f f4 88 f0 7a 59  a6 49 3e 44 a3 7b 6e 36  |..o...zY.I>D.{n6|
-00000100  ae 66 87                                          |.f.|
+00000030  6f ec 80 83 61 4f 7f 09  64 32 96 26 b5 71 46 6a  |o...aO..d2.&.qFj|
+00000040  29 7d fd 0b bb 49 13 0e  c8 c5 de 06 ed 47 e8 cb  |)}...I.......G..|
+00000050  d8 9f 18 82 69 af ab 24  d2 78 90 ba 9a c8 24 95  |....i..$.x....$.|
+00000060  46 53 19 2e e8 33 94 3c  22 73 26 d6 86 4e 01 a4  |FS...3.<"s&..N..|
+00000070  34 ea a8 bf f2 ca b5 0d  fc f6 08 b9 31 b3 42 e7  |4...........1.B.|
+00000080  c1 92 96 f9 bf 9a 00 14  03 03 00 01 01 16 03 03  |................|
+00000090  00 28 00 00 00 00 00 00  00 00 bd 51 1d 0e bd 51  |.(.........Q...Q|
+000000a0  a3 b1 03 f2 df f4 ba 9b  1e a5 a8 22 e7 ce 7c 19  |..........."..|.|
+000000b0  1a bf 37 3d 42 f4 4d 6f  63 75 17 03 03 00 25 00  |..7=B.Mocu....%.|
+000000c0  00 00 00 00 00 00 01 52  8a d2 34 52 70 f1 cf 87  |.......R..4Rp...|
+000000d0  54 4e fd e6 11 a7 76 1a  f4 7b 70 e8 34 ef 01 c8  |TN....v..{p.4...|
+000000e0  6c 4a f8 6d 15 03 03 00  1a 00 00 00 00 00 00 00  |lJ.m............|
+000000f0  02 8a 4c f9 7c d1 61 a6  cd 2a e6 3a 5b b0 cb aa  |..L.|.a..*.:[...|
+00000100  91 2e 8b                                          |...|
diff --git a/src/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA b/src/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA
index 344d973..ae3748f 100644
--- a/src/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA
+++ b/src/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceECDSA
@@ -1,7 +1,7 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 01 34 01 00 01  30 03 03 78 08 b2 d4 18  |....4...0..x....|
-00000010  8e b1 6b a2 d2 e0 c6 41  02 c5 93 f1 b9 60 94 e8  |..k....A.....`..|
-00000020  f2 64 6c 97 50 2d 24 a3  cd c0 36 00 00 b6 c0 30  |.dl.P-$...6....0|
+00000000  16 03 01 01 35 01 00 01  31 03 03 00 02 67 8e 1d  |....5...1....g..|
+00000010  3b d2 26 20 63 c5 6a b6  68 25 02 72 ce 86 6b c7  |;.& c.j.h%.r..k.|
+00000020  97 1a 9f 4d be 02 98 ac  24 5e 82 00 00 b6 c0 30  |...M....$^.....0|
 00000030  c0 2c c0 28 c0 24 c0 14  c0 0a 00 a5 00 a3 00 a1  |.,.(.$..........|
 00000040  00 9f 00 6b 00 6a 00 69  00 68 00 39 00 38 00 37  |...k.j.i.h.9.8.7|
 00000050  00 36 00 88 00 87 00 86  00 85 c0 32 c0 2e c0 2a  |.6.........2...*|
@@ -13,12 +13,12 @@
 000000b0  00 3c 00 2f 00 96 00 41  00 07 c0 11 c0 07 c0 0c  |.<./...A........|
 000000c0  c0 02 00 05 00 04 c0 12  c0 08 00 16 00 13 00 10  |................|
 000000d0  00 0d c0 0d c0 03 00 0a  00 15 00 12 00 0f 00 0c  |................|
-000000e0  00 09 00 ff 01 00 00 51  00 0b 00 04 03 00 01 02  |.......Q........|
-000000f0  00 0a 00 1c 00 1a 00 17  00 19 00 1c 00 1b 00 18  |................|
-00000100  00 1a 00 16 00 0e 00 0d  00 0b 00 0c 00 09 00 0a  |................|
-00000110  00 0d 00 20 00 1e 06 01  06 02 06 03 05 01 05 02  |... ............|
-00000120  05 03 04 01 04 02 04 03  03 01 03 02 03 03 02 01  |................|
-00000130  02 02 02 03 00 0f 00 01  01                       |.........|
+000000e0  00 09 00 ff 02 01 00 00  51 00 0b 00 04 03 00 01  |........Q.......|
+000000f0  02 00 0a 00 1c 00 1a 00  17 00 19 00 1c 00 1b 00  |................|
+00000100  18 00 1a 00 16 00 0e 00  0d 00 0b 00 0c 00 09 00  |................|
+00000110  0a 00 0d 00 20 00 1e 06  01 06 02 06 03 05 01 05  |.... ...........|
+00000120  02 05 03 04 01 04 02 04  03 03 01 03 02 03 03 02  |................|
+00000130  01 02 02 02 03 00 0f 00  01 01                    |..........|
 >>> Flow 2 (server to client)
 00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -62,37 +62,37 @@
 00000270  b2 56 1c ce 97 28 5e f8  2b 2d 4f 9e f1 07 9f 6c  |.V...(^.+-O....l|
 00000280  4b 5b 83 56 e2 32 42 e9  58 b6 d7 49 a6 b5 68 1a  |K[.V.2B.X..I..h.|
 00000290  41 03 56 6b dc 5a 89 05  03 00 8b 30 81 88 02 42  |A.Vk.Z.....0...B|
-000002a0  00 91 b4 4a f2 9d 13 a1  6d 3b ee 46 2f 3b 97 50  |...J....m;.F/;.P|
-000002b0  b9 3e 28 7a 51 7a 8b 3b  a6 16 03 d6 1f 92 0a ec  |.>(zQz.;........|
-000002c0  5b 9b b5 48 98 ce d8 22  bd 7d eb cb 14 7b 14 73  |[..H...".}...{.s|
-000002d0  2d 5f 01 8c dc 5a 63 34  92 4e 59 4a 90 f9 b1 c9  |-_...Zc4.NYJ....|
-000002e0  d8 18 02 42 01 89 e4 e4  39 d0 52 d1 70 19 fe d7  |...B....9.R.p...|
-000002f0  c6 70 10 36 94 1e 45 fd  b4 03 37 79 c7 db cf 6d  |.p.6..E...7y...m|
-00000300  33 5d 80 fe 04 de d1 78  bf c4 dd cf 91 82 57 14  |3].....x......W.|
-00000310  14 09 e3 2d dd d2 78 9c  53 cc 1f f7 40 6c 4a 59  |...-..x.S... at lJY|
-00000320  49 a8 a1 06 24 18 16 03  03 00 04 0e 00 00 00     |I...$..........|
+000002a0  01 bc 56 16 22 ad fd e7  ac ba c8 f5 3f c0 d7 f8  |..V.".......?...|
+000002b0  8c 64 e0 ba 09 30 c3 66  49 90 7e d2 68 86 07 72  |.d...0.fI.~.h..r|
+000002c0  20 87 a1 e1 36 92 a7 68  e2 c3 6e 34 93 a9 ca e8  | ...6..h..n4....|
+000002d0  68 3d 9e 42 c4 1e 8e 2d  95 05 ee a6 a4 2c 8d be  |h=.B...-.....,..|
+000002e0  e3 88 02 42 01 16 18 77  b9 99 0e f8 46 90 46 07  |...B...w....F.F.|
+000002f0  f9 67 a9 26 68 d7 da c8  a1 d9 67 55 ec 37 11 2d  |.g.&h.....gU.7.-|
+00000300  4b f3 52 f4 96 6a 0e 8a  6a 14 21 94 63 ea f9 70  |K.R..j..j.!.c..p|
+00000310  2d 57 05 8a 72 29 6e d2  60 a1 97 af 08 5b c3 cf  |-W..r)n.`....[..|
+00000320  3a 82 a3 81 11 cf 16 03  03 00 04 0e 00 00 00     |:..............|
 >>> Flow 3 (client to server)
-00000000  16 03 03 00 46 10 00 00  42 41 04 66 37 3a ce 68  |....F...BA.f7:.h|
-00000010  23 0f b2 d0 cb 20 24 26  37 d5 84 46 4a 2e 59 80  |#.... $&7..FJ.Y.|
-00000020  87 b3 10 7e 36 fd af 7c  99 07 99 dd 18 af 6d 7c  |...~6..|......m||
-00000030  b5 b2 b7 93 45 95 d9 98  1a 13 5b a2 12 e8 b7 95  |....E.....[.....|
-00000040  ed a1 3a 6d aa 8f fc b6  b5 b4 41 14 03 03 00 01  |..:m......A.....|
-00000050  01 16 03 03 00 40 b0 12  69 00 a4 3a 6d bd 56 40  |..... at ..i..:m.V@|
-00000060  6e 9d 5e a8 1b 0f 59 c5  09 48 b2 07 d8 bc 7b 02  |n.^...Y..H....{.|
-00000070  70 61 f6 1b a9 27 55 8c  16 4d 69 4c ca 31 30 9f  |pa...'U..MiL.10.|
-00000080  d3 62 ba d4 1b 11 ee 0a  a0 f3 61 be c6 64 c3 dc  |.b........a..d..|
-00000090  97 50 47 27 ed 09                                 |.PG'..|
+00000000  16 03 03 00 46 10 00 00  42 41 04 8c 80 0c da 24  |....F...BA.....$|
+00000010  d6 66 ff cc 1b 26 d5 3f  37 37 16 8f 16 ee 0d 5f  |.f...&.?77....._|
+00000020  c3 0e 62 7c e4 52 2d 43  29 e9 6b da 49 bc 99 16  |..b|.R-C).k.I...|
+00000030  28 46 8e 43 20 7f 12 66  1c 94 1c 03 55 6f 05 53  |(F.C ..f....Uo.S|
+00000040  6f b7 dc 8b 70 9d 9d c5  1f da 5b 14 03 03 00 01  |o...p.....[.....|
+00000050  01 16 03 03 00 40 17 60  dd e5 b2 58 fd 74 10 38  |..... at .`...X.t.8|
+00000060  95 b1 73 7e 8f 7a 2b d0  f5 65 80 0c dc b1 ca 29  |..s~.z+..e.....)|
+00000070  06 25 e1 f9 c3 c0 7c 88  e4 ad d3 16 0a 8a dd 1f  |.%....|.........|
+00000080  a7 86 86 0f ac c7 ea f5  0f 1f 2b 97 85 b3 81 f7  |..........+.....|
+00000090  5d 42 2f 3b 72 80                                 |]B/;r.|
 >>> Flow 4 (server to client)
 00000000  14 03 03 00 01 01 16 03  03 00 40 00 00 00 00 00  |.......... at .....|
-00000010  00 00 00 00 00 00 00 00  00 00 00 09 34 9a eb 7c  |............4..||
-00000020  6a 6d 6a 02 7b 50 14 b8  f7 b0 93 30 ea 0b 61 4a  |jmj.{P.....0..aJ|
-00000030  0b 75 10 39 41 78 46 9d  ba 8e d3 e9 e4 ab dc 1f  |.u.9AxF.........|
-00000040  c9 43 95 e8 f9 d6 3a d3  5d 7d 09 17 03 03 00 40  |.C....:.]}.....@|
+00000010  00 00 00 00 00 00 00 00  00 00 00 82 01 fd 38 ae  |..............8.|
+00000020  a4 07 8f bd 72 0a a2 b5  c5 78 09 89 65 1b 6d 1e  |....r....x..e.m.|
+00000030  56 52 9d 4f de 02 15 2d  93 d8 8f d7 1f bb 07 3b  |VR.O...-.......;|
+00000040  e9 62 3c 19 3e 19 65 ac  10 aa e5 17 03 03 00 40  |.b<.>.e........@|
 00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000060  b4 64 88 d5 53 f9 1e 47  d4 d8 c4 fa 0e c2 76 a6  |.d..S..G......v.|
-00000070  ed 5c 17 ba ea 76 72 cb  c5 73 a3 c5 44 21 3c 40  |.\...vr..s..D!<@|
-00000080  33 27 09 37 73 3b 0e a3  7b 95 72 10 8d 74 85 19  |3'.7s;..{.r..t..|
+00000060  18 61 1d 26 f3 b9 34 20  00 6c 27 75 fc 35 f5 c2  |.a.&..4 .l'u.5..|
+00000070  6f 71 ca 9b 0d 70 30 46  57 7c 07 86 7d 52 a9 d6  |oq...p0FW|..}R..|
+00000080  ab fc 89 a5 48 79 ae 60  03 05 4b 17 b2 d9 6b 39  |....Hy.`..K...k9|
 00000090  15 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
-000000a0  00 00 00 00 00 b3 c0 05  e9 ec 05 06 52 ef 09 b7  |............R...|
-000000b0  52 29 04 88 ed 11 bb bd  36 a3 0f ce 2c 55 a2 87  |R)......6...,U..|
-000000c0  7e 2b 0c aa 83                                    |~+...|
+000000a0  00 00 00 00 00 8f 8d 88  88 c5 1e f5 bf 06 f2 45  |...............E|
+000000b0  e7 fe f0 24 c7 4c 92 5a  80 a7 89 c8 2b ac 49 d9  |...$.L.Z....+.I.|
+000000c0  39 00 ca 57 ec                                    |9..W.|
diff --git a/src/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA b/src/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA
index 10624c0..144ef42 100644
--- a/src/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA
+++ b/src/crypto/tls/testdata/Server-TLSv12-CipherSuiteCertPreferenceRSA
@@ -1,7 +1,7 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 01 34 01 00 01  30 03 03 10 5e c8 3f c6  |....4...0...^.?.|
-00000010  fe 44 c4 f0 13 c5 bd ad  06 21 65 e5 a8 40 b5 1d  |.D.......!e.. at ..|
-00000020  21 07 99 34 5b ef 70 85  29 92 7d 00 00 b6 c0 30  |!..4[.p.).}....0|
+00000000  16 03 01 01 35 01 00 01  31 03 03 ed 84 e2 1a c1  |....5...1.......|
+00000010  d9 3f a5 ba 70 0b 5f 3f  3b 87 79 18 27 03 92 ee  |.?..p._?;.y.'...|
+00000020  b1 9f c7 36 26 e3 0b 6d  fc d5 ed 00 00 b6 c0 30  |...6&..m.......0|
 00000030  c0 2c c0 28 c0 24 c0 14  c0 0a 00 a5 00 a3 00 a1  |.,.(.$..........|
 00000040  00 9f 00 6b 00 6a 00 69  00 68 00 39 00 38 00 37  |...k.j.i.h.9.8.7|
 00000050  00 36 00 88 00 87 00 86  00 85 c0 32 c0 2e c0 2a  |.6.........2...*|
@@ -13,12 +13,12 @@
 000000b0  00 3c 00 2f 00 96 00 41  00 07 c0 11 c0 07 c0 0c  |.<./...A........|
 000000c0  c0 02 00 05 00 04 c0 12  c0 08 00 16 00 13 00 10  |................|
 000000d0  00 0d c0 0d c0 03 00 0a  00 15 00 12 00 0f 00 0c  |................|
-000000e0  00 09 00 ff 01 00 00 51  00 0b 00 04 03 00 01 02  |.......Q........|
-000000f0  00 0a 00 1c 00 1a 00 17  00 19 00 1c 00 1b 00 18  |................|
-00000100  00 1a 00 16 00 0e 00 0d  00 0b 00 0c 00 09 00 0a  |................|
-00000110  00 0d 00 20 00 1e 06 01  06 02 06 03 05 01 05 02  |... ............|
-00000120  05 03 04 01 04 02 04 03  03 01 03 02 03 03 02 01  |................|
-00000130  02 02 02 03 00 0f 00 01  01                       |.........|
+000000e0  00 09 00 ff 02 01 00 00  51 00 0b 00 04 03 00 01  |........Q.......|
+000000f0  02 00 0a 00 1c 00 1a 00  17 00 19 00 1c 00 1b 00  |................|
+00000100  18 00 1a 00 16 00 0e 00  0d 00 0b 00 0c 00 09 00  |................|
+00000110  0a 00 0d 00 20 00 1e 06  01 06 02 06 03 05 01 05  |.... ...........|
+00000120  02 05 03 04 01 04 02 04  03 03 01 03 02 03 03 02  |................|
+00000130  01 02 02 02 03 00 0f 00  01 01                    |..........|
 >>> Flow 2 (server to client)
 00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -67,38 +67,38 @@
 000002c0  51 88 35 75 71 b5 e5 54  5b 12 2e 8f 09 67 fd a7  |Q.5uq..T[....g..|
 000002d0  24 20 3e b2 56 1c ce 97  28 5e f8 2b 2d 4f 9e f1  |$ >.V...(^.+-O..|
 000002e0  07 9f 6c 4b 5b 83 56 e2  32 42 e9 58 b6 d7 49 a6  |..lK[.V.2B.X..I.|
-000002f0  b5 68 1a 41 03 56 6b dc  5a 89 05 01 00 80 6a 4b  |.h.A.Vk.Z.....jK|
-00000300  b1 7d 23 cd 0e cb 26 02  d4 ee 90 f2 e0 4a 47 3d  |.}#...&......JG=|
-00000310  b3 36 90 8d 01 42 98 92  ad 75 87 71 02 70 02 a8  |.6...B...u.q.p..|
-00000320  0c b0 06 ee bd 6a 1f 3f  6c 4b 4b 6b 75 41 23 b4  |.....j.?lKKkuA#.|
-00000330  f9 c2 a6 60 e2 de 55 b6  d4 85 62 e9 8f 20 70 ed  |...`..U...b.. p.|
-00000340  9a b8 bb dd 1f 19 87 e9  ad b3 30 3f 7c 63 51 f1  |..........0?|cQ.|
-00000350  59 ab d1 a0 a1 80 22 56  ca 68 52 f8 0f 80 c6 a6  |Y....."V.hR.....|
-00000360  9e 12 51 ed 29 d0 6d c2  1a e5 37 dc 76 e3 f3 53  |..Q.).m...7.v..S|
-00000370  1b 07 0b ea a6 11 af dc  54 d3 ee 25 cc 27 16 03  |........T..%.'..|
+000002f0  b5 68 1a 41 03 56 6b dc  5a 89 05 01 00 80 7c 5c  |.h.A.Vk.Z.....|\|
+00000300  f6 68 cc 07 f0 bd ec 30  07 d0 70 1b c6 95 a4 14  |.h.....0..p.....|
+00000310  67 3a 83 a1 43 ff 0a c3  f0 b7 ee 59 f8 c7 09 65  |g:..C......Y...e|
+00000320  08 ac 18 34 d4 8f 46 c4  2c 91 7b 57 95 e0 54 03  |...4..F.,.{W..T.|
+00000330  d8 8e b6 53 61 74 77 8b  a3 5f 23 f0 06 dc 3a 56  |...Satw.._#...:V|
+00000340  61 80 5e 31 d5 75 c3 05  9f d0 06 1f c5 32 ba 79  |a.^1.u.......2.y|
+00000350  fd 14 a9 54 5a 18 b4 2b  09 0e 19 ab 76 0b 12 5d  |...TZ..+....v..]|
+00000360  52 27 ce b8 dd 4c f8 f2  d2 70 56 43 19 53 b3 13  |R'...L...pVC.S..|
+00000370  b9 b7 65 ce cd 50 ed 4a  9f 42 96 c7 3c b9 16 03  |..e..P.J.B..<...|
 00000380  03 00 04 0e 00 00 00                              |.......|
 >>> Flow 3 (client to server)
-00000000  16 03 03 00 46 10 00 00  42 41 04 2d 4b 0c 6b 65  |....F...BA.-K.ke|
-00000010  82 32 95 8b 77 ec f0 f2  b2 ba d1 38 74 ed 82 49  |.2..w......8t..I|
-00000020  fb ce 8f 66 97 9d b6 97  d8 ae f5 19 af ad 47 b9  |...f..........G.|
-00000030  db 7b d2 c9 4e 10 68 14  ed 23 a5 98 94 f9 2a 00  |.{..N.h..#....*.|
-00000040  b6 44 b3 44 01 29 6c 56  da bb a8 14 03 03 00 01  |.D.D.)lV........|
-00000050  01 16 03 03 00 40 f4 fd  de d6 20 2e 18 80 4e 73  |..... at .... ...Ns|
-00000060  af dd 97 42 08 3b 51 80  e9 26 00 48 6b 8b 21 99  |...B.;Q..&.Hk.!.|
-00000070  a8 60 1f 64 51 d0 5a 90  8b b0 69 b8 6b 29 59 21  |.`.dQ.Z...i.k)Y!|
-00000080  b1 13 19 13 07 01 e1 2c  c3 6b 17 2d 01 a5 be d6  |.......,.k.-....|
-00000090  b0 0d 3d 6a 8c fe                                 |..=j..|
+00000000  16 03 03 00 46 10 00 00  42 41 04 36 1c 6c f5 0a  |....F...BA.6.l..|
+00000010  7f 52 84 ac 5a 27 45 76  79 a6 89 f1 1d d9 30 30  |.R..Z'Evy.....00|
+00000020  b6 64 af c7 34 11 12 b3  b9 72 83 e6 78 bc 06 74  |.d..4....r..x..t|
+00000030  a7 a4 10 01 34 77 5c 05  88 82 0f a9 cf 8d e8 68  |....4w\........h|
+00000040  09 80 c7 79 b6 e9 5a 2a  5f 80 5e 14 03 03 00 01  |...y..Z*_.^.....|
+00000050  01 16 03 03 00 40 ef f9  3c 34 cd 26 70 c9 7b 60  |..... at ..<4.&p.{`|
+00000060  a7 27 0a 2b 86 18 2f 10  ad 48 3f 2e 9e 88 13 d6  |.'.+../..H?.....|
+00000070  d8 c6 fd 35 99 be 09 e6  dd ae 02 06 ea df 60 62  |...5..........`b|
+00000080  e0 f8 67 ea 9d c8 8c 11  d8 5a e7 6a a6 b2 eb 62  |..g......Z.j...b|
+00000090  23 b2 d2 be 75 58                                 |#...uX|
 >>> Flow 4 (server to client)
 00000000  14 03 03 00 01 01 16 03  03 00 40 00 00 00 00 00  |.......... at .....|
-00000010  00 00 00 00 00 00 00 00  00 00 00 84 e2 7f e3 b4  |................|
-00000020  53 d7 d0 30 c4 e5 ea 09  df ba 33 b0 02 34 eb 2e  |S..0......3..4..|
-00000030  b2 ec 47 0d e7 20 76 12  fa 53 3b 44 86 e1 e1 63  |..G.. v..S;D...c|
-00000040  06 29 57 98 ce 87 18 ad  02 17 01 17 03 03 00 40  |.)W............@|
+00000010  00 00 00 00 00 00 00 00  00 00 00 a6 52 02 4f 20  |............R.O |
+00000020  f6 d7 2d 2d 7c 65 4e 7b  43 33 32 50 9b c6 68 2c  |..--|eN{C32P..h,|
+00000030  c0 6a 02 6f c6 bc 38 d8  06 c0 42 ba c1 41 ce 5c  |.j.o..8...B..A.\|
+00000040  d0 a0 5f fc 8a 31 33 26  a2 79 9a 17 03 03 00 40  |.._..13&.y.....@|
 00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000060  b0 3a f5 90 90 30 9c b3  39 5b b4 56 f6 b9 30 7e  |.:...0..9[.V..0~|
-00000070  8e a8 2d 60 47 b6 57 8a  20 61 02 f2 8e 43 c2 01  |..-`G.W. a...C..|
-00000080  ee f0 be 5a 93 52 2f ea  03 2a 4f 01 ea 9e 1c a2  |...Z.R/..*O.....|
+00000060  f2 42 8f e8 79 0d f3 c0  a0 b7 8a 5e de b8 52 c4  |.B..y......^..R.|
+00000070  b6 9d b2 10 00 e8 a3 19  27 12 ac 38 e7 d8 ec 89  |........'..8....|
+00000080  af 7d 68 15 03 e8 c4 c8  08 34 ad ad 15 7b 69 bb  |.}h......4...{i.|
 00000090  15 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
-000000a0  00 00 00 00 00 c0 7e 61  51 a1 76 15 8a 7e 20 5f  |......~aQ.v..~ _|
-000000b0  d4 a4 c6 3e 6c 50 18 c6  63 88 d0 ac 4c fa 31 b3  |...>lP..c...L.1.|
-000000c0  e7 c9 77 11 7a                                    |..w.z|
+000000a0  00 00 00 00 00 a0 a5 02  ff b1 77 9a 8f e0 fc ca  |..........w.....|
+000000b0  86 ee ca 9c 7c 3b ca 61  33 7f f9 12 54 79 41 97  |....|;.a3...TyA.|
+000000c0  b0 7d bd 9b 93                                    |.}...|
diff --git a/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven
index 56c3c82..626024c 100644
--- a/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven
+++ b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndECDSAGiven
@@ -1,10 +1,10 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 5a 01 00 00  56 03 03 80 13 c8 83 43  |....Z...V......C|
-00000010  94 79 15 01 6e 0a 9f c5  0f e7 f6 d8 b1 94 de b4  |.y..n...........|
-00000020  57 8c 4f a8 08 48 ee 9b  b4 d2 43 00 00 04 00 05  |W.O..H....C.....|
-00000030  00 ff 01 00 00 29 00 0d  00 20 00 1e 06 01 06 02  |.....)... ......|
-00000040  06 03 05 01 05 02 05 03  04 01 04 02 04 03 03 01  |................|
-00000050  03 02 03 03 02 01 02 02  02 03 00 0f 00 01 01     |...............|
+00000000  16 03 01 00 5b 01 00 00  57 03 03 55 46 9e 3b 51  |....[...W..UF.;Q|
+00000010  e7 cd bf df bc fe 0d 5a  5a de a6 09 6c 72 cb ea  |.......ZZ...lr..|
+00000020  ab f8 a6 fd 9a 5b be 77  7d 25 20 00 00 04 00 05  |.....[.w}% .....|
+00000030  00 ff 02 01 00 00 29 00  0d 00 20 00 1e 06 01 06  |......)... .....|
+00000040  02 06 03 05 01 05 02 05  03 04 01 04 02 04 03 03  |................|
+00000050  01 03 02 03 03 02 01 02  02 02 03 00 0f 00 01 01  |................|
 >>> Flow 2 (server to client)
 00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -86,32 +86,32 @@
 000001e0  be e8 91 b3 da 1a f5 5d  a3 23 f5 26 8b 45 70 8d  |.......].#.&.Ep.|
 000001f0  65 62 9b 7e 01 99 3d 18  f6 10 9a 38 61 9b 2e 57  |eb.~..=....8a..W|
 00000200  e4 fa cc b1 8a ce e2 23  a0 87 f0 e1 67 51 eb 16  |.......#....gQ..|
-00000210  03 03 00 86 10 00 00 82  00 80 88 00 24 23 a5 c7  |............$#..|
-00000220  03 2d 86 37 91 f1 71 a9  5f fb 97 49 88 04 9b 0e  |.-.7..q._..I....|
-00000230  89 da 65 d0 56 71 e7 76  22 ef 8e 11 0e 6b 50 3d  |..e.Vq.v"....kP=|
-00000240  64 3f f7 9b e4 45 01 d9  12 cb da fe 10 da 4e b5  |d?...E........N.|
-00000250  b8 6a b5 bc 74 19 d3 4f  a9 bb ee 54 37 e4 70 d0  |.j..t..O...T7.p.|
-00000260  b6 e7 35 96 70 fe a5 2b  14 ac fb c6 1a fa 7d 12  |..5.p..+......}.|
-00000270  87 1b 63 9d 72 30 4d 2c  1a c9 29 32 72 b6 13 53  |..c.r0M,..)2r..S|
-00000280  96 05 de 78 bc f0 1a 74  e2 31 b9 ea db 62 62 6e  |...x...t.1...bbn|
-00000290  a0 a6 b2 c0 3e 2a 94 0d  6a f7 16 03 03 00 92 0f  |....>*..j.......|
-000002a0  00 00 8e 04 03 00 8a 30  81 87 02 42 01 71 5b 3b  |.......0...B.q[;|
-000002b0  a3 35 58 c0 b6 08 09 4f  ac af 89 e0 b3 d5 3d 45  |.5X....O......=E|
-000002c0  1f 49 7f 4a c9 bc 9d 0e  50 3a f5 79 bc 54 5d a9  |.I.J....P:.y.T].|
-000002d0  62 ed 85 c5 f3 47 36 03  cc f1 cd 33 c3 70 2a a6  |b....G6....3.p*.|
-000002e0  7c d9 6e 0c db 0d 1b 4f  6a 39 ba 77 bd ea 02 41  ||.n....Oj9.w...A|
-000002f0  00 f2 b7 06 df 2f 81 7e  98 24 46 06 59 4e 86 6a  |...../.~.$F.YN.j|
-00000300  b7 4f b6 4b 95 40 88 f0  8f f8 bd 16 f5 d5 82 7e  |.O.K. at .........~|
-00000310  82 51 6f 05 49 43 59 cd  1d 40 69 67 ff 65 a8 68  |.Qo.ICY.. at ig.e.h|
-00000320  39 2f a1 ad a7 6a ef 5c  d5 69 5e 16 50 bb 2a b2  |9/...j.\.i^.P.*.|
-00000330  2f 14 03 03 00 01 01 16  03 03 00 24 55 f6 74 21  |/..........$U.t!|
-00000340  b4 08 a0 7f a2 dc 86 44  e3 f8 e3 0d e1 d6 5c 1c  |.......D......\.|
-00000350  22 1e 41 2b 30 cc 34 0f  a4 a1 7c a0 27 21 01 e0  |".A+0.4...|.'!..|
+00000210  03 03 00 86 10 00 00 82  00 80 03 64 6f 74 1b 0e  |...........dot..|
+00000220  df 6b a4 8e f8 ec b5 02  c2 d6 7a 9a f3 bf 3e 32  |.k........z...>2|
+00000230  ba 41 dd 61 33 8a 63 fb  71 e6 87 68 32 9c 41 d5  |.A.a3.c.q..h2.A.|
+00000240  59 ee 93 55 16 e9 0a 01  72 14 93 23 82 73 91 3a  |Y..U....r..#.s.:|
+00000250  6d 3c e6 e0 a8 33 34 84  80 59 65 6b c1 6d 01 19  |m<...34..Yek.m..|
+00000260  cc d5 4f 1d f6 88 4f cc  b5 c6 3c 9c 68 4a be 47  |..O...O...<.hJ.G|
+00000270  c2 67 61 a4 e3 c3 00 c0  9c d4 83 ed b5 65 25 a4  |.ga..........e%.|
+00000280  2e 1c 8d 47 3f 80 b8 1d  5b 74 a2 bf fa b9 b7 e2  |...G?...[t......|
+00000290  58 94 ba ec a9 cf 1c 56  ef 0a 16 03 03 00 92 0f  |X......V........|
+000002a0  00 00 8e 04 03 00 8a 30  81 87 02 41 75 cf 19 3a  |.......0...Au..:|
+000002b0  a1 9e e9 69 c7 f3 63 0b  46 c2 60 35 e1 cc 95 0d  |...i..c.F.`5....|
+000002c0  ee 0f ad 28 17 b4 b2 09  ea 38 18 c7 08 84 b6 ac  |...(.....8......|
+000002d0  65 03 b9 49 c3 ea ff e4  45 d3 15 14 3a 94 14 0c  |e..I....E...:...|
+000002e0  cb 48 ce 75 c2 a4 4a 0e  7d d8 f0 c5 5f 02 42 01  |.H.u..J.}..._.B.|
+000002f0  99 dd c7 54 ce ee 38 bb  18 16 eb 92 0a 53 0b 92  |...T..8......S..|
+00000300  d8 73 73 48 b3 0a 3b ea  12 ea 62 d3 88 99 00 54  |.ssH..;...b....T|
+00000310  bc 92 28 7d 66 b3 17 7f  e7 5f 69 50 d1 a1 4c 6a  |..(}f...._iP..Lj|
+00000320  99 60 00 59 0a 4d 6c 97  05 54 ee 82 5a e1 c5 88  |.`.Y.Ml..T..Z...|
+00000330  1b 14 03 03 00 01 01 16  03 03 00 24 80 64 11 aa  |...........$.d..|
+00000340  cc 9d 1c 83 b6 2f 56 dc  48 cb 33 e5 0f 25 a2 42  |...../V.H.3..%.B|
+00000350  df b8 a6 cc 64 93 10 63  ad 76 91 27 3f c7 8f d4  |....d..c.v.'?...|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 24 6f 6b e7 fb f7  |..........$ok...|
-00000010  52 83 b3 6f ba 1b d7 e8  cb 0a 05 ee 90 04 2b c7  |R..o..........+.|
-00000020  c2 bd 0d 8e ee 42 88 40  ae 01 4a d0 07 4b f4 17  |.....B. at ..J..K..|
-00000030  03 03 00 21 e0 8b bd 80  04 18 9c be 12 07 d4 4d  |...!...........M|
-00000040  58 d9 ec c3 f0 67 b5 b3  d1 78 25 e7 2e dd a0 0a  |X....g...x%.....|
-00000050  ac 0f a1 90 59 15 03 03  00 16 76 30 22 0b 00 83  |....Y.....v0"...|
-00000060  c4 31 29 1c ca 44 cb 9f  0e 48 17 21 43 f6 af 47  |.1)..D...H.!C..G|
+00000000  14 03 03 00 01 01 16 03  03 00 24 24 8d e5 5f d9  |..........$$.._.|
+00000010  99 7d d4 f2 5f f4 4b e3  b4 8e 33 84 7a c3 cb bf  |.}.._.K...3.z...|
+00000020  21 00 94 db 7b 7f 6c fa  a0 f2 9f 0e e9 3b 27 17  |!...{.l......;'.|
+00000030  03 03 00 21 67 f8 3a ff  c1 3b cb de 04 bf 49 a6  |...!g.:..;....I.|
+00000040  9a 45 56 ab 64 99 06 7e  40 cc a7 f6 4e 1e ca cb  |.EV.d..~@...N...|
+00000050  11 87 da 58 b7 15 03 03  00 16 10 1b 62 97 25 bf  |...X........b.%.|
+00000060  84 c1 23 d6 76 4a a1 da  07 c7 25 68 f6 6e 63 55  |..#.vJ....%h.ncU|
diff --git a/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven
index 862e0be..819825c 100644
--- a/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven
+++ b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedAndGiven
@@ -1,10 +1,10 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 5a 01 00 00  56 03 03 b0 80 f6 7c 13  |....Z...V.....|.|
-00000010  30 5d 57 f0 11 3b 30 4b  0e 01 50 9a 44 0b 89 6f  |0]W..;0K..P.D..o|
-00000020  b6 f1 a3 34 b4 f1 b9 bf  fe 66 a5 00 00 04 00 05  |...4.....f......|
-00000030  00 ff 01 00 00 29 00 0d  00 20 00 1e 06 01 06 02  |.....)... ......|
-00000040  06 03 05 01 05 02 05 03  04 01 04 02 04 03 03 01  |................|
-00000050  03 02 03 03 02 01 02 02  02 03 00 0f 00 01 01     |...............|
+00000000  16 03 01 00 5b 01 00 00  57 03 03 87 41 6f c5 67  |....[...W...Ao.g|
+00000010  07 3b 12 46 ad aa d2 be  0d 08 98 e3 c7 4b ac 48  |.;.F.........K.H|
+00000020  67 02 6b 3b dc 84 79 c5  57 e9 89 00 00 04 00 05  |g.k;..y.W.......|
+00000030  00 ff 02 01 00 00 29 00  0d 00 20 00 1e 06 01 06  |......)... .....|
+00000040  02 06 03 05 01 05 02 05  03 04 01 04 02 04 03 03  |................|
+00000050  01 03 02 03 03 02 01 02  02 02 03 00 0f 00 01 01  |................|
 >>> Flow 2 (server to client)
 00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -85,32 +85,32 @@
 000001d0  8b ec ab 67 be c8 64 b0  11 50 46 58 17 6b 99 1c  |...g..d..PFX.k..|
 000001e0  d3 1d fc 06 f1 0e e5 96  a8 0c f9 78 20 b7 44 18  |...........x .D.|
 000001f0  51 8d 10 7e 4f 94 67 df  a3 4e 70 73 8e 90 91 85  |Q..~O.g..Nps....|
-00000200  16 03 03 00 86 10 00 00  82 00 80 98 61 16 34 c4  |............a.4.|
-00000210  c6 0a 47 c1 de 87 b1 b7  70 1b 24 8d 7e 35 90 35  |..G.....p.$.~5.5|
-00000220  f7 a5 6f c7 c9 91 ad 46  4c 50 e5 7e 61 7c 49 66  |..o....FLP.~a|If|
-00000230  e9 fe 1e 2c 30 fa 22 03  36 8f 44 27 a7 d2 14 84  |...,0.".6.D'....|
-00000240  d0 1f 21 ca 40 35 d1 7d  31 3f e1 73 de 69 bc da  |..!. at 5.}1?.s.i..|
-00000250  a5 96 8a b5 50 2b 4b 87  5a b3 fb e1 11 0a 29 59  |....P+K.Z.....)Y|
-00000260  13 2e e3 c2 05 d3 23 e8  09 0c 42 f6 8e 26 67 89  |......#...B..&g.|
-00000270  24 0f 08 2f 3d 24 2b 0c  a2 98 38 02 5c 95 9f ce  |$../=$+...8.\...|
-00000280  e3 75 ba 05 b5 f8 f0 07  e9 a1 44 16 03 03 00 88  |.u........D.....|
-00000290  0f 00 00 84 04 01 00 80  04 c0 bc 4b 23 59 ed 26  |...........K#Y.&|
-000002a0  8d 90 35 da 5b 55 88 e7  12 10 7b d7 1c 27 d1 c4  |..5.[U....{..'..|
-000002b0  d8 1b e2 e7 54 ad a4 be  00 6b 5b 61 2d ec 97 0c  |....T....k[a-...|
-000002c0  a5 9b ae ab 13 fa 94 53  1c 65 28 21 7d b5 c5 be  |.......S.e(!}...|
-000002d0  22 62 91 78 fc e3 de 84  5c 4e 0d f5 73 5e 20 49  |"b.x....\N..s^ I|
-000002e0  5a e2 f9 d3 2f 36 23 91  31 5b ee c7 0b 6f b3 35  |Z.../6#.1[...o.5|
-000002f0  2f 8a 51 84 3c fe 78 34  1f 8c 68 d3 fc 4f c6 5e  |/.Q.<.x4..h..O.^|
-00000300  7b fe b2 81 79 91 37 ee  7f f1 9b a4 88 5f 1b 44  |{...y.7......_.D|
-00000310  dc e9 36 bb d1 45 bb 1f  14 03 03 00 01 01 16 03  |..6..E..........|
-00000320  03 00 24 12 e7 8a 31 36  26 9f fe 45 95 cf 41 56  |..$...16&..E..AV|
-00000330  b4 69 ef e4 22 14 5a 4d  c8 79 a7 18 7b 68 a8 02  |.i..".ZM.y..{h..|
-00000340  75 ea 42 fe c4 a1 32                              |u.B...2|
+00000200  16 03 03 00 86 10 00 00  82 00 80 79 a7 23 10 fc  |...........y.#..|
+00000210  64 a7 ab 17 ce d6 8b ab  ff c2 44 40 3b ba b4 c6  |d.........D@;...|
+00000220  86 b7 66 7d be 9b fa 66  f9 f6 bb e4 f7 02 16 ea  |..f}...f........|
+00000230  0f 13 9c 8a 98 3a 34 e6  58 82 dc dc 27 3a 3d 5c  |.....:4.X...':=\|
+00000240  99 09 db 48 54 a5 5a a2  16 7f ba 99 d9 0d ca fb  |...HT.Z.........|
+00000250  4a 9e b7 f6 3a ab 26 ef  f9 df a2 0c 4c 45 19 3b  |J...:.&.....LE.;|
+00000260  b2 9f 21 cd ff fc cc c7  fb 91 fa 54 93 a9 42 a9  |..!........T..B.|
+00000270  4c 48 4a 8c 7b 9a d7 90  97 f6 21 89 03 f6 a5 86  |LHJ.{.....!.....|
+00000280  83 6f 21 19 2f 5b f8 ec  a6 36 e9 16 03 03 00 88  |.o!./[...6......|
+00000290  0f 00 00 84 04 01 00 80  0f 9d 15 cc c0 0b 71 8a  |..............q.|
+000002a0  b9 95 ca 9a 86 ff bf 93  8d da 64 ce 99 28 e2 6e  |..........d..(.n|
+000002b0  6d 6f 34 c9 03 fa 87 96  b0 1d 4f b2 3c 9e 4d 2c  |mo4.......O.<.M,|
+000002c0  df be 7d fb 53 fe 90 6f  45 f3 f0 d9 ab 70 d4 df  |..}.S..oE....p..|
+000002d0  5a 95 a4 53 12 02 c1 45  15 c2 2b 69 7e 5f 6f cd  |Z..S...E..+i~_o.|
+000002e0  b3 eb 5d ff 48 36 94 ad  28 29 fe 47 40 ab 9c eb  |..].H6..().G at ...|
+000002f0  02 f9 ca 7d e0 48 9f 6e  a4 9f 1e c2 d7 fd 16 18  |...}.H.n........|
+00000300  db ad d9 35 27 89 96 c8  c4 70 10 be a4 5d 6b b4  |...5'....p...]k.|
+00000310  d8 61 70 93 08 00 0f c9  14 03 03 00 01 01 16 03  |.ap.............|
+00000320  03 00 24 7b ee b7 23 12  63 f0 80 ca b3 6f d3 b8  |..${..#.c....o..|
+00000330  ca cc 4a 54 06 ea e5 3e  73 f2 de 1d d6 16 7e 61  |..JT...>s.....~a|
+00000340  32 76 eb f8 8a 66 74                              |2v...ft|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 24 ae 6d 7b ac b6  |..........$.m{..|
-00000010  62 5c 40 65 6b 0e 5c 12  68 61 14 90 54 3e 24 78  |b\@ek.\.ha..T>$x|
-00000020  be 85 17 a0 9b de a0 00  e9 80 1b a9 0f e4 d7 17  |................|
-00000030  03 03 00 21 86 06 17 6b  62 02 a7 a0 71 fe c0 e4  |...!...kb...q...|
-00000040  44 00 54 dd cc a9 70 cf  bc 92 0d 40 07 62 f5 39  |D.T...p.... at .b.9|
-00000050  2a 30 ab 7f cd 15 03 03  00 16 6f 8d c9 d4 62 02  |*0........o...b.|
-00000060  da 64 4c 89 32 86 9f 29  24 05 ed cc 77 9d e5 55  |.dL.2..)$...w..U|
+00000000  14 03 03 00 01 01 16 03  03 00 24 64 d5 a4 78 e9  |..........$d..x.|
+00000010  f1 1d d1 34 f7 b3 95 87  18 f6 cf 65 c6 f0 02 08  |...4.......e....|
+00000020  69 f5 6d aa f2 da fc 2c  ac fc aa f8 25 aa 50 17  |i.m....,....%.P.|
+00000030  03 03 00 21 9f 94 f8 78  46 58 2c 21 0d 30 04 89  |...!...xFX,!.0..|
+00000040  bd 35 03 dc 04 b6 0f 6f  22 65 db 3d 8d 96 00 0c  |.5.....o"e.=....|
+00000050  db bf e5 b3 59 15 03 03  00 16 a6 35 f2 07 5e 32  |....Y......5..^2|
+00000060  4e 09 e4 31 3a f6 4a 83  c2 03 db b9 bf b0 eb 6d  |N..1:.J........m|
diff --git a/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven
index 5de6dd8..903272b 100644
--- a/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven
+++ b/src/crypto/tls/testdata/Server-TLSv12-ClientAuthRequestedNotGiven
@@ -1,10 +1,10 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 5a 01 00 00  56 03 03 52 b6 c5 b4 e3  |....Z...V..R....|
-00000010  35 ce 4e b2 9c e0 38 09  e7 fe 00 a2 1a 0a 43 eb  |5.N...8.......C.|
-00000020  df 98 6a 34 71 f9 d0 f8  5d e7 5e 00 00 04 00 05  |..j4q...].^.....|
-00000030  00 ff 01 00 00 29 00 0d  00 20 00 1e 06 01 06 02  |.....)... ......|
-00000040  06 03 05 01 05 02 05 03  04 01 04 02 04 03 03 01  |................|
-00000050  03 02 03 03 02 01 02 02  02 03 00 0f 00 01 01     |...............|
+00000000  16 03 01 00 5b 01 00 00  57 03 03 9a 56 e0 d9 b8  |....[...W...V...|
+00000010  ac d5 88 c7 2f d1 87 1b  44 c6 ff 7b 4f 6f f0 2a  |..../...D..{Oo.*|
+00000020  56 a1 9e 46 86 4b 6f 91  29 29 3b 00 00 04 00 05  |V..F.Ko.));.....|
+00000030  00 ff 02 01 00 00 29 00  0d 00 20 00 1e 06 01 06  |......)... .....|
+00000040  02 06 03 05 01 05 02 05  03 04 01 04 02 04 03 03  |................|
+00000050  01 03 02 03 03 02 01 02  02 02 03 00 0f 00 01 01  |................|
 >>> Flow 2 (server to client)
 00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -54,23 +54,23 @@
 000002d0  00                                                |.|
 >>> Flow 3 (client to server)
 00000000  16 03 03 00 07 0b 00 00  03 00 00 00 16 03 03 00  |................|
-00000010  86 10 00 00 82 00 80 2e  8e cb 6c f5 db 45 5b f0  |..........l..E[.|
-00000020  67 7d b1 ac 87 c2 d6 e9  ea 37 40 15 2a ea a1 af  |g}.......7 at .*...|
-00000030  ed 71 68 18 9c 6c 84 20  52 3e 38 94 8e d9 cd b3  |.qh..l. R>8.....|
-00000040  15 73 8b db d7 ff 1d 8a  ed a6 f4 00 7d d0 0a 1e  |.s..........}...|
-00000050  9a 1b 5c 59 f6 a0 29 62  03 a1 c6 bf 8a 57 14 06  |..\Y..)b.....W..|
-00000060  9a e8 03 72 bc cd cd 6f  6d e2 ce a8 41 7a f0 65  |...r...om...Az.e|
-00000070  42 0c 7b dd 93 d7 ab 37  f8 2a b3 c4 72 95 61 e1  |B.{....7.*..r.a.|
-00000080  75 98 f5 99 69 ef 0a d0  00 41 0f 05 87 13 d3 7d  |u...i....A.....}|
-00000090  ba 74 34 43 9a 6c d0 14  03 03 00 01 01 16 03 03  |.t4C.l..........|
-000000a0  00 24 87 7e 7d 48 ca 17  9c ad 30 b8 6a 05 2f d3  |.$.~}H....0.j./.|
-000000b0  fc 18 2e df fd f5 0e 38  c3 06 57 4c 27 66 02 af  |.......8..WL'f..|
-000000c0  6d 78 4d 2e b6 dc                                 |mxM...|
+00000010  86 10 00 00 82 00 80 3a  72 91 a2 c3 ba 83 75 1b  |.......:r.....u.|
+00000020  d3 f6 1c 07 7f 92 a8 b0  1f 47 42 cc 8d 4e 7e 1e  |.........GB..N~.|
+00000030  23 49 44 29 53 19 9f 3b  5c bb 5d ed 6c d9 49 5d  |#ID)S..;\.].l.I]|
+00000040  6e f9 d1 59 9d 40 67 b3  0c ee 41 85 6c 4a 4d 3b  |n..Y. at g...A.lJM;|
+00000050  c1 e6 c8 7f 93 15 cb 2a  17 64 da 70 f3 2a c3 7c  |.......*.d.p.*.||
+00000060  a2 02 48 19 fb 74 5a dc  52 0d 80 6b ed c0 8c 15  |..H..tZ.R..k....|
+00000070  3e 3b 34 7c 55 6e 95 e0  d1 4a 7f b0 bc 33 67 a7  |>;4|Un...J...3g.|
+00000080  3b 40 bb eb 83 58 4a fb  fb 01 9b 0d fa ef 83 c4  |;@...XJ.........|
+00000090  87 10 75 0c a7 ad 91 14  03 03 00 01 01 16 03 03  |..u.............|
+000000a0  00 24 18 ce de 8d ab c1  6e 3b 0b 51 fe 94 ae 0a  |.$......n;.Q....|
+000000b0  39 9c 4d a2 90 53 d4 1e  5f f6 96 5a 51 f2 39 c1  |9.M..S.._..ZQ.9.|
+000000c0  d6 06 c0 4e 58 99                                 |...NX.|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 24 cf ee f6 28 ea  |..........$...(.|
-00000010  df e2 7e 9a 75 e0 f9 b4  c4 c2 57 3a 54 26 db 7f  |..~.u.....W:T&..|
-00000020  c4 19 6d b6 d6 c7 b1 05  7f 92 21 9e 51 1a 0a 17  |..m.......!.Q...|
-00000030  03 03 00 21 87 48 77 c4  eb 7c 5d 13 3b f4 8d 08  |...!.Hw..|].;...|
-00000040  f9 35 c3 d2 e5 c0 8c ea  15 c9 2d c5 e0 70 fd 7c  |.5........-..p.||
-00000050  de 93 4f 8c 8d 15 03 03  00 16 d4 8a d5 6a fc db  |..O..........j..|
-00000060  c7 1d 1f 76 64 b9 31 68  72 cc 58 de 9f 2a a6 45  |...vd.1hr.X..*.E|
+00000000  14 03 03 00 01 01 16 03  03 00 24 8b 7e 57 f3 7d  |..........$.~W.}|
+00000010  ab 44 f0 c7 53 2d 39 08  14 32 12 4e 4b 45 9a e3  |.D..S-9..2.NKE..|
+00000020  1c 43 36 16 59 a0 4b e4  78 43 d2 a5 dc 96 b1 17  |.C6.Y.K.xC......|
+00000030  03 03 00 21 54 89 75 23  de 7d c7 c6 80 a6 a6 69  |...!T.u#.}.....i|
+00000040  d0 a8 95 77 71 a0 89 34  f4 c3 31 73 bb b0 ac d7  |...wq..4..1s....|
+00000050  e5 e4 83 4b 10 15 03 03  00 16 0d 44 43 67 21 cc  |...K.......DCg!.|
+00000060  6c c1 7e 72 99 aa 7f a1  de 10 0b 36 ae 05 d9 9e  |l.~r.......6....|
diff --git a/src/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES b/src/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES
index 3b7238a..8b04a5a 100644
--- a/src/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES
+++ b/src/crypto/tls/testdata/Server-TLSv12-ECDHE-ECDSA-AES
@@ -1,15 +1,13 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 a1 01 00 00  9d 03 03 0f b7 07 5f c7  |.............._.|
-00000010  18 b8 39 6d 92 b3 90 ed  bf 5c 48 7c 6a 56 ee e9  |..9m.....\H|jV..|
-00000020  7a 5b 5f 71 a4 f0 7f 47  57 73 78 00 00 04 c0 0a  |z[_q...GWsx.....|
-00000030  00 ff 02 01 00 00 6f 00  0b 00 04 03 00 01 02 00  |......o.........|
-00000040  0a 00 3a 00 38 00 0e 00  0d 00 19 00 1c 00 0b 00  |..:.8...........|
-00000050  0c 00 1b 00 18 00 09 00  0a 00 1a 00 16 00 17 00  |................|
-00000060  08 00 06 00 07 00 14 00  15 00 04 00 05 00 12 00  |................|
-00000070  13 00 01 00 02 00 03 00  0f 00 10 00 11 00 0d 00  |................|
-00000080  20 00 1e 06 01 06 02 06  03 05 01 05 02 05 03 04  | ...............|
-00000090  01 04 02 04 03 03 01 03  02 03 03 02 01 02 02 02  |................|
-000000a0  03 00 0f 00 01 01                                 |......|
+00000000  16 03 01 00 83 01 00 00  7f 03 03 ec 8e d0 43 01  |..............C.|
+00000010  8e 81 3f d8 1f 7e 96 f1  de 4c 94 18 09 1d c5 8c  |..?..~...L......|
+00000020  3a 58 68 5b 3e 7d 46 66  fe 04 74 00 00 04 c0 0a  |:Xh[>}Ff..t.....|
+00000030  00 ff 02 01 00 00 51 00  0b 00 04 03 00 01 02 00  |......Q.........|
+00000040  0a 00 1c 00 1a 00 17 00  19 00 1c 00 1b 00 18 00  |................|
+00000050  1a 00 16 00 0e 00 0d 00  0b 00 0c 00 09 00 0a 00  |................|
+00000060  0d 00 20 00 1e 06 01 06  02 06 03 05 01 05 02 05  |.. .............|
+00000070  03 04 01 04 02 04 03 03  01 03 02 03 03 02 01 02  |................|
+00000080  02 02 03 00 0f 00 01 01                           |........|
 >>> Flow 2 (server to client)
 00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -53,37 +51,37 @@
 00000270  b2 56 1c ce 97 28 5e f8  2b 2d 4f 9e f1 07 9f 6c  |.V...(^.+-O....l|
 00000280  4b 5b 83 56 e2 32 42 e9  58 b6 d7 49 a6 b5 68 1a  |K[.V.2B.X..I..h.|
 00000290  41 03 56 6b dc 5a 89 05  03 00 8b 30 81 88 02 42  |A.Vk.Z.....0...B|
-000002a0  00 d3 cf 21 cd 3c 2e 11  f5 f8 1d c8 c1 57 4b f8  |...!.<.......WK.|
-000002b0  1a c0 2b 1d 47 0f 2d a5  ac a1 c8 83 5d 76 87 05  |..+.G.-.....]v..|
-000002c0  2b 0d 36 d5 57 9f b9 8a  a0 a2 94 67 6a cd 29 db  |+.6.W......gj.).|
-000002d0  04 b0 6b 06 d9 f7 17 9f  1c 60 92 e7 4e 50 48 7f  |..k......`..NPH.|
-000002e0  dc d0 02 42 01 56 fd 38  bd 05 a5 16 6d 91 d1 ce  |...B.V.8....m...|
-000002f0  bb 8c 45 b2 76 2f 92 9c  8b 94 57 7d de 53 8b 7b  |..E.v/....W}.S.{|
-00000300  80 26 6c 4a 43 4b a6 c9  46 49 08 ab c7 57 f3 d9  |.&lJCK..FI...W..|
-00000310  fa 1d 55 fe 91 de 8a 0d  8b d1 44 96 87 85 cb 02  |..U.......D.....|
-00000320  76 9c 00 ad 5f b8 16 03  03 00 04 0e 00 00 00     |v..._..........|
+000002a0  01 08 89 99 1c 91 97 fb  e8 5b 69 5f f5 36 66 d6  |.........[i_.6f.|
+000002b0  dd 53 04 09 c8 7f c1 25  28 8c 28 57 55 3a 95 3f  |.S.....%(.(WU:.?|
+000002c0  ab 09 47 9a 27 74 83 84  44 cf 86 b7 5e 7f fe db  |..G.'t..D...^...|
+000002d0  05 33 3c 1a b7 f6 bc ff  0d 33 e4 ec 3c e2 1d e2  |.3<......3..<...|
+000002e0  6e ab 02 42 00 92 4e 45  a7 86 e4 bd 40 82 b7 04  |n..B..NE.... at ...|
+000002f0  12 fe 34 ab e3 c9 4a 05  1f 4e 58 79 67 58 94 53  |..4...J..NXygX.S|
+00000300  e8 1b ba 60 76 92 00 99  a7 5f 0a 98 cb e3 1e de  |...`v...._......|
+00000310  0c df 18 76 58 d5 e1 f1  ef a5 da 9a a3 62 77 50  |...vX........bwP|
+00000320  37 d0 22 d0 31 90 16 03  03 00 04 0e 00 00 00     |7.".1..........|
 >>> Flow 3 (client to server)
-00000000  16 03 03 00 46 10 00 00  42 41 04 0b dc ea 22 05  |....F...BA....".|
-00000010  44 c2 09 47 65 31 3b 0b  e1 05 1a 87 8c 2d 3b 56  |D..Ge1;......-;V|
-00000020  49 34 27 3e d6 3b 93 e2  12 7f 5d 7b dc 85 c8 96  |I4'>.;....]{....|
-00000030  4c 8c f9 18 6f 15 cf db  6e 2c 14 6a c9 dd 1c 70  |L...o...n,.j...p|
-00000040  7e 05 c4 17 71 76 df 10  ee 8c b1 14 03 03 00 01  |~...qv..........|
-00000050  01 16 03 03 00 40 ff 12  88 36 3c 00 17 d1 b9 41  |..... at ...6<....A|
-00000060  7a 12 25 94 4c 90 65 62  d8 09 ab f9 b4 ee c3 de  |z.%.L.eb........|
-00000070  46 2f cb ee 18 76 4f 76  8e dd 89 fc 7a 21 3b 5f  |F/...vOv....z!;_|
-00000080  ff ac 1c 03 aa be 96 82  82 ea 2e 22 2a 80 b3 86  |..........."*...|
-00000090  38 e4 4d 90 91 46                                 |8.M..F|
+00000000  16 03 03 00 46 10 00 00  42 41 04 9e 94 25 4f 70  |....F...BA...%Op|
+00000010  a8 e0 87 3a 09 6c 58 4f  5e 76 d9 63 dc c3 d5 63  |...:.lXO^v.c...c|
+00000020  be f2 75 ff 23 23 79 6b  82 fe 56 f5 b9 7a 55 55  |..u.##yk..V..zUU|
+00000030  32 3b ee c5 f0 1f 7b e9  82 01 21 8d 06 03 48 95  |2;....{...!...H.|
+00000040  21 b8 fa 9d 18 2a 08 9c  71 a8 4d 14 03 03 00 01  |!....*..q.M.....|
+00000050  01 16 03 03 00 40 31 f0  7b 5f e8 94 a3 7f b0 12  |..... at 1.{_......|
+00000060  a9 80 87 26 eb cf b6 87  61 e7 5b 9b 36 3d 11 bb  |...&....a.[.6=..|
+00000070  21 55 5c f7 e8 f3 b7 1e  f2 06 0d c5 a9 8d f8 48  |!U\............H|
+00000080  c2 2b 8f 83 be 17 4f ec  ff 8e 24 44 74 25 09 40  |.+....O...$Dt%.@|
+00000090  90 fd 70 4d fb bb                                 |..pM..|
 >>> Flow 4 (server to client)
 00000000  14 03 03 00 01 01 16 03  03 00 40 00 00 00 00 00  |.......... at .....|
-00000010  00 00 00 00 00 00 00 00  00 00 00 e5 c1 f0 6a db  |..............j.|
-00000020  05 98 ed 33 94 73 7f 13  7f 78 17 7f d1 9e c5 a7  |...3.s...x......|
-00000030  62 7f 85 14 2c 7d b2 8e  ef 75 a9 df 92 cc 22 20  |b...,}...u...." |
-00000040  66 08 85 22 d3 ea 5c 4c  4c c8 d7 17 03 03 00 40  |f.."..\LL......@|
+00000010  00 00 00 00 00 00 00 00  00 00 00 13 eb 4e 56 3d  |.............NV=|
+00000020  1b 10 2e e8 08 65 b9 53  9e 56 49 b7 e9 25 35 94  |.....e.S.VI..%5.|
+00000030  c7 df 7d f7 78 2e f3 8b  9c 2b 9d 42 90 91 5c 97  |..}.x....+.B..\.|
+00000040  22 20 ca 6d a2 83 b3 d8  b3 71 64 17 03 03 00 40  |" .m.....qd....@|
 00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000060  f2 20 07 d2 13 ca ed 01  c9 7b 91 14 01 2c 08 f5  |. .......{...,..|
-00000070  8a 69 94 bc 19 9a d9 65  6b 15 04 b4 45 17 ec 6f  |.i.....ek...E..o|
-00000080  85 de 31 dc a2 de 8b 4d  53 57 66 4a 29 21 5a 20  |..1....MSWfJ)!Z |
+00000060  97 f1 c4 2e bf 6d 85 d5  3d 4b 4a 8b ee 53 08 5a  |.....m..=KJ..S.Z|
+00000070  db 8b 75 49 d9 cb db e3  86 90 ac 93 ce e7 9a 70  |..uI...........p|
+00000080  4c dc 4a f4 c9 f6 b5 fd  f0 3f 9f e9 f9 c3 b3 c6  |L.J......?......|
 00000090  15 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
-000000a0  00 00 00 00 00 55 15 f7  89 8d 75 57 7e 92 db ec  |.....U....uW~...|
-000000b0  32 ec 07 5c 83 32 36 59  61 f1 9d a6 7a eb 76 c1  |2..\.26Ya...z.v.|
-000000c0  c7 96 3f 4d 0a                                    |..?M.|
+000000a0  00 00 00 00 00 5e b1 b7  21 7d 89 65 66 17 d8 79  |.....^..!}.ef..y|
+000000b0  26 db ad 08 28 2c e7 7a  c4 ec 93 19 4f c8 bb 5c  |&...(,.z....O..\|
+000000c0  c2 9e 09 56 07                                    |...V.|
diff --git a/src/crypto/tls/testdata/Server-TLSv12-IssueTicket b/src/crypto/tls/testdata/Server-TLSv12-IssueTicket
index 20a0731..2760508 100644
--- a/src/crypto/tls/testdata/Server-TLSv12-IssueTicket
+++ b/src/crypto/tls/testdata/Server-TLSv12-IssueTicket
@@ -1,11 +1,11 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 5e 01 00 00  5a 03 03 f0 0a 06 d0 65  |....^...Z......e|
-00000010  1c c3 90 ac dc 61 42 e5  b8 a9 17 fb e7 c3 1e bd  |.....aB.........|
-00000020  d9 09 5a 63 71 e2 f9 58  db 26 6e 00 00 04 00 05  |..Zcq..X.&n.....|
-00000030  00 ff 01 00 00 2d 00 23  00 00 00 0d 00 20 00 1e  |.....-.#..... ..|
-00000040  06 01 06 02 06 03 05 01  05 02 05 03 04 01 04 02  |................|
-00000050  04 03 03 01 03 02 03 03  02 01 02 02 02 03 00 0f  |................|
-00000060  00 01 01                                          |...|
+00000000  16 03 01 00 5f 01 00 00  5b 03 03 6e cc 37 81 0a  |...._...[..n.7..|
+00000010  b9 fe 58 30 8e 32 61 3c  b1 38 1e 2b f6 ab 44 ee  |..X0.2a<.8.+..D.|
+00000020  f2 cc fe 6e fe 40 65 49  d9 ba aa 00 00 04 00 05  |...n. at eI........|
+00000030  00 ff 02 01 00 00 2d 00  23 00 00 00 0d 00 20 00  |......-.#..... .|
+00000040  1e 06 01 06 02 06 03 05  01 05 02 05 03 04 01 04  |................|
+00000050  02 04 03 03 01 03 02 03  03 02 01 02 02 02 03 00  |................|
+00000060  0f 00 01 01                                       |....|
 >>> Flow 2 (server to client)
 00000000  16 03 03 00 35 02 00 00  31 03 03 00 00 00 00 00  |....5...1.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -52,32 +52,32 @@
 000002a0  4f 86 c7 f9 a4 c2 41 34  ac cc f6 ea b0 ab 39 18  |O.....A4......9.|
 000002b0  16 03 03 00 04 0e 00 00  00                       |.........|
 >>> Flow 3 (client to server)
-00000000  16 03 03 00 86 10 00 00  82 00 80 87 06 ba d7 1f  |................|
-00000010  68 0c f2 a6 51 b4 ae af  8c c5 5d d4 bd f1 82 6d  |h...Q.....]....m|
-00000020  1d dd ce 69 be 07 62 13  af 06 71 3a 47 a9 bd f7  |...i..b...q:G...|
-00000030  bb 27 f0 38 df 88 01 40  29 c9 bb 7b 5d 6d 28 bd  |.'.8...@)..{]m(.|
-00000040  c8 28 e6 6d ff 5c c9 d3  c6 f5 06 17 e5 e5 1c 5b  |.(.m.\.........[|
-00000050  a1 18 7a 34 92 0a 39 20  5a 22 44 6c cc 5c 8c 83  |..z4..9 Z"Dl.\..|
-00000060  d0 19 4c bb 4e dc e2 64  ec b2 b8 3f 18 3f 9d 65  |..L.N..d...?.?.e|
-00000070  5b 89 26 ae f6 fd 54 71  c4 45 e9 56 6a 28 42 a9  |[.&...Tq.E.Vj(B.|
-00000080  5b 9f 12 69 a4 08 83 53  95 04 18 14 03 03 00 01  |[..i...S........|
-00000090  01 16 03 03 00 24 55 80  0f 43 c3 08 45 99 c9 1b  |.....$U..C..E...|
-000000a0  fd fe dd e8 48 f2 89 99  86 ef f7 fd 5f 2a 4b 0b  |....H......._*K.|
-000000b0  33 0e 5f 17 bb b7 a2 3c  9d 30                    |3._....<.0|
+00000000  16 03 03 00 86 10 00 00  82 00 80 5d f3 3b c6 24  |...........].;.$|
+00000010  34 17 eb e1 6c de fa cd  ed 6f 42 74 01 5f 4b 22  |4...l....oBt._K"|
+00000020  9e 79 da 68 9f e9 f8 af  84 6b b7 38 52 f3 5e a1  |.y.h.....k.8R.^.|
+00000030  e2 aa d1 48 15 1e 39 6e  18 59 3e dc 57 4a fb b1  |...H..9n.Y>.WJ..|
+00000040  18 18 40 ae 84 da d8 76  50 65 3b a5 d9 7a 72 b1  |.. at ....vPe;..zr.|
+00000050  51 07 65 08 0e 1d 05 f5  47 a8 7d 79 89 1e fe 00  |Q.e.....G.}y....|
+00000060  89 af 01 7f 4d 0c 11 d7  02 cf 88 7b be 03 c5 65  |....M......{...e|
+00000070  44 77 32 56 5c da 01 53  d1 dd d9 b4 5f 42 85 da  |Dw2V\..S...._B..|
+00000080  82 0b 95 59 45 a3 7a 48  d4 00 22 14 03 03 00 01  |...YE.zH..".....|
+00000090  01 16 03 03 00 24 dd 06  a2 4b a0 8e 8b 31 f2 26  |.....$...K...1.&|
+000000a0  b2 6f d4 5d ff 34 eb 31  42 16 e7 c2 26 3d f7 16  |.o.].4.1B...&=..|
+000000b0  ed bd 41 4b 6f d4 03 fb  b7 83                    |..AKo.....|
 >>> Flow 4 (server to client)
 00000000  16 03 03 00 82 04 00 00  7e 00 00 00 00 00 78 50  |........~.....xP|
 00000010  46 ad c1 db a8 38 86 7b  2b bb fd d0 c3 42 3e 00  |F....8.{+....B>.|
 00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 94  |................|
-00000030  6f 2c b5 83 61 c4 74 90  94 e5 6c fd 70 64 57 3a  |o,..a.t...l.pdW:|
-00000040  25 78 bf 9f a0 7c 51 bc  2a 69 1e b3 fd 71 34 b7  |%x...|Q.*i...q4.|
-00000050  9a ef cb 49 37 f8 5d 5e  7c cf 6d fc 13 c1 52 79  |...I7.]^|.m...Ry|
-00000060  8e ed c3 84 01 33 94 10  65 34 64 5e b4 9c 07 46  |.....3..e4d^...F|
-00000070  5b 9e d7 5e 55 df fd c0  e9 d2 e8 d3 c6 42 18 ef  |[..^U........B..|
-00000080  a5 6c be e8 d2 49 c6 14  03 03 00 01 01 16 03 03  |.l...I..........|
-00000090  00 24 66 94 4b b5 3f 5d  59 db 36 c1 dd 55 8c ee  |.$f.K.?]Y.6..U..|
-000000a0  de a4 bc d0 12 44 31 3e  e4 e7 4a 51 e3 62 69 ab  |.....D1>..JQ.bi.|
-000000b0  14 78 85 49 a3 97 17 03  03 00 21 dd 96 5d 21 e0  |.x.I......!..]!.|
-000000c0  2e 3d 33 dd 6c df bb 41  d7 bd 50 c7 1c 6f 97 34  |.=3.l..A..P..o.4|
-000000d0  6a 6e d6 1d 27 81 2d f7  fb 32 85 02 15 03 03 00  |jn..'.-..2......|
-000000e0  16 5e 4e 62 15 97 a7 a3  9b 1b 50 44 85 fb 28 66  |.^Nb......PD..(f|
-000000f0  aa 66 54 45 c9 dc 61                              |.fTE..a|
+00000030  6f 2c b5 83 61 4d 51 5f  33 46 48 fe 9e e9 83 f4  |o,..aMQ_3FH.....|
+00000040  b1 aa c9 b1 61 2a b2 9d  0f 17 c4 09 f6 26 7a 75  |....a*.......&zu|
+00000050  f1 19 99 db 36 d8 32 f0  94 61 4f 8f ed 80 33 51  |....6.2..aO...3Q|
+00000060  f3 c6 15 84 6b 33 94 c8  4f 84 b7 7c 27 6d 8f fe  |....k3..O..|'m..|
+00000070  41 8e b2 92 ca 80 e8 6c  ba 75 77 f5 3a 87 17 ae  |A......l.uw.:...|
+00000080  f8 b9 6b 10 f9 85 da 14  03 03 00 01 01 16 03 03  |..k.............|
+00000090  00 24 70 bd b9 24 02 ce  69 8a 07 c7 c8 7e cf b7  |.$p..$..i....~..|
+000000a0  4e 2b e2 dc 47 fc f7 3a  c8 2d ab a0 9a ed 27 d9  |N+..G..:.-....'.|
+000000b0  71 ea 45 29 d6 25 17 03  03 00 21 d9 28 ee 99 04  |q.E).%....!.(...|
+000000c0  35 ff ca 3d 30 3f 76 fb  08 1a 56 73 f5 72 c3 fa  |5..=0?v...Vs.r..|
+000000d0  cd 9e 3c 1b 3f 43 4d 56  92 38 9e a6 15 03 03 00  |..<.?CMV.8......|
+000000e0  16 6f 55 57 7b 81 6f 7d  fa 90 76 0b 5b 6d 95 35  |.oUW{.o}..v.[m.5|
+000000f0  39 9f a8 c9 dc b7 80                              |9......|
diff --git a/src/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable b/src/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable
index a8f7edf..b5eb6c7 100644
--- a/src/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable
+++ b/src/crypto/tls/testdata/Server-TLSv12-IssueTicketPreDisable
@@ -1,11 +1,11 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 5e 01 00 00  5a 03 03 62 f6 20 66 23  |....^...Z..b. f#|
-00000010  d5 71 0a c0 57 92 2e 80  b6 06 0c 54 5b 1c 77 a0  |.q..W......T[.w.|
-00000020  ce 0b b2 52 4a b9 f2 c6  97 33 42 00 00 04 00 05  |...RJ....3B.....|
-00000030  00 ff 01 00 00 2d 00 23  00 00 00 0d 00 20 00 1e  |.....-.#..... ..|
-00000040  06 01 06 02 06 03 05 01  05 02 05 03 04 01 04 02  |................|
-00000050  04 03 03 01 03 02 03 03  02 01 02 02 02 03 00 0f  |................|
-00000060  00 01 01                                          |...|
+00000000  16 03 01 00 5f 01 00 00  5b 03 03 54 25 f9 0f b8  |...._...[..T%...|
+00000010  2d 52 a0 17 b6 62 1c 60  38 31 30 67 f1 55 9c c8  |-R...b.`810g.U..|
+00000020  d3 74 65 bf cd 34 fb 6f  f2 60 7c 00 00 04 00 05  |.te..4.o.`|.....|
+00000030  00 ff 02 01 00 00 2d 00  23 00 00 00 0d 00 20 00  |......-.#..... .|
+00000040  1e 06 01 06 02 06 03 05  01 05 02 05 03 04 01 04  |................|
+00000050  02 04 03 03 01 03 02 03  03 02 01 02 02 02 03 00  |................|
+00000060  0f 00 01 01                                       |....|
 >>> Flow 2 (server to client)
 00000000  16 03 03 00 35 02 00 00  31 03 03 00 00 00 00 00  |....5...1.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -52,32 +52,32 @@
 000002a0  4f 86 c7 f9 a4 c2 41 34  ac cc f6 ea b0 ab 39 18  |O.....A4......9.|
 000002b0  16 03 03 00 04 0e 00 00  00                       |.........|
 >>> Flow 3 (client to server)
-00000000  16 03 03 00 86 10 00 00  82 00 80 5b 43 6f db 52  |...........[Co.R|
-00000010  56 e3 d9 4b 1e c8 95 8b  78 a6 19 00 44 9c 44 b4  |V..K....x...D.D.|
-00000020  f7 fe d4 3f 69 ea 9c 67  d3 48 b8 c5 93 bc 22 f1  |...?i..g.H....".|
-00000030  a9 0e 81 82 d0 cf dc 0b  ea f0 02 67 92 8d 72 40  |...........g..r@|
-00000040  25 bb f3 88 53 c0 2f ba  38 ef da d1 7c 73 84 ec  |%...S./.8...|s..|
-00000050  61 96 b9 d4 93 06 4a 06  7b 6d 40 e7 bb 15 59 6e  |a.....J.{m at ...Yn|
-00000060  ad 31 71 eb cf 84 57 3b  0c ad aa 70 02 63 24 a9  |.1q...W;...p.c$.|
-00000070  7c a1 9a 6d b7 e0 4c d5  67 4c ce 53 9d b6 31 de  ||..m..L.gL.S..1.|
-00000080  69 b9 f5 ca a8 e3 ea d6  f5 a3 f3 14 03 03 00 01  |i...............|
-00000090  01 16 03 03 00 24 66 ae  13 67 70 20 f5 f5 76 03  |.....$f..gp ..v.|
-000000a0  11 6e 32 a6 73 a2 70 42  ab 4f 16 93 d2 fa a1 ac  |.n2.s.pB.O......|
-000000b0  4e b2 08 4a a9 b5 20 aa  80 b6                    |N..J.. ...|
+00000000  16 03 03 00 86 10 00 00  82 00 80 19 db c8 25 14  |..............%.|
+00000010  e0 7b 6e 87 7b 59 2d 85  8b 47 ce 31 d7 3a 53 06  |.{n.{Y-..G.1.:S.|
+00000020  ff cf 89 ae 45 fd 59 d2  50 c2 31 33 48 81 a8 d7  |....E.Y.P.13H...|
+00000030  47 36 b9 bd 8d f3 f9 f8  c2 6d 6a 8a 6b c4 e5 53  |G6.......mj.k..S|
+00000040  24 52 40 66 49 a9 56 74  4c 94 bc 85 5b 79 5a e1  |$R at fI.VtL...[yZ.|
+00000050  66 3c 42 d8 ca e1 3f c5  36 b8 b5 8c b2 ea 87 68  |f<B...?.6......h|
+00000060  70 eb e3 da 27 fe ed f5  d0 4a c7 fe 46 0b 0f 29  |p...'....J..F..)|
+00000070  19 41 ef dd a9 85 8a 67  02 41 04 30 20 07 09 55  |.A.....g.A.0 ..U|
+00000080  ff 92 44 f1 59 49 39 dd  fa d7 a0 14 03 03 00 01  |..D.YI9.........|
+00000090  01 16 03 03 00 24 82 b5  7b d1 7c 03 93 88 fd 97  |.....$..{.|.....|
+000000a0  54 b7 ff 39 a7 11 c3 cd  53 f3 1c 6c ed ab b6 a0  |T..9....S..l....|
+000000b0  1c b9 89 f0 1a f8 5f 15  7f 85                    |......_...|
 >>> Flow 4 (server to client)
 00000000  16 03 03 00 82 04 00 00  7e 00 00 00 00 00 78 50  |........~.....xP|
 00000010  46 ad c1 db a8 38 86 7b  2b bb fd d0 c3 42 3e 00  |F....8.{+....B>.|
 00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 94  |................|
-00000030  6f 2c b5 83 61 bd 50 da  49 7f 8b 8f 58 57 00 a1  |o,..a.P.I...XW..|
-00000040  11 0d 4a 9d 8a 39 dd 85  23 c0 eb 9d 1a 45 93 92  |..J..9..#....E..|
-00000050  e7 af 15 a3 a4 48 da f9  a4 d8 8e cb 6c 3d 44 77  |.....H......l=Dw|
-00000060  f9 c4 83 89 85 33 94 c1  c6 20 9a 73 44 83 89 5e  |.....3... .sD..^|
-00000070  59 ee 05 c6 7e 8d e9 7d  7b f8 84 46 b6 7d 43 ec  |Y...~..}{..F.}C.|
-00000080  f1 af 1f 0f 35 b4 1c 14  03 03 00 01 01 16 03 03  |....5...........|
-00000090  00 24 8c 0d bd bc 34 93  ed ad 80 21 6d 08 e4 0e  |.$....4....!m...|
-000000a0  67 4f 99 8d df 2a 2d 4f  13 39 82 be a1 d2 1f 75  |gO...*-O.9.....u|
-000000b0  73 c8 b2 ce 41 0c 17 03  03 00 21 d8 c2 50 d6 11  |s...A.....!..P..|
-000000c0  bc 86 58 68 0e 60 4a 47  a5 d0 12 7e a3 b5 be 64  |..Xh.`JG...~...d|
-000000d0  e6 b1 bc 62 70 85 d4 7c  cd fe 67 cf 15 03 03 00  |...bp..|..g.....|
-000000e0  16 e4 1c d5 f4 f7 d0 f5  b2 b3 2b 3d b0 7d c0 23  |..........+=.}.#|
-000000f0  e2 5c a5 c7 a4 23 fa                              |.\...#.|
+00000030  6f 2c b5 83 61 01 55 65  2a 95 38 d4 d5 5f 41 c1  |o,..a.Ue*.8.._A.|
+00000040  45 e4 f8 4b 3b 08 44 df  0b 72 11 93 cd d4 ff 36  |E..K;.D..r.....6|
+00000050  0f 4f 3a a9 4c 9f ab c7  ae 88 97 bc 1e ff 2d 27  |.O:.L.........-'|
+00000060  39 a8 82 84 ae 33 94 48  8b 1c 58 9d 60 65 3c 3f  |9....3.H..X.`e<?|
+00000070  17 9d 6a eb 50 cd 65 04  bb c7 28 c8 0d 57 44 52  |..j.P.e...(..WDR|
+00000080  e0 17 de df f3 13 b1 14  03 03 00 01 01 16 03 03  |................|
+00000090  00 24 5a 41 90 0a eb d9  6b 02 68 3d 98 12 1d fa  |.$ZA....k.h=....|
+000000a0  46 7d 73 ea 8e 49 72 a5  2f 04 40 5c 7d 03 c7 3a  |F}s..Ir./.@\}..:|
+000000b0  6e 50 7c 87 bb 13 17 03  03 00 21 46 da ec ad 52  |nP|.......!F...R|
+000000c0  ea 5a 01 89 15 77 79 af  86 02 b5 89 c8 97 dc f7  |.Z...wy.........|
+000000d0  ac 73 09 87 7a 61 57 d6  9b 17 10 af 15 03 03 00  |.s..zaW.........|
+000000e0  16 bb 20 22 ad 6e 65 66  8c d6 07 e3 82 5f ac 1e  |.. ".nef....._..|
+000000f0  ec 54 72 eb 2d c5 af                              |.Tr.-..|
diff --git a/src/crypto/tls/testdata/Server-TLSv12-RSA-3DES b/src/crypto/tls/testdata/Server-TLSv12-RSA-3DES
index 7457626..23b6c5b 100644
--- a/src/crypto/tls/testdata/Server-TLSv12-RSA-3DES
+++ b/src/crypto/tls/testdata/Server-TLSv12-RSA-3DES
@@ -1,10 +1,10 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 5a 01 00 00  56 03 03 ac 1d 0b 6e f3  |....Z...V.....n.|
-00000010  25 04 00 97 a0 79 39 c5  ef 95 8b e3 c1 87 0d 1c  |%....y9.........|
-00000020  0b c3 39 3e ff 23 0e 3c  28 8f 75 00 00 04 00 0a  |..9>.#.<(.u.....|
-00000030  00 ff 01 00 00 29 00 0d  00 20 00 1e 06 01 06 02  |.....)... ......|
-00000040  06 03 05 01 05 02 05 03  04 01 04 02 04 03 03 01  |................|
-00000050  03 02 03 03 02 01 02 02  02 03 00 0f 00 01 01     |...............|
+00000000  16 03 01 00 5b 01 00 00  57 03 03 1e c8 d0 4c b2  |....[...W.....L.|
+00000010  8d 37 e1 88 c7 0f e0 6a  21 3c 5e 8a bf fa 97 1f  |.7.....j!<^.....|
+00000020  5b 28 bc 6d 47 32 0a 6b  f7 11 f5 00 00 04 00 0a  |[(.mG2.k........|
+00000030  00 ff 02 01 00 00 29 00  0d 00 20 00 1e 06 01 06  |......)... .....|
+00000040  02 06 03 05 01 05 02 05  03 04 01 04 02 04 03 03  |................|
+00000050  01 03 02 03 03 02 01 02  02 02 03 00 0f 00 01 01  |................|
 >>> Flow 2 (server to client)
 00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -51,27 +51,27 @@
 000002a0  a4 c2 41 34 ac cc f6 ea  b0 ab 39 18 16 03 03 00  |..A4......9.....|
 000002b0  04 0e 00 00 00                                    |.....|
 >>> Flow 3 (client to server)
-00000000  16 03 03 00 86 10 00 00  82 00 80 15 75 c5 63 e0  |............u.c.|
-00000010  c3 a5 89 dd b3 bf 03 1d  bd 62 86 2e 10 98 79 cb  |.........b....y.|
-00000020  40 3d 9b 36 7e 55 65 d7  80 0a c5 24 ff ad 98 d5  |@=.6~Ue....$....|
-00000030  d4 d9 4e 1b ed 50 0a fa  8a 3e f3 01 c4 e3 47 f7  |..N..P...>....G.|
-00000040  bd 81 fc 33 0b 61 6b b5  3f 38 9b 24 cd 7d 46 66  |...3.ak.?8.$.}Ff|
-00000050  18 87 ea 67 04 b7 ad 23  ac 64 4e 21 cd 29 9f 60  |...g...#.dN!.).`|
-00000060  0e c1 ca 3d 25 d6 d5 2b  e2 60 dc b5 57 be c0 b8  |...=%..+.`..W...|
-00000070  b6 35 25 96 5b 36 55 53  86 b7 90 ef 6c bf 45 2a  |.5%.[6US....l.E*|
-00000080  3d a0 af 08 f0 8a 9c d0  d8 6b 88 14 03 03 00 01  |=........k......|
-00000090  01 16 03 03 00 30 c5 0f  b8 12 c6 5a 42 6a d8 3f  |.....0.....ZBj.?|
-000000a0  f5 49 e4 9a 5d b7 93 90  e7 09 1f 68 40 9d 33 a9  |.I..]......h at .3.|
-000000b0  21 fa 9c 12 c7 7c d4 bf  91 c2 f8 ac 27 b9 8b b6  |!....|......'...|
-000000c0  34 6e f3 c0 fb 83                                 |4n....|
+00000000  16 03 03 00 86 10 00 00  82 00 80 4d c2 e0 9b 40  |...........M...@|
+00000010  44 52 aa 55 06 71 0b bc  17 89 3a 94 d8 d0 1d ed  |DR.U.q....:.....|
+00000020  70 d3 21 30 1b be 97 e0  72 30 60 05 de 9a a9 dd  |p.!0....r0`.....|
+00000030  8c 0c 81 78 3a 15 9c 1c  c6 22 81 0a 10 57 d1 9a  |...x:...."...W..|
+00000040  17 5c 74 9e 58 79 4b f1  70 d9 d9 21 d8 79 64 fa  |.\t.XyK.p..!.yd.|
+00000050  aa a5 e6 93 2a 16 57 23  a7 17 fb 71 b6 c2 d3 5b  |....*.W#...q...[|
+00000060  3d 22 50 16 47 17 5f 15  e8 f1 30 da 10 69 84 25  |="P.G._...0..i.%|
+00000070  05 d0 b5 f0 e8 69 72 4e  93 d3 7c 1a 01 6d 37 fb  |.....irN..|..m7.|
+00000080  cf e1 af f9 da dd 71 56  9b 08 24 14 03 03 00 01  |......qV..$.....|
+00000090  01 16 03 03 00 30 53 ab  b5 09 5a 36 36 df b1 ed  |.....0S...Z66...|
+000000a0  d2 69 5c 45 0b a9 02 8f  6d 25 d4 01 da 5f 27 ab  |.i\E....m%..._'.|
+000000b0  ba 89 6e ee d8 91 24 f8  5e ca 6e 4d 51 41 88 3c  |..n...$.^.nMQA.<|
+000000c0  f8 67 b4 fb d3 cb                                 |.g....|
 >>> Flow 4 (server to client)
 00000000  14 03 03 00 01 01 16 03  03 00 30 00 00 00 00 00  |..........0.....|
-00000010  00 00 00 c1 a2 65 c1 36  63 85 cd ca 5a eb 50 ab  |.....e.6c...Z.P.|
-00000020  bb ec 43 30 37 8f 71 b9  b7 2d 1b bb a2 88 fa d5  |..C07.q..-......|
-00000030  b4 a5 c5 4b 19 71 53 46  7d bb d0 17 03 03 00 30  |...K.qSF}......0|
-00000040  00 00 00 00 00 00 00 00  6a a1 3d c6 35 a0 58 c4  |........j.=.5.X.|
-00000050  ef 12 f2 59 1e 02 42 33  42 5f fe 87 a2 1a ce b7  |...Y..B3B_......|
-00000060  0d d2 36 7c 7f 1a 4c 79  1f 38 34 58 b3 05 fb 96  |..6|..Ly.84X....|
-00000070  15 03 03 00 20 00 00 00  00 00 00 00 00 a1 89 42  |.... ..........B|
-00000080  bc 58 1f 2f 9b c4 d7 e2  d1 ce 1c c9 e0 a5 47 be  |.X./..........G.|
-00000090  63 0c a4 bf 26                                    |c...&|
+00000010  00 00 00 50 83 52 65 2d  6e 76 aa 8d 2d 46 06 12  |...P.Re-nv..-F..|
+00000020  1a e7 25 79 28 61 9e 2d  07 0b fb 3c 77 38 d8 b0  |..%y(a.-...<w8..|
+00000030  af ca 86 8a 51 07 4d 83  39 81 9b 17 03 03 00 30  |....Q.M.9......0|
+00000040  00 00 00 00 00 00 00 00  a1 ea 74 b2 7b fc 3f 9d  |..........t.{.?.|
+00000050  bc eb 9d 09 a2 56 4a ff  d4 fd 00 23 0b e6 69 62  |.....VJ....#..ib|
+00000060  0e 4c 82 43 3f 21 8f b8  fd 5c ce 37 6c 57 d2 98  |.L.C?!...\.7lW..|
+00000070  15 03 03 00 20 00 00 00  00 00 00 00 00 dc 47 cc  |.... .........G.|
+00000080  34 eb 9e 7f d0 8f 5a 32  e6 6d 76 15 18 cc 8d 21  |4.....Z2.mv....!|
+00000090  43 91 81 31 81                                    |C..1.|
diff --git a/src/crypto/tls/testdata/Server-TLSv12-RSA-AES b/src/crypto/tls/testdata/Server-TLSv12-RSA-AES
index 4ca860d..66155e7 100644
--- a/src/crypto/tls/testdata/Server-TLSv12-RSA-AES
+++ b/src/crypto/tls/testdata/Server-TLSv12-RSA-AES
@@ -1,10 +1,10 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 5a 01 00 00  56 03 03 be 9a 2f 46 66  |....Z...V..../Ff|
-00000010  a3 b3 10 62 63 b6 32 cb  de 1e eb 76 13 50 60 d0  |...bc.2....v.P`.|
-00000020  ee 40 a9 cd 50 ae d8 86  10 37 8b 00 00 04 00 2f  |. at ..P....7...../|
-00000030  00 ff 01 00 00 29 00 0d  00 20 00 1e 06 01 06 02  |.....)... ......|
-00000040  06 03 05 01 05 02 05 03  04 01 04 02 04 03 03 01  |................|
-00000050  03 02 03 03 02 01 02 02  02 03 00 0f 00 01 01     |...............|
+00000000  16 03 01 00 5b 01 00 00  57 03 03 5a ba 29 44 35  |....[...W..Z.)D5|
+00000010  c4 48 64 61 06 84 70 5c  b5 65 ad 01 9b b2 29 0d  |.Hda..p\.e....).|
+00000020  d1 46 17 3a 27 fb 92 d8  aa 21 aa 00 00 04 00 2f  |.F.:'....!...../|
+00000030  00 ff 02 01 00 00 29 00  0d 00 20 00 1e 06 01 06  |......)... .....|
+00000040  02 06 03 05 01 05 02 05  03 04 01 04 02 04 03 03  |................|
+00000050  01 03 02 03 03 02 01 02  02 02 03 00 0f 00 01 01  |................|
 >>> Flow 2 (server to client)
 00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -51,31 +51,31 @@
 000002a0  a4 c2 41 34 ac cc f6 ea  b0 ab 39 18 16 03 03 00  |..A4......9.....|
 000002b0  04 0e 00 00 00                                    |.....|
 >>> Flow 3 (client to server)
-00000000  16 03 03 00 86 10 00 00  82 00 80 61 b4 31 93 2b  |...........a.1.+|
-00000010  d5 e8 06 74 b1 f6 d6 5f  a3 92 78 b6 cf bf 7f ea  |...t..._..x.....|
-00000020  a2 07 1e 90 94 68 5b 19  ae d4 e3 11 78 96 58 fd  |.....h[.....x.X.|
-00000030  96 18 f2 09 58 dc 39 a1  d9 9e 83 f0 24 45 6e 6b  |....X.9.....$Enk|
-00000040  e6 5e e7 cb 94 42 00 10  64 d5 d2 bc 80 23 bd fe  |.^...B..d....#..|
-00000050  5c 3e 3a 80 ff 38 b8 dc  ff 25 ba b0 0a cc ef 94  |\>:..8...%......|
-00000060  a1 31 bd 04 93 91 86 6e  8b fd a1 9d 01 ee 91 a6  |.1.....n........|
-00000070  44 8b 21 55 52 67 3e b1  e4 6e bd 1f 07 85 e1 97  |D.!URg>..n......|
-00000080  7f 55 70 00 5f f4 4b e6  50 45 f7 14 03 03 00 01  |.Up._.K.PE......|
-00000090  01 16 03 03 00 40 71 ff  ab 6d 79 3c da dc 5b 34  |..... at q..my<..[4|
-000000a0  48 39 48 08 e3 29 cb 53  21 fd 67 93 0b f8 81 47  |H9H..).S!.g....G|
-000000b0  40 7f 23 50 5f 94 db 2b  7b 7e 9f 0b bf 38 59 d9  |@.#P_..+{~...8Y.|
-000000c0  6b 57 8f 1e 83 eb 93 2c  62 12 31 c6 f5 21 f2 22  |kW.....,b.1..!."|
-000000d0  7a 82 e9 e6 ec 38                                 |z....8|
+00000000  16 03 03 00 86 10 00 00  82 00 80 ad e8 09 aa 07  |................|
+00000010  c0 3c 8b 39 d2 a8 bd ca  59 eb cf 0a de 33 3e d2  |.<.9....Y....3>.|
+00000020  4f 76 1f 7a 96 50 b3 52  6b 04 9e 6f f1 06 2b 4a  |Ov.z.P.Rk..o..+J|
+00000030  7f 01 f2 51 a3 a7 1e f6  20 a7 27 4e 97 68 61 98  |...Q.... .'N.ha.|
+00000040  9f fd bd aa e8 e6 80 4d  9a 65 51 35 11 44 e4 2c  |.......M.eQ5.D.,|
+00000050  a2 47 33 d1 b6 b7 d5 40  c0 17 34 ff e2 12 8e 00  |.G3.... at ..4.....|
+00000060  41 e6 4f 3e 56 2f d9 30  6b d9 99 e3 9f ce 10 ba  |A.O>V/.0k.......|
+00000070  7c 95 3b 49 c9 5f 1e 97  37 90 e4 da 9a e0 01 5f  ||.;I._..7......_|
+00000080  b8 6f 95 19 40 0f ca 63  76 6b 2a 14 03 03 00 01  |.o.. at ..cvk*.....|
+00000090  01 16 03 03 00 40 86 cb  f5 69 1b ee 67 6e 3b be  |..... at ...i..gn;.|
+000000a0  e0 de 22 06 8c d4 f4 98  a6 45 1c 2f e5 f0 b4 25  |.."......E./...%|
+000000b0  f4 c0 87 7f e8 1c 2c 1d  20 52 50 fe dc a3 0c 22  |......,. RP...."|
+000000c0  b7 7f d3 9c 42 b8 23 d0  3e fd 93 be a2 50 28 dd  |....B.#.>....P(.|
+000000d0  79 f3 c6 90 c7 bb                                 |y.....|
 >>> Flow 4 (server to client)
 00000000  14 03 03 00 01 01 16 03  03 00 40 00 00 00 00 00  |.......... at .....|
-00000010  00 00 00 00 00 00 00 00  00 00 00 45 87 33 41 c1  |...........E.3A.|
-00000020  b8 e7 4c 11 1c 1b 7b 55  51 85 06 01 c1 b6 87 6b  |..L...{UQ......k|
-00000030  01 b3 56 c4 5a 37 ea b6  3a c4 b0 da 1b 5c 15 d4  |..V.Z7..:....\..|
-00000040  03 5a 57 e9 9a 56 16 a5  fa 77 1c 17 03 03 00 40  |.ZW..V...w.....@|
+00000010  00 00 00 00 00 00 00 00  00 00 00 70 e5 19 ef 25  |...........p...%|
+00000020  05 0b 02 79 2b 79 49 e6  2c ad c0 e7 03 b3 40 68  |...y+yI.,..... at h|
+00000030  67 98 31 7c 7e 85 86 a8  5c de 72 3f d1 59 12 20  |g.1|~...\.r?.Y. |
+00000040  87 95 44 57 64 35 03 f5  68 61 20 17 03 03 00 40  |..DWd5..ha ....@|
 00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000060  6f 2e 7c ba 3d 85 4c 7b  1f 13 a5 d6 97 e6 67 f4  |o.|.=.L{......g.|
-00000070  24 d5 a8 d4 26 41 64 0a  fd b3 2e a0 a2 7a 2b 54  |$...&Ad......z+T|
-00000080  a4 1d 6e fe 4c c4 73 e3  76 d0 3a 60 52 df b0 53  |..n.L.s.v.:`R..S|
+00000060  1b 17 7c bb 04 4f 31 7b  da 40 5e 93 64 97 4a 8d  |..|..O1{.@^.d.J.|
+00000070  98 cf 77 2d 01 53 37 53  2c 59 8f ca ac 65 ae f3  |..w-.S7S,Y...e..|
+00000080  f8 d4 ae 67 74 c8 72 21  67 51 9a 1b 71 f2 0e 04  |...gt.r!gQ..q...|
 00000090  15 03 03 00 30 00 00 00  00 00 00 00 00 00 00 00  |....0...........|
-000000a0  00 00 00 00 00 8b 0a 6d  14 3b 84 bc 7d c6 8d 9d  |.......m.;..}...|
-000000b0  d5 27 32 84 4b 14 75 42  0f aa 5e 88 ba fa a2 c7  |.'2.K.uB..^.....|
-000000c0  16 93 8a c4 fd                                    |.....|
+000000a0  00 00 00 00 00 fd 36 99  3d c7 44 1b 30 39 4a a7  |......6.=.D.09J.|
+000000b0  40 43 e3 01 2b 22 3d c6  8c a1 0d 73 d5 16 d2 25  |@C..+"=....s...%|
+000000c0  19 c8 d7 76 ee                                    |...v.|
diff --git a/src/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM b/src/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM
index 7a26ebd..a6e7a07 100644
--- a/src/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM
+++ b/src/crypto/tls/testdata/Server-TLSv12-RSA-AES-GCM
@@ -1,14 +1,13 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 9a 01 00 00  96 03 03 16 dc f8 f5 3a  |...............:|
-00000010  13 32 e6 1f bd f6 3c 66  b7 4c 67 17 ee b2 2a ba  |.2....<f.Lg...*.|
-00000020  68 5b 8e b1 7c 8f 71 d6  6c 30 e1 00 00 04 c0 2f  |h[..|.q.l0...../|
-00000030  00 ff 01 00 00 69 00 0b  00 04 03 00 01 02 00 0a  |.....i..........|
-00000040  00 34 00 32 00 0e 00 0d  00 19 00 0b 00 0c 00 18  |.4.2............|
-00000050  00 09 00 0a 00 16 00 17  00 08 00 06 00 07 00 14  |................|
-00000060  00 15 00 04 00 05 00 12  00 13 00 01 00 02 00 03  |................|
-00000070  00 0f 00 10 00 11 00 0d  00 20 00 1e 06 01 06 02  |......... ......|
-00000080  06 03 05 01 05 02 05 03  04 01 04 02 04 03 03 01  |................|
-00000090  03 02 03 03 02 01 02 02  02 03 00 0f 00 01 01     |...............|
+00000000  16 03 01 00 83 01 00 00  7f 03 03 19 c7 02 a0 bf  |................|
+00000010  5a fb c2 d4 f5 68 0a 19  0f 5e 3a 6b c5 88 17 0b  |Z....h...^:k....|
+00000020  35 ff df ee 06 32 ad 32  99 0e c9 00 00 04 c0 2f  |5....2.2......./|
+00000030  00 ff 02 01 00 00 51 00  0b 00 04 03 00 01 02 00  |......Q.........|
+00000040  0a 00 1c 00 1a 00 17 00  19 00 1c 00 1b 00 18 00  |................|
+00000050  1a 00 16 00 0e 00 0d 00  0b 00 0c 00 09 00 0a 00  |................|
+00000060  0d 00 20 00 1e 06 01 06  02 06 03 05 01 05 02 05  |.. .............|
+00000070  03 04 01 04 02 04 03 03  01 03 02 03 03 02 01 02  |................|
+00000080  02 02 03 00 0f 00 01 01                           |........|
 >>> Flow 2 (server to client)
 00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -57,31 +56,31 @@
 000002c0  51 88 35 75 71 b5 e5 54  5b 12 2e 8f 09 67 fd a7  |Q.5uq..T[....g..|
 000002d0  24 20 3e b2 56 1c ce 97  28 5e f8 2b 2d 4f 9e f1  |$ >.V...(^.+-O..|
 000002e0  07 9f 6c 4b 5b 83 56 e2  32 42 e9 58 b6 d7 49 a6  |..lK[.V.2B.X..I.|
-000002f0  b5 68 1a 41 03 56 6b dc  5a 89 05 01 00 80 40 b3  |.h.A.Vk.Z..... at .|
-00000300  66 ee 53 3c 80 f4 da d1  de e6 fe 50 c8 89 60 d5  |f.S<.......P..`.|
-00000310  e4 80 73 39 91 79 6c cf  89 bb a5 da e4 c7 e5 0d  |..s9.yl.........|
-00000320  13 a6 76 24 65 1a a2 b8  cb 95 c2 c6 9d 66 74 57  |..v$e........ftW|
-00000330  9e 90 4f 48 77 88 3a b4  f3 fa 88 ab 61 22 d3 40  |..OHw.:.....a".@|
-00000340  08 c4 0a 69 19 ed c3 ea  d8 15 79 12 d5 ac 8d af  |...i......y.....|
-00000350  41 7d 87 4b a9 ff f8 cb  24 55 88 38 34 11 a5 bd  |A}.K....$U.84...|
-00000360  c1 d6 e5 86 d5 64 b5 f2  df c8 03 f2 a2 6b ff f4  |.....d.......k..|
-00000370  a8 38 e0 18 04 d4 cd bd  e0 cc 63 fc 3f 8b 16 03  |.8........c.?...|
+000002f0  b5 68 1a 41 03 56 6b dc  5a 89 05 01 00 80 97 53  |.h.A.Vk.Z......S|
+00000300  cc 1f a2 55 e2 52 69 a6  b3 78 4f 7e 34 3e 37 e4  |...U.Ri..xO~4>7.|
+00000310  e0 bb 15 ff 96 f8 1d 9c  11 03 2c 68 ca 6d 2b 3c  |..........,h.m+<|
+00000320  b3 96 64 21 d6 3f 81 42  07 c0 1b 85 7e a9 65 54  |..d!.?.B....~.eT|
+00000330  23 89 33 c1 71 b9 29 72  47 8a 0e 71 75 20 d7 b6  |#.3.q.)rG..qu ..|
+00000340  9d c2 ac c1 a8 dc 6c 0e  7e 29 93 fc b2 68 83 2e  |......l.~)...h..|
+00000350  e1 fe e5 eb 54 d7 c3 30  f2 8f 9d 91 49 48 4f 84  |....T..0....IHO.|
+00000360  1a d5 47 75 27 bf c8 09  65 4a a8 7c 65 a0 d0 23  |..Gu'...eJ.|e..#|
+00000370  9f 26 d6 57 62 cb e1 06  64 90 16 73 1b d4 16 03  |.&.Wb...d..s....|
 00000380  03 00 04 0e 00 00 00                              |.......|
 >>> Flow 3 (client to server)
-00000000  16 03 03 00 46 10 00 00  42 41 04 de de ff 8c df  |....F...BA......|
-00000010  d8 4c 72 af 29 3c 4d e0  ed 0f 34 cc fd 2d 52 63  |.Lr.)<M...4..-Rc|
-00000020  94 e8 74 f1 0b 18 69 28  ed 1e f7 62 4e 4f 2c 14  |..t...i(...bNO,.|
-00000030  61 4b 9f 55 d8 70 59 8f  4b a8 ab c6 d2 cd aa 59  |aK.U.pY.K......Y|
-00000040  8a ef 9b b3 f6 ba 52 e5  51 bb a1 14 03 03 00 01  |......R.Q.......|
-00000050  01 16 03 03 00 28 44 1c  eb 89 59 bb ad fb 9f 3f  |.....(D...Y....?|
-00000060  56 06 54 ae 27 6d e4 47  3c 0c 60 30 db 0e d6 0e  |V.T.'m.G<.`0....|
-00000070  9d 0d a9 a0 e7 25 26 6e  99 d0 8f e0 1b 9d        |.....%&n......|
+00000000  16 03 03 00 46 10 00 00  42 41 04 1a 94 a7 1a 36  |....F...BA.....6|
+00000010  d1 ca ad d7 e8 64 03 84  b4 a6 9f dc 30 a2 a3 60  |.....d......0..`|
+00000020  a0 5a 1f a0 3d 8e d1 b8  96 75 37 ee a6 3f d6 ad  |.Z..=....u7..?..|
+00000030  93 b6 7d 58 99 53 04 4b  6e c6 7f 04 bf 60 f9 ba  |..}X.S.Kn....`..|
+00000040  e7 b8 04 73 10 77 ff 22  93 b2 7b 14 03 03 00 01  |...s.w."..{.....|
+00000050  01 16 03 03 00 28 29 6b  2b 14 21 a7 e4 84 c0 9d  |.....()k+.!.....|
+00000060  92 07 cd dd 0b eb c1 b0  76 06 71 48 46 93 b8 05  |........v.qHF...|
+00000070  1a 2b 53 14 da 34 ac 05  4c cc 4d 47 12 28        |.+S..4..L.MG.(|
 >>> Flow 4 (server to client)
 00000000  14 03 03 00 01 01 16 03  03 00 28 00 00 00 00 00  |..........(.....|
-00000010  00 00 00 92 90 01 f0 70  fa 57 2e 40 d3 4c ef 6a  |.......p.W. at .L.j|
-00000020  03 0c 56 65 f7 c0 3b d0  8a db 48 c9 ae 58 3e 7c  |..Ve..;...H..X>||
-00000030  d1 48 67 17 03 03 00 25  00 00 00 00 00 00 00 01  |.Hg....%........|
-00000040  9e 35 a0 13 73 da 3f 26  ff 1d 90 08 e9 cc 40 7e  |.5..s.?&......@~|
-00000050  82 f3 5e 6e b4 8e 5a 39  7f a4 09 60 b2 15 03 03  |..^n..Z9...`....|
-00000060  00 1a 00 00 00 00 00 00  00 02 04 95 9b 2d 17 1c  |.............-..|
-00000070  6a bc 26 f7 6c 8e f1 c0  0e 82 4a 44              |j.&.l.....JD|
+00000010  00 00 00 b9 c9 6f cb 58  df 1c a1 0a 79 4e fa 8f  |.....o.X....yN..|
+00000020  41 55 8a 0a f8 d1 83 88  28 fb 44 00 8a a5 11 39  |AU......(.D....9|
+00000030  5b d4 83 17 03 03 00 25  00 00 00 00 00 00 00 01  |[......%........|
+00000040  85 4f 2a 54 aa c0 ce 7b  1e 4e e4 64 56 57 68 5e  |.O*T...{.N.dVWh^|
+00000050  fa 41 67 8a da 9d f4 78  a6 c6 13 76 7c 15 03 03  |.Ag....x...v|...|
+00000060  00 1a 00 00 00 00 00 00  00 02 38 71 21 c6 82 bc  |..........8q!...|
+00000070  2e 37 14 1d 15 2f 74 9d  7c 99 d8 66              |.7.../t.|..f|
diff --git a/src/crypto/tls/testdata/Server-TLSv12-RSA-AES256-GCM-SHA384 b/src/crypto/tls/testdata/Server-TLSv12-RSA-AES256-GCM-SHA384
index d59645c..cc94ac7 100644
--- a/src/crypto/tls/testdata/Server-TLSv12-RSA-AES256-GCM-SHA384
+++ b/src/crypto/tls/testdata/Server-TLSv12-RSA-AES256-GCM-SHA384
@@ -1,14 +1,13 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 9a 01 00 00  96 03 03 5d 6b 2a ff 74  |...........]k*.t|
-00000010  88 f1 68 8d 1b eb c3 84  34 b5 19 0a 7d f1 9a 0f  |..h.....4...}...|
-00000020  4d c3 0a d7 98 b8 72 e0  73 e4 38 00 00 04 c0 30  |M.....r.s.8....0|
-00000030  00 ff 01 00 00 69 00 0b  00 04 03 00 01 02 00 0a  |.....i..........|
-00000040  00 34 00 32 00 0e 00 0d  00 19 00 0b 00 0c 00 18  |.4.2............|
-00000050  00 09 00 0a 00 16 00 17  00 08 00 06 00 07 00 14  |................|
-00000060  00 15 00 04 00 05 00 12  00 13 00 01 00 02 00 03  |................|
-00000070  00 0f 00 10 00 11 00 0d  00 20 00 1e 06 01 06 02  |......... ......|
-00000080  06 03 05 01 05 02 05 03  04 01 04 02 04 03 03 01  |................|
-00000090  03 02 03 03 02 01 02 02  02 03 00 0f 00 01 01     |...............|
+00000000  16 03 01 00 83 01 00 00  7f 03 03 55 9b 71 e2 46  |...........U.q.F|
+00000010  88 58 c4 16 6a 6e 14 3d  3a 5a f9 fe ec 68 71 24  |.X..jn.=:Z...hq$|
+00000020  d0 06 6f a1 56 8f d6 15  42 6b ba 00 00 04 c0 30  |..o.V...Bk.....0|
+00000030  00 ff 02 01 00 00 51 00  0b 00 04 03 00 01 02 00  |......Q.........|
+00000040  0a 00 1c 00 1a 00 17 00  19 00 1c 00 1b 00 18 00  |................|
+00000050  1a 00 16 00 0e 00 0d 00  0b 00 0c 00 09 00 0a 00  |................|
+00000060  0d 00 20 00 1e 06 01 06  02 06 03 05 01 05 02 05  |.. .............|
+00000070  03 04 01 04 02 04 03 03  01 03 02 03 03 02 01 02  |................|
+00000080  02 02 03 00 0f 00 01 01                           |........|
 >>> Flow 2 (server to client)
 00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -57,31 +56,31 @@
 000002c0  51 88 35 75 71 b5 e5 54  5b 12 2e 8f 09 67 fd a7  |Q.5uq..T[....g..|
 000002d0  24 20 3e b2 56 1c ce 97  28 5e f8 2b 2d 4f 9e f1  |$ >.V...(^.+-O..|
 000002e0  07 9f 6c 4b 5b 83 56 e2  32 42 e9 58 b6 d7 49 a6  |..lK[.V.2B.X..I.|
-000002f0  b5 68 1a 41 03 56 6b dc  5a 89 05 01 00 80 22 6b  |.h.A.Vk.Z....."k|
-00000300  87 4b f8 ba f2 09 91 ee  ce 81 67 d4 fd d8 b5 07  |.K........g.....|
-00000310  fe c3 88 96 ca e3 3a f0  87 cc ae 44 94 8e 8f 70  |......:....D...p|
-00000320  79 cd de a2 26 4e 17 45  d7 ea 0f 95 a6 c9 7b 17  |y...&N.E......{.|
-00000330  68 7c f5 e8 6c d5 87 6d  5a 7e 53 af 95 0c 42 91  |h|..l..mZ~S...B.|
-00000340  c0 07 18 75 fd 74 1c ad  ef df f8 41 b1 ad fc 36  |...u.t.....A...6|
-00000350  19 31 cf c8 3f 36 55 dd  54 ac 44 a9 3a d1 ae 23  |.1..?6U.T.D.:..#|
-00000360  0a 18 bf b7 6f c7 bc a6  70 50 5e 50 dd da ff 5b  |....o...pP^P...[|
-00000370  67 7d 0a f5 70 a0 8c 88  d9 38 d4 bf a9 c3 16 03  |g}..p....8......|
+000002f0  b5 68 1a 41 03 56 6b dc  5a 89 05 01 00 80 7f 44  |.h.A.Vk.Z......D|
+00000300  af 7b 21 01 6b f0 1c 75  d3 6b 28 99 68 e1 0e d3  |.{!.k..u.k(.h...|
+00000310  a8 cb 5a 2e 23 ad d7 92  73 46 5b 66 88 bd f1 d6  |..Z.#...sF[f....|
+00000320  5d 52 d1 07 53 88 9c 64  e3 ce 80 b3 39 7f 9e 2b  |]R..S..d....9..+|
+00000330  0a 02 a7 e1 3e 00 70 51  3b b4 52 d1 3c 4a e9 f7  |....>.pQ;.R.<J..|
+00000340  0f 85 fa ff d7 ba 96 fc  77 8e 66 8d c6 4c b8 c2  |........w.f..L..|
+00000350  a5 d3 ad 72 f0 8c ba d2  bf 1c 81 7b 4e d5 9e 80  |...r.......{N...|
+00000360  7e b2 90 a0 2f d6 ad c2  33 43 da 46 b0 22 40 ff  |~.../...3C.F."@.|
+00000370  df 95 b3 1e f1 97 b9 7b  61 3c 78 d9 ae cb 16 03  |.......{a<x.....|
 00000380  03 00 04 0e 00 00 00                              |.......|
 >>> Flow 3 (client to server)
-00000000  16 03 03 00 46 10 00 00  42 41 04 d0 f7 11 ae 9f  |....F...BA......|
-00000010  ec 2e ac 8e 97 6c 58 0e  57 32 8e ac fa 3e af 36  |.....lX.W2...>.6|
-00000020  22 e1 41 2b d3 d1 9c c2  1d 51 c0 e4 20 b3 4c 85  |".A+.....Q.. .L.|
-00000030  b8 bd f2 d1 c6 2f 7d 83  c7 43 d9 31 36 1a 83 ca  |...../}..C.16...|
-00000040  c6 89 f8 ba 8c d1 7e 99  04 6e 92 14 03 03 00 01  |......~..n......|
-00000050  01 16 03 03 00 28 32 67  c1 6e 5e 1e 4b 51 1b 70  |.....(2g.n^.KQ.p|
-00000060  54 b9 1d 69 79 38 bd fa  7c 6b 58 71 af 72 08 2d  |T..iy8..|kXq.r.-|
-00000070  55 df 24 be 5b 41 0a ef  0e 90 cf d9 62 81        |U.$.[A......b.|
+00000000  16 03 03 00 46 10 00 00  42 41 04 d8 85 85 d2 78  |....F...BA.....x|
+00000010  27 a5 0a bb 10 67 ec a9  d8 11 f0 ba b9 d7 21 39  |'....g........!9|
+00000020  ed c7 0a a0 a2 69 ab fb  9b 15 e0 d7 ec ca 97 c8  |.....i..........|
+00000030  c0 b2 66 0b 2c 68 37 ac  f0 34 fa 3a 07 dd f2 ae  |..f.,h7..4.:....|
+00000040  8e f6 e3 eb de 08 1f 56  e5 66 eb 14 03 03 00 01  |.......V.f......|
+00000050  01 16 03 03 00 28 f5 2d  89 00 0c 9d d9 0e 54 1b  |.....(.-......T.|
+00000060  71 84 4d c7 bb 98 36 8c  29 b6 06 d8 7b df d9 92  |q.M...6.)...{...|
+00000070  01 00 16 44 5e e3 db f3  8f b7 fa 43 0c f7        |...D^......C..|
 >>> Flow 4 (server to client)
 00000000  14 03 03 00 01 01 16 03  03 00 28 00 00 00 00 00  |..........(.....|
-00000010  00 00 00 87 2a 3e 09 54  54 c3 58 c0 5b 7b 91 00  |....*>.TT.X.[{..|
-00000020  c4 07 98 9e de 1f f8 04  bb d7 42 04 55 7d 18 a4  |..........B.U}..|
-00000030  41 7c a6 17 03 03 00 25  00 00 00 00 00 00 00 01  |A|.....%........|
-00000040  ab 23 05 51 b4 60 a2 77  01 58 be a6 9f 89 2b b5  |.#.Q.`.w.X....+.|
-00000050  77 6b 19 23 67 f7 89 f1  ef d6 1b f5 e7 15 03 03  |wk.#g...........|
-00000060  00 1a 00 00 00 00 00 00  00 02 8a bf f0 fb 9f 56  |...............V|
-00000070  36 f1 92 49 a9 e5 40 87  f9 87 9e 4d              |6..I.. at ....M|
+00000010  00 00 00 a4 82 dc d1 67  ed 17 ae 22 13 0d ac d2  |.......g..."....|
+00000020  f4 58 44 5b b4 c6 25 29  80 b6 bc 63 0e 67 22 6e  |.XD[..%)...c.g"n|
+00000030  18 92 48 17 03 03 00 25  00 00 00 00 00 00 00 01  |..H....%........|
+00000040  a0 fe 37 25 fb 4d 29 96  f9 01 67 19 d8 83 26 68  |..7%.M)...g...&h|
+00000050  d0 e8 58 2c ef 90 a3 b5  26 51 26 a9 28 15 03 03  |..X,....&Q&.(...|
+00000060  00 1a 00 00 00 00 00 00  00 02 91 4b d5 54 4a ef  |...........K.TJ.|
+00000070  22 88 ab b7 a2 bb 20 5a  b2 3e 7b 36              |"..... Z.>{6|
diff --git a/src/crypto/tls/testdata/Server-TLSv12-RSA-RC4 b/src/crypto/tls/testdata/Server-TLSv12-RSA-RC4
index 13163d6..c55f891 100644
--- a/src/crypto/tls/testdata/Server-TLSv12-RSA-RC4
+++ b/src/crypto/tls/testdata/Server-TLSv12-RSA-RC4
@@ -1,10 +1,10 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 5a 01 00 00  56 03 03 8a fe f5 09 70  |....Z...V......p|
-00000010  8e 6b e3 2b 12 ff d1 b2  ae 15 bf 47 0e ca 5c b5  |.k.+.......G..\.|
-00000020  bb 0e ad af e5 a6 7e 36  c5 a4 c3 00 00 04 00 05  |......~6........|
-00000030  00 ff 01 00 00 29 00 0d  00 20 00 1e 06 01 06 02  |.....)... ......|
-00000040  06 03 05 01 05 02 05 03  04 01 04 02 04 03 03 01  |................|
-00000050  03 02 03 03 02 01 02 02  02 03 00 0f 00 01 01     |...............|
+00000000  16 03 01 00 5b 01 00 00  57 03 03 ec 96 78 51 74  |....[...W....xQt|
+00000010  1b f2 21 ad f2 4f 50 aa  67 f1 20 e2 4f d3 4d 0e  |..!..OP.g. .O.M.|
+00000020  54 91 df 91 d8 81 e3 75  bb 20 c2 00 00 04 00 05  |T......u. ......|
+00000030  00 ff 02 01 00 00 29 00  0d 00 20 00 1e 06 01 06  |......)... .....|
+00000040  02 06 03 05 01 05 02 05  03 04 01 04 02 04 03 03  |................|
+00000050  01 03 02 03 03 02 01 02  02 02 03 00 0f 00 01 01  |................|
 >>> Flow 2 (server to client)
 00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -51,23 +51,23 @@
 000002a0  a4 c2 41 34 ac cc f6 ea  b0 ab 39 18 16 03 03 00  |..A4......9.....|
 000002b0  04 0e 00 00 00                                    |.....|
 >>> Flow 3 (client to server)
-00000000  16 03 03 00 86 10 00 00  82 00 80 1c f7 2c 18 38  |.............,.8|
-00000010  d9 41 b5 ab b7 35 2b 75  2d 66 ba c8 70 c2 19 1c  |.A...5+u-f..p...|
-00000020  f2 6d d9 a9 a8 40 8e b5  2c 75 99 06 a5 25 be 0d  |.m... at ..,u...%..|
-00000030  b4 b0 9b aa fc 6b 12 a5  b3 e7 02 60 aa 25 e9 7f  |.....k.....`.%..|
-00000040  6b f5 c4 7a 1d 16 a5 d1  76 cc d5 a1 18 68 91 c3  |k..z....v....h..|
-00000050  57 b8 10 f2 b8 81 f3 1b  74 ef 6c 37 3e 81 41 09  |W.......t.l7>.A.|
-00000060  2a c5 15 e6 cc bb 74 4c  01 7a b9 82 5c e2 7f b7  |*.....tL.z..\...|
-00000070  ac 2d 76 30 18 30 c2 19  8c 5f f2 80 41 89 bb 47  |.-v0.0..._..A..G|
-00000080  28 3d 61 cc 3c 06 a8 76  93 57 71 14 03 03 00 01  |(=a.<..v.Wq.....|
-00000090  01 16 03 03 00 24 46 34  1f cc eb 53 c7 d2 04 28  |.....$F4...S...(|
-000000a0  b6 3d 3f 39 06 70 56 b7  db eb 53 9c 66 c3 45 9f  |.=?9.pV...S.f.E.|
-000000b0  69 ca 58 8f e7 ba a7 e6  5a 97                    |i.X.....Z.|
+00000000  16 03 03 00 86 10 00 00  82 00 80 05 4b 04 74 76  |............K.tv|
+00000010  73 3a 92 04 4d 8b 3b 59  c2 43 c5 f4 07 e8 bc a3  |s:..M.;Y.C......|
+00000020  62 44 b7 80 9f 8f bc 43  8a 67 09 64 a7 93 9f f9  |bD.....C.g.d....|
+00000030  2c 55 03 4b e5 87 9d 18  a2 c3 48 4f 02 6e e0 23  |,U.K......HO.n.#|
+00000040  0b 2f 57 81 e4 38 50 11  d6 b1 71 4f c2 e5 a4 03  |./W..8P...qO....|
+00000050  34 a4 eb a1 42 47 79 05  bc 7b b8 26 5b c1 f9 82  |4...BGy..{.&[...|
+00000060  fc 58 49 eb 04 52 fe 57  3c ed 5c 2b d8 fe 49 d7  |.XI..R.W<.\+..I.|
+00000070  d2 2e 6c e8 74 74 0d 87  b3 f6 2d f0 ff 03 f0 2d  |..l.tt....-....-|
+00000080  c8 a2 20 89 3f 3f 11 e1  fb 93 85 14 03 03 00 01  |.. .??..........|
+00000090  01 16 03 03 00 24 9a 81  c0 9e 76 b6 3d 78 37 8e  |.....$....v.=x7.|
+000000a0  ab 33 48 93 bb 0d f4 86  3c ff 72 28 10 35 c2 10  |.3H.....<.r(.5..|
+000000b0  f0 a0 ff 0c 20 f3 c4 29  83 a6                    |.... ..)..|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 24 78 c3 02 89 60  |..........$x...`|
-00000010  e7 72 9f 51 87 14 ca 2e  0d 79 98 eb 1e 39 62 f9  |.r.Q.....y...9b.|
-00000020  fc a5 c9 2c f8 0c 04 16  60 70 90 b7 31 f8 30 17  |...,....`p..1.0.|
-00000030  03 03 00 21 6a b7 24 73  a7 0d 17 04 d7 54 a8 ea  |...!j.$s.....T..|
-00000040  28 4e f2 0a ef 87 d5 a9  b8 84 81 46 8e 97 d1 ae  |(N.........F....|
-00000050  3c cc b1 6b 72 15 03 03  00 16 1a bb 2f df ae 3e  |<..kr......./..>|
-00000060  a7 89 69 3e 35 f2 f6 cd  35 60 29 3a 6f be 32 0d  |..i>5...5`):o.2.|
+00000000  14 03 03 00 01 01 16 03  03 00 24 93 15 62 c5 2b  |..........$..b.+|
+00000010  4f 8a d7 0f 70 1f 9d 11  fc 8f 9a a9 b7 d7 44 50  |O...p.........DP|
+00000020  6e 0e 5b d7 3b de 15 7d  17 35 31 42 1f a4 40 17  |n.[.;..}.51B.. at .|
+00000030  03 03 00 21 a9 ca 73 e9  ce 2d 21 ef 7d bc 40 91  |...!..s..-!.}. at .|
+00000040  41 c9 53 62 af 09 8e b4  37 0f fa ab b7 76 8f 5b  |A.Sb....7....v.[|
+00000050  7d 0f 04 48 49 15 03 03  00 16 76 b1 d7 91 88 6f  |}..HI.....v....o|
+00000060  b4 e7 a4 f1 d2 c2 ac 50  db 31 ae 5c f7 53 a1 68  |.......P.1.\.S.h|
diff --git a/src/crypto/tls/testdata/Server-TLSv12-Resume b/src/crypto/tls/testdata/Server-TLSv12-Resume
index 8cacd21..521376c 100644
--- a/src/crypto/tls/testdata/Server-TLSv12-Resume
+++ b/src/crypto/tls/testdata/Server-TLSv12-Resume
@@ -1,37 +1,37 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 f6 01 00 00  f2 03 03 53 1e 13 2e bd  |...........S....|
-00000010  ad 66 fd 77 1a ad 5f 4d  cb bd 2e ca b5 c2 45 1d  |.f.w.._M......E.|
-00000020  7c 83 9d 62 3e 39 9c ce  78 99 e7 20 b4 06 b0 ec  ||..b>9..x.. ....|
-00000030  cf b7 52 6e 38 10 31 37  b2 e6 58 0f fa e3 b0 cb  |..Rn8.17..X.....|
-00000040  20 a4 d2 4b f3 7d 92 e6  7e 13 37 08 00 04 00 05  | ..K.}..~.7.....|
-00000050  00 ff 01 00 00 a5 00 23  00 78 50 46 ad c1 db a8  |.......#.xPF....|
-00000060  38 86 7b 2b bb fd d0 c3  42 3e 00 00 00 00 00 00  |8.{+....B>......|
-00000070  00 00 00 00 00 00 00 00  00 00 94 6f 2c b5 83 61  |...........o,..a|
-00000080  c4 74 90 94 e5 6c fd 70  64 57 3a 25 78 bf 9f a0  |.t...l.pdW:%x...|
-00000090  7c 51 bc 2a 69 1e b3 fd  71 34 b7 9a ef cb 49 37  ||Q.*i...q4....I7|
-000000a0  f8 5d 5e 7c cf 6d fc 13  c1 52 79 8e ed c3 84 01  |.]^|.m...Ry.....|
-000000b0  33 94 10 65 34 64 5e b4  9c 07 46 5b 9e d7 5e 55  |3..e4d^...F[..^U|
-000000c0  df fd c0 e9 d2 e8 d3 c6  42 18 ef a5 6c be e8 d2  |........B...l...|
-000000d0  49 c6 00 0d 00 20 00 1e  06 01 06 02 06 03 05 01  |I.... ..........|
-000000e0  05 02 05 03 04 01 04 02  04 03 03 01 03 02 03 03  |................|
-000000f0  02 01 02 02 02 03 00 0f  00 01 01                 |...........|
+00000000  16 03 01 00 f7 01 00 00  f3 03 03 35 70 0b ed 1c  |...........5p...|
+00000010  83 57 b1 7b 0a 47 ce d4  07 3a 49 96 93 4c a1 83  |.W.{.G...:I..L..|
+00000020  4b ab b7 ab 7d b0 14 be  dd 91 92 20 09 34 b7 de  |K...}...... .4..|
+00000030  bd 43 e8 cd 8e f3 43 aa  04 64 8f 0a 55 a6 58 ed  |.C....C..d..U.X.|
+00000040  31 8b 3d 4c 84 4f 2c 6d  b0 b1 75 6f 00 04 00 05  |1.=L.O,m..uo....|
+00000050  00 ff 02 01 00 00 a5 00  23 00 78 50 46 ad c1 db  |........#.xPF...|
+00000060  a8 38 86 7b 2b bb fd d0  c3 42 3e 00 00 00 00 00  |.8.{+....B>.....|
+00000070  00 00 00 00 00 00 00 00  00 00 00 94 6f 2c b5 83  |............o,..|
+00000080  61 4d 51 5f 33 46 48 fe  9e e9 83 f4 b1 aa c9 b1  |aMQ_3FH.........|
+00000090  61 2a b2 9d 0f 17 c4 09  f6 26 7a 75 f1 19 99 db  |a*.......&zu....|
+000000a0  36 d8 32 f0 94 61 4f 8f  ed 80 33 51 f3 c6 15 84  |6.2..aO...3Q....|
+000000b0  6b 33 94 c8 4f 84 b7 7c  27 6d 8f fe 41 8e b2 92  |k3..O..|'m..A...|
+000000c0  ca 80 e8 6c ba 75 77 f5  3a 87 17 ae f8 b9 6b 10  |...l.uw.:.....k.|
+000000d0  f9 85 da 00 0d 00 20 00  1e 06 01 06 02 06 03 05  |...... .........|
+000000e0  01 05 02 05 03 04 01 04  02 04 03 03 01 03 02 03  |................|
+000000f0  03 02 01 02 02 02 03 00  0f 00 01 01              |............|
 >>> Flow 2 (server to client)
 00000000  16 03 03 00 51 02 00 00  4d 03 03 00 00 00 00 00  |....Q...M.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
-00000020  00 00 00 00 00 00 00 00  00 00 00 20 b4 06 b0 ec  |........... ....|
-00000030  cf b7 52 6e 38 10 31 37  b2 e6 58 0f fa e3 b0 cb  |..Rn8.17..X.....|
-00000040  20 a4 d2 4b f3 7d 92 e6  7e 13 37 08 00 05 00 00  | ..K.}..~.7.....|
+00000020  00 00 00 00 00 00 00 00  00 00 00 20 09 34 b7 de  |........... .4..|
+00000030  bd 43 e8 cd 8e f3 43 aa  04 64 8f 0a 55 a6 58 ed  |.C....C..d..U.X.|
+00000040  31 8b 3d 4c 84 4f 2c 6d  b0 b1 75 6f 00 05 00 00  |1.=L.O,m..uo....|
 00000050  05 ff 01 00 01 00 14 03  03 00 01 01 16 03 03 00  |................|
-00000060  24 24 31 13 8c 45 4f 8a  fc 71 50 94 b0 6f 02 5e  |$$1..EO..qP..o.^|
-00000070  da d3 a3 13 8b c8 53 fb  54 8d ef 90 f7 55 b1 be  |......S.T....U..|
-00000080  37 30 05 e5 5d                                    |70..]|
+00000060  24 18 67 37 5a c6 ea 3f  5f 06 2d c3 f1 2a ff d3  |$.g7Z..?_.-..*..|
+00000070  45 ce fe 38 1a e6 39 25  e7 e5 01 4d 6e fd 23 af  |E..8..9%...Mn.#.|
+00000080  dc 67 1b 1d e2                                    |.g...|
 >>> Flow 3 (client to server)
-00000000  14 03 03 00 01 01 16 03  03 00 24 ed dd e4 a5 09  |..........$.....|
-00000010  0d 7c cb e4 90 9c a1 1c  21 f4 13 bd 45 8f f4 d8  |.|......!...E...|
-00000020  7e e2 89 7a 0d f4 75 99  66 8c 05 a3 1a e2 2b     |~..z..u.f.....+|
+00000000  14 03 03 00 01 01 16 03  03 00 24 b5 75 e6 1d 1d  |..........$.u...|
+00000010  cb 2c 5d 9f d1 07 de 23  11 84 c2 59 50 55 72 27  |.,]....#...YPUr'|
+00000020  f2 5e 34 e2 c1 53 bf 21  5f f4 c4 2c f1 e1 7a     |.^4..S.!_..,..z|
 >>> Flow 4 (server to client)
-00000000  17 03 03 00 21 69 fa 9e  98 fb 7a 95 b1 8e e5 74  |....!i....z....t|
-00000010  03 02 d7 3d 69 c4 b8 c9  5b 49 e3 30 32 e3 c5 6a  |...=i...[I.02..j|
-00000020  fa 20 98 bd 01 ed 15 03  03 00 16 c9 b1 20 1f 30  |. ........... .0|
-00000030  c1 2f 15 75 cd 82 45 de  1a 81 cd dc 10 05 1c 45  |./.u..E........E|
-00000040  dc                                                |.|
+00000000  17 03 03 00 21 93 92 dd  07 a3 8f 3d 34 6d b8 94  |....!......=4m..|
+00000010  a7 6f 18 27 e7 cd 30 0a  08 4f b6 9b cb 43 93 27  |.o.'..0..O...C.'|
+00000020  b6 8b 83 ae d6 8a 15 03  03 00 16 68 a1 a4 f8 66  |...........h...f|
+00000030  8a c0 e7 d3 97 83 cb 35  94 84 7a e6 47 3c 97 8c  |.......5..z.G<..|
+00000040  69                                                |i|
diff --git a/src/crypto/tls/testdata/Server-TLSv12-ResumeDisabled b/src/crypto/tls/testdata/Server-TLSv12-ResumeDisabled
index 912c178..c3cd2ef 100644
--- a/src/crypto/tls/testdata/Server-TLSv12-ResumeDisabled
+++ b/src/crypto/tls/testdata/Server-TLSv12-ResumeDisabled
@@ -1,20 +1,20 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 f6 01 00 00  f2 03 03 aa 0c c2 75 42  |..............uB|
-00000010  62 2a 1d 14 a0 cc a1 e4  a7 19 77 50 80 2b f8 05  |b*........wP.+..|
-00000020  0b fa 60 3a a7 a7 84 d3  e1 68 26 20 68 97 0c ae  |..`:.....h& h...|
-00000030  7b 1d bc 13 14 a8 f6 c1  e1 96 1f 54 18 2c cb 99  |{..........T.,..|
-00000040  17 7d be 45 6a 39 53 c6  50 c7 8c 75 00 04 00 05  |.}.Ej9S.P..u....|
-00000050  00 ff 01 00 00 a5 00 23  00 78 50 46 ad c1 db a8  |.......#.xPF....|
-00000060  38 86 7b 2b bb fd d0 c3  42 3e 00 00 00 00 00 00  |8.{+....B>......|
-00000070  00 00 00 00 00 00 00 00  00 00 94 6f 2c b5 83 61  |...........o,..a|
-00000080  bd 50 da 49 7f 8b 8f 58  57 00 a1 11 0d 4a 9d 8a  |.P.I...XW....J..|
-00000090  39 dd 85 23 c0 eb 9d 1a  45 93 92 e7 af 15 a3 a4  |9..#....E.......|
-000000a0  48 da f9 a4 d8 8e cb 6c  3d 44 77 f9 c4 83 89 85  |H......l=Dw.....|
-000000b0  33 94 c1 c6 20 9a 73 44  83 89 5e 59 ee 05 c6 7e  |3... .sD..^Y...~|
-000000c0  8d e9 7d 7b f8 84 46 b6  7d 43 ec f1 af 1f 0f 35  |..}{..F.}C.....5|
-000000d0  b4 1c 00 0d 00 20 00 1e  06 01 06 02 06 03 05 01  |..... ..........|
-000000e0  05 02 05 03 04 01 04 02  04 03 03 01 03 02 03 03  |................|
-000000f0  02 01 02 02 02 03 00 0f  00 01 01                 |...........|
+00000000  16 03 01 00 f7 01 00 00  f3 03 03 2b 89 3f 02 47  |...........+.?.G|
+00000010  f6 14 64 3b 64 08 84 6e  9c e1 c9 4d 4f 30 92 06  |..d;d..n...MO0..|
+00000020  d1 19 58 5d 93 30 41 4d  a6 2c f6 20 53 3c e7 f4  |..X].0AM.,. S<..|
+00000030  23 7e 59 b1 32 c4 2d db  0b 6f ab 64 4a 72 c9 31  |#~Y.2.-..o.dJr.1|
+00000040  d9 b9 38 a8 b4 4e 0c 39  f8 f4 61 7a 00 04 00 05  |..8..N.9..az....|
+00000050  00 ff 02 01 00 00 a5 00  23 00 78 50 46 ad c1 db  |........#.xPF...|
+00000060  a8 38 86 7b 2b bb fd d0  c3 42 3e 00 00 00 00 00  |.8.{+....B>.....|
+00000070  00 00 00 00 00 00 00 00  00 00 00 94 6f 2c b5 83  |............o,..|
+00000080  61 01 55 65 2a 95 38 d4  d5 5f 41 c1 45 e4 f8 4b  |a.Ue*.8.._A.E..K|
+00000090  3b 08 44 df 0b 72 11 93  cd d4 ff 36 0f 4f 3a a9  |;.D..r.....6.O:.|
+000000a0  4c 9f ab c7 ae 88 97 bc  1e ff 2d 27 39 a8 82 84  |L.........-'9...|
+000000b0  ae 33 94 48 8b 1c 58 9d  60 65 3c 3f 17 9d 6a eb  |.3.H..X.`e<?..j.|
+000000c0  50 cd 65 04 bb c7 28 c8  0d 57 44 52 e0 17 de df  |P.e...(..WDR....|
+000000d0  f3 13 b1 00 0d 00 20 00  1e 06 01 06 02 06 03 05  |...... .........|
+000000e0  01 05 02 05 03 04 01 04  02 04 03 03 01 03 02 03  |................|
+000000f0  03 02 01 02 02 02 03 00  0f 00 01 01              |............|
 >>> Flow 2 (server to client)
 00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -61,23 +61,23 @@
 000002a0  a4 c2 41 34 ac cc f6 ea  b0 ab 39 18 16 03 03 00  |..A4......9.....|
 000002b0  04 0e 00 00 00                                    |.....|
 >>> Flow 3 (client to server)
-00000000  16 03 03 00 86 10 00 00  82 00 80 ac 10 32 61 b0  |.............2a.|
-00000010  03 e3 1e 2f 89 91 5f d6  4c e0 82 a7 82 41 67 d3  |.../.._.L....Ag.|
-00000020  5f b3 68 2d c0 d1 6f 03  7b 79 94 cc bb 35 6c 8a  |_.h-..o.{y...5l.|
-00000030  bf 1c 83 ff 88 91 5c 04  64 cc a0 df 0b 08 8c 0f  |......\.d.......|
-00000040  72 13 17 9f 27 14 8d 9a  af 17 70 41 44 9f 89 8c  |r...'.....pAD...|
-00000050  fa e4 66 33 4d bd 2f 93  2a 1e 85 a1 af 9e 27 12  |..f3M./.*.....'.|
-00000060  59 a4 13 67 56 85 c2 86  47 f8 c5 49 8f a4 c2 6e  |Y..gV...G..I...n|
-00000070  04 78 0f 11 2b fb 7e 34  b8 eb 25 93 71 ab 9f f5  |.x..+.~4..%.q...|
-00000080  93 df 2b c3 1e 9e 6a 9e  e3 57 aa 14 03 03 00 01  |..+...j..W......|
-00000090  01 16 03 03 00 24 e0 13  15 10 4c db f3 b6 de d2  |.....$....L.....|
-000000a0  68 02 f5 ea 1f 8e 58 70  4a 5a 78 d9 66 c5 74 77  |h.....XpJZx.f.tw|
-000000b0  a0 3a ec d8 b7 42 e3 a5  d4 62                    |.:...B...b|
+00000000  16 03 03 00 86 10 00 00  82 00 80 ab d9 61 5e d3  |.............a^.|
+00000010  87 d7 eb 21 12 6f f9 61  dd 8b de 76 d7 14 70 2f  |...!.o.a...v..p/|
+00000020  9c 0f 3c d4 4c 77 41 e2  ac 73 18 c3 0f 66 f2 b1  |..<.LwA..s...f..|
+00000030  fd 4b 1e d9 cb 5c 94 16  4d c2 98 f9 0d 55 f7 79  |.K...\..M....U.y|
+00000040  e2 8d 2c 87 96 e7 10 fb  78 fb ce 27 5d 9f ac 97  |..,.....x..']...|
+00000050  d6 54 6f 0c 78 dc 7b 2e  49 4c e2 42 24 b9 3d de  |.To.x.{.IL.B$.=.|
+00000060  89 5f 1a 40 54 33 11 96  89 6f 59 25 5e 89 60 40  |._. at T3...oY%^.`@|
+00000070  83 8c 0e 92 0e 7d 68 9d  17 74 ba 39 e8 6f e3 43  |.....}h..t.9.o.C|
+00000080  44 80 e6 62 4b 35 43 21  5b eb 32 14 03 03 00 01  |D..bK5C![.2.....|
+00000090  01 16 03 03 00 24 77 1a  b5 2c 88 d7 a6 83 f5 30  |.....$w..,.....0|
+000000a0  a0 c3 b4 45 a6 af 9b c2  ac 55 cf 73 4f a0 ba e5  |...E.....U.sO...|
+000000b0  2a be 9c 97 d2 d2 0b e9  95 0e                    |*.........|
 >>> Flow 4 (server to client)
-00000000  14 03 03 00 01 01 16 03  03 00 24 e9 c1 1f 5b e6  |..........$...[.|
-00000010  c1 d5 8a 14 eb c6 41 c1  77 6d 59 83 b6 95 34 f9  |......A.wmY...4.|
-00000020  7b a1 c9 9d 58 a5 b2 1b  33 6e 04 ab e0 03 61 17  |{...X...3n....a.|
-00000030  03 03 00 21 67 8b 55 43  d7 a7 05 c9 1f a0 d3 65  |...!g.UC.......e|
-00000040  30 36 07 8f d8 52 7e 40  79 31 2e 1c 1a c2 a6 fe  |06...R~@y1......|
-00000050  e0 39 4d a0 5d 15 03 03  00 16 b8 94 fb 17 e5 1d  |.9M.]...........|
-00000060  2e 28 95 cf 02 85 8e 11  2e 16 b1 53 72 aa a4 94  |.(.........Sr...|
+00000000  14 03 03 00 01 01 16 03  03 00 24 a9 ae 0c a5 ed  |..........$.....|
+00000010  51 10 d9 14 71 41 40 bd  be f5 44 98 11 2f d8 0f  |Q...qA at ...D../..|
+00000020  4d 42 bf 28 53 bf 02 7e  d6 16 92 7f dd 03 ec 17  |MB.(S..~........|
+00000030  03 03 00 21 46 c2 68 a1  6a 35 67 e7 7d 62 71 43  |...!F.h.j5g.}bqC|
+00000040  6b ea d6 fc 22 fc 2d ad  45 d6 6d 98 9e e5 88 a0  |k...".-.E.m.....|
+00000050  ac 80 f7 6f 05 15 03 03  00 16 0c ae f4 fc 0e 09  |...o............|
+00000060  0b 09 73 69 83 0d 00 89  39 ff f6 20 4e 2b 88 3d  |..si....9.. N+.=|
diff --git a/src/crypto/tls/testdata/Server-TLSv12-SNI b/src/crypto/tls/testdata/Server-TLSv12-SNI
index aee5742..ae52ac2 100644
--- a/src/crypto/tls/testdata/Server-TLSv12-SNI
+++ b/src/crypto/tls/testdata/Server-TLSv12-SNI
@@ -1,12 +1,12 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 6e 01 00 00  6a 03 03 be 99 22 5c d2  |....n...j...."\.|
-00000010  02 c7 a6 be f3 33 7a d4  76 1f cf 1e 39 0b 25 7c  |.....3z.v...9.%||
-00000020  32 70 e4 8c 49 a6 87 b9  c1 2f 6d 00 00 04 00 2f  |2p..I..../m..../|
-00000030  00 ff 01 00 00 3d 00 00  00 10 00 0e 00 00 0b 73  |.....=.........s|
-00000040  6e 69 74 65 73 74 2e 63  6f 6d 00 0d 00 20 00 1e  |nitest.com... ..|
-00000050  06 01 06 02 06 03 05 01  05 02 05 03 04 01 04 02  |................|
-00000060  04 03 03 01 03 02 03 03  02 01 02 02 02 03 00 0f  |................|
-00000070  00 01 01                                          |...|
+00000000  16 03 01 00 6f 01 00 00  6b 03 03 07 0f b6 b9 cc  |....o...k.......|
+00000010  db 23 57 92 d0 9b 37 72  9d ad 9a 0d 17 6b dd b8  |.#W...7r.....k..|
+00000020  81 b7 7c 54 dd 68 fe 4e  28 00 39 00 00 04 00 2f  |..|T.h.N(.9..../|
+00000030  00 ff 02 01 00 00 3d 00  00 00 10 00 0e 00 00 0b  |......=.........|
+00000040  73 6e 69 74 65 73 74 2e  63 6f 6d 00 0d 00 20 00  |snitest.com... .|
+00000050  1e 06 01 06 02 06 03 05  01 05 02 05 03 04 01 04  |................|
+00000060  02 04 03 03 01 03 02 03  03 02 01 02 02 02 03 00  |................|
+00000070  0f 00 01 01                                       |....|
 >>> Flow 2 (server to client)
 00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -46,19 +46,19 @@
 00000230  2c 65 25 d6 52 b6 e3 18  45 bd cc 16 03 03 00 04  |,e%.R...E.......|
 00000240  0e 00 00 00                                       |....|
 >>> Flow 3 (client to server)
-00000000  16 03 03 00 86 10 00 00  82 00 80 6b 03 31 ca a0  |...........k.1..|
-00000010  62 a2 53 11 ce 13 d9 f6  e7 d4 ec 2e c3 0a 38 56  |b.S...........8V|
-00000020  23 22 67 23 c8 8d 16 b4  3c 0b 26 9f 1c 2d 65 13  |#"g#....<.&..-e.|
-00000030  c3 cb 65 69 b0 47 ff 87  e8 02 56 c4 77 8a 40 29  |..ei.G....V.w.@)|
-00000040  82 62 8b 06 61 0a 1c b3  c7 29 b6 aa c9 96 37 18  |.b..a....)....7.|
-00000050  d0 60 66 63 9b 62 4b 30  cc 03 9c 37 05 c6 32 98  |.`fc.bK0...7..2.|
-00000060  cb a0 e2 e4 38 60 d4 93  99 9a fc 03 66 fb b6 ef  |....8`......f...|
-00000070  8a 1e bb ca 13 c5 d9 7a  7c 3b 50 dc d0 ad 00 b5  |.......z|;P.....|
-00000080  2c dc 1a ef c4 5c af d3  4e cd e6 14 03 03 00 01  |,....\..N.......|
-00000090  01 16 03 03 00 40 42 31  83 8a 2c 86 22 c5 df e5  |..... at B1..,."...|
-000000a0  f2 0b f8 0c 2f 1e 82 f4  69 fe 1d bd 4c db f1 80  |..../...i...L...|
-000000b0  68 30 b7 e3 60 76 b3 f1  52 ae d6 e7 b3 cb 4a e0  |h0..`v..R.....J.|
-000000c0  27 0a c1 1a 72 ed 71 ab  0a fc 10 d9 5e 4d fd 10  |'...r.q.....^M..|
-000000d0  04 92 39 78 be 23                                 |..9x.#|
+00000000  16 03 03 00 86 10 00 00  82 00 80 72 6a 6f a8 c9  |...........rjo..|
+00000010  3e 4c 33 da 92 23 97 68  fc 4e ca 74 77 98 f3 88  |>L3..#.h.N.tw...|
+00000020  ba a0 55 b6 a0 6f ff c8  db 2b 90 17 1f 45 bc 26  |..U..o...+...E.&|
+00000030  62 6e b9 91 96 b9 03 5d  eb f2 a2 59 87 7b 81 4a  |bn.....]...Y.{.J|
+00000040  0c f9 e2 23 60 e3 c7 4d  53 4f 3a 1f c5 5f dd 15  |...#`..MSO:.._..|
+00000050  cc 78 c5 21 fd 33 02 68  77 7c 8d 5f e8 80 a7 84  |.x.!.3.hw|._....|
+00000060  a7 2c b3 1f 64 df 8a 63  e9 b3 24 02 c1 6a 94 bd  |.,..d..c..$..j..|
+00000070  a1 62 e5 32 e5 d9 83 25  0d 0f 1a 02 90 8a cd 79  |.b.2...%.......y|
+00000080  1c bd 4a c2 f4 5d a0 24  c6 c1 ae 14 03 03 00 01  |..J..].$........|
+00000090  01 16 03 03 00 40 1f 1a  17 47 15 25 5b 3d 5f e5  |..... at ...G.%[=_.|
+000000a0  f4 d9 64 47 5f 80 09 f7  dd 5a ff 58 19 08 b5 db  |..dG_....Z.X....|
+000000b0  38 88 a4 44 07 01 fb 80  1d 89 b2 d4 af 95 80 b3  |8..D............|
+000000c0  75 13 82 0e 24 12 1d 5c  29 72 1d 21 d4 69 16 e0  |u...$..\)r.!.i..|
+000000d0  b5 4b 46 62 fe f7                                 |.KFb..|
 >>> Flow 4 (server to client)
 00000000  15 03 03 00 02 02 14                              |.......|
diff --git a/src/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificate b/src/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificate
index 40d3714..7ac8dc9 100644
--- a/src/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificate
+++ b/src/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificate
@@ -1,12 +1,12 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 6e 01 00 00  6a 03 03 23 de 75 da 8e  |....n...j..#.u..|
-00000010  0a 4b 7b e4 cb 34 14 83  be d1 6a 95 25 86 f8 91  |.K{..4....j.%...|
-00000020  d8 bb ac 82 9e 19 d6 9f  52 26 f6 00 00 04 00 2f  |........R&...../|
-00000030  00 ff 01 00 00 3d 00 00  00 10 00 0e 00 00 0b 73  |.....=.........s|
-00000040  6e 69 74 65 73 74 2e 63  6f 6d 00 0d 00 20 00 1e  |nitest.com... ..|
-00000050  06 01 06 02 06 03 05 01  05 02 05 03 04 01 04 02  |................|
-00000060  04 03 03 01 03 02 03 03  02 01 02 02 02 03 00 0f  |................|
-00000070  00 01 01                                          |...|
+00000000  16 03 01 00 6f 01 00 00  6b 03 03 fe d6 ce b5 1b  |....o...k.......|
+00000010  1c 50 0c db 9c 35 5d 0e  f2 ee 57 3f 65 83 9f 28  |.P...5]...W?e..(|
+00000020  96 50 1c e0 7f 95 f9 17  39 4f c3 00 00 04 00 2f  |.P......9O...../|
+00000030  00 ff 02 01 00 00 3d 00  00 00 10 00 0e 00 00 0b  |......=.........|
+00000040  73 6e 69 74 65 73 74 2e  63 6f 6d 00 0d 00 20 00  |snitest.com... .|
+00000050  1e 06 01 06 02 06 03 05  01 05 02 05 03 04 01 04  |................|
+00000060  02 04 03 03 01 03 02 03  03 02 01 02 02 02 03 00  |................|
+00000070  0f 00 01 01                                       |....|
 >>> Flow 2 (server to client)
 00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -46,19 +46,19 @@
 00000230  2c 65 25 d6 52 b6 e3 18  45 bd cc 16 03 03 00 04  |,e%.R...E.......|
 00000240  0e 00 00 00                                       |....|
 >>> Flow 3 (client to server)
-00000000  16 03 03 00 86 10 00 00  82 00 80 a2 99 61 c5 90  |.............a..|
-00000010  47 1a e7 47 56 51 59 e4  6e ab 82 01 18 78 ee 95  |G..GVQY.n....x..|
-00000020  b8 e2 c7 c7 f9 64 98 dd  84 8d 96 d9 2d 08 62 1e  |.....d......-.b.|
-00000030  4f 29 83 b6 93 68 77 7a  14 1b f0 b3 1a 67 7b 7a  |O)...hwz.....g{z|
-00000040  f9 54 f3 7e 6d eb b6 7a  c9 37 70 6a 83 68 f2 15  |.T.~m..z.7pj.h..|
-00000050  81 07 30 6e b8 fa 19 0e  46 dc d6 9a 4a 8e 8d f1  |..0n....F...J...|
-00000060  05 78 60 75 d4 00 d9 1e  11 5f 16 f7 bc 9f e8 8a  |.x`u....._......|
-00000070  c4 3e bd d9 1a b8 67 50  00 be 5f 43 ee 07 ad be  |.>....gP.._C....|
-00000080  f5 85 67 fc 8f c6 87 47  6d 6e b2 14 03 03 00 01  |..g....Gmn......|
-00000090  01 16 03 03 00 40 91 7d  7b 05 99 48 05 70 a9 67  |..... at .}{..H.p.g|
-000000a0  e9 7a 0a c3 6b bf b0 ad  68 65 17 fb 18 bf 8d bd  |.z..k...he......|
-000000b0  e1 4b 12 bf ea 82 9d a6  1e 3a c8 77 65 32 bd 5e  |.K.......:.we2.^|
-000000c0  c4 46 da e7 e1 ac 09 fe  4a ac bc 57 6a 17 7d dc  |.F......J..Wj.}.|
-000000d0  fe 9c d0 d0 6e fc                                 |....n.|
+00000000  16 03 03 00 86 10 00 00  82 00 80 6f bc 33 c8 2d  |...........o.3.-|
+00000010  5a 50 65 2f 06 1a 45 16  9e 5b ab 97 43 b1 9e 96  |ZPe/..E..[..C...|
+00000020  b5 4a fe c3 7c e8 e4 07  ea 00 47 d2 51 23 11 ae  |.J..|.....G.Q#..|
+00000030  11 a8 79 71 b9 c6 82 17  40 ae c7 fc cd 05 4d 6d  |..yq.... at .....Mm|
+00000040  cb bc f1 ce 30 d0 10 37  4a e6 aa d3 14 fb bc 62  |....0..7J......b|
+00000050  eb 6c fa ec e1 e1 dd 63  39 95 0b 87 71 a0 83 ba  |.l.....c9...q...|
+00000060  bf 25 f8 a9 d3 c4 35 e1  88 23 85 56 c6 f4 0b 10  |.%....5..#.V....|
+00000070  d1 70 f8 0a 3d a1 08 17  ce 27 2d 4c a7 c5 b5 0d  |.p..=....'-L....|
+00000080  f2 43 b7 b9 02 21 7a eb  40 d2 66 14 03 03 00 01  |.C...!z. at .f.....|
+00000090  01 16 03 03 00 40 0a 93  47 0b 6e 40 ff cd 09 a5  |..... at ..G.n@....|
+000000a0  bc a4 c5 a8 c3 1c 0a fb  d4 2e 8a 2f 0c f3 d6 e1  |.........../....|
+000000b0  de 1f 56 2f 09 61 2d 31  d5 b1 29 6b f2 18 8b f2  |..V/.a-1..)k....|
+000000c0  0c 0e 09 5f ec 11 56 af  44 8b e5 2d 09 68 eb c2  |..._..V.D..-.h..|
+000000d0  91 4d 04 b2 10 02                                 |.M....|
 >>> Flow 4 (server to client)
 00000000  15 03 03 00 02 02 14                              |.......|
diff --git a/src/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificateNotFound b/src/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificateNotFound
index 904f69e..32c0d4a 100644
--- a/src/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificateNotFound
+++ b/src/crypto/tls/testdata/Server-TLSv12-SNI-GetCertificateNotFound
@@ -1,12 +1,12 @@
 >>> Flow 1 (client to server)
-00000000  16 03 01 00 6e 01 00 00  6a 03 03 27 db e3 e8 f4  |....n...j..'....|
-00000010  48 1d 45 d5 20 64 97 b2  20 a6 67 94 7a 1e 87 12  |H.E. d.. .g.z...|
-00000020  25 b1 53 94 27 78 ed ae  58 2f 1b 00 00 04 00 2f  |%.S.'x..X/...../|
-00000030  00 ff 01 00 00 3d 00 00  00 10 00 0e 00 00 0b 73  |.....=.........s|
-00000040  6e 69 74 65 73 74 2e 63  6f 6d 00 0d 00 20 00 1e  |nitest.com... ..|
-00000050  06 01 06 02 06 03 05 01  05 02 05 03 04 01 04 02  |................|
-00000060  04 03 03 01 03 02 03 03  02 01 02 02 02 03 00 0f  |................|
-00000070  00 01 01                                          |...|
+00000000  16 03 01 00 6f 01 00 00  6b 03 03 64 29 6e 67 3d  |....o...k..d)ng=|
+00000010  5a 13 48 8a ae a5 67 6b  2f 5b 76 d2 c1 df 23 c6  |Z.H...gk/[v...#.|
+00000020  f9 52 26 33 ce 0b 03 f6  53 a7 db 00 00 04 00 2f  |.R&3....S....../|
+00000030  00 ff 02 01 00 00 3d 00  00 00 10 00 0e 00 00 0b  |......=.........|
+00000040  73 6e 69 74 65 73 74 2e  63 6f 6d 00 0d 00 20 00  |snitest.com... .|
+00000050  1e 06 01 06 02 06 03 05  01 05 02 05 03 04 01 04  |................|
+00000060  02 04 03 03 01 03 02 03  03 02 01 02 02 02 03 00  |................|
+00000070  0f 00 01 01                                       |....|
 >>> Flow 2 (server to client)
 00000000  16 03 03 00 31 02 00 00  2d 03 03 00 00 00 00 00  |....1...-.......|
 00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
@@ -46,19 +46,19 @@
 00000230  2c 65 25 d6 52 b6 e3 18  45 bd cc 16 03 03 00 04  |,e%.R...E.......|
 00000240  0e 00 00 00                                       |....|
 >>> Flow 3 (client to server)
-00000000  16 03 03 00 86 10 00 00  82 00 80 72 23 e9 89 70  |...........r#..p|
-00000010  97 02 08 58 0d 28 96 5b  19 73 dd 4f 6e 4c 11 dd  |...X.(.[.s.OnL..|
-00000020  cb 56 14 f4 8f c8 e5 84  03 f5 7e f0 a4 08 44 8c  |.V........~...D.|
-00000030  22 74 01 5c e4 9d e0 38  53 90 66 e3 df bb 09 a8  |"t.\...8S.f.....|
-00000040  11 97 0a 44 01 d2 70 85  14 a1 9a 2f 02 34 40 6d  |...D..p..../.4 at m|
-00000050  66 80 72 9a 97 98 5c 91  0e dc 42 ac c2 90 2f 30  |f.r...\...B.../0|
-00000060  ca 39 25 94 da 6e b6 5f  94 a9 94 66 7f 32 6a bb  |.9%..n._...f.2j.|
-00000070  5d 43 20 c3 74 f7 52 29  1f d5 62 6b a4 a1 8c 25  |]C .t.R)..bk...%|
-00000080  46 69 22 a5 68 54 f4 68  30 e2 52 14 03 03 00 01  |Fi".hT.h0.R.....|
-00000090  01 16 03 03 00 40 51 d2  78 64 e3 59 ee b7 5f 95  |..... at Q.xd.Y.._.|
-000000a0  4c 49 7f 0d 49 3f 55 71  8c 3b 24 e3 81 22 4a d1  |LI..I?Uq.;$.."J.|
-000000b0  ab 84 4e df 02 9d 56 ea  2a 14 71 e1 dc 1d 5c 1d  |..N...V.*.q...\.|
-000000c0  54 ce cb 58 f6 4d e7 73  44 0d 99 95 a5 2d 7c 2f  |T..X.M.sD....-|/|
-000000d0  15 f5 8f fd 97 40                                 |.....@|
+00000000  16 03 03 00 86 10 00 00  82 00 80 7b 3b b8 73 f0  |...........{;.s.|
+00000010  78 2c 75 91 ee 4a ac 6e  9d 08 8e ef dd 52 fb 38  |x,u..J.n.....R.8|
+00000020  d7 6f b3 39 8a 8c 3c dc  4b e0 a9 2b 0b de 9a d6  |.o.9..<.K..+....|
+00000030  38 72 ae 0f 76 87 4b f6  45 17 f6 fa b2 5a 07 30  |8r..v.K.E....Z.0|
+00000040  5b ef e7 40 e0 95 98 bf  8d 8d 5e 7a 6a ea 2d 2e  |[.. at ......^zj.-.|
+00000050  9c 99 e4 47 6b 4f 16 32  fb 0d a7 01 36 2e 06 f2  |...GkO.2....6...|
+00000060  65 74 b6 ed 07 51 60 7a  98 d6 77 36 f4 c7 f6 b1  |et...Q`z..w6....|
+00000070  f1 6a 3e 38 7c 79 5c c6  b4 53 5c 85 fb 0b 2c f9  |.j>8|y\..S\...,.|
+00000080  2c 60 97 c8 73 f7 22 ef  52 4c 10 14 03 03 00 01  |,`..s.".RL......|
+00000090  01 16 03 03 00 40 4c 73  6e 5e 66 9d 53 2e fa b7  |..... at Lsn^f.S...|
+000000a0  90 2d 52 55 13 d2 67 28  aa 1a 6f 62 42 ef 2f 4d  |.-RU..g(..obB./M|
+000000b0  04 1d ef 64 8f 1a 70 c0  d0 bf 06 72 ee db 3e 43  |...d..p....r..>C|
+000000c0  7f ed 37 bb a1 62 0c c5  c8 a9 c0 51 8f 77 95 b3  |..7..b.....Q.w..|
+000000d0  72 7e 01 89 c4 32                                 |r~...2|
 >>> Flow 4 (server to client)
 00000000  15 03 03 00 02 02 14                              |.......|
diff --git a/src/crypto/tls/tls.go b/src/crypto/tls/tls.go
index 0b1c377..4bedd76 100644
--- a/src/crypto/tls/tls.go
+++ b/src/crypto/tls/tls.go
@@ -5,6 +5,11 @@
 // Package tls partially implements TLS 1.2, as specified in RFC 5246.
 package tls
 
+// BUG(agl): The crypto/tls package does not implement countermeasures
+// against Lucky13 attacks on CBC-mode encryption. See
+// http://www.isg.rhul.ac.uk/tls/TLStiming.pdf and
+// https://www.imperialviolet.org/2013/02/04/luckythirteen.html.
+
 import (
 	"crypto"
 	"crypto/ecdsa"
@@ -12,6 +17,7 @@ import (
 	"crypto/x509"
 	"encoding/pem"
 	"errors"
+	"fmt"
 	"io/ioutil"
 	"net"
 	"strings"
@@ -20,8 +26,8 @@ import (
 
 // Server returns a new TLS server side connection
 // using conn as the underlying transport.
-// The configuration config must be non-nil and must have
-// at least one certificate.
+// The configuration config must be non-nil and must include
+// at least one certificate or else set GetCertificate.
 func Server(conn net.Conn, config *Config) *Conn {
 	return &Conn{conn: conn, config: config}
 }
@@ -53,8 +59,8 @@ func (l *listener) Accept() (c net.Conn, err error) {
 
 // NewListener creates a Listener which accepts connections from an inner
 // Listener and wraps each connection with Server.
-// The configuration config must be non-nil and must have
-// at least one certificate.
+// The configuration config must be non-nil and must include
+// at least one certificate or else set GetCertificate.
 func NewListener(inner net.Listener, config *Config) net.Listener {
 	l := new(listener)
 	l.Listener = inner
@@ -64,11 +70,11 @@ func NewListener(inner net.Listener, config *Config) net.Listener {
 
 // Listen creates a TLS listener accepting connections on the
 // given network address using net.Listen.
-// The configuration config must be non-nil and must have
-// at least one certificate.
+// The configuration config must be non-nil and must include
+// at least one certificate or else set GetCertificate.
 func Listen(network, laddr string, config *Config) (net.Listener, error) {
-	if config == nil || len(config.Certificates) == 0 {
-		return nil, errors.New("tls.Listen: no certificates in configuration")
+	if config == nil || (len(config.Certificates) == 0 && config.GetCertificate == nil) {
+		return nil, errors.New("tls: neither Certificates nor GetCertificate set in Config")
 	}
 	l, err := net.Listen(network, laddr)
 	if err != nil {
@@ -166,7 +172,9 @@ func Dial(network, addr string, config *Config) (*Conn, error) {
 }
 
 // LoadX509KeyPair reads and parses a public/private key pair from a pair of
-// files. The files must contain PEM encoded data.
+// files. The files must contain PEM encoded data. On successful return,
+// Certificate.Leaf will be nil because the parsed form of the certificate is
+// not retained.
 func LoadX509KeyPair(certFile, keyFile string) (Certificate, error) {
 	certPEMBlock, err := ioutil.ReadFile(certFile)
 	if err != nil {
@@ -180,34 +188,53 @@ func LoadX509KeyPair(certFile, keyFile string) (Certificate, error) {
 }
 
 // X509KeyPair parses a public/private key pair from a pair of
-// PEM encoded data.
+// PEM encoded data. On successful return, Certificate.Leaf will be nil because
+// the parsed form of the certificate is not retained.
 func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (Certificate, error) {
-	var cert Certificate
-	var certDERBlock *pem.Block
 	fail := func(err error) (Certificate, error) { return Certificate{}, err }
+
+	var cert Certificate
+	var skippedBlockTypes []string
 	for {
+		var certDERBlock *pem.Block
 		certDERBlock, certPEMBlock = pem.Decode(certPEMBlock)
 		if certDERBlock == nil {
 			break
 		}
 		if certDERBlock.Type == "CERTIFICATE" {
 			cert.Certificate = append(cert.Certificate, certDERBlock.Bytes)
+		} else {
+			skippedBlockTypes = append(skippedBlockTypes, certDERBlock.Type)
 		}
 	}
 
 	if len(cert.Certificate) == 0 {
-		return fail(errors.New("crypto/tls: failed to parse certificate PEM data"))
+		if len(skippedBlockTypes) == 0 {
+			return fail(errors.New("crypto/tls: failed to find any PEM data in certificate input"))
+		} else if len(skippedBlockTypes) == 1 && strings.HasSuffix(skippedBlockTypes[0], "PRIVATE KEY") {
+			return fail(errors.New("crypto/tls: failed to find certificate PEM data in certificate input, but did find a private key; PEM inputs may have been switched"))
+		} else {
+			return fail(fmt.Errorf("crypto/tls: failed to find \"CERTIFICATE\" PEM block in certificate input after skipping PEM blocks of the following types: %v", skippedBlockTypes))
+		}
 	}
 
+	skippedBlockTypes = skippedBlockTypes[:0]
 	var keyDERBlock *pem.Block
 	for {
 		keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock)
 		if keyDERBlock == nil {
-			return fail(errors.New("crypto/tls: failed to parse key PEM data"))
+			if len(skippedBlockTypes) == 0 {
+				return fail(errors.New("crypto/tls: failed to find any PEM data in key input"))
+			} else if len(skippedBlockTypes) == 1 && skippedBlockTypes[0] == "CERTIFICATE" {
+				return fail(errors.New("crypto/tls: found a certificate rather than a key in the PEM for the private key"))
+			} else {
+				return fail(fmt.Errorf("crypto/tls: failed to find PEM block with type ending in \"PRIVATE KEY\" in key input after skipping PEM blocks of the following types: %v", skippedBlockTypes))
+			}
 		}
 		if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") {
 			break
 		}
+		skippedBlockTypes = append(skippedBlockTypes, keyDERBlock.Type)
 	}
 
 	var err error
diff --git a/src/crypto/tls/tls_test.go b/src/crypto/tls/tls_test.go
index c45c103..5cc1427 100644
--- a/src/crypto/tls/tls_test.go
+++ b/src/crypto/tls/tls_test.go
@@ -6,6 +6,7 @@ package tls
 
 import (
 	"bytes"
+	"errors"
 	"fmt"
 	"internal/testenv"
 	"io"
@@ -104,6 +105,38 @@ func TestX509KeyPair(t *testing.T) {
 	}
 }
 
+func TestX509KeyPairErrors(t *testing.T) {
+	_, err := X509KeyPair([]byte(rsaKeyPEM), []byte(rsaCertPEM))
+	if err == nil {
+		t.Fatalf("X509KeyPair didn't return an error when arguments were switched")
+	}
+	if subStr := "been switched"; !strings.Contains(err.Error(), subStr) {
+		t.Fatalf("Expected %q in the error when switching arguments to X509KeyPair, but the error was %q", subStr, err)
+	}
+
+	_, err = X509KeyPair([]byte(rsaCertPEM), []byte(rsaCertPEM))
+	if err == nil {
+		t.Fatalf("X509KeyPair didn't return an error when both arguments were certificates")
+	}
+	if subStr := "certificate"; !strings.Contains(err.Error(), subStr) {
+		t.Fatalf("Expected %q in the error when both arguments to X509KeyPair were certificates, but the error was %q", subStr, err)
+	}
+
+	const nonsensePEM = `
+-----BEGIN NONSENSE-----
+Zm9vZm9vZm9v
+-----END NONSENSE-----
+`
+
+	_, err = X509KeyPair([]byte(nonsensePEM), []byte(nonsensePEM))
+	if err == nil {
+		t.Fatalf("X509KeyPair didn't return an error when both arguments were nonsense")
+	}
+	if subStr := "NONSENSE"; !strings.Contains(err.Error(), subStr) {
+		t.Fatalf("Expected %q in the error when both arguments to X509KeyPair were nonsense, but the error was %q", subStr, err)
+	}
+}
+
 func TestX509MixedKeyPair(t *testing.T) {
 	if _, err := X509KeyPair([]byte(rsaCertPEM), []byte(ecdsaKeyPEM)); err == nil {
 		t.Error("Load of RSA certificate succeeded with ECDSA private key")
@@ -332,3 +365,104 @@ func TestVerifyHostnameResumed(t *testing.T) {
 		c.Close()
 	}
 }
+
+func TestConnCloseBreakingWrite(t *testing.T) {
+	ln := newLocalListener(t)
+	defer ln.Close()
+
+	srvCh := make(chan *Conn, 1)
+	var serr error
+	var sconn net.Conn
+	go func() {
+		var err error
+		sconn, err = ln.Accept()
+		if err != nil {
+			serr = err
+			srvCh <- nil
+			return
+		}
+		serverConfig := *testConfig
+		srv := Server(sconn, &serverConfig)
+		if err := srv.Handshake(); err != nil {
+			serr = fmt.Errorf("handshake: %v", err)
+			srvCh <- nil
+			return
+		}
+		srvCh <- srv
+	}()
+
+	cconn, err := net.Dial("tcp", ln.Addr().String())
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer cconn.Close()
+
+	conn := &changeImplConn{
+		Conn: cconn,
+	}
+
+	clientConfig := *testConfig
+	tconn := Client(conn, &clientConfig)
+	if err := tconn.Handshake(); err != nil {
+		t.Fatal(err)
+	}
+
+	srv := <-srvCh
+	if srv == nil {
+		t.Fatal(serr)
+	}
+	defer sconn.Close()
+
+	connClosed := make(chan struct{})
+	conn.closeFunc = func() error {
+		close(connClosed)
+		return nil
+	}
+
+	inWrite := make(chan bool, 1)
+	var errConnClosed = errors.New("conn closed for test")
+	conn.writeFunc = func(p []byte) (n int, err error) {
+		inWrite <- true
+		<-connClosed
+		return 0, errConnClosed
+	}
+
+	closeReturned := make(chan bool, 1)
+	go func() {
+		<-inWrite
+		tconn.Close() // test that this doesn't block forever.
+		closeReturned <- true
+	}()
+
+	_, err = tconn.Write([]byte("foo"))
+	if err != errConnClosed {
+		t.Errorf("Write error = %v; want errConnClosed", err)
+	}
+
+	<-closeReturned
+	if err := tconn.Close(); err != errClosed {
+		t.Errorf("Close error = %v; want errClosed", err)
+	}
+}
+
+// changeImplConn is a net.Conn which can change its Write and Close
+// methods.
+type changeImplConn struct {
+	net.Conn
+	writeFunc func([]byte) (int, error)
+	closeFunc func() error
+}
+
+func (w *changeImplConn) Write(p []byte) (n int, err error) {
+	if w.writeFunc != nil {
+		return w.writeFunc(p)
+	}
+	return w.Conn.Write(p)
+}
+
+func (w *changeImplConn) Close() error {
+	if w.closeFunc != nil {
+		return w.closeFunc()
+	}
+	return w.Conn.Close()
+}
diff --git a/src/crypto/x509/pkix/pkix.go b/src/crypto/x509/pkix/pkix.go
index 5add4e5..1b3e3c0 100644
--- a/src/crypto/x509/pkix/pkix.go
+++ b/src/crypto/x509/pkix/pkix.go
@@ -129,12 +129,12 @@ func (n Name) appendRDNs(in RDNSequence, values []string, oid asn1.ObjectIdentif
 
 func (n Name) ToRDNSequence() (ret RDNSequence) {
 	ret = n.appendRDNs(ret, n.Country, oidCountry)
-	ret = n.appendRDNs(ret, n.Organization, oidOrganization)
-	ret = n.appendRDNs(ret, n.OrganizationalUnit, oidOrganizationalUnit)
-	ret = n.appendRDNs(ret, n.Locality, oidLocality)
 	ret = n.appendRDNs(ret, n.Province, oidProvince)
+	ret = n.appendRDNs(ret, n.Locality, oidLocality)
 	ret = n.appendRDNs(ret, n.StreetAddress, oidStreetAddress)
 	ret = n.appendRDNs(ret, n.PostalCode, oidPostalCode)
+	ret = n.appendRDNs(ret, n.Organization, oidOrganization)
+	ret = n.appendRDNs(ret, n.OrganizationalUnit, oidOrganizationalUnit)
 	if len(n.CommonName) > 0 {
 		ret = n.appendRDNs(ret, []string{n.CommonName}, oidCommonName)
 	}
diff --git a/src/crypto/x509/root_unix.go b/src/crypto/x509/root_unix.go
index 8d3b2fb..9f06f9d 100644
--- a/src/crypto/x509/root_unix.go
+++ b/src/crypto/x509/root_unix.go
@@ -11,6 +11,7 @@ import "io/ioutil"
 // Possible directories with certificate files; stop after successfully
 // reading at least one file from a directory.
 var certDirectories = []string{
+	"/etc/ssl/certs",               // SLES10/SLES11, https://golang.org/issue/12139
 	"/system/etc/security/cacerts", // Android
 }
 
diff --git a/src/crypto/x509/sec1.go b/src/crypto/x509/sec1.go
index c4d7ab6..f484b6d 100644
--- a/src/crypto/x509/sec1.go
+++ b/src/crypto/x509/sec1.go
@@ -39,9 +39,14 @@ func MarshalECPrivateKey(key *ecdsa.PrivateKey) ([]byte, error) {
 	if !ok {
 		return nil, errors.New("x509: unknown elliptic curve")
 	}
+
+	privateKeyBytes := key.D.Bytes()
+	paddedPrivateKey := make([]byte, (key.Curve.Params().N.BitLen() + 7) / 8)
+	copy(paddedPrivateKey[len(paddedPrivateKey) - len(privateKeyBytes):], privateKeyBytes)
+
 	return asn1.Marshal(ecPrivateKey{
 		Version:       1,
-		PrivateKey:    key.D.Bytes(),
+		PrivateKey:    paddedPrivateKey,
 		NamedCurveOID: oid,
 		PublicKey:     asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)},
 	})
@@ -71,13 +76,30 @@ func parseECPrivateKey(namedCurveOID *asn1.ObjectIdentifier, der []byte) (key *e
 	}
 
 	k := new(big.Int).SetBytes(privKey.PrivateKey)
-	if k.Cmp(curve.Params().N) >= 0 {
+	curveOrder := curve.Params().N
+	if k.Cmp(curveOrder) >= 0 {
 		return nil, errors.New("x509: invalid elliptic curve private key value")
 	}
 	priv := new(ecdsa.PrivateKey)
 	priv.Curve = curve
 	priv.D = k
-	priv.X, priv.Y = curve.ScalarBaseMult(privKey.PrivateKey)
+
+	privateKey := make([]byte, (curveOrder.BitLen() + 7) / 8)
+
+	// Some private keys have leading zero padding. This is invalid
+	// according to [SEC1], but this code will ignore it.
+	for len(privKey.PrivateKey) > len(privateKey) {
+		if privKey.PrivateKey[0] != 0 {
+			return nil, errors.New("x509: invalid private key length")
+		}
+		privKey.PrivateKey = privKey.PrivateKey[1:]
+	}
+
+	// Some private keys remove all leading zeros, this is also invalid
+	// according to [SEC1] but since OpenSSL used to do this, we ignore
+	// this too.
+	copy(privateKey[len(privateKey) - len(privKey.PrivateKey):], privKey.PrivateKey)
+	priv.X, priv.Y = curve.ScalarBaseMult(privateKey)
 
 	return priv, nil
 }
diff --git a/src/crypto/x509/sec1_test.go b/src/crypto/x509/sec1_test.go
index 95f18e7..5e9ded5 100644
--- a/src/crypto/x509/sec1_test.go
+++ b/src/crypto/x509/sec1_test.go
@@ -10,21 +10,35 @@ import (
 	"testing"
 )
 
-// Generated using:
-//   openssl ecparam -genkey -name secp384r1 -outform PEM
-var ecPrivateKeyHex = `3081a40201010430bdb9839c08ee793d1157886a7a758a3c8b2a17a4df48f17ace57c72c56b4723cf21dcda21d4e1ad57ff034f19fcfd98ea00706052b81040022a16403620004feea808b5ee2429cfcce13c32160e1c960990bd050bb0fdf7222f3decd0a55008e32a6aa3c9062051c4cba92a7a3b178b24567412d43cdd2f882fa5addddd726fe3e208d2c26d733a773a597abb749714df7256ead5105fa6e7b3650de236b50`
+var ecKeyTests = []struct{
+	derHex string
+	shouldReserialize bool
+}{
+	// Generated using:
+	//   openssl ecparam -genkey -name secp384r1 -outform PEM
+	{"3081a40201010430bdb9839c08ee793d1157886a7a758a3c8b2a17a4df48f17ace57c72c56b4723cf21dcda21d4e1ad57ff034f19fcfd98ea00706052b81040022a16403620004feea808b5ee2429cfcce13c32160e1c960990bd050bb0fdf7222f3decd0a55008e32a6aa3c9062051c4cba92a7a3b178b24567412d43cdd2f882fa5addddd726fe3e208d2c26d733a773a597abb749714df7256ead5105fa6e7b3650de236b50", true},
+	// This key was generated by GnuTLS and has illegal zero-padding of the
+	// private key. See https://github.com/golang/go/issues/13699.
+	{"3078020101042100f9f43a04b9bdc3ab01f53be6df80e7a7bc3eaf7b87fc24e630a4a0aa97633645a00a06082a8648ce3d030107a1440342000441a51bc318461b4c39a45048a16d4fc2a935b1ea7fe86e8c1fa219d6f2438f7c7fd62957d3442efb94b6a23eb0ea66dda663dc42f379cda6630b21b7888a5d3d", false},
+	// This was generated using an old version of OpenSSL and is missing a
+	// leading zero byte in the private key that should be present.
+	{"3081db0201010441607b4f985774ac21e633999794542e09312073480baa69550914d6d43d8414441e61b36650567901da714f94dffb3ce0e2575c31928a0997d51df5c440e983ca17a00706052b81040023a181890381860004001661557afedd7ac8d6b70e038e576558c626eb62edda36d29c3a1310277c11f67a8c6f949e5430a37dcfb95d902c1b5b5379c389873b9dd17be3bdb088a4774a7401072f830fb9a08d93bfa50a03dd3292ea07928724ddb915d831917a338f6b0aecfbc3cf5352c4a1295d356890c41c34116d29eeb93779aab9d9d78e2613437740f6", false},
+}
 
 func TestParseECPrivateKey(t *testing.T) {
-	derBytes, _ := hex.DecodeString(ecPrivateKeyHex)
-	key, err := ParseECPrivateKey(derBytes)
-	if err != nil {
-		t.Errorf("failed to decode EC private key: %s", err)
-	}
-	serialized, err := MarshalECPrivateKey(key)
-	if err != nil {
-		t.Fatalf("failed to encode EC private key: %s", err)
-	}
-	if !bytes.Equal(serialized, derBytes) {
-		t.Fatalf("serialized key differs: got %x, want %x", serialized, derBytes)
+	for i, test := range ecKeyTests {
+		derBytes, _ := hex.DecodeString(test.derHex)
+		key, err := ParseECPrivateKey(derBytes)
+		if err != nil {
+			t.Fatalf("#%d: failed to decode EC private key: %s", i, err)
+		}
+		serialized, err := MarshalECPrivateKey(key)
+		if err != nil {
+			t.Fatalf("#%d: failed to encode EC private key: %s", i, err)
+		}
+		matches := bytes.Equal(serialized, derBytes)
+		if matches != test.shouldReserialize {
+			t.Fatalf("#%d: when serializing key: matches=%t, should match=%t: original %x, reserialized %x", i, matches, test.shouldReserialize, serialized, derBytes)
+		}
 	}
 }
diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go
index 21b870c..27e9bbf 100644
--- a/src/crypto/x509/verify.go
+++ b/src/crypto/x509/verify.go
@@ -5,6 +5,7 @@
 package x509
 
 import (
+	"errors"
 	"fmt"
 	"net"
 	"runtime"
@@ -122,6 +123,10 @@ func (SystemRootsError) Error() string {
 	return "x509: failed to load system roots and no roots provided"
 }
 
+// errNotParsed is returned when a certificate without ASN.1 contents is
+// verified. Platform-specific verification needs the ASN.1 contents.
+var errNotParsed = errors.New("x509: missing ASN.1 contents; use ParseCertificate")
+
 // VerifyOptions contains parameters for Certificate.Verify. It's a structure
 // because other PKIX verification APIs have ended up needing many options.
 type VerifyOptions struct {
@@ -210,6 +215,19 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
 //
 // WARNING: this doesn't do any revocation checking.
 func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) {
+	// Platform-specific verification needs the ASN.1 contents so
+	// this makes the behaviour consistent across platforms.
+	if len(c.Raw) == 0 {
+		return nil, errNotParsed
+	}
+	if opts.Intermediates != nil {
+		for _, intermediate := range opts.Intermediates.certs {
+			if len(intermediate.Raw) == 0 {
+				return nil, errNotParsed
+			}
+		}
+	}
+
 	// Use Windows's own verification and chain building.
 	if opts.Roots == nil && runtime.GOOS == "windows" {
 		return c.systemVerify(&opts)
diff --git a/src/crypto/x509/x509.go b/src/crypto/x509/x509.go
index be6c013..d9288bb 100644
--- a/src/crypto/x509/x509.go
+++ b/src/crypto/x509/x509.go
@@ -19,6 +19,7 @@ import (
 	"encoding/asn1"
 	"encoding/pem"
 	"errors"
+	"fmt"
 	"io"
 	"math/big"
 	"net"
@@ -56,6 +57,9 @@ func marshalPublicKey(pub interface{}) (publicKeyBytes []byte, publicKeyAlgorith
 			N: pub.N,
 			E: pub.E,
 		})
+		if err != nil {
+			return nil, pkix.AlgorithmIdentifier{}, err
+		}
 		publicKeyAlgorithm.Algorithm = oidPublicKeyRSA
 		// This is a NULL parameters value which is technically
 		// superfluous, but most other code includes it and, by
@@ -171,6 +175,28 @@ const (
 	ECDSAWithSHA512
 )
 
+var algoName = [...]string{
+	MD2WithRSA:      "MD2-RSA",
+	MD5WithRSA:      "MD5-RSA",
+	SHA1WithRSA:     "SHA1-RSA",
+	SHA256WithRSA:   "SHA256-RSA",
+	SHA384WithRSA:   "SHA384-RSA",
+	SHA512WithRSA:   "SHA512-RSA",
+	DSAWithSHA1:     "DSA-SHA1",
+	DSAWithSHA256:   "DSA-SHA256",
+	ECDSAWithSHA1:   "ECDSA-SHA1",
+	ECDSAWithSHA256: "ECDSA-SHA256",
+	ECDSAWithSHA384: "ECDSA-SHA384",
+	ECDSAWithSHA512: "ECDSA-SHA512",
+}
+
+func (algo SignatureAlgorithm) String() string {
+	if 0 < algo && int(algo) < len(algoName) {
+		return algoName[algo]
+	}
+	return strconv.Itoa(int(algo))
+}
+
 type PublicKeyAlgorithm int
 
 const (
@@ -538,6 +564,13 @@ type Certificate struct {
 // involves algorithms that are not currently implemented.
 var ErrUnsupportedAlgorithm = errors.New("x509: cannot verify signature: algorithm unimplemented")
 
+// An InsecureAlgorithmError
+type InsecureAlgorithmError SignatureAlgorithm
+
+func (e InsecureAlgorithmError) Error() string {
+	return fmt.Sprintf("x509: cannot verify signature: insecure algorithm %v", SignatureAlgorithm(e))
+}
+
 // ConstraintViolationError results when a requested usage is not permitted by
 // a certificate. For example: checking a signature when the public key isn't a
 // certificate signing key.
@@ -648,6 +681,8 @@ func checkSignature(algo SignatureAlgorithm, signed, signature []byte, publicKey
 		hashType = crypto.SHA384
 	case SHA512WithRSA, ECDSAWithSHA512:
 		hashType = crypto.SHA512
+	case MD2WithRSA, MD5WithRSA:
+		return InsecureAlgorithmError(algo)
 	default:
 		return ErrUnsupportedAlgorithm
 	}
@@ -906,10 +941,6 @@ func parseCertificate(in *certificate) (*Certificate, error) {
 		return nil, err
 	}
 
-	if in.TBSCertificate.SerialNumber.Sign() < 0 {
-		return nil, errors.New("x509: negative serial number")
-	}
-
 	out.Version = in.TBSCertificate.Version + 1
 	out.SerialNumber = in.TBSCertificate.SerialNumber
 
@@ -1017,7 +1048,7 @@ func parseCertificate(in *certificate) (*Certificate, error) {
 				}
 
 			case 31:
-				// RFC 5280, 4.2.1.14
+				// RFC 5280, 4.2.1.13
 
 				// CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
 				//
@@ -1038,6 +1069,11 @@ func parseCertificate(in *certificate) (*Certificate, error) {
 				}
 
 				for _, dp := range cdp {
+					// Per RFC 5280, 4.2.1.13, one of distributionPoint or cRLIssuer may be empty.
+					if len(dp.DistributionPoint.FullName.Bytes) == 0 {
+						continue
+					}
+
 					var n asn1.RawValue
 					if _, err := asn1.Unmarshal(dp.DistributionPoint.FullName.Bytes, &n); err != nil {
 						return nil, err
@@ -1704,9 +1740,7 @@ type CertificateRequest struct {
 
 	Subject pkix.Name
 
-	// Attributes is a collection of attributes providing
-	// additional information about the subject of the certificate.
-	// See RFC 2986 section 4.1.
+	// Attributes is the dried husk of a bug and shouldn't be used.
 	Attributes []pkix.AttributeTypeAndValueSET
 
 	// Extensions contains raw X.509 extensions. When parsing CSRs, this
@@ -1781,6 +1815,38 @@ func parseRawAttributes(rawAttributes []asn1.RawValue) []pkix.AttributeTypeAndVa
 	return attributes
 }
 
+// parseCSRExtensions parses the attributes from a CSR and extracts any
+// requested extensions.
+func parseCSRExtensions(rawAttributes []asn1.RawValue) ([]pkix.Extension, error) {
+	// pkcs10Attribute reflects the Attribute structure from section 4.1 of
+	// https://tools.ietf.org/html/rfc2986.
+	type pkcs10Attribute struct {
+		Id     asn1.ObjectIdentifier
+		Values []asn1.RawValue `asn1:"set"`
+	}
+
+	var ret []pkix.Extension
+	for _, rawAttr := range rawAttributes {
+		var attr pkcs10Attribute
+		if rest, err := asn1.Unmarshal(rawAttr.FullBytes, &attr); err != nil || len(rest) != 0 || len(attr.Values) == 0 {
+			// Ignore attributes that don't parse.
+			continue
+		}
+
+		if !attr.Id.Equal(oidExtensionRequest) {
+			continue
+		}
+
+		var extensions []pkix.Extension
+		if _, err := asn1.Unmarshal(attr.Values[0].FullBytes, &extensions); err != nil {
+			return nil, err
+		}
+		ret = append(ret, extensions...)
+	}
+
+	return ret, nil
+}
+
 // CreateCertificateRequest creates a new certificate based on a template. The
 // following members of template are used: Subject, Attributes,
 // SignatureAlgorithm, Extensions, DNSNames, EmailAddresses, and IPAddresses.
@@ -1983,38 +2049,15 @@ func parseCertificateRequest(in *certificateRequest) (*CertificateRequest, error
 
 	out.Subject.FillFromRDNSequence(&subject)
 
-	var extensions []pkix.AttributeTypeAndValue
-
-	for _, atvSet := range out.Attributes {
-		if !atvSet.Type.Equal(oidExtensionRequest) {
-			continue
-		}
-
-		for _, atvs := range atvSet.Value {
-			extensions = append(extensions, atvs...)
-		}
+	if out.Extensions, err = parseCSRExtensions(in.TBSCSR.RawAttributes); err != nil {
+		return nil, err
 	}
 
-	out.Extensions = make([]pkix.Extension, 0, len(extensions))
-
-	for _, e := range extensions {
-		value, ok := e.Value.([]byte)
-		if !ok {
-			return nil, errors.New("x509: extension attribute contained non-OCTET STRING data")
-		}
-
-		out.Extensions = append(out.Extensions, pkix.Extension{
-			Id:    e.Type,
-			Value: value,
-		})
-
-		if len(e.Type) == 4 && e.Type[0] == 2 && e.Type[1] == 5 && e.Type[2] == 29 {
-			switch e.Type[3] {
-			case 17:
-				out.DNSNames, out.EmailAddresses, out.IPAddresses, err = parseSANExtension(value)
-				if err != nil {
-					return nil, err
-				}
+	for _, extension := range out.Extensions {
+		if extension.Id.Equal(oidExtensionSubjectAltName) {
+			out.DNSNames, out.EmailAddresses, out.IPAddresses, err = parseSANExtension(extension.Value)
+			if err != nil {
+				return nil, err
 			}
 		}
 	}
diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go
index f4f9fa2..d1ef027 100644
--- a/src/crypto/x509/x509_test.go
+++ b/src/crypto/x509/x509_test.go
@@ -18,6 +18,7 @@ import (
 	"encoding/base64"
 	"encoding/hex"
 	"encoding/pem"
+	"fmt"
 	"internal/testenv"
 	"math/big"
 	"net"
@@ -343,7 +344,11 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
 	for _, test := range tests {
 		commonName := "test.example.com"
 		template := Certificate{
-			SerialNumber: big.NewInt(1),
+			// SerialNumber is negative to ensure that negative
+			// values are parsed. This is due to the prevalence of
+			// buggy code that produces certificates with negative
+			// serial numbers.
+			SerialNumber: big.NewInt(-1),
 			Subject: pkix.Name{
 				CommonName:   commonName,
 				Organization: []string{"Σ Acme Co"},
@@ -504,9 +509,9 @@ func TestUnknownCriticalExtension(t *testing.T) {
 
 	oids := []asn1.ObjectIdentifier{
 		// This OID is in the PKIX arc, but unknown.
-		asn1.ObjectIdentifier{2, 5, 29, 999999},
+		{2, 5, 29, 999999},
 		// This is a nonsense, unassigned OID.
-		asn1.ObjectIdentifier{1, 2, 3, 4},
+		{1, 2, 3, 4},
 	}
 
 	for _, oid := range oids {
@@ -1074,6 +1079,40 @@ func TestParseCertificateRequest(t *testing.T) {
 	}
 }
 
+func TestCriticalFlagInCSRRequestedExtensions(t *testing.T) {
+	// This CSR contains an extension request where the extensions have a
+	// critical flag in them. In the past we failed to handle this.
+	const csrBase64 = "MIICrTCCAZUCAQIwMzEgMB4GA1UEAwwXU0NFUCBDQSBmb3IgRGV2ZWxlciBTcmwxDzANBgNVBAsMBjQzNTk3MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALFMAJ7Zy9YyfgbNlbUWAW0LalNRMPs7aXmLANsCpjhnw3lLlfDPaLeWyKh1nK5I5ojaJOW6KIOSAcJkDUe3rrE0wR0RVt3UxArqs0R/ND3u5Q+bDQY2X1HAFUHzUzcdm5JRAIA355v90teMckaWAIlkRQjDE22Lzc6NAl64KOd1rqOUNj8+PfX6fSo20jm94Pp1+a6mfk3G/RUWVuSm7owO5DZI/Fsi2ijdmb4NUar6K/bDKYTrDFkzcqAyMfP3TitUtBp19Mp3B1yAlHjlbp/r5fSSXfOGHZdgIvp0WkLuK2u5eQrX5l7HMB/5epgUs3HQxKY6ljhh5wAjDwz//LsC [...]
+
+	csrBytes := fromBase64(csrBase64)
+	csr, err := ParseCertificateRequest(csrBytes)
+	if err != nil {
+		t.Fatalf("failed to parse CSR: %s", err)
+	}
+
+	expected := []struct {
+		Id    asn1.ObjectIdentifier
+		Value []byte
+	}{
+		{oidExtensionBasicConstraints, fromBase64("MAYBAf8CAQA=")},
+		{oidExtensionKeyUsage, fromBase64("AwIChA==")},
+	}
+
+	if n := len(csr.Extensions); n != len(expected) {
+		t.Fatalf("expected to find %d extensions but found %d", len(expected), n)
+	}
+
+	for i, extension := range csr.Extensions {
+		if !extension.Id.Equal(expected[i].Id) {
+			t.Fatalf("extension #%d has unexpected type %v (expected %v)", i, extension.Id, expected[i].Id)
+		}
+
+		if !bytes.Equal(extension.Value, expected[i].Value) {
+			t.Fatalf("extension #%d has unexpected contents %x (expected %x)", i, extension.Value, expected[i].Value)
+		}
+	}
+}
+
 func TestMaxPathLen(t *testing.T) {
 	block, _ := pem.Decode([]byte(pemPrivateKey))
 	rsaPriv, err := ParsePKCS1PrivateKey(block.Bytes)
@@ -1159,6 +1198,29 @@ func TestASN1BitLength(t *testing.T) {
 	}
 }
 
+func TestVerifyEmptyCertificate(t *testing.T) {
+	if _, err := new(Certificate).Verify(VerifyOptions{}); err != errNotParsed {
+		t.Errorf("Verifying empty certificate resulted in unexpected error: %q (wanted %q)", err, errNotParsed)
+	}
+}
+
+func TestInsecureAlgorithmErrorString(t *testing.T) {
+	tests := []struct {
+		sa   SignatureAlgorithm
+		want string
+	}{
+		{MD2WithRSA, "x509: cannot verify signature: insecure algorithm MD2-RSA"},
+		{-1, "x509: cannot verify signature: insecure algorithm -1"},
+		{0, "x509: cannot verify signature: insecure algorithm 0"},
+		{9999, "x509: cannot verify signature: insecure algorithm 9999"},
+	}
+	for i, tt := range tests {
+		if got := fmt.Sprint(InsecureAlgorithmError(tt.sa)); got != tt.want {
+			t.Errorf("%d. mismatch.\n got: %s\nwant: %s\n", i, got, tt.want)
+		}
+	}
+}
+
 // These CSR was generated with OpenSSL:
 //  openssl req -out CSR.csr -new -sha256 -nodes -keyout privateKey.key -config openssl.cnf
 //
@@ -1176,3 +1238,36 @@ var csrBase64Array = [...]string{
 	// Both [ v3_req ] and [ req_attributes ]
 	"MIIDaTCCAlECAQAwfjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEUMBIGA1UEAwwLQ29tbW9uIE5hbWUxITAfBgkqhkiG9w0BCQEWEnRlc3RAZW1haWwuYWRkcmVzczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK1GY4YFx2ujlZEOJxQVYmsjUnLsd5nFVnNpLE4cV+77sgv9NPNlB8uhn3MXt5leD34rm/2BisCHOifPucYlSrszo2beuKhvwn4+2FxDmWtBEMu/QA16L5IvoOfYZm/gJTsPwKDqvaR0tTU67a9OtxwNTBMI56YKtmwd/o8d3hYv9cg+9ZGAZ/gKONcg/OWYx/XRh6bd0g8DMbCikpWgXKDsvvK1Nk+VtkDO1JxuBaj4Lz/p/MifTfnHoqHxWOWl4EaTs4 [...]
 }
+
+var md5cert = `
+-----BEGIN CERTIFICATE-----
+MIIB4TCCAUoCCQCfmw3vMgPS5TANBgkqhkiG9w0BAQQFADA1MQswCQYDVQQGEwJB
+VTETMBEGA1UECBMKU29tZS1TdGF0ZTERMA8GA1UEChMITUQ1IEluYy4wHhcNMTUx
+MjAzMTkyOTMyWhcNMjkwODEyMTkyOTMyWjA1MQswCQYDVQQGEwJBVTETMBEGA1UE
+CBMKU29tZS1TdGF0ZTERMA8GA1UEChMITUQ1IEluYy4wgZ8wDQYJKoZIhvcNAQEB
+BQADgY0AMIGJAoGBANrq2nhLQj5mlXbpVX3QUPhfEm/vdEqPkoWtR/jRZIWm4WGf
+Wpq/LKHJx2Pqwn+t117syN8l4U5unyAi1BJSXjBwPZNd7dXjcuJ+bRLV7FZ/iuvs
+cfYyQQFTxan4TaJMd0x1HoNDbNbjHa02IyjjYE/r3mb/PIg+J2t5AZEh80lPAgMB
+AAEwDQYJKoZIhvcNAQEEBQADgYEAjGzp3K3ey/YfKHohf33yHHWd695HQxDAP+wY
+cs9/TAyLR+gJzJP7d18EcDDLJWVi7bhfa4EAD86di05azOh9kWSn4b3o9QYRGCSw
+GNnI3Zk0cwNKA49hZntKKiy22DhRk7JAHF01d6Bu3KkHkmENrtJ+zj/+159WAnUa
+qViorq4=
+-----END CERTIFICATE-----
+`
+
+func TestMD5(t *testing.T) {
+	pemBlock, _ := pem.Decode([]byte(md5cert))
+	cert, err := ParseCertificate(pemBlock.Bytes)
+	if err != nil {
+		t.Fatalf("failed to parse certificate: %s", err)
+	}
+	if sa := cert.SignatureAlgorithm; sa != MD5WithRSA {
+		t.Errorf("signature algorithm is %v, want %v", sa, MD5WithRSA)
+	}
+	if err = cert.CheckSignatureFrom(cert); err == nil {
+		t.Fatalf("certificate verification succeeded incorrectly")
+	}
+	if _, ok := err.(InsecureAlgorithmError); !ok {
+		t.Fatalf("certificate verification returned %v (%T), wanted InsecureAlgorithmError", err, err)
+	}
+}
diff --git a/src/database/sql/convert.go b/src/database/sql/convert.go
index c0b38a2..740fd9d 100644
--- a/src/database/sql/convert.go
+++ b/src/database/sql/convert.go
@@ -12,6 +12,7 @@ import (
 	"fmt"
 	"reflect"
 	"strconv"
+	"time"
 )
 
 var errNilPtr = errors.New("destination pointer is nil") // embedded in descriptive error
@@ -127,6 +128,18 @@ func convertAssign(dest, src interface{}) error {
 			*d = s
 			return nil
 		}
+	case time.Time:
+		switch d := dest.(type) {
+		case *string:
+			*d = s.Format(time.RFC3339Nano)
+			return nil
+		case *[]byte:
+			if d == nil {
+				return errNilPtr
+			}
+			*d = []byte(s.Format(time.RFC3339Nano))
+			return nil
+		}
 	case nil:
 		switch d := dest.(type) {
 		case *interface{}:
@@ -203,11 +216,16 @@ func convertAssign(dest, src interface{}) error {
 	}
 
 	dv := reflect.Indirect(dpv)
-	if dv.Kind() == sv.Kind() {
+	if sv.IsValid() && sv.Type().AssignableTo(dv.Type()) {
 		dv.Set(sv)
 		return nil
 	}
 
+	if dv.Kind() == sv.Kind() && sv.Type().ConvertibleTo(dv.Type()) {
+		dv.Set(sv.Convert(dv.Type()))
+		return nil
+	}
+
 	switch dv.Kind() {
 	case reflect.Ptr:
 		if src == nil {
@@ -221,7 +239,8 @@ func convertAssign(dest, src interface{}) error {
 		s := asString(src)
 		i64, err := strconv.ParseInt(s, 10, dv.Type().Bits())
 		if err != nil {
-			return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
+			err = strconvErr(err)
+			return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
 		}
 		dv.SetInt(i64)
 		return nil
@@ -229,7 +248,8 @@ func convertAssign(dest, src interface{}) error {
 		s := asString(src)
 		u64, err := strconv.ParseUint(s, 10, dv.Type().Bits())
 		if err != nil {
-			return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
+			err = strconvErr(err)
+			return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
 		}
 		dv.SetUint(u64)
 		return nil
@@ -237,13 +257,21 @@ func convertAssign(dest, src interface{}) error {
 		s := asString(src)
 		f64, err := strconv.ParseFloat(s, dv.Type().Bits())
 		if err != nil {
-			return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
+			err = strconvErr(err)
+			return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
 		}
 		dv.SetFloat(f64)
 		return nil
 	}
 
-	return fmt.Errorf("unsupported driver -> Scan pair: %T -> %T", src, dest)
+	return fmt.Errorf("unsupported Scan, storing driver.Value type %T into type %T", src, dest)
+}
+
+func strconvErr(err error) error {
+	if ne, ok := err.(*strconv.NumError); ok {
+		return ne.Err
+	}
+	return err
 }
 
 func cloneBytes(b []byte) []byte {
diff --git a/src/database/sql/convert_test.go b/src/database/sql/convert_test.go
index 98af9fb..342875e 100644
--- a/src/database/sql/convert_test.go
+++ b/src/database/sql/convert_test.go
@@ -16,23 +16,28 @@ import (
 var someTime = time.Unix(123, 0)
 var answer int64 = 42
 
+type userDefined float64
+
+type userDefinedSlice []int
+
 type conversionTest struct {
 	s, d interface{} // source and destination
 
 	// following are used if they're non-zero
-	wantint   int64
-	wantuint  uint64
-	wantstr   string
-	wantbytes []byte
-	wantraw   RawBytes
-	wantf32   float32
-	wantf64   float64
-	wanttime  time.Time
-	wantbool  bool // used if d is of type *bool
-	wanterr   string
-	wantiface interface{}
-	wantptr   *int64 // if non-nil, *d's pointed value must be equal to *wantptr
-	wantnil   bool   // if true, *d must be *int64(nil)
+	wantint    int64
+	wantuint   uint64
+	wantstr    string
+	wantbytes  []byte
+	wantraw    RawBytes
+	wantf32    float32
+	wantf64    float64
+	wanttime   time.Time
+	wantbool   bool // used if d is of type *bool
+	wanterr    string
+	wantiface  interface{}
+	wantptr    *int64 // if non-nil, *d's pointed value must be equal to *wantptr
+	wantnil    bool   // if true, *d must be *int64(nil)
+	wantusrdef userDefined
 }
 
 // Target variables for scanning into.
@@ -72,6 +77,14 @@ var conversionTests = []conversionTest{
 	{s: uint64(123), d: &scanstr, wantstr: "123"},
 	{s: 1.5, d: &scanstr, wantstr: "1.5"},
 
+	// From time.Time:
+	{s: time.Unix(1, 0).UTC(), d: &scanstr, wantstr: "1970-01-01T00:00:01Z"},
+	{s: time.Unix(1453874597, 0).In(time.FixedZone("here", -3600*8)), d: &scanstr, wantstr: "2016-01-26T22:03:17-08:00"},
+	{s: time.Unix(1, 2).UTC(), d: &scanstr, wantstr: "1970-01-01T00:00:01.000000002Z"},
+	{s: time.Time{}, d: &scanstr, wantstr: "0001-01-01T00:00:00Z"},
+	{s: time.Unix(1, 2).UTC(), d: &scanbytes, wantbytes: []byte("1970-01-01T00:00:01.000000002Z")},
+	{s: time.Unix(1, 2).UTC(), d: &scaniface, wantiface: time.Unix(1, 2).UTC()},
+
 	// To []byte
 	{s: nil, d: &scanbytes, wantbytes: nil},
 	{s: "string", d: &scanbytes, wantbytes: []byte("string")},
@@ -99,10 +112,16 @@ var conversionTests = []conversionTest{
 
 	// Strings to integers
 	{s: "255", d: &scanuint8, wantuint: 255},
-	{s: "256", d: &scanuint8, wanterr: `converting string "256" to a uint8: strconv.ParseUint: parsing "256": value out of range`},
+	{s: "256", d: &scanuint8, wanterr: "converting driver.Value type string (\"256\") to a uint8: value out of range"},
 	{s: "256", d: &scanuint16, wantuint: 256},
 	{s: "-1", d: &scanint, wantint: -1},
-	{s: "foo", d: &scanint, wanterr: `converting string "foo" to a int: strconv.ParseInt: parsing "foo": invalid syntax`},
+	{s: "foo", d: &scanint, wanterr: "converting driver.Value type string (\"foo\") to a int: invalid syntax"},
+
+	// int64 to smaller integers
+	{s: int64(5), d: &scanuint8, wantuint: 5},
+	{s: int64(256), d: &scanuint8, wanterr: "converting driver.Value type int64 (\"256\") to a uint8: value out of range"},
+	{s: int64(256), d: &scanuint16, wantuint: 256},
+	{s: int64(65536), d: &scanuint16, wanterr: "converting driver.Value type int64 (\"65536\") to a uint16: value out of range"},
 
 	// True bools
 	{s: true, d: &scanbool, wantbool: true},
@@ -145,6 +164,15 @@ var conversionTests = []conversionTest{
 	{s: true, d: &scaniface, wantiface: true},
 	{s: nil, d: &scaniface},
 	{s: []byte(nil), d: &scaniface, wantiface: []byte(nil)},
+
+	// To a user-defined type
+	{s: 1.5, d: new(userDefined), wantusrdef: 1.5},
+	{s: int64(123), d: new(userDefined), wantusrdef: 123},
+	{s: "1.5", d: new(userDefined), wantusrdef: 1.5},
+	{s: []byte{1, 2, 3}, d: new(userDefinedSlice), wanterr: `unsupported Scan, storing driver.Value type []uint8 into type *sql.userDefinedSlice`},
+
+	// Other errors
+	{s: complex(1, 2), d: &scanstr, wanterr: `unsupported Scan, storing driver.Value type complex128 into type *string`},
 }
 
 func intPtrValue(intptr interface{}) interface{} {
@@ -228,6 +256,9 @@ func TestConversions(t *testing.T) {
 				}
 			}
 		}
+		if ct.wantusrdef != 0 && ct.wantusrdef != *ct.d.(*userDefined) {
+			errf("want userDefined %f, got %f", ct.wantusrdef, *ct.d.(*userDefined))
+		}
 	}
 }
 
diff --git a/src/database/sql/driver/types.go b/src/database/sql/driver/types.go
index 3305354..bc54784 100644
--- a/src/database/sql/driver/types.go
+++ b/src/database/sql/driver/types.go
@@ -200,10 +200,15 @@ func IsScanValue(v interface{}) bool {
 // ValueConverter that's used when a Stmt doesn't implement
 // ColumnConverter.
 //
-// DefaultParameterConverter returns the given value directly if
-// IsValue(value).  Otherwise integer type are converted to
-// int64, floats to float64, and strings to []byte.  Other types are
-// an error.
+// DefaultParameterConverter returns its argument directly if
+// IsValue(arg). Otherwise, if the argument implements Valuer, its
+// Value method is used to return a Value. As a fallback, the provided
+// argument's underlying type is used to convert it to a Value:
+// underlying integer types are converted to int64, floats to float64,
+// and strings to []byte. If the argument is a nil pointer,
+// ConvertValue returns a nil Value. If the argument is a non-nil
+// pointer, it is dereferenced and ConvertValue is called
+// recursively. Other types are an error.
 var DefaultParameterConverter defaultConverter
 
 type defaultConverter struct{}
diff --git a/src/database/sql/fakedb_test.go b/src/database/sql/fakedb_test.go
index 8cbbb29..b5ff121 100644
--- a/src/database/sql/fakedb_test.go
+++ b/src/database/sql/fakedb_test.go
@@ -33,6 +33,9 @@ var _ = log.Printf
 //   INSERT|<tablename>|col=val,col2=val2,col3=?
 //   SELECT|<tablename>|projectcol1,projectcol2|filtercol=?,filtercol2=?
 //
+// Any of these can be preceded by PANIC|<method>|, to cause the
+// named method on fakeStmt to panic.
+//
 // When opening a fakeDriver's database, it starts empty with no
 // tables.  All tables and data are stored in memory only.
 type fakeDriver struct {
@@ -111,6 +114,7 @@ type fakeStmt struct {
 
 	cmd   string
 	table string
+	panic string
 
 	closed bool
 
@@ -153,12 +157,32 @@ func TestDrivers(t *testing.T) {
 	}
 }
 
+// hook to simulate connection failures
+var hookOpenErr struct {
+	sync.Mutex
+	fn func() error
+}
+
+func setHookOpenErr(fn func() error) {
+	hookOpenErr.Lock()
+	defer hookOpenErr.Unlock()
+	hookOpenErr.fn = fn
+}
+
 // Supports dsn forms:
 //    <dbname>
 //    <dbname>;<opts>  (only currently supported option is `badConn`,
 //                      which causes driver.ErrBadConn to be returned on
 //                      every other conn.Begin())
 func (d *fakeDriver) Open(dsn string) (driver.Conn, error) {
+	hookOpenErr.Lock()
+	fn := hookOpenErr.fn
+	hookOpenErr.Unlock()
+	if fn != nil {
+		if err := fn(); err != nil {
+			return nil, err
+		}
+	}
 	parts := strings.Split(dsn, ";")
 	if len(parts) < 1 {
 		return nil, errors.New("fakedb: no database name")
@@ -479,9 +503,15 @@ func (c *fakeConn) Prepare(query string) (driver.Stmt, error) {
 	if len(parts) < 1 {
 		return nil, errf("empty query")
 	}
+	stmt := &fakeStmt{q: query, c: c}
+	if len(parts) >= 3 && parts[0] == "PANIC" {
+		stmt.panic = parts[1]
+		parts = parts[2:]
+	}
 	cmd := parts[0]
+	stmt.cmd = cmd
 	parts = parts[1:]
-	stmt := &fakeStmt{q: query, c: c, cmd: cmd}
+
 	c.incrStat(&c.stmtsMade)
 	switch cmd {
 	case "WIPE":
@@ -504,6 +534,9 @@ func (c *fakeConn) Prepare(query string) (driver.Stmt, error) {
 }
 
 func (s *fakeStmt) ColumnConverter(idx int) driver.ValueConverter {
+	if s.panic == "ColumnConverter" {
+		panic(s.panic)
+	}
 	if len(s.placeholderConverter) == 0 {
 		return driver.DefaultParameterConverter
 	}
@@ -511,6 +544,9 @@ func (s *fakeStmt) ColumnConverter(idx int) driver.ValueConverter {
 }
 
 func (s *fakeStmt) Close() error {
+	if s.panic == "Close" {
+		panic(s.panic)
+	}
 	if s.c == nil {
 		panic("nil conn in fakeStmt.Close")
 	}
@@ -530,6 +566,9 @@ var errClosed = errors.New("fakedb: statement has been closed")
 var hookExecBadConn func() bool
 
 func (s *fakeStmt) Exec(args []driver.Value) (driver.Result, error) {
+	if s.panic == "Exec" {
+		panic(s.panic)
+	}
 	if s.closed {
 		return nil, errClosed
 	}
@@ -614,6 +653,9 @@ func (s *fakeStmt) execInsert(args []driver.Value, doInsert bool) (driver.Result
 var hookQueryBadConn func() bool
 
 func (s *fakeStmt) Query(args []driver.Value) (driver.Rows, error) {
+	if s.panic == "Query" {
+		panic(s.panic)
+	}
 	if s.closed {
 		return nil, errClosed
 	}
@@ -696,16 +738,31 @@ rows:
 }
 
 func (s *fakeStmt) NumInput() int {
+	if s.panic == "NumInput" {
+		panic(s.panic)
+	}
 	return s.placeholders
 }
 
+// hook to simulate broken connections
+var hookCommitBadConn func() bool
+
 func (tx *fakeTx) Commit() error {
 	tx.c.currTx = nil
+	if hookCommitBadConn != nil && hookCommitBadConn() {
+		return driver.ErrBadConn
+	}
 	return nil
 }
 
+// hook to simulate broken connections
+var hookRollbackBadConn func() bool
+
 func (tx *fakeTx) Rollback() error {
 	tx.c.currTx = nil
+	if hookRollbackBadConn != nil && hookRollbackBadConn() {
+		return driver.ErrBadConn
+	}
 	return nil
 }
 
diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go
index aaa4ea2..d8e7cb7 100644
--- a/src/database/sql/sql.go
+++ b/src/database/sql/sql.go
@@ -21,13 +21,17 @@ import (
 	"sort"
 	"sync"
 	"sync/atomic"
+	"time"
 )
 
 var (
-	driversMu sync.Mutex
+	driversMu sync.RWMutex
 	drivers   = make(map[string]driver.Driver)
 )
 
+// nowFunc returns the current time; it's overridden in tests.
+var nowFunc = time.Now
+
 // Register makes a database driver available by the provided name.
 // If Register is called twice with the same name or if driver is nil,
 // it panics.
@@ -52,8 +56,8 @@ func unregisterAllDrivers() {
 
 // Drivers returns a sorted list of the names of the registered drivers.
 func Drivers() []string {
-	driversMu.Lock()
-	defer driversMu.Unlock()
+	driversMu.RLock()
+	defer driversMu.RUnlock()
 	var list []string
 	for name := range drivers {
 		list = append(list, name)
@@ -185,8 +189,7 @@ func (n NullBool) Value() (driver.Value, error) {
 type Scanner interface {
 	// Scan assigns a value from a database driver.
 	//
-	// The src value will be of one of the following restricted
-	// set of types:
+	// The src value will be of one of the following types:
 	//
 	//    int64
 	//    float64
@@ -229,19 +232,20 @@ type DB struct {
 	mu           sync.Mutex // protects following fields
 	freeConn     []*driverConn
 	connRequests []chan connRequest
-	numOpen      int
-	pendingOpens int
+	numOpen      int // number of opened and pending open connections
 	// Used to signal the need for new connections
 	// a goroutine running connectionOpener() reads on this chan and
 	// maybeOpenNewConnections sends on the chan (one send per needed connection)
 	// It is closed during db.Close(). The close tells the connectionOpener
 	// goroutine to exit.
-	openerCh chan struct{}
-	closed   bool
-	dep      map[finalCloser]depSet
-	lastPut  map[*driverConn]string // stacktrace of last conn's put; debug only
-	maxIdle  int                    // zero means defaultMaxIdleConns; negative means 0
-	maxOpen  int                    // <= 0 means unlimited
+	openerCh    chan struct{}
+	closed      bool
+	dep         map[finalCloser]depSet
+	lastPut     map[*driverConn]string // stacktrace of last conn's put; debug only
+	maxIdle     int                    // zero means defaultMaxIdleConns; negative means 0
+	maxOpen     int                    // <= 0 means unlimited
+	maxLifetime time.Duration          // maximum amount of time a connection may be reused
+	cleanerCh   chan struct{}
 }
 
 // connReuseStrategy determines how (*DB).conn returns database connections.
@@ -261,7 +265,8 @@ const (
 // interfaces returned via that Conn, such as calls on Tx, Stmt,
 // Result, Rows)
 type driverConn struct {
-	db *DB
+	db        *DB
+	createdAt time.Time
 
 	sync.Mutex  // guards following
 	ci          driver.Conn
@@ -285,6 +290,13 @@ func (dc *driverConn) removeOpenStmt(si driver.Stmt) {
 	delete(dc.openStmt, si)
 }
 
+func (dc *driverConn) expired(timeout time.Duration) bool {
+	if timeout <= 0 {
+		return false
+	}
+	return dc.createdAt.Add(timeout).Before(nowFunc())
+}
+
 func (dc *driverConn) prepareLocked(query string) (driver.Stmt, error) {
 	si, err := dc.ci.Prepare(query)
 	if err == nil {
@@ -441,7 +453,7 @@ func (db *DB) removeDepLocked(x finalCloser, dep interface{}) func() error {
 	}
 }
 
-// This is the size of the connectionOpener request chan (dn.openerCh).
+// This is the size of the connectionOpener request chan (DB.openerCh).
 // This value should be larger than the maximum typical value
 // used for db.maxOpen. If maxOpen is significantly larger than
 // connectionRequestQueueSize then it is possible for ALL calls into the *DB
@@ -466,9 +478,9 @@ var connectionRequestQueueSize = 1000000
 // function should be called just once. It is rarely necessary to
 // close a DB.
 func Open(driverName, dataSourceName string) (*DB, error) {
-	driversMu.Lock()
+	driversMu.RLock()
 	driveri, ok := drivers[driverName]
-	driversMu.Unlock()
+	driversMu.RUnlock()
 	if !ok {
 		return nil, fmt.Errorf("sql: unknown driver %q (forgotten import?)", driverName)
 	}
@@ -507,6 +519,9 @@ func (db *DB) Close() error {
 		return nil
 	}
 	close(db.openerCh)
+	if db.cleanerCh != nil {
+		close(db.cleanerCh)
+	}
 	var err error
 	fns := make([]func() error, 0, len(db.freeConn))
 	for _, dc := range db.freeConn {
@@ -595,6 +610,84 @@ func (db *DB) SetMaxOpenConns(n int) {
 	}
 }
 
+// SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
+//
+// Expired connections may be closed lazily before reuse.
+//
+// If d <= 0, connections are reused forever.
+func (db *DB) SetConnMaxLifetime(d time.Duration) {
+	if d < 0 {
+		d = 0
+	}
+	db.mu.Lock()
+	// wake cleaner up when lifetime is shortened.
+	if d > 0 && d < db.maxLifetime && db.cleanerCh != nil {
+		select {
+		case db.cleanerCh <- struct{}{}:
+		default:
+		}
+	}
+	db.maxLifetime = d
+	db.startCleanerLocked()
+	db.mu.Unlock()
+}
+
+// startCleanerLocked starts connectionCleaner if needed.
+func (db *DB) startCleanerLocked() {
+	if db.maxLifetime > 0 && db.numOpen > 0 && db.cleanerCh == nil {
+		db.cleanerCh = make(chan struct{}, 1)
+		go db.connectionCleaner(db.maxLifetime)
+	}
+}
+
+func (db *DB) connectionCleaner(d time.Duration) {
+	const minInterval = time.Second
+
+	if d < minInterval {
+		d = minInterval
+	}
+	t := time.NewTimer(d)
+
+	for {
+		select {
+		case <-t.C:
+		case <-db.cleanerCh: // maxLifetime was changed or db was closed.
+		}
+
+		db.mu.Lock()
+		d = db.maxLifetime
+		if db.closed || db.numOpen == 0 || d <= 0 {
+			db.cleanerCh = nil
+			db.mu.Unlock()
+			return
+		}
+
+		expiredSince := nowFunc().Add(-d)
+		var closing []*driverConn
+		for i := 0; i < len(db.freeConn); i++ {
+			c := db.freeConn[i]
+			if c.createdAt.Before(expiredSince) {
+				closing = append(closing, c)
+				last := len(db.freeConn) - 1
+				db.freeConn[i] = db.freeConn[last]
+				db.freeConn[last] = nil
+				db.freeConn = db.freeConn[:last]
+				i--
+			}
+		}
+		db.mu.Unlock()
+
+		for _, c := range closing {
+			c.Close()
+		}
+
+		if d < minInterval {
+			d = minInterval
+		}
+		t.Reset(d)
+	}
+}
+
 // DBStats contains database statistics.
 type DBStats struct {
 	// OpenConnections is the number of open connections to the database.
@@ -615,15 +708,15 @@ func (db *DB) Stats() DBStats {
 // If there are connRequests and the connection limit hasn't been reached,
 // then tell the connectionOpener to open new connections.
 func (db *DB) maybeOpenNewConnections() {
-	numRequests := len(db.connRequests) - db.pendingOpens
+	numRequests := len(db.connRequests)
 	if db.maxOpen > 0 {
-		numCanOpen := db.maxOpen - (db.numOpen + db.pendingOpens)
+		numCanOpen := db.maxOpen - db.numOpen
 		if numRequests > numCanOpen {
 			numRequests = numCanOpen
 		}
 	}
 	for numRequests > 0 {
-		db.pendingOpens++
+		db.numOpen++ // optimistically
 		numRequests--
 		db.openerCh <- struct{}{}
 	}
@@ -638,6 +731,9 @@ func (db *DB) connectionOpener() {
 
 // Open one new connection
 func (db *DB) openNewConnection() {
+	// maybeOpenNewConnctions has already executed db.numOpen++ before it sent
+	// on db.openerCh. This function must execute db.numOpen-- if the
+	// connection fails or is closed before returning.
 	ci, err := db.driver.Open(db.dsn)
 	db.mu.Lock()
 	defer db.mu.Unlock()
@@ -645,21 +741,24 @@ func (db *DB) openNewConnection() {
 		if err == nil {
 			ci.Close()
 		}
+		db.numOpen--
 		return
 	}
-	db.pendingOpens--
 	if err != nil {
+		db.numOpen--
 		db.putConnDBLocked(nil, err)
+		db.maybeOpenNewConnections()
 		return
 	}
 	dc := &driverConn{
-		db: db,
-		ci: ci,
+		db:        db,
+		createdAt: nowFunc(),
+		ci:        ci,
 	}
 	if db.putConnDBLocked(dc, err) {
 		db.addDepLocked(dc, dc)
-		db.numOpen++
 	} else {
+		db.numOpen--
 		ci.Close()
 	}
 }
@@ -681,6 +780,7 @@ func (db *DB) conn(strategy connReuseStrategy) (*driverConn, error) {
 		db.mu.Unlock()
 		return nil, errDBClosed
 	}
+	lifetime := db.maxLifetime
 
 	// Prefer a free connection, if possible.
 	numFree := len(db.freeConn)
@@ -690,6 +790,10 @@ func (db *DB) conn(strategy connReuseStrategy) (*driverConn, error) {
 		db.freeConn = db.freeConn[:numFree-1]
 		conn.inUse = true
 		db.mu.Unlock()
+		if conn.expired(lifetime) {
+			conn.Close()
+			return nil, driver.ErrBadConn
+		}
 		return conn, nil
 	}
 
@@ -701,7 +805,14 @@ func (db *DB) conn(strategy connReuseStrategy) (*driverConn, error) {
 		req := make(chan connRequest, 1)
 		db.connRequests = append(db.connRequests, req)
 		db.mu.Unlock()
-		ret := <-req
+		ret, ok := <-req
+		if !ok {
+			return nil, errDBClosed
+		}
+		if ret.err == nil && ret.conn.expired(lifetime) {
+			ret.conn.Close()
+			return nil, driver.ErrBadConn
+		}
 		return ret.conn, ret.err
 	}
 
@@ -711,13 +822,15 @@ func (db *DB) conn(strategy connReuseStrategy) (*driverConn, error) {
 	if err != nil {
 		db.mu.Lock()
 		db.numOpen-- // correct for earlier optimism
+		db.maybeOpenNewConnections()
 		db.mu.Unlock()
 		return nil, err
 	}
 	db.mu.Lock()
 	dc := &driverConn{
-		db: db,
-		ci: ci,
+		db:        db,
+		createdAt: nowFunc(),
+		ci:        ci,
 	}
 	db.addDepLocked(dc, dc)
 	dc.inUse = true
@@ -827,6 +940,7 @@ func (db *DB) putConnDBLocked(dc *driverConn, err error) bool {
 		return true
 	} else if err == nil && !db.closed && db.maxIdleConnsLocked() > len(db.freeConn) {
 		db.freeConn = append(db.freeConn, dc)
+		db.startCleanerLocked()
 		return true
 	}
 	return false
@@ -1022,7 +1136,7 @@ func (db *DB) queryConn(dc *driverConn, releaseConn func(error), query string, a
 }
 
 // QueryRow executes a query that is expected to return at most one row.
-// QueryRow always return a non-nil value. Errors are deferred until
+// QueryRow always returns a non-nil value. Errors are deferred until
 // Row's Scan method is called.
 func (db *DB) QueryRow(query string, args ...interface{}) *Row {
 	rows, err := db.Query(query, args...)
@@ -1103,12 +1217,12 @@ type Tx struct {
 
 var ErrTxDone = errors.New("sql: Transaction has already been committed or rolled back")
 
-func (tx *Tx) close() {
+func (tx *Tx) close(err error) {
 	if tx.done {
 		panic("double close") // internal error
 	}
 	tx.done = true
-	tx.db.putConn(tx.dc, nil)
+	tx.db.putConn(tx.dc, err)
 	tx.dc = nil
 	tx.txi = nil
 }
@@ -1134,13 +1248,13 @@ func (tx *Tx) Commit() error {
 	if tx.done {
 		return ErrTxDone
 	}
-	defer tx.close()
 	tx.dc.Lock()
 	err := tx.txi.Commit()
 	tx.dc.Unlock()
 	if err != driver.ErrBadConn {
 		tx.closePrepared()
 	}
+	tx.close(err)
 	return err
 }
 
@@ -1149,13 +1263,13 @@ func (tx *Tx) Rollback() error {
 	if tx.done {
 		return ErrTxDone
 	}
-	defer tx.close()
 	tx.dc.Lock()
 	err := tx.txi.Rollback()
 	tx.dc.Unlock()
 	if err != driver.ErrBadConn {
 		tx.closePrepared()
 	}
+	tx.close(err)
 	return err
 }
 
@@ -1296,7 +1410,7 @@ func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error) {
 }
 
 // QueryRow executes a query that is expected to return at most one row.
-// QueryRow always return a non-nil value. Errors are deferred until
+// QueryRow always returns a non-nil value. Errors are deferred until
 // Row's Scan method is called.
 func (tx *Tx) QueryRow(query string, args ...interface{}) *Row {
 	rows, err := tx.Query(query, args...)
@@ -1362,10 +1476,14 @@ func (s *Stmt) Exec(args ...interface{}) (Result, error) {
 	return nil, driver.ErrBadConn
 }
 
-func resultFromStatement(ds driverStmt, args ...interface{}) (Result, error) {
+func driverNumInput(ds driverStmt) int {
 	ds.Lock()
-	want := ds.si.NumInput()
-	ds.Unlock()
+	defer ds.Unlock() // in case NumInput panics
+	return ds.si.NumInput()
+}
+
+func resultFromStatement(ds driverStmt, args ...interface{}) (Result, error) {
+	want := driverNumInput(ds)
 
 	// -1 means the driver doesn't know how to count the number of
 	// placeholders, so we won't sanity check input here and instead let the
@@ -1380,8 +1498,8 @@ func resultFromStatement(ds driverStmt, args ...interface{}) (Result, error) {
 	}
 
 	ds.Lock()
+	defer ds.Unlock()
 	resi, err := ds.si.Exec(dargs)
-	ds.Unlock()
 	if err != nil {
 		return nil, err
 	}
@@ -1576,9 +1694,9 @@ func (s *Stmt) Close() error {
 	s.closed = true
 
 	if s.tx != nil {
-		s.txsi.Close()
+		err := s.txsi.Close()
 		s.mu.Unlock()
-		return nil
+		return err
 	}
 	s.mu.Unlock()
 
@@ -1667,17 +1785,56 @@ func (rs *Rows) Columns() ([]string, error) {
 }
 
 // Scan copies the columns in the current row into the values pointed
-// at by dest.
+// at by dest. The number of values in dest must be the same as the
+// number of columns in Rows.
+//
+// Scan converts columns read from the database into the following
+// common Go types and special types provided by the sql package:
+//
+//    *string
+//    *[]byte
+//    *int, *int8, *int16, *int32, *int64
+//    *uint, *uint8, *uint16, *uint32, *uint64
+//    *bool
+//    *float32, *float64
+//    *interface{}
+//    *RawBytes
+//    any type implementing Scanner (see Scanner docs)
+//
+// In the most simple case, if the type of the value from the source
+// column is an integer, bool or string type T and dest is of type *T,
+// Scan simply assigns the value through the pointer.
 //
-// If an argument has type *[]byte, Scan saves in that argument a copy
-// of the corresponding data. The copy is owned by the caller and can
-// be modified and held indefinitely. The copy can be avoided by using
-// an argument of type *RawBytes instead; see the documentation for
-// RawBytes for restrictions on its use.
+// Scan also converts between string and numeric types, as long as no
+// information would be lost. While Scan stringifies all numbers
+// scanned from numeric database columns into *string, scans into
+// numeric types are checked for overflow. For example, a float64 with
+// value 300 or a string with value "300" can scan into a uint16, but
+// not into a uint8, though float64(255) or "255" can scan into a
+// uint8. One exception is that scans of some float64 numbers to
+// strings may lose information when stringifying. In general, scan
+// floating point columns into *float64.
+//
+// If a dest argument has type *[]byte, Scan saves in that argument a
+// copy of the corresponding data. The copy is owned by the caller and
+// can be modified and held indefinitely. The copy can be avoided by
+// using an argument of type *RawBytes instead; see the documentation
+// for RawBytes for restrictions on its use.
 //
 // If an argument has type *interface{}, Scan copies the value
-// provided by the underlying driver without conversion. If the value
-// is of type []byte, a copy is made and the caller owns the result.
+// provided by the underlying driver without conversion. When scanning
+// from a source value of type []byte to *interface{}, a copy of the
+// slice is made and the caller owns the result.
+//
+// Source values of type time.Time may be scanned into values of type
+// *time.Time, *interface{}, *string, or *[]byte. When converting to
+// the latter two, time.Format3339Nano is used.
+//
+// Source values of type bool may be scanned into types *bool,
+// *interface{}, *string, *[]byte, or *RawBytes.
+//
+// For scanning into *bool, the source may be true, false, 1, 0, or
+// string inputs parseable by strconv.ParseBool.
 func (rs *Rows) Scan(dest ...interface{}) error {
 	if rs.closed {
 		return errors.New("sql: Rows are closed")
@@ -1726,8 +1883,9 @@ type Row struct {
 }
 
 // Scan copies the columns from the matched row into the values
-// pointed at by dest.  If more than one row matches the query,
-// Scan uses the first row and discards the rest.  If no row matches
+// pointed at by dest. See the documentation on Rows.Scan for details.
+// If more than one row matches the query,
+// Scan uses the first row and discards the rest. If no row matches
 // the query, Scan returns ErrNoRows.
 func (r *Row) Scan(dest ...interface{}) error {
 	if r.err != nil {
@@ -1812,6 +1970,6 @@ func stack() string {
 // withLock runs while holding lk.
 func withLock(lk sync.Locker, fn func()) {
 	lk.Lock()
+	defer lk.Unlock() // in case fn panics
 	fn()
-	lk.Unlock()
 }
diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go
index 432a641..8ec70d9 100644
--- a/src/database/sql/sql_test.go
+++ b/src/database/sql/sql_test.go
@@ -68,6 +68,46 @@ func newTestDB(t testing.TB, name string) *DB {
 	return db
 }
 
+func TestDriverPanic(t *testing.T) {
+	// Test that if driver panics, database/sql does not deadlock.
+	db, err := Open("test", fakeDBName)
+	if err != nil {
+		t.Fatalf("Open: %v", err)
+	}
+	expectPanic := func(name string, f func()) {
+		defer func() {
+			err := recover()
+			if err == nil {
+				t.Fatalf("%s did not panic", name)
+			}
+		}()
+		f()
+	}
+
+	expectPanic("Exec Exec", func() { db.Exec("PANIC|Exec|WIPE") })
+	exec(t, db, "WIPE") // check not deadlocked
+	expectPanic("Exec NumInput", func() { db.Exec("PANIC|NumInput|WIPE") })
+	exec(t, db, "WIPE") // check not deadlocked
+	expectPanic("Exec Close", func() { db.Exec("PANIC|Close|WIPE") })
+	exec(t, db, "WIPE")             // check not deadlocked
+	exec(t, db, "PANIC|Query|WIPE") // should run successfully: Exec does not call Query
+	exec(t, db, "WIPE")             // check not deadlocked
+
+	exec(t, db, "CREATE|people|name=string,age=int32,photo=blob,dead=bool,bdate=datetime")
+
+	expectPanic("Query Query", func() { db.Query("PANIC|Query|SELECT|people|age,name|") })
+	expectPanic("Query NumInput", func() { db.Query("PANIC|NumInput|SELECT|people|age,name|") })
+	expectPanic("Query Close", func() {
+		rows, err := db.Query("PANIC|Close|SELECT|people|age,name|")
+		if err != nil {
+			t.Fatal(err)
+		}
+		rows.Close()
+	})
+	db.Query("PANIC|Exec|SELECT|people|age,name|") // should run successfully: Query does not call Exec
+	exec(t, db, "WIPE")                            // check not deadlocked
+}
+
 func exec(t testing.TB, db *DB, query string, args ...interface{}) {
 	_, err := db.Exec(query, args...)
 	if err != nil {
@@ -142,6 +182,20 @@ func (db *DB) numFreeConns() int {
 	return len(db.freeConn)
 }
 
+// clearAllConns closes all connections in db.
+func (db *DB) clearAllConns(t *testing.T) {
+	db.SetMaxIdleConns(0)
+
+	if g, w := db.numFreeConns(), 0; g != w {
+		t.Errorf("free conns = %d; want %d", g, w)
+	}
+
+	if n := db.numDepsPollUntil(0, time.Second); n > 0 {
+		t.Errorf("number of dependencies = %d; expected 0", n)
+		db.dumpDeps(t)
+	}
+}
+
 func (db *DB) dumpDeps(t *testing.T) {
 	for fc := range db.dep {
 		db.dumpDep(t, 0, fc, map[finalCloser]bool{})
@@ -356,6 +410,44 @@ func TestStatementQueryRow(t *testing.T) {
 	}
 }
 
+type stubDriverStmt struct {
+	err error
+}
+
+func (s stubDriverStmt) Close() error {
+	return s.err
+}
+
+func (s stubDriverStmt) NumInput() int {
+	return -1
+}
+
+func (s stubDriverStmt) Exec(args []driver.Value) (driver.Result, error) {
+	return nil, nil
+}
+
+func (s stubDriverStmt) Query(args []driver.Value) (driver.Rows, error) {
+	return nil, nil
+}
+
+// golang.org/issue/12798
+func TestStatementClose(t *testing.T) {
+	want := errors.New("STMT ERROR")
+
+	tests := []struct {
+		stmt *Stmt
+		msg  string
+	}{
+		{&Stmt{stickyErr: want}, "stickyErr not propagated"},
+		{&Stmt{tx: &Tx{}, txsi: &driverStmt{&sync.Mutex{}, stubDriverStmt{want}}}, "driverStmt.Close() error not propagated"},
+	}
+	for _, test := range tests {
+		if err := test.stmt.Close(); err != want {
+			t.Errorf("%s. Got stmt.Close() = %v, want = %v", test.msg, err, want)
+		}
+	}
+}
+
 // golang.org/issue/3734
 func TestStatementQueryRowConcurrent(t *testing.T) {
 	db := newTestDB(t, "people")
@@ -953,16 +1045,7 @@ func TestMaxOpenConns(t *testing.T) {
 
 	// Force the number of open connections to 0 so we can get an accurate
 	// count for the test
-	db.SetMaxIdleConns(0)
-
-	if g, w := db.numFreeConns(), 0; g != w {
-		t.Errorf("free conns = %d; want %d", g, w)
-	}
-
-	if n := db.numDepsPollUntil(0, time.Second); n > 0 {
-		t.Errorf("number of dependencies = %d; expected 0", n)
-		db.dumpDeps(t)
-	}
+	db.clearAllConns(t)
 
 	driver.mu.Lock()
 	opens0 := driver.openCount
@@ -1058,16 +1141,7 @@ func TestMaxOpenConns(t *testing.T) {
 		db.dumpDeps(t)
 	}
 
-	db.SetMaxIdleConns(0)
-
-	if g, w := db.numFreeConns(), 0; g != w {
-		t.Errorf("free conns = %d; want %d", g, w)
-	}
-
-	if n := db.numDepsPollUntil(0, time.Second); n > 0 {
-		t.Errorf("number of dependencies = %d; expected 0", n)
-		db.dumpDeps(t)
-	}
+	db.clearAllConns(t)
 }
 
 // Issue 9453: tests that SetMaxOpenConns can be lowered at runtime
@@ -1121,6 +1195,67 @@ func TestMaxOpenConnsOnBusy(t *testing.T) {
 	}
 }
 
+// Issue 10886: tests that all connection attempts return when more than
+// DB.maxOpen connections are in flight and the first DB.maxOpen fail.
+func TestPendingConnsAfterErr(t *testing.T) {
+	const (
+		maxOpen = 2
+		tryOpen = maxOpen*2 + 2
+	)
+
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+	defer func() {
+		for k, v := range db.lastPut {
+			t.Logf("%p: %v", k, v)
+		}
+	}()
+
+	db.SetMaxOpenConns(maxOpen)
+	db.SetMaxIdleConns(0)
+
+	errOffline := errors.New("db offline")
+	defer func() { setHookOpenErr(nil) }()
+
+	errs := make(chan error, tryOpen)
+
+	unblock := make(chan struct{})
+	setHookOpenErr(func() error {
+		<-unblock // block until all connections are in flight
+		return errOffline
+	})
+
+	var opening sync.WaitGroup
+	opening.Add(tryOpen)
+	for i := 0; i < tryOpen; i++ {
+		go func() {
+			opening.Done() // signal one connection is in flight
+			_, err := db.Exec("INSERT|people|name=Julia,age=19")
+			errs <- err
+		}()
+	}
+
+	opening.Wait()                    // wait for all workers to begin running
+	time.Sleep(10 * time.Millisecond) // make extra sure all workers are blocked
+	close(unblock)                    // let all workers proceed
+
+	const timeout = 100 * time.Millisecond
+	to := time.NewTimer(timeout)
+	defer to.Stop()
+
+	// check that all connections fail without deadlock
+	for i := 0; i < tryOpen; i++ {
+		select {
+		case err := <-errs:
+			if got, want := err, errOffline; got != want {
+				t.Errorf("unexpected err: got %v, want %v", got, want)
+			}
+		case <-to.C:
+			t.Fatalf("orphaned connection request(s), still waiting after %v", timeout)
+		}
+	}
+}
+
 func TestSingleOpenConn(t *testing.T) {
 	db := newTestDB(t, "people")
 	defer closeDB(t, db)
@@ -1164,6 +1299,90 @@ func TestStats(t *testing.T) {
 	}
 }
 
+func TestConnMaxLifetime(t *testing.T) {
+	t0 := time.Unix(1000000, 0)
+	offset := time.Duration(0)
+
+	nowFunc = func() time.Time { return t0.Add(offset) }
+	defer func() { nowFunc = time.Now }()
+
+	db := newTestDB(t, "magicquery")
+	defer closeDB(t, db)
+
+	driver := db.driver.(*fakeDriver)
+
+	// Force the number of open connections to 0 so we can get an accurate
+	// count for the test
+	db.clearAllConns(t)
+
+	driver.mu.Lock()
+	opens0 := driver.openCount
+	closes0 := driver.closeCount
+	driver.mu.Unlock()
+
+	db.SetMaxIdleConns(10)
+	db.SetMaxOpenConns(10)
+
+	tx, err := db.Begin()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	offset = time.Second
+	tx2, err := db.Begin()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	tx.Commit()
+	tx2.Commit()
+
+	driver.mu.Lock()
+	opens := driver.openCount - opens0
+	closes := driver.closeCount - closes0
+	driver.mu.Unlock()
+
+	if opens != 2 {
+		t.Errorf("opens = %d; want 2", opens)
+	}
+	if closes != 0 {
+		t.Errorf("closes = %d; want 0", closes)
+	}
+	if g, w := db.numFreeConns(), 2; g != w {
+		t.Errorf("free conns = %d; want %d", g, w)
+	}
+
+	// Expire first conn
+	offset = time.Second * 11
+	db.SetConnMaxLifetime(time.Second * 10)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	tx, err = db.Begin()
+	if err != nil {
+		t.Fatal(err)
+	}
+	tx2, err = db.Begin()
+	if err != nil {
+		t.Fatal(err)
+	}
+	tx.Commit()
+	tx2.Commit()
+
+	driver.mu.Lock()
+	opens = driver.openCount - opens0
+	closes = driver.closeCount - closes0
+	driver.mu.Unlock()
+
+	if opens != 3 {
+		t.Errorf("opens = %d; want 3", opens)
+	}
+	if closes != 1 {
+		t.Errorf("closes = %d; want 1", closes)
+	}
+}
+
 // golang.org/issue/5323
 func TestStmtCloseDeps(t *testing.T) {
 	if testing.Short() {
@@ -1257,16 +1476,7 @@ func TestStmtCloseDeps(t *testing.T) {
 		db.dumpDeps(t)
 	}
 
-	db.SetMaxIdleConns(0)
-
-	if g, w := db.numFreeConns(), 0; g != w {
-		t.Errorf("free conns = %d; want %d", g, w)
-	}
-
-	if n := db.numDepsPollUntil(0, time.Second); n > 0 {
-		t.Errorf("number of dependencies = %d; expected 0", n)
-		db.dumpDeps(t)
-	}
+	db.clearAllConns(t)
 }
 
 // golang.org/issue/5046
@@ -1564,6 +1774,77 @@ func TestErrBadConnReconnect(t *testing.T) {
 	simulateBadConn("stmt.Query exec", &hookQueryBadConn, stmtQuery)
 }
 
+// golang.org/issue/11264
+func TestTxEndBadConn(t *testing.T) {
+	db := newTestDB(t, "foo")
+	defer closeDB(t, db)
+	db.SetMaxIdleConns(0)
+	exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
+	db.SetMaxIdleConns(1)
+
+	simulateBadConn := func(name string, hook *func() bool, op func() error) {
+		broken := false
+		numOpen := db.numOpen
+
+		*hook = func() bool {
+			if !broken {
+				broken = true
+			}
+			return broken
+		}
+
+		if err := op(); err != driver.ErrBadConn {
+			t.Errorf(name+": %v", err)
+			return
+		}
+
+		if !broken {
+			t.Error(name + ": Failed to simulate broken connection")
+		}
+		*hook = nil
+
+		if numOpen != db.numOpen {
+			t.Errorf(name+": leaked %d connection(s)!", db.numOpen-numOpen)
+		}
+	}
+
+	// db.Exec
+	dbExec := func(endTx func(tx *Tx) error) func() error {
+		return func() error {
+			tx, err := db.Begin()
+			if err != nil {
+				return err
+			}
+			_, err = tx.Exec("INSERT|t1|name=?,age=?,dead=?", "Gordon", 3, true)
+			if err != nil {
+				return err
+			}
+			return endTx(tx)
+		}
+	}
+	simulateBadConn("db.Tx.Exec commit", &hookCommitBadConn, dbExec((*Tx).Commit))
+	simulateBadConn("db.Tx.Exec rollback", &hookRollbackBadConn, dbExec((*Tx).Rollback))
+
+	// db.Query
+	dbQuery := func(endTx func(tx *Tx) error) func() error {
+		return func() error {
+			tx, err := db.Begin()
+			if err != nil {
+				return err
+			}
+			rows, err := tx.Query("SELECT|t1|age,name|")
+			if err == nil {
+				err = rows.Close()
+			} else {
+				return err
+			}
+			return endTx(tx)
+		}
+	}
+	simulateBadConn("db.Tx.Query commit", &hookCommitBadConn, dbQuery((*Tx).Commit))
+	simulateBadConn("db.Tx.Query rollback", &hookRollbackBadConn, dbQuery((*Tx).Rollback))
+}
+
 type concurrentTest interface {
 	init(t testing.TB, db *DB)
 	finish(t testing.TB)
diff --git a/src/debug/dwarf/class_string.go b/src/debug/dwarf/class_string.go
index 0b1206b..d57d9f7 100644
--- a/src/debug/dwarf/class_string.go
+++ b/src/debug/dwarf/class_string.go
@@ -4,14 +4,13 @@ package dwarf
 
 import "fmt"
 
-const _Class_name = "ClassAddressClassBlockClassConstantClassExprLocClassFlagClassLinePtrClassLocListPtrClassMacPtrClassRangeListPtrClassReferenceClassReferenceSigClassStringClassReferenceAltClassStringAlt"
+const _Class_name = "ClassUnknownClassAddressClassBlockClassConstantClassExprLocClassFlagClassLinePtrClassLocListPtrClassMacPtrClassRangeListPtrClassReferenceClassReferenceSigClassStringClassReferenceAltClassStringAlt"
 
-var _Class_index = [...]uint8{0, 12, 22, 35, 47, 56, 68, 83, 94, 111, 125, 142, 153, 170, 184}
+var _Class_index = [...]uint8{0, 12, 24, 34, 47, 59, 68, 80, 95, 106, 123, 137, 154, 165, 182, 196}
 
 func (i Class) String() string {
-	i -= 1
 	if i < 0 || i+1 >= Class(len(_Class_index)) {
-		return fmt.Sprintf("Class(%d)", i+1)
+		return fmt.Sprintf("Class(%d)", i)
 	}
 	return _Class_name[_Class_index[i]:_Class_index[i+1]]
 }
diff --git a/src/debug/dwarf/entry.go b/src/debug/dwarf/entry.go
index d607e5b..5ca8667 100644
--- a/src/debug/dwarf/entry.go
+++ b/src/debug/dwarf/entry.go
@@ -193,8 +193,7 @@ func formToClass(form format, attr Attr, vers int, b *buf) Class {
 		if class, ok := attrPtrClass[attr]; ok {
 			return class
 		}
-		b.error("cannot determine class of unknown attribute with formSecOffset")
-		return 0
+		return ClassUnknown
 
 	case formExprloc:
 		return ClassExprLoc
@@ -235,6 +234,9 @@ type Entry struct {
 //    loclistptr        int64          ClassLocListPtr
 //    macptr            int64          ClassMacPtr
 //    rangelistptr      int64          ClassRangeListPtr
+//
+// For unrecognized or vendor-defined attributes, Class may be
+// ClassUnknown.
 type Field struct {
 	Attr  Attr
 	Val   interface{}
@@ -258,9 +260,12 @@ type Field struct {
 type Class int
 
 const (
+	// ClassUnknown represents values of unknown DWARF class.
+	ClassUnknown Class = iota
+
 	// ClassAddress represents values of type uint64 that are
 	// addresses on the target machine.
-	ClassAddress Class = 1 + iota
+	ClassAddress
 
 	// ClassBlock represents values of type []byte whose
 	// interpretation depends on the attribute.
diff --git a/src/debug/dwarf/entry_test.go b/src/debug/dwarf/entry_test.go
new file mode 100644
index 0000000..8bd2d2a
--- /dev/null
+++ b/src/debug/dwarf/entry_test.go
@@ -0,0 +1,36 @@
+// Copyright 2009 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 dwarf_test
+
+import (
+	. "debug/dwarf"
+	"testing"
+)
+
+func TestSplit(t *testing.T) {
+	// debug/dwarf doesn't (currently) support split DWARF, but
+	// the attributes that pointed to the split DWARF used to
+	// cause loading the DWARF data to fail entirely (issue
+	// #12592). Test that we can at least read the DWARF data.
+	d := elfData(t, "testdata/split.elf")
+	r := d.Reader()
+	e, err := r.Next()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if e.Tag != TagCompileUnit {
+		t.Fatalf("bad tag: have %s, want %s", e.Tag, TagCompileUnit)
+	}
+	// Check that we were able to parse the unknown section offset
+	// field, even if we can't figure out its DWARF class.
+	const AttrGNUAddrBase Attr = 0x2133
+	f := e.AttrField(AttrGNUAddrBase)
+	if _, ok := f.Val.(int64); !ok {
+		t.Fatalf("bad attribute value type: have %T, want int64", f.Val)
+	}
+	if f.Class != ClassUnknown {
+		t.Fatalf("bad class: have %s, want %s", f.Class, ClassUnknown)
+	}
+}
diff --git a/src/debug/dwarf/testdata/cycle.c b/src/debug/dwarf/testdata/cycle.c
new file mode 100644
index 0000000..a0b53df
--- /dev/null
+++ b/src/debug/dwarf/testdata/cycle.c
@@ -0,0 +1,7 @@
+typedef struct aaa *AAA;
+typedef AAA BBB;
+struct aaa { BBB val; };
+
+AAA x(void) {
+    return (AAA)0;
+}
diff --git a/src/debug/dwarf/testdata/cycle.elf b/src/debug/dwarf/testdata/cycle.elf
new file mode 100644
index 0000000..e0b66ca
Binary files /dev/null and b/src/debug/dwarf/testdata/cycle.elf differ
diff --git a/src/debug/dwarf/testdata/line-clang.elf b/src/debug/dwarf/testdata/line-clang.elf
old mode 100755
new mode 100644
diff --git a/src/debug/dwarf/testdata/line-gcc.elf b/src/debug/dwarf/testdata/line-gcc.elf
old mode 100755
new mode 100644
diff --git a/src/debug/dwarf/testdata/split.c b/src/debug/dwarf/testdata/split.c
new file mode 100644
index 0000000..0ef3427
--- /dev/null
+++ b/src/debug/dwarf/testdata/split.c
@@ -0,0 +1,5 @@
+// gcc -gsplit-dwarf split.c -o split.elf
+
+int main() 
+{
+}
diff --git a/src/debug/dwarf/testdata/split.elf b/src/debug/dwarf/testdata/split.elf
new file mode 100644
index 0000000..99ee2c2
Binary files /dev/null and b/src/debug/dwarf/testdata/split.elf differ
diff --git a/src/debug/dwarf/type.go b/src/debug/dwarf/type.go
index a5daa1d..c76a472 100644
--- a/src/debug/dwarf/type.go
+++ b/src/debug/dwarf/type.go
@@ -275,12 +275,14 @@ type typeReader interface {
 
 // Type reads the type at off in the DWARF ``info'' section.
 func (d *Data) Type(off Offset) (Type, error) {
-	return d.readType("info", d.Reader(), off, d.typeCache)
+	return d.readType("info", d.Reader(), off, d.typeCache, nil)
 }
 
-// readType reads a type from r at off of name using and updating a
-// type cache.
-func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Offset]Type) (Type, error) {
+// readType reads a type from r at off of name. It adds types to the
+// type cache, appends new typedef types to typedefs, and computes the
+// sizes of types. Callers should pass nil for typedefs; this is used
+// for internal recursion.
+func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Offset]Type, typedefs *[]*TypedefType) (Type, error) {
 	if t, ok := typeCache[off]; ok {
 		return t, nil
 	}
@@ -294,9 +296,24 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
 		return nil, DecodeError{name, off, "no type at offset"}
 	}
 
+	// If this is the root of the recursion, prepare to resolve
+	// typedef sizes once the recursion is done. This must be done
+	// after the type graph is constructed because it may need to
+	// resolve cycles in a different order than readType
+	// encounters them.
+	if typedefs == nil {
+		var typedefList []*TypedefType
+		defer func() {
+			for _, t := range typedefList {
+				t.Common().ByteSize = t.Type.Size()
+			}
+		}()
+		typedefs = &typedefList
+	}
+
 	// Parse type from Entry.
 	// Must always set typeCache[off] before calling
-	// d.Type recursively, to handle circular types correctly.
+	// d.readType recursively, to handle circular types correctly.
 	var typ Type
 
 	nextDepth := 0
@@ -345,7 +362,7 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
 		var t Type
 		switch toff := tval.(type) {
 		case Offset:
-			if t, err = d.readType(name, r.clone(), toff, typeCache); err != nil {
+			if t, err = d.readType(name, r.clone(), toff, typeCache, typedefs); err != nil {
 				return nil
 			}
 		case uint64:
@@ -674,7 +691,10 @@ func (d *Data) readType(name string, r typeReader, off Offset, typeCache map[Off
 			b = -1
 			switch t := typ.(type) {
 			case *TypedefType:
-				b = t.Type.Size()
+				// Record that we need to resolve this
+				// type's size once the type graph is
+				// constructed.
+				*typedefs = append(*typedefs, t)
 			case *PtrType:
 				b = int64(addressSize)
 			}
diff --git a/src/debug/dwarf/type_test.go b/src/debug/dwarf/type_test.go
index 2cb85e7..ad6308d 100644
--- a/src/debug/dwarf/type_test.go
+++ b/src/debug/dwarf/type_test.go
@@ -120,3 +120,37 @@ func testTypedefs(t *testing.T, d *Data, kind string) {
 		}
 	}
 }
+
+func TestTypedefCycle(t *testing.T) {
+	// See issue #13039: reading a typedef cycle starting from a
+	// different place than the size needed to be computed from
+	// used to crash.
+	//
+	// cycle.elf built with GCC 4.8.4:
+	//    gcc -g -c -o cycle.elf cycle.c
+	d := elfData(t, "testdata/cycle.elf")
+	r := d.Reader()
+	offsets := []Offset{}
+	for {
+		e, err := r.Next()
+		if err != nil {
+			t.Fatal("r.Next:", err)
+		}
+		if e == nil {
+			break
+		}
+		switch e.Tag {
+		case TagBaseType, TagTypedef, TagPointerType, TagStructType:
+			offsets = append(offsets, e.Offset)
+		}
+	}
+
+	// Parse each type with a fresh type cache.
+	for _, offset := range offsets {
+		d := elfData(t, "testdata/cycle.elf")
+		_, err := d.Type(offset)
+		if err != nil {
+			t.Fatalf("d.Type(0x%x): %s", offset, err)
+		}
+	}
+}
diff --git a/src/debug/dwarf/typeunit.go b/src/debug/dwarf/typeunit.go
index 9cfb4a8..0f4e07e 100644
--- a/src/debug/dwarf/typeunit.go
+++ b/src/debug/dwarf/typeunit.go
@@ -101,7 +101,7 @@ func (d *Data) sigToType(sig uint64) (Type, error) {
 
 	b := makeBuf(d, tu, tu.name, tu.off, tu.data)
 	r := &typeUnitReader{d: d, tu: tu, b: b}
-	t, err := d.readType(tu.name, r, Offset(tu.toff), make(map[Offset]Type))
+	t, err := d.readType(tu.name, r, Offset(tu.toff), make(map[Offset]Type), nil)
 	if err != nil {
 		return nil, err
 	}
diff --git a/src/debug/elf/elf.go b/src/debug/elf/elf.go
index 70daeec..f53ba00 100644
--- a/src/debug/elf/elf.go
+++ b/src/debug/elf/elf.go
@@ -411,6 +411,7 @@ const (
 	SHF_OS_NONCONFORMING SectionFlag = 0x100      /* OS-specific processing required. */
 	SHF_GROUP            SectionFlag = 0x200      /* Member of section group. */
 	SHF_TLS              SectionFlag = 0x400      /* Section contains TLS data. */
+	SHF_COMPRESSED       SectionFlag = 0x800      /* Section is compressed. */
 	SHF_MASKOS           SectionFlag = 0x0ff00000 /* OS-specific semantics. */
 	SHF_MASKPROC         SectionFlag = 0xf0000000 /* Processor-specific semantics. */
 )
@@ -426,11 +427,34 @@ var shfStrings = []intName{
 	{0x100, "SHF_OS_NONCONFORMING"},
 	{0x200, "SHF_GROUP"},
 	{0x400, "SHF_TLS"},
+	{0x800, "SHF_COMPRESSED"},
 }
 
 func (i SectionFlag) String() string   { return flagName(uint32(i), shfStrings, false) }
 func (i SectionFlag) GoString() string { return flagName(uint32(i), shfStrings, true) }
 
+// Section compression type.
+type CompressionType int
+
+const (
+	COMPRESS_ZLIB   CompressionType = 1          /* ZLIB compression. */
+	COMPRESS_LOOS   CompressionType = 0x60000000 /* First OS-specific. */
+	COMPRESS_HIOS   CompressionType = 0x6fffffff /* Last OS-specific. */
+	COMPRESS_LOPROC CompressionType = 0x70000000 /* First processor-specific type. */
+	COMPRESS_HIPROC CompressionType = 0x7fffffff /* Last processor-specific type. */
+)
+
+var compressionStrings = []intName{
+	{0, "COMPRESS_ZLIB"},
+	{0x60000000, "COMPRESS_LOOS"},
+	{0x6fffffff, "COMPRESS_HIOS"},
+	{0x70000000, "COMPRESS_LOPROC"},
+	{0x7fffffff, "COMPRESS_HIPROC"},
+}
+
+func (i CompressionType) String() string   { return stringName(uint32(i), compressionStrings, false) }
+func (i CompressionType) GoString() string { return stringName(uint32(i), compressionStrings, true) }
+
 // Prog.Type
 type ProgType int
 
@@ -1246,6 +1270,115 @@ var r386Strings = []intName{
 func (i R_386) String() string   { return stringName(uint32(i), r386Strings, false) }
 func (i R_386) GoString() string { return stringName(uint32(i), r386Strings, true) }
 
+// Relocation types for MIPS.
+type R_MIPS int
+
+const (
+	R_MIPS_NONE          R_MIPS = 0
+	R_MIPS_16            R_MIPS = 1
+	R_MIPS_32            R_MIPS = 2
+	R_MIPS_REL32         R_MIPS = 3
+	R_MIPS_26            R_MIPS = 4
+	R_MIPS_HI16          R_MIPS = 5  /* high 16 bits of symbol value */
+	R_MIPS_LO16          R_MIPS = 6  /* low 16 bits of symbol value */
+	R_MIPS_GPREL16       R_MIPS = 7  /* GP-relative reference  */
+	R_MIPS_LITERAL       R_MIPS = 8  /* Reference to literal section  */
+	R_MIPS_GOT16         R_MIPS = 9  /* Reference to global offset table */
+	R_MIPS_PC16          R_MIPS = 10 /* 16 bit PC relative reference */
+	R_MIPS_CALL16        R_MIPS = 11 /* 16 bit call thru glbl offset tbl */
+	R_MIPS_GPREL32       R_MIPS = 12
+	R_MIPS_SHIFT5        R_MIPS = 16
+	R_MIPS_SHIFT6        R_MIPS = 17
+	R_MIPS_64            R_MIPS = 18
+	R_MIPS_GOT_DISP      R_MIPS = 19
+	R_MIPS_GOT_PAGE      R_MIPS = 20
+	R_MIPS_GOT_OFST      R_MIPS = 21
+	R_MIPS_GOT_HI16      R_MIPS = 22
+	R_MIPS_GOT_LO16      R_MIPS = 23
+	R_MIPS_SUB           R_MIPS = 24
+	R_MIPS_INSERT_A      R_MIPS = 25
+	R_MIPS_INSERT_B      R_MIPS = 26
+	R_MIPS_DELETE        R_MIPS = 27
+	R_MIPS_HIGHER        R_MIPS = 28
+	R_MIPS_HIGHEST       R_MIPS = 29
+	R_MIPS_CALL_HI16     R_MIPS = 30
+	R_MIPS_CALL_LO16     R_MIPS = 31
+	R_MIPS_SCN_DISP      R_MIPS = 32
+	R_MIPS_REL16         R_MIPS = 33
+	R_MIPS_ADD_IMMEDIATE R_MIPS = 34
+	R_MIPS_PJUMP         R_MIPS = 35
+	R_MIPS_RELGOT        R_MIPS = 36
+	R_MIPS_JALR          R_MIPS = 37
+
+	R_MIPS_TLS_DTPMOD32    R_MIPS = 38 /* Module number 32 bit */
+	R_MIPS_TLS_DTPREL32    R_MIPS = 39 /* Module-relative offset 32 bit */
+	R_MIPS_TLS_DTPMOD64    R_MIPS = 40 /* Module number 64 bit */
+	R_MIPS_TLS_DTPREL64    R_MIPS = 41 /* Module-relative offset 64 bit */
+	R_MIPS_TLS_GD          R_MIPS = 42 /* 16 bit GOT offset for GD */
+	R_MIPS_TLS_LDM         R_MIPS = 43 /* 16 bit GOT offset for LDM */
+	R_MIPS_TLS_DTPREL_HI16 R_MIPS = 44 /* Module-relative offset, high 16 bits */
+	R_MIPS_TLS_DTPREL_LO16 R_MIPS = 45 /* Module-relative offset, low 16 bits */
+	R_MIPS_TLS_GOTTPREL    R_MIPS = 46 /* 16 bit GOT offset for IE */
+	R_MIPS_TLS_TPREL32     R_MIPS = 47 /* TP-relative offset, 32 bit */
+	R_MIPS_TLS_TPREL64     R_MIPS = 48 /* TP-relative offset, 64 bit */
+	R_MIPS_TLS_TPREL_HI16  R_MIPS = 49 /* TP-relative offset, high 16 bits */
+	R_MIPS_TLS_TPREL_LO16  R_MIPS = 50 /* TP-relative offset, low 16 bits */
+)
+
+var rmipsStrings = []intName{
+	{0, "R_MIPS_NONE"},
+	{1, "R_MIPS_16"},
+	{2, "R_MIPS_32"},
+	{3, "R_MIPS_REL32"},
+	{4, "R_MIPS_26"},
+	{5, "R_MIPS_HI16"},
+	{6, "R_MIPS_LO16"},
+	{7, "R_MIPS_GPREL16"},
+	{8, "R_MIPS_LITERAL"},
+	{9, "R_MIPS_GOT16"},
+	{10, "R_MIPS_PC16"},
+	{11, "R_MIPS_CALL16"},
+	{12, "R_MIPS_GPREL32"},
+	{16, "R_MIPS_SHIFT5"},
+	{17, "R_MIPS_SHIFT6"},
+	{18, "R_MIPS_64"},
+	{19, "R_MIPS_GOT_DISP"},
+	{20, "R_MIPS_GOT_PAGE"},
+	{21, "R_MIPS_GOT_OFST"},
+	{22, "R_MIPS_GOT_HI16"},
+	{23, "R_MIPS_GOT_LO16"},
+	{24, "R_MIPS_SUB"},
+	{25, "R_MIPS_INSERT_A"},
+	{26, "R_MIPS_INSERT_B"},
+	{27, "R_MIPS_DELETE"},
+	{28, "R_MIPS_HIGHER"},
+	{29, "R_MIPS_HIGHEST"},
+	{30, "R_MIPS_CALL_HI16"},
+	{31, "R_MIPS_CALL_LO16"},
+	{32, "R_MIPS_SCN_DISP"},
+	{33, "R_MIPS_REL16"},
+	{34, "R_MIPS_ADD_IMMEDIATE"},
+	{35, "R_MIPS_PJUMP"},
+	{36, "R_MIPS_RELGOT"},
+	{37, "R_MIPS_JALR"},
+	{38, "R_MIPS_TLS_DTPMOD32"},
+	{39, "R_MIPS_TLS_DTPREL32"},
+	{40, "R_MIPS_TLS_DTPMOD64"},
+	{41, "R_MIPS_TLS_DTPREL64"},
+	{42, "R_MIPS_TLS_GD"},
+	{43, "R_MIPS_TLS_LDM"},
+	{44, "R_MIPS_TLS_DTPREL_HI16"},
+	{45, "R_MIPS_TLS_DTPREL_LO16"},
+	{46, "R_MIPS_TLS_GOTTPREL"},
+	{47, "R_MIPS_TLS_TPREL32"},
+	{48, "R_MIPS_TLS_TPREL64"},
+	{49, "R_MIPS_TLS_TPREL_HI16"},
+	{50, "R_MIPS_TLS_TPREL_LO16"},
+}
+
+func (i R_MIPS) String() string   { return stringName(uint32(i), rmipsStrings, false) }
+func (i R_MIPS) GoString() string { return stringName(uint32(i), rmipsStrings, true) }
+
 // Relocation types for PowerPC.
 type R_PPC int
 
@@ -1769,6 +1902,13 @@ type Dyn32 struct {
 	Val uint32 /* Integer/Address value. */
 }
 
+// ELF32 Compression header.
+type Chdr32 struct {
+	Type      uint32
+	Size      uint32
+	Addralign uint32
+}
+
 /*
  * Relocation entries.
  */
@@ -1863,6 +2003,14 @@ type Dyn64 struct {
 	Val uint64 /* Integer/address value */
 }
 
+// ELF64 Compression header.
+type Chdr64 struct {
+	Type      uint32
+	_         uint32 /* Reserved. */
+	Size      uint64
+	Addralign uint64
+}
+
 /*
  * Relocation entries.
  */
diff --git a/src/debug/elf/file.go b/src/debug/elf/file.go
index 4062543..199aa4e 100644
--- a/src/debug/elf/file.go
+++ b/src/debug/elf/file.go
@@ -7,6 +7,7 @@ package elf
 
 import (
 	"bytes"
+	"compress/zlib"
 	"debug/dwarf"
 	"encoding/binary"
 	"errors"
@@ -57,6 +58,12 @@ type SectionHeader struct {
 	Info      uint32
 	Addralign uint64
 	Entsize   uint64
+
+	// FileSize is the size of this section in the file in bytes.
+	// If a section is compressed, FileSize is the size of the
+	// compressed data, while Size (above) is the size of the
+	// uncompressed data.
+	FileSize uint64
 }
 
 // A Section represents a single section in an ELF file.
@@ -69,17 +76,23 @@ type Section struct {
 	// If a client wants Read and Seek it must use
 	// Open() to avoid fighting over the seek offset
 	// with other clients.
+	//
+	// ReaderAt may be nil if the section is not easily available
+	// in a random-access form. For example, a compressed section
+	// may have a nil ReaderAt.
 	io.ReaderAt
 	sr *io.SectionReader
+
+	compressionType   CompressionType
+	compressionOffset int64
 }
 
 // Data reads and returns the contents of the ELF section.
+// Even if the section is stored compressed in the ELF file,
+// Data returns uncompressed data.
 func (s *Section) Data() ([]byte, error) {
-	dat := make([]byte, s.sr.Size())
-	n, err := s.sr.ReadAt(dat, 0)
-	if n == len(dat) {
-		err = nil
-	}
+	dat := make([]byte, s.Size)
+	n, err := io.ReadFull(s.Open(), dat)
 	return dat[0:n], err
 }
 
@@ -93,7 +106,24 @@ func (f *File) stringTable(link uint32) ([]byte, error) {
 }
 
 // Open returns a new ReadSeeker reading the ELF section.
-func (s *Section) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) }
+// Even if the section is stored compressed in the ELF file,
+// the ReadSeeker reads uncompressed data.
+func (s *Section) Open() io.ReadSeeker {
+	if s.Flags&SHF_COMPRESSED == 0 {
+		return io.NewSectionReader(s.sr, 0, 1<<63-1)
+	}
+	if s.compressionType == COMPRESS_ZLIB {
+		return &readSeekerFromReader{
+			reset: func() (io.Reader, error) {
+				fr := io.NewSectionReader(s.sr, s.compressionOffset, int64(s.FileSize)-s.compressionOffset)
+				return zlib.NewReader(fr)
+			},
+			size: int64(s.Size),
+		}
+	}
+	err := &FormatError{int64(s.Offset), "unknown compression type", s.compressionType}
+	return errorReader{err}
+}
 
 // A ProgHeader represents a single ELF program header.
 type ProgHeader struct {
@@ -343,7 +373,7 @@ func NewFile(r io.ReaderAt) (*File, error) {
 				Flags:     SectionFlag(sh.Flags),
 				Addr:      uint64(sh.Addr),
 				Offset:    uint64(sh.Off),
-				Size:      uint64(sh.Size),
+				FileSize:  uint64(sh.Size),
 				Link:      uint32(sh.Link),
 				Info:      uint32(sh.Info),
 				Addralign: uint64(sh.Addralign),
@@ -359,7 +389,7 @@ func NewFile(r io.ReaderAt) (*File, error) {
 				Type:      SectionType(sh.Type),
 				Flags:     SectionFlag(sh.Flags),
 				Offset:    uint64(sh.Off),
-				Size:      uint64(sh.Size),
+				FileSize:  uint64(sh.Size),
 				Addr:      uint64(sh.Addr),
 				Link:      uint32(sh.Link),
 				Info:      uint32(sh.Info),
@@ -367,8 +397,35 @@ func NewFile(r io.ReaderAt) (*File, error) {
 				Entsize:   uint64(sh.Entsize),
 			}
 		}
-		s.sr = io.NewSectionReader(r, int64(s.Offset), int64(s.Size))
-		s.ReaderAt = s.sr
+		s.sr = io.NewSectionReader(r, int64(s.Offset), int64(s.FileSize))
+
+		if s.Flags&SHF_COMPRESSED == 0 {
+			s.ReaderAt = s.sr
+			s.Size = s.FileSize
+		} else {
+			// Read the compression header.
+			switch f.Class {
+			case ELFCLASS32:
+				ch := new(Chdr32)
+				if err := binary.Read(s.sr, f.ByteOrder, ch); err != nil {
+					return nil, err
+				}
+				s.compressionType = CompressionType(ch.Type)
+				s.Size = uint64(ch.Size)
+				s.Addralign = uint64(ch.Addralign)
+				s.compressionOffset = int64(binary.Size(ch))
+			case ELFCLASS64:
+				ch := new(Chdr64)
+				if err := binary.Read(s.sr, f.ByteOrder, ch); err != nil {
+					return nil, err
+				}
+				s.compressionType = CompressionType(ch.Type)
+				s.Size = ch.Size
+				s.Addralign = ch.Addralign
+				s.compressionOffset = int64(binary.Size(ch))
+			}
+		}
+
 		f.Sections[i] = s
 	}
 
@@ -537,6 +594,8 @@ func (f *File) applyRelocations(dst []byte, rels []byte) error {
 		return f.applyRelocationsPPC(dst, rels)
 	case f.Class == ELFCLASS64 && f.Machine == EM_PPC64:
 		return f.applyRelocationsPPC64(dst, rels)
+	case f.Class == ELFCLASS64 && f.Machine == EM_MIPS:
+		return f.applyRelocationsMIPS64(dst, rels)
 	default:
 		return errors.New("applyRelocations: not implemented")
 	}
@@ -800,6 +859,58 @@ func (f *File) applyRelocationsPPC64(dst []byte, rels []byte) error {
 	return nil
 }
 
+func (f *File) applyRelocationsMIPS64(dst []byte, rels []byte) error {
+	// 24 is the size of Rela64.
+	if len(rels)%24 != 0 {
+		return errors.New("length of relocation section is not a multiple of 24")
+	}
+
+	symbols, _, err := f.getSymbols(SHT_SYMTAB)
+	if err != nil {
+		return err
+	}
+
+	b := bytes.NewReader(rels)
+	var rela Rela64
+
+	for b.Len() > 0 {
+		binary.Read(b, f.ByteOrder, &rela)
+		var symNo uint64
+		var t R_MIPS
+		if f.ByteOrder == binary.BigEndian {
+			symNo = rela.Info >> 32
+			t = R_MIPS(rela.Info & 0xff)
+		} else {
+			symNo = rela.Info & 0xffffffff
+			t = R_MIPS(rela.Info >> 56)
+		}
+
+		if symNo == 0 || symNo > uint64(len(symbols)) {
+			continue
+		}
+		sym := &symbols[symNo-1]
+		if SymType(sym.Info&0xf) != STT_SECTION {
+			// We don't handle non-section relocations for now.
+			continue
+		}
+
+		switch t {
+		case R_MIPS_64:
+			if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 {
+				continue
+			}
+			f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], uint64(rela.Addend))
+		case R_MIPS_32:
+			if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 {
+				continue
+			}
+			f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], uint32(rela.Addend))
+		}
+	}
+
+	return nil
+}
+
 func (f *File) DWARF() (*dwarf.Data, error) {
 	// sectionData gets the data for s, checks its size, and
 	// applies any applicable relations.
@@ -809,6 +920,22 @@ func (f *File) DWARF() (*dwarf.Data, error) {
 			return nil, err
 		}
 
+		if len(b) >= 12 && string(b[:4]) == "ZLIB" {
+			dlen := binary.BigEndian.Uint64(b[4:12])
+			dbuf := make([]byte, dlen)
+			r, err := zlib.NewReader(bytes.NewBuffer(b[12:]))
+			if err != nil {
+				return nil, err
+			}
+			if _, err := io.ReadFull(r, dbuf); err != nil {
+				return nil, err
+			}
+			if err := r.Close(); err != nil {
+				return nil, err
+			}
+			b = dbuf
+		}
+
 		for _, r := range f.Sections {
 			if r.Type != SHT_RELA && r.Type != SHT_REL {
 				continue
@@ -833,17 +960,23 @@ func (f *File) DWARF() (*dwarf.Data, error) {
 	// Don't bother loading others.
 	var dat = map[string][]byte{"abbrev": nil, "info": nil, "str": nil, "line": nil}
 	for i, s := range f.Sections {
-		if !strings.HasPrefix(s.Name, ".debug_") {
+		suffix := ""
+		switch {
+		case strings.HasPrefix(s.Name, ".debug_"):
+			suffix = s.Name[7:]
+		case strings.HasPrefix(s.Name, ".zdebug_"):
+			suffix = s.Name[8:]
+		default:
 			continue
 		}
-		if _, ok := dat[s.Name[7:]]; !ok {
+		if _, ok := dat[suffix]; !ok {
 			continue
 		}
 		b, err := sectionData(i, s)
 		if err != nil {
 			return nil, err
 		}
-		dat[s.Name[7:]] = b
+		dat[suffix] = b
 	}
 
 	d, err := dwarf.New(dat["abbrev"], nil, nil, dat["info"], dat["line"], nil, nil, dat["str"])
diff --git a/src/debug/elf/file_test.go b/src/debug/elf/file_test.go
index 1ad4314..5c0df0f 100644
--- a/src/debug/elf/file_test.go
+++ b/src/debug/elf/file_test.go
@@ -10,6 +10,7 @@ import (
 	"debug/dwarf"
 	"encoding/binary"
 	"io"
+	"math/rand"
 	"net"
 	"os"
 	"path"
@@ -31,36 +32,36 @@ var fileTests = []fileTest{
 		"testdata/gcc-386-freebsd-exec",
 		FileHeader{ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_FREEBSD, 0, binary.LittleEndian, ET_EXEC, EM_386, 0x80483cc},
 		[]SectionHeader{
-			{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
-			{".interp", SHT_PROGBITS, SHF_ALLOC, 0x80480d4, 0xd4, 0x15, 0x0, 0x0, 0x1, 0x0},
-			{".hash", SHT_HASH, SHF_ALLOC, 0x80480ec, 0xec, 0x90, 0x3, 0x0, 0x4, 0x4},
-			{".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x804817c, 0x17c, 0x110, 0x4, 0x1, 0x4, 0x10},
-			{".dynstr", SHT_STRTAB, SHF_ALLOC, 0x804828c, 0x28c, 0xbb, 0x0, 0x0, 0x1, 0x0},
-			{".rel.plt", SHT_REL, SHF_ALLOC, 0x8048348, 0x348, 0x20, 0x3, 0x7, 0x4, 0x8},
-			{".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x8048368, 0x368, 0x11, 0x0, 0x0, 0x4, 0x0},
-			{".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x804837c, 0x37c, 0x50, 0x0, 0x0, 0x4, 0x4},
-			{".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x80483cc, 0x3cc, 0x180, 0x0, 0x0, 0x4, 0x0},
-			{".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x804854c, 0x54c, 0xc, 0x0, 0x0, 0x4, 0x0},
-			{".rodata", SHT_PROGBITS, SHF_ALLOC, 0x8048558, 0x558, 0xa3, 0x0, 0x0, 0x1, 0x0},
-			{".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80495fc, 0x5fc, 0xc, 0x0, 0x0, 0x4, 0x0},
-			{".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x8049608, 0x608, 0x4, 0x0, 0x0, 0x4, 0x0},
-			{".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x804960c, 0x60c, 0x98, 0x4, 0x0, 0x4, 0x8},
-			{".ctors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496a4, 0x6a4, 0x8, 0x0, 0x0, 0x4, 0x0},
-			{".dtors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496ac, 0x6ac, 0x8, 0x0, 0x0, 0x4, 0x0},
-			{".jcr", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496b4, 0x6b4, 0x4, 0x0, 0x0, 0x4, 0x0},
-			{".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496b8, 0x6b8, 0x1c, 0x0, 0x0, 0x4, 0x4},
-			{".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x80496d4, 0x6d4, 0x20, 0x0, 0x0, 0x4, 0x0},
-			{".comment", SHT_PROGBITS, 0x0, 0x0, 0x6d4, 0x12d, 0x0, 0x0, 0x1, 0x0},
-			{".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x801, 0x20, 0x0, 0x0, 0x1, 0x0},
-			{".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0x821, 0x1b, 0x0, 0x0, 0x1, 0x0},
-			{".debug_info", SHT_PROGBITS, 0x0, 0x0, 0x83c, 0x11d, 0x0, 0x0, 0x1, 0x0},
-			{".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0x959, 0x41, 0x0, 0x0, 0x1, 0x0},
-			{".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x99a, 0x35, 0x0, 0x0, 0x1, 0x0},
-			{".debug_frame", SHT_PROGBITS, 0x0, 0x0, 0x9d0, 0x30, 0x0, 0x0, 0x4, 0x0},
-			{".debug_str", SHT_PROGBITS, 0x0, 0x0, 0xa00, 0xd, 0x0, 0x0, 0x1, 0x0},
-			{".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xa0d, 0xf8, 0x0, 0x0, 0x1, 0x0},
-			{".symtab", SHT_SYMTAB, 0x0, 0x0, 0xfb8, 0x4b0, 0x1d, 0x38, 0x4, 0x10},
-			{".strtab", SHT_STRTAB, 0x0, 0x0, 0x1468, 0x206, 0x0, 0x0, 0x1, 0x0},
+			{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+			{".interp", SHT_PROGBITS, SHF_ALLOC, 0x80480d4, 0xd4, 0x15, 0x0, 0x0, 0x1, 0x0, 0x15},
+			{".hash", SHT_HASH, SHF_ALLOC, 0x80480ec, 0xec, 0x90, 0x3, 0x0, 0x4, 0x4, 0x90},
+			{".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x804817c, 0x17c, 0x110, 0x4, 0x1, 0x4, 0x10, 0x110},
+			{".dynstr", SHT_STRTAB, SHF_ALLOC, 0x804828c, 0x28c, 0xbb, 0x0, 0x0, 0x1, 0x0, 0xbb},
+			{".rel.plt", SHT_REL, SHF_ALLOC, 0x8048348, 0x348, 0x20, 0x3, 0x7, 0x4, 0x8, 0x20},
+			{".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x8048368, 0x368, 0x11, 0x0, 0x0, 0x4, 0x0, 0x11},
+			{".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x804837c, 0x37c, 0x50, 0x0, 0x0, 0x4, 0x4, 0x50},
+			{".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x80483cc, 0x3cc, 0x180, 0x0, 0x0, 0x4, 0x0, 0x180},
+			{".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x804854c, 0x54c, 0xc, 0x0, 0x0, 0x4, 0x0, 0xc},
+			{".rodata", SHT_PROGBITS, SHF_ALLOC, 0x8048558, 0x558, 0xa3, 0x0, 0x0, 0x1, 0x0, 0xa3},
+			{".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80495fc, 0x5fc, 0xc, 0x0, 0x0, 0x4, 0x0, 0xc},
+			{".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x8049608, 0x608, 0x4, 0x0, 0x0, 0x4, 0x0, 0x4},
+			{".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x804960c, 0x60c, 0x98, 0x4, 0x0, 0x4, 0x8, 0x98},
+			{".ctors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496a4, 0x6a4, 0x8, 0x0, 0x0, 0x4, 0x0, 0x8},
+			{".dtors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496ac, 0x6ac, 0x8, 0x0, 0x0, 0x4, 0x0, 0x8},
+			{".jcr", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496b4, 0x6b4, 0x4, 0x0, 0x0, 0x4, 0x0, 0x4},
+			{".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x80496b8, 0x6b8, 0x1c, 0x0, 0x0, 0x4, 0x4, 0x1c},
+			{".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x80496d4, 0x6d4, 0x20, 0x0, 0x0, 0x4, 0x0, 0x20},
+			{".comment", SHT_PROGBITS, 0x0, 0x0, 0x6d4, 0x12d, 0x0, 0x0, 0x1, 0x0, 0x12d},
+			{".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x801, 0x20, 0x0, 0x0, 0x1, 0x0, 0x20},
+			{".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0x821, 0x1b, 0x0, 0x0, 0x1, 0x0, 0x1b},
+			{".debug_info", SHT_PROGBITS, 0x0, 0x0, 0x83c, 0x11d, 0x0, 0x0, 0x1, 0x0, 0x11d},
+			{".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0x959, 0x41, 0x0, 0x0, 0x1, 0x0, 0x41},
+			{".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x99a, 0x35, 0x0, 0x0, 0x1, 0x0, 0x35},
+			{".debug_frame", SHT_PROGBITS, 0x0, 0x0, 0x9d0, 0x30, 0x0, 0x0, 0x4, 0x0, 0x30},
+			{".debug_str", SHT_PROGBITS, 0x0, 0x0, 0xa00, 0xd, 0x0, 0x0, 0x1, 0x0, 0xd},
+			{".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xa0d, 0xf8, 0x0, 0x0, 0x1, 0x0, 0xf8},
+			{".symtab", SHT_SYMTAB, 0x0, 0x0, 0xfb8, 0x4b0, 0x1d, 0x38, 0x4, 0x10, 0x4b0},
+			{".strtab", SHT_STRTAB, 0x0, 0x0, 0x1468, 0x206, 0x0, 0x0, 0x1, 0x0, 0x206},
 		},
 		[]ProgHeader{
 			{PT_PHDR, PF_R + PF_X, 0x34, 0x8048034, 0x8048034, 0xa0, 0xa0, 0x4},
@@ -75,43 +76,43 @@ var fileTests = []fileTest{
 		"testdata/gcc-amd64-linux-exec",
 		FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0, binary.LittleEndian, ET_EXEC, EM_X86_64, 0x4003e0},
 		[]SectionHeader{
-			{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
-			{".interp", SHT_PROGBITS, SHF_ALLOC, 0x400200, 0x200, 0x1c, 0x0, 0x0, 0x1, 0x0},
-			{".note.ABI-tag", SHT_NOTE, SHF_ALLOC, 0x40021c, 0x21c, 0x20, 0x0, 0x0, 0x4, 0x0},
-			{".hash", SHT_HASH, SHF_ALLOC, 0x400240, 0x240, 0x24, 0x5, 0x0, 0x8, 0x4},
-			{".gnu.hash", SHT_LOOS + 268435446, SHF_ALLOC, 0x400268, 0x268, 0x1c, 0x5, 0x0, 0x8, 0x0},
-			{".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x400288, 0x288, 0x60, 0x6, 0x1, 0x8, 0x18},
-			{".dynstr", SHT_STRTAB, SHF_ALLOC, 0x4002e8, 0x2e8, 0x3d, 0x0, 0x0, 0x1, 0x0},
-			{".gnu.version", SHT_HIOS, SHF_ALLOC, 0x400326, 0x326, 0x8, 0x5, 0x0, 0x2, 0x2},
-			{".gnu.version_r", SHT_LOOS + 268435454, SHF_ALLOC, 0x400330, 0x330, 0x20, 0x6, 0x1, 0x8, 0x0},
-			{".rela.dyn", SHT_RELA, SHF_ALLOC, 0x400350, 0x350, 0x18, 0x5, 0x0, 0x8, 0x18},
-			{".rela.plt", SHT_RELA, SHF_ALLOC, 0x400368, 0x368, 0x30, 0x5, 0xc, 0x8, 0x18},
-			{".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x400398, 0x398, 0x18, 0x0, 0x0, 0x4, 0x0},
-			{".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x4003b0, 0x3b0, 0x30, 0x0, 0x0, 0x4, 0x10},
-			{".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x4003e0, 0x3e0, 0x1b4, 0x0, 0x0, 0x10, 0x0},
-			{".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x400594, 0x594, 0xe, 0x0, 0x0, 0x4, 0x0},
-			{".rodata", SHT_PROGBITS, SHF_ALLOC, 0x4005a4, 0x5a4, 0x11, 0x0, 0x0, 0x4, 0x0},
-			{".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, 0x4005b8, 0x5b8, 0x24, 0x0, 0x0, 0x4, 0x0},
-			{".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x4005e0, 0x5e0, 0xa4, 0x0, 0x0, 0x8, 0x0},
-			{".ctors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600688, 0x688, 0x10, 0x0, 0x0, 0x8, 0x0},
-			{".dtors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600698, 0x698, 0x10, 0x0, 0x0, 0x8, 0x0},
-			{".jcr", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x6006a8, 0x6a8, 0x8, 0x0, 0x0, 0x8, 0x0},
-			{".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x6006b0, 0x6b0, 0x1a0, 0x6, 0x0, 0x8, 0x10},
-			{".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600850, 0x850, 0x8, 0x0, 0x0, 0x8, 0x8},
-			{".got.plt", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600858, 0x858, 0x28, 0x0, 0x0, 0x8, 0x8},
-			{".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600880, 0x880, 0x18, 0x0, 0x0, 0x8, 0x0},
-			{".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x600898, 0x898, 0x8, 0x0, 0x0, 0x4, 0x0},
-			{".comment", SHT_PROGBITS, 0x0, 0x0, 0x898, 0x126, 0x0, 0x0, 0x1, 0x0},
-			{".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x9c0, 0x90, 0x0, 0x0, 0x10, 0x0},
-			{".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0xa50, 0x25, 0x0, 0x0, 0x1, 0x0},
-			{".debug_info", SHT_PROGBITS, 0x0, 0x0, 0xa75, 0x1a7, 0x0, 0x0, 0x1, 0x0},
-			{".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xc1c, 0x6f, 0x0, 0x0, 0x1, 0x0},
-			{".debug_line", SHT_PROGBITS, 0x0, 0x0, 0xc8b, 0x13f, 0x0, 0x0, 0x1, 0x0},
-			{".debug_str", SHT_PROGBITS, SHF_MERGE + SHF_STRINGS, 0x0, 0xdca, 0xb1, 0x0, 0x0, 0x1, 0x1},
-			{".debug_ranges", SHT_PROGBITS, 0x0, 0x0, 0xe80, 0x90, 0x0, 0x0, 0x10, 0x0},
-			{".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xf10, 0x149, 0x0, 0x0, 0x1, 0x0},
-			{".symtab", SHT_SYMTAB, 0x0, 0x0, 0x19a0, 0x6f0, 0x24, 0x39, 0x8, 0x18},
-			{".strtab", SHT_STRTAB, 0x0, 0x0, 0x2090, 0x1fc, 0x0, 0x0, 0x1, 0x0},
+			{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+			{".interp", SHT_PROGBITS, SHF_ALLOC, 0x400200, 0x200, 0x1c, 0x0, 0x0, 0x1, 0x0, 0x1c},
+			{".note.ABI-tag", SHT_NOTE, SHF_ALLOC, 0x40021c, 0x21c, 0x20, 0x0, 0x0, 0x4, 0x0, 0x20},
+			{".hash", SHT_HASH, SHF_ALLOC, 0x400240, 0x240, 0x24, 0x5, 0x0, 0x8, 0x4, 0x24},
+			{".gnu.hash", SHT_LOOS + 268435446, SHF_ALLOC, 0x400268, 0x268, 0x1c, 0x5, 0x0, 0x8, 0x0, 0x1c},
+			{".dynsym", SHT_DYNSYM, SHF_ALLOC, 0x400288, 0x288, 0x60, 0x6, 0x1, 0x8, 0x18, 0x60},
+			{".dynstr", SHT_STRTAB, SHF_ALLOC, 0x4002e8, 0x2e8, 0x3d, 0x0, 0x0, 0x1, 0x0, 0x3d},
+			{".gnu.version", SHT_HIOS, SHF_ALLOC, 0x400326, 0x326, 0x8, 0x5, 0x0, 0x2, 0x2, 0x8},
+			{".gnu.version_r", SHT_LOOS + 268435454, SHF_ALLOC, 0x400330, 0x330, 0x20, 0x6, 0x1, 0x8, 0x0, 0x20},
+			{".rela.dyn", SHT_RELA, SHF_ALLOC, 0x400350, 0x350, 0x18, 0x5, 0x0, 0x8, 0x18, 0x18},
+			{".rela.plt", SHT_RELA, SHF_ALLOC, 0x400368, 0x368, 0x30, 0x5, 0xc, 0x8, 0x18, 0x30},
+			{".init", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x400398, 0x398, 0x18, 0x0, 0x0, 0x4, 0x0, 0x18},
+			{".plt", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x4003b0, 0x3b0, 0x30, 0x0, 0x0, 0x4, 0x10, 0x30},
+			{".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x4003e0, 0x3e0, 0x1b4, 0x0, 0x0, 0x10, 0x0, 0x1b4},
+			{".fini", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR, 0x400594, 0x594, 0xe, 0x0, 0x0, 0x4, 0x0, 0xe},
+			{".rodata", SHT_PROGBITS, SHF_ALLOC, 0x4005a4, 0x5a4, 0x11, 0x0, 0x0, 0x4, 0x0, 0x11},
+			{".eh_frame_hdr", SHT_PROGBITS, SHF_ALLOC, 0x4005b8, 0x5b8, 0x24, 0x0, 0x0, 0x4, 0x0, 0x24},
+			{".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x4005e0, 0x5e0, 0xa4, 0x0, 0x0, 0x8, 0x0, 0xa4},
+			{".ctors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600688, 0x688, 0x10, 0x0, 0x0, 0x8, 0x0, 0x10},
+			{".dtors", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600698, 0x698, 0x10, 0x0, 0x0, 0x8, 0x0, 0x10},
+			{".jcr", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x6006a8, 0x6a8, 0x8, 0x0, 0x0, 0x8, 0x0, 0x8},
+			{".dynamic", SHT_DYNAMIC, SHF_WRITE + SHF_ALLOC, 0x6006b0, 0x6b0, 0x1a0, 0x6, 0x0, 0x8, 0x10, 0x1a0},
+			{".got", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600850, 0x850, 0x8, 0x0, 0x0, 0x8, 0x8, 0x8},
+			{".got.plt", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600858, 0x858, 0x28, 0x0, 0x0, 0x8, 0x8, 0x28},
+			{".data", SHT_PROGBITS, SHF_WRITE + SHF_ALLOC, 0x600880, 0x880, 0x18, 0x0, 0x0, 0x8, 0x0, 0x18},
+			{".bss", SHT_NOBITS, SHF_WRITE + SHF_ALLOC, 0x600898, 0x898, 0x8, 0x0, 0x0, 0x4, 0x0, 0x8},
+			{".comment", SHT_PROGBITS, 0x0, 0x0, 0x898, 0x126, 0x0, 0x0, 0x1, 0x0, 0x126},
+			{".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x9c0, 0x90, 0x0, 0x0, 0x10, 0x0, 0x90},
+			{".debug_pubnames", SHT_PROGBITS, 0x0, 0x0, 0xa50, 0x25, 0x0, 0x0, 0x1, 0x0, 0x25},
+			{".debug_info", SHT_PROGBITS, 0x0, 0x0, 0xa75, 0x1a7, 0x0, 0x0, 0x1, 0x0, 0x1a7},
+			{".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xc1c, 0x6f, 0x0, 0x0, 0x1, 0x0, 0x6f},
+			{".debug_line", SHT_PROGBITS, 0x0, 0x0, 0xc8b, 0x13f, 0x0, 0x0, 0x1, 0x0, 0x13f},
+			{".debug_str", SHT_PROGBITS, SHF_MERGE + SHF_STRINGS, 0x0, 0xdca, 0xb1, 0x0, 0x0, 0x1, 0x1, 0xb1},
+			{".debug_ranges", SHT_PROGBITS, 0x0, 0x0, 0xe80, 0x90, 0x0, 0x0, 0x10, 0x0, 0x90},
+			{".shstrtab", SHT_STRTAB, 0x0, 0x0, 0xf10, 0x149, 0x0, 0x0, 0x1, 0x0, 0x149},
+			{".symtab", SHT_SYMTAB, 0x0, 0x0, 0x19a0, 0x6f0, 0x24, 0x39, 0x8, 0x18, 0x6f0},
+			{".strtab", SHT_STRTAB, 0x0, 0x0, 0x2090, 0x1fc, 0x0, 0x0, 0x1, 0x0, 0x1fc},
 		},
 		[]ProgHeader{
 			{PT_PHDR, PF_R + PF_X, 0x40, 0x400040, 0x400040, 0x1c0, 0x1c0, 0x8},
@@ -150,6 +151,64 @@ var fileTests = []fileTest{
 		},
 		nil,
 	},
+	{
+		"testdata/compressed-32.obj",
+		FileHeader{ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_REL, EM_386, 0x0},
+		[]SectionHeader{
+			{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+			{".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, 0x0, 0x34, 0x17, 0x0, 0x0, 0x1, 0x0, 0x17},
+			{".rel.text", SHT_REL, SHF_INFO_LINK, 0x0, 0x3dc, 0x10, 0x13, 0x1, 0x4, 0x8, 0x10},
+			{".data", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x4b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
+			{".bss", SHT_NOBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x4b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
+			{".rodata", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x4b, 0xd, 0x0, 0x0, 0x1, 0x0, 0xd},
+			{".debug_info", SHT_PROGBITS, SHF_COMPRESSED, 0x0, 0x58, 0xb4, 0x0, 0x0, 0x1, 0x0, 0x84},
+			{".rel.debug_info", SHT_REL, SHF_INFO_LINK, 0x0, 0x3ec, 0xa0, 0x13, 0x6, 0x4, 0x8, 0xa0},
+			{".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xdc, 0x5a, 0x0, 0x0, 0x1, 0x0, 0x5a},
+			{".debug_aranges", SHT_PROGBITS, 0x0, 0x0, 0x136, 0x20, 0x0, 0x0, 0x1, 0x0, 0x20},
+			{".rel.debug_aranges", SHT_REL, SHF_INFO_LINK, 0x0, 0x48c, 0x10, 0x13, 0x9, 0x4, 0x8, 0x10},
+			{".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x156, 0x5c, 0x0, 0x0, 0x1, 0x0, 0x5c},
+			{".rel.debug_line", SHT_REL, SHF_INFO_LINK, 0x0, 0x49c, 0x8, 0x13, 0xb, 0x4, 0x8, 0x8},
+			{".debug_str", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS | SHF_COMPRESSED, 0x0, 0x1b2, 0x10f, 0x0, 0x0, 0x1, 0x1, 0xb3},
+			{".comment", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS, 0x0, 0x265, 0x2a, 0x0, 0x0, 0x1, 0x1, 0x2a},
+			{".note.GNU-stack", SHT_PROGBITS, 0x0, 0x0, 0x28f, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
+			{".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x290, 0x38, 0x0, 0x0, 0x4, 0x0, 0x38},
+			{".rel.eh_frame", SHT_REL, SHF_INFO_LINK, 0x0, 0x4a4, 0x8, 0x13, 0x10, 0x4, 0x8, 0x8},
+			{".shstrtab", SHT_STRTAB, 0x0, 0x0, 0x4ac, 0xab, 0x0, 0x0, 0x1, 0x0, 0xab},
+			{".symtab", SHT_SYMTAB, 0x0, 0x0, 0x2c8, 0x100, 0x14, 0xe, 0x4, 0x10, 0x100},
+			{".strtab", SHT_STRTAB, 0x0, 0x0, 0x3c8, 0x13, 0x0, 0x0, 0x1, 0x0, 0x13},
+		},
+		[]ProgHeader{},
+		nil,
+	},
+	{
+		"testdata/compressed-64.obj",
+		FileHeader{ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE, 0x0, binary.LittleEndian, ET_REL, EM_X86_64, 0x0},
+		[]SectionHeader{
+			{"", SHT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+			{".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, 0x0, 0x40, 0x1b, 0x0, 0x0, 0x1, 0x0, 0x1b},
+			{".rela.text", SHT_RELA, SHF_INFO_LINK, 0x0, 0x488, 0x30, 0x13, 0x1, 0x8, 0x18, 0x30},
+			{".data", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x5b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
+			{".bss", SHT_NOBITS, SHF_WRITE | SHF_ALLOC, 0x0, 0x5b, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
+			{".rodata", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x5b, 0xd, 0x0, 0x0, 0x1, 0x0, 0xd},
+			{".debug_info", SHT_PROGBITS, SHF_COMPRESSED, 0x0, 0x68, 0xba, 0x0, 0x0, 0x1, 0x0, 0x72},
+			{".rela.debug_info", SHT_RELA, SHF_INFO_LINK, 0x0, 0x4b8, 0x1c8, 0x13, 0x6, 0x8, 0x18, 0x1c8},
+			{".debug_abbrev", SHT_PROGBITS, 0x0, 0x0, 0xda, 0x5c, 0x0, 0x0, 0x1, 0x0, 0x5c},
+			{".debug_aranges", SHT_PROGBITS, SHF_COMPRESSED, 0x0, 0x136, 0x30, 0x0, 0x0, 0x1, 0x0, 0x2f},
+			{".rela.debug_aranges", SHT_RELA, SHF_INFO_LINK, 0x0, 0x680, 0x30, 0x13, 0x9, 0x8, 0x18, 0x30},
+			{".debug_line", SHT_PROGBITS, 0x0, 0x0, 0x165, 0x60, 0x0, 0x0, 0x1, 0x0, 0x60},
+			{".rela.debug_line", SHT_RELA, SHF_INFO_LINK, 0x0, 0x6b0, 0x18, 0x13, 0xb, 0x8, 0x18, 0x18},
+			{".debug_str", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS | SHF_COMPRESSED, 0x0, 0x1c5, 0x104, 0x0, 0x0, 0x1, 0x1, 0xc3},
+			{".comment", SHT_PROGBITS, SHF_MERGE | SHF_STRINGS, 0x0, 0x288, 0x2a, 0x0, 0x0, 0x1, 0x1, 0x2a},
+			{".note.GNU-stack", SHT_PROGBITS, 0x0, 0x0, 0x2b2, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0},
+			{".eh_frame", SHT_PROGBITS, SHF_ALLOC, 0x0, 0x2b8, 0x38, 0x0, 0x0, 0x8, 0x0, 0x38},
+			{".rela.eh_frame", SHT_RELA, SHF_INFO_LINK, 0x0, 0x6c8, 0x18, 0x13, 0x10, 0x8, 0x18, 0x18},
+			{".shstrtab", SHT_STRTAB, 0x0, 0x0, 0x6e0, 0xb0, 0x0, 0x0, 0x1, 0x0, 0xb0},
+			{".symtab", SHT_SYMTAB, 0x0, 0x0, 0x2f0, 0x180, 0x14, 0xe, 0x8, 0x18, 0x180},
+			{".strtab", SHT_STRTAB, 0x0, 0x0, 0x470, 0x13, 0x0, 0x0, 0x1, 0x0, 0x13},
+		},
+		[]ProgHeader{},
+		nil,
+	},
 }
 
 func TestOpen(t *testing.T) {
@@ -245,62 +304,237 @@ var relocationTests = []relocationTest{
 	{
 		"testdata/go-relocation-test-gcc441-x86-64.obj",
 		[]relocationTestEntry{
-			{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString}, {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, {Attr: dwarf.AttrName, Val: "go-relocation-test.c", Class: dwarf.ClassString}, {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, {Attr: dwarf.AttrHighpc, Val: uint6 [...]
+			{0, &dwarf.Entry{
+				Offset:   0xb,
+				Tag:      dwarf.TagCompileUnit,
+				Children: true,
+				Field: []dwarf.Field{
+					{Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
+					{Attr: dwarf.AttrName, Val: "go-relocation-test.c", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
+					{Attr: dwarf.AttrHighpc, Val: uint64(0x6), Class: dwarf.ClassAddress},
+					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
+				},
+			}},
 		},
 	},
 	{
 		"testdata/go-relocation-test-gcc441-x86.obj",
 		[]relocationTestEntry{
-			{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString}, {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, {Attr: dwarf.AttrName, Val: "t.c", Class: dwarf.ClassString}, {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, {Attr: dwarf.AttrHighpc, Val: uint64(0x5), Class: dw [...]
+			{0, &dwarf.Entry{
+				Offset:   0xb,
+				Tag:      dwarf.TagCompileUnit,
+				Children: true,
+				Field: []dwarf.Field{
+					{Attr: dwarf.AttrProducer, Val: "GNU C 4.4.1", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
+					{Attr: dwarf.AttrName, Val: "t.c", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
+					{Attr: dwarf.AttrHighpc, Val: uint64(0x5), Class: dwarf.ClassAddress},
+					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
+				},
+			}},
 		},
 	},
 	{
 		"testdata/go-relocation-test-gcc424-x86-64.obj",
 		[]relocationTestEntry{
-			{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.2.4 (Ubuntu 4.2.4-1ubuntu4)", Class: dwarf.ClassString}, {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc424.c", Class: dwarf.ClassString}, {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, {Att [...]
+			{0, &dwarf.Entry{
+				Offset:   0xb,
+				Tag:      dwarf.TagCompileUnit,
+				Children: true,
+				Field: []dwarf.Field{
+					{Attr: dwarf.AttrProducer, Val: "GNU C 4.2.4 (Ubuntu 4.2.4-1ubuntu4)", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
+					{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc424.c", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
+					{Attr: dwarf.AttrHighpc, Val: uint64(0x6), Class: dwarf.ClassAddress},
+					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
+				},
+			}},
 		},
 	},
 	{
 		"testdata/go-relocation-test-gcc482-aarch64.obj",
 		[]relocationTestEntry{
-			{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -g -fstack-protector", Class: dwarf.ClassString}, {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482.c", Class: dwarf.ClassString}, {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, {Attr:  [...]
+			{0, &dwarf.Entry{
+				Offset:   0xb,
+				Tag:      dwarf.TagCompileUnit,
+				Children: true,
+				Field: []dwarf.Field{
+					{Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -g -fstack-protector", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
+					{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482.c", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
+					{Attr: dwarf.AttrHighpc, Val: int64(0x24), Class: dwarf.ClassConstant},
+					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
+				},
+			}},
 		},
 	},
 	{
 		"testdata/go-relocation-test-gcc492-arm.obj",
 		[]relocationTestEntry{
-			{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 20141224 (prerelease) -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -mtls-dialect=gnu -g", Class: dwarf.ClassString}, {Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, {Attr: dwarf.AttrName, Val: "go-relocation-test-gcc492.c", Class: dwarf.ClassString}, {Attr: dwarf.AttrCompDir, Val: "/root/go/src/debug/elf/testdata", Class:  [...]
+			{0, &dwarf.Entry{
+				Offset:   0xb,
+				Tag:      dwarf.TagCompileUnit,
+				Children: true,
+				Field: []dwarf.Field{
+					{Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 20141224 (prerelease) -march=armv7-a -mfloat-abi=hard -mfpu=vfpv3-d16 -mtls-dialect=gnu -g", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
+					{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc492.c", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrCompDir, Val: "/root/go/src/debug/elf/testdata", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
+					{Attr: dwarf.AttrHighpc, Val: int64(0x28), Class: dwarf.ClassConstant},
+					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
+				},
+			}},
 		},
 	},
 	{
 		"testdata/go-relocation-test-clang-arm.obj",
 		[]relocationTestEntry{
-			{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{dwarf.Field{Attr: dwarf.AttrProducer, Val: "Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)", Class: dwarf.ClassString}, dwarf.Field{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, dwarf.Field{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, dwarf.Field{Attr: dwarf.AttrStmtList, Val: int64(0x0), Class: dwarf.ClassLinePtr}, dw [...]
+			{0, &dwarf.Entry{
+				Offset:   0xb,
+				Tag:      dwarf.TagCompileUnit,
+				Children: true,
+				Field: []dwarf.Field{
+					{Attr: dwarf.AttrProducer, Val: "Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
+					{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrStmtList, Val: int64(0x0), Class: dwarf.ClassLinePtr},
+					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
+					{Attr: dwarf.AttrHighpc, Val: int64(48), Class: dwarf.ClassConstant},
+				},
+			}},
 		},
 	},
 	{
 		"testdata/go-relocation-test-gcc5-ppc.obj",
 		[]relocationTestEntry{
-			{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{dwarf.Field{Attr: dwarf.AttrProducer, Val: "GNU C11 5.0.0 20150116 (experimental) -Asystem=linux -Asystem=unix -Asystem=posix -g", Class: dwarf.ClassString}, dwarf.Field{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, dwarf.Field{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc5-ppc.c", Class: dwarf.ClassString}, dwarf.Field{Attr: dwarf.AttrCompDir, Val: "/tmp", Class [...]
+			{0, &dwarf.Entry{
+				Offset:   0xb,
+				Tag:      dwarf.TagCompileUnit,
+				Children: true,
+				Field: []dwarf.Field{
+					{Attr: dwarf.AttrProducer, Val: "GNU C11 5.0.0 20150116 (experimental) -Asystem=linux -Asystem=unix -Asystem=posix -g", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
+					{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc5-ppc.c", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
+					{Attr: dwarf.AttrHighpc, Val: int64(0x44), Class: dwarf.ClassConstant},
+					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
+				},
+			}},
 		},
 	},
 	{
 		"testdata/go-relocation-test-gcc482-ppc64le.obj",
 		[]relocationTestEntry{
-			{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{dwarf.Field{Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -Asystem=linux -Asystem=unix -Asystem=posix -msecure-plt -mtune=power8 -mcpu=power7 -gdwarf-2 -fstack-protector", Class: dwarf.ClassString}, dwarf.Field{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant}, dwarf.Field{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482-ppc64le.c", Class: dwarf.ClassString}, dwarf.Field [...]
+			{0, &dwarf.Entry{
+				Offset:   0xb,
+				Tag:      dwarf.TagCompileUnit,
+				Children: true,
+				Field: []dwarf.Field{
+					{Attr: dwarf.AttrProducer, Val: "GNU C 4.8.2 -Asystem=linux -Asystem=unix -Asystem=posix -msecure-plt -mtune=power8 -mcpu=power7 -gdwarf-2 -fstack-protector", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
+					{Attr: dwarf.AttrName, Val: "go-relocation-test-gcc482-ppc64le.c", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
+					{Attr: dwarf.AttrHighpc, Val: uint64(0x24), Class: dwarf.ClassAddress},
+					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
+				},
+			}},
+		},
+	},
+	{
+		"testdata/go-relocation-test-gcc492-mips64.obj",
+		[]relocationTestEntry{
+			{0, &dwarf.Entry{
+				Offset:   0xb,
+				Tag:      dwarf.TagCompileUnit,
+				Children: true,
+				Field: []dwarf.Field{
+					{Attr: dwarf.AttrProducer, Val: "GNU C 4.9.2 -meb -mabi=64 -march=mips3 -mtune=mips64 -mllsc -mno-shared -g", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
+					{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
+					{Attr: dwarf.AttrHighpc, Val: int64(100), Class: dwarf.ClassConstant},
+					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
+				},
+			}},
+		},
+	},
+	{
+		"testdata/go-relocation-test-gcc493-mips64le.obj",
+		[]relocationTestEntry{
+			{0, &dwarf.Entry{
+				Offset:   0xb,
+				Tag:      dwarf.TagCompileUnit,
+				Children: true,
+				Field: []dwarf.Field{
+					{Attr: dwarf.AttrProducer, Val: "GNU C 4.9.3 -mel -mabi=64 -mllsc -mno-shared -g -fstack-protector-strong", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrLanguage, Val: int64(1), Class: dwarf.ClassConstant},
+					{Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress},
+					{Attr: dwarf.AttrHighpc, Val: int64(100), Class: dwarf.ClassConstant},
+					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
+				},
+			}},
 		},
 	},
 	{
 		"testdata/go-relocation-test-clang-x86.obj",
 		[]relocationTestEntry{
-			{0, &dwarf.Entry{Offset: 0xb, Tag: dwarf.TagCompileUnit, Children: true, Field: []dwarf.Field{{Attr: dwarf.AttrProducer, Val: "clang version google3-trunk (trunk r209387)", Class: dwarf.ClassString}, {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, {Attr: dwarf.AttrName, Val: "go-relocation-test-clang.c", Class: dwarf.ClassString}, {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}}}},
+			{0, &dwarf.Entry{
+				Offset:   0xb,
+				Tag:      dwarf.TagCompileUnit,
+				Children: true,
+				Field: []dwarf.Field{
+					{Attr: dwarf.AttrProducer, Val: "clang version google3-trunk (trunk r209387)", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant},
+					{Attr: dwarf.AttrName, Val: "go-relocation-test-clang.c", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr},
+					{Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString},
+				},
+			}},
 		},
 	},
 	{
 		"testdata/gcc-amd64-openbsd-debug-with-rela.obj",
 		[]relocationTestEntry{
-			{203, &dwarf.Entry{Offset: 0xc62, Tag: dwarf.TagMember, Children: false, Field: []dwarf.Field{{Attr: dwarf.AttrName, Val: "it_interval", Class: dwarf.ClassString}, {Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant}, {Attr: dwarf.AttrDeclLine, Val: int64(236), Class: dwarf.ClassConstant}, {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference}, {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x0}, Class: dwarf.ClassExprLoc}}}},
-			{204, &dwarf.Entry{Offset: 0xc70, Tag: dwarf.TagMember, Children: false, Field: []dwarf.Field{{Attr: dwarf.AttrName, Val: "it_value", Class: dwarf.ClassString}, {Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant}, {Attr: dwarf.AttrDeclLine, Val: int64(237), Class: dwarf.ClassConstant}, {Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference}, {Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x10}, Class: dwarf.ClassExprLoc}}}},
+			{203, &dwarf.Entry{
+				Offset:   0xc62,
+				Tag:      dwarf.TagMember,
+				Children: false,
+				Field: []dwarf.Field{
+					{Attr: dwarf.AttrName, Val: "it_interval", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant},
+					{Attr: dwarf.AttrDeclLine, Val: int64(236), Class: dwarf.ClassConstant},
+					{Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference},
+					{Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x0}, Class: dwarf.ClassExprLoc},
+				},
+			}},
+			{204, &dwarf.Entry{
+				Offset:   0xc70,
+				Tag:      dwarf.TagMember,
+				Children: false,
+				Field: []dwarf.Field{
+					{Attr: dwarf.AttrName, Val: "it_value", Class: dwarf.ClassString},
+					{Attr: dwarf.AttrDeclFile, Val: int64(7), Class: dwarf.ClassConstant},
+					{Attr: dwarf.AttrDeclLine, Val: int64(237), Class: dwarf.ClassConstant},
+					{Attr: dwarf.AttrType, Val: dwarf.Offset(0xb7f), Class: dwarf.ClassReference},
+					{Attr: dwarf.AttrDataMemberLoc, Val: []byte{0x23, 0x10}, Class: dwarf.ClassExprLoc},
+				},
+			}},
 		},
 	},
 }
@@ -339,6 +573,119 @@ func TestDWARFRelocations(t *testing.T) {
 	}
 }
 
+func TestCompressedDWARF(t *testing.T) {
+	// Test file built with GCC 4.8.4 and as 2.24 using:
+	// gcc -Wa,--compress-debug-sections -g -c -o zdebug-test-gcc484-x86-64.obj hello.c
+	f, err := Open("testdata/zdebug-test-gcc484-x86-64.obj")
+	if err != nil {
+		t.Fatal(err)
+	}
+	dwarf, err := f.DWARF()
+	if err != nil {
+		t.Fatal(err)
+	}
+	reader := dwarf.Reader()
+	n := 0
+	for {
+		entry, err := reader.Next()
+		if err != nil {
+			t.Fatal(err)
+		}
+		if entry == nil {
+			break
+		}
+		n++
+	}
+	if n != 18 {
+		t.Fatalf("want %d DWARF entries, got %d", 18, n)
+	}
+}
+
+func TestCompressedSection(t *testing.T) {
+	// Test files built with gcc -g -S hello.c and assembled with
+	// --compress-debug-sections=zlib-gabi.
+	f, err := Open("testdata/compressed-64.obj")
+	if err != nil {
+		t.Fatal(err)
+	}
+	sec := f.Section(".debug_info")
+	wantData := []byte{
+		182, 0, 0, 0, 4, 0, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0,
+		1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7,
+		0, 0, 0, 0, 2, 1, 8, 0, 0, 0, 0, 2, 2, 7, 0, 0,
+		0, 0, 2, 4, 7, 0, 0, 0, 0, 2, 1, 6, 0, 0, 0, 0,
+		2, 2, 5, 0, 0, 0, 0, 3, 4, 5, 105, 110, 116, 0, 2, 8,
+		5, 0, 0, 0, 0, 2, 8, 7, 0, 0, 0, 0, 4, 8, 114, 0,
+		0, 0, 2, 1, 6, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 4,
+		0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0,
+		1, 156, 179, 0, 0, 0, 6, 0, 0, 0, 0, 1, 4, 87, 0, 0,
+		0, 2, 145, 108, 6, 0, 0, 0, 0, 1, 4, 179, 0, 0, 0, 2,
+		145, 96, 0, 4, 8, 108, 0, 0, 0, 0,
+	}
+
+	// Test Data method.
+	b, err := sec.Data()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !bytes.Equal(wantData, b) {
+		t.Fatalf("want data %x, got %x", wantData, b)
+	}
+
+	// Test Open method and seeking.
+	buf, have, count := make([]byte, len(b)), make([]bool, len(b)), 0
+	sf := sec.Open()
+	if got, err := sf.Seek(0, 2); got != int64(len(b)) || err != nil {
+		t.Fatalf("want seek end %d, got %d error %v", len(b), got, err)
+	}
+	if n, err := sf.Read(buf); n != 0 || err != io.EOF {
+		t.Fatalf("want EOF with 0 bytes, got %v with %d bytes", err, n)
+	}
+	pos := int64(len(buf))
+	for count < len(buf) {
+		// Construct random seek arguments.
+		whence := rand.Intn(3)
+		target := rand.Int63n(int64(len(buf)))
+		var offset int64
+		switch whence {
+		case 0:
+			offset = target
+		case 1:
+			offset = target - pos
+		case 2:
+			offset = target - int64(len(buf))
+		}
+		pos, err = sf.Seek(offset, whence)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if pos != target {
+			t.Fatalf("want position %d, got %d", target, pos)
+		}
+
+		// Read data from the new position.
+		end := pos + 16
+		if end > int64(len(buf)) {
+			end = int64(len(buf))
+		}
+		n, err := sf.Read(buf[pos:end])
+		if err != nil {
+			t.Fatal(err)
+		}
+		for i := 0; i < n; i++ {
+			if !have[pos] {
+				have[pos] = true
+				count++
+			}
+			pos++
+		}
+	}
+	if !bytes.Equal(wantData, buf) {
+		t.Fatalf("want data %x, got %x", wantData, buf)
+	}
+}
+
 func TestNoSectionOverlaps(t *testing.T) {
 	// Ensure 6l outputs sections without overlaps.
 	if runtime.GOOS != "linux" && runtime.GOOS != "freebsd" {
diff --git a/src/debug/elf/reader.go b/src/debug/elf/reader.go
new file mode 100644
index 0000000..17b5716
--- /dev/null
+++ b/src/debug/elf/reader.go
@@ -0,0 +1,108 @@
+// Copyright 2015 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 elf
+
+import (
+	"io"
+	"os"
+)
+
+// errorReader returns error from all operations.
+type errorReader struct {
+	error
+}
+
+func (r errorReader) Read(p []byte) (n int, err error) {
+	return 0, r.error
+}
+
+func (r errorReader) ReadAt(p []byte, off int64) (n int, err error) {
+	return 0, r.error
+}
+
+func (r errorReader) Seek(offset int64, whence int) (int64, error) {
+	return 0, r.error
+}
+
+func (r errorReader) Close() error {
+	return r.error
+}
+
+// readSeekerFromReader converts an io.Reader into an io.ReadSeeker.
+// In general Seek may not be efficient, but it is optimized for
+// common cases such as seeking to the end to find the length of the
+// data.
+type readSeekerFromReader struct {
+	reset  func() (io.Reader, error)
+	r      io.Reader
+	size   int64
+	offset int64
+}
+
+func (r *readSeekerFromReader) start() {
+	x, err := r.reset()
+	if err != nil {
+		r.r = errorReader{err}
+	} else {
+		r.r = x
+	}
+	r.offset = 0
+}
+
+func (r *readSeekerFromReader) Read(p []byte) (n int, err error) {
+	if r.r == nil {
+		r.start()
+	}
+	n, err = r.r.Read(p)
+	r.offset += int64(n)
+	return n, err
+}
+
+func (r *readSeekerFromReader) Seek(offset int64, whence int) (int64, error) {
+	var newOffset int64
+	switch whence {
+	case 0:
+		newOffset = offset
+	case 1:
+		newOffset = r.offset + offset
+	case 2:
+		newOffset = r.size + offset
+	default:
+		return 0, os.ErrInvalid
+	}
+
+	switch {
+	case newOffset == r.offset:
+		return newOffset, nil
+
+	case newOffset < 0, newOffset > r.size:
+		return 0, os.ErrInvalid
+
+	case newOffset == 0:
+		r.r = nil
+
+	case newOffset == r.size:
+		r.r = errorReader{io.EOF}
+
+	default:
+		if newOffset < r.offset {
+			// Restart at the beginning.
+			r.start()
+		}
+		// Read until we reach offset.
+		var buf [512]byte
+		for r.offset < newOffset {
+			b := buf[:]
+			if newOffset-r.offset < int64(len(buf)) {
+				b = buf[:newOffset-r.offset]
+			}
+			if _, err := r.Read(b); err != nil {
+				return 0, err
+			}
+		}
+	}
+	r.offset = newOffset
+	return r.offset, nil
+}
diff --git a/src/debug/elf/testdata/compressed-32.obj b/src/debug/elf/testdata/compressed-32.obj
new file mode 100644
index 0000000..2bfdb44
Binary files /dev/null and b/src/debug/elf/testdata/compressed-32.obj differ
diff --git a/src/debug/elf/testdata/compressed-64.obj b/src/debug/elf/testdata/compressed-64.obj
new file mode 100644
index 0000000..ffae56a
Binary files /dev/null and b/src/debug/elf/testdata/compressed-64.obj differ
diff --git a/src/debug/elf/testdata/gcc-386-freebsd-exec b/src/debug/elf/testdata/gcc-386-freebsd-exec
old mode 100755
new mode 100644
diff --git a/src/debug/elf/testdata/gcc-amd64-linux-exec b/src/debug/elf/testdata/gcc-amd64-linux-exec
old mode 100755
new mode 100644
diff --git a/src/debug/elf/testdata/go-relocation-test-gcc492-mips64.obj b/src/debug/elf/testdata/go-relocation-test-gcc492-mips64.obj
new file mode 100644
index 0000000..68febe1
Binary files /dev/null and b/src/debug/elf/testdata/go-relocation-test-gcc492-mips64.obj differ
diff --git a/src/debug/elf/testdata/go-relocation-test-gcc493-mips64le.obj b/src/debug/elf/testdata/go-relocation-test-gcc493-mips64le.obj
new file mode 100644
index 0000000..20bbd6c
Binary files /dev/null and b/src/debug/elf/testdata/go-relocation-test-gcc493-mips64le.obj differ
diff --git a/src/debug/elf/testdata/zdebug-test-gcc484-x86-64.obj b/src/debug/elf/testdata/zdebug-test-gcc484-x86-64.obj
new file mode 100644
index 0000000..a595a01
Binary files /dev/null and b/src/debug/elf/testdata/zdebug-test-gcc484-x86-64.obj differ
diff --git a/src/debug/gosym/pclntab_test.go b/src/debug/gosym/pclntab_test.go
index 53f3e95..8d4aa54 100644
--- a/src/debug/gosym/pclntab_test.go
+++ b/src/debug/gosym/pclntab_test.go
@@ -6,6 +6,7 @@ package gosym
 
 import (
 	"debug/elf"
+	"internal/testenv"
 	"io/ioutil"
 	"os"
 	"os/exec"
@@ -20,25 +21,16 @@ var (
 	pclinetestBinary string
 )
 
-func dotest(self bool) bool {
+func dotest(t *testing.T) {
+	testenv.MustHaveGoBuild(t)
 	// For now, only works on amd64 platforms.
 	if runtime.GOARCH != "amd64" {
-		return false
-	}
-	// Self test reads test binary; only works on Linux.
-	if self && runtime.GOOS != "linux" {
-		return false
-	}
-	if pclinetestBinary != "" {
-		return true
+		t.Skipf("skipping on non-AMD64 system %s", runtime.GOARCH)
 	}
 	var err error
 	pclineTempDir, err = ioutil.TempDir("", "pclinetest")
 	if err != nil {
-		panic(err)
-	}
-	if strings.Contains(pclineTempDir, " ") {
-		panic("unexpected space in tempdir")
+		t.Fatal(err)
 	}
 	// This command builds pclinetest from pclinetest.asm;
 	// the resulting binary looks like it was built from pclinetest.s,
@@ -48,16 +40,15 @@ func dotest(self bool) bool {
 	cmd.Stdout = os.Stdout
 	cmd.Stderr = os.Stderr
 	if err := cmd.Run(); err != nil {
-		panic(err)
+		t.Fatal(err)
 	}
 	cmd = exec.Command("go", "tool", "link", "-H", "linux", "-E", "main",
 		"-o", pclinetestBinary, pclinetestBinary+".o")
 	cmd.Stdout = os.Stdout
 	cmd.Stderr = os.Stderr
 	if err := cmd.Run(); err != nil {
-		panic(err)
+		t.Fatal(err)
 	}
-	return true
 }
 
 func endtest() {
@@ -68,6 +59,17 @@ func endtest() {
 	}
 }
 
+// skipIfNotELF skips the test if we are not running on an ELF system.
+// These tests open and examine the test binary, and use elf.Open to do so.
+func skipIfNotELF(t *testing.T) {
+	switch runtime.GOOS {
+	case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
+		// OK.
+	default:
+		t.Skipf("skipping on non-ELF system %s", runtime.GOOS)
+	}
+}
+
 func getTable(t *testing.T) *Table {
 	f, tab := crack(os.Args[0], t)
 	f.Close()
@@ -112,10 +114,7 @@ func parse(file string, f *elf.File, t *testing.T) (*elf.File, *Table) {
 var goarch = os.Getenv("O")
 
 func TestLineFromAline(t *testing.T) {
-	if !dotest(true) {
-		return
-	}
-	defer endtest()
+	skipIfNotELF(t)
 
 	tab := getTable(t)
 	if tab.go12line != nil {
@@ -164,10 +163,7 @@ func TestLineFromAline(t *testing.T) {
 }
 
 func TestLineAline(t *testing.T) {
-	if !dotest(true) {
-		return
-	}
-	defer endtest()
+	skipIfNotELF(t)
 
 	tab := getTable(t)
 	if tab.go12line != nil {
@@ -210,9 +206,7 @@ func TestLineAline(t *testing.T) {
 }
 
 func TestPCLine(t *testing.T) {
-	if !dotest(false) {
-		return
-	}
+	dotest(t)
 	defer endtest()
 
 	f, tab := crack(pclinetestBinary, t)
diff --git a/src/debug/macho/testdata/gcc-386-darwin-exec b/src/debug/macho/testdata/gcc-386-darwin-exec
old mode 100755
new mode 100644
diff --git a/src/debug/macho/testdata/gcc-amd64-darwin-exec b/src/debug/macho/testdata/gcc-amd64-darwin-exec
old mode 100755
new mode 100644
diff --git a/src/debug/plan9obj/testdata/386-plan9-exec b/src/debug/plan9obj/testdata/386-plan9-exec
old mode 100755
new mode 100644
diff --git a/src/debug/plan9obj/testdata/amd64-plan9-exec b/src/debug/plan9obj/testdata/amd64-plan9-exec
old mode 100755
new mode 100644
diff --git a/src/encoding/asn1/asn1.go b/src/encoding/asn1/asn1.go
index 2ac411a..8bafefd 100644
--- a/src/encoding/asn1/asn1.go
+++ b/src/encoding/asn1/asn1.go
@@ -71,9 +71,28 @@ func parseBool(bytes []byte) (ret bool, err error) {
 
 // INTEGER
 
+// checkInteger returns nil if the given bytes are a valid DER-encoded
+// INTEGER and an error otherwise.
+func checkInteger(bytes []byte) error {
+	if len(bytes) == 0 {
+		return StructuralError{"empty integer"}
+	}
+	if len(bytes) == 1 {
+		return nil
+	}
+	if (bytes[0] == 0 && bytes[1]&0x80 == 0) || (bytes[0] == 0xff && bytes[1]&0x80 == 0x80) {
+		return StructuralError{"integer not minimally-encoded"}
+	}
+	return nil
+}
+
 // parseInt64 treats the given bytes as a big-endian, signed integer and
 // returns the result.
 func parseInt64(bytes []byte) (ret int64, err error) {
+	err = checkInteger(bytes)
+	if err != nil {
+		return
+	}
 	if len(bytes) > 8 {
 		// We'll overflow an int64 in this case.
 		err = StructuralError{"integer too large"}
@@ -93,6 +112,9 @@ func parseInt64(bytes []byte) (ret int64, err error) {
 // parseInt treats the given bytes as a big-endian, signed integer and returns
 // the result.
 func parseInt32(bytes []byte) (int32, error) {
+	if err := checkInteger(bytes); err != nil {
+		return 0, err
+	}
 	ret64, err := parseInt64(bytes)
 	if err != nil {
 		return 0, err
@@ -107,7 +129,10 @@ var bigOne = big.NewInt(1)
 
 // parseBigInt treats the given bytes as a big-endian, signed integer and returns
 // the result.
-func parseBigInt(bytes []byte) *big.Int {
+func parseBigInt(bytes []byte) (*big.Int, error) {
+	if err := checkInteger(bytes); err != nil {
+		return nil, err
+	}
 	ret := new(big.Int)
 	if len(bytes) > 0 && bytes[0]&0x80 == 0x80 {
 		// This is a negative number.
@@ -118,10 +143,10 @@ func parseBigInt(bytes []byte) *big.Int {
 		ret.SetBytes(notBytes)
 		ret.Add(ret, bigOne)
 		ret.Neg(ret)
-		return ret
+		return ret, nil
 	}
 	ret.SetBytes(bytes)
-	return ret
+	return ret, nil
 }
 
 // BIT STRING
@@ -269,7 +294,7 @@ type Flag bool
 func parseBase128Int(bytes []byte, initOffset int) (ret, offset int, err error) {
 	offset = initOffset
 	for shifted := 0; offset < len(bytes); shifted++ {
-		if shifted > 4 {
+		if shifted == 4 {
 			err = StructuralError{"base 128 integer too large"}
 			return
 		}
@@ -475,6 +500,11 @@ func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i
 				return
 			}
 		}
+		// Short lengths must be encoded in short form.
+		if ret.length < 0x80 {
+			err = StructuralError{"non-minimal length"}
+			return
+		}
 	}
 
 	return
@@ -500,17 +530,17 @@ func parseSequenceOf(bytes []byte, sliceType reflect.Type, elemType reflect.Type
 			return
 		}
 		switch t.tag {
-		case tagIA5String, tagGeneralString, tagT61String, tagUTF8String:
+		case TagIA5String, TagGeneralString, TagT61String, TagUTF8String:
 			// We pretend that various other string types are
 			// PRINTABLE STRINGs so that a sequence of them can be
 			// parsed into a []string.
-			t.tag = tagPrintableString
-		case tagGeneralizedTime, tagUTCTime:
+			t.tag = TagPrintableString
+		case TagGeneralizedTime, TagUTCTime:
 			// Likewise, both time types are treated the same.
-			t.tag = tagUTCTime
+			t.tag = TagUTCTime
 		}
 
-		if t.class != classUniversal || t.isCompound != compoundType || t.tag != expectedTag {
+		if t.class != ClassUniversal || t.isCompound != compoundType || t.tag != expectedTag {
 			err = StructuralError{"sequence tag mismatch"}
 			return
 		}
@@ -594,28 +624,28 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 			return
 		}
 		var result interface{}
-		if !t.isCompound && t.class == classUniversal {
+		if !t.isCompound && t.class == ClassUniversal {
 			innerBytes := bytes[offset : offset+t.length]
 			switch t.tag {
-			case tagPrintableString:
+			case TagPrintableString:
 				result, err = parsePrintableString(innerBytes)
-			case tagIA5String:
+			case TagIA5String:
 				result, err = parseIA5String(innerBytes)
-			case tagT61String:
+			case TagT61String:
 				result, err = parseT61String(innerBytes)
-			case tagUTF8String:
+			case TagUTF8String:
 				result, err = parseUTF8String(innerBytes)
-			case tagInteger:
+			case TagInteger:
 				result, err = parseInt64(innerBytes)
-			case tagBitString:
+			case TagBitString:
 				result, err = parseBitString(innerBytes)
-			case tagOID:
+			case TagOID:
 				result, err = parseObjectIdentifier(innerBytes)
-			case tagUTCTime:
+			case TagUTCTime:
 				result, err = parseUTCTime(innerBytes)
-			case tagGeneralizedTime:
+			case TagGeneralizedTime:
 				result, err = parseGeneralizedTime(innerBytes)
-			case tagOctetString:
+			case TagOctetString:
 				result = innerBytes
 			default:
 				// If we don't know how to handle the type, we just leave Value as nil.
@@ -641,9 +671,9 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 		return
 	}
 	if params.explicit {
-		expectedClass := classContextSpecific
+		expectedClass := ClassContextSpecific
 		if params.application {
-			expectedClass = classApplication
+			expectedClass = ClassApplication
 		}
 		if offset == len(bytes) {
 			err = StructuralError{"explicit tag has no child"}
@@ -679,10 +709,10 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 	// type string. getUniversalType returns the tag for PrintableString
 	// when it sees a string, so if we see a different string type on the
 	// wire, we change the universal type to match.
-	if universalTag == tagPrintableString {
-		if t.class == classUniversal {
+	if universalTag == TagPrintableString {
+		if t.class == ClassUniversal {
 			switch t.tag {
-			case tagIA5String, tagGeneralString, tagT61String, tagUTF8String:
+			case TagIA5String, TagGeneralString, TagT61String, TagUTF8String:
 				universalTag = t.tag
 			}
 		} else if params.stringType != 0 {
@@ -692,24 +722,24 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 
 	// Special case for time: UTCTime and GeneralizedTime both map to the
 	// Go type time.Time.
-	if universalTag == tagUTCTime && t.tag == tagGeneralizedTime && t.class == classUniversal {
-		universalTag = tagGeneralizedTime
+	if universalTag == TagUTCTime && t.tag == TagGeneralizedTime && t.class == ClassUniversal {
+		universalTag = TagGeneralizedTime
 	}
 
 	if params.set {
-		universalTag = tagSet
+		universalTag = TagSet
 	}
 
-	expectedClass := classUniversal
+	expectedClass := ClassUniversal
 	expectedTag := universalTag
 
 	if !params.explicit && params.tag != nil {
-		expectedClass = classContextSpecific
+		expectedClass = ClassContextSpecific
 		expectedTag = *params.tag
 	}
 
 	if !params.explicit && params.application && params.tag != nil {
-		expectedClass = classApplication
+		expectedClass = ClassApplication
 		expectedTag = *params.tag
 	}
 
@@ -751,7 +781,7 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 	case timeType:
 		var time time.Time
 		var err1 error
-		if universalTag == tagUTCTime {
+		if universalTag == TagUTCTime {
 			time, err1 = parseUTCTime(innerBytes)
 		} else {
 			time, err1 = parseGeneralizedTime(innerBytes)
@@ -772,8 +802,11 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 		v.SetBool(true)
 		return
 	case bigIntType:
-		parsedInt := parseBigInt(innerBytes)
-		v.Set(reflect.ValueOf(parsedInt))
+		parsedInt, err1 := parseBigInt(innerBytes)
+		if err1 == nil {
+			v.Set(reflect.ValueOf(parsedInt))
+		}
+		err = err1
 		return
 	}
 	switch val := v; val.Kind() {
@@ -840,15 +873,15 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
 	case reflect.String:
 		var v string
 		switch universalTag {
-		case tagPrintableString:
+		case TagPrintableString:
 			v, err = parsePrintableString(innerBytes)
-		case tagIA5String:
+		case TagIA5String:
 			v, err = parseIA5String(innerBytes)
-		case tagT61String:
+		case TagT61String:
 			v, err = parseT61String(innerBytes)
-		case tagUTF8String:
+		case TagUTF8String:
 			v, err = parseUTF8String(innerBytes)
-		case tagGeneralString:
+		case TagGeneralString:
 			// GeneralString is specified in ISO-2022/ECMA-35,
 			// A brief review suggests that it includes structures
 			// that allow the encoding to change midstring and
diff --git a/src/encoding/asn1/asn1_test.go b/src/encoding/asn1/asn1_test.go
index 893d080..e0e8331 100644
--- a/src/encoding/asn1/asn1_test.go
+++ b/src/encoding/asn1/asn1_test.go
@@ -53,10 +53,12 @@ var int64TestData = []int64Test{
 	{[]byte{0x01, 0x00}, true, 256},
 	{[]byte{0x80}, true, -128},
 	{[]byte{0xff, 0x7f}, true, -129},
-	{[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, true, -1},
 	{[]byte{0xff}, true, -1},
 	{[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, true, -9223372036854775808},
 	{[]byte{0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, false, 0},
+	{[]byte{}, false, 0},
+	{[]byte{0x00, 0x7f}, false, 0},
+	{[]byte{0xff, 0xf0}, false, 0},
 }
 
 func TestParseInt64(t *testing.T) {
@@ -84,10 +86,12 @@ var int32TestData = []int32Test{
 	{[]byte{0x01, 0x00}, true, 256},
 	{[]byte{0x80}, true, -128},
 	{[]byte{0xff, 0x7f}, true, -129},
-	{[]byte{0xff, 0xff, 0xff, 0xff}, true, -1},
 	{[]byte{0xff}, true, -1},
 	{[]byte{0x80, 0x00, 0x00, 0x00}, true, -2147483648},
 	{[]byte{0x80, 0x00, 0x00, 0x00, 0x00}, false, 0},
+	{[]byte{}, false, 0},
+	{[]byte{0x00, 0x7f}, false, 0},
+	{[]byte{0xff, 0xf0}, false, 0},
 }
 
 func TestParseInt32(t *testing.T) {
@@ -104,27 +108,36 @@ func TestParseInt32(t *testing.T) {
 
 var bigIntTests = []struct {
 	in     []byte
+	ok     bool
 	base10 string
 }{
-	{[]byte{0xff}, "-1"},
-	{[]byte{0x00}, "0"},
-	{[]byte{0x01}, "1"},
-	{[]byte{0x00, 0xff}, "255"},
-	{[]byte{0xff, 0x00}, "-256"},
-	{[]byte{0x01, 0x00}, "256"},
+	{[]byte{0xff}, true, "-1"},
+	{[]byte{0x00}, true, "0"},
+	{[]byte{0x01}, true, "1"},
+	{[]byte{0x00, 0xff}, true, "255"},
+	{[]byte{0xff, 0x00}, true, "-256"},
+	{[]byte{0x01, 0x00}, true, "256"},
+	{[]byte{}, false, ""},
+	{[]byte{0x00, 0x7f}, false, ""},
+	{[]byte{0xff, 0xf0}, false, ""},
 }
 
 func TestParseBigInt(t *testing.T) {
 	for i, test := range bigIntTests {
-		ret := parseBigInt(test.in)
-		if ret.String() != test.base10 {
-			t.Errorf("#%d: bad result from %x, got %s want %s", i, test.in, ret.String(), test.base10)
+		ret, err := parseBigInt(test.in)
+		if (err == nil) != test.ok {
+			t.Errorf("#%d: Incorrect error result (did fail? %v, expected: %v)", i, err == nil, test.ok)
 		}
-		fw := newForkableWriter()
-		marshalBigInt(fw, ret)
-		result := fw.Bytes()
-		if !bytes.Equal(result, test.in) {
-			t.Errorf("#%d: got %x from marshaling %s, want %x", i, result, ret, test.in)
+		if test.ok {
+			if ret.String() != test.base10 {
+				t.Errorf("#%d: bad result from %x, got %s want %s", i, test.in, ret.String(), test.base10)
+			}
+			fw := newForkableWriter()
+			marshalBigInt(fw, ret)
+			result := fw.Bytes()
+			if !bytes.Equal(result, test.in) {
+				t.Errorf("#%d: got %x from marshaling %s, want %x", i, result, ret, test.in)
+			}
 		}
 	}
 }
@@ -354,17 +367,21 @@ var tagAndLengthData = []tagAndLengthTest{
 	{[]byte{0x1f, 0x01, 0x00}, true, tagAndLength{0, 1, 0, false}},
 	{[]byte{0x1f, 0x81, 0x00, 0x00}, true, tagAndLength{0, 128, 0, false}},
 	{[]byte{0x1f, 0x81, 0x80, 0x01, 0x00}, true, tagAndLength{0, 0x4001, 0, false}},
-	{[]byte{0x00, 0x81, 0x01}, true, tagAndLength{0, 0, 1, false}},
+	{[]byte{0x00, 0x81, 0x80}, true, tagAndLength{0, 0, 128, false}},
 	{[]byte{0x00, 0x82, 0x01, 0x00}, true, tagAndLength{0, 0, 256, false}},
 	{[]byte{0x00, 0x83, 0x01, 0x00}, false, tagAndLength{}},
 	{[]byte{0x1f, 0x85}, false, tagAndLength{}},
 	{[]byte{0x30, 0x80}, false, tagAndLength{}},
 	// Superfluous zeros in the length should be an error.
-	{[]byte{0xa0, 0x82, 0x00, 0x01}, false, tagAndLength{}},
+	{[]byte{0xa0, 0x82, 0x00, 0xff}, false, tagAndLength{}},
 	// Lengths up to the maximum size of an int should work.
 	{[]byte{0xa0, 0x84, 0x7f, 0xff, 0xff, 0xff}, true, tagAndLength{2, 0, 0x7fffffff, true}},
 	// Lengths that would overflow an int should be rejected.
 	{[]byte{0xa0, 0x84, 0x80, 0x00, 0x00, 0x00}, false, tagAndLength{}},
+	// Long length form may not be used for lengths that fit in short form.
+	{[]byte{0xa0, 0x81, 0x7f}, false, tagAndLength{}},
+	// Tag numbers which would overflow int32 are rejected. (The value below is 2^31.)
+	{[]byte{0x1f, 0x88, 0x80, 0x80, 0x80, 0x00, 0x00}, false, tagAndLength{}},
 }
 
 func TestParseTagAndLength(t *testing.T) {
@@ -394,10 +411,10 @@ func newBool(b bool) *bool { return &b }
 
 var parseFieldParametersTestData []parseFieldParametersTest = []parseFieldParametersTest{
 	{"", fieldParameters{}},
-	{"ia5", fieldParameters{stringType: tagIA5String}},
-	{"generalized", fieldParameters{timeType: tagGeneralizedTime}},
-	{"utc", fieldParameters{timeType: tagUTCTime}},
-	{"printable", fieldParameters{stringType: tagPrintableString}},
+	{"ia5", fieldParameters{stringType: TagIA5String}},
+	{"generalized", fieldParameters{timeType: TagGeneralizedTime}},
+	{"utc", fieldParameters{timeType: TagUTCTime}},
+	{"printable", fieldParameters{stringType: TagPrintableString}},
 	{"optional", fieldParameters{optional: true}},
 	{"explicit", fieldParameters{explicit: true, tag: new(int)}},
 	{"application", fieldParameters{application: true, tag: new(int)}},
@@ -940,3 +957,15 @@ func TestUnmarshalInvalidUTF8(t *testing.T) {
 		t.Fatalf("Expected error to mention %q but error was %q", expectedSubstring, err.Error())
 	}
 }
+
+func TestMarshalNilValue(t *testing.T) {
+	nilValueTestData := []interface{}{
+		nil,
+		struct{ v interface{} }{},
+	}
+	for i, test := range nilValueTestData {
+		if _, err := Marshal(test); err == nil {
+			t.Fatalf("#%d: successfully marshaled nil value", i)
+		}
+	}
+}
diff --git a/src/encoding/asn1/common.go b/src/encoding/asn1/common.go
index ab85e04..0695180 100644
--- a/src/encoding/asn1/common.go
+++ b/src/encoding/asn1/common.go
@@ -18,29 +18,31 @@ import (
 
 // Here are some standard tags and classes
 
+// ASN.1 tags represent the type of the following object.
 const (
-	tagBoolean         = 1
-	tagInteger         = 2
-	tagBitString       = 3
-	tagOctetString     = 4
-	tagOID             = 6
-	tagEnum            = 10
-	tagUTF8String      = 12
-	tagSequence        = 16
-	tagSet             = 17
-	tagPrintableString = 19
-	tagT61String       = 20
-	tagIA5String       = 22
-	tagUTCTime         = 23
-	tagGeneralizedTime = 24
-	tagGeneralString   = 27
+	TagBoolean         = 1
+	TagInteger         = 2
+	TagBitString       = 3
+	TagOctetString     = 4
+	TagOID             = 6
+	TagEnum            = 10
+	TagUTF8String      = 12
+	TagSequence        = 16
+	TagSet             = 17
+	TagPrintableString = 19
+	TagT61String       = 20
+	TagIA5String       = 22
+	TagUTCTime         = 23
+	TagGeneralizedTime = 24
+	TagGeneralString   = 27
 )
 
+// ASN.1 class types represent the namespace of the tag.
 const (
-	classUniversal       = 0
-	classApplication     = 1
-	classContextSpecific = 2
-	classPrivate         = 3
+	ClassUniversal       = 0
+	ClassApplication     = 1
+	ClassContextSpecific = 2
+	ClassPrivate         = 3
 )
 
 type tagAndLength struct {
@@ -96,15 +98,15 @@ func parseFieldParameters(str string) (ret fieldParameters) {
 				ret.tag = new(int)
 			}
 		case part == "generalized":
-			ret.timeType = tagGeneralizedTime
+			ret.timeType = TagGeneralizedTime
 		case part == "utc":
-			ret.timeType = tagUTCTime
+			ret.timeType = TagUTCTime
 		case part == "ia5":
-			ret.stringType = tagIA5String
+			ret.stringType = TagIA5String
 		case part == "printable":
-			ret.stringType = tagPrintableString
+			ret.stringType = TagPrintableString
 		case part == "utf8":
-			ret.stringType = tagUTF8String
+			ret.stringType = TagUTF8String
 		case strings.HasPrefix(part, "default:"):
 			i, err := strconv.ParseInt(part[8:], 10, 64)
 			if err == nil {
@@ -136,33 +138,33 @@ func parseFieldParameters(str string) (ret fieldParameters) {
 func getUniversalType(t reflect.Type) (tagNumber int, isCompound, ok bool) {
 	switch t {
 	case objectIdentifierType:
-		return tagOID, false, true
+		return TagOID, false, true
 	case bitStringType:
-		return tagBitString, false, true
+		return TagBitString, false, true
 	case timeType:
-		return tagUTCTime, false, true
+		return TagUTCTime, false, true
 	case enumeratedType:
-		return tagEnum, false, true
+		return TagEnum, false, true
 	case bigIntType:
-		return tagInteger, false, true
+		return TagInteger, false, true
 	}
 	switch t.Kind() {
 	case reflect.Bool:
-		return tagBoolean, false, true
+		return TagBoolean, false, true
 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		return tagInteger, false, true
+		return TagInteger, false, true
 	case reflect.Struct:
-		return tagSequence, true, true
+		return TagSequence, true, true
 	case reflect.Slice:
 		if t.Elem().Kind() == reflect.Uint8 {
-			return tagOctetString, false, true
+			return TagOctetString, false, true
 		}
 		if strings.HasSuffix(t.Name(), "SET") {
-			return tagSet, true, true
+			return TagSet, true, true
 		}
-		return tagSequence, true, true
+		return TagSequence, true, true
 	case reflect.String:
-		return tagPrintableString, false, true
+		return TagPrintableString, false, true
 	}
 	return 0, false, false
 }
diff --git a/src/encoding/asn1/marshal.go b/src/encoding/asn1/marshal.go
index 67a019d..6e85858 100644
--- a/src/encoding/asn1/marshal.go
+++ b/src/encoding/asn1/marshal.go
@@ -414,7 +414,7 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
 		return nil
 	case timeType:
 		t := value.Interface().(time.Time)
-		if params.timeType == tagGeneralizedTime || outsideUTCRange(t) {
+		if params.timeType == TagGeneralizedTime || outsideUTCRange(t) {
 			return marshalGeneralizedTime(out, t)
 		} else {
 			return marshalUTCTime(out, t)
@@ -493,9 +493,9 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
 		return
 	case reflect.String:
 		switch params.stringType {
-		case tagIA5String:
+		case TagIA5String:
 			return marshalIA5String(out, v.String())
-		case tagPrintableString:
+		case TagPrintableString:
 			return marshalPrintableString(out, v.String())
 		default:
 			return marshalUTF8String(out, v.String())
@@ -506,6 +506,9 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
 }
 
 func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters) (err error) {
+	if !v.IsValid() {
+		return fmt.Errorf("asn1: cannot marshal nil value")
+	}
 	// If the field is an interface{} then recurse into it.
 	if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 {
 		return marshalField(out, v.Elem(), params)
@@ -552,18 +555,18 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
 		err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type())}
 		return
 	}
-	class := classUniversal
+	class := ClassUniversal
 
-	if params.timeType != 0 && tag != tagUTCTime {
+	if params.timeType != 0 && tag != TagUTCTime {
 		return StructuralError{"explicit time type given to non-time member"}
 	}
 
-	if params.stringType != 0 && tag != tagPrintableString {
+	if params.stringType != 0 && tag != TagPrintableString {
 		return StructuralError{"explicit string type given to non-string member"}
 	}
 
 	switch tag {
-	case tagPrintableString:
+	case TagPrintableString:
 		if params.stringType == 0 {
 			// This is a string without an explicit string type. We'll use
 			// a PrintableString if the character set in the string is
@@ -573,24 +576,24 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
 					if !utf8.ValidString(v.String()) {
 						return errors.New("asn1: string not valid UTF-8")
 					}
-					tag = tagUTF8String
+					tag = TagUTF8String
 					break
 				}
 			}
 		} else {
 			tag = params.stringType
 		}
-	case tagUTCTime:
-		if params.timeType == tagGeneralizedTime || outsideUTCRange(v.Interface().(time.Time)) {
-			tag = tagGeneralizedTime
+	case TagUTCTime:
+		if params.timeType == TagGeneralizedTime || outsideUTCRange(v.Interface().(time.Time)) {
+			tag = TagGeneralizedTime
 		}
 	}
 
 	if params.set {
-		if tag != tagSequence {
+		if tag != TagSequence {
 			return StructuralError{"non sequence tagged as set"}
 		}
-		tag = tagSet
+		tag = TagSet
 	}
 
 	tags, body := out.fork()
@@ -610,7 +613,7 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
 	if !params.explicit && params.tag != nil {
 		// implicit tag.
 		tag = *params.tag
-		class = classContextSpecific
+		class = ClassContextSpecific
 	}
 
 	err = marshalTagAndLength(tags, tagAndLength{class, tag, bodyLen, isCompound})
@@ -620,14 +623,14 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
 
 	if params.explicit {
 		err = marshalTagAndLength(explicitTag, tagAndLength{
-			class:      classContextSpecific,
+			class:      ClassContextSpecific,
 			tag:        *params.tag,
 			length:     bodyLen + tags.Len(),
 			isCompound: true,
 		})
 	}
 
-	return nil
+	return err
 }
 
 // Marshal returns the ASN.1 encoding of val.
@@ -648,5 +651,5 @@ func Marshal(val interface{}) ([]byte, error) {
 		return nil, err
 	}
 	_, err = f.writeTo(&out)
-	return out.Bytes(), nil
+	return out.Bytes(), err
 }
diff --git a/src/encoding/base64/base64.go b/src/encoding/base64/base64.go
index 3302fb4..1bda804 100644
--- a/src/encoding/base64/base64.go
+++ b/src/encoding/base64/base64.go
@@ -75,7 +75,7 @@ var URLEncoding = NewEncoding(encodeURL)
 // This is the same as StdEncoding but omits padding characters.
 var RawStdEncoding = StdEncoding.WithPadding(NoPadding)
 
-// URLEncoding is the unpadded alternate base64 encoding defined in RFC 4648.
+// RawURLEncoding is the unpadded alternate base64 encoding defined in RFC 4648.
 // It is typically used in URLs and file names.
 // This is the same as URLEncoding but omits padding characters.
 var RawURLEncoding = URLEncoding.WithPadding(NoPadding)
@@ -346,21 +346,18 @@ func (enc *Encoding) DecodeString(s string) ([]byte, error) {
 }
 
 type decoder struct {
-	err    error
-	enc    *Encoding
-	r      io.Reader
-	end    bool       // saw end of message
-	buf    [1024]byte // leftover input
-	nbuf   int
-	out    []byte // leftover decoded output
-	outbuf [1024 / 4 * 3]byte
+	err     error
+	readErr error // error from r.Read
+	enc     *Encoding
+	r       io.Reader
+	end     bool       // saw end of message
+	buf     [1024]byte // leftover input
+	nbuf    int
+	out     []byte // leftover decoded output
+	outbuf  [1024 / 4 * 3]byte
 }
 
 func (d *decoder) Read(p []byte) (n int, err error) {
-	if d.err != nil {
-		return 0, d.err
-	}
-
 	// Use leftover decoded output from last read.
 	if len(d.out) > 0 {
 		n = copy(p, d.out)
@@ -368,19 +365,46 @@ func (d *decoder) Read(p []byte) (n int, err error) {
 		return n, nil
 	}
 
+	if d.err != nil {
+		return 0, d.err
+	}
+
 	// This code assumes that d.r strips supported whitespace ('\r' and '\n').
 
-	// Read a chunk.
-	nn := len(p) / 3 * 4
-	if nn < 4 {
-		nn = 4
-	}
-	if nn > len(d.buf) {
-		nn = len(d.buf)
+	// Refill buffer.
+	for d.nbuf < 4 && d.readErr == nil {
+		nn := len(p) / 3 * 4
+		if nn < 4 {
+			nn = 4
+		}
+		if nn > len(d.buf) {
+			nn = len(d.buf)
+		}
+		nn, d.readErr = d.r.Read(d.buf[d.nbuf:nn])
+		d.nbuf += nn
 	}
-	nn, d.err = io.ReadAtLeast(d.r, d.buf[d.nbuf:nn], 4-d.nbuf)
-	d.nbuf += nn
-	if d.err != nil || d.nbuf < 4 {
+
+	if d.nbuf < 4 {
+		if d.enc.padChar == NoPadding && d.nbuf > 0 {
+			// Decode final fragment, without padding.
+			var nw int
+			nw, _, d.err = d.enc.decode(d.outbuf[:], d.buf[:d.nbuf])
+			d.nbuf = 0
+			d.end = true
+			d.out = d.outbuf[:nw]
+			n = copy(p, d.out)
+			d.out = d.out[n:]
+			if n > 0 || len(p) == 0 && len(d.out) > 0 {
+				return n, nil
+			}
+			if d.err != nil {
+				return 0, d.err
+			}
+		}
+		d.err = d.readErr
+		if d.err == io.EOF && d.nbuf > 0 {
+			d.err = io.ErrUnexpectedEOF
+		}
 		return 0, d.err
 	}
 
@@ -396,13 +420,7 @@ func (d *decoder) Read(p []byte) (n int, err error) {
 		n, d.end, d.err = d.enc.decode(p, d.buf[:nr])
 	}
 	d.nbuf -= nr
-	for i := 0; i < d.nbuf; i++ {
-		d.buf[i] = d.buf[i+nr]
-	}
-
-	if d.err == nil {
-		d.err = err
-	}
+	copy(d.buf[:d.nbuf], d.buf[nr:])
 	return n, d.err
 }
 
diff --git a/src/encoding/base64/base64_test.go b/src/encoding/base64/base64_test.go
index d144b96..fc6a1ea 100644
--- a/src/encoding/base64/base64_test.go
+++ b/src/encoding/base64/base64_test.go
@@ -80,11 +80,11 @@ type encodingTest struct {
 }
 
 var encodingTests = []encodingTest{
-	encodingTest{StdEncoding, stdRef},
-	encodingTest{URLEncoding, urlRef},
-	encodingTest{RawStdEncoding, rawRef},
-	encodingTest{RawURLEncoding, rawUrlRef},
-	encodingTest{funnyEncoding, funnyRef},
+	{StdEncoding, stdRef},
+	{URLEncoding, urlRef},
+	{RawStdEncoding, rawRef},
+	{RawURLEncoding, rawUrlRef},
+	{funnyEncoding, funnyRef},
 }
 
 var bigtest = testpair{
@@ -406,3 +406,28 @@ func BenchmarkDecodeString(b *testing.B) {
 		StdEncoding.DecodeString(data)
 	}
 }
+
+func TestDecoderRaw(t *testing.T) {
+	source := "AAAAAA"
+	want := []byte{0, 0, 0, 0}
+
+	// Direct.
+	dec1, err := RawURLEncoding.DecodeString(source)
+	if err != nil || !bytes.Equal(dec1, want) {
+		t.Errorf("RawURLEncoding.DecodeString(%q) = %x, %v, want %x, nil", source, dec1, err, want)
+	}
+
+	// Through reader. Used to fail.
+	r := NewDecoder(RawURLEncoding, bytes.NewReader([]byte(source)))
+	dec2, err := ioutil.ReadAll(io.LimitReader(r, 100))
+	if err != nil || !bytes.Equal(dec2, want) {
+		t.Errorf("reading NewDecoder(RawURLEncoding, %q) = %x, %v, want %x, nil", source, dec2, err, want)
+	}
+
+	// Should work with padding.
+	r = NewDecoder(URLEncoding, bytes.NewReader([]byte(source+"==")))
+	dec3, err := ioutil.ReadAll(r)
+	if err != nil || !bytes.Equal(dec3, want) {
+		t.Errorf("reading NewDecoder(URLEncoding, %q) = %x, %v, want %x, nil", source+"==", dec3, err, want)
+	}
+}
diff --git a/src/encoding/base64/example_test.go b/src/encoding/base64/example_test.go
index d18b856..8d2c9ce 100644
--- a/src/encoding/base64/example_test.go
+++ b/src/encoding/base64/example_test.go
@@ -12,6 +12,21 @@ import (
 	"os"
 )
 
+func Example() {
+	msg := "Hello, 世界"
+	encoded := base64.StdEncoding.EncodeToString([]byte(msg))
+	fmt.Println(encoded)
+	decoded, err := base64.StdEncoding.DecodeString(encoded)
+	if err != nil {
+		fmt.Println("decode error:", err)
+		return
+	}
+	fmt.Println(string(decoded))
+	// Output:
+	// SGVsbG8sIOS4lueVjA==
+	// Hello, 世界
+}
+
 func ExampleEncoding_EncodeToString() {
 	data := []byte("any + old & data")
 	str := base64.StdEncoding.EncodeToString(data)
diff --git a/src/encoding/binary/binary.go b/src/encoding/binary/binary.go
index 2bbe07c..1c2577b 100644
--- a/src/encoding/binary/binary.go
+++ b/src/encoding/binary/binary.go
@@ -135,6 +135,10 @@ func (bigEndian) GoString() string { return "binary.BigEndian" }
 // blank (_) field names is skipped; i.e., blank field names
 // may be used for padding.
 // When reading into a struct, all non-blank fields must be exported.
+//
+// The error is EOF only if no bytes were read.
+// If an EOF happens after reading some but not all the bytes,
+// Read returns ErrUnexpectedEOF.
 func Read(r io.Reader, order ByteOrder, data interface{}) error {
 	// Fast path for basic types and slices.
 	if n := intDataSize(data); n != 0 {
diff --git a/src/encoding/binary/binary_test.go b/src/encoding/binary/binary_test.go
index 8ee595f..7fd36fa 100644
--- a/src/encoding/binary/binary_test.go
+++ b/src/encoding/binary/binary_test.go
@@ -309,6 +309,36 @@ func TestReadErrorMsg(t *testing.T) {
 	read(&p)
 }
 
+func TestReadTruncated(t *testing.T) {
+	const data = "0123456789abcdef"
+
+	var b1 = make([]int32, 4)
+	var b2 struct {
+		A, B, C, D byte
+		E          int32
+		F          float64
+	}
+
+	for i := 0; i <= len(data); i++ {
+		var errWant error
+		switch i {
+		case 0:
+			errWant = io.EOF
+		case len(data):
+			errWant = nil
+		default:
+			errWant = io.ErrUnexpectedEOF
+		}
+
+		if err := Read(strings.NewReader(data[:i]), LittleEndian, &b1); err != errWant {
+			t.Errorf("Read(%d) with slice: got %v, want %v", i, err, errWant)
+		}
+		if err := Read(strings.NewReader(data[:i]), LittleEndian, &b2); err != errWant {
+			t.Errorf("Read(%d) with struct: got %v, want %v", i, err, errWant)
+		}
+	}
+}
+
 type byteSliceReader struct {
 	remain []byte
 }
diff --git a/src/encoding/csv/reader.go b/src/encoding/csv/reader.go
index 37bf80c..a6bb780 100644
--- a/src/encoding/csv/reader.go
+++ b/src/encoding/csv/reader.go
@@ -155,7 +155,7 @@ func (r *Reader) Read() (record []string, err error) {
 
 // ReadAll reads all the remaining records from r.
 // Each record is a slice of fields.
-// A successful call returns err == nil, not err == EOF. Because ReadAll is
+// A successful call returns err == nil, not err == io.EOF. Because ReadAll is
 // defined to read until EOF, it does not treat end of file as an error to be
 // reported.
 func (r *Reader) ReadAll() (records [][]string, err error) {
diff --git a/src/encoding/gob/codec_test.go b/src/encoding/gob/codec_test.go
index c2583bf..8efcdc7 100644
--- a/src/encoding/gob/codec_test.go
+++ b/src/encoding/gob/codec_test.go
@@ -88,7 +88,6 @@ func verifyInt(i int64, t *testing.T) {
 	encState := newEncoderState(b)
 	encState.encodeInt(i)
 	decState := newDecodeState(newDecBuffer(b.Bytes()))
-	decState.buf = make([]byte, 8)
 	j := decState.decodeInt()
 	if i != j {
 		t.Errorf("Encode/Decode: sent %#x received %#x", uint64(i), uint64(j))
@@ -127,7 +126,6 @@ var bytesResult = []byte{0x07, 0x05, 'h', 'e', 'l', 'l', 'o'}
 func newDecodeState(buf *decBuffer) *decoderState {
 	d := new(decoderState)
 	d.b = buf
-	d.buf = make([]byte, uint64Size)
 	return d
 }
 
@@ -1488,7 +1486,7 @@ func TestErrorInvalidTypeId(t *testing.T) {
 		var foo struct{}
 		err := d.Decode(&foo)
 		if err != errBadType {
-			t.Fatal("decode: expected %s, got %s", errBadType, err)
+			t.Fatalf("decode: expected %s, got %s", errBadType, err)
 		}
 	}
 }
diff --git a/src/encoding/gob/dec_helpers.go b/src/encoding/gob/dec_helpers.go
index a1b6766..3aa038d 100644
--- a/src/encoding/gob/dec_helpers.go
+++ b/src/encoding/gob/dec_helpers.go
@@ -327,11 +327,12 @@ func decStringSlice(state *decoderState, v reflect.Value, length int, ovfl error
 			errorf("string data too long for buffer: %d", n)
 		}
 		// Read the data.
-		data := make([]byte, n)
-		if _, err := state.b.Read(data); err != nil {
-			errorf("error decoding string: %s", err)
+		data := state.b.Bytes()
+		if len(data) < n {
+			errorf("invalid string length %d: exceeds input size %d", n, len(data))
 		}
-		slice[i] = string(data)
+		slice[i] = string(data[:n])
+		state.b.Drop(n)
 	}
 	return true
 }
diff --git a/src/encoding/gob/decgen.go b/src/encoding/gob/decgen.go
index da41a89..ef73f2d 100644
--- a/src/encoding/gob/decgen.go
+++ b/src/encoding/gob/decgen.go
@@ -112,11 +112,12 @@ var types = []Type{
 			errorf("string data too long for buffer: %d", n)
 		}
 		// Read the data.
-		data := make([]byte, n)
-		if _, err := state.b.Read(data); err != nil {
-			errorf("error decoding string: %s", err)
+		data := state.b.Bytes()
+		if len(data) < n {
+			errorf("invalid string length %d: exceeds input size %d", n, len(data))
 		}
-		slice[i] = string(data)`,
+		slice[i] = string(data[:n])
+		state.b.Drop(n)`,
 	},
 	{
 		"uint",
diff --git a/src/encoding/gob/decode.go b/src/encoding/gob/decode.go
index e913f15..3b0dca8 100644
--- a/src/encoding/gob/decode.go
+++ b/src/encoding/gob/decode.go
@@ -29,8 +29,7 @@ type decoderState struct {
 	// The buffer is stored with an extra indirection because it may be replaced
 	// if we load a type during decode (when reading an interface value).
 	b        *decBuffer
-	fieldnum int // the last field number read.
-	buf      []byte
+	fieldnum int           // the last field number read.
 	next     *decoderState // for free list
 }
 
@@ -97,7 +96,6 @@ func (dec *Decoder) newDecoderState(buf *decBuffer) *decoderState {
 	if d == nil {
 		d = new(decoderState)
 		d.dec = dec
-		d.buf = make([]byte, uint64Size)
 	} else {
 		dec.freeList = d.next
 	}
@@ -160,15 +158,16 @@ func (state *decoderState) decodeUint() (x uint64) {
 	if n > uint64Size {
 		error_(errBadUint)
 	}
-	width, err := state.b.Read(state.buf[0:n])
-	if err != nil {
-		error_(err)
+	buf := state.b.Bytes()
+	if len(buf) < n {
+		errorf("invalid uint data length %d: exceeds input size %d", n, len(buf))
 	}
 	// Don't need to check error; it's safe to loop regardless.
 	// Could check that the high byte is zero but it's not worth it.
-	for _, b := range state.buf[0:width] {
+	for _, b := range buf[0:n] {
 		x = x<<8 | uint64(b)
 	}
+	state.b.Drop(n)
 	return x
 }
 
@@ -397,11 +396,13 @@ func decString(i *decInstr, state *decoderState, value reflect.Value) {
 		errorf("bad %s slice length: %d", value.Type(), n)
 	}
 	// Read the data.
-	data := make([]byte, n)
-	if _, err := state.b.Read(data); err != nil {
-		errorf("error decoding string: %s", err)
+	data := state.b.Bytes()
+	if len(data) < n {
+		errorf("invalid string length %d: exceeds input size %d", n, len(data))
 	}
-	value.SetString(string(data))
+	s := string(data[:n])
+	state.b.Drop(n)
+	value.SetString(s)
 }
 
 // ignoreUint8Array skips over the data for a byte slice value with no destination.
@@ -410,8 +411,11 @@ func ignoreUint8Array(i *decInstr, state *decoderState, value reflect.Value) {
 	if !ok {
 		errorf("slice length too large")
 	}
-	b := make([]byte, n)
-	state.b.Read(b)
+	bn := state.b.Len()
+	if bn < n {
+		errorf("invalid slice length %d: exceeds input size %d", n, bn)
+	}
+	state.b.Drop(n)
 }
 
 // Execution engine
@@ -634,15 +638,15 @@ func (dec *Decoder) ignoreSlice(state *decoderState, elemOp decOp) {
 func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, value reflect.Value) {
 	// Read the name of the concrete type.
 	nr := state.decodeUint()
-	if nr < 0 || nr > 1<<31 { // zero is permissible for anonymous types
+	if nr > 1<<31 { // zero is permissible for anonymous types
 		errorf("invalid type name length %d", nr)
 	}
 	if nr > uint64(state.b.Len()) {
 		errorf("invalid type name length %d: exceeds input size", nr)
 	}
-	b := make([]byte, nr)
-	state.b.Read(b)
-	name := string(b)
+	n := int(nr)
+	name := string(state.b.Bytes()[:n])
+	state.b.Drop(n)
 	// Allocate the destination interface value.
 	if name == "" {
 		// Copy the nil interface value to the target.
@@ -689,11 +693,11 @@ func (dec *Decoder) ignoreInterface(state *decoderState) {
 	if !ok {
 		errorf("bad interface encoding: name too large for buffer")
 	}
-	b := make([]byte, n)
-	_, err := state.b.Read(b)
-	if err != nil {
-		error_(err)
+	bn := state.b.Len()
+	if bn < n {
+		errorf("invalid interface value length %d: exceeds input size %d", n, bn)
 	}
+	state.b.Drop(n)
 	id := dec.decodeTypeSequence(true)
 	if id < 0 {
 		error_(dec.err)
@@ -714,11 +718,13 @@ func (dec *Decoder) decodeGobDecoder(ut *userTypeInfo, state *decoderState, valu
 	if !ok {
 		errorf("GobDecoder: length too large for buffer")
 	}
-	b := make([]byte, n)
-	_, err := state.b.Read(b)
-	if err != nil {
-		error_(err)
+	b := state.b.Bytes()
+	if len(b) < n {
+		errorf("GobDecoder: invalid data length %d: exceeds input size %d", n, len(b))
 	}
+	b = b[:n]
+	state.b.Drop(n)
+	var err error
 	// We know it's one of these.
 	switch ut.externalDec {
 	case xGob:
@@ -740,11 +746,11 @@ func (dec *Decoder) ignoreGobDecoder(state *decoderState) {
 	if !ok {
 		errorf("GobDecoder: length too large for buffer")
 	}
-	b := make([]byte, n)
-	_, err := state.b.Read(b)
-	if err != nil {
-		error_(err)
+	bn := state.b.Len()
+	if bn < n {
+		errorf("GobDecoder: invalid data length %d: exceeds input size %d", n, bn)
 	}
+	state.b.Drop(n)
 }
 
 // Index by Go types.
diff --git a/src/encoding/gob/doc.go b/src/encoding/gob/doc.go
index 4d3d007..cf878f4 100644
--- a/src/encoding/gob/doc.go
+++ b/src/encoding/gob/doc.go
@@ -82,6 +82,12 @@ slice has capacity the slice will be extended in place; if not, a new array is
 allocated. Regardless, the length of the resulting slice reports the number of
 elements decoded.
 
+In general, if allocation is required, the decoder will allocate memory. If not,
+it will update the destination variables with values read from the stream. It does
+not initialize them first, so if the destination is a compound value such as a
+map, struct, or slice, the decoded values will be merged elementwise into the
+existing variables.
+
 Functions and channels will not be sent in a gob. Attempting to encode such a value
 at the top level will fail. A struct field of chan or func type is treated exactly
 like an unexported field and is ignored.
@@ -141,18 +147,21 @@ pairs. Empty but non-nil maps are sent, so if the receiver has not allocated
 one already, one will always be allocated on receipt unless the transmitted map
 is nil and not at the top level.
 
+In slices and arrays, as well as maps, all elements, even zero-valued elements,
+are transmitted, even if all the elements are zero.
+
 Structs are sent as a sequence of (field number, field value) pairs.  The field
 value is sent using the standard gob encoding for its type, recursively.  If a
-field has the zero value for its type, it is omitted from the transmission.  The
-field number is defined by the type of the encoded struct: the first field of the
-encoded type is field 0, the second is field 1, etc.  When encoding a value, the
-field numbers are delta encoded for efficiency and the fields are always sent in
-order of increasing field number; the deltas are therefore unsigned.  The
-initialization for the delta encoding sets the field number to -1, so an unsigned
-integer field 0 with value 7 is transmitted as unsigned delta = 1, unsigned value
-= 7 or (01 07).  Finally, after all the fields have been sent a terminating mark
-denotes the end of the struct.  That mark is a delta=0 value, which has
-representation (00).
+field has the zero value for its type (except for arrays; see above), it is omitted
+from the transmission.  The field number is defined by the type of the encoded
+struct: the first field of the encoded type is field 0, the second is field 1,
+etc.  When encoding a value, the field numbers are delta encoded for efficiency
+and the fields are always sent in order of increasing field number; the deltas are
+therefore unsigned.  The initialization for the delta encoding sets the field
+number to -1, so an unsigned integer field 0 with value 7 is transmitted as unsigned
+delta = 1, unsigned value = 7 or (01 07).  Finally, after all the fields have been
+sent a terminating mark denotes the end of the struct.  That mark is a delta=0
+value, which has representation (00).
 
 Interface types are not checked for compatibility; all interface types are
 treated, for transmission, as members of a single "interface" type, analogous to
diff --git a/src/encoding/gob/encode.go b/src/encoding/gob/encode.go
index f66279f..96052ef 100644
--- a/src/encoding/gob/encode.go
+++ b/src/encoding/gob/encode.go
@@ -10,6 +10,7 @@ import (
 	"encoding"
 	"math"
 	"reflect"
+	"sync"
 )
 
 const uint64Size = 8
@@ -36,6 +37,14 @@ type encBuffer struct {
 	scratch [64]byte
 }
 
+var encBufferPool = sync.Pool{
+	New: func() interface{} {
+		e := new(encBuffer)
+		e.data = e.scratch[0:0]
+		return e
+	},
+}
+
 func (e *encBuffer) WriteByte(c byte) {
 	e.data = append(e.data, c)
 }
@@ -58,7 +67,11 @@ func (e *encBuffer) Bytes() []byte {
 }
 
 func (e *encBuffer) Reset() {
-	e.data = e.data[0:0]
+	if len(e.data) >= tooBig {
+		e.data = e.scratch[0:0]
+	} else {
+		e.data = e.data[0:0]
+	}
 }
 
 func (enc *Encoder) newEncoderState(b *encBuffer) *encoderState {
@@ -407,7 +420,7 @@ func (enc *Encoder) encodeInterface(b *encBuffer, iv reflect.Value) {
 	// Encode the value into a new buffer.  Any nested type definitions
 	// should be written to b, before the encoded value.
 	enc.pushWriter(b)
-	data := new(encBuffer)
+	data := encBufferPool.Get().(*encBuffer)
 	data.Write(spaceForLength)
 	enc.encode(data, elem, ut)
 	if enc.err != nil {
@@ -415,6 +428,8 @@ func (enc *Encoder) encodeInterface(b *encBuffer, iv reflect.Value) {
 	}
 	enc.popWriter()
 	enc.writeMessage(b, data)
+	data.Reset()
+	encBufferPool.Put(data)
 	if enc.err != nil {
 		error_(enc.err)
 	}
diff --git a/src/encoding/gob/encoder_test.go b/src/encoding/gob/encoder_test.go
index dc65734..570d796 100644
--- a/src/encoding/gob/encoder_test.go
+++ b/src/encoding/gob/encoder_test.go
@@ -978,7 +978,7 @@ var badDataTests = []badDataTest{
 	{"0f1000fb285d003316020735ff023a65c5", "interface encoding", nil},
 	{"03fffb0616fffc00f902ff02ff03bf005d02885802a311a8120228022c028ee7", "GobDecoder", nil},
 	// Issue 10491.
-	{"10fe010f020102fe01100001fe010e000016fe010d030102fe010e00010101015801fe01100000000bfe011000f85555555555555555", "length exceeds input size", nil},
+	{"10fe010f020102fe01100001fe010e000016fe010d030102fe010e00010101015801fe01100000000bfe011000f85555555555555555", "exceeds input size", nil},
 }
 
 // TestBadData tests that various problems caused by malformed input
diff --git a/src/encoding/gob/timing_test.go b/src/encoding/gob/timing_test.go
index 940e5ad..424b7e6 100644
--- a/src/encoding/gob/timing_test.go
+++ b/src/encoding/gob/timing_test.go
@@ -127,8 +127,8 @@ func TestCountDecodeMallocs(t *testing.T) {
 			t.Fatal("decode:", err)
 		}
 	})
-	if allocs != 4 {
-		t.Fatalf("mallocs per decode of type Bench: %v; wanted 4\n", allocs)
+	if allocs != 3 {
+		t.Fatalf("mallocs per decode of type Bench: %v; wanted 3\n", allocs)
 	}
 }
 
@@ -200,6 +200,23 @@ func BenchmarkEncodeStringSlice(b *testing.B) {
 	}
 }
 
+func BenchmarkEncodeInterfaceSlice(b *testing.B) {
+	var buf bytes.Buffer
+	enc := NewEncoder(&buf)
+	a := make([]interface{}, 1000)
+	for i := range a {
+		a[i] = "now is the time"
+	}
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		buf.Reset()
+		err := enc.Encode(a)
+		if err != nil {
+			b.Fatal(err)
+		}
+	}
+}
+
 // benchmarkBuf is a read buffer we can reset
 type benchmarkBuf struct {
 	offset int
@@ -323,3 +340,27 @@ func BenchmarkDecodeStringSlice(b *testing.B) {
 		}
 	}
 }
+
+func BenchmarkDecodeInterfaceSlice(b *testing.B) {
+	var buf bytes.Buffer
+	enc := NewEncoder(&buf)
+	a := make([]interface{}, 1000)
+	for i := range a {
+		a[i] = "now is the time"
+	}
+	err := enc.Encode(a)
+	if err != nil {
+		b.Fatal(err)
+	}
+	x := make([]interface{}, 1000)
+	bbuf := benchmarkBuf{data: buf.Bytes()}
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		bbuf.reset()
+		dec := NewDecoder(&bbuf)
+		err := dec.Decode(&x)
+		if err != nil {
+			b.Fatal(i, err)
+		}
+	}
+}
diff --git a/src/encoding/gob/type.go b/src/encoding/gob/type.go
index a49b71a..cf5cec0 100644
--- a/src/encoding/gob/type.go
+++ b/src/encoding/gob/type.go
@@ -787,7 +787,7 @@ func mustGetTypeInfo(rt reflect.Type) *typeInfo {
 // contain things such as private fields, channels, and functions,
 // which are not usually transmissible in gob streams.
 //
-// Note: Since gobs can be stored permanently, It is good design
+// Note: Since gobs can be stored permanently, it is good design
 // to guarantee the encoding used by a GobEncoder is stable as the
 // software evolves.  For instance, it might make sense for GobEncode
 // to include a version number in the encoding.
diff --git a/src/encoding/json/decode.go b/src/encoding/json/decode.go
index 530e852..539d952 100644
--- a/src/encoding/json/decode.go
+++ b/src/encoding/json/decode.go
@@ -37,6 +37,7 @@ import (
 // To unmarshal JSON into a struct, Unmarshal matches incoming object
 // keys to the keys used by Marshal (either the struct field name or its tag),
 // preferring an exact match but also accepting a case-insensitive match.
+// Unmarshal will only set exported fields of the struct.
 //
 // To unmarshal JSON into an interface value,
 // Unmarshal stores one of these in the interface value:
@@ -48,16 +49,26 @@ import (
 //	map[string]interface{}, for JSON objects
 //	nil for JSON null
 //
-// To unmarshal a JSON array into a slice, Unmarshal resets the slice to nil
-// and then appends each element to the slice.
+// To unmarshal a JSON array into a slice, Unmarshal resets the slice length
+// to zero and then appends each element to the slice.
+// As a special case, to unmarshal an empty JSON array into a slice,
+// Unmarshal replaces the slice with a new empty slice.
 //
-// To unmarshal a JSON object into a map, Unmarshal replaces the map
-// with an empty map and then adds key-value pairs from the object to
-// the map.
+// To unmarshal a JSON array into a Go array, Unmarshal decodes
+// JSON array elements into corresponding Go array elements.
+// If the Go array is smaller than the JSON array,
+// the additional JSON array elements are discarded.
+// If the JSON array is smaller than the Go array,
+// the additional Go array elements are set to zero values.
+//
+// To unmarshal a JSON object into a string-keyed map, Unmarshal first
+// establishes a map to use, If the map is nil, Unmarshal allocates a new map.
+// Otherwise Unmarshal reuses the existing map, keeping existing entries.
+// Unmarshal then stores key-value pairs from the JSON object into the map.
 //
 // If a JSON value is not appropriate for a given target type,
 // or if a JSON number overflows the target type, Unmarshal
-// skips that field and completes the unmarshalling as best it can.
+// skips that field and completes the unmarshaling as best it can.
 // If no more serious errors are encountered, Unmarshal returns
 // an UnmarshalTypeError describing the earliest such error.
 //
@@ -174,6 +185,66 @@ func (n Number) Int64() (int64, error) {
 	return strconv.ParseInt(string(n), 10, 64)
 }
 
+// isValidNumber reports whether s is a valid JSON number literal.
+func isValidNumber(s string) bool {
+	// This function implements the JSON numbers grammar.
+	// See https://tools.ietf.org/html/rfc7159#section-6
+	// and http://json.org/number.gif
+
+	if s == "" {
+		return false
+	}
+
+	// Optional -
+	if s[0] == '-' {
+		s = s[1:]
+		if s == "" {
+			return false
+		}
+	}
+
+	// Digits
+	switch {
+	default:
+		return false
+
+	case s[0] == '0':
+		s = s[1:]
+
+	case '1' <= s[0] && s[0] <= '9':
+		s = s[1:]
+		for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
+			s = s[1:]
+		}
+	}
+
+	// . followed by 1 or more digits.
+	if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' {
+		s = s[2:]
+		for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
+			s = s[1:]
+		}
+	}
+
+	// e or E followed by an optional - or + and
+	// 1 or more digits.
+	if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
+		s = s[1:]
+		if s[0] == '+' || s[0] == '-' {
+			s = s[1:]
+			if s == "" {
+				return false
+			}
+		}
+		for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
+			s = s[1:]
+		}
+	}
+
+	// Make sure we are at the end.
+	return s == ""
+}
+
 // decodeState represents the state while decoding a JSON value.
 type decodeState struct {
 	data       []byte
@@ -241,7 +312,7 @@ func (d *decodeState) scanWhile(op int) int {
 			newOp = d.scan.eof()
 			d.off = len(d.data) + 1 // mark processed EOF with len+1
 		} else {
-			c := int(d.data[d.off])
+			c := d.data[d.off]
 			d.off++
 			newOp = d.scan.step(&d.scan, c)
 		}
@@ -757,7 +828,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
 				d.saveError(err)
 				break
 			}
-			v.Set(reflect.ValueOf(b[0:n]))
+			v.SetBytes(b[:n])
 		case reflect.String:
 			v.SetString(string(s))
 		case reflect.Interface:
@@ -781,6 +852,9 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
 		default:
 			if v.Kind() == reflect.String && v.Type() == numberType {
 				v.SetString(s)
+				if !isValidNumber(s) {
+					d.error(fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", item))
+				}
 				break
 			}
 			if fromQuoted {
diff --git a/src/encoding/json/decode_test.go b/src/encoding/json/decode_test.go
index 8aa158f..9546ae4 100644
--- a/src/encoding/json/decode_test.go
+++ b/src/encoding/json/decode_test.go
@@ -118,6 +118,7 @@ type Top struct {
 	Loop
 	Embed0p // has Point with X, Y, used
 	Embed0q // has Point with Z, used
+	embed   // contains exported field
 }
 
 type Embed0 struct {
@@ -148,6 +149,10 @@ type Embed0q struct {
 	Point
 }
 
+type embed struct {
+	Q int
+}
+
 type Loop struct {
 	Loop1 int `json:",omitempty"`
 	Loop2 int `json:",omitempty"`
@@ -331,7 +336,8 @@ var unmarshalTests = []unmarshalTest{
 			"Loop2": 14,
 			"X": 15,
 			"Y": 16,
-			"Z": 17
+			"Z": 17,
+			"Q": 18
 		}`,
 		ptr: new(Top),
 		out: Top{
@@ -361,6 +367,9 @@ var unmarshalTests = []unmarshalTest{
 			Embed0q: Embed0q{
 				Point: Point{Z: 17},
 			},
+			embed: embed{
+				Q: 18,
+			},
 		},
 	},
 	{
@@ -507,12 +516,15 @@ func TestMarshalEmbeds(t *testing.T) {
 		Embed0q: Embed0q{
 			Point: Point{Z: 17},
 		},
+		embed: embed{
+			Q: 18,
+		},
 	}
 	b, err := Marshal(top)
 	if err != nil {
 		t.Fatal(err)
 	}
-	want := "{\"Level0\":1,\"Level1b\":2,\"Level1c\":3,\"Level1a\":5,\"LEVEL1B\":6,\"e\":{\"Level1a\":8,\"Level1b\":9,\"Level1c\":10,\"Level1d\":11,\"x\":12},\"Loop1\":13,\"Loop2\":14,\"X\":15,\"Y\":16,\"Z\":17}"
+	want := "{\"Level0\":1,\"Level1b\":2,\"Level1c\":3,\"Level1a\":5,\"LEVEL1B\":6,\"e\":{\"Level1a\":8,\"Level1b\":9,\"Level1c\":10,\"Level1d\":11,\"x\":12},\"Loop1\":13,\"Loop2\":14,\"X\":15,\"Y\":16,\"Z\":17,\"Q\":18}"
 	if string(b) != want {
 		t.Errorf("Wrong marshal result.\n got: %q\nwant: %q", b, want)
 	}
@@ -716,7 +728,7 @@ func TestErrorMessageFromMisusedString(t *testing.T) {
 }
 
 func noSpace(c rune) rune {
-	if isSpace(c) {
+	if isSpace(byte(c)) { //only used for ascii
 		return -1
 	}
 	return c
@@ -1206,12 +1218,12 @@ func TestStringKind(t *testing.T) {
 
 	data, err := Marshal(m1)
 	if err != nil {
-		t.Errorf("Unexpected error marshalling: %v", err)
+		t.Errorf("Unexpected error marshaling: %v", err)
 	}
 
 	err = Unmarshal(data, &m2)
 	if err != nil {
-		t.Errorf("Unexpected error unmarshalling: %v", err)
+		t.Errorf("Unexpected error unmarshaling: %v", err)
 	}
 
 	if !reflect.DeepEqual(m1, m2) {
@@ -1241,6 +1253,27 @@ func TestByteKind(t *testing.T) {
 	}
 }
 
+// The fix for issue 8962 introduced a regression.
+// Issue 12921.
+func TestSliceOfCustomByte(t *testing.T) {
+	type Uint8 uint8
+
+	a := []Uint8("hello")
+
+	data, err := Marshal(a)
+	if err != nil {
+		t.Fatal(err)
+	}
+	var b []Uint8
+	err = Unmarshal(data, &b)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !reflect.DeepEqual(a, b) {
+		t.Fatal("expected %v == %v", a, b)
+	}
+}
+
 var decodeTypeErrorTests = []struct {
 	dest interface{}
 	src  string
diff --git a/src/encoding/json/encode.go b/src/encoding/json/encode.go
index 90782de..69ac7e0 100644
--- a/src/encoding/json/encode.go
+++ b/src/encoding/json/encode.go
@@ -14,6 +14,7 @@ import (
 	"bytes"
 	"encoding"
 	"encoding/base64"
+	"fmt"
 	"math"
 	"reflect"
 	"runtime"
@@ -30,7 +31,10 @@ import (
 // Marshal traverses the value v recursively.
 // If an encountered value implements the Marshaler interface
 // and is not a nil pointer, Marshal calls its MarshalJSON method
-// to produce JSON.  The nil pointer exception is not strictly necessary
+// to produce JSON. If no MarshalJSON method is present but the
+// value implements encoding.TextMarshaler instead, Marshal calls
+// its MarshalText method.
+// The nil pointer exception is not strictly necessary
 // but mimics a similar, necessary exception in the behavior of
 // UnmarshalJSON.
 //
@@ -445,12 +449,10 @@ func textMarshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
 	}
 	m := v.Interface().(encoding.TextMarshaler)
 	b, err := m.MarshalText()
-	if err == nil {
-		_, err = e.stringBytes(b)
-	}
 	if err != nil {
 		e.error(&MarshalerError{v.Type(), err})
 	}
+	e.stringBytes(b)
 }
 
 func addrTextMarshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
@@ -461,12 +463,10 @@ func addrTextMarshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
 	}
 	m := va.Interface().(encoding.TextMarshaler)
 	b, err := m.MarshalText()
-	if err == nil {
-		_, err = e.stringBytes(b)
-	}
 	if err != nil {
 		e.error(&MarshalerError{v.Type(), err})
 	}
+	e.stringBytes(b)
 }
 
 func boolEncoder(e *encodeState, v reflect.Value, quoted bool) {
@@ -530,9 +530,14 @@ var (
 func stringEncoder(e *encodeState, v reflect.Value, quoted bool) {
 	if v.Type() == numberType {
 		numStr := v.String()
+		// In Go1.5 the empty string encodes to "0", while this is not a valid number literal
+		// we keep compatibility so check validity after this.
 		if numStr == "" {
 			numStr = "0" // Number's zero-val
 		}
+		if !isValidNumber(numStr) {
+			e.error(fmt.Errorf("json: invalid number literal %q", numStr))
+		}
 		e.WriteString(numStr)
 		return
 	}
@@ -780,7 +785,7 @@ func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
 func (sv stringValues) get(i int) string   { return sv[i].String() }
 
 // NOTE: keep in sync with stringBytes below.
-func (e *encodeState) string(s string) (int, error) {
+func (e *encodeState) string(s string) int {
 	len0 := e.Len()
 	e.WriteByte('"')
 	start := 0
@@ -852,11 +857,11 @@ func (e *encodeState) string(s string) (int, error) {
 		e.WriteString(s[start:])
 	}
 	e.WriteByte('"')
-	return e.Len() - len0, nil
+	return e.Len() - len0
 }
 
 // NOTE: keep in sync with string above.
-func (e *encodeState) stringBytes(s []byte) (int, error) {
+func (e *encodeState) stringBytes(s []byte) int {
 	len0 := e.Len()
 	e.WriteByte('"')
 	start := 0
@@ -928,7 +933,7 @@ func (e *encodeState) stringBytes(s []byte) (int, error) {
 		e.Write(s[start:])
 	}
 	e.WriteByte('"')
-	return e.Len() - len0, nil
+	return e.Len() - len0
 }
 
 // A field represents a single field found in a struct.
@@ -1022,7 +1027,7 @@ func typeFields(t reflect.Type) []field {
 			// Scan f.typ for fields to include.
 			for i := 0; i < f.typ.NumField(); i++ {
 				sf := f.typ.Field(i)
-				if sf.PkgPath != "" { // unexported
+				if sf.PkgPath != "" && !sf.Anonymous { // unexported
 					continue
 				}
 				tag := sf.Tag.Get("json")
diff --git a/src/encoding/json/encode_test.go b/src/encoding/json/encode_test.go
index 7abfa85..c00491e 100644
--- a/src/encoding/json/encode_test.go
+++ b/src/encoding/json/encode_test.go
@@ -381,16 +381,10 @@ func TestStringBytes(t *testing.T) {
 		r = append(r, i)
 	}
 	s := string(r) + "\xff\xff\xffhello" // some invalid UTF-8 too
-	_, err := es.string(s)
-	if err != nil {
-		t.Fatal(err)
-	}
+	es.string(s)
 
 	esBytes := &encodeState{}
-	_, err = esBytes.stringBytes([]byte(s))
-	if err != nil {
-		t.Fatal(err)
-	}
+	esBytes.stringBytes([]byte(s))
 
 	enc := es.Buffer.String()
 	encBytes := esBytes.Buffer.String()
@@ -443,6 +437,18 @@ func TestIssue6458(t *testing.T) {
 	}
 }
 
+func TestIssue10281(t *testing.T) {
+	type Foo struct {
+		N Number
+	}
+	x := Foo{Number(`invalid`)}
+
+	b, err := Marshal(&x)
+	if err == nil {
+		t.Errorf("Marshal(&x) = %#q; want error", b)
+	}
+}
+
 func TestHTMLEscape(t *testing.T) {
 	var b, want bytes.Buffer
 	m := `{"M":"<html>foo &` + "\xe2\x80\xa8 \xe2\x80\xa9" + `</html>"}`
diff --git a/src/encoding/json/indent.go b/src/encoding/json/indent.go
index e1bacaf..7cd9f4d 100644
--- a/src/encoding/json/indent.go
+++ b/src/encoding/json/indent.go
@@ -36,7 +36,7 @@ func compact(dst *bytes.Buffer, src []byte, escape bool) error {
 			dst.WriteByte(hex[src[i+2]&0xF])
 			start = i + 3
 		}
-		v := scan.step(&scan, int(c))
+		v := scan.step(&scan, c)
 		if v >= scanSkipSpace {
 			if v == scanError {
 				break
@@ -70,8 +70,12 @@ func newline(dst *bytes.Buffer, prefix, indent string, depth int) {
 // indented line beginning with prefix followed by one or more
 // copies of indent according to the indentation nesting.
 // The data appended to dst does not begin with the prefix nor
-// any indentation, and has no trailing newline, to make it
-// easier to embed inside other formatted JSON data.
+// any indentation, to make it easier to embed inside other formatted JSON data.
+// Although leading space characters (space, tab, carriage return, newline)
+// at the beginning of src are dropped, trailing space characters
+// at the end of src are preserved and copied to dst.
+// For example, if src has no trailing spaces, neither will dst;
+// if src ends in a trailing newline, so will dst.
 func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
 	origLen := dst.Len()
 	var scan scanner
@@ -80,7 +84,7 @@ func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
 	depth := 0
 	for _, c := range src {
 		scan.bytes++
-		v := scan.step(&scan, int(c))
+		v := scan.step(&scan, c)
 		if v == scanSkipSpace {
 			continue
 		}
diff --git a/src/encoding/json/number_test.go b/src/encoding/json/number_test.go
new file mode 100644
index 0000000..4e63cf9
--- /dev/null
+++ b/src/encoding/json/number_test.go
@@ -0,0 +1,133 @@
+// Copyright 2011 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 json
+
+import (
+	"regexp"
+	"testing"
+)
+
+func TestNumberIsValid(t *testing.T) {
+	// From: http://stackoverflow.com/a/13340826
+	var jsonNumberRegexp = regexp.MustCompile(`^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$`)
+
+	validTests := []string{
+		"0",
+		"-0",
+		"1",
+		"-1",
+		"0.1",
+		"-0.1",
+		"1234",
+		"-1234",
+		"12.34",
+		"-12.34",
+		"12E0",
+		"12E1",
+		"12e34",
+		"12E-0",
+		"12e+1",
+		"12e-34",
+		"-12E0",
+		"-12E1",
+		"-12e34",
+		"-12E-0",
+		"-12e+1",
+		"-12e-34",
+		"1.2E0",
+		"1.2E1",
+		"1.2e34",
+		"1.2E-0",
+		"1.2e+1",
+		"1.2e-34",
+		"-1.2E0",
+		"-1.2E1",
+		"-1.2e34",
+		"-1.2E-0",
+		"-1.2e+1",
+		"-1.2e-34",
+		"0E0",
+		"0E1",
+		"0e34",
+		"0E-0",
+		"0e+1",
+		"0e-34",
+		"-0E0",
+		"-0E1",
+		"-0e34",
+		"-0E-0",
+		"-0e+1",
+		"-0e-34",
+	}
+
+	for _, test := range validTests {
+		if !isValidNumber(test) {
+			t.Errorf("%s should be valid", test)
+		}
+
+		var f float64
+		if err := Unmarshal([]byte(test), &f); err != nil {
+			t.Errorf("%s should be valid but Unmarshal failed: %v", test, err)
+		}
+
+		if !jsonNumberRegexp.MatchString(test) {
+			t.Errorf("%s should be valid but regexp does not match", test)
+		}
+	}
+
+	invalidTests := []string{
+		"",
+		"invalid",
+		"1.0.1",
+		"1..1",
+		"-1-2",
+		"012a42",
+		"01.2",
+		"012",
+		"12E12.12",
+		"1e2e3",
+		"1e+-2",
+		"1e--23",
+		"1e",
+		"e1",
+		"1e+",
+		"1ea",
+		"1a",
+		"1.a",
+		"1.",
+		"01",
+		"1.e1",
+	}
+
+	for _, test := range invalidTests {
+		if isValidNumber(test) {
+			t.Errorf("%s should be invalid", test)
+		}
+
+		var f float64
+		if err := Unmarshal([]byte(test), &f); err == nil {
+			t.Errorf("%s should be invalid but unmarshal wrote %v", test, f)
+		}
+
+		if jsonNumberRegexp.MatchString(test) {
+			t.Errorf("%s should be invalid but matches regexp", test)
+		}
+	}
+}
+
+func BenchmarkNumberIsValid(b *testing.B) {
+	s := "-61657.61667E+61673"
+	for i := 0; i < b.N; i++ {
+		isValidNumber(s)
+	}
+}
+
+func BenchmarkNumberIsValidRegexp(b *testing.B) {
+	var jsonNumberRegexp = regexp.MustCompile(`^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$`)
+	s := "-61657.61667E+61673"
+	for i := 0; i < b.N; i++ {
+		jsonNumberRegexp.MatchString(s)
+	}
+}
diff --git a/src/encoding/json/scanner.go b/src/encoding/json/scanner.go
index 38d0b08..ee6622e 100644
--- a/src/encoding/json/scanner.go
+++ b/src/encoding/json/scanner.go
@@ -21,7 +21,7 @@ func checkValid(data []byte, scan *scanner) error {
 	scan.reset()
 	for _, c := range data {
 		scan.bytes++
-		if scan.step(scan, int(c)) == scanError {
+		if scan.step(scan, c) == scanError {
 			return scan.err
 		}
 	}
@@ -37,7 +37,7 @@ func checkValid(data []byte, scan *scanner) error {
 func nextValue(data []byte, scan *scanner) (value, rest []byte, err error) {
 	scan.reset()
 	for i, c := range data {
-		v := scan.step(scan, int(c))
+		v := scan.step(scan, c)
 		if v >= scanEndObject {
 			switch v {
 			// probe the scanner with a space to determine whether we will
@@ -50,7 +50,7 @@ func nextValue(data []byte, scan *scanner) (value, rest []byte, err error) {
 			case scanError:
 				return nil, nil, scan.err
 			case scanEnd:
-				return data[0:i], data[i:], nil
+				return data[:i], data[i:], nil
 			}
 		}
 	}
@@ -85,7 +85,7 @@ type scanner struct {
 	// Also tried using an integer constant and a single func
 	// with a switch, but using the func directly was 10% faster
 	// on a 64-bit Mac Mini, and it's nicer to read.
-	step func(*scanner, int) int
+	step func(*scanner, byte) int
 
 	// Reached end of top-level value.
 	endTop bool
@@ -99,7 +99,7 @@ type scanner struct {
 	// 1-byte redo (see undo method)
 	redo      bool
 	redoCode  int
-	redoState func(*scanner, int) int
+	redoState func(*scanner, byte) int
 
 	// total bytes consumed, updated by decoder.Decode
 	bytes int64
@@ -188,13 +188,13 @@ func (s *scanner) popParseState() {
 	}
 }
 
-func isSpace(c rune) bool {
+func isSpace(c byte) bool {
 	return c == ' ' || c == '\t' || c == '\r' || c == '\n'
 }
 
 // stateBeginValueOrEmpty is the state after reading `[`.
-func stateBeginValueOrEmpty(s *scanner, c int) int {
-	if c <= ' ' && isSpace(rune(c)) {
+func stateBeginValueOrEmpty(s *scanner, c byte) int {
+	if c <= ' ' && isSpace(c) {
 		return scanSkipSpace
 	}
 	if c == ']' {
@@ -204,8 +204,8 @@ func stateBeginValueOrEmpty(s *scanner, c int) int {
 }
 
 // stateBeginValue is the state at the beginning of the input.
-func stateBeginValue(s *scanner, c int) int {
-	if c <= ' ' && isSpace(rune(c)) {
+func stateBeginValue(s *scanner, c byte) int {
+	if c <= ' ' && isSpace(c) {
 		return scanSkipSpace
 	}
 	switch c {
@@ -244,8 +244,8 @@ func stateBeginValue(s *scanner, c int) int {
 }
 
 // stateBeginStringOrEmpty is the state after reading `{`.
-func stateBeginStringOrEmpty(s *scanner, c int) int {
-	if c <= ' ' && isSpace(rune(c)) {
+func stateBeginStringOrEmpty(s *scanner, c byte) int {
+	if c <= ' ' && isSpace(c) {
 		return scanSkipSpace
 	}
 	if c == '}' {
@@ -257,8 +257,8 @@ func stateBeginStringOrEmpty(s *scanner, c int) int {
 }
 
 // stateBeginString is the state after reading `{"key": value,`.
-func stateBeginString(s *scanner, c int) int {
-	if c <= ' ' && isSpace(rune(c)) {
+func stateBeginString(s *scanner, c byte) int {
+	if c <= ' ' && isSpace(c) {
 		return scanSkipSpace
 	}
 	if c == '"' {
@@ -270,7 +270,7 @@ func stateBeginString(s *scanner, c int) int {
 
 // stateEndValue is the state after completing a value,
 // such as after reading `{}` or `true` or `["x"`.
-func stateEndValue(s *scanner, c int) int {
+func stateEndValue(s *scanner, c byte) int {
 	n := len(s.parseState)
 	if n == 0 {
 		// Completed top-level before the current byte.
@@ -278,7 +278,7 @@ func stateEndValue(s *scanner, c int) int {
 		s.endTop = true
 		return stateEndTop(s, c)
 	}
-	if c <= ' ' && isSpace(rune(c)) {
+	if c <= ' ' && isSpace(c) {
 		s.step = stateEndValue
 		return scanSkipSpace
 	}
@@ -319,7 +319,7 @@ func stateEndValue(s *scanner, c int) int {
 // stateEndTop is the state after finishing the top-level value,
 // such as after reading `{}` or `[1,2,3]`.
 // Only space characters should be seen now.
-func stateEndTop(s *scanner, c int) int {
+func stateEndTop(s *scanner, c byte) int {
 	if c != ' ' && c != '\t' && c != '\r' && c != '\n' {
 		// Complain about non-space byte on next call.
 		s.error(c, "after top-level value")
@@ -328,7 +328,7 @@ func stateEndTop(s *scanner, c int) int {
 }
 
 // stateInString is the state after reading `"`.
-func stateInString(s *scanner, c int) int {
+func stateInString(s *scanner, c byte) int {
 	if c == '"' {
 		s.step = stateEndValue
 		return scanContinue
@@ -344,13 +344,12 @@ func stateInString(s *scanner, c int) int {
 }
 
 // stateInStringEsc is the state after reading `"\` during a quoted string.
-func stateInStringEsc(s *scanner, c int) int {
+func stateInStringEsc(s *scanner, c byte) int {
 	switch c {
 	case 'b', 'f', 'n', 'r', 't', '\\', '/', '"':
 		s.step = stateInString
 		return scanContinue
-	}
-	if c == 'u' {
+	case 'u':
 		s.step = stateInStringEscU
 		return scanContinue
 	}
@@ -358,7 +357,7 @@ func stateInStringEsc(s *scanner, c int) int {
 }
 
 // stateInStringEscU is the state after reading `"\u` during a quoted string.
-func stateInStringEscU(s *scanner, c int) int {
+func stateInStringEscU(s *scanner, c byte) int {
 	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
 		s.step = stateInStringEscU1
 		return scanContinue
@@ -368,7 +367,7 @@ func stateInStringEscU(s *scanner, c int) int {
 }
 
 // stateInStringEscU1 is the state after reading `"\u1` during a quoted string.
-func stateInStringEscU1(s *scanner, c int) int {
+func stateInStringEscU1(s *scanner, c byte) int {
 	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
 		s.step = stateInStringEscU12
 		return scanContinue
@@ -378,7 +377,7 @@ func stateInStringEscU1(s *scanner, c int) int {
 }
 
 // stateInStringEscU12 is the state after reading `"\u12` during a quoted string.
-func stateInStringEscU12(s *scanner, c int) int {
+func stateInStringEscU12(s *scanner, c byte) int {
 	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
 		s.step = stateInStringEscU123
 		return scanContinue
@@ -388,7 +387,7 @@ func stateInStringEscU12(s *scanner, c int) int {
 }
 
 // stateInStringEscU123 is the state after reading `"\u123` during a quoted string.
-func stateInStringEscU123(s *scanner, c int) int {
+func stateInStringEscU123(s *scanner, c byte) int {
 	if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
 		s.step = stateInString
 		return scanContinue
@@ -398,7 +397,7 @@ func stateInStringEscU123(s *scanner, c int) int {
 }
 
 // stateNeg is the state after reading `-` during a number.
-func stateNeg(s *scanner, c int) int {
+func stateNeg(s *scanner, c byte) int {
 	if c == '0' {
 		s.step = state0
 		return scanContinue
@@ -412,7 +411,7 @@ func stateNeg(s *scanner, c int) int {
 
 // state1 is the state after reading a non-zero integer during a number,
 // such as after reading `1` or `100` but not `0`.
-func state1(s *scanner, c int) int {
+func state1(s *scanner, c byte) int {
 	if '0' <= c && c <= '9' {
 		s.step = state1
 		return scanContinue
@@ -421,7 +420,7 @@ func state1(s *scanner, c int) int {
 }
 
 // state0 is the state after reading `0` during a number.
-func state0(s *scanner, c int) int {
+func state0(s *scanner, c byte) int {
 	if c == '.' {
 		s.step = stateDot
 		return scanContinue
@@ -435,7 +434,7 @@ func state0(s *scanner, c int) int {
 
 // stateDot is the state after reading the integer and decimal point in a number,
 // such as after reading `1.`.
-func stateDot(s *scanner, c int) int {
+func stateDot(s *scanner, c byte) int {
 	if '0' <= c && c <= '9' {
 		s.step = stateDot0
 		return scanContinue
@@ -445,9 +444,8 @@ func stateDot(s *scanner, c int) int {
 
 // stateDot0 is the state after reading the integer, decimal point, and subsequent
 // digits of a number, such as after reading `3.14`.
-func stateDot0(s *scanner, c int) int {
+func stateDot0(s *scanner, c byte) int {
 	if '0' <= c && c <= '9' {
-		s.step = stateDot0
 		return scanContinue
 	}
 	if c == 'e' || c == 'E' {
@@ -459,12 +457,8 @@ func stateDot0(s *scanner, c int) int {
 
 // stateE is the state after reading the mantissa and e in a number,
 // such as after reading `314e` or `0.314e`.
-func stateE(s *scanner, c int) int {
-	if c == '+' {
-		s.step = stateESign
-		return scanContinue
-	}
-	if c == '-' {
+func stateE(s *scanner, c byte) int {
+	if c == '+' || c == '-' {
 		s.step = stateESign
 		return scanContinue
 	}
@@ -473,7 +467,7 @@ func stateE(s *scanner, c int) int {
 
 // stateESign is the state after reading the mantissa, e, and sign in a number,
 // such as after reading `314e-` or `0.314e+`.
-func stateESign(s *scanner, c int) int {
+func stateESign(s *scanner, c byte) int {
 	if '0' <= c && c <= '9' {
 		s.step = stateE0
 		return scanContinue
@@ -484,16 +478,15 @@ func stateESign(s *scanner, c int) int {
 // stateE0 is the state after reading the mantissa, e, optional sign,
 // and at least one digit of the exponent in a number,
 // such as after reading `314e-2` or `0.314e+1` or `3.14e0`.
-func stateE0(s *scanner, c int) int {
+func stateE0(s *scanner, c byte) int {
 	if '0' <= c && c <= '9' {
-		s.step = stateE0
 		return scanContinue
 	}
 	return stateEndValue(s, c)
 }
 
 // stateT is the state after reading `t`.
-func stateT(s *scanner, c int) int {
+func stateT(s *scanner, c byte) int {
 	if c == 'r' {
 		s.step = stateTr
 		return scanContinue
@@ -502,7 +495,7 @@ func stateT(s *scanner, c int) int {
 }
 
 // stateTr is the state after reading `tr`.
-func stateTr(s *scanner, c int) int {
+func stateTr(s *scanner, c byte) int {
 	if c == 'u' {
 		s.step = stateTru
 		return scanContinue
@@ -511,7 +504,7 @@ func stateTr(s *scanner, c int) int {
 }
 
 // stateTru is the state after reading `tru`.
-func stateTru(s *scanner, c int) int {
+func stateTru(s *scanner, c byte) int {
 	if c == 'e' {
 		s.step = stateEndValue
 		return scanContinue
@@ -520,7 +513,7 @@ func stateTru(s *scanner, c int) int {
 }
 
 // stateF is the state after reading `f`.
-func stateF(s *scanner, c int) int {
+func stateF(s *scanner, c byte) int {
 	if c == 'a' {
 		s.step = stateFa
 		return scanContinue
@@ -529,7 +522,7 @@ func stateF(s *scanner, c int) int {
 }
 
 // stateFa is the state after reading `fa`.
-func stateFa(s *scanner, c int) int {
+func stateFa(s *scanner, c byte) int {
 	if c == 'l' {
 		s.step = stateFal
 		return scanContinue
@@ -538,7 +531,7 @@ func stateFa(s *scanner, c int) int {
 }
 
 // stateFal is the state after reading `fal`.
-func stateFal(s *scanner, c int) int {
+func stateFal(s *scanner, c byte) int {
 	if c == 's' {
 		s.step = stateFals
 		return scanContinue
@@ -547,7 +540,7 @@ func stateFal(s *scanner, c int) int {
 }
 
 // stateFals is the state after reading `fals`.
-func stateFals(s *scanner, c int) int {
+func stateFals(s *scanner, c byte) int {
 	if c == 'e' {
 		s.step = stateEndValue
 		return scanContinue
@@ -556,7 +549,7 @@ func stateFals(s *scanner, c int) int {
 }
 
 // stateN is the state after reading `n`.
-func stateN(s *scanner, c int) int {
+func stateN(s *scanner, c byte) int {
 	if c == 'u' {
 		s.step = stateNu
 		return scanContinue
@@ -565,7 +558,7 @@ func stateN(s *scanner, c int) int {
 }
 
 // stateNu is the state after reading `nu`.
-func stateNu(s *scanner, c int) int {
+func stateNu(s *scanner, c byte) int {
 	if c == 'l' {
 		s.step = stateNul
 		return scanContinue
@@ -574,7 +567,7 @@ func stateNu(s *scanner, c int) int {
 }
 
 // stateNul is the state after reading `nul`.
-func stateNul(s *scanner, c int) int {
+func stateNul(s *scanner, c byte) int {
 	if c == 'l' {
 		s.step = stateEndValue
 		return scanContinue
@@ -584,19 +577,19 @@ func stateNul(s *scanner, c int) int {
 
 // stateError is the state after reaching a syntax error,
 // such as after reading `[1}` or `5.1.2`.
-func stateError(s *scanner, c int) int {
+func stateError(s *scanner, c byte) int {
 	return scanError
 }
 
 // error records an error and switches to the error state.
-func (s *scanner) error(c int, context string) int {
+func (s *scanner) error(c byte, context string) int {
 	s.step = stateError
 	s.err = &SyntaxError{"invalid character " + quoteChar(c) + " " + context, s.bytes}
 	return scanError
 }
 
 // quoteChar formats c as a quoted character literal
-func quoteChar(c int) string {
+func quoteChar(c byte) string {
 	// special cases - different from quoted strings
 	if c == '\'' {
 		return `'\''`
@@ -623,7 +616,7 @@ func (s *scanner) undo(scanCode int) {
 }
 
 // stateRedo helps implement the scanner's 1-byte undo.
-func stateRedo(s *scanner, c int) int {
+func stateRedo(s *scanner, c byte) int {
 	s.redo = false
 	s.step = s.redoState
 	return s.redoCode
diff --git a/src/encoding/json/stream.go b/src/encoding/json/stream.go
index dc53bce..8ddcf4d 100644
--- a/src/encoding/json/stream.go
+++ b/src/encoding/json/stream.go
@@ -90,7 +90,7 @@ Input:
 		// Look in the buffer for a new value.
 		for i, c := range dec.buf[scanp:] {
 			dec.scan.bytes++
-			v := dec.scan.step(&dec.scan, int(c))
+			v := dec.scan.step(&dec.scan, c)
 			if v == scanEnd {
 				scanp += i
 				break Input
@@ -157,7 +157,7 @@ func (dec *Decoder) refill() error {
 
 func nonSpace(b []byte) bool {
 	for _, c := range b {
-		if !isSpace(rune(c)) {
+		if !isSpace(c) {
 			return true
 		}
 	}
@@ -433,7 +433,7 @@ func (dec *Decoder) tokenError(c byte) (Token, error) {
 	case tokenObjectComma:
 		context = " after object key:value pair"
 	}
-	return nil, &SyntaxError{"invalid character " + quoteChar(int(c)) + " " + context, 0}
+	return nil, &SyntaxError{"invalid character " + quoteChar(c) + " " + context, 0}
 }
 
 // More reports whether there is another element in the
@@ -448,7 +448,7 @@ func (dec *Decoder) peek() (byte, error) {
 	for {
 		for i := dec.scanp; i < len(dec.buf); i++ {
 			c := dec.buf[i]
-			if isSpace(rune(c)) {
+			if isSpace(c) {
 				continue
 			}
 			dec.scanp = i
diff --git a/src/encoding/pem/pem_test.go b/src/encoding/pem/pem_test.go
index ab656c6..958dbc1 100644
--- a/src/encoding/pem/pem_test.go
+++ b/src/encoding/pem/pem_test.go
@@ -155,20 +155,28 @@ func TestFuzz(t *testing.T) {
 		}
 
 		var buf bytes.Buffer
-		err := Encode(&buf, &block)
-		decoded, rest := Decode(buf.Bytes())
-
-		switch {
-		case err != nil:
+		if err := Encode(&buf, &block); err != nil {
 			t.Errorf("Encode of %#v resulted in error: %s", &block, err)
-		case !reflect.DeepEqual(&block, decoded):
+			return false
+		}
+		decoded, rest := Decode(buf.Bytes())
+		if block.Headers == nil {
+			// Encoder supports nil Headers but decoder returns initialized.
+			block.Headers = make(map[string]string)
+		}
+		if block.Bytes == nil {
+			// Encoder supports nil Bytes but decoder returns initialized.
+			block.Bytes = make([]byte, 0)
+		}
+		if !reflect.DeepEqual(decoded, &block) {
 			t.Errorf("Encode of %#v decoded as %#v", &block, decoded)
-		case len(rest) != 0:
+			return false
+		}
+		if len(rest) != 0 {
 			t.Errorf("Encode of %#v decoded correctly, but with %x left over", block, rest)
-		default:
-			return true
+			return false
 		}
-		return false
+		return true
 	}
 
 	// Explicitly test the empty block.
diff --git a/src/encoding/xml/marshal.go b/src/encoding/xml/marshal.go
index 86d1422..8ebd693 100644
--- a/src/encoding/xml/marshal.go
+++ b/src/encoding/xml/marshal.go
@@ -48,6 +48,8 @@ const (
 //       field name in the XML element.
 //     - a field with tag ",chardata" is written as character data,
 //       not as an XML element.
+//     - a field with tag ",cdata" is written as character data
+//       wrapped in one or more <![CDATA[ ... ]]> tags, not as an XML element.
 //     - a field with tag ",innerxml" is written verbatim, not subject
 //       to the usual marshalling procedure.
 //     - a field with tag ",comment" is written as an XML comment, not
@@ -768,7 +770,11 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
 		}
 
 		switch finfo.flags & fMode {
-		case fCharData:
+		case fCDATA, fCharData:
+			emit := EscapeText
+			if finfo.flags&fMode == fCDATA {
+				emit = emitCDATA
+			}
 			if err := s.trim(finfo.parents); err != nil {
 				return err
 			}
@@ -777,7 +783,9 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
 				if err != nil {
 					return err
 				}
-				Escape(p, data)
+				if err := emit(p, data); err != nil {
+					return err
+				}
 				continue
 			}
 			if vf.CanAddr() {
@@ -787,27 +795,37 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
 					if err != nil {
 						return err
 					}
-					Escape(p, data)
+					if err := emit(p, data); err != nil {
+						return err
+					}
 					continue
 				}
 			}
 			var scratch [64]byte
 			switch vf.Kind() {
 			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-				Escape(p, strconv.AppendInt(scratch[:0], vf.Int(), 10))
+				if err := emit(p, strconv.AppendInt(scratch[:0], vf.Int(), 10)); err != nil {
+					return err
+				}
 			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
-				Escape(p, strconv.AppendUint(scratch[:0], vf.Uint(), 10))
+				if err := emit(p, strconv.AppendUint(scratch[:0], vf.Uint(), 10)); err != nil {
+					return err
+				}
 			case reflect.Float32, reflect.Float64:
-				Escape(p, strconv.AppendFloat(scratch[:0], vf.Float(), 'g', -1, vf.Type().Bits()))
+				if err := emit(p, strconv.AppendFloat(scratch[:0], vf.Float(), 'g', -1, vf.Type().Bits())); err != nil {
+					return err
+				}
 			case reflect.Bool:
-				Escape(p, strconv.AppendBool(scratch[:0], vf.Bool()))
+				if err := emit(p, strconv.AppendBool(scratch[:0], vf.Bool())); err != nil {
+					return err
+				}
 			case reflect.String:
-				if err := EscapeText(p, []byte(vf.String())); err != nil {
+				if err := emit(p, []byte(vf.String())); err != nil {
 					return err
 				}
 			case reflect.Slice:
 				if elem, ok := vf.Interface().([]byte); ok {
-					if err := EscapeText(p, elem); err != nil {
+					if err := emit(p, elem); err != nil {
 						return err
 					}
 				}
diff --git a/src/encoding/xml/marshal_test.go b/src/encoding/xml/marshal_test.go
index 66675d7..fe8b16f 100644
--- a/src/encoding/xml/marshal_test.go
+++ b/src/encoding/xml/marshal_test.go
@@ -139,6 +139,7 @@ type EmbedA struct {
 	EmbedC
 	EmbedB EmbedB
 	FieldA string
+	embedD
 }
 
 type EmbedB struct {
@@ -153,6 +154,11 @@ type EmbedC struct {
 	FieldC  string
 }
 
+type embedD struct {
+	fieldD string
+	FieldE string // Promoted and visible when embedD is embedded.
+}
+
 type NameCasing struct {
 	XMLName struct{} `xml:"casing"`
 	Xy      string
@@ -350,6 +356,15 @@ type NestedAndComment struct {
 	Comment string   `xml:",comment"`
 }
 
+type CDataTest struct {
+	Chardata string `xml:",cdata"`
+}
+
+type NestedAndCData struct {
+	AB    []string `xml:"A>B"`
+	CDATA string   `xml:",cdata"`
+}
+
 func ifaceptr(x interface{}) interface{} {
 	return &x
 }
@@ -711,6 +726,9 @@ var marshalTests = []struct {
 				},
 			},
 			FieldA: "A.A",
+			embedD: embedD{
+				FieldE: "A.D.E",
+			},
 		},
 		ExpectXML: `<EmbedA>` +
 			`<FieldB>A.C.B</FieldB>` +
@@ -724,6 +742,7 @@ var marshalTests = []struct {
 			`<FieldC>A.B.C.C</FieldC>` +
 			`</EmbedB>` +
 			`<FieldA>A.A</FieldA>` +
+			`<FieldE>A.D.E</FieldE>` +
 			`</EmbedA>`,
 	},
 
@@ -968,6 +987,42 @@ var marshalTests = []struct {
 			MyInt: 42,
 		},
 	},
+	// Test outputting CDATA-wrapped text.
+	{
+		ExpectXML: `<CDataTest></CDataTest>`,
+		Value:     &CDataTest{},
+	},
+	{
+		ExpectXML: `<CDataTest><![CDATA[http://example.com/tests/1?foo=1&bar=baz]]></CDataTest>`,
+		Value: &CDataTest{
+			Chardata: "http://example.com/tests/1?foo=1&bar=baz",
+		},
+	},
+	{
+		ExpectXML: `<CDataTest><![CDATA[Literal <![CDATA[Nested]]]]><![CDATA[>!]]></CDataTest>`,
+		Value: &CDataTest{
+			Chardata: "Literal <![CDATA[Nested]]>!",
+		},
+	},
+	{
+		ExpectXML: `<CDataTest><![CDATA[<![CDATA[Nested]]]]><![CDATA[> Literal!]]></CDataTest>`,
+		Value: &CDataTest{
+			Chardata: "<![CDATA[Nested]]> Literal!",
+		},
+	},
+	{
+		ExpectXML: `<CDataTest><![CDATA[<![CDATA[Nested]]]]><![CDATA[> Literal! <![CDATA[Nested]]]]><![CDATA[> Literal!]]></CDataTest>`,
+		Value: &CDataTest{
+			Chardata: "<![CDATA[Nested]]> Literal! <![CDATA[Nested]]> Literal!",
+		},
+	},
+	{
+		ExpectXML: `<CDataTest><![CDATA[<![CDATA[<![CDATA[Nested]]]]><![CDATA[>]]]]><![CDATA[>]]></CDataTest>`,
+		Value: &CDataTest{
+			Chardata: "<![CDATA[<![CDATA[Nested]]>]]>",
+		},
+	},
+
 	// Test omitempty with parent chain; see golang.org/issue/4168.
 	{
 		ExpectXML: `<Strings><A></A></Strings>`,
@@ -1006,6 +1061,10 @@ var marshalTests = []struct {
 		ExpectXML: `<NestedAndComment><A><B></B><B></B></A><!--test--></NestedAndComment>`,
 		Value:     &NestedAndComment{AB: make([]string, 2), Comment: "test"},
 	},
+	{
+		ExpectXML: `<NestedAndCData><A><B></B><B></B></A><![CDATA[test]]></NestedAndCData>`,
+		Value:     &NestedAndCData{AB: make([]string, 2), CDATA: "test"},
+	},
 }
 
 func TestMarshal(t *testing.T) {
@@ -1695,7 +1754,7 @@ func TestRace9796(t *testing.T) {
 	for i := 0; i < 2; i++ {
 		wg.Add(1)
 		go func() {
-			Marshal(B{[]A{A{}}})
+			Marshal(B{[]A{{}}})
 			wg.Done()
 		}()
 	}
diff --git a/src/encoding/xml/read.go b/src/encoding/xml/read.go
index 75b9f2b..77b4c7b 100644
--- a/src/encoding/xml/read.go
+++ b/src/encoding/xml/read.go
@@ -431,7 +431,7 @@ func (p *Decoder) unmarshal(val reflect.Value, start *StartElement) error {
 					}
 				}
 
-			case fCharData:
+			case fCDATA, fCharData:
 				if !saveData.IsValid() {
 					saveData = finfo.value(sv)
 				}
diff --git a/src/encoding/xml/read_test.go b/src/encoding/xml/read_test.go
index 7d004dc..7a98092 100644
--- a/src/encoding/xml/read_test.go
+++ b/src/encoding/xml/read_test.go
@@ -712,3 +712,24 @@ func TestUnmarshalIntoInterface(t *testing.T) {
 		t.Errorf("failed to unmarshal into interface, have %q want %q", have, want)
 	}
 }
+
+type X struct {
+	D string `xml:",comment"`
+}
+
+// Issue 11112. Unmarshal must reject invalid comments.
+func TestMalformedComment(t *testing.T) {
+	testData := []string{
+		"<X><!-- a---></X>",
+		"<X><!-- -- --></X>",
+		"<X><!-- a--b --></X>",
+		"<X><!------></X>",
+	}
+	for i, test := range testData {
+		data := []byte(test)
+		v := new(X)
+		if err := Unmarshal(data, v); err == nil {
+			t.Errorf("%d: unmarshal should reject invalid comments", i)
+		}
+	}
+}
diff --git a/src/encoding/xml/typeinfo.go b/src/encoding/xml/typeinfo.go
index 22248d2..6483c8d 100644
--- a/src/encoding/xml/typeinfo.go
+++ b/src/encoding/xml/typeinfo.go
@@ -31,6 +31,7 @@ type fieldFlags int
 const (
 	fElement fieldFlags = 1 << iota
 	fAttr
+	fCDATA
 	fCharData
 	fInnerXml
 	fComment
@@ -38,7 +39,7 @@ const (
 
 	fOmitEmpty
 
-	fMode = fElement | fAttr | fCharData | fInnerXml | fComment | fAny
+	fMode = fElement | fAttr | fCDATA | fCharData | fInnerXml | fComment | fAny
 )
 
 var tinfoMap = make(map[reflect.Type]*typeInfo)
@@ -60,7 +61,7 @@ func getTypeInfo(typ reflect.Type) (*typeInfo, error) {
 		n := typ.NumField()
 		for i := 0; i < n; i++ {
 			f := typ.Field(i)
-			if f.PkgPath != "" || f.Tag.Get("xml") == "-" {
+			if (f.PkgPath != "" && !f.Anonymous) || f.Tag.Get("xml") == "-" {
 				continue // Private field
 			}
 
@@ -130,6 +131,8 @@ func structFieldInfo(typ reflect.Type, f *reflect.StructField) (*fieldInfo, erro
 			switch flag {
 			case "attr":
 				finfo.flags |= fAttr
+			case "cdata":
+				finfo.flags |= fCDATA
 			case "chardata":
 				finfo.flags |= fCharData
 			case "innerxml":
@@ -148,7 +151,7 @@ func structFieldInfo(typ reflect.Type, f *reflect.StructField) (*fieldInfo, erro
 		switch mode := finfo.flags & fMode; mode {
 		case 0:
 			finfo.flags |= fElement
-		case fAttr, fCharData, fInnerXml, fComment, fAny:
+		case fAttr, fCDATA, fCharData, fInnerXml, fComment, fAny:
 			if f.Name == "XMLName" || tag != "" && mode != fAttr {
 				valid = false
 			}
diff --git a/src/encoding/xml/xml.go b/src/encoding/xml/xml.go
index 0a21c93..45f4157 100644
--- a/src/encoding/xml/xml.go
+++ b/src/encoding/xml/xml.go
@@ -227,7 +227,8 @@ func NewDecoder(r io.Reader) *Decoder {
 //
 // Token guarantees that the StartElement and EndElement
 // tokens it returns are properly nested and matched:
-// if Token encounters an unexpected end element,
+// if Token encounters an unexpected end element
+// or EOF before all expected end elements,
 // it will return an error.
 //
 // Token implements XML name spaces as described by
@@ -245,6 +246,9 @@ func (d *Decoder) Token() (t Token, err error) {
 		t = d.nextToken
 		d.nextToken = nil
 	} else if t, err = d.rawToken(); err != nil {
+		if err == io.EOF && d.stk != nil && d.stk.kind != stkEOF {
+			err = d.syntaxError("unexpected EOF")
+		}
 		return
 	}
 
@@ -580,7 +584,7 @@ func (d *Decoder) rawToken() (Token, error) {
 				return nil, d.err
 			}
 			enc := procInst("encoding", content)
-			if enc != "" && enc != "utf-8" && enc != "UTF-8" {
+			if enc != "" && enc != "utf-8" && enc != "UTF-8" && !strings.EqualFold(enc, "utf-8") {
 				if d.CharsetReader == nil {
 					d.err = fmt.Errorf("xml: encoding %q declared but Decoder.CharsetReader is nil", enc)
 					return nil, d.err
@@ -621,7 +625,12 @@ func (d *Decoder) rawToken() (Token, error) {
 					return nil, d.err
 				}
 				d.buf.WriteByte(b)
-				if b0 == '-' && b1 == '-' && b == '>' {
+				if b0 == '-' && b1 == '-' {
+					if b != '>' {
+						d.err = d.syntaxError(
+							`invalid sequence "--" not allowed in comments`)
+						return nil, d.err
+					}
 					break
 				}
 				b0, b1 = b1, b
@@ -1940,6 +1949,46 @@ func Escape(w io.Writer, s []byte) {
 	EscapeText(w, s)
 }
 
+var (
+	cdataStart  = []byte("<![CDATA[")
+	cdataEnd    = []byte("]]>")
+	cdataEscape = []byte("]]]]><![CDATA[>")
+)
+
+// emitCDATA writes to w the CDATA-wrapped plain text data s.
+// It escapes CDATA directives nested in s.
+func emitCDATA(w io.Writer, s []byte) error {
+	if len(s) == 0 {
+		return nil
+	}
+	if _, err := w.Write(cdataStart); err != nil {
+		return err
+	}
+	for {
+		i := bytes.Index(s, cdataEnd)
+		if i >= 0 && i+len(cdataEnd) <= len(s) {
+			// Found a nested CDATA directive end.
+			if _, err := w.Write(s[:i]); err != nil {
+				return err
+			}
+			if _, err := w.Write(cdataEscape); err != nil {
+				return err
+			}
+			i += len(cdataEnd)
+		} else {
+			if _, err := w.Write(s); err != nil {
+				return err
+			}
+			break
+		}
+		s = s[i:]
+	}
+	if _, err := w.Write(cdataEnd); err != nil {
+		return err
+	}
+	return nil
+}
+
 // procInst parses the `param="..."` or `param='...'`
 // value out of the provided string, returning "" if not found.
 func procInst(param, s string) string {
diff --git a/src/encoding/xml/xml_test.go b/src/encoding/xml/xml_test.go
index 312a7c9..5d5e4bf 100644
--- a/src/encoding/xml/xml_test.go
+++ b/src/encoding/xml/xml_test.go
@@ -750,3 +750,56 @@ func TestIssue5880(t *testing.T) {
 		t.Errorf("Marshal generated invalid UTF-8: %x", data)
 	}
 }
+
+func TestIssue11405(t *testing.T) {
+	testCases := []string{
+		"<root>",
+		"<root><foo>",
+		"<root><foo></foo>",
+	}
+	for _, tc := range testCases {
+		d := NewDecoder(strings.NewReader(tc))
+		var err error
+		for {
+			_, err = d.Token()
+			if err != nil {
+				break
+			}
+		}
+		if _, ok := err.(*SyntaxError); !ok {
+			t.Errorf("%s: Token: Got error %v, want SyntaxError", tc, err)
+		}
+	}
+}
+
+func TestIssue12417(t *testing.T) {
+	testCases := []struct {
+		s  string
+		ok bool
+	}{
+		{`<?xml encoding="UtF-8" version="1.0"?><root/>`, true},
+		{`<?xml encoding="UTF-8" version="1.0"?><root/>`, true},
+		{`<?xml encoding="utf-8" version="1.0"?><root/>`, true},
+		{`<?xml encoding="uuu-9" version="1.0"?><root/>`, false},
+	}
+	for _, tc := range testCases {
+		d := NewDecoder(strings.NewReader(tc.s))
+		var err error
+		for {
+			_, err = d.Token()
+			if err != nil {
+				if err == io.EOF {
+					err = nil
+				}
+				break
+			}
+		}
+		if err != nil && tc.ok {
+			t.Errorf("%q: Encoding charset: expected no error, got %s", tc.s, err)
+			continue
+		}
+		if err == nil && !tc.ok {
+			t.Errorf("%q: Encoding charset: expected error, got nil", tc.s)
+		}
+	}
+}
diff --git a/src/fmt/doc.go b/src/fmt/doc.go
index ef91368..4eea48e 100644
--- a/src/fmt/doc.go
+++ b/src/fmt/doc.go
@@ -34,8 +34,8 @@
 		%b	decimalless scientific notation with exponent a power of two,
 			in the manner of strconv.FormatFloat with the 'b' format,
 			e.g. -123456p-78
-		%e	scientific notation, e.g. -1234.456e+78
-		%E	scientific notation, e.g. -1234.456E+78
+		%e	scientific notation, e.g. -1.234456e+78
+		%E	scientific notation, e.g. -1.234456E+78
 		%f	decimal point but no exponent, e.g. 123.456
 		%F	synonym for %f
 		%g	%e for large exponents, %f otherwise
@@ -138,8 +138,8 @@
 	formatting considerations apply for operands that implement
 	certain interfaces. In order of application:
 
-	1. If the operand is a reflect.Value, the concrete value it
-	holds is printed as if it was the operand.
+	1. If the operand is a reflect.Value, the operand is replaced by the
+	concrete value that it holds, and printing continues with the next rule.
 
 	2. If an operand implements the Formatter interface, it will
 	be invoked. Formatter provides fine control of formatting.
diff --git a/src/fmt/fmt_test.go b/src/fmt/fmt_test.go
index 90a4031..793f709 100644
--- a/src/fmt/fmt_test.go
+++ b/src/fmt/fmt_test.go
@@ -7,6 +7,7 @@ package fmt_test
 import (
 	"bytes"
 	. "fmt"
+	"internal/race"
 	"io"
 	"math"
 	"reflect"
@@ -982,7 +983,7 @@ func TestCountMallocs(t *testing.T) {
 		t.Skip("skipping malloc count in short mode")
 	case runtime.GOMAXPROCS(0) > 1:
 		t.Skip("skipping; GOMAXPROCS>1")
-	case raceenabled:
+	case race.Enabled:
 		t.Skip("skipping malloc count under race detector")
 	}
 	for _, mt := range mallocTest {
@@ -1188,6 +1189,11 @@ var startests = []struct {
 	{"%.*d", args(4, 42), "0042"},
 	{"%*.*d", args(8, 4, 42), "    0042"},
 	{"%0*d", args(4, 42), "0042"},
+	// Some non-int types for width. (Issue 10732).
+	{"%0*d", args(uint(4), 42), "0042"},
+	{"%0*d", args(uint64(4), 42), "0042"},
+	{"%0*d", args('\x04', 42), "0042"},
+	{"%0*d", args(uintptr(4), 42), "0042"},
 
 	// erroneous
 	{"%*d", args(nil, 42), "%!(BADWIDTH)42"},
@@ -1196,17 +1202,19 @@ var startests = []struct {
 	{"%.*d", args(nil, 42), "%!(BADPREC)42"},
 	{"%.*d", args(-1, 42), "%!(BADPREC)42"},
 	{"%.*d", args(int(1e7), 42), "%!(BADPREC)42"},
+	{"%.*d", args(uint(1e7), 42), "%!(BADPREC)42"},
+	{"%.*d", args(uint64(1<<63), 42), "%!(BADPREC)42"},   // Huge negative (-inf).
+	{"%.*d", args(uint64(1<<64-1), 42), "%!(BADPREC)42"}, // Small negative (-1).
 	{"%*d", args(5, "foo"), "%!d(string=  foo)"},
 	{"%*% %d", args(20, 5), "% 5"},
 	{"%*", args(4), "%!(NOVERB)"},
-	{"%*d", args(int32(4), 42), "%!(BADWIDTH)42"},
 }
 
 func TestWidthAndPrecision(t *testing.T) {
-	for _, tt := range startests {
+	for i, tt := range startests {
 		s := Sprintf(tt.fmt, tt.in...)
 		if s != tt.out {
-			t.Errorf("%q: got %q expected %q", tt.fmt, s, tt.out)
+			t.Errorf("#%d: %q: got %q expected %q", i, tt.fmt, s, tt.out)
 		}
 	}
 }
diff --git a/src/fmt/norace_test.go b/src/fmt/norace_test.go
deleted file mode 100644
index 1267cc3..0000000
--- a/src/fmt/norace_test.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2015 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.
-
-// +build !race
-
-package fmt_test
-
-const raceenabled = false
diff --git a/src/fmt/print.go b/src/fmt/print.go
index 8d3e97c..ebfa13e 100644
--- a/src/fmt/print.go
+++ b/src/fmt/print.go
@@ -1024,11 +1024,30 @@ BigSwitch:
 	return wasString
 }
 
-// intFromArg gets the argNumth element of a. On return, isInt reports whether the argument has type int.
+// intFromArg gets the argNumth element of a. On return, isInt reports whether the argument has integer type.
 func intFromArg(a []interface{}, argNum int) (num int, isInt bool, newArgNum int) {
 	newArgNum = argNum
 	if argNum < len(a) {
-		num, isInt = a[argNum].(int)
+		num, isInt = a[argNum].(int) // Almost always OK.
+		if !isInt {
+			// Work harder.
+			switch v := reflect.ValueOf(a[argNum]); v.Kind() {
+			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+				n := v.Int()
+				if int64(int(n)) == n {
+					num = int(n)
+					isInt = true
+				}
+			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+				n := v.Uint()
+				if int64(n) >= 0 && uint64(int(n)) == n {
+					num = int(n)
+					isInt = true
+				}
+			default:
+				// Already 0, false.
+			}
+		}
 		newArgNum = argNum + 1
 		if tooLarge(num) {
 			num = 0
diff --git a/src/fmt/race_test.go b/src/fmt/race_test.go
deleted file mode 100644
index ae3147a..0000000
--- a/src/fmt/race_test.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2015 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.
-
-// +build race
-
-package fmt_test
-
-const raceenabled = true
diff --git a/src/fmt/scan.go b/src/fmt/scan.go
index e3e0fd0..4618ed4 100644
--- a/src/fmt/scan.go
+++ b/src/fmt/scan.go
@@ -538,7 +538,7 @@ func (s *ss) okVerb(verb rune, okVerbs, typ string) bool {
 			return true
 		}
 	}
-	s.errorString("bad verb %" + string(verb) + " for " + typ)
+	s.errorString("bad verb '%" + string(verb) + "' for " + typ)
 	return false
 }
 
@@ -813,7 +813,7 @@ func (s *ss) scanComplex(verb rune, n int) complex128 {
 // convertString returns the string represented by the next input characters.
 // The format of the input is determined by the verb.
 func (s *ss) convertString(verb rune) (str string) {
-	if !s.okVerb(verb, "svqx", "string") {
+	if !s.okVerb(verb, "svqxX", "string") {
 		return ""
 	}
 	s.skipSpace(false)
@@ -821,7 +821,7 @@ func (s *ss) convertString(verb rune) (str string) {
 	switch verb {
 	case 'q':
 		str = s.quotedString()
-	case 'x':
+	case 'x', 'X':
 		str = s.hexString()
 	default:
 		str = string(s.token(true, notSpace)) // %s and %v just return the next word
@@ -1078,6 +1078,10 @@ func (s *ss) advance(format string) (i int) {
 	for i < len(format) {
 		fmtc, w := utf8.DecodeRuneInString(format[i:])
 		if fmtc == '%' {
+			// % at end of string is an error.
+			if i+w == len(format) {
+				s.errorString("missing verb: % at end of format string")
+			}
 			// %% acts like a real percent
 			nextc, _ := utf8.DecodeRuneInString(format[i+w:]) // will not match % if string is empty
 			if nextc != '%' {
@@ -1179,7 +1183,7 @@ func (s *ss) doScanf(format string, a []interface{}) (numProcessed int, err erro
 		}
 
 		if numProcessed >= len(a) { // out of operands
-			s.errorString("too few operands for format %" + format[i-w:])
+			s.errorString("too few operands for format '%" + format[i-w:] + "'")
 			break
 		}
 		arg := a[numProcessed]
diff --git a/src/fmt/scan_test.go b/src/fmt/scan_test.go
index 334c4a6..7ac74dc 100644
--- a/src/fmt/scan_test.go
+++ b/src/fmt/scan_test.go
@@ -255,12 +255,14 @@ var scanfTests = []ScanfTest{
 	// Strings
 	{"%s", "using-%s\n", &stringVal, "using-%s"},
 	{"%x", "7573696e672d2578\n", &stringVal, "using-%x"},
+	{"%X", "7573696E672D2558\n", &stringVal, "using-%X"},
 	{"%q", `"quoted\twith\\do\u0075bl\x65s"` + "\n", &stringVal, "quoted\twith\\doubles"},
 	{"%q", "`quoted with backs`\n", &stringVal, "quoted with backs"},
 
 	// Byte slices
 	{"%s", "bytes-%s\n", &bytesVal, []byte("bytes-%s")},
 	{"%x", "62797465732d2578\n", &bytesVal, []byte("bytes-%x")},
+	{"%X", "62797465732D2558\n", &bytesVal, []byte("bytes-%X")},
 	{"%q", `"bytes\rwith\vdo\u0075bl\x65s"` + "\n", &bytesVal, []byte("bytes\rwith\vdoubles")},
 	{"%q", "`bytes with backs`\n", &bytesVal, []byte("bytes with backs")},
 
@@ -291,6 +293,7 @@ var scanfTests = []ScanfTest{
 	// Interesting formats
 	{"here is\tthe value:%d", "here is   the\tvalue:118\n", &intVal, 118},
 	{"%% %%:%d", "% %:119\n", &intVal, 119},
+	{"%d%%", "42%", &intVal, 42}, // %% at end of string.
 
 	// Corner cases
 	{"%x", "FFFFFFFF\n", &uint32Val, uint32(0xFFFFFFFF)},
@@ -356,6 +359,8 @@ var multiTests = []ScanfMultiTest{
 	{"%d %d", "23 18 27", args(&i, &j, &k), args(23, 18), "too many operands"},
 	{"%c", "\u0100", args(&int8Val), nil, "overflow"},
 	{"X%d", "10X", args(&intVal), nil, "input does not match format"},
+	{"%d%", "42%", args(&intVal), args(42), "missing verb: % at end of format string"},
+	{"%d% ", "42%", args(&intVal), args(42), "too few operands for format '% '"}, // Slightly odd error, but correct.
 
 	// Bad UTF-8: should see every byte.
 	{"%c%c%c", "\xc2X\xc2", args(&r1, &r2, &r3), args(utf8.RuneError, 'X', utf8.RuneError), ""},
diff --git a/src/go/ast/import.go b/src/go/ast/import.go
index d2770d1..5c794c3 100644
--- a/src/go/ast/import.go
+++ b/src/go/ast/import.go
@@ -43,8 +43,10 @@ func SortImports(fset *token.FileSet, f *File) {
 		if len(d.Specs) > 0 {
 			lastSpec := d.Specs[len(d.Specs)-1]
 			lastLine := fset.Position(lastSpec.Pos()).Line
-			if rParenLine := fset.Position(d.Rparen).Line; rParenLine > lastLine+1 {
-				fset.File(d.Rparen).MergeLine(rParenLine - 1)
+			rParenLine := fset.Position(d.Rparen).Line
+			for rParenLine > lastLine+1 {
+				rParenLine--
+				fset.File(d.Rparen).MergeLine(rParenLine)
 			}
 		}
 	}
diff --git a/src/go/build/build.go b/src/go/build/build.go
index 496fe11..c1b70bc 100644
--- a/src/go/build/build.go
+++ b/src/go/build/build.go
@@ -110,7 +110,7 @@ func (ctxt *Context) splitPathList(s string) []string {
 	return filepath.SplitList(s)
 }
 
-// isAbsPath calls ctxt.IsAbsSPath (if not nil) or else filepath.IsAbs.
+// isAbsPath calls ctxt.IsAbsPath (if not nil) or else filepath.IsAbs.
 func (ctxt *Context) isAbsPath(path string) bool {
 	if f := ctxt.IsAbsPath; f != nil {
 		return f(path)
@@ -289,7 +289,7 @@ func defaultContext() Context {
 
 	c.GOARCH = envOr("GOARCH", runtime.GOARCH)
 	c.GOOS = envOr("GOOS", runtime.GOOS)
-	c.GOROOT = runtime.GOROOT()
+	c.GOROOT = pathpkg.Clean(runtime.GOROOT())
 	c.GOPATH = envOr("GOPATH", "")
 	c.Compiler = runtime.Compiler
 
@@ -298,7 +298,7 @@ func defaultContext() Context {
 	// in all releases >= Go 1.x. Code that requires Go 1.x or later should
 	// say "+build go1.x", and code that should only be built before Go 1.x
 	// (perhaps it is the stub to use in that case) should say "+build !go1.x".
-	c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4", "go1.5"}
+	c.ReleaseTags = []string{"go1.1", "go1.2", "go1.3", "go1.4", "go1.5", "go1.6"}
 
 	switch os.Getenv("CGO_ENABLED") {
 	case "1":
@@ -343,6 +343,21 @@ const (
 	// or finds conflicting comments in multiple source files.
 	// See golang.org/s/go14customimport for more information.
 	ImportComment
+
+	// By default, Import searches vendor directories
+	// that apply in the given source directory before searching
+	// the GOROOT and GOPATH roots.
+	// If an Import finds and returns a package using a vendor
+	// directory, the resulting ImportPath is the complete path
+	// to the package, including the path elements leading up
+	// to and including "vendor".
+	// For example, if Import("y", "x/subdir", 0) finds
+	// "x/vendor/y", the returned package's ImportPath is "x/vendor/y",
+	// not plain "y".
+	// See golang.org/s/go15vendor for more information.
+	//
+	// Setting IgnoreVendor ignores vendor directories.
+	IgnoreVendor
 )
 
 // A Package describes the Go package found in a directory.
@@ -366,6 +381,7 @@ type Package struct {
 	GoFiles        []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
 	CgoFiles       []string // .go source files that import "C"
 	IgnoredGoFiles []string // .go source files ignored for this build
+	InvalidGoFiles []string // .go source files with detected problems (parse error, wrong package name, and so on)
 	CFiles         []string // .c source files
 	CXXFiles       []string // .cc, .cpp and .cxx source files
 	MFiles         []string // .m (Objective-C) source files
@@ -474,15 +490,22 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
 	switch ctxt.Compiler {
 	case "gccgo":
 		pkgtargetroot = "pkg/gccgo_" + ctxt.GOOS + "_" + ctxt.GOARCH + suffix
-		dir, elem := pathpkg.Split(p.ImportPath)
-		pkga = pkgtargetroot + "/" + dir + "lib" + elem + ".a"
 	case "gc":
 		pkgtargetroot = "pkg/" + ctxt.GOOS + "_" + ctxt.GOARCH + suffix
-		pkga = pkgtargetroot + "/" + p.ImportPath + ".a"
 	default:
 		// Save error for end of function.
 		pkgerr = fmt.Errorf("import %q: unknown compiler %q", path, ctxt.Compiler)
 	}
+	setPkga := func() {
+		switch ctxt.Compiler {
+		case "gccgo":
+			dir, elem := pathpkg.Split(p.ImportPath)
+			pkga = pkgtargetroot + "/" + dir + "lib" + elem + ".a"
+		case "gc":
+			pkga = pkgtargetroot + "/" + p.ImportPath + ".a"
+		}
+	}
+	setPkga()
 
 	binaryOnly := false
 	if IsLocalImport(path) {
@@ -543,9 +566,50 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
 
 		// tried records the location of unsuccessful package lookups
 		var tried struct {
+			vendor []string
 			goroot string
 			gopath []string
 		}
+		gopath := ctxt.gopath()
+
+		// Vendor directories get first chance to satisfy import.
+		if mode&IgnoreVendor == 0 && srcDir != "" {
+			searchVendor := func(root string, isGoroot bool) bool {
+				sub, ok := ctxt.hasSubdir(root, srcDir)
+				if !ok || !strings.HasPrefix(sub, "src/") || strings.Contains(sub, "/testdata/") {
+					return false
+				}
+				for {
+					vendor := ctxt.joinPath(root, sub, "vendor")
+					if ctxt.isDir(vendor) {
+						dir := ctxt.joinPath(vendor, path)
+						if ctxt.isDir(dir) && hasGoFiles(ctxt, dir) {
+							p.Dir = dir
+							p.ImportPath = strings.TrimPrefix(pathpkg.Join(sub, "vendor", path), "src/")
+							p.Goroot = isGoroot
+							p.Root = root
+							setPkga() // p.ImportPath changed
+							return true
+						}
+						tried.vendor = append(tried.vendor, dir)
+					}
+					i := strings.LastIndex(sub, "/")
+					if i < 0 {
+						break
+					}
+					sub = sub[:i]
+				}
+				return false
+			}
+			if searchVendor(ctxt.GOROOT, true) {
+				goto Found
+			}
+			for _, root := range gopath {
+				if searchVendor(root, false) {
+					goto Found
+				}
+			}
+		}
 
 		// Determine directory from import path.
 		if ctxt.GOROOT != "" {
@@ -560,7 +624,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
 			}
 			tried.goroot = dir
 		}
-		for _, root := range ctxt.gopath() {
+		for _, root := range gopath {
 			dir := ctxt.joinPath(root, "src", path)
 			isDir := ctxt.isDir(dir)
 			binaryOnly = !isDir && mode&AllowBinary != 0 && pkga != "" && ctxt.isFile(ctxt.joinPath(root, pkga))
@@ -574,20 +638,22 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa
 
 		// package was not found
 		var paths []string
+		format := "\t%s (vendor tree)"
+		for _, dir := range tried.vendor {
+			paths = append(paths, fmt.Sprintf(format, dir))
+			format = "\t%s"
+		}
 		if tried.goroot != "" {
 			paths = append(paths, fmt.Sprintf("\t%s (from $GOROOT)", tried.goroot))
 		} else {
 			paths = append(paths, "\t($GOROOT not set)")
 		}
-		var i int
-		var format = "\t%s (from $GOPATH)"
-		for ; i < len(tried.gopath); i++ {
-			if i > 0 {
-				format = "\t%s"
-			}
-			paths = append(paths, fmt.Sprintf(format, tried.gopath[i]))
+		format = "\t%s (from $GOPATH)"
+		for _, dir := range tried.gopath {
+			paths = append(paths, fmt.Sprintf(format, dir))
+			format = "\t%s"
 		}
-		if i == 0 {
+		if len(tried.gopath) == 0 {
 			paths = append(paths, "\t($GOPATH not set)")
 		}
 		return p, fmt.Errorf("cannot find package %q in any of:\n%s", path, strings.Join(paths, "\n"))
@@ -616,6 +682,7 @@ Found:
 		return p, err
 	}
 
+	var badGoError error
 	var Sfiles []string // files with ".S" (capital S)
 	var firstFile, firstCommentFile string
 	imported := make(map[string][]token.Position)
@@ -631,9 +698,17 @@ Found:
 		name := d.Name()
 		ext := nameExt(name)
 
+		badFile := func(err error) {
+			if badGoError == nil {
+				badGoError = err
+			}
+			p.InvalidGoFiles = append(p.InvalidGoFiles, name)
+		}
+
 		match, data, filename, err := ctxt.matchFile(p.Dir, name, true, allTags)
 		if err != nil {
-			return p, err
+			badFile(err)
+			continue
 		}
 		if !match {
 			if ext == ".go" {
@@ -678,7 +753,8 @@ Found:
 
 		pf, err := parser.ParseFile(fset, filename, data, parser.ImportsOnly|parser.ParseComments)
 		if err != nil {
-			return p, err
+			badFile(err)
+			continue
 		}
 
 		pkg := pf.Name.Name
@@ -698,11 +774,12 @@ Found:
 			p.Name = pkg
 			firstFile = name
 		} else if pkg != p.Name {
-			return p, &MultiplePackageError{
+			badFile(&MultiplePackageError{
 				Dir:      p.Dir,
 				Packages: []string{p.Name, pkg},
 				Files:    []string{firstFile, name},
-			}
+			})
+			p.InvalidGoFiles = append(p.InvalidGoFiles, name)
 		}
 		if pf.Doc != nil && p.Doc == "" {
 			p.Doc = doc.Synopsis(pf.Doc.Text())
@@ -713,13 +790,12 @@ Found:
 			if line != 0 {
 				com, err := strconv.Unquote(qcom)
 				if err != nil {
-					return p, fmt.Errorf("%s:%d: cannot parse import comment", filename, line)
-				}
-				if p.ImportComment == "" {
+					badFile(fmt.Errorf("%s:%d: cannot parse import comment", filename, line))
+				} else if p.ImportComment == "" {
 					p.ImportComment = com
 					firstCommentFile = name
 				} else if p.ImportComment != com {
-					return p, fmt.Errorf("found import comments %q (%s) and %q (%s) in %s", p.ImportComment, firstCommentFile, com, name, p.Dir)
+					badFile(fmt.Errorf("found import comments %q (%s) and %q (%s) in %s", p.ImportComment, firstCommentFile, com, name, p.Dir))
 				}
 			}
 		}
@@ -750,18 +826,19 @@ Found:
 				}
 				if path == "C" {
 					if isTest {
-						return p, fmt.Errorf("use of cgo in test %s not supported", filename)
-					}
-					cg := spec.Doc
-					if cg == nil && len(d.Specs) == 1 {
-						cg = d.Doc
-					}
-					if cg != nil {
-						if err := ctxt.saveCgo(filename, p, cg); err != nil {
-							return p, err
+						badFile(fmt.Errorf("use of cgo in test %s not supported", filename))
+					} else {
+						cg := spec.Doc
+						if cg == nil && len(d.Specs) == 1 {
+							cg = d.Doc
+						}
+						if cg != nil {
+							if err := ctxt.saveCgo(filename, p, cg); err != nil {
+								badFile(err)
+							}
 						}
+						isCgo = true
 					}
-					isCgo = true
 				}
 			}
 		}
@@ -780,6 +857,9 @@ Found:
 			p.GoFiles = append(p.GoFiles, name)
 		}
 	}
+	if badGoError != nil {
+		return p, badGoError
+	}
 	if len(p.GoFiles)+len(p.CgoFiles)+len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 {
 		return p, &NoGoError{p.Dir}
 	}
@@ -804,6 +884,20 @@ Found:
 	return p, pkgerr
 }
 
+// hasGoFiles reports whether dir contains any files with names ending in .go.
+// For a vendor check we must exclude directories that contain no .go files.
+// Otherwise it is not possible to vendor just a/b/c and still import the
+// non-vendored a/b. See golang.org/issue/13832.
+func hasGoFiles(ctxt *Context, dir string) bool {
+	ents, _ := ctxt.readDir(dir)
+	for _, ent := range ents {
+		if !ent.IsDir() && strings.HasSuffix(ent.Name(), ".go") {
+			return true
+		}
+	}
+	return false
+}
+
 func findImportComment(data []byte) (s string, line int) {
 	// expect keyword package
 	word, data := parseWord(data)
@@ -1127,9 +1221,9 @@ func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup)
 		if err != nil {
 			return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig)
 		}
+		var ok bool
 		for i, arg := range args {
-			arg = expandSrcDir(arg, di.Dir)
-			if !safeCgoName(arg) {
+			if arg, ok = expandSrcDir(arg, di.Dir); !ok {
 				return fmt.Errorf("%s: malformed #cgo argument: %s", filename, arg)
 			}
 			args[i] = arg
@@ -1153,25 +1247,47 @@ func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup)
 	return nil
 }
 
-func expandSrcDir(str string, srcdir string) string {
+// expandSrcDir expands any occurrence of ${SRCDIR}, making sure
+// the result is safe for the shell.
+func expandSrcDir(str string, srcdir string) (string, bool) {
 	// "\" delimited paths cause safeCgoName to fail
 	// so convert native paths with a different delimeter
-	// to "/" before starting (eg: on windows)
+	// to "/" before starting (eg: on windows).
 	srcdir = filepath.ToSlash(srcdir)
-	return strings.Replace(str, "${SRCDIR}", srcdir, -1)
+
+	// Spaces are tolerated in ${SRCDIR}, but not anywhere else.
+	chunks := strings.Split(str, "${SRCDIR}")
+	if len(chunks) < 2 {
+		return str, safeCgoName(str, false)
+	}
+	ok := true
+	for _, chunk := range chunks {
+		ok = ok && (chunk == "" || safeCgoName(chunk, false))
+	}
+	ok = ok && (srcdir == "" || safeCgoName(srcdir, true))
+	res := strings.Join(chunks, srcdir)
+	return res, ok && res != ""
 }
 
 // NOTE: $ is not safe for the shell, but it is allowed here because of linker options like -Wl,$ORIGIN.
 // We never pass these arguments to a shell (just to programs we construct argv for), so this should be okay.
 // See golang.org/issue/6038.
-var safeBytes = []byte("+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz:$")
+// The @ is for OS X. See golang.org/issue/13720.
+const safeString = "+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz:$@"
+const safeSpaces = " "
 
-func safeCgoName(s string) bool {
+var safeBytes = []byte(safeSpaces + safeString)
+
+func safeCgoName(s string, spaces bool) bool {
 	if s == "" {
 		return false
 	}
+	safe := safeBytes
+	if !spaces {
+		safe = safe[len(safeSpaces):]
+	}
 	for i := 0; i < len(s); i++ {
-		if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 {
+		if c := s[i]; c < 0x80 && bytes.IndexByte(safe, c) < 0 {
 			return false
 		}
 	}
diff --git a/src/go/build/build_test.go b/src/go/build/build_test.go
index 92c3fe3..7312af0 100644
--- a/src/go/build/build_test.go
+++ b/src/go/build/build_test.go
@@ -5,6 +5,7 @@
 package build
 
 import (
+	"internal/testenv"
 	"io"
 	"os"
 	"path/filepath"
@@ -267,7 +268,7 @@ var expandSrcDirTests = []struct {
 
 func TestExpandSrcDir(t *testing.T) {
 	for _, test := range expandSrcDirTests {
-		output := expandSrcDir(test.input, expandSrcDirPath)
+		output, _ := expandSrcDir(test.input, expandSrcDirPath)
 		if output != test.expected {
 			t.Errorf("%q expands to %q with SRCDIR=%q when %q is expected", test.input, output, expandSrcDirPath, test.expected)
 		} else {
@@ -275,3 +276,73 @@ func TestExpandSrcDir(t *testing.T) {
 		}
 	}
 }
+
+func TestShellSafety(t *testing.T) {
+	tests := []struct {
+		input, srcdir, expected string
+		result                  bool
+	}{
+		{"-I${SRCDIR}/../include", "/projects/src/issue 11868", "-I/projects/src/issue 11868/../include", true},
+		{"-X${SRCDIR}/1,${SRCDIR}/2", "/projects/src/issue 11868", "-X/projects/src/issue 11868/1,/projects/src/issue 11868/2", true},
+		{"-I/tmp -I/tmp", "/tmp2", "-I/tmp -I/tmp", false},
+		{"-I/tmp", "/tmp/[0]", "-I/tmp", true},
+		{"-I${SRCDIR}/dir", "/tmp/[0]", "-I/tmp/[0]/dir", false},
+	}
+	for _, test := range tests {
+		output, ok := expandSrcDir(test.input, test.srcdir)
+		if ok != test.result {
+			t.Errorf("Expected %t while %q expands to %q with SRCDIR=%q; got %t", test.result, test.input, output, test.srcdir, ok)
+		}
+		if output != test.expected {
+			t.Errorf("Expected %q while %q expands with SRCDIR=%q; got %q", test.expected, test.input, test.srcdir, output)
+		}
+	}
+}
+
+func TestImportVendor(t *testing.T) {
+	t.Skip("skipping; hpack has moved to internal for now; golang.org/issue/14047")
+	testenv.MustHaveGoBuild(t) // really must just have source
+	ctxt := Default
+	ctxt.GOPATH = ""
+	p, err := ctxt.Import("golang.org/x/net/http2/hpack", filepath.Join(ctxt.GOROOT, "src/net/http"), 0)
+	if err != nil {
+		t.Fatalf("cannot find vendored golang.org/x/net/http2/hpack from net/http directory: %v", err)
+	}
+	want := "vendor/golang.org/x/net/http2/hpack"
+	if p.ImportPath != want {
+		t.Fatalf("Import succeeded but found %q, want %q", p.ImportPath, want)
+	}
+}
+
+func TestImportVendorFailure(t *testing.T) {
+	testenv.MustHaveGoBuild(t) // really must just have source
+	ctxt := Default
+	ctxt.GOPATH = ""
+	p, err := ctxt.Import("x.com/y/z", filepath.Join(ctxt.GOROOT, "src/net/http"), 0)
+	if err == nil {
+		t.Fatalf("found made-up package x.com/y/z in %s", p.Dir)
+	}
+
+	e := err.Error()
+	if !strings.Contains(e, " (vendor tree)") {
+		t.Fatalf("error on failed import does not mention GOROOT/src/vendor directory:\n%s", e)
+	}
+}
+
+func TestImportVendorParentFailure(t *testing.T) {
+	testenv.MustHaveGoBuild(t) // really must just have source
+	ctxt := Default
+	ctxt.GOPATH = ""
+	// This import should fail because the vendor/golang.org/x/net/http2 directory has no source code.
+	p, err := ctxt.Import("golang.org/x/net/http2", filepath.Join(ctxt.GOROOT, "src/net/http"), 0)
+	if err == nil {
+		t.Fatalf("found empty parent in %s", p.Dir)
+	}
+	if p != nil && p.Dir != "" {
+		t.Fatalf("decided to use %s", p.Dir)
+	}
+	e := err.Error()
+	if !strings.Contains(e, " (vendor tree)") {
+		t.Fatalf("error on failed import does not mention GOROOT/src/vendor directory:\n%s", e)
+	}
+}
diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
index 7cea949..376931e 100644
--- a/src/go/build/deps_test.go
+++ b/src/go/build/deps_test.go
@@ -34,17 +34,21 @@ import (
 //
 var pkgDeps = map[string][]string{
 	// L0 is the lowest level, core, nearly unavoidable packages.
-	"errors":      {},
-	"io":          {"errors", "sync"},
-	"runtime":     {"unsafe"},
-	"sync":        {"runtime", "sync/atomic", "unsafe"},
-	"sync/atomic": {"unsafe"},
-	"unsafe":      {},
+	"errors":                  {},
+	"io":                      {"errors", "sync"},
+	"runtime":                 {"unsafe", "runtime/internal/atomic", "runtime/internal/sys"},
+	"runtime/internal/sys":    {},
+	"runtime/internal/atomic": {"unsafe", "runtime/internal/sys"},
+	"internal/race":           {"runtime", "unsafe"},
+	"sync":                    {"internal/race", "runtime", "sync/atomic", "unsafe"},
+	"sync/atomic":             {"unsafe"},
+	"unsafe":                  {},
 
 	"L0": {
 		"errors",
 		"io",
 		"runtime",
+		"runtime/internal/atomic",
 		"sync",
 		"sync/atomic",
 		"unsafe",
@@ -128,7 +132,7 @@ var pkgDeps = map[string][]string{
 	// End of linear dependency definitions.
 
 	// Operating system access.
-	"syscall":                           {"L0", "unicode/utf16"},
+	"syscall":                           {"L0", "internal/race", "unicode/utf16"},
 	"internal/syscall/unix":             {"L0", "syscall"},
 	"internal/syscall/windows":          {"L0", "syscall"},
 	"internal/syscall/windows/registry": {"L0", "syscall", "unicode/utf16"},
@@ -161,7 +165,7 @@ var pkgDeps = map[string][]string{
 	"runtime/trace":  {"L0"},
 	"text/tabwriter": {"L2"},
 
-	"testing":          {"L2", "flag", "fmt", "os", "runtime/pprof", "runtime/trace", "time"},
+	"testing":          {"L2", "flag", "fmt", "os", "runtime/debug", "runtime/pprof", "runtime/trace", "time"},
 	"testing/iotest":   {"L2", "log"},
 	"testing/quick":    {"L2", "flag", "fmt", "reflect"},
 	"internal/testenv": {"L2", "os", "testing"},
@@ -214,7 +218,7 @@ var pkgDeps = map[string][]string{
 	"database/sql":             {"L4", "container/list", "database/sql/driver"},
 	"database/sql/driver":      {"L4", "time"},
 	"debug/dwarf":              {"L4"},
-	"debug/elf":                {"L4", "OS", "debug/dwarf"},
+	"debug/elf":                {"L4", "OS", "debug/dwarf", "compress/zlib"},
 	"debug/gosym":              {"L4"},
 	"debug/macho":              {"L4", "OS", "debug/dwarf"},
 	"debug/pe":                 {"L4", "OS", "debug/dwarf"},
@@ -256,6 +260,8 @@ var pkgDeps = map[string][]string{
 	},
 
 	// Cgo.
+	// If you add a dependency on CGO, you must add the package to
+	// cgoPackages in cmd/dist/test.go.
 	"runtime/cgo": {"L0", "C"},
 	"CGO":         {"C", "runtime/cgo"},
 
@@ -263,16 +269,17 @@ var pkgDeps = map[string][]string{
 	// that shows up in programs that use cgo.
 	"C": {},
 
-	// Race detector uses cgo.
+	// Race detector/MSan uses cgo.
 	"runtime/race": {"C"},
+	"runtime/msan": {"C"},
 
 	// Plan 9 alone needs io/ioutil and os.
 	"os/user": {"L4", "CGO", "io/ioutil", "os", "syscall"},
 
 	// Basic networking.
 	// Because net must be used by any package that wants to
-	// do networking portably, it must have a small dependency set: just L1+basic os.
-	"net": {"L1", "CGO", "os", "syscall", "time", "internal/syscall/windows", "internal/singleflight"},
+	// do networking portably, it must have a small dependency set: just L0+basic os.
+	"net": {"L0", "CGO", "math/rand", "os", "sort", "syscall", "time", "internal/syscall/windows", "internal/singleflight", "internal/race"},
 
 	// NET enables use of basic network-related packages.
 	"NET": {
@@ -333,7 +340,7 @@ var pkgDeps = map[string][]string{
 
 	// SSL/TLS.
 	"crypto/tls": {
-		"L4", "CRYPTO-MATH", "CGO", "OS",
+		"L4", "CRYPTO-MATH", "OS",
 		"container/list", "crypto/x509", "encoding/pem", "net", "syscall",
 	},
 	"crypto/x509": {
@@ -351,6 +358,7 @@ var pkgDeps = map[string][]string{
 		"L4", "NET", "OS",
 		"compress/gzip", "crypto/tls", "mime/multipart", "runtime/debug",
 		"net/http/internal",
+		"internal/golang.org/x/net/http2/hpack",
 	},
 	"net/http/internal": {"L4"},
 
@@ -359,7 +367,7 @@ var pkgDeps = map[string][]string{
 	"net/http/cgi":       {"L4", "NET", "OS", "crypto/tls", "net/http", "regexp"},
 	"net/http/cookiejar": {"L4", "NET", "net/http"},
 	"net/http/fcgi":      {"L4", "NET", "OS", "net/http", "net/http/cgi"},
-	"net/http/httptest":  {"L4", "NET", "OS", "crypto/tls", "flag", "net/http"},
+	"net/http/httptest":  {"L4", "NET", "OS", "crypto/tls", "flag", "net/http", "net/http/internal"},
 	"net/http/httputil":  {"L4", "NET", "OS", "net/http", "net/http/internal"},
 	"net/http/pprof":     {"L4", "OS", "html/template", "net/http", "runtime/pprof", "runtime/trace"},
 	"net/rpc":            {"L4", "NET", "encoding/gob", "html/template", "net/http"},
@@ -454,26 +462,23 @@ func TestDependencies(t *testing.T) {
 	}
 	sort.Strings(all)
 
-	test := func(mustImport bool) {
-		for _, pkg := range all {
-			imports, err := findImports(pkg)
-			if err != nil {
-				t.Error(err)
-				continue
-			}
-			ok := allowed(pkg)
-			var bad []string
-			for _, imp := range imports {
-				if !ok[imp] {
-					bad = append(bad, imp)
-				}
-			}
-			if bad != nil {
-				t.Errorf("unexpected dependency: %s imports %v", pkg, bad)
+	for _, pkg := range all {
+		imports, err := findImports(pkg)
+		if err != nil {
+			t.Error(err)
+			continue
+		}
+		ok := allowed(pkg)
+		var bad []string
+		for _, imp := range imports {
+			if !ok[imp] {
+				bad = append(bad, imp)
 			}
 		}
+		if bad != nil {
+			t.Errorf("unexpected dependency: %s imports %v", pkg, bad)
+		}
 	}
-	test(true)
 }
 
 var buildIgnore = []byte("\n// +build ignore")
diff --git a/src/go/build/doc.go b/src/go/build/doc.go
index 233f8b9..d436d28 100644
--- a/src/go/build/doc.go
+++ b/src/go/build/doc.go
@@ -102,6 +102,7 @@
 //	- "go1.3", from Go version 1.3 onward
 //	- "go1.4", from Go version 1.4 onward
 //	- "go1.5", from Go version 1.5 onward
+//	- "go1.6", from Go version 1.6 onward
 //	- any additional words listed in ctxt.BuildTags
 //
 // If a file's name, after stripping the extension and a possible _test suffix,
diff --git a/src/go/constant/go13.go b/src/go/constant/go13.go
deleted file mode 100644
index a4a838a..0000000
--- a/src/go/constant/go13.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// 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.
-
-// +build !go1.4
-
-package constant
-
-import (
-	"math"
-	"math/big"
-)
-
-func ratToFloat32(x *big.Rat) (float32, bool) {
-	// Before 1.4, there's no Rat.Float32.
-	// Emulate it, albeit at the cost of
-	// imprecision in corner cases.
-	x64, exact := x.Float64()
-	x32 := float32(x64)
-	if math.IsInf(float64(x32), 0) {
-		exact = false
-	}
-	return x32, exact
-}
diff --git a/src/go/constant/go14.go b/src/go/constant/go14.go
deleted file mode 100644
index 2ab6da0..0000000
--- a/src/go/constant/go14.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// 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.
-
-// +build go1.4
-
-package constant
-
-import "math/big"
-
-func ratToFloat32(x *big.Rat) (float32, bool) {
-	return x.Float32()
-}
diff --git a/src/go/constant/value.go b/src/go/constant/value.go
index 79a80af..310814d 100644
--- a/src/go/constant/value.go
+++ b/src/go/constant/value.go
@@ -3,8 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // Package constant implements Values representing untyped
-// Go constants and the corresponding operations. Values
-// and operations may have arbitrary or unlimited precision.
+// Go constants and their corresponding operations.
 //
 // A special Unknown value may be used when a value
 // is unknown due to an error. Operations on unknown
@@ -16,16 +15,15 @@ package constant // import "go/constant"
 import (
 	"fmt"
 	"go/token"
+	"math"
 	"math/big"
 	"strconv"
+	"unicode/utf8"
 )
 
 // Kind specifies the kind of value represented by a Value.
 type Kind int
 
-// Implementation note: Kinds must be enumerated in
-// order of increasing "complexity" (used by match).
-
 const (
 	// unknown values
 	Unknown Kind = iota
@@ -40,15 +38,20 @@ const (
 	Complex
 )
 
-// A Value represents a mathematically exact value of a given Kind.
+// A Value represents the value of a Go constant.
 type Value interface {
-	// Kind returns the value kind; it is always the smallest
-	// kind in which the value can be represented exactly.
+	// Kind returns the value kind.
 	Kind() Kind
 
-	// String returns a human-readable form of the value.
+	// String returns a short, human-readable form of the value.
+	// For numeric values, the result may be an approximation;
+	// for String values the result may be a shortened string.
+	// Use ExactString for a string representing a value exactly.
 	String() string
 
+	// ExactString returns an exact, printable form of the value.
+	ExactString() string
+
 	// Prevent external implementations.
 	implementsValue()
 }
@@ -56,14 +59,19 @@ type Value interface {
 // ----------------------------------------------------------------------------
 // Implementations
 
+// Maximum supported mantissa precision.
+// The spec requires at least 256 bits; typical implementations use 512 bits.
+const prec = 512
+
 type (
 	unknownVal struct{}
 	boolVal    bool
 	stringVal  string
-	int64Val   int64
-	intVal     struct{ val *big.Int }
-	floatVal   struct{ val *big.Rat }
-	complexVal struct{ re, im *big.Rat }
+	int64Val   int64                    // Int values representable as an int64
+	intVal     struct{ val *big.Int }   // Int values not representable as an int64
+	ratVal     struct{ val *big.Rat }   // Float values representable as a fraction
+	floatVal   struct{ val *big.Float } // Float values not representable as a fraction
+	complexVal struct{ re, im Value }
 )
 
 func (unknownVal) Kind() Kind { return Unknown }
@@ -71,52 +79,197 @@ func (boolVal) Kind() Kind    { return Bool }
 func (stringVal) Kind() Kind  { return String }
 func (int64Val) Kind() Kind   { return Int }
 func (intVal) Kind() Kind     { return Int }
+func (ratVal) Kind() Kind     { return Float }
 func (floatVal) Kind() Kind   { return Float }
 func (complexVal) Kind() Kind { return Complex }
 
-func (unknownVal) String() string   { return "unknown" }
-func (x boolVal) String() string    { return fmt.Sprintf("%v", bool(x)) }
-func (x stringVal) String() string  { return strconv.Quote(string(x)) }
-func (x int64Val) String() string   { return strconv.FormatInt(int64(x), 10) }
-func (x intVal) String() string     { return x.val.String() }
-func (x floatVal) String() string   { return x.val.String() }
+func (unknownVal) String() string { return "unknown" }
+func (x boolVal) String() string  { return strconv.FormatBool(bool(x)) }
+
+// String returns a possibly shortened quoted form of the String value.
+func (x stringVal) String() string {
+	const maxLen = 72 // a reasonable length
+	s := strconv.Quote(string(x))
+	if utf8.RuneCountInString(s) > maxLen {
+		// The string without the enclosing quotes is greater than maxLen-2 runes
+		// long. Remove the last 3 runes (including the closing '"') by keeping
+		// only the first maxLen-3 runes; then add "...".
+		i := 0
+		for n := 0; n < maxLen-3; n++ {
+			_, size := utf8.DecodeRuneInString(s[i:])
+			i += size
+		}
+		s = s[:i] + "..."
+	}
+	return s
+}
+
+func (x int64Val) String() string { return strconv.FormatInt(int64(x), 10) }
+func (x intVal) String() string   { return x.val.String() }
+func (x ratVal) String() string   { return rtof(x).String() }
+
+// String returns returns a decimal approximation of the Float value.
+func (x floatVal) String() string {
+	f := x.val
+
+	// Don't try to convert infinities (will not terminate).
+	if f.IsInf() {
+		return f.String()
+	}
+
+	// Use exact fmt formatting if in float64 range (common case):
+	// proceed if f doesn't underflow to 0 or overflow to inf.
+	if x, _ := f.Float64(); f.Sign() == 0 == (x == 0) && !math.IsInf(x, 0) {
+		return fmt.Sprintf("%.6g", x)
+	}
+
+	// Out of float64 range. Do approximate manual to decimal
+	// conversion to avoid precise but possibly slow Float
+	// formatting.
+	// f = mant * 2**exp
+	var mant big.Float
+	exp := f.MantExp(&mant) // 0.5 <= |mant| < 1.0
+
+	// approximate float64 mantissa m and decimal exponent d
+	// f ~ m * 10**d
+	m, _ := mant.Float64()                     // 0.5 <= |m| < 1.0
+	d := float64(exp) * (math.Ln2 / math.Ln10) // log_10(2)
+
+	// adjust m for truncated (integer) decimal exponent e
+	e := int64(d)
+	m *= math.Pow(10, d-float64(e))
+
+	// ensure 1 <= |m| < 10
+	switch am := math.Abs(m); {
+	case am < 1-0.5e-6:
+		// The %.6g format below rounds m to 5 digits after the
+		// decimal point. Make sure that m*10 < 10 even after
+		// rounding up: m*10 + 0.5e-5 < 10 => m < 1 - 0.5e6.
+		m *= 10
+		e--
+	case am >= 10:
+		m /= 10
+		e++
+	}
+
+	return fmt.Sprintf("%.6ge%+d", m, e)
+}
+
 func (x complexVal) String() string { return fmt.Sprintf("(%s + %si)", x.re, x.im) }
 
+func (x unknownVal) ExactString() string { return x.String() }
+func (x boolVal) ExactString() string    { return x.String() }
+func (x stringVal) ExactString() string  { return strconv.Quote(string(x)) }
+func (x int64Val) ExactString() string   { return x.String() }
+func (x intVal) ExactString() string     { return x.String() }
+
+func (x ratVal) ExactString() string {
+	r := x.val
+	if r.IsInt() {
+		return r.Num().String()
+	}
+	return r.String()
+}
+
+func (x floatVal) ExactString() string { return x.val.Text('p', 0) }
+
+func (x complexVal) ExactString() string {
+	return fmt.Sprintf("(%s + %si)", x.re.ExactString(), x.im.ExactString())
+}
+
 func (unknownVal) implementsValue() {}
 func (boolVal) implementsValue()    {}
 func (stringVal) implementsValue()  {}
 func (int64Val) implementsValue()   {}
+func (ratVal) implementsValue()     {}
 func (intVal) implementsValue()     {}
 func (floatVal) implementsValue()   {}
 func (complexVal) implementsValue() {}
 
-// int64 bounds
+func newInt() *big.Int     { return new(big.Int) }
+func newRat() *big.Rat     { return new(big.Rat) }
+func newFloat() *big.Float { return new(big.Float).SetPrec(prec) }
+
+func i64toi(x int64Val) intVal   { return intVal{newInt().SetInt64(int64(x))} }
+func i64tor(x int64Val) ratVal   { return ratVal{newRat().SetInt64(int64(x))} }
+func i64tof(x int64Val) floatVal { return floatVal{newFloat().SetInt64(int64(x))} }
+func itor(x intVal) ratVal       { return ratVal{newRat().SetInt(x.val)} }
+func itof(x intVal) floatVal     { return floatVal{newFloat().SetInt(x.val)} }
+
+func rtof(x ratVal) floatVal {
+	a := newFloat().SetInt(x.val.Num())
+	b := newFloat().SetInt(x.val.Denom())
+	return floatVal{a.Quo(a, b)}
+}
+
+func vtoc(x Value) complexVal { return complexVal{x, int64Val(0)} }
+
 var (
 	minInt64 = big.NewInt(-1 << 63)
 	maxInt64 = big.NewInt(1<<63 - 1)
 )
 
-func normInt(x *big.Int) Value {
+func makeInt(x *big.Int) Value {
 	if minInt64.Cmp(x) <= 0 && x.Cmp(maxInt64) <= 0 {
 		return int64Val(x.Int64())
 	}
 	return intVal{x}
 }
 
-func normFloat(x *big.Rat) Value {
-	if x.IsInt() {
-		return normInt(x.Num())
+// Permit fractions with component sizes up to maxExp
+// before switching to using floating-point numbers.
+const maxExp = 4 << 10
+
+func makeRat(x *big.Rat) Value {
+	a := x.Num()
+	b := x.Denom()
+	if a.BitLen() < maxExp && b.BitLen() < maxExp {
+		// ok to remain fraction
+		return ratVal{x}
 	}
-	return floatVal{x}
+	// components too large => switch to float
+	fa := newFloat().SetInt(a)
+	fb := newFloat().SetInt(b)
+	return floatVal{fa.Quo(fa, fb)}
 }
 
-func normComplex(re, im *big.Rat) Value {
-	if im.Sign() == 0 {
-		return normFloat(re)
+var floatVal0 = floatVal{newFloat()}
+
+func makeFloat(x *big.Float) Value {
+	// convert -0
+	if x.Sign() == 0 {
+		return floatVal0
 	}
+	return floatVal{x}
+}
+
+func makeComplex(re, im Value) Value {
 	return complexVal{re, im}
 }
 
+func makeFloatFromLiteral(lit string) Value {
+	if f, ok := newFloat().SetString(lit); ok {
+		if smallRat(f) {
+			// ok to use rationals
+			r, _ := newRat().SetString(lit)
+			return ratVal{r}
+		}
+		// otherwise use floats
+		return makeFloat(f)
+	}
+	return nil
+}
+
+// smallRat reports whether x would lead to "reasonably"-sized fraction
+// if converted to a *big.Rat.
+func smallRat(x *big.Float) bool {
+	if !x.IsInf() {
+		e := x.MantExp(nil)
+		return -maxExp < e && e < maxExp
+	}
+	return false
+}
+
 // ----------------------------------------------------------------------------
 // Factories
 
@@ -133,62 +286,74 @@ func MakeString(s string) Value { return stringVal(s) }
 func MakeInt64(x int64) Value { return int64Val(x) }
 
 // MakeUint64 returns the Int value for x.
-func MakeUint64(x uint64) Value { return normInt(new(big.Int).SetUint64(x)) }
+func MakeUint64(x uint64) Value {
+	if x < 1<<63 {
+		return int64Val(int64(x))
+	}
+	return intVal{newInt().SetUint64(x)}
+}
 
-// MakeFloat64 returns the numeric value for x.
-// If x is not finite, the result is unknown.
+// MakeFloat64 returns the Float value for x.
+// If x is not finite, the result is an Unknown.
 func MakeFloat64(x float64) Value {
-	if f := new(big.Rat).SetFloat64(x); f != nil {
-		return normFloat(f)
+	if math.IsInf(x, 0) || math.IsNaN(x) {
+		return unknownVal{}
 	}
-	return unknownVal{}
+	// convert -0 to 0
+	if x == 0 {
+		return int64Val(0)
+	}
+	return ratVal{newRat().SetFloat64(x)}
 }
 
 // MakeFromLiteral returns the corresponding integer, floating-point,
-// imaginary, character, or string value for a Go literal string.
-// If prec > 0, prec specifies an upper limit for the precision of
-// a numeric value. If the literal string is invalid, the result is
-// nil.
-// BUG(gri) Only prec == 0 is supported at the moment.
-func MakeFromLiteral(lit string, tok token.Token, prec uint) Value {
-	if prec != 0 {
-		panic("limited precision not supported")
+// imaginary, character, or string value for a Go literal string. The
+// tok value must be one of token.INT, token.FLOAT, toke.IMAG, token.
+// CHAR, or token.STRING. The final argument must be zero.
+// If the literal string syntax is invalid, the result is an Unknown.
+func MakeFromLiteral(lit string, tok token.Token, zero uint) Value {
+	if zero != 0 {
+		panic("MakeFromLiteral called with non-zero last argument")
 	}
+
 	switch tok {
 	case token.INT:
 		if x, err := strconv.ParseInt(lit, 0, 64); err == nil {
 			return int64Val(x)
 		}
-		if x, ok := new(big.Int).SetString(lit, 0); ok {
+		if x, ok := newInt().SetString(lit, 0); ok {
 			return intVal{x}
 		}
 
 	case token.FLOAT:
-		if x, ok := new(big.Rat).SetString(lit); ok {
-			return normFloat(x)
+		if x := makeFloatFromLiteral(lit); x != nil {
+			return x
 		}
 
 	case token.IMAG:
 		if n := len(lit); n > 0 && lit[n-1] == 'i' {
-			if im, ok := new(big.Rat).SetString(lit[0 : n-1]); ok {
-				return normComplex(big.NewRat(0, 1), im)
+			if im := makeFloatFromLiteral(lit[:n-1]); im != nil {
+				return makeComplex(int64Val(0), im)
 			}
 		}
 
 	case token.CHAR:
 		if n := len(lit); n >= 2 {
 			if code, _, _, err := strconv.UnquoteChar(lit[1:n-1], '\''); err == nil {
-				return int64Val(code)
+				return MakeInt64(int64(code))
 			}
 		}
 
 	case token.STRING:
 		if s, err := strconv.Unquote(lit); err == nil {
-			return stringVal(s)
+			return MakeString(s)
 		}
+
+	default:
+		panic(fmt.Sprintf("%v is not a valid token", tok))
 	}
 
-	return nil
+	return unknownVal{}
 }
 
 // ----------------------------------------------------------------------------
@@ -205,8 +370,9 @@ func BoolVal(x Value) bool {
 		return bool(x)
 	case unknownVal:
 		return false
+	default:
+		panic(fmt.Sprintf("%v not a Bool", x))
 	}
-	panic(fmt.Sprintf("%v not a Bool", x))
 }
 
 // StringVal returns the Go string value of x, which must be a String or an Unknown.
@@ -217,8 +383,9 @@ func StringVal(x Value) string {
 		return string(x)
 	case unknownVal:
 		return ""
+	default:
+		panic(fmt.Sprintf("%v not a String", x))
 	}
-	panic(fmt.Sprintf("%v not a String", x))
 }
 
 // Int64Val returns the Go int64 value of x and whether the result is exact;
@@ -229,11 +396,12 @@ func Int64Val(x Value) (int64, bool) {
 	case int64Val:
 		return int64(x), true
 	case intVal:
-		return x.val.Int64(), x.val.BitLen() <= 63
+		return x.val.Int64(), false // not an int64Val and thus not exact
 	case unknownVal:
 		return 0, false
+	default:
+		panic(fmt.Sprintf("%v not an Int", x))
 	}
-	panic(fmt.Sprintf("%v not an Int", x))
 }
 
 // Uint64Val returns the Go uint64 value of x and whether the result is exact;
@@ -247,8 +415,9 @@ func Uint64Val(x Value) (uint64, bool) {
 		return x.val.Uint64(), x.val.Sign() >= 0 && x.val.BitLen() <= 64
 	case unknownVal:
 		return 0, false
+	default:
+		panic(fmt.Sprintf("%v not an Int", x))
 	}
-	panic(fmt.Sprintf("%v not an Int", x))
 }
 
 // Float32Val is like Float64Val but for float32 instead of float64.
@@ -258,17 +427,22 @@ func Float32Val(x Value) (float32, bool) {
 		f := float32(x)
 		return f, int64Val(f) == x
 	case intVal:
-		return ratToFloat32(new(big.Rat).SetFrac(x.val, int1))
+		f, acc := newFloat().SetInt(x.val).Float32()
+		return f, acc == big.Exact
+	case ratVal:
+		return x.val.Float32()
 	case floatVal:
-		return ratToFloat32(x.val)
+		f, acc := x.val.Float32()
+		return f, acc == big.Exact
 	case unknownVal:
 		return 0, false
+	default:
+		panic(fmt.Sprintf("%v not a Float", x))
 	}
-	panic(fmt.Sprintf("%v not a Float", x))
 }
 
 // Float64Val returns the nearest Go float64 value of x and whether the result is exact;
-// x must be numeric but not Complex, or Unknown. For values too small (too close to 0)
+// x must be numeric or an Unknown, but not Complex. For values too small (too close to 0)
 // to represent as float64, Float64Val silently underflows to 0. The result sign always
 // matches the sign of x, even for 0.
 // If x is Unknown, the result is (0, false).
@@ -278,13 +452,18 @@ func Float64Val(x Value) (float64, bool) {
 		f := float64(int64(x))
 		return f, int64Val(f) == x
 	case intVal:
-		return new(big.Rat).SetFrac(x.val, int1).Float64()
-	case floatVal:
+		f, acc := newFloat().SetInt(x.val).Float64()
+		return f, acc == big.Exact
+	case ratVal:
 		return x.val.Float64()
+	case floatVal:
+		f, acc := x.val.Float64()
+		return f, acc == big.Exact
 	case unknownVal:
 		return 0, false
+	default:
+		panic(fmt.Sprintf("%v not a Float", x))
 	}
-	panic(fmt.Sprintf("%v not a Float", x))
 }
 
 // BitLen returns the number of bits required to represent
@@ -293,13 +472,14 @@ func Float64Val(x Value) (float64, bool) {
 func BitLen(x Value) int {
 	switch x := x.(type) {
 	case int64Val:
-		return new(big.Int).SetInt64(int64(x)).BitLen()
+		return i64toi(x).val.BitLen()
 	case intVal:
 		return x.val.BitLen()
 	case unknownVal:
 		return 0
+	default:
+		panic(fmt.Sprintf("%v not an Int", x))
 	}
-	panic(fmt.Sprintf("%v not an Int", x))
 }
 
 // Sign returns -1, 0, or 1 depending on whether x < 0, x == 0, or x > 0;
@@ -317,18 +497,21 @@ func Sign(x Value) int {
 		return 0
 	case intVal:
 		return x.val.Sign()
+	case ratVal:
+		return x.val.Sign()
 	case floatVal:
 		return x.val.Sign()
 	case complexVal:
-		return x.re.Sign() | x.im.Sign()
+		return Sign(x.re) | Sign(x.im)
 	case unknownVal:
 		return 1 // avoid spurious division by zero errors
+	default:
+		panic(fmt.Sprintf("%v not numeric", x))
 	}
-	panic(fmt.Sprintf("%v not numeric", x))
 }
 
 // ----------------------------------------------------------------------------
-// Support for serializing/deserializing integers
+// Support for assembling/disassembling numeric values
 
 const (
 	// Compute the size of a Word in bytes.
@@ -340,17 +523,17 @@ const (
 // Bytes returns the bytes for the absolute value of x in little-
 // endian binary representation; x must be an Int.
 func Bytes(x Value) []byte {
-	var val *big.Int
+	var t intVal
 	switch x := x.(type) {
 	case int64Val:
-		val = new(big.Int).SetInt64(int64(x))
+		t = i64toi(x)
 	case intVal:
-		val = x.val
+		t = x
 	default:
 		panic(fmt.Sprintf("%v not an Int", x))
 	}
 
-	words := val.Bits()
+	words := t.val.Bits()
 	bytes := make([]byte, len(words)*wordSize)
 
 	i := 0
@@ -396,72 +579,79 @@ func MakeFromBytes(bytes []byte) Value {
 		i--
 	}
 
-	return normInt(new(big.Int).SetBits(words[:i]))
+	return makeInt(newInt().SetBits(words[:i]))
 }
 
-// ----------------------------------------------------------------------------
-// Support for disassembling fractions
-
 // Num returns the numerator of x; x must be Int, Float, or Unknown.
-// If x is Unknown, the result is Unknown, otherwise it is an Int
+// If x is Unknown, or if it is too large or small to represent as a
+// fraction, the result is Unknown. Otherwise the result is an Int
 // with the same sign as x.
 func Num(x Value) Value {
 	switch x := x.(type) {
-	case unknownVal, int64Val, intVal:
+	case int64Val, intVal:
 		return x
+	case ratVal:
+		return makeInt(x.val.Num())
 	case floatVal:
-		return normInt(x.val.Num())
+		if smallRat(x.val) {
+			r, _ := x.val.Rat(nil)
+			return makeInt(r.Num())
+		}
+	case unknownVal:
+		break
+	default:
+		panic(fmt.Sprintf("%v not Int or Float", x))
 	}
-	panic(fmt.Sprintf("%v not Int or Float", x))
+	return unknownVal{}
 }
 
 // Denom returns the denominator of x; x must be Int, Float, or Unknown.
-// If x is Unknown, the result is Unknown, otherwise it is an Int >= 1.
+// If x is Unknown, or if it is too large or small to represent as a
+// fraction, the result is Unknown. Otherwise the result is an Int >= 1.
 func Denom(x Value) Value {
 	switch x := x.(type) {
-	case unknownVal:
-		return x
 	case int64Val, intVal:
 		return int64Val(1)
+	case ratVal:
+		return makeInt(x.val.Denom())
 	case floatVal:
-		return normInt(x.val.Denom())
+		if smallRat(x.val) {
+			r, _ := x.val.Rat(nil)
+			return makeInt(r.Denom())
+		}
+	case unknownVal:
+		break
+	default:
+		panic(fmt.Sprintf("%v not Int or Float", x))
 	}
-	panic(fmt.Sprintf("%v not Int or Float", x))
+	return unknownVal{}
 }
 
-// ----------------------------------------------------------------------------
-// Support for assembling/disassembling complex numbers
-
-// MakeImag returns the numeric value x*i (possibly 0);
+// MakeImag returns the Complex value x*i;
 // x must be Int, Float, or Unknown.
 // If x is Unknown, the result is Unknown.
 func MakeImag(x Value) Value {
-	var im *big.Rat
-	switch x := x.(type) {
+	switch x.(type) {
 	case unknownVal:
 		return x
-	case int64Val:
-		im = big.NewRat(int64(x), 1)
-	case intVal:
-		im = new(big.Rat).SetFrac(x.val, int1)
-	case floatVal:
-		im = x.val
+	case int64Val, intVal, ratVal, floatVal:
+		return makeComplex(int64Val(0), x)
 	default:
 		panic(fmt.Sprintf("%v not Int or Float", x))
 	}
-	return normComplex(rat0, im)
 }
 
 // Real returns the real part of x, which must be a numeric or unknown value.
 // If x is Unknown, the result is Unknown.
 func Real(x Value) Value {
 	switch x := x.(type) {
-	case unknownVal, int64Val, intVal, floatVal:
+	case unknownVal, int64Val, intVal, ratVal, floatVal:
 		return x
 	case complexVal:
-		return normFloat(x.re)
+		return x.re
+	default:
+		panic(fmt.Sprintf("%v not numeric", x))
 	}
-	panic(fmt.Sprintf("%v not numeric", x))
 }
 
 // Imag returns the imaginary part of x, which must be a numeric or unknown value.
@@ -470,12 +660,107 @@ func Imag(x Value) Value {
 	switch x := x.(type) {
 	case unknownVal:
 		return x
-	case int64Val, intVal, floatVal:
+	case int64Val, intVal, ratVal, floatVal:
 		return int64Val(0)
 	case complexVal:
-		return normFloat(x.im)
+		return x.im
+	default:
+		panic(fmt.Sprintf("%v not numeric", x))
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Numeric conversions
+
+// ToInt converts x to an Int value if x is representable as an Int.
+// Otherwise it returns an Unknown.
+func ToInt(x Value) Value {
+	switch x := x.(type) {
+	case int64Val, intVal:
+		return x
+
+	case ratVal:
+		if x.val.IsInt() {
+			return makeInt(x.val.Num())
+		}
+
+	case floatVal:
+		// avoid creation of huge integers
+		// (Existing tests require permitting exponents of at least 1024;
+		// allow any value that would also be permissible as a fraction.)
+		if smallRat(x.val) {
+			i := newInt()
+			if _, acc := x.val.Int(i); acc == big.Exact {
+				return makeInt(i)
+			}
+
+			// If we can get an integer by rounding up or down,
+			// assume x is not an integer because of rounding
+			// errors in prior computations.
+
+			const delta = 4 // a small number of bits > 0
+			var t big.Float
+			t.SetPrec(prec - delta)
+
+			// try rounding down a little
+			t.SetMode(big.ToZero)
+			t.Set(x.val)
+			if _, acc := t.Int(i); acc == big.Exact {
+				return makeInt(i)
+			}
+
+			// try rounding up a little
+			t.SetMode(big.AwayFromZero)
+			t.Set(x.val)
+			if _, acc := t.Int(i); acc == big.Exact {
+				return makeInt(i)
+			}
+		}
+
+	case complexVal:
+		if re := ToFloat(x); re.Kind() == Float {
+			return ToInt(re)
+		}
+	}
+
+	return unknownVal{}
+}
+
+// ToFloat converts x to a Float value if x is representable as a Float.
+// Otherwise it returns an Unknown.
+func ToFloat(x Value) Value {
+	switch x := x.(type) {
+	case int64Val:
+		return i64tof(x)
+	case intVal:
+		return itof(x)
+	case ratVal, floatVal:
+		return x
+	case complexVal:
+		if im := ToInt(x.im); im.Kind() == Int && Sign(im) == 0 {
+			// imaginary component is 0
+			return ToFloat(x.re)
+		}
+	}
+	return unknownVal{}
+}
+
+// ToComplex converts x to a Complex value if x is representable as a Complex.
+// Otherwise it returns an Unknown.
+func ToComplex(x Value) Value {
+	switch x := x.(type) {
+	case int64Val:
+		return vtoc(i64tof(x))
+	case intVal:
+		return vtoc(itof(x))
+	case ratVal:
+		return vtoc(x)
+	case floatVal:
+		return vtoc(x)
+	case complexVal:
+		return x
 	}
-	panic(fmt.Sprintf("%v not numeric", x))
+	return unknownVal{}
 }
 
 // ----------------------------------------------------------------------------
@@ -502,7 +787,7 @@ func UnaryOp(op token.Token, y Value, prec uint) Value {
 	switch op {
 	case token.ADD:
 		switch y.(type) {
-		case unknownVal, int64Val, intVal, floatVal, complexVal:
+		case unknownVal, int64Val, intVal, ratVal, floatVal, complexVal:
 			return y
 		}
 
@@ -514,17 +799,21 @@ func UnaryOp(op token.Token, y Value, prec uint) Value {
 			if z := -y; z != y {
 				return z // no overflow
 			}
-			return normInt(new(big.Int).Neg(big.NewInt(int64(y))))
+			return makeInt(newInt().Neg(big.NewInt(int64(y))))
 		case intVal:
-			return normInt(new(big.Int).Neg(y.val))
+			return makeInt(newInt().Neg(y.val))
+		case ratVal:
+			return makeRat(newRat().Neg(y.val))
 		case floatVal:
-			return normFloat(new(big.Rat).Neg(y.val))
+			return makeFloat(newFloat().Neg(y.val))
 		case complexVal:
-			return normComplex(new(big.Rat).Neg(y.re), new(big.Rat).Neg(y.im))
+			re := UnaryOp(token.SUB, y.re, 0)
+			im := UnaryOp(token.SUB, y.im, 0)
+			return makeComplex(re, im)
 		}
 
 	case token.XOR:
-		var z big.Int
+		z := newInt()
 		switch y := y.(type) {
 		case unknownVal:
 			return y
@@ -539,9 +828,9 @@ func UnaryOp(op token.Token, y Value, prec uint) Value {
 		// thus "too large": We must limit the result precision
 		// to the type's precision.
 		if prec > 0 {
-			z.AndNot(&z, new(big.Int).Lsh(big.NewInt(-1), prec)) // z &^= (-1)<<prec
+			z.AndNot(z, newInt().Lsh(big.NewInt(-1), prec)) // z &^= (-1)<<prec
 		}
-		return normInt(&z)
+		return makeInt(z)
 
 	case token.NOT:
 		switch y := y.(type) {
@@ -556,14 +845,9 @@ Error:
 	panic(fmt.Sprintf("invalid unary operation %s%v", op, y))
 }
 
-var (
-	int1 = big.NewInt(1)
-	rat0 = big.NewRat(0, 1)
-)
-
 func ord(x Value) int {
 	switch x.(type) {
-	default:
+	case unknownVal:
 		return 0
 	case boolVal, stringVal:
 		return 1
@@ -571,10 +855,14 @@ func ord(x Value) int {
 		return 2
 	case intVal:
 		return 3
-	case floatVal:
+	case ratVal:
 		return 4
-	case complexVal:
+	case floatVal:
 		return 5
+	case complexVal:
+		return 6
+	default:
+		panic("unreachable")
 	}
 }
 
@@ -602,29 +890,42 @@ func match(x, y Value) (_, _ Value) {
 		case int64Val:
 			return x, y
 		case intVal:
-			return intVal{big.NewInt(int64(x))}, y
+			return i64toi(x), y
+		case ratVal:
+			return i64tor(x), y
 		case floatVal:
-			return floatVal{big.NewRat(int64(x), 1)}, y
+			return i64tof(x), y
 		case complexVal:
-			return complexVal{big.NewRat(int64(x), 1), rat0}, y
+			return vtoc(x), y
 		}
 
 	case intVal:
 		switch y := y.(type) {
 		case intVal:
 			return x, y
+		case ratVal:
+			return itor(x), y
 		case floatVal:
-			return floatVal{new(big.Rat).SetFrac(x.val, int1)}, y
+			return itof(x), y
 		case complexVal:
-			return complexVal{new(big.Rat).SetFrac(x.val, int1), rat0}, y
+			return vtoc(x), y
 		}
 
+	case ratVal:
+		switch y := y.(type) {
+		case ratVal:
+			return x, y
+		case floatVal:
+			return rtof(x), y
+		case complexVal:
+			return vtoc(x), y
+		}
 	case floatVal:
 		switch y := y.(type) {
 		case floatVal:
 			return x, y
 		case complexVal:
-			return complexVal{x.val, rat0}, y
+			return vtoc(x), y
 		}
 	}
 
@@ -661,21 +962,21 @@ func BinaryOp(x Value, op token.Token, y Value) Value {
 		switch op {
 		case token.ADD:
 			if !is63bit(a) || !is63bit(b) {
-				return normInt(new(big.Int).Add(big.NewInt(a), big.NewInt(b)))
+				return makeInt(newInt().Add(big.NewInt(a), big.NewInt(b)))
 			}
 			c = a + b
 		case token.SUB:
 			if !is63bit(a) || !is63bit(b) {
-				return normInt(new(big.Int).Sub(big.NewInt(a), big.NewInt(b)))
+				return makeInt(newInt().Sub(big.NewInt(a), big.NewInt(b)))
 			}
 			c = a - b
 		case token.MUL:
 			if !is32bit(a) || !is32bit(b) {
-				return normInt(new(big.Int).Mul(big.NewInt(a), big.NewInt(b)))
+				return makeInt(newInt().Mul(big.NewInt(a), big.NewInt(b)))
 			}
 			c = a * b
 		case token.QUO:
-			return normFloat(new(big.Rat).SetFrac(big.NewInt(a), big.NewInt(b)))
+			return makeRat(big.NewRat(a, b))
 		case token.QUO_ASSIGN: // force integer division
 			c = a / b
 		case token.REM:
@@ -696,7 +997,7 @@ func BinaryOp(x Value, op token.Token, y Value) Value {
 	case intVal:
 		a := x.val
 		b := y.(intVal).val
-		var c big.Int
+		c := newInt()
 		switch op {
 		case token.ADD:
 			c.Add(a, b)
@@ -705,7 +1006,7 @@ func BinaryOp(x Value, op token.Token, y Value) Value {
 		case token.MUL:
 			c.Mul(a, b)
 		case token.QUO:
-			return normFloat(new(big.Rat).SetFrac(a, b))
+			return makeRat(newRat().SetFrac(a, b))
 		case token.QUO_ASSIGN: // force integer division
 			c.Quo(a, b)
 		case token.REM:
@@ -721,12 +1022,30 @@ func BinaryOp(x Value, op token.Token, y Value) Value {
 		default:
 			goto Error
 		}
-		return normInt(&c)
+		return makeInt(c)
+
+	case ratVal:
+		a := x.val
+		b := y.(ratVal).val
+		c := newRat()
+		switch op {
+		case token.ADD:
+			c.Add(a, b)
+		case token.SUB:
+			c.Sub(a, b)
+		case token.MUL:
+			c.Mul(a, b)
+		case token.QUO:
+			c.Quo(a, b)
+		default:
+			goto Error
+		}
+		return makeRat(c)
 
 	case floatVal:
 		a := x.val
 		b := y.(floatVal).val
-		var c big.Rat
+		c := newFloat()
 		switch op {
 		case token.ADD:
 			c.Add(a, b)
@@ -739,49 +1058,47 @@ func BinaryOp(x Value, op token.Token, y Value) Value {
 		default:
 			goto Error
 		}
-		return normFloat(&c)
+		return makeFloat(c)
 
 	case complexVal:
 		y := y.(complexVal)
 		a, b := x.re, x.im
 		c, d := y.re, y.im
-		var re, im big.Rat
+		var re, im Value
 		switch op {
 		case token.ADD:
 			// (a+c) + i(b+d)
-			re.Add(a, c)
-			im.Add(b, d)
+			re = add(a, c)
+			im = add(b, d)
 		case token.SUB:
 			// (a-c) + i(b-d)
-			re.Sub(a, c)
-			im.Sub(b, d)
+			re = sub(a, c)
+			im = sub(b, d)
 		case token.MUL:
 			// (ac-bd) + i(bc+ad)
-			var ac, bd, bc, ad big.Rat
-			ac.Mul(a, c)
-			bd.Mul(b, d)
-			bc.Mul(b, c)
-			ad.Mul(a, d)
-			re.Sub(&ac, &bd)
-			im.Add(&bc, &ad)
+			ac := mul(a, c)
+			bd := mul(b, d)
+			bc := mul(b, c)
+			ad := mul(a, d)
+			re = sub(ac, bd)
+			im = add(bc, ad)
 		case token.QUO:
 			// (ac+bd)/s + i(bc-ad)/s, with s = cc + dd
-			var ac, bd, bc, ad, s, cc, dd big.Rat
-			ac.Mul(a, c)
-			bd.Mul(b, d)
-			bc.Mul(b, c)
-			ad.Mul(a, d)
-			cc.Mul(c, c)
-			dd.Mul(d, d)
-			s.Add(&cc, &dd)
-			re.Add(&ac, &bd)
-			re.Quo(&re, &s)
-			im.Sub(&bc, &ad)
-			im.Quo(&im, &s)
+			ac := mul(a, c)
+			bd := mul(b, d)
+			bc := mul(b, c)
+			ad := mul(a, d)
+			cc := mul(c, c)
+			dd := mul(d, d)
+			s := add(cc, dd)
+			re = add(ac, bd)
+			re = quo(re, s)
+			im = sub(bc, ad)
+			im = quo(im, s)
 		default:
 			goto Error
 		}
-		return normComplex(&re, &im)
+		return makeComplex(re, im)
 
 	case stringVal:
 		if op == token.ADD {
@@ -793,6 +1110,11 @@ Error:
 	panic(fmt.Sprintf("invalid binary operation %v %s %v", x, op, y))
 }
 
+func add(x, y Value) Value { return BinaryOp(x, token.ADD, y) }
+func sub(x, y Value) Value { return BinaryOp(x, token.SUB, y) }
+func mul(x, y Value) Value { return BinaryOp(x, token.MUL, y) }
+func quo(x, y Value) Value { return BinaryOp(x, token.QUO, y) }
+
 // Shift returns the result of the shift expression x op s
 // with op == token.SHL or token.SHR (<< or >>). x must be
 // an Int or an Unknown. If x is Unknown, the result is x.
@@ -808,8 +1130,8 @@ func Shift(x Value, op token.Token, s uint) Value {
 		}
 		switch op {
 		case token.SHL:
-			z := big.NewInt(int64(x))
-			return normInt(z.Lsh(z, s))
+			z := i64toi(x).val
+			return makeInt(z.Lsh(z, s))
 		case token.SHR:
 			return x >> s
 		}
@@ -818,12 +1140,12 @@ func Shift(x Value, op token.Token, s uint) Value {
 		if s == 0 {
 			return x
 		}
-		var z big.Int
+		z := newInt()
 		switch op {
 		case token.SHL:
-			return normInt(z.Lsh(x.val, s))
+			return makeInt(z.Lsh(x.val, s))
 		case token.SHR:
-			return normInt(z.Rsh(x.val, s))
+			return makeInt(z.Rsh(x.val, s))
 		}
 	}
 
@@ -889,18 +1211,21 @@ func Compare(x Value, op token.Token, y Value) bool {
 	case intVal:
 		return cmpZero(x.val.Cmp(y.(intVal).val), op)
 
+	case ratVal:
+		return cmpZero(x.val.Cmp(y.(ratVal).val), op)
+
 	case floatVal:
 		return cmpZero(x.val.Cmp(y.(floatVal).val), op)
 
 	case complexVal:
 		y := y.(complexVal)
-		re := x.re.Cmp(y.re)
-		im := x.im.Cmp(y.im)
+		re := Compare(x.re, token.EQL, y.re)
+		im := Compare(x.im, token.EQL, y.im)
 		switch op {
 		case token.EQL:
-			return re == 0 && im == 0
+			return re && im
 		case token.NEQ:
-			return re != 0 || im != 0
+			return !re || !im
 		}
 
 	case stringVal:
diff --git a/src/go/constant/value_test.go b/src/go/constant/value_test.go
index 08cdd5e..dbd96c0 100644
--- a/src/go/constant/value_test.go
+++ b/src/go/constant/value_test.go
@@ -176,12 +176,17 @@ func TestOps(t *testing.T) {
 		want := val(a[i+3])
 		if !eql(got, want) {
 			t.Errorf("%s: got %s; want %s", test, got, want)
+			continue
 		}
+
 		if x0 != nil && !eql(x, x0) {
 			t.Errorf("%s: x changed to %s", test, x)
+			continue
 		}
+
 		if !eql(y, y0) {
 			t.Errorf("%s: y changed to %s", test, y)
+			continue
 		}
 	}
 }
@@ -196,6 +201,71 @@ func eql(x, y Value) bool {
 }
 
 // ----------------------------------------------------------------------------
+// String tests
+
+var xxx = strings.Repeat("x", 68)
+var issue14262 = `"بموجب الشروط التالية نسب المصنف — يجب عليك أن تنسب العمل بالطريقة التي تحددها المؤلف أو المرخص (ولكن ليس بأي حال من الأحوال أن توحي وتقترح بتحول أو استخدامك للعمل).  المشاركة على قدم المساواة — إذا كنت يعدل ، والتغيير ، أو الاستفادة من هذا العمل ، قد ينتج عن توزيع العمل إلا في ظل تشابه او تطابق فى واحد لهذا الترخيص."`
+
+var stringTests = []struct {
+	input, short, exact string
+}{
+	// Unknown
+	{"", "unknown", "unknown"},
+	{"0x", "unknown", "unknown"},
+	{"'", "unknown", "unknown"},
+	{"1f0", "unknown", "unknown"},
+	{"unknown", "unknown", "unknown"},
+
+	// Bool
+	{"true", "true", "true"},
+	{"false", "false", "false"},
+
+	// String
+	{`""`, `""`, `""`},
+	{`"foo"`, `"foo"`, `"foo"`},
+	{`"` + xxx + `xx"`, `"` + xxx + `xx"`, `"` + xxx + `xx"`},
+	{`"` + xxx + `xxx"`, `"` + xxx + `...`, `"` + xxx + `xxx"`},
+	{`"` + xxx + xxx + `xxx"`, `"` + xxx + `...`, `"` + xxx + xxx + `xxx"`},
+	{issue14262, `"بموجب الشروط التالية نسب المصنف — يجب عليك أن تنسب العمل بالطريقة ال...`, issue14262},
+
+	// Int
+	{"0", "0", "0"},
+	{"-1", "-1", "-1"},
+	{"12345", "12345", "12345"},
+	{"-12345678901234567890", "-12345678901234567890", "-12345678901234567890"},
+	{"12345678901234567890", "12345678901234567890", "12345678901234567890"},
+
+	// Float
+	{"0.", "0", "0"},
+	{"-0.0", "0", "0"},
+	{"10.0", "10", "10"},
+	{"2.1", "2.1", "21/10"},
+	{"-2.1", "-2.1", "-21/10"},
+	{"1e9999", "1e+9999", "0x.f8d4a9da224650a8cb2959e10d985ad92adbd44c62917e608b1f24c0e1b76b6f61edffeb15c135a4b601637315f7662f325f82325422b244286a07663c9415d2p+33216"},
+	{"1e-9999", "1e-9999", "0x.83b01ba6d8c0425eec1b21e96f7742d63c2653ed0a024cf8a2f9686df578d7b07d7a83d84df6a2ec70a921d1f6cd5574893a7eda4d28ee719e13a5dce2700759p-33215"},
+	{"2.71828182845904523536028747135266249775724709369995957496696763", "2.71828", "271828182845904523536028747135266249775724709369995957496696763/100000000000000000000000000000000000000000000000000000000000000"},
+
+	// Complex
+	{"0i", "(0 + 0i)", "(0 + 0i)"},
+	{"-0i", "(0 + 0i)", "(0 + 0i)"},
+	{"10i", "(0 + 10i)", "(0 + 10i)"},
+	{"-10i", "(0 + -10i)", "(0 + -10i)"},
+	{"1e9999i", "(0 + 1e+9999i)", "(0 + 0x.f8d4a9da224650a8cb2959e10d985ad92adbd44c62917e608b1f24c0e1b76b6f61edffeb15c135a4b601637315f7662f325f82325422b244286a07663c9415d2p+33216i)"},
+}
+
+func TestString(t *testing.T) {
+	for _, test := range stringTests {
+		x := val(test.input)
+		if got := x.String(); got != test.short {
+			t.Errorf("%s: got %q; want %q as short string", test.input, got, test.short)
+		}
+		if got := x.ExactString(); got != test.exact {
+			t.Errorf("%s: got %q; want %q as exact string", test.input, got, test.exact)
+		}
+	}
+}
+
+// ----------------------------------------------------------------------------
 // Support functions
 
 func val(lit string) Value {
@@ -212,6 +282,13 @@ func val(lit string) Value {
 		return MakeBool(false)
 	}
 
+	if i := strings.IndexByte(lit, '/'); i >= 0 {
+		// assume fraction
+		a := MakeFromLiteral(lit[:i], token.INT, 0)
+		b := MakeFromLiteral(lit[i+1:], token.INT, 0)
+		return BinaryOp(a, token.QUO, b)
+	}
+
 	tok := token.INT
 	switch first, last := lit[0], lit[len(lit)-1]; {
 	case first == '"' || first == '`':
@@ -290,32 +367,29 @@ func doOp(x Value, op token.Token, y Value) (z Value) {
 // Other tests
 
 var fracTests = []string{
-	"0 0 1",
-	"1 1 1",
-	"-1 -1 1",
-	"1.2 6 5",
-	"-0.991 -991 1000",
-	"1e100 1e100 1",
+	"0",
+	"1",
+	"-1",
+	"1.2",
+	"-0.991",
+	"2.718281828",
+	"3.14159265358979323e-10",
+	"1e100",
+	"1e1000",
 }
 
 func TestFractions(t *testing.T) {
 	for _, test := range fracTests {
-		a := strings.Split(test, " ")
-		if len(a) != 3 {
-			t.Errorf("invalid test case: %s", test)
-			continue
-		}
-
-		x := val(a[0])
-		n := val(a[1])
-		d := val(a[2])
-
-		if got := Num(x); !eql(got, n) {
-			t.Errorf("%s: got num = %s; want %s", test, got, n)
-		}
-
-		if got := Denom(x); !eql(got, d) {
-			t.Errorf("%s: got denom = %s; want %s", test, got, d)
+		x := val(test)
+		// We don't check the actual numerator and denominator because they
+		// are unlikely to be 100% correct due to floatVal rounding errors.
+		// Instead, we compute the fraction again and compare the rounded
+		// result.
+		q := BinaryOp(Num(x), token.QUO, Denom(x))
+		got := q.String()
+		want := x.String()
+		if got != want {
+			t.Errorf("%s: got quotient %s, want %s", x, got, want)
 		}
 	}
 }
diff --git a/src/go/doc/reader.go b/src/go/doc/reader.go
index ed82c47..e4e7b7c 100644
--- a/src/go/doc/reader.go
+++ b/src/go/doc/reader.go
@@ -18,7 +18,7 @@ import (
 // Internally, we treat functions like methods and collect them in method sets.
 
 // A methodSet describes a set of methods. Entries where Decl == nil are conflict
-// entries (more then one method with the same name at the same embedding level).
+// entries (more than one method with the same name at the same embedding level).
 //
 type methodSet map[string]*Func
 
@@ -71,7 +71,7 @@ func (mset methodSet) set(f *ast.FuncDecl) {
 
 // add adds method m to the method set; m is ignored if the method set
 // already contains a method with the same name at the same or a higher
-// level then m.
+// level than m.
 //
 func (mset methodSet) add(m *Func) {
 	old := mset[m.Name]
@@ -151,10 +151,11 @@ type reader struct {
 	notes     map[string][]*Note
 
 	// declarations
-	imports map[string]int
-	values  []*Value // consts and vars
-	types   map[string]*namedType
-	funcs   methodSet
+	imports   map[string]int
+	hasDotImp bool     // if set, package contains a dot import
+	values    []*Value // consts and vars
+	types     map[string]*namedType
+	funcs     methodSet
 
 	// support for package-local error type declarations
 	errorDecl bool                 // if set, type "error" was declared locally
@@ -208,7 +209,7 @@ func (r *reader) recordAnonymousField(parent *namedType, fieldType ast.Expr) (fn
 
 func (r *reader) readDoc(comment *ast.CommentGroup) {
 	// By convention there should be only one package comment
-	// but collect all of them if there are more then one.
+	// but collect all of them if there are more than one.
 	text := comment.Text()
 	if r.doc == "" {
 		r.doc = text
@@ -471,6 +472,9 @@ func (r *reader) readFile(src *ast.File) {
 					if s, ok := spec.(*ast.ImportSpec); ok {
 						if import_, err := strconv.Unquote(s.Path.Value); err == nil {
 							r.imports[import_] = 1
+							if s.Name != nil && s.Name.Name == "." {
+								r.hasDotImp = true
+							}
 						}
 					}
 				}
@@ -641,11 +645,12 @@ func (r *reader) computeMethodSets() {
 func (r *reader) cleanupTypes() {
 	for _, t := range r.types {
 		visible := r.isVisible(t.name)
-		if t.decl == nil && (predeclaredTypes[t.name] || t.isEmbedded && visible) {
+		if t.decl == nil && (predeclaredTypes[t.name] || visible && (t.isEmbedded || r.hasDotImp)) {
 			// t.name is a predeclared type (and was not redeclared in this package),
 			// or it was embedded somewhere but its declaration is missing (because
-			// the AST is incomplete): move any associated values, funcs, and methods
-			// back to the top-level so that they are not lost.
+			// the AST is incomplete), or we have a dot-import (and all bets are off):
+			// move any associated values, funcs, and methods back to the top-level so
+			// that they are not lost.
 			// 1) move values
 			r.values = append(r.values, t.values...)
 			// 2) move factory functions
diff --git a/src/go/doc/testdata/issue13742.0.golden b/src/go/doc/testdata/issue13742.0.golden
new file mode 100644
index 0000000..8dee9aa
--- /dev/null
+++ b/src/go/doc/testdata/issue13742.0.golden
@@ -0,0 +1,25 @@
+// 
+PACKAGE issue13742
+
+IMPORTPATH
+	testdata/issue13742
+
+IMPORTS
+	go/ast
+
+FILENAMES
+	testdata/issue13742.go
+
+FUNCTIONS
+	// Both F0 and G0 should appear as functions. 
+	func F0(Node)
+
+	// Both F1 and G1 should appear as functions. 
+	func F1(ast.Node)
+
+	// 
+	func G0() Node
+
+	// 
+	func G1() ast.Node
+
diff --git a/src/go/doc/testdata/issue13742.1.golden b/src/go/doc/testdata/issue13742.1.golden
new file mode 100644
index 0000000..8dee9aa
--- /dev/null
+++ b/src/go/doc/testdata/issue13742.1.golden
@@ -0,0 +1,25 @@
+// 
+PACKAGE issue13742
+
+IMPORTPATH
+	testdata/issue13742
+
+IMPORTS
+	go/ast
+
+FILENAMES
+	testdata/issue13742.go
+
+FUNCTIONS
+	// Both F0 and G0 should appear as functions. 
+	func F0(Node)
+
+	// Both F1 and G1 should appear as functions. 
+	func F1(ast.Node)
+
+	// 
+	func G0() Node
+
+	// 
+	func G1() ast.Node
+
diff --git a/src/go/doc/testdata/issue13742.2.golden b/src/go/doc/testdata/issue13742.2.golden
new file mode 100644
index 0000000..8dee9aa
--- /dev/null
+++ b/src/go/doc/testdata/issue13742.2.golden
@@ -0,0 +1,25 @@
+// 
+PACKAGE issue13742
+
+IMPORTPATH
+	testdata/issue13742
+
+IMPORTS
+	go/ast
+
+FILENAMES
+	testdata/issue13742.go
+
+FUNCTIONS
+	// Both F0 and G0 should appear as functions. 
+	func F0(Node)
+
+	// Both F1 and G1 should appear as functions. 
+	func F1(ast.Node)
+
+	// 
+	func G0() Node
+
+	// 
+	func G1() ast.Node
+
diff --git a/src/go/doc/testdata/issue13742.go b/src/go/doc/testdata/issue13742.go
new file mode 100644
index 0000000..dbc1941
--- /dev/null
+++ b/src/go/doc/testdata/issue13742.go
@@ -0,0 +1,18 @@
+// 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 issue13742
+
+import (
+	"go/ast"
+	. "go/ast"
+)
+
+// Both F0 and G0 should appear as functions.
+func F0(Node)  {}
+func G0() Node { return nil }
+
+// Both F1 and G1 should appear as functions.
+func F1(ast.Node)  {}
+func G1() ast.Node { return nil }
diff --git a/src/go/format/format.go b/src/go/format/format.go
index 1adfd7d..b9cacfe 100644
--- a/src/go/format/format.go
+++ b/src/go/format/format.go
@@ -12,7 +12,6 @@ import (
 	"go/parser"
 	"go/printer"
 	"go/token"
-	"internal/format"
 	"io"
 )
 
@@ -82,7 +81,7 @@ func Node(dst io.Writer, fset *token.FileSet, node interface{}) error {
 //
 func Source(src []byte) ([]byte, error) {
 	fset := token.NewFileSet()
-	file, sourceAdj, indentAdj, err := format.Parse(fset, "", src, true)
+	file, sourceAdj, indentAdj, err := parse(fset, "", src, true)
 	if err != nil {
 		return nil, err
 	}
@@ -93,7 +92,7 @@ func Source(src []byte) ([]byte, error) {
 		ast.SortImports(fset, file)
 	}
 
-	return format.Format(fset, file, sourceAdj, indentAdj, src, config)
+	return format(fset, file, sourceAdj, indentAdj, src, config)
 }
 
 func hasUnsortedImports(file *ast.File) bool {
diff --git a/src/go/format/format_test.go b/src/go/format/format_test.go
index 000c611..b5817a5 100644
--- a/src/go/format/format_test.go
+++ b/src/go/format/format_test.go
@@ -72,6 +72,7 @@ func TestSource(t *testing.T) {
 }
 
 // Test cases that are expected to fail are marked by the prefix "ERROR".
+// The formatted result must look the same as the input for successful tests.
 var tests = []string{
 	// declaration lists
 	`import "go/format"`,
@@ -91,11 +92,23 @@ var tests = []string{
 	"\n\t\t\n\n\t\t\tx := 0\n\t\t\tconst s = `\n\t\tfoo\n`\n\n\n", // no indentation removed inside raw strings
 
 	// comments
-	"i := 5 /* Comment */",         // Issue 5551.
-	"\ta()\n//line :1",             // Issue 11276.
-	"\t//xxx\n\ta()\n//line :2",    // Issue 11276.
-	"\ta() //line :1\n\tb()\n",     // Issue 11276.
-	"x := 0\n//line :1\n//line :2", // Issue 11276.
+	"/* Comment */",
+	"\t/* Comment */ ",
+	"\n/* Comment */ ",
+	"i := 5 /* Comment */",         // issue #5551
+	"\ta()\n//line :1",             // issue #11276
+	"\t//xxx\n\ta()\n//line :2",    // issue #11276
+	"\ta() //line :1\n\tb()\n",     // issue #11276
+	"x := 0\n//line :1\n//line :2", // issue #11276
+
+	// whitespace
+	"",     // issue #11275
+	" ",    // issue #11275
+	"\t",   // issue #11275
+	"\t\t", // issue #11275
+	"\n",   // issue #11275
+	"\n\n", // issue #11275
+	"\t\n", // issue #11275
 
 	// erroneous programs
 	"ERROR1 + 2 +",
diff --git a/src/go/format/internal.go b/src/go/format/internal.go
new file mode 100644
index 0000000..9d04878
--- /dev/null
+++ b/src/go/format/internal.go
@@ -0,0 +1,176 @@
+// Copyright 2015 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.
+
+// TODO(gri): This file and the file src/cmd/gofmt/internal.go are
+// the same (but for this comment and the package name). Do not modify
+// one without the other. Determine if we can factor out functionality
+// in a public API. See also #11844 for context.
+
+package format
+
+import (
+	"bytes"
+	"go/ast"
+	"go/parser"
+	"go/printer"
+	"go/token"
+	"strings"
+)
+
+// parse parses src, which was read from the named file,
+// as a Go source file, declaration, or statement list.
+func parse(fset *token.FileSet, filename string, src []byte, fragmentOk bool) (
+	file *ast.File,
+	sourceAdj func(src []byte, indent int) []byte,
+	indentAdj int,
+	err error,
+) {
+	// Try as whole source file.
+	file, err = parser.ParseFile(fset, filename, src, parserMode)
+	// If there's no error, return.  If the error is that the source file didn't begin with a
+	// package line and source fragments are ok, fall through to
+	// try as a source fragment.  Stop and return on any other error.
+	if err == nil || !fragmentOk || !strings.Contains(err.Error(), "expected 'package'") {
+		return
+	}
+
+	// If this is a declaration list, make it a source file
+	// by inserting a package clause.
+	// Insert using a ;, not a newline, so that the line numbers
+	// in psrc match the ones in src.
+	psrc := append([]byte("package p;"), src...)
+	file, err = parser.ParseFile(fset, filename, psrc, parserMode)
+	if err == nil {
+		sourceAdj = func(src []byte, indent int) []byte {
+			// Remove the package clause.
+			// Gofmt has turned the ; into a \n.
+			src = src[indent+len("package p\n"):]
+			return bytes.TrimSpace(src)
+		}
+		return
+	}
+	// If the error is that the source file didn't begin with a
+	// declaration, fall through to try as a statement list.
+	// Stop and return on any other error.
+	if !strings.Contains(err.Error(), "expected declaration") {
+		return
+	}
+
+	// If this is a statement list, make it a source file
+	// by inserting a package clause and turning the list
+	// into a function body.  This handles expressions too.
+	// Insert using a ;, not a newline, so that the line numbers
+	// in fsrc match the ones in src. Add an extra '\n' before the '}'
+	// to make sure comments are flushed before the '}'.
+	fsrc := append(append([]byte("package p; func _() {"), src...), '\n', '\n', '}')
+	file, err = parser.ParseFile(fset, filename, fsrc, parserMode)
+	if err == nil {
+		sourceAdj = func(src []byte, indent int) []byte {
+			// Cap adjusted indent to zero.
+			if indent < 0 {
+				indent = 0
+			}
+			// Remove the wrapping.
+			// Gofmt has turned the ; into a \n\n.
+			// There will be two non-blank lines with indent, hence 2*indent.
+			src = src[2*indent+len("package p\n\nfunc _() {"):]
+			// Remove only the "}\n" suffix: remaining whitespaces will be trimmed anyway
+			src = src[:len(src)-len("}\n")]
+			return bytes.TrimSpace(src)
+		}
+		// Gofmt has also indented the function body one level.
+		// Adjust that with indentAdj.
+		indentAdj = -1
+	}
+
+	// Succeeded, or out of options.
+	return
+}
+
+// format formats the given package file originally obtained from src
+// and adjusts the result based on the original source via sourceAdj
+// and indentAdj.
+func format(
+	fset *token.FileSet,
+	file *ast.File,
+	sourceAdj func(src []byte, indent int) []byte,
+	indentAdj int,
+	src []byte,
+	cfg printer.Config,
+) ([]byte, error) {
+	if sourceAdj == nil {
+		// Complete source file.
+		var buf bytes.Buffer
+		err := cfg.Fprint(&buf, fset, file)
+		if err != nil {
+			return nil, err
+		}
+		return buf.Bytes(), nil
+	}
+
+	// Partial source file.
+	// Determine and prepend leading space.
+	i, j := 0, 0
+	for j < len(src) && isSpace(src[j]) {
+		if src[j] == '\n' {
+			i = j + 1 // byte offset of last line in leading space
+		}
+		j++
+	}
+	var res []byte
+	res = append(res, src[:i]...)
+
+	// Determine and prepend indentation of first code line.
+	// Spaces are ignored unless there are no tabs,
+	// in which case spaces count as one tab.
+	indent := 0
+	hasSpace := false
+	for _, b := range src[i:j] {
+		switch b {
+		case ' ':
+			hasSpace = true
+		case '\t':
+			indent++
+		}
+	}
+	if indent == 0 && hasSpace {
+		indent = 1
+	}
+	for i := 0; i < indent; i++ {
+		res = append(res, '\t')
+	}
+
+	// Format the source.
+	// Write it without any leading and trailing space.
+	cfg.Indent = indent + indentAdj
+	var buf bytes.Buffer
+	err := cfg.Fprint(&buf, fset, file)
+	if err != nil {
+		return nil, err
+	}
+	out := sourceAdj(buf.Bytes(), cfg.Indent)
+
+	// If the adjusted output is empty, the source
+	// was empty but (possibly) for white space.
+	// The result is the incoming source.
+	if len(out) == 0 {
+		return src, nil
+	}
+
+	// Otherwise, append output to leading space.
+	res = append(res, out...)
+
+	// Determine and append trailing space.
+	i = len(src)
+	for i > 0 && isSpace(src[i-1]) {
+		i--
+	}
+	return append(res, src[i:]...), nil
+}
+
+// isSpace reports whether the byte is a space character.
+// isSpace defines a space as being among the following bytes: ' ', '\t', '\n' and '\r'.
+func isSpace(b byte) bool {
+	return b == ' ' || b == '\t' || b == '\n' || b == '\r'
+}
diff --git a/src/go/importer/importer.go b/src/go/importer/importer.go
index 4590ca3..560b853 100644
--- a/src/go/importer/importer.go
+++ b/src/go/importer/importer.go
@@ -20,31 +20,37 @@ type Lookup func(path string) (io.ReadCloser, error)
 // For returns an Importer for the given compiler and lookup interface,
 // or nil. Supported compilers are "gc", and "gccgo". If lookup is nil,
 // the default package lookup mechanism for the given compiler is used.
+// BUG(issue13847): For does not support non-nil lookup functions.
 func For(compiler string, lookup Lookup) types.Importer {
 	switch compiler {
 	case "gc":
-		if lookup == nil {
-			return make(gcimports)
+		if lookup != nil {
+			panic("gc importer for custom import path lookup not yet implemented")
 		}
-		panic("gc importer for custom import path lookup not yet implemented")
+
+		return make(gcimports)
+
 	case "gccgo":
 		if lookup == nil {
-			var inst gccgoimporter.GccgoInstallation
-			if err := inst.InitFromDriver("gccgo"); err != nil {
-				return nil
-			}
-			return &gccgoimports{
-				packages: make(map[string]*types.Package),
-				importer: inst.GetImporter(nil, nil),
-			}
+			panic("gccgo importer for custom import path lookup not yet implemented")
+		}
+
+		var inst gccgoimporter.GccgoInstallation
+		if err := inst.InitFromDriver("gccgo"); err != nil {
+			return nil
+		}
+		return &gccgoimports{
+			packages: make(map[string]*types.Package),
+			importer: inst.GetImporter(nil, nil),
 		}
-		panic("gccgo importer for custom import path lookup not yet implemented")
 	}
+
 	// compiler not supported
 	return nil
 }
 
 // Default returns an Importer for the compiler that built the running binary.
+// If available, the result implements types.ImporterFrom.
 func Default() types.Importer {
 	return For(runtime.Compiler, nil)
 }
@@ -54,7 +60,14 @@ func Default() types.Importer {
 type gcimports map[string]*types.Package
 
 func (m gcimports) Import(path string) (*types.Package, error) {
-	return gcimporter.Import(m, path)
+	return m.ImportFrom(path, "" /* no vendoring */, 0)
+}
+
+func (m gcimports) ImportFrom(path, srcDir string, mode types.ImportMode) (*types.Package, error) {
+	if mode != 0 {
+		panic("mode must be 0")
+	}
+	return gcimporter.Import(m, path, srcDir)
 }
 
 // gccgo support
@@ -65,5 +78,13 @@ type gccgoimports struct {
 }
 
 func (m *gccgoimports) Import(path string) (*types.Package, error) {
+	return m.ImportFrom(path, "" /* no vendoring */, 0)
+}
+
+func (m *gccgoimports) ImportFrom(path, srcDir string, mode types.ImportMode) (*types.Package, error) {
+	if mode != 0 {
+		panic("mode must be 0")
+	}
+	// TODO(gri) pass srcDir
 	return m.importer(m.packages, path)
 }
diff --git a/src/go/internal/gccgoimporter/importer_test.go b/src/go/internal/gccgoimporter/importer_test.go
index f3bcadb..c10fa48 100644
--- a/src/go/internal/gccgoimporter/importer_test.go
+++ b/src/go/internal/gccgoimporter/importer_test.go
@@ -91,10 +91,10 @@ func runImporterTest(t *testing.T, imp Importer, initmap map[*types.Package]Init
 
 var importerTests = [...]importerTest{
 	{pkgpath: "pointer", name: "Int8Ptr", want: "type Int8Ptr *int8"},
-	{pkgpath: "complexnums", name: "NN", want: "const NN untyped complex", wantval: "(-1/1 + -1/1i)"},
-	{pkgpath: "complexnums", name: "NP", want: "const NP untyped complex", wantval: "(-1/1 + 1/1i)"},
-	{pkgpath: "complexnums", name: "PN", want: "const PN untyped complex", wantval: "(1/1 + -1/1i)"},
-	{pkgpath: "complexnums", name: "PP", want: "const PP untyped complex", wantval: "(1/1 + 1/1i)"},
+	{pkgpath: "complexnums", name: "NN", want: "const NN untyped complex", wantval: "(-1 + -1i)"},
+	{pkgpath: "complexnums", name: "NP", want: "const NP untyped complex", wantval: "(-1 + 1i)"},
+	{pkgpath: "complexnums", name: "PN", want: "const PN untyped complex", wantval: "(1 + -1i)"},
+	{pkgpath: "complexnums", name: "PP", want: "const PP untyped complex", wantval: "(1 + 1i)"},
 	// TODO: enable this entry once bug has been tracked down
 	//{pkgpath: "imports", wantinits: []string{"imports..import", "fmt..import", "math..import"}},
 }
diff --git a/src/go/internal/gcimporter/bimport.go b/src/go/internal/gcimporter/bimport.go
new file mode 100644
index 0000000..6869042
--- /dev/null
+++ b/src/go/internal/gcimporter/bimport.go
@@ -0,0 +1,681 @@
+// Copyright 2015 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 gcimporter
+
+import (
+	"encoding/binary"
+	"fmt"
+	"go/constant"
+	"go/token"
+	"go/types"
+	"sort"
+	"unicode"
+	"unicode/utf8"
+)
+
+// BImportData imports a package from the serialized package data
+// and returns the number of bytes consumed and a reference to the package.
+// If data is obviously malformed, an error is returned but in
+// general it is not recommended to call BImportData on untrusted data.
+func BImportData(imports map[string]*types.Package, data []byte, path string) (int, *types.Package, error) {
+	p := importer{
+		imports: imports,
+		data:    data,
+	}
+	p.buf = p.bufarray[:]
+
+	// read low-level encoding format
+	switch format := p.byte(); format {
+	case 'c':
+		// compact format - nothing to do
+	case 'd':
+		p.debugFormat = true
+	default:
+		return p.read, nil, fmt.Errorf("invalid encoding format in export data: got %q; want 'c' or 'd'", format)
+	}
+
+	// --- generic export data ---
+
+	if v := p.string(); v != "v0" {
+		return p.read, nil, fmt.Errorf("unknown version: %s", v)
+	}
+
+	// populate typList with predeclared "known" types
+	p.typList = append(p.typList, predeclared...)
+
+	// read package data
+	// TODO(gri) clean this up
+	i := p.tagOrIndex()
+	if i != packageTag {
+		panic(fmt.Sprintf("package tag expected, got %d", i))
+	}
+	name := p.string()
+	if s := p.string(); s != "" {
+		panic(fmt.Sprintf("empty path expected, got %s", s))
+	}
+	pkg := p.imports[path]
+	if pkg == nil {
+		pkg = types.NewPackage(path, name)
+		p.imports[path] = pkg
+	}
+	p.pkgList = append(p.pkgList, pkg)
+
+	if debug && p.pkgList[0] != pkg {
+		panic("imported packaged not found in pkgList[0]")
+	}
+
+	// read compiler-specific flags
+	p.string() // discard
+
+	// read consts
+	for i := p.int(); i > 0; i-- {
+		name := p.string()
+		typ := p.typ(nil)
+		val := p.value()
+		p.declare(types.NewConst(token.NoPos, pkg, name, typ, val))
+	}
+
+	// read vars
+	for i := p.int(); i > 0; i-- {
+		name := p.string()
+		typ := p.typ(nil)
+		p.declare(types.NewVar(token.NoPos, pkg, name, typ))
+	}
+
+	// read funcs
+	for i := p.int(); i > 0; i-- {
+		name := p.string()
+		sig := p.typ(nil).(*types.Signature)
+		p.int() // read and discard index of inlined function body
+		p.declare(types.NewFunc(token.NoPos, pkg, name, sig))
+	}
+
+	// read types
+	for i := p.int(); i > 0; i-- {
+		// name is parsed as part of named type and the
+		// type object is added to scope via respective
+		// named type
+		_ = p.typ(nil).(*types.Named)
+	}
+
+	// ignore compiler-specific import data
+
+	// complete interfaces
+	for _, typ := range p.typList {
+		if it, ok := typ.(*types.Interface); ok {
+			it.Complete()
+		}
+	}
+
+	// record all referenced packages as imports
+	list := append(([]*types.Package)(nil), p.pkgList[1:]...)
+	sort.Sort(byPath(list))
+	pkg.SetImports(list)
+
+	// package was imported completely and without errors
+	pkg.MarkComplete()
+
+	return p.read, pkg, nil
+}
+
+type importer struct {
+	imports  map[string]*types.Package
+	data     []byte
+	buf      []byte   // for reading strings
+	bufarray [64]byte // initial underlying array for buf, large enough to avoid allocation when compiling std lib
+	pkgList  []*types.Package
+	typList  []types.Type
+
+	debugFormat bool
+	read        int // bytes read
+}
+
+func (p *importer) declare(obj types.Object) {
+	if alt := p.pkgList[0].Scope().Insert(obj); alt != nil {
+		// This can only happen if we import a package a second time.
+		panic(fmt.Sprintf("%s already declared", alt.Name()))
+	}
+}
+
+func (p *importer) pkg() *types.Package {
+	// if the package was seen before, i is its index (>= 0)
+	i := p.tagOrIndex()
+	if i >= 0 {
+		return p.pkgList[i]
+	}
+
+	// otherwise, i is the package tag (< 0)
+	if i != packageTag {
+		panic(fmt.Sprintf("unexpected package tag %d", i))
+	}
+
+	// read package data
+	name := p.string()
+	path := p.string()
+
+	// we should never see an empty package name
+	if name == "" {
+		panic("empty package name in import")
+	}
+
+	// we should never see an empty import path
+	if path == "" {
+		panic("empty import path")
+	}
+
+	// if the package was imported before, use that one; otherwise create a new one
+	pkg := p.imports[path]
+	if pkg == nil {
+		pkg = types.NewPackage(path, name)
+		p.imports[path] = pkg
+	}
+	p.pkgList = append(p.pkgList, pkg)
+
+	return pkg
+}
+
+func (p *importer) record(t types.Type) {
+	p.typList = append(p.typList, t)
+}
+
+// A dddSlice is a types.Type representing ...T parameters.
+// It only appears for parameter types and does not escape
+// the importer.
+type dddSlice struct {
+	elem types.Type
+}
+
+func (t *dddSlice) Underlying() types.Type { return t }
+func (t *dddSlice) String() string         { return "..." + t.elem.String() }
+
+// parent is the package which declared the type; parent == nil means
+// the package currently imported. The parent package is needed for
+// exported struct fields and interface methods which don't contain
+// explicit package information in the export data.
+func (p *importer) typ(parent *types.Package) types.Type {
+	// if the type was seen before, i is its index (>= 0)
+	i := p.tagOrIndex()
+	if i >= 0 {
+		return p.typList[i]
+	}
+
+	// otherwise, i is the type tag (< 0)
+	switch i {
+	case namedTag:
+		// read type object
+		name := p.string()
+		parent = p.pkg()
+		scope := parent.Scope()
+		obj := scope.Lookup(name)
+
+		// if the object doesn't exist yet, create and insert it
+		if obj == nil {
+			obj = types.NewTypeName(token.NoPos, parent, name, nil)
+			scope.Insert(obj)
+		}
+
+		if _, ok := obj.(*types.TypeName); !ok {
+			panic(fmt.Sprintf("pkg = %s, name = %s => %s", parent, name, obj))
+		}
+
+		// associate new named type with obj if it doesn't exist yet
+		t0 := types.NewNamed(obj.(*types.TypeName), nil, nil)
+
+		// but record the existing type, if any
+		t := obj.Type().(*types.Named)
+		p.record(t)
+
+		// read underlying type
+		t0.SetUnderlying(p.typ(parent))
+
+		// interfaces don't have associated methods
+		if _, ok := t0.Underlying().(*types.Interface); ok {
+			return t
+		}
+
+		// read associated methods
+		for i := p.int(); i > 0; i-- {
+			name := p.string()
+			recv, _ := p.paramList() // TODO(gri) do we need a full param list for the receiver?
+			params, isddd := p.paramList()
+			result, _ := p.paramList()
+			p.int() // read and discard index of inlined function body
+			sig := types.NewSignature(recv.At(0), params, result, isddd)
+			t0.AddMethod(types.NewFunc(token.NoPos, parent, name, sig))
+		}
+
+		return t
+
+	case arrayTag:
+		t := new(types.Array)
+		p.record(t)
+
+		n := p.int64()
+		*t = *types.NewArray(p.typ(parent), n)
+		return t
+
+	case sliceTag:
+		t := new(types.Slice)
+		p.record(t)
+
+		*t = *types.NewSlice(p.typ(parent))
+		return t
+
+	case dddTag:
+		t := new(dddSlice)
+		p.record(t)
+
+		t.elem = p.typ(parent)
+		return t
+
+	case structTag:
+		t := new(types.Struct)
+		p.record(t)
+
+		n := p.int()
+		fields := make([]*types.Var, n)
+		tags := make([]string, n)
+		for i := range fields {
+			fields[i] = p.field(parent)
+			tags[i] = p.string()
+		}
+		*t = *types.NewStruct(fields, tags)
+		return t
+
+	case pointerTag:
+		t := new(types.Pointer)
+		p.record(t)
+
+		*t = *types.NewPointer(p.typ(parent))
+		return t
+
+	case signatureTag:
+		t := new(types.Signature)
+		p.record(t)
+
+		params, isddd := p.paramList()
+		result, _ := p.paramList()
+		*t = *types.NewSignature(nil, params, result, isddd)
+		return t
+
+	case interfaceTag:
+		// Create a dummy entry in the type list. This is safe because we
+		// cannot expect the interface type to appear in a cycle, as any
+		// such cycle must contain a named type which would have been
+		// first defined earlier.
+		n := len(p.typList)
+		p.record(nil)
+
+		// no embedded interfaces with gc compiler
+		if p.int() != 0 {
+			panic("unexpected embedded interface")
+		}
+
+		// read methods
+		methods := make([]*types.Func, p.int())
+		for i := range methods {
+			pkg, name := p.fieldName(parent)
+			params, isddd := p.paramList()
+			result, _ := p.paramList()
+			sig := types.NewSignature(nil, params, result, isddd)
+			methods[i] = types.NewFunc(token.NoPos, pkg, name, sig)
+		}
+
+		t := types.NewInterface(methods, nil)
+		p.typList[n] = t
+		return t
+
+	case mapTag:
+		t := new(types.Map)
+		p.record(t)
+
+		key := p.typ(parent)
+		val := p.typ(parent)
+		*t = *types.NewMap(key, val)
+		return t
+
+	case chanTag:
+		t := new(types.Chan)
+		p.record(t)
+
+		var dir types.ChanDir
+		// tag values must match the constants in cmd/compile/internal/gc/go.go
+		switch d := p.int(); d {
+		case 1 /* Crecv */ :
+			dir = types.RecvOnly
+		case 2 /* Csend */ :
+			dir = types.SendOnly
+		case 3 /* Cboth */ :
+			dir = types.SendRecv
+		default:
+			panic(fmt.Sprintf("unexpected channel dir %d", d))
+		}
+		val := p.typ(parent)
+		*t = *types.NewChan(dir, val)
+		return t
+
+	default:
+		panic(fmt.Sprintf("unexpected type tag %d", i))
+	}
+}
+
+func (p *importer) field(parent *types.Package) *types.Var {
+	pkg, name := p.fieldName(parent)
+	typ := p.typ(parent)
+
+	anonymous := false
+	if name == "" {
+		// anonymous field - typ must be T or *T and T must be a type name
+		switch typ := deref(typ).(type) {
+		case *types.Basic: // basic types are named types
+			pkg = nil // // objects defined in Universe scope have no package
+			name = typ.Name()
+		case *types.Named:
+			name = typ.Obj().Name()
+		default:
+			panic("anonymous field expected")
+		}
+		anonymous = true
+	}
+
+	return types.NewField(token.NoPos, pkg, name, typ, anonymous)
+}
+
+func (p *importer) fieldName(parent *types.Package) (*types.Package, string) {
+	pkg := parent
+	if pkg == nil {
+		// use the imported package instead
+		pkg = p.pkgList[0]
+	}
+	name := p.string()
+	if name == "" {
+		return pkg, "" // anonymous
+	}
+	if name == "?" || name != "_" && !exported(name) {
+		// explicitly qualified field
+		if name == "?" {
+			name = "" // anonymous
+		}
+		pkg = p.pkg()
+	}
+	return pkg, name
+}
+
+func (p *importer) paramList() (*types.Tuple, bool) {
+	n := p.int()
+	if n == 0 {
+		return nil, false
+	}
+	// negative length indicates unnamed parameters
+	named := true
+	if n < 0 {
+		n = -n
+		named = false
+	}
+	// n > 0
+	params := make([]*types.Var, n)
+	isddd := false
+	for i := range params {
+		params[i], isddd = p.param(named)
+	}
+	return types.NewTuple(params...), isddd
+}
+
+func (p *importer) param(named bool) (*types.Var, bool) {
+	t := p.typ(nil)
+	td, isddd := t.(*dddSlice)
+	if isddd {
+		t = types.NewSlice(td.elem)
+	}
+
+	var name string
+	if named {
+		name = p.string()
+		if name == "" {
+			panic("expected named parameter")
+		}
+	}
+
+	// read and discard compiler-specific info
+	p.string()
+
+	return types.NewVar(token.NoPos, nil, name, t), isddd
+}
+
+func exported(name string) bool {
+	ch, _ := utf8.DecodeRuneInString(name)
+	return unicode.IsUpper(ch)
+}
+
+func (p *importer) value() constant.Value {
+	switch tag := p.tagOrIndex(); tag {
+	case falseTag:
+		return constant.MakeBool(false)
+	case trueTag:
+		return constant.MakeBool(true)
+	case int64Tag:
+		return constant.MakeInt64(p.int64())
+	case floatTag:
+		return p.float()
+	case complexTag:
+		re := p.float()
+		im := p.float()
+		return constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
+	case stringTag:
+		return constant.MakeString(p.string())
+	default:
+		panic(fmt.Sprintf("unexpected value tag %d", tag))
+	}
+}
+
+func (p *importer) float() constant.Value {
+	sign := p.int()
+	if sign == 0 {
+		return constant.MakeInt64(0)
+	}
+
+	exp := p.int()
+	mant := []byte(p.string()) // big endian
+
+	// remove leading 0's if any
+	for len(mant) > 0 && mant[0] == 0 {
+		mant = mant[1:]
+	}
+
+	// convert to little endian
+	// TODO(gri) go/constant should have a more direct conversion function
+	//           (e.g., once it supports a big.Float based implementation)
+	for i, j := 0, len(mant)-1; i < j; i, j = i+1, j-1 {
+		mant[i], mant[j] = mant[j], mant[i]
+	}
+
+	// adjust exponent (constant.MakeFromBytes creates an integer value,
+	// but mant represents the mantissa bits such that 0.5 <= mant < 1.0)
+	exp -= len(mant) << 3
+	if len(mant) > 0 {
+		for msd := mant[len(mant)-1]; msd&0x80 == 0; msd <<= 1 {
+			exp++
+		}
+	}
+
+	x := constant.MakeFromBytes(mant)
+	switch {
+	case exp < 0:
+		d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp))
+		x = constant.BinaryOp(x, token.QUO, d)
+	case exp > 0:
+		x = constant.Shift(x, token.SHL, uint(exp))
+	}
+
+	if sign < 0 {
+		x = constant.UnaryOp(token.SUB, x, 0)
+	}
+	return x
+}
+
+// ----------------------------------------------------------------------------
+// Low-level decoders
+
+func (p *importer) tagOrIndex() int {
+	if p.debugFormat {
+		p.marker('t')
+	}
+
+	return int(p.rawInt64())
+}
+
+func (p *importer) int() int {
+	x := p.int64()
+	if int64(int(x)) != x {
+		panic("exported integer too large")
+	}
+	return int(x)
+}
+
+func (p *importer) int64() int64 {
+	if p.debugFormat {
+		p.marker('i')
+	}
+
+	return p.rawInt64()
+}
+
+func (p *importer) string() string {
+	if p.debugFormat {
+		p.marker('s')
+	}
+
+	if n := int(p.rawInt64()); n > 0 {
+		if cap(p.buf) < n {
+			p.buf = make([]byte, n)
+		} else {
+			p.buf = p.buf[:n]
+		}
+		for i := 0; i < n; i++ {
+			p.buf[i] = p.byte()
+		}
+		return string(p.buf)
+	}
+
+	return ""
+}
+
+func (p *importer) marker(want byte) {
+	if got := p.byte(); got != want {
+		panic(fmt.Sprintf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read))
+	}
+
+	pos := p.read
+	if n := int(p.rawInt64()); n != pos {
+		panic(fmt.Sprintf("incorrect position: got %d; want %d", n, pos))
+	}
+}
+
+// rawInt64 should only be used by low-level decoders
+func (p *importer) rawInt64() int64 {
+	i, err := binary.ReadVarint(p)
+	if err != nil {
+		panic(fmt.Sprintf("read error: %v", err))
+	}
+	return i
+}
+
+// needed for binary.ReadVarint in rawInt64
+func (p *importer) ReadByte() (byte, error) {
+	return p.byte(), nil
+}
+
+// byte is the bottleneck interface for reading p.data.
+// It unescapes '|' 'S' to '$' and '|' '|' to '|'.
+func (p *importer) byte() byte {
+	b := p.data[0]
+	r := 1
+	if b == '|' {
+		b = p.data[1]
+		r = 2
+		switch b {
+		case 'S':
+			b = '$'
+		case '|':
+			// nothing to do
+		default:
+			panic("unexpected escape sequence in export data")
+		}
+	}
+	p.data = p.data[r:]
+	p.read += r
+	return b
+
+}
+
+// ----------------------------------------------------------------------------
+// Export format
+
+// Tags. Must be < 0.
+const (
+	// Packages
+	packageTag = -(iota + 1)
+
+	// Types
+	namedTag
+	arrayTag
+	sliceTag
+	dddTag
+	structTag
+	pointerTag
+	signatureTag
+	interfaceTag
+	mapTag
+	chanTag
+
+	// Values
+	falseTag
+	trueTag
+	int64Tag
+	floatTag
+	fractionTag // not used by gc
+	complexTag
+	stringTag
+)
+
+var predeclared = []types.Type{
+	// basic types
+	types.Typ[types.Bool],
+	types.Typ[types.Int],
+	types.Typ[types.Int8],
+	types.Typ[types.Int16],
+	types.Typ[types.Int32],
+	types.Typ[types.Int64],
+	types.Typ[types.Uint],
+	types.Typ[types.Uint8],
+	types.Typ[types.Uint16],
+	types.Typ[types.Uint32],
+	types.Typ[types.Uint64],
+	types.Typ[types.Uintptr],
+	types.Typ[types.Float32],
+	types.Typ[types.Float64],
+	types.Typ[types.Complex64],
+	types.Typ[types.Complex128],
+	types.Typ[types.String],
+
+	// aliases
+	types.Universe.Lookup("byte").Type(),
+	types.Universe.Lookup("rune").Type(),
+
+	// error
+	types.Universe.Lookup("error").Type(),
+
+	// untyped types
+	types.Typ[types.UntypedBool],
+	types.Typ[types.UntypedInt],
+	types.Typ[types.UntypedRune],
+	types.Typ[types.UntypedFloat],
+	types.Typ[types.UntypedComplex],
+	types.Typ[types.UntypedString],
+	types.Typ[types.UntypedNil],
+
+	// package unsafe
+	types.Typ[types.UnsafePointer],
+}
diff --git a/src/go/internal/gcimporter/exportdata.go b/src/go/internal/gcimporter/exportdata.go
index 657742b..18bea41 100644
--- a/src/go/internal/gcimporter/exportdata.go
+++ b/src/go/internal/gcimporter/exportdata.go
@@ -39,14 +39,16 @@ func readGopackHeader(r *bufio.Reader) (name string, size int, err error) {
 // FindExportData positions the reader r at the beginning of the
 // export data section of an underlying GC-created object/archive
 // file by reading from it. The reader must be positioned at the
-// start of the file before calling this function.
+// start of the file before calling this function. The hdr result
+// is the string before the export data, either "$$" or "$$B".
 //
-func FindExportData(r *bufio.Reader) (err error) {
+func FindExportData(r *bufio.Reader) (hdr string, err error) {
 	// Read first line to make sure this is an object file.
 	line, err := r.ReadSlice('\n')
 	if err != nil {
 		return
 	}
+
 	if string(line) == "!<arch>\n" {
 		// Archive file. Scan to __.PKGDEF.
 		var name string
@@ -71,7 +73,7 @@ func FindExportData(r *bufio.Reader) (err error) {
 				size -= n
 			}
 
-			if name, size, err = readGopackHeader(r); err != nil {
+			if name, _, err = readGopackHeader(r); err != nil {
 				return
 			}
 		}
@@ -97,12 +99,13 @@ func FindExportData(r *bufio.Reader) (err error) {
 	}
 
 	// Skip over object header to export data.
-	// Begins after first line with $$.
+	// Begins after first line starting with $$.
 	for line[0] != '$' {
 		if line, err = r.ReadSlice('\n'); err != nil {
 			return
 		}
 	}
+	hdr = string(line)
 
 	return
 }
diff --git a/src/go/internal/gcimporter/gcimporter.go b/src/go/internal/gcimporter/gcimporter.go
index 1d485cf..d70ec08 100644
--- a/src/go/internal/gcimporter/gcimporter.go
+++ b/src/go/internal/gcimporter/gcimporter.go
@@ -12,6 +12,7 @@ import (
 	"go/build"
 	"go/token"
 	"io"
+	"io/ioutil"
 	"os"
 	"path/filepath"
 	"sort"
@@ -30,25 +31,29 @@ var pkgExts = [...]string{".a", ".o"}
 
 // FindPkg returns the filename and unique package id for an import
 // path based on package information provided by build.Import (using
-// the build.Default build.Context).
+// the build.Default build.Context). A relative srcDir is interpreted
+// relative to the current working directory.
 // If no file was found, an empty filename is returned.
 //
 func FindPkg(path, srcDir string) (filename, id string) {
-	if len(path) == 0 {
+	if path == "" {
 		return
 	}
 
-	id = path
 	var noext string
 	switch {
 	default:
 		// "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x"
 		// Don't require the source files to be present.
+		if abs, err := filepath.Abs(srcDir); err == nil { // see issue 14282
+			srcDir = abs
+		}
 		bp, _ := build.Import(path, srcDir, build.FindOnly|build.AllowBinary)
 		if bp.PkgObj == "" {
 			return
 		}
 		noext = strings.TrimSuffix(bp.PkgObj, ".a")
+		id = bp.ImportPath
 
 	case build.IsLocalImport(path):
 		// "./x" -> "/this/directory/x.ext", "/this/directory/x"
@@ -60,6 +65,13 @@ func FindPkg(path, srcDir string) (filename, id string) {
 		// does not support absolute imports
 		// "/x" -> "/x.ext", "/x"
 		noext = path
+		id = path
+	}
+
+	if false { // for debugging
+		if path != id {
+			fmt.Printf("%s -> %s\n", path, id)
+		}
 	}
 
 	// try extensions
@@ -106,27 +118,16 @@ func ImportData(packages map[string]*types.Package, filename, id string, data io
 	return
 }
 
-// Import imports a gc-generated package given its import path, adds the
-// corresponding package object to the packages map, and returns the object.
-// Local import paths are interpreted relative to the current working directory.
+// Import imports a gc-generated package given its import path and srcDir, adds
+// the corresponding package object to the packages map, and returns the object.
 // The packages map must contain all packages already imported.
 //
-func Import(packages map[string]*types.Package, path string) (pkg *types.Package, err error) {
-	// package "unsafe" is handled by the type checker
-	if path == "unsafe" {
-		panic(`gcimporter.Import called for package "unsafe"`)
-	}
-
-	srcDir := "."
-	if build.IsLocalImport(path) {
-		srcDir, err = os.Getwd()
-		if err != nil {
-			return
-		}
-	}
-
+func Import(packages map[string]*types.Package, path, srcDir string) (pkg *types.Package, err error) {
 	filename, id := FindPkg(path, srcDir)
 	if filename == "" {
+		if path == "unsafe" {
+			return types.Unsafe, nil
+		}
 		err = fmt.Errorf("can't find import: %s", id)
 		return
 	}
@@ -149,12 +150,25 @@ func Import(packages map[string]*types.Package, path string) (pkg *types.Package
 		}
 	}()
 
+	var hdr string
 	buf := bufio.NewReader(f)
-	if err = FindExportData(buf); err != nil {
+	if hdr, err = FindExportData(buf); err != nil {
 		return
 	}
 
-	pkg, err = ImportData(packages, filename, id, buf)
+	switch hdr {
+	case "$$\n":
+		return ImportData(packages, filename, id, buf)
+	case "$$B\n":
+		var data []byte
+		data, err = ioutil.ReadAll(buf)
+		if err == nil {
+			_, pkg, err = BImportData(packages, data, path)
+			return
+		}
+	default:
+		err = fmt.Errorf("unknown export data header: %q", hdr)
+	}
 
 	return
 }
@@ -335,8 +349,10 @@ func (p *parser) parseQualifiedName() (id, name string) {
 }
 
 // getPkg returns the package for a given id. If the package is
-// not found but we have a package name, create the package and
-// add it to the p.localPkgs and p.sharedPkgs maps.
+// not found, create the package and add it to the p.localPkgs
+// and p.sharedPkgs maps. name is the (expected) name of the
+// package. If name == "", the package name is expected to be
+// set later via an import clause in the export data.
 //
 // id identifies a package, usually by a canonical package path like
 // "encoding/json" but possibly by a non-canonical import path like
@@ -349,19 +365,28 @@ func (p *parser) getPkg(id, name string) *types.Package {
 	}
 
 	pkg := p.localPkgs[id]
-	if pkg == nil && name != "" {
+	if pkg == nil {
 		// first import of id from this package
 		pkg = p.sharedPkgs[id]
 		if pkg == nil {
-			// first import of id by this importer
+			// first import of id by this importer;
+			// add (possibly unnamed) pkg to shared packages
 			pkg = types.NewPackage(id, name)
 			p.sharedPkgs[id] = pkg
 		}
-
+		// add (possibly unnamed) pkg to local packages
 		if p.localPkgs == nil {
 			p.localPkgs = make(map[string]*types.Package)
 		}
 		p.localPkgs[id] = pkg
+	} else if name != "" {
+		// package exists already and we have an expected package name;
+		// make sure names match or set package name if necessary
+		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)
+		}
 	}
 	return pkg
 }
@@ -372,9 +397,6 @@ func (p *parser) getPkg(id, name string) *types.Package {
 func (p *parser) parseExportedName() (pkg *types.Package, name string) {
 	id, name := p.parseQualifiedName()
 	pkg = p.getPkg(id, "")
-	if pkg == nil {
-		p.errorf("%s package not found", id)
-	}
 	return
 }
 
@@ -395,11 +417,11 @@ func (p *parser) parseBasicType() types.Type {
 
 // ArrayType = "[" int_lit "]" Type .
 //
-func (p *parser) parseArrayType() types.Type {
+func (p *parser) parseArrayType(parent *types.Package) types.Type {
 	// "[" already consumed and lookahead known not to be "]"
 	lit := p.expect(scanner.Int)
 	p.expect(']')
-	elem := p.parseType()
+	elem := p.parseType(parent)
 	n, err := strconv.ParseInt(lit, 10, 64)
 	if err != nil {
 		p.error(err)
@@ -409,46 +431,47 @@ func (p *parser) parseArrayType() types.Type {
 
 // MapType = "map" "[" Type "]" Type .
 //
-func (p *parser) parseMapType() types.Type {
+func (p *parser) parseMapType(parent *types.Package) types.Type {
 	p.expectKeyword("map")
 	p.expect('[')
-	key := p.parseType()
+	key := p.parseType(parent)
 	p.expect(']')
-	elem := p.parseType()
+	elem := p.parseType(parent)
 	return types.NewMap(key, elem)
 }
 
 // Name = identifier | "?" | QualifiedName .
 //
-// If materializePkg is set, the returned package is guaranteed to be set.
-// For fully qualified names, the returned package may be a fake package
-// (without name, scope, and not in the p.sharedPkgs map), created for the
-// sole purpose of providing a package path. Fake packages are created
-// when the package id is not found in the p.sharedPkgs map; in that case
-// we cannot create a real package because we don't have a package name.
-// For non-qualified names, the returned package is the imported package.
+// For unqualified and anonymous names, the returned package is the parent
+// package unless parent == nil, in which case the returned package is the
+// package being imported. (The parent package is not nil if the the name
+// is an unqualified struct field or interface method name belonging to a
+// type declared in another package.)
+//
+// For qualified names, the returned package is nil (and not created if
+// it doesn't exist yet) unless materializePkg is set (which creates an
+// unnamed package with valid package path). In the latter case, a
+// subequent import clause is expected to provide a name for the package.
 //
-func (p *parser) parseName(materializePkg bool) (pkg *types.Package, name string) {
+func (p *parser) parseName(parent *types.Package, materializePkg bool) (pkg *types.Package, name string) {
+	pkg = parent
+	if pkg == nil {
+		pkg = p.sharedPkgs[p.id]
+	}
 	switch p.tok {
 	case scanner.Ident:
-		pkg = p.sharedPkgs[p.id]
 		name = p.lit
 		p.next()
 	case '?':
 		// anonymous
-		pkg = p.sharedPkgs[p.id]
 		p.next()
 	case '@':
 		// exported name prefixed with package path
+		pkg = nil
 		var id string
 		id, name = p.parseQualifiedName()
 		if materializePkg {
-			// we don't have a package name - if the package
-			// doesn't exist yet, create a fake package instead
 			pkg = p.getPkg(id, "")
-			if pkg == nil {
-				pkg = types.NewPackage(id, "")
-			}
 		}
 	default:
 		p.error("name expected")
@@ -465,15 +488,15 @@ func deref(typ types.Type) types.Type {
 
 // Field = Name Type [ string_lit ] .
 //
-func (p *parser) parseField() (*types.Var, string) {
-	pkg, name := p.parseName(true)
-	typ := p.parseType()
+func (p *parser) parseField(parent *types.Package) (*types.Var, string) {
+	pkg, name := p.parseName(parent, true)
+	typ := p.parseType(parent)
 	anonymous := false
 	if name == "" {
 		// anonymous field - typ must be T or *T and T must be a type name
 		switch typ := deref(typ).(type) {
 		case *types.Basic: // basic types are named types
-			pkg = nil
+			pkg = nil // objects defined in Universe scope have no package
 			name = typ.Name()
 		case *types.Named:
 			name = typ.Obj().Name()
@@ -497,7 +520,7 @@ func (p *parser) parseField() (*types.Var, string) {
 // StructType = "struct" "{" [ FieldList ] "}" .
 // FieldList  = Field { ";" Field } .
 //
-func (p *parser) parseStructType() types.Type {
+func (p *parser) parseStructType(parent *types.Package) types.Type {
 	var fields []*types.Var
 	var tags []string
 
@@ -507,7 +530,7 @@ func (p *parser) parseStructType() types.Type {
 		if i > 0 {
 			p.expect(';')
 		}
-		fld, tag := p.parseField()
+		fld, tag := p.parseField(parent)
 		if tag != "" && tags == nil {
 			tags = make([]string, i)
 		}
@@ -524,7 +547,7 @@ func (p *parser) parseStructType() types.Type {
 // Parameter = ( identifier | "?" ) [ "..." ] Type [ string_lit ] .
 //
 func (p *parser) parseParameter() (par *types.Var, isVariadic bool) {
-	_, name := p.parseName(false)
+	_, name := p.parseName(nil, false)
 	// remove gc-specific parameter numbering
 	if i := strings.Index(name, "·"); i >= 0 {
 		name = name[:i]
@@ -533,7 +556,7 @@ func (p *parser) parseParameter() (par *types.Var, isVariadic bool) {
 		p.expectSpecial("...")
 		isVariadic = true
 	}
-	typ := p.parseType()
+	typ := p.parseType(nil)
 	if isVariadic {
 		typ = types.NewSlice(typ)
 	}
@@ -596,7 +619,7 @@ func (p *parser) parseSignature(recv *types.Var) *types.Signature {
 // by the compiler and thus embedded interfaces are never
 // visible in the export data.
 //
-func (p *parser) parseInterfaceType() types.Type {
+func (p *parser) parseInterfaceType(parent *types.Package) types.Type {
 	var methods []*types.Func
 
 	p.expectKeyword("interface")
@@ -605,7 +628,7 @@ func (p *parser) parseInterfaceType() types.Type {
 		if i > 0 {
 			p.expect(';')
 		}
-		pkg, name := p.parseName(true)
+		pkg, name := p.parseName(parent, true)
 		sig := p.parseSignature(nil)
 		methods = append(methods, types.NewFunc(token.NoPos, pkg, name, sig))
 	}
@@ -618,7 +641,7 @@ func (p *parser) parseInterfaceType() types.Type {
 
 // ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type .
 //
-func (p *parser) parseChanType() types.Type {
+func (p *parser) parseChanType(parent *types.Package) types.Type {
 	dir := types.SendRecv
 	if p.tok == scanner.Ident {
 		p.expectKeyword("chan")
@@ -631,7 +654,7 @@ func (p *parser) parseChanType() types.Type {
 		p.expectKeyword("chan")
 		dir = types.RecvOnly
 	}
-	elem := p.parseType()
+	elem := p.parseType(parent)
 	return types.NewChan(dir, elem)
 }
 
@@ -646,24 +669,24 @@ func (p *parser) parseChanType() types.Type {
 // PointerType = "*" Type .
 // FuncType    = "func" Signature .
 //
-func (p *parser) parseType() types.Type {
+func (p *parser) parseType(parent *types.Package) types.Type {
 	switch p.tok {
 	case scanner.Ident:
 		switch p.lit {
 		default:
 			return p.parseBasicType()
 		case "struct":
-			return p.parseStructType()
+			return p.parseStructType(parent)
 		case "func":
 			// FuncType
 			p.next()
 			return p.parseSignature(nil)
 		case "interface":
-			return p.parseInterfaceType()
+			return p.parseInterfaceType(parent)
 		case "map":
-			return p.parseMapType()
+			return p.parseMapType(parent)
 		case "chan":
-			return p.parseChanType()
+			return p.parseChanType(parent)
 		}
 	case '@':
 		// TypeName
@@ -674,19 +697,19 @@ func (p *parser) parseType() types.Type {
 		if p.tok == ']' {
 			// SliceType
 			p.next()
-			return types.NewSlice(p.parseType())
+			return types.NewSlice(p.parseType(parent))
 		}
-		return p.parseArrayType()
+		return p.parseArrayType(parent)
 	case '*':
 		// PointerType
 		p.next()
-		return types.NewPointer(p.parseType())
+		return types.NewPointer(p.parseType(parent))
 	case '<':
-		return p.parseChanType()
+		return p.parseChanType(parent)
 	case '(':
 		// "(" Type ")"
 		p.next()
-		typ := p.parseType()
+		typ := p.parseType(parent)
 		p.expect(')')
 		return typ
 	}
@@ -768,7 +791,8 @@ func (p *parser) parseConstDecl() {
 
 	var typ0 types.Type
 	if p.tok != '=' {
-		typ0 = p.parseType()
+		// constant types are never structured - no need for parent type
+		typ0 = p.parseType(nil)
 	}
 
 	p.expect('=')
@@ -842,7 +866,7 @@ func (p *parser) parseTypeDecl() {
 	// structure, but throw it away if the object already has a type.
 	// This ensures that all imports refer to the same type object for
 	// a given type declaration.
-	typ := p.parseType()
+	typ := p.parseType(pkg)
 
 	if name := obj.Type().(*types.Named); name.Underlying() == nil {
 		name.SetUnderlying(typ)
@@ -854,7 +878,7 @@ func (p *parser) parseTypeDecl() {
 func (p *parser) parseVarDecl() {
 	p.expectKeyword("var")
 	pkg, name := p.parseExportedName()
-	typ := p.parseType()
+	typ := p.parseType(pkg)
 	pkg.Scope().Insert(types.NewVar(token.NoPos, pkg, name, typ))
 }
 
@@ -890,7 +914,7 @@ func (p *parser) parseMethodDecl() {
 	base := deref(recv.Type()).(*types.Named)
 
 	// parse method name, signature, and possibly inlined body
-	_, name := p.parseName(true)
+	_, name := p.parseName(nil, false)
 	sig := p.parseFunc(recv)
 
 	// methods always belong to the same package as the base type object
@@ -967,9 +991,12 @@ func (p *parser) parseExport() *types.Package {
 		p.errorf("expected no scanner errors, got %d", n)
 	}
 
-	// Record all referenced packages as imports.
+	// Record all locally referenced packages as imports.
 	var imports []*types.Package
 	for id, pkg2 := range p.localPkgs {
+		if pkg2.Name() == "" {
+			p.errorf("%s package has no name", id)
+		}
 		if id == p.id {
 			continue // avoid self-edge
 		}
diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go
index 07993a8..e56720b 100644
--- a/src/go/internal/gcimporter/gcimporter_test.go
+++ b/src/go/internal/gcimporter/gcimporter_test.go
@@ -46,13 +46,23 @@ func compile(t *testing.T, dirname, filename string) string {
 	return filepath.Join(dirname, filename[:len(filename)-2]+"o")
 }
 
-// Use the same global imports map for all tests. The effect is
-// as if all tested packages were imported into a single package.
-var imports = make(map[string]*types.Package)
+// TODO(gri) Remove this function once we switched to new export format by default.
+func compileNewExport(t *testing.T, dirname, filename string) string {
+	testenv.MustHaveGoBuild(t)
+	cmd := exec.Command("go", "tool", "compile", "-newexport", filename)
+	cmd.Dir = dirname
+	out, err := cmd.CombinedOutput()
+	if err != nil {
+		t.Logf("%s", out)
+		t.Fatalf("go tool compile %s failed: %s", filename, err)
+	}
+	// filename should end with ".go"
+	return filepath.Join(dirname, filename[:len(filename)-2]+"o")
+}
 
-func testPath(t *testing.T, path string) *types.Package {
+func testPath(t *testing.T, path, srcDir string) *types.Package {
 	t0 := time.Now()
-	pkg, err := Import(imports, path)
+	pkg, err := Import(make(map[string]*types.Package), path, srcDir)
 	if err != nil {
 		t.Errorf("testPath(%s): %s", path, err)
 		return nil
@@ -80,7 +90,7 @@ func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) {
 			for _, ext := range pkgExts {
 				if strings.HasSuffix(f.Name(), ext) {
 					name := f.Name()[0 : len(f.Name())-len(ext)] // remove extension
-					if testPath(t, filepath.Join(dir, name)) != nil {
+					if testPath(t, filepath.Join(dir, name), dir) != nil {
 						nimports++
 					}
 				}
@@ -92,7 +102,7 @@ func testDir(t *testing.T, dir string, endTime time.Time) (nimports int) {
 	return
 }
 
-func TestImport(t *testing.T) {
+func TestImportTestdata(t *testing.T) {
 	// This package only handles gc export data.
 	if runtime.Compiler != "gc" {
 		t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
@@ -103,20 +113,62 @@ func TestImport(t *testing.T) {
 		defer os.Remove(outFn)
 	}
 
-	nimports := 0
-	if pkg := testPath(t, "./testdata/exports"); pkg != nil {
-		nimports++
-		// The package's Imports should include all the types
-		// referenced by the exportdata, which may be more than
-		// the import statements in the package's source, but
-		// fewer than the transitive closure of dependencies.
-		want := `[package ast ("go/ast") package token ("go/token") package runtime ("runtime")]`
+	if pkg := testPath(t, "./testdata/exports", "."); pkg != nil {
+		// The package's Imports list must include all packages
+		// explicitly imported by exports.go, plus all packages
+		// referenced indirectly via exported objects in exports.go.
+		// With the textual export format, the list may also include
+		// additional packages that are not strictly required for
+		// import processing alone (they are exported to err "on
+		// the safe side").
+		got := fmt.Sprint(pkg.Imports())
+		for _, want := range []string{"go/ast", "go/token"} {
+			if !strings.Contains(got, want) {
+				t.Errorf(`Package("exports").Imports() = %s, does not contain %s`, got, want)
+			}
+		}
+	}
+}
+
+// TODO(gri) Remove this function once we switched to new export format by default
+//           (and update the comment and want list in TestImportTestdata).
+func TestImportTestdataNewExport(t *testing.T) {
+	// This package only handles gc export data.
+	if runtime.Compiler != "gc" {
+		t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+		return
+	}
+
+	if outFn := compileNewExport(t, "testdata", "exports.go"); outFn != "" {
+		defer os.Remove(outFn)
+	}
+
+	if pkg := testPath(t, "./testdata/exports", "."); pkg != nil {
+		// The package's Imports list must include all packages
+		// explicitly imported by exports.go, plus all packages
+		// referenced indirectly via exported objects in exports.go.
+		want := `[package ast ("go/ast") package token ("go/token")]`
 		got := fmt.Sprint(pkg.Imports())
 		if got != want {
 			t.Errorf(`Package("exports").Imports() = %s, want %s`, got, want)
 		}
 	}
-	nimports += testDir(t, "", time.Now().Add(maxTime)) // installed packages
+}
+
+func TestImportStdLib(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	// This package only handles gc export data.
+	if runtime.Compiler != "gc" {
+		t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+		return
+	}
+
+	dt := maxTime
+	if testing.Short() && testenv.Builder() == "" {
+		dt = 10 * time.Millisecond
+	}
+	nimports := testDir(t, "", time.Now().Add(dt)) // installed packages
 	t.Logf("tested %d imports", nimports)
 }
 
@@ -148,7 +200,7 @@ func TestImportedTypes(t *testing.T) {
 		importPath := s[0]
 		objName := s[1]
 
-		pkg, err := Import(imports, importPath)
+		pkg, err := Import(make(map[string]*types.Package), importPath, ".")
 		if err != nil {
 			t.Error(err)
 			continue
@@ -176,7 +228,7 @@ func TestIssue5815(t *testing.T) {
 		return
 	}
 
-	pkg, err := Import(make(map[string]*types.Package), "strings")
+	pkg, err := Import(make(map[string]*types.Package), "strings", ".")
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -210,7 +262,7 @@ func TestCorrectMethodPackage(t *testing.T) {
 	}
 
 	imports := make(map[string]*types.Package)
-	_, err := Import(imports, "net/http")
+	_, err := Import(imports, "net/http", ".")
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -223,3 +275,89 @@ func TestCorrectMethodPackage(t *testing.T) {
 		t.Errorf("got package path %q; want %q", got, want)
 	}
 }
+
+func TestIssue13566(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	// This package only handles gc export data.
+	if runtime.Compiler != "gc" {
+		t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+		return
+	}
+
+	// On windows, we have to set the -D option for the compiler to avoid having a drive
+	// letter and an illegal ':' in the import path - just skip it (see also issue #3483).
+	if runtime.GOOS == "windows" {
+		t.Skip("avoid dealing with relative paths/drive letters on windows")
+	}
+
+	if f := compile(t, "testdata", "a.go"); f != "" {
+		defer os.Remove(f)
+	}
+	if f := compile(t, "testdata", "b.go"); f != "" {
+		defer os.Remove(f)
+	}
+
+	// import must succeed (test for issue at hand)
+	pkg, err := Import(make(map[string]*types.Package), "./testdata/b", ".")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// make sure all indirectly imported packages have names
+	for _, imp := range pkg.Imports() {
+		if imp.Name() == "" {
+			t.Errorf("no name for %s package", imp.Path())
+		}
+	}
+}
+
+func TestIssue13898(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	// This package only handles gc export data.
+	if runtime.Compiler != "gc" {
+		t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+		return
+	}
+
+	// import go/internal/gcimporter which imports go/types partially
+	imports := make(map[string]*types.Package)
+	_, err := Import(imports, "go/internal/gcimporter", ".")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// look for go/types package
+	var goTypesPkg *types.Package
+	for path, pkg := range imports {
+		if path == "go/types" {
+			goTypesPkg = pkg
+			break
+		}
+	}
+	if goTypesPkg == nil {
+		t.Fatal("go/types not found")
+	}
+
+	// look for go/types.Object type
+	obj := goTypesPkg.Scope().Lookup("Object")
+	if obj == nil {
+		t.Fatal("go/types.Object not found")
+	}
+	typ, ok := obj.Type().(*types.Named)
+	if !ok {
+		t.Fatalf("go/types.Object type is %v; wanted named type", typ)
+	}
+
+	// lookup go/types.Object.Pkg method
+	m, _, _ := types.LookupFieldOrMethod(typ, false, nil, "Pkg")
+	if m == nil {
+		t.Fatal("go/types.Object.Pkg not found")
+	}
+
+	// the method must belong to go/types
+	if m.Pkg().Path() != "go/types" {
+		t.Fatalf("found %v; want go/types", m.Pkg())
+	}
+}
diff --git a/src/go/internal/gcimporter/testdata/a.go b/src/go/internal/gcimporter/testdata/a.go
new file mode 100644
index 0000000..56e4292
--- /dev/null
+++ b/src/go/internal/gcimporter/testdata/a.go
@@ -0,0 +1,14 @@
+// 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.
+
+// Input for TestIssue13566
+
+package a
+
+import "encoding/json"
+
+type A struct {
+	a    *A
+	json json.RawMessage
+}
diff --git a/src/go/internal/gcimporter/testdata/b.go b/src/go/internal/gcimporter/testdata/b.go
new file mode 100644
index 0000000..4196678
--- /dev/null
+++ b/src/go/internal/gcimporter/testdata/b.go
@@ -0,0 +1,11 @@
+// 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.
+
+// Input for TestIssue13566
+
+package b
+
+import "./a"
+
+type A a.A
diff --git a/src/go/parser/parser.go b/src/go/parser/parser.go
index e82c0bd..f3a2603 100644
--- a/src/go/parser/parser.go
+++ b/src/go/parser/parser.go
@@ -410,9 +410,14 @@ func (p *parser) expectClosing(tok token.Token, context string) token.Pos {
 func (p *parser) expectSemi() {
 	// semicolon is optional before a closing ')' or '}'
 	if p.tok != token.RPAREN && p.tok != token.RBRACE {
-		if p.tok == token.SEMICOLON {
+		switch p.tok {
+		case token.COMMA:
+			// permit a ',' instead of a ';' but complain
+			p.errorExpected(p.pos, "';'")
+			fallthrough
+		case token.SEMICOLON:
 			p.next()
-		} else {
+		default:
 			p.errorExpected(p.pos, "';'")
 			syncStmt(p)
 		}
@@ -690,16 +695,19 @@ func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field {
 
 	doc := p.leadComment
 
-	// FieldDecl
-	list, typ := p.parseVarList(false)
-
-	// Tag
-	var tag *ast.BasicLit
-	if p.tok == token.STRING {
-		tag = &ast.BasicLit{ValuePos: p.pos, Kind: p.tok, Value: p.lit}
+	// 1st FieldDecl
+	// A type name used as an anonymous field looks like a field identifier.
+	var list []ast.Expr
+	for {
+		list = append(list, p.parseVarType(false))
+		if p.tok != token.COMMA {
+			break
+		}
 		p.next()
 	}
 
+	typ := p.tryVarType(false)
+
 	// analyze case
 	var idents []*ast.Ident
 	if typ != nil {
@@ -708,13 +716,22 @@ func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field {
 	} else {
 		// ["*"] TypeName (AnonymousField)
 		typ = list[0] // we always have at least one element
-		if n := len(list); n > 1 || !isTypeName(deref(typ)) {
-			pos := typ.Pos()
-			p.errorExpected(pos, "anonymous field")
-			typ = &ast.BadExpr{From: pos, To: p.safePos(list[n-1].End())}
+		if n := len(list); n > 1 {
+			p.errorExpected(p.pos, "type")
+			typ = &ast.BadExpr{From: p.pos, To: p.pos}
+		} else if !isTypeName(deref(typ)) {
+			p.errorExpected(typ.Pos(), "anonymous field")
+			typ = &ast.BadExpr{From: typ.Pos(), To: p.safePos(typ.End())}
 		}
 	}
 
+	// Tag
+	var tag *ast.BasicLit
+	if p.tok == token.STRING {
+		tag = &ast.BasicLit{ValuePos: p.pos, Kind: p.tok, Value: p.lit}
+		p.next()
+	}
+
 	p.expectSemi() // call before accessing p.linecomment
 
 	field := &ast.Field{Doc: doc, Names: idents, Type: typ, Tag: tag, Comment: p.lineComment}
@@ -791,42 +808,27 @@ func (p *parser) parseVarType(isParam bool) ast.Expr {
 	return typ
 }
 
-// If any of the results are identifiers, they are not resolved.
-func (p *parser) parseVarList(isParam bool) (list []ast.Expr, typ ast.Expr) {
+func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params []*ast.Field) {
 	if p.trace {
-		defer un(trace(p, "VarList"))
+		defer un(trace(p, "ParameterList"))
 	}
 
-	// a list of identifiers looks like a list of type names
-	//
-	// parse/tryVarType accepts any type (including parenthesized
-	// ones) even though the syntax does not permit them here: we
-	// accept them all for more robust parsing and complain later
-	for typ := p.parseVarType(isParam); typ != nil; {
-		list = append(list, typ)
+	// 1st ParameterDecl
+	// A list of identifiers looks like a list of type names.
+	var list []ast.Expr
+	for {
+		list = append(list, p.parseVarType(ellipsisOk))
 		if p.tok != token.COMMA {
 			break
 		}
 		p.next()
-		typ = p.tryVarType(isParam) // maybe nil as in: func f(int,) {}
-	}
-
-	// if we had a list of identifiers, it must be followed by a type
-	typ = p.tryVarType(isParam)
-
-	return
-}
-
-func (p *parser) parseParameterList(scope *ast.Scope, ellipsisOk bool) (params []*ast.Field) {
-	if p.trace {
-		defer un(trace(p, "ParameterList"))
+		if p.tok == token.RPAREN {
+			break
+		}
 	}
 
-	// ParameterDecl
-	list, typ := p.parseVarList(ellipsisOk)
-
 	// analyze case
-	if typ != nil {
+	if typ := p.tryVarType(ellipsisOk); typ != nil {
 		// IdentifierList Type
 		idents := p.makeIdentList(list)
 		field := &ast.Field{Names: idents, Type: typ}
@@ -1855,7 +1857,16 @@ func (p *parser) parseIfStmt() *ast.IfStmt {
 	var else_ ast.Stmt
 	if p.tok == token.ELSE {
 		p.next()
-		else_ = p.parseStmt()
+		switch p.tok {
+		case token.IF:
+			else_ = p.parseIfStmt()
+		case token.LBRACE:
+			else_ = p.parseBlockStmt()
+			p.expectSemi()
+		default:
+			p.errorExpected(p.pos, "if statement or block")
+			else_ = &ast.BadStmt{From: p.pos, To: p.pos}
+		}
 	} else {
 		p.expectSemi()
 	}
@@ -1908,14 +1919,23 @@ func isTypeSwitchAssert(x ast.Expr) bool {
 	return ok && a.Type == nil
 }
 
-func isTypeSwitchGuard(s ast.Stmt) bool {
+func (p *parser) isTypeSwitchGuard(s ast.Stmt) bool {
 	switch t := s.(type) {
 	case *ast.ExprStmt:
-		// x.(nil)
+		// x.(type)
 		return isTypeSwitchAssert(t.X)
 	case *ast.AssignStmt:
-		// v := x.(nil)
-		return len(t.Lhs) == 1 && t.Tok == token.DEFINE && len(t.Rhs) == 1 && isTypeSwitchAssert(t.Rhs[0])
+		// v := x.(type)
+		if len(t.Lhs) == 1 && len(t.Rhs) == 1 && isTypeSwitchAssert(t.Rhs[0]) {
+			switch t.Tok {
+			case token.ASSIGN:
+				// permit v = x.(type) but complain
+				p.error(t.TokPos, "expected ':=', found '='")
+				fallthrough
+			case token.DEFINE:
+				return true
+			}
+		}
 	}
 	return false
 }
@@ -1961,7 +1981,7 @@ func (p *parser) parseSwitchStmt() ast.Stmt {
 		p.exprLev = prevLev
 	}
 
-	typeSwitch := isTypeSwitchGuard(s2)
+	typeSwitch := p.isTypeSwitchGuard(s2)
 	lbrace := p.expect(token.LBRACE)
 	var list []ast.Stmt
 	for p.tok == token.CASE || p.tok == token.DEFAULT {
diff --git a/src/go/parser/short_test.go b/src/go/parser/short_test.go
index ef2ffad..cdd343e 100644
--- a/src/go/parser/short_test.go
+++ b/src/go/parser/short_test.go
@@ -64,7 +64,7 @@ var invalids = []string{
 	`package p; func f() { for _ = range x ; /* ERROR "expected '{'" */ ; {} };`,
 	`package p; func f() { for ; ; _ = range /* ERROR "expected operand" */ x {} };`,
 	`package p; func f() { for ; _ /* ERROR "expected boolean or range expression" */ = range x ; {} };`,
-	`package p; func f() { switch t /* ERROR "expected switch expression" */ = t.(type) {} };`,
+	`package p; func f() { switch t = /* ERROR "expected ':=', found '='" */ t.(type) {} };`,
 	`package p; func f() { switch t /* ERROR "expected switch expression" */ , t = t.(type) {} };`,
 	`package p; func f() { switch t /* ERROR "expected switch expression" */ = t.(type), t {} };`,
 	`package p; var a = [ /* ERROR "expected expression" */ 1]int;`,
@@ -101,11 +101,30 @@ var invalids = []string{
 	`package p; func f() { defer func() {} /* ERROR HERE "function must be invoked" */ }`,
 	`package p; func f() { go func() { func() { f(x func /* ERROR "missing ','" */ (){}) } } }`,
 	`package p; func f(x func(), u v func /* ERROR "missing ','" */ ()){}`,
-	`package p; func f() (a b string /* ERROR "missing ','" */ , ok bool)`,           // issue 8656
-	`package p; var x /* ERROR "missing variable type or initialization" */ , y, z;`, // issue 9639
-	`package p; const x /* ERROR "missing constant value" */ ;`,                      // issue 9639
-	`package p; const x /* ERROR "missing constant value" */ int;`,                   // issue 9639
-	`package p; const (x = 0; y; z /* ERROR "missing constant value" */ int);`,       // issue 9639
+
+	// issue 8656
+	`package p; func f() (a b string /* ERROR "missing ','" */ , ok bool)`,
+
+	// issue 9639
+	`package p; var x /* ERROR "missing variable type or initialization" */ , y, z;`,
+	`package p; const x /* ERROR "missing constant value" */ ;`,
+	`package p; const x /* ERROR "missing constant value" */ int;`,
+	`package p; const (x = 0; y; z /* ERROR "missing constant value" */ int);`,
+
+	// issue 12437
+	`package p; var _ = struct { x int, /* ERROR "expected ';', found ','" */ }{};`,
+	`package p; var _ = struct { x int, /* ERROR "expected ';', found ','" */ y float }{};`,
+
+	// issue 11611
+	`package p; type _ struct { int, } /* ERROR "expected type, found '}'" */ ;`,
+	`package p; type _ struct { int, float } /* ERROR "expected type, found '}'" */ ;`,
+	`package p; type _ struct { ( /* ERROR "expected anonymous field" */ int) };`,
+	`package p; func _()(x, y, z ... /* ERROR "expected '\)', found '...'" */ int){}`,
+	`package p; func _()(... /* ERROR "expected type, found '...'" */ int){}`,
+
+	// issue 13475
+	`package p; func f() { if true {} else ; /* ERROR "expected if statement or block" */ }`,
+	`package p; func f() { if true {} else defer /* ERROR "expected if statement or block" */ f() }`,
 }
 
 func TestInvalid(t *testing.T) {
diff --git a/src/go/printer/nodes.go b/src/go/printer/nodes.go
index fe04705..11f26d4 100644
--- a/src/go/printer/nodes.go
+++ b/src/go/printer/nodes.go
@@ -747,13 +747,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
 		}
 
 	case *ast.SelectorExpr:
-		p.expr1(x.X, token.HighestPrec, depth)
-		p.print(token.PERIOD)
-		if line := p.lineFor(x.Sel.Pos()); p.pos.IsValid() && p.pos.Line < line {
-			p.print(indent, newline, x.Sel.Pos(), x.Sel, unindent)
-		} else {
-			p.print(x.Sel.Pos(), x.Sel)
-		}
+		p.selectorExpr(x, depth, false)
 
 	case *ast.TypeAssertExpr:
 		p.expr1(x.X, token.HighestPrec, depth)
@@ -802,13 +796,14 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
 		if len(x.Args) > 1 {
 			depth++
 		}
+		var wasIndented bool
 		if _, ok := x.Fun.(*ast.FuncType); ok {
 			// conversions to literal function types require parentheses around the type
 			p.print(token.LPAREN)
-			p.expr1(x.Fun, token.HighestPrec, depth)
+			wasIndented = p.possibleSelectorExpr(x.Fun, token.HighestPrec, depth)
 			p.print(token.RPAREN)
 		} else {
-			p.expr1(x.Fun, token.HighestPrec, depth)
+			wasIndented = p.possibleSelectorExpr(x.Fun, token.HighestPrec, depth)
 		}
 		p.print(x.Lparen, token.LPAREN)
 		if x.Ellipsis.IsValid() {
@@ -821,6 +816,9 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
 			p.exprList(x.Lparen, x.Args, depth, commaTerm, x.Rparen)
 		}
 		p.print(x.Rparen, token.RPAREN)
+		if wasIndented {
+			p.print(unindent)
+		}
 
 	case *ast.CompositeLit:
 		// composite literal elements that are composite literals themselves may have the type omitted
@@ -891,6 +889,30 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
 	return
 }
 
+func (p *printer) possibleSelectorExpr(expr ast.Expr, prec1, depth int) bool {
+	if x, ok := expr.(*ast.SelectorExpr); ok {
+		return p.selectorExpr(x, depth, true)
+	}
+	p.expr1(expr, prec1, depth)
+	return false
+}
+
+// selectorExpr handles an *ast.SelectorExpr node and returns whether x spans
+// multiple lines.
+func (p *printer) selectorExpr(x *ast.SelectorExpr, depth int, isMethod bool) bool {
+	p.expr1(x.X, token.HighestPrec, depth)
+	p.print(token.PERIOD)
+	if line := p.lineFor(x.Sel.Pos()); p.pos.IsValid() && p.pos.Line < line {
+		p.print(indent, newline, x.Sel.Pos(), x.Sel)
+		if !isMethod {
+			p.print(unindent)
+		}
+		return true
+	}
+	p.print(x.Sel.Pos(), x.Sel)
+	return false
+}
+
 func (p *printer) expr0(x ast.Expr, depth int) {
 	p.expr1(x, token.LowestPrec, depth)
 }
@@ -1163,6 +1185,9 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool) {
 			case *ast.BlockStmt, *ast.IfStmt:
 				p.stmt(s.Else, nextIsRBrace)
 			default:
+				// This can only happen with an incorrectly
+				// constructed AST. Permit it but print so
+				// that it can be parsed without errors.
 				p.print(token.LBRACE, indent, formfeed)
 				p.stmt(s.Else, true)
 				p.print(unindent, formfeed, token.RBRACE)
diff --git a/src/go/printer/printer.go b/src/go/printer/printer.go
index f9343d3..a3eaa66 100644
--- a/src/go/printer/printer.go
+++ b/src/go/printer/printer.go
@@ -1178,7 +1178,9 @@ func (p *trimmer) Write(data []byte) (n int, err error) {
 			case '\n', '\f':
 				_, err = p.output.Write(data[m:n])
 				p.resetSpace()
-				_, err = p.output.Write(aNewline)
+				if err == nil {
+					_, err = p.output.Write(aNewline)
+				}
 			case tabwriter.Escape:
 				_, err = p.output.Write(data[m:n])
 				p.state = inEscape
diff --git a/src/go/printer/printer_test.go b/src/go/printer/printer_test.go
index 3b0570e..73f9ead 100644
--- a/src/go/printer/printer_test.go
+++ b/src/go/printer/printer_test.go
@@ -12,6 +12,7 @@ import (
 	"go/ast"
 	"go/parser"
 	"go/token"
+	"io"
 	"io/ioutil"
 	"path/filepath"
 	"testing"
@@ -548,6 +549,46 @@ func f()
 	}
 }
 
+type limitWriter struct {
+	remaining int
+	errCount  int
+}
+
+func (l *limitWriter) Write(buf []byte) (n int, err error) {
+	n = len(buf)
+	if n >= l.remaining {
+		n = l.remaining
+		err = io.EOF
+		l.errCount++
+	}
+	l.remaining -= n
+	return n, err
+}
+
+// Test whether the printer stops writing after the first error
+func TestWriteErrors(t *testing.T) {
+	const filename = "printer.go"
+	src, err := ioutil.ReadFile(filename)
+	if err != nil {
+		panic(err) // error in test
+	}
+	file, err := parser.ParseFile(fset, filename, src, 0)
+	if err != nil {
+		panic(err) // error in test
+	}
+	for i := 0; i < 20; i++ {
+		lw := &limitWriter{remaining: i}
+		err := (&Config{Mode: RawFormat}).Fprint(lw, fset, file)
+		if lw.errCount > 1 {
+			t.Fatal("Writes continued after first error returned")
+		}
+		// We expect errCount be 1 iff err is set
+		if (lw.errCount != 0) != (err != nil) {
+			t.Fatal("Expected err when errCount != 0")
+		}
+	}
+}
+
 // TextX is a skeleton test that can be filled in for debugging one-off cases.
 // Do not remove.
 func TestX(t *testing.T) {
diff --git a/src/go/printer/testdata/expressions.golden b/src/go/printer/testdata/expressions.golden
index e3d17a4..cab991f 100644
--- a/src/go/printer/testdata/expressions.golden
+++ b/src/go/printer/testdata/expressions.golden
@@ -567,7 +567,7 @@ func _() {
 	// handle multiline argument list correctly
 	_ = new(T).
 		foo(
-		1).
+			1).
 		foo(2)
 
 	_ = new(T).foo(
@@ -614,7 +614,7 @@ func _() {
 		Blob.(*Type).
 		Slices[1:4].
 		Method(1, 2,
-		3).
+			3).
 		Thingy
 
 	_ = a.b.c
@@ -684,3 +684,21 @@ func _() {
 	_ = (func(x int) float)(nil)
 	_ = (func() func() func())(nil)
 }
+
+func _() {
+	_ = f().
+		f(func() {
+			f()
+		}).
+		f(map[int]int{
+			1:	2,
+			3:	4,
+		})
+
+	_ = f().
+		f(
+			func() {
+				f()
+			},
+		)
+}
diff --git a/src/go/printer/testdata/expressions.input b/src/go/printer/testdata/expressions.input
index d20a593..7c88042 100644
--- a/src/go/printer/testdata/expressions.input
+++ b/src/go/printer/testdata/expressions.input
@@ -713,3 +713,21 @@ func _() {
 	_ = (func(x int)(float))(nil)
 	_ = (func() func() func()())(nil)
 }
+
+func _() {
+	_ = f().
+	f(func() {
+		f()
+	}).
+	f(map[int]int{
+	1: 2,
+	3: 4,
+})
+
+	_ = f().
+	f(
+	func() {
+		f()
+	},
+	)
+}
diff --git a/src/go/printer/testdata/expressions.raw b/src/go/printer/testdata/expressions.raw
index 2357336..d906062 100644
--- a/src/go/printer/testdata/expressions.raw
+++ b/src/go/printer/testdata/expressions.raw
@@ -567,7 +567,7 @@ func _() {
 	// handle multiline argument list correctly
 	_ = new(T).
 		foo(
-		1).
+			1).
 		foo(2)
 
 	_ = new(T).foo(
@@ -614,7 +614,7 @@ func _() {
 		Blob.(*Type).
 		Slices[1:4].
 		Method(1, 2,
-		3).
+			3).
 		Thingy
 
 	_ = a.b.c
@@ -684,3 +684,21 @@ func _() {
 	_ = (func(x int) float)(nil)
 	_ = (func() func() func())(nil)
 }
+
+func _() {
+	_ = f().
+		f(func() {
+			f()
+		}).
+		f(map[int]int{
+			1:	2,
+			3:	4,
+		})
+
+	_ = f().
+		f(
+			func() {
+				f()
+			},
+		)
+}
diff --git a/src/go/types/api.go b/src/go/types/api.go
index b3bf6f0..ca109f0 100644
--- a/src/go/types/api.go
+++ b/src/go/types/api.go
@@ -22,6 +22,8 @@
 // and checks for compliance with the language specification.
 // Use Info.Types[expr].Type for the results of type inference.
 //
+// For a tutorial, see https://golang.org/s/types-tutorial.
+//
 package types // import "go/types"
 
 import (
@@ -49,16 +51,42 @@ func (err Error) Error() string {
 	return fmt.Sprintf("%s: %s", err.Fset.Position(err.Pos), err.Msg)
 }
 
-// An importer resolves import paths to Packages.
-// See go/importer for existing implementations.
+// An Importer resolves import paths to Packages.
+//
+// CAUTION: This interface does not support the import of locally
+// vendored packages. See https://golang.org/s/go15vendor.
+// If possible, external implementations should implement ImporterFrom.
 type Importer interface {
 	// Import returns the imported package for the given import
 	// path, or an error if the package couldn't be imported.
-	// Import is responsible for returning the same package for
-	// matching import paths.
+	// Two calls to Import with the same path return the same
+	// package.
 	Import(path string) (*Package, error)
 }
 
+// ImportMode is reserved for future use.
+type ImportMode int
+
+// An ImporterFrom resolves import paths to packages; it
+// supports vendoring per https://golang.org/s/go15vendor.
+// Use go/importer to obtain an ImporterFrom implementation.
+type ImporterFrom interface {
+	// Importer is present for backward-compatibility. Calling
+	// Import(path) is the same as calling ImportFrom(path, "", 0);
+	// i.e., locally vendored packages may not be found.
+	// The types package does not call Import if an ImporterFrom
+	// is present.
+	Importer
+
+	// ImportFrom returns the imported package for the given import
+	// path when imported by the package in srcDir, or an error
+	// if the package couldn't be imported. The mode value must
+	// be 0; it is reserved for future use.
+	// Two calls to ImportFrom with the same path and srcDir return
+	// the same package.
+	ImportFrom(path, srcDir string, mode ImportMode) (*Package, error)
+}
+
 // A Config specifies the configuration for type checking.
 // The zero value for Config is a ready-to-use default configuration.
 type Config struct {
@@ -84,9 +112,12 @@ type Config struct {
 	// error found.
 	Error func(err error)
 
-	// Importer is called for each import declaration except when
-	// importing package "unsafe". An error is reported if an
-	// importer is needed but none was installed.
+	// An importer is used to import packages referred to from
+	// import declarations.
+	// If the installed importer implements ImporterFrom, the type
+	// checker calls ImportFrom instead of Import.
+	// The type checker reports an error if an importer is needed
+	// but none was installed.
 	Importer Importer
 
 	// If Sizes != nil, it provides the sizing functions for package unsafe.
@@ -142,7 +173,7 @@ type Info struct {
 	//
 	//	*ast.ImportSpec    *PkgName for dot-imports and imports without renames
 	//	*ast.CaseClause    type-specific *Var for each type switch case clause (incl. default)
-	//      *ast.Field         anonymous struct field or parameter *Var
+	//      *ast.Field         anonymous parameter *Var
 	//
 	Implicits map[ast.Node]Object
 
@@ -297,8 +328,10 @@ func (init *Initializer) String() string {
 	return buf.String()
 }
 
-// Check type-checks a package and returns the resulting package object,
-// the first error if any, and if info != nil, additional type information.
+// Check type-checks a package and returns the resulting package object and
+// the first error if any. Additionally, if info != nil, Check populates each
+// of the non-nil maps in the Info struct.
+//
 // The package is marked as complete if no errors occurred, otherwise it is
 // incomplete. See Config.Error for controlling behavior in the presence of
 // errors.
@@ -320,7 +353,7 @@ func AssertableTo(V *Interface, T Type) bool {
 // AssignableTo reports whether a value of type V is assignable to a variable of type T.
 func AssignableTo(V, T Type) bool {
 	x := operand{mode: value, typ: V}
-	return x.assignableTo(nil, T) // config not needed for non-constant x
+	return x.assignableTo(nil, T, nil) // config not needed for non-constant x
 }
 
 // ConvertibleTo reports whether a value of type V is convertible to a value of type T.
diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go
index eeda0d8..c2feed3 100644
--- a/src/go/types/api_test.go
+++ b/src/go/types/api_test.go
@@ -54,14 +54,14 @@ func TestValuesInfo(t *testing.T) {
 		{`package a1; const _ = 0`, `0`, `untyped int`, `0`},
 		{`package a2; const _ = 'A'`, `'A'`, `untyped rune`, `65`},
 		{`package a3; const _ = 0.`, `0.`, `untyped float`, `0`},
-		{`package a4; const _ = 0i`, `0i`, `untyped complex`, `0`},
+		{`package a4; const _ = 0i`, `0i`, `untyped complex`, `(0 + 0i)`},
 		{`package a5; const _ = "foo"`, `"foo"`, `untyped string`, `"foo"`},
 
 		{`package b0; var _ = false`, `false`, `bool`, `false`},
 		{`package b1; var _ = 0`, `0`, `int`, `0`},
 		{`package b2; var _ = 'A'`, `'A'`, `rune`, `65`},
 		{`package b3; var _ = 0.`, `0.`, `float64`, `0`},
-		{`package b4; var _ = 0i`, `0i`, `complex128`, `0`},
+		{`package b4; var _ = 0i`, `0i`, `complex128`, `(0 + 0i)`},
 		{`package b5; var _ = "foo"`, `"foo"`, `string`, `"foo"`},
 
 		{`package c0a; var _ = bool(false)`, `false`, `bool`, `false`},
@@ -80,9 +80,9 @@ func TestValuesInfo(t *testing.T) {
 		{`package c3b; var _ = float32(0.)`, `float32(0.)`, `float32`, `0`},
 		{`package c3c; type T float32; var _ = T(0.)`, `T(0.)`, `c3c.T`, `0`},
 
-		{`package c4a; var _ = complex64(0i)`, `0i`, `complex64`, `0`},
-		{`package c4b; var _ = complex64(0i)`, `complex64(0i)`, `complex64`, `0`},
-		{`package c4c; type T complex64; var _ = T(0i)`, `T(0i)`, `c4c.T`, `0`},
+		{`package c4a; var _ = complex64(0i)`, `0i`, `complex64`, `(0 + 0i)`},
+		{`package c4b; var _ = complex64(0i)`, `complex64(0i)`, `complex64`, `(0 + 0i)`},
+		{`package c4c; type T complex64; var _ = T(0i)`, `T(0i)`, `c4c.T`, `(0 + 0i)`},
 
 		{`package c5a; var _ = string("foo")`, `"foo"`, `string`, `"foo"`},
 		{`package c5b; var _ = string("foo")`, `string("foo")`, `string`, `"foo"`},
@@ -97,10 +97,10 @@ func TestValuesInfo(t *testing.T) {
 		{`package e1; const _ = float32(-1e-200)`, `float32(-1e-200)`, `float32`, `0`},
 		{`package e2; const _ = float64( 1e-2000)`, `float64(1e-2000)`, `float64`, `0`},
 		{`package e3; const _ = float64(-1e-2000)`, `float64(-1e-2000)`, `float64`, `0`},
-		{`package e4; const _ = complex64( 1e-200)`, `complex64(1e-200)`, `complex64`, `0`},
-		{`package e5; const _ = complex64(-1e-200)`, `complex64(-1e-200)`, `complex64`, `0`},
-		{`package e6; const _ = complex128( 1e-2000)`, `complex128(1e-2000)`, `complex128`, `0`},
-		{`package e7; const _ = complex128(-1e-2000)`, `complex128(-1e-2000)`, `complex128`, `0`},
+		{`package e4; const _ = complex64( 1e-200)`, `complex64(1e-200)`, `complex64`, `(0 + 0i)`},
+		{`package e5; const _ = complex64(-1e-200)`, `complex64(-1e-200)`, `complex64`, `(0 + 0i)`},
+		{`package e6; const _ = complex128( 1e-2000)`, `complex128(1e-2000)`, `complex128`, `(0 + 0i)`},
+		{`package e7; const _ = complex128(-1e-2000)`, `complex128(-1e-2000)`, `complex128`, `(0 + 0i)`},
 
 		{`package f0 ; var _ float32 =  1e-200`, `1e-200`, `float32`, `0`},
 		{`package f1 ; var _ float32 = -1e-200`, `-1e-200`, `float32`, `0`},
@@ -108,12 +108,12 @@ func TestValuesInfo(t *testing.T) {
 		{`package f3a; var _ float64 = -1e-2000`, `-1e-2000`, `float64`, `0`},
 		{`package f2b; var _         =  1e-2000`, `1e-2000`, `float64`, `0`},
 		{`package f3b; var _         = -1e-2000`, `-1e-2000`, `float64`, `0`},
-		{`package f4 ; var _ complex64  =  1e-200 `, `1e-200`, `complex64`, `0`},
-		{`package f5 ; var _ complex64  = -1e-200 `, `-1e-200`, `complex64`, `0`},
-		{`package f6a; var _ complex128 =  1e-2000i`, `1e-2000i`, `complex128`, `0`},
-		{`package f7a; var _ complex128 = -1e-2000i`, `-1e-2000i`, `complex128`, `0`},
-		{`package f6b; var _            =  1e-2000i`, `1e-2000i`, `complex128`, `0`},
-		{`package f7b; var _            = -1e-2000i`, `-1e-2000i`, `complex128`, `0`},
+		{`package f4 ; var _ complex64  =  1e-200 `, `1e-200`, `complex64`, `(0 + 0i)`},
+		{`package f5 ; var _ complex64  = -1e-200 `, `-1e-200`, `complex64`, `(0 + 0i)`},
+		{`package f6a; var _ complex128 =  1e-2000i`, `1e-2000i`, `complex128`, `(0 + 0i)`},
+		{`package f7a; var _ complex128 = -1e-2000i`, `-1e-2000i`, `complex128`, `(0 + 0i)`},
+		{`package f6b; var _            =  1e-2000i`, `1e-2000i`, `complex128`, `(0 + 0i)`},
+		{`package f7b; var _            = -1e-2000i`, `-1e-2000i`, `complex128`, `(0 + 0i)`},
 	}
 
 	for _, test := range tests {
@@ -143,7 +143,7 @@ func TestValuesInfo(t *testing.T) {
 		}
 
 		// check that value is correct
-		if got := tv.Value.String(); got != test.val {
+		if got := tv.Value.ExactString(); got != test.val {
 			t.Errorf("package %s: got value %s; want %s", name, got, test.val)
 		}
 	}
@@ -797,7 +797,7 @@ func main() {
 	makePkg("main", mainSrc)
 
 	for e, sel := range selections {
-		sel.String() // assertion: must not panic
+		_ = sel.String() // assertion: must not panic
 
 		start := fset.Position(e.Pos()).Offset
 		end := fset.Position(e.End()).Offset
diff --git a/src/go/types/assignments.go b/src/go/types/assignments.go
index e88de56..10ab17b 100644
--- a/src/go/types/assignments.go
+++ b/src/go/types/assignments.go
@@ -13,31 +13,21 @@ import (
 
 // assignment reports whether x can be assigned to a variable of type T,
 // if necessary by attempting to convert untyped values to the appropriate
-// type. If x.mode == invalid upon return, then assignment has already
-// issued an error message and the caller doesn't have to report another.
+// type. context describes the context in which the assignment takes place.
 // Use T == nil to indicate assignment to an untyped blank identifier.
-//
-// TODO(gri) Should find a better way to handle in-band errors.
-//
-func (check *Checker) assignment(x *operand, T Type) bool {
+// x.mode is set to invalid if the assignment failed.
+func (check *Checker) assignment(x *operand, T Type, context string) {
+	check.singleValue(x)
+
 	switch x.mode {
 	case invalid:
-		return true // error reported before
+		return // error reported before
 	case constant_, variable, mapindex, value, commaok:
 		// ok
 	default:
 		unreachable()
 	}
 
-	// x must be a single value
-	// (tuple types are never named - no need for underlying type)
-	if t, _ := x.typ.(*Tuple); t != nil {
-		assert(t.Len() > 1)
-		check.errorf(x.pos(), "%d-valued expression %s used as single value", t.Len(), x)
-		x.mode = invalid
-		return false
-	}
-
 	if isUntyped(x.typ) {
 		target := T
 		// spec: "If an untyped constant is assigned to a variable of interface
@@ -47,22 +37,34 @@ func (check *Checker) assignment(x *operand, T Type) bool {
 		// or string constant."
 		if T == nil || IsInterface(T) {
 			if T == nil && x.typ == Typ[UntypedNil] {
-				check.errorf(x.pos(), "use of untyped nil")
+				check.errorf(x.pos(), "use of untyped nil in %s", context)
 				x.mode = invalid
-				return false
+				return
 			}
 			target = defaultType(x.typ)
 		}
 		check.convertUntyped(x, target)
 		if x.mode == invalid {
-			return false
+			return
 		}
 	}
+	// x.typ is typed
 
 	// spec: "If a left-hand side is the blank identifier, any typed or
 	// non-constant value except for the predeclared identifier nil may
 	// be assigned to it."
-	return T == nil || x.assignableTo(check.conf, T)
+	if T == nil {
+		return
+	}
+
+	if reason := ""; !x.assignableTo(check.conf, T, &reason) {
+		if reason != "" {
+			check.errorf(x.pos(), "cannot use %s as %s value in %s: %s", x, T, context, reason)
+		} else {
+			check.errorf(x.pos(), "cannot use %s as %s value in %s", x, T, context)
+		}
+		x.mode = invalid
+	}
 }
 
 func (check *Checker) initConst(lhs *Const, x *operand) {
@@ -88,18 +90,15 @@ func (check *Checker) initConst(lhs *Const, x *operand) {
 		lhs.typ = x.typ
 	}
 
-	if !check.assignment(x, lhs.typ) {
-		if x.mode != invalid {
-			check.errorf(x.pos(), "cannot define constant %s (type %s) as %s", lhs.Name(), lhs.typ, x)
-		}
+	check.assignment(x, lhs.typ, "constant declaration")
+	if x.mode == invalid {
 		return
 	}
 
 	lhs.val = x.val
 }
 
-// If result is set, lhs is a function result parameter and x is a return result.
-func (check *Checker) initVar(lhs *Var, x *operand, result bool) Type {
+func (check *Checker) initVar(lhs *Var, x *operand, context string) Type {
 	if x.mode == invalid || x.typ == Typ[Invalid] || lhs.typ == Typ[Invalid] {
 		if lhs.typ == nil {
 			lhs.typ = Typ[Invalid]
@@ -113,7 +112,7 @@ func (check *Checker) initVar(lhs *Var, x *operand, result bool) Type {
 		if isUntyped(typ) {
 			// convert untyped types to default types
 			if typ == Typ[UntypedNil] {
-				check.errorf(x.pos(), "use of untyped nil")
+				check.errorf(x.pos(), "use of untyped nil in %s", context)
 				lhs.typ = Typ[Invalid]
 				return nil
 			}
@@ -122,15 +121,8 @@ func (check *Checker) initVar(lhs *Var, x *operand, result bool) Type {
 		lhs.typ = typ
 	}
 
-	if !check.assignment(x, lhs.typ) {
-		if x.mode != invalid {
-			if result {
-				// don't refer to lhs.name because it may be an anonymous result parameter
-				check.errorf(x.pos(), "cannot return %s as value of type %s", x, lhs.typ)
-			} else {
-				check.errorf(x.pos(), "cannot initialize %s with %s", lhs, x)
-			}
-		}
+	check.assignment(x, lhs.typ, context)
+	if x.mode == invalid {
 		return nil
 	}
 
@@ -148,9 +140,9 @@ func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type {
 	// Don't evaluate lhs if it is the blank identifier.
 	if ident != nil && ident.Name == "_" {
 		check.recordDef(ident, nil)
-		if !check.assignment(x, nil) {
-			assert(x.mode == invalid)
-			x.typ = nil
+		check.assignment(x, nil, "assignment to _ identifier")
+		if x.mode == invalid {
+			return nil
 		}
 		return x.typ
 	}
@@ -191,10 +183,8 @@ func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type {
 		return nil
 	}
 
-	if !check.assignment(x, z.typ) {
-		if x.mode != invalid {
-			check.errorf(x.pos(), "cannot assign %s to %s", x, &z)
-		}
+	check.assignment(x, z.typ, "assignment")
+	if x.mode == invalid {
 		return nil
 	}
 
@@ -205,7 +195,7 @@ func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type {
 // return expressions, and returnPos is the position of the return statement.
 func (check *Checker) initVars(lhs []*Var, rhs []ast.Expr, returnPos token.Pos) {
 	l := len(lhs)
-	get, r, commaOk := unpack(func(x *operand, i int) { check.expr(x, rhs[i]) }, len(rhs), l == 2 && !returnPos.IsValid())
+	get, r, commaOk := unpack(func(x *operand, i int) { check.multiExpr(x, rhs[i]) }, len(rhs), l == 2 && !returnPos.IsValid())
 	if get == nil || l != r {
 		// invalidate lhs and use rhs
 		for _, obj := range lhs {
@@ -225,12 +215,17 @@ func (check *Checker) initVars(lhs []*Var, rhs []ast.Expr, returnPos token.Pos)
 		return
 	}
 
+	context := "assignment"
+	if returnPos.IsValid() {
+		context = "return statement"
+	}
+
 	var x operand
 	if commaOk {
 		var a [2]Type
 		for i := range a {
 			get(&x, i)
-			a[i] = check.initVar(lhs[i], &x, returnPos.IsValid())
+			a[i] = check.initVar(lhs[i], &x, context)
 		}
 		check.recordCommaOkTypes(rhs[0], a)
 		return
@@ -238,13 +233,13 @@ func (check *Checker) initVars(lhs []*Var, rhs []ast.Expr, returnPos token.Pos)
 
 	for i, lhs := range lhs {
 		get(&x, i)
-		check.initVar(lhs, &x, returnPos.IsValid())
+		check.initVar(lhs, &x, context)
 	}
 }
 
 func (check *Checker) assignVars(lhs, rhs []ast.Expr) {
 	l := len(lhs)
-	get, r, commaOk := unpack(func(x *operand, i int) { check.expr(x, rhs[i]) }, len(rhs), l == 2)
+	get, r, commaOk := unpack(func(x *operand, i int) { check.multiExpr(x, rhs[i]) }, len(rhs), l == 2)
 	if get == nil {
 		return // error reported by unpack
 	}
diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go
index 4729591..803264f 100644
--- a/src/go/types/builtins.go
+++ b/src/go/types/builtins.go
@@ -44,7 +44,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 	switch id {
 	default:
 		// make argument getter
-		arg, nargs, _ = unpack(func(x *operand, i int) { check.expr(x, call.Args[i]) }, nargs, false)
+		arg, nargs, _ = unpack(func(x *operand, i int) { check.multiExpr(x, call.Args[i]) }, nargs, false)
 		if arg == nil {
 			return
 		}
@@ -95,7 +95,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 		// spec: "As a special case, append also accepts a first argument assignable
 		// to type []byte with a second argument of string type followed by ... .
 		// This form appends the bytes of the string.
-		if nargs == 2 && call.Ellipsis.IsValid() && x.assignableTo(check.conf, NewSlice(universeByte)) {
+		if nargs == 2 && call.Ellipsis.IsValid() && x.assignableTo(check.conf, NewSlice(universeByte), nil) {
 			arg(x, 1)
 			if x.mode == invalid {
 				return
@@ -200,77 +200,96 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 		}
 
 	case _Complex:
-		// complex(x, y realT) complexT
-		if !check.complexArg(x) {
-			return
-		}
-
+		// complex(x, y floatT) complexT
 		var y operand
 		arg(&y, 1)
 		if y.mode == invalid {
 			return
 		}
-		if !check.complexArg(&y) {
-			return
-		}
 
-		check.convertUntyped(x, y.typ)
-		if x.mode == invalid {
-			return
+		// convert or check untyped arguments
+		d := 0
+		if isUntyped(x.typ) {
+			d |= 1
+		}
+		if isUntyped(y.typ) {
+			d |= 2
+		}
+		switch d {
+		case 0:
+			// x and y are typed => nothing to do
+		case 1:
+			// only x is untyped => convert to type of y
+			check.convertUntyped(x, y.typ)
+		case 2:
+			// only y is untyped => convert to type of x
+			check.convertUntyped(&y, x.typ)
+		case 3:
+			// x and y are untyped =>
+			// 1) if both are constants, convert them to untyped
+			//    floating-point numbers if possible,
+			// 2) if one of them is not constant (possible because
+			//    it contains a shift that is yet untyped), convert
+			//    both of them to float64 since they must have the
+			//    same type to succeed (this will result in an error
+			//    because shifts of floats are not permitted)
+			if x.mode == constant_ && y.mode == constant_ {
+				toFloat := func(x *operand) {
+					if isNumeric(x.typ) && constant.Sign(constant.Imag(x.val)) == 0 {
+						x.typ = Typ[UntypedFloat]
+					}
+				}
+				toFloat(x)
+				toFloat(&y)
+			} else {
+				check.convertUntyped(x, Typ[Float64])
+				check.convertUntyped(&y, Typ[Float64])
+				// x and y should be invalid now, but be conservative
+				// and check below
+			}
 		}
-		check.convertUntyped(&y, x.typ)
-		if y.mode == invalid {
+		if x.mode == invalid || y.mode == invalid {
 			return
 		}
 
+		// both argument types must be identical
 		if !Identical(x.typ, y.typ) {
 			check.invalidArg(x.pos(), "mismatched types %s and %s", x.typ, y.typ)
 			return
 		}
 
+		// the argument types must be of floating-point type
+		if !isFloat(x.typ) {
+			check.invalidArg(x.pos(), "arguments have type %s, expected floating-point", x.typ)
+			return
+		}
+
+		// if both arguments are constants, the result is a constant
 		if x.mode == constant_ && y.mode == constant_ {
-			x.val = constant.BinaryOp(x.val, token.ADD, constant.MakeImag(y.val))
+			x.val = constant.BinaryOp(constant.ToFloat(x.val), token.ADD, constant.MakeImag(constant.ToFloat(y.val)))
 		} else {
 			x.mode = value
 		}
 
-		realT := x.typ
-		complexT := Typ[Invalid]
-		switch realT.Underlying().(*Basic).kind {
+		// determine result type
+		var res BasicKind
+		switch x.typ.Underlying().(*Basic).kind {
 		case Float32:
-			complexT = Typ[Complex64]
+			res = Complex64
 		case Float64:
-			complexT = Typ[Complex128]
-		case UntypedInt, UntypedRune, UntypedFloat:
-			if x.mode == constant_ {
-				realT = defaultType(realT).(*Basic)
-				complexT = Typ[UntypedComplex]
-			} else {
-				// untyped but not constant; probably because one
-				// operand is a non-constant shift of untyped lhs
-				realT = Typ[Float64]
-				complexT = Typ[Complex128]
-			}
+			res = Complex128
+		case UntypedFloat:
+			res = UntypedComplex
 		default:
-			check.invalidArg(x.pos(), "float32 or float64 arguments expected")
-			return
+			unreachable()
 		}
+		resTyp := Typ[res]
 
-		x.typ = complexT
 		if check.Types != nil && x.mode != constant_ {
-			check.recordBuiltinType(call.Fun, makeSig(complexT, realT, realT))
+			check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ, x.typ))
 		}
 
-		if x.mode != constant_ {
-			// The arguments have now their final types, which at run-
-			// time will be materialized. Update the expression trees.
-			// If the current types are untyped, the materialized type
-			// is the respective default type.
-			// (If the result is constant, the arguments are never
-			// materialized and there is nothing to do.)
-			check.updateExprType(x.expr, realT, true)
-			check.updateExprType(y.expr, realT, true)
-		}
+		x.typ = resTyp
 
 	case _Copy:
 		// copy(x, y []T) int
@@ -322,7 +341,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 			return
 		}
 
-		if !x.assignableTo(check.conf, m.key) {
+		if !x.assignableTo(check.conf, m.key, nil) {
 			check.invalidArg(x.pos(), "%s is not assignable to %s", x, m.key)
 			return
 		}
@@ -333,12 +352,37 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 		}
 
 	case _Imag, _Real:
-		// imag(complexT) realT
-		// real(complexT) realT
+		// imag(complexT) floatT
+		// real(complexT) floatT
+
+		// convert or check untyped argument
+		if isUntyped(x.typ) {
+			if x.mode == constant_ {
+				// an untyped constant number can alway be considered
+				// as a complex constant
+				if isNumeric(x.typ) {
+					x.typ = Typ[UntypedComplex]
+				}
+			} else {
+				// an untyped non-constant argument may appear if
+				// it contains a (yet untyped non-constant) shift
+				// epression: convert it to complex128 which will
+				// result in an error (shift of complex value)
+				check.convertUntyped(x, Typ[Complex128])
+				// x should be invalid now, but be conservative and check
+				if x.mode == invalid {
+					return
+				}
+			}
+		}
+
+		// the argument must be of complex type
 		if !isComplex(x.typ) {
-			check.invalidArg(x.pos(), "%s must be a complex number", x)
+			check.invalidArg(x.pos(), "argument has type %s, expected complex type", x.typ)
 			return
 		}
+
+		// if the argument is a constant, the result is a constant
 		if x.mode == constant_ {
 			if id == _Real {
 				x.val = constant.Real(x.val)
@@ -348,22 +392,26 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 		} else {
 			x.mode = value
 		}
-		var k BasicKind
+
+		// determine result type
+		var res BasicKind
 		switch x.typ.Underlying().(*Basic).kind {
 		case Complex64:
-			k = Float32
+			res = Float32
 		case Complex128:
-			k = Float64
+			res = Float64
 		case UntypedComplex:
-			k = UntypedFloat
+			res = UntypedFloat
 		default:
 			unreachable()
 		}
+		resTyp := Typ[res]
 
 		if check.Types != nil && x.mode != constant_ {
-			check.recordBuiltinType(call.Fun, makeSig(Typ[k], x.typ))
+			check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ))
 		}
-		x.typ = Typ[k]
+
+		x.typ = resTyp
 
 	case _Make:
 		// make(T, n)
@@ -423,8 +471,8 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 	case _Panic:
 		// panic(x)
 		T := new(Interface)
-		if !check.assignment(x, T) {
-			assert(x.mode == invalid)
+		check.assignment(x, T, "argument to panic")
+		if x.mode == invalid {
 			return
 		}
 
@@ -443,8 +491,9 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 				if i > 0 {
 					arg(x, i) // first argument already evaluated
 				}
-				if !check.assignment(x, nil) {
-					assert(x.mode == invalid)
+				check.assignment(x, nil, "argument to "+predeclaredFuncs[id].name)
+				if x.mode == invalid {
+					// TODO(gri) "use" all arguments?
 					return
 				}
 				params[i] = x.typ
@@ -466,8 +515,8 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 
 	case _Alignof:
 		// unsafe.Alignof(x T) uintptr
-		if !check.assignment(x, nil) {
-			assert(x.mode == invalid)
+		check.assignment(x, nil, "argument to unsafe.Alignof")
+		if x.mode == invalid {
 			return
 		}
 
@@ -523,8 +572,8 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 
 	case _Sizeof:
 		// unsafe.Sizeof(x T) uintptr
-		if !check.assignment(x, nil) {
-			assert(x.mode == invalid)
+		check.assignment(x, nil, "argument to unsafe.Sizeof")
+		if x.mode == invalid {
 			return
 		}
 
@@ -616,12 +665,3 @@ func unparen(e ast.Expr) ast.Expr {
 		e = p.X
 	}
 }
-
-func (check *Checker) complexArg(x *operand) bool {
-	t, _ := x.typ.Underlying().(*Basic)
-	if t != nil && (t.info&IsFloat != 0 || t.kind == UntypedInt || t.kind == UntypedRune) {
-		return true
-	}
-	check.invalidArg(x.pos(), "%s must be a float32, float64, or an untyped non-complex numeric constant", x)
-	return false
-}
diff --git a/src/go/types/call.go b/src/go/types/call.go
index 62cefc0..8aeb862 100644
--- a/src/go/types/call.go
+++ b/src/go/types/call.go
@@ -61,7 +61,7 @@ func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind {
 			return statement
 		}
 
-		arg, n, _ := unpack(func(x *operand, i int) { check.expr(x, e.Args[i]) }, len(e.Args), false)
+		arg, n, _ := unpack(func(x *operand, i int) { check.multiExpr(x, e.Args[i]) }, len(e.Args), false)
 		if arg == nil {
 			x.mode = invalid
 			x.expr = e
@@ -181,14 +181,14 @@ func unpack(get getter, n int, allowCommaOk bool) (getter, int, bool) {
 func (check *Checker) arguments(x *operand, call *ast.CallExpr, sig *Signature, arg getter, n int) {
 	if call.Ellipsis.IsValid() {
 		// last argument is of the form x...
-		if len(call.Args) == 1 && n > 1 {
-			// f()... is not permitted if f() is multi-valued
-			check.errorf(call.Ellipsis, "cannot use ... with %d-valued expression %s", n, call.Args[0])
+		if !sig.variadic {
+			check.errorf(call.Ellipsis, "cannot use ... in call to non-variadic %s", call.Fun)
 			check.useGetter(arg, n)
 			return
 		}
-		if !sig.variadic {
-			check.errorf(call.Ellipsis, "cannot use ... in call to non-variadic %s", call.Fun)
+		if len(call.Args) == 1 && n > 1 {
+			// f()... is not permitted if f() is multi-valued
+			check.errorf(call.Ellipsis, "cannot use ... with %d-valued %s", n, call.Args[0])
 			check.useGetter(arg, n)
 			return
 		}
@@ -202,7 +202,7 @@ func (check *Checker) arguments(x *operand, call *ast.CallExpr, sig *Signature,
 			if i == n-1 && call.Ellipsis.IsValid() {
 				ellipsis = call.Ellipsis
 			}
-			check.argument(sig, i, x, ellipsis)
+			check.argument(call.Fun, sig, i, x, ellipsis)
 		}
 	}
 
@@ -220,7 +220,12 @@ func (check *Checker) arguments(x *operand, call *ast.CallExpr, sig *Signature,
 
 // argument checks passing of argument x to the i'th parameter of the given signature.
 // If ellipsis is valid, the argument is followed by ... at that position in the call.
-func (check *Checker) argument(sig *Signature, i int, x *operand, ellipsis token.Pos) {
+func (check *Checker) argument(fun ast.Expr, sig *Signature, i int, x *operand, ellipsis token.Pos) {
+	check.singleValue(x)
+	if x.mode == invalid {
+		return
+	}
+
 	n := sig.params.Len()
 
 	// determine parameter type
@@ -241,18 +246,12 @@ func (check *Checker) argument(sig *Signature, i int, x *operand, ellipsis token
 	}
 
 	if ellipsis.IsValid() {
-		// argument is of the form x...
+		// argument is of the form x... and x is single-valued
 		if i != n-1 {
 			check.errorf(ellipsis, "can only use ... with matching parameter")
 			return
 		}
-		switch t := x.typ.Underlying().(type) {
-		case *Slice:
-			// ok
-		case *Tuple:
-			check.errorf(ellipsis, "cannot use ... with %d-valued expression %s", t.Len(), x)
-			return
-		default:
+		if _, ok := x.typ.Underlying().(*Slice); !ok {
 			check.errorf(x.pos(), "cannot use %s as parameter of type %s", x, typ)
 			return
 		}
@@ -261,9 +260,7 @@ func (check *Checker) argument(sig *Signature, i int, x *operand, ellipsis token
 		typ = typ.(*Slice).elem
 	}
 
-	if !check.assignment(x, typ) && x.mode != invalid {
-		check.errorf(x.pos(), "cannot pass argument %s to parameter of type %s", x, typ)
-	}
+	check.assignment(x, typ, check.sprintf("argument to %s", fun))
 }
 
 func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
diff --git a/src/go/types/check_test.go b/src/go/types/check_test.go
index 5e34c65..5e2043b 100644
--- a/src/go/types/check_test.go
+++ b/src/go/types/check_test.go
@@ -55,6 +55,7 @@ var tests = [][]string{
 	{"testdata/errors.src"},
 	{"testdata/importdecl0a.src", "testdata/importdecl0b.src"},
 	{"testdata/importdecl1a.src", "testdata/importdecl1b.src"},
+	{"testdata/importC.src"}, // special handling in checkFiles
 	{"testdata/cycles.src"},
 	{"testdata/cycles1.src"},
 	{"testdata/cycles2.src"},
@@ -245,6 +246,10 @@ func checkFiles(t *testing.T, testfiles []string) {
 
 	// typecheck and collect typechecker errors
 	var conf Config
+	// special case for importC.src
+	if len(testfiles) == 1 && testfiles[0] == "testdata/importC.src" {
+		conf.FakeImportC = true
+	}
 	conf.Importer = importer.Default()
 	conf.Error = func(err error) {
 		if *listErrors {
diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go
index 74826ce..f98cc8d 100644
--- a/src/go/types/conversions.go
+++ b/src/go/types/conversions.go
@@ -18,7 +18,7 @@ func (check *Checker) conversion(x *operand, T Type) {
 	case constArg && isConstType(T):
 		// constant conversion
 		switch t := T.Underlying().(*Basic); {
-		case representableConst(x.val, check.conf, t.kind, &x.val):
+		case representableConst(x.val, check.conf, t, &x.val):
 			ok = true
 		case isInteger(x.typ) && isString(t):
 			codepoint := int64(-1)
@@ -65,7 +65,7 @@ func (check *Checker) conversion(x *operand, T Type) {
 
 func (x *operand) convertibleTo(conf *Config, T Type) bool {
 	// "x is assignable to T"
-	if x.assignableTo(conf, T) {
+	if x.assignableTo(conf, T, nil) {
 		return true
 	}
 
diff --git a/src/go/types/decl.go b/src/go/types/decl.go
index 8e9e5f3..f064f68 100644
--- a/src/go/types/decl.go
+++ b/src/go/types/decl.go
@@ -156,7 +156,7 @@ func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) {
 		assert(lhs == nil || lhs[0] == obj)
 		var x operand
 		check.expr(&x, init)
-		check.initVar(obj, &x, false)
+		check.initVar(obj, &x, "variable declaration")
 		return
 	}
 
diff --git a/src/go/types/eval_test.go b/src/go/types/eval_test.go
index 7e0be43..6032112 100644
--- a/src/go/types/eval_test.go
+++ b/src/go/types/eval_test.go
@@ -48,7 +48,7 @@ func testEval(t *testing.T, fset *token.FileSet, pkg *Package, pos token.Pos, ex
 	// compare values
 	gotStr := ""
 	if gotTv.Value != nil {
-		gotStr = gotTv.Value.String()
+		gotStr = gotTv.Value.ExactString()
 	}
 	if gotStr != valStr {
 		t.Errorf("Eval(%q) got value %s, want %s", expr, gotStr, valStr)
diff --git a/src/go/types/expr.go b/src/go/types/expr.go
index 7d00dd5..f7c4a17 100644
--- a/src/go/types/expr.go
+++ b/src/go/types/expr.go
@@ -180,25 +180,31 @@ func roundFloat64(x constant.Value) constant.Value {
 }
 
 // representableConst reports whether x can be represented as
-// value of the given basic type kind and for the configuration
+// value of the given basic type and for the configuration
 // provided (only needed for int/uint sizes).
 //
 // If rounded != nil, *rounded is set to the rounded value of x for
-// representable floating-point values; it is left alone otherwise.
+// representable floating-point and complex values, and to an Int
+// value for integer values; it is left alone otherwise.
 // It is ok to provide the addressof the first argument for rounded.
-func representableConst(x constant.Value, conf *Config, as BasicKind, rounded *constant.Value) bool {
-	switch x.Kind() {
-	case constant.Unknown:
-		return true
-
-	case constant.Bool:
-		return as == Bool || as == UntypedBool
+func representableConst(x constant.Value, conf *Config, typ *Basic, rounded *constant.Value) bool {
+	if x.Kind() == constant.Unknown {
+		return true // avoid follow-up errors
+	}
 
-	case constant.Int:
+	switch {
+	case isInteger(typ):
+		x := constant.ToInt(x)
+		if x.Kind() != constant.Int {
+			return false
+		}
+		if rounded != nil {
+			*rounded = x
+		}
 		if x, ok := constant.Int64Val(x); ok {
-			switch as {
+			switch typ.kind {
 			case Int:
-				var s = uint(conf.sizeof(Typ[as])) * 8
+				var s = uint(conf.sizeof(typ)) * 8
 				return int64(-1)<<(s-1) <= x && x <= int64(1)<<(s-1)-1
 			case Int8:
 				const s = 8
@@ -209,10 +215,10 @@ func representableConst(x constant.Value, conf *Config, as BasicKind, rounded *c
 			case Int32:
 				const s = 32
 				return -1<<(s-1) <= x && x <= 1<<(s-1)-1
-			case Int64:
+			case Int64, UntypedInt:
 				return true
 			case Uint, Uintptr:
-				if s := uint(conf.sizeof(Typ[as])) * 8; s < 64 {
+				if s := uint(conf.sizeof(typ)) * 8; s < 64 {
 					return 0 <= x && x <= int64(1)<<s-1
 				}
 				return 0 <= x
@@ -227,44 +233,28 @@ func representableConst(x constant.Value, conf *Config, as BasicKind, rounded *c
 				return 0 <= x && x <= 1<<s-1
 			case Uint64:
 				return 0 <= x
-			case Float32, Float64, Complex64, Complex128,
-				UntypedInt, UntypedFloat, UntypedComplex:
-				return true
+			default:
+				unreachable()
 			}
 		}
-
-		n := constant.BitLen(x)
-		switch as {
+		// x does not fit into int64
+		switch n := constant.BitLen(x); typ.kind {
 		case Uint, Uintptr:
-			var s = uint(conf.sizeof(Typ[as])) * 8
+			var s = uint(conf.sizeof(typ)) * 8
 			return constant.Sign(x) >= 0 && n <= int(s)
 		case Uint64:
 			return constant.Sign(x) >= 0 && n <= 64
-		case Float32, Complex64:
-			if rounded == nil {
-				return fitsFloat32(x)
-			}
-			r := roundFloat32(x)
-			if r != nil {
-				*rounded = r
-				return true
-			}
-		case Float64, Complex128:
-			if rounded == nil {
-				return fitsFloat64(x)
-			}
-			r := roundFloat64(x)
-			if r != nil {
-				*rounded = r
-				return true
-			}
-		case UntypedInt, UntypedFloat, UntypedComplex:
+		case UntypedInt:
 			return true
 		}
 
-	case constant.Float:
-		switch as {
-		case Float32, Complex64:
+	case isFloat(typ):
+		x := constant.ToFloat(x)
+		if x.Kind() != constant.Float {
+			return false
+		}
+		switch typ.kind {
+		case Float32:
 			if rounded == nil {
 				return fitsFloat32(x)
 			}
@@ -273,7 +263,7 @@ func representableConst(x constant.Value, conf *Config, as BasicKind, rounded *c
 				*rounded = r
 				return true
 			}
-		case Float64, Complex128:
+		case Float64:
 			if rounded == nil {
 				return fitsFloat64(x)
 			}
@@ -282,12 +272,18 @@ func representableConst(x constant.Value, conf *Config, as BasicKind, rounded *c
 				*rounded = r
 				return true
 			}
-		case UntypedFloat, UntypedComplex:
+		case UntypedFloat:
 			return true
+		default:
+			unreachable()
 		}
 
-	case constant.Complex:
-		switch as {
+	case isComplex(typ):
+		x := constant.ToComplex(x)
+		if x.Kind() != constant.Complex {
+			return false
+		}
+		switch typ.kind {
 		case Complex64:
 			if rounded == nil {
 				return fitsFloat32(constant.Real(x)) && fitsFloat32(constant.Imag(x))
@@ -310,13 +306,15 @@ func representableConst(x constant.Value, conf *Config, as BasicKind, rounded *c
 			}
 		case UntypedComplex:
 			return true
+		default:
+			unreachable()
 		}
 
-	case constant.String:
-		return as == String || as == UntypedString
+	case isString(typ):
+		return x.Kind() == constant.String
 
-	default:
-		unreachable()
+	case isBoolean(typ):
+		return x.Kind() == constant.Bool
 	}
 
 	return false
@@ -325,7 +323,7 @@ func representableConst(x constant.Value, conf *Config, as BasicKind, rounded *c
 // representable checks that a constant operand is representable in the given basic type.
 func (check *Checker) representable(x *operand, typ *Basic) {
 	assert(x.mode == constant_)
-	if !representableConst(x.val, check.conf, typ.kind, &x.val) {
+	if !representableConst(x.val, check.conf, typ, &x.val) {
 		var msg string
 		if isNumeric(x.typ) && isNumeric(typ) {
 			// numeric conversion : error msg
@@ -498,8 +496,6 @@ func (check *Checker) convertUntyped(x *operand, target Type) {
 				return
 			}
 			// expression value may have been rounded - update if needed
-			// TODO(gri) A floating-point value may silently underflow to
-			// zero. If it was negative, the sign is lost. See issue 6898.
 			check.updateExprVal(x.expr, x.val)
 		} else {
 			// Non-constant untyped values may appear as the
@@ -570,7 +566,7 @@ func (check *Checker) comparison(x, y *operand, op token.Token) {
 	// spec: "In any comparison, the first operand must be assignable
 	// to the type of the second operand, or vice versa."
 	err := ""
-	if x.assignableTo(check.conf, y.typ) || y.assignableTo(check.conf, x.typ) {
+	if x.assignableTo(check.conf, y.typ, nil) || y.assignableTo(check.conf, x.typ, nil) {
 		defined := false
 		switch op {
 		case token.EQL, token.NEQ:
@@ -618,12 +614,19 @@ func (check *Checker) comparison(x, y *operand, op token.Token) {
 	x.typ = Typ[UntypedBool]
 }
 
-func (check *Checker) shift(x, y *operand, op token.Token) {
+func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) {
 	untypedx := isUntyped(x.typ)
 
-	// The lhs must be of integer type or be representable
-	// as an integer; otherwise the shift has no chance.
-	if !x.isInteger() {
+	var xval constant.Value
+	if x.mode == constant_ {
+		xval = constant.ToInt(x.val)
+	}
+
+	if isInteger(x.typ) || untypedx && xval != nil && xval.Kind() == constant.Int {
+		// The lhs is of integer type or an untyped constant representable
+		// as an integer. Nothing to do.
+	} else {
+		// shift has no chance
 		check.invalidOp(x.pos(), "shifted operand %s must be integer", x)
 		x.mode = invalid
 		return
@@ -633,7 +636,7 @@ func (check *Checker) shift(x, y *operand, op token.Token) {
 	// integer type or be an untyped constant that can be converted to
 	// unsigned integer type."
 	switch {
-	case isInteger(y.typ) && isUnsigned(y.typ):
+	case isUnsigned(y.typ):
 		// nothing to do
 	case isUntyped(y.typ):
 		check.convertUntyped(y, Typ[UntypedInt])
@@ -650,14 +653,15 @@ func (check *Checker) shift(x, y *operand, op token.Token) {
 	if x.mode == constant_ {
 		if y.mode == constant_ {
 			// rhs must be an integer value
-			if !y.isInteger() {
+			yval := constant.ToInt(y.val)
+			if yval.Kind() != constant.Int {
 				check.invalidOp(y.pos(), "shift count %s must be unsigned integer", y)
 				x.mode = invalid
 				return
 			}
 			// rhs must be within reasonable bounds
 			const stupidShift = 1023 - 1 + 52 // so we can express smallestFloat64
-			s, ok := constant.Uint64Val(y.val)
+			s, ok := constant.Uint64Val(yval)
 			if !ok || s > stupidShift {
 				check.invalidOp(y.pos(), "stupid shift count %s", y)
 				x.mode = invalid
@@ -670,7 +674,16 @@ func (check *Checker) shift(x, y *operand, op token.Token) {
 			if !isInteger(x.typ) {
 				x.typ = Typ[UntypedInt]
 			}
-			x.val = constant.Shift(x.val, op, uint(s))
+			// x is a constant so xval != nil and it must be of Int kind.
+			x.val = constant.Shift(xval, op, uint(s))
+			// Typed constants must be representable in
+			// their type after each constant operation.
+			if isTyped(x.typ) {
+				if e != nil {
+					x.expr = e // for better error message
+				}
+				check.representable(x, x.typ.Underlying().(*Basic))
+			}
 			return
 		}
 
@@ -681,13 +694,24 @@ func (check *Checker) shift(x, y *operand, op token.Token) {
 			// constant is what it would be if the shift expression
 			// were replaced by its left operand alone.".
 			//
-			// Delay operand checking until we know the final type:
-			// The lhs expression must be in the untyped map, mark
-			// the entry as lhs shift operand.
-			info, found := check.untyped[x.expr]
-			assert(found)
-			info.isLhs = true
-			check.untyped[x.expr] = info
+			// Delay operand checking until we know the final type
+			// by marking the lhs expression as lhs shift operand.
+			//
+			// Usually (in correct programs), the lhs expression
+			// is in the untyped map. However, it is possible to
+			// create incorrect programs where the same expression
+			// is evaluated twice (via a declaration cycle) such
+			// that the lhs expression type is determined in the
+			// first round and thus deleted from the map, and then
+			// not found in the second round (double insertion of
+			// the same expr node still just leads to one entry for
+			// that node, and it can only be deleted once).
+			// Be cautious and check for presence of entry.
+			// Example: var e, f = int(1<<""[f]) // issue 11347
+			if info, found := check.untyped[x.expr]; found {
+				info.isLhs = true
+				check.untyped[x.expr] = info
+			}
 			// keep x's type
 			x.mode = value
 			return
@@ -742,7 +766,7 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o
 	}
 
 	if isShift(op) {
-		check.shift(x, &y, op)
+		check.shift(x, &y, e, op)
 		return
 	}
 
@@ -783,12 +807,14 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o
 	}
 
 	if x.mode == constant_ && y.mode == constant_ {
+		xval := x.val
+		yval := y.val
 		typ := x.typ.Underlying().(*Basic)
 		// force integer division of integer operands
 		if op == token.QUO && isInteger(typ) {
 			op = token.QUO_ASSIGN
 		}
-		x.val = constant.BinaryOp(x.val, op, y.val)
+		x.val = constant.BinaryOp(xval, op, yval)
 		// Typed constants must be representable in
 		// their type after each constant operation.
 		if isTyped(typ) {
@@ -832,7 +858,7 @@ func (check *Checker) index(index ast.Expr, max int64) (i int64, valid bool) {
 			check.invalidArg(x.pos(), "index %s must not be negative", &x)
 			return
 		}
-		i, valid = constant.Int64Val(x.val)
+		i, valid = constant.Int64Val(constant.ToInt(x.val))
 		if !valid || max >= 0 && i >= max {
 			check.errorf(x.pos(), "index %s is out of bounds", &x)
 			return i, false
@@ -887,9 +913,7 @@ func (check *Checker) indexedElts(elts []ast.Expr, typ Type, length int64) int64
 		// check element against composite literal element type
 		var x operand
 		check.exprWithHint(&x, eval, typ)
-		if !check.assignment(&x, typ) && x.mode != invalid {
-			check.errorf(x.pos(), "cannot use %s as %s value in array or slice literal", &x, typ)
-		}
+		check.assignment(&x, typ, "array or slice literal")
 	}
 	return max
 }
@@ -1051,12 +1075,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
 					visited[i] = true
 					check.expr(x, kv.Value)
 					etyp := fld.typ
-					if !check.assignment(x, etyp) {
-						if x.mode != invalid {
-							check.errorf(x.pos(), "cannot use %s as %s value in struct literal", x, etyp)
-						}
-						continue
-					}
+					check.assignment(x, etyp, "struct literal")
 				}
 			} else {
 				// no element must have a key
@@ -1077,12 +1096,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
 						continue
 					}
 					etyp := fld.typ
-					if !check.assignment(x, etyp) {
-						if x.mode != invalid {
-							check.errorf(x.pos(), "cannot use %s as %s value in struct literal", x, etyp)
-						}
-						continue
-					}
+					check.assignment(x, etyp, "struct literal")
 				}
 				if len(e.Elts) < len(fields) {
 					check.error(e.Rbrace, "too few values in struct literal")
@@ -1109,10 +1123,8 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
 					continue
 				}
 				check.exprWithHint(x, kv.Key, utyp.key)
-				if !check.assignment(x, utyp.key) {
-					if x.mode != invalid {
-						check.errorf(x.pos(), "cannot use %s as %s key in map literal", x, utyp.key)
-					}
+				check.assignment(x, utyp.key, "map literal")
+				if x.mode == invalid {
 					continue
 				}
 				if x.mode == constant_ {
@@ -1136,12 +1148,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
 					}
 				}
 				check.exprWithHint(x, kv.Value, utyp.elem)
-				if !check.assignment(x, utyp.elem) {
-					if x.mode != invalid {
-						check.errorf(x.pos(), "cannot use %s as %s value in map literal", x, utyp.elem)
-					}
-					continue
-				}
+				check.assignment(x, utyp.elem, "map literal")
 			}
 
 		default:
@@ -1209,10 +1216,8 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
 		case *Map:
 			var key operand
 			check.expr(&key, e.Index)
-			if !check.assignment(&key, typ.key) {
-				if key.mode != invalid {
-					check.invalidOp(key.pos(), "cannot use %s as map index of type %s", &key, typ.key)
-				}
+			check.assignment(&key, typ.key, "map index")
+			if x.mode == invalid {
 				goto Error
 			}
 			x.mode = mapindex
@@ -1245,7 +1250,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
 		switch typ := x.typ.Underlying().(type) {
 		case *Basic:
 			if isString(typ) {
-				if slice3(e) {
+				if e.Slice3 {
 					check.invalidOp(x.pos(), "3-index slice of string")
 					goto Error
 				}
@@ -1289,14 +1294,14 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
 		x.mode = value
 
 		// spec: "Only the first index may be omitted; it defaults to 0."
-		if slice3(e) && (e.High == nil || sliceMax(e) == nil) {
+		if e.Slice3 && (e.High == nil || e.Max == nil) {
 			check.error(e.Rbrack, "2nd and 3rd index required in 3-index slice")
 			goto Error
 		}
 
 		// check indices
 		var ind [3]int64
-		for i, expr := range []ast.Expr{e.Low, e.High, sliceMax(e)} {
+		for i, expr := range []ast.Expr{e.Low, e.High, e.Max} {
 			x := int64(-1)
 			switch {
 			case expr != nil:
@@ -1442,45 +1447,64 @@ func (check *Checker) typeAssertion(pos token.Pos, x *operand, xtyp *Interface,
 	check.errorf(pos, "%s cannot have dynamic type %s (%s %s)", x, T, msg, method.name)
 }
 
+func (check *Checker) singleValue(x *operand) {
+	if x.mode == value {
+		// tuple types are never named - no need for underlying type below
+		if t, ok := x.typ.(*Tuple); ok {
+			assert(t.Len() != 1)
+			check.errorf(x.pos(), "%d-valued %s where single value is expected", t.Len(), x)
+			x.mode = invalid
+		}
+	}
+}
+
 // expr typechecks expression e and initializes x with the expression value.
+// The result must be a single value.
 // If an error occurred, x.mode is set to invalid.
 //
 func (check *Checker) expr(x *operand, e ast.Expr) {
+	check.multiExpr(x, e)
+	check.singleValue(x)
+}
+
+// multiExpr is like expr but the result may be a multi-value.
+func (check *Checker) multiExpr(x *operand, e ast.Expr) {
 	check.rawExpr(x, e, nil)
 	var msg string
 	switch x.mode {
 	default:
 		return
 	case novalue:
-		msg = "used as value"
+		msg = "%s used as value"
 	case builtin:
-		msg = "must be called"
+		msg = "%s must be called"
 	case typexpr:
-		msg = "is not an expression"
+		msg = "%s is not an expression"
 	}
-	check.errorf(x.pos(), "%s %s", x, msg)
+	check.errorf(x.pos(), msg, x)
 	x.mode = invalid
 }
 
-// exprWithHint typechecks expression e and initializes x with the expression value.
+// exprWithHint typechecks expression e and initializes x with the expression value;
+// hint is the type of a composite literal element.
 // If an error occurred, x.mode is set to invalid.
-// If hint != nil, it is the type of a composite literal element.
 //
 func (check *Checker) exprWithHint(x *operand, e ast.Expr, hint Type) {
 	assert(hint != nil)
 	check.rawExpr(x, e, hint)
+	check.singleValue(x)
 	var msg string
 	switch x.mode {
 	default:
 		return
 	case novalue:
-		msg = "used as value"
+		msg = "%s used as value"
 	case builtin:
-		msg = "must be called"
+		msg = "%s must be called"
 	case typexpr:
-		msg = "is not an expression"
+		msg = "%s is not an expression"
 	}
-	check.errorf(x.pos(), "%s %s", x, msg)
+	check.errorf(x.pos(), msg, x)
 	x.mode = invalid
 }
 
@@ -1489,6 +1513,7 @@ func (check *Checker) exprWithHint(x *operand, e ast.Expr, hint Type) {
 //
 func (check *Checker) exprOrType(x *operand, e ast.Expr) {
 	check.rawExpr(x, e, nil)
+	check.singleValue(x)
 	if x.mode == novalue {
 		check.errorf(x.pos(), "%s used as value or type", x)
 		x.mode = invalid
diff --git a/src/go/types/go11.go b/src/go/types/go11.go
deleted file mode 100644
index cf41cab..0000000
--- a/src/go/types/go11.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2013 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.
-
-// +build !go1.2
-
-package types
-
-import "go/ast"
-
-func slice3(x *ast.SliceExpr) bool {
-	return false
-}
-
-func sliceMax(x *ast.SliceExpr) ast.Expr {
-	return nil
-}
diff --git a/src/go/types/go12.go b/src/go/types/go12.go
deleted file mode 100644
index 2017442..0000000
--- a/src/go/types/go12.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2013 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.
-
-// +build go1.2
-
-package types
-
-import "go/ast"
-
-func slice3(x *ast.SliceExpr) bool {
-	return x.Slice3
-}
-
-func sliceMax(x *ast.SliceExpr) ast.Expr {
-	return x.Max
-}
diff --git a/src/go/types/gotype.go b/src/go/types/gotype.go
new file mode 100644
index 0000000..0a36c08
--- /dev/null
+++ b/src/go/types/gotype.go
@@ -0,0 +1,322 @@
+// Copyright 2011 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.
+
+// +build ignore
+
+// Build this command explicitly: go build gotype.go
+
+/*
+The gotype command does syntactic and semantic analysis of Go files
+and packages like the front-end of a Go compiler. Errors are reported
+if the analysis fails; otherwise gotype is quiet (unless -v is set).
+
+Without a list of paths, gotype reads from standard input, which
+must provide a single Go source file defining a complete package.
+
+If a single path is specified that is a directory, gotype checks
+the Go files in that directory; they must all belong to the same
+package.
+
+Otherwise, each path must be the filename of Go file belonging to
+the same package.
+
+Usage:
+	gotype [flags] [path...]
+
+The flags are:
+	-a
+		use all (incl. _test.go) files when processing a directory
+	-e
+		report all errors (not just the first 10)
+	-v
+		verbose mode
+	-c
+		compiler used to compile packages (gc or gccgo); default: gc
+		(gotype based on Go1.5 and up only)
+	-gccgo
+		use gccimporter instead of gcimporter
+		(gotype based on Go1.4 and before only)
+
+Debugging flags:
+	-seq
+		parse sequentially, rather than in parallel
+	-ast
+		print AST (forces -seq)
+	-trace
+		print parse trace (forces -seq)
+	-comments
+		parse comments (ignored unless -ast or -trace is provided)
+
+Examples:
+
+To check the files a.go, b.go, and c.go:
+
+	gotype a.go b.go c.go
+
+To check an entire package in the directory dir and print the processed files:
+
+	gotype -v dir
+
+To check an entire package including tests in the local directory:
+
+	gotype -a .
+
+To verify the output of a pipe:
+
+	echo "package foo" | gotype
+
+*/
+package main
+
+import (
+	"flag"
+	"fmt"
+	"go/ast"
+	"go/build"
+	"go/importer"
+	"go/parser"
+	"go/scanner"
+	"go/token"
+	"go/types"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"time"
+)
+
+var (
+	// main operation modes
+	allFiles  = flag.Bool("a", false, "use all (incl. _test.go) files when processing a directory")
+	allErrors = flag.Bool("e", false, "report all errors (not just the first 10)")
+	verbose   = flag.Bool("v", false, "verbose mode")
+	gccgo     = flag.Bool("gccgo", false, "use gccgoimporter instead of gcimporter")
+
+	// debugging support
+	sequential    = flag.Bool("seq", false, "parse sequentially, rather than in parallel")
+	printAST      = flag.Bool("ast", false, "print AST (forces -seq)")
+	printTrace    = flag.Bool("trace", false, "print parse trace (forces -seq)")
+	parseComments = flag.Bool("comments", false, "parse comments (ignored unless -ast or -trace is provided)")
+)
+
+var (
+	fset       = token.NewFileSet()
+	errorCount = 0
+	parserMode parser.Mode
+	sizes      types.Sizes
+)
+
+func initParserMode() {
+	if *allErrors {
+		parserMode |= parser.AllErrors
+	}
+	if *printTrace {
+		parserMode |= parser.Trace
+	}
+	if *parseComments && (*printAST || *printTrace) {
+		parserMode |= parser.ParseComments
+	}
+}
+
+func initSizes() {
+	wordSize := 8
+	maxAlign := 8
+	switch build.Default.GOARCH {
+	case "386", "arm":
+		wordSize = 4
+		maxAlign = 4
+		// add more cases as needed
+	}
+	sizes = &types.StdSizes{WordSize: int64(wordSize), MaxAlign: int64(maxAlign)}
+}
+
+func usage() {
+	fmt.Fprintln(os.Stderr, "usage: gotype [flags] [path ...]")
+	flag.PrintDefaults()
+	os.Exit(2)
+}
+
+func report(err error) {
+	scanner.PrintError(os.Stderr, err)
+	if list, ok := err.(scanner.ErrorList); ok {
+		errorCount += len(list)
+		return
+	}
+	errorCount++
+}
+
+// parse may be called concurrently
+func parse(filename string, src interface{}) (*ast.File, error) {
+	if *verbose {
+		fmt.Println(filename)
+	}
+	file, err := parser.ParseFile(fset, filename, src, parserMode) // ok to access fset concurrently
+	if *printAST {
+		ast.Print(fset, file)
+	}
+	return file, err
+}
+
+func parseStdin() (*ast.File, error) {
+	src, err := ioutil.ReadAll(os.Stdin)
+	if err != nil {
+		return nil, err
+	}
+	return parse("<standard input>", src)
+}
+
+func parseFiles(filenames []string) ([]*ast.File, error) {
+	files := make([]*ast.File, len(filenames))
+
+	if *sequential {
+		for i, filename := range filenames {
+			var err error
+			files[i], err = parse(filename, nil)
+			if err != nil {
+				return nil, err // leave unfinished goroutines hanging
+			}
+		}
+	} else {
+		type parseResult struct {
+			file *ast.File
+			err  error
+		}
+
+		out := make(chan parseResult)
+		for _, filename := range filenames {
+			go func(filename string) {
+				file, err := parse(filename, nil)
+				out <- parseResult{file, err}
+			}(filename)
+		}
+
+		for i := range filenames {
+			res := <-out
+			if res.err != nil {
+				return nil, res.err // leave unfinished goroutines hanging
+			}
+			files[i] = res.file
+		}
+	}
+
+	return files, nil
+}
+
+func parseDir(dirname string) ([]*ast.File, error) {
+	ctxt := build.Default
+	pkginfo, err := ctxt.ImportDir(dirname, 0)
+	if _, nogo := err.(*build.NoGoError); err != nil && !nogo {
+		return nil, err
+	}
+	filenames := append(pkginfo.GoFiles, pkginfo.CgoFiles...)
+	if *allFiles {
+		filenames = append(filenames, pkginfo.TestGoFiles...)
+	}
+
+	// complete file names
+	for i, filename := range filenames {
+		filenames[i] = filepath.Join(dirname, filename)
+	}
+
+	return parseFiles(filenames)
+}
+
+func getPkgFiles(args []string) ([]*ast.File, error) {
+	if len(args) == 0 {
+		// stdin
+		file, err := parseStdin()
+		if err != nil {
+			return nil, err
+		}
+		return []*ast.File{file}, nil
+	}
+
+	if len(args) == 1 {
+		// possibly a directory
+		path := args[0]
+		info, err := os.Stat(path)
+		if err != nil {
+			return nil, err
+		}
+		if info.IsDir() {
+			return parseDir(path)
+		}
+	}
+
+	// list of files
+	return parseFiles(args)
+}
+
+func checkPkgFiles(files []*ast.File) {
+	compiler := "gc"
+	if *gccgo {
+		compiler = "gccgo"
+	}
+	type bailout struct{}
+	conf := types.Config{
+		FakeImportC: true,
+		Error: func(err error) {
+			if !*allErrors && errorCount >= 10 {
+				panic(bailout{})
+			}
+			report(err)
+		},
+		Importer: importer.For(compiler, nil),
+		Sizes:    sizes,
+	}
+
+	defer func() {
+		switch p := recover().(type) {
+		case nil, bailout:
+			// normal return or early exit
+		default:
+			// re-panic
+			panic(p)
+		}
+	}()
+
+	const path = "pkg" // any non-empty string will do for now
+	conf.Check(path, fset, files, nil)
+}
+
+func printStats(d time.Duration) {
+	fileCount := 0
+	lineCount := 0
+	fset.Iterate(func(f *token.File) bool {
+		fileCount++
+		lineCount += f.LineCount()
+		return true
+	})
+
+	fmt.Printf(
+		"%s (%d files, %d lines, %d lines/s)\n",
+		d, fileCount, lineCount, int64(float64(lineCount)/d.Seconds()),
+	)
+}
+
+func main() {
+	flag.Usage = usage
+	flag.Parse()
+	if *printAST || *printTrace {
+		*sequential = true
+	}
+	initParserMode()
+	initSizes()
+
+	start := time.Now()
+
+	files, err := getPkgFiles(flag.Args())
+	if err != nil {
+		report(err)
+		os.Exit(2)
+	}
+
+	checkPkgFiles(files)
+	if errorCount > 0 {
+		os.Exit(2)
+	}
+
+	if *verbose {
+		printStats(time.Since(start))
+	}
+}
diff --git a/src/go/types/issues_test.go b/src/go/types/issues_test.go
index 672c78d..3884735 100644
--- a/src/go/types/issues_test.go
+++ b/src/go/types/issues_test.go
@@ -11,6 +11,7 @@ import (
 	"go/ast"
 	"go/importer"
 	"go/parser"
+	"internal/testenv"
 	"sort"
 	"strings"
 	"testing"
@@ -204,3 +205,90 @@ L7 uses var z int`
 		t.Errorf("Unexpected defs/uses\ngot:\n%s\nwant:\n%s", got, want)
 	}
 }
+
+// This tests that the package associated with the types.Object.Pkg method
+// is the type's package independent of the order in which the imports are
+// listed in the sources src1, src2 below.
+// The actual issue is in go/internal/gcimporter which has a corresponding
+// test; we leave this test here to verify correct behavior at the go/types
+// level.
+func TestIssue13898(t *testing.T) {
+	testenv.MustHaveGoBuild(t)
+
+	const src0 = `
+package main
+
+import "go/types"
+
+func main() {
+	var info types.Info
+	for _, obj := range info.Uses {
+		_ = obj.Pkg()
+	}
+}
+`
+	// like src0, but also imports go/importer
+	const src1 = `
+package main
+
+import (
+	"go/types"
+	_ "go/importer"
+)
+
+func main() {
+	var info types.Info
+	for _, obj := range info.Uses {
+		_ = obj.Pkg()
+	}
+}
+`
+	// like src1 but with different import order
+	// (used to fail with this issue)
+	const src2 = `
+package main
+
+import (
+	_ "go/importer"
+	"go/types"
+)
+
+func main() {
+	var info types.Info
+	for _, obj := range info.Uses {
+		_ = obj.Pkg()
+	}
+}
+`
+	f := func(test, src string) {
+		f, err := parser.ParseFile(fset, "", src, 0)
+		if err != nil {
+			t.Fatal(err)
+		}
+		cfg := Config{Importer: importer.Default()}
+		info := Info{Uses: make(map[*ast.Ident]Object)}
+		_, err = cfg.Check("main", fset, []*ast.File{f}, &info)
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		var pkg *Package
+		count := 0
+		for id, obj := range info.Uses {
+			if id.Name == "Pkg" {
+				pkg = obj.Pkg()
+				count++
+			}
+		}
+		if count != 1 {
+			t.Fatalf("%s: got %d entries named Pkg; want 1", test, count)
+		}
+		if pkg.Name() != "types" {
+			t.Fatalf("%s: got %v; want package types", test, pkg)
+		}
+	}
+
+	f("src0", src0)
+	f("src1", src1)
+	f("src2", src2)
+}
diff --git a/src/go/types/operand.go b/src/go/types/operand.go
index d3bab51..b2f16b6 100644
--- a/src/go/types/operand.go
+++ b/src/go/types/operand.go
@@ -166,13 +166,6 @@ func (x *operand) String() string {
 
 // setConst sets x to the untyped constant for literal lit.
 func (x *operand) setConst(tok token.Token, lit string) {
-	val := constant.MakeFromLiteral(lit, tok, 0)
-	if val == nil {
-		// TODO(gri) Should we make it an unknown constant instead?
-		x.mode = invalid
-		return
-	}
-
 	var kind BasicKind
 	switch tok {
 	case token.INT:
@@ -185,11 +178,13 @@ func (x *operand) setConst(tok token.Token, lit string) {
 		kind = UntypedRune
 	case token.STRING:
 		kind = UntypedString
+	default:
+		unreachable()
 	}
 
 	x.mode = constant_
 	x.typ = Typ[kind]
-	x.val = val
+	x.val = constant.MakeFromLiteral(lit, tok, 0)
 }
 
 // isNil reports whether x is the nil value.
@@ -202,7 +197,9 @@ func (x *operand) isNil() bool {
 //           overlapping in functionality. Need to simplify and clean up.
 
 // assignableTo reports whether x is assignable to a variable of type T.
-func (x *operand) assignableTo(conf *Config, T Type) bool {
+// If the result is false and a non-nil reason is provided, it may be set
+// to a more detailed explanation of the failure (result != "").
+func (x *operand) assignableTo(conf *Config, T Type, reason *string) bool {
 	if x.mode == invalid || T == Typ[Invalid] {
 		return true // avoid spurious errors
 	}
@@ -217,51 +214,17 @@ func (x *operand) assignableTo(conf *Config, T Type) bool {
 	Vu := V.Underlying()
 	Tu := T.Underlying()
 
-	// T is an interface type and x implements T
-	// (Do this check first as it might succeed early.)
-	if Ti, ok := Tu.(*Interface); ok {
-		if Implements(x.typ, Ti) {
-			return true
-		}
-	}
-
-	// x's type V and T have identical underlying types
-	// and at least one of V or T is not a named type
-	if Identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) {
-		return true
-	}
-
-	// x is a bidirectional channel value, T is a channel
-	// type, x's type V and T have identical element types,
-	// and at least one of V or T is not a named type
-	if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv {
-		if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) {
-			return !isNamed(V) || !isNamed(T)
-		}
-	}
-
-	// x is the predeclared identifier nil and T is a pointer,
-	// function, slice, map, channel, or interface type
-	if x.isNil() {
-		switch t := Tu.(type) {
-		case *Basic:
-			if t.kind == UnsafePointer {
-				return true
-			}
-		case *Pointer, *Signature, *Slice, *Map, *Chan, *Interface:
-			return true
-		}
-		return false
-	}
-
-	// x is an untyped constant representable by a value of type T
+	// x is an untyped value representable by a value of type T
 	// TODO(gri) This is borrowing from checker.convertUntyped and
 	//           checker.representable. Need to clean up.
 	if isUntyped(Vu) {
 		switch t := Tu.(type) {
 		case *Basic:
+			if x.isNil() && t.kind == UnsafePointer {
+				return true
+			}
 			if x.mode == constant_ {
-				return representableConst(x.val, conf, t.kind, nil)
+				return representableConst(x.val, conf, t, nil)
 			}
 			// The result of a comparison is an untyped boolean,
 			// but may not be a constant.
@@ -274,14 +237,37 @@ func (x *operand) assignableTo(conf *Config, T Type) bool {
 			return x.isNil()
 		}
 	}
+	// Vu is typed
 
-	return false
-}
+	// x's type V and T have identical underlying types
+	// and at least one of V or T is not a named type
+	if Identical(Vu, Tu) && (!isNamed(V) || !isNamed(T)) {
+		return true
+	}
+
+	// T is an interface type and x implements T
+	if Ti, ok := Tu.(*Interface); ok {
+		if m, wrongType := MissingMethod(x.typ, Ti, true); m != nil /* Implements(x.typ, Ti) */ {
+			if reason != nil {
+				if wrongType {
+					*reason = "wrong type for method " + m.Name()
+				} else {
+					*reason = "missing method " + m.Name()
+				}
+			}
+			return false
+		}
+		return true
+	}
+
+	// x is a bidirectional channel value, T is a channel
+	// type, x's type V and T have identical element types,
+	// and at least one of V or T is not a named type
+	if Vc, ok := Vu.(*Chan); ok && Vc.dir == SendRecv {
+		if Tc, ok := Tu.(*Chan); ok && Identical(Vc.elem, Tc.elem) {
+			return !isNamed(V) || !isNamed(T)
+		}
+	}
 
-// isInteger reports whether x is value of integer type
-// or an untyped constant representable as an integer.
-func (x *operand) isInteger() bool {
-	return x.mode == invalid ||
-		isInteger(x.typ) ||
-		isUntyped(x.typ) && x.mode == constant_ && representableConst(x.val, nil, UntypedInt, nil) // no *Config required for UntypedInt
+	return false
 }
diff --git a/src/go/types/package.go b/src/go/types/package.go
index 48fe839..4a432b5 100644
--- a/src/go/types/package.go
+++ b/src/go/types/package.go
@@ -36,6 +36,9 @@ func (pkg *Package) Path() string { return pkg.path }
 // Name returns the package name.
 func (pkg *Package) Name() string { return pkg.name }
 
+// SetName sets the package name.
+func (pkg *Package) SetName(name string) { pkg.name = name }
+
 // Scope returns the (complete or incomplete) package scope
 // holding the objects declared at package level (TypeNames,
 // Consts, Vars, and Funcs).
diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go
index c31ef42..1536df5 100644
--- a/src/go/types/resolver.go
+++ b/src/go/types/resolver.go
@@ -9,7 +9,6 @@ import (
 	"go/ast"
 	"go/constant"
 	"go/token"
-	pathLib "path"
 	"strconv"
 	"strings"
 	"unicode"
@@ -134,6 +133,20 @@ func (check *Checker) collectObjects() {
 		pkgImports[imp] = true
 	}
 
+	// srcDir is the directory used by the Importer to look up packages.
+	// The typechecker itself doesn't need this information so it is not
+	// explicitly provided. Instead, we extract it from position info of
+	// the source files as needed.
+	// This is the only place where the type-checker (just the importer)
+	// needs to know the actual source location of a file.
+	// TODO(gri) can we come up with a better API instead?
+	var srcDir string
+	if len(check.files) > 0 {
+		// FileName may be "" (typically for tests) in which case
+		// we get "." as the srcDir which is what we would want.
+		srcDir = dir(check.fset.Position(check.files[0].Name.Pos()).Filename)
+	}
+
 	for fileNo, file := range check.files {
 		// The package identifier denotes the current package,
 		// but there is no corresponding package object.
@@ -170,17 +183,20 @@ func (check *Checker) collectObjects() {
 							// TODO(gri) shouldn't create a new one each time
 							imp = NewPackage("C", "C")
 							imp.fake = true
-						} else if path == "unsafe" {
-							// package "unsafe" is known to the language
-							imp = Unsafe
 						} else {
-							if importer := check.conf.Importer; importer != nil {
+							// ordinary import
+							if importer := check.conf.Importer; importer == nil {
+								err = fmt.Errorf("Config.Importer not installed")
+							} else if importerFrom, ok := importer.(ImporterFrom); ok {
+								imp, err = importerFrom.ImportFrom(path, srcDir, 0)
+								if imp == nil && err == nil {
+									err = fmt.Errorf("Config.Importer.ImportFrom(%s, %s, 0) returned nil but no error", path, pkg.path)
+								}
+							} else {
 								imp, err = importer.Import(path)
 								if imp == nil && err == nil {
 									err = fmt.Errorf("Config.Importer.Import(%s) returned nil but no error", path)
 								}
-							} else {
-								err = fmt.Errorf("Config.Importer not installed")
 							}
 							if err != nil {
 								check.errorf(s.Path.Pos(), "could not import %s (%s)", path, err)
@@ -202,6 +218,11 @@ func (check *Checker) collectObjects() {
 						name := imp.name
 						if s.Name != nil {
 							name = s.Name.Name
+							if path == "C" {
+								// match cmd/compile (not prescribed by spec)
+								check.errorf(s.Name.Pos(), `cannot rename import "C"`)
+								continue
+							}
 							if name == "init" {
 								check.errorf(s.Name.Pos(), "cannot declare init - must be func")
 								continue
@@ -216,6 +237,11 @@ func (check *Checker) collectObjects() {
 							check.recordImplicit(s, obj)
 						}
 
+						if path == "C" {
+							// match cmd/compile (not prescribed by spec)
+							obj.used = true
+						}
+
 						// add import to file scope
 						if name == "." {
 							// merge imported scope with file scope
@@ -425,7 +451,7 @@ func (check *Checker) unusedImports() {
 				// since _ identifiers are not entered into scopes.
 				if !obj.used {
 					path := obj.imported.path
-					base := pathLib.Base(path)
+					base := pkgName(path)
 					if obj.name == base {
 						check.softErrorf(obj.pos, "%q imported but not used", path)
 					} else {
@@ -443,3 +469,23 @@ func (check *Checker) unusedImports() {
 		}
 	}
 }
+
+// pkgName returns the package name (last element) of an import path.
+func pkgName(path string) string {
+	if i := strings.LastIndex(path, "/"); i >= 0 {
+		path = path[i+1:]
+	}
+	return path
+}
+
+// dir makes a good-faith attempt to return the directory
+// portion of path. If path is empty, the result is ".".
+// (Per the go/build package dependency tests, we cannot import
+// path/filepath and simply use filepath.Dir.)
+func dir(path string) string {
+	if i := strings.LastIndexAny(path, `/\`); i > 0 {
+		return path[:i]
+	}
+	// i <= 0
+	return "."
+}
diff --git a/src/go/types/resolver_test.go b/src/go/types/resolver_test.go
index 34deae2..4bb63b6 100644
--- a/src/go/types/resolver_test.go
+++ b/src/go/types/resolver_test.go
@@ -18,16 +18,23 @@ import (
 )
 
 type resolveTestImporter struct {
-	importer Importer
+	importer ImporterFrom
 	imported map[string]bool
 }
 
-func (imp *resolveTestImporter) Import(path string) (*Package, error) {
+func (imp *resolveTestImporter) Import(string) (*Package, error) {
+	panic("should not be called")
+}
+
+func (imp *resolveTestImporter) ImportFrom(path, srcDir string, mode ImportMode) (*Package, error) {
+	if mode != 0 {
+		panic("mode must be 0")
+	}
 	if imp.importer == nil {
-		imp.importer = importer.Default()
+		imp.importer = importer.Default().(ImporterFrom)
 		imp.imported = make(map[string]bool)
 	}
-	pkg, err := imp.importer.Import(path)
+	pkg, err := imp.importer.ImportFrom(path, srcDir, mode)
 	if err != nil {
 		return nil, err
 	}
diff --git a/src/go/types/sizes.go b/src/go/types/sizes.go
index 56fb310..87c3ce4 100644
--- a/src/go/types/sizes.go
+++ b/src/go/types/sizes.go
@@ -132,13 +132,8 @@ func (s *StdSizes) Sizeof(T Type) int64 {
 		if n == 0 {
 			return 0
 		}
-		offsets := t.offsets
-		if t.offsets == nil {
-			// compute offsets on demand
-			offsets = s.Offsetsof(t.fields)
-			t.offsets = offsets
-		}
-		return offsets[n-1] + s.Sizeof(t.fields[n-1].typ)
+		setOffsets(t, s)
+		return t.offsets[n-1] + s.Sizeof(t.fields[n-1].typ)
 	case *Interface:
 		return s.WordSize * 2
 	}
@@ -159,24 +154,27 @@ func (conf *Config) alignof(T Type) int64 {
 }
 
 func (conf *Config) offsetsof(T *Struct) []int64 {
-	offsets := T.offsets
-	if offsets == nil && T.NumFields() > 0 {
+	var offsets []int64
+	if T.NumFields() > 0 {
 		// compute offsets on demand
 		if s := conf.Sizes; s != nil {
-			offsets = s.Offsetsof(T.fields)
-			// sanity checks
-			if len(offsets) != T.NumFields() {
-				panic("Config.Sizes.Offsetsof returned the wrong number of offsets")
-			}
-			for _, o := range offsets {
-				if o < 0 {
-					panic("Config.Sizes.Offsetsof returned an offset < 0")
+			calculated := setOffsets(T, s)
+			offsets = T.offsets
+			if calculated {
+				// sanity checks
+				if len(offsets) != T.NumFields() {
+					panic("Config.Sizes.Offsetsof returned the wrong number of offsets")
+				}
+				for _, o := range offsets {
+					if o < 0 {
+						panic("Config.Sizes.Offsetsof returned an offset < 0")
+					}
 				}
 			}
 		} else {
-			offsets = stdSizes.Offsetsof(T.fields)
+			setOffsets(T, &stdSizes)
+			offsets = T.offsets
 		}
-		T.offsets = offsets
 	}
 	return offsets
 }
@@ -209,3 +207,15 @@ func align(x, a int64) int64 {
 	y := x + a - 1
 	return y - y%a
 }
+
+// setOffsets sets the offsets of s for the given sizes if necessary.
+// The result is true if the offsets were not set before; otherwise it
+// is false.
+func setOffsets(s *Struct, sizes Sizes) bool {
+	var calculated bool
+	s.offsetsOnce.Do(func() {
+		calculated = true
+		s.offsets = sizes.Offsetsof(s.fields)
+	})
+	return calculated
+}
diff --git a/src/go/types/stdlib_test.go b/src/go/types/stdlib_test.go
index c6c946e..09f2585 100644
--- a/src/go/types/stdlib_test.go
+++ b/src/go/types/stdlib_test.go
@@ -127,6 +127,10 @@ func testTestDir(t *testing.T, path string, ignore ...string) {
 func TestStdTest(t *testing.T) {
 	testenv.MustHaveGoBuild(t)
 
+	if testing.Short() && testenv.Builder() == "" {
+		t.Skip("skipping in short mode")
+	}
+
 	// test/recover4.go is only built for Linux and Darwin.
 	// TODO(gri) Remove once tests consider +build tags (issue 10370).
 	if runtime.GOOS != "linux" && runtime.GOOS != "darwin" {
@@ -142,14 +146,15 @@ func TestStdTest(t *testing.T) {
 func TestStdFixed(t *testing.T) {
 	testenv.MustHaveGoBuild(t)
 
+	if testing.Short() && testenv.Builder() == "" {
+		t.Skip("skipping in short mode")
+	}
+
 	testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "fixedbugs"),
 		"bug248.go", "bug302.go", "bug369.go", // complex test instructions - ignore
-		"bug459.go",      // possibly incorrect test - see issue 6703 (pending spec clarification)
-		"issue3924.go",   // possibly incorrect test - see issue 6671 (pending spec clarification)
-		"issue6889.go",   // gc-specific test
-		"issue7746.go",   // large constants - consumes too much memory
-		"issue11326.go",  // large constants
-		"issue11326b.go", // large constants
+		"issue6889.go",  // gc-specific test
+		"issue7746.go",  // large constants - consumes too much memory
+		"issue11362.go", // canonical import path check
 	)
 }
 
@@ -250,7 +255,7 @@ func pkgFilenames(dir string) ([]string, error) {
 
 func walkDirs(t *testing.T, dir string) {
 	// limit run time for short tests
-	if testing.Short() && time.Since(start) >= 750*time.Millisecond {
+	if testing.Short() && time.Since(start) >= 10*time.Millisecond {
 		return
 	}
 
diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go
index 88a1d9b..e0129cf 100644
--- a/src/go/types/stmt.go
+++ b/src/go/types/stmt.go
@@ -155,25 +155,84 @@ func (check *Checker) suspendedCall(keyword string, call *ast.CallExpr) {
 	check.errorf(x.pos(), "%s %s %s", keyword, msg, &x)
 }
 
-func (check *Checker) caseValues(x operand /* copy argument (not *operand!) */, values []ast.Expr) {
-	// No duplicate checking for now. See issue 4524.
+// goVal returns the Go value for val, or nil.
+func goVal(val constant.Value) interface{} {
+	// val should exist, but be conservative and check
+	if val == nil {
+		return nil
+	}
+	// Match implementation restriction of other compilers.
+	// gc only checks duplicates for integer, floating-point
+	// and string values, so only create Go values for these
+	// types.
+	switch val.Kind() {
+	case constant.Int:
+		if x, ok := constant.Int64Val(val); ok {
+			return x
+		}
+		if x, ok := constant.Uint64Val(val); ok {
+			return x
+		}
+	case constant.Float:
+		if x, ok := constant.Float64Val(val); ok {
+			return x
+		}
+	case constant.String:
+		return constant.StringVal(val)
+	}
+	return nil
+}
+
+// A valueMap maps a case value (of a basic Go type) to a list of positions
+// where the same case value appeared, together with the corresponding case
+// types.
+// Since two case values may have the same "underlying" value but different
+// types we need to also check the value's types (e.g., byte(1) vs myByte(1))
+// when the switch expression is of interface type.
+type (
+	valueMap  map[interface{}][]valueType // underlying Go value -> valueType
+	valueType struct {
+		pos token.Pos
+		typ Type
+	}
+)
+
+func (check *Checker) caseValues(x *operand, values []ast.Expr, seen valueMap) {
+L:
 	for _, e := range values {
-		var y operand
-		check.expr(&y, e)
-		if y.mode == invalid {
-			return
-		}
-		// TODO(gri) The convertUntyped call pair below appears in other places. Factor!
-		// Order matters: By comparing y against x, error positions are at the case values.
-		check.convertUntyped(&y, x.typ)
-		if y.mode == invalid {
-			return
-		}
-		check.convertUntyped(&x, y.typ)
-		if x.mode == invalid {
-			return
+		var v operand
+		check.expr(&v, e)
+		if x.mode == invalid || v.mode == invalid {
+			continue L
+		}
+		check.convertUntyped(&v, x.typ)
+		if v.mode == invalid {
+			continue L
+		}
+		// Order matters: By comparing v against x, error positions are at the case values.
+		res := v // keep original v unchanged
+		check.comparison(&res, x, token.EQL)
+		if res.mode == invalid {
+			continue L
+		}
+		if v.mode != constant_ {
+			continue L // we're done
+		}
+		// look for duplicate values
+		if val := goVal(v.val); val != nil {
+			if list := seen[val]; list != nil {
+				// look for duplicate types for a given value
+				// (quadratic algorithm, but these lists tend to be very short)
+				for _, vt := range list {
+					if Identical(v.typ, vt.typ) {
+						check.errorf(v.pos(), "duplicate case %s in expression switch", &v)
+						check.error(vt.pos, "\tprevious case") // secondary error, \t indented
+						continue L
+					}
+				}
+			}
+			seen[val] = append(seen[val], valueType{v.pos(), v.typ})
 		}
-		check.comparison(&y, &x, token.EQL)
 	}
 }
 
@@ -182,15 +241,19 @@ L:
 	for _, e := range types {
 		T = check.typOrNil(e)
 		if T == Typ[Invalid] {
-			continue
+			continue L
 		}
-		// complain about duplicate types
-		// TODO(gri) use a type hash to avoid quadratic algorithm
+		// look for duplicate types
+		// (quadratic algorithm, but type switches tend to be reasonably small)
 		for t, pos := range seen {
 			if T == nil && t == nil || T != nil && t != nil && Identical(T, t) {
 				// talk about "case" rather than "type" because of nil case
-				check.error(e.Pos(), "duplicate case in type switch")
-				check.errorf(pos, "\tprevious case %s", T) // secondary error, \t indented
+				Ts := "nil"
+				if T != nil {
+					Ts = T.String()
+				}
+				check.errorf(e.Pos(), "duplicate case %s in type switch", Ts)
+				check.error(pos, "\tprevious case") // secondary error, \t indented
 				continue L
 			}
 		}
@@ -258,12 +321,20 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
 		if ch.mode == invalid || x.mode == invalid {
 			return
 		}
-		if tch, ok := ch.typ.Underlying().(*Chan); !ok || tch.dir == RecvOnly || !check.assignment(&x, tch.elem) {
-			if x.mode != invalid {
-				check.invalidOp(ch.pos(), "cannot send %s to channel %s", &x, &ch)
-			}
+
+		tch, ok := ch.typ.Underlying().(*Chan)
+		if !ok {
+			check.invalidOp(s.Arrow, "cannot send to non-chan type %s", ch.typ)
+			return
 		}
 
+		if tch.dir == RecvOnly {
+			check.invalidOp(s.Arrow, "cannot send to receive-only type %s", tch)
+			return
+		}
+
+		check.assignment(&x, tch.elem, "send")
+
 	case *ast.IncDecStmt:
 		var op token.Token
 		switch s.Tok {
@@ -386,8 +457,15 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
 			check.error(s.Cond.Pos(), "non-boolean condition in if statement")
 		}
 		check.stmt(inner, s.Body)
-		if s.Else != nil {
+		// The parser produces a correct AST but if it was modified
+		// elsewhere the else branch may be invalid. Check again.
+		switch s.Else.(type) {
+		case nil, *ast.BadStmt:
+			// valid or error already reported
+		case *ast.IfStmt, *ast.BlockStmt:
 			check.stmt(inner, s.Else)
+		default:
+			check.error(s.Else.Pos(), "invalid else branch in if statement")
 		}
 
 	case *ast.SwitchStmt:
@@ -399,6 +477,9 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
 		var x operand
 		if s.Tag != nil {
 			check.expr(&x, s.Tag)
+			// By checking assignment of x to an invisible temporary
+			// (as a compiler would), we get all the relevant checks.
+			check.assignment(&x, nil, "switch expression")
 		} else {
 			// spec: "A missing switch expression is
 			// equivalent to the boolean value true."
@@ -410,15 +491,14 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
 
 		check.multipleDefaults(s.Body.List)
 
+		seen := make(valueMap) // map of seen case values to positions and types
 		for i, c := range s.Body.List {
 			clause, _ := c.(*ast.CaseClause)
 			if clause == nil {
 				check.invalidAST(c.Pos(), "incorrect expression switch case")
 				continue
 			}
-			if x.mode != invalid {
-				check.caseValues(x, clause.List)
-			}
+			check.caseValues(&x, clause.List, seen)
 			check.openScope(clause, "case")
 			inner := inner
 			if i+1 < len(s.Body.List) {
@@ -701,7 +781,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
 					x.mode = value
 					x.expr = lhs // we don't have a better rhs expression to use here
 					x.typ = typ
-					check.initVar(obj, &x, false)
+					check.initVar(obj, &x, "range clause")
 				} else {
 					obj.typ = Typ[Invalid]
 					obj.used = true // don't complain about unused variable
diff --git a/src/go/types/testdata/builtins.src b/src/go/types/testdata/builtins.src
index 9eb551d..7fb7b58 100644
--- a/src/go/types/testdata/builtins.src
+++ b/src/go/types/testdata/builtins.src
@@ -22,12 +22,12 @@ func append1() {
 	append /* ERROR not used */ (s)
 
 	_ = append(s, b)
-	_ = append(s, x /* ERROR cannot pass argument x */ )
-	_ = append(s, s /* ERROR cannot pass argument s */ )
+	_ = append(s, x /* ERROR cannot use x */ )
+	_ = append(s, s /* ERROR cannot use s */ )
 	_ = append(s... /* ERROR can only use ... with matching parameter */ )
 	_ = append(s, b, s... /* ERROR can only use ... with matching parameter */ )
 	_ = append(s, 1, 2, 3)
-	_ = append(s, 1, 2, 3, x /* ERROR cannot pass argument x */ , 5, 6, 6)
+	_ = append(s, 1, 2, 3, x /* ERROR cannot use x */ , 5, 6, 6)
 	_ = append(s, 1, 2, s... /* ERROR can only use ... with matching parameter */ )
 	_ = append([]interface{}(nil), 1, 2, "foo", x, 3.1425, false)
 
@@ -38,13 +38,13 @@ func append1() {
 	_ = append(s, "foo"...)
 	_ = append(S(s), "foo" /* ERROR cannot convert */ )
 	_ = append(S(s), "foo"...)
-	_ = append(s, t /* ERROR cannot pass argument t */ )
+	_ = append(s, t /* ERROR cannot use t */ )
 	_ = append(s, t...)
 	_ = append(s, T("foo")...)
-	_ = append(S(s), t /* ERROR cannot pass argument t */ )
+	_ = append(S(s), t /* ERROR cannot use t */ )
 	_ = append(S(s), t...)
 	_ = append(S(s), T("foo")...)
-	_ = append([]string{}, t /* ERROR cannot pass argument t */ , "foo")
+	_ = append([]string{}, t /* ERROR cannot use t */ , "foo")
 	_ = append([]T{}, t, "foo")
 }
 
@@ -168,14 +168,14 @@ func complex1() {
 	var c128 complex128
 	_ = complex() // ERROR not enough arguments
 	_ = complex(1) // ERROR not enough arguments
-	_ = complex(true /* ERROR invalid argument */ , 0)
-	_ = complex(i32 /* ERROR invalid argument */ , 0)
-	_ = complex("foo" /* ERROR invalid argument */ , 0)
-	_ = complex(c64 /* ERROR invalid argument */ , 0)
-	_ = complex(0, true /* ERROR invalid argument */ )
-	_ = complex(0, i32 /* ERROR invalid argument */ )
-	_ = complex(0, "foo" /* ERROR invalid argument */ )
-	_ = complex(0, c64 /* ERROR invalid argument */ )
+	_ = complex(true /* ERROR mismatched types */ , 0)
+	_ = complex(i32 /* ERROR expected floating-point */ , 0)
+	_ = complex("foo" /* ERROR mismatched types */ , 0)
+	_ = complex(c64 /* ERROR expected floating-point */ , 0)
+	_ = complex(0 /* ERROR mismatched types */ , true)
+	_ = complex(0 /* ERROR expected floating-point */ , i32)
+	_ = complex(0 /* ERROR mismatched types */ , "foo")
+	_ = complex(0 /* ERROR expected floating-point */ , c64)
 	_ = complex(f32, f32)
 	_ = complex(f32, 1)
 	_ = complex(f32, 1.0)
@@ -192,9 +192,9 @@ func complex1() {
 	complex /* ERROR not used */ (1, 2)
 
 	var _ complex64 = complex(f32, f32)
-	var _ complex64 = complex /* ERROR cannot initialize */ (f64, f64)
+	var _ complex64 = complex /* ERROR cannot use .* in variable declaration */ (f64, f64)
 
-	var _ complex128 = complex /* ERROR cannot initialize */ (f32, f32)
+	var _ complex128 = complex /* ERROR cannot use .* in variable declaration */ (f32, f32)
 	var _ complex128 = complex(f64, f64)
 
 	// untyped constants
@@ -202,6 +202,9 @@ func complex1() {
 	const _ float32 = complex(1, 0)
 	const _ complex64 = complex(1, 0)
 	const _ complex128 = complex(1, 0)
+	const _ = complex(0i, 0i)
+	const _ = complex(0i, 0)
+	const _ int = 1.0 + complex(1, 0i)
 
 	const _ int = complex /* ERROR int */ (1.1, 0)
 	const _ float32 = complex /* ERROR float32 */ (1, 2)
@@ -210,7 +213,7 @@ func complex1() {
 	var s uint
 	_ = complex(1 /* ERROR integer */ <<s, 0)
 	const _ = complex /* ERROR not constant */ (1 /* ERROR integer */ <<s, 0)
-	var _ int = complex /* ERROR cannot initialize */ (1 /* ERROR integer */ <<s, 0)
+	var _ int = complex /* ERROR cannot use .* in variable declaration */ (1 /* ERROR integer */ <<s, 0)
 
 	// floating-point argument types must be identical
 	type F32 float32
@@ -304,9 +307,10 @@ func imag1() {
 	var c128 complex128
 	_ = imag() // ERROR not enough arguments
 	_ = imag(1, 2) // ERROR too many arguments
-	_ = imag(10 /* ERROR must be a complex number */)
-	_ = imag(2.7182818 /* ERROR must be a complex number */)
-	_ = imag("foo" /* ERROR must be a complex number */)
+	_ = imag(10)
+	_ = imag(2.7182818)
+	_ = imag("foo" /* ERROR expected complex */)
+	_ = imag('a')
 	const _5 = imag(1 + 2i)
 	assert(_5 == 2)
 	f32 = _5
@@ -315,8 +319,8 @@ func imag1() {
 	assert(_6 == 0)
 	f32 = imag(c64)
 	f64 = imag(c128)
-	f32 = imag /* ERROR cannot assign */ (c128)
-	f64 = imag /* ERROR cannot assign */ (c64)
+	f32 = imag /* ERROR cannot use .* in assignment */ (c128)
+	f64 = imag /* ERROR cannot use .* in assignment */ (c64)
 	imag /* ERROR not used */ (c64)
 	_, _ = f32, f64
 
@@ -328,8 +332,16 @@ func imag1() {
 	f32 = imag(x64)
 	f64 = imag(x128)
 
-	var s []complex64
-	_ = imag(s... /* ERROR invalid use of \.\.\. */ )
+	var a []complex64
+	_ = imag(a... /* ERROR invalid use of \.\.\. */ )
+
+	// if argument is untyped, result is untyped
+	const _ byte = imag(1.2 + 3i)
+	const _ complex128 = imag(1.2 + 3i)
+
+	// lhs constant shift operands are typed as complex128
+	var s uint
+	_ = imag(1 /* ERROR must be integer */ << s)
 }
 
 func imag2() {
@@ -576,9 +588,9 @@ func real1() {
 	var c128 complex128
 	_ = real() // ERROR not enough arguments
 	_ = real(1, 2) // ERROR too many arguments
-	_ = real(10 /* ERROR must be a complex number */)
-	_ = real(2.7182818 /* ERROR must be a complex number */)
-	_ = real("foo" /* ERROR must be a complex number */)
+	_ = real(10)
+	_ = real(2.7182818)
+	_ = real("foo" /* ERROR expected complex */)
 	const _5 = real(1 + 2i)
 	assert(_5 == 1)
 	f32 = _5
@@ -587,8 +599,8 @@ func real1() {
 	assert(_6 == 0)
 	f32 = real(c64)
 	f64 = real(c128)
-	f32 = real /* ERROR cannot assign */ (c128)
-	f64 = real /* ERROR cannot assign */ (c64)
+	f32 = real /* ERROR cannot use .* in assignment */ (c128)
+	f64 = real /* ERROR cannot use .* in assignment */ (c64)
 	real /* ERROR not used */ (c64)
 
 	// complex type may not be predeclared
@@ -598,10 +610,18 @@ func real1() {
 	var x128 C128
 	f32 = imag(x64)
 	f64 = imag(x128)
-
-	var s []complex64
-	_ = real(s... /* ERROR invalid use of \.\.\. */ )
 	_, _ = f32, f64
+
+	var a []complex64
+	_ = real(a... /* ERROR invalid use of \.\.\. */ )
+
+	// if argument is untyped, result is untyped
+	const _ byte = real(1 + 2.3i)
+	const _ complex128 = real(1 + 2.3i)
+
+	// lhs constant shift operands are typed as complex128
+	var s uint
+	_ = real(1 /* ERROR must be integer */ << s)
 }
 
 func real2() {
diff --git a/src/go/types/testdata/const0.src b/src/go/types/testdata/const0.src
index c4419ab..716a590 100644
--- a/src/go/types/testdata/const0.src
+++ b/src/go/types/testdata/const0.src
@@ -280,3 +280,16 @@ func _() {
 	var y = iota
 	_ = y
 }
+
+// constant arithmetic precision and rounding must lead to expected (integer) results
+var _ = []int64{
+	0.0005 * 1e9,
+	0.001 * 1e9,
+	0.005 * 1e9,
+	0.01 * 1e9,
+	0.05 * 1e9,
+	0.1 * 1e9,
+	0.5 * 1e9,
+	1 * 1e9,
+	5 * 1e9,
+}
diff --git a/src/go/types/testdata/const1.src b/src/go/types/testdata/const1.src
index 88e9fad..d827704 100644
--- a/src/go/types/testdata/const1.src
+++ b/src/go/types/testdata/const1.src
@@ -312,3 +312,11 @@ const (
 	y64 = float64(f64)
 	_ = assert(x64 - y64 == 0)
 )
+
+const (
+	_ = int8(-1) << 7
+	_ = int8 /* ERROR "overflows" */ (-1) << 8
+
+	_ = uint32(1) << 31
+	_ = uint32 /* ERROR "overflows" */ (1) << 32
+)
diff --git a/src/go/types/testdata/decls0.src b/src/go/types/testdata/decls0.src
index 21baafe..d4df386 100644
--- a/src/go/types/testdata/decls0.src
+++ b/src/go/types/testdata/decls0.src
@@ -50,7 +50,10 @@ func _() { var init int; _ = init }
 // invalid array types
 type (
 	iA0 [... /* ERROR "invalid use of '...'" */ ]byte
-	iA1 [1 /* ERROR "invalid array length" */ <<100]int
+	// The error message below could be better. At the moment
+	// we believe an integer that is too large is not an integer.
+	// But at least we get an error.
+	iA1 [1 /* ERROR "must be integer" */ <<100]int
 	iA2 [- /* ERROR "invalid array length" */ 1]complex128
 	iA3 ["foo" /* ERROR "must be integer" */ ]string
 	iA4 [float64 /* ERROR "must be integer" */ (0)]int
diff --git a/src/go/types/testdata/decls1.src b/src/go/types/testdata/decls1.src
index 7855e46..cb162f7 100644
--- a/src/go/types/testdata/decls1.src
+++ b/src/go/types/testdata/decls1.src
@@ -25,7 +25,7 @@ var (
 	s, t string
 	array []byte
 	iface interface{}
-	
+
 	blank _ /* ERROR "cannot use _" */
 )
 
@@ -43,33 +43,33 @@ var (
 	s11 = &v
 	s12 = -(u + *t11) / *&v
 	s13 = a /* ERROR "shifted operand" */ << d
-	s14 = i << j /* ERROR "must be unsigned" */ 
+	s14 = i << j /* ERROR "must be unsigned" */
 	s18 = math.Pi * 10.0
 	s19 = s1 /* ERROR "cannot call" */ ()
  	s20 = f0 /* ERROR "no value" */ ()
 	s21 = f6(1, s1, i)
-	s22 = f6(1, s1, uu /* ERROR "cannot pass argument" */ )
-	
+	s22 = f6(1, s1, uu /* ERROR "cannot use .* in argument" */ )
+
 	t1 int = i + j
 	t2 int = i /* ERROR "mismatched types" */ + x
-	t3 int = c /* ERROR "cannot initialize" */ + d
+	t3 int = c /* ERROR "cannot use .* variable declaration" */ + d
 	t4 string = s + t
 	t5 string = s /* ERROR "invalid operation" */ / t
 	t6 byte = array[t1]
 	t7 byte = array[x /* ERROR "must be integer" */]
-	t8 *int = & /* ERROR "cannot initialize" */ a
+	t8 *int = & /* ERROR "cannot use .* variable declaration" */ a
 	t10 *int = &42 /* ERROR "cannot take address" */
 	t11 *complex64 = &v
 	t12 complex64 = -(u + *t11) / *&v
 	t13 int = a /* ERROR "shifted operand" */ << d
-	t14 int = i << j /* ERROR "must be unsigned" */ 
+	t14 int = i << j /* ERROR "must be unsigned" */
 	t15 math /* ERROR "not in selector" */
 	t16 math /* ERROR "not declared" */ .xxx
 	t17 math /* ERROR "not a type" */ .Pi
 	t18 float64 = math.Pi * 10.0
 	t19 int = t1 /* ERROR "cannot call" */ ()
 	t20 int = f0 /* ERROR "no value" */ ()
-	t21 int = a /* ERROR "cannot initialize" */
+	t21 int = a /* ERROR "cannot use .* variable declaration" */
 )
 
 // Various more complex expressions
diff --git a/src/go/types/testdata/errors.src b/src/go/types/testdata/errors.src
index 45bd45a..29fcd8f 100644
--- a/src/go/types/testdata/errors.src
+++ b/src/go/types/testdata/errors.src
@@ -21,8 +21,8 @@ func f(x int, m map[string]int) {
 	const c2 float32 = 0.5
 	0 /* ERROR "0 \(untyped int constant\) is not used" */
 	c1 /* ERROR "c1 \(untyped int constant 991\) is not used" */
-	c2 /* ERROR "c2 \(constant 1/2 of type float32\) is not used" */
-	c1 /* ERROR "c1 \+ c2 \(constant 1983/2 of type float32\) is not used" */ + c2
+	c2 /* ERROR "c2 \(constant 0.5 of type float32\) is not used" */
+	c1 /* ERROR "c1 \+ c2 \(constant 991.5 of type float32\) is not used" */ + c2
 
 	// variables
 	x /* ERROR "x \(variable of type int\) is not used" */
diff --git a/src/go/types/testdata/expr0.src b/src/go/types/testdata/expr0.src
index 3120c6f..1aac726 100644
--- a/src/go/types/testdata/expr0.src
+++ b/src/go/types/testdata/expr0.src
@@ -144,7 +144,7 @@ var (
 	ch10, ok = <-ch
 	// ok is of type bool
 	ch11, myok = <-ch
-	_ mybool = myok /* ERROR "cannot initialize" */
+	_ mybool = myok /* ERROR "cannot use .* in variable declaration" */
 )
 
 // address of composite literals
@@ -172,3 +172,9 @@ var (
 	p3 P = &p2
 )
 
+func g() (a, b int) { return }
+
+func _() {
+	_ = -g /* ERROR 2-valued g */ ()
+	_ = <-g /* ERROR 2-valued g */ ()
+}
diff --git a/src/go/types/testdata/expr1.src b/src/go/types/testdata/expr1.src
index 8ef0aed..eaaf610 100644
--- a/src/go/types/testdata/expr1.src
+++ b/src/go/types/testdata/expr1.src
@@ -5,3 +5,123 @@
 // binary expressions
 
 package expr1
+
+type mybool bool
+
+func _(x, y bool, z mybool) {
+	x = x || y
+	x = x || true
+	x = x || false
+	x = x && y
+	x = x && true
+	x = x && false
+
+	z = z /* ERROR mismatched types */ || y
+	z = z || true
+	z = z || false
+	z = z /* ERROR mismatched types */ && y
+	z = z && true
+	z = z && false
+}
+
+type myint int
+
+func _(x, y int, z myint) {
+	x = x + 1
+	x = x + 1.0
+	x = x + 1.1 // ERROR truncated to int
+	x = x + y
+	x = x - y
+	x = x * y
+	x = x / y
+	x = x % y
+	x = x << y // ERROR must be unsigned integer
+	x = x >> y // ERROR must be unsigned integer
+
+	z = z + 1
+	z = z + 1.0
+	z = z + 1.1 // ERROR truncated to int
+	z = z /* ERROR mismatched types */ + y
+	z = z /* ERROR mismatched types */ - y
+	z = z /* ERROR mismatched types */ * y
+	z = z /* ERROR mismatched types */ / y
+	z = z /* ERROR mismatched types */ % y
+	z = z << y // ERROR must be unsigned integer
+	z = z >> y // ERROR must be unsigned integer
+}
+
+type myuint uint
+
+func _(x, y uint, z myuint) {
+	x = x + 1
+	x = x + - /* ERROR overflows uint */ 1
+	x = x + 1.0
+	x = x + 1.1 // ERROR truncated to uint
+	x = x + y
+	x = x - y
+	x = x * y
+	x = x / y
+	x = x % y
+	x = x << y
+	x = x >> y
+
+	z = z + 1
+	z = x + - /* ERROR overflows uint */ 1
+	z = z + 1.0
+	z = z + 1.1 // ERROR truncated to uint
+	z = z /* ERROR mismatched types */ + y
+	z = z /* ERROR mismatched types */ - y
+	z = z /* ERROR mismatched types */ * y
+	z = z /* ERROR mismatched types */ / y
+	z = z /* ERROR mismatched types */ % y
+	z = z << y
+	z = z >> y
+}
+
+type myfloat64 float64
+
+func _(x, y float64, z myfloat64) {
+	x = x + 1
+	x = x + -1
+	x = x + 1.0
+	x = x + 1.1
+	x = x + y
+	x = x - y
+	x = x * y
+	x = x / y
+	x = x /* ERROR not defined */ % y
+	x = x /* ERROR operand x .* must be integer */ << y
+	x = x /* ERROR operand x .* must be integer */ >> y
+
+	z = z + 1
+	z = z + -1
+	z = z + 1.0
+	z = z + 1.1
+	z = z /* ERROR mismatched types */ + y
+	z = z /* ERROR mismatched types */ - y
+	z = z /* ERROR mismatched types */ * y
+	z = z /* ERROR mismatched types */ / y
+	z = z /* ERROR mismatched types */ % y
+	z = z /* ERROR operand z .* must be integer */ << y
+	z = z /* ERROR operand z .* must be integer */ >> y
+}
+
+type mystring string
+
+func _(x, y string, z mystring) {
+	x = x + "foo"
+	x = x /* ERROR not defined */ - "foo"
+	x = x + 1 // ERROR cannot convert
+	x = x + y
+	x = x /* ERROR not defined */ - y
+	x = x * 10 // ERROR cannot convert
+}
+
+func f() (a, b int) { return }
+
+func _(x int) {
+	_ = f /* ERROR 2-valued f */ () + 1
+	_ = x + f /* ERROR 2-valued f */ ()
+	_ = f /* ERROR 2-valued f */ () + f
+	_ = f /* ERROR 2-valued f */ () + f /* ERROR 2-valued f */ ()
+}
diff --git a/src/go/types/testdata/expr3.src b/src/go/types/testdata/expr3.src
index 5772095..53c03e7 100644
--- a/src/go/types/testdata/expr3.src
+++ b/src/go/types/testdata/expr3.src
@@ -28,7 +28,7 @@ func indexes() {
 	a0 = a[0]
 	_ = a0
 	var a1 int32
-	a1 = a /* ERROR "cannot assign" */ [1]
+	a1 = a /* ERROR "cannot use .* in assignment" */ [1]
 	_ = a1
 
 	_ = a[9]
@@ -113,7 +113,7 @@ func indexes() {
 	t0 = t[0]
 	_ = t0
 	var t1 rune
-	t1 = t /* ERROR "cannot assign" */ [2]
+	t1 = t /* ERROR "cannot use .* in assignment" */ [2]
 	_ = t1
 	_ = ("foo" + "bar")[5]
 	_ = ("foo" + "bar")[6 /* ERROR "index .* out of bounds" */ ]
@@ -126,7 +126,7 @@ func indexes() {
 	c0 = c[0]
 	_ = c0
 	var c2 float32
-	c2 = c /* ERROR "cannot assign" */ [2]
+	c2 = c /* ERROR "cannot use .* in assignment" */ [2]
 	_ = c[3 /* ERROR "index .* out of bounds" */ ]
 	_ = ""[0 /* ERROR "index .* out of bounds" */ ]
 	_ = c2
@@ -140,8 +140,8 @@ func indexes() {
 	var i, j int
 	ss = "foo"[1:2]
 	ss = "foo"[i:j]
-	ms = "foo" /* ERROR "cannot assign" */ [1:2]
-	ms = "foo" /* ERROR "cannot assign" */ [i:j]
+	ms = "foo" /* ERROR "cannot use .* in assignment" */ [1:2]
+	ms = "foo" /* ERROR "cannot use .* in assignment" */ [i:j]
 	_, _ = ss, ms
 }
 
@@ -253,7 +253,7 @@ func array_literals() {
 	var a13 [3]int
 	var a14 [4]int
 	a13 = a1
-	a14 = a1 /* ERROR "cannot assign" */
+	a14 = a1 /* ERROR "cannot use .* in assignment" */
 	_, _ = a13, a14
 
 	a2 := [...]int{- /* ERROR "negative" */ 1: 0}
@@ -465,7 +465,7 @@ func _calls() {
 	f1(10.0)
 	f1() /* ERROR "too few arguments" */
 	f1(x, y /* ERROR "too many arguments" */ )
-	f1(s /* ERROR "cannot pass" */ )
+	f1(s /* ERROR "cannot use .* in argument" */ )
 	f1(x ... /* ERROR "cannot use ..." */ )
 	f1(g0 /* ERROR "used as value" */ ())
 	f1(g1())
@@ -474,57 +474,57 @@ func _calls() {
 	f2() /* ERROR "too few arguments" */
 	f2(3.14) /* ERROR "too few arguments" */
 	f2(3.14, "foo")
-	f2(x /* ERROR "cannot pass" */ , "foo")
+	f2(x /* ERROR "cannot use .* in argument" */ , "foo")
 	f2(g0 /* ERROR "used as value" */ ())
-	f2(g1 /* ERROR "cannot pass" */ ()) /* ERROR "too few arguments" */
+	f2(g1 /* ERROR "cannot use .* in argument" */ ()) /* ERROR "too few arguments" */
 	f2(g2())
 
 	fs() /* ERROR "too few arguments" */
 	fs(g0 /* ERROR "used as value" */ ())
-	fs(g1 /* ERROR "cannot pass" */ ())
-	fs(g2 /* ERROR "cannot pass" */ /* ERROR "too many arguments" */ ())
+	fs(g1 /* ERROR "cannot use .* in argument" */ ())
+	fs(g2 /* ERROR "cannot use .* in argument" */ /* ERROR "too many arguments" */ ())
 	fs(gs())
 
 	fv()
 	fv(1, 2.0, x)
-	fv(s /* ERROR "cannot pass" */ )
+	fv(s /* ERROR "cannot use .* in argument" */ )
 	fv(s...)
 	fv(x /* ERROR "cannot use" */ ...)
 	fv(1, s... /* ERROR "can only use ... with matching parameter" */ )
-	fv(gs /* ERROR "cannot pass" */ ())
-	fv(gs /* ERROR "cannot pass" */ ()...)
+	fv(gs /* ERROR "cannot use .* in argument" */ ())
+	fv(gs /* ERROR "cannot use .* in argument" */ ()...)
 
 	var t T
 	t.fm()
 	t.fm(1, 2.0, x)
-	t.fm(s /* ERROR "cannot pass" */ )
+	t.fm(s /* ERROR "cannot use .* in argument" */ )
 	t.fm(g1())
 	t.fm(1, s... /* ERROR "can only use ... with matching parameter" */ )
-	t.fm(gs /* ERROR "cannot pass" */ ())
-	t.fm(gs /* ERROR "cannot pass" */ ()...)
+	t.fm(gs /* ERROR "cannot use .* in argument" */ ())
+	t.fm(gs /* ERROR "cannot use .* in argument" */ ()...)
 
 	T.fm(t, )
 	T.fm(t, 1, 2.0, x)
-	T.fm(t, s /* ERROR "cannot pass" */ )
+	T.fm(t, s /* ERROR "cannot use .* in argument" */ )
 	T.fm(t, g1())
 	T.fm(t, 1, s... /* ERROR "can only use ... with matching parameter" */ )
-	T.fm(t, gs /* ERROR "cannot pass" */ ())
-	T.fm(t, gs /* ERROR "cannot pass" */ ()...)
+	T.fm(t, gs /* ERROR "cannot use .* in argument" */ ())
+	T.fm(t, gs /* ERROR "cannot use .* in argument" */ ()...)
 
 	var i interface{ fm(x ...int) } = t
 	i.fm()
 	i.fm(1, 2.0, x)
-	i.fm(s /* ERROR "cannot pass" */ )
+	i.fm(s /* ERROR "cannot use .* in argument" */ )
 	i.fm(g1())
 	i.fm(1, s... /* ERROR "can only use ... with matching parameter" */ )
-	i.fm(gs /* ERROR "cannot pass" */ ())
-	i.fm(gs /* ERROR "cannot pass" */ ()...)
+	i.fm(gs /* ERROR "cannot use .* in argument" */ ())
+	i.fm(gs /* ERROR "cannot use .* in argument" */ ()...)
 
 	fi()
 	fi(1, 2.0, x, 3.14, "foo")
 	fi(g2())
 	fi(0, g2)
-	fi(0, g2 /* ERROR "2-valued expression" */ ())
+	fi(0, g2 /* ERROR "2-valued g2" */ ())
 }
 
 func issue6344() {
diff --git a/src/go/types/testdata/importC.src b/src/go/types/testdata/importC.src
new file mode 100644
index 0000000..31436be
--- /dev/null
+++ b/src/go/types/testdata/importC.src
@@ -0,0 +1,10 @@
+// Copyright 2015 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 importC
+
+import "C"
+import _ /* ERROR cannot rename import "C" */ "C"
+import foo /* ERROR cannot rename import "C" */ "C"
+import . /* ERROR cannot rename import "C" */ "C"
diff --git a/src/go/types/testdata/issues.src b/src/go/types/testdata/issues.src
index 595a634..4fe0c62 100644
--- a/src/go/types/testdata/issues.src
+++ b/src/go/types/testdata/issues.src
@@ -17,8 +17,7 @@ func issue7035() {
 
 func issue8066() {
 	const (
-		// TODO(gri) Enable test below for releases 1.4 and higher
-		// _ = float32(340282356779733661637539395458142568447)
+		_ = float32(340282356779733661637539395458142568447)
 		_ = float32(340282356779733661637539395458142568448 /* ERROR cannot convert */ )
 	)
 }
@@ -53,23 +52,23 @@ func issue9473(a []int, b ...int) {
 	_ = append(f0())
 	_ = append(f0(), f0()...)
 	_ = append(f1())
-	_ = append(f2 /* ERROR cannot pass argument */ ())
+	_ = append(f2 /* ERROR cannot use .* in argument */ ())
 	_ = append(f2()... /* ERROR cannot use ... */ )
-	_ = append(f0(), f1 /* ERROR 2-valued expression */ ())
-	_ = append(f0(), f2 /* ERROR 2-valued expression */ ())
-	_ = append(f0(), f1()... /* ERROR cannot use ... */ )
-	_ = append(f0(), f2()... /* ERROR cannot use ... */ )
+	_ = append(f0(), f1 /* ERROR 2-valued f1 */ ())
+	_ = append(f0(), f2 /* ERROR 2-valued f2 */ ())
+	_ = append(f0(), f1 /* ERROR 2-valued f1 */ ()...)
+	_ = append(f0(), f2 /* ERROR 2-valued f2 */ ()...)
 
 	// variadic user-defined function
 	append_(f0())
 	append_(f0(), f0()...)
 	append_(f1())
-	append_(f2 /* ERROR cannot pass argument */ ())
+	append_(f2 /* ERROR cannot use .* in argument */ ())
 	append_(f2()... /* ERROR cannot use ... */ )
-	append_(f0(), f1 /* ERROR 2-valued expression */ ())
-	append_(f0(), f2 /* ERROR 2-valued expression */ ())
-	append_(f0(), f1()... /* ERROR cannot use */ )
-	append_(f0(), f2()... /* ERROR cannot use */ )
+	append_(f0(), f1 /* ERROR 2-valued f1 */ ())
+	append_(f0(), f2 /* ERROR 2-valued f2 */ ())
+	append_(f0(), f1 /* ERROR 2-valued f1 */ ()...)
+	append_(f0(), f2 /* ERROR 2-valued f2 */ ()...)
 }
 
 // Check that embedding a non-interface type in an interface results in a good error message.
@@ -95,3 +94,79 @@ func issue10979() {
 		m()
 	}
 }
+
+// issue11347
+// These should not crash.
+var a1, b1 /* ERROR cycle */ , c1 /* ERROR cycle */ b1 = 0 > 0<<""[""[c1]]>c1
+var a2, b2 /* ERROR cycle */ = 0 /* ERROR mismatch */ /* ERROR mismatch */ > 0<<""[b2]
+var a3, b3 /* ERROR cycle */ = int /* ERROR mismatch */ /* ERROR mismatch */ (1<<""[b3])
+
+// issue10260
+// Check that error messages explain reason for interface assignment failures.
+type (
+	I0 interface{}
+	I1 interface{ foo() }
+	I2 interface{ foo(x int) }
+	T0 struct{}
+	T1 struct{}
+	T2 struct{}
+)
+
+func (*T1) foo() {}
+func (*T2) foo(x int) {}
+
+func issue10260() {
+	var (
+		i0 I0
+		i1 I1
+		i2 I2
+		t0 *T0
+		t1 *T1
+		t2 *T2
+	)
+	i1 = i0 /* ERROR cannot use .* missing method foo */
+	i1 = t0 /* ERROR cannot use .* missing method foo */
+	i1 = i2 /* ERROR cannot use .* wrong type for method foo */
+	i1 = t2 /* ERROR cannot use .* wrong type for method foo */
+	i2 = i1 /* ERROR cannot use .* wrong type for method foo */
+	i2 = t1 /* ERROR cannot use .* wrong type for method foo */
+
+	_ = func() I1 { return i0 /* ERROR cannot use .* missing method foo */ }
+	_ = func() I1 { return t0 /* ERROR cannot use .* missing method foo */ }
+	_ = func() I1 { return i2 /* ERROR cannot use .* wrong type for method foo */ }
+	_ = func() I1 { return t2 /* ERROR cannot use .* wrong type for method foo */ }
+	_ = func() I2 { return i1 /* ERROR cannot use .* wrong type for method foo */ }
+	_ = func() I2 { return t1 /* ERROR cannot use .* wrong type for method foo */ }
+
+	// a few more - less exhaustive now
+
+	f := func(I1, I2){}
+	f(i0 /* ERROR cannot use .* missing method foo */ , i1 /* ERROR cannot use .* wrong type for method foo */)
+
+	_ = [...]I1{i0 /* ERROR cannot use .* missing method foo */ }
+	_ = [...]I1{i2 /* ERROR cannot use .* wrong type for method foo */ }
+	_ = []I1{i0 /* ERROR cannot use .* missing method foo */ }
+	_ = []I1{i2 /* ERROR cannot use .* wrong type for method foo */ }
+	_ = map[int]I1{0: i0 /* ERROR cannot use .* missing method foo */ }
+	_ = map[int]I1{0: i2 /* ERROR cannot use .* wrong type for method foo */ }
+
+	make(chan I1) <- i0 /* ERROR cannot use .* in send: missing method foo */
+	make(chan I1) <- i2 /* ERROR cannot use .* in send: wrong type for method foo */
+}
+
+// Check that constants representable as integers are in integer form
+// before being used in operations that are only defined on integers.
+func issue14229() {
+	// from the issue
+	const _ = int64(-1<<63) % 1e6
+
+	// related
+	const (
+		a int = 3
+		b = 4.0
+		_ = a / b
+		_ = a % b
+		_ = b / a
+		_ = b % a
+	)
+}
diff --git a/src/go/types/testdata/stmt0.src b/src/go/types/testdata/stmt0.src
index fd1ddba..b7966ed 100644
--- a/src/go/types/testdata/stmt0.src
+++ b/src/go/types/testdata/stmt0.src
@@ -37,11 +37,11 @@ func assignments0() (int, int) {
 
 func assignments1() {
 	b, i, f, c, s := false, 1, 1.0, 1i, "foo"
-	b = i /* ERROR "cannot assign" */
-	i = f /* ERROR "cannot assign" */
-	f = c /* ERROR "cannot assign" */
-	c = s /* ERROR "cannot assign" */
-	s = b /* ERROR "cannot assign" */
+	b = i /* ERROR "cannot use .* in assignment" */
+	i = f /* ERROR "cannot use .* in assignment" */
+	f = c /* ERROR "cannot use .* in assignment" */
+	c = s /* ERROR "cannot use .* in assignment" */
+	s = b /* ERROR "cannot use .* in assignment" */
 
 	v0, v1, v2 := 1 /* ERROR "mismatch" */ , 2, 3, 4
 	_, _, _ = v0, v1, v2
@@ -180,8 +180,8 @@ func sends() {
 	var ch chan int
 	var rch <-chan int
 	var x int
-	x /* ERROR "cannot send" */ <- x
-	rch /* ERROR "cannot send" */ <- x
+	x <- /* ERROR "cannot send" */ x
+	rch <- /* ERROR "cannot send" */ x
 	ch <- "foo" /* ERROR "cannot convert" */
 	ch <- x
 }
@@ -381,7 +381,7 @@ func returns0() {
 func returns1(x float64) (int, *float64) {
 	return 0, &x
 	return /* ERROR wrong number of return values */
-	return "foo" /* ERROR "cannot convert" */, x /* ERROR "cannot return" */
+	return "foo" /* ERROR "cannot convert" */, x /* ERROR "cannot use .* in return statement" */
 	return /* ERROR wrong number of return values */ 0, &x, 1
 }
 
@@ -421,7 +421,7 @@ func switches0() {
 
 	true := "false"
 	_ = true
-	// A tagless switch is equivalent to the bool 
+	// A tagless switch is equivalent to the bool
         // constant true, not the identifier 'true'.
 	switch {
 	case "false" /* ERROR "cannot convert" */:
@@ -438,14 +438,85 @@ func switches0() {
 
 	switch x {
 	case 1:
-	case 1 /* DISABLED "duplicate case" */ :
+	case 1 /* ERROR "duplicate case" */ :
+	case ( /* ERROR "duplicate case" */ 1):
 	case 2, 3, 4:
-	case 1 /* DISABLED "duplicate case" */ :
+	case 5, 1 /* ERROR "duplicate case" */ :
 	}
 
 	switch uint64(x) {
-	case 1 /* DISABLED duplicate case */ <<64-1:
-	case 1 /* DISABLED duplicate case */ <<64-1:
+	case 1<<64 - 1:
+	case 1 /* ERROR duplicate case */ <<64 - 1:
+	case 2, 3, 4:
+	case 5, 1 /* ERROR duplicate case */ <<64 - 1:
+	}
+
+	var y32 float32
+	switch y32 {
+	case 1.1:
+	case 11/10: // integer division!
+	case 11. /* ERROR duplicate case */ /10:
+	case 2, 3.0, 4.1:
+	case 5.2, 1.10 /* ERROR duplicate case */ :
+	}
+
+	var y64 float64
+	switch y64 {
+	case 1.1:
+	case 11/10: // integer division!
+	case 11. /* ERROR duplicate case */ /10:
+	case 2, 3.0, 4.1:
+	case 5.2, 1.10 /* ERROR duplicate case */ :
+	}
+
+	var s string
+	switch s {
+	case "foo":
+	case "foo" /* ERROR duplicate case */ :
+	case "f" /* ERROR duplicate case */ + "oo":
+	case "abc", "def", "ghi":
+	case "jkl", "foo" /* ERROR duplicate case */ :
+	}
+
+	type T int
+	type F float64
+	type S string
+	type B bool
+	var i interface{}
+	switch i {
+	case nil:
+	case nil: // no duplicate detection
+	case (*int)(nil):
+	case (*int)(nil): // do duplicate detection
+	case 1:
+	case byte(1):
+	case int /* ERROR duplicate case */ (1):
+	case T(1):
+	case 1.0:
+	case F(1.0):
+	case F /* ERROR duplicate case */ (1.0):
+	case "hello":
+	case S("hello"):
+	case S /* ERROR duplicate case */ ("hello"):
+	case 1==1, B(false):
+	case false, B(2==2):
+	}
+
+	// switch on array
+	var a [3]int
+	switch a {
+	case [3]int{1, 2, 3}:
+	case [3]int{1, 2, 3}: // no duplicate detection
+	case [ /* ERROR "mismatched types */ 4]int{4, 5, 6}:
+	}
+
+	// switch on channel
+	var c1, c2 chan int
+	switch c1 {
+	case nil:
+	case c1:
+	case c2:
+	case c1, c2: // no duplicate detection
 	}
 }
 
@@ -512,6 +583,65 @@ func switches1() {
 	}
 }
 
+func switches2() {
+	// untyped nil is not permitted as switch expression
+	switch nil /* ERROR "use of untyped nil" */ {
+	case 1, 2, "foo": // don't report additional errors here
+	}
+
+	// untyped constants are converted to default types
+	switch 1<<63-1 {
+	}
+	switch 1 /* ERROR "overflows int" */ << 63 {
+	}
+	var x int
+	switch 1.0 {
+	case 1.0, 2.0, x /* ERROR "mismatched types int and float64" */ :
+	}
+	switch x {
+	case 1.0:
+	}
+
+	// untyped bools become of type bool
+	type B bool
+	var b B = true
+	switch x == x {
+	case b /* ERROR "mismatched types B and bool" */ :
+	}
+	switch {
+	case b /* ERROR "mismatched types B and bool" */ :
+	}
+}
+
+func issue11667() {
+	switch 9223372036854775808 /* ERROR "overflows int" */ {
+	}
+	switch 9223372036854775808 /* ERROR "overflows int" */ {
+	case 9223372036854775808:
+	}
+	var x int
+	switch x {
+	case 9223372036854775808 /* ERROR "overflows int" */ :
+	}
+	var y float64
+	switch y {
+	case 9223372036854775808:
+	}
+}
+
+func issue11687() {
+	f := func() (_, _ int) { return }
+	switch f /* ERROR "2-valued f" */ () {
+	}
+	var x int
+	switch f /* ERROR "2-valued f" */ () {
+	case x:
+	}
+	switch x {
+	case f /* ERROR "2-valued f" */ ():
+	}
+}
+
 type I interface {
 	m()
 }
@@ -552,16 +682,16 @@ func typeswitches() {
 
 	switch t := x.(type) {
 	case nil:
-		var v bool = t /* ERROR "cannot initialize" */
+		var v bool = t /* ERROR "cannot use .* in variable declaration" */
 		_ = v
 	case int:
 		var v int = t
 		_ = v
 	case float32, complex64:
-		var v float32 = t /* ERROR "cannot initialize" */
+		var v float32 = t /* ERROR "cannot use .* in variable declaration" */
 		_ = v
 	default:
-		var v float32 = t /* ERROR "cannot initialize" */
+		var v float32 = t /* ERROR "cannot use .* in variable declaration" */
 		_ = v
 	}
 
@@ -671,7 +801,7 @@ func rangeloops1() {
 		ii = i
 		_ = ii
 		var xx float64
-		xx = x /* ERROR "cannot assign" */
+		xx = x /* ERROR "cannot use .* in assignment" */
 		_ = xx
 	}
 	var ii int
@@ -722,7 +852,7 @@ func rangeloops1() {
 	for range m {}
 	for k := range m {
 		var kk int32
-		kk = k /* ERROR "cannot assign" */
+		kk = k /* ERROR "cannot use .* in assignment" */
 		_ = kk
 	}
 	for k, v := range m {
@@ -764,17 +894,17 @@ func rangeloops2() {
 	var a [10]int
 	var i I
 	_ = i
-	for i /* ERROR cannot assign */ = range a {}
-	for i /* ERROR cannot assign */ = range &a {}
-	for i /* ERROR cannot assign */ = range a[:] {}
+	for i /* ERROR cannot use .* in assignment */ = range a {}
+	for i /* ERROR cannot use .* in assignment */ = range &a {}
+	for i /* ERROR cannot use .* in assignment */ = range a[:] {}
 
 	var s string
 	var r R
 	_ = r
-	for i /* ERROR cannot assign */ = range s {}
-	for i /* ERROR cannot assign */ = range "foo" {}
-	for _, r /* ERROR cannot assign */ = range s {}
-	for _, r /* ERROR cannot assign */ = range "foo" {}
+	for i /* ERROR cannot use .* in assignment */ = range s {}
+	for i /* ERROR cannot use .* in assignment */ = range "foo" {}
+	for _, r /* ERROR cannot use .* in assignment */ = range s {}
+	for _, r /* ERROR cannot use .* in assignment */ = range "foo" {}
 }
 
 func issue6766b() {
@@ -807,7 +937,7 @@ func labels0() {
 	L1:
 	L1 /* ERROR "already declared" */ :
 	if true {
-		goto L2		
+		goto L2
 		L2:
 		L0 /* ERROR "already declared" */ :
 	}
diff --git a/src/go/types/testdata/vardecl.src b/src/go/types/testdata/vardecl.src
index fb6b5f7..0082537 100644
--- a/src/go/types/testdata/vardecl.src
+++ b/src/go/types/testdata/vardecl.src
@@ -31,7 +31,7 @@ var _ = 1, 2 /* ERROR "extra init expr 2" */
 var _, _ = 1 /* ERROR "assignment count mismatch" */
 var _, _, _ /* ERROR "missing init expr for _" */ = 1, 2
 
-var _ = g /* ERROR "2-valued expr" */ ()
+var _ = g /* ERROR "2-valued g" */ ()
 var _, _ = g()
 var _, _, _ = g /* ERROR "assignment count mismatch" */ ()
 
@@ -50,7 +50,7 @@ var (
 	_, _ = 1 /* ERROR "assignment count mismatch" */
 	_, _, _ /* ERROR "missing init expr for _" */ = 1, 2
 
-	_ = g /* ERROR "2-valued expr" */ ()
+	_ = g /* ERROR "2-valued g" */ ()
 	_, _ = g()
 	_, _, _ = g /* ERROR "assignment count mismatch" */ ()
 
diff --git a/src/go/types/type.go b/src/go/types/type.go
index 1df8b45..d8415f1 100644
--- a/src/go/types/type.go
+++ b/src/go/types/type.go
@@ -4,9 +4,10 @@
 
 package types
 
-import "sort"
-
-// TODO(gri) Revisit factory functions - make sure they have all relevant parameters.
+import (
+	"sort"
+	"sync"
+)
 
 // A Type represents a type of Go.
 // All types implement the Type interface.
@@ -120,10 +121,10 @@ func (s *Slice) Elem() Type { return s.elem }
 
 // A Struct represents a struct type.
 type Struct struct {
-	fields []*Var
-	tags   []string // field tags; nil if there are no tags
-	// TODO(gri) access to offsets is not threadsafe - fix this
-	offsets []int64 // field offsets in bytes, lazily initialized
+	fields      []*Var
+	tags        []string  // field tags; nil if there are no tags
+	offsets     []int64   // field offsets in bytes, lazily initialized
+	offsetsOnce sync.Once // for threadsafe lazy initialization of offsets
 }
 
 // NewStruct returns a new struct with the given fields and corresponding field tags.
@@ -360,7 +361,7 @@ type Chan struct {
 // A ChanDir value indicates a channel direction.
 type ChanDir int
 
-// The direction of a channel is indicated by one of the following constants.
+// The direction of a channel is indicated by one of these constants.
 const (
 	SendRecv ChanDir = iota
 	SendOnly
diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go
index bd62f4d..47378e7 100644
--- a/src/go/types/typestring.go
+++ b/src/go/types/typestring.go
@@ -71,7 +71,7 @@ func TypeString(typ Type, qf Qualifier) string {
 // The Qualifier controls the printing of
 // package-level objects, and may be nil.
 func WriteType(buf *bytes.Buffer, typ Type, qf Qualifier) {
-	writeType(buf, typ, qf, make([]Type, 8))
+	writeType(buf, typ, qf, make([]Type, 0, 8))
 }
 
 func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
@@ -272,7 +272,7 @@ func writeTuple(buf *bytes.Buffer, tup *Tuple, variadic bool, qf Qualifier, visi
 // The Qualifier controls the printing of
 // package-level objects, and may be nil.
 func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) {
-	writeSignature(buf, sig, qf, make([]Type, 8))
+	writeSignature(buf, sig, qf, make([]Type, 0, 8))
 }
 
 func writeSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier, visited []Type) {
diff --git a/src/go/types/typestring_test.go b/src/go/types/typestring_test.go
index 913e6c7..6365df5 100644
--- a/src/go/types/typestring_test.go
+++ b/src/go/types/typestring_test.go
@@ -148,6 +148,7 @@ func TestQualifiedTypeString(t *testing.T) {
 		this *Package
 		want string
 	}{
+		{nil, nil, "<nil>"},
 		{pT, nil, "p.T"},
 		{pT, p, "T"},
 		{pT, q, "p.T"},
diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go
index c744eea..931b924 100644
--- a/src/go/types/typexpr.go
+++ b/src/go/types/typexpr.go
@@ -373,16 +373,19 @@ func (check *Checker) arrayLength(e ast.Expr) int64 {
 		}
 		return 0
 	}
-	if !x.isInteger() {
-		check.errorf(x.pos(), "array length %s must be integer", &x)
-		return 0
-	}
-	n, ok := constant.Int64Val(x.val)
-	if !ok || n < 0 {
-		check.errorf(x.pos(), "invalid array length %s", &x)
-		return 0
+	if isUntyped(x.typ) || isInteger(x.typ) {
+		if val := constant.ToInt(x.val); val.Kind() == constant.Int {
+			if representableConst(val, check.conf, Typ[Int], nil) {
+				if n, ok := constant.Int64Val(val); ok && n >= 0 {
+					return n
+				}
+				check.errorf(x.pos(), "invalid array length %s", &x)
+				return 0
+			}
+		}
 	}
-	return n
+	check.errorf(x.pos(), "array length %s must be integer", &x)
+	return 0
 }
 
 func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicOk bool) (params []*Var, variadic bool) {
diff --git a/src/hash/adler32/adler32.go b/src/hash/adler32/adler32.go
index 7c80796..0c733f7 100644
--- a/src/hash/adler32/adler32.go
+++ b/src/hash/adler32/adler32.go
@@ -33,6 +33,7 @@ type digest uint32
 func (d *digest) Reset() { *d = 1 }
 
 // New returns a new hash.Hash32 computing the Adler-32 checksum.
+// Its Sum method will lay the value out in big-endian byte order.
 func New() hash.Hash32 {
 	d := new(digest)
 	d.Reset()
diff --git a/src/hash/crc32/crc32.go b/src/hash/crc32/crc32.go
index 234d929..dc59948 100644
--- a/src/hash/crc32/crc32.go
+++ b/src/hash/crc32/crc32.go
@@ -57,11 +57,12 @@ var IEEETable = makeTable(IEEE)
 // slicing8Table is array of 8 Tables
 type slicing8Table [8]Table
 
-// iEEETable8 is the slicing8Table for IEEE
-var iEEETable8 *slicing8Table
-var iEEETable8Once sync.Once
+// ieeeTable8 is the slicing8Table for IEEE
+var ieeeTable8 *slicing8Table
+var ieeeTable8Once sync.Once
 
-// MakeTable returns the Table constructed from the specified polynomial.
+// MakeTable returns a Table constructed from the specified polynomial.
+// The contents of this Table must not be modified.
 func MakeTable(poly uint32) *Table {
 	switch poly {
 	case IEEE:
@@ -112,10 +113,12 @@ type digest struct {
 
 // New creates a new hash.Hash32 computing the CRC-32 checksum
 // using the polynomial represented by the Table.
+// Its Sum method will lay the value out in big-endian byte order.
 func New(tab *Table) hash.Hash32 { return &digest{0, tab} }
 
 // NewIEEE creates a new hash.Hash32 computing the CRC-32 checksum
 // using the IEEE polynomial.
+// Its Sum method will lay the value out in big-endian byte order.
 func NewIEEE() hash.Hash32 { return New(IEEETable) }
 
 func (d *digest) Size() int { return Size }
@@ -148,15 +151,11 @@ func updateSlicingBy8(crc uint32, tab *slicing8Table, p []byte) uint32 {
 
 // Update returns the result of adding the bytes in p to the crc.
 func Update(crc uint32, tab *Table, p []byte) uint32 {
-	if tab == castagnoliTable {
+	switch tab {
+	case castagnoliTable:
 		return updateCastagnoli(crc, p)
-	}
-	// only use slicing-by-8 when input is larger than 4KB
-	if tab == IEEETable && len(p) >= 4096 {
-		iEEETable8Once.Do(func() {
-			iEEETable8 = makeTable8(IEEE)
-		})
-		return updateSlicingBy8(crc, iEEETable8, p)
+	case IEEETable:
+		return updateIEEE(crc, p)
 	}
 	return update(crc, tab, p)
 }
diff --git a/src/hash/crc32/crc32_amd64.go b/src/hash/crc32/crc32_amd64.go
new file mode 100644
index 0000000..ab4e2b8
--- /dev/null
+++ b/src/hash/crc32/crc32_amd64.go
@@ -0,0 +1,56 @@
+// Copyright 2011 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 crc32
+
+// This file contains the code to call the SSE 4.2 version of the Castagnoli
+// and IEEE CRC.
+
+// haveSSE41/haveSSE42/haveCLMUL are defined in crc_amd64.s and use
+// CPUID to test for SSE 4.1, 4.2 and CLMUL support.
+func haveSSE41() bool
+func haveSSE42() bool
+func haveCLMUL() bool
+
+// castagnoliSSE42 is defined in crc_amd64.s and uses the SSE4.2 CRC32
+// instruction.
+//go:noescape
+func castagnoliSSE42(crc uint32, p []byte) uint32
+
+// ieeeCLMUL is defined in crc_amd64.s and uses the PCLMULQDQ
+// instruction as well as SSE 4.1.
+//go:noescape
+func ieeeCLMUL(crc uint32, p []byte) uint32
+
+var sse42 = haveSSE42()
+var useFastIEEE = haveCLMUL() && haveSSE41()
+
+func updateCastagnoli(crc uint32, p []byte) uint32 {
+	if sse42 {
+		return castagnoliSSE42(crc, p)
+	}
+	return update(crc, castagnoliTable, p)
+}
+
+func updateIEEE(crc uint32, p []byte) uint32 {
+	if useFastIEEE && len(p) >= 64 {
+		left := len(p) & 15
+		do := len(p) - left
+		crc = ^ieeeCLMUL(^crc, p[:do])
+		if left > 0 {
+			crc = update(crc, IEEETable, p[do:])
+		}
+		return crc
+	}
+
+	// only use slicing-by-8 when input is >= 4KB
+	if len(p) >= 4096 {
+		ieeeTable8Once.Do(func() {
+			ieeeTable8 = makeTable8(IEEE)
+		})
+		return updateSlicingBy8(crc, ieeeTable8, p)
+	}
+
+	return update(crc, IEEETable, p)
+}
diff --git a/src/hash/crc32/crc32_amd64.s b/src/hash/crc32/crc32_amd64.s
index 30b0d06..caacfae 100644
--- a/src/hash/crc32/crc32_amd64.s
+++ b/src/hash/crc32/crc32_amd64.s
@@ -62,3 +62,170 @@ TEXT ·haveSSE42(SB),NOSPLIT,$0
 	MOVB CX, ret+0(FP)
 	RET
 
+// func haveCLMUL() bool
+TEXT ·haveCLMUL(SB),NOSPLIT,$0
+	XORQ AX, AX
+	INCL AX
+	CPUID
+	SHRQ $1, CX
+	ANDQ $1, CX
+	MOVB CX, ret+0(FP)
+	RET
+
+// func haveSSE41() bool
+TEXT ·haveSSE41(SB),NOSPLIT,$0
+	XORQ AX, AX
+	INCL AX
+	CPUID
+	SHRQ $19, CX
+	ANDQ $1, CX
+	MOVB CX, ret+0(FP)
+	RET
+
+// CRC32 polynomial data
+//
+// These constants are lifted from the
+// Linux kernel, since they avoid the costly
+// PSHUFB 16 byte reversal proposed in the
+// original Intel paper.
+DATA r2r1<>+0(SB)/8, $0x154442bd4
+DATA r2r1<>+8(SB)/8, $0x1c6e41596
+DATA r4r3<>+0(SB)/8, $0x1751997d0
+DATA r4r3<>+8(SB)/8, $0x0ccaa009e
+DATA rupoly<>+0(SB)/8, $0x1db710641
+DATA rupoly<>+8(SB)/8, $0x1f7011641
+DATA r5<>+0(SB)/8, $0x163cd6124
+
+GLOBL r2r1<>(SB),RODATA,$16
+GLOBL r4r3<>(SB),RODATA,$16
+GLOBL rupoly<>(SB),RODATA,$16
+GLOBL r5<>(SB),RODATA,$8
+
+// Based on http://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf
+// len(p) must be at least 64, and must be a multiple of 16.
+
+// func ieeeCLMUL(crc uint32, p []byte) uint32
+TEXT ·ieeeCLMUL(SB),NOSPLIT,$0
+	MOVL   crc+0(FP), X0             // Initial CRC value
+	MOVQ   p+8(FP), SI  	         // data pointer
+	MOVQ   p_len+16(FP), CX          // len(p)
+
+	MOVOU  (SI), X1
+	MOVOU  16(SI), X2
+	MOVOU  32(SI), X3
+	MOVOU  48(SI), X4
+	PXOR   X0, X1
+	ADDQ   $64, SI                  // buf+=64
+	SUBQ   $64, CX                  // len-=64
+	CMPQ   CX, $64                  // Less than 64 bytes left
+	JB     remain64
+
+	MOVOA  r2r1<>+0(SB), X0
+loopback64:
+	MOVOA  X1, X5
+	MOVOA  X2, X6
+	MOVOA  X3, X7
+	MOVOA  X4, X8
+
+	PCLMULQDQ $0, X0, X1
+	PCLMULQDQ $0, X0, X2
+	PCLMULQDQ $0, X0, X3
+	PCLMULQDQ $0, X0, X4
+
+	/* Load next early */
+	MOVOU    (SI), X11
+	MOVOU    16(SI), X12
+	MOVOU    32(SI), X13
+	MOVOU    48(SI), X14
+
+	PCLMULQDQ $0x11, X0, X5
+	PCLMULQDQ $0x11, X0, X6
+	PCLMULQDQ $0x11, X0, X7
+	PCLMULQDQ $0x11, X0, X8
+
+	PXOR     X5, X1
+	PXOR     X6, X2
+	PXOR     X7, X3
+	PXOR     X8, X4
+
+	PXOR     X11, X1
+	PXOR     X12, X2
+	PXOR     X13, X3
+	PXOR     X14, X4
+
+	ADDQ    $0x40, DI
+	ADDQ    $64, SI      // buf+=64
+	SUBQ    $64, CX      // len-=64
+	CMPQ    CX, $64      // Less than 64 bytes left?
+	JGE     loopback64
+
+	/* Fold result into a single register (X1) */
+remain64:
+	MOVOA       r4r3<>+0(SB), X0
+
+	MOVOA       X1, X5
+	PCLMULQDQ   $0, X0, X1
+	PCLMULQDQ   $0x11, X0, X5
+	PXOR        X5, X1
+	PXOR        X2, X1
+
+	MOVOA       X1, X5
+	PCLMULQDQ   $0, X0, X1
+	PCLMULQDQ   $0x11, X0, X5
+	PXOR        X5, X1
+	PXOR        X3, X1
+
+	MOVOA       X1, X5
+	PCLMULQDQ   $0, X0, X1
+	PCLMULQDQ   $0x11, X0, X5
+	PXOR        X5, X1
+	PXOR        X4, X1
+
+	/* If there is less than 16 bytes left we are done */
+	CMPQ        CX, $16
+	JB          finish
+
+	/* Encode 16 bytes */
+remain16:
+	MOVOU       (SI), X10
+	MOVOA       X1, X5
+	PCLMULQDQ   $0, X0, X1
+	PCLMULQDQ   $0x11, X0, X5
+	PXOR        X5, X1
+	PXOR        X10, X1
+	SUBQ        $16, CX
+	ADDQ        $16, SI
+	CMPQ        CX, $16
+	JGE         remain16
+
+finish:
+	/* Fold final result into 32 bits and return it */
+	PCMPEQB     X3, X3
+	PCLMULQDQ   $1, X1, X0
+	PSRLDQ      $8, X1
+	PXOR        X0, X1
+
+	MOVOA       X1, X2
+	MOVQ        r5<>+0(SB), X0
+
+	/* Creates 32 bit mask. Note that we don't care about upper half. */
+	PSRLQ       $32, X3
+
+	PSRLDQ      $4, X2
+	PAND        X3, X1
+	PCLMULQDQ   $0, X0, X1
+	PXOR        X2, X1
+
+	MOVOA       rupoly<>+0(SB), X0
+
+	MOVOA       X1, X2
+	PAND        X3, X1
+	PCLMULQDQ   $0x10, X0, X1
+	PAND        X3, X1
+	PCLMULQDQ   $0, X0, X1
+	PXOR        X2, X1
+
+	PEXTRD	$1, X1, AX
+	MOVL        AX, ret+32(FP)
+
+	RET
diff --git a/src/hash/crc32/crc32_amd64p32.go b/src/hash/crc32/crc32_amd64p32.go
new file mode 100644
index 0000000..067fbb1
--- /dev/null
+++ b/src/hash/crc32/crc32_amd64p32.go
@@ -0,0 +1,38 @@
+// Copyright 2011 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 crc32
+
+// This file contains the code to call the SSE 4.2 version of the Castagnoli
+// CRC.
+
+// haveSSE42 is defined in crc_amd64p32.s and uses CPUID to test for SSE 4.2
+// support.
+func haveSSE42() bool
+
+// castagnoliSSE42 is defined in crc_amd64.s and uses the SSE4.2 CRC32
+// instruction.
+//go:noescape
+func castagnoliSSE42(crc uint32, p []byte) uint32
+
+var sse42 = haveSSE42()
+
+func updateCastagnoli(crc uint32, p []byte) uint32 {
+	if sse42 {
+		return castagnoliSSE42(crc, p)
+	}
+	return update(crc, castagnoliTable, p)
+}
+
+func updateIEEE(crc uint32, p []byte) uint32 {
+	// only use slicing-by-8 when input is >= 4KB
+	if len(p) >= 4096 {
+		ieeeTable8Once.Do(func() {
+			ieeeTable8 = makeTable8(IEEE)
+		})
+		return updateSlicingBy8(crc, ieeeTable8, p)
+	}
+
+	return update(crc, IEEETable, p)
+}
diff --git a/src/hash/crc32/crc32_amd64x.go b/src/hash/crc32/crc32_amd64x.go
deleted file mode 100644
index b7e3599..0000000
--- a/src/hash/crc32/crc32_amd64x.go
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2011 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.
-
-// +build amd64 amd64p32
-
-package crc32
-
-// This file contains the code to call the SSE 4.2 version of the Castagnoli
-// CRC.
-
-// haveSSE42 is defined in crc_amd64.s and uses CPUID to test for SSE 4.2
-// support.
-func haveSSE42() bool
-
-// castagnoliSSE42 is defined in crc_amd64.s and uses the SSE4.2 CRC32
-// instruction.
-func castagnoliSSE42(crc uint32, p []byte) uint32
-
-var sse42 = haveSSE42()
-
-func updateCastagnoli(crc uint32, p []byte) uint32 {
-	if sse42 {
-		return castagnoliSSE42(crc, p)
-	}
-	return update(crc, castagnoliTable, p)
-}
diff --git a/src/hash/crc32/crc32_generic.go b/src/hash/crc32/crc32_generic.go
index 416c1b7..8fc11a7 100644
--- a/src/hash/crc32/crc32_generic.go
+++ b/src/hash/crc32/crc32_generic.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.
 
-// +build 386 arm arm64 ppc64 ppc64le
+// +build 386 arm arm64 mips64 mips64le ppc64 ppc64le
 
 package crc32
 
@@ -12,3 +12,14 @@ package crc32
 func updateCastagnoli(crc uint32, p []byte) uint32 {
 	return update(crc, castagnoliTable, p)
 }
+
+func updateIEEE(crc uint32, p []byte) uint32 {
+	// only use slicing-by-8 when input is >= 4KB
+	if len(p) >= 4096 {
+		ieeeTable8Once.Do(func() {
+			ieeeTable8 = makeTable8(IEEE)
+		})
+		return updateSlicingBy8(crc, ieeeTable8, p)
+	}
+	return update(crc, IEEETable, p)
+}
diff --git a/src/hash/crc64/crc64.go b/src/hash/crc64/crc64.go
index 6925867..54cc560 100644
--- a/src/hash/crc64/crc64.go
+++ b/src/hash/crc64/crc64.go
@@ -24,7 +24,8 @@ const (
 // Table is a 256-word table representing the polynomial for efficient processing.
 type Table [256]uint64
 
-// MakeTable returns the Table constructed from the specified polynomial.
+// MakeTable returns a Table constructed from the specified polynomial.
+// The contents of this Table must not be modified.
 func MakeTable(poly uint64) *Table {
 	t := new(Table)
 	for i := 0; i < 256; i++ {
@@ -49,6 +50,7 @@ type digest struct {
 
 // New creates a new hash.Hash64 computing the CRC-64 checksum
 // using the polynomial represented by the Table.
+// Its Sum method will lay the value out in big-endian byte order.
 func New(tab *Table) hash.Hash64 { return &digest{0, tab} }
 
 func (d *digest) Size() int { return Size }
diff --git a/src/hash/fnv/fnv.go b/src/hash/fnv/fnv.go
index c020661..f1fbb25 100644
--- a/src/hash/fnv/fnv.go
+++ b/src/hash/fnv/fnv.go
@@ -5,7 +5,7 @@
 // Package fnv implements FNV-1 and FNV-1a, non-cryptographic hash functions
 // created by Glenn Fowler, Landon Curt Noll, and Phong Vo.
 // See
-// http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function.
+// https://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function.
 package fnv
 
 import (
@@ -27,24 +27,28 @@ const (
 )
 
 // New32 returns a new 32-bit FNV-1 hash.Hash.
+// Its Sum method will lay the value out in big-endian byte order.
 func New32() hash.Hash32 {
 	var s sum32 = offset32
 	return &s
 }
 
 // New32a returns a new 32-bit FNV-1a hash.Hash.
+// Its Sum method will lay the value out in big-endian byte order.
 func New32a() hash.Hash32 {
 	var s sum32a = offset32
 	return &s
 }
 
 // New64 returns a new 64-bit FNV-1 hash.Hash.
+// Its Sum method will lay the value out in big-endian byte order.
 func New64() hash.Hash64 {
 	var s sum64 = offset64
 	return &s
 }
 
 // New64a returns a new 64-bit FNV-1a hash.Hash.
+// Its Sum method will lay the value out in big-endian byte order.
 func New64a() hash.Hash64 {
 	var s sum64a = offset64
 	return &s
diff --git a/src/html/escape.go b/src/html/escape.go
index f50a4b9..ab6fd1c 100644
--- a/src/html/escape.go
+++ b/src/html/escape.go
@@ -57,8 +57,9 @@ var replacementTable = [...]rune{
 // unescapeEntity reads an entity like "<" from b[src:] and writes the
 // corresponding "<" to b[dst:], returning the incremented dst and src cursors.
 // Precondition: b[src] == '&' && dst <= src.
-// attribute should be true if parsing an attribute value.
-func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 int) {
+func unescapeEntity(b []byte, dst, src int) (dst1, src1 int) {
+	const attribute = false
+
 	// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#consume-a-character-reference
 
 	// i starts at 1 because we already know that s[0] == '&'.
@@ -139,14 +140,14 @@ func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 int) {
 		break
 	}
 
-	entityName := string(s[1:i])
-	if entityName == "" {
+	entityName := s[1:i]
+	if len(entityName) == 0 {
 		// No-op.
 	} else if attribute && entityName[len(entityName)-1] != ';' && len(s) > i && s[i] == '=' {
 		// No-op.
-	} else if x := entity[entityName]; x != 0 {
+	} else if x := entity[string(entityName)]; x != 0 {
 		return dst + utf8.EncodeRune(b[dst:], x), src + i
-	} else if x := entity2[entityName]; x[0] != 0 {
+	} else if x := entity2[string(entityName)]; x[0] != 0 {
 		dst1 := dst + utf8.EncodeRune(b[dst:], x[0])
 		return dst1 + utf8.EncodeRune(b[dst1:], x[1]), src + i
 	} else if !attribute {
@@ -155,7 +156,7 @@ func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 int) {
 			maxLen = longestEntityWithoutSemicolon
 		}
 		for j := maxLen; j > 1; j-- {
-			if x := entity[entityName[:j]]; x != 0 {
+			if x := entity[string(entityName[:j])]; x != 0 {
 				return dst + utf8.EncodeRune(b[dst:], x), src + j + 1
 			}
 		}
@@ -166,26 +167,6 @@ func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 int) {
 	return dst1, src1
 }
 
-// unescape unescapes b's entities in-place, so that "a<b" becomes "a<b".
-func unescape(b []byte) []byte {
-	for i, c := range b {
-		if c == '&' {
-			dst, src := unescapeEntity(b, i, i, false)
-			for src < len(b) {
-				c := b[src]
-				if c == '&' {
-					dst, src = unescapeEntity(b, dst, src, false)
-				} else {
-					b[dst] = c
-					dst, src = dst+1, src+1
-				}
-			}
-			return b[0:dst]
-		}
-	}
-	return b
-}
-
 var htmlEscaper = strings.NewReplacer(
 	`&`, "&",
 	`'`, "'", // "'" is shorter than "'" and apos was not in HTML until HTML5.
@@ -208,8 +189,29 @@ func EscapeString(s string) string {
 // UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
 // always true.
 func UnescapeString(s string) string {
-	if !strings.Contains(s, "&") {
+	i := strings.IndexByte(s, '&')
+
+	if i < 0 {
 		return s
 	}
-	return string(unescape([]byte(s)))
+
+	b := []byte(s)
+	dst, src := unescapeEntity(b, i, i)
+	for len(s[src:]) > 0 {
+		if s[src] == '&' {
+			i = 0
+		} else {
+			i = strings.IndexByte(s[src:], '&')
+		}
+		if i < 0 {
+			dst += copy(b[dst:], s[src:])
+			break
+		}
+
+		if i > 0 {
+			copy(b[dst:], s[src:src+i])
+		}
+		dst, src = unescapeEntity(b, dst+i, src+i)
+	}
+	return string(b[:dst])
 }
diff --git a/src/html/escape_test.go b/src/html/escape_test.go
index 3702626..8b51a55 100644
--- a/src/html/escape_test.go
+++ b/src/html/escape_test.go
@@ -118,8 +118,10 @@ func TestUnescapeEscape(t *testing.T) {
 }
 
 var (
-	benchEscapeData = strings.Repeat("AAAAA < BBBBB > CCCCC & DDDDD ' EEEEE \" ", 100)
-	benchEscapeNone = strings.Repeat("AAAAA x BBBBB x CCCCC x DDDDD x EEEEE x ", 100)
+	benchEscapeData     = strings.Repeat("AAAAA < BBBBB > CCCCC & DDDDD ' EEEEE \" ", 100)
+	benchEscapeNone     = strings.Repeat("AAAAA x BBBBB x CCCCC x DDDDD x EEEEE x ", 100)
+	benchUnescapeSparse = strings.Repeat(strings.Repeat("AAAAA x BBBBB x CCCCC x DDDDD x EEEEE x ", 10)+"&", 10)
+	benchUnescapeDense  = strings.Repeat("&< & <", 100)
 )
 
 func BenchmarkEscape(b *testing.B) {
@@ -151,3 +153,17 @@ func BenchmarkUnescapeNone(b *testing.B) {
 		n += len(UnescapeString(s))
 	}
 }
+
+func BenchmarkUnescapeSparse(b *testing.B) {
+	n := 0
+	for i := 0; i < b.N; i++ {
+		n += len(UnescapeString(benchUnescapeSparse))
+	}
+}
+
+func BenchmarkUnescapeDense(b *testing.B) {
+	n := 0
+	for i := 0; i < b.N; i++ {
+		n += len(UnescapeString(benchUnescapeDense))
+	}
+}
diff --git a/src/html/template/clone_test.go b/src/html/template/clone_test.go
index c89d22a..d7c62fa 100644
--- a/src/html/template/clone_test.go
+++ b/src/html/template/clone_test.go
@@ -78,9 +78,17 @@ func TestClone(t *testing.T) {
 	Must(t0.Parse(`{{define "lhs"}} ( {{end}}`))
 	Must(t0.Parse(`{{define "rhs"}} ) {{end}}`))
 
-	// Clone t0 as t4. Redefining the "lhs" template should fail.
+	// Clone t0 as t4. Redefining the "lhs" template should not fail.
 	t4 := Must(t0.Clone())
-	if _, err := t4.Parse(`{{define "lhs"}} FAIL {{end}}`); err == nil {
+	if _, err := t4.Parse(`{{define "lhs"}} OK {{end}}`); err != nil {
+		t.Errorf(`redefine "lhs": got err %v want nil`, err)
+	}
+	// Cloning t1 should fail as it has been executed.
+	if _, err := t1.Clone(); err == nil {
+		t.Error("cloning t1: got nil err want non-nil")
+	}
+	// Redefining the "lhs" template in t1 should fail as it has been executed.
+	if _, err := t1.Parse(`{{define "lhs"}} OK {{end}}`); err == nil {
 		t.Error(`redefine "lhs": got nil err want non-nil`)
 	}
 
diff --git a/src/html/template/context.go b/src/html/template/context.go
index 59e794d..c90fc1f 100644
--- a/src/html/template/context.go
+++ b/src/html/template/context.go
@@ -310,7 +310,8 @@ func (e element) String() string {
 	return fmt.Sprintf("illegal element %d", int(e))
 }
 
-// attr identifies the most recent HTML attribute when inside a start tag.
+// attr identifies the current HTML attribute when inside the attribute,
+// that is, starting from stateAttrName until stateTag/stateText (exclusive).
 type attr uint8
 
 const (
diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
index bea2d13..707394e 100644
--- a/src/html/template/escape_test.go
+++ b/src/html/template/escape_test.go
@@ -1054,7 +1054,7 @@ func TestEscapeText(t *testing.T) {
 		},
 		{
 			`<a href=x`,
-			context{state: stateURL, delim: delimSpaceOrTagEnd, urlPart: urlPartPreQuery},
+			context{state: stateURL, delim: delimSpaceOrTagEnd, urlPart: urlPartPreQuery, attr: attrURL},
 		},
 		{
 			`<a href=x `,
@@ -1070,7 +1070,7 @@ func TestEscapeText(t *testing.T) {
 		},
 		{
 			`<a href ='`,
-			context{state: stateURL, delim: delimSingleQuote},
+			context{state: stateURL, delim: delimSingleQuote, attr: attrURL},
 		},
 		{
 			`<a href=''`,
@@ -1078,7 +1078,7 @@ func TestEscapeText(t *testing.T) {
 		},
 		{
 			`<a href= "`,
-			context{state: stateURL, delim: delimDoubleQuote},
+			context{state: stateURL, delim: delimDoubleQuote, attr: attrURL},
 		},
 		{
 			`<a href=""`,
@@ -1090,35 +1090,35 @@ func TestEscapeText(t *testing.T) {
 		},
 		{
 			`<a HREF='http:`,
-			context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery},
+			context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery, attr: attrURL},
 		},
 		{
 			`<a Href='/`,
-			context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery},
+			context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery, attr: attrURL},
 		},
 		{
 			`<a href='"`,
-			context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery},
+			context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery, attr: attrURL},
 		},
 		{
 			`<a href="'`,
-			context{state: stateURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+			context{state: stateURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery, attr: attrURL},
 		},
 		{
 			`<a href=''`,
-			context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery},
+			context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery, attr: attrURL},
 		},
 		{
 			`<a href=""`,
-			context{state: stateURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+			context{state: stateURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery, attr: attrURL},
 		},
 		{
 			`<a href=""`,
-			context{state: stateURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+			context{state: stateURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery, attr: attrURL},
 		},
 		{
 			`<a href="`,
-			context{state: stateURL, delim: delimSpaceOrTagEnd, urlPart: urlPartPreQuery},
+			context{state: stateURL, delim: delimSpaceOrTagEnd, urlPart: urlPartPreQuery, attr: attrURL},
 		},
 		{
 			`<img alt="1">`,
@@ -1138,83 +1138,83 @@ func TestEscapeText(t *testing.T) {
 		},
 		{
 			`<a onclick="`,
-			context{state: stateJS, delim: delimDoubleQuote},
+			context{state: stateJS, delim: delimDoubleQuote, attr: attrScript},
 		},
 		{
 			`<a onclick="//foo`,
-			context{state: stateJSLineCmt, delim: delimDoubleQuote},
+			context{state: stateJSLineCmt, delim: delimDoubleQuote, attr: attrScript},
 		},
 		{
 			"<a onclick='//\n",
-			context{state: stateJS, delim: delimSingleQuote},
+			context{state: stateJS, delim: delimSingleQuote, attr: attrScript},
 		},
 		{
 			"<a onclick='//\r\n",
-			context{state: stateJS, delim: delimSingleQuote},
+			context{state: stateJS, delim: delimSingleQuote, attr: attrScript},
 		},
 		{
 			"<a onclick='//\u2028",
-			context{state: stateJS, delim: delimSingleQuote},
+			context{state: stateJS, delim: delimSingleQuote, attr: attrScript},
 		},
 		{
 			`<a onclick="/*`,
-			context{state: stateJSBlockCmt, delim: delimDoubleQuote},
+			context{state: stateJSBlockCmt, delim: delimDoubleQuote, attr: attrScript},
 		},
 		{
 			`<a onclick="/*/`,
-			context{state: stateJSBlockCmt, delim: delimDoubleQuote},
+			context{state: stateJSBlockCmt, delim: delimDoubleQuote, attr: attrScript},
 		},
 		{
 			`<a onclick="/**/`,
-			context{state: stateJS, delim: delimDoubleQuote},
+			context{state: stateJS, delim: delimDoubleQuote, attr: attrScript},
 		},
 		{
 			`<a onkeypress=""`,
-			context{state: stateJSDqStr, delim: delimDoubleQuote},
+			context{state: stateJSDqStr, delim: delimDoubleQuote, attr: attrScript},
 		},
 		{
 			`<a onclick='"foo"`,
-			context{state: stateJS, delim: delimSingleQuote, jsCtx: jsCtxDivOp},
+			context{state: stateJS, delim: delimSingleQuote, jsCtx: jsCtxDivOp, attr: attrScript},
 		},
 		{
 			`<a onclick='foo'`,
-			context{state: stateJS, delim: delimSpaceOrTagEnd, jsCtx: jsCtxDivOp},
+			context{state: stateJS, delim: delimSpaceOrTagEnd, jsCtx: jsCtxDivOp, attr: attrScript},
 		},
 		{
 			`<a onclick='foo`,
-			context{state: stateJSSqStr, delim: delimSpaceOrTagEnd},
+			context{state: stateJSSqStr, delim: delimSpaceOrTagEnd, attr: attrScript},
 		},
 		{
 			`<a onclick=""foo'`,
-			context{state: stateJSDqStr, delim: delimDoubleQuote},
+			context{state: stateJSDqStr, delim: delimDoubleQuote, attr: attrScript},
 		},
 		{
 			`<a onclick="'foo"`,
-			context{state: stateJSSqStr, delim: delimDoubleQuote},
+			context{state: stateJSSqStr, delim: delimDoubleQuote, attr: attrScript},
 		},
 		{
 			`<A ONCLICK="'`,
-			context{state: stateJSSqStr, delim: delimDoubleQuote},
+			context{state: stateJSSqStr, delim: delimDoubleQuote, attr: attrScript},
 		},
 		{
 			`<a onclick="/`,
-			context{state: stateJSRegexp, delim: delimDoubleQuote},
+			context{state: stateJSRegexp, delim: delimDoubleQuote, attr: attrScript},
 		},
 		{
 			`<a onclick="'foo'`,
-			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
+			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp, attr: attrScript},
 		},
 		{
 			`<a onclick="'foo\'`,
-			context{state: stateJSSqStr, delim: delimDoubleQuote},
+			context{state: stateJSSqStr, delim: delimDoubleQuote, attr: attrScript},
 		},
 		{
 			`<a onclick="'foo\'`,
-			context{state: stateJSSqStr, delim: delimDoubleQuote},
+			context{state: stateJSSqStr, delim: delimDoubleQuote, attr: attrScript},
 		},
 		{
 			`<a onclick="/foo/`,
-			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
+			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp, attr: attrScript},
 		},
 		{
 			`<script>/foo/ /=`,
@@ -1222,111 +1222,111 @@ func TestEscapeText(t *testing.T) {
 		},
 		{
 			`<a onclick="1 /foo`,
-			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
+			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp, attr: attrScript},
 		},
 		{
 			`<a onclick="1 /*c*/ /foo`,
-			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
+			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp, attr: attrScript},
 		},
 		{
 			`<a onclick="/foo[/]`,
-			context{state: stateJSRegexp, delim: delimDoubleQuote},
+			context{state: stateJSRegexp, delim: delimDoubleQuote, attr: attrScript},
 		},
 		{
 			`<a onclick="/foo\/`,
-			context{state: stateJSRegexp, delim: delimDoubleQuote},
+			context{state: stateJSRegexp, delim: delimDoubleQuote, attr: attrScript},
 		},
 		{
 			`<a onclick="/foo/`,
-			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
+			context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp, attr: attrScript},
 		},
 		{
 			`<input checked style="`,
-			context{state: stateCSS, delim: delimDoubleQuote},
+			context{state: stateCSS, delim: delimDoubleQuote, attr: attrStyle},
 		},
 		{
 			`<a style="//`,
-			context{state: stateCSSLineCmt, delim: delimDoubleQuote},
+			context{state: stateCSSLineCmt, delim: delimDoubleQuote, attr: attrStyle},
 		},
 		{
 			`<a style="//</script>`,
-			context{state: stateCSSLineCmt, delim: delimDoubleQuote},
+			context{state: stateCSSLineCmt, delim: delimDoubleQuote, attr: attrStyle},
 		},
 		{
 			"<a style='//\n",
-			context{state: stateCSS, delim: delimSingleQuote},
+			context{state: stateCSS, delim: delimSingleQuote, attr: attrStyle},
 		},
 		{
 			"<a style='//\r",
-			context{state: stateCSS, delim: delimSingleQuote},
+			context{state: stateCSS, delim: delimSingleQuote, attr: attrStyle},
 		},
 		{
 			`<a style="/*`,
-			context{state: stateCSSBlockCmt, delim: delimDoubleQuote},
+			context{state: stateCSSBlockCmt, delim: delimDoubleQuote, attr: attrStyle},
 		},
 		{
 			`<a style="/*/`,
-			context{state: stateCSSBlockCmt, delim: delimDoubleQuote},
+			context{state: stateCSSBlockCmt, delim: delimDoubleQuote, attr: attrStyle},
 		},
 		{
 			`<a style="/**/`,
-			context{state: stateCSS, delim: delimDoubleQuote},
+			context{state: stateCSS, delim: delimDoubleQuote, attr: attrStyle},
 		},
 		{
 			`<a style="background: '`,
-			context{state: stateCSSSqStr, delim: delimDoubleQuote},
+			context{state: stateCSSSqStr, delim: delimDoubleQuote, attr: attrStyle},
 		},
 		{
 			`<a style="background: "`,
-			context{state: stateCSSDqStr, delim: delimDoubleQuote},
+			context{state: stateCSSDqStr, delim: delimDoubleQuote, attr: attrStyle},
 		},
 		{
 			`<a style="background: '/foo?img=`,
-			context{state: stateCSSSqStr, delim: delimDoubleQuote, urlPart: urlPartQueryOrFrag},
+			context{state: stateCSSSqStr, delim: delimDoubleQuote, urlPart: urlPartQueryOrFrag, attr: attrStyle},
 		},
 		{
 			`<a style="background: '/`,
-			context{state: stateCSSSqStr, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+			context{state: stateCSSSqStr, delim: delimDoubleQuote, urlPart: urlPartPreQuery, attr: attrStyle},
 		},
 		{
 			`<a style="background: url(&#x22;/`,
-			context{state: stateCSSDqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+			context{state: stateCSSDqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery, attr: attrStyle},
 		},
 		{
 			`<a style="background: url('/`,
-			context{state: stateCSSSqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+			context{state: stateCSSSqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery, attr: attrStyle},
 		},
 		{
 			`<a style="background: url('/)`,
-			context{state: stateCSSSqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+			context{state: stateCSSSqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery, attr: attrStyle},
 		},
 		{
 			`<a style="background: url('/ `,
-			context{state: stateCSSSqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+			context{state: stateCSSSqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery, attr: attrStyle},
 		},
 		{
 			`<a style="background: url(/`,
-			context{state: stateCSSURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+			context{state: stateCSSURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery, attr: attrStyle},
 		},
 		{
 			`<a style="background: url( `,
-			context{state: stateCSSURL, delim: delimDoubleQuote},
+			context{state: stateCSSURL, delim: delimDoubleQuote, attr: attrStyle},
 		},
 		{
 			`<a style="background: url( /image?name=`,
-			context{state: stateCSSURL, delim: delimDoubleQuote, urlPart: urlPartQueryOrFrag},
+			context{state: stateCSSURL, delim: delimDoubleQuote, urlPart: urlPartQueryOrFrag, attr: attrStyle},
 		},
 		{
 			`<a style="background: url(x)`,
-			context{state: stateCSS, delim: delimDoubleQuote},
+			context{state: stateCSS, delim: delimDoubleQuote, attr: attrStyle},
 		},
 		{
 			`<a style="background: url('x'`,
-			context{state: stateCSS, delim: delimDoubleQuote},
+			context{state: stateCSS, delim: delimDoubleQuote, attr: attrStyle},
 		},
 		{
 			`<a style="background: url( x `,
-			context{state: stateCSS, delim: delimDoubleQuote},
+			context{state: stateCSS, delim: delimDoubleQuote, attr: attrStyle},
 		},
 		{
 			`<!-- foo`,
@@ -1466,7 +1466,7 @@ func TestEscapeText(t *testing.T) {
 		},
 		{
 			`<a svg:style='`,
-			context{state: stateCSS, delim: delimSingleQuote},
+			context{state: stateCSS, delim: delimSingleQuote, attr: attrStyle},
 		},
 		{
 			`<svg:font-face`,
@@ -1474,7 +1474,11 @@ func TestEscapeText(t *testing.T) {
 		},
 		{
 			`<svg:a svg:onclick="`,
-			context{state: stateJS, delim: delimDoubleQuote},
+			context{state: stateJS, delim: delimDoubleQuote, attr: attrScript},
+		},
+		{
+			`<svg:a svg:onclick="x()">`,
+			context{},
 		},
 	}
 
diff --git a/src/html/template/example_test.go b/src/html/template/example_test.go
index a75ceec..3fc9820 100644
--- a/src/html/template/example_test.go
+++ b/src/html/template/example_test.go
@@ -9,6 +9,7 @@ import (
 	"html/template"
 	"log"
 	"os"
+	"strings"
 )
 
 func Example() {
@@ -30,6 +31,7 @@ func Example() {
 		}
 	}
 	t, err := template.New("webpage").Parse(tpl)
+	check(err)
 
 	data := struct {
 		Title string
@@ -120,3 +122,38 @@ func Example_escape() {
 	// %22Fran+%26+Freddie%27s+Diner%2232%3Ctasty%40example.com%3E
 
 }
+
+// The following example is duplicated in text/template; keep them in sync.
+
+func ExampleTemplate_block() {
+	const (
+		master  = `Names:{{block "list" .}}{{"\n"}}{{range .}}{{println "-" .}}{{end}}{{end}}`
+		overlay = `{{define "list"}} {{join . ", "}}{{end}} `
+	)
+	var (
+		funcs     = template.FuncMap{"join": strings.Join}
+		guardians = []string{"Gamora", "Groot", "Nebula", "Rocket", "Star-Lord"}
+	)
+	masterTmpl, err := template.New("master").Funcs(funcs).Parse(master)
+	if err != nil {
+		log.Fatal(err)
+	}
+	overlayTmpl, err := template.Must(masterTmpl.Clone()).Parse(overlay)
+	if err != nil {
+		log.Fatal(err)
+	}
+	if err := masterTmpl.Execute(os.Stdout, guardians); err != nil {
+		log.Fatal(err)
+	}
+	if err := overlayTmpl.Execute(os.Stdout, guardians); err != nil {
+		log.Fatal(err)
+	}
+	// Output:
+	// Names:
+	// - Gamora
+	// - Groot
+	// - Nebula
+	// - Rocket
+	// - Star-Lord
+	// Names: Gamora, Groot, Nebula, Rocket, Star-Lord
+}
diff --git a/src/html/template/template.go b/src/html/template/template.go
index bb9140a..96ab268 100644
--- a/src/html/template/template.go
+++ b/src/html/template/template.go
@@ -17,7 +17,7 @@ import (
 // Template is a specialized Template from "text/template" that produces a safe
 // HTML document fragment.
 type Template struct {
-	// Sticky error if escaping fails.
+	// Sticky error if escaping fails, or escapeOK if succeeded.
 	escapeErr error
 	// We could embed the text/template field, but it's safer not to because
 	// we need to keep our version of the name space and the underlying
@@ -80,7 +80,7 @@ func (t *Template) escape() error {
 	defer t.nameSpace.mu.Unlock()
 	if t.escapeErr == nil {
 		if t.Tree == nil {
-			return fmt.Errorf("template: %q is an incomplete or empty template%s", t.Name(), t.text.DefinedTemplates())
+			return fmt.Errorf("template: %q is an incomplete or empty template%s", t.Name(), t.DefinedTemplates())
 		}
 		if err := escapeTemplate(t, t.text.Root, t.Name()); err != nil {
 			return err
@@ -143,6 +143,13 @@ func (t *Template) lookupAndEscapeTemplate(name string) (tmpl *Template, err err
 	return tmpl, err
 }
 
+// DefinedTemplates returns a string listing the defined templates,
+// prefixed by the string "; defined templates are: ". If there are none,
+// it returns the empty string. Used to generate an error message.
+func (t *Template) DefinedTemplates() string {
+	return t.text.DefinedTemplates()
+}
+
 // Parse parses a string into a template. Nested template definitions
 // will be associated with the top-level template t. Parse may be
 // called multiple times to parse definitions of templates to associate
@@ -169,6 +176,8 @@ func (t *Template) Parse(src string) (*Template, error) {
 		tmpl := t.set[name]
 		if tmpl == nil {
 			tmpl = t.new(name)
+		} else if tmpl.escapeErr != nil {
+			return nil, fmt.Errorf("html/template: cannot redefine %q after it has executed", name)
 		}
 		// Restore our record of this text/template to its unescaped original state.
 		tmpl.escapeErr = nil
@@ -228,6 +237,7 @@ func (t *Template) Clone() (*Template, error) {
 			set: make(map[string]*Template),
 		},
 	}
+	ret.set[ret.Name()] = ret
 	for _, x := range textClone.Templates() {
 		name := x.Name()
 		src := t.set[name]
@@ -413,3 +423,10 @@ func parseGlob(t *Template, pattern string) (*Template, error) {
 	}
 	return parseFiles(t, filenames...)
 }
+
+// IsTrue reports whether the value is 'true', in the sense of not the zero of its type,
+// and whether the value has a meaningful truth value. This is the definition of
+// truth used by if and other such actions.
+func IsTrue(val interface{}) (truth, ok bool) {
+	return template.IsTrue(val)
+}
diff --git a/src/html/template/template_test.go b/src/html/template/template_test.go
new file mode 100644
index 0000000..6f70d67
--- /dev/null
+++ b/src/html/template/template_test.go
@@ -0,0 +1,29 @@
+package template
+
+import (
+	"bytes"
+	"testing"
+)
+
+func TestTemplateClone(t *testing.T) {
+	// https://golang.org/issue/12996
+	orig := New("name")
+	clone, err := orig.Clone()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if len(clone.Templates()) != len(orig.Templates()) {
+		t.Fatalf("Invalid lenth of t.Clone().Templates()")
+	}
+
+	const want = "stuff"
+	parsed := Must(clone.Parse(want))
+	var buf bytes.Buffer
+	err = parsed.Execute(&buf, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if got := buf.String(); got != want {
+		t.Fatalf("got %q; want %q", got, want)
+	}
+}
diff --git a/src/html/template/transition.go b/src/html/template/transition.go
index d2e0287..aefe035 100644
--- a/src/html/template/transition.go
+++ b/src/html/template/transition.go
@@ -169,7 +169,7 @@ func tBeforeValue(c context, s []byte) (context, int) {
 	case '"':
 		delim, i = delimDoubleQuote, i+1
 	}
-	c.state, c.delim, c.attr = attrStartStates[c.attr], delim, attrNone
+	c.state, c.delim = attrStartStates[c.attr], delim
 	return c, i
 }
 
diff --git a/src/image/color/ycbcr.go b/src/image/color/ycbcr.go
index 4bcb07d..904434f 100644
--- a/src/image/color/ycbcr.go
+++ b/src/image/color/ycbcr.go
@@ -98,7 +98,7 @@ func (c YCbCr) RGBA() (uint32, uint32, uint32, uint32) {
 	//	fmt.Printf("0x%04x 0x%04x 0x%04x\n", r0, g0, b0)
 	//	fmt.Printf("0x%04x 0x%04x 0x%04x\n", r1, g1, b1)
 	// prints:
-	//	0x7e18 0x808e 0x7db9
+	//	0x7e18 0x808d 0x7db9
 	//	0x7e7e 0x8080 0x7d7d
 
 	yy1 := int32(c.Y) * 0x10100 // Convert 0x12 to 0x121200.
@@ -137,6 +137,66 @@ func yCbCrModel(c Color) Color {
 	return YCbCr{y, u, v}
 }
 
+// NYCbCrA represents a non-alpha-premultiplied Y'CbCr-with-alpha color, having
+// 8 bits each for one luma, two chroma and one alpha component.
+type NYCbCrA struct {
+	YCbCr
+	A uint8
+}
+
+func (c NYCbCrA) RGBA() (uint32, uint32, uint32, uint32) {
+	// The first part of this method is the same as YCbCr.RGBA.
+	yy1 := int32(c.Y) * 0x10100 // Convert 0x12 to 0x121200.
+	cb1 := int32(c.Cb) - 128
+	cr1 := int32(c.Cr) - 128
+	r := (yy1 + 91881*cr1) >> 8
+	g := (yy1 - 22554*cb1 - 46802*cr1) >> 8
+	b := (yy1 + 116130*cb1) >> 8
+	if r < 0 {
+		r = 0
+	} else if r > 0xffff {
+		r = 0xffff
+	}
+	if g < 0 {
+		g = 0
+	} else if g > 0xffff {
+		g = 0xffff
+	}
+	if b < 0 {
+		b = 0
+	} else if b > 0xffff {
+		b = 0xffff
+	}
+
+	// The second part of this method applies the alpha.
+	a := uint32(c.A) * 0x101
+	return uint32(r) * a / 0xffff, uint32(g) * a / 0xffff, uint32(b) * a / 0xffff, a
+}
+
+// NYCbCrAModel is the Model for non-alpha-premultiplied Y'CbCr-with-alpha
+// colors.
+var NYCbCrAModel Model = ModelFunc(nYCbCrAModel)
+
+func nYCbCrAModel(c Color) Color {
+	switch c := c.(type) {
+	case NYCbCrA:
+		return c
+	case YCbCr:
+		return NYCbCrA{c, 0xff}
+	}
+	r, g, b, a := c.RGBA()
+
+	// Convert from alpha-premultiplied to non-alpha-premultiplied.
+	if a != 0 {
+		r = (r * 0xffff) / a
+		g = (g * 0xffff) / a
+		b = (b * 0xffff) / a
+	}
+
+	y, u, v := RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
+	return NYCbCrA{YCbCr{Y: y, Cb: u, Cr: v}, uint8(a >> 8)}
+}
+
 // RGBToCMYK converts an RGB triple to a CMYK quadruple.
 func RGBToCMYK(r, g, b uint8) (uint8, uint8, uint8, uint8) {
 	rr := uint32(r)
diff --git a/src/image/color/ycbcr_test.go b/src/image/color/ycbcr_test.go
index 5da49d3..f5e7cbf 100644
--- a/src/image/color/ycbcr_test.go
+++ b/src/image/color/ycbcr_test.go
@@ -67,7 +67,31 @@ func TestYCbCrToRGBConsistency(t *testing.T) {
 // TestYCbCrGray tests that YCbCr colors are a superset of Gray colors.
 func TestYCbCrGray(t *testing.T) {
 	for i := 0; i < 256; i++ {
-		if err := eq(YCbCr{uint8(i), 0x80, 0x80}, Gray{uint8(i)}); err != nil {
+		c0 := YCbCr{uint8(i), 0x80, 0x80}
+		c1 := Gray{uint8(i)}
+		if err := eq(c0, c1); err != nil {
+			t.Errorf("i=0x%02x:\n%v", i, err)
+		}
+	}
+}
+
+// TestNYCbCrAAlpha tests that NYCbCrA colors are a superset of Alpha colors.
+func TestNYCbCrAAlpha(t *testing.T) {
+	for i := 0; i < 256; i++ {
+		c0 := NYCbCrA{YCbCr{0xff, 0x80, 0x80}, uint8(i)}
+		c1 := Alpha{uint8(i)}
+		if err := eq(c0, c1); err != nil {
+			t.Errorf("i=0x%02x:\n%v", i, err)
+		}
+	}
+}
+
+// TestNYCbCrAYCbCr tests that NYCbCrA colors are a superset of YCbCr colors.
+func TestNYCbCrAYCbCr(t *testing.T) {
+	for i := 0; i < 256; i++ {
+		c0 := NYCbCrA{YCbCr{uint8(i), 0x40, 0xc0}, 0xff}
+		c1 := YCbCr{uint8(i), 0x40, 0xc0}
+		if err := eq(c0, c1); err != nil {
 			t.Errorf("i=0x%02x:\n%v", i, err)
 		}
 	}
diff --git a/src/image/draw/draw.go b/src/image/draw/draw.go
index 9419d5e..e47c48d 100644
--- a/src/image/draw/draw.go
+++ b/src/image/draw/draw.go
@@ -240,15 +240,15 @@ func drawFillOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform) {
 	i1 := i0 + r.Dx()*4
 	for y := r.Min.Y; y != r.Max.Y; y++ {
 		for i := i0; i < i1; i += 4 {
-			dr := uint32(dst.Pix[i+0])
-			dg := uint32(dst.Pix[i+1])
-			db := uint32(dst.Pix[i+2])
-			da := uint32(dst.Pix[i+3])
-
-			dst.Pix[i+0] = uint8((dr*a/m + sr) >> 8)
-			dst.Pix[i+1] = uint8((dg*a/m + sg) >> 8)
-			dst.Pix[i+2] = uint8((db*a/m + sb) >> 8)
-			dst.Pix[i+3] = uint8((da*a/m + sa) >> 8)
+			dr := &dst.Pix[i+0]
+			dg := &dst.Pix[i+1]
+			db := &dst.Pix[i+2]
+			da := &dst.Pix[i+3]
+
+			*dr = uint8((uint32(*dr)*a/m + sr) >> 8)
+			*dg = uint8((uint32(*dg)*a/m + sg) >> 8)
+			*db = uint8((uint32(*db)*a/m + sb) >> 8)
+			*da = uint8((uint32(*da)*a/m + sa) >> 8)
 		}
 		i0 += dst.Stride
 		i1 += dst.Stride
@@ -310,18 +310,18 @@ func drawCopyOver(dst *image.RGBA, r image.Rectangle, src *image.RGBA, sp image.
 			sb := uint32(spix[i+2]) * 0x101
 			sa := uint32(spix[i+3]) * 0x101
 
-			dr := uint32(dpix[i+0])
-			dg := uint32(dpix[i+1])
-			db := uint32(dpix[i+2])
-			da := uint32(dpix[i+3])
+			dr := &dpix[i+0]
+			dg := &dpix[i+1]
+			db := &dpix[i+2]
+			da := &dpix[i+3]
 
 			// The 0x101 is here for the same reason as in drawRGBA.
 			a := (m - sa) * 0x101
 
-			dpix[i+0] = uint8((dr*a/m + sr) >> 8)
-			dpix[i+1] = uint8((dg*a/m + sg) >> 8)
-			dpix[i+2] = uint8((db*a/m + sb) >> 8)
-			dpix[i+3] = uint8((da*a/m + sa) >> 8)
+			*dr = uint8((uint32(*dr)*a/m + sr) >> 8)
+			*dg = uint8((uint32(*dg)*a/m + sg) >> 8)
+			*db = uint8((uint32(*db)*a/m + sb) >> 8)
+			*da = uint8((uint32(*da)*a/m + sa) >> 8)
 		}
 		d0 += ddelta
 		s0 += sdelta
@@ -471,18 +471,18 @@ func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform, mask
 			}
 			ma |= ma << 8
 
-			dr := uint32(dst.Pix[i+0])
-			dg := uint32(dst.Pix[i+1])
-			db := uint32(dst.Pix[i+2])
-			da := uint32(dst.Pix[i+3])
+			dr := &dst.Pix[i+0]
+			dg := &dst.Pix[i+1]
+			db := &dst.Pix[i+2]
+			da := &dst.Pix[i+3]
 
 			// The 0x101 is here for the same reason as in drawRGBA.
 			a := (m - (sa * ma / m)) * 0x101
 
-			dst.Pix[i+0] = uint8((dr*a + sr*ma) / m >> 8)
-			dst.Pix[i+1] = uint8((dg*a + sg*ma) / m >> 8)
-			dst.Pix[i+2] = uint8((db*a + sb*ma) / m >> 8)
-			dst.Pix[i+3] = uint8((da*a + sa*ma) / m >> 8)
+			*dr = uint8((uint32(*dr)*a + sr*ma) / m >> 8)
+			*dg = uint8((uint32(*dg)*a + sg*ma) / m >> 8)
+			*db = uint8((uint32(*db)*a + sb*ma) / m >> 8)
+			*da = uint8((uint32(*da)*a + sa*ma) / m >> 8)
 		}
 		i0 += dst.Stride
 		i1 += dst.Stride
diff --git a/src/image/gif/writer.go b/src/image/gif/writer.go
index dd31790..1918196 100644
--- a/src/image/gif/writer.go
+++ b/src/image/gif/writer.go
@@ -83,7 +83,7 @@ func (b blockWriter) Write(data []byte) (int, error) {
 		total += n
 		b.e.buf[0] = uint8(n)
 
-		n, b.e.err = b.e.w.Write(b.e.buf[:n+1])
+		_, b.e.err = b.e.w.Write(b.e.buf[:n+1])
 		if b.e.err != nil {
 			return 0, b.e.err
 		}
diff --git a/src/image/gif/writer_test.go b/src/image/gif/writer_test.go
index db61a5c..775ccea 100644
--- a/src/image/gif/writer_test.go
+++ b/src/image/gif/writer_test.go
@@ -328,11 +328,11 @@ func TestEncodeAllFramesOutOfBounds(t *testing.T) {
 
 func TestEncodeNonZeroMinPoint(t *testing.T) {
 	points := []image.Point{
-		image.Point{-8, -9},
-		image.Point{-4, -4},
-		image.Point{-3, +3},
-		image.Point{+0, +0},
-		image.Point{+2, +2},
+		{-8, -9},
+		{-4, -4},
+		{-3, +3},
+		{+0, +0},
+		{+2, +2},
 	}
 	for _, p := range points {
 		src := image.NewPaletted(image.Rectangle{Min: p, Max: p.Add(image.Point{6, 6})}, palette.Plan9)
diff --git a/src/image/image.go b/src/image/image.go
index 20b64d7..bebb9f7 100644
--- a/src/image/image.go
+++ b/src/image/image.go
@@ -148,7 +148,7 @@ func (p *RGBA) Opaque() bool {
 	return true
 }
 
-// NewRGBA returns a new RGBA with the given bounds.
+// NewRGBA returns a new RGBA image with the given bounds.
 func NewRGBA(r Rectangle) *RGBA {
 	w, h := r.Dx(), r.Dy()
 	buf := make([]uint8, 4*w*h)
@@ -260,7 +260,7 @@ func (p *RGBA64) Opaque() bool {
 	return true
 }
 
-// NewRGBA64 returns a new RGBA64 with the given bounds.
+// NewRGBA64 returns a new RGBA64 image with the given bounds.
 func NewRGBA64(r Rectangle) *RGBA64 {
 	w, h := r.Dx(), r.Dy()
 	pix := make([]uint8, 8*w*h)
@@ -359,7 +359,7 @@ func (p *NRGBA) Opaque() bool {
 	return true
 }
 
-// NewNRGBA returns a new NRGBA with the given bounds.
+// NewNRGBA returns a new NRGBA image with the given bounds.
 func NewNRGBA(r Rectangle) *NRGBA {
 	w, h := r.Dx(), r.Dy()
 	pix := make([]uint8, 4*w*h)
@@ -471,7 +471,7 @@ func (p *NRGBA64) Opaque() bool {
 	return true
 }
 
-// NewNRGBA64 returns a new NRGBA64 with the given bounds.
+// NewNRGBA64 returns a new NRGBA64 image with the given bounds.
 func NewNRGBA64(r Rectangle) *NRGBA64 {
 	w, h := r.Dx(), r.Dy()
 	pix := make([]uint8, 8*w*h)
@@ -563,7 +563,7 @@ func (p *Alpha) Opaque() bool {
 	return true
 }
 
-// NewAlpha returns a new Alpha with the given bounds.
+// NewAlpha returns a new Alpha image with the given bounds.
 func NewAlpha(r Rectangle) *Alpha {
 	w, h := r.Dx(), r.Dy()
 	pix := make([]uint8, 1*w*h)
@@ -658,7 +658,7 @@ func (p *Alpha16) Opaque() bool {
 	return true
 }
 
-// NewAlpha16 returns a new Alpha16 with the given bounds.
+// NewAlpha16 returns a new Alpha16 image with the given bounds.
 func NewAlpha16(r Rectangle) *Alpha16 {
 	w, h := r.Dx(), r.Dy()
 	pix := make([]uint8, 2*w*h)
@@ -737,7 +737,7 @@ func (p *Gray) Opaque() bool {
 	return true
 }
 
-// NewGray returns a new Gray with the given bounds.
+// NewGray returns a new Gray image with the given bounds.
 func NewGray(r Rectangle) *Gray {
 	w, h := r.Dx(), r.Dy()
 	pix := make([]uint8, 1*w*h)
@@ -819,7 +819,7 @@ func (p *Gray16) Opaque() bool {
 	return true
 }
 
-// NewGray16 returns a new Gray16 with the given bounds.
+// NewGray16 returns a new Gray16 image with the given bounds.
 func NewGray16(r Rectangle) *Gray16 {
 	w, h := r.Dx(), r.Dy()
 	pix := make([]uint8, 2*w*h)
@@ -905,7 +905,7 @@ func (p *CMYK) Opaque() bool {
 	return true
 }
 
-// NewCMYK returns a new CMYK with the given bounds.
+// NewCMYK returns a new CMYK image with the given bounds.
 func NewCMYK(r Rectangle) *CMYK {
 	w, h := r.Dx(), r.Dy()
 	buf := make([]uint8, 4*w*h)
@@ -1014,7 +1014,8 @@ func (p *Paletted) Opaque() bool {
 	return true
 }
 
-// NewPaletted returns a new Paletted with the given width, height and palette.
+// NewPaletted returns a new Paletted image with the given width, height and
+// palette.
 func NewPaletted(r Rectangle, p color.Palette) *Paletted {
 	w, h := r.Dx(), r.Dy()
 	pix := make([]uint8, 1*w*h)
diff --git a/src/image/png/reader.go b/src/image/png/reader.go
index bbd6f75..9e6f985 100644
--- a/src/image/png/reader.go
+++ b/src/image/png/reader.go
@@ -154,8 +154,8 @@ func (d *decoder) parseIHDR(length uint32) error {
 	d.interlace = int(d.tmp[12])
 	w := int32(binary.BigEndian.Uint32(d.tmp[0:4]))
 	h := int32(binary.BigEndian.Uint32(d.tmp[4:8]))
-	if w < 0 || h < 0 {
-		return FormatError("negative dimension")
+	if w <= 0 || h <= 0 {
+		return FormatError("non-positive dimension")
 	}
 	nPixels := int64(w) * int64(h)
 	if nPixels != int64(int(nPixels)) {
@@ -727,6 +727,9 @@ func (d *decoder) parseChunk() error {
 		d.stage = dsSeenIEND
 		return d.parseIEND(length)
 	}
+	if length > 0x7fffffff {
+		return FormatError(fmt.Sprintf("Bad chunk length: %d", length))
+	}
 	// Ignore this chunk (of a known length).
 	var ignored [4096]byte
 	for length > 0 {
diff --git a/src/image/png/reader_test.go b/src/image/png/reader_test.go
index f89e7ef..f058f6b 100644
--- a/src/image/png/reader_test.go
+++ b/src/image/png/reader_test.go
@@ -408,6 +408,18 @@ func TestMultipletRNSChunks(t *testing.T) {
 	}
 }
 
+func TestUnknownChunkLengthUnderflow(t *testing.T) {
+	data := []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0xff, 0xff,
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0xf4, 0x7c, 0x55, 0x04, 0x1a,
+		0xd3, 0x11, 0x9a, 0x73, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e, 0x00, 0x00,
+		0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf4, 0x7c, 0x55, 0x04, 0x1a,
+		0xd3}
+	_, err := Decode(bytes.NewReader(data))
+	if err == nil {
+		t.Errorf("Didn't fail reading an unknown chunk with length 0xffffffff")
+	}
+}
+
 func benchmarkDecode(b *testing.B, filename string, bytesPerPixel int) {
 	b.StopTimer()
 	data, err := ioutil.ReadFile(filename)
diff --git a/src/image/ycbcr.go b/src/image/ycbcr.go
index 93c354b..71c0518 100644
--- a/src/image/ycbcr.go
+++ b/src/image/ycbcr.go
@@ -138,9 +138,8 @@ func (p *YCbCr) Opaque() bool {
 	return true
 }
 
-// NewYCbCr returns a new YCbCr with the given bounds and subsample ratio.
-func NewYCbCr(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr {
-	w, h, cw, ch := r.Dx(), r.Dy(), 0, 0
+func yCbCrSize(r Rectangle, subsampleRatio YCbCrSubsampleRatio) (w, h, cw, ch int) {
+	w, h = r.Dx(), r.Dy()
 	switch subsampleRatio {
 	case YCbCrSubsampleRatio422:
 		cw = (r.Max.X+1)/2 - r.Min.X/2
@@ -162,6 +161,13 @@ func NewYCbCr(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr {
 		cw = w
 		ch = h
 	}
+	return
+}
+
+// NewYCbCr returns a new YCbCr image with the given bounds and subsample
+// ratio.
+func NewYCbCr(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr {
+	w, h, cw, ch := yCbCrSize(r, subsampleRatio)
 	i0 := w*h + 0*cw*ch
 	i1 := w*h + 1*cw*ch
 	i2 := w*h + 2*cw*ch
@@ -176,3 +182,117 @@ func NewYCbCr(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *YCbCr {
 		Rect:           r,
 	}
 }
+
+// NYCbCrA is an in-memory image of non-alpha-premultiplied Y'CbCr-with-alpha
+// colors. A and AStride are analogous to the Y and YStride fields of the
+// embedded YCbCr.
+type NYCbCrA struct {
+	YCbCr
+	A       []uint8
+	AStride int
+}
+
+func (p *NYCbCrA) ColorModel() color.Model {
+	return color.NYCbCrAModel
+}
+
+func (p *NYCbCrA) At(x, y int) color.Color {
+	return p.NYCbCrAAt(x, y)
+}
+
+func (p *NYCbCrA) NYCbCrAAt(x, y int) color.NYCbCrA {
+	if !(Point{X: x, Y: y}.In(p.Rect)) {
+		return color.NYCbCrA{}
+	}
+	yi := p.YOffset(x, y)
+	ci := p.COffset(x, y)
+	ai := p.AOffset(x, y)
+	return color.NYCbCrA{
+		color.YCbCr{
+			Y:  p.Y[yi],
+			Cb: p.Cb[ci],
+			Cr: p.Cr[ci],
+		},
+		p.A[ai],
+	}
+}
+
+// AOffset returns the index of the first element of A that corresponds to the
+// pixel at (x, y).
+func (p *NYCbCrA) AOffset(x, y int) int {
+	return (y-p.Rect.Min.Y)*p.AStride + (x - p.Rect.Min.X)
+}
+
+// SubImage returns an image representing the portion of the image p visible
+// through r. The returned value shares pixels with the original image.
+func (p *NYCbCrA) SubImage(r Rectangle) Image {
+	r = r.Intersect(p.Rect)
+	// If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
+	// either r1 or r2 if the intersection is empty. Without explicitly checking for
+	// this, the Pix[i:] expression below can panic.
+	if r.Empty() {
+		return &NYCbCrA{
+			YCbCr: YCbCr{
+				SubsampleRatio: p.SubsampleRatio,
+			},
+		}
+	}
+	yi := p.YOffset(r.Min.X, r.Min.Y)
+	ci := p.COffset(r.Min.X, r.Min.Y)
+	ai := p.AOffset(r.Min.X, r.Min.Y)
+	return &NYCbCrA{
+		YCbCr: YCbCr{
+			Y:              p.Y[yi:],
+			Cb:             p.Cb[ci:],
+			Cr:             p.Cr[ci:],
+			SubsampleRatio: p.SubsampleRatio,
+			YStride:        p.YStride,
+			CStride:        p.CStride,
+			Rect:           r,
+		},
+		A:       p.A[ai:],
+		AStride: p.AStride,
+	}
+}
+
+// Opaque scans the entire image and reports whether it is fully opaque.
+func (p *NYCbCrA) Opaque() bool {
+	if p.Rect.Empty() {
+		return true
+	}
+	i0, i1 := 0, p.Rect.Dx()
+	for y := p.Rect.Min.Y; y < p.Rect.Max.Y; y++ {
+		for _, a := range p.A[i0:i1] {
+			if a != 0xff {
+				return false
+			}
+		}
+		i0 += p.AStride
+		i1 += p.AStride
+	}
+	return true
+}
+
+// NewNYCbCrA returns a new NYCbCrA image with the given bounds and subsample
+// ratio.
+func NewNYCbCrA(r Rectangle, subsampleRatio YCbCrSubsampleRatio) *NYCbCrA {
+	w, h, cw, ch := yCbCrSize(r, subsampleRatio)
+	i0 := 1*w*h + 0*cw*ch
+	i1 := 1*w*h + 1*cw*ch
+	i2 := 1*w*h + 2*cw*ch
+	i3 := 2*w*h + 2*cw*ch
+	b := make([]byte, i3)
+	return &NYCbCrA{
+		YCbCr: YCbCr{
+			Y:              b[:i0:i0],
+			Cb:             b[i0:i1:i1],
+			Cr:             b[i1:i2:i2],
+			SubsampleRatio: subsampleRatio,
+			YStride:        w,
+			CStride:        cw,
+			Rect:           r,
+		},
+		A:       b[i2:],
+		AStride: w,
+	}
+}
diff --git a/src/internal/format/format.go b/src/internal/format/format.go
deleted file mode 100644
index a8270ba..0000000
--- a/src/internal/format/format.go
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright 2015 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 format
-
-import (
-	"bytes"
-	"go/ast"
-	"go/parser"
-	"go/printer"
-	"go/token"
-	"strings"
-)
-
-const parserMode = parser.ParseComments
-
-// Parse parses src, which was read from the named file,
-// as a Go source file, declaration, or statement list.
-func Parse(fset *token.FileSet, filename string, src []byte, fragmentOk bool) (
-	file *ast.File,
-	sourceAdj func(src []byte, indent int) []byte,
-	indentAdj int,
-	err error,
-) {
-	// Try as whole source file.
-	file, err = parser.ParseFile(fset, filename, src, parserMode)
-	// If there's no error, return.  If the error is that the source file didn't begin with a
-	// package line and source fragments are ok, fall through to
-	// try as a source fragment.  Stop and return on any other error.
-	if err == nil || !fragmentOk || !strings.Contains(err.Error(), "expected 'package'") {
-		return
-	}
-
-	// If this is a declaration list, make it a source file
-	// by inserting a package clause.
-	// Insert using a ;, not a newline, so that the line numbers
-	// in psrc match the ones in src.
-	psrc := append([]byte("package p;"), src...)
-	file, err = parser.ParseFile(fset, filename, psrc, parserMode)
-	if err == nil {
-		sourceAdj = func(src []byte, indent int) []byte {
-			// Remove the package clause.
-			// Gofmt has turned the ; into a \n.
-			src = src[indent+len("package p\n"):]
-			return bytes.TrimSpace(src)
-		}
-		return
-	}
-	// If the error is that the source file didn't begin with a
-	// declaration, fall through to try as a statement list.
-	// Stop and return on any other error.
-	if !strings.Contains(err.Error(), "expected declaration") {
-		return
-	}
-
-	// If this is a statement list, make it a source file
-	// by inserting a package clause and turning the list
-	// into a function body.  This handles expressions too.
-	// Insert using a ;, not a newline, so that the line numbers
-	// in fsrc match the ones in src. Add an extra '\n' before the '}'
-	// to make sure comments are flushed before the '}'.
-	fsrc := append(append([]byte("package p; func _() {"), src...), '\n', '\n', '}')
-	file, err = parser.ParseFile(fset, filename, fsrc, parserMode)
-	if err == nil {
-		sourceAdj = func(src []byte, indent int) []byte {
-			// Cap adjusted indent to zero.
-			if indent < 0 {
-				indent = 0
-			}
-			// Remove the wrapping.
-			// Gofmt has turned the ; into a \n\n.
-			// There will be two non-blank lines with indent, hence 2*indent.
-			src = src[2*indent+len("package p\n\nfunc _() {"):]
-			// Remove only the "}\n" suffix: remaining whitespaces will be trimmed anyway
-			src = src[:len(src)-len("}\n")]
-			return bytes.TrimSpace(src)
-		}
-		// Gofmt has also indented the function body one level.
-		// Adjust that with indentAdj.
-		indentAdj = -1
-	}
-
-	// Succeeded, or out of options.
-	return
-}
-
-// Format formats the given package file originally obtained from src
-// and adjusts the result based on the original source via sourceAdj
-// and indentAdj.
-func Format(
-	fset *token.FileSet,
-	file *ast.File,
-	sourceAdj func(src []byte, indent int) []byte,
-	indentAdj int,
-	src []byte,
-	cfg printer.Config,
-) ([]byte, error) {
-	if sourceAdj == nil {
-		// Complete source file.
-		var buf bytes.Buffer
-		err := cfg.Fprint(&buf, fset, file)
-		if err != nil {
-			return nil, err
-		}
-		return buf.Bytes(), nil
-	}
-
-	// Partial source file.
-	// Determine and prepend leading space.
-	i, j := 0, 0
-	for j < len(src) && IsSpace(src[j]) {
-		if src[j] == '\n' {
-			i = j + 1 // byte offset of last line in leading space
-		}
-		j++
-	}
-	var res []byte
-	res = append(res, src[:i]...)
-
-	// Determine and prepend indentation of first code line.
-	// Spaces are ignored unless there are no tabs,
-	// in which case spaces count as one tab.
-	indent := 0
-	hasSpace := false
-	for _, b := range src[i:j] {
-		switch b {
-		case ' ':
-			hasSpace = true
-		case '\t':
-			indent++
-		}
-	}
-	if indent == 0 && hasSpace {
-		indent = 1
-	}
-	for i := 0; i < indent; i++ {
-		res = append(res, '\t')
-	}
-
-	// Format the source.
-	// Write it without any leading and trailing space.
-	cfg.Indent = indent + indentAdj
-	var buf bytes.Buffer
-	err := cfg.Fprint(&buf, fset, file)
-	if err != nil {
-		return nil, err
-	}
-	res = append(res, sourceAdj(buf.Bytes(), cfg.Indent)...)
-
-	// Determine and append trailing space.
-	i = len(src)
-	for i > 0 && IsSpace(src[i-1]) {
-		i--
-	}
-	return append(res, src[i:]...), nil
-}
-
-// IsSpace reports whether the byte is a space character.
-// IsSpace defines a space as being among the following bytes: ' ', '\t', '\n' and '\r'.
-func IsSpace(b byte) bool {
-	return b == ' ' || b == '\t' || b == '\n' || b == '\r'
-}
diff --git a/src/internal/golang.org/x/net/http2/hpack/encode.go b/src/internal/golang.org/x/net/http2/hpack/encode.go
new file mode 100644
index 0000000..80d621c
--- /dev/null
+++ b/src/internal/golang.org/x/net/http2/hpack/encode.go
@@ -0,0 +1,251 @@
+// 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 hpack
+
+import (
+	"io"
+)
+
+const (
+	uint32Max              = ^uint32(0)
+	initialHeaderTableSize = 4096
+)
+
+type Encoder struct {
+	dynTab dynamicTable
+	// minSize is the minimum table size set by
+	// SetMaxDynamicTableSize after the previous Header Table Size
+	// Update.
+	minSize uint32
+	// maxSizeLimit is the maximum table size this encoder
+	// supports. This will protect the encoder from too large
+	// size.
+	maxSizeLimit uint32
+	// tableSizeUpdate indicates whether "Header Table Size
+	// Update" is required.
+	tableSizeUpdate bool
+	w               io.Writer
+	buf             []byte
+}
+
+// NewEncoder returns a new Encoder which performs HPACK encoding. An
+// encoded data is written to w.
+func NewEncoder(w io.Writer) *Encoder {
+	e := &Encoder{
+		minSize:         uint32Max,
+		maxSizeLimit:    initialHeaderTableSize,
+		tableSizeUpdate: false,
+		w:               w,
+	}
+	e.dynTab.setMaxSize(initialHeaderTableSize)
+	return e
+}
+
+// WriteField encodes f into a single Write to e's underlying Writer.
+// This function may also produce bytes for "Header Table Size Update"
+// if necessary.  If produced, it is done before encoding f.
+func (e *Encoder) WriteField(f HeaderField) error {
+	e.buf = e.buf[:0]
+
+	if e.tableSizeUpdate {
+		e.tableSizeUpdate = false
+		if e.minSize < e.dynTab.maxSize {
+			e.buf = appendTableSize(e.buf, e.minSize)
+		}
+		e.minSize = uint32Max
+		e.buf = appendTableSize(e.buf, e.dynTab.maxSize)
+	}
+
+	idx, nameValueMatch := e.searchTable(f)
+	if nameValueMatch {
+		e.buf = appendIndexed(e.buf, idx)
+	} else {
+		indexing := e.shouldIndex(f)
+		if indexing {
+			e.dynTab.add(f)
+		}
+
+		if idx == 0 {
+			e.buf = appendNewName(e.buf, f, indexing)
+		} else {
+			e.buf = appendIndexedName(e.buf, f, idx, indexing)
+		}
+	}
+	n, err := e.w.Write(e.buf)
+	if err == nil && n != len(e.buf) {
+		err = io.ErrShortWrite
+	}
+	return err
+}
+
+// searchTable searches f in both stable and dynamic header tables.
+// The static header table is searched first. Only when there is no
+// exact match for both name and value, the dynamic header table is
+// then searched. If there is no match, i is 0. If both name and value
+// match, i is the matched index and nameValueMatch becomes true. If
+// only name matches, i points to that index and nameValueMatch
+// becomes false.
+func (e *Encoder) searchTable(f HeaderField) (i uint64, nameValueMatch bool) {
+	for idx, hf := range staticTable {
+		if !constantTimeStringCompare(hf.Name, f.Name) {
+			continue
+		}
+		if i == 0 {
+			i = uint64(idx + 1)
+		}
+		if f.Sensitive {
+			continue
+		}
+		if !constantTimeStringCompare(hf.Value, f.Value) {
+			continue
+		}
+		i = uint64(idx + 1)
+		nameValueMatch = true
+		return
+	}
+
+	j, nameValueMatch := e.dynTab.search(f)
+	if nameValueMatch || (i == 0 && j != 0) {
+		i = j + uint64(len(staticTable))
+	}
+	return
+}
+
+// SetMaxDynamicTableSize changes the dynamic header table size to v.
+// The actual size is bounded by the value passed to
+// SetMaxDynamicTableSizeLimit.
+func (e *Encoder) SetMaxDynamicTableSize(v uint32) {
+	if v > e.maxSizeLimit {
+		v = e.maxSizeLimit
+	}
+	if v < e.minSize {
+		e.minSize = v
+	}
+	e.tableSizeUpdate = true
+	e.dynTab.setMaxSize(v)
+}
+
+// SetMaxDynamicTableSizeLimit changes the maximum value that can be
+// specified in SetMaxDynamicTableSize to v. By default, it is set to
+// 4096, which is the same size of the default dynamic header table
+// size described in HPACK specification. If the current maximum
+// dynamic header table size is strictly greater than v, "Header Table
+// Size Update" will be done in the next WriteField call and the
+// maximum dynamic header table size is truncated to v.
+func (e *Encoder) SetMaxDynamicTableSizeLimit(v uint32) {
+	e.maxSizeLimit = v
+	if e.dynTab.maxSize > v {
+		e.tableSizeUpdate = true
+		e.dynTab.setMaxSize(v)
+	}
+}
+
+// shouldIndex reports whether f should be indexed.
+func (e *Encoder) shouldIndex(f HeaderField) bool {
+	return !f.Sensitive && f.size() <= e.dynTab.maxSize
+}
+
+// appendIndexed appends index i, as encoded in "Indexed Header Field"
+// representation, to dst and returns the extended buffer.
+func appendIndexed(dst []byte, i uint64) []byte {
+	first := len(dst)
+	dst = appendVarInt(dst, 7, i)
+	dst[first] |= 0x80
+	return dst
+}
+
+// appendNewName appends f, as encoded in one of "Literal Header field
+// - New Name" representation variants, to dst and returns the
+// extended buffer.
+//
+// If f.Sensitive is true, "Never Indexed" representation is used. If
+// f.Sensitive is false and indexing is true, "Inremental Indexing"
+// representation is used.
+func appendNewName(dst []byte, f HeaderField, indexing bool) []byte {
+	dst = append(dst, encodeTypeByte(indexing, f.Sensitive))
+	dst = appendHpackString(dst, f.Name)
+	return appendHpackString(dst, f.Value)
+}
+
+// appendIndexedName appends f and index i referring indexed name
+// entry, as encoded in one of "Literal Header field - Indexed Name"
+// representation variants, to dst and returns the extended buffer.
+//
+// If f.Sensitive is true, "Never Indexed" representation is used. If
+// f.Sensitive is false and indexing is true, "Incremental Indexing"
+// representation is used.
+func appendIndexedName(dst []byte, f HeaderField, i uint64, indexing bool) []byte {
+	first := len(dst)
+	var n byte
+	if indexing {
+		n = 6
+	} else {
+		n = 4
+	}
+	dst = appendVarInt(dst, n, i)
+	dst[first] |= encodeTypeByte(indexing, f.Sensitive)
+	return appendHpackString(dst, f.Value)
+}
+
+// appendTableSize appends v, as encoded in "Header Table Size Update"
+// representation, to dst and returns the extended buffer.
+func appendTableSize(dst []byte, v uint32) []byte {
+	first := len(dst)
+	dst = appendVarInt(dst, 5, uint64(v))
+	dst[first] |= 0x20
+	return dst
+}
+
+// appendVarInt appends i, as encoded in variable integer form using n
+// bit prefix, to dst and returns the extended buffer.
+//
+// See
+// http://http2.github.io/http2-spec/compression.html#integer.representation
+func appendVarInt(dst []byte, n byte, i uint64) []byte {
+	k := uint64((1 << n) - 1)
+	if i < k {
+		return append(dst, byte(i))
+	}
+	dst = append(dst, byte(k))
+	i -= k
+	for ; i >= 128; i >>= 7 {
+		dst = append(dst, byte(0x80|(i&0x7f)))
+	}
+	return append(dst, byte(i))
+}
+
+// appendHpackString appends s, as encoded in "String Literal"
+// representation, to dst and returns the the extended buffer.
+//
+// s will be encoded in Huffman codes only when it produces strictly
+// shorter byte string.
+func appendHpackString(dst []byte, s string) []byte {
+	huffmanLength := HuffmanEncodeLength(s)
+	if huffmanLength < uint64(len(s)) {
+		first := len(dst)
+		dst = appendVarInt(dst, 7, huffmanLength)
+		dst = AppendHuffmanString(dst, s)
+		dst[first] |= 0x80
+	} else {
+		dst = appendVarInt(dst, 7, uint64(len(s)))
+		dst = append(dst, s...)
+	}
+	return dst
+}
+
+// encodeTypeByte returns type byte. If sensitive is true, type byte
+// for "Never Indexed" representation is returned. If sensitive is
+// false and indexing is true, type byte for "Incremental Indexing"
+// representation is returned. Otherwise, type byte for "Without
+// Indexing" is returned.
+func encodeTypeByte(indexing, sensitive bool) byte {
+	if sensitive {
+		return 0x10
+	}
+	if indexing {
+		return 0x40
+	}
+	return 0
+}
diff --git a/src/internal/golang.org/x/net/http2/hpack/encode_test.go b/src/internal/golang.org/x/net/http2/hpack/encode_test.go
new file mode 100644
index 0000000..92286f3
--- /dev/null
+++ b/src/internal/golang.org/x/net/http2/hpack/encode_test.go
@@ -0,0 +1,330 @@
+// 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 hpack
+
+import (
+	"bytes"
+	"encoding/hex"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+func TestEncoderTableSizeUpdate(t *testing.T) {
+	tests := []struct {
+		size1, size2 uint32
+		wantHex      string
+	}{
+		// Should emit 2 table size updates (2048 and 4096)
+		{2048, 4096, "3fe10f 3fe11f 82"},
+
+		// Should emit 1 table size update (2048)
+		{16384, 2048, "3fe10f 82"},
+	}
+	for _, tt := range tests {
+		var buf bytes.Buffer
+		e := NewEncoder(&buf)
+		e.SetMaxDynamicTableSize(tt.size1)
+		e.SetMaxDynamicTableSize(tt.size2)
+		if err := e.WriteField(pair(":method", "GET")); err != nil {
+			t.Fatal(err)
+		}
+		want := removeSpace(tt.wantHex)
+		if got := hex.EncodeToString(buf.Bytes()); got != want {
+			t.Errorf("e.SetDynamicTableSize %v, %v = %q; want %q", tt.size1, tt.size2, got, want)
+		}
+	}
+}
+
+func TestEncoderWriteField(t *testing.T) {
+	var buf bytes.Buffer
+	e := NewEncoder(&buf)
+	var got []HeaderField
+	d := NewDecoder(4<<10, func(f HeaderField) {
+		got = append(got, f)
+	})
+
+	tests := []struct {
+		hdrs []HeaderField
+	}{
+		{[]HeaderField{
+			pair(":method", "GET"),
+			pair(":scheme", "http"),
+			pair(":path", "/"),
+			pair(":authority", "www.example.com"),
+		}},
+		{[]HeaderField{
+			pair(":method", "GET"),
+			pair(":scheme", "http"),
+			pair(":path", "/"),
+			pair(":authority", "www.example.com"),
+			pair("cache-control", "no-cache"),
+		}},
+		{[]HeaderField{
+			pair(":method", "GET"),
+			pair(":scheme", "https"),
+			pair(":path", "/index.html"),
+			pair(":authority", "www.example.com"),
+			pair("custom-key", "custom-value"),
+		}},
+	}
+	for i, tt := range tests {
+		buf.Reset()
+		got = got[:0]
+		for _, hf := range tt.hdrs {
+			if err := e.WriteField(hf); err != nil {
+				t.Fatal(err)
+			}
+		}
+		_, err := d.Write(buf.Bytes())
+		if err != nil {
+			t.Errorf("%d. Decoder Write = %v", i, err)
+		}
+		if !reflect.DeepEqual(got, tt.hdrs) {
+			t.Errorf("%d. Decoded %+v; want %+v", i, got, tt.hdrs)
+		}
+	}
+}
+
+func TestEncoderSearchTable(t *testing.T) {
+	e := NewEncoder(nil)
+
+	e.dynTab.add(pair("foo", "bar"))
+	e.dynTab.add(pair("blake", "miz"))
+	e.dynTab.add(pair(":method", "GET"))
+
+	tests := []struct {
+		hf        HeaderField
+		wantI     uint64
+		wantMatch bool
+	}{
+		// Name and Value match
+		{pair("foo", "bar"), uint64(len(staticTable) + 3), true},
+		{pair("blake", "miz"), uint64(len(staticTable) + 2), true},
+		{pair(":method", "GET"), 2, true},
+
+		// Only name match because Sensitive == true
+		{HeaderField{":method", "GET", true}, 2, false},
+
+		// Only Name matches
+		{pair("foo", "..."), uint64(len(staticTable) + 3), false},
+		{pair("blake", "..."), uint64(len(staticTable) + 2), false},
+		{pair(":method", "..."), 2, false},
+
+		// None match
+		{pair("foo-", "bar"), 0, false},
+	}
+	for _, tt := range tests {
+		if gotI, gotMatch := e.searchTable(tt.hf); gotI != tt.wantI || gotMatch != tt.wantMatch {
+			t.Errorf("d.search(%+v) = %v, %v; want %v, %v", tt.hf, gotI, gotMatch, tt.wantI, tt.wantMatch)
+		}
+	}
+}
+
+func TestAppendVarInt(t *testing.T) {
+	tests := []struct {
+		n    byte
+		i    uint64
+		want []byte
+	}{
+		// Fits in a byte:
+		{1, 0, []byte{0}},
+		{2, 2, []byte{2}},
+		{3, 6, []byte{6}},
+		{4, 14, []byte{14}},
+		{5, 30, []byte{30}},
+		{6, 62, []byte{62}},
+		{7, 126, []byte{126}},
+		{8, 254, []byte{254}},
+
+		// Multiple bytes:
+		{5, 1337, []byte{31, 154, 10}},
+	}
+	for _, tt := range tests {
+		got := appendVarInt(nil, tt.n, tt.i)
+		if !bytes.Equal(got, tt.want) {
+			t.Errorf("appendVarInt(nil, %v, %v) = %v; want %v", tt.n, tt.i, got, tt.want)
+		}
+	}
+}
+
+func TestAppendHpackString(t *testing.T) {
+	tests := []struct {
+		s, wantHex string
+	}{
+		// Huffman encoded
+		{"www.example.com", "8c f1e3 c2e5 f23a 6ba0 ab90 f4ff"},
+
+		// Not Huffman encoded
+		{"a", "01 61"},
+
+		// zero length
+		{"", "00"},
+	}
+	for _, tt := range tests {
+		want := removeSpace(tt.wantHex)
+		buf := appendHpackString(nil, tt.s)
+		if got := hex.EncodeToString(buf); want != got {
+			t.Errorf("appendHpackString(nil, %q) = %q; want %q", tt.s, got, want)
+		}
+	}
+}
+
+func TestAppendIndexed(t *testing.T) {
+	tests := []struct {
+		i       uint64
+		wantHex string
+	}{
+		// 1 byte
+		{1, "81"},
+		{126, "fe"},
+
+		// 2 bytes
+		{127, "ff00"},
+		{128, "ff01"},
+	}
+	for _, tt := range tests {
+		want := removeSpace(tt.wantHex)
+		buf := appendIndexed(nil, tt.i)
+		if got := hex.EncodeToString(buf); want != got {
+			t.Errorf("appendIndex(nil, %v) = %q; want %q", tt.i, got, want)
+		}
+	}
+}
+
+func TestAppendNewName(t *testing.T) {
+	tests := []struct {
+		f        HeaderField
+		indexing bool
+		wantHex  string
+	}{
+		// Incremental indexing
+		{HeaderField{"custom-key", "custom-value", false}, true, "40 88 25a8 49e9 5ba9 7d7f 89 25a8 49e9 5bb8 e8b4 bf"},
+
+		// Without indexing
+		{HeaderField{"custom-key", "custom-value", false}, false, "00 88 25a8 49e9 5ba9 7d7f 89 25a8 49e9 5bb8 e8b4 bf"},
+
+		// Never indexed
+		{HeaderField{"custom-key", "custom-value", true}, true, "10 88 25a8 49e9 5ba9 7d7f 89 25a8 49e9 5bb8 e8b4 bf"},
+		{HeaderField{"custom-key", "custom-value", true}, false, "10 88 25a8 49e9 5ba9 7d7f 89 25a8 49e9 5bb8 e8b4 bf"},
+	}
+	for _, tt := range tests {
+		want := removeSpace(tt.wantHex)
+		buf := appendNewName(nil, tt.f, tt.indexing)
+		if got := hex.EncodeToString(buf); want != got {
+			t.Errorf("appendNewName(nil, %+v, %v) = %q; want %q", tt.f, tt.indexing, got, want)
+		}
+	}
+}
+
+func TestAppendIndexedName(t *testing.T) {
+	tests := []struct {
+		f        HeaderField
+		i        uint64
+		indexing bool
+		wantHex  string
+	}{
+		// Incremental indexing
+		{HeaderField{":status", "302", false}, 8, true, "48 82 6402"},
+
+		// Without indexing
+		{HeaderField{":status", "302", false}, 8, false, "08 82 6402"},
+
+		// Never indexed
+		{HeaderField{":status", "302", true}, 8, true, "18 82 6402"},
+		{HeaderField{":status", "302", true}, 8, false, "18 82 6402"},
+	}
+	for _, tt := range tests {
+		want := removeSpace(tt.wantHex)
+		buf := appendIndexedName(nil, tt.f, tt.i, tt.indexing)
+		if got := hex.EncodeToString(buf); want != got {
+			t.Errorf("appendIndexedName(nil, %+v, %v) = %q; want %q", tt.f, tt.indexing, got, want)
+		}
+	}
+}
+
+func TestAppendTableSize(t *testing.T) {
+	tests := []struct {
+		i       uint32
+		wantHex string
+	}{
+		// Fits into 1 byte
+		{30, "3e"},
+
+		// Extra byte
+		{31, "3f00"},
+		{32, "3f01"},
+	}
+	for _, tt := range tests {
+		want := removeSpace(tt.wantHex)
+		buf := appendTableSize(nil, tt.i)
+		if got := hex.EncodeToString(buf); want != got {
+			t.Errorf("appendTableSize(nil, %v) = %q; want %q", tt.i, got, want)
+		}
+	}
+}
+
+func TestEncoderSetMaxDynamicTableSize(t *testing.T) {
+	var buf bytes.Buffer
+	e := NewEncoder(&buf)
+	tests := []struct {
+		v           uint32
+		wantUpdate  bool
+		wantMinSize uint32
+		wantMaxSize uint32
+	}{
+		// Set new table size to 2048
+		{2048, true, 2048, 2048},
+
+		// Set new table size to 16384, but still limited to
+		// 4096
+		{16384, true, 2048, 4096},
+	}
+	for _, tt := range tests {
+		e.SetMaxDynamicTableSize(tt.v)
+		if got := e.tableSizeUpdate; tt.wantUpdate != got {
+			t.Errorf("e.tableSizeUpdate = %v; want %v", got, tt.wantUpdate)
+		}
+		if got := e.minSize; tt.wantMinSize != got {
+			t.Errorf("e.minSize = %v; want %v", got, tt.wantMinSize)
+		}
+		if got := e.dynTab.maxSize; tt.wantMaxSize != got {
+			t.Errorf("e.maxSize = %v; want %v", got, tt.wantMaxSize)
+		}
+	}
+}
+
+func TestEncoderSetMaxDynamicTableSizeLimit(t *testing.T) {
+	e := NewEncoder(nil)
+	// 4095 < initialHeaderTableSize means maxSize is truncated to
+	// 4095.
+	e.SetMaxDynamicTableSizeLimit(4095)
+	if got, want := e.dynTab.maxSize, uint32(4095); got != want {
+		t.Errorf("e.dynTab.maxSize = %v; want %v", got, want)
+	}
+	if got, want := e.maxSizeLimit, uint32(4095); got != want {
+		t.Errorf("e.maxSizeLimit = %v; want %v", got, want)
+	}
+	if got, want := e.tableSizeUpdate, true; got != want {
+		t.Errorf("e.tableSizeUpdate = %v; want %v", got, want)
+	}
+	// maxSize will be truncated to maxSizeLimit
+	e.SetMaxDynamicTableSize(16384)
+	if got, want := e.dynTab.maxSize, uint32(4095); got != want {
+		t.Errorf("e.dynTab.maxSize = %v; want %v", got, want)
+	}
+	// 8192 > current maxSizeLimit, so maxSize does not change.
+	e.SetMaxDynamicTableSizeLimit(8192)
+	if got, want := e.dynTab.maxSize, uint32(4095); got != want {
+		t.Errorf("e.dynTab.maxSize = %v; want %v", got, want)
+	}
+	if got, want := e.maxSizeLimit, uint32(8192); got != want {
+		t.Errorf("e.maxSizeLimit = %v; want %v", got, want)
+	}
+}
+
+func removeSpace(s string) string {
+	return strings.Replace(s, " ", "", -1)
+}
diff --git a/src/internal/golang.org/x/net/http2/hpack/hpack.go b/src/internal/golang.org/x/net/http2/hpack/hpack.go
new file mode 100644
index 0000000..2ea4949
--- /dev/null
+++ b/src/internal/golang.org/x/net/http2/hpack/hpack.go
@@ -0,0 +1,533 @@
+// 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 hpack implements HPACK, a compression format for
+// efficiently representing HTTP header fields in the context of HTTP/2.
+//
+// See http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-09
+package hpack
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+)
+
+// A DecodingError is something the spec defines as a decoding error.
+type DecodingError struct {
+	Err error
+}
+
+func (de DecodingError) Error() string {
+	return fmt.Sprintf("decoding error: %v", de.Err)
+}
+
+// An InvalidIndexError is returned when an encoder references a table
+// entry before the static table or after the end of the dynamic table.
+type InvalidIndexError int
+
+func (e InvalidIndexError) Error() string {
+	return fmt.Sprintf("invalid indexed representation index %d", int(e))
+}
+
+// A HeaderField is a name-value pair. Both the name and value are
+// treated as opaque sequences of octets.
+type HeaderField struct {
+	Name, Value string
+
+	// Sensitive means that this header field should never be
+	// indexed.
+	Sensitive bool
+}
+
+func (hf HeaderField) String() string {
+	var suffix string
+	if hf.Sensitive {
+		suffix = " (sensitive)"
+	}
+	return fmt.Sprintf("header field %q = %q%s", hf.Name, hf.Value, suffix)
+}
+
+func (hf *HeaderField) size() uint32 {
+	// http://http2.github.io/http2-spec/compression.html#rfc.section.4.1
+	// "The size of the dynamic table is the sum of the size of
+	// its entries.  The size of an entry is the sum of its name's
+	// length in octets (as defined in Section 5.2), its value's
+	// length in octets (see Section 5.2), plus 32.  The size of
+	// an entry is calculated using the length of the name and
+	// value without any Huffman encoding applied."
+
+	// This can overflow if somebody makes a large HeaderField
+	// Name and/or Value by hand, but we don't care, because that
+	// won't happen on the wire because the encoding doesn't allow
+	// it.
+	return uint32(len(hf.Name) + len(hf.Value) + 32)
+}
+
+// A Decoder is the decoding context for incremental processing of
+// header blocks.
+type Decoder struct {
+	dynTab dynamicTable
+	emit   func(f HeaderField)
+
+	emitEnabled bool // whether calls to emit are enabled
+	maxStrLen   int  // 0 means unlimited
+
+	// buf is the unparsed buffer. It's only written to
+	// saveBuf if it was truncated in the middle of a header
+	// block. Because it's usually not owned, we can only
+	// process it under Write.
+	buf []byte // not owned; only valid during Write
+
+	// saveBuf is previous data passed to Write which we weren't able
+	// to fully parse before. Unlike buf, we own this data.
+	saveBuf bytes.Buffer
+}
+
+// NewDecoder returns a new decoder with the provided maximum dynamic
+// table size. The emitFunc will be called for each valid field
+// parsed, in the same goroutine as calls to Write, before Write returns.
+func NewDecoder(maxDynamicTableSize uint32, emitFunc func(f HeaderField)) *Decoder {
+	d := &Decoder{
+		emit:        emitFunc,
+		emitEnabled: true,
+	}
+	d.dynTab.allowedMaxSize = maxDynamicTableSize
+	d.dynTab.setMaxSize(maxDynamicTableSize)
+	return d
+}
+
+// ErrStringLength is returned by Decoder.Write when the max string length
+// (as configured by Decoder.SetMaxStringLength) would be violated.
+var ErrStringLength = errors.New("hpack: string too long")
+
+// SetMaxStringLength sets the maximum size of a HeaderField name or
+// value string. If a string exceeds this length (even after any
+// decompression), Write will return ErrStringLength.
+// A value of 0 means unlimited and is the default from NewDecoder.
+func (d *Decoder) SetMaxStringLength(n int) {
+	d.maxStrLen = n
+}
+
+// SetEmitFunc changes the callback used when new header fields
+// are decoded.
+// It must be non-nil. It does not affect EmitEnabled.
+func (d *Decoder) SetEmitFunc(emitFunc func(f HeaderField)) {
+	d.emit = emitFunc
+}
+
+// SetEmitEnabled controls whether the emitFunc provided to NewDecoder
+// should be called. The default is true.
+//
+// This facility exists to let servers enforce MAX_HEADER_LIST_SIZE
+// while still decoding and keeping in-sync with decoder state, but
+// without doing unnecessary decompression or generating unnecessary
+// garbage for header fields past the limit.
+func (d *Decoder) SetEmitEnabled(v bool) { d.emitEnabled = v }
+
+// EmitEnabled reports whether calls to the emitFunc provided to NewDecoder
+// are currently enabled. The default is true.
+func (d *Decoder) EmitEnabled() bool { return d.emitEnabled }
+
+// TODO: add method *Decoder.Reset(maxSize, emitFunc) to let callers re-use Decoders and their
+// underlying buffers for garbage reasons.
+
+func (d *Decoder) SetMaxDynamicTableSize(v uint32) {
+	d.dynTab.setMaxSize(v)
+}
+
+// SetAllowedMaxDynamicTableSize sets the upper bound that the encoded
+// stream (via dynamic table size updates) may set the maximum size
+// to.
+func (d *Decoder) SetAllowedMaxDynamicTableSize(v uint32) {
+	d.dynTab.allowedMaxSize = v
+}
+
+type dynamicTable struct {
+	// ents is the FIFO described at
+	// http://http2.github.io/http2-spec/compression.html#rfc.section.2.3.2
+	// The newest (low index) is append at the end, and items are
+	// evicted from the front.
+	ents           []HeaderField
+	size           uint32
+	maxSize        uint32 // current maxSize
+	allowedMaxSize uint32 // maxSize may go up to this, inclusive
+}
+
+func (dt *dynamicTable) setMaxSize(v uint32) {
+	dt.maxSize = v
+	dt.evict()
+}
+
+// TODO: change dynamicTable to be a struct with a slice and a size int field,
+// per http://http2.github.io/http2-spec/compression.html#rfc.section.4.1:
+//
+//
+// Then make add increment the size. maybe the max size should move from Decoder to
+// dynamicTable and add should return an ok bool if there was enough space.
+//
+// Later we'll need a remove operation on dynamicTable.
+
+func (dt *dynamicTable) add(f HeaderField) {
+	dt.ents = append(dt.ents, f)
+	dt.size += f.size()
+	dt.evict()
+}
+
+// If we're too big, evict old stuff (front of the slice)
+func (dt *dynamicTable) evict() {
+	base := dt.ents // keep base pointer of slice
+	for dt.size > dt.maxSize {
+		dt.size -= dt.ents[0].size()
+		dt.ents = dt.ents[1:]
+	}
+
+	// Shift slice contents down if we evicted things.
+	if len(dt.ents) != len(base) {
+		copy(base, dt.ents)
+		dt.ents = base[:len(dt.ents)]
+	}
+}
+
+// constantTimeStringCompare compares string a and b in a constant
+// time manner.
+func constantTimeStringCompare(a, b string) bool {
+	if len(a) != len(b) {
+		return false
+	}
+
+	c := byte(0)
+
+	for i := 0; i < len(a); i++ {
+		c |= a[i] ^ b[i]
+	}
+
+	return c == 0
+}
+
+// Search searches f in the table. The return value i is 0 if there is
+// no name match. If there is name match or name/value match, i is the
+// index of that entry (1-based). If both name and value match,
+// nameValueMatch becomes true.
+func (dt *dynamicTable) search(f HeaderField) (i uint64, nameValueMatch bool) {
+	l := len(dt.ents)
+	for j := l - 1; j >= 0; j-- {
+		ent := dt.ents[j]
+		if !constantTimeStringCompare(ent.Name, f.Name) {
+			continue
+		}
+		if i == 0 {
+			i = uint64(l - j)
+		}
+		if f.Sensitive {
+			continue
+		}
+		if !constantTimeStringCompare(ent.Value, f.Value) {
+			continue
+		}
+		i = uint64(l - j)
+		nameValueMatch = true
+		return
+	}
+	return
+}
+
+func (d *Decoder) maxTableIndex() int {
+	return len(d.dynTab.ents) + len(staticTable)
+}
+
+func (d *Decoder) at(i uint64) (hf HeaderField, ok bool) {
+	if i < 1 {
+		return
+	}
+	if i > uint64(d.maxTableIndex()) {
+		return
+	}
+	if i <= uint64(len(staticTable)) {
+		return staticTable[i-1], true
+	}
+	dents := d.dynTab.ents
+	return dents[len(dents)-(int(i)-len(staticTable))], true
+}
+
+// Decode decodes an entire block.
+//
+// TODO: remove this method and make it incremental later? This is
+// easier for debugging now.
+func (d *Decoder) DecodeFull(p []byte) ([]HeaderField, error) {
+	var hf []HeaderField
+	saveFunc := d.emit
+	defer func() { d.emit = saveFunc }()
+	d.emit = func(f HeaderField) { hf = append(hf, f) }
+	if _, err := d.Write(p); err != nil {
+		return nil, err
+	}
+	if err := d.Close(); err != nil {
+		return nil, err
+	}
+	return hf, nil
+}
+
+func (d *Decoder) Close() error {
+	if d.saveBuf.Len() > 0 {
+		d.saveBuf.Reset()
+		return DecodingError{errors.New("truncated headers")}
+	}
+	return nil
+}
+
+func (d *Decoder) Write(p []byte) (n int, err error) {
+	if len(p) == 0 {
+		// Prevent state machine CPU attacks (making us redo
+		// work up to the point of finding out we don't have
+		// enough data)
+		return
+	}
+	// Only copy the data if we have to. Optimistically assume
+	// that p will contain a complete header block.
+	if d.saveBuf.Len() == 0 {
+		d.buf = p
+	} else {
+		d.saveBuf.Write(p)
+		d.buf = d.saveBuf.Bytes()
+		d.saveBuf.Reset()
+	}
+
+	for len(d.buf) > 0 {
+		err = d.parseHeaderFieldRepr()
+		if err == errNeedMore {
+			// Extra paranoia, making sure saveBuf won't
+			// get too large.  All the varint and string
+			// reading code earlier should already catch
+			// overlong things and return ErrStringLength,
+			// but keep this as a last resort.
+			const varIntOverhead = 8 // conservative
+			if d.maxStrLen != 0 && int64(len(d.buf)) > 2*(int64(d.maxStrLen)+varIntOverhead) {
+				return 0, ErrStringLength
+			}
+			d.saveBuf.Write(d.buf)
+			return len(p), nil
+		}
+		if err != nil {
+			break
+		}
+	}
+	return len(p), err
+}
+
+// errNeedMore is an internal sentinel error value that means the
+// buffer is truncated and we need to read more data before we can
+// continue parsing.
+var errNeedMore = errors.New("need more data")
+
+type indexType int
+
+const (
+	indexedTrue indexType = iota
+	indexedFalse
+	indexedNever
+)
+
+func (v indexType) indexed() bool   { return v == indexedTrue }
+func (v indexType) sensitive() bool { return v == indexedNever }
+
+// returns errNeedMore if there isn't enough data available.
+// any other error is fatal.
+// consumes d.buf iff it returns nil.
+// precondition: must be called with len(d.buf) > 0
+func (d *Decoder) parseHeaderFieldRepr() error {
+	b := d.buf[0]
+	switch {
+	case b&128 != 0:
+		// Indexed representation.
+		// High bit set?
+		// http://http2.github.io/http2-spec/compression.html#rfc.section.6.1
+		return d.parseFieldIndexed()
+	case b&192 == 64:
+		// 6.2.1 Literal Header Field with Incremental Indexing
+		// 0b10xxxxxx: top two bits are 10
+		// http://http2.github.io/http2-spec/compression.html#rfc.section.6.2.1
+		return d.parseFieldLiteral(6, indexedTrue)
+	case b&240 == 0:
+		// 6.2.2 Literal Header Field without Indexing
+		// 0b0000xxxx: top four bits are 0000
+		// http://http2.github.io/http2-spec/compression.html#rfc.section.6.2.2
+		return d.parseFieldLiteral(4, indexedFalse)
+	case b&240 == 16:
+		// 6.2.3 Literal Header Field never Indexed
+		// 0b0001xxxx: top four bits are 0001
+		// http://http2.github.io/http2-spec/compression.html#rfc.section.6.2.3
+		return d.parseFieldLiteral(4, indexedNever)
+	case b&224 == 32:
+		// 6.3 Dynamic Table Size Update
+		// Top three bits are '001'.
+		// http://http2.github.io/http2-spec/compression.html#rfc.section.6.3
+		return d.parseDynamicTableSizeUpdate()
+	}
+
+	return DecodingError{errors.New("invalid encoding")}
+}
+
+// (same invariants and behavior as parseHeaderFieldRepr)
+func (d *Decoder) parseFieldIndexed() error {
+	buf := d.buf
+	idx, buf, err := readVarInt(7, buf)
+	if err != nil {
+		return err
+	}
+	hf, ok := d.at(idx)
+	if !ok {
+		return DecodingError{InvalidIndexError(idx)}
+	}
+	d.buf = buf
+	return d.callEmit(HeaderField{Name: hf.Name, Value: hf.Value})
+}
+
+// (same invariants and behavior as parseHeaderFieldRepr)
+func (d *Decoder) parseFieldLiteral(n uint8, it indexType) error {
+	buf := d.buf
+	nameIdx, buf, err := readVarInt(n, buf)
+	if err != nil {
+		return err
+	}
+
+	var hf HeaderField
+	wantStr := d.emitEnabled || it.indexed()
+	if nameIdx > 0 {
+		ihf, ok := d.at(nameIdx)
+		if !ok {
+			return DecodingError{InvalidIndexError(nameIdx)}
+		}
+		hf.Name = ihf.Name
+	} else {
+		hf.Name, buf, err = d.readString(buf, wantStr)
+		if err != nil {
+			return err
+		}
+	}
+	hf.Value, buf, err = d.readString(buf, wantStr)
+	if err != nil {
+		return err
+	}
+	d.buf = buf
+	if it.indexed() {
+		d.dynTab.add(hf)
+	}
+	hf.Sensitive = it.sensitive()
+	return d.callEmit(hf)
+}
+
+func (d *Decoder) callEmit(hf HeaderField) error {
+	if d.maxStrLen != 0 {
+		if len(hf.Name) > d.maxStrLen || len(hf.Value) > d.maxStrLen {
+			return ErrStringLength
+		}
+	}
+	if d.emitEnabled {
+		d.emit(hf)
+	}
+	return nil
+}
+
+// (same invariants and behavior as parseHeaderFieldRepr)
+func (d *Decoder) parseDynamicTableSizeUpdate() error {
+	buf := d.buf
+	size, buf, err := readVarInt(5, buf)
+	if err != nil {
+		return err
+	}
+	if size > uint64(d.dynTab.allowedMaxSize) {
+		return DecodingError{errors.New("dynamic table size update too large")}
+	}
+	d.dynTab.setMaxSize(uint32(size))
+	d.buf = buf
+	return nil
+}
+
+var errVarintOverflow = DecodingError{errors.New("varint integer overflow")}
+
+// readVarInt reads an unsigned variable length integer off the
+// beginning of p. n is the parameter as described in
+// http://http2.github.io/http2-spec/compression.html#rfc.section.5.1.
+//
+// n must always be between 1 and 8.
+//
+// The returned remain buffer is either a smaller suffix of p, or err != nil.
+// The error is errNeedMore if p doesn't contain a complete integer.
+func readVarInt(n byte, p []byte) (i uint64, remain []byte, err error) {
+	if n < 1 || n > 8 {
+		panic("bad n")
+	}
+	if len(p) == 0 {
+		return 0, p, errNeedMore
+	}
+	i = uint64(p[0])
+	if n < 8 {
+		i &= (1 << uint64(n)) - 1
+	}
+	if i < (1<<uint64(n))-1 {
+		return i, p[1:], nil
+	}
+
+	origP := p
+	p = p[1:]
+	var m uint64
+	for len(p) > 0 {
+		b := p[0]
+		p = p[1:]
+		i += uint64(b&127) << m
+		if b&128 == 0 {
+			return i, p, nil
+		}
+		m += 7
+		if m >= 63 { // TODO: proper overflow check. making this up.
+			return 0, origP, errVarintOverflow
+		}
+	}
+	return 0, origP, errNeedMore
+}
+
+// readString decodes an hpack string from p.
+//
+// wantStr is whether s will be used. If false, decompression and
+// []byte->string garbage are skipped if s will be ignored
+// anyway. This does mean that huffman decoding errors for non-indexed
+// strings past the MAX_HEADER_LIST_SIZE are ignored, but the server
+// is returning an error anyway, and because they're not indexed, the error
+// won't affect the decoding state.
+func (d *Decoder) readString(p []byte, wantStr bool) (s string, remain []byte, err error) {
+	if len(p) == 0 {
+		return "", p, errNeedMore
+	}
+	isHuff := p[0]&128 != 0
+	strLen, p, err := readVarInt(7, p)
+	if err != nil {
+		return "", p, err
+	}
+	if d.maxStrLen != 0 && strLen > uint64(d.maxStrLen) {
+		return "", nil, ErrStringLength
+	}
+	if uint64(len(p)) < strLen {
+		return "", p, errNeedMore
+	}
+	if !isHuff {
+		if wantStr {
+			s = string(p[:strLen])
+		}
+		return s, p[strLen:], nil
+	}
+
+	if wantStr {
+		buf := bufPool.Get().(*bytes.Buffer)
+		buf.Reset() // don't trust others
+		defer bufPool.Put(buf)
+		if err := huffmanDecode(buf, d.maxStrLen, p[:strLen]); err != nil {
+			buf.Reset()
+			return "", nil, err
+		}
+		s = buf.String()
+		buf.Reset() // be nice to GC
+	}
+	return s, p[strLen:], nil
+}
diff --git a/src/internal/golang.org/x/net/http2/hpack/hpack_test.go b/src/internal/golang.org/x/net/http2/hpack/hpack_test.go
new file mode 100644
index 0000000..6dc69f9
--- /dev/null
+++ b/src/internal/golang.org/x/net/http2/hpack/hpack_test.go
@@ -0,0 +1,813 @@
+// 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 hpack
+
+import (
+	"bufio"
+	"bytes"
+	"encoding/hex"
+	"fmt"
+	"math/rand"
+	"reflect"
+	"regexp"
+	"strconv"
+	"strings"
+	"testing"
+	"time"
+)
+
+func TestStaticTable(t *testing.T) {
+	fromSpec := `
+          +-------+-----------------------------+---------------+
+          | 1     | :authority                  |               |
+          | 2     | :method                     | GET           |
+          | 3     | :method                     | POST          |
+          | 4     | :path                       | /             |
+          | 5     | :path                       | /index.html   |
+          | 6     | :scheme                     | http          |
+          | 7     | :scheme                     | https         |
+          | 8     | :status                     | 200           |
+          | 9     | :status                     | 204           |
+          | 10    | :status                     | 206           |
+          | 11    | :status                     | 304           |
+          | 12    | :status                     | 400           |
+          | 13    | :status                     | 404           |
+          | 14    | :status                     | 500           |
+          | 15    | accept-charset              |               |
+          | 16    | accept-encoding             | gzip, deflate |
+          | 17    | accept-language             |               |
+          | 18    | accept-ranges               |               |
+          | 19    | accept                      |               |
+          | 20    | access-control-allow-origin |               |
+          | 21    | age                         |               |
+          | 22    | allow                       |               |
+          | 23    | authorization               |               |
+          | 24    | cache-control               |               |
+          | 25    | content-disposition         |               |
+          | 26    | content-encoding            |               |
+          | 27    | content-language            |               |
+          | 28    | content-length              |               |
+          | 29    | content-location            |               |
+          | 30    | content-range               |               |
+          | 31    | content-type                |               |
+          | 32    | cookie                      |               |
+          | 33    | date                        |               |
+          | 34    | etag                        |               |
+          | 35    | expect                      |               |
+          | 36    | expires                     |               |
+          | 37    | from                        |               |
+          | 38    | host                        |               |
+          | 39    | if-match                    |               |
+          | 40    | if-modified-since           |               |
+          | 41    | if-none-match               |               |
+          | 42    | if-range                    |               |
+          | 43    | if-unmodified-since         |               |
+          | 44    | last-modified               |               |
+          | 45    | link                        |               |
+          | 46    | location                    |               |
+          | 47    | max-forwards                |               |
+          | 48    | proxy-authenticate          |               |
+          | 49    | proxy-authorization         |               |
+          | 50    | range                       |               |
+          | 51    | referer                     |               |
+          | 52    | refresh                     |               |
+          | 53    | retry-after                 |               |
+          | 54    | server                      |               |
+          | 55    | set-cookie                  |               |
+          | 56    | strict-transport-security   |               |
+          | 57    | transfer-encoding           |               |
+          | 58    | user-agent                  |               |
+          | 59    | vary                        |               |
+          | 60    | via                         |               |
+          | 61    | www-authenticate            |               |
+          +-------+-----------------------------+---------------+
+`
+	bs := bufio.NewScanner(strings.NewReader(fromSpec))
+	re := regexp.MustCompile(`\| (\d+)\s+\| (\S+)\s*\| (\S(.*\S)?)?\s+\|`)
+	for bs.Scan() {
+		l := bs.Text()
+		if !strings.Contains(l, "|") {
+			continue
+		}
+		m := re.FindStringSubmatch(l)
+		if m == nil {
+			continue
+		}
+		i, err := strconv.Atoi(m[1])
+		if err != nil {
+			t.Errorf("Bogus integer on line %q", l)
+			continue
+		}
+		if i < 1 || i > len(staticTable) {
+			t.Errorf("Bogus index %d on line %q", i, l)
+			continue
+		}
+		if got, want := staticTable[i-1].Name, m[2]; got != want {
+			t.Errorf("header index %d name = %q; want %q", i, got, want)
+		}
+		if got, want := staticTable[i-1].Value, m[3]; got != want {
+			t.Errorf("header index %d value = %q; want %q", i, got, want)
+		}
+	}
+	if err := bs.Err(); err != nil {
+		t.Error(err)
+	}
+}
+
+func (d *Decoder) mustAt(idx int) HeaderField {
+	if hf, ok := d.at(uint64(idx)); !ok {
+		panic(fmt.Sprintf("bogus index %d", idx))
+	} else {
+		return hf
+	}
+}
+
+func TestDynamicTableAt(t *testing.T) {
+	d := NewDecoder(4096, nil)
+	at := d.mustAt
+	if got, want := at(2), (pair(":method", "GET")); got != want {
+		t.Errorf("at(2) = %v; want %v", got, want)
+	}
+	d.dynTab.add(pair("foo", "bar"))
+	d.dynTab.add(pair("blake", "miz"))
+	if got, want := at(len(staticTable)+1), (pair("blake", "miz")); got != want {
+		t.Errorf("at(dyn 1) = %v; want %v", got, want)
+	}
+	if got, want := at(len(staticTable)+2), (pair("foo", "bar")); got != want {
+		t.Errorf("at(dyn 2) = %v; want %v", got, want)
+	}
+	if got, want := at(3), (pair(":method", "POST")); got != want {
+		t.Errorf("at(3) = %v; want %v", got, want)
+	}
+}
+
+func TestDynamicTableSearch(t *testing.T) {
+	dt := dynamicTable{}
+	dt.setMaxSize(4096)
+
+	dt.add(pair("foo", "bar"))
+	dt.add(pair("blake", "miz"))
+	dt.add(pair(":method", "GET"))
+
+	tests := []struct {
+		hf        HeaderField
+		wantI     uint64
+		wantMatch bool
+	}{
+		// Name and Value match
+		{pair("foo", "bar"), 3, true},
+		{pair(":method", "GET"), 1, true},
+
+		// Only name match because of Sensitive == true
+		{HeaderField{"blake", "miz", true}, 2, false},
+
+		// Only Name matches
+		{pair("foo", "..."), 3, false},
+		{pair("blake", "..."), 2, false},
+		{pair(":method", "..."), 1, false},
+
+		// None match
+		{pair("foo-", "bar"), 0, false},
+	}
+	for _, tt := range tests {
+		if gotI, gotMatch := dt.search(tt.hf); gotI != tt.wantI || gotMatch != tt.wantMatch {
+			t.Errorf("d.search(%+v) = %v, %v; want %v, %v", tt.hf, gotI, gotMatch, tt.wantI, tt.wantMatch)
+		}
+	}
+}
+
+func TestDynamicTableSizeEvict(t *testing.T) {
+	d := NewDecoder(4096, nil)
+	if want := uint32(0); d.dynTab.size != want {
+		t.Fatalf("size = %d; want %d", d.dynTab.size, want)
+	}
+	add := d.dynTab.add
+	add(pair("blake", "eats pizza"))
+	if want := uint32(15 + 32); d.dynTab.size != want {
+		t.Fatalf("after pizza, size = %d; want %d", d.dynTab.size, want)
+	}
+	add(pair("foo", "bar"))
+	if want := uint32(15 + 32 + 6 + 32); d.dynTab.size != want {
+		t.Fatalf("after foo bar, size = %d; want %d", d.dynTab.size, want)
+	}
+	d.dynTab.setMaxSize(15 + 32 + 1 /* slop */)
+	if want := uint32(6 + 32); d.dynTab.size != want {
+		t.Fatalf("after setMaxSize, size = %d; want %d", d.dynTab.size, want)
+	}
+	if got, want := d.mustAt(len(staticTable)+1), (pair("foo", "bar")); got != want {
+		t.Errorf("at(dyn 1) = %v; want %v", got, want)
+	}
+	add(pair("long", strings.Repeat("x", 500)))
+	if want := uint32(0); d.dynTab.size != want {
+		t.Fatalf("after big one, size = %d; want %d", d.dynTab.size, want)
+	}
+}
+
+func TestDecoderDecode(t *testing.T) {
+	tests := []struct {
+		name       string
+		in         []byte
+		want       []HeaderField
+		wantDynTab []HeaderField // newest entry first
+	}{
+		// C.2.1 Literal Header Field with Indexing
+		// http://http2.github.io/http2-spec/compression.html#rfc.section.C.2.1
+		{"C.2.1", dehex("400a 6375 7374 6f6d 2d6b 6579 0d63 7573 746f 6d2d 6865 6164 6572"),
+			[]HeaderField{pair("custom-key", "custom-header")},
+			[]HeaderField{pair("custom-key", "custom-header")},
+		},
+
+		// C.2.2 Literal Header Field without Indexing
+		// http://http2.github.io/http2-spec/compression.html#rfc.section.C.2.2
+		{"C.2.2", dehex("040c 2f73 616d 706c 652f 7061 7468"),
+			[]HeaderField{pair(":path", "/sample/path")},
+			[]HeaderField{}},
+
+		// C.2.3 Literal Header Field never Indexed
+		// http://http2.github.io/http2-spec/compression.html#rfc.section.C.2.3
+		{"C.2.3", dehex("1008 7061 7373 776f 7264 0673 6563 7265 74"),
+			[]HeaderField{{"password", "secret", true}},
+			[]HeaderField{}},
+
+		// C.2.4 Indexed Header Field
+		// http://http2.github.io/http2-spec/compression.html#rfc.section.C.2.4
+		{"C.2.4", []byte("\x82"),
+			[]HeaderField{pair(":method", "GET")},
+			[]HeaderField{}},
+	}
+	for _, tt := range tests {
+		d := NewDecoder(4096, nil)
+		hf, err := d.DecodeFull(tt.in)
+		if err != nil {
+			t.Errorf("%s: %v", tt.name, err)
+			continue
+		}
+		if !reflect.DeepEqual(hf, tt.want) {
+			t.Errorf("%s: Got %v; want %v", tt.name, hf, tt.want)
+		}
+		gotDynTab := d.dynTab.reverseCopy()
+		if !reflect.DeepEqual(gotDynTab, tt.wantDynTab) {
+			t.Errorf("%s: dynamic table after = %v; want %v", tt.name, gotDynTab, tt.wantDynTab)
+		}
+	}
+}
+
+func (dt *dynamicTable) reverseCopy() (hf []HeaderField) {
+	hf = make([]HeaderField, len(dt.ents))
+	for i := range hf {
+		hf[i] = dt.ents[len(dt.ents)-1-i]
+	}
+	return
+}
+
+type encAndWant struct {
+	enc         []byte
+	want        []HeaderField
+	wantDynTab  []HeaderField
+	wantDynSize uint32
+}
+
+// C.3 Request Examples without Huffman Coding
+// http://http2.github.io/http2-spec/compression.html#rfc.section.C.3
+func TestDecodeC3_NoHuffman(t *testing.T) {
+	testDecodeSeries(t, 4096, []encAndWant{
+		{dehex("8286 8441 0f77 7777 2e65 7861 6d70 6c65 2e63 6f6d"),
+			[]HeaderField{
+				pair(":method", "GET"),
+				pair(":scheme", "http"),
+				pair(":path", "/"),
+				pair(":authority", "www.example.com"),
+			},
+			[]HeaderField{
+				pair(":authority", "www.example.com"),
+			},
+			57,
+		},
+		{dehex("8286 84be 5808 6e6f 2d63 6163 6865"),
+			[]HeaderField{
+				pair(":method", "GET"),
+				pair(":scheme", "http"),
+				pair(":path", "/"),
+				pair(":authority", "www.example.com"),
+				pair("cache-control", "no-cache"),
+			},
+			[]HeaderField{
+				pair("cache-control", "no-cache"),
+				pair(":authority", "www.example.com"),
+			},
+			110,
+		},
+		{dehex("8287 85bf 400a 6375 7374 6f6d 2d6b 6579 0c63 7573 746f 6d2d 7661 6c75 65"),
+			[]HeaderField{
+				pair(":method", "GET"),
+				pair(":scheme", "https"),
+				pair(":path", "/index.html"),
+				pair(":authority", "www.example.com"),
+				pair("custom-key", "custom-value"),
+			},
+			[]HeaderField{
+				pair("custom-key", "custom-value"),
+				pair("cache-control", "no-cache"),
+				pair(":authority", "www.example.com"),
+			},
+			164,
+		},
+	})
+}
+
+// C.4 Request Examples with Huffman Coding
+// http://http2.github.io/http2-spec/compression.html#rfc.section.C.4
+func TestDecodeC4_Huffman(t *testing.T) {
+	testDecodeSeries(t, 4096, []encAndWant{
+		{dehex("8286 8441 8cf1 e3c2 e5f2 3a6b a0ab 90f4 ff"),
+			[]HeaderField{
+				pair(":method", "GET"),
+				pair(":scheme", "http"),
+				pair(":path", "/"),
+				pair(":authority", "www.example.com"),
+			},
+			[]HeaderField{
+				pair(":authority", "www.example.com"),
+			},
+			57,
+		},
+		{dehex("8286 84be 5886 a8eb 1064 9cbf"),
+			[]HeaderField{
+				pair(":method", "GET"),
+				pair(":scheme", "http"),
+				pair(":path", "/"),
+				pair(":authority", "www.example.com"),
+				pair("cache-control", "no-cache"),
+			},
+			[]HeaderField{
+				pair("cache-control", "no-cache"),
+				pair(":authority", "www.example.com"),
+			},
+			110,
+		},
+		{dehex("8287 85bf 4088 25a8 49e9 5ba9 7d7f 8925 a849 e95b b8e8 b4bf"),
+			[]HeaderField{
+				pair(":method", "GET"),
+				pair(":scheme", "https"),
+				pair(":path", "/index.html"),
+				pair(":authority", "www.example.com"),
+				pair("custom-key", "custom-value"),
+			},
+			[]HeaderField{
+				pair("custom-key", "custom-value"),
+				pair("cache-control", "no-cache"),
+				pair(":authority", "www.example.com"),
+			},
+			164,
+		},
+	})
+}
+
+// http://http2.github.io/http2-spec/compression.html#rfc.section.C.5
+// "This section shows several consecutive header lists, corresponding
+// to HTTP responses, on the same connection. The HTTP/2 setting
+// parameter SETTINGS_HEADER_TABLE_SIZE is set to the value of 256
+// octets, causing some evictions to occur."
+func TestDecodeC5_ResponsesNoHuff(t *testing.T) {
+	testDecodeSeries(t, 256, []encAndWant{
+		{dehex(`
+4803 3330 3258 0770 7269 7661 7465 611d
+4d6f 6e2c 2032 3120 4f63 7420 3230 3133
+2032 303a 3133 3a32 3120 474d 546e 1768
+7474 7073 3a2f 2f77 7777 2e65 7861 6d70
+6c65 2e63 6f6d
+`),
+			[]HeaderField{
+				pair(":status", "302"),
+				pair("cache-control", "private"),
+				pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+				pair("location", "https://www.example.com"),
+			},
+			[]HeaderField{
+				pair("location", "https://www.example.com"),
+				pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+				pair("cache-control", "private"),
+				pair(":status", "302"),
+			},
+			222,
+		},
+		{dehex("4803 3330 37c1 c0bf"),
+			[]HeaderField{
+				pair(":status", "307"),
+				pair("cache-control", "private"),
+				pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+				pair("location", "https://www.example.com"),
+			},
+			[]HeaderField{
+				pair(":status", "307"),
+				pair("location", "https://www.example.com"),
+				pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+				pair("cache-control", "private"),
+			},
+			222,
+		},
+		{dehex(`
+88c1 611d 4d6f 6e2c 2032 3120 4f63 7420
+3230 3133 2032 303a 3133 3a32 3220 474d
+54c0 5a04 677a 6970 7738 666f 6f3d 4153
+444a 4b48 514b 425a 584f 5157 454f 5049
+5541 5851 5745 4f49 553b 206d 6178 2d61
+6765 3d33 3630 303b 2076 6572 7369 6f6e
+3d31
+`),
+			[]HeaderField{
+				pair(":status", "200"),
+				pair("cache-control", "private"),
+				pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
+				pair("location", "https://www.example.com"),
+				pair("content-encoding", "gzip"),
+				pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"),
+			},
+			[]HeaderField{
+				pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"),
+				pair("content-encoding", "gzip"),
+				pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
+			},
+			215,
+		},
+	})
+}
+
+// http://http2.github.io/http2-spec/compression.html#rfc.section.C.6
+// "This section shows the same examples as the previous section, but
+// using Huffman encoding for the literal values. The HTTP/2 setting
+// parameter SETTINGS_HEADER_TABLE_SIZE is set to the value of 256
+// octets, causing some evictions to occur. The eviction mechanism
+// uses the length of the decoded literal values, so the same
+// evictions occurs as in the previous section."
+func TestDecodeC6_ResponsesHuffman(t *testing.T) {
+	testDecodeSeries(t, 256, []encAndWant{
+		{dehex(`
+4882 6402 5885 aec3 771a 4b61 96d0 7abe
+9410 54d4 44a8 2005 9504 0b81 66e0 82a6
+2d1b ff6e 919d 29ad 1718 63c7 8f0b 97c8
+e9ae 82ae 43d3
+`),
+			[]HeaderField{
+				pair(":status", "302"),
+				pair("cache-control", "private"),
+				pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+				pair("location", "https://www.example.com"),
+			},
+			[]HeaderField{
+				pair("location", "https://www.example.com"),
+				pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+				pair("cache-control", "private"),
+				pair(":status", "302"),
+			},
+			222,
+		},
+		{dehex("4883 640e ffc1 c0bf"),
+			[]HeaderField{
+				pair(":status", "307"),
+				pair("cache-control", "private"),
+				pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+				pair("location", "https://www.example.com"),
+			},
+			[]HeaderField{
+				pair(":status", "307"),
+				pair("location", "https://www.example.com"),
+				pair("date", "Mon, 21 Oct 2013 20:13:21 GMT"),
+				pair("cache-control", "private"),
+			},
+			222,
+		},
+		{dehex(`
+88c1 6196 d07a be94 1054 d444 a820 0595
+040b 8166 e084 a62d 1bff c05a 839b d9ab
+77ad 94e7 821d d7f2 e6c7 b335 dfdf cd5b
+3960 d5af 2708 7f36 72c1 ab27 0fb5 291f
+9587 3160 65c0 03ed 4ee5 b106 3d50 07
+`),
+			[]HeaderField{
+				pair(":status", "200"),
+				pair("cache-control", "private"),
+				pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
+				pair("location", "https://www.example.com"),
+				pair("content-encoding", "gzip"),
+				pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"),
+			},
+			[]HeaderField{
+				pair("set-cookie", "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"),
+				pair("content-encoding", "gzip"),
+				pair("date", "Mon, 21 Oct 2013 20:13:22 GMT"),
+			},
+			215,
+		},
+	})
+}
+
+func testDecodeSeries(t *testing.T, size uint32, steps []encAndWant) {
+	d := NewDecoder(size, nil)
+	for i, step := range steps {
+		hf, err := d.DecodeFull(step.enc)
+		if err != nil {
+			t.Fatalf("Error at step index %d: %v", i, err)
+		}
+		if !reflect.DeepEqual(hf, step.want) {
+			t.Fatalf("At step index %d: Got headers %v; want %v", i, hf, step.want)
+		}
+		gotDynTab := d.dynTab.reverseCopy()
+		if !reflect.DeepEqual(gotDynTab, step.wantDynTab) {
+			t.Errorf("After step index %d, dynamic table = %v; want %v", i, gotDynTab, step.wantDynTab)
+		}
+		if d.dynTab.size != step.wantDynSize {
+			t.Errorf("After step index %d, dynamic table size = %v; want %v", i, d.dynTab.size, step.wantDynSize)
+		}
+	}
+}
+
+func TestHuffmanDecode(t *testing.T) {
+	tests := []struct {
+		inHex, want string
+	}{
+		{"f1e3 c2e5 f23a 6ba0 ab90 f4ff", "www.example.com"},
+		{"a8eb 1064 9cbf", "no-cache"},
+		{"25a8 49e9 5ba9 7d7f", "custom-key"},
+		{"25a8 49e9 5bb8 e8b4 bf", "custom-value"},
+		{"6402", "302"},
+		{"aec3 771a 4b", "private"},
+		{"d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff", "Mon, 21 Oct 2013 20:13:21 GMT"},
+		{"9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3", "https://www.example.com"},
+		{"9bd9 ab", "gzip"},
+		{"94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 3160 65c0 03ed 4ee5 b106 3d50 07",
+			"foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1"},
+	}
+	for i, tt := range tests {
+		var buf bytes.Buffer
+		in, err := hex.DecodeString(strings.Replace(tt.inHex, " ", "", -1))
+		if err != nil {
+			t.Errorf("%d. hex input error: %v", i, err)
+			continue
+		}
+		if _, err := HuffmanDecode(&buf, in); err != nil {
+			t.Errorf("%d. decode error: %v", i, err)
+			continue
+		}
+		if got := buf.String(); tt.want != got {
+			t.Errorf("%d. decode = %q; want %q", i, got, tt.want)
+		}
+	}
+}
+
+func TestAppendHuffmanString(t *testing.T) {
+	tests := []struct {
+		in, want string
+	}{
+		{"www.example.com", "f1e3 c2e5 f23a 6ba0 ab90 f4ff"},
+		{"no-cache", "a8eb 1064 9cbf"},
+		{"custom-key", "25a8 49e9 5ba9 7d7f"},
+		{"custom-value", "25a8 49e9 5bb8 e8b4 bf"},
+		{"302", "6402"},
+		{"private", "aec3 771a 4b"},
+		{"Mon, 21 Oct 2013 20:13:21 GMT", "d07a be94 1054 d444 a820 0595 040b 8166 e082 a62d 1bff"},
+		{"https://www.example.com", "9d29 ad17 1863 c78f 0b97 c8e9 ae82 ae43 d3"},
+		{"gzip", "9bd9 ab"},
+		{"foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1",
+			"94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 3160 65c0 03ed 4ee5 b106 3d50 07"},
+	}
+	for i, tt := range tests {
+		buf := []byte{}
+		want := strings.Replace(tt.want, " ", "", -1)
+		buf = AppendHuffmanString(buf, tt.in)
+		if got := hex.EncodeToString(buf); want != got {
+			t.Errorf("%d. encode = %q; want %q", i, got, want)
+		}
+	}
+}
+
+func TestHuffmanMaxStrLen(t *testing.T) {
+	const msg = "Some string"
+	huff := AppendHuffmanString(nil, msg)
+
+	testGood := func(max int) {
+		var out bytes.Buffer
+		if err := huffmanDecode(&out, max, huff); err != nil {
+			t.Errorf("For maxLen=%d, unexpected error: %v", max, err)
+		}
+		if out.String() != msg {
+			t.Errorf("For maxLen=%d, out = %q; want %q", max, out.String(), msg)
+		}
+	}
+	testGood(0)
+	testGood(len(msg))
+	testGood(len(msg) + 1)
+
+	var out bytes.Buffer
+	if err := huffmanDecode(&out, len(msg)-1, huff); err != ErrStringLength {
+		t.Errorf("err = %v; want ErrStringLength", err)
+	}
+}
+
+func TestHuffmanRoundtripStress(t *testing.T) {
+	const Len = 50 // of uncompressed string
+	input := make([]byte, Len)
+	var output bytes.Buffer
+	var huff []byte
+
+	n := 5000
+	if testing.Short() {
+		n = 100
+	}
+	seed := time.Now().UnixNano()
+	t.Logf("Seed = %v", seed)
+	src := rand.New(rand.NewSource(seed))
+	var encSize int64
+	for i := 0; i < n; i++ {
+		for l := range input {
+			input[l] = byte(src.Intn(256))
+		}
+		huff = AppendHuffmanString(huff[:0], string(input))
+		encSize += int64(len(huff))
+		output.Reset()
+		if err := huffmanDecode(&output, 0, huff); err != nil {
+			t.Errorf("Failed to decode %q -> %q -> error %v", input, huff, err)
+			continue
+		}
+		if !bytes.Equal(output.Bytes(), input) {
+			t.Errorf("Roundtrip failure on %q -> %q -> %q", input, huff, output.Bytes())
+		}
+	}
+	t.Logf("Compressed size of original: %0.02f%% (%v -> %v)", 100*(float64(encSize)/(Len*float64(n))), Len*n, encSize)
+}
+
+func TestHuffmanDecodeFuzz(t *testing.T) {
+	const Len = 50 // of compressed
+	var buf, zbuf bytes.Buffer
+
+	n := 5000
+	if testing.Short() {
+		n = 100
+	}
+	seed := time.Now().UnixNano()
+	t.Logf("Seed = %v", seed)
+	src := rand.New(rand.NewSource(seed))
+	numFail := 0
+	for i := 0; i < n; i++ {
+		zbuf.Reset()
+		if i == 0 {
+			// Start with at least one invalid one.
+			zbuf.WriteString("00\x91\xff\xff\xff\xff\xc8")
+		} else {
+			for l := 0; l < Len; l++ {
+				zbuf.WriteByte(byte(src.Intn(256)))
+			}
+		}
+
+		buf.Reset()
+		if err := huffmanDecode(&buf, 0, zbuf.Bytes()); err != nil {
+			if err == ErrInvalidHuffman {
+				numFail++
+				continue
+			}
+			t.Errorf("Failed to decode %q: %v", zbuf.Bytes(), err)
+			continue
+		}
+	}
+	t.Logf("%0.02f%% are invalid (%d / %d)", 100*float64(numFail)/float64(n), numFail, n)
+	if numFail < 1 {
+		t.Error("expected at least one invalid huffman encoding (test starts with one)")
+	}
+}
+
+func TestReadVarInt(t *testing.T) {
+	type res struct {
+		i        uint64
+		consumed int
+		err      error
+	}
+	tests := []struct {
+		n    byte
+		p    []byte
+		want res
+	}{
+		// Fits in a byte:
+		{1, []byte{0}, res{0, 1, nil}},
+		{2, []byte{2}, res{2, 1, nil}},
+		{3, []byte{6}, res{6, 1, nil}},
+		{4, []byte{14}, res{14, 1, nil}},
+		{5, []byte{30}, res{30, 1, nil}},
+		{6, []byte{62}, res{62, 1, nil}},
+		{7, []byte{126}, res{126, 1, nil}},
+		{8, []byte{254}, res{254, 1, nil}},
+
+		// Doesn't fit in a byte:
+		{1, []byte{1}, res{0, 0, errNeedMore}},
+		{2, []byte{3}, res{0, 0, errNeedMore}},
+		{3, []byte{7}, res{0, 0, errNeedMore}},
+		{4, []byte{15}, res{0, 0, errNeedMore}},
+		{5, []byte{31}, res{0, 0, errNeedMore}},
+		{6, []byte{63}, res{0, 0, errNeedMore}},
+		{7, []byte{127}, res{0, 0, errNeedMore}},
+		{8, []byte{255}, res{0, 0, errNeedMore}},
+
+		// Ignoring top bits:
+		{5, []byte{255, 154, 10}, res{1337, 3, nil}}, // high dummy three bits: 111
+		{5, []byte{159, 154, 10}, res{1337, 3, nil}}, // high dummy three bits: 100
+		{5, []byte{191, 154, 10}, res{1337, 3, nil}}, // high dummy three bits: 101
+
+		// Extra byte:
+		{5, []byte{191, 154, 10, 2}, res{1337, 3, nil}}, // extra byte
+
+		// Short a byte:
+		{5, []byte{191, 154}, res{0, 0, errNeedMore}},
+
+		// integer overflow:
+		{1, []byte{255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128}, res{0, 0, errVarintOverflow}},
+	}
+	for _, tt := range tests {
+		i, remain, err := readVarInt(tt.n, tt.p)
+		consumed := len(tt.p) - len(remain)
+		got := res{i, consumed, err}
+		if got != tt.want {
+			t.Errorf("readVarInt(%d, %v ~ %x) = %+v; want %+v", tt.n, tt.p, tt.p, got, tt.want)
+		}
+	}
+}
+
+// Fuzz crash, originally reported at https://github.com/bradfitz/http2/issues/56
+func TestHuffmanFuzzCrash(t *testing.T) {
+	got, err := HuffmanDecodeToString([]byte("00\x91\xff\xff\xff\xff\xc8"))
+	if got != "" {
+		t.Errorf("Got %q; want empty string", got)
+	}
+	if err != ErrInvalidHuffman {
+		t.Errorf("Err = %v; want ErrInvalidHuffman", err)
+	}
+}
+
+func dehex(s string) []byte {
+	s = strings.Replace(s, " ", "", -1)
+	s = strings.Replace(s, "\n", "", -1)
+	b, err := hex.DecodeString(s)
+	if err != nil {
+		panic(err)
+	}
+	return b
+}
+
+func TestEmitEnabled(t *testing.T) {
+	var buf bytes.Buffer
+	enc := NewEncoder(&buf)
+	enc.WriteField(HeaderField{Name: "foo", Value: "bar"})
+	enc.WriteField(HeaderField{Name: "foo", Value: "bar"})
+
+	numCallback := 0
+	var dec *Decoder
+	dec = NewDecoder(8<<20, func(HeaderField) {
+		numCallback++
+		dec.SetEmitEnabled(false)
+	})
+	if !dec.EmitEnabled() {
+		t.Errorf("initial emit enabled = false; want true")
+	}
+	if _, err := dec.Write(buf.Bytes()); err != nil {
+		t.Error(err)
+	}
+	if numCallback != 1 {
+		t.Errorf("num callbacks = %d; want 1", numCallback)
+	}
+	if dec.EmitEnabled() {
+		t.Errorf("emit enabled = true; want false")
+	}
+}
+
+func TestSaveBufLimit(t *testing.T) {
+	const maxStr = 1 << 10
+	var got []HeaderField
+	dec := NewDecoder(initialHeaderTableSize, func(hf HeaderField) {
+		got = append(got, hf)
+	})
+	dec.SetMaxStringLength(maxStr)
+	var frag []byte
+	frag = append(frag[:0], encodeTypeByte(false, false))
+	frag = appendVarInt(frag, 7, 3)
+	frag = append(frag, "foo"...)
+	frag = appendVarInt(frag, 7, 3)
+	frag = append(frag, "bar"...)
+
+	if _, err := dec.Write(frag); err != nil {
+		t.Fatal(err)
+	}
+
+	want := []HeaderField{{Name: "foo", Value: "bar"}}
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("After small writes, got %v; want %v", got, want)
+	}
+
+	frag = append(frag[:0], encodeTypeByte(false, false))
+	frag = appendVarInt(frag, 7, maxStr*3)
+	frag = append(frag, make([]byte, maxStr*3)...)
+
+	_, err := dec.Write(frag)
+	if err != ErrStringLength {
+		t.Fatalf("Write error = %v; want ErrStringLength", err)
+	}
+}
diff --git a/src/internal/golang.org/x/net/http2/hpack/huffman.go b/src/internal/golang.org/x/net/http2/hpack/huffman.go
new file mode 100644
index 0000000..eb4b1f0
--- /dev/null
+++ b/src/internal/golang.org/x/net/http2/hpack/huffman.go
@@ -0,0 +1,190 @@
+// 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 hpack
+
+import (
+	"bytes"
+	"errors"
+	"io"
+	"sync"
+)
+
+var bufPool = sync.Pool{
+	New: func() interface{} { return new(bytes.Buffer) },
+}
+
+// HuffmanDecode decodes the string in v and writes the expanded
+// result to w, returning the number of bytes written to w and the
+// Write call's return value. At most one Write call is made.
+func HuffmanDecode(w io.Writer, v []byte) (int, error) {
+	buf := bufPool.Get().(*bytes.Buffer)
+	buf.Reset()
+	defer bufPool.Put(buf)
+	if err := huffmanDecode(buf, 0, v); err != nil {
+		return 0, err
+	}
+	return w.Write(buf.Bytes())
+}
+
+// HuffmanDecodeToString decodes the string in v.
+func HuffmanDecodeToString(v []byte) (string, error) {
+	buf := bufPool.Get().(*bytes.Buffer)
+	buf.Reset()
+	defer bufPool.Put(buf)
+	if err := huffmanDecode(buf, 0, v); err != nil {
+		return "", err
+	}
+	return buf.String(), nil
+}
+
+// ErrInvalidHuffman is returned for errors found decoding
+// Huffman-encoded strings.
+var ErrInvalidHuffman = errors.New("hpack: invalid Huffman-encoded data")
+
+// huffmanDecode decodes v to buf.
+// If maxLen is greater than 0, attempts to write more to buf than
+// maxLen bytes will return ErrStringLength.
+func huffmanDecode(buf *bytes.Buffer, maxLen int, v []byte) error {
+	n := rootHuffmanNode
+	cur, nbits := uint(0), uint8(0)
+	for _, b := range v {
+		cur = cur<<8 | uint(b)
+		nbits += 8
+		for nbits >= 8 {
+			idx := byte(cur >> (nbits - 8))
+			n = n.children[idx]
+			if n == nil {
+				return ErrInvalidHuffman
+			}
+			if n.children == nil {
+				if maxLen != 0 && buf.Len() == maxLen {
+					return ErrStringLength
+				}
+				buf.WriteByte(n.sym)
+				nbits -= n.codeLen
+				n = rootHuffmanNode
+			} else {
+				nbits -= 8
+			}
+		}
+	}
+	for nbits > 0 {
+		n = n.children[byte(cur<<(8-nbits))]
+		if n.children != nil || n.codeLen > nbits {
+			break
+		}
+		buf.WriteByte(n.sym)
+		nbits -= n.codeLen
+		n = rootHuffmanNode
+	}
+	return nil
+}
+
+type node struct {
+	// children is non-nil for internal nodes
+	children []*node
+
+	// The following are only valid if children is nil:
+	codeLen uint8 // number of bits that led to the output of sym
+	sym     byte  // output symbol
+}
+
+func newInternalNode() *node {
+	return &node{children: make([]*node, 256)}
+}
+
+var rootHuffmanNode = newInternalNode()
+
+func init() {
+	if len(huffmanCodes) != 256 {
+		panic("unexpected size")
+	}
+	for i, code := range huffmanCodes {
+		addDecoderNode(byte(i), code, huffmanCodeLen[i])
+	}
+}
+
+func addDecoderNode(sym byte, code uint32, codeLen uint8) {
+	cur := rootHuffmanNode
+	for codeLen > 8 {
+		codeLen -= 8
+		i := uint8(code >> codeLen)
+		if cur.children[i] == nil {
+			cur.children[i] = newInternalNode()
+		}
+		cur = cur.children[i]
+	}
+	shift := 8 - codeLen
+	start, end := int(uint8(code<<shift)), int(1<<shift)
+	for i := start; i < start+end; i++ {
+		cur.children[i] = &node{sym: sym, codeLen: codeLen}
+	}
+}
+
+// AppendHuffmanString appends s, as encoded in Huffman codes, to dst
+// and returns the extended buffer.
+func AppendHuffmanString(dst []byte, s string) []byte {
+	rembits := uint8(8)
+
+	for i := 0; i < len(s); i++ {
+		if rembits == 8 {
+			dst = append(dst, 0)
+		}
+		dst, rembits = appendByteToHuffmanCode(dst, rembits, s[i])
+	}
+
+	if rembits < 8 {
+		// special EOS symbol
+		code := uint32(0x3fffffff)
+		nbits := uint8(30)
+
+		t := uint8(code >> (nbits - rembits))
+		dst[len(dst)-1] |= t
+	}
+
+	return dst
+}
+
+// HuffmanEncodeLength returns the number of bytes required to encode
+// s in Huffman codes. The result is round up to byte boundary.
+func HuffmanEncodeLength(s string) uint64 {
+	n := uint64(0)
+	for i := 0; i < len(s); i++ {
+		n += uint64(huffmanCodeLen[s[i]])
+	}
+	return (n + 7) / 8
+}
+
+// appendByteToHuffmanCode appends Huffman code for c to dst and
+// returns the extended buffer and the remaining bits in the last
+// element. The appending is not byte aligned and the remaining bits
+// in the last element of dst is given in rembits.
+func appendByteToHuffmanCode(dst []byte, rembits uint8, c byte) ([]byte, uint8) {
+	code := huffmanCodes[c]
+	nbits := huffmanCodeLen[c]
+
+	for {
+		if rembits > nbits {
+			t := uint8(code << (rembits - nbits))
+			dst[len(dst)-1] |= t
+			rembits -= nbits
+			break
+		}
+
+		t := uint8(code >> (nbits - rembits))
+		dst[len(dst)-1] |= t
+
+		nbits -= rembits
+		rembits = 8
+
+		if nbits == 0 {
+			break
+		}
+
+		dst = append(dst, 0)
+	}
+
+	return dst, rembits
+}
diff --git a/src/internal/golang.org/x/net/http2/hpack/tables.go b/src/internal/golang.org/x/net/http2/hpack/tables.go
new file mode 100644
index 0000000..b9283a0
--- /dev/null
+++ b/src/internal/golang.org/x/net/http2/hpack/tables.go
@@ -0,0 +1,352 @@
+// 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 hpack
+
+func pair(name, value string) HeaderField {
+	return HeaderField{Name: name, Value: value}
+}
+
+// http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B
+var staticTable = [...]HeaderField{
+	pair(":authority", ""), // index 1 (1-based)
+	pair(":method", "GET"),
+	pair(":method", "POST"),
+	pair(":path", "/"),
+	pair(":path", "/index.html"),
+	pair(":scheme", "http"),
+	pair(":scheme", "https"),
+	pair(":status", "200"),
+	pair(":status", "204"),
+	pair(":status", "206"),
+	pair(":status", "304"),
+	pair(":status", "400"),
+	pair(":status", "404"),
+	pair(":status", "500"),
+	pair("accept-charset", ""),
+	pair("accept-encoding", "gzip, deflate"),
+	pair("accept-language", ""),
+	pair("accept-ranges", ""),
+	pair("accept", ""),
+	pair("access-control-allow-origin", ""),
+	pair("age", ""),
+	pair("allow", ""),
+	pair("authorization", ""),
+	pair("cache-control", ""),
+	pair("content-disposition", ""),
+	pair("content-encoding", ""),
+	pair("content-language", ""),
+	pair("content-length", ""),
+	pair("content-location", ""),
+	pair("content-range", ""),
+	pair("content-type", ""),
+	pair("cookie", ""),
+	pair("date", ""),
+	pair("etag", ""),
+	pair("expect", ""),
+	pair("expires", ""),
+	pair("from", ""),
+	pair("host", ""),
+	pair("if-match", ""),
+	pair("if-modified-since", ""),
+	pair("if-none-match", ""),
+	pair("if-range", ""),
+	pair("if-unmodified-since", ""),
+	pair("last-modified", ""),
+	pair("link", ""),
+	pair("location", ""),
+	pair("max-forwards", ""),
+	pair("proxy-authenticate", ""),
+	pair("proxy-authorization", ""),
+	pair("range", ""),
+	pair("referer", ""),
+	pair("refresh", ""),
+	pair("retry-after", ""),
+	pair("server", ""),
+	pair("set-cookie", ""),
+	pair("strict-transport-security", ""),
+	pair("transfer-encoding", ""),
+	pair("user-agent", ""),
+	pair("vary", ""),
+	pair("via", ""),
+	pair("www-authenticate", ""),
+}
+
+var huffmanCodes = [256]uint32{
+	0x1ff8,
+	0x7fffd8,
+	0xfffffe2,
+	0xfffffe3,
+	0xfffffe4,
+	0xfffffe5,
+	0xfffffe6,
+	0xfffffe7,
+	0xfffffe8,
+	0xffffea,
+	0x3ffffffc,
+	0xfffffe9,
+	0xfffffea,
+	0x3ffffffd,
+	0xfffffeb,
+	0xfffffec,
+	0xfffffed,
+	0xfffffee,
+	0xfffffef,
+	0xffffff0,
+	0xffffff1,
+	0xffffff2,
+	0x3ffffffe,
+	0xffffff3,
+	0xffffff4,
+	0xffffff5,
+	0xffffff6,
+	0xffffff7,
+	0xffffff8,
+	0xffffff9,
+	0xffffffa,
+	0xffffffb,
+	0x14,
+	0x3f8,
+	0x3f9,
+	0xffa,
+	0x1ff9,
+	0x15,
+	0xf8,
+	0x7fa,
+	0x3fa,
+	0x3fb,
+	0xf9,
+	0x7fb,
+	0xfa,
+	0x16,
+	0x17,
+	0x18,
+	0x0,
+	0x1,
+	0x2,
+	0x19,
+	0x1a,
+	0x1b,
+	0x1c,
+	0x1d,
+	0x1e,
+	0x1f,
+	0x5c,
+	0xfb,
+	0x7ffc,
+	0x20,
+	0xffb,
+	0x3fc,
+	0x1ffa,
+	0x21,
+	0x5d,
+	0x5e,
+	0x5f,
+	0x60,
+	0x61,
+	0x62,
+	0x63,
+	0x64,
+	0x65,
+	0x66,
+	0x67,
+	0x68,
+	0x69,
+	0x6a,
+	0x6b,
+	0x6c,
+	0x6d,
+	0x6e,
+	0x6f,
+	0x70,
+	0x71,
+	0x72,
+	0xfc,
+	0x73,
+	0xfd,
+	0x1ffb,
+	0x7fff0,
+	0x1ffc,
+	0x3ffc,
+	0x22,
+	0x7ffd,
+	0x3,
+	0x23,
+	0x4,
+	0x24,
+	0x5,
+	0x25,
+	0x26,
+	0x27,
+	0x6,
+	0x74,
+	0x75,
+	0x28,
+	0x29,
+	0x2a,
+	0x7,
+	0x2b,
+	0x76,
+	0x2c,
+	0x8,
+	0x9,
+	0x2d,
+	0x77,
+	0x78,
+	0x79,
+	0x7a,
+	0x7b,
+	0x7ffe,
+	0x7fc,
+	0x3ffd,
+	0x1ffd,
+	0xffffffc,
+	0xfffe6,
+	0x3fffd2,
+	0xfffe7,
+	0xfffe8,
+	0x3fffd3,
+	0x3fffd4,
+	0x3fffd5,
+	0x7fffd9,
+	0x3fffd6,
+	0x7fffda,
+	0x7fffdb,
+	0x7fffdc,
+	0x7fffdd,
+	0x7fffde,
+	0xffffeb,
+	0x7fffdf,
+	0xffffec,
+	0xffffed,
+	0x3fffd7,
+	0x7fffe0,
+	0xffffee,
+	0x7fffe1,
+	0x7fffe2,
+	0x7fffe3,
+	0x7fffe4,
+	0x1fffdc,
+	0x3fffd8,
+	0x7fffe5,
+	0x3fffd9,
+	0x7fffe6,
+	0x7fffe7,
+	0xffffef,
+	0x3fffda,
+	0x1fffdd,
+	0xfffe9,
+	0x3fffdb,
+	0x3fffdc,
+	0x7fffe8,
+	0x7fffe9,
+	0x1fffde,
+	0x7fffea,
+	0x3fffdd,
+	0x3fffde,
+	0xfffff0,
+	0x1fffdf,
+	0x3fffdf,
+	0x7fffeb,
+	0x7fffec,
+	0x1fffe0,
+	0x1fffe1,
+	0x3fffe0,
+	0x1fffe2,
+	0x7fffed,
+	0x3fffe1,
+	0x7fffee,
+	0x7fffef,
+	0xfffea,
+	0x3fffe2,
+	0x3fffe3,
+	0x3fffe4,
+	0x7ffff0,
+	0x3fffe5,
+	0x3fffe6,
+	0x7ffff1,
+	0x3ffffe0,
+	0x3ffffe1,
+	0xfffeb,
+	0x7fff1,
+	0x3fffe7,
+	0x7ffff2,
+	0x3fffe8,
+	0x1ffffec,
+	0x3ffffe2,
+	0x3ffffe3,
+	0x3ffffe4,
+	0x7ffffde,
+	0x7ffffdf,
+	0x3ffffe5,
+	0xfffff1,
+	0x1ffffed,
+	0x7fff2,
+	0x1fffe3,
+	0x3ffffe6,
+	0x7ffffe0,
+	0x7ffffe1,
+	0x3ffffe7,
+	0x7ffffe2,
+	0xfffff2,
+	0x1fffe4,
+	0x1fffe5,
+	0x3ffffe8,
+	0x3ffffe9,
+	0xffffffd,
+	0x7ffffe3,
+	0x7ffffe4,
+	0x7ffffe5,
+	0xfffec,
+	0xfffff3,
+	0xfffed,
+	0x1fffe6,
+	0x3fffe9,
+	0x1fffe7,
+	0x1fffe8,
+	0x7ffff3,
+	0x3fffea,
+	0x3fffeb,
+	0x1ffffee,
+	0x1ffffef,
+	0xfffff4,
+	0xfffff5,
+	0x3ffffea,
+	0x7ffff4,
+	0x3ffffeb,
+	0x7ffffe6,
+	0x3ffffec,
+	0x3ffffed,
+	0x7ffffe7,
+	0x7ffffe8,
+	0x7ffffe9,
+	0x7ffffea,
+	0x7ffffeb,
+	0xffffffe,
+	0x7ffffec,
+	0x7ffffed,
+	0x7ffffee,
+	0x7ffffef,
+	0x7fffff0,
+	0x3ffffee,
+}
+
+var huffmanCodeLen = [256]uint8{
+	13, 23, 28, 28, 28, 28, 28, 28, 28, 24, 30, 28, 28, 30, 28, 28,
+	28, 28, 28, 28, 28, 28, 30, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+	6, 10, 10, 12, 13, 6, 8, 11, 10, 10, 8, 11, 8, 6, 6, 6,
+	5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 8, 15, 6, 12, 10,
+	13, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+	7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 13, 19, 13, 14, 6,
+	15, 5, 6, 5, 6, 5, 6, 6, 6, 5, 7, 7, 6, 6, 6, 5,
+	6, 7, 6, 5, 5, 6, 7, 7, 7, 7, 7, 15, 11, 14, 13, 28,
+	20, 22, 20, 20, 22, 22, 22, 23, 22, 23, 23, 23, 23, 23, 24, 23,
+	24, 24, 22, 23, 24, 23, 23, 23, 23, 21, 22, 23, 22, 23, 23, 24,
+	22, 21, 20, 22, 22, 23, 23, 21, 23, 22, 22, 24, 21, 22, 23, 23,
+	21, 21, 22, 21, 23, 22, 23, 23, 20, 22, 22, 22, 23, 22, 22, 23,
+	26, 26, 20, 19, 22, 23, 22, 25, 26, 26, 26, 27, 27, 26, 24, 25,
+	19, 21, 26, 27, 27, 26, 27, 24, 21, 21, 26, 26, 28, 27, 27, 27,
+	20, 24, 20, 21, 22, 21, 21, 23, 22, 22, 25, 25, 24, 24, 26, 23,
+	26, 27, 26, 26, 27, 27, 27, 27, 27, 28, 27, 27, 27, 27, 27, 26,
+}
diff --git a/src/internal/race/doc.go b/src/internal/race/doc.go
new file mode 100644
index 0000000..d6a2243
--- /dev/null
+++ b/src/internal/race/doc.go
@@ -0,0 +1,11 @@
+// Copyright 2015 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 race contains helper functions for manually instrumenting code for the race detector.
+
+The runtime package intentionally exports these functions only in the race build;
+this package exports them unconditionally but without the "race" build tag they are no-ops.
+*/
+package race
diff --git a/src/internal/race/norace.go b/src/internal/race/norace.go
new file mode 100644
index 0000000..d9049eb
--- /dev/null
+++ b/src/internal/race/norace.go
@@ -0,0 +1,40 @@
+// Copyright 2015 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.
+
+// +build !race
+
+package race
+
+import (
+	"unsafe"
+)
+
+const Enabled = false
+
+func Acquire(addr unsafe.Pointer) {
+}
+
+func Release(addr unsafe.Pointer) {
+}
+
+func ReleaseMerge(addr unsafe.Pointer) {
+}
+
+func Disable() {
+}
+
+func Enable() {
+}
+
+func Read(addr unsafe.Pointer) {
+}
+
+func Write(addr unsafe.Pointer) {
+}
+
+func ReadRange(addr unsafe.Pointer, len int) {
+}
+
+func WriteRange(addr unsafe.Pointer, len int) {
+}
diff --git a/src/internal/race/race.go b/src/internal/race/race.go
new file mode 100644
index 0000000..cb0e773
--- /dev/null
+++ b/src/internal/race/race.go
@@ -0,0 +1,50 @@
+// Copyright 2015 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.
+
+// +build race
+
+package race
+
+import (
+	"runtime"
+	"unsafe"
+)
+
+const Enabled = true
+
+func Acquire(addr unsafe.Pointer) {
+	runtime.RaceAcquire(addr)
+}
+
+func Release(addr unsafe.Pointer) {
+	runtime.RaceRelease(addr)
+}
+
+func ReleaseMerge(addr unsafe.Pointer) {
+	runtime.RaceReleaseMerge(addr)
+}
+
+func Disable() {
+	runtime.RaceDisable()
+}
+
+func Enable() {
+	runtime.RaceEnable()
+}
+
+func Read(addr unsafe.Pointer) {
+	runtime.RaceRead(addr)
+}
+
+func Write(addr unsafe.Pointer) {
+	runtime.RaceWrite(addr)
+}
+
+func ReadRange(addr unsafe.Pointer, len int) {
+	runtime.RaceReadRange(addr, len)
+}
+
+func WriteRange(addr unsafe.Pointer, len int) {
+	runtime.RaceWriteRange(addr, len)
+}
diff --git a/src/internal/syscall/unix/getrandom_linux.go b/src/internal/syscall/unix/getrandom_linux.go
index 7388271..e07557a 100644
--- a/src/internal/syscall/unix/getrandom_linux.go
+++ b/src/internal/syscall/unix/getrandom_linux.go
@@ -5,20 +5,11 @@
 package unix
 
 import (
-	"runtime"
 	"sync/atomic"
 	"syscall"
 	"unsafe"
 )
 
-var randomTrap = map[string]uintptr{
-	"386":     355,
-	"amd64":   318,
-	"arm":     384,
-	"ppc64":   359,
-	"ppc64le": 359,
-}[runtime.GOARCH]
-
 var randomUnsupported int32 // atomic
 
 // GetRandomFlag is a flag supported by the getrandom system call.
diff --git a/src/internal/syscall/unix/getrandom_linux_386.go b/src/internal/syscall/unix/getrandom_linux_386.go
new file mode 100644
index 0000000..48c69b4
--- /dev/null
+++ b/src/internal/syscall/unix/getrandom_linux_386.go
@@ -0,0 +1,7 @@
+// 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 unix
+
+const randomTrap uintptr = 355
diff --git a/src/internal/syscall/unix/getrandom_linux_amd64.go b/src/internal/syscall/unix/getrandom_linux_amd64.go
new file mode 100644
index 0000000..7175e36
--- /dev/null
+++ b/src/internal/syscall/unix/getrandom_linux_amd64.go
@@ -0,0 +1,7 @@
+// 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 unix
+
+const randomTrap uintptr = 318
diff --git a/src/internal/syscall/unix/getrandom_linux_arm.go b/src/internal/syscall/unix/getrandom_linux_arm.go
new file mode 100644
index 0000000..c4d6f43
--- /dev/null
+++ b/src/internal/syscall/unix/getrandom_linux_arm.go
@@ -0,0 +1,7 @@
+// 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 unix
+
+const randomTrap uintptr = 384
diff --git a/src/internal/syscall/unix/getrandom_linux_generic.go b/src/internal/syscall/unix/getrandom_linux_generic.go
new file mode 100644
index 0000000..0e632dc
--- /dev/null
+++ b/src/internal/syscall/unix/getrandom_linux_generic.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.
+
+// +build arm64
+
+package unix
+
+const randomTrap uintptr = 278
diff --git a/src/internal/syscall/unix/getrandom_linux_mips64x.go b/src/internal/syscall/unix/getrandom_linux_mips64x.go
new file mode 100644
index 0000000..8531db6
--- /dev/null
+++ b/src/internal/syscall/unix/getrandom_linux_mips64x.go
@@ -0,0 +1,9 @@
+// Copyright 2015 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.
+
+// +build mips64 mips64le
+
+package unix
+
+const randomTrap uintptr = 5313
diff --git a/src/internal/syscall/unix/getrandom_linux_ppc64x.go b/src/internal/syscall/unix/getrandom_linux_ppc64x.go
new file mode 100644
index 0000000..6edaba2
--- /dev/null
+++ b/src/internal/syscall/unix/getrandom_linux_ppc64x.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.
+
+// +build ppc64 ppc64le
+
+package unix
+
+const randomTrap uintptr = 359
diff --git a/src/internal/syscall/windows/registry/registry_test.go b/src/internal/syscall/windows/registry/registry_test.go
index 07eccb2..a63c420 100644
--- a/src/internal/syscall/windows/registry/registry_test.go
+++ b/src/internal/syscall/windows/registry/registry_test.go
@@ -12,6 +12,7 @@ import (
 	"os"
 	"syscall"
 	"testing"
+	"unsafe"
 
 	"internal/syscall/windows/registry"
 )
@@ -676,3 +677,76 @@ func TestInvalidValues(t *testing.T) {
 		}
 	}
 }
+
+func TestGetMUIStringValue(t *testing.T) {
+	if err := registry.LoadRegLoadMUIString(); err != nil {
+		t.Skip("regLoadMUIString not supported; skipping")
+	}
+	if err := procGetDynamicTimeZoneInformation.Find(); err != nil {
+		t.Skipf("%s not supported; skipping", procGetDynamicTimeZoneInformation.Name)
+	}
+	var dtzi DynamicTimezoneinformation
+	if _, err := GetDynamicTimeZoneInformation(&dtzi); err != nil {
+		t.Fatal(err)
+	}
+	tzKeyName := syscall.UTF16ToString(dtzi.TimeZoneKeyName[:])
+	timezoneK, err := registry.OpenKey(registry.LOCAL_MACHINE,
+		`SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\`+tzKeyName, registry.READ)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer timezoneK.Close()
+
+	type testType struct {
+		name string
+		want string
+	}
+	var tests = []testType{
+		{"MUI_Std", syscall.UTF16ToString(dtzi.StandardName[:])},
+	}
+	if dtzi.DynamicDaylightTimeDisabled == 0 {
+		tests = append(tests, testType{"MUI_Dlt", syscall.UTF16ToString(dtzi.DaylightName[:])})
+	}
+
+	for _, test := range tests {
+		got, err := timezoneK.GetMUIStringValue(test.name)
+		if err != nil {
+			t.Error("GetMUIStringValue:", err)
+		}
+
+		if got != test.want {
+			t.Errorf("GetMUIStringValue: %s: Got %q, want %q", test.name, got, test.want)
+		}
+	}
+}
+
+type DynamicTimezoneinformation struct {
+	Bias                        int32
+	StandardName                [32]uint16
+	StandardDate                syscall.Systemtime
+	StandardBias                int32
+	DaylightName                [32]uint16
+	DaylightDate                syscall.Systemtime
+	DaylightBias                int32
+	TimeZoneKeyName             [128]uint16
+	DynamicDaylightTimeDisabled uint8
+}
+
+var (
+	kernel32DLL = syscall.NewLazyDLL("kernel32")
+
+	procGetDynamicTimeZoneInformation = kernel32DLL.NewProc("GetDynamicTimeZoneInformation")
+)
+
+func GetDynamicTimeZoneInformation(dtzi *DynamicTimezoneinformation) (rc uint32, err error) {
+	r0, _, e1 := syscall.Syscall(procGetDynamicTimeZoneInformation.Addr(), 1, uintptr(unsafe.Pointer(dtzi)), 0, 0)
+	rc = uint32(r0)
+	if rc == 0xffffffff {
+		if e1 != 0 {
+			err = error(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
diff --git a/src/internal/syscall/windows/registry/syscall.go b/src/internal/syscall/windows/registry/syscall.go
index 38e573f..5426cae 100644
--- a/src/internal/syscall/windows/registry/syscall.go
+++ b/src/internal/syscall/windows/registry/syscall.go
@@ -19,10 +19,15 @@ const (
 	_ERROR_NO_MORE_ITEMS syscall.Errno = 259
 )
 
+func LoadRegLoadMUIString() error {
+	return procRegLoadMUIStringW.Find()
+}
+
 //sys	regCreateKeyEx(key syscall.Handle, subkey *uint16, reserved uint32, class *uint16, options uint32, desired uint32, sa *syscall.SecurityAttributes, result *syscall.Handle, disposition *uint32) (regerrno error) = advapi32.RegCreateKeyExW
 //sys	regDeleteKey(key syscall.Handle, subkey *uint16) (regerrno error) = advapi32.RegDeleteKeyW
 //sys	regSetValueEx(key syscall.Handle, valueName *uint16, reserved uint32, vtype uint32, buf *byte, bufsize uint32) (regerrno error) = advapi32.RegSetValueExW
 //sys	regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegEnumValueW
 //sys	regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) = advapi32.RegDeleteValueW
+//sys   regLoadMUIString(key syscall.Handle, name *uint16, buf *uint16, buflen uint32, buflenCopied *uint32, flags uint32, dir *uint16) (regerrno error) = advapi32.RegLoadMUIStringW
 
 //sys	expandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32, err error) = kernel32.ExpandEnvironmentStringsW
diff --git a/src/internal/syscall/windows/registry/value.go b/src/internal/syscall/windows/registry/value.go
index f4bb1b3..71d4e15 100644
--- a/src/internal/syscall/windows/registry/value.go
+++ b/src/internal/syscall/windows/registry/value.go
@@ -108,10 +108,65 @@ func (k Key) GetStringValue(name string) (val string, valtype uint32, err error)
 	if len(data) == 0 {
 		return "", typ, nil
 	}
-	u := (*[1 << 10]uint16)(unsafe.Pointer(&data[0]))[:]
+	u := (*[1 << 29]uint16)(unsafe.Pointer(&data[0]))[:]
 	return syscall.UTF16ToString(u), typ, nil
 }
 
+// GetMUIStringValue retrieves the localized string value for
+// the specified value name associated with an open key k.
+// If the value name doesn't exist or the localized string value
+// can't be resolved, GetMUIStringValue returns ErrNotExist.
+// GetMUIStringValue panics if the system doesn't support
+// regLoadMUIString; use LoadRegLoadMUIString to check if
+// regLoadMUIString is supported before calling this function.
+func (k Key) GetMUIStringValue(name string) (string, error) {
+	pname, err := syscall.UTF16PtrFromString(name)
+	if err != nil {
+		return "", err
+	}
+
+	buf := make([]uint16, 1024)
+	var buflen uint32
+	var pdir *uint16
+
+	err = regLoadMUIString(syscall.Handle(k), pname, &buf[0], uint32(len(buf)), &buflen, 0, pdir)
+	if err == syscall.ERROR_FILE_NOT_FOUND { // Try fallback path
+
+		// Try to resolve the string value using the system directory as
+		// a DLL search path; this assumes the string value is of the form
+		// @[path]\dllname,-strID but with no path given, e.g. @tzres.dll,-320.
+
+		// This approach works with tzres.dll but may have to be revised
+		// in the future to allow callers to provide custom search paths.
+
+		var s string
+		s, err = ExpandString("%SystemRoot%\\system32\\")
+		if err != nil {
+			return "", err
+		}
+		pdir, err = syscall.UTF16PtrFromString(s)
+		if err != nil {
+			return "", err
+		}
+
+		err = regLoadMUIString(syscall.Handle(k), pname, &buf[0], uint32(len(buf)), &buflen, 0, pdir)
+	}
+
+	for err == syscall.ERROR_MORE_DATA { // Grow buffer if needed
+		if buflen <= uint32(len(buf)) {
+			break // Buffer not growing, assume race; break
+		}
+		buf = make([]uint16, buflen)
+		err = regLoadMUIString(syscall.Handle(k), pname, &buf[0], uint32(len(buf)), &buflen, 0, pdir)
+	}
+
+	if err != nil {
+		return "", err
+	}
+
+	return syscall.UTF16ToString(buf), nil
+}
+
 // ExpandString expands environment-variable strings and replaces
 // them with the values defined for the current user.
 // Use ExpandString to expand EXPAND_SZ strings.
@@ -130,7 +185,7 @@ func ExpandString(value string) (string, error) {
 			return "", err
 		}
 		if n <= uint32(len(r)) {
-			u := (*[1 << 15]uint16)(unsafe.Pointer(&r[0]))[:]
+			u := (*[1 << 29]uint16)(unsafe.Pointer(&r[0]))[:]
 			return syscall.UTF16ToString(u), nil
 		}
 		r = make([]uint16, n)
@@ -153,7 +208,7 @@ func (k Key) GetStringsValue(name string) (val []string, valtype uint32, err err
 	if len(data) == 0 {
 		return nil, typ, nil
 	}
-	p := (*[1 << 24]uint16)(unsafe.Pointer(&data[0]))[:len(data)/2]
+	p := (*[1 << 29]uint16)(unsafe.Pointer(&data[0]))[:len(data)/2]
 	if len(p) == 0 {
 		return nil, typ, nil
 	}
@@ -241,7 +296,7 @@ func (k Key) setStringValue(name string, valtype uint32, value string) error {
 	if err != nil {
 		return err
 	}
-	buf := (*[1 << 10]byte)(unsafe.Pointer(&v[0]))[:len(v)*2]
+	buf := (*[1 << 29]byte)(unsafe.Pointer(&v[0]))[:len(v)*2]
 	return k.setValue(name, valtype, buf)
 }
 
@@ -271,7 +326,7 @@ func (k Key) SetStringsValue(name string, value []string) error {
 		ss += s + "\x00"
 	}
 	v := utf16.Encode([]rune(ss + "\x00"))
-	buf := (*[1 << 10]byte)(unsafe.Pointer(&v[0]))[:len(v)*2]
+	buf := (*[1 << 29]byte)(unsafe.Pointer(&v[0]))[:len(v)*2]
 	return k.setValue(name, MULTI_SZ, buf)
 }
 
diff --git a/src/internal/syscall/windows/registry/zsyscall_windows.go b/src/internal/syscall/windows/registry/zsyscall_windows.go
index 2b3de63..9c17675 100644
--- a/src/internal/syscall/windows/registry/zsyscall_windows.go
+++ b/src/internal/syscall/windows/registry/zsyscall_windows.go
@@ -16,6 +16,7 @@ var (
 	procRegSetValueExW            = modadvapi32.NewProc("RegSetValueExW")
 	procRegEnumValueW             = modadvapi32.NewProc("RegEnumValueW")
 	procRegDeleteValueW           = modadvapi32.NewProc("RegDeleteValueW")
+	procRegLoadMUIStringW         = modadvapi32.NewProc("RegLoadMUIStringW")
 	procExpandEnvironmentStringsW = modkernel32.NewProc("ExpandEnvironmentStringsW")
 )
 
@@ -59,6 +60,14 @@ func regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) {
 	return
 }
 
+func regLoadMUIString(key syscall.Handle, name *uint16, buf *uint16, buflen uint32, buflenCopied *uint32, flags uint32, dir *uint16) (regerrno error) {
+	r0, _, _ := syscall.Syscall9(procRegLoadMUIStringW.Addr(), 7, uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(unsafe.Pointer(buflenCopied)), uintptr(flags), uintptr(unsafe.Pointer(dir)), 0, 0)
+	if r0 != 0 {
+		regerrno = syscall.Errno(r0)
+	}
+	return
+}
+
 func expandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32, err error) {
 	r0, _, e1 := syscall.Syscall(procExpandEnvironmentStringsW.Addr(), 3, uintptr(unsafe.Pointer(src)), uintptr(unsafe.Pointer(dst)), uintptr(size))
 	n = uint32(r0)
diff --git a/src/internal/syscall/windows/syscall_windows.go b/src/internal/syscall/windows/syscall_windows.go
index dc8a916..165e894 100644
--- a/src/internal/syscall/windows/syscall_windows.go
+++ b/src/internal/syscall/windows/syscall_windows.go
@@ -10,7 +10,17 @@ import "syscall"
 
 const GAA_FLAG_INCLUDE_PREFIX = 0x00000010
 
-const IF_TYPE_SOFTWARE_LOOPBACK = 24
+const (
+	IF_TYPE_OTHER              = 1
+	IF_TYPE_ETHERNET_CSMACD    = 6
+	IF_TYPE_ISO88025_TOKENRING = 9
+	IF_TYPE_PPP                = 23
+	IF_TYPE_SOFTWARE_LOOPBACK  = 24
+	IF_TYPE_ATM                = 37
+	IF_TYPE_IEEE80211          = 71
+	IF_TYPE_TUNNEL             = 131
+	IF_TYPE_IEEE1394           = 144
+)
 
 type SocketAddress struct {
 	Sockaddr       *syscall.RawSockaddrAny
@@ -94,7 +104,7 @@ const (
 	IfOperStatusLowerLayerDown = 7
 )
 
-//sys GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizeOfPointer *uint32) (errcode error) = iphlpapi.GetAdaptersAddresses
+//sys	GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) = iphlpapi.GetAdaptersAddresses
 //sys	GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW
 //sys	MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) = MoveFileExW
 
@@ -128,3 +138,6 @@ func Rename(oldpath, newpath string) error {
 	}
 	return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING)
 }
+
+//sys	GetACP() (acp uint32) = kernel32.GetACP
+//sys	MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar
diff --git a/src/internal/syscall/windows/zsyscall_windows.go b/src/internal/syscall/windows/zsyscall_windows.go
index c6f607a..de41786 100644
--- a/src/internal/syscall/windows/zsyscall_windows.go
+++ b/src/internal/syscall/windows/zsyscall_windows.go
@@ -14,10 +14,12 @@ var (
 	procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses")
 	procGetComputerNameExW   = modkernel32.NewProc("GetComputerNameExW")
 	procMoveFileExW          = modkernel32.NewProc("MoveFileExW")
+	procGetACP               = modkernel32.NewProc("GetACP")
+	procMultiByteToWideChar  = modkernel32.NewProc("MultiByteToWideChar")
 )
 
-func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizeOfPointer *uint32) (errcode error) {
-	r0, _, _ := syscall.Syscall6(procGetAdaptersAddresses.Addr(), 5, uintptr(family), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(adapterAddresses)), uintptr(unsafe.Pointer(sizeOfPointer)), 0)
+func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) {
+	r0, _, _ := syscall.Syscall6(procGetAdaptersAddresses.Addr(), 5, uintptr(family), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(adapterAddresses)), uintptr(unsafe.Pointer(sizePointer)), 0)
 	if r0 != 0 {
 		errcode = syscall.Errno(r0)
 	}
@@ -47,3 +49,22 @@ func MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) {
 	}
 	return
 }
+
+func GetACP() (acp uint32) {
+	r0, _, _ := syscall.Syscall(procGetACP.Addr(), 0, 0, 0, 0)
+	acp = uint32(r0)
+	return
+}
+
+func MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) {
+	r0, _, e1 := syscall.Syscall6(procMultiByteToWideChar.Addr(), 6, uintptr(codePage), uintptr(dwFlags), uintptr(unsafe.Pointer(str)), uintptr(nstr), uintptr(unsafe.Pointer(wchar)), uintptr(nwchar))
+	nwrite = int32(r0)
+	if nwrite == 0 {
+		if e1 != 0 {
+			err = error(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
diff --git a/src/internal/trace/parser.go b/src/internal/trace/parser.go
index 1eb39dd..11f9aba 100644
--- a/src/internal/trace/parser.go
+++ b/src/internal/trace/parser.go
@@ -479,7 +479,7 @@ func postProcessTrace(events []*Event) error {
 			p.g = ev.G
 			if g.evCreate != nil {
 				// +1 because symbolizer expects return pc.
-				ev.Stk = []*Frame{&Frame{PC: g.evCreate.Args[1] + 1}}
+				ev.Stk = []*Frame{{PC: g.evCreate.Args[1] + 1}}
 				g.evCreate = nil
 			}
 
diff --git a/src/internal/trace/parser_test.go b/src/internal/trace/parser_test.go
index 0eeb3e6..fecefc4 100644
--- a/src/internal/trace/parser_test.go
+++ b/src/internal/trace/parser_test.go
@@ -24,7 +24,7 @@ func TestCorruptedInputs(t *testing.T) {
 	for _, data := range tests {
 		events, err := Parse(strings.NewReader(data))
 		if err == nil || events != nil {
-			t.Fatalf("no error on input: %q\n", t)
+			t.Fatalf("no error on input: %q\n", data)
 		}
 	}
 }
diff --git a/src/io/example_test.go b/src/io/example_test.go
new file mode 100644
index 0000000..412dfb3
--- /dev/null
+++ b/src/io/example_test.go
@@ -0,0 +1,223 @@
+// Copyright 2015 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 io_test
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"os"
+	"strings"
+)
+
+func ExampleCopy() {
+	r := strings.NewReader("some io.Reader stream to be read\n")
+
+	if _, err := io.Copy(os.Stdout, r); err != nil {
+		log.Fatal(err)
+	}
+
+	// Output:
+	// some io.Reader stream to be read
+}
+
+func ExampleCopyBuffer() {
+	r1 := strings.NewReader("first reader\n")
+	r2 := strings.NewReader("second reader\n")
+	buf := make([]byte, 8)
+
+	// buf is used here...
+	if _, err := io.CopyBuffer(os.Stdout, r1, buf); err != nil {
+		log.Fatal(err)
+	}
+
+	// ... reused here also. No need to allocate an extra buffer.
+	if _, err := io.CopyBuffer(os.Stdout, r2, buf); err != nil {
+		log.Fatal(err)
+	}
+
+	// Output:
+	// first reader
+	// second reader
+}
+
+func ExampleCopyN() {
+	r := strings.NewReader("some io.Reader stream to be read")
+
+	if _, err := io.CopyN(os.Stdout, r, 5); err != nil {
+		log.Fatal(err)
+	}
+
+	// Output:
+	// some
+}
+
+func ExampleReadAtLeast() {
+	r := strings.NewReader("some io.Reader stream to be read\n")
+
+	buf := make([]byte, 33)
+	if _, err := io.ReadAtLeast(r, buf, 4); err != nil {
+		log.Fatal(err)
+	}
+	fmt.Printf("%s\n", buf)
+
+	// buffer smaller than minimal read size.
+	shortBuf := make([]byte, 3)
+	if _, err := io.ReadAtLeast(r, shortBuf, 4); err != nil {
+		fmt.Println("error:", err)
+	}
+
+	// minimal read size bigger than io.Reader stream
+	longBuf := make([]byte, 64)
+	if _, err := io.ReadAtLeast(r, longBuf, 64); err != nil {
+		fmt.Println("error:", err)
+	}
+
+	// Output:
+	// some io.Reader stream to be read
+	//
+	// error: short buffer
+	// error: EOF
+}
+
+func ExampleReadFull() {
+	r := strings.NewReader("some io.Reader stream to be read\n")
+
+	buf := make([]byte, 4)
+	if _, err := io.ReadFull(r, buf); err != nil {
+		log.Fatal(err)
+	}
+	fmt.Printf("%s\n", buf)
+
+	// minimal read size bigger than io.Reader stream
+	longBuf := make([]byte, 64)
+	if _, err := io.ReadFull(r, longBuf); err != nil {
+		fmt.Println("error:", err)
+	}
+
+	// Output:
+	// some
+	// error: unexpected EOF
+}
+
+func ExampleWriteString() {
+	io.WriteString(os.Stdout, "Hello World")
+
+	// Output: Hello World
+}
+
+func ExampleLimitReader() {
+	r := strings.NewReader("some io.Reader stream to be read\n")
+	lr := io.LimitReader(r, 4)
+
+	if _, err := io.Copy(os.Stdout, lr); err != nil {
+		log.Fatal(err)
+	}
+
+	// Output:
+	// some
+}
+
+func ExampleMultiReader() {
+	r1 := strings.NewReader("first reader ")
+	r2 := strings.NewReader("second reader ")
+	r3 := strings.NewReader("third reader\n")
+	r := io.MultiReader(r1, r2, r3)
+
+	if _, err := io.Copy(os.Stdout, r); err != nil {
+		log.Fatal(err)
+	}
+
+	// Output:
+	// first reader second reader third reader
+}
+
+func ExampleTeeReader() {
+	r := strings.NewReader("some io.Reader stream to be read\n")
+	var buf bytes.Buffer
+	tee := io.TeeReader(r, &buf)
+
+	printall := func(r io.Reader) {
+		b, err := ioutil.ReadAll(r)
+		if err != nil {
+			log.Fatal(err)
+		}
+
+		fmt.Printf("%s", b)
+	}
+
+	printall(tee)
+	printall(&buf)
+
+	// Output:
+	// some io.Reader stream to be read
+	// some io.Reader stream to be read
+}
+
+func ExampleSectionReader() {
+	r := strings.NewReader("some io.Reader stream to be read\n")
+	s := io.NewSectionReader(r, 5, 17)
+
+	if _, err := io.Copy(os.Stdout, s); err != nil {
+		log.Fatal(err)
+	}
+
+	// Output:
+	// io.Reader stream
+}
+
+func ExampleSectionReader_ReadAt() {
+	r := strings.NewReader("some io.Reader stream to be read\n")
+	s := io.NewSectionReader(r, 5, 16)
+
+	buf := make([]byte, 6)
+	if _, err := s.ReadAt(buf, 10); err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Printf("%s\n", buf)
+
+	// Output:
+	// stream
+}
+
+func ExampleSectionReader_Seek() {
+	r := strings.NewReader("some io.Reader stream to be read\n")
+	s := io.NewSectionReader(r, 5, 16)
+
+	if _, err := s.Seek(10, 0); err != nil {
+		log.Fatal(err)
+	}
+
+	buf := make([]byte, 6)
+	if _, err := s.Read(buf); err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Printf("%s\n", buf)
+
+	// Output:
+	// stream
+}
+
+func ExampleMultiWriter() {
+	r := strings.NewReader("some io.Reader stream to be read\n")
+
+	var buf1, buf2 bytes.Buffer
+	w := io.MultiWriter(&buf1, &buf2)
+
+	if _, err := io.Copy(w, r); err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Print(buf1.String())
+	fmt.Print(buf2.String())
+
+	// Output:
+	// some io.Reader stream to be read
+	// some io.Reader stream to be read
+}
diff --git a/src/io/io.go b/src/io/io.go
index 8851eaf..8e7855c 100644
--- a/src/io/io.go
+++ b/src/io/io.go
@@ -95,14 +95,14 @@ type Closer interface {
 // Seeker is the interface that wraps the basic Seek method.
 //
 // Seek sets the offset for the next Read or Write to offset,
-// interpreted according to whence: 0 means relative to the origin of
+// interpreted according to whence: 0 means relative to the start of
 // the file, 1 means relative to the current offset, and 2 means
-// relative to the end.  Seek returns the new offset and an error, if
-// any.
+// relative to the end. Seek returns the new offset relative to the
+// start of the file and an error, if any.
 //
-// Seeking to a negative offset is an error. Seeking to any positive
-// offset is legal, but the behavior of subsequent I/O operations on
-// the underlying object is implementation-dependent.
+// Seeking to an offset before the start of the file is an error.
+// Seeking to any positive offset is legal, but the behavior of subsequent
+// I/O operations on the underlying object is implementation-dependent.
 type Seeker interface {
 	Seek(offset int64, whence int) (int64, error)
 }
@@ -225,7 +225,6 @@ type WriterAt interface {
 // ByteReader is the interface that wraps the ReadByte method.
 //
 // ReadByte reads and returns the next byte from the input.
-// If no byte is available, err will be set.
 type ByteReader interface {
 	ReadByte() (c byte, err error)
 }
diff --git a/src/io/ioutil/example_test.go b/src/io/ioutil/example_test.go
new file mode 100644
index 0000000..0ccc92d
--- /dev/null
+++ b/src/io/ioutil/example_test.go
@@ -0,0 +1,71 @@
+// Copyright 2015 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 ioutil_test
+
+import (
+	"fmt"
+	"io/ioutil"
+	"log"
+	"os"
+	"path/filepath"
+	"strings"
+)
+
+func ExampleReadAll() {
+	r := strings.NewReader("Go is a general-purpose language designed with systems programming in mind.")
+
+	b, err := ioutil.ReadAll(r)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Printf("%s", b)
+
+	// Output:
+	// Go is a general-purpose language designed with systems programming in mind.
+}
+
+func ExampleReadDir() {
+	files, err := ioutil.ReadDir(".")
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	for _, file := range files {
+		fmt.Println(file.Name())
+	}
+}
+
+func ExampleTempDir() {
+	content := []byte("temporary file's content")
+	dir, err := ioutil.TempDir("", "example")
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	defer os.RemoveAll(dir) // clean up
+
+	tmpfn := filepath.Join(dir, "tmpfile")
+	if err := ioutil.WriteFile(tmpfn, content, 0666); err != nil {
+		log.Fatal(err)
+	}
+}
+
+func ExampleTempFile() {
+	content := []byte("temporary file's content")
+	tmpfile, err := ioutil.TempFile("", "example")
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	defer os.Remove(tmpfile.Name()) // clean up
+
+	if _, err := tmpfile.Write(content); err != nil {
+		log.Fatal(err)
+	}
+	if err := tmpfile.Close(); err != nil {
+		log.Fatal(err)
+	}
+}
diff --git a/src/io/ioutil/ioutil.go b/src/io/ioutil/ioutil.go
index 909a815..e90a33f 100644
--- a/src/io/ioutil/ioutil.go
+++ b/src/io/ioutil/ioutil.go
@@ -96,7 +96,7 @@ func (f byName) Less(i, j int) bool { return f[i].Name() < f[j].Name() }
 func (f byName) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }
 
 // ReadDir reads the directory named by dirname and returns
-// a list of sorted directory entries.
+// a list of directory entries sorted by filename.
 func ReadDir(dirname string) ([]os.FileInfo, error) {
 	f, err := os.Open(dirname)
 	if err != nil {
diff --git a/src/io/multi.go b/src/io/multi.go
index e26cc53..16860aa 100644
--- a/src/io/multi.go
+++ b/src/io/multi.go
@@ -52,6 +52,30 @@ func (t *multiWriter) Write(p []byte) (n int, err error) {
 	return len(p), nil
 }
 
+var _ stringWriter = (*multiWriter)(nil)
+
+func (t *multiWriter) WriteString(s string) (n int, err error) {
+	var p []byte // lazily initialized if/when needed
+	for _, w := range t.writers {
+		if sw, ok := w.(stringWriter); ok {
+			n, err = sw.WriteString(s)
+		} else {
+			if p == nil {
+				p = []byte(s)
+			}
+			n, err = w.Write(p)
+		}
+		if err != nil {
+			return
+		}
+		if n != len(s) {
+			err = ErrShortWrite
+			return
+		}
+	}
+	return len(s), nil
+}
+
 // MultiWriter creates a writer that duplicates its writes to all the
 // provided writers, similar to the Unix tee(1) command.
 func MultiWriter(writers ...Writer) Writer {
diff --git a/src/io/multi_test.go b/src/io/multi_test.go
index 56c6769..e80592e 100644
--- a/src/io/multi_test.go
+++ b/src/io/multi_test.go
@@ -62,8 +62,59 @@ func TestMultiReader(t *testing.T) {
 }
 
 func TestMultiWriter(t *testing.T) {
-	sha1 := sha1.New()
 	sink := new(bytes.Buffer)
+	// Hide bytes.Buffer's WriteString method:
+	testMultiWriter(t, struct {
+		Writer
+		fmt.Stringer
+	}{sink, sink})
+}
+
+func TestMultiWriter_String(t *testing.T) {
+	testMultiWriter(t, new(bytes.Buffer))
+}
+
+// test that a multiWriter.WriteString calls results in at most 1 allocation,
+// even if multiple targets don't support WriteString.
+func TestMultiWriter_WriteStringSingleAlloc(t *testing.T) {
+	var sink1, sink2 bytes.Buffer
+	type simpleWriter struct { // hide bytes.Buffer's WriteString
+		Writer
+	}
+	mw := MultiWriter(simpleWriter{&sink1}, simpleWriter{&sink2})
+	allocs := int(testing.AllocsPerRun(1000, func() {
+		WriteString(mw, "foo")
+	}))
+	if allocs != 1 {
+		t.Errorf("num allocations = %d; want 1", allocs)
+	}
+}
+
+type writeStringChecker struct{ called bool }
+
+func (c *writeStringChecker) WriteString(s string) (n int, err error) {
+	c.called = true
+	return len(s), nil
+}
+
+func (c *writeStringChecker) Write(p []byte) (n int, err error) {
+	return len(p), nil
+}
+
+func TestMultiWriter_StringCheckCall(t *testing.T) {
+	var c writeStringChecker
+	mw := MultiWriter(&c)
+	WriteString(mw, "foo")
+	if !c.called {
+		t.Error("did not see WriteString call to writeStringChecker")
+	}
+}
+
+func testMultiWriter(t *testing.T, sink interface {
+	Writer
+	fmt.Stringer
+}) {
+	sha1 := sha1.New()
 	mw := MultiWriter(sha1, sink)
 
 	sourceString := "My input text."
diff --git a/src/log/syslog/doc.go b/src/log/syslog/doc.go
index 54e76ed..dfcc2dd 100644
--- a/src/log/syslog/doc.go
+++ b/src/log/syslog/doc.go
@@ -9,10 +9,18 @@
 // Only one call to Dial is necessary. On write failures,
 // the syslog client will attempt to reconnect to the server
 // and write again.
+//
+// The syslog package is frozen and not accepting new features.
+// Some external packages provide more functionality. See:
+//
+//   https://godoc.org/?q=syslog
 package syslog
 
-// BUG(brainman): This package is not implemented on Windows yet.
+// BUG(brainman): This package is not implemented on Windows. As the
+// syslog package is frozen, Windows users are encouraged to
+// use a package outside of the standard library. For background,
+// see https://golang.org/issue/1108.
 
-// BUG(akumar): This package is not implemented on Plan 9 yet.
+// BUG(akumar): This package is not implemented on Plan 9.
 
-// BUG(minux): This package is not implemented on NaCl (Native Client) yet.
+// BUG(minux): This package is not implemented on NaCl (Native Client).
diff --git a/src/log/syslog/syslog_test.go b/src/log/syslog/syslog_test.go
index 85aec53..52363f9 100644
--- a/src/log/syslog/syslog_test.go
+++ b/src/log/syslog/syslog_test.go
@@ -47,6 +47,22 @@ func runPktSyslog(c net.PacketConn, done chan<- string) {
 
 var crashy = false
 
+func testableNetwork(network string) bool {
+	switch network {
+	case "unix", "unixgram":
+		switch runtime.GOOS {
+		case "darwin":
+			switch runtime.GOARCH {
+			case "arm", "arm64":
+				return false
+			}
+		case "android":
+			return false
+		}
+	}
+	return true
+}
+
 func runStreamSyslog(l net.Listener, done chan<- string, wg *sync.WaitGroup) {
 	for {
 		var c net.Conn
@@ -119,12 +135,10 @@ func startServer(n, la string, done chan<- string) (addr string, sock io.Closer,
 
 func TestWithSimulated(t *testing.T) {
 	msg := "Test 123"
-	transport := []string{"unix", "unixgram", "udp", "tcp"}
-
-	if runtime.GOOS == "darwin" {
-		switch runtime.GOARCH {
-		case "arm", "arm64":
-			transport = []string{"udp", "tcp"}
+	var transport []string
+	for _, n := range []string{"unix", "unixgram", "udp", "tcp"} {
+		if testableNetwork(n) {
+			transport = append(transport, n)
 		}
 	}
 
@@ -150,14 +164,11 @@ func TestWithSimulated(t *testing.T) {
 }
 
 func TestFlap(t *testing.T) {
-	if runtime.GOOS == "darwin" {
-		switch runtime.GOARCH {
-		case "arm", "arm64":
-			t.Skipf("skipping on %s/%s", runtime.GOOS, runtime.GOARCH)
-		}
+	net := "unix"
+	if !testableNetwork(net) {
+		t.Skipf("skipping on %s/%s; 'unix' is not supported", runtime.GOOS, runtime.GOARCH)
 	}
 
-	net := "unix"
 	done := make(chan string)
 	addr, sock, srvWG := startServer(net, "", done)
 	defer srvWG.Wait()
@@ -321,10 +332,10 @@ func TestConcurrentReconnect(t *testing.T) {
 	const N = 10
 	const M = 100
 	net := "unix"
-	if runtime.GOOS == "darwin" {
-		switch runtime.GOARCH {
-		case "arm", "arm64":
-			net = "tcp"
+	if !testableNetwork(net) {
+		net = "tcp"
+		if !testableNetwork(net) {
+			t.Skipf("skipping on %s/%s; neither 'unix' or 'tcp' is supported", runtime.GOOS, runtime.GOARCH)
 		}
 	}
 	done := make(chan string, N*M)
diff --git a/src/make.bash b/src/make.bash
index f17648a..2531ca4 100755
--- a/src/make.bash
+++ b/src/make.bash
@@ -44,8 +44,7 @@
 # This is used by cgo. Default is CXX, or, if that is not set, 
 # "g++" or "clang++".
 #
-# GO_DISTFLAGS: extra flags to provide to "dist bootstrap". Use "-s"
-# to build a statically linked toolchain.
+# GO_DISTFLAGS: extra flags to provide to "dist bootstrap".
 
 set -e
 if [ ! -f run.bash ]; then
@@ -116,6 +115,12 @@ GOROOT_BOOTSTRAP=${GOROOT_BOOTSTRAP:-$HOME/go1.4}
 if [ ! -x "$GOROOT_BOOTSTRAP/bin/go" ]; then
 	echo "ERROR: Cannot find $GOROOT_BOOTSTRAP/bin/go." >&2
 	echo "Set \$GOROOT_BOOTSTRAP to a working Go tree >= Go 1.4." >&2
+	exit 1
+fi
+if [ "$GOROOT_BOOTSTRAP" == "$GOROOT" ]; then
+	echo "ERROR: \$GOROOT_BOOTSTRAP must not be set to \$GOROOT" >&2
+	echo "Set \$GOROOT_BOOTSTRAP to a working Go tree >= Go 1.4." >&2
+	exit 1
 fi
 rm -f cmd/dist/dist
 GOROOT="$GOROOT_BOOTSTRAP" GOOS="" GOARCH="" "$GOROOT_BOOTSTRAP/bin/go" build -o cmd/dist/dist ./cmd/dist
diff --git a/src/math/abs.go b/src/math/abs.go
index bc41a6d..924ee7c 100644
--- a/src/math/abs.go
+++ b/src/math/abs.go
@@ -9,13 +9,14 @@ package math
 // Special cases are:
 //	Abs(±Inf) = +Inf
 //	Abs(NaN) = NaN
-func Abs(x float64) float64
-
-func abs(x float64) float64 {
-	switch {
-	case x < 0:
+func Abs(x float64) float64 {
+	// TODO: once golang.org/issue/13095 is fixed, change this to:
+	// return Float64frombits(Float64bits(x) &^ (1 << 63))
+	// But for now, this generates better code and can also be inlined:
+	if x < 0 {
 		return -x
-	case x == 0:
+	}
+	if x == 0 {
 		return 0 // return correctly abs(-0)
 	}
 	return x
diff --git a/src/math/abs_386.s b/src/math/abs_386.s
deleted file mode 100644
index f30a439..0000000
--- a/src/math/abs_386.s
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2010 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 Abs(x float64) float64
-TEXT ·Abs(SB),NOSPLIT,$0
-	FMOVD   x+0(FP), F0  // F0=x
-	FABS                 // F0=|x|
-	FMOVDP  F0, ret+8(FP)
-	RET
diff --git a/src/math/abs_amd64.s b/src/math/abs_amd64.s
deleted file mode 100644
index 0424eb5..0000000
--- a/src/math/abs_amd64.s
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2010 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 Abs(x float64) float64
-TEXT ·Abs(SB),NOSPLIT,$0
-	MOVQ   $(1<<63), BX
-	MOVQ   BX, X0 // movsd $(-0.0), x0
-	MOVSD  x+0(FP), X1
-	ANDNPD X1, X0
-	MOVSD  X0, ret+8(FP)
-	RET
diff --git a/src/math/abs_amd64p32.s b/src/math/abs_amd64p32.s
deleted file mode 100644
index 08c8c6b..0000000
--- a/src/math/abs_amd64p32.s
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright 2013 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 "abs_amd64.s"
diff --git a/src/math/abs_arm.s b/src/math/abs_arm.s
deleted file mode 100644
index bfa77eb..0000000
--- a/src/math/abs_arm.s
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2011 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"
-
-TEXT ·Abs(SB),NOSPLIT,$0
-	MOVW	x_lo+0(FP), R0
-	MOVW	x_hi+4(FP), R1
-	AND 	$((1<<31)-1), R1
-	MOVW	R0, ret_lo+8(FP)
-	MOVW	R1, ret_hi+12(FP)
-	RET
diff --git a/src/math/abs_arm64.s b/src/math/abs_arm64.s
deleted file mode 100644
index d8f9382..0000000
--- a/src/math/abs_arm64.s
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2011 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"
-
-TEXT ·Abs(SB),NOSPLIT,$0-16
-	FMOVD	x+0(FP), F3
-	FABSD	F3, F3
-	FMOVD	F3, ret+8(FP)
-	RET
diff --git a/src/math/abs_ppc64x.s b/src/math/abs_ppc64x.s
deleted file mode 100644
index 06effb4..0000000
--- a/src/math/abs_ppc64x.s
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2011 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.
-
-// +build ppc64 ppc64le
-
-#include "textflag.h"
-
-TEXT ·Abs(SB),NOSPLIT,$0-16
-	MOVD	x+0(FP), R3
-	MOVD 	$((1<<63)-1), R4
-	AND	R4, R3
-	MOVD	R3, ret+8(FP)
-	RET
diff --git a/src/math/all_test.go b/src/math/all_test.go
index e18e45e..968a7b1 100644
--- a/src/math/all_test.go
+++ b/src/math/all_test.go
@@ -234,6 +234,18 @@ var expm1 = []float64{
 	1.842068661871398836913874273e-02,
 	-8.3193870863553801814961137573e-02,
 }
+var expm1Large = []float64{
+	4.2031418113550844e+21,
+	4.0690789717473863e+33,
+	-0.9372627915981363e+00,
+	-1.0,
+	7.077694784145933e+41,
+	5.117936223839153e+12,
+	5.124137759001189e+22,
+	7.03546003972584e+11,
+	8.456921800389698e+07,
+	-1.0,
+}
 var exp2 = []float64{
 	3.1537839463286288034313104e+01,
 	2.1361549283756232296144849e+02,
@@ -447,7 +459,7 @@ var log2 = []float64{
 var modf = [][2]float64{
 	{4.0000000000000000e+00, 9.7901192488367350108546816e-01},
 	{7.0000000000000000e+00, 7.3887247457810456552351752e-01},
-	{0.0000000000000000e+00, -2.7688005719200159404635997e-01},
+	{Copysign(0, -1), -2.7688005719200159404635997e-01},
 	{-5.0000000000000000e+00, -1.060361827107492160848778e-02},
 	{9.0000000000000000e+00, 6.3629370719841737980004837e-01},
 	{2.0000000000000000e+00, 9.2637723924396464525443662e-01},
@@ -1356,12 +1368,14 @@ var log1pSC = []float64{
 
 var vfmodfSC = []float64{
 	Inf(-1),
+	Copysign(0, -1),
 	Inf(1),
 	NaN(),
 }
 var modfSC = [][2]float64{
 	{Inf(-1), NaN()}, // [2]float64{Copysign(0, -1), Inf(-1)},
-	{Inf(1), NaN()},  // [2]float64{0, Inf(1)},
+	{Copysign(0, -1), Copysign(0, -1)},
+	{Inf(1), NaN()}, // [2]float64{0, Inf(1)},
 	{NaN(), NaN()},
 }
 
@@ -1609,6 +1623,7 @@ var vfsqrtSC = []float64{
 	0,
 	Inf(1),
 	NaN(),
+	Float64frombits(2), // subnormal; see https://golang.org/issue/13013
 }
 var sqrtSC = []float64{
 	NaN(),
@@ -1617,6 +1632,7 @@ var sqrtSC = []float64{
 	0,
 	Inf(1),
 	NaN(),
+	3.1434555694052576e-162,
 }
 
 var vftanhSC = []float64{
@@ -1983,6 +1999,12 @@ func TestExpm1(t *testing.T) {
 			t.Errorf("Expm1(%g) = %g, want %g", a, f, expm1[i])
 		}
 	}
+	for i := 0; i < len(vf); i++ {
+		a := vf[i] * 10
+		if f := Expm1(a); !close(expm1Large[i], f) {
+			t.Errorf("Expm1(%g) = %g, want %g", a, f, expm1Large[i])
+		}
+	}
 	for i := 0; i < len(vfexpm1SC); i++ {
 		if f := Expm1(vfexpm1SC[i]); !alike(expm1SC[i], f) {
 			t.Errorf("Expm1(%g) = %g, want %g", vfexpm1SC[i], f, expm1SC[i])
diff --git a/src/math/big/arith_mips64x.s b/src/math/big/arith_mips64x.s
new file mode 100644
index 0000000..f9288fc
--- /dev/null
+++ b/src/math/big/arith_mips64x.s
@@ -0,0 +1,46 @@
+// Copyright 2013 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.
+
+// +build !math_big_pure_go,mips64 !math_big_pure_go,mips64le
+
+#include "textflag.h"
+
+// This file provides fast assembly versions for the elementary
+// arithmetic operations on vectors implemented in arith.go.
+
+TEXT ·mulWW(SB),NOSPLIT,$0
+	JMP ·mulWW_g(SB)
+
+TEXT ·divWW(SB),NOSPLIT,$0
+	JMP ·divWW_g(SB)
+
+TEXT ·addVV(SB),NOSPLIT,$0
+	JMP ·addVV_g(SB)
+
+TEXT ·subVV(SB),NOSPLIT,$0
+	JMP ·subVV_g(SB)
+
+TEXT ·addVW(SB),NOSPLIT,$0
+	JMP ·addVW_g(SB)
+
+TEXT ·subVW(SB),NOSPLIT,$0
+	JMP ·subVW_g(SB)
+
+TEXT ·shlVU(SB),NOSPLIT,$0
+	JMP ·shlVU_g(SB)
+
+TEXT ·shrVU(SB),NOSPLIT,$0
+	JMP ·shrVU_g(SB)
+
+TEXT ·mulAddVWW(SB),NOSPLIT,$0
+	JMP ·mulAddVWW_g(SB)
+
+TEXT ·addMulVVW(SB),NOSPLIT,$0
+	JMP ·addMulVVW_g(SB)
+
+TEXT ·divWVW(SB),NOSPLIT,$0
+	JMP ·divWVW_g(SB)
+
+TEXT ·bitLen(SB),NOSPLIT,$0
+	JMP ·bitLen_g(SB)
diff --git a/src/math/big/decimal.go b/src/math/big/decimal.go
index 2595e5f..2c0c9da 100644
--- a/src/math/big/decimal.go
+++ b/src/math/big/decimal.go
@@ -20,7 +20,7 @@
 package big
 
 // A decimal represents an unsigned floating-point number in decimal representation.
-// The value of a non-zero decimal x is x.mant * 10 ** x.exp with 0.5 <= x.mant < 1,
+// The value of a non-zero decimal d is d.mant * 10**d.exp with 0.5 <= d.mant < 1,
 // with the most-significant mantissa digit at index 0. For the zero decimal, the
 // mantissa length and exponent are 0.
 // The zero value for decimal represents a ready-to-use 0.0.
@@ -29,6 +29,14 @@ type decimal struct {
 	exp  int    // exponent
 }
 
+// at returns the i'th mantissa digit, starting with the most significant digit at 0.
+func (d *decimal) at(i int) byte {
+	if 0 <= i && i < len(d.mant) {
+		return d.mant[i]
+	}
+	return '0'
+}
+
 // Maximum shift amount that can be done in one pass without overflow.
 // A Word has _W bits and (1<<maxShift - 1)*10 + 9 must fit into Word.
 const maxShift = _W - 4
@@ -72,7 +80,7 @@ func (x *decimal) init(m nat, shift int) {
 	}
 
 	// Convert mantissa into decimal representation.
-	s := m.decimalString() // TODO(gri) avoid string conversion here
+	s := m.utoa(10)
 	n := len(s)
 	x.exp = n
 	// Trim trailing zeros; instead the exponent is tracking
@@ -92,12 +100,6 @@ func (x *decimal) init(m nat, shift int) {
 	}
 }
 
-// Possibly optimization: The current implementation of nat.string takes
-// a charset argument. When a right shift is needed, we could provide
-// "\x00\x01...\x09" instead of "012..9" (as in nat.decimalString) and
-// avoid the repeated +'0' and -'0' operations in decimal.shr (and do a
-// single +'0' pass at the end).
-
 // shr implements x >> s, for s <= maxShift.
 func shr(x *decimal, s uint) {
 	// Division by 1<<s using shift-and-subtract algorithm.
diff --git a/src/math/big/decimal_test.go b/src/math/big/decimal_test.go
index 81e022a..15bdb18 100644
--- a/src/math/big/decimal_test.go
+++ b/src/math/big/decimal_test.go
@@ -104,3 +104,13 @@ func TestDecimalRounding(t *testing.T) {
 		}
 	}
 }
+
+func BenchmarkDecimalConversion(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for shift := -100; shift <= +100; shift++ {
+			var d decimal
+			d.init(natOne, shift)
+			d.String()
+		}
+	}
+}
diff --git a/src/math/big/doc.go b/src/math/big/doc.go
new file mode 100644
index 0000000..a3c2375
--- /dev/null
+++ b/src/math/big/doc.go
@@ -0,0 +1,99 @@
+// Copyright 2009 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 big implements arbitrary-precision arithmetic (big numbers).
+The following numeric types are supported:
+
+	Int    signed integers
+	Rat    rational numbers
+	Float  floating-point numbers
+
+The zero value for an Int, Rat, or Float correspond to 0. Thus, new
+values can be declared in the usual ways and denote 0 without further
+initialization:
+
+	var x Int        // &x is an *Int of value 0
+	var r = &Rat{}   // r is a *Rat of value 0
+	y := new(Float)  // y is a *Float of value 0
+
+Alternatively, new values can be allocated and initialized with factory
+functions of the form:
+
+	func NewT(v V) *T
+
+For instance, NewInt(x) returns an *Int set to the value of the int64
+argument x, NewRat(a, b) returns a *Rat set to the fraction a/b where
+a and b are int64 values, and NewFloat(f) returns a *Float initialized
+to the float64 argument f. More flexibility is provided with explicit
+setters, for instance:
+
+	var z1 Int
+	z1.SetUint64(123)                 // z1 := 123
+	z2 := new(Rat).SetFloat64(1.2)    // z2 := 6/5
+	z3 := new(Float).SetInt(z1)       // z3 := 123.0
+
+Setters, numeric operations and predicates are represented as methods of
+the form:
+
+	func (z *T) SetV(v V) *T          // z = v
+	func (z *T) Unary(x *T) *T        // z = unary x
+	func (z *T) Binary(x, y *T) *T    // z = x binary y
+	func (x *T) Pred() P              // p = pred(x)
+
+with T one of Int, Rat, or Float. For unary and binary operations, the
+result is the receiver (usually named z in that case; see below); if it
+is one of the operands x or y it may be safely overwritten (and its memory
+reused).
+
+Arithmetic expressions are typically written as a sequence of individual
+method calls, with each call corresponding to an operation. The receiver
+denotes the result and the method arguments are the operation's operands.
+For instance, given three *Int values a, b and c, the invocation
+
+	c.Add(a, b)
+
+computes the sum a + b and stores the result in c, overwriting whatever
+value was held in c before. Unless specified otherwise, operations permit
+aliasing of parameters, so it is perfectly ok to write
+
+	sum.Add(sum, x)
+
+to accumulate values x in a sum.
+
+(By always passing in a result value via the receiver, memory use can be
+much better controlled. Instead of having to allocate new memory for each
+result, an operation can reuse the space allocated for the result value,
+and overwrite that value with the new result in the process.)
+
+Notational convention: Incoming method parameters (including the receiver)
+are named consistently in the API to clarify their use. Incoming operands
+are usually named x, y, a, b, and so on, but never z. A parameter specifying
+the result is named z (typically the receiver).
+
+For instance, the arguments for (*Int).Add are named x and y, and because
+the receiver specifies the result destination, it is called z:
+
+	func (z *Int) Add(x, y *Int) *Int
+
+Methods of this form typically return the incoming receiver as well, to
+enable simple call chaining.
+
+Methods which don't require a result value to be passed in (for instance,
+Int.Sign), simply return the result. In this case, the receiver is typically
+the first operand, named x:
+
+	func (x *Int) Sign() int
+
+Various methods support conversions between strings and corresponding
+numeric values, and vice versa: *Int, *Rat, and *Float values implement
+the Stringer interface for a (default) string representation of the value,
+but also provide SetString methods to initialize a value from a string in
+a variety of supported formats (see the respective SetString documentation).
+
+Finally, *Int, *Rat, and *Float satisfy the fmt package's Scanner interface
+for scanning and (except for *Rat) the Formatter interface for formatted
+printing.
+*/
+package big
diff --git a/src/math/big/example_rat_test.go b/src/math/big/example_rat_test.go
new file mode 100644
index 0000000..a971170
--- /dev/null
+++ b/src/math/big/example_rat_test.go
@@ -0,0 +1,65 @@
+// Copyright 2015 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 big_test
+
+import (
+	"fmt"
+	"math/big"
+)
+
+// Use the classic continued fraction for e
+//     e = [1; 0, 1, 1, 2, 1, 1, ... 2n, 1, 1, ...]
+// i.e., for the nth term, use
+//     1          if   n mod 3 != 1
+//  (n-1)/3 * 2   if   n mod 3 == 1
+func recur(n, lim int64) *big.Rat {
+	term := new(big.Rat)
+	if n%3 != 1 {
+		term.SetInt64(1)
+	} else {
+		term.SetInt64((n - 1) / 3 * 2)
+	}
+
+	if n > lim {
+		return term
+	}
+
+	// Directly initialize frac as the fractional
+	// inverse of the result of recur.
+	frac := new(big.Rat).Inv(recur(n+1, lim))
+
+	return term.Add(term, frac)
+}
+
+// This example demonstrates how to use big.Rat to compute the
+// first 15 terms in the sequence of rational convergents for
+// the constant e (base of natural logarithm).
+func Example_eConvergents() {
+	for i := 1; i <= 15; i++ {
+		r := recur(0, int64(i))
+
+		// Print r both as a fraction and as a floating-point number.
+		// Since big.Rat implements fmt.Formatter, we can use %-13s to
+		// get a left-aligned string representation of the fraction.
+		fmt.Printf("%-13s = %s\n", r, r.FloatString(8))
+	}
+
+	// Output:
+	// 2/1           = 2.00000000
+	// 3/1           = 3.00000000
+	// 8/3           = 2.66666667
+	// 11/4          = 2.75000000
+	// 19/7          = 2.71428571
+	// 87/32         = 2.71875000
+	// 106/39        = 2.71794872
+	// 193/71        = 2.71830986
+	// 1264/465      = 2.71827957
+	// 1457/536      = 2.71828358
+	// 2721/1001     = 2.71828172
+	// 23225/8544    = 2.71828184
+	// 25946/9545    = 2.71828182
+	// 49171/18089   = 2.71828183
+	// 517656/190435 = 2.71828183
+}
diff --git a/src/math/big/float.go b/src/math/big/float.go
index d7aa895..b1c748c 100644
--- a/src/math/big/float.go
+++ b/src/math/big/float.go
@@ -124,7 +124,7 @@ const (
 // rounding error is described by the Float's Accuracy.
 type RoundingMode byte
 
-// The following rounding modes are supported.
+// These constants define supported rounding modes.
 const (
 	ToNearestEven RoundingMode = iota // == IEEE 754-2008 roundTiesToEven
 	ToNearestAway                     // == IEEE 754-2008 roundTiesToAway
@@ -298,7 +298,7 @@ func (z *Float) setExpAndRound(exp int64, sbit uint) {
 // not require 0.5 <= |mant| < 1.0. Specifically:
 //
 //	mant := new(Float)
-//	new(Float).SetMantExp(mant, x.SetMantExp(mant)).Cmp(x).Eql() is true
+//	new(Float).SetMantExp(mant, x.MantExp(mant)).Cmp(x) == 0
 //
 // Special cases are:
 //
@@ -1123,7 +1123,7 @@ func (x *Float) Int(z *Int) (*Int, Accuracy) {
 
 // Rat returns the rational number corresponding to x;
 // or nil if x is an infinity.
-// The result is Exact is x is not an Inf.
+// The result is Exact if x is not an Inf.
 // If a non-nil *Rat argument z is provided, Rat stores
 // the result in z instead of allocating a new Rat.
 func (x *Float) Rat(z *Rat) (*Rat, Accuracy) {
@@ -1272,7 +1272,7 @@ func (z *Float) usub(x, y *Float) {
 		ex = ey
 	}
 
-	// operands may have cancelled each other out
+	// operands may have canceled each other out
 	if len(z.mant) == 0 {
 		z.acc = Exact
 		z.form = zero
diff --git a/src/math/big/floatconv.go b/src/math/big/floatconv.go
index 4a070ca..37d5c06 100644
--- a/src/math/big/floatconv.go
+++ b/src/math/big/floatconv.go
@@ -72,37 +72,46 @@ func (z *Float) scan(r io.ByteScanner, base int) (f *Float, b int, err error) {
 	// ebase**exp. Finally, mantissa normalization (shift left) requires
 	// a correcting multiplication by 2**(-shiftcount). Multiplications
 	// are commutative, so we can apply them in any order as long as there
-	// is no loss of precision. We only have powers of 2 and 10; keep
-	// track via separate exponents exp2 and exp10.
+	// is no loss of precision. We only have powers of 2 and 10, and
+	// we split powers of 10 into the product of the same powers of
+	// 2 and 5. This reduces the size of the multiplication factor
+	// needed for base-10 exponents.
 
-	// normalize mantissa and get initial binary exponent
-	var exp2 = int64(len(z.mant))*_W - fnorm(z.mant)
+	// normalize mantissa and determine initial exponent contributions
+	exp2 := int64(len(z.mant))*_W - fnorm(z.mant)
+	exp5 := int64(0)
 
 	// determine binary or decimal exponent contribution of decimal point
-	var exp10 int64
 	if fcount < 0 {
 		// The mantissa has a "decimal" point ddd.dddd; and
 		// -fcount is the number of digits to the right of '.'.
 		// Adjust relevant exponent accodingly.
+		d := int64(fcount)
 		switch b {
-		case 16:
-			fcount *= 4 // hexadecimal digits are 4 bits each
-			fallthrough
+		case 10:
+			exp5 = d
+			fallthrough // 10**e == 5**e * 2**e
 		case 2:
-			exp2 += int64(fcount)
-		default: // b == 10
-			exp10 = int64(fcount)
+			exp2 += d
+		case 16:
+			exp2 += d * 4 // hexadecimal digits are 4 bits each
+		default:
+			panic("unexpected mantissa base")
 		}
-		// we don't need fcount anymore
+		// fcount consumed - not needed anymore
 	}
 
 	// take actual exponent into account
-	if ebase == 2 {
+	switch ebase {
+	case 10:
+		exp5 += exp
+		fallthrough
+	case 2:
 		exp2 += exp
-	} else { // ebase == 10
-		exp10 += exp
+	default:
+		panic("unexpected exponent base")
 	}
-	// we don't need exp anymore
+	// exp consumed - not needed anymore
 
 	// apply 2**exp2
 	if MinExp <= exp2 && exp2 <= MaxExp {
@@ -115,49 +124,76 @@ func (z *Float) scan(r io.ByteScanner, base int) (f *Float, b int, err error) {
 		return
 	}
 
-	if exp10 == 0 {
-		// no decimal exponent to consider
+	if exp5 == 0 {
+		// no decimal exponent contribution
 		z.round(0)
 		return
 	}
-	// exp10 != 0
+	// exp5 != 0
 
-	// apply 10**exp10
+	// apply 5**exp5
 	p := new(Float).SetPrec(z.Prec() + 64) // use more bits for p -- TODO(gri) what is the right number?
-	if exp10 < 0 {
-		z.uquo(z, p.pow10(-exp10))
+	if exp5 < 0 {
+		z.Quo(z, p.pow5(uint64(-exp5)))
 	} else {
-		z.umul(z, p.pow10(exp10))
+		z.Mul(z, p.pow5(uint64(exp5)))
 	}
 
 	return
 }
 
-// These powers of 10 can be represented exactly as a float64.
-var pow10tab = [...]float64{
-	1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
-	1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+// These powers of 5 fit into a uint64.
+//
+//	for p, q := uint64(0), uint64(1); p < q; p, q = q, q*5 {
+//		fmt.Println(q)
+//	}
+//
+var pow5tab = [...]uint64{
+	1,
+	5,
+	25,
+	125,
+	625,
+	3125,
+	15625,
+	78125,
+	390625,
+	1953125,
+	9765625,
+	48828125,
+	244140625,
+	1220703125,
+	6103515625,
+	30517578125,
+	152587890625,
+	762939453125,
+	3814697265625,
+	19073486328125,
+	95367431640625,
+	476837158203125,
+	2384185791015625,
+	11920928955078125,
+	59604644775390625,
+	298023223876953125,
+	1490116119384765625,
+	7450580596923828125,
 }
 
-// pow10 sets z to 10**n and returns z.
+// pow5 sets z to 5**n and returns z.
 // n must not be negative.
-func (z *Float) pow10(n int64) *Float {
-	if n < 0 {
-		panic("pow10 called with negative argument")
-	}
-
-	const m = int64(len(pow10tab) - 1)
+func (z *Float) pow5(n uint64) *Float {
+	const m = uint64(len(pow5tab) - 1)
 	if n <= m {
-		return z.SetFloat64(pow10tab[n])
+		return z.SetUint64(pow5tab[n])
 	}
 	// n > m
 
-	z.SetFloat64(pow10tab[m])
+	z.SetUint64(pow5tab[m])
 	n -= m
 
 	// use more bits for f than for z
 	// TODO(gri) what is the right number?
-	f := new(Float).SetPrec(z.Prec() + 64).SetInt64(10)
+	f := new(Float).SetPrec(z.Prec() + 64).SetUint64(5)
 
 	for n > 0 {
 		if n&1 != 0 {
diff --git a/src/math/big/floatconv_test.go b/src/math/big/floatconv_test.go
index 4f23953..b6f9993 100644
--- a/src/math/big/floatconv_test.go
+++ b/src/math/big/floatconv_test.go
@@ -139,6 +139,8 @@ func TestFloatSetFloat64String(t *testing.T) {
 	}
 }
 
+func fdiv(a, b float64) float64 { return a / b }
+
 const (
 	below1e23 = 99999999999999974834176
 	above1e23 = 100000000000000008388608
@@ -187,11 +189,11 @@ func TestFloat64Text(t *testing.T) {
 		{1, 'e', 5, "1.00000e+00"},
 		{1, 'f', 5, "1.00000"},
 		{1, 'g', 5, "1"},
-		// {1, 'g', -1, "1"},
-		// {20, 'g', -1, "20"},
-		// {1234567.8, 'g', -1, "1.2345678e+06"},
-		// {200000, 'g', -1, "200000"},
-		// {2000000, 'g', -1, "2e+06"},
+		{1, 'g', -1, "1"},
+		{20, 'g', -1, "20"},
+		{1234567.8, 'g', -1, "1.2345678e+06"},
+		{200000, 'g', -1, "200000"},
+		{2000000, 'g', -1, "2e+06"},
 
 		// g conversion and zero suppression
 		{400, 'g', 2, "4e+02"},
@@ -207,22 +209,22 @@ func TestFloat64Text(t *testing.T) {
 		{0, 'e', 5, "0.00000e+00"},
 		{0, 'f', 5, "0.00000"},
 		{0, 'g', 5, "0"},
-		// {0, 'g', -1, "0"},
+		{0, 'g', -1, "0"},
 
 		{-1, 'e', 5, "-1.00000e+00"},
 		{-1, 'f', 5, "-1.00000"},
 		{-1, 'g', 5, "-1"},
-		// {-1, 'g', -1, "-1"},
+		{-1, 'g', -1, "-1"},
 
 		{12, 'e', 5, "1.20000e+01"},
 		{12, 'f', 5, "12.00000"},
 		{12, 'g', 5, "12"},
-		// {12, 'g', -1, "12"},
+		{12, 'g', -1, "12"},
 
 		{123456700, 'e', 5, "1.23457e+08"},
 		{123456700, 'f', 5, "123456700.00000"},
 		{123456700, 'g', 5, "1.2346e+08"},
-		// {123456700, 'g', -1, "1.234567e+08"},
+		{123456700, 'g', -1, "1.234567e+08"},
 
 		{1.2345e6, 'e', 5, "1.23450e+06"},
 		{1.2345e6, 'f', 5, "1234500.00000"},
@@ -232,36 +234,38 @@ func TestFloat64Text(t *testing.T) {
 		{1e23, 'f', 17, "99999999999999991611392.00000000000000000"},
 		{1e23, 'g', 17, "9.9999999999999992e+22"},
 
-		// {1e23, 'e', -1, "1e+23"},
-		// {1e23, 'f', -1, "100000000000000000000000"},
-		// {1e23, 'g', -1, "1e+23"},
+		{1e23, 'e', -1, "1e+23"},
+		{1e23, 'f', -1, "100000000000000000000000"},
+		{1e23, 'g', -1, "1e+23"},
 
 		{below1e23, 'e', 17, "9.99999999999999748e+22"},
 		{below1e23, 'f', 17, "99999999999999974834176.00000000000000000"},
 		{below1e23, 'g', 17, "9.9999999999999975e+22"},
 
-		// {below1e23, 'e', -1, "9.999999999999997e+22"},
-		// {below1e23, 'f', -1, "99999999999999970000000"},
-		// {below1e23, 'g', -1, "9.999999999999997e+22"},
+		{below1e23, 'e', -1, "9.999999999999997e+22"},
+		{below1e23, 'f', -1, "99999999999999970000000"},
+		{below1e23, 'g', -1, "9.999999999999997e+22"},
 
 		{above1e23, 'e', 17, "1.00000000000000008e+23"},
 		{above1e23, 'f', 17, "100000000000000008388608.00000000000000000"},
-		// {above1e23, 'g', 17, "1.0000000000000001e+23"},
+		{above1e23, 'g', 17, "1.0000000000000001e+23"},
 
-		// {above1e23, 'e', -1, "1.0000000000000001e+23"},
-		// {above1e23, 'f', -1, "100000000000000010000000"},
-		// {above1e23, 'g', -1, "1.0000000000000001e+23"},
+		{above1e23, 'e', -1, "1.0000000000000001e+23"},
+		{above1e23, 'f', -1, "100000000000000010000000"},
+		{above1e23, 'g', -1, "1.0000000000000001e+23"},
 
-		// {fdiv(5e-304, 1e20), 'g', -1, "5e-324"},
-		// {fdiv(-5e-304, 1e20), 'g', -1, "-5e-324"},
+		{5e-304 / 1e20, 'g', -1, "5e-324"},
+		{-5e-304 / 1e20, 'g', -1, "-5e-324"},
+		{fdiv(5e-304, 1e20), 'g', -1, "5e-324"},   // avoid constant arithmetic
+		{fdiv(-5e-304, 1e20), 'g', -1, "-5e-324"}, // avoid constant arithmetic
 
-		// {32, 'g', -1, "32"},
-		// {32, 'g', 0, "3e+01"},
+		{32, 'g', -1, "32"},
+		{32, 'g', 0, "3e+01"},
 
-		// {100, 'x', -1, "%x"},
+		{100, 'x', -1, "%x"},
 
-		// {math.NaN(), 'g', -1, "NaN"},
-		// {-math.NaN(), 'g', -1, "NaN"},
+		// {math.NaN(), 'g', -1, "NaN"},  // Float doesn't support NaNs
+		// {-math.NaN(), 'g', -1, "NaN"}, // Float doesn't support NaNs
 		{math.Inf(0), 'g', -1, "+Inf"},
 		{math.Inf(-1), 'g', -1, "-Inf"},
 		{-math.Inf(0), 'g', -1, "-Inf"},
@@ -279,18 +283,24 @@ func TestFloat64Text(t *testing.T) {
 		{1.5, 'f', 0, "2"},
 
 		// http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
-		// {2.2250738585072012e-308, 'g', -1, "2.2250738585072014e-308"},
+		{2.2250738585072012e-308, 'g', -1, "2.2250738585072014e-308"},
 		// http://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/
-		// {2.2250738585072011e-308, 'g', -1, "2.225073858507201e-308"},
+		{2.2250738585072011e-308, 'g', -1, "2.225073858507201e-308"},
 
 		// Issue 2625.
 		{383260575764816448, 'f', 0, "383260575764816448"},
-		// {383260575764816448, 'g', -1, "3.8326057576481645e+17"},
+		{383260575764816448, 'g', -1, "3.8326057576481645e+17"},
 	} {
-		f := new(Float).SetFloat64(test.x)
+		// The test cases are from the strconv package which tests float64 values.
+		// When formatting values with prec = -1 (shortest representation),
+		// the actually available mantissa precision matters.
+		// For denormalized values, that precision is < 53 (SetFloat64 default).
+		// Compute and set the actual precision explicitly.
+		f := new(Float).SetPrec(actualPrec(test.x)).SetFloat64(test.x)
 		got := f.Text(test.format, test.prec)
 		if got != test.want {
 			t.Errorf("%v: got %s; want %s", test, got, test.want)
+			continue
 		}
 
 		if test.format == 'b' && test.x == 0 {
@@ -308,6 +318,15 @@ func TestFloat64Text(t *testing.T) {
 	}
 }
 
+// actualPrec returns the number of actually used mantissa bits.
+func actualPrec(x float64) uint {
+	if bits := math.Float64bits(x); x != 0 && bits&(0x7ff<<52) == 0 {
+		// x is denormalized
+		return 64 - nlz64(bits&(1<<52-1))
+	}
+	return 53
+}
+
 func TestFloatText(t *testing.T) {
 	for _, test := range []struct {
 		x      string
@@ -367,9 +386,19 @@ func TestFloatText(t *testing.T) {
 
 		// make sure "stupid" exponents don't stall the machine
 		{"1e1000000", 64, 'p', 0, "0x.88b3a28a05eade3ap+3321929"},
-		{"1e1000000000", 64, 'p', 0, "0x.ecc5f45aa573d3p+1538481529"},
+		{"1e646456992", 64, 'p', 0, "0x.e883a0c5c8c7c42ap+2147483644"},
+		{"1e646456993", 64, 'p', 0, "+Inf"},
+		{"1e1000000000", 64, 'p', 0, "+Inf"},
 		{"1e-1000000", 64, 'p', 0, "0x.efb4542cc8ca418ap-3321928"},
-		{"1e-1000000000", 64, 'p', 0, "0x.8a64dd983a4c7dabp-1538481528"},
+		{"1e-646456993", 64, 'p', 0, "0x.e17c8956983d9d59p-2147483647"},
+		{"1e-646456994", 64, 'p', 0, "0"},
+		{"1e-1000000000", 64, 'p', 0, "0"},
+
+		// minimum and maximum values
+		{"1p2147483646", 64, 'p', 0, "0x.8p+2147483647"},
+		{"0x.8p2147483647", 64, 'p', 0, "0x.8p+2147483647"},
+		{"0x.8p-2147483647", 64, 'p', 0, "0x.8p-2147483647"},
+		{"1p-2147483649", 64, 'p', 0, "0x.8p-2147483648"},
 
 		// TODO(gri) need tests for actual large Floats
 
@@ -438,9 +467,6 @@ func TestFloatFormat(t *testing.T) {
 		value  interface{} // float32, float64, or string (== 512bit *Float)
 		want   string
 	}{
-		// TODO(gri) uncomment the disabled 'g'/'G' formats
-		// 	     below once (*Float).Text supports prec < 0
-
 		// from fmt/fmt_test.go
 		{"%+.3e", 0.0, "+0.000e+00"},
 		{"%+.3e", 1.0, "+1.000e+00"},
@@ -471,9 +497,9 @@ func TestFloatFormat(t *testing.T) {
 		{"%f", 1234.5678e-8, "0.000012"},
 		{"%f", -7.0, "-7.000000"},
 		{"%f", -1e-9, "-0.000000"},
-		// {"%g", 1234.5678e3, "1.2345678e+06"},
-		// {"%g", float32(1234.5678e3), "1.2345678e+06"},
-		// {"%g", 1234.5678e-8, "1.2345678e-05"},
+		{"%g", 1234.5678e3, "1.2345678e+06"},
+		{"%g", float32(1234.5678e3), "1.2345678e+06"},
+		{"%g", 1234.5678e-8, "1.2345678e-05"},
 		{"%g", -7.0, "-7"},
 		{"%g", -1e-9, "-1e-09"},
 		{"%g", float32(-1e-9), "-1e-09"},
@@ -482,9 +508,9 @@ func TestFloatFormat(t *testing.T) {
 		{"%E", 1234.5678e-8, "1.234568E-05"},
 		{"%E", -7.0, "-7.000000E+00"},
 		{"%E", -1e-9, "-1.000000E-09"},
-		// {"%G", 1234.5678e3, "1.2345678E+06"},
-		// {"%G", float32(1234.5678e3), "1.2345678E+06"},
-		// {"%G", 1234.5678e-8, "1.2345678E-05"},
+		{"%G", 1234.5678e3, "1.2345678E+06"},
+		{"%G", float32(1234.5678e3), "1.2345678E+06"},
+		{"%G", 1234.5678e-8, "1.2345678E-05"},
 		{"%G", -7.0, "-7"},
 		{"%G", -1e-9, "-1E-09"},
 		{"%G", float32(-1e-9), "-1E-09"},
@@ -500,9 +526,9 @@ func TestFloatFormat(t *testing.T) {
 		{"%-20f", 1.23456789e3, "1234.567890         "},
 		{"%20.8f", 1.23456789e3, "       1234.56789000"},
 		{"%20.8f", 1.23456789e-3, "          0.00123457"},
-		// {"%g", 1.23456789e3, "1234.56789"},
-		// {"%g", 1.23456789e-3, "0.00123456789"},
-		// {"%g", 1.23456789e20, "1.23456789e+20"},
+		{"%g", 1.23456789e3, "1234.56789"},
+		{"%g", 1.23456789e-3, "0.00123456789"},
+		{"%g", 1.23456789e20, "1.23456789e+20"},
 		{"%20e", math.Inf(1), "                +Inf"},
 		{"%-20f", math.Inf(-1), "-Inf                "},
 
@@ -541,7 +567,6 @@ func TestFloatFormat(t *testing.T) {
 		{"%v", -1e-9, "-1e-09"},
 		{"%v", float32(-1e-9), "-1e-09"},
 		{"%010v", 0.0, "0000000000"},
-		{"%010v", 0.0, "0000000000"},
 
 		// *Float cases
 		{"%.20f", "1e-20", "0.00000000000000000001"},
@@ -571,3 +596,67 @@ func TestFloatFormat(t *testing.T) {
 		}
 	}
 }
+
+func BenchmarkParseFloatSmallExp(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, s := range []string{
+			"1e0",
+			"1e-1",
+			"1e-2",
+			"1e-3",
+			"1e-4",
+			"1e-5",
+			"1e-10",
+			"1e-20",
+			"1e-50",
+			"1e1",
+			"1e2",
+			"1e3",
+			"1e4",
+			"1e5",
+			"1e10",
+			"1e20",
+			"1e50",
+		} {
+			var x Float
+			_, _, err := x.Parse(s, 0)
+			if err != nil {
+				b.Fatalf("%s: %v", s, err)
+			}
+		}
+	}
+}
+
+func BenchmarkParseFloatLargeExp(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		for _, s := range []string{
+			"1e0",
+			"1e-10",
+			"1e-20",
+			"1e-30",
+			"1e-40",
+			"1e-50",
+			"1e-100",
+			"1e-500",
+			"1e-1000",
+			"1e-5000",
+			"1e-10000",
+			"1e10",
+			"1e20",
+			"1e30",
+			"1e40",
+			"1e50",
+			"1e100",
+			"1e500",
+			"1e1000",
+			"1e5000",
+			"1e10000",
+		} {
+			var x Float
+			_, _, err := x.Parse(s, 0)
+			if err != nil {
+				b.Fatalf("%s: %v", s, err)
+			}
+		}
+	}
+}
diff --git a/src/math/big/floatexample_test.go b/src/math/big/floatexample_test.go
index 358776e..fb799d5 100644
--- a/src/math/big/floatexample_test.go
+++ b/src/math/big/floatexample_test.go
@@ -109,3 +109,33 @@ func ExampleFloat_Cmp() {
 	// +Inf   1.2    1
 	// +Inf  +Inf    0
 }
+
+func ExampleRoundingMode() {
+	operands := []float64{2.6, 2.5, 2.1, -2.1, -2.5, -2.6}
+
+	fmt.Print("   x")
+	for mode := big.ToNearestEven; mode <= big.ToPositiveInf; mode++ {
+		fmt.Printf("  %s", mode)
+	}
+	fmt.Println()
+
+	for _, f64 := range operands {
+		fmt.Printf("%4g", f64)
+		for mode := big.ToNearestEven; mode <= big.ToPositiveInf; mode++ {
+			// sample operands above require 2 bits to represent mantissa
+			// set binary precision to 2 to round them to integer values
+			f := new(big.Float).SetPrec(2).SetMode(mode).SetFloat64(f64)
+			fmt.Printf("  %*g", len(mode.String()), f)
+		}
+		fmt.Println()
+	}
+
+	// Output:
+	//    x  ToNearestEven  ToNearestAway  ToZero  AwayFromZero  ToNegativeInf  ToPositiveInf
+	//  2.6              3              3       2             3              2              3
+	//  2.5              2              3       2             3              2              3
+	//  2.1              2              2       2             3              2              3
+	// -2.1             -2             -2      -2            -3             -3             -2
+	// -2.5             -2             -3      -2            -3             -3             -2
+	// -2.6             -3             -3      -2            -3             -3             -2
+}
diff --git a/src/math/big/floatmarsh.go b/src/math/big/floatmarsh.go
new file mode 100644
index 0000000..44987ee
--- /dev/null
+++ b/src/math/big/floatmarsh.go
@@ -0,0 +1,33 @@
+// Copyright 2015 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 file implements encoding/decoding of Floats.
+
+package big
+
+import "fmt"
+
+// MarshalText implements the encoding.TextMarshaler interface.
+// Only the Float value is marshaled (in full precision), other
+// attributes such as precision or accuracy are ignored.
+func (x *Float) MarshalText() (text []byte, err error) {
+	if x == nil {
+		return []byte("<nil>"), nil
+	}
+	var buf []byte
+	return x.Append(buf, 'g', -1), nil
+}
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface.
+// The result is rounded per the precision and rounding mode of z.
+// If z's precision is 0, it is changed to 64 before rounding takes
+// effect.
+func (z *Float) UnmarshalText(text []byte) error {
+	// TODO(gri): get rid of the []byte/string conversion
+	_, _, err := z.Parse(string(text), 0)
+	if err != nil {
+		err = fmt.Errorf("math/big: cannot unmarshal %q into a *big.Float (%v)", text, err)
+	}
+	return err
+}
diff --git a/src/math/big/floatmarsh_test.go b/src/math/big/floatmarsh_test.go
new file mode 100644
index 0000000..d7ef2fc
--- /dev/null
+++ b/src/math/big/floatmarsh_test.go
@@ -0,0 +1,54 @@
+// Copyright 2015 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 big
+
+import (
+	"encoding/json"
+	"testing"
+)
+
+var floatVals = []string{
+	"0",
+	"1",
+	"0.1",
+	"2.71828",
+	"1234567890",
+	"3.14e1234",
+	"3.14e-1234",
+	"0.738957395793475734757349579759957975985497e100",
+	"0.73895739579347546656564656573475734957975995797598589749859834759476745986795497e100",
+	"inf",
+	"Inf",
+}
+
+func TestFloatJSONEncoding(t *testing.T) {
+	for _, test := range floatVals {
+		for _, sign := range []string{"", "+", "-"} {
+			for _, prec := range []uint{0, 1, 2, 10, 53, 64, 100, 1000} {
+				x := sign + test
+				var tx Float
+				_, _, err := tx.SetPrec(prec).Parse(x, 0)
+				if err != nil {
+					t.Errorf("parsing of %s (prec = %d) failed (invalid test case): %v", x, prec, err)
+					continue
+				}
+				b, err := json.Marshal(&tx)
+				if err != nil {
+					t.Errorf("marshaling of %v (prec = %d) failed: %v", &tx, prec, err)
+					continue
+				}
+				var rx Float
+				rx.SetPrec(prec)
+				if err := json.Unmarshal(b, &rx); err != nil {
+					t.Errorf("unmarshaling of %v (prec = %d) failed: %v", &tx, prec, err)
+					continue
+				}
+				if rx.Cmp(&tx) != 0 {
+					t.Errorf("JSON encoding of %v (prec = %d) failed: got %v want %v", &tx, prec, &rx, &tx)
+				}
+			}
+		}
+	}
+}
diff --git a/src/math/big/ftoa.go b/src/math/big/ftoa.go
index 5c5f2ce..c5cdb5e 100644
--- a/src/math/big/ftoa.go
+++ b/src/math/big/ftoa.go
@@ -9,9 +9,9 @@
 package big
 
 import (
+	"bytes"
 	"fmt"
 	"strconv"
-	"strings"
 )
 
 // Text converts the floating-point number x to a string according
@@ -37,16 +37,16 @@ import (
 // printed by the 'e', 'E', 'f', 'g', and 'G' formats. For 'e', 'E', and 'f'
 // it is the number of digits after the decimal point. For 'g' and 'G' it is
 // the total number of digits. A negative precision selects the smallest
-// number of digits necessary to identify the value x uniquely.
+// number of decimal digits necessary to identify the value x uniquely using
+// x.Prec() mantissa bits.
 // The prec value is ignored for the 'b' or 'p' format.
-//
-// BUG(gri) Float.Text does not accept negative precisions (issue #10991).
 func (x *Float) Text(format byte, prec int) string {
 	const extra = 10 // TODO(gri) determine a good/better value here
 	return string(x.Append(make([]byte, 0, prec+extra), format, prec))
 }
 
 // String formats x like x.Text('g', 10).
+// (String must be called explicitly, Float.Format does not support %s verb.)
 func (x *Float) String() string {
 	return x.Text('g', 10)
 }
@@ -83,6 +83,7 @@ func (x *Float) Append(buf []byte, fmt byte, prec int) []byte {
 	// 1) convert Float to multiprecision decimal
 	var d decimal // == 0.0
 	if x.form == finite {
+		// x != 0
 		d.init(x.mant, int(x.exp)-x.mant.bitLen())
 	}
 
@@ -90,9 +91,7 @@ func (x *Float) Append(buf []byte, fmt byte, prec int) []byte {
 	shortest := false
 	if prec < 0 {
 		shortest = true
-		panic("unimplemented")
-		// TODO(gri) complete this
-		// roundShortest(&d, f.mant, int(f.exp))
+		roundShortest(&d, x)
 		// Precision for shortest representation mode.
 		switch fmt {
 		case 'e', 'E':
@@ -158,6 +157,80 @@ func (x *Float) Append(buf []byte, fmt byte, prec int) []byte {
 	return append(buf, '%', fmt)
 }
 
+func roundShortest(d *decimal, x *Float) {
+	// if the mantissa is zero, the number is zero - stop now
+	if len(d.mant) == 0 {
+		return
+	}
+
+	// Approach: All numbers in the interval [x - 1/2ulp, x + 1/2ulp]
+	// (possibly exclusive) round to x for the given precision of x.
+	// Compute the lower and upper bound in decimal form and find the
+	// shortest decimal number d such that lower <= d <= upper.
+
+	// TODO(gri) strconv/ftoa.do describes a shortcut in some cases.
+	// See if we can use it (in adjusted form) here as well.
+
+	// 1) Compute normalized mantissa mant and exponent exp for x such
+	// that the lsb of mant corresponds to 1/2 ulp for the precision of
+	// x (i.e., for mant we want x.prec + 1 bits).
+	mant := nat(nil).set(x.mant)
+	exp := int(x.exp) - mant.bitLen()
+	s := mant.bitLen() - int(x.prec+1)
+	switch {
+	case s < 0:
+		mant = mant.shl(mant, uint(-s))
+	case s > 0:
+		mant = mant.shr(mant, uint(+s))
+	}
+	exp += s
+	// x = mant * 2**exp with lsb(mant) == 1/2 ulp of x.prec
+
+	// 2) Compute lower bound by subtracting 1/2 ulp.
+	var lower decimal
+	var tmp nat
+	lower.init(tmp.sub(mant, natOne), exp)
+
+	// 3) Compute upper bound by adding 1/2 ulp.
+	var upper decimal
+	upper.init(tmp.add(mant, natOne), exp)
+
+	// The upper and lower bounds are possible outputs only if
+	// the original mantissa is even, so that ToNearestEven rounding
+	// would round to the original mantissa and not the neighbors.
+	inclusive := mant[0]&2 == 0 // test bit 1 since original mantissa was shifted by 1
+
+	// Now we can figure out the minimum number of digits required.
+	// Walk along until d has distinguished itself from upper and lower.
+	for i, m := range d.mant {
+		l := lower.at(i)
+		u := upper.at(i)
+
+		// Okay to round down (truncate) if lower has a different digit
+		// or if lower is inclusive and is exactly the result of rounding
+		// down (i.e., and we have reached the final digit of lower).
+		okdown := l != m || inclusive && i+1 == len(lower.mant)
+
+		// Okay to round up if upper has a different digit and either upper
+		// is inclusive or upper is bigger than the result of rounding up.
+		okup := m != u && (inclusive || m+1 < u || i+1 < len(upper.mant))
+
+		// If it's okay to do either, then round to the nearest one.
+		// If it's okay to do only one, do it.
+		switch {
+		case okdown && okup:
+			d.round(i + 1)
+			return
+		case okdown:
+			d.roundDown(i + 1)
+			return
+		case okup:
+			d.roundUp(i + 1)
+			return
+		}
+	}
+}
+
 // %e: d.ddddde±dd
 func fmtE(buf []byte, fmt byte, prec int, d decimal) []byte {
 	// first digit
@@ -219,11 +292,7 @@ func fmtF(buf []byte, prec int, d decimal) []byte {
 	if prec > 0 {
 		buf = append(buf, '.')
 		for i := 0; i < prec; i++ {
-			ch := byte('0')
-			if j := d.exp + i; 0 <= j && j < len(d.mant) {
-				ch = d.mant[j]
-			}
-			buf = append(buf, ch)
+			buf = append(buf, d.at(d.exp+i))
 		}
 	}
 
@@ -255,7 +324,7 @@ func (x *Float) fmtB(buf []byte) []byte {
 		m = nat(nil).shr(m, uint(w-x.prec))
 	}
 
-	buf = append(buf, m.decimalString()...)
+	buf = append(buf, m.utoa(10)...)
 	buf = append(buf, 'p')
 	e := int64(x.exp) - int64(x.prec)
 	if e >= 0 {
@@ -289,7 +358,7 @@ func (x *Float) fmtP(buf []byte) []byte {
 	m = m[i:]
 
 	buf = append(buf, "0x."...)
-	buf = append(buf, strings.TrimRight(m.hexString(), "0")...)
+	buf = append(buf, bytes.TrimRight(m.utoa(16), "0")...)
 	buf = append(buf, 'p')
 	if x.exp >= 0 {
 		buf = append(buf, '+')
@@ -314,10 +383,6 @@ func min(x, y int) int {
 // '+' and ' ' for sign control, '0' for space or zero padding,
 // and '-' for left or right justification. See the fmt package
 // for details.
-//
-// BUG(gri) A missing precision for the 'g' format, or a negative
-//          (via '*') precision is not yet supported. Instead the
-//          default precision (6) is used in that case (issue #10991).
 func (x *Float) Format(s fmt.State, format rune) {
 	prec, hasPrec := s.Precision()
 	if !hasPrec {
@@ -336,8 +401,7 @@ func (x *Float) Format(s fmt.State, format rune) {
 		fallthrough
 	case 'g', 'G':
 		if !hasPrec {
-			// TODO(gri) uncomment once (*Float).Text handles prec < 0
-			// prec = -1 // default precision for 'g', 'G'
+			prec = -1 // default precision for 'g', 'G'
 		}
 	default:
 		fmt.Fprintf(s, "%%!%c(*big.Float=%s)", format, x.String())
diff --git a/src/math/big/int.go b/src/math/big/int.go
index 65334e0..67ab704 100644
--- a/src/math/big/int.go
+++ b/src/math/big/int.go
@@ -273,7 +273,7 @@ func (z *Int) Mod(x, y *Int) *Int {
 // DivMod implements Euclidean division and modulus (unlike Go):
 //
 //	q = x div y  such that
-//	m = x - y*q  with 0 <= m < |q|
+//	m = x - y*q  with 0 <= m < |y|
 //
 // (See Raymond T. Boute, ``The Euclidean definition of the functions
 // div and mod''. ACM Transactions on Programming Languages and
@@ -551,8 +551,11 @@ func (z *Int) binaryGCD(a, b *Int) *Int {
 }
 
 // ProbablyPrime performs n Miller-Rabin tests to check whether x is prime.
-// If it returns true, x is prime with probability 1 - 1/4^n.
-// If it returns false, x is not prime. n must be > 0.
+// If x is prime, it returns true.
+// If x is not prime, it returns false with probability at least 1 - ¼ⁿ.
+//
+// It is not suitable for judging primes that an adversary may have crafted
+// to fool this test.
 func (x *Int) ProbablyPrime(n int) bool {
 	if n <= 0 {
 		panic("non-positive n for ProbablyPrime")
@@ -640,23 +643,23 @@ func Jacobi(x, y *Int) int {
 	}
 }
 
-// ModSqrt sets z to a square root of x mod p if such a square root exists, and
-// returns z. The modulus p must be an odd prime. If x is not a square mod p,
-// ModSqrt leaves z unchanged and returns nil. This function panics if p is
-// not an odd integer.
-func (z *Int) ModSqrt(x, p *Int) *Int {
-	switch Jacobi(x, p) {
-	case -1:
-		return nil // x is not a square mod p
-	case 0:
-		return z.SetInt64(0) // sqrt(0) mod p = 0
-	case 1:
-		break
-	}
-	if x.neg || x.Cmp(p) >= 0 { // ensure 0 <= x < p
-		x = new(Int).Mod(x, p)
-	}
+// modSqrt3Mod4 uses the identity
+//      (a^((p+1)/4))^2  mod p
+//   == u^(p+1)          mod p
+//   == u^2              mod p
+// to calculate the square root of any quadratic residue mod p quickly for 3
+// mod 4 primes.
+func (z *Int) modSqrt3Mod4Prime(x, p *Int) *Int {
+	z.Set(p)         // z = p
+	z.Add(z, intOne) // z = p + 1
+	z.Rsh(z, 2)      // z = (p + 1) / 4
+	z.Exp(x, z, p)   // z = x^z mod p
+	return z
+}
 
+// modSqrtTonelliShanks uses the Tonelli-Shanks algorithm to find the square
+// root of a quadratic residue modulo any prime.
+func (z *Int) modSqrtTonelliShanks(x, p *Int) *Int {
 	// Break p-1 into s*2^e such that s is odd.
 	var s Int
 	s.Sub(p, intOne)
@@ -703,6 +706,31 @@ func (z *Int) ModSqrt(x, p *Int) *Int {
 	}
 }
 
+// ModSqrt sets z to a square root of x mod p if such a square root exists, and
+// returns z. The modulus p must be an odd prime. If x is not a square mod p,
+// ModSqrt leaves z unchanged and returns nil. This function panics if p is
+// not an odd integer.
+func (z *Int) ModSqrt(x, p *Int) *Int {
+	switch Jacobi(x, p) {
+	case -1:
+		return nil // x is not a square mod p
+	case 0:
+		return z.SetInt64(0) // sqrt(0) mod p = 0
+	case 1:
+		break
+	}
+	if x.neg || x.Cmp(p) >= 0 { // ensure 0 <= x < p
+		x = new(Int).Mod(x, p)
+	}
+
+	// Check whether p is 3 mod 4, and if so, use the faster algorithm.
+	if len(p.abs) > 0 && p.abs[0]%4 == 3 {
+		return z.modSqrt3Mod4Prime(x, p)
+	}
+	// Otherwise, use Tonelli-Shanks.
+	return z.modSqrtTonelliShanks(x, p)
+}
+
 // Lsh sets z = x << n and returns z.
 func (z *Int) Lsh(x *Int, n uint) *Int {
 	z.abs = z.abs.shl(x.abs, n)
@@ -904,65 +932,3 @@ func (z *Int) Not(x *Int) *Int {
 	z.neg = true // z cannot be zero if x is positive
 	return z
 }
-
-// Gob codec version. Permits backward-compatible changes to the encoding.
-const intGobVersion byte = 1
-
-// GobEncode implements the gob.GobEncoder interface.
-func (x *Int) GobEncode() ([]byte, error) {
-	if x == nil {
-		return nil, nil
-	}
-	buf := make([]byte, 1+len(x.abs)*_S) // extra byte for version and sign bit
-	i := x.abs.bytes(buf) - 1            // i >= 0
-	b := intGobVersion << 1              // make space for sign bit
-	if x.neg {
-		b |= 1
-	}
-	buf[i] = b
-	return buf[i:], nil
-}
-
-// GobDecode implements the gob.GobDecoder interface.
-func (z *Int) GobDecode(buf []byte) error {
-	if len(buf) == 0 {
-		// Other side sent a nil or default value.
-		*z = Int{}
-		return nil
-	}
-	b := buf[0]
-	if b>>1 != intGobVersion {
-		return fmt.Errorf("Int.GobDecode: encoding version %d not supported", b>>1)
-	}
-	z.neg = b&1 != 0
-	z.abs = z.abs.setBytes(buf[1:])
-	return nil
-}
-
-// MarshalJSON implements the json.Marshaler interface.
-func (z *Int) MarshalJSON() ([]byte, error) {
-	// TODO(gri): get rid of the []byte/string conversions
-	return []byte(z.String()), nil
-}
-
-// UnmarshalJSON implements the json.Unmarshaler interface.
-func (z *Int) UnmarshalJSON(text []byte) error {
-	// TODO(gri): get rid of the []byte/string conversions
-	if _, ok := z.SetString(string(text), 0); !ok {
-		return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Int", text)
-	}
-	return nil
-}
-
-// MarshalText implements the encoding.TextMarshaler interface.
-func (z *Int) MarshalText() (text []byte, err error) {
-	return []byte(z.String()), nil
-}
-
-// UnmarshalText implements the encoding.TextUnmarshaler interface.
-func (z *Int) UnmarshalText(text []byte) error {
-	if _, ok := z.SetString(string(text), 0); !ok {
-		return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Int", text)
-	}
-	return nil
-}
diff --git a/src/math/big/int_test.go b/src/math/big/int_test.go
index f3def5a..45a3765 100644
--- a/src/math/big/int_test.go
+++ b/src/math/big/int_test.go
@@ -6,10 +6,7 @@ package big
 
 import (
 	"bytes"
-	"encoding/gob"
 	"encoding/hex"
-	"encoding/json"
-	"encoding/xml"
 	"fmt"
 	"math/rand"
 	"testing"
@@ -387,6 +384,11 @@ func TestSetBytes(t *testing.T) {
 }
 
 func checkBytes(b []byte) bool {
+	// trim leading zero bytes since Bytes() won't return them
+	// (was issue 12231)
+	for len(b) > 0 && b[0] == 0 {
+		b = b[1:]
+	}
 	b2 := new(Int).SetBytes(b).Bytes()
 	return bytes.Equal(b, b2)
 }
@@ -542,6 +544,9 @@ var expTests = []struct {
 	{"0x8000000000000000", "1000", "6719", "1603"},
 	{"0x8000000000000000", "1000000", "6719", "3199"},
 	{"0x8000000000000000", "-1000000", "6719", "1"},
+
+	{"0xffffffffffffffffffffffffffffffff", "0x12345678123456781234567812345678123456789", "0x01112222333344445555666677778889", "0x36168FA1DB3AAE6C8CE647E137F97A"},
+
 	{
 		"2938462938472983472983659726349017249287491026512746239764525612965293865296239471239874193284792387498274256129746192347",
 		"298472983472983471903246121093472394872319615612417471234712061",
@@ -550,6 +555,12 @@ var expTests = []struct {
 	},
 	// test case for issue 8822
 	{
+		"110012891183630896460173593721179634992505463752690475427779280061032468766887567357609056806046466243531968695727526232851404087554203740493176464281852700795553727635031156460546028675936629238941409408374795071949342675328316945655164667650254349023483145256274185156465881609558628390220513536530529470731360847807427297278748034576438481974995482975700269269275025056342970795272990042677697807685656954599452355868926270591788849987729893975050612063954555915037716775009312694775035 [...]
+		"0xB08FFB20760FFED58FADA86DFEF71AD72AA0FA763219618FE022C197E54708BB1191C66470250FCE8879487507CEE41381CA4D932F81C2B3F1AB20B539D50DCD",
+		"0xAC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E37 [...]
+		"214842521977763024996399388837777103219931130979872010505011829095813593576185795667465563725893853616836105247305090413288550665149633855225708948390358847130516401714741865487135466864767613064364341464751401562843891818086750165768458333404948482836810888865842197505544080605567694866280290287207273932931116788263564804554339092335205041120744013761330771504712375494741491902420104695390064495966115766125739557543490423291306311282346379247864665857034884605402284774408534933920862 [...]
+	},
+	{
 		"-0x1BCE04427D8032319A89E5C4136456671AC620883F2C4139E57F91307C485AD2D6204F4F87A58262652DB5DBBAC72B0613E51B835E7153BEC6068F5C8D696B74DBD18FEC316AEF73985CF0475663208EB46B4F17DD9DA55367B03323E5491A70997B90C059FB34809E6EE55BCFBD5F2F52233BFE62E6AA9E4E26A1D4C2439883D14F2633D55D8AA66A1ACD5595E778AC3A280517F1157989E70C1A437B849F1877B779CC3CDDEDE2DAA6594A6C66D181A00A5F777EE60596D8773998F6E988DEAE4CCA60E4DDCF9590543C89F74F603259FCAD71660D30294FBBE6490300F78A9D63FA660DC9417B8B9DDA28BEB3977B621B98 [...]
 		"0xB08FFB20760FFED58FADA86DFEF71AD72AA0FA763219618FE022C197E54708BB1191C66470250FCE8879487507CEE41381CA4D932F81C2B3F1AB20B539D50DCD",
 		"0xAC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E37 [...]
@@ -699,7 +710,9 @@ func TestGcd(t *testing.T) {
 		testGcd(t, d, x, y, a, b)
 	}
 
-	quick.Check(checkGcd, nil)
+	if err := quick.Check(checkGcd, nil); err != nil {
+		t.Error(err)
+	}
 }
 
 var primes = []string{
@@ -1186,6 +1199,53 @@ func BenchmarkBitsetNegOrig(b *testing.B) {
 	}
 }
 
+// tri generates the trinomial 2**(n*2) - 2**n - 1, which is always 3 mod 4 and
+// 7 mod 8, so that 2 is always a quadratic residue.
+func tri(n uint) *Int {
+	x := NewInt(1)
+	x.Lsh(x, n)
+	x2 := new(Int).Lsh(x, n)
+	x2.Sub(x2, x)
+	x2.Sub(x2, intOne)
+	return x2
+}
+
+func BenchmarkModSqrt225_Tonelli(b *testing.B) {
+	p := tri(225)
+	x := NewInt(2)
+	for i := 0; i < b.N; i++ {
+		x.SetUint64(2)
+		x.modSqrtTonelliShanks(x, p)
+	}
+}
+
+func BenchmarkModSqrt224_3Mod4(b *testing.B) {
+	p := tri(225)
+	x := new(Int).SetUint64(2)
+	for i := 0; i < b.N; i++ {
+		x.SetUint64(2)
+		x.modSqrt3Mod4Prime(x, p)
+	}
+}
+
+func BenchmarkModSqrt5430_Tonelli(b *testing.B) {
+	p := tri(5430)
+	x := new(Int).SetUint64(2)
+	for i := 0; i < b.N; i++ {
+		x.SetUint64(2)
+		x.modSqrtTonelliShanks(x, p)
+	}
+}
+
+func BenchmarkModSqrt5430_3Mod4(b *testing.B) {
+	p := tri(5430)
+	x := new(Int).SetUint64(2)
+	for i := 0; i < b.N; i++ {
+		x.SetUint64(2)
+		x.modSqrt3Mod4Prime(x, p)
+	}
+}
+
 func TestBitwise(t *testing.T) {
 	x := new(Int)
 	y := new(Int)
@@ -1324,6 +1384,14 @@ func TestModSqrt(t *testing.T) {
 				t.Errorf("#%d: failed (sqrt(e) = %s)", i, &sqrt)
 			}
 		}
+
+		if testing.Short() && i > 2 {
+			break
+		}
+	}
+
+	if testing.Short() {
+		return
 	}
 
 	// exhaustive test for small values
@@ -1407,138 +1475,6 @@ func TestJacobiPanic(t *testing.T) {
 	panic(failureMsg)
 }
 
-var encodingTests = []string{
-	"-539345864568634858364538753846587364875430589374589",
-	"-678645873",
-	"-100",
-	"-2",
-	"-1",
-	"0",
-	"1",
-	"2",
-	"10",
-	"42",
-	"1234567890",
-	"298472983472983471903246121093472394872319615612417471234712061",
-}
-
-func TestIntGobEncoding(t *testing.T) {
-	var medium bytes.Buffer
-	enc := gob.NewEncoder(&medium)
-	dec := gob.NewDecoder(&medium)
-	for _, test := range encodingTests {
-		medium.Reset() // empty buffer for each test case (in case of failures)
-		var tx Int
-		tx.SetString(test, 10)
-		if err := enc.Encode(&tx); err != nil {
-			t.Errorf("encoding of %s failed: %s", &tx, err)
-		}
-		var rx Int
-		if err := dec.Decode(&rx); err != nil {
-			t.Errorf("decoding of %s failed: %s", &tx, err)
-		}
-		if rx.Cmp(&tx) != 0 {
-			t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx)
-		}
-	}
-}
-
-// Sending a nil Int pointer (inside a slice) on a round trip through gob should yield a zero.
-// TODO: top-level nils.
-func TestGobEncodingNilIntInSlice(t *testing.T) {
-	buf := new(bytes.Buffer)
-	enc := gob.NewEncoder(buf)
-	dec := gob.NewDecoder(buf)
-
-	var in = make([]*Int, 1)
-	err := enc.Encode(&in)
-	if err != nil {
-		t.Errorf("gob encode failed: %q", err)
-	}
-	var out []*Int
-	err = dec.Decode(&out)
-	if err != nil {
-		t.Fatalf("gob decode failed: %q", err)
-	}
-	if len(out) != 1 {
-		t.Fatalf("wrong len; want 1 got %d", len(out))
-	}
-	var zero Int
-	if out[0].Cmp(&zero) != 0 {
-		t.Errorf("transmission of (*Int)(nill) failed: got %s want 0", out)
-	}
-}
-
-func TestIntJSONEncoding(t *testing.T) {
-	for _, test := range encodingTests {
-		var tx Int
-		tx.SetString(test, 10)
-		b, err := json.Marshal(&tx)
-		if err != nil {
-			t.Errorf("marshaling of %s failed: %s", &tx, err)
-		}
-		var rx Int
-		if err := json.Unmarshal(b, &rx); err != nil {
-			t.Errorf("unmarshaling of %s failed: %s", &tx, err)
-		}
-		if rx.Cmp(&tx) != 0 {
-			t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx)
-		}
-	}
-}
-
-var intVals = []string{
-	"-141592653589793238462643383279502884197169399375105820974944592307816406286",
-	"-1415926535897932384626433832795028841971",
-	"-141592653589793",
-	"-1",
-	"0",
-	"1",
-	"141592653589793",
-	"1415926535897932384626433832795028841971",
-	"141592653589793238462643383279502884197169399375105820974944592307816406286",
-}
-
-func TestIntJSONEncodingTextMarshaller(t *testing.T) {
-	for _, num := range intVals {
-		var tx Int
-		tx.SetString(num, 0)
-		b, err := json.Marshal(&tx)
-		if err != nil {
-			t.Errorf("marshaling of %s failed: %s", &tx, err)
-			continue
-		}
-		var rx Int
-		if err := json.Unmarshal(b, &rx); err != nil {
-			t.Errorf("unmarshaling of %s failed: %s", &tx, err)
-			continue
-		}
-		if rx.Cmp(&tx) != 0 {
-			t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx)
-		}
-	}
-}
-
-func TestIntXMLEncodingTextMarshaller(t *testing.T) {
-	for _, num := range intVals {
-		var tx Int
-		tx.SetString(num, 0)
-		b, err := xml.Marshal(&tx)
-		if err != nil {
-			t.Errorf("marshaling of %s failed: %s", &tx, err)
-			continue
-		}
-		var rx Int
-		if err := xml.Unmarshal(b, &rx); err != nil {
-			t.Errorf("unmarshaling of %s failed: %s", &tx, err)
-			continue
-		}
-		if rx.Cmp(&tx) != 0 {
-			t.Errorf("XML encoding of %s failed: got %s want %s", &tx, &rx, &tx)
-		}
-	}
-}
-
 func TestIssue2607(t *testing.T) {
 	// This code sequence used to hang.
 	n := NewInt(10)
diff --git a/src/math/big/intconv.go b/src/math/big/intconv.go
index 9c68a22..56a75f8 100644
--- a/src/math/big/intconv.go
+++ b/src/math/big/intconv.go
@@ -12,30 +12,34 @@ import (
 	"io"
 )
 
-func (x *Int) String() string {
-	switch {
-	case x == nil:
+// TODO(gri) Should rename itoa to utoa (there's no sign). That
+// would permit the introduction of itoa which is like utoa but
+// reserves a byte for a possible sign that's passed in. That
+// would permit Int.Text to be implemented w/o the need for
+// string copy if the number is negative.
+
+// Text returns the string representation of x in the given base.
+// Base must be between 2 and 36, inclusive. The result uses the
+// lower-case letters 'a' to 'z' for digit values >= 10. No base
+// prefix (such as "0x") is added to the string.
+func (x *Int) Text(base int) string {
+	if x == nil {
 		return "<nil>"
-	case x.neg:
-		return "-" + x.abs.decimalString()
 	}
-	return x.abs.decimalString()
+	return string(x.abs.itoa(x.neg, base))
 }
 
-func charset(ch rune) string {
-	switch ch {
-	case 'b':
-		return lowercaseDigits[0:2]
-	case 'o':
-		return lowercaseDigits[0:8]
-	case 'd', 's', 'v':
-		return lowercaseDigits[0:10]
-	case 'x':
-		return lowercaseDigits[0:16]
-	case 'X':
-		return uppercaseDigits[0:16]
+// Append appends the string representation of x, as generated by
+// x.Text(base), to buf and returns the extended buffer.
+func (x *Int) Append(buf []byte, base int) []byte {
+	if x == nil {
+		return append(buf, "<nil>"...)
 	}
-	return "" // unknown format
+	return append(buf, x.abs.itoa(x.neg, base)...)
+}
+
+func (x *Int) String() string {
+	return x.Text(10)
 }
 
 // write count copies of text to s
@@ -60,15 +64,24 @@ func writeMultiple(s fmt.State, text string, count int) {
 // right justification.
 //
 func (x *Int) Format(s fmt.State, ch rune) {
-	cs := charset(ch)
-
-	// special cases
-	switch {
-	case cs == "":
+	// determine base
+	var base int
+	switch ch {
+	case 'b':
+		base = 2
+	case 'o':
+		base = 8
+	case 'd', 's', 'v':
+		base = 10
+	case 'x', 'X':
+		base = 16
+	default:
 		// unknown format
 		fmt.Fprintf(s, "%%!%c(big.Int=%s)", ch, x.String())
 		return
-	case x == nil:
+	}
+
+	if x == nil {
 		fmt.Fprint(s, "<nil>")
 		return
 	}
@@ -97,35 +110,42 @@ func (x *Int) Format(s fmt.State, ch rune) {
 		}
 	}
 
-	// determine digits with base set by len(cs) and digit characters from cs
-	digits := x.abs.string(cs)
+	digits := x.abs.utoa(base)
+	if ch == 'X' {
+		// faster than bytes.ToUpper
+		for i, d := range digits {
+			if 'a' <= d && d <= 'z' {
+				digits[i] = 'A' + (d - 'a')
+			}
+		}
+	}
 
 	// number of characters for the three classes of number padding
-	var left int   // space characters to left of digits for right justification ("%8d")
-	var zeroes int // zero characters (actually cs[0]) as left-most digits ("%.8d")
-	var right int  // space characters to right of digits for left justification ("%-8d")
+	var left int  // space characters to left of digits for right justification ("%8d")
+	var zeros int // zero characters (actually cs[0]) as left-most digits ("%.8d")
+	var right int // space characters to right of digits for left justification ("%-8d")
 
 	// determine number padding from precision: the least number of digits to output
 	precision, precisionSet := s.Precision()
 	if precisionSet {
 		switch {
 		case len(digits) < precision:
-			zeroes = precision - len(digits) // count of zero padding
-		case digits == "0" && precision == 0:
+			zeros = precision - len(digits) // count of zero padding
+		case len(digits) == 1 && digits[0] == '0' && precision == 0:
 			return // print nothing if zero value (x == 0) and zero precision ("." or ".0")
 		}
 	}
 
 	// determine field pad from width: the least number of characters to output
-	length := len(sign) + len(prefix) + zeroes + len(digits)
+	length := len(sign) + len(prefix) + zeros + len(digits)
 	if width, widthSet := s.Width(); widthSet && length < width { // pad as specified
 		switch d := width - length; {
 		case s.Flag('-'):
 			// pad on the right with spaces; supersedes '0' when both specified
 			right = d
 		case s.Flag('0') && !precisionSet:
-			// pad with zeroes unless precision also specified
-			zeroes = d
+			// pad with zeros unless precision also specified
+			zeros = d
 		default:
 			// pad on the left with spaces
 			left = d
@@ -136,8 +156,8 @@ func (x *Int) Format(s fmt.State, ch rune) {
 	writeMultiple(s, " ", left)
 	writeMultiple(s, sign, 1)
 	writeMultiple(s, prefix, 1)
-	writeMultiple(s, "0", zeroes)
-	writeMultiple(s, digits, 1)
+	writeMultiple(s, "0", zeros)
+	s.Write(digits)
 	writeMultiple(s, " ", right)
 }
 
diff --git a/src/math/big/intconv_test.go b/src/math/big/intconv_test.go
index 2deb84b..5142081 100644
--- a/src/math/big/intconv_test.go
+++ b/src/math/big/intconv_test.go
@@ -17,19 +17,19 @@ var stringTests = []struct {
 	val  int64
 	ok   bool
 }{
-	{in: "", ok: false},
-	{in: "a", ok: false},
-	{in: "z", ok: false},
-	{in: "+", ok: false},
-	{in: "-", ok: false},
-	{in: "0b", ok: false},
-	{in: "0x", ok: false},
-	{in: "2", base: 2, ok: false},
-	{in: "0b2", base: 0, ok: false},
-	{in: "08", ok: false},
-	{in: "8", base: 8, ok: false},
-	{in: "0xg", base: 0, ok: false},
-	{in: "g", base: 16, ok: false},
+	{in: ""},
+	{in: "a"},
+	{in: "z"},
+	{in: "+"},
+	{in: "-"},
+	{in: "0b"},
+	{in: "0x"},
+	{in: "2", base: 2},
+	{in: "0b2", base: 0},
+	{in: "08"},
+	{in: "8", base: 8},
+	{in: "0xg", base: 0},
+	{in: "g", base: 16},
 	{"0", "0", 0, 0, true},
 	{"0", "0", 10, 0, true},
 	{"0", "0", 16, 0, true},
@@ -41,7 +41,7 @@ var stringTests = []struct {
 	{"-10", "-10", 16, -16, true},
 	{"+10", "10", 16, 16, true},
 	{"0x10", "16", 0, 16, true},
-	{in: "0x10", base: 16, ok: false},
+	{in: "0x10", base: 16},
 	{"-0x10", "-16", 0, -16, true},
 	{"+0x10", "16", 0, 16, true},
 	{"00", "0", 0, 0, true},
@@ -58,6 +58,57 @@ var stringTests = []struct {
 	{"1001010111", "1001010111", 2, 0x257, true},
 }
 
+func TestIntText(t *testing.T) {
+	z := new(Int)
+	for _, test := range stringTests {
+		if !test.ok {
+			continue
+		}
+
+		_, ok := z.SetString(test.in, test.base)
+		if !ok {
+			t.Errorf("%v: failed to parse", test)
+			continue
+		}
+
+		base := test.base
+		if base == 0 {
+			base = 10
+		}
+
+		if got := z.Text(base); got != test.out {
+			t.Errorf("%v: got %s; want %s", test, got, test.out)
+		}
+	}
+}
+
+func TestAppendText(t *testing.T) {
+	z := new(Int)
+	var buf []byte
+	for _, test := range stringTests {
+		if !test.ok {
+			continue
+		}
+
+		_, ok := z.SetString(test.in, test.base)
+		if !ok {
+			t.Errorf("%v: failed to parse", test)
+			continue
+		}
+
+		base := test.base
+		if base == 0 {
+			base = 10
+		}
+
+		i := len(buf)
+		buf = z.Append(buf, base)
+		if got := string(buf[i:]); got != test.out {
+			t.Errorf("%v: got %s; want %s", test, got, test.out)
+		}
+	}
+}
+
 func format(base int) string {
 	switch base {
 	case 2:
@@ -79,15 +130,13 @@ func TestGetString(t *testing.T) {
 		z.SetInt64(test.val)
 
 		if test.base == 10 {
-			s := z.String()
-			if s != test.out {
-				t.Errorf("#%da got %s; want %s", i, s, test.out)
+			if got := z.String(); got != test.out {
+				t.Errorf("#%da got %s; want %s", i, got, test.out)
 			}
 		}
 
-		s := fmt.Sprintf(format(test.base), z)
-		if s != test.out {
-			t.Errorf("#%db got %s; want %s", i, s, test.out)
+		if got := fmt.Sprintf(format(test.base), z); got != test.out {
+			t.Errorf("#%db got %s; want %s", i, got, test.out)
 		}
 	}
 }
diff --git a/src/math/big/intmarsh.go b/src/math/big/intmarsh.go
new file mode 100644
index 0000000..4ff57b6
--- /dev/null
+++ b/src/math/big/intmarsh.go
@@ -0,0 +1,74 @@
+// Copyright 2015 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 file implements encoding/decoding of Ints.
+
+package big
+
+import "fmt"
+
+// Gob codec version. Permits backward-compatible changes to the encoding.
+const intGobVersion byte = 1
+
+// GobEncode implements the gob.GobEncoder interface.
+func (x *Int) GobEncode() ([]byte, error) {
+	if x == nil {
+		return nil, nil
+	}
+	buf := make([]byte, 1+len(x.abs)*_S) // extra byte for version and sign bit
+	i := x.abs.bytes(buf) - 1            // i >= 0
+	b := intGobVersion << 1              // make space for sign bit
+	if x.neg {
+		b |= 1
+	}
+	buf[i] = b
+	return buf[i:], nil
+}
+
+// GobDecode implements the gob.GobDecoder interface.
+func (z *Int) GobDecode(buf []byte) error {
+	if len(buf) == 0 {
+		// Other side sent a nil or default value.
+		*z = Int{}
+		return nil
+	}
+	b := buf[0]
+	if b>>1 != intGobVersion {
+		return fmt.Errorf("Int.GobDecode: encoding version %d not supported", b>>1)
+	}
+	z.neg = b&1 != 0
+	z.abs = z.abs.setBytes(buf[1:])
+	return nil
+}
+
+// MarshalText implements the encoding.TextMarshaler interface.
+func (x *Int) MarshalText() (text []byte, err error) {
+	if x == nil {
+		return []byte("<nil>"), nil
+	}
+	return x.abs.itoa(x.neg, 10), nil
+}
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface.
+func (z *Int) UnmarshalText(text []byte) error {
+	// TODO(gri): get rid of the []byte/string conversion
+	if _, ok := z.SetString(string(text), 0); !ok {
+		return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Int", text)
+	}
+	return nil
+}
+
+// The JSON marshallers are only here for API backward compatibility
+// (programs that explicitly look for these two methods). JSON works
+// fine with the TextMarshaler only.
+
+// MarshalJSON implements the json.Marshaler interface.
+func (x *Int) MarshalJSON() ([]byte, error) {
+	return x.MarshalText()
+}
+
+// UnmarshalJSON implements the json.Unmarshaler interface.
+func (z *Int) UnmarshalJSON(text []byte) error {
+	return z.UnmarshalText(text)
+}
diff --git a/src/math/big/intmarsh_test.go b/src/math/big/intmarsh_test.go
new file mode 100644
index 0000000..f82956c
--- /dev/null
+++ b/src/math/big/intmarsh_test.go
@@ -0,0 +1,121 @@
+// Copyright 2015 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 big
+
+import (
+	"bytes"
+	"encoding/gob"
+	"encoding/json"
+	"encoding/xml"
+	"testing"
+)
+
+var encodingTests = []string{
+	"0",
+	"1",
+	"2",
+	"10",
+	"1000",
+	"1234567890",
+	"298472983472983471903246121093472394872319615612417471234712061",
+}
+
+func TestIntGobEncoding(t *testing.T) {
+	var medium bytes.Buffer
+	enc := gob.NewEncoder(&medium)
+	dec := gob.NewDecoder(&medium)
+	for _, test := range encodingTests {
+		for _, sign := range []string{"", "+", "-"} {
+			x := sign + test
+			medium.Reset() // empty buffer for each test case (in case of failures)
+			var tx Int
+			tx.SetString(x, 10)
+			if err := enc.Encode(&tx); err != nil {
+				t.Errorf("encoding of %s failed: %s", &tx, err)
+				continue
+			}
+			var rx Int
+			if err := dec.Decode(&rx); err != nil {
+				t.Errorf("decoding of %s failed: %s", &tx, err)
+				continue
+			}
+			if rx.Cmp(&tx) != 0 {
+				t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx)
+			}
+		}
+	}
+}
+
+// Sending a nil Int pointer (inside a slice) on a round trip through gob should yield a zero.
+// TODO: top-level nils.
+func TestGobEncodingNilIntInSlice(t *testing.T) {
+	buf := new(bytes.Buffer)
+	enc := gob.NewEncoder(buf)
+	dec := gob.NewDecoder(buf)
+
+	var in = make([]*Int, 1)
+	err := enc.Encode(&in)
+	if err != nil {
+		t.Errorf("gob encode failed: %q", err)
+	}
+	var out []*Int
+	err = dec.Decode(&out)
+	if err != nil {
+		t.Fatalf("gob decode failed: %q", err)
+	}
+	if len(out) != 1 {
+		t.Fatalf("wrong len; want 1 got %d", len(out))
+	}
+	var zero Int
+	if out[0].Cmp(&zero) != 0 {
+		t.Fatalf("transmission of (*Int)(nil) failed: got %s want 0", out)
+	}
+}
+
+func TestIntJSONEncoding(t *testing.T) {
+	for _, test := range encodingTests {
+		for _, sign := range []string{"", "+", "-"} {
+			x := sign + test
+			var tx Int
+			tx.SetString(x, 10)
+			b, err := json.Marshal(&tx)
+			if err != nil {
+				t.Errorf("marshaling of %s failed: %s", &tx, err)
+				continue
+			}
+			var rx Int
+			if err := json.Unmarshal(b, &rx); err != nil {
+				t.Errorf("unmarshaling of %s failed: %s", &tx, err)
+				continue
+			}
+			if rx.Cmp(&tx) != 0 {
+				t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx)
+			}
+		}
+	}
+}
+
+func TestIntXMLEncoding(t *testing.T) {
+	for _, test := range encodingTests {
+		for _, sign := range []string{"", "+", "-"} {
+			x := sign + test
+			var tx Int
+			tx.SetString(x, 0)
+			b, err := xml.Marshal(&tx)
+			if err != nil {
+				t.Errorf("marshaling of %s failed: %s", &tx, err)
+				continue
+			}
+			var rx Int
+			if err := xml.Unmarshal(b, &rx); err != nil {
+				t.Errorf("unmarshaling of %s failed: %s", &tx, err)
+				continue
+			}
+			if rx.Cmp(&tx) != 0 {
+				t.Errorf("XML encoding of %s failed: got %s want %s", &tx, &rx, &tx)
+			}
+		}
+	}
+}
diff --git a/src/math/big/nat.go b/src/math/big/nat.go
index 6c242c8..79cf6e0 100644
--- a/src/math/big/nat.go
+++ b/src/math/big/nat.go
@@ -2,31 +2,11 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Package big implements multi-precision arithmetic (big numbers).
-// The following numeric types are supported:
-//
-//   Int    signed integers
-//   Rat    rational numbers
-//   Float  floating-point numbers
-//
-// Methods are typically of the form:
-//
-//   func (z *T) Unary(x *T) *T        // z = op x
-//   func (z *T) Binary(x, y *T) *T    // z = x op y
-//   func (x *T) M() T1                // v = x.M()
-//
-// with T one of Int, Rat, or Float. For unary and binary operations, the
-// result is the receiver (usually named z in that case); if it is one of
-// the operands x or y it may be overwritten (and its memory reused).
-// To enable chaining of operations, the result is also returned. Methods
-// returning a result other than *Int, *Rat, or *Float take an operand as
-// the receiver (usually named x in that case).
-//
-package big
+// This file implements unsigned multi-precision integers (natural
+// numbers). They are the building blocks for the implementation
+// of signed integers, rationals, and floating-point numbers.
 
-// This file contains operations on unsigned multi-precision integers.
-// These are the building blocks for the operations on signed integers
-// and rationals.
+package big
 
 import "math/rand"
 
@@ -233,25 +213,25 @@ func (z nat) montgomery(x, y, m nat, k Word, n int) nat {
 	if len(x) != n || len(y) != n || len(m) != n {
 		panic("math/big: mismatched montgomery number lengths")
 	}
-	var c1, c2, c3 Word
 	z = z.make(n)
 	z.clear()
+	var c Word
 	for i := 0; i < n; i++ {
 		d := y[i]
-		c2 = addMulVVW(z, x, d)
+		c2 := addMulVVW(z, x, d)
 		t := z[0] * k
-		c3 = addMulVVW(z, m, t)
+		c3 := addMulVVW(z, m, t)
 		copy(z, z[1:])
-		cx := c1 + c2
+		cx := c + c2
 		cy := cx + c3
 		z[n-1] = cy
 		if cx < c2 || cy < c3 {
-			c1 = 1
+			c = 1
 		} else {
-			c1 = 0
+			c = 0
 		}
 	}
-	if c1 != 0 {
+	if c != 0 {
 		subVV(z, z, m)
 	}
 	return z
@@ -1076,26 +1056,22 @@ func (z nat) expNNWindowed(x, y, m nat) nat {
 // expNNMontgomery calculates x**y mod m using a fixed, 4-bit window.
 // Uses Montgomery representation.
 func (z nat) expNNMontgomery(x, y, m nat) nat {
-	var zz, one, rr, RR nat
-
 	numWords := len(m)
 
 	// We want the lengths of x and m to be equal.
+	// It is OK if x >= m as long as len(x) == len(m).
 	if len(x) > numWords {
-		_, rr = rr.div(rr, x, m)
-	} else if len(x) < numWords {
-		rr = rr.make(numWords)
-		rr.clear()
-		for i := range x {
-			rr[i] = x[i]
-		}
-	} else {
-		rr = x
+		_, x = nat(nil).div(nil, x, m)
+		// Note: now len(x) <= numWords, not guaranteed ==.
+	}
+	if len(x) < numWords {
+		rr := make(nat, numWords)
+		copy(rr, x)
+		x = rr
 	}
-	x = rr
 
 	// Ideally the precomputations would be performed outside, and reused
-	// k0 = -mˆ-1 mod 2ˆ_W. Algorithm from: Dumas, J.G. "On Newton–Raphson
+	// k0 = -m**-1 mod 2**_W. Algorithm from: Dumas, J.G. "On Newton–Raphson
 	// Iteration for Multiplicative Inverses Modulo Prime Powers".
 	k0 := 2 - m[0]
 	t := m[0] - 1
@@ -1105,9 +1081,9 @@ func (z nat) expNNMontgomery(x, y, m nat) nat {
 	}
 	k0 = -k0
 
-	// RR = 2ˆ(2*_W*len(m)) mod m
-	RR = RR.setWord(1)
-	zz = zz.shl(RR, uint(2*numWords*_W))
+	// RR = 2**(2*_W*len(m)) mod m
+	RR := nat(nil).setWord(1)
+	zz := nat(nil).shl(RR, uint(2*numWords*_W))
 	_, RR = RR.div(RR, zz, m)
 	if len(RR) < numWords {
 		zz = zz.make(numWords)
@@ -1115,8 +1091,7 @@ func (z nat) expNNMontgomery(x, y, m nat) nat {
 		RR = zz
 	}
 	// one = 1, with equal length to that of m
-	one = one.make(numWords)
-	one.clear()
+	one := make(nat, numWords)
 	one[0] = 1
 
 	const n = 4
@@ -1171,9 +1146,12 @@ func (z nat) expNNMontgomery(x, y, m nat) nat {
 	return zz.norm()
 }
 
-// probablyPrime performs reps Miller-Rabin tests to check whether n is prime.
-// If it returns true, n is prime with probability 1 - 1/4^reps.
-// If it returns false, n is not prime.
+// probablyPrime performs n Miller-Rabin tests to check whether x is prime.
+// If x is prime, it returns true.
+// If x is not prime, it returns false with probability at least 1 - ¼ⁿ.
+//
+// It is not suitable for judging primes that an adversary may have crafted
+// to fool this test.
 func (n nat) probablyPrime(reps int) bool {
 	if len(n) == 0 {
 		return false
diff --git a/src/math/big/nat_test.go b/src/math/big/nat_test.go
index 13caec4..563ccb3 100644
--- a/src/math/big/nat_test.go
+++ b/src/math/big/nat_test.go
@@ -158,7 +158,7 @@ var mulRangesN = []struct {
 
 func TestMulRangeN(t *testing.T) {
 	for i, r := range mulRangesN {
-		prod := nat(nil).mulRange(r.a, r.b).decimalString()
+		prod := string(nat(nil).mulRange(r.a, r.b).utoa(10))
 		if prod != r.prod {
 			t.Errorf("#%d: got %s; want %s", i, prod, r.prod)
 		}
@@ -326,7 +326,7 @@ func TestTrailingZeroBits(t *testing.T) {
 	for i := uint(0); i <= 3*_W; i++ {
 		n := y.trailingZeroBits()
 		if n != i {
-			t.Errorf("got 0x%s.trailingZeroBits() = %d; want %d", y.hexString(), n, i)
+			t.Errorf("got 0x%s.trailingZeroBits() = %d; want %d", y.utoa(16), n, i)
 		}
 		y = y.shl(y, 1)
 	}
@@ -419,11 +419,11 @@ func TestMontgomery(t *testing.T) {
 
 		if x.cmp(m) > 0 {
 			_, r := nat(nil).div(nil, x, m)
-			t.Errorf("#%d: x > m (0x%s > 0x%s; use 0x%s)", i, x.hexString(), m.hexString(), r.hexString())
+			t.Errorf("#%d: x > m (0x%s > 0x%s; use 0x%s)", i, x.utoa(16), m.utoa(16), r.utoa(16))
 		}
 		if y.cmp(m) > 0 {
 			_, r := nat(nil).div(nil, x, m)
-			t.Errorf("#%d: y > m (0x%s > 0x%s; use 0x%s)", i, y.hexString(), m.hexString(), r.hexString())
+			t.Errorf("#%d: y > m (0x%s > 0x%s; use 0x%s)", i, y.utoa(16), m.utoa(16), r.utoa(16))
 		}
 
 		var out nat
@@ -441,7 +441,7 @@ func TestMontgomery(t *testing.T) {
 		mi := &Int{abs: m}
 		p := new(Int).Mod(new(Int).Mul(xi, new(Int).Mul(yi, new(Int).ModInverse(new(Int).Lsh(one, uint(len(m))*_W), mi))), mi)
 		if out.cmp(p.abs.norm()) != 0 {
-			t.Errorf("#%d: out in table=0x%s, computed=0x%s", i, out.hexString(), p.abs.norm().hexString())
+			t.Errorf("#%d: out in table=0x%s, computed=0x%s", i, out.utoa(16), p.abs.norm().utoa(16))
 		}
 
 		// check k0 in table
@@ -457,7 +457,7 @@ func TestMontgomery(t *testing.T) {
 		z := nat(nil).montgomery(x, y, m, k0, len(m))
 		z = z.norm()
 		if z.cmp(out) != 0 {
-			t.Errorf("#%d: got 0x%s want 0x%s", i, z.hexString(), out.hexString())
+			t.Errorf("#%d: got 0x%s want 0x%s", i, z.utoa(16), out.utoa(16))
 		}
 	}
 }
@@ -483,6 +483,12 @@ var expNNTests = []struct {
 		"29834729834729834729347290846729561262544958723956495615629569234729836259263598127342374289365912465901365498236492183464",
 		"23537740700184054162508175125554701713153216681790245129157191391322321508055833908509185839069455749219131480588829346291",
 	},
+	{
+		"11521922904531591643048817447554701904414021819823889996244743037378330903763518501116638828335352811871131385129455853417360623007349090150042001944696604737499160174391019030572483602867266711107136838523916077674888297896995042968746762200926853379",
+		"426343618817810911523",
+		"444747819283133684179",
+		"42",
+	},
 }
 
 func TestExpNN(t *testing.T) {
@@ -498,7 +504,7 @@ func TestExpNN(t *testing.T) {
 
 		z := nat(nil).expNN(x, y, m)
 		if z.cmp(out) != 0 {
-			t.Errorf("#%d got %s want %s", i, z.decimalString(), out.decimalString())
+			t.Errorf("#%d got %s want %s", i, z.utoa(10), out.utoa(10))
 		}
 	}
 }
@@ -555,7 +561,7 @@ var fiboNums = []string{
 func TestFibo(t *testing.T) {
 	for i, want := range fiboNums {
 		n := i * 10
-		got := fibo(n).decimalString()
+		got := string(fibo(n).utoa(10))
 		if got != want {
 			t.Errorf("fibo(%d) failed: got %s want %s", n, got, want)
 		}
diff --git a/src/math/big/natconv.go b/src/math/big/natconv.go
index 022dcfe..d2ce667 100644
--- a/src/math/big/natconv.go
+++ b/src/math/big/natconv.go
@@ -14,6 +14,11 @@ import (
 	"sync"
 )
 
+const digits = "0123456789abcdefghijklmnopqrstuvwxyz"
+
+// Note: MaxBase = len(digits), but it must remain a rune constant
+//       for API compatibility.
+
 // MaxBase is the largest number base accepted for string conversions.
 const MaxBase = 'z' - 'a' + 10 + 1
 
@@ -229,56 +234,45 @@ func (z nat) scan(r io.ByteScanner, base int, fracOk bool) (res nat, b, count in
 	return
 }
 
-// Character sets for string conversion.
-const (
-	lowercaseDigits = "0123456789abcdefghijklmnopqrstuvwxyz"
-	uppercaseDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-)
-
-// decimalString returns a decimal representation of x.
-// It calls x.string with the charset "0123456789".
-func (x nat) decimalString() string {
-	return x.string(lowercaseDigits[:10])
+// utoa converts x to an ASCII representation in the given base;
+// base must be between 2 and MaxBase, inclusive.
+func (x nat) utoa(base int) []byte {
+	return x.itoa(false, base)
 }
 
-// hexString returns a hexadecimal representation of x.
-// It calls x.string with the charset "0123456789abcdef".
-func (x nat) hexString() string {
-	return x.string(lowercaseDigits[:16])
-}
+// itoa is like utoa but it prepends a '-' if neg && x != 0.
+func (x nat) itoa(neg bool, base int) []byte {
+	if base < 2 || base > MaxBase {
+		panic("invalid base")
+	}
 
-// string converts x to a string using digits from a charset; a digit with
-// value d is represented by charset[d]. The conversion base is determined
-// by len(charset), which must be >= 2 and <= 256.
-func (x nat) string(charset string) string {
-	b := Word(len(charset))
-
-	// special cases
-	switch {
-	case b < 2 || b > 256:
-		panic("invalid character set length")
-	case len(x) == 0:
-		return string(charset[0])
+	// x == 0
+	if len(x) == 0 {
+		return []byte("0")
 	}
+	// len(x) > 0
 
 	// allocate buffer for conversion
-	i := int(float64(x.bitLen())/math.Log2(float64(b))) + 1 // off by one at most
+	i := int(float64(x.bitLen())/math.Log2(float64(base))) + 1 // off by 1 at most
+	if neg {
+		i++
+	}
 	s := make([]byte, i)
 
 	// convert power of two and non power of two bases separately
-	if b == b&-b {
-		// shift is base-b digit size in bits
+	if b := Word(base); b == b&-b {
+		// shift is base b digit size in bits
 		shift := trailingZeroBits(b) // shift > 0 because b >= 2
-		mask := Word(1)<<shift - 1
-		w := x[0]
+		mask := Word(1<<shift - 1)
+		w := x[0]         // current word
 		nbits := uint(_W) // number of unprocessed bits in w
 
-		// convert less-significant words
+		// convert less-significant words (include leading zeros)
 		for k := 1; k < len(x); k++ {
 			// convert full digits
 			for nbits >= shift {
 				i--
-				s[i] = charset[w&mask]
+				s[i] = digits[w&mask]
 				w >>= shift
 				nbits -= shift
 			}
@@ -289,10 +283,10 @@ func (x nat) string(charset string) string {
 				w = x[k]
 				nbits = _W
 			} else {
-				// partial digit in current (k-1) and next (k) word
+				// partial digit in current word w (== x[k-1]) and next word x[k]
 				w |= x[k] << nbits
 				i--
-				s[i] = charset[w&mask]
+				s[i] = digits[w&mask]
 
 				// advance
 				w = x[k] >> (shift - nbits)
@@ -300,12 +294,11 @@ func (x nat) string(charset string) string {
 			}
 		}
 
-		// convert digits of most-significant word (omit leading zeros)
-		for nbits >= 0 && w != 0 {
+		// convert digits of most-significant word w (omit leading zeros)
+		for w != 0 {
 			i--
-			s[i] = charset[w&mask]
+			s[i] = digits[w&mask]
 			w >>= shift
-			nbits -= shift
 		}
 
 	} else {
@@ -319,18 +312,23 @@ func (x nat) string(charset string) string {
 		q := nat(nil).set(x)
 
 		// convert q to string s in base b
-		q.convertWords(s, charset, b, ndigits, bb, table)
+		q.convertWords(s, b, ndigits, bb, table)
 
 		// strip leading zeros
 		// (x != 0; thus s must contain at least one non-zero digit
 		// and the loop will terminate)
 		i = 0
-		for zero := charset[0]; s[i] == zero; {
+		for s[i] == '0' {
 			i++
 		}
 	}
 
-	return string(s[i:])
+	if neg {
+		i--
+		s[i] = '-'
+	}
+
+	return s[i:]
 }
 
 // Convert words of q to base b digits in s. If q is large, it is recursively "split in half"
@@ -349,7 +347,7 @@ func (x nat) string(charset string) string {
 // ~30x for 20000 digits. Use nat_test.go's BenchmarkLeafSize tests to optimize leafSize for
 // specific hardware.
 //
-func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word, table []divisor) {
+func (q nat) convertWords(s []byte, b Word, ndigits int, bb Word, table []divisor) {
 	// split larger blocks recursively
 	if table != nil {
 		// len(q) > leafSize > 0
@@ -374,8 +372,8 @@ func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word
 
 			// convert subblocks and collect results in s[:h] and s[h:]
 			h := len(s) - table[index].ndigits
-			r.convertWords(s[h:], charset, b, ndigits, bb, table[0:index])
-			s = s[:h] // == q.convertWords(s, charset, b, ndigits, bb, table[0:index+1])
+			r.convertWords(s[h:], b, ndigits, bb, table[0:index])
+			s = s[:h] // == q.convertWords(s, b, ndigits, bb, table[0:index+1])
 		}
 	}
 
@@ -393,7 +391,7 @@ func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word
 				// this appears to be faster for BenchmarkString10000Base10
 				// and smaller strings (but a bit slower for larger ones)
 				t := r / 10
-				s[i] = charset[r-t<<3-t-t] // TODO(gri) replace w/ t*10 once compiler produces better code
+				s[i] = '0' + byte(r-t<<3-t-t) // TODO(gri) replace w/ t*10 once compiler produces better code
 				r = t
 			}
 		}
@@ -403,17 +401,16 @@ func (q nat) convertWords(s []byte, charset string, b Word, ndigits int, bb Word
 			q, r = q.divW(q, bb)
 			for j := 0; j < ndigits && i > 0; j++ {
 				i--
-				s[i] = charset[r%b]
+				s[i] = digits[r%b]
 				r /= b
 			}
 		}
 	}
 
-	// prepend high-order zeroes
-	zero := charset[0]
-	for i > 0 { // while need more leading zeroes
+	// prepend high-order zeros
+	for i > 0 { // while need more leading zeros
 		i--
-		s[i] = zero
+		s[i] = '0'
 	}
 }
 
@@ -425,7 +422,7 @@ var leafSize int = 8 // number of Word-size binary values treat as a monolithic
 
 type divisor struct {
 	bbb     nat // divisor
-	nbits   int // bit length of divisor (discounting leading zeroes) ~= log2(bbb)
+	nbits   int // bit length of divisor (discounting leading zeros) ~= log2(bbb)
 	ndigits int // digit length of divisor in terms of output base digits
 }
 
diff --git a/src/math/big/natconv_test.go b/src/math/big/natconv_test.go
index f321fbc..028e5a8 100644
--- a/src/math/big/natconv_test.go
+++ b/src/math/big/natconv_test.go
@@ -5,20 +5,19 @@
 package big
 
 import (
+	"bytes"
 	"io"
 	"strings"
 	"testing"
 )
 
-func toString(x nat, charset string) string {
-	base := len(charset)
-
+func itoa(x nat, base int) []byte {
 	// special cases
 	switch {
 	case base < 2:
 		panic("illegal base")
 	case len(x) == 0:
-		return string(charset[0])
+		return []byte("0")
 	}
 
 	// allocate buffer for conversion
@@ -33,54 +32,53 @@ func toString(x nat, charset string) string {
 		i--
 		var r Word
 		q, r = q.divW(q, Word(base))
-		s[i] = charset[r]
+		s[i] = digits[r]
 	}
 
-	return string(s[i:])
+	return s[i:]
 }
 
 var strTests = []struct {
 	x nat    // nat value to be converted
-	c string // conversion charset
+	b int    // conversion base
 	s string // expected result
 }{
-	{nil, "01", "0"},
-	{nat{1}, "01", "1"},
-	{nat{0xc5}, "01", "11000101"},
-	{nat{03271}, lowercaseDigits[:8], "3271"},
-	{nat{10}, lowercaseDigits[:10], "10"},
-	{nat{1234567890}, uppercaseDigits[:10], "1234567890"},
-	{nat{0xdeadbeef}, lowercaseDigits[:16], "deadbeef"},
-	{nat{0xdeadbeef}, uppercaseDigits[:16], "DEADBEEF"},
-	{nat{0x229be7}, lowercaseDigits[:17], "1a2b3c"},
-	{nat{0x309663e6}, uppercaseDigits[:32], "O9COV6"},
+	{nil, 2, "0"},
+	{nat{1}, 2, "1"},
+	{nat{0xc5}, 2, "11000101"},
+	{nat{03271}, 8, "3271"},
+	{nat{10}, 10, "10"},
+	{nat{1234567890}, 10, "1234567890"},
+	{nat{0xdeadbeef}, 16, "deadbeef"},
+	{nat{0x229be7}, 17, "1a2b3c"},
+	{nat{0x309663e6}, 32, "o9cov6"},
 }
 
 func TestString(t *testing.T) {
-	// test invalid character set explicitly
+	// test invalid base explicitly
 	var panicStr string
 	func() {
 		defer func() {
 			panicStr = recover().(string)
 		}()
-		natOne.string("0")
+		natOne.utoa(1)
 	}()
-	if panicStr != "invalid character set length" {
-		t.Errorf("expected panic for invalid character set")
+	if panicStr != "invalid base" {
+		t.Errorf("expected panic for invalid base")
 	}
 
 	for _, a := range strTests {
-		s := a.x.string(a.c)
+		s := string(a.x.utoa(a.b))
 		if s != a.s {
 			t.Errorf("string%+v\n\tgot s = %s; want %s", a, s, a.s)
 		}
 
-		x, b, _, err := nat(nil).scan(strings.NewReader(a.s), len(a.c), false)
+		x, b, _, err := nat(nil).scan(strings.NewReader(a.s), a.b, false)
 		if x.cmp(a.x) != 0 {
 			t.Errorf("scan%+v\n\tgot z = %v; want %v", a, x, a.x)
 		}
-		if b != len(a.c) {
-			t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, len(a.c))
+		if b != a.b {
+			t.Errorf("scan%+v\n\tgot b = %d; want %d", a, b, a.b)
 		}
 		if err != nil {
 			t.Errorf("scan%+v\n\tgot error = %s", a, err)
@@ -236,7 +234,7 @@ func TestScanPi(t *testing.T) {
 	if err != nil {
 		t.Errorf("scanning pi: %s", err)
 	}
-	if s := z.decimalString(); s != pi {
+	if s := string(z.utoa(10)); s != pi {
 		t.Errorf("scanning pi: got %s", s)
 	}
 }
@@ -265,12 +263,12 @@ func BenchmarkScanPi(b *testing.B) {
 func BenchmarkStringPiParallel(b *testing.B) {
 	var x nat
 	x, _, _, _ = x.scan(strings.NewReader(pi), 0, false)
-	if x.decimalString() != pi {
+	if string(x.utoa(10)) != pi {
 		panic("benchmark incorrect: conversion failed")
 	}
 	b.RunParallel(func(pb *testing.PB) {
 		for pb.Next() {
-			x.decimalString()
+			x.utoa(10)
 		}
 	})
 }
@@ -304,15 +302,14 @@ func ScanHelper(b *testing.B, base int, x, y Word) {
 	var z nat
 	z = z.expWW(x, y)
 
-	var s string
-	s = z.string(lowercaseDigits[:base])
-	if t := toString(z, lowercaseDigits[:base]); t != s {
+	s := z.utoa(base)
+	if t := itoa(z, base); !bytes.Equal(s, t) {
 		b.Fatalf("scanning: got %s; want %s", s, t)
 	}
 	b.StartTimer()
 
 	for i := 0; i < b.N; i++ {
-		z.scan(strings.NewReader(s), base, false)
+		z.scan(bytes.NewReader(s), base, false)
 	}
 }
 
@@ -344,11 +341,11 @@ func StringHelper(b *testing.B, base int, x, y Word) {
 	b.StopTimer()
 	var z nat
 	z = z.expWW(x, y)
-	z.string(lowercaseDigits[:base]) // warm divisor cache
+	z.utoa(base) // warm divisor cache
 	b.StartTimer()
 
 	for i := 0; i < b.N; i++ {
-		_ = z.string(lowercaseDigits[:base])
+		_ = z.utoa(base)
 	}
 }
 
@@ -372,7 +369,7 @@ func BenchmarkLeafSize16(b *testing.B) { LeafSizeHelper(b, 10, 16) }
 func BenchmarkLeafSize32(b *testing.B) { LeafSizeHelper(b, 10, 32) } // try some large lengths
 func BenchmarkLeafSize64(b *testing.B) { LeafSizeHelper(b, 10, 64) }
 
-func LeafSizeHelper(b *testing.B, base Word, size int) {
+func LeafSizeHelper(b *testing.B, base, size int) {
 	b.StopTimer()
 	originalLeafSize := leafSize
 	resetTable(cacheBase10.table[:])
@@ -382,12 +379,12 @@ func LeafSizeHelper(b *testing.B, base Word, size int) {
 	for d := 1; d <= 10000; d *= 10 {
 		b.StopTimer()
 		var z nat
-		z = z.expWW(base, Word(d))           // build target number
-		_ = z.string(lowercaseDigits[:base]) // warm divisor cache
+		z = z.expWW(Word(base), Word(d)) // build target number
+		_ = z.utoa(base)                 // warm divisor cache
 		b.StartTimer()
 
 		for i := 0; i < b.N; i++ {
-			_ = z.string(lowercaseDigits[:base])
+			_ = z.utoa(base)
 		}
 	}
 
@@ -408,13 +405,13 @@ func resetTable(table []divisor) {
 }
 
 func TestStringPowers(t *testing.T) {
-	var b, p Word
-	for b = 2; b <= 16; b++ {
+	var p Word
+	for b := 2; b <= 16; b++ {
 		for p = 0; p <= 512; p++ {
-			x := nat(nil).expWW(b, p)
-			xs := x.string(lowercaseDigits[:b])
-			xs2 := toString(x, lowercaseDigits[:b])
-			if xs != xs2 {
+			x := nat(nil).expWW(Word(b), p)
+			xs := x.utoa(b)
+			xs2 := itoa(x, b)
+			if !bytes.Equal(xs, xs2) {
 				t.Errorf("failed at %d ** %d in base %d: %s != %s", b, p, b, xs, xs2)
 			}
 		}
diff --git a/src/math/big/rat.go b/src/math/big/rat.go
index fb16f18..2cd9ed0 100644
--- a/src/math/big/rat.go
+++ b/src/math/big/rat.go
@@ -7,8 +7,6 @@
 package big
 
 import (
-	"encoding/binary"
-	"errors"
 	"fmt"
 	"math"
 )
@@ -510,61 +508,3 @@ func (z *Rat) Quo(x, y *Rat) *Rat {
 	z.a.neg = a.neg != b.neg
 	return z.norm()
 }
-
-// Gob codec version. Permits backward-compatible changes to the encoding.
-const ratGobVersion byte = 1
-
-// GobEncode implements the gob.GobEncoder interface.
-func (x *Rat) GobEncode() ([]byte, error) {
-	if x == nil {
-		return nil, nil
-	}
-	buf := make([]byte, 1+4+(len(x.a.abs)+len(x.b.abs))*_S) // extra bytes for version and sign bit (1), and numerator length (4)
-	i := x.b.abs.bytes(buf)
-	j := x.a.abs.bytes(buf[:i])
-	n := i - j
-	if int(uint32(n)) != n {
-		// this should never happen
-		return nil, errors.New("Rat.GobEncode: numerator too large")
-	}
-	binary.BigEndian.PutUint32(buf[j-4:j], uint32(n))
-	j -= 1 + 4
-	b := ratGobVersion << 1 // make space for sign bit
-	if x.a.neg {
-		b |= 1
-	}
-	buf[j] = b
-	return buf[j:], nil
-}
-
-// GobDecode implements the gob.GobDecoder interface.
-func (z *Rat) GobDecode(buf []byte) error {
-	if len(buf) == 0 {
-		// Other side sent a nil or default value.
-		*z = Rat{}
-		return nil
-	}
-	b := buf[0]
-	if b>>1 != ratGobVersion {
-		return fmt.Errorf("Rat.GobDecode: encoding version %d not supported", b>>1)
-	}
-	const j = 1 + 4
-	i := j + binary.BigEndian.Uint32(buf[j-4:j])
-	z.a.neg = b&1 != 0
-	z.a.abs = z.a.abs.setBytes(buf[j:i])
-	z.b.abs = z.b.abs.setBytes(buf[i:])
-	return nil
-}
-
-// MarshalText implements the encoding.TextMarshaler interface.
-func (r *Rat) MarshalText() (text []byte, err error) {
-	return []byte(r.RatString()), nil
-}
-
-// UnmarshalText implements the encoding.TextUnmarshaler interface.
-func (r *Rat) UnmarshalText(text []byte) error {
-	if _, ok := r.SetString(string(text)); !ok {
-		return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Rat", text)
-	}
-	return nil
-}
diff --git a/src/math/big/rat_test.go b/src/math/big/rat_test.go
index 012d0c4..3a06fca 100644
--- a/src/math/big/rat_test.go
+++ b/src/math/big/rat_test.go
@@ -5,10 +5,6 @@
 package big
 
 import (
-	"bytes"
-	"encoding/gob"
-	"encoding/json"
-	"encoding/xml"
 	"math"
 	"testing"
 )
@@ -280,116 +276,6 @@ func TestRatSetFrac64Rat(t *testing.T) {
 	}
 }
 
-func TestRatGobEncoding(t *testing.T) {
-	var medium bytes.Buffer
-	enc := gob.NewEncoder(&medium)
-	dec := gob.NewDecoder(&medium)
-	for _, test := range encodingTests {
-		medium.Reset() // empty buffer for each test case (in case of failures)
-		var tx Rat
-		tx.SetString(test + ".14159265")
-		if err := enc.Encode(&tx); err != nil {
-			t.Errorf("encoding of %s failed: %s", &tx, err)
-		}
-		var rx Rat
-		if err := dec.Decode(&rx); err != nil {
-			t.Errorf("decoding of %s failed: %s", &tx, err)
-		}
-		if rx.Cmp(&tx) != 0 {
-			t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx)
-		}
-	}
-}
-
-// Sending a nil Rat pointer (inside a slice) on a round trip through gob should yield a zero.
-// TODO: top-level nils.
-func TestGobEncodingNilRatInSlice(t *testing.T) {
-	buf := new(bytes.Buffer)
-	enc := gob.NewEncoder(buf)
-	dec := gob.NewDecoder(buf)
-
-	var in = make([]*Rat, 1)
-	err := enc.Encode(&in)
-	if err != nil {
-		t.Errorf("gob encode failed: %q", err)
-	}
-	var out []*Rat
-	err = dec.Decode(&out)
-	if err != nil {
-		t.Fatalf("gob decode failed: %q", err)
-	}
-	if len(out) != 1 {
-		t.Fatalf("wrong len; want 1 got %d", len(out))
-	}
-	var zero Rat
-	if out[0].Cmp(&zero) != 0 {
-		t.Errorf("transmission of (*Int)(nill) failed: got %s want 0", out)
-	}
-}
-
-var ratNums = []string{
-	"-141592653589793238462643383279502884197169399375105820974944592307816406286",
-	"-1415926535897932384626433832795028841971",
-	"-141592653589793",
-	"-1",
-	"0",
-	"1",
-	"141592653589793",
-	"1415926535897932384626433832795028841971",
-	"141592653589793238462643383279502884197169399375105820974944592307816406286",
-}
-
-var ratDenoms = []string{
-	"1",
-	"718281828459045",
-	"7182818284590452353602874713526624977572",
-	"718281828459045235360287471352662497757247093699959574966967627724076630353",
-}
-
-func TestRatJSONEncoding(t *testing.T) {
-	for _, num := range ratNums {
-		for _, denom := range ratDenoms {
-			var tx Rat
-			tx.SetString(num + "/" + denom)
-			b, err := json.Marshal(&tx)
-			if err != nil {
-				t.Errorf("marshaling of %s failed: %s", &tx, err)
-				continue
-			}
-			var rx Rat
-			if err := json.Unmarshal(b, &rx); err != nil {
-				t.Errorf("unmarshaling of %s failed: %s", &tx, err)
-				continue
-			}
-			if rx.Cmp(&tx) != 0 {
-				t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx)
-			}
-		}
-	}
-}
-
-func TestRatXMLEncoding(t *testing.T) {
-	for _, num := range ratNums {
-		for _, denom := range ratDenoms {
-			var tx Rat
-			tx.SetString(num + "/" + denom)
-			b, err := xml.Marshal(&tx)
-			if err != nil {
-				t.Errorf("marshaling of %s failed: %s", &tx, err)
-				continue
-			}
-			var rx Rat
-			if err := xml.Unmarshal(b, &rx); err != nil {
-				t.Errorf("unmarshaling of %s failed: %s", &tx, err)
-				continue
-			}
-			if rx.Cmp(&tx) != 0 {
-				t.Errorf("XML encoding of %s failed: got %s want %s", &tx, &rx, &tx)
-			}
-		}
-	}
-}
-
 func TestIssue2379(t *testing.T) {
 	// 1) no aliasing
 	q := NewRat(3, 2)
diff --git a/src/math/big/ratconv.go b/src/math/big/ratconv.go
index 961ff64..4566ff4 100644
--- a/src/math/big/ratconv.go
+++ b/src/math/big/ratconv.go
@@ -188,11 +188,15 @@ func scanExponent(r io.ByteScanner, binExpOk bool) (exp int64, base int, err err
 
 // String returns a string representation of x in the form "a/b" (even if b == 1).
 func (x *Rat) String() string {
-	s := "/1"
+	var buf []byte
+	buf = x.a.Append(buf, 10)
+	buf = append(buf, '/')
 	if len(x.b.abs) != 0 {
-		s = "/" + x.b.abs.decimalString()
+		buf = x.b.Append(buf, 10)
+	} else {
+		buf = append(buf, '1')
 	}
-	return x.a.String() + s
+	return string(buf)
 }
 
 // RatString returns a string representation of x in the form "a/b" if b != 1,
@@ -208,12 +212,17 @@ func (x *Rat) RatString() string {
 // digits of precision after the decimal point. The last digit is rounded to
 // nearest, with halves rounded away from zero.
 func (x *Rat) FloatString(prec int) string {
+	var buf []byte
+
 	if x.IsInt() {
-		s := x.a.String()
+		buf = x.a.Append(buf, 10)
 		if prec > 0 {
-			s += "." + strings.Repeat("0", prec)
+			buf = append(buf, '.')
+			for i := prec; i > 0; i-- {
+				buf = append(buf, '0')
+			}
 		}
-		return s
+		return string(buf)
 	}
 	// x.b.abs != 0
 
@@ -237,16 +246,19 @@ func (x *Rat) FloatString(prec int) string {
 		}
 	}
 
-	s := q.decimalString()
 	if x.a.neg {
-		s = "-" + s
+		buf = append(buf, '-')
 	}
+	buf = append(buf, q.utoa(10)...) // itoa ignores sign if q == 0
 
 	if prec > 0 {
-		rs := r.decimalString()
-		leadingZeros := prec - len(rs)
-		s += "." + strings.Repeat("0", leadingZeros) + rs
+		buf = append(buf, '.')
+		rs := r.utoa(10)
+		for i := prec - len(rs); i > 0; i-- {
+			buf = append(buf, '0')
+		}
+		buf = append(buf, rs...)
 	}
 
-	return s
+	return string(buf)
 }
diff --git a/src/math/big/ratmarsh.go b/src/math/big/ratmarsh.go
new file mode 100644
index 0000000..b82e8d4
--- /dev/null
+++ b/src/math/big/ratmarsh.go
@@ -0,0 +1,73 @@
+// Copyright 2015 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 file implements encoding/decoding of Rats.
+
+package big
+
+import (
+	"encoding/binary"
+	"errors"
+	"fmt"
+)
+
+// Gob codec version. Permits backward-compatible changes to the encoding.
+const ratGobVersion byte = 1
+
+// GobEncode implements the gob.GobEncoder interface.
+func (x *Rat) GobEncode() ([]byte, error) {
+	if x == nil {
+		return nil, nil
+	}
+	buf := make([]byte, 1+4+(len(x.a.abs)+len(x.b.abs))*_S) // extra bytes for version and sign bit (1), and numerator length (4)
+	i := x.b.abs.bytes(buf)
+	j := x.a.abs.bytes(buf[:i])
+	n := i - j
+	if int(uint32(n)) != n {
+		// this should never happen
+		return nil, errors.New("Rat.GobEncode: numerator too large")
+	}
+	binary.BigEndian.PutUint32(buf[j-4:j], uint32(n))
+	j -= 1 + 4
+	b := ratGobVersion << 1 // make space for sign bit
+	if x.a.neg {
+		b |= 1
+	}
+	buf[j] = b
+	return buf[j:], nil
+}
+
+// GobDecode implements the gob.GobDecoder interface.
+func (z *Rat) GobDecode(buf []byte) error {
+	if len(buf) == 0 {
+		// Other side sent a nil or default value.
+		*z = Rat{}
+		return nil
+	}
+	b := buf[0]
+	if b>>1 != ratGobVersion {
+		return fmt.Errorf("Rat.GobDecode: encoding version %d not supported", b>>1)
+	}
+	const j = 1 + 4
+	i := j + binary.BigEndian.Uint32(buf[j-4:j])
+	z.a.neg = b&1 != 0
+	z.a.abs = z.a.abs.setBytes(buf[j:i])
+	z.b.abs = z.b.abs.setBytes(buf[i:])
+	return nil
+}
+
+// MarshalText implements the encoding.TextMarshaler interface.
+func (x *Rat) MarshalText() (text []byte, err error) {
+	// TODO(gri): get rid of the []byte/string conversion
+	return []byte(x.RatString()), nil
+}
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface.
+func (z *Rat) UnmarshalText(text []byte) error {
+	// TODO(gri): get rid of the []byte/string conversion
+	if _, ok := z.SetString(string(text)); !ok {
+		return fmt.Errorf("math/big: cannot unmarshal %q into a *big.Rat", text)
+	}
+	return nil
+}
diff --git a/src/math/big/ratmarsh_test.go b/src/math/big/ratmarsh_test.go
new file mode 100644
index 0000000..351d109
--- /dev/null
+++ b/src/math/big/ratmarsh_test.go
@@ -0,0 +1,125 @@
+// Copyright 2015 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 big
+
+import (
+	"bytes"
+	"encoding/gob"
+	"encoding/json"
+	"encoding/xml"
+	"testing"
+)
+
+func TestRatGobEncoding(t *testing.T) {
+	var medium bytes.Buffer
+	enc := gob.NewEncoder(&medium)
+	dec := gob.NewDecoder(&medium)
+	for _, test := range encodingTests {
+		medium.Reset() // empty buffer for each test case (in case of failures)
+		var tx Rat
+		tx.SetString(test + ".14159265")
+		if err := enc.Encode(&tx); err != nil {
+			t.Errorf("encoding of %s failed: %s", &tx, err)
+			continue
+		}
+		var rx Rat
+		if err := dec.Decode(&rx); err != nil {
+			t.Errorf("decoding of %s failed: %s", &tx, err)
+			continue
+		}
+		if rx.Cmp(&tx) != 0 {
+			t.Errorf("transmission of %s failed: got %s want %s", &tx, &rx, &tx)
+		}
+	}
+}
+
+// Sending a nil Rat pointer (inside a slice) on a round trip through gob should yield a zero.
+// TODO: top-level nils.
+func TestGobEncodingNilRatInSlice(t *testing.T) {
+	buf := new(bytes.Buffer)
+	enc := gob.NewEncoder(buf)
+	dec := gob.NewDecoder(buf)
+
+	var in = make([]*Rat, 1)
+	err := enc.Encode(&in)
+	if err != nil {
+		t.Errorf("gob encode failed: %q", err)
+	}
+	var out []*Rat
+	err = dec.Decode(&out)
+	if err != nil {
+		t.Fatalf("gob decode failed: %q", err)
+	}
+	if len(out) != 1 {
+		t.Fatalf("wrong len; want 1 got %d", len(out))
+	}
+	var zero Rat
+	if out[0].Cmp(&zero) != 0 {
+		t.Fatalf("transmission of (*Int)(nil) failed: got %s want 0", out)
+	}
+}
+
+var ratNums = []string{
+	"-141592653589793238462643383279502884197169399375105820974944592307816406286",
+	"-1415926535897932384626433832795028841971",
+	"-141592653589793",
+	"-1",
+	"0",
+	"1",
+	"141592653589793",
+	"1415926535897932384626433832795028841971",
+	"141592653589793238462643383279502884197169399375105820974944592307816406286",
+}
+
+var ratDenoms = []string{
+	"1",
+	"718281828459045",
+	"7182818284590452353602874713526624977572",
+	"718281828459045235360287471352662497757247093699959574966967627724076630353",
+}
+
+func TestRatJSONEncoding(t *testing.T) {
+	for _, num := range ratNums {
+		for _, denom := range ratDenoms {
+			var tx Rat
+			tx.SetString(num + "/" + denom)
+			b, err := json.Marshal(&tx)
+			if err != nil {
+				t.Errorf("marshaling of %s failed: %s", &tx, err)
+				continue
+			}
+			var rx Rat
+			if err := json.Unmarshal(b, &rx); err != nil {
+				t.Errorf("unmarshaling of %s failed: %s", &tx, err)
+				continue
+			}
+			if rx.Cmp(&tx) != 0 {
+				t.Errorf("JSON encoding of %s failed: got %s want %s", &tx, &rx, &tx)
+			}
+		}
+	}
+}
+
+func TestRatXMLEncoding(t *testing.T) {
+	for _, num := range ratNums {
+		for _, denom := range ratDenoms {
+			var tx Rat
+			tx.SetString(num + "/" + denom)
+			b, err := xml.Marshal(&tx)
+			if err != nil {
+				t.Errorf("marshaling of %s failed: %s", &tx, err)
+				continue
+			}
+			var rx Rat
+			if err := xml.Unmarshal(b, &rx); err != nil {
+				t.Errorf("unmarshaling of %s failed: %s", &tx, err)
+				continue
+			}
+			if rx.Cmp(&tx) != 0 {
+				t.Errorf("XML encoding of %s failed: got %s want %s", &tx, &rx, &tx)
+			}
+		}
+	}
+}
diff --git a/src/math/cmplx/cmath_test.go b/src/math/cmplx/cmath_test.go
index f285646..18d9be8 100644
--- a/src/math/cmplx/cmath_test.go
+++ b/src/math/cmplx/cmath_test.go
@@ -438,8 +438,10 @@ func tolerance(a, b, e float64) bool {
 		d = -d
 	}
 
-	if a != 0 {
-		e = e * a
+	// note: b is correct (expected) value, a is actual value.
+	// make error tolerance a fraction of b, not a.
+	if b != 0 {
+		e = e * b
 		if e < 0 {
 			e = -e
 		}
@@ -460,8 +462,8 @@ func alike(a, b float64) bool {
 
 func cTolerance(a, b complex128, e float64) bool {
 	d := Abs(a - b)
-	if a != 0 {
-		e = e * Abs(a)
+	if b != 0 {
+		e = e * Abs(b)
 		if e < 0 {
 			e = -e
 		}
diff --git a/src/math/cmplx/sqrt.go b/src/math/cmplx/sqrt.go
index 4ef6807..276be07 100644
--- a/src/math/cmplx/sqrt.go
+++ b/src/math/cmplx/sqrt.go
@@ -40,7 +40,7 @@ import "math"
 //                       1/2
 // Im w  =  [ (r - x)/2 ]   .
 //
-// Cancellation error in r-x or r+x is avoided by using the
+// Cancelation error in r-x or r+x is avoided by using the
 // identity  2 Re w Im w  =  y.
 //
 // Note that -w is also a square root of z.  The root chosen
diff --git a/src/math/expm1.go b/src/math/expm1.go
index 064e131..670b96d 100644
--- a/src/math/expm1.go
+++ b/src/math/expm1.go
@@ -227,7 +227,7 @@ func expm1(x float64) float64 {
 			y = Float64frombits(Float64bits(y) + uint64(k)<<52) // add k to y's exponent
 			return y
 		}
-		t := Float64frombits(uint64((0x3ff - k) << 52)) // 2**-k
+		t := Float64frombits(uint64(0x3ff-k) << 52) // 2**-k
 		y := x - (e + t)
 		y += 1
 		y = Float64frombits(Float64bits(y) + uint64(k)<<52) // add k to y's exponent
diff --git a/src/math/floor_amd64.s b/src/math/floor_amd64.s
index 67b7cde..7f512e7 100644
--- a/src/math/floor_amd64.s
+++ b/src/math/floor_amd64.s
@@ -6,8 +6,25 @@
 
 #define Big		0x4330000000000000 // 2**52
 
+// func hasSSE4() bool
+// returns whether SSE4.1 is supported
+TEXT ·hasSSE4(SB),NOSPLIT,$0
+	XORQ AX, AX
+	INCL AX
+	CPUID
+	SHRQ $19, CX
+	ANDQ $1, CX
+	MOVB CX, ret+0(FP)
+	RET
+
 // func Floor(x float64) float64
 TEXT ·Floor(SB),NOSPLIT,$0
+	CMPB    math·useSSE4(SB), $1
+	JNE     nosse4
+	ROUNDSD $1, x+0(FP), X0
+	MOVQ X0, ret+8(FP)
+	RET
+nosse4:
 	MOVQ	x+0(FP), AX
 	MOVQ	$~(1<<63), DX // sign bit mask
 	ANDQ	AX,DX // DX = |x|
@@ -30,6 +47,12 @@ isBig_floor:
 
 // func Ceil(x float64) float64
 TEXT ·Ceil(SB),NOSPLIT,$0
+	CMPB    math·useSSE4(SB), $1
+	JNE     nosse4
+	ROUNDSD $2, x+0(FP), X0
+	MOVQ X0, ret+8(FP)
+	RET
+nosse4:
 	MOVQ	x+0(FP), AX
 	MOVQ	$~(1<<63), DX // sign bit mask
 	MOVQ	AX, BX // BX = copy of x
diff --git a/src/math/floor_asm.go b/src/math/floor_asm.go
new file mode 100644
index 0000000..28e56a5
--- /dev/null
+++ b/src/math/floor_asm.go
@@ -0,0 +1,12 @@
+// Copyright 2015 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.
+
+// +build amd64 amd64p32
+
+package math
+
+//defined in floor_amd64.s
+func hasSSE4() bool
+
+var useSSE4 = hasSSE4()
diff --git a/src/math/j0.go b/src/math/j0.go
index c20a9b2..de77388 100644
--- a/src/math/j0.go
+++ b/src/math/j0.go
@@ -38,7 +38,7 @@ package math
 //                      = 1/sqrt(2) * (cos(x) + sin(x))
 //              sin(x0) = sin(x)cos(pi/4)-cos(x)sin(pi/4)
 //                      = 1/sqrt(2) * (sin(x) - cos(x))
-//         (To avoid cancellation, use
+//         (To avoid cancelation, use
 //              sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
 //         to compute the worse one.)
 //
@@ -188,7 +188,7 @@ func Y0(x float64) float64 {
 		//             =  1/sqrt(2) * (sin(x) + cos(x))
 		//     sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
 		//             =  1/sqrt(2) * (sin(x) - cos(x))
-		// To avoid cancellation, use
+		// To avoid cancelation, use
 		//     sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
 		// to compute the worse one.
 
diff --git a/src/math/j1.go b/src/math/j1.go
index 7ac186b..c537a72 100644
--- a/src/math/j1.go
+++ b/src/math/j1.go
@@ -39,7 +39,7 @@ package math
 //                      =  1/sqrt(2) * (sin(x) - cos(x))
 //              sin(x1) =  sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
 //                      = -1/sqrt(2) * (sin(x) + cos(x))
-//         (To avoid cancellation, use
+//         (To avoid cancelation, use
 //              sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
 //         to compute the worse one.)
 //
@@ -197,7 +197,7 @@ func Y1(x float64) float64 {
 		//                 =  1/sqrt(2) * (sin(x) - cos(x))
 		//         sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
 		//                 = -1/sqrt(2) * (cos(x) + sin(x))
-		// To avoid cancellation, use
+		// To avoid cancelation, use
 		//     sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
 		// to compute the worse one.
 
diff --git a/src/math/jn.go b/src/math/jn.go
index a7909eb..ffb8a00 100644
--- a/src/math/jn.go
+++ b/src/math/jn.go
@@ -200,13 +200,11 @@ func Jn(n int, x float64) float64 {
 				for i := n - 1; i > 0; i-- {
 					di := float64(i + i)
 					a, b = b, b*di/x-a
-					di -= 2
 				}
 			} else {
 				for i := n - 1; i > 0; i-- {
 					di := float64(i + i)
 					a, b = b, b*di/x-a
-					di -= 2
 					// scale b to avoid spurious overflow
 					if b > 1e100 {
 						a /= b
diff --git a/src/math/modf.go b/src/math/modf.go
index 1e8376a..81cb8b5 100644
--- a/src/math/modf.go
+++ b/src/math/modf.go
@@ -14,9 +14,12 @@ func Modf(f float64) (int float64, frac float64)
 
 func modf(f float64) (int float64, frac float64) {
 	if f < 1 {
-		if f < 0 {
+		switch {
+		case f < 0:
 			int, frac = Modf(-f)
 			return -int, -frac
+		case f == 0:
+			return f, f // Return -0, -0 when f == -0
 		}
 		return 0, f
 	}
diff --git a/src/math/modf_386.s b/src/math/modf_386.s
index 3debd3b..d549f1d 100644
--- a/src/math/modf_386.s
+++ b/src/math/modf_386.s
@@ -6,6 +6,19 @@
 
 // func Modf(f float64) (int float64, frac float64)
 TEXT ·Modf(SB),NOSPLIT,$0
+	// special case for f == -0.0
+	MOVL f+4(FP), DX	// high word
+	MOVL f+0(FP), AX	// low word
+	CMPL DX, $(1<<31)	// beginning of -0.0
+	JNE notNegativeZero
+	CMPL AX, $0			// could be denormalized
+	JNE notNegativeZero
+	MOVL AX, int+8(FP)
+	MOVL DX, int+12(FP)
+	MOVL AX, frac+16(FP)
+	MOVL DX, frac+20(FP)
+	RET
+notNegativeZero:
 	FMOVD   f+0(FP), F0  // F0=f
 	FMOVD   F0, F1       // F0=f, F1=f
 	FSTCW   -2(SP)       // save old Control Word
diff --git a/src/math/rand/rand.go b/src/math/rand/rand.go
index 6360128..d693bfb 100644
--- a/src/math/rand/rand.go
+++ b/src/math/rand/rand.go
@@ -113,19 +113,18 @@ func (r *Rand) Float64() float64 {
 	//
 	// There is one bug in the value stream: r.Int63() may be so close
 	// to 1<<63 that the division rounds up to 1.0, and we've guaranteed
-	// that the result is always less than 1.0. To fix that, we treat the
-	// range as cyclic and map 1 back to 0. This is justified by observing
-	// that while some of the values rounded down to 0, nothing was
-	// rounding up to 0, so 0 was underrepresented in the results.
-	// Mapping 1 back to zero restores some balance.
-	// (The balance is not perfect because the implementation
-	// returns denormalized numbers for very small r.Int63(),
-	// and those steal from what would normally be 0 results.)
-	// The remapping only happens 1/2⁵³ of the time, so most clients
+	// that the result is always less than 1.0.
+	//
+	// We tried to fix this by mapping 1.0 back to 0.0, but since float64
+	// values near 0 are much denser than near 1, mapping 1 to 0 caused
+	// a theoretically significant overshoot in the probability of returning 0.
+	// Instead of that, if we round up to 1, just try again.
+	// Getting 1 only happens 1/2⁵³ of the time, so most clients
 	// will not observe it anyway.
+again:
 	f := float64(r.Int63()) / (1 << 63)
 	if f == 1 {
-		f = 0
+		goto again // resample; this branch is taken O(never)
 	}
 	return f
 }
@@ -134,13 +133,11 @@ func (r *Rand) Float64() float64 {
 func (r *Rand) Float32() float32 {
 	// Same rationale as in Float64: we want to preserve the Go 1 value
 	// stream except we want to fix it not to return 1.0
-	// There is a double rounding going on here, but the argument for
-	// mapping 1 to 0 still applies: 0 was underrepresented before,
-	// so mapping 1 to 0 doesn't cause too many 0s.
 	// This only happens 1/2²⁴ of the time (plus the 1/2⁵³ of the time in Float64).
+again:
 	f := float32(r.Float64())
 	if f == 1 {
-		f = 0
+		goto again // resample; this branch is taken O(very rarely)
 	}
 	return f
 }
@@ -148,6 +145,11 @@ func (r *Rand) Float32() float32 {
 // Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
 func (r *Rand) Perm(n int) []int {
 	m := make([]int, n)
+	// In the following loop, the iteration when i=0 always swaps m[0] with m[0].
+	// A change to remove this useless iteration is to assign 1 to i in the init
+	// statement. But Perm also effects r. Making this change will affect
+	// the final state of r. So this change can't be made for compatibility
+	// reasons for Go 1.
 	for i := 0; i < n; i++ {
 		j := r.Intn(i + 1)
 		m[i] = m[j]
@@ -156,6 +158,19 @@ func (r *Rand) Perm(n int) []int {
 	return m
 }
 
+// Read generates len(p) random bytes and writes them into p. It
+// always returns len(p) and a nil error.
+func (r *Rand) Read(p []byte) (n int, err error) {
+	for i := 0; i < len(p); i += 7 {
+		val := r.src.Int63()
+		for j := 0; i+j < len(p) && j < 7; j++ {
+			p[i+j] = byte(val)
+			val >>= 8
+		}
+	}
+	return len(p), nil
+}
+
 /*
  * Top-level convenience functions
  */
@@ -209,6 +224,10 @@ func Float32() float32 { return globalRand.Float32() }
 // from the default Source.
 func Perm(n int) []int { return globalRand.Perm(n) }
 
+// Read generates len(p) random bytes from the default Source and
+// writes them into p. It always returns len(p) and a nil error.
+func Read(p []byte) (n int, err error) { return globalRand.Read(p) }
+
 // NormFloat64 returns a normally distributed float64 in the range
 // [-math.MaxFloat64, +math.MaxFloat64] with
 // standard normal distribution (mean = 0, stddev = 1)
diff --git a/src/math/rand/rand_test.go b/src/math/rand/rand_test.go
index c61494f..8d68335 100644
--- a/src/math/rand/rand_test.go
+++ b/src/math/rand/rand_test.go
@@ -7,6 +7,7 @@ package rand
 import (
 	"errors"
 	"fmt"
+	"internal/testenv"
 	"math"
 	"os"
 	"runtime"
@@ -327,9 +328,10 @@ func TestExpTables(t *testing.T) {
 func TestFloat32(t *testing.T) {
 	// For issue 6721, the problem came after 7533753 calls, so check 10e6.
 	num := int(10e6)
+	// But do the full amount only on builders (not locally).
 	// But ARM5 floating point emulation is slow (Issue 10749), so
 	// do less for that builder:
-	if testing.Short() && runtime.GOARCH == "arm" && os.Getenv("GOARM") == "5" {
+	if testing.Short() && (testenv.Builder() == "" || runtime.GOARCH == "arm" && os.Getenv("GOARM") == "5") {
 		num /= 100 // 1.72 seconds instead of 172 seconds
 	}
 
@@ -342,6 +344,59 @@ func TestFloat32(t *testing.T) {
 	}
 }
 
+func testReadUniformity(t *testing.T, n int, seed int64) {
+	r := New(NewSource(seed))
+	buf := make([]byte, n)
+	nRead, err := r.Read(buf)
+	if err != nil {
+		t.Errorf("Read err %v", err)
+	}
+	if nRead != n {
+		t.Errorf("Read returned unexpected n; %d != %d", nRead, n)
+	}
+
+	// Expect a uniform distribution of byte values, which lie in [0, 255].
+	var (
+		mean       = 255.0 / 2
+		stddev     = math.Sqrt(255.0 * 255.0 / 12.0)
+		errorScale = stddev / math.Sqrt(float64(n))
+	)
+
+	expected := &statsResults{mean, stddev, 0.10 * errorScale, 0.08 * errorScale}
+
+	// Cast bytes as floats to use the common distribution-validity checks.
+	samples := make([]float64, n)
+	for i, val := range buf {
+		samples[i] = float64(val)
+	}
+	// Make sure that the entire set matches the expected distribution.
+	checkSampleDistribution(t, samples, expected)
+}
+
+func TestRead(t *testing.T) {
+	testBufferSizes := []int{
+		2, 4, 7, 64, 1024, 1 << 16, 1 << 20,
+	}
+	for _, seed := range testSeeds {
+		for _, n := range testBufferSizes {
+			testReadUniformity(t, n, seed)
+		}
+	}
+}
+
+func TestReadEmpty(t *testing.T) {
+	r := New(NewSource(1))
+	buf := make([]byte, 0)
+	n, err := r.Read(buf)
+	if err != nil {
+		t.Errorf("Read err into empty buffer; %v", err)
+	}
+	if n != 0 {
+		t.Errorf("Read into empty buffer returned unexpected n of %d", n)
+	}
+
+}
+
 // Benchmarks
 
 func BenchmarkInt63Threadsafe(b *testing.B) {
@@ -405,3 +460,30 @@ func BenchmarkPerm30(b *testing.B) {
 		r.Perm(30)
 	}
 }
+
+func BenchmarkRead3(b *testing.B) {
+	r := New(NewSource(1))
+	buf := make([]byte, 3)
+	b.ResetTimer()
+	for n := b.N; n > 0; n-- {
+		r.Read(buf)
+	}
+}
+
+func BenchmarkRead64(b *testing.B) {
+	r := New(NewSource(1))
+	buf := make([]byte, 64)
+	b.ResetTimer()
+	for n := b.N; n > 0; n-- {
+		r.Read(buf)
+	}
+}
+
+func BenchmarkRead1000(b *testing.B) {
+	r := New(NewSource(1))
+	buf := make([]byte, 1000)
+	b.ResetTimer()
+	for n := b.N; n > 0; n-- {
+		r.Read(buf)
+	}
+}
diff --git a/src/math/rand/regress_test.go b/src/math/rand/regress_test.go
index 2b012af..9ae5357 100644
--- a/src/math/rand/regress_test.go
+++ b/src/math/rand/regress_test.go
@@ -25,6 +25,7 @@ func TestRegress(t *testing.T) {
 	var int32s = []int32{1, 10, 32, 1 << 20, 1<<20 + 1, 1000000000, 1 << 30, 1<<31 - 2, 1<<31 - 1}
 	var int64s = []int64{1, 10, 32, 1 << 20, 1<<20 + 1, 1000000000, 1 << 30, 1<<31 - 2, 1<<31 - 1, 1000000000000000000, 1 << 60, 1<<63 - 2, 1<<63 - 1}
 	var permSizes = []int{0, 1, 5, 8, 9, 10, 16}
+	var readBufferSizes = []int{1, 7, 8, 9, 10}
 	r := New(NewSource(0))
 
 	rv := reflect.ValueOf(r)
@@ -40,9 +41,6 @@ func TestRegress(t *testing.T) {
 		if mt.NumOut() == 0 {
 			continue
 		}
-		if mt.NumOut() != 1 {
-			t.Fatalf("unexpected result count for r.%s", m.Name)
-		}
 		r.Seed(0)
 		for repeat := 0; repeat < 20; repeat++ {
 			var args []reflect.Value
@@ -74,14 +72,25 @@ func TestRegress(t *testing.T) {
 
 				case reflect.Int64:
 					x = int64s[repeat%len(int64s)]
+
+				case reflect.Slice:
+					if m.Name == "Read" {
+						n := readBufferSizes[repeat%len(readBufferSizes)]
+						x = make([]byte, n)
+					}
 				}
 				argstr = fmt.Sprint(x)
 				args = append(args, reflect.ValueOf(x))
 			}
-			out := mv.Call(args)[0].Interface()
+
+			var out interface{}
+			out = mv.Call(args)[0].Interface()
 			if m.Name == "Int" || m.Name == "Intn" {
 				out = int64(out.(int))
 			}
+			if m.Name == "Read" {
+				out = args[0].Interface().([]byte)
+			}
 			if *printgolden {
 				var val string
 				big := int64(1 << 60)
@@ -332,24 +341,44 @@ var regressGolden = []interface{}{
 	[]int{2, 1, 7, 0, 6, 3, 4, 5},       // Perm(8)
 	[]int{8, 7, 5, 3, 4, 6, 0, 1, 2},    // Perm(9)
 	[]int{1, 0, 2, 5, 7, 6, 9, 8, 3, 4}, // Perm(10)
-	uint32(4059586549),                  // Uint32()
-	uint32(1052117029),                  // Uint32()
-	uint32(2817310706),                  // Uint32()
-	uint32(233405013),                   // Uint32()
-	uint32(1578775030),                  // Uint32()
-	uint32(1243308993),                  // Uint32()
-	uint32(826517535),                   // Uint32()
-	uint32(2814630155),                  // Uint32()
-	uint32(3853314576),                  // Uint32()
-	uint32(718781857),                   // Uint32()
-	uint32(1239465936),                  // Uint32()
-	uint32(3876658295),                  // Uint32()
-	uint32(3649778518),                  // Uint32()
-	uint32(1172727096),                  // Uint32()
-	uint32(2615979505),                  // Uint32()
-	uint32(1089444252),                  // Uint32()
-	uint32(3327114623),                  // Uint32()
-	uint32(75079301),                    // Uint32()
-	uint32(3380456901),                  // Uint32()
-	uint32(3433369789),                  // Uint32()
+	[]byte{0x1},                         // Read([0])
+	[]byte{0xc0, 0x41, 0xd3, 0xff, 0x12, 0x4, 0x5b},                   // Read([0 0 0 0 0 0 0])
+	[]byte{0x73, 0xc8, 0x6e, 0x4f, 0xf9, 0x5f, 0xf6, 0x62},            // Read([0 0 0 0 0 0 0 0])
+	[]byte{0x4a, 0x2d, 0xb, 0x75, 0xfb, 0x18, 0xd, 0xaf, 0x48},        // Read([0 0 0 0 0 0 0 0 0])
+	[]byte{0x39, 0x46, 0x51, 0x85, 0xf, 0xd4, 0xa1, 0x78, 0x89, 0x2e}, // Read([0 0 0 0 0 0 0 0 0 0])
+	[]byte{0x51}, // Read([0])
+	[]byte{0x4e, 0xe2, 0xd3, 0xd0, 0xd0, 0xde, 0x6b},                   // Read([0 0 0 0 0 0 0])
+	[]byte{0xf8, 0xf9, 0xb4, 0x4c, 0xe8, 0x5f, 0xf0, 0x44},             // Read([0 0 0 0 0 0 0 0])
+	[]byte{0x3b, 0xbf, 0x85, 0x7a, 0xab, 0x99, 0xc5, 0xb2, 0x52},       // Read([0 0 0 0 0 0 0 0 0])
+	[]byte{0xa8, 0xae, 0xb7, 0x9e, 0xf8, 0x56, 0xf6, 0x59, 0xc1, 0x8f}, // Read([0 0 0 0 0 0 0 0 0 0])
+	[]byte{0xc7}, // Read([0])
+	[]byte{0x5f, 0x67, 0xcf, 0xe2, 0x42, 0xcf, 0x3c},                   // Read([0 0 0 0 0 0 0])
+	[]byte{0xc3, 0x54, 0xf3, 0xed, 0xe2, 0xd6, 0xbe, 0xcc},             // Read([0 0 0 0 0 0 0 0])
+	[]byte{0x6a, 0x9f, 0x4a, 0x57, 0x8b, 0xcb, 0x9e, 0xf2, 0xd4},       // Read([0 0 0 0 0 0 0 0 0])
+	[]byte{0x6d, 0x29, 0x97, 0x61, 0xea, 0x9e, 0x4f, 0x5a, 0xa6, 0xae}, // Read([0 0 0 0 0 0 0 0 0 0])
+	[]byte{0xaa}, // Read([0])
+	[]byte{0x20, 0xef, 0xcd, 0x6c, 0xea, 0x84, 0xb6},                   // Read([0 0 0 0 0 0 0])
+	[]byte{0x92, 0x5e, 0x60, 0x7b, 0xe0, 0x63, 0x71, 0x6f},             // Read([0 0 0 0 0 0 0 0])
+	[]byte{0x4, 0x5c, 0x3f, 0x0, 0xf, 0x8a, 0x79, 0x6b, 0xce},          // Read([0 0 0 0 0 0 0 0 0])
+	[]byte{0xaa, 0xca, 0xee, 0xdf, 0xad, 0x5b, 0x50, 0x66, 0x64, 0xe8}, // Read([0 0 0 0 0 0 0 0 0 0])
+	uint32(4059586549),                                                 // Uint32()
+	uint32(1052117029),                                                 // Uint32()
+	uint32(2817310706),                                                 // Uint32()
+	uint32(233405013),                                                  // Uint32()
+	uint32(1578775030),                                                 // Uint32()
+	uint32(1243308993),                                                 // Uint32()
+	uint32(826517535),                                                  // Uint32()
+	uint32(2814630155),                                                 // Uint32()
+	uint32(3853314576),                                                 // Uint32()
+	uint32(718781857),                                                  // Uint32()
+	uint32(1239465936),                                                 // Uint32()
+	uint32(3876658295),                                                 // Uint32()
+	uint32(3649778518),                                                 // Uint32()
+	uint32(1172727096),                                                 // Uint32()
+	uint32(2615979505),                                                 // Uint32()
+	uint32(1089444252),                                                 // Uint32()
+	uint32(3327114623),                                                 // Uint32()
+	uint32(75079301),                                                   // Uint32()
+	uint32(3380456901),                                                 // Uint32()
+	uint32(3433369789),                                                 // Uint32()
 }
diff --git a/src/math/sqrt.go b/src/math/sqrt.go
index 23cf299..96af6e2 100644
--- a/src/math/sqrt.go
+++ b/src/math/sqrt.go
@@ -108,7 +108,7 @@ func sqrt(x float64) float64 {
 	// normalize x
 	exp := int((ix >> shift) & mask)
 	if exp == 0 { // subnormal x
-		for ix&1<<shift == 0 {
+		for ix&(1<<shift) == 0 {
 			ix <<= 1
 			exp--
 		}
diff --git a/src/math/stubs_mips64x.s b/src/math/stubs_mips64x.s
new file mode 100644
index 0000000..63be6ea
--- /dev/null
+++ b/src/math/stubs_mips64x.s
@@ -0,0 +1,91 @@
+// 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.
+
+// +build mips64 mips64le
+
+#include "textflag.h"
+
+TEXT ·Asin(SB),NOSPLIT,$0
+	JMP ·asin(SB)
+
+TEXT ·Acos(SB),NOSPLIT,$0
+	JMP ·acos(SB)
+
+TEXT ·Atan2(SB),NOSPLIT,$0
+	JMP ·atan2(SB)
+
+TEXT ·Atan(SB),NOSPLIT,$0
+	JMP ·atan(SB)
+
+TEXT ·Dim(SB),NOSPLIT,$0
+	JMP ·dim(SB)
+
+TEXT ·Min(SB),NOSPLIT,$0
+	JMP ·min(SB)
+
+TEXT ·Max(SB),NOSPLIT,$0
+	JMP ·max(SB)
+
+TEXT ·Exp2(SB),NOSPLIT,$0
+	JMP ·exp2(SB)
+
+TEXT ·Expm1(SB),NOSPLIT,$0
+	JMP ·expm1(SB)
+
+TEXT ·Exp(SB),NOSPLIT,$0
+	JMP ·exp(SB)
+
+TEXT ·Floor(SB),NOSPLIT,$0
+	JMP ·floor(SB)
+
+TEXT ·Ceil(SB),NOSPLIT,$0
+	JMP ·ceil(SB)
+
+TEXT ·Trunc(SB),NOSPLIT,$0
+	JMP ·trunc(SB)
+
+TEXT ·Frexp(SB),NOSPLIT,$0
+	JMP ·frexp(SB)
+
+TEXT ·Hypot(SB),NOSPLIT,$0
+	JMP ·hypot(SB)
+
+TEXT ·Ldexp(SB),NOSPLIT,$0
+	JMP ·ldexp(SB)
+
+TEXT ·Log10(SB),NOSPLIT,$0
+	JMP ·log10(SB)
+
+TEXT ·Log2(SB),NOSPLIT,$0
+	JMP ·log2(SB)
+
+TEXT ·Log1p(SB),NOSPLIT,$0
+	JMP ·log1p(SB)
+
+TEXT ·Log(SB),NOSPLIT,$0
+	JMP ·log(SB)
+
+TEXT ·Modf(SB),NOSPLIT,$0
+	JMP ·modf(SB)
+
+TEXT ·Mod(SB),NOSPLIT,$0
+	JMP ·mod(SB)
+
+TEXT ·Remainder(SB),NOSPLIT,$0
+	JMP ·remainder(SB)
+
+TEXT ·Sincos(SB),NOSPLIT,$0
+	JMP ·sincos(SB)
+
+TEXT ·Sin(SB),NOSPLIT,$0
+	JMP ·sin(SB)
+
+TEXT ·Cos(SB),NOSPLIT,$0
+	JMP ·cos(SB)
+
+TEXT ·Sqrt(SB),NOSPLIT,$0
+	JMP ·sqrt(SB)
+
+TEXT ·Tan(SB),NOSPLIT,$0
+	JMP ·tan(SB)
diff --git a/src/mime/encodedword.go b/src/mime/encodedword.go
index 9796f50..db4b5f4 100644
--- a/src/mime/encodedword.go
+++ b/src/mime/encodedword.go
@@ -54,35 +54,129 @@ func (e WordEncoder) encodeWord(charset, s string) string {
 	buf := getBuffer()
 	defer putBuffer(buf)
 
+	e.openWord(buf, charset)
+	if e == BEncoding {
+		e.bEncode(buf, charset, s)
+	} else {
+		e.qEncode(buf, charset, s)
+	}
+	closeWord(buf)
+
+	return buf.String()
+}
+
+const (
+	// The maximum length of an encoded-word is 75 characters.
+	// See RFC 2047, section 2.
+	maxEncodedWordLen = 75
+	// maxContentLen is how much content can be encoded, ignoring the header and
+	// 2-byte footer.
+	maxContentLen = maxEncodedWordLen - len("=?UTF-8?") - len("?=")
+)
+
+var maxBase64Len = base64.StdEncoding.DecodedLen(maxContentLen)
+
+// bEncode encodes s using base64 encoding and writes it to buf.
+func (e WordEncoder) bEncode(buf *bytes.Buffer, charset, s string) {
+	w := base64.NewEncoder(base64.StdEncoding, buf)
+	// If the charset is not UTF-8 or if the content is short, do not bother
+	// splitting the encoded-word.
+	if !isUTF8(charset) || base64.StdEncoding.EncodedLen(len(s)) <= maxContentLen {
+		io.WriteString(w, s)
+		w.Close()
+		return
+	}
+
+	var currentLen, last, runeLen int
+	for i := 0; i < len(s); i += runeLen {
+		// Multi-byte characters must not be split accross encoded-words.
+		// See RFC 2047, section 5.3.
+		_, runeLen = utf8.DecodeRuneInString(s[i:])
+
+		if currentLen+runeLen <= maxBase64Len {
+			currentLen += runeLen
+		} else {
+			io.WriteString(w, s[last:i])
+			w.Close()
+			e.splitWord(buf, charset)
+			last = i
+			currentLen = runeLen
+		}
+	}
+	io.WriteString(w, s[last:])
+	w.Close()
+}
+
+// qEncode encodes s using Q encoding and writes it to buf. It splits the
+// encoded-words when necessary.
+func (e WordEncoder) qEncode(buf *bytes.Buffer, charset, s string) {
+	// We only split encoded-words when the charset is UTF-8.
+	if !isUTF8(charset) {
+		writeQString(buf, s)
+		return
+	}
+
+	var currentLen, runeLen int
+	for i := 0; i < len(s); i += runeLen {
+		b := s[i]
+		// Multi-byte characters must not be split accross encoded-words.
+		// See RFC 2047, section 5.3.
+		var encLen int
+		if b >= ' ' && b <= '~' && b != '=' && b != '?' && b != '_' {
+			runeLen, encLen = 1, 1
+		} else {
+			_, runeLen = utf8.DecodeRuneInString(s[i:])
+			encLen = 3 * runeLen
+		}
+
+		if currentLen+encLen > maxContentLen {
+			e.splitWord(buf, charset)
+			currentLen = 0
+		}
+		writeQString(buf, s[i:i+runeLen])
+		currentLen += encLen
+	}
+}
+
+// writeQString encodes s using Q encoding and writes it to buf.
+func writeQString(buf *bytes.Buffer, s string) {
+	for i := 0; i < len(s); i++ {
+		switch b := s[i]; {
+		case b == ' ':
+			buf.WriteByte('_')
+		case b >= '!' && b <= '~' && b != '=' && b != '?' && b != '_':
+			buf.WriteByte(b)
+		default:
+			buf.WriteByte('=')
+			buf.WriteByte(upperhex[b>>4])
+			buf.WriteByte(upperhex[b&0x0f])
+		}
+	}
+}
+
+// openWord writes the beginning of an encoded-word into buf.
+func (e WordEncoder) openWord(buf *bytes.Buffer, charset string) {
 	buf.WriteString("=?")
 	buf.WriteString(charset)
 	buf.WriteByte('?')
 	buf.WriteByte(byte(e))
 	buf.WriteByte('?')
+}
 
-	if e == BEncoding {
-		w := base64.NewEncoder(base64.StdEncoding, buf)
-		io.WriteString(w, s)
-		w.Close()
-	} else {
-		enc := make([]byte, 3)
-		for i := 0; i < len(s); i++ {
-			b := s[i]
-			switch {
-			case b == ' ':
-				buf.WriteByte('_')
-			case b <= '~' && b >= '!' && b != '=' && b != '?' && b != '_':
-				buf.WriteByte(b)
-			default:
-				enc[0] = '='
-				enc[1] = upperhex[b>>4]
-				enc[2] = upperhex[b&0x0f]
-				buf.Write(enc)
-			}
-		}
-	}
+// closeWord writes the end of an encoded-word into buf.
+func closeWord(buf *bytes.Buffer) {
 	buf.WriteString("?=")
-	return buf.String()
+}
+
+// splitWord closes the current encoded-word and opens a new one.
+func (e WordEncoder) splitWord(buf *bytes.Buffer, charset string) {
+	closeWord(buf)
+	buf.WriteByte(' ')
+	e.openWord(buf, charset)
+}
+
+func isUTF8(charset string) bool {
+	return strings.EqualFold(charset, "UTF-8")
 }
 
 const upperhex = "0123456789ABCDEF"
@@ -98,15 +192,26 @@ type WordDecoder struct {
 	CharsetReader func(charset string, input io.Reader) (io.Reader, error)
 }
 
-// Decode decodes an encoded-word. If word is not a valid RFC 2047 encoded-word,
-// word is returned unchanged.
+// Decode decodes an RFC 2047 encoded-word.
 func (d *WordDecoder) Decode(word string) (string, error) {
-	fields := strings.Split(word, "?") // TODO: remove allocation?
-	if len(fields) != 5 || fields[0] != "=" || fields[4] != "=" || len(fields[2]) != 1 {
+	if !strings.HasPrefix(word, "=?") || !strings.HasSuffix(word, "?=") || strings.Count(word, "?") != 4 {
+		return "", errInvalidWord
+	}
+	word = word[2 : len(word)-2]
+
+	// split delimits the first 2 fields
+	split := strings.IndexByte(word, '?')
+	// the field after split must only be one byte
+	if word[split+2] != '?' {
 		return "", errInvalidWord
 	}
 
-	content, err := decode(fields[2][0], fields[3])
+	// split word "UTF-8?q?ascii" into "UTF-8", 'q', and "ascii"
+	charset := word[:split]
+	encoding := word[split+1]
+	text := word[split+3:]
+
+	content, err := decode(encoding, text)
 	if err != nil {
 		return "", err
 	}
@@ -114,7 +219,7 @@ func (d *WordDecoder) Decode(word string) (string, error) {
 	buf := getBuffer()
 	defer putBuffer(buf)
 
-	if err := d.convert(buf, fields[1], content); err != nil {
+	if err := d.convert(buf, charset, content); err != nil {
 		return "", err
 	}
 
diff --git a/src/mime/encodedword_test.go b/src/mime/encodedword_test.go
index 2beff5d..5fcd7a0 100644
--- a/src/mime/encodedword_test.go
+++ b/src/mime/encodedword_test.go
@@ -5,100 +5,13 @@
 package mime
 
 import (
-	"bytes"
 	"errors"
-	"fmt"
 	"io"
 	"io/ioutil"
 	"strings"
 	"testing"
 )
 
-func ExampleWordEncoder_Encode() {
-	fmt.Println(QEncoding.Encode("utf-8", "¡Hola, señor!"))
-	fmt.Println(QEncoding.Encode("utf-8", "Hello!"))
-	fmt.Println(BEncoding.Encode("UTF-8", "¡Hola, señor!"))
-	fmt.Println(QEncoding.Encode("ISO-8859-1", "Caf\xE9"))
-	// Output:
-	// =?utf-8?q?=C2=A1Hola,_se=C3=B1or!?=
-	// Hello!
-	// =?UTF-8?b?wqFIb2xhLCBzZcOxb3Ih?=
-	// =?ISO-8859-1?q?Caf=E9?=
-}
-
-func ExampleWordDecoder_Decode() {
-	dec := new(WordDecoder)
-	header, err := dec.Decode("=?utf-8?q?=C2=A1Hola,_se=C3=B1or!?=")
-	if err != nil {
-		panic(err)
-	}
-	fmt.Println(header)
-
-	dec.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
-		switch charset {
-		case "x-case":
-			// Fake character set for example.
-			// Real use would integrate with packages such
-			// as code.google.com/p/go-charset
-			content, err := ioutil.ReadAll(input)
-			if err != nil {
-				return nil, err
-			}
-			return bytes.NewReader(bytes.ToUpper(content)), nil
-		default:
-			return nil, fmt.Errorf("unhandled charset %q", charset)
-		}
-	}
-	header, err = dec.Decode("=?x-case?q?hello!?=")
-	if err != nil {
-		panic(err)
-	}
-	fmt.Println(header)
-	// Output:
-	// ¡Hola, señor!
-	// HELLO!
-}
-
-func ExampleWordDecoder_DecodeHeader() {
-	dec := new(WordDecoder)
-	header, err := dec.DecodeHeader("=?utf-8?q?=C3=89ric?= <eric at example.org>, =?utf-8?q?Ana=C3=AFs?= <anais at example.org>")
-	if err != nil {
-		panic(err)
-	}
-	fmt.Println(header)
-
-	header, err = dec.DecodeHeader("=?utf-8?q?=C2=A1Hola,?= =?utf-8?q?_se=C3=B1or!?=")
-	if err != nil {
-		panic(err)
-	}
-	fmt.Println(header)
-
-	dec.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
-		switch charset {
-		case "x-case":
-			// Fake character set for example.
-			// Real use would integrate with packages such
-			// as code.google.com/p/go-charset
-			content, err := ioutil.ReadAll(input)
-			if err != nil {
-				return nil, err
-			}
-			return bytes.NewReader(bytes.ToUpper(content)), nil
-		default:
-			return nil, fmt.Errorf("unhandled charset %q", charset)
-		}
-	}
-	header, err = dec.DecodeHeader("=?x-case?q?hello_?= =?x-case?q?world!?=")
-	if err != nil {
-		panic(err)
-	}
-	fmt.Println(header)
-	// Output:
-	// Éric <eric at example.org>, Anaïs <anais at example.org>
-	// ¡Hola, señor!
-	// HELLO WORLD!
-}
-
 func TestEncodeWord(t *testing.T) {
 	utf8, iso88591 := "utf-8", "iso-8859-1"
 	tests := []struct {
@@ -114,6 +27,14 @@ func TestEncodeWord(t *testing.T) {
 		{QEncoding, iso88591, "a", "a"},
 		{QEncoding, utf8, "123 456", "123 456"},
 		{QEncoding, utf8, "\t !\"#$%&'()*+,-./ :;<>?@[\\]^_`{|}~", "\t !\"#$%&'()*+,-./ :;<>?@[\\]^_`{|}~"},
+		{QEncoding, utf8, strings.Repeat("é", 10), "=?utf-8?q?" + strings.Repeat("=C3=A9", 10) + "?="},
+		{QEncoding, utf8, strings.Repeat("é", 11), "=?utf-8?q?" + strings.Repeat("=C3=A9", 10) + "?= =?utf-8?q?=C3=A9?="},
+		{QEncoding, iso88591, strings.Repeat("\xe9", 22), "=?iso-8859-1?q?" + strings.Repeat("=E9", 22) + "?="},
+		{QEncoding, utf8, strings.Repeat("\x80", 22), "=?utf-8?q?" + strings.Repeat("=80", 21) + "?= =?utf-8?q?=80?="},
+		{BEncoding, utf8, strings.Repeat("é", 24), "=?utf-8?b?" + strings.Repeat("w6nDqcOp", 8) + "?="},
+		{BEncoding, utf8, strings.Repeat("é", 27), "=?utf-8?b?" + strings.Repeat("w6nDqcOp", 8) + "?= =?utf-8?b?w6nDqcOp?="},
+		{BEncoding, iso88591, strings.Repeat("\xe9", 45), "=?iso-8859-1?b?" + strings.Repeat("6enp", 15) + "?="},
+		{BEncoding, utf8, strings.Repeat("\x80", 51), "=?utf-8?b?" + strings.Repeat("gICA", 16) + "?= =?utf-8?b?gICA?="},
 	}
 
 	for _, test := range tests {
diff --git a/src/mime/example_test.go b/src/mime/example_test.go
new file mode 100644
index 0000000..c7d13cd
--- /dev/null
+++ b/src/mime/example_test.go
@@ -0,0 +1,98 @@
+// Copyright 2015 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 mime_test
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"mime"
+)
+
+func ExampleWordEncoder_Encode() {
+	fmt.Println(mime.QEncoding.Encode("utf-8", "¡Hola, señor!"))
+	fmt.Println(mime.QEncoding.Encode("utf-8", "Hello!"))
+	fmt.Println(mime.BEncoding.Encode("UTF-8", "¡Hola, señor!"))
+	fmt.Println(mime.QEncoding.Encode("ISO-8859-1", "Caf\xE9"))
+	// Output:
+	// =?utf-8?q?=C2=A1Hola,_se=C3=B1or!?=
+	// Hello!
+	// =?UTF-8?b?wqFIb2xhLCBzZcOxb3Ih?=
+	// =?ISO-8859-1?q?Caf=E9?=
+}
+
+func ExampleWordDecoder_Decode() {
+	dec := new(mime.WordDecoder)
+	header, err := dec.Decode("=?utf-8?q?=C2=A1Hola,_se=C3=B1or!?=")
+	if err != nil {
+		panic(err)
+	}
+	fmt.Println(header)
+
+	dec.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
+		switch charset {
+		case "x-case":
+			// Fake character set for example.
+			// Real use would integrate with packages such
+			// as code.google.com/p/go-charset
+			content, err := ioutil.ReadAll(input)
+			if err != nil {
+				return nil, err
+			}
+			return bytes.NewReader(bytes.ToUpper(content)), nil
+		default:
+			return nil, fmt.Errorf("unhandled charset %q", charset)
+		}
+	}
+	header, err = dec.Decode("=?x-case?q?hello!?=")
+	if err != nil {
+		panic(err)
+	}
+	fmt.Println(header)
+	// Output:
+	// ¡Hola, señor!
+	// HELLO!
+}
+
+func ExampleWordDecoder_DecodeHeader() {
+	dec := new(mime.WordDecoder)
+	header, err := dec.DecodeHeader("=?utf-8?q?=C3=89ric?= <eric at example.org>, =?utf-8?q?Ana=C3=AFs?= <anais at example.org>")
+	if err != nil {
+		panic(err)
+	}
+	fmt.Println(header)
+
+	header, err = dec.DecodeHeader("=?utf-8?q?=C2=A1Hola,?= =?utf-8?q?_se=C3=B1or!?=")
+	if err != nil {
+		panic(err)
+	}
+	fmt.Println(header)
+
+	dec.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
+		switch charset {
+		case "x-case":
+			// Fake character set for example.
+			// Real use would integrate with packages such
+			// as code.google.com/p/go-charset
+			content, err := ioutil.ReadAll(input)
+			if err != nil {
+				return nil, err
+			}
+			return bytes.NewReader(bytes.ToUpper(content)), nil
+		default:
+			return nil, fmt.Errorf("unhandled charset %q", charset)
+		}
+	}
+	header, err = dec.DecodeHeader("=?x-case?q?hello_?= =?x-case?q?world!?=")
+	if err != nil {
+		panic(err)
+	}
+	fmt.Println(header)
+	// Output:
+	// Éric <eric at example.org>, Anaïs <anais at example.org>
+	// ¡Hola, señor!
+	// HELLO WORLD!
+}
diff --git a/src/mime/mediatype.go b/src/mime/mediatype.go
index ad63f9b..efee65b 100644
--- a/src/mime/mediatype.go
+++ b/src/mime/mediatype.go
@@ -19,18 +19,21 @@ import (
 // When any of the arguments result in a standard violation then
 // FormatMediaType returns the empty string.
 func FormatMediaType(t string, param map[string]string) string {
-	slash := strings.Index(t, "/")
-	if slash == -1 {
-		return ""
-	}
-	major, sub := t[:slash], t[slash+1:]
-	if !isToken(major) || !isToken(sub) {
-		return ""
-	}
 	var b bytes.Buffer
-	b.WriteString(strings.ToLower(major))
-	b.WriteByte('/')
-	b.WriteString(strings.ToLower(sub))
+	if slash := strings.Index(t, "/"); slash == -1 {
+		if !isToken(t) {
+			return ""
+		}
+		b.WriteString(strings.ToLower(t))
+	} else {
+		major, sub := t[:slash], t[slash+1:]
+		if !isToken(major) || !isToken(sub) {
+			return ""
+		}
+		b.WriteString(strings.ToLower(major))
+		b.WriteByte('/')
+		b.WriteString(strings.ToLower(sub))
+	}
 
 	attrs := make([]string, 0, len(param))
 	for a := range param {
@@ -237,24 +240,23 @@ func consumeToken(v string) (token, rest string) {
 // quoted-string) and the rest of the string.  On failure, returns
 // ("", v).
 func consumeValue(v string) (value, rest string) {
-	if !strings.HasPrefix(v, `"`) && !strings.HasPrefix(v, `'`) {
+	if v == "" {
+		return
+	}
+	if v[0] != '"' {
 		return consumeToken(v)
 	}
 
-	leadQuote := rune(v[0])
-
 	// parse a quoted-string
 	rest = v[1:] // consume the leading quote
 	buffer := new(bytes.Buffer)
-	var idx int
-	var r rune
 	var nextIsLiteral bool
-	for idx, r = range rest {
+	for idx, r := range rest {
 		switch {
 		case nextIsLiteral:
 			buffer.WriteRune(r)
 			nextIsLiteral = false
-		case r == leadQuote:
+		case r == '"':
 			return buffer.String(), rest[idx+1:]
 		case r == '\\':
 			nextIsLiteral = true
@@ -287,10 +289,11 @@ func consumeMediaParam(v string) (param, value, rest string) {
 	}
 	rest = rest[1:] // consume equals sign
 	rest = strings.TrimLeftFunc(rest, unicode.IsSpace)
-	value, rest = consumeValue(rest)
-	if value == "" {
+	value, rest2 := consumeValue(rest)
+	if value == "" && rest2 == rest {
 		return "", "", v
 	}
+	rest = rest2
 	return param, value, rest
 }
 
diff --git a/src/mime/mediatype_test.go b/src/mime/mediatype_test.go
index 026bfa4..9afa558 100644
--- a/src/mime/mediatype_test.go
+++ b/src/mime/mediatype_test.go
@@ -159,7 +159,7 @@ func TestParseMediaType(t *testing.T) {
 			m("filename", "foo.html")},
 		{`attachment; filename='foo.html'`,
 			"attachment",
-			m("filename", "foo.html")},
+			m("filename", "'foo.html'")},
 		{`attachment; filename="foo-%41.html"`,
 			"attachment",
 			m("filename", "foo-%41.html")},
@@ -217,6 +217,9 @@ func TestParseMediaType(t *testing.T) {
 		{`form-data; firstname="Брэд"; lastname="Фицпатрик"`,
 			"form-data",
 			m("firstname", "Брэд", "lastname", "Фицпатрик")},
+
+		// Empty string used to be mishandled.
+		{`foo; bar=""`, "foo", m("bar", "")},
 	}
 	for _, test := range tests {
 		mt, params, err := ParseMediaType(test.in)
@@ -281,7 +284,7 @@ type formatTest struct {
 }
 
 var formatTests = []formatTest{
-	{"noslash", nil, ""},
+	{"noslash", map[string]string{"X": "Y"}, "noslash; x=Y"}, // e.g. Content-Disposition values (RFC 2183); issue 11289
 	{"foo bar/baz", nil, ""},
 	{"foo/bar baz", nil, ""},
 	{"foo/BAR", nil, "foo/bar"},
@@ -294,6 +297,8 @@ var formatTests = []formatTest{
 	{"foo/BAR", map[string]string{"bad attribute": "baz"}, ""},
 	{"foo/BAR", map[string]string{"nonascii": "not an ascii character: ä"}, ""},
 	{"foo/bar", map[string]string{"a": "av", "b": "bv", "c": "cv"}, "foo/bar; a=av; b=bv; c=cv"},
+	{"foo/bar", map[string]string{"0": "'", "9": "'"}, "foo/bar; 0='; 9='"},
+	{"foo", map[string]string{"bar": ""}, `foo; bar=""`},
 }
 
 func TestFormatMediaType(t *testing.T) {
diff --git a/src/mime/multipart/multipart.go b/src/mime/multipart/multipart.go
index eeec974..3b746a5 100644
--- a/src/mime/multipart/multipart.go
+++ b/src/mime/multipart/multipart.go
@@ -366,7 +366,7 @@ func (mr *Reader) peekBufferSeparatorIndex(peek []byte) (idx int, isEnd bool) {
 	peek = skipLWSPChar(peek)
 	// Don't have a complete line after the peek.
 	if bytes.IndexByte(peek, '\n') == -1 {
-		return -1, false
+		return idx, false
 	}
 	if len(peek) > 0 && peek[0] == '\n' {
 		return idx, true
diff --git a/src/mime/multipart/multipart_test.go b/src/mime/multipart/multipart_test.go
index 32cec57..d06bb41 100644
--- a/src/mime/multipart/multipart_test.go
+++ b/src/mime/multipart/multipart_test.go
@@ -664,6 +664,38 @@ Content-Type: application/octet-stream
 			},
 		},
 	},
+	// Context: https://github.com/camlistore/camlistore/issues/642
+	// If the file contents in the form happens to have a size such as:
+	// size = peekBufferSize - (len("\n--") + len(boundary) + len("\r") + 1), (modulo peekBufferSize)
+	// then peekBufferSeparatorIndex was wrongly returning (-1, false), which was leading to an nCopy
+	// cut such as:
+	// "somedata\r| |\n--Boundary\r" (instead of "somedata| |\r\n--Boundary\r"), which was making the
+	// subsequent Read miss the boundary.
+	{
+		name: "safeCount off by one",
+		sep:  "08b84578eabc563dcba967a945cdf0d9f613864a8f4a716f0e81caa71a74",
+		in: strings.Replace(`--08b84578eabc563dcba967a945cdf0d9f613864a8f4a716f0e81caa71a74
+Content-Disposition: form-data; name="myfile"; filename="my-file.txt"
+Content-Type: application/octet-stream
+
+`, "\n", "\r\n", -1) +
+			strings.Repeat("A", peekBufferSize-(len("\n--")+len("08b84578eabc563dcba967a945cdf0d9f613864a8f4a716f0e81caa71a74")+len("\r")+1)) +
+			strings.Replace(`
+--08b84578eabc563dcba967a945cdf0d9f613864a8f4a716f0e81caa71a74
+Content-Disposition: form-data; name="key"
+
+val
+--08b84578eabc563dcba967a945cdf0d9f613864a8f4a716f0e81caa71a74--
+`, "\n", "\r\n", -1),
+		want: []headerBody{
+			{textproto.MIMEHeader{"Content-Type": {`application/octet-stream`}, "Content-Disposition": {`form-data; name="myfile"; filename="my-file.txt"`}},
+				strings.Repeat("A", peekBufferSize-(len("\n--")+len("08b84578eabc563dcba967a945cdf0d9f613864a8f4a716f0e81caa71a74")+len("\r")+1)),
+			},
+			{textproto.MIMEHeader{"Content-Disposition": {`form-data; name="key"`}},
+				"val",
+			},
+		},
+	},
 
 	roundTripParseTest(),
 }
@@ -704,6 +736,53 @@ Cases:
 	}
 }
 
+func partsFromReader(r *Reader) ([]headerBody, error) {
+	got := []headerBody{}
+	for {
+		p, err := r.NextPart()
+		if err == io.EOF {
+			return got, nil
+		}
+		if err != nil {
+			return nil, fmt.Errorf("NextPart: %v", err)
+		}
+		pbody, err := ioutil.ReadAll(p)
+		if err != nil {
+			return nil, fmt.Errorf("error reading part: %v", err)
+		}
+		got = append(got, headerBody{p.Header, string(pbody)})
+	}
+}
+
+func TestParseAllSizes(t *testing.T) {
+	const maxSize = 5 << 10
+	var buf bytes.Buffer
+	body := strings.Repeat("a", maxSize)
+	bodyb := []byte(body)
+	for size := 0; size < maxSize; size++ {
+		buf.Reset()
+		w := NewWriter(&buf)
+		part, _ := w.CreateFormField("f")
+		part.Write(bodyb[:size])
+		part, _ = w.CreateFormField("key")
+		part.Write([]byte("val"))
+		w.Close()
+		r := NewReader(&buf, w.Boundary())
+		got, err := partsFromReader(r)
+		if err != nil {
+			t.Errorf("For size %d: %v", size, err)
+			continue
+		}
+		if len(got) != 2 {
+			t.Errorf("For size %d, num parts = %d; want 2", size, len(got))
+			continue
+		}
+		if got[0].body != body[:size] {
+			t.Errorf("For size %d, got unexpected len %d: %q", size, len(got[0].body), got[0].body)
+		}
+	}
+}
+
 func roundTripParseTest() parseTest {
 	t := parseTest{
 		name: "round trip",
diff --git a/src/net/addrselect.go b/src/net/addrselect.go
index e22fbac..58ab7d7 100644
--- a/src/net/addrselect.go
+++ b/src/net/addrselect.go
@@ -197,6 +197,24 @@ func (s *byRFC6724) Less(i, j int) bool {
 	if da4 == db4 {
 		commonA := commonPrefixLen(SourceDA, DA)
 		commonB := commonPrefixLen(SourceDB, DB)
+
+		// CommonPrefixLen doesn't really make sense for IPv4, and even
+		// causes problems for common load balancing practices
+		// (e.g., https://golang.org/issue/13283).  Glibc instead only
+		// uses CommonPrefixLen for IPv4 when the source and destination
+		// addresses are on the same subnet, but that requires extra
+		// work to find the netmask for our source addresses.  As a
+		// simpler heuristic, we limit its use to when the source and
+		// destination belong to the same special purpose block.
+		if da4 {
+			if !sameIPv4SpecialPurposeBlock(SourceDA, DA) {
+				commonA = 0
+			}
+			if !sameIPv4SpecialPurposeBlock(SourceDB, DB) {
+				commonB = 0
+			}
+		}
+
 		if commonA > commonB {
 			return preferDA
 		}
@@ -386,3 +404,28 @@ func commonPrefixLen(a, b IP) (cpl int) {
 	}
 	return
 }
+
+// sameIPv4SpecialPurposeBlock reports whether a and b belong to the same
+// address block reserved by the IANA IPv4 Special-Purpose Address Registry:
+// http://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
+func sameIPv4SpecialPurposeBlock(a, b IP) bool {
+	a, b = a.To4(), b.To4()
+	if a == nil || b == nil || a[0] != b[0] {
+		return false
+	}
+	// IANA defines more special-purpose blocks, but these are the only
+	// ones likely to be relevant to typical Go systems.
+	switch a[0] {
+	case 10: // 10.0.0.0/8: Private-Use
+		return true
+	case 127: // 127.0.0.0/8: Loopback
+		return true
+	case 169: // 169.254.0.0/16: Link Local
+		return a[1] == 254 && b[1] == 254
+	case 172: // 172.16.0.0/12: Private-Use
+		return a[1]&0xf0 == 16 && b[1]&0xf0 == 16
+	case 192: // 192.168.0.0/16: Private-Use
+		return a[1] == 168 && b[1] == 168
+	}
+	return false
+}
diff --git a/src/net/addrselect_test.go b/src/net/addrselect_test.go
index 5620227..80aa4eb 100644
--- a/src/net/addrselect_test.go
+++ b/src/net/addrselect_test.go
@@ -87,6 +87,57 @@ func TestSortByRFC6724(t *testing.T) {
 			},
 			reverse: true,
 		},
+
+		// Issue 13283.  Having a 10/8 source address does not
+		// mean we should prefer 23/8 destination addresses.
+		{
+			in: []IPAddr{
+				{IP: ParseIP("54.83.193.112")},
+				{IP: ParseIP("184.72.238.214")},
+				{IP: ParseIP("23.23.172.185")},
+				{IP: ParseIP("75.101.148.21")},
+				{IP: ParseIP("23.23.134.56")},
+				{IP: ParseIP("23.21.50.150")},
+			},
+			srcs: []IP{
+				ParseIP("10.2.3.4"),
+				ParseIP("10.2.3.4"),
+				ParseIP("10.2.3.4"),
+				ParseIP("10.2.3.4"),
+				ParseIP("10.2.3.4"),
+				ParseIP("10.2.3.4"),
+			},
+			want: []IPAddr{
+				{IP: ParseIP("54.83.193.112")},
+				{IP: ParseIP("184.72.238.214")},
+				{IP: ParseIP("23.23.172.185")},
+				{IP: ParseIP("75.101.148.21")},
+				{IP: ParseIP("23.23.134.56")},
+				{IP: ParseIP("23.21.50.150")},
+			},
+			reverse: false,
+		},
+
+		// Prefer longer common prefixes, but only for IPv4 address
+		// pairs in the same special-purpose block.
+		{
+			in: []IPAddr{
+				{IP: ParseIP("1.2.3.4")},
+				{IP: ParseIP("10.55.0.1")},
+				{IP: ParseIP("10.66.0.1")},
+			},
+			srcs: []IP{
+				ParseIP("1.2.3.5"),
+				ParseIP("10.66.1.2"),
+				ParseIP("10.66.1.2"),
+			},
+			want: []IPAddr{
+				{IP: ParseIP("10.66.0.1")},
+				{IP: ParseIP("10.55.0.1")},
+				{IP: ParseIP("1.2.3.4")},
+			},
+			reverse: true,
+		},
 	}
 	for i, tt := range tests {
 		inCopy := make([]IPAddr, len(tt.in))
@@ -217,3 +268,67 @@ func TestRFC6724CommonPrefixLength(t *testing.T) {
 	}
 
 }
+
+func mustParseCIDRs(t *testing.T, blocks ...string) []*IPNet {
+	res := make([]*IPNet, len(blocks))
+	for i, block := range blocks {
+		var err error
+		_, res[i], err = ParseCIDR(block)
+		if err != nil {
+			t.Fatalf("ParseCIDR(%s) failed: %v", block, err)
+		}
+	}
+	return res
+}
+
+func TestSameIPv4SpecialPurposeBlock(t *testing.T) {
+	blocks := mustParseCIDRs(t,
+		"10.0.0.0/8",
+		"127.0.0.0/8",
+		"169.254.0.0/16",
+		"172.16.0.0/12",
+		"192.168.0.0/16",
+	)
+
+	addrs := []struct {
+		ip    IP
+		block int // index or -1
+	}{
+		{IP{1, 2, 3, 4}, -1},
+		{IP{2, 3, 4, 5}, -1},
+		{IP{10, 2, 3, 4}, 0},
+		{IP{10, 6, 7, 8}, 0},
+		{IP{127, 0, 0, 1}, 1},
+		{IP{127, 255, 255, 255}, 1},
+		{IP{169, 254, 77, 99}, 2},
+		{IP{169, 254, 44, 22}, 2},
+		{IP{169, 255, 0, 1}, -1},
+		{IP{172, 15, 5, 6}, -1},
+		{IP{172, 16, 32, 41}, 3},
+		{IP{172, 31, 128, 9}, 3},
+		{IP{172, 32, 88, 100}, -1},
+		{IP{192, 168, 1, 1}, 4},
+		{IP{192, 168, 128, 42}, 4},
+		{IP{192, 169, 1, 1}, -1},
+	}
+
+	for i, addr := range addrs {
+		for j, block := range blocks {
+			got := block.Contains(addr.ip)
+			want := addr.block == j
+			if got != want {
+				t.Errorf("%d/%d. %s.Contains(%s): got %v, want %v", i, j, block, addr.ip, got, want)
+			}
+		}
+	}
+
+	for i, addr1 := range addrs {
+		for j, addr2 := range addrs {
+			got := sameIPv4SpecialPurposeBlock(addr1.ip, addr2.ip)
+			want := addr1.block >= 0 && addr1.block == addr2.block
+			if got != want {
+				t.Errorf("%d/%d. sameIPv4SpecialPurposeBlock(%s, %s): got %v, want %v", i, j, addr1.ip, addr2.ip, got, want)
+			}
+		}
+	}
+}
diff --git a/src/net/cgo_socknew.go b/src/net/cgo_socknew.go
index b508284..3b13926 100644
--- a/src/net/cgo_socknew.go
+++ b/src/net/cgo_socknew.go
@@ -26,8 +26,8 @@ func cgoSockaddrInet4(ip IP) *C.struct_sockaddr {
 	return (*C.struct_sockaddr)(unsafe.Pointer(&sa))
 }
 
-func cgoSockaddrInet6(ip IP) *C.struct_sockaddr {
-	sa := syscall.RawSockaddrInet6{Family: syscall.AF_INET6}
+func cgoSockaddrInet6(ip IP, zone int) *C.struct_sockaddr {
+	sa := syscall.RawSockaddrInet6{Family: syscall.AF_INET6, Scope_id: uint32(zone)}
 	copy(sa.Addr[:], ip)
 	return (*C.struct_sockaddr)(unsafe.Pointer(&sa))
 }
diff --git a/src/net/cgo_sockold.go b/src/net/cgo_sockold.go
index 522e8e5..e629a09 100644
--- a/src/net/cgo_sockold.go
+++ b/src/net/cgo_sockold.go
@@ -26,8 +26,8 @@ func cgoSockaddrInet4(ip IP) *C.struct_sockaddr {
 	return (*C.struct_sockaddr)(unsafe.Pointer(&sa))
 }
 
-func cgoSockaddrInet6(ip IP) *C.struct_sockaddr {
-	sa := syscall.RawSockaddrInet6{Len: syscall.SizeofSockaddrInet6, Family: syscall.AF_INET6}
+func cgoSockaddrInet6(ip IP, zone int) *C.struct_sockaddr {
+	sa := syscall.RawSockaddrInet6{Len: syscall.SizeofSockaddrInet6, Family: syscall.AF_INET6, Scope_id: uint32(zone)}
 	copy(sa.Addr[:], ip)
 	return (*C.struct_sockaddr)(unsafe.Pointer(&sa))
 }
diff --git a/src/net/cgo_unix.go b/src/net/cgo_unix.go
index cb89d65..c14f085 100644
--- a/src/net/cgo_unix.go
+++ b/src/net/cgo_unix.go
@@ -186,11 +186,15 @@ func cgoLookupPTR(addr string) ([]string, error, bool) {
 	acquireThread()
 	defer releaseThread()
 
-	ip := ParseIP(addr)
+	var zone string
+	ip := parseIPv4(addr)
+	if ip == nil {
+		ip, zone = parseIPv6(addr, true)
+	}
 	if ip == nil {
 		return nil, &DNSError{Err: "invalid address", Name: addr}, true
 	}
-	sa, salen := cgoSockaddr(ip)
+	sa, salen := cgoSockaddr(ip, zone)
 	if sa == nil {
 		return nil, &DNSError{Err: "invalid address " + ip.String(), Name: addr}, true
 	}
@@ -222,20 +226,15 @@ func cgoLookupPTR(addr string) ([]string, error, bool) {
 			break
 		}
 	}
-	// Add trailing dot to match pure Go reverse resolver
-	// and all other lookup routines. See golang.org/issue/12189.
-	if len(b) > 0 && b[len(b)-1] != '.' {
-		b = append(b, '.')
-	}
-	return []string{string(b)}, nil, true
+	return []string{absDomainName(b)}, nil, true
 }
 
-func cgoSockaddr(ip IP) (*C.struct_sockaddr, C.socklen_t) {
+func cgoSockaddr(ip IP, zone string) (*C.struct_sockaddr, C.socklen_t) {
 	if ip4 := ip.To4(); ip4 != nil {
 		return cgoSockaddrInet4(ip4), C.socklen_t(syscall.SizeofSockaddrInet4)
 	}
 	if ip6 := ip.To16(); ip6 != nil {
-		return cgoSockaddrInet6(ip6), C.socklen_t(syscall.SizeofSockaddrInet6)
+		return cgoSockaddrInet6(ip6, zoneToInt(zone)), C.socklen_t(syscall.SizeofSockaddrInet6)
 	}
 	return nil, 0
 }
diff --git a/src/net/conf.go b/src/net/conf.go
index c92e579..ddaa978 100644
--- a/src/net/conf.go
+++ b/src/net/conf.go
@@ -9,7 +9,6 @@ package net
 import (
 	"os"
 	"runtime"
-	"strconv"
 	"sync"
 	"syscall"
 )
@@ -293,7 +292,7 @@ func goDebugNetDNS() (dnsMode string, debugLevel int) {
 			return
 		}
 		if '0' <= s[0] && s[0] <= '9' {
-			debugLevel, _ = strconv.Atoi(s)
+			debugLevel, _, _ = dtoi(s, 0)
 		} else {
 			dnsMode = s
 		}
diff --git a/src/net/dial.go b/src/net/dial.go
index cb4ec21..193776f 100644
--- a/src/net/dial.go
+++ b/src/net/dial.go
@@ -57,6 +57,11 @@ type Dialer struct {
 	// If zero, keep-alives are not enabled. Network protocols
 	// that do not support keep-alives ignore this field.
 	KeepAlive time.Duration
+
+	// Cancel is an optional channel whose closure indicates that
+	// the dial should be canceled. Not all types of dials support
+	// cancelation.
+	Cancel <-chan struct{}
 }
 
 // Return either now+Timeout or Deadline, whichever comes first.
@@ -165,12 +170,14 @@ func resolveAddrList(op, net, addr string, deadline time.Time) (addrList, error)
 // in square brackets as in "[::1]:80" or "[ipv6-host%zone]:80".
 // The functions JoinHostPort and SplitHostPort manipulate addresses
 // in this form.
+// If the host is empty, as in ":80", the local system is assumed.
 //
 // Examples:
 //	Dial("tcp", "12.34.56.78:80")
 //	Dial("tcp", "google.com:http")
 //	Dial("tcp", "[2001:db8::1]:http")
 //	Dial("tcp", "[fe80::1%lo0]:80")
+//	Dial("tcp", ":80")
 //
 // For IP networks, the network must be "ip", "ip4" or "ip6" followed
 // by a colon and a protocol number or name and the addr must be a
@@ -361,7 +368,7 @@ func dialSingle(ctx *dialContext, ra Addr, deadline time.Time) (c Conn, err erro
 	switch ra := ra.(type) {
 	case *TCPAddr:
 		la, _ := la.(*TCPAddr)
-		c, err = testHookDialTCP(ctx.network, la, ra, deadline)
+		c, err = testHookDialTCP(ctx.network, la, ra, deadline, ctx.Cancel)
 	case *UDPAddr:
 		la, _ := la.(*UDPAddr)
 		c, err = dialUDP(ctx.network, la, ra, deadline)
@@ -383,7 +390,10 @@ func dialSingle(ctx *dialContext, ra Addr, deadline time.Time) (c Conn, err erro
 // Listen announces on the local network address laddr.
 // The network net must be a stream-oriented network: "tcp", "tcp4",
 // "tcp6", "unix" or "unixpacket".
-// See Dial for the syntax of laddr.
+// For TCP and UDP, the syntax of laddr is "host:port", like "127.0.0.1:8080".
+// If host is omitted, as in ":8080", Listen listens on all available interfaces
+// instead of just the interface with the given host address.
+// See Dial for more details about address syntax.
 func Listen(net, laddr string) (Listener, error) {
 	addrs, err := resolveAddrList("listen", net, laddr, noDeadline)
 	if err != nil {
@@ -407,6 +417,9 @@ func Listen(net, laddr string) (Listener, error) {
 // ListenPacket announces on the local network address laddr.
 // The network net must be a packet-oriented network: "udp", "udp4",
 // "udp6", "ip", "ip4", "ip6" or "unixgram".
+// For TCP and UDP, the syntax of laddr is "host:port", like "127.0.0.1:8080".
+// If host is omitted, as in ":8080", ListenPacket listens on all available interfaces
+// instead of just the interface with the given host address.
 // See Dial for the syntax of laddr.
 func ListenPacket(net, laddr string) (PacketConn, error) {
 	addrs, err := resolveAddrList("listen", net, laddr, noDeadline)
diff --git a/src/net/dial_test.go b/src/net/dial_test.go
index ed6d7cc..2311b10 100644
--- a/src/net/dial_test.go
+++ b/src/net/dial_test.go
@@ -5,6 +5,7 @@
 package net
 
 import (
+	"internal/testenv"
 	"io"
 	"net/internal/socktest"
 	"runtime"
@@ -236,8 +237,8 @@ const (
 // In some environments, the slow IPs may be explicitly unreachable, and fail
 // more quickly than expected. This test hook prevents dialTCP from returning
 // before the deadline.
-func slowDialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, error) {
-	c, err := dialTCP(net, laddr, raddr, deadline)
+func slowDialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time, cancel <-chan struct{}) (*TCPConn, error) {
+	c, err := dialTCP(net, laddr, raddr, deadline, cancel)
 	if ParseIP(slowDst4).Equal(raddr.IP) || ParseIP(slowDst6).Equal(raddr.IP) {
 		time.Sleep(deadline.Sub(time.Now()))
 	}
@@ -509,6 +510,9 @@ func TestDialerFallbackDelay(t *testing.T) {
 }
 
 func TestDialSerialAsyncSpuriousConnection(t *testing.T) {
+	if runtime.GOOS == "plan9" {
+		t.Skip("skipping on plan9; no deadline support, golang.org/issue/11932")
+	}
 	ln, err := newLocalListener("tcp")
 	if err != nil {
 		t.Fatal(err)
@@ -643,7 +647,7 @@ func TestDialerDualStack(t *testing.T) {
 		}
 	}
 
-	var timeout = 100*time.Millisecond + closedPortDelay
+	var timeout = 150*time.Millisecond + closedPortDelay
 	for _, dualstack := range []bool{false, true} {
 		dss, err := newDualStackServer([]streamListener{
 			{network: "tcp4", address: "127.0.0.1"},
@@ -713,3 +717,67 @@ func TestDialerKeepAlive(t *testing.T) {
 		}
 	}
 }
+
+func TestDialCancel(t *testing.T) {
+	if runtime.GOOS == "plan9" || runtime.GOOS == "nacl" {
+		// plan9 is not implemented and nacl doesn't have
+		// external network access.
+		t.Skipf("skipping on %s", runtime.GOOS)
+	}
+	onGoBuildFarm := testenv.Builder() != ""
+	if testing.Short() && !onGoBuildFarm {
+		t.Skip("skipping in short mode")
+	}
+
+	blackholeIPPort := JoinHostPort(slowDst4, "1234")
+	if !supportsIPv4 {
+		blackholeIPPort = JoinHostPort(slowDst6, "1234")
+	}
+
+	ticker := time.NewTicker(10 * time.Millisecond)
+	defer ticker.Stop()
+
+	const cancelTick = 5 // the timer tick we cancel the dial at
+	const timeoutTick = 100
+
+	var d Dialer
+	cancel := make(chan struct{})
+	d.Cancel = cancel
+	errc := make(chan error, 1)
+	connc := make(chan Conn, 1)
+	go func() {
+		if c, err := d.Dial("tcp", blackholeIPPort); err != nil {
+			errc <- err
+		} else {
+			connc <- c
+		}
+	}()
+	ticks := 0
+	for {
+		select {
+		case <-ticker.C:
+			ticks++
+			if ticks == cancelTick {
+				close(cancel)
+			}
+			if ticks == timeoutTick {
+				t.Fatal("timeout waiting for dial to fail")
+			}
+		case c := <-connc:
+			c.Close()
+			t.Fatal("unexpected successful connection")
+		case err := <-errc:
+			if perr := parseDialError(err); perr != nil {
+				t.Error(perr)
+			}
+			if ticks < cancelTick {
+				t.Fatalf("dial error after %d ticks (%d before cancel sent): %v",
+					ticks, cancelTick-ticks, err)
+			}
+			if oe, ok := err.(*OpError); !ok || oe.Err != errCanceled {
+				t.Fatalf("dial error = %v (%T); want OpError with Err == errCanceled", err, err)
+			}
+			return // success.
+		}
+	}
+}
diff --git a/src/net/dnsclient.go b/src/net/dnsclient.go
index ce48521..5dc2a03 100644
--- a/src/net/dnsclient.go
+++ b/src/net/dnsclient.go
@@ -40,15 +40,20 @@ func reverseaddr(addr string) (arpa string, err error) {
 func answer(name, server string, dns *dnsMsg, qtype uint16) (cname string, addrs []dnsRR, err error) {
 	addrs = make([]dnsRR, 0, len(dns.answer))
 
-	if dns.rcode == dnsRcodeNameError && dns.recursion_available {
+	if dns.rcode == dnsRcodeNameError {
 		return "", nil, &DNSError{Err: errNoSuchHost.Error(), Name: name, Server: server}
 	}
 	if dns.rcode != dnsRcodeSuccess {
 		// None of the error codes make sense
 		// for the query we sent.  If we didn't get
 		// a name error and we didn't get success,
-		// the server is behaving incorrectly.
-		return "", nil, &DNSError{Err: "server misbehaving", Name: name, Server: server}
+		// the server is behaving incorrectly or
+		// having temporary trouble.
+		err := &DNSError{Err: "server misbehaving", Name: name, Server: server}
+		if dns.rcode == dnsRcodeServerFailure {
+			err.IsTemporary = true
+		}
+		return "", nil, err
 	}
 
 	// Look for the name.
@@ -156,6 +161,28 @@ func isDomainName(s string) bool {
 	return ok
 }
 
+// absDomainName returns an absoulte domain name which ends with a
+// trailing dot to match pure Go reverse resolver and all other lookup
+// routines.
+// See golang.org/issue/12189.
+// But we don't want to add dots for local names from /etc/hosts.
+// It's hard to tell so we settle on the heuristic that names without dots
+// (like "localhost" or "myhost") do not get trailing dots, but any other
+// names do.
+func absDomainName(b []byte) string {
+	hasDots := false
+	for _, x := range b {
+		if x == '.' {
+			hasDots = true
+			break
+		}
+	}
+	if hasDots && b[len(b)-1] != '.' {
+		b = append(b, '.')
+	}
+	return string(b)
+}
+
 // An SRV represents a single DNS SRV record.
 type SRV struct {
 	Target   string
diff --git a/src/net/dnsclient_test.go b/src/net/dnsclient_test.go
index 3ab2b83..7308fb0 100644
--- a/src/net/dnsclient_test.go
+++ b/src/net/dnsclient_test.go
@@ -67,3 +67,51 @@ func testWeighting(t *testing.T, margin float64) {
 func TestWeighting(t *testing.T) {
 	testWeighting(t, 0.05)
 }
+
+// Issue 8434: verify that Temporary returns true on an error when rcode
+// is SERVFAIL
+func TestIssue8434(t *testing.T) {
+	msg := &dnsMsg{
+		dnsMsgHdr: dnsMsgHdr{
+			rcode: dnsRcodeServerFailure,
+		},
+	}
+
+	_, _, err := answer("golang.org", "foo:53", msg, uint16(dnsTypeSRV))
+	if err == nil {
+		t.Fatal("expected an error")
+	}
+	if ne, ok := err.(Error); !ok {
+		t.Fatalf("err = %#v; wanted something supporting net.Error", err)
+	} else if !ne.Temporary() {
+		t.Fatalf("Temporary = false for err = %#v; want Temporary == true", err)
+	}
+	if de, ok := err.(*DNSError); !ok {
+		t.Fatalf("err = %#v; wanted a *net.DNSError", err)
+	} else if !de.IsTemporary {
+		t.Fatalf("IsTemporary = false for err = %#v; want IsTemporary == true", err)
+	}
+}
+
+// Issue 12778: verify that NXDOMAIN without RA bit errors as
+// "no such host" and not "server misbehaving"
+func TestIssue12778(t *testing.T) {
+	msg := &dnsMsg{
+		dnsMsgHdr: dnsMsgHdr{
+			rcode:               dnsRcodeNameError,
+			recursion_available: false,
+		},
+	}
+
+	_, _, err := answer("golang.org", "foo:53", msg, uint16(dnsTypeSRV))
+	if err == nil {
+		t.Fatal("expected an error")
+	}
+	de, ok := err.(*DNSError)
+	if !ok {
+		t.Fatalf("err = %#v; wanted a *net.DNSError", err)
+	}
+	if de.Err != errNoSuchHost.Error() {
+		t.Fatalf("Err = %#v; wanted %q", de.Err, errNoSuchHost.Error())
+	}
+}
diff --git a/src/net/dnsclient_unix.go b/src/net/dnsclient_unix.go
index c03c1b1..17188f0 100644
--- a/src/net/dnsclient_unix.go
+++ b/src/net/dnsclient_unix.go
@@ -20,14 +20,22 @@ import (
 	"io"
 	"math/rand"
 	"os"
-	"strconv"
 	"sync"
 	"time"
 )
 
+// A dnsDialer provides dialing suitable for DNS queries.
+type dnsDialer interface {
+	dialDNS(string, string) (dnsConn, error)
+}
+
+var testHookDNSDialer = func(d time.Duration) dnsDialer { return &Dialer{Timeout: d} }
+
 // A dnsConn represents a DNS transport endpoint.
 type dnsConn interface {
-	Conn
+	io.Closer
+
+	SetDeadline(time.Time) error
 
 	// readDNSResponse reads a DNS response message from the DNS
 	// transport endpoint and returns the received DNS response
@@ -122,7 +130,7 @@ func (d *Dialer) dialDNS(network, server string) (dnsConn, error) {
 
 // exchange sends a query on the connection and hopes for a response.
 func exchange(server, name string, qtype uint16, timeout time.Duration) (*dnsMsg, error) {
-	d := Dialer{Timeout: timeout}
+	d := testHookDNSDialer(timeout)
 	out := dnsMsg{
 		dnsMsgHdr: dnsMsgHdr{
 			recursion_desired: true,
@@ -165,9 +173,6 @@ func tryOneName(cfg *dnsConfig, name string, qtype uint16) (string, []dnsRR, err
 	if len(cfg.servers) == 0 {
 		return "", nil, &DNSError{Err: "no DNS servers", Name: name}
 	}
-	if len(name) >= 256 {
-		return "", nil, &DNSError{Err: "DNS name too long", Name: name}
-	}
 	timeout := time.Duration(cfg.timeout) * time.Second
 	var lastErr error
 	for i := 0; i < cfg.attempts; i++ {
@@ -186,7 +191,11 @@ func tryOneName(cfg *dnsConfig, name string, qtype uint16) (string, []dnsRR, err
 				continue
 			}
 			cname, rrs, err := answer(name, server, msg, qtype)
-			if err == nil || msg.rcode == dnsRcodeSuccess || msg.rcode == dnsRcodeNameError && msg.recursion_available {
+			// If answer errored for rcodes dnsRcodeSuccess or dnsRcodeNameError,
+			// it means the response in msg was not useful and trying another
+			// server probably won't help. Return now in those cases.
+			// TODO: indicate this in a more obvious way, such as a field on DNSError?
+			if err == nil || msg.rcode == dnsRcodeSuccess || msg.rcode == dnsRcodeNameError {
 				return cname, rrs, err
 			}
 			lastErr = err
@@ -374,7 +383,7 @@ func (o hostLookupOrder) String() string {
 	if s, ok := lookupOrderName[o]; ok {
 		return s
 	}
-	return "hostLookupOrder=" + strconv.Itoa(int(o)) + "??"
+	return "hostLookupOrder=" + itoa(int(o)) + "??"
 }
 
 // goLookupHost is the native Go implementation of LookupHost.
@@ -440,7 +449,8 @@ func goLookupIPOrder(name string, order hostLookupOrder) (addrs []IPAddr, err er
 	conf := resolvConf.dnsConfig
 	resolvConf.mu.RUnlock()
 	type racer struct {
-		rrs []dnsRR
+		fqdn string
+		rrs  []dnsRR
 		error
 	}
 	lane := make(chan racer, 1)
@@ -450,13 +460,16 @@ func goLookupIPOrder(name string, order hostLookupOrder) (addrs []IPAddr, err er
 		for _, qtype := range qtypes {
 			go func(qtype uint16) {
 				_, rrs, err := tryOneName(conf, fqdn, qtype)
-				lane <- racer{rrs, err}
+				lane <- racer{fqdn, rrs, err}
 			}(qtype)
 		}
 		for range qtypes {
 			racer := <-lane
 			if racer.error != nil {
-				lastErr = racer.error
+				// Prefer error for original name.
+				if lastErr == nil || racer.fqdn == name+"." {
+					lastErr = racer.error
+				}
 				continue
 			}
 			addrs = append(addrs, addrRecordList(racer.rrs)...)
@@ -473,12 +486,12 @@ func goLookupIPOrder(name string, order hostLookupOrder) (addrs []IPAddr, err er
 	}
 	sortByRFC6724(addrs)
 	if len(addrs) == 0 {
-		if lastErr != nil {
-			return nil, lastErr
-		}
 		if order == hostLookupDNSFiles {
 			addrs = goLookupIPFiles(name)
 		}
+		if len(addrs) == 0 && lastErr != nil {
+			return nil, lastErr
+		}
 	}
 	return addrs, nil
 }
diff --git a/src/net/dnsclient_unix_test.go b/src/net/dnsclient_unix_test.go
index a999f8f..934f25b 100644
--- a/src/net/dnsclient_unix_test.go
+++ b/src/net/dnsclient_unix_test.go
@@ -80,7 +80,7 @@ func TestSpecialDomainName(t *testing.T) {
 
 	server := "8.8.8.8:53"
 	for _, tt := range specialDomainNameTests {
-		msg, err := exchange(server, tt.name, tt.qtype, 0)
+		msg, err := exchange(server, tt.name, tt.qtype, 3*time.Second)
 		if err != nil {
 			t.Error(err)
 			continue
@@ -378,6 +378,103 @@ func TestGoLookupIPWithResolverConfig(t *testing.T) {
 	}
 }
 
+// Test that goLookupIPOrder falls back to the host file when no DNS servers are available.
+func TestGoLookupIPOrderFallbackToFile(t *testing.T) {
+	if testing.Short() || !*testExternal {
+		t.Skip("avoid external network")
+	}
+
+	// Add a config that simulates no dns servers being available.
+	conf, err := newResolvConfTest()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if err := conf.writeAndUpdate([]string{}); err != nil {
+		t.Fatal(err)
+	}
+	conf.tryUpdate(conf.path)
+	// Redirect host file lookups.
+	defer func(orig string) { testHookHostsPath = orig }(testHookHostsPath)
+	testHookHostsPath = "testdata/hosts"
+
+	for _, order := range []hostLookupOrder{hostLookupFilesDNS, hostLookupDNSFiles} {
+		name := fmt.Sprintf("order %v", order)
+
+		// First ensure that we get an error when contacting a non-existant host.
+		_, err := goLookupIPOrder("notarealhost", order)
+		if err == nil {
+			t.Errorf("%s: expected error while looking up name not in hosts file", name)
+			continue
+		}
+
+		// Now check that we get an address when the name appears in the hosts file.
+		addrs, err := goLookupIPOrder("thor", order) // entry is in "testdata/hosts"
+		if err != nil {
+			t.Errorf("%s: expected to successfully lookup host entry", name)
+			continue
+		}
+		if len(addrs) != 1 {
+			t.Errorf("%s: expected exactly one result, but got %v", name, addrs)
+			continue
+		}
+		if got, want := addrs[0].String(), "127.1.1.1"; got != want {
+			t.Errorf("%s: address doesn't match expectation. got %v, want %v", name, got, want)
+		}
+	}
+	defer conf.teardown()
+}
+
+// Issue 12712.
+// When using search domains, return the error encountered
+// querying the original name instead of an error encountered
+// querying a generated name.
+func TestErrorForOriginalNameWhenSearching(t *testing.T) {
+	const fqdn = "doesnotexist.domain"
+
+	origTestHookDNSDialer := testHookDNSDialer
+	defer func() { testHookDNSDialer = origTestHookDNSDialer }()
+
+	conf, err := newResolvConfTest()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer conf.teardown()
+
+	if err := conf.writeAndUpdate([]string{"search servfail"}); err != nil {
+		t.Fatal(err)
+	}
+
+	d := &fakeDNSConn{}
+	testHookDNSDialer = func(time.Duration) dnsDialer { return d }
+
+	d.rh = func(q *dnsMsg) (*dnsMsg, error) {
+		r := &dnsMsg{
+			dnsMsgHdr: dnsMsgHdr{
+				id: q.id,
+			},
+		}
+
+		switch q.question[0].Name {
+		case fqdn + ".servfail.":
+			r.rcode = dnsRcodeServerFailure
+		default:
+			r.rcode = dnsRcodeNameError
+		}
+
+		return r, nil
+	}
+
+	_, err = goLookupIP(fqdn)
+	if err == nil {
+		t.Fatal("expected an error")
+	}
+
+	want := &DNSError{Name: fqdn, Err: errNoSuchHost.Error()}
+	if err, ok := err.(*DNSError); !ok || err.Name != want.Name || err.Err != want.Err {
+		t.Errorf("got %v; want %v", err, want)
+	}
+}
+
 func BenchmarkGoLookupIP(b *testing.B) {
 	testHookUninstaller.Do(uninstallTestHooks)
 
@@ -415,3 +512,37 @@ func BenchmarkGoLookupIPWithBrokenNameServer(b *testing.B) {
 		goLookupIP("www.example.com")
 	}
 }
+
+type fakeDNSConn struct {
+	// last query
+	qmu sync.Mutex // guards q
+	q   *dnsMsg
+	// reply handler
+	rh func(*dnsMsg) (*dnsMsg, error)
+}
+
+func (f *fakeDNSConn) dialDNS(n, s string) (dnsConn, error) {
+	return f, nil
+}
+
+func (f *fakeDNSConn) Close() error {
+	return nil
+}
+
+func (f *fakeDNSConn) SetDeadline(time.Time) error {
+	return nil
+}
+
+func (f *fakeDNSConn) writeDNSQuery(q *dnsMsg) error {
+	f.qmu.Lock()
+	defer f.qmu.Unlock()
+	f.q = q
+	return nil
+}
+
+func (f *fakeDNSConn) readDNSResponse() (*dnsMsg, error) {
+	f.qmu.Lock()
+	q := f.q
+	f.qmu.Unlock()
+	return f.rh(q)
+}
diff --git a/src/net/dnsmsg.go b/src/net/dnsmsg.go
index 6ecaa94..93078fe 100644
--- a/src/net/dnsmsg.go
+++ b/src/net/dnsmsg.go
@@ -691,6 +691,9 @@ func packRR(rr dnsRR, msg []byte, off int) (off2 int, ok bool) {
 	// off1 is end of header
 	// off2 is end of rr
 	off1, ok = packStruct(rr.Header(), msg, off)
+	if !ok {
+		return len(msg), false
+	}
 	off2, ok = packStruct(rr, msg, off)
 	if !ok {
 		return len(msg), false
diff --git a/src/net/error_test.go b/src/net/error_test.go
index bf95ff6..1aab14c 100644
--- a/src/net/error_test.go
+++ b/src/net/error_test.go
@@ -93,7 +93,7 @@ second:
 		goto third
 	}
 	switch nestedErr {
-	case errClosing, errMissingAddress:
+	case errCanceled, errClosing, errMissingAddress:
 		return nil
 	}
 	return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
@@ -116,8 +116,10 @@ var dialErrorTests = []struct {
 	{"tcp", "no-such-name:80"},
 	{"tcp", "mh/astro/r70:http"},
 
-	{"tcp", "127.0.0.1:0"},
-	{"udp", "127.0.0.1:0"},
+	{"tcp", JoinHostPort("127.0.0.1", "-1")},
+	{"tcp", JoinHostPort("127.0.0.1", "123456789")},
+	{"udp", JoinHostPort("127.0.0.1", "-1")},
+	{"udp", JoinHostPort("127.0.0.1", "123456789")},
 	{"ip:icmp", "127.0.0.1"},
 
 	{"unix", "/path/to/somewhere"},
@@ -145,10 +147,23 @@ func TestDialError(t *testing.T) {
 	for i, tt := range dialErrorTests {
 		c, err := d.Dial(tt.network, tt.address)
 		if err == nil {
-			t.Errorf("#%d: should fail; %s:%s->%s", i, tt.network, c.LocalAddr(), c.RemoteAddr())
+			t.Errorf("#%d: should fail; %s:%s->%s", i, c.LocalAddr().Network(), c.LocalAddr(), c.RemoteAddr())
 			c.Close()
 			continue
 		}
+		if tt.network == "tcp" || tt.network == "udp" {
+			nerr := err
+			if op, ok := nerr.(*OpError); ok {
+				nerr = op.Err
+			}
+			if sys, ok := nerr.(*os.SyscallError); ok {
+				nerr = sys.Err
+			}
+			if nerr == errOpNotSupported {
+				t.Errorf("#%d: should fail without %v; %s:%s->", i, nerr, tt.network, tt.address)
+				continue
+			}
+		}
 		if c != nil {
 			t.Errorf("Dial returned non-nil interface %T(%v) with err != nil", c, c)
 		}
@@ -198,7 +213,8 @@ var listenErrorTests = []struct {
 	{"tcp", "no-such-name:80"},
 	{"tcp", "mh/astro/r70:http"},
 
-	{"tcp", "127.0.0.1:0"},
+	{"tcp", JoinHostPort("127.0.0.1", "-1")},
+	{"tcp", JoinHostPort("127.0.0.1", "123456789")},
 
 	{"unix", "/path/to/somewhere"},
 	{"unixpacket", "/path/to/somewhere"},
@@ -223,10 +239,23 @@ func TestListenError(t *testing.T) {
 	for i, tt := range listenErrorTests {
 		ln, err := Listen(tt.network, tt.address)
 		if err == nil {
-			t.Errorf("#%d: should fail; %s:%s->", i, tt.network, ln.Addr())
+			t.Errorf("#%d: should fail; %s:%s->", i, ln.Addr().Network(), ln.Addr())
 			ln.Close()
 			continue
 		}
+		if tt.network == "tcp" {
+			nerr := err
+			if op, ok := nerr.(*OpError); ok {
+				nerr = op.Err
+			}
+			if sys, ok := nerr.(*os.SyscallError); ok {
+				nerr = sys.Err
+			}
+			if nerr == errOpNotSupported {
+				t.Errorf("#%d: should fail without %v; %s:%s->", i, nerr, tt.network, tt.address)
+				continue
+			}
+		}
 		if ln != nil {
 			t.Errorf("Listen returned non-nil interface %T(%v) with err != nil", ln, ln)
 		}
@@ -246,6 +275,9 @@ var listenPacketErrorTests = []struct {
 	{"udp", "127.0.0.1:☺"},
 	{"udp", "no-such-name:80"},
 	{"udp", "mh/astro/r70:http"},
+
+	{"udp", JoinHostPort("127.0.0.1", "-1")},
+	{"udp", JoinHostPort("127.0.0.1", "123456789")},
 }
 
 func TestListenPacketError(t *testing.T) {
@@ -263,7 +295,7 @@ func TestListenPacketError(t *testing.T) {
 	for i, tt := range listenPacketErrorTests {
 		c, err := ListenPacket(tt.network, tt.address)
 		if err == nil {
-			t.Errorf("#%d: should fail; %s:%s->", i, tt.network, c.LocalAddr())
+			t.Errorf("#%d: should fail; %s:%s->", i, c.LocalAddr().Network(), c.LocalAddr())
 			c.Close()
 			continue
 		}
@@ -381,7 +413,7 @@ second:
 		goto third
 	}
 	switch nestedErr {
-	case errClosing, errTimeout, ErrWriteToConnected, io.ErrUnexpectedEOF:
+	case errCanceled, errClosing, errTimeout, ErrWriteToConnected, io.ErrUnexpectedEOF:
 		return nil
 	}
 	return fmt.Errorf("unexpected type on 2nd nested level: %T", nestedErr)
diff --git a/src/net/fd_plan9.go b/src/net/fd_plan9.go
index 32766f5..cec8860 100644
--- a/src/net/fd_plan9.go
+++ b/src/net/fd_plan9.go
@@ -171,6 +171,14 @@ func (fd *netFD) Close() error {
 	if !fd.ok() {
 		return syscall.EINVAL
 	}
+	if fd.net == "tcp" {
+		// The following line is required to unblock Reads.
+		// For some reason, WriteString returns an error:
+		// "write /net/tcp/39/listen: inappropriate use of fd"
+		// But without it, Reads on dead conns hang forever.
+		// See Issue 9554.
+		fd.ctl.WriteString("hangup")
+	}
 	err := fd.ctl.Close()
 	if fd.data != nil {
 		if err1 := fd.data.Close(); err1 != nil && err == nil {
diff --git a/src/net/fd_unix.go b/src/net/fd_unix.go
index 6463b0d..2639eab 100644
--- a/src/net/fd_unix.go
+++ b/src/net/fd_unix.go
@@ -68,7 +68,7 @@ func (fd *netFD) name() string {
 	return fd.net + ":" + ls + "->" + rs
 }
 
-func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time) error {
+func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time, cancel <-chan struct{}) error {
 	// Do not need to call fd.writeLock here,
 	// because fd is not yet accessible to user,
 	// so no concurrent operations are possible.
@@ -102,6 +102,19 @@ func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time) error {
 		fd.setWriteDeadline(deadline)
 		defer fd.setWriteDeadline(noDeadline)
 	}
+	if cancel != nil {
+		done := make(chan bool)
+		defer close(done)
+		go func() {
+			select {
+			case <-cancel:
+				// Force the runtime's poller to immediately give
+				// up waiting for writability.
+				fd.setWriteDeadline(aLongTimeAgo)
+			case <-done:
+			}
+		}()
+	}
 	for {
 		// Performing multiple connect system calls on a
 		// non-blocking socket under Unix variants does not
@@ -112,6 +125,11 @@ func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time) error {
 		// succeeded or failed. See issue 7474 for further
 		// details.
 		if err := fd.pd.WaitWrite(); err != nil {
+			select {
+			case <-cancel:
+				return errCanceled
+			default:
+			}
 			return err
 		}
 		nerr, err := getsockoptIntFunc(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
diff --git a/src/net/fd_windows.go b/src/net/fd_windows.go
index 205daff..fd50d77 100644
--- a/src/net/fd_windows.go
+++ b/src/net/fd_windows.go
@@ -5,6 +5,7 @@
 package net
 
 import (
+	"internal/race"
 	"os"
 	"runtime"
 	"sync"
@@ -208,7 +209,7 @@ func (s *ioSrv) ExecIO(o *operation, name string, submit func(o *operation) erro
 		s.req <- ioSrvReq{o, nil}
 		<-o.errc
 	}
-	// Wait for cancellation to complete.
+	// Wait for cancelation to complete.
 	fd.pd.WaitCanceled(int(o.mode))
 	if o.errno != 0 {
 		err = syscall.Errno(o.errno)
@@ -217,8 +218,8 @@ func (s *ioSrv) ExecIO(o *operation, name string, submit func(o *operation) erro
 		}
 		return 0, err
 	}
-	// We issued cancellation request. But, it seems, IO operation succeeded
-	// before cancellation request run. We need to treat IO operation as
+	// We issued a cancelation request. But, it seems, IO operation succeeded
+	// before the cancelation request run. We need to treat the IO operation as
 	// succeeded (the bytes are actually sent/recv from network).
 	return int(o.qty), nil
 }
@@ -319,7 +320,7 @@ func (fd *netFD) setAddr(laddr, raddr Addr) {
 	runtime.SetFinalizer(fd, (*netFD).Close)
 }
 
-func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time) error {
+func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time, cancel <-chan struct{}) error {
 	// Do not need to call fd.writeLock here,
 	// because fd is not yet accessible to user,
 	// so no concurrent operations are possible.
@@ -350,14 +351,32 @@ func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time) error {
 	// Call ConnectEx API.
 	o := &fd.wop
 	o.sa = ra
+	if cancel != nil {
+		done := make(chan struct{})
+		defer close(done)
+		go func() {
+			select {
+			case <-cancel:
+				// Force the runtime's poller to immediately give
+				// up waiting for writability.
+				fd.setWriteDeadline(aLongTimeAgo)
+			case <-done:
+			}
+		}()
+	}
 	_, err := wsrv.ExecIO(o, "ConnectEx", func(o *operation) error {
 		return connectExFunc(o.fd.sysfd, o.sa, nil, 0, nil, &o.o)
 	})
 	if err != nil {
-		if _, ok := err.(syscall.Errno); ok {
-			err = os.NewSyscallError("connectex", err)
+		select {
+		case <-cancel:
+			return errCanceled
+		default:
+			if _, ok := err.(syscall.Errno); ok {
+				err = os.NewSyscallError("connectex", err)
+			}
+			return err
 		}
-		return err
 	}
 	// Refresh socket properties.
 	return os.NewSyscallError("setsockopt", syscall.Setsockopt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd))))
@@ -461,8 +480,8 @@ func (fd *netFD) Read(buf []byte) (int, error) {
 	n, err := rsrv.ExecIO(o, "WSARecv", func(o *operation) error {
 		return syscall.WSARecv(o.fd.sysfd, &o.buf, 1, &o.qty, &o.flags, &o.o, nil)
 	})
-	if raceenabled {
-		raceAcquire(unsafe.Pointer(&ioSync))
+	if race.Enabled {
+		race.Acquire(unsafe.Pointer(&ioSync))
 	}
 	err = fd.eofError(n, err)
 	if _, ok := err.(syscall.Errno); ok {
@@ -504,8 +523,8 @@ func (fd *netFD) Write(buf []byte) (int, error) {
 		return 0, err
 	}
 	defer fd.writeUnlock()
-	if raceenabled {
-		raceReleaseMerge(unsafe.Pointer(&ioSync))
+	if race.Enabled {
+		race.ReleaseMerge(unsafe.Pointer(&ioSync))
 	}
 	o := &fd.wop
 	o.InitBuf(buf)
diff --git a/src/net/file_test.go b/src/net/file_test.go
index 003dbb2..6566ce2 100644
--- a/src/net/file_test.go
+++ b/src/net/file_test.go
@@ -8,158 +8,222 @@ import (
 	"os"
 	"reflect"
 	"runtime"
+	"sync"
 	"testing"
 )
 
-type listenerFile interface {
-	Listener
-	File() (f *os.File, err error)
-}
-
-type packetConnFile interface {
-	PacketConn
-	File() (f *os.File, err error)
-}
+// The full stack test cases for IPConn have been moved to the
+// following:
+//      golang.org/x/net/ipv4
+//      golang.org/x/net/ipv6
+//      golang.org/x/net/icmp
 
-type connFile interface {
-	Conn
-	File() (f *os.File, err error)
+var fileConnTests = []struct {
+	network string
+}{
+	{"tcp"},
+	{"udp"},
+	{"unix"},
+	{"unixpacket"},
 }
 
-func testFileListener(t *testing.T, net, laddr string) {
-	l, err := Listen(net, laddr)
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer l.Close()
-	lf := l.(listenerFile)
-	f, err := lf.File()
-	if err != nil {
-		t.Fatal(err)
-	}
-	c, err := FileListener(f)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if !reflect.DeepEqual(l.Addr(), c.Addr()) {
-		t.Fatalf("got %#v; want%#v", l.Addr(), c.Addr())
-	}
-	if err := c.Close(); err != nil {
-		t.Fatal(err)
-	}
-	if err := f.Close(); err != nil {
-		t.Fatal(err)
+func TestFileConn(t *testing.T) {
+	switch runtime.GOOS {
+	case "nacl", "plan9", "windows":
+		t.Skipf("not supported on %s", runtime.GOOS)
 	}
-}
 
-var fileListenerTests = []struct {
-	net   string
-	laddr string
-}{
-	{net: "tcp", laddr: ":0"},
-	{net: "tcp", laddr: "0.0.0.0:0"},
-	{net: "tcp", laddr: "[::ffff:0.0.0.0]:0"},
-	{net: "tcp", laddr: "[::]:0"},
+	for _, tt := range fileConnTests {
+		if !testableNetwork(tt.network) {
+			t.Logf("skipping %s test", tt.network)
+			continue
+		}
 
-	{net: "tcp", laddr: "127.0.0.1:0"},
-	{net: "tcp", laddr: "[::ffff:127.0.0.1]:0"},
-	{net: "tcp", laddr: "[::1]:0"},
+		var network, address string
+		switch tt.network {
+		case "udp":
+			c, err := newLocalPacketListener(tt.network)
+			if err != nil {
+				t.Fatal(err)
+			}
+			defer c.Close()
+			network = c.LocalAddr().Network()
+			address = c.LocalAddr().String()
+		default:
+			handler := func(ls *localServer, ln Listener) {
+				c, err := ln.Accept()
+				if err != nil {
+					return
+				}
+				defer c.Close()
+				var b [1]byte
+				c.Read(b[:])
+			}
+			ls, err := newLocalServer(tt.network)
+			if err != nil {
+				t.Fatal(err)
+			}
+			defer ls.teardown()
+			if err := ls.buildup(handler); err != nil {
+				t.Fatal(err)
+			}
+			network = ls.Listener.Addr().Network()
+			address = ls.Listener.Addr().String()
+		}
 
-	{net: "tcp4", laddr: ":0"},
-	{net: "tcp4", laddr: "0.0.0.0:0"},
-	{net: "tcp4", laddr: "[::ffff:0.0.0.0]:0"},
+		c1, err := Dial(network, address)
+		if err != nil {
+			if perr := parseDialError(err); perr != nil {
+				t.Error(perr)
+			}
+			t.Fatal(err)
+		}
+		addr := c1.LocalAddr()
 
-	{net: "tcp4", laddr: "127.0.0.1:0"},
-	{net: "tcp4", laddr: "[::ffff:127.0.0.1]:0"},
+		var f *os.File
+		switch c1 := c1.(type) {
+		case *TCPConn:
+			f, err = c1.File()
+		case *UDPConn:
+			f, err = c1.File()
+		case *UnixConn:
+			f, err = c1.File()
+		}
+		if err := c1.Close(); err != nil {
+			if perr := parseCloseError(err); perr != nil {
+				t.Error(perr)
+			}
+			t.Error(err)
+		}
+		if err != nil {
+			if perr := parseCommonError(err); perr != nil {
+				t.Error(perr)
+			}
+			t.Fatal(err)
+		}
 
-	{net: "tcp6", laddr: ":0"},
-	{net: "tcp6", laddr: "[::]:0"},
+		c2, err := FileConn(f)
+		if err := f.Close(); err != nil {
+			t.Error(err)
+		}
+		if err != nil {
+			if perr := parseCommonError(err); perr != nil {
+				t.Error(perr)
+			}
+			t.Fatal(err)
+		}
+		defer c2.Close()
 
-	{net: "tcp6", laddr: "[::1]:0"},
+		if _, err := c2.Write([]byte("FILECONN TEST")); err != nil {
+			if perr := parseWriteError(err); perr != nil {
+				t.Error(perr)
+			}
+			t.Fatal(err)
+		}
+		if !reflect.DeepEqual(c2.LocalAddr(), addr) {
+			t.Fatalf("got %#v; want %#v", c2.LocalAddr(), addr)
+		}
+	}
+}
 
-	{net: "unix", laddr: "@gotest/net"},
-	{net: "unixpacket", laddr: "@gotest/net"},
+var fileListenerTests = []struct {
+	network string
+}{
+	{"tcp"},
+	{"unix"},
+	{"unixpacket"},
 }
 
 func TestFileListener(t *testing.T) {
 	switch runtime.GOOS {
-	case "nacl", "windows":
+	case "nacl", "plan9", "windows":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
 
 	for _, tt := range fileListenerTests {
-		if !testableListenArgs(tt.net, tt.laddr, "") {
-			t.Logf("skipping %s test", tt.net+" "+tt.laddr)
+		if !testableNetwork(tt.network) {
+			t.Logf("skipping %s test", tt.network)
 			continue
 		}
-		testFileListener(t, tt.net, tt.laddr)
-	}
-}
 
-func testFilePacketConn(t *testing.T, pcf packetConnFile, listen bool) {
-	f, err := pcf.File()
-	if err != nil {
-		t.Fatal(err)
-	}
-	c, err := FilePacketConn(f)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if !reflect.DeepEqual(pcf.LocalAddr(), c.LocalAddr()) {
-		t.Fatalf("got %#v; want %#v", pcf.LocalAddr(), c.LocalAddr())
-	}
-	if listen {
-		if _, err := c.WriteTo([]byte{}, c.LocalAddr()); err != nil {
+		ln1, err := newLocalListener(tt.network)
+		if err != nil {
 			t.Fatal(err)
 		}
-	}
-	if err := c.Close(); err != nil {
-		t.Fatal(err)
-	}
-	if err := f.Close(); err != nil {
-		t.Fatal(err)
-	}
-}
+		switch tt.network {
+		case "unix", "unixpacket":
+			defer os.Remove(ln1.Addr().String())
+		}
+		addr := ln1.Addr()
 
-func testFilePacketConnListen(t *testing.T, net, laddr string) {
-	l, err := ListenPacket(net, laddr)
-	if err != nil {
-		t.Fatal(err)
-	}
-	testFilePacketConn(t, l.(packetConnFile), true)
-	if err := l.Close(); err != nil {
-		t.Fatal(err)
-	}
-}
+		var f *os.File
+		switch ln1 := ln1.(type) {
+		case *TCPListener:
+			f, err = ln1.File()
+		case *UnixListener:
+			f, err = ln1.File()
+		}
+		switch tt.network {
+		case "unix", "unixpacket":
+			defer ln1.Close() // UnixListener.Close calls syscall.Unlink internally
+		default:
+			if err := ln1.Close(); err != nil {
+				t.Error(err)
+			}
+		}
+		if err != nil {
+			if perr := parseCommonError(err); perr != nil {
+				t.Error(perr)
+			}
+			t.Fatal(err)
+		}
 
-func testFilePacketConnDial(t *testing.T, net, raddr string) {
-	c, err := Dial(net, raddr)
-	if err != nil {
-		t.Fatal(err)
-	}
-	testFilePacketConn(t, c.(packetConnFile), false)
-	if err := c.Close(); err != nil {
-		t.Fatal(err)
+		ln2, err := FileListener(f)
+		if err := f.Close(); err != nil {
+			t.Error(err)
+		}
+		if err != nil {
+			if perr := parseCommonError(err); perr != nil {
+				t.Error(perr)
+			}
+			t.Fatal(err)
+		}
+		defer ln2.Close()
+
+		var wg sync.WaitGroup
+		wg.Add(1)
+		go func() {
+			defer wg.Done()
+			c, err := Dial(ln2.Addr().Network(), ln2.Addr().String())
+			if err != nil {
+				if perr := parseDialError(err); perr != nil {
+					t.Error(perr)
+				}
+				t.Error(err)
+				return
+			}
+			c.Close()
+		}()
+		c, err := ln2.Accept()
+		if err != nil {
+			if perr := parseAcceptError(err); perr != nil {
+				t.Error(perr)
+			}
+			t.Fatal(err)
+		}
+		c.Close()
+		wg.Wait()
+		if !reflect.DeepEqual(ln2.Addr(), addr) {
+			t.Fatalf("got %#v; want %#v", ln2.Addr(), addr)
+		}
 	}
 }
 
 var filePacketConnTests = []struct {
-	net  string
-	addr string
+	network string
 }{
-	{net: "udp", addr: "127.0.0.1:0"},
-	{net: "udp", addr: "[::ffff:127.0.0.1]:0"},
-	{net: "udp", addr: "[::1]:0"},
-
-	{net: "udp4", addr: "127.0.0.1:0"},
-	{net: "udp4", addr: "[::ffff:127.0.0.1]:0"},
-
-	{net: "udp6", addr: "[::1]:0"},
-
-	// TODO(mikioh,bradfitz): reenable once 10730 is fixed
-	// {net: "ip4:icmp", addr: "127.0.0.1"},
-
-	{net: "unixgram", addr: "@gotest3/net"},
+	{"udp"},
+	{"unixgram"},
 }
 
 func TestFilePacketConn(t *testing.T) {
@@ -169,25 +233,61 @@ func TestFilePacketConn(t *testing.T) {
 	}
 
 	for _, tt := range filePacketConnTests {
-		if !testableListenArgs(tt.net, tt.addr, "") {
-			t.Logf("skipping %s test", tt.net+" "+tt.addr)
+		if !testableNetwork(tt.network) {
+			t.Logf("skipping %s test", tt.network)
 			continue
 		}
-		if os.Getuid() != 0 && tt.net == "ip4:icmp" {
-			t.Log("skipping test; must be root")
-			continue
+
+		c1, err := newLocalPacketListener(tt.network)
+		if err != nil {
+			t.Fatal(err)
 		}
-		testFilePacketConnListen(t, tt.net, tt.addr)
-		switch tt.net {
-		case "udp", "udp4", "udp6":
-			host, _, err := SplitHostPort(tt.addr)
-			if err != nil {
-				t.Error(err)
-				continue
+		switch tt.network {
+		case "unixgram":
+			defer os.Remove(c1.LocalAddr().String())
+		}
+		addr := c1.LocalAddr()
+
+		var f *os.File
+		switch c1 := c1.(type) {
+		case *UDPConn:
+			f, err = c1.File()
+		case *UnixConn:
+			f, err = c1.File()
+		}
+		if err := c1.Close(); err != nil {
+			if perr := parseCloseError(err); perr != nil {
+				t.Error(perr)
 			}
-			testFilePacketConnDial(t, tt.net, JoinHostPort(host, "12345"))
-		case "ip4:icmp":
-			testFilePacketConnDial(t, tt.net, tt.addr)
+			t.Error(err)
+		}
+		if err != nil {
+			if perr := parseCommonError(err); perr != nil {
+				t.Error(perr)
+			}
+			t.Fatal(err)
+		}
+
+		c2, err := FilePacketConn(f)
+		if err := f.Close(); err != nil {
+			t.Error(err)
+		}
+		if err != nil {
+			if perr := parseCommonError(err); perr != nil {
+				t.Error(perr)
+			}
+			t.Fatal(err)
+		}
+		defer c2.Close()
+
+		if _, err := c2.WriteTo([]byte("FILEPACKETCONN TEST"), addr); err != nil {
+			if perr := parseWriteError(err); perr != nil {
+				t.Error(perr)
+			}
+			t.Fatal(err)
+		}
+		if !reflect.DeepEqual(c2.LocalAddr(), addr) {
+			t.Fatalf("got %#v; want %#v", c2.LocalAddr(), addr)
 		}
 	}
 }
diff --git a/src/net/file_unix.go b/src/net/file_unix.go
index 5b24c7d..9e581fc 100644
--- a/src/net/file_unix.go
+++ b/src/net/file_unix.go
@@ -91,7 +91,7 @@ func fileListener(f *os.File) (Listener, error) {
 	case *TCPAddr:
 		return &TCPListener{fd}, nil
 	case *UnixAddr:
-		return &UnixListener{fd, laddr.Name}, nil
+		return &UnixListener{fd: fd, path: laddr.Name, unlink: false}, nil
 	}
 	fd.Close()
 	return nil, syscall.EINVAL
diff --git a/src/net/hosts.go b/src/net/hosts.go
index 27958c7..c4de1b6 100644
--- a/src/net/hosts.go
+++ b/src/net/hosts.go
@@ -9,7 +9,7 @@ import (
 	"time"
 )
 
-const cacheMaxAge = 5 * time.Minute
+const cacheMaxAge = 5 * time.Second
 
 func parseLiteralIP(addr string) string {
 	var ip IP
@@ -27,51 +27,76 @@ func parseLiteralIP(addr string) string {
 	return ip.String() + "%" + zone
 }
 
-// Simple cache.
+// hosts contains known host entries.
 var hosts struct {
 	sync.Mutex
+
+	// Key for the list of literal IP addresses must be a host
+	// name. It would be part of DNS labels, a FQDN or an absolute
+	// FQDN.
+	// For now the key is converted to lower case for convenience.
 	byName map[string][]string
+
+	// Key for the list of host names must be a literal IP address
+	// including IPv6 address with zone identifier.
+	// We don't support old-classful IP address notation.
 	byAddr map[string][]string
+
 	expire time.Time
 	path   string
+	mtime  time.Time
+	size   int64
 }
 
 func readHosts() {
 	now := time.Now()
 	hp := testHookHostsPath
-	if len(hosts.byName) == 0 || now.After(hosts.expire) || hosts.path != hp {
-		hs := make(map[string][]string)
-		is := make(map[string][]string)
-		var file *file
-		if file, _ = open(hp); file == nil {
-			return
+
+	if now.Before(hosts.expire) && hosts.path == hp && len(hosts.byName) > 0 {
+		return
+	}
+	mtime, size, err := stat(hp)
+	if err == nil && hosts.path == hp && hosts.mtime.Equal(mtime) && hosts.size == size {
+		hosts.expire = now.Add(cacheMaxAge)
+		return
+	}
+
+	hs := make(map[string][]string)
+	is := make(map[string][]string)
+	var file *file
+	if file, _ = open(hp); file == nil {
+		return
+	}
+	for line, ok := file.readLine(); ok; line, ok = file.readLine() {
+		if i := byteIndex(line, '#'); i >= 0 {
+			// Discard comments.
+			line = line[0:i]
 		}
-		for line, ok := file.readLine(); ok; line, ok = file.readLine() {
-			if i := byteIndex(line, '#'); i >= 0 {
-				// Discard comments.
-				line = line[0:i]
-			}
-			f := getFields(line)
-			if len(f) < 2 {
-				continue
-			}
-			addr := parseLiteralIP(f[0])
-			if addr == "" {
-				continue
-			}
-			for i := 1; i < len(f); i++ {
-				h := f[i]
-				hs[h] = append(hs[h], addr)
-				is[addr] = append(is[addr], h)
-			}
+		f := getFields(line)
+		if len(f) < 2 {
+			continue
+		}
+		addr := parseLiteralIP(f[0])
+		if addr == "" {
+			continue
+		}
+		for i := 1; i < len(f); i++ {
+			name := absDomainName([]byte(f[i]))
+			h := []byte(f[i])
+			lowerASCIIBytes(h)
+			key := absDomainName(h)
+			hs[key] = append(hs[key], addr)
+			is[addr] = append(is[addr], name)
 		}
-		// Update the data cache.
-		hosts.expire = now.Add(cacheMaxAge)
-		hosts.path = hp
-		hosts.byName = hs
-		hosts.byAddr = is
-		file.close()
 	}
+	// Update the data cache.
+	hosts.expire = now.Add(cacheMaxAge)
+	hosts.path = hp
+	hosts.byName = hs
+	hosts.byAddr = is
+	hosts.mtime = mtime
+	hosts.size = size
+	file.close()
 }
 
 // lookupStaticHost looks up the addresses for the given host from /etc/hosts.
@@ -80,7 +105,11 @@ func lookupStaticHost(host string) []string {
 	defer hosts.Unlock()
 	readHosts()
 	if len(hosts.byName) != 0 {
-		if ips, ok := hosts.byName[host]; ok {
+		// TODO(jbd,bradfitz): avoid this alloc if host is already all lowercase?
+		// or linear scan the byName map if it's small enough?
+		lowerHost := []byte(host)
+		lowerASCIIBytes(lowerHost)
+		if ips, ok := hosts.byName[absDomainName(lowerHost)]; ok {
 			return ips
 		}
 	}
diff --git a/src/net/hosts_test.go b/src/net/hosts_test.go
index aca64c3..4c67bfa 100644
--- a/src/net/hosts_test.go
+++ b/src/net/hosts_test.go
@@ -6,6 +6,7 @@ package net
 
 import (
 	"reflect"
+	"strings"
 	"testing"
 )
 
@@ -48,6 +49,13 @@ var lookupStaticHostTests = []struct {
 			{"localhost.localdomain", []string{"fe80::3%lo0"}},
 		},
 	},
+	{
+		"testdata/case-hosts", // see golang.org/issue/12806
+		[]staticHostEntry{
+			{"PreserveMe", []string{"127.0.0.1", "::1"}},
+			{"PreserveMe.local", []string{"127.0.0.1", "::1"}},
+		},
+	},
 }
 
 func TestLookupStaticHost(t *testing.T) {
@@ -56,9 +64,12 @@ func TestLookupStaticHost(t *testing.T) {
 	for _, tt := range lookupStaticHostTests {
 		testHookHostsPath = tt.name
 		for _, ent := range tt.ents {
-			addrs := lookupStaticHost(ent.in)
-			if !reflect.DeepEqual(addrs, ent.out) {
-				t.Errorf("%s, lookupStaticHost(%s) = %v; want %v", tt.name, ent.in, addrs, ent.out)
+			ins := []string{ent.in, absDomainName([]byte(ent.in)), strings.ToLower(ent.in), strings.ToUpper(ent.in)}
+			for _, in := range ins {
+				addrs := lookupStaticHost(in)
+				if !reflect.DeepEqual(addrs, ent.out) {
+					t.Errorf("%s, lookupStaticHost(%s) = %v; want %v", tt.name, in, addrs, ent.out)
+				}
 			}
 		}
 	}
@@ -103,6 +114,13 @@ var lookupStaticAddrTests = []struct {
 			{"fe80::3%lo0", []string{"localhost", "localhost.localdomain"}},
 		},
 	},
+	{
+		"testdata/case-hosts", // see golang.org/issue/12806
+		[]staticHostEntry{
+			{"127.0.0.1", []string{"PreserveMe", "PreserveMe.local"}},
+			{"::1", []string{"PreserveMe", "PreserveMe.local"}},
+		},
+	},
 }
 
 func TestLookupStaticAddr(t *testing.T) {
@@ -112,6 +130,9 @@ func TestLookupStaticAddr(t *testing.T) {
 		testHookHostsPath = tt.name
 		for _, ent := range tt.ents {
 			hosts := lookupStaticAddr(ent.in)
+			for i := range ent.out {
+				ent.out[i] = absDomainName([]byte(ent.out[i]))
+			}
 			if !reflect.DeepEqual(hosts, ent.out) {
 				t.Errorf("%s, lookupStaticAddr(%s) = %v; want %v", tt.name, ent.in, hosts, ent.out)
 			}
diff --git a/src/net/http/cgi/host.go b/src/net/http/cgi/host.go
index 4efbe7a..9b4d875 100644
--- a/src/net/http/cgi/host.go
+++ b/src/net/http/cgi/host.go
@@ -77,15 +77,15 @@ type Handler struct {
 //      Env: []string{"SCRIPT_FILENAME=foo.php"},
 //    }
 func removeLeadingDuplicates(env []string) (ret []string) {
-	n := len(env)
-	for i := 0; i < n; i++ {
-		e := env[i]
-		s := strings.SplitN(e, "=", 2)[0]
+	for i, e := range env {
 		found := false
-		for j := i + 1; j < n; j++ {
-			if s == strings.SplitN(env[j], "=", 2)[0] {
-				found = true
-				break
+		if eq := strings.IndexByte(e, '='); eq != -1 {
+			keq := e[:eq+1] // "key="
+			for _, e2 := range env[i+1:] {
+				if strings.HasPrefix(e2, keq) {
+					found = true
+					break
+				}
 			}
 		}
 		if !found {
@@ -159,10 +159,6 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
 		env = append(env, "CONTENT_TYPE="+ctype)
 	}
 
-	if h.Env != nil {
-		env = append(env, h.Env...)
-	}
-
 	envPath := os.Getenv("PATH")
 	if envPath == "" {
 		envPath = "/bin:/usr/bin:/usr/ucb:/usr/bsd:/usr/local/bin"
@@ -181,6 +177,10 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
 		}
 	}
 
+	if h.Env != nil {
+		env = append(env, h.Env...)
+	}
+
 	env = removeLeadingDuplicates(env)
 
 	var cwd, path string
diff --git a/src/net/http/cgi/host_test.go b/src/net/http/cgi/host_test.go
index 4aa67e4..3327764 100644
--- a/src/net/http/cgi/host_test.go
+++ b/src/net/http/cgi/host_test.go
@@ -16,6 +16,7 @@ import (
 	"os"
 	"os/exec"
 	"path/filepath"
+	"reflect"
 	"runtime"
 	"strconv"
 	"strings"
@@ -487,12 +488,36 @@ func TestEnvOverride(t *testing.T) {
 		Args: []string{cgifile},
 		Env: []string{
 			"SCRIPT_FILENAME=" + cgifile,
-			"REQUEST_URI=/foo/bar"},
+			"REQUEST_URI=/foo/bar",
+			"PATH=/wibble"},
 	}
 	expectedMap := map[string]string{
 		"cwd": cwd,
 		"env-SCRIPT_FILENAME": cgifile,
 		"env-REQUEST_URI":     "/foo/bar",
+		"env-PATH":            "/wibble",
 	}
 	runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
 }
+
+func TestRemoveLeadingDuplicates(t *testing.T) {
+	tests := []struct {
+		env  []string
+		want []string
+	}{
+		{
+			env:  []string{"a=b", "b=c", "a=b2"},
+			want: []string{"b=c", "a=b2"},
+		},
+		{
+			env:  []string{"a=b", "b=c", "d", "e=f"},
+			want: []string{"a=b", "b=c", "d", "e=f"},
+		},
+	}
+	for _, tt := range tests {
+		got := removeLeadingDuplicates(tt.env)
+		if !reflect.DeepEqual(got, tt.want) {
+			t.Errorf("removeLeadingDuplicates(%q) = %q; want %q", tt.env, got, tt.want)
+		}
+	}
+}
diff --git a/src/net/http/client.go b/src/net/http/client.go
index 7f2fbb4..3106d22 100644
--- a/src/net/http/client.go
+++ b/src/net/http/client.go
@@ -10,6 +10,7 @@
 package http
 
 import (
+	"crypto/tls"
 	"encoding/base64"
 	"errors"
 	"fmt"
@@ -19,7 +20,6 @@ import (
 	"net/url"
 	"strings"
 	"sync"
-	"sync/atomic"
 	"time"
 )
 
@@ -65,10 +65,15 @@ type Client struct {
 	//
 	// A Timeout of zero means no timeout.
 	//
-	// The Client's Transport must support the CancelRequest
-	// method or Client will return errors when attempting to make
-	// a request with Get, Head, Post, or Do. Client's default
-	// Transport (DefaultTransport) supports CancelRequest.
+	// The Client cancels requests to the underlying Transport
+	// using the Request.Cancel mechanism. Requests passed
+	// to Client.Do may still set Request.Cancel; both will
+	// cancel the request.
+	//
+	// For compatibility, the Client will also use the deprecated
+	// CancelRequest method on Transport if found. New
+	// RoundTripper implementations should use Request.Cancel
+	// instead of implementing CancelRequest.
 	Timeout time.Duration
 }
 
@@ -82,19 +87,26 @@ var DefaultClient = &Client{}
 // goroutines.
 type RoundTripper interface {
 	// RoundTrip executes a single HTTP transaction, returning
-	// the Response for the request req.  RoundTrip should not
-	// attempt to interpret the response.  In particular,
-	// RoundTrip must return err == nil if it obtained a response,
-	// regardless of the response's HTTP status code.  A non-nil
-	// err should be reserved for failure to obtain a response.
-	// Similarly, RoundTrip should not attempt to handle
-	// higher-level protocol details such as redirects,
+	// a Response for the provided Request.
+	//
+	// RoundTrip should not attempt to interpret the response. In
+	// particular, RoundTrip must return err == nil if it obtained
+	// a response, regardless of the response's HTTP status code.
+	// A non-nil err should be reserved for failure to obtain a
+	// response. Similarly, RoundTrip should not attempt to
+	// handle higher-level protocol details such as redirects,
 	// authentication, or cookies.
 	//
 	// RoundTrip should not modify the request, except for
-	// consuming and closing the Body, including on errors. The
-	// request's URL and Header fields are guaranteed to be
-	// initialized.
+	// consuming and closing the Request's Body.
+	//
+	// RoundTrip must always close the body, including on errors,
+	// but depending on the implementation may do so in a separate
+	// goroutine even after RoundTrip returns. This means that
+	// callers wanting to reuse the body for subsequent requests
+	// must arrange to wait for the Close call before doing so.
+	//
+	// The Request's URL and Header fields must be initialized.
 	RoundTrip(*Request) (*Response, error)
 }
 
@@ -134,13 +146,13 @@ type readClose struct {
 	io.Closer
 }
 
-func (c *Client) send(req *Request) (*Response, error) {
+func (c *Client) send(req *Request, deadline time.Time) (*Response, error) {
 	if c.Jar != nil {
 		for _, cookie := range c.Jar.Cookies(req.URL) {
 			req.AddCookie(cookie)
 		}
 	}
-	resp, err := send(req, c.transport())
+	resp, err := send(req, c.transport(), deadline)
 	if err != nil {
 		return nil, err
 	}
@@ -171,13 +183,21 @@ func (c *Client) send(req *Request) (*Response, error) {
 //
 // Generally Get, Post, or PostForm will be used instead of Do.
 func (c *Client) Do(req *Request) (resp *Response, err error) {
-	if req.Method == "GET" || req.Method == "HEAD" {
+	method := valueOrDefault(req.Method, "GET")
+	if method == "GET" || method == "HEAD" {
 		return c.doFollowingRedirects(req, shouldRedirectGet)
 	}
-	if req.Method == "POST" || req.Method == "PUT" {
+	if method == "POST" || method == "PUT" {
 		return c.doFollowingRedirects(req, shouldRedirectPost)
 	}
-	return c.send(req)
+	return c.send(req, c.deadline())
+}
+
+func (c *Client) deadline() time.Time {
+	if c.Timeout > 0 {
+		return time.Now().Add(c.Timeout)
+	}
+	return time.Time{}
 }
 
 func (c *Client) transport() RoundTripper {
@@ -189,8 +209,10 @@ func (c *Client) transport() RoundTripper {
 
 // send issues an HTTP request.
 // Caller should close resp.Body when done reading from it.
-func send(req *Request, t RoundTripper) (resp *Response, err error) {
-	if t == nil {
+func send(ireq *Request, rt RoundTripper, deadline time.Time) (*Response, error) {
+	req := ireq // req is either the original request, or a modified fork
+
+	if rt == nil {
 		req.closeBody()
 		return nil, errors.New("http: no Client.Transport or DefaultTransport")
 	}
@@ -205,28 +227,122 @@ func send(req *Request, t RoundTripper) (resp *Response, err error) {
 		return nil, errors.New("http: Request.RequestURI can't be set in client requests.")
 	}
 
+	// forkReq forks req into a shallow clone of ireq the first
+	// time it's called.
+	forkReq := func() {
+		if ireq == req {
+			req = new(Request)
+			*req = *ireq // shallow clone
+		}
+	}
+
 	// Most the callers of send (Get, Post, et al) don't need
 	// Headers, leaving it uninitialized.  We guarantee to the
 	// Transport that this has been initialized, though.
 	if req.Header == nil {
+		forkReq()
 		req.Header = make(Header)
 	}
 
 	if u := req.URL.User; u != nil && req.Header.Get("Authorization") == "" {
 		username := u.Username()
 		password, _ := u.Password()
+		forkReq()
+		req.Header = cloneHeader(ireq.Header)
 		req.Header.Set("Authorization", "Basic "+basicAuth(username, password))
 	}
-	resp, err = t.RoundTrip(req)
+
+	if !deadline.IsZero() {
+		forkReq()
+	}
+	stopTimer, wasCanceled := setRequestCancel(req, rt, deadline)
+
+	resp, err := rt.RoundTrip(req)
 	if err != nil {
+		stopTimer()
 		if resp != nil {
 			log.Printf("RoundTripper returned a response & error; ignoring response")
 		}
+		if tlsErr, ok := err.(tls.RecordHeaderError); ok {
+			// If we get a bad TLS record header, check to see if the
+			// response looks like HTTP and give a more helpful error.
+			// See golang.org/issue/11111.
+			if string(tlsErr.RecordHeader[:]) == "HTTP/" {
+				err = errors.New("http: server gave HTTP response to HTTPS client")
+			}
+		}
 		return nil, err
 	}
+	if !deadline.IsZero() {
+		resp.Body = &cancelTimerBody{
+			stop:           stopTimer,
+			rc:             resp.Body,
+			reqWasCanceled: wasCanceled,
+		}
+	}
 	return resp, nil
 }
 
+// setRequestCancel sets the Cancel field of req, if deadline is
+// non-zero. The RoundTripper's type is used to determine whether the legacy
+// CancelRequest behavior should be used.
+func setRequestCancel(req *Request, rt RoundTripper, deadline time.Time) (stopTimer func(), wasCanceled func() bool) {
+	if deadline.IsZero() {
+		return nop, alwaysFalse
+	}
+
+	initialReqCancel := req.Cancel // the user's original Request.Cancel, if any
+
+	cancel := make(chan struct{})
+	req.Cancel = cancel
+
+	wasCanceled = func() bool {
+		select {
+		case <-cancel:
+			return true
+		default:
+			return false
+		}
+	}
+
+	doCancel := func() {
+		// The new way:
+		close(cancel)
+
+		// The legacy compatibility way, used only
+		// for RoundTripper implementations written
+		// before Go 1.5 or Go 1.6.
+		type canceler interface {
+			CancelRequest(*Request)
+		}
+		switch v := rt.(type) {
+		case *Transport, *http2Transport:
+			// Do nothing. The net/http package's transports
+			// support the new Request.Cancel channel
+		case canceler:
+			v.CancelRequest(req)
+		}
+	}
+
+	stopTimerCh := make(chan struct{})
+	var once sync.Once
+	stopTimer = func() { once.Do(func() { close(stopTimerCh) }) }
+
+	timer := time.NewTimer(deadline.Sub(time.Now()))
+	go func() {
+		select {
+		case <-initialReqCancel:
+			doCancel()
+		case <-timer.C:
+			doCancel()
+		case <-stopTimerCh:
+			timer.Stop()
+		}
+	}()
+
+	return stopTimer, wasCanceled
+}
+
 // See 2 (end of page 4) http://www.ietf.org/rfc/rfc2617.txt
 // "To receive authorization, the client sends the userid and password,
 // separated by a single colon (":") character, within a base64
@@ -321,34 +437,15 @@ func (c *Client) doFollowingRedirects(ireq *Request, shouldRedirect func(int) bo
 		return nil, errors.New("http: nil Request.URL")
 	}
 
-	var reqmu sync.Mutex // guards req
 	req := ireq
-
-	var timer *time.Timer
-	var atomicWasCanceled int32 // atomic bool (1 or 0)
-	var wasCanceled = alwaysFalse
-	if c.Timeout > 0 {
-		wasCanceled = func() bool { return atomic.LoadInt32(&atomicWasCanceled) != 0 }
-		type canceler interface {
-			CancelRequest(*Request)
-		}
-		tr, ok := c.transport().(canceler)
-		if !ok {
-			return nil, fmt.Errorf("net/http: Client Transport of type %T doesn't support CancelRequest; Timeout not supported", c.transport())
-		}
-		timer = time.AfterFunc(c.Timeout, func() {
-			atomic.StoreInt32(&atomicWasCanceled, 1)
-			reqmu.Lock()
-			defer reqmu.Unlock()
-			tr.CancelRequest(req)
-		})
-	}
+	deadline := c.deadline()
 
 	urlStr := "" // next relative or absolute URL to fetch (after first request)
 	redirectFailed := false
 	for redirect := 0; ; redirect++ {
 		if redirect != 0 {
 			nreq := new(Request)
+			nreq.Cancel = ireq.Cancel
 			nreq.Method = ireq.Method
 			if ireq.Method == "POST" || ireq.Method == "PUT" {
 				nreq.Method = "GET"
@@ -371,14 +468,12 @@ func (c *Client) doFollowingRedirects(ireq *Request, shouldRedirect func(int) bo
 					break
 				}
 			}
-			reqmu.Lock()
 			req = nreq
-			reqmu.Unlock()
 		}
 
 		urlStr = req.URL.String()
-		if resp, err = c.send(req); err != nil {
-			if wasCanceled() {
+		if resp, err = c.send(req, deadline); err != nil {
+			if !deadline.IsZero() && !time.Now().Before(deadline) {
 				err = &httpError{
 					err:     err.Error() + " (Client.Timeout exceeded while awaiting headers)",
 					timeout: true,
@@ -403,19 +498,12 @@ func (c *Client) doFollowingRedirects(ireq *Request, shouldRedirect func(int) bo
 			via = append(via, req)
 			continue
 		}
-		if timer != nil {
-			resp.Body = &cancelTimerBody{
-				t:              timer,
-				rc:             resp.Body,
-				reqWasCanceled: wasCanceled,
-			}
-		}
 		return resp, nil
 	}
 
-	method := ireq.Method
+	method := valueOrDefault(ireq.Method, "GET")
 	urlErr := &url.Error{
-		Op:  method[0:1] + strings.ToLower(method[1:]),
+		Op:  method[:1] + strings.ToLower(method[1:]),
 		URL: urlStr,
 		Err: err,
 	}
@@ -528,30 +616,35 @@ func (c *Client) Head(url string) (resp *Response, err error) {
 }
 
 // cancelTimerBody is an io.ReadCloser that wraps rc with two features:
-// 1) on Read EOF or Close, the timer t is Stopped,
+// 1) on Read error or close, the stop func is called.
 // 2) On Read failure, if reqWasCanceled is true, the error is wrapped and
 //    marked as net.Error that hit its timeout.
 type cancelTimerBody struct {
-	t              *time.Timer
+	stop           func() // stops the time.Timer waiting to cancel the request
 	rc             io.ReadCloser
 	reqWasCanceled func() bool
 }
 
 func (b *cancelTimerBody) Read(p []byte) (n int, err error) {
 	n, err = b.rc.Read(p)
+	if err == nil {
+		return n, nil
+	}
+	b.stop()
 	if err == io.EOF {
-		b.t.Stop()
-	} else if err != nil && b.reqWasCanceled() {
-		return n, &httpError{
+		return n, err
+	}
+	if b.reqWasCanceled() {
+		err = &httpError{
 			err:     err.Error() + " (Client.Timeout exceeded while reading body)",
 			timeout: true,
 		}
 	}
-	return
+	return n, err
 }
 
 func (b *cancelTimerBody) Close() error {
 	err := b.rc.Close()
-	b.t.Stop()
+	b.stop()
 	return err
 }
diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go
index 7b524d3..8939dc8 100644
--- a/src/net/http/client_test.go
+++ b/src/net/http/client_test.go
@@ -20,8 +20,6 @@ import (
 	. "net/http"
 	"net/http/httptest"
 	"net/url"
-	"reflect"
-	"sort"
 	"strconv"
 	"strings"
 	"sync"
@@ -83,12 +81,15 @@ func TestClient(t *testing.T) {
 	}
 }
 
-func TestClientHead(t *testing.T) {
+func TestClientHead_h1(t *testing.T) { testClientHead(t, h1Mode) }
+func TestClientHead_h2(t *testing.T) { testClientHead(t, h2Mode) }
+
+func testClientHead(t *testing.T, h2 bool) {
 	defer afterTest(t)
-	ts := httptest.NewServer(robotsTxtHandler)
-	defer ts.Close()
+	cst := newClientServerTest(t, h2, robotsTxtHandler)
+	defer cst.close()
 
-	r, err := Head(ts.URL)
+	r, err := cst.c.Head(cst.ts.URL)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -230,9 +231,18 @@ func TestClientRedirects(t *testing.T) {
 		t.Errorf("with default client Do, expected error %q, got %q", e, g)
 	}
 
+	// Requests with an empty Method should also redirect (Issue 12705)
+	greq.Method = ""
+	_, err = c.Do(greq)
+	if e, g := "Get /?n=10: stopped after 10 redirects", fmt.Sprintf("%v", err); e != g {
+		t.Errorf("with default client Do and empty Method, expected error %q, got %q", e, g)
+	}
+
 	var checkErr error
 	var lastVia []*Request
-	c = &Client{CheckRedirect: func(_ *Request, via []*Request) error {
+	var lastReq *Request
+	c = &Client{CheckRedirect: func(req *Request, via []*Request) error {
+		lastReq = req
 		lastVia = via
 		return checkErr
 	}}
@@ -252,6 +262,20 @@ func TestClientRedirects(t *testing.T) {
 		t.Errorf("expected lastVia to have contained %d elements; got %d", e, g)
 	}
 
+	// Test that Request.Cancel is propagated between requests (Issue 14053)
+	creq, _ := NewRequest("HEAD", ts.URL, nil)
+	cancel := make(chan struct{})
+	creq.Cancel = cancel
+	if _, err := c.Do(creq); err != nil {
+		t.Fatal(err)
+	}
+	if lastReq == nil {
+		t.Fatal("didn't see redirect")
+	}
+	if lastReq.Cancel != cancel {
+		t.Errorf("expected lastReq to have the cancel channel set on the inital req")
+	}
+
 	checkErr = errors.New("no redirects allowed")
 	res, err = c.Get(ts.URL)
 	if urlError, ok := err.(*url.Error); !ok || urlError.Err != checkErr {
@@ -486,20 +510,23 @@ func (j *RecordingJar) logf(format string, args ...interface{}) {
 	fmt.Fprintf(&j.log, format, args...)
 }
 
-func TestStreamingGet(t *testing.T) {
+func TestStreamingGet_h1(t *testing.T) { testStreamingGet(t, h1Mode) }
+func TestStreamingGet_h2(t *testing.T) { testStreamingGet(t, h2Mode) }
+
+func testStreamingGet(t *testing.T, h2 bool) {
 	defer afterTest(t)
 	say := make(chan string)
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
 		w.(Flusher).Flush()
 		for str := range say {
 			w.Write([]byte(str))
 			w.(Flusher).Flush()
 		}
 	}))
-	defer ts.Close()
+	defer cst.close()
 
-	c := &Client{}
-	res, err := c.Get(ts.URL)
+	c := cst.c
+	res, err := c.Get(cst.ts.URL)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -642,14 +669,18 @@ func newTLSTransport(t *testing.T, ts *httptest.Server) *Transport {
 
 func TestClientWithCorrectTLSServerName(t *testing.T) {
 	defer afterTest(t)
+
+	const serverName = "example.com"
 	ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		if r.TLS.ServerName != "127.0.0.1" {
-			t.Errorf("expected client to set ServerName 127.0.0.1, got: %q", r.TLS.ServerName)
+		if r.TLS.ServerName != serverName {
+			t.Errorf("expected client to set ServerName %q, got: %q", serverName, r.TLS.ServerName)
 		}
 	}))
 	defer ts.Close()
 
-	c := &Client{Transport: newTLSTransport(t, ts)}
+	trans := newTLSTransport(t, ts)
+	trans.TLSClientConfig.ServerName = serverName
+	c := &Client{Transport: trans}
 	if _, err := c.Get(ts.URL); err != nil {
 		t.Fatalf("expected successful TLS connection, got error: %v", err)
 	}
@@ -739,15 +770,37 @@ func TestResponseSetsTLSConnectionState(t *testing.T) {
 	}
 }
 
+// Check that an HTTPS client can interpret a particular TLS error
+// to determine that the server is speaking HTTP.
+// See golang.org/issue/11111.
+func TestHTTPSClientDetectsHTTPServer(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
+	defer ts.Close()
+
+	_, err := Get(strings.Replace(ts.URL, "http", "https", 1))
+	if got := err.Error(); !strings.Contains(got, "HTTP response to HTTPS client") {
+		t.Fatalf("error = %q; want error indicating HTTP response to HTTPS request", got)
+	}
+}
+
 // Verify Response.ContentLength is populated. https://golang.org/issue/4126
-func TestClientHeadContentLength(t *testing.T) {
+func TestClientHeadContentLength_h1(t *testing.T) {
+	testClientHeadContentLength(t, h1Mode)
+}
+
+func TestClientHeadContentLength_h2(t *testing.T) {
+	testClientHeadContentLength(t, h2Mode)
+}
+
+func testClientHeadContentLength(t *testing.T, h2 bool) {
 	defer afterTest(t)
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
 		if v := r.FormValue("cl"); v != "" {
 			w.Header().Set("Content-Length", v)
 		}
 	}))
-	defer ts.Close()
+	defer cst.close()
 	tests := []struct {
 		suffix string
 		want   int64
@@ -757,8 +810,8 @@ func TestClientHeadContentLength(t *testing.T) {
 		{"", -1},
 	}
 	for _, tt := range tests {
-		req, _ := NewRequest("HEAD", ts.URL+tt.suffix, nil)
-		res, err := DefaultClient.Do(req)
+		req, _ := NewRequest("HEAD", cst.ts.URL+tt.suffix, nil)
+		res, err := cst.c.Do(req)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -884,14 +937,17 @@ func TestBasicAuthHeadersPreserved(t *testing.T) {
 
 }
 
-func TestClientTimeout(t *testing.T) {
+func TestClientTimeout_h1(t *testing.T) { testClientTimeout(t, h1Mode) }
+func TestClientTimeout_h2(t *testing.T) { testClientTimeout(t, h2Mode) }
+
+func testClientTimeout(t *testing.T, h2 bool) {
 	if testing.Short() {
 		t.Skip("skipping in short mode")
 	}
 	defer afterTest(t)
 	sawRoot := make(chan bool, 1)
 	sawSlow := make(chan bool, 1)
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
 		if r.URL.Path == "/" {
 			sawRoot <- true
 			Redirect(w, r, "/slow", StatusFound)
@@ -905,13 +961,11 @@ func TestClientTimeout(t *testing.T) {
 			return
 		}
 	}))
-	defer ts.Close()
+	defer cst.close()
 	const timeout = 500 * time.Millisecond
-	c := &Client{
-		Timeout: timeout,
-	}
+	cst.c.Timeout = timeout
 
-	res, err := c.Get(ts.URL)
+	res, err := cst.c.Get(cst.ts.URL)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -957,17 +1011,20 @@ func TestClientTimeout(t *testing.T) {
 	}
 }
 
+func TestClientTimeout_Headers_h1(t *testing.T) { testClientTimeout_Headers(t, h1Mode) }
+func TestClientTimeout_Headers_h2(t *testing.T) { testClientTimeout_Headers(t, h2Mode) }
+
 // Client.Timeout firing before getting to the body
-func TestClientTimeout_Headers(t *testing.T) {
+func testClientTimeout_Headers(t *testing.T, h2 bool) {
 	if testing.Short() {
 		t.Skip("skipping in short mode")
 	}
 	defer afterTest(t)
 	donec := make(chan bool)
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
 		<-donec
 	}))
-	defer ts.Close()
+	defer cst.close()
 	// Note that we use a channel send here and not a close.
 	// The race detector doesn't know that we're waiting for a timeout
 	// and thinks that the waitgroup inside httptest.Server is added to concurrently
@@ -977,19 +1034,17 @@ func TestClientTimeout_Headers(t *testing.T) {
 	// doesn't know this, so synchronize explicitly.
 	defer func() { donec <- true }()
 
-	c := &Client{Timeout: 500 * time.Millisecond}
-
-	_, err := c.Get(ts.URL)
+	cst.c.Timeout = 500 * time.Millisecond
+	_, err := cst.c.Get(cst.ts.URL)
 	if err == nil {
 		t.Fatal("got response from Get; expected error")
 	}
-	ue, ok := err.(*url.Error)
-	if !ok {
+	if _, ok := err.(*url.Error); !ok {
 		t.Fatalf("Got error of type %T; want *url.Error", err)
 	}
-	ne, ok := ue.Err.(net.Error)
+	ne, ok := err.(net.Error)
 	if !ok {
-		t.Fatalf("Got url.Error.Err of type %T; want some net.Error", err)
+		t.Fatalf("Got error of type %T; want some net.Error", err)
 	}
 	if !ne.Timeout() {
 		t.Error("net.Error.Timeout = false; want true")
@@ -999,18 +1054,20 @@ func TestClientTimeout_Headers(t *testing.T) {
 	}
 }
 
-func TestClientRedirectEatsBody(t *testing.T) {
+func TestClientRedirectEatsBody_h1(t *testing.T) { testClientRedirectEatsBody(t, h1Mode) }
+func TestClientRedirectEatsBody_h2(t *testing.T) { testClientRedirectEatsBody(t, h2Mode) }
+func testClientRedirectEatsBody(t *testing.T, h2 bool) {
 	defer afterTest(t)
 	saw := make(chan string, 2)
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
 		saw <- r.RemoteAddr
 		if r.URL.Path == "/" {
 			Redirect(w, r, "/foo", StatusFound) // which includes a body
 		}
 	}))
-	defer ts.Close()
+	defer cst.close()
 
-	res, err := Get(ts.URL)
+	res, err := cst.c.Get(cst.ts.URL)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -1047,76 +1104,6 @@ func (f eofReaderFunc) Read(p []byte) (n int, err error) {
 	return 0, io.EOF
 }
 
-func TestClientTrailers(t *testing.T) {
-	defer afterTest(t)
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		w.Header().Set("Connection", "close")
-		w.Header().Set("Trailer", "Server-Trailer-A, Server-Trailer-B")
-		w.Header().Add("Trailer", "Server-Trailer-C")
-
-		var decl []string
-		for k := range r.Trailer {
-			decl = append(decl, k)
-		}
-		sort.Strings(decl)
-
-		slurp, err := ioutil.ReadAll(r.Body)
-		if err != nil {
-			t.Errorf("Server reading request body: %v", err)
-		}
-		if string(slurp) != "foo" {
-			t.Errorf("Server read request body %q; want foo", slurp)
-		}
-		if r.Trailer == nil {
-			io.WriteString(w, "nil Trailer")
-		} else {
-			fmt.Fprintf(w, "decl: %v, vals: %s, %s",
-				decl,
-				r.Trailer.Get("Client-Trailer-A"),
-				r.Trailer.Get("Client-Trailer-B"))
-		}
-
-		// How handlers set Trailers: declare it ahead of time
-		// with the Trailer header, and then mutate the
-		// Header() of those values later, after the response
-		// has been written (we wrote to w above).
-		w.Header().Set("Server-Trailer-A", "valuea")
-		w.Header().Set("Server-Trailer-C", "valuec") // skipping B
-	}))
-	defer ts.Close()
-
-	var req *Request
-	req, _ = NewRequest("POST", ts.URL, io.MultiReader(
-		eofReaderFunc(func() {
-			req.Trailer["Client-Trailer-A"] = []string{"valuea"}
-		}),
-		strings.NewReader("foo"),
-		eofReaderFunc(func() {
-			req.Trailer["Client-Trailer-B"] = []string{"valueb"}
-		}),
-	))
-	req.Trailer = Header{
-		"Client-Trailer-A": nil, //  to be set later
-		"Client-Trailer-B": nil, //  to be set later
-	}
-	req.ContentLength = -1
-	res, err := DefaultClient.Do(req)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if err := wantBody(res, err, "decl: [Client-Trailer-A Client-Trailer-B], vals: valuea, valueb"); err != nil {
-		t.Error(err)
-	}
-	want := Header{
-		"Server-Trailer-A": []string{"valuea"},
-		"Server-Trailer-B": nil,
-		"Server-Trailer-C": []string{"valuec"},
-	}
-	if !reflect.DeepEqual(res.Trailer, want) {
-		t.Errorf("Response trailers = %#v; want %#v", res.Trailer, want)
-	}
-}
-
 func TestReferer(t *testing.T) {
 	tests := []struct {
 		lastReq, newReq string // from -> to URLs
diff --git a/src/net/http/clientserver_test.go b/src/net/http/clientserver_test.go
new file mode 100644
index 0000000..fbaa805
--- /dev/null
+++ b/src/net/http/clientserver_test.go
@@ -0,0 +1,1056 @@
+// Copyright 2015 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.
+
+// Tests that use both the client & server, in both HTTP/1 and HTTP/2 mode.
+
+package http_test
+
+import (
+	"bytes"
+	"compress/gzip"
+	"crypto/tls"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"log"
+	"net"
+	. "net/http"
+	"net/http/httptest"
+	"net/url"
+	"os"
+	"reflect"
+	"runtime"
+	"sort"
+	"strings"
+	"sync"
+	"sync/atomic"
+	"testing"
+	"time"
+)
+
+type clientServerTest struct {
+	t  *testing.T
+	h2 bool
+	h  Handler
+	ts *httptest.Server
+	tr *Transport
+	c  *Client
+}
+
+func (t *clientServerTest) close() {
+	t.tr.CloseIdleConnections()
+	t.ts.Close()
+}
+
+const (
+	h1Mode = false
+	h2Mode = true
+)
+
+func newClientServerTest(t *testing.T, h2 bool, h Handler, opts ...interface{}) *clientServerTest {
+	cst := &clientServerTest{
+		t:  t,
+		h2: h2,
+		h:  h,
+		tr: &Transport{},
+	}
+	cst.c = &Client{Transport: cst.tr}
+
+	for _, opt := range opts {
+		switch opt := opt.(type) {
+		case func(*Transport):
+			opt(cst.tr)
+		default:
+			t.Fatalf("unhandled option type %T", opt)
+		}
+	}
+
+	if !h2 {
+		cst.ts = httptest.NewServer(h)
+		return cst
+	}
+	cst.ts = httptest.NewUnstartedServer(h)
+	ExportHttp2ConfigureServer(cst.ts.Config, nil)
+	cst.ts.TLS = cst.ts.Config.TLSConfig
+	cst.ts.StartTLS()
+
+	cst.tr.TLSClientConfig = &tls.Config{
+		InsecureSkipVerify: true,
+	}
+	if err := ExportHttp2ConfigureTransport(cst.tr); err != nil {
+		t.Fatal(err)
+	}
+	return cst
+}
+
+// Testing the newClientServerTest helper itself.
+func TestNewClientServerTest(t *testing.T) {
+	var got struct {
+		sync.Mutex
+		log []string
+	}
+	h := HandlerFunc(func(w ResponseWriter, r *Request) {
+		got.Lock()
+		defer got.Unlock()
+		got.log = append(got.log, r.Proto)
+	})
+	for _, v := range [2]bool{false, true} {
+		cst := newClientServerTest(t, v, h)
+		if _, err := cst.c.Head(cst.ts.URL); err != nil {
+			t.Fatal(err)
+		}
+		cst.close()
+	}
+	got.Lock() // no need to unlock
+	if want := []string{"HTTP/1.1", "HTTP/2.0"}; !reflect.DeepEqual(got.log, want) {
+		t.Errorf("got %q; want %q", got.log, want)
+	}
+}
+
+func TestChunkedResponseHeaders_h1(t *testing.T) { testChunkedResponseHeaders(t, h1Mode) }
+func TestChunkedResponseHeaders_h2(t *testing.T) { testChunkedResponseHeaders(t, h2Mode) }
+
+func testChunkedResponseHeaders(t *testing.T, h2 bool) {
+	defer afterTest(t)
+	log.SetOutput(ioutil.Discard) // is noisy otherwise
+	defer log.SetOutput(os.Stderr)
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Content-Length", "intentional gibberish") // we check that this is deleted
+		w.(Flusher).Flush()
+		fmt.Fprintf(w, "I am a chunked response.")
+	}))
+	defer cst.close()
+
+	res, err := cst.c.Get(cst.ts.URL)
+	if err != nil {
+		t.Fatalf("Get error: %v", err)
+	}
+	defer res.Body.Close()
+	if g, e := res.ContentLength, int64(-1); g != e {
+		t.Errorf("expected ContentLength of %d; got %d", e, g)
+	}
+	wantTE := []string{"chunked"}
+	if h2 {
+		wantTE = nil
+	}
+	if !reflect.DeepEqual(res.TransferEncoding, wantTE) {
+		t.Errorf("TransferEncoding = %v; want %v", res.TransferEncoding, wantTE)
+	}
+	if got, haveCL := res.Header["Content-Length"]; haveCL {
+		t.Errorf("Unexpected Content-Length: %q", got)
+	}
+}
+
+type reqFunc func(c *Client, url string) (*Response, error)
+
+// h12Compare is a test that compares HTTP/1 and HTTP/2 behavior
+// against each other.
+type h12Compare struct {
+	Handler       func(ResponseWriter, *Request)    // required
+	ReqFunc       reqFunc                           // optional
+	CheckResponse func(proto string, res *Response) // optional
+	Opts          []interface{}
+}
+
+func (tt h12Compare) reqFunc() reqFunc {
+	if tt.ReqFunc == nil {
+		return (*Client).Get
+	}
+	return tt.ReqFunc
+}
+
+func (tt h12Compare) run(t *testing.T) {
+	cst1 := newClientServerTest(t, false, HandlerFunc(tt.Handler), tt.Opts...)
+	defer cst1.close()
+	cst2 := newClientServerTest(t, true, HandlerFunc(tt.Handler), tt.Opts...)
+	defer cst2.close()
+
+	res1, err := tt.reqFunc()(cst1.c, cst1.ts.URL)
+	if err != nil {
+		t.Errorf("HTTP/1 request: %v", err)
+		return
+	}
+	res2, err := tt.reqFunc()(cst2.c, cst2.ts.URL)
+	if err != nil {
+		t.Errorf("HTTP/2 request: %v", err)
+		return
+	}
+	tt.normalizeRes(t, res1, "HTTP/1.1")
+	tt.normalizeRes(t, res2, "HTTP/2.0")
+	res1body, res2body := res1.Body, res2.Body
+
+	eres1 := mostlyCopy(res1)
+	eres2 := mostlyCopy(res2)
+	if !reflect.DeepEqual(eres1, eres2) {
+		t.Errorf("Response headers to handler differed:\nhttp/1 (%v):\n\t%#v\nhttp/2 (%v):\n\t%#v",
+			cst1.ts.URL, eres1, cst2.ts.URL, eres2)
+	}
+	if !reflect.DeepEqual(res1body, res2body) {
+		t.Errorf("Response bodies to handler differed.\nhttp1: %v\nhttp2: %v\n", res1body, res2body)
+	}
+	if fn := tt.CheckResponse; fn != nil {
+		res1.Body, res2.Body = res1body, res2body
+		fn("HTTP/1.1", res1)
+		fn("HTTP/2.0", res2)
+	}
+}
+
+func mostlyCopy(r *Response) *Response {
+	c := *r
+	c.Body = nil
+	c.TransferEncoding = nil
+	c.TLS = nil
+	c.Request = nil
+	return &c
+}
+
+type slurpResult struct {
+	io.ReadCloser
+	body []byte
+	err  error
+}
+
+func (sr slurpResult) String() string { return fmt.Sprintf("body %q; err %v", sr.body, sr.err) }
+
+func (tt h12Compare) normalizeRes(t *testing.T, res *Response, wantProto string) {
+	if res.Proto == wantProto {
+		res.Proto, res.ProtoMajor, res.ProtoMinor = "", 0, 0
+	} else {
+		t.Errorf("got %q response; want %q", res.Proto, wantProto)
+	}
+	slurp, err := ioutil.ReadAll(res.Body)
+	res.Body.Close()
+	res.Body = slurpResult{
+		ReadCloser: ioutil.NopCloser(bytes.NewReader(slurp)),
+		body:       slurp,
+		err:        err,
+	}
+	for i, v := range res.Header["Date"] {
+		res.Header["Date"][i] = strings.Repeat("x", len(v))
+	}
+	if res.Request == nil {
+		t.Errorf("for %s, no request", wantProto)
+	}
+	if (res.TLS != nil) != (wantProto == "HTTP/2.0") {
+		t.Errorf("TLS set = %v; want %v", res.TLS != nil, res.TLS == nil)
+	}
+}
+
+// Issue 13532
+func TestH12_HeadContentLengthNoBody(t *testing.T) {
+	h12Compare{
+		ReqFunc: (*Client).Head,
+		Handler: func(w ResponseWriter, r *Request) {
+		},
+	}.run(t)
+}
+
+func TestH12_HeadContentLengthSmallBody(t *testing.T) {
+	h12Compare{
+		ReqFunc: (*Client).Head,
+		Handler: func(w ResponseWriter, r *Request) {
+			io.WriteString(w, "small")
+		},
+	}.run(t)
+}
+
+func TestH12_HeadContentLengthLargeBody(t *testing.T) {
+	h12Compare{
+		ReqFunc: (*Client).Head,
+		Handler: func(w ResponseWriter, r *Request) {
+			chunk := strings.Repeat("x", 512<<10)
+			for i := 0; i < 10; i++ {
+				io.WriteString(w, chunk)
+			}
+		},
+	}.run(t)
+}
+
+func TestH12_200NoBody(t *testing.T) {
+	h12Compare{Handler: func(w ResponseWriter, r *Request) {}}.run(t)
+}
+
+func TestH2_204NoBody(t *testing.T) { testH12_noBody(t, 204) }
+func TestH2_304NoBody(t *testing.T) { testH12_noBody(t, 304) }
+func TestH2_404NoBody(t *testing.T) { testH12_noBody(t, 404) }
+
+func testH12_noBody(t *testing.T, status int) {
+	h12Compare{Handler: func(w ResponseWriter, r *Request) {
+		w.WriteHeader(status)
+	}}.run(t)
+}
+
+func TestH12_SmallBody(t *testing.T) {
+	h12Compare{Handler: func(w ResponseWriter, r *Request) {
+		io.WriteString(w, "small body")
+	}}.run(t)
+}
+
+func TestH12_ExplicitContentLength(t *testing.T) {
+	h12Compare{Handler: func(w ResponseWriter, r *Request) {
+		w.Header().Set("Content-Length", "3")
+		io.WriteString(w, "foo")
+	}}.run(t)
+}
+
+func TestH12_FlushBeforeBody(t *testing.T) {
+	h12Compare{Handler: func(w ResponseWriter, r *Request) {
+		w.(Flusher).Flush()
+		io.WriteString(w, "foo")
+	}}.run(t)
+}
+
+func TestH12_FlushMidBody(t *testing.T) {
+	h12Compare{Handler: func(w ResponseWriter, r *Request) {
+		io.WriteString(w, "foo")
+		w.(Flusher).Flush()
+		io.WriteString(w, "bar")
+	}}.run(t)
+}
+
+func TestH12_Head_ExplicitLen(t *testing.T) {
+	h12Compare{
+		ReqFunc: (*Client).Head,
+		Handler: func(w ResponseWriter, r *Request) {
+			if r.Method != "HEAD" {
+				t.Errorf("unexpected method %q", r.Method)
+			}
+			w.Header().Set("Content-Length", "1235")
+		},
+	}.run(t)
+}
+
+func TestH12_Head_ImplicitLen(t *testing.T) {
+	h12Compare{
+		ReqFunc: (*Client).Head,
+		Handler: func(w ResponseWriter, r *Request) {
+			if r.Method != "HEAD" {
+				t.Errorf("unexpected method %q", r.Method)
+			}
+			io.WriteString(w, "foo")
+		},
+	}.run(t)
+}
+
+func TestH12_HandlerWritesTooLittle(t *testing.T) {
+	h12Compare{
+		Handler: func(w ResponseWriter, r *Request) {
+			w.Header().Set("Content-Length", "3")
+			io.WriteString(w, "12") // one byte short
+		},
+		CheckResponse: func(proto string, res *Response) {
+			sr, ok := res.Body.(slurpResult)
+			if !ok {
+				t.Errorf("%s body is %T; want slurpResult", proto, res.Body)
+				return
+			}
+			if sr.err != io.ErrUnexpectedEOF {
+				t.Errorf("%s read error = %v; want io.ErrUnexpectedEOF", proto, sr.err)
+			}
+			if string(sr.body) != "12" {
+				t.Errorf("%s body = %q; want %q", proto, sr.body, "12")
+			}
+		},
+	}.run(t)
+}
+
+// Tests that the HTTP/1 and HTTP/2 servers prevent handlers from
+// writing more than they declared.  This test does not test whether
+// the transport deals with too much data, though, since the server
+// doesn't make it possible to send bogus data. For those tests, see
+// transport_test.go (for HTTP/1) or x/net/http2/transport_test.go
+// (for HTTP/2).
+func TestH12_HandlerWritesTooMuch(t *testing.T) {
+	h12Compare{
+		Handler: func(w ResponseWriter, r *Request) {
+			w.Header().Set("Content-Length", "3")
+			w.(Flusher).Flush()
+			io.WriteString(w, "123")
+			w.(Flusher).Flush()
+			n, err := io.WriteString(w, "x") // too many
+			if n > 0 || err == nil {
+				t.Errorf("for proto %q, final write = %v, %v; want 0, some error", r.Proto, n, err)
+			}
+		},
+	}.run(t)
+}
+
+// Verify that both our HTTP/1 and HTTP/2 request and auto-decompress gzip.
+// Some hosts send gzip even if you don't ask for it; see golang.org/issue/13298
+func TestH12_AutoGzip(t *testing.T) {
+	h12Compare{
+		Handler: func(w ResponseWriter, r *Request) {
+			if ae := r.Header.Get("Accept-Encoding"); ae != "gzip" {
+				t.Errorf("%s Accept-Encoding = %q; want gzip", r.Proto, ae)
+			}
+			w.Header().Set("Content-Encoding", "gzip")
+			gz := gzip.NewWriter(w)
+			io.WriteString(gz, "I am some gzipped content. Go go go go go go go go go go go go should compress well.")
+			gz.Close()
+		},
+	}.run(t)
+}
+
+func TestH12_AutoGzip_Disabled(t *testing.T) {
+	h12Compare{
+		Opts: []interface{}{
+			func(tr *Transport) { tr.DisableCompression = true },
+		},
+		Handler: func(w ResponseWriter, r *Request) {
+			fmt.Fprintf(w, "%q", r.Header["Accept-Encoding"])
+			if ae := r.Header.Get("Accept-Encoding"); ae != "" {
+				t.Errorf("%s Accept-Encoding = %q; want empty", r.Proto, ae)
+			}
+		},
+	}.run(t)
+}
+
+// Test304Responses verifies that 304s don't declare that they're
+// chunking in their response headers and aren't allowed to produce
+// output.
+func Test304Responses_h1(t *testing.T) { test304Responses(t, h1Mode) }
+func Test304Responses_h2(t *testing.T) { test304Responses(t, h2Mode) }
+
+func test304Responses(t *testing.T, h2 bool) {
+	defer afterTest(t)
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.WriteHeader(StatusNotModified)
+		_, err := w.Write([]byte("illegal body"))
+		if err != ErrBodyNotAllowed {
+			t.Errorf("on Write, expected ErrBodyNotAllowed, got %v", err)
+		}
+	}))
+	defer cst.close()
+	res, err := cst.c.Get(cst.ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if len(res.TransferEncoding) > 0 {
+		t.Errorf("expected no TransferEncoding; got %v", res.TransferEncoding)
+	}
+	body, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Error(err)
+	}
+	if len(body) > 0 {
+		t.Errorf("got unexpected body %q", string(body))
+	}
+}
+
+func TestH12_ServerEmptyContentLength(t *testing.T) {
+	h12Compare{
+		Handler: func(w ResponseWriter, r *Request) {
+			w.Header()["Content-Type"] = []string{""}
+			io.WriteString(w, "<html><body>hi</body></html>")
+		},
+	}.run(t)
+}
+
+func TestH12_RequestContentLength_Known_NonZero(t *testing.T) {
+	h12requestContentLength(t, func() io.Reader { return strings.NewReader("FOUR") }, 4)
+}
+
+func TestH12_RequestContentLength_Known_Zero(t *testing.T) {
+	h12requestContentLength(t, func() io.Reader { return strings.NewReader("") }, 0)
+}
+
+func TestH12_RequestContentLength_Unknown(t *testing.T) {
+	h12requestContentLength(t, func() io.Reader { return struct{ io.Reader }{strings.NewReader("Stuff")} }, -1)
+}
+
+func h12requestContentLength(t *testing.T, bodyfn func() io.Reader, wantLen int64) {
+	h12Compare{
+		Handler: func(w ResponseWriter, r *Request) {
+			w.Header().Set("Got-Length", fmt.Sprint(r.ContentLength))
+			fmt.Fprintf(w, "Req.ContentLength=%v", r.ContentLength)
+		},
+		ReqFunc: func(c *Client, url string) (*Response, error) {
+			return c.Post(url, "text/plain", bodyfn())
+		},
+		CheckResponse: func(proto string, res *Response) {
+			if got, want := res.Header.Get("Got-Length"), fmt.Sprint(wantLen); got != want {
+				t.Errorf("Proto %q got length %q; want %q", proto, got, want)
+			}
+		},
+	}.run(t)
+}
+
+// Tests that closing the Request.Cancel channel also while still
+// reading the response body. Issue 13159.
+func TestCancelRequestMidBody_h1(t *testing.T) { testCancelRequestMidBody(t, h1Mode) }
+func TestCancelRequestMidBody_h2(t *testing.T) { testCancelRequestMidBody(t, h2Mode) }
+func testCancelRequestMidBody(t *testing.T, h2 bool) {
+	defer afterTest(t)
+	unblock := make(chan bool)
+	didFlush := make(chan bool, 1)
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
+		io.WriteString(w, "Hello")
+		w.(Flusher).Flush()
+		didFlush <- true
+		<-unblock
+		io.WriteString(w, ", world.")
+	}))
+	defer cst.close()
+	defer close(unblock)
+
+	req, _ := NewRequest("GET", cst.ts.URL, nil)
+	cancel := make(chan struct{})
+	req.Cancel = cancel
+
+	res, err := cst.c.Do(req)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer res.Body.Close()
+	<-didFlush
+
+	// Read a bit before we cancel. (Issue 13626)
+	// We should have "Hello" at least sitting there.
+	firstRead := make([]byte, 10)
+	n, err := res.Body.Read(firstRead)
+	if err != nil {
+		t.Fatal(err)
+	}
+	firstRead = firstRead[:n]
+
+	close(cancel)
+
+	rest, err := ioutil.ReadAll(res.Body)
+	all := string(firstRead) + string(rest)
+	if all != "Hello" {
+		t.Errorf("Read %q (%q + %q); want Hello", all, firstRead, rest)
+	}
+	if !reflect.DeepEqual(err, ExportErrRequestCanceled) {
+		t.Errorf("ReadAll error = %v; want %v", err, ExportErrRequestCanceled)
+	}
+}
+
+// Tests that clients can send trailers to a server and that the server can read them.
+func TestTrailersClientToServer_h1(t *testing.T) { testTrailersClientToServer(t, h1Mode) }
+func TestTrailersClientToServer_h2(t *testing.T) { testTrailersClientToServer(t, h2Mode) }
+
+func testTrailersClientToServer(t *testing.T, h2 bool) {
+	defer afterTest(t)
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
+		var decl []string
+		for k := range r.Trailer {
+			decl = append(decl, k)
+		}
+		sort.Strings(decl)
+
+		slurp, err := ioutil.ReadAll(r.Body)
+		if err != nil {
+			t.Errorf("Server reading request body: %v", err)
+		}
+		if string(slurp) != "foo" {
+			t.Errorf("Server read request body %q; want foo", slurp)
+		}
+		if r.Trailer == nil {
+			io.WriteString(w, "nil Trailer")
+		} else {
+			fmt.Fprintf(w, "decl: %v, vals: %s, %s",
+				decl,
+				r.Trailer.Get("Client-Trailer-A"),
+				r.Trailer.Get("Client-Trailer-B"))
+		}
+	}))
+	defer cst.close()
+
+	var req *Request
+	req, _ = NewRequest("POST", cst.ts.URL, io.MultiReader(
+		eofReaderFunc(func() {
+			req.Trailer["Client-Trailer-A"] = []string{"valuea"}
+		}),
+		strings.NewReader("foo"),
+		eofReaderFunc(func() {
+			req.Trailer["Client-Trailer-B"] = []string{"valueb"}
+		}),
+	))
+	req.Trailer = Header{
+		"Client-Trailer-A": nil, //  to be set later
+		"Client-Trailer-B": nil, //  to be set later
+	}
+	req.ContentLength = -1
+	res, err := cst.c.Do(req)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if err := wantBody(res, err, "decl: [Client-Trailer-A Client-Trailer-B], vals: valuea, valueb"); err != nil {
+		t.Error(err)
+	}
+}
+
+// Tests that servers send trailers to a client and that the client can read them.
+func TestTrailersServerToClient_h1(t *testing.T)       { testTrailersServerToClient(t, h1Mode, false) }
+func TestTrailersServerToClient_h2(t *testing.T)       { testTrailersServerToClient(t, h2Mode, false) }
+func TestTrailersServerToClient_Flush_h1(t *testing.T) { testTrailersServerToClient(t, h1Mode, true) }
+func TestTrailersServerToClient_Flush_h2(t *testing.T) { testTrailersServerToClient(t, h2Mode, true) }
+
+func testTrailersServerToClient(t *testing.T, h2, flush bool) {
+	defer afterTest(t)
+	const body = "Some body"
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Trailer", "Server-Trailer-A, Server-Trailer-B")
+		w.Header().Add("Trailer", "Server-Trailer-C")
+
+		io.WriteString(w, body)
+		if flush {
+			w.(Flusher).Flush()
+		}
+
+		// How handlers set Trailers: declare it ahead of time
+		// with the Trailer header, and then mutate the
+		// Header() of those values later, after the response
+		// has been written (we wrote to w above).
+		w.Header().Set("Server-Trailer-A", "valuea")
+		w.Header().Set("Server-Trailer-C", "valuec") // skipping B
+		w.Header().Set("Server-Trailer-NotDeclared", "should be omitted")
+	}))
+	defer cst.close()
+
+	res, err := cst.c.Get(cst.ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	wantHeader := Header{
+		"Content-Type": {"text/plain; charset=utf-8"},
+	}
+	wantLen := -1
+	if h2 && !flush {
+		// In HTTP/1.1, any use of trailers forces HTTP/1.1
+		// chunking and a flush at the first write. That's
+		// unnecessary with HTTP/2's framing, so the server
+		// is able to calculate the length while still sending
+		// trailers afterwards.
+		wantLen = len(body)
+		wantHeader["Content-Length"] = []string{fmt.Sprint(wantLen)}
+	}
+	if res.ContentLength != int64(wantLen) {
+		t.Errorf("ContentLength = %v; want %v", res.ContentLength, wantLen)
+	}
+
+	delete(res.Header, "Date") // irrelevant for test
+	if !reflect.DeepEqual(res.Header, wantHeader) {
+		t.Errorf("Header = %v; want %v", res.Header, wantHeader)
+	}
+
+	if got, want := res.Trailer, (Header{
+		"Server-Trailer-A": nil,
+		"Server-Trailer-B": nil,
+		"Server-Trailer-C": nil,
+	}); !reflect.DeepEqual(got, want) {
+		t.Errorf("Trailer before body read = %v; want %v", got, want)
+	}
+
+	if err := wantBody(res, nil, body); err != nil {
+		t.Fatal(err)
+	}
+
+	if got, want := res.Trailer, (Header{
+		"Server-Trailer-A": {"valuea"},
+		"Server-Trailer-B": nil,
+		"Server-Trailer-C": {"valuec"},
+	}); !reflect.DeepEqual(got, want) {
+		t.Errorf("Trailer after body read = %v; want %v", got, want)
+	}
+}
+
+// Don't allow a Body.Read after Body.Close. Issue 13648.
+func TestResponseBodyReadAfterClose_h1(t *testing.T) { testResponseBodyReadAfterClose(t, h1Mode) }
+func TestResponseBodyReadAfterClose_h2(t *testing.T) { testResponseBodyReadAfterClose(t, h2Mode) }
+
+func testResponseBodyReadAfterClose(t *testing.T, h2 bool) {
+	defer afterTest(t)
+	const body = "Some body"
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
+		io.WriteString(w, body)
+	}))
+	defer cst.close()
+	res, err := cst.c.Get(cst.ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	res.Body.Close()
+	data, err := ioutil.ReadAll(res.Body)
+	if len(data) != 0 || err == nil {
+		t.Fatalf("ReadAll returned %q, %v; want error", data, err)
+	}
+}
+
+func TestConcurrentReadWriteReqBody_h1(t *testing.T) { testConcurrentReadWriteReqBody(t, h1Mode) }
+func TestConcurrentReadWriteReqBody_h2(t *testing.T) { testConcurrentReadWriteReqBody(t, h2Mode) }
+func testConcurrentReadWriteReqBody(t *testing.T, h2 bool) {
+	defer afterTest(t)
+	const reqBody = "some request body"
+	const resBody = "some response body"
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
+		var wg sync.WaitGroup
+		wg.Add(2)
+		didRead := make(chan bool, 1)
+		// Read in one goroutine.
+		go func() {
+			defer wg.Done()
+			data, err := ioutil.ReadAll(r.Body)
+			if string(data) != reqBody {
+				t.Errorf("Handler read %q; want %q", data, reqBody)
+			}
+			if err != nil {
+				t.Errorf("Handler Read: %v", err)
+			}
+			didRead <- true
+		}()
+		// Write in another goroutine.
+		go func() {
+			defer wg.Done()
+			if !h2 {
+				// our HTTP/1 implementation intentionally
+				// doesn't permit writes during read (mostly
+				// due to it being undefined); if that is ever
+				// relaxed, change this.
+				<-didRead
+			}
+			io.WriteString(w, resBody)
+		}()
+		wg.Wait()
+	}))
+	defer cst.close()
+	req, _ := NewRequest("POST", cst.ts.URL, strings.NewReader(reqBody))
+	req.Header.Add("Expect", "100-continue") // just to complicate things
+	res, err := cst.c.Do(req)
+	if err != nil {
+		t.Fatal(err)
+	}
+	data, err := ioutil.ReadAll(res.Body)
+	defer res.Body.Close()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if string(data) != resBody {
+		t.Errorf("read %q; want %q", data, resBody)
+	}
+}
+
+func TestConnectRequest_h1(t *testing.T) { testConnectRequest(t, h1Mode) }
+func TestConnectRequest_h2(t *testing.T) { testConnectRequest(t, h2Mode) }
+func testConnectRequest(t *testing.T, h2 bool) {
+	defer afterTest(t)
+	gotc := make(chan *Request, 1)
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
+		gotc <- r
+	}))
+	defer cst.close()
+
+	u, err := url.Parse(cst.ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	tests := []struct {
+		req  *Request
+		want string
+	}{
+		{
+			req: &Request{
+				Method: "CONNECT",
+				Header: Header{},
+				URL:    u,
+			},
+			want: u.Host,
+		},
+		{
+			req: &Request{
+				Method: "CONNECT",
+				Header: Header{},
+				URL:    u,
+				Host:   "example.com:123",
+			},
+			want: "example.com:123",
+		},
+	}
+
+	for i, tt := range tests {
+		res, err := cst.c.Do(tt.req)
+		if err != nil {
+			t.Errorf("%d. RoundTrip = %v", i, err)
+			continue
+		}
+		res.Body.Close()
+		req := <-gotc
+		if req.Method != "CONNECT" {
+			t.Errorf("method = %q; want CONNECT", req.Method)
+		}
+		if req.Host != tt.want {
+			t.Errorf("Host = %q; want %q", req.Host, tt.want)
+		}
+		if req.URL.Host != tt.want {
+			t.Errorf("URL.Host = %q; want %q", req.URL.Host, tt.want)
+		}
+	}
+}
+
+func TestTransportUserAgent_h1(t *testing.T) { testTransportUserAgent(t, h1Mode) }
+func TestTransportUserAgent_h2(t *testing.T) { testTransportUserAgent(t, h2Mode) }
+func testTransportUserAgent(t *testing.T, h2 bool) {
+	defer afterTest(t)
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
+		fmt.Fprintf(w, "%q", r.Header["User-Agent"])
+	}))
+	defer cst.close()
+
+	either := func(a, b string) string {
+		if h2 {
+			return b
+		}
+		return a
+	}
+
+	tests := []struct {
+		setup func(*Request)
+		want  string
+	}{
+		{
+			func(r *Request) {},
+			either(`["Go-http-client/1.1"]`, `["Go-http-client/2.0"]`),
+		},
+		{
+			func(r *Request) { r.Header.Set("User-Agent", "foo/1.2.3") },
+			`["foo/1.2.3"]`,
+		},
+		{
+			func(r *Request) { r.Header["User-Agent"] = []string{"single", "or", "multiple"} },
+			`["single"]`,
+		},
+		{
+			func(r *Request) { r.Header.Set("User-Agent", "") },
+			`[]`,
+		},
+		{
+			func(r *Request) { r.Header["User-Agent"] = nil },
+			`[]`,
+		},
+	}
+	for i, tt := range tests {
+		req, _ := NewRequest("GET", cst.ts.URL, nil)
+		tt.setup(req)
+		res, err := cst.c.Do(req)
+		if err != nil {
+			t.Errorf("%d. RoundTrip = %v", i, err)
+			continue
+		}
+		slurp, err := ioutil.ReadAll(res.Body)
+		res.Body.Close()
+		if err != nil {
+			t.Errorf("%d. read body = %v", i, err)
+			continue
+		}
+		if string(slurp) != tt.want {
+			t.Errorf("%d. body mismatch.\n got: %s\nwant: %s\n", i, slurp, tt.want)
+		}
+	}
+}
+
+func TestStarRequestFoo_h1(t *testing.T)     { testStarRequest(t, "FOO", h1Mode) }
+func TestStarRequestFoo_h2(t *testing.T)     { testStarRequest(t, "FOO", h2Mode) }
+func TestStarRequestOptions_h1(t *testing.T) { testStarRequest(t, "OPTIONS", h1Mode) }
+func TestStarRequestOptions_h2(t *testing.T) { testStarRequest(t, "OPTIONS", h2Mode) }
+func testStarRequest(t *testing.T, method string, h2 bool) {
+	defer afterTest(t)
+	gotc := make(chan *Request, 1)
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("foo", "bar")
+		gotc <- r
+		w.(Flusher).Flush()
+	}))
+	defer cst.close()
+
+	u, err := url.Parse(cst.ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	u.Path = "*"
+
+	req := &Request{
+		Method: method,
+		Header: Header{},
+		URL:    u,
+	}
+
+	res, err := cst.c.Do(req)
+	if err != nil {
+		t.Fatalf("RoundTrip = %v", err)
+	}
+	res.Body.Close()
+
+	wantFoo := "bar"
+	wantLen := int64(-1)
+	if method == "OPTIONS" {
+		wantFoo = ""
+		wantLen = 0
+	}
+	if res.StatusCode != 200 {
+		t.Errorf("status code = %v; want %d", res.Status, 200)
+	}
+	if res.ContentLength != wantLen {
+		t.Errorf("content length = %v; want %d", res.ContentLength, wantLen)
+	}
+	if got := res.Header.Get("foo"); got != wantFoo {
+		t.Errorf("response \"foo\" header = %q; want %q", got, wantFoo)
+	}
+	select {
+	case req = <-gotc:
+	default:
+		req = nil
+	}
+	if req == nil {
+		if method != "OPTIONS" {
+			t.Fatalf("handler never got request")
+		}
+		return
+	}
+	if req.Method != method {
+		t.Errorf("method = %q; want %q", req.Method, method)
+	}
+	if req.URL.Path != "*" {
+		t.Errorf("URL.Path = %q; want *", req.URL.Path)
+	}
+	if req.RequestURI != "*" {
+		t.Errorf("RequestURI = %q; want *", req.RequestURI)
+	}
+}
+
+// Issue 13957
+func TestTransportDiscardsUnneededConns(t *testing.T) {
+	defer afterTest(t)
+	cst := newClientServerTest(t, h2Mode, HandlerFunc(func(w ResponseWriter, r *Request) {
+		fmt.Fprintf(w, "Hello, %v", r.RemoteAddr)
+	}))
+	defer cst.close()
+
+	var numOpen, numClose int32 // atomic
+
+	tlsConfig := &tls.Config{InsecureSkipVerify: true}
+	tr := &Transport{
+		TLSClientConfig: tlsConfig,
+		DialTLS: func(_, addr string) (net.Conn, error) {
+			time.Sleep(10 * time.Millisecond)
+			rc, err := net.Dial("tcp", addr)
+			if err != nil {
+				return nil, err
+			}
+			atomic.AddInt32(&numOpen, 1)
+			c := noteCloseConn{rc, func() { atomic.AddInt32(&numClose, 1) }}
+			return tls.Client(c, tlsConfig), nil
+		},
+	}
+	if err := ExportHttp2ConfigureTransport(tr); err != nil {
+		t.Fatal(err)
+	}
+	defer tr.CloseIdleConnections()
+
+	c := &Client{Transport: tr}
+
+	const N = 10
+	gotBody := make(chan string, N)
+	var wg sync.WaitGroup
+	for i := 0; i < N; i++ {
+		wg.Add(1)
+		go func() {
+			defer wg.Done()
+			resp, err := c.Get(cst.ts.URL)
+			if err != nil {
+				t.Errorf("Get: %v", err)
+				return
+			}
+			defer resp.Body.Close()
+			slurp, err := ioutil.ReadAll(resp.Body)
+			if err != nil {
+				t.Error(err)
+			}
+			gotBody <- string(slurp)
+		}()
+	}
+	wg.Wait()
+	close(gotBody)
+
+	var last string
+	for got := range gotBody {
+		if last == "" {
+			last = got
+			continue
+		}
+		if got != last {
+			t.Errorf("Response body changed: %q -> %q", last, got)
+		}
+	}
+
+	var open, close int32
+	for i := 0; i < 150; i++ {
+		open, close = atomic.LoadInt32(&numOpen), atomic.LoadInt32(&numClose)
+		if open < 1 {
+			t.Fatalf("open = %d; want at least", open)
+		}
+		if close == open-1 {
+			// Success
+			return
+		}
+		time.Sleep(10 * time.Millisecond)
+	}
+	t.Errorf("%d connections opened, %d closed; want %d to close", open, close, open-1)
+}
+
+// tests that Transport doesn't retain a pointer to the provided request.
+func TestTransportGCRequest_Body_h1(t *testing.T)   { testTransportGCRequest(t, h1Mode, true) }
+func TestTransportGCRequest_Body_h2(t *testing.T)   { testTransportGCRequest(t, h2Mode, true) }
+func TestTransportGCRequest_NoBody_h1(t *testing.T) { testTransportGCRequest(t, h1Mode, false) }
+func TestTransportGCRequest_NoBody_h2(t *testing.T) { testTransportGCRequest(t, h2Mode, false) }
+func testTransportGCRequest(t *testing.T, h2, body bool) {
+	defer afterTest(t)
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
+		ioutil.ReadAll(r.Body)
+		if body {
+			io.WriteString(w, "Hello.")
+		}
+	}))
+	defer cst.close()
+
+	didGC := make(chan struct{})
+	(func() {
+		body := strings.NewReader("some body")
+		req, _ := NewRequest("POST", cst.ts.URL, body)
+		runtime.SetFinalizer(req, func(*Request) { close(didGC) })
+		res, err := cst.c.Do(req)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if _, err := ioutil.ReadAll(res.Body); err != nil {
+			t.Fatal(err)
+		}
+		if err := res.Body.Close(); err != nil {
+			t.Fatal(err)
+		}
+	})()
+	timeout := time.NewTimer(5 * time.Second)
+	defer timeout.Stop()
+	for {
+		select {
+		case <-didGC:
+			return
+		case <-time.After(100 * time.Millisecond):
+			runtime.GC()
+		case <-timeout.C:
+			t.Fatal("never saw GC of request")
+		}
+	}
+}
+
+type noteCloseConn struct {
+	net.Conn
+	closeFunc func()
+}
+
+func (x noteCloseConn) Close() error {
+	x.closeFunc()
+	return x.Conn.Close()
+}
diff --git a/src/net/http/doc.go b/src/net/http/doc.go
index b1216e8..4ec8272 100644
--- a/src/net/http/doc.go
+++ b/src/net/http/doc.go
@@ -76,5 +76,20 @@ custom Server:
 		MaxHeaderBytes: 1 << 20,
 	}
 	log.Fatal(s.ListenAndServe())
+
+The http package has transparent support for the HTTP/2 protocol when
+using HTTPS. Programs that must disable HTTP/2 can do so by setting
+Transport.TLSNextProto (for clients) or Server.TLSNextProto (for
+servers) to a non-nil, empty map. Alternatively, the following GODEBUG
+environment variables are currently supported:
+
+	GODEBUG=http2client=0  # disable HTTP/2 client support
+	GODEBUG=http2server=0  # disable HTTP/2 server support
+	GODEBUG=http2debug=1   # enable verbose HTTP/2 debug logs
+	GODEBUG=http2debug=2   # ... even more verbose, with frame dumps
+
+The GODEBUG variables are not covered by Go's API compatibility promise.
+HTTP/2 support was added in Go 1.6. Please report any issues instead of
+disabling HTTP/2 support: https://golang.org/s/http2bug
 */
 package http
diff --git a/src/net/http/export_test.go b/src/net/http/export_test.go
index 0457be5..52bccbd 100644
--- a/src/net/http/export_test.go
+++ b/src/net/http/export_test.go
@@ -9,11 +9,24 @@ package http
 
 import (
 	"net"
-	"net/url"
 	"sync"
 	"time"
 )
 
+var (
+	DefaultUserAgent              = defaultUserAgent
+	NewLoggingConn                = newLoggingConn
+	ExportAppendTime              = appendTime
+	ExportRefererForURL           = refererForURL
+	ExportServerNewConn           = (*Server).newConn
+	ExportCloseWriteAndWait       = (*conn).closeWriteAndWait
+	ExportErrRequestCanceled      = errRequestCanceled
+	ExportErrRequestCanceledConn  = errRequestCanceledConn
+	ExportServeFile               = serveFile
+	ExportHttp2ConfigureTransport = http2ConfigureTransport
+	ExportHttp2ConfigureServer    = http2ConfigureServer
+)
+
 func init() {
 	// We only want to pay for this cost during testing.
 	// When not under test, these values are always nil
@@ -21,11 +34,42 @@ func init() {
 	testHookMu = new(sync.Mutex)
 }
 
-func NewLoggingConn(baseName string, c net.Conn) net.Conn {
-	return newLoggingConn(baseName, c)
+var (
+	SetEnterRoundTripHook  = hookSetter(&testHookEnterRoundTrip)
+	SetTestHookWaitResLoop = hookSetter(&testHookWaitResLoop)
+	SetRoundTripRetried    = hookSetter(&testHookRoundTripRetried)
+)
+
+func SetReadLoopBeforeNextReadHook(f func()) {
+	testHookMu.Lock()
+	defer testHookMu.Unlock()
+	unnilTestHook(&f)
+	testHookReadLoopBeforeNextRead = f
+}
+
+// SetPendingDialHooks sets the hooks that run before and after handling
+// pending dials.
+func SetPendingDialHooks(before, after func()) {
+	unnilTestHook(&before)
+	unnilTestHook(&after)
+	testHookPrePendingDial, testHookPostPendingDial = before, after
 }
 
-var ExportAppendTime = appendTime
+func SetTestHookServerServe(fn func(*Server, net.Listener)) { testHookServerServe = fn }
+
+func NewTestTimeoutHandler(handler Handler, ch <-chan time.Time) Handler {
+	return &timeoutHandler{
+		handler: handler,
+		timeout: func() <-chan time.Time { return ch },
+		// (no body and nil cancelTimer)
+	}
+}
+
+func ResetCachedEnvironment() {
+	httpProxyEnv.reset()
+	httpsProxyEnv.reset()
+	noProxyEnv.reset()
+}
 
 func (t *Transport) NumPendingRequestsForTesting() int {
 	t.reqMu.Lock()
@@ -78,55 +122,25 @@ func (t *Transport) RequestIdleConnChForTesting() {
 
 func (t *Transport) PutIdleTestConn() bool {
 	c, _ := net.Pipe()
-	return t.putIdleConn(&persistConn{
+	return t.tryPutIdleConn(&persistConn{
 		t:        t,
 		conn:     c,                   // dummy
 		closech:  make(chan struct{}), // so it can be closed
 		cacheKey: connectMethodKey{"", "http", "example.com"},
-	})
-}
-
-func SetInstallConnClosedHook(f func()) {
-	testHookPersistConnClosedGotRes = f
+	}) == nil
 }
 
-func SetEnterRoundTripHook(f func()) {
-	testHookEnterRoundTrip = f
-}
-
-func SetReadLoopBeforeNextReadHook(f func()) {
-	testHookMu.Lock()
-	defer testHookMu.Unlock()
-	testHookReadLoopBeforeNextRead = f
-}
-
-func NewTestTimeoutHandler(handler Handler, ch <-chan time.Time) Handler {
-	f := func() <-chan time.Time {
-		return ch
+// All test hooks must be non-nil so they can be called directly,
+// but the tests use nil to mean hook disabled.
+func unnilTestHook(f *func()) {
+	if *f == nil {
+		*f = nop
 	}
-	return &timeoutHandler{handler, f, ""}
 }
 
-func ResetCachedEnvironment() {
-	httpProxyEnv.reset()
-	httpsProxyEnv.reset()
-	noProxyEnv.reset()
-}
-
-var DefaultUserAgent = defaultUserAgent
-
-func ExportRefererForURL(lastReq, newReq *url.URL) string {
-	return refererForURL(lastReq, newReq)
-}
-
-// SetPendingDialHooks sets the hooks that run before and after handling
-// pending dials.
-func SetPendingDialHooks(before, after func()) {
-	prePendingDial, postPendingDial = before, after
+func hookSetter(dst *func()) func(func()) {
+	return func(fn func()) {
+		unnilTestHook(&fn)
+		*dst = fn
+	}
 }
-
-var ExportServerNewConn = (*Server).newConn
-
-var ExportCloseWriteAndWait = (*conn).closeWriteAndWait
-
-var ExportErrRequestCanceled = errRequestCanceled
diff --git a/src/net/http/fcgi/child.go b/src/net/http/fcgi/child.go
index da824ed..8870424 100644
--- a/src/net/http/fcgi/child.go
+++ b/src/net/http/fcgi/child.go
@@ -56,6 +56,9 @@ func (r *request) parseParams() {
 			return
 		}
 		text = text[n:]
+		if int(keyLen)+int(valLen) > len(text) {
+			return
+		}
 		key := readString(text, keyLen)
 		text = text[keyLen:]
 		val := readString(text, valLen)
diff --git a/src/net/http/fcgi/fcgi_test.go b/src/net/http/fcgi/fcgi_test.go
index de0f7f8..b6013bf 100644
--- a/src/net/http/fcgi/fcgi_test.go
+++ b/src/net/http/fcgi/fcgi_test.go
@@ -254,3 +254,27 @@ func TestChildServeCleansUp(t *testing.T) {
 		<-done
 	}
 }
+
+type rwNopCloser struct {
+	io.Reader
+	io.Writer
+}
+
+func (rwNopCloser) Close() error {
+	return nil
+}
+
+// Verifies it doesn't crash. 	Issue 11824.
+func TestMalformedParams(t *testing.T) {
+	input := []byte{
+		// beginRequest, requestId=1, contentLength=8, role=1, keepConn=1
+		1, 1, 0, 1, 0, 8, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,
+		// params, requestId=1, contentLength=10, k1Len=50, v1Len=50 (malformed, wrong length)
+		1, 4, 0, 1, 0, 10, 0, 0, 50, 50, 3, 4, 5, 6, 7, 8, 9, 10,
+		// end of params
+		1, 4, 0, 1, 0, 0, 0, 0,
+	}
+	rw := rwNopCloser{bytes.NewReader(input), ioutil.Discard}
+	c := newChild(rw, http.DefaultServeMux)
+	c.serve()
+}
diff --git a/src/net/http/fs.go b/src/net/http/fs.go
index 7572023..f61c138 100644
--- a/src/net/http/fs.go
+++ b/src/net/http/fs.go
@@ -17,6 +17,7 @@ import (
 	"os"
 	"path"
 	"path/filepath"
+	"sort"
 	"strconv"
 	"strings"
 	"time"
@@ -62,30 +63,34 @@ type FileSystem interface {
 type File interface {
 	io.Closer
 	io.Reader
+	io.Seeker
 	Readdir(count int) ([]os.FileInfo, error)
-	Seek(offset int64, whence int) (int64, error)
 	Stat() (os.FileInfo, error)
 }
 
 func dirList(w ResponseWriter, f File) {
+	dirs, err := f.Readdir(-1)
+	if err != nil {
+		// TODO: log err.Error() to the Server.ErrorLog, once it's possible
+		// for a handler to get at its Server via the ResponseWriter. See
+		// Issue 12438.
+		Error(w, "Error reading directory", StatusInternalServerError)
+		return
+	}
+	sort.Sort(byName(dirs))
+
 	w.Header().Set("Content-Type", "text/html; charset=utf-8")
 	fmt.Fprintf(w, "<pre>\n")
-	for {
-		dirs, err := f.Readdir(100)
-		if err != nil || len(dirs) == 0 {
-			break
-		}
-		for _, d := range dirs {
-			name := d.Name()
-			if d.IsDir() {
-				name += "/"
-			}
-			// name may contain '?' or '#', which must be escaped to remain
-			// part of the URL path, and not indicate the start of a query
-			// string or fragment.
-			url := url.URL{Path: name}
-			fmt.Fprintf(w, "<a href=\"%s\">%s</a>\n", url.String(), htmlReplacer.Replace(name))
+	for _, d := range dirs {
+		name := d.Name()
+		if d.IsDir() {
+			name += "/"
 		}
+		// name may contain '?' or '#', which must be escaped to remain
+		// part of the URL path, and not indicate the start of a query
+		// string or fragment.
+		url := url.URL{Path: name}
+		fmt.Fprintf(w, "<a href=\"%s\">%s</a>\n", url.String(), htmlReplacer.Replace(name))
 	}
 	fmt.Fprintf(w, "</pre>\n")
 }
@@ -364,8 +369,8 @@ func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirec
 	}
 	defer f.Close()
 
-	d, err1 := f.Stat()
-	if err1 != nil {
+	d, err := f.Stat()
+	if err != nil {
 		msg, code := toHTTPError(err)
 		Error(w, msg, code)
 		return
@@ -446,15 +451,44 @@ func localRedirect(w ResponseWriter, r *Request, newPath string) {
 // ServeFile replies to the request with the contents of the named
 // file or directory.
 //
+// If the provided file or direcory name is a relative path, it is
+// interpreted relative to the current directory and may ascend to parent
+// directories. If the provided name is constructed from user input, it
+// should be sanitized before calling ServeFile. As a precaution, ServeFile
+// will reject requests where r.URL.Path contains a ".." path element.
+//
 // As a special case, ServeFile redirects any request where r.URL.Path
 // ends in "/index.html" to the same path, without the final
 // "index.html". To avoid such redirects either modify the path or
 // use ServeContent.
 func ServeFile(w ResponseWriter, r *Request, name string) {
+	if containsDotDot(r.URL.Path) {
+		// Too many programs use r.URL.Path to construct the argument to
+		// serveFile. Reject the request under the assumption that happened
+		// here and ".." may not be wanted.
+		// Note that name might not contain "..", for example if code (still
+		// incorrectly) used filepath.Join(myDir, r.URL.Path).
+		Error(w, "invalid URL path", StatusBadRequest)
+		return
+	}
 	dir, file := filepath.Split(name)
 	serveFile(w, r, Dir(dir), file, false)
 }
 
+func containsDotDot(v string) bool {
+	if !strings.Contains(v, "..") {
+		return false
+	}
+	for _, ent := range strings.FieldsFunc(v, isSlashRune) {
+		if ent == ".." {
+			return true
+		}
+	}
+	return false
+}
+
+func isSlashRune(r rune) bool { return r == '/' || r == '\\' }
+
 type fileHandler struct {
 	root FileSystem
 }
@@ -585,3 +619,9 @@ func sumRangesSize(ranges []httpRange) (size int64) {
 	}
 	return
 }
+
+type byName []os.FileInfo
+
+func (s byName) Len() int           { return len(s) }
+func (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() }
+func (s byName) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
diff --git a/src/net/http/fs_test.go b/src/net/http/fs_test.go
index 794dabc..69d7806 100644
--- a/src/net/http/fs_test.go
+++ b/src/net/http/fs_test.go
@@ -5,6 +5,7 @@
 package http_test
 
 import (
+	"bufio"
 	"bytes"
 	"errors"
 	"fmt"
@@ -177,6 +178,36 @@ Cases:
 	}
 }
 
+func TestServeFile_DotDot(t *testing.T) {
+	tests := []struct {
+		req        string
+		wantStatus int
+	}{
+		{"/testdata/file", 200},
+		{"/../file", 400},
+		{"/..", 400},
+		{"/../", 400},
+		{"/../foo", 400},
+		{"/..\\foo", 400},
+		{"/file/a", 200},
+		{"/file/a..", 200},
+		{"/file/a/..", 400},
+		{"/file/a\\..", 400},
+	}
+	for _, tt := range tests {
+		req, err := ReadRequest(bufio.NewReader(strings.NewReader("GET " + tt.req + " HTTP/1.1\r\nHost: foo\r\n\r\n")))
+		if err != nil {
+			t.Errorf("bad request %q: %v", tt.req, err)
+			continue
+		}
+		rec := httptest.NewRecorder()
+		ServeFile(rec, req, "testdata/file")
+		if rec.Code != tt.wantStatus {
+			t.Errorf("for request %q, status = %d; want %d", tt.req, rec.Code, tt.wantStatus)
+		}
+	}
+}
+
 var fsRedirectTestData = []struct {
 	original, redirect string
 }{
@@ -283,6 +314,49 @@ func TestFileServerEscapesNames(t *testing.T) {
 	}
 }
 
+func TestFileServerSortsNames(t *testing.T) {
+	defer afterTest(t)
+	const contents = "I am a fake file"
+	dirMod := time.Unix(123, 0).UTC()
+	fileMod := time.Unix(1000000000, 0).UTC()
+	fs := fakeFS{
+		"/": &fakeFileInfo{
+			dir:     true,
+			modtime: dirMod,
+			ents: []*fakeFileInfo{
+				{
+					basename: "b",
+					modtime:  fileMod,
+					contents: contents,
+				},
+				{
+					basename: "a",
+					modtime:  fileMod,
+					contents: contents,
+				},
+			},
+		},
+	}
+
+	ts := httptest.NewServer(FileServer(&fs))
+	defer ts.Close()
+
+	res, err := Get(ts.URL)
+	if err != nil {
+		t.Fatalf("Get: %v", err)
+	}
+	defer res.Body.Close()
+
+	b, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Fatalf("read Body: %v", err)
+	}
+	s := string(b)
+	if !strings.Contains(s, "<a href=\"a\">a</a>\n<a href=\"b\">b</a>") {
+		t.Errorf("output appears to be unsorted:\n%s", s)
+	}
+}
+
 func mustRemoveAll(dir string) {
 	err := os.RemoveAll(dir)
 	if err != nil {
@@ -434,14 +508,27 @@ func TestServeFileFromCWD(t *testing.T) {
 	}
 }
 
-func TestServeFileWithContentEncoding(t *testing.T) {
+// Tests that ServeFile doesn't add a Content-Length if a Content-Encoding is
+// specified.
+func TestServeFileWithContentEncoding_h1(t *testing.T) { testServeFileWithContentEncoding(t, h1Mode) }
+func TestServeFileWithContentEncoding_h2(t *testing.T) { testServeFileWithContentEncoding(t, h2Mode) }
+func testServeFileWithContentEncoding(t *testing.T, h2 bool) {
 	defer afterTest(t)
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
 		w.Header().Set("Content-Encoding", "foo")
 		ServeFile(w, r, "testdata/file")
+
+		// Because the testdata is so small, it would fit in
+		// both the h1 and h2 Server's write buffers. For h1,
+		// sendfile is used, though, forcing a header flush at
+		// the io.Copy. http2 doesn't do a header flush so
+		// buffers all 11 bytes and then adds its own
+		// Content-Length. To prevent the Server's
+		// Content-Length and test ServeFile only, flush here.
+		w.(Flusher).Flush()
 	}))
-	defer ts.Close()
-	resp, err := Get(ts.URL)
+	defer cst.close()
+	resp, err := cst.c.Get(cst.ts.URL)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -807,6 +894,28 @@ func TestServeContent(t *testing.T) {
 	}
 }
 
+// Issue 12991
+func TestServerFileStatError(t *testing.T) {
+	rec := httptest.NewRecorder()
+	r, _ := NewRequest("GET", "http://foo/", nil)
+	redirect := false
+	name := "file.txt"
+	fs := issue12991FS{}
+	ExportServeFile(rec, r, fs, name, redirect)
+	if body := rec.Body.String(); !strings.Contains(body, "403") || !strings.Contains(body, "Forbidden") {
+		t.Errorf("wanted 403 forbidden message; got: %s", body)
+	}
+}
+
+type issue12991FS struct{}
+
+func (issue12991FS) Open(string) (File, error) { return issue12991File{}, nil }
+
+type issue12991File struct{ File }
+
+func (issue12991File) Stat() (os.FileInfo, error) { return nil, os.ErrPermission }
+func (issue12991File) Close() error               { return nil }
+
 func TestServeContentErrorMessages(t *testing.T) {
 	defer afterTest(t)
 	fs := fakeFS{
@@ -852,8 +961,16 @@ func TestLinuxSendfile(t *testing.T) {
 	}
 	defer ln.Close()
 
+	syscalls := "sendfile,sendfile64"
+	switch runtime.GOARCH {
+	case "mips64", "mips64le":
+		// mips64 strace doesn't support sendfile64 and will error out
+		// if we specify that with `-e trace='.
+		syscalls = "sendfile"
+	}
+
 	var buf bytes.Buffer
-	child := exec.Command("strace", "-f", "-q", "-e", "trace=sendfile,sendfile64", os.Args[0], "-test.run=TestLinuxSendfileChild")
+	child := exec.Command("strace", "-f", "-q", "-e", "trace="+syscalls, os.Args[0], "-test.run=TestLinuxSendfileChild")
 	child.ExtraFiles = append(child.ExtraFiles, lnf)
 	child.Env = append([]string{"GO_WANT_HELPER_PROCESS=1"}, os.Environ()...)
 	child.Stdout = &buf
@@ -873,7 +990,7 @@ func TestLinuxSendfile(t *testing.T) {
 	res.Body.Close()
 
 	// Force child to exit cleanly.
-	Get(fmt.Sprintf("http://%s/quit", ln.Addr()))
+	Post(fmt.Sprintf("http://%s/quit", ln.Addr()), "", nil)
 	child.Wait()
 
 	rx := regexp.MustCompile(`sendfile(64)?\(\d+,\s*\d+,\s*NULL,\s*\d+\)\s*=\s*\d+\s*\n`)
diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go
new file mode 100644
index 0000000..4e19b3e
--- /dev/null
+++ b/src/net/http/h2_bundle.go
@@ -0,0 +1,6671 @@
+// Code generated by golang.org/x/tools/cmd/bundle.
+//go:generate bundle -o h2_bundle.go -prefix http2 -import golang.org/x/net/http2/hpack=internal/golang.org/x/net/http2/hpack golang.org/x/net/http2
+
+// Package http2 implements the HTTP/2 protocol.
+//
+// This package is low-level and intended to be used directly by very
+// few people. Most users will use it indirectly through the automatic
+// use by the net/http package (from Go 1.6 and later).
+// For use in earlier Go versions see ConfigureServer. (Transport support
+// requires Go 1.6 or later)
+//
+// See https://http2.github.io/ for more information on HTTP/2.
+//
+// See https://http2.golang.org/ for a test server running this code.
+//
+
+package http
+
+import (
+	"bufio"
+	"bytes"
+	"compress/gzip"
+	"crypto/tls"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"internal/golang.org/x/net/http2/hpack"
+	"io"
+	"io/ioutil"
+	"log"
+	"net"
+	"net/textproto"
+	"net/url"
+	"os"
+	"reflect"
+	"runtime"
+	"sort"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+)
+
+// ClientConnPool manages a pool of HTTP/2 client connections.
+type http2ClientConnPool interface {
+	GetClientConn(req *Request, addr string) (*http2ClientConn, error)
+	MarkDead(*http2ClientConn)
+}
+
+// TODO: use singleflight for dialing and addConnCalls?
+type http2clientConnPool struct {
+	t *http2Transport
+
+	mu sync.Mutex // TODO: maybe switch to RWMutex
+	// TODO: add support for sharing conns based on cert names
+	// (e.g. share conn for googleapis.com and appspot.com)
+	conns        map[string][]*http2ClientConn // key is host:port
+	dialing      map[string]*http2dialCall     // currently in-flight dials
+	keys         map[*http2ClientConn][]string
+	addConnCalls map[string]*http2addConnCall // in-flight addConnIfNeede calls
+}
+
+func (p *http2clientConnPool) GetClientConn(req *Request, addr string) (*http2ClientConn, error) {
+	return p.getClientConn(req, addr, http2dialOnMiss)
+}
+
+const (
+	http2dialOnMiss   = true
+	http2noDialOnMiss = false
+)
+
+func (p *http2clientConnPool) getClientConn(_ *Request, addr string, dialOnMiss bool) (*http2ClientConn, error) {
+	p.mu.Lock()
+	for _, cc := range p.conns[addr] {
+		if cc.CanTakeNewRequest() {
+			p.mu.Unlock()
+			return cc, nil
+		}
+	}
+	if !dialOnMiss {
+		p.mu.Unlock()
+		return nil, http2ErrNoCachedConn
+	}
+	call := p.getStartDialLocked(addr)
+	p.mu.Unlock()
+	<-call.done
+	return call.res, call.err
+}
+
+// dialCall is an in-flight Transport dial call to a host.
+type http2dialCall struct {
+	p    *http2clientConnPool
+	done chan struct{}    // closed when done
+	res  *http2ClientConn // valid after done is closed
+	err  error            // valid after done is closed
+}
+
+// requires p.mu is held.
+func (p *http2clientConnPool) getStartDialLocked(addr string) *http2dialCall {
+	if call, ok := p.dialing[addr]; ok {
+
+		return call
+	}
+	call := &http2dialCall{p: p, done: make(chan struct{})}
+	if p.dialing == nil {
+		p.dialing = make(map[string]*http2dialCall)
+	}
+	p.dialing[addr] = call
+	go call.dial(addr)
+	return call
+}
+
+// run in its own goroutine.
+func (c *http2dialCall) dial(addr string) {
+	c.res, c.err = c.p.t.dialClientConn(addr)
+	close(c.done)
+
+	c.p.mu.Lock()
+	delete(c.p.dialing, addr)
+	if c.err == nil {
+		c.p.addConnLocked(addr, c.res)
+	}
+	c.p.mu.Unlock()
+}
+
+// addConnIfNeeded makes a NewClientConn out of c if a connection for key doesn't
+// already exist. It coalesces concurrent calls with the same key.
+// This is used by the http1 Transport code when it creates a new connection. Because
+// the http1 Transport doesn't de-dup TCP dials to outbound hosts (because it doesn't know
+// the protocol), it can get into a situation where it has multiple TLS connections.
+// This code decides which ones live or die.
+// The return value used is whether c was used.
+// c is never closed.
+func (p *http2clientConnPool) addConnIfNeeded(key string, t *http2Transport, c *tls.Conn) (used bool, err error) {
+	p.mu.Lock()
+	for _, cc := range p.conns[key] {
+		if cc.CanTakeNewRequest() {
+			p.mu.Unlock()
+			return false, nil
+		}
+	}
+	call, dup := p.addConnCalls[key]
+	if !dup {
+		if p.addConnCalls == nil {
+			p.addConnCalls = make(map[string]*http2addConnCall)
+		}
+		call = &http2addConnCall{
+			p:    p,
+			done: make(chan struct{}),
+		}
+		p.addConnCalls[key] = call
+		go call.run(t, key, c)
+	}
+	p.mu.Unlock()
+
+	<-call.done
+	if call.err != nil {
+		return false, call.err
+	}
+	return !dup, nil
+}
+
+type http2addConnCall struct {
+	p    *http2clientConnPool
+	done chan struct{} // closed when done
+	err  error
+}
+
+func (c *http2addConnCall) run(t *http2Transport, key string, tc *tls.Conn) {
+	cc, err := t.NewClientConn(tc)
+
+	p := c.p
+	p.mu.Lock()
+	if err != nil {
+		c.err = err
+	} else {
+		p.addConnLocked(key, cc)
+	}
+	delete(p.addConnCalls, key)
+	p.mu.Unlock()
+	close(c.done)
+}
+
+func (p *http2clientConnPool) addConn(key string, cc *http2ClientConn) {
+	p.mu.Lock()
+	p.addConnLocked(key, cc)
+	p.mu.Unlock()
+}
+
+// p.mu must be held
+func (p *http2clientConnPool) addConnLocked(key string, cc *http2ClientConn) {
+	for _, v := range p.conns[key] {
+		if v == cc {
+			return
+		}
+	}
+	if p.conns == nil {
+		p.conns = make(map[string][]*http2ClientConn)
+	}
+	if p.keys == nil {
+		p.keys = make(map[*http2ClientConn][]string)
+	}
+	p.conns[key] = append(p.conns[key], cc)
+	p.keys[cc] = append(p.keys[cc], key)
+}
+
+func (p *http2clientConnPool) MarkDead(cc *http2ClientConn) {
+	p.mu.Lock()
+	defer p.mu.Unlock()
+	for _, key := range p.keys[cc] {
+		vv, ok := p.conns[key]
+		if !ok {
+			continue
+		}
+		newList := http2filterOutClientConn(vv, cc)
+		if len(newList) > 0 {
+			p.conns[key] = newList
+		} else {
+			delete(p.conns, key)
+		}
+	}
+	delete(p.keys, cc)
+}
+
+func (p *http2clientConnPool) closeIdleConnections() {
+	p.mu.Lock()
+	defer p.mu.Unlock()
+
+	for _, vv := range p.conns {
+		for _, cc := range vv {
+			cc.closeIfIdle()
+		}
+	}
+}
+
+func http2filterOutClientConn(in []*http2ClientConn, exclude *http2ClientConn) []*http2ClientConn {
+	out := in[:0]
+	for _, v := range in {
+		if v != exclude {
+			out = append(out, v)
+		}
+	}
+
+	if len(in) != len(out) {
+		in[len(in)-1] = nil
+	}
+	return out
+}
+
+func http2configureTransport(t1 *Transport) (*http2Transport, error) {
+	connPool := new(http2clientConnPool)
+	t2 := &http2Transport{
+		ConnPool: http2noDialClientConnPool{connPool},
+		t1:       t1,
+	}
+	connPool.t = t2
+	if err := http2registerHTTPSProtocol(t1, http2noDialH2RoundTripper{t2}); err != nil {
+		return nil, err
+	}
+	if t1.TLSClientConfig == nil {
+		t1.TLSClientConfig = new(tls.Config)
+	}
+	if !http2strSliceContains(t1.TLSClientConfig.NextProtos, "h2") {
+		t1.TLSClientConfig.NextProtos = append([]string{"h2"}, t1.TLSClientConfig.NextProtos...)
+	}
+	if !http2strSliceContains(t1.TLSClientConfig.NextProtos, "http/1.1") {
+		t1.TLSClientConfig.NextProtos = append(t1.TLSClientConfig.NextProtos, "http/1.1")
+	}
+	upgradeFn := func(authority string, c *tls.Conn) RoundTripper {
+		addr := http2authorityAddr(authority)
+		if used, err := connPool.addConnIfNeeded(addr, t2, c); err != nil {
+			go c.Close()
+			return http2erringRoundTripper{err}
+		} else if !used {
+
+			go c.Close()
+		}
+		return t2
+	}
+	if m := t1.TLSNextProto; len(m) == 0 {
+		t1.TLSNextProto = map[string]func(string, *tls.Conn) RoundTripper{
+			"h2": upgradeFn,
+		}
+	} else {
+		m["h2"] = upgradeFn
+	}
+	return t2, nil
+}
+
+// registerHTTPSProtocol calls Transport.RegisterProtocol but
+// convering panics into errors.
+func http2registerHTTPSProtocol(t *Transport, rt RoundTripper) (err error) {
+	defer func() {
+		if e := recover(); e != nil {
+			err = fmt.Errorf("%v", e)
+		}
+	}()
+	t.RegisterProtocol("https", rt)
+	return nil
+}
+
+// noDialClientConnPool is an implementation of http2.ClientConnPool
+// which never dials.  We let the HTTP/1.1 client dial and use its TLS
+// connection instead.
+type http2noDialClientConnPool struct{ *http2clientConnPool }
+
+func (p http2noDialClientConnPool) GetClientConn(req *Request, addr string) (*http2ClientConn, error) {
+	return p.getClientConn(req, addr, http2noDialOnMiss)
+}
+
+// noDialH2RoundTripper is a RoundTripper which only tries to complete the request
+// if there's already has a cached connection to the host.
+type http2noDialH2RoundTripper struct{ t *http2Transport }
+
+func (rt http2noDialH2RoundTripper) RoundTrip(req *Request) (*Response, error) {
+	res, err := rt.t.RoundTrip(req)
+	if err == http2ErrNoCachedConn {
+		return nil, ErrSkipAltProtocol
+	}
+	return res, err
+}
+
+// An ErrCode is an unsigned 32-bit error code as defined in the HTTP/2 spec.
+type http2ErrCode uint32
+
+const (
+	http2ErrCodeNo                 http2ErrCode = 0x0
+	http2ErrCodeProtocol           http2ErrCode = 0x1
+	http2ErrCodeInternal           http2ErrCode = 0x2
+	http2ErrCodeFlowControl        http2ErrCode = 0x3
+	http2ErrCodeSettingsTimeout    http2ErrCode = 0x4
+	http2ErrCodeStreamClosed       http2ErrCode = 0x5
+	http2ErrCodeFrameSize          http2ErrCode = 0x6
+	http2ErrCodeRefusedStream      http2ErrCode = 0x7
+	http2ErrCodeCancel             http2ErrCode = 0x8
+	http2ErrCodeCompression        http2ErrCode = 0x9
+	http2ErrCodeConnect            http2ErrCode = 0xa
+	http2ErrCodeEnhanceYourCalm    http2ErrCode = 0xb
+	http2ErrCodeInadequateSecurity http2ErrCode = 0xc
+	http2ErrCodeHTTP11Required     http2ErrCode = 0xd
+)
+
+var http2errCodeName = map[http2ErrCode]string{
+	http2ErrCodeNo:                 "NO_ERROR",
+	http2ErrCodeProtocol:           "PROTOCOL_ERROR",
+	http2ErrCodeInternal:           "INTERNAL_ERROR",
+	http2ErrCodeFlowControl:        "FLOW_CONTROL_ERROR",
+	http2ErrCodeSettingsTimeout:    "SETTINGS_TIMEOUT",
+	http2ErrCodeStreamClosed:       "STREAM_CLOSED",
+	http2ErrCodeFrameSize:          "FRAME_SIZE_ERROR",
+	http2ErrCodeRefusedStream:      "REFUSED_STREAM",
+	http2ErrCodeCancel:             "CANCEL",
+	http2ErrCodeCompression:        "COMPRESSION_ERROR",
+	http2ErrCodeConnect:            "CONNECT_ERROR",
+	http2ErrCodeEnhanceYourCalm:    "ENHANCE_YOUR_CALM",
+	http2ErrCodeInadequateSecurity: "INADEQUATE_SECURITY",
+	http2ErrCodeHTTP11Required:     "HTTP_1_1_REQUIRED",
+}
+
+func (e http2ErrCode) String() string {
+	if s, ok := http2errCodeName[e]; ok {
+		return s
+	}
+	return fmt.Sprintf("unknown error code 0x%x", uint32(e))
+}
+
+// ConnectionError is an error that results in the termination of the
+// entire connection.
+type http2ConnectionError http2ErrCode
+
+func (e http2ConnectionError) Error() string {
+	return fmt.Sprintf("connection error: %s", http2ErrCode(e))
+}
+
+// StreamError is an error that only affects one stream within an
+// HTTP/2 connection.
+type http2StreamError struct {
+	StreamID uint32
+	Code     http2ErrCode
+}
+
+func (e http2StreamError) Error() string {
+	return fmt.Sprintf("stream error: stream ID %d; %v", e.StreamID, e.Code)
+}
+
+// 6.9.1 The Flow Control Window
+// "If a sender receives a WINDOW_UPDATE that causes a flow control
+// window to exceed this maximum it MUST terminate either the stream
+// or the connection, as appropriate. For streams, [...]; for the
+// connection, a GOAWAY frame with a FLOW_CONTROL_ERROR code."
+type http2goAwayFlowError struct{}
+
+func (http2goAwayFlowError) Error() string { return "connection exceeded flow control window size" }
+
+// Errors of this type are only returned by the frame parser functions
+// and converted into ConnectionError(ErrCodeProtocol).
+type http2connError struct {
+	Code   http2ErrCode
+	Reason string
+}
+
+func (e http2connError) Error() string {
+	return fmt.Sprintf("http2: connection error: %v: %v", e.Code, e.Reason)
+}
+
+// fixedBuffer is an io.ReadWriter backed by a fixed size buffer.
+// It never allocates, but moves old data as new data is written.
+type http2fixedBuffer struct {
+	buf  []byte
+	r, w int
+}
+
+var (
+	http2errReadEmpty = errors.New("read from empty fixedBuffer")
+	http2errWriteFull = errors.New("write on full fixedBuffer")
+)
+
+// Read copies bytes from the buffer into p.
+// It is an error to read when no data is available.
+func (b *http2fixedBuffer) Read(p []byte) (n int, err error) {
+	if b.r == b.w {
+		return 0, http2errReadEmpty
+	}
+	n = copy(p, b.buf[b.r:b.w])
+	b.r += n
+	if b.r == b.w {
+		b.r = 0
+		b.w = 0
+	}
+	return n, nil
+}
+
+// Len returns the number of bytes of the unread portion of the buffer.
+func (b *http2fixedBuffer) Len() int {
+	return b.w - b.r
+}
+
+// Write copies bytes from p into the buffer.
+// It is an error to write more data than the buffer can hold.
+func (b *http2fixedBuffer) Write(p []byte) (n int, err error) {
+
+	if b.r > 0 && len(p) > len(b.buf)-b.w {
+		copy(b.buf, b.buf[b.r:b.w])
+		b.w -= b.r
+		b.r = 0
+	}
+
+	n = copy(b.buf[b.w:], p)
+	b.w += n
+	if n < len(p) {
+		err = http2errWriteFull
+	}
+	return n, err
+}
+
+// flow is the flow control window's size.
+type http2flow struct {
+	// n is the number of DATA bytes we're allowed to send.
+	// A flow is kept both on a conn and a per-stream.
+	n int32
+
+	// conn points to the shared connection-level flow that is
+	// shared by all streams on that conn. It is nil for the flow
+	// that's on the conn directly.
+	conn *http2flow
+}
+
+func (f *http2flow) setConnFlow(cf *http2flow) { f.conn = cf }
+
+func (f *http2flow) available() int32 {
+	n := f.n
+	if f.conn != nil && f.conn.n < n {
+		n = f.conn.n
+	}
+	return n
+}
+
+func (f *http2flow) take(n int32) {
+	if n > f.available() {
+		panic("internal error: took too much")
+	}
+	f.n -= n
+	if f.conn != nil {
+		f.conn.n -= n
+	}
+}
+
+// add adds n bytes (positive or negative) to the flow control window.
+// It returns false if the sum would exceed 2^31-1.
+func (f *http2flow) add(n int32) bool {
+	remain := (1<<31 - 1) - f.n
+	if n > remain {
+		return false
+	}
+	f.n += n
+	return true
+}
+
+const http2frameHeaderLen = 9
+
+var http2padZeros = make([]byte, 255) // zeros for padding
+
+// A FrameType is a registered frame type as defined in
+// http://http2.github.io/http2-spec/#rfc.section.11.2
+type http2FrameType uint8
+
+const (
+	http2FrameData         http2FrameType = 0x0
+	http2FrameHeaders      http2FrameType = 0x1
+	http2FramePriority     http2FrameType = 0x2
+	http2FrameRSTStream    http2FrameType = 0x3
+	http2FrameSettings     http2FrameType = 0x4
+	http2FramePushPromise  http2FrameType = 0x5
+	http2FramePing         http2FrameType = 0x6
+	http2FrameGoAway       http2FrameType = 0x7
+	http2FrameWindowUpdate http2FrameType = 0x8
+	http2FrameContinuation http2FrameType = 0x9
+)
+
+var http2frameName = map[http2FrameType]string{
+	http2FrameData:         "DATA",
+	http2FrameHeaders:      "HEADERS",
+	http2FramePriority:     "PRIORITY",
+	http2FrameRSTStream:    "RST_STREAM",
+	http2FrameSettings:     "SETTINGS",
+	http2FramePushPromise:  "PUSH_PROMISE",
+	http2FramePing:         "PING",
+	http2FrameGoAway:       "GOAWAY",
+	http2FrameWindowUpdate: "WINDOW_UPDATE",
+	http2FrameContinuation: "CONTINUATION",
+}
+
+func (t http2FrameType) String() string {
+	if s, ok := http2frameName[t]; ok {
+		return s
+	}
+	return fmt.Sprintf("UNKNOWN_FRAME_TYPE_%d", uint8(t))
+}
+
+// Flags is a bitmask of HTTP/2 flags.
+// The meaning of flags varies depending on the frame type.
+type http2Flags uint8
+
+// Has reports whether f contains all (0 or more) flags in v.
+func (f http2Flags) Has(v http2Flags) bool {
+	return (f & v) == v
+}
+
+// Frame-specific FrameHeader flag bits.
+const (
+	// Data Frame
+	http2FlagDataEndStream http2Flags = 0x1
+	http2FlagDataPadded    http2Flags = 0x8
+
+	// Headers Frame
+	http2FlagHeadersEndStream  http2Flags = 0x1
+	http2FlagHeadersEndHeaders http2Flags = 0x4
+	http2FlagHeadersPadded     http2Flags = 0x8
+	http2FlagHeadersPriority   http2Flags = 0x20
+
+	// Settings Frame
+	http2FlagSettingsAck http2Flags = 0x1
+
+	// Ping Frame
+	http2FlagPingAck http2Flags = 0x1
+
+	// Continuation Frame
+	http2FlagContinuationEndHeaders http2Flags = 0x4
+
+	http2FlagPushPromiseEndHeaders http2Flags = 0x4
+	http2FlagPushPromisePadded     http2Flags = 0x8
+)
+
+var http2flagName = map[http2FrameType]map[http2Flags]string{
+	http2FrameData: {
+		http2FlagDataEndStream: "END_STREAM",
+		http2FlagDataPadded:    "PADDED",
+	},
+	http2FrameHeaders: {
+		http2FlagHeadersEndStream:  "END_STREAM",
+		http2FlagHeadersEndHeaders: "END_HEADERS",
+		http2FlagHeadersPadded:     "PADDED",
+		http2FlagHeadersPriority:   "PRIORITY",
+	},
+	http2FrameSettings: {
+		http2FlagSettingsAck: "ACK",
+	},
+	http2FramePing: {
+		http2FlagPingAck: "ACK",
+	},
+	http2FrameContinuation: {
+		http2FlagContinuationEndHeaders: "END_HEADERS",
+	},
+	http2FramePushPromise: {
+		http2FlagPushPromiseEndHeaders: "END_HEADERS",
+		http2FlagPushPromisePadded:     "PADDED",
+	},
+}
+
+// a frameParser parses a frame given its FrameHeader and payload
+// bytes. The length of payload will always equal fh.Length (which
+// might be 0).
+type http2frameParser func(fh http2FrameHeader, payload []byte) (http2Frame, error)
+
+var http2frameParsers = map[http2FrameType]http2frameParser{
+	http2FrameData:         http2parseDataFrame,
+	http2FrameHeaders:      http2parseHeadersFrame,
+	http2FramePriority:     http2parsePriorityFrame,
+	http2FrameRSTStream:    http2parseRSTStreamFrame,
+	http2FrameSettings:     http2parseSettingsFrame,
+	http2FramePushPromise:  http2parsePushPromise,
+	http2FramePing:         http2parsePingFrame,
+	http2FrameGoAway:       http2parseGoAwayFrame,
+	http2FrameWindowUpdate: http2parseWindowUpdateFrame,
+	http2FrameContinuation: http2parseContinuationFrame,
+}
+
+func http2typeFrameParser(t http2FrameType) http2frameParser {
+	if f := http2frameParsers[t]; f != nil {
+		return f
+	}
+	return http2parseUnknownFrame
+}
+
+// A FrameHeader is the 9 byte header of all HTTP/2 frames.
+//
+// See http://http2.github.io/http2-spec/#FrameHeader
+type http2FrameHeader struct {
+	valid bool // caller can access []byte fields in the Frame
+
+	// Type is the 1 byte frame type. There are ten standard frame
+	// types, but extension frame types may be written by WriteRawFrame
+	// and will be returned by ReadFrame (as UnknownFrame).
+	Type http2FrameType
+
+	// Flags are the 1 byte of 8 potential bit flags per frame.
+	// They are specific to the frame type.
+	Flags http2Flags
+
+	// Length is the length of the frame, not including the 9 byte header.
+	// The maximum size is one byte less than 16MB (uint24), but only
+	// frames up to 16KB are allowed without peer agreement.
+	Length uint32
+
+	// StreamID is which stream this frame is for. Certain frames
+	// are not stream-specific, in which case this field is 0.
+	StreamID uint32
+}
+
+// Header returns h. It exists so FrameHeaders can be embedded in other
+// specific frame types and implement the Frame interface.
+func (h http2FrameHeader) Header() http2FrameHeader { return h }
+
+func (h http2FrameHeader) String() string {
+	var buf bytes.Buffer
+	buf.WriteString("[FrameHeader ")
+	h.writeDebug(&buf)
+	buf.WriteByte(']')
+	return buf.String()
+}
+
+func (h http2FrameHeader) writeDebug(buf *bytes.Buffer) {
+	buf.WriteString(h.Type.String())
+	if h.Flags != 0 {
+		buf.WriteString(" flags=")
+		set := 0
+		for i := uint8(0); i < 8; i++ {
+			if h.Flags&(1<<i) == 0 {
+				continue
+			}
+			set++
+			if set > 1 {
+				buf.WriteByte('|')
+			}
+			name := http2flagName[h.Type][http2Flags(1<<i)]
+			if name != "" {
+				buf.WriteString(name)
+			} else {
+				fmt.Fprintf(buf, "0x%x", 1<<i)
+			}
+		}
+	}
+	if h.StreamID != 0 {
+		fmt.Fprintf(buf, " stream=%d", h.StreamID)
+	}
+	fmt.Fprintf(buf, " len=%d", h.Length)
+}
+
+func (h *http2FrameHeader) checkValid() {
+	if !h.valid {
+		panic("Frame accessor called on non-owned Frame")
+	}
+}
+
+func (h *http2FrameHeader) invalidate() { h.valid = false }
+
+// frame header bytes.
+// Used only by ReadFrameHeader.
+var http2fhBytes = sync.Pool{
+	New: func() interface{} {
+		buf := make([]byte, http2frameHeaderLen)
+		return &buf
+	},
+}
+
+// ReadFrameHeader reads 9 bytes from r and returns a FrameHeader.
+// Most users should use Framer.ReadFrame instead.
+func http2ReadFrameHeader(r io.Reader) (http2FrameHeader, error) {
+	bufp := http2fhBytes.Get().(*[]byte)
+	defer http2fhBytes.Put(bufp)
+	return http2readFrameHeader(*bufp, r)
+}
+
+func http2readFrameHeader(buf []byte, r io.Reader) (http2FrameHeader, error) {
+	_, err := io.ReadFull(r, buf[:http2frameHeaderLen])
+	if err != nil {
+		return http2FrameHeader{}, err
+	}
+	return http2FrameHeader{
+		Length:   (uint32(buf[0])<<16 | uint32(buf[1])<<8 | uint32(buf[2])),
+		Type:     http2FrameType(buf[3]),
+		Flags:    http2Flags(buf[4]),
+		StreamID: binary.BigEndian.Uint32(buf[5:]) & (1<<31 - 1),
+		valid:    true,
+	}, nil
+}
+
+// A Frame is the base interface implemented by all frame types.
+// Callers will generally type-assert the specific frame type:
+// *HeadersFrame, *SettingsFrame, *WindowUpdateFrame, etc.
+//
+// Frames are only valid until the next call to Framer.ReadFrame.
+type http2Frame interface {
+	Header() http2FrameHeader
+
+	// invalidate is called by Framer.ReadFrame to make this
+	// frame's buffers as being invalid, since the subsequent
+	// frame will reuse them.
+	invalidate()
+}
+
+// A Framer reads and writes Frames.
+type http2Framer struct {
+	r         io.Reader
+	lastFrame http2Frame
+	errReason string
+
+	// lastHeaderStream is non-zero if the last frame was an
+	// unfinished HEADERS/CONTINUATION.
+	lastHeaderStream uint32
+
+	maxReadSize uint32
+	headerBuf   [http2frameHeaderLen]byte
+
+	// TODO: let getReadBuf be configurable, and use a less memory-pinning
+	// allocator in server.go to minimize memory pinned for many idle conns.
+	// Will probably also need to make frame invalidation have a hook too.
+	getReadBuf func(size uint32) []byte
+	readBuf    []byte // cache for default getReadBuf
+
+	maxWriteSize uint32 // zero means unlimited; TODO: implement
+
+	w    io.Writer
+	wbuf []byte
+
+	// AllowIllegalWrites permits the Framer's Write methods to
+	// write frames that do not conform to the HTTP/2 spec. This
+	// permits using the Framer to test other HTTP/2
+	// implementations' conformance to the spec.
+	// If false, the Write methods will prefer to return an error
+	// rather than comply.
+	AllowIllegalWrites bool
+
+	// AllowIllegalReads permits the Framer's ReadFrame method
+	// to return non-compliant frames or frame orders.
+	// This is for testing and permits using the Framer to test
+	// other HTTP/2 implementations' conformance to the spec.
+	AllowIllegalReads bool
+
+	logReads bool
+
+	debugFramer    *http2Framer // only use for logging written writes
+	debugFramerBuf *bytes.Buffer
+}
+
+func (f *http2Framer) startWrite(ftype http2FrameType, flags http2Flags, streamID uint32) {
+
+	f.wbuf = append(f.wbuf[:0],
+		0,
+		0,
+		0,
+		byte(ftype),
+		byte(flags),
+		byte(streamID>>24),
+		byte(streamID>>16),
+		byte(streamID>>8),
+		byte(streamID))
+}
+
+func (f *http2Framer) endWrite() error {
+
+	length := len(f.wbuf) - http2frameHeaderLen
+	if length >= (1 << 24) {
+		return http2ErrFrameTooLarge
+	}
+	_ = append(f.wbuf[:0],
+		byte(length>>16),
+		byte(length>>8),
+		byte(length))
+	if http2logFrameWrites {
+		f.logWrite()
+	}
+
+	n, err := f.w.Write(f.wbuf)
+	if err == nil && n != len(f.wbuf) {
+		err = io.ErrShortWrite
+	}
+	return err
+}
+
+func (f *http2Framer) logWrite() {
+	if f.debugFramer == nil {
+		f.debugFramerBuf = new(bytes.Buffer)
+		f.debugFramer = http2NewFramer(nil, f.debugFramerBuf)
+		f.debugFramer.logReads = false
+
+		f.debugFramer.AllowIllegalReads = true
+	}
+	f.debugFramerBuf.Write(f.wbuf)
+	fr, err := f.debugFramer.ReadFrame()
+	if err != nil {
+		log.Printf("http2: Framer %p: failed to decode just-written frame", f)
+		return
+	}
+	log.Printf("http2: Framer %p: wrote %v", f, http2summarizeFrame(fr))
+}
+
+func (f *http2Framer) writeByte(v byte) { f.wbuf = append(f.wbuf, v) }
+
+func (f *http2Framer) writeBytes(v []byte) { f.wbuf = append(f.wbuf, v...) }
+
+func (f *http2Framer) writeUint16(v uint16) { f.wbuf = append(f.wbuf, byte(v>>8), byte(v)) }
+
+func (f *http2Framer) writeUint32(v uint32) {
+	f.wbuf = append(f.wbuf, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
+}
+
+const (
+	http2minMaxFrameSize = 1 << 14
+	http2maxFrameSize    = 1<<24 - 1
+)
+
+// NewFramer returns a Framer that writes frames to w and reads them from r.
+func http2NewFramer(w io.Writer, r io.Reader) *http2Framer {
+	fr := &http2Framer{
+		w:        w,
+		r:        r,
+		logReads: http2logFrameReads,
+	}
+	fr.getReadBuf = func(size uint32) []byte {
+		if cap(fr.readBuf) >= int(size) {
+			return fr.readBuf[:size]
+		}
+		fr.readBuf = make([]byte, size)
+		return fr.readBuf
+	}
+	fr.SetMaxReadFrameSize(http2maxFrameSize)
+	return fr
+}
+
+// SetMaxReadFrameSize sets the maximum size of a frame
+// that will be read by a subsequent call to ReadFrame.
+// It is the caller's responsibility to advertise this
+// limit with a SETTINGS frame.
+func (fr *http2Framer) SetMaxReadFrameSize(v uint32) {
+	if v > http2maxFrameSize {
+		v = http2maxFrameSize
+	}
+	fr.maxReadSize = v
+}
+
+// ErrFrameTooLarge is returned from Framer.ReadFrame when the peer
+// sends a frame that is larger than declared with SetMaxReadFrameSize.
+var http2ErrFrameTooLarge = errors.New("http2: frame too large")
+
+// terminalReadFrameError reports whether err is an unrecoverable
+// error from ReadFrame and no other frames should be read.
+func http2terminalReadFrameError(err error) bool {
+	if _, ok := err.(http2StreamError); ok {
+		return false
+	}
+	return err != nil
+}
+
+// ReadFrame reads a single frame. The returned Frame is only valid
+// until the next call to ReadFrame.
+//
+// If the frame is larger than previously set with SetMaxReadFrameSize, the
+// returned error is ErrFrameTooLarge. Other errors may be of type
+// ConnectionError, StreamError, or anything else from from the underlying
+// reader.
+func (fr *http2Framer) ReadFrame() (http2Frame, error) {
+	if fr.lastFrame != nil {
+		fr.lastFrame.invalidate()
+	}
+	fh, err := http2readFrameHeader(fr.headerBuf[:], fr.r)
+	if err != nil {
+		return nil, err
+	}
+	if fh.Length > fr.maxReadSize {
+		return nil, http2ErrFrameTooLarge
+	}
+	payload := fr.getReadBuf(fh.Length)
+	if _, err := io.ReadFull(fr.r, payload); err != nil {
+		return nil, err
+	}
+	f, err := http2typeFrameParser(fh.Type)(fh, payload)
+	if err != nil {
+		if ce, ok := err.(http2connError); ok {
+			return nil, fr.connError(ce.Code, ce.Reason)
+		}
+		return nil, err
+	}
+	if err := fr.checkFrameOrder(f); err != nil {
+		return nil, err
+	}
+	if fr.logReads {
+		log.Printf("http2: Framer %p: read %v", fr, http2summarizeFrame(f))
+	}
+	return f, nil
+}
+
+// connError returns ConnectionError(code) but first
+// stashes away a public reason to the caller can optionally relay it
+// to the peer before hanging up on them. This might help others debug
+// their implementations.
+func (fr *http2Framer) connError(code http2ErrCode, reason string) error {
+	fr.errReason = reason
+	return http2ConnectionError(code)
+}
+
+// checkFrameOrder reports an error if f is an invalid frame to return
+// next from ReadFrame. Mostly it checks whether HEADERS and
+// CONTINUATION frames are contiguous.
+func (fr *http2Framer) checkFrameOrder(f http2Frame) error {
+	last := fr.lastFrame
+	fr.lastFrame = f
+	if fr.AllowIllegalReads {
+		return nil
+	}
+
+	fh := f.Header()
+	if fr.lastHeaderStream != 0 {
+		if fh.Type != http2FrameContinuation {
+			return fr.connError(http2ErrCodeProtocol,
+				fmt.Sprintf("got %s for stream %d; expected CONTINUATION following %s for stream %d",
+					fh.Type, fh.StreamID,
+					last.Header().Type, fr.lastHeaderStream))
+		}
+		if fh.StreamID != fr.lastHeaderStream {
+			return fr.connError(http2ErrCodeProtocol,
+				fmt.Sprintf("got CONTINUATION for stream %d; expected stream %d",
+					fh.StreamID, fr.lastHeaderStream))
+		}
+	} else if fh.Type == http2FrameContinuation {
+		return fr.connError(http2ErrCodeProtocol, fmt.Sprintf("unexpected CONTINUATION for stream %d", fh.StreamID))
+	}
+
+	switch fh.Type {
+	case http2FrameHeaders, http2FrameContinuation:
+		if fh.Flags.Has(http2FlagHeadersEndHeaders) {
+			fr.lastHeaderStream = 0
+		} else {
+			fr.lastHeaderStream = fh.StreamID
+		}
+	}
+
+	return nil
+}
+
+// A DataFrame conveys arbitrary, variable-length sequences of octets
+// associated with a stream.
+// See http://http2.github.io/http2-spec/#rfc.section.6.1
+type http2DataFrame struct {
+	http2FrameHeader
+	data []byte
+}
+
+func (f *http2DataFrame) StreamEnded() bool {
+	return f.http2FrameHeader.Flags.Has(http2FlagDataEndStream)
+}
+
+// Data returns the frame's data octets, not including any padding
+// size byte or padding suffix bytes.
+// The caller must not retain the returned memory past the next
+// call to ReadFrame.
+func (f *http2DataFrame) Data() []byte {
+	f.checkValid()
+	return f.data
+}
+
+func http2parseDataFrame(fh http2FrameHeader, payload []byte) (http2Frame, error) {
+	if fh.StreamID == 0 {
+
+		return nil, http2connError{http2ErrCodeProtocol, "DATA frame with stream ID 0"}
+	}
+	f := &http2DataFrame{
+		http2FrameHeader: fh,
+	}
+	var padSize byte
+	if fh.Flags.Has(http2FlagDataPadded) {
+		var err error
+		payload, padSize, err = http2readByte(payload)
+		if err != nil {
+			return nil, err
+		}
+	}
+	if int(padSize) > len(payload) {
+
+		return nil, http2connError{http2ErrCodeProtocol, "pad size larger than data payload"}
+	}
+	f.data = payload[:len(payload)-int(padSize)]
+	return f, nil
+}
+
+var http2errStreamID = errors.New("invalid streamid")
+
+func http2validStreamID(streamID uint32) bool {
+	return streamID != 0 && streamID&(1<<31) == 0
+}
+
+// WriteData writes a DATA frame.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *http2Framer) WriteData(streamID uint32, endStream bool, data []byte) error {
+
+	if !http2validStreamID(streamID) && !f.AllowIllegalWrites {
+		return http2errStreamID
+	}
+	var flags http2Flags
+	if endStream {
+		flags |= http2FlagDataEndStream
+	}
+	f.startWrite(http2FrameData, flags, streamID)
+	f.wbuf = append(f.wbuf, data...)
+	return f.endWrite()
+}
+
+// A SettingsFrame conveys configuration parameters that affect how
+// endpoints communicate, such as preferences and constraints on peer
+// behavior.
+//
+// See http://http2.github.io/http2-spec/#SETTINGS
+type http2SettingsFrame struct {
+	http2FrameHeader
+	p []byte
+}
+
+func http2parseSettingsFrame(fh http2FrameHeader, p []byte) (http2Frame, error) {
+	if fh.Flags.Has(http2FlagSettingsAck) && fh.Length > 0 {
+
+		return nil, http2ConnectionError(http2ErrCodeFrameSize)
+	}
+	if fh.StreamID != 0 {
+
+		return nil, http2ConnectionError(http2ErrCodeProtocol)
+	}
+	if len(p)%6 != 0 {
+
+		return nil, http2ConnectionError(http2ErrCodeFrameSize)
+	}
+	f := &http2SettingsFrame{http2FrameHeader: fh, p: p}
+	if v, ok := f.Value(http2SettingInitialWindowSize); ok && v > (1<<31)-1 {
+
+		return nil, http2ConnectionError(http2ErrCodeFlowControl)
+	}
+	return f, nil
+}
+
+func (f *http2SettingsFrame) IsAck() bool {
+	return f.http2FrameHeader.Flags.Has(http2FlagSettingsAck)
+}
+
+func (f *http2SettingsFrame) Value(s http2SettingID) (v uint32, ok bool) {
+	f.checkValid()
+	buf := f.p
+	for len(buf) > 0 {
+		settingID := http2SettingID(binary.BigEndian.Uint16(buf[:2]))
+		if settingID == s {
+			return binary.BigEndian.Uint32(buf[2:6]), true
+		}
+		buf = buf[6:]
+	}
+	return 0, false
+}
+
+// ForeachSetting runs fn for each setting.
+// It stops and returns the first error.
+func (f *http2SettingsFrame) ForeachSetting(fn func(http2Setting) error) error {
+	f.checkValid()
+	buf := f.p
+	for len(buf) > 0 {
+		if err := fn(http2Setting{
+			http2SettingID(binary.BigEndian.Uint16(buf[:2])),
+			binary.BigEndian.Uint32(buf[2:6]),
+		}); err != nil {
+			return err
+		}
+		buf = buf[6:]
+	}
+	return nil
+}
+
+// WriteSettings writes a SETTINGS frame with zero or more settings
+// specified and the ACK bit not set.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *http2Framer) WriteSettings(settings ...http2Setting) error {
+	f.startWrite(http2FrameSettings, 0, 0)
+	for _, s := range settings {
+		f.writeUint16(uint16(s.ID))
+		f.writeUint32(s.Val)
+	}
+	return f.endWrite()
+}
+
+// WriteSettings writes an empty SETTINGS frame with the ACK bit set.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *http2Framer) WriteSettingsAck() error {
+	f.startWrite(http2FrameSettings, http2FlagSettingsAck, 0)
+	return f.endWrite()
+}
+
+// A PingFrame is a mechanism for measuring a minimal round trip time
+// from the sender, as well as determining whether an idle connection
+// is still functional.
+// See http://http2.github.io/http2-spec/#rfc.section.6.7
+type http2PingFrame struct {
+	http2FrameHeader
+	Data [8]byte
+}
+
+func (f *http2PingFrame) IsAck() bool { return f.Flags.Has(http2FlagPingAck) }
+
+func http2parsePingFrame(fh http2FrameHeader, payload []byte) (http2Frame, error) {
+	if len(payload) != 8 {
+		return nil, http2ConnectionError(http2ErrCodeFrameSize)
+	}
+	if fh.StreamID != 0 {
+		return nil, http2ConnectionError(http2ErrCodeProtocol)
+	}
+	f := &http2PingFrame{http2FrameHeader: fh}
+	copy(f.Data[:], payload)
+	return f, nil
+}
+
+func (f *http2Framer) WritePing(ack bool, data [8]byte) error {
+	var flags http2Flags
+	if ack {
+		flags = http2FlagPingAck
+	}
+	f.startWrite(http2FramePing, flags, 0)
+	f.writeBytes(data[:])
+	return f.endWrite()
+}
+
+// A GoAwayFrame informs the remote peer to stop creating streams on this connection.
+// See http://http2.github.io/http2-spec/#rfc.section.6.8
+type http2GoAwayFrame struct {
+	http2FrameHeader
+	LastStreamID uint32
+	ErrCode      http2ErrCode
+	debugData    []byte
+}
+
+// DebugData returns any debug data in the GOAWAY frame. Its contents
+// are not defined.
+// The caller must not retain the returned memory past the next
+// call to ReadFrame.
+func (f *http2GoAwayFrame) DebugData() []byte {
+	f.checkValid()
+	return f.debugData
+}
+
+func http2parseGoAwayFrame(fh http2FrameHeader, p []byte) (http2Frame, error) {
+	if fh.StreamID != 0 {
+		return nil, http2ConnectionError(http2ErrCodeProtocol)
+	}
+	if len(p) < 8 {
+		return nil, http2ConnectionError(http2ErrCodeFrameSize)
+	}
+	return &http2GoAwayFrame{
+		http2FrameHeader: fh,
+		LastStreamID:     binary.BigEndian.Uint32(p[:4]) & (1<<31 - 1),
+		ErrCode:          http2ErrCode(binary.BigEndian.Uint32(p[4:8])),
+		debugData:        p[8:],
+	}, nil
+}
+
+func (f *http2Framer) WriteGoAway(maxStreamID uint32, code http2ErrCode, debugData []byte) error {
+	f.startWrite(http2FrameGoAway, 0, 0)
+	f.writeUint32(maxStreamID & (1<<31 - 1))
+	f.writeUint32(uint32(code))
+	f.writeBytes(debugData)
+	return f.endWrite()
+}
+
+// An UnknownFrame is the frame type returned when the frame type is unknown
+// or no specific frame type parser exists.
+type http2UnknownFrame struct {
+	http2FrameHeader
+	p []byte
+}
+
+// Payload returns the frame's payload (after the header).  It is not
+// valid to call this method after a subsequent call to
+// Framer.ReadFrame, nor is it valid to retain the returned slice.
+// The memory is owned by the Framer and is invalidated when the next
+// frame is read.
+func (f *http2UnknownFrame) Payload() []byte {
+	f.checkValid()
+	return f.p
+}
+
+func http2parseUnknownFrame(fh http2FrameHeader, p []byte) (http2Frame, error) {
+	return &http2UnknownFrame{fh, p}, nil
+}
+
+// A WindowUpdateFrame is used to implement flow control.
+// See http://http2.github.io/http2-spec/#rfc.section.6.9
+type http2WindowUpdateFrame struct {
+	http2FrameHeader
+	Increment uint32 // never read with high bit set
+}
+
+func http2parseWindowUpdateFrame(fh http2FrameHeader, p []byte) (http2Frame, error) {
+	if len(p) != 4 {
+		return nil, http2ConnectionError(http2ErrCodeFrameSize)
+	}
+	inc := binary.BigEndian.Uint32(p[:4]) & 0x7fffffff
+	if inc == 0 {
+
+		if fh.StreamID == 0 {
+			return nil, http2ConnectionError(http2ErrCodeProtocol)
+		}
+		return nil, http2StreamError{fh.StreamID, http2ErrCodeProtocol}
+	}
+	return &http2WindowUpdateFrame{
+		http2FrameHeader: fh,
+		Increment:        inc,
+	}, nil
+}
+
+// WriteWindowUpdate writes a WINDOW_UPDATE frame.
+// The increment value must be between 1 and 2,147,483,647, inclusive.
+// If the Stream ID is zero, the window update applies to the
+// connection as a whole.
+func (f *http2Framer) WriteWindowUpdate(streamID, incr uint32) error {
+
+	if (incr < 1 || incr > 2147483647) && !f.AllowIllegalWrites {
+		return errors.New("illegal window increment value")
+	}
+	f.startWrite(http2FrameWindowUpdate, 0, streamID)
+	f.writeUint32(incr)
+	return f.endWrite()
+}
+
+// A HeadersFrame is used to open a stream and additionally carries a
+// header block fragment.
+type http2HeadersFrame struct {
+	http2FrameHeader
+
+	// Priority is set if FlagHeadersPriority is set in the FrameHeader.
+	Priority http2PriorityParam
+
+	headerFragBuf []byte // not owned
+}
+
+func (f *http2HeadersFrame) HeaderBlockFragment() []byte {
+	f.checkValid()
+	return f.headerFragBuf
+}
+
+func (f *http2HeadersFrame) HeadersEnded() bool {
+	return f.http2FrameHeader.Flags.Has(http2FlagHeadersEndHeaders)
+}
+
+func (f *http2HeadersFrame) StreamEnded() bool {
+	return f.http2FrameHeader.Flags.Has(http2FlagHeadersEndStream)
+}
+
+func (f *http2HeadersFrame) HasPriority() bool {
+	return f.http2FrameHeader.Flags.Has(http2FlagHeadersPriority)
+}
+
+func http2parseHeadersFrame(fh http2FrameHeader, p []byte) (_ http2Frame, err error) {
+	hf := &http2HeadersFrame{
+		http2FrameHeader: fh,
+	}
+	if fh.StreamID == 0 {
+
+		return nil, http2connError{http2ErrCodeProtocol, "HEADERS frame with stream ID 0"}
+	}
+	var padLength uint8
+	if fh.Flags.Has(http2FlagHeadersPadded) {
+		if p, padLength, err = http2readByte(p); err != nil {
+			return
+		}
+	}
+	if fh.Flags.Has(http2FlagHeadersPriority) {
+		var v uint32
+		p, v, err = http2readUint32(p)
+		if err != nil {
+			return nil, err
+		}
+		hf.Priority.StreamDep = v & 0x7fffffff
+		hf.Priority.Exclusive = (v != hf.Priority.StreamDep)
+		p, hf.Priority.Weight, err = http2readByte(p)
+		if err != nil {
+			return nil, err
+		}
+	}
+	if len(p)-int(padLength) <= 0 {
+		return nil, http2StreamError{fh.StreamID, http2ErrCodeProtocol}
+	}
+	hf.headerFragBuf = p[:len(p)-int(padLength)]
+	return hf, nil
+}
+
+// HeadersFrameParam are the parameters for writing a HEADERS frame.
+type http2HeadersFrameParam struct {
+	// StreamID is the required Stream ID to initiate.
+	StreamID uint32
+	// BlockFragment is part (or all) of a Header Block.
+	BlockFragment []byte
+
+	// EndStream indicates that the header block is the last that
+	// the endpoint will send for the identified stream. Setting
+	// this flag causes the stream to enter one of "half closed"
+	// states.
+	EndStream bool
+
+	// EndHeaders indicates that this frame contains an entire
+	// header block and is not followed by any
+	// CONTINUATION frames.
+	EndHeaders bool
+
+	// PadLength is the optional number of bytes of zeros to add
+	// to this frame.
+	PadLength uint8
+
+	// Priority, if non-zero, includes stream priority information
+	// in the HEADER frame.
+	Priority http2PriorityParam
+}
+
+// WriteHeaders writes a single HEADERS frame.
+//
+// This is a low-level header writing method. Encoding headers and
+// splitting them into any necessary CONTINUATION frames is handled
+// elsewhere.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *http2Framer) WriteHeaders(p http2HeadersFrameParam) error {
+	if !http2validStreamID(p.StreamID) && !f.AllowIllegalWrites {
+		return http2errStreamID
+	}
+	var flags http2Flags
+	if p.PadLength != 0 {
+		flags |= http2FlagHeadersPadded
+	}
+	if p.EndStream {
+		flags |= http2FlagHeadersEndStream
+	}
+	if p.EndHeaders {
+		flags |= http2FlagHeadersEndHeaders
+	}
+	if !p.Priority.IsZero() {
+		flags |= http2FlagHeadersPriority
+	}
+	f.startWrite(http2FrameHeaders, flags, p.StreamID)
+	if p.PadLength != 0 {
+		f.writeByte(p.PadLength)
+	}
+	if !p.Priority.IsZero() {
+		v := p.Priority.StreamDep
+		if !http2validStreamID(v) && !f.AllowIllegalWrites {
+			return errors.New("invalid dependent stream id")
+		}
+		if p.Priority.Exclusive {
+			v |= 1 << 31
+		}
+		f.writeUint32(v)
+		f.writeByte(p.Priority.Weight)
+	}
+	f.wbuf = append(f.wbuf, p.BlockFragment...)
+	f.wbuf = append(f.wbuf, http2padZeros[:p.PadLength]...)
+	return f.endWrite()
+}
+
+// A PriorityFrame specifies the sender-advised priority of a stream.
+// See http://http2.github.io/http2-spec/#rfc.section.6.3
+type http2PriorityFrame struct {
+	http2FrameHeader
+	http2PriorityParam
+}
+
+// PriorityParam are the stream prioritzation parameters.
+type http2PriorityParam struct {
+	// StreamDep is a 31-bit stream identifier for the
+	// stream that this stream depends on. Zero means no
+	// dependency.
+	StreamDep uint32
+
+	// Exclusive is whether the dependency is exclusive.
+	Exclusive bool
+
+	// Weight is the stream's zero-indexed weight. It should be
+	// set together with StreamDep, or neither should be set.  Per
+	// the spec, "Add one to the value to obtain a weight between
+	// 1 and 256."
+	Weight uint8
+}
+
+func (p http2PriorityParam) IsZero() bool {
+	return p == http2PriorityParam{}
+}
+
+func http2parsePriorityFrame(fh http2FrameHeader, payload []byte) (http2Frame, error) {
+	if fh.StreamID == 0 {
+		return nil, http2connError{http2ErrCodeProtocol, "PRIORITY frame with stream ID 0"}
+	}
+	if len(payload) != 5 {
+		return nil, http2connError{http2ErrCodeFrameSize, fmt.Sprintf("PRIORITY frame payload size was %d; want 5", len(payload))}
+	}
+	v := binary.BigEndian.Uint32(payload[:4])
+	streamID := v & 0x7fffffff
+	return &http2PriorityFrame{
+		http2FrameHeader: fh,
+		http2PriorityParam: http2PriorityParam{
+			Weight:    payload[4],
+			StreamDep: streamID,
+			Exclusive: streamID != v,
+		},
+	}, nil
+}
+
+// WritePriority writes a PRIORITY frame.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *http2Framer) WritePriority(streamID uint32, p http2PriorityParam) error {
+	if !http2validStreamID(streamID) && !f.AllowIllegalWrites {
+		return http2errStreamID
+	}
+	f.startWrite(http2FramePriority, 0, streamID)
+	v := p.StreamDep
+	if p.Exclusive {
+		v |= 1 << 31
+	}
+	f.writeUint32(v)
+	f.writeByte(p.Weight)
+	return f.endWrite()
+}
+
+// A RSTStreamFrame allows for abnormal termination of a stream.
+// See http://http2.github.io/http2-spec/#rfc.section.6.4
+type http2RSTStreamFrame struct {
+	http2FrameHeader
+	ErrCode http2ErrCode
+}
+
+func http2parseRSTStreamFrame(fh http2FrameHeader, p []byte) (http2Frame, error) {
+	if len(p) != 4 {
+		return nil, http2ConnectionError(http2ErrCodeFrameSize)
+	}
+	if fh.StreamID == 0 {
+		return nil, http2ConnectionError(http2ErrCodeProtocol)
+	}
+	return &http2RSTStreamFrame{fh, http2ErrCode(binary.BigEndian.Uint32(p[:4]))}, nil
+}
+
+// WriteRSTStream writes a RST_STREAM frame.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *http2Framer) WriteRSTStream(streamID uint32, code http2ErrCode) error {
+	if !http2validStreamID(streamID) && !f.AllowIllegalWrites {
+		return http2errStreamID
+	}
+	f.startWrite(http2FrameRSTStream, 0, streamID)
+	f.writeUint32(uint32(code))
+	return f.endWrite()
+}
+
+// A ContinuationFrame is used to continue a sequence of header block fragments.
+// See http://http2.github.io/http2-spec/#rfc.section.6.10
+type http2ContinuationFrame struct {
+	http2FrameHeader
+	headerFragBuf []byte
+}
+
+func http2parseContinuationFrame(fh http2FrameHeader, p []byte) (http2Frame, error) {
+	if fh.StreamID == 0 {
+		return nil, http2connError{http2ErrCodeProtocol, "CONTINUATION frame with stream ID 0"}
+	}
+	return &http2ContinuationFrame{fh, p}, nil
+}
+
+func (f *http2ContinuationFrame) HeaderBlockFragment() []byte {
+	f.checkValid()
+	return f.headerFragBuf
+}
+
+func (f *http2ContinuationFrame) HeadersEnded() bool {
+	return f.http2FrameHeader.Flags.Has(http2FlagContinuationEndHeaders)
+}
+
+// WriteContinuation writes a CONTINUATION frame.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *http2Framer) WriteContinuation(streamID uint32, endHeaders bool, headerBlockFragment []byte) error {
+	if !http2validStreamID(streamID) && !f.AllowIllegalWrites {
+		return http2errStreamID
+	}
+	var flags http2Flags
+	if endHeaders {
+		flags |= http2FlagContinuationEndHeaders
+	}
+	f.startWrite(http2FrameContinuation, flags, streamID)
+	f.wbuf = append(f.wbuf, headerBlockFragment...)
+	return f.endWrite()
+}
+
+// A PushPromiseFrame is used to initiate a server stream.
+// See http://http2.github.io/http2-spec/#rfc.section.6.6
+type http2PushPromiseFrame struct {
+	http2FrameHeader
+	PromiseID     uint32
+	headerFragBuf []byte // not owned
+}
+
+func (f *http2PushPromiseFrame) HeaderBlockFragment() []byte {
+	f.checkValid()
+	return f.headerFragBuf
+}
+
+func (f *http2PushPromiseFrame) HeadersEnded() bool {
+	return f.http2FrameHeader.Flags.Has(http2FlagPushPromiseEndHeaders)
+}
+
+func http2parsePushPromise(fh http2FrameHeader, p []byte) (_ http2Frame, err error) {
+	pp := &http2PushPromiseFrame{
+		http2FrameHeader: fh,
+	}
+	if pp.StreamID == 0 {
+
+		return nil, http2ConnectionError(http2ErrCodeProtocol)
+	}
+	// The PUSH_PROMISE frame includes optional padding.
+	// Padding fields and flags are identical to those defined for DATA frames
+	var padLength uint8
+	if fh.Flags.Has(http2FlagPushPromisePadded) {
+		if p, padLength, err = http2readByte(p); err != nil {
+			return
+		}
+	}
+
+	p, pp.PromiseID, err = http2readUint32(p)
+	if err != nil {
+		return
+	}
+	pp.PromiseID = pp.PromiseID & (1<<31 - 1)
+
+	if int(padLength) > len(p) {
+
+		return nil, http2ConnectionError(http2ErrCodeProtocol)
+	}
+	pp.headerFragBuf = p[:len(p)-int(padLength)]
+	return pp, nil
+}
+
+// PushPromiseParam are the parameters for writing a PUSH_PROMISE frame.
+type http2PushPromiseParam struct {
+	// StreamID is the required Stream ID to initiate.
+	StreamID uint32
+
+	// PromiseID is the required Stream ID which this
+	// Push Promises
+	PromiseID uint32
+
+	// BlockFragment is part (or all) of a Header Block.
+	BlockFragment []byte
+
+	// EndHeaders indicates that this frame contains an entire
+	// header block and is not followed by any
+	// CONTINUATION frames.
+	EndHeaders bool
+
+	// PadLength is the optional number of bytes of zeros to add
+	// to this frame.
+	PadLength uint8
+}
+
+// WritePushPromise writes a single PushPromise Frame.
+//
+// As with Header Frames, This is the low level call for writing
+// individual frames. Continuation frames are handled elsewhere.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *http2Framer) WritePushPromise(p http2PushPromiseParam) error {
+	if !http2validStreamID(p.StreamID) && !f.AllowIllegalWrites {
+		return http2errStreamID
+	}
+	var flags http2Flags
+	if p.PadLength != 0 {
+		flags |= http2FlagPushPromisePadded
+	}
+	if p.EndHeaders {
+		flags |= http2FlagPushPromiseEndHeaders
+	}
+	f.startWrite(http2FramePushPromise, flags, p.StreamID)
+	if p.PadLength != 0 {
+		f.writeByte(p.PadLength)
+	}
+	if !http2validStreamID(p.PromiseID) && !f.AllowIllegalWrites {
+		return http2errStreamID
+	}
+	f.writeUint32(p.PromiseID)
+	f.wbuf = append(f.wbuf, p.BlockFragment...)
+	f.wbuf = append(f.wbuf, http2padZeros[:p.PadLength]...)
+	return f.endWrite()
+}
+
+// WriteRawFrame writes a raw frame. This can be used to write
+// extension frames unknown to this package.
+func (f *http2Framer) WriteRawFrame(t http2FrameType, flags http2Flags, streamID uint32, payload []byte) error {
+	f.startWrite(t, flags, streamID)
+	f.writeBytes(payload)
+	return f.endWrite()
+}
+
+func http2readByte(p []byte) (remain []byte, b byte, err error) {
+	if len(p) == 0 {
+		return nil, 0, io.ErrUnexpectedEOF
+	}
+	return p[1:], p[0], nil
+}
+
+func http2readUint32(p []byte) (remain []byte, v uint32, err error) {
+	if len(p) < 4 {
+		return nil, 0, io.ErrUnexpectedEOF
+	}
+	return p[4:], binary.BigEndian.Uint32(p[:4]), nil
+}
+
+type http2streamEnder interface {
+	StreamEnded() bool
+}
+
+type http2headersEnder interface {
+	HeadersEnded() bool
+}
+
+func http2summarizeFrame(f http2Frame) string {
+	var buf bytes.Buffer
+	f.Header().writeDebug(&buf)
+	switch f := f.(type) {
+	case *http2SettingsFrame:
+		n := 0
+		f.ForeachSetting(func(s http2Setting) error {
+			n++
+			if n == 1 {
+				buf.WriteString(", settings:")
+			}
+			fmt.Fprintf(&buf, " %v=%v,", s.ID, s.Val)
+			return nil
+		})
+		if n > 0 {
+			buf.Truncate(buf.Len() - 1)
+		}
+	case *http2DataFrame:
+		data := f.Data()
+		const max = 256
+		if len(data) > max {
+			data = data[:max]
+		}
+		fmt.Fprintf(&buf, " data=%q", data)
+		if len(f.Data()) > max {
+			fmt.Fprintf(&buf, " (%d bytes omitted)", len(f.Data())-max)
+		}
+	case *http2WindowUpdateFrame:
+		if f.StreamID == 0 {
+			buf.WriteString(" (conn)")
+		}
+		fmt.Fprintf(&buf, " incr=%v", f.Increment)
+	case *http2PingFrame:
+		fmt.Fprintf(&buf, " ping=%q", f.Data[:])
+	case *http2GoAwayFrame:
+		fmt.Fprintf(&buf, " LastStreamID=%v ErrCode=%v Debug=%q",
+			f.LastStreamID, f.ErrCode, f.debugData)
+	case *http2RSTStreamFrame:
+		fmt.Fprintf(&buf, " ErrCode=%v", f.ErrCode)
+	}
+	return buf.String()
+}
+
+func http2requestCancel(req *Request) <-chan struct{} { return req.Cancel }
+
+var http2DebugGoroutines = os.Getenv("DEBUG_HTTP2_GOROUTINES") == "1"
+
+type http2goroutineLock uint64
+
+func http2newGoroutineLock() http2goroutineLock {
+	if !http2DebugGoroutines {
+		return 0
+	}
+	return http2goroutineLock(http2curGoroutineID())
+}
+
+func (g http2goroutineLock) check() {
+	if !http2DebugGoroutines {
+		return
+	}
+	if http2curGoroutineID() != uint64(g) {
+		panic("running on the wrong goroutine")
+	}
+}
+
+func (g http2goroutineLock) checkNotOn() {
+	if !http2DebugGoroutines {
+		return
+	}
+	if http2curGoroutineID() == uint64(g) {
+		panic("running on the wrong goroutine")
+	}
+}
+
+var http2goroutineSpace = []byte("goroutine ")
+
+func http2curGoroutineID() uint64 {
+	bp := http2littleBuf.Get().(*[]byte)
+	defer http2littleBuf.Put(bp)
+	b := *bp
+	b = b[:runtime.Stack(b, false)]
+
+	b = bytes.TrimPrefix(b, http2goroutineSpace)
+	i := bytes.IndexByte(b, ' ')
+	if i < 0 {
+		panic(fmt.Sprintf("No space found in %q", b))
+	}
+	b = b[:i]
+	n, err := http2parseUintBytes(b, 10, 64)
+	if err != nil {
+		panic(fmt.Sprintf("Failed to parse goroutine ID out of %q: %v", b, err))
+	}
+	return n
+}
+
+var http2littleBuf = sync.Pool{
+	New: func() interface{} {
+		buf := make([]byte, 64)
+		return &buf
+	},
+}
+
+// parseUintBytes is like strconv.ParseUint, but using a []byte.
+func http2parseUintBytes(s []byte, base int, bitSize int) (n uint64, err error) {
+	var cutoff, maxVal uint64
+
+	if bitSize == 0 {
+		bitSize = int(strconv.IntSize)
+	}
+
+	s0 := s
+	switch {
+	case len(s) < 1:
+		err = strconv.ErrSyntax
+		goto Error
+
+	case 2 <= base && base <= 36:
+
+	case base == 0:
+
+		switch {
+		case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
+			base = 16
+			s = s[2:]
+			if len(s) < 1 {
+				err = strconv.ErrSyntax
+				goto Error
+			}
+		case s[0] == '0':
+			base = 8
+		default:
+			base = 10
+		}
+
+	default:
+		err = errors.New("invalid base " + strconv.Itoa(base))
+		goto Error
+	}
+
+	n = 0
+	cutoff = http2cutoff64(base)
+	maxVal = 1<<uint(bitSize) - 1
+
+	for i := 0; i < len(s); i++ {
+		var v byte
+		d := s[i]
+		switch {
+		case '0' <= d && d <= '9':
+			v = d - '0'
+		case 'a' <= d && d <= 'z':
+			v = d - 'a' + 10
+		case 'A' <= d && d <= 'Z':
+			v = d - 'A' + 10
+		default:
+			n = 0
+			err = strconv.ErrSyntax
+			goto Error
+		}
+		if int(v) >= base {
+			n = 0
+			err = strconv.ErrSyntax
+			goto Error
+		}
+
+		if n >= cutoff {
+
+			n = 1<<64 - 1
+			err = strconv.ErrRange
+			goto Error
+		}
+		n *= uint64(base)
+
+		n1 := n + uint64(v)
+		if n1 < n || n1 > maxVal {
+
+			n = 1<<64 - 1
+			err = strconv.ErrRange
+			goto Error
+		}
+		n = n1
+	}
+
+	return n, nil
+
+Error:
+	return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err}
+}
+
+// Return the first number n such that n*base >= 1<<64.
+func http2cutoff64(base int) uint64 {
+	if base < 2 {
+		return 0
+	}
+	return (1<<64-1)/uint64(base) + 1
+}
+
+var (
+	http2commonLowerHeader = map[string]string{} // Go-Canonical-Case -> lower-case
+	http2commonCanonHeader = map[string]string{} // lower-case -> Go-Canonical-Case
+)
+
+func init() {
+	for _, v := range []string{
+		"accept",
+		"accept-charset",
+		"accept-encoding",
+		"accept-language",
+		"accept-ranges",
+		"age",
+		"access-control-allow-origin",
+		"allow",
+		"authorization",
+		"cache-control",
+		"content-disposition",
+		"content-encoding",
+		"content-language",
+		"content-length",
+		"content-location",
+		"content-range",
+		"content-type",
+		"cookie",
+		"date",
+		"etag",
+		"expect",
+		"expires",
+		"from",
+		"host",
+		"if-match",
+		"if-modified-since",
+		"if-none-match",
+		"if-unmodified-since",
+		"last-modified",
+		"link",
+		"location",
+		"max-forwards",
+		"proxy-authenticate",
+		"proxy-authorization",
+		"range",
+		"referer",
+		"refresh",
+		"retry-after",
+		"server",
+		"set-cookie",
+		"strict-transport-security",
+		"trailer",
+		"transfer-encoding",
+		"user-agent",
+		"vary",
+		"via",
+		"www-authenticate",
+	} {
+		chk := CanonicalHeaderKey(v)
+		http2commonLowerHeader[chk] = v
+		http2commonCanonHeader[v] = chk
+	}
+}
+
+func http2lowerHeader(v string) string {
+	if s, ok := http2commonLowerHeader[v]; ok {
+		return s
+	}
+	return strings.ToLower(v)
+}
+
+var (
+	http2VerboseLogs    bool
+	http2logFrameWrites bool
+	http2logFrameReads  bool
+)
+
+func init() {
+	e := os.Getenv("GODEBUG")
+	if strings.Contains(e, "http2debug=1") {
+		http2VerboseLogs = true
+	}
+	if strings.Contains(e, "http2debug=2") {
+		http2VerboseLogs = true
+		http2logFrameWrites = true
+		http2logFrameReads = true
+	}
+}
+
+const (
+	// ClientPreface is the string that must be sent by new
+	// connections from clients.
+	http2ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
+
+	// SETTINGS_MAX_FRAME_SIZE default
+	// http://http2.github.io/http2-spec/#rfc.section.6.5.2
+	http2initialMaxFrameSize = 16384
+
+	// NextProtoTLS is the NPN/ALPN protocol negotiated during
+	// HTTP/2's TLS setup.
+	http2NextProtoTLS = "h2"
+
+	// http://http2.github.io/http2-spec/#SettingValues
+	http2initialHeaderTableSize = 4096
+
+	http2initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size
+
+	http2defaultMaxReadFrameSize = 1 << 20
+)
+
+var (
+	http2clientPreface = []byte(http2ClientPreface)
+)
+
+type http2streamState int
+
+const (
+	http2stateIdle http2streamState = iota
+	http2stateOpen
+	http2stateHalfClosedLocal
+	http2stateHalfClosedRemote
+	http2stateResvLocal
+	http2stateResvRemote
+	http2stateClosed
+)
+
+var http2stateName = [...]string{
+	http2stateIdle:             "Idle",
+	http2stateOpen:             "Open",
+	http2stateHalfClosedLocal:  "HalfClosedLocal",
+	http2stateHalfClosedRemote: "HalfClosedRemote",
+	http2stateResvLocal:        "ResvLocal",
+	http2stateResvRemote:       "ResvRemote",
+	http2stateClosed:           "Closed",
+}
+
+func (st http2streamState) String() string {
+	return http2stateName[st]
+}
+
+// Setting is a setting parameter: which setting it is, and its value.
+type http2Setting struct {
+	// ID is which setting is being set.
+	// See http://http2.github.io/http2-spec/#SettingValues
+	ID http2SettingID
+
+	// Val is the value.
+	Val uint32
+}
+
+func (s http2Setting) String() string {
+	return fmt.Sprintf("[%v = %d]", s.ID, s.Val)
+}
+
+// Valid reports whether the setting is valid.
+func (s http2Setting) Valid() error {
+
+	switch s.ID {
+	case http2SettingEnablePush:
+		if s.Val != 1 && s.Val != 0 {
+			return http2ConnectionError(http2ErrCodeProtocol)
+		}
+	case http2SettingInitialWindowSize:
+		if s.Val > 1<<31-1 {
+			return http2ConnectionError(http2ErrCodeFlowControl)
+		}
+	case http2SettingMaxFrameSize:
+		if s.Val < 16384 || s.Val > 1<<24-1 {
+			return http2ConnectionError(http2ErrCodeProtocol)
+		}
+	}
+	return nil
+}
+
+// A SettingID is an HTTP/2 setting as defined in
+// http://http2.github.io/http2-spec/#iana-settings
+type http2SettingID uint16
+
+const (
+	http2SettingHeaderTableSize      http2SettingID = 0x1
+	http2SettingEnablePush           http2SettingID = 0x2
+	http2SettingMaxConcurrentStreams http2SettingID = 0x3
+	http2SettingInitialWindowSize    http2SettingID = 0x4
+	http2SettingMaxFrameSize         http2SettingID = 0x5
+	http2SettingMaxHeaderListSize    http2SettingID = 0x6
+)
+
+var http2settingName = map[http2SettingID]string{
+	http2SettingHeaderTableSize:      "HEADER_TABLE_SIZE",
+	http2SettingEnablePush:           "ENABLE_PUSH",
+	http2SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS",
+	http2SettingInitialWindowSize:    "INITIAL_WINDOW_SIZE",
+	http2SettingMaxFrameSize:         "MAX_FRAME_SIZE",
+	http2SettingMaxHeaderListSize:    "MAX_HEADER_LIST_SIZE",
+}
+
+func (s http2SettingID) String() string {
+	if v, ok := http2settingName[s]; ok {
+		return v
+	}
+	return fmt.Sprintf("UNKNOWN_SETTING_%d", uint16(s))
+}
+
+var (
+	http2errInvalidHeaderFieldName  = errors.New("http2: invalid header field name")
+	http2errInvalidHeaderFieldValue = errors.New("http2: invalid header field value")
+)
+
+// validHeaderFieldName reports whether v is a valid header field name (key).
+//  RFC 7230 says:
+//   header-field   = field-name ":" OWS field-value OWS
+//   field-name     = token
+//   tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
+//           "^" / "_" / "
+// Further, http2 says:
+//   "Just as in HTTP/1.x, header field names are strings of ASCII
+//   characters that are compared in a case-insensitive
+//   fashion. However, header field names MUST be converted to
+//   lowercase prior to their encoding in HTTP/2. "
+func http2validHeaderFieldName(v string) bool {
+	if len(v) == 0 {
+		return false
+	}
+	for _, r := range v {
+		if int(r) >= len(http2isTokenTable) || ('A' <= r && r <= 'Z') {
+			return false
+		}
+		if !http2isTokenTable[byte(r)] {
+			return false
+		}
+	}
+	return true
+}
+
+// validHeaderFieldValue reports whether v is a valid header field value.
+//
+// RFC 7230 says:
+//  field-value    = *( field-content / obs-fold )
+//  obj-fold       =  N/A to http2, and deprecated
+//  field-content  = field-vchar [ 1*( SP / HTAB ) field-vchar ]
+//  field-vchar    = VCHAR / obs-text
+//  obs-text       = %x80-FF
+//  VCHAR          = "any visible [USASCII] character"
+//
+// http2 further says: "Similarly, HTTP/2 allows header field values
+// that are not valid. While most of the values that can be encoded
+// will not alter header field parsing, carriage return (CR, ASCII
+// 0xd), line feed (LF, ASCII 0xa), and the zero character (NUL, ASCII
+// 0x0) might be exploited by an attacker if they are translated
+// verbatim. Any request or response that contains a character not
+// permitted in a header field value MUST be treated as malformed
+// (Section 8.1.2.6). Valid characters are defined by the
+// field-content ABNF rule in Section 3.2 of [RFC7230]."
+//
+// This function does not (yet?) properly handle the rejection of
+// strings that begin or end with SP or HTAB.
+func http2validHeaderFieldValue(v string) bool {
+	for i := 0; i < len(v); i++ {
+		if b := v[i]; b < ' ' && b != '\t' || b == 0x7f {
+			return false
+		}
+	}
+	return true
+}
+
+var http2httpCodeStringCommon = map[int]string{} // n -> strconv.Itoa(n)
+
+func init() {
+	for i := 100; i <= 999; i++ {
+		if v := StatusText(i); v != "" {
+			http2httpCodeStringCommon[i] = strconv.Itoa(i)
+		}
+	}
+}
+
+func http2httpCodeString(code int) string {
+	if s, ok := http2httpCodeStringCommon[code]; ok {
+		return s
+	}
+	return strconv.Itoa(code)
+}
+
+// from pkg io
+type http2stringWriter interface {
+	WriteString(s string) (n int, err error)
+}
+
+// A gate lets two goroutines coordinate their activities.
+type http2gate chan struct{}
+
+func (g http2gate) Done() { g <- struct{}{} }
+
+func (g http2gate) Wait() { <-g }
+
+// A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed).
+type http2closeWaiter chan struct{}
+
+// Init makes a closeWaiter usable.
+// It exists because so a closeWaiter value can be placed inside a
+// larger struct and have the Mutex and Cond's memory in the same
+// allocation.
+func (cw *http2closeWaiter) Init() {
+	*cw = make(chan struct{})
+}
+
+// Close marks the closeWaiter as closed and unblocks any waiters.
+func (cw http2closeWaiter) Close() {
+	close(cw)
+}
+
+// Wait waits for the closeWaiter to become closed.
+func (cw http2closeWaiter) Wait() {
+	<-cw
+}
+
+// bufferedWriter is a buffered writer that writes to w.
+// Its buffered writer is lazily allocated as needed, to minimize
+// idle memory usage with many connections.
+type http2bufferedWriter struct {
+	w  io.Writer     // immutable
+	bw *bufio.Writer // non-nil when data is buffered
+}
+
+func http2newBufferedWriter(w io.Writer) *http2bufferedWriter {
+	return &http2bufferedWriter{w: w}
+}
+
+var http2bufWriterPool = sync.Pool{
+	New: func() interface{} {
+
+		return bufio.NewWriterSize(nil, 4<<10)
+	},
+}
+
+func (w *http2bufferedWriter) Write(p []byte) (n int, err error) {
+	if w.bw == nil {
+		bw := http2bufWriterPool.Get().(*bufio.Writer)
+		bw.Reset(w.w)
+		w.bw = bw
+	}
+	return w.bw.Write(p)
+}
+
+func (w *http2bufferedWriter) Flush() error {
+	bw := w.bw
+	if bw == nil {
+		return nil
+	}
+	err := bw.Flush()
+	bw.Reset(nil)
+	http2bufWriterPool.Put(bw)
+	w.bw = nil
+	return err
+}
+
+func http2mustUint31(v int32) uint32 {
+	if v < 0 || v > 2147483647 {
+		panic("out of range")
+	}
+	return uint32(v)
+}
+
+// bodyAllowedForStatus reports whether a given response status code
+// permits a body. See RFC2616, section 4.4.
+func http2bodyAllowedForStatus(status int) bool {
+	switch {
+	case status >= 100 && status <= 199:
+		return false
+	case status == 204:
+		return false
+	case status == 304:
+		return false
+	}
+	return true
+}
+
+type http2httpError struct {
+	msg     string
+	timeout bool
+}
+
+func (e *http2httpError) Error() string { return e.msg }
+
+func (e *http2httpError) Timeout() bool { return e.timeout }
+
+func (e *http2httpError) Temporary() bool { return true }
+
+var http2errTimeout error = &http2httpError{msg: "http2: timeout awaiting response headers", timeout: true}
+
+var http2isTokenTable = [127]bool{
+	'!':  true,
+	'#':  true,
+	'$':  true,
+	'%':  true,
+	'&':  true,
+	'\'': true,
+	'*':  true,
+	'+':  true,
+	'-':  true,
+	'.':  true,
+	'0':  true,
+	'1':  true,
+	'2':  true,
+	'3':  true,
+	'4':  true,
+	'5':  true,
+	'6':  true,
+	'7':  true,
+	'8':  true,
+	'9':  true,
+	'A':  true,
+	'B':  true,
+	'C':  true,
+	'D':  true,
+	'E':  true,
+	'F':  true,
+	'G':  true,
+	'H':  true,
+	'I':  true,
+	'J':  true,
+	'K':  true,
+	'L':  true,
+	'M':  true,
+	'N':  true,
+	'O':  true,
+	'P':  true,
+	'Q':  true,
+	'R':  true,
+	'S':  true,
+	'T':  true,
+	'U':  true,
+	'W':  true,
+	'V':  true,
+	'X':  true,
+	'Y':  true,
+	'Z':  true,
+	'^':  true,
+	'_':  true,
+	'`':  true,
+	'a':  true,
+	'b':  true,
+	'c':  true,
+	'd':  true,
+	'e':  true,
+	'f':  true,
+	'g':  true,
+	'h':  true,
+	'i':  true,
+	'j':  true,
+	'k':  true,
+	'l':  true,
+	'm':  true,
+	'n':  true,
+	'o':  true,
+	'p':  true,
+	'q':  true,
+	'r':  true,
+	's':  true,
+	't':  true,
+	'u':  true,
+	'v':  true,
+	'w':  true,
+	'x':  true,
+	'y':  true,
+	'z':  true,
+	'|':  true,
+	'~':  true,
+}
+
+type http2connectionStater interface {
+	ConnectionState() tls.ConnectionState
+}
+
+// pipe is a goroutine-safe io.Reader/io.Writer pair.  It's like
+// io.Pipe except there are no PipeReader/PipeWriter halves, and the
+// underlying buffer is an interface. (io.Pipe is always unbuffered)
+type http2pipe struct {
+	mu       sync.Mutex
+	c        sync.Cond // c.L lazily initialized to &p.mu
+	b        http2pipeBuffer
+	err      error         // read error once empty. non-nil means closed.
+	breakErr error         // immediate read error (caller doesn't see rest of b)
+	donec    chan struct{} // closed on error
+	readFn   func()        // optional code to run in Read before error
+}
+
+type http2pipeBuffer interface {
+	Len() int
+	io.Writer
+	io.Reader
+}
+
+// Read waits until data is available and copies bytes
+// from the buffer into p.
+func (p *http2pipe) Read(d []byte) (n int, err error) {
+	p.mu.Lock()
+	defer p.mu.Unlock()
+	if p.c.L == nil {
+		p.c.L = &p.mu
+	}
+	for {
+		if p.breakErr != nil {
+			return 0, p.breakErr
+		}
+		if p.b.Len() > 0 {
+			return p.b.Read(d)
+		}
+		if p.err != nil {
+			if p.readFn != nil {
+				p.readFn()
+				p.readFn = nil
+			}
+			return 0, p.err
+		}
+		p.c.Wait()
+	}
+}
+
+var http2errClosedPipeWrite = errors.New("write on closed buffer")
+
+// Write copies bytes from p into the buffer and wakes a reader.
+// It is an error to write more data than the buffer can hold.
+func (p *http2pipe) Write(d []byte) (n int, err error) {
+	p.mu.Lock()
+	defer p.mu.Unlock()
+	if p.c.L == nil {
+		p.c.L = &p.mu
+	}
+	defer p.c.Signal()
+	if p.err != nil {
+		return 0, http2errClosedPipeWrite
+	}
+	return p.b.Write(d)
+}
+
+// CloseWithError causes the next Read (waking up a current blocked
+// Read if needed) to return the provided err after all data has been
+// read.
+//
+// The error must be non-nil.
+func (p *http2pipe) CloseWithError(err error) { p.closeWithError(&p.err, err, nil) }
+
+// BreakWithError causes the next Read (waking up a current blocked
+// Read if needed) to return the provided err immediately, without
+// waiting for unread data.
+func (p *http2pipe) BreakWithError(err error) { p.closeWithError(&p.breakErr, err, nil) }
+
+// closeWithErrorAndCode is like CloseWithError but also sets some code to run
+// in the caller's goroutine before returning the error.
+func (p *http2pipe) closeWithErrorAndCode(err error, fn func()) { p.closeWithError(&p.err, err, fn) }
+
+func (p *http2pipe) closeWithError(dst *error, err error, fn func()) {
+	if err == nil {
+		panic("err must be non-nil")
+	}
+	p.mu.Lock()
+	defer p.mu.Unlock()
+	if p.c.L == nil {
+		p.c.L = &p.mu
+	}
+	defer p.c.Signal()
+	if *dst != nil {
+
+		return
+	}
+	p.readFn = fn
+	*dst = err
+	p.closeDoneLocked()
+}
+
+// requires p.mu be held.
+func (p *http2pipe) closeDoneLocked() {
+	if p.donec == nil {
+		return
+	}
+
+	select {
+	case <-p.donec:
+	default:
+		close(p.donec)
+	}
+}
+
+// Err returns the error (if any) first set by BreakWithError or CloseWithError.
+func (p *http2pipe) Err() error {
+	p.mu.Lock()
+	defer p.mu.Unlock()
+	if p.breakErr != nil {
+		return p.breakErr
+	}
+	return p.err
+}
+
+// Done returns a channel which is closed if and when this pipe is closed
+// with CloseWithError.
+func (p *http2pipe) Done() <-chan struct{} {
+	p.mu.Lock()
+	defer p.mu.Unlock()
+	if p.donec == nil {
+		p.donec = make(chan struct{})
+		if p.err != nil || p.breakErr != nil {
+
+			p.closeDoneLocked()
+		}
+	}
+	return p.donec
+}
+
+const (
+	http2prefaceTimeout        = 10 * time.Second
+	http2firstSettingsTimeout  = 2 * time.Second // should be in-flight with preface anyway
+	http2handlerChunkWriteSize = 4 << 10
+	http2defaultMaxStreams     = 250 // TODO: make this 100 as the GFE seems to?
+)
+
+var (
+	http2errClientDisconnected = errors.New("client disconnected")
+	http2errClosedBody         = errors.New("body closed by handler")
+	http2errHandlerComplete    = errors.New("http2: request body closed due to handler exiting")
+	http2errStreamClosed       = errors.New("http2: stream closed")
+)
+
+var http2responseWriterStatePool = sync.Pool{
+	New: func() interface{} {
+		rws := &http2responseWriterState{}
+		rws.bw = bufio.NewWriterSize(http2chunkWriter{rws}, http2handlerChunkWriteSize)
+		return rws
+	},
+}
+
+// Test hooks.
+var (
+	http2testHookOnConn        func()
+	http2testHookGetServerConn func(*http2serverConn)
+	http2testHookOnPanicMu     *sync.Mutex // nil except in tests
+	http2testHookOnPanic       func(sc *http2serverConn, panicVal interface{}) (rePanic bool)
+)
+
+// Server is an HTTP/2 server.
+type http2Server struct {
+	// MaxHandlers limits the number of http.Handler ServeHTTP goroutines
+	// which may run at a time over all connections.
+	// Negative or zero no limit.
+	// TODO: implement
+	MaxHandlers int
+
+	// MaxConcurrentStreams optionally specifies the number of
+	// concurrent streams that each client may have open at a
+	// time. This is unrelated to the number of http.Handler goroutines
+	// which may be active globally, which is MaxHandlers.
+	// If zero, MaxConcurrentStreams defaults to at least 100, per
+	// the HTTP/2 spec's recommendations.
+	MaxConcurrentStreams uint32
+
+	// MaxReadFrameSize optionally specifies the largest frame
+	// this server is willing to read. A valid value is between
+	// 16k and 16M, inclusive. If zero or otherwise invalid, a
+	// default value is used.
+	MaxReadFrameSize uint32
+
+	// PermitProhibitedCipherSuites, if true, permits the use of
+	// cipher suites prohibited by the HTTP/2 spec.
+	PermitProhibitedCipherSuites bool
+}
+
+func (s *http2Server) maxReadFrameSize() uint32 {
+	if v := s.MaxReadFrameSize; v >= http2minMaxFrameSize && v <= http2maxFrameSize {
+		return v
+	}
+	return http2defaultMaxReadFrameSize
+}
+
+func (s *http2Server) maxConcurrentStreams() uint32 {
+	if v := s.MaxConcurrentStreams; v > 0 {
+		return v
+	}
+	return http2defaultMaxStreams
+}
+
+// ConfigureServer adds HTTP/2 support to a net/http Server.
+//
+// The configuration conf may be nil.
+//
+// ConfigureServer must be called before s begins serving.
+func http2ConfigureServer(s *Server, conf *http2Server) error {
+	if conf == nil {
+		conf = new(http2Server)
+	}
+
+	if s.TLSConfig == nil {
+		s.TLSConfig = new(tls.Config)
+	} else if s.TLSConfig.CipherSuites != nil {
+		// If they already provided a CipherSuite list, return
+		// an error if it has a bad order or is missing
+		// ECDHE_RSA_WITH_AES_128_GCM_SHA256.
+		const requiredCipher = tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+		haveRequired := false
+		sawBad := false
+		for i, cs := range s.TLSConfig.CipherSuites {
+			if cs == requiredCipher {
+				haveRequired = true
+			}
+			if http2isBadCipher(cs) {
+				sawBad = true
+			} else if sawBad {
+				return fmt.Errorf("http2: TLSConfig.CipherSuites index %d contains an HTTP/2-approved cipher suite (%#04x), but it comes after unapproved cipher suites. With this configuration, clients that don't support previous, approved cipher suites may be given an unapproved one and reject the connection.", i, cs)
+			}
+		}
+		if !haveRequired {
+			return fmt.Errorf("http2: TLSConfig.CipherSuites is missing HTTP/2-required TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")
+		}
+	}
+
+	s.TLSConfig.PreferServerCipherSuites = true
+
+	haveNPN := false
+	for _, p := range s.TLSConfig.NextProtos {
+		if p == http2NextProtoTLS {
+			haveNPN = true
+			break
+		}
+	}
+	if !haveNPN {
+		s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, http2NextProtoTLS)
+	}
+
+	s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, "h2-14")
+
+	if s.TLSNextProto == nil {
+		s.TLSNextProto = map[string]func(*Server, *tls.Conn, Handler){}
+	}
+	protoHandler := func(hs *Server, c *tls.Conn, h Handler) {
+		if http2testHookOnConn != nil {
+			http2testHookOnConn()
+		}
+		conf.ServeConn(c, &http2ServeConnOpts{
+			Handler:    h,
+			BaseConfig: hs,
+		})
+	}
+	s.TLSNextProto[http2NextProtoTLS] = protoHandler
+	s.TLSNextProto["h2-14"] = protoHandler
+	return nil
+}
+
+// ServeConnOpts are options for the Server.ServeConn method.
+type http2ServeConnOpts struct {
+	// BaseConfig optionally sets the base configuration
+	// for values. If nil, defaults are used.
+	BaseConfig *Server
+
+	// Handler specifies which handler to use for processing
+	// requests. If nil, BaseConfig.Handler is used. If BaseConfig
+	// or BaseConfig.Handler is nil, http.DefaultServeMux is used.
+	Handler Handler
+}
+
+func (o *http2ServeConnOpts) baseConfig() *Server {
+	if o != nil && o.BaseConfig != nil {
+		return o.BaseConfig
+	}
+	return new(Server)
+}
+
+func (o *http2ServeConnOpts) handler() Handler {
+	if o != nil {
+		if o.Handler != nil {
+			return o.Handler
+		}
+		if o.BaseConfig != nil && o.BaseConfig.Handler != nil {
+			return o.BaseConfig.Handler
+		}
+	}
+	return DefaultServeMux
+}
+
+// ServeConn serves HTTP/2 requests on the provided connection and
+// blocks until the connection is no longer readable.
+//
+// ServeConn starts speaking HTTP/2 assuming that c has not had any
+// reads or writes. It writes its initial settings frame and expects
+// to be able to read the preface and settings frame from the
+// client. If c has a ConnectionState method like a *tls.Conn, the
+// ConnectionState is used to verify the TLS ciphersuite and to set
+// the Request.TLS field in Handlers.
+//
+// ServeConn does not support h2c by itself. Any h2c support must be
+// implemented in terms of providing a suitably-behaving net.Conn.
+//
+// The opts parameter is optional. If nil, default values are used.
+func (s *http2Server) ServeConn(c net.Conn, opts *http2ServeConnOpts) {
+	sc := &http2serverConn{
+		srv:              s,
+		hs:               opts.baseConfig(),
+		conn:             c,
+		remoteAddrStr:    c.RemoteAddr().String(),
+		bw:               http2newBufferedWriter(c),
+		handler:          opts.handler(),
+		streams:          make(map[uint32]*http2stream),
+		readFrameCh:      make(chan http2readFrameResult),
+		wantWriteFrameCh: make(chan http2frameWriteMsg, 8),
+		wroteFrameCh:     make(chan http2frameWriteResult, 1),
+		bodyReadCh:       make(chan http2bodyReadMsg),
+		doneServing:      make(chan struct{}),
+		advMaxStreams:    s.maxConcurrentStreams(),
+		writeSched: http2writeScheduler{
+			maxFrameSize: http2initialMaxFrameSize,
+		},
+		initialWindowSize: http2initialWindowSize,
+		headerTableSize:   http2initialHeaderTableSize,
+		serveG:            http2newGoroutineLock(),
+		pushEnabled:       true,
+	}
+	sc.flow.add(http2initialWindowSize)
+	sc.inflow.add(http2initialWindowSize)
+	sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
+	sc.hpackDecoder = hpack.NewDecoder(http2initialHeaderTableSize, nil)
+	sc.hpackDecoder.SetMaxStringLength(sc.maxHeaderStringLen())
+
+	fr := http2NewFramer(sc.bw, c)
+	fr.SetMaxReadFrameSize(s.maxReadFrameSize())
+	sc.framer = fr
+
+	if tc, ok := c.(http2connectionStater); ok {
+		sc.tlsState = new(tls.ConnectionState)
+		*sc.tlsState = tc.ConnectionState()
+
+		if sc.tlsState.Version < tls.VersionTLS12 {
+			sc.rejectConn(http2ErrCodeInadequateSecurity, "TLS version too low")
+			return
+		}
+
+		if sc.tlsState.ServerName == "" {
+
+		}
+
+		if !s.PermitProhibitedCipherSuites && http2isBadCipher(sc.tlsState.CipherSuite) {
+
+			sc.rejectConn(http2ErrCodeInadequateSecurity, fmt.Sprintf("Prohibited TLS 1.2 Cipher Suite: %x", sc.tlsState.CipherSuite))
+			return
+		}
+	}
+
+	if hook := http2testHookGetServerConn; hook != nil {
+		hook(sc)
+	}
+	sc.serve()
+}
+
+// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
+func http2isBadCipher(cipher uint16) bool {
+	switch cipher {
+	case tls.TLS_RSA_WITH_RC4_128_SHA,
+		tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+		tls.TLS_RSA_WITH_AES_128_CBC_SHA,
+		tls.TLS_RSA_WITH_AES_256_CBC_SHA,
+		tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+		tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+		tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+		tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
+		tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+		tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+		tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+
+		return true
+	default:
+		return false
+	}
+}
+
+func (sc *http2serverConn) rejectConn(err http2ErrCode, debug string) {
+	sc.vlogf("http2: server rejecting conn: %v, %s", err, debug)
+
+	sc.framer.WriteGoAway(0, err, []byte(debug))
+	sc.bw.Flush()
+	sc.conn.Close()
+}
+
+type http2serverConn struct {
+	// Immutable:
+	srv              *http2Server
+	hs               *Server
+	conn             net.Conn
+	bw               *http2bufferedWriter // writing to conn
+	handler          Handler
+	framer           *http2Framer
+	hpackDecoder     *hpack.Decoder
+	doneServing      chan struct{}              // closed when serverConn.serve ends
+	readFrameCh      chan http2readFrameResult  // written by serverConn.readFrames
+	wantWriteFrameCh chan http2frameWriteMsg    // from handlers -> serve
+	wroteFrameCh     chan http2frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes
+	bodyReadCh       chan http2bodyReadMsg      // from handlers -> serve
+	testHookCh       chan func(int)             // code to run on the serve loop
+	flow             http2flow                  // conn-wide (not stream-specific) outbound flow control
+	inflow           http2flow                  // conn-wide inbound flow control
+	tlsState         *tls.ConnectionState       // shared by all handlers, like net/http
+	remoteAddrStr    string
+
+	// Everything following is owned by the serve loop; use serveG.check():
+	serveG                http2goroutineLock // used to verify funcs are on serve()
+	pushEnabled           bool
+	sawFirstSettings      bool // got the initial SETTINGS frame after the preface
+	needToSendSettingsAck bool
+	unackedSettings       int    // how many SETTINGS have we sent without ACKs?
+	clientMaxStreams      uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit)
+	advMaxStreams         uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client
+	curOpenStreams        uint32 // client's number of open streams
+	maxStreamID           uint32 // max ever seen
+	streams               map[uint32]*http2stream
+	initialWindowSize     int32
+	headerTableSize       uint32
+	peerMaxHeaderListSize uint32            // zero means unknown (default)
+	canonHeader           map[string]string // http2-lower-case -> Go-Canonical-Case
+	req                   http2requestParam // non-zero while reading request headers
+	writingFrame          bool              // started write goroutine but haven't heard back on wroteFrameCh
+	needsFrameFlush       bool              // last frame write wasn't a flush
+	writeSched            http2writeScheduler
+	inGoAway              bool // we've started to or sent GOAWAY
+	needToSendGoAway      bool // we need to schedule a GOAWAY frame write
+	goAwayCode            http2ErrCode
+	shutdownTimerCh       <-chan time.Time // nil until used
+	shutdownTimer         *time.Timer      // nil until used
+
+	// Owned by the writeFrameAsync goroutine:
+	headerWriteBuf bytes.Buffer
+	hpackEncoder   *hpack.Encoder
+}
+
+func (sc *http2serverConn) maxHeaderStringLen() int {
+	v := sc.maxHeaderListSize()
+	if uint32(int(v)) == v {
+		return int(v)
+	}
+
+	return 0
+}
+
+func (sc *http2serverConn) maxHeaderListSize() uint32 {
+	n := sc.hs.MaxHeaderBytes
+	if n <= 0 {
+		n = DefaultMaxHeaderBytes
+	}
+	// http2's count is in a slightly different unit and includes 32 bytes per pair.
+	// So, take the net/http.Server value and pad it up a bit, assuming 10 headers.
+	const perFieldOverhead = 32 // per http2 spec
+	const typicalHeaders = 10   // conservative
+	return uint32(n + typicalHeaders*perFieldOverhead)
+}
+
+// requestParam is the state of the next request, initialized over
+// potentially several frames HEADERS + zero or more CONTINUATION
+// frames.
+type http2requestParam struct {
+	// stream is non-nil if we're reading (HEADER or CONTINUATION)
+	// frames for a request (but not DATA).
+	stream            *http2stream
+	header            Header
+	method, path      string
+	scheme, authority string
+	sawRegularHeader  bool  // saw a non-pseudo header already
+	invalidHeader     bool  // an invalid header was seen
+	headerListSize    int64 // actually uint32, but easier math this way
+}
+
+// stream represents a stream. This is the minimal metadata needed by
+// the serve goroutine. Most of the actual stream state is owned by
+// the http.Handler's goroutine in the responseWriter. Because the
+// responseWriter's responseWriterState is recycled at the end of a
+// handler, this struct intentionally has no pointer to the
+// *responseWriter{,State} itself, as the Handler ending nils out the
+// responseWriter's state field.
+type http2stream struct {
+	// immutable:
+	sc   *http2serverConn
+	id   uint32
+	body *http2pipe       // non-nil if expecting DATA frames
+	cw   http2closeWaiter // closed wait stream transitions to closed state
+
+	// owned by serverConn's serve loop:
+	bodyBytes        int64        // body bytes seen so far
+	declBodyBytes    int64        // or -1 if undeclared
+	flow             http2flow    // limits writing from Handler to client
+	inflow           http2flow    // what the client is allowed to POST/etc to us
+	parent           *http2stream // or nil
+	numTrailerValues int64
+	weight           uint8
+	state            http2streamState
+	sentReset        bool // only true once detached from streams map
+	gotReset         bool // only true once detacted from streams map
+	gotTrailerHeader bool // HEADER frame for trailers was seen
+
+	trailer    Header // accumulated trailers
+	reqTrailer Header // handler's Request.Trailer
+}
+
+func (sc *http2serverConn) Framer() *http2Framer { return sc.framer }
+
+func (sc *http2serverConn) CloseConn() error { return sc.conn.Close() }
+
+func (sc *http2serverConn) Flush() error { return sc.bw.Flush() }
+
+func (sc *http2serverConn) HeaderEncoder() (*hpack.Encoder, *bytes.Buffer) {
+	return sc.hpackEncoder, &sc.headerWriteBuf
+}
+
+func (sc *http2serverConn) state(streamID uint32) (http2streamState, *http2stream) {
+	sc.serveG.check()
+
+	if st, ok := sc.streams[streamID]; ok {
+		return st.state, st
+	}
+
+	if streamID <= sc.maxStreamID {
+		return http2stateClosed, nil
+	}
+	return http2stateIdle, nil
+}
+
+// setConnState calls the net/http ConnState hook for this connection, if configured.
+// Note that the net/http package does StateNew and StateClosed for us.
+// There is currently no plan for StateHijacked or hijacking HTTP/2 connections.
+func (sc *http2serverConn) setConnState(state ConnState) {
+	if sc.hs.ConnState != nil {
+		sc.hs.ConnState(sc.conn, state)
+	}
+}
+
+func (sc *http2serverConn) vlogf(format string, args ...interface{}) {
+	if http2VerboseLogs {
+		sc.logf(format, args...)
+	}
+}
+
+func (sc *http2serverConn) logf(format string, args ...interface{}) {
+	if lg := sc.hs.ErrorLog; lg != nil {
+		lg.Printf(format, args...)
+	} else {
+		log.Printf(format, args...)
+	}
+}
+
+// errno returns v's underlying uintptr, else 0.
+//
+// TODO: remove this helper function once http2 can use build
+// tags. See comment in isClosedConnError.
+func http2errno(v error) uintptr {
+	if rv := reflect.ValueOf(v); rv.Kind() == reflect.Uintptr {
+		return uintptr(rv.Uint())
+	}
+	return 0
+}
+
+// isClosedConnError reports whether err is an error from use of a closed
+// network connection.
+func http2isClosedConnError(err error) bool {
+	if err == nil {
+		return false
+	}
+
+	str := err.Error()
+	if strings.Contains(str, "use of closed network connection") {
+		return true
+	}
+
+	if runtime.GOOS == "windows" {
+		if oe, ok := err.(*net.OpError); ok && oe.Op == "read" {
+			if se, ok := oe.Err.(*os.SyscallError); ok && se.Syscall == "wsarecv" {
+				const WSAECONNABORTED = 10053
+				const WSAECONNRESET = 10054
+				if n := http2errno(se.Err); n == WSAECONNRESET || n == WSAECONNABORTED {
+					return true
+				}
+			}
+		}
+	}
+	return false
+}
+
+func (sc *http2serverConn) condlogf(err error, format string, args ...interface{}) {
+	if err == nil {
+		return
+	}
+	if err == io.EOF || err == io.ErrUnexpectedEOF || http2isClosedConnError(err) {
+
+		sc.vlogf(format, args...)
+	} else {
+		sc.logf(format, args...)
+	}
+}
+
+func (sc *http2serverConn) onNewHeaderField(f hpack.HeaderField) {
+	sc.serveG.check()
+	if http2VerboseLogs {
+		sc.vlogf("http2: server decoded %v", f)
+	}
+	switch {
+	case !http2validHeaderFieldValue(f.Value):
+		sc.req.invalidHeader = true
+	case strings.HasPrefix(f.Name, ":"):
+		if sc.req.sawRegularHeader {
+			sc.logf("pseudo-header after regular header")
+			sc.req.invalidHeader = true
+			return
+		}
+		var dst *string
+		switch f.Name {
+		case ":method":
+			dst = &sc.req.method
+		case ":path":
+			dst = &sc.req.path
+		case ":scheme":
+			dst = &sc.req.scheme
+		case ":authority":
+			dst = &sc.req.authority
+		default:
+
+			sc.logf("invalid pseudo-header %q", f.Name)
+			sc.req.invalidHeader = true
+			return
+		}
+		if *dst != "" {
+			sc.logf("duplicate pseudo-header %q sent", f.Name)
+			sc.req.invalidHeader = true
+			return
+		}
+		*dst = f.Value
+	case !http2validHeaderFieldName(f.Name):
+		sc.req.invalidHeader = true
+	default:
+		sc.req.sawRegularHeader = true
+		sc.req.header.Add(sc.canonicalHeader(f.Name), f.Value)
+		const headerFieldOverhead = 32 // per spec
+		sc.req.headerListSize += int64(len(f.Name)) + int64(len(f.Value)) + headerFieldOverhead
+		if sc.req.headerListSize > int64(sc.maxHeaderListSize()) {
+			sc.hpackDecoder.SetEmitEnabled(false)
+		}
+	}
+}
+
+func (st *http2stream) onNewTrailerField(f hpack.HeaderField) {
+	sc := st.sc
+	sc.serveG.check()
+	if http2VerboseLogs {
+		sc.vlogf("http2: server decoded trailer %v", f)
+	}
+	switch {
+	case strings.HasPrefix(f.Name, ":"):
+		sc.req.invalidHeader = true
+		return
+	case !http2validHeaderFieldName(f.Name) || !http2validHeaderFieldValue(f.Value):
+		sc.req.invalidHeader = true
+		return
+	default:
+		key := sc.canonicalHeader(f.Name)
+		if st.trailer != nil {
+			vv := append(st.trailer[key], f.Value)
+			st.trailer[key] = vv
+
+			// arbitrary; TODO: read spec about header list size limits wrt trailers
+			const tooBig = 1000
+			if len(vv) >= tooBig {
+				sc.hpackDecoder.SetEmitEnabled(false)
+			}
+		}
+	}
+}
+
+func (sc *http2serverConn) canonicalHeader(v string) string {
+	sc.serveG.check()
+	cv, ok := http2commonCanonHeader[v]
+	if ok {
+		return cv
+	}
+	cv, ok = sc.canonHeader[v]
+	if ok {
+		return cv
+	}
+	if sc.canonHeader == nil {
+		sc.canonHeader = make(map[string]string)
+	}
+	cv = CanonicalHeaderKey(v)
+	sc.canonHeader[v] = cv
+	return cv
+}
+
+type http2readFrameResult struct {
+	f   http2Frame // valid until readMore is called
+	err error
+
+	// readMore should be called once the consumer no longer needs or
+	// retains f. After readMore, f is invalid and more frames can be
+	// read.
+	readMore func()
+}
+
+// readFrames is the loop that reads incoming frames.
+// It takes care to only read one frame at a time, blocking until the
+// consumer is done with the frame.
+// It's run on its own goroutine.
+func (sc *http2serverConn) readFrames() {
+	gate := make(http2gate)
+	for {
+		f, err := sc.framer.ReadFrame()
+		select {
+		case sc.readFrameCh <- http2readFrameResult{f, err, gate.Done}:
+		case <-sc.doneServing:
+			return
+		}
+		select {
+		case <-gate:
+		case <-sc.doneServing:
+			return
+		}
+		if http2terminalReadFrameError(err) {
+			return
+		}
+	}
+}
+
+// frameWriteResult is the message passed from writeFrameAsync to the serve goroutine.
+type http2frameWriteResult struct {
+	wm  http2frameWriteMsg // what was written (or attempted)
+	err error              // result of the writeFrame call
+}
+
+// writeFrameAsync runs in its own goroutine and writes a single frame
+// and then reports when it's done.
+// At most one goroutine can be running writeFrameAsync at a time per
+// serverConn.
+func (sc *http2serverConn) writeFrameAsync(wm http2frameWriteMsg) {
+	err := wm.write.writeFrame(sc)
+	sc.wroteFrameCh <- http2frameWriteResult{wm, err}
+}
+
+func (sc *http2serverConn) closeAllStreamsOnConnClose() {
+	sc.serveG.check()
+	for _, st := range sc.streams {
+		sc.closeStream(st, http2errClientDisconnected)
+	}
+}
+
+func (sc *http2serverConn) stopShutdownTimer() {
+	sc.serveG.check()
+	if t := sc.shutdownTimer; t != nil {
+		t.Stop()
+	}
+}
+
+func (sc *http2serverConn) notePanic() {
+
+	if http2testHookOnPanicMu != nil {
+		http2testHookOnPanicMu.Lock()
+		defer http2testHookOnPanicMu.Unlock()
+	}
+	if http2testHookOnPanic != nil {
+		if e := recover(); e != nil {
+			if http2testHookOnPanic(sc, e) {
+				panic(e)
+			}
+		}
+	}
+}
+
+func (sc *http2serverConn) serve() {
+	sc.serveG.check()
+	defer sc.notePanic()
+	defer sc.conn.Close()
+	defer sc.closeAllStreamsOnConnClose()
+	defer sc.stopShutdownTimer()
+	defer close(sc.doneServing)
+
+	if http2VerboseLogs {
+		sc.vlogf("http2: server connection from %v on %p", sc.conn.RemoteAddr(), sc.hs)
+	}
+
+	sc.writeFrame(http2frameWriteMsg{
+		write: http2writeSettings{
+			{http2SettingMaxFrameSize, sc.srv.maxReadFrameSize()},
+			{http2SettingMaxConcurrentStreams, sc.advMaxStreams},
+			{http2SettingMaxHeaderListSize, sc.maxHeaderListSize()},
+		},
+	})
+	sc.unackedSettings++
+
+	if err := sc.readPreface(); err != nil {
+		sc.condlogf(err, "http2: server: error reading preface from client %v: %v", sc.conn.RemoteAddr(), err)
+		return
+	}
+
+	sc.setConnState(StateActive)
+	sc.setConnState(StateIdle)
+
+	go sc.readFrames()
+
+	settingsTimer := time.NewTimer(http2firstSettingsTimeout)
+	loopNum := 0
+	for {
+		loopNum++
+		select {
+		case wm := <-sc.wantWriteFrameCh:
+			sc.writeFrame(wm)
+		case res := <-sc.wroteFrameCh:
+			sc.wroteFrame(res)
+		case res := <-sc.readFrameCh:
+			if !sc.processFrameFromReader(res) {
+				return
+			}
+			res.readMore()
+			if settingsTimer.C != nil {
+				settingsTimer.Stop()
+				settingsTimer.C = nil
+			}
+		case m := <-sc.bodyReadCh:
+			sc.noteBodyRead(m.st, m.n)
+		case <-settingsTimer.C:
+			sc.logf("timeout waiting for SETTINGS frames from %v", sc.conn.RemoteAddr())
+			return
+		case <-sc.shutdownTimerCh:
+			sc.vlogf("GOAWAY close timer fired; closing conn from %v", sc.conn.RemoteAddr())
+			return
+		case fn := <-sc.testHookCh:
+			fn(loopNum)
+		}
+	}
+}
+
+// readPreface reads the ClientPreface greeting from the peer
+// or returns an error on timeout or an invalid greeting.
+func (sc *http2serverConn) readPreface() error {
+	errc := make(chan error, 1)
+	go func() {
+
+		buf := make([]byte, len(http2ClientPreface))
+		if _, err := io.ReadFull(sc.conn, buf); err != nil {
+			errc <- err
+		} else if !bytes.Equal(buf, http2clientPreface) {
+			errc <- fmt.Errorf("bogus greeting %q", buf)
+		} else {
+			errc <- nil
+		}
+	}()
+	timer := time.NewTimer(http2prefaceTimeout)
+	defer timer.Stop()
+	select {
+	case <-timer.C:
+		return errors.New("timeout waiting for client preface")
+	case err := <-errc:
+		if err == nil {
+			if http2VerboseLogs {
+				sc.vlogf("http2: server: client %v said hello", sc.conn.RemoteAddr())
+			}
+		}
+		return err
+	}
+}
+
+var http2errChanPool = sync.Pool{
+	New: func() interface{} { return make(chan error, 1) },
+}
+
+var http2writeDataPool = sync.Pool{
+	New: func() interface{} { return new(http2writeData) },
+}
+
+// writeDataFromHandler writes DATA response frames from a handler on
+// the given stream.
+func (sc *http2serverConn) writeDataFromHandler(stream *http2stream, data []byte, endStream bool) error {
+	ch := http2errChanPool.Get().(chan error)
+	writeArg := http2writeDataPool.Get().(*http2writeData)
+	*writeArg = http2writeData{stream.id, data, endStream}
+	err := sc.writeFrameFromHandler(http2frameWriteMsg{
+		write:  writeArg,
+		stream: stream,
+		done:   ch,
+	})
+	if err != nil {
+		return err
+	}
+	var frameWriteDone bool // the frame write is done (successfully or not)
+	select {
+	case err = <-ch:
+		frameWriteDone = true
+	case <-sc.doneServing:
+		return http2errClientDisconnected
+	case <-stream.cw:
+
+		select {
+		case err = <-ch:
+			frameWriteDone = true
+		default:
+			return http2errStreamClosed
+		}
+	}
+	http2errChanPool.Put(ch)
+	if frameWriteDone {
+		http2writeDataPool.Put(writeArg)
+	}
+	return err
+}
+
+// writeFrameFromHandler sends wm to sc.wantWriteFrameCh, but aborts
+// if the connection has gone away.
+//
+// This must not be run from the serve goroutine itself, else it might
+// deadlock writing to sc.wantWriteFrameCh (which is only mildly
+// buffered and is read by serve itself). If you're on the serve
+// goroutine, call writeFrame instead.
+func (sc *http2serverConn) writeFrameFromHandler(wm http2frameWriteMsg) error {
+	sc.serveG.checkNotOn()
+	select {
+	case sc.wantWriteFrameCh <- wm:
+		return nil
+	case <-sc.doneServing:
+
+		return http2errClientDisconnected
+	}
+}
+
+// writeFrame schedules a frame to write and sends it if there's nothing
+// already being written.
+//
+// There is no pushback here (the serve goroutine never blocks). It's
+// the http.Handlers that block, waiting for their previous frames to
+// make it onto the wire
+//
+// If you're not on the serve goroutine, use writeFrameFromHandler instead.
+func (sc *http2serverConn) writeFrame(wm http2frameWriteMsg) {
+	sc.serveG.check()
+	sc.writeSched.add(wm)
+	sc.scheduleFrameWrite()
+}
+
+// startFrameWrite starts a goroutine to write wm (in a separate
+// goroutine since that might block on the network), and updates the
+// serve goroutine's state about the world, updated from info in wm.
+func (sc *http2serverConn) startFrameWrite(wm http2frameWriteMsg) {
+	sc.serveG.check()
+	if sc.writingFrame {
+		panic("internal error: can only be writing one frame at a time")
+	}
+
+	st := wm.stream
+	if st != nil {
+		switch st.state {
+		case http2stateHalfClosedLocal:
+			panic("internal error: attempt to send frame on half-closed-local stream")
+		case http2stateClosed:
+			if st.sentReset || st.gotReset {
+
+				sc.scheduleFrameWrite()
+				return
+			}
+			panic(fmt.Sprintf("internal error: attempt to send a write %v on a closed stream", wm))
+		}
+	}
+
+	sc.writingFrame = true
+	sc.needsFrameFlush = true
+	go sc.writeFrameAsync(wm)
+}
+
+// errHandlerPanicked is the error given to any callers blocked in a read from
+// Request.Body when the main goroutine panics. Since most handlers read in the
+// the main ServeHTTP goroutine, this will show up rarely.
+var http2errHandlerPanicked = errors.New("http2: handler panicked")
+
+// wroteFrame is called on the serve goroutine with the result of
+// whatever happened on writeFrameAsync.
+func (sc *http2serverConn) wroteFrame(res http2frameWriteResult) {
+	sc.serveG.check()
+	if !sc.writingFrame {
+		panic("internal error: expected to be already writing a frame")
+	}
+	sc.writingFrame = false
+
+	wm := res.wm
+	st := wm.stream
+
+	closeStream := http2endsStream(wm.write)
+
+	if _, ok := wm.write.(http2handlerPanicRST); ok {
+		sc.closeStream(st, http2errHandlerPanicked)
+	}
+
+	if ch := wm.done; ch != nil {
+		select {
+		case ch <- res.err:
+		default:
+			panic(fmt.Sprintf("unbuffered done channel passed in for type %T", wm.write))
+		}
+	}
+	wm.write = nil
+
+	if closeStream {
+		if st == nil {
+			panic("internal error: expecting non-nil stream")
+		}
+		switch st.state {
+		case http2stateOpen:
+
+			st.state = http2stateHalfClosedLocal
+			errCancel := http2StreamError{st.id, http2ErrCodeCancel}
+			sc.resetStream(errCancel)
+		case http2stateHalfClosedRemote:
+			sc.closeStream(st, http2errHandlerComplete)
+		}
+	}
+
+	sc.scheduleFrameWrite()
+}
+
+// scheduleFrameWrite tickles the frame writing scheduler.
+//
+// If a frame is already being written, nothing happens. This will be called again
+// when the frame is done being written.
+//
+// If a frame isn't being written we need to send one, the best frame
+// to send is selected, preferring first things that aren't
+// stream-specific (e.g. ACKing settings), and then finding the
+// highest priority stream.
+//
+// If a frame isn't being written and there's nothing else to send, we
+// flush the write buffer.
+func (sc *http2serverConn) scheduleFrameWrite() {
+	sc.serveG.check()
+	if sc.writingFrame {
+		return
+	}
+	if sc.needToSendGoAway {
+		sc.needToSendGoAway = false
+		sc.startFrameWrite(http2frameWriteMsg{
+			write: &http2writeGoAway{
+				maxStreamID: sc.maxStreamID,
+				code:        sc.goAwayCode,
+			},
+		})
+		return
+	}
+	if sc.needToSendSettingsAck {
+		sc.needToSendSettingsAck = false
+		sc.startFrameWrite(http2frameWriteMsg{write: http2writeSettingsAck{}})
+		return
+	}
+	if !sc.inGoAway {
+		if wm, ok := sc.writeSched.take(); ok {
+			sc.startFrameWrite(wm)
+			return
+		}
+	}
+	if sc.needsFrameFlush {
+		sc.startFrameWrite(http2frameWriteMsg{write: http2flushFrameWriter{}})
+		sc.needsFrameFlush = false
+		return
+	}
+}
+
+func (sc *http2serverConn) goAway(code http2ErrCode) {
+	sc.serveG.check()
+	if sc.inGoAway {
+		return
+	}
+	if code != http2ErrCodeNo {
+		sc.shutDownIn(250 * time.Millisecond)
+	} else {
+
+		sc.shutDownIn(1 * time.Second)
+	}
+	sc.inGoAway = true
+	sc.needToSendGoAway = true
+	sc.goAwayCode = code
+	sc.scheduleFrameWrite()
+}
+
+func (sc *http2serverConn) shutDownIn(d time.Duration) {
+	sc.serveG.check()
+	sc.shutdownTimer = time.NewTimer(d)
+	sc.shutdownTimerCh = sc.shutdownTimer.C
+}
+
+func (sc *http2serverConn) resetStream(se http2StreamError) {
+	sc.serveG.check()
+	sc.writeFrame(http2frameWriteMsg{write: se})
+	if st, ok := sc.streams[se.StreamID]; ok {
+		st.sentReset = true
+		sc.closeStream(st, se)
+	}
+}
+
+// processFrameFromReader processes the serve loop's read from readFrameCh from the
+// frame-reading goroutine.
+// processFrameFromReader returns whether the connection should be kept open.
+func (sc *http2serverConn) processFrameFromReader(res http2readFrameResult) bool {
+	sc.serveG.check()
+	err := res.err
+	if err != nil {
+		if err == http2ErrFrameTooLarge {
+			sc.goAway(http2ErrCodeFrameSize)
+			return true
+		}
+		clientGone := err == io.EOF || err == io.ErrUnexpectedEOF || http2isClosedConnError(err)
+		if clientGone {
+
+			return false
+		}
+	} else {
+		f := res.f
+		if http2VerboseLogs {
+			sc.vlogf("http2: server read frame %v", http2summarizeFrame(f))
+		}
+		err = sc.processFrame(f)
+		if err == nil {
+			return true
+		}
+	}
+
+	switch ev := err.(type) {
+	case http2StreamError:
+		sc.resetStream(ev)
+		return true
+	case http2goAwayFlowError:
+		sc.goAway(http2ErrCodeFlowControl)
+		return true
+	case http2ConnectionError:
+		sc.logf("http2: server connection error from %v: %v", sc.conn.RemoteAddr(), ev)
+		sc.goAway(http2ErrCode(ev))
+		return true
+	default:
+		if res.err != nil {
+			sc.vlogf("http2: server closing client connection; error reading frame from client %s: %v", sc.conn.RemoteAddr(), err)
+		} else {
+			sc.logf("http2: server closing client connection: %v", err)
+		}
+		return false
+	}
+}
+
+func (sc *http2serverConn) processFrame(f http2Frame) error {
+	sc.serveG.check()
+
+	if !sc.sawFirstSettings {
+		if _, ok := f.(*http2SettingsFrame); !ok {
+			return http2ConnectionError(http2ErrCodeProtocol)
+		}
+		sc.sawFirstSettings = true
+	}
+
+	switch f := f.(type) {
+	case *http2SettingsFrame:
+		return sc.processSettings(f)
+	case *http2HeadersFrame:
+		return sc.processHeaders(f)
+	case *http2ContinuationFrame:
+		return sc.processContinuation(f)
+	case *http2WindowUpdateFrame:
+		return sc.processWindowUpdate(f)
+	case *http2PingFrame:
+		return sc.processPing(f)
+	case *http2DataFrame:
+		return sc.processData(f)
+	case *http2RSTStreamFrame:
+		return sc.processResetStream(f)
+	case *http2PriorityFrame:
+		return sc.processPriority(f)
+	case *http2PushPromiseFrame:
+
+		return http2ConnectionError(http2ErrCodeProtocol)
+	default:
+		sc.vlogf("http2: server ignoring frame: %v", f.Header())
+		return nil
+	}
+}
+
+func (sc *http2serverConn) processPing(f *http2PingFrame) error {
+	sc.serveG.check()
+	if f.IsAck() {
+
+		return nil
+	}
+	if f.StreamID != 0 {
+
+		return http2ConnectionError(http2ErrCodeProtocol)
+	}
+	sc.writeFrame(http2frameWriteMsg{write: http2writePingAck{f}})
+	return nil
+}
+
+func (sc *http2serverConn) processWindowUpdate(f *http2WindowUpdateFrame) error {
+	sc.serveG.check()
+	switch {
+	case f.StreamID != 0:
+		st := sc.streams[f.StreamID]
+		if st == nil {
+
+			return nil
+		}
+		if !st.flow.add(int32(f.Increment)) {
+			return http2StreamError{f.StreamID, http2ErrCodeFlowControl}
+		}
+	default:
+		if !sc.flow.add(int32(f.Increment)) {
+			return http2goAwayFlowError{}
+		}
+	}
+	sc.scheduleFrameWrite()
+	return nil
+}
+
+func (sc *http2serverConn) processResetStream(f *http2RSTStreamFrame) error {
+	sc.serveG.check()
+
+	state, st := sc.state(f.StreamID)
+	if state == http2stateIdle {
+
+		return http2ConnectionError(http2ErrCodeProtocol)
+	}
+	if st != nil {
+		st.gotReset = true
+		sc.closeStream(st, http2StreamError{f.StreamID, f.ErrCode})
+	}
+	return nil
+}
+
+func (sc *http2serverConn) closeStream(st *http2stream, err error) {
+	sc.serveG.check()
+	if st.state == http2stateIdle || st.state == http2stateClosed {
+		panic(fmt.Sprintf("invariant; can't close stream in state %v", st.state))
+	}
+	st.state = http2stateClosed
+	sc.curOpenStreams--
+	if sc.curOpenStreams == 0 {
+		sc.setConnState(StateIdle)
+	}
+	delete(sc.streams, st.id)
+	if p := st.body; p != nil {
+		p.CloseWithError(err)
+	}
+	st.cw.Close()
+	sc.writeSched.forgetStream(st.id)
+}
+
+func (sc *http2serverConn) processSettings(f *http2SettingsFrame) error {
+	sc.serveG.check()
+	if f.IsAck() {
+		sc.unackedSettings--
+		if sc.unackedSettings < 0 {
+
+			return http2ConnectionError(http2ErrCodeProtocol)
+		}
+		return nil
+	}
+	if err := f.ForeachSetting(sc.processSetting); err != nil {
+		return err
+	}
+	sc.needToSendSettingsAck = true
+	sc.scheduleFrameWrite()
+	return nil
+}
+
+func (sc *http2serverConn) processSetting(s http2Setting) error {
+	sc.serveG.check()
+	if err := s.Valid(); err != nil {
+		return err
+	}
+	if http2VerboseLogs {
+		sc.vlogf("http2: server processing setting %v", s)
+	}
+	switch s.ID {
+	case http2SettingHeaderTableSize:
+		sc.headerTableSize = s.Val
+		sc.hpackEncoder.SetMaxDynamicTableSize(s.Val)
+	case http2SettingEnablePush:
+		sc.pushEnabled = s.Val != 0
+	case http2SettingMaxConcurrentStreams:
+		sc.clientMaxStreams = s.Val
+	case http2SettingInitialWindowSize:
+		return sc.processSettingInitialWindowSize(s.Val)
+	case http2SettingMaxFrameSize:
+		sc.writeSched.maxFrameSize = s.Val
+	case http2SettingMaxHeaderListSize:
+		sc.peerMaxHeaderListSize = s.Val
+	default:
+
+		if http2VerboseLogs {
+			sc.vlogf("http2: server ignoring unknown setting %v", s)
+		}
+	}
+	return nil
+}
+
+func (sc *http2serverConn) processSettingInitialWindowSize(val uint32) error {
+	sc.serveG.check()
+
+	old := sc.initialWindowSize
+	sc.initialWindowSize = int32(val)
+	growth := sc.initialWindowSize - old
+	for _, st := range sc.streams {
+		if !st.flow.add(growth) {
+
+			return http2ConnectionError(http2ErrCodeFlowControl)
+		}
+	}
+	return nil
+}
+
+func (sc *http2serverConn) processData(f *http2DataFrame) error {
+	sc.serveG.check()
+
+	id := f.Header().StreamID
+	st, ok := sc.streams[id]
+	if !ok || st.state != http2stateOpen || st.gotTrailerHeader {
+
+		return http2StreamError{id, http2ErrCodeStreamClosed}
+	}
+	if st.body == nil {
+		panic("internal error: should have a body in this state")
+	}
+	data := f.Data()
+
+	if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes {
+		st.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes))
+		return http2StreamError{id, http2ErrCodeStreamClosed}
+	}
+	if len(data) > 0 {
+
+		if int(st.inflow.available()) < len(data) {
+			return http2StreamError{id, http2ErrCodeFlowControl}
+		}
+		st.inflow.take(int32(len(data)))
+		wrote, err := st.body.Write(data)
+		if err != nil {
+			return http2StreamError{id, http2ErrCodeStreamClosed}
+		}
+		if wrote != len(data) {
+			panic("internal error: bad Writer")
+		}
+		st.bodyBytes += int64(len(data))
+	}
+	if f.StreamEnded() {
+		st.endStream()
+	}
+	return nil
+}
+
+// endStream closes a Request.Body's pipe. It is called when a DATA
+// frame says a request body is over (or after trailers).
+func (st *http2stream) endStream() {
+	sc := st.sc
+	sc.serveG.check()
+
+	if st.declBodyBytes != -1 && st.declBodyBytes != st.bodyBytes {
+		st.body.CloseWithError(fmt.Errorf("request declared a Content-Length of %d but only wrote %d bytes",
+			st.declBodyBytes, st.bodyBytes))
+	} else {
+		st.body.closeWithErrorAndCode(io.EOF, st.copyTrailersToHandlerRequest)
+		st.body.CloseWithError(io.EOF)
+	}
+	st.state = http2stateHalfClosedRemote
+}
+
+// copyTrailersToHandlerRequest is run in the Handler's goroutine in
+// its Request.Body.Read just before it gets io.EOF.
+func (st *http2stream) copyTrailersToHandlerRequest() {
+	for k, vv := range st.trailer {
+		if _, ok := st.reqTrailer[k]; ok {
+
+			st.reqTrailer[k] = vv
+		}
+	}
+}
+
+func (sc *http2serverConn) processHeaders(f *http2HeadersFrame) error {
+	sc.serveG.check()
+	id := f.Header().StreamID
+	if sc.inGoAway {
+
+		return nil
+	}
+
+	if id%2 != 1 {
+		return http2ConnectionError(http2ErrCodeProtocol)
+	}
+
+	st := sc.streams[f.Header().StreamID]
+	if st != nil {
+		return st.processTrailerHeaders(f)
+	}
+
+	if id <= sc.maxStreamID || sc.req.stream != nil {
+		return http2ConnectionError(http2ErrCodeProtocol)
+	}
+
+	if id > sc.maxStreamID {
+		sc.maxStreamID = id
+	}
+	st = &http2stream{
+		sc:    sc,
+		id:    id,
+		state: http2stateOpen,
+	}
+	if f.StreamEnded() {
+		st.state = http2stateHalfClosedRemote
+	}
+	st.cw.Init()
+
+	st.flow.conn = &sc.flow
+	st.flow.add(sc.initialWindowSize)
+	st.inflow.conn = &sc.inflow
+	st.inflow.add(http2initialWindowSize)
+
+	sc.streams[id] = st
+	if f.HasPriority() {
+		http2adjustStreamPriority(sc.streams, st.id, f.Priority)
+	}
+	sc.curOpenStreams++
+	if sc.curOpenStreams == 1 {
+		sc.setConnState(StateActive)
+	}
+	sc.req = http2requestParam{
+		stream: st,
+		header: make(Header),
+	}
+	sc.hpackDecoder.SetEmitFunc(sc.onNewHeaderField)
+	sc.hpackDecoder.SetEmitEnabled(true)
+	return sc.processHeaderBlockFragment(st, f.HeaderBlockFragment(), f.HeadersEnded())
+}
+
+func (st *http2stream) processTrailerHeaders(f *http2HeadersFrame) error {
+	sc := st.sc
+	sc.serveG.check()
+	if st.gotTrailerHeader {
+		return http2ConnectionError(http2ErrCodeProtocol)
+	}
+	st.gotTrailerHeader = true
+	if !f.StreamEnded() {
+		return http2StreamError{st.id, http2ErrCodeProtocol}
+	}
+	sc.resetPendingRequest()
+	return st.processTrailerHeaderBlockFragment(f.HeaderBlockFragment(), f.HeadersEnded())
+}
+
+func (sc *http2serverConn) processContinuation(f *http2ContinuationFrame) error {
+	sc.serveG.check()
+	st := sc.streams[f.Header().StreamID]
+	if st.gotTrailerHeader {
+		return st.processTrailerHeaderBlockFragment(f.HeaderBlockFragment(), f.HeadersEnded())
+	}
+	return sc.processHeaderBlockFragment(st, f.HeaderBlockFragment(), f.HeadersEnded())
+}
+
+func (sc *http2serverConn) processHeaderBlockFragment(st *http2stream, frag []byte, end bool) error {
+	sc.serveG.check()
+	if _, err := sc.hpackDecoder.Write(frag); err != nil {
+		return http2ConnectionError(http2ErrCodeCompression)
+	}
+	if !end {
+		return nil
+	}
+	if err := sc.hpackDecoder.Close(); err != nil {
+		return http2ConnectionError(http2ErrCodeCompression)
+	}
+	defer sc.resetPendingRequest()
+	if sc.curOpenStreams > sc.advMaxStreams {
+
+		if sc.unackedSettings == 0 {
+
+			return http2StreamError{st.id, http2ErrCodeProtocol}
+		}
+
+		return http2StreamError{st.id, http2ErrCodeRefusedStream}
+	}
+
+	rw, req, err := sc.newWriterAndRequest()
+	if err != nil {
+		return err
+	}
+	st.reqTrailer = req.Trailer
+	if st.reqTrailer != nil {
+		st.trailer = make(Header)
+	}
+	st.body = req.Body.(*http2requestBody).pipe
+	st.declBodyBytes = req.ContentLength
+
+	handler := sc.handler.ServeHTTP
+	if !sc.hpackDecoder.EmitEnabled() {
+
+		handler = http2handleHeaderListTooLong
+	}
+
+	go sc.runHandler(rw, req, handler)
+	return nil
+}
+
+func (st *http2stream) processTrailerHeaderBlockFragment(frag []byte, end bool) error {
+	sc := st.sc
+	sc.serveG.check()
+	sc.hpackDecoder.SetEmitFunc(st.onNewTrailerField)
+	if _, err := sc.hpackDecoder.Write(frag); err != nil {
+		return http2ConnectionError(http2ErrCodeCompression)
+	}
+	if !end {
+		return nil
+	}
+
+	rp := &sc.req
+	if rp.invalidHeader {
+		return http2StreamError{rp.stream.id, http2ErrCodeProtocol}
+	}
+
+	err := sc.hpackDecoder.Close()
+	st.endStream()
+	if err != nil {
+		return http2ConnectionError(http2ErrCodeCompression)
+	}
+	return nil
+}
+
+func (sc *http2serverConn) processPriority(f *http2PriorityFrame) error {
+	http2adjustStreamPriority(sc.streams, f.StreamID, f.http2PriorityParam)
+	return nil
+}
+
+func http2adjustStreamPriority(streams map[uint32]*http2stream, streamID uint32, priority http2PriorityParam) {
+	st, ok := streams[streamID]
+	if !ok {
+
+		return
+	}
+	st.weight = priority.Weight
+	parent := streams[priority.StreamDep]
+	if parent == st {
+
+		return
+	}
+
+	for piter := parent; piter != nil; piter = piter.parent {
+		if piter == st {
+			parent.parent = st.parent
+			break
+		}
+	}
+	st.parent = parent
+	if priority.Exclusive && (st.parent != nil || priority.StreamDep == 0) {
+		for _, openStream := range streams {
+			if openStream != st && openStream.parent == st.parent {
+				openStream.parent = st
+			}
+		}
+	}
+}
+
+// resetPendingRequest zeros out all state related to a HEADERS frame
+// and its zero or more CONTINUATION frames sent to start a new
+// request.
+func (sc *http2serverConn) resetPendingRequest() {
+	sc.serveG.check()
+	sc.req = http2requestParam{}
+}
+
+func (sc *http2serverConn) newWriterAndRequest() (*http2responseWriter, *Request, error) {
+	sc.serveG.check()
+	rp := &sc.req
+
+	if rp.invalidHeader {
+		return nil, nil, http2StreamError{rp.stream.id, http2ErrCodeProtocol}
+	}
+
+	isConnect := rp.method == "CONNECT"
+	if isConnect {
+		if rp.path != "" || rp.scheme != "" || rp.authority == "" {
+			return nil, nil, http2StreamError{rp.stream.id, http2ErrCodeProtocol}
+		}
+	} else if rp.method == "" || rp.path == "" ||
+		(rp.scheme != "https" && rp.scheme != "http") {
+
+		return nil, nil, http2StreamError{rp.stream.id, http2ErrCodeProtocol}
+	}
+
+	bodyOpen := rp.stream.state == http2stateOpen
+	if rp.method == "HEAD" && bodyOpen {
+
+		return nil, nil, http2StreamError{rp.stream.id, http2ErrCodeProtocol}
+	}
+	var tlsState *tls.ConnectionState // nil if not scheme https
+
+	if rp.scheme == "https" {
+		tlsState = sc.tlsState
+	}
+	authority := rp.authority
+	if authority == "" {
+		authority = rp.header.Get("Host")
+	}
+	needsContinue := rp.header.Get("Expect") == "100-continue"
+	if needsContinue {
+		rp.header.Del("Expect")
+	}
+
+	if cookies := rp.header["Cookie"]; len(cookies) > 1 {
+		rp.header.Set("Cookie", strings.Join(cookies, "; "))
+	}
+
+	// Setup Trailers
+	var trailer Header
+	for _, v := range rp.header["Trailer"] {
+		for _, key := range strings.Split(v, ",") {
+			key = CanonicalHeaderKey(strings.TrimSpace(key))
+			switch key {
+			case "Transfer-Encoding", "Trailer", "Content-Length":
+
+			default:
+				if trailer == nil {
+					trailer = make(Header)
+				}
+				trailer[key] = nil
+			}
+		}
+	}
+	delete(rp.header, "Trailer")
+
+	body := &http2requestBody{
+		conn:          sc,
+		stream:        rp.stream,
+		needsContinue: needsContinue,
+	}
+	var url_ *url.URL
+	var requestURI string
+	if isConnect {
+		url_ = &url.URL{Host: rp.authority}
+		requestURI = rp.authority
+	} else {
+		var err error
+		url_, err = url.ParseRequestURI(rp.path)
+		if err != nil {
+			return nil, nil, http2StreamError{rp.stream.id, http2ErrCodeProtocol}
+		}
+		requestURI = rp.path
+	}
+	req := &Request{
+		Method:     rp.method,
+		URL:        url_,
+		RemoteAddr: sc.remoteAddrStr,
+		Header:     rp.header,
+		RequestURI: requestURI,
+		Proto:      "HTTP/2.0",
+		ProtoMajor: 2,
+		ProtoMinor: 0,
+		TLS:        tlsState,
+		Host:       authority,
+		Body:       body,
+		Trailer:    trailer,
+	}
+	if bodyOpen {
+		body.pipe = &http2pipe{
+			b: &http2fixedBuffer{buf: make([]byte, http2initialWindowSize)},
+		}
+
+		if vv, ok := rp.header["Content-Length"]; ok {
+			req.ContentLength, _ = strconv.ParseInt(vv[0], 10, 64)
+		} else {
+			req.ContentLength = -1
+		}
+	}
+
+	rws := http2responseWriterStatePool.Get().(*http2responseWriterState)
+	bwSave := rws.bw
+	*rws = http2responseWriterState{}
+	rws.conn = sc
+	rws.bw = bwSave
+	rws.bw.Reset(http2chunkWriter{rws})
+	rws.stream = rp.stream
+	rws.req = req
+	rws.body = body
+
+	rw := &http2responseWriter{rws: rws}
+	return rw, req, nil
+}
+
+// Run on its own goroutine.
+func (sc *http2serverConn) runHandler(rw *http2responseWriter, req *Request, handler func(ResponseWriter, *Request)) {
+	didPanic := true
+	defer func() {
+		if didPanic {
+			e := recover()
+			// Same as net/http:
+			const size = 64 << 10
+			buf := make([]byte, size)
+			buf = buf[:runtime.Stack(buf, false)]
+			sc.writeFrameFromHandler(http2frameWriteMsg{
+				write:  http2handlerPanicRST{rw.rws.stream.id},
+				stream: rw.rws.stream,
+			})
+			sc.logf("http2: panic serving %v: %v\n%s", sc.conn.RemoteAddr(), e, buf)
+			return
+		}
+		rw.handlerDone()
+	}()
+	handler(rw, req)
+	didPanic = false
+}
+
+func http2handleHeaderListTooLong(w ResponseWriter, r *Request) {
+	// 10.5.1 Limits on Header Block Size:
+	// .. "A server that receives a larger header block than it is
+	// willing to handle can send an HTTP 431 (Request Header Fields Too
+	// Large) status code"
+	const statusRequestHeaderFieldsTooLarge = 431 // only in Go 1.6+
+	w.WriteHeader(statusRequestHeaderFieldsTooLarge)
+	io.WriteString(w, "<h1>HTTP Error 431</h1><p>Request Header Field(s) Too Large</p>")
+}
+
+// called from handler goroutines.
+// h may be nil.
+func (sc *http2serverConn) writeHeaders(st *http2stream, headerData *http2writeResHeaders) error {
+	sc.serveG.checkNotOn()
+	var errc chan error
+	if headerData.h != nil {
+
+		errc = http2errChanPool.Get().(chan error)
+	}
+	if err := sc.writeFrameFromHandler(http2frameWriteMsg{
+		write:  headerData,
+		stream: st,
+		done:   errc,
+	}); err != nil {
+		return err
+	}
+	if errc != nil {
+		select {
+		case err := <-errc:
+			http2errChanPool.Put(errc)
+			return err
+		case <-sc.doneServing:
+			return http2errClientDisconnected
+		case <-st.cw:
+			return http2errStreamClosed
+		}
+	}
+	return nil
+}
+
+// called from handler goroutines.
+func (sc *http2serverConn) write100ContinueHeaders(st *http2stream) {
+	sc.writeFrameFromHandler(http2frameWriteMsg{
+		write:  http2write100ContinueHeadersFrame{st.id},
+		stream: st,
+	})
+}
+
+// A bodyReadMsg tells the server loop that the http.Handler read n
+// bytes of the DATA from the client on the given stream.
+type http2bodyReadMsg struct {
+	st *http2stream
+	n  int
+}
+
+// called from handler goroutines.
+// Notes that the handler for the given stream ID read n bytes of its body
+// and schedules flow control tokens to be sent.
+func (sc *http2serverConn) noteBodyReadFromHandler(st *http2stream, n int) {
+	sc.serveG.checkNotOn()
+	select {
+	case sc.bodyReadCh <- http2bodyReadMsg{st, n}:
+	case <-sc.doneServing:
+	}
+}
+
+func (sc *http2serverConn) noteBodyRead(st *http2stream, n int) {
+	sc.serveG.check()
+	sc.sendWindowUpdate(nil, n)
+	if st.state != http2stateHalfClosedRemote && st.state != http2stateClosed {
+
+		sc.sendWindowUpdate(st, n)
+	}
+}
+
+// st may be nil for conn-level
+func (sc *http2serverConn) sendWindowUpdate(st *http2stream, n int) {
+	sc.serveG.check()
+	// "The legal range for the increment to the flow control
+	// window is 1 to 2^31-1 (2,147,483,647) octets."
+	// A Go Read call on 64-bit machines could in theory read
+	// a larger Read than this. Very unlikely, but we handle it here
+	// rather than elsewhere for now.
+	const maxUint31 = 1<<31 - 1
+	for n >= maxUint31 {
+		sc.sendWindowUpdate32(st, maxUint31)
+		n -= maxUint31
+	}
+	sc.sendWindowUpdate32(st, int32(n))
+}
+
+// st may be nil for conn-level
+func (sc *http2serverConn) sendWindowUpdate32(st *http2stream, n int32) {
+	sc.serveG.check()
+	if n == 0 {
+		return
+	}
+	if n < 0 {
+		panic("negative update")
+	}
+	var streamID uint32
+	if st != nil {
+		streamID = st.id
+	}
+	sc.writeFrame(http2frameWriteMsg{
+		write:  http2writeWindowUpdate{streamID: streamID, n: uint32(n)},
+		stream: st,
+	})
+	var ok bool
+	if st == nil {
+		ok = sc.inflow.add(n)
+	} else {
+		ok = st.inflow.add(n)
+	}
+	if !ok {
+		panic("internal error; sent too many window updates without decrements?")
+	}
+}
+
+type http2requestBody struct {
+	stream        *http2stream
+	conn          *http2serverConn
+	closed        bool
+	pipe          *http2pipe // non-nil if we have a HTTP entity message body
+	needsContinue bool       // need to send a 100-continue
+}
+
+func (b *http2requestBody) Close() error {
+	if b.pipe != nil {
+		b.pipe.CloseWithError(http2errClosedBody)
+	}
+	b.closed = true
+	return nil
+}
+
+func (b *http2requestBody) Read(p []byte) (n int, err error) {
+	if b.needsContinue {
+		b.needsContinue = false
+		b.conn.write100ContinueHeaders(b.stream)
+	}
+	if b.pipe == nil {
+		return 0, io.EOF
+	}
+	n, err = b.pipe.Read(p)
+	if n > 0 {
+		b.conn.noteBodyReadFromHandler(b.stream, n)
+	}
+	return
+}
+
+// responseWriter is the http.ResponseWriter implementation.  It's
+// intentionally small (1 pointer wide) to minimize garbage.  The
+// responseWriterState pointer inside is zeroed at the end of a
+// request (in handlerDone) and calls on the responseWriter thereafter
+// simply crash (caller's mistake), but the much larger responseWriterState
+// and buffers are reused between multiple requests.
+type http2responseWriter struct {
+	rws *http2responseWriterState
+}
+
+// Optional http.ResponseWriter interfaces implemented.
+var (
+	_ CloseNotifier     = (*http2responseWriter)(nil)
+	_ Flusher           = (*http2responseWriter)(nil)
+	_ http2stringWriter = (*http2responseWriter)(nil)
+)
+
+type http2responseWriterState struct {
+	// immutable within a request:
+	stream *http2stream
+	req    *Request
+	body   *http2requestBody // to close at end of request, if DATA frames didn't
+	conn   *http2serverConn
+
+	// TODO: adjust buffer writing sizes based on server config, frame size updates from peer, etc
+	bw *bufio.Writer // writing to a chunkWriter{this *responseWriterState}
+
+	// mutated by http.Handler goroutine:
+	handlerHeader Header   // nil until called
+	snapHeader    Header   // snapshot of handlerHeader at WriteHeader time
+	trailers      []string // set in writeChunk
+	status        int      // status code passed to WriteHeader
+	wroteHeader   bool     // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
+	sentHeader    bool     // have we sent the header frame?
+	handlerDone   bool     // handler has finished
+
+	sentContentLen int64 // non-zero if handler set a Content-Length header
+	wroteBytes     int64
+
+	closeNotifierMu sync.Mutex // guards closeNotifierCh
+	closeNotifierCh chan bool  // nil until first used
+}
+
+type http2chunkWriter struct{ rws *http2responseWriterState }
+
+func (cw http2chunkWriter) Write(p []byte) (n int, err error) { return cw.rws.writeChunk(p) }
+
+func (rws *http2responseWriterState) hasTrailers() bool { return len(rws.trailers) != 0 }
+
+// declareTrailer is called for each Trailer header when the
+// response header is written. It notes that a header will need to be
+// written in the trailers at the end of the response.
+func (rws *http2responseWriterState) declareTrailer(k string) {
+	k = CanonicalHeaderKey(k)
+	switch k {
+	case "Transfer-Encoding", "Content-Length", "Trailer":
+
+		return
+	}
+	if !http2strSliceContains(rws.trailers, k) {
+		rws.trailers = append(rws.trailers, k)
+	}
+}
+
+// writeChunk writes chunks from the bufio.Writer. But because
+// bufio.Writer may bypass its chunking, sometimes p may be
+// arbitrarily large.
+//
+// writeChunk is also responsible (on the first chunk) for sending the
+// HEADER response.
+func (rws *http2responseWriterState) writeChunk(p []byte) (n int, err error) {
+	if !rws.wroteHeader {
+		rws.writeHeader(200)
+	}
+
+	isHeadResp := rws.req.Method == "HEAD"
+	if !rws.sentHeader {
+		rws.sentHeader = true
+		var ctype, clen string
+		if clen = rws.snapHeader.Get("Content-Length"); clen != "" {
+			rws.snapHeader.Del("Content-Length")
+			clen64, err := strconv.ParseInt(clen, 10, 64)
+			if err == nil && clen64 >= 0 {
+				rws.sentContentLen = clen64
+			} else {
+				clen = ""
+			}
+		}
+		if clen == "" && rws.handlerDone && http2bodyAllowedForStatus(rws.status) && (len(p) > 0 || !isHeadResp) {
+			clen = strconv.Itoa(len(p))
+		}
+		_, hasContentType := rws.snapHeader["Content-Type"]
+		if !hasContentType && http2bodyAllowedForStatus(rws.status) {
+			ctype = DetectContentType(p)
+		}
+		var date string
+		if _, ok := rws.snapHeader["Date"]; !ok {
+
+			date = time.Now().UTC().Format(TimeFormat)
+		}
+
+		for _, v := range rws.snapHeader["Trailer"] {
+			http2foreachHeaderElement(v, rws.declareTrailer)
+		}
+
+		endStream := (rws.handlerDone && !rws.hasTrailers() && len(p) == 0) || isHeadResp
+		err = rws.conn.writeHeaders(rws.stream, &http2writeResHeaders{
+			streamID:      rws.stream.id,
+			httpResCode:   rws.status,
+			h:             rws.snapHeader,
+			endStream:     endStream,
+			contentType:   ctype,
+			contentLength: clen,
+			date:          date,
+		})
+		if err != nil {
+			return 0, err
+		}
+		if endStream {
+			return 0, nil
+		}
+	}
+	if isHeadResp {
+		return len(p), nil
+	}
+	if len(p) == 0 && !rws.handlerDone {
+		return 0, nil
+	}
+
+	if rws.handlerDone {
+		rws.promoteUndeclaredTrailers()
+	}
+
+	endStream := rws.handlerDone && !rws.hasTrailers()
+	if len(p) > 0 || endStream {
+
+		if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil {
+			return 0, err
+		}
+	}
+
+	if rws.handlerDone && rws.hasTrailers() {
+		err = rws.conn.writeHeaders(rws.stream, &http2writeResHeaders{
+			streamID:  rws.stream.id,
+			h:         rws.handlerHeader,
+			trailers:  rws.trailers,
+			endStream: true,
+		})
+		return len(p), err
+	}
+	return len(p), nil
+}
+
+// TrailerPrefix is a magic prefix for ResponseWriter.Header map keys
+// that, if present, signals that the map entry is actually for
+// the response trailers, and not the response headers. The prefix
+// is stripped after the ServeHTTP call finishes and the values are
+// sent in the trailers.
+//
+// This mechanism is intended only for trailers that are not known
+// prior to the headers being written. If the set of trailers is fixed
+// or known before the header is written, the normal Go trailers mechanism
+// is preferred:
+//    https://golang.org/pkg/net/http/#ResponseWriter
+//    https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
+const http2TrailerPrefix = "Trailer:"
+
+// promoteUndeclaredTrailers permits http.Handlers to set trailers
+// after the header has already been flushed. Because the Go
+// ResponseWriter interface has no way to set Trailers (only the
+// Header), and because we didn't want to expand the ResponseWriter
+// interface, and because nobody used trailers, and because RFC 2616
+// says you SHOULD (but not must) predeclare any trailers in the
+// header, the official ResponseWriter rules said trailers in Go must
+// be predeclared, and then we reuse the same ResponseWriter.Header()
+// map to mean both Headers and Trailers.  When it's time to write the
+// Trailers, we pick out the fields of Headers that were declared as
+// trailers. That worked for a while, until we found the first major
+// user of Trailers in the wild: gRPC (using them only over http2),
+// and gRPC libraries permit setting trailers mid-stream without
+// predeclarnig them. So: change of plans. We still permit the old
+// way, but we also permit this hack: if a Header() key begins with
+// "Trailer:", the suffix of that key is a Trailer. Because ':' is an
+// invalid token byte anyway, there is no ambiguity. (And it's already
+// filtered out) It's mildly hacky, but not terrible.
+//
+// This method runs after the Handler is done and promotes any Header
+// fields to be trailers.
+func (rws *http2responseWriterState) promoteUndeclaredTrailers() {
+	for k, vv := range rws.handlerHeader {
+		if !strings.HasPrefix(k, http2TrailerPrefix) {
+			continue
+		}
+		trailerKey := strings.TrimPrefix(k, http2TrailerPrefix)
+		rws.declareTrailer(trailerKey)
+		rws.handlerHeader[CanonicalHeaderKey(trailerKey)] = vv
+	}
+	sort.Strings(rws.trailers)
+}
+
+func (w *http2responseWriter) Flush() {
+	rws := w.rws
+	if rws == nil {
+		panic("Header called after Handler finished")
+	}
+	if rws.bw.Buffered() > 0 {
+		if err := rws.bw.Flush(); err != nil {
+
+			return
+		}
+	} else {
+
+		rws.writeChunk(nil)
+	}
+}
+
+func (w *http2responseWriter) CloseNotify() <-chan bool {
+	rws := w.rws
+	if rws == nil {
+		panic("CloseNotify called after Handler finished")
+	}
+	rws.closeNotifierMu.Lock()
+	ch := rws.closeNotifierCh
+	if ch == nil {
+		ch = make(chan bool, 1)
+		rws.closeNotifierCh = ch
+		go func() {
+			rws.stream.cw.Wait()
+			ch <- true
+		}()
+	}
+	rws.closeNotifierMu.Unlock()
+	return ch
+}
+
+func (w *http2responseWriter) Header() Header {
+	rws := w.rws
+	if rws == nil {
+		panic("Header called after Handler finished")
+	}
+	if rws.handlerHeader == nil {
+		rws.handlerHeader = make(Header)
+	}
+	return rws.handlerHeader
+}
+
+func (w *http2responseWriter) WriteHeader(code int) {
+	rws := w.rws
+	if rws == nil {
+		panic("WriteHeader called after Handler finished")
+	}
+	rws.writeHeader(code)
+}
+
+func (rws *http2responseWriterState) writeHeader(code int) {
+	if !rws.wroteHeader {
+		rws.wroteHeader = true
+		rws.status = code
+		if len(rws.handlerHeader) > 0 {
+			rws.snapHeader = http2cloneHeader(rws.handlerHeader)
+		}
+	}
+}
+
+func http2cloneHeader(h Header) Header {
+	h2 := make(Header, len(h))
+	for k, vv := range h {
+		vv2 := make([]string, len(vv))
+		copy(vv2, vv)
+		h2[k] = vv2
+	}
+	return h2
+}
+
+// The Life Of A Write is like this:
+//
+// * Handler calls w.Write or w.WriteString ->
+// * -> rws.bw (*bufio.Writer) ->
+// * (Handler migth call Flush)
+// * -> chunkWriter{rws}
+// * -> responseWriterState.writeChunk(p []byte)
+// * -> responseWriterState.writeChunk (most of the magic; see comment there)
+func (w *http2responseWriter) Write(p []byte) (n int, err error) {
+	return w.write(len(p), p, "")
+}
+
+func (w *http2responseWriter) WriteString(s string) (n int, err error) {
+	return w.write(len(s), nil, s)
+}
+
+// either dataB or dataS is non-zero.
+func (w *http2responseWriter) write(lenData int, dataB []byte, dataS string) (n int, err error) {
+	rws := w.rws
+	if rws == nil {
+		panic("Write called after Handler finished")
+	}
+	if !rws.wroteHeader {
+		w.WriteHeader(200)
+	}
+	if !http2bodyAllowedForStatus(rws.status) {
+		return 0, ErrBodyNotAllowed
+	}
+	rws.wroteBytes += int64(len(dataB)) + int64(len(dataS))
+	if rws.sentContentLen != 0 && rws.wroteBytes > rws.sentContentLen {
+
+		return 0, errors.New("http2: handler wrote more than declared Content-Length")
+	}
+
+	if dataB != nil {
+		return rws.bw.Write(dataB)
+	} else {
+		return rws.bw.WriteString(dataS)
+	}
+}
+
+func (w *http2responseWriter) handlerDone() {
+	rws := w.rws
+	rws.handlerDone = true
+	w.Flush()
+	w.rws = nil
+	http2responseWriterStatePool.Put(rws)
+}
+
+// foreachHeaderElement splits v according to the "#rule" construction
+// in RFC 2616 section 2.1 and calls fn for each non-empty element.
+func http2foreachHeaderElement(v string, fn func(string)) {
+	v = textproto.TrimString(v)
+	if v == "" {
+		return
+	}
+	if !strings.Contains(v, ",") {
+		fn(v)
+		return
+	}
+	for _, f := range strings.Split(v, ",") {
+		if f = textproto.TrimString(f); f != "" {
+			fn(f)
+		}
+	}
+}
+
+const (
+	// transportDefaultConnFlow is how many connection-level flow control
+	// tokens we give the server at start-up, past the default 64k.
+	http2transportDefaultConnFlow = 1 << 30
+
+	// transportDefaultStreamFlow is how many stream-level flow
+	// control tokens we announce to the peer, and how many bytes
+	// we buffer per stream.
+	http2transportDefaultStreamFlow = 4 << 20
+
+	// transportDefaultStreamMinRefresh is the minimum number of bytes we'll send
+	// a stream-level WINDOW_UPDATE for at a time.
+	http2transportDefaultStreamMinRefresh = 4 << 10
+
+	http2defaultUserAgent = "Go-http-client/2.0"
+)
+
+// Transport is an HTTP/2 Transport.
+//
+// A Transport internally caches connections to servers. It is safe
+// for concurrent use by multiple goroutines.
+type http2Transport struct {
+	// DialTLS specifies an optional dial function for creating
+	// TLS connections for requests.
+	//
+	// If DialTLS is nil, tls.Dial is used.
+	//
+	// If the returned net.Conn has a ConnectionState method like tls.Conn,
+	// it will be used to set http.Response.TLS.
+	DialTLS func(network, addr string, cfg *tls.Config) (net.Conn, error)
+
+	// TLSClientConfig specifies the TLS configuration to use with
+	// tls.Client. If nil, the default configuration is used.
+	TLSClientConfig *tls.Config
+
+	// ConnPool optionally specifies an alternate connection pool to use.
+	// If nil, the default is used.
+	ConnPool http2ClientConnPool
+
+	// DisableCompression, if true, prevents the Transport from
+	// requesting compression with an "Accept-Encoding: gzip"
+	// request header when the Request contains no existing
+	// Accept-Encoding value. If the Transport requests gzip on
+	// its own and gets a gzipped response, it's transparently
+	// decoded in the Response.Body. However, if the user
+	// explicitly requested gzip it is not automatically
+	// uncompressed.
+	DisableCompression bool
+
+	// MaxHeaderListSize is the http2 SETTINGS_MAX_HEADER_LIST_SIZE to
+	// send in the initial settings frame. It is how many bytes
+	// of response headers are allow. Unlike the http2 spec, zero here
+	// means to use a default limit (currently 10MB). If you actually
+	// want to advertise an ulimited value to the peer, Transport
+	// interprets the highest possible value here (0xffffffff or 1<<32-1)
+	// to mean no limit.
+	MaxHeaderListSize uint32
+
+	// t1, if non-nil, is the standard library Transport using
+	// this transport. Its settings are used (but not its
+	// RoundTrip method, etc).
+	t1 *Transport
+
+	connPoolOnce  sync.Once
+	connPoolOrDef http2ClientConnPool // non-nil version of ConnPool
+}
+
+func (t *http2Transport) maxHeaderListSize() uint32 {
+	if t.MaxHeaderListSize == 0 {
+		return 10 << 20
+	}
+	if t.MaxHeaderListSize == 0xffffffff {
+		return 0
+	}
+	return t.MaxHeaderListSize
+}
+
+func (t *http2Transport) disableCompression() bool {
+	return t.DisableCompression || (t.t1 != nil && t.t1.DisableCompression)
+}
+
+var http2errTransportVersion = errors.New("http2: ConfigureTransport is only supported starting at Go 1.6")
+
+// ConfigureTransport configures a net/http HTTP/1 Transport to use HTTP/2.
+// It requires Go 1.6 or later and returns an error if the net/http package is too old
+// or if t1 has already been HTTP/2-enabled.
+func http2ConfigureTransport(t1 *Transport) error {
+	_, err := http2configureTransport(t1)
+	return err
+}
+
+func (t *http2Transport) connPool() http2ClientConnPool {
+	t.connPoolOnce.Do(t.initConnPool)
+	return t.connPoolOrDef
+}
+
+func (t *http2Transport) initConnPool() {
+	if t.ConnPool != nil {
+		t.connPoolOrDef = t.ConnPool
+	} else {
+		t.connPoolOrDef = &http2clientConnPool{t: t}
+	}
+}
+
+// ClientConn is the state of a single HTTP/2 client connection to an
+// HTTP/2 server.
+type http2ClientConn struct {
+	t        *http2Transport
+	tconn    net.Conn             // usually *tls.Conn, except specialized impls
+	tlsState *tls.ConnectionState // nil only for specialized impls
+
+	// readLoop goroutine fields:
+	readerDone chan struct{} // closed on error
+	readerErr  error         // set before readerDone is closed
+
+	mu           sync.Mutex // guards following
+	cond         *sync.Cond // hold mu; broadcast on flow/closed changes
+	flow         http2flow  // our conn-level flow control quota (cs.flow is per stream)
+	inflow       http2flow  // peer's conn-level flow control
+	closed       bool
+	goAway       *http2GoAwayFrame             // if non-nil, the GoAwayFrame we received
+	streams      map[uint32]*http2clientStream // client-initiated
+	nextStreamID uint32
+	bw           *bufio.Writer
+	br           *bufio.Reader
+	fr           *http2Framer
+	// Settings from peer:
+	maxFrameSize         uint32
+	maxConcurrentStreams uint32
+	initialWindowSize    uint32
+	hbuf                 bytes.Buffer // HPACK encoder writes into this
+	henc                 *hpack.Encoder
+	freeBuf              [][]byte
+
+	wmu  sync.Mutex // held while writing; acquire AFTER mu if holding both
+	werr error      // first write error that has occurred
+}
+
+// clientStream is the state for a single HTTP/2 stream. One of these
+// is created for each Transport.RoundTrip call.
+type http2clientStream struct {
+	cc            *http2ClientConn
+	req           *Request
+	ID            uint32
+	resc          chan http2resAndError
+	bufPipe       http2pipe // buffered pipe with the flow-controlled response payload
+	requestedGzip bool
+
+	flow        http2flow // guarded by cc.mu
+	inflow      http2flow // guarded by cc.mu
+	bytesRemain int64     // -1 means unknown; owned by transportResponseBody.Read
+	readErr     error     // sticky read error; owned by transportResponseBody.Read
+	stopReqBody error     // if non-nil, stop writing req body; guarded by cc.mu
+
+	peerReset chan struct{} // closed on peer reset
+	resetErr  error         // populated before peerReset is closed
+
+	done chan struct{} // closed when stream remove from cc.streams map; close calls guarded by cc.mu
+
+	// owned by clientConnReadLoop:
+	pastHeaders  bool // got HEADERS w/ END_HEADERS
+	pastTrailers bool // got second HEADERS frame w/ END_HEADERS
+
+	trailer    Header  // accumulated trailers
+	resTrailer *Header // client's Response.Trailer
+}
+
+// awaitRequestCancel runs in its own goroutine and waits for the user
+// to either cancel a RoundTrip request (using the provided
+// Request.Cancel channel), or for the request to be done (any way it
+// might be removed from the cc.streams map: peer reset, successful
+// completion, TCP connection breakage, etc)
+func (cs *http2clientStream) awaitRequestCancel(cancel <-chan struct{}) {
+	if cancel == nil {
+		return
+	}
+	select {
+	case <-cancel:
+		cs.bufPipe.CloseWithError(http2errRequestCanceled)
+		cs.cc.writeStreamReset(cs.ID, http2ErrCodeCancel, nil)
+	case <-cs.done:
+	}
+}
+
+// checkReset reports any error sent in a RST_STREAM frame by the
+// server.
+func (cs *http2clientStream) checkReset() error {
+	select {
+	case <-cs.peerReset:
+		return cs.resetErr
+	default:
+		return nil
+	}
+}
+
+func (cs *http2clientStream) abortRequestBodyWrite(err error) {
+	if err == nil {
+		panic("nil error")
+	}
+	cc := cs.cc
+	cc.mu.Lock()
+	cs.stopReqBody = err
+	cc.cond.Broadcast()
+	cc.mu.Unlock()
+}
+
+type http2stickyErrWriter struct {
+	w   io.Writer
+	err *error
+}
+
+func (sew http2stickyErrWriter) Write(p []byte) (n int, err error) {
+	if *sew.err != nil {
+		return 0, *sew.err
+	}
+	n, err = sew.w.Write(p)
+	*sew.err = err
+	return
+}
+
+var http2ErrNoCachedConn = errors.New("http2: no cached connection was available")
+
+// RoundTripOpt are options for the Transport.RoundTripOpt method.
+type http2RoundTripOpt struct {
+	// OnlyCachedConn controls whether RoundTripOpt may
+	// create a new TCP connection. If set true and
+	// no cached connection is available, RoundTripOpt
+	// will return ErrNoCachedConn.
+	OnlyCachedConn bool
+}
+
+func (t *http2Transport) RoundTrip(req *Request) (*Response, error) {
+	return t.RoundTripOpt(req, http2RoundTripOpt{})
+}
+
+// authorityAddr returns a given authority (a host/IP, or host:port / ip:port)
+// and returns a host:port. The port 443 is added if needed.
+func http2authorityAddr(authority string) (addr string) {
+	if _, _, err := net.SplitHostPort(authority); err == nil {
+		return authority
+	}
+	return net.JoinHostPort(authority, "443")
+}
+
+// RoundTripOpt is like RoundTrip, but takes options.
+func (t *http2Transport) RoundTripOpt(req *Request, opt http2RoundTripOpt) (*Response, error) {
+	if req.URL.Scheme != "https" {
+		return nil, errors.New("http2: unsupported scheme")
+	}
+
+	addr := http2authorityAddr(req.URL.Host)
+	for {
+		cc, err := t.connPool().GetClientConn(req, addr)
+		if err != nil {
+			t.vlogf("http2: Transport failed to get client conn for %s: %v", addr, err)
+			return nil, err
+		}
+		res, err := cc.RoundTrip(req)
+		if http2shouldRetryRequest(req, err) {
+			continue
+		}
+		if err != nil {
+			t.vlogf("RoundTrip failure: %v", err)
+			return nil, err
+		}
+		return res, nil
+	}
+}
+
+// CloseIdleConnections closes any connections which were previously
+// connected from previous requests but are now sitting idle.
+// It does not interrupt any connections currently in use.
+func (t *http2Transport) CloseIdleConnections() {
+	if cp, ok := t.connPool().(*http2clientConnPool); ok {
+		cp.closeIdleConnections()
+	}
+}
+
+var (
+	http2errClientConnClosed   = errors.New("http2: client conn is closed")
+	http2errClientConnUnusable = errors.New("http2: client conn not usable")
+)
+
+func http2shouldRetryRequest(req *Request, err error) bool {
+
+	return err == http2errClientConnUnusable
+}
+
+func (t *http2Transport) dialClientConn(addr string) (*http2ClientConn, error) {
+	host, _, err := net.SplitHostPort(addr)
+	if err != nil {
+		return nil, err
+	}
+	tconn, err := t.dialTLS()("tcp", addr, t.newTLSConfig(host))
+	if err != nil {
+		return nil, err
+	}
+	return t.NewClientConn(tconn)
+}
+
+func (t *http2Transport) newTLSConfig(host string) *tls.Config {
+	cfg := new(tls.Config)
+	if t.TLSClientConfig != nil {
+		*cfg = *t.TLSClientConfig
+	}
+	cfg.NextProtos = []string{http2NextProtoTLS}
+	cfg.ServerName = host
+	return cfg
+}
+
+func (t *http2Transport) dialTLS() func(string, string, *tls.Config) (net.Conn, error) {
+	if t.DialTLS != nil {
+		return t.DialTLS
+	}
+	return t.dialTLSDefault
+}
+
+func (t *http2Transport) dialTLSDefault(network, addr string, cfg *tls.Config) (net.Conn, error) {
+	cn, err := tls.Dial(network, addr, cfg)
+	if err != nil {
+		return nil, err
+	}
+	if err := cn.Handshake(); err != nil {
+		return nil, err
+	}
+	if !cfg.InsecureSkipVerify {
+		if err := cn.VerifyHostname(cfg.ServerName); err != nil {
+			return nil, err
+		}
+	}
+	state := cn.ConnectionState()
+	if p := state.NegotiatedProtocol; p != http2NextProtoTLS {
+		return nil, fmt.Errorf("http2: unexpected ALPN protocol %q; want %q", p, http2NextProtoTLS)
+	}
+	if !state.NegotiatedProtocolIsMutual {
+		return nil, errors.New("http2: could not negotiate protocol mutually")
+	}
+	return cn, nil
+}
+
+// disableKeepAlives reports whether connections should be closed as
+// soon as possible after handling the first request.
+func (t *http2Transport) disableKeepAlives() bool {
+	return t.t1 != nil && t.t1.DisableKeepAlives
+}
+
+func (t *http2Transport) NewClientConn(c net.Conn) (*http2ClientConn, error) {
+	if http2VerboseLogs {
+		t.vlogf("http2: Transport creating client conn to %v", c.RemoteAddr())
+	}
+	if _, err := c.Write(http2clientPreface); err != nil {
+		t.vlogf("client preface write error: %v", err)
+		return nil, err
+	}
+
+	cc := &http2ClientConn{
+		t:                    t,
+		tconn:                c,
+		readerDone:           make(chan struct{}),
+		nextStreamID:         1,
+		maxFrameSize:         16 << 10,
+		initialWindowSize:    65535,
+		maxConcurrentStreams: 1000,
+		streams:              make(map[uint32]*http2clientStream),
+	}
+	cc.cond = sync.NewCond(&cc.mu)
+	cc.flow.add(int32(http2initialWindowSize))
+
+	cc.bw = bufio.NewWriter(http2stickyErrWriter{c, &cc.werr})
+	cc.br = bufio.NewReader(c)
+	cc.fr = http2NewFramer(cc.bw, cc.br)
+
+	cc.henc = hpack.NewEncoder(&cc.hbuf)
+
+	if cs, ok := c.(http2connectionStater); ok {
+		state := cs.ConnectionState()
+		cc.tlsState = &state
+	}
+
+	initialSettings := []http2Setting{
+		http2Setting{ID: http2SettingEnablePush, Val: 0},
+		http2Setting{ID: http2SettingInitialWindowSize, Val: http2transportDefaultStreamFlow},
+	}
+	if max := t.maxHeaderListSize(); max != 0 {
+		initialSettings = append(initialSettings, http2Setting{ID: http2SettingMaxHeaderListSize, Val: max})
+	}
+	cc.fr.WriteSettings(initialSettings...)
+	cc.fr.WriteWindowUpdate(0, http2transportDefaultConnFlow)
+	cc.inflow.add(http2transportDefaultConnFlow + http2initialWindowSize)
+	cc.bw.Flush()
+	if cc.werr != nil {
+		return nil, cc.werr
+	}
+
+	f, err := cc.fr.ReadFrame()
+	if err != nil {
+		return nil, err
+	}
+	sf, ok := f.(*http2SettingsFrame)
+	if !ok {
+		return nil, fmt.Errorf("expected settings frame, got: %T", f)
+	}
+	cc.fr.WriteSettingsAck()
+	cc.bw.Flush()
+
+	sf.ForeachSetting(func(s http2Setting) error {
+		switch s.ID {
+		case http2SettingMaxFrameSize:
+			cc.maxFrameSize = s.Val
+		case http2SettingMaxConcurrentStreams:
+			cc.maxConcurrentStreams = s.Val
+		case http2SettingInitialWindowSize:
+			cc.initialWindowSize = s.Val
+		default:
+
+			t.vlogf("Unhandled Setting: %v", s)
+		}
+		return nil
+	})
+
+	go cc.readLoop()
+	return cc, nil
+}
+
+func (cc *http2ClientConn) setGoAway(f *http2GoAwayFrame) {
+	cc.mu.Lock()
+	defer cc.mu.Unlock()
+	cc.goAway = f
+}
+
+func (cc *http2ClientConn) CanTakeNewRequest() bool {
+	cc.mu.Lock()
+	defer cc.mu.Unlock()
+	return cc.canTakeNewRequestLocked()
+}
+
+func (cc *http2ClientConn) canTakeNewRequestLocked() bool {
+	return cc.goAway == nil && !cc.closed &&
+		int64(len(cc.streams)+1) < int64(cc.maxConcurrentStreams) &&
+		cc.nextStreamID < 2147483647
+}
+
+func (cc *http2ClientConn) closeIfIdle() {
+	cc.mu.Lock()
+	if len(cc.streams) > 0 {
+		cc.mu.Unlock()
+		return
+	}
+	cc.closed = true
+
+	cc.mu.Unlock()
+
+	cc.tconn.Close()
+}
+
+const http2maxAllocFrameSize = 512 << 10
+
+// frameBuffer returns a scratch buffer suitable for writing DATA frames.
+// They're capped at the min of the peer's max frame size or 512KB
+// (kinda arbitrarily), but definitely capped so we don't allocate 4GB
+// bufers.
+func (cc *http2ClientConn) frameScratchBuffer() []byte {
+	cc.mu.Lock()
+	size := cc.maxFrameSize
+	if size > http2maxAllocFrameSize {
+		size = http2maxAllocFrameSize
+	}
+	for i, buf := range cc.freeBuf {
+		if len(buf) >= int(size) {
+			cc.freeBuf[i] = nil
+			cc.mu.Unlock()
+			return buf[:size]
+		}
+	}
+	cc.mu.Unlock()
+	return make([]byte, size)
+}
+
+func (cc *http2ClientConn) putFrameScratchBuffer(buf []byte) {
+	cc.mu.Lock()
+	defer cc.mu.Unlock()
+	const maxBufs = 4 // arbitrary; 4 concurrent requests per conn? investigate.
+	if len(cc.freeBuf) < maxBufs {
+		cc.freeBuf = append(cc.freeBuf, buf)
+		return
+	}
+	for i, old := range cc.freeBuf {
+		if old == nil {
+			cc.freeBuf[i] = buf
+			return
+		}
+	}
+
+}
+
+// errRequestCanceled is a copy of net/http's errRequestCanceled because it's not
+// exported. At least they'll be DeepEqual for h1-vs-h2 comparisons tests.
+var http2errRequestCanceled = errors.New("net/http: request canceled")
+
+func http2commaSeparatedTrailers(req *Request) (string, error) {
+	keys := make([]string, 0, len(req.Trailer))
+	for k := range req.Trailer {
+		k = CanonicalHeaderKey(k)
+		switch k {
+		case "Transfer-Encoding", "Trailer", "Content-Length":
+			return "", &http2badStringError{"invalid Trailer key", k}
+		}
+		keys = append(keys, k)
+	}
+	if len(keys) > 0 {
+		sort.Strings(keys)
+
+		return strings.Join(keys, ","), nil
+	}
+	return "", nil
+}
+
+func (cc *http2ClientConn) responseHeaderTimeout() time.Duration {
+	if cc.t.t1 != nil {
+		return cc.t.t1.ResponseHeaderTimeout
+	}
+
+	return 0
+}
+
+// checkConnHeaders checks whether req has any invalid connection-level headers.
+// per RFC 7540 section 8.1.2.2: Connection-Specific Header Fields.
+// Certain headers are special-cased as okay but not transmitted later.
+func http2checkConnHeaders(req *Request) error {
+	if v := req.Header.Get("Upgrade"); v != "" {
+		return errors.New("http2: invalid Upgrade request header")
+	}
+	if v := req.Header.Get("Transfer-Encoding"); (v != "" && v != "chunked") || len(req.Header["Transfer-Encoding"]) > 1 {
+		return errors.New("http2: invalid Transfer-Encoding request header")
+	}
+	if v := req.Header.Get("Connection"); (v != "" && v != "close" && v != "keep-alive") || len(req.Header["Connection"]) > 1 {
+		return errors.New("http2: invalid Connection request header")
+	}
+	return nil
+}
+
+func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) {
+	if err := http2checkConnHeaders(req); err != nil {
+		return nil, err
+	}
+
+	trailers, err := http2commaSeparatedTrailers(req)
+	if err != nil {
+		return nil, err
+	}
+	hasTrailers := trailers != ""
+
+	var body io.Reader = req.Body
+	contentLen := req.ContentLength
+	if req.Body != nil && contentLen == 0 {
+		// Test to see if it's actually zero or just unset.
+		var buf [1]byte
+		n, rerr := io.ReadFull(body, buf[:])
+		if rerr != nil && rerr != io.EOF {
+			contentLen = -1
+			body = http2errorReader{rerr}
+		} else if n == 1 {
+
+			contentLen = -1
+			body = io.MultiReader(bytes.NewReader(buf[:]), body)
+		} else {
+
+			body = nil
+		}
+	}
+
+	cc.mu.Lock()
+	if cc.closed || !cc.canTakeNewRequestLocked() {
+		cc.mu.Unlock()
+		return nil, http2errClientConnUnusable
+	}
+
+	cs := cc.newStream()
+	cs.req = req
+	hasBody := body != nil
+
+	if !cc.t.disableCompression() &&
+		req.Header.Get("Accept-Encoding") == "" &&
+		req.Header.Get("Range") == "" &&
+		req.Method != "HEAD" {
+
+		cs.requestedGzip = true
+	}
+
+	hdrs := cc.encodeHeaders(req, cs.requestedGzip, trailers, contentLen)
+	cc.wmu.Lock()
+	endStream := !hasBody && !hasTrailers
+	werr := cc.writeHeaders(cs.ID, endStream, hdrs)
+	cc.wmu.Unlock()
+	cc.mu.Unlock()
+
+	if werr != nil {
+		if hasBody {
+			req.Body.Close()
+		}
+		cc.forgetStreamID(cs.ID)
+
+		return nil, werr
+	}
+
+	var respHeaderTimer <-chan time.Time
+	var bodyCopyErrc chan error // result of body copy
+	if hasBody {
+		bodyCopyErrc = make(chan error, 1)
+		go func() {
+			bodyCopyErrc <- cs.writeRequestBody(body, req.Body)
+		}()
+	} else {
+		if d := cc.responseHeaderTimeout(); d != 0 {
+			timer := time.NewTimer(d)
+			defer timer.Stop()
+			respHeaderTimer = timer.C
+		}
+	}
+
+	readLoopResCh := cs.resc
+	requestCanceledCh := http2requestCancel(req)
+	bodyWritten := false
+
+	for {
+		select {
+		case re := <-readLoopResCh:
+			res := re.res
+			if re.err != nil || res.StatusCode > 299 {
+
+				cs.abortRequestBodyWrite(http2errStopReqBodyWrite)
+			}
+			if re.err != nil {
+				cc.forgetStreamID(cs.ID)
+				return nil, re.err
+			}
+			res.Request = req
+			res.TLS = cc.tlsState
+			return res, nil
+		case <-respHeaderTimer:
+			cc.forgetStreamID(cs.ID)
+			if !hasBody || bodyWritten {
+				cc.writeStreamReset(cs.ID, http2ErrCodeCancel, nil)
+			} else {
+				cs.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel)
+			}
+			return nil, http2errTimeout
+		case <-requestCanceledCh:
+			cc.forgetStreamID(cs.ID)
+			if !hasBody || bodyWritten {
+				cc.writeStreamReset(cs.ID, http2ErrCodeCancel, nil)
+			} else {
+				cs.abortRequestBodyWrite(http2errStopReqBodyWriteAndCancel)
+			}
+			return nil, http2errRequestCanceled
+		case <-cs.peerReset:
+
+			return nil, cs.resetErr
+		case err := <-bodyCopyErrc:
+			if err != nil {
+				return nil, err
+			}
+			bodyWritten = true
+			if d := cc.responseHeaderTimeout(); d != 0 {
+				timer := time.NewTimer(d)
+				defer timer.Stop()
+				respHeaderTimer = timer.C
+			}
+		}
+	}
+}
+
+// requires cc.wmu be held
+func (cc *http2ClientConn) writeHeaders(streamID uint32, endStream bool, hdrs []byte) error {
+	first := true
+	frameSize := int(cc.maxFrameSize)
+	for len(hdrs) > 0 && cc.werr == nil {
+		chunk := hdrs
+		if len(chunk) > frameSize {
+			chunk = chunk[:frameSize]
+		}
+		hdrs = hdrs[len(chunk):]
+		endHeaders := len(hdrs) == 0
+		if first {
+			cc.fr.WriteHeaders(http2HeadersFrameParam{
+				StreamID:      streamID,
+				BlockFragment: chunk,
+				EndStream:     endStream,
+				EndHeaders:    endHeaders,
+			})
+			first = false
+		} else {
+			cc.fr.WriteContinuation(streamID, endHeaders, chunk)
+		}
+	}
+
+	cc.bw.Flush()
+	return cc.werr
+}
+
+// internal error values; they don't escape to callers
+var (
+	// abort request body write; don't send cancel
+	http2errStopReqBodyWrite = errors.New("http2: aborting request body write")
+
+	// abort request body write, but send stream reset of cancel.
+	http2errStopReqBodyWriteAndCancel = errors.New("http2: canceling request")
+)
+
+func (cs *http2clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (err error) {
+	cc := cs.cc
+	sentEnd := false
+	buf := cc.frameScratchBuffer()
+	defer cc.putFrameScratchBuffer(buf)
+
+	defer func() {
+
+		cerr := bodyCloser.Close()
+		if err == nil {
+			err = cerr
+		}
+	}()
+
+	req := cs.req
+	hasTrailers := req.Trailer != nil
+
+	var sawEOF bool
+	for !sawEOF {
+		n, err := body.Read(buf)
+		if err == io.EOF {
+			sawEOF = true
+			err = nil
+		} else if err != nil {
+			return err
+		}
+
+		remain := buf[:n]
+		for len(remain) > 0 && err == nil {
+			var allowed int32
+			allowed, err = cs.awaitFlowControl(len(remain))
+			switch {
+			case err == http2errStopReqBodyWrite:
+				return err
+			case err == http2errStopReqBodyWriteAndCancel:
+				cc.writeStreamReset(cs.ID, http2ErrCodeCancel, nil)
+				return err
+			case err != nil:
+				return err
+			}
+			cc.wmu.Lock()
+			data := remain[:allowed]
+			remain = remain[allowed:]
+			sentEnd = sawEOF && len(remain) == 0 && !hasTrailers
+			err = cc.fr.WriteData(cs.ID, sentEnd, data)
+			if err == nil {
+
+				err = cc.bw.Flush()
+			}
+			cc.wmu.Unlock()
+		}
+		if err != nil {
+			return err
+		}
+	}
+
+	cc.wmu.Lock()
+	if !sentEnd {
+		var trls []byte
+		if hasTrailers {
+			cc.mu.Lock()
+			trls = cc.encodeTrailers(req)
+			cc.mu.Unlock()
+		}
+
+		if len(trls) > 0 {
+			err = cc.writeHeaders(cs.ID, true, trls)
+		} else {
+			err = cc.fr.WriteData(cs.ID, true, nil)
+		}
+	}
+	if ferr := cc.bw.Flush(); ferr != nil && err == nil {
+		err = ferr
+	}
+	cc.wmu.Unlock()
+
+	return err
+}
+
+// awaitFlowControl waits for [1, min(maxBytes, cc.cs.maxFrameSize)] flow
+// control tokens from the server.
+// It returns either the non-zero number of tokens taken or an error
+// if the stream is dead.
+func (cs *http2clientStream) awaitFlowControl(maxBytes int) (taken int32, err error) {
+	cc := cs.cc
+	cc.mu.Lock()
+	defer cc.mu.Unlock()
+	for {
+		if cc.closed {
+			return 0, http2errClientConnClosed
+		}
+		if cs.stopReqBody != nil {
+			return 0, cs.stopReqBody
+		}
+		if err := cs.checkReset(); err != nil {
+			return 0, err
+		}
+		if a := cs.flow.available(); a > 0 {
+			take := a
+			if int(take) > maxBytes {
+
+				take = int32(maxBytes)
+			}
+			if take > int32(cc.maxFrameSize) {
+				take = int32(cc.maxFrameSize)
+			}
+			cs.flow.take(take)
+			return take, nil
+		}
+		cc.cond.Wait()
+	}
+}
+
+type http2badStringError struct {
+	what string
+	str  string
+}
+
+func (e *http2badStringError) Error() string { return fmt.Sprintf("%s %q", e.what, e.str) }
+
+// requires cc.mu be held.
+func (cc *http2ClientConn) encodeHeaders(req *Request, addGzipHeader bool, trailers string, contentLength int64) []byte {
+	cc.hbuf.Reset()
+
+	host := req.Host
+	if host == "" {
+		host = req.URL.Host
+	}
+
+	cc.writeHeader(":authority", host)
+	cc.writeHeader(":method", req.Method)
+	if req.Method != "CONNECT" {
+		cc.writeHeader(":path", req.URL.RequestURI())
+		cc.writeHeader(":scheme", "https")
+	}
+	if trailers != "" {
+		cc.writeHeader("trailer", trailers)
+	}
+
+	var didUA bool
+	for k, vv := range req.Header {
+		lowKey := strings.ToLower(k)
+		switch lowKey {
+		case "host", "content-length":
+
+			continue
+		case "connection", "proxy-connection", "transfer-encoding", "upgrade":
+
+			continue
+		case "user-agent":
+
+			didUA = true
+			if len(vv) < 1 {
+				continue
+			}
+			vv = vv[:1]
+			if vv[0] == "" {
+				continue
+			}
+		}
+		for _, v := range vv {
+			cc.writeHeader(lowKey, v)
+		}
+	}
+	if http2shouldSendReqContentLength(req.Method, contentLength) {
+		cc.writeHeader("content-length", strconv.FormatInt(contentLength, 10))
+	}
+	if addGzipHeader {
+		cc.writeHeader("accept-encoding", "gzip")
+	}
+	if !didUA {
+		cc.writeHeader("user-agent", http2defaultUserAgent)
+	}
+	return cc.hbuf.Bytes()
+}
+
+// shouldSendReqContentLength reports whether the http2.Transport should send
+// a "content-length" request header. This logic is basically a copy of the net/http
+// transferWriter.shouldSendContentLength.
+// The contentLength is the corrected contentLength (so 0 means actually 0, not unknown).
+// -1 means unknown.
+func http2shouldSendReqContentLength(method string, contentLength int64) bool {
+	if contentLength > 0 {
+		return true
+	}
+	if contentLength < 0 {
+		return false
+	}
+
+	switch method {
+	case "POST", "PUT", "PATCH":
+		return true
+	default:
+		return false
+	}
+}
+
+// requires cc.mu be held.
+func (cc *http2ClientConn) encodeTrailers(req *Request) []byte {
+	cc.hbuf.Reset()
+	for k, vv := range req.Trailer {
+
+		lowKey := strings.ToLower(k)
+		for _, v := range vv {
+			cc.writeHeader(lowKey, v)
+		}
+	}
+	return cc.hbuf.Bytes()
+}
+
+func (cc *http2ClientConn) writeHeader(name, value string) {
+	if http2VerboseLogs {
+		log.Printf("http2: Transport encoding header %q = %q", name, value)
+	}
+	cc.henc.WriteField(hpack.HeaderField{Name: name, Value: value})
+}
+
+type http2resAndError struct {
+	res *Response
+	err error
+}
+
+// requires cc.mu be held.
+func (cc *http2ClientConn) newStream() *http2clientStream {
+	cs := &http2clientStream{
+		cc:        cc,
+		ID:        cc.nextStreamID,
+		resc:      make(chan http2resAndError, 1),
+		peerReset: make(chan struct{}),
+		done:      make(chan struct{}),
+	}
+	cs.flow.add(int32(cc.initialWindowSize))
+	cs.flow.setConnFlow(&cc.flow)
+	cs.inflow.add(http2transportDefaultStreamFlow)
+	cs.inflow.setConnFlow(&cc.inflow)
+	cc.nextStreamID += 2
+	cc.streams[cs.ID] = cs
+	return cs
+}
+
+func (cc *http2ClientConn) forgetStreamID(id uint32) {
+	cc.streamByID(id, true)
+}
+
+func (cc *http2ClientConn) streamByID(id uint32, andRemove bool) *http2clientStream {
+	cc.mu.Lock()
+	defer cc.mu.Unlock()
+	cs := cc.streams[id]
+	if andRemove && cs != nil && !cc.closed {
+		delete(cc.streams, id)
+		close(cs.done)
+	}
+	return cs
+}
+
+// clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop.
+type http2clientConnReadLoop struct {
+	cc            *http2ClientConn
+	activeRes     map[uint32]*http2clientStream // keyed by streamID
+	closeWhenIdle bool
+
+	hdec *hpack.Decoder
+
+	// Fields reset on each HEADERS:
+	nextRes              *Response
+	sawRegHeader         bool  // saw non-pseudo header
+	reqMalformed         error // non-nil once known to be malformed
+	lastHeaderEndsStream bool
+	headerListSize       int64 // actually uint32, but easier math this way
+}
+
+// readLoop runs in its own goroutine and reads and dispatches frames.
+func (cc *http2ClientConn) readLoop() {
+	rl := &http2clientConnReadLoop{
+		cc:        cc,
+		activeRes: make(map[uint32]*http2clientStream),
+	}
+	rl.hdec = hpack.NewDecoder(http2initialHeaderTableSize, rl.onNewHeaderField)
+
+	defer rl.cleanup()
+	cc.readerErr = rl.run()
+	if ce, ok := cc.readerErr.(http2ConnectionError); ok {
+		cc.wmu.Lock()
+		cc.fr.WriteGoAway(0, http2ErrCode(ce), nil)
+		cc.wmu.Unlock()
+	}
+}
+
+func (rl *http2clientConnReadLoop) cleanup() {
+	cc := rl.cc
+	defer cc.tconn.Close()
+	defer cc.t.connPool().MarkDead(cc)
+	defer close(cc.readerDone)
+
+	err := cc.readerErr
+	if err == io.EOF {
+		err = io.ErrUnexpectedEOF
+	}
+	cc.mu.Lock()
+	for _, cs := range rl.activeRes {
+		cs.bufPipe.CloseWithError(err)
+	}
+	for _, cs := range cc.streams {
+		select {
+		case cs.resc <- http2resAndError{err: err}:
+		default:
+		}
+		close(cs.done)
+	}
+	cc.closed = true
+	cc.cond.Broadcast()
+	cc.mu.Unlock()
+}
+
+func (rl *http2clientConnReadLoop) run() error {
+	cc := rl.cc
+	rl.closeWhenIdle = cc.t.disableKeepAlives()
+	gotReply := false
+	for {
+		f, err := cc.fr.ReadFrame()
+		if err != nil {
+			cc.vlogf("Transport readFrame error: (%T) %v", err, err)
+		}
+		if se, ok := err.(http2StreamError); ok {
+
+			return se
+		} else if err != nil {
+			return err
+		}
+		if http2VerboseLogs {
+			cc.vlogf("http2: Transport received %s", http2summarizeFrame(f))
+		}
+		maybeIdle := false
+
+		switch f := f.(type) {
+		case *http2HeadersFrame:
+			err = rl.processHeaders(f)
+			maybeIdle = true
+			gotReply = true
+		case *http2ContinuationFrame:
+			err = rl.processContinuation(f)
+			maybeIdle = true
+		case *http2DataFrame:
+			err = rl.processData(f)
+			maybeIdle = true
+		case *http2GoAwayFrame:
+			err = rl.processGoAway(f)
+			maybeIdle = true
+		case *http2RSTStreamFrame:
+			err = rl.processResetStream(f)
+			maybeIdle = true
+		case *http2SettingsFrame:
+			err = rl.processSettings(f)
+		case *http2PushPromiseFrame:
+			err = rl.processPushPromise(f)
+		case *http2WindowUpdateFrame:
+			err = rl.processWindowUpdate(f)
+		case *http2PingFrame:
+			err = rl.processPing(f)
+		default:
+			cc.logf("Transport: unhandled response frame type %T", f)
+		}
+		if err != nil {
+			return err
+		}
+		if rl.closeWhenIdle && gotReply && maybeIdle && len(rl.activeRes) == 0 {
+			cc.closeIfIdle()
+		}
+	}
+}
+
+func (rl *http2clientConnReadLoop) processHeaders(f *http2HeadersFrame) error {
+	rl.sawRegHeader = false
+	rl.reqMalformed = nil
+	rl.lastHeaderEndsStream = f.StreamEnded()
+	rl.headerListSize = 0
+	rl.nextRes = &Response{
+		Proto:      "HTTP/2.0",
+		ProtoMajor: 2,
+		Header:     make(Header),
+	}
+	rl.hdec.SetEmitEnabled(true)
+	return rl.processHeaderBlockFragment(f.HeaderBlockFragment(), f.StreamID, f.HeadersEnded())
+}
+
+func (rl *http2clientConnReadLoop) processContinuation(f *http2ContinuationFrame) error {
+	return rl.processHeaderBlockFragment(f.HeaderBlockFragment(), f.StreamID, f.HeadersEnded())
+}
+
+func (rl *http2clientConnReadLoop) processHeaderBlockFragment(frag []byte, streamID uint32, finalFrag bool) error {
+	cc := rl.cc
+	streamEnded := rl.lastHeaderEndsStream
+	cs := cc.streamByID(streamID, streamEnded && finalFrag)
+	if cs == nil {
+
+		return nil
+	}
+	if cs.pastHeaders {
+		rl.hdec.SetEmitFunc(func(f hpack.HeaderField) { rl.onNewTrailerField(cs, f) })
+	} else {
+		rl.hdec.SetEmitFunc(rl.onNewHeaderField)
+	}
+	_, err := rl.hdec.Write(frag)
+	if err != nil {
+		return http2ConnectionError(http2ErrCodeCompression)
+	}
+	if finalFrag {
+		if err := rl.hdec.Close(); err != nil {
+			return http2ConnectionError(http2ErrCodeCompression)
+		}
+	}
+
+	if !finalFrag {
+		return nil
+	}
+
+	if !cs.pastHeaders {
+		cs.pastHeaders = true
+	} else {
+
+		if cs.pastTrailers {
+
+			return http2ConnectionError(http2ErrCodeProtocol)
+		}
+		cs.pastTrailers = true
+		if !streamEnded {
+
+			return http2ConnectionError(http2ErrCodeProtocol)
+		}
+		rl.endStream(cs)
+		return nil
+	}
+
+	if rl.reqMalformed != nil {
+		cs.resc <- http2resAndError{err: rl.reqMalformed}
+		rl.cc.writeStreamReset(cs.ID, http2ErrCodeProtocol, rl.reqMalformed)
+		return nil
+	}
+
+	res := rl.nextRes
+
+	if res.StatusCode == 100 {
+
+		cs.pastHeaders = false
+		return nil
+	}
+
+	if !streamEnded || cs.req.Method == "HEAD" {
+		res.ContentLength = -1
+		if clens := res.Header["Content-Length"]; len(clens) == 1 {
+			if clen64, err := strconv.ParseInt(clens[0], 10, 64); err == nil {
+				res.ContentLength = clen64
+			} else {
+
+			}
+		} else if len(clens) > 1 {
+
+		}
+	}
+
+	if streamEnded {
+		res.Body = http2noBody
+	} else {
+		buf := new(bytes.Buffer)
+		cs.bufPipe = http2pipe{b: buf}
+		cs.bytesRemain = res.ContentLength
+		res.Body = http2transportResponseBody{cs}
+		go cs.awaitRequestCancel(http2requestCancel(cs.req))
+
+		if cs.requestedGzip && res.Header.Get("Content-Encoding") == "gzip" {
+			res.Header.Del("Content-Encoding")
+			res.Header.Del("Content-Length")
+			res.ContentLength = -1
+			res.Body = &http2gzipReader{body: res.Body}
+		}
+		rl.activeRes[cs.ID] = cs
+	}
+
+	cs.resTrailer = &res.Trailer
+	cs.resc <- http2resAndError{res: res}
+	rl.nextRes = nil
+	return nil
+}
+
+// transportResponseBody is the concrete type of Transport.RoundTrip's
+// Response.Body. It is an io.ReadCloser. On Read, it reads from cs.body.
+// On Close it sends RST_STREAM if EOF wasn't already seen.
+type http2transportResponseBody struct {
+	cs *http2clientStream
+}
+
+func (b http2transportResponseBody) Read(p []byte) (n int, err error) {
+	cs := b.cs
+	cc := cs.cc
+
+	if cs.readErr != nil {
+		return 0, cs.readErr
+	}
+	n, err = b.cs.bufPipe.Read(p)
+	if cs.bytesRemain != -1 {
+		if int64(n) > cs.bytesRemain {
+			n = int(cs.bytesRemain)
+			if err == nil {
+				err = errors.New("net/http: server replied with more than declared Content-Length; truncated")
+				cc.writeStreamReset(cs.ID, http2ErrCodeProtocol, err)
+			}
+			cs.readErr = err
+			return int(cs.bytesRemain), err
+		}
+		cs.bytesRemain -= int64(n)
+		if err == io.EOF && cs.bytesRemain > 0 {
+			err = io.ErrUnexpectedEOF
+			cs.readErr = err
+			return n, err
+		}
+	}
+	if n == 0 {
+
+		return
+	}
+
+	cc.mu.Lock()
+	defer cc.mu.Unlock()
+
+	var connAdd, streamAdd int32
+
+	if v := cc.inflow.available(); v < http2transportDefaultConnFlow/2 {
+		connAdd = http2transportDefaultConnFlow - v
+		cc.inflow.add(connAdd)
+	}
+	if err == nil {
+		if v := cs.inflow.available(); v < http2transportDefaultStreamFlow-http2transportDefaultStreamMinRefresh {
+			streamAdd = http2transportDefaultStreamFlow - v
+			cs.inflow.add(streamAdd)
+		}
+	}
+	if connAdd != 0 || streamAdd != 0 {
+		cc.wmu.Lock()
+		defer cc.wmu.Unlock()
+		if connAdd != 0 {
+			cc.fr.WriteWindowUpdate(0, http2mustUint31(connAdd))
+		}
+		if streamAdd != 0 {
+			cc.fr.WriteWindowUpdate(cs.ID, http2mustUint31(streamAdd))
+		}
+		cc.bw.Flush()
+	}
+	return
+}
+
+var http2errClosedResponseBody = errors.New("http2: response body closed")
+
+func (b http2transportResponseBody) Close() error {
+	cs := b.cs
+	if cs.bufPipe.Err() != io.EOF {
+
+		cs.cc.writeStreamReset(cs.ID, http2ErrCodeCancel, nil)
+	}
+	cs.bufPipe.BreakWithError(http2errClosedResponseBody)
+	return nil
+}
+
+func (rl *http2clientConnReadLoop) processData(f *http2DataFrame) error {
+	cc := rl.cc
+	cs := cc.streamByID(f.StreamID, f.StreamEnded())
+	if cs == nil {
+		cc.mu.Lock()
+		neverSent := cc.nextStreamID
+		cc.mu.Unlock()
+		if f.StreamID >= neverSent {
+
+			cc.logf("http2: Transport received unsolicited DATA frame; closing connection")
+			return http2ConnectionError(http2ErrCodeProtocol)
+		}
+
+		return nil
+	}
+	if data := f.Data(); len(data) > 0 {
+		if cs.bufPipe.b == nil {
+
+			cc.logf("http2: Transport received DATA frame for closed stream; closing connection")
+			return http2ConnectionError(http2ErrCodeProtocol)
+		}
+
+		cc.mu.Lock()
+		if cs.inflow.available() >= int32(len(data)) {
+			cs.inflow.take(int32(len(data)))
+		} else {
+			cc.mu.Unlock()
+			return http2ConnectionError(http2ErrCodeFlowControl)
+		}
+		cc.mu.Unlock()
+
+		if _, err := cs.bufPipe.Write(data); err != nil {
+			return err
+		}
+	}
+
+	if f.StreamEnded() {
+		rl.endStream(cs)
+	}
+	return nil
+}
+
+var http2errInvalidTrailers = errors.New("http2: invalid trailers")
+
+func (rl *http2clientConnReadLoop) endStream(cs *http2clientStream) {
+
+	err := io.EOF
+	code := cs.copyTrailers
+	if rl.reqMalformed != nil {
+		err = rl.reqMalformed
+		code = nil
+	}
+	cs.bufPipe.closeWithErrorAndCode(err, code)
+	delete(rl.activeRes, cs.ID)
+	if cs.req.Close || cs.req.Header.Get("Connection") == "close" {
+		rl.closeWhenIdle = true
+	}
+}
+
+func (cs *http2clientStream) copyTrailers() {
+	for k, vv := range cs.trailer {
+		t := cs.resTrailer
+		if *t == nil {
+			*t = make(Header)
+		}
+		(*t)[k] = vv
+	}
+}
+
+func (rl *http2clientConnReadLoop) processGoAway(f *http2GoAwayFrame) error {
+	cc := rl.cc
+	cc.t.connPool().MarkDead(cc)
+	if f.ErrCode != 0 {
+
+		cc.vlogf("transport got GOAWAY with error code = %v", f.ErrCode)
+	}
+	cc.setGoAway(f)
+	return nil
+}
+
+func (rl *http2clientConnReadLoop) processSettings(f *http2SettingsFrame) error {
+	cc := rl.cc
+	cc.mu.Lock()
+	defer cc.mu.Unlock()
+	return f.ForeachSetting(func(s http2Setting) error {
+		switch s.ID {
+		case http2SettingMaxFrameSize:
+			cc.maxFrameSize = s.Val
+		case http2SettingMaxConcurrentStreams:
+			cc.maxConcurrentStreams = s.Val
+		case http2SettingInitialWindowSize:
+
+			cc.initialWindowSize = s.Val
+		default:
+
+			cc.vlogf("Unhandled Setting: %v", s)
+		}
+		return nil
+	})
+}
+
+func (rl *http2clientConnReadLoop) processWindowUpdate(f *http2WindowUpdateFrame) error {
+	cc := rl.cc
+	cs := cc.streamByID(f.StreamID, false)
+	if f.StreamID != 0 && cs == nil {
+		return nil
+	}
+
+	cc.mu.Lock()
+	defer cc.mu.Unlock()
+
+	fl := &cc.flow
+	if cs != nil {
+		fl = &cs.flow
+	}
+	if !fl.add(int32(f.Increment)) {
+		return http2ConnectionError(http2ErrCodeFlowControl)
+	}
+	cc.cond.Broadcast()
+	return nil
+}
+
+func (rl *http2clientConnReadLoop) processResetStream(f *http2RSTStreamFrame) error {
+	cs := rl.cc.streamByID(f.StreamID, true)
+	if cs == nil {
+
+		return nil
+	}
+	select {
+	case <-cs.peerReset:
+
+	default:
+		err := http2StreamError{cs.ID, f.ErrCode}
+		cs.resetErr = err
+		close(cs.peerReset)
+		cs.bufPipe.CloseWithError(err)
+		cs.cc.cond.Broadcast()
+	}
+	delete(rl.activeRes, cs.ID)
+	return nil
+}
+
+func (rl *http2clientConnReadLoop) processPing(f *http2PingFrame) error {
+	if f.IsAck() {
+
+		return nil
+	}
+	cc := rl.cc
+	cc.wmu.Lock()
+	defer cc.wmu.Unlock()
+	if err := cc.fr.WritePing(true, f.Data); err != nil {
+		return err
+	}
+	return cc.bw.Flush()
+}
+
+func (rl *http2clientConnReadLoop) processPushPromise(f *http2PushPromiseFrame) error {
+
+	return http2ConnectionError(http2ErrCodeProtocol)
+}
+
+func (cc *http2ClientConn) writeStreamReset(streamID uint32, code http2ErrCode, err error) {
+
+	cc.wmu.Lock()
+	cc.fr.WriteRSTStream(streamID, code)
+	cc.bw.Flush()
+	cc.wmu.Unlock()
+}
+
+var (
+	http2errResponseHeaderListSize = errors.New("http2: response header list larger than advertised limit")
+	http2errPseudoTrailers         = errors.New("http2: invalid pseudo header in trailers")
+)
+
+func (rl *http2clientConnReadLoop) checkHeaderField(f hpack.HeaderField) bool {
+	if rl.reqMalformed != nil {
+		return false
+	}
+
+	const headerFieldOverhead = 32 // per spec
+	rl.headerListSize += int64(len(f.Name)) + int64(len(f.Value)) + headerFieldOverhead
+	if max := rl.cc.t.maxHeaderListSize(); max != 0 && rl.headerListSize > int64(max) {
+		rl.hdec.SetEmitEnabled(false)
+		rl.reqMalformed = http2errResponseHeaderListSize
+		return false
+	}
+
+	if !http2validHeaderFieldValue(f.Value) {
+		rl.reqMalformed = http2errInvalidHeaderFieldValue
+		return false
+	}
+
+	isPseudo := strings.HasPrefix(f.Name, ":")
+	if isPseudo {
+		if rl.sawRegHeader {
+			rl.reqMalformed = errors.New("http2: invalid pseudo header after regular header")
+			return false
+		}
+	} else {
+		if !http2validHeaderFieldName(f.Name) {
+			rl.reqMalformed = http2errInvalidHeaderFieldName
+			return false
+		}
+		rl.sawRegHeader = true
+	}
+
+	return true
+}
+
+// onNewHeaderField runs on the readLoop goroutine whenever a new
+// hpack header field is decoded.
+func (rl *http2clientConnReadLoop) onNewHeaderField(f hpack.HeaderField) {
+	cc := rl.cc
+	if http2VerboseLogs {
+		cc.logf("http2: Transport decoded %v", f)
+	}
+
+	if !rl.checkHeaderField(f) {
+		return
+	}
+
+	isPseudo := strings.HasPrefix(f.Name, ":")
+	if isPseudo {
+		switch f.Name {
+		case ":status":
+			code, err := strconv.Atoi(f.Value)
+			if err != nil {
+				rl.reqMalformed = errors.New("http2: invalid :status")
+				return
+			}
+			rl.nextRes.Status = f.Value + " " + StatusText(code)
+			rl.nextRes.StatusCode = code
+		default:
+
+			rl.reqMalformed = fmt.Errorf("http2: unknown response pseudo header %q", f.Name)
+		}
+		return
+	}
+
+	key := CanonicalHeaderKey(f.Name)
+	if key == "Trailer" {
+		t := rl.nextRes.Trailer
+		if t == nil {
+			t = make(Header)
+			rl.nextRes.Trailer = t
+		}
+		http2foreachHeaderElement(f.Value, func(v string) {
+			t[CanonicalHeaderKey(v)] = nil
+		})
+	} else {
+		rl.nextRes.Header.Add(key, f.Value)
+	}
+}
+
+func (rl *http2clientConnReadLoop) onNewTrailerField(cs *http2clientStream, f hpack.HeaderField) {
+	if http2VerboseLogs {
+		rl.cc.logf("http2: Transport decoded trailer %v", f)
+	}
+	if !rl.checkHeaderField(f) {
+		return
+	}
+	if strings.HasPrefix(f.Name, ":") {
+
+		rl.reqMalformed = http2errPseudoTrailers
+		return
+	}
+
+	key := CanonicalHeaderKey(f.Name)
+
+	// The spec says one must predeclare their trailers but in practice
+	// popular users (which is to say the only user we found) do not so we
+	// violate the spec and accept all of them.
+	const acceptAllTrailers = true
+	if _, ok := (*cs.resTrailer)[key]; ok || acceptAllTrailers {
+		if cs.trailer == nil {
+			cs.trailer = make(Header)
+		}
+		cs.trailer[key] = append(cs.trailer[key], f.Value)
+	}
+}
+
+func (cc *http2ClientConn) logf(format string, args ...interface{}) {
+	cc.t.logf(format, args...)
+}
+
+func (cc *http2ClientConn) vlogf(format string, args ...interface{}) {
+	cc.t.vlogf(format, args...)
+}
+
+func (t *http2Transport) vlogf(format string, args ...interface{}) {
+	if http2VerboseLogs {
+		t.logf(format, args...)
+	}
+}
+
+func (t *http2Transport) logf(format string, args ...interface{}) {
+	log.Printf(format, args...)
+}
+
+var http2noBody io.ReadCloser = ioutil.NopCloser(bytes.NewReader(nil))
+
+func http2strSliceContains(ss []string, s string) bool {
+	for _, v := range ss {
+		if v == s {
+			return true
+		}
+	}
+	return false
+}
+
+type http2erringRoundTripper struct{ err error }
+
+func (rt http2erringRoundTripper) RoundTrip(*Request) (*Response, error) { return nil, rt.err }
+
+// gzipReader wraps a response body so it can lazily
+// call gzip.NewReader on the first call to Read
+type http2gzipReader struct {
+	body io.ReadCloser // underlying Response.Body
+	zr   *gzip.Reader  // lazily-initialized gzip reader
+	zerr error         // sticky error
+}
+
+func (gz *http2gzipReader) Read(p []byte) (n int, err error) {
+	if gz.zerr != nil {
+		return 0, gz.zerr
+	}
+	if gz.zr == nil {
+		gz.zr, err = gzip.NewReader(gz.body)
+		if err != nil {
+			gz.zerr = err
+			return 0, err
+		}
+	}
+	return gz.zr.Read(p)
+}
+
+func (gz *http2gzipReader) Close() error {
+	return gz.body.Close()
+}
+
+type http2errorReader struct{ err error }
+
+func (r http2errorReader) Read(p []byte) (int, error) { return 0, r.err }
+
+// writeFramer is implemented by any type that is used to write frames.
+type http2writeFramer interface {
+	writeFrame(http2writeContext) error
+}
+
+// writeContext is the interface needed by the various frame writer
+// types below. All the writeFrame methods below are scheduled via the
+// frame writing scheduler (see writeScheduler in writesched.go).
+//
+// This interface is implemented by *serverConn.
+//
+// TODO: decide whether to a) use this in the client code (which didn't
+// end up using this yet, because it has a simpler design, not
+// currently implementing priorities), or b) delete this and
+// make the server code a bit more concrete.
+type http2writeContext interface {
+	Framer() *http2Framer
+	Flush() error
+	CloseConn() error
+	// HeaderEncoder returns an HPACK encoder that writes to the
+	// returned buffer.
+	HeaderEncoder() (*hpack.Encoder, *bytes.Buffer)
+}
+
+// endsStream reports whether the given frame writer w will locally
+// close the stream.
+func http2endsStream(w http2writeFramer) bool {
+	switch v := w.(type) {
+	case *http2writeData:
+		return v.endStream
+	case *http2writeResHeaders:
+		return v.endStream
+	case nil:
+
+		panic("endsStream called on nil writeFramer")
+	}
+	return false
+}
+
+type http2flushFrameWriter struct{}
+
+func (http2flushFrameWriter) writeFrame(ctx http2writeContext) error {
+	return ctx.Flush()
+}
+
+type http2writeSettings []http2Setting
+
+func (s http2writeSettings) writeFrame(ctx http2writeContext) error {
+	return ctx.Framer().WriteSettings([]http2Setting(s)...)
+}
+
+type http2writeGoAway struct {
+	maxStreamID uint32
+	code        http2ErrCode
+}
+
+func (p *http2writeGoAway) writeFrame(ctx http2writeContext) error {
+	err := ctx.Framer().WriteGoAway(p.maxStreamID, p.code, nil)
+	if p.code != 0 {
+		ctx.Flush()
+		time.Sleep(50 * time.Millisecond)
+		ctx.CloseConn()
+	}
+	return err
+}
+
+type http2writeData struct {
+	streamID  uint32
+	p         []byte
+	endStream bool
+}
+
+func (w *http2writeData) String() string {
+	return fmt.Sprintf("writeData(stream=%d, p=%d, endStream=%v)", w.streamID, len(w.p), w.endStream)
+}
+
+func (w *http2writeData) writeFrame(ctx http2writeContext) error {
+	return ctx.Framer().WriteData(w.streamID, w.endStream, w.p)
+}
+
+// handlerPanicRST is the message sent from handler goroutines when
+// the handler panics.
+type http2handlerPanicRST struct {
+	StreamID uint32
+}
+
+func (hp http2handlerPanicRST) writeFrame(ctx http2writeContext) error {
+	return ctx.Framer().WriteRSTStream(hp.StreamID, http2ErrCodeInternal)
+}
+
+func (se http2StreamError) writeFrame(ctx http2writeContext) error {
+	return ctx.Framer().WriteRSTStream(se.StreamID, se.Code)
+}
+
+type http2writePingAck struct{ pf *http2PingFrame }
+
+func (w http2writePingAck) writeFrame(ctx http2writeContext) error {
+	return ctx.Framer().WritePing(true, w.pf.Data)
+}
+
+type http2writeSettingsAck struct{}
+
+func (http2writeSettingsAck) writeFrame(ctx http2writeContext) error {
+	return ctx.Framer().WriteSettingsAck()
+}
+
+// writeResHeaders is a request to write a HEADERS and 0+ CONTINUATION frames
+// for HTTP response headers or trailers from a server handler.
+type http2writeResHeaders struct {
+	streamID    uint32
+	httpResCode int      // 0 means no ":status" line
+	h           Header   // may be nil
+	trailers    []string // if non-nil, which keys of h to write. nil means all.
+	endStream   bool
+
+	date          string
+	contentType   string
+	contentLength string
+}
+
+func http2encKV(enc *hpack.Encoder, k, v string) {
+	if http2VerboseLogs {
+		log.Printf("http2: server encoding header %q = %q", k, v)
+	}
+	enc.WriteField(hpack.HeaderField{Name: k, Value: v})
+}
+
+func (w *http2writeResHeaders) writeFrame(ctx http2writeContext) error {
+	enc, buf := ctx.HeaderEncoder()
+	buf.Reset()
+
+	if w.httpResCode != 0 {
+		http2encKV(enc, ":status", http2httpCodeString(w.httpResCode))
+	}
+
+	http2encodeHeaders(enc, w.h, w.trailers)
+
+	if w.contentType != "" {
+		http2encKV(enc, "content-type", w.contentType)
+	}
+	if w.contentLength != "" {
+		http2encKV(enc, "content-length", w.contentLength)
+	}
+	if w.date != "" {
+		http2encKV(enc, "date", w.date)
+	}
+
+	headerBlock := buf.Bytes()
+	if len(headerBlock) == 0 && w.trailers == nil {
+		panic("unexpected empty hpack")
+	}
+
+	// For now we're lazy and just pick the minimum MAX_FRAME_SIZE
+	// that all peers must support (16KB). Later we could care
+	// more and send larger frames if the peer advertised it, but
+	// there's little point. Most headers are small anyway (so we
+	// generally won't have CONTINUATION frames), and extra frames
+	// only waste 9 bytes anyway.
+	const maxFrameSize = 16384
+
+	first := true
+	for len(headerBlock) > 0 {
+		frag := headerBlock
+		if len(frag) > maxFrameSize {
+			frag = frag[:maxFrameSize]
+		}
+		headerBlock = headerBlock[len(frag):]
+		endHeaders := len(headerBlock) == 0
+		var err error
+		if first {
+			first = false
+			err = ctx.Framer().WriteHeaders(http2HeadersFrameParam{
+				StreamID:      w.streamID,
+				BlockFragment: frag,
+				EndStream:     w.endStream,
+				EndHeaders:    endHeaders,
+			})
+		} else {
+			err = ctx.Framer().WriteContinuation(w.streamID, endHeaders, frag)
+		}
+		if err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+type http2write100ContinueHeadersFrame struct {
+	streamID uint32
+}
+
+func (w http2write100ContinueHeadersFrame) writeFrame(ctx http2writeContext) error {
+	enc, buf := ctx.HeaderEncoder()
+	buf.Reset()
+	http2encKV(enc, ":status", "100")
+	return ctx.Framer().WriteHeaders(http2HeadersFrameParam{
+		StreamID:      w.streamID,
+		BlockFragment: buf.Bytes(),
+		EndStream:     false,
+		EndHeaders:    true,
+	})
+}
+
+type http2writeWindowUpdate struct {
+	streamID uint32 // or 0 for conn-level
+	n        uint32
+}
+
+func (wu http2writeWindowUpdate) writeFrame(ctx http2writeContext) error {
+	return ctx.Framer().WriteWindowUpdate(wu.streamID, wu.n)
+}
+
+func http2encodeHeaders(enc *hpack.Encoder, h Header, keys []string) {
+
+	if keys == nil {
+		keys = make([]string, 0, len(h))
+		for k := range h {
+			keys = append(keys, k)
+		}
+		sort.Strings(keys)
+	}
+	for _, k := range keys {
+		vv := h[k]
+		k = http2lowerHeader(k)
+		if !http2validHeaderFieldName(k) {
+
+			continue
+		}
+		isTE := k == "transfer-encoding"
+		for _, v := range vv {
+			if !http2validHeaderFieldValue(v) {
+
+				continue
+			}
+
+			if isTE && v != "trailers" {
+				continue
+			}
+			http2encKV(enc, k, v)
+		}
+	}
+}
+
+// frameWriteMsg is a request to write a frame.
+type http2frameWriteMsg struct {
+	// write is the interface value that does the writing, once the
+	// writeScheduler (below) has decided to select this frame
+	// to write. The write functions are all defined in write.go.
+	write http2writeFramer
+
+	stream *http2stream // used for prioritization. nil for non-stream frames.
+
+	// done, if non-nil, must be a buffered channel with space for
+	// 1 message and is sent the return value from write (or an
+	// earlier error) when the frame has been written.
+	done chan error
+}
+
+// for debugging only:
+func (wm http2frameWriteMsg) String() string {
+	var streamID uint32
+	if wm.stream != nil {
+		streamID = wm.stream.id
+	}
+	var des string
+	if s, ok := wm.write.(fmt.Stringer); ok {
+		des = s.String()
+	} else {
+		des = fmt.Sprintf("%T", wm.write)
+	}
+	return fmt.Sprintf("[frameWriteMsg stream=%d, ch=%v, type: %v]", streamID, wm.done != nil, des)
+}
+
+// writeScheduler tracks pending frames to write, priorities, and decides
+// the next one to use. It is not thread-safe.
+type http2writeScheduler struct {
+	// zero are frames not associated with a specific stream.
+	// They're sent before any stream-specific freams.
+	zero http2writeQueue
+
+	// maxFrameSize is the maximum size of a DATA frame
+	// we'll write. Must be non-zero and between 16K-16M.
+	maxFrameSize uint32
+
+	// sq contains the stream-specific queues, keyed by stream ID.
+	// when a stream is idle, it's deleted from the map.
+	sq map[uint32]*http2writeQueue
+
+	// canSend is a slice of memory that's reused between frame
+	// scheduling decisions to hold the list of writeQueues (from sq)
+	// which have enough flow control data to send. After canSend is
+	// built, the best is selected.
+	canSend []*http2writeQueue
+
+	// pool of empty queues for reuse.
+	queuePool []*http2writeQueue
+}
+
+func (ws *http2writeScheduler) putEmptyQueue(q *http2writeQueue) {
+	if len(q.s) != 0 {
+		panic("queue must be empty")
+	}
+	ws.queuePool = append(ws.queuePool, q)
+}
+
+func (ws *http2writeScheduler) getEmptyQueue() *http2writeQueue {
+	ln := len(ws.queuePool)
+	if ln == 0 {
+		return new(http2writeQueue)
+	}
+	q := ws.queuePool[ln-1]
+	ws.queuePool = ws.queuePool[:ln-1]
+	return q
+}
+
+func (ws *http2writeScheduler) empty() bool { return ws.zero.empty() && len(ws.sq) == 0 }
+
+func (ws *http2writeScheduler) add(wm http2frameWriteMsg) {
+	st := wm.stream
+	if st == nil {
+		ws.zero.push(wm)
+	} else {
+		ws.streamQueue(st.id).push(wm)
+	}
+}
+
+func (ws *http2writeScheduler) streamQueue(streamID uint32) *http2writeQueue {
+	if q, ok := ws.sq[streamID]; ok {
+		return q
+	}
+	if ws.sq == nil {
+		ws.sq = make(map[uint32]*http2writeQueue)
+	}
+	q := ws.getEmptyQueue()
+	ws.sq[streamID] = q
+	return q
+}
+
+// take returns the most important frame to write and removes it from the scheduler.
+// It is illegal to call this if the scheduler is empty or if there are no connection-level
+// flow control bytes available.
+func (ws *http2writeScheduler) take() (wm http2frameWriteMsg, ok bool) {
+	if ws.maxFrameSize == 0 {
+		panic("internal error: ws.maxFrameSize not initialized or invalid")
+	}
+
+	if !ws.zero.empty() {
+		return ws.zero.shift(), true
+	}
+	if len(ws.sq) == 0 {
+		return
+	}
+
+	for id, q := range ws.sq {
+		if q.firstIsNoCost() {
+			return ws.takeFrom(id, q)
+		}
+	}
+
+	if len(ws.canSend) != 0 {
+		panic("should be empty")
+	}
+	for _, q := range ws.sq {
+		if n := ws.streamWritableBytes(q); n > 0 {
+			ws.canSend = append(ws.canSend, q)
+		}
+	}
+	if len(ws.canSend) == 0 {
+		return
+	}
+	defer ws.zeroCanSend()
+
+	q := ws.canSend[0]
+
+	return ws.takeFrom(q.streamID(), q)
+}
+
+// zeroCanSend is defered from take.
+func (ws *http2writeScheduler) zeroCanSend() {
+	for i := range ws.canSend {
+		ws.canSend[i] = nil
+	}
+	ws.canSend = ws.canSend[:0]
+}
+
+// streamWritableBytes returns the number of DATA bytes we could write
+// from the given queue's stream, if this stream/queue were
+// selected. It is an error to call this if q's head isn't a
+// *writeData.
+func (ws *http2writeScheduler) streamWritableBytes(q *http2writeQueue) int32 {
+	wm := q.head()
+	ret := wm.stream.flow.available()
+	if ret == 0 {
+		return 0
+	}
+	if int32(ws.maxFrameSize) < ret {
+		ret = int32(ws.maxFrameSize)
+	}
+	if ret == 0 {
+		panic("internal error: ws.maxFrameSize not initialized or invalid")
+	}
+	wd := wm.write.(*http2writeData)
+	if len(wd.p) < int(ret) {
+		ret = int32(len(wd.p))
+	}
+	return ret
+}
+
+func (ws *http2writeScheduler) takeFrom(id uint32, q *http2writeQueue) (wm http2frameWriteMsg, ok bool) {
+	wm = q.head()
+
+	if wd, ok := wm.write.(*http2writeData); ok && len(wd.p) > 0 {
+		allowed := wm.stream.flow.available()
+		if allowed == 0 {
+
+			return http2frameWriteMsg{}, false
+		}
+		if int32(ws.maxFrameSize) < allowed {
+			allowed = int32(ws.maxFrameSize)
+		}
+
+		if len(wd.p) > int(allowed) {
+			wm.stream.flow.take(allowed)
+			chunk := wd.p[:allowed]
+			wd.p = wd.p[allowed:]
+
+			return http2frameWriteMsg{
+				stream: wm.stream,
+				write: &http2writeData{
+					streamID: wd.streamID,
+					p:        chunk,
+
+					endStream: false,
+				},
+
+				done: nil,
+			}, true
+		}
+		wm.stream.flow.take(int32(len(wd.p)))
+	}
+
+	q.shift()
+	if q.empty() {
+		ws.putEmptyQueue(q)
+		delete(ws.sq, id)
+	}
+	return wm, true
+}
+
+func (ws *http2writeScheduler) forgetStream(id uint32) {
+	q, ok := ws.sq[id]
+	if !ok {
+		return
+	}
+	delete(ws.sq, id)
+
+	for i := range q.s {
+		q.s[i] = http2frameWriteMsg{}
+	}
+	q.s = q.s[:0]
+	ws.putEmptyQueue(q)
+}
+
+type http2writeQueue struct {
+	s []http2frameWriteMsg
+}
+
+// streamID returns the stream ID for a non-empty stream-specific queue.
+func (q *http2writeQueue) streamID() uint32 { return q.s[0].stream.id }
+
+func (q *http2writeQueue) empty() bool { return len(q.s) == 0 }
+
+func (q *http2writeQueue) push(wm http2frameWriteMsg) {
+	q.s = append(q.s, wm)
+}
+
+// head returns the next item that would be removed by shift.
+func (q *http2writeQueue) head() http2frameWriteMsg {
+	if len(q.s) == 0 {
+		panic("invalid use of queue")
+	}
+	return q.s[0]
+}
+
+func (q *http2writeQueue) shift() http2frameWriteMsg {
+	if len(q.s) == 0 {
+		panic("invalid use of queue")
+	}
+	wm := q.s[0]
+
+	copy(q.s, q.s[1:])
+	q.s[len(q.s)-1] = http2frameWriteMsg{}
+	q.s = q.s[:len(q.s)-1]
+	return wm
+}
+
+func (q *http2writeQueue) firstIsNoCost() bool {
+	if df, ok := q.s[0].write.(*http2writeData); ok {
+		return len(df.p) == 0
+	}
+	return true
+}
diff --git a/src/net/http/header.go b/src/net/http/header.go
index d847b13..049f32f 100644
--- a/src/net/http/header.go
+++ b/src/net/http/header.go
@@ -211,3 +211,13 @@ func hasToken(v, token string) bool {
 func isTokenBoundary(b byte) bool {
 	return b == ' ' || b == ',' || b == '\t'
 }
+
+func cloneHeader(h Header) Header {
+	h2 := make(Header, len(h))
+	for k, vv := range h {
+		vv2 := make([]string, len(vv))
+		copy(vv2, vv)
+		h2[k] = vv2
+	}
+	return h2
+}
diff --git a/src/net/http/httptest/recorder.go b/src/net/http/httptest/recorder.go
index 5451f54..7c51af1 100644
--- a/src/net/http/httptest/recorder.go
+++ b/src/net/http/httptest/recorder.go
@@ -44,23 +44,60 @@ func (rw *ResponseRecorder) Header() http.Header {
 	return m
 }
 
+// writeHeader writes a header if it was not written yet and
+// detects Content-Type if needed.
+//
+// bytes or str are the beginning of the response body.
+// We pass both to avoid unnecessarily generate garbage
+// in rw.WriteString which was created for performance reasons.
+// Non-nil bytes win.
+func (rw *ResponseRecorder) writeHeader(b []byte, str string) {
+	if rw.wroteHeader {
+		return
+	}
+	if len(str) > 512 {
+		str = str[:512]
+	}
+
+	_, hasType := rw.HeaderMap["Content-Type"]
+	hasTE := rw.HeaderMap.Get("Transfer-Encoding") != ""
+	if !hasType && !hasTE {
+		if b == nil {
+			b = []byte(str)
+		}
+		if rw.HeaderMap == nil {
+			rw.HeaderMap = make(http.Header)
+		}
+		rw.HeaderMap.Set("Content-Type", http.DetectContentType(b))
+	}
+
+	rw.WriteHeader(200)
+}
+
 // Write always succeeds and writes to rw.Body, if not nil.
 func (rw *ResponseRecorder) Write(buf []byte) (int, error) {
-	if !rw.wroteHeader {
-		rw.WriteHeader(200)
-	}
+	rw.writeHeader(buf, "")
 	if rw.Body != nil {
 		rw.Body.Write(buf)
 	}
 	return len(buf), nil
 }
 
+// WriteString always succeeds and writes to rw.Body, if not nil.
+func (rw *ResponseRecorder) WriteString(str string) (int, error) {
+	rw.writeHeader(nil, str)
+	if rw.Body != nil {
+		rw.Body.WriteString(str)
+	}
+	return len(str), nil
+}
+
 // WriteHeader sets rw.Code.
 func (rw *ResponseRecorder) WriteHeader(code int) {
 	if !rw.wroteHeader {
 		rw.Code = code
+		rw.wroteHeader = true
 	}
-	rw.wroteHeader = true
 }
 
 // Flush sets rw.Flushed to true.
diff --git a/src/net/http/httptest/recorder_test.go b/src/net/http/httptest/recorder_test.go
index 2b56326..c29b6d4 100644
--- a/src/net/http/httptest/recorder_test.go
+++ b/src/net/http/httptest/recorder_test.go
@@ -6,6 +6,7 @@ package httptest
 
 import (
 	"fmt"
+	"io"
 	"net/http"
 	"testing"
 )
@@ -38,6 +39,14 @@ func TestRecorder(t *testing.T) {
 			return nil
 		}
 	}
+	hasHeader := func(key, want string) checkFunc {
+		return func(rec *ResponseRecorder) error {
+			if got := rec.HeaderMap.Get(key); got != want {
+				return fmt.Errorf("header %s = %q; want %q", key, got, want)
+			}
+			return nil
+		}
+	}
 
 	tests := []struct {
 		name   string
@@ -68,6 +77,18 @@ func TestRecorder(t *testing.T) {
 			check(hasStatus(200), hasContents("hi first"), hasFlush(false)),
 		},
 		{
+			"write string",
+			func(w http.ResponseWriter, r *http.Request) {
+				io.WriteString(w, "hi first")
+			},
+			check(
+				hasStatus(200),
+				hasContents("hi first"),
+				hasFlush(false),
+				hasHeader("Content-Type", "text/plain; charset=utf-8"),
+			),
+		},
+		{
 			"flush",
 			func(w http.ResponseWriter, r *http.Request) {
 				w.(http.Flusher).Flush() // also sends a 200
@@ -75,6 +96,40 @@ func TestRecorder(t *testing.T) {
 			},
 			check(hasStatus(200), hasFlush(true)),
 		},
+		{
+			"Content-Type detection",
+			func(w http.ResponseWriter, r *http.Request) {
+				io.WriteString(w, "<html>")
+			},
+			check(hasHeader("Content-Type", "text/html; charset=utf-8")),
+		},
+		{
+			"no Content-Type detection with Transfer-Encoding",
+			func(w http.ResponseWriter, r *http.Request) {
+				w.Header().Set("Transfer-Encoding", "some encoding")
+				io.WriteString(w, "<html>")
+			},
+			check(hasHeader("Content-Type", "")), // no header
+		},
+		{
+			"no Content-Type detection if set explicitly",
+			func(w http.ResponseWriter, r *http.Request) {
+				w.Header().Set("Content-Type", "some/type")
+				io.WriteString(w, "<html>")
+			},
+			check(hasHeader("Content-Type", "some/type")),
+		},
+		{
+			"Content-Type detection doesn't crash if HeaderMap is nil",
+			func(w http.ResponseWriter, r *http.Request) {
+				// Act as if the user wrote new(httptest.ResponseRecorder)
+				// rather than using NewRecorder (which initializes
+				// HeaderMap)
+				w.(*ResponseRecorder).HeaderMap = nil
+				io.WriteString(w, "<html>")
+			},
+			check(hasHeader("Content-Type", "text/html; charset=utf-8")),
+		},
 	}
 	r, _ := http.NewRequest("GET", "http://foo.com/", nil)
 	for _, tt := range tests {
diff --git a/src/net/http/httptest/server.go b/src/net/http/httptest/server.go
index 96eb0ef..a2573df 100644
--- a/src/net/http/httptest/server.go
+++ b/src/net/http/httptest/server.go
@@ -7,13 +7,18 @@
 package httptest
 
 import (
+	"bytes"
 	"crypto/tls"
 	"flag"
 	"fmt"
+	"log"
 	"net"
 	"net/http"
+	"net/http/internal"
 	"os"
+	"runtime"
 	"sync"
+	"time"
 )
 
 // A Server is an HTTP server listening on a system-chosen port on the
@@ -34,24 +39,10 @@ type Server struct {
 	// wg counts the number of outstanding HTTP requests on this server.
 	// Close blocks until all requests are finished.
 	wg sync.WaitGroup
-}
 
-// historyListener keeps track of all connections that it's ever
-// accepted.
-type historyListener struct {
-	net.Listener
-	sync.Mutex // protects history
-	history    []net.Conn
-}
-
-func (hs *historyListener) Accept() (c net.Conn, err error) {
-	c, err = hs.Listener.Accept()
-	if err == nil {
-		hs.Lock()
-		hs.history = append(hs.history, c)
-		hs.Unlock()
-	}
-	return
+	mu     sync.Mutex // guards closed and conns
+	closed bool
+	conns  map[net.Conn]http.ConnState // except terminal states
 }
 
 func newLocalListener() net.Listener {
@@ -103,10 +94,9 @@ func (s *Server) Start() {
 	if s.URL != "" {
 		panic("Server already started")
 	}
-	s.Listener = &historyListener{Listener: s.Listener}
 	s.URL = "http://" + s.Listener.Addr().String()
-	s.wrapHandler()
-	go s.Config.Serve(s.Listener)
+	s.wrap()
+	s.goServe()
 	if *serve != "" {
 		fmt.Fprintln(os.Stderr, "httptest: serving on", s.URL)
 		select {}
@@ -118,7 +108,7 @@ func (s *Server) StartTLS() {
 	if s.URL != "" {
 		panic("Server already started")
 	}
-	cert, err := tls.X509KeyPair(localhostCert, localhostKey)
+	cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey)
 	if err != nil {
 		panic(fmt.Sprintf("httptest: NewTLSServer: %v", err))
 	}
@@ -134,23 +124,10 @@ func (s *Server) StartTLS() {
 	if len(s.TLS.Certificates) == 0 {
 		s.TLS.Certificates = []tls.Certificate{cert}
 	}
-	tlsListener := tls.NewListener(s.Listener, s.TLS)
-
-	s.Listener = &historyListener{Listener: tlsListener}
+	s.Listener = tls.NewListener(s.Listener, s.TLS)
 	s.URL = "https://" + s.Listener.Addr().String()
-	s.wrapHandler()
-	go s.Config.Serve(s.Listener)
-}
-
-func (s *Server) wrapHandler() {
-	h := s.Config.Handler
-	if h == nil {
-		h = http.DefaultServeMux
-	}
-	s.Config.Handler = &waitGroupHandler{
-		s: s,
-		h: h,
-	}
+	s.wrap()
+	s.goServe()
 }
 
 // NewTLSServer starts and returns a new Server using TLS.
@@ -161,78 +138,194 @@ func NewTLSServer(handler http.Handler) *Server {
 	return ts
 }
 
+type closeIdleTransport interface {
+	CloseIdleConnections()
+}
+
 // Close shuts down the server and blocks until all outstanding
 // requests on this server have completed.
 func (s *Server) Close() {
-	s.Listener.Close()
-	s.wg.Wait()
-	s.CloseClientConnections()
-	if t, ok := http.DefaultTransport.(*http.Transport); ok {
+	s.mu.Lock()
+	if !s.closed {
+		s.closed = true
+		s.Listener.Close()
+		s.Config.SetKeepAlivesEnabled(false)
+		for c, st := range s.conns {
+			// Force-close any idle connections (those between
+			// requests) and new connections (those which connected
+			// but never sent a request). StateNew connections are
+			// super rare and have only been seen (in
+			// previously-flaky tests) in the case of
+			// socket-late-binding races from the http Client
+			// dialing this server and then getting an idle
+			// connection before the dial completed.  There is thus
+			// a connected connection in StateNew with no
+			// associated Request. We only close StateIdle and
+			// StateNew because they're not doing anything. It's
+			// possible StateNew is about to do something in a few
+			// milliseconds, but a previous CL to check again in a
+			// few milliseconds wasn't liked (early versions of
+			// https://golang.org/cl/15151) so now we just
+			// forcefully close StateNew. The docs for Server.Close say
+			// we wait for "oustanding requests", so we don't close things
+			// in StateActive.
+			if st == http.StateIdle || st == http.StateNew {
+				s.closeConn(c)
+			}
+		}
+		// If this server doesn't shut down in 5 seconds, tell the user why.
+		t := time.AfterFunc(5*time.Second, s.logCloseHangDebugInfo)
+		defer t.Stop()
+	}
+	s.mu.Unlock()
+
+	// Not part of httptest.Server's correctness, but assume most
+	// users of httptest.Server will be using the standard
+	// transport, so help them out and close any idle connections for them.
+	if t, ok := http.DefaultTransport.(closeIdleTransport); ok {
 		t.CloseIdleConnections()
 	}
+
+	s.wg.Wait()
+}
+
+func (s *Server) logCloseHangDebugInfo() {
+	s.mu.Lock()
+	defer s.mu.Unlock()
+	var buf bytes.Buffer
+	buf.WriteString("httptest.Server blocked in Close after 5 seconds, waiting for connections:\n")
+	for c, st := range s.conns {
+		fmt.Fprintf(&buf, "  %T %p %v in state %v\n", c, c, c.RemoteAddr(), st)
+	}
+	log.Print(buf.String())
 }
 
-// CloseClientConnections closes any currently open HTTP connections
-// to the test Server.
+// CloseClientConnections closes any open HTTP connections to the test Server.
 func (s *Server) CloseClientConnections() {
-	hl, ok := s.Listener.(*historyListener)
-	if !ok {
-		return
+	var conns int
+	ch := make(chan bool)
+
+	s.mu.Lock()
+	for c := range s.conns {
+		conns++
+		s.closeConnChan(c, ch)
 	}
-	hl.Lock()
-	for _, conn := range hl.history {
-		conn.Close()
+	s.mu.Unlock()
+
+	// Wait for outstanding closes to finish.
+	//
+	// Out of paranoia for making a late change in Go 1.6, we
+	// bound how long this can wait, since golang.org/issue/14291
+	// isn't fully understood yet. At least this should only be used
+	// in tests.
+	timer := time.NewTimer(5 * time.Second)
+	defer timer.Stop()
+	for i := 0; i < conns; i++ {
+		select {
+		case <-ch:
+		case <-timer.C:
+			// Too slow. Give up.
+			return
+		}
 	}
-	hl.Unlock()
 }
 
-// waitGroupHandler wraps a handler, incrementing and decrementing a
-// sync.WaitGroup on each request, to enable Server.Close to block
-// until outstanding requests are finished.
-type waitGroupHandler struct {
-	s *Server
-	h http.Handler // non-nil
+func (s *Server) goServe() {
+	s.wg.Add(1)
+	go func() {
+		defer s.wg.Done()
+		s.Config.Serve(s.Listener)
+	}()
 }
 
-func (h *waitGroupHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-	h.s.wg.Add(1)
-	defer h.s.wg.Done() // a defer, in case ServeHTTP below panics
-	h.h.ServeHTTP(w, r)
+// wrap installs the connection state-tracking hook to know which
+// connections are idle.
+func (s *Server) wrap() {
+	oldHook := s.Config.ConnState
+	s.Config.ConnState = func(c net.Conn, cs http.ConnState) {
+		s.mu.Lock()
+		defer s.mu.Unlock()
+		switch cs {
+		case http.StateNew:
+			s.wg.Add(1)
+			if _, exists := s.conns[c]; exists {
+				panic("invalid state transition")
+			}
+			if s.conns == nil {
+				s.conns = make(map[net.Conn]http.ConnState)
+			}
+			s.conns[c] = cs
+			if s.closed {
+				// Probably just a socket-late-binding dial from
+				// the default transport that lost the race (and
+				// thus this connection is now idle and will
+				// never be used).
+				s.closeConn(c)
+			}
+		case http.StateActive:
+			if oldState, ok := s.conns[c]; ok {
+				if oldState != http.StateNew && oldState != http.StateIdle {
+					panic("invalid state transition")
+				}
+				s.conns[c] = cs
+			}
+		case http.StateIdle:
+			if oldState, ok := s.conns[c]; ok {
+				if oldState != http.StateActive {
+					panic("invalid state transition")
+				}
+				s.conns[c] = cs
+			}
+			if s.closed {
+				s.closeConn(c)
+			}
+		case http.StateHijacked, http.StateClosed:
+			s.forgetConn(c)
+		}
+		if oldHook != nil {
+			oldHook(c, cs)
+		}
+	}
 }
 
-// localhostCert is a PEM-encoded TLS cert with SAN IPs
-// "127.0.0.1" and "[::1]", expiring at the last second of 2049 (the end
-// of ASN.1 time).
-// generated from src/crypto/tls:
-// go run generate_cert.go  --rsa-bits 1024 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
-var localhostCert = []byte(`-----BEGIN CERTIFICATE-----
-MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS
-MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
-MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
-iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4
-iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul
-rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO
-BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
-AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA
-AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9
-tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs
-h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM
-fblo6RBxUQ==
------END CERTIFICATE-----`)
-
-// localhostKey is the private key for localhostCert.
-var localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
-MIICXgIBAAKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9
-SjY1bIw4iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZB
-l2+XsDulrKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQAB
-AoGAGRzwwir7XvBOAy5tM/uV6e+Zf6anZzus1s1Y1ClbjbE6HXbnWWF/wbZGOpet
-3Zm4vD6MXc7jpTLryzTQIvVdfQbRc6+MUVeLKwZatTXtdZrhu+Jk7hx0nTPy8Jcb
-uJqFk541aEw+mMogY/xEcfbWd6IOkp+4xqjlFLBEDytgbIECQQDvH/E6nk+hgN4H
-qzzVtxxr397vWrjrIgPbJpQvBsafG7b0dA4AFjwVbFLmQcj2PprIMmPcQrooz8vp
-jy4SHEg1AkEA/v13/5M47K9vCxmb8QeD/asydfsgS5TeuNi8DoUBEmiSJwma7FXY
-fFUtxuvL7XvjwjN5B30pNEbc6Iuyt7y4MQJBAIt21su4b3sjXNueLKH85Q+phy2U
-fQtuUE9txblTu14q3N7gHRZB4ZMhFYyDy8CKrN2cPg/Fvyt0Xlp/DoCzjA0CQQDU
-y2ptGsuSmgUtWj3NM9xuwYPm+Z/F84K6+ARYiZ6PYj013sovGKUFfYAqVXVlxtIX
-qyUBnu3X9ps8ZfjLZO7BAkEAlT4R5Yl6cGhaJQYZHOde3JEMhNRcVFMO8dJDaFeo
-f9Oeos0UUothgiDktdQHxdNEwLjQf7lJJBzV+5OtwswCWA==
------END RSA PRIVATE KEY-----`)
+// closeConn closes c.
+// s.mu must be held.
+func (s *Server) closeConn(c net.Conn) { s.closeConnChan(c, nil) }
+
+// closeConnChan is like closeConn, but takes an optional channel to receive a value
+// when the goroutine closing c is done.
+func (s *Server) closeConnChan(c net.Conn, done chan<- bool) {
+	if runtime.GOOS == "plan9" {
+		// Go's Plan 9 net package isn't great at unblocking reads when
+		// their underlying TCP connections are closed.  Don't trust
+		// that that the ConnState state machine will get to
+		// StateClosed. Instead, just go there directly. Plan 9 may leak
+		// resources if the syscall doesn't end up returning. Oh well.
+		s.forgetConn(c)
+	}
+
+	// Somewhere in the chaos of https://golang.org/cl/15151 we found that
+	// some types of conns were blocking in Close too long (or deadlocking?)
+	// and we had to call Close in a goroutine. I (bradfitz) forget what
+	// that was at this point, but I suspect it was *tls.Conns, which
+	// were later fixed in https://golang.org/cl/18572, so this goroutine
+	// is _probably_ unnecessary now. But it's too late in Go 1.6 too remove
+	// it with confidence.
+	// TODO(bradfitz): try to remove it for Go 1.7. (golang.org/issue/14291)
+	go func() {
+		c.Close()
+		if done != nil {
+			done <- true
+		}
+	}()
+}
+
+// forgetConn removes c from the set of tracked conns and decrements it from the
+// waitgroup, unless it was previously removed.
+// s.mu must be held.
+func (s *Server) forgetConn(c net.Conn) {
+	if _, ok := s.conns[c]; ok {
+		delete(s.conns, c)
+		s.wg.Done()
+	}
+}
diff --git a/src/net/http/httptest/server_test.go b/src/net/http/httptest/server_test.go
index 500a9f0..c9606f2 100644
--- a/src/net/http/httptest/server_test.go
+++ b/src/net/http/httptest/server_test.go
@@ -5,7 +5,9 @@
 package httptest
 
 import (
+	"bufio"
 	"io/ioutil"
+	"net"
 	"net/http"
 	"testing"
 )
@@ -27,3 +29,72 @@ func TestServer(t *testing.T) {
 		t.Errorf("got %q, want hello", string(got))
 	}
 }
+
+// Issue 12781
+func TestGetAfterClose(t *testing.T) {
+	ts := NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.Write([]byte("hello"))
+	}))
+
+	res, err := http.Get(ts.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	got, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if string(got) != "hello" {
+		t.Fatalf("got %q, want hello", string(got))
+	}
+
+	ts.Close()
+
+	res, err = http.Get(ts.URL)
+	if err == nil {
+		body, _ := ioutil.ReadAll(res.Body)
+		t.Fatalf("Unexected response after close: %v, %v, %s", res.Status, res.Header, body)
+	}
+}
+
+func TestServerCloseBlocking(t *testing.T) {
+	ts := NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.Write([]byte("hello"))
+	}))
+	dial := func() net.Conn {
+		c, err := net.Dial("tcp", ts.Listener.Addr().String())
+		if err != nil {
+			t.Fatal(err)
+		}
+		return c
+	}
+
+	// Keep one connection in StateNew (connected, but not sending anything)
+	cnew := dial()
+	defer cnew.Close()
+
+	// Keep one connection in StateIdle (idle after a request)
+	cidle := dial()
+	defer cidle.Close()
+	cidle.Write([]byte("HEAD / HTTP/1.1\r\nHost: foo\r\n\r\n"))
+	_, err := http.ReadResponse(bufio.NewReader(cidle), nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	ts.Close() // test we don't hang here forever.
+}
+
+// Issue 14290
+func TestServerCloseClientConnections(t *testing.T) {
+	var s *Server
+	s = NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		s.CloseClientConnections()
+	}))
+	defer s.Close()
+	res, err := http.Get(s.URL)
+	if err == nil {
+		res.Body.Close()
+		t.Fatal("Unexpected response: %#v", res)
+	}
+}
diff --git a/src/net/http/httputil/dump.go b/src/net/http/httputil/dump.go
index ca2d1cd..e22cc66 100644
--- a/src/net/http/httputil/dump.go
+++ b/src/net/http/httputil/dump.go
@@ -25,10 +25,10 @@ import (
 func drainBody(b io.ReadCloser) (r1, r2 io.ReadCloser, err error) {
 	var buf bytes.Buffer
 	if _, err = buf.ReadFrom(b); err != nil {
-		return nil, nil, err
+		return nil, b, err
 	}
 	if err = b.Close(); err != nil {
-		return nil, nil, err
+		return nil, b, err
 	}
 	return ioutil.NopCloser(&buf), ioutil.NopCloser(bytes.NewReader(buf.Bytes())), nil
 }
@@ -55,9 +55,9 @@ func (b neverEnding) Read(p []byte) (n int, err error) {
 	return len(p), nil
 }
 
-// DumpRequestOut is like DumpRequest but includes
-// headers that the standard http.Transport adds,
-// such as User-Agent.
+// DumpRequestOut is like DumpRequest but for outgoing client requests. It
+// includes any headers that the standard http.Transport adds, such as
+// User-Agent.
 func DumpRequestOut(req *http.Request, body bool) ([]byte, error) {
 	save := req.Body
 	dummyBody := false
@@ -175,13 +175,22 @@ func dumpAsReceived(req *http.Request, w io.Writer) error {
 	return nil
 }
 
-// DumpRequest returns the as-received wire representation of req,
-// optionally including the request body, for debugging.
-// DumpRequest is semantically a no-op, but in order to
-// dump the body, it reads the body data into memory and
-// changes req.Body to refer to the in-memory copy.
+// DumpRequest returns the given request in its HTTP/1.x wire
+// representation. It should only be used by servers to debug client
+// requests. The returned representation is an approximation only;
+// some details of the initial request are lost while parsing it into
+// an http.Request. In particular, the order and case of header field
+// names are lost. The order of values in multi-valued headers is kept
+// intact. HTTP/2 requests are dumped in HTTP/1.x form, not in their
+// original binary representations.
+//
+// If body is true, DumpRequest also returns the body. To do so, it
+// consumes req.Body and then replaces it with a new io.ReadCloser
+// that yields the same bytes. If DumpRequest returns an error,
+// the state of req is undefined.
+//
 // The documentation for http.Request.Write details which fields
-// of req are used.
+// of req are included in the dump.
 func DumpRequest(req *http.Request, body bool) (dump []byte, err error) {
 	save := req.Body
 	if !body || req.Body == nil {
@@ -189,21 +198,35 @@ func DumpRequest(req *http.Request, body bool) (dump []byte, err error) {
 	} else {
 		save, req.Body, err = drainBody(req.Body)
 		if err != nil {
-			return
+			return nil, err
 		}
 	}
 
 	var b bytes.Buffer
 
+	// By default, print out the unmodified req.RequestURI, which
+	// is always set for incoming server requests. But because we
+	// previously used req.URL.RequestURI and the docs weren't
+	// always so clear about when to use DumpRequest vs
+	// DumpRequestOut, fall back to the old way if the caller
+	// provides a non-server Request.
+	reqURI := req.RequestURI
+	if reqURI == "" {
+		reqURI = req.URL.RequestURI()
+	}
+
 	fmt.Fprintf(&b, "%s %s HTTP/%d.%d\r\n", valueOrDefault(req.Method, "GET"),
-		req.URL.RequestURI(), req.ProtoMajor, req.ProtoMinor)
+		reqURI, req.ProtoMajor, req.ProtoMinor)
 
-	host := req.Host
-	if host == "" && req.URL != nil {
-		host = req.URL.Host
-	}
-	if host != "" {
-		fmt.Fprintf(&b, "Host: %s\r\n", host)
+	absRequestURI := strings.HasPrefix(req.RequestURI, "http://") || strings.HasPrefix(req.RequestURI, "https://")
+	if !absRequestURI {
+		host := req.Host
+		if host == "" && req.URL != nil {
+			host = req.URL.Host
+		}
+		if host != "" {
+			fmt.Fprintf(&b, "Host: %s\r\n", host)
+		}
 	}
 
 	chunked := len(req.TransferEncoding) > 0 && req.TransferEncoding[0] == "chunked"
@@ -269,7 +292,7 @@ func DumpResponse(resp *http.Response, body bool) (dump []byte, err error) {
 	} else {
 		save, resp.Body, err = drainBody(resp.Body)
 		if err != nil {
-			return
+			return nil, err
 		}
 	}
 	err = resp.Write(&b)
diff --git a/src/net/http/httputil/dump_test.go b/src/net/http/httputil/dump_test.go
index ae67e98..46bf521 100644
--- a/src/net/http/httputil/dump_test.go
+++ b/src/net/http/httputil/dump_test.go
@@ -5,6 +5,7 @@
 package httputil
 
 import (
+	"bufio"
 	"bytes"
 	"fmt"
 	"io"
@@ -135,6 +136,14 @@ var dumpTests = []dumpTest{
 			"Accept-Encoding: gzip\r\n\r\n" +
 			strings.Repeat("a", 8193),
 	},
+
+	{
+		Req: *mustReadRequest("GET http://foo.com/ HTTP/1.1\r\n" +
+			"User-Agent: blah\r\n\r\n"),
+		NoBody: true,
+		WantDump: "GET http://foo.com/ HTTP/1.1\r\n" +
+			"User-Agent: blah\r\n\r\n",
+	},
 }
 
 func TestDumpRequest(t *testing.T) {
@@ -211,6 +220,14 @@ func mustNewRequest(method, url string, body io.Reader) *http.Request {
 	return req
 }
 
+func mustReadRequest(s string) *http.Request {
+	req, err := http.ReadRequest(bufio.NewReader(strings.NewReader(s)))
+	if err != nil {
+		panic(err)
+	}
+	return req
+}
+
 var dumpResTests = []struct {
 	res  *http.Response
 	body bool
diff --git a/src/net/http/httputil/example_test.go b/src/net/http/httputil/example_test.go
new file mode 100644
index 0000000..f856135
--- /dev/null
+++ b/src/net/http/httputil/example_test.go
@@ -0,0 +1,123 @@
+// Copyright 2015 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 httputil_test
+
+import (
+	"fmt"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"net/http/httptest"
+	"net/http/httputil"
+	"net/url"
+	"strings"
+)
+
+func ExampleDumpRequest() {
+	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		dump, err := httputil.DumpRequest(r, true)
+		if err != nil {
+			http.Error(w, fmt.Sprint(err), http.StatusInternalServerError)
+			return
+		}
+
+		fmt.Fprintf(w, "%q", dump)
+	}))
+	defer ts.Close()
+
+	const body = "Go is a general-purpose language designed with systems programming in mind."
+	req, err := http.NewRequest("POST", ts.URL, strings.NewReader(body))
+	if err != nil {
+		log.Fatal(err)
+	}
+	req.Host = "www.example.org"
+	resp, err := http.DefaultClient.Do(req)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer resp.Body.Close()
+
+	b, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Printf("%s", b)
+
+	// Output:
+	// "POST / HTTP/1.1\r\nHost: www.example.org\r\nAccept-Encoding: gzip\r\nUser-Agent: Go-http-client/1.1\r\n\r\nGo is a general-purpose language designed with systems programming in mind."
+}
+
+func ExampleDumpRequestOut() {
+	const body = "Go is a general-purpose language designed with systems programming in mind."
+	req, err := http.NewRequest("PUT", "http://www.example.org", strings.NewReader(body))
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	dump, err := httputil.DumpRequestOut(req, true)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Printf("%q", dump)
+
+	// Output:
+	// "PUT / HTTP/1.1\r\nHost: www.example.org\r\nUser-Agent: Go-http-client/1.1\r\nContent-Length: 75\r\nAccept-Encoding: gzip\r\n\r\nGo is a general-purpose language designed with systems programming in mind."
+}
+
+func ExampleDumpResponse() {
+	const body = "Go is a general-purpose language designed with systems programming in mind."
+	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.Header().Set("Date", "Wed, 19 Jul 1972 19:00:00 GMT")
+		fmt.Fprintln(w, body)
+	}))
+	defer ts.Close()
+
+	resp, err := http.Get(ts.URL)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer resp.Body.Close()
+
+	dump, err := httputil.DumpResponse(resp, true)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Printf("%q", dump)
+
+	// Output:
+	// "HTTP/1.1 200 OK\r\nContent-Length: 76\r\nContent-Type: text/plain; charset=utf-8\r\nDate: Wed, 19 Jul 1972 19:00:00 GMT\r\n\r\nGo is a general-purpose language designed with systems programming in mind.\n"
+}
+
+func ExampleReverseProxy() {
+	backendServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		fmt.Fprintln(w, "this call was relayed by the reverse proxy")
+	}))
+	defer backendServer.Close()
+
+	rpURL, err := url.Parse(backendServer.URL)
+	if err != nil {
+		log.Fatal(err)
+	}
+	frontendProxy := httptest.NewServer(httputil.NewSingleHostReverseProxy(rpURL))
+	defer frontendProxy.Close()
+
+	resp, err := http.Get(frontendProxy.URL)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	b, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Printf("%s", b)
+
+	// Output:
+	// this call was relayed by the reverse proxy
+}
diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go
index c8e1132..54411ca 100644
--- a/src/net/http/httputil/reverseproxy.go
+++ b/src/net/http/httputil/reverseproxy.go
@@ -46,6 +46,18 @@ type ReverseProxy struct {
 	// If nil, logging goes to os.Stderr via the log package's
 	// standard logger.
 	ErrorLog *log.Logger
+
+	// BufferPool optionally specifies a buffer pool to
+	// get byte slices for use by io.CopyBuffer when
+	// copying HTTP response bodies.
+	BufferPool BufferPool
+}
+
+// A BufferPool is an interface for getting and returning temporary
+// byte slices for use by io.CopyBuffer.
+type BufferPool interface {
+	Get() []byte
+	Put([]byte)
 }
 
 func singleJoiningSlash(a, b string) string {
@@ -60,10 +72,13 @@ func singleJoiningSlash(a, b string) string {
 	return a + b
 }
 
-// NewSingleHostReverseProxy returns a new ReverseProxy that rewrites
+// NewSingleHostReverseProxy returns a new ReverseProxy that routes
 // URLs to the scheme, host, and base path provided in target. If the
 // target's path is "/base" and the incoming request was for "/dir",
 // the target request will be for /base/dir.
+// NewSingleHostReverseProxy does not rewrite the Host header.
+// To rewrite Host headers, use ReverseProxy directly with a custom
+// Director policy.
 func NewSingleHostReverseProxy(target *url.URL) *ReverseProxy {
 	targetQuery := target.RawQuery
 	director := func(req *http.Request) {
@@ -91,11 +106,12 @@ func copyHeader(dst, src http.Header) {
 // http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
 var hopHeaders = []string{
 	"Connection",
+	"Proxy-Connection", // non-standard but still sent by libcurl and rejected by e.g. google
 	"Keep-Alive",
 	"Proxy-Authenticate",
 	"Proxy-Authorization",
-	"Te", // canonicalized version of "TE"
-	"Trailers",
+	"Te",      // canonicalized version of "TE"
+	"Trailer", // not Trailers per URL above; http://www.rfc-editor.org/errata_search.php?eid=4522
 	"Transfer-Encoding",
 	"Upgrade",
 }
@@ -242,7 +258,14 @@ func (p *ReverseProxy) copyResponse(dst io.Writer, src io.Reader) {
 		}
 	}
 
-	io.Copy(dst, src)
+	var buf []byte
+	if p.BufferPool != nil {
+		buf = p.BufferPool.Get()
+	}
+	io.CopyBuffer(dst, src, buf)
+	if p.BufferPool != nil {
+		p.BufferPool.Put(buf)
+	}
 }
 
 func (p *ReverseProxy) logf(format string, args ...interface{}) {
diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go
index 80a26ab..0849427 100644
--- a/src/net/http/httputil/reverseproxy_test.go
+++ b/src/net/http/httputil/reverseproxy_test.go
@@ -8,14 +8,17 @@ package httputil
 
 import (
 	"bufio"
+	"bytes"
+	"io"
 	"io/ioutil"
 	"log"
 	"net/http"
 	"net/http/httptest"
 	"net/url"
 	"reflect"
-	"runtime"
+	"strconv"
 	"strings"
+	"sync"
 	"testing"
 	"time"
 )
@@ -42,9 +45,13 @@ func TestReverseProxy(t *testing.T) {
 		if c := r.Header.Get("Upgrade"); c != "" {
 			t.Errorf("handler got Upgrade header value %q", c)
 		}
+		if c := r.Header.Get("Proxy-Connection"); c != "" {
+			t.Errorf("handler got Proxy-Connection header value %q", c)
+		}
 		if g, e := r.Host, "some-name"; g != e {
 			t.Errorf("backend got Host header %q, want %q", g, e)
 		}
+		w.Header().Set("Trailers", "not a special header field name")
 		w.Header().Set("Trailer", "X-Trailer")
 		w.Header().Set("X-Foo", "bar")
 		w.Header().Set("Upgrade", "foo")
@@ -68,6 +75,7 @@ func TestReverseProxy(t *testing.T) {
 	getReq, _ := http.NewRequest("GET", frontend.URL, nil)
 	getReq.Host = "some-name"
 	getReq.Header.Set("Connection", "close")
+	getReq.Header.Set("Proxy-Connection", "should be deleted")
 	getReq.Header.Set("Upgrade", "foo")
 	getReq.Close = true
 	res, err := http.DefaultClient.Do(getReq)
@@ -83,6 +91,9 @@ func TestReverseProxy(t *testing.T) {
 	if c := res.Header.Get(fakeHopHeader); c != "" {
 		t.Errorf("got %s header value %q", fakeHopHeader, c)
 	}
+	if g, e := res.Header.Get("Trailers"), "not a special header field name"; g != e {
+		t.Errorf("header Trailers = %q; want %q", g, e)
+	}
 	if g, e := len(res.Header["X-Multi-Value"]), 2; g != e {
 		t.Errorf("got %d X-Multi-Value header values; expected %d", g, e)
 	}
@@ -102,7 +113,6 @@ func TestReverseProxy(t *testing.T) {
 	if g, e := res.Trailer.Get("X-Trailer"), "trailer_value"; g != e {
 		t.Errorf("Trailer(X-Trailer) = %q ; want %q", g, e)
 	}
-
 }
 
 func TestXForwardedFor(t *testing.T) {
@@ -225,10 +235,7 @@ func TestReverseProxyFlushInterval(t *testing.T) {
 	}
 }
 
-func TestReverseProxyCancellation(t *testing.T) {
-	if runtime.GOOS == "plan9" {
-		t.Skip("skipping test; see https://golang.org/issue/9554")
-	}
+func TestReverseProxyCancelation(t *testing.T) {
 	const backendResponse = "I am the backend"
 
 	reqInFlight := make(chan struct{})
@@ -320,3 +327,108 @@ func TestNilBody(t *testing.T) {
 		t.Errorf("Got %q; want %q", slurp, "hi")
 	}
 }
+
+type bufferPool struct {
+	get func() []byte
+	put func([]byte)
+}
+
+func (bp bufferPool) Get() []byte  { return bp.get() }
+func (bp bufferPool) Put(v []byte) { bp.put(v) }
+
+func TestReverseProxyGetPutBuffer(t *testing.T) {
+	const msg = "hi"
+	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		io.WriteString(w, msg)
+	}))
+	defer backend.Close()
+
+	backendURL, err := url.Parse(backend.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var (
+		mu  sync.Mutex
+		log []string
+	)
+	addLog := func(event string) {
+		mu.Lock()
+		defer mu.Unlock()
+		log = append(log, event)
+	}
+	rp := NewSingleHostReverseProxy(backendURL)
+	const size = 1234
+	rp.BufferPool = bufferPool{
+		get: func() []byte {
+			addLog("getBuf")
+			return make([]byte, size)
+		},
+		put: func(p []byte) {
+			addLog("putBuf-" + strconv.Itoa(len(p)))
+		},
+	}
+	frontend := httptest.NewServer(rp)
+	defer frontend.Close()
+
+	req, _ := http.NewRequest("GET", frontend.URL, nil)
+	req.Close = true
+	res, err := http.DefaultClient.Do(req)
+	if err != nil {
+		t.Fatalf("Get: %v", err)
+	}
+	slurp, err := ioutil.ReadAll(res.Body)
+	res.Body.Close()
+	if err != nil {
+		t.Fatalf("reading body: %v", err)
+	}
+	if string(slurp) != msg {
+		t.Errorf("msg = %q; want %q", slurp, msg)
+	}
+	wantLog := []string{"getBuf", "putBuf-" + strconv.Itoa(size)}
+	mu.Lock()
+	defer mu.Unlock()
+	if !reflect.DeepEqual(log, wantLog) {
+		t.Errorf("Log events = %q; want %q", log, wantLog)
+	}
+}
+
+func TestReverseProxy_Post(t *testing.T) {
+	const backendResponse = "I am the backend"
+	const backendStatus = 200
+	var requestBody = bytes.Repeat([]byte("a"), 1<<20)
+	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		slurp, err := ioutil.ReadAll(r.Body)
+		if err != nil {
+			t.Errorf("Backend body read = %v", err)
+		}
+		if len(slurp) != len(requestBody) {
+			t.Errorf("Backend read %d request body bytes; want %d", len(slurp), len(requestBody))
+		}
+		if !bytes.Equal(slurp, requestBody) {
+			t.Error("Backend read wrong request body.") // 1MB; omitting details
+		}
+		w.Write([]byte(backendResponse))
+	}))
+	defer backend.Close()
+	backendURL, err := url.Parse(backend.URL)
+	if err != nil {
+		t.Fatal(err)
+	}
+	proxyHandler := NewSingleHostReverseProxy(backendURL)
+	frontend := httptest.NewServer(proxyHandler)
+	defer frontend.Close()
+
+	postReq, _ := http.NewRequest("POST", frontend.URL, bytes.NewReader(requestBody))
+	res, err := http.DefaultClient.Do(postReq)
+	if err != nil {
+		t.Fatalf("Do: %v", err)
+	}
+	if g, e := res.StatusCode, backendStatus; g != e {
+		t.Errorf("got res.StatusCode %d; expected %d", g, e)
+	}
+	bodyBytes, _ := ioutil.ReadAll(res.Body)
+	if g, e := string(bodyBytes), backendResponse; g != e {
+		t.Errorf("got body %q; expected %q", g, e)
+	}
+}
diff --git a/src/net/http/internal/chunked.go b/src/net/http/internal/chunked.go
index 6d7c698..2e62c00 100644
--- a/src/net/http/internal/chunked.go
+++ b/src/net/http/internal/chunked.go
@@ -44,7 +44,7 @@ type chunkedReader struct {
 func (cr *chunkedReader) beginChunk() {
 	// chunk-size CRLF
 	var line []byte
-	line, cr.err = readLine(cr.r)
+	line, cr.err = readChunkLine(cr.r)
 	if cr.err != nil {
 		return
 	}
@@ -104,10 +104,11 @@ func (cr *chunkedReader) Read(b []uint8) (n int, err error) {
 
 // Read a line of bytes (up to \n) from b.
 // Give up if the line exceeds maxLineLength.
-// The returned bytes are a pointer into storage in
-// the bufio, so they are only valid until the next bufio read.
-func readLine(b *bufio.Reader) (p []byte, err error) {
-	if p, err = b.ReadSlice('\n'); err != nil {
+// The returned bytes are owned by the bufio.Reader
+// so they are only valid until the next bufio read.
+func readChunkLine(b *bufio.Reader) ([]byte, error) {
+	p, err := b.ReadSlice('\n')
+	if err != nil {
 		// We always know when EOF is coming.
 		// If the caller asked for a line, there should be a line.
 		if err == io.EOF {
@@ -120,7 +121,12 @@ func readLine(b *bufio.Reader) (p []byte, err error) {
 	if len(p) >= maxLineLength {
 		return nil, ErrLineTooLong
 	}
-	return trimTrailingWhitespace(p), nil
+	p = trimTrailingWhitespace(p)
+	p, err = removeChunkExtension(p)
+	if err != nil {
+		return nil, err
+	}
+	return p, nil
 }
 
 func trimTrailingWhitespace(b []byte) []byte {
@@ -134,6 +140,23 @@ func isASCIISpace(b byte) bool {
 	return b == ' ' || b == '\t' || b == '\n' || b == '\r'
 }
 
+// removeChunkExtension removes any chunk-extension from p.
+// For example,
+//     "0" => "0"
+//     "0;token" => "0"
+//     "0;token=val" => "0"
+//     `0;token="quoted string"` => "0"
+func removeChunkExtension(p []byte) ([]byte, error) {
+	semi := bytes.IndexByte(p, ';')
+	if semi == -1 {
+		return p, nil
+	}
+	// TODO: care about exact syntax of chunk extensions? We're
+	// ignoring and stripping them anyway. For now just never
+	// return an error.
+	return p[:semi], nil
+}
+
 // NewChunkedWriter returns a new chunkedWriter that translates writes into HTTP
 // "chunked" format before writing them to w. Closing the returned chunkedWriter
 // sends the final 0-length chunk that marks the end of the stream.
@@ -197,8 +220,7 @@ type FlushAfterChunkWriter struct {
 }
 
 func parseHexUint(v []byte) (n uint64, err error) {
-	for _, b := range v {
-		n <<= 4
+	for i, b := range v {
 		switch {
 		case '0' <= b && b <= '9':
 			b = b - '0'
@@ -209,6 +231,10 @@ func parseHexUint(v []byte) (n uint64, err error) {
 		default:
 			return 0, errors.New("invalid byte in chunk length")
 		}
+		if i == 16 {
+			return 0, errors.New("http chunk length too large")
+		}
+		n <<= 4
 		n |= uint64(b)
 	}
 	return
diff --git a/src/net/http/internal/chunked_test.go b/src/net/http/internal/chunked_test.go
index ebc626e..a136dc9 100644
--- a/src/net/http/internal/chunked_test.go
+++ b/src/net/http/internal/chunked_test.go
@@ -139,18 +139,49 @@ func TestChunkReaderAllocs(t *testing.T) {
 }
 
 func TestParseHexUint(t *testing.T) {
+	type testCase struct {
+		in      string
+		want    uint64
+		wantErr string
+	}
+	tests := []testCase{
+		{"x", 0, "invalid byte in chunk length"},
+		{"0000000000000000", 0, ""},
+		{"0000000000000001", 1, ""},
+		{"ffffffffffffffff", 1<<64 - 1, ""},
+		{"000000000000bogus", 0, "invalid byte in chunk length"},
+		{"00000000000000000", 0, "http chunk length too large"}, // could accept if we wanted
+		{"10000000000000000", 0, "http chunk length too large"},
+		{"00000000000000001", 0, "http chunk length too large"}, // could accept if we wanted
+	}
 	for i := uint64(0); i <= 1234; i++ {
-		line := []byte(fmt.Sprintf("%x", i))
-		got, err := parseHexUint(line)
-		if err != nil {
-			t.Fatalf("on %d: %v", i, err)
-		}
-		if got != i {
-			t.Errorf("for input %q = %d; want %d", line, got, i)
+		tests = append(tests, testCase{in: fmt.Sprintf("%x", i), want: i})
+	}
+	for _, tt := range tests {
+		got, err := parseHexUint([]byte(tt.in))
+		if tt.wantErr != "" {
+			if !strings.Contains(fmt.Sprint(err), tt.wantErr) {
+				t.Errorf("parseHexUint(%q) = %v, %v; want error %q", tt.in, got, err, tt.wantErr)
+			}
+		} else {
+			if err != nil || got != tt.want {
+				t.Errorf("parseHexUint(%q) = %v, %v; want %v", tt.in, got, err, tt.want)
+			}
 		}
 	}
-	_, err := parseHexUint([]byte("bogus"))
-	if err == nil {
-		t.Error("expected error on bogus input")
+}
+
+func TestChunkReadingIgnoresExtensions(t *testing.T) {
+	in := "7;ext=\"some quoted string\"\r\n" + // token=quoted string
+		"hello, \r\n" +
+		"17;someext\r\n" + // token without value
+		"world! 0123456789abcdef\r\n" +
+		"0;someextension=sometoken\r\n" // token=token
+	data, err := ioutil.ReadAll(NewChunkedReader(strings.NewReader(in)))
+	if err != nil {
+		t.Fatalf("ReadAll = %q, %v", data, err)
+	}
+	if g, e := string(data), "hello, world! 0123456789abcdef"; g != e {
+		t.Errorf("read %q; want %q", g, e)
 	}
 }
diff --git a/src/net/http/internal/testcert.go b/src/net/http/internal/testcert.go
new file mode 100644
index 0000000..4078909
--- /dev/null
+++ b/src/net/http/internal/testcert.go
@@ -0,0 +1,41 @@
+// Copyright 2015 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 internal
+
+// LocalhostCert is a PEM-encoded TLS cert with SAN IPs
+// "127.0.0.1" and "[::1]", expiring at Jan 29 16:00:00 2084 GMT.
+// generated from src/crypto/tls:
+// go run generate_cert.go  --rsa-bits 1024 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
+var LocalhostCert = []byte(`-----BEGIN CERTIFICATE-----
+MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS
+MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
+MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
+iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4
+iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul
+rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO
+BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
+AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA
+AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9
+tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs
+h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM
+fblo6RBxUQ==
+-----END CERTIFICATE-----`)
+
+// LocalhostKey is the private key for localhostCert.
+var LocalhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIICXgIBAAKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9
+SjY1bIw4iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZB
+l2+XsDulrKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQAB
+AoGAGRzwwir7XvBOAy5tM/uV6e+Zf6anZzus1s1Y1ClbjbE6HXbnWWF/wbZGOpet
+3Zm4vD6MXc7jpTLryzTQIvVdfQbRc6+MUVeLKwZatTXtdZrhu+Jk7hx0nTPy8Jcb
+uJqFk541aEw+mMogY/xEcfbWd6IOkp+4xqjlFLBEDytgbIECQQDvH/E6nk+hgN4H
+qzzVtxxr397vWrjrIgPbJpQvBsafG7b0dA4AFjwVbFLmQcj2PprIMmPcQrooz8vp
+jy4SHEg1AkEA/v13/5M47K9vCxmb8QeD/asydfsgS5TeuNi8DoUBEmiSJwma7FXY
+fFUtxuvL7XvjwjN5B30pNEbc6Iuyt7y4MQJBAIt21su4b3sjXNueLKH85Q+phy2U
+fQtuUE9txblTu14q3N7gHRZB4ZMhFYyDy8CKrN2cPg/Fvyt0Xlp/DoCzjA0CQQDU
+y2ptGsuSmgUtWj3NM9xuwYPm+Z/F84K6+ARYiZ6PYj013sovGKUFfYAqVXVlxtIX
+qyUBnu3X9ps8ZfjLZO7BAkEAlT4R5Yl6cGhaJQYZHOde3JEMhNRcVFMO8dJDaFeo
+f9Oeos0UUothgiDktdQHxdNEwLjQf7lJJBzV+5OtwswCWA==
+-----END RSA PRIVATE KEY-----`)
diff --git a/src/net/http/lex.go b/src/net/http/lex.go
index 50b14f8..52b6481 100644
--- a/src/net/http/lex.go
+++ b/src/net/http/lex.go
@@ -167,3 +167,17 @@ func tokenEqual(t1, t2 string) bool {
 	}
 	return true
 }
+
+// isLWS reports whether b is linear white space, according
+// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
+//      LWS            = [CRLF] 1*( SP | HT )
+func isLWS(b byte) bool { return b == ' ' || b == '\t' }
+
+// isCTL reports whether b is a control byte, according
+// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
+//      CTL            = <any US-ASCII control character
+//                       (octets 0 - 31) and DEL (127)>
+func isCTL(b byte) bool {
+	const del = 0x7f // a CTL
+	return b < ' ' || b == del
+}
diff --git a/src/net/http/main_test.go b/src/net/http/main_test.go
index 12eea6f..299cd7b 100644
--- a/src/net/http/main_test.go
+++ b/src/net/http/main_test.go
@@ -5,6 +5,7 @@
 package http_test
 
 import (
+	"flag"
 	"fmt"
 	"net/http"
 	"os"
@@ -15,6 +16,8 @@ import (
 	"time"
 )
 
+var flaky = flag.Bool("flaky", false, "run known-flaky tests too")
+
 func TestMain(m *testing.M) {
 	v := m.Run()
 	if v == 0 && goroutineLeaked() {
@@ -79,6 +82,21 @@ func goroutineLeaked() bool {
 	return true
 }
 
+// setParallel marks t as a parallel test if we're in short mode
+// (all.bash), but as a serial test otherwise. Using t.Parallel isn't
+// compatible with the afterTest func in non-short mode.
+func setParallel(t *testing.T) {
+	if testing.Short() {
+		t.Parallel()
+	}
+}
+
+func setFlaky(t *testing.T, issue int) {
+	if !*flaky {
+		t.Skipf("skipping known flaky test; see golang.org/issue/%d", issue)
+	}
+}
+
 func afterTest(t testing.TB) {
 	http.DefaultTransport.(*http.Transport).CloseIdleConnections()
 	if testing.Short() {
diff --git a/src/net/http/method.go b/src/net/http/method.go
new file mode 100644
index 0000000..b74f960
--- /dev/null
+++ b/src/net/http/method.go
@@ -0,0 +1,20 @@
+// Copyright 2015 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 http
+
+// Common HTTP methods.
+//
+// Unless otherwise noted, these are defined in RFC 7231 section 4.3.
+const (
+	MethodGet     = "GET"
+	MethodHead    = "HEAD"
+	MethodPost    = "POST"
+	MethodPut     = "PUT"
+	MethodPatch   = "PATCH" // RFC 5741
+	MethodDelete  = "DELETE"
+	MethodConnect = "CONNECT"
+	MethodOptions = "OPTIONS"
+	MethodTrace   = "TRACE"
+)
diff --git a/src/net/http/pprof/pprof.go b/src/net/http/pprof/pprof.go
index fd9154a..63ff221 100644
--- a/src/net/http/pprof/pprof.go
+++ b/src/net/http/pprof/pprof.go
@@ -80,6 +80,17 @@ func Cmdline(w http.ResponseWriter, r *http.Request) {
 	fmt.Fprintf(w, strings.Join(os.Args, "\x00"))
 }
 
+func sleep(w http.ResponseWriter, d time.Duration) {
+	var clientGone <-chan bool
+	if cn, ok := w.(http.CloseNotifier); ok {
+		clientGone = cn.CloseNotify()
+	}
+	select {
+	case <-time.After(d):
+	case <-clientGone:
+	}
+}
+
 // Profile responds with the pprof-formatted cpu profile.
 // The package initialization registers it as /debug/pprof/profile.
 func Profile(w http.ResponseWriter, r *http.Request) {
@@ -100,7 +111,7 @@ func Profile(w http.ResponseWriter, r *http.Request) {
 		fmt.Fprintf(w, "Could not enable CPU profiling: %s\n", err)
 		return
 	}
-	time.Sleep(time.Duration(sec) * time.Second)
+	sleep(w, time.Duration(sec)*time.Second)
 	pprof.StopCPUProfile()
 }
 
@@ -124,7 +135,7 @@ func Trace(w http.ResponseWriter, r *http.Request) {
 		fmt.Fprintf(w, "Could not enable tracing: %s\n", err)
 		return
 	}
-	time.Sleep(time.Duration(sec) * time.Second)
+	sleep(w, time.Duration(sec)*time.Second)
 	trace.Stop()
 }
 
diff --git a/src/net/http/request.go b/src/net/http/request.go
index 31fe45a..8cdab02 100644
--- a/src/net/http/request.go
+++ b/src/net/http/request.go
@@ -90,36 +90,46 @@ type Request struct {
 	// request.
 	URL *url.URL
 
-	// The protocol version for incoming requests.
-	// Client requests always use HTTP/1.1.
+	// The protocol version for incoming server requests.
+	//
+	// For client requests these fields are ignored. The HTTP
+	// client code always uses either HTTP/1.1 or HTTP/2.
+	// See the docs on Transport for details.
 	Proto      string // "HTTP/1.0"
 	ProtoMajor int    // 1
 	ProtoMinor int    // 0
 
-	// A header maps request lines to their values.
-	// If the header says
+	// Header contains the request header fields either received
+	// by the server or to be sent by the client.
+	//
+	// If a server received a request with header lines,
 	//
+	//	Host: example.com
 	//	accept-encoding: gzip, deflate
 	//	Accept-Language: en-us
-	//	Connection: keep-alive
+	//	fOO: Bar
+	//	foo: two
 	//
 	// then
 	//
 	//	Header = map[string][]string{
 	//		"Accept-Encoding": {"gzip, deflate"},
 	//		"Accept-Language": {"en-us"},
-	//		"Connection": {"keep-alive"},
+	//		"Foo": {"Bar", "two"},
 	//	}
 	//
-	// HTTP defines that header names are case-insensitive.
-	// The request parser implements this by canonicalizing the
-	// name, making the first character and any characters
-	// following a hyphen uppercase and the rest lowercase.
+	// For incoming requests, the Host header is promoted to the
+	// Request.Host field and removed from the Header map.
 	//
-	// For client requests certain headers are automatically
-	// added and may override values in Header.
+	// HTTP defines that header names are case-insensitive. The
+	// request parser implements this by using CanonicalHeaderKey,
+	// making the first character and any characters following a
+	// hyphen uppercase and the rest lowercase.
 	//
-	// See the documentation for the Request.Write method.
+	// For client requests, certain headers such as Content-Length
+	// and Connection are automatically written when needed and
+	// values in Header may be ignored. See the documentation
+	// for the Request.Write method.
 	Header Header
 
 	// Body is the request's body.
@@ -149,8 +159,15 @@ type Request struct {
 	TransferEncoding []string
 
 	// Close indicates whether to close the connection after
-	// replying to this request (for servers) or after sending
-	// the request (for clients).
+	// replying to this request (for servers) or after sending this
+	// request and reading its response (for clients).
+	//
+	// For server requests, the HTTP server handles this automatically
+	// and this field is not needed by Handlers.
+	//
+	// For client requests, setting this field prevents re-use of
+	// TCP connections between requests to the same hosts, as if
+	// Transport.DisableKeepAlives were set.
 	Close bool
 
 	// For server requests Host specifies the host on which the
@@ -354,7 +371,7 @@ const defaultUserAgent = "Go-http-client/1.1"
 // hasn't been set to "identity", Write adds "Transfer-Encoding:
 // chunked" to the header. Body is closed after it is sent.
 func (r *Request) Write(w io.Writer) error {
-	return r.write(w, false, nil)
+	return r.write(w, false, nil, nil)
 }
 
 // WriteProxy is like Write but writes the request in the form
@@ -364,11 +381,16 @@ func (r *Request) Write(w io.Writer) error {
 // In either case, WriteProxy also writes a Host header, using
 // either r.Host or r.URL.Host.
 func (r *Request) WriteProxy(w io.Writer) error {
-	return r.write(w, true, nil)
+	return r.write(w, true, nil, nil)
 }
 
+// errMissingHost is returned by Write when there is no Host or URL present in
+// the Request.
+var errMissingHost = errors.New("http: Request.Write on Request with no Host or URL set")
+
 // extraHeaders may be nil
-func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header) error {
+// waitForContinue may be nil
+func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, waitForContinue func() bool) error {
 	// Find the target host. Prefer the Host: header, but if that
 	// is not given, use the host from the request URL.
 	//
@@ -376,7 +398,7 @@ func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header) err
 	host := cleanHost(req.Host)
 	if host == "" {
 		if req.URL == nil {
-			return errors.New("http: Request.Write on Request with no Host or URL set")
+			return errMissingHost
 		}
 		host = cleanHost(req.URL.Host)
 	}
@@ -419,10 +441,8 @@ func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header) err
 	// Use the defaultUserAgent unless the Header contains one, which
 	// may be blank to not send the header.
 	userAgent := defaultUserAgent
-	if req.Header != nil {
-		if ua := req.Header["User-Agent"]; len(ua) > 0 {
-			userAgent = ua[0]
-		}
+	if _, ok := req.Header["User-Agent"]; ok {
+		userAgent = req.Header.Get("User-Agent")
 	}
 	if userAgent != "" {
 		_, err = fmt.Fprintf(w, "User-Agent: %s\r\n", userAgent)
@@ -458,6 +478,21 @@ func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header) err
 		return err
 	}
 
+	// Flush and wait for 100-continue if expected.
+	if waitForContinue != nil {
+		if bw, ok := w.(*bufio.Writer); ok {
+			err = bw.Flush()
+			if err != nil {
+				return err
+			}
+		}
+
+		if !waitForContinue() {
+			req.closeBody()
+			return nil
+		}
+	}
+
 	// Write body and trailer
 	err = tw.WriteBody(w)
 	if err != nil {
@@ -531,6 +566,23 @@ func ParseHTTPVersion(vers string) (major, minor int, ok bool) {
 	return major, minor, true
 }
 
+func validMethod(method string) bool {
+	/*
+	     Method         = "OPTIONS"                ; Section 9.2
+	                    | "GET"                    ; Section 9.3
+	                    | "HEAD"                   ; Section 9.4
+	                    | "POST"                   ; Section 9.5
+	                    | "PUT"                    ; Section 9.6
+	                    | "DELETE"                 ; Section 9.7
+	                    | "TRACE"                  ; Section 9.8
+	                    | "CONNECT"                ; Section 9.9
+	                    | extension-method
+	   extension-method = token
+	     token          = 1*<any CHAR except CTLs or separators>
+	*/
+	return len(method) > 0 && strings.IndexFunc(method, isNotToken) == -1
+}
+
 // NewRequest returns a new Request given a method, URL, and optional body.
 //
 // If the provided body is also an io.Closer, the returned
@@ -544,6 +596,15 @@ func ParseHTTPVersion(vers string) (major, minor int, ok bool) {
 // type's documentation for the difference between inbound and outbound
 // request fields.
 func NewRequest(method, urlStr string, body io.Reader) (*Request, error) {
+	if method == "" {
+		// We document that "" means "GET" for Request.Method, and people have
+		// relied on that from NewRequest, so keep that working.
+		// We still enforce validMethod for non-empty methods.
+		method = "GET"
+	}
+	if !validMethod(method) {
+		return nil, fmt.Errorf("net/http: invalid method %q", method)
+	}
 	u, err := url.Parse(urlStr)
 	if err != nil {
 		return nil, err
@@ -643,8 +704,15 @@ func putTextprotoReader(r *textproto.Reader) {
 }
 
 // ReadRequest reads and parses an incoming request from b.
-func ReadRequest(b *bufio.Reader) (req *Request, err error) {
+func ReadRequest(b *bufio.Reader) (req *Request, err error) { return readRequest(b, deleteHostHeader) }
 
+// Constants for readRequest's deleteHostHeader parameter.
+const (
+	deleteHostHeader = true
+	keepHostHeader   = false
+)
+
+func readRequest(b *bufio.Reader, deleteHostHeader bool) (req *Request, err error) {
 	tp := newTextprotoReader(b)
 	req = new(Request)
 
@@ -711,7 +779,9 @@ func ReadRequest(b *bufio.Reader) (req *Request, err error) {
 	if req.Host == "" {
 		req.Host = req.Header.get("Host")
 	}
-	delete(req.Header, "Host")
+	if deleteHostHeader {
+		delete(req.Header, "Host")
+	}
 
 	fixPragmaCacheControl(req.Header)
 
@@ -1006,3 +1076,102 @@ func (r *Request) closeBody() {
 		r.Body.Close()
 	}
 }
+
+func (r *Request) isReplayable() bool {
+	if r.Body == nil {
+		switch valueOrDefault(r.Method, "GET") {
+		case "GET", "HEAD", "OPTIONS", "TRACE":
+			return true
+		}
+	}
+	return false
+}
+
+func validHostHeader(h string) bool {
+	// The latests spec is actually this:
+	//
+	// http://tools.ietf.org/html/rfc7230#section-5.4
+	//     Host = uri-host [ ":" port ]
+	//
+	// Where uri-host is:
+	//     http://tools.ietf.org/html/rfc3986#section-3.2.2
+	//
+	// But we're going to be much more lenient for now and just
+	// search for any byte that's not a valid byte in any of those
+	// expressions.
+	for i := 0; i < len(h); i++ {
+		if !validHostByte[h[i]] {
+			return false
+		}
+	}
+	return true
+}
+
+// See the validHostHeader comment.
+var validHostByte = [256]bool{
+	'0': true, '1': true, '2': true, '3': true, '4': true, '5': true, '6': true, '7': true,
+	'8': true, '9': true,
+
+	'a': true, 'b': true, 'c': true, 'd': true, 'e': true, 'f': true, 'g': true, 'h': true,
+	'i': true, 'j': true, 'k': true, 'l': true, 'm': true, 'n': true, 'o': true, 'p': true,
+	'q': true, 'r': true, 's': true, 't': true, 'u': true, 'v': true, 'w': true, 'x': true,
+	'y': true, 'z': true,
+
+	'A': true, 'B': true, 'C': true, 'D': true, 'E': true, 'F': true, 'G': true, 'H': true,
+	'I': true, 'J': true, 'K': true, 'L': true, 'M': true, 'N': true, 'O': true, 'P': true,
+	'Q': true, 'R': true, 'S': true, 'T': true, 'U': true, 'V': true, 'W': true, 'X': true,
+	'Y': true, 'Z': true,
+
+	'!':  true, // sub-delims
+	'$':  true, // sub-delims
+	'%':  true, // pct-encoded (and used in IPv6 zones)
+	'&':  true, // sub-delims
+	'(':  true, // sub-delims
+	')':  true, // sub-delims
+	'*':  true, // sub-delims
+	'+':  true, // sub-delims
+	',':  true, // sub-delims
+	'-':  true, // unreserved
+	'.':  true, // unreserved
+	':':  true, // IPv6address + Host expression's optional port
+	';':  true, // sub-delims
+	'=':  true, // sub-delims
+	'[':  true,
+	'\'': true, // sub-delims
+	']':  true,
+	'_':  true, // unreserved
+	'~':  true, // unreserved
+}
+
+func validHeaderName(v string) bool {
+	if len(v) == 0 {
+		return false
+	}
+	return strings.IndexFunc(v, isNotToken) == -1
+}
+
+// validHeaderValue reports whether v is a valid "field-value" according to
+// http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 :
+//
+//        message-header = field-name ":" [ field-value ]
+//        field-value    = *( field-content | LWS )
+//        field-content  = <the OCTETs making up the field-value
+//                         and consisting of either *TEXT or combinations
+//                         of token, separators, and quoted-string>
+//
+// http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2 :
+//
+//        TEXT           = <any OCTET except CTLs,
+//                          but including LWS>
+//        LWS            = [CRLF] 1*( SP | HT )
+//        CTL            = <any US-ASCII control character
+//                         (octets 0 - 31) and DEL (127)>
+func validHeaderValue(v string) bool {
+	for i := 0; i < len(v); i++ {
+		b := v[i]
+		if isCTL(b) && !isLWS(b) {
+			return false
+		}
+	}
+	return true
+}
diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go
index 627620c..0ecdf85 100644
--- a/src/net/http/request_test.go
+++ b/src/net/http/request_test.go
@@ -13,7 +13,6 @@ import (
 	"io/ioutil"
 	"mime/multipart"
 	. "net/http"
-	"net/http/httptest"
 	"net/url"
 	"os"
 	"reflect"
@@ -177,9 +176,11 @@ func TestParseMultipartForm(t *testing.T) {
 	}
 }
 
-func TestRedirect(t *testing.T) {
+func TestRedirect_h1(t *testing.T) { testRedirect(t, h1Mode) }
+func TestRedirect_h2(t *testing.T) { testRedirect(t, h2Mode) }
+func testRedirect(t *testing.T, h2 bool) {
 	defer afterTest(t)
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
 		switch r.URL.Path {
 		case "/":
 			w.Header().Set("Location", "/foo/")
@@ -190,10 +191,10 @@ func TestRedirect(t *testing.T) {
 			w.WriteHeader(StatusBadRequest)
 		}
 	}))
-	defer ts.Close()
+	defer cst.close()
 
 	var end = regexp.MustCompile("/foo/$")
-	r, err := Get(ts.URL)
+	r, err := cst.c.Get(cst.ts.URL)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -355,6 +356,29 @@ func TestNewRequestHost(t *testing.T) {
 	}
 }
 
+func TestRequestInvalidMethod(t *testing.T) {
+	_, err := NewRequest("bad method", "http://foo.com/", nil)
+	if err == nil {
+		t.Error("expected error from NewRequest with invalid method")
+	}
+	req, err := NewRequest("GET", "http://foo.example/", nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	req.Method = "bad method"
+	_, err = DefaultClient.Do(req)
+	if err == nil || !strings.Contains(err.Error(), "invalid method") {
+		t.Errorf("Transport error = %v; want invalid method", err)
+	}
+
+	req, err = NewRequest("", "http://foo.com/", nil)
+	if err != nil {
+		t.Errorf("NewRequest(empty method) = %v; want nil", err)
+	} else if req.Method != "GET" {
+		t.Errorf("NewRequest(empty method) has method %q; want GET", req.Method)
+	}
+}
+
 func TestNewRequestContentLength(t *testing.T) {
 	readByte := func(r io.Reader) io.Reader {
 		var b [1]byte
@@ -515,10 +539,12 @@ func TestRequestWriteBufferedWriter(t *testing.T) {
 
 func TestRequestBadHost(t *testing.T) {
 	got := []string{}
-	req, err := NewRequest("GET", "http://foo.com with spaces/after", nil)
+	req, err := NewRequest("GET", "http://foo/after", nil)
 	if err != nil {
 		t.Fatal(err)
 	}
+	req.Host = "foo.com with spaces"
+	req.URL.Host = "foo.com with spaces"
 	req.Write(logWrites{t, &got})
 	want := []string{
 		"GET /after HTTP/1.1\r\n",
diff --git a/src/net/http/response.go b/src/net/http/response.go
index 76b8538..c424f61 100644
--- a/src/net/http/response.go
+++ b/src/net/http/response.go
@@ -72,8 +72,18 @@ type Response struct {
 	// ReadResponse nor Response.Write ever closes a connection.
 	Close bool
 
-	// Trailer maps trailer keys to values, in the same
-	// format as the header.
+	// Trailer maps trailer keys to values in the same
+	// format as Header.
+	//
+	// The Trailer initially contains only nil values, one for
+	// each key specified in the server's "Trailer" header
+	// value. Those values are not added to Header.
+	//
+	// Trailer must not be accessed concurrently with Read calls
+	// on the Body.
+	//
+	// After Body.Read has returned io.EOF, Trailer will contain
+	// any trailer values sent by the server.
 	Trailer Header
 
 	// The Request that was sent to obtain this Response.
@@ -140,12 +150,14 @@ func ReadResponse(r *bufio.Reader, req *Request) (*Response, error) {
 	if len(f) > 2 {
 		reasonPhrase = f[2]
 	}
-	resp.Status = f[1] + " " + reasonPhrase
+	if len(f[1]) != 3 {
+		return nil, &badStringError{"malformed HTTP status code", f[1]}
+	}
 	resp.StatusCode, err = strconv.Atoi(f[1])
-	if err != nil {
+	if err != nil || resp.StatusCode < 0 {
 		return nil, &badStringError{"malformed HTTP status code", f[1]}
 	}
-
+	resp.Status = f[1] + " " + reasonPhrase
 	resp.Proto = f[0]
 	var ok bool
 	if resp.ProtoMajor, resp.ProtoMinor, ok = ParseHTTPVersion(resp.Proto); !ok {
diff --git a/src/net/http/response_test.go b/src/net/http/response_test.go
index 421cf55..d8a5340 100644
--- a/src/net/http/response_test.go
+++ b/src/net/http/response_test.go
@@ -456,8 +456,59 @@ some body`,
 
 		"",
 	},
+
+	// Issue 12785: HTTP/1.0 response with bogus (to be ignored) Transfer-Encoding.
+	// Without a Content-Length.
+	{
+		"HTTP/1.0 200 OK\r\n" +
+			"Transfer-Encoding: bogus\r\n" +
+			"\r\n" +
+			"Body here\n",
+
+		Response{
+			Status:        "200 OK",
+			StatusCode:    200,
+			Proto:         "HTTP/1.0",
+			ProtoMajor:    1,
+			ProtoMinor:    0,
+			Request:       dummyReq("GET"),
+			Header:        Header{},
+			Close:         true,
+			ContentLength: -1,
+		},
+
+		"Body here\n",
+	},
+
+	// Issue 12785: HTTP/1.0 response with bogus (to be ignored) Transfer-Encoding.
+	// With a Content-Length.
+	{
+		"HTTP/1.0 200 OK\r\n" +
+			"Transfer-Encoding: bogus\r\n" +
+			"Content-Length: 10\r\n" +
+			"\r\n" +
+			"Body here\n",
+
+		Response{
+			Status:     "200 OK",
+			StatusCode: 200,
+			Proto:      "HTTP/1.0",
+			ProtoMajor: 1,
+			ProtoMinor: 0,
+			Request:    dummyReq("GET"),
+			Header: Header{
+				"Content-Length": {"10"},
+			},
+			Close:         true,
+			ContentLength: 10,
+		},
+
+		"Body here\n",
+	},
 }
 
+// tests successful calls to ReadResponse, and inspects the returned Response.
+// For error cases, see TestReadResponseErrors below.
 func TestReadResponse(t *testing.T) {
 	for i, tt := range respTests {
 		resp, err := ReadResponse(bufio.NewReader(strings.NewReader(tt.Raw)), tt.Resp.Request)
@@ -624,6 +675,7 @@ var responseLocationTests = []responseLocationTest{
 	{"/foo", "http://bar.com/baz", "http://bar.com/foo", nil},
 	{"http://foo.com/", "http://bar.com/baz", "http://foo.com/", nil},
 	{"", "http://bar.com/baz", "", ErrNoLocation},
+	{"/bar", "", "/bar", nil},
 }
 
 func TestLocationResponse(t *testing.T) {
@@ -702,13 +754,106 @@ func TestResponseContentLengthShortBody(t *testing.T) {
 	}
 }
 
-func TestReadResponseUnexpectedEOF(t *testing.T) {
-	br := bufio.NewReader(strings.NewReader("HTTP/1.1 301 Moved Permanently\r\n" +
-		"Location: http://example.com"))
-	_, err := ReadResponse(br, nil)
-	if err != io.ErrUnexpectedEOF {
-		t.Errorf("ReadResponse = %v; want io.ErrUnexpectedEOF", err)
+// Test various ReadResponse error cases. (also tests success cases, but mostly
+// it's about errors).  This does not test anything involving the bodies. Only
+// the return value from ReadResponse itself.
+func TestReadResponseErrors(t *testing.T) {
+	type testCase struct {
+		name    string // optional, defaults to in
+		in      string
+		wantErr interface{} // nil, err value, or string substring
+	}
+
+	status := func(s string, wantErr interface{}) testCase {
+		if wantErr == true {
+			wantErr = "malformed HTTP status code"
+		}
+		return testCase{
+			name:    fmt.Sprintf("status %q", s),
+			in:      "HTTP/1.1 " + s + "\r\nFoo: bar\r\n\r\n",
+			wantErr: wantErr,
+		}
+	}
+
+	version := func(s string, wantErr interface{}) testCase {
+		if wantErr == true {
+			wantErr = "malformed HTTP version"
+		}
+		return testCase{
+			name:    fmt.Sprintf("version %q", s),
+			in:      s + " 200 OK\r\n\r\n",
+			wantErr: wantErr,
+		}
+	}
+
+	tests := []testCase{
+		{"", "", io.ErrUnexpectedEOF},
+		{"", "HTTP/1.1 301 Moved Permanently\r\nFoo: bar", io.ErrUnexpectedEOF},
+		{"", "HTTP/1.1", "malformed HTTP response"},
+		{"", "HTTP/2.0", "malformed HTTP response"},
+		status("20X Unknown", true),
+		status("abcd Unknown", true),
+		status("二百/两百 OK", true),
+		status(" Unknown", true),
+		status("c8 OK", true),
+		status("0x12d Moved Permanently", true),
+		status("200 OK", nil),
+		status("000 OK", nil),
+		status("001 OK", nil),
+		status("404 NOTFOUND", nil),
+		status("20 OK", true),
+		status("00 OK", true),
+		status("-10 OK", true),
+		status("1000 OK", true),
+		status("999 Done", nil),
+		status("-1 OK", true),
+		status("-200 OK", true),
+		version("HTTP/1.2", nil),
+		version("HTTP/2.0", nil),
+		version("HTTP/1.100000000002", true),
+		version("HTTP/1.-1", true),
+		version("HTTP/A.B", true),
+		version("HTTP/1", true),
+		version("http/1.1", true),
+	}
+	for i, tt := range tests {
+		br := bufio.NewReader(strings.NewReader(tt.in))
+		_, rerr := ReadResponse(br, nil)
+		if err := matchErr(rerr, tt.wantErr); err != nil {
+			name := tt.name
+			if name == "" {
+				name = fmt.Sprintf("%d. input %q", i, tt.in)
+			}
+			t.Errorf("%s: %v", name, err)
+		}
+	}
+}
+
+// wantErr can be nil, an error value to match exactly, or type string to
+// match a substring.
+func matchErr(err error, wantErr interface{}) error {
+	if err == nil {
+		if wantErr == nil {
+			return nil
+		}
+		if sub, ok := wantErr.(string); ok {
+			return fmt.Errorf("unexpected success; want error with substring %q", sub)
+		}
+		return fmt.Errorf("unexpected success; want error %v", wantErr)
+	}
+	if wantErr == nil {
+		return fmt.Errorf("%v; want success", err)
+	}
+	if sub, ok := wantErr.(string); ok {
+		if strings.Contains(err.Error(), sub) {
+			return nil
+		}
+		return fmt.Errorf("error = %v; want an error with substring %q", err, sub)
+	}
+	if err == wantErr {
+		return nil
 	}
+	return fmt.Errorf("%v; want %v", err, wantErr)
 }
 
 func TestNeedsSniff(t *testing.T) {
diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go
index d51417e..384b453 100644
--- a/src/net/http/serve_test.go
+++ b/src/net/http/serve_test.go
@@ -12,6 +12,7 @@ import (
 	"crypto/tls"
 	"errors"
 	"fmt"
+	"internal/testenv"
 	"io"
 	"io/ioutil"
 	"log"
@@ -26,6 +27,8 @@ import (
 	"os/exec"
 	"reflect"
 	"runtime"
+	"runtime/debug"
+	"sort"
 	"strconv"
 	"strings"
 	"sync"
@@ -96,6 +99,7 @@ func (c *rwTestConn) Close() error {
 }
 
 type testConn struct {
+	readMu   sync.Mutex // for TestHandlerBodyClose
 	readBuf  bytes.Buffer
 	writeBuf bytes.Buffer
 	closec   chan bool // if non-nil, send value to it on close
@@ -103,6 +107,8 @@ type testConn struct {
 }
 
 func (c *testConn) Read(b []byte) (int, error) {
+	c.readMu.Lock()
+	defer c.readMu.Unlock()
 	return c.readBuf.Read(b)
 }
 
@@ -450,6 +456,7 @@ func TestServerTimeouts(t *testing.T) {
 	if runtime.GOOS == "plan9" {
 		t.Skip("skipping test; see https://golang.org/issue/7237")
 	}
+	setParallel(t)
 	defer afterTest(t)
 	reqNum := 0
 	ts := httptest.NewUnstartedServer(HandlerFunc(func(res ResponseWriter, req *Request) {
@@ -734,14 +741,17 @@ func TestHandlersCanSetConnectionClose10(t *testing.T) {
 	}))
 }
 
-func TestSetsRemoteAddr(t *testing.T) {
+func TestSetsRemoteAddr_h1(t *testing.T) { testSetsRemoteAddr(t, h1Mode) }
+func TestSetsRemoteAddr_h2(t *testing.T) { testSetsRemoteAddr(t, h2Mode) }
+
+func testSetsRemoteAddr(t *testing.T, h2 bool) {
 	defer afterTest(t)
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
 		fmt.Fprintf(w, "%s", r.RemoteAddr)
 	}))
-	defer ts.Close()
+	defer cst.close()
 
-	res, err := Get(ts.URL)
+	res, err := cst.c.Get(cst.ts.URL)
 	if err != nil {
 		t.Fatalf("Get error: %v", err)
 	}
@@ -755,34 +765,106 @@ func TestSetsRemoteAddr(t *testing.T) {
 	}
 }
 
-func TestChunkedResponseHeaders(t *testing.T) {
-	defer afterTest(t)
-	log.SetOutput(ioutil.Discard) // is noisy otherwise
-	defer log.SetOutput(os.Stderr)
+type blockingRemoteAddrListener struct {
+	net.Listener
+	conns chan<- net.Conn
+}
 
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		w.Header().Set("Content-Length", "intentional gibberish") // we check that this is deleted
-		w.(Flusher).Flush()
-		fmt.Fprintf(w, "I am a chunked response.")
+func (l *blockingRemoteAddrListener) Accept() (net.Conn, error) {
+	c, err := l.Listener.Accept()
+	if err != nil {
+		return nil, err
+	}
+	brac := &blockingRemoteAddrConn{
+		Conn:  c,
+		addrs: make(chan net.Addr, 1),
+	}
+	l.conns <- brac
+	return brac, nil
+}
+
+type blockingRemoteAddrConn struct {
+	net.Conn
+	addrs chan net.Addr
+}
+
+func (c *blockingRemoteAddrConn) RemoteAddr() net.Addr {
+	return <-c.addrs
+}
+
+// Issue 12943
+func TestServerAllowsBlockingRemoteAddr(t *testing.T) {
+	defer afterTest(t)
+	ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		fmt.Fprintf(w, "RA:%s", r.RemoteAddr)
 	}))
+	conns := make(chan net.Conn)
+	ts.Listener = &blockingRemoteAddrListener{
+		Listener: ts.Listener,
+		conns:    conns,
+	}
+	ts.Start()
 	defer ts.Close()
 
-	res, err := Get(ts.URL)
-	if err != nil {
-		t.Fatalf("Get error: %v", err)
+	tr := &Transport{DisableKeepAlives: true}
+	defer tr.CloseIdleConnections()
+	c := &Client{Transport: tr, Timeout: time.Second}
+
+	fetch := func(response chan string) {
+		resp, err := c.Get(ts.URL)
+		if err != nil {
+			t.Error(err)
+			response <- ""
+			return
+		}
+		defer resp.Body.Close()
+		body, err := ioutil.ReadAll(resp.Body)
+		if err != nil {
+			t.Error(err)
+			response <- ""
+			return
+		}
+		response <- string(body)
 	}
-	defer res.Body.Close()
-	if g, e := res.ContentLength, int64(-1); g != e {
-		t.Errorf("expected ContentLength of %d; got %d", e, g)
+
+	// Start a request. The server will block on getting conn.RemoteAddr.
+	response1c := make(chan string, 1)
+	go fetch(response1c)
+
+	// Wait for the server to accept it; grab the connection.
+	conn1 := <-conns
+
+	// Start another request and grab its connection
+	response2c := make(chan string, 1)
+	go fetch(response2c)
+	var conn2 net.Conn
+
+	select {
+	case conn2 = <-conns:
+	case <-time.After(time.Second):
+		t.Fatal("Second Accept didn't happen")
 	}
-	if g, e := res.TransferEncoding, []string{"chunked"}; !reflect.DeepEqual(g, e) {
-		t.Errorf("expected TransferEncoding of %v; got %v", e, g)
+
+	// Send a response on connection 2.
+	conn2.(*blockingRemoteAddrConn).addrs <- &net.TCPAddr{
+		IP: net.ParseIP("12.12.12.12"), Port: 12}
+
+	// ... and see it
+	response2 := <-response2c
+	if g, e := response2, "RA:12.12.12.12:12"; g != e {
+		t.Fatalf("response 2 addr = %q; want %q", g, e)
 	}
-	if _, haveCL := res.Header["Content-Length"]; haveCL {
-		t.Errorf("Unexpected Content-Length")
+
+	// Finish the first response.
+	conn1.(*blockingRemoteAddrConn).addrs <- &net.TCPAddr{
+		IP: net.ParseIP("21.21.21.21"), Port: 21}
+
+	// ... and see it
+	response1 := <-response1c
+	if g, e := response1, "RA:21.21.21.21:21"; g != e {
+		t.Fatalf("response 1 addr = %q; want %q", g, e)
 	}
 }
-
 func TestIdentityResponseHeaders(t *testing.T) {
 	defer afterTest(t)
 	log.SetOutput(ioutil.Discard) // is noisy otherwise
@@ -812,40 +894,14 @@ func TestIdentityResponseHeaders(t *testing.T) {
 	}
 }
 
-// Test304Responses verifies that 304s don't declare that they're
-// chunking in their response headers and aren't allowed to produce
-// output.
-func Test304Responses(t *testing.T) {
-	defer afterTest(t)
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		w.WriteHeader(StatusNotModified)
-		_, err := w.Write([]byte("illegal body"))
-		if err != ErrBodyNotAllowed {
-			t.Errorf("on Write, expected ErrBodyNotAllowed, got %v", err)
-		}
-	}))
-	defer ts.Close()
-	res, err := Get(ts.URL)
-	if err != nil {
-		t.Error(err)
-	}
-	if len(res.TransferEncoding) > 0 {
-		t.Errorf("expected no TransferEncoding; got %v", res.TransferEncoding)
-	}
-	body, err := ioutil.ReadAll(res.Body)
-	if err != nil {
-		t.Error(err)
-	}
-	if len(body) > 0 {
-		t.Errorf("got unexpected body %q", string(body))
-	}
-}
-
 // TestHeadResponses verifies that all MIME type sniffing and Content-Length
 // counting of GET requests also happens on HEAD requests.
-func TestHeadResponses(t *testing.T) {
+func TestHeadResponses_h1(t *testing.T) { testHeadResponses(t, h1Mode) }
+func TestHeadResponses_h2(t *testing.T) { testHeadResponses(t, h2Mode) }
+
+func testHeadResponses(t *testing.T, h2 bool) {
 	defer afterTest(t)
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
 		_, err := w.Write([]byte("<html>"))
 		if err != nil {
 			t.Errorf("ResponseWriter.Write: %v", err)
@@ -857,8 +913,8 @@ func TestHeadResponses(t *testing.T) {
 			t.Errorf("Copy(ResponseWriter, ...): %v", err)
 		}
 	}))
-	defer ts.Close()
-	res, err := Head(ts.URL)
+	defer cst.close()
+	res, err := cst.c.Head(cst.ts.URL)
 	if err != nil {
 		t.Error(err)
 	}
@@ -884,6 +940,7 @@ func TestTLSHandshakeTimeout(t *testing.T) {
 	if runtime.GOOS == "plan9" {
 		t.Skip("skipping test; see https://golang.org/issue/7237")
 	}
+	setParallel(t)
 	defer afterTest(t)
 	ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
 	errc := make(chanWriter, 10) // but only expecting 1
@@ -967,6 +1024,95 @@ func TestTLSServer(t *testing.T) {
 	})
 }
 
+func TestAutomaticHTTP2_Serve(t *testing.T) {
+	defer afterTest(t)
+	ln := newLocalListener(t)
+	ln.Close() // immediately (not a defer!)
+	var s Server
+	if err := s.Serve(ln); err == nil {
+		t.Fatal("expected an error")
+	}
+	on := s.TLSNextProto["h2"] != nil
+	if !on {
+		t.Errorf("http2 wasn't automatically enabled")
+	}
+}
+
+func TestAutomaticHTTP2_ListenAndServe(t *testing.T) {
+	cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey)
+	if err != nil {
+		t.Fatal(err)
+	}
+	testAutomaticHTTP2_ListenAndServe(t, &tls.Config{
+		Certificates: []tls.Certificate{cert},
+	})
+}
+
+func TestAutomaticHTTP2_ListenAndServe_GetCertificate(t *testing.T) {
+	cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey)
+	if err != nil {
+		t.Fatal(err)
+	}
+	testAutomaticHTTP2_ListenAndServe(t, &tls.Config{
+		GetCertificate: func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
+			return &cert, nil
+		},
+	})
+}
+
+func testAutomaticHTTP2_ListenAndServe(t *testing.T, tlsConf *tls.Config) {
+	defer afterTest(t)
+	defer SetTestHookServerServe(nil)
+	var ok bool
+	var s *Server
+	const maxTries = 5
+	var ln net.Listener
+Try:
+	for try := 0; try < maxTries; try++ {
+		ln = newLocalListener(t)
+		addr := ln.Addr().String()
+		ln.Close()
+		t.Logf("Got %v", addr)
+		lnc := make(chan net.Listener, 1)
+		SetTestHookServerServe(func(s *Server, ln net.Listener) {
+			lnc <- ln
+		})
+		s = &Server{
+			Addr:      addr,
+			TLSConfig: tlsConf,
+		}
+		errc := make(chan error, 1)
+		go func() { errc <- s.ListenAndServeTLS("", "") }()
+		select {
+		case err := <-errc:
+			t.Logf("On try #%v: %v", try+1, err)
+			continue
+		case ln = <-lnc:
+			ok = true
+			t.Logf("Listening on %v", ln.Addr().String())
+			break Try
+		}
+	}
+	if !ok {
+		t.Fatalf("Failed to start up after %d tries", maxTries)
+	}
+	defer ln.Close()
+	c, err := tls.Dial("tcp", ln.Addr().String(), &tls.Config{
+		InsecureSkipVerify: true,
+		NextProtos:         []string{"h2", "http/1.1"},
+	})
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer c.Close()
+	if got, want := c.ConnectionState().NegotiatedProtocol, "h2"; got != want {
+		t.Errorf("NegotiatedProtocol = %q; want %q", got, want)
+	}
+	if got, want := c.ConnectionState().NegotiatedProtocolIsMutual, true; got != want {
+		t.Errorf("NegotiatedProtocolIsMutual = %v; want %v", got, want)
+	}
+}
+
 type serverExpectTest struct {
 	contentLength    int // of request body
 	chunked          bool
@@ -1016,6 +1162,7 @@ var serverExpectTests = []serverExpectTest{
 
 // Tests that the server responds to the "Expect" request header
 // correctly.
+// http2 test: TestServer_Response_Automatic100Continue
 func TestServerExpect(t *testing.T) {
 	defer afterTest(t)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -1122,15 +1269,21 @@ func TestServerUnreadRequestBodyLittle(t *testing.T) {
 
 	done := make(chan bool)
 
+	readBufLen := func() int {
+		conn.readMu.Lock()
+		defer conn.readMu.Unlock()
+		return conn.readBuf.Len()
+	}
+
 	ls := &oneConnListener{conn}
 	go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
 		defer close(done)
-		if conn.readBuf.Len() < len(body)/2 {
-			t.Errorf("on request, read buffer length is %d; expected about 100 KB", conn.readBuf.Len())
+		if bufLen := readBufLen(); bufLen < len(body)/2 {
+			t.Errorf("on request, read buffer length is %d; expected about 100 KB", bufLen)
 		}
 		rw.WriteHeader(200)
 		rw.(Flusher).Flush()
-		if g, e := conn.readBuf.Len(), 0; g != e {
+		if g, e := readBufLen(), 0; g != e {
 			t.Errorf("after WriteHeader, read buffer length is %d; want %d", g, e)
 		}
 		if c := rw.Header().Get("Connection"); c != "" {
@@ -1144,6 +1297,9 @@ func TestServerUnreadRequestBodyLittle(t *testing.T) {
 // should ignore client request bodies that a handler didn't read
 // and close the connection.
 func TestServerUnreadRequestBodyLarge(t *testing.T) {
+	if testing.Short() && testenv.Builder() == "" {
+		t.Log("skipping in short mode")
+	}
 	conn := new(testConn)
 	body := strings.Repeat("x", 1<<20)
 	conn.readBuf.Write([]byte(fmt.Sprintf(
@@ -1274,6 +1430,9 @@ var handlerBodyCloseTests = [...]handlerBodyCloseTest{
 }
 
 func TestHandlerBodyClose(t *testing.T) {
+	if testing.Short() && testenv.Builder() == "" {
+		t.Skip("skipping in -short mode")
+	}
 	for i, tt := range handlerBodyCloseTests {
 		testHandlerBodyClose(t, i, tt)
 	}
@@ -1306,15 +1465,21 @@ func testHandlerBodyClose(t *testing.T, i int, tt handlerBodyCloseTest) {
 	}
 	conn.closec = make(chan bool, 1)
 
+	readBufLen := func() int {
+		conn.readMu.Lock()
+		defer conn.readMu.Unlock()
+		return conn.readBuf.Len()
+	}
+
 	ls := &oneConnListener{conn}
 	var numReqs int
 	var size0, size1 int
 	go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
 		numReqs++
 		if numReqs == 1 {
-			size0 = conn.readBuf.Len()
+			size0 = readBufLen()
 			req.Body.Close()
-			size1 = conn.readBuf.Len()
+			size1 = readBufLen()
 		}
 	}))
 	<-conn.closec
@@ -1414,7 +1579,9 @@ type slowTestConn struct {
 	// over multiple calls to Read, time.Durations are slept, strings are read.
 	script []interface{}
 	closec chan bool
-	rd, wd time.Time // read, write deadline
+
+	mu     sync.Mutex // guards rd/wd
+	rd, wd time.Time  // read, write deadline
 	noopConn
 }
 
@@ -1425,16 +1592,22 @@ func (c *slowTestConn) SetDeadline(t time.Time) error {
 }
 
 func (c *slowTestConn) SetReadDeadline(t time.Time) error {
+	c.mu.Lock()
+	defer c.mu.Unlock()
 	c.rd = t
 	return nil
 }
 
 func (c *slowTestConn) SetWriteDeadline(t time.Time) error {
+	c.mu.Lock()
+	defer c.mu.Unlock()
 	c.wd = t
 	return nil
 }
 
 func (c *slowTestConn) Read(b []byte) (n int, err error) {
+	c.mu.Lock()
+	defer c.mu.Unlock()
 restart:
 	if !c.rd.IsZero() && time.Now().After(c.rd) {
 		return 0, syscall.ETIMEDOUT
@@ -1531,7 +1704,9 @@ func TestRequestBodyTimeoutClosesConnection(t *testing.T) {
 	}
 }
 
-func TestTimeoutHandler(t *testing.T) {
+func TestTimeoutHandler_h1(t *testing.T) { testTimeoutHandler(t, h1Mode) }
+func TestTimeoutHandler_h2(t *testing.T) { testTimeoutHandler(t, h2Mode) }
+func testTimeoutHandler(t *testing.T, h2 bool) {
 	defer afterTest(t)
 	sendHi := make(chan bool, 1)
 	writeErrors := make(chan error, 1)
@@ -1541,12 +1716,12 @@ func TestTimeoutHandler(t *testing.T) {
 		writeErrors <- werr
 	})
 	timeout := make(chan time.Time, 1) // write to this to force timeouts
-	ts := httptest.NewServer(NewTestTimeoutHandler(sayHi, timeout))
-	defer ts.Close()
+	cst := newClientServerTest(t, h2, NewTestTimeoutHandler(sayHi, timeout))
+	defer cst.close()
 
 	// Succeed without timing out:
 	sendHi <- true
-	res, err := Get(ts.URL)
+	res, err := cst.c.Get(cst.ts.URL)
 	if err != nil {
 		t.Error(err)
 	}
@@ -1563,7 +1738,7 @@ func TestTimeoutHandler(t *testing.T) {
 
 	// Times out:
 	timeout <- time.Time{}
-	res, err = Get(ts.URL)
+	res, err = cst.c.Get(cst.ts.URL)
 	if err != nil {
 		t.Error(err)
 	}
@@ -1659,6 +1834,60 @@ func TestTimeoutHandlerRaceHeader(t *testing.T) {
 	wg.Wait()
 }
 
+// Issue 9162
+func TestTimeoutHandlerRaceHeaderTimeout(t *testing.T) {
+	defer afterTest(t)
+	sendHi := make(chan bool, 1)
+	writeErrors := make(chan error, 1)
+	sayHi := HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("Content-Type", "text/plain")
+		<-sendHi
+		_, werr := w.Write([]byte("hi"))
+		writeErrors <- werr
+	})
+	timeout := make(chan time.Time, 1) // write to this to force timeouts
+	cst := newClientServerTest(t, h1Mode, NewTestTimeoutHandler(sayHi, timeout))
+	defer cst.close()
+
+	// Succeed without timing out:
+	sendHi <- true
+	res, err := cst.c.Get(cst.ts.URL)
+	if err != nil {
+		t.Error(err)
+	}
+	if g, e := res.StatusCode, StatusOK; g != e {
+		t.Errorf("got res.StatusCode %d; expected %d", g, e)
+	}
+	body, _ := ioutil.ReadAll(res.Body)
+	if g, e := string(body), "hi"; g != e {
+		t.Errorf("got body %q; expected %q", g, e)
+	}
+	if g := <-writeErrors; g != nil {
+		t.Errorf("got unexpected Write error on first request: %v", g)
+	}
+
+	// Times out:
+	timeout <- time.Time{}
+	res, err = cst.c.Get(cst.ts.URL)
+	if err != nil {
+		t.Error(err)
+	}
+	if g, e := res.StatusCode, StatusServiceUnavailable; g != e {
+		t.Errorf("got res.StatusCode %d; expected %d", g, e)
+	}
+	body, _ = ioutil.ReadAll(res.Body)
+	if !strings.Contains(string(body), "<title>Timeout</title>") {
+		t.Errorf("expected timeout body; got %q", string(body))
+	}
+
+	// Now make the previously-timed out handler speak again,
+	// which verifies the panic is handled:
+	sendHi <- true
+	if g, e := <-writeErrors, ErrHandlerTimeout; g != e {
+		t.Errorf("expected Write error of %v; got %v", e, g)
+	}
+}
+
 // Verifies we don't path.Clean() on the wrong parts in redirects.
 func TestRedirectMunging(t *testing.T) {
 	req, _ := NewRequest("GET", "http://example.com/", nil)
@@ -1693,15 +1922,57 @@ func TestRedirectBadPath(t *testing.T) {
 	}
 }
 
+// Test different URL formats and schemes
+func TestRedirectURLFormat(t *testing.T) {
+	req, _ := NewRequest("GET", "http://example.com/qux/", nil)
+
+	var tests = []struct {
+		in   string
+		want string
+	}{
+		// normal http
+		{"http://foobar.com/baz", "http://foobar.com/baz"},
+		// normal https
+		{"https://foobar.com/baz", "https://foobar.com/baz"},
+		// custom scheme
+		{"test://foobar.com/baz", "test://foobar.com/baz"},
+		// schemeless
+		{"//foobar.com/baz", "//foobar.com/baz"},
+		// relative to the root
+		{"/foobar.com/baz", "/foobar.com/baz"},
+		// relative to the current path
+		{"foobar.com/baz", "/qux/foobar.com/baz"},
+		// relative to the current path (+ going upwards)
+		{"../quux/foobar.com/baz", "/quux/foobar.com/baz"},
+		// incorrect number of slashes
+		{"///foobar.com/baz", "/foobar.com/baz"},
+	}
+
+	for _, tt := range tests {
+		rec := httptest.NewRecorder()
+		Redirect(rec, req, tt.in, 302)
+		if got := rec.Header().Get("Location"); got != tt.want {
+			t.Errorf("Redirect(%q) generated Location header %q; want %q", tt.in, got, tt.want)
+		}
+	}
+}
+
 // TestZeroLengthPostAndResponse exercises an optimization done by the Transport:
 // when there is no body (either because the method doesn't permit a body, or an
 // explicit Content-Length of zero is present), then the transport can re-use the
 // connection immediately. But when it re-uses the connection, it typically closes
 // the previous request's body, which is not optimal for zero-lengthed bodies,
 // as the client would then see http.ErrBodyReadAfterClose and not 0, io.EOF.
-func TestZeroLengthPostAndResponse(t *testing.T) {
+func TestZeroLengthPostAndResponse_h1(t *testing.T) {
+	testZeroLengthPostAndResponse(t, h1Mode)
+}
+func TestZeroLengthPostAndResponse_h2(t *testing.T) {
+	testZeroLengthPostAndResponse(t, h2Mode)
+}
+
+func testZeroLengthPostAndResponse(t *testing.T, h2 bool) {
 	defer afterTest(t)
-	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, r *Request) {
+	cst := newClientServerTest(t, h2, HandlerFunc(func(rw ResponseWriter, r *Request) {
 		all, err := ioutil.ReadAll(r.Body)
 		if err != nil {
 			t.Fatalf("handler ReadAll: %v", err)
@@ -1711,9 +1982,9 @@ func TestZeroLengthPostAndResponse(t *testing.T) {
 		}
 		rw.Header().Set("Content-Length", "0")
 	}))
-	defer ts.Close()
+	defer cst.close()
 
-	req, err := NewRequest("POST", ts.URL, strings.NewReader(""))
+	req, err := NewRequest("POST", cst.ts.URL, strings.NewReader(""))
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -1721,7 +1992,7 @@ func TestZeroLengthPostAndResponse(t *testing.T) {
 
 	var resp [5]*Response
 	for i := range resp {
-		resp[i], err = DefaultClient.Do(req)
+		resp[i], err = cst.c.Do(req)
 		if err != nil {
 			t.Fatalf("client post #%d: %v", i, err)
 		}
@@ -1738,19 +2009,22 @@ func TestZeroLengthPostAndResponse(t *testing.T) {
 	}
 }
 
-func TestHandlerPanicNil(t *testing.T) {
-	testHandlerPanic(t, false, nil)
-}
+func TestHandlerPanicNil_h1(t *testing.T) { testHandlerPanic(t, false, h1Mode, nil) }
+func TestHandlerPanicNil_h2(t *testing.T) { testHandlerPanic(t, false, h2Mode, nil) }
 
-func TestHandlerPanic(t *testing.T) {
-	testHandlerPanic(t, false, "intentional death for testing")
+func TestHandlerPanic_h1(t *testing.T) {
+	testHandlerPanic(t, false, h1Mode, "intentional death for testing")
+}
+func TestHandlerPanic_h2(t *testing.T) {
+	testHandlerPanic(t, false, h2Mode, "intentional death for testing")
 }
 
 func TestHandlerPanicWithHijack(t *testing.T) {
-	testHandlerPanic(t, true, "intentional death for testing")
+	// Only testing HTTP/1, and our http2 server doesn't support hijacking.
+	testHandlerPanic(t, true, h1Mode, "intentional death for testing")
 }
 
-func testHandlerPanic(t *testing.T, withHijack bool, panicValue interface{}) {
+func testHandlerPanic(t *testing.T, withHijack, h2 bool, panicValue interface{}) {
 	defer afterTest(t)
 	// Unlike the other tests that set the log output to ioutil.Discard
 	// to quiet the output, this test uses a pipe.  The pipe serves three
@@ -1773,7 +2047,7 @@ func testHandlerPanic(t *testing.T, withHijack bool, panicValue interface{}) {
 	defer log.SetOutput(os.Stderr)
 	defer pw.Close()
 
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
 		if withHijack {
 			rwc, _, err := w.(Hijacker).Hijack()
 			if err != nil {
@@ -1783,7 +2057,7 @@ func testHandlerPanic(t *testing.T, withHijack bool, panicValue interface{}) {
 		}
 		panic(panicValue)
 	}))
-	defer ts.Close()
+	defer cst.close()
 
 	// Do a blocking read on the log output pipe so its logging
 	// doesn't bleed into the next test.  But wait only 5 seconds
@@ -1799,7 +2073,7 @@ func testHandlerPanic(t *testing.T, withHijack bool, panicValue interface{}) {
 		done <- true
 	}()
 
-	_, err := Get(ts.URL)
+	_, err := cst.c.Get(cst.ts.URL)
 	if err == nil {
 		t.Logf("expected an error")
 	}
@@ -1816,17 +2090,19 @@ func testHandlerPanic(t *testing.T, withHijack bool, panicValue interface{}) {
 	}
 }
 
-func TestServerNoDate(t *testing.T)        { testServerNoHeader(t, "Date") }
-func TestServerNoContentType(t *testing.T) { testServerNoHeader(t, "Content-Type") }
+func TestServerNoDate_h1(t *testing.T)        { testServerNoHeader(t, h1Mode, "Date") }
+func TestServerNoDate_h2(t *testing.T)        { testServerNoHeader(t, h2Mode, "Date") }
+func TestServerNoContentType_h1(t *testing.T) { testServerNoHeader(t, h1Mode, "Content-Type") }
+func TestServerNoContentType_h2(t *testing.T) { testServerNoHeader(t, h2Mode, "Content-Type") }
 
-func testServerNoHeader(t *testing.T, header string) {
+func testServerNoHeader(t *testing.T, h2 bool, header string) {
 	defer afterTest(t)
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
 		w.Header()[header] = nil
 		io.WriteString(w, "<html>foo</html>") // non-empty
 	}))
-	defer ts.Close()
-	res, err := Get(ts.URL)
+	defer cst.close()
+	res, err := cst.c.Get(cst.ts.URL)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -1863,18 +2139,20 @@ func TestStripPrefix(t *testing.T) {
 	res.Body.Close()
 }
 
-func TestRequestLimit(t *testing.T) {
+func TestRequestLimit_h1(t *testing.T) { testRequestLimit(t, h1Mode) }
+func TestRequestLimit_h2(t *testing.T) { testRequestLimit(t, h2Mode) }
+func testRequestLimit(t *testing.T, h2 bool) {
 	defer afterTest(t)
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
 		t.Fatalf("didn't expect to get request in Handler")
 	}))
-	defer ts.Close()
-	req, _ := NewRequest("GET", ts.URL, nil)
+	defer cst.close()
+	req, _ := NewRequest("GET", cst.ts.URL, nil)
 	var bytesPerHeader = len("header12345: val12345\r\n")
 	for i := 0; i < ((DefaultMaxHeaderBytes+4096)/bytesPerHeader)+1; i++ {
 		req.Header.Set(fmt.Sprintf("header%05d", i), fmt.Sprintf("val%05d", i))
 	}
-	res, err := DefaultClient.Do(req)
+	res, err := cst.c.Do(req)
 	if err != nil {
 		// Some HTTP clients may fail on this undefined behavior (server replying and
 		// closing the connection while the request is still being written), but
@@ -1882,8 +2160,8 @@ func TestRequestLimit(t *testing.T) {
 		t.Fatalf("Do: %v", err)
 	}
 	defer res.Body.Close()
-	if res.StatusCode != 413 {
-		t.Fatalf("expected 413 response status; got: %d %s", res.StatusCode, res.Status)
+	if res.StatusCode != 431 {
+		t.Fatalf("expected 431 response status; got: %d %s", res.StatusCode, res.Status)
 	}
 }
 
@@ -1907,10 +2185,12 @@ func (cr countReader) Read(p []byte) (n int, err error) {
 	return
 }
 
-func TestRequestBodyLimit(t *testing.T) {
+func TestRequestBodyLimit_h1(t *testing.T) { testRequestBodyLimit(t, h1Mode) }
+func TestRequestBodyLimit_h2(t *testing.T) { testRequestBodyLimit(t, h2Mode) }
+func testRequestBodyLimit(t *testing.T, h2 bool) {
 	defer afterTest(t)
 	const limit = 1 << 20
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
 		r.Body = MaxBytesReader(w, r.Body, limit)
 		n, err := io.Copy(ioutil.Discard, r.Body)
 		if err == nil {
@@ -1920,10 +2200,10 @@ func TestRequestBodyLimit(t *testing.T) {
 			t.Errorf("io.Copy = %d, want %d", n, limit)
 		}
 	}))
-	defer ts.Close()
+	defer cst.close()
 
 	nWritten := new(int64)
-	req, _ := NewRequest("POST", ts.URL, io.LimitReader(countReader{neverEnding('a'), nWritten}, limit*200))
+	req, _ := NewRequest("POST", cst.ts.URL, io.LimitReader(countReader{neverEnding('a'), nWritten}, limit*200))
 
 	// Send the POST, but don't care it succeeds or not.  The
 	// remote side is going to reply and then close the TCP
@@ -1934,7 +2214,7 @@ func TestRequestBodyLimit(t *testing.T) {
 	//
 	// But that's okay, since what we're really testing is that
 	// the remote side hung up on us before we wrote too much.
-	_, _ = DefaultClient.Do(req)
+	_, _ = cst.c.Do(req)
 
 	if atomic.LoadInt64(nWritten) > limit*100 {
 		t.Errorf("handler restricted the request body to %d bytes, but client managed to write %d",
@@ -1982,7 +2262,7 @@ func TestClientWriteShutdown(t *testing.T) {
 // buffered before chunk headers are added, not after chunk headers.
 func TestServerBufferedChunking(t *testing.T) {
 	conn := new(testConn)
-	conn.readBuf.Write([]byte("GET / HTTP/1.1\r\n\r\n"))
+	conn.readBuf.Write([]byte("GET / HTTP/1.1\r\nHost: foo\r\n\r\n"))
 	conn.closec = make(chan bool, 1)
 	ls := &oneConnListener{conn}
 	go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
@@ -2045,20 +2325,23 @@ func TestServerGracefulClose(t *testing.T) {
 	<-writeErr
 }
 
-func TestCaseSensitiveMethod(t *testing.T) {
+func TestCaseSensitiveMethod_h1(t *testing.T) { testCaseSensitiveMethod(t, h1Mode) }
+func TestCaseSensitiveMethod_h2(t *testing.T) { testCaseSensitiveMethod(t, h2Mode) }
+func testCaseSensitiveMethod(t *testing.T, h2 bool) {
 	defer afterTest(t)
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
 		if r.Method != "get" {
 			t.Errorf(`Got method %q; want "get"`, r.Method)
 		}
 	}))
-	defer ts.Close()
-	req, _ := NewRequest("get", ts.URL, nil)
-	res, err := DefaultClient.Do(req)
+	defer cst.close()
+	req, _ := NewRequest("get", cst.ts.URL, nil)
+	res, err := cst.c.Do(req)
 	if err != nil {
 		t.Error(err)
 		return
 	}
+
 	res.Body.Close()
 }
 
@@ -2131,6 +2414,59 @@ For:
 	ts.Close()
 }
 
+// Tests that a pipelined request causes the first request's Handler's CloseNotify
+// channel to fire. Previously it deadlocked.
+//
+// Issue 13165
+func TestCloseNotifierPipelined(t *testing.T) {
+	defer afterTest(t)
+	gotReq := make(chan bool, 2)
+	sawClose := make(chan bool, 2)
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+		gotReq <- true
+		cc := rw.(CloseNotifier).CloseNotify()
+		<-cc
+		sawClose <- true
+	}))
+	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatalf("error dialing: %v", err)
+	}
+	diec := make(chan bool, 1)
+	go func() {
+		const req = "GET / HTTP/1.1\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n"
+		_, err = io.WriteString(conn, req+req) // two requests
+		if err != nil {
+			t.Fatal(err)
+		}
+		<-diec
+		conn.Close()
+	}()
+	reqs := 0
+	closes := 0
+For:
+	for {
+		select {
+		case <-gotReq:
+			reqs++
+			if reqs > 2 {
+				t.Fatal("too many requests")
+			} else if reqs > 1 {
+				diec <- true
+			}
+		case <-sawClose:
+			closes++
+			if closes > 1 {
+				break For
+			}
+		case <-time.After(5 * time.Second):
+			ts.CloseClientConnections()
+			t.Fatal("timeout")
+		}
+	}
+	ts.Close()
+}
+
 func TestCloseNotifierChanLeak(t *testing.T) {
 	defer afterTest(t)
 	req := reqBytes("GET / HTTP/1.0\nHost: golang.org")
@@ -2153,6 +2489,114 @@ func TestCloseNotifierChanLeak(t *testing.T) {
 	}
 }
 
+// Tests that we can use CloseNotifier in one request, and later call Hijack
+// on a second request on the same connection.
+//
+// It also tests that the connReader stitches together its background
+// 1-byte read for CloseNotifier when CloseNotifier doesn't fire with
+// the rest of the second HTTP later.
+//
+// Issue 9763.
+// HTTP/1-only test. (http2 doesn't have Hijack)
+func TestHijackAfterCloseNotifier(t *testing.T) {
+	defer afterTest(t)
+	script := make(chan string, 2)
+	script <- "closenotify"
+	script <- "hijack"
+	close(script)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		plan := <-script
+		switch plan {
+		default:
+			panic("bogus plan; too many requests")
+		case "closenotify":
+			w.(CloseNotifier).CloseNotify() // discard result
+			w.Header().Set("X-Addr", r.RemoteAddr)
+		case "hijack":
+			c, _, err := w.(Hijacker).Hijack()
+			if err != nil {
+				t.Errorf("Hijack in Handler: %v", err)
+				return
+			}
+			if _, ok := c.(*net.TCPConn); !ok {
+				// Verify it's not wrapped in some type.
+				// Not strictly a go1 compat issue, but in practice it probably is.
+				t.Errorf("type of hijacked conn is %T; want *net.TCPConn", c)
+			}
+			fmt.Fprintf(c, "HTTP/1.0 200 OK\r\nX-Addr: %v\r\nContent-Length: 0\r\n\r\n", r.RemoteAddr)
+			c.Close()
+			return
+		}
+	}))
+	defer ts.Close()
+	res1, err := Get(ts.URL)
+	if err != nil {
+		log.Fatal(err)
+	}
+	res2, err := Get(ts.URL)
+	if err != nil {
+		log.Fatal(err)
+	}
+	addr1 := res1.Header.Get("X-Addr")
+	addr2 := res2.Header.Get("X-Addr")
+	if addr1 == "" || addr1 != addr2 {
+		t.Errorf("addr1, addr2 = %q, %q; want same", addr1, addr2)
+	}
+}
+
+func TestHijackBeforeRequestBodyRead(t *testing.T) {
+	defer afterTest(t)
+	var requestBody = bytes.Repeat([]byte("a"), 1<<20)
+	bodyOkay := make(chan bool, 1)
+	gotCloseNotify := make(chan bool, 1)
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+		defer close(bodyOkay) // caller will read false if nothing else
+
+		reqBody := r.Body
+		r.Body = nil // to test that server.go doesn't use this value.
+
+		gone := w.(CloseNotifier).CloseNotify()
+		slurp, err := ioutil.ReadAll(reqBody)
+		if err != nil {
+			t.Errorf("Body read: %v", err)
+			return
+		}
+		if len(slurp) != len(requestBody) {
+			t.Errorf("Backend read %d request body bytes; want %d", len(slurp), len(requestBody))
+			return
+		}
+		if !bytes.Equal(slurp, requestBody) {
+			t.Error("Backend read wrong request body.") // 1MB; omitting details
+			return
+		}
+		bodyOkay <- true
+		select {
+		case <-gone:
+			gotCloseNotify <- true
+		case <-time.After(5 * time.Second):
+			gotCloseNotify <- false
+		}
+	}))
+	defer ts.Close()
+
+	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer conn.Close()
+
+	fmt.Fprintf(conn, "POST / HTTP/1.1\r\nHost: foo\r\nContent-Length: %d\r\n\r\n%s",
+		len(requestBody), requestBody)
+	if !<-bodyOkay {
+		// already failed.
+		return
+	}
+	conn.Close()
+	if !<-gotCloseNotify {
+		t.Error("timeout waiting for CloseNotify")
+	}
+}
+
 func TestOptions(t *testing.T) {
 	uric := make(chan string, 2) // only expect 1, but leave space for 2
 	mux := NewServeMux()
@@ -2230,7 +2674,7 @@ func TestHeaderToWire(t *testing.T) {
 					return errors.New("no content-length")
 				}
 				if !strings.Contains(got, "Content-Type: text/plain") {
-					return errors.New("no content-length")
+					return errors.New("no content-type")
 				}
 				return nil
 			},
@@ -2302,7 +2746,7 @@ func TestHeaderToWire(t *testing.T) {
 					return errors.New("header appeared from after WriteHeader")
 				}
 				if !strings.Contains(got, "Content-Type: some/type") {
-					return errors.New("wrong content-length")
+					return errors.New("wrong content-type")
 				}
 				return nil
 			},
@@ -2315,7 +2759,7 @@ func TestHeaderToWire(t *testing.T) {
 			},
 			check: func(got string) error {
 				if !strings.Contains(got, "Content-Type: text/html") {
-					return errors.New("wrong content-length; want html")
+					return errors.New("wrong content-type; want html")
 				}
 				return nil
 			},
@@ -2328,7 +2772,7 @@ func TestHeaderToWire(t *testing.T) {
 			},
 			check: func(got string) error {
 				if !strings.Contains(got, "Content-Type: some/type") {
-					return errors.New("wrong content-length; want html")
+					return errors.New("wrong content-type; want html")
 				}
 				return nil
 			},
@@ -2339,7 +2783,7 @@ func TestHeaderToWire(t *testing.T) {
 			},
 			check: func(got string) error {
 				if !strings.Contains(got, "Content-Type: text/plain") {
-					return errors.New("wrong content-length; want text/plain")
+					return errors.New("wrong content-type; want text/plain")
 				}
 				if !strings.Contains(got, "Content-Length: 0") {
 					return errors.New("want 0 content-length")
@@ -2369,7 +2813,7 @@ func TestHeaderToWire(t *testing.T) {
 				if !strings.Contains(got, "404") {
 					return errors.New("wrong status")
 				}
-				if strings.Contains(got, "Some-Header") {
+				if strings.Contains(got, "Too-Late") {
 					return errors.New("shouldn't have seen Too-Late")
 				}
 				return nil
@@ -2503,7 +2947,7 @@ func TestHTTP10ConnectionHeader(t *testing.T) {
 	defer afterTest(t)
 
 	mux := NewServeMux()
-	mux.Handle("/", HandlerFunc(func(resp ResponseWriter, req *Request) {}))
+	mux.Handle("/", HandlerFunc(func(ResponseWriter, *Request) {}))
 	ts := httptest.NewServer(mux)
 	defer ts.Close()
 
@@ -2552,11 +2996,13 @@ func TestHTTP10ConnectionHeader(t *testing.T) {
 }
 
 // See golang.org/issue/5660
-func TestServerReaderFromOrder(t *testing.T) {
+func TestServerReaderFromOrder_h1(t *testing.T) { testServerReaderFromOrder(t, h1Mode) }
+func TestServerReaderFromOrder_h2(t *testing.T) { testServerReaderFromOrder(t, h2Mode) }
+func testServerReaderFromOrder(t *testing.T, h2 bool) {
 	defer afterTest(t)
 	pr, pw := io.Pipe()
 	const size = 3 << 20
-	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+	cst := newClientServerTest(t, h2, HandlerFunc(func(rw ResponseWriter, req *Request) {
 		rw.Header().Set("Content-Type", "text/plain") // prevent sniffing path
 		done := make(chan bool)
 		go func() {
@@ -2576,13 +3022,13 @@ func TestServerReaderFromOrder(t *testing.T) {
 		pw.Close()
 		<-done
 	}))
-	defer ts.Close()
+	defer cst.close()
 
-	req, err := NewRequest("POST", ts.URL, io.LimitReader(neverEnding('a'), size))
+	req, err := NewRequest("POST", cst.ts.URL, io.LimitReader(neverEnding('a'), size))
 	if err != nil {
 		t.Fatal(err)
 	}
-	res, err := DefaultClient.Do(req)
+	res, err := cst.c.Do(req)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -2612,9 +3058,9 @@ func TestCodesPreventingContentTypeAndBody(t *testing.T) {
 			"GET / HTTP/1.0",
 			"GET /header HTTP/1.0",
 			"GET /more HTTP/1.0",
-			"GET / HTTP/1.1",
-			"GET /header HTTP/1.1",
-			"GET /more HTTP/1.1",
+			"GET / HTTP/1.1\nHost: foo",
+			"GET /header HTTP/1.1\nHost: foo",
+			"GET /more HTTP/1.1\nHost: foo",
 		} {
 			got := ht.rawResponse(req)
 			wantStatus := fmt.Sprintf("%d %s", code, StatusText(code))
@@ -2635,7 +3081,7 @@ func TestContentTypeOkayOn204(t *testing.T) {
 		w.Header().Set("Content-Type", "foo/bar")
 		w.WriteHeader(204)
 	}))
-	got := ht.rawResponse("GET / HTTP/1.1")
+	got := ht.rawResponse("GET / HTTP/1.1\nHost: foo")
 	if !strings.Contains(got, "Content-Type: foo/bar") {
 		t.Errorf("Response = %q; want Content-Type: foo/bar", got)
 	}
@@ -2650,45 +3096,101 @@ func TestContentTypeOkayOn204(t *testing.T) {
 // proxy).  So then two people own that Request.Body (both the server
 // and the http client), and both think they can close it on failure.
 // Therefore, all incoming server requests Bodies need to be thread-safe.
-func TestTransportAndServerSharedBodyRace(t *testing.T) {
+func TestTransportAndServerSharedBodyRace_h1(t *testing.T) {
+	testTransportAndServerSharedBodyRace(t, h1Mode)
+}
+func TestTransportAndServerSharedBodyRace_h2(t *testing.T) {
+	testTransportAndServerSharedBodyRace(t, h2Mode)
+}
+func testTransportAndServerSharedBodyRace(t *testing.T, h2 bool) {
 	defer afterTest(t)
 
 	const bodySize = 1 << 20
 
+	// errorf is like t.Errorf, but also writes to println.  When
+	// this test fails, it hangs. This helps debugging and I've
+	// added this enough times "temporarily".  It now gets added
+	// full time.
+	errorf := func(format string, args ...interface{}) {
+		v := fmt.Sprintf(format, args...)
+		println(v)
+		t.Error(v)
+	}
+
 	unblockBackend := make(chan bool)
-	backend := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
-		io.CopyN(rw, req.Body, bodySize)
+	backend := newClientServerTest(t, h2, HandlerFunc(func(rw ResponseWriter, req *Request) {
+		gone := rw.(CloseNotifier).CloseNotify()
+		didCopy := make(chan interface{})
+		go func() {
+			n, err := io.CopyN(rw, req.Body, bodySize)
+			didCopy <- []interface{}{n, err}
+		}()
+		isGone := false
+	Loop:
+		for {
+			select {
+			case <-didCopy:
+				break Loop
+			case <-gone:
+				isGone = true
+			case <-time.After(time.Second):
+				println("1 second passes in backend, proxygone=", isGone)
+			}
+		}
 		<-unblockBackend
 	}))
-	defer backend.Close()
+	var quitTimer *time.Timer
+	defer func() { quitTimer.Stop() }()
+	defer backend.close()
 
 	backendRespc := make(chan *Response, 1)
-	proxy := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
-		req2, _ := NewRequest("POST", backend.URL, req.Body)
+	var proxy *clientServerTest
+	proxy = newClientServerTest(t, h2, HandlerFunc(func(rw ResponseWriter, req *Request) {
+		req2, _ := NewRequest("POST", backend.ts.URL, req.Body)
 		req2.ContentLength = bodySize
+		cancel := make(chan struct{})
+		req2.Cancel = cancel
 
-		bresp, err := DefaultClient.Do(req2)
+		bresp, err := proxy.c.Do(req2)
 		if err != nil {
-			t.Errorf("Proxy outbound request: %v", err)
+			errorf("Proxy outbound request: %v", err)
 			return
 		}
 		_, err = io.CopyN(ioutil.Discard, bresp.Body, bodySize/2)
 		if err != nil {
-			t.Errorf("Proxy copy error: %v", err)
+			errorf("Proxy copy error: %v", err)
 			return
 		}
 		backendRespc <- bresp // to close later
 
-		// Try to cause a race: Both the DefaultTransport and the proxy handler's Server
+		// Try to cause a race: Both the Transport and the proxy handler's Server
 		// will try to read/close req.Body (aka req2.Body)
-		DefaultTransport.(*Transport).CancelRequest(req2)
+		if h2 {
+			close(cancel)
+		} else {
+			proxy.c.Transport.(*Transport).CancelRequest(req2)
+		}
 		rw.Write([]byte("OK"))
 	}))
-	defer proxy.Close()
+	defer proxy.close()
+	defer func() {
+		// Before we shut down our two httptest.Servers, start a timer.
+		// We choose 7 seconds because httptest.Server starts logging
+		// warnings to stderr at 5 seconds. If we don't disarm this bomb
+		// in 7 seconds (after the two httptest.Server.Close calls above),
+		// then we explode with stacks.
+		quitTimer = time.AfterFunc(7*time.Second, func() {
+			debug.SetTraceback("ALL")
+			stacks := make([]byte, 1<<20)
+			stacks = stacks[:runtime.Stack(stacks, true)]
+			fmt.Fprintf(os.Stderr, "%s", stacks)
+			log.Fatalf("Timeout.")
+		})
+	}()
 
 	defer close(unblockBackend)
-	req, _ := NewRequest("POST", proxy.URL, io.LimitReader(neverEnding('a'), bodySize))
-	res, err := DefaultClient.Do(req)
+	req, _ := NewRequest("POST", proxy.ts.URL, io.LimitReader(neverEnding('a'), bodySize))
+	res, err := proxy.c.Do(req)
 	if err != nil {
 		t.Fatalf("Original request: %v", err)
 	}
@@ -2699,7 +3201,7 @@ func TestTransportAndServerSharedBodyRace(t *testing.T) {
 	case res := <-backendRespc:
 		res.Body.Close()
 	default:
-		// We failed earlier. (e.g. on DefaultClient.Do(req2))
+		// We failed earlier. (e.g. on proxy.c.Do(req2))
 	}
 }
 
@@ -2863,6 +3365,7 @@ func TestServerConnState(t *testing.T) {
 		if _, err := io.WriteString(c, "BOGUS REQUEST\r\n\r\n"); err != nil {
 			t.Fatal(err)
 		}
+		c.Read(make([]byte, 1)) // block until server hangs up on us
 		c.Close()
 	}
 
@@ -2896,9 +3399,14 @@ func TestServerConnState(t *testing.T) {
 	}
 	logString := func(m map[int][]ConnState) string {
 		var b bytes.Buffer
-		for id, l := range m {
+		var keys []int
+		for id := range m {
+			keys = append(keys, id)
+		}
+		sort.Ints(keys)
+		for _, id := range keys {
 			fmt.Fprintf(&b, "Conn %d: ", id)
-			for _, s := range l {
+			for _, s := range m[id] {
 				fmt.Fprintf(&b, "%s ", s)
 			}
 			b.WriteString("\n")
@@ -2959,20 +3467,22 @@ func TestServerKeepAlivesEnabled(t *testing.T) {
 }
 
 // golang.org/issue/7856
-func TestServerEmptyBodyRace(t *testing.T) {
+func TestServerEmptyBodyRace_h1(t *testing.T) { testServerEmptyBodyRace(t, h1Mode) }
+func TestServerEmptyBodyRace_h2(t *testing.T) { testServerEmptyBodyRace(t, h2Mode) }
+func testServerEmptyBodyRace(t *testing.T, h2 bool) {
 	defer afterTest(t)
 	var n int32
-	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+	cst := newClientServerTest(t, h2, HandlerFunc(func(rw ResponseWriter, req *Request) {
 		atomic.AddInt32(&n, 1)
 	}))
-	defer ts.Close()
+	defer cst.close()
 	var wg sync.WaitGroup
 	const reqs = 20
 	for i := 0; i < reqs; i++ {
 		wg.Add(1)
 		go func() {
 			defer wg.Done()
-			res, err := Get(ts.URL)
+			res, err := cst.c.Get(cst.ts.URL)
 			if err != nil {
 				t.Error(err)
 				return
@@ -3025,10 +3535,7 @@ func (c *closeWriteTestConn) CloseWrite() error {
 func TestCloseWrite(t *testing.T) {
 	var srv Server
 	var testConn closeWriteTestConn
-	c, err := ExportServerNewConn(&srv, &testConn)
-	if err != nil {
-		t.Fatal(err)
-	}
+	c := ExportServerNewConn(&srv, &testConn)
 	ExportCloseWriteAndWait(c)
 	if !testConn.didCloseWrite {
 		t.Error("didn't see CloseWrite call")
@@ -3193,6 +3700,33 @@ func TestTolerateCRLFBeforeRequestLine(t *testing.T) {
 	}
 }
 
+func TestIssue13893_Expect100(t *testing.T) {
+	// test that the Server doesn't filter out Expect headers.
+	req := reqBytes(`PUT /readbody HTTP/1.1
+User-Agent: PycURL/7.22.0
+Host: 127.0.0.1:9000
+Accept: */*
+Expect: 100-continue
+Content-Length: 10
+
+HelloWorld
+
+`)
+	var buf bytes.Buffer
+	conn := &rwTestConn{
+		Reader: bytes.NewReader(req),
+		Writer: &buf,
+		closec: make(chan bool, 1),
+	}
+	ln := &oneConnListener{conn: conn}
+	go Serve(ln, HandlerFunc(func(w ResponseWriter, r *Request) {
+		if _, ok := r.Header["Expect"]; !ok {
+			t.Error("Expect header should not be filtered out")
+		}
+	}))
+	<-conn.closec
+}
+
 func TestIssue11549_Expect100(t *testing.T) {
 	req := reqBytes(`PUT /readbody HTTP/1.1
 User-Agent: PycURL/7.22.0
@@ -3260,6 +3794,122 @@ func TestHandlerFinishSkipBigContentLengthRead(t *testing.T) {
 	}
 }
 
+func TestHandlerSetsBodyNil_h1(t *testing.T) { testHandlerSetsBodyNil(t, h1Mode) }
+func TestHandlerSetsBodyNil_h2(t *testing.T) { testHandlerSetsBodyNil(t, h2Mode) }
+func testHandlerSetsBodyNil(t *testing.T, h2 bool) {
+	defer afterTest(t)
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
+		r.Body = nil
+		fmt.Fprintf(w, "%v", r.RemoteAddr)
+	}))
+	defer cst.close()
+	get := func() string {
+		res, err := cst.c.Get(cst.ts.URL)
+		if err != nil {
+			t.Fatal(err)
+		}
+		defer res.Body.Close()
+		slurp, err := ioutil.ReadAll(res.Body)
+		if err != nil {
+			t.Fatal(err)
+		}
+		return string(slurp)
+	}
+	a, b := get(), get()
+	if a != b {
+		t.Errorf("Failed to reuse connections between requests: %v vs %v", a, b)
+	}
+}
+
+// Test that we validate the Host header.
+// Issue 11206 (invalid bytes in Host) and 13624 (Host present in HTTP/1.1)
+func TestServerValidatesHostHeader(t *testing.T) {
+	tests := []struct {
+		proto string
+		host  string
+		want  int
+	}{
+		{"HTTP/1.1", "", 400},
+		{"HTTP/1.1", "Host: \r\n", 200},
+		{"HTTP/1.1", "Host: 1.2.3.4\r\n", 200},
+		{"HTTP/1.1", "Host: foo.com\r\n", 200},
+		{"HTTP/1.1", "Host: foo-bar_baz.com\r\n", 200},
+		{"HTTP/1.1", "Host: foo.com:80\r\n", 200},
+		{"HTTP/1.1", "Host: ::1\r\n", 200},
+		{"HTTP/1.1", "Host: [::1]\r\n", 200}, // questionable without port, but accept it
+		{"HTTP/1.1", "Host: [::1]:80\r\n", 200},
+		{"HTTP/1.1", "Host: [::1%25en0]:80\r\n", 200},
+		{"HTTP/1.1", "Host: 1.2.3.4\r\n", 200},
+		{"HTTP/1.1", "Host: \x06\r\n", 400},
+		{"HTTP/1.1", "Host: \xff\r\n", 400},
+		{"HTTP/1.1", "Host: {\r\n", 400},
+		{"HTTP/1.1", "Host: }\r\n", 400},
+		{"HTTP/1.1", "Host: first\r\nHost: second\r\n", 400},
+
+		// HTTP/1.0 can lack a host header, but if present
+		// must play by the rules too:
+		{"HTTP/1.0", "", 200},
+		{"HTTP/1.0", "Host: first\r\nHost: second\r\n", 400},
+		{"HTTP/1.0", "Host: \xff\r\n", 400},
+	}
+	for _, tt := range tests {
+		conn := &testConn{closec: make(chan bool, 1)}
+		io.WriteString(&conn.readBuf, "GET / "+tt.proto+"\r\n"+tt.host+"\r\n")
+
+		ln := &oneConnListener{conn}
+		go Serve(ln, HandlerFunc(func(ResponseWriter, *Request) {}))
+		<-conn.closec
+		res, err := ReadResponse(bufio.NewReader(&conn.writeBuf), nil)
+		if err != nil {
+			t.Errorf("For %s %q, ReadResponse: %v", tt.proto, tt.host, res)
+			continue
+		}
+		if res.StatusCode != tt.want {
+			t.Errorf("For %s %q, Status = %d; want %d", tt.proto, tt.host, res.StatusCode, tt.want)
+		}
+	}
+}
+
+// Test that we validate the valid bytes in HTTP/1 headers.
+// Issue 11207.
+func TestServerValidatesHeaders(t *testing.T) {
+	tests := []struct {
+		header string
+		want   int
+	}{
+		{"", 200},
+		{"Foo: bar\r\n", 200},
+		{"X-Foo: bar\r\n", 200},
+		{"Foo: a space\r\n", 200},
+
+		{"A space: foo\r\n", 400},    // space in header
+		{"foo\xffbar: foo\r\n", 400}, // binary in header
+		{"foo\x00bar: foo\r\n", 400}, // binary in header
+
+		{"foo: foo foo\r\n", 200},    // LWS space is okay
+		{"foo: foo\tfoo\r\n", 200},   // LWS tab is okay
+		{"foo: foo\x00foo\r\n", 400}, // CTL 0x00 in value is bad
+		{"foo: foo\x7ffoo\r\n", 400}, // CTL 0x7f in value is bad
+		{"foo: foo\xfffoo\r\n", 200}, // non-ASCII high octets in value are fine
+	}
+	for _, tt := range tests {
+		conn := &testConn{closec: make(chan bool, 1)}
+		io.WriteString(&conn.readBuf, "GET / HTTP/1.1\r\nHost: foo\r\n"+tt.header+"\r\n")
+
+		ln := &oneConnListener{conn}
+		go Serve(ln, HandlerFunc(func(ResponseWriter, *Request) {}))
+		<-conn.closec
+		res, err := ReadResponse(bufio.NewReader(&conn.writeBuf), nil)
+		if err != nil {
+			t.Errorf("For %q, ReadResponse: %v", tt.header, res)
+			continue
+		}
+		if res.StatusCode != tt.want {
+			t.Errorf("For %q, Status = %d; want %d", tt.header, res.StatusCode, tt.want)
+		}
+	}
+}
+
 func BenchmarkClientServer(b *testing.B) {
 	b.ReportAllocs()
 	b.StopTimer()
@@ -3685,3 +4335,35 @@ Host: golang.org
 		<-conn.closec
 	}
 }
+
+func BenchmarkCloseNotifier(b *testing.B) {
+	b.ReportAllocs()
+	b.StopTimer()
+	sawClose := make(chan bool)
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+		<-rw.(CloseNotifier).CloseNotify()
+		sawClose <- true
+	}))
+	defer ts.Close()
+	tot := time.NewTimer(5 * time.Second)
+	defer tot.Stop()
+	b.StartTimer()
+	for i := 0; i < b.N; i++ {
+		conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+		if err != nil {
+			b.Fatalf("error dialing: %v", err)
+		}
+		_, err = fmt.Fprintf(conn, "GET / HTTP/1.1\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n")
+		if err != nil {
+			b.Fatal(err)
+		}
+		conn.Close()
+		tot.Reset(5 * time.Second)
+		select {
+		case <-sawClose:
+		case <-tot.C:
+			b.Fatal("timeout")
+		}
+	}
+	b.StopTimer()
+}
diff --git a/src/net/http/server.go b/src/net/http/server.go
index a3e4355..5e3b608 100644
--- a/src/net/http/server.go
+++ b/src/net/http/server.go
@@ -8,6 +8,7 @@ package http
 
 import (
 	"bufio"
+	"bytes"
 	"crypto/tls"
 	"errors"
 	"fmt"
@@ -35,26 +36,33 @@ var (
 	ErrContentLength   = errors.New("Conn.Write wrote more than the declared Content-Length")
 )
 
-// Objects implementing the Handler interface can be
-// registered to serve a particular path or subtree
-// in the HTTP server.
+// A Handler responds to an HTTP request.
 //
 // ServeHTTP should write reply headers and data to the ResponseWriter
-// and then return.  Returning signals that the request is finished
-// and that the HTTP server can move on to the next request on
-// the connection.
+// and then return. Returning signals that the request is finished; it
+// is not valid to use the ResponseWriter or read from the
+// Request.Body after or concurrently with the completion of the
+// ServeHTTP call.
+//
+// Depending on the HTTP client software, HTTP protocol version, and
+// any intermediaries between the client and the Go server, it may not
+// be possible to read from the Request.Body after writing to the
+// ResponseWriter. Cautious handlers should read the Request.Body
+// first, and then reply.
 //
 // If ServeHTTP panics, the server (the caller of ServeHTTP) assumes
 // that the effect of the panic was isolated to the active request.
 // It recovers the panic, logs a stack trace to the server error log,
 // and hangs up the connection.
-//
 type Handler interface {
 	ServeHTTP(ResponseWriter, *Request)
 }
 
 // A ResponseWriter interface is used by an HTTP handler to
 // construct an HTTP response.
+//
+// A ResponseWriter may not be used after the Handler.ServeHTTP method
+// has returned.
 type ResponseWriter interface {
 	// Header returns the header map that will be sent by
 	// WriteHeader. Changing the header after a call to
@@ -114,28 +122,76 @@ type Hijacker interface {
 // This mechanism can be used to cancel long operations on the server
 // if the client has disconnected before the response is ready.
 type CloseNotifier interface {
-	// CloseNotify returns a channel that receives a single value
-	// when the client connection has gone away.
+	// CloseNotify returns a channel that receives at most a
+	// single value (true) when the client connection has gone
+	// away.
+	//
+	// CloseNotify may wait to notify until Request.Body has been
+	// fully read.
+	//
+	// After the Handler has returned, there is no guarantee
+	// that the channel receives a value.
+	//
+	// If the protocol is HTTP/1.1 and CloseNotify is called while
+	// processing an idempotent request (such a GET) while
+	// HTTP/1.1 pipelining is in use, the arrival of a subsequent
+	// pipelined request may cause a value to be sent on the
+	// returned channel. In practice HTTP/1.1 pipelining is not
+	// enabled in browsers and not seen often in the wild. If this
+	// is a problem, use HTTP/2 or only use CloseNotify on methods
+	// such as POST.
 	CloseNotify() <-chan bool
 }
 
 // A conn represents the server side of an HTTP connection.
 type conn struct {
-	remoteAddr string               // network address of remote side
-	server     *Server              // the Server on which the connection arrived
-	rwc        net.Conn             // i/o connection
-	w          io.Writer            // checkConnErrorWriter's copy of wrc, not zeroed on Hijack
-	werr       error                // any errors writing to w
-	sr         liveSwitchReader     // where the LimitReader reads from; usually the rwc
-	lr         *io.LimitedReader    // io.LimitReader(sr)
-	buf        *bufio.ReadWriter    // buffered(lr,rwc), reading from bufio->limitReader->sr->rwc
-	tlsState   *tls.ConnectionState // or nil when not using TLS
-	lastMethod string               // method of previous request, or ""
-
-	mu           sync.Mutex // guards the following
-	clientGone   bool       // if client has disconnected mid-request
-	closeNotifyc chan bool  // made lazily
-	hijackedv    bool       // connection has been hijacked by handler
+	// server is the server on which the connection arrived.
+	// Immutable; never nil.
+	server *Server
+
+	// rwc is the underlying network connection.
+	// This is never wrapped by other types and is the value given out
+	// to CloseNotifier callers. It is usually of type *net.TCPConn or
+	// *tls.Conn.
+	rwc net.Conn
+
+	// remoteAddr is rwc.RemoteAddr().String(). It is not populated synchronously
+	// inside the Listener's Accept goroutine, as some implementations block.
+	// It is populated immediately inside the (*conn).serve goroutine.
+	// This is the value of a Handler's (*Request).RemoteAddr.
+	remoteAddr string
+
+	// tlsState is the TLS connection state when using TLS.
+	// nil means not TLS.
+	tlsState *tls.ConnectionState
+
+	// werr is set to the first write error to rwc.
+	// It is set via checkConnErrorWriter{w}, where bufw writes.
+	werr error
+
+	// r is bufr's read source. It's a wrapper around rwc that provides
+	// io.LimitedReader-style limiting (while reading request headers)
+	// and functionality to support CloseNotifier. See *connReader docs.
+	r *connReader
+
+	// bufr reads from r.
+	// Users of bufr must hold mu.
+	bufr *bufio.Reader
+
+	// bufw writes to checkConnErrorWriter{c}, which populates werr on error.
+	bufw *bufio.Writer
+
+	// lastMethod is the method of the most recent request
+	// on this connection, if any.
+	lastMethod string
+
+	// mu guards hijackedv, use of bufr, (*response).closeNotifyCh.
+	mu sync.Mutex
+
+	// hijackedv is whether this connection has been hijacked
+	// by a Handler with the Hijacker interface.
+	// It is guarded by mu.
+	hijackedv bool
 }
 
 func (c *conn) hijacked() bool {
@@ -144,81 +200,18 @@ func (c *conn) hijacked() bool {
 	return c.hijackedv
 }
 
-func (c *conn) hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
-	c.mu.Lock()
-	defer c.mu.Unlock()
+// c.mu must be held.
+func (c *conn) hijackLocked() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
 	if c.hijackedv {
 		return nil, nil, ErrHijacked
 	}
-	if c.closeNotifyc != nil {
-		return nil, nil, errors.New("http: Hijack is incompatible with use of CloseNotifier")
-	}
 	c.hijackedv = true
 	rwc = c.rwc
-	buf = c.buf
-	c.rwc = nil
-	c.buf = nil
+	buf = bufio.NewReadWriter(c.bufr, bufio.NewWriter(rwc))
 	c.setState(rwc, StateHijacked)
 	return
 }
 
-func (c *conn) closeNotify() <-chan bool {
-	c.mu.Lock()
-	defer c.mu.Unlock()
-	if c.closeNotifyc == nil {
-		c.closeNotifyc = make(chan bool, 1)
-		if c.hijackedv {
-			// to obey the function signature, even though
-			// it'll never receive a value.
-			return c.closeNotifyc
-		}
-		pr, pw := io.Pipe()
-
-		readSource := c.sr.r
-		c.sr.Lock()
-		c.sr.r = pr
-		c.sr.Unlock()
-		go func() {
-			_, err := io.Copy(pw, readSource)
-			if err == nil {
-				err = io.EOF
-			}
-			pw.CloseWithError(err)
-			c.noteClientGone()
-		}()
-	}
-	return c.closeNotifyc
-}
-
-func (c *conn) noteClientGone() {
-	c.mu.Lock()
-	defer c.mu.Unlock()
-	if c.closeNotifyc != nil && !c.clientGone {
-		c.closeNotifyc <- true
-	}
-	c.clientGone = true
-}
-
-// A switchWriter can have its Writer changed at runtime.
-// It's not safe for concurrent Writes and switches.
-type switchWriter struct {
-	io.Writer
-}
-
-// A liveSwitchReader can have its Reader changed at runtime. It's
-// safe for concurrent reads and switches, if its mutex is held.
-type liveSwitchReader struct {
-	sync.Mutex
-	r io.Reader
-}
-
-func (sr *liveSwitchReader) Read(p []byte) (n int, err error) {
-	sr.Lock()
-	r := sr.r
-	sr.Unlock()
-	return r.Read(p)
-}
-
 // This should be >= 512 bytes for DetectContentType,
 // but otherwise it's somewhat arbitrary.
 const bufferBeforeChunkingSize = 2048
@@ -265,15 +258,15 @@ func (cw *chunkWriter) Write(p []byte) (n int, err error) {
 		return len(p), nil
 	}
 	if cw.chunking {
-		_, err = fmt.Fprintf(cw.res.conn.buf, "%x\r\n", len(p))
+		_, err = fmt.Fprintf(cw.res.conn.bufw, "%x\r\n", len(p))
 		if err != nil {
 			cw.res.conn.rwc.Close()
 			return
 		}
 	}
-	n, err = cw.res.conn.buf.Write(p)
+	n, err = cw.res.conn.bufw.Write(p)
 	if cw.chunking && err == nil {
-		_, err = cw.res.conn.buf.Write(crlf)
+		_, err = cw.res.conn.bufw.Write(crlf)
 	}
 	if err != nil {
 		cw.res.conn.rwc.Close()
@@ -285,7 +278,7 @@ func (cw *chunkWriter) flush() {
 	if !cw.wroteHeader {
 		cw.writeHeader(nil)
 	}
-	cw.res.conn.buf.Flush()
+	cw.res.conn.bufw.Flush()
 }
 
 func (cw *chunkWriter) close() {
@@ -293,7 +286,7 @@ func (cw *chunkWriter) close() {
 		cw.writeHeader(nil)
 	}
 	if cw.chunking {
-		bw := cw.res.conn.buf // conn's bufio writer
+		bw := cw.res.conn.bufw // conn's bufio writer
 		// zero chunk to mark EOF
 		bw.WriteString("0\r\n")
 		if len(cw.res.trailers) > 0 {
@@ -315,12 +308,12 @@ func (cw *chunkWriter) close() {
 type response struct {
 	conn          *conn
 	req           *Request // request for this response
-	wroteHeader   bool     // reply header has been (logically) written
-	wroteContinue bool     // 100 Continue response was written
+	reqBody       io.ReadCloser
+	wroteHeader   bool // reply header has been (logically) written
+	wroteContinue bool // 100 Continue response was written
 
 	w  *bufio.Writer // buffers output in chunks to chunkWriter
 	cw chunkWriter
-	sw *switchWriter // of the bufio.Writer, for return to putBufioWriter
 
 	// handlerHeader is the Header that Handlers get access to,
 	// which may be retained and mutated even after WriteHeader.
@@ -354,13 +347,22 @@ type response struct {
 	// written.
 	trailers []string
 
-	handlerDone bool // set true when the handler exits
+	handlerDone atomicBool // set true when the handler exits
 
 	// Buffers for Date and Content-Length
 	dateBuf [len(TimeFormat)]byte
 	clenBuf [10]byte
+
+	// closeNotifyCh is non-nil once CloseNotify is called.
+	// Guarded by conn.mu
+	closeNotifyCh <-chan bool
 }
 
+type atomicBool int32
+
+func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
+func (b *atomicBool) setTrue()    { atomic.StoreInt32((*int32)(b), 1) }
+
 // declareTrailer is called for each Trailer header when the
 // response header is written. It notes that a header will need to be
 // written in the trailers at the end of the response.
@@ -423,7 +425,9 @@ func (w *response) ReadFrom(src io.Reader) (n int64, err error) {
 		return 0, err
 	}
 	if !ok || !regFile {
-		return io.Copy(writerOnly{w}, src)
+		bufp := copyBufPool.Get().(*[]byte)
+		defer copyBufPool.Put(bufp)
+		return io.CopyBuffer(writerOnly{w}, src, *bufp)
 	}
 
 	// sendfile path:
@@ -456,29 +460,88 @@ func (w *response) ReadFrom(src io.Reader) (n int64, err error) {
 	return n, err
 }
 
-// noLimit is an effective infinite upper bound for io.LimitedReader
-const noLimit int64 = (1 << 63) - 1
-
 // debugServerConnections controls whether all server connections are wrapped
 // with a verbose logging wrapper.
 const debugServerConnections = false
 
 // Create new connection from rwc.
-func (srv *Server) newConn(rwc net.Conn) (c *conn, err error) {
-	c = new(conn)
-	c.remoteAddr = rwc.RemoteAddr().String()
-	c.server = srv
-	c.rwc = rwc
-	c.w = rwc
+func (srv *Server) newConn(rwc net.Conn) *conn {
+	c := &conn{
+		server: srv,
+		rwc:    rwc,
+	}
 	if debugServerConnections {
 		c.rwc = newLoggingConn("server", c.rwc)
 	}
-	c.sr.r = c.rwc
-	c.lr = io.LimitReader(&c.sr, noLimit).(*io.LimitedReader)
-	br := newBufioReader(c.lr)
-	bw := newBufioWriterSize(checkConnErrorWriter{c}, 4<<10)
-	c.buf = bufio.NewReadWriter(br, bw)
-	return c, nil
+	return c
+}
+
+type readResult struct {
+	n   int
+	err error
+	b   byte // byte read, if n == 1
+}
+
+// connReader is the io.Reader wrapper used by *conn. It combines a
+// selectively-activated io.LimitedReader (to bound request header
+// read sizes) with support for selectively keeping an io.Reader.Read
+// call blocked in a background goroutine to wait for activity and
+// trigger a CloseNotifier channel.
+type connReader struct {
+	r      io.Reader
+	remain int64 // bytes remaining
+
+	// ch is non-nil if a background read is in progress.
+	// It is guarded by conn.mu.
+	ch chan readResult
+}
+
+func (cr *connReader) setReadLimit(remain int64) { cr.remain = remain }
+func (cr *connReader) setInfiniteReadLimit()     { cr.remain = 1<<63 - 1 }
+func (cr *connReader) hitReadLimit() bool        { return cr.remain <= 0 }
+
+func (cr *connReader) Read(p []byte) (n int, err error) {
+	if cr.hitReadLimit() {
+		return 0, io.EOF
+	}
+	if len(p) == 0 {
+		return
+	}
+	if int64(len(p)) > cr.remain {
+		p = p[:cr.remain]
+	}
+
+	// Is a background read (started by CloseNotifier) already in
+	// flight? If so, wait for it and use its result.
+	ch := cr.ch
+	if ch != nil {
+		cr.ch = nil
+		res := <-ch
+		if res.n == 1 {
+			p[0] = res.b
+			cr.remain -= 1
+		}
+		return res.n, res.err
+	}
+	n, err = cr.r.Read(p)
+	cr.remain -= int64(n)
+	return
+}
+
+func (cr *connReader) startBackgroundRead(onReadComplete func()) {
+	if cr.ch != nil {
+		// Background read already started.
+		return
+	}
+	cr.ch = make(chan readResult, 1)
+	go cr.closeNotifyAwaitActivityRead(cr.ch, onReadComplete)
+}
+
+func (cr *connReader) closeNotifyAwaitActivityRead(ch chan<- readResult, onReadComplete func()) {
+	var buf [1]byte
+	n, err := cr.r.Read(buf[:1])
+	onReadComplete()
+	ch <- readResult{n, err, buf[0]}
 }
 
 var (
@@ -487,6 +550,13 @@ var (
 	bufioWriter4kPool sync.Pool
 )
 
+var copyBufPool = sync.Pool{
+	New: func() interface{} {
+		b := make([]byte, 32*1024)
+		return &b
+	},
+}
+
 func bufioWriterPool(size int) *sync.Pool {
 	switch size {
 	case 2 << 10:
@@ -544,7 +614,7 @@ func (srv *Server) maxHeaderBytes() int {
 	return DefaultMaxHeaderBytes
 }
 
-func (srv *Server) initialLimitedReaderSize() int64 {
+func (srv *Server) initialReadLimitSize() int64 {
 	return int64(srv.maxHeaderBytes()) + 4096 // bufio slop
 }
 
@@ -563,8 +633,8 @@ func (ecr *expectContinueReader) Read(p []byte) (n int, err error) {
 	}
 	if !ecr.resp.wroteContinue && !ecr.resp.conn.hijacked() {
 		ecr.resp.wroteContinue = true
-		ecr.resp.conn.buf.WriteString("HTTP/1.1 100 Continue\r\n\r\n")
-		ecr.resp.conn.buf.Flush()
+		ecr.resp.conn.bufw.WriteString("HTTP/1.1 100 Continue\r\n\r\n")
+		ecr.resp.conn.bufw.Flush()
 	}
 	n, err = ecr.readCloser.Read(p)
 	if err == io.EOF {
@@ -578,10 +648,12 @@ func (ecr *expectContinueReader) Close() error {
 	return ecr.readCloser.Close()
 }
 
-// TimeFormat is the time format to use with
-// time.Parse and time.Time.Format when parsing
-// or generating times in HTTP headers.
-// It is like time.RFC1123 but hard codes GMT as the time zone.
+// TimeFormat is the time format to use when generating times in HTTP
+// headers. It is like time.RFC1123 but hard-codes GMT as the time
+// zone. The time being formatted must be in UTC for Format to
+// generate the correct format.
+//
+// For parsing this time format, see ParseTime.
 const TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
 
 // appendTime is a non-allocating version of []byte(t.UTC().Format(TimeFormat))
@@ -623,21 +695,45 @@ func (c *conn) readRequest() (w *response, err error) {
 		}()
 	}
 
-	c.lr.N = c.server.initialLimitedReaderSize()
+	c.r.setReadLimit(c.server.initialReadLimitSize())
+	c.mu.Lock() // while using bufr
 	if c.lastMethod == "POST" {
 		// RFC 2616 section 4.1 tolerance for old buggy clients.
-		peek, _ := c.buf.Reader.Peek(4) // ReadRequest will get err below
-		c.buf.Reader.Discard(numLeadingCRorLF(peek))
+		peek, _ := c.bufr.Peek(4) // ReadRequest will get err below
+		c.bufr.Discard(numLeadingCRorLF(peek))
 	}
-	var req *Request
-	if req, err = ReadRequest(c.buf.Reader); err != nil {
-		if c.lr.N == 0 {
+	req, err := readRequest(c.bufr, keepHostHeader)
+	c.mu.Unlock()
+	if err != nil {
+		if c.r.hitReadLimit() {
 			return nil, errTooLarge
 		}
 		return nil, err
 	}
-	c.lr.N = noLimit
 	c.lastMethod = req.Method
+	c.r.setInfiniteReadLimit()
+
+	hosts, haveHost := req.Header["Host"]
+	if req.ProtoAtLeast(1, 1) && (!haveHost || len(hosts) == 0) {
+		return nil, badRequestError("missing required Host header")
+	}
+	if len(hosts) > 1 {
+		return nil, badRequestError("too many Host headers")
+	}
+	if len(hosts) == 1 && !validHostHeader(hosts[0]) {
+		return nil, badRequestError("malformed Host header")
+	}
+	for k, vv := range req.Header {
+		if !validHeaderName(k) {
+			return nil, badRequestError("invalid header name")
+		}
+		for _, v := range vv {
+			if !validHeaderValue(v) {
+				return nil, badRequestError("invalid header value")
+			}
+		}
+	}
+	delete(req.Header, "Host")
 
 	req.RemoteAddr = c.remoteAddr
 	req.TLS = c.tlsState
@@ -648,6 +744,7 @@ func (c *conn) readRequest() (w *response, err error) {
 	w = &response{
 		conn:          c,
 		req:           req,
+		reqBody:       req.Body,
 		handlerHeader: make(Header),
 		contentLength: -1,
 	}
@@ -755,7 +852,7 @@ func (h extraHeader) Write(w *bufio.Writer) {
 }
 
 // writeHeader finalizes the header sent to the client and writes it
-// to cw.res.conn.buf.
+// to cw.res.conn.bufw.
 //
 // p is not written by writeHeader, but is the first chunk of the body
 // that will be written.  It is sniffed for a Content-Type if none is
@@ -821,7 +918,7 @@ func (cw *chunkWriter) writeHeader(p []byte) {
 	// send a Content-Length header.
 	// Further, we don't send an automatic Content-Length if they
 	// set a Transfer-Encoding, because they're generally incompatible.
-	if w.handlerDone && !trailers && !hasTE && bodyAllowedForStatus(w.status) && header.get("Content-Length") == "" && (!isHEAD || len(p) > 0) {
+	if w.handlerDone.isSet() && !trailers && !hasTE && bodyAllowedForStatus(w.status) && header.get("Content-Length") == "" && (!isHEAD || len(p) > 0) {
 		w.contentLength = int64(len(p))
 		setHeader.contentLength = strconv.AppendInt(cw.res.clenBuf[:0], int64(len(p)), 10)
 	}
@@ -898,7 +995,7 @@ func (cw *chunkWriter) writeHeader(p []byte) {
 		}
 
 		if discard {
-			_, err := io.CopyN(ioutil.Discard, w.req.Body, maxPostHandlerReadBytes+1)
+			_, err := io.CopyN(ioutil.Discard, w.reqBody, maxPostHandlerReadBytes+1)
 			switch err {
 			case nil:
 				// There must be even more data left over.
@@ -907,7 +1004,7 @@ func (cw *chunkWriter) writeHeader(p []byte) {
 				// Body was already consumed and closed.
 			case io.EOF:
 				// The remaining body was just consumed, close it.
-				err = w.req.Body.Close()
+				err = w.reqBody.Close()
 				if err != nil {
 					w.closeAfterReply = true
 				}
@@ -996,10 +1093,10 @@ func (cw *chunkWriter) writeHeader(p []byte) {
 		}
 	}
 
-	w.conn.buf.WriteString(statusLine(w.req, code))
-	cw.header.WriteSubset(w.conn.buf, excludeHeader)
-	setHeader.Write(w.conn.buf.Writer)
-	w.conn.buf.Write(crlf)
+	w.conn.bufw.WriteString(statusLine(w.req, code))
+	cw.header.WriteSubset(w.conn.bufw, excludeHeader)
+	setHeader.Write(w.conn.bufw)
+	w.conn.bufw.Write(crlf)
 }
 
 // foreachHeaderElement splits v according to the "#rule" construction
@@ -1144,7 +1241,7 @@ func (w *response) write(lenData int, dataB []byte, dataS string) (n int, err er
 }
 
 func (w *response) finishRequest() {
-	w.handlerDone = true
+	w.handlerDone.setTrue()
 
 	if !w.wroteHeader {
 		w.WriteHeader(StatusOK)
@@ -1153,11 +1250,11 @@ func (w *response) finishRequest() {
 	w.w.Flush()
 	putBufioWriter(w.w)
 	w.cw.close()
-	w.conn.buf.Flush()
+	w.conn.bufw.Flush()
 
 	// Close the body (regardless of w.closeAfterReply) so we can
 	// re-use its bufio.Reader later safely.
-	w.req.Body.Close()
+	w.reqBody.Close()
 
 	if w.req.MultipartForm != nil {
 		w.req.MultipartForm.RemoveAll()
@@ -1206,28 +1303,26 @@ func (w *response) Flush() {
 }
 
 func (c *conn) finalFlush() {
-	if c.buf != nil {
-		c.buf.Flush()
-
+	if c.bufr != nil {
 		// Steal the bufio.Reader (~4KB worth of memory) and its associated
 		// reader for a future connection.
-		putBufioReader(c.buf.Reader)
+		putBufioReader(c.bufr)
+		c.bufr = nil
+	}
 
+	if c.bufw != nil {
+		c.bufw.Flush()
 		// Steal the bufio.Writer (~4KB worth of memory) and its associated
 		// writer for a future connection.
-		putBufioWriter(c.buf.Writer)
-
-		c.buf = nil
+		putBufioWriter(c.bufw)
+		c.bufw = nil
 	}
 }
 
 // Close the connection.
 func (c *conn) close() {
 	c.finalFlush()
-	if c.rwc != nil {
-		c.rwc.Close()
-		c.rwc = nil
-	}
+	c.rwc.Close()
 }
 
 // rstAvoidanceDelay is the amount of time we sleep after closing the
@@ -1277,9 +1372,16 @@ func (c *conn) setState(nc net.Conn, state ConnState) {
 	}
 }
 
+// badRequestError is a literal string (used by in the server in HTML,
+// unescaped) to tell the user why their request was bad. It should
+// be plain text without user info or other embeddded errors.
+type badRequestError string
+
+func (e badRequestError) Error() string { return "Bad Request: " + string(e) }
+
 // Serve a new connection.
 func (c *conn) serve() {
-	origConn := c.rwc // copy it before it's set nil on Close or Hijack
+	c.remoteAddr = c.rwc.RemoteAddr().String()
 	defer func() {
 		if err := recover(); err != nil {
 			const size = 64 << 10
@@ -1289,7 +1391,7 @@ func (c *conn) serve() {
 		}
 		if !c.hijacked() {
 			c.close()
-			c.setState(origConn, StateClosed)
+			c.setState(c.rwc, StateClosed)
 		}
 	}()
 
@@ -1315,9 +1417,13 @@ func (c *conn) serve() {
 		}
 	}
 
+	c.r = &connReader{r: c.rwc}
+	c.bufr = newBufioReader(c.r)
+	c.bufw = newBufioWriterSize(checkConnErrorWriter{c}, 4<<10)
+
 	for {
 		w, err := c.readRequest()
-		if c.lr.N != c.server.initialLimitedReaderSize() {
+		if c.r.remain != c.server.initialReadLimitSize() {
 			// If we read any bytes off the wire, we're active.
 			c.setState(c.rwc, StateActive)
 		}
@@ -1328,16 +1434,22 @@ func (c *conn) serve() {
 				// responding to them and hanging up
 				// while they're still writing their
 				// request.  Undefined behavior.
-				io.WriteString(c.rwc, "HTTP/1.1 413 Request Entity Too Large\r\n\r\n")
+				io.WriteString(c.rwc, "HTTP/1.1 431 Request Header Fields Too Large\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\n431 Request Header Fields Too Large")
 				c.closeWriteAndWait()
-				break
-			} else if err == io.EOF {
-				break // Don't reply
-			} else if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
-				break // Don't reply
+				return
 			}
-			io.WriteString(c.rwc, "HTTP/1.1 400 Bad Request\r\n\r\n")
-			break
+			if err == io.EOF {
+				return // don't reply
+			}
+			if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
+				return // don't reply
+			}
+			var publicErr string
+			if v, ok := err.(badRequestError); ok {
+				publicErr = ": " + string(v)
+			}
+			io.WriteString(c.rwc, "HTTP/1.1 400 Bad Request\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\n400 Bad Request"+publicErr)
+			return
 		}
 
 		// Expect 100 Continue support
@@ -1347,10 +1459,9 @@ func (c *conn) serve() {
 				// Wrap the Body reader with one that replies on the connection
 				req.Body = &expectContinueReader{readCloser: req.Body, resp: w}
 			}
-			req.Header.Del("Expect")
 		} else if req.Header.get("Expect") != "" {
 			w.sendExpectationFailed()
-			break
+			return
 		}
 
 		// HTTP cannot have multiple simultaneous active requests.[*]
@@ -1367,7 +1478,7 @@ func (c *conn) serve() {
 			if w.requestBodyLimitHit || w.closedRequestBodyEarly() {
 				c.closeWriteAndWait()
 			}
-			break
+			return
 		}
 		c.setState(c.rwc, StateIdle)
 	}
@@ -1394,12 +1505,24 @@ func (w *response) sendExpectationFailed() {
 // Hijack implements the Hijacker.Hijack method. Our response is both a ResponseWriter
 // and a Hijacker.
 func (w *response) Hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
+	if w.handlerDone.isSet() {
+		panic("net/http: Hijack called after ServeHTTP finished")
+	}
 	if w.wroteHeader {
 		w.cw.flush()
 	}
+
+	c := w.conn
+	c.mu.Lock()
+	defer c.mu.Unlock()
+
+	if w.closeNotifyCh != nil {
+		return nil, nil, errors.New("http: Hijack is incompatible with use of CloseNotifier in same ServeHTTP call")
+	}
+
 	// Release the bufioWriter that writes to the chunk writer, it is not
 	// used after a connection has been hijacked.
-	rwc, buf, err = w.conn.hijack()
+	rwc, buf, err = c.hijackLocked()
 	if err == nil {
 		putBufioWriter(w.w)
 		w.w = nil
@@ -1408,13 +1531,86 @@ func (w *response) Hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
 }
 
 func (w *response) CloseNotify() <-chan bool {
-	return w.conn.closeNotify()
+	if w.handlerDone.isSet() {
+		panic("net/http: CloseNotify called after ServeHTTP finished")
+	}
+	c := w.conn
+	c.mu.Lock()
+	defer c.mu.Unlock()
+
+	if w.closeNotifyCh != nil {
+		return w.closeNotifyCh
+	}
+	ch := make(chan bool, 1)
+	w.closeNotifyCh = ch
+
+	if w.conn.hijackedv {
+		// CloseNotify is undefined after a hijack, but we have
+		// no place to return an error, so just return a channel,
+		// even though it'll never receive a value.
+		return ch
+	}
+
+	var once sync.Once
+	notify := func() { once.Do(func() { ch <- true }) }
+
+	if requestBodyRemains(w.reqBody) {
+		// They're still consuming the request body, so we
+		// shouldn't notify yet.
+		registerOnHitEOF(w.reqBody, func() {
+			c.mu.Lock()
+			defer c.mu.Unlock()
+			startCloseNotifyBackgroundRead(c, notify)
+		})
+	} else {
+		startCloseNotifyBackgroundRead(c, notify)
+	}
+	return ch
+}
+
+// c.mu must be held.
+func startCloseNotifyBackgroundRead(c *conn, notify func()) {
+	if c.bufr.Buffered() > 0 {
+		// They've consumed the request body, so anything
+		// remaining is a pipelined request, which we
+		// document as firing on.
+		notify()
+	} else {
+		c.r.startBackgroundRead(notify)
+	}
+}
+
+func registerOnHitEOF(rc io.ReadCloser, fn func()) {
+	switch v := rc.(type) {
+	case *expectContinueReader:
+		registerOnHitEOF(v.readCloser, fn)
+	case *body:
+		v.registerOnHitEOF(fn)
+	default:
+		panic("unexpected type " + fmt.Sprintf("%T", rc))
+	}
+}
+
+// requestBodyRemains reports whether future calls to Read
+// on rc might yield more data.
+func requestBodyRemains(rc io.ReadCloser) bool {
+	if rc == eofReader {
+		return false
+	}
+	switch v := rc.(type) {
+	case *expectContinueReader:
+		return requestBodyRemains(v.readCloser)
+	case *body:
+		return v.bodyRemains()
+	default:
+		panic("unexpected type " + fmt.Sprintf("%T", rc))
+	}
 }
 
 // The HandlerFunc type is an adapter to allow the use of
 // ordinary functions as HTTP handlers.  If f is a function
 // with the appropriate signature, HandlerFunc(f) is a
-// Handler object that calls f.
+// Handler that calls f.
 type HandlerFunc func(ResponseWriter, *Request)
 
 // ServeHTTP calls f(w, r).
@@ -1461,6 +1657,9 @@ func StripPrefix(prefix string, h Handler) Handler {
 
 // Redirect replies to the request with a redirect to url,
 // which may be a path relative to the request path.
+//
+// The provided code should be in the 3xx range and is usually
+// StatusMovedPermanently, StatusFound or StatusSeeOther.
 func Redirect(w ResponseWriter, r *Request, urlStr string, code int) {
 	if u, err := url.Parse(urlStr); err == nil {
 		// If url was relative, make absolute by
@@ -1479,11 +1678,12 @@ func Redirect(w ResponseWriter, r *Request, urlStr string, code int) {
 		// Because of this problem, no one pays attention
 		// to the RFC; they all send back just a new path.
 		// So do we.
-		oldpath := r.URL.Path
-		if oldpath == "" { // should not happen, but avoid a crash if it does
-			oldpath = "/"
-		}
-		if u.Scheme == "" {
+		if u.Scheme == "" && u.Host == "" {
+			oldpath := r.URL.Path
+			if oldpath == "" { // should not happen, but avoid a crash if it does
+				oldpath = "/"
+			}
+
 			// no leading http://server
 			if urlStr == "" || urlStr[0] != '/' {
 				// make relative path absolute
@@ -1545,6 +1745,9 @@ func (rh *redirectHandler) ServeHTTP(w ResponseWriter, r *Request) {
 // RedirectHandler returns a request handler that redirects
 // each request it receives to the given url using the given
 // status code.
+//
+// The provided code should be in the 3xx range and is usually
+// StatusMovedPermanently, StatusFound or StatusSeeOther.
 func RedirectHandler(url string, code int) Handler {
 	return &redirectHandler{url, code}
 }
@@ -1567,6 +1770,14 @@ func RedirectHandler(url string, code int) Handler {
 // the pattern "/" matches all paths not matched by other registered
 // patterns, not just the URL with Path == "/".
 //
+// If a subtree has been registered and a request is received naming the
+// subtree root without its trailing slash, ServeMux redirects that
+// request to the subtree root (adding the trailing slash). This behavior can
+// be overridden with a separate registration for the path without
+// the trailing slash. For example, registering "/images/" causes ServeMux
+// to redirect a request for "/images" to "/images/", unless "/images" has
+// been registered separately.
+//
 // Patterns may optionally begin with a host name, restricting matches to
 // URLs on that host only.  Host-specific patterns take precedence over
 // general patterns, so that a handler might register for the two patterns
@@ -1574,8 +1785,8 @@ func RedirectHandler(url string, code int) Handler {
 // requests for "http://www.google.com/".
 //
 // ServeMux also takes care of sanitizing the URL request path,
-// redirecting any request containing . or .. elements to an
-// equivalent .- and ..-free URL.
+// redirecting any request containing . or .. elements or repeated slashes
+// to an equivalent, cleaner URL.
 type ServeMux struct {
 	mu    sync.RWMutex
 	m     map[string]muxEntry
@@ -1782,6 +1993,7 @@ type Server struct {
 	// handle HTTP requests and will initialize the Request's TLS
 	// and RemoteAddr if not already set.  The connection is
 	// automatically closed when the function returns.
+	// If TLSNextProto is nil, HTTP/2 support is enabled automatically.
 	TLSNextProto map[string]func(*Server, *tls.Conn, Handler)
 
 	// ConnState specifies an optional callback function that is
@@ -1795,7 +2007,9 @@ type Server struct {
 	// standard logger.
 	ErrorLog *log.Logger
 
-	disableKeepAlives int32 // accessed atomically.
+	disableKeepAlives int32     // accessed atomically.
+	nextProtoOnce     sync.Once // guards initialization of TLSNextProto in Serve
+	nextProtoErr      error
 }
 
 // A ConnState represents the state of a client connection to a server.
@@ -1815,6 +2029,11 @@ const (
 	// and doesn't fire again until the request has been
 	// handled. After the request is handled, the state
 	// transitions to StateClosed, StateHijacked, or StateIdle.
+	// For HTTP/2, StateActive fires on the transition from zero
+	// to one active request, and only transitions away once all
+	// active requests are complete. That means that ConnState
+	// can not be used to do per-request work; ConnState only notes
+	// the overall state of the connection.
 	StateActive
 
 	// StateIdle represents a connection that has finished
@@ -1863,8 +2082,10 @@ func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
 }
 
 // ListenAndServe listens on the TCP network address srv.Addr and then
-// calls Serve to handle requests on incoming connections.  If
-// srv.Addr is blank, ":http" is used.
+// calls Serve to handle requests on incoming connections.
+// Accepted connections are configured to enable TCP keep-alives.
+// If srv.Addr is blank, ":http" is used.
+// ListenAndServe always returns a non-nil error.
 func (srv *Server) ListenAndServe() error {
 	addr := srv.Addr
 	if addr == "" {
@@ -1877,12 +2098,21 @@ func (srv *Server) ListenAndServe() error {
 	return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
 }
 
+var testHookServerServe func(*Server, net.Listener) // used if non-nil
+
 // Serve accepts incoming connections on the Listener l, creating a
-// new service goroutine for each.  The service goroutines read requests and
+// new service goroutine for each. The service goroutines read requests and
 // then call srv.Handler to reply to them.
+// Serve always returns a non-nil error.
 func (srv *Server) Serve(l net.Listener) error {
 	defer l.Close()
+	if fn := testHookServerServe; fn != nil {
+		fn(srv, l)
+	}
 	var tempDelay time.Duration // how long to sleep on accept failure
+	if err := srv.setupHTTP2(); err != nil {
+		return err
+	}
 	for {
 		rw, e := l.Accept()
 		if e != nil {
@@ -1902,10 +2132,7 @@ func (srv *Server) Serve(l net.Listener) error {
 			return e
 		}
 		tempDelay = 0
-		c, err := srv.newConn(rw)
-		if err != nil {
-			continue
-		}
+		c := srv.newConn(rw)
 		c.setState(c.rwc, StateNew) // before Serve can return
 		go c.serve()
 	}
@@ -1937,8 +2164,10 @@ func (s *Server) logf(format string, args ...interface{}) {
 
 // ListenAndServe listens on the TCP network address addr
 // and then calls Serve with handler to handle requests
-// on incoming connections.  Handler is typically nil,
-// in which case the DefaultServeMux is used.
+// on incoming connections.
+// Accepted connections are configured to enable TCP keep-alives.
+// Handler is typically nil, in which case the DefaultServeMux is
+// used.
 //
 // A trivial example server is:
 //
@@ -1957,11 +2186,10 @@ func (s *Server) logf(format string, args ...interface{}) {
 //
 //	func main() {
 //		http.HandleFunc("/hello", HelloServer)
-//		err := http.ListenAndServe(":12345", nil)
-//		if err != nil {
-//			log.Fatal("ListenAndServe: ", err)
-//		}
+//		log.Fatal(http.ListenAndServe(":12345", nil))
 //	}
+//
+// ListenAndServe always returns a non-nil error.
 func ListenAndServe(addr string, handler Handler) error {
 	server := &Server{Addr: addr, Handler: handler}
 	return server.ListenAndServe()
@@ -1989,38 +2217,50 @@ func ListenAndServe(addr string, handler Handler) error {
 //		http.HandleFunc("/", handler)
 //		log.Printf("About to listen on 10443. Go to https://127.0.0.1:10443/")
 //		err := http.ListenAndServeTLS(":10443", "cert.pem", "key.pem", nil)
-//		if err != nil {
-//			log.Fatal(err)
-//		}
+//		log.Fatal(err)
 //	}
 //
 // One can use generate_cert.go in crypto/tls to generate cert.pem and key.pem.
-func ListenAndServeTLS(addr string, certFile string, keyFile string, handler Handler) error {
+//
+// ListenAndServeTLS always returns a non-nil error.
+func ListenAndServeTLS(addr, certFile, keyFile string, handler Handler) error {
 	server := &Server{Addr: addr, Handler: handler}
 	return server.ListenAndServeTLS(certFile, keyFile)
 }
 
 // ListenAndServeTLS listens on the TCP network address srv.Addr and
 // then calls Serve to handle requests on incoming TLS connections.
+// Accepted connections are configured to enable TCP keep-alives.
 //
 // Filenames containing a certificate and matching private key for the
-// server must be provided if the Server's TLSConfig.Certificates is
-// not populated. If the certificate is signed by a certificate
-// authority, the certFile should be the concatenation of the server's
-// certificate, any intermediates, and the CA's certificate.
+// server must be provided if neither the Server's TLSConfig.Certificates
+// nor TLSConfig.GetCertificate are populated. If the certificate is
+// signed by a certificate authority, the certFile should be the
+// concatenation of the server's certificate, any intermediates, and
+// the CA's certificate.
 //
 // If srv.Addr is blank, ":https" is used.
+//
+// ListenAndServeTLS always returns a non-nil error.
 func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
 	addr := srv.Addr
 	if addr == "" {
 		addr = ":https"
 	}
+
+	// Setup HTTP/2 before srv.Serve, to initialize srv.TLSConfig
+	// before we clone it and create the TLS Listener.
+	if err := srv.setupHTTP2(); err != nil {
+		return err
+	}
+
 	config := cloneTLSConfig(srv.TLSConfig)
-	if config.NextProtos == nil {
-		config.NextProtos = []string{"http/1.1"}
+	if !strSliceContains(config.NextProtos, "http/1.1") {
+		config.NextProtos = append(config.NextProtos, "http/1.1")
 	}
 
-	if len(config.Certificates) == 0 || certFile != "" || keyFile != "" {
+	configHasCert := len(config.Certificates) > 0 || config.GetCertificate != nil
+	if !configHasCert || certFile != "" || keyFile != "" {
 		var err error
 		config.Certificates = make([]tls.Certificate, 1)
 		config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
@@ -2038,6 +2278,25 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
 	return srv.Serve(tlsListener)
 }
 
+func (srv *Server) setupHTTP2() error {
+	srv.nextProtoOnce.Do(srv.onceSetNextProtoDefaults)
+	return srv.nextProtoErr
+}
+
+// onceSetNextProtoDefaults configures HTTP/2, if the user hasn't
+// configured otherwise. (by setting srv.TLSNextProto non-nil)
+// It must only be called via srv.nextProtoOnce (use srv.setupHTTP2).
+func (srv *Server) onceSetNextProtoDefaults() {
+	if strings.Contains(os.Getenv("GODEBUG"), "http2server=0") {
+		return
+	}
+	// Enable HTTP/2 by default if the user hasn't otherwise
+	// configured their TLSNextProto map.
+	if srv.TLSNextProto == nil {
+		srv.nextProtoErr = http2ConfigureServer(srv, nil)
+	}
+}
+
 // TimeoutHandler returns a Handler that runs h with the given time limit.
 //
 // The new Handler calls h.ServeHTTP to handle each request, but if a
@@ -2046,11 +2305,20 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
 // (If msg is empty, a suitable default message will be sent.)
 // After such a timeout, writes by h to its ResponseWriter will return
 // ErrHandlerTimeout.
+//
+// TimeoutHandler buffers all Handler writes to memory and does not
+// support the Hijacker or Flusher interfaces.
 func TimeoutHandler(h Handler, dt time.Duration, msg string) Handler {
-	f := func() <-chan time.Time {
-		return time.After(dt)
+	t := time.NewTimer(dt)
+	return &timeoutHandler{
+		handler: h,
+		body:    msg,
+
+		// Effectively storing a *time.Timer, but decomposed
+		// for testing:
+		timeout:     func() <-chan time.Time { return t.C },
+		cancelTimer: t.Stop,
 	}
-	return &timeoutHandler{h, f, msg}
 }
 
 // ErrHandlerTimeout is returned on ResponseWriter Write calls
@@ -2059,8 +2327,13 @@ var ErrHandlerTimeout = errors.New("http: Handler timeout")
 
 type timeoutHandler struct {
 	handler Handler
-	timeout func() <-chan time.Time // returns channel producing a timeout
 	body    string
+
+	// timeout returns the channel of a *time.Timer and
+	// cancelTimer cancels it.  They're stored separately for
+	// testing purposes.
+	timeout     func() <-chan time.Time // returns channel producing a timeout
+	cancelTimer func() bool             // optional
 }
 
 func (h *timeoutHandler) errorBody() string {
@@ -2071,46 +2344,61 @@ func (h *timeoutHandler) errorBody() string {
 }
 
 func (h *timeoutHandler) ServeHTTP(w ResponseWriter, r *Request) {
-	done := make(chan bool, 1)
-	tw := &timeoutWriter{w: w}
+	done := make(chan struct{})
+	tw := &timeoutWriter{
+		w: w,
+		h: make(Header),
+	}
 	go func() {
 		h.handler.ServeHTTP(tw, r)
-		done <- true
+		close(done)
 	}()
 	select {
 	case <-done:
-		return
-	case <-h.timeout():
 		tw.mu.Lock()
 		defer tw.mu.Unlock()
-		if !tw.wroteHeader {
-			tw.w.WriteHeader(StatusServiceUnavailable)
-			tw.w.Write([]byte(h.errorBody()))
+		dst := w.Header()
+		for k, vv := range tw.h {
+			dst[k] = vv
+		}
+		w.WriteHeader(tw.code)
+		w.Write(tw.wbuf.Bytes())
+		if h.cancelTimer != nil {
+			h.cancelTimer()
 		}
+	case <-h.timeout():
+		tw.mu.Lock()
+		defer tw.mu.Unlock()
+		w.WriteHeader(StatusServiceUnavailable)
+		io.WriteString(w, h.errorBody())
 		tw.timedOut = true
+		return
 	}
 }
 
 type timeoutWriter struct {
-	w ResponseWriter
+	w    ResponseWriter
+	h    Header
+	wbuf bytes.Buffer
 
 	mu          sync.Mutex
 	timedOut    bool
 	wroteHeader bool
+	code        int
 }
 
-func (tw *timeoutWriter) Header() Header {
-	return tw.w.Header()
-}
+func (tw *timeoutWriter) Header() Header { return tw.h }
 
 func (tw *timeoutWriter) Write(p []byte) (int, error) {
 	tw.mu.Lock()
 	defer tw.mu.Unlock()
-	tw.wroteHeader = true // implicitly at least
 	if tw.timedOut {
 		return 0, ErrHandlerTimeout
 	}
-	return tw.w.Write(p)
+	if !tw.wroteHeader {
+		tw.writeHeader(StatusOK)
+	}
+	return tw.wbuf.Write(p)
 }
 
 func (tw *timeoutWriter) WriteHeader(code int) {
@@ -2119,8 +2407,12 @@ func (tw *timeoutWriter) WriteHeader(code int) {
 	if tw.timedOut || tw.wroteHeader {
 		return
 	}
+	tw.writeHeader(code)
+}
+
+func (tw *timeoutWriter) writeHeader(code int) {
 	tw.wroteHeader = true
-	tw.w.WriteHeader(code)
+	tw.code = code
 }
 
 // tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
@@ -2247,7 +2539,7 @@ type checkConnErrorWriter struct {
 }
 
 func (w checkConnErrorWriter) Write(p []byte) (n int, err error) {
-	n, err = w.c.w.Write(p) // c.w == c.rwc, except after a hijack, when rwc is nil.
+	n, err = w.c.rwc.Write(p)
 	if err != nil && w.c.werr == nil {
 		w.c.werr = err
 	}
@@ -2265,3 +2557,12 @@ func numLeadingCRorLF(v []byte) (n int) {
 	return
 
 }
+
+func strSliceContains(ss []string, s string) bool {
+	for _, v := range ss {
+		if v == s {
+			return true
+		}
+	}
+	return false
+}
diff --git a/src/net/http/sniff.go b/src/net/http/sniff.go
index 3be8c86..18810ba 100644
--- a/src/net/http/sniff.go
+++ b/src/net/http/sniff.go
@@ -102,10 +102,9 @@ var sniffSignatures = []sniffSig{
 	&exactSig{[]byte("\x50\x4B\x03\x04"), "application/zip"},
 	&exactSig{[]byte("\x1F\x8B\x08"), "application/x-gzip"},
 
-	// TODO(dsymonds): Re-enable this when the spec is sorted w.r.t. MP4.
-	//mp4Sig(0),
+	mp4Sig{},
 
-	textSig(0), // should be last
+	textSig{}, // should be last
 }
 
 type exactSig struct {
@@ -166,12 +165,14 @@ func (h htmlSig) match(data []byte, firstNonWS int) string {
 }
 
 var mp4ftype = []byte("ftyp")
+var mp4 = []byte("mp4")
 
-type mp4Sig int
+type mp4Sig struct{}
 
 func (mp4Sig) match(data []byte, firstNonWS int) string {
-	// c.f. section 6.1.
-	if len(data) < 8 {
+	// https://mimesniff.spec.whatwg.org/#signature-for-mp4
+	// c.f. section 6.2.1
+	if len(data) < 12 {
 		return ""
 	}
 	boxSize := int(binary.BigEndian.Uint32(data[:4]))
@@ -186,30 +187,20 @@ func (mp4Sig) match(data []byte, firstNonWS int) string {
 			// minor version number
 			continue
 		}
-		seg := string(data[st : st+3])
-		switch seg {
-		case "mp4", "iso", "M4V", "M4P", "M4B":
+		if bytes.Equal(data[st:st+3], mp4) {
 			return "video/mp4"
-			/* The remainder are not in the spec.
-			case "M4A":
-				return "audio/mp4"
-			case "3gp":
-				return "video/3gpp"
-			case "jp2":
-				return "image/jp2" // JPEG 2000
-			*/
 		}
 	}
 	return ""
 }
 
-type textSig int
+type textSig struct{}
 
 func (textSig) match(data []byte, firstNonWS int) string {
 	// c.f. section 5, step 4.
 	for _, b := range data[firstNonWS:] {
 		switch {
-		case 0x00 <= b && b <= 0x08,
+		case b <= 0x08,
 			b == 0x0B,
 			0x0E <= b && b <= 0x1A,
 			0x1C <= b && b <= 0x1F:
diff --git a/src/net/http/sniff_test.go b/src/net/http/sniff_test.go
index 24ca27a..e008551 100644
--- a/src/net/http/sniff_test.go
+++ b/src/net/http/sniff_test.go
@@ -11,7 +11,6 @@ import (
 	"io/ioutil"
 	"log"
 	. "net/http"
-	"net/http/httptest"
 	"reflect"
 	"strconv"
 	"strings"
@@ -40,9 +39,7 @@ var sniffTests = []struct {
 	{"GIF 87a", []byte(`GIF87a`), "image/gif"},
 	{"GIF 89a", []byte(`GIF89a...`), "image/gif"},
 
-	// TODO(dsymonds): Re-enable this when the spec is sorted w.r.t. MP4.
-	//{"MP4 video", []byte("\x00\x00\x00\x18ftypmp42\x00\x00\x00\x00mp42isom<\x06t\xbfmdat"), "video/mp4"},
-	//{"MP4 audio", []byte("\x00\x00\x00\x20ftypM4A \x00\x00\x00\x00M4A mp42isom\x00\x00\x00\x00"), "audio/mp4"},
+	{"MP4 video", []byte("\x00\x00\x00\x18ftypmp42\x00\x00\x00\x00mp42isom<\x06t\xbfmdat"), "video/mp4"},
 }
 
 func TestDetectContentType(t *testing.T) {
@@ -54,9 +51,12 @@ func TestDetectContentType(t *testing.T) {
 	}
 }
 
-func TestServerContentType(t *testing.T) {
+func TestServerContentType_h1(t *testing.T) { testServerContentType(t, h1Mode) }
+func TestServerContentType_h2(t *testing.T) { testServerContentType(t, h2Mode) }
+
+func testServerContentType(t *testing.T, h2 bool) {
 	defer afterTest(t)
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
 		i, _ := strconv.Atoi(r.FormValue("i"))
 		tt := sniffTests[i]
 		n, err := w.Write(tt.data)
@@ -64,10 +64,10 @@ func TestServerContentType(t *testing.T) {
 			log.Fatalf("%v: Write(%q) = %v, %v want %d, nil", tt.desc, tt.data, n, err, len(tt.data))
 		}
 	}))
-	defer ts.Close()
+	defer cst.close()
 
 	for i, tt := range sniffTests {
-		resp, err := Get(ts.URL + "/?i=" + strconv.Itoa(i))
+		resp, err := cst.c.Get(cst.ts.URL + "/?i=" + strconv.Itoa(i))
 		if err != nil {
 			t.Errorf("%v: %v", tt.desc, err)
 			continue
@@ -87,15 +87,17 @@ func TestServerContentType(t *testing.T) {
 
 // Issue 5953: shouldn't sniff if the handler set a Content-Type header,
 // even if it's the empty string.
-func TestServerIssue5953(t *testing.T) {
+func TestServerIssue5953_h1(t *testing.T) { testServerIssue5953(t, h1Mode) }
+func TestServerIssue5953_h2(t *testing.T) { testServerIssue5953(t, h2Mode) }
+func testServerIssue5953(t *testing.T, h2 bool) {
 	defer afterTest(t)
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
 		w.Header()["Content-Type"] = []string{""}
 		fmt.Fprintf(w, "<html><head></head><body>hi</body></html>")
 	}))
-	defer ts.Close()
+	defer cst.close()
 
-	resp, err := Get(ts.URL)
+	resp, err := cst.c.Get(cst.ts.URL)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -108,7 +110,9 @@ func TestServerIssue5953(t *testing.T) {
 	resp.Body.Close()
 }
 
-func TestContentTypeWithCopy(t *testing.T) {
+func TestContentTypeWithCopy_h1(t *testing.T) { testContentTypeWithCopy(t, h1Mode) }
+func TestContentTypeWithCopy_h2(t *testing.T) { testContentTypeWithCopy(t, h2Mode) }
+func testContentTypeWithCopy(t *testing.T, h2 bool) {
 	defer afterTest(t)
 
 	const (
@@ -116,7 +120,7 @@ func TestContentTypeWithCopy(t *testing.T) {
 		expected = "text/html; charset=utf-8"
 	)
 
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
 		// Use io.Copy from a bytes.Buffer to trigger ReadFrom.
 		buf := bytes.NewBuffer([]byte(input))
 		n, err := io.Copy(w, buf)
@@ -124,9 +128,9 @@ func TestContentTypeWithCopy(t *testing.T) {
 			t.Errorf("io.Copy(w, %q) = %v, %v want %d, nil", input, n, err, len(input))
 		}
 	}))
-	defer ts.Close()
+	defer cst.close()
 
-	resp, err := Get(ts.URL)
+	resp, err := cst.c.Get(cst.ts.URL)
 	if err != nil {
 		t.Fatalf("Get: %v", err)
 	}
@@ -142,9 +146,11 @@ func TestContentTypeWithCopy(t *testing.T) {
 	resp.Body.Close()
 }
 
-func TestSniffWriteSize(t *testing.T) {
+func TestSniffWriteSize_h1(t *testing.T) { testSniffWriteSize(t, h1Mode) }
+func TestSniffWriteSize_h2(t *testing.T) { testSniffWriteSize(t, h2Mode) }
+func testSniffWriteSize(t *testing.T, h2 bool) {
 	defer afterTest(t)
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
 		size, _ := strconv.Atoi(r.FormValue("size"))
 		written, err := io.WriteString(w, strings.Repeat("a", size))
 		if err != nil {
@@ -155,9 +161,9 @@ func TestSniffWriteSize(t *testing.T) {
 			t.Errorf("write of %d bytes wrote %d bytes", size, written)
 		}
 	}))
-	defer ts.Close()
+	defer cst.close()
 	for _, size := range []int{0, 1, 200, 600, 999, 1000, 1023, 1024, 512 << 10, 1 << 20} {
-		res, err := Get(fmt.Sprintf("%s/?size=%d", ts.URL, size))
+		res, err := cst.c.Get(fmt.Sprintf("%s/?size=%d", cst.ts.URL, size))
 		if err != nil {
 			t.Fatalf("size %d: %v", size, err)
 		}
diff --git a/src/net/http/status.go b/src/net/http/status.go
index d253bd5..f3dacab 100644
--- a/src/net/http/status.go
+++ b/src/net/http/status.go
@@ -44,20 +44,18 @@ const (
 	StatusRequestedRangeNotSatisfiable = 416
 	StatusExpectationFailed            = 417
 	StatusTeapot                       = 418
+	StatusPreconditionRequired         = 428
+	StatusTooManyRequests              = 429
+	StatusRequestHeaderFieldsTooLarge  = 431
+	StatusUnavailableForLegalReasons   = 451
 
-	StatusInternalServerError     = 500
-	StatusNotImplemented          = 501
-	StatusBadGateway              = 502
-	StatusServiceUnavailable      = 503
-	StatusGatewayTimeout          = 504
-	StatusHTTPVersionNotSupported = 505
-
-	// New HTTP status codes from RFC 6585. Not exported yet in Go 1.1.
-	// See discussion at https://codereview.appspot.com/7678043/
-	statusPreconditionRequired          = 428
-	statusTooManyRequests               = 429
-	statusRequestHeaderFieldsTooLarge   = 431
-	statusNetworkAuthenticationRequired = 511
+	StatusInternalServerError           = 500
+	StatusNotImplemented                = 501
+	StatusBadGateway                    = 502
+	StatusServiceUnavailable            = 503
+	StatusGatewayTimeout                = 504
+	StatusHTTPVersionNotSupported       = 505
+	StatusNetworkAuthenticationRequired = 511
 )
 
 var statusText = map[int]string{
@@ -99,18 +97,18 @@ var statusText = map[int]string{
 	StatusRequestedRangeNotSatisfiable: "Requested Range Not Satisfiable",
 	StatusExpectationFailed:            "Expectation Failed",
 	StatusTeapot:                       "I'm a teapot",
+	StatusPreconditionRequired:         "Precondition Required",
+	StatusTooManyRequests:              "Too Many Requests",
+	StatusRequestHeaderFieldsTooLarge:  "Request Header Fields Too Large",
+	StatusUnavailableForLegalReasons:   "Unavailable For Legal Reasons",
 
-	StatusInternalServerError:     "Internal Server Error",
-	StatusNotImplemented:          "Not Implemented",
-	StatusBadGateway:              "Bad Gateway",
-	StatusServiceUnavailable:      "Service Unavailable",
-	StatusGatewayTimeout:          "Gateway Timeout",
-	StatusHTTPVersionNotSupported: "HTTP Version Not Supported",
-
-	statusPreconditionRequired:          "Precondition Required",
-	statusTooManyRequests:               "Too Many Requests",
-	statusRequestHeaderFieldsTooLarge:   "Request Header Fields Too Large",
-	statusNetworkAuthenticationRequired: "Network Authentication Required",
+	StatusInternalServerError:           "Internal Server Error",
+	StatusNotImplemented:                "Not Implemented",
+	StatusBadGateway:                    "Bad Gateway",
+	StatusServiceUnavailable:            "Service Unavailable",
+	StatusGatewayTimeout:                "Gateway Timeout",
+	StatusHTTPVersionNotSupported:       "HTTP Version Not Supported",
+	StatusNetworkAuthenticationRequired: "Network Authentication Required",
 }
 
 // StatusText returns a text for the HTTP status code. It returns the empty
diff --git a/src/net/http/transfer.go b/src/net/http/transfer.go
index a8736b2..6e59af8 100644
--- a/src/net/http/transfer.go
+++ b/src/net/http/transfer.go
@@ -56,7 +56,7 @@ func newTransferWriter(r interface{}) (t *transferWriter, err error) {
 		if rr.ContentLength != 0 && rr.Body == nil {
 			return nil, fmt.Errorf("http: Request.ContentLength=%d with nil Body", rr.ContentLength)
 		}
-		t.Method = rr.Method
+		t.Method = valueOrDefault(rr.Method, "GET")
 		t.Body = rr.Body
 		t.BodyCloser = rr.Body
 		t.ContentLength = rr.ContentLength
@@ -271,6 +271,10 @@ type transferReader struct {
 	Trailer          Header
 }
 
+func (t *transferReader) protoAtLeast(m, n int) bool {
+	return t.ProtoMajor > m || (t.ProtoMajor == m && t.ProtoMinor >= n)
+}
+
 // bodyAllowedForStatus reports whether a given response status code
 // permits a body.  See RFC2616, section 4.4.
 func bodyAllowedForStatus(status int) bool {
@@ -337,7 +341,7 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
 	}
 
 	// Transfer encoding, content length
-	t.TransferEncoding, err = fixTransferEncoding(isResponse, t.RequestMethod, t.Header)
+	err = t.fixTransferEncoding()
 	if err != nil {
 		return err
 	}
@@ -424,13 +428,18 @@ func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" }
 // Checks whether the encoding is explicitly "identity".
 func isIdentity(te []string) bool { return len(te) == 1 && te[0] == "identity" }
 
-// Sanitize transfer encoding
-func fixTransferEncoding(isResponse bool, requestMethod string, header Header) ([]string, error) {
-	raw, present := header["Transfer-Encoding"]
+// fixTransferEncoding sanitizes t.TransferEncoding, if needed.
+func (t *transferReader) fixTransferEncoding() error {
+	raw, present := t.Header["Transfer-Encoding"]
 	if !present {
-		return nil, nil
+		return nil
+	}
+	delete(t.Header, "Transfer-Encoding")
+
+	// Issue 12785; ignore Transfer-Encoding on HTTP/1.0 requests.
+	if !t.protoAtLeast(1, 1) {
+		return nil
 	}
-	delete(header, "Transfer-Encoding")
 
 	encodings := strings.Split(raw[0], ",")
 	te := make([]string, 0, len(encodings))
@@ -445,13 +454,13 @@ func fixTransferEncoding(isResponse bool, requestMethod string, header Header) (
 			break
 		}
 		if encoding != "chunked" {
-			return nil, &badStringError{"unsupported transfer encoding", encoding}
+			return &badStringError{"unsupported transfer encoding", encoding}
 		}
 		te = te[0 : len(te)+1]
 		te[len(te)-1] = encoding
 	}
 	if len(te) > 1 {
-		return nil, &badStringError{"too many transfer encodings", strings.Join(te, ",")}
+		return &badStringError{"too many transfer encodings", strings.Join(te, ",")}
 	}
 	if len(te) > 0 {
 		// RFC 7230 3.3.2 says "A sender MUST NOT send a
@@ -470,11 +479,12 @@ func fixTransferEncoding(isResponse bool, requestMethod string, header Header) (
 		// such a message downstream."
 		//
 		// Reportedly, these appear in the wild.
-		delete(header, "Content-Length")
-		return te, nil
+		delete(t.Header, "Content-Length")
+		t.TransferEncoding = te
+		return nil
 	}
 
-	return nil, nil
+	return nil
 }
 
 // Determine the expected body length, using RFC 2616 Section 4.4. This
@@ -567,21 +577,29 @@ func shouldClose(major, minor int, header Header, removeCloseHeader bool) bool {
 
 // Parse the trailer header
 func fixTrailer(header Header, te []string) (Header, error) {
-	raw := header.get("Trailer")
-	if raw == "" {
+	vv, ok := header["Trailer"]
+	if !ok {
 		return nil, nil
 	}
-
 	header.Del("Trailer")
+
 	trailer := make(Header)
-	keys := strings.Split(raw, ",")
-	for _, key := range keys {
-		key = CanonicalHeaderKey(strings.TrimSpace(key))
-		switch key {
-		case "Transfer-Encoding", "Trailer", "Content-Length":
-			return nil, &badStringError{"bad trailer key", key}
-		}
-		trailer[key] = nil
+	var err error
+	for _, v := range vv {
+		foreachHeaderElement(v, func(key string) {
+			key = CanonicalHeaderKey(key)
+			switch key {
+			case "Transfer-Encoding", "Trailer", "Content-Length":
+				if err == nil {
+					err = &badStringError{"bad trailer key", key}
+					return
+				}
+			}
+			trailer[key] = nil
+		})
+	}
+	if err != nil {
+		return nil, err
 	}
 	if len(trailer) == 0 {
 		return nil, nil
@@ -603,10 +621,11 @@ type body struct {
 	closing      bool          // is the connection to be closed after reading body?
 	doEarlyClose bool          // whether Close should stop early
 
-	mu         sync.Mutex // guards closed, and calls to Read and Close
+	mu         sync.Mutex // guards following, and calls to Read and Close
 	sawEOF     bool
 	closed     bool
-	earlyClose bool // Close called and we didn't read to the end of src
+	earlyClose bool   // Close called and we didn't read to the end of src
+	onHitEOF   func() // if non-nil, func to call when EOF is Read
 }
 
 // ErrBodyReadAfterClose is returned when reading a Request or Response
@@ -666,6 +685,10 @@ func (b *body) readLocked(p []byte) (n int, err error) {
 		}
 	}
 
+	if b.sawEOF && b.onHitEOF != nil {
+		b.onHitEOF()
+	}
+
 	return n, err
 }
 
@@ -800,6 +823,20 @@ func (b *body) didEarlyClose() bool {
 	return b.earlyClose
 }
 
+// bodyRemains reports whether future Read calls might
+// yield data.
+func (b *body) bodyRemains() bool {
+	b.mu.Lock()
+	defer b.mu.Unlock()
+	return !b.sawEOF
+}
+
+func (b *body) registerOnHitEOF(fn func()) {
+	b.mu.Lock()
+	defer b.mu.Unlock()
+	b.onHitEOF = fn
+}
+
 // bodyLocked is a io.Reader reading from a *body when its mutex is
 // already held.
 type bodyLocked struct {
diff --git a/src/net/http/transport.go b/src/net/http/transport.go
index 70d1864..baf71d5 100644
--- a/src/net/http/transport.go
+++ b/src/net/http/transport.go
@@ -36,7 +36,8 @@ var DefaultTransport RoundTripper = &Transport{
 		Timeout:   30 * time.Second,
 		KeepAlive: 30 * time.Second,
 	}).Dial,
-	TLSHandshakeTimeout: 10 * time.Second,
+	TLSHandshakeTimeout:   10 * time.Second,
+	ExpectContinueTimeout: 1 * time.Second,
 }
 
 // DefaultMaxIdleConnsPerHost is the default value of Transport's
@@ -45,7 +46,21 @@ const DefaultMaxIdleConnsPerHost = 2
 
 // Transport is an implementation of RoundTripper that supports HTTP,
 // HTTPS, and HTTP proxies (for either HTTP or HTTPS with CONNECT).
-// Transport can also cache connections for future re-use.
+//
+// By default, Transport caches connections for future re-use.
+// This may leave many open connections when accessing many hosts.
+// This behavior can be managed using Transport's CloseIdleConnections method
+// and the MaxIdleConnsPerHost and DisableKeepAlives fields.
+//
+// Transports should be reused instead of created as needed.
+// Transports are safe for concurrent use by multiple goroutines.
+//
+// A Transport is a low-level primitive for making HTTP and HTTPS requests.
+// For high-level functionality, such as cookies and redirects, see Client.
+//
+// Transport uses HTTP/1.1 for HTTP URLs and either HTTP/1.1 or HTTP/2
+// for HTTPS URLs, depending on whether the server supports HTTP/2.
+// See the package docs for more about HTTP/2.
 type Transport struct {
 	idleMu     sync.Mutex
 	wantIdle   bool // user has requested to close all idle conns
@@ -113,8 +128,65 @@ type Transport struct {
 	// time does not include the time to read the response body.
 	ResponseHeaderTimeout time.Duration
 
+	// ExpectContinueTimeout, if non-zero, specifies the amount of
+	// time to wait for a server's first response headers after fully
+	// writing the request headers if the request has an
+	// "Expect: 100-continue" header. Zero means no timeout.
+	// This time does not include the time to send the request header.
+	ExpectContinueTimeout time.Duration
+
+	// TLSNextProto specifies how the Transport switches to an
+	// alternate protocol (such as HTTP/2) after a TLS NPN/ALPN
+	// protocol negotiation.  If Transport dials an TLS connection
+	// with a non-empty protocol name and TLSNextProto contains a
+	// map entry for that key (such as "h2"), then the func is
+	// called with the request's authority (such as "example.com"
+	// or "example.com:1234") and the TLS connection. The function
+	// must return a RoundTripper that then handles the request.
+	// If TLSNextProto is nil, HTTP/2 support is enabled automatically.
+	TLSNextProto map[string]func(authority string, c *tls.Conn) RoundTripper
+
+	// nextProtoOnce guards initialization of TLSNextProto and
+	// h2transport (via onceSetNextProtoDefaults)
+	nextProtoOnce sync.Once
+	h2transport   *http2Transport // non-nil if http2 wired up
+
 	// TODO: tunable on global max cached connections
 	// TODO: tunable on timeout on cached connections
+	// TODO: tunable on max per-host TCP dials in flight (Issue 13957)
+}
+
+// onceSetNextProtoDefaults initializes TLSNextProto.
+// It must be called via t.nextProtoOnce.Do.
+func (t *Transport) onceSetNextProtoDefaults() {
+	if strings.Contains(os.Getenv("GODEBUG"), "http2client=0") {
+		return
+	}
+	if t.TLSNextProto != nil {
+		// This is the documented way to disable http2 on a
+		// Transport.
+		return
+	}
+	if t.TLSClientConfig != nil {
+		// Be conservative for now (for Go 1.6) at least and
+		// don't automatically enable http2 if they've
+		// specified a custom TLS config. Let them opt-in
+		// themselves via http2.ConfigureTransport so we don't
+		// surprise them by modifying their tls.Config.
+		// Issue 14275.
+		return
+	}
+	if t.ExpectContinueTimeout != 0 {
+		// Unsupported in http2, so disable http2 for now.
+		// Issue 13851.
+		return
+	}
+	t2, err := http2configureTransport(t)
+	if err != nil {
+		log.Printf("Error enabling Transport HTTP/2 support: %v", err)
+	} else {
+		t.h2transport = t2
+	}
 }
 
 // ProxyFromEnvironment returns the URL of the proxy to use for a
@@ -188,7 +260,8 @@ func (tr *transportRequest) extraHeaders() Header {
 //
 // For higher-level HTTP client support (such as handling of cookies
 // and redirects), see Get, Post, and the Client type.
-func (t *Transport) RoundTrip(req *Request) (resp *Response, err error) {
+func (t *Transport) RoundTrip(req *Request) (*Response, error) {
+	t.nextProtoOnce.Do(t.onceSetNextProtoDefaults)
 	if req.URL == nil {
 		req.closeBody()
 		return nil, errors.New("http: nil Request.URL")
@@ -197,54 +270,114 @@ func (t *Transport) RoundTrip(req *Request) (resp *Response, err error) {
 		req.closeBody()
 		return nil, errors.New("http: nil Request.Header")
 	}
-	if req.URL.Scheme != "http" && req.URL.Scheme != "https" {
-		t.altMu.RLock()
-		var rt RoundTripper
-		if t.altProto != nil {
-			rt = t.altProto[req.URL.Scheme]
+	// TODO(bradfitz): switch to atomic.Value for this map instead of RWMutex
+	t.altMu.RLock()
+	altRT := t.altProto[req.URL.Scheme]
+	t.altMu.RUnlock()
+	if altRT != nil {
+		if resp, err := altRT.RoundTrip(req); err != ErrSkipAltProtocol {
+			return resp, err
 		}
-		t.altMu.RUnlock()
-		if rt == nil {
-			req.closeBody()
-			return nil, &badStringError{"unsupported protocol scheme", req.URL.Scheme}
-		}
-		return rt.RoundTrip(req)
 	}
-	if req.URL.Host == "" {
+	if s := req.URL.Scheme; s != "http" && s != "https" {
 		req.closeBody()
-		return nil, errors.New("http: no Host in request URL")
+		return nil, &badStringError{"unsupported protocol scheme", s}
 	}
-	treq := &transportRequest{Request: req}
-	cm, err := t.connectMethodForRequest(treq)
-	if err != nil {
+	if req.Method != "" && !validMethod(req.Method) {
+		return nil, fmt.Errorf("net/http: invalid method %q", req.Method)
+	}
+	if req.URL.Host == "" {
 		req.closeBody()
-		return nil, err
+		return nil, errors.New("http: no Host in request URL")
 	}
 
-	// Get the cached or newly-created connection to either the
-	// host (for http or https), the http proxy, or the http proxy
-	// pre-CONNECTed to https server.  In any case, we'll be ready
-	// to send it requests.
-	pconn, err := t.getConn(req, cm)
-	if err != nil {
-		t.setReqCanceler(req, nil)
-		req.closeBody()
-		return nil, err
+	for {
+		// treq gets modified by roundTrip, so we need to recreate for each retry.
+		treq := &transportRequest{Request: req}
+		cm, err := t.connectMethodForRequest(treq)
+		if err != nil {
+			req.closeBody()
+			return nil, err
+		}
+
+		// Get the cached or newly-created connection to either the
+		// host (for http or https), the http proxy, or the http proxy
+		// pre-CONNECTed to https server.  In any case, we'll be ready
+		// to send it requests.
+		pconn, err := t.getConn(req, cm)
+		if err != nil {
+			t.setReqCanceler(req, nil)
+			req.closeBody()
+			return nil, err
+		}
+
+		var resp *Response
+		if pconn.alt != nil {
+			// HTTP/2 path.
+			t.setReqCanceler(req, nil) // not cancelable with CancelRequest
+			resp, err = pconn.alt.RoundTrip(req)
+		} else {
+			resp, err = pconn.roundTrip(treq)
+		}
+		if err == nil {
+			return resp, nil
+		}
+		if err := checkTransportResend(err, req, pconn); err != nil {
+			return nil, err
+		}
+		testHookRoundTripRetried()
 	}
+}
 
-	return pconn.roundTrip(treq)
+// checkTransportResend checks whether a failed HTTP request can be
+// resent on a new connection. The non-nil input error is the error from
+// roundTrip, which might be wrapped in a beforeRespHeaderError error.
+//
+// The return value is err or the unwrapped error inside a
+// beforeRespHeaderError.
+func checkTransportResend(err error, req *Request, pconn *persistConn) error {
+	brhErr, ok := err.(beforeRespHeaderError)
+	if !ok {
+		return err
+	}
+	err = brhErr.error // unwrap the custom error in case we return it
+	if err != errMissingHost && pconn.isReused() && req.isReplayable() {
+		// If we try to reuse a connection that the server is in the process of
+		// closing, we may end up successfully writing out our request (or a
+		// portion of our request) only to find a connection error when we try to
+		// read from (or finish writing to) the socket.
+
+		// There can be a race between the socket pool checking whether a socket
+		// is still connected, receiving the FIN, and sending/reading data on a
+		// reused socket. If we receive the FIN between the connectedness check
+		// and writing/reading from the socket, we may first learn the socket is
+		// disconnected when we get a ERR_SOCKET_NOT_CONNECTED. This will most
+		// likely happen when trying to retrieve its IP address. See
+		// http://crbug.com/105824 for more details.
+
+		// We resend a request only if we reused a keep-alive connection and did
+		// not yet receive any header data. This automatically prevents an
+		// infinite resend loop because we'll run out of the cached keep-alive
+		// connections eventually.
+		return nil
+	}
+	return err
 }
 
+// ErrSkipAltProtocol is a sentinel error value defined by Transport.RegisterProtocol.
+var ErrSkipAltProtocol = errors.New("net/http: skip alternate protocol")
+
 // RegisterProtocol registers a new protocol with scheme.
 // The Transport will pass requests using the given scheme to rt.
 // It is rt's responsibility to simulate HTTP request semantics.
 //
 // RegisterProtocol can be used by other packages to provide
 // implementations of protocol schemes like "ftp" or "file".
+//
+// If rt.RoundTrip returns ErrSkipAltProtocol, the Transport will
+// handle the RoundTrip itself for that one request, as if the
+// protocol were not registered.
 func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper) {
-	if scheme == "http" || scheme == "https" {
-		panic("protocol " + scheme + " already registered")
-	}
 	t.altMu.Lock()
 	defer t.altMu.Unlock()
 	if t.altProto == nil {
@@ -261,6 +394,7 @@ func (t *Transport) RegisterProtocol(scheme string, rt RoundTripper) {
 // a "keep-alive" state. It does not interrupt any connections currently
 // in use.
 func (t *Transport) CloseIdleConnections() {
+	t.nextProtoOnce.Do(t.onceSetNextProtoDefaults)
 	t.idleMu.Lock()
 	m := t.idleConn
 	t.idleConn = nil
@@ -269,13 +403,19 @@ func (t *Transport) CloseIdleConnections() {
 	t.idleMu.Unlock()
 	for _, conns := range m {
 		for _, pconn := range conns {
-			pconn.close()
+			pconn.close(errCloseIdleConns)
 		}
 	}
+	if t2 := t.h2transport; t2 != nil {
+		t2.CloseIdleConnections()
+	}
 }
 
 // CancelRequest cancels an in-flight request by closing its connection.
 // CancelRequest should only be called after RoundTrip has returned.
+//
+// Deprecated: Use Request.Cancel instead. CancelRequest can not cancel
+// HTTP/2 requests.
 func (t *Transport) CancelRequest(req *Request) {
 	t.reqMu.Lock()
 	cancel := t.reqCanceler[req]
@@ -354,23 +494,41 @@ func (cm *connectMethod) proxyAuth() string {
 	return ""
 }
 
-// putIdleConn adds pconn to the list of idle persistent connections awaiting
+// error values for debugging and testing, not seen by users.
+var (
+	errKeepAlivesDisabled = errors.New("http: putIdleConn: keep alives disabled")
+	errConnBroken         = errors.New("http: putIdleConn: connection is in bad state")
+	errWantIdle           = errors.New("http: putIdleConn: CloseIdleConnections was called")
+	errTooManyIdle        = errors.New("http: putIdleConn: too many idle connections")
+	errCloseIdleConns     = errors.New("http: CloseIdleConnections called")
+	errReadLoopExiting    = errors.New("http: persistConn.readLoop exiting")
+	errServerClosedIdle   = errors.New("http: server closed idle conn")
+)
+
+func (t *Transport) putOrCloseIdleConn(pconn *persistConn) {
+	if err := t.tryPutIdleConn(pconn); err != nil {
+		pconn.close(err)
+	}
+}
+
+// tryPutIdleConn adds pconn to the list of idle persistent connections awaiting
 // a new request.
-// If pconn is no longer needed or not in a good state, putIdleConn
-// returns false.
-func (t *Transport) putIdleConn(pconn *persistConn) bool {
+// If pconn is no longer needed or not in a good state, tryPutIdleConn returns
+// an error explaining why it wasn't registered.
+// tryPutIdleConn does not close pconn. Use putOrCloseIdleConn instead for that.
+func (t *Transport) tryPutIdleConn(pconn *persistConn) error {
 	if t.DisableKeepAlives || t.MaxIdleConnsPerHost < 0 {
-		pconn.close()
-		return false
+		return errKeepAlivesDisabled
 	}
 	if pconn.isBroken() {
-		return false
+		return errConnBroken
 	}
 	key := pconn.cacheKey
 	max := t.MaxIdleConnsPerHost
 	if max == 0 {
 		max = DefaultMaxIdleConnsPerHost
 	}
+	pconn.markReused()
 	t.idleMu.Lock()
 
 	waitingDialer := t.idleConnCh[key]
@@ -382,7 +540,7 @@ func (t *Transport) putIdleConn(pconn *persistConn) bool {
 		// first). Chrome calls this socket late binding.  See
 		// https://insouciant.org/tech/connection-management-in-chromium/
 		t.idleMu.Unlock()
-		return true
+		return nil
 	default:
 		if waitingDialer != nil {
 			// They had populated this, but their dial won
@@ -392,16 +550,14 @@ func (t *Transport) putIdleConn(pconn *persistConn) bool {
 	}
 	if t.wantIdle {
 		t.idleMu.Unlock()
-		pconn.close()
-		return false
+		return errWantIdle
 	}
 	if t.idleConn == nil {
 		t.idleConn = make(map[connectMethodKey][]*persistConn)
 	}
 	if len(t.idleConn[key]) >= max {
 		t.idleMu.Unlock()
-		pconn.close()
-		return false
+		return errTooManyIdle
 	}
 	for _, exist := range t.idleConn[key] {
 		if exist == pconn {
@@ -410,7 +566,7 @@ func (t *Transport) putIdleConn(pconn *persistConn) bool {
 	}
 	t.idleConn[key] = append(t.idleConn[key], pconn)
 	t.idleMu.Unlock()
-	return true
+	return nil
 }
 
 // getIdleConnCh returns a channel to receive and return idle
@@ -494,16 +650,17 @@ func (t *Transport) replaceReqCanceler(r *Request, fn func()) bool {
 	return true
 }
 
-func (t *Transport) dial(network, addr string) (c net.Conn, err error) {
+func (t *Transport) dial(network, addr string) (net.Conn, error) {
 	if t.Dial != nil {
-		return t.Dial(network, addr)
+		c, err := t.Dial(network, addr)
+		if c == nil && err == nil {
+			err = errors.New("net/http: Transport.Dial hook returned (nil, nil)")
+		}
+		return c, err
 	}
 	return net.Dial(network, addr)
 }
 
-// Testing hooks:
-var prePendingDial, postPendingDial func()
-
 // getConn dials and creates a new persistConn to the target as
 // specified in the connectMethod.  This includes doing a proxy CONNECT
 // and/or setting up TLS.  If this doesn't return an error, the persistConn
@@ -525,20 +682,16 @@ func (t *Transport) getConn(req *Request, cm connectMethod) (*persistConn, error
 
 	// Copy these hooks so we don't race on the postPendingDial in
 	// the goroutine we launch. Issue 11136.
-	prePendingDial := prePendingDial
-	postPendingDial := postPendingDial
+	testHookPrePendingDial := testHookPrePendingDial
+	testHookPostPendingDial := testHookPostPendingDial
 
 	handlePendingDial := func() {
-		if prePendingDial != nil {
-			prePendingDial()
-		}
+		testHookPrePendingDial()
 		go func() {
 			if v := <-dialc; v.err == nil {
-				t.putIdleConn(v.pc)
-			}
-			if postPendingDial != nil {
-				postPendingDial()
+				t.putOrCloseIdleConn(v.pc)
 			}
+			testHookPostPendingDial()
 		}()
 	}
 
@@ -565,10 +718,10 @@ func (t *Transport) getConn(req *Request, cm connectMethod) (*persistConn, error
 		return pc, nil
 	case <-req.Cancel:
 		handlePendingDial()
-		return nil, errors.New("net/http: request canceled while waiting for connection")
+		return nil, errRequestCanceledConn
 	case <-cancelc:
 		handlePendingDial()
-		return nil, errors.New("net/http: request canceled while waiting for connection")
+		return nil, errRequestCanceledConn
 	}
 }
 
@@ -588,7 +741,16 @@ func (t *Transport) dialConn(cm connectMethod) (*persistConn, error) {
 		if err != nil {
 			return nil, err
 		}
+		if pconn.conn == nil {
+			return nil, errors.New("net/http: Transport.DialTLS returned (nil, nil)")
+		}
 		if tc, ok := pconn.conn.(*tls.Conn); ok {
+			// Handshake here, in case DialTLS didn't. TLSNextProto below
+			// depends on it for knowing the connection state.
+			if err := tc.Handshake(); err != nil {
+				go pconn.conn.Close()
+				return nil, err
+			}
 			cs := tc.ConnectionState()
 			pconn.tlsState = &cs
 		}
@@ -680,6 +842,12 @@ func (t *Transport) dialConn(cm connectMethod) (*persistConn, error) {
 		pconn.conn = tlsConn
 	}
 
+	if s := pconn.tlsState; s != nil && s.NegotiatedProtocolIsMutual && s.NegotiatedProtocol != "" {
+		if next, ok := t.TLSNextProto[s.NegotiatedProtocol]; ok {
+			return &persistConn{alt: next(cm.targetAddr, pconn.conn.(*tls.Conn))}, nil
+		}
+	}
+
 	pconn.br = bufio.NewReader(noteEOFReader{pconn.conn, &pconn.sawEOF})
 	pconn.bw = bufio.NewWriter(pconn.conn)
 	go pconn.readLoop()
@@ -809,6 +977,11 @@ func (k connectMethodKey) String() string {
 // persistConn wraps a connection, usually a persistent one
 // (but may be used for non-keep-alive requests as well)
 type persistConn struct {
+	// alt optionally specifies the TLS NextProto RoundTripper.
+	// This is used for HTTP/2 today and future protocol laters.
+	// If it's non-nil, the rest of the fields are unused.
+	alt RoundTripper
+
 	t        *Transport
 	cacheKey connectMethodKey
 	conn     net.Conn
@@ -828,9 +1001,10 @@ type persistConn struct {
 
 	lk                   sync.Mutex // guards following fields
 	numExpectedResponses int
-	closed               bool // whether conn has been closed
-	broken               bool // an error has happened on this connection; marked broken so it's not reused.
-	canceled             bool // whether this conn was broken due a CancelRequest
+	closed               error // set non-nil when conn is closed, before closech is closed
+	broken               bool  // an error has happened on this connection; marked broken so it's not reused.
+	canceled             bool  // whether this conn was broken due a CancelRequest
+	reused               bool  // whether conn has had successful request/response and is being reused.
 	// mutateHeaderFunc is an optional func to modify extra
 	// headers on each outbound request before it's written. (the
 	// original Request given to RoundTrip is not modified)
@@ -852,15 +1026,34 @@ func (pc *persistConn) isCanceled() bool {
 	return pc.canceled
 }
 
+// isReused reports whether this connection is in a known broken state.
+func (pc *persistConn) isReused() bool {
+	pc.lk.Lock()
+	r := pc.reused
+	pc.lk.Unlock()
+	return r
+}
+
 func (pc *persistConn) cancelRequest() {
 	pc.lk.Lock()
 	defer pc.lk.Unlock()
 	pc.canceled = true
-	pc.closeLocked()
+	pc.closeLocked(errRequestCanceled)
 }
 
 func (pc *persistConn) readLoop() {
-	// eofc is used to block http.Handler goroutines reading from Response.Body
+	closeErr := errReadLoopExiting // default value, if not changed below
+	defer func() { pc.close(closeErr) }()
+
+	tryPutIdleConn := func() bool {
+		if err := pc.t.tryPutIdleConn(pc); err != nil {
+			closeErr = err
+			return false
+		}
+		return true
+	}
+
+	// eofc is used to block caller goroutines reading from Response.Body
 	// at EOF until this goroutines has (potentially) added the connection
 	// back to the idle pool.
 	eofc := make(chan struct{})
@@ -873,17 +1066,14 @@ func (pc *persistConn) readLoop() {
 
 	alive := true
 	for alive {
-		pb, err := pc.br.Peek(1)
+		_, err := pc.br.Peek(1)
+		if err != nil {
+			err = beforeRespHeaderError{err}
+		}
 
 		pc.lk.Lock()
 		if pc.numExpectedResponses == 0 {
-			if !pc.closed {
-				pc.closeLocked()
-				if len(pb) > 0 {
-					log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v",
-						string(pb), err)
-				}
-			}
+			pc.readLoopPeekFailLocked(err)
 			pc.lk.Unlock()
 			return
 		}
@@ -893,115 +1083,189 @@ func (pc *persistConn) readLoop() {
 
 		var resp *Response
 		if err == nil {
-			resp, err = ReadResponse(pc.br, rc.req)
-			if err == nil && resp.StatusCode == 100 {
-				// Skip any 100-continue for now.
-				// TODO(bradfitz): if rc.req had "Expect: 100-continue",
-				// actually block the request body write and signal the
-				// writeLoop now to begin sending it. (Issue 2184) For now we
-				// eat it, since we're never expecting one.
-				resp, err = ReadResponse(pc.br, rc.req)
-			}
+			resp, err = pc.readResponse(rc)
 		}
 
-		if resp != nil {
-			resp.TLS = pc.tlsState
-		}
-
-		hasBody := resp != nil && rc.req.Method != "HEAD" && resp.ContentLength != 0
-
 		if err != nil {
-			pc.close()
-		} else {
-			if rc.addedGzip && hasBody && resp.Header.Get("Content-Encoding") == "gzip" {
-				resp.Header.Del("Content-Encoding")
-				resp.Header.Del("Content-Length")
-				resp.ContentLength = -1
-				resp.Body = &gzipReader{body: resp.Body}
+			// If we won't be able to retry this request later (from the
+			// roundTrip goroutine), mark it as done now.
+			// BEFORE the send on rc.ch, as the client might re-use the
+			// same *Request pointer, and we don't want to set call
+			// t.setReqCanceler from this persistConn while the Transport
+			// potentially spins up a different persistConn for the
+			// caller's subsequent request.
+			if checkTransportResend(err, rc.req, pc) != nil {
+				pc.t.setReqCanceler(rc.req, nil)
 			}
-			resp.Body = &bodyEOFSignal{body: resp.Body}
+			select {
+			case rc.ch <- responseAndError{err: err}:
+			case <-rc.callerGone:
+				return
+			}
+			return
 		}
 
-		if err != nil || resp.Close || rc.req.Close || resp.StatusCode <= 199 {
+		pc.lk.Lock()
+		pc.numExpectedResponses--
+		pc.lk.Unlock()
+
+		hasBody := rc.req.Method != "HEAD" && resp.ContentLength != 0
+
+		if resp.Close || rc.req.Close || resp.StatusCode <= 199 {
 			// Don't do keep-alive on error if either party requested a close
 			// or we get an unexpected informational (1xx) response.
 			// StatusCode 100 is already handled above.
 			alive = false
 		}
 
-		var waitForBodyRead chan bool // channel is nil when there's no body
-		if hasBody {
-			waitForBodyRead = make(chan bool, 2)
-			resp.Body.(*bodyEOFSignal).earlyCloseFn = func() error {
-				waitForBodyRead <- false
-				return nil
-			}
-			resp.Body.(*bodyEOFSignal).fn = func(err error) error {
-				isEOF := err == io.EOF
-				waitForBodyRead <- isEOF
-				if isEOF {
-					<-eofc // see comment at top
-				} else if err != nil && pc.isCanceled() {
-					return errRequestCanceled
-				}
-				return err
-			}
-		} else {
-			// Before send on rc.ch, as client might re-use the
-			// same *Request pointer, and we don't want to set this
-			// on t from this persistConn while the Transport
-			// potentially spins up a different persistConn for the
-			// caller's subsequent request.
+		if !hasBody {
 			pc.t.setReqCanceler(rc.req, nil)
-		}
 
-		pc.lk.Lock()
-		pc.numExpectedResponses--
-		pc.lk.Unlock()
+			// Put the idle conn back into the pool before we send the response
+			// so if they process it quickly and make another request, they'll
+			// get this same conn. But we use the unbuffered channel 'rc'
+			// to guarantee that persistConn.roundTrip got out of its select
+			// potentially waiting for this persistConn to close.
+			// but after
+			alive = alive &&
+				!pc.sawEOF &&
+				pc.wroteRequest() &&
+				tryPutIdleConn()
 
-		// The connection might be going away when we put the
-		// idleConn below. When that happens, we close the response channel to signal
-		// to roundTrip that the connection is gone. roundTrip waits for
-		// both closing and a response in a select, so it might choose
-		// the close channel, rather than the response.
-		// We send the response first so that roundTrip can check
-		// if there is a pending one with a non-blocking select
-		// on the response channel before erroring out.
-		rc.ch <- responseAndError{resp, err}
-
-		if hasBody {
-			// To avoid a race, wait for the just-returned
-			// response body to be fully consumed before peek on
-			// the underlying bufio reader.
 			select {
-			case <-rc.req.Cancel:
-				alive = false
-				pc.t.CancelRequest(rc.req)
-			case bodyEOF := <-waitForBodyRead:
-				pc.t.setReqCanceler(rc.req, nil) // before pc might return to idle pool
-				alive = alive &&
-					bodyEOF &&
-					!pc.sawEOF &&
-					pc.wroteRequest() &&
-					pc.t.putIdleConn(pc)
-				if bodyEOF {
-					eofc <- struct{}{}
-				}
-			case <-pc.closech:
-				alive = false
+			case rc.ch <- responseAndError{res: resp}:
+			case <-rc.callerGone:
+				return
 			}
-		} else {
+
+			// Now that they've read from the unbuffered channel, they're safely
+			// out of the select that also waits on this goroutine to die, so
+			// we're allowed to exit now if needed (if alive is false)
+			testHookReadLoopBeforeNextRead()
+			continue
+		}
+
+		if rc.addedGzip {
+			maybeUngzipResponse(resp)
+		}
+		resp.Body = &bodyEOFSignal{body: resp.Body}
+
+		waitForBodyRead := make(chan bool, 2)
+		resp.Body.(*bodyEOFSignal).earlyCloseFn = func() error {
+			waitForBodyRead <- false
+			return nil
+		}
+		resp.Body.(*bodyEOFSignal).fn = func(err error) error {
+			isEOF := err == io.EOF
+			waitForBodyRead <- isEOF
+			if isEOF {
+				<-eofc // see comment above eofc declaration
+			} else if err != nil && pc.isCanceled() {
+				return errRequestCanceled
+			}
+			return err
+		}
+
+		select {
+		case rc.ch <- responseAndError{res: resp}:
+		case <-rc.callerGone:
+			return
+		}
+
+		// Before looping back to the top of this function and peeking on
+		// the bufio.Reader, wait for the caller goroutine to finish
+		// reading the response body. (or for cancelation or death)
+		select {
+		case bodyEOF := <-waitForBodyRead:
+			pc.t.setReqCanceler(rc.req, nil) // before pc might return to idle pool
 			alive = alive &&
+				bodyEOF &&
 				!pc.sawEOF &&
 				pc.wroteRequest() &&
-				pc.t.putIdleConn(pc)
+				tryPutIdleConn()
+			if bodyEOF {
+				eofc <- struct{}{}
+			}
+		case <-rc.req.Cancel:
+			alive = false
+			pc.t.CancelRequest(rc.req)
+		case <-pc.closech:
+			alive = false
 		}
 
-		if hook := testHookReadLoopBeforeNextRead; hook != nil {
-			hook()
+		testHookReadLoopBeforeNextRead()
+	}
+}
+
+func maybeUngzipResponse(resp *Response) {
+	if resp.Header.Get("Content-Encoding") == "gzip" {
+		resp.Header.Del("Content-Encoding")
+		resp.Header.Del("Content-Length")
+		resp.ContentLength = -1
+		resp.Body = &gzipReader{body: resp.Body}
+	}
+}
+
+func (pc *persistConn) readLoopPeekFailLocked(peekErr error) {
+	if pc.closed != nil {
+		return
+	}
+	if n := pc.br.Buffered(); n > 0 {
+		buf, _ := pc.br.Peek(n)
+		log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v", buf, peekErr)
+	}
+	if peekErr == io.EOF {
+		// common case.
+		pc.closeLocked(errServerClosedIdle)
+	} else {
+		pc.closeLocked(fmt.Errorf("readLoopPeekFailLocked: %v", peekErr))
+	}
+}
+
+// readResponse reads an HTTP response (or two, in the case of "Expect:
+// 100-continue") from the server. It returns the final non-100 one.
+func (pc *persistConn) readResponse(rc requestAndChan) (resp *Response, err error) {
+	resp, err = ReadResponse(pc.br, rc.req)
+	if err != nil {
+		return
+	}
+	if rc.continueCh != nil {
+		if resp.StatusCode == 100 {
+			rc.continueCh <- struct{}{}
+		} else {
+			close(rc.continueCh)
+		}
+	}
+	if resp.StatusCode == 100 {
+		resp, err = ReadResponse(pc.br, rc.req)
+		if err != nil {
+			return
+		}
+	}
+	resp.TLS = pc.tlsState
+	return
+}
+
+// waitForContinue returns the function to block until
+// any response, timeout or connection close. After any of them,
+// the function returns a bool which indicates if the body should be sent.
+func (pc *persistConn) waitForContinue(continueCh <-chan struct{}) func() bool {
+	if continueCh == nil {
+		return nil
+	}
+	return func() bool {
+		timer := time.NewTimer(pc.t.ExpectContinueTimeout)
+		defer timer.Stop()
+
+		select {
+		case _, ok := <-continueCh:
+			return ok
+		case <-timer.C:
+			return true
+		case <-pc.closech:
+			return false
 		}
 	}
-	pc.close()
 }
 
 func (pc *persistConn) writeLoop() {
@@ -1012,7 +1276,7 @@ func (pc *persistConn) writeLoop() {
 				wr.ch <- errors.New("http: can't write HTTP request on broken connection")
 				continue
 			}
-			err := wr.req.Request.write(pc.bw, pc.isProxy, wr.req.extra)
+			err := wr.req.Request.write(pc.bw, pc.isProxy, wr.req.extra, pc.waitForContinue(wr.continueCh))
 			if err == nil {
 				err = pc.bw.Flush()
 			}
@@ -1056,19 +1320,29 @@ func (pc *persistConn) wroteRequest() bool {
 	}
 }
 
+// responseAndError is how the goroutine reading from an HTTP/1 server
+// communicates with the goroutine doing the RoundTrip.
 type responseAndError struct {
-	res *Response
+	res *Response // else use this response (see res method)
 	err error
 }
 
 type requestAndChan struct {
 	req *Request
-	ch  chan responseAndError
+	ch  chan responseAndError // unbuffered; always send in select on callerGone
 
 	// did the Transport (as opposed to the client code) add an
 	// Accept-Encoding gzip header? only if it we set it do
 	// we transparently decode the gzip.
 	addedGzip bool
+
+	// Optional blocking chan for Expect: 100-continue (for send).
+	// If the request has an "Expect: 100-continue" header and
+	// the server responds 100 Continue, readLoop send a value
+	// to writeLoop via this chan.
+	continueCh chan<- struct{}
+
+	callerGone <-chan struct{} // closed when roundTrip caller has returned
 }
 
 // A writeRequest is sent by the readLoop's goroutine to the
@@ -1078,6 +1352,11 @@ type requestAndChan struct {
 type writeRequest struct {
 	req *transportRequest
 	ch  chan<- error
+
+	// Optional blocking chan for Expect: 100-continue (for recieve).
+	// If not nil, writeLoop blocks sending request body until
+	// it receives from this chan.
+	continueCh <-chan struct{}
 }
 
 type httpError struct {
@@ -1090,23 +1369,34 @@ func (e *httpError) Timeout() bool   { return e.timeout }
 func (e *httpError) Temporary() bool { return true }
 
 var errTimeout error = &httpError{err: "net/http: timeout awaiting response headers", timeout: true}
-var errClosed error = &httpError{err: "net/http: transport closed before response was received"}
+var errClosed error = &httpError{err: "net/http: server closed connection before response was received"}
 var errRequestCanceled = errors.New("net/http: request canceled")
+var errRequestCanceledConn = errors.New("net/http: request canceled while waiting for connection") // TODO: unify?
+
+func nop() {}
 
-// nil except for tests
+// testHooks. Always non-nil.
 var (
-	testHookPersistConnClosedGotRes func()
-	testHookEnterRoundTrip          func()
-	testHookMu                      sync.Locker = fakeLocker{} // guards following
-	testHookReadLoopBeforeNextRead  func()
+	testHookEnterRoundTrip   = nop
+	testHookWaitResLoop      = nop
+	testHookRoundTripRetried = nop
+	testHookPrePendingDial   = nop
+	testHookPostPendingDial  = nop
+
+	testHookMu                     sync.Locker = fakeLocker{} // guards following
+	testHookReadLoopBeforeNextRead             = nop
 )
 
+// beforeRespHeaderError is used to indicate when an IO error has occurred before
+// any header data was received.
+type beforeRespHeaderError struct {
+	error
+}
+
 func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err error) {
-	if hook := testHookEnterRoundTrip; hook != nil {
-		hook()
-	}
+	testHookEnterRoundTrip()
 	if !pc.t.replaceReqCanceler(req.Request, pc.cancelRequest) {
-		pc.t.putIdleConn(pc)
+		pc.t.putOrCloseIdleConn(pc)
 		return nil, errRequestCanceled
 	}
 	pc.lk.Lock()
@@ -1143,42 +1433,47 @@ func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err err
 		req.extraHeaders().Set("Accept-Encoding", "gzip")
 	}
 
+	var continueCh chan struct{}
+	if req.ProtoAtLeast(1, 1) && req.Body != nil && req.expectsContinue() {
+		continueCh = make(chan struct{}, 1)
+	}
+
 	if pc.t.DisableKeepAlives {
 		req.extraHeaders().Set("Connection", "close")
 	}
 
+	gone := make(chan struct{})
+	defer close(gone)
+
 	// Write the request concurrently with waiting for a response,
 	// in case the server decides to reply before reading our full
 	// request body.
 	writeErrCh := make(chan error, 1)
-	pc.writech <- writeRequest{req, writeErrCh}
+	pc.writech <- writeRequest{req, writeErrCh, continueCh}
 
-	resc := make(chan responseAndError, 1)
-	pc.reqch <- requestAndChan{req.Request, resc, requestedGzip}
+	resc := make(chan responseAndError)
+	pc.reqch <- requestAndChan{
+		req:        req.Request,
+		ch:         resc,
+		addedGzip:  requestedGzip,
+		continueCh: continueCh,
+		callerGone: gone,
+	}
 
 	var re responseAndError
 	var respHeaderTimer <-chan time.Time
 	cancelChan := req.Request.Cancel
 WaitResponse:
 	for {
+		testHookWaitResLoop()
 		select {
 		case err := <-writeErrCh:
-			if isNetWriteError(err) {
-				// Issue 11745. If we failed to write the request
-				// body, it's possible the server just heard enough
-				// and already wrote to us. Prioritize the server's
-				// response over returning a body write error.
-				select {
-				case re = <-resc:
-					pc.close()
-					break WaitResponse
-				case <-time.After(50 * time.Millisecond):
-					// Fall through.
-				}
-			}
 			if err != nil {
-				re = responseAndError{nil, err}
-				pc.close()
+				if pc.isCanceled() {
+					err = errRequestCanceled
+				}
+				re = responseAndError{err: beforeRespHeaderError{err}}
+				pc.close(fmt.Errorf("write error: %v", err))
 				break WaitResponse
 			}
 			if d := pc.t.ResponseHeaderTimeout; d > 0 {
@@ -1187,33 +1482,22 @@ WaitResponse:
 				respHeaderTimer = timer.C
 			}
 		case <-pc.closech:
-			// The persist connection is dead. This shouldn't
-			// usually happen (only with Connection: close responses
-			// with no response bodies), but if it does happen it
-			// means either a) the remote server hung up on us
-			// prematurely, or b) the readLoop sent us a response &
-			// closed its closech at roughly the same time, and we
-			// selected this case first. If we got a response, readLoop makes sure
-			// to send it before it puts the conn and closes the channel.
-			// That way, we can fetch the response, if there is one,
-			// with a non-blocking receive.
-			select {
-			case re = <-resc:
-				if fn := testHookPersistConnClosedGotRes; fn != nil {
-					fn()
-				}
-			default:
-				re = responseAndError{err: errClosed}
-				if pc.isCanceled() {
-					re = responseAndError{err: errRequestCanceled}
-				}
+			var err error
+			if pc.isCanceled() {
+				err = errRequestCanceled
+			} else {
+				err = beforeRespHeaderError{fmt.Errorf("net/http: HTTP/1 transport connection broken: %v", pc.closed)}
 			}
+			re = responseAndError{err: err}
 			break WaitResponse
 		case <-respHeaderTimer:
-			pc.close()
+			pc.close(errTimeout)
 			re = responseAndError{err: errTimeout}
 			break WaitResponse
 		case re = <-resc:
+			if re.err != nil && pc.isCanceled() {
+				re.err = errRequestCanceled
+			}
 			break WaitResponse
 		case <-cancelChan:
 			pc.t.CancelRequest(req.Request)
@@ -1224,6 +1508,9 @@ WaitResponse:
 	if re.err != nil {
 		pc.t.setReqCanceler(req.Request, nil)
 	}
+	if (re.res == nil) == (re.err == nil) {
+		panic("internal error: exactly one of res or err should be set")
+	}
 	return re.res, re.err
 }
 
@@ -1236,18 +1523,44 @@ func (pc *persistConn) markBroken() {
 	pc.broken = true
 }
 
-func (pc *persistConn) close() {
+// markReused marks this connection as having been successfully used for a
+// request and response.
+func (pc *persistConn) markReused() {
+	pc.lk.Lock()
+	pc.reused = true
+	pc.lk.Unlock()
+}
+
+// close closes the underlying TCP connection and closes
+// the pc.closech channel.
+//
+// The provided err is only for testing and debugging; in normal
+// circumstances it should never be seen by users.
+func (pc *persistConn) close(err error) {
 	pc.lk.Lock()
 	defer pc.lk.Unlock()
-	pc.closeLocked()
+	pc.closeLocked(err)
 }
 
-func (pc *persistConn) closeLocked() {
+func (pc *persistConn) closeLocked(err error) {
+	if err == nil {
+		panic("nil error")
+	}
 	pc.broken = true
-	if !pc.closed {
-		pc.conn.Close()
-		pc.closed = true
-		close(pc.closech)
+	if pc.closed == nil {
+		pc.closed = err
+		if pc.alt != nil {
+			// Do nothing; can only get here via getConn's
+			// handlePendingDial's putOrCloseIdleConn when
+			// it turns out the abandoned connection in
+			// flight ended up negotiating an alternate
+			// protocol.  We don't use the connection
+			// freelist for http2. That's done by the
+			// alternate protocol's RoundTripper.
+		} else {
+			pc.conn.Close()
+			close(pc.closech)
+		}
 	}
 	pc.mutateHeaderFunc = nil
 }
diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go
index c21d4af..0c901b3 100644
--- a/src/net/http/transport_test.go
+++ b/src/net/http/transport_test.go
@@ -2,7 +2,10 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Tests for transport.go
+// Tests for transport.go.
+//
+// More tests are in clientserver_test.go (for things testing both client & server for both
+// HTTP/1 and HTTP/2). This
 
 package http_test
 
@@ -20,6 +23,8 @@ import (
 	"net"
 	. "net/http"
 	"net/http/httptest"
+	"net/http/httputil"
+	"net/http/internal"
 	"net/url"
 	"os"
 	"reflect"
@@ -256,6 +261,7 @@ func TestTransportConnectionCloseOnRequest(t *testing.T) {
 
 // if the Transport's DisableKeepAlives is set, all requests should
 // send Connection: close.
+// HTTP/1-only (Connection: close doesn't exist in h2)
 func TestTransportConnectionCloseOnRequestDisableKeepAlive(t *testing.T) {
 	defer afterTest(t)
 	ts := httptest.NewServer(hostPortHandler)
@@ -431,6 +437,7 @@ func TestTransportMaxPerHostIdleConns(t *testing.T) {
 }
 
 func TestTransportServerClosingUnexpectedly(t *testing.T) {
+	setParallel(t)
 	defer afterTest(t)
 	ts := httptest.NewServer(hostPortHandler)
 	defer ts.Close()
@@ -597,6 +604,7 @@ func TestTransportHeadChunkedResponse(t *testing.T) {
 
 	tr := &Transport{DisableKeepAlives: false}
 	c := &Client{Transport: tr}
+	defer tr.CloseIdleConnections()
 
 	// Ensure that we wait for the readLoop to complete before
 	// calling Head again
@@ -790,6 +798,94 @@ func TestTransportGzip(t *testing.T) {
 	}
 }
 
+// If a request has Expect:100-continue header, the request blocks sending body until the first response.
+// Premature consumption of the request body should not be occurred.
+func TestTransportExpect100Continue(t *testing.T) {
+	defer afterTest(t)
+
+	ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
+		switch req.URL.Path {
+		case "/100":
+			// This endpoint implicitly responds 100 Continue and reads body.
+			if _, err := io.Copy(ioutil.Discard, req.Body); err != nil {
+				t.Error("Failed to read Body", err)
+			}
+			rw.WriteHeader(StatusOK)
+		case "/200":
+			// Go 1.5 adds Connection: close header if the client expect
+			// continue but not entire request body is consumed.
+			rw.WriteHeader(StatusOK)
+		case "/500":
+			rw.WriteHeader(StatusInternalServerError)
+		case "/keepalive":
+			// This hijacked endpoint responds error without Connection:close.
+			_, bufrw, err := rw.(Hijacker).Hijack()
+			if err != nil {
+				log.Fatal(err)
+			}
+			bufrw.WriteString("HTTP/1.1 500 Internal Server Error\r\n")
+			bufrw.WriteString("Content-Length: 0\r\n\r\n")
+			bufrw.Flush()
+		case "/timeout":
+			// This endpoint tries to read body without 100 (Continue) response.
+			// After ExpectContinueTimeout, the reading will be started.
+			conn, bufrw, err := rw.(Hijacker).Hijack()
+			if err != nil {
+				log.Fatal(err)
+			}
+			if _, err := io.CopyN(ioutil.Discard, bufrw, req.ContentLength); err != nil {
+				t.Error("Failed to read Body", err)
+			}
+			bufrw.WriteString("HTTP/1.1 200 OK\r\n\r\n")
+			bufrw.Flush()
+			conn.Close()
+		}
+
+	}))
+	defer ts.Close()
+
+	tests := []struct {
+		path   string
+		body   []byte
+		sent   int
+		status int
+	}{
+		{path: "/100", body: []byte("hello"), sent: 5, status: 200},       // Got 100 followed by 200, entire body is sent.
+		{path: "/200", body: []byte("hello"), sent: 0, status: 200},       // Got 200 without 100. body isn't sent.
+		{path: "/500", body: []byte("hello"), sent: 0, status: 500},       // Got 500 without 100. body isn't sent.
+		{path: "/keepalive", body: []byte("hello"), sent: 0, status: 500}, // Althogh without Connection:close, body isn't sent.
+		{path: "/timeout", body: []byte("hello"), sent: 5, status: 200},   // Timeout exceeded and entire body is sent.
+	}
+
+	for i, v := range tests {
+		tr := &Transport{ExpectContinueTimeout: 2 * time.Second}
+		defer tr.CloseIdleConnections()
+		c := &Client{Transport: tr}
+
+		body := bytes.NewReader(v.body)
+		req, err := NewRequest("PUT", ts.URL+v.path, body)
+		if err != nil {
+			t.Fatal(err)
+		}
+		req.Header.Set("Expect", "100-continue")
+		req.ContentLength = int64(len(v.body))
+
+		resp, err := c.Do(req)
+		if err != nil {
+			t.Fatal(err)
+		}
+		resp.Body.Close()
+
+		sent := len(v.body) - body.Len()
+		if v.status != resp.StatusCode {
+			t.Errorf("test %d: status code should be %d but got %d. (%s)", i, v.status, resp.StatusCode, v.path)
+		}
+		if v.sent != sent {
+			t.Errorf("test %d: sent body should be %d but sent %d. (%s)", i, v.sent, sent, v.path)
+		}
+	}
+}
+
 func TestTransportProxy(t *testing.T) {
 	defer afterTest(t)
 	ch := make(chan string, 1)
@@ -874,9 +970,7 @@ func TestTransportGzipShort(t *testing.T) {
 
 // tests that persistent goroutine connections shut down when no longer desired.
 func TestTransportPersistConnLeak(t *testing.T) {
-	if runtime.GOOS == "plan9" {
-		t.Skip("skipping test; see https://golang.org/issue/7237")
-	}
+	setParallel(t)
 	defer afterTest(t)
 	gotReqCh := make(chan bool)
 	unblockCh := make(chan bool)
@@ -943,9 +1037,7 @@ func TestTransportPersistConnLeak(t *testing.T) {
 // golang.org/issue/4531: Transport leaks goroutines when
 // request.ContentLength is explicitly short
 func TestTransportPersistConnLeakShortBody(t *testing.T) {
-	if runtime.GOOS == "plan9" {
-		t.Skip("skipping test; see https://golang.org/issue/7237")
-	}
+	setParallel(t)
 	defer afterTest(t)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 	}))
@@ -1286,6 +1378,7 @@ func TestIssue4191_InfiniteGetToPutTimeout(t *testing.T) {
 }
 
 func TestTransportResponseHeaderTimeout(t *testing.T) {
+	setParallel(t)
 	defer afterTest(t)
 	if testing.Short() {
 		t.Skip("skipping timeout test in -short mode")
@@ -1357,6 +1450,7 @@ func TestTransportResponseHeaderTimeout(t *testing.T) {
 }
 
 func TestTransportCancelRequest(t *testing.T) {
+	setParallel(t)
 	defer afterTest(t)
 	if testing.Short() {
 		t.Skip("skipping test in -short mode")
@@ -1466,6 +1560,7 @@ Get = Get http://something.no-network.tld/: net/http: request canceled while wai
 }
 
 func TestCancelRequestWithChannel(t *testing.T) {
+	setParallel(t)
 	defer afterTest(t)
 	if testing.Short() {
 		t.Skip("skipping test in -short mode")
@@ -1523,6 +1618,7 @@ func TestCancelRequestWithChannel(t *testing.T) {
 }
 
 func TestCancelRequestWithChannelBeforeDo(t *testing.T) {
+	setParallel(t)
 	defer afterTest(t)
 	unblockc := make(chan bool)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -1554,7 +1650,6 @@ func TestCancelRequestWithChannelBeforeDo(t *testing.T) {
 
 // Issue 11020. The returned error message should be errRequestCanceled
 func TestTransportCancelBeforeResponseHeaders(t *testing.T) {
-	t.Skip("Skipping flaky test; see Issue 11894")
 	defer afterTest(t)
 
 	serverConnCh := make(chan net.Conn, 1)
@@ -1704,6 +1799,19 @@ func TestTransportNoHost(t *testing.T) {
 	}
 }
 
+// Issue 13311
+func TestTransportEmptyMethod(t *testing.T) {
+	req, _ := NewRequest("GET", "http://foo.com/", nil)
+	req.Method = ""                                 // docs say "For client requests an empty string means GET"
+	got, err := httputil.DumpRequestOut(req, false) // DumpRequestOut uses Transport
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !strings.Contains(string(got), "GET ") {
+		t.Fatalf("expected substring 'GET '; got: %s", got)
+	}
+}
+
 func TestTransportSocketLateBinding(t *testing.T) {
 	defer afterTest(t)
 
@@ -2100,9 +2208,8 @@ func TestTransportTLSHandshakeTimeout(t *testing.T) {
 // Trying to repro golang.org/issue/3514
 func TestTLSServerClosesConnection(t *testing.T) {
 	defer afterTest(t)
-	if runtime.GOOS == "windows" {
-		t.Skip("skipping flaky test on Windows; golang.org/issue/7634")
-	}
+	setFlaky(t, 7634)
+
 	closedc := make(chan bool, 1)
 	ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		if strings.Contains(r.URL.Path, "/keep-alive-then-die") {
@@ -2291,15 +2398,103 @@ type errorReader struct {
 
 func (e errorReader) Read(p []byte) (int, error) { return 0, e.err }
 
+type plan9SleepReader struct{}
+
+func (plan9SleepReader) Read(p []byte) (int, error) {
+	if runtime.GOOS == "plan9" {
+		// After the fix to unblock TCP Reads in
+		// https://golang.org/cl/15941, this sleep is required
+		// on plan9 to make sure TCP Writes before an
+		// immediate TCP close go out on the wire.  On Plan 9,
+		// it seems that a hangup of a TCP connection with
+		// queued data doesn't send the queued data first.
+		// https://golang.org/issue/9554
+		time.Sleep(50 * time.Millisecond)
+	}
+	return 0, io.EOF
+}
+
 type closerFunc func() error
 
 func (f closerFunc) Close() error { return f() }
 
+// Issue 4677. If we try to reuse a connection that the server is in the
+// process of closing, we may end up successfully writing out our request (or a
+// portion of our request) only to find a connection error when we try to read
+// from (or finish writing to) the socket.
+//
+// NOTE: we resend a request only if the request is idempotent, we reused a
+// keep-alive connection, and we haven't yet received any header data.  This
+// automatically prevents an infinite resend loop because we'll run out of the
+// cached keep-alive connections eventually.
+func TestRetryIdempotentRequestsOnError(t *testing.T) {
+	defer afterTest(t)
+
+	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+	}))
+	defer ts.Close()
+
+	tr := &Transport{}
+	c := &Client{Transport: tr}
+
+	const N = 2
+	retryc := make(chan struct{}, N)
+	SetRoundTripRetried(func() {
+		retryc <- struct{}{}
+	})
+	defer SetRoundTripRetried(nil)
+
+	for n := 0; n < 100; n++ {
+		// open 2 conns
+		errc := make(chan error, N)
+		for i := 0; i < N; i++ {
+			// start goroutines, send on errc
+			go func() {
+				res, err := c.Get(ts.URL)
+				if err == nil {
+					res.Body.Close()
+				}
+				errc <- err
+			}()
+		}
+		for i := 0; i < N; i++ {
+			if err := <-errc; err != nil {
+				t.Fatal(err)
+			}
+		}
+
+		ts.CloseClientConnections()
+		for i := 0; i < N; i++ {
+			go func() {
+				res, err := c.Get(ts.URL)
+				if err == nil {
+					res.Body.Close()
+				}
+				errc <- err
+			}()
+		}
+
+		for i := 0; i < N; i++ {
+			if err := <-errc; err != nil {
+				t.Fatal(err)
+			}
+		}
+		for i := 0; i < N; i++ {
+			select {
+			case <-retryc:
+				// we triggered a retry, test was successful
+				t.Logf("finished after %d runs\n", n)
+				return
+			default:
+			}
+		}
+	}
+	t.Fatal("did not trigger any retries")
+}
+
 // Issue 6981
 func TestTransportClosesBodyOnError(t *testing.T) {
-	if runtime.GOOS == "plan9" {
-		t.Skip("skipping test; see https://golang.org/issue/7782")
-	}
+	setParallel(t)
 	defer afterTest(t)
 	readBody := make(chan error, 1)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
@@ -2313,7 +2508,7 @@ func TestTransportClosesBodyOnError(t *testing.T) {
 		io.Reader
 		io.Closer
 	}{
-		io.MultiReader(io.LimitReader(neverEnding('x'), 1<<20), errorReader{fakeErr}),
+		io.MultiReader(io.LimitReader(neverEnding('x'), 1<<20), plan9SleepReader{}, errorReader{fakeErr}),
 		closerFunc(func() error {
 			select {
 			case didClose <- true:
@@ -2474,52 +2669,6 @@ func TestTransportRangeAndGzip(t *testing.T) {
 	res.Body.Close()
 }
 
-// Previously, we used to handle a logical race within RoundTrip by waiting for 100ms
-// in the case of an error. Changing the order of the channel operations got rid of this
-// race.
-//
-// In order to test that the channel op reordering works, we install a hook into the
-// roundTrip function which gets called if we saw the connection go away and
-// we subsequently received a response.
-func TestTransportResponseCloseRace(t *testing.T) {
-	if testing.Short() {
-		t.Skip("skipping in short mode")
-	}
-	defer afterTest(t)
-
-	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-	}))
-	defer ts.Close()
-	sawRace := false
-	SetInstallConnClosedHook(func() {
-		sawRace = true
-	})
-	defer SetInstallConnClosedHook(nil)
-	tr := &Transport{
-		DisableKeepAlives: true,
-	}
-	req, err := NewRequest("GET", ts.URL, nil)
-	if err != nil {
-		t.Fatal(err)
-	}
-	// selects are not deterministic, so do this a bunch
-	// and see if we handle the logical race at least once.
-	for i := 0; i < 10000; i++ {
-		resp, err := tr.RoundTrip(req)
-		if err != nil {
-			t.Fatalf("unexpected error: %s", err)
-			continue
-		}
-		resp.Body.Close()
-		if sawRace {
-			break
-		}
-	}
-	if !sawRace {
-		t.Errorf("didn't see response/connection going away race")
-	}
-}
-
 // Test for issue 10474
 func TestTransportResponseCancelRace(t *testing.T) {
 	defer afterTest(t)
@@ -2645,7 +2794,7 @@ func TestTransportFlushesBodyChunks(t *testing.T) {
 		req.Header.Set("User-Agent", "x") // known value for test
 		res, err := tr.RoundTrip(req)
 		if err != nil {
-			t.Error("RoundTrip: %v", err)
+			t.Errorf("RoundTrip: %v", err)
 			close(resc)
 			return
 		}
@@ -2735,6 +2884,164 @@ func TestTransportPrefersResponseOverWriteError(t *testing.T) {
 	}
 }
 
+func TestTransportAutomaticHTTP2(t *testing.T) {
+	testTransportAutoHTTP(t, &Transport{}, true)
+}
+
+func TestTransportAutomaticHTTP2_TLSNextProto(t *testing.T) {
+	testTransportAutoHTTP(t, &Transport{
+		TLSNextProto: make(map[string]func(string, *tls.Conn) RoundTripper),
+	}, false)
+}
+
+func TestTransportAutomaticHTTP2_TLSConfig(t *testing.T) {
+	testTransportAutoHTTP(t, &Transport{
+		TLSClientConfig: new(tls.Config),
+	}, false)
+}
+
+func TestTransportAutomaticHTTP2_ExpectContinueTimeout(t *testing.T) {
+	testTransportAutoHTTP(t, &Transport{
+		ExpectContinueTimeout: 1 * time.Second,
+	}, false)
+}
+
+func testTransportAutoHTTP(t *testing.T, tr *Transport, wantH2 bool) {
+	_, err := tr.RoundTrip(new(Request))
+	if err == nil {
+		t.Error("expected error from RoundTrip")
+	}
+	if reg := tr.TLSNextProto["h2"] != nil; reg != wantH2 {
+		t.Errorf("HTTP/2 registered = %v; want %v", reg, wantH2)
+	}
+}
+
+// Issue 13633: there was a race where we returned bodyless responses
+// to callers before recycling the persistent connection, which meant
+// a client doing two subsequent requests could end up on different
+// connections. It's somewhat harmless but enough tests assume it's
+// not true in order to test other things that it's worth fixing.
+// Plus it's nice to be consistent and not have timing-dependent
+// behavior.
+func TestTransportReuseConnEmptyResponseBody(t *testing.T) {
+	defer afterTest(t)
+	cst := newClientServerTest(t, h1Mode, HandlerFunc(func(w ResponseWriter, r *Request) {
+		w.Header().Set("X-Addr", r.RemoteAddr)
+		// Empty response body.
+	}))
+	defer cst.close()
+	n := 100
+	if testing.Short() {
+		n = 10
+	}
+	var firstAddr string
+	for i := 0; i < n; i++ {
+		res, err := cst.c.Get(cst.ts.URL)
+		if err != nil {
+			log.Fatal(err)
+		}
+		addr := res.Header.Get("X-Addr")
+		if i == 0 {
+			firstAddr = addr
+		} else if addr != firstAddr {
+			t.Fatalf("On request %d, addr %q != original addr %q", i+1, addr, firstAddr)
+		}
+		res.Body.Close()
+	}
+}
+
+// Issue 13839
+func TestNoCrashReturningTransportAltConn(t *testing.T) {
+	cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey)
+	if err != nil {
+		t.Fatal(err)
+	}
+	ln := newLocalListener(t)
+	defer ln.Close()
+
+	handledPendingDial := make(chan bool, 1)
+	SetPendingDialHooks(nil, func() { handledPendingDial <- true })
+	defer SetPendingDialHooks(nil, nil)
+
+	testDone := make(chan struct{})
+	defer close(testDone)
+	go func() {
+		tln := tls.NewListener(ln, &tls.Config{
+			NextProtos:   []string{"foo"},
+			Certificates: []tls.Certificate{cert},
+		})
+		sc, err := tln.Accept()
+		if err != nil {
+			t.Error(err)
+			return
+		}
+		if err := sc.(*tls.Conn).Handshake(); err != nil {
+			t.Error(err)
+			return
+		}
+		<-testDone
+		sc.Close()
+	}()
+
+	addr := ln.Addr().String()
+
+	req, _ := NewRequest("GET", "https://fake.tld/", nil)
+	cancel := make(chan struct{})
+	req.Cancel = cancel
+
+	doReturned := make(chan bool, 1)
+	madeRoundTripper := make(chan bool, 1)
+
+	tr := &Transport{
+		DisableKeepAlives: true,
+		TLSNextProto: map[string]func(string, *tls.Conn) RoundTripper{
+			"foo": func(authority string, c *tls.Conn) RoundTripper {
+				madeRoundTripper <- true
+				return funcRoundTripper(func() {
+					t.Error("foo RoundTripper should not be called")
+				})
+			},
+		},
+		Dial: func(_, _ string) (net.Conn, error) {
+			panic("shouldn't be called")
+		},
+		DialTLS: func(_, _ string) (net.Conn, error) {
+			tc, err := tls.Dial("tcp", addr, &tls.Config{
+				InsecureSkipVerify: true,
+				NextProtos:         []string{"foo"},
+			})
+			if err != nil {
+				return nil, err
+			}
+			if err := tc.Handshake(); err != nil {
+				return nil, err
+			}
+			close(cancel)
+			<-doReturned
+			return tc, nil
+		},
+	}
+	c := &Client{Transport: tr}
+
+	_, err = c.Do(req)
+	if ue, ok := err.(*url.Error); !ok || ue.Err != ExportErrRequestCanceledConn {
+		t.Fatalf("Do error = %v; want url.Error with errRequestCanceledConn", err)
+	}
+
+	doReturned <- true
+	<-madeRoundTripper
+	<-handledPendingDial
+}
+
+var errFakeRoundTrip = errors.New("fake roundtrip")
+
+type funcRoundTripper func()
+
+func (fn funcRoundTripper) RoundTrip(*Request) (*Response, error) {
+	fn()
+	return nil, errFakeRoundTrip
+}
+
 func wantBody(res *Response, err error, want string) error {
 	if err != nil {
 		return err
diff --git a/src/net/http/triv.go b/src/net/http/triv.go
index 232d650..cfbc577 100644
--- a/src/net/http/triv.go
+++ b/src/net/http/triv.go
@@ -134,8 +134,5 @@ func main() {
 	http.HandleFunc("/args", ArgServer)
 	http.HandleFunc("/go/hello", HelloServer)
 	http.HandleFunc("/date", DateServer)
-	err := http.ListenAndServe(":12345", nil)
-	if err != nil {
-		log.Panicln("ListenAndServe:", err)
-	}
+	log.Fatal(http.ListenAndServe(":12345", nil))
 }
diff --git a/src/net/interface_test.go b/src/net/interface_test.go
index 567d18d..7bdd924 100644
--- a/src/net/interface_test.go
+++ b/src/net/interface_test.go
@@ -185,21 +185,50 @@ func testAddrs(t *testing.T, ifat []Addr) (naf4, naf6 int) {
 				t.Errorf("unexpected value: %#v", ifa)
 				continue
 			}
+			if len(ifa.IP) != IPv6len {
+				t.Errorf("should be internal representation either IPv6 or IPv6 IPv4-mapped address: %#v", ifa)
+				continue
+			}
 			prefixLen, maxPrefixLen := ifa.Mask.Size()
 			if ifa.IP.To4() != nil {
 				if 0 >= prefixLen || prefixLen > 8*IPv4len || maxPrefixLen != 8*IPv4len {
-					t.Errorf("unexpected prefix length: %v/%v", prefixLen, maxPrefixLen)
+					t.Errorf("unexpected prefix length: %d/%d", prefixLen, maxPrefixLen)
+					continue
+				}
+				if ifa.IP.IsLoopback() && (prefixLen != 8 && prefixLen != 8*IPv4len) { // see RFC 1122
+					t.Errorf("unexpected prefix length for IPv4 loopback: %d/%d", prefixLen, maxPrefixLen)
 					continue
 				}
 				naf4++
-			} else if ifa.IP.To16() != nil {
+			}
+			if ifa.IP.To16() != nil && ifa.IP.To4() == nil {
 				if 0 >= prefixLen || prefixLen > 8*IPv6len || maxPrefixLen != 8*IPv6len {
-					t.Errorf("unexpected prefix length: %v/%v", prefixLen, maxPrefixLen)
+					t.Errorf("unexpected prefix length: %d/%d", prefixLen, maxPrefixLen)
+					continue
+				}
+				if ifa.IP.IsLoopback() && prefixLen != 8*IPv6len { // see RFC 4291
+					t.Errorf("unexpected prefix length for IPv6 loopback: %d/%d", prefixLen, maxPrefixLen)
 					continue
 				}
 				naf6++
 			}
 			t.Logf("interface address %q", ifa.String())
+		case *IPAddr:
+			if ifa == nil || ifa.IP == nil || ifa.IP.IsUnspecified() || ifa.IP.IsMulticast() {
+				t.Errorf("unexpected value: %#v", ifa)
+				continue
+			}
+			if len(ifa.IP) != IPv6len {
+				t.Errorf("should be internal representation either IPv6 or IPv6 IPv4-mapped address: %#v", ifa)
+				continue
+			}
+			if ifa.IP.To4() != nil {
+				naf4++
+			}
+			if ifa.IP.To16() != nil && ifa.IP.To4() == nil {
+				naf6++
+			}
+			t.Logf("interface address %s", ifa.String())
 		default:
 			t.Errorf("unexpected type: %T", ifa)
 		}
@@ -212,12 +241,17 @@ func testMulticastAddrs(t *testing.T, ifmat []Addr) (nmaf4, nmaf6 int) {
 		switch ifma := ifma.(type) {
 		case *IPAddr:
 			if ifma == nil || ifma.IP == nil || ifma.IP.IsUnspecified() || !ifma.IP.IsMulticast() {
-				t.Errorf("unexpected value: %#v", ifma)
+				t.Errorf("unexpected value: %+v", ifma)
+				continue
+			}
+			if len(ifma.IP) != IPv6len {
+				t.Errorf("should be internal representation either IPv6 or IPv6 IPv4-mapped address: %#v", ifma)
 				continue
 			}
 			if ifma.IP.To4() != nil {
 				nmaf4++
-			} else if ifma.IP.To16() != nil {
+			}
+			if ifma.IP.To16() != nil && ifma.IP.To4() == nil {
 				nmaf6++
 			}
 			t.Logf("joined group address %q", ifma.String())
diff --git a/src/net/interface_windows.go b/src/net/interface_windows.go
index 8cb9d76..4d6bcdf 100644
--- a/src/net/interface_windows.go
+++ b/src/net/interface_windows.go
@@ -11,131 +11,103 @@ import (
 	"unsafe"
 )
 
-func getAdapters() (*windows.IpAdapterAddresses, error) {
-	block := uint32(unsafe.Sizeof(windows.IpAdapterAddresses{}))
+// supportsVistaIP reports whether the platform implements new IP
+// stack and ABIs supported on Windows Vista and above.
+var supportsVistaIP bool
 
-	// pre-allocate a 15KB working buffer pointed to by the AdapterAddresses
-	// parameter.
-	// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365915(v=vs.85).aspx
-	size := uint32(15000)
-
-	var addrs []windows.IpAdapterAddresses
-	for {
-		addrs = make([]windows.IpAdapterAddresses, size/block+1)
-		err := windows.GetAdaptersAddresses(syscall.AF_UNSPEC, windows.GAA_FLAG_INCLUDE_PREFIX, 0, &addrs[0], &size)
-		if err == nil {
-			break
-		}
-		if err.(syscall.Errno) != syscall.ERROR_BUFFER_OVERFLOW {
-			return nil, os.NewSyscallError("getadaptersaddresses", err)
-		}
-	}
-	return &addrs[0], nil
+func init() {
+	supportsVistaIP = probeWindowsIPStack()
 }
 
-func getInterfaceInfos() ([]syscall.InterfaceInfo, error) {
-	s, err := sysSocket(syscall.AF_INET, syscall.SOCK_DGRAM, syscall.IPPROTO_UDP)
-	if err != nil {
-		return nil, err
-	}
-	defer closeFunc(s)
-
-	iia := [20]syscall.InterfaceInfo{}
-	ret := uint32(0)
-	size := uint32(unsafe.Sizeof(iia))
-	err = syscall.WSAIoctl(s, syscall.SIO_GET_INTERFACE_LIST, nil, 0, (*byte)(unsafe.Pointer(&iia[0])), size, &ret, nil, 0)
+func probeWindowsIPStack() (supportsVistaIP bool) {
+	v, err := syscall.GetVersion()
 	if err != nil {
-		return nil, os.NewSyscallError("wsaioctl", err)
+		return true // Windows 10 and above will deprecate this API
 	}
-	iilen := ret / uint32(unsafe.Sizeof(iia[0]))
-	return iia[:iilen], nil
-}
-
-func bytesEqualIP(a []byte, b []int8) bool {
-	for i := 0; i < len(a); i++ {
-		if a[i] != byte(b[i]) {
-			return false
-		}
+	if byte(v) < 6 { // major version of Windows Vista is 6
+		return false
 	}
 	return true
 }
 
-func findInterfaceInfo(iis []syscall.InterfaceInfo, paddr *windows.IpAdapterAddresses) *syscall.InterfaceInfo {
-	for _, ii := range iis {
-		iaddr := (*syscall.RawSockaddr)(unsafe.Pointer(&ii.Address))
-		puni := paddr.FirstUnicastAddress
-		for ; puni != nil; puni = puni.Next {
-			if iaddr.Family == puni.Address.Sockaddr.Addr.Family {
-				switch iaddr.Family {
-				case syscall.AF_INET:
-					a := (*syscall.RawSockaddrInet4)(unsafe.Pointer(&ii.Address)).Addr
-					if bytesEqualIP(a[:], puni.Address.Sockaddr.Addr.Data[2:]) {
-						return &ii
-					}
-				case syscall.AF_INET6:
-					a := (*syscall.RawSockaddrInet6)(unsafe.Pointer(&ii.Address)).Addr
-					if bytesEqualIP(a[:], puni.Address.Sockaddr.Addr.Data[2:]) {
-						return &ii
-					}
-				default:
-					continue
-				}
+// adapterAddresses returns a list of IP adapter and address
+// structures. The structure contains an IP adapter and flattened
+// multiple IP addresses including unicast, anycast and multicast
+// addresses.
+func adapterAddresses() ([]*windows.IpAdapterAddresses, error) {
+	var b []byte
+	l := uint32(15000) // recommended initial size
+	for {
+		b = make([]byte, l)
+		err := windows.GetAdaptersAddresses(syscall.AF_UNSPEC, windows.GAA_FLAG_INCLUDE_PREFIX, 0, (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])), &l)
+		if err == nil {
+			if l == 0 {
+				return nil, nil
 			}
+			break
 		}
+		if err.(syscall.Errno) != syscall.ERROR_BUFFER_OVERFLOW {
+			return nil, os.NewSyscallError("getadaptersaddresses", err)
+		}
+		if l <= uint32(len(b)) {
+			return nil, os.NewSyscallError("getadaptersaddresses", err)
+		}
+	}
+	var aas []*windows.IpAdapterAddresses
+	for aa := (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])); aa != nil; aa = aa.Next {
+		aas = append(aas, aa)
 	}
-	return nil
+	return aas, nil
 }
 
 // If the ifindex is zero, interfaceTable returns mappings of all
 // network interfaces.  Otherwise it returns a mapping of a specific
 // interface.
 func interfaceTable(ifindex int) ([]Interface, error) {
-	paddr, err := getAdapters()
-	if err != nil {
-		return nil, err
-	}
-
-	iis, err := getInterfaceInfos()
+	aas, err := adapterAddresses()
 	if err != nil {
 		return nil, err
 	}
-
 	var ift []Interface
-	for ; paddr != nil; paddr = paddr.Next {
-		index := paddr.IfIndex
-		if paddr.Ipv6IfIndex != 0 {
-			index = paddr.Ipv6IfIndex
+	for _, aa := range aas {
+		index := aa.IfIndex
+		if index == 0 { // ipv6IfIndex is a substitute for ifIndex
+			index = aa.Ipv6IfIndex
 		}
 		if ifindex == 0 || ifindex == int(index) {
-			ii := findInterfaceInfo(iis, paddr)
-			if ii == nil {
-				continue
-			}
-			var flags Flags
-			if paddr.Flags&windows.IfOperStatusUp != 0 {
-				flags |= FlagUp
-			}
-			if paddr.IfType&windows.IF_TYPE_SOFTWARE_LOOPBACK != 0 {
-				flags |= FlagLoopback
+			ifi := Interface{
+				Index: int(index),
+				Name:  syscall.UTF16ToString((*(*[10000]uint16)(unsafe.Pointer(aa.FriendlyName)))[:]),
 			}
-			if ii.Flags&syscall.IFF_BROADCAST != 0 {
-				flags |= FlagBroadcast
+			if aa.OperStatus == windows.IfOperStatusUp {
+				ifi.Flags |= FlagUp
 			}
-			if ii.Flags&syscall.IFF_POINTTOPOINT != 0 {
-				flags |= FlagPointToPoint
+			// For now we need to infer link-layer service
+			// capabilities from media types.
+			// We will be able to use
+			// MIB_IF_ROW2.AccessType once we drop support
+			// for Windows XP.
+			switch aa.IfType {
+			case windows.IF_TYPE_ETHERNET_CSMACD, windows.IF_TYPE_ISO88025_TOKENRING, windows.IF_TYPE_IEEE80211, windows.IF_TYPE_IEEE1394:
+				ifi.Flags |= FlagBroadcast | FlagMulticast
+			case windows.IF_TYPE_PPP, windows.IF_TYPE_TUNNEL:
+				ifi.Flags |= FlagPointToPoint | FlagMulticast
+			case windows.IF_TYPE_SOFTWARE_LOOPBACK:
+				ifi.Flags |= FlagLoopback | FlagMulticast
+			case windows.IF_TYPE_ATM:
+				ifi.Flags |= FlagBroadcast | FlagPointToPoint | FlagMulticast // assume all services available; LANE, point-to-point and point-to-multipoint
 			}
-			if ii.Flags&syscall.IFF_MULTICAST != 0 {
-				flags |= FlagMulticast
+			if aa.Mtu == 0xffffffff {
+				ifi.MTU = -1
+			} else {
+				ifi.MTU = int(aa.Mtu)
 			}
-			ifi := Interface{
-				Index:        int(index),
-				MTU:          int(paddr.Mtu),
-				Name:         syscall.UTF16ToString((*(*[10000]uint16)(unsafe.Pointer(paddr.FriendlyName)))[:]),
-				HardwareAddr: HardwareAddr(paddr.PhysicalAddress[:]),
-				Flags:        flags,
+			if aa.PhysicalAddressLength > 0 {
+				ifi.HardwareAddr = make(HardwareAddr, aa.PhysicalAddressLength)
+				copy(ifi.HardwareAddr, aa.PhysicalAddress[:])
 			}
 			ift = append(ift, ifi)
-			if ifindex == int(ifi.Index) {
+			if ifindex == ifi.Index {
 				break
 			}
 		}
@@ -147,86 +119,150 @@ func interfaceTable(ifindex int) ([]Interface, error) {
 // network interfaces.  Otherwise it returns addresses for a specific
 // interface.
 func interfaceAddrTable(ifi *Interface) ([]Addr, error) {
-	paddr, err := getAdapters()
+	aas, err := adapterAddresses()
 	if err != nil {
 		return nil, err
 	}
-
 	var ifat []Addr
-	for ; paddr != nil; paddr = paddr.Next {
-		index := paddr.IfIndex
-		if paddr.Ipv6IfIndex != 0 {
-			index = paddr.Ipv6IfIndex
+	for _, aa := range aas {
+		index := aa.IfIndex
+		if index == 0 { // ipv6IfIndex is a substitute for ifIndex
+			index = aa.Ipv6IfIndex
+		}
+		var pfx4, pfx6 []IPNet
+		if !supportsVistaIP {
+			pfx4, pfx6, err = addrPrefixTable(aa)
+			if err != nil {
+				return nil, err
+			}
 		}
 		if ifi == nil || ifi.Index == int(index) {
-			puni := paddr.FirstUnicastAddress
-			for ; puni != nil; puni = puni.Next {
-				if sa, err := puni.Address.Sockaddr.Sockaddr(); err == nil {
-					switch sav := sa.(type) {
-					case *syscall.SockaddrInet4:
-						ifa := &IPNet{IP: make(IP, IPv4len), Mask: CIDRMask(int(puni.Address.SockaddrLength), 8*IPv4len)}
-						copy(ifa.IP, sav.Addr[:])
-						ifat = append(ifat, ifa)
-					case *syscall.SockaddrInet6:
-						ifa := &IPNet{IP: make(IP, IPv6len), Mask: CIDRMask(int(puni.Address.SockaddrLength), 8*IPv6len)}
-						copy(ifa.IP, sav.Addr[:])
-						ifat = append(ifat, ifa)
+			for puni := aa.FirstUnicastAddress; puni != nil; puni = puni.Next {
+				sa, err := puni.Address.Sockaddr.Sockaddr()
+				if err != nil {
+					return nil, os.NewSyscallError("sockaddr", err)
+				}
+				var l int
+				switch sa := sa.(type) {
+				case *syscall.SockaddrInet4:
+					if supportsVistaIP {
+						l = int(puni.OnLinkPrefixLength)
+					} else {
+						l = addrPrefixLen(pfx4, IP(sa.Addr[:]))
 					}
+					ifat = append(ifat, &IPNet{IP: IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3]), Mask: CIDRMask(l, 8*IPv4len)})
+				case *syscall.SockaddrInet6:
+					if supportsVistaIP {
+						l = int(puni.OnLinkPrefixLength)
+					} else {
+						l = addrPrefixLen(pfx6, IP(sa.Addr[:]))
+					}
+					ifa := &IPNet{IP: make(IP, IPv6len), Mask: CIDRMask(l, 8*IPv6len)}
+					copy(ifa.IP, sa.Addr[:])
+					ifat = append(ifat, ifa)
 				}
 			}
-			pany := paddr.FirstAnycastAddress
-			for ; pany != nil; pany = pany.Next {
-				if sa, err := pany.Address.Sockaddr.Sockaddr(); err == nil {
-					switch sav := sa.(type) {
-					case *syscall.SockaddrInet4:
-						ifa := &IPNet{IP: make(IP, IPv4len), Mask: CIDRMask(int(pany.Address.SockaddrLength), 8*IPv4len)}
-						copy(ifa.IP, sav.Addr[:])
-						ifat = append(ifat, ifa)
-					case *syscall.SockaddrInet6:
-						ifa := &IPNet{IP: make(IP, IPv6len), Mask: CIDRMask(int(pany.Address.SockaddrLength), 8*IPv6len)}
-						copy(ifa.IP, sav.Addr[:])
-						ifat = append(ifat, ifa)
-					}
+			for pany := aa.FirstAnycastAddress; pany != nil; pany = pany.Next {
+				sa, err := pany.Address.Sockaddr.Sockaddr()
+				if err != nil {
+					return nil, os.NewSyscallError("sockaddr", err)
+				}
+				switch sa := sa.(type) {
+				case *syscall.SockaddrInet4:
+					ifat = append(ifat, &IPAddr{IP: IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])})
+				case *syscall.SockaddrInet6:
+					ifa := &IPAddr{IP: make(IP, IPv6len)}
+					copy(ifa.IP, sa.Addr[:])
+					ifat = append(ifat, ifa)
 				}
 			}
 		}
 	}
-
 	return ifat, nil
 }
 
+func addrPrefixTable(aa *windows.IpAdapterAddresses) (pfx4, pfx6 []IPNet, err error) {
+	for p := aa.FirstPrefix; p != nil; p = p.Next {
+		sa, err := p.Address.Sockaddr.Sockaddr()
+		if err != nil {
+			return nil, nil, os.NewSyscallError("sockaddr", err)
+		}
+		switch sa := sa.(type) {
+		case *syscall.SockaddrInet4:
+			pfx := IPNet{IP: IP(sa.Addr[:]), Mask: CIDRMask(int(p.PrefixLength), 8*IPv4len)}
+			pfx4 = append(pfx4, pfx)
+		case *syscall.SockaddrInet6:
+			pfx := IPNet{IP: IP(sa.Addr[:]), Mask: CIDRMask(int(p.PrefixLength), 8*IPv6len)}
+			pfx6 = append(pfx6, pfx)
+		}
+	}
+	return
+}
+
+// addrPrefixLen returns an appropriate prefix length in bits for ip
+// from pfxs. It returns 32 or 128 when no appropriate on-link address
+// prefix found.
+//
+// NOTE: This is pretty naive implementation that contains many
+// allocations and non-effective linear search, and should not be used
+// freely.
+func addrPrefixLen(pfxs []IPNet, ip IP) int {
+	var l int
+	var cand *IPNet
+	for i := range pfxs {
+		if !pfxs[i].Contains(ip) {
+			continue
+		}
+		if cand == nil {
+			l, _ = pfxs[i].Mask.Size()
+			cand = &pfxs[i]
+			continue
+		}
+		m, _ := pfxs[i].Mask.Size()
+		if m > l {
+			l = m
+			cand = &pfxs[i]
+			continue
+		}
+	}
+	if l > 0 {
+		return l
+	}
+	if ip.To4() != nil {
+		return 8 * IPv4len
+	}
+	return 8 * IPv6len
+}
+
 // interfaceMulticastAddrTable returns addresses for a specific
 // interface.
 func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) {
-	paddr, err := getAdapters()
+	aas, err := adapterAddresses()
 	if err != nil {
 		return nil, err
 	}
-
 	var ifat []Addr
-	for ; paddr != nil; paddr = paddr.Next {
-		index := paddr.IfIndex
-		if paddr.Ipv6IfIndex != 0 {
-			index = paddr.Ipv6IfIndex
+	for _, aa := range aas {
+		index := aa.IfIndex
+		if index == 0 { // ipv6IfIndex is a substitute for ifIndex
+			index = aa.Ipv6IfIndex
 		}
 		if ifi == nil || ifi.Index == int(index) {
-			pmul := paddr.FirstMulticastAddress
-			for ; pmul != nil; pmul = pmul.Next {
-				if sa, err := pmul.Address.Sockaddr.Sockaddr(); err == nil {
-					switch sav := sa.(type) {
-					case *syscall.SockaddrInet4:
-						ifa := &IPAddr{IP: make(IP, IPv4len)}
-						copy(ifa.IP, sav.Addr[:])
-						ifat = append(ifat, ifa)
-					case *syscall.SockaddrInet6:
-						ifa := &IPAddr{IP: make(IP, IPv6len)}
-						copy(ifa.IP, sav.Addr[:])
-						ifat = append(ifat, ifa)
-					}
+			for pmul := aa.FirstMulticastAddress; pmul != nil; pmul = pmul.Next {
+				sa, err := pmul.Address.Sockaddr.Sockaddr()
+				if err != nil {
+					return nil, os.NewSyscallError("sockaddr", err)
+				}
+				switch sa := sa.(type) {
+				case *syscall.SockaddrInet4:
+					ifat = append(ifat, &IPAddr{IP: IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3])})
+				case *syscall.SockaddrInet6:
+					ifa := &IPAddr{IP: make(IP, IPv6len)}
+					copy(ifa.IP, sa.Addr[:])
+					ifat = append(ifat, ifa)
 				}
 			}
 		}
 	}
-
 	return ifat, nil
 }
diff --git a/src/net/interface_windows_test.go b/src/net/interface_windows_test.go
new file mode 100644
index 0000000..03f9168
--- /dev/null
+++ b/src/net/interface_windows_test.go
@@ -0,0 +1,132 @@
+// Copyright 2015 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 net
+
+import (
+	"bytes"
+	"internal/syscall/windows"
+	"sort"
+	"testing"
+)
+
+func TestWindowsInterfaces(t *testing.T) {
+	aas, err := adapterAddresses()
+	if err != nil {
+		t.Fatal(err)
+	}
+	ift, err := Interfaces()
+	if err != nil {
+		t.Fatal(err)
+	}
+	for i, ifi := range ift {
+		aa := aas[i]
+		if len(ifi.HardwareAddr) != int(aa.PhysicalAddressLength) {
+			t.Errorf("got %d; want %d", len(ifi.HardwareAddr), aa.PhysicalAddressLength)
+		}
+		if ifi.MTU > 0x7fffffff {
+			t.Errorf("%s: got %d; want less than or equal to 1<<31 - 1", ifi.Name, ifi.MTU)
+		}
+		if ifi.Flags&FlagUp != 0 && aa.OperStatus != windows.IfOperStatusUp {
+			t.Errorf("%s: got %v; should not include FlagUp", ifi.Name, ifi.Flags)
+		}
+		if ifi.Flags&FlagLoopback != 0 && aa.IfType != windows.IF_TYPE_SOFTWARE_LOOPBACK {
+			t.Errorf("%s: got %v; should not include FlagLoopback", ifi.Name, ifi.Flags)
+		}
+		if _, _, err := addrPrefixTable(aa); err != nil {
+			t.Errorf("%s: %v", ifi.Name, err)
+		}
+	}
+}
+
+type byAddrLen []IPNet
+
+func (ps byAddrLen) Len() int { return len(ps) }
+
+func (ps byAddrLen) Less(i, j int) bool {
+	if n := bytes.Compare(ps[i].IP, ps[j].IP); n != 0 {
+		return n < 0
+	}
+	if n := bytes.Compare(ps[i].Mask, ps[j].Mask); n != 0 {
+		return n < 0
+	}
+	return false
+}
+
+func (ps byAddrLen) Swap(i, j int) { ps[i], ps[j] = ps[j], ps[i] }
+
+var windowsAddrPrefixLenTests = []struct {
+	pfxs []IPNet
+	ip   IP
+	out  int
+}{
+	{
+		[]IPNet{
+			{IP: IPv4(172, 16, 0, 0), Mask: IPv4Mask(255, 255, 0, 0)},
+			{IP: IPv4(192, 168, 0, 0), Mask: IPv4Mask(255, 255, 255, 0)},
+			{IP: IPv4(192, 168, 0, 0), Mask: IPv4Mask(255, 255, 255, 128)},
+			{IP: IPv4(192, 168, 0, 0), Mask: IPv4Mask(255, 255, 255, 192)},
+		},
+		IPv4(192, 168, 0, 1),
+		26,
+	},
+	{
+		[]IPNet{
+			{IP: ParseIP("2001:db8::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff0"))},
+			{IP: ParseIP("2001:db8::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff8"))},
+			{IP: ParseIP("2001:db8::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc"))},
+		},
+		ParseIP("2001:db8::1"),
+		126,
+	},
+
+	// Fallback cases. It may happen on Windows XP or 2003 server.
+	{
+		[]IPNet{
+			{IP: IPv4(127, 0, 0, 0).To4(), Mask: IPv4Mask(255, 0, 0, 0)},
+			{IP: IPv4(10, 0, 0, 0).To4(), Mask: IPv4Mask(255, 0, 0, 0)},
+			{IP: IPv4(172, 16, 0, 0).To4(), Mask: IPv4Mask(255, 255, 0, 0)},
+			{IP: IPv4(192, 168, 255, 0), Mask: IPv4Mask(255, 255, 255, 0)},
+			{IP: IPv4zero, Mask: IPv4Mask(0, 0, 0, 0)},
+		},
+		IPv4(192, 168, 0, 1),
+		8 * IPv4len,
+	},
+	{
+		nil,
+		IPv4(192, 168, 0, 1),
+		8 * IPv4len,
+	},
+	{
+		[]IPNet{
+			{IP: IPv6loopback, Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"))},
+			{IP: ParseIP("2001:db8:1::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff0"))},
+			{IP: ParseIP("2001:db8:2::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff8"))},
+			{IP: ParseIP("2001:db8:3::"), Mask: IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc"))},
+			{IP: IPv6unspecified, Mask: IPMask(ParseIP("::"))},
+		},
+		ParseIP("2001:db8::1"),
+		8 * IPv6len,
+	},
+	{
+		nil,
+		ParseIP("2001:db8::1"),
+		8 * IPv6len,
+	},
+}
+
+func TestWindowsAddrPrefixLen(t *testing.T) {
+	for i, tt := range windowsAddrPrefixLenTests {
+		sort.Sort(byAddrLen(tt.pfxs))
+		l := addrPrefixLen(tt.pfxs, tt.ip)
+		if l != tt.out {
+			t.Errorf("#%d: got %d; want %d", i, l, tt.out)
+		}
+		sort.Sort(sort.Reverse(byAddrLen(tt.pfxs)))
+		l = addrPrefixLen(tt.pfxs, tt.ip)
+		if l != tt.out {
+			t.Errorf("#%d: got %d; want %d", i, l, tt.out)
+		}
+	}
+}
diff --git a/src/net/internal/socktest/switch.go b/src/net/internal/socktest/switch.go
index 4e38c7a..8bef06b 100644
--- a/src/net/internal/socktest/switch.go
+++ b/src/net/internal/socktest/switch.go
@@ -77,7 +77,7 @@ type Status struct {
 }
 
 func (so Status) String() string {
-	return fmt.Sprintf("(%s, %s, %s): syscallerr=%v, socketerr=%v", familyString(so.Cookie.Family()), typeString(so.Cookie.Type()), protocolString(so.Cookie.Protocol()), so.Err, so.SocketErr)
+	return fmt.Sprintf("(%s, %s, %s): syscallerr=%v socketerr=%v", familyString(so.Cookie.Family()), typeString(so.Cookie.Type()), protocolString(so.Cookie.Protocol()), so.Err, so.SocketErr)
 }
 
 // A Stat represents a per-cookie socket statistics.
@@ -100,7 +100,7 @@ type Stat struct {
 }
 
 func (st Stat) String() string {
-	return fmt.Sprintf("(%s, %s, %s): opened=%d, connected=%d, listened=%d, accepted=%d, closed=%d, openfailed=%d, connectfailed=%d, listenfailed=%d, acceptfailed=%d, closefailed=%d", familyString(st.Family), typeString(st.Type), protocolString(st.Protocol), st.Opened, st.Connected, st.Listened, st.Accepted, st.Closed, st.OpenFailed, st.ConnectFailed, st.ListenFailed, st.AcceptFailed, st.CloseFailed)
+	return fmt.Sprintf("(%s, %s, %s): opened=%d connected=%d listened=%d accepted=%d closed=%d openfailed=%d connectfailed=%d listenfailed=%d acceptfailed=%d closefailed=%d", familyString(st.Family), typeString(st.Type), protocolString(st.Protocol), st.Opened, st.Connected, st.Listened, st.Accepted, st.Closed, st.OpenFailed, st.ConnectFailed, st.ListenFailed, st.AcceptFailed, st.CloseFailed)
 }
 
 type stats map[Cookie]*Stat
diff --git a/src/net/iprawsock_posix.go b/src/net/iprawsock_posix.go
index 9417606..93fee3e 100644
--- a/src/net/iprawsock_posix.go
+++ b/src/net/iprawsock_posix.go
@@ -220,7 +220,7 @@ func dialIP(netProto string, laddr, raddr *IPAddr, deadline time.Time) (*IPConn,
 	if raddr == nil {
 		return nil, &OpError{Op: "dial", Net: netProto, Source: laddr.opAddr(), Addr: nil, Err: errMissingAddress}
 	}
-	fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_RAW, proto, "dial")
+	fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_RAW, proto, "dial", noCancel)
 	if err != nil {
 		return nil, &OpError{Op: "dial", Net: netProto, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
 	}
@@ -241,7 +241,7 @@ func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
 	default:
 		return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(netProto)}
 	}
-	fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_RAW, proto, "listen")
+	fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_RAW, proto, "listen", noCancel)
 	if err != nil {
 		return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr.opAddr(), Err: err}
 	}
diff --git a/src/net/ipsock.go b/src/net/ipsock.go
index 6e75c33..55f697f 100644
--- a/src/net/ipsock.go
+++ b/src/net/ipsock.go
@@ -213,7 +213,7 @@ func internetAddrList(net, addr string, deadline time.Time) (addrList, error) {
 			if host, port, err = SplitHostPort(addr); err != nil {
 				return nil, err
 			}
-			if portnum, err = parsePort(net, port); err != nil {
+			if portnum, err = LookupPort(net, port); err != nil {
 				return nil, err
 			}
 		}
diff --git a/src/net/ipsock_posix.go b/src/net/ipsock_posix.go
index 83eaf85..2bddd46 100644
--- a/src/net/ipsock_posix.go
+++ b/src/net/ipsock_posix.go
@@ -101,10 +101,11 @@ func probeIPv6Stack() (supportsIPv6, supportsIPv4map bool) {
 //
 //	1. A wild-wild listen, "tcp" + ""
 //	If the platform supports both IPv6 and IPv6 IPv4-mapping
-//	capabilities, we assume that the user want to listen on
-//	both IPv4 and IPv6 wildcard address over an AF_INET6
-//	socket with IPV6_V6ONLY=0.  Otherwise we prefer an IPv4
-//	wildcard address listen over an AF_INET socket.
+//	capabilities, or does not support IPv4, we assume that
+//	the user wants to listen on both IPv4 and IPv6 wildcard
+//	addresses over an AF_INET6 socket with IPV6_V6ONLY=0.
+//	Otherwise we prefer an IPv4 wildcard address listen over
+//	an AF_INET socket.
 //
 //	2. A wild-ipv4wild listen, "tcp" + "0.0.0.0"
 //	Same as 1.
@@ -137,7 +138,7 @@ func favoriteAddrFamily(net string, laddr, raddr sockaddr, mode string) (family
 	}
 
 	if mode == "listen" && (laddr == nil || laddr.isWildcard()) {
-		if supportsIPv4map {
+		if supportsIPv4map || !supportsIPv4 {
 			return syscall.AF_INET6, false
 		}
 		if laddr == nil {
@@ -155,9 +156,9 @@ func favoriteAddrFamily(net string, laddr, raddr sockaddr, mode string) (family
 
 // Internet sockets (TCP, UDP, IP)
 
-func internetSocket(net string, laddr, raddr sockaddr, deadline time.Time, sotype, proto int, mode string) (fd *netFD, err error) {
+func internetSocket(net string, laddr, raddr sockaddr, deadline time.Time, sotype, proto int, mode string, cancel <-chan struct{}) (fd *netFD, err error) {
 	family, ipv6only := favoriteAddrFamily(net, laddr, raddr, mode)
-	return socket(net, family, sotype, proto, ipv6only, laddr, raddr, deadline)
+	return socket(net, family, sotype, proto, ipv6only, laddr, raddr, deadline, cancel)
 }
 
 func ipToSockaddr(family int, ip IP, port int, zone string) (syscall.Sockaddr, error) {
diff --git a/src/net/listen_test.go b/src/net/listen_test.go
index d5627f2..51ffe67 100644
--- a/src/net/listen_test.go
+++ b/src/net/listen_test.go
@@ -542,7 +542,7 @@ func TestIPv4MulticastListener(t *testing.T) {
 		// routing stuff for finding out an appropriate
 		// nexthop containing both network and link layer
 		// adjacencies.
-		if ifi == nil && !*testExternal {
+		if ifi == nil && (testing.Short() || !*testExternal) {
 			continue
 		}
 		for _, tt := range ipv4MulticastListenerTests {
@@ -618,7 +618,7 @@ func TestIPv6MulticastListener(t *testing.T) {
 		// routing stuff for finding out an appropriate
 		// nexthop containing both network and link layer
 		// adjacencies.
-		if ifi == nil && (!*testExternal || !*testIPv6) {
+		if ifi == nil && (testing.Short() || !*testExternal || !*testIPv6) {
 			continue
 		}
 		for _, tt := range ipv6MulticastListenerTests {
diff --git a/src/net/lookup.go b/src/net/lookup.go
index 9008322..7aa111b 100644
--- a/src/net/lookup.go
+++ b/src/net/lookup.go
@@ -123,10 +123,22 @@ func lookupIPDeadline(host string, deadline time.Time) (addrs []IPAddr, err erro
 
 // LookupPort looks up the port for the given network and service.
 func LookupPort(network, service string) (port int, err error) {
-	if n, i, ok := dtoi(service, 0); ok && i == len(service) {
-		return n, nil
+	if service == "" {
+		// Lock in the legacy behavior that an empty string
+		// means port 0. See Issue 13610.
+		return 0, nil
 	}
-	return lookupPort(network, service)
+	port, _, ok := dtoi(service, 0)
+	if !ok && port != big && port != -big {
+		port, err = lookupPort(network, service)
+		if err != nil {
+			return 0, err
+		}
+	}
+	if 0 > port || port > 65535 {
+		return 0, &AddrError{Err: "invalid port", Addr: service}
+	}
+	return port, nil
 }
 
 // LookupCNAME returns the canonical DNS host for the given name.
diff --git a/src/net/lookup_plan9.go b/src/net/lookup_plan9.go
index c627464..a331628 100644
--- a/src/net/lookup_plan9.go
+++ b/src/net/lookup_plan9.go
@@ -225,8 +225,8 @@ func lookupSRV(service, proto, name string) (cname string, addrs []*SRV, err err
 		if !(portOk && priorityOk && weightOk) {
 			continue
 		}
-		addrs = append(addrs, &SRV{f[5], uint16(port), uint16(priority), uint16(weight)})
-		cname = f[0]
+		addrs = append(addrs, &SRV{absDomainName([]byte(f[5])), uint16(port), uint16(priority), uint16(weight)})
+		cname = absDomainName([]byte(f[0]))
 	}
 	byPriorityWeight(addrs).sort()
 	return
@@ -243,7 +243,7 @@ func lookupMX(name string) (mx []*MX, err error) {
 			continue
 		}
 		if pref, _, ok := dtoi(f[2], 0); ok {
-			mx = append(mx, &MX{f[3], uint16(pref)})
+			mx = append(mx, &MX{absDomainName([]byte(f[3])), uint16(pref)})
 		}
 	}
 	byPref(mx).sort()
@@ -260,7 +260,7 @@ func lookupNS(name string) (ns []*NS, err error) {
 		if len(f) < 3 {
 			continue
 		}
-		ns = append(ns, &NS{f[2]})
+		ns = append(ns, &NS{absDomainName([]byte(f[2]))})
 	}
 	return
 }
@@ -272,7 +272,7 @@ func lookupTXT(name string) (txt []string, err error) {
 	}
 	for _, line := range lines {
 		if i := byteIndex(line, '\t'); i >= 0 {
-			txt = append(txt, line[i+1:])
+			txt = append(txt, absDomainName([]byte(line[i+1:])))
 		}
 	}
 	return
@@ -292,7 +292,7 @@ func lookupAddr(addr string) (name []string, err error) {
 		if len(f) < 3 {
 			continue
 		}
-		name = append(name, f[2])
+		name = append(name, absDomainName([]byte(f[2])))
 	}
 	return
 }
diff --git a/src/net/lookup_test.go b/src/net/lookup_test.go
index 86957b5..439496a 100644
--- a/src/net/lookup_test.go
+++ b/src/net/lookup_test.go
@@ -7,6 +7,8 @@ package net
 import (
 	"bytes"
 	"fmt"
+	"internal/testenv"
+	"runtime"
 	"strings"
 	"testing"
 	"time"
@@ -37,26 +39,26 @@ var lookupGoogleSRVTests = []struct {
 }{
 	{
 		"xmpp-server", "tcp", "google.com",
-		"google.com", "google.com",
+		"google.com.", "google.com.",
 	},
 	{
 		"xmpp-server", "tcp", "google.com.",
-		"google.com", "google.com",
+		"google.com.", "google.com.",
 	},
 
 	// non-standard back door
 	{
 		"", "", "_xmpp-server._tcp.google.com",
-		"google.com", "google.com",
+		"google.com.", "google.com.",
 	},
 	{
 		"", "", "_xmpp-server._tcp.google.com.",
-		"google.com", "google.com",
+		"google.com.", "google.com.",
 	},
 }
 
 func TestLookupGoogleSRV(t *testing.T) {
-	if testing.Short() || !*testExternal {
+	if testing.Short() && testenv.Builder() == "" || !*testExternal {
 		t.Skip("avoid external network")
 	}
 	if !supportsIPv4 || !*testIPv4 {
@@ -71,11 +73,11 @@ func TestLookupGoogleSRV(t *testing.T) {
 		if len(srvs) == 0 {
 			t.Error("got no record")
 		}
-		if !strings.HasSuffix(cname, tt.cname) && !strings.HasSuffix(cname, tt.cname+".") {
+		if !strings.HasSuffix(cname, tt.cname) {
 			t.Errorf("got %s; want %s", cname, tt.cname)
 		}
 		for _, srv := range srvs {
-			if !strings.HasSuffix(srv.Target, tt.target) && !strings.HasSuffix(srv.Target, tt.target+".") {
+			if !strings.HasSuffix(srv.Target, tt.target) {
 				t.Errorf("got %v; want a record containing %s", srv, tt.target)
 			}
 		}
@@ -85,12 +87,12 @@ func TestLookupGoogleSRV(t *testing.T) {
 var lookupGmailMXTests = []struct {
 	name, host string
 }{
-	{"gmail.com", "google.com"},
-	{"gmail.com.", "google.com"},
+	{"gmail.com", "google.com."},
+	{"gmail.com.", "google.com."},
 }
 
 func TestLookupGmailMX(t *testing.T) {
-	if testing.Short() || !*testExternal {
+	if testing.Short() && testenv.Builder() == "" || !*testExternal {
 		t.Skip("avoid external network")
 	}
 	if !supportsIPv4 || !*testIPv4 {
@@ -106,7 +108,7 @@ func TestLookupGmailMX(t *testing.T) {
 			t.Error("got no record")
 		}
 		for _, mx := range mxs {
-			if !strings.HasSuffix(mx.Host, tt.host) && !strings.HasSuffix(mx.Host, tt.host+".") {
+			if !strings.HasSuffix(mx.Host, tt.host) {
 				t.Errorf("got %v; want a record containing %s", mx, tt.host)
 			}
 		}
@@ -116,12 +118,12 @@ func TestLookupGmailMX(t *testing.T) {
 var lookupGmailNSTests = []struct {
 	name, host string
 }{
-	{"gmail.com", "google.com"},
-	{"gmail.com.", "google.com"},
+	{"gmail.com", "google.com."},
+	{"gmail.com.", "google.com."},
 }
 
 func TestLookupGmailNS(t *testing.T) {
-	if testing.Short() || !*testExternal {
+	if testing.Short() && testenv.Builder() == "" || !*testExternal {
 		t.Skip("avoid external network")
 	}
 	if !supportsIPv4 || !*testIPv4 {
@@ -137,7 +139,7 @@ func TestLookupGmailNS(t *testing.T) {
 			t.Error("got no record")
 		}
 		for _, ns := range nss {
-			if !strings.HasSuffix(ns.Host, tt.host) && !strings.HasSuffix(ns.Host, tt.host+".") {
+			if !strings.HasSuffix(ns.Host, tt.host) {
 				t.Errorf("got %v; want a record containing %s", ns, tt.host)
 			}
 		}
@@ -152,7 +154,7 @@ var lookupGmailTXTTests = []struct {
 }
 
 func TestLookupGmailTXT(t *testing.T) {
-	if testing.Short() || !*testExternal {
+	if testing.Short() && testenv.Builder() == "" || !*testExternal {
 		t.Skip("avoid external network")
 	}
 	if !supportsIPv4 || !*testIPv4 {
@@ -178,14 +180,15 @@ func TestLookupGmailTXT(t *testing.T) {
 var lookupGooglePublicDNSAddrTests = []struct {
 	addr, name string
 }{
-	{"8.8.8.8", ".google.com"},
-	{"8.8.4.4", ".google.com"},
-	{"2001:4860:4860::8888", ".google.com"},
-	{"2001:4860:4860::8844", ".google.com"},
+	{"8.8.8.8", ".google.com."},
+	{"8.8.4.4", ".google.com."},
+
+	{"2001:4860:4860::8888", ".google.com."},
+	{"2001:4860:4860::8844", ".google.com."},
 }
 
 func TestLookupGooglePublicDNSAddr(t *testing.T) {
-	if testing.Short() || !*testExternal {
+	if testing.Short() && testenv.Builder() == "" || !*testExternal {
 		t.Skip("avoid external network")
 	}
 	if !supportsIPv4 || !supportsIPv6 || !*testIPv4 || !*testIPv6 {
@@ -201,22 +204,46 @@ func TestLookupGooglePublicDNSAddr(t *testing.T) {
 			t.Error("got no record")
 		}
 		for _, name := range names {
-			if !strings.HasSuffix(name, tt.name) && !strings.HasSuffix(name, tt.name+".") {
+			if !strings.HasSuffix(name, tt.name) {
 				t.Errorf("got %s; want a record containing %s", name, tt.name)
 			}
 		}
 	}
 }
 
+func TestLookupIPv6LinkLocalAddr(t *testing.T) {
+	if !supportsIPv6 || !*testIPv6 {
+		t.Skip("IPv6 is required")
+	}
+
+	addrs, err := LookupHost("localhost")
+	if err != nil {
+		t.Fatal(err)
+	}
+	found := false
+	for _, addr := range addrs {
+		if addr == "fe80::1%lo0" {
+			found = true
+			break
+		}
+	}
+	if !found {
+		t.Skipf("not supported on %s", runtime.GOOS)
+	}
+	if _, err := LookupAddr("fe80::1%lo0"); err != nil {
+		t.Error(err)
+	}
+}
+
 var lookupIANACNAMETests = []struct {
 	name, cname string
 }{
-	{"www.iana.org", "icann.org"},
-	{"www.iana.org.", "icann.org"},
+	{"www.iana.org", "icann.org."},
+	{"www.iana.org.", "icann.org."},
 }
 
 func TestLookupIANACNAME(t *testing.T) {
-	if testing.Short() || !*testExternal {
+	if testing.Short() && testenv.Builder() == "" || !*testExternal {
 		t.Skip("avoid external network")
 	}
 	if !supportsIPv4 || !*testIPv4 {
@@ -228,7 +255,7 @@ func TestLookupIANACNAME(t *testing.T) {
 		if err != nil {
 			t.Fatal(err)
 		}
-		if !strings.HasSuffix(cname, tt.cname) && !strings.HasSuffix(cname, tt.cname+".") {
+		if !strings.HasSuffix(cname, tt.cname) {
 			t.Errorf("got %s; want a record containing %s", cname, tt.cname)
 		}
 	}
@@ -242,7 +269,7 @@ var lookupGoogleHostTests = []struct {
 }
 
 func TestLookupGoogleHost(t *testing.T) {
-	if testing.Short() || !*testExternal {
+	if testing.Short() && testenv.Builder() == "" || !*testExternal {
 		t.Skip("avoid external network")
 	}
 	if !supportsIPv4 || !*testIPv4 {
@@ -273,7 +300,7 @@ var lookupGoogleIPTests = []struct {
 }
 
 func TestLookupGoogleIP(t *testing.T) {
-	if testing.Short() || !*testExternal {
+	if testing.Short() && testenv.Builder() == "" || !*testExternal {
 		t.Skip("avoid external network")
 	}
 	if !supportsIPv4 || !*testIPv4 {
@@ -394,17 +421,62 @@ func TestLookupIPDeadline(t *testing.T) {
 	t.Logf("%v succeeded, %v failed (%v timeout, %v temporary, %v other, %v unknown)", qstats.succeeded, qstats.failed, qstats.timeout, qstats.temporary, qstats.other, qstats.unknown)
 }
 
-func TestLookupDots(t *testing.T) {
-	if testing.Short() || !*testExternal {
-		t.Skipf("skipping external network test")
+func TestLookupDotsWithLocalSource(t *testing.T) {
+	if !supportsIPv4 || !*testIPv4 {
+		t.Skip("IPv4 is required")
 	}
 
-	fixup := forceGoDNS()
-	defer fixup()
-	testDots(t, "go")
+	for i, fn := range []func() func(){forceGoDNS, forceCgoDNS} {
+		fixup := fn()
+		if fixup == nil {
+			continue
+		}
+		names, err := LookupAddr("127.0.0.1")
+		fixup()
+		if err != nil {
+			t.Logf("#%d: %v", i, err)
+			continue
+		}
+		mode := "netgo"
+		if i == 1 {
+			mode = "netcgo"
+		}
+	loop:
+		for i, name := range names {
+			if strings.Index(name, ".") == len(name)-1 { // "localhost" not "localhost."
+				for j := range names {
+					if j == i {
+						continue
+					}
+					if names[j] == name[:len(name)-1] {
+						// It's OK if we find the name without the dot,
+						// as some systems say 127.0.0.1 localhost localhost.
+						continue loop
+					}
+				}
+				t.Errorf("%s: got %s; want %s", mode, name, name[:len(name)-1])
+			} else if strings.Contains(name, ".") && !strings.HasSuffix(name, ".") { // "localhost.localdomain." not "localhost.localdomain"
+				t.Errorf("%s: got %s; want name ending with trailing dot", mode, name)
+			}
+		}
+	}
+}
+
+func TestLookupDotsWithRemoteSource(t *testing.T) {
+	if testing.Short() && testenv.Builder() == "" || !*testExternal {
+		t.Skip("avoid external network")
+	}
+	if !supportsIPv4 || !*testIPv4 {
+		t.Skip("IPv4 is required")
+	}
 
-	if forceCgoDNS() {
+	if fixup := forceGoDNS(); fixup != nil {
+		testDots(t, "go")
+		fixup()
+	}
+	if fixup := forceCgoDNS(); fixup != nil {
 		testDots(t, "cgo")
+		fixup()
 	}
 }
 
@@ -501,3 +573,62 @@ func srvString(srvs []*SRV) string {
 	fmt.Fprintf(&buf, "]")
 	return buf.String()
 }
+
+var lookupPortTests = []struct {
+	network string
+	name    string
+	port    int
+	ok      bool
+}{
+	{"tcp", "0", 0, true},
+	{"tcp", "echo", 7, true},
+	{"tcp", "discard", 9, true},
+	{"tcp", "systat", 11, true},
+	{"tcp", "daytime", 13, true},
+	{"tcp", "chargen", 19, true},
+	{"tcp", "ftp-data", 20, true},
+	{"tcp", "ftp", 21, true},
+	{"tcp", "telnet", 23, true},
+	{"tcp", "smtp", 25, true},
+	{"tcp", "time", 37, true},
+	{"tcp", "domain", 53, true},
+	{"tcp", "finger", 79, true},
+	{"tcp", "42", 42, true},
+
+	{"udp", "0", 0, true},
+	{"udp", "echo", 7, true},
+	{"udp", "tftp", 69, true},
+	{"udp", "bootpc", 68, true},
+	{"udp", "bootps", 67, true},
+	{"udp", "domain", 53, true},
+	{"udp", "ntp", 123, true},
+	{"udp", "snmp", 161, true},
+	{"udp", "syslog", 514, true},
+	{"udp", "42", 42, true},
+
+	{"--badnet--", "zzz", 0, false},
+	{"tcp", "--badport--", 0, false},
+	{"tcp", "-1", 0, false},
+	{"tcp", "65536", 0, false},
+	{"udp", "-1", 0, false},
+	{"udp", "65536", 0, false},
+
+	// Issue 13610: LookupPort("tcp", "")
+	{"tcp", "", 0, true},
+	{"tcp6", "", 0, true},
+	{"tcp4", "", 0, true},
+	{"udp", "", 0, true},
+}
+
+func TestLookupPort(t *testing.T) {
+	switch runtime.GOOS {
+	case "nacl":
+		t.Skipf("not supported on %s", runtime.GOOS)
+	}
+
+	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/lookup_windows.go b/src/net/lookup_windows.go
index 1b6d392..13edc26 100644
--- a/src/net/lookup_windows.go
+++ b/src/net/lookup_windows.go
@@ -19,7 +19,7 @@ var (
 func getprotobyname(name string) (proto int, err error) {
 	p, err := syscall.GetProtoByName(name)
 	if err != nil {
-		return 0, os.NewSyscallError("getorotobyname", err)
+		return 0, os.NewSyscallError("getprotobyname", err)
 	}
 	return int(p.Proto), nil
 }
@@ -221,10 +221,7 @@ func lookupCNAME(name string) (string, error) {
 	// windows returns DNS_INFO_NO_RECORDS if there are no CNAME-s
 	if errno, ok := e.(syscall.Errno); ok && errno == syscall.DNS_INFO_NO_RECORDS {
 		// if there are no aliases, the canonical name is the input name
-		if name == "" || name[len(name)-1] != '.' {
-			return name + ".", nil
-		}
-		return name, nil
+		return absDomainName([]byte(name)), nil
 	}
 	if e != nil {
 		return "", &DNSError{Err: os.NewSyscallError("dnsquery", e).Error(), Name: name}
@@ -232,8 +229,8 @@ func lookupCNAME(name string) (string, error) {
 	defer syscall.DnsRecordListFree(r, 1)
 
 	resolved := resolveCNAME(syscall.StringToUTF16Ptr(name), r)
-	cname := syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(resolved))[:]) + "."
-	return cname, nil
+	cname := syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(resolved))[:])
+	return absDomainName([]byte(cname)), nil
 }
 
 func lookupSRV(service, proto, name string) (string, []*SRV, error) {
@@ -255,10 +252,10 @@ func lookupSRV(service, proto, name string) (string, []*SRV, error) {
 	srvs := make([]*SRV, 0, 10)
 	for _, p := range validRecs(r, syscall.DNS_TYPE_SRV, target) {
 		v := (*syscall.DNSSRVData)(unsafe.Pointer(&p.Data[0]))
-		srvs = append(srvs, &SRV{syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Target))[:]), v.Port, v.Priority, v.Weight})
+		srvs = append(srvs, &SRV{absDomainName([]byte(syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Target))[:]))), v.Port, v.Priority, v.Weight})
 	}
 	byPriorityWeight(srvs).sort()
-	return name, srvs, nil
+	return absDomainName([]byte(target)), srvs, nil
 }
 
 func lookupMX(name string) ([]*MX, error) {
@@ -274,7 +271,7 @@ func lookupMX(name string) ([]*MX, error) {
 	mxs := make([]*MX, 0, 10)
 	for _, p := range validRecs(r, syscall.DNS_TYPE_MX, name) {
 		v := (*syscall.DNSMXData)(unsafe.Pointer(&p.Data[0]))
-		mxs = append(mxs, &MX{syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.NameExchange))[:]) + ".", v.Preference})
+		mxs = append(mxs, &MX{absDomainName([]byte(syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.NameExchange))[:]))), v.Preference})
 	}
 	byPref(mxs).sort()
 	return mxs, nil
@@ -293,7 +290,7 @@ func lookupNS(name string) ([]*NS, error) {
 	nss := make([]*NS, 0, 10)
 	for _, p := range validRecs(r, syscall.DNS_TYPE_NS, name) {
 		v := (*syscall.DNSPTRData)(unsafe.Pointer(&p.Data[0]))
-		nss = append(nss, &NS{syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Host))[:]) + "."})
+		nss = append(nss, &NS{absDomainName([]byte(syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Host))[:])))})
 	}
 	return nss, nil
 }
@@ -336,7 +333,7 @@ func lookupAddr(addr string) ([]string, error) {
 	ptrs := make([]string, 0, 10)
 	for _, p := range validRecs(r, syscall.DNS_TYPE_PTR, arpa) {
 		v := (*syscall.DNSPTRData)(unsafe.Pointer(&p.Data[0]))
-		ptrs = append(ptrs, syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Host))[:]))
+		ptrs = append(ptrs, absDomainName([]byte(syscall.UTF16ToString((*[256]uint16)(unsafe.Pointer(v.Host))[:]))))
 	}
 	return ptrs, nil
 }
diff --git a/src/net/lookup_windows_test.go b/src/net/lookup_windows_test.go
index 3f64d8c..7ff32b8 100644
--- a/src/net/lookup_windows_test.go
+++ b/src/net/lookup_windows_test.go
@@ -12,7 +12,6 @@ import (
 	"reflect"
 	"regexp"
 	"sort"
-	"strconv"
 	"strings"
 	"testing"
 )
@@ -149,13 +148,6 @@ func (s byHost) Len() int           { return len(s) }
 func (s byHost) Less(i, j int) bool { return s[i].Host < s[j].Host }
 func (s byHost) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
 
-func fqdn(s string) string {
-	if len(s) == 0 || s[len(s)-1] != '.' {
-		return s + "."
-	}
-	return s
-}
-
 func nslookup(qtype, name string) (string, error) {
 	var out bytes.Buffer
 	var err bytes.Buffer
@@ -184,15 +176,15 @@ func nslookupMX(name string) (mx []*MX, err error) {
 	// golang.org      mail exchanger = 2 alt1.aspmx.l.google.com.
 	rx := regexp.MustCompile(`(?m)^([a-z0-9.\-]+)\s+mail exchanger\s*=\s*([0-9]+)\s*([a-z0-9.\-]+)$`)
 	for _, ans := range rx.FindAllStringSubmatch(r, -1) {
-		pref, _ := strconv.Atoi(ans[2])
-		mx = append(mx, &MX{fqdn(ans[3]), uint16(pref)})
+		pref, _, _ := dtoi(ans[2], 0)
+		mx = append(mx, &MX{absDomainName([]byte(ans[3])), uint16(pref)})
 	}
 	// windows nslookup syntax
 	// gmail.com       MX preference = 30, mail exchanger = alt3.gmail-smtp-in.l.google.com
 	rx = regexp.MustCompile(`(?m)^([a-z0-9.\-]+)\s+MX preference\s*=\s*([0-9]+)\s*,\s*mail exchanger\s*=\s*([a-z0-9.\-]+)$`)
 	for _, ans := range rx.FindAllStringSubmatch(r, -1) {
-		pref, _ := strconv.Atoi(ans[2])
-		mx = append(mx, &MX{fqdn(ans[3]), uint16(pref)})
+		pref, _, _ := dtoi(ans[2], 0)
+		mx = append(mx, &MX{absDomainName([]byte(ans[3])), uint16(pref)})
 	}
 	return
 }
@@ -206,7 +198,7 @@ func nslookupNS(name string) (ns []*NS, err error) {
 	// golang.org      nameserver = ns1.google.com.
 	rx := regexp.MustCompile(`(?m)^([a-z0-9.\-]+)\s+nameserver\s*=\s*([a-z0-9.\-]+)$`)
 	for _, ans := range rx.FindAllStringSubmatch(r, -1) {
-		ns = append(ns, &NS{fqdn(ans[2])})
+		ns = append(ns, &NS{absDomainName([]byte(ans[2]))})
 	}
 	return
 }
@@ -223,7 +215,7 @@ func nslookupCNAME(name string) (cname string, err error) {
 	for _, ans := range rx.FindAllStringSubmatch(r, -1) {
 		last = ans[2]
 	}
-	return fqdn(last), nil
+	return absDomainName([]byte(last)), nil
 }
 
 func nslookupTXT(name string) (txt []string, err error) {
diff --git a/src/net/mac.go b/src/net/mac.go
index 8594a91..93f0b09 100644
--- a/src/net/mac.go
+++ b/src/net/mac.go
@@ -24,14 +24,17 @@ func (a HardwareAddr) String() string {
 	return string(buf)
 }
 
-// ParseMAC parses s as an IEEE 802 MAC-48, EUI-48, or EUI-64 using one of the
-// following formats:
+// ParseMAC parses s as an IEEE 802 MAC-48, EUI-48, EUI-64, or a 20-octet
+// IP over InfiniBand link-layer address using one of the following formats:
 //   01:23:45:67:89:ab
 //   01:23:45:67:89:ab:cd:ef
+//   01:23:45:67:89:ab:cd:ef:00:00:01:23:45:67:89:ab:cd:ef:00:00
 //   01-23-45-67-89-ab
 //   01-23-45-67-89-ab-cd-ef
+//   01-23-45-67-89-ab-cd-ef-00-00-01-23-45-67-89-ab-cd-ef-00-00
 //   0123.4567.89ab
 //   0123.4567.89ab.cdef
+//   0123.4567.89ab.cdef.0000.0123.4567.89ab.cdef.0000
 func ParseMAC(s string) (hw HardwareAddr, err error) {
 	if len(s) < 14 {
 		goto error
@@ -42,7 +45,7 @@ func ParseMAC(s string) (hw HardwareAddr, err error) {
 			goto error
 		}
 		n := (len(s) + 1) / 3
-		if n != 6 && n != 8 {
+		if n != 6 && n != 8 && n != 20 {
 			goto error
 		}
 		hw = make(HardwareAddr, n)
@@ -58,7 +61,7 @@ func ParseMAC(s string) (hw HardwareAddr, err error) {
 			goto error
 		}
 		n := 2 * (len(s) + 1) / 5
-		if n != 6 && n != 8 {
+		if n != 6 && n != 8 && n != 20 {
 			goto error
 		}
 		hw = make(HardwareAddr, n)
diff --git a/src/net/mac_test.go b/src/net/mac_test.go
index 0af0c01..1ec6b28 100644
--- a/src/net/mac_test.go
+++ b/src/net/mac_test.go
@@ -34,6 +34,30 @@ var parseMACTests = []struct {
 	{"01:23:45:67:89:AB:CD:EF", HardwareAddr{1, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, ""},
 	{"01-23-45-67-89-AB-CD-EF", HardwareAddr{1, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, ""},
 	{"0123.4567.89AB.CDEF", HardwareAddr{1, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, ""},
+	{
+		"01:23:45:67:89:ab:cd:ef:00:00:01:23:45:67:89:ab:cd:ef:00:00",
+		HardwareAddr{
+			0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x00, 0x00,
+			0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x00, 0x00,
+		},
+		"",
+	},
+	{
+		"01-23-45-67-89-ab-cd-ef-00-00-01-23-45-67-89-ab-cd-ef-00-00",
+		HardwareAddr{
+			0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x00, 0x00,
+			0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x00, 0x00,
+		},
+		"",
+	},
+	{
+		"0123.4567.89ab.cdef.0000.0123.4567.89ab.cdef.0000",
+		HardwareAddr{
+			0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x00, 0x00,
+			0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x00, 0x00,
+		},
+		"",
+	},
 }
 
 func TestParseMAC(t *testing.T) {
diff --git a/src/net/mail/message.go b/src/net/mail/message.go
index 266ac50..923630c 100644
--- a/src/net/mail/message.go
+++ b/src/net/mail/message.go
@@ -234,6 +234,12 @@ func (a *Address) String() string {
 		return b.String()
 	}
 
+	// Text in an encoded-word in a display-name must not contain certain
+	// characters like quotes or parentheses (see RFC 2047 section 5.3).
+	// When this is the case encode the name using base64 encoding.
+	if strings.ContainsAny(a.Name, "\"#$%&'(),.:;<>@[]^`{|}~") {
+		return mime.BEncoding.Encode("utf-8", a.Name) + " " + s
+	}
 	return mime.QEncoding.Encode("utf-8", a.Name) + " " + s
 }
 
@@ -386,10 +392,9 @@ func (p *addrParser) consumePhrase() (phrase string, err error) {
 			// We actually parse dot-atom here to be more permissive
 			// than what RFC 5322 specifies.
 			word, err = p.consumeAtom(true, true)
-		}
-
-		if err == nil {
-			word, err = p.decodeRFC2047Word(word)
+			if err == nil {
+				word, err = p.decodeRFC2047Word(word)
+			}
 		}
 
 		if err != nil {
@@ -442,17 +447,25 @@ Loop:
 	return string(qsb), nil
 }
 
+var errNonASCII = errors.New("mail: unencoded non-ASCII text in address")
+
 // consumeAtom parses an RFC 5322 atom at the start of p.
 // If dot is true, consumeAtom parses an RFC 5322 dot-atom instead.
 // If permissive is true, consumeAtom will not fail on
 // leading/trailing/double dots in the atom (see golang.org/issue/4938).
 func (p *addrParser) consumeAtom(dot bool, permissive bool) (atom string, err error) {
-	if !isAtext(p.peek(), false) {
+	if c := p.peek(); !isAtext(c, false) {
+		if c > 127 {
+			return "", errNonASCII
+		}
 		return "", errors.New("mail: invalid string")
 	}
 	i := 1
 	for ; i < p.len() && isAtext(p.s[i], dot); i++ {
 	}
+	if i < p.len() && p.s[i] > 127 {
+		return "", errNonASCII
+	}
 	atom, p.s = string(p.s[:i]), p.s[i:]
 	if !permissive {
 		if strings.HasPrefix(atom, ".") {
diff --git a/src/net/mail/message_test.go b/src/net/mail/message_test.go
index 1b42274..4e718e2 100644
--- a/src/net/mail/message_test.go
+++ b/src/net/mail/message_test.go
@@ -127,6 +127,14 @@ func TestAddressParsingError(t *testing.T) {
 	}
 }
 
+func TestAddressParsingErrorUnquotedNonASCII(t *testing.T) {
+	const txt = "µ <micro at example.net>"
+	_, err := ParseAddress(txt)
+	if err == nil || !strings.Contains(err.Error(), "unencoded non-ASCII text in address") {
+		t.Errorf(`mail.ParseAddress(%q) err: %q, want ".*unencoded non-ASCII text in address.*"`, txt, err)
+	}
+}
+
 func TestAddressParsing(t *testing.T) {
 	tests := []struct {
 		addrsStr string
@@ -449,7 +457,7 @@ func TestAddressParser(t *testing.T) {
 	}
 }
 
-func TestAddressFormatting(t *testing.T) {
+func TestAddressString(t *testing.T) {
 	tests := []struct {
 		addr *Address
 		exp  string
@@ -491,11 +499,40 @@ func TestAddressFormatting(t *testing.T) {
 			&Address{Name: "Rob", Address: "@"},
 			`"Rob" <@>`,
 		},
+		{
+			&Address{Name: "Böb, Jacöb", Address: "bob at example.com"},
+			`=?utf-8?b?QsO2YiwgSmFjw7Zi?= <bob at example.com>`,
+		},
+		{
+			&Address{Name: "=??Q?x?=", Address: "hello at world.com"},
+			`"=??Q?x?=" <hello at world.com>`,
+		},
+		{
+			&Address{Name: "=?hello", Address: "hello at world.com"},
+			`"=?hello" <hello at world.com>`,
+		},
+		{
+			&Address{Name: "world?=", Address: "hello at world.com"},
+			`"world?=" <hello at world.com>`,
+		},
 	}
 	for _, test := range tests {
 		s := test.addr.String()
 		if s != test.exp {
 			t.Errorf("Address%+v.String() = %v, want %v", *test.addr, s, test.exp)
+			continue
+		}
+
+		// Check round-trip.
+		if test.addr.Address != "" && test.addr.Address != "@" {
+			a, err := ParseAddress(test.exp)
+			if err != nil {
+				t.Errorf("ParseAddress(%#q): %v", test.exp, err)
+				continue
+			}
+			if a.Name != test.addr.Name || a.Address != test.addr.Address {
+				t.Errorf("ParseAddress(%#q) = %#v, want %#v", test.exp, a, test.addr)
+			}
 		}
 	}
 }
@@ -586,3 +623,32 @@ func TestAddressParsingAndFormatting(t *testing.T) {
 	}
 
 }
+
+func TestAddressFormattingAndParsing(t *testing.T) {
+	tests := []*Address{
+		{Name: "@lïce", Address: "alice at example.com"},
+		{Name: "Böb O'Connor", Address: "bob at example.com"},
+		{Name: "???", Address: "bob at example.com"},
+		{Name: "Böb ???", Address: "bob at example.com"},
+		{Name: "Böb (Jacöb)", Address: "bob at example.com"},
+		{Name: "à#$%&'(),.:;<>@[]^`{|}~'", Address: "bob at example.com"},
+		// https://golang.org/issue/11292
+		{Name: "\"\\\x1f,\"", Address: "0 at 0"},
+		// https://golang.org/issue/12782
+		{Name: "naé, mée", Address: "test.mail at gmail.com"},
+	}
+
+	for i, test := range tests {
+		parsed, err := ParseAddress(test.String())
+		if err != nil {
+			t.Errorf("test #%d: ParseAddr(%q) error: %v", i, test.String(), err)
+			continue
+		}
+		if parsed.Name != test.Name {
+			t.Errorf("test #%d: Parsed name = %q; want %q", i, parsed.Name, test.Name)
+		}
+		if parsed.Address != test.Address {
+			t.Errorf("test #%d: Parsed address = %q; want %q", i, parsed.Address, test.Address)
+		}
+	}
+}
diff --git a/src/net/net.go b/src/net/net.go
index 6e84c3a..d9d23fa 100644
--- a/src/net/net.go
+++ b/src/net/net.go
@@ -345,7 +345,7 @@ var listenerBacklog = maxListenerBacklog()
 // Multiple goroutines may invoke methods on a Listener simultaneously.
 type Listener interface {
 	// Accept waits for and returns the next connection to the listener.
-	Accept() (c Conn, err error)
+	Accept() (Conn, error)
 
 	// Close closes the listener.
 	// Any blocked Accept operations will be unblocked and return errors.
@@ -426,7 +426,16 @@ func (e *OpError) Error() string {
 	return s
 }
 
-var noDeadline = time.Time{}
+var (
+	// aLongTimeAgo is a non-zero time, far in the past, used for
+	// immediate cancelation of dials.
+	aLongTimeAgo = time.Unix(233431200, 0)
+
+	// nonDeadline and noCancel are just zero values for
+	// readability with functions taking too many parameters.
+	noDeadline = time.Time{}
+	noCancel   = (chan struct{})(nil)
+)
 
 type timeout interface {
 	Timeout() bool
@@ -520,10 +529,11 @@ var (
 
 // DNSError represents a DNS lookup error.
 type DNSError struct {
-	Err       string // description of the error
-	Name      string // name looked for
-	Server    string // server used
-	IsTimeout bool   // if true, timed out; not all timeouts set this
+	Err         string // description of the error
+	Name        string // name looked for
+	Server      string // server used
+	IsTimeout   bool   // if true, timed out; not all timeouts set this
+	IsTemporary bool   // if true, error is temporary; not all errors set this
 }
 
 func (e *DNSError) Error() string {
@@ -546,7 +556,7 @@ func (e *DNSError) Timeout() bool { return e.IsTimeout }
 // Temporary reports whether the DNS error is known to be temporary.
 // This is not always known; a DNS lookup may fail due to a temporary
 // error and return a DNSError for which Temporary returns false.
-func (e *DNSError) Temporary() bool { return e.IsTimeout }
+func (e *DNSError) Temporary() bool { return e.IsTimeout || e.IsTemporary }
 
 type writerOnly struct {
 	io.Writer
diff --git a/src/net/net_test.go b/src/net/net_test.go
index 3907ce4..cd62b43 100644
--- a/src/net/net_test.go
+++ b/src/net/net_test.go
@@ -9,6 +9,7 @@ import (
 	"os"
 	"runtime"
 	"testing"
+	"time"
 )
 
 func TestCloseRead(t *testing.T) {
@@ -208,8 +209,8 @@ func TestListenerClose(t *testing.T) {
 		case "unix", "unixpacket":
 			defer os.Remove(ln.Addr().String())
 		}
-		defer ln.Close()
 
+		dst := ln.Addr().String()
 		if err := ln.Close(); err != nil {
 			if perr := parseCloseError(err); perr != nil {
 				t.Error(perr)
@@ -221,6 +222,29 @@ func TestListenerClose(t *testing.T) {
 			c.Close()
 			t.Fatal("should fail")
 		}
+
+		if network == "tcp" {
+			// We will have two TCP FSMs inside the
+			// kernel here. There's no guarantee that a
+			// signal comes from the far end FSM will be
+			// delivered immediately to the near end FSM,
+			// especially on the platforms that allow
+			// multiple consumer threads to pull pending
+			// established connections at the same time by
+			// enabling SO_REUSEPORT option such as Linux,
+			// DragonFly BSD. So we need to give some time
+			// quantum to the kernel.
+			//
+			// Note that net.inet.tcp.reuseport_ext=1 by
+			// default on DragonFly BSD.
+			time.Sleep(time.Millisecond)
+
+			cc, err := Dial("tcp", dst)
+			if err == nil {
+				t.Error("Dial to closed TCP listener succeeded.")
+				cc.Close()
+			}
+		}
 	}
 }
 
@@ -254,3 +278,29 @@ func TestPacketConnClose(t *testing.T) {
 		}
 	}
 }
+
+// nacl was previous failing to reuse an address.
+func TestListenCloseListen(t *testing.T) {
+	const maxTries = 10
+	for tries := 0; tries < maxTries; tries++ {
+		ln, err := newLocalListener("tcp")
+		if err != nil {
+			t.Fatal(err)
+		}
+		addr := ln.Addr().String()
+		if err := ln.Close(); err != nil {
+			if perr := parseCloseError(err); perr != nil {
+				t.Error(perr)
+			}
+			t.Fatal(err)
+		}
+		ln, err = Listen("tcp", addr)
+		if err == nil {
+			// Success. nacl couldn't do this before.
+			ln.Close()
+			return
+		}
+		t.Errorf("failed on try %d/%d: %v", tries+1, maxTries, err)
+	}
+	t.Fatalf("failed to listen/close/listen on same address after %d tries", maxTries)
+}
diff --git a/src/net/net_windows_test.go b/src/net/net_windows_test.go
index 4f6bd45..df39032 100644
--- a/src/net/net_windows_test.go
+++ b/src/net/net_windows_test.go
@@ -9,8 +9,10 @@ import (
 	"bytes"
 	"fmt"
 	"io"
+	"io/ioutil"
 	"os"
 	"os/exec"
+	"regexp"
 	"sort"
 	"strings"
 	"syscall"
@@ -176,43 +178,426 @@ func isWindowsXP(t *testing.T) bool {
 	return major < 6
 }
 
-func listInterfacesWithNetsh() ([]string, error) {
-	out, err := exec.Command("netsh", "interface", "ip", "show", "config").CombinedOutput()
+var (
+	modkernel32 = syscall.NewLazyDLL("kernel32.dll")
+	procGetACP  = modkernel32.NewProc("GetACP")
+)
+
+func isEnglishOS(t *testing.T) bool {
+	const windows_1252 = 1252 // ANSI Latin 1; Western European (Windows)
+	r0, _, _ := syscall.Syscall(procGetACP.Addr(), 0, 0, 0, 0)
+	acp := uint32(r0)
+	return acp == windows_1252
+}
+
+func runCmd(args ...string) ([]byte, error) {
+	removeUTF8BOM := func(b []byte) []byte {
+		if len(b) >= 3 && b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF {
+			return b[3:]
+		}
+		return b
+	}
+	f, err := ioutil.TempFile("", "netcmd")
+	if err != nil {
+		return nil, err
+	}
+	f.Close()
+	defer os.Remove(f.Name())
+	cmd := fmt.Sprintf(`%s | Out-File "%s" -encoding UTF8`, strings.Join(args, " "), f.Name())
+	out, err := exec.Command("powershell", "-Command", cmd).CombinedOutput()
+	if err != nil {
+		if len(out) != 0 {
+			return nil, fmt.Errorf("%s failed: %v: %q", args[0], err, string(removeUTF8BOM(out)))
+		}
+		var err2 error
+		out, err2 = ioutil.ReadFile(f.Name())
+		if err2 != nil {
+			return nil, err2
+		}
+		if len(out) != 0 {
+			return nil, fmt.Errorf("%s failed: %v: %q", args[0], err, string(removeUTF8BOM(out)))
+		}
+		return nil, fmt.Errorf("%s failed: %v", args[0], err)
+	}
+	out, err = ioutil.ReadFile(f.Name())
+	if err != nil {
+		return nil, err
+	}
+	return removeUTF8BOM(out), nil
+}
+
+func netshInterfaceIPShowInterface(ipver string, ifaces map[string]bool) error {
+	out, err := runCmd("netsh", "interface", ipver, "show", "interface", "level=verbose")
 	if err != nil {
-		return nil, fmt.Errorf("netsh failed: %v: %q", err, string(out))
+		return err
 	}
+	// interface information is listed like:
+	//
+	//Interface Local Area Connection Parameters
+	//----------------------------------------------
+	//IfLuid                             : ethernet_6
+	//IfIndex                            : 11
+	//State                              : connected
+	//Metric                             : 10
+	//...
+	var name string
 	lines := bytes.Split(out, []byte{'\r', '\n'})
-	names := make([]string, 0)
 	for _, line := range lines {
-		f := bytes.Split(line, []byte{'"'})
-		if len(f) == 3 {
-			names = append(names, string(f[1]))
+		if bytes.HasPrefix(line, []byte("Interface ")) && bytes.HasSuffix(line, []byte(" Parameters")) {
+			f := line[len("Interface "):]
+			f = f[:len(f)-len(" Parameters")]
+			name = string(f)
+			continue
+		}
+		var isup bool
+		switch string(line) {
+		case "State                              : connected":
+			isup = true
+		case "State                              : disconnected":
+			isup = false
+		default:
+			continue
+		}
+		if name != "" {
+			if v, ok := ifaces[name]; ok && v != isup {
+				return fmt.Errorf("%s:%s isup=%v: ipv4 and ipv6 report different interface state", ipver, name, isup)
+			}
+			ifaces[name] = isup
+			name = ""
 		}
 	}
-	return names, nil
+	return nil
 }
 
-func TestInterfaceList(t *testing.T) {
+func TestInterfacesWithNetsh(t *testing.T) {
 	if isWindowsXP(t) {
 		t.Skip("Windows XP netsh command does not provide required functionality")
 	}
+	if !isEnglishOS(t) {
+		t.Skip("English version of OS required for this test")
+	}
+
+	toString := func(name string, isup bool) string {
+		if isup {
+			return name + ":up"
+		}
+		return name + ":down"
+	}
+
 	ift, err := Interfaces()
 	if err != nil {
 		t.Fatal(err)
 	}
 	have := make([]string, 0)
 	for _, ifi := range ift {
-		have = append(have, ifi.Name)
+		have = append(have, toString(ifi.Name, ifi.Flags&FlagUp != 0))
 	}
 	sort.Strings(have)
 
-	want, err := listInterfacesWithNetsh()
+	ifaces := make(map[string]bool)
+	err = netshInterfaceIPShowInterface("ipv6", ifaces)
 	if err != nil {
 		t.Fatal(err)
 	}
+	err = netshInterfaceIPShowInterface("ipv4", ifaces)
+	if err != nil {
+		t.Fatal(err)
+	}
+	want := make([]string, 0)
+	for name, isup := range ifaces {
+		want = append(want, toString(name, isup))
+	}
 	sort.Strings(want)
 
 	if strings.Join(want, "/") != strings.Join(have, "/") {
 		t.Fatalf("unexpected interface list %q, want %q", have, want)
 	}
 }
+
+func netshInterfaceIPv4ShowAddress(name string, netshOutput []byte) []string {
+	// adress information is listed like:
+	//
+	//Configuration for interface "Local Area Connection"
+	//    DHCP enabled:                         Yes
+	//    IP Address:                           10.0.0.2
+	//    Subnet Prefix:                        10.0.0.0/24 (mask 255.255.255.0)
+	//    IP Address:                           10.0.0.3
+	//    Subnet Prefix:                        10.0.0.0/24 (mask 255.255.255.0)
+	//    Default Gateway:                      10.0.0.254
+	//    Gateway Metric:                       0
+	//    InterfaceMetric:                      10
+	//
+	//Configuration for interface "Loopback Pseudo-Interface 1"
+	//    DHCP enabled:                         No
+	//    IP Address:                           127.0.0.1
+	//    Subnet Prefix:                        127.0.0.0/8 (mask 255.0.0.0)
+	//    InterfaceMetric:                      50
+	//
+	addrs := make([]string, 0)
+	var addr, subnetprefix string
+	var processingOurInterface bool
+	lines := bytes.Split(netshOutput, []byte{'\r', '\n'})
+	for _, line := range lines {
+		if !processingOurInterface {
+			if !bytes.HasPrefix(line, []byte("Configuration for interface")) {
+				continue
+			}
+			if !bytes.Contains(line, []byte(`"`+name+`"`)) {
+				continue
+			}
+			processingOurInterface = true
+			continue
+		}
+		if len(line) == 0 {
+			break
+		}
+		if bytes.Contains(line, []byte("Subnet Prefix:")) {
+			f := bytes.Split(line, []byte{':'})
+			if len(f) == 2 {
+				f = bytes.Split(f[1], []byte{'('})
+				if len(f) == 2 {
+					f = bytes.Split(f[0], []byte{'/'})
+					if len(f) == 2 {
+						subnetprefix = string(bytes.TrimSpace(f[1]))
+						if addr != "" && subnetprefix != "" {
+							addrs = append(addrs, addr+"/"+subnetprefix)
+						}
+					}
+				}
+			}
+		}
+		addr = ""
+		if bytes.Contains(line, []byte("IP Address:")) {
+			f := bytes.Split(line, []byte{':'})
+			if len(f) == 2 {
+				addr = string(bytes.TrimSpace(f[1]))
+			}
+		}
+	}
+	return addrs
+}
+
+func netshInterfaceIPv6ShowAddress(name string, netshOutput []byte) []string {
+	// adress information is listed like:
+	//
+	//Address ::1 Parameters
+	//---------------------------------------------------------
+	//Interface Luid     : Loopback Pseudo-Interface 1
+	//Scope Id           : 0.0
+	//Valid Lifetime     : infinite
+	//Preferred Lifetime : infinite
+	//DAD State          : Preferred
+	//Address Type       : Other
+	//Skip as Source     : false
+	//
+	//Address XXXX::XXXX:XXXX:XXXX:XXXX%11 Parameters
+	//---------------------------------------------------------
+	//Interface Luid     : Local Area Connection
+	//Scope Id           : 0.11
+	//Valid Lifetime     : infinite
+	//Preferred Lifetime : infinite
+	//DAD State          : Preferred
+	//Address Type       : Other
+	//Skip as Source     : false
+	//
+
+	// TODO: need to test ipv6 netmask too, but netsh does not outputs it
+	var addr string
+	addrs := make([]string, 0)
+	lines := bytes.Split(netshOutput, []byte{'\r', '\n'})
+	for _, line := range lines {
+		if addr != "" {
+			if len(line) == 0 {
+				addr = ""
+				continue
+			}
+			if string(line) != "Interface Luid     : "+name {
+				continue
+			}
+			addrs = append(addrs, addr)
+			addr = ""
+			continue
+		}
+		if !bytes.HasPrefix(line, []byte("Address")) {
+			continue
+		}
+		if !bytes.HasSuffix(line, []byte("Parameters")) {
+			continue
+		}
+		f := bytes.Split(line, []byte{' '})
+		if len(f) != 3 {
+			continue
+		}
+		// remove scope ID if present
+		f = bytes.Split(f[1], []byte{'%'})
+
+		// netsh can create IPv4-embedded IPv6 addresses, like fe80::5efe:192.168.140.1.
+		// Convert these to all hexadecimal fe80::5efe:c0a8:8c01 for later string comparisons.
+		ipv4Tail := regexp.MustCompile(`:\d+\.\d+\.\d+\.\d+$`)
+		if ipv4Tail.Match(f[0]) {
+			f[0] = []byte(ParseIP(string(f[0])).String())
+		}
+
+		addr = string(bytes.ToLower(bytes.TrimSpace(f[0])))
+	}
+	return addrs
+}
+
+func TestInterfaceAddrsWithNetsh(t *testing.T) {
+	if isWindowsXP(t) {
+		t.Skip("Windows XP netsh command does not provide required functionality")
+	}
+	if !isEnglishOS(t) {
+		t.Skip("English version of OS required for this test")
+	}
+
+	outIPV4, err := runCmd("netsh", "interface", "ipv4", "show", "address")
+	if err != nil {
+		t.Fatal(err)
+	}
+	outIPV6, err := runCmd("netsh", "interface", "ipv6", "show", "address", "level=verbose")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	ift, err := Interfaces()
+	if err != nil {
+		t.Fatal(err)
+	}
+	for _, ifi := range ift {
+		// Skip the interface if it's down.
+		if (ifi.Flags & FlagUp) == 0 {
+			continue
+		}
+		have := make([]string, 0)
+		addrs, err := ifi.Addrs()
+		if err != nil {
+			t.Fatal(err)
+		}
+		for _, addr := range addrs {
+			switch addr := addr.(type) {
+			case *IPNet:
+				if addr.IP.To4() != nil {
+					have = append(have, addr.String())
+				}
+				if addr.IP.To16() != nil && addr.IP.To4() == nil {
+					// netsh does not output netmask for ipv6, so ignore ipv6 mask
+					have = append(have, addr.IP.String())
+				}
+			case *IPAddr:
+				if addr.IP.To4() != nil {
+					have = append(have, addr.String())
+				}
+				if addr.IP.To16() != nil && addr.IP.To4() == nil {
+					// netsh does not output netmask for ipv6, so ignore ipv6 mask
+					have = append(have, addr.IP.String())
+				}
+			}
+		}
+		sort.Strings(have)
+
+		want := netshInterfaceIPv4ShowAddress(ifi.Name, outIPV4)
+		wantIPv6 := netshInterfaceIPv6ShowAddress(ifi.Name, outIPV6)
+		want = append(want, wantIPv6...)
+		sort.Strings(want)
+
+		if strings.Join(want, "/") != strings.Join(have, "/") {
+			t.Errorf("%s: unexpected addresses list %q, want %q", ifi.Name, have, want)
+		}
+	}
+}
+
+func TestInterfaceHardwareAddrWithGetmac(t *testing.T) {
+	if isWindowsXP(t) {
+		t.Skip("Windows XP does not have powershell command")
+	}
+	if !isEnglishOS(t) {
+		t.Skip("English version of OS required for this test")
+	}
+
+	ift, err := Interfaces()
+	if err != nil {
+		t.Fatal(err)
+	}
+	have := make(map[string]string)
+	for _, ifi := range ift {
+		if ifi.Flags&FlagLoopback != 0 {
+			// no MAC address for loopback interfaces
+			continue
+		}
+		have[ifi.Name] = ifi.HardwareAddr.String()
+	}
+
+	out, err := runCmd("getmac", "/fo", "list", "/v")
+	if err != nil {
+		t.Fatal(err)
+	}
+	// getmac output looks like:
+	//
+	//Connection Name:  Local Area Connection
+	//Network Adapter:  Intel Gigabit Network Connection
+	//Physical Address: XX-XX-XX-XX-XX-XX
+	//Transport Name:   \Device\Tcpip_{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}
+	//
+	//Connection Name:  Wireless Network Connection
+	//Network Adapter:  Wireles WLAN Card
+	//Physical Address: XX-XX-XX-XX-XX-XX
+	//Transport Name:   Media disconnected
+	//
+	//Connection Name:  Bluetooth Network Connection
+	//Network Adapter:  Bluetooth Device (Personal Area Network)
+	//Physical Address: N/A
+	//Transport Name:   Hardware not present
+	//
+	//Connection Name:  VMware Network Adapter VMnet8
+	//Network Adapter:  VMware Virtual Ethernet Adapter for VMnet8
+	//Physical Address: Disabled
+	//Transport Name:   Disconnected
+	//
+	want := make(map[string]string)
+	var name string
+	lines := bytes.Split(out, []byte{'\r', '\n'})
+	for _, line := range lines {
+		if bytes.Contains(line, []byte("Connection Name:")) {
+			f := bytes.Split(line, []byte{':'})
+			if len(f) != 2 {
+				t.Fatal("unexpected \"Connection Name\" line: %q", line)
+			}
+			name = string(bytes.TrimSpace(f[1]))
+			if name == "" {
+				t.Fatal("empty name on \"Connection Name\" line: %q", line)
+			}
+		}
+		if bytes.Contains(line, []byte("Physical Address:")) {
+			if name == "" {
+				t.Fatal("no matching name found: %q", string(out))
+			}
+			f := bytes.Split(line, []byte{':'})
+			if len(f) != 2 {
+				t.Fatal("unexpected \"Physical Address\" line: %q", line)
+			}
+			addr := string(bytes.ToLower(bytes.TrimSpace(f[1])))
+			if addr == "" {
+				t.Fatal("empty address on \"Physical Address\" line: %q", line)
+			}
+			if addr == "disabled" || addr == "n/a" {
+				continue
+			}
+			addr = strings.Replace(addr, "-", ":", -1)
+			want[name] = addr
+			name = ""
+		}
+	}
+
+	for name, wantAddr := range want {
+		haveAddr, ok := have[name]
+		if !ok {
+			t.Errorf("getmac lists %q, but it could not be found among Go interfaces %v", name, have)
+			continue
+		}
+		if haveAddr != wantAddr {
+			t.Errorf("unexpected MAC address for %q - %v, want %v", name, haveAddr, wantAddr)
+			continue
+		}
+	}
+}
diff --git a/src/net/non_unix_test.go b/src/net/non_unix_test.go
index eddca56..db3427e 100644
--- a/src/net/non_unix_test.go
+++ b/src/net/non_unix_test.go
@@ -6,6 +6,17 @@
 
 package net
 
+import "runtime"
+
+// See unix_test.go for what these (don't) do.
+func forceGoDNS() func() {
+	switch runtime.GOOS {
+	case "plan9", "windows":
+		return func() {}
+	default:
+		return nil
+	}
+}
+
 // See unix_test.go for what these (don't) do.
-func forceGoDNS() func() { return func() {} }
-func forceCgoDNS() bool  { return false }
+func forceCgoDNS() func() { return nil }
diff --git a/src/net/parse.go b/src/net/parse.go
index c72e1c2..eaaa1ed 100644
--- a/src/net/parse.go
+++ b/src/net/parse.go
@@ -10,6 +10,8 @@ package net
 import (
 	"io"
 	"os"
+	"time"
+	_ "unsafe" // For go:linkname
 )
 
 type file struct {
@@ -70,15 +72,20 @@ func open(name string) (*file, error) {
 	return &file{fd, make([]byte, 0, os.Getpagesize()), false}, nil
 }
 
-func byteIndex(s string, c byte) int {
-	for i := 0; i < len(s); i++ {
-		if s[i] == c {
-			return i
-		}
+func stat(name string) (mtime time.Time, size int64, err error) {
+	st, err := os.Stat(name)
+	if err != nil {
+		return time.Time{}, 0, err
 	}
-	return -1
+	return st.ModTime(), st.Size(), nil
 }
 
+// byteIndex is strings.IndexByte. It returns the index of the
+// first instance of c in s, or -1 if c is not present in s.
+// strings.IndexByte is implemented in  runtime/asm_$GOARCH.s
+//go:linkname byteIndex strings.IndexByte
+func byteIndex(s string, c byte) int
+
 // Count occurrences in s of any bytes in t.
 func countAnyByte(s string, t string) int {
 	n := 0
@@ -120,15 +127,27 @@ const big = 0xFFFFFF
 // Returns number, new offset, success.
 func dtoi(s string, i0 int) (n int, i int, ok bool) {
 	n = 0
+	neg := false
+	if len(s) > 0 && s[0] == '-' {
+		neg = true
+		s = s[1:]
+	}
 	for i = i0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
 		n = n*10 + int(s[i]-'0')
 		if n >= big {
-			return 0, i, false
+			if neg {
+				return -big, i + 1, false
+			}
+			return big, i, false
 		}
 	}
 	if i == i0 {
 		return 0, i, false
 	}
+	if neg {
+		n = -n
+		i++
+	}
 	return n, i, true
 }
 
@@ -314,14 +333,9 @@ func foreachField(x []byte, fn func(field []byte) error) error {
 
 // bytesIndexByte is bytes.IndexByte. It returns the index of the
 // first instance of c in s, or -1 if c is not present in s.
-func bytesIndexByte(s []byte, c byte) int {
-	for i, b := range s {
-		if b == c {
-			return i
-		}
-	}
-	return -1
-}
+// bytes.IndexByte is implemented in  runtime/asm_$GOARCH.s
+//go:linkname bytesIndexByte bytes.IndexByte
+func bytesIndexByte(s []byte, c byte) int
 
 // stringsHasSuffix is strings.HasSuffix. It reports whether s ends in
 // suffix.
diff --git a/src/net/parse_test.go b/src/net/parse_test.go
index 0f048fc..fec9200 100644
--- a/src/net/parse_test.go
+++ b/src/net/parse_test.go
@@ -77,3 +77,25 @@ func TestGoDebugString(t *testing.T) {
 		}
 	}
 }
+
+func TestDtoi(t *testing.T) {
+	for _, tt := range []struct {
+		in  string
+		out int
+		off int
+		ok  bool
+	}{
+		{"", 0, 0, false},
+
+		{"-123456789", -big, 9, false},
+		{"-1", -1, 2, true},
+		{"0", 0, 1, true},
+		{"65536", 65536, 5, true},
+		{"123456789", big, 8, false},
+	} {
+		n, i, ok := dtoi(tt.in, 0)
+		if n != tt.out || i != tt.off || ok != tt.ok {
+			t.Errorf("got %d, %d, %v; want %d, %d, %v", n, i, ok, tt.out, tt.off, tt.ok)
+		}
+	}
+}
diff --git a/src/net/platform_test.go b/src/net/platform_test.go
index d624852..76c5313 100644
--- a/src/net/platform_test.go
+++ b/src/net/platform_test.go
@@ -32,7 +32,7 @@ func testableNetwork(network string) bool {
 		}
 	case "unix", "unixgram":
 		switch runtime.GOOS {
-		case "nacl", "plan9", "windows":
+		case "android", "nacl", "plan9", "windows":
 			return false
 		}
 		// iOS does not support unix, unixgram.
@@ -134,7 +134,7 @@ func testableListenArgs(network, address, client string) bool {
 
 	// Test functionality of IPv4 communication using AF_INET6
 	// sockets.
-	if !supportsIPv4map && (network == "tcp" || network == "udp" || network == "ip") && wildcard {
+	if !supportsIPv4map && supportsIPv4 && (network == "tcp" || network == "udp" || network == "ip") && wildcard {
 		// At this point, we prefer IPv4 when ip is nil.
 		// See favoriteAddrFamily for further information.
 		if ip.To16() != nil && ip.To4() == nil && cip.To4() != nil { // a pair of IPv6 server and IPv4 client
diff --git a/src/net/port.go b/src/net/port.go
deleted file mode 100644
index a2a5387..0000000
--- a/src/net/port.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2012 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.
-
-// Network service port manipulations
-
-package net
-
-// parsePort parses port as a network service port number for both
-// TCP and UDP.
-func parsePort(net, port string) (int, error) {
-	p, i, ok := dtoi(port, 0)
-	if !ok || i != len(port) {
-		var err error
-		p, err = LookupPort(net, port)
-		if err != nil {
-			return 0, err
-		}
-	}
-	if p < 0 || p > 0xFFFF {
-		return 0, &AddrError{Err: "invalid port", Addr: port}
-	}
-	return p, nil
-}
diff --git a/src/net/port_test.go b/src/net/port_test.go
deleted file mode 100644
index 258a5bd..0000000
--- a/src/net/port_test.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2009 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 net
-
-import (
-	"runtime"
-	"testing"
-)
-
-var portTests = []struct {
-	network string
-	name    string
-	port    int
-	ok      bool
-}{
-	{"tcp", "echo", 7, true},
-	{"tcp", "discard", 9, true},
-	{"tcp", "systat", 11, true},
-	{"tcp", "daytime", 13, true},
-	{"tcp", "chargen", 19, true},
-	{"tcp", "ftp-data", 20, true},
-	{"tcp", "ftp", 21, true},
-	{"tcp", "telnet", 23, true},
-	{"tcp", "smtp", 25, true},
-	{"tcp", "time", 37, true},
-	{"tcp", "domain", 53, true},
-	{"tcp", "finger", 79, true},
-	{"tcp", "42", 42, true},
-
-	{"udp", "echo", 7, true},
-	{"udp", "tftp", 69, true},
-	{"udp", "bootpc", 68, true},
-	{"udp", "bootps", 67, true},
-	{"udp", "domain", 53, true},
-	{"udp", "ntp", 123, true},
-	{"udp", "snmp", 161, true},
-	{"udp", "syslog", 514, true},
-	{"udp", "42", 42, true},
-
-	{"--badnet--", "zzz", 0, false},
-	{"tcp", "--badport--", 0, false},
-}
-
-func TestLookupPort(t *testing.T) {
-	switch runtime.GOOS {
-	case "nacl":
-		t.Skipf("not supported on %s", runtime.GOOS)
-	}
-
-	for _, tt := range portTests {
-		if port, err := LookupPort(tt.network, tt.name); port != tt.port || (err == nil) != tt.ok {
-			t.Errorf("LookupPort(%q, %q) = %v, %v; want %v", tt.network, tt.name, port, err, tt.port)
-		}
-	}
-}
diff --git a/src/net/race.go b/src/net/race.go
deleted file mode 100644
index 2f02a6c..0000000
--- a/src/net/race.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013 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.
-
-// +build race
-// +build windows
-
-package net
-
-import (
-	"runtime"
-	"unsafe"
-)
-
-const raceenabled = true
-
-func raceAcquire(addr unsafe.Pointer) {
-	runtime.RaceAcquire(addr)
-}
-
-func raceReleaseMerge(addr unsafe.Pointer) {
-	runtime.RaceReleaseMerge(addr)
-}
-
-func raceReadRange(addr unsafe.Pointer, len int) {
-	runtime.RaceReadRange(addr, len)
-}
-
-func raceWriteRange(addr unsafe.Pointer, len int) {
-	runtime.RaceWriteRange(addr, len)
-}
diff --git a/src/net/race0.go b/src/net/race0.go
deleted file mode 100644
index f504297..0000000
--- a/src/net/race0.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2013 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.
-
-// +build !race
-// +build windows
-
-package net
-
-import (
-	"unsafe"
-)
-
-const raceenabled = false
-
-func raceAcquire(addr unsafe.Pointer) {
-}
-
-func raceReleaseMerge(addr unsafe.Pointer) {
-}
-
-func raceReadRange(addr unsafe.Pointer, len int) {
-}
-
-func raceWriteRange(addr unsafe.Pointer, len int) {
-}
diff --git a/src/net/rpc/server.go b/src/net/rpc/server.go
index 6e6e881..c4d4479 100644
--- a/src/net/rpc/server.go
+++ b/src/net/rpc/server.go
@@ -611,13 +611,15 @@ func (server *Server) readRequestHeader(codec ServerCodec) (service *service, mt
 }
 
 // Accept accepts connections on the listener and serves requests
-// for each incoming connection.  Accept blocks; the caller typically
-// invokes it in a go statement.
+// for each incoming connection. Accept blocks until the listener
+// returns a non-nil error. The caller typically invokes Accept in a
+// go statement.
 func (server *Server) Accept(lis net.Listener) {
 	for {
 		conn, err := lis.Accept()
 		if err != nil {
-			log.Fatal("rpc.Serve: accept:", err.Error()) // TODO(r): exit?
+			log.Print("rpc.Serve: accept:", err.Error())
+			return
 		}
 		go server.ServeConn(conn)
 	}
diff --git a/src/net/rpc/server_test.go b/src/net/rpc/server_test.go
index 0dc4ddc..8871c88 100644
--- a/src/net/rpc/server_test.go
+++ b/src/net/rpc/server_test.go
@@ -74,6 +74,17 @@ func (t *Arith) Error(args *Args, reply *Reply) error {
 	panic("ERROR")
 }
 
+type hidden int
+
+func (t *hidden) Exported(args Args, reply *Reply) error {
+	reply.C = args.A + args.B
+	return nil
+}
+
+type Embed struct {
+	hidden
+}
+
 func listenTCP() (net.Listener, string) {
 	l, e := net.Listen("tcp", "127.0.0.1:0") // any available address
 	if e != nil {
@@ -84,6 +95,7 @@ func listenTCP() (net.Listener, string) {
 
 func startServer() {
 	Register(new(Arith))
+	Register(new(Embed))
 	RegisterName("net.rpc.Arith", new(Arith))
 
 	var l net.Listener
@@ -98,6 +110,7 @@ func startServer() {
 func startNewServer() {
 	newServer = NewServer()
 	newServer.Register(new(Arith))
+	newServer.Register(new(Embed))
 	newServer.RegisterName("net.rpc.Arith", new(Arith))
 	newServer.RegisterName("newServer.Arith", new(Arith))
 
@@ -142,6 +155,17 @@ func testRPC(t *testing.T, addr string) {
 		t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
 	}
 
+	// Methods exported from unexported embedded structs
+	args = &Args{7, 0}
+	reply = new(Reply)
+	err = client.Call("Embed.Exported", args, reply)
+	if err != nil {
+		t.Errorf("Add: expected no error but got string %q", err.Error())
+	}
+	if reply.C != args.A+args.B {
+		t.Errorf("Add: expected %d got %d", reply.C, args.A+args.B)
+	}
+
 	// Nonexistent method
 	args = &Args{7, 0}
 	reply = new(Reply)
@@ -593,6 +617,19 @@ func TestErrorAfterClientClose(t *testing.T) {
 	}
 }
 
+// Tests the fix to issue 11221. Without the fix, this loops forever or crashes.
+func TestAcceptExitAfterListenerClose(t *testing.T) {
+	newServer = NewServer()
+	newServer.Register(new(Arith))
+	newServer.RegisterName("net.rpc.Arith", new(Arith))
+	newServer.RegisterName("newServer.Arith", new(Arith))
+
+	var l net.Listener
+	l, newServerAddr = listenTCP()
+	l.Close()
+	newServer.Accept(l)
+}
+
 func benchmarkEndToEnd(dial func() (*Client, error), b *testing.B) {
 	once.Do(startServer)
 	client, err := dial()
diff --git a/src/net/sendfile_solaris.go b/src/net/sendfile_solaris.go
index 0966575..f683381 100644
--- a/src/net/sendfile_solaris.go
+++ b/src/net/sendfile_solaris.go
@@ -26,6 +26,8 @@ const maxSendfileSize int = 4 << 20
 //
 // if handled == false, sendFile performed no work.
 func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
+	return // Solaris sendfile is disabled until Issue 13892 is understood and fixed
+
 	// Solaris uses 0 as the "until EOF" value. If you pass in more bytes than the
 	// file contains, it will loop back to the beginning ad nauseam until it's sent
 	// exactly the number of bytes told to. As such, we need to know exactly how many
diff --git a/src/net/server_test.go b/src/net/server_test.go
index fe0006b..2e998e2 100644
--- a/src/net/server_test.go
+++ b/src/net/server_test.go
@@ -55,7 +55,7 @@ func TestTCPServer(t *testing.T) {
 
 	for i, tt := range tcpServerTests {
 		if !testableListenArgs(tt.snet, tt.saddr, tt.taddr) {
-			t.Logf("skipping %s test", tt.snet+" "+tt.saddr+"->"+tt.taddr)
+			t.Logf("skipping %s test", tt.snet+" "+tt.saddr+"<-"+tt.taddr)
 			continue
 		}
 
@@ -251,7 +251,7 @@ var udpServerTests = []struct {
 func TestUDPServer(t *testing.T) {
 	for i, tt := range udpServerTests {
 		if !testableListenArgs(tt.snet, tt.saddr, tt.taddr) {
-			t.Logf("skipping %s test", tt.snet+" "+tt.saddr+"->"+tt.taddr)
+			t.Logf("skipping %s test", tt.snet+" "+tt.saddr+"<-"+tt.taddr)
 			continue
 		}
 
@@ -329,7 +329,7 @@ var unixgramServerTests = []struct {
 func TestUnixgramServer(t *testing.T) {
 	for i, tt := range unixgramServerTests {
 		if !testableListenArgs("unixgram", tt.saddr, "") {
-			t.Logf("skipping %s test", "unixgram "+tt.saddr+"->"+tt.caddr)
+			t.Logf("skipping %s test", "unixgram "+tt.saddr+"<-"+tt.caddr)
 			continue
 		}
 
diff --git a/src/net/sock_posix.go b/src/net/sock_posix.go
index 4d2cfde..4676721 100644
--- a/src/net/sock_posix.go
+++ b/src/net/sock_posix.go
@@ -34,7 +34,7 @@ type sockaddr interface {
 
 // socket returns a network file descriptor that is ready for
 // asynchronous I/O using the network poller.
-func socket(net string, family, sotype, proto int, ipv6only bool, laddr, raddr sockaddr, deadline time.Time) (fd *netFD, err error) {
+func socket(net string, family, sotype, proto int, ipv6only bool, laddr, raddr sockaddr, deadline time.Time, cancel <-chan struct{}) (fd *netFD, err error) {
 	s, err := sysSocket(family, sotype, proto)
 	if err != nil {
 		return nil, err
@@ -86,7 +86,7 @@ func socket(net string, family, sotype, proto int, ipv6only bool, laddr, raddr s
 			return fd, nil
 		}
 	}
-	if err := fd.dial(laddr, raddr, deadline); err != nil {
+	if err := fd.dial(laddr, raddr, deadline, cancel); err != nil {
 		fd.Close()
 		return nil, err
 	}
@@ -117,7 +117,7 @@ func (fd *netFD) addrFunc() func(syscall.Sockaddr) Addr {
 	return func(syscall.Sockaddr) Addr { return nil }
 }
 
-func (fd *netFD) dial(laddr, raddr sockaddr, deadline time.Time) error {
+func (fd *netFD) dial(laddr, raddr sockaddr, deadline time.Time, cancel <-chan struct{}) error {
 	var err error
 	var lsa syscall.Sockaddr
 	if laddr != nil {
@@ -134,7 +134,7 @@ func (fd *netFD) dial(laddr, raddr sockaddr, deadline time.Time) error {
 		if rsa, err = raddr.sockaddr(fd.family); err != nil {
 			return err
 		}
-		if err := fd.connect(lsa, rsa, deadline); err != nil {
+		if err := fd.connect(lsa, rsa, deadline, cancel); err != nil {
 			return err
 		}
 		fd.isConnected = true
diff --git a/src/net/tcp_test.go b/src/net/tcp_test.go
index 2191c91..30c5762 100644
--- a/src/net/tcp_test.go
+++ b/src/net/tcp_test.go
@@ -539,9 +539,12 @@ func TestTCPStress(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	defer ln.Close()
+	done := make(chan bool)
 	// Acceptor.
 	go func() {
+		defer func() {
+			done <- true
+		}()
 		for {
 			c, err := ln.Accept()
 			if err != nil {
@@ -559,7 +562,6 @@ func TestTCPStress(t *testing.T) {
 			}(c)
 		}
 	}()
-	done := make(chan bool)
 	for i := 0; i < conns; i++ {
 		// Client connection.
 		go func() {
@@ -583,4 +585,6 @@ func TestTCPStress(t *testing.T) {
 	for i := 0; i < conns; i++ {
 		<-done
 	}
+	ln.Close()
+	<-done
 }
diff --git a/src/net/tcpsock_plan9.go b/src/net/tcpsock_plan9.go
index 9f23703..afccbfe 100644
--- a/src/net/tcpsock_plan9.go
+++ b/src/net/tcpsock_plan9.go
@@ -107,13 +107,14 @@ func (c *TCPConn) SetNoDelay(noDelay bool) error {
 // which must be "tcp", "tcp4", or "tcp6".  If laddr is not nil, it is
 // used as the local address for the connection.
 func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
-	return dialTCP(net, laddr, raddr, noDeadline)
+	return dialTCP(net, laddr, raddr, noDeadline, noCancel)
 }
 
-func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, error) {
+func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time, cancel <-chan struct{}) (*TCPConn, error) {
 	if !deadline.IsZero() {
 		panic("net.dialTCP: deadline not implemented on Plan 9")
 	}
+	// TODO(bradfitz,0intro): also use the cancel channel.
 	switch net {
 	case "tcp", "tcp4", "tcp6":
 	default:
diff --git a/src/net/tcpsock_posix.go b/src/net/tcpsock_posix.go
index 7e49b76..0e12d54 100644
--- a/src/net/tcpsock_posix.go
+++ b/src/net/tcpsock_posix.go
@@ -164,11 +164,11 @@ func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error) {
 	if raddr == nil {
 		return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: nil, Err: errMissingAddress}
 	}
-	return dialTCP(net, laddr, raddr, noDeadline)
+	return dialTCP(net, laddr, raddr, noDeadline, noCancel)
 }
 
-func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, error) {
-	fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_STREAM, 0, "dial")
+func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time, cancel <-chan struct{}) (*TCPConn, error) {
+	fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_STREAM, 0, "dial", cancel)
 
 	// TCP has a rarely used mechanism called a 'simultaneous connection' in
 	// which Dial("tcp", addr1, addr2) run on the machine at addr1 can
@@ -198,7 +198,7 @@ func dialTCP(net string, laddr, raddr *TCPAddr, deadline time.Time) (*TCPConn, e
 		if err == nil {
 			fd.Close()
 		}
-		fd, err = internetSocket(net, laddr, raddr, deadline, syscall.SOCK_STREAM, 0, "dial")
+		fd, err = internetSocket(net, laddr, raddr, deadline, syscall.SOCK_STREAM, 0, "dial", cancel)
 	}
 
 	if err != nil {
@@ -326,7 +326,7 @@ func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error) {
 	if laddr == nil {
 		laddr = &TCPAddr{}
 	}
-	fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_STREAM, 0, "listen")
+	fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_STREAM, 0, "listen", noCancel)
 	if err != nil {
 		return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: err}
 	}
diff --git a/src/net/tcpsockopt_plan9.go b/src/net/tcpsockopt_plan9.go
index 9abe186..157282a 100644
--- a/src/net/tcpsockopt_plan9.go
+++ b/src/net/tcpsockopt_plan9.go
@@ -7,13 +7,12 @@
 package net
 
 import (
-	"strconv"
 	"time"
 )
 
 // Set keep alive period.
 func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
-	cmd := "keepalive " + strconv.Itoa(int(d/time.Millisecond))
+	cmd := "keepalive " + itoa(int(d/time.Millisecond))
 	_, e := fd.ctl.WriteAt([]byte(cmd), 0)
 	return e
 }
diff --git a/src/net/testdata/case-hosts b/src/net/testdata/case-hosts
new file mode 100644
index 0000000..1f30df1
--- /dev/null
+++ b/src/net/testdata/case-hosts
@@ -0,0 +1,2 @@
+127.0.0.1	PreserveMe	PreserveMe.local
+::1		PreserveMe	PreserveMe.local
diff --git a/src/net/testdata/hosts b/src/net/testdata/hosts
index b601763..3ed83ff 100644
--- a/src/net/testdata/hosts
+++ b/src/net/testdata/hosts
@@ -5,8 +5,7 @@
 127.1.1.1	thor
 # aliases
 127.1.1.2	ullr ullrhost
+fe80::1%lo0	localhost
 # Bogus entries that must be ignored.
 123.123.123	loki
 321.321.321.321
-# TODO(yvesj): Should we be able to parse this? From a Darwin system.
-fe80::1%lo0	localhost
diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go
index 91303fe..91bbb57 100644
--- a/src/net/textproto/reader.go
+++ b/src/net/textproto/reader.go
@@ -150,7 +150,7 @@ func (r *Reader) readContinuedLineSlice() ([]byte, error) {
 			break
 		}
 		r.buf = append(r.buf, ' ')
-		r.buf = append(r.buf, line...)
+		r.buf = append(r.buf, trim(line)...)
 	}
 	return r.buf, nil
 }
@@ -237,7 +237,12 @@ func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err err
 // separated by a newline (\n).
 //
 // See page 36 of RFC 959 (http://www.ietf.org/rfc/rfc959.txt) for
-// details.
+// details of another form of response accepted:
+//
+//  code-message line 1
+//  message line 2
+//  ...
+//  code message line n
 //
 // If the prefix of the status does not match the digits in expectCode,
 // ReadResponse returns with err set to &Error{code, message}.
@@ -248,7 +253,8 @@ func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err err
 //
 func (r *Reader) ReadResponse(expectCode int) (code int, message string, err error) {
 	code, continued, message, err := r.readCodeLine(expectCode)
-	for err == nil && continued {
+	multi := continued
+	for continued {
 		line, err := r.ReadLine()
 		if err != nil {
 			return 0, "", err
@@ -256,7 +262,7 @@ func (r *Reader) ReadResponse(expectCode int) (code int, message string, err err
 
 		var code2 int
 		var moreMessage string
-		code2, continued, moreMessage, err = parseCodeLine(line, expectCode)
+		code2, continued, moreMessage, err = parseCodeLine(line, 0)
 		if err != nil || code2 != code {
 			message += "\n" + strings.TrimRight(line, "\r\n")
 			continued = true
@@ -264,6 +270,10 @@ func (r *Reader) ReadResponse(expectCode int) (code int, message string, err err
 		}
 		message += "\n" + moreMessage
 	}
+	if err != nil && multi && message != "" {
+		// replace one line error message with all lines (full message)
+		err = &Error{code, message}
+	}
 	return
 }
 
diff --git a/src/net/textproto/reader_test.go b/src/net/textproto/reader_test.go
index 8fce7dd..9c71594 100644
--- a/src/net/textproto/reader_test.go
+++ b/src/net/textproto/reader_test.go
@@ -205,6 +205,32 @@ func TestReadMIMEHeaderNonCompliant(t *testing.T) {
 	}
 }
 
+// Test that continued lines are properly trimmed. Issue 11204.
+func TestReadMIMEHeaderTrimContinued(t *testing.T) {
+	// In this header, \n and \r\n terminated lines are mixed on purpose.
+	// We expect each line to be trimmed (prefix and suffix) before being concatenated.
+	// Keep the spaces as they are.
+	r := reader("" + // for code formatting purpose.
+		"a:\n" +
+		" 0 \r\n" +
+		"b:1 \t\r\n" +
+		"c: 2\r\n" +
+		" 3\t\n" +
+		"  \t 4  \r\n\n")
+	m, err := r.ReadMIMEHeader()
+	if err != nil {
+		t.Fatal(err)
+	}
+	want := MIMEHeader{
+		"A": {"0"},
+		"B": {"1"},
+		"C": {"2 3 4"},
+	}
+	if !reflect.DeepEqual(m, want) {
+		t.Fatalf("ReadMIMEHeader mismatch.\n got: %q\nwant: %q", m, want)
+	}
+}
+
 type readResponseTest struct {
 	in       string
 	inCode   int
@@ -258,6 +284,35 @@ func TestRFC959Lines(t *testing.T) {
 	}
 }
 
+// Test that multi-line errors are appropriately and fully read. Issue 10230.
+func TestReadMultiLineError(t *testing.T) {
+	r := reader("550-5.1.1 The email account that you tried to reach does not exist. Please try\n" +
+		"550-5.1.1 double-checking the recipient's email address for typos or\n" +
+		"550-5.1.1 unnecessary spaces. Learn more at\n" +
+		"Unexpected but legal text!\n" +
+		"550 5.1.1 https://support.google.com/mail/answer/6596 h20si25154304pfd.166 - gsmtp\n")
+
+	wantMsg := "5.1.1 The email account that you tried to reach does not exist. Please try\n" +
+		"5.1.1 double-checking the recipient's email address for typos or\n" +
+		"5.1.1 unnecessary spaces. Learn more at\n" +
+		"Unexpected but legal text!\n" +
+		"5.1.1 https://support.google.com/mail/answer/6596 h20si25154304pfd.166 - gsmtp"
+
+	code, msg, err := r.ReadResponse(250)
+	if err == nil {
+		t.Errorf("ReadResponse: no error, want error")
+	}
+	if code != 550 {
+		t.Errorf("ReadResponse: code=%d, want %d", code, 550)
+	}
+	if msg != wantMsg {
+		t.Errorf("ReadResponse: msg=%q, want %q", msg, wantMsg)
+	}
+	if err.Error() != "550 "+wantMsg {
+		t.Errorf("ReadResponse: error=%q, want %q", err.Error(), "550 "+wantMsg)
+	}
+}
+
 func TestCommonHeaders(t *testing.T) {
 	for h := range commonHeader {
 		if h != CanonicalMIMEHeaderKey(h) {
diff --git a/src/net/timeout_test.go b/src/net/timeout_test.go
index ca94e24..98e3164 100644
--- a/src/net/timeout_test.go
+++ b/src/net/timeout_test.go
@@ -33,6 +33,7 @@ var dialTimeoutTests = []struct {
 }
 
 func TestDialTimeout(t *testing.T) {
+	// Cannot use t.Parallel - modifies global hooks.
 	origTestHookDialChannel := testHookDialChannel
 	defer func() { testHookDialChannel = origTestHookDialChannel }()
 	defer sw.Set(socktest.FilterConnect, nil)
@@ -110,6 +111,8 @@ var acceptTimeoutTests = []struct {
 }
 
 func TestAcceptTimeout(t *testing.T) {
+	t.Parallel()
+
 	switch runtime.GOOS {
 	case "plan9":
 		t.Skipf("not supported on %s", runtime.GOOS)
@@ -161,6 +164,8 @@ func TestAcceptTimeout(t *testing.T) {
 }
 
 func TestAcceptTimeoutMustReturn(t *testing.T) {
+	t.Parallel()
+
 	switch runtime.GOOS {
 	case "plan9":
 		t.Skipf("not supported on %s", runtime.GOOS)
@@ -205,6 +210,8 @@ func TestAcceptTimeoutMustReturn(t *testing.T) {
 }
 
 func TestAcceptTimeoutMustNotReturn(t *testing.T) {
+	t.Parallel()
+
 	switch runtime.GOOS {
 	case "plan9":
 		t.Skipf("not supported on %s", runtime.GOOS)
@@ -254,6 +261,8 @@ var readTimeoutTests = []struct {
 }
 
 func TestReadTimeout(t *testing.T) {
+	t.Parallel()
+
 	switch runtime.GOOS {
 	case "plan9":
 		t.Skipf("not supported on %s", runtime.GOOS)
@@ -313,6 +322,8 @@ func TestReadTimeout(t *testing.T) {
 }
 
 func TestReadTimeoutMustNotReturn(t *testing.T) {
+	t.Parallel()
+
 	switch runtime.GOOS {
 	case "plan9":
 		t.Skipf("not supported on %s", runtime.GOOS)
@@ -454,6 +465,8 @@ var writeTimeoutTests = []struct {
 }
 
 func TestWriteTimeout(t *testing.T) {
+	t.Parallel()
+
 	switch runtime.GOOS {
 	case "plan9":
 		t.Skipf("not supported on %s", runtime.GOOS)
@@ -500,6 +513,8 @@ func TestWriteTimeout(t *testing.T) {
 }
 
 func TestWriteTimeoutMustNotReturn(t *testing.T) {
+	t.Parallel()
+
 	switch runtime.GOOS {
 	case "plan9":
 		t.Skipf("not supported on %s", runtime.GOOS)
@@ -569,6 +584,8 @@ var writeToTimeoutTests = []struct {
 }
 
 func TestWriteToTimeout(t *testing.T) {
+	t.Parallel()
+
 	switch runtime.GOOS {
 	case "nacl", "plan9":
 		t.Skipf("not supported on %s", runtime.GOOS)
@@ -620,6 +637,8 @@ func TestWriteToTimeout(t *testing.T) {
 }
 
 func TestReadTimeoutFluctuation(t *testing.T) {
+	t.Parallel()
+
 	switch runtime.GOOS {
 	case "plan9":
 		t.Skipf("not supported on %s", runtime.GOOS)
@@ -656,6 +675,8 @@ func TestReadTimeoutFluctuation(t *testing.T) {
 }
 
 func TestReadFromTimeoutFluctuation(t *testing.T) {
+	t.Parallel()
+
 	switch runtime.GOOS {
 	case "plan9":
 		t.Skipf("not supported on %s", runtime.GOOS)
@@ -692,6 +713,8 @@ func TestReadFromTimeoutFluctuation(t *testing.T) {
 }
 
 func TestWriteTimeoutFluctuation(t *testing.T) {
+	t.Parallel()
+
 	switch runtime.GOOS {
 	case "plan9":
 		t.Skipf("not supported on %s", runtime.GOOS)
@@ -731,12 +754,27 @@ func TestWriteTimeoutFluctuation(t *testing.T) {
 	}
 }
 
+func TestVariousDeadlines(t *testing.T) {
+	t.Parallel()
+	testVariousDeadlines(t)
+}
+
 func TestVariousDeadlines1Proc(t *testing.T) {
-	testVariousDeadlines(t, 1)
+	// Cannot use t.Parallel - modifies global GOMAXPROCS.
+	if testing.Short() {
+		t.Skip("skipping in short mode")
+	}
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
+	testVariousDeadlines(t)
 }
 
 func TestVariousDeadlines4Proc(t *testing.T) {
-	testVariousDeadlines(t, 4)
+	// Cannot use t.Parallel - modifies global GOMAXPROCS.
+	if testing.Short() {
+		t.Skip("skipping in short mode")
+	}
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
+	testVariousDeadlines(t)
 }
 
 type neverEnding byte
@@ -748,14 +786,12 @@ func (b neverEnding) Read(p []byte) (int, error) {
 	return len(p), nil
 }
 
-func testVariousDeadlines(t *testing.T, maxProcs int) {
+func testVariousDeadlines(t *testing.T) {
 	switch runtime.GOOS {
 	case "plan9":
 		t.Skipf("not supported on %s", runtime.GOOS)
 	}
 
-	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs))
-
 	type result struct {
 		n   int64
 		err error
@@ -869,6 +905,8 @@ func testVariousDeadlines(t *testing.T, maxProcs int) {
 // TestReadWriteProlongedTimeout tests concurrent deadline
 // modification. Known to cause data races in the past.
 func TestReadWriteProlongedTimeout(t *testing.T) {
+	t.Parallel()
+
 	switch runtime.GOOS {
 	case "plan9":
 		t.Skipf("not supported on %s", runtime.GOOS)
@@ -947,6 +985,8 @@ func TestReadWriteProlongedTimeout(t *testing.T) {
 }
 
 func TestReadWriteDeadlineRace(t *testing.T) {
+	t.Parallel()
+
 	switch runtime.GOOS {
 	case "nacl", "plan9":
 		t.Skipf("not supported on %s", runtime.GOOS)
@@ -956,7 +996,6 @@ func TestReadWriteDeadlineRace(t *testing.T) {
 	if testing.Short() {
 		N = 50
 	}
-	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
 
 	ln, err := newLocalListener("tcp")
 	if err != nil {
diff --git a/src/net/udpsock_posix.go b/src/net/udpsock_posix.go
index 61868c4..932c6ce 100644
--- a/src/net/udpsock_posix.go
+++ b/src/net/udpsock_posix.go
@@ -189,7 +189,7 @@ func DialUDP(net string, laddr, raddr *UDPAddr) (*UDPConn, error) {
 }
 
 func dialUDP(net string, laddr, raddr *UDPAddr, deadline time.Time) (*UDPConn, error) {
-	fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_DGRAM, 0, "dial")
+	fd, err := internetSocket(net, laddr, raddr, deadline, syscall.SOCK_DGRAM, 0, "dial", noCancel)
 	if err != nil {
 		return nil, &OpError{Op: "dial", Net: net, Source: laddr.opAddr(), Addr: raddr.opAddr(), Err: err}
 	}
@@ -212,7 +212,7 @@ func ListenUDP(net string, laddr *UDPAddr) (*UDPConn, error) {
 	if laddr == nil {
 		laddr = &UDPAddr{}
 	}
-	fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_DGRAM, 0, "listen")
+	fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_DGRAM, 0, "listen", noCancel)
 	if err != nil {
 		return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr, Err: err}
 	}
@@ -239,7 +239,7 @@ func ListenMulticastUDP(network string, ifi *Interface, gaddr *UDPAddr) (*UDPCon
 	if gaddr == nil || gaddr.IP == nil {
 		return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: gaddr.opAddr(), Err: errMissingAddress}
 	}
-	fd, err := internetSocket(network, gaddr, nil, noDeadline, syscall.SOCK_DGRAM, 0, "listen")
+	fd, err := internetSocket(network, gaddr, nil, noDeadline, syscall.SOCK_DGRAM, 0, "listen", noCancel)
 	if err != nil {
 		return nil, &OpError{Op: "listen", Net: network, Source: nil, Addr: gaddr, Err: err}
 	}
diff --git a/src/net/unix_test.go b/src/net/unix_test.go
index 358ff31..f0c5830 100644
--- a/src/net/unix_test.go
+++ b/src/net/unix_test.go
@@ -405,6 +405,42 @@ func TestUnixgramConnLocalAndRemoteNames(t *testing.T) {
 	}
 }
 
+func TestUnixUnlink(t *testing.T) {
+	if !testableNetwork("unix") {
+		t.Skip("unix test")
+	}
+	name := testUnixAddr()
+	l, err := Listen("unix", name)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if _, err := os.Stat(name); err != nil {
+		t.Fatalf("cannot stat unix socket after ListenUnix: %v", err)
+	}
+	f, _ := l.(*UnixListener).File()
+	l1, err := FileListener(f)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if _, err := os.Stat(name); err != nil {
+		t.Fatalf("cannot stat unix socket after FileListener: %v", err)
+	}
+	if err := l1.Close(); err != nil {
+		t.Fatalf("closing file listener: %v", err)
+	}
+	if _, err := os.Stat(name); err != nil {
+		t.Fatalf("cannot stat unix socket after closing FileListener: %v", err)
+	}
+	f.Close()
+	if _, err := os.Stat(name); err != nil {
+		t.Fatalf("cannot stat unix socket after closing FileListener and fd: %v", err)
+	}
+	l.Close()
+	if _, err := os.Stat(name); err == nil {
+		t.Fatal("closing unix listener did not remove unix socket")
+	}
+}
+
 // forceGoDNS forces the resolver configuration to use the pure Go resolver
 // and returns a fixup function to restore the old settings.
 func forceGoDNS() func() {
@@ -421,11 +457,17 @@ func forceGoDNS() func() {
 }
 
 // forceCgoDNS forces the resolver configuration to use the cgo resolver
-// and returns true to indicate that it did so.
-// (On non-Unix systems forceCgoDNS returns false.)
-func forceCgoDNS() bool {
+// and returns a fixup function to restore the old settings.
+// (On non-Unix systems forceCgoDNS returns nil.)
+func forceCgoDNS() func() {
 	c := systemConf()
+	oldGo := c.netGo
+	oldCgo := c.netCgo
+	fixup := func() {
+		c.netGo = oldGo
+		c.netCgo = oldCgo
+	}
 	c.netGo = false
 	c.netCgo = true
-	return true
+	return fixup
 }
diff --git a/src/net/unixsock_posix.go b/src/net/unixsock_posix.go
index 351d9b3..fb2397e 100644
--- a/src/net/unixsock_posix.go
+++ b/src/net/unixsock_posix.go
@@ -42,7 +42,7 @@ func unixSocket(net string, laddr, raddr sockaddr, mode string, deadline time.Ti
 		return nil, errors.New("unknown mode: " + mode)
 	}
 
-	fd, err := socket(net, syscall.AF_UNIX, sotype, 0, false, laddr, raddr, deadline)
+	fd, err := socket(net, syscall.AF_UNIX, sotype, 0, false, laddr, raddr, deadline, noCancel)
 	if err != nil {
 		return nil, err
 	}
@@ -273,8 +273,9 @@ func dialUnix(net string, laddr, raddr *UnixAddr, deadline time.Time) (*UnixConn
 // typically use variables of type Listener instead of assuming Unix
 // domain sockets.
 type UnixListener struct {
-	fd   *netFD
-	path string
+	fd     *netFD
+	path   string
+	unlink bool
 }
 
 // ListenUnix announces on the Unix domain socket laddr and returns a
@@ -292,7 +293,7 @@ func ListenUnix(net string, laddr *UnixAddr) (*UnixListener, error) {
 	if err != nil {
 		return nil, &OpError{Op: "listen", Net: net, Source: nil, Addr: laddr.opAddr(), Err: err}
 	}
-	return &UnixListener{fd: fd, path: fd.laddr.String()}, nil
+	return &UnixListener{fd: fd, path: fd.laddr.String(), unlink: true}, nil
 }
 
 // AcceptUnix accepts the next incoming call and returns the new
@@ -335,7 +336,7 @@ func (l *UnixListener) Close() error {
 	// is at least compatible with the auto-remove
 	// sequence in ListenUnix.  It's only non-Go
 	// programs that can mess us up.
-	if l.path[0] != '@' {
+	if l.path[0] != '@' && l.unlink {
 		syscall.Unlink(l.path)
 	}
 	err := l.fd.Close()
diff --git a/src/net/url/url.go b/src/net/url/url.go
index 8ffad66..1a93e34 100644
--- a/src/net/url/url.go
+++ b/src/net/url/url.go
@@ -24,6 +24,24 @@ type Error struct {
 
 func (e *Error) Error() string { return e.Op + " " + e.URL + ": " + e.Err.Error() }
 
+type timeout interface {
+	Timeout() bool
+}
+
+func (e *Error) Timeout() bool {
+	t, ok := e.Err.(timeout)
+	return ok && t.Timeout()
+}
+
+type temporary interface {
+	Temporary() bool
+}
+
+func (e *Error) Temporary() bool {
+	t, ok := e.Err.(temporary)
+	return ok && t.Temporary()
+}
+
 func ishex(c byte) bool {
 	switch {
 	case '0' <= c && c <= '9':
@@ -53,6 +71,7 @@ type encoding int
 const (
 	encodePath encoding = 1 + iota
 	encodeHost
+	encodeZone
 	encodeUserPassword
 	encodeQueryComponent
 	encodeFragment
@@ -64,6 +83,12 @@ func (e EscapeError) Error() string {
 	return "invalid URL escape " + strconv.Quote(string(e))
 }
 
+type InvalidHostError string
+
+func (e InvalidHostError) Error() string {
+	return "invalid character " + strconv.Quote(string(e)) + " in host name"
+}
+
 // Return true if the specified character should be escaped when
 // appearing in a URL string, according to RFC 3986.
 //
@@ -75,14 +100,18 @@ func shouldEscape(c byte, mode encoding) bool {
 		return false
 	}
 
-	if mode == encodeHost {
+	if mode == encodeHost || mode == encodeZone {
 		// §3.2.2 Host allows
 		//	sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
 		// as part of reg-name.
 		// We add : because we include :port as part of host.
-		// We add [ ] because we include [ipv6]:port as part of host
+		// We add [ ] because we include [ipv6]:port as part of host.
+		// We add < > because they're the only characters left that
+		// we could possibly allow, and Parse will reject them if we
+		// escape them (because hosts can't use %-encoding for
+		// ASCII bytes).
 		switch c {
-		case '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=', ':', '[', ']':
+		case '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=', ':', '[', ']', '<', '>', '"':
 			return false
 		}
 	}
@@ -148,11 +177,36 @@ func unescape(s string, mode encoding) (string, error) {
 				}
 				return "", EscapeError(s)
 			}
+			// Per https://tools.ietf.org/html/rfc3986#page-21
+			// in the host component %-encoding can only be used
+			// for non-ASCII bytes.
+			// But https://tools.ietf.org/html/rfc6874#section-2
+			// introduces %25 being allowed to escape a percent sign
+			// in IPv6 scoped-address literals. Yay.
+			if mode == encodeHost && unhex(s[i+1]) < 8 && s[i:i+3] != "%25" {
+				return "", EscapeError(s[i : i+3])
+			}
+			if mode == encodeZone {
+				// RFC 6874 says basically "anything goes" for zone identifiers
+				// and that even non-ASCII can be redundantly escaped,
+				// but it seems prudent to restrict %-escaped bytes here to those
+				// that are valid host name bytes in their unescaped form.
+				// That is, you can use escaping in the zone identifier but not
+				// to introduce bytes you couldn't just write directly.
+				// But Windows puts spaces here! Yay.
+				v := unhex(s[i+1])<<4 | unhex(s[i+2])
+				if s[i:i+3] != "%25" && v != ' ' && shouldEscape(v, encodeHost) {
+					return "", EscapeError(s[i : i+3])
+				}
+			}
 			i += 3
 		case '+':
 			hasPlus = mode == encodeQueryComponent
 			i++
 		default:
+			if (mode == encodeHost || mode == encodeZone) && s[i] < 0x80 && shouldEscape(s[i], mode) {
+				return "", InvalidHostError(s[i : i+1])
+			}
 			i++
 		}
 	}
@@ -246,7 +300,7 @@ func escape(s string, mode encoding) string {
 // Go 1.5 introduced the RawPath field to hold the encoded form of Path.
 // The Parse function sets both Path and RawPath in the URL it returns,
 // and URL's String method uses RawPath if it is a valid encoding of Path,
-// by calling the EncodedPath method.
+// by calling the EscapedPath method.
 //
 // In earlier versions of Go, the more indirect workarounds were that an
 // HTTP server could consult req.RequestURI and an HTTP client could
@@ -431,7 +485,7 @@ func parse(rawurl string, viaRequest bool) (url *URL, err error) {
 		goto Error
 	}
 	// RawPath is a hint as to the encoding of Path to use
-	// in url.EncodedPath. If that method already gets the
+	// in url.EscapedPath. If that method already gets the
 	// right answer without RawPath, leave it empty.
 	// This will help make sure that people don't rely on it in general.
 	if url.EscapedPath() != rest && validEncodedPath(rest) {
@@ -478,14 +532,9 @@ func parseAuthority(authority string) (user *Userinfo, host string, err error) {
 // parseHost parses host as an authority without user
 // information. That is, as host[:port].
 func parseHost(host string) (string, error) {
-	litOrName := host
 	if strings.HasPrefix(host, "[") {
 		// Parse an IP-Literal in RFC 3986 and RFC 6874.
-		// E.g., "[fe80::1], "[fe80::1%25en0]"
-		//
-		// RFC 4007 defines "%" as a delimiter character in
-		// the textual representation of IPv6 addresses.
-		// Per RFC 6874, in URIs that "%" is encoded as "%25".
+		// E.g., "[fe80::1]", "[fe80::1%25en0]", "[fe80::1]:80".
 		i := strings.LastIndex(host, "]")
 		if i < 0 {
 			return "", errors.New("missing ']' in host")
@@ -494,29 +543,31 @@ func parseHost(host string) (string, error) {
 		if !validOptionalPort(colonPort) {
 			return "", fmt.Errorf("invalid port %q after host", colonPort)
 		}
-		// Parse a host subcomponent without a ZoneID in RFC
-		// 6874 because the ZoneID is allowed to use the
-		// percent encoded form.
-		j := strings.Index(host[:i], "%25")
-		if j < 0 {
-			litOrName = host[1:i]
-		} else {
-			litOrName = host[1:j]
+
+		// RFC 6874 defines that %25 (%-encoded percent) introduces
+		// the zone identifier, and the zone identifier can use basically
+		// any %-encoding it likes. That's different from the host, which
+		// can only %-encode non-ASCII bytes.
+		// We do impose some restrictions on the zone, to avoid stupidity
+		// like newlines.
+		zone := strings.Index(host[:i], "%25")
+		if zone >= 0 {
+			host1, err := unescape(host[:zone], encodeHost)
+			if err != nil {
+				return "", err
+			}
+			host2, err := unescape(host[zone:i], encodeZone)
+			if err != nil {
+				return "", err
+			}
+			host3, err := unescape(host[i:], encodeHost)
+			if err != nil {
+				return "", err
+			}
+			return host1 + host2 + host3, nil
 		}
 	}
 
-	// A URI containing an IP-Literal without a ZoneID or
-	// IPv4address in RFC 3986 and RFC 6847 must not be
-	// percent-encoded.
-	//
-	// A URI containing a DNS registered name in RFC 3986 is
-	// allowed to be percent-encoded, though we don't use it for
-	// now to avoid messing up with the gap between allowed
-	// characters in URI and allowed characters in DNS.
-	// See golang.org/issue/7991.
-	if strings.Contains(litOrName, "%") {
-		return "", errors.New("percent-encoded characters in host")
-	}
 	var err error
 	if host, err = unescape(host, encodeHost); err != nil {
 		return "", err
@@ -572,12 +623,12 @@ func validEncodedPath(s string) bool {
 }
 
 // validOptionalPort reports whether port is either an empty string
-// or matches /^:\d+$/
+// or matches /^:\d*$/
 func validOptionalPort(port string) bool {
 	if port == "" {
 		return true
 	}
-	if port[0] != ':' || len(port) == 1 {
+	if port[0] != ':' {
 		return false
 	}
 	for _, b := range port[1:] {
@@ -596,7 +647,7 @@ func validOptionalPort(port string) bool {
 //
 // If u.Opaque is non-empty, String uses the first form;
 // otherwise it uses the second form.
-// To obtain the path, String uses u.EncodedPath().
+// To obtain the path, String uses u.EscapedPath().
 //
 // In the second form, the following rules apply:
 //	- if u.Scheme is empty, scheme: is omitted.
diff --git a/src/net/url/url_test.go b/src/net/url/url_test.go
index ff6e9e4..d3f8487 100644
--- a/src/net/url/url_test.go
+++ b/src/net/url/url_test.go
@@ -6,6 +6,8 @@ package url
 
 import (
 	"fmt"
+	"io"
+	"net"
 	"reflect"
 	"strings"
 	"testing"
@@ -330,7 +332,7 @@ var urltests = []URLTest{
 		},
 		"",
 	},
-	// host subcomponent; IPv6 address with zone identifier in RFC 6847
+	// host subcomponent; IPv6 address with zone identifier in RFC 6874
 	{
 		"http://[fe80::1%25en0]/", // alphanum zone identifier
 		&URL{
@@ -340,7 +342,7 @@ var urltests = []URLTest{
 		},
 		"",
 	},
-	// host and port subcomponents; IPv6 address with zone identifier in RFC 6847
+	// host and port subcomponents; IPv6 address with zone identifier in RFC 6874
 	{
 		"http://[fe80::1%25en0]:8080/", // alphanum zone identifier
 		&URL{
@@ -350,7 +352,7 @@ var urltests = []URLTest{
 		},
 		"",
 	},
-	// host subcomponent; IPv6 address with zone identifier in RFC 6847
+	// host subcomponent; IPv6 address with zone identifier in RFC 6874
 	{
 		"http://[fe80::1%25%65%6e%301-._~]/", // percent-encoded+unreserved zone identifier
 		&URL{
@@ -360,7 +362,7 @@ var urltests = []URLTest{
 		},
 		"http://[fe80::1%25en01-._~]/",
 	},
-	// host and port subcomponents; IPv6 address with zone identifier in RFC 6847
+	// host and port subcomponents; IPv6 address with zone identifier in RFC 6874
 	{
 		"http://[fe80::1%25%65%6e%301-._~]:8080/", // percent-encoded+unreserved zone identifier
 		&URL{
@@ -424,6 +426,122 @@ var urltests = []URLTest{
 		},
 		"",
 	},
+	// golang.org/issue/12200 (colon with empty port)
+	{
+		"http://192.168.0.2:8080/foo",
+		&URL{
+			Scheme: "http",
+			Host:   "192.168.0.2:8080",
+			Path:   "/foo",
+		},
+		"",
+	},
+	{
+		"http://192.168.0.2:/foo",
+		&URL{
+			Scheme: "http",
+			Host:   "192.168.0.2:",
+			Path:   "/foo",
+		},
+		"",
+	},
+	{
+		// Malformed IPv6 but still accepted.
+		"http://2b01:e34:ef40:7730:8e70:5aff:fefe:edac:8080/foo",
+		&URL{
+			Scheme: "http",
+			Host:   "2b01:e34:ef40:7730:8e70:5aff:fefe:edac:8080",
+			Path:   "/foo",
+		},
+		"",
+	},
+	{
+		// Malformed IPv6 but still accepted.
+		"http://2b01:e34:ef40:7730:8e70:5aff:fefe:edac:/foo",
+		&URL{
+			Scheme: "http",
+			Host:   "2b01:e34:ef40:7730:8e70:5aff:fefe:edac:",
+			Path:   "/foo",
+		},
+		"",
+	},
+	{
+		"http://[2b01:e34:ef40:7730:8e70:5aff:fefe:edac]:8080/foo",
+		&URL{
+			Scheme: "http",
+			Host:   "[2b01:e34:ef40:7730:8e70:5aff:fefe:edac]:8080",
+			Path:   "/foo",
+		},
+		"",
+	},
+	{
+		"http://[2b01:e34:ef40:7730:8e70:5aff:fefe:edac]:/foo",
+		&URL{
+			Scheme: "http",
+			Host:   "[2b01:e34:ef40:7730:8e70:5aff:fefe:edac]:",
+			Path:   "/foo",
+		},
+		"",
+	},
+	// golang.org/issue/7991 and golang.org/issue/12719 (non-ascii %-encoded in host)
+	{
+		"http://hello.世界.com/foo",
+		&URL{
+			Scheme: "http",
+			Host:   "hello.世界.com",
+			Path:   "/foo",
+		},
+		"http://hello.%E4%B8%96%E7%95%8C.com/foo",
+	},
+	{
+		"http://hello.%e4%b8%96%e7%95%8c.com/foo",
+		&URL{
+			Scheme: "http",
+			Host:   "hello.世界.com",
+			Path:   "/foo",
+		},
+		"http://hello.%E4%B8%96%E7%95%8C.com/foo",
+	},
+	{
+		"http://hello.%E4%B8%96%E7%95%8C.com/foo",
+		&URL{
+			Scheme: "http",
+			Host:   "hello.世界.com",
+			Path:   "/foo",
+		},
+		"",
+	},
+	// golang.org/issue/10433 (path beginning with //)
+	{
+		"http://example.com//foo",
+		&URL{
+			Scheme: "http",
+			Host:   "example.com",
+			Path:   "//foo",
+		},
+		"",
+	},
+	// test that we can reparse the host names we accept.
+	{
+		"myscheme://authority<\"hi\">/foo",
+		&URL{
+			Scheme: "myscheme",
+			Host:   "authority<\"hi\">",
+			Path:   "/foo",
+		},
+		"",
+	},
+	// spaces in hosts are disallowed but escaped spaces in IPv6 scope IDs are grudgingly OK.
+	// This happens on Windows.
+	// golang.org/issue/14002
+	{
+		"tcp://[2020::2020:20:2020:2020%25Windows%20Loves%20Spaces]:2020",
+		&URL{
+			Scheme: "tcp",
+			Host:   "[2020::2020:20:2020:2020%Windows Loves Spaces]:2020",
+		},
+		"",
+	},
 }
 
 // more useful string for debugging than fmt's struct printer
@@ -1091,6 +1209,14 @@ var requritests = []RequestURITest{
 		},
 		"opaque?q=go+language",
 	},
+	{
+		&URL{
+			Scheme: "http",
+			Host:   "example.com",
+			Path:   "//foo",
+		},
+		"//foo",
+	},
 }
 
 func TestRequestURI(t *testing.T) {
@@ -1124,16 +1250,17 @@ func TestParseAuthority(t *testing.T) {
 		{"http://[::1]a", true},
 		{"http://[::1]%23", true},
 		{"http://[::1%25en0]", false},     // valid zone id
-		{"http://[::1]:", true},           // colon, but no port
-		{"http://[::1]:%38%30", true},     // no hex in port
-		{"http://[::1%25%10]", false},     // TODO: reject the %10 after the valid zone %25 separator?
+		{"http://[::1]:", false},          // colon, but no port OK
+		{"http://[::1]:%38%30", true},     // not allowed: % encoding only for non-ASCII
+		{"http://[::1%25%41]", false},     // RFC 6874 allows over-escaping in zone
 		{"http://[%10::1]", true},         // no %xx escapes in IP address
 		{"http://[::1]/%48", false},       // %xx in path is fine
-		{"http://%41:8080/", true},        // TODO: arguably we should accept reg-name with %xx
+		{"http://%41:8080/", true},        // not allowed: % encoding only for non-ASCII
 		{"mysql://x@y(z:123)/foo", false}, // golang.org/issue/12023
 		{"mysql://x@y(1.2.3.4:123)/foo", false},
 		{"mysql://x@y([2001:db8::1]:123)/foo", false},
 		{"http://[]%20%48%54%54%50%2f%31%2e%31%0a%4d%79%48%65%61%64%65%72%3a%20%31%32%33%0a%0a/", true}, // golang.org/issue/11208
+		{"http://a b.com/", true},                                                                       // no space in host name please
 	}
 	for _, tt := range tests {
 		u, err := Parse(tt.in)
@@ -1229,3 +1356,84 @@ func TestShouldEscape(t *testing.T) {
 		}
 	}
 }
+
+type timeoutError struct {
+	timeout bool
+}
+
+func (e *timeoutError) Error() string { return "timeout error" }
+func (e *timeoutError) Timeout() bool { return e.timeout }
+
+type temporaryError struct {
+	temporary bool
+}
+
+func (e *temporaryError) Error() string   { return "temporary error" }
+func (e *temporaryError) Temporary() bool { return e.temporary }
+
+type timeoutTemporaryError struct {
+	timeoutError
+	temporaryError
+}
+
+func (e *timeoutTemporaryError) Error() string { return "timeout/temporary error" }
+
+var netErrorTests = []struct {
+	err       error
+	timeout   bool
+	temporary bool
+}{{
+	err:       &Error{"Get", "http://google.com/", &timeoutError{timeout: true}},
+	timeout:   true,
+	temporary: false,
+}, {
+	err:       &Error{"Get", "http://google.com/", &timeoutError{timeout: false}},
+	timeout:   false,
+	temporary: false,
+}, {
+	err:       &Error{"Get", "http://google.com/", &temporaryError{temporary: true}},
+	timeout:   false,
+	temporary: true,
+}, {
+	err:       &Error{"Get", "http://google.com/", &temporaryError{temporary: false}},
+	timeout:   false,
+	temporary: false,
+}, {
+	err:       &Error{"Get", "http://google.com/", &timeoutTemporaryError{timeoutError{timeout: true}, temporaryError{temporary: true}}},
+	timeout:   true,
+	temporary: true,
+}, {
+	err:       &Error{"Get", "http://google.com/", &timeoutTemporaryError{timeoutError{timeout: false}, temporaryError{temporary: true}}},
+	timeout:   false,
+	temporary: true,
+}, {
+	err:       &Error{"Get", "http://google.com/", &timeoutTemporaryError{timeoutError{timeout: true}, temporaryError{temporary: false}}},
+	timeout:   true,
+	temporary: false,
+}, {
+	err:       &Error{"Get", "http://google.com/", &timeoutTemporaryError{timeoutError{timeout: false}, temporaryError{temporary: false}}},
+	timeout:   false,
+	temporary: false,
+}, {
+	err:       &Error{"Get", "http://google.com/", io.EOF},
+	timeout:   false,
+	temporary: false,
+}}
+
+// Test that url.Error implements net.Error and that it forwards
+func TestURLErrorImplementsNetError(t *testing.T) {
+	for i, tt := range netErrorTests {
+		err, ok := tt.err.(net.Error)
+		if !ok {
+			t.Errorf("%d: %T does not implement net.Error", i+1, tt.err)
+			continue
+		}
+		if err.Timeout() != tt.timeout {
+			t.Errorf("%d: err.Timeout(): want %v, have %v", i+1, tt.timeout, err.Timeout())
+			continue
+		}
+		if err.Temporary() != tt.temporary {
+			t.Errorf("%d: err.Temporary(): want %v, have %v", i+1, tt.temporary, err.Temporary())
+		}
+	}
+}
diff --git a/src/os/doc.go b/src/os/doc.go
index 389a8eb..869a28a 100644
--- a/src/os/doc.go
+++ b/src/os/doc.go
@@ -7,9 +7,13 @@ package os
 import "time"
 
 // FindProcess looks for a running process by its pid.
+//
 // The Process it returns can be used to obtain information
 // about the underlying operating system process.
-func FindProcess(pid int) (p *Process, err error) {
+//
+// On Unix systems, FindProcess always succeeds and returns a Process
+// for the given pid, regardless of whether the process exists.
+func FindProcess(pid int) (*Process, error) {
 	return findProcess(pid)
 }
 
diff --git a/src/os/error.go b/src/os/error.go
index 8810e69..e26ce27 100644
--- a/src/os/error.go
+++ b/src/os/error.go
@@ -10,7 +10,7 @@ import (
 
 // Portable analogs of some common system call errors.
 var (
-	ErrInvalid    = errors.New("invalid argument")
+	ErrInvalid    = errors.New("invalid argument") // methods on File will return this error when the receiver is nil
 	ErrPermission = errors.New("permission denied")
 	ErrExist      = errors.New("file already exists")
 	ErrNotExist   = errors.New("file does not exist")
diff --git a/src/os/error_plan9.go b/src/os/error_plan9.go
index 001cdfc..2dc6b39 100644
--- a/src/os/error_plan9.go
+++ b/src/os/error_plan9.go
@@ -12,6 +12,8 @@ func isExist(err error) bool {
 		err = pe.Err
 	case *LinkError:
 		err = pe.Err
+	case *SyscallError:
+		err = pe.Err
 	}
 	return contains(err.Error(), " exists")
 }
@@ -24,6 +26,8 @@ func isNotExist(err error) bool {
 		err = pe.Err
 	case *LinkError:
 		err = pe.Err
+	case *SyscallError:
+		err = pe.Err
 	}
 	return contains(err.Error(), "does not exist") || contains(err.Error(), "not found") ||
 		contains(err.Error(), "has been removed") || contains(err.Error(), "no parent")
@@ -37,6 +41,8 @@ func isPermission(err error) bool {
 		err = pe.Err
 	case *LinkError:
 		err = pe.Err
+	case *SyscallError:
+		err = pe.Err
 	}
 	return contains(err.Error(), "permission denied")
 }
diff --git a/src/os/error_test.go b/src/os/error_test.go
index 02ed235..5477e7e 100644
--- a/src/os/error_test.go
+++ b/src/os/error_test.go
@@ -93,6 +93,8 @@ var isExistTests = []struct {
 	{&os.LinkError{Err: os.ErrPermission}, false, false},
 	{&os.LinkError{Err: os.ErrExist}, true, false},
 	{&os.LinkError{Err: os.ErrNotExist}, false, true},
+	{&os.SyscallError{Err: os.ErrNotExist}, false, true},
+	{&os.SyscallError{Err: os.ErrExist}, true, false},
 	{nil, false, false},
 }
 
@@ -107,6 +109,23 @@ func TestIsExist(t *testing.T) {
 	}
 }
 
+var isPermissionTests = []struct {
+	err  error
+	want bool
+}{
+	{nil, false},
+	{&os.PathError{Err: os.ErrPermission}, true},
+	{&os.SyscallError{Err: os.ErrPermission}, true},
+}
+
+func TestIsPermission(t *testing.T) {
+	for _, tt := range isPermissionTests {
+		if got := os.IsPermission(tt.err); got != tt.want {
+			t.Errorf("os.IsPermission(%#v) = %v; want %v", tt.err, got, tt.want)
+		}
+	}
+}
+
 func TestErrPathNUL(t *testing.T) {
 	f, err := ioutil.TempFile("", "_Go_ErrPathNUL\x00")
 	if err == nil {
diff --git a/src/os/error_unix.go b/src/os/error_unix.go
index f2aabbb..c600227 100644
--- a/src/os/error_unix.go
+++ b/src/os/error_unix.go
@@ -16,6 +16,8 @@ func isExist(err error) bool {
 		err = pe.Err
 	case *LinkError:
 		err = pe.Err
+	case *SyscallError:
+		err = pe.Err
 	}
 	return err == syscall.EEXIST || err == ErrExist
 }
@@ -28,6 +30,8 @@ func isNotExist(err error) bool {
 		err = pe.Err
 	case *LinkError:
 		err = pe.Err
+	case *SyscallError:
+		err = pe.Err
 	}
 	return err == syscall.ENOENT || err == ErrNotExist
 }
@@ -40,6 +44,8 @@ func isPermission(err error) bool {
 		err = pe.Err
 	case *LinkError:
 		err = pe.Err
+	case *SyscallError:
+		err = pe.Err
 	}
 	return err == syscall.EACCES || err == syscall.EPERM || err == ErrPermission
 }
diff --git a/src/os/error_windows.go b/src/os/error_windows.go
index 83db6c0..2c1c39c 100644
--- a/src/os/error_windows.go
+++ b/src/os/error_windows.go
@@ -14,11 +14,15 @@ func isExist(err error) bool {
 		err = pe.Err
 	case *LinkError:
 		err = pe.Err
+	case *SyscallError:
+		err = pe.Err
 	}
 	return err == syscall.ERROR_ALREADY_EXISTS ||
 		err == syscall.ERROR_FILE_EXISTS || err == ErrExist
 }
 
+const _ERROR_BAD_NETPATH = syscall.Errno(53)
+
 func isNotExist(err error) bool {
 	switch pe := err.(type) {
 	case nil:
@@ -27,8 +31,11 @@ func isNotExist(err error) bool {
 		err = pe.Err
 	case *LinkError:
 		err = pe.Err
+	case *SyscallError:
+		err = pe.Err
 	}
 	return err == syscall.ERROR_FILE_NOT_FOUND ||
+		err == _ERROR_BAD_NETPATH ||
 		err == syscall.ERROR_PATH_NOT_FOUND || err == ErrNotExist
 }
 
@@ -40,6 +47,8 @@ func isPermission(err error) bool {
 		err = pe.Err
 	case *LinkError:
 		err = pe.Err
+	case *SyscallError:
+		err = pe.Err
 	}
 	return err == syscall.ERROR_ACCESS_DENIED || err == ErrPermission
 }
diff --git a/src/os/exec/exec.go b/src/os/exec/exec.go
index 8a84e26..340ebd4 100644
--- a/src/os/exec/exec.go
+++ b/src/os/exec/exec.go
@@ -5,6 +5,10 @@
 // Package exec runs external commands. It wraps os.StartProcess to make it
 // easier to remap stdin and stdout, connect I/O with pipes, and do other
 // adjustments.
+//
+// Note that the examples in this package assume a Unix system.
+// They may not run on Windows, and they do not run in the Go Playground
+// used by golang.org and godoc.org.
 package exec
 
 import (
@@ -347,6 +351,18 @@ func (c *Cmd) Start() error {
 // An ExitError reports an unsuccessful exit by a command.
 type ExitError struct {
 	*os.ProcessState
+
+	// Stderr holds a subset of the standard error output from the
+	// Cmd.Output method if standard error was not otherwise being
+	// collected.
+	//
+	// If the error output is long, Stderr may contain only a prefix
+	// and suffix of the output, with the middle replaced with
+	// text about the number of omitted bytes.
+	//
+	// Stderr is provided for debugging, for inclusion in error messages.
+	// Users with other needs should redirect Cmd.Stderr as needed.
+	Stderr []byte
 }
 
 func (e *ExitError) Error() string {
@@ -392,21 +408,34 @@ func (c *Cmd) Wait() error {
 	if err != nil {
 		return err
 	} else if !state.Success() {
-		return &ExitError{state}
+		return &ExitError{ProcessState: state}
 	}
 
 	return copyError
 }
 
 // Output runs the command and returns its standard output.
+// Any returned error will usually be of type *ExitError.
+// If c.Stderr was nil, Output populates ExitError.Stderr.
 func (c *Cmd) Output() ([]byte, error) {
 	if c.Stdout != nil {
 		return nil, errors.New("exec: Stdout already set")
 	}
-	var b bytes.Buffer
-	c.Stdout = &b
+	var stdout bytes.Buffer
+	c.Stdout = &stdout
+
+	captureErr := c.Stderr == nil
+	if captureErr {
+		c.Stderr = &prefixSuffixSaver{N: 32 << 10}
+	}
+
 	err := c.Run()
-	return b.Bytes(), err
+	if err != nil && captureErr {
+		if ee, ok := err.(*ExitError); ok {
+			ee.Stderr = c.Stderr.(*prefixSuffixSaver).Bytes()
+		}
+	}
+	return stdout.Bytes(), err
 }
 
 // CombinedOutput runs the command and returns its combined standard
@@ -514,3 +543,80 @@ func (c *Cmd) StderrPipe() (io.ReadCloser, error) {
 	c.closeAfterWait = append(c.closeAfterWait, pr)
 	return pr, nil
 }
+
+// prefixSuffixSaver is an io.Writer which retains the first N bytes
+// and the last N bytes written to it. The Bytes() methods reconstructs
+// it with a pretty error message.
+type prefixSuffixSaver struct {
+	N         int // max size of prefix or suffix
+	prefix    []byte
+	suffix    []byte // ring buffer once len(suffix) == N
+	suffixOff int    // offset to write into suffix
+	skipped   int64
+
+	// TODO(bradfitz): we could keep one large []byte and use part of it for
+	// the prefix, reserve space for the '... Omitting N bytes ...' message,
+	// then the ring buffer suffix, and just rearrange the ring buffer
+	// suffix when Bytes() is called, but it doesn't seem worth it for
+	// now just for error messages. It's only ~64KB anyway.
+}
+
+func (w *prefixSuffixSaver) Write(p []byte) (n int, err error) {
+	lenp := len(p)
+	p = w.fill(&w.prefix, p)
+
+	// Only keep the last w.N bytes of suffix data.
+	if overage := len(p) - w.N; overage > 0 {
+		p = p[overage:]
+		w.skipped += int64(overage)
+	}
+	p = w.fill(&w.suffix, p)
+
+	// w.suffix is full now if p is non-empty. Overwrite it in a circle.
+	for len(p) > 0 { // 0, 1, or 2 iterations.
+		n := copy(w.suffix[w.suffixOff:], p)
+		p = p[n:]
+		w.skipped += int64(n)
+		w.suffixOff += n
+		if w.suffixOff == w.N {
+			w.suffixOff = 0
+		}
+	}
+	return lenp, nil
+}
+
+// fill appends up to len(p) bytes of p to *dst, such that *dst does not
+// grow larger than w.N. It returns the un-appended suffix of p.
+func (w *prefixSuffixSaver) fill(dst *[]byte, p []byte) (pRemain []byte) {
+	if remain := w.N - len(*dst); remain > 0 {
+		add := minInt(len(p), remain)
+		*dst = append(*dst, p[:add]...)
+		p = p[add:]
+	}
+	return p
+}
+
+func (w *prefixSuffixSaver) Bytes() []byte {
+	if w.suffix == nil {
+		return w.prefix
+	}
+	if w.skipped == 0 {
+		return append(w.prefix, w.suffix...)
+	}
+	var buf bytes.Buffer
+	buf.Grow(len(w.prefix) + len(w.suffix) + 50)
+	buf.Write(w.prefix)
+	buf.WriteString("\n... omitting ")
+	buf.WriteString(strconv.FormatInt(w.skipped, 10))
+	buf.WriteString(" bytes ...\n")
+	buf.Write(w.suffix[w.suffixOff:])
+	buf.Write(w.suffix[:w.suffixOff])
+	return buf.Bytes()
+}
+
+func minInt(a, b int) int {
+	if a < b {
+		return a
+	}
+	return b
+}
diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go
index 28be21c..52b4724 100644
--- a/src/os/exec/exec_test.go
+++ b/src/os/exec/exec_test.go
@@ -760,6 +760,9 @@ func TestHelperProcess(*testing.T) {
 		}
 		fmt.Print(p)
 		os.Exit(0)
+	case "stderrfail":
+		fmt.Fprintf(os.Stderr, "some stderr text\n")
+		os.Exit(1)
 	default:
 		fmt.Fprintf(os.Stderr, "Unknown command %q\n", cmd)
 		os.Exit(2)
@@ -816,3 +819,19 @@ func TestClosePipeOnCopyError(t *testing.T) {
 		t.Fatalf("yes got stuck writing to bad writer")
 	}
 }
+
+func TestOutputStderrCapture(t *testing.T) {
+	testenv.MustHaveExec(t)
+
+	cmd := helperCommand(t, "stderrfail")
+	_, err := cmd.Output()
+	ee, ok := err.(*exec.ExitError)
+	if !ok {
+		t.Fatalf("Output error type = %T; want ExitError", err)
+	}
+	got := string(ee.Stderr)
+	want := "some stderr text\n"
+	if got != want {
+		t.Errorf("ExitError.Stderr = %q; want %q", got, want)
+	}
+}
diff --git a/src/os/exec/internal_test.go b/src/os/exec/internal_test.go
new file mode 100644
index 0000000..68d517f
--- /dev/null
+++ b/src/os/exec/internal_test.go
@@ -0,0 +1,61 @@
+// Copyright 2015 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 exec
+
+import (
+	"io"
+	"testing"
+)
+
+func TestPrefixSuffixSaver(t *testing.T) {
+	tests := []struct {
+		N      int
+		writes []string
+		want   string
+	}{
+		{
+			N:      2,
+			writes: nil,
+			want:   "",
+		},
+		{
+			N:      2,
+			writes: []string{"a"},
+			want:   "a",
+		},
+		{
+			N:      2,
+			writes: []string{"abc", "d"},
+			want:   "abcd",
+		},
+		{
+			N:      2,
+			writes: []string{"abc", "d", "e"},
+			want:   "ab\n... omitting 1 bytes ...\nde",
+		},
+		{
+			N:      2,
+			writes: []string{"ab______________________yz"},
+			want:   "ab\n... omitting 22 bytes ...\nyz",
+		},
+		{
+			N:      2,
+			writes: []string{"ab_______________________y", "z"},
+			want:   "ab\n... omitting 23 bytes ...\nyz",
+		},
+	}
+	for i, tt := range tests {
+		w := &prefixSuffixSaver{N: tt.N}
+		for _, s := range tt.writes {
+			n, err := io.WriteString(w, s)
+			if err != nil || n != len(s) {
+				t.Errorf("%d. WriteString(%q) = %v, %v; want %v, %v", i, s, n, err, len(s), nil)
+			}
+		}
+		if got := string(w.Bytes()); got != tt.want {
+			t.Errorf("%d. Bytes = %q; want %q", i, got, tt.want)
+		}
+	}
+}
diff --git a/src/os/file.go b/src/os/file.go
index 8c0e3ff..4f8e3f3 100644
--- a/src/os/file.go
+++ b/src/os/file.go
@@ -52,8 +52,8 @@ var (
 	Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
 )
 
-// Flags to Open wrapping those of the underlying system. Not all flags
-// may be implemented on a given system.
+// Flags to OpenFile wrapping those of the underlying system. Not all
+// flags may be implemented on a given system.
 const (
 	O_RDONLY int = syscall.O_RDONLY // open the file read-only.
 	O_WRONLY int = syscall.O_WRONLY // open the file write-only.
@@ -93,9 +93,6 @@ func (f *File) Read(b []byte) (n int, err error) {
 		return 0, ErrInvalid
 	}
 	n, e := f.read(b)
-	if n < 0 {
-		n = 0
-	}
 	if n == 0 && len(b) > 0 && e == nil {
 		return 0, io.EOF
 	}
@@ -176,6 +173,7 @@ func (f *File) WriteAt(b []byte, off int64) (n int, err error) {
 // according to whence: 0 means relative to the origin of the file, 1 means
 // relative to the current offset, and 2 means relative to the end.
 // It returns the new offset and an error, if any.
+// The behavior of Seek on a file opened with O_APPEND is not specified.
 func (f *File) Seek(offset int64, whence int) (ret int64, err error) {
 	if f == nil {
 		return 0, ErrInvalid
@@ -258,7 +256,9 @@ func Create(name string) (*File, error) {
 // lstat is overridden in tests.
 var lstat = Lstat
 
-// Rename renames (moves) a file. OS-specific restrictions might apply.
+// Rename renames (moves) oldpath to newpath.
+// If newpath already exists, Rename replaces it.
+// OS-specific restrictions may apply when oldpath and newpath are in different directories.
 // If there is an error, it will be of type *LinkError.
 func Rename(oldpath, newpath string) error {
 	return rename(oldpath, newpath)
diff --git a/src/os/file_plan9.go b/src/os/file_plan9.go
index 085ebc4..c83fa02 100644
--- a/src/os/file_plan9.go
+++ b/src/os/file_plan9.go
@@ -339,7 +339,9 @@ func rename(oldname, newname string) error {
 
 	// If newname still contains slashes after removing the oldname
 	// prefix, the rename is cross-directory and must be rejected.
-	// This case is caught by d.Marshal below.
+	if lastIndex(newname, '/') >= 0 {
+		return &LinkError{"rename", oldname, newname, ErrInvalid}
+	}
 
 	var d syscall.Dir
 
@@ -351,6 +353,13 @@ func rename(oldname, newname string) error {
 	if err != nil {
 		return &LinkError{"rename", oldname, newname, err}
 	}
+
+	// If newname already exists and is not a directory, rename replaces it.
+	f, err := Stat(dirname + newname)
+	if err == nil && !f.IsDir() {
+		Remove(dirname + newname)
+	}
+
 	if err = syscall.Wstat(oldname, buf[:n]); err != nil {
 		return &LinkError{"rename", oldname, newname, err}
 	}
diff --git a/src/os/file_unix.go b/src/os/file_unix.go
index 0677707..05d94f6 100644
--- a/src/os/file_unix.go
+++ b/src/os/file_unix.go
@@ -8,10 +8,13 @@ package os
 
 import (
 	"runtime"
-	"sync/atomic"
 	"syscall"
 )
 
+func sameFile(fs1, fs2 *fileStat) bool {
+	return fs1.sys.Dev == fs2.sys.Dev && fs1.sys.Ino == fs2.sys.Ino
+}
+
 func rename(oldname, newname string) error {
 	e := syscall.Rename(oldname, newname)
 	if e != nil {
@@ -33,7 +36,6 @@ type file struct {
 	fd      int
 	name    string
 	dirinfo *dirInfo // nil unless directory being read
-	nepipe  int32    // number of consecutive EPIPE in Write
 }
 
 // Fd returns the integer Unix file descriptor referencing the open file.
@@ -63,13 +65,12 @@ type dirInfo struct {
 	bufp int    // location of next record in buf.
 }
 
+// epipecheck raises SIGPIPE if we get an EPIPE error on standard
+// output or standard error. See the SIGPIPE docs in os/signal, and
+// issue 11845.
 func epipecheck(file *File, e error) {
-	if e == syscall.EPIPE {
-		if atomic.AddInt32(&file.nepipe, 1) >= 10 {
-			sigpipe()
-		}
-	} else {
-		atomic.StoreInt32(&file.nepipe, 0)
+	if e == syscall.EPIPE && (file.fd == 1 || file.fd == 2) {
+		sigpipe()
 	}
 }
 
@@ -90,8 +91,21 @@ func OpenFile(name string, flag int, perm FileMode) (*File, error) {
 		}
 	}
 
-	r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm))
-	if e != nil {
+	var r int
+	for {
+		var e error
+		r, e = syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm))
+		if e == nil {
+			break
+		}
+
+		// On OS X, sigaction(2) doesn't guarantee that SA_RESTART will cause
+		// open(2) to be restarted for regular files. This is easy to reproduce on
+		// fuse file systems (see http://golang.org/issue/11180).
+		if runtime.GOOS == "darwin" && e == syscall.EINTR {
+			continue
+		}
+
 		return nil, &PathError{"open", name, e}
 	}
 
@@ -139,23 +153,25 @@ func (f *File) Stat() (FileInfo, error) {
 	if f == nil {
 		return nil, ErrInvalid
 	}
-	var stat syscall.Stat_t
-	err := syscall.Fstat(f.fd, &stat)
+	var fs fileStat
+	err := syscall.Fstat(f.fd, &fs.sys)
 	if err != nil {
 		return nil, &PathError{"stat", f.name, err}
 	}
-	return fileInfoFromStat(&stat, f.name), nil
+	fillFileStatFromSys(&fs, f.name)
+	return &fs, nil
 }
 
 // Stat returns a FileInfo describing the named file.
 // If there is an error, it will be of type *PathError.
 func Stat(name string) (FileInfo, error) {
-	var stat syscall.Stat_t
-	err := syscall.Stat(name, &stat)
+	var fs fileStat
+	err := syscall.Stat(name, &fs.sys)
 	if err != nil {
 		return nil, &PathError{"stat", name, err}
 	}
-	return fileInfoFromStat(&stat, name), nil
+	fillFileStatFromSys(&fs, name)
+	return &fs, nil
 }
 
 // Lstat returns a FileInfo describing the named file.
@@ -163,12 +179,13 @@ func Stat(name string) (FileInfo, error) {
 // describes the symbolic link.  Lstat makes no attempt to follow the link.
 // If there is an error, it will be of type *PathError.
 func Lstat(name string) (FileInfo, error) {
-	var stat syscall.Stat_t
-	err := syscall.Lstat(name, &stat)
+	var fs fileStat
+	err := syscall.Lstat(name, &fs.sys)
 	if err != nil {
 		return nil, &PathError{"lstat", name, err}
 	}
-	return fileInfoFromStat(&stat, name), nil
+	fillFileStatFromSys(&fs, name)
+	return &fs, nil
 }
 
 func (f *File) readdir(n int) (fi []FileInfo, err error) {
diff --git a/src/os/file_windows.go b/src/os/file_windows.go
index 89b1d27..aa8c05c 100644
--- a/src/os/file_windows.go
+++ b/src/os/file_windows.go
@@ -90,7 +90,13 @@ func openFile(name string, flag int, perm FileMode) (file *File, err error) {
 }
 
 func openDir(name string) (file *File, err error) {
-	maskp, e := syscall.UTF16PtrFromString(name + `\*`)
+	var mask string
+	if len(name) == 2 && name[1] == ':' { // it is a drive letter, like C:
+		mask = name + `*`
+	} else {
+		mask = name + `\*`
+	}
+	maskp, e := syscall.UTF16PtrFromString(mask)
 	if e != nil {
 		return nil, e
 	}
@@ -257,24 +263,37 @@ func (f *File) readConsole(b []byte) (n int, err error) {
 		return 0, nil
 	}
 	if len(f.readbuf) == 0 {
-		// syscall.ReadConsole seems to fail, if given large buffer.
-		// So limit the buffer to 16000 characters.
 		numBytes := len(b)
-		if numBytes > 16000 {
-			numBytes = 16000
-		}
-		// get more input data from os
-		wchars := make([]uint16, numBytes)
-		var p *uint16
-		if len(b) > 0 {
-			p = &wchars[0]
+		// Windows  can't read bytes over max of int16.
+		// Some versions of Windows can read even less.
+		// See golang.org/issue/13697.
+		if numBytes > 10000 {
+			numBytes = 10000
 		}
-		var nw uint32
-		err := syscall.ReadConsole(f.fd, p, uint32(len(wchars)), &nw, nil)
+		mbytes := make([]byte, numBytes)
+		var nmb uint32
+		err := syscall.ReadFile(f.fd, mbytes, &nmb, nil)
 		if err != nil {
 			return 0, err
 		}
-		f.readbuf = utf16.Decode(wchars[:nw])
+		if nmb > 0 {
+			var pmb *byte
+			if len(b) > 0 {
+				pmb = &mbytes[0]
+			}
+			acp := windows.GetACP()
+			nwc, err := windows.MultiByteToWideChar(acp, 2, pmb, int32(nmb), nil, 0)
+			if err != nil {
+				return 0, err
+			}
+			wchars := make([]uint16, nwc)
+			pwc := &wchars[0]
+			nwc, err = windows.MultiByteToWideChar(acp, 2, pmb, int32(nmb), pwc, int32(nwc))
+			if err != nil {
+				return 0, err
+			}
+			f.readbuf = utf16.Decode(wchars[:nwc])
+		}
 	}
 	for i, r := range f.readbuf {
 		if utf8.RuneLen(r) > len(b) {
diff --git a/src/os/os_test.go b/src/os/os_test.go
index 6b72674..945724b 100644
--- a/src/os/os_test.go
+++ b/src/os/os_test.go
@@ -47,10 +47,10 @@ var sysdir = func() *sysDir {
 	switch runtime.GOOS {
 	case "android":
 		return &sysDir{
-			"/system/etc",
+			"/system/framework",
 			[]string{
-				"audio_policy.conf",
-				"system_fonts.xml",
+				"ext.jar",
+				"framework.jar",
 			},
 		}
 	case "darwin":
@@ -296,6 +296,48 @@ func TestReaddir(t *testing.T) {
 	testReaddir(sysdir.name, sysdir.files, t)
 }
 
+func benchmarkReaddirname(path string, b *testing.B) {
+	var nentries int
+	for i := 0; i < b.N; i++ {
+		f, err := Open(path)
+		if err != nil {
+			b.Fatalf("open %q failed: %v", path, err)
+		}
+		ns, err := f.Readdirnames(-1)
+		f.Close()
+		if err != nil {
+			b.Fatalf("readdirnames %q failed: %v", path, err)
+		}
+		nentries = len(ns)
+	}
+	b.Logf("benchmarkReaddirname %q: %d entries", path, nentries)
+}
+
+func benchmarkReaddir(path string, b *testing.B) {
+	var nentries int
+	for i := 0; i < b.N; i++ {
+		f, err := Open(path)
+		if err != nil {
+			b.Fatalf("open %q failed: %v", path, err)
+		}
+		fs, err := f.Readdir(-1)
+		f.Close()
+		if err != nil {
+			b.Fatalf("readdir %q failed: %v", path, err)
+		}
+		nentries = len(fs)
+	}
+	b.Logf("benchmarkReaddir %q: %d entries", path, nentries)
+}
+
+func BenchmarkReaddirname(b *testing.B) {
+	benchmarkReaddirname(".", b)
+}
+
+func BenchmarkReaddir(b *testing.B) {
+	benchmarkReaddir(".", b)
+}
+
 // Read the directory one entry at a time.
 func smallReaddirnames(file *File, length int, t *testing.T) []string {
 	names := make([]string, length)
@@ -541,6 +583,12 @@ func TestHardLink(t *testing.T) {
 	if runtime.GOOS == "plan9" {
 		t.Skip("skipping on plan9, hardlinks not supported")
 	}
+	// From Android release M (Marshmallow), hard linking files is blocked
+	// and an attempt to call link() on a file will return EACCES.
+	// - https://code.google.com/p/android-developer-preview/issues/detail?id=3150
+	if runtime.GOOS == "android" {
+		t.Skip("skipping on android, hardlinks not supported")
+	}
 	defer chtmpdir(t)()
 	from, to := "hardlinktestfrom", "hardlinktestto"
 	Remove(from) // Just in case.
@@ -672,7 +720,7 @@ func TestSymlink(t *testing.T) {
 
 func TestLongSymlink(t *testing.T) {
 	switch runtime.GOOS {
-	case "plan9", "nacl":
+	case "android", "plan9", "nacl":
 		t.Skipf("skipping on %s", runtime.GOOS)
 	case "windows":
 		if !supportsSymlinks {
@@ -725,9 +773,6 @@ func TestRename(t *testing.T) {
 }
 
 func TestRenameOverwriteDest(t *testing.T) {
-	if runtime.GOOS == "plan9" {
-		t.Skip("skipping on plan9")
-	}
 	defer chtmpdir(t)()
 	from, to := "renamefrom", "renameto"
 	// Just in case.
diff --git a/src/os/os_unix_test.go b/src/os/os_unix_test.go
index 2adc3b5..d02e07b 100644
--- a/src/os/os_unix_test.go
+++ b/src/os/os_unix_test.go
@@ -18,16 +18,16 @@ func init() {
 }
 
 func checkUidGid(t *testing.T, path string, uid, gid int) {
-	dir, err := Stat(path)
+	dir, err := Lstat(path)
 	if err != nil {
-		t.Fatalf("Stat %q (looking for uid/gid %d/%d): %s", path, uid, gid, err)
+		t.Fatalf("Lstat %q (looking for uid/gid %d/%d): %s", path, uid, gid, err)
 	}
 	sys := dir.Sys().(*syscall.Stat_t)
 	if int(sys.Uid) != uid {
-		t.Errorf("Stat %q: uid %d want %d", path, sys.Uid, uid)
+		t.Errorf("Lstat %q: uid %d want %d", path, sys.Uid, uid)
 	}
 	if int(sys.Gid) != gid {
-		t.Errorf("Stat %q: gid %d want %d", path, sys.Gid, gid)
+		t.Errorf("Lstat %q: gid %d want %d", path, sys.Gid, gid)
 	}
 }
 
@@ -144,17 +144,11 @@ func TestLchown(t *testing.T) {
 	}
 
 	linkname := f.Name() + "2"
-	if err := Link(f.Name(), linkname); err != nil {
+	if err := Symlink(f.Name(), linkname); err != nil {
 		t.Fatalf("link %s -> %s: %v", f.Name(), linkname, err)
 	}
 	defer Remove(linkname)
 
-	f2, err := Open(linkname)
-	if err != nil {
-		t.Fatalf("open %s: %v", linkname, err)
-	}
-	defer f2.Close()
-
 	// Can't change uid unless root, but can try
 	// changing the group id.  First try our current group.
 	gid := Getgid()
@@ -177,10 +171,7 @@ func TestLchown(t *testing.T) {
 		}
 		checkUidGid(t, linkname, int(sys.Uid), g)
 
-		// change back to gid to test fd.Chown
-		if err = f2.Chown(-1, gid); err != nil {
-			t.Fatalf("fchown %s -1 %d: %s", linkname, gid, err)
-		}
-		checkUidGid(t, linkname, int(sys.Uid), gid)
+		// Check that link target's gid is unchanged.
+		checkUidGid(t, f.Name(), int(sys.Uid), int(sys.Gid))
 	}
 }
diff --git a/src/os/os_windows_test.go b/src/os/os_windows_test.go
index ee19b2b..5c073da 100644
--- a/src/os/os_windows_test.go
+++ b/src/os/os_windows_test.go
@@ -1,3 +1,7 @@
+// 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 os_test
 
 import (
@@ -5,6 +9,7 @@ import (
 	"os"
 	osexec "os/exec"
 	"path/filepath"
+	"sort"
 	"strings"
 	"syscall"
 	"testing"
@@ -126,3 +131,95 @@ func TestStartProcessAttr(t *testing.T) {
 	defer p.Wait()
 	t.Fatalf("StartProcess expected to fail, but succeeded.")
 }
+
+func TestShareNotExistError(t *testing.T) {
+	if testing.Short() {
+		t.Skip("slow test that uses network; skipping")
+	}
+	_, err := os.Stat(`\\no_such_server\no_such_share\no_such_file`)
+	if err == nil {
+		t.Fatal("stat succeeded, but expected to fail")
+	}
+	if !os.IsNotExist(err) {
+		t.Fatalf("os.Stat failed with %q, but os.IsNotExist(err) is false", err)
+	}
+}
+
+func TestBadNetPathError(t *testing.T) {
+	const ERROR_BAD_NETPATH = syscall.Errno(53)
+	if !os.IsNotExist(ERROR_BAD_NETPATH) {
+		t.Fatal("os.IsNotExist(syscall.Errno(53)) is false, but want true")
+	}
+}
+
+func TestStatDir(t *testing.T) {
+	defer chtmpdir(t)()
+
+	f, err := os.Open(".")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer f.Close()
+
+	fi, err := f.Stat()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = os.Chdir("..")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	fi2, err := f.Stat()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if !os.SameFile(fi, fi2) {
+		t.Fatal("race condition occured")
+	}
+}
+
+func TestOpenVolumeName(t *testing.T) {
+	tmpdir, err := ioutil.TempDir("", "TestOpenVolumeName")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(tmpdir)
+
+	wd, err := os.Getwd()
+	if err != nil {
+		t.Fatal(err)
+	}
+	err = os.Chdir(tmpdir)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.Chdir(wd)
+
+	want := []string{"file1", "file2", "file3", "gopher.txt"}
+	sort.Strings(want)
+	for _, name := range want {
+		err := ioutil.WriteFile(filepath.Join(tmpdir, name), nil, 0777)
+		if err != nil {
+			t.Fatal(err)
+		}
+	}
+
+	f, err := os.Open(filepath.VolumeName(tmpdir))
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer f.Close()
+
+	have, err := f.Readdirnames(-1)
+	if err != nil {
+		t.Fatal(err)
+	}
+	sort.Strings(have)
+
+	if strings.Join(want, "/") != strings.Join(have, "/") {
+		t.Fatalf("unexpected file list %q, want %q", have, want)
+	}
+}
diff --git a/src/os/path_test.go b/src/os/path_test.go
index f985381..b453131 100644
--- a/src/os/path_test.go
+++ b/src/os/path_test.go
@@ -170,7 +170,7 @@ func TestRemoveAll(t *testing.T) {
 
 func TestMkdirAllWithSymlink(t *testing.T) {
 	switch runtime.GOOS {
-	case "nacl", "plan9":
+	case "android", "nacl", "plan9":
 		t.Skipf("skipping on %s", runtime.GOOS)
 	case "windows":
 		if !supportsSymlinks {
diff --git a/src/os/pipe_test.go b/src/os/pipe_test.go
new file mode 100644
index 0000000..82b792e
--- /dev/null
+++ b/src/os/pipe_test.go
@@ -0,0 +1,113 @@
+// Copyright 2015 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 broken pipes on Unix systems.
+// +build !windows,!plan9,!nacl
+
+package os_test
+
+import (
+	"fmt"
+	"internal/testenv"
+	"os"
+	osexec "os/exec"
+	"os/signal"
+	"syscall"
+	"testing"
+)
+
+func TestEPIPE(t *testing.T) {
+	r, w, err := os.Pipe()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if err := r.Close(); err != nil {
+		t.Fatal(err)
+	}
+
+	// Every time we write to the pipe we should get an EPIPE.
+	for i := 0; i < 20; i++ {
+		_, err = w.Write([]byte("hi"))
+		if err == nil {
+			t.Fatal("unexpected success of Write to broken pipe")
+		}
+		if pe, ok := err.(*os.PathError); ok {
+			err = pe.Err
+		}
+		if se, ok := err.(*os.SyscallError); ok {
+			err = se.Err
+		}
+		if err != syscall.EPIPE {
+			t.Errorf("iteration %d: got %v, expected EPIPE", i, err)
+		}
+	}
+}
+
+func TestStdPipe(t *testing.T) {
+	testenv.MustHaveExec(t)
+	r, w, err := os.Pipe()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if err := r.Close(); err != nil {
+		t.Fatal(err)
+	}
+	// Invoke the test program to run the test and write to a closed pipe.
+	// If sig is false:
+	// writing to stdout or stderr should cause an immediate SIGPIPE;
+	// writing to descriptor 3 should fail with EPIPE and then exit 0.
+	// If sig is true:
+	// all writes should fail with EPIPE and then exit 0.
+	for _, sig := range []bool{false, true} {
+		for dest := 1; dest < 4; dest++ {
+			cmd := osexec.Command(os.Args[0], "-test.run", "TestStdPipeHelper")
+			cmd.Stdout = w
+			cmd.Stderr = w
+			cmd.ExtraFiles = []*os.File{w}
+			cmd.Env = append(os.Environ(), fmt.Sprintf("GO_TEST_STD_PIPE_HELPER=%d", dest))
+			if sig {
+				cmd.Env = append(cmd.Env, "GO_TEST_STD_PIPE_HELPER_SIGNAL=1")
+			}
+			if err := cmd.Run(); err == nil {
+				if !sig && dest < 3 {
+					t.Errorf("unexpected success of write to closed pipe %d sig %t in child", dest, sig)
+				}
+			} else if ee, ok := err.(*osexec.ExitError); !ok {
+				t.Errorf("unexpected exec error type %T: %v", err, err)
+			} else if ws, ok := ee.Sys().(syscall.WaitStatus); !ok {
+				t.Errorf("unexpected wait status type %T: %v", ee.Sys(), ee.Sys())
+			} else if ws.Signaled() && ws.Signal() == syscall.SIGPIPE {
+				if sig || dest > 2 {
+					t.Errorf("unexpected SIGPIPE signal for descriptor %d sig %t", dest, sig)
+				}
+			} else {
+				t.Errorf("unexpected exit status %v for descriptor %ds sig %t", err, dest, sig)
+			}
+		}
+	}
+}
+
+// This is a helper for TestStdPipe.  It's not a test in itself.
+func TestStdPipeHelper(t *testing.T) {
+	if os.Getenv("GO_TEST_STD_PIPE_HELPER_SIGNAL") != "" {
+		signal.Notify(make(chan os.Signal, 1), syscall.SIGPIPE)
+	}
+	switch os.Getenv("GO_TEST_STD_PIPE_HELPER") {
+	case "1":
+		os.Stdout.Write([]byte("stdout"))
+	case "2":
+		os.Stderr.Write([]byte("stderr"))
+	case "3":
+		if _, err := os.NewFile(3, "3").Write([]byte("3")); err == nil {
+			os.Exit(3)
+		}
+	default:
+		t.Skip("skipping test helper")
+	}
+	// For stdout/stderr, we should have crashed with a broken pipe error.
+	// The caller will be looking for that exit status,
+	// so just exit normally here to cause a failure in the caller.
+	// For descriptor 3, a normal exit is expected.
+	os.Exit(0)
+}
diff --git a/src/os/signal/doc.go b/src/os/signal/doc.go
new file mode 100644
index 0000000..80e66cf
--- /dev/null
+++ b/src/os/signal/doc.go
@@ -0,0 +1,220 @@
+// Copyright 2015 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 signal implements access to incoming signals.
+
+Signals are primarily used on Unix-like systems. For the use of this
+package on Windows and Plan 9, see below.
+
+Types of signals
+
+The signals SIGKILL and SIGSTOP may not be caught by a program, and
+therefore can not be affected by this package.
+
+Synchronous signals are signals triggered by errors in program
+execution: SIGBUS, SIGFPE, and SIGSEGV. These are only considered
+synchronous when caused by program execution, not when sent using
+os.Process.Kill or the kill program or some similar mechanism. In
+general, except as discussed below, Go programs will convert a
+synchronous signal into a run-time panic.
+
+The remaining signals are asynchronous signals. They are not
+triggered by program errors, but are instead sent from the kernel or
+from some other program.
+
+Of the asynchronous signals, the SIGHUP signal is sent when a program
+loses its controlling terminal. The SIGINT signal is sent when the
+user at the controlling terminal presses the interrupt character,
+which by default is ^C (Control-C). The SIGQUIT signal is sent when
+the user at the controlling terminal presses the quit character, which
+by default is ^\ (Control-Backslash). In general you can cause a
+program to simply exit by pressing ^C, and you can cause it to exit
+with a stack dump by pressing ^\.
+
+Default behavior of signals in Go programs
+
+By default, a synchronous signal is converted into a run-time panic. A
+SIGHUP, SIGINT, or SIGTERM signal causes the program to exit. A
+SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGSTKFLT, SIGEMT, or SIGSYS signal
+causes the program to exit with a stack dump. A SIGTSTP, SIGTTIN, or
+SIGTTOU signal gets the system default behavior (these signals are
+used by the shell for job control). The SIGPROF signal is handled
+directly by the Go runtime to implement runtime.CPUProfile. Other
+signals will be caught but no action will be taken.
+
+If the Go program is started with either SIGHUP or SIGINT ignored
+(signal handler set to SIG_IGN), they will remain ignored.
+
+If the Go program is started with a non-empty signal mask, that will
+generally be honored. However, some signals are explicitly unblocked:
+the synchronous signals, SIGILL, SIGTRAP, SIGSTKFLT, SIGCHLD, SIGPROF,
+and, on GNU/Linux, signals 32 (SIGCANCEL) and 33 (SIGSETXID)
+(SIGCANCEL and SIGSETXID are used internally by glibc). Subprocesses
+started by os.Exec, or by the os/exec package, will inherit the
+modified signal mask.
+
+Changing the behavior of signals in Go programs
+
+The functions in this package allow a program to change the way Go
+programs handle signals.
+
+Notify disables the default behavior for a given set of asynchronous
+signals and instead delivers them over one or more registered
+channels. Specifically, it applies to the signals SIGHUP, SIGINT,
+SIGQUIT, SIGABRT, and SIGTERM. It also applies to the job control
+signals SIGTSTP, SIGTTIN, and SIGTTOU, in which case the system
+default behavior does not occur. It also applies to some signals that
+otherwise cause no action: SIGUSR1, SIGUSR2, SIGPIPE, SIGALRM,
+SIGCHLD, SIGCONT, SIGURG, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGWINCH,
+SIGIO, SIGPWR, SIGSYS, SIGINFO, SIGTHR, SIGWAITING, SIGLWP, SIGFREEZE,
+SIGTHAW, SIGLOST, SIGXRES, SIGJVM1, SIGJVM2, and any real time signals
+used on the system. Note that not all of these signals are available
+on all systems.
+
+If the program was started with SIGHUP or SIGINT ignored, and Notify
+is called for either signal, a signal handler will be installed for
+that signal and it will no longer be ignored. If, later, Reset or
+Ignore is called for that signal, or Stop is called on all channels
+passed to Notify for that signal, the signal will once again be
+ignored. Reset will restore the system default behavior for the
+signal, while Ignore will cause the system to ignore the signal
+entirely.
+
+If the program is started with a non-empty signal mask, some signals
+will be explicitly unblocked as described above. If Notify is called
+for a blocked signal, it will be unblocked. If, later, Reset is
+called for that signal, or Stop is called on all channels passed to
+Notify for that signal, the signal will once again be blocked.
+
+SIGPIPE
+
+When a Go program writes to a broken pipe, the kernel will raise a
+SIGPIPE signal.
+
+If the program has not called Notify to receive SIGPIPE signals, then
+the behavior depends on the file descriptor number. A write to a
+broken pipe on file descriptors 1 or 2 (standard output or standard
+error) will cause the program to exit with a SIGPIPE signal. A write
+to a broken pipe on some other file descriptor will take no action on
+the SIGPIPE signal, and the write will fail with an EPIPE error.
+
+If the program has called Notify to receive SIGPIPE signals, the file
+descriptor number does not matter. The SIGPIPE signal will be
+delivered to the Notify channel, and the write will fail with an EPIPE
+error.
+
+This means that, by default, command line programs will behave like
+typical Unix command line programs, while other programs will not
+crash with SIGPIPE when writing to a closed network connection.
+
+Go programs that use cgo or SWIG
+
+In a Go program that includes non-Go code, typically C/C++ code
+accessed using cgo or SWIG, Go's startup code normally runs first. It
+configures the signal handlers as expected by the Go runtime, before
+the non-Go startup code runs. If the non-Go startup code wishes to
+install its own signal handlers, it must take certain steps to keep Go
+working well. This section documents those steps and the overall
+effect changes to signal handler settings by the non-Go code can have
+on Go programs. In rare cases, the non-Go code may run before the Go
+code, in which case the next section also applies.
+
+If the non-Go code called by the Go program does not change any signal
+handlers or masks, then the behavior is the same as for a pure Go
+program.
+
+If the non-Go code installs any signal handlers, it must use the
+SA_ONSTACK flag with sigaction. Failing to do so is likely to cause
+the program to crash if the signal is received. Go programs routinely
+run with a limited stack, and therefore set up an alternate signal
+stack. Also, the Go standard library expects that any signal handlers
+will use the SA_RESTART flag. Failing to do so may cause some library
+calls to return "interrupted system call" errors.
+
+If the non-Go code installs a signal handler for any of the
+synchronous signals (SIGBUS, SIGFPE, SIGSEGV), then it should record
+the existing Go signal handler. If those signals occur while
+executing Go code, it should invoke the Go signal handler (whether the
+signal occurs while executing Go code can be determined by looking at
+the PC passed to the signal handler). Otherwise some Go run-time
+panics will not occur as expected.
+
+If the non-Go code installs a signal handler for any of the
+asynchronous signals, it may invoke the Go signal handler or not as it
+chooses. Naturally, if it does not invoke the Go signal handler, the
+Go behavior described above will not occur. This can be an issue with
+the SIGPROF signal in particular.
+
+The non-Go code should not change the signal mask on any threads
+created by the Go runtime. If the non-Go code starts new threads of
+its own, it may set the signal mask as it pleases.
+
+If the non-Go code starts a new thread, changes the signal mask, and
+then invokes a Go function in that thread, the Go runtime will
+automatically unblock certain signals: the synchronous signals,
+SIGILL, SIGTRAP, SIGSTKFLT, SIGCHLD, SIGPROF, SIGCANCEL, and
+SIGSETXID. When the Go function returns, the non-Go signal mask will
+be restored.
+
+If the Go signal handler is invoked on a non-Go thread not running Go
+code, the handler generally forwards the signal to the non-Go code, as
+follows. If the signal is SIGPROF, the Go handler does
+nothing. Otherwise, the Go handler removes itself, unblocks the
+signal, and raises it again, to invoke any non-Go handler or default
+system handler. If the program does not exit, the Go handler then
+reinstalls itself and continues execution of the program.
+
+Non-Go programs that call Go code
+
+When Go code is built with options like -buildmode=c-shared, it will
+be run as part of an existing non-Go program. The non-Go code may
+have already installed signal handlers when the Go code starts (that
+may also happen in unusual cases when using cgo or SWIG; in that case,
+the discussion here applies).  For -buildmode=c-archive the Go runtime
+will initialize signals at global constructor time.  For
+-buildmode=c-shared the Go runtime will initialize signals when the
+shared library is loaded.
+
+If the Go runtime sees an existing signal handler for the SIGCANCEL or
+SIGSETXID signals (which are used only on GNU/Linux), it will turn on
+the SA_ONSTACK flag and otherwise keep the signal handler.
+
+For the synchronous signals, the Go runtime will install a signal
+handler. It will save any existing signal handler. If a synchronous
+signal arrives while executing non-Go code, the Go runtime will invoke
+the existing signal handler instead of the Go signal handler.
+
+Go code built with -buildmode=c-archive or -buildmode=c-shared will
+not install any other signal handlers by default. If there is an
+existing signal handler, the Go runtime will turn on the SA_ONSTACK
+flag and otherwise keep the signal handler. If Notify is called for an
+asynchronous signal, a Go signal handler will be installed for that
+signal. If, later, Reset is called for that signal, the original
+handling for that signal will be reinstalled, restoring the non-Go
+signal handler if any.
+
+Go code built without -buildmode=c-archive or -buildmode=c-shared will
+install a signal handler for the asynchronous signals listed above,
+and save any existing signal handler. If a signal is delivered to a
+non-Go thread, it will act as described above, except that if there is
+an existing non-Go signal handler, that handler will be installed
+before raising the signal.
+
+Windows
+
+On Windows a ^C (Control-C) or ^BREAK (Control-Break) normally cause
+the program to exit. If Notify is called for os.SIGINT, ^C or ^BREAK
+will cause os.SIGINT to be sent on the channel, and the program will
+not exit. If Reset is called, or Stop is called on all channels passed
+to Notify, then the default behavior will be restored.
+
+Plan 9
+
+On Plan 9, signals have type syscall.Note, which is a string. Calling
+Notify with a syscall.Note will cause that value to be sent on the
+channel when that string is posted as a note.
+
+*/
+package signal
diff --git a/src/os/signal/example_test.go b/src/os/signal/example_test.go
index 079ee50..5dfbe5f 100644
--- a/src/os/signal/example_test.go
+++ b/src/os/signal/example_test.go
@@ -15,7 +15,7 @@ func ExampleNotify() {
 	// We must use a buffered channel or risk missing the signal
 	// if we're not ready to receive when the signal is sent.
 	c := make(chan os.Signal, 1)
-	signal.Notify(c, os.Interrupt, os.Kill)
+	signal.Notify(c, os.Interrupt)
 
 	// Block until a signal is received.
 	s := <-c
diff --git a/src/os/signal/sig.s b/src/os/signal/sig.s
index 7fa6c92..2e94c91 100644
--- a/src/os/signal/sig.s
+++ b/src/os/signal/sig.s
@@ -2,31 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Assembly to get into package runtime without using exported symbols.
-
-// +build amd64 amd64p32 arm arm64 386 ppc64 ppc64le
-
-#include "textflag.h"
-
-#ifdef GOARCH_arm
-#define JMP B
-#endif
-#ifdef GOARCH_ppc64
-#define JMP BR
-#endif
-#ifdef GOARCH_ppc64le
-#define JMP BR
-#endif
-
-TEXT ·signal_disable(SB),NOSPLIT,$0
-	JMP runtime·signal_disable(SB)
-
-TEXT ·signal_enable(SB),NOSPLIT,$0
-	JMP runtime·signal_enable(SB)
-
-TEXT ·signal_ignore(SB),NOSPLIT,$0
-	JMP runtime·signal_ignore(SB)
-
-TEXT ·signal_recv(SB),NOSPLIT,$0
-	JMP runtime·signal_recv(SB)
-
+// The runtime package uses //go:linkname to push a few functions into this
+// package but we still need a .s file so the Go tool does not pass -complete
+// to the go tool compile so the latter does not complain about Go functions
+// with no bodies.
diff --git a/src/os/signal/signal.go b/src/os/signal/signal.go
index 1625786..2e6f186 100644
--- a/src/os/signal/signal.go
+++ b/src/os/signal/signal.go
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Package signal implements access to incoming signals.
 package signal
 
 import (
diff --git a/src/os/signal/signal_test.go b/src/os/signal/signal_test.go
index a71633c..56d786e 100644
--- a/src/os/signal/signal_test.go
+++ b/src/os/signal/signal_test.go
@@ -182,13 +182,14 @@ func TestStop(t *testing.T) {
 	sigs := []syscall.Signal{
 		syscall.SIGWINCH,
 		syscall.SIGHUP,
+		syscall.SIGUSR1,
 	}
 
 	for _, sig := range sigs {
 		// Send the signal.
 		// If it's SIGWINCH, we should not see it.
 		// If it's SIGHUP, maybe we'll die. Let the flag tell us what to do.
-		if sig != syscall.SIGHUP || *sendUncaughtSighup == 1 {
+		if sig == syscall.SIGWINCH || (sig == syscall.SIGHUP && *sendUncaughtSighup == 1) {
 			syscall.Kill(syscall.Getpid(), sig)
 		}
 		time.Sleep(100 * time.Millisecond)
@@ -255,6 +256,12 @@ func TestNohup(t *testing.T) {
 
 	Stop(c)
 
+	// Skip the nohup test below when running in tmux on darwin, since nohup
+	// doesn't work correctly there. See issue #5135.
+	if runtime.GOOS == "darwin" && os.Getenv("TMUX") != "" {
+		t.Skip("Skipping nohup test due to running in tmux on darwin")
+	}
+
 	// Again, this time with nohup, assuming we can find it.
 	_, err := os.Stat("/usr/bin/nohup")
 	if err != nil {
@@ -272,3 +279,12 @@ func TestNohup(t *testing.T) {
 		}
 	}
 }
+
+// Test that SIGCONT works (issue 8953).
+func TestSIGCONT(t *testing.T) {
+	c := make(chan os.Signal, 1)
+	Notify(c, syscall.SIGCONT)
+	defer Stop(c)
+	syscall.Kill(syscall.Getpid(), syscall.SIGCONT)
+	waitSig(t, c, syscall.SIGCONT)
+}
diff --git a/src/os/signal/signal_unix.go b/src/os/signal/signal_unix.go
index 1bdf1d7..01b1b14 100644
--- a/src/os/signal/signal_unix.go
+++ b/src/os/signal/signal_unix.go
@@ -11,7 +11,7 @@ import (
 	"syscall"
 )
 
-// In assembly.
+// Defined by the runtime package.
 func signal_disable(uint32)
 func signal_enable(uint32)
 func signal_ignore(uint32)
diff --git a/src/os/stat_darwin.go b/src/os/stat_darwin.go
index 0eea522..9dc7a99 100644
--- a/src/os/stat_darwin.go
+++ b/src/os/stat_darwin.go
@@ -9,21 +9,12 @@ import (
 	"time"
 )
 
-func sameFile(fs1, fs2 *fileStat) bool {
-	stat1 := fs1.sys.(*syscall.Stat_t)
-	stat2 := fs2.sys.(*syscall.Stat_t)
-	return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
-}
-
-func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
-	fs := &fileStat{
-		name:    basename(name),
-		size:    int64(st.Size),
-		modTime: timespecToTime(st.Mtimespec),
-		sys:     st,
-	}
-	fs.mode = FileMode(st.Mode & 0777)
-	switch st.Mode & syscall.S_IFMT {
+func fillFileStatFromSys(fs *fileStat, name string) {
+	fs.name = basename(name)
+	fs.size = int64(fs.sys.Size)
+	fs.modTime = timespecToTime(fs.sys.Mtimespec)
+	fs.mode = FileMode(fs.sys.Mode & 0777)
+	switch fs.sys.Mode & syscall.S_IFMT {
 	case syscall.S_IFBLK, syscall.S_IFWHT:
 		fs.mode |= ModeDevice
 	case syscall.S_IFCHR:
@@ -39,16 +30,15 @@ func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
 	case syscall.S_IFSOCK:
 		fs.mode |= ModeSocket
 	}
-	if st.Mode&syscall.S_ISGID != 0 {
+	if fs.sys.Mode&syscall.S_ISGID != 0 {
 		fs.mode |= ModeSetgid
 	}
-	if st.Mode&syscall.S_ISUID != 0 {
+	if fs.sys.Mode&syscall.S_ISUID != 0 {
 		fs.mode |= ModeSetuid
 	}
-	if st.Mode&syscall.S_ISVTX != 0 {
+	if fs.sys.Mode&syscall.S_ISVTX != 0 {
 		fs.mode |= ModeSticky
 	}
-	return fs
 }
 
 func timespecToTime(ts syscall.Timespec) time.Time {
diff --git a/src/os/stat_dragonfly.go b/src/os/stat_dragonfly.go
index 605c1d9..69e6323 100644
--- a/src/os/stat_dragonfly.go
+++ b/src/os/stat_dragonfly.go
@@ -9,21 +9,12 @@ import (
 	"time"
 )
 
-func sameFile(fs1, fs2 *fileStat) bool {
-	stat1 := fs1.sys.(*syscall.Stat_t)
-	stat2 := fs2.sys.(*syscall.Stat_t)
-	return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
-}
-
-func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
-	fs := &fileStat{
-		name:    basename(name),
-		size:    int64(st.Size),
-		modTime: timespecToTime(st.Mtim),
-		sys:     st,
-	}
-	fs.mode = FileMode(st.Mode & 0777)
-	switch st.Mode & syscall.S_IFMT {
+func fillFileStatFromSys(fs *fileStat, name string) {
+	fs.name = basename(name)
+	fs.size = int64(fs.sys.Size)
+	fs.modTime = timespecToTime(fs.sys.Mtim)
+	fs.mode = FileMode(fs.sys.Mode & 0777)
+	switch fs.sys.Mode & syscall.S_IFMT {
 	case syscall.S_IFBLK:
 		fs.mode |= ModeDevice
 	case syscall.S_IFCHR:
@@ -39,16 +30,15 @@ func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
 	case syscall.S_IFSOCK:
 		fs.mode |= ModeSocket
 	}
-	if st.Mode&syscall.S_ISGID != 0 {
+	if fs.sys.Mode&syscall.S_ISGID != 0 {
 		fs.mode |= ModeSetgid
 	}
-	if st.Mode&syscall.S_ISUID != 0 {
+	if fs.sys.Mode&syscall.S_ISUID != 0 {
 		fs.mode |= ModeSetuid
 	}
-	if st.Mode&syscall.S_ISVTX != 0 {
+	if fs.sys.Mode&syscall.S_ISVTX != 0 {
 		fs.mode |= ModeSticky
 	}
-	return fs
 }
 
 func timespecToTime(ts syscall.Timespec) time.Time {
diff --git a/src/os/stat_freebsd.go b/src/os/stat_freebsd.go
index 2ffb60f..e9d38aa 100644
--- a/src/os/stat_freebsd.go
+++ b/src/os/stat_freebsd.go
@@ -9,21 +9,12 @@ import (
 	"time"
 )
 
-func sameFile(fs1, fs2 *fileStat) bool {
-	stat1 := fs1.sys.(*syscall.Stat_t)
-	stat2 := fs2.sys.(*syscall.Stat_t)
-	return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
-}
-
-func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
-	fs := &fileStat{
-		name:    basename(name),
-		size:    int64(st.Size),
-		modTime: timespecToTime(st.Mtimespec),
-		sys:     st,
-	}
-	fs.mode = FileMode(st.Mode & 0777)
-	switch st.Mode & syscall.S_IFMT {
+func fillFileStatFromSys(fs *fileStat, name string) {
+	fs.name = basename(name)
+	fs.size = int64(fs.sys.Size)
+	fs.modTime = timespecToTime(fs.sys.Mtimespec)
+	fs.mode = FileMode(fs.sys.Mode & 0777)
+	switch fs.sys.Mode & syscall.S_IFMT {
 	case syscall.S_IFBLK:
 		fs.mode |= ModeDevice
 	case syscall.S_IFCHR:
@@ -39,16 +30,15 @@ func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
 	case syscall.S_IFSOCK:
 		fs.mode |= ModeSocket
 	}
-	if st.Mode&syscall.S_ISGID != 0 {
+	if fs.sys.Mode&syscall.S_ISGID != 0 {
 		fs.mode |= ModeSetgid
 	}
-	if st.Mode&syscall.S_ISUID != 0 {
+	if fs.sys.Mode&syscall.S_ISUID != 0 {
 		fs.mode |= ModeSetuid
 	}
-	if st.Mode&syscall.S_ISVTX != 0 {
+	if fs.sys.Mode&syscall.S_ISVTX != 0 {
 		fs.mode |= ModeSticky
 	}
-	return fs
 }
 
 func timespecToTime(ts syscall.Timespec) time.Time {
diff --git a/src/os/stat_linux.go b/src/os/stat_linux.go
index 605c1d9..69e6323 100644
--- a/src/os/stat_linux.go
+++ b/src/os/stat_linux.go
@@ -9,21 +9,12 @@ import (
 	"time"
 )
 
-func sameFile(fs1, fs2 *fileStat) bool {
-	stat1 := fs1.sys.(*syscall.Stat_t)
-	stat2 := fs2.sys.(*syscall.Stat_t)
-	return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
-}
-
-func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
-	fs := &fileStat{
-		name:    basename(name),
-		size:    int64(st.Size),
-		modTime: timespecToTime(st.Mtim),
-		sys:     st,
-	}
-	fs.mode = FileMode(st.Mode & 0777)
-	switch st.Mode & syscall.S_IFMT {
+func fillFileStatFromSys(fs *fileStat, name string) {
+	fs.name = basename(name)
+	fs.size = int64(fs.sys.Size)
+	fs.modTime = timespecToTime(fs.sys.Mtim)
+	fs.mode = FileMode(fs.sys.Mode & 0777)
+	switch fs.sys.Mode & syscall.S_IFMT {
 	case syscall.S_IFBLK:
 		fs.mode |= ModeDevice
 	case syscall.S_IFCHR:
@@ -39,16 +30,15 @@ func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
 	case syscall.S_IFSOCK:
 		fs.mode |= ModeSocket
 	}
-	if st.Mode&syscall.S_ISGID != 0 {
+	if fs.sys.Mode&syscall.S_ISGID != 0 {
 		fs.mode |= ModeSetgid
 	}
-	if st.Mode&syscall.S_ISUID != 0 {
+	if fs.sys.Mode&syscall.S_ISUID != 0 {
 		fs.mode |= ModeSetuid
 	}
-	if st.Mode&syscall.S_ISVTX != 0 {
+	if fs.sys.Mode&syscall.S_ISVTX != 0 {
 		fs.mode |= ModeSticky
 	}
-	return fs
 }
 
 func timespecToTime(ts syscall.Timespec) time.Time {
diff --git a/src/os/stat_nacl.go b/src/os/stat_nacl.go
index a503b59..d3bed14 100644
--- a/src/os/stat_nacl.go
+++ b/src/os/stat_nacl.go
@@ -9,21 +9,12 @@ import (
 	"time"
 )
 
-func sameFile(fs1, fs2 *fileStat) bool {
-	stat1 := fs1.sys.(*syscall.Stat_t)
-	stat2 := fs2.sys.(*syscall.Stat_t)
-	return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
-}
-
-func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
-	fs := &fileStat{
-		name:    basename(name),
-		size:    int64(st.Size),
-		modTime: timespecToTime(st.Mtime, st.MtimeNsec),
-		sys:     st,
-	}
-	fs.mode = FileMode(st.Mode & 0777)
-	switch st.Mode & syscall.S_IFMT {
+func fillFileStatFromSys(fs *fileStat, name string) {
+	fs.name = basename(name)
+	fs.size = int64(fs.sys.Size)
+	fs.modTime = timespecToTime(fs.sys.Mtime, fs.sys.MtimeNsec)
+	fs.mode = FileMode(fs.sys.Mode & 0777)
+	switch fs.sys.Mode & syscall.S_IFMT {
 	case syscall.S_IFBLK:
 		fs.mode |= ModeDevice
 	case syscall.S_IFCHR:
@@ -39,16 +30,15 @@ func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
 	case syscall.S_IFSOCK:
 		fs.mode |= ModeSocket
 	}
-	if st.Mode&syscall.S_ISGID != 0 {
+	if fs.sys.Mode&syscall.S_ISGID != 0 {
 		fs.mode |= ModeSetgid
 	}
-	if st.Mode&syscall.S_ISUID != 0 {
+	if fs.sys.Mode&syscall.S_ISUID != 0 {
 		fs.mode |= ModeSetuid
 	}
-	if st.Mode&syscall.S_ISVTX != 0 {
+	if fs.sys.Mode&syscall.S_ISVTX != 0 {
 		fs.mode |= ModeSticky
 	}
-	return fs
 }
 
 func timespecToTime(sec, nsec int64) time.Time {
diff --git a/src/os/stat_netbsd.go b/src/os/stat_netbsd.go
index 2ffb60f..e9d38aa 100644
--- a/src/os/stat_netbsd.go
+++ b/src/os/stat_netbsd.go
@@ -9,21 +9,12 @@ import (
 	"time"
 )
 
-func sameFile(fs1, fs2 *fileStat) bool {
-	stat1 := fs1.sys.(*syscall.Stat_t)
-	stat2 := fs2.sys.(*syscall.Stat_t)
-	return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
-}
-
-func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
-	fs := &fileStat{
-		name:    basename(name),
-		size:    int64(st.Size),
-		modTime: timespecToTime(st.Mtimespec),
-		sys:     st,
-	}
-	fs.mode = FileMode(st.Mode & 0777)
-	switch st.Mode & syscall.S_IFMT {
+func fillFileStatFromSys(fs *fileStat, name string) {
+	fs.name = basename(name)
+	fs.size = int64(fs.sys.Size)
+	fs.modTime = timespecToTime(fs.sys.Mtimespec)
+	fs.mode = FileMode(fs.sys.Mode & 0777)
+	switch fs.sys.Mode & syscall.S_IFMT {
 	case syscall.S_IFBLK:
 		fs.mode |= ModeDevice
 	case syscall.S_IFCHR:
@@ -39,16 +30,15 @@ func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
 	case syscall.S_IFSOCK:
 		fs.mode |= ModeSocket
 	}
-	if st.Mode&syscall.S_ISGID != 0 {
+	if fs.sys.Mode&syscall.S_ISGID != 0 {
 		fs.mode |= ModeSetgid
 	}
-	if st.Mode&syscall.S_ISUID != 0 {
+	if fs.sys.Mode&syscall.S_ISUID != 0 {
 		fs.mode |= ModeSetuid
 	}
-	if st.Mode&syscall.S_ISVTX != 0 {
+	if fs.sys.Mode&syscall.S_ISVTX != 0 {
 		fs.mode |= ModeSticky
 	}
-	return fs
 }
 
 func timespecToTime(ts syscall.Timespec) time.Time {
diff --git a/src/os/stat_openbsd.go b/src/os/stat_openbsd.go
index 605c1d9..69e6323 100644
--- a/src/os/stat_openbsd.go
+++ b/src/os/stat_openbsd.go
@@ -9,21 +9,12 @@ import (
 	"time"
 )
 
-func sameFile(fs1, fs2 *fileStat) bool {
-	stat1 := fs1.sys.(*syscall.Stat_t)
-	stat2 := fs2.sys.(*syscall.Stat_t)
-	return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
-}
-
-func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
-	fs := &fileStat{
-		name:    basename(name),
-		size:    int64(st.Size),
-		modTime: timespecToTime(st.Mtim),
-		sys:     st,
-	}
-	fs.mode = FileMode(st.Mode & 0777)
-	switch st.Mode & syscall.S_IFMT {
+func fillFileStatFromSys(fs *fileStat, name string) {
+	fs.name = basename(name)
+	fs.size = int64(fs.sys.Size)
+	fs.modTime = timespecToTime(fs.sys.Mtim)
+	fs.mode = FileMode(fs.sys.Mode & 0777)
+	switch fs.sys.Mode & syscall.S_IFMT {
 	case syscall.S_IFBLK:
 		fs.mode |= ModeDevice
 	case syscall.S_IFCHR:
@@ -39,16 +30,15 @@ func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
 	case syscall.S_IFSOCK:
 		fs.mode |= ModeSocket
 	}
-	if st.Mode&syscall.S_ISGID != 0 {
+	if fs.sys.Mode&syscall.S_ISGID != 0 {
 		fs.mode |= ModeSetgid
 	}
-	if st.Mode&syscall.S_ISUID != 0 {
+	if fs.sys.Mode&syscall.S_ISUID != 0 {
 		fs.mode |= ModeSetuid
 	}
-	if st.Mode&syscall.S_ISVTX != 0 {
+	if fs.sys.Mode&syscall.S_ISVTX != 0 {
 		fs.mode |= ModeSticky
 	}
-	return fs
 }
 
 func timespecToTime(ts syscall.Timespec) time.Time {
diff --git a/src/os/stat_solaris.go b/src/os/stat_solaris.go
index 605c1d9..69e6323 100644
--- a/src/os/stat_solaris.go
+++ b/src/os/stat_solaris.go
@@ -9,21 +9,12 @@ import (
 	"time"
 )
 
-func sameFile(fs1, fs2 *fileStat) bool {
-	stat1 := fs1.sys.(*syscall.Stat_t)
-	stat2 := fs2.sys.(*syscall.Stat_t)
-	return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino
-}
-
-func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
-	fs := &fileStat{
-		name:    basename(name),
-		size:    int64(st.Size),
-		modTime: timespecToTime(st.Mtim),
-		sys:     st,
-	}
-	fs.mode = FileMode(st.Mode & 0777)
-	switch st.Mode & syscall.S_IFMT {
+func fillFileStatFromSys(fs *fileStat, name string) {
+	fs.name = basename(name)
+	fs.size = int64(fs.sys.Size)
+	fs.modTime = timespecToTime(fs.sys.Mtim)
+	fs.mode = FileMode(fs.sys.Mode & 0777)
+	switch fs.sys.Mode & syscall.S_IFMT {
 	case syscall.S_IFBLK:
 		fs.mode |= ModeDevice
 	case syscall.S_IFCHR:
@@ -39,16 +30,15 @@ func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo {
 	case syscall.S_IFSOCK:
 		fs.mode |= ModeSocket
 	}
-	if st.Mode&syscall.S_ISGID != 0 {
+	if fs.sys.Mode&syscall.S_ISGID != 0 {
 		fs.mode |= ModeSetgid
 	}
-	if st.Mode&syscall.S_ISUID != 0 {
+	if fs.sys.Mode&syscall.S_ISUID != 0 {
 		fs.mode |= ModeSetuid
 	}
-	if st.Mode&syscall.S_ISVTX != 0 {
+	if fs.sys.Mode&syscall.S_ISVTX != 0 {
 		fs.mode |= ModeSticky
 	}
-	return fs
 }
 
 func timespecToTime(ts syscall.Timespec) time.Time {
diff --git a/src/os/stat_windows.go b/src/os/stat_windows.go
index 966163b..0b6c22c 100644
--- a/src/os/stat_windows.go
+++ b/src/os/stat_windows.go
@@ -20,7 +20,7 @@ func (file *File) Stat() (FileInfo, error) {
 	}
 	if file.isdir() {
 		// I don't know any better way to do that for directory
-		return Stat(file.name)
+		return Stat(file.dirinfo.path)
 	}
 	if file.name == DevNull {
 		return &devNullStat, nil
diff --git a/src/os/types_notwin.go b/src/os/types_notwin.go
deleted file mode 100644
index ea1a073..0000000
--- a/src/os/types_notwin.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2009 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.
-
-// +build !windows
-
-package os
-
-import (
-	"time"
-)
-
-// A fileStat is the implementation of FileInfo returned by Stat and Lstat.
-type fileStat struct {
-	name    string
-	size    int64
-	mode    FileMode
-	modTime time.Time
-	sys     interface{}
-}
-
-func (fs *fileStat) Size() int64        { return fs.size }
-func (fs *fileStat) Mode() FileMode     { return fs.mode }
-func (fs *fileStat) ModTime() time.Time { return fs.modTime }
-func (fs *fileStat) Sys() interface{}   { return fs.sys }
diff --git a/src/os/types_plan9.go b/src/os/types_plan9.go
new file mode 100644
index 0000000..6d46ca9
--- /dev/null
+++ b/src/os/types_plan9.go
@@ -0,0 +1,21 @@
+// Copyright 2009 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 os
+
+import "time"
+
+// A fileStat is the implementation of FileInfo returned by Stat and Lstat.
+type fileStat struct {
+	name    string
+	size    int64
+	mode    FileMode
+	modTime time.Time
+	sys     interface{}
+}
+
+func (fs *fileStat) Size() int64        { return fs.size }
+func (fs *fileStat) Mode() FileMode     { return fs.mode }
+func (fs *fileStat) ModTime() time.Time { return fs.modTime }
+func (fs *fileStat) Sys() interface{}   { return fs.sys }
diff --git a/src/os/types_unix.go b/src/os/types_unix.go
new file mode 100644
index 0000000..056220c
--- /dev/null
+++ b/src/os/types_unix.go
@@ -0,0 +1,27 @@
+// Copyright 2009 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.
+
+// +build !windows
+// +build !plan9
+
+package os
+
+import (
+	"syscall"
+	"time"
+)
+
+// A fileStat is the implementation of FileInfo returned by Stat and Lstat.
+type fileStat struct {
+	name    string
+	size    int64
+	mode    FileMode
+	modTime time.Time
+	sys     syscall.Stat_t
+}
+
+func (fs *fileStat) Size() int64        { return fs.size }
+func (fs *fileStat) Mode() FileMode     { return fs.mode }
+func (fs *fileStat) ModTime() time.Time { return fs.modTime }
+func (fs *fileStat) Sys() interface{}   { return &fs.sys }
diff --git a/src/os/user/lookup_unix.go b/src/os/user/lookup_unix.go
index f4f603e..e8a1eb1 100644
--- a/src/os/user/lookup_unix.go
+++ b/src/os/user/lookup_unix.go
@@ -9,7 +9,6 @@ package user
 
 import (
 	"fmt"
-	"runtime"
 	"strconv"
 	"strings"
 	"syscall"
@@ -55,17 +54,15 @@ func lookupUnix(uid int, username string, lookupByName bool) (*User, error) {
 	var pwd C.struct_passwd
 	var result *C.struct_passwd
 
-	var bufSize C.long
-	if runtime.GOOS == "dragonfly" || runtime.GOOS == "freebsd" {
-		// DragonFly and FreeBSD do not have _SC_GETPW_R_SIZE_MAX
-		// and just return -1.  So just use the same
-		// size that Linux returns.
+	bufSize := C.sysconf(C._SC_GETPW_R_SIZE_MAX)
+	if bufSize == -1 {
+		// DragonFly and FreeBSD do not have _SC_GETPW_R_SIZE_MAX.
+		// Additionally, not all Linux systems have it, either. For
+		// example, the musl libc returns -1.
 		bufSize = 1024
-	} else {
-		bufSize = C.sysconf(C._SC_GETPW_R_SIZE_MAX)
-		if bufSize <= 0 || bufSize > 1<<20 {
-			return nil, fmt.Errorf("user: unreasonable _SC_GETPW_R_SIZE_MAX of %d", bufSize)
-		}
+	}
+	if bufSize <= 0 || bufSize > 1<<20 {
+		return nil, fmt.Errorf("user: unreasonable _SC_GETPW_R_SIZE_MAX of %d", bufSize)
 	}
 	buf := C.malloc(C.size_t(bufSize))
 	defer C.free(buf)
diff --git a/src/path/filepath/example_unix_test.go b/src/path/filepath/example_unix_test.go
index 27d85d1..893be1b 100644
--- a/src/path/filepath/example_unix_test.go
+++ b/src/path/filepath/example_unix_test.go
@@ -35,7 +35,7 @@ func ExampleRel() {
 	// On Unix:
 	// "/a/b/c": "b/c" <nil>
 	// "/b/c": "../b/c" <nil>
-	// "./b/c": "" Rel: can't make b/c relative to /a
+	// "./b/c": "" Rel: can't make ./b/c relative to /a
 }
 
 func ExampleSplit() {
diff --git a/src/path/filepath/match_test.go b/src/path/filepath/match_test.go
index 20ec5aa..0edbfc7 100644
--- a/src/path/filepath/match_test.go
+++ b/src/path/filepath/match_test.go
@@ -167,7 +167,7 @@ var globSymlinkTests = []struct {
 
 func TestGlobSymlink(t *testing.T) {
 	switch runtime.GOOS {
-	case "nacl", "plan9":
+	case "android", "nacl", "plan9":
 		t.Skipf("skipping on %s", runtime.GOOS)
 	case "windows":
 		if !supportsSymlinks {
diff --git a/src/path/filepath/path.go b/src/path/filepath/path.go
index 5dc5cfd..dd6f3e7 100644
--- a/src/path/filepath/path.go
+++ b/src/path/filepath/path.go
@@ -258,7 +258,7 @@ func Rel(basepath, targpath string) (string, error) {
 	targVol := VolumeName(targpath)
 	base := Clean(basepath)
 	targ := Clean(targpath)
-	if targ == base {
+	if sameWord(targ, base) {
 		return ".", nil
 	}
 	base = base[len(baseVol):]
@@ -269,8 +269,8 @@ func Rel(basepath, targpath string) (string, error) {
 	// Can't use IsAbs - `\a` and `a` are both relative in Windows.
 	baseSlashed := len(base) > 0 && base[0] == Separator
 	targSlashed := len(targ) > 0 && targ[0] == Separator
-	if baseSlashed != targSlashed || baseVol != targVol {
-		return "", errors.New("Rel: can't make " + targ + " relative to " + base)
+	if baseSlashed != targSlashed || !sameWord(baseVol, targVol) {
+		return "", errors.New("Rel: can't make " + targpath + " relative to " + basepath)
 	}
 	// Position base[b0:bi] and targ[t0:ti] at the first differing elements.
 	bl := len(base)
@@ -283,7 +283,7 @@ func Rel(basepath, targpath string) (string, error) {
 		for ti < tl && targ[ti] != Separator {
 			ti++
 		}
-		if targ[t0:ti] != base[b0:bi] {
+		if !sameWord(targ[t0:ti], base[b0:bi]) {
 			break
 		}
 		if bi < bl {
@@ -296,7 +296,7 @@ func Rel(basepath, targpath string) (string, error) {
 		t0 = ti
 	}
 	if base[b0:bi] == ".." {
-		return "", errors.New("Rel: can't make " + targ + " relative to " + base)
+		return "", errors.New("Rel: can't make " + targpath + " relative to " + basepath)
 	}
 	if b0 != bl {
 		// Base elements left. Must go up before going down.
diff --git a/src/path/filepath/path_plan9.go b/src/path/filepath/path_plan9.go
index 962774e..60d46d9 100644
--- a/src/path/filepath/path_plan9.go
+++ b/src/path/filepath/path_plan9.go
@@ -42,3 +42,7 @@ func join(elem []string) string {
 	}
 	return ""
 }
+
+func sameWord(a, b string) bool {
+	return a == b
+}
diff --git a/src/path/filepath/path_test.go b/src/path/filepath/path_test.go
index 1c32e27..baeee97 100644
--- a/src/path/filepath/path_test.go
+++ b/src/path/filepath/path_test.go
@@ -267,7 +267,12 @@ var winjointests = []JoinTest{
 	{[]string{`C:\Windows\`, `System32`}, `C:\Windows\System32`},
 	{[]string{`C:\Windows\`, ``}, `C:\Windows`},
 	{[]string{`C:\`, `Windows`}, `C:\Windows`},
-	{[]string{`C:`, `Windows`}, `C:\Windows`},
+	{[]string{`C:`, `a`}, `C:a`},
+	{[]string{`C:`, `a\b`}, `C:a\b`},
+	{[]string{`C:`, `a`, `b`}, `C:a\b`},
+	{[]string{`C:.`, `a`}, `C:a`},
+	{[]string{`C:a`, `b`}, `C:a\b`},
+	{[]string{`C:a`, `b`, `d`}, `C:a\b\d`},
 	{[]string{`\\host\share`, `foo`}, `\\host\share\foo`},
 	{[]string{`\\host\share\foo`}, `\\host\share\foo`},
 	{[]string{`//host/share`, `foo/bar`}, `\\host\share\foo\bar`},
@@ -402,18 +407,18 @@ func mark(path string, info os.FileInfo, err error, errors *[]error, clear bool)
 func chtmpdir(t *testing.T) (restore func()) {
 	oldwd, err := os.Getwd()
 	if err != nil {
-		t.Fatal("chtmpdir: %v", err)
+		t.Fatalf("chtmpdir: %v", err)
 	}
 	d, err := ioutil.TempDir("", "test")
 	if err != nil {
-		t.Fatal("chtmpdir: %v", err)
+		t.Fatalf("chtmpdir: %v", err)
 	}
 	if err := os.Chdir(d); err != nil {
-		t.Fatal("chtmpdir: %v", err)
+		t.Fatalf("chtmpdir: %v", err)
 	}
 	return func() {
 		if err := os.Chdir(oldwd); err != nil {
-			t.Fatal("chtmpdir: %v", err)
+			t.Fatalf("chtmpdir: %v", err)
 		}
 		os.RemoveAll(d)
 	}
@@ -752,8 +757,16 @@ var EvalSymlinksTests = []EvalSymlinksTest{
 	{"test/linkabs", "/"},
 }
 
-var EvalSymlinksAbsWindowsTests = []EvalSymlinksTest{
-	{`c:\`, `c:\`},
+// findEvalSymlinksTestDirsDest searches testDirs
+// for matching path and returns correspondent dest.
+func findEvalSymlinksTestDirsDest(t *testing.T, testDirs []EvalSymlinksTest, path string) string {
+	for _, d := range testDirs {
+		if d.path == path {
+			return d.dest
+		}
+	}
+	t.Fatalf("did not find %q in testDirs slice", path)
+	return ""
 }
 
 // simpleJoin builds a file name from the directory and path.
@@ -764,9 +777,12 @@ func simpleJoin(dir, path string) string {
 
 func TestEvalSymlinks(t *testing.T) {
 	switch runtime.GOOS {
-	case "nacl", "plan9":
+	case "android", "nacl", "plan9":
 		t.Skipf("skipping on %s", runtime.GOOS)
 	}
+	if !supportsSymlinks {
+		t.Skip("skipping because symlinks are not supported")
+	}
 
 	tmpDir, err := ioutil.TempDir("", "evalsymlink")
 	if err != nil {
@@ -781,38 +797,37 @@ func TestEvalSymlinks(t *testing.T) {
 		t.Fatal("eval symlink for tmp dir:", err)
 	}
 
+	tests := EvalSymlinksTests
+	testdirs := EvalSymlinksTestDirs
+	if runtime.GOOS == "windows" {
+		if len(tmpDir) < 3 {
+			t.Fatalf("tmpDir path %q is too short", tmpDir)
+		}
+		if tmpDir[1] != ':' {
+			t.Fatalf("tmpDir path %q must have drive letter in it", tmpDir)
+		}
+		newtest := EvalSymlinksTest{"test/linkabswin", tmpDir[:3]}
+		tests = append(tests, newtest)
+		testdirs = append(testdirs, newtest)
+	}
+
 	// Create the symlink farm using relative paths.
-	for _, d := range EvalSymlinksTestDirs {
+	for _, d := range testdirs {
 		var err error
 		path := simpleJoin(tmpDir, d.path)
 		if d.dest == "" {
 			err = os.Mkdir(path, 0755)
 		} else {
-			if supportsSymlinks {
-				err = os.Symlink(d.dest, path)
-			}
+			err = os.Symlink(d.dest, path)
 		}
 		if err != nil {
 			t.Fatal(err)
 		}
 	}
 
-	var tests []EvalSymlinksTest
-	if supportsSymlinks {
-		tests = EvalSymlinksTests
-	} else {
-		for _, d := range EvalSymlinksTests {
-			if d.path == d.dest {
-				// will test only real files and directories
-				tests = append(tests, d)
-				// test "canonical" names
-				d2 := EvalSymlinksTest{
-					path: strings.ToUpper(d.path),
-					dest: d.dest,
-				}
-				tests = append(tests, d2)
-			}
-		}
+	wd, err := os.Getwd()
+	if err != nil {
+		t.Fatal(err)
 	}
 
 	// Evaluate the symlink farm.
@@ -827,6 +842,125 @@ func TestEvalSymlinks(t *testing.T) {
 		} else if filepath.Clean(p) != filepath.Clean(dest) {
 			t.Errorf("Clean(%q)=%q, want %q", path, p, dest)
 		}
+
+		// test EvalSymlinks(".")
+		func() {
+			defer func() {
+				err := os.Chdir(wd)
+				if err != nil {
+					t.Fatal(err)
+				}
+			}()
+
+			err := os.Chdir(path)
+			if err != nil {
+				t.Error(err)
+				return
+			}
+			p, err := filepath.EvalSymlinks(".")
+			if err != nil {
+				t.Errorf(`EvalSymlinks(".") in %q directory error: %v`, d.path, err)
+				return
+			}
+			if p == "." {
+				return
+			}
+			want := filepath.Clean(findEvalSymlinksTestDirsDest(t, testdirs, d.path))
+			if p == want {
+				return
+			}
+			t.Errorf(`EvalSymlinks(".") in %q directory returns %q, want "." or %q`, d.path, p, want)
+		}()
+
+		// test EvalSymlinks where parameter is relative path
+		func() {
+			defer func() {
+				err := os.Chdir(wd)
+				if err != nil {
+					t.Fatal(err)
+				}
+			}()
+
+			err := os.Chdir(tmpDir)
+			if err != nil {
+				t.Error(err)
+				return
+			}
+			if p, err := filepath.EvalSymlinks(d.path); err != nil {
+				t.Errorf("EvalSymlinks(%q) error: %v", d.path, err)
+			} else if filepath.Clean(p) != filepath.Clean(d.dest) {
+				t.Errorf("Clean(%q)=%q, want %q", d.path, p, d.dest)
+			}
+		}()
+	}
+}
+
+func TestIssue13582(t *testing.T) {
+	switch runtime.GOOS {
+	case "android", "nacl", "plan9":
+		t.Skipf("skipping on %s", runtime.GOOS)
+	}
+	if !supportsSymlinks {
+		t.Skip("skipping because symlinks are not supported")
+	}
+
+	tmpDir, err := ioutil.TempDir("", "issue13582")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(tmpDir)
+
+	dir := filepath.Join(tmpDir, "dir")
+	err = os.Mkdir(dir, 0755)
+	if err != nil {
+		t.Fatal(err)
+	}
+	linkToDir := filepath.Join(tmpDir, "link_to_dir")
+	err = os.Symlink(dir, linkToDir)
+	if err != nil {
+		t.Fatal(err)
+	}
+	file := filepath.Join(linkToDir, "file")
+	err = ioutil.WriteFile(file, nil, 0644)
+	if err != nil {
+		t.Fatal(err)
+	}
+	link1 := filepath.Join(linkToDir, "link1")
+	err = os.Symlink(file, link1)
+	if err != nil {
+		t.Fatal(err)
+	}
+	link2 := filepath.Join(linkToDir, "link2")
+	err = os.Symlink(link1, link2)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// /tmp may itself be a symlink!
+	realTmpDir, err := filepath.EvalSymlinks(tmpDir)
+	if err != nil {
+		t.Fatal(err)
+	}
+	realDir := filepath.Join(realTmpDir, "dir")
+	realFile := filepath.Join(realDir, "file")
+
+	tests := []struct {
+		path, want string
+	}{
+		{dir, realDir},
+		{linkToDir, realDir},
+		{file, realFile},
+		{link1, realFile},
+		{link2, realFile},
+	}
+	for i, test := range tests {
+		have, err := filepath.EvalSymlinks(test.path)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if have != test.want {
+			t.Errorf("test#%d: EvalSymlinks(%q) returns %q, want %q", i, test.path, have, test.want)
+		}
 	}
 }
 
@@ -973,6 +1107,9 @@ var winreltests = []RelTests{
 	{`C:a\b\c`, `C:a/b/d`, `..\d`},
 	{`C:\`, `D:\`, `err`},
 	{`C:`, `D:`, `err`},
+	{`C:\Projects`, `c:\projects\src`, `src`},
+	{`C:\Projects`, `c:\projects`, `.`},
+	{`C:\Projects\a\..`, `c:\projects`, `.`},
 }
 
 func TestRel(t *testing.T) {
diff --git a/src/path/filepath/path_unix.go b/src/path/filepath/path_unix.go
index d241d78..2d242cc 100644
--- a/src/path/filepath/path_unix.go
+++ b/src/path/filepath/path_unix.go
@@ -44,3 +44,7 @@ func join(elem []string) string {
 	}
 	return ""
 }
+
+func sameWord(a, b string) bool {
+	return a == b
+}
diff --git a/src/path/filepath/path_windows.go b/src/path/filepath/path_windows.go
index bcfe0a3..ef6e7ca 100644
--- a/src/path/filepath/path_windows.go
+++ b/src/path/filepath/path_windows.go
@@ -120,6 +120,11 @@ func join(elem []string) string {
 
 // joinNonEmpty is like join, but it assumes that the first element is non-empty.
 func joinNonEmpty(elem []string) string {
+	if len(elem[0]) == 2 && elem[0][1] == ':' {
+		// First element is drive leter without terminating slash.
+		// Keep path relative to current directory on that drive.
+		return Clean(elem[0] + strings.Join(elem[1:], string(Separator)))
+	}
 	// The following logic prevents Join from inadvertently creating a
 	// UNC path on Windows. Unless the first element is a UNC path, Join
 	// shouldn't create a UNC path. See golang.org/issue/9167.
@@ -145,3 +150,7 @@ func joinNonEmpty(elem []string) string {
 func isUNC(path string) bool {
 	return volumeNameLen(path) > 2
 }
+
+func sameWord(a, b string) bool {
+	return strings.EqualFold(a, b)
+}
diff --git a/src/path/filepath/path_windows_test.go b/src/path/filepath/path_windows_test.go
index 100cf30..255c894 100644
--- a/src/path/filepath/path_windows_test.go
+++ b/src/path/filepath/path_windows_test.go
@@ -10,6 +10,7 @@ import (
 	"os/exec"
 	"path/filepath"
 	"reflect"
+	"strings"
 	"syscall"
 	"testing"
 )
@@ -111,3 +112,65 @@ func testWinSplitListTestIsValid(t *testing.T, ti int, tt SplitListTest,
 		}
 	}
 }
+
+// TestEvalSymlinksCanonicalNames verify that EvalSymlinks
+// returns "canonical" path names on windows.
+func TestEvalSymlinksCanonicalNames(t *testing.T) {
+	tmp, err := ioutil.TempDir("", "evalsymlinkcanonical")
+	if err != nil {
+		t.Fatal("creating temp dir:", err)
+	}
+	defer os.RemoveAll(tmp)
+
+	// ioutil.TempDir might return "non-canonical" name.
+	cTmpName, err := filepath.EvalSymlinks(tmp)
+	if err != nil {
+		t.Errorf("EvalSymlinks(%q) error: %v", tmp, err)
+	}
+
+	dirs := []string{
+		"test",
+		"test/dir",
+		"testing_long_dir",
+		"TEST2",
+	}
+
+	for _, d := range dirs {
+		dir := filepath.Join(cTmpName, d)
+		err := os.Mkdir(dir, 0755)
+		if err != nil {
+			t.Fatal(err)
+		}
+		cname, err := filepath.EvalSymlinks(dir)
+		if err != nil {
+			t.Errorf("EvalSymlinks(%q) error: %v", dir, err)
+			continue
+		}
+		if dir != cname {
+			t.Errorf("EvalSymlinks(%q) returns %q, but should return %q", dir, cname, dir)
+			continue
+		}
+		// test non-canonical names
+		test := strings.ToUpper(dir)
+		p, err := filepath.EvalSymlinks(test)
+		if err != nil {
+			t.Errorf("EvalSymlinks(%q) error: %v", test, err)
+			continue
+		}
+		if p != cname {
+			t.Errorf("EvalSymlinks(%q) returns %q, but should return %q", test, p, cname)
+			continue
+		}
+		// another test
+		test = strings.ToLower(dir)
+		p, err = filepath.EvalSymlinks(test)
+		if err != nil {
+			t.Errorf("EvalSymlinks(%q) error: %v", test, err)
+			continue
+		}
+		if p != cname {
+			t.Errorf("EvalSymlinks(%q) returns %q, but should return %q", test, p, cname)
+			continue
+		}
+	}
+}
diff --git a/src/path/filepath/symlink.go b/src/path/filepath/symlink.go
index df0a9e0..bc287c5 100644
--- a/src/path/filepath/symlink.go
+++ b/src/path/filepath/symlink.go
@@ -5,68 +5,113 @@
 package filepath
 
 import (
-	"bytes"
 	"errors"
 	"os"
+	"runtime"
 )
 
-const utf8RuneSelf = 0x80
+// isRoot returns true if path is root of file system
+// (`/` on unix and `/`, `\`, `c:\` or `c:/` on windows).
+func isRoot(path string) bool {
+	if runtime.GOOS != "windows" {
+		return path == "/"
+	}
+	switch len(path) {
+	case 1:
+		return os.IsPathSeparator(path[0])
+	case 3:
+		return path[1] == ':' && os.IsPathSeparator(path[2])
+	}
+	return false
+}
 
-func walkSymlinks(path string) (string, error) {
-	const maxIter = 255
-	originalPath := path
-	// consume path by taking each frontmost path element,
-	// expanding it if it's a symlink, and appending it to b
-	var b bytes.Buffer
-	for n := 0; path != ""; n++ {
-		if n > maxIter {
-			return "", errors.New("EvalSymlinks: too many links in " + originalPath)
-		}
+// isDriveLetter returns true if path is Windows drive letter (like "c:").
+func isDriveLetter(path string) bool {
+	if runtime.GOOS != "windows" {
+		return false
+	}
+	return len(path) == 2 && path[1] == ':'
+}
 
-		// find next path component, p
-		var i = -1
-		for j, c := range path {
-			if c < utf8RuneSelf && os.IsPathSeparator(uint8(c)) {
-				i = j
-				break
-			}
-		}
-		var p string
-		if i == -1 {
-			p, path = path, ""
-		} else {
-			p, path = path[:i], path[i+1:]
-		}
+func walkLink(path string, linksWalked *int) (newpath string, islink bool, err error) {
+	if *linksWalked > 255 {
+		return "", false, errors.New("EvalSymlinks: too many links")
+	}
+	fi, err := os.Lstat(path)
+	if err != nil {
+		return "", false, err
+	}
+	if fi.Mode()&os.ModeSymlink == 0 {
+		return path, false, nil
+	}
+	newpath, err = os.Readlink(path)
+	if err != nil {
+		return "", false, err
+	}
+	*linksWalked++
+	return newpath, true, nil
+}
 
-		if p == "" {
-			if b.Len() == 0 {
-				// must be absolute path
-				b.WriteRune(Separator)
+func walkLinks(path string, linksWalked *int) (string, error) {
+	switch dir, file := Split(path); {
+	case dir == "":
+		newpath, _, err := walkLink(file, linksWalked)
+		return newpath, err
+	case file == "":
+		if isDriveLetter(dir) {
+			return dir, nil
+		}
+		if os.IsPathSeparator(dir[len(dir)-1]) {
+			if isRoot(dir) {
+				return dir, nil
 			}
-			continue
+			return walkLinks(dir[:len(dir)-1], linksWalked)
 		}
-
-		fi, err := os.Lstat(b.String() + p)
+		newpath, _, err := walkLink(dir, linksWalked)
+		return newpath, err
+	default:
+		newdir, err := walkLinks(dir, linksWalked)
 		if err != nil {
 			return "", err
 		}
-		if fi.Mode()&os.ModeSymlink == 0 {
-			b.WriteString(p)
-			if path != "" || (b.Len() == 2 && len(p) == 2 && p[1] == ':') {
-				b.WriteRune(Separator)
-			}
-			continue
+		newpath, islink, err := walkLink(Join(newdir, file), linksWalked)
+		if err != nil {
+			return "", err
+		}
+		if !islink {
+			return newpath, nil
 		}
+		if IsAbs(newpath) || os.IsPathSeparator(newpath[0]) {
+			return newpath, nil
+		}
+		return Join(newdir, newpath), nil
+	}
+}
 
-		// it's a symlink, put it at the front of path
-		dest, err := os.Readlink(b.String() + p)
+func walkSymlinks(path string) (string, error) {
+	if path == "" {
+		return path, nil
+	}
+	var linksWalked int // to protect against cycles
+	for {
+		i := linksWalked
+		newpath, err := walkLinks(path, &linksWalked)
 		if err != nil {
 			return "", err
 		}
-		if IsAbs(dest) || os.IsPathSeparator(dest[0]) {
-			b.Reset()
+		if runtime.GOOS == "windows" {
+			// walkLinks(".", ...) always retuns "." on unix.
+			// But on windows it returns symlink target, if current
+			// directory is a symlink. Stop the walk, if symlink
+			// target is not absolute path, and return "."
+			// to the caller (just like unix does).
+			if path == "." && !IsAbs(newpath) {
+				return ".", nil
+			}
+		}
+		if i == linksWalked {
+			return Clean(newpath), nil
 		}
-		path = dest + string(Separator) + path
+		path = newpath
 	}
-	return Clean(b.String()), nil
 }
diff --git a/src/path/filepath/symlink_windows.go b/src/path/filepath/symlink_windows.go
index 4b38f6f..eb48367 100644
--- a/src/path/filepath/symlink_windows.go
+++ b/src/path/filepath/symlink_windows.go
@@ -51,7 +51,6 @@ func evalSymlinks(path string) (string, error) {
 	if err != nil {
 		return "", err
 	}
-
 	p, err := toShort(path)
 	if err != nil {
 		return "", err
diff --git a/src/path/path.go b/src/path/path.go
index 77f2185..01071a9 100644
--- a/src/path/path.go
+++ b/src/path/path.go
@@ -136,7 +136,7 @@ func Clean(path string) string {
 
 // Split splits path immediately following the final slash,
 // separating it into a directory and file name component.
-// If there is no slash path, Split returns an empty dir and
+// If there is no slash in path, Split returns an empty dir and
 // file set to path.
 // The returned values have the property that path = dir+file.
 func Split(path string) (dir, file string) {
diff --git a/src/race.bash b/src/race.bash
index e091736..adf2297 100755
--- a/src/race.bash
+++ b/src/race.bash
@@ -41,4 +41,4 @@ if [ ! -f make.bash ]; then
 fi
 . ./make.bash --no-banner
 go install -race std
-go tool dist test -no-rebuild -race
+go tool dist test -race
diff --git a/src/race.bat b/src/race.bat
index 33db692..e8df480 100644
--- a/src/race.bat
+++ b/src/race.bat
@@ -34,7 +34,7 @@ echo # go install -race std
 go install -race std
 if errorlevel 1 goto fail
 
-go tool dist test -no-rebuild -race
+go tool dist test -race
 
 if errorlevel 1 goto fail
 goto succ
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index 1748bf6..c80df34 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -10,6 +10,7 @@ import (
 	"flag"
 	"fmt"
 	"io"
+	"math"
 	"math/rand"
 	"os"
 	. "reflect"
@@ -647,6 +648,8 @@ var (
 	fn3 = func() { fn1() } // Not nil.
 )
 
+type self struct{}
+
 var deepEqualTests = []DeepEqualTest{
 	// Equalities
 	{nil, nil, true},
@@ -681,6 +684,13 @@ var deepEqualTests = []DeepEqualTest{
 	{fn1, fn3, false},
 	{fn3, fn3, false},
 	{[][]int{{1}}, [][]int{{2}}, false},
+	{math.NaN(), math.NaN(), false},
+	{&[1]float64{math.NaN()}, &[1]float64{math.NaN()}, false},
+	{&[1]float64{math.NaN()}, self{}, true},
+	{[]float64{math.NaN()}, []float64{math.NaN()}, false},
+	{[]float64{math.NaN()}, self{}, true},
+	{map[float64]float64{math.NaN(): 1}, map[float64]float64{1: 2}, false},
+	{map[float64]float64{math.NaN(): 1}, self{}, true},
 
 	// Nil vs empty: not the same.
 	{[]int{}, []int(nil), false},
@@ -702,6 +712,9 @@ var deepEqualTests = []DeepEqualTest{
 
 func TestDeepEqual(t *testing.T) {
 	for _, test := range deepEqualTests {
+		if test.b == (self{}) {
+			test.b = test.a
+		}
 		if r := DeepEqual(test.a, test.b); r != test.eq {
 			t.Errorf("DeepEqual(%v, %v) = %v, want %v", test.a, test.b, r, test.eq)
 		}
@@ -2776,14 +2789,27 @@ func TestSetBytes(t *testing.T) {
 type Private struct {
 	x int
 	y **int
+	Z int
 }
 
 func (p *Private) m() {
 }
 
+type private struct {
+	Z int
+	z int
+	S string
+	A [1]Private
+	T []Private
+}
+
+func (p *private) P() {
+}
+
 type Public struct {
 	X int
 	Y **int
+	private
 }
 
 func (p *Public) M() {
@@ -2791,17 +2817,30 @@ func (p *Public) M() {
 
 func TestUnexported(t *testing.T) {
 	var pub Public
+	pub.S = "S"
+	pub.T = pub.A[:]
 	v := ValueOf(&pub)
 	isValid(v.Elem().Field(0))
 	isValid(v.Elem().Field(1))
+	isValid(v.Elem().Field(2))
 	isValid(v.Elem().FieldByName("X"))
 	isValid(v.Elem().FieldByName("Y"))
+	isValid(v.Elem().FieldByName("Z"))
 	isValid(v.Type().Method(0).Func)
+	m, _ := v.Type().MethodByName("M")
+	isValid(m.Func)
+	m, _ = v.Type().MethodByName("P")
+	isValid(m.Func)
 	isNonNil(v.Elem().Field(0).Interface())
 	isNonNil(v.Elem().Field(1).Interface())
+	isNonNil(v.Elem().Field(2).Field(2).Index(0))
 	isNonNil(v.Elem().FieldByName("X").Interface())
 	isNonNil(v.Elem().FieldByName("Y").Interface())
+	isNonNil(v.Elem().FieldByName("Z").Interface())
+	isNonNil(v.Elem().FieldByName("S").Index(0).Interface())
 	isNonNil(v.Type().Method(0).Func.Interface())
+	m, _ = v.Type().MethodByName("P")
+	isNonNil(m.Func.Interface())
 
 	var priv Private
 	v = ValueOf(&priv)
@@ -2817,6 +2856,170 @@ func TestUnexported(t *testing.T) {
 	shouldPanic(func() { v.Type().Method(0).Func.Interface() })
 }
 
+func TestSetPanic(t *testing.T) {
+	ok := func(f func()) { f() }
+	bad := shouldPanic
+	clear := func(v Value) { v.Set(Zero(v.Type())) }
+
+	type t0 struct {
+		W int
+	}
+
+	type t1 struct {
+		Y int
+		t0
+	}
+
+	type T2 struct {
+		Z       int
+		namedT0 t0
+	}
+
+	type T struct {
+		X int
+		t1
+		T2
+		NamedT1 t1
+		NamedT2 T2
+		namedT1 t1
+		namedT2 T2
+	}
+
+	// not addressable
+	v := ValueOf(T{})
+	bad(func() { clear(v.Field(0)) })                   // .X
+	bad(func() { clear(v.Field(1)) })                   // .t1
+	bad(func() { clear(v.Field(1).Field(0)) })          // .t1.Y
+	bad(func() { clear(v.Field(1).Field(1)) })          // .t1.t0
+	bad(func() { clear(v.Field(1).Field(1).Field(0)) }) // .t1.t0.W
+	bad(func() { clear(v.Field(2)) })                   // .T2
+	bad(func() { clear(v.Field(2).Field(0)) })          // .T2.Z
+	bad(func() { clear(v.Field(2).Field(1)) })          // .T2.namedT0
+	bad(func() { clear(v.Field(2).Field(1).Field(0)) }) // .T2.namedT0.W
+	bad(func() { clear(v.Field(3)) })                   // .NamedT1
+	bad(func() { clear(v.Field(3).Field(0)) })          // .NamedT1.Y
+	bad(func() { clear(v.Field(3).Field(1)) })          // .NamedT1.t0
+	bad(func() { clear(v.Field(3).Field(1).Field(0)) }) // .NamedT1.t0.W
+	bad(func() { clear(v.Field(4)) })                   // .NamedT2
+	bad(func() { clear(v.Field(4).Field(0)) })          // .NamedT2.Z
+	bad(func() { clear(v.Field(4).Field(1)) })          // .NamedT2.namedT0
+	bad(func() { clear(v.Field(4).Field(1).Field(0)) }) // .NamedT2.namedT0.W
+	bad(func() { clear(v.Field(5)) })                   // .namedT1
+	bad(func() { clear(v.Field(5).Field(0)) })          // .namedT1.Y
+	bad(func() { clear(v.Field(5).Field(1)) })          // .namedT1.t0
+	bad(func() { clear(v.Field(5).Field(1).Field(0)) }) // .namedT1.t0.W
+	bad(func() { clear(v.Field(6)) })                   // .namedT2
+	bad(func() { clear(v.Field(6).Field(0)) })          // .namedT2.Z
+	bad(func() { clear(v.Field(6).Field(1)) })          // .namedT2.namedT0
+	bad(func() { clear(v.Field(6).Field(1).Field(0)) }) // .namedT2.namedT0.W
+
+	// addressable
+	v = ValueOf(&T{}).Elem()
+	ok(func() { clear(v.Field(0)) })                    // .X
+	bad(func() { clear(v.Field(1)) })                   // .t1
+	ok(func() { clear(v.Field(1).Field(0)) })           // .t1.Y
+	bad(func() { clear(v.Field(1).Field(1)) })          // .t1.t0
+	ok(func() { clear(v.Field(1).Field(1).Field(0)) })  // .t1.t0.W
+	ok(func() { clear(v.Field(2)) })                    // .T2
+	ok(func() { clear(v.Field(2).Field(0)) })           // .T2.Z
+	bad(func() { clear(v.Field(2).Field(1)) })          // .T2.namedT0
+	bad(func() { clear(v.Field(2).Field(1).Field(0)) }) // .T2.namedT0.W
+	ok(func() { clear(v.Field(3)) })                    // .NamedT1
+	ok(func() { clear(v.Field(3).Field(0)) })           // .NamedT1.Y
+	bad(func() { clear(v.Field(3).Field(1)) })          // .NamedT1.t0
+	ok(func() { clear(v.Field(3).Field(1).Field(0)) })  // .NamedT1.t0.W
+	ok(func() { clear(v.Field(4)) })                    // .NamedT2
+	ok(func() { clear(v.Field(4).Field(0)) })           // .NamedT2.Z
+	bad(func() { clear(v.Field(4).Field(1)) })          // .NamedT2.namedT0
+	bad(func() { clear(v.Field(4).Field(1).Field(0)) }) // .NamedT2.namedT0.W
+	bad(func() { clear(v.Field(5)) })                   // .namedT1
+	bad(func() { clear(v.Field(5).Field(0)) })          // .namedT1.Y
+	bad(func() { clear(v.Field(5).Field(1)) })          // .namedT1.t0
+	bad(func() { clear(v.Field(5).Field(1).Field(0)) }) // .namedT1.t0.W
+	bad(func() { clear(v.Field(6)) })                   // .namedT2
+	bad(func() { clear(v.Field(6).Field(0)) })          // .namedT2.Z
+	bad(func() { clear(v.Field(6).Field(1)) })          // .namedT2.namedT0
+	bad(func() { clear(v.Field(6).Field(1).Field(0)) }) // .namedT2.namedT0.W
+}
+
+type timp int
+
+func (t timp) W() {}
+func (t timp) Y() {}
+func (t timp) w() {}
+func (t timp) y() {}
+
+func TestCallPanic(t *testing.T) {
+	type t0 interface {
+		W()
+		w()
+	}
+	type T1 interface {
+		Y()
+		y()
+	}
+	type T2 struct {
+		T1
+		t0
+	}
+	type T struct {
+		t0 // 0
+		T1 // 1
+
+		NamedT0 t0 // 2
+		NamedT1 T1 // 3
+		NamedT2 T2 // 4
+
+		namedT0 t0 // 5
+		namedT1 T1 // 6
+		namedT2 T2 // 7
+	}
+	ok := func(f func()) { f() }
+	bad := shouldPanic
+	call := func(v Value) { v.Call(nil) }
+
+	i := timp(0)
+	v := ValueOf(T{i, i, i, i, T2{i, i}, i, i, T2{i, i}})
+	ok(func() { call(v.Field(0).Method(0)) })         // .t0.W
+	ok(func() { call(v.Field(0).Elem().Method(0)) })  // .t0.W
+	bad(func() { call(v.Field(0).Method(1)) })        // .t0.w
+	bad(func() { call(v.Field(0).Elem().Method(2)) }) // .t0.w
+	ok(func() { call(v.Field(1).Method(0)) })         // .T1.Y
+	ok(func() { call(v.Field(1).Elem().Method(0)) })  // .T1.Y
+	bad(func() { call(v.Field(1).Method(1)) })        // .T1.y
+	bad(func() { call(v.Field(1).Elem().Method(2)) }) // .T1.y
+
+	ok(func() { call(v.Field(2).Method(0)) })         // .NamedT0.W
+	ok(func() { call(v.Field(2).Elem().Method(0)) })  // .NamedT0.W
+	bad(func() { call(v.Field(2).Method(1)) })        // .NamedT0.w
+	bad(func() { call(v.Field(2).Elem().Method(2)) }) // .NamedT0.w
+
+	ok(func() { call(v.Field(3).Method(0)) })         // .NamedT1.Y
+	ok(func() { call(v.Field(3).Elem().Method(0)) })  // .NamedT1.Y
+	bad(func() { call(v.Field(3).Method(1)) })        // .NamedT1.y
+	bad(func() { call(v.Field(3).Elem().Method(3)) }) // .NamedT1.y
+
+	ok(func() { call(v.Field(4).Field(0).Method(0)) })        // .NamedT2.T1.Y
+	ok(func() { call(v.Field(4).Field(0).Elem().Method(0)) }) // .NamedT2.T1.W
+	ok(func() { call(v.Field(4).Field(1).Method(0)) })        // .NamedT2.t0.W
+	ok(func() { call(v.Field(4).Field(1).Elem().Method(0)) }) // .NamedT2.t0.W
+
+	bad(func() { call(v.Field(5).Method(0)) })        // .namedT0.W
+	bad(func() { call(v.Field(5).Elem().Method(0)) }) // .namedT0.W
+	bad(func() { call(v.Field(5).Method(1)) })        // .namedT0.w
+	bad(func() { call(v.Field(5).Elem().Method(2)) }) // .namedT0.w
+
+	bad(func() { call(v.Field(6).Method(0)) })        // .namedT1.Y
+	bad(func() { call(v.Field(6).Elem().Method(0)) }) // .namedT1.Y
+	bad(func() { call(v.Field(6).Method(0)) })        // .namedT1.y
+	bad(func() { call(v.Field(6).Elem().Method(0)) }) // .namedT1.y
+
+	bad(func() { call(v.Field(7).Field(0).Method(0)) })        // .namedT2.T1.Y
+	bad(func() { call(v.Field(7).Field(0).Elem().Method(0)) }) // .namedT2.T1.W
+	bad(func() { call(v.Field(7).Field(1).Method(0)) })        // .namedT2.t0.W
+	bad(func() { call(v.Field(7).Field(1).Elem().Method(0)) }) // .namedT2.t0.W
+}
+
 func shouldPanic(f func()) {
 	defer func() {
 		if recover() == nil {
@@ -4775,3 +4978,32 @@ func TestPtrToMethods(t *testing.T) {
 		t.Fatal("does not implement Stringer, but should")
 	}
 }
+
+func TestMapAlloc(t *testing.T) {
+	m := ValueOf(make(map[int]int, 10))
+	k := ValueOf(5)
+	v := ValueOf(7)
+	allocs := testing.AllocsPerRun(100, func() {
+		m.SetMapIndex(k, v)
+	})
+	if allocs > 0.5 {
+		t.Errorf("allocs per map assignment: want 0 got %f", allocs)
+	}
+}
+
+func TestChanAlloc(t *testing.T) {
+	// Note: for a chan int, the return Value must be allocated, so we
+	// use a chan *int instead.
+	c := ValueOf(make(chan *int, 1))
+	v := ValueOf(new(int))
+	allocs := testing.AllocsPerRun(100, func() {
+		c.Send(v)
+		_, _ = c.Recv()
+	})
+	if allocs < 0.5 || allocs > 1.5 {
+		t.Errorf("allocs per chan send/recv: want 1 got %f", allocs)
+	}
+	// Note: there is one allocation in reflect.recv which seems to be
+	// a limitation of escape analysis.  If that is ever fixed the
+	// allocs < 0.5 condition will trigger and this test should be fixed.
+}
diff --git a/src/reflect/asm_mips64x.s b/src/reflect/asm_mips64x.s
new file mode 100644
index 0000000..159d3d5
--- /dev/null
+++ b/src/reflect/asm_mips64x.s
@@ -0,0 +1,34 @@
+// Copyright 2015 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.
+
+// +build mips64 mips64le
+
+#include "textflag.h"
+#include "funcdata.h"
+
+#define	REGCTXT	R22
+
+// makeFuncStub is the code half of the function returned by MakeFunc.
+// See the comment on the declaration of makeFuncStub in makefunc.go
+// for more details.
+// No arg size here, runtime pulls arg map out of the func value.
+TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
+	NO_LOCAL_POINTERS
+	MOVV	REGCTXT, 8(R29)
+	MOVV	$argframe+0(FP), R1
+	MOVV	R1, 16(R29)
+	JAL	·callReflect(SB)
+	RET
+
+// methodValueCall is the code half of the function returned by makeMethodValue.
+// See the comment on the declaration of methodValueCall in makefunc.go
+// for more details.
+// No arg size here; runtime pulls arg map out of the func value.
+TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
+	NO_LOCAL_POINTERS
+	MOVV	REGCTXT, 8(R29)
+	MOVV	$argframe+0(FP), R1
+	MOVV	R1, 16(R29)
+	JAL	·callMethod(SB)
+	RET
diff --git a/src/reflect/asm_ppc64x.s b/src/reflect/asm_ppc64x.s
index d5f7f8f..0fa570c 100644
--- a/src/reflect/asm_ppc64x.s
+++ b/src/reflect/asm_ppc64x.s
@@ -6,6 +6,7 @@
 
 #include "textflag.h"
 #include "funcdata.h"
+#include "asm_ppc64x.h"
 
 // makeFuncStub is the code half of the function returned by MakeFunc.
 // See the comment on the declaration of makeFuncStub in makefunc.go
@@ -13,9 +14,9 @@
 // No arg size here, runtime pulls arg map out of the func value.
 TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
 	NO_LOCAL_POINTERS
-	MOVD	R11, 8(R1)
+	MOVD	R11, FIXED_FRAME+0(R1)
 	MOVD	$argframe+0(FP), R3
-	MOVD	R3, 16(R1)
+	MOVD	R3, FIXED_FRAME+8(R1)
 	BL	·callReflect(SB)
 	RET
 
@@ -25,8 +26,8 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$16
 // No arg size here; runtime pulls arg map out of the func value.
 TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$16
 	NO_LOCAL_POINTERS
-	MOVD	R11, 8(R1)
+	MOVD	R11, FIXED_FRAME+0(R1)
 	MOVD	$argframe+0(FP), R3
-	MOVD	R3, 16(R1)
+	MOVD	R3, FIXED_FRAME+8(R1)
 	BL	·callMethod(SB)
 	RET
diff --git a/src/reflect/deepequal.go b/src/reflect/deepequal.go
index f63715c..3743e80 100644
--- a/src/reflect/deepequal.go
+++ b/src/reflect/deepequal.go
@@ -6,13 +6,15 @@
 
 package reflect
 
+import "unsafe"
+
 // During deepValueEqual, must keep track of checks that are
 // in progress.  The comparison algorithm assumes that all
 // checks in progress are true when it reencounters them.
 // Visited comparisons are stored in a map indexed by visit.
 type visit struct {
-	a1  uintptr
-	a2  uintptr
+	a1  unsafe.Pointer
+	a2  unsafe.Pointer
 	typ Type
 }
 
@@ -37,19 +39,15 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool {
 	}
 
 	if v1.CanAddr() && v2.CanAddr() && hard(v1.Kind()) {
-		addr1 := v1.UnsafeAddr()
-		addr2 := v2.UnsafeAddr()
-		if addr1 > addr2 {
+		addr1 := unsafe.Pointer(v1.UnsafeAddr())
+		addr2 := unsafe.Pointer(v2.UnsafeAddr())
+		if uintptr(addr1) > uintptr(addr2) {
 			// Canonicalize order to reduce number of entries in visited.
+			// Assumes non-moving garbage collector.
 			addr1, addr2 = addr2, addr1
 		}
 
-		// Short circuit if references are identical ...
-		if addr1 == addr2 {
-			return true
-		}
-
-		// ... or already seen
+		// Short circuit if references are already seen.
 		typ := v1.Type()
 		v := visit{addr1, addr2, typ}
 		if visited[v] {
@@ -90,6 +88,9 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool {
 		}
 		return deepValueEqual(v1.Elem(), v2.Elem(), visited, depth+1)
 	case Ptr:
+		if v1.Pointer() == v2.Pointer() {
+			return true
+		}
 		return deepValueEqual(v1.Elem(), v2.Elem(), visited, depth+1)
 	case Struct:
 		for i, n := 0, v1.NumField(); i < n; i++ {
@@ -109,7 +110,9 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool {
 			return true
 		}
 		for _, k := range v1.MapKeys() {
-			if !deepValueEqual(v1.MapIndex(k), v2.MapIndex(k), visited, depth+1) {
+			val1 := v1.MapIndex(k)
+			val2 := v2.MapIndex(k)
+			if !val1.IsValid() || !val2.IsValid() || !deepValueEqual(v1.MapIndex(k), v2.MapIndex(k), visited, depth+1) {
 				return false
 			}
 		}
@@ -126,18 +129,56 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool {
 	}
 }
 
-// DeepEqual tests for deep equality. It uses normal == equality where
-// possible but will scan elements of arrays, slices, maps, and fields of
-// structs. In maps, keys are compared with == but elements use deep
-// equality. DeepEqual correctly handles recursive types. Functions are equal
-// only if they are both nil.
-// An empty slice is not equal to a nil slice.
-func DeepEqual(a1, a2 interface{}) bool {
-	if a1 == nil || a2 == nil {
-		return a1 == a2
+// DeepEqual reports whether x and y are ``deeply equal,'' defined as follows.
+// Two values of identical type are deeply equal if one of the following cases applies.
+// Values of distinct types are never deeply equal.
+//
+// Array values are deeply equal when their corresponding elements are deeply equal.
+//
+// Struct values are deeply equal if their corresponding fields,
+// both exported and unexported, are deeply equal.
+//
+// Func values are deeply equal if both are nil; otherwise they are not deeply equal.
+//
+// Interface values are deeply equal if they hold deeply equal concrete values.
+//
+// Map values are deeply equal if they are the same map object
+// or if they have the same length and their corresponding keys
+// (matched using Go equality) map to deeply equal values.
+//
+// Pointer values are deeply equal if they are equal using Go's == operator
+// or if they point to deeply equal values.
+//
+// Slice values are deeply equal when all of the following are true:
+// they are both nil or both non-nil, they have the same length,
+// and either they point to the same initial entry of the same underlying array
+// (that is, &x[0] == &y[0]) or their corresponding elements (up to length) are deeply equal.
+// Note that a non-nil empty slice and a nil slice (for example, []byte{} and []byte(nil))
+// are not deeply equal.
+//
+// Other values - numbers, bools, strings, and channels - are deeply equal
+// if they are equal using Go's == operator.
+//
+// In general DeepEqual is a recursive relaxation of Go's == operator.
+// However, this idea is impossible to implement without some inconsistency.
+// Specifically, it is possible for a value to be unequal to itself,
+// either because it is of func type (uncomparable in general)
+// or because it is a floating-point NaN value (not equal to itself in floating-point comparison),
+// or because it is an array, struct, or interface containing
+// such a value.
+// On the other hand, pointer values are always equal to themselves,
+// even if they point at or contain such problematic values,
+// because they compare equal using Go's == operator, and that
+// is a sufficient condition to be deeply equal, regardless of content.
+// DeepEqual has been defined so that the same short-cut applies
+// to slices and maps: if x and y are the same slice or the same map,
+// they are deeply equal regardless of content.
+func DeepEqual(x, y interface{}) bool {
+	if x == nil || y == nil {
+		return x == y
 	}
-	v1 := ValueOf(a1)
-	v2 := ValueOf(a2)
+	v1 := ValueOf(x)
+	v2 := ValueOf(y)
 	if v1.Type() != v2.Type() {
 		return false
 	}
diff --git a/src/reflect/export_test.go b/src/reflect/export_test.go
index 0b9d0fd..26a648e 100644
--- a/src/reflect/export_test.go
+++ b/src/reflect/export_test.go
@@ -8,13 +8,13 @@ import "unsafe"
 
 // MakeRO returns a copy of v with the read-only flag set.
 func MakeRO(v Value) Value {
-	v.flag |= flagRO
+	v.flag |= flagStickyRO
 	return v
 }
 
 // IsRO reports whether v's read-only flag is set.
 func IsRO(v Value) bool {
-	return v.flag&flagRO != 0
+	return v.flag&flagStickyRO != 0
 }
 
 var CallGC = &callGC
diff --git a/src/reflect/type.go b/src/reflect/type.go
index e20e5cf..003c610 100644
--- a/src/reflect/type.go
+++ b/src/reflect/type.go
@@ -247,17 +247,16 @@ const (
 type rtype struct {
 	size          uintptr
 	ptrdata       uintptr
-	hash          uint32         // hash of type; avoids computation in hash tables
-	_             uint8          // unused/padding
-	align         uint8          // alignment of variable with this type
-	fieldAlign    uint8          // alignment of struct field with this type
-	kind          uint8          // enumeration for C
-	alg           *typeAlg       // algorithm table
-	gcdata        *byte          // garbage collection data
-	string        *string        // string form; unnecessary but undeniably useful
-	*uncommonType                // (relatively) uncommon fields
-	ptrToThis     *rtype         // type for pointer to this type, if used in binary or has methods
-	zero          unsafe.Pointer // pointer to zero value
+	hash          uint32   // hash of type; avoids computation in hash tables
+	_             uint8    // unused/padding
+	align         uint8    // alignment of variable with this type
+	fieldAlign    uint8    // alignment of struct field with this type
+	kind          uint8    // enumeration for C
+	alg           *typeAlg // algorithm table
+	gcdata        *byte    // garbage collection data
+	string        *string  // string form; unnecessary but undeniably useful
+	*uncommonType          // (relatively) uncommon fields
+	ptrToThis     *rtype   // type for pointer to this type, if used in binary or has methods
 }
 
 // a copy of runtime.typeAlg
@@ -348,6 +347,7 @@ type mapType struct {
 	indirectvalue uint8  // store ptr to value instead of value itself
 	bucketsize    uint16 // size of bucket
 	reflexivekey  bool   // true if k==k for all keys
+	needkeyupdate bool   // true if we need to update key on an overwrite
 }
 
 // ptrType represents a pointer type.
@@ -496,7 +496,7 @@ func (t *uncommonType) Method(i int) (m Method) {
 	fl := flag(Func)
 	if p.pkgPath != nil {
 		m.PkgPath = *p.pkgPath
-		fl |= flagRO
+		fl |= flagStickyRO
 	}
 	mt := p.typ
 	m.Type = mt
@@ -735,10 +735,10 @@ func (t *interfaceType) MethodByName(name string) (m Method, ok bool) {
 // A StructField describes a single field in a struct.
 type StructField struct {
 	// Name is the field name.
+	Name string
 	// PkgPath is the package path that qualifies a lower case (unexported)
 	// field name.  It is empty for upper case (exported) field names.
 	// See https://golang.org/ref/spec#Uniqueness_of_identifiers
-	Name    string
 	PkgPath string
 
 	Type      Type      // field type
@@ -1526,6 +1526,7 @@ func MapOf(key, elem Type) Type {
 	}
 	mt.bucketsize = uint16(mt.bucket.size)
 	mt.reflexivekey = isReflexive(ktyp)
+	mt.needkeyupdate = needKeyUpdate(ktyp)
 	mt.uncommonType = nil
 	mt.ptrToThis = nil
 
@@ -1670,6 +1671,33 @@ func isReflexive(t *rtype) bool {
 	}
 }
 
+// needKeyUpdate reports whether map overwrites require the key to be copied.
+func needKeyUpdate(t *rtype) bool {
+	switch t.Kind() {
+	case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Ptr, UnsafePointer:
+		return false
+	case Float32, Float64, Complex64, Complex128, Interface, String:
+		// Float keys can be updated from +0 to -0.
+		// String keys can be updated to use a smaller backing store.
+		// Interfaces might have floats of strings in them.
+		return true
+	case Array:
+		tt := (*arrayType)(unsafe.Pointer(t))
+		return needKeyUpdate(tt.elem)
+	case Struct:
+		tt := (*structType)(unsafe.Pointer(t))
+		for _, f := range tt.fields {
+			if needKeyUpdate(f.typ) {
+				return true
+			}
+		}
+		return false
+	default:
+		// Func, Map, Slice, Invalid
+		panic("needKeyUpdate called on non-key type " + t.String())
+	}
+}
+
 // Make sure these routines stay in sync with ../../runtime/hashmap.go!
 // These types exist only for GC, so we only fill out GC relevant info.
 // Currently, that's just size and the GC program.  We also fill in string
diff --git a/src/reflect/value.go b/src/reflect/value.go
index 001d027..182c45a 100644
--- a/src/reflect/value.go
+++ b/src/reflect/value.go
@@ -44,7 +44,8 @@ type Value struct {
 
 	// flag holds metadata about the value.
 	// The lowest bits are flag bits:
-	//	- flagRO: obtained via unexported field, so read-only
+	//	- flagStickyRO: obtained via unexported not embedded field, so read-only
+	//	- flagEmbedRO: obtained via unexported embedded field, so read-only
 	//	- flagIndir: val holds a pointer to the data
 	//	- flagAddr: v.CanAddr is true (implies flagIndir)
 	//	- flagMethod: v is a method value.
@@ -67,11 +68,13 @@ type flag uintptr
 const (
 	flagKindWidth        = 5 // there are 27 kinds
 	flagKindMask    flag = 1<<flagKindWidth - 1
-	flagRO          flag = 1 << 5
-	flagIndir       flag = 1 << 6
-	flagAddr        flag = 1 << 7
-	flagMethod      flag = 1 << 8
-	flagMethodShift      = 9
+	flagStickyRO    flag = 1 << 5
+	flagEmbedRO     flag = 1 << 6
+	flagIndir       flag = 1 << 7
+	flagAddr        flag = 1 << 8
+	flagMethod      flag = 1 << 9
+	flagMethodShift      = 10
+	flagRO          flag = flagStickyRO | flagEmbedRO
 )
 
 func (f flag) kind() Kind {
@@ -139,7 +142,7 @@ func unpackEface(i interface{}) Value {
 	if ifaceIndir(t) {
 		f |= flagIndir
 	}
-	return Value{t, unsafe.Pointer(e.word), f}
+	return Value{t, e.word, f}
 }
 
 // A ValueError occurs when a Value method is invoked on
@@ -587,7 +590,7 @@ func storeRcvr(v Value, p unsafe.Pointer) {
 	if t.Kind() == Interface {
 		// the interface data word becomes the receiver word
 		iface := (*nonEmptyInterface)(v.ptr)
-		*(*unsafe.Pointer)(p) = unsafe.Pointer(iface.word)
+		*(*unsafe.Pointer)(p) = iface.word
 	} else if v.flag&flagIndir != 0 && !ifaceIndir(t) {
 		*(*unsafe.Pointer)(p) = *(*unsafe.Pointer)(v.ptr)
 	} else {
@@ -745,11 +748,15 @@ func (v Value) Field(i int) Value {
 	field := &tt.fields[i]
 	typ := field.typ
 
-	// Inherit permission bits from v.
-	fl := v.flag&(flagRO|flagIndir|flagAddr) | flag(typ.Kind())
+	// Inherit permission bits from v, but clear flagEmbedRO.
+	fl := v.flag&(flagStickyRO|flagIndir|flagAddr) | flag(typ.Kind())
 	// Using an unexported field forces flagRO.
 	if field.pkgPath != nil {
-		fl |= flagRO
+		if field.name == nil {
+			fl |= flagEmbedRO
+		} else {
+			fl |= flagStickyRO
+		}
 	}
 	// Either flagIndir is set and v.ptr points at struct,
 	// or flagIndir is not set and v.ptr is the actual struct data.
@@ -1104,7 +1111,7 @@ func (v Value) Method(i int) Value {
 	if v.typ.Kind() == Interface && v.IsNil() {
 		panic("reflect: Method on nil interface value")
 	}
-	fl := v.flag & (flagRO | flagIndir)
+	fl := v.flag & (flagStickyRO | flagIndir) // Clear flagEmbedRO
 	fl |= flag(Func)
 	fl |= flag(i)<<flagMethodShift | flagMethod
 	return Value{v.typ, v.ptr, fl}
@@ -2079,11 +2086,10 @@ func ValueOf(i interface{}) Value {
 		return Value{}
 	}
 
-	// TODO(rsc): Eliminate this terrible hack.
-	// In the call to unpackEface, i.typ doesn't escape,
-	// and i.word is an integer.  So it looks like
-	// i doesn't escape.  But really it does,
-	// because i.word is actually a pointer.
+	// TODO: Maybe allow contents of a Value to live on the stack.
+	// For now we make the contents always escape to the heap.  It
+	// makes life easier in a few places (see chanrecv/mapassign
+	// comment below).
 	escapes(i)
 
 	return unpackEface(i)
@@ -2439,6 +2445,14 @@ func chancap(ch unsafe.Pointer) int
 func chanclose(ch unsafe.Pointer)
 func chanlen(ch unsafe.Pointer) int
 
+// Note: some of the noescape annotations below are technically a lie,
+// but safe in the context of this package.  Functions like chansend
+// and mapassign don't escape the referent, but may escape anything
+// the referent points to (they do shallow copies of the referent).
+// It is safe in this package because the referent may only point
+// to something a Value may point to, and that is always in the heap
+// (due to the escapes() call in ValueOf).
+
 //go:noescape
 func chanrecv(t *rtype, ch unsafe.Pointer, nb bool, val unsafe.Pointer) (selected, received bool)
 
@@ -2451,6 +2465,7 @@ func makemap(t *rtype) (m unsafe.Pointer)
 //go:noescape
 func mapaccess(t *rtype, m unsafe.Pointer, key unsafe.Pointer) (val unsafe.Pointer)
 
+//go:noescape
 func mapassign(t *rtype, m unsafe.Pointer, key, val unsafe.Pointer)
 
 //go:noescape
diff --git a/src/regexp/all_test.go b/src/regexp/all_test.go
index d78ae6a..88391ff 100644
--- a/src/regexp/all_test.go
+++ b/src/regexp/all_test.go
@@ -113,6 +113,25 @@ func TestMatchFunction(t *testing.T) {
 	}
 }
 
+func copyMatchTest(t *testing.T, test *FindTest) {
+	re := compileTest(t, test.pat, "")
+	if re == nil {
+		return
+	}
+	m1 := re.MatchString(test.text)
+	m2 := re.Copy().MatchString(test.text)
+	if m1 != m2 {
+		t.Errorf("Copied Regexp match failure on %s: original gave %t; copy gave %t; should be %t",
+			test, m1, m2, len(test.matches) > 0)
+	}
+}
+
+func TestCopyMatch(t *testing.T) {
+	for _, test := range findTests {
+		copyMatchTest(t, &test)
+	}
+}
+
 type ReplaceTest struct {
 	pattern, replacement, input, output string
 }
@@ -201,6 +220,12 @@ var replaceTests = []ReplaceTest{
 	// Substitution when subexpression isn't found
 	{"(x)?", "$1", "123", "123"},
 	{"abc", "$1", "123", "123"},
+
+	// Substitutions involving a (x){0}
+	{"(a)(b){0}(c)", ".$1|$3.", "xacxacx", "x.a|c.x.a|c.x"},
+	{"(a)(((b))){0}c", ".$1.", "xacxacx", "x.a.x.a.x"},
+	{"((a(b){0}){3}){5}(h)", "y caramb$2", "say aaaaaaaaaaaaaaaah", "say ay caramba"},
+	{"((a(b){0}){3}){5}h", "y caramb$2", "say aaaaaaaaaaaaaaaah", "say ay caramba"},
 }
 
 var replaceLiteralTests = []ReplaceTest{
@@ -334,6 +359,19 @@ var metaTests = []MetaTest{
 	{`!@#$%^&*()_+-=[{]}\|,<.>/?~`, `!@#\$%\^&\*\(\)_\+-=\[\{\]\}\\\|,<\.>/\?~`, `!@#`, false},
 }
 
+var literalPrefixTests = []MetaTest{
+	// See golang.org/issue/11175.
+	// output is unused.
+	{`^0^0$`, ``, `0`, false},
+	{`^0^`, ``, ``, false},
+	{`^0$`, ``, `0`, true},
+	{`$0^`, ``, ``, false},
+	{`$0$`, ``, ``, false},
+	{`^^0$$`, ``, ``, false},
+	{`^$^$`, ``, ``, false},
+	{`$$0^^`, ``, ``, false},
+}
+
 func TestQuoteMeta(t *testing.T) {
 	for _, tc := range metaTests {
 		// Verify that QuoteMeta returns the expected string.
@@ -365,7 +403,7 @@ func TestQuoteMeta(t *testing.T) {
 }
 
 func TestLiteralPrefix(t *testing.T) {
-	for _, tc := range metaTests {
+	for _, tc := range append(metaTests, literalPrefixTests...) {
 		// Literal method needs to scan the pattern.
 		re := MustCompile(tc.pattern)
 		str, complete := re.LiteralPrefix()
@@ -665,3 +703,26 @@ func BenchmarkOnePassLongNotPrefix(b *testing.B) {
 		re.Match(x)
 	}
 }
+
+func BenchmarkMatchParallelShared(b *testing.B) {
+	x := []byte("this is a long line that contains foo bar baz")
+	re := MustCompile("foo (ba+r)? baz")
+	b.ResetTimer()
+	b.RunParallel(func(pb *testing.PB) {
+		for pb.Next() {
+			re.Match(x)
+		}
+	})
+}
+
+func BenchmarkMatchParallelCopied(b *testing.B) {
+	x := []byte("this is a long line that contains foo bar baz")
+	re := MustCompile("foo (ba+r)? baz")
+	b.ResetTimer()
+	b.RunParallel(func(pb *testing.PB) {
+		re := re.Copy()
+		for pb.Next() {
+			re.Match(x)
+		}
+	})
+}
diff --git a/src/regexp/example_test.go b/src/regexp/example_test.go
index a4e0da8..d05e87b 100644
--- a/src/regexp/example_test.go
+++ b/src/regexp/example_test.go
@@ -146,3 +146,25 @@ func ExampleRegexp_SubexpNames() {
 	// ${last} ${first}
 	// Turing Alan
 }
+
+func ExampleRegexp_Split() {
+	a := regexp.MustCompile("a")
+	fmt.Println(a.Split("banana", -1))
+	fmt.Println(a.Split("banana", 0))
+	fmt.Println(a.Split("banana", 1))
+	fmt.Println(a.Split("banana", 2))
+	zp := regexp.MustCompile("z+")
+	fmt.Println(zp.Split("pizza", -1))
+	fmt.Println(zp.Split("pizza", 0))
+	fmt.Println(zp.Split("pizza", 1))
+	fmt.Println(zp.Split("pizza", 2))
+	// Output:
+	// [b n n ]
+	// []
+	// [banana]
+	// [b nana]
+	// [pi a]
+	// []
+	// [pizza]
+	// [pi a]
+}
diff --git a/src/regexp/onepass.go b/src/regexp/onepass.go
index e6f4285..2ce3902 100644
--- a/src/regexp/onepass.go
+++ b/src/regexp/onepass.go
@@ -59,7 +59,12 @@ func onePassPrefix(p *syntax.Prog) (prefix string, complete bool, pc uint32) {
 		buf.WriteRune(i.Rune[0])
 		pc, i = i.Out, &p.Inst[i.Out]
 	}
-	return buf.String(), i.Op == syntax.InstEmptyWidth && (syntax.EmptyOp(i.Arg))&syntax.EmptyBeginText != 0, pc
+	if i.Op == syntax.InstEmptyWidth &&
+		syntax.EmptyOp(i.Arg)&syntax.EmptyEndText != 0 &&
+		p.Inst[i.Out].Op == syntax.InstMatch {
+		complete = true
+	}
+	return buf.String(), complete, pc
 }
 
 // OnePassNext selects the next actionable state of the prog, based on the input character.
@@ -108,10 +113,6 @@ func (q *queueOnePass) clear() {
 	q.nextIndex = 0
 }
 
-func (q *queueOnePass) reset() {
-	q.nextIndex = 0
-}
-
 func (q *queueOnePass) contains(u uint32) bool {
 	if u >= uint32(len(q.sparse)) {
 		return false
@@ -308,25 +309,9 @@ func makeOnePass(p *onePassProg) *onePassProg {
 	var (
 		instQueue    = newQueue(len(p.Inst))
 		visitQueue   = newQueue(len(p.Inst))
-		build        func(uint32, *queueOnePass)
 		check        func(uint32, map[uint32]bool) bool
 		onePassRunes = make([][]rune, len(p.Inst))
 	)
-	build = func(pc uint32, q *queueOnePass) {
-		if q.contains(pc) {
-			return
-		}
-		inst := p.Inst[pc]
-		switch inst.Op {
-		case syntax.InstAlt, syntax.InstAltMatch:
-			q.insert(inst.Out)
-			build(inst.Out, q)
-			q.insert(inst.Arg)
-		case syntax.InstMatch, syntax.InstFail:
-		default:
-			q.insert(inst.Out)
-		}
-	}
 
 	// check that paths from Alt instructions are unambiguous, and rebuild the new
 	// program as a onepass program
@@ -385,11 +370,11 @@ func makeOnePass(p *onePassProg) *onePassProg {
 			m[pc] = inst.Op == syntax.InstMatch
 			break
 		case syntax.InstRune:
-			ok = check(inst.Out, m)
 			m[pc] = false
 			if len(inst.Next) > 0 {
 				break
 			}
+			instQueue.insert(inst.Out)
 			if len(inst.Rune) == 0 {
 				onePassRunes[pc] = []rune{}
 				inst.Next = []uint32{inst.Out}
@@ -413,11 +398,11 @@ func makeOnePass(p *onePassProg) *onePassProg {
 			}
 			inst.Op = syntax.InstRune
 		case syntax.InstRune1:
-			ok = check(inst.Out, m)
 			m[pc] = false
 			if len(inst.Next) > 0 {
 				break
 			}
+			instQueue.insert(inst.Out)
 			runes := []rune{}
 			// expand case-folded runes
 			if syntax.Flags(inst.Arg)&syntax.FoldCase != 0 {
@@ -437,19 +422,19 @@ func makeOnePass(p *onePassProg) *onePassProg {
 			}
 			inst.Op = syntax.InstRune
 		case syntax.InstRuneAny:
-			ok = check(inst.Out, m)
 			m[pc] = false
 			if len(inst.Next) > 0 {
 				break
 			}
+			instQueue.insert(inst.Out)
 			onePassRunes[pc] = append([]rune{}, anyRune...)
 			inst.Next = []uint32{inst.Out}
 		case syntax.InstRuneAnyNotNL:
-			ok = check(inst.Out, m)
 			m[pc] = false
 			if len(inst.Next) > 0 {
 				break
 			}
+			instQueue.insert(inst.Out)
 			onePassRunes[pc] = append([]rune{}, anyRuneNotNL...)
 			inst.Next = []uint32{}
 			for i := len(onePassRunes[pc]) / 2; i >= 0; i-- {
@@ -463,24 +448,12 @@ func makeOnePass(p *onePassProg) *onePassProg {
 	instQueue.insert(uint32(p.Start))
 	m := make(map[uint32]bool, len(p.Inst))
 	for !instQueue.empty() {
-		pc := instQueue.next()
-		inst := p.Inst[pc]
 		visitQueue.clear()
+		pc := instQueue.next()
 		if !check(uint32(pc), m) {
 			p = notOnePass
 			break
 		}
-		switch inst.Op {
-		case syntax.InstAlt, syntax.InstAltMatch:
-			instQueue.insert(inst.Out)
-			instQueue.insert(inst.Arg)
-		case syntax.InstCapture, syntax.InstEmptyWidth, syntax.InstNop:
-			instQueue.insert(inst.Out)
-		case syntax.InstMatch:
-		case syntax.InstFail:
-		case syntax.InstRune, syntax.InstRune1, syntax.InstRuneAny, syntax.InstRuneAnyNotNL:
-		default:
-		}
 	}
 	if p != notOnePass {
 		for i := range p.Inst {
@@ -490,47 +463,6 @@ func makeOnePass(p *onePassProg) *onePassProg {
 	return p
 }
 
-// walk visits each Inst in the prog once, and applies the argument
-// function(ip, next), in pre-order.
-func walk(prog *syntax.Prog, funcs ...func(ip, next uint32)) {
-	var walk1 func(uint32)
-	progQueue := newQueue(len(prog.Inst))
-	walk1 = func(ip uint32) {
-		if progQueue.contains(ip) {
-			return
-		}
-		progQueue.insert(ip)
-		inst := prog.Inst[ip]
-		switch inst.Op {
-		case syntax.InstAlt, syntax.InstAltMatch:
-			for _, f := range funcs {
-				f(ip, inst.Out)
-				f(ip, inst.Arg)
-			}
-			walk1(inst.Out)
-			walk1(inst.Arg)
-		default:
-			for _, f := range funcs {
-				f(ip, inst.Out)
-			}
-			walk1(inst.Out)
-		}
-	}
-	walk1(uint32(prog.Start))
-}
-
-// find returns the Insts that match the argument predicate function
-func find(prog *syntax.Prog, f func(*syntax.Prog, int) bool) (matches []uint32) {
-	matches = []uint32{}
-
-	for ip := range prog.Inst {
-		if f(prog, ip) {
-			matches = append(matches, uint32(ip))
-		}
-	}
-	return
-}
-
 var notOnePass *onePassProg = nil
 
 // compileOnePass returns a new *syntax.Prog suitable for onePass execution if the original Prog
diff --git a/src/regexp/onepass_test.go b/src/regexp/onepass_test.go
index 7b2beea..8202ebe 100644
--- a/src/regexp/onepass_test.go
+++ b/src/regexp/onepass_test.go
@@ -140,47 +140,41 @@ var onePass = &onePassProg{}
 var onePassTests = []struct {
 	re      string
 	onePass *onePassProg
-	prog    string
 }{
-	{`^(?:a|(?:a*))$`, notOnePass, noStr},
-	{`^(?:(a)|(?:a*))$`, notOnePass, noStr},
-	{`^(?:(?:(?:.(?:$))?))$`, onePass, `a`},
-	{`^abcd$`, onePass, `abcd`},
-	{`^abcd$`, onePass, `abcde`},
-	{`^(?:(?:a{0,})*?)$`, onePass, `a`},
-	{`^(?:(?:a+)*)$`, onePass, ``},
-	{`^(?:(?:a|(?:aa)))$`, onePass, ``},
-	{`^(?:[^\s\S])$`, onePass, ``},
-	{`^(?:(?:a{3,4}){0,})$`, notOnePass, `aaaaaa`},
-	{`^(?:(?:a+)*)$`, onePass, `a`},
-	{`^(?:(?:(?:a*)+))$`, onePass, noStr},
-	{`^(?:(?:a+)*)$`, onePass, ``},
-	{`^[a-c]+$`, onePass, `abc`},
-	{`^[a-c]*$`, onePass, `abcdabc`},
-	{`^(?:a*)$`, onePass, `aaaaaaa`},
-	{`^(?:(?:aa)|a)$`, onePass, `a`},
-	{`^[a-c]*`, notOnePass, `abcdabc`},
-	{`^[a-c]*$`, onePass, `abc`},
-	{`^...$`, onePass, ``},
-	{`^(?:a|(?:aa))$`, onePass, `a`},
-	{`^[a-c]*`, notOnePass, `abcabc`},
-	{`^a((b))c$`, onePass, noStr},
-	{`^a.[l-nA-Cg-j]?e$`, onePass, noStr},
-	{`^a((b))$`, onePass, noStr},
-	{`^a(?:(b)|(c))c$`, onePass, noStr},
-	{`^a(?:(b*)|(c))c$`, notOnePass, noStr},
-	{`^a(?:b|c)$`, onePass, noStr},
-	{`^a(?:b?|c)$`, onePass, noStr},
-	{`^a(?:b?|c?)$`, notOnePass, noStr},
-	{`^a(?:b?|c+)$`, onePass, noStr},
-	{`^a(?:b+|(bc))d$`, notOnePass, noStr},
-	{`^a(?:bc)+$`, onePass, noStr},
-	{`^a(?:[bcd])+$`, onePass, noStr},
-	{`^a((?:[bcd])+)$`, onePass, noStr},
-	{`^a(:?b|c)*d$`, onePass, `abbbccbbcbbd"`},
-	{`^.bc(d|e)*$`, onePass, `abcddddddeeeededd`},
-	{`^(?:(?:aa)|.)$`, notOnePass, `a`},
-	{`^(?:(?:a{1,2}){1,2})$`, notOnePass, `aaaa`},
+	{`^(?:a|(?:a*))$`, notOnePass},
+	{`^(?:(a)|(?:a*))$`, notOnePass},
+	{`^(?:(?:(?:.(?:$))?))$`, onePass},
+	{`^abcd$`, onePass},
+	{`^(?:(?:a{0,})*?)$`, onePass},
+	{`^(?:(?:a+)*)$`, onePass},
+	{`^(?:(?:a|(?:aa)))$`, onePass},
+	{`^(?:[^\s\S])$`, onePass},
+	{`^(?:(?:a{3,4}){0,})$`, notOnePass},
+	{`^(?:(?:(?:a*)+))$`, onePass},
+	{`^[a-c]+$`, onePass},
+	{`^[a-c]*$`, onePass},
+	{`^(?:a*)$`, onePass},
+	{`^(?:(?:aa)|a)$`, onePass},
+	{`^[a-c]*`, notOnePass},
+	{`^...$`, onePass},
+	{`^(?:a|(?:aa))$`, onePass},
+	{`^a((b))c$`, onePass},
+	{`^a.[l-nA-Cg-j]?e$`, onePass},
+	{`^a((b))$`, onePass},
+	{`^a(?:(b)|(c))c$`, onePass},
+	{`^a(?:(b*)|(c))c$`, notOnePass},
+	{`^a(?:b|c)$`, onePass},
+	{`^a(?:b?|c)$`, onePass},
+	{`^a(?:b?|c?)$`, notOnePass},
+	{`^a(?:b?|c+)$`, onePass},
+	{`^a(?:b+|(bc))d$`, notOnePass},
+	{`^a(?:bc)+$`, onePass},
+	{`^a(?:[bcd])+$`, onePass},
+	{`^a((?:[bcd])+)$`, onePass},
+	{`^a(:?b|c)*d$`, onePass},
+	{`^.bc(d|e)*$`, onePass},
+	{`^(?:(?:aa)|.)$`, notOnePass},
+	{`^(?:(?:a{1,2}){1,2})$`, notOnePass},
 }
 
 func TestCompileOnePass(t *testing.T) {
@@ -206,3 +200,28 @@ func TestCompileOnePass(t *testing.T) {
 		}
 	}
 }
+
+// TODO(cespare): Unify with onePassTests and rationalize one-pass test cases.
+var onePassTests1 = []struct {
+	re    string
+	match string
+}{
+	{`^a(/b+(#c+)*)*$`, "a/b#c"}, // golang.org/issue/11905
+}
+
+func TestRunOnePass(t *testing.T) {
+	for _, test := range onePassTests1 {
+		re, err := Compile(test.re)
+		if err != nil {
+			t.Errorf("Compile(%q): got err: %s", test.re, err)
+			continue
+		}
+		if re.onepass == notOnePass {
+			t.Errorf("Compile(%q): got notOnePass, want one-pass", test.re)
+			continue
+		}
+		if !re.MatchString(test.match) {
+			t.Errorf("onepass %q did not match %q", test.re, test.match)
+		}
+	}
+}
diff --git a/src/regexp/regexp.go b/src/regexp/regexp.go
index 4e4b412..d7d0edb 100644
--- a/src/regexp/regexp.go
+++ b/src/regexp/regexp.go
@@ -104,6 +104,17 @@ func (re *Regexp) String() string {
 	return re.expr
 }
 
+// Copy returns a new Regexp object copied from re.
+//
+// When using a Regexp in multiple goroutines, giving each goroutine
+// its own copy helps to avoid lock contention.
+func (re *Regexp) Copy() *Regexp {
+	r := *re
+	r.mu = sync.Mutex{}
+	r.machine = nil
+	return &r
+}
+
 // Compile parses a regular expression and returns, if successful,
 // a Regexp object that can be used to match against text.
 //
@@ -482,6 +493,10 @@ func (re *Regexp) replaceAll(bsrc []byte, src string, nmatch int, repl func(dst
 	} else {
 		endPos = len(src)
 	}
+	if nmatch > re.prog.NumCap {
+		nmatch = re.prog.NumCap
+	}
+
 	for searchPos <= endPos {
 		a := re.doExecute(nil, bsrc, src, searchPos, nmatch)
 		if len(a) == 0 {
diff --git a/src/regexp/syntax/parse.go b/src/regexp/syntax/parse.go
index d579a40..f38bbf6 100644
--- a/src/regexp/syntax/parse.go
+++ b/src/regexp/syntax/parse.go
@@ -470,9 +470,14 @@ func (p *parser) factor(sub []*Regexp, flags Flags) []*Regexp {
 	}
 	sub = out
 
-	// Round 2: Factor out common complex prefixes,
-	// just the first piece of each concatenation,
-	// whatever it is.  This is good enough a lot of the time.
+	// Round 2: Factor out common simple prefixes,
+	// just the first piece of each concatenation.
+	// This will be good enough a lot of the time.
+	//
+	// Complex subexpressions (e.g. involving quantifiers)
+	// are not safe to factor because that collapses their
+	// distinct paths through the automaton, which affects
+	// correctness in some cases.
 	start = 0
 	out = sub[:0]
 	var first *Regexp
@@ -485,7 +490,9 @@ func (p *parser) factor(sub []*Regexp, flags Flags) []*Regexp {
 		var ifirst *Regexp
 		if i < len(sub) {
 			ifirst = p.leadingRegexp(sub[i])
-			if first != nil && first.Equal(ifirst) {
+			if first != nil && first.Equal(ifirst) &&
+				// first must be a character class OR a fixed repeat of a character class.
+				(isCharClass(first) || (first.Op == OpRepeat && first.Min == first.Max && isCharClass(first.Sub[0]))) {
 				continue
 			}
 		}
@@ -830,7 +837,14 @@ func Parse(s string, flags Flags) (*Regexp, error) {
 						lit = t[2:i]
 						t = t[i+2:]
 					}
-					p.push(literalRegexp(lit, p.flags))
+					for lit != "" {
+						c, rest, err := nextRune(lit)
+						if err != nil {
+							return nil, err
+						}
+						p.literal(c)
+						lit = rest
+					}
 					break BigSwitch
 				case 'z':
 					p.op(OpEndText)
diff --git a/src/regexp/syntax/parse_test.go b/src/regexp/syntax/parse_test.go
index c4a1117..5ca54bb 100644
--- a/src/regexp/syntax/parse_test.go
+++ b/src/regexp/syntax/parse_test.go
@@ -144,6 +144,7 @@ var parseTests = []parseTest{
 	// Test Perl quoted literals
 	{`\Q+|*?{[\E`, `str{+|*?{[}`},
 	{`\Q+\E+`, `plus{lit{+}}`},
+	{`\Qab\E+`, `cat{lit{a}plus{lit{b}}}`},
 	{`\Q\\E`, `lit{\}`},
 	{`\Q\\\E`, `str{\\}`},
 
@@ -171,7 +172,7 @@ var parseTests = []parseTest{
 
 	// Factoring.
 	{`abc|abd|aef|bcx|bcy`, `alt{cat{lit{a}alt{cat{lit{b}cc{0x63-0x64}}str{ef}}}cat{str{bc}cc{0x78-0x79}}}`},
-	{`ax+y|ax+z|ay+w`, `cat{lit{a}alt{cat{plus{lit{x}}cc{0x79-0x7a}}cat{plus{lit{y}}lit{w}}}}`},
+	{`ax+y|ax+z|ay+w`, `cat{lit{a}alt{cat{plus{lit{x}}lit{y}}cat{plus{lit{x}}lit{z}}cat{plus{lit{y}}lit{w}}}}`},
 
 	// Bug fixes.
 	{`(?:.)`, `dot{}`},
@@ -194,12 +195,13 @@ var parseTests = []parseTest{
 	{`abc|x|abd`, `alt{str{abc}lit{x}str{abd}}`},
 	{`(?i)abc|ABD`, `cat{strfold{AB}cc{0x43-0x44 0x63-0x64}}`},
 	{`[ab]c|[ab]d`, `cat{cc{0x61-0x62}cc{0x63-0x64}}`},
-	{`(?:xx|yy)c|(?:xx|yy)d`,
-		`cat{alt{str{xx}str{yy}}cc{0x63-0x64}}`},
+	{`.c|.d`, `cat{dot{}cc{0x63-0x64}}`},
 	{`x{2}|x{2}[0-9]`,
 		`cat{rep{2,2 lit{x}}alt{emp{}cc{0x30-0x39}}}`},
 	{`x{2}y|x{2}[0-9]y`,
 		`cat{rep{2,2 lit{x}}alt{lit{y}cat{cc{0x30-0x39}lit{y}}}}`},
+	{`a.*?c|a.*?b`,
+		`cat{lit{a}alt{cat{nstar{dot{}}lit{c}}cat{nstar{dot{}}lit{b}}}}`},
 
 	// Valid repetitions.
 	{`((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}))`, ``},
@@ -479,6 +481,7 @@ var invalidRegexps = []string{
 	`a{100000}`,
 	`a{100000,}`,
 	"((((((((((x{2}){2}){2}){2}){2}){2}){2}){2}){2}){2})",
+	`\Q\E*`,
 }
 
 var onlyPerl = []string{
diff --git a/src/regexp/syntax/regexp.go b/src/regexp/syntax/regexp.go
index cea7d9e..75822cf 100644
--- a/src/regexp/syntax/regexp.go
+++ b/src/regexp/syntax/regexp.go
@@ -166,9 +166,9 @@ func writeRegexp(b *bytes.Buffer, re *Regexp) {
 	case OpAnyChar:
 		b.WriteString(`(?s:.)`)
 	case OpBeginLine:
-		b.WriteRune('^')
+		b.WriteString(`(?m:^)`)
 	case OpEndLine:
-		b.WriteRune('$')
+		b.WriteString(`(?m:$)`)
 	case OpBeginText:
 		b.WriteString(`\A`)
 	case OpEndText:
diff --git a/src/regexp/syntax/simplify_test.go b/src/regexp/syntax/simplify_test.go
index 879eff5..5d0f1de 100644
--- a/src/regexp/syntax/simplify_test.go
+++ b/src/regexp/syntax/simplify_test.go
@@ -19,8 +19,8 @@ var simplifyTests = []struct {
 	{`(ab)+`, `(ab)+`},
 	{`(ab)?`, `(ab)?`},
 	{`.`, `(?s:.)`},
-	{`^`, `^`},
-	{`$`, `$`},
+	{`^`, `(?m:^)`},
+	{`$`, `(?m:$)`},
 	{`[ac]`, `[ac]`},
 	{`[^ac]`, `[^ac]`},
 
diff --git a/src/regexp/testdata/re2-search.txt b/src/regexp/testdata/re2-search.txt
index f648e55..4d02e9c 100644
--- a/src/regexp/testdata/re2-search.txt
+++ b/src/regexp/testdata/re2-search.txt
@@ -3665,3 +3665,8 @@ regexps
 "(?:a\\C*|ba\\C)$"
 -;-;-;-
 -;1-4;-;1-4
+strings
+"abc"
+regexps
+"a.*?c|a.*?b"
+0-3;0-3;0-3;0-3
diff --git a/src/run.bash b/src/run.bash
index f35ec78..3acf46a 100755
--- a/src/run.bash
+++ b/src/run.bash
@@ -35,4 +35,4 @@ if ulimit -T &> /dev/null; then
 	[ "$(ulimit -H -T)" == "unlimited" ] || ulimit -S -T $(ulimit -H -T)
 fi
 
-exec go tool dist test "$@"
+exec go tool dist test -rebuild "$@"
diff --git a/src/run.bat b/src/run.bat
index 4957111..01a66bc 100644
--- a/src/run.bat
+++ b/src/run.bat
@@ -37,7 +37,7 @@ call env.bat
 del env.bat
 echo.
 
-go tool dist test --no-rebuild
+go tool dist test
 if errorlevel 1 goto fail
 echo.
 
diff --git a/src/run.rc b/src/run.rc
index d0ba866..d314808 100755
--- a/src/run.rc
+++ b/src/run.rc
@@ -10,4 +10,4 @@ eval `{go env}
 GOPATH = () # we disallow local import for non-local packages, if $GOROOT happens
             # to be under $GOPATH, then some tests below will fail
 
-exec go tool dist test $*
+exec go tool dist test -rebuild $*
diff --git a/src/runtime/alg.go b/src/runtime/alg.go
index c666836..9ea0eb0 100644
--- a/src/runtime/alg.go
+++ b/src/runtime/alg.go
@@ -4,11 +4,14 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 const (
-	c0 = uintptr((8-ptrSize)/4*2860486313 + (ptrSize-4)/4*33054211828000289)
-	c1 = uintptr((8-ptrSize)/4*3267000013 + (ptrSize-4)/4*23344194077549503)
+	c0 = uintptr((8-sys.PtrSize)/4*2860486313 + (sys.PtrSize-4)/4*33054211828000289)
+	c1 = uintptr((8-sys.PtrSize)/4*3267000013 + (sys.PtrSize-4)/4*23344194077549503)
 )
 
 // type algorithms - known to compiler
@@ -226,18 +229,12 @@ func strequal(p, q unsafe.Pointer) bool {
 	return *(*string)(p) == *(*string)(q)
 }
 func interequal(p, q unsafe.Pointer) bool {
-	return ifaceeq(*(*interface {
-		f()
-	})(p), *(*interface {
-		f()
-	})(q))
+	return ifaceeq(*(*iface)(p), *(*iface)(q))
 }
 func nilinterequal(p, q unsafe.Pointer) bool {
-	return efaceeq(*(*interface{})(p), *(*interface{})(q))
+	return efaceeq(*(*eface)(p), *(*eface)(q))
 }
-func efaceeq(p, q interface{}) bool {
-	x := (*eface)(unsafe.Pointer(&p))
-	y := (*eface)(unsafe.Pointer(&q))
+func efaceeq(x, y eface) bool {
 	t := x._type
 	if t != y._type {
 		return false
@@ -254,11 +251,7 @@ func efaceeq(p, q interface{}) bool {
 	}
 	return eq(x.data, y.data)
 }
-func ifaceeq(p, q interface {
-	f()
-}) bool {
-	x := (*iface)(unsafe.Pointer(&p))
-	y := (*iface)(unsafe.Pointer(&q))
+func ifaceeq(x, y iface) bool {
 	xtab := x.tab
 	if xtab != y.tab {
 		return false
@@ -311,7 +304,7 @@ func memclrBytes(b []byte) {
 	memclr(s.array, uintptr(s.len))
 }
 
-const hashRandomBytes = ptrSize / 4 * 64
+const hashRandomBytes = sys.PtrSize / 4 * 64
 
 // used in asm_{386,amd64}.s to seed the hash function
 var aeskeysched [hashRandomBytes]byte
@@ -334,6 +327,9 @@ func init() {
 		getRandomData(aeskeysched[:])
 		return
 	}
-	getRandomData((*[len(hashkey) * ptrSize]byte)(unsafe.Pointer(&hashkey))[:])
-	hashkey[0] |= 1 // make sure this number is odd
+	getRandomData((*[len(hashkey) * sys.PtrSize]byte)(unsafe.Pointer(&hashkey))[:])
+	hashkey[0] |= 1 // make sure these numbers are odd
+	hashkey[1] |= 1
+	hashkey[2] |= 1
+	hashkey[3] |= 1
 }
diff --git a/src/runtime/arch1_386.go b/src/runtime/arch1_386.go
deleted file mode 100644
index d41696a..0000000
--- a/src/runtime/arch1_386.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2011 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 runtime
-
-const (
-	thechar        = '8'
-	_BigEndian     = 0
-	_CacheLineSize = 64
-	_PhysPageSize  = goos_nacl*65536 + (1-goos_nacl)*4096 // 4k normally; 64k on NaCl
-	_PCQuantum     = 1
-	_Int64Align    = 4
-	hugePageSize   = 1 << 21
-)
diff --git a/src/runtime/arch1_amd64.go b/src/runtime/arch1_amd64.go
deleted file mode 100644
index 15f4cc6..0000000
--- a/src/runtime/arch1_amd64.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2011 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 runtime
-
-const (
-	thechar        = '6'
-	_BigEndian     = 0
-	_CacheLineSize = 64
-	_PhysPageSize  = 4096
-	_PCQuantum     = 1
-	_Int64Align    = 8
-	hugePageSize   = 1 << 21
-)
diff --git a/src/runtime/arch1_amd64p32.go b/src/runtime/arch1_amd64p32.go
deleted file mode 100644
index 3c5456f..0000000
--- a/src/runtime/arch1_amd64p32.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2011 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 runtime
-
-const (
-	thechar        = '6'
-	_BigEndian     = 0
-	_CacheLineSize = 64
-	_PhysPageSize  = 65536*goos_nacl + 4096*(1-goos_nacl)
-	_PCQuantum     = 1
-	_Int64Align    = 8
-	hugePageSize   = 1 << 21
-)
diff --git a/src/runtime/arch1_arm.go b/src/runtime/arch1_arm.go
deleted file mode 100644
index 0ec2093..0000000
--- a/src/runtime/arch1_arm.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2011 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 runtime
-
-const (
-	thechar        = '5'
-	_BigEndian     = 0
-	_CacheLineSize = 32
-	_PhysPageSize  = 65536*goos_nacl + 4096*(1-goos_nacl)
-	_PCQuantum     = 4
-	_Int64Align    = 4
-	hugePageSize   = 0
-)
diff --git a/src/runtime/arch1_arm64.go b/src/runtime/arch1_arm64.go
deleted file mode 100644
index 29a87db..0000000
--- a/src/runtime/arch1_arm64.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2011 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 runtime
-
-const (
-	thechar        = '7'
-	_BigEndian     = 0
-	_CacheLineSize = 32
-	_PhysPageSize  = 65536
-	_PCQuantum     = 4
-	_Int64Align    = 8
-	hugePageSize   = 0
-)
diff --git a/src/runtime/arch1_ppc64.go b/src/runtime/arch1_ppc64.go
deleted file mode 100644
index de6dd91..0000000
--- a/src/runtime/arch1_ppc64.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// 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 runtime
-
-const (
-	thechar        = '9'
-	_BigEndian     = 1
-	_CacheLineSize = 64
-	_PhysPageSize  = 65536
-	_PCQuantum     = 4
-	_Int64Align    = 8
-	hugePageSize   = 0
-)
diff --git a/src/runtime/arch1_ppc64le.go b/src/runtime/arch1_ppc64le.go
deleted file mode 100644
index 9a55c71..0000000
--- a/src/runtime/arch1_ppc64le.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// 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 runtime
-
-const (
-	thechar        = '9'
-	_BigEndian     = 0
-	_CacheLineSize = 64
-	_PhysPageSize  = 65536
-	_PCQuantum     = 4
-	_Int64Align    = 8
-	hugePageSize   = 0
-)
diff --git a/src/runtime/arch_386.go b/src/runtime/arch_386.go
deleted file mode 100644
index 79d38c7..0000000
--- a/src/runtime/arch_386.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// 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 runtime
-
-type uintreg uint32
-type intptr int32 // TODO(rsc): remove
diff --git a/src/runtime/arch_amd64.go b/src/runtime/arch_amd64.go
deleted file mode 100644
index 270cd7b..0000000
--- a/src/runtime/arch_amd64.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// 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 runtime
-
-type uintreg uint64
-type intptr int64 // TODO(rsc): remove
diff --git a/src/runtime/arch_amd64p32.go b/src/runtime/arch_amd64p32.go
deleted file mode 100644
index 5c636ae..0000000
--- a/src/runtime/arch_amd64p32.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// 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 runtime
-
-type uintreg uint64
-type intptr int32 // TODO(rsc): remove
diff --git a/src/runtime/arch_arm.go b/src/runtime/arch_arm.go
deleted file mode 100644
index 79d38c7..0000000
--- a/src/runtime/arch_arm.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// 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 runtime
-
-type uintreg uint32
-type intptr int32 // TODO(rsc): remove
diff --git a/src/runtime/arch_arm64.go b/src/runtime/arch_arm64.go
deleted file mode 100644
index 270cd7b..0000000
--- a/src/runtime/arch_arm64.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// 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 runtime
-
-type uintreg uint64
-type intptr int64 // TODO(rsc): remove
diff --git a/src/runtime/arch_ppc64.go b/src/runtime/arch_ppc64.go
deleted file mode 100644
index 270cd7b..0000000
--- a/src/runtime/arch_ppc64.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// 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 runtime
-
-type uintreg uint64
-type intptr int64 // TODO(rsc): remove
diff --git a/src/runtime/arch_ppc64le.go b/src/runtime/arch_ppc64le.go
deleted file mode 100644
index 270cd7b..0000000
--- a/src/runtime/arch_ppc64le.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// 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 runtime
-
-type uintreg uint64
-type intptr int64 // TODO(rsc): remove
diff --git a/src/runtime/asm_386.s b/src/runtime/asm_386.s
index eb9ca63..4181859 100644
--- a/src/runtime/asm_386.s
+++ b/src/runtime/asm_386.s
@@ -26,6 +26,32 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$0
 	MOVL	SP, (g_stack+stack_hi)(BP)
 	
 	// find out information about the processor we're on
+#ifdef GOOS_nacl // NaCl doesn't like PUSHFL/POPFL
+	JMP 	has_cpuid
+#else
+	// first see if CPUID instruction is supported.
+	PUSHFL
+	PUSHFL
+	XORL	$(1<<21), 0(SP) // flip ID bit
+	POPFL
+	PUSHFL
+	POPL	AX
+	XORL	0(SP), AX
+	POPFL	// restore EFLAGS
+	TESTL	$(1<<21), AX
+	JNE 	has_cpuid
+#endif
+
+bad_proc: // show that the program requires MMX.
+	MOVL	$2, 0(SP)
+	MOVL	$bad_proc_msg<>(SB), 4(SP)
+	MOVL	$0x3d, 8(SP)
+	CALL	runtime·write(SB)
+	MOVL	$1, 0(SP)
+	CALL	runtime·exit(SB)
+	INT	$3
+
+has_cpuid:
 	MOVL	$0, AX
 	CPUID
 	CMPL	AX, $0
@@ -45,8 +71,14 @@ notintel:
 
 	MOVL	$1, AX
 	CPUID
-	MOVL	CX, runtime·cpuid_ecx(SB)
+	MOVL	CX, AX // Move to global variable clobbers CX when generating PIC
+	MOVL	AX, runtime·cpuid_ecx(SB)
 	MOVL	DX, runtime·cpuid_edx(SB)
+
+	// Check for MMX support
+	TESTL	$(1<<23), DX	// MMX
+	JZ 	bad_proc
+
 nocpuinfo:	
 
 	// if there is an _cgo_init, call it to let it
@@ -67,13 +99,15 @@ nocpuinfo:
 	MOVL	AX, g_stackguard0(CX)
 	MOVL	AX, g_stackguard1(CX)
 
+#ifndef GOOS_windows
 	// skip runtime·ldt0setup(SB) and tls test after _cgo_init for non-windows
-	CMPL runtime·iswindows(SB), $0
-	JEQ ok
+	JMP ok
+#endif
 needtls:
+#ifdef GOOS_plan9
 	// skip runtime·ldt0setup(SB) and tls test on Plan 9 in all cases
-	CMPL	runtime·isplan9(SB), $1
-	JEQ	ok
+	JMP	ok
+#endif
 
 	// set up %gs
 	CALL	runtime·ldt0setup(SB)
@@ -81,21 +115,21 @@ needtls:
 	// store through it, to make sure it works
 	get_tls(BX)
 	MOVL	$0x123, g(BX)
-	MOVL	runtime·tls0(SB), AX
+	MOVL	runtime·m0+m_tls(SB), AX
 	CMPL	AX, $0x123
 	JEQ	ok
 	MOVL	AX, 0	// abort
 ok:
 	// set up m and g "registers"
 	get_tls(BX)
-	LEAL	runtime·g0(SB), CX
-	MOVL	CX, g(BX)
+	LEAL	runtime·g0(SB), DX
+	MOVL	DX, g(BX)
 	LEAL	runtime·m0(SB), AX
 
 	// save m->g0 = g0
-	MOVL	CX, m_g0(AX)
+	MOVL	DX, m_g0(AX)
 	// save g0->m = m0
-	MOVL	AX, g_m(CX)
+	MOVL	AX, g_m(DX)
 
 	CALL	runtime·emptyfunc(SB)	// fault if stack check is wrong
 
@@ -126,6 +160,17 @@ ok:
 	INT $3
 	RET
 
+DATA	bad_proc_msg<>+0x00(SB)/8, $"This pro"
+DATA	bad_proc_msg<>+0x08(SB)/8, $"gram can"
+DATA	bad_proc_msg<>+0x10(SB)/8, $" only be"
+DATA	bad_proc_msg<>+0x18(SB)/8, $" run on "
+DATA	bad_proc_msg<>+0x20(SB)/8, $"processe"
+DATA	bad_proc_msg<>+0x28(SB)/8, $"rs with "
+DATA	bad_proc_msg<>+0x30(SB)/8, $"MMX supp"
+DATA	bad_proc_msg<>+0x38(SB)/4, $"ort."
+DATA	bad_proc_msg<>+0x3c(SB)/1, $0xa
+GLOBL	bad_proc_msg<>(SB), RODATA, $0x3d
+
 DATA	runtime·mainPC+0(SB)/4,$runtime·main(SB)
 GLOBL	runtime·mainPC(SB),RODATA,$4
 
@@ -185,9 +230,9 @@ TEXT runtime·gogo(SB), NOSPLIT, $0-4
 // to keep running g.
 TEXT runtime·mcall(SB), NOSPLIT, $0-4
 	MOVL	fn+0(FP), DI
-	
-	get_tls(CX)
-	MOVL	g(CX), AX	// save state in g->sched
+
+	get_tls(DX)
+	MOVL	g(DX), AX	// save state in g->sched
 	MOVL	0(SP), BX	// caller's PC
 	MOVL	BX, (g_sched+gobuf_pc)(AX)
 	LEAL	fn+0(FP), BX	// caller's SP
@@ -195,14 +240,14 @@ TEXT runtime·mcall(SB), NOSPLIT, $0-4
 	MOVL	AX, (g_sched+gobuf_g)(AX)
 
 	// switch to m->g0 & its stack, call fn
-	MOVL	g(CX), BX
+	MOVL	g(DX), BX
 	MOVL	g_m(BX), BX
 	MOVL	m_g0(BX), SI
 	CMPL	SI, AX	// if g == m->g0 call badmcall
 	JNE	3(PC)
 	MOVL	$runtime·badmcall(SB), AX
 	JMP	AX
-	MOVL	SI, g(CX)	// g = m->g0
+	MOVL	SI, g(DX)	// g = m->g0
 	MOVL	(g_sched+gobuf_sp)(SI), SP	// sp = m->g0->sched.sp
 	PUSHL	AX
 	MOVL	DI, DX
@@ -253,6 +298,7 @@ switch:
 	MOVL	AX, (g_sched+gobuf_g)(AX)
 
 	// switch to g0
+	get_tls(CX)
 	MOVL	DX, g(CX)
 	MOVL	(g_sched+gobuf_sp)(DX), BX
 	// make it look like mstart called systemstack on g0, to stop traceback
@@ -467,100 +513,6 @@ CALLFN(·call268435456, 268435456)
 CALLFN(·call536870912, 536870912)
 CALLFN(·call1073741824, 1073741824)
 
-// bool cas(int32 *val, int32 old, int32 new)
-// Atomically:
-//	if(*val == old){
-//		*val = new;
-//		return 1;
-//	}else
-//		return 0;
-TEXT runtime·cas(SB), NOSPLIT, $0-13
-	MOVL	ptr+0(FP), BX
-	MOVL	old+4(FP), AX
-	MOVL	new+8(FP), CX
-	LOCK
-	CMPXCHGL	CX, 0(BX)
-	SETEQ	ret+12(FP)
-	RET
-
-TEXT runtime·casuintptr(SB), NOSPLIT, $0-13
-	JMP	runtime·cas(SB)
-
-TEXT runtime·atomicloaduintptr(SB), NOSPLIT, $0-8
-	JMP	runtime·atomicload(SB)
-
-TEXT runtime·atomicloaduint(SB), NOSPLIT, $0-8
-	JMP	runtime·atomicload(SB)
-
-TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-8
-	JMP	runtime·atomicstore(SB)
-
-// bool runtime·cas64(uint64 *val, uint64 old, uint64 new)
-// Atomically:
-//	if(*val == *old){
-//		*val = new;
-//		return 1;
-//	} else {
-//		return 0;
-//	}
-TEXT runtime·cas64(SB), NOSPLIT, $0-21
-	MOVL	ptr+0(FP), BP
-	MOVL	old_lo+4(FP), AX
-	MOVL	old_hi+8(FP), DX
-	MOVL	new_lo+12(FP), BX
-	MOVL	new_hi+16(FP), CX
-	LOCK
-	CMPXCHG8B	0(BP)
-	SETEQ	ret+20(FP)
-	RET
-
-// bool casp(void **p, void *old, void *new)
-// Atomically:
-//	if(*p == old){
-//		*p = new;
-//		return 1;
-//	}else
-//		return 0;
-TEXT runtime·casp1(SB), NOSPLIT, $0-13
-	MOVL	ptr+0(FP), BX
-	MOVL	old+4(FP), AX
-	MOVL	new+8(FP), CX
-	LOCK
-	CMPXCHGL	CX, 0(BX)
-	SETEQ	ret+12(FP)
-	RET
-
-// uint32 xadd(uint32 volatile *val, int32 delta)
-// Atomically:
-//	*val += delta;
-//	return *val;
-TEXT runtime·xadd(SB), NOSPLIT, $0-12
-	MOVL	ptr+0(FP), BX
-	MOVL	delta+4(FP), AX
-	MOVL	AX, CX
-	LOCK
-	XADDL	AX, 0(BX)
-	ADDL	CX, AX
-	MOVL	AX, ret+8(FP)
-	RET
-
-TEXT runtime·xchg(SB), NOSPLIT, $0-12
-	MOVL	ptr+0(FP), BX
-	MOVL	new+4(FP), AX
-	XCHGL	AX, 0(BX)
-	MOVL	AX, ret+8(FP)
-	RET
-
-TEXT runtime·xchgp1(SB), NOSPLIT, $0-12
-	MOVL	ptr+0(FP), BX
-	MOVL	new+4(FP), AX
-	XCHGL	AX, 0(BX)
-	MOVL	AX, ret+8(FP)
-	RET
-
-TEXT runtime·xchguintptr(SB), NOSPLIT, $0-12
-	JMP	runtime·xchg(SB)
-
 TEXT runtime·procyield(SB),NOSPLIT,$0-0
 	MOVL	cycles+0(FP), AX
 again:
@@ -569,69 +521,6 @@ again:
 	JNZ	again
 	RET
 
-TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-8
-	MOVL	ptr+0(FP), BX
-	MOVL	val+4(FP), AX
-	XCHGL	AX, 0(BX)
-	RET
-
-TEXT runtime·atomicstore(SB), NOSPLIT, $0-8
-	MOVL	ptr+0(FP), BX
-	MOVL	val+4(FP), AX
-	XCHGL	AX, 0(BX)
-	RET
-
-// uint64 atomicload64(uint64 volatile* addr);
-TEXT runtime·atomicload64(SB), NOSPLIT, $0-12
-	MOVL	ptr+0(FP), AX
-	TESTL	$7, AX
-	JZ	2(PC)
-	MOVL	0, AX // crash with nil ptr deref
-	LEAL	ret_lo+4(FP), BX
-	// MOVQ (%EAX), %MM0
-	BYTE $0x0f; BYTE $0x6f; BYTE $0x00
-	// MOVQ %MM0, 0(%EBX)
-	BYTE $0x0f; BYTE $0x7f; BYTE $0x03
-	// EMMS
-	BYTE $0x0F; BYTE $0x77
-	RET
-
-// void runtime·atomicstore64(uint64 volatile* addr, uint64 v);
-TEXT runtime·atomicstore64(SB), NOSPLIT, $0-12
-	MOVL	ptr+0(FP), AX
-	TESTL	$7, AX
-	JZ	2(PC)
-	MOVL	0, AX // crash with nil ptr deref
-	// MOVQ and EMMS were introduced on the Pentium MMX.
-	// MOVQ 0x8(%ESP), %MM0
-	BYTE $0x0f; BYTE $0x6f; BYTE $0x44; BYTE $0x24; BYTE $0x08
-	// MOVQ %MM0, (%EAX)
-	BYTE $0x0f; BYTE $0x7f; BYTE $0x00 
-	// EMMS
-	BYTE $0x0F; BYTE $0x77
-	// This is essentially a no-op, but it provides required memory fencing.
-	// It can be replaced with MFENCE, but MFENCE was introduced only on the Pentium4 (SSE2).
-	MOVL	$0, AX
-	LOCK
-	XADDL	AX, (SP)
-	RET
-
-// void	runtime·atomicor8(byte volatile*, byte);
-TEXT runtime·atomicor8(SB), NOSPLIT, $0-5
-	MOVL	ptr+0(FP), AX
-	MOVB	val+4(FP), BX
-	LOCK
-	ORB	BX, (AX)
-	RET
-
-// void	runtime·atomicand8(byte volatile*, byte);
-TEXT runtime·atomicand8(SB), NOSPLIT, $0-5
-	MOVL	ptr+0(FP), AX
-	MOVB	val+4(FP), BX
-	LOCK
-	ANDB	BX, (AX)
-	RET
-
 TEXT ·publicationBarrier(SB),NOSPLIT,$0-0
 	// Stores are already ordered on x86, so this is just a
 	// compile barrier.
@@ -685,11 +574,13 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-12
 	MOVL	m_g0(BP), SI
 	MOVL	g(CX), DI
 	CMPL	SI, DI
-	JEQ	4(PC)
+	JEQ	noswitch
 	CALL	gosave<>(SB)
+	get_tls(CX)
 	MOVL	SI, g(CX)
 	MOVL	(g_sched+gobuf_sp)(SI), SP
 
+noswitch:
 	// Now on a scheduling stack (a pthread-created stack).
 	SUBL	$32, SP
 	ANDL	$~15, SP	// alignment, perhaps unnecessary
@@ -887,8 +778,8 @@ nobar:
 TEXT runtime·setcallerpc(SB),NOSPLIT,$4-8
 	MOVL	argp+0(FP),AX		// addr of first arg
 	MOVL	pc+4(FP), BX
-	MOVL	-4(AX), CX
-	CMPL	CX, runtime·stackBarrierPC(SB)
+	MOVL	-4(AX), DX
+	CMPL	DX, runtime·stackBarrierPC(SB)
 	JEQ	setbar
 	MOVL	BX, -4(AX)		// set calling pc
 	RET
@@ -920,11 +811,11 @@ done:
 	RET
 
 TEXT runtime·ldt0setup(SB),NOSPLIT,$16-0
-	// set up ldt 7 to point at tls0
+	// set up ldt 7 to point at m0.tls
 	// ldt 1 would be fine on Linux, but on OS X, 7 is as low as we can go.
 	// the entry number is just a hint.  setldt will set up GS with what it used.
 	MOVL	$7, 0(SP)
-	LEAL	runtime·tls0(SB), AX
+	LEAL	runtime·m0+m_tls(SB), AX
 	MOVL	AX, 4(SP)
 	MOVL	$32, 8(SP)	// sizeof(tls array)
 	CALL	runtime·setldt(SB)
@@ -956,36 +847,39 @@ TEXT runtime·memhash_varlen(SB),NOSPLIT,$16-12
 // hash function using AES hardware instructions
 TEXT runtime·aeshash(SB),NOSPLIT,$0-16
 	MOVL	p+0(FP), AX	// ptr to data
-	MOVL	s+8(FP), CX	// size
+	MOVL	s+8(FP), BX	// size
 	LEAL	ret+12(FP), DX
 	JMP	runtime·aeshashbody(SB)
 
 TEXT runtime·aeshashstr(SB),NOSPLIT,$0-12
 	MOVL	p+0(FP), AX	// ptr to string object
-	MOVL	4(AX), CX	// length of string
+	MOVL	4(AX), BX	// length of string
 	MOVL	(AX), AX	// string data
 	LEAL	ret+8(FP), DX
 	JMP	runtime·aeshashbody(SB)
 
 // AX: data
-// CX: length
+// BX: length
 // DX: address to put return value
 TEXT runtime·aeshashbody(SB),NOSPLIT,$0-0
-	MOVL	h+4(FP), X6	// seed to low 64 bits of xmm6
-	PINSRD	$2, CX, X6	// size to high 64 bits of xmm6
-	PSHUFHW	$0, X6, X6	// replace size with its low 2 bytes repeated 4 times
-	MOVO	runtime·aeskeysched(SB), X7
-	CMPL	CX, $16
+	MOVL	h+4(FP), X0	            // 32 bits of per-table hash seed
+	PINSRW	$4, BX, X0	            // 16 bits of length
+	PSHUFHW	$0, X0, X0	            // replace size with its low 2 bytes repeated 4 times
+	MOVO	X0, X1                      // save unscrambled seed
+	PXOR	runtime·aeskeysched(SB), X0 // xor in per-process seed
+	AESENC	X0, X0                      // scramble seed
+
+	CMPL	BX, $16
 	JB	aes0to15
 	JE	aes16
-	CMPL	CX, $32
+	CMPL	BX, $32
 	JBE	aes17to32
-	CMPL	CX, $64
+	CMPL	BX, $64
 	JBE	aes33to64
 	JMP	aes65plus
 	
 aes0to15:
-	TESTL	CX, CX
+	TESTL	BX, BX
 	JE	aes0
 
 	ADDL	$16, AX
@@ -994,140 +888,158 @@ aes0to15:
 
 	// 16 bytes loaded at this address won't cross
 	// a page boundary, so we can load it directly.
-	MOVOU	-16(AX), X0
-	ADDL	CX, CX
-	PAND	masks<>(SB)(CX*8), X0
+	MOVOU	-16(AX), X1
+	ADDL	BX, BX
+	PAND	masks<>(SB)(BX*8), X1
 
-	// scramble 3 times
-	AESENC	X6, X0
-	AESENC	X7, X0
-	AESENC	X7, X0
-	MOVL	X0, (DX)
+final1:	
+	AESENC	X0, X1  // scramble input, xor in seed
+	AESENC	X1, X1  // scramble combo 2 times
+	AESENC	X1, X1
+	MOVL	X1, (DX)
 	RET
 
 endofpage:
 	// address ends in 1111xxxx.  Might be up against
 	// a page boundary, so load ending at last byte.
 	// Then shift bytes down using pshufb.
-	MOVOU	-32(AX)(CX*1), X0
-	ADDL	CX, CX
-	PSHUFB	shifts<>(SB)(CX*8), X0
-	AESENC	X6, X0
-	AESENC	X7, X0
-	AESENC	X7, X0
-	MOVL	X0, (DX)
-	RET
+	MOVOU	-32(AX)(BX*1), X1
+	ADDL	BX, BX
+	PSHUFB	shifts<>(SB)(BX*8), X1
+	JMP	final1
 
 aes0:
-	// return input seed
-	MOVL	h+4(FP), AX
-	MOVL	AX, (DX)
-	RET
-
-aes16:
-	MOVOU	(AX), X0
-	AESENC	X6, X0
-	AESENC	X7, X0
-	AESENC	X7, X0
+	// Return scrambled input seed
+	AESENC	X0, X0
 	MOVL	X0, (DX)
 	RET
 
+aes16:
+	MOVOU	(AX), X1
+	JMP	final1
 
 aes17to32:
+	// make second starting seed
+	PXOR	runtime·aeskeysched+16(SB), X1
+	AESENC	X1, X1
+	
 	// load data to be hashed
-	MOVOU	(AX), X0
-	MOVOU	-16(AX)(CX*1), X1
+	MOVOU	(AX), X2
+	MOVOU	-16(AX)(BX*1), X3
 
 	// scramble 3 times
-	AESENC	X6, X0
-	AESENC	runtime·aeskeysched+16(SB), X1
-	AESENC	X7, X0
-	AESENC	X7, X1
-	AESENC	X7, X0
-	AESENC	X7, X1
+	AESENC	X0, X2
+	AESENC	X1, X3
+	AESENC	X2, X2
+	AESENC	X3, X3
+	AESENC	X2, X2
+	AESENC	X3, X3
 
 	// combine results
-	PXOR	X1, X0
-	MOVL	X0, (DX)
+	PXOR	X3, X2
+	MOVL	X2, (DX)
 	RET
 
 aes33to64:
-	MOVOU	(AX), X0
-	MOVOU	16(AX), X1
-	MOVOU	-32(AX)(CX*1), X2
-	MOVOU	-16(AX)(CX*1), X3
+	// make 3 more starting seeds
+	MOVO	X1, X2
+	MOVO	X1, X3
+	PXOR	runtime·aeskeysched+16(SB), X1
+	PXOR	runtime·aeskeysched+32(SB), X2
+	PXOR	runtime·aeskeysched+48(SB), X3
+	AESENC	X1, X1
+	AESENC	X2, X2
+	AESENC	X3, X3
 	
-	AESENC	X6, X0
-	AESENC	runtime·aeskeysched+16(SB), X1
-	AESENC	runtime·aeskeysched+32(SB), X2
-	AESENC	runtime·aeskeysched+48(SB), X3
-	AESENC	X7, X0
-	AESENC	X7, X1
-	AESENC	X7, X2
-	AESENC	X7, X3
-	AESENC	X7, X0
-	AESENC	X7, X1
-	AESENC	X7, X2
-	AESENC	X7, X3
-
-	PXOR	X2, X0
-	PXOR	X3, X1
-	PXOR	X1, X0
-	MOVL	X0, (DX)
+	MOVOU	(AX), X4
+	MOVOU	16(AX), X5
+	MOVOU	-32(AX)(BX*1), X6
+	MOVOU	-16(AX)(BX*1), X7
+	
+	AESENC	X0, X4
+	AESENC	X1, X5
+	AESENC	X2, X6
+	AESENC	X3, X7
+	
+	AESENC	X4, X4
+	AESENC	X5, X5
+	AESENC	X6, X6
+	AESENC	X7, X7
+	
+	AESENC	X4, X4
+	AESENC	X5, X5
+	AESENC	X6, X6
+	AESENC	X7, X7
+
+	PXOR	X6, X4
+	PXOR	X7, X5
+	PXOR	X5, X4
+	MOVL	X4, (DX)
 	RET
 
 aes65plus:
+	// make 3 more starting seeds
+	MOVO	X1, X2
+	MOVO	X1, X3
+	PXOR	runtime·aeskeysched+16(SB), X1
+	PXOR	runtime·aeskeysched+32(SB), X2
+	PXOR	runtime·aeskeysched+48(SB), X3
+	AESENC	X1, X1
+	AESENC	X2, X2
+	AESENC	X3, X3
+	
 	// start with last (possibly overlapping) block
-	MOVOU	-64(AX)(CX*1), X0
-	MOVOU	-48(AX)(CX*1), X1
-	MOVOU	-32(AX)(CX*1), X2
-	MOVOU	-16(AX)(CX*1), X3
+	MOVOU	-64(AX)(BX*1), X4
+	MOVOU	-48(AX)(BX*1), X5
+	MOVOU	-32(AX)(BX*1), X6
+	MOVOU	-16(AX)(BX*1), X7
 
 	// scramble state once
-	AESENC	X6, X0
-	AESENC	runtime·aeskeysched+16(SB), X1
-	AESENC	runtime·aeskeysched+32(SB), X2
-	AESENC	runtime·aeskeysched+48(SB), X3
+	AESENC	X0, X4
+	AESENC	X1, X5
+	AESENC	X2, X6
+	AESENC	X3, X7
 
 	// compute number of remaining 64-byte blocks
-	DECL	CX
-	SHRL	$6, CX
+	DECL	BX
+	SHRL	$6, BX
 	
 aesloop:
 	// scramble state, xor in a block
-	MOVOU	(AX), X4
-	MOVOU	16(AX), X5
-	AESENC	X4, X0
-	AESENC	X5, X1
-	MOVOU	32(AX), X4
-	MOVOU	48(AX), X5
-	AESENC	X4, X2
-	AESENC	X5, X3
+	MOVOU	(AX), X0
+	MOVOU	16(AX), X1
+	MOVOU	32(AX), X2
+	MOVOU	48(AX), X3
+	AESENC	X0, X4
+	AESENC	X1, X5
+	AESENC	X2, X6
+	AESENC	X3, X7
 
 	// scramble state
-	AESENC	X7, X0
-	AESENC	X7, X1
-	AESENC	X7, X2
-	AESENC	X7, X3
+	AESENC	X4, X4
+	AESENC	X5, X5
+	AESENC	X6, X6
+	AESENC	X7, X7
 
 	ADDL	$64, AX
-	DECL	CX
+	DECL	BX
 	JNE	aesloop
 
 	// 2 more scrambles to finish
-	AESENC	X7, X0
-	AESENC	X7, X1
-	AESENC	X7, X2
-	AESENC	X7, X3
-	AESENC	X7, X0
-	AESENC	X7, X1
-	AESENC	X7, X2
-	AESENC	X7, X3
-
-	PXOR	X2, X0
-	PXOR	X3, X1
-	PXOR	X1, X0
-	MOVL	X0, (DX)
+	AESENC	X4, X4
+	AESENC	X5, X5
+	AESENC	X6, X6
+	AESENC	X7, X7
+	
+	AESENC	X4, X4
+	AESENC	X5, X5
+	AESENC	X6, X6
+	AESENC	X7, X7
+
+	PXOR	X6, X4
+	PXOR	X7, X5
+	PXOR	X5, X4
+	MOVL	X4, (DX)
 	RET
 
 TEXT runtime·aeshash32(SB),NOSPLIT,$0-12
@@ -1318,6 +1230,15 @@ DATA shifts<>+0xfc(SB)/4, $0xff0f0e0d
 
 GLOBL shifts<>(SB),RODATA,$256
 
+TEXT ·checkASM(SB),NOSPLIT,$0-1
+	// check that masks<>(SB) and shifts<>(SB) are aligned to 16-byte
+	MOVL	$masks<>(SB), AX
+	MOVL	$shifts<>(SB), BX
+	ORL	BX, AX
+	TESTL	$15, AX
+	SETEQ	ret+0(FP)
+	RET
+
 TEXT runtime·memeq(SB),NOSPLIT,$0-13
 	MOVL	a+0(FP), SI
 	MOVL	b+4(FP), DI
@@ -1518,7 +1439,8 @@ TEXT strings·IndexByte(SB),NOSPLIT,$0-16
 TEXT runtime·cmpbody(SB),NOSPLIT,$0-0
 	MOVL	DX, BP
 	SUBL	BX, DX // DX = blen-alen
-	CMOVLGT	BX, BP // BP = min(alen, blen)
+	JLE	2(PC)
+	MOVL	BX, BP // BP = min(alen, blen)
 	CMPL	SI, DI
 	JEQ	allsame
 	CMPL	BP, $4
@@ -1637,7 +1559,8 @@ TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
 	ADDL	DX, DX
 	MOVL	DX, BX
 	XORL	$0x88888eef, DX
-	CMOVLMI	BX, DX
+	JPL	2(PC)
+	MOVL	BX, DX
 	MOVL	DX, m_fastrand(AX)
 	MOVL	DX, ret+0(FP)
 	RET
@@ -1664,23 +1587,26 @@ TEXT runtime·goexit(SB),NOSPLIT,$0-0
 	// traceback from goexit1 must hit code range of goexit
 	BYTE	$0x90	// NOP
 
+// Prefetching doesn't seem to help.
 TEXT runtime·prefetcht0(SB),NOSPLIT,$0-4
-	MOVL	addr+0(FP), AX
-	PREFETCHT0	(AX)
 	RET
 
 TEXT runtime·prefetcht1(SB),NOSPLIT,$0-4
-	MOVL	addr+0(FP), AX
-	PREFETCHT1	(AX)
 	RET
 
-
 TEXT runtime·prefetcht2(SB),NOSPLIT,$0-4
-	MOVL	addr+0(FP), AX
-	PREFETCHT2	(AX)
 	RET
 
 TEXT runtime·prefetchnta(SB),NOSPLIT,$0-4
-	MOVL	addr+0(FP), AX
-	PREFETCHNTA	(AX)
 	RET
+
+// Add a module's moduledata to the linked list of moduledata objects.  This
+// is called from .init_array by a function generated in the linker and so
+// follows the platform ABI wrt register preservation -- it only touches AX,
+// CX (implicitly) and DX, but it does not follow the ABI wrt arguments:
+// instead the pointer to the moduledata is passed in AX.
+TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0
+       MOVL    runtime·lastmoduledatap(SB), DX
+       MOVL    AX, moduledata_next(DX)
+       MOVL    AX, runtime·lastmoduledatap(SB)
+       RET
diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s
index 980b1ca..5094812 100644
--- a/src/runtime/asm_amd64.s
+++ b/src/runtime/asm_amd64.s
@@ -42,11 +42,37 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$0
 	JNE	notintel
 	MOVB	$1, runtime·lfenceBeforeRdtsc(SB)
 notintel:
+	// Do nothing.
 
 	MOVQ	$1, AX
 	CPUID
 	MOVL	CX, runtime·cpuid_ecx(SB)
 	MOVL	DX, runtime·cpuid_edx(SB)
+	// Detect AVX and AVX2 as per 14.7.1  Detection of AVX2 chapter of [1]
+	// [1] 64-ia-32-architectures-software-developer-manual-325462.pdf
+	// http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf
+	ANDL    $0x18000000, CX // check for OSXSAVE and AVX bits
+	CMPL    CX, $0x18000000
+	JNE     noavx
+	MOVL    $0, CX
+	// For XGETBV, OSXSAVE bit is required and sufficient
+	XGETBV
+	ANDL    $6, AX
+	CMPL    AX, $6 // Check for OS support of YMM registers
+	JNE     noavx
+	MOVB    $1, runtime·support_avx(SB)
+	MOVL    $7, AX
+	MOVL    $0, CX
+	CPUID
+	ANDL    $0x20, BX // check for AVX2 bit
+	CMPL    BX, $0x20
+	JNE     noavx2
+	MOVB    $1, runtime·support_avx2(SB)
+	JMP     nocpuinfo
+noavx:
+	MOVB    $0, runtime·support_avx(SB)
+noavx2:
+	MOVB    $0, runtime·support_avx2(SB)
 nocpuinfo:	
 	
 	// if there is an _cgo_init, call it.
@@ -65,23 +91,26 @@ nocpuinfo:
 	MOVQ	AX, g_stackguard0(CX)
 	MOVQ	AX, g_stackguard1(CX)
 
-	CMPL	runtime·iswindows(SB), $0
-	JEQ ok
+#ifndef GOOS_windows
+	JMP ok
+#endif
 needtls:
+#ifdef GOOS_plan9
 	// skip TLS setup on Plan 9
-	CMPL	runtime·isplan9(SB), $1
-	JEQ ok
+	JMP ok
+#endif
+#ifdef GOOS_solaris
 	// skip TLS setup on Solaris
-	CMPL	runtime·issolaris(SB), $1
-	JEQ ok
+	JMP ok
+#endif
 
-	LEAQ	runtime·tls0(SB), DI
+	LEAQ	runtime·m0+m_tls(SB), DI
 	CALL	runtime·settls(SB)
 
 	// store through it, to make sure it works
 	get_tls(BX)
 	MOVQ	$0x123, g(BX)
-	MOVQ	runtime·tls0(SB), AX
+	MOVQ	runtime·m0+m_tls(SB), AX
 	CMPQ	AX, $0x123
 	JEQ 2(PC)
 	MOVL	AX, 0	// abort
@@ -346,7 +375,13 @@ TEXT runtime·stackBarrier(SB),NOSPLIT,$0
 	MOVQ	(g_stkbar+slice_array)(CX), DX
 	MOVQ	g_stkbarPos(CX), BX
 	IMULQ	$stkbar__size, BX	// Too big for SIB.
+	MOVQ	stkbar_savedLRPtr(DX)(BX*1), R8
 	MOVQ	stkbar_savedLRVal(DX)(BX*1), BX
+	// Assert that we're popping the right saved LR.
+	ADDQ	$8, R8
+	CMPQ	R8, SP
+	JEQ	2(PC)
+	MOVL	$0, 0
 	// Record that this stack barrier was hit.
 	ADDQ	$1, g_stkbarPos(CX)
 	// Jump to the original return PC.
@@ -461,118 +496,6 @@ CALLFN(·call268435456, 268435456)
 CALLFN(·call536870912, 536870912)
 CALLFN(·call1073741824, 1073741824)
 
-// bool cas(int32 *val, int32 old, int32 new)
-// Atomically:
-//	if(*val == old){
-//		*val = new;
-//		return 1;
-//	} else
-//		return 0;
-TEXT runtime·cas(SB), NOSPLIT, $0-17
-	MOVQ	ptr+0(FP), BX
-	MOVL	old+8(FP), AX
-	MOVL	new+12(FP), CX
-	LOCK
-	CMPXCHGL	CX, 0(BX)
-	SETEQ	ret+16(FP)
-	RET
-
-// bool	runtime·cas64(uint64 *val, uint64 old, uint64 new)
-// Atomically:
-//	if(*val == *old){
-//		*val = new;
-//		return 1;
-//	} else {
-//		return 0;
-//	}
-TEXT runtime·cas64(SB), NOSPLIT, $0-25
-	MOVQ	ptr+0(FP), BX
-	MOVQ	old+8(FP), AX
-	MOVQ	new+16(FP), CX
-	LOCK
-	CMPXCHGQ	CX, 0(BX)
-	SETEQ	ret+24(FP)
-	RET
-	
-TEXT runtime·casuintptr(SB), NOSPLIT, $0-25
-	JMP	runtime·cas64(SB)
-
-TEXT runtime·atomicloaduintptr(SB), NOSPLIT, $0-16
-	JMP	runtime·atomicload64(SB)
-
-TEXT runtime·atomicloaduint(SB), NOSPLIT, $0-16
-	JMP	runtime·atomicload64(SB)
-
-TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-16
-	JMP	runtime·atomicstore64(SB)
-
-// bool casp(void **val, void *old, void *new)
-// Atomically:
-//	if(*val == old){
-//		*val = new;
-//		return 1;
-//	} else
-//		return 0;
-TEXT runtime·casp1(SB), NOSPLIT, $0-25
-	MOVQ	ptr+0(FP), BX
-	MOVQ	old+8(FP), AX
-	MOVQ	new+16(FP), CX
-	LOCK
-	CMPXCHGQ	CX, 0(BX)
-	SETEQ	ret+24(FP)
-	RET
-
-// uint32 xadd(uint32 volatile *val, int32 delta)
-// Atomically:
-//	*val += delta;
-//	return *val;
-TEXT runtime·xadd(SB), NOSPLIT, $0-20
-	MOVQ	ptr+0(FP), BX
-	MOVL	delta+8(FP), AX
-	MOVL	AX, CX
-	LOCK
-	XADDL	AX, 0(BX)
-	ADDL	CX, AX
-	MOVL	AX, ret+16(FP)
-	RET
-
-TEXT runtime·xadd64(SB), NOSPLIT, $0-24
-	MOVQ	ptr+0(FP), BX
-	MOVQ	delta+8(FP), AX
-	MOVQ	AX, CX
-	LOCK
-	XADDQ	AX, 0(BX)
-	ADDQ	CX, AX
-	MOVQ	AX, ret+16(FP)
-	RET
-
-TEXT runtime·xadduintptr(SB), NOSPLIT, $0-24
-	JMP	runtime·xadd64(SB)
-
-TEXT runtime·xchg(SB), NOSPLIT, $0-20
-	MOVQ	ptr+0(FP), BX
-	MOVL	new+8(FP), AX
-	XCHGL	AX, 0(BX)
-	MOVL	AX, ret+16(FP)
-	RET
-
-TEXT runtime·xchg64(SB), NOSPLIT, $0-24
-	MOVQ	ptr+0(FP), BX
-	MOVQ	new+8(FP), AX
-	XCHGQ	AX, 0(BX)
-	MOVQ	AX, ret+16(FP)
-	RET
-
-TEXT runtime·xchgp1(SB), NOSPLIT, $0-24
-	MOVQ	ptr+0(FP), BX
-	MOVQ	new+8(FP), AX
-	XCHGQ	AX, 0(BX)
-	MOVQ	AX, ret+16(FP)
-	RET
-
-TEXT runtime·xchguintptr(SB), NOSPLIT, $0-24
-	JMP	runtime·xchg64(SB)
-
 TEXT runtime·procyield(SB),NOSPLIT,$0-0
 	MOVL	cycles+0(FP), AX
 again:
@@ -581,39 +504,6 @@ again:
 	JNZ	again
 	RET
 
-TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-16
-	MOVQ	ptr+0(FP), BX
-	MOVQ	val+8(FP), AX
-	XCHGQ	AX, 0(BX)
-	RET
-
-TEXT runtime·atomicstore(SB), NOSPLIT, $0-12
-	MOVQ	ptr+0(FP), BX
-	MOVL	val+8(FP), AX
-	XCHGL	AX, 0(BX)
-	RET
-
-TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
-	MOVQ	ptr+0(FP), BX
-	MOVQ	val+8(FP), AX
-	XCHGQ	AX, 0(BX)
-	RET
-
-// void	runtime·atomicor8(byte volatile*, byte);
-TEXT runtime·atomicor8(SB), NOSPLIT, $0-9
-	MOVQ	ptr+0(FP), AX
-	MOVB	val+8(FP), BX
-	LOCK
-	ORB	BX, (AX)
-	RET
-
-// void	runtime·atomicand8(byte volatile*, byte);
-TEXT runtime·atomicand8(SB), NOSPLIT, $0-9
-	MOVQ	ptr+0(FP), AX
-	MOVB	val+8(FP), BX
-	LOCK
-	ANDB	BX, (AX)
-	RET
 
 TEXT ·publicationBarrier(SB),NOSPLIT,$0-0
 	// Stores are already ordered on x86, so this is just a
@@ -932,10 +822,10 @@ TEXT runtime·getcallersp(SB),NOSPLIT,$0-16
 TEXT runtime·cputicks(SB),NOSPLIT,$0-0
 	CMPB	runtime·lfenceBeforeRdtsc(SB), $1
 	JNE	mfence
-	BYTE	$0x0f; BYTE $0xae; BYTE $0xe8 // LFENCE
+	LFENCE
 	JMP	done
 mfence:
-	BYTE	$0x0f; BYTE $0xae; BYTE $0xf0 // MFENCE
+	MFENCE
 done:
 	RDTSC
 	SHLQ	$32, DX
@@ -978,10 +868,14 @@ TEXT runtime·aeshashstr(SB),NOSPLIT,$0-24
 // CX: length
 // DX: address to put return value
 TEXT runtime·aeshashbody(SB),NOSPLIT,$0-0
-	MOVQ	h+8(FP), X6	// seed to low 64 bits of xmm6
-	PINSRQ	$1, CX, X6	// size to high 64 bits of xmm6
-	PSHUFHW	$0, X6, X6	// replace size with its low 2 bytes repeated 4 times
-	MOVO	runtime·aeskeysched(SB), X7
+	// Fill an SSE register with our seeds.
+	MOVQ	h+8(FP), X0			// 64 bits of per-table hash seed
+	PINSRW	$4, CX, X0			// 16 bits of length
+	PSHUFHW $0, X0, X0			// repeat length 4 times total
+	MOVO	X0, X1				// save unscrambled seed
+	PXOR	runtime·aeskeysched(SB), X0	// xor in per-process seed
+	AESENC	X0, X0				// scramble seed
+
 	CMPQ	CX, $16
 	JB	aes0to15
 	JE	aes16
@@ -1003,218 +897,275 @@ aes0to15:
 
 	// 16 bytes loaded at this address won't cross
 	// a page boundary, so we can load it directly.
-	MOVOU	-16(AX), X0
+	MOVOU	-16(AX), X1
 	ADDQ	CX, CX
 	MOVQ	$masks<>(SB), AX
-	PAND	(AX)(CX*8), X0
-
-	// scramble 3 times
-	AESENC	X6, X0
-	AESENC	X7, X0
-	AESENC	X7, X0
-	MOVQ	X0, (DX)
+	PAND	(AX)(CX*8), X1
+final1:
+	AESENC	X0, X1	// scramble input, xor in seed
+	AESENC	X1, X1  // scramble combo 2 times
+	AESENC	X1, X1
+	MOVQ	X1, (DX)
 	RET
 
 endofpage:
 	// address ends in 1111xxxx.  Might be up against
 	// a page boundary, so load ending at last byte.
 	// Then shift bytes down using pshufb.
-	MOVOU	-32(AX)(CX*1), X0
+	MOVOU	-32(AX)(CX*1), X1
 	ADDQ	CX, CX
 	MOVQ	$shifts<>(SB), AX
-	PSHUFB	(AX)(CX*8), X0
-	AESENC	X6, X0
-	AESENC	X7, X0
-	AESENC	X7, X0
-	MOVQ	X0, (DX)
-	RET
+	PSHUFB	(AX)(CX*8), X1
+	JMP	final1
 
 aes0:
-	// return input seed
-	MOVQ	h+8(FP), AX
-	MOVQ	AX, (DX)
+	// Return scrambled input seed
+	AESENC	X0, X0
+	MOVQ	X0, (DX)
 	RET
 
 aes16:
-	MOVOU	(AX), X0
-	AESENC	X6, X0
-	AESENC	X7, X0
-	AESENC	X7, X0
-	MOVQ	X0, (DX)
-	RET
+	MOVOU	(AX), X1
+	JMP	final1
 
 aes17to32:
+	// make second starting seed
+	PXOR	runtime·aeskeysched+16(SB), X1
+	AESENC	X1, X1
+	
 	// load data to be hashed
-	MOVOU	(AX), X0
-	MOVOU	-16(AX)(CX*1), X1
+	MOVOU	(AX), X2
+	MOVOU	-16(AX)(CX*1), X3
 
 	// scramble 3 times
-	AESENC	X6, X0
-	AESENC	runtime·aeskeysched+16(SB), X1
-	AESENC	X7, X0
-	AESENC	X7, X1
-	AESENC	X7, X0
-	AESENC	X7, X1
+	AESENC	X0, X2
+	AESENC	X1, X3
+	AESENC	X2, X2
+	AESENC	X3, X3
+	AESENC	X2, X2
+	AESENC	X3, X3
 
 	// combine results
-	PXOR	X1, X0
-	MOVQ	X0, (DX)
+	PXOR	X3, X2
+	MOVQ	X2, (DX)
 	RET
 
 aes33to64:
-	MOVOU	(AX), X0
-	MOVOU	16(AX), X1
-	MOVOU	-32(AX)(CX*1), X2
-	MOVOU	-16(AX)(CX*1), X3
+	// make 3 more starting seeds
+	MOVO	X1, X2
+	MOVO	X1, X3
+	PXOR	runtime·aeskeysched+16(SB), X1
+	PXOR	runtime·aeskeysched+32(SB), X2
+	PXOR	runtime·aeskeysched+48(SB), X3
+	AESENC	X1, X1
+	AESENC	X2, X2
+	AESENC	X3, X3
 	
-	AESENC	X6, X0
-	AESENC	runtime·aeskeysched+16(SB), X1
-	AESENC	runtime·aeskeysched+32(SB), X2
-	AESENC	runtime·aeskeysched+48(SB), X3
-	AESENC	X7, X0
-	AESENC	X7, X1
-	AESENC	X7, X2
-	AESENC	X7, X3
-	AESENC	X7, X0
-	AESENC	X7, X1
-	AESENC	X7, X2
-	AESENC	X7, X3
-
-	PXOR	X2, X0
-	PXOR	X3, X1
-	PXOR	X1, X0
-	MOVQ	X0, (DX)
+	MOVOU	(AX), X4
+	MOVOU	16(AX), X5
+	MOVOU	-32(AX)(CX*1), X6
+	MOVOU	-16(AX)(CX*1), X7
+	
+	AESENC	X0, X4
+	AESENC	X1, X5
+	AESENC	X2, X6
+	AESENC	X3, X7
+	
+	AESENC	X4, X4
+	AESENC	X5, X5
+	AESENC	X6, X6
+	AESENC	X7, X7
+	
+	AESENC	X4, X4
+	AESENC	X5, X5
+	AESENC	X6, X6
+	AESENC	X7, X7
+
+	PXOR	X6, X4
+	PXOR	X7, X5
+	PXOR	X5, X4
+	MOVQ	X4, (DX)
 	RET
 
 aes65to128:
-	MOVOU	(AX), X0
-	MOVOU	16(AX), X1
-	MOVOU	32(AX), X2
-	MOVOU	48(AX), X3
-	MOVOU	-64(AX)(CX*1), X4
-	MOVOU	-48(AX)(CX*1), X5
-	MOVOU	-32(AX)(CX*1), X8
-	MOVOU	-16(AX)(CX*1), X9
+	// make 7 more starting seeds
+	MOVO	X1, X2
+	MOVO	X1, X3
+	MOVO	X1, X4
+	MOVO	X1, X5
+	MOVO	X1, X6
+	MOVO	X1, X7
+	PXOR	runtime·aeskeysched+16(SB), X1
+	PXOR	runtime·aeskeysched+32(SB), X2
+	PXOR	runtime·aeskeysched+48(SB), X3
+	PXOR	runtime·aeskeysched+64(SB), X4
+	PXOR	runtime·aeskeysched+80(SB), X5
+	PXOR	runtime·aeskeysched+96(SB), X6
+	PXOR	runtime·aeskeysched+112(SB), X7
+	AESENC	X1, X1
+	AESENC	X2, X2
+	AESENC	X3, X3
+	AESENC	X4, X4
+	AESENC	X5, X5
+	AESENC	X6, X6
+	AESENC	X7, X7
+
+	// load data
+	MOVOU	(AX), X8
+	MOVOU	16(AX), X9
+	MOVOU	32(AX), X10
+	MOVOU	48(AX), X11
+	MOVOU	-64(AX)(CX*1), X12
+	MOVOU	-48(AX)(CX*1), X13
+	MOVOU	-32(AX)(CX*1), X14
+	MOVOU	-16(AX)(CX*1), X15
+
+	// scramble data, xor in seed
+	AESENC	X0, X8
+	AESENC	X1, X9
+	AESENC	X2, X10
+	AESENC	X3, X11
+	AESENC	X4, X12
+	AESENC	X5, X13
+	AESENC	X6, X14
+	AESENC	X7, X15
+
+	// scramble twice
+	AESENC	X8, X8
+	AESENC	X9, X9
+	AESENC	X10, X10
+	AESENC	X11, X11
+	AESENC	X12, X12
+	AESENC	X13, X13
+	AESENC	X14, X14
+	AESENC	X15, X15
 	
-	AESENC	X6, X0
-	AESENC	runtime·aeskeysched+16(SB), X1
-	AESENC	runtime·aeskeysched+32(SB), X2
-	AESENC	runtime·aeskeysched+48(SB), X3
-	AESENC	runtime·aeskeysched+64(SB), X4
-	AESENC	runtime·aeskeysched+80(SB), X5
-	AESENC	runtime·aeskeysched+96(SB), X8
-	AESENC	runtime·aeskeysched+112(SB), X9
-	AESENC	X7, X0
-	AESENC	X7, X1
-	AESENC	X7, X2
-	AESENC	X7, X3
-	AESENC	X7, X4
-	AESENC	X7, X5
-	AESENC	X7, X8
-	AESENC	X7, X9
-	AESENC	X7, X0
-	AESENC	X7, X1
-	AESENC	X7, X2
-	AESENC	X7, X3
-	AESENC	X7, X4
-	AESENC	X7, X5
-	AESENC	X7, X8
-	AESENC	X7, X9
-
-	PXOR	X4, X0
-	PXOR	X5, X1
-	PXOR	X8, X2
-	PXOR	X9, X3
-	PXOR	X2, X0
-	PXOR	X3, X1
-	PXOR	X1, X0
-	MOVQ	X0, (DX)
+	AESENC	X8, X8
+	AESENC	X9, X9
+	AESENC	X10, X10
+	AESENC	X11, X11
+	AESENC	X12, X12
+	AESENC	X13, X13
+	AESENC	X14, X14
+	AESENC	X15, X15
+
+	// combine results
+	PXOR	X12, X8
+	PXOR	X13, X9
+	PXOR	X14, X10
+	PXOR	X15, X11
+	PXOR	X10, X8
+	PXOR	X11, X9
+	PXOR	X9, X8
+	MOVQ	X8, (DX)
 	RET
 
 aes129plus:
+	// make 7 more starting seeds
+	MOVO	X1, X2
+	MOVO	X1, X3
+	MOVO	X1, X4
+	MOVO	X1, X5
+	MOVO	X1, X6
+	MOVO	X1, X7
+	PXOR	runtime·aeskeysched+16(SB), X1
+	PXOR	runtime·aeskeysched+32(SB), X2
+	PXOR	runtime·aeskeysched+48(SB), X3
+	PXOR	runtime·aeskeysched+64(SB), X4
+	PXOR	runtime·aeskeysched+80(SB), X5
+	PXOR	runtime·aeskeysched+96(SB), X6
+	PXOR	runtime·aeskeysched+112(SB), X7
+	AESENC	X1, X1
+	AESENC	X2, X2
+	AESENC	X3, X3
+	AESENC	X4, X4
+	AESENC	X5, X5
+	AESENC	X6, X6
+	AESENC	X7, X7
+	
 	// start with last (possibly overlapping) block
-	MOVOU	-128(AX)(CX*1), X0
-	MOVOU	-112(AX)(CX*1), X1
-	MOVOU	-96(AX)(CX*1), X2
-	MOVOU	-80(AX)(CX*1), X3
-	MOVOU	-64(AX)(CX*1), X4
-	MOVOU	-48(AX)(CX*1), X5
-	MOVOU	-32(AX)(CX*1), X8
-	MOVOU	-16(AX)(CX*1), X9
-
-	// scramble state once
-	AESENC	X6, X0
-	AESENC	runtime·aeskeysched+16(SB), X1
-	AESENC	runtime·aeskeysched+32(SB), X2
-	AESENC	runtime·aeskeysched+48(SB), X3
-	AESENC	runtime·aeskeysched+64(SB), X4
-	AESENC	runtime·aeskeysched+80(SB), X5
-	AESENC	runtime·aeskeysched+96(SB), X8
-	AESENC	runtime·aeskeysched+112(SB), X9
-
+	MOVOU	-128(AX)(CX*1), X8
+	MOVOU	-112(AX)(CX*1), X9
+	MOVOU	-96(AX)(CX*1), X10
+	MOVOU	-80(AX)(CX*1), X11
+	MOVOU	-64(AX)(CX*1), X12
+	MOVOU	-48(AX)(CX*1), X13
+	MOVOU	-32(AX)(CX*1), X14
+	MOVOU	-16(AX)(CX*1), X15
+
+	// scramble input once, xor in seed
+	AESENC	X0, X8
+	AESENC	X1, X9
+	AESENC	X2, X10
+	AESENC	X3, X11
+	AESENC	X4, X12
+	AESENC	X5, X13
+	AESENC	X6, X14
+	AESENC	X7, X15
+	
 	// compute number of remaining 128-byte blocks
 	DECQ	CX
 	SHRQ	$7, CX
 	
 aesloop:
 	// scramble state, xor in a block
-	MOVOU	(AX), X10
-	MOVOU	16(AX), X11
-	MOVOU	32(AX), X12
-	MOVOU	48(AX), X13
-	AESENC	X10, X0
-	AESENC	X11, X1
-	AESENC	X12, X2
-	AESENC	X13, X3
-	MOVOU	64(AX), X10
-	MOVOU	80(AX), X11
-	MOVOU	96(AX), X12
-	MOVOU	112(AX), X13
-	AESENC	X10, X4
-	AESENC	X11, X5
-	AESENC	X12, X8
-	AESENC	X13, X9
+	MOVOU	(AX), X0
+	MOVOU	16(AX), X1
+	MOVOU	32(AX), X2
+	MOVOU	48(AX), X3
+	AESENC	X0, X8
+	AESENC	X1, X9
+	AESENC	X2, X10
+	AESENC	X3, X11
+	MOVOU	64(AX), X4
+	MOVOU	80(AX), X5
+	MOVOU	96(AX), X6
+	MOVOU	112(AX), X7
+	AESENC	X4, X12
+	AESENC	X5, X13
+	AESENC	X6, X14
+	AESENC	X7, X15
 
 	// scramble state
-	AESENC	X7, X0
-	AESENC	X7, X1
-	AESENC	X7, X2
-	AESENC	X7, X3
-	AESENC	X7, X4
-	AESENC	X7, X5
-	AESENC	X7, X8
-	AESENC	X7, X9
+	AESENC	X8, X8
+	AESENC	X9, X9
+	AESENC	X10, X10
+	AESENC	X11, X11
+	AESENC	X12, X12
+	AESENC	X13, X13
+	AESENC	X14, X14
+	AESENC	X15, X15
 
 	ADDQ	$128, AX
 	DECQ	CX
 	JNE	aesloop
 
 	// 2 more scrambles to finish
-	AESENC	X7, X0
-	AESENC	X7, X1
-	AESENC	X7, X2
-	AESENC	X7, X3
-	AESENC	X7, X4
-	AESENC	X7, X5
-	AESENC	X7, X8
-	AESENC	X7, X9
-	AESENC	X7, X0
-	AESENC	X7, X1
-	AESENC	X7, X2
-	AESENC	X7, X3
-	AESENC	X7, X4
-	AESENC	X7, X5
-	AESENC	X7, X8
-	AESENC	X7, X9
-
-	PXOR	X4, X0
-	PXOR	X5, X1
-	PXOR	X8, X2
-	PXOR	X9, X3
-	PXOR	X2, X0
-	PXOR	X3, X1
-	PXOR	X1, X0
-	MOVQ	X0, (DX)
+	AESENC	X8, X8
+	AESENC	X9, X9
+	AESENC	X10, X10
+	AESENC	X11, X11
+	AESENC	X12, X12
+	AESENC	X13, X13
+	AESENC	X14, X14
+	AESENC	X15, X15
+	AESENC	X8, X8
+	AESENC	X9, X9
+	AESENC	X10, X10
+	AESENC	X11, X11
+	AESENC	X12, X12
+	AESENC	X13, X13
+	AESENC	X14, X14
+	AESENC	X15, X15
+
+	PXOR	X12, X8
+	PXOR	X13, X9
+	PXOR	X14, X10
+	PXOR	X15, X11
+	PXOR	X10, X8
+	PXOR	X11, X9
+	PXOR	X9, X8
+	MOVQ	X8, (DX)
 	RET
 	
 TEXT runtime·aeshash32(SB),NOSPLIT,$0-24
@@ -1272,6 +1223,15 @@ DATA masks<>+0xf0(SB)/8, $0xffffffffffffffff
 DATA masks<>+0xf8(SB)/8, $0x00ffffffffffffff
 GLOBL masks<>(SB),RODATA,$256
 
+TEXT ·checkASM(SB),NOSPLIT,$0-1
+	// check that masks<>(SB) and shifts<>(SB) are aligned to 16-byte
+	MOVQ	$masks<>(SB), AX
+	MOVQ	$shifts<>(SB), BX
+	ORQ	BX, AX
+	TESTQ	$15, AX
+	SETEQ	ret+0(FP)
+	RET
+
 // these are arguments to pshufb.  They move data down from
 // the high bytes of the register to the low bytes of the register.
 // index is how many bytes to move.
@@ -1353,6 +1313,10 @@ eq:
 TEXT runtime·memeqbody(SB),NOSPLIT,$0-0
 	CMPQ	BX, $8
 	JB	small
+	CMPQ	BX, $64
+	JB	bigloop
+	CMPB    runtime·support_avx2(SB), $1
+	JE	hugeloop_avx2
 	
 	// 64 bytes at a time using xmm registers
 hugeloop:
@@ -1382,6 +1346,30 @@ hugeloop:
 	MOVB	$0, (AX)
 	RET
 
+	// 64 bytes at a time using ymm registers
+hugeloop_avx2:
+	CMPQ	BX, $64
+	JB	bigloop_avx2
+	VMOVDQU	(SI), Y0
+	VMOVDQU	(DI), Y1
+	VMOVDQU	32(SI), Y2
+	VMOVDQU	32(DI), Y3
+	VPCMPEQB	Y1, Y0, Y4
+	VPCMPEQB	Y2, Y3, Y5
+	VPAND	Y4, Y5, Y6
+	VPMOVMSKB Y6, DX
+	ADDQ	$64, SI
+	ADDQ	$64, DI
+	SUBQ	$64, BX
+	CMPL	DX, $0xffffffff
+	JEQ	hugeloop_avx2
+	VZEROUPPER
+	MOVB	$0, (AX)
+	RET
+
+bigloop_avx2:
+	VZEROUPPER
+
 	// 8 bytes at a time using 64-bit register
 bigloop:
 	CMPQ	BX, $8
@@ -1470,6 +1458,11 @@ TEXT runtime·cmpbody(SB),NOSPLIT,$0-0
 	CMPQ	R8, $8
 	JB	small
 
+	CMPQ	R8, $63
+	JBE	loop
+	CMPB    runtime·support_avx2(SB), $1
+	JEQ     big_loop_avx2
+	JMP	big_loop
 loop:
 	CMPQ	R8, $16
 	JBE	_0through16
@@ -1484,6 +1477,17 @@ loop:
 	SUBQ	$16, R8
 	JMP	loop
 	
+diff64:
+	ADDQ	$48, SI
+	ADDQ	$48, DI
+	JMP	diff16
+diff48:
+	ADDQ	$32, SI
+	ADDQ	$32, DI
+	JMP	diff16
+diff32:
+	ADDQ	$16, SI
+	ADDQ	$16, DI
 	// AX = bit mask of differences
 diff16:
 	BSFQ	AX, BX	// index of first byte that differs
@@ -1570,6 +1574,244 @@ allsame:
 	MOVQ	AX, (R9)
 	RET
 
+	// this works for >= 64 bytes of data.
+big_loop:
+	MOVOU	(SI), X0
+	MOVOU	(DI), X1
+	PCMPEQB X0, X1
+	PMOVMSKB X1, AX
+	XORQ	$0xffff, AX
+	JNE	diff16
+
+	MOVOU	16(SI), X0
+	MOVOU	16(DI), X1
+	PCMPEQB X0, X1
+	PMOVMSKB X1, AX
+	XORQ	$0xffff, AX
+	JNE	diff32
+
+	MOVOU	32(SI), X0
+	MOVOU	32(DI), X1
+	PCMPEQB X0, X1
+	PMOVMSKB X1, AX
+	XORQ	$0xffff, AX
+	JNE	diff48
+
+	MOVOU	48(SI), X0
+	MOVOU	48(DI), X1
+	PCMPEQB X0, X1
+	PMOVMSKB X1, AX
+	XORQ	$0xffff, AX
+	JNE	diff64
+
+	ADDQ	$64, SI
+	ADDQ	$64, DI
+	SUBQ	$64, R8
+	CMPQ	R8, $64
+	JBE	loop
+	JMP	big_loop
+
+	// Compare 64-bytes per loop iteration.
+	// Loop is unrolled and uses AVX2.
+big_loop_avx2:
+	VMOVDQU	(SI), Y2
+	VMOVDQU	(DI), Y3
+	VMOVDQU	32(SI), Y4
+	VMOVDQU	32(DI), Y5
+	VPCMPEQB Y2, Y3, Y0
+	VPMOVMSKB Y0, AX
+	XORL	$0xffffffff, AX
+	JNE	diff32_avx2
+	VPCMPEQB Y4, Y5, Y6
+	VPMOVMSKB Y6, AX
+	XORL	$0xffffffff, AX
+	JNE	diff64_avx2
+
+	ADDQ	$64, SI
+	ADDQ	$64, DI
+	SUBQ	$64, R8
+	CMPQ	R8, $64
+	JB	big_loop_avx2_exit
+	JMP	big_loop_avx2
+
+	// Avoid AVX->SSE transition penalty and search first 32 bytes of 64 byte chunk.
+diff32_avx2:
+	VZEROUPPER
+	JMP diff16
+
+	// Same as diff32_avx2, but for last 32 bytes.
+diff64_avx2:
+	VZEROUPPER
+	JMP diff48
+
+	// For <64 bytes remainder jump to normal loop.
+big_loop_avx2_exit:
+	VZEROUPPER
+	JMP loop
+
+
+// TODO: Also use this in bytes.Index
+TEXT strings·indexShortStr(SB),NOSPLIT,$0-40
+	MOVQ s+0(FP), DI
+	MOVQ s_len+8(FP), CX
+	MOVQ c+16(FP), AX
+	MOVQ c_len+24(FP), BX
+	CMPQ BX, CX
+	JA fail
+	CMPQ BX, $2
+	JA   _3_or_more
+	MOVW (AX), AX
+	LEAQ -1(DI)(CX*1), CX
+loop2:
+	MOVW (DI), SI
+	CMPW SI,AX
+	JZ success
+	ADDQ $1,DI
+	CMPQ DI,CX
+	JB loop2
+	JMP fail
+_3_or_more:
+	CMPQ BX, $3
+	JA   _4_or_more
+	MOVW 1(AX), DX
+	MOVW (AX), AX
+	LEAQ -2(DI)(CX*1), CX
+loop3:
+	MOVW (DI), SI
+	CMPW SI,AX
+	JZ   partial_success3
+	ADDQ $1,DI
+	CMPQ DI,CX
+	JB loop3
+	JMP fail
+partial_success3:
+	MOVW 1(DI), SI
+	CMPW SI,DX
+	JZ success
+	ADDQ $1,DI
+	CMPQ DI,CX
+	JB loop3
+	JMP fail
+_4_or_more:
+	CMPQ BX, $4
+	JA   _5_or_more
+	MOVL (AX), AX
+	LEAQ -3(DI)(CX*1), CX
+loop4:
+	MOVL (DI), SI
+	CMPL SI,AX
+	JZ   success
+	ADDQ $1,DI
+	CMPQ DI,CX
+	JB loop4
+	JMP fail
+_5_or_more:
+	CMPQ BX, $7
+	JA   _8_or_more
+	LEAQ 1(DI)(CX*1), CX
+	SUBQ BX, CX
+	MOVL -4(AX)(BX*1), DX
+	MOVL (AX), AX
+loop5to7:
+	MOVL (DI), SI
+	CMPL SI,AX
+	JZ   partial_success5to7
+	ADDQ $1,DI
+	CMPQ DI,CX
+	JB loop5to7
+	JMP fail
+partial_success5to7:
+	MOVL -4(BX)(DI*1), SI
+	CMPL SI,DX
+	JZ success
+	ADDQ $1,DI
+	CMPQ DI,CX
+	JB loop5to7
+	JMP fail
+_8_or_more:
+	CMPQ BX, $8
+	JA   _9_or_more
+	MOVQ (AX), AX
+	LEAQ -7(DI)(CX*1), CX
+loop8:
+	MOVQ (DI), SI
+	CMPQ SI,AX
+	JZ   success
+	ADDQ $1,DI
+	CMPQ DI,CX
+	JB loop8
+	JMP fail
+_9_or_more:
+	CMPQ BX, $16
+	JA   _16_or_more
+	LEAQ 1(DI)(CX*1), CX
+	SUBQ BX, CX
+	MOVQ -8(AX)(BX*1), DX
+	MOVQ (AX), AX
+loop9to15:
+	MOVQ (DI), SI
+	CMPQ SI,AX
+	JZ   partial_success9to15
+	ADDQ $1,DI
+	CMPQ DI,CX
+	JB loop9to15
+	JMP fail
+partial_success9to15:
+	MOVQ -8(BX)(DI*1), SI
+	CMPQ SI,DX
+	JZ success
+	ADDQ $1,DI
+	CMPQ DI,CX
+	JB loop9to15
+	JMP fail
+_16_or_more:
+	CMPQ BX, $16
+	JA   _17_to_31
+	MOVOU (AX), X1
+	LEAQ -15(DI)(CX*1), CX
+loop16:
+	MOVOU (DI), X2
+	PCMPEQB X1, X2
+	PMOVMSKB X2, SI
+	CMPQ  SI, $0xffff
+	JE   success
+	ADDQ $1,DI
+	CMPQ DI,CX
+	JB loop16
+	JMP fail
+_17_to_31:
+	LEAQ 1(DI)(CX*1), CX
+	SUBQ BX, CX
+	MOVOU -16(AX)(BX*1), X0
+	MOVOU (AX), X1
+loop17to31:
+	MOVOU (DI), X2
+	PCMPEQB X1,X2
+	PMOVMSKB X2, SI
+	CMPQ  SI, $0xffff
+	JE   partial_success17to31
+	ADDQ $1,DI
+	CMPQ DI,CX
+	JB loop17to31
+	JMP fail
+partial_success17to31:
+	MOVOU -16(BX)(DI*1), X3
+	PCMPEQB X0, X3
+	PMOVMSKB X3, SI
+	CMPQ  SI, $0xffff
+	JE success
+	ADDQ $1,DI
+	CMPQ DI,CX
+	JB loop17to31
+fail:
+	MOVQ $-1, ret+32(FP)
+	RET
+success:
+	SUBQ s+0(FP), DI
+	MOVQ DI, ret+32(FP)
+	RET
+
+
 TEXT bytes·IndexByte(SB),NOSPLIT,$0-40
 	MOVQ s+0(FP), SI
 	MOVQ s_len+8(FP), BX
@@ -1595,6 +1837,9 @@ TEXT runtime·indexbytebody(SB),NOSPLIT,$0
 	CMPQ BX, $16
 	JLT small
 
+	CMPQ BX, $32
+	JA avx2
+no_avx2:
 	// round up to first 16-byte boundary
 	TESTQ $15, SI
 	JZ aligned
@@ -1658,6 +1903,38 @@ small:
 	MOVQ $-1, (R8)
 	RET
 
+avx2:
+	CMPB   runtime·support_avx2(SB), $1
+	JNE no_avx2
+	MOVD AX, X0
+	LEAQ -32(SI)(BX*1), R11
+	VPBROADCASTB  X0, Y1
+avx2_loop:
+	VMOVDQU (DI), Y2
+	VPCMPEQB Y1, Y2, Y3
+	VPTEST Y3, Y3
+	JNZ avx2success
+	ADDQ $32, DI
+	CMPQ DI, R11
+	JLT avx2_loop
+	MOVQ R11, DI
+	VMOVDQU (DI), Y2
+	VPCMPEQB Y1, Y2, Y3
+	VPTEST Y3, Y3
+	JNZ avx2success
+	VZEROUPPER
+	MOVQ $-1, (R8)
+	RET
+
+avx2success:
+	VPMOVMSKB Y3, DX
+	BSFL DX, DX
+	SUBQ SI, DI
+	ADDQ DI, DX
+	MOVQ DX, (R8)
+	VZEROUPPER
+	RET
+
 // we've found the chunk containing the byte
 // now just figure out which specific byte it is
 ssesuccess:
diff --git a/src/runtime/asm_amd64p32.s b/src/runtime/asm_amd64p32.s
index 4b12f01..ecbc597 100644
--- a/src/runtime/asm_amd64p32.s
+++ b/src/runtime/asm_amd64p32.s
@@ -39,13 +39,13 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$0
 nocpuinfo:	
 	
 needtls:
-	LEAL	runtime·tls0(SB), DI
+	LEAL	runtime·m0+m_tls(SB), DI
 	CALL	runtime·settls(SB)
 
 	// store through it, to make sure it works
 	get_tls(BX)
 	MOVQ	$0x123, g(BX)
-	MOVQ	runtime·tls0(SB), AX
+	MOVQ	runtime·m0+m_tls(SB), AX
 	CMPQ	AX, $0x123
 	JEQ 2(PC)
 	MOVL	AX, 0	// abort
@@ -415,118 +415,6 @@ CALLFN(·call268435456, 268435456)
 CALLFN(·call536870912, 536870912)
 CALLFN(·call1073741824, 1073741824)
 
-// bool cas(int32 *val, int32 old, int32 new)
-// Atomically:
-//	if(*val == old){
-//		*val = new;
-//		return 1;
-//	} else
-//		return 0;
-TEXT runtime·cas(SB), NOSPLIT, $0-17
-	MOVL	ptr+0(FP), BX
-	MOVL	old+4(FP), AX
-	MOVL	new+8(FP), CX
-	LOCK
-	CMPXCHGL	CX, 0(BX)
-	SETEQ	ret+16(FP)
-	RET
-
-TEXT runtime·casuintptr(SB), NOSPLIT, $0-17
-	JMP	runtime·cas(SB)
-
-TEXT runtime·atomicloaduintptr(SB), NOSPLIT, $0-12
-	JMP	runtime·atomicload(SB)
-
-TEXT runtime·atomicloaduint(SB), NOSPLIT, $0-12
-	JMP	runtime·atomicload(SB)
-
-TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-12
-	JMP	runtime·atomicstore(SB)
-
-// bool	runtime·cas64(uint64 *val, uint64 old, uint64 new)
-// Atomically:
-//	if(*val == *old){
-//		*val = new;
-//		return 1;
-//	} else {
-//		return 0;
-//	}
-TEXT runtime·cas64(SB), NOSPLIT, $0-25
-	MOVL	ptr+0(FP), BX
-	MOVQ	old+8(FP), AX
-	MOVQ	new+16(FP), CX
-	LOCK
-	CMPXCHGQ	CX, 0(BX)
-	SETEQ	ret+24(FP)
-	RET
-
-// bool casp(void **val, void *old, void *new)
-// Atomically:
-//	if(*val == old){
-//		*val = new;
-//		return 1;
-//	} else
-//		return 0;
-TEXT runtime·casp1(SB), NOSPLIT, $0-17
-	MOVL	ptr+0(FP), BX
-	MOVL	old+4(FP), AX
-	MOVL	new+8(FP), CX
-	LOCK
-	CMPXCHGL	CX, 0(BX)
-	SETEQ	ret+16(FP)
-	RET
-
-// uint32 xadd(uint32 volatile *val, int32 delta)
-// Atomically:
-//	*val += delta;
-//	return *val;
-TEXT runtime·xadd(SB), NOSPLIT, $0-12
-	MOVL	ptr+0(FP), BX
-	MOVL	delta+4(FP), AX
-	MOVL	AX, CX
-	LOCK
-	XADDL	AX, 0(BX)
-	ADDL	CX, AX
-	MOVL	AX, ret+8(FP)
-	RET
-
-TEXT runtime·xadd64(SB), NOSPLIT, $0-24
-	MOVL	ptr+0(FP), BX
-	MOVQ	delta+8(FP), AX
-	MOVQ	AX, CX
-	LOCK
-	XADDQ	AX, 0(BX)
-	ADDQ	CX, AX
-	MOVQ	AX, ret+16(FP)
-	RET
-
-TEXT runtime·xadduintptr(SB), NOSPLIT, $0-12
-	JMP	runtime·xadd(SB)
-
-TEXT runtime·xchg(SB), NOSPLIT, $0-12
-	MOVL	ptr+0(FP), BX
-	MOVL	new+4(FP), AX
-	XCHGL	AX, 0(BX)
-	MOVL	AX, ret+8(FP)
-	RET
-
-TEXT runtime·xchg64(SB), NOSPLIT, $0-24
-	MOVL	ptr+0(FP), BX
-	MOVQ	new+8(FP), AX
-	XCHGQ	AX, 0(BX)
-	MOVQ	AX, ret+16(FP)
-	RET
-
-TEXT runtime·xchgp1(SB), NOSPLIT, $0-12
-	MOVL	ptr+0(FP), BX
-	MOVL	new+4(FP), AX
-	XCHGL	AX, 0(BX)
-	MOVL	AX, ret+8(FP)
-	RET
-
-TEXT runtime·xchguintptr(SB), NOSPLIT, $0-12
-	JMP	runtime·xchg(SB)
-
 TEXT runtime·procyield(SB),NOSPLIT,$0-0
 	MOVL	cycles+0(FP), AX
 again:
@@ -535,40 +423,6 @@ again:
 	JNZ	again
 	RET
 
-TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-8
-	MOVL	ptr+0(FP), BX
-	MOVL	val+4(FP), AX
-	XCHGL	AX, 0(BX)
-	RET
-
-TEXT runtime·atomicstore(SB), NOSPLIT, $0-8
-	MOVL	ptr+0(FP), BX
-	MOVL	val+4(FP), AX
-	XCHGL	AX, 0(BX)
-	RET
-
-TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
-	MOVL	ptr+0(FP), BX
-	MOVQ	val+8(FP), AX
-	XCHGQ	AX, 0(BX)
-	RET
-
-// void	runtime·atomicor8(byte volatile*, byte);
-TEXT runtime·atomicor8(SB), NOSPLIT, $0-5
-	MOVL	ptr+0(FP), BX
-	MOVB	val+4(FP), AX
-	LOCK
-	ORB	AX, 0(BX)
-	RET
-
-// void	runtime·atomicand8(byte volatile*, byte);
-TEXT runtime·atomicand8(SB), NOSPLIT, $0-5
-	MOVL	ptr+0(FP), BX
-	MOVB	val+4(FP), AX
-	LOCK
-	ANDB	AX, 0(BX)
-	RET
-
 TEXT ·publicationBarrier(SB),NOSPLIT,$0-0
 	// Stores are already ordered on x86, so this is just a
 	// compile barrier.
@@ -1158,3 +1012,7 @@ TEXT runtime·prefetchnta(SB),NOSPLIT,$0-4
 	MOVL	addr+0(FP), AX
 	PREFETCHNTA	(AX)
 	RET
+
+TEXT ·checkASM(SB),NOSPLIT,$0-1
+	MOVB	$1, ret+0(FP)
+	RET
diff --git a/src/runtime/asm_arm.s b/src/runtime/asm_arm.s
index 9c32e42..07894a3 100644
--- a/src/runtime/asm_arm.s
+++ b/src/runtime/asm_arm.s
@@ -31,7 +31,8 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$-4
 	MOVW	R8, g_m(g)
 
 	// create istack out of the OS stack
-	MOVW	$(-8192+104)(R13), R0
+	// (1MB of system stack is available on iOS and Android)
+	MOVW	$(-64*1024+104)(R13), R0
 	MOVW	R0, g_stackguard0(g)
 	MOVW	R0, g_stackguard1(g)
 	MOVW	R0, (g_stack+stack_lo)(g)
@@ -85,8 +86,12 @@ TEXT runtime·breakpoint(SB),NOSPLIT,$0-0
 #ifdef GOOS_nacl
 	WORD	$0xe125be7f	// BKPT 0x5bef, NACL_INSTR_ARM_BREAKPOINT
 #else
+#ifdef GOOS_plan9
+	WORD	$0xD1200070	// undefined instruction used as armv5 breakpoint in Plan 9
+#else
 	WORD	$0xe7f001f0	// undefined instruction that gdb understands is a software breakpoint
 #endif
+#endif
 	RET
 
 TEXT runtime·asminit(SB),NOSPLIT,$0-0
@@ -555,7 +560,13 @@ TEXT	·cgocallback_gofunc(SB),NOSPLIT,$8-12
 	// lots of space, but the linker doesn't know. Hide the call from
 	// the linker analysis by using an indirect call.
 	CMP	$0, g
-	B.NE	havem
+	B.EQ	needm
+
+	MOVW	g_m(g), R8
+	MOVW	R8, savedm-4(SP)
+	B	havem
+
+needm:
 	MOVW	g, savedm-4(SP) // g is zero, so is m.
 	MOVW	$runtime·needm(SB), R0
 	BL	(R0)
@@ -576,8 +587,6 @@ TEXT	·cgocallback_gofunc(SB),NOSPLIT,$8-12
 	MOVW	R13, (g_sched+gobuf_sp)(R3)
 
 havem:
-	MOVW	g_m(g), R8
-	MOVW	R8, savedm-4(SP)
 	// Now there's a valid m, and we're running on its m->g0.
 	// Save current m->g0->sched.sp on stack and then set it to SP.
 	// Save current sp in m->g0->sched.sp in preparation for
@@ -694,63 +703,6 @@ TEXT runtime·abort(SB),NOSPLIT,$-4-0
 	MOVW	$0, R0
 	MOVW	(R0), R1
 
-// bool armcas(int32 *val, int32 old, int32 new)
-// Atomically:
-//	if(*val == old){
-//		*val = new;
-//		return 1;
-//	}else
-//		return 0;
-//
-// To implement runtime·cas in sys_$GOOS_arm.s
-// using the native instructions, use:
-//
-//	TEXT runtime·cas(SB),NOSPLIT,$0
-//		B	runtime·armcas(SB)
-//
-TEXT runtime·armcas(SB),NOSPLIT,$0-13
-	MOVW	valptr+0(FP), R1
-	MOVW	old+4(FP), R2
-	MOVW	new+8(FP), R3
-casl:
-	LDREX	(R1), R0
-	CMP	R0, R2
-	BNE	casfail
-
-	MOVB	runtime·goarm(SB), R11
-	CMP	$7, R11
-	BLT	2(PC)
-	WORD	$0xf57ff05a	// dmb ishst
-
-	STREX	R3, (R1), R0
-	CMP	$0, R0
-	BNE	casl
-	MOVW	$1, R0
-
-	MOVB	runtime·goarm(SB), R11
-	CMP	$7, R11
-	BLT	2(PC)
-	WORD	$0xf57ff05b	// dmb ish
-
-	MOVB	R0, ret+12(FP)
-	RET
-casfail:
-	MOVW	$0, R0
-	MOVB	R0, ret+12(FP)
-	RET
-
-TEXT runtime·casuintptr(SB),NOSPLIT,$0-13
-	B	runtime·cas(SB)
-
-TEXT runtime·atomicloaduintptr(SB),NOSPLIT,$0-8
-	B	runtime·atomicload(SB)
-
-TEXT runtime·atomicloaduint(SB),NOSPLIT,$0-8
-	B	runtime·atomicload(SB)
-
-TEXT runtime·atomicstoreuintptr(SB),NOSPLIT,$0-8
-	B	runtime·atomicstore(SB)
-
 // armPublicationBarrier is a native store/store barrier for ARMv7+.
 // On earlier ARM revisions, armPublicationBarrier is a no-op.
 // This will not work on SMP ARMv6 machines, if any are in use.
@@ -862,6 +814,8 @@ TEXT bytes·Compare(SB),NOSPLIT,$-4-28
 // On exit:
 // R4, R5, and R6 are clobbered
 TEXT runtime·cmpbody(SB),NOSPLIT,$-4-0
+	CMP	R2, R3
+	BEQ	samebytes
 	CMP 	R0, R1
 	MOVW 	R0, R6
 	MOVW.LT	R1, R6	// R6 is min(R0, R1)
@@ -1070,3 +1024,22 @@ TEXT runtime·usplitR0(SB),NOSPLIT,$0
 	MULU	R0, R1
 	SUB	R1, R3, R1
 	RET
+
+TEXT runtime·sigreturn(SB),NOSPLIT,$0-4
+        RET
+
+#ifndef GOOS_nacl
+// This is called from .init_array and follows the platform, not Go, ABI.
+TEXT runtime·addmoduledata(SB),NOSPLIT,$0-4
+	MOVW	R9, saver9-4(SP) // The access to global variables below implicitly uses R9, which is callee-save
+	MOVW	runtime·lastmoduledatap(SB), R1
+	MOVW	R0, moduledata_next(R1)
+	MOVW	R0, runtime·lastmoduledatap(SB)
+	MOVW	saver9-4(SP), R9
+	RET
+#endif
+
+TEXT ·checkASM(SB),NOSPLIT,$0-1
+	MOVW	$1, R3
+	MOVB	R3, ret+0(FP)
+	RET
diff --git a/src/runtime/asm_arm64.s b/src/runtime/asm_arm64.s
index 9aff9c7..ab5d5b5 100644
--- a/src/runtime/asm_arm64.s
+++ b/src/runtime/asm_arm64.s
@@ -36,9 +36,9 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$0
 	MRS_TPIDR_R0			// load TLS base pointer
 	MOVD	R0, R3			// arg 3: TLS base pointer
 #ifdef TLSG_IS_VARIABLE
-	MOVD	$runtime·tls_g(SB), R2 	// arg 2: tlsg
+	MOVD	$runtime·tls_g(SB), R2 	// arg 2: &tls_g
 #else
-	MOVD	$0x10, R2		// arg 2: tlsg TODO(minux): hardcoded for linux
+	MOVD	$0, R2		        // arg 2: not used when using platform's TLS
 #endif
 	MOVD	$setg_gcc<>(SB), R1	// arg 1: setg
 	MOVD	g, R0			// arg 0: G
@@ -426,7 +426,6 @@ end:						\
 
 // These have 8 added to make the overall frame size a multiple of 16,
 // as required by the ABI. (There is another +8 for the saved LR.)
-CALLFN(·call16, 24 )
 CALLFN(·call32, 40 )
 CALLFN(·call64, 72 )
 CALLFN(·call128, 136 )
@@ -454,40 +453,6 @@ CALLFN(·call268435456, 268435464 )
 CALLFN(·call536870912, 536870920 )
 CALLFN(·call1073741824, 1073741832 )
 
-// bool cas(uint32 *ptr, uint32 old, uint32 new)
-// Atomically:
-//	if(*val == old){
-//		*val = new;
-//		return 1;
-//	} else
-//		return 0;
-TEXT runtime·cas(SB), NOSPLIT, $0-17
-	MOVD	ptr+0(FP), R0
-	MOVW	old+8(FP), R1
-	MOVW	new+12(FP), R2
-again:
-	LDAXRW	(R0), R3
-	CMPW	R1, R3
-	BNE	ok
-	STLXRW	R2, (R0), R3
-	CBNZ	R3, again
-ok:
-	CSET	EQ, R0
-	MOVB	R0, ret+16(FP)
-	RET
-
-TEXT runtime·casuintptr(SB), NOSPLIT, $0-25
-	B	runtime·cas64(SB)
-
-TEXT runtime·atomicloaduintptr(SB), NOSPLIT, $-8-16
-	B	runtime·atomicload64(SB)
-
-TEXT runtime·atomicloaduint(SB), NOSPLIT, $-8-16
-	B	runtime·atomicload64(SB)
-
-TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-16
-	B	runtime·atomicstore64(SB)
-
 // AES hashing not implemented for ARM64, issue #10109.
 TEXT runtime·aeshash(SB),NOSPLIT,$-8-0
 	MOVW	$0, R0
@@ -501,17 +466,7 @@ TEXT runtime·aeshash64(SB),NOSPLIT,$-8-0
 TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0
 	MOVW	$0, R0
 	MOVW	(R0), R1
-
-// bool casp(void **val, void *old, void *new)
-// Atomically:
-//	if(*val == old){
-//		*val = new;
-//		return 1;
-//	} else
-//		return 0;
-TEXT runtime·casp1(SB), NOSPLIT, $0-25
-	B runtime·cas64(SB)
-
+	
 TEXT runtime·procyield(SB),NOSPLIT,$0-0
 	MOVWU	cycles+0(FP), R0
 again:
@@ -631,7 +586,13 @@ nocgo:
 	// lots of space, but the linker doesn't know. Hide the call from
 	// the linker analysis by using an indirect call.
 	CMP	$0, g
-	BNE	havem
+	BEQ	needm
+
+	MOVD	g_m(g), R8
+	MOVD	R8, savedm-8(SP)
+	B	havem
+
+needm:
 	MOVD	g, savedm-8(SP) // g is zero, so is m.
 	MOVD	$runtime·needm(SB), R0
 	BL	(R0)
@@ -653,8 +614,6 @@ nocgo:
 	MOVD	R0, (g_sched+gobuf_sp)(R3)
 
 havem:
-	MOVD	g_m(g), R8
-	MOVD	R8, savedm-8(SP)
 	// Now there's a valid m, and we're running on its m->g0.
 	// Save current m->g0->sched.sp on stack and then set it to SP.
 	// Save current sp in m->g0->sched.sp in preparation for
@@ -870,6 +829,8 @@ TEXT bytes·Compare(SB),NOSPLIT,$-4-56
 // On exit:
 // R4, R5, and R6 are clobbered
 TEXT runtime·cmpbody<>(SB),NOSPLIT,$-4-0
+	CMP	R2, R3
+	BEQ	samebytes // same starting pointers; compare lengths
 	CMP	R0, R1
 	CSEL    LT, R1, R0, R6 // R6 is min(R0, R1)
 
@@ -1027,3 +988,21 @@ TEXT runtime·prefetcht2(SB),NOSPLIT,$0-8
 TEXT runtime·prefetchnta(SB),NOSPLIT,$0-8
 	RET
 
+TEXT runtime·sigreturn(SB),NOSPLIT,$0-8
+        RET
+
+// This is called from .init_array and follows the platform, not Go, ABI.
+TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0
+	SUB	$0x10, RSP
+	MOVD	R27, 8(RSP) // The access to global variables below implicitly uses R27, which is callee-save
+	MOVD	runtime·lastmoduledatap(SB), R1
+	MOVD	R0, moduledata_next(R1)
+	MOVD	R0, runtime·lastmoduledatap(SB)
+	MOVD	8(RSP), R27
+	ADD	$0x10, RSP
+	RET
+
+TEXT ·checkASM(SB),NOSPLIT,$0-1
+	MOVW	$1, R3
+	MOVB	R3, ret+0(FP)
+	RET
diff --git a/src/runtime/asm_mips64x.s b/src/runtime/asm_mips64x.s
new file mode 100644
index 0000000..08482fe
--- /dev/null
+++ b/src/runtime/asm_mips64x.s
@@ -0,0 +1,829 @@
+// Copyright 2015 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.
+
+// +build mips64 mips64le
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "funcdata.h"
+#include "textflag.h"
+
+#define	REGCTXT	R22
+
+TEXT runtime·rt0_go(SB),NOSPLIT,$0
+	// R29 = stack; R1 = argc; R2 = argv
+
+	// initialize essential registers
+	JAL	runtime·reginit(SB)
+
+	ADDV	$-24, R29
+	MOVW	R1, 8(R29) // argc
+	MOVV	R2, 16(R29) // argv
+
+	// create istack out of the given (operating system) stack.
+	// _cgo_init may update stackguard.
+	MOVV	$runtime·g0(SB), g
+	MOVV	$(-64*1024), R28
+	ADDV	R28, R29, R1
+	MOVV	R1, g_stackguard0(g)
+	MOVV	R1, g_stackguard1(g)
+	MOVV	R1, (g_stack+stack_lo)(g)
+	MOVV	R29, (g_stack+stack_hi)(g)
+
+	// no cgo yet
+
+nocgo:
+	// update stackguard after _cgo_init
+	MOVV	(g_stack+stack_lo)(g), R1
+	ADDV	$const__StackGuard, R1
+	MOVV	R1, g_stackguard0(g)
+	MOVV	R1, g_stackguard1(g)
+
+	// set the per-goroutine and per-mach "registers"
+	MOVV	$runtime·m0(SB), R1
+
+	// save m->g0 = g0
+	MOVV	g, m_g0(R1)
+	// save m0 to g0->m
+	MOVV	R1, g_m(g)
+
+	JAL	runtime·check(SB)
+
+	// args are already prepared
+	JAL	runtime·args(SB)
+	JAL	runtime·osinit(SB)
+	JAL	runtime·schedinit(SB)
+
+	// create a new goroutine to start program
+	MOVV	$runtime·mainPC(SB), R1		// entry
+	ADDV	$-24, R29
+	MOVV	R1, 16(R29)
+	MOVV	R0, 8(R29)
+	MOVV	R0, 0(R29)
+	JAL	runtime·newproc(SB)
+	ADDV	$24, R29
+
+	// start this M
+	JAL	runtime·mstart(SB)
+
+	MOVV	R0, 1(R0)
+	RET
+
+DATA	runtime·mainPC+0(SB)/8,$runtime·main(SB)
+GLOBL	runtime·mainPC(SB),RODATA,$8
+
+TEXT runtime·breakpoint(SB),NOSPLIT,$-8-0
+	MOVV	R0, 2(R0) // TODO: TD
+	RET
+
+TEXT runtime·asminit(SB),NOSPLIT,$-8-0
+	RET
+
+TEXT _cgo_reginit(SB),NOSPLIT,$-8-0
+	// crosscall_ppc64 and crosscall2 need to reginit, but can't
+	// get at the 'runtime.reginit' symbol.
+	JMP	runtime·reginit(SB)
+
+TEXT runtime·reginit(SB),NOSPLIT,$-8-0
+	// initialize essential FP registers
+	MOVD	$0.5, F26
+	SUBD	F26, F26, F24
+	ADDD	F26, F26, F28
+	ADDD	F28, F28, F30
+	RET
+
+/*
+ *  go-routine
+ */
+
+// void gosave(Gobuf*)
+// save state in Gobuf; setjmp
+TEXT runtime·gosave(SB), NOSPLIT, $-8-8
+	MOVV	buf+0(FP), R1
+	MOVV	R29, gobuf_sp(R1)
+	MOVV	R31, gobuf_pc(R1)
+	MOVV	g, gobuf_g(R1)
+	MOVV	R0, gobuf_lr(R1)
+	MOVV	R0, gobuf_ret(R1)
+	MOVV	R0, gobuf_ctxt(R1)
+	RET
+
+// void gogo(Gobuf*)
+// restore state from Gobuf; longjmp
+TEXT runtime·gogo(SB), NOSPLIT, $-8-8
+	MOVV	buf+0(FP), R3
+	MOVV	gobuf_g(R3), g	// make sure g is not nil
+	JAL	runtime·save_g(SB)
+
+	MOVV	0(g), R2
+	MOVV	gobuf_sp(R3), R29
+	MOVV	gobuf_lr(R3), R31
+	MOVV	gobuf_ret(R3), R1
+	MOVV	gobuf_ctxt(R3), REGCTXT
+	MOVV	R0, gobuf_sp(R3)
+	MOVV	R0, gobuf_ret(R3)
+	MOVV	R0, gobuf_lr(R3)
+	MOVV	R0, gobuf_ctxt(R3)
+	MOVV	gobuf_pc(R3), R4
+	JMP	(R4)
+
+// void mcall(fn func(*g))
+// Switch to m->g0's stack, call fn(g).
+// Fn must never return.  It should gogo(&g->sched)
+// to keep running g.
+TEXT runtime·mcall(SB), NOSPLIT, $-8-8
+	// Save caller state in g->sched
+	MOVV	R29, (g_sched+gobuf_sp)(g)
+	MOVV	R31, (g_sched+gobuf_pc)(g)
+	MOVV	R0, (g_sched+gobuf_lr)(g)
+	MOVV	g, (g_sched+gobuf_g)(g)
+
+	// Switch to m->g0 & its stack, call fn.
+	MOVV	g, R1
+	MOVV	g_m(g), R3
+	MOVV	m_g0(R3), g
+	JAL	runtime·save_g(SB)
+	BNE	g, R1, 2(PC)
+	JMP	runtime·badmcall(SB)
+	MOVV	fn+0(FP), REGCTXT			// context
+	MOVV	0(REGCTXT), R4			// code pointer
+	MOVV	(g_sched+gobuf_sp)(g), R29	// sp = m->g0->sched.sp
+	ADDV	$-16, R29
+	MOVV	R1, 8(R29)
+	MOVV	R0, 0(R29)
+	JAL	(R4)
+	JMP	runtime·badmcall2(SB)
+
+// systemstack_switch is a dummy routine that systemstack leaves at the bottom
+// of the G stack.  We need to distinguish the routine that
+// lives at the bottom of the G stack from the one that lives
+// at the top of the system stack because the one at the top of
+// the system stack terminates the stack walk (see topofstack()).
+TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
+	UNDEF
+	JAL	(R31)	// make sure this function is not leaf
+	RET
+
+// func systemstack(fn func())
+TEXT runtime·systemstack(SB), NOSPLIT, $0-8
+	MOVV	fn+0(FP), R1	// R1 = fn
+	MOVV	R1, REGCTXT		// context
+	MOVV	g_m(g), R2	// R2 = m
+
+	MOVV	m_gsignal(R2), R3	// R3 = gsignal
+	BEQ	g, R3, noswitch
+
+	MOVV	m_g0(R2), R3	// R3 = g0
+	BEQ	g, R3, noswitch
+
+	MOVV	m_curg(R2), R4
+	BEQ	g, R4, switch
+
+	// Bad: g is not gsignal, not g0, not curg. What is it?
+	// Hide call from linker nosplit analysis.
+	MOVV	$runtime·badsystemstack(SB), R4
+	JAL	(R4)
+
+switch:
+	// save our state in g->sched.  Pretend to
+	// be systemstack_switch if the G stack is scanned.
+	MOVV	$runtime·systemstack_switch(SB), R4
+	ADDV	$8, R4	// get past prologue
+	MOVV	R4, (g_sched+gobuf_pc)(g)
+	MOVV	R29, (g_sched+gobuf_sp)(g)
+	MOVV	R0, (g_sched+gobuf_lr)(g)
+	MOVV	g, (g_sched+gobuf_g)(g)
+
+	// switch to g0
+	MOVV	R3, g
+	JAL	runtime·save_g(SB)
+	MOVV	(g_sched+gobuf_sp)(g), R1
+	// make it look like mstart called systemstack on g0, to stop traceback
+	ADDV	$-8, R1
+	MOVV	$runtime·mstart(SB), R2
+	MOVV	R2, 0(R1)
+	MOVV	R1, R29
+
+	// call target function
+	MOVV	0(REGCTXT), R4	// code pointer
+	JAL	(R4)
+
+	// switch back to g
+	MOVV	g_m(g), R1
+	MOVV	m_curg(R1), g
+	JAL	runtime·save_g(SB)
+	MOVV	(g_sched+gobuf_sp)(g), R29
+	MOVV	R0, (g_sched+gobuf_sp)(g)
+	RET
+
+noswitch:
+	// already on m stack, just call directly
+	MOVV	0(REGCTXT), R4	// code pointer
+	JAL	(R4)
+	RET
+
+/*
+ * support for morestack
+ */
+
+// Called during function prolog when more stack is needed.
+// Caller has already loaded:
+// R1: framesize, R2: argsize, R3: LR
+//
+// The traceback routines see morestack on a g0 as being
+// the top of a stack (for example, morestack calling newstack
+// calling the scheduler calling newm calling gc), so we must
+// record an argument size. For that purpose, it has no arguments.
+TEXT runtime·morestack(SB),NOSPLIT,$-8-0
+	// Cannot grow scheduler stack (m->g0).
+	MOVV	g_m(g), R7
+	MOVV	m_g0(R7), R8
+	BNE	g, R8, 2(PC)
+	JAL	runtime·abort(SB)
+
+	// Cannot grow signal stack (m->gsignal).
+	MOVV	m_gsignal(R7), R8
+	BNE	g, R8, 2(PC)
+	JAL	runtime·abort(SB)
+
+	// Called from f.
+	// Set g->sched to context in f.
+	MOVV	REGCTXT, (g_sched+gobuf_ctxt)(g)
+	MOVV	R29, (g_sched+gobuf_sp)(g)
+	MOVV	R31, (g_sched+gobuf_pc)(g)
+	MOVV	R3, (g_sched+gobuf_lr)(g)
+
+	// Called from f.
+	// Set m->morebuf to f's caller.
+	MOVV	R3, (m_morebuf+gobuf_pc)(R7)	// f's caller's PC
+	MOVV	R29, (m_morebuf+gobuf_sp)(R7)	// f's caller's SP
+	MOVV	g, (m_morebuf+gobuf_g)(R7)
+
+	// Call newstack on m->g0's stack.
+	MOVV	m_g0(R7), g
+	JAL	runtime·save_g(SB)
+	MOVV	(g_sched+gobuf_sp)(g), R29
+	JAL	runtime·newstack(SB)
+
+	// Not reached, but make sure the return PC from the call to newstack
+	// is still in this function, and not the beginning of the next.
+	UNDEF
+
+TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-8-0
+	MOVV	R0, REGCTXT
+	JMP	runtime·morestack(SB)
+
+TEXT runtime·stackBarrier(SB),NOSPLIT,$0
+	// We came here via a RET to an overwritten LR.
+	// R1 may be live. Other registers are available.
+
+	// Get the original return PC, g.stkbar[g.stkbarPos].savedLRVal.
+	MOVV	(g_stkbar+slice_array)(g), R2
+	MOVV	g_stkbarPos(g), R3
+	MOVV	$stkbar__size, R4
+	MULVU	R3, R4
+	MOVV	LO, R4
+	ADDV	R2, R4
+	MOVV	stkbar_savedLRVal(R4), R4
+	// Record that this stack barrier was hit.
+	ADDV	$1, R3
+	MOVV	R3, g_stkbarPos(g)
+	// Jump to the original return PC.
+	JMP	(R4)
+
+// reflectcall: call a function with the given argument list
+// func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32).
+// we don't have variable-sized frames, so we use a small number
+// of constant-sized-frame functions to encode a few bits of size in the pc.
+// Caution: ugly multiline assembly macros in your future!
+
+#define DISPATCH(NAME,MAXSIZE)		\
+	MOVV	$MAXSIZE, R28;		\
+	SGTU	R1, R28, R28;		\
+	BNE	R28, 3(PC);			\
+	MOVV	$NAME(SB), R4;	\
+	JMP	(R4)
+// Note: can't just "BR NAME(SB)" - bad inlining results.
+
+TEXT reflect·call(SB), NOSPLIT, $0-0
+	JMP	·reflectcall(SB)
+
+TEXT ·reflectcall(SB), NOSPLIT, $-8-32
+	MOVWU argsize+24(FP), R1
+	// NOTE(rsc): No call16, because CALLFN needs four words
+	// of argument space to invoke callwritebarrier.
+	DISPATCH(runtime·call32, 32)
+	DISPATCH(runtime·call64, 64)
+	DISPATCH(runtime·call128, 128)
+	DISPATCH(runtime·call256, 256)
+	DISPATCH(runtime·call512, 512)
+	DISPATCH(runtime·call1024, 1024)
+	DISPATCH(runtime·call2048, 2048)
+	DISPATCH(runtime·call4096, 4096)
+	DISPATCH(runtime·call8192, 8192)
+	DISPATCH(runtime·call16384, 16384)
+	DISPATCH(runtime·call32768, 32768)
+	DISPATCH(runtime·call65536, 65536)
+	DISPATCH(runtime·call131072, 131072)
+	DISPATCH(runtime·call262144, 262144)
+	DISPATCH(runtime·call524288, 524288)
+	DISPATCH(runtime·call1048576, 1048576)
+	DISPATCH(runtime·call2097152, 2097152)
+	DISPATCH(runtime·call4194304, 4194304)
+	DISPATCH(runtime·call8388608, 8388608)
+	DISPATCH(runtime·call16777216, 16777216)
+	DISPATCH(runtime·call33554432, 33554432)
+	DISPATCH(runtime·call67108864, 67108864)
+	DISPATCH(runtime·call134217728, 134217728)
+	DISPATCH(runtime·call268435456, 268435456)
+	DISPATCH(runtime·call536870912, 536870912)
+	DISPATCH(runtime·call1073741824, 1073741824)
+	MOVV	$runtime·badreflectcall(SB), R4
+	JMP	(R4)
+
+#define CALLFN(NAME,MAXSIZE)			\
+TEXT NAME(SB), WRAPPER, $MAXSIZE-24;		\
+	NO_LOCAL_POINTERS;			\
+	/* copy arguments to stack */		\
+	MOVV	arg+16(FP), R1;			\
+	MOVWU	argsize+24(FP), R2;			\
+	MOVV	R29, R3;				\
+	ADDV	$8, R3;			\
+	ADDV	R3, R2;				\
+	BEQ	R3, R2, 6(PC);				\
+	MOVBU	(R1), R4;			\
+	ADDV	$1, R1;			\
+	MOVBU	R4, (R3);			\
+	ADDV	$1, R3;			\
+	JMP	-5(PC);				\
+	/* call function */			\
+	MOVV	f+8(FP), REGCTXT;			\
+	MOVV	(REGCTXT), R4;			\
+	PCDATA  $PCDATA_StackMapIndex, $0;	\
+	JAL	(R4);				\
+	/* copy return values back */		\
+	MOVV	arg+16(FP), R1;			\
+	MOVWU	n+24(FP), R2;			\
+	MOVWU	retoffset+28(FP), R4;		\
+	MOVV	R29, R3;				\
+	ADDV	R4, R3; 			\
+	ADDV	R4, R1;				\
+	SUBVU	R4, R2;				\
+	ADDV	$8, R3;			\
+	ADDV	R3, R2;				\
+loop:						\
+	BEQ	R3, R2, end;				\
+	MOVBU	(R3), R4;			\
+	ADDV	$1, R3;			\
+	MOVBU	R4, (R1);			\
+	ADDV	$1, R1;			\
+	JMP	loop;				\
+end:						\
+	/* execute write barrier updates */	\
+	MOVV	argtype+0(FP), R5;		\
+	MOVV	arg+16(FP), R1;			\
+	MOVWU	n+24(FP), R2;			\
+	MOVWU	retoffset+28(FP), R4;		\
+	MOVV	R5, 8(R29);			\
+	MOVV	R1, 16(R29);			\
+	MOVV	R2, 24(R29);			\
+	MOVV	R4, 32(R29);			\
+	JAL	runtime·callwritebarrier(SB);	\
+	RET
+
+CALLFN(·call16, 16)
+CALLFN(·call32, 32)
+CALLFN(·call64, 64)
+CALLFN(·call128, 128)
+CALLFN(·call256, 256)
+CALLFN(·call512, 512)
+CALLFN(·call1024, 1024)
+CALLFN(·call2048, 2048)
+CALLFN(·call4096, 4096)
+CALLFN(·call8192, 8192)
+CALLFN(·call16384, 16384)
+CALLFN(·call32768, 32768)
+CALLFN(·call65536, 65536)
+CALLFN(·call131072, 131072)
+CALLFN(·call262144, 262144)
+CALLFN(·call524288, 524288)
+CALLFN(·call1048576, 1048576)
+CALLFN(·call2097152, 2097152)
+CALLFN(·call4194304, 4194304)
+CALLFN(·call8388608, 8388608)
+CALLFN(·call16777216, 16777216)
+CALLFN(·call33554432, 33554432)
+CALLFN(·call67108864, 67108864)
+CALLFN(·call134217728, 134217728)
+CALLFN(·call268435456, 268435456)
+CALLFN(·call536870912, 536870912)
+CALLFN(·call1073741824, 1073741824)
+
+TEXT runtime·procyield(SB),NOSPLIT,$0-0
+	RET
+
+// void jmpdefer(fv, sp);
+// called from deferreturn.
+// 1. grab stored LR for caller
+// 2. sub 8 bytes to get back to JAL deferreturn
+// 3. JMP to fn
+TEXT runtime·jmpdefer(SB), NOSPLIT, $-8-16
+	MOVV	0(R29), R31
+	ADDV	$-8, R31
+
+	MOVV	fv+0(FP), REGCTXT
+	MOVV	argp+8(FP), R29
+	ADDV	$-8, R29
+	NOR	R0, R0	// prevent scheduling
+	MOVV	0(REGCTXT), R4
+	JMP	(R4)
+
+// Save state of caller into g->sched. Smashes R31.
+TEXT gosave<>(SB),NOSPLIT,$-8
+	MOVV	R31, (g_sched+gobuf_pc)(g)
+	MOVV	R29, (g_sched+gobuf_sp)(g)
+	MOVV	R0, (g_sched+gobuf_lr)(g)
+	MOVV	R0, (g_sched+gobuf_ret)(g)
+	MOVV	R0, (g_sched+gobuf_ctxt)(g)
+	RET
+
+// func asmcgocall(fn, arg unsafe.Pointer) int32
+// Call fn(arg) on the scheduler stack,
+// aligned appropriately for the gcc ABI.
+// See cgocall.go for more details.
+TEXT ·asmcgocall(SB),NOSPLIT,$0-20
+	UNDEF	// no cgo yet
+	RET
+
+// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
+// Turn the fn into a Go func (by taking its address) and call
+// cgocallback_gofunc.
+TEXT runtime·cgocallback(SB),NOSPLIT,$24-24
+	MOVV	$fn+0(FP), R1
+	MOVV	R1, 8(R29)
+	MOVV	frame+8(FP), R1
+	MOVV	R1, 16(R29)
+	MOVV	framesize+16(FP), R1
+	MOVV	R1, 24(R29)
+	MOVV	$runtime·cgocallback_gofunc(SB), R1
+	JAL	(R1)
+	RET
+
+// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
+// See cgocall.go for more details.
+TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-24
+	NO_LOCAL_POINTERS
+
+	// Load m and g from thread-local storage.
+	MOVB	runtime·iscgo(SB), R1
+	BEQ	R1, nocgo
+	JAL	runtime·load_g(SB)
+nocgo:
+
+	// If g is nil, Go did not create the current thread.
+	// Call needm to obtain one for temporary use.
+	// In this case, we're running on the thread stack, so there's
+	// lots of space, but the linker doesn't know. Hide the call from
+	// the linker analysis by using an indirect call.
+	BEQ	g, needm
+
+	MOVV	g_m(g), R3
+	MOVV	R3, savedm-8(SP)
+	JMP	havem
+
+needm:
+	MOVV	g, savedm-8(SP) // g is zero, so is m.
+	MOVV	$runtime·needm(SB), R4
+	JAL	(R4)
+
+	// Set m->sched.sp = SP, so that if a panic happens
+	// during the function we are about to execute, it will
+	// have a valid SP to run on the g0 stack.
+	// The next few lines (after the havem label)
+	// will save this SP onto the stack and then write
+	// the same SP back to m->sched.sp. That seems redundant,
+	// but if an unrecovered panic happens, unwindm will
+	// restore the g->sched.sp from the stack location
+	// and then systemstack will try to use it. If we don't set it here,
+	// that restored SP will be uninitialized (typically 0) and
+	// will not be usable.
+	MOVV	g_m(g), R1
+	MOVV	m_g0(R1), R1
+	MOVV	R29, (g_sched+gobuf_sp)(R1)
+
+havem:
+	// Now there's a valid m, and we're running on its m->g0.
+	// Save current m->g0->sched.sp on stack and then set it to SP.
+	// Save current sp in m->g0->sched.sp in preparation for
+	// switch back to m->curg stack.
+	// NOTE: unwindm knows that the saved g->sched.sp is at 8(R29) aka savedsp-16(SP).
+	MOVV	m_g0(R3), R1
+	MOVV	(g_sched+gobuf_sp)(R1), R2
+	MOVV	R2, savedsp-16(SP)
+	MOVV	R29, (g_sched+gobuf_sp)(R1)
+
+	// Switch to m->curg stack and call runtime.cgocallbackg.
+	// Because we are taking over the execution of m->curg
+	// but *not* resuming what had been running, we need to
+	// save that information (m->curg->sched) so we can restore it.
+	// We can restore m->curg->sched.sp easily, because calling
+	// runtime.cgocallbackg leaves SP unchanged upon return.
+	// To save m->curg->sched.pc, we push it onto the stack.
+	// This has the added benefit that it looks to the traceback
+	// routine like cgocallbackg is going to return to that
+	// PC (because the frame we allocate below has the same
+	// size as cgocallback_gofunc's frame declared above)
+	// so that the traceback will seamlessly trace back into
+	// the earlier calls.
+	//
+	// In the new goroutine, -16(SP) and -8(SP) are unused.
+	MOVV	m_curg(R3), g
+	JAL	runtime·save_g(SB)
+	MOVV	(g_sched+gobuf_sp)(g), R2 // prepare stack as R2
+	MOVV	(g_sched+gobuf_pc)(g), R3
+	MOVV	R3, -24(R2)
+	MOVV	$-24(R2), R29
+	JAL	runtime·cgocallbackg(SB)
+
+	// Restore g->sched (== m->curg->sched) from saved values.
+	MOVV	0(R29), R3
+	MOVV	R3, (g_sched+gobuf_pc)(g)
+	MOVV	$24(R29), R2
+	MOVV	R2, (g_sched+gobuf_sp)(g)
+
+	// Switch back to m->g0's stack and restore m->g0->sched.sp.
+	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
+	// so we do not have to restore it.)
+	MOVV	g_m(g), R3
+	MOVV	m_g0(R3), g
+	JAL	runtime·save_g(SB)
+	MOVV	(g_sched+gobuf_sp)(g), R29
+	MOVV	savedsp-16(SP), R2
+	MOVV	R2, (g_sched+gobuf_sp)(g)
+
+	// If the m on entry was nil, we called needm above to borrow an m
+	// for the duration of the call. Since the call is over, return it with dropm.
+	MOVV	savedm-8(SP), R3
+	BNE	R3, droppedm
+	MOVV	$runtime·dropm(SB), R4
+	JAL	(R4)
+droppedm:
+
+	// Done!
+	RET
+
+// void setg(G*); set g. for use by needm.
+TEXT runtime·setg(SB), NOSPLIT, $0-8
+	MOVV	gg+0(FP), g
+	// This only happens if iscgo, so jump straight to save_g
+	JAL	runtime·save_g(SB)
+	RET
+
+// void setg_gcc(G*); set g in C TLS.
+// Must obey the gcc calling convention.
+TEXT setg_gcc<>(SB),NOSPLIT,$-8-0
+	UNDEF	// no cgo yet
+	RET
+
+TEXT runtime·getcallerpc(SB),NOSPLIT,$8-16
+	MOVV	16(R29), R1		// LR saved by caller
+	MOVV	runtime·stackBarrierPC(SB), R2
+	BNE	R1, R2, nobar
+	// Get original return PC.
+	JAL	runtime·nextBarrierPC(SB)
+	MOVV	8(R29), R1
+nobar:
+	MOVV	R1, ret+8(FP)
+	RET
+
+TEXT runtime·setcallerpc(SB),NOSPLIT,$8-16
+	MOVV	pc+8(FP), R1
+	MOVV	16(R29), R2
+	MOVV	runtime·stackBarrierPC(SB), R3
+	BEQ	R2, R3, setbar
+	MOVV	R1, 16(R29)		// set LR in caller
+	RET
+setbar:
+	// Set the stack barrier return PC.
+	MOVV	R1, 8(R29)
+	JAL	runtime·setNextBarrierPC(SB)
+	RET
+
+TEXT runtime·getcallersp(SB),NOSPLIT,$0-16
+	MOVV	argp+0(FP), R1
+	ADDV	$-8, R1
+	MOVV	R1, ret+8(FP)
+	RET
+
+TEXT runtime·abort(SB),NOSPLIT,$-8-0
+	MOVW	(R0), R0
+	UNDEF
+
+// memhash_varlen(p unsafe.Pointer, h seed) uintptr
+// redirects to memhash(p, h, size) using the size
+// stored in the closure.
+TEXT runtime·memhash_varlen(SB),NOSPLIT,$40-24
+	GO_ARGS
+	NO_LOCAL_POINTERS
+	MOVV	p+0(FP), R1
+	MOVV	h+8(FP), R2
+	MOVV	8(REGCTXT), R3
+	MOVV	R1, 8(R29)
+	MOVV	R2, 16(R29)
+	MOVV	R3, 24(R29)
+	JAL	runtime·memhash(SB)
+	MOVV	32(R29), R1
+	MOVV	R1, ret+16(FP)
+	RET
+
+// AES hashing not implemented for mips64
+TEXT runtime·aeshash(SB),NOSPLIT,$-8-0
+	MOVW	(R0), R1
+TEXT runtime·aeshash32(SB),NOSPLIT,$-8-0
+	MOVW	(R0), R1
+TEXT runtime·aeshash64(SB),NOSPLIT,$-8-0
+	MOVW	(R0), R1
+TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0
+	MOVW	(R0), R1
+
+TEXT runtime·memeq(SB),NOSPLIT,$-8-25
+	MOVV	a+0(FP), R1
+	MOVV	b+8(FP), R2
+	MOVV	size+16(FP), R3
+	ADDV	R1, R3, R4
+loop:
+	BNE	R1, R4, test
+	MOVV	$1, R1
+	MOVB	R1, ret+24(FP)
+	RET
+test:
+	MOVBU	(R1), R6
+	ADDV	$1, R1
+	MOVBU	(R2), R7
+	ADDV	$1, R2
+	BEQ	R6, R7, loop
+
+	MOVB	R0, ret+24(FP)
+	RET
+
+// memequal_varlen(a, b unsafe.Pointer) bool
+TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17
+	MOVV	a+0(FP), R1
+	MOVV	b+8(FP), R2
+	BEQ	R1, R2, eq
+	MOVV	8(REGCTXT), R3    // compiler stores size at offset 8 in the closure
+	MOVV	R1, 8(R29)
+	MOVV	R2, 16(R29)
+	MOVV	R3, 24(R29)
+	JAL	runtime·memeq(SB)
+	MOVBU	32(R29), R1
+	MOVB	R1, ret+16(FP)
+	RET
+eq:
+	MOVV	$1, R1
+	MOVB	R1, ret+16(FP)
+	RET
+
+// 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
+	MOVV	s1str+0(FP), R1
+	MOVV	s2str+16(FP), R2
+	MOVV	$1, R3
+	MOVB	R3, ret+32(FP)
+	BNE	R1, R2, 2(PC)
+	RET
+	MOVV	s1len+8(FP), R3
+	ADDV	R1, R3, R4
+loop:
+	BNE	R1, R4, 2(PC)
+	RET
+	MOVBU	(R1), R6
+	ADDV	$1, R1
+	MOVBU	(R2), R7
+	ADDV	$1, R2
+	BEQ	R6, R7, loop
+	MOVB	R0, ret+32(FP)
+	RET
+
+// TODO: share code with memeq?
+TEXT bytes·Equal(SB),NOSPLIT,$0-49
+	MOVV	a_len+8(FP), R3
+	MOVV	b_len+32(FP), R4
+	BNE	R3, R4, noteq		// unequal lengths are not equal
+
+	MOVV	a+0(FP), R1
+	MOVV	b+24(FP), R2
+	ADDV	R1, R3		// end
+
+loop:
+	BEQ	R1, R3, equal		// reached the end
+	MOVBU	(R1), R6
+	ADDV	$1, R1
+	MOVBU	(R2), R7
+	ADDV	$1, R2
+	BEQ	R6, R7, loop
+
+noteq:
+	MOVB	R0, ret+48(FP)
+	RET
+
+equal:
+	MOVV	$1, R1
+	MOVB	R1, ret+48(FP)
+	RET
+
+TEXT bytes·IndexByte(SB),NOSPLIT,$0-40
+	MOVV	s+0(FP), R1
+	MOVV	s_len+8(FP), R2
+	MOVBU	c+24(FP), R3	// byte to find
+	MOVV	R1, R4		// store base for later
+	ADDV	R1, R2		// end
+	ADDV	$-1, R1
+
+loop:
+	ADDV	$1, R1
+	BEQ	R1, R2, notfound
+	MOVBU	(R1), R5
+	BNE	R3, R5, loop
+
+	SUBV	R4, R1		// remove base
+	MOVV	R1, ret+32(FP)
+	RET
+
+notfound:
+	MOVV	$-1, R1
+	MOVV	R1, ret+32(FP)
+	RET
+
+TEXT strings·IndexByte(SB),NOSPLIT,$0-32
+	MOVV	p+0(FP), R1
+	MOVV	b_len+8(FP), R2
+	MOVBU	c+16(FP), R3	// byte to find
+	MOVV	R1, R4		// store base for later
+	ADDV	R1, R2		// end
+	ADDV	$-1, R1
+
+loop:
+	ADDV	$1, R1
+	BEQ	R1, R2, notfound
+	MOVBU	(R1), R5
+	BNE	R3, R5, loop
+
+	SUBV	R4, R1		// remove base
+	MOVV	R1, ret+24(FP)
+	RET
+
+notfound:
+	MOVV	$-1, R1
+	MOVV	R1, ret+24(FP)
+	RET
+
+TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
+	MOVV	g_m(g), R2
+	MOVWU	m_fastrand(R2), R1
+	ADDU	R1, R1
+	BGEZ	R1, 2(PC)
+	XOR	$0x88888eef, R1
+	MOVW	R1, m_fastrand(R2)
+	MOVW	R1, ret+0(FP)
+	RET
+
+TEXT runtime·return0(SB), NOSPLIT, $0
+	MOVW	$0, R1
+	RET
+
+// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
+// Must obey the gcc calling convention.
+TEXT _cgo_topofstack(SB),NOSPLIT,$-8
+	UNDEF	// no cgo yet
+	RET
+
+// The top-most function running on a goroutine
+// returns to goexit+PCQuantum.
+TEXT runtime·goexit(SB),NOSPLIT,$-8-0
+	NOR	R0, R0	// NOP
+	JAL	runtime·goexit1(SB)	// does not return
+	// traceback from goexit1 must hit code range of goexit
+	NOR	R0, R0	// NOP
+
+TEXT runtime·prefetcht0(SB),NOSPLIT,$0-8
+	RET
+
+TEXT runtime·prefetcht1(SB),NOSPLIT,$0-8
+	RET
+
+TEXT runtime·prefetcht2(SB),NOSPLIT,$0-8
+	RET
+
+TEXT runtime·prefetchnta(SB),NOSPLIT,$0-8
+	RET
+
+TEXT ·checkASM(SB),NOSPLIT,$0-1
+	MOVW	$1, R1
+	MOVB	R1, ret+0(FP)
+	RET
diff --git a/src/runtime/asm_ppc64x.h b/src/runtime/asm_ppc64x.h
new file mode 100644
index 0000000..a413df6
--- /dev/null
+++ b/src/runtime/asm_ppc64x.h
@@ -0,0 +1,25 @@
+// Copyright 2015 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.
+
+// FIXED_FRAME defines the size of the fixed part of a stack frame. A stack
+// frame looks like this:
+//
+// +---------------------+
+// | local variable area |
+// +---------------------+
+// | argument area       |
+// +---------------------+ <- R1+FIXED_FRAME
+// | fixed area          |
+// +---------------------+ <- R1
+//
+// So a function that sets up a stack frame at all uses as least FIXED_FRAME
+// bytes of stack.  This mostly affects assembly that calls other functions
+// with arguments (the arguments should be stored at FIXED_FRAME+0(R1),
+// FIXED_FRAME+8(R1) etc) and some other low-level places.
+//
+// The reason for using a constant is to make supporting PIC easier (although
+// we only support PIC on ppc64le which has a minimum 32 bytes of stack frame,
+// and currently always use that much, PIC on ppc64 would need to use 48).
+
+#define FIXED_FRAME 32
diff --git a/src/runtime/asm_ppc64x.s b/src/runtime/asm_ppc64x.s
index 0404124..50c4f26 100644
--- a/src/runtime/asm_ppc64x.s
+++ b/src/runtime/asm_ppc64x.s
@@ -8,6 +8,7 @@
 #include "go_tls.h"
 #include "funcdata.h"
 #include "textflag.h"
+#include "asm_ppc64x.h"
 
 TEXT runtime·rt0_go(SB),NOSPLIT,$0
 	// R1 = stack; R3 = argc; R4 = argv; R13 = C TLS base pointer
@@ -15,9 +16,10 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$0
 	// initialize essential registers
 	BL	runtime·reginit(SB)
 
-	SUB	$24, R1
-	MOVW	R3, 8(R1) // argc
-	MOVD	R4, 16(R1) // argv
+	SUB	$(FIXED_FRAME+16), R1
+	MOVD	R2, 24(R1)		// stash the TOC pointer away again now we've created a new frame
+	MOVW	R3, FIXED_FRAME+0(R1)	// argc
+	MOVD	R4, FIXED_FRAME+8(R1)	// argv
 
 	// create istack out of the given (operating system) stack.
 	// _cgo_init may update stackguard.
@@ -44,6 +46,7 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$0
 	RLDCR	$0, R1, $~15, R1	// 16-byte align
 	BL	(CTR)			// may clobber R0, R3-R12
 	MOVD	R14, R1			// restore stack
+	MOVD	24(R1), R2
 	XOR	R0, R0			// fix R0
 
 nocgo:
@@ -73,8 +76,11 @@ nocgo:
 	MOVDU	R3, -8(R1)
 	MOVDU	R0, -8(R1)
 	MOVDU	R0, -8(R1)
+	MOVDU	R0, -8(R1)
+	MOVDU	R0, -8(R1)
+	MOVDU	R0, -8(R1)
 	BL	runtime·newproc(SB)
-	ADD	$24, R1
+	ADD	$(16+FIXED_FRAME), R1
 
 	// start this M
 	BL	runtime·mstart(SB)
@@ -85,19 +91,19 @@ nocgo:
 DATA	runtime·mainPC+0(SB)/8,$runtime·main(SB)
 GLOBL	runtime·mainPC(SB),RODATA,$8
 
-TEXT runtime·breakpoint(SB),NOSPLIT,$-8-0
+TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0
 	MOVD	R0, 2(R0) // TODO: TD
 	RET
 
-TEXT runtime·asminit(SB),NOSPLIT,$-8-0
+TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0
 	RET
 
-TEXT _cgo_reginit(SB),NOSPLIT,$-8-0
+TEXT _cgo_reginit(SB),NOSPLIT|NOFRAME,$0-0
 	// crosscall_ppc64 and crosscall2 need to reginit, but can't
 	// get at the 'runtime.reginit' symbol.
 	BR	runtime·reginit(SB)
 
-TEXT runtime·reginit(SB),NOSPLIT,$-8-0
+TEXT runtime·reginit(SB),NOSPLIT|NOFRAME,$0-0
 	// set R0 to zero, it's expected by the toolchain
 	XOR R0, R0
 	// initialize essential FP registers
@@ -114,7 +120,7 @@ TEXT runtime·reginit(SB),NOSPLIT,$-8-0
 
 // void gosave(Gobuf*)
 // save state in Gobuf; setjmp
-TEXT runtime·gosave(SB), NOSPLIT, $-8-8
+TEXT runtime·gosave(SB), NOSPLIT|NOFRAME, $0-8
 	MOVD	buf+0(FP), R3
 	MOVD	R1, gobuf_sp(R3)
 	MOVD	LR, R31
@@ -127,7 +133,7 @@ TEXT runtime·gosave(SB), NOSPLIT, $-8-8
 
 // void gogo(Gobuf*)
 // restore state from Gobuf; longjmp
-TEXT runtime·gogo(SB), NOSPLIT, $-8-8
+TEXT runtime·gogo(SB), NOSPLIT|NOFRAME, $0-8
 	MOVD	buf+0(FP), R5
 	MOVD	gobuf_g(R5), g	// make sure g is not nil
 	BL	runtime·save_g(SB)
@@ -143,15 +149,15 @@ TEXT runtime·gogo(SB), NOSPLIT, $-8-8
 	MOVD	R0, gobuf_lr(R5)
 	MOVD	R0, gobuf_ctxt(R5)
 	CMP	R0, R0 // set condition codes for == test, needed by stack split
-	MOVD	gobuf_pc(R5), R31
-	MOVD	R31, CTR
+	MOVD	gobuf_pc(R5), R12
+	MOVD	R12, CTR
 	BR	(CTR)
 
 // void mcall(fn func(*g))
 // Switch to m->g0's stack, call fn(g).
 // Fn must never return.  It should gogo(&g->sched)
 // to keep running g.
-TEXT runtime·mcall(SB), NOSPLIT, $-8-8
+TEXT runtime·mcall(SB), NOSPLIT|NOFRAME, $0-8
 	// Save caller state in g->sched
 	MOVD	R1, (g_sched+gobuf_sp)(g)
 	MOVD	LR, R31
@@ -168,12 +174,16 @@ TEXT runtime·mcall(SB), NOSPLIT, $-8-8
 	BNE	2(PC)
 	BR	runtime·badmcall(SB)
 	MOVD	fn+0(FP), R11			// context
-	MOVD	0(R11), R4			// code pointer
-	MOVD	R4, CTR
+	MOVD	0(R11), R12			// code pointer
+	MOVD	R12, CTR
 	MOVD	(g_sched+gobuf_sp)(g), R1	// sp = m->g0->sched.sp
 	MOVDU	R3, -8(R1)
 	MOVDU	R0, -8(R1)
+	MOVDU	R0, -8(R1)
+	MOVDU	R0, -8(R1)
+	MOVDU	R0, -8(R1)
 	BL	(CTR)
+	MOVD	24(R1), R2
 	BR	runtime·badmcall2(SB)
 
 // systemstack_switch is a dummy routine that systemstack leaves at the bottom
@@ -182,6 +192,11 @@ TEXT runtime·mcall(SB), NOSPLIT, $-8-8
 // at the top of the system stack because the one at the top of
 // the system stack terminates the stack walk (see topofstack()).
 TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
+	// We have several undefs here so that 16 bytes past
+	// $runtime·systemstack_switch lies within them whether or not the
+        // instructions that derive r2 from r12 are there.
+	UNDEF
+	UNDEF
 	UNDEF
 	BL	(LR)	// make sure this function is not leaf
 	RET
@@ -206,15 +221,15 @@ TEXT runtime·systemstack(SB), NOSPLIT, $0-8
 
 	// Bad: g is not gsignal, not g0, not curg. What is it?
 	// Hide call from linker nosplit analysis.
-	MOVD	$runtime·badsystemstack(SB), R3
-	MOVD	R3, CTR
+	MOVD	$runtime·badsystemstack(SB), R12
+	MOVD	R12, CTR
 	BL	(CTR)
 
 switch:
 	// save our state in g->sched.  Pretend to
 	// be systemstack_switch if the G stack is scanned.
 	MOVD	$runtime·systemstack_switch(SB), R6
-	ADD	$8, R6	// get past prologue
+	ADD     $16, R6 // get past prologue (including r2-setting instructions when they're there)
 	MOVD	R6, (g_sched+gobuf_pc)(g)
 	MOVD	R1, (g_sched+gobuf_sp)(g)
 	MOVD	R0, (g_sched+gobuf_lr)(g)
@@ -225,16 +240,23 @@ switch:
 	BL	runtime·save_g(SB)
 	MOVD	(g_sched+gobuf_sp)(g), R3
 	// make it look like mstart called systemstack on g0, to stop traceback
-	SUB	$8, R3
+	SUB	$FIXED_FRAME, R3
 	MOVD	$runtime·mstart(SB), R4
 	MOVD	R4, 0(R3)
 	MOVD	R3, R1
 
 	// call target function
-	MOVD	0(R11), R3	// code pointer
-	MOVD	R3, CTR
+	MOVD	0(R11), R12	// code pointer
+	MOVD	R12, CTR
 	BL	(CTR)
 
+	// restore TOC pointer. It seems unlikely that we will use systemstack
+	// to call a function defined in another module, but the results of
+	// doing so would be so confusing that it's worth doing this.
+	MOVD	g_m(g), R3
+	MOVD	m_curg(R3), g
+	MOVD	(g_sched+gobuf_sp)(g), R3
+	MOVD	24(R3), R2
 	// switch back to g
 	MOVD	g_m(g), R3
 	MOVD	m_curg(R3), g
@@ -245,9 +267,10 @@ switch:
 
 noswitch:
 	// already on m stack, just call directly
-	MOVD	0(R11), R3	// code pointer
-	MOVD	R3, CTR
+	MOVD	0(R11), R12	// code pointer
+	MOVD	R12, CTR
 	BL	(CTR)
+	MOVD	24(R1), R2
 	RET
 
 /*
@@ -262,7 +285,7 @@ noswitch:
 // the top of a stack (for example, morestack calling newstack
 // calling the scheduler calling newm calling gc), so we must
 // record an argument size. For that purpose, it has no arguments.
-TEXT runtime·morestack(SB),NOSPLIT,$-8-0
+TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
 	// Cannot grow scheduler stack (m->g0).
 	MOVD	g_m(g), R7
 	MOVD	m_g0(R7), R8
@@ -300,7 +323,7 @@ TEXT runtime·morestack(SB),NOSPLIT,$-8-0
 	// is still in this function, and not the beginning of the next.
 	UNDEF
 
-TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-8-0
+TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
 	MOVD	R0, R11
 	BR	runtime·morestack(SB)
 
@@ -332,15 +355,15 @@ TEXT runtime·stackBarrier(SB),NOSPLIT,$0
 	MOVD	$MAXSIZE, R31;		\
 	CMP	R3, R31;		\
 	BGT	4(PC);			\
-	MOVD	$NAME(SB), R31;	\
-	MOVD	R31, CTR;		\
+	MOVD	$NAME(SB), R12;		\
+	MOVD	R12, CTR;		\
 	BR	(CTR)
 // Note: can't just "BR NAME(SB)" - bad inlining results.
 
 TEXT reflect·call(SB), NOSPLIT, $0-0
 	BR	·reflectcall(SB)
 
-TEXT ·reflectcall(SB), NOSPLIT, $-8-32
+TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-32
 	MOVWZ argsize+24(FP), R3
 	// NOTE(rsc): No call16, because CALLFN needs four words
 	// of argument space to invoke callwritebarrier.
@@ -370,8 +393,8 @@ TEXT ·reflectcall(SB), NOSPLIT, $-8-32
 	DISPATCH(runtime·call268435456, 268435456)
 	DISPATCH(runtime·call536870912, 536870912)
 	DISPATCH(runtime·call1073741824, 1073741824)
-	MOVD	$runtime·badreflectcall(SB), R31
-	MOVD	R31, CTR
+	MOVD	$runtime·badreflectcall(SB), R12
+	MOVD	R12, CTR
 	BR	(CTR)
 
 #define CALLFN(NAME,MAXSIZE)			\
@@ -381,7 +404,7 @@ TEXT NAME(SB), WRAPPER, $MAXSIZE-24;		\
 	MOVD	arg+16(FP), R3;			\
 	MOVWZ	argsize+24(FP), R4;			\
 	MOVD	R1, R5;				\
-	ADD	$(8-1), R5;			\
+	ADD	$(FIXED_FRAME-1), R5;			\
 	SUB	$1, R3;				\
 	ADD	R5, R4;				\
 	CMP	R5, R4;				\
@@ -391,10 +414,11 @@ TEXT NAME(SB), WRAPPER, $MAXSIZE-24;		\
 	BR	-4(PC);				\
 	/* call function */			\
 	MOVD	f+8(FP), R11;			\
-	MOVD	(R11), R31;			\
-	MOVD	R31, CTR;			\
+	MOVD	(R11), R12;			\
+	MOVD	R12, CTR;			\
 	PCDATA  $PCDATA_StackMapIndex, $0;	\
 	BL	(CTR);				\
+	MOVD	24(R1), R2;			\
 	/* copy return values back */		\
 	MOVD	arg+16(FP), R3;			\
 	MOVWZ	n+24(FP), R4;			\
@@ -403,7 +427,7 @@ TEXT NAME(SB), WRAPPER, $MAXSIZE-24;		\
 	ADD	R6, R5; 			\
 	ADD	R6, R3;				\
 	SUB	R6, R4;				\
-	ADD	$(8-1), R5;			\
+	ADD	$(FIXED_FRAME-1), R5;			\
 	SUB	$1, R3;				\
 	ADD	R5, R4;				\
 loop:						\
@@ -418,14 +442,13 @@ end:						\
 	MOVD	arg+16(FP), R3;			\
 	MOVWZ	n+24(FP), R4;			\
 	MOVWZ	retoffset+28(FP), R6;		\
-	MOVD	R7, 8(R1);			\
-	MOVD	R3, 16(R1);			\
-	MOVD	R4, 24(R1);			\
-	MOVD	R6, 32(R1);			\
+	MOVD	R7, FIXED_FRAME+0(R1);			\
+	MOVD	R3, FIXED_FRAME+8(R1);			\
+	MOVD	R4, FIXED_FRAME+16(R1);			\
+	MOVD	R6, FIXED_FRAME+24(R1);			\
 	BL	runtime·callwritebarrier(SB);	\
 	RET
 
-CALLFN(·call16, 16)
 CALLFN(·call32, 32)
 CALLFN(·call64, 64)
 CALLFN(·call128, 128)
@@ -453,239 +476,32 @@ CALLFN(·call268435456, 268435456)
 CALLFN(·call536870912, 536870912)
 CALLFN(·call1073741824, 1073741824)
 
-// bool cas(uint32 *ptr, uint32 old, uint32 new)
-// Atomically:
-//	if(*val == old){
-//		*val = new;
-//		return 1;
-//	} else
-//		return 0;
-TEXT runtime·cas(SB), NOSPLIT, $0-17
-	MOVD	ptr+0(FP), R3
-	MOVWZ	old+8(FP), R4
-	MOVWZ	new+12(FP), R5
-cas_again:
-	SYNC
-	LWAR	(R3), R6
-	CMPW	R6, R4
-	BNE	cas_fail
-	STWCCC	R5, (R3)
-	BNE	cas_again
-	MOVD	$1, R3
-	SYNC
-	ISYNC
-	MOVB	R3, ret+16(FP)
-	RET
-cas_fail:
-	MOVD	$0, R3
-	BR	-5(PC)
-
-// bool	runtime·cas64(uint64 *ptr, uint64 old, uint64 new)
-// Atomically:
-//	if(*val == *old){
-//		*val = new;
-//		return 1;
-//	} else {
-//		return 0;
-//	}
-TEXT runtime·cas64(SB), NOSPLIT, $0-25
-	MOVD	ptr+0(FP), R3
-	MOVD	old+8(FP), R4
-	MOVD	new+16(FP), R5
-cas64_again:
-	SYNC
-	LDAR	(R3), R6
-	CMP	R6, R4
-	BNE	cas64_fail
-	STDCCC	R5, (R3)
-	BNE	cas64_again
-	MOVD	$1, R3
-	SYNC
-	ISYNC
-	MOVB	R3, ret+24(FP)
-	RET
-cas64_fail:
-	MOVD	$0, R3
-	BR	-5(PC)
-
-TEXT runtime·casuintptr(SB), NOSPLIT, $0-25
-	BR	runtime·cas64(SB)
-
-TEXT runtime·atomicloaduintptr(SB), NOSPLIT, $-8-16
-	BR	runtime·atomicload64(SB)
-
-TEXT runtime·atomicloaduint(SB), NOSPLIT, $-8-16
-	BR	runtime·atomicload64(SB)
-
-TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-16
-	BR	runtime·atomicstore64(SB)
-
-// bool casp(void **val, void *old, void *new)
-// Atomically:
-//	if(*val == old){
-//		*val = new;
-//		return 1;
-//	} else
-//		return 0;
-TEXT runtime·casp1(SB), NOSPLIT, $0-25
-	BR runtime·cas64(SB)
-
-// uint32 xadd(uint32 volatile *ptr, int32 delta)
-// Atomically:
-//	*val += delta;
-//	return *val;
-TEXT runtime·xadd(SB), NOSPLIT, $0-20
-	MOVD	ptr+0(FP), R4
-	MOVW	delta+8(FP), R5
-	SYNC
-	LWAR	(R4), R3
-	ADD	R5, R3
-	STWCCC	R3, (R4)
-	BNE	-4(PC)
-	SYNC
-	ISYNC
-	MOVW	R3, ret+16(FP)
-	RET
-
-TEXT runtime·xadd64(SB), NOSPLIT, $0-24
-	MOVD	ptr+0(FP), R4
-	MOVD	delta+8(FP), R5
-	SYNC
-	LDAR	(R4), R3
-	ADD	R5, R3
-	STDCCC	R3, (R4)
-	BNE	-4(PC)
-	SYNC
-	ISYNC
-	MOVD	R3, ret+16(FP)
-	RET
-
-TEXT runtime·xchg(SB), NOSPLIT, $0-20
-	MOVD	ptr+0(FP), R4
-	MOVW	new+8(FP), R5
-	SYNC
-	LWAR	(R4), R3
-	STWCCC	R5, (R4)
-	BNE	-3(PC)
-	SYNC
-	ISYNC
-	MOVW	R3, ret+16(FP)
-	RET
-
-TEXT runtime·xchg64(SB), NOSPLIT, $0-24
-	MOVD	ptr+0(FP), R4
-	MOVD	new+8(FP), R5
-	SYNC
-	LDAR	(R4), R3
-	STDCCC	R5, (R4)
-	BNE	-3(PC)
-	SYNC
-	ISYNC
-	MOVD	R3, ret+16(FP)
-	RET
-
-TEXT runtime·xchgp1(SB), NOSPLIT, $0-24
-	BR	runtime·xchg64(SB)
-
-TEXT runtime·xchguintptr(SB), NOSPLIT, $0-24
-	BR	runtime·xchg64(SB)
-
 TEXT runtime·procyield(SB),NOSPLIT,$0-0
 	RET
 
-TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-16
-	BR	runtime·atomicstore64(SB)
-
-TEXT runtime·atomicstore(SB), NOSPLIT, $0-12
-	MOVD	ptr+0(FP), R3
-	MOVW	val+8(FP), R4
-	SYNC
-	MOVW	R4, 0(R3)
-	RET
-
-TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
-	MOVD	ptr+0(FP), R3
-	MOVD	val+8(FP), R4
-	SYNC
-	MOVD	R4, 0(R3)
-	RET
-
-// void	runtime·atomicor8(byte volatile*, byte);
-TEXT runtime·atomicor8(SB), NOSPLIT, $0-9
-	MOVD	ptr+0(FP), R3
-	MOVBZ	val+8(FP), R4
-	// Align ptr down to 4 bytes so we can use 32-bit load/store.
-	// R5 = (R3 << 0) & ~3
-	RLDCR	$0, R3, $~3, R5
-	// Compute val shift.
-#ifdef GOARCH_ppc64
-	// Big endian.  ptr = ptr ^ 3
-	XOR	$3, R3
-#endif
-	// R6 = ((ptr & 3) * 8) = (ptr << 3) & (3*8)
-	RLDC	$3, R3, $(3*8), R6
-	// Shift val for aligned ptr.  R4 = val << R6
-	SLD	R6, R4, R4
-
-again:
-	SYNC
-	LWAR	(R5), R6
-	OR	R4, R6
-	STWCCC	R6, (R5)
-	BNE	again
-	SYNC
-	ISYNC
-	RET
-
-// void	runtime·atomicand8(byte volatile*, byte);
-TEXT runtime·atomicand8(SB), NOSPLIT, $0-9
-	MOVD	ptr+0(FP), R3
-	MOVBZ	val+8(FP), R4
-	// Align ptr down to 4 bytes so we can use 32-bit load/store.
-	// R5 = (R3 << 0) & ~3
-	RLDCR	$0, R3, $~3, R5
-	// Compute val shift.
-#ifdef GOARCH_ppc64
-	// Big endian.  ptr = ptr ^ 3
-	XOR	$3, R3
-#endif
-	// R6 = ((ptr & 3) * 8) = (ptr << 3) & (3*8)
-	RLDC	$3, R3, $(3*8), R6
-	// Shift val for aligned ptr.  R4 = val << R6 | ^(0xFF << R6)
-	MOVD	$0xFF, R7
-	SLD	R6, R4
-	SLD	R6, R7
-	XOR $-1, R7
-	OR	R7, R4
-again:
-	SYNC
-	LWAR	(R5), R6
-	AND	R4, R6
-	STWCCC	R6, (R5)
-	BNE	again
-	SYNC
-	ISYNC
-	RET
-
 // void jmpdefer(fv, sp);
 // called from deferreturn.
 // 1. grab stored LR for caller
-// 2. sub 4 bytes to get back to BL deferreturn
+// 2. sub 8 bytes to get back to either nop or toc reload before deferreturn
 // 3. BR to fn
-TEXT runtime·jmpdefer(SB), NOSPLIT, $-8-16
+// When dynamically linking Go, it is not sufficient to rewind to the BL
+// deferreturn -- we might be jumping between modules and so we need to reset
+// the TOC pointer in r2. To do this, codegen inserts MOVD 24(R1), R2 *before*
+// the BL deferreturn and jmpdefer rewinds to that.
+TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16
 	MOVD	0(R1), R31
-	SUB	$4, R31
+	SUB     $8, R31
 	MOVD	R31, LR
 
 	MOVD	fv+0(FP), R11
 	MOVD	argp+8(FP), R1
-	SUB	$8, R1
-	MOVD	0(R11), R3
-	MOVD	R3, CTR
+	SUB	$FIXED_FRAME, R1
+	MOVD	0(R11), R12
+	MOVD	R12, CTR
 	BR	(CTR)
 
 // Save state of caller into g->sched. Smashes R31.
-TEXT gosave<>(SB),NOSPLIT,$-8
+TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
 	MOVD	LR, R31
 	MOVD	R31, (g_sched+gobuf_pc)(g)
 	MOVD	R1, (g_sched+gobuf_sp)(g)
@@ -702,7 +518,7 @@ TEXT ·asmcgocall(SB),NOSPLIT,$0-20
 	MOVD	fn+0(FP), R3
 	MOVD	arg+8(FP), R4
 
-	MOVD	R1, R2		// save original stack pointer
+	MOVD	R1, R7		// save original stack pointer
 	MOVD	g, R5
 
 	// Figure out if we need to switch to m->g0 stack.
@@ -725,7 +541,7 @@ g0:
 	RLDCR	$0, R1, $~15, R1	// 16-byte alignment for gcc ABI
 	MOVD	R5, 40(R1)	// save old g on stack
 	MOVD	(g_stack+stack_hi)(R5), R5
-	SUB	R2, R5
+	SUB	R7, R5
 	MOVD	R5, 32(R1)	// save depth in old g stack (can't just save SP, as stack might be copied during a callback)
 	MOVD	R0, 0(R1)	// clear back chain pointer (TODO can we give it real back trace information?)
 	// This is a "global call", so put the global entry point in r12
@@ -737,8 +553,13 @@ g0:
 	// C code can clobber R0, so set it back to 0.  F27-F31 are
 	// callee save, so we don't need to recover those.
 	XOR	R0, R0
-	// Restore g, stack pointer.  R3 is errno, so don't touch it
+	// Restore g, stack pointer, toc pointer.
+	// R3 is errno, so don't touch it
 	MOVD	40(R1), g
+	MOVD    (g_stack+stack_hi)(g), R5
+	MOVD    32(R1), R6
+	SUB     R6, R5
+	MOVD    24(R5), R2
 	BL	runtime·save_g(SB)
 	MOVD	(g_stack+stack_hi)(g), R5
 	MOVD	32(R1), R6
@@ -753,13 +574,13 @@ g0:
 // cgocallback_gofunc.
 TEXT runtime·cgocallback(SB),NOSPLIT,$24-24
 	MOVD	$fn+0(FP), R3
-	MOVD	R3, 8(R1)
+	MOVD	R3, FIXED_FRAME+0(R1)
 	MOVD	frame+8(FP), R3
-	MOVD	R3, 16(R1)
+	MOVD	R3, FIXED_FRAME+8(R1)
 	MOVD	framesize+16(FP), R3
-	MOVD	R3, 24(R1)
-	MOVD	$runtime·cgocallback_gofunc(SB), R3
-	MOVD	R3, CTR
+	MOVD	R3, FIXED_FRAME+16(R1)
+	MOVD	$runtime·cgocallback_gofunc(SB), R12
+	MOVD	R12, CTR
 	BL	(CTR)
 	RET
 
@@ -781,10 +602,16 @@ nocgo:
 	// lots of space, but the linker doesn't know. Hide the call from
 	// the linker analysis by using an indirect call.
 	CMP	g, $0
-	BNE	havem
+	BEQ	needm
+
+	MOVD	g_m(g), R8
+	MOVD	R8, savedm-8(SP)
+	BR	havem
+
+needm:
 	MOVD	g, savedm-8(SP) // g is zero, so is m.
-	MOVD	$runtime·needm(SB), R3
-	MOVD	R3, CTR
+	MOVD	$runtime·needm(SB), R12
+	MOVD	R12, CTR
 	BL	(CTR)
 
 	// Set m->sched.sp = SP, so that if a panic happens
@@ -798,13 +625,11 @@ nocgo:
 	// and then systemstack will try to use it. If we don't set it here,
 	// that restored SP will be uninitialized (typically 0) and
 	// will not be usable.
-	MOVD	g_m(g), R3
-	MOVD	m_g0(R3), R3
+	MOVD	g_m(g), R8
+	MOVD	m_g0(R8), R3
 	MOVD	R1, (g_sched+gobuf_sp)(R3)
 
 havem:
-	MOVD	g_m(g), R8
-	MOVD	R8, savedm-8(SP)
 	// Now there's a valid m, and we're running on its m->g0.
 	// Save current m->g0->sched.sp on stack and then set it to SP.
 	// Save current sp in m->g0->sched.sp in preparation for
@@ -834,14 +659,14 @@ havem:
 	BL	runtime·save_g(SB)
 	MOVD	(g_sched+gobuf_sp)(g), R4 // prepare stack as R4
 	MOVD	(g_sched+gobuf_pc)(g), R5
-	MOVD	R5, -24(R4)
-	MOVD	$-24(R4), R1
+	MOVD	R5, -(FIXED_FRAME+16)(R4)
+	MOVD	$-(FIXED_FRAME+16)(R4), R1
 	BL	runtime·cgocallbackg(SB)
 
 	// Restore g->sched (== m->curg->sched) from saved values.
 	MOVD	0(R1), R5
 	MOVD	R5, (g_sched+gobuf_pc)(g)
-	MOVD	$24(R1), R4
+	MOVD	$(FIXED_FRAME+16)(R1), R4
 	MOVD	R4, (g_sched+gobuf_sp)(g)
 
 	// Switch back to m->g0's stack and restore m->g0->sched.sp.
@@ -859,8 +684,8 @@ havem:
 	MOVD	savedm-8(SP), R6
 	CMP	R6, $0
 	BNE	droppedm
-	MOVD	$runtime·dropm(SB), R3
-	MOVD	R3, CTR
+	MOVD	$runtime·dropm(SB), R12
+	MOVD	R12, CTR
 	BL	(CTR)
 droppedm:
 
@@ -876,7 +701,7 @@ TEXT runtime·setg(SB), NOSPLIT, $0-8
 
 // void setg_gcc(G*); set g in C TLS.
 // Must obey the gcc calling convention.
-TEXT setg_gcc<>(SB),NOSPLIT,$-8-0
+TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
 	// The standard prologue clobbers R31, which is callee-save in
 	// the C ABI, so we have to use $-8-0 and save LR ourselves.
 	MOVD	LR, R4
@@ -893,38 +718,38 @@ TEXT setg_gcc<>(SB),NOSPLIT,$-8-0
 	RET
 
 TEXT runtime·getcallerpc(SB),NOSPLIT,$8-16
-	MOVD	16(R1), R3		// LR saved by caller
+	MOVD	FIXED_FRAME+8(R1), R3		// LR saved by caller
 	MOVD	runtime·stackBarrierPC(SB), R4
 	CMP	R3, R4
 	BNE	nobar
 	// Get original return PC.
 	BL	runtime·nextBarrierPC(SB)
-	MOVD	8(R1), R3
+	MOVD	FIXED_FRAME+0(R1), R3
 nobar:
 	MOVD	R3, ret+8(FP)
 	RET
 
 TEXT runtime·setcallerpc(SB),NOSPLIT,$8-16
 	MOVD	pc+8(FP), R3
-	MOVD	16(R1), R4
+	MOVD	FIXED_FRAME+8(R1), R4
 	MOVD	runtime·stackBarrierPC(SB), R5
 	CMP	R4, R5
 	BEQ	setbar
-	MOVD	R3, 16(R1)		// set LR in caller
+	MOVD	R3, FIXED_FRAME+8(R1)		// set LR in caller
 	RET
 setbar:
 	// Set the stack barrier return PC.
-	MOVD	R3, 8(R1)
+	MOVD	R3, FIXED_FRAME+0(R1)
 	BL	runtime·setNextBarrierPC(SB)
 	RET
 
 TEXT runtime·getcallersp(SB),NOSPLIT,$0-16
 	MOVD	argp+0(FP), R3
-	SUB	$8, R3
+	SUB	$FIXED_FRAME, R3
 	MOVD	R3, ret+8(FP)
 	RET
 
-TEXT runtime·abort(SB),NOSPLIT,$-8-0
+TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
 	MOVW	(R0), R0
 	UNDEF
 
@@ -952,25 +777,25 @@ TEXT runtime·memhash_varlen(SB),NOSPLIT,$40-24
 	MOVD	p+0(FP), R3
 	MOVD	h+8(FP), R4
 	MOVD	8(R11), R5
-	MOVD	R3, 8(R1)
-	MOVD	R4, 16(R1)
-	MOVD	R5, 24(R1)
+	MOVD	R3, FIXED_FRAME+0(R1)
+	MOVD	R4, FIXED_FRAME+8(R1)
+	MOVD	R5, FIXED_FRAME+16(R1)
 	BL	runtime·memhash(SB)
-	MOVD	32(R1), R3
+	MOVD	FIXED_FRAME+24(R1), R3
 	MOVD	R3, ret+16(FP)
 	RET
 
 // AES hashing not implemented for ppc64
-TEXT runtime·aeshash(SB),NOSPLIT,$-8-0
+TEXT runtime·aeshash(SB),NOSPLIT|NOFRAME,$0-0
 	MOVW	(R0), R1
-TEXT runtime·aeshash32(SB),NOSPLIT,$-8-0
+TEXT runtime·aeshash32(SB),NOSPLIT|NOFRAME,$0-0
 	MOVW	(R0), R1
-TEXT runtime·aeshash64(SB),NOSPLIT,$-8-0
+TEXT runtime·aeshash64(SB),NOSPLIT|NOFRAME,$0-0
 	MOVW	(R0), R1
-TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0
+TEXT runtime·aeshashstr(SB),NOSPLIT|NOFRAME,$0-0
 	MOVW	(R0), R1
 
-TEXT runtime·memeq(SB),NOSPLIT,$-8-25
+TEXT runtime·memeq(SB),NOSPLIT|NOFRAME,$0-25
 	MOVD	a+0(FP), R3
 	MOVD	b+8(FP), R4
 	MOVD	size+16(FP), R5
@@ -999,11 +824,11 @@ TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17
 	CMP	R3, R4
 	BEQ	eq
 	MOVD	8(R11), R5    // compiler stores size at offset 8 in the closure
-	MOVD	R3, 8(R1)
-	MOVD	R4, 16(R1)
-	MOVD	R5, 24(R1)
+	MOVD	R3, FIXED_FRAME+0(R1)
+	MOVD	R4, FIXED_FRAME+8(R1)
+	MOVD	R5, FIXED_FRAME+16(R1)
 	BL	runtime·memeq(SB)
-	MOVBZ	32(R1), R3
+	MOVBZ	FIXED_FRAME+24(R1), R3
 	MOVB	R3, ret+16(FP)
 	RET
 eq:
@@ -1118,6 +943,65 @@ notfound:
 	MOVD	R3, ret+24(FP)
 	RET
 
+TEXT runtime·cmpstring(SB),NOSPLIT|NOFRAME,$0-40
+	MOVD	s1_base+0(FP), R5
+	MOVD	s1_len+8(FP), R3
+	MOVD	s2_base+16(FP), R6
+	MOVD	s2_len+24(FP), R4
+	MOVD	$ret+32(FP), R7
+	BR	runtime·cmpbody<>(SB)
+
+TEXT bytes·Compare(SB),NOSPLIT|NOFRAME,$0-56
+	MOVD	s1+0(FP), R5
+	MOVD	s1+8(FP), R3
+	MOVD	s2+24(FP), R6
+	MOVD	s2+32(FP), R4
+	MOVD	$ret+48(FP), R7
+	BR	runtime·cmpbody<>(SB)
+
+// On entry:
+// R3 is the length of s1
+// R4 is the length of s2
+// R5 points to the start of s1
+// R6 points to the start of s2
+// R7 points to return value (-1/0/1 will be written here)
+//
+// On exit:
+// R5, R6, R8, R9 and R10 are clobbered
+TEXT runtime·cmpbody<>(SB),NOSPLIT|NOFRAME,$0-0
+	CMP	R5, R6
+	BEQ	samebytes // same starting pointers; compare lengths
+	SUB	$1, R5
+	SUB	$1, R6
+	MOVD	R4, R8
+	CMP	R3, R4
+	BGE	2(PC)
+	MOVD	R3, R8	// R8 is min(R3, R4)
+	ADD	R5, R8	// R5 is current byte in s1, R8 is last byte in s1 to compare
+loop:
+	CMP	R5, R8
+	BEQ	samebytes // all compared bytes were the same; compare lengths
+	MOVBZU	1(R5), R9
+	MOVBZU	1(R6), R10
+	CMP	R9, R10
+	BEQ	loop
+	// bytes differed
+	MOVD	$1, R4
+	BGT	2(PC)
+	NEG	R4
+	MOVD	R4, (R7)
+	RET
+samebytes:
+	MOVD	$1, R8
+	CMP	R3, R4
+	BNE	3(PC)
+	MOVD	R0, (R7)
+	RET
+	BGT	2(PC)
+	NEG	R8
+	MOVD	R8, (R7)
+	RET
+
 TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
 	MOVD	g_m(g), R4
 	MOVWZ	m_fastrand(R4), R3
@@ -1135,7 +1019,7 @@ TEXT runtime·return0(SB), NOSPLIT, $0
 
 // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
 // Must obey the gcc calling convention.
-TEXT _cgo_topofstack(SB),NOSPLIT,$-8
+TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
 	// g (R30) and R31 are callee-save in the C ABI, so save them
 	MOVD	g, R4
 	MOVD	R31, R5
@@ -1153,8 +1037,16 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$-8
 
 // The top-most function running on a goroutine
 // returns to goexit+PCQuantum.
-TEXT runtime·goexit(SB),NOSPLIT,$-8-0
-	MOVD	R0, R0	// NOP
+//
+// When dynamically linking Go, it can be returned to from a function
+// implemented in a different module and so needs to reload the TOC pointer
+// from the stack (although this function declares that it does not set up x-a
+// frame, newproc1 does in fact allocate one for goexit and saves the TOC
+// pointer in the correct place).
+// goexit+_PCQuantum is halfway through the usual global entry point prologue
+// that derives r2 from r12 which is a bit silly, but not harmful.
+TEXT runtime·goexit(SB),NOSPLIT|NOFRAME,$0-0
+	MOVD	24(R1), R2
 	BL	runtime·goexit1(SB)	// does not return
 	// traceback from goexit1 must hit code range of goexit
 	MOVD	R0, R0	// NOP
@@ -1170,3 +1062,30 @@ TEXT runtime·prefetcht2(SB),NOSPLIT,$0-8
 
 TEXT runtime·prefetchnta(SB),NOSPLIT,$0-8
 	RET
+
+TEXT runtime·sigreturn(SB),NOSPLIT,$0-8
+        RET
+
+// prepGoExitFrame saves the current TOC pointer (i.e. the TOC pointer for the
+// module containing runtime) to the frame that goexit will execute in when
+// the goroutine exits. It's implemented in assembly mainly because that's the
+// easiest way to get access to R2.
+TEXT runtime·prepGoExitFrame(SB),NOSPLIT,$0-8
+      MOVD    sp+0(FP), R3
+      MOVD    R2, 24(R3)
+      RET
+
+TEXT runtime·addmoduledata(SB),NOSPLIT|NOFRAME,$0-0
+	ADD	$-8, R1
+	MOVD	R31, 0(R1)
+	MOVD	runtime·lastmoduledatap(SB), R4
+	MOVD	R3, moduledata_next(R4)
+	MOVD	R3, runtime·lastmoduledatap(SB)
+	MOVD	0(R1), R31
+	ADD	$8, R1
+	RET
+
+TEXT ·checkASM(SB),NOSPLIT,$0-1
+	MOVW	$1, R3
+	MOVB	R3, ret+0(FP)
+	RET
diff --git a/src/runtime/atomic_386.go b/src/runtime/atomic_386.go
deleted file mode 100644
index f8d589e..0000000
--- a/src/runtime/atomic_386.go
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2009 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 runtime
-
-import "unsafe"
-
-// The calls to nop are to keep these functions from being inlined.
-// If they are inlined we have no guarantee that later rewrites of the
-// code by optimizers will preserve the relative order of memory accesses.
-
-//go:nosplit
-func atomicload(ptr *uint32) uint32 {
-	nop()
-	return *ptr
-}
-
-//go:nosplit
-func atomicloadp(ptr unsafe.Pointer) unsafe.Pointer {
-	nop()
-	return *(*unsafe.Pointer)(ptr)
-}
-
-//go:nosplit
-func xadd64(ptr *uint64, delta int64) uint64 {
-	for {
-		old := *ptr
-		if cas64(ptr, old, old+uint64(delta)) {
-			return old + uint64(delta)
-		}
-	}
-}
-
-//go:noescape
-//go:linkname xadduintptr runtime.xadd
-func xadduintptr(ptr *uintptr, delta uintptr) uintptr
-
-//go:nosplit
-func xchg64(ptr *uint64, new uint64) uint64 {
-	for {
-		old := *ptr
-		if cas64(ptr, old, new) {
-			return old
-		}
-	}
-}
-
-//go:noescape
-func xadd(ptr *uint32, delta int32) uint32
-
-//go:noescape
-func xchg(ptr *uint32, new uint32) uint32
-
-// NO go:noescape annotation; see atomic_pointer.go.
-func xchgp1(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer
-
-//go:noescape
-func xchguintptr(ptr *uintptr, new uintptr) uintptr
-
-//go:noescape
-func atomicload64(ptr *uint64) uint64
-
-//go:noescape
-func atomicand8(ptr *uint8, val uint8)
-
-//go:noescape
-func atomicor8(ptr *uint8, val uint8)
-
-// NOTE: Do not add atomicxor8 (XOR is not idempotent).
-
-//go:noescape
-func cas64(ptr *uint64, old, new uint64) bool
-
-//go:noescape
-func atomicstore(ptr *uint32, val uint32)
-
-//go:noescape
-func atomicstore64(ptr *uint64, val uint64)
-
-// NO go:noescape annotation; see atomic_pointer.go.
-func atomicstorep1(ptr unsafe.Pointer, val unsafe.Pointer)
diff --git a/src/runtime/atomic_amd64x.go b/src/runtime/atomic_amd64x.go
deleted file mode 100644
index edcc6d6..0000000
--- a/src/runtime/atomic_amd64x.go
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2009 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.
-
-// +build amd64 amd64p32
-
-package runtime
-
-import "unsafe"
-
-// The calls to nop are to keep these functions from being inlined.
-// If they are inlined we have no guarantee that later rewrites of the
-// code by optimizers will preserve the relative order of memory accesses.
-
-//go:nosplit
-func atomicload(ptr *uint32) uint32 {
-	nop()
-	return *ptr
-}
-
-//go:nosplit
-func atomicloadp(ptr unsafe.Pointer) unsafe.Pointer {
-	nop()
-	return *(*unsafe.Pointer)(ptr)
-}
-
-//go:nosplit
-func atomicload64(ptr *uint64) uint64 {
-	nop()
-	return *ptr
-}
-
-//go:noescape
-func xadd(ptr *uint32, delta int32) uint32
-
-//go:noescape
-func xadd64(ptr *uint64, delta int64) uint64
-
-//go:noescape
-func xadduintptr(ptr *uintptr, delta uintptr) uintptr
-
-//go:noescape
-func xchg(ptr *uint32, new uint32) uint32
-
-//go:noescape
-func xchg64(ptr *uint64, new uint64) uint64
-
-// NO go:noescape annotation; see atomic_pointer.go.
-func xchgp1(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer
-
-//go:noescape
-func xchguintptr(ptr *uintptr, new uintptr) uintptr
-
-//go:noescape
-func atomicand8(ptr *uint8, val uint8)
-
-//go:noescape
-func atomicor8(ptr *uint8, val uint8)
-
-// NOTE: Do not add atomicxor8 (XOR is not idempotent).
-
-//go:noescape
-func cas64(ptr *uint64, old, new uint64) bool
-
-//go:noescape
-func atomicstore(ptr *uint32, val uint32)
-
-//go:noescape
-func atomicstore64(ptr *uint64, val uint64)
-
-// NO go:noescape annotation; see atomic_pointer.go.
-func atomicstorep1(ptr unsafe.Pointer, val unsafe.Pointer)
diff --git a/src/runtime/atomic_arm.go b/src/runtime/atomic_arm.go
deleted file mode 100644
index 02a1f35..0000000
--- a/src/runtime/atomic_arm.go
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright 2009 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 runtime
-
-import "unsafe"
-
-var locktab [57]struct {
-	l   mutex
-	pad [_CacheLineSize - unsafe.Sizeof(mutex{})]byte
-}
-
-func addrLock(addr *uint64) *mutex {
-	return &locktab[(uintptr(unsafe.Pointer(addr))>>3)%uintptr(len(locktab))].l
-}
-
-// Atomic add and return new value.
-//go:nosplit
-func xadd(val *uint32, delta int32) uint32 {
-	for {
-		oval := *val
-		nval := oval + uint32(delta)
-		if cas(val, oval, nval) {
-			return nval
-		}
-	}
-}
-
-//go:noescape
-//go:linkname xadduintptr runtime.xadd
-func xadduintptr(ptr *uintptr, delta uintptr) uintptr
-
-//go:nosplit
-func xchg(addr *uint32, v uint32) uint32 {
-	for {
-		old := *addr
-		if cas(addr, old, v) {
-			return old
-		}
-	}
-}
-
-//go:nosplit
-func xchgp1(addr unsafe.Pointer, v unsafe.Pointer) unsafe.Pointer {
-	for {
-		old := *(*unsafe.Pointer)(addr)
-		if casp1((*unsafe.Pointer)(addr), old, v) {
-			return old
-		}
-	}
-}
-
-//go:nosplit
-func xchguintptr(addr *uintptr, v uintptr) uintptr {
-	return uintptr(xchg((*uint32)(unsafe.Pointer(addr)), uint32(v)))
-}
-
-//go:nosplit
-func atomicload(addr *uint32) uint32 {
-	return xadd(addr, 0)
-}
-
-//go:nosplit
-func atomicloadp(addr unsafe.Pointer) unsafe.Pointer {
-	return unsafe.Pointer(uintptr(xadd((*uint32)(addr), 0)))
-}
-
-//go:nosplit
-func atomicstorep1(addr unsafe.Pointer, v unsafe.Pointer) {
-	for {
-		old := *(*unsafe.Pointer)(addr)
-		if casp1((*unsafe.Pointer)(addr), old, v) {
-			return
-		}
-	}
-}
-
-//go:nosplit
-func atomicstore(addr *uint32, v uint32) {
-	for {
-		old := *addr
-		if cas(addr, old, v) {
-			return
-		}
-	}
-}
-
-//go:nosplit
-func cas64(addr *uint64, old, new uint64) bool {
-	var ok bool
-	systemstack(func() {
-		lock(addrLock(addr))
-		if *addr == old {
-			*addr = new
-			ok = true
-		}
-		unlock(addrLock(addr))
-	})
-	return ok
-}
-
-//go:nosplit
-func xadd64(addr *uint64, delta int64) uint64 {
-	var r uint64
-	systemstack(func() {
-		lock(addrLock(addr))
-		r = *addr + uint64(delta)
-		*addr = r
-		unlock(addrLock(addr))
-	})
-	return r
-}
-
-//go:nosplit
-func xchg64(addr *uint64, v uint64) uint64 {
-	var r uint64
-	systemstack(func() {
-		lock(addrLock(addr))
-		r = *addr
-		*addr = v
-		unlock(addrLock(addr))
-	})
-	return r
-}
-
-//go:nosplit
-func atomicload64(addr *uint64) uint64 {
-	var r uint64
-	systemstack(func() {
-		lock(addrLock(addr))
-		r = *addr
-		unlock(addrLock(addr))
-	})
-	return r
-}
-
-//go:nosplit
-func atomicstore64(addr *uint64, v uint64) {
-	systemstack(func() {
-		lock(addrLock(addr))
-		*addr = v
-		unlock(addrLock(addr))
-	})
-}
-
-//go:nosplit
-func atomicor8(addr *uint8, v uint8) {
-	// Align down to 4 bytes and use 32-bit CAS.
-	uaddr := uintptr(unsafe.Pointer(addr))
-	addr32 := (*uint32)(unsafe.Pointer(uaddr &^ 3))
-	word := uint32(v) << ((uaddr & 3) * 8) // little endian
-	for {
-		old := *addr32
-		if cas(addr32, old, old|word) {
-			return
-		}
-	}
-}
-
-//go:nosplit
-func atomicand8(addr *uint8, v uint8) {
-	// Align down to 4 bytes and use 32-bit CAS.
-	uaddr := uintptr(unsafe.Pointer(addr))
-	addr32 := (*uint32)(unsafe.Pointer(uaddr &^ 3))
-	word := uint32(v) << ((uaddr & 3) * 8)    // little endian
-	mask := uint32(0xFF) << ((uaddr & 3) * 8) // little endian
-	word |= ^mask
-	for {
-		old := *addr32
-		if cas(addr32, old, old&word) {
-			return
-		}
-	}
-}
diff --git a/src/runtime/atomic_arm64.go b/src/runtime/atomic_arm64.go
deleted file mode 100644
index a377e3e..0000000
--- a/src/runtime/atomic_arm64.go
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2015 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 runtime
-
-import "unsafe"
-
-//go:noescape
-func xadd(ptr *uint32, delta int32) uint32
-
-//go:noescape
-func xadd64(ptr *uint64, delta int64) uint64
-
-//go:noescape
-//go:linkname xadduintptr runtime.xadd64
-func xadduintptr(ptr *uintptr, delta uintptr) uintptr
-
-//go:noescape
-func xchg(ptr *uint32, new uint32) uint32
-
-//go:noescape
-func xchg64(ptr *uint64, new uint64) uint64
-
-// NO go:noescape annotation; see atomic_pointer.go.
-func xchgp1(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer
-
-//go:noescape
-func xchguintptr(ptr *uintptr, new uintptr) uintptr
-
-//go:noescape
-func atomicload(ptr *uint32) uint32
-
-//go:noescape
-func atomicload64(ptr *uint64) uint64
-
-//go:noescape
-func atomicloadp(ptr unsafe.Pointer) unsafe.Pointer
-
-//go:nosplit
-func atomicor8(addr *uint8, v uint8) {
-	// TODO(dfc) implement this in asm.
-	// Align down to 4 bytes and use 32-bit CAS.
-	uaddr := uintptr(unsafe.Pointer(addr))
-	addr32 := (*uint32)(unsafe.Pointer(uaddr &^ 3))
-	word := uint32(v) << ((uaddr & 3) * 8) // little endian
-	for {
-		old := *addr32
-		if cas(addr32, old, old|word) {
-			return
-		}
-	}
-}
-
-//go:nosplit
-func atomicand8(addr *uint8, v uint8) {
-	// TODO(dfc) implement this in asm.
-	// Align down to 4 bytes and use 32-bit CAS.
-	uaddr := uintptr(unsafe.Pointer(addr))
-	addr32 := (*uint32)(unsafe.Pointer(uaddr &^ 3))
-	word := uint32(v) << ((uaddr & 3) * 8)    // little endian
-	mask := uint32(0xFF) << ((uaddr & 3) * 8) // little endian
-	word |= ^mask
-	for {
-		old := *addr32
-		if cas(addr32, old, old&word) {
-			return
-		}
-	}
-}
-
-//go:noescape
-func cas64(ptr *uint64, old, new uint64) bool
-
-//go:noescape
-func atomicstore(ptr *uint32, val uint32)
-
-//go:noescape
-func atomicstore64(ptr *uint64, val uint64)
-
-// NO go:noescape annotation; see atomic_pointer.go.
-func atomicstorep1(ptr unsafe.Pointer, val unsafe.Pointer)
diff --git a/src/runtime/atomic_arm64.s b/src/runtime/atomic_arm64.s
index d3ab2a1..4704aa6 100644
--- a/src/runtime/atomic_arm64.s
+++ b/src/runtime/atomic_arm64.s
@@ -4,114 +4,6 @@
 
 #include "textflag.h"
 
-// uint32 runtime·atomicload(uint32 volatile* addr)
-TEXT ·atomicload(SB),NOSPLIT,$-8-12
-	MOVD	ptr+0(FP), R0
-	LDARW	(R0), R0
-	MOVW	R0, ret+8(FP)
-	RET
-
-// uint64 runtime·atomicload64(uint64 volatile* addr)
-TEXT ·atomicload64(SB),NOSPLIT,$-8-16
-	MOVD	ptr+0(FP), R0
-	LDAR	(R0), R0
-	MOVD	R0, ret+8(FP)
-	RET
-
-// void *runtime·atomicloadp(void *volatile *addr)
-TEXT ·atomicloadp(SB),NOSPLIT,$-8-16
-	MOVD	ptr+0(FP), R0
-	LDAR	(R0), R0
-	MOVD	R0, ret+8(FP)
-	RET
-
-TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-16
-	B	runtime·atomicstore64(SB)
-
-TEXT runtime·atomicstore(SB), NOSPLIT, $0-12
-	MOVD	ptr+0(FP), R0
-	MOVW	val+8(FP), R1
-	STLRW	R1, (R0)
-	RET
-
-TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
-	MOVD	ptr+0(FP), R0
-	MOVD	val+8(FP), R1
-	STLR	R1, (R0)
-	RET
-
-TEXT runtime·xchg(SB), NOSPLIT, $0-20
-again:
-	MOVD	ptr+0(FP), R0
-	MOVW	new+8(FP), R1
-	LDAXRW	(R0), R2
-	STLXRW	R1, (R0), R3
-	CBNZ	R3, again
-	MOVW	R2, ret+16(FP)
-	RET
-
-TEXT runtime·xchg64(SB), NOSPLIT, $0-24
-again:
-	MOVD	ptr+0(FP), R0
-	MOVD	new+8(FP), R1
-	LDAXR	(R0), R2
-	STLXR	R1, (R0), R3
-	CBNZ	R3, again
-	MOVD	R2, ret+16(FP)
-	RET
-
-// bool runtime·cas64(uint64 *ptr, uint64 old, uint64 new)
-// Atomically:
-//      if(*val == *old){
-//              *val = new;
-//              return 1;
-//      } else {
-//              return 0;
-//      }
-TEXT runtime·cas64(SB), NOSPLIT, $0-25
-	MOVD	ptr+0(FP), R0
-	MOVD	old+8(FP), R1
-	MOVD	new+16(FP), R2
-again:
-	LDAXR	(R0), R3
-	CMP	R1, R3
-	BNE	ok
-	STLXR	R2, (R0), R3
-	CBNZ	R3, again
-ok:
-	CSET	EQ, R0
-	MOVB	R0, ret+24(FP)
-	RET
-
-// uint32 xadd(uint32 volatile *ptr, int32 delta)
-// Atomically:
-//      *val += delta;
-//      return *val;
-TEXT runtime·xadd(SB), NOSPLIT, $0-20
-again:
-	MOVD	ptr+0(FP), R0
-	MOVW	delta+8(FP), R1
-	LDAXRW	(R0), R2
-	ADDW	R2, R1, R2
-	STLXRW	R2, (R0), R3
-	CBNZ	R3, again
-	MOVW	R2, ret+16(FP)
-	RET
-
-TEXT runtime·xadd64(SB), NOSPLIT, $0-24
-again:
-	MOVD	ptr+0(FP), R0
-	MOVD	delta+8(FP), R1
-	LDAXR	(R0), R2
-	ADD	R2, R1, R2
-	STLXR	R2, (R0), R3
-	CBNZ	R3, again
-	MOVD	R2, ret+16(FP)
-	RET
-
-TEXT runtime·xchguintptr(SB), NOSPLIT, $0-24
-	B	runtime·xchg64(SB)
-
 TEXT ·publicationBarrier(SB),NOSPLIT,$-8-0
 	DMB	$0xe	// DMB ST
 	RET
diff --git a/src/runtime/atomic_mips64x.s b/src/runtime/atomic_mips64x.s
new file mode 100644
index 0000000..0f849ca
--- /dev/null
+++ b/src/runtime/atomic_mips64x.s
@@ -0,0 +1,13 @@
+// Copyright 2015 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.
+
+// +build mips64 mips64le
+
+#include "textflag.h"
+
+#define SYNC	WORD $0xf
+
+TEXT ·publicationBarrier(SB),NOSPLIT,$-8-0
+	SYNC
+	RET
diff --git a/src/runtime/atomic_pointer.go b/src/runtime/atomic_pointer.go
index f84afe0..bd21b49 100644
--- a/src/runtime/atomic_pointer.go
+++ b/src/runtime/atomic_pointer.go
@@ -4,13 +4,16 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"unsafe"
+)
 
 // These functions cannot have go:noescape annotations,
 // because while ptr does not escape, new does.
 // If new is marked as not escaping, the compiler will make incorrect
 // escape analysis decisions about the pointer value being stored.
-// Instead, these are wrappers around the actual atomics (xchgp1 and so on)
+// Instead, these are wrappers around the actual atomics (casp1 and so on)
 // that use noescape to convey which arguments do not escape.
 //
 // Additionally, these functions must update the shadow heap for
@@ -18,20 +21,13 @@ import "unsafe"
 
 //go:nosplit
 func atomicstorep(ptr unsafe.Pointer, new unsafe.Pointer) {
-	atomicstorep1(noescape(ptr), new)
+	atomic.Storep1(noescape(ptr), new)
 	writebarrierptr_nostore((*uintptr)(ptr), uintptr(new))
 }
 
 //go:nosplit
-func xchgp(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer {
-	old := xchgp1(noescape(ptr), new)
-	writebarrierptr_nostore((*uintptr)(ptr), uintptr(new))
-	return old
-}
-
-//go:nosplit
 func casp(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool {
-	if !casp1((*unsafe.Pointer)(noescape(unsafe.Pointer(ptr))), noescape(old), new) {
+	if !atomic.Casp1((*unsafe.Pointer)(noescape(unsafe.Pointer(ptr))), noescape(old), new) {
 		return false
 	}
 	writebarrierptr_nostore((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
@@ -49,7 +45,7 @@ func sync_atomic_StoreUintptr(ptr *uintptr, new uintptr)
 //go:nosplit
 func sync_atomic_StorePointer(ptr *unsafe.Pointer, new unsafe.Pointer) {
 	sync_atomic_StoreUintptr((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
-	atomicstorep1(noescape(unsafe.Pointer(ptr)), new)
+	atomic.Storep1(noescape(unsafe.Pointer(ptr)), new)
 	writebarrierptr_nostore((*uintptr)(unsafe.Pointer(ptr)), uintptr(new))
 }
 
diff --git a/src/runtime/atomic_ppc64x.go b/src/runtime/atomic_ppc64x.go
deleted file mode 100644
index b58ee5a..0000000
--- a/src/runtime/atomic_ppc64x.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// 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.
-
-// +build ppc64 ppc64le
-
-package runtime
-
-import "unsafe"
-
-//go:noescape
-func xadd(ptr *uint32, delta int32) uint32
-
-//go:noescape
-func xadd64(ptr *uint64, delta int64) uint64
-
-//go:noescape
-//go:linkname xadduintptr runtime.xadd64
-func xadduintptr(ptr *uintptr, delta uintptr) uintptr
-
-//go:noescape
-func xchg(ptr *uint32, new uint32) uint32
-
-//go:noescape
-func xchg64(ptr *uint64, new uint64) uint64
-
-// NO go:noescape annotation; see atomic_pointer.go.
-func xchgp1(ptr unsafe.Pointer, new unsafe.Pointer) unsafe.Pointer
-
-//go:noescape
-func xchguintptr(ptr *uintptr, new uintptr) uintptr
-
-//go:noescape
-func atomicload(ptr *uint32) uint32
-
-//go:noescape
-func atomicload64(ptr *uint64) uint64
-
-//go:noescape
-func atomicloadp(ptr unsafe.Pointer) unsafe.Pointer
-
-//go:noescape
-func atomicand8(ptr *uint8, val uint8)
-
-//go:noescape
-func atomicor8(ptr *uint8, val uint8)
-
-// NOTE: Do not add atomicxor8 (XOR is not idempotent).
-
-//go:noescape
-func cas64(ptr *uint64, old, new uint64) bool
-
-//go:noescape
-func atomicstore(ptr *uint32, val uint32)
-
-//go:noescape
-func atomicstore64(ptr *uint64, val uint64)
-
-// NO go:noescape annotation; see atomic_pointer.go.
-func atomicstorep1(ptr unsafe.Pointer, val unsafe.Pointer)
diff --git a/src/runtime/atomic_ppc64x.s b/src/runtime/atomic_ppc64x.s
index 28c5bf3..7cdb746 100644
--- a/src/runtime/atomic_ppc64x.s
+++ b/src/runtime/atomic_ppc64x.s
@@ -6,40 +6,7 @@
 
 #include "textflag.h"
 
-// uint32 runtime·atomicload(uint32 volatile* addr)
-TEXT ·atomicload(SB),NOSPLIT,$-8-12
-	MOVD	addr+0(FP), R3
-	SYNC
-	MOVWZ	0(R3), R3
-	CMPW	R3, R3, CR7
-	BC	4, 30, 1(PC) // bne- cr7,0x4
-	ISYNC
-	MOVW	R3, ret+8(FP)
-	RET
-
-// uint64 runtime·atomicload64(uint64 volatile* addr)
-TEXT ·atomicload64(SB),NOSPLIT,$-8-16
-	MOVD	addr+0(FP), R3
-	SYNC
-	MOVD	0(R3), R3
-	CMP	R3, R3, CR7
-	BC	4, 30, 1(PC) // bne- cr7,0x4
-	ISYNC
-	MOVD	R3, ret+8(FP)
-	RET
-
-// void *runtime·atomicloadp(void *volatile *addr)
-TEXT ·atomicloadp(SB),NOSPLIT,$-8-16
-	MOVD	addr+0(FP), R3
-	SYNC
-	MOVD	0(R3), R3
-	CMP	R3, R3, CR7
-	BC	4, 30, 1(PC) // bne- cr7,0x4
-	ISYNC
-	MOVD	R3, ret+8(FP)
-	RET
-
-TEXT ·publicationBarrier(SB),NOSPLIT,$-8-0
+TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
 	// LWSYNC is the "export" barrier recommended by Power ISA
 	// v2.07 book II, appendix B.2.2.2.
 	// LWSYNC is a load/load, load/store, and store/store barrier.
diff --git a/src/runtime/atomic_test.go b/src/runtime/atomic_test.go
deleted file mode 100644
index 2699103..0000000
--- a/src/runtime/atomic_test.go
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2015 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 runtime_test
-
-import (
-	"runtime"
-	"testing"
-	"unsafe"
-)
-
-func runParallel(N, iter int, f func()) {
-	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(int(N)))
-	done := make(chan bool)
-	for i := 0; i < N; i++ {
-		go func() {
-			for j := 0; j < iter; j++ {
-				f()
-			}
-			done <- true
-		}()
-	}
-	for i := 0; i < N; i++ {
-		<-done
-	}
-}
-
-func TestXadduintptr(t *testing.T) {
-	const N = 20
-	const iter = 100000
-	inc := uintptr(100)
-	total := uintptr(0)
-	runParallel(N, iter, func() {
-		runtime.Xadduintptr(&total, inc)
-	})
-	if want := uintptr(N * iter * inc); want != total {
-		t.Fatalf("xadduintpr error, want %d, got %d", want, total)
-	}
-	total = 0
-	runParallel(N, iter, func() {
-		runtime.Xadduintptr(&total, inc)
-		runtime.Xadduintptr(&total, uintptr(-int64(inc)))
-	})
-	if total != 0 {
-		t.Fatalf("xadduintpr total error, want %d, got %d", 0, total)
-	}
-}
-
-// Tests that xadduintptr correctly updates 64-bit values.  The place where
-// we actually do so is mstats.go, functions mSysStat{Inc,Dec}.
-func TestXadduintptrOnUint64(t *testing.T) {
-	if runtime.BigEndian != 0 {
-		// On big endian architectures, we never use xadduintptr to update
-		// 64-bit values and hence we skip the test.  (Note that functions
-		// mSysStat{Inc,Dec} in mstats.go have explicit checks for
-		// big-endianness.)
-		return
-	}
-	const inc = 100
-	val := uint64(0)
-	runtime.Xadduintptr((*uintptr)(unsafe.Pointer(&val)), inc)
-	if inc != val {
-		t.Fatalf("xadduintptr should increase lower-order bits, want %d, got %d", inc, val)
-	}
-}
diff --git a/src/runtime/cgo/asm_ppc64x.s b/src/runtime/cgo/asm_ppc64x.s
index 0c08a1d..5cdbe06 100644
--- a/src/runtime/cgo/asm_ppc64x.s
+++ b/src/runtime/cgo/asm_ppc64x.s
@@ -5,13 +5,14 @@
 // +build ppc64 ppc64le
 
 #include "textflag.h"
+#include "asm_ppc64x.h"
 
 /*
  * void crosscall2(void (*fn)(void*, int32), void*, int32)
  * Save registers and call fn with two arguments.
  * crosscall2 obeys the C ABI; fn obeys the Go ABI.
  */
-TEXT crosscall2(SB),NOSPLIT,$-8
+TEXT crosscall2(SB),NOSPLIT|NOFRAME,$0
 	// TODO(austin): ABI v1 (fn is probably a function descriptor)
 
 	// Start with standard C stack frame layout and linkage
@@ -21,18 +22,19 @@ TEXT crosscall2(SB),NOSPLIT,$-8
 
 	BL	saveregs2<>(SB)
 
-	MOVDU	R1, (-288-3*8)(R1)
+	MOVDU	R1, (-288-2*8-FIXED_FRAME)(R1)
 
 	// Initialize Go ABI environment
 	BL	runtime·reginit(SB)
 	BL	runtime·load_g(SB)
 
+	MOVD	R3, R12
 	MOVD	R3, CTR
-	MOVD	R4, 8(R1)
-	MOVD	R5, 16(R1)
+	MOVD	R4, FIXED_FRAME+0(R1)
+	MOVD	R5, FIXED_FRAME+8(R1)
 	BL	(CTR)
 
-	ADD	$(288+3*8), R1
+	ADD	$(288+2*8+FIXED_FRAME), R1
 
 	BL	restoreregs2<>(SB)
 
@@ -41,7 +43,7 @@ TEXT crosscall2(SB),NOSPLIT,$-8
 	MOVD	R0, LR
 	RET
 
-TEXT saveregs2<>(SB),NOSPLIT,$-8
+TEXT saveregs2<>(SB),NOSPLIT|NOFRAME,$0
 	// O=-288; for R in R{14..31}; do echo "\tMOVD\t$R, $O(R1)"|sed s/R30/g/; ((O+=8)); done; for F in F{14..31}; do echo "\tFMOVD\t$F, $O(R1)"; ((O+=8)); done
 	MOVD	R14, -288(R1)
 	MOVD	R15, -280(R1)
@@ -82,7 +84,7 @@ TEXT saveregs2<>(SB),NOSPLIT,$-8
 
 	RET
 
-TEXT restoreregs2<>(SB),NOSPLIT,$-8
+TEXT restoreregs2<>(SB),NOSPLIT|NOFRAME,$0
 	// O=-288; for R in R{14..31}; do echo "\tMOVD\t$O(R1), $R"|sed s/R30/g/; ((O+=8)); done; for F in F{14..31}; do echo "\tFMOVD\t$O(R1), $F"; ((O+=8)); done
 	MOVD	-288(R1), R14
 	MOVD	-280(R1), R15
diff --git a/src/runtime/cgo/gcc_386.S b/src/runtime/cgo/gcc_386.S
index bf41427..ff11ce1 100644
--- a/src/runtime/cgo/gcc_386.S
+++ b/src/runtime/cgo/gcc_386.S
@@ -35,11 +35,6 @@ EXT(crosscall_386):
 	popl %ebp
 	ret
 
-.globl EXT(__stack_chk_fail_local)
-EXT(__stack_chk_fail_local):
-1:
-	jmp 1b
-
 #ifdef __ELF__
 .section .note.GNU-stack,"", at progbits
 #endif
diff --git a/src/runtime/cgo/gcc_android.c b/src/runtime/cgo/gcc_android.c
index be27725..a3bc6c4 100644
--- a/src/runtime/cgo/gcc_android.c
+++ b/src/runtime/cgo/gcc_android.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <stdarg.h>
 #include <android/log.h>
 #include "libcgo.h"
diff --git a/src/runtime/cgo/gcc_android_386.c b/src/runtime/cgo/gcc_android_386.c
new file mode 100644
index 0000000..db1d48a
--- /dev/null
+++ b/src/runtime/cgo/gcc_android_386.c
@@ -0,0 +1,89 @@
+// Copyright 2015 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.
+
+// +build cgo
+
+#include <string.h> /* for strerror */
+#include <pthread.h>
+#include <signal.h>
+#include "libcgo.h"
+
+static void* threadentry(void*);
+static pthread_key_t k1;
+
+#define magic1 (0x23581321U)
+
+static void
+inittls(void)
+{
+	uint32 x;
+	pthread_key_t tofree[128], k;
+	int i, ntofree;
+
+	/*
+	 * Same logic, code as gcc_android_amd64.c:/inittls.
+	 * Note that this is a temporary hack that should be fixed soon.
+	 *
+	 * TODO: fix this.
+	 *
+	 * The linker and runtime hard-code this constant offset
+	 * from %gs where we expect to find g. Disgusting.
+	 *
+	 * Known to src/cmd/link/internal/ld/sym.go:/0xf8
+	 * and to src/runtime/sys_linux_386.s:/0xf8 or /GOOS_android.
+	 * TODO(hyangah): check 0xb0 works with API23+
+	 *
+	 * As disgusting as on the darwin/386, darwin/amd64.
+	 */
+	ntofree = 0;
+	for(;;) {
+		if(pthread_key_create(&k, nil) < 0) {
+			fprintf(stderr, "runtime/cgo: pthread_key_create failed\n");
+			abort();
+		}
+		pthread_setspecific(k, (void*)magic1);
+		asm volatile("movl %%gs:0xf8, %0" : "=r"(x));
+		pthread_setspecific(k, 0);
+		if (x == magic1) {
+			k1 = k;
+			break;
+		}
+		if(ntofree >= nelem(tofree)) {
+			fprintf(stderr, "runtime/cgo: could not obtain pthread_keys\n");
+			fprintf(stderr, "\ttried");
+			for(i=0; i<ntofree; i++)
+				fprintf(stderr, " %#x", (unsigned)tofree[i]);
+			fprintf(stderr, "\n");
+			abort();
+		}
+		tofree[ntofree++] = k;
+	}
+	// TODO: output to stderr is not useful for apps.
+	// Can we fall back to Android's log library?
+
+	/*
+	 * We got the key we wanted.  Free the others.
+	 */
+	for(i=0; i<ntofree; i++) {
+		pthread_key_delete(tofree[i]);
+	}
+}
+
+
+static void*
+threadentry(void *v)
+{
+	ThreadStart ts;
+
+	ts = *(ThreadStart*)v;
+	free(v);
+
+	pthread_setspecific(k1, (void*)ts.g);
+
+	crosscall_386(ts.fn);
+	return nil;
+}
+
+void (*x_cgo_inittls)(void) = inittls;
+void* (*x_cgo_threadentry)(void*) = threadentry;
diff --git a/src/runtime/cgo/gcc_android_amd64.c b/src/runtime/cgo/gcc_android_amd64.c
new file mode 100644
index 0000000..17d88ce
--- /dev/null
+++ b/src/runtime/cgo/gcc_android_amd64.c
@@ -0,0 +1,94 @@
+// Copyright 2015 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.
+
+// +build cgo
+
+#include <string.h> /* for strerror */
+#include <pthread.h>
+#include <signal.h>
+#include "libcgo.h"
+
+static void* threadentry(void*);
+static pthread_key_t k1;
+
+#define magic1 (0x23581321345589ULL)
+
+static void
+inittls(void)
+{
+	uint64 x;
+	pthread_key_t tofree[128], k;
+	int i, ntofree;
+
+	/*
+	 * Same logic, code as gcc_darwin_386.c:/inittls.
+	 * Note that this is a temporary hack that should be fixed soon.
+	 * Android-L and M bionic's pthread implementation differ
+	 * significantly, and can change any time.
+	 * https://android-review.googlesource.com/#/c/134202
+	 *
+	 * We chose %fs:0x1d0 which seems to work in testing with Android
+	 * emulators (API22, API23) but it may break any time.
+	 *
+	 * TODO: fix this.
+	 *
+	 * The linker and runtime hard-code this constant offset
+	 * from %fs where we expect to find g. Disgusting.
+	 *
+	 * Known to src/cmd/link/internal/ld/sym.go:/0x1d0
+	 * and to src/runtime/sys_linux_amd64.s:/0x1d0 or /GOOS_android.
+	 *
+	 * As disgusting as on the darwin/386, darwin/amd64.
+	 */
+	ntofree = 0;
+	for(;;) {
+		if(pthread_key_create(&k, nil) < 0) {
+			fprintf(stderr, "runtime/cgo: pthread_key_create failed\n");
+			abort();
+		}
+		pthread_setspecific(k, (void*)magic1);
+		asm volatile("movq %%fs:0x1d0, %0" : "=r"(x));
+		pthread_setspecific(k, 0);
+		if(x == magic1) {
+			k1 = k;
+			break;
+		}
+		if(ntofree >= nelem(tofree)) {
+			fprintf(stderr, "runtime/cgo: could not obtain pthread_keys\n");
+			fprintf(stderr, "\ttried");
+			for(i=0; i<ntofree; i++)
+				fprintf(stderr, " %#x", (unsigned)tofree[i]);
+			fprintf(stderr, "\n");
+			abort();
+		}
+		tofree[ntofree++] = k;
+	}
+	// TODO: output to stderr is not useful for apps.
+	// Can we fall back to Android's log library?
+
+	/*
+	 * We got the key we wanted.  Free the others.
+	 */
+	for(i=0; i<ntofree; i++) {
+		pthread_key_delete(tofree[i]);
+	}
+}
+
+
+static void*
+threadentry(void *v)
+{
+	ThreadStart ts;
+
+	ts = *(ThreadStart*)v;
+	free(v);
+
+	pthread_setspecific(k1, (void*)ts.g);
+
+	crosscall_amd64(ts.fn);
+	return nil;
+}
+
+void (*x_cgo_inittls)(void) = inittls;
+void* (*x_cgo_threadentry)(void*) = threadentry;
diff --git a/src/runtime/cgo/gcc_android_arm.c b/src/runtime/cgo/gcc_android_arm.c
index 85cd244..67cb5a8 100644
--- a/src/runtime/cgo/gcc_android_arm.c
+++ b/src/runtime/cgo/gcc_android_arm.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <pthread.h>
 #include <signal.h>
 #include <stdio.h>
diff --git a/src/runtime/cgo/gcc_android_arm64.c b/src/runtime/cgo/gcc_android_arm64.c
new file mode 100644
index 0000000..acf3735
--- /dev/null
+++ b/src/runtime/cgo/gcc_android_arm64.c
@@ -0,0 +1,40 @@
+// Copyright 2015 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.
+
+// +build cgo
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <sys/limits.h>
+#include "libcgo.h"
+
+#define magic1 (0x23581321345589ULL)
+
+// inittls allocates a thread-local storage slot for g.
+//
+// It finds the first available slot using pthread_key_create and uses
+// it as the offset value for runtime.tlsg.
+static void
+inittls(void **tlsg, void **tlsbase)
+{
+	pthread_key_t k;
+	int i, err;
+
+	err = pthread_key_create(&k, nil);
+	if(err != 0) {
+		fatalf("pthread_key_create failed: %d", err);
+	}
+	pthread_setspecific(k, (void*)magic1);
+	for (i=0; i<PTHREAD_KEYS_MAX; i++) {
+		if (*(tlsbase+i) == (void*)magic1) {
+			*tlsg = (void*)(i*sizeof(void *));
+			pthread_setspecific(k, 0);
+			return;
+		}
+	}
+	fatalf("could not find pthread key");
+}
+
+void (*x_cgo_inittls)(void **tlsg, void **tlsbase) = inittls;
diff --git a/src/runtime/cgo/gcc_arm.S b/src/runtime/cgo/gcc_arm.S
index 980ab57..d225298 100644
--- a/src/runtime/cgo/gcc_arm.S
+++ b/src/runtime/cgo/gcc_arm.S
@@ -36,10 +36,6 @@ EXT(crosscall_arm1):
 
 	pop {r4, r5, r6, r7, r8, r9, r10, r11, ip, pc}
 
-.globl EXT(__stack_chk_fail_local)
-EXT(__stack_chk_fail_local):
-1:
-	b 1b
 
 #ifdef __ELF__
 .section .note.GNU-stack,"",%progbits
diff --git a/src/runtime/cgo/gcc_arm64.S b/src/runtime/cgo/gcc_arm64.S
index b7379d1..d9da272 100644
--- a/src/runtime/cgo/gcc_arm64.S
+++ b/src/runtime/cgo/gcc_arm64.S
@@ -47,10 +47,6 @@ EXT(crosscall1):
 	ldp x19, x20, [sp], #16
 	ret
 
-.globl EXT(__stack_chk_fail_local)
-EXT(__stack_chk_fail_local):
-1:
-	b 1b
 
 #ifdef __ELF__
 .section .note.GNU-stack,"",%progbits
diff --git a/src/runtime/cgo/gcc_darwin_386.c b/src/runtime/cgo/gcc_darwin_386.c
index 6668ba4..a94e5ee 100644
--- a/src/runtime/cgo/gcc_darwin_386.c
+++ b/src/runtime/cgo/gcc_darwin_386.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <string.h> /* for strerror */
 #include <pthread.h>
 #include <signal.h>
diff --git a/src/runtime/cgo/gcc_darwin_amd64.c b/src/runtime/cgo/gcc_darwin_amd64.c
index dc679ac..b70c833 100644
--- a/src/runtime/cgo/gcc_darwin_amd64.c
+++ b/src/runtime/cgo/gcc_darwin_amd64.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <string.h> /* for strerror */
 #include <pthread.h>
 #include <signal.h>
diff --git a/src/runtime/cgo/gcc_darwin_arm.c b/src/runtime/cgo/gcc_darwin_arm.c
index c303b91..c0ce449 100644
--- a/src/runtime/cgo/gcc_darwin_arm.c
+++ b/src/runtime/cgo/gcc_darwin_arm.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <limits.h>
 #include <pthread.h>
 #include <signal.h>
diff --git a/src/runtime/cgo/gcc_darwin_arm64.c b/src/runtime/cgo/gcc_darwin_arm64.c
index b64a063..1ba00b0 100644
--- a/src/runtime/cgo/gcc_darwin_arm64.c
+++ b/src/runtime/cgo/gcc_darwin_arm64.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <limits.h>
 #include <pthread.h>
 #include <signal.h>
diff --git a/src/runtime/cgo/gcc_dragonfly_amd64.c b/src/runtime/cgo/gcc_dragonfly_amd64.c
index f79f652..9d02add 100644
--- a/src/runtime/cgo/gcc_dragonfly_amd64.c
+++ b/src/runtime/cgo/gcc_dragonfly_amd64.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <sys/types.h>
 #include <sys/signalvar.h>
 #include <pthread.h>
@@ -56,6 +58,7 @@ static void*
 threadentry(void *v)
 {
 	ThreadStart ts;
+	stack_t ss;
 
 	ts = *(ThreadStart*)v;
 	free(v);
@@ -65,6 +68,17 @@ threadentry(void *v)
 	 */
 	setg_gcc((void*)ts.g);
 
+	// On DragonFly, a new thread inherits the signal stack of the
+	// creating thread.  That confuses minit, so we remove that
+	// signal stack here before calling the regular mstart.  It's
+	// a bit baroque to remove a signal stack here only to add one
+	// in minit, but it's a simple change that keeps DragonFly
+	// working like other OS's.  At this point all signals are
+	// blocked, so there is no race.
+	memset(&ss, 0, sizeof ss);
+	ss.ss_flags = SS_DISABLE;
+	sigaltstack(&ss, nil);
+
 	crosscall_amd64(ts.fn);
 	return nil;
 }
diff --git a/src/runtime/cgo/gcc_fatalf.c b/src/runtime/cgo/gcc_fatalf.c
index 21c1acf..c931b79 100644
--- a/src/runtime/cgo/gcc_fatalf.c
+++ b/src/runtime/cgo/gcc_fatalf.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 // +build !android,linux
 
 #include <stdarg.h>
diff --git a/src/runtime/cgo/gcc_freebsd_386.c b/src/runtime/cgo/gcc_freebsd_386.c
index 074418f..2afdf20 100644
--- a/src/runtime/cgo/gcc_freebsd_386.c
+++ b/src/runtime/cgo/gcc_freebsd_386.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <sys/types.h>
 #include <sys/signalvar.h>
 #include <pthread.h>
diff --git a/src/runtime/cgo/gcc_freebsd_amd64.c b/src/runtime/cgo/gcc_freebsd_amd64.c
index f79f652..bf71d4c 100644
--- a/src/runtime/cgo/gcc_freebsd_amd64.c
+++ b/src/runtime/cgo/gcc_freebsd_amd64.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <sys/types.h>
 #include <sys/signalvar.h>
 #include <pthread.h>
diff --git a/src/runtime/cgo/gcc_freebsd_arm.c b/src/runtime/cgo/gcc_freebsd_arm.c
index 2a86a91..60bca55 100644
--- a/src/runtime/cgo/gcc_freebsd_arm.c
+++ b/src/runtime/cgo/gcc_freebsd_arm.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <sys/types.h>
 #include <machine/sysarch.h>
 #include <sys/signalvar.h>
diff --git a/src/runtime/cgo/gcc_libinit.c b/src/runtime/cgo/gcc_libinit.c
index c3e94f5..5b9558a 100644
--- a/src/runtime/cgo/gcc_libinit.c
+++ b/src/runtime/cgo/gcc_libinit.c
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
 // +build darwin dragonfly freebsd linux netbsd solaris
 // +build !ppc64,!ppc64le
 
diff --git a/src/runtime/cgo/gcc_libinit_linux_ppc64x.c b/src/runtime/cgo/gcc_libinit_linux_ppc64x.c
index 82413a5..18ccf93 100644
--- a/src/runtime/cgo/gcc_libinit_linux_ppc64x.c
+++ b/src/runtime/cgo/gcc_libinit_linux_ppc64x.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 // TODO: see issue #10410
 // +build linux
 // +build ppc64 ppc64le
diff --git a/src/runtime/cgo/gcc_libinit_openbsd.c b/src/runtime/cgo/gcc_libinit_openbsd.c
index 7e5b646..13904ee 100644
--- a/src/runtime/cgo/gcc_libinit_openbsd.c
+++ b/src/runtime/cgo/gcc_libinit_openbsd.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <stdio.h>
 #include <stdlib.h>
 
diff --git a/src/runtime/cgo/gcc_libinit_windows.c b/src/runtime/cgo/gcc_libinit_windows.c
index 7e5b646..13904ee 100644
--- a/src/runtime/cgo/gcc_libinit_windows.c
+++ b/src/runtime/cgo/gcc_libinit_windows.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <stdio.h>
 #include <stdlib.h>
 
diff --git a/src/runtime/cgo/gcc_linux_386.c b/src/runtime/cgo/gcc_linux_386.c
index 9801c87..2457eb3 100644
--- a/src/runtime/cgo/gcc_linux_386.c
+++ b/src/runtime/cgo/gcc_linux_386.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <pthread.h>
 #include <string.h>
 #include <signal.h>
@@ -10,6 +12,10 @@
 static void *threadentry(void*);
 static void (*setg_gcc)(void*);
 
+// These will be set in gcc_android_386.c for android-specific customization.
+void (*x_cgo_inittls)(void);
+void* (*x_cgo_threadentry)(void*);
+
 void
 x_cgo_init(G *g, void (*setg)(void*))
 {
@@ -21,6 +27,10 @@ x_cgo_init(G *g, void (*setg)(void*))
 	pthread_attr_getstacksize(&attr, &size);
 	g->stacklo = (uintptr)&attr - size + 4096;
 	pthread_attr_destroy(&attr);
+
+	if (x_cgo_inittls) {
+		x_cgo_inittls();
+	}
 }
 
 
@@ -57,6 +67,10 @@ _cgo_sys_thread_start(ThreadStart *ts)
 static void*
 threadentry(void *v)
 {
+	if (x_cgo_threadentry) {
+		return x_cgo_threadentry(v);
+	}
+
 	ThreadStart ts;
 
 	ts = *(ThreadStart*)v;
diff --git a/src/runtime/cgo/gcc_linux_amd64.c b/src/runtime/cgo/gcc_linux_amd64.c
index 275d5dd..5113a76 100644
--- a/src/runtime/cgo/gcc_linux_amd64.c
+++ b/src/runtime/cgo/gcc_linux_amd64.c
@@ -2,25 +2,57 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <pthread.h>
+#include <errno.h>
 #include <string.h> // strerror
 #include <signal.h>
+#include <stdlib.h>
 #include "libcgo.h"
 
 static void* threadentry(void*);
 static void (*setg_gcc)(void*);
 
+// These will be set in gcc_android_amd64.c for android-specific customization.
+void (*x_cgo_inittls)(void);
+void* (*x_cgo_threadentry)(void*);
+
 void
 x_cgo_init(G* g, void (*setg)(void*))
 {
-	pthread_attr_t attr;
+	pthread_attr_t *attr;
 	size_t size;
 
+	/* The memory sanitizer distributed with versions of clang
+	   before 3.8 has a bug: if you call mmap before malloc, mmap
+	   may return an address that is later overwritten by the msan
+	   library.  Avoid this problem by forcing a call to malloc
+	   here, before we ever call malloc.
+
+	   This is only required for the memory sanitizer, so it's
+	   unfortunate that we always run it.  It should be possible
+	   to remove this when we no longer care about versions of
+	   clang before 3.8.  The test for this is
+	   misc/cgo/testsanitizers.
+
+	   GCC works hard to eliminate a seemingly unnecessary call to
+	   malloc, so we actually use the memory we allocate.  */
+
 	setg_gcc = setg;
-	pthread_attr_init(&attr);
-	pthread_attr_getstacksize(&attr, &size);
-	g->stacklo = (uintptr)&attr - size + 4096;
-	pthread_attr_destroy(&attr);
+	attr = (pthread_attr_t*)malloc(sizeof *attr);
+	if (attr == NULL) {
+		fatalf("malloc failed: %s", strerror(errno));
+	}
+	pthread_attr_init(attr);
+	pthread_attr_getstacksize(attr, &size);
+	g->stacklo = (uintptr)&size - size + 4096;
+	pthread_attr_destroy(attr);
+	free(attr);
+
+	if (x_cgo_inittls) {
+		x_cgo_inittls();
+	}
 }
 
 
@@ -52,6 +84,10 @@ _cgo_sys_thread_start(ThreadStart *ts)
 static void*
 threadentry(void *v)
 {
+	if (x_cgo_threadentry) {
+		return x_cgo_threadentry(v);
+	}
+
 	ThreadStart ts;
 
 	ts = *(ThreadStart*)v;
diff --git a/src/runtime/cgo/gcc_linux_arm.c b/src/runtime/cgo/gcc_linux_arm.c
index 7d4b4d6..ce940fe 100644
--- a/src/runtime/cgo/gcc_linux_arm.c
+++ b/src/runtime/cgo/gcc_linux_arm.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <pthread.h>
 #include <string.h>
 #include <signal.h>
diff --git a/src/runtime/cgo/gcc_linux_arm64.c b/src/runtime/cgo/gcc_linux_arm64.c
index ea11cf5..babbd50 100644
--- a/src/runtime/cgo/gcc_linux_arm64.c
+++ b/src/runtime/cgo/gcc_linux_arm64.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <pthread.h>
 #include <string.h>
 #include <signal.h>
diff --git a/src/runtime/cgo/gcc_linux_ppc64x.c b/src/runtime/cgo/gcc_linux_ppc64x.c
index b176295..1264ab5 100644
--- a/src/runtime/cgo/gcc_linux_ppc64x.c
+++ b/src/runtime/cgo/gcc_linux_ppc64x.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 // +build ppc64 ppc64le
 
 #include <pthread.h>
diff --git a/src/runtime/cgo/gcc_mmap.c b/src/runtime/cgo/gcc_mmap.c
new file mode 100644
index 0000000..f2bcc98
--- /dev/null
+++ b/src/runtime/cgo/gcc_mmap.c
@@ -0,0 +1,23 @@
+// Copyright 2015 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.
+
+// +build cgo
+
+// +build linux,amd64
+
+#include <errno.h>
+#include <stdint.h>
+#include <sys/mman.h>
+
+void *
+x_cgo_mmap(void *addr, uintptr_t length, int32_t prot, int32_t flags, int32_t fd, uint32_t offset) {
+	void *p;
+
+	p = mmap(addr, length, prot, flags, fd, offset);
+	if (p == MAP_FAILED) {
+		/* This is what the Go code expects on failure.  */
+		p = (void *) (uintptr_t) errno;
+	}
+	return p;
+}
diff --git a/src/runtime/cgo/gcc_netbsd_386.c b/src/runtime/cgo/gcc_netbsd_386.c
index 2505e6d..4355bd0 100644
--- a/src/runtime/cgo/gcc_netbsd_386.c
+++ b/src/runtime/cgo/gcc_netbsd_386.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <sys/types.h>
 #include <pthread.h>
 #include <signal.h>
@@ -55,6 +57,7 @@ static void*
 threadentry(void *v)
 {
 	ThreadStart ts;
+	stack_t ss;
 
 	ts = *(ThreadStart*)v;
 	free(v);
@@ -64,6 +67,17 @@ threadentry(void *v)
 	 */
 	setg_gcc((void*)ts.g);
 
+	// On NetBSD, a new thread inherits the signal stack of the
+	// creating thread.  That confuses minit, so we remove that
+	// signal stack here before calling the regular mstart.  It's
+	// a bit baroque to remove a signal stack here only to add one
+	// in minit, but it's a simple change that keeps NetBSD
+	// working like other OS's.  At this point all signals are
+	// blocked, so there is no race.
+	memset(&ss, 0, sizeof ss);
+	ss.ss_flags = SS_DISABLE;
+	sigaltstack(&ss, nil);
+
 	crosscall_386(ts.fn);
 	return nil;
 }
diff --git a/src/runtime/cgo/gcc_netbsd_amd64.c b/src/runtime/cgo/gcc_netbsd_amd64.c
index 8f64650..00e0667 100644
--- a/src/runtime/cgo/gcc_netbsd_amd64.c
+++ b/src/runtime/cgo/gcc_netbsd_amd64.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <sys/types.h>
 #include <pthread.h>
 #include <signal.h>
@@ -56,6 +58,7 @@ static void*
 threadentry(void *v)
 {
 	ThreadStart ts;
+	stack_t ss;
 
 	ts = *(ThreadStart*)v;
 	free(v);
@@ -65,6 +68,17 @@ threadentry(void *v)
 	 */
 	setg_gcc((void*)ts.g);
 
+	// On NetBSD, a new thread inherits the signal stack of the
+	// creating thread.  That confuses minit, so we remove that
+	// signal stack here before calling the regular mstart.  It's
+	// a bit baroque to remove a signal stack here only to add one
+	// in minit, but it's a simple change that keeps NetBSD
+	// working like other OS's.  At this point all signals are
+	// blocked, so there is no race.
+	memset(&ss, 0, sizeof ss);
+	ss.ss_flags = SS_DISABLE;
+	sigaltstack(&ss, nil);
+
 	crosscall_amd64(ts.fn);
 	return nil;
 }
diff --git a/src/runtime/cgo/gcc_netbsd_arm.c b/src/runtime/cgo/gcc_netbsd_arm.c
index 7a98c0d..32bc85b 100644
--- a/src/runtime/cgo/gcc_netbsd_arm.c
+++ b/src/runtime/cgo/gcc_netbsd_arm.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <sys/types.h>
 #include <pthread.h>
 #include <signal.h>
@@ -57,10 +59,22 @@ static void*
 threadentry(void *v)
 {
 	ThreadStart ts;
+	stack_t ss;
 
 	ts = *(ThreadStart*)v;
 	free(v);
 
+	// On NetBSD, a new thread inherits the signal stack of the
+	// creating thread.  That confuses minit, so we remove that
+	// signal stack here before calling the regular mstart.  It's
+	// a bit baroque to remove a signal stack here only to add one
+	// in minit, but it's a simple change that keeps NetBSD
+	// working like other OS's.  At this point all signals are
+	// blocked, so there is no race.
+	memset(&ss, 0, sizeof ss);
+	ss.ss_flags = SS_DISABLE;
+	sigaltstack(&ss, nil);
+
 	crosscall_arm1(ts.fn, setg_gcc, (void*)ts.g);
 	return nil;
 }
diff --git a/src/runtime/cgo/gcc_openbsd_386.c b/src/runtime/cgo/gcc_openbsd_386.c
index c4be9a0..5f6d4cb 100644
--- a/src/runtime/cgo/gcc_openbsd_386.c
+++ b/src/runtime/cgo/gcc_openbsd_386.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <sys/types.h>
 #include <dlfcn.h>
 #include <errno.h>
diff --git a/src/runtime/cgo/gcc_openbsd_amd64.c b/src/runtime/cgo/gcc_openbsd_amd64.c
index 8522cd4..4226567 100644
--- a/src/runtime/cgo/gcc_openbsd_amd64.c
+++ b/src/runtime/cgo/gcc_openbsd_amd64.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <sys/types.h>
 #include <dlfcn.h>
 #include <errno.h>
diff --git a/src/runtime/cgo/gcc_ppc64x.S b/src/runtime/cgo/gcc_ppc64x.S
index 05af070..a817b3a 100644
--- a/src/runtime/cgo/gcc_ppc64x.S
+++ b/src/runtime/cgo/gcc_ppc64x.S
@@ -31,11 +31,13 @@ EXT(crosscall_ppc64):
 
 	// Set up Go ABI constant registers
 	bl	_cgo_reginit
+	nop
 
 	// Restore g pointer (r30 in Go ABI, which may have been clobbered by C)
 	mr	%r30, %r4
 
 	// Call fn
+	mr	%r12, %r3
 	mtctr	%r3
 	bctrl
 
@@ -129,11 +131,6 @@ restoreregs:
 
 	blr
 
-.globl EXT(__stack_chk_fail_local)
-EXT(__stack_chk_fail_local):
-1:
-	// TODO(austin)
-	b 1b
 
 #ifdef __ELF__
 .section .note.GNU-stack,"",%progbits
diff --git a/src/runtime/cgo/gcc_setenv.c b/src/runtime/cgo/gcc_setenv.c
index ca29dcb..c976ac3 100644
--- a/src/runtime/cgo/gcc_setenv.c
+++ b/src/runtime/cgo/gcc_setenv.c
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
 // +build darwin dragonfly freebsd linux netbsd openbsd solaris
 
 #include "libcgo.h"
diff --git a/src/runtime/cgo/gcc_signal_darwin_armx.c b/src/runtime/cgo/gcc_signal_darwin_armx.c
index e36fe26..295c562 100644
--- a/src/runtime/cgo/gcc_signal_darwin_armx.c
+++ b/src/runtime/cgo/gcc_signal_darwin_armx.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 // Emulation of the Unix signal SIGSEGV.
 //
 // On iOS, Go tests and apps under development are run by lldb.
diff --git a/src/runtime/cgo/gcc_signal_darwin_lldb.c b/src/runtime/cgo/gcc_signal_darwin_lldb.c
index b26315f..edb55f3 100644
--- a/src/runtime/cgo/gcc_signal_darwin_lldb.c
+++ b/src/runtime/cgo/gcc_signal_darwin_lldb.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 // +build !lldb
 // +build darwin
 // +build arm arm64
diff --git a/src/runtime/cgo/gcc_solaris_amd64.c b/src/runtime/cgo/gcc_solaris_amd64.c
index 72ace56..5a01e08 100644
--- a/src/runtime/cgo/gcc_solaris_amd64.c
+++ b/src/runtime/cgo/gcc_solaris_amd64.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include <pthread.h>
 #include <string.h>
 #include <signal.h>
@@ -20,6 +22,12 @@ x_cgo_init(G *g, void (*setg)(void*))
 	if (getcontext(&ctx) != 0)
 		perror("runtime/cgo: getcontext failed");
 	g->stacklo = (uintptr_t)ctx.uc_stack.ss_sp;
+
+	// Solaris processes report a tiny stack when run with "ulimit -s unlimited".
+	// Correct that as best we can: assume it's at least 1 MB.
+	// See golang.org/issue/12210.
+	if(ctx.uc_stack.ss_size < 1024*1024)
+		g->stacklo -= 1024*1024 - ctx.uc_stack.ss_size;
 }
 
 void
diff --git a/src/runtime/cgo/gcc_util.c b/src/runtime/cgo/gcc_util.c
index 143734e..d5efec3 100644
--- a/src/runtime/cgo/gcc_util.c
+++ b/src/runtime/cgo/gcc_util.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #include "libcgo.h"
 
 /* Stub for calling malloc from Go */
diff --git a/src/runtime/cgo/gcc_windows_386.c b/src/runtime/cgo/gcc_windows_386.c
index acd038c..e02991a 100644
--- a/src/runtime/cgo/gcc_windows_386.c
+++ b/src/runtime/cgo/gcc_windows_386.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #include <process.h>
diff --git a/src/runtime/cgo/gcc_windows_amd64.c b/src/runtime/cgo/gcc_windows_amd64.c
index ce7e06b..1b3e8e3 100644
--- a/src/runtime/cgo/gcc_windows_amd64.c
+++ b/src/runtime/cgo/gcc_windows_amd64.c
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build cgo
+
 #define WIN64_LEAN_AND_MEAN
 #include <windows.h>
 #include <process.h>
diff --git a/src/runtime/cgo/mmap.go b/src/runtime/cgo/mmap.go
new file mode 100644
index 0000000..d514c38
--- /dev/null
+++ b/src/runtime/cgo/mmap.go
@@ -0,0 +1,22 @@
+// Copyright 2015 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.
+
+// +build linux,amd64
+
+package cgo
+
+// Import "unsafe" because we use go:linkname.
+import _ "unsafe"
+
+// When using cgo, call the C library for mmap, so that we call into
+// any sanitizer interceptors.  This supports using the memory
+// sanitizer with Go programs.  The memory sanitizer only applies to
+// C/C++ code; this permits that code to see the Go code as normal
+// program addresses that have been initialized.
+
+//go:cgo_import_static x_cgo_mmap
+//go:linkname x_cgo_mmap x_cgo_mmap
+//go:linkname _cgo_mmap _cgo_mmap
+var x_cgo_mmap byte
+var _cgo_mmap = &x_cgo_mmap
diff --git a/src/runtime/cgo_mmap.go b/src/runtime/cgo_mmap.go
new file mode 100644
index 0000000..c0396bd
--- /dev/null
+++ b/src/runtime/cgo_mmap.go
@@ -0,0 +1,41 @@
+// Copyright 2015 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.
+
+// Support for memory sanitizer.  See runtime/cgo/mmap.go.
+
+// +build linux,amd64
+
+package runtime
+
+import "unsafe"
+
+// _cgo_mmap is filled in by runtime/cgo when it is linked into the
+// program, so it is only non-nil when using cgo.
+//go:linkname _cgo_mmap _cgo_mmap
+var _cgo_mmap unsafe.Pointer
+
+func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer {
+	if _cgo_mmap != nil {
+		// Make ret a uintptr so that writing to it in the
+		// function literal does not trigger a write barrier.
+		// A write barrier here could break because of the way
+		// that mmap uses the same value both as a pointer and
+		// an errno value.
+		// TODO: Fix mmap to return two values.
+		var ret uintptr
+		systemstack(func() {
+			ret = callCgoMmap(addr, n, prot, flags, fd, off)
+		})
+		return unsafe.Pointer(ret)
+	}
+	return sysMmap(addr, n, prot, flags, fd, off)
+}
+
+// sysMmap calls the mmap system call.  It is implemented in assembly.
+func sysMmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer
+
+// cgoMmap calls the mmap function in the runtime/cgo package on the
+// callCgoMmap calls the mmap function in the runtime/cgo package
+// using the GCC calling convention.  It is implemented in assembly.
+func callCgoMmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) uintptr
diff --git a/src/runtime/cgo_ppc64x.go b/src/runtime/cgo_ppc64x.go
new file mode 100644
index 0000000..6a1b3bb
--- /dev/null
+++ b/src/runtime/cgo_ppc64x.go
@@ -0,0 +1,12 @@
+// Copyright 2015 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.
+
+// +build ppc64 ppc64le
+
+package runtime
+
+// crosscall_ppc64 calls into the runtime to set up the registers the
+// Go runtime expects and so the symbol it calls needs to be exported
+// for external linking to work.
+//go:cgo_export_static _cgo_reginit
diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go
index f09a66a..66115fd 100644
--- a/src/runtime/cgocall.go
+++ b/src/runtime/cgocall.go
@@ -79,7 +79,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 // Call from Go to C.
 //go:nosplit
@@ -220,27 +223,39 @@ func cgocallbackg1() {
 	case "arm":
 		// On arm, stack frame is two words and there's a saved LR between
 		// SP and the stack frame and between the stack frame and the arguments.
-		cb = (*args)(unsafe.Pointer(sp + 4*ptrSize))
+		cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize))
 	case "arm64":
 		// On arm64, stack frame is four words and there's a saved LR between
 		// SP and the stack frame and between the stack frame and the arguments.
-		cb = (*args)(unsafe.Pointer(sp + 5*ptrSize))
+		cb = (*args)(unsafe.Pointer(sp + 5*sys.PtrSize))
 	case "amd64":
 		// On amd64, stack frame is one word, plus caller PC.
 		if framepointer_enabled {
 			// In this case, there's also saved BP.
-			cb = (*args)(unsafe.Pointer(sp + 3*ptrSize))
+			cb = (*args)(unsafe.Pointer(sp + 3*sys.PtrSize))
 			break
 		}
-		cb = (*args)(unsafe.Pointer(sp + 2*ptrSize))
+		cb = (*args)(unsafe.Pointer(sp + 2*sys.PtrSize))
 	case "386":
 		// On 386, stack frame is three words, plus caller PC.
-		cb = (*args)(unsafe.Pointer(sp + 4*ptrSize))
+		cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize))
 	case "ppc64", "ppc64le":
-		// On ppc64, stack frame is two words and there's a
-		// saved LR between SP and the stack frame and between
-		// the stack frame and the arguments.
-		cb = (*args)(unsafe.Pointer(sp + 4*ptrSize))
+		// On ppc64, the callback arguments are in the arguments area of
+		// cgocallback's stack frame. The stack looks like this:
+		// +--------------------+------------------------------+
+		// |                    | ...                          |
+		// | cgoexp_$fn         +------------------------------+
+		// |                    | fixed frame area             |
+		// +--------------------+------------------------------+
+		// |                    | arguments area               |
+		// | cgocallback        +------------------------------+ <- sp + 2*minFrameSize + 2*ptrSize
+		// |                    | fixed frame area             |
+		// +--------------------+------------------------------+ <- sp + minFrameSize + 2*ptrSize
+		// |                    | local variables (2 pointers) |
+		// | cgocallback_gofunc +------------------------------+ <- sp + minFrameSize
+		// |                    | fixed frame area             |
+		// +--------------------+------------------------------+ <- sp
+		cb = (*args)(unsafe.Pointer(sp + 2*sys.MinFrameSize + 2*sys.PtrSize))
 	}
 
 	// Invoke callback.
@@ -254,6 +269,13 @@ func cgocallbackg1() {
 	if raceenabled {
 		racereleasemerge(unsafe.Pointer(&racecgosync))
 	}
+	if msanenabled {
+		// Tell msan that we wrote to the entire argument block.
+		// This tells msan that we set the results.
+		// Since we have already called the function it doesn't
+		// matter that we are writing to the non-result parameters.
+		msanwrite(cb.arg, cb.argsize)
+	}
 
 	// Do not unwind m->g0->sched.sp.
 	// Our caller, cgocallback, will do that.
@@ -271,14 +293,10 @@ func unwindm(restore *bool) {
 	switch GOARCH {
 	default:
 		throw("unwindm not implemented")
-	case "386", "amd64":
-		sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp))
-	case "arm":
-		sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + 4))
+	case "386", "amd64", "arm", "ppc64", "ppc64le":
+		sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + sys.MinFrameSize))
 	case "arm64":
 		sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + 16))
-	case "ppc64", "ppc64le":
-		sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + 8))
 	}
 	releasem(mp)
 }
@@ -294,3 +312,288 @@ func cgounimpl() {
 }
 
 var racecgosync uint64 // represents possible synchronization in C code
+
+// Pointer checking for cgo code.
+
+// We want to detect all cases where a program that does not use
+// unsafe makes a cgo call passing a Go pointer to memory that
+// contains a Go pointer.  Here a Go pointer is defined as a pointer
+// to memory allocated by the Go runtime.  Programs that use unsafe
+// can evade this restriction easily, so we don't try to catch them.
+// The cgo program will rewrite all possibly bad pointer arguments to
+// call cgoCheckPointer, where we can catch cases of a Go pointer
+// pointing to a Go pointer.
+
+// Complicating matters, taking the address of a slice or array
+// element permits the C program to access all elements of the slice
+// or array.  In that case we will see a pointer to a single element,
+// but we need to check the entire data structure.
+
+// The cgoCheckPointer call takes additional arguments indicating that
+// it was called on an address expression.  An additional argument of
+// true means that it only needs to check a single element.  An
+// additional argument of a slice or array means that it needs to
+// check the entire slice/array, but nothing else.  Otherwise, the
+// pointer could be anything, and we check the entire heap object,
+// which is conservative but safe.
+
+// When and if we implement a moving garbage collector,
+// cgoCheckPointer will pin the pointer for the duration of the cgo
+// call.  (This is necessary but not sufficient; the cgo program will
+// also have to change to pin Go pointers that can not point to Go
+// pointers.)
+
+// cgoCheckPointer checks if the argument contains a Go pointer that
+// points to a Go pointer, and panics if it does.  It returns the pointer.
+func cgoCheckPointer(ptr interface{}, args ...interface{}) interface{} {
+	if debug.cgocheck == 0 {
+		return ptr
+	}
+
+	ep := (*eface)(unsafe.Pointer(&ptr))
+	t := ep._type
+
+	top := true
+	if len(args) > 0 && (t.kind&kindMask == kindPtr || t.kind&kindMask == kindUnsafePointer) {
+		p := ep.data
+		if t.kind&kindDirectIface == 0 {
+			p = *(*unsafe.Pointer)(p)
+		}
+		if !cgoIsGoPointer(p) {
+			return ptr
+		}
+		aep := (*eface)(unsafe.Pointer(&args[0]))
+		switch aep._type.kind & kindMask {
+		case kindBool:
+			if t.kind&kindMask == kindUnsafePointer {
+				// We don't know the type of the element.
+				break
+			}
+			pt := (*ptrtype)(unsafe.Pointer(t))
+			cgoCheckArg(pt.elem, p, true, false, cgoCheckPointerFail)
+			return ptr
+		case kindSlice:
+			// Check the slice rather than the pointer.
+			ep = aep
+			t = ep._type
+		case kindArray:
+			// Check the array rather than the pointer.
+			// Pass top as false since we have a pointer
+			// to the array.
+			ep = aep
+			t = ep._type
+			top = false
+		default:
+			throw("can't happen")
+		}
+	}
+
+	cgoCheckArg(t, ep.data, t.kind&kindDirectIface == 0, top, cgoCheckPointerFail)
+	return ptr
+}
+
+const cgoCheckPointerFail = "cgo argument has Go pointer to Go pointer"
+const cgoResultFail = "cgo result has Go pointer"
+
+// cgoCheckArg is the real work of cgoCheckPointer.  The argument p
+// is either a pointer to the value (of type t), or the value itself,
+// depending on indir.  The top parameter is whether we are at the top
+// level, where Go pointers are allowed.
+func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool, msg string) {
+	if t.kind&kindNoPointers != 0 {
+		// If the type has no pointers there is nothing to do.
+		return
+	}
+
+	switch t.kind & kindMask {
+	default:
+		throw("can't happen")
+	case kindArray:
+		at := (*arraytype)(unsafe.Pointer(t))
+		if !indir {
+			if at.len != 1 {
+				throw("can't happen")
+			}
+			cgoCheckArg(at.elem, p, at.elem.kind&kindDirectIface == 0, top, msg)
+			return
+		}
+		for i := uintptr(0); i < at.len; i++ {
+			cgoCheckArg(at.elem, p, true, top, msg)
+			p = add(p, at.elem.size)
+		}
+	case kindChan, kindMap:
+		// These types contain internal pointers that will
+		// always be allocated in the Go heap.  It's never OK
+		// to pass them to C.
+		panic(errorString(msg))
+	case kindFunc:
+		if indir {
+			p = *(*unsafe.Pointer)(p)
+		}
+		if !cgoIsGoPointer(p) {
+			return
+		}
+		panic(errorString(msg))
+	case kindInterface:
+		it := *(**_type)(p)
+		if it == nil {
+			return
+		}
+		// A type known at compile time is OK since it's
+		// constant.  A type not known at compile time will be
+		// in the heap and will not be OK.
+		if inheap(uintptr(unsafe.Pointer(it))) {
+			panic(errorString(msg))
+		}
+		p = *(*unsafe.Pointer)(add(p, sys.PtrSize))
+		if !cgoIsGoPointer(p) {
+			return
+		}
+		if !top {
+			panic(errorString(msg))
+		}
+		cgoCheckArg(it, p, it.kind&kindDirectIface == 0, false, msg)
+	case kindSlice:
+		st := (*slicetype)(unsafe.Pointer(t))
+		s := (*slice)(p)
+		p = s.array
+		if !cgoIsGoPointer(p) {
+			return
+		}
+		if !top {
+			panic(errorString(msg))
+		}
+		for i := 0; i < s.cap; i++ {
+			cgoCheckArg(st.elem, p, true, false, msg)
+			p = add(p, st.elem.size)
+		}
+	case kindString:
+		ss := (*stringStruct)(p)
+		if !cgoIsGoPointer(ss.str) {
+			return
+		}
+		if !top {
+			panic(errorString(msg))
+		}
+	case kindStruct:
+		st := (*structtype)(unsafe.Pointer(t))
+		if !indir {
+			if len(st.fields) != 1 {
+				throw("can't happen")
+			}
+			cgoCheckArg(st.fields[0].typ, p, st.fields[0].typ.kind&kindDirectIface == 0, top, msg)
+			return
+		}
+		for _, f := range st.fields {
+			cgoCheckArg(f.typ, add(p, f.offset), true, top, msg)
+		}
+	case kindPtr, kindUnsafePointer:
+		if indir {
+			p = *(*unsafe.Pointer)(p)
+		}
+
+		if !cgoIsGoPointer(p) {
+			return
+		}
+		if !top {
+			panic(errorString(msg))
+		}
+
+		cgoCheckUnknownPointer(p, msg)
+	}
+}
+
+// cgoCheckUnknownPointer is called for an arbitrary pointer into Go
+// memory.  It checks whether that Go memory contains any other
+// pointer into Go memory.  If it does, we panic.
+// The return values are unused but useful to see in panic tracebacks.
+func cgoCheckUnknownPointer(p unsafe.Pointer, msg string) (base, i uintptr) {
+	if cgoInRange(p, mheap_.arena_start, mheap_.arena_used) {
+		if !inheap(uintptr(p)) {
+			// On 32-bit systems it is possible for C's allocated memory
+			// to have addresses between arena_start and arena_used.
+			// Either this pointer is a stack or an unused span or it's
+			// a C allocation. Escape analysis should prevent the first,
+			// garbage collection should prevent the second,
+			// and the third is completely OK.
+			return
+		}
+
+		b, hbits, span := heapBitsForObject(uintptr(p), 0, 0)
+		base = b
+		if base == 0 {
+			return
+		}
+		n := span.elemsize
+		for i = uintptr(0); i < n; i += sys.PtrSize {
+			bits := hbits.bits()
+			if i >= 2*sys.PtrSize && bits&bitMarked == 0 {
+				// No more possible pointers.
+				break
+			}
+			if bits&bitPointer != 0 {
+				if cgoIsGoPointer(*(*unsafe.Pointer)(unsafe.Pointer(base + i))) {
+					panic(errorString(msg))
+				}
+			}
+			hbits = hbits.next()
+		}
+
+		return
+	}
+
+	for datap := &firstmoduledata; datap != nil; datap = datap.next {
+		if cgoInRange(p, datap.data, datap.edata) || cgoInRange(p, datap.bss, datap.ebss) {
+			// We have no way to know the size of the object.
+			// We have to assume that it might contain a pointer.
+			panic(errorString(msg))
+		}
+		// In the text or noptr sections, we know that the
+		// pointer does not point to a Go pointer.
+	}
+
+	return
+}
+
+// cgoIsGoPointer returns whether the pointer is a Go pointer--a
+// pointer to Go memory.  We only care about Go memory that might
+// contain pointers.
+//go:nosplit
+//go:nowritebarrierrec
+func cgoIsGoPointer(p unsafe.Pointer) bool {
+	if p == nil {
+		return false
+	}
+
+	if cgoInRange(p, mheap_.arena_start, mheap_.arena_used) {
+		return true
+	}
+
+	for datap := &firstmoduledata; datap != nil; datap = datap.next {
+		if cgoInRange(p, datap.data, datap.edata) || cgoInRange(p, datap.bss, datap.ebss) {
+			return true
+		}
+	}
+
+	return false
+}
+
+// cgoInRange returns whether p is between start and end.
+//go:nosplit
+//go:nowritebarrierrec
+func cgoInRange(p unsafe.Pointer, start, end uintptr) bool {
+	return start <= uintptr(p) && uintptr(p) < end
+}
+
+// cgoCheckResult is called to check the result parameter of an
+// exported Go function.  It panics if the result is or contains a Go
+// pointer.
+func cgoCheckResult(val interface{}) {
+	if debug.cgocheck == 0 {
+		return
+	}
+
+	ep := (*eface)(unsafe.Pointer(&val))
+	t := ep._type
+	cgoCheckArg(t, ep.data, t.kind&kindDirectIface == 0, false, cgoResultFail)
+}
diff --git a/src/runtime/cgocheck.go b/src/runtime/cgocheck.go
new file mode 100644
index 0000000..aebce15
--- /dev/null
+++ b/src/runtime/cgocheck.go
@@ -0,0 +1,240 @@
+// Copyright 2015 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.
+
+// Code to check that pointer writes follow the cgo rules.
+// These functions are invoked via the write barrier when debug.cgocheck > 1.
+
+package runtime
+
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
+
+const cgoWriteBarrierFail = "Go pointer stored into non-Go memory"
+
+// cgoCheckWriteBarrier is called whenever a pointer is stored into memory.
+// It throws if the program is storing a Go pointer into non-Go memory.
+//go:nosplit
+//go:nowritebarrier
+func cgoCheckWriteBarrier(dst *uintptr, src uintptr) {
+	if !cgoIsGoPointer(unsafe.Pointer(src)) {
+		return
+	}
+	if cgoIsGoPointer(unsafe.Pointer(dst)) {
+		return
+	}
+
+	// If we are running on the system stack then dst might be an
+	// address on the stack, which is OK.
+	g := getg()
+	if g == g.m.g0 || g == g.m.gsignal {
+		return
+	}
+
+	// Allocating memory can write to various mfixalloc structs
+	// that look like they are non-Go memory.
+	if g.m.mallocing != 0 {
+		return
+	}
+
+	systemstack(func() {
+		println("write of Go pointer", hex(src), "to non-Go memory", hex(uintptr(unsafe.Pointer(dst))))
+		throw(cgoWriteBarrierFail)
+	})
+}
+
+// cgoCheckMemmove is called when moving a block of memory.
+// dst and src point off bytes into the value to copy.
+// size is the number of bytes to copy.
+// It throws if the program is copying a block that contains a Go pointer
+// into non-Go memory.
+//go:nosplit
+//go:nowritebarrier
+func cgoCheckMemmove(typ *_type, dst, src unsafe.Pointer, off, size uintptr) {
+	if typ.kind&kindNoPointers != 0 {
+		return
+	}
+	if !cgoIsGoPointer(src) {
+		return
+	}
+	if cgoIsGoPointer(dst) {
+		return
+	}
+	cgoCheckTypedBlock(typ, src, off, size)
+}
+
+// cgoCheckSliceCopy is called when copying n elements of a slice from
+// src to dst.  typ is the element type of the slice.
+// It throws if the program is copying slice elements that contain Go pointers
+// into non-Go memory.
+//go:nosplit
+//go:nowritebarrier
+func cgoCheckSliceCopy(typ *_type, dst, src slice, n int) {
+	if typ.kind&kindNoPointers != 0 {
+		return
+	}
+	if !cgoIsGoPointer(src.array) {
+		return
+	}
+	if cgoIsGoPointer(dst.array) {
+		return
+	}
+	p := src.array
+	for i := 0; i < n; i++ {
+		cgoCheckTypedBlock(typ, p, 0, typ.size)
+		p = add(p, typ.size)
+	}
+}
+
+// cgoCheckTypedBlock checks the block of memory at src, for up to size bytes,
+// and throws if it finds a Go pointer.  The type of the memory is typ,
+// and src is off bytes into that type.
+//go:nosplit
+//go:nowritebarrier
+func cgoCheckTypedBlock(typ *_type, src unsafe.Pointer, off, size uintptr) {
+	if typ.kind&kindGCProg == 0 {
+		cgoCheckBits(src, typ.gcdata, off, size)
+		return
+	}
+
+	// The type has a GC program.  Try to find GC bits somewhere else.
+	for datap := &firstmoduledata; datap != nil; datap = datap.next {
+		if cgoInRange(src, datap.data, datap.edata) {
+			doff := uintptr(src) - datap.data
+			cgoCheckBits(add(src, -doff), datap.gcdatamask.bytedata, off+doff, size)
+			return
+		}
+		if cgoInRange(src, datap.bss, datap.ebss) {
+			boff := uintptr(src) - datap.bss
+			cgoCheckBits(add(src, -boff), datap.gcbssmask.bytedata, off+boff, size)
+			return
+		}
+	}
+
+	aoff := uintptr(src) - mheap_.arena_start
+	idx := aoff >> _PageShift
+	s := h_spans[idx]
+	if s.state == _MSpanStack {
+		// There are no heap bits for value stored on the stack.
+		// For a channel receive src might be on the stack of some
+		// other goroutine, so we can't unwind the stack even if
+		// we wanted to.
+		// We can't expand the GC program without extra storage
+		// space we can't easily get.
+		// Fortunately we have the type information.
+		systemstack(func() {
+			cgoCheckUsingType(typ, src, off, size)
+		})
+		return
+	}
+
+	// src must be in the regular heap.
+
+	hbits := heapBitsForAddr(uintptr(src))
+	for i := uintptr(0); i < off+size; i += sys.PtrSize {
+		bits := hbits.bits()
+		if i >= off && bits&bitPointer != 0 {
+			v := *(*unsafe.Pointer)(add(src, i))
+			if cgoIsGoPointer(v) {
+				systemstack(func() {
+					throw(cgoWriteBarrierFail)
+				})
+			}
+		}
+		hbits = hbits.next()
+	}
+}
+
+// cgoCheckBits checks the block of memory at src, for up to size
+// bytes, and throws if it finds a Go pointer.  The gcbits mark each
+// pointer value.  The src pointer is off bytes into the gcbits.
+//go:nosplit
+//go:nowritebarrier
+func cgoCheckBits(src unsafe.Pointer, gcbits *byte, off, size uintptr) {
+	skipMask := off / sys.PtrSize / 8
+	skipBytes := skipMask * sys.PtrSize * 8
+	ptrmask := addb(gcbits, skipMask)
+	src = add(src, skipBytes)
+	off -= skipBytes
+	size += off
+	var bits uint32
+	for i := uintptr(0); i < size; i += sys.PtrSize {
+		if i&(sys.PtrSize*8-1) == 0 {
+			bits = uint32(*ptrmask)
+			ptrmask = addb(ptrmask, 1)
+		} else {
+			bits >>= 1
+		}
+		if off > 0 {
+			off -= sys.PtrSize
+		} else {
+			if bits&1 != 0 {
+				v := *(*unsafe.Pointer)(add(src, i))
+				if cgoIsGoPointer(v) {
+					systemstack(func() {
+						throw(cgoWriteBarrierFail)
+					})
+				}
+			}
+		}
+	}
+}
+
+// cgoCheckUsingType is like cgoCheckTypedBlock, but is a last ditch
+// fall back to look for pointers in src using the type information.
+// We only this when looking at a value on the stack when the type
+// uses a GC program, because otherwise it's more efficient to use the
+// GC bits.  This is called on the system stack.
+//go:nowritebarrier
+//go:systemstack
+func cgoCheckUsingType(typ *_type, src unsafe.Pointer, off, size uintptr) {
+	if typ.kind&kindNoPointers != 0 {
+		return
+	}
+	if typ.kind&kindGCProg == 0 {
+		cgoCheckBits(src, typ.gcdata, off, size)
+		return
+	}
+	switch typ.kind & kindMask {
+	default:
+		throw("can't happen")
+	case kindArray:
+		at := (*arraytype)(unsafe.Pointer(typ))
+		for i := uintptr(0); i < at.len; i++ {
+			if off < at.elem.size {
+				cgoCheckUsingType(at.elem, src, off, size)
+			}
+			src = add(src, at.elem.size)
+			skipped := off
+			if skipped > at.elem.size {
+				skipped = at.elem.size
+			}
+			checked := at.elem.size - skipped
+			off -= skipped
+			if size <= checked {
+				return
+			}
+			size -= checked
+		}
+	case kindStruct:
+		st := (*structtype)(unsafe.Pointer(typ))
+		for _, f := range st.fields {
+			if off < f.typ.size {
+				cgoCheckUsingType(f.typ, src, off, size)
+			}
+			src = add(src, f.typ.size)
+			skipped := off
+			if skipped > f.typ.size {
+				skipped = f.typ.size
+			}
+			checked := f.typ.size - skipped
+			off -= skipped
+			if size <= checked {
+				return
+			}
+			size -= checked
+		}
+	}
+}
diff --git a/src/runtime/chan.go b/src/runtime/chan.go
index cfee12a..5be18be 100644
--- a/src/runtime/chan.go
+++ b/src/runtime/chan.go
@@ -6,7 +6,15 @@ package runtime
 
 // This file contains the implementation of Go channels.
 
-import "unsafe"
+// Invariants:
+//  At least one of c.sendq and c.recvq is empty.
+// For buffered channels, also:
+//  c.qcount > 0 implies that c.recvq is empty.
+//  c.qcount < c.dataqsiz implies that c.sendq is empty.
+import (
+	"runtime/internal/atomic"
+	"unsafe"
+)
 
 const (
 	maxAlign  = 8
@@ -108,6 +116,9 @@ func chansend(t *chantype, c *hchan, ep unsafe.Pointer, block bool, callerpc uin
 	if raceenabled {
 		raceReadObjectPC(t.elem, ep, callerpc, funcPC(chansend))
 	}
+	if msanenabled {
+		msanread(ep, t.elem.size)
+	}
 
 	if c == nil {
 		if !block {
@@ -150,135 +161,117 @@ func chansend(t *chantype, c *hchan, ep unsafe.Pointer, block bool, callerpc uin
 	}
 
 	lock(&c.lock)
+
 	if c.closed != 0 {
 		unlock(&c.lock)
 		panic("send on closed channel")
 	}
 
-	if c.dataqsiz == 0 { // synchronous channel
-		sg := c.recvq.dequeue()
-		if sg != nil { // found a waiting receiver
-			if raceenabled {
-				racesync(c, sg)
-			}
-			unlock(&c.lock)
-
-			recvg := sg.g
-			if sg.elem != nil {
-				syncsend(c, sg, ep)
-			}
-			recvg.param = unsafe.Pointer(sg)
-			if sg.releasetime != 0 {
-				sg.releasetime = cputicks()
-			}
-			goready(recvg, 3)
-			return true
-		}
-
-		if !block {
-			unlock(&c.lock)
-			return false
-		}
-
-		// no receiver available: block on this channel.
-		gp := getg()
-		mysg := acquireSudog()
-		mysg.releasetime = 0
-		if t0 != 0 {
-			mysg.releasetime = -1
-		}
-		mysg.elem = ep
-		mysg.waitlink = nil
-		gp.waiting = mysg
-		mysg.g = gp
-		mysg.selectdone = nil
-		gp.param = nil
-		c.sendq.enqueue(mysg)
-		goparkunlock(&c.lock, "chan send", traceEvGoBlockSend, 3)
+	if sg := c.recvq.dequeue(); sg != nil {
+		// Found a waiting receiver. We pass the value we want to send
+		// directly to the receiver, bypassing the channel buffer (if any).
+		send(c, sg, ep, func() { unlock(&c.lock) })
+		return true
+	}
 
-		// someone woke us up.
-		if mysg != gp.waiting {
-			throw("G waiting list is corrupted!")
-		}
-		gp.waiting = nil
-		if gp.param == nil {
-			if c.closed == 0 {
-				throw("chansend: spurious wakeup")
-			}
-			panic("send on closed channel")
+	if c.qcount < c.dataqsiz {
+		// Space is available in the channel buffer.  Enqueue the element to send.
+		qp := chanbuf(c, c.sendx)
+		if raceenabled {
+			raceacquire(qp)
+			racerelease(qp)
 		}
-		gp.param = nil
-		if mysg.releasetime > 0 {
-			blockevent(int64(mysg.releasetime)-t0, 2)
+		typedmemmove(c.elemtype, qp, ep)
+		c.sendx++
+		if c.sendx == c.dataqsiz {
+			c.sendx = 0
 		}
-		releaseSudog(mysg)
+		c.qcount++
+		unlock(&c.lock)
 		return true
 	}
 
-	// asynchronous channel
-	// wait for some space to write our data
-	var t1 int64
-	for futile := byte(0); c.qcount >= c.dataqsiz; futile = traceFutileWakeup {
-		if !block {
-			unlock(&c.lock)
-			return false
-		}
-		gp := getg()
-		mysg := acquireSudog()
-		mysg.releasetime = 0
-		if t0 != 0 {
-			mysg.releasetime = -1
-		}
-		mysg.g = gp
-		mysg.elem = nil
-		mysg.selectdone = nil
-		c.sendq.enqueue(mysg)
-		goparkunlock(&c.lock, "chan send", traceEvGoBlockSend|futile, 3)
-
-		// someone woke us up - try again
-		if mysg.releasetime > 0 {
-			t1 = mysg.releasetime
-		}
-		releaseSudog(mysg)
-		lock(&c.lock)
-		if c.closed != 0 {
-			unlock(&c.lock)
-			panic("send on closed channel")
-		}
+	if !block {
+		unlock(&c.lock)
+		return false
 	}
 
-	// write our data into the channel buffer
-	if raceenabled {
-		raceacquire(chanbuf(c, c.sendx))
-		racerelease(chanbuf(c, c.sendx))
+	// Block on the channel.  Some receiver will complete our operation for us.
+	gp := getg()
+	mysg := acquireSudog()
+	mysg.releasetime = 0
+	if t0 != 0 {
+		mysg.releasetime = -1
+	}
+	mysg.elem = ep
+	mysg.waitlink = nil
+	mysg.g = gp
+	mysg.selectdone = nil
+	gp.waiting = mysg
+	gp.param = nil
+	c.sendq.enqueue(mysg)
+	goparkunlock(&c.lock, "chan send", traceEvGoBlockSend, 3)
+
+	// someone woke us up.
+	if mysg != gp.waiting {
+		throw("G waiting list is corrupted")
+	}
+	gp.waiting = nil
+	if gp.param == nil {
+		if c.closed == 0 {
+			throw("chansend: spurious wakeup")
+		}
+		panic("send on closed channel")
 	}
-	typedmemmove(c.elemtype, chanbuf(c, c.sendx), ep)
-	c.sendx++
-	if c.sendx == c.dataqsiz {
-		c.sendx = 0
+	gp.param = nil
+	if mysg.releasetime > 0 {
+		blockevent(int64(mysg.releasetime)-t0, 2)
 	}
-	c.qcount++
+	releaseSudog(mysg)
+	return true
+}
 
-	// wake up a waiting receiver
-	sg := c.recvq.dequeue()
-	if sg != nil {
-		recvg := sg.g
-		unlock(&c.lock)
-		if sg.releasetime != 0 {
-			sg.releasetime = cputicks()
+// send processes a send operation on an empty channel c.
+// The value ep sent by the sender is copied to the receiver sg.
+// The receiver is then woken up to go on its merry way.
+// Channel c must be empty and locked.  send unlocks c with unlockf.
+// sg must already be dequeued from c.
+// ep must be non-nil and point to the heap or the caller's stack.
+func send(c *hchan, sg *sudog, ep unsafe.Pointer, unlockf func()) {
+	if raceenabled {
+		if c.dataqsiz == 0 {
+			racesync(c, sg)
+		} else {
+			// Pretend we go through the buffer, even though
+			// we copy directly.  Note that we need to increment
+			// the head/tail locations only when raceenabled.
+			qp := chanbuf(c, c.recvx)
+			raceacquire(qp)
+			racerelease(qp)
+			raceacquireg(sg.g, qp)
+			racereleaseg(sg.g, qp)
+			c.recvx++
+			if c.recvx == c.dataqsiz {
+				c.recvx = 0
+			}
+			c.sendx = c.recvx // c.sendx = (c.sendx+1) % c.dataqsiz
 		}
-		goready(recvg, 3)
-	} else {
-		unlock(&c.lock)
 	}
-	if t1 > 0 {
-		blockevent(t1-t0, 2)
+	unlockf()
+	if sg.elem != nil {
+		sendDirect(c.elemtype, sg, ep)
+		sg.elem = nil
+	}
+	gp := sg.g
+	gp.param = unsafe.Pointer(sg)
+	if sg.releasetime != 0 {
+		sg.releasetime = cputicks()
 	}
-	return true
+	goready(gp, 4)
 }
 
-func syncsend(c *hchan, sg *sudog, elem unsafe.Pointer) {
-	// Send on unbuffered channel is the only operation
+func sendDirect(t *_type, sg *sudog, src unsafe.Pointer) {
+	// Send on an unbuffered or empty-buffered channel is the only operation
 	// in the entire runtime where one goroutine
 	// writes to the stack of another goroutine. The GC assumes that
 	// stack writes only happen when the goroutine is running and are
@@ -287,9 +280,13 @@ func syncsend(c *hchan, sg *sudog, elem unsafe.Pointer) {
 	// typedmemmove will call heapBitsBulkBarrier, but the target bytes
 	// are not in the heap, so that will not help. We arrange to call
 	// memmove and typeBitsBulkBarrier instead.
-	memmove(sg.elem, elem, c.elemtype.size)
-	typeBitsBulkBarrier(c.elemtype, uintptr(sg.elem), c.elemtype.size)
-	sg.elem = nil
+
+	// Once we read sg.elem out of sg, it will no longer
+	// be updated if the destination's stack gets copied (shrunk).
+	// So make sure that no preemption points can happen between read & use.
+	dst := sg.elem
+	memmove(dst, src, t.size)
+	typeBitsBulkBarrier(t, uintptr(dst), t.size)
 }
 
 func closechan(c *hchan) {
@@ -317,27 +314,36 @@ func closechan(c *hchan) {
 		if sg == nil {
 			break
 		}
-		gp := sg.g
-		sg.elem = nil
-		gp.param = nil
+		if sg.elem != nil {
+			memclr(sg.elem, uintptr(c.elemsize))
+			sg.elem = nil
+		}
 		if sg.releasetime != 0 {
 			sg.releasetime = cputicks()
 		}
+		gp := sg.g
+		gp.param = nil
+		if raceenabled {
+			raceacquireg(gp, unsafe.Pointer(c))
+		}
 		goready(gp, 3)
 	}
 
-	// release all writers
+	// release all writers (they will panic)
 	for {
 		sg := c.sendq.dequeue()
 		if sg == nil {
 			break
 		}
-		gp := sg.g
 		sg.elem = nil
-		gp.param = nil
 		if sg.releasetime != 0 {
 			sg.releasetime = cputicks()
 		}
+		gp := sg.g
+		gp.param = nil
+		if raceenabled {
+			raceacquireg(gp, unsafe.Pointer(c))
+		}
 		goready(gp, 3)
 	}
 	unlock(&c.lock)
@@ -360,8 +366,10 @@ func chanrecv2(t *chantype, c *hchan, elem unsafe.Pointer) (received bool) {
 // If block == false and no elements are available, returns (false, false).
 // Otherwise, if c is closed, zeros *ep and returns (true, false).
 // Otherwise, fills in *ep with an element and returns (true, true).
+// A non-nil ep must point to the heap or the caller's stack.
 func chanrecv(t *chantype, c *hchan, ep unsafe.Pointer, block bool) (selected, received bool) {
-	// raceenabled: don't need to check ep, as it is always on the stack.
+	// raceenabled: don't need to check ep, as it is always on the stack
+	// or is new memory allocated by reflect.
 
 	if debugChan {
 		print("chanrecv: chan=", c, "\n")
@@ -388,8 +396,8 @@ func chanrecv(t *chantype, c *hchan, ep unsafe.Pointer, block bool) (selected, r
 	// The order of operations is important here: reversing the operations can lead to
 	// incorrect behavior when racing with a close.
 	if !block && (c.dataqsiz == 0 && c.sendq.first == nil ||
-		c.dataqsiz > 0 && atomicloaduint(&c.qcount) == 0) &&
-		atomicload(&c.closed) == 0 {
+		c.dataqsiz > 0 && atomic.Loaduint(&c.qcount) == 0) &&
+		atomic.Load(&c.closed) == 0 {
 		return
 	}
 
@@ -399,167 +407,139 @@ func chanrecv(t *chantype, c *hchan, ep unsafe.Pointer, block bool) (selected, r
 	}
 
 	lock(&c.lock)
-	if c.dataqsiz == 0 { // synchronous channel
-		if c.closed != 0 {
-			return recvclosed(c, ep)
-		}
-
-		sg := c.sendq.dequeue()
-		if sg != nil {
-			if raceenabled {
-				racesync(c, sg)
-			}
-			unlock(&c.lock)
-
-			if ep != nil {
-				typedmemmove(c.elemtype, ep, sg.elem)
-			}
-			sg.elem = nil
-			gp := sg.g
-			gp.param = unsafe.Pointer(sg)
-			if sg.releasetime != 0 {
-				sg.releasetime = cputicks()
-			}
-			goready(gp, 3)
-			selected = true
-			received = true
-			return
-		}
-
-		if !block {
-			unlock(&c.lock)
-			return
-		}
-
-		// no sender available: block on this channel.
-		gp := getg()
-		mysg := acquireSudog()
-		mysg.releasetime = 0
-		if t0 != 0 {
-			mysg.releasetime = -1
-		}
-		mysg.elem = ep
-		mysg.waitlink = nil
-		gp.waiting = mysg
-		mysg.g = gp
-		mysg.selectdone = nil
-		gp.param = nil
-		c.recvq.enqueue(mysg)
-		goparkunlock(&c.lock, "chan receive", traceEvGoBlockRecv, 3)
 
-		// someone woke us up
-		if mysg != gp.waiting {
-			throw("G waiting list is corrupted!")
+	if c.closed != 0 && c.qcount == 0 {
+		if raceenabled {
+			raceacquire(unsafe.Pointer(c))
 		}
-		gp.waiting = nil
-		if mysg.releasetime > 0 {
-			blockevent(mysg.releasetime-t0, 2)
-		}
-		haveData := gp.param != nil
-		gp.param = nil
-		releaseSudog(mysg)
-
-		if haveData {
-			// a sender sent us some data. It already wrote to ep.
-			selected = true
-			received = true
-			return
-		}
-
-		lock(&c.lock)
-		if c.closed == 0 {
-			throw("chanrecv: spurious wakeup")
+		unlock(&c.lock)
+		if ep != nil {
+			memclr(ep, uintptr(c.elemsize))
 		}
-		return recvclosed(c, ep)
+		return true, false
 	}
 
-	// asynchronous channel
-	// wait for some data to appear
-	var t1 int64
-	for futile := byte(0); c.qcount <= 0; futile = traceFutileWakeup {
-		if c.closed != 0 {
-			selected, received = recvclosed(c, ep)
-			if t1 > 0 {
-				blockevent(t1-t0, 2)
-			}
-			return
-		}
+	if sg := c.sendq.dequeue(); sg != nil {
+		// Found a waiting sender.  If buffer is size 0, receive value
+		// directly from sender.  Otherwise, recieve from head of queue
+		// and add sender's value to the tail of the queue (both map to
+		// the same buffer slot because the queue is full).
+		recv(c, sg, ep, func() { unlock(&c.lock) })
+		return true, true
+	}
 
-		if !block {
-			unlock(&c.lock)
-			return
+	if c.qcount > 0 {
+		// Receive directly from queue
+		qp := chanbuf(c, c.recvx)
+		if raceenabled {
+			raceacquire(qp)
+			racerelease(qp)
 		}
-
-		// wait for someone to send an element
-		gp := getg()
-		mysg := acquireSudog()
-		mysg.releasetime = 0
-		if t0 != 0 {
-			mysg.releasetime = -1
+		if ep != nil {
+			typedmemmove(c.elemtype, ep, qp)
 		}
-		mysg.elem = nil
-		mysg.g = gp
-		mysg.selectdone = nil
-
-		c.recvq.enqueue(mysg)
-		goparkunlock(&c.lock, "chan receive", traceEvGoBlockRecv|futile, 3)
-
-		// someone woke us up - try again
-		if mysg.releasetime > 0 {
-			t1 = mysg.releasetime
+		memclr(qp, uintptr(c.elemsize))
+		c.recvx++
+		if c.recvx == c.dataqsiz {
+			c.recvx = 0
 		}
-		releaseSudog(mysg)
-		lock(&c.lock)
-	}
-
-	if raceenabled {
-		raceacquire(chanbuf(c, c.recvx))
-		racerelease(chanbuf(c, c.recvx))
-	}
-	if ep != nil {
-		typedmemmove(c.elemtype, ep, chanbuf(c, c.recvx))
-	}
-	memclr(chanbuf(c, c.recvx), uintptr(c.elemsize))
-
-	c.recvx++
-	if c.recvx == c.dataqsiz {
-		c.recvx = 0
-	}
-	c.qcount--
-
-	// ping a sender now that there is space
-	sg := c.sendq.dequeue()
-	if sg != nil {
-		gp := sg.g
-		unlock(&c.lock)
-		if sg.releasetime != 0 {
-			sg.releasetime = cputicks()
-		}
-		goready(gp, 3)
-	} else {
+		c.qcount--
 		unlock(&c.lock)
+		return true, true
 	}
 
-	if t1 > 0 {
-		blockevent(t1-t0, 2)
-	}
-	selected = true
-	received = true
-	return
+	if !block {
+		unlock(&c.lock)
+		return false, false
+	}
+
+	// no sender available: block on this channel.
+	gp := getg()
+	mysg := acquireSudog()
+	mysg.releasetime = 0
+	if t0 != 0 {
+		mysg.releasetime = -1
+	}
+	mysg.elem = ep
+	mysg.waitlink = nil
+	gp.waiting = mysg
+	mysg.g = gp
+	mysg.selectdone = nil
+	gp.param = nil
+	c.recvq.enqueue(mysg)
+	goparkunlock(&c.lock, "chan receive", traceEvGoBlockRecv, 3)
+
+	// someone woke us up
+	if mysg != gp.waiting {
+		throw("G waiting list is corrupted")
+	}
+	gp.waiting = nil
+	if mysg.releasetime > 0 {
+		blockevent(mysg.releasetime-t0, 2)
+	}
+	closed := gp.param == nil
+	gp.param = nil
+	releaseSudog(mysg)
+	return true, !closed
 }
 
-// recvclosed is a helper function for chanrecv.  Handles cleanup
-// when the receiver encounters a closed channel.
-// Caller must hold c.lock, recvclosed will release the lock.
-func recvclosed(c *hchan, ep unsafe.Pointer) (selected, recevied bool) {
-	if raceenabled {
-		raceacquire(unsafe.Pointer(c))
+// recv processes a receive operation on a full channel c.
+// There are 2 parts:
+// 1) The value sent by the sender sg is put into the channel
+//    and the sender is woken up to go on its merry way.
+// 2) The value received by the receiver (the current G) is
+//    written to ep.
+// For synchronous channels, both values are the same.
+// For asynchronous channels, the receiver gets its data from
+// the channel buffer and the sender's data is put in the
+// channel buffer.
+// Channel c must be full and locked. recv unlocks c with unlockf.
+// sg must already be dequeued from c.
+// A non-nil ep must point to the heap or the caller's stack.
+func recv(c *hchan, sg *sudog, ep unsafe.Pointer, unlockf func()) {
+	if c.dataqsiz == 0 {
+		if raceenabled {
+			racesync(c, sg)
+		}
+		unlockf()
+		if ep != nil {
+			// copy data from sender
+			// ep points to our own stack or heap, so nothing
+			// special (ala sendDirect) needed here.
+			typedmemmove(c.elemtype, ep, sg.elem)
+		}
+	} else {
+		// Queue is full.  Take the item at the
+		// head of the queue.  Make the sender enqueue
+		// its item at the tail of the queue.  Since the
+		// queue is full, those are both the same slot.
+		qp := chanbuf(c, c.recvx)
+		if raceenabled {
+			raceacquire(qp)
+			racerelease(qp)
+			raceacquireg(sg.g, qp)
+			racereleaseg(sg.g, qp)
+		}
+		// copy data from queue to receiver
+		if ep != nil {
+			typedmemmove(c.elemtype, ep, qp)
+		}
+		// copy data from sender to queue
+		typedmemmove(c.elemtype, qp, sg.elem)
+		c.recvx++
+		if c.recvx == c.dataqsiz {
+			c.recvx = 0
+		}
+		c.sendx = c.recvx // c.sendx = (c.sendx+1) % c.dataqsiz
+		unlockf()
 	}
-	unlock(&c.lock)
-	if ep != nil {
-		memclr(ep, uintptr(c.elemsize))
+	sg.elem = nil
+	gp := sg.g
+	gp.param = unsafe.Pointer(sg)
+	if sg.releasetime != 0 {
+		sg.releasetime = cputicks()
 	}
-	return true, false
+	goready(gp, 4)
 }
 
 // compiler implements
@@ -692,7 +672,7 @@ func (q *waitq) dequeue() *sudog {
 		// if sgp participates in a select and is already signaled, ignore it
 		if sgp.selectdone != nil {
 			// claim the right to signal
-			if *sgp.selectdone != 0 || !cas(sgp.selectdone, 0, 1) {
+			if *sgp.selectdone != 0 || !atomic.Cas(sgp.selectdone, 0, 1) {
 				continue
 			}
 		}
diff --git a/src/runtime/cpuprof.go b/src/runtime/cpuprof.go
index 0790852..87d5f99 100644
--- a/src/runtime/cpuprof.go
+++ b/src/runtime/cpuprof.go
@@ -50,7 +50,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"unsafe"
+)
 
 const (
 	numBuckets      = 1 << 10
@@ -173,7 +176,7 @@ func SetCPUProfileRate(hz int) {
 			if n&0x80000000 != 0 {
 				print("runtime: setcpuprofile(off) twice\n")
 			}
-			if cas(&cpuprof.handoff, n, n|0x80000000) {
+			if atomic.Cas(&cpuprof.handoff, n, n|0x80000000) {
 				if n == 0 {
 					// we did the transition from 0 -> nonzero so we wake getprofile
 					notewakeup(&cpuprof.wait)
@@ -276,7 +279,7 @@ func (p *cpuProfile) evict(e *cpuprofEntry) bool {
 // so it cannot allocate memory or block.  It can try to swap logs with
 // the writing goroutine, as explained in the comment at the top of this file.
 func (p *cpuProfile) flushlog() bool {
-	if !cas(&p.handoff, 0, uint32(p.nlog)) {
+	if !atomic.Cas(&p.handoff, 0, uint32(p.nlog)) {
 		return false
 	}
 	notewakeup(&p.wait)
@@ -318,7 +321,7 @@ func (p *cpuProfile) getprofile() []byte {
 				p.flushing = true
 				goto Flush
 			}
-			if cas(&p.handoff, n, 0) {
+			if atomic.Cas(&p.handoff, n, 0) {
 				break
 			}
 		}
@@ -389,7 +392,7 @@ Flush:
 
 	// Finally done.  Clean up and return nil.
 	p.flushing = false
-	if !cas(&p.handoff, p.handoff, 0) {
+	if !atomic.Cas(&p.handoff, p.handoff, 0) {
 		print("runtime: profile flush racing with something\n")
 	}
 	return nil
diff --git a/src/runtime/cputicks.go b/src/runtime/cputicks.go
index 162e026..f5a60e6 100644
--- a/src/runtime/cputicks.go
+++ b/src/runtime/cputicks.go
@@ -4,6 +4,8 @@
 
 // +build !arm
 // +build !arm64
+// +build !mips64
+// +build !mips64le
 
 package runtime
 
diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go
index 2e65e4c..d7b367f 100644
--- a/src/runtime/crash_cgo_test.go
+++ b/src/runtime/crash_cgo_test.go
@@ -21,18 +21,18 @@ func TestCgoSignalDeadlock(t *testing.T) {
 	if testing.Short() && runtime.GOOS == "windows" {
 		t.Skip("Skipping in short mode") // takes up to 64 seconds
 	}
-	got := executeTest(t, cgoSignalDeadlockSource, nil)
+	got := runTestProg(t, "testprogcgo", "CgoSignalDeadlock")
 	want := "OK\n"
 	if got != want {
-		t.Fatalf("expected %q, but got %q", want, got)
+		t.Fatalf("expected %q, but got:\n%s", want, got)
 	}
 }
 
 func TestCgoTraceback(t *testing.T) {
-	got := executeTest(t, cgoTracebackSource, nil)
+	got := runTestProg(t, "testprogcgo", "CgoTraceback")
 	want := "OK\n"
 	if got != want {
-		t.Fatalf("expected %q, but got %q", want, got)
+		t.Fatalf("expected %q, but got:\n%s", want, got)
 	}
 }
 
@@ -40,13 +40,18 @@ func TestCgoCallbackGC(t *testing.T) {
 	if runtime.GOOS == "plan9" || runtime.GOOS == "windows" {
 		t.Skipf("no pthreads on %s", runtime.GOOS)
 	}
-	if testing.Short() && runtime.GOOS == "dragonfly" {
-		t.Skip("see golang.org/issue/11990")
+	if testing.Short() {
+		switch {
+		case runtime.GOOS == "dragonfly":
+			t.Skip("see golang.org/issue/11990")
+		case runtime.GOOS == "linux" && runtime.GOARCH == "arm":
+			t.Skip("too slow for arm builders")
+		}
 	}
-	got := executeTest(t, cgoCallbackGCSource, nil)
+	got := runTestProg(t, "testprogcgo", "CgoCallbackGC")
 	want := "OK\n"
 	if got != want {
-		t.Fatalf("expected %q, but got %q", want, got)
+		t.Fatalf("expected %q, but got:\n%s", want, got)
 	}
 }
 
@@ -54,11 +59,7 @@ func TestCgoExternalThreadPanic(t *testing.T) {
 	if runtime.GOOS == "plan9" {
 		t.Skipf("no pthreads on %s", runtime.GOOS)
 	}
-	csrc := cgoExternalThreadPanicC
-	if runtime.GOOS == "windows" {
-		csrc = cgoExternalThreadPanicC_windows
-	}
-	got := executeTest(t, cgoExternalThreadPanicSource, nil, "main.c", csrc)
+	got := runTestProg(t, "testprogcgo", "CgoExternalThreadPanic")
 	want := "panic: BOOM"
 	if !strings.Contains(got, want) {
 		t.Fatalf("want failure containing %q. output:\n%s\n", want, got)
@@ -84,15 +85,15 @@ func TestCgoExternalThreadSIGPROF(t *testing.T) {
 			}
 		}
 	}
-	if runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" {
+	if runtime.GOARCH == "ppc64" {
 		// TODO(austin) External linking not implemented on
 		// ppc64 (issue #8912)
 		t.Skipf("no external linking on ppc64")
 	}
-	got := executeTest(t, cgoExternalThreadSIGPROFSource, nil)
+	got := runTestProg(t, "testprogcgo", "CgoExternalThreadSIGPROF")
 	want := "OK\n"
 	if got != want {
-		t.Fatalf("expected %q, but got %q", want, got)
+		t.Fatalf("expected %q, but got:\n%s", want, got)
 	}
 }
 
@@ -102,10 +103,10 @@ func TestCgoExternalThreadSignal(t *testing.T) {
 	case "plan9", "windows":
 		t.Skipf("no pthreads on %s", runtime.GOOS)
 	}
-	got := executeTest(t, cgoExternalThreadSignalSource, nil)
+	got := runTestProg(t, "testprogcgo", "CgoExternalThreadSignal")
 	want := "OK\n"
 	if got != want {
-		t.Fatalf("expected %q, but got %q", want, got)
+		t.Fatalf("expected %q, but got:\n%s", want, got)
 	}
 }
 
@@ -114,368 +115,35 @@ func TestCgoDLLImports(t *testing.T) {
 	if runtime.GOOS != "windows" {
 		t.Skip("skipping windows specific test")
 	}
-	got := executeTest(t, cgoDLLImportsMainSource, nil, "a/a.go", cgoDLLImportsPkgSource)
+	got := runTestProg(t, "testprogcgo", "CgoDLLImportsMain")
 	want := "OK\n"
 	if got != want {
 		t.Fatalf("expected %q, but got %v", want, got)
 	}
 }
 
-const cgoSignalDeadlockSource = `
-package main
-
-import "C"
-
-import (
-	"fmt"
-	"runtime"
-	"time"
-)
-
-func main() {
-	runtime.GOMAXPROCS(100)
-	ping := make(chan bool)
-	go func() {
-		for i := 0; ; i++ {
-			runtime.Gosched()
-			select {
-			case done := <-ping:
-				if done {
-					ping <- true
-					return
-				}
-				ping <- true
-			default:
-			}
-			func() {
-				defer func() {
-					recover()
-				}()
-				var s *string
-				*s = ""
-			}()
-		}
-	}()
-	time.Sleep(time.Millisecond)
-	for i := 0; i < 64; i++ {
-		go func() {
-			runtime.LockOSThread()
-			select {}
-		}()
-		go func() {
-			runtime.LockOSThread()
-			select {}
-		}()
-		time.Sleep(time.Millisecond)
-		ping <- false
-		select {
-		case <-ping:
-		case <-time.After(time.Second):
-			fmt.Printf("HANG\n")
-			return
-		}
-	}
-	ping <- true
-	select {
-	case <-ping:
-	case <-time.After(time.Second):
-		fmt.Printf("HANG\n")
-		return
-	}
-	fmt.Printf("OK\n")
-}
-`
-
-const cgoTracebackSource = `
-package main
-
-/* void foo(void) {} */
-import "C"
-
-import (
-	"fmt"
-	"runtime"
-)
-
-func main() {
-	C.foo()
-	buf := make([]byte, 1)
-	runtime.Stack(buf, true)
-	fmt.Printf("OK\n")
-}
-`
-
-const cgoCallbackGCSource = `
-package main
-
-import "runtime"
-
-/*
-#include <pthread.h>
-
-void go_callback();
-
-static void *thr(void *arg) {
-    go_callback();
-    return 0;
-}
-
-static void foo() {
-    pthread_t th;
-    pthread_create(&th, 0, thr, 0);
-    pthread_join(th, 0);
-}
-*/
-import "C"
-import "fmt"
-
-//export go_callback
-func go_callback() {
-	runtime.GC()
-	grow()
-	runtime.GC()
-}
-
-var cnt int
-
-func grow() {
-	x := 10000
-	sum := 0
-	if grow1(&x, &sum) == 0 {
-		panic("bad")
-	}
-}
-
-func grow1(x, sum *int) int {
-	if *x == 0 {
-		return *sum + 1
-	}
-	*x--
-	sum1 := *sum + *x
-	return grow1(x, &sum1)
-}
-
-func main() {
-	const P = 100
-	done := make(chan bool)
-	// allocate a bunch of stack frames and spray them with pointers
-	for i := 0; i < P; i++ {
-		go func() {
-			grow()
-			done <- true
-		}()
-	}
-	for i := 0; i < P; i++ {
-		<-done
-	}
-	// now give these stack frames to cgo callbacks
-	for i := 0; i < P; i++ {
-		go func() {
-			C.foo()
-			done <- true
-		}()
-	}
-	for i := 0; i < P; i++ {
-		<-done
+func TestCgoExecSignalMask(t *testing.T) {
+	// Test issue 13164.
+	switch runtime.GOOS {
+	case "windows", "plan9":
+		t.Skipf("skipping signal mask test on %s", runtime.GOOS)
 	}
-	fmt.Printf("OK\n")
-}
-`
-
-const cgoExternalThreadPanicSource = `
-package main
-
-// void start(void);
-import "C"
-
-func main() {
-	C.start()
-	select {}
-}
-
-//export gopanic
-func gopanic() {
-	panic("BOOM")
-}
-`
-
-const cgoExternalThreadPanicC = `
-#include <stdlib.h>
-#include <stdio.h>
-#include <pthread.h>
-
-void gopanic(void);
-
-static void*
-die(void* x)
-{
-	gopanic();
-	return 0;
-}
-
-void
-start(void)
-{
-	pthread_t t;
-	if(pthread_create(&t, 0, die, 0) != 0)
-		printf("pthread_create failed\n");
-}
-`
-
-const cgoExternalThreadPanicC_windows = `
-#include <stdlib.h>
-#include <stdio.h>
-
-void gopanic(void);
-
-static void*
-die(void* x)
-{
-	gopanic();
-	return 0;
-}
-
-void
-start(void)
-{
-	if(_beginthreadex(0, 0, die, 0, 0, 0) != 0)
-		printf("_beginthreadex failed\n");
-}
-`
-
-const cgoExternalThreadSIGPROFSource = `
-package main
-
-/*
-#include <stdint.h>
-#include <signal.h>
-#include <pthread.h>
-
-volatile int32_t spinlock;
-
-static void *thread1(void *p) {
-	(void)p;
-	while (spinlock == 0)
-		;
-	pthread_kill(pthread_self(), SIGPROF);
-	spinlock = 0;
-	return NULL;
-}
-__attribute__((constructor)) void issue9456() {
-	pthread_t tid;
-	pthread_create(&tid, 0, thread1, NULL);
-}
-*/
-import "C"
-
-import (
-	"runtime"
-	"sync/atomic"
-	"unsafe"
-)
-
-func main() {
-	// This test intends to test that sending SIGPROF to foreign threads
-	// before we make any cgo call will not abort the whole process, so
-	// we cannot make any cgo call here. See https://golang.org/issue/9456.
-	atomic.StoreInt32((*int32)(unsafe.Pointer(&C.spinlock)), 1)
-	for atomic.LoadInt32((*int32)(unsafe.Pointer(&C.spinlock))) == 1 {
-		runtime.Gosched()
+	got := runTestProg(t, "testprogcgo", "CgoExecSignalMask")
+	want := "OK\n"
+	if got != want {
+		t.Errorf("expected %q, got %v", want, got)
 	}
-	println("OK")
-}
-`
-
-const cgoExternalThreadSignalSource = `
-package main
-
-/*
-#include <pthread.h>
-
-void **nullptr;
-
-void *crash(void *p) {
-	*nullptr = p;
-	return 0;
 }
 
-int start_crashing_thread(void) {
-	pthread_t tid;
-	return pthread_create(&tid, 0, crash, 0);
-}
-*/
-import "C"
-
-import (
-	"fmt"
-	"os"
-	"os/exec"
-	"time"
-)
-
-func main() {
-	if len(os.Args) > 1 && os.Args[1] == "crash" {
-		i := C.start_crashing_thread()
-		if i != 0 {
-			fmt.Println("pthread_create failed:", i)
-			// Exit with 0 because parent expects us to crash.
-			return
-		}
-
-		// We should crash immediately, but give it plenty of
-		// time before failing (by exiting 0) in case we are
-		// running on a slow system.
-		time.Sleep(5 * time.Second)
-		return
+func TestEnsureDropM(t *testing.T) {
+	// Test for issue 13881.
+	switch runtime.GOOS {
+	case "windows", "plan9":
+		t.Skipf("skipping dropm test on %s", runtime.GOOS)
 	}
-
-	out, err := exec.Command(os.Args[0], "crash").CombinedOutput()
-	if err == nil {
-		fmt.Println("C signal did not crash as expected\n")
-		fmt.Printf("%s\n", out)
-		os.Exit(1)
+	got := runTestProg(t, "testprogcgo", "EnsureDropM")
+	want := "OK\n"
+	if got != want {
+		t.Errorf("expected %q, got %v", want, got)
 	}
-
-	fmt.Println("OK")
-}
-`
-
-const cgoDLLImportsMainSource = `
-package main
-
-/*
-#include <windows.h>
-
-DWORD getthread() {
-	return GetCurrentThreadId();
-}
-*/
-import "C"
-
-import "./a"
-
-func main() {
-	C.getthread()
-	a.GetThread()
-	println("OK")
-}
-`
-
-const cgoDLLImportsPkgSource = `
-package a
-
-/*
-#cgo CFLAGS: -mnop-fun-dllimport
-
-#include <windows.h>
-
-DWORD agetthread() {
-	return GetCurrentThreadId();
-}
-*/
-import "C"
-
-func GetThread() uint32 {
-	return uint32(C.agetthread())
 }
-`
diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go
index 8efce4d..5f0e77b 100644
--- a/src/runtime/crash_test.go
+++ b/src/runtime/crash_test.go
@@ -16,9 +16,18 @@ import (
 	"strings"
 	"sync"
 	"testing"
-	"text/template"
 )
 
+var toRemove []string
+
+func TestMain(m *testing.M) {
+	status := m.Run()
+	for _, file := range toRemove {
+		os.RemoveAll(file)
+	}
+	os.Exit(status)
+}
+
 func testEnv(cmd *exec.Cmd) *exec.Cmd {
 	if cmd.Env != nil {
 		panic("environment already set")
@@ -38,55 +47,63 @@ func testEnv(cmd *exec.Cmd) *exec.Cmd {
 	return cmd
 }
 
-func executeTest(t *testing.T, templ string, data interface{}, extra ...string) string {
-	testenv.MustHaveGoBuild(t)
+var testprog struct {
+	sync.Mutex
+	dir    string
+	target map[string]buildexe
+}
 
-	checkStaleRuntime(t)
+type buildexe struct {
+	exe string
+	err error
+}
 
-	st := template.Must(template.New("crashSource").Parse(templ))
+func runTestProg(t *testing.T, binary, name string) string {
+	testenv.MustHaveGoBuild(t)
 
-	dir, err := ioutil.TempDir("", "go-build")
+	exe, err := buildTestProg(t, binary)
 	if err != nil {
-		t.Fatalf("failed to create temp directory: %v", err)
+		t.Fatal(err)
 	}
-	defer os.RemoveAll(dir)
+	got, _ := testEnv(exec.Command(exe, name)).CombinedOutput()
+	return string(got)
+}
 
-	src := filepath.Join(dir, "main.go")
-	f, err := os.Create(src)
-	if err != nil {
-		t.Fatalf("failed to create file: %v", err)
-	}
-	err = st.Execute(f, data)
-	if err != nil {
-		f.Close()
-		t.Fatalf("failed to execute template: %v", err)
-	}
-	if err := f.Close(); err != nil {
-		t.Fatalf("failed to close file: %v", err)
-	}
+func buildTestProg(t *testing.T, binary string) (string, error) {
+	checkStaleRuntime(t)
 
-	for i := 0; i < len(extra); i += 2 {
-		fname := extra[i]
-		contents := extra[i+1]
-		if d, _ := filepath.Split(fname); d != "" {
-			if err := os.Mkdir(filepath.Join(dir, d), 0755); err != nil {
-				t.Fatal(err)
-			}
-		}
-		if err := ioutil.WriteFile(filepath.Join(dir, fname), []byte(contents), 0666); err != nil {
-			t.Fatal(err)
+	testprog.Lock()
+	defer testprog.Unlock()
+	if testprog.dir == "" {
+		dir, err := ioutil.TempDir("", "go-build")
+		if err != nil {
+			t.Fatalf("failed to create temp directory: %v", err)
 		}
+		testprog.dir = dir
+		toRemove = append(toRemove, dir)
 	}
 
-	cmd := exec.Command("go", "build", "-o", "a.exe")
-	cmd.Dir = dir
+	if testprog.target == nil {
+		testprog.target = make(map[string]buildexe)
+	}
+	target, ok := testprog.target[binary]
+	if ok {
+		return target.exe, target.err
+	}
+
+	exe := filepath.Join(testprog.dir, binary+".exe")
+	cmd := exec.Command("go", "build", "-o", exe)
+	cmd.Dir = "testdata/" + binary
 	out, err := testEnv(cmd).CombinedOutput()
 	if err != nil {
-		t.Fatalf("building source: %v\n%s", err, out)
+		exe = ""
+		target.err = fmt.Errorf("building %s: %v\n%s", binary, err, out)
+		testprog.target[binary] = target
+		return "", target.err
 	}
-
-	got, _ := testEnv(exec.Command(filepath.Join(dir, "a.exe"))).CombinedOutput()
-	return string(got)
+	target.exe = exe
+	testprog.target[binary] = target
+	return exe, nil
 }
 
 var (
@@ -115,7 +132,12 @@ func testCrashHandler(t *testing.T, cgo bool) {
 	type crashTest struct {
 		Cgo bool
 	}
-	output := executeTest(t, crashSource, &crashTest{Cgo: cgo})
+	var output string
+	if cgo {
+		output = runTestProg(t, "testprogcgo", "Crash")
+	} else {
+		output = runTestProg(t, "testprog", "Crash")
+	}
 	want := "main: recovered done\nnew-thread: recovered done\nsecond-new-thread: recovered done\nmain-again: recovered done\n"
 	if output != want {
 		t.Fatalf("output:\n%s\n\nwanted:\n%s", output, want)
@@ -126,8 +148,8 @@ func TestCrashHandler(t *testing.T) {
 	testCrashHandler(t, false)
 }
 
-func testDeadlock(t *testing.T, source string) {
-	output := executeTest(t, source, nil)
+func testDeadlock(t *testing.T, name string) {
+	output := runTestProg(t, "testprog", name)
 	want := "fatal error: all goroutines are asleep - deadlock!\n"
 	if !strings.HasPrefix(output, want) {
 		t.Fatalf("output does not start with %q:\n%s", want, output)
@@ -135,23 +157,23 @@ func testDeadlock(t *testing.T, source string) {
 }
 
 func TestSimpleDeadlock(t *testing.T) {
-	testDeadlock(t, simpleDeadlockSource)
+	testDeadlock(t, "SimpleDeadlock")
 }
 
 func TestInitDeadlock(t *testing.T) {
-	testDeadlock(t, initDeadlockSource)
+	testDeadlock(t, "InitDeadlock")
 }
 
 func TestLockedDeadlock(t *testing.T) {
-	testDeadlock(t, lockedDeadlockSource)
+	testDeadlock(t, "LockedDeadlock")
 }
 
 func TestLockedDeadlock2(t *testing.T) {
-	testDeadlock(t, lockedDeadlockSource2)
+	testDeadlock(t, "LockedDeadlock2")
 }
 
 func TestGoexitDeadlock(t *testing.T) {
-	output := executeTest(t, goexitDeadlockSource, nil)
+	output := runTestProg(t, "testprog", "GoexitDeadlock")
 	want := "no goroutines (main called runtime.Goexit) - deadlock!"
 	if !strings.Contains(output, want) {
 		t.Fatalf("output:\n%s\n\nwant output containing: %s", output, want)
@@ -159,15 +181,15 @@ func TestGoexitDeadlock(t *testing.T) {
 }
 
 func TestStackOverflow(t *testing.T) {
-	output := executeTest(t, stackOverflowSource, nil)
-	want := "runtime: goroutine stack exceeds 4194304-byte limit\nfatal error: stack overflow"
+	output := runTestProg(t, "testprog", "StackOverflow")
+	want := "runtime: goroutine stack exceeds 1474560-byte limit\nfatal error: stack overflow"
 	if !strings.HasPrefix(output, want) {
 		t.Fatalf("output does not start with %q:\n%s", want, output)
 	}
 }
 
 func TestThreadExhaustion(t *testing.T) {
-	output := executeTest(t, threadExhaustionSource, nil)
+	output := runTestProg(t, "testprog", "ThreadExhaustion")
 	want := "runtime: program exceeds 10-thread limit\nfatal error: thread exhaustion"
 	if !strings.HasPrefix(output, want) {
 		t.Fatalf("output does not start with %q:\n%s", want, output)
@@ -175,7 +197,7 @@ func TestThreadExhaustion(t *testing.T) {
 }
 
 func TestRecursivePanic(t *testing.T) {
-	output := executeTest(t, recursivePanicSource, nil)
+	output := runTestProg(t, "testprog", "RecursivePanic")
 	want := `wrap: bad
 panic: again
 
@@ -187,7 +209,7 @@ panic: again
 }
 
 func TestGoexitCrash(t *testing.T) {
-	output := executeTest(t, goexitExitSource, nil)
+	output := runTestProg(t, "testprog", "GoexitExit")
 	want := "no goroutines (main called runtime.Goexit) - deadlock!"
 	if !strings.Contains(output, want) {
 		t.Fatalf("output:\n%s\n\nwant output containing: %s", output, want)
@@ -211,15 +233,15 @@ func TestGoexitDefer(t *testing.T) {
 }
 
 func TestGoNil(t *testing.T) {
-	output := executeTest(t, goNilSource, nil)
+	output := runTestProg(t, "testprog", "GoNil")
 	want := "go of nil func value"
 	if !strings.Contains(output, want) {
 		t.Fatalf("output:\n%s\n\nwant output containing: %s", output, want)
 	}
 }
 
-func TestMainGoroutineId(t *testing.T) {
-	output := executeTest(t, mainGoroutineIdSource, nil)
+func TestMainGoroutineID(t *testing.T) {
+	output := runTestProg(t, "testprog", "MainGoroutineID")
 	want := "panic: test\n\ngoroutine 1 [running]:\n"
 	if !strings.HasPrefix(output, want) {
 		t.Fatalf("output does not start with %q:\n%s", want, output)
@@ -227,7 +249,7 @@ func TestMainGoroutineId(t *testing.T) {
 }
 
 func TestNoHelperGoroutines(t *testing.T) {
-	output := executeTest(t, noHelperGoroutinesSource, nil)
+	output := runTestProg(t, "testprog", "NoHelperGoroutines")
 	matches := regexp.MustCompile(`goroutine [0-9]+ \[`).FindAllStringSubmatch(output, -1)
 	if len(matches) != 1 || matches[0][0] != "goroutine 1 [" {
 		t.Fatalf("want to see only goroutine 1, see:\n%s", output)
@@ -235,311 +257,39 @@ func TestNoHelperGoroutines(t *testing.T) {
 }
 
 func TestBreakpoint(t *testing.T) {
-	output := executeTest(t, breakpointSource, nil)
+	output := runTestProg(t, "testprog", "Breakpoint")
 	want := "runtime.Breakpoint()"
 	if !strings.Contains(output, want) {
 		t.Fatalf("output:\n%s\n\nwant output containing: %s", output, want)
 	}
 }
 
-const crashSource = `
-package main
-
-import (
-	"fmt"
-	"runtime"
-)
-
-{{if .Cgo}}
-import "C"
-{{end}}
-
-func test(name string) {
-	defer func() {
-		if x := recover(); x != nil {
-			fmt.Printf(" recovered")
-		}
-		fmt.Printf(" done\n")
-	}()
-	fmt.Printf("%s:", name)
-	var s *string
-	_ = *s
-	fmt.Print("SHOULD NOT BE HERE")
-}
-
-func testInNewThread(name string) {
-	c := make(chan bool)
-	go func() {
-		runtime.LockOSThread()
-		test(name)
-		c <- true
-	}()
-	<-c
-}
-
-func main() {
-	runtime.LockOSThread()
-	test("main")
-	testInNewThread("new-thread")
-	testInNewThread("second-new-thread")
-	test("main-again")
-}
-`
-
-const simpleDeadlockSource = `
-package main
-func main() {
-	select {}
-}
-`
-
-const initDeadlockSource = `
-package main
-func init() {
-	select {}
-}
-func main() {
-}
-`
-
-const lockedDeadlockSource = `
-package main
-import "runtime"
-func main() {
-	runtime.LockOSThread()
-	select {}
-}
-`
-
-const lockedDeadlockSource2 = `
-package main
-import (
-	"runtime"
-	"time"
-)
-func main() {
-	go func() {
-		runtime.LockOSThread()
-		select {}
-	}()
-	time.Sleep(time.Millisecond)
-	select {}
-}
-`
-
-const goexitDeadlockSource = `
-package main
-import (
-      "runtime"
-)
-
-func F() {
-      for i := 0; i < 10; i++ {
-      }
-}
-
-func main() {
-      go F()
-      go F()
-      runtime.Goexit()
-}
-`
-
-const stackOverflowSource = `
-package main
-
-import "runtime/debug"
-
-func main() {
-	debug.SetMaxStack(4<<20)
-	f(make([]byte, 10))
-}
-
-func f(x []byte) byte {
-	var buf [64<<10]byte
-	return x[0] + f(buf[:])
-}
-`
-
-const threadExhaustionSource = `
-package main
-
-import (
-	"runtime"
-	"runtime/debug"
-)
-
-func main() {
-	debug.SetMaxThreads(10)
-	c := make(chan int)
-	for i := 0; i < 100; i++ {
-		go func() {
-			runtime.LockOSThread()
-			c <- 0
-			select{}
-		}()
-		<-c
-	}
-}
-`
-
-const recursivePanicSource = `
-package main
-
-import (
-	"fmt"
-)
-
-func main() {
-	func() {
-		defer func() {
-			fmt.Println(recover())
-		}()
-		var x [8192]byte
-		func(x [8192]byte) {
-			defer func() {
-				if err := recover(); err != nil {
-					panic("wrap: " + err.(string))
-				}
-			}()
-			panic("bad")
-		}(x)
-	}()
-	panic("again")
-}
-`
-
-const goexitExitSource = `
-package main
-
-import (
-	"runtime"
-	"time"
-)
-
-func main() {
-	go func() {
-		time.Sleep(time.Millisecond)
-	}()
-	i := 0
-	runtime.SetFinalizer(&i, func(p *int) {})
-	runtime.GC()
-	runtime.Goexit()
-}
-`
-
-const goNilSource = `
-package main
-
-func main() {
-	defer func() {
-		recover()
-	}()
-	var f func()
-	go f()
-	select{}
-}
-`
-
-const mainGoroutineIdSource = `
-package main
-func main() {
-	panic("test")
-}
-`
-
-const noHelperGoroutinesSource = `
-package main
-import (
-	"runtime"
-	"time"
-)
-func init() {
-	i := 0
-	runtime.SetFinalizer(&i, func(p *int) {})
-	time.AfterFunc(time.Hour, func() {})
-	panic("oops")
-}
-func main() {
-}
-`
-
-const breakpointSource = `
-package main
-import "runtime"
-func main() {
-	runtime.Breakpoint()
-}
-`
-
 func TestGoexitInPanic(t *testing.T) {
 	// see issue 8774: this code used to trigger an infinite recursion
-	output := executeTest(t, goexitInPanicSource, nil)
+	output := runTestProg(t, "testprog", "GoexitInPanic")
 	want := "fatal error: no goroutines (main called runtime.Goexit) - deadlock!"
 	if !strings.HasPrefix(output, want) {
 		t.Fatalf("output does not start with %q:\n%s", want, output)
 	}
 }
 
-const goexitInPanicSource = `
-package main
-import "runtime"
-func main() {
-	go func() {
-		defer func() {
-			runtime.Goexit()
-		}()
-		panic("hello")
-	}()
-	runtime.Goexit()
-}
-`
-
 func TestPanicAfterGoexit(t *testing.T) {
 	// an uncaught panic should still work after goexit
-	output := executeTest(t, panicAfterGoexitSource, nil)
+	output := runTestProg(t, "testprog", "PanicAfterGoexit")
 	want := "panic: hello"
 	if !strings.HasPrefix(output, want) {
 		t.Fatalf("output does not start with %q:\n%s", want, output)
 	}
 }
 
-const panicAfterGoexitSource = `
-package main
-import "runtime"
-func main() {
-	defer func() {
-		panic("hello")
-	}()
-	runtime.Goexit()
-}
-`
-
 func TestRecoveredPanicAfterGoexit(t *testing.T) {
-	output := executeTest(t, recoveredPanicAfterGoexitSource, nil)
+	output := runTestProg(t, "testprog", "RecoveredPanicAfterGoexit")
 	want := "fatal error: no goroutines (main called runtime.Goexit) - deadlock!"
 	if !strings.HasPrefix(output, want) {
 		t.Fatalf("output does not start with %q:\n%s", want, output)
 	}
 }
 
-const recoveredPanicAfterGoexitSource = `
-package main
-import "runtime"
-func main() {
-	defer func() {
-		defer func() {
-			r := recover()
-			if r == nil {
-				panic("bad recover")
-			}
-		}()
-		panic("hello")
-	}()
-	runtime.Goexit()
-}
-`
-
 func TestRecoverBeforePanicAfterGoexit(t *testing.T) {
 	// 1. defer a function that recovers
 	// 2. defer a function that panics
@@ -561,29 +311,28 @@ func TestRecoverBeforePanicAfterGoexit(t *testing.T) {
 }
 
 func TestNetpollDeadlock(t *testing.T) {
-	output := executeTest(t, netpollDeadlockSource, nil)
+	output := runTestProg(t, "testprognet", "NetpollDeadlock")
 	want := "done\n"
 	if !strings.HasSuffix(output, want) {
 		t.Fatalf("output does not start with %q:\n%s", want, output)
 	}
 }
 
-const netpollDeadlockSource = `
-package main
-import (
-	"fmt"
-	"net"
-)
-func init() {
-	fmt.Println("dialing")
-	c, err := net.Dial("tcp", "localhost:14356")
-	if err == nil {
-		c.Close()
-	} else {
-		fmt.Println("error: ", err)
+func TestPanicTraceback(t *testing.T) {
+	output := runTestProg(t, "testprog", "PanicTraceback")
+	want := "panic: hello"
+	if !strings.HasPrefix(output, want) {
+		t.Fatalf("output does not start with %q:\n%s", want, output)
+	}
+
+	// Check functions in the traceback.
+	fns := []string{"panic", "main.pt1.func1", "panic", "main.pt2.func1", "panic", "main.pt2", "main.pt1"}
+	for _, fn := range fns {
+		re := regexp.MustCompile(`(?m)^` + regexp.QuoteMeta(fn) + `\(.*\n`)
+		idx := re.FindStringIndex(output)
+		if idx == nil {
+			t.Fatalf("expected %q function in traceback:\n%s", fn, output)
+		}
+		output = output[idx[1]:]
 	}
 }
-func main() {
-	fmt.Println("done")
-}
-`
diff --git a/src/runtime/crash_unix_test.go b/src/runtime/crash_unix_test.go
index b925d02..771b303 100644
--- a/src/runtime/crash_unix_test.go
+++ b/src/runtime/crash_unix_test.go
@@ -14,6 +14,7 @@ import (
 	"os/exec"
 	"path/filepath"
 	"runtime"
+	"strings"
 	"syscall"
 	"testing"
 )
@@ -52,6 +53,18 @@ func TestCrashDumpsAllThreads(t *testing.T) {
 	cmd = exec.Command(filepath.Join(dir, "a.exe"))
 	cmd = testEnv(cmd)
 	cmd.Env = append(cmd.Env, "GOTRACEBACK=crash")
+
+	// Set GOGC=off. Because of golang.org/issue/10958, the tight
+	// loops in the test program are not preemptible. If GC kicks
+	// in, it may lock up and prevent main from saying it's ready.
+	newEnv := []string{}
+	for _, s := range cmd.Env {
+		if !strings.HasPrefix(s, "GOGC=") {
+			newEnv = append(newEnv, s)
+		}
+	}
+	cmd.Env = append(newEnv, "GOGC=off")
+
 	var outbuf bytes.Buffer
 	cmd.Stdout = &outbuf
 	cmd.Stderr = &outbuf
@@ -133,3 +146,33 @@ func loop(i int, c chan bool) {
 	}
 }
 `
+
+func TestSignalExitStatus(t *testing.T) {
+	testenv.MustHaveGoBuild(t)
+	switch runtime.GOOS {
+	case "netbsd", "solaris":
+		t.Skipf("skipping on %s; see https://golang.org/issue/14063", runtime.GOOS)
+	}
+	exe, err := buildTestProg(t, "testprog")
+	if err != nil {
+		t.Fatal(err)
+	}
+	err = testEnv(exec.Command(exe, "SignalExitStatus")).Run()
+	if err == nil {
+		t.Error("test program succeeded unexpectedly")
+	} else if ee, ok := err.(*exec.ExitError); !ok {
+		t.Errorf("error (%v) has type %T; expected exec.ExitError", err, err)
+	} else if ws, ok := ee.Sys().(syscall.WaitStatus); !ok {
+		t.Errorf("error.Sys (%v) has type %T; expected syscall.WaitStatus", ee.Sys(), ee.Sys())
+	} else if !ws.Signaled() || ws.Signal() != syscall.SIGTERM {
+		t.Errorf("got %v; expected SIGTERM", ee)
+	}
+}
+
+func TestSignalIgnoreSIGTRAP(t *testing.T) {
+	output := runTestProg(t, "testprognet", "SignalIgnoreSIGTRAP")
+	want := "OK\n"
+	if output != want {
+		t.Fatalf("want %s, got %s\n", want, output)
+	}
+}
diff --git a/src/runtime/debug.go b/src/runtime/debug.go
index b7e7971..0f59365 100644
--- a/src/runtime/debug.go
+++ b/src/runtime/debug.go
@@ -4,7 +4,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"unsafe"
+)
 
 // GOMAXPROCS sets the maximum number of CPUs that can be executing
 // simultaneously and returns the previous setting.  If n < 1, it does not
@@ -32,6 +35,10 @@ func GOMAXPROCS(n int) int {
 }
 
 // NumCPU returns the number of logical CPUs usable by the current process.
+//
+// The set of available CPUs is checked by querying the operating system
+// at process startup. Changes to operating system CPU allocation after
+// process startup are not reflected.
 func NumCPU() int {
 	return int(ncpu)
 }
@@ -39,7 +46,7 @@ func NumCPU() int {
 // NumCgoCall returns the number of cgo calls made by the current process.
 func NumCgoCall() int64 {
 	var n int64
-	for mp := (*m)(atomicloadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
+	for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
 		n += int64(mp.ncgocall)
 	}
 	return n
diff --git a/src/runtime/debug/garbage.go b/src/runtime/debug/garbage.go
index 41202f9..8d6d278 100644
--- a/src/runtime/debug/garbage.go
+++ b/src/runtime/debug/garbage.go
@@ -157,3 +157,14 @@ func SetPanicOnFault(enabled bool) bool {
 // it to the given file descriptor.
 // The heap dump format is defined at https://golang.org/s/go13heapdump.
 func WriteHeapDump(fd uintptr)
+
+// SetTraceback sets the amount of detail printed by the runtime in
+// the traceback it prints before exiting due to an unrecovered panic
+// or an internal runtime error.
+// The level argument takes the same values as the GOTRACEBACK
+// environment variable. For example, SetTraceback("all") ensure
+// that the program prints all goroutines when it crashes.
+// See the package runtime documentation for details.
+// If SetTraceback is called with a level lower than that of the
+// environment variable, the call is ignored.
+func SetTraceback(level string)
diff --git a/src/runtime/debug/garbage_test.go b/src/runtime/debug/garbage_test.go
index 3e3483d..d834da8 100644
--- a/src/runtime/debug/garbage_test.go
+++ b/src/runtime/debug/garbage_test.go
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package debug
+package debug_test
 
 import (
 	"runtime"
+	. "runtime/debug"
 	"testing"
 	"time"
 )
@@ -88,7 +89,7 @@ func TestReadGCStats(t *testing.T) {
 var big = make([]byte, 1<<20)
 
 func TestFreeOSMemory(t *testing.T) {
-	if runtime.GOARCH == "arm64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" ||
+	if runtime.GOARCH == "arm64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le" ||
 		runtime.GOOS == "nacl" {
 		t.Skip("issue 9993; scavenger temporarily disabled on systems with physical pages larger than logical pages")
 	}
diff --git a/src/runtime/debug/heapdump_test.go b/src/runtime/debug/heapdump_test.go
index cb2f2f0..5761c01 100644
--- a/src/runtime/debug/heapdump_test.go
+++ b/src/runtime/debug/heapdump_test.go
@@ -2,12 +2,13 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package debug
+package debug_test
 
 import (
 	"io/ioutil"
 	"os"
 	"runtime"
+	. "runtime/debug"
 	"testing"
 )
 
diff --git a/src/runtime/debug/stack.go b/src/runtime/debug/stack.go
index ab12bff..5d810af 100644
--- a/src/runtime/debug/stack.go
+++ b/src/runtime/debug/stack.go
@@ -7,92 +7,24 @@
 package debug
 
 import (
-	"bytes"
-	"fmt"
-	"io/ioutil"
 	"os"
 	"runtime"
 )
 
-var (
-	dunno     = []byte("???")
-	centerDot = []byte("·")
-	dot       = []byte(".")
-	slash     = []byte("/")
-)
-
-// PrintStack prints to standard error the stack trace returned by Stack.
+// PrintStack prints to standard error the stack trace returned by runtime.Stack.
 func PrintStack() {
-	os.Stderr.Write(stack())
+	os.Stderr.Write(Stack())
 }
 
 // Stack returns a formatted stack trace of the goroutine that calls it.
-// For each routine, it includes the source line information and PC value,
-// then attempts to discover, for Go functions, the calling function or
-// method and the text of the line containing the invocation.
-//
-// Deprecated: Use package runtime's Stack instead.
+// It calls runtime.Stack with a large enough buffer to capture the entire trace.
 func Stack() []byte {
-	return stack()
-}
-
-// stack implements Stack, skipping 2 frames
-func stack() []byte {
-	buf := new(bytes.Buffer) // the returned data
-	// As we loop, we open files and read them. These variables record the currently
-	// loaded file.
-	var lines [][]byte
-	var lastFile string
-	for i := 2; ; i++ { // Caller we care about is the user, 2 frames up
-		pc, file, line, ok := runtime.Caller(i)
-		if !ok {
-			break
+	buf := make([]byte, 1024)
+	for {
+		n := runtime.Stack(buf, false)
+		if n < len(buf) {
+			return buf[:n]
 		}
-		// Print this much at least.  If we can't find the source, it won't show.
-		fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
-		if file != lastFile {
-			data, err := ioutil.ReadFile(file)
-			if err != nil {
-				continue
-			}
-			lines = bytes.Split(data, []byte{'\n'})
-			lastFile = file
-		}
-		line-- // in stack trace, lines are 1-indexed but our array is 0-indexed
-		fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line))
-	}
-	return buf.Bytes()
-}
-
-// source returns a space-trimmed slice of the n'th line.
-func source(lines [][]byte, n int) []byte {
-	if n < 0 || n >= len(lines) {
-		return dunno
-	}
-	return bytes.Trim(lines[n], " \t")
-}
-
-// function returns, if possible, the name of the function containing the PC.
-func function(pc uintptr) []byte {
-	fn := runtime.FuncForPC(pc)
-	if fn == nil {
-		return dunno
-	}
-	name := []byte(fn.Name())
-	// The name includes the path name to the package, which is unnecessary
-	// since the file name is already included.  Plus, it has center dots.
-	// That is, we see
-	//	runtime/debug.*T·ptrmethod
-	// and want
-	//	*T.ptrmethod
-	// Since the package path might contains dots (e.g. code.google.com/...),
-	// we first remove the path prefix if there is one.
-	if lastslash := bytes.LastIndex(name, slash); lastslash >= 0 {
-		name = name[lastslash+1:]
-	}
-	if period := bytes.Index(name, dot); period >= 0 {
-		name = name[period+1:]
+		buf = make([]byte, 2*len(buf))
 	}
-	name = bytes.Replace(name, centerDot, dot, -1)
-	return name
 }
diff --git a/src/runtime/debug/stack_test.go b/src/runtime/debug/stack_test.go
index 28691ee..f544372 100644
--- a/src/runtime/debug/stack_test.go
+++ b/src/runtime/debug/stack_test.go
@@ -2,9 +2,10 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package debug
+package debug_test
 
 import (
+	. "runtime/debug"
 	"strings"
 	"testing"
 )
@@ -22,16 +23,19 @@ func (t T) method() []byte {
 	The traceback should look something like this, modulo line numbers and hex constants.
 	Don't worry much about the base levels, but check the ones in our own package.
 
-		/Users/r/go/src/runtime/debug/stack_test.go:15 (0x13878)
-			(*T).ptrmethod: return Stack()
-		/Users/r/go/src/runtime/debug/stack_test.go:18 (0x138dd)
-			T.method: return t.ptrmethod()
-		/Users/r/go/src/runtime/debug/stack_test.go:23 (0x13920)
-			TestStack: b := T(0).method()
-		/Users/r/go/src/testing/testing.go:132 (0x14a7a)
-			tRunner: test.F(t)
-		/Users/r/go/src/runtime/proc.c:145 (0xc970)
-			???: runtime·unlock(&runtime·sched);
+		goroutine 10 [running]:
+		runtime/debug.Stack(0x0, 0x0, 0x0)
+			/Users/r/go/src/runtime/debug/stack.go:28 +0x80
+		runtime/debug.(*T).ptrmethod(0xc82005ee70, 0x0, 0x0, 0x0)
+			/Users/r/go/src/runtime/debug/stack_test.go:15 +0x29
+		runtime/debug.T.method(0x0, 0x0, 0x0, 0x0)
+			/Users/r/go/src/runtime/debug/stack_test.go:18 +0x32
+		runtime/debug.TestStack(0xc8201ce000)
+			/Users/r/go/src/runtime/debug/stack_test.go:37 +0x38
+		testing.tRunner(0xc8201ce000, 0x664b58)
+			/Users/r/go/src/testing/testing.go:456 +0x98
+		created by testing.RunTests
+			/Users/r/go/src/testing/testing.go:561 +0x86d
 */
 func TestStack(t *testing.T) {
 	b := T(0).method()
@@ -41,17 +45,16 @@ func TestStack(t *testing.T) {
 	}
 	n := 0
 	frame := func(line, code string) {
+		check(t, lines[n], code)
+		n++
 		check(t, lines[n], line)
 		n++
-		// The source might not be available while running the test.
-		if strings.HasPrefix(lines[n], "\t") {
-			check(t, lines[n], code)
-			n++
-		}
 	}
-	frame("src/runtime/debug/stack_test.go", "\t(*T).ptrmethod: return Stack()")
-	frame("src/runtime/debug/stack_test.go", "\tT.method: return t.ptrmethod()")
-	frame("src/runtime/debug/stack_test.go", "\tTestStack: b := T(0).method()")
+	n++
+	frame("src/runtime/debug/stack.go", "runtime/debug.Stack")
+	frame("src/runtime/debug/stack_test.go", "runtime/debug_test.(*T).ptrmethod")
+	frame("src/runtime/debug/stack_test.go", "runtime/debug_test.T.method")
+	frame("src/runtime/debug/stack_test.go", "runtime/debug_test.TestStack")
 	frame("src/testing/testing.go", "")
 }
 
diff --git a/src/runtime/debug/stubs.go b/src/runtime/debug/stubs.go
index 95b33e4..6c87ffd 100644
--- a/src/runtime/debug/stubs.go
+++ b/src/runtime/debug/stubs.go
@@ -8,12 +8,10 @@ import (
 	"time"
 )
 
-// Uses assembly to call corresponding runtime-internal functions.
+// Implemented in package runtime.
+func readGCStats(*[]time.Duration)
+func freeOSMemory()
 func setMaxStack(int) int
 func setGCPercent(int32) int32
 func setPanicOnFault(bool) bool
 func setMaxThreads(int) int
-
-// Implemented in package runtime.
-func readGCStats(*[]time.Duration)
-func freeOSMemory()
diff --git a/src/runtime/debug/stubs.s b/src/runtime/debug/stubs.s
deleted file mode 100644
index 9dc8e54..0000000
--- a/src/runtime/debug/stubs.s
+++ /dev/null
@@ -1,30 +0,0 @@
-// 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"
-
-#ifdef GOARCH_arm
-#define JMP B
-#endif
-#ifdef GOARCH_arm64
-#define JMP B
-#endif
-#ifdef GOARCH_ppc64
-#define JMP BR
-#endif
-#ifdef GOARCH_ppc64le
-#define JMP BR
-#endif
-
-TEXT ·setMaxStack(SB),NOSPLIT,$0-0
-  JMP runtime·setMaxStack(SB)
-
-TEXT ·setGCPercent(SB),NOSPLIT,$0-0
-  JMP runtime·setGCPercent(SB)
-
-TEXT ·setPanicOnFault(SB),NOSPLIT,$0-0
-  JMP runtime·setPanicOnFault(SB)
-
-TEXT ·setMaxThreads(SB),NOSPLIT,$0-0
-  JMP runtime·setMaxThreads(SB)
diff --git a/src/runtime/defs_darwin.go b/src/runtime/defs_darwin.go
index 722013b..78df4e7 100644
--- a/src/runtime/defs_darwin.go
+++ b/src/runtime/defs_darwin.go
@@ -152,7 +152,7 @@ type StackT C.struct_sigaltstack
 type Sighandler C.union___sigaction_u
 
 type Sigaction C.struct___sigaction // used in syscalls
-// type Sigaction C.struct_sigaction	// used by the C library
+type Usigaction C.struct_sigaction  // used by sigaction second argument
 type Sigval C.union_sigval
 type Siginfo C.siginfo_t
 type Timeval C.struct_timeval
diff --git a/src/runtime/defs_darwin_386.go b/src/runtime/defs_darwin_386.go
index e051301..1a5967b 100644
--- a/src/runtime/defs_darwin_386.go
+++ b/src/runtime/defs_darwin_386.go
@@ -167,6 +167,12 @@ type sigactiont struct {
 	sa_flags      int32
 }
 
+type usigactiont struct {
+	__sigaction_u [4]byte
+	sa_mask       uint32
+	sa_flags      int32
+}
+
 type siginfo struct {
 	si_signo  int32
 	si_errno  int32
diff --git a/src/runtime/defs_darwin_amd64.go b/src/runtime/defs_darwin_amd64.go
index d9d9fc5..a4ab090 100644
--- a/src/runtime/defs_darwin_amd64.go
+++ b/src/runtime/defs_darwin_amd64.go
@@ -168,6 +168,12 @@ type sigactiont struct {
 	sa_flags      int32
 }
 
+type usigactiont struct {
+	__sigaction_u [8]byte
+	sa_mask       uint32
+	sa_flags      int32
+}
+
 type siginfo struct {
 	si_signo  int32
 	si_errno  int32
diff --git a/src/runtime/defs_darwin_arm.go b/src/runtime/defs_darwin_arm.go
index b53336c..3f8dbbf 100644
--- a/src/runtime/defs_darwin_arm.go
+++ b/src/runtime/defs_darwin_arm.go
@@ -169,6 +169,12 @@ type sigactiont struct {
 	sa_flags      int32
 }
 
+type usigactiont struct {
+	__sigaction_u [4]byte
+	sa_mask       uint32
+	sa_flags      int32
+}
+
 type siginfo struct {
 	si_signo  int32
 	si_errno  int32
diff --git a/src/runtime/defs_darwin_arm64.go b/src/runtime/defs_darwin_arm64.go
index 3cc77c1..c25a41b 100644
--- a/src/runtime/defs_darwin_arm64.go
+++ b/src/runtime/defs_darwin_arm64.go
@@ -168,6 +168,12 @@ type sigactiont struct {
 	sa_flags      int32
 }
 
+type usigactiont struct {
+	__sigaction_u [8]byte
+	sa_mask       uint32
+	sa_flags      int32
+}
+
 type siginfo struct {
 	si_signo  int32
 	si_errno  int32
diff --git a/src/runtime/defs_linux_386.go b/src/runtime/defs_linux_386.go
index 7cf57c8..44d2fd1 100644
--- a/src/runtime/defs_linux_386.go
+++ b/src/runtime/defs_linux_386.go
@@ -90,6 +90,10 @@ const (
 	_EPOLL_CTL_ADD = 0x1
 	_EPOLL_CTL_DEL = 0x2
 	_EPOLL_CTL_MOD = 0x3
+
+	_AF_UNIX    = 0x1
+	_F_SETFL    = 0x4
+	_SOCK_DGRAM = 0x2
 )
 
 type fpreg struct {
@@ -218,3 +222,8 @@ type epollevent struct {
 	events uint32
 	data   [8]byte // to match amd64
 }
+
+type sockaddr_un struct {
+	family uint16
+	path   [108]byte
+}
diff --git a/src/runtime/defs_linux_amd64.go b/src/runtime/defs_linux_amd64.go
index 48aeb80..1936285 100644
--- a/src/runtime/defs_linux_amd64.go
+++ b/src/runtime/defs_linux_amd64.go
@@ -87,6 +87,10 @@ const (
 	_EPOLL_CTL_ADD = 0x1
 	_EPOLL_CTL_DEL = 0x2
 	_EPOLL_CTL_MOD = 0x3
+
+	_AF_UNIX    = 0x1
+	_F_SETFL    = 0x4
+	_SOCK_DGRAM = 0x2
 )
 
 type timespec struct {
@@ -253,3 +257,8 @@ type sigcontext struct {
 	fpstate     *fpstate1
 	__reserved1 [8]uint64
 }
+
+type sockaddr_un struct {
+	family uint16
+	path   [108]byte
+}
diff --git a/src/runtime/defs_linux_arm64.go b/src/runtime/defs_linux_arm64.go
index 1a4d884..d1b1a36 100644
--- a/src/runtime/defs_linux_arm64.go
+++ b/src/runtime/defs_linux_arm64.go
@@ -87,6 +87,10 @@ const (
 	_EPOLL_CTL_ADD = 0x1
 	_EPOLL_CTL_DEL = 0x2
 	_EPOLL_CTL_MOD = 0x3
+
+	_AF_UNIX    = 0x1
+	_F_SETFL    = 0x4
+	_SOCK_DGRAM = 0x2
 )
 
 type timespec struct {
@@ -167,6 +171,11 @@ type sigcontext struct {
 	__reserved [4096]byte
 }
 
+type sockaddr_un struct {
+	family uint16
+	path   [108]byte
+}
+
 type ucontext struct {
 	uc_flags    uint64
 	uc_link     *ucontext
diff --git a/src/runtime/defs_linux_mips64x.go b/src/runtime/defs_linux_mips64x.go
new file mode 100644
index 0000000..bb3cd98
--- /dev/null
+++ b/src/runtime/defs_linux_mips64x.go
@@ -0,0 +1,183 @@
+// +build mips64 mips64le
+// +build linux
+
+package runtime
+
+const (
+	_EINTR  = 0x4
+	_EAGAIN = 0xb
+	_ENOMEM = 0xc
+
+	_PROT_NONE  = 0x0
+	_PROT_READ  = 0x1
+	_PROT_WRITE = 0x2
+	_PROT_EXEC  = 0x4
+
+	_MAP_ANON    = 0x800
+	_MAP_PRIVATE = 0x2
+	_MAP_FIXED   = 0x10
+
+	_MADV_DONTNEED   = 0x4
+	_MADV_HUGEPAGE   = 0xe
+	_MADV_NOHUGEPAGE = 0xf
+
+	_SA_RESTART = 0x10000000
+	_SA_ONSTACK = 0x8000000
+	_SA_SIGINFO = 0x8
+
+	_SIGHUP    = 0x1
+	_SIGINT    = 0x2
+	_SIGQUIT   = 0x3
+	_SIGILL    = 0x4
+	_SIGTRAP   = 0x5
+	_SIGABRT   = 0x6
+	_SIGEMT    = 0x7
+	_SIGFPE    = 0x8
+	_SIGKILL   = 0x9
+	_SIGBUS    = 0xa
+	_SIGSEGV   = 0xb
+	_SIGSYS    = 0xc
+	_SIGPIPE   = 0xd
+	_SIGALRM   = 0xe
+	_SIGUSR1   = 0x10
+	_SIGUSR2   = 0x11
+	_SIGCHLD   = 0x12
+	_SIGPWR    = 0x13
+	_SIGWINCH  = 0x14
+	_SIGURG    = 0x15
+	_SIGIO     = 0x16
+	_SIGSTOP   = 0x17
+	_SIGTSTP   = 0x18
+	_SIGCONT   = 0x19
+	_SIGTTIN   = 0x1a
+	_SIGTTOU   = 0x1b
+	_SIGVTALRM = 0x1c
+	_SIGPROF   = 0x1d
+	_SIGXCPU   = 0x1e
+	_SIGXFSZ   = 0x1f
+
+	_FPE_INTDIV = 0x1
+	_FPE_INTOVF = 0x2
+	_FPE_FLTDIV = 0x3
+	_FPE_FLTOVF = 0x4
+	_FPE_FLTUND = 0x5
+	_FPE_FLTRES = 0x6
+	_FPE_FLTINV = 0x7
+	_FPE_FLTSUB = 0x8
+
+	_BUS_ADRALN = 0x1
+	_BUS_ADRERR = 0x2
+	_BUS_OBJERR = 0x3
+
+	_SEGV_MAPERR = 0x1
+	_SEGV_ACCERR = 0x2
+
+	_ITIMER_REAL    = 0x0
+	_ITIMER_VIRTUAL = 0x1
+	_ITIMER_PROF    = 0x2
+
+	_EPOLLIN       = 0x1
+	_EPOLLOUT      = 0x4
+	_EPOLLERR      = 0x8
+	_EPOLLHUP      = 0x10
+	_EPOLLRDHUP    = 0x2000
+	_EPOLLET       = 0x80000000
+	_EPOLL_CLOEXEC = 0x80000
+	_EPOLL_CTL_ADD = 0x1
+	_EPOLL_CTL_DEL = 0x2
+	_EPOLL_CTL_MOD = 0x3
+)
+
+//struct Sigset {
+//	uint64	sig[1];
+//};
+//typedef uint64 Sigset;
+
+type timespec struct {
+	tv_sec  int64
+	tv_nsec int64
+}
+
+func (ts *timespec) set_sec(x int64) {
+	ts.tv_sec = x
+}
+
+func (ts *timespec) set_nsec(x int32) {
+	ts.tv_nsec = int64(x)
+}
+
+type timeval struct {
+	tv_sec  int64
+	tv_usec int64
+}
+
+func (tv *timeval) set_usec(x int32) {
+	tv.tv_usec = int64(x)
+}
+
+type sigactiont struct {
+	sa_flags   uint32
+	sa_handler uintptr
+	sa_mask    [2]uint64
+	// linux header does not have sa_restorer field,
+	// but it is used in setsig(). it is no harm to put it here
+	sa_restorer uintptr
+}
+
+type siginfo struct {
+	si_signo int32
+	si_code  int32
+	si_errno int32
+	__pad0   [1]int32
+	// below here is a union; si_addr is the only field we use
+	si_addr uint64
+}
+
+type itimerval struct {
+	it_interval timeval
+	it_value    timeval
+}
+
+type epollevent struct {
+	events    uint32
+	pad_cgo_0 [4]byte
+	data      [8]byte // unaligned uintptr
+}
+
+const (
+	_O_RDONLY    = 0x0
+	_O_CLOEXEC   = 0x80000
+	_SA_RESTORER = 0
+)
+
+type sigaltstackt struct {
+	ss_sp    *byte
+	ss_size  uintptr
+	ss_flags int32
+}
+
+type sigcontext struct {
+	sc_regs      [32]uint64
+	sc_fpregs    [32]uint64
+	sc_mdhi      uint64
+	sc_hi1       uint64
+	sc_hi2       uint64
+	sc_hi3       uint64
+	sc_mdlo      uint64
+	sc_lo1       uint64
+	sc_lo2       uint64
+	sc_lo3       uint64
+	sc_pc        uint64
+	sc_fpc_csr   uint32
+	sc_used_math uint32
+	sc_dsp       uint32
+	sc_reserved  uint32
+}
+
+type ucontext struct {
+	uc_flags    uint64
+	uc_link     *ucontext
+	uc_stack    sigaltstackt
+	uc_mcontext sigcontext
+	uc_sigmask  uint64
+}
diff --git a/src/runtime/duff_amd64.s b/src/runtime/duff_amd64.s
index 0b51228..6ed7f65 100644
--- a/src/runtime/duff_amd64.s
+++ b/src/runtime/duff_amd64.s
@@ -5,837 +5,423 @@
 #include "textflag.h"
 
 TEXT runtime·duffzero(SB), NOSPLIT, $0-0
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	MOVQ	AX,(DI)
-	MOVQ	AX,8(DI)
-	MOVQ	AX,16(DI)
-	MOVQ	AX,24(DI)
-	ADDQ	$32,DI
-
-	STOSQ
-	STOSQ
-	STOSQ
-	STOSQ
+	MOVUPS	X0,(DI)
+	MOVUPS	X0,16(DI)
+	MOVUPS	X0,32(DI)
+	MOVUPS	X0,48(DI)
+	ADDQ	$64,DI
+
+	MOVUPS	X0,(DI)
+	MOVUPS	X0,16(DI)
+	MOVUPS	X0,32(DI)
+	MOVUPS	X0,48(DI)
+	ADDQ	$64,DI
+
+	MOVUPS	X0,(DI)
+	MOVUPS	X0,16(DI)
+	MOVUPS	X0,32(DI)
+	MOVUPS	X0,48(DI)
+	ADDQ	$64,DI
+
+	MOVUPS	X0,(DI)
+	MOVUPS	X0,16(DI)
+	MOVUPS	X0,32(DI)
+	MOVUPS	X0,48(DI)
+	ADDQ	$64,DI
+
+	MOVUPS	X0,(DI)
+	MOVUPS	X0,16(DI)
+	MOVUPS	X0,32(DI)
+	MOVUPS	X0,48(DI)
+	ADDQ	$64,DI
+
+	MOVUPS	X0,(DI)
+	MOVUPS	X0,16(DI)
+	MOVUPS	X0,32(DI)
+	MOVUPS	X0,48(DI)
+	ADDQ	$64,DI
+
+	MOVUPS	X0,(DI)
+	MOVUPS	X0,16(DI)
+	MOVUPS	X0,32(DI)
+	MOVUPS	X0,48(DI)
+	ADDQ	$64,DI
+
+	MOVUPS	X0,(DI)
+	MOVUPS	X0,16(DI)
+	MOVUPS	X0,32(DI)
+	MOVUPS	X0,48(DI)
+	ADDQ	$64,DI
+
+	MOVUPS	X0,(DI)
+	MOVUPS	X0,16(DI)
+	MOVUPS	X0,32(DI)
+	MOVUPS	X0,48(DI)
+	ADDQ	$64,DI
+
+	MOVUPS	X0,(DI)
+	MOVUPS	X0,16(DI)
+	MOVUPS	X0,32(DI)
+	MOVUPS	X0,48(DI)
+	ADDQ	$64,DI
+
+	MOVUPS	X0,(DI)
+	MOVUPS	X0,16(DI)
+	MOVUPS	X0,32(DI)
+	MOVUPS	X0,48(DI)
+	ADDQ	$64,DI
+
+	MOVUPS	X0,(DI)
+	MOVUPS	X0,16(DI)
+	MOVUPS	X0,32(DI)
+	MOVUPS	X0,48(DI)
+	ADDQ	$64,DI
+
+	MOVUPS	X0,(DI)
+	MOVUPS	X0,16(DI)
+	MOVUPS	X0,32(DI)
+	MOVUPS	X0,48(DI)
+	ADDQ	$64,DI
+
+	MOVUPS	X0,(DI)
+	MOVUPS	X0,16(DI)
+	MOVUPS	X0,32(DI)
+	MOVUPS	X0,48(DI)
+	ADDQ	$64,DI
+
+	MOVUPS	X0,(DI)
+	MOVUPS	X0,16(DI)
+	MOVUPS	X0,32(DI)
+	MOVUPS	X0,48(DI)
+	ADDQ	$64,DI
+
+	MOVUPS	X0,(DI)
+	MOVUPS	X0,16(DI)
+	MOVUPS	X0,32(DI)
+	MOVUPS	X0,48(DI)
+	ADDQ	$64,DI
+
 	RET
 
 TEXT runtime·duffcopy(SB), NOSPLIT, $0-0
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
-
-	MOVQ	(SI), CX
-	ADDQ	$8, SI
-	MOVQ	CX, (DI)
-	ADDQ	$8, DI
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
+
+	MOVUPS	(SI), X0
+	ADDQ	$16, SI
+	MOVUPS	X0, (DI)
+	ADDQ	$16, DI
 
 	RET
diff --git a/src/runtime/duff_mips64x.s b/src/runtime/duff_mips64x.s
new file mode 100644
index 0000000..062e04a
--- /dev/null
+++ b/src/runtime/duff_mips64x.s
@@ -0,0 +1,268 @@
+// AUTO-GENERATED by mkduff.go
+// Run go generate from src/runtime to update.
+// See mkduff.go for comments.
+
+// +build mips64 mips64le
+
+#include "textflag.h"
+
+TEXT runtime·duffzero(SB), NOSPLIT, $-8-0
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	MOVV	R0, 8(R1)
+	ADDV	$8, R1
+	RET
+
+// TODO: Implement runtime·duffcopy.
diff --git a/src/runtime/duff_ppc64x.s b/src/runtime/duff_ppc64x.s
index 14bc33e..c8204c4 100644
--- a/src/runtime/duff_ppc64x.s
+++ b/src/runtime/duff_ppc64x.s
@@ -6,7 +6,7 @@
 
 #include "textflag.h"
 
-TEXT runtime·duffzero(SB), NOSPLIT, $-8-0
+TEXT runtime·duffzero(SB), NOSPLIT|NOFRAME, $0-0
 	MOVDU	R0, 8(R3)
 	MOVDU	R0, 8(R3)
 	MOVDU	R0, 8(R3)
diff --git a/src/runtime/env_plan9.go b/src/runtime/env_plan9.go
index 0e2588b..2daba0c 100644
--- a/src/runtime/env_plan9.go
+++ b/src/runtime/env_plan9.go
@@ -40,8 +40,8 @@ func gogetenv(key string) string {
 	}
 
 	var s string
-	sp := (*_string)(unsafe.Pointer(&s))
-	sp.str = &p[0]
+	sp := stringStructOf(&s)
+	sp.str = unsafe.Pointer(&p[0])
 	sp.len = int(r)
 	return s
 }
diff --git a/src/runtime/env_posix.go b/src/runtime/env_posix.go
index 5e49287..c3b06f7 100644
--- a/src/runtime/env_posix.go
+++ b/src/runtime/env_posix.go
@@ -48,7 +48,6 @@ func syscall_unsetenv_c(k string) {
 
 func cstring(s string) unsafe.Pointer {
 	p := make([]byte, len(s)+1)
-	sp := (*_string)(unsafe.Pointer(&s))
-	memmove(unsafe.Pointer(&p[0]), unsafe.Pointer(sp.str), uintptr(len(s)))
+	copy(p, s)
 	return unsafe.Pointer(&p[0])
 }
diff --git a/src/runtime/error.go b/src/runtime/error.go
index 4280306..de07bcb 100644
--- a/src/runtime/error.go
+++ b/src/runtime/error.go
@@ -4,8 +4,6 @@
 
 package runtime
 
-import "unsafe"
-
 // The Error interface identifies a run time error.
 type Error interface {
 	error
@@ -57,7 +55,7 @@ type stringer interface {
 }
 
 func typestring(x interface{}) string {
-	e := (*eface)(unsafe.Pointer(&x))
+	e := efaceOf(&x)
 	return *e._type._string
 }
 
diff --git a/src/runtime/export_linux_test.go b/src/runtime/export_linux_test.go
index c8b9746..61d6ae4 100644
--- a/src/runtime/export_linux_test.go
+++ b/src/runtime/export_linux_test.go
@@ -7,3 +7,4 @@
 package runtime
 
 var NewOSProc0 = newosproc0
+var Mincore = mincore
diff --git a/src/runtime/export_mmap_test.go b/src/runtime/export_mmap_test.go
new file mode 100644
index 0000000..11ea076
--- /dev/null
+++ b/src/runtime/export_mmap_test.go
@@ -0,0 +1,15 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+// Export guts for testing.
+
+package runtime
+
+var Mmap = mmap
+
+const ENOMEM = _ENOMEM
+const MAP_ANON = _MAP_ANON
+const MAP_PRIVATE = _MAP_PRIVATE
diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go
index f14dc30..5400c1d 100644
--- a/src/runtime/export_test.go
+++ b/src/runtime/export_test.go
@@ -6,7 +6,11 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 var Fadd64 = fadd64
 var Fsub64 = fsub64
@@ -22,10 +26,12 @@ var Sqrt = sqrt
 var Entersyscall = entersyscall
 var Exitsyscall = exitsyscall
 var LockedOSThread = lockedOSThread
-var Xadduintptr = xadduintptr
+var Xadduintptr = atomic.Xadduintptr
 
 var FuncPC = funcPC
 
+var Fastlog2 = fastlog2
+
 type LFNode struct {
 	Next    uint64
 	Pushcnt uintptr
@@ -110,7 +116,7 @@ func GostringW(w []uint16) (s string) {
 var Gostringnocopy = gostringnocopy
 var Maxstring = &maxstring
 
-type Uintreg uintreg
+type Uintreg sys.Uintreg
 
 var Open = open
 var Close = closefd
@@ -120,21 +126,21 @@ var Write = write
 func Envs() []string     { return envs }
 func SetEnvs(e []string) { envs = e }
 
-var BigEndian = _BigEndian
+var BigEndian = sys.BigEndian
 
 // For benchmarking.
 
 func BenchSetType(n int, x interface{}) {
-	e := *(*eface)(unsafe.Pointer(&x))
+	e := *efaceOf(&x)
 	t := e._type
 	var size uintptr
 	var p unsafe.Pointer
 	switch t.kind & kindMask {
-	case _KindPtr:
+	case kindPtr:
 		t = (*ptrtype)(unsafe.Pointer(t)).elem
 		size = t.size
 		p = e.data
-	case _KindSlice:
+	case kindSlice:
 		slice := *(*struct {
 			ptr      unsafe.Pointer
 			len, cap uintptr
@@ -151,7 +157,17 @@ func BenchSetType(n int, x interface{}) {
 	})
 }
 
-const PtrSize = ptrSize
+const PtrSize = sys.PtrSize
 
 var TestingAssertE2I2GC = &testingAssertE2I2GC
 var TestingAssertE2T2GC = &testingAssertE2T2GC
+
+var ForceGCPeriod = &forcegcperiod
+
+// SetTracebackEnv is like runtime/debug.SetTraceback, but it raises
+// the "environment" traceback level, so later calls to
+// debug.SetTraceback (e.g., from testing timeouts) can't lower it.
+func SetTracebackEnv(level string) {
+	setTraceback(level)
+	traceback_env = traceback_cache
+}
diff --git a/src/runtime/export_windows_test.go b/src/runtime/export_windows_test.go
index 61fcef9..f712c6f 100644
--- a/src/runtime/export_windows_test.go
+++ b/src/runtime/export_windows_test.go
@@ -6,4 +6,12 @@
 
 package runtime
 
+import "unsafe"
+
 var TestingWER = &testingWER
+
+func NumberOfProcessors() int32 {
+	var info systeminfo
+	stdcall1(_GetSystemInfo, uintptr(unsafe.Pointer(&info)))
+	return int32(info.dwnumberofprocessors)
+}
diff --git a/src/runtime/extern.go b/src/runtime/extern.go
index cdb66ba..2c98482 100644
--- a/src/runtime/extern.go
+++ b/src/runtime/extern.go
@@ -27,6 +27,13 @@ It is a comma-separated list of name=val pairs setting these named variables:
 	allocfreetrace: setting allocfreetrace=1 causes every allocation to be
 	profiled and a stack trace printed on each object's allocation and free.
 
+	cgocheck: setting cgocheck=0 disables all checks for packages
+	using cgo to incorrectly pass Go pointers to non-Go code.
+	Setting cgocheck=1 (the default) enables relatively cheap
+	checks that may miss some errors.  Setting cgocheck=2 enables
+	expensive checks that should not miss any errors, but will
+	cause your program to run slower.
+
 	efence: setting efence=1 causes the allocator to run in a mode
 	where each object is allocated on a unique page and addresses are
 	never recycled.
@@ -59,7 +66,7 @@ It is a comma-separated list of name=val pairs setting these named variables:
 	length of the pause. Setting gctrace=2 emits the same summary but also
 	repeats each collection. The format of this line is subject to change.
 	Currently, it is:
-		gc # @#s #%: #+...+# ms clock, #+...+# ms cpu, #->#-># MB, # MB goal, # P
+		gc # @#s #%: #+#+# ms clock, #+#/#/#+# ms cpu, #->#-># MB, # MB goal, # P
 	where the fields are as follows:
 		gc #        the GC number, incremented at each GC
 		@#s         time in seconds since program start
@@ -68,9 +75,9 @@ It is a comma-separated list of name=val pairs setting these named variables:
 		#->#-># MB  heap size at GC start, at GC end, and live heap
 		# MB goal   goal heap size
 		# P         number of processors used
-	The phases are stop-the-world (STW) sweep termination, scan,
-	synchronize Ps, mark, and STW mark termination. The CPU times
-	for mark are broken down in to assist time (GC performed in
+	The phases are stop-the-world (STW) sweep termination, concurrent
+	mark and scan, and STW mark termination. The CPU times
+	for mark/scan are broken down in to assist time (GC performed in
 	line with allocation), background GC time, and idle GC time.
 	If the line ends with "(forced)", this GC was forced by a
 	runtime.GC() call and all phases are STW.
@@ -98,6 +105,9 @@ It is a comma-separated list of name=val pairs setting these named variables:
 	schedtrace: setting schedtrace=X causes the scheduler to emit a single line to standard
 	error every X milliseconds, summarizing the scheduler state.
 
+The net and net/http packages also refer to debugging variables in GODEBUG.
+See the documentation for those packages for details.
+
 The GOMAXPROCS variable limits the number of operating system threads that
 can execute user-level Go code simultaneously. There is no limit to the number of threads
 that can be blocked in system calls on behalf of Go code; those do not count against
@@ -106,15 +116,24 @@ the limit.
 
 The GOTRACEBACK variable controls the amount of output generated when a Go
 program fails due to an unrecovered panic or an unexpected runtime condition.
-By default, a failure prints a stack trace for every extant goroutine, eliding functions
-internal to the run-time system, and then exits with exit code 2.
-If GOTRACEBACK=0, the per-goroutine stack traces are omitted entirely.
-If GOTRACEBACK=1, the default behavior is used.
-If GOTRACEBACK=2, the per-goroutine stack traces include run-time functions.
-If GOTRACEBACK=crash, the per-goroutine stack traces include run-time functions,
-and if possible the program crashes in an operating-specific manner instead of
-exiting. For example, on Unix systems, the program raises SIGABRT to trigger a
-core dump.
+By default, a failure prints a stack trace for the current goroutine,
+eliding functions internal to the run-time system, and then exits with exit code 2.
+The failure prints stack traces for all goroutines if there is no current goroutine
+or the failure is internal to the run-time.
+GOTRACEBACK=none omits the goroutine stack traces entirely.
+GOTRACEBACK=single (the default) behaves as described above.
+GOTRACEBACK=all adds stack traces for all user-created goroutines.
+GOTRACEBACK=system is like ``all'' but adds stack frames for run-time functions
+and shows goroutines created internally by the run-time.
+GOTRACEBACK=crash is like ``system'' but crashes in an operating system-specific
+manner instead of exiting. For example, on Unix systems, the crash raises
+SIGABRT to trigger a core dump.
+For historical reasons, the GOTRACEBACK settings 0, 1, and 2 are synonyms for
+none, all, and system, respectively.
+The runtime/debug package's SetTraceback function allows increasing the
+amount of output at run time, but it cannot reduce the amount below that
+specified by the environment variable.
+See https://golang.org/pkg/runtime/debug/#SetTraceback.
 
 The GOARCH, GOOS, GOPATH, and GOROOT environment variables complete
 the set of Go environment variables. They influence the building of Go programs
@@ -125,6 +144,8 @@ of the run-time system.
 */
 package runtime
 
+import "runtime/internal/sys"
+
 // Caller reports file and line number information about function invocations on
 // the calling goroutine's stack.  The argument skip is the number of stack frames
 // to ascend, with 0 identifying the caller of Caller.  (For historical reasons the
@@ -194,20 +215,20 @@ func GOROOT() string {
 	if s != "" {
 		return s
 	}
-	return defaultGoroot
+	return sys.DefaultGoroot
 }
 
 // Version returns the Go tree's version string.
 // It is either the commit hash and date at the time of the build or,
 // when possible, a release tag like "go1.3".
 func Version() string {
-	return theVersion
+	return sys.TheVersion
 }
 
 // GOOS is the running program's operating system target:
 // one of darwin, freebsd, linux, and so on.
-const GOOS string = theGoos
+const GOOS string = sys.TheGoos
 
 // GOARCH is the running program's architecture target:
 // 386, amd64, or arm.
-const GOARCH string = theGoarch
+const GOARCH string = sys.TheGoarch
diff --git a/src/runtime/fastlog2.go b/src/runtime/fastlog2.go
new file mode 100644
index 0000000..b22e825
--- /dev/null
+++ b/src/runtime/fastlog2.go
@@ -0,0 +1,33 @@
+// Copyright 2015 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 runtime
+
+import "unsafe"
+
+// fastlog2 implements a fast approximation to the base 2 log of a
+// float64. This is used to compute a geometric distribution for heap
+// sampling, without introducing dependences into package math. This
+// uses a very rough approximation using the float64 exponent and the
+// first 25 bits of the mantissa. The top 5 bits of the mantissa are
+// used to load limits from a table of constants and the rest are used
+// to scale linearly between them.
+func fastlog2(x float64) float64 {
+	const fastlogScaleBits = 20
+	const fastlogScaleRatio = 1.0 / (1 << fastlogScaleBits)
+
+	xBits := float64bits(x)
+	// Extract the exponent from the IEEE float64, and index a constant
+	// table with the first 10 bits from the mantissa.
+	xExp := int64((xBits>>52)&0x7FF) - 1023
+	xManIndex := (xBits >> (52 - fastlogNumBits)) % (1 << fastlogNumBits)
+	xManScale := (xBits >> (52 - fastlogNumBits - fastlogScaleBits)) % (1 << fastlogScaleBits)
+
+	low, high := fastlog2Table[xManIndex], fastlog2Table[xManIndex+1]
+	return float64(xExp) + low + (high-low)*float64(xManScale)*fastlogScaleRatio
+}
+
+// float64bits returns the IEEE 754 binary representation of f.
+// Taken from math.Float64bits to avoid dependences into package math.
+func float64bits(f float64) uint64 { return *(*uint64)(unsafe.Pointer(&f)) }
diff --git a/src/runtime/fastlog2_test.go b/src/runtime/fastlog2_test.go
new file mode 100644
index 0000000..14f6c90
--- /dev/null
+++ b/src/runtime/fastlog2_test.go
@@ -0,0 +1,34 @@
+// Copyright 2015 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 runtime_test
+
+import (
+	"math"
+	"runtime"
+	"testing"
+)
+
+func TestFastLog2(t *testing.T) {
+	// Compute the euclidean distance between math.Log2 and the FastLog2
+	// implementation over the range of interest for heap sampling.
+	const randomBitCount = 26
+	var e float64
+
+	inc := 1
+	if testing.Short() {
+		// Check 1K total values, down from 64M.
+		inc = 1 << 16
+	}
+	for i := 1; i < 1<<randomBitCount; i += inc {
+		l, fl := math.Log2(float64(i)), runtime.Fastlog2(float64(i))
+		d := l - fl
+		e += d * d
+	}
+	e = math.Sqrt(e)
+
+	if e > 1.0 {
+		t.Fatalf("imprecision on fastlog2 implementation, want <=1.0, got %f", e)
+	}
+}
diff --git a/src/runtime/fastlog2table.go b/src/runtime/fastlog2table.go
new file mode 100644
index 0000000..c36d583
--- /dev/null
+++ b/src/runtime/fastlog2table.go
@@ -0,0 +1,43 @@
+// AUTO-GENERATED by mkfastlog2table.go
+// Run go generate from src/runtime to update.
+// See mkfastlog2table.go for comments.
+
+package runtime
+
+const fastlogNumBits = 5
+
+var fastlog2Table = [1<<fastlogNumBits + 1]float64{
+	0,
+	0.0443941193584535,
+	0.08746284125033943,
+	0.12928301694496647,
+	0.16992500144231248,
+	0.2094533656289499,
+	0.24792751344358555,
+	0.28540221886224837,
+	0.3219280948873623,
+	0.3575520046180837,
+	0.39231742277876036,
+	0.4262647547020979,
+	0.4594316186372973,
+	0.4918530963296748,
+	0.5235619560570128,
+	0.5545888516776374,
+	0.5849625007211563,
+	0.6147098441152082,
+	0.6438561897747247,
+	0.6724253419714956,
+	0.7004397181410922,
+	0.7279204545631992,
+	0.7548875021634686,
+	0.7813597135246596,
+	0.8073549220576042,
+	0.8328900141647417,
+	0.8579809951275721,
+	0.8826430493618412,
+	0.9068905956085185,
+	0.9307373375628862,
+	0.9541963103868752,
+	0.9772799234999164,
+	1,
+}
diff --git a/src/runtime/funcdata.h b/src/runtime/funcdata.h
index ce62dab..375a881 100644
--- a/src/runtime/funcdata.h
+++ b/src/runtime/funcdata.h
@@ -14,7 +14,6 @@
 
 #define FUNCDATA_ArgsPointerMaps 0 /* garbage collector blocks */
 #define FUNCDATA_LocalsPointerMaps 1
-#define FUNCDATA_DeadValueMaps 2
 
 // Pseudo-assembly statements.
 
@@ -48,13 +47,3 @@
 // assembly code without an explicit specification).
 // This value is generated by the compiler, assembler, or linker.
 #define ArgsSizeUnknown 0x80000000
-
-/*c2go
-enum {
-	PCDATA_StackMapIndex = 0,
-	FUNCDATA_ArgsPointerMaps = 0,
-	FUNCDATA_LocalsPointerMaps = 1,
-	FUNCDATA_DeadValueMaps = 2,
-	ArgsSizeUnknown = 0x80000000,
-};
-*/
diff --git a/src/runtime/futex_test.go b/src/runtime/futex_test.go
index b85249a..8504396 100644
--- a/src/runtime/futex_test.go
+++ b/src/runtime/futex_test.go
@@ -13,6 +13,8 @@ package runtime_test
 
 import (
 	"runtime"
+	"sync"
+	"sync/atomic"
 	"testing"
 	"time"
 )
@@ -21,12 +23,12 @@ type futexsleepTest struct {
 	mtx uint32
 	ns  int64
 	msg string
-	ch  chan futexsleepTest
+	ch  chan *futexsleepTest
 }
 
 var futexsleepTests = []futexsleepTest{
-	beforeY2038: {mtx: 0, ns: 86400 * 1e9, msg: "before the year 2038", ch: make(chan futexsleepTest, 1)},
-	afterY2038:  {mtx: 0, ns: (1<<31 + 100) * 1e9, msg: "after the year 2038", ch: make(chan futexsleepTest, 1)},
+	beforeY2038: {mtx: 0, ns: 86400 * 1e9, msg: "before the year 2038"},
+	afterY2038:  {mtx: 0, ns: (1<<31 + 100) * 1e9, msg: "after the year 2038"},
 }
 
 const (
@@ -42,12 +44,18 @@ func TestFutexsleep(t *testing.T) {
 	}
 
 	start := time.Now()
-	for _, tt := range futexsleepTests {
-		go func(tt futexsleepTest) {
+	var wg sync.WaitGroup
+	for i := range futexsleepTests {
+		tt := &futexsleepTests[i]
+		tt.mtx = 0
+		tt.ch = make(chan *futexsleepTest, 1)
+		wg.Add(1)
+		go func(tt *futexsleepTest) {
 			runtime.Entersyscall(0)
-			runtime.Futexsleep(&tt.mtx, tt.mtx, tt.ns)
+			runtime.Futexsleep(&tt.mtx, 0, tt.ns)
 			runtime.Exitsyscall(0)
 			tt.ch <- tt
+			wg.Done()
 		}(tt)
 	}
 loop:
@@ -71,7 +79,10 @@ loop:
 			break loop
 		}
 	}
-	for _, tt := range futexsleepTests {
+	for i := range futexsleepTests {
+		tt := &futexsleepTests[i]
+		atomic.StoreUint32(&tt.mtx, 1)
 		runtime.Futexwakeup(&tt.mtx, 1)
 	}
+	wg.Wait()
 }
diff --git a/src/runtime/gc_test.go b/src/runtime/gc_test.go
index 6c9b314..c8c96bb 100644
--- a/src/runtime/gc_test.go
+++ b/src/runtime/gc_test.go
@@ -19,59 +19,13 @@ func TestGcSys(t *testing.T) {
 	if os.Getenv("GOGC") == "off" {
 		t.Skip("skipping test; GOGC=off in environment")
 	}
-	data := struct{ Short bool }{testing.Short()}
-	got := executeTest(t, testGCSysSource, &data)
+	got := runTestProg(t, "testprog", "GCSys")
 	want := "OK\n"
 	if got != want {
 		t.Fatalf("expected %q, but got %q", want, got)
 	}
 }
 
-const testGCSysSource = `
-package main
-
-import (
-	"fmt"
-	"runtime"
-)
-
-func main() {
-	runtime.GOMAXPROCS(1)
-	memstats := new(runtime.MemStats)
-	runtime.GC()
-	runtime.ReadMemStats(memstats)
-	sys := memstats.Sys
-
-	runtime.MemProfileRate = 0 // disable profiler
-
-	itercount := 1000000
-{{if .Short}}
-	itercount = 100000
-{{end}}
-	for i := 0; i < itercount; i++ {
-		workthegc()
-	}
-
-	// Should only be using a few MB.
-	// We allocated 100 MB or (if not short) 1 GB.
-	runtime.ReadMemStats(memstats)
-	if sys > memstats.Sys {
-		sys = 0
-	} else {
-		sys = memstats.Sys - sys
-	}
-	if sys > 16<<20 {
-		fmt.Printf("using too much memory: %d bytes\n", sys)
-		return
-	}
-	fmt.Printf("OK\n")
-}
-
-func workthegc() []byte {
-	return make([]byte, 1029)
-}
-`
-
 func TestGcDeepNesting(t *testing.T) {
 	type T [2][2][2][2][2][2][2][2][2][2]*int
 	a := new(T)
@@ -199,6 +153,37 @@ func TestHugeGCInfo(t *testing.T) {
 	}
 }
 
+func TestPeriodicGC(t *testing.T) {
+	// Make sure we're not in the middle of a GC.
+	runtime.GC()
+
+	var ms1, ms2 runtime.MemStats
+	runtime.ReadMemStats(&ms1)
+
+	// Make periodic GC run continuously.
+	orig := *runtime.ForceGCPeriod
+	*runtime.ForceGCPeriod = 0
+
+	// Let some periodic GCs happen. In a heavily loaded system,
+	// it's possible these will be delayed, so this is designed to
+	// succeed quickly if things are working, but to give it some
+	// slack if things are slow.
+	var numGCs uint32
+	const want = 2
+	for i := 0; i < 20 && numGCs < want; i++ {
+		time.Sleep(5 * time.Millisecond)
+
+		// Test that periodic GC actually happened.
+		runtime.ReadMemStats(&ms2)
+		numGCs = ms2.NumGC - ms1.NumGC
+	}
+	*runtime.ForceGCPeriod = orig
+
+	if numGCs < want {
+		t.Fatalf("no periodic GC: got %v GCs, want >= 2", numGCs)
+	}
+}
+
 func BenchmarkSetTypePtr(b *testing.B) {
 	benchSetType(b, new(*byte))
 }
@@ -480,9 +465,11 @@ func TestAssertE2T2Liveness(t *testing.T) {
 	testIfaceEqual(io.EOF)
 }
 
+var a bool
+
+//go:noinline
 func testIfaceEqual(x interface{}) {
 	if x == "abc" {
-		// Prevent inlining
-		panic("")
+		a = true
 	}
 }
diff --git a/src/runtime/gcinfo_test.go b/src/runtime/gcinfo_test.go
index f330bf2..edb6361 100644
--- a/src/runtime/gcinfo_test.go
+++ b/src/runtime/gcinfo_test.go
@@ -144,7 +144,7 @@ func infoBigStruct() []byte {
 			typeScalar, typeScalar, typeScalar, typeScalar, // t int; y uint16; u uint64
 			typePointer, typeScalar, // i string
 		}
-	case "arm64", "amd64", "ppc64", "ppc64le":
+	case "arm64", "amd64", "mips64", "mips64le", "ppc64", "ppc64le":
 		return []byte{
 			typePointer,                        // q *int
 			typeScalar, typeScalar, typeScalar, // w byte; e [17]byte
diff --git a/src/runtime/gengoos.go b/src/runtime/gengoos.go
deleted file mode 100644
index 06621c8..0000000
--- a/src/runtime/gengoos.go
+++ /dev/null
@@ -1,84 +0,0 @@
-// 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.
-
-// +build ignore
-
-package main
-
-import (
-	"bytes"
-	"fmt"
-	"io/ioutil"
-	"log"
-	"strconv"
-	"strings"
-)
-
-var gooses, goarches []string
-
-func main() {
-	data, err := ioutil.ReadFile("../go/build/syslist.go")
-	if err != nil {
-		log.Fatal(err)
-	}
-	const (
-		goosPrefix   = `const goosList = `
-		goarchPrefix = `const goarchList = `
-	)
-	for _, line := range strings.Split(string(data), "\n") {
-		if strings.HasPrefix(line, goosPrefix) {
-			text, err := strconv.Unquote(strings.TrimPrefix(line, goosPrefix))
-			if err != nil {
-				log.Fatalf("parsing goosList %#q: %v", strings.TrimPrefix(line, goosPrefix), err)
-			}
-			gooses = strings.Fields(text)
-		}
-		if strings.HasPrefix(line, goarchPrefix) {
-			text, err := strconv.Unquote(strings.TrimPrefix(line, goarchPrefix))
-			if err != nil {
-				log.Fatal("parsing goarchList: %v", err)
-			}
-			goarches = strings.Fields(text)
-		}
-	}
-
-	for _, target := range gooses {
-		var buf bytes.Buffer
-		fmt.Fprintf(&buf, "// generated by gengoos.go using 'go generate'\n\n")
-		if target == "linux" {
-			fmt.Fprintf(&buf, "// +build !android\n\n") // must explicitly exclude android for linux
-		}
-		fmt.Fprintf(&buf, "package runtime\n\n")
-		fmt.Fprintf(&buf, "const theGoos = `%s`\n\n", target)
-		for _, goos := range gooses {
-			value := 0
-			if goos == target {
-				value = 1
-			}
-			fmt.Fprintf(&buf, "const goos_%s = %d\n", goos, value)
-		}
-		err := ioutil.WriteFile("zgoos_"+target+".go", buf.Bytes(), 0666)
-		if err != nil {
-			log.Fatal(err)
-		}
-	}
-
-	for _, target := range goarches {
-		var buf bytes.Buffer
-		fmt.Fprintf(&buf, "// generated by gengoos.go using 'go generate'\n\n")
-		fmt.Fprintf(&buf, "package runtime\n\n")
-		fmt.Fprintf(&buf, "const theGoarch = `%s`\n\n", target)
-		for _, goarch := range goarches {
-			value := 0
-			if goarch == target {
-				value = 1
-			}
-			fmt.Fprintf(&buf, "const goarch_%s = %d\n", goarch, value)
-		}
-		err := ioutil.WriteFile("zgoarch_"+target+".go", buf.Bytes(), 0666)
-		if err != nil {
-			log.Fatal(err)
-		}
-	}
-}
diff --git a/src/runtime/hash32.go b/src/runtime/hash32.go
index 79fb15c..2b7c5c0 100644
--- a/src/runtime/hash32.go
+++ b/src/runtime/hash32.go
@@ -52,9 +52,9 @@ tail:
 		h = rotl_15(h*m1) * m2
 	default:
 		v1 := h
-		v2 := uint32(hashkey[1])
-		v3 := uint32(hashkey[2])
-		v4 := uint32(hashkey[3])
+		v2 := uint32(seed * hashkey[1])
+		v3 := uint32(seed * hashkey[2])
+		v4 := uint32(seed * hashkey[3])
 		for s >= 16 {
 			v1 ^= readUnaligned32(p)
 			v1 = rotl_15(v1*m1) * m2
diff --git a/src/runtime/hash64.go b/src/runtime/hash64.go
index 716db61..fb3dba4 100644
--- a/src/runtime/hash64.go
+++ b/src/runtime/hash64.go
@@ -6,7 +6,7 @@
 //   xxhash: https://code.google.com/p/xxhash/
 // cityhash: https://code.google.com/p/cityhash/
 
-// +build amd64 amd64p32 arm64 ppc64 ppc64le
+// +build amd64 amd64p32 arm64 mips64 mips64le ppc64 ppc64le
 
 package runtime
 
@@ -53,9 +53,9 @@ tail:
 		h = rotl_31(h*m1) * m2
 	default:
 		v1 := h
-		v2 := uint64(hashkey[1])
-		v3 := uint64(hashkey[2])
-		v4 := uint64(hashkey[3])
+		v2 := uint64(seed * hashkey[1])
+		v3 := uint64(seed * hashkey[2])
+		v4 := uint64(seed * hashkey[3])
 		for s >= 32 {
 			v1 ^= readUnaligned64(p)
 			v1 = rotl_31(v1*m1) * m2
diff --git a/src/runtime/hash_test.go b/src/runtime/hash_test.go
index 6b229bd..1651485 100644
--- a/src/runtime/hash_test.go
+++ b/src/runtime/hash_test.go
@@ -74,7 +74,7 @@ func (s *HashSet) check(t *testing.T) {
 	pairs := int64(s.n) * int64(s.n-1) / 2
 	expected := float64(pairs) / math.Pow(2.0, float64(hashSize))
 	stddev := math.Sqrt(expected)
-	if float64(collisions) > expected+SLOP*3*stddev {
+	if float64(collisions) > expected+SLOP*(3*stddev+1) {
 		t.Errorf("unexpected number of collisions: got=%d mean=%f stddev=%f", collisions, expected, stddev)
 	}
 }
@@ -561,3 +561,100 @@ func BenchmarkHash16(b *testing.B)    { benchmarkHash(b, 16) }
 func BenchmarkHash64(b *testing.B)    { benchmarkHash(b, 64) }
 func BenchmarkHash1024(b *testing.B)  { benchmarkHash(b, 1024) }
 func BenchmarkHash65536(b *testing.B) { benchmarkHash(b, 65536) }
+
+func TestArrayHash(t *testing.T) {
+	// Make sure that "" in arrays hash correctly.  The hash
+	// should at least scramble the input seed so that, e.g.,
+	// {"","foo"} and {"foo",""} have different hashes.
+
+	// If the hash is bad, then all (8 choose 4) = 70 keys
+	// have the same hash. If so, we allocate 70/8 = 8
+	// overflow buckets.  If the hash is good we don't
+	// normally allocate any overflow buckets, and the
+	// probability of even one or two overflows goes down rapidly.
+	// (There is always 1 allocation of the bucket array.  The map
+	// header is allocated on the stack.)
+	f := func() {
+		// Make the key type at most 128 bytes.  Otherwise,
+		// we get an allocation per key.
+		type key [8]string
+		m := make(map[key]bool, 70)
+
+		// fill m with keys that have 4 "foo"s and 4 ""s.
+		for i := 0; i < 256; i++ {
+			var k key
+			cnt := 0
+			for j := uint(0); j < 8; j++ {
+				if i>>j&1 != 0 {
+					k[j] = "foo"
+					cnt++
+				}
+			}
+			if cnt == 4 {
+				m[k] = true
+			}
+		}
+		if len(m) != 70 {
+			t.Errorf("bad test: (8 choose 4) should be 70, not %d", len(m))
+		}
+	}
+	if n := testing.AllocsPerRun(10, f); n > 6 {
+		t.Errorf("too many allocs %f - hash not balanced", n)
+	}
+}
+func TestStructHash(t *testing.T) {
+	// See the comment in TestArrayHash.
+	f := func() {
+		type key struct {
+			a, b, c, d, e, f, g, h string
+		}
+		m := make(map[key]bool, 70)
+
+		// fill m with keys that have 4 "foo"s and 4 ""s.
+		for i := 0; i < 256; i++ {
+			var k key
+			cnt := 0
+			if i&1 != 0 {
+				k.a = "foo"
+				cnt++
+			}
+			if i&2 != 0 {
+				k.b = "foo"
+				cnt++
+			}
+			if i&4 != 0 {
+				k.c = "foo"
+				cnt++
+			}
+			if i&8 != 0 {
+				k.d = "foo"
+				cnt++
+			}
+			if i&16 != 0 {
+				k.e = "foo"
+				cnt++
+			}
+			if i&32 != 0 {
+				k.f = "foo"
+				cnt++
+			}
+			if i&64 != 0 {
+				k.g = "foo"
+				cnt++
+			}
+			if i&128 != 0 {
+				k.h = "foo"
+				cnt++
+			}
+			if cnt == 4 {
+				m[k] = true
+			}
+		}
+		if len(m) != 70 {
+			t.Errorf("bad test: (8 choose 4) should be 70, not %d", len(m))
+		}
+	}
+	if n := testing.AllocsPerRun(10, f); n > 6 {
+		t.Errorf("too many allocs %f - hash not balanced", n)
+	}
+}
diff --git a/src/runtime/hashmap.go b/src/runtime/hashmap.go
index 917ed21..892a79a 100644
--- a/src/runtime/hashmap.go
+++ b/src/runtime/hashmap.go
@@ -54,6 +54,8 @@ package runtime
 // before the table grows.  Typical tables will be somewhat less loaded.
 
 import (
+	"runtime/internal/atomic"
+	"runtime/internal/sys"
 	"unsafe"
 )
 
@@ -93,9 +95,10 @@ const (
 	// flags
 	iterator    = 1 // there may be an iterator using buckets
 	oldIterator = 2 // there may be an iterator using oldbuckets
+	hashWriting = 4 // a goroutine is writing to the map
 
 	// sentinel bucket ID for iterator checks
-	noCheck = 1<<(8*ptrSize) - 1
+	noCheck = 1<<(8*sys.PtrSize) - 1
 )
 
 // A header for a Go map.
@@ -159,7 +162,7 @@ func evacuated(b *bmap) bool {
 }
 
 func (b *bmap) overflow(t *maptype) *bmap {
-	return *(**bmap)(add(unsafe.Pointer(b), uintptr(t.bucketsize)-ptrSize))
+	return *(**bmap)(add(unsafe.Pointer(b), uintptr(t.bucketsize)-sys.PtrSize))
 }
 
 func (h *hmap) setoverflow(t *maptype, b, ovf *bmap) {
@@ -167,7 +170,7 @@ func (h *hmap) setoverflow(t *maptype, b, ovf *bmap) {
 		h.createOverflow()
 		*h.overflow[0] = append(*h.overflow[0], ovf)
 	}
-	*(**bmap)(add(unsafe.Pointer(b), uintptr(t.bucketsize)-ptrSize)) = ovf
+	*(**bmap)(add(unsafe.Pointer(b), uintptr(t.bucketsize)-sys.PtrSize)) = ovf
 }
 
 func (h *hmap) createOverflow() {
@@ -200,11 +203,11 @@ func makemap(t *maptype, hint int64, h *hmap, bucket unsafe.Pointer) *hmap {
 	}
 
 	// check compiler's and reflect's math
-	if t.key.size > maxKeySize && (!t.indirectkey || t.keysize != uint8(ptrSize)) ||
+	if t.key.size > maxKeySize && (!t.indirectkey || t.keysize != uint8(sys.PtrSize)) ||
 		t.key.size <= maxKeySize && (t.indirectkey || t.keysize != uint8(t.key.size)) {
 		throw("key size wrong")
 	}
-	if t.elem.size > maxValueSize && (!t.indirectvalue || t.valuesize != uint8(ptrSize)) ||
+	if t.elem.size > maxValueSize && (!t.indirectvalue || t.valuesize != uint8(sys.PtrSize)) ||
 		t.elem.size <= maxValueSize && (t.indirectvalue || t.valuesize != uint8(t.elem.size)) {
 		throw("value size wrong")
 	}
@@ -233,7 +236,7 @@ func makemap(t *maptype, hint int64, h *hmap, bucket unsafe.Pointer) *hmap {
 		throw("need padding in bucket (value)")
 	}
 
-	// make sure zero of element type is available.
+	// make sure zeroptr is large enough
 	mapzero(t.elem)
 
 	// find size parameter which will hold the requested # of elements
@@ -276,8 +279,14 @@ func mapaccess1(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
 		racereadpc(unsafe.Pointer(h), callerpc, pc)
 		raceReadObjectPC(t.key, key, callerpc, pc)
 	}
+	if msanenabled && h != nil {
+		msanread(key, t.key.size)
+	}
 	if h == nil || h.count == 0 {
-		return unsafe.Pointer(t.elem.zero)
+		return atomic.Loadp(unsafe.Pointer(&zeroptr))
+	}
+	if h.flags&hashWriting != 0 {
+		throw("concurrent map read and map write")
 	}
 	alg := t.key.alg
 	hash := alg.hash(key, uintptr(h.hash0))
@@ -289,7 +298,7 @@ func mapaccess1(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
 			b = oldb
 		}
 	}
-	top := uint8(hash >> (ptrSize*8 - 8))
+	top := uint8(hash >> (sys.PtrSize*8 - 8))
 	if top < minTopHash {
 		top += minTopHash
 	}
@@ -312,7 +321,7 @@ func mapaccess1(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
 		}
 		b = b.overflow(t)
 		if b == nil {
-			return unsafe.Pointer(t.elem.zero)
+			return atomic.Loadp(unsafe.Pointer(&zeroptr))
 		}
 	}
 }
@@ -324,8 +333,14 @@ func mapaccess2(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, bool)
 		racereadpc(unsafe.Pointer(h), callerpc, pc)
 		raceReadObjectPC(t.key, key, callerpc, pc)
 	}
+	if msanenabled && h != nil {
+		msanread(key, t.key.size)
+	}
 	if h == nil || h.count == 0 {
-		return unsafe.Pointer(t.elem.zero), false
+		return atomic.Loadp(unsafe.Pointer(&zeroptr)), false
+	}
+	if h.flags&hashWriting != 0 {
+		throw("concurrent map read and map write")
 	}
 	alg := t.key.alg
 	hash := alg.hash(key, uintptr(h.hash0))
@@ -337,7 +352,7 @@ func mapaccess2(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, bool)
 			b = oldb
 		}
 	}
-	top := uint8(hash >> (ptrSize*8 - 8))
+	top := uint8(hash >> (sys.PtrSize*8 - 8))
 	if top < minTopHash {
 		top += minTopHash
 	}
@@ -360,7 +375,7 @@ func mapaccess2(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, bool)
 		}
 		b = b.overflow(t)
 		if b == nil {
-			return unsafe.Pointer(t.elem.zero), false
+			return atomic.Loadp(unsafe.Pointer(&zeroptr)), false
 		}
 	}
 }
@@ -370,6 +385,9 @@ func mapaccessK(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, unsafe
 	if h == nil || h.count == 0 {
 		return nil, nil
 	}
+	if h.flags&hashWriting != 0 {
+		throw("concurrent map read and map write")
+	}
 	alg := t.key.alg
 	hash := alg.hash(key, uintptr(h.hash0))
 	m := uintptr(1)<<h.B - 1
@@ -380,7 +398,7 @@ func mapaccessK(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, unsafe
 			b = oldb
 		}
 	}
-	top := uint8(hash >> (ptrSize*8 - 8))
+	top := uint8(hash >> (sys.PtrSize*8 - 8))
 	if top < minTopHash {
 		top += minTopHash
 	}
@@ -419,6 +437,14 @@ func mapassign1(t *maptype, h *hmap, key unsafe.Pointer, val unsafe.Pointer) {
 		raceReadObjectPC(t.key, key, callerpc, pc)
 		raceReadObjectPC(t.elem, val, callerpc, pc)
 	}
+	if msanenabled {
+		msanread(key, t.key.size)
+		msanread(val, t.elem.size)
+	}
+	if h.flags&hashWriting != 0 {
+		throw("concurrent map writes")
+	}
+	h.flags |= hashWriting
 
 	alg := t.key.alg
 	hash := alg.hash(key, uintptr(h.hash0))
@@ -433,7 +459,7 @@ again:
 		growWork(t, h, bucket)
 	}
 	b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + bucket*uintptr(t.bucketsize)))
-	top := uint8(hash >> (ptrSize*8 - 8))
+	top := uint8(hash >> (sys.PtrSize*8 - 8))
 	if top < minTopHash {
 		top += minTopHash
 	}
@@ -460,14 +486,16 @@ again:
 				continue
 			}
 			// already have a mapping for key.  Update it.
-			typedmemmove(t.key, k2, key)
+			if t.needkeyupdate {
+				typedmemmove(t.key, k2, key)
+			}
 			v := add(unsafe.Pointer(b), dataOffset+bucketCnt*uintptr(t.keysize)+i*uintptr(t.valuesize))
 			v2 := v
 			if t.indirectvalue {
 				v2 = *((*unsafe.Pointer)(v2))
 			}
 			typedmemmove(t.elem, v2, val)
-			return
+			goto done
 		}
 		ovf := b.overflow(t)
 		if ovf == nil {
@@ -506,6 +534,12 @@ again:
 	typedmemmove(t.elem, insertv, val)
 	*inserti = top
 	h.count++
+
+done:
+	if h.flags&hashWriting == 0 {
+		throw("concurrent map writes")
+	}
+	h.flags &^= hashWriting
 }
 
 func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) {
@@ -515,9 +549,17 @@ func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) {
 		racewritepc(unsafe.Pointer(h), callerpc, pc)
 		raceReadObjectPC(t.key, key, callerpc, pc)
 	}
+	if msanenabled && h != nil {
+		msanread(key, t.key.size)
+	}
 	if h == nil || h.count == 0 {
 		return
 	}
+	if h.flags&hashWriting != 0 {
+		throw("concurrent map writes")
+	}
+	h.flags |= hashWriting
+
 	alg := t.key.alg
 	hash := alg.hash(key, uintptr(h.hash0))
 	bucket := hash & (uintptr(1)<<h.B - 1)
@@ -525,7 +567,7 @@ func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) {
 		growWork(t, h, bucket)
 	}
 	b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + bucket*uintptr(t.bucketsize)))
-	top := uint8(hash >> (ptrSize*8 - 8))
+	top := uint8(hash >> (sys.PtrSize*8 - 8))
 	if top < minTopHash {
 		top += minTopHash
 	}
@@ -547,13 +589,19 @@ func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) {
 			memclr(v, uintptr(t.valuesize))
 			b.tophash[i] = empty
 			h.count--
-			return
+			goto done
 		}
 		b = b.overflow(t)
 		if b == nil {
-			return
+			goto done
 		}
 	}
+
+done:
+	if h.flags&hashWriting == 0 {
+		throw("concurrent map writes")
+	}
+	h.flags &^= hashWriting
 }
 
 func mapiterinit(t *maptype, h *hmap, it *hiter) {
@@ -578,7 +626,7 @@ func mapiterinit(t *maptype, h *hmap, it *hiter) {
 		return
 	}
 
-	if unsafe.Sizeof(hiter{})/ptrSize != 12 {
+	if unsafe.Sizeof(hiter{})/sys.PtrSize != 12 {
 		throw("hash_iter size incorrect") // see ../../cmd/internal/gc/reflect.go
 	}
 	it.t = t
@@ -612,7 +660,7 @@ func mapiterinit(t *maptype, h *hmap, it *hiter) {
 	// Remember we have an iterator.
 	// Can run concurrently with another hash_iter_init().
 	if old := h.flags; old&(iterator|oldIterator) != iterator|oldIterator {
-		atomicor8(&h.flags, iterator|oldIterator)
+		atomic.Or8(&h.flags, iterator|oldIterator)
 	}
 
 	mapiternext(it)
@@ -849,7 +897,7 @@ func evacuate(t *maptype, h *hmap, oldbucket uintptr) {
 						} else {
 							hash &^= newbit
 						}
-						top = uint8(hash >> (ptrSize*8 - 8))
+						top = uint8(hash >> (sys.PtrSize*8 - 8))
 						if top < minTopHash {
 							top += minTopHash
 						}
@@ -994,59 +1042,39 @@ func reflect_ismapkey(t *_type) bool {
 	return ismapkey(t)
 }
 
-var zerobuf struct {
-	lock mutex
-	p    *byte
-	size uintptr
-}
+var zerolock mutex
 
-var zerotiny [1024]byte
+const initialZeroSize = 1024
 
-// mapzero ensures that t.zero points at a zero value for type t.
-// Types known to the compiler are in read-only memory and all point
-// to a single zero in the bss of a large enough size.
-// Types allocated by package reflect are in writable memory and
-// start out with zero set to nil; we initialize those on demand.
-func mapzero(t *_type) {
-	// On ARM, atomicloadp is implemented as xadd(p, 0),
-	// so we cannot use atomicloadp on read-only memory.
-	// Check whether the pointer is in the heap; if not, it's not writable
-	// so the zero value must already be set.
-	if GOARCH == "arm" && !inheap(uintptr(unsafe.Pointer(t))) {
-		if t.zero == nil {
-			print("runtime: map element ", *t._string, " missing zero value\n")
-			throw("mapzero")
-		}
-		return
-	}
+var zeroinitial [initialZeroSize]byte
 
-	// Already done?
-	// Check without lock, so must use atomicload to sync with atomicstore in allocation case below.
-	if atomicloadp(unsafe.Pointer(&t.zero)) != nil {
-		return
-	}
+// All accesses to zeroptr and zerosize must be atomic so that they
+// can be accessed without locks in the common case.
+var zeroptr unsafe.Pointer = unsafe.Pointer(&zeroinitial)
+var zerosize uintptr = initialZeroSize
 
-	// Small enough for static buffer?
-	if t.size <= uintptr(len(zerotiny)) {
-		atomicstorep(unsafe.Pointer(&t.zero), unsafe.Pointer(&zerotiny[0]))
+// mapzero ensures that zeroptr points to a buffer large enough to
+// serve as the zero value for t.
+func mapzero(t *_type) {
+	// Is the type small enough for existing buffer?
+	cursize := uintptr(atomic.Loadp(unsafe.Pointer(&zerosize)))
+	if t.size <= cursize {
 		return
 	}
 
-	// Use allocated buffer.
-	lock(&zerobuf.lock)
-	if zerobuf.size < t.size {
-		if zerobuf.size == 0 {
-			zerobuf.size = 4 * 1024
-		}
-		for zerobuf.size < t.size {
-			zerobuf.size *= 2
-			if zerobuf.size == 0 {
+	// Allocate a new buffer.
+	lock(&zerolock)
+	cursize = uintptr(atomic.Loadp(unsafe.Pointer(&zerosize)))
+	if cursize < t.size {
+		for cursize < t.size {
+			cursize *= 2
+			if cursize == 0 {
 				// need >2GB zero on 32-bit machine
 				throw("map element too large")
 			}
 		}
-		zerobuf.p = (*byte)(persistentalloc(zerobuf.size, 64, &memstats.other_sys))
+		atomic.Storep1(unsafe.Pointer(&zeroptr), persistentalloc(cursize, 64, &memstats.other_sys))
+		atomic.Storep1(unsafe.Pointer(&zerosize), unsafe.Pointer(zerosize))
 	}
-	atomicstorep(unsafe.Pointer(&t.zero), unsafe.Pointer(zerobuf.p))
-	unlock(&zerobuf.lock)
+	unlock(&zerolock)
 }
diff --git a/src/runtime/hashmap_fast.go b/src/runtime/hashmap_fast.go
index 02c51a2..519dc77 100644
--- a/src/runtime/hashmap_fast.go
+++ b/src/runtime/hashmap_fast.go
@@ -5,6 +5,8 @@
 package runtime
 
 import (
+	"runtime/internal/atomic"
+	"runtime/internal/sys"
 	"unsafe"
 )
 
@@ -14,7 +16,10 @@ func mapaccess1_fast32(t *maptype, h *hmap, key uint32) unsafe.Pointer {
 		racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess1_fast32))
 	}
 	if h == nil || h.count == 0 {
-		return unsafe.Pointer(t.elem.zero)
+		return atomic.Loadp(unsafe.Pointer(&zeroptr))
+	}
+	if h.flags&hashWriting != 0 {
+		throw("concurrent map read and map write")
 	}
 	var b *bmap
 	if h.B == 0 {
@@ -45,7 +50,7 @@ func mapaccess1_fast32(t *maptype, h *hmap, key uint32) unsafe.Pointer {
 		}
 		b = b.overflow(t)
 		if b == nil {
-			return unsafe.Pointer(t.elem.zero)
+			return atomic.Loadp(unsafe.Pointer(&zeroptr))
 		}
 	}
 }
@@ -56,7 +61,10 @@ func mapaccess2_fast32(t *maptype, h *hmap, key uint32) (unsafe.Pointer, bool) {
 		racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess2_fast32))
 	}
 	if h == nil || h.count == 0 {
-		return unsafe.Pointer(t.elem.zero), false
+		return atomic.Loadp(unsafe.Pointer(&zeroptr)), false
+	}
+	if h.flags&hashWriting != 0 {
+		throw("concurrent map read and map write")
 	}
 	var b *bmap
 	if h.B == 0 {
@@ -87,7 +95,7 @@ func mapaccess2_fast32(t *maptype, h *hmap, key uint32) (unsafe.Pointer, bool) {
 		}
 		b = b.overflow(t)
 		if b == nil {
-			return unsafe.Pointer(t.elem.zero), false
+			return atomic.Loadp(unsafe.Pointer(&zeroptr)), false
 		}
 	}
 }
@@ -98,7 +106,10 @@ func mapaccess1_fast64(t *maptype, h *hmap, key uint64) unsafe.Pointer {
 		racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess1_fast64))
 	}
 	if h == nil || h.count == 0 {
-		return unsafe.Pointer(t.elem.zero)
+		return atomic.Loadp(unsafe.Pointer(&zeroptr))
+	}
+	if h.flags&hashWriting != 0 {
+		throw("concurrent map read and map write")
 	}
 	var b *bmap
 	if h.B == 0 {
@@ -129,7 +140,7 @@ func mapaccess1_fast64(t *maptype, h *hmap, key uint64) unsafe.Pointer {
 		}
 		b = b.overflow(t)
 		if b == nil {
-			return unsafe.Pointer(t.elem.zero)
+			return atomic.Loadp(unsafe.Pointer(&zeroptr))
 		}
 	}
 }
@@ -140,7 +151,10 @@ func mapaccess2_fast64(t *maptype, h *hmap, key uint64) (unsafe.Pointer, bool) {
 		racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess2_fast64))
 	}
 	if h == nil || h.count == 0 {
-		return unsafe.Pointer(t.elem.zero), false
+		return atomic.Loadp(unsafe.Pointer(&zeroptr)), false
+	}
+	if h.flags&hashWriting != 0 {
+		throw("concurrent map read and map write")
 	}
 	var b *bmap
 	if h.B == 0 {
@@ -171,7 +185,7 @@ func mapaccess2_fast64(t *maptype, h *hmap, key uint64) (unsafe.Pointer, bool) {
 		}
 		b = b.overflow(t)
 		if b == nil {
-			return unsafe.Pointer(t.elem.zero), false
+			return atomic.Loadp(unsafe.Pointer(&zeroptr)), false
 		}
 	}
 }
@@ -182,9 +196,12 @@ func mapaccess1_faststr(t *maptype, h *hmap, ky string) unsafe.Pointer {
 		racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess1_faststr))
 	}
 	if h == nil || h.count == 0 {
-		return unsafe.Pointer(t.elem.zero)
+		return atomic.Loadp(unsafe.Pointer(&zeroptr))
+	}
+	if h.flags&hashWriting != 0 {
+		throw("concurrent map read and map write")
 	}
-	key := (*stringStruct)(unsafe.Pointer(&ky))
+	key := stringStructOf(&ky)
 	if h.B == 0 {
 		// One-bucket table.
 		b := (*bmap)(h.buckets)
@@ -195,15 +212,15 @@ func mapaccess1_faststr(t *maptype, h *hmap, ky string) unsafe.Pointer {
 				if x == empty {
 					continue
 				}
-				k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*ptrSize))
+				k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*sys.PtrSize))
 				if k.len != key.len {
 					continue
 				}
 				if k.str == key.str || memeq(k.str, key.str, uintptr(key.len)) {
-					return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*ptrSize+i*uintptr(t.valuesize))
+					return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.valuesize))
 				}
 			}
-			return unsafe.Pointer(t.elem.zero)
+			return atomic.Loadp(unsafe.Pointer(&zeroptr))
 		}
 		// long key, try not to do more comparisons than necessary
 		keymaybe := uintptr(bucketCnt)
@@ -212,12 +229,12 @@ func mapaccess1_faststr(t *maptype, h *hmap, ky string) unsafe.Pointer {
 			if x == empty {
 				continue
 			}
-			k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*ptrSize))
+			k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*sys.PtrSize))
 			if k.len != key.len {
 				continue
 			}
 			if k.str == key.str {
-				return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*ptrSize+i*uintptr(t.valuesize))
+				return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.valuesize))
 			}
 			// check first 4 bytes
 			// TODO: on amd64/386 at least, make this compile to one 4-byte comparison instead of
@@ -236,12 +253,12 @@ func mapaccess1_faststr(t *maptype, h *hmap, ky string) unsafe.Pointer {
 			keymaybe = i
 		}
 		if keymaybe != bucketCnt {
-			k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+keymaybe*2*ptrSize))
+			k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+keymaybe*2*sys.PtrSize))
 			if memeq(k.str, key.str, uintptr(key.len)) {
-				return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*ptrSize+keymaybe*uintptr(t.valuesize))
+				return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+keymaybe*uintptr(t.valuesize))
 			}
 		}
-		return unsafe.Pointer(t.elem.zero)
+		return atomic.Loadp(unsafe.Pointer(&zeroptr))
 	}
 dohash:
 	hash := t.key.alg.hash(noescape(unsafe.Pointer(&ky)), uintptr(h.hash0))
@@ -253,7 +270,7 @@ dohash:
 			b = oldb
 		}
 	}
-	top := uint8(hash >> (ptrSize*8 - 8))
+	top := uint8(hash >> (sys.PtrSize*8 - 8))
 	if top < minTopHash {
 		top += minTopHash
 	}
@@ -263,17 +280,17 @@ dohash:
 			if x != top {
 				continue
 			}
-			k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*ptrSize))
+			k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*sys.PtrSize))
 			if k.len != key.len {
 				continue
 			}
 			if k.str == key.str || memeq(k.str, key.str, uintptr(key.len)) {
-				return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*ptrSize+i*uintptr(t.valuesize))
+				return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.valuesize))
 			}
 		}
 		b = b.overflow(t)
 		if b == nil {
-			return unsafe.Pointer(t.elem.zero)
+			return atomic.Loadp(unsafe.Pointer(&zeroptr))
 		}
 	}
 }
@@ -284,9 +301,12 @@ func mapaccess2_faststr(t *maptype, h *hmap, ky string) (unsafe.Pointer, bool) {
 		racereadpc(unsafe.Pointer(h), callerpc, funcPC(mapaccess2_faststr))
 	}
 	if h == nil || h.count == 0 {
-		return unsafe.Pointer(t.elem.zero), false
+		return atomic.Loadp(unsafe.Pointer(&zeroptr)), false
+	}
+	if h.flags&hashWriting != 0 {
+		throw("concurrent map read and map write")
 	}
-	key := (*stringStruct)(unsafe.Pointer(&ky))
+	key := stringStructOf(&ky)
 	if h.B == 0 {
 		// One-bucket table.
 		b := (*bmap)(h.buckets)
@@ -297,15 +317,15 @@ func mapaccess2_faststr(t *maptype, h *hmap, ky string) (unsafe.Pointer, bool) {
 				if x == empty {
 					continue
 				}
-				k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*ptrSize))
+				k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*sys.PtrSize))
 				if k.len != key.len {
 					continue
 				}
 				if k.str == key.str || memeq(k.str, key.str, uintptr(key.len)) {
-					return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*ptrSize+i*uintptr(t.valuesize)), true
+					return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.valuesize)), true
 				}
 			}
-			return unsafe.Pointer(t.elem.zero), false
+			return atomic.Loadp(unsafe.Pointer(&zeroptr)), false
 		}
 		// long key, try not to do more comparisons than necessary
 		keymaybe := uintptr(bucketCnt)
@@ -314,12 +334,12 @@ func mapaccess2_faststr(t *maptype, h *hmap, ky string) (unsafe.Pointer, bool) {
 			if x == empty {
 				continue
 			}
-			k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*ptrSize))
+			k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*sys.PtrSize))
 			if k.len != key.len {
 				continue
 			}
 			if k.str == key.str {
-				return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*ptrSize+i*uintptr(t.valuesize)), true
+				return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.valuesize)), true
 			}
 			// check first 4 bytes
 			if *((*[4]byte)(key.str)) != *((*[4]byte)(k.str)) {
@@ -336,12 +356,12 @@ func mapaccess2_faststr(t *maptype, h *hmap, ky string) (unsafe.Pointer, bool) {
 			keymaybe = i
 		}
 		if keymaybe != bucketCnt {
-			k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+keymaybe*2*ptrSize))
+			k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+keymaybe*2*sys.PtrSize))
 			if memeq(k.str, key.str, uintptr(key.len)) {
-				return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*ptrSize+keymaybe*uintptr(t.valuesize)), true
+				return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+keymaybe*uintptr(t.valuesize)), true
 			}
 		}
-		return unsafe.Pointer(t.elem.zero), false
+		return atomic.Loadp(unsafe.Pointer(&zeroptr)), false
 	}
 dohash:
 	hash := t.key.alg.hash(noescape(unsafe.Pointer(&ky)), uintptr(h.hash0))
@@ -353,7 +373,7 @@ dohash:
 			b = oldb
 		}
 	}
-	top := uint8(hash >> (ptrSize*8 - 8))
+	top := uint8(hash >> (sys.PtrSize*8 - 8))
 	if top < minTopHash {
 		top += minTopHash
 	}
@@ -363,17 +383,17 @@ dohash:
 			if x != top {
 				continue
 			}
-			k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*ptrSize))
+			k := (*stringStruct)(add(unsafe.Pointer(b), dataOffset+i*2*sys.PtrSize))
 			if k.len != key.len {
 				continue
 			}
 			if k.str == key.str || memeq(k.str, key.str, uintptr(key.len)) {
-				return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*ptrSize+i*uintptr(t.valuesize)), true
+				return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*sys.PtrSize+i*uintptr(t.valuesize)), true
 			}
 		}
 		b = b.overflow(t)
 		if b == nil {
-			return unsafe.Pointer(t.elem.zero), false
+			return atomic.Loadp(unsafe.Pointer(&zeroptr)), false
 		}
 	}
 }
diff --git a/src/runtime/heapdump.go b/src/runtime/heapdump.go
index 492ea92..4d1da1c 100644
--- a/src/runtime/heapdump.go
+++ b/src/runtime/heapdump.go
@@ -11,7 +11,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 //go:linkname runtime_debug_WriteHeapDump runtime/debug.WriteHeapDump
 func runtime_debug_WriteHeapDump(fd uintptr) {
@@ -70,7 +73,7 @@ func dwrite(data unsafe.Pointer, len uintptr) {
 		return
 	}
 
-	write(dumpfd, (unsafe.Pointer)(&buf), int32(nbuf))
+	write(dumpfd, unsafe.Pointer(&buf), int32(nbuf))
 	if len >= bufSize {
 		write(dumpfd, data, int32(len))
 		nbuf = 0
@@ -85,7 +88,7 @@ func dwritebyte(b byte) {
 }
 
 func flush() {
-	write(dumpfd, (unsafe.Pointer)(&buf), int32(nbuf))
+	write(dumpfd, unsafe.Pointer(&buf), int32(nbuf))
 	nbuf = 0
 }
 
@@ -142,7 +145,7 @@ func dumpslice(b []byte) {
 }
 
 func dumpstr(s string) {
-	sp := (*stringStruct)(unsafe.Pointer(&s))
+	sp := stringStructOf(&s)
 	dumpmemrange(sp.str, uintptr(sp.len))
 }
 
@@ -183,8 +186,8 @@ func dumptype(t *_type) {
 	if t.x == nil || t.x.pkgpath == nil || t.x.name == nil {
 		dumpstr(*t._string)
 	} else {
-		pkgpath := (*stringStruct)(unsafe.Pointer(&t.x.pkgpath))
-		name := (*stringStruct)(unsafe.Pointer(&t.x.name))
+		pkgpath := stringStructOf(t.x.pkgpath)
+		name := stringStructOf(t.x.name)
 		dumpint(uint64(uintptr(pkgpath.len) + 1 + uintptr(name.len)))
 		dwrite(pkgpath.str, uintptr(pkgpath.len))
 		dwritebyte('.')
@@ -233,7 +236,7 @@ func dumpbv(cbv *bitvector, offset uintptr) {
 	for i := uintptr(0); i < uintptr(bv.n); i++ {
 		if bv.bytedata[i/8]>>(i%8)&1 == 1 {
 			dumpint(fieldKindPtr)
-			dumpint(uint64(offset + i*ptrSize))
+			dumpint(uint64(offset + i*sys.PtrSize))
 		}
 	}
 }
@@ -247,7 +250,7 @@ func dumpframe(s *stkframe, arg unsafe.Pointer) bool {
 	if pc != f.entry {
 		pc--
 	}
-	pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, pc)
+	pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, pc, nil)
 	if pcdata == -1 {
 		// We do not have a valid pcdata value but there might be a
 		// stackmap for this function.  It is likely that we are looking
@@ -263,7 +266,7 @@ func dumpframe(s *stkframe, arg unsafe.Pointer) bool {
 	var bv bitvector
 	if stkmap != nil && stkmap.n > 0 {
 		bv = stackmapdata(stkmap, pcdata)
-		dumpbvtypes(&bv, unsafe.Pointer(s.varp-uintptr(bv.n*ptrSize)))
+		dumpbvtypes(&bv, unsafe.Pointer(s.varp-uintptr(bv.n*sys.PtrSize)))
 	} else {
 		bv.n = -1
 	}
@@ -288,7 +291,7 @@ func dumpframe(s *stkframe, arg unsafe.Pointer) bool {
 		dumpbv(&child.args, child.argoff)
 	} else {
 		// conservative - everything might be a pointer
-		for off := child.argoff; off < child.argoff+child.arglen; off += ptrSize {
+		for off := child.argoff; off < child.argoff+child.arglen; off += sys.PtrSize {
 			dumpint(fieldKindPtr)
 			dumpint(uint64(off))
 		}
@@ -297,21 +300,21 @@ func dumpframe(s *stkframe, arg unsafe.Pointer) bool {
 	// Dump fields in the local vars section
 	if stkmap == nil {
 		// No locals information, dump everything.
-		for off := child.arglen; off < s.varp-s.sp; off += ptrSize {
+		for off := child.arglen; off < s.varp-s.sp; off += sys.PtrSize {
 			dumpint(fieldKindPtr)
 			dumpint(uint64(off))
 		}
 	} else if stkmap.n < 0 {
 		// Locals size information, dump just the locals.
 		size := uintptr(-stkmap.n)
-		for off := s.varp - size - s.sp; off < s.varp-s.sp; off += ptrSize {
+		for off := s.varp - size - s.sp; off < s.varp-s.sp; off += sys.PtrSize {
 			dumpint(fieldKindPtr)
 			dumpint(uint64(off))
 		}
 	} else if stkmap.n > 0 {
 		// Locals bitmap information, scan just the pointers in
 		// locals.
-		dumpbv(&bv, s.varp-uintptr(bv.n)*ptrSize-s.sp)
+		dumpbv(&bv, s.varp-uintptr(bv.n)*sys.PtrSize-s.sp)
 	}
 	dumpint(fieldKindEol)
 
@@ -379,7 +382,7 @@ func dumpgoroutine(gp *g) {
 		dumpint(tagPanic)
 		dumpint(uint64(uintptr(unsafe.Pointer(p))))
 		dumpint(uint64(uintptr(unsafe.Pointer(gp))))
-		eface := (*eface)(unsafe.Pointer(&p.arg))
+		eface := efaceOf(&p.arg)
 		dumpint(uint64(uintptr(unsafe.Pointer(eface._type))))
 		dumpint(uint64(uintptr(unsafe.Pointer(eface.data))))
 		dumpint(0) // was p->defer, no longer recorded
@@ -489,11 +492,11 @@ func dumpparams() {
 	} else {
 		dumpbool(true) // big-endian ptrs
 	}
-	dumpint(ptrSize)
+	dumpint(sys.PtrSize)
 	dumpint(uint64(mheap_.arena_start))
 	dumpint(uint64(mheap_.arena_used))
-	dumpint(thechar)
-	dumpstr(goexperiment)
+	dumpint(sys.TheChar)
+	dumpstr(sys.Goexperiment)
 	dumpint(uint64(ncpu))
 }
 
@@ -636,14 +639,14 @@ func dumpmemprof() {
 	}
 }
 
-var dumphdr = []byte("go1.5 heap dump\n")
+var dumphdr = []byte("go1.6 heap dump\n")
 
 func mdump() {
 	// make sure we're done sweeping
 	for i := uintptr(0); i < uintptr(mheap_.nspan); i++ {
 		s := h_allspans[i]
 		if s.state == _MSpanInUse {
-			mSpan_EnsureSwept(s)
+			s.ensureSwept()
 		}
 	}
 	memclr(unsafe.Pointer(&typecache), unsafe.Sizeof(typecache))
@@ -704,7 +707,7 @@ func dumpbvtypes(bv *bitvector, base unsafe.Pointer) {
 
 func makeheapobjbv(p uintptr, size uintptr) bitvector {
 	// Extend the temp buffer if necessary.
-	nptr := size / ptrSize
+	nptr := size / sys.PtrSize
 	if uintptr(len(tmpbuf)) < nptr/8+1 {
 		if tmpbuf != nil {
 			sysFree(unsafe.Pointer(&tmpbuf[0]), uintptr(len(tmpbuf)), &memstats.other_sys)
diff --git a/src/runtime/iface.go b/src/runtime/iface.go
index 332b7d5..71dc865 100644
--- a/src/runtime/iface.go
+++ b/src/runtime/iface.go
@@ -4,7 +4,11 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 const (
 	hashSize = 1009
@@ -15,13 +19,6 @@ var (
 	hash      [hashSize]*itab
 )
 
-// fInterface is our standard non-empty interface.  We use it instead
-// of interface{f()} in function prototypes because gofmt insists on
-// putting lots of newlines in the otherwise concise interface{f()}.
-type fInterface interface {
-	f()
-}
-
 func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
 	if len(inter.mhdr) == 0 {
 		throw("internal error - misuse of itab")
@@ -50,7 +47,7 @@ func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
 		if locked != 0 {
 			lock(&ifaceLock)
 		}
-		for m = (*itab)(atomicloadp(unsafe.Pointer(&hash[h]))); m != nil; m = m.link {
+		for m = (*itab)(atomic.Loadp(unsafe.Pointer(&hash[h]))); m != nil; m = m.link {
 			if m.inter == inter && m._type == typ {
 				if m.bad != 0 {
 					m = nil
@@ -73,7 +70,7 @@ func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
 		}
 	}
 
-	m = (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(inter.mhdr)-1)*ptrSize, 0, &memstats.other_sys))
+	m = (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(inter.mhdr)-1)*sys.PtrSize, 0, &memstats.other_sys))
 	m.inter = inter
 	m._type = typ
 
@@ -94,7 +91,7 @@ search:
 			t := &x.mhdr[j]
 			if t.mtyp == itype && (t.name == iname || *t.name == *iname) && t.pkgpath == ipkgpath {
 				if m != nil {
-					*(*unsafe.Pointer)(add(unsafe.Pointer(&m.fun[0]), uintptr(k)*ptrSize)) = t.ifn
+					*(*unsafe.Pointer)(add(unsafe.Pointer(&m.fun[0]), uintptr(k)*sys.PtrSize)) = t.ifn
 				}
 				goto nextimethod
 			}
@@ -128,11 +125,16 @@ func typ2Itab(t *_type, inter *interfacetype, cache **itab) *itab {
 	return tab
 }
 
-func convT2E(t *_type, elem unsafe.Pointer, x unsafe.Pointer) (e interface{}) {
-	ep := (*eface)(unsafe.Pointer(&e))
+func convT2E(t *_type, elem unsafe.Pointer, x unsafe.Pointer) (e eface) {
+	if raceenabled {
+		raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&t)), funcPC(convT2E))
+	}
+	if msanenabled {
+		msanread(elem, t.size)
+	}
 	if isDirectIface(t) {
-		ep._type = t
-		typedmemmove(t, unsafe.Pointer(&ep.data), elem)
+		e._type = t
+		typedmemmove(t, unsafe.Pointer(&e.data), elem)
 	} else {
 		if x == nil {
 			x = newobject(t)
@@ -140,29 +142,34 @@ func convT2E(t *_type, elem unsafe.Pointer, x unsafe.Pointer) (e interface{}) {
 		// TODO: We allocate a zeroed object only to overwrite it with
 		// actual data.  Figure out how to avoid zeroing.  Also below in convT2I.
 		typedmemmove(t, x, elem)
-		ep._type = t
-		ep.data = x
+		e._type = t
+		e.data = x
 	}
 	return
 }
 
-func convT2I(t *_type, inter *interfacetype, cache **itab, elem unsafe.Pointer, x unsafe.Pointer) (i fInterface) {
-	tab := (*itab)(atomicloadp(unsafe.Pointer(cache)))
+func convT2I(t *_type, inter *interfacetype, cache **itab, elem unsafe.Pointer, x unsafe.Pointer) (i iface) {
+	if raceenabled {
+		raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&t)), funcPC(convT2I))
+	}
+	if msanenabled {
+		msanread(elem, t.size)
+	}
+	tab := (*itab)(atomic.Loadp(unsafe.Pointer(cache)))
 	if tab == nil {
 		tab = getitab(inter, t, false)
 		atomicstorep(unsafe.Pointer(cache), unsafe.Pointer(tab))
 	}
-	pi := (*iface)(unsafe.Pointer(&i))
 	if isDirectIface(t) {
-		pi.tab = tab
-		typedmemmove(t, unsafe.Pointer(&pi.data), elem)
+		i.tab = tab
+		typedmemmove(t, unsafe.Pointer(&i.data), elem)
 	} else {
 		if x == nil {
 			x = newobject(t)
 		}
 		typedmemmove(t, x, elem)
-		pi.tab = tab
-		pi.data = x
+		i.tab = tab
+		i.data = x
 	}
 	return
 }
@@ -175,9 +182,8 @@ func panicdottype(have, want, iface *_type) {
 	panic(&TypeAssertionError{*iface._string, haveString, *want._string, ""})
 }
 
-func assertI2T(t *_type, i fInterface, r unsafe.Pointer) {
-	ip := (*iface)(unsafe.Pointer(&i))
-	tab := ip.tab
+func assertI2T(t *_type, i iface, r unsafe.Pointer) {
+	tab := i.tab
 	if tab == nil {
 		panic(&TypeAssertionError{"", "", *t._string, ""})
 	}
@@ -186,16 +192,15 @@ func assertI2T(t *_type, i fInterface, r unsafe.Pointer) {
 	}
 	if r != nil {
 		if isDirectIface(t) {
-			writebarrierptr((*uintptr)(r), uintptr(ip.data))
+			writebarrierptr((*uintptr)(r), uintptr(i.data))
 		} else {
-			typedmemmove(t, r, ip.data)
+			typedmemmove(t, r, i.data)
 		}
 	}
 }
 
-func assertI2T2(t *_type, i fInterface, r unsafe.Pointer) bool {
-	ip := (*iface)(unsafe.Pointer(&i))
-	tab := ip.tab
+func assertI2T2(t *_type, i iface, r unsafe.Pointer) bool {
+	tab := i.tab
 	if tab == nil || tab._type != t {
 		if r != nil {
 			memclr(r, uintptr(t.size))
@@ -204,27 +209,26 @@ func assertI2T2(t *_type, i fInterface, r unsafe.Pointer) bool {
 	}
 	if r != nil {
 		if isDirectIface(t) {
-			writebarrierptr((*uintptr)(r), uintptr(ip.data))
+			writebarrierptr((*uintptr)(r), uintptr(i.data))
 		} else {
-			typedmemmove(t, r, ip.data)
+			typedmemmove(t, r, i.data)
 		}
 	}
 	return true
 }
 
-func assertE2T(t *_type, e interface{}, r unsafe.Pointer) {
-	ep := (*eface)(unsafe.Pointer(&e))
-	if ep._type == nil {
+func assertE2T(t *_type, e eface, r unsafe.Pointer) {
+	if e._type == nil {
 		panic(&TypeAssertionError{"", "", *t._string, ""})
 	}
-	if ep._type != t {
-		panic(&TypeAssertionError{"", *ep._type._string, *t._string, ""})
+	if e._type != t {
+		panic(&TypeAssertionError{"", *e._type._string, *t._string, ""})
 	}
 	if r != nil {
 		if isDirectIface(t) {
-			writebarrierptr((*uintptr)(r), uintptr(ep.data))
+			writebarrierptr((*uintptr)(r), uintptr(e.data))
 		} else {
-			typedmemmove(t, r, ep.data)
+			typedmemmove(t, r, e.data)
 		}
 	}
 }
@@ -232,101 +236,89 @@ func assertE2T(t *_type, e interface{}, r unsafe.Pointer) {
 var testingAssertE2T2GC bool
 
 // The compiler ensures that r is non-nil.
-func assertE2T2(t *_type, e interface{}, r unsafe.Pointer) bool {
+func assertE2T2(t *_type, e eface, r unsafe.Pointer) bool {
 	if testingAssertE2T2GC {
 		GC()
 	}
-	ep := (*eface)(unsafe.Pointer(&e))
-	if ep._type != t {
+	if e._type != t {
 		memclr(r, uintptr(t.size))
 		return false
 	}
 	if isDirectIface(t) {
-		writebarrierptr((*uintptr)(r), uintptr(ep.data))
+		writebarrierptr((*uintptr)(r), uintptr(e.data))
 	} else {
-		typedmemmove(t, r, ep.data)
+		typedmemmove(t, r, e.data)
 	}
 	return true
 }
 
-func convI2E(i fInterface) (r interface{}) {
-	ip := (*iface)(unsafe.Pointer(&i))
-	tab := ip.tab
+func convI2E(i iface) (r eface) {
+	tab := i.tab
 	if tab == nil {
 		return
 	}
-	rp := (*eface)(unsafe.Pointer(&r))
-	rp._type = tab._type
-	rp.data = ip.data
+	r._type = tab._type
+	r.data = i.data
 	return
 }
 
-func assertI2E(inter *interfacetype, i fInterface, r *interface{}) {
-	ip := (*iface)(unsafe.Pointer(&i))
-	tab := ip.tab
+func assertI2E(inter *interfacetype, i iface, r *eface) {
+	tab := i.tab
 	if tab == nil {
 		// explicit conversions require non-nil interface value.
 		panic(&TypeAssertionError{"", "", *inter.typ._string, ""})
 	}
-	rp := (*eface)(unsafe.Pointer(r))
-	rp._type = tab._type
-	rp.data = ip.data
+	r._type = tab._type
+	r.data = i.data
 	return
 }
 
 // The compiler ensures that r is non-nil.
-func assertI2E2(inter *interfacetype, i fInterface, r *interface{}) bool {
-	ip := (*iface)(unsafe.Pointer(&i))
-	tab := ip.tab
+func assertI2E2(inter *interfacetype, i iface, r *eface) bool {
+	tab := i.tab
 	if tab == nil {
 		return false
 	}
-	rp := (*eface)(unsafe.Pointer(r))
-	rp._type = tab._type
-	rp.data = ip.data
+	r._type = tab._type
+	r.data = i.data
 	return true
 }
 
-func convI2I(inter *interfacetype, i fInterface) (r fInterface) {
-	ip := (*iface)(unsafe.Pointer(&i))
-	tab := ip.tab
+func convI2I(inter *interfacetype, i iface) (r iface) {
+	tab := i.tab
 	if tab == nil {
 		return
 	}
-	rp := (*iface)(unsafe.Pointer(&r))
 	if tab.inter == inter {
-		rp.tab = tab
-		rp.data = ip.data
+		r.tab = tab
+		r.data = i.data
 		return
 	}
-	rp.tab = getitab(inter, tab._type, false)
-	rp.data = ip.data
+	r.tab = getitab(inter, tab._type, false)
+	r.data = i.data
 	return
 }
 
-func assertI2I(inter *interfacetype, i fInterface, r *fInterface) {
-	ip := (*iface)(unsafe.Pointer(&i))
-	tab := ip.tab
+func assertI2I(inter *interfacetype, i iface, r *iface) {
+	tab := i.tab
 	if tab == nil {
 		// explicit conversions require non-nil interface value.
 		panic(&TypeAssertionError{"", "", *inter.typ._string, ""})
 	}
-	rp := (*iface)(unsafe.Pointer(r))
 	if tab.inter == inter {
-		rp.tab = tab
-		rp.data = ip.data
+		r.tab = tab
+		r.data = i.data
 		return
 	}
-	rp.tab = getitab(inter, tab._type, false)
-	rp.data = ip.data
+	r.tab = getitab(inter, tab._type, false)
+	r.data = i.data
 }
 
-func assertI2I2(inter *interfacetype, i fInterface, r *fInterface) bool {
-	ip := (*iface)(unsafe.Pointer(&i))
-	tab := ip.tab
+func assertI2I2(inter *interfacetype, i iface, r *iface) bool {
+	tab := i.tab
 	if tab == nil {
 		if r != nil {
-			*r = nil
+			*r = iface{}
 		}
 		return false
 	}
@@ -334,68 +326,62 @@ func assertI2I2(inter *interfacetype, i fInterface, r *fInterface) bool {
 		tab = getitab(inter, tab._type, true)
 		if tab == nil {
 			if r != nil {
-				*r = nil
+				*r = iface{}
 			}
 			return false
 		}
 	}
 	if r != nil {
-		rp := (*iface)(unsafe.Pointer(r))
-		rp.tab = tab
-		rp.data = ip.data
+		r.tab = tab
+		r.data = i.data
 	}
 	return true
 }
 
-func assertE2I(inter *interfacetype, e interface{}, r *fInterface) {
-	ep := (*eface)(unsafe.Pointer(&e))
-	t := ep._type
+func assertE2I(inter *interfacetype, e eface, r *iface) {
+	t := e._type
 	if t == nil {
 		// explicit conversions require non-nil interface value.
 		panic(&TypeAssertionError{"", "", *inter.typ._string, ""})
 	}
-	rp := (*iface)(unsafe.Pointer(r))
-	rp.tab = getitab(inter, t, false)
-	rp.data = ep.data
+	r.tab = getitab(inter, t, false)
+	r.data = e.data
 }
 
 var testingAssertE2I2GC bool
 
-func assertE2I2(inter *interfacetype, e interface{}, r *fInterface) bool {
+func assertE2I2(inter *interfacetype, e eface, r *iface) bool {
 	if testingAssertE2I2GC {
 		GC()
 	}
-	ep := (*eface)(unsafe.Pointer(&e))
-	t := ep._type
+	t := e._type
 	if t == nil {
 		if r != nil {
-			*r = nil
+			*r = iface{}
 		}
 		return false
 	}
 	tab := getitab(inter, t, true)
 	if tab == nil {
 		if r != nil {
-			*r = nil
+			*r = iface{}
 		}
 		return false
 	}
 	if r != nil {
-		rp := (*iface)(unsafe.Pointer(r))
-		rp.tab = tab
-		rp.data = ep.data
+		r.tab = tab
+		r.data = e.data
 	}
 	return true
 }
 
 //go:linkname reflect_ifaceE2I reflect.ifaceE2I
-func reflect_ifaceE2I(inter *interfacetype, e interface{}, dst *fInterface) {
+func reflect_ifaceE2I(inter *interfacetype, e eface, dst *iface) {
 	assertE2I(inter, e, dst)
 }
 
-func assertE2E(inter *interfacetype, e interface{}, r *interface{}) {
-	ep := (*eface)(unsafe.Pointer(&e))
-	if ep._type == nil {
+func assertE2E(inter *interfacetype, e eface, r *eface) {
+	if e._type == nil {
 		// explicit conversions require non-nil interface value.
 		panic(&TypeAssertionError{"", "", *inter.typ._string, ""})
 	}
@@ -403,28 +389,25 @@ func assertE2E(inter *interfacetype, e interface{}, r *interface{}) {
 }
 
 // The compiler ensures that r is non-nil.
-func assertE2E2(inter *interfacetype, e interface{}, r *interface{}) bool {
-	ep := (*eface)(unsafe.Pointer(&e))
-	if ep._type == nil {
-		*r = nil
+func assertE2E2(inter *interfacetype, e eface, r *eface) bool {
+	if e._type == nil {
+		*r = eface{}
 		return false
 	}
 	*r = e
 	return true
 }
 
-func ifacethash(i fInterface) uint32 {
-	ip := (*iface)(unsafe.Pointer(&i))
-	tab := ip.tab
+func ifacethash(i iface) uint32 {
+	tab := i.tab
 	if tab == nil {
 		return 0
 	}
 	return tab._type.hash
 }
 
-func efacethash(e interface{}) uint32 {
-	ep := (*eface)(unsafe.Pointer(&e))
-	t := ep._type
+func efacethash(e eface) uint32 {
+	t := e._type
 	if t == nil {
 		return 0
 	}
diff --git a/src/runtime/internal/atomic/asm.s b/src/runtime/internal/atomic/asm.s
new file mode 100644
index 0000000..b5d0211
--- /dev/null
+++ b/src/runtime/internal/atomic/asm.s
@@ -0,0 +1,8 @@
+// Copyright 2015 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"
+
+TEXT runtime∕internal∕atomic·nop(SB),NOSPLIT,$0-0
+	RET
diff --git a/src/runtime/internal/atomic/asm_386.s b/src/runtime/internal/atomic/asm_386.s
new file mode 100644
index 0000000..ce84fd8
--- /dev/null
+++ b/src/runtime/internal/atomic/asm_386.s
@@ -0,0 +1,166 @@
+// Copyright 2015 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"
+
+// bool Cas(int32 *val, int32 old, int32 new)
+// Atomically:
+//	if(*val == old){
+//		*val = new;
+//		return 1;
+//	}else
+//		return 0;
+TEXT runtime∕internal∕atomic·Cas(SB), NOSPLIT, $0-13
+	MOVL	ptr+0(FP), BX
+	MOVL	old+4(FP), AX
+	MOVL	new+8(FP), CX
+	LOCK
+	CMPXCHGL	CX, 0(BX)
+	SETEQ	ret+12(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Casuintptr(SB), NOSPLIT, $0-13
+	JMP	runtime∕internal∕atomic·Cas(SB)
+
+TEXT runtime∕internal∕atomic·Loaduintptr(SB), NOSPLIT, $0-8
+	JMP	runtime∕internal∕atomic·Load(SB)
+
+TEXT runtime∕internal∕atomic·Loaduint(SB), NOSPLIT, $0-8
+	JMP	runtime∕internal∕atomic·Load(SB)
+
+TEXT runtime∕internal∕atomic·Storeuintptr(SB), NOSPLIT, $0-8
+	JMP	runtime∕internal∕atomic·Store(SB)
+
+TEXT runtime∕internal∕atomic·Xadduintptr(SB), NOSPLIT, $0-8
+	JMP runtime∕internal∕atomic·Xadd(SB)
+
+TEXT runtime∕internal∕atomic·Loadint64(SB), NOSPLIT, $0-16
+	JMP runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Xaddint64(SB), NOSPLIT, $0-16
+	JMP runtime∕internal∕atomic·Xadd64(SB)
+
+
+// bool runtime∕internal∕atomic·Cas64(uint64 *val, uint64 old, uint64 new)
+// Atomically:
+//	if(*val == *old){
+//		*val = new;
+//		return 1;
+//	} else {
+//		return 0;
+//	}
+TEXT runtime∕internal∕atomic·Cas64(SB), NOSPLIT, $0-21
+	MOVL	ptr+0(FP), BP
+	MOVL	old_lo+4(FP), AX
+	MOVL	old_hi+8(FP), DX
+	MOVL	new_lo+12(FP), BX
+	MOVL	new_hi+16(FP), CX
+	LOCK
+	CMPXCHG8B	0(BP)
+	SETEQ	ret+20(FP)
+	RET
+
+// bool Casp(void **p, void *old, void *new)
+// Atomically:
+//	if(*p == old){
+//		*p = new;
+//		return 1;
+//	}else
+//		return 0;
+TEXT runtime∕internal∕atomic·Casp1(SB), NOSPLIT, $0-13
+	MOVL	ptr+0(FP), BX
+	MOVL	old+4(FP), AX
+	MOVL	new+8(FP), CX
+	LOCK
+	CMPXCHGL	CX, 0(BX)
+	SETEQ	ret+12(FP)
+	RET
+
+// uint32 Xadd(uint32 volatile *val, int32 delta)
+// Atomically:
+//	*val += delta;
+//	return *val;
+TEXT runtime∕internal∕atomic·Xadd(SB), NOSPLIT, $0-12
+	MOVL	ptr+0(FP), BX
+	MOVL	delta+4(FP), AX
+	MOVL	AX, CX
+	LOCK
+	XADDL	AX, 0(BX)
+	ADDL	CX, AX
+	MOVL	AX, ret+8(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Xchg(SB), NOSPLIT, $0-12
+	MOVL	ptr+0(FP), BX
+	MOVL	new+4(FP), AX
+	XCHGL	AX, 0(BX)
+	MOVL	AX, ret+8(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Xchguintptr(SB), NOSPLIT, $0-12
+	JMP	runtime∕internal∕atomic·Xchg(SB)
+
+
+TEXT runtime∕internal∕atomic·Storep1(SB), NOSPLIT, $0-8
+	MOVL	ptr+0(FP), BX
+	MOVL	val+4(FP), AX
+	XCHGL	AX, 0(BX)
+	RET
+
+TEXT runtime∕internal∕atomic·Store(SB), NOSPLIT, $0-8
+	MOVL	ptr+0(FP), BX
+	MOVL	val+4(FP), AX
+	XCHGL	AX, 0(BX)
+	RET
+
+// uint64 atomicload64(uint64 volatile* addr);
+TEXT runtime∕internal∕atomic·Load64(SB), NOSPLIT, $0-12
+	MOVL	ptr+0(FP), AX
+	TESTL	$7, AX
+	JZ	2(PC)
+	MOVL	0, AX // crash with nil ptr deref
+	LEAL	ret_lo+4(FP), BX
+	// MOVQ (%EAX), %MM0
+	BYTE $0x0f; BYTE $0x6f; BYTE $0x00
+	// MOVQ %MM0, 0(%EBX)
+	BYTE $0x0f; BYTE $0x7f; BYTE $0x03
+	// EMMS
+	BYTE $0x0F; BYTE $0x77
+	RET
+
+// void runtime∕internal∕atomic·Store64(uint64 volatile* addr, uint64 v);
+TEXT runtime∕internal∕atomic·Store64(SB), NOSPLIT, $0-12
+	MOVL	ptr+0(FP), AX
+	TESTL	$7, AX
+	JZ	2(PC)
+	MOVL	0, AX // crash with nil ptr deref
+	// MOVQ and EMMS were introduced on the Pentium MMX.
+	// MOVQ 0x8(%ESP), %MM0
+	BYTE $0x0f; BYTE $0x6f; BYTE $0x44; BYTE $0x24; BYTE $0x08
+	// MOVQ %MM0, (%EAX)
+	BYTE $0x0f; BYTE $0x7f; BYTE $0x00 
+	// EMMS
+	BYTE $0x0F; BYTE $0x77
+	// This is essentially a no-op, but it provides required memory fencing.
+	// It can be replaced with MFENCE, but MFENCE was introduced only on the Pentium4 (SSE2).
+	MOVL	$0, AX
+	LOCK
+	XADDL	AX, (SP)
+	RET
+
+// void	runtime∕internal∕atomic·Or8(byte volatile*, byte);
+TEXT runtime∕internal∕atomic·Or8(SB), NOSPLIT, $0-5
+	MOVL	ptr+0(FP), AX
+	MOVB	val+4(FP), BX
+	LOCK
+	ORB	BX, (AX)
+	RET
+
+// void	runtime∕internal∕atomic·And8(byte volatile*, byte);
+TEXT runtime∕internal∕atomic·And8(SB), NOSPLIT, $0-5
+	MOVL	ptr+0(FP), AX
+	MOVB	val+4(FP), BX
+	LOCK
+	ANDB	BX, (AX)
+	RET
diff --git a/src/runtime/internal/atomic/asm_amd64.s b/src/runtime/internal/atomic/asm_amd64.s
new file mode 100644
index 0000000..7463fec
--- /dev/null
+++ b/src/runtime/internal/atomic/asm_amd64.s
@@ -0,0 +1,150 @@
+// Copyright 2015 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"
+
+// bool Cas(int32 *val, int32 old, int32 new)
+// Atomically:
+//	if(*val == old){
+//		*val = new;
+//		return 1;
+//	} else
+//		return 0;
+TEXT runtime∕internal∕atomic·Cas(SB),NOSPLIT,$0-17
+	MOVQ	ptr+0(FP), BX
+	MOVL	old+8(FP), AX
+	MOVL	new+12(FP), CX
+	LOCK
+	CMPXCHGL	CX, 0(BX)
+	SETEQ	ret+16(FP)
+	RET
+
+// bool	runtime∕internal∕atomic·Cas64(uint64 *val, uint64 old, uint64 new)
+// Atomically:
+//	if(*val == *old){
+//		*val = new;
+//		return 1;
+//	} else {
+//		return 0;
+//	}
+TEXT runtime∕internal∕atomic·Cas64(SB), NOSPLIT, $0-25
+	MOVQ	ptr+0(FP), BX
+	MOVQ	old+8(FP), AX
+	MOVQ	new+16(FP), CX
+	LOCK
+	CMPXCHGQ	CX, 0(BX)
+	SETEQ	ret+24(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Casuintptr(SB), NOSPLIT, $0-25
+	JMP	runtime∕internal∕atomic·Cas64(SB)
+
+TEXT runtime∕internal∕atomic·Loaduintptr(SB), NOSPLIT, $0-16
+	JMP	runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Loaduint(SB), NOSPLIT, $0-16
+	JMP	runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Storeuintptr(SB), NOSPLIT, $0-16
+	JMP	runtime∕internal∕atomic·Store64(SB)
+
+TEXT runtime∕internal∕atomic·Loadint64(SB), NOSPLIT, $0-16
+	JMP	runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Xaddint64(SB), NOSPLIT, $0-16
+	JMP	runtime∕internal∕atomic·Xadd64(SB)
+
+// bool Casp(void **val, void *old, void *new)
+// Atomically:
+//	if(*val == old){
+//		*val = new;
+//		return 1;
+//	} else
+//		return 0;
+TEXT runtime∕internal∕atomic·Casp1(SB), NOSPLIT, $0-25
+	MOVQ	ptr+0(FP), BX
+	MOVQ	old+8(FP), AX
+	MOVQ	new+16(FP), CX
+	LOCK
+	CMPXCHGQ	CX, 0(BX)
+	SETEQ	ret+24(FP)
+	RET
+
+// uint32 Xadd(uint32 volatile *val, int32 delta)
+// Atomically:
+//	*val += delta;
+//	return *val;
+TEXT runtime∕internal∕atomic·Xadd(SB), NOSPLIT, $0-20
+	MOVQ	ptr+0(FP), BX
+	MOVL	delta+8(FP), AX
+	MOVL	AX, CX
+	LOCK
+	XADDL	AX, 0(BX)
+	ADDL	CX, AX
+	MOVL	AX, ret+16(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Xadd64(SB), NOSPLIT, $0-24
+	MOVQ	ptr+0(FP), BX
+	MOVQ	delta+8(FP), AX
+	MOVQ	AX, CX
+	LOCK
+	XADDQ	AX, 0(BX)
+	ADDQ	CX, AX
+	MOVQ	AX, ret+16(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Xadduintptr(SB), NOSPLIT, $0-24
+	JMP	runtime∕internal∕atomic·Xadd64(SB)
+
+TEXT runtime∕internal∕atomic·Xchg(SB), NOSPLIT, $0-20
+	MOVQ	ptr+0(FP), BX
+	MOVL	new+8(FP), AX
+	XCHGL	AX, 0(BX)
+	MOVL	AX, ret+16(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Xchg64(SB), NOSPLIT, $0-24
+	MOVQ	ptr+0(FP), BX
+	MOVQ	new+8(FP), AX
+	XCHGQ	AX, 0(BX)
+	MOVQ	AX, ret+16(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Xchguintptr(SB), NOSPLIT, $0-24
+	JMP	runtime∕internal∕atomic·Xchg64(SB)
+
+TEXT runtime∕internal∕atomic·Storep1(SB), NOSPLIT, $0-16
+	MOVQ	ptr+0(FP), BX
+	MOVQ	val+8(FP), AX
+	XCHGQ	AX, 0(BX)
+	RET
+
+TEXT runtime∕internal∕atomic·Store(SB), NOSPLIT, $0-12
+	MOVQ	ptr+0(FP), BX
+	MOVL	val+8(FP), AX
+	XCHGL	AX, 0(BX)
+	RET
+
+TEXT runtime∕internal∕atomic·Store64(SB), NOSPLIT, $0-16
+	MOVQ	ptr+0(FP), BX
+	MOVQ	val+8(FP), AX
+	XCHGQ	AX, 0(BX)
+	RET
+
+// void	runtime∕internal∕atomic·Or8(byte volatile*, byte);
+TEXT runtime∕internal∕atomic·Or8(SB), NOSPLIT, $0-9
+	MOVQ	ptr+0(FP), AX
+	MOVB	val+8(FP), BX
+	LOCK
+	ORB	BX, (AX)
+	RET
+
+// void	runtime∕internal∕atomic·And8(byte volatile*, byte);
+TEXT runtime∕internal∕atomic·And8(SB), NOSPLIT, $0-9
+	MOVQ	ptr+0(FP), AX
+	MOVB	val+8(FP), BX
+	LOCK
+	ANDB	BX, (AX)
+	RET
diff --git a/src/runtime/internal/atomic/asm_amd64p32.s b/src/runtime/internal/atomic/asm_amd64p32.s
new file mode 100644
index 0000000..f1e2c3a
--- /dev/null
+++ b/src/runtime/internal/atomic/asm_amd64p32.s
@@ -0,0 +1,150 @@
+// Copyright 2015 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"
+
+// bool Cas(int32 *val, int32 old, int32 new)
+// Atomically:
+//	if(*val == old){
+//		*val = new;
+//		return 1;
+//	} else
+//		return 0;
+TEXT runtime∕internal∕atomic·Cas(SB), NOSPLIT, $0-17
+	MOVL	ptr+0(FP), BX
+	MOVL	old+4(FP), AX
+	MOVL	new+8(FP), CX
+	LOCK
+	CMPXCHGL	CX, 0(BX)
+	SETEQ	ret+16(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Casuintptr(SB), NOSPLIT, $0-17
+	JMP	runtime∕internal∕atomic·Cas(SB)
+
+TEXT runtime∕internal∕atomic·Loaduintptr(SB), NOSPLIT, $0-12
+	JMP	runtime∕internal∕atomic·Load(SB)
+
+TEXT runtime∕internal∕atomic·Loaduint(SB), NOSPLIT, $0-12
+	JMP	runtime∕internal∕atomic·Load(SB)
+
+TEXT runtime∕internal∕atomic·Storeuintptr(SB), NOSPLIT, $0-12
+	JMP	runtime∕internal∕atomic·Store(SB)
+
+TEXT runtime∕internal∕atomic·Loadint64(SB), NOSPLIT, $0-24
+	JMP	runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Xaddint64(SB), NOSPLIT, $0-24
+	JMP	runtime∕internal∕atomic·Xadd64(SB)
+
+// bool	runtime∕internal∕atomic·cas64(uint64 *val, uint64 old, uint64 new)
+// Atomically:
+//	if(*val == *old){
+//		*val = new;
+//		return 1;
+//	} else {
+//		return 0;
+//	}
+TEXT runtime∕internal∕atomic·Cas64(SB), NOSPLIT, $0-25
+	MOVL	ptr+0(FP), BX
+	MOVQ	old+8(FP), AX
+	MOVQ	new+16(FP), CX
+	LOCK
+	CMPXCHGQ	CX, 0(BX)
+	SETEQ	ret+24(FP)
+	RET
+
+// bool Casp(void **val, void *old, void *new)
+// Atomically:
+//	if(*val == old){
+//		*val = new;
+//		return 1;
+//	} else
+//		return 0;
+TEXT runtime∕internal∕atomic·Casp1(SB), NOSPLIT, $0-17
+	MOVL	ptr+0(FP), BX
+	MOVL	old+4(FP), AX
+	MOVL	new+8(FP), CX
+	LOCK
+	CMPXCHGL	CX, 0(BX)
+	SETEQ	ret+16(FP)
+	RET
+
+// uint32 Xadd(uint32 volatile *val, int32 delta)
+// Atomically:
+//	*val += delta;
+//	return *val;
+TEXT runtime∕internal∕atomic·Xadd(SB), NOSPLIT, $0-12
+	MOVL	ptr+0(FP), BX
+	MOVL	delta+4(FP), AX
+	MOVL	AX, CX
+	LOCK
+	XADDL	AX, 0(BX)
+	ADDL	CX, AX
+	MOVL	AX, ret+8(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Xadd64(SB), NOSPLIT, $0-24
+	MOVL	ptr+0(FP), BX
+	MOVQ	delta+8(FP), AX
+	MOVQ	AX, CX
+	LOCK
+	XADDQ	AX, 0(BX)
+	ADDQ	CX, AX
+	MOVQ	AX, ret+16(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Xadduintptr(SB), NOSPLIT, $0-12
+	JMP	runtime∕internal∕atomic·Xadd(SB)
+
+TEXT runtime∕internal∕atomic·Xchg(SB), NOSPLIT, $0-12
+	MOVL	ptr+0(FP), BX
+	MOVL	new+4(FP), AX
+	XCHGL	AX, 0(BX)
+	MOVL	AX, ret+8(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Xchg64(SB), NOSPLIT, $0-24
+	MOVL	ptr+0(FP), BX
+	MOVQ	new+8(FP), AX
+	XCHGQ	AX, 0(BX)
+	MOVQ	AX, ret+16(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Xchguintptr(SB), NOSPLIT, $0-12
+	JMP	runtime∕internal∕atomic·Xchg(SB)
+
+TEXT runtime∕internal∕atomic·Storep1(SB), NOSPLIT, $0-8
+	MOVL	ptr+0(FP), BX
+	MOVL	val+4(FP), AX
+	XCHGL	AX, 0(BX)
+	RET
+
+TEXT runtime∕internal∕atomic·Store(SB), NOSPLIT, $0-8
+	MOVL	ptr+0(FP), BX
+	MOVL	val+4(FP), AX
+	XCHGL	AX, 0(BX)
+	RET
+
+TEXT runtime∕internal∕atomic·Store64(SB), NOSPLIT, $0-16
+	MOVL	ptr+0(FP), BX
+	MOVQ	val+8(FP), AX
+	XCHGQ	AX, 0(BX)
+	RET
+
+// void	runtime∕internal∕atomic·Or8(byte volatile*, byte);
+TEXT runtime∕internal∕atomic·Or8(SB), NOSPLIT, $0-5
+	MOVL	ptr+0(FP), BX
+	MOVB	val+4(FP), AX
+	LOCK
+	ORB	AX, 0(BX)
+	RET
+
+// void	runtime∕internal∕atomic·And8(byte volatile*, byte);
+TEXT runtime∕internal∕atomic·And8(SB), NOSPLIT, $0-5
+	MOVL	ptr+0(FP), BX
+	MOVB	val+4(FP), AX
+	LOCK
+	ANDB	AX, 0(BX)
+	RET
diff --git a/src/runtime/internal/atomic/asm_arm.s b/src/runtime/internal/atomic/asm_arm.s
new file mode 100644
index 0000000..235e8bf
--- /dev/null
+++ b/src/runtime/internal/atomic/asm_arm.s
@@ -0,0 +1,71 @@
+// Copyright 2015 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"
+
+// bool armcas(int32 *val, int32 old, int32 new)
+// Atomically:
+//	if(*val == old){
+//		*val = new;
+//		return 1;
+//	}else
+//		return 0;
+//
+// To implement runtime∕internal∕atomic·cas in sys_$GOOS_arm.s
+// using the native instructions, use:
+//
+//	TEXT runtime∕internal∕atomic·cas(SB),NOSPLIT,$0
+//		B	runtime∕internal∕atomic·armcas(SB)
+//
+TEXT runtime∕internal∕atomic·armcas(SB),NOSPLIT,$0-13
+	MOVW	valptr+0(FP), R1
+	MOVW	old+4(FP), R2
+	MOVW	new+8(FP), R3
+casl:
+	LDREX	(R1), R0
+	CMP	R0, R2
+	BNE	casfail
+
+	MOVB	runtime·goarm(SB), R11
+	CMP	$7, R11
+	BLT	2(PC)
+	WORD	$0xf57ff05a	// dmb ishst
+
+	STREX	R3, (R1), R0
+	CMP	$0, R0
+	BNE	casl
+	MOVW	$1, R0
+
+	MOVB	runtime·goarm(SB), R11
+	CMP	$7, R11
+	BLT	2(PC)
+	WORD	$0xf57ff05b	// dmb ish
+
+	MOVB	R0, ret+12(FP)
+	RET
+casfail:
+	MOVW	$0, R0
+	MOVB	R0, ret+12(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Casuintptr(SB),NOSPLIT,$0-13
+	B	runtime∕internal∕atomic·Cas(SB)
+
+TEXT runtime∕internal∕atomic·Loaduintptr(SB),NOSPLIT,$0-8
+	B	runtime∕internal∕atomic·Load(SB)
+
+TEXT runtime∕internal∕atomic·Loaduint(SB),NOSPLIT,$0-8
+	B	runtime∕internal∕atomic·Load(SB)
+
+TEXT runtime∕internal∕atomic·Storeuintptr(SB),NOSPLIT,$0-8
+	B	runtime∕internal∕atomic·Store(SB)
+
+TEXT runtime∕internal∕atomic·Xadduintptr(SB),NOSPLIT,$0-8
+	B	runtime∕internal∕atomic·Xadd(SB)
+
+TEXT runtime∕internal∕atomic·Loadint64(SB),NOSPLIT,$0-16
+	B	runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Xaddint64(SB),NOSPLIT,$0-16
+	B	runtime∕internal∕atomic·Xadd64(SB)
diff --git a/src/runtime/internal/atomic/asm_arm64.s b/src/runtime/internal/atomic/asm_arm64.s
new file mode 100644
index 0000000..c255677
--- /dev/null
+++ b/src/runtime/internal/atomic/asm_arm64.s
@@ -0,0 +1,58 @@
+// Copyright 2015 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"
+
+// bool Cas(uint32 *ptr, uint32 old, uint32 new)
+// Atomically:
+//	if(*val == old){
+//		*val = new;
+//		return 1;
+//	} else
+//		return 0;
+TEXT runtime∕internal∕atomic·Cas(SB), NOSPLIT, $0-17
+	MOVD	ptr+0(FP), R0
+	MOVW	old+8(FP), R1
+	MOVW	new+12(FP), R2
+again:
+	LDAXRW	(R0), R3
+	CMPW	R1, R3
+	BNE	ok
+	STLXRW	R2, (R0), R3
+	CBNZ	R3, again
+ok:
+	CSET	EQ, R0
+	MOVB	R0, ret+16(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Casuintptr(SB), NOSPLIT, $0-25
+	B	runtime∕internal∕atomic·Cas64(SB)
+
+TEXT runtime∕internal∕atomic·Loaduintptr(SB), NOSPLIT, $-8-16
+	B	runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Loaduint(SB), NOSPLIT, $-8-16
+	B	runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Storeuintptr(SB), NOSPLIT, $0-16
+	B	runtime∕internal∕atomic·Store64(SB)
+
+TEXT runtime∕internal∕atomic·Xadduintptr(SB), NOSPLIT, $0-16
+	B	runtime∕internal∕atomic·Xadd64(SB)
+
+TEXT runtime∕internal∕atomic·Loadint64(SB), NOSPLIT, $0-16
+	B	runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Xaddint64(SB), NOSPLIT, $0-16
+	B	runtime∕internal∕atomic·Xadd64(SB)
+
+// bool Casp(void **val, void *old, void *new)
+// Atomically:
+//	if(*val == old){
+//		*val = new;
+//		return 1;
+//	} else
+//		return 0;
+TEXT runtime∕internal∕atomic·Casp1(SB), NOSPLIT, $0-25
+	B runtime∕internal∕atomic·Cas64(SB)
diff --git a/src/runtime/internal/atomic/asm_mips64x.s b/src/runtime/internal/atomic/asm_mips64x.s
new file mode 100644
index 0000000..4cab434
--- /dev/null
+++ b/src/runtime/internal/atomic/asm_mips64x.s
@@ -0,0 +1,231 @@
+// Copyright 2015 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.
+
+// +build mips64 mips64le
+
+#include "textflag.h"
+
+#define LL(base, rt)	WORD	$((060<<26)|((base)<<21)|((rt)<<16))
+#define LLV(base, rt)	WORD	$((064<<26)|((base)<<21)|((rt)<<16))
+#define SC(base, rt)	WORD	$((070<<26)|((base)<<21)|((rt)<<16))
+#define SCV(base, rt)	WORD	$((074<<26)|((base)<<21)|((rt)<<16))
+#define SYNC	WORD $0xf
+
+// bool cas(uint32 *ptr, uint32 old, uint32 new)
+// Atomically:
+//	if(*val == old){
+//		*val = new;
+//		return 1;
+//	} else
+//		return 0;
+TEXT ·Cas(SB), NOSPLIT, $0-17
+	MOVV	ptr+0(FP), R1
+	MOVW	old+8(FP), R2
+	MOVW	new+12(FP), R5
+	SYNC
+cas_again:
+	MOVV	R5, R3
+	LL(1, 4)	// R4 = *R1
+	BNE	R2, R4, cas_fail
+	SC(1, 3)	// *R1 = R3
+	BEQ	R3, cas_again
+	MOVV	$1, R1
+	MOVB	R1, ret+16(FP)
+	SYNC
+	RET
+cas_fail:
+	MOVV	$0, R1
+	JMP	-4(PC)
+
+// bool	cas64(uint64 *ptr, uint64 old, uint64 new)
+// Atomically:
+//	if(*val == *old){
+//		*val = new;
+//		return 1;
+//	} else {
+//		return 0;
+//	}
+TEXT ·Cas64(SB), NOSPLIT, $0-25
+	MOVV	ptr+0(FP), R1
+	MOVV	old+8(FP), R2
+	MOVV	new+16(FP), R5
+	SYNC
+cas64_again:
+	MOVV	R5, R3
+	LLV(1, 4)	// R4 = *R1
+	BNE	R2, R4, cas64_fail
+	SCV(1, 3)	// *R1 = R3
+	BEQ	R3, cas64_again
+	MOVV	$1, R1
+	MOVB	R1, ret+24(FP)
+	SYNC
+	RET
+cas64_fail:
+	MOVV	$0, R1
+	JMP	-4(PC)
+
+TEXT ·Casuintptr(SB), NOSPLIT, $0-25
+	JMP	·Cas64(SB)
+
+TEXT ·Loaduintptr(SB),  NOSPLIT|NOFRAME, $0-16
+	JMP	·Load64(SB)
+
+TEXT ·Loaduint(SB), NOSPLIT|NOFRAME, $0-16
+	JMP	·Load64(SB)
+
+TEXT ·Storeuintptr(SB), NOSPLIT, $0-16
+	JMP	·Store64(SB)
+
+TEXT ·Xadduintptr(SB), NOSPLIT, $0-24
+	JMP	·Xadd64(SB)
+
+TEXT ·Loadint64(SB), NOSPLIT, $0-16
+	JMP	·Load64(SB)
+
+TEXT ·Xaddint64(SB), NOSPLIT, $0-16
+	JMP	·Xadd64(SB)
+
+// bool casp(void **val, void *old, void *new)
+// Atomically:
+//	if(*val == old){
+//		*val = new;
+//		return 1;
+//	} else
+//		return 0;
+TEXT ·Casp1(SB), NOSPLIT, $0-25
+	JMP runtime∕internal∕atomic·Cas64(SB)
+
+// uint32 xadd(uint32 volatile *ptr, int32 delta)
+// Atomically:
+//	*val += delta;
+//	return *val;
+TEXT ·Xadd(SB), NOSPLIT, $0-20
+	MOVV	ptr+0(FP), R2
+	MOVW	delta+8(FP), R3
+	SYNC
+	LL(2, 1)	// R1 = *R2
+	ADDU	R1, R3, R4
+	MOVV	R4, R1
+	SC(2, 4)	// *R2 = R4
+	BEQ	R4, -4(PC)
+	MOVW	R1, ret+16(FP)
+	SYNC
+	RET
+
+TEXT ·Xadd64(SB), NOSPLIT, $0-24
+	MOVV	ptr+0(FP), R2
+	MOVV	delta+8(FP), R3
+	SYNC
+	LLV(2, 1)	// R1 = *R2
+	ADDVU	R1, R3, R4
+	MOVV	R4, R1
+	SCV(2, 4)	// *R2 = R4
+	BEQ	R4, -4(PC)
+	MOVV	R1, ret+16(FP)
+	SYNC
+	RET
+
+TEXT ·Xchg(SB), NOSPLIT, $0-20
+	MOVV	ptr+0(FP), R2
+	MOVW	new+8(FP), R5
+
+	SYNC
+	MOVV	R5, R3
+	LL(2, 1)	// R1 = *R2
+	SC(2, 3)	// *R2 = R3
+	BEQ	R3, -3(PC)
+	MOVW	R1, ret+16(FP)
+	SYNC
+	RET
+
+TEXT ·Xchg64(SB), NOSPLIT, $0-24
+	MOVV	ptr+0(FP), R2
+	MOVV	new+8(FP), R5
+
+	SYNC
+	MOVV	R5, R3
+	LLV(2, 1)	// R1 = *R2
+	SCV(2, 3)	// *R2 = R3
+	BEQ	R3, -3(PC)
+	MOVV	R1, ret+16(FP)
+	SYNC
+	RET
+
+TEXT ·Xchguintptr(SB), NOSPLIT, $0-24
+	JMP	·Xchg64(SB)
+
+TEXT ·Storep1(SB), NOSPLIT, $0-16
+	JMP	·Store64(SB)
+
+TEXT ·Store(SB), NOSPLIT, $0-12
+	MOVV	ptr+0(FP), R1
+	MOVW	val+8(FP), R2
+	SYNC
+	MOVW	R2, 0(R1)
+	SYNC
+	RET
+
+TEXT ·Store64(SB), NOSPLIT, $0-16
+	MOVV	ptr+0(FP), R1
+	MOVV	val+8(FP), R2
+	SYNC
+	MOVV	R2, 0(R1)
+	SYNC
+	RET
+
+// void	Or8(byte volatile*, byte);
+TEXT ·Or8(SB), NOSPLIT, $0-9
+	MOVV	ptr+0(FP), R1
+	MOVBU	val+8(FP), R2
+	// Align ptr down to 4 bytes so we can use 32-bit load/store.
+	MOVV	$~3, R3
+	AND	R1, R3
+	// Compute val shift.
+#ifdef GOARCH_mips64
+	// Big endian.  ptr = ptr ^ 3
+	XOR	$3, R1
+#endif
+	// R4 = ((ptr & 3) * 8)
+	AND	$3, R1, R4
+	SLLV	$3, R4
+	// Shift val for aligned ptr.  R2 = val << R4
+	SLLV	R4, R2
+
+	SYNC
+	LL(3, 4)	// R4 = *R3
+	OR	R2, R4
+	SC(3, 4)	// *R3 = R4
+	BEQ	R4, -4(PC)
+	SYNC
+	RET
+
+// void	And8(byte volatile*, byte);
+TEXT ·And8(SB), NOSPLIT, $0-9
+	MOVV	ptr+0(FP), R1
+	MOVBU	val+8(FP), R2
+	// Align ptr down to 4 bytes so we can use 32-bit load/store.
+	MOVV	$~3, R3
+	AND	R1, R3
+	// Compute val shift.
+#ifdef GOARCH_mips64
+	// Big endian.  ptr = ptr ^ 3
+	XOR	$3, R1
+#endif
+	// R4 = ((ptr & 3) * 8)
+	AND	$3, R1, R4
+	SLLV	$3, R4
+	// Shift val for aligned ptr.  R2 = val << R4 | ^(0xFF << R4)
+	MOVV	$0xFF, R5
+	SLLV	R4, R2
+	SLLV	R4, R5
+	NOR	R0, R5
+	OR	R5, R2
+
+	SYNC
+	LL(3, 4)	// R4 = *R3
+	AND	R2, R4
+	SC(3, 4)	// *R3 = R4
+	BEQ	R4, -4(PC)
+	SYNC
+	RET
diff --git a/src/runtime/internal/atomic/asm_ppc64x.s b/src/runtime/internal/atomic/asm_ppc64x.s
new file mode 100644
index 0000000..87f7f5d
--- /dev/null
+++ b/src/runtime/internal/atomic/asm_ppc64x.s
@@ -0,0 +1,225 @@
+// Copyright 2015 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.
+
+// +build ppc64 ppc64le
+
+#include "textflag.h"
+
+// bool cas(uint32 *ptr, uint32 old, uint32 new)
+// Atomically:
+//	if(*val == old){
+//		*val = new;
+//		return 1;
+//	} else
+//		return 0;
+TEXT runtime∕internal∕atomic·Cas(SB), NOSPLIT, $0-17
+	MOVD	ptr+0(FP), R3
+	MOVWZ	old+8(FP), R4
+	MOVWZ	new+12(FP), R5
+cas_again:
+	SYNC
+	LWAR	(R3), R6
+	CMPW	R6, R4
+	BNE	cas_fail
+	STWCCC	R5, (R3)
+	BNE	cas_again
+	MOVD	$1, R3
+	SYNC
+	ISYNC
+	MOVB	R3, ret+16(FP)
+	RET
+cas_fail:
+	MOVD	$0, R3
+	BR	-5(PC)
+
+// bool	runtime∕internal∕atomic·Cas64(uint64 *ptr, uint64 old, uint64 new)
+// Atomically:
+//	if(*val == *old){
+//		*val = new;
+//		return 1;
+//	} else {
+//		return 0;
+//	}
+TEXT runtime∕internal∕atomic·Cas64(SB), NOSPLIT, $0-25
+	MOVD	ptr+0(FP), R3
+	MOVD	old+8(FP), R4
+	MOVD	new+16(FP), R5
+cas64_again:
+	SYNC
+	LDAR	(R3), R6
+	CMP	R6, R4
+	BNE	cas64_fail
+	STDCCC	R5, (R3)
+	BNE	cas64_again
+	MOVD	$1, R3
+	SYNC
+	ISYNC
+	MOVB	R3, ret+24(FP)
+	RET
+cas64_fail:
+	MOVD	$0, R3
+	BR	-5(PC)
+
+TEXT runtime∕internal∕atomic·Casuintptr(SB), NOSPLIT, $0-25
+	BR	runtime∕internal∕atomic·Cas64(SB)
+
+TEXT runtime∕internal∕atomic·Loaduintptr(SB),  NOSPLIT|NOFRAME, $0-16
+	BR	runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Loaduint(SB), NOSPLIT|NOFRAME, $0-16
+	BR	runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Storeuintptr(SB), NOSPLIT, $0-16
+	BR	runtime∕internal∕atomic·Store64(SB)
+
+TEXT runtime∕internal∕atomic·Xadduintptr(SB), NOSPLIT, $0-24
+	BR	runtime∕internal∕atomic·Xadd64(SB)
+
+TEXT runtime∕internal∕atomic·Loadint64(SB), NOSPLIT, $0-16
+	BR	runtime∕internal∕atomic·Load64(SB)
+
+TEXT runtime∕internal∕atomic·Xaddint64(SB), NOSPLIT, $0-16
+	BR	runtime∕internal∕atomic·Xadd64(SB)
+
+// bool casp(void **val, void *old, void *new)
+// Atomically:
+//	if(*val == old){
+//		*val = new;
+//		return 1;
+//	} else
+//		return 0;
+TEXT runtime∕internal∕atomic·Casp1(SB), NOSPLIT, $0-25
+	BR runtime∕internal∕atomic·Cas64(SB)
+
+// uint32 xadd(uint32 volatile *ptr, int32 delta)
+// Atomically:
+//	*val += delta;
+//	return *val;
+TEXT runtime∕internal∕atomic·Xadd(SB), NOSPLIT, $0-20
+	MOVD	ptr+0(FP), R4
+	MOVW	delta+8(FP), R5
+	SYNC
+	LWAR	(R4), R3
+	ADD	R5, R3
+	STWCCC	R3, (R4)
+	BNE	-4(PC)
+	SYNC
+	ISYNC
+	MOVW	R3, ret+16(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Xadd64(SB), NOSPLIT, $0-24
+	MOVD	ptr+0(FP), R4
+	MOVD	delta+8(FP), R5
+	SYNC
+	LDAR	(R4), R3
+	ADD	R5, R3
+	STDCCC	R3, (R4)
+	BNE	-4(PC)
+	SYNC
+	ISYNC
+	MOVD	R3, ret+16(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Xchg(SB), NOSPLIT, $0-20
+	MOVD	ptr+0(FP), R4
+	MOVW	new+8(FP), R5
+	SYNC
+	LWAR	(R4), R3
+	STWCCC	R5, (R4)
+	BNE	-3(PC)
+	SYNC
+	ISYNC
+	MOVW	R3, ret+16(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Xchg64(SB), NOSPLIT, $0-24
+	MOVD	ptr+0(FP), R4
+	MOVD	new+8(FP), R5
+	SYNC
+	LDAR	(R4), R3
+	STDCCC	R5, (R4)
+	BNE	-3(PC)
+	SYNC
+	ISYNC
+	MOVD	R3, ret+16(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Xchguintptr(SB), NOSPLIT, $0-24
+	BR	runtime∕internal∕atomic·Xchg64(SB)
+
+
+TEXT runtime∕internal∕atomic·Storep1(SB), NOSPLIT, $0-16
+	BR	runtime∕internal∕atomic·Store64(SB)
+
+TEXT runtime∕internal∕atomic·Store(SB), NOSPLIT, $0-12
+	MOVD	ptr+0(FP), R3
+	MOVW	val+8(FP), R4
+	SYNC
+	MOVW	R4, 0(R3)
+	RET
+
+TEXT runtime∕internal∕atomic·Store64(SB), NOSPLIT, $0-16
+	MOVD	ptr+0(FP), R3
+	MOVD	val+8(FP), R4
+	SYNC
+	MOVD	R4, 0(R3)
+	RET
+
+// void	runtime∕internal∕atomic·Or8(byte volatile*, byte);
+TEXT runtime∕internal∕atomic·Or8(SB), NOSPLIT, $0-9
+	MOVD	ptr+0(FP), R3
+	MOVBZ	val+8(FP), R4
+	// Align ptr down to 4 bytes so we can use 32-bit load/store.
+	// R5 = (R3 << 0) & ~3
+	RLDCR	$0, R3, $~3, R5
+	// Compute val shift.
+#ifdef GOARCH_ppc64
+	// Big endian.  ptr = ptr ^ 3
+	XOR	$3, R3
+#endif
+	// R6 = ((ptr & 3) * 8) = (ptr << 3) & (3*8)
+	RLDC	$3, R3, $(3*8), R6
+	// Shift val for aligned ptr.  R4 = val << R6
+	SLD	R6, R4, R4
+
+again:
+	SYNC
+	LWAR	(R5), R6
+	OR	R4, R6
+	STWCCC	R6, (R5)
+	BNE	again
+	SYNC
+	ISYNC
+	RET
+
+// void	runtime∕internal∕atomic·And8(byte volatile*, byte);
+TEXT runtime∕internal∕atomic·And8(SB), NOSPLIT, $0-9
+	MOVD	ptr+0(FP), R3
+	MOVBZ	val+8(FP), R4
+	// Align ptr down to 4 bytes so we can use 32-bit load/store.
+	// R5 = (R3 << 0) & ~3
+	RLDCR	$0, R3, $~3, R5
+	// Compute val shift.
+#ifdef GOARCH_ppc64
+	// Big endian.  ptr = ptr ^ 3
+	XOR	$3, R3
+#endif
+	// R6 = ((ptr & 3) * 8) = (ptr << 3) & (3*8)
+	RLDC	$3, R3, $(3*8), R6
+	// Shift val for aligned ptr.  R4 = val << R6 | ^(0xFF << R6)
+	MOVD	$0xFF, R7
+	SLD	R6, R4
+	SLD	R6, R7
+	XOR $-1, R7
+	OR	R7, R4
+again:
+	SYNC
+	LWAR	(R5), R6
+	AND	R4, R6
+	STWCCC	R6, (R5)
+	BNE	again
+	SYNC
+	ISYNC
+	RET
diff --git a/src/runtime/internal/atomic/atomic_386.go b/src/runtime/internal/atomic/atomic_386.go
new file mode 100644
index 0000000..f4c50b0
--- /dev/null
+++ b/src/runtime/internal/atomic/atomic_386.go
@@ -0,0 +1,76 @@
+// Copyright 2009 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.
+
+// +build 386
+
+package atomic
+
+import "unsafe"
+
+//go:nosplit
+//go:noinline
+func Load(ptr *uint32) uint32 {
+	return *ptr
+}
+
+//go:nosplit
+//go:noinline
+func Loadp(ptr unsafe.Pointer) unsafe.Pointer {
+	return *(*unsafe.Pointer)(ptr)
+}
+
+//go:nosplit
+func Xadd64(ptr *uint64, delta int64) uint64 {
+	for {
+		old := *ptr
+		if Cas64(ptr, old, old+uint64(delta)) {
+			return old + uint64(delta)
+		}
+	}
+}
+
+//go:noescape
+func Xadduintptr(ptr *uintptr, delta uintptr) uintptr
+
+//go:nosplit
+func Xchg64(ptr *uint64, new uint64) uint64 {
+	for {
+		old := *ptr
+		if Cas64(ptr, old, new) {
+			return old
+		}
+	}
+}
+
+//go:noescape
+func Xadd(ptr *uint32, delta int32) uint32
+
+//go:noescape
+func Xchg(ptr *uint32, new uint32) uint32
+
+//go:noescape
+func Xchguintptr(ptr *uintptr, new uintptr) uintptr
+
+//go:noescape
+func Load64(ptr *uint64) uint64
+
+//go:noescape
+func And8(ptr *uint8, val uint8)
+
+//go:noescape
+func Or8(ptr *uint8, val uint8)
+
+// NOTE: Do not add atomicxor8 (XOR is not idempotent).
+
+//go:noescape
+func Cas64(ptr *uint64, old, new uint64) bool
+
+//go:noescape
+func Store(ptr *uint32, val uint32)
+
+//go:noescape
+func Store64(ptr *uint64, val uint64)
+
+// NO go:noescape annotation; see atomic_pointer.go.
+func Storep1(ptr unsafe.Pointer, val unsafe.Pointer)
diff --git a/src/runtime/internal/atomic/atomic_amd64x.go b/src/runtime/internal/atomic/atomic_amd64x.go
new file mode 100644
index 0000000..bd40fb3
--- /dev/null
+++ b/src/runtime/internal/atomic/atomic_amd64x.go
@@ -0,0 +1,65 @@
+// Copyright 2009 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.
+
+// +build amd64 amd64p32
+
+package atomic
+
+import "unsafe"
+
+//go:nosplit
+//go:noinline
+func Load(ptr *uint32) uint32 {
+	return *ptr
+}
+
+//go:nosplit
+//go:noinline
+func Loadp(ptr unsafe.Pointer) unsafe.Pointer {
+	return *(*unsafe.Pointer)(ptr)
+}
+
+//go:nosplit
+//go:noinline
+func Load64(ptr *uint64) uint64 {
+	return *ptr
+}
+
+//go:noescape
+func Xadd(ptr *uint32, delta int32) uint32
+
+//go:noescape
+func Xadd64(ptr *uint64, delta int64) uint64
+
+//go:noescape
+func Xadduintptr(ptr *uintptr, delta uintptr) uintptr
+
+//go:noescape
+func Xchg(ptr *uint32, new uint32) uint32
+
+//go:noescape
+func Xchg64(ptr *uint64, new uint64) uint64
+
+//go:noescape
+func Xchguintptr(ptr *uintptr, new uintptr) uintptr
+
+//go:noescape
+func And8(ptr *uint8, val uint8)
+
+//go:noescape
+func Or8(ptr *uint8, val uint8)
+
+// NOTE: Do not add atomicxor8 (XOR is not idempotent).
+
+//go:noescape
+func Cas64(ptr *uint64, old, new uint64) bool
+
+//go:noescape
+func Store(ptr *uint32, val uint32)
+
+//go:noescape
+func Store64(ptr *uint64, val uint64)
+
+// NO go:noescape annotation; see atomic_pointer.go.
+func Storep1(ptr unsafe.Pointer, val unsafe.Pointer)
diff --git a/src/runtime/internal/atomic/atomic_arm.go b/src/runtime/internal/atomic/atomic_arm.go
new file mode 100644
index 0000000..c361aef
--- /dev/null
+++ b/src/runtime/internal/atomic/atomic_arm.go
@@ -0,0 +1,183 @@
+// Copyright 2009 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.
+
+// +build arm
+
+package atomic
+
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
+
+type spinlock struct {
+	v uint32
+}
+
+//go:nosplit
+func (l *spinlock) lock() {
+	for {
+		if Cas(&l.v, 0, 1) {
+			return
+		}
+	}
+}
+
+//go:nosplit
+func (l *spinlock) unlock() {
+	Store(&l.v, 0)
+}
+
+var locktab [57]struct {
+	l   spinlock
+	pad [sys.CacheLineSize - unsafe.Sizeof(spinlock{})]byte
+}
+
+func addrLock(addr *uint64) *spinlock {
+	return &locktab[(uintptr(unsafe.Pointer(addr))>>3)%uintptr(len(locktab))].l
+}
+
+// Atomic add and return new value.
+//go:nosplit
+func Xadd(val *uint32, delta int32) uint32 {
+	for {
+		oval := *val
+		nval := oval + uint32(delta)
+		if Cas(val, oval, nval) {
+			return nval
+		}
+	}
+}
+
+//go:noescape
+func Xadduintptr(ptr *uintptr, delta uintptr) uintptr
+
+//go:nosplit
+func Xchg(addr *uint32, v uint32) uint32 {
+	for {
+		old := *addr
+		if Cas(addr, old, v) {
+			return old
+		}
+	}
+}
+
+//go:nosplit
+func Xchguintptr(addr *uintptr, v uintptr) uintptr {
+	return uintptr(Xchg((*uint32)(unsafe.Pointer(addr)), uint32(v)))
+}
+
+//go:nosplit
+func Load(addr *uint32) uint32 {
+	return Xadd(addr, 0)
+}
+
+// Should be a built-in for unsafe.Pointer?
+//go:nosplit
+func add(p unsafe.Pointer, x uintptr) unsafe.Pointer {
+	return unsafe.Pointer(uintptr(p) + x)
+}
+
+//go:nosplit
+func Loadp(addr unsafe.Pointer) unsafe.Pointer {
+	return unsafe.Pointer(uintptr(Xadd((*uint32)(addr), 0)))
+}
+
+//go:nosplit
+func Storep1(addr unsafe.Pointer, v unsafe.Pointer) {
+	for {
+		old := *(*unsafe.Pointer)(addr)
+		if Casp1((*unsafe.Pointer)(addr), old, v) {
+			return
+		}
+	}
+}
+
+//go:nosplit
+func Store(addr *uint32, v uint32) {
+	for {
+		old := *addr
+		if Cas(addr, old, v) {
+			return
+		}
+	}
+}
+
+//go:nosplit
+func Cas64(addr *uint64, old, new uint64) bool {
+	var ok bool
+	addrLock(addr).lock()
+	if *addr == old {
+		*addr = new
+		ok = true
+	}
+	addrLock(addr).unlock()
+	return ok
+}
+
+//go:nosplit
+func Xadd64(addr *uint64, delta int64) uint64 {
+	var r uint64
+	addrLock(addr).lock()
+	r = *addr + uint64(delta)
+	*addr = r
+	addrLock(addr).unlock()
+	return r
+}
+
+//go:nosplit
+func Xchg64(addr *uint64, v uint64) uint64 {
+	var r uint64
+	addrLock(addr).lock()
+	r = *addr
+	*addr = v
+	addrLock(addr).unlock()
+	return r
+}
+
+//go:nosplit
+func Load64(addr *uint64) uint64 {
+	var r uint64
+	addrLock(addr).lock()
+	r = *addr
+	addrLock(addr).unlock()
+	return r
+}
+
+//go:nosplit
+func Store64(addr *uint64, v uint64) {
+	addrLock(addr).lock()
+	*addr = v
+	addrLock(addr).unlock()
+}
+
+//go:nosplit
+func Or8(addr *uint8, v uint8) {
+	// Align down to 4 bytes and use 32-bit CAS.
+	uaddr := uintptr(unsafe.Pointer(addr))
+	addr32 := (*uint32)(unsafe.Pointer(uaddr &^ 3))
+	word := uint32(v) << ((uaddr & 3) * 8) // little endian
+	for {
+		old := *addr32
+		if Cas(addr32, old, old|word) {
+			return
+		}
+	}
+}
+
+//go:nosplit
+func And8(addr *uint8, v uint8) {
+	// Align down to 4 bytes and use 32-bit CAS.
+	uaddr := uintptr(unsafe.Pointer(addr))
+	addr32 := (*uint32)(unsafe.Pointer(uaddr &^ 3))
+	word := uint32(v) << ((uaddr & 3) * 8)    // little endian
+	mask := uint32(0xFF) << ((uaddr & 3) * 8) // little endian
+	word |= ^mask
+	for {
+		old := *addr32
+		if Cas(addr32, old, old&word) {
+			return
+		}
+	}
+}
diff --git a/src/runtime/internal/atomic/atomic_arm64.go b/src/runtime/internal/atomic/atomic_arm64.go
new file mode 100644
index 0000000..6b32346
--- /dev/null
+++ b/src/runtime/internal/atomic/atomic_arm64.go
@@ -0,0 +1,80 @@
+// Copyright 2015 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.
+
+// +build arm64
+
+package atomic
+
+import "unsafe"
+
+//go:noescape
+func Xadd(ptr *uint32, delta int32) uint32
+
+//go:noescape
+func Xadd64(ptr *uint64, delta int64) uint64
+
+//go:noescape
+func Xadduintptr(ptr *uintptr, delta uintptr) uintptr
+
+//go:noescape
+func Xchg(ptr *uint32, new uint32) uint32
+
+//go:noescape
+func Xchg64(ptr *uint64, new uint64) uint64
+
+//go:noescape
+func Xchguintptr(ptr *uintptr, new uintptr) uintptr
+
+//go:noescape
+func Load(ptr *uint32) uint32
+
+//go:noescape
+func Load64(ptr *uint64) uint64
+
+//go:noescape
+func Loadp(ptr unsafe.Pointer) unsafe.Pointer
+
+//go:nosplit
+func Or8(addr *uint8, v uint8) {
+	// TODO(dfc) implement this in asm.
+	// Align down to 4 bytes and use 32-bit CAS.
+	uaddr := uintptr(unsafe.Pointer(addr))
+	addr32 := (*uint32)(unsafe.Pointer(uaddr &^ 3))
+	word := uint32(v) << ((uaddr & 3) * 8) // little endian
+	for {
+		old := *addr32
+		if Cas(addr32, old, old|word) {
+			return
+		}
+	}
+}
+
+//go:nosplit
+func And8(addr *uint8, v uint8) {
+	// TODO(dfc) implement this in asm.
+	// Align down to 4 bytes and use 32-bit CAS.
+	uaddr := uintptr(unsafe.Pointer(addr))
+	addr32 := (*uint32)(unsafe.Pointer(uaddr &^ 3))
+	word := uint32(v) << ((uaddr & 3) * 8)    // little endian
+	mask := uint32(0xFF) << ((uaddr & 3) * 8) // little endian
+	word |= ^mask
+	for {
+		old := *addr32
+		if Cas(addr32, old, old&word) {
+			return
+		}
+	}
+}
+
+//go:noescape
+func Cas64(ptr *uint64, old, new uint64) bool
+
+//go:noescape
+func Store(ptr *uint32, val uint32)
+
+//go:noescape
+func Store64(ptr *uint64, val uint64)
+
+// NO go:noescape annotation; see atomic_pointer.go.
+func Storep1(ptr unsafe.Pointer, val unsafe.Pointer)
diff --git a/src/runtime/internal/atomic/atomic_arm64.s b/src/runtime/internal/atomic/atomic_arm64.s
new file mode 100644
index 0000000..7b1b0ef
--- /dev/null
+++ b/src/runtime/internal/atomic/atomic_arm64.s
@@ -0,0 +1,113 @@
+// 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"
+
+// uint32 runtime∕internal∕atomic·Load(uint32 volatile* addr)
+TEXT ·Load(SB),NOSPLIT,$-8-12
+	MOVD	ptr+0(FP), R0
+	LDARW	(R0), R0
+	MOVW	R0, ret+8(FP)
+	RET
+
+// uint64 runtime∕internal∕atomic·Load64(uint64 volatile* addr)
+TEXT ·Load64(SB),NOSPLIT,$-8-16
+	MOVD	ptr+0(FP), R0
+	LDAR	(R0), R0
+	MOVD	R0, ret+8(FP)
+	RET
+
+// void *runtime∕internal∕atomic·Loadp(void *volatile *addr)
+TEXT ·Loadp(SB),NOSPLIT,$-8-16
+	MOVD	ptr+0(FP), R0
+	LDAR	(R0), R0
+	MOVD	R0, ret+8(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Storep1(SB), NOSPLIT, $0-16
+	B	runtime∕internal∕atomic·Store64(SB)
+
+TEXT runtime∕internal∕atomic·Store(SB), NOSPLIT, $0-12
+	MOVD	ptr+0(FP), R0
+	MOVW	val+8(FP), R1
+	STLRW	R1, (R0)
+	RET
+
+TEXT runtime∕internal∕atomic·Store64(SB), NOSPLIT, $0-16
+	MOVD	ptr+0(FP), R0
+	MOVD	val+8(FP), R1
+	STLR	R1, (R0)
+	RET
+
+TEXT runtime∕internal∕atomic·Xchg(SB), NOSPLIT, $0-20
+again:
+	MOVD	ptr+0(FP), R0
+	MOVW	new+8(FP), R1
+	LDAXRW	(R0), R2
+	STLXRW	R1, (R0), R3
+	CBNZ	R3, again
+	MOVW	R2, ret+16(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Xchg64(SB), NOSPLIT, $0-24
+again:
+	MOVD	ptr+0(FP), R0
+	MOVD	new+8(FP), R1
+	LDAXR	(R0), R2
+	STLXR	R1, (R0), R3
+	CBNZ	R3, again
+	MOVD	R2, ret+16(FP)
+	RET
+
+// bool runtime∕internal∕atomic·Cas64(uint64 *ptr, uint64 old, uint64 new)
+// Atomically:
+//      if(*val == *old){
+//              *val = new;
+//              return 1;
+//      } else {
+//              return 0;
+//      }
+TEXT runtime∕internal∕atomic·Cas64(SB), NOSPLIT, $0-25
+	MOVD	ptr+0(FP), R0
+	MOVD	old+8(FP), R1
+	MOVD	new+16(FP), R2
+again:
+	LDAXR	(R0), R3
+	CMP	R1, R3
+	BNE	ok
+	STLXR	R2, (R0), R3
+	CBNZ	R3, again
+ok:
+	CSET	EQ, R0
+	MOVB	R0, ret+24(FP)
+	RET
+
+// uint32 xadd(uint32 volatile *ptr, int32 delta)
+// Atomically:
+//      *val += delta;
+//      return *val;
+TEXT runtime∕internal∕atomic·Xadd(SB), NOSPLIT, $0-20
+again:
+	MOVD	ptr+0(FP), R0
+	MOVW	delta+8(FP), R1
+	LDAXRW	(R0), R2
+	ADDW	R2, R1, R2
+	STLXRW	R2, (R0), R3
+	CBNZ	R3, again
+	MOVW	R2, ret+16(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Xadd64(SB), NOSPLIT, $0-24
+again:
+	MOVD	ptr+0(FP), R0
+	MOVD	delta+8(FP), R1
+	LDAXR	(R0), R2
+	ADD	R2, R1, R2
+	STLXR	R2, (R0), R3
+	CBNZ	R3, again
+	MOVD	R2, ret+16(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Xchguintptr(SB), NOSPLIT, $0-24
+	B	runtime∕internal∕atomic·Xchg64(SB)
diff --git a/src/runtime/internal/atomic/atomic_mips64x.go b/src/runtime/internal/atomic/atomic_mips64x.go
new file mode 100644
index 0000000..8094db5
--- /dev/null
+++ b/src/runtime/internal/atomic/atomic_mips64x.go
@@ -0,0 +1,56 @@
+// Copyright 2015 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.
+
+// +build mips64 mips64le
+
+package atomic
+
+import "unsafe"
+
+//go:noescape
+func Xadd(ptr *uint32, delta int32) uint32
+
+//go:noescape
+func Xadd64(ptr *uint64, delta int64) uint64
+
+//go:noescape
+func Xadduintptr(ptr *uintptr, delta uintptr) uintptr
+
+//go:noescape
+func Xchg(ptr *uint32, new uint32) uint32
+
+//go:noescape
+func Xchg64(ptr *uint64, new uint64) uint64
+
+//go:noescape
+func Xchguintptr(ptr *uintptr, new uintptr) uintptr
+
+//go:noescape
+func Load(ptr *uint32) uint32
+
+//go:noescape
+func Load64(ptr *uint64) uint64
+
+//go:noescape
+func Loadp(ptr unsafe.Pointer) unsafe.Pointer
+
+//go:noescape
+func And8(ptr *uint8, val uint8)
+
+//go:noescape
+func Or8(ptr *uint8, val uint8)
+
+// NOTE: Do not add atomicxor8 (XOR is not idempotent).
+
+//go:noescape
+func Cas64(ptr *uint64, old, new uint64) bool
+
+//go:noescape
+func Store(ptr *uint32, val uint32)
+
+//go:noescape
+func Store64(ptr *uint64, val uint64)
+
+// NO go:noescape annotation; see atomic_pointer.go.
+func Storep1(ptr unsafe.Pointer, val unsafe.Pointer)
diff --git a/src/runtime/internal/atomic/atomic_mips64x.s b/src/runtime/internal/atomic/atomic_mips64x.s
new file mode 100644
index 0000000..ae8500e
--- /dev/null
+++ b/src/runtime/internal/atomic/atomic_mips64x.s
@@ -0,0 +1,36 @@
+// Copyright 2015 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.
+
+// +build mips64 mips64le
+
+#include "textflag.h"
+
+#define SYNC	WORD $0xf
+
+// uint32 runtime∕internal∕atomic·Load(uint32 volatile* addr)
+TEXT ·Load(SB),NOSPLIT,$-8-12
+	MOVV	addr+0(FP), R1
+	SYNC
+	MOVWU	0(R1), R1
+	SYNC
+	MOVW	R1, ret+8(FP)
+	RET
+
+// uint64 runtime∕internal∕atomic·Load64(uint64 volatile* addr)
+TEXT ·Load64(SB),NOSPLIT,$-8-16
+	MOVV	addr+0(FP), R1
+	SYNC
+	MOVV	0(R1), R1
+	SYNC
+	MOVV	R1, ret+8(FP)
+	RET
+
+// void *runtime∕internal∕atomic·Loadp(void *volatile *addr)
+TEXT ·Loadp(SB),NOSPLIT,$-8-16
+	MOVV	addr+0(FP), R1
+	SYNC
+	MOVV	0(R1), R1
+	SYNC
+	MOVV	R1, ret+8(FP)
+	RET
diff --git a/src/runtime/internal/atomic/atomic_ppc64x.go b/src/runtime/internal/atomic/atomic_ppc64x.go
new file mode 100644
index 0000000..bf82b82
--- /dev/null
+++ b/src/runtime/internal/atomic/atomic_ppc64x.go
@@ -0,0 +1,56 @@
+// 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.
+
+// +build ppc64 ppc64le
+
+package atomic
+
+import "unsafe"
+
+//go:noescape
+func Xadd(ptr *uint32, delta int32) uint32
+
+//go:noescape
+func Xadd64(ptr *uint64, delta int64) uint64
+
+//go:noescape
+func Xadduintptr(ptr *uintptr, delta uintptr) uintptr
+
+//go:noescape
+func Xchg(ptr *uint32, new uint32) uint32
+
+//go:noescape
+func Xchg64(ptr *uint64, new uint64) uint64
+
+//go:noescape
+func Xchguintptr(ptr *uintptr, new uintptr) uintptr
+
+//go:noescape
+func Load(ptr *uint32) uint32
+
+//go:noescape
+func Load64(ptr *uint64) uint64
+
+//go:noescape
+func Loadp(ptr unsafe.Pointer) unsafe.Pointer
+
+//go:noescape
+func And8(ptr *uint8, val uint8)
+
+//go:noescape
+func Or8(ptr *uint8, val uint8)
+
+// NOTE: Do not add atomicxor8 (XOR is not idempotent).
+
+//go:noescape
+func Cas64(ptr *uint64, old, new uint64) bool
+
+//go:noescape
+func Store(ptr *uint32, val uint32)
+
+//go:noescape
+func Store64(ptr *uint64, val uint64)
+
+// NO go:noescape annotation; see atomic_pointer.go.
+func Storep1(ptr unsafe.Pointer, val unsafe.Pointer)
diff --git a/src/runtime/internal/atomic/atomic_ppc64x.s b/src/runtime/internal/atomic/atomic_ppc64x.s
new file mode 100644
index 0000000..1a7537e
--- /dev/null
+++ b/src/runtime/internal/atomic/atomic_ppc64x.s
@@ -0,0 +1,40 @@
+// 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.
+
+// +build ppc64 ppc64le
+
+#include "textflag.h"
+
+// uint32 runtime∕internal∕atomic·Load(uint32 volatile* addr)
+TEXT ·Load(SB),NOSPLIT|NOFRAME,$-8-12
+	MOVD	addr+0(FP), R3
+	SYNC
+	MOVWZ	0(R3), R3
+	CMPW	R3, R3, CR7
+	BC	4, 30, 1(PC) // bne- cr7,0x4
+	ISYNC
+	MOVW	R3, ret+8(FP)
+	RET
+
+// uint64 runtime∕internal∕atomic·Load64(uint64 volatile* addr)
+TEXT ·Load64(SB),NOSPLIT|NOFRAME,$-8-16
+	MOVD	addr+0(FP), R3
+	SYNC
+	MOVD	0(R3), R3
+	CMP	R3, R3, CR7
+	BC	4, 30, 1(PC) // bne- cr7,0x4
+	ISYNC
+	MOVD	R3, ret+8(FP)
+	RET
+
+// void *runtime∕internal∕atomic·Loadp(void *volatile *addr)
+TEXT ·Loadp(SB),NOSPLIT|NOFRAME,$-8-16
+	MOVD	addr+0(FP), R3
+	SYNC
+	MOVD	0(R3), R3
+	CMP	R3, R3, CR7
+	BC	4, 30, 1(PC) // bne- cr7,0x4
+	ISYNC
+	MOVD	R3, ret+8(FP)
+	RET
diff --git a/src/runtime/internal/atomic/atomic_test.go b/src/runtime/internal/atomic/atomic_test.go
new file mode 100644
index 0000000..e8ec788
--- /dev/null
+++ b/src/runtime/internal/atomic/atomic_test.go
@@ -0,0 +1,67 @@
+// Copyright 2015 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 atomic_test
+
+import (
+	"runtime"
+	"runtime/internal/atomic"
+	"testing"
+	"unsafe"
+)
+
+func runParallel(N, iter int, f func()) {
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(int(N)))
+	done := make(chan bool)
+	for i := 0; i < N; i++ {
+		go func() {
+			for j := 0; j < iter; j++ {
+				f()
+			}
+			done <- true
+		}()
+	}
+	for i := 0; i < N; i++ {
+		<-done
+	}
+}
+
+func TestXadduintptr(t *testing.T) {
+	const N = 20
+	const iter = 100000
+	inc := uintptr(100)
+	total := uintptr(0)
+	runParallel(N, iter, func() {
+		atomic.Xadduintptr(&total, inc)
+	})
+	if want := uintptr(N * iter * inc); want != total {
+		t.Fatalf("xadduintpr error, want %d, got %d", want, total)
+	}
+	total = 0
+	runParallel(N, iter, func() {
+		atomic.Xadduintptr(&total, inc)
+		atomic.Xadduintptr(&total, uintptr(-int64(inc)))
+	})
+	if total != 0 {
+		t.Fatalf("xadduintpr total error, want %d, got %d", 0, total)
+	}
+}
+
+// Tests that xadduintptr correctly updates 64-bit values.  The place where
+// we actually do so is mstats.go, functions mSysStat{Inc,Dec}.
+func TestXadduintptrOnUint64(t *testing.T) {
+	/*	if runtime.BigEndian != 0 {
+		// On big endian architectures, we never use xadduintptr to update
+		// 64-bit values and hence we skip the test.  (Note that functions
+		// mSysStat{Inc,Dec} in mstats.go have explicit checks for
+		// big-endianness.)
+		return
+	}*/
+	const inc = 100
+	val := uint64(0)
+	atomic.Xadduintptr((*uintptr)(unsafe.Pointer(&val)), inc)
+	if inc != val {
+		t.Fatalf("xadduintptr should increase lower-order bits, want %d, got %d", inc, val)
+	}
+}
diff --git a/src/runtime/internal/atomic/stubs.go b/src/runtime/internal/atomic/stubs.go
new file mode 100644
index 0000000..497b980
--- /dev/null
+++ b/src/runtime/internal/atomic/stubs.go
@@ -0,0 +1,33 @@
+// Copyright 2015 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 atomic
+
+import "unsafe"
+
+//go:noescape
+func Cas(ptr *uint32, old, new uint32) bool
+
+// NO go:noescape annotation; see atomic_pointer.go.
+func Casp1(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool
+
+//go:noescape
+func Casuintptr(ptr *uintptr, old, new uintptr) bool
+
+//go:noescape
+func Storeuintptr(ptr *uintptr, new uintptr)
+
+//go:noescape
+func Loaduintptr(ptr *uintptr) uintptr
+
+//go:noescape
+func Loaduint(ptr *uint) uint
+
+// TODO(matloob): Should these functions have the go:noescape annotation?
+
+//go:noescape
+func Loadint64(ptr *int64) int64
+
+//go:noescape
+func Xaddint64(ptr *int64, delta int64) int64
diff --git a/src/runtime/internal/atomic/sys_darwin_arm.s b/src/runtime/internal/atomic/sys_darwin_arm.s
new file mode 100644
index 0000000..01b7aef
--- /dev/null
+++ b/src/runtime/internal/atomic/sys_darwin_arm.s
@@ -0,0 +1,11 @@
+// Copyright 2015 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"
+
+TEXT runtime∕internal∕atomic·Cas(SB),NOSPLIT,$0
+	B	runtime∕internal∕atomic·armcas(SB)
+
+TEXT runtime∕internal∕atomic·Casp1(SB),NOSPLIT,$0
+	B	runtime∕internal∕atomic·Cas(SB)
diff --git a/src/runtime/internal/atomic/sys_freebsd_arm.s b/src/runtime/internal/atomic/sys_freebsd_arm.s
new file mode 100644
index 0000000..30d49b8
--- /dev/null
+++ b/src/runtime/internal/atomic/sys_freebsd_arm.s
@@ -0,0 +1,19 @@
+// Copyright 2015 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"
+
+// TODO(minux): this is only valid for ARMv6+
+// bool armcas(int32 *val, int32 old, int32 new)
+// Atomically:
+//	if(*val == old){
+//		*val = new;
+//		return 1;
+//	}else
+//		return 0;
+TEXT runtime∕internal∕atomic·Cas(SB),NOSPLIT,$0
+	B	runtime∕internal∕atomic·armcas(SB)
+
+TEXT runtime∕internal∕atomic·Casp1(SB),NOSPLIT,$0
+	B	runtime∕internal∕atomic·Cas(SB)
diff --git a/src/runtime/internal/atomic/sys_linux_arm.s b/src/runtime/internal/atomic/sys_linux_arm.s
new file mode 100644
index 0000000..f8de2a2
--- /dev/null
+++ b/src/runtime/internal/atomic/sys_linux_arm.s
@@ -0,0 +1,42 @@
+// Copyright 2015 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"
+
+// Use kernel version instead of native armcas in asm_arm.s.
+// See ../../../sync/atomic/asm_linux_arm.s for details.
+TEXT cas<>(SB),NOSPLIT,$0
+	MOVW	$0xffff0fc0, R15 // R15 is hardware PC.
+
+TEXT runtime∕internal∕atomic·Cas(SB),NOSPLIT,$0
+	MOVW	ptr+0(FP), R2
+	MOVW	old+4(FP), R0
+loop:
+	MOVW	new+8(FP), R1
+	BL	cas<>(SB)
+	BCC	check
+	MOVW	$1, R0
+	MOVB	R0, ret+12(FP)
+	RET
+check:
+	// Kernel lies; double-check.
+	MOVW	ptr+0(FP), R2
+	MOVW	old+4(FP), R0
+	MOVW	0(R2), R3
+	CMP	R0, R3
+	BEQ	loop
+	MOVW	$0, R0
+	MOVB	R0, ret+12(FP)
+	RET
+
+TEXT runtime∕internal∕atomic·Casp1(SB),NOSPLIT,$0
+	B	runtime∕internal∕atomic·Cas(SB)
+
+// As for cas, memory barriers are complicated on ARM, but the kernel
+// provides a user helper. ARMv5 does not support SMP and has no
+// memory barrier instruction at all. ARMv6 added SMP support and has
+// a memory barrier, but it requires writing to a coprocessor
+// register. ARMv7 introduced the DMB instruction, but it's expensive
+// even on single-core devices. The kernel helper takes care of all of
+// this for us.
\ No newline at end of file
diff --git a/src/runtime/internal/atomic/sys_nacl_arm.s b/src/runtime/internal/atomic/sys_nacl_arm.s
new file mode 100644
index 0000000..efa9604
--- /dev/null
+++ b/src/runtime/internal/atomic/sys_nacl_arm.s
@@ -0,0 +1,16 @@
+// Copyright 2015 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"
+
+TEXT runtime∕internal∕atomic·Casp(SB),NOSPLIT,$0
+	B	runtime·cas(SB)
+
+// This is only valid for ARMv6+, however, NaCl/ARM is only defined
+// for ARMv7A anyway.
+TEXT runtime∕internal∕atomic·Cas(SB),NOSPLIT,$0
+	B	runtime∕internal∕atomic·armcas(SB)
+
+TEXT runtime∕internal∕atomic·Casp1(SB),NOSPLIT,$0
+	B	runtime∕internal∕atomic·Cas(SB)
diff --git a/src/runtime/internal/atomic/sys_netbsd_arm.s b/src/runtime/internal/atomic/sys_netbsd_arm.s
new file mode 100644
index 0000000..3277d94
--- /dev/null
+++ b/src/runtime/internal/atomic/sys_netbsd_arm.s
@@ -0,0 +1,21 @@
+// Copyright 2015 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"
+
+// TODO(minux): this is only valid for ARMv6+
+// bool Armcas(int32 *val, int32 old, int32 new)
+// Atomically:
+//	if(*val == old){
+//		*val = new;
+//		return 1;
+//	}else
+//		return 0;
+TEXT runtime∕internal∕atomic·Cas(SB),NOSPLIT,$0
+	B	runtime∕internal∕atomic·armcas(SB)
+
+TEXT runtime∕internal∕atomic·Casp1(SB),NOSPLIT,$0
+	B	runtime∕internal∕atomic·Cas(SB)
+
+
diff --git a/src/runtime/internal/atomic/sys_openbsd_arm.s b/src/runtime/internal/atomic/sys_openbsd_arm.s
new file mode 100644
index 0000000..01b7aef
--- /dev/null
+++ b/src/runtime/internal/atomic/sys_openbsd_arm.s
@@ -0,0 +1,11 @@
+// Copyright 2015 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"
+
+TEXT runtime∕internal∕atomic·Cas(SB),NOSPLIT,$0
+	B	runtime∕internal∕atomic·armcas(SB)
+
+TEXT runtime∕internal∕atomic·Casp1(SB),NOSPLIT,$0
+	B	runtime∕internal∕atomic·Cas(SB)
diff --git a/src/runtime/internal/sys/arch_386.go b/src/runtime/internal/sys/arch_386.go
new file mode 100644
index 0000000..1f1c704
--- /dev/null
+++ b/src/runtime/internal/sys/arch_386.go
@@ -0,0 +1,18 @@
+// 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 sys
+
+const (
+	TheChar       = '8'
+	BigEndian     = 0
+	CacheLineSize = 64
+	PhysPageSize  = GoosNacl*65536 + (1-GoosNacl)*4096 // 4k normally; 64k on NaCl
+	PCQuantum     = 1
+	Int64Align    = 4
+	HugePageSize  = 1 << 21
+	MinFrameSize  = 0
+)
+
+type Uintreg uint32
diff --git a/src/runtime/internal/sys/arch_amd64.go b/src/runtime/internal/sys/arch_amd64.go
new file mode 100644
index 0000000..80fff55
--- /dev/null
+++ b/src/runtime/internal/sys/arch_amd64.go
@@ -0,0 +1,18 @@
+// 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 sys
+
+const (
+	TheChar       = '6'
+	BigEndian     = 0
+	CacheLineSize = 64
+	PhysPageSize  = 4096
+	PCQuantum     = 1
+	Int64Align    = 8
+	HugePageSize  = 1 << 21
+	MinFrameSize  = 0
+)
+
+type Uintreg uint64
diff --git a/src/runtime/internal/sys/arch_amd64p32.go b/src/runtime/internal/sys/arch_amd64p32.go
new file mode 100644
index 0000000..ca29f69
--- /dev/null
+++ b/src/runtime/internal/sys/arch_amd64p32.go
@@ -0,0 +1,18 @@
+// 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 sys
+
+const (
+	TheChar       = '6'
+	BigEndian     = 0
+	CacheLineSize = 64
+	PhysPageSize  = 65536*GoosNacl + 4096*(1-GoosNacl)
+	PCQuantum     = 1
+	Int64Align    = 8
+	HugePageSize  = 1 << 21
+	MinFrameSize  = 0
+)
+
+type Uintreg uint64
diff --git a/src/runtime/internal/sys/arch_arm.go b/src/runtime/internal/sys/arch_arm.go
new file mode 100644
index 0000000..b185e8f
--- /dev/null
+++ b/src/runtime/internal/sys/arch_arm.go
@@ -0,0 +1,18 @@
+// 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 sys
+
+const (
+	TheChar       = '5'
+	BigEndian     = 0
+	CacheLineSize = 32
+	PhysPageSize  = 65536*GoosNacl + 4096*(1-GoosNacl)
+	PCQuantum     = 4
+	Int64Align    = 4
+	HugePageSize  = 0
+	MinFrameSize  = 4
+)
+
+type Uintreg uint32
diff --git a/src/runtime/internal/sys/arch_arm64.go b/src/runtime/internal/sys/arch_arm64.go
new file mode 100644
index 0000000..b63a7a6
--- /dev/null
+++ b/src/runtime/internal/sys/arch_arm64.go
@@ -0,0 +1,18 @@
+// 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 sys
+
+const (
+	TheChar       = '7'
+	BigEndian     = 0
+	CacheLineSize = 32
+	PhysPageSize  = 65536
+	PCQuantum     = 4
+	Int64Align    = 8
+	HugePageSize  = 0
+	MinFrameSize  = 8
+)
+
+type Uintreg uint64
diff --git a/src/runtime/internal/sys/arch_mips64.go b/src/runtime/internal/sys/arch_mips64.go
new file mode 100644
index 0000000..5b933d4
--- /dev/null
+++ b/src/runtime/internal/sys/arch_mips64.go
@@ -0,0 +1,18 @@
+// Copyright 2015 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 sys
+
+const (
+	TheChar       = '0'
+	BigEndian     = 1
+	CacheLineSize = 32
+	PhysPageSize  = 16384
+	PCQuantum     = 4
+	Int64Align    = 8
+	HugePageSize  = 0
+	MinFrameSize  = 8
+)
+
+type Uintreg uint64
diff --git a/src/runtime/internal/sys/arch_mips64le.go b/src/runtime/internal/sys/arch_mips64le.go
new file mode 100644
index 0000000..ce2e98b
--- /dev/null
+++ b/src/runtime/internal/sys/arch_mips64le.go
@@ -0,0 +1,18 @@
+// Copyright 2015 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 sys
+
+const (
+	TheChar       = '0'
+	BigEndian     = 0
+	CacheLineSize = 32
+	PhysPageSize  = 16384
+	PCQuantum     = 4
+	Int64Align    = 8
+	HugePageSize  = 0
+	MinFrameSize  = 8
+)
+
+type Uintreg uint64
diff --git a/src/runtime/internal/sys/arch_ppc64.go b/src/runtime/internal/sys/arch_ppc64.go
new file mode 100644
index 0000000..3aa07e1
--- /dev/null
+++ b/src/runtime/internal/sys/arch_ppc64.go
@@ -0,0 +1,18 @@
+// 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 sys
+
+const (
+	TheChar       = '9'
+	BigEndian     = 1
+	CacheLineSize = 64
+	PhysPageSize  = 65536
+	PCQuantum     = 4
+	Int64Align    = 8
+	HugePageSize  = 0
+	MinFrameSize  = 32
+)
+
+type Uintreg uint64
diff --git a/src/runtime/internal/sys/arch_ppc64le.go b/src/runtime/internal/sys/arch_ppc64le.go
new file mode 100644
index 0000000..0f02f0b
--- /dev/null
+++ b/src/runtime/internal/sys/arch_ppc64le.go
@@ -0,0 +1,18 @@
+// 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 sys
+
+const (
+	TheChar       = '9'
+	BigEndian     = 0
+	CacheLineSize = 64
+	PhysPageSize  = 65536
+	PCQuantum     = 4
+	Int64Align    = 8
+	HugePageSize  = 0
+	MinFrameSize  = 32
+)
+
+type Uintreg uint64
diff --git a/src/runtime/internal/sys/gengoos.go b/src/runtime/internal/sys/gengoos.go
new file mode 100644
index 0000000..55d991c
--- /dev/null
+++ b/src/runtime/internal/sys/gengoos.go
@@ -0,0 +1,84 @@
+// 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.
+
+// +build ignore
+
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"log"
+	"strconv"
+	"strings"
+)
+
+var gooses, goarches []string
+
+func main() {
+	data, err := ioutil.ReadFile("../../../go/build/syslist.go")
+	if err != nil {
+		log.Fatal(err)
+	}
+	const (
+		goosPrefix   = `const goosList = `
+		goarchPrefix = `const goarchList = `
+	)
+	for _, line := range strings.Split(string(data), "\n") {
+		if strings.HasPrefix(line, goosPrefix) {
+			text, err := strconv.Unquote(strings.TrimPrefix(line, goosPrefix))
+			if err != nil {
+				log.Fatalf("parsing goosList %#q: %v", strings.TrimPrefix(line, goosPrefix), err)
+			}
+			gooses = strings.Fields(text)
+		}
+		if strings.HasPrefix(line, goarchPrefix) {
+			text, err := strconv.Unquote(strings.TrimPrefix(line, goarchPrefix))
+			if err != nil {
+				log.Fatal("parsing goarchList: %v", err)
+			}
+			goarches = strings.Fields(text)
+		}
+	}
+
+	for _, target := range gooses {
+		var buf bytes.Buffer
+		fmt.Fprintf(&buf, "// generated by gengoos.go using 'go generate'\n\n")
+		if target == "linux" {
+			fmt.Fprintf(&buf, "// +build !android\n\n") // must explicitly exclude android for linux
+		}
+		fmt.Fprintf(&buf, "package sys\n\n")
+		fmt.Fprintf(&buf, "const TheGoos = `%s`\n\n", target)
+		for _, goos := range gooses {
+			value := 0
+			if goos == target {
+				value = 1
+			}
+			fmt.Fprintf(&buf, "const Goos%s = %d\n", strings.Title(goos), value)
+		}
+		err := ioutil.WriteFile("zgoos_"+target+".go", buf.Bytes(), 0666)
+		if err != nil {
+			log.Fatal(err)
+		}
+	}
+
+	for _, target := range goarches {
+		var buf bytes.Buffer
+		fmt.Fprintf(&buf, "// generated by gengoos.go using 'go generate'\n\n")
+		fmt.Fprintf(&buf, "package sys\n\n")
+		fmt.Fprintf(&buf, "const TheGoarch = `%s`\n\n", target)
+		for _, goarch := range goarches {
+			value := 0
+			if goarch == target {
+				value = 1
+			}
+			fmt.Fprintf(&buf, "const Goarch%s = %d\n", strings.Title(goarch), value)
+		}
+		err := ioutil.WriteFile("zgoarch_"+target+".go", buf.Bytes(), 0666)
+		if err != nil {
+			log.Fatal(err)
+		}
+	}
+}
diff --git a/src/runtime/internal/sys/stubs.go b/src/runtime/internal/sys/stubs.go
new file mode 100644
index 0000000..0a94502
--- /dev/null
+++ b/src/runtime/internal/sys/stubs.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 sys
+
+// Declarations for runtime services implemented in C or assembly.
+
+const PtrSize = 4 << (^uintptr(0) >> 63)           // unsafe.Sizeof(uintptr(0)) but an ideal const
+const RegSize = 4 << (^Uintreg(0) >> 63)           // unsafe.Sizeof(uintreg(0)) but an ideal const
+const SpAlign = 1*(1-GoarchArm64) + 16*GoarchArm64 // SP alignment: 1 normally, 16 for ARM64
diff --git a/src/runtime/internal/sys/sys.go b/src/runtime/internal/sys/sys.go
new file mode 100644
index 0000000..15ad7f5
--- /dev/null
+++ b/src/runtime/internal/sys/sys.go
@@ -0,0 +1,15 @@
+// Copyright 2015 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 sys contains system- and configuration- and architecture-specific
+// constants used by the runtime.
+package sys
+
+// The next line makes 'go generate' write the zgen_*.go files with
+// per-OS and per-arch information, including constants
+// named goos_$GOOS and goarch_$GOARCH for every
+// known GOOS and GOARCH. The constant is 1 on the
+// current system, 0 otherwise; multiplying by them is
+// useful for defining GOOS- or GOARCH-specific constants.
+//go:generate go run gengoos.go
diff --git a/src/runtime/internal/sys/zgoarch_386.go b/src/runtime/internal/sys/zgoarch_386.go
new file mode 100644
index 0000000..3ad2445
--- /dev/null
+++ b/src/runtime/internal/sys/zgoarch_386.go
@@ -0,0 +1,26 @@
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoarch = `386`
+
+const Goarch386 = 1
+const GoarchAmd64 = 0
+const GoarchAmd64p32 = 0
+const GoarchArm = 0
+const GoarchArmbe = 0
+const GoarchArm64 = 0
+const GoarchArm64be = 0
+const GoarchPpc64 = 0
+const GoarchPpc64le = 0
+const GoarchMips = 0
+const GoarchMipsle = 0
+const GoarchMips64 = 0
+const GoarchMips64le = 0
+const GoarchMips64p32 = 0
+const GoarchMips64p32le = 0
+const GoarchPpc = 0
+const GoarchS390 = 0
+const GoarchS390x = 0
+const GoarchSparc = 0
+const GoarchSparc64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_amd64.go b/src/runtime/internal/sys/zgoarch_amd64.go
new file mode 100644
index 0000000..7c858e3
--- /dev/null
+++ b/src/runtime/internal/sys/zgoarch_amd64.go
@@ -0,0 +1,26 @@
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoarch = `amd64`
+
+const Goarch386 = 0
+const GoarchAmd64 = 1
+const GoarchAmd64p32 = 0
+const GoarchArm = 0
+const GoarchArmbe = 0
+const GoarchArm64 = 0
+const GoarchArm64be = 0
+const GoarchPpc64 = 0
+const GoarchPpc64le = 0
+const GoarchMips = 0
+const GoarchMipsle = 0
+const GoarchMips64 = 0
+const GoarchMips64le = 0
+const GoarchMips64p32 = 0
+const GoarchMips64p32le = 0
+const GoarchPpc = 0
+const GoarchS390 = 0
+const GoarchS390x = 0
+const GoarchSparc = 0
+const GoarchSparc64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_amd64p32.go b/src/runtime/internal/sys/zgoarch_amd64p32.go
new file mode 100644
index 0000000..772031c
--- /dev/null
+++ b/src/runtime/internal/sys/zgoarch_amd64p32.go
@@ -0,0 +1,26 @@
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoarch = `amd64p32`
+
+const Goarch386 = 0
+const GoarchAmd64 = 0
+const GoarchAmd64p32 = 1
+const GoarchArm = 0
+const GoarchArmbe = 0
+const GoarchArm64 = 0
+const GoarchArm64be = 0
+const GoarchPpc64 = 0
+const GoarchPpc64le = 0
+const GoarchMips = 0
+const GoarchMipsle = 0
+const GoarchMips64 = 0
+const GoarchMips64le = 0
+const GoarchMips64p32 = 0
+const GoarchMips64p32le = 0
+const GoarchPpc = 0
+const GoarchS390 = 0
+const GoarchS390x = 0
+const GoarchSparc = 0
+const GoarchSparc64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_arm.go b/src/runtime/internal/sys/zgoarch_arm.go
new file mode 100644
index 0000000..276e8a8
--- /dev/null
+++ b/src/runtime/internal/sys/zgoarch_arm.go
@@ -0,0 +1,26 @@
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoarch = `arm`
+
+const Goarch386 = 0
+const GoarchAmd64 = 0
+const GoarchAmd64p32 = 0
+const GoarchArm = 1
+const GoarchArmbe = 0
+const GoarchArm64 = 0
+const GoarchArm64be = 0
+const GoarchPpc64 = 0
+const GoarchPpc64le = 0
+const GoarchMips = 0
+const GoarchMipsle = 0
+const GoarchMips64 = 0
+const GoarchMips64le = 0
+const GoarchMips64p32 = 0
+const GoarchMips64p32le = 0
+const GoarchPpc = 0
+const GoarchS390 = 0
+const GoarchS390x = 0
+const GoarchSparc = 0
+const GoarchSparc64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_arm64.go b/src/runtime/internal/sys/zgoarch_arm64.go
new file mode 100644
index 0000000..d124ec0
--- /dev/null
+++ b/src/runtime/internal/sys/zgoarch_arm64.go
@@ -0,0 +1,26 @@
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoarch = `arm64`
+
+const Goarch386 = 0
+const GoarchAmd64 = 0
+const GoarchAmd64p32 = 0
+const GoarchArm = 0
+const GoarchArmbe = 0
+const GoarchArm64 = 1
+const GoarchArm64be = 0
+const GoarchPpc64 = 0
+const GoarchPpc64le = 0
+const GoarchMips = 0
+const GoarchMipsle = 0
+const GoarchMips64 = 0
+const GoarchMips64le = 0
+const GoarchMips64p32 = 0
+const GoarchMips64p32le = 0
+const GoarchPpc = 0
+const GoarchS390 = 0
+const GoarchS390x = 0
+const GoarchSparc = 0
+const GoarchSparc64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_mips64.go b/src/runtime/internal/sys/zgoarch_mips64.go
new file mode 100644
index 0000000..b4a97d6
--- /dev/null
+++ b/src/runtime/internal/sys/zgoarch_mips64.go
@@ -0,0 +1,26 @@
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoarch = `mips64`
+
+const Goarch386 = 0
+const GoarchAmd64 = 0
+const GoarchAmd64p32 = 0
+const GoarchArm = 0
+const GoarchArmbe = 0
+const GoarchArm64 = 0
+const GoarchArm64be = 0
+const GoarchPpc64 = 0
+const GoarchPpc64le = 0
+const GoarchMips = 0
+const GoarchMipsle = 0
+const GoarchMips64 = 1
+const GoarchMips64le = 0
+const GoarchMips64p32 = 0
+const GoarchMips64p32le = 0
+const GoarchPpc = 0
+const GoarchS390 = 0
+const GoarchS390x = 0
+const GoarchSparc = 0
+const GoarchSparc64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_mips64le.go b/src/runtime/internal/sys/zgoarch_mips64le.go
new file mode 100644
index 0000000..3328a35
--- /dev/null
+++ b/src/runtime/internal/sys/zgoarch_mips64le.go
@@ -0,0 +1,26 @@
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoarch = `mips64le`
+
+const Goarch386 = 0
+const GoarchAmd64 = 0
+const GoarchAmd64p32 = 0
+const GoarchArm = 0
+const GoarchArmbe = 0
+const GoarchArm64 = 0
+const GoarchArm64be = 0
+const GoarchPpc64 = 0
+const GoarchPpc64le = 0
+const GoarchMips = 0
+const GoarchMipsle = 0
+const GoarchMips64 = 0
+const GoarchMips64le = 1
+const GoarchMips64p32 = 0
+const GoarchMips64p32le = 0
+const GoarchPpc = 0
+const GoarchS390 = 0
+const GoarchS390x = 0
+const GoarchSparc = 0
+const GoarchSparc64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_ppc64.go b/src/runtime/internal/sys/zgoarch_ppc64.go
new file mode 100644
index 0000000..06f78b2
--- /dev/null
+++ b/src/runtime/internal/sys/zgoarch_ppc64.go
@@ -0,0 +1,26 @@
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoarch = `ppc64`
+
+const Goarch386 = 0
+const GoarchAmd64 = 0
+const GoarchAmd64p32 = 0
+const GoarchArm = 0
+const GoarchArmbe = 0
+const GoarchArm64 = 0
+const GoarchArm64be = 0
+const GoarchPpc64 = 1
+const GoarchPpc64le = 0
+const GoarchMips = 0
+const GoarchMipsle = 0
+const GoarchMips64 = 0
+const GoarchMips64le = 0
+const GoarchMips64p32 = 0
+const GoarchMips64p32le = 0
+const GoarchPpc = 0
+const GoarchS390 = 0
+const GoarchS390x = 0
+const GoarchSparc = 0
+const GoarchSparc64 = 0
diff --git a/src/runtime/internal/sys/zgoarch_ppc64le.go b/src/runtime/internal/sys/zgoarch_ppc64le.go
new file mode 100644
index 0000000..50b56db
--- /dev/null
+++ b/src/runtime/internal/sys/zgoarch_ppc64le.go
@@ -0,0 +1,26 @@
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoarch = `ppc64le`
+
+const Goarch386 = 0
+const GoarchAmd64 = 0
+const GoarchAmd64p32 = 0
+const GoarchArm = 0
+const GoarchArmbe = 0
+const GoarchArm64 = 0
+const GoarchArm64be = 0
+const GoarchPpc64 = 0
+const GoarchPpc64le = 1
+const GoarchMips = 0
+const GoarchMipsle = 0
+const GoarchMips64 = 0
+const GoarchMips64le = 0
+const GoarchMips64p32 = 0
+const GoarchMips64p32le = 0
+const GoarchPpc = 0
+const GoarchS390 = 0
+const GoarchS390x = 0
+const GoarchSparc = 0
+const GoarchSparc64 = 0
diff --git a/src/runtime/internal/sys/zgoos_android.go b/src/runtime/internal/sys/zgoos_android.go
new file mode 100644
index 0000000..03d9176
--- /dev/null
+++ b/src/runtime/internal/sys/zgoos_android.go
@@ -0,0 +1,17 @@
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoos = `android`
+
+const GoosAndroid = 1
+const GoosDarwin = 0
+const GoosDragonfly = 0
+const GoosFreebsd = 0
+const GoosLinux = 0
+const GoosNacl = 0
+const GoosNetbsd = 0
+const GoosOpenbsd = 0
+const GoosPlan9 = 0
+const GoosSolaris = 0
+const GoosWindows = 0
diff --git a/src/runtime/internal/sys/zgoos_darwin.go b/src/runtime/internal/sys/zgoos_darwin.go
new file mode 100644
index 0000000..eb2efeb
--- /dev/null
+++ b/src/runtime/internal/sys/zgoos_darwin.go
@@ -0,0 +1,17 @@
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoos = `darwin`
+
+const GoosAndroid = 0
+const GoosDarwin = 1
+const GoosDragonfly = 0
+const GoosFreebsd = 0
+const GoosLinux = 0
+const GoosNacl = 0
+const GoosNetbsd = 0
+const GoosOpenbsd = 0
+const GoosPlan9 = 0
+const GoosSolaris = 0
+const GoosWindows = 0
diff --git a/src/runtime/internal/sys/zgoos_dragonfly.go b/src/runtime/internal/sys/zgoos_dragonfly.go
new file mode 100644
index 0000000..403cf65
--- /dev/null
+++ b/src/runtime/internal/sys/zgoos_dragonfly.go
@@ -0,0 +1,17 @@
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoos = `dragonfly`
+
+const GoosAndroid = 0
+const GoosDarwin = 0
+const GoosDragonfly = 1
+const GoosFreebsd = 0
+const GoosLinux = 0
+const GoosNacl = 0
+const GoosNetbsd = 0
+const GoosOpenbsd = 0
+const GoosPlan9 = 0
+const GoosSolaris = 0
+const GoosWindows = 0
diff --git a/src/runtime/internal/sys/zgoos_freebsd.go b/src/runtime/internal/sys/zgoos_freebsd.go
new file mode 100644
index 0000000..632d5db
--- /dev/null
+++ b/src/runtime/internal/sys/zgoos_freebsd.go
@@ -0,0 +1,17 @@
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoos = `freebsd`
+
+const GoosAndroid = 0
+const GoosDarwin = 0
+const GoosDragonfly = 0
+const GoosFreebsd = 1
+const GoosLinux = 0
+const GoosNacl = 0
+const GoosNetbsd = 0
+const GoosOpenbsd = 0
+const GoosPlan9 = 0
+const GoosSolaris = 0
+const GoosWindows = 0
diff --git a/src/runtime/internal/sys/zgoos_linux.go b/src/runtime/internal/sys/zgoos_linux.go
new file mode 100644
index 0000000..2d43869
--- /dev/null
+++ b/src/runtime/internal/sys/zgoos_linux.go
@@ -0,0 +1,19 @@
+// generated by gengoos.go using 'go generate'
+
+// +build !android
+
+package sys
+
+const TheGoos = `linux`
+
+const GoosAndroid = 0
+const GoosDarwin = 0
+const GoosDragonfly = 0
+const GoosFreebsd = 0
+const GoosLinux = 1
+const GoosNacl = 0
+const GoosNetbsd = 0
+const GoosOpenbsd = 0
+const GoosPlan9 = 0
+const GoosSolaris = 0
+const GoosWindows = 0
diff --git a/src/runtime/internal/sys/zgoos_nacl.go b/src/runtime/internal/sys/zgoos_nacl.go
new file mode 100644
index 0000000..a56b6ef
--- /dev/null
+++ b/src/runtime/internal/sys/zgoos_nacl.go
@@ -0,0 +1,17 @@
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoos = `nacl`
+
+const GoosAndroid = 0
+const GoosDarwin = 0
+const GoosDragonfly = 0
+const GoosFreebsd = 0
+const GoosLinux = 0
+const GoosNacl = 1
+const GoosNetbsd = 0
+const GoosOpenbsd = 0
+const GoosPlan9 = 0
+const GoosSolaris = 0
+const GoosWindows = 0
diff --git a/src/runtime/internal/sys/zgoos_netbsd.go b/src/runtime/internal/sys/zgoos_netbsd.go
new file mode 100644
index 0000000..46fd0a7
--- /dev/null
+++ b/src/runtime/internal/sys/zgoos_netbsd.go
@@ -0,0 +1,17 @@
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoos = `netbsd`
+
+const GoosAndroid = 0
+const GoosDarwin = 0
+const GoosDragonfly = 0
+const GoosFreebsd = 0
+const GoosLinux = 0
+const GoosNacl = 0
+const GoosNetbsd = 1
+const GoosOpenbsd = 0
+const GoosPlan9 = 0
+const GoosSolaris = 0
+const GoosWindows = 0
diff --git a/src/runtime/internal/sys/zgoos_openbsd.go b/src/runtime/internal/sys/zgoos_openbsd.go
new file mode 100644
index 0000000..7ee650a
--- /dev/null
+++ b/src/runtime/internal/sys/zgoos_openbsd.go
@@ -0,0 +1,17 @@
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoos = `openbsd`
+
+const GoosAndroid = 0
+const GoosDarwin = 0
+const GoosDragonfly = 0
+const GoosFreebsd = 0
+const GoosLinux = 0
+const GoosNacl = 0
+const GoosNetbsd = 0
+const GoosOpenbsd = 1
+const GoosPlan9 = 0
+const GoosSolaris = 0
+const GoosWindows = 0
diff --git a/src/runtime/internal/sys/zgoos_plan9.go b/src/runtime/internal/sys/zgoos_plan9.go
new file mode 100644
index 0000000..162e7f6
--- /dev/null
+++ b/src/runtime/internal/sys/zgoos_plan9.go
@@ -0,0 +1,17 @@
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoos = `plan9`
+
+const GoosAndroid = 0
+const GoosDarwin = 0
+const GoosDragonfly = 0
+const GoosFreebsd = 0
+const GoosLinux = 0
+const GoosNacl = 0
+const GoosNetbsd = 0
+const GoosOpenbsd = 0
+const GoosPlan9 = 1
+const GoosSolaris = 0
+const GoosWindows = 0
diff --git a/src/runtime/internal/sys/zgoos_solaris.go b/src/runtime/internal/sys/zgoos_solaris.go
new file mode 100644
index 0000000..b2a8f98
--- /dev/null
+++ b/src/runtime/internal/sys/zgoos_solaris.go
@@ -0,0 +1,17 @@
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoos = `solaris`
+
+const GoosAndroid = 0
+const GoosDarwin = 0
+const GoosDragonfly = 0
+const GoosFreebsd = 0
+const GoosLinux = 0
+const GoosNacl = 0
+const GoosNetbsd = 0
+const GoosOpenbsd = 0
+const GoosPlan9 = 0
+const GoosSolaris = 1
+const GoosWindows = 0
diff --git a/src/runtime/internal/sys/zgoos_windows.go b/src/runtime/internal/sys/zgoos_windows.go
new file mode 100644
index 0000000..817ec79
--- /dev/null
+++ b/src/runtime/internal/sys/zgoos_windows.go
@@ -0,0 +1,17 @@
+// generated by gengoos.go using 'go generate'
+
+package sys
+
+const TheGoos = `windows`
+
+const GoosAndroid = 0
+const GoosDarwin = 0
+const GoosDragonfly = 0
+const GoosFreebsd = 0
+const GoosLinux = 0
+const GoosNacl = 0
+const GoosNetbsd = 0
+const GoosOpenbsd = 0
+const GoosPlan9 = 0
+const GoosSolaris = 0
+const GoosWindows = 1
diff --git a/src/runtime/lfstack.go b/src/runtime/lfstack.go
index 5838c1d..ea640eb 100644
--- a/src/runtime/lfstack.go
+++ b/src/runtime/lfstack.go
@@ -7,19 +7,22 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"unsafe"
+)
 
 func lfstackpush(head *uint64, node *lfnode) {
 	node.pushcnt++
 	new := lfstackPack(node, node.pushcnt)
 	if node1, _ := lfstackUnpack(new); node1 != node {
-		println("runtime: lfstackpush invalid packing: node=", node, " cnt=", hex(node.pushcnt), " packed=", hex(new), " -> node=", node1, "\n")
+		print("runtime: lfstackpush invalid packing: node=", node, " cnt=", hex(node.pushcnt), " packed=", hex(new), " -> node=", node1, "\n")
 		throw("lfstackpush")
 	}
 	for {
-		old := atomicload64(head)
+		old := atomic.Load64(head)
 		node.next = old
-		if cas64(head, old, new) {
+		if atomic.Cas64(head, old, new) {
 			break
 		}
 	}
@@ -27,13 +30,13 @@ func lfstackpush(head *uint64, node *lfnode) {
 
 func lfstackpop(head *uint64) unsafe.Pointer {
 	for {
-		old := atomicload64(head)
+		old := atomic.Load64(head)
 		if old == 0 {
 			return nil
 		}
 		node, _ := lfstackUnpack(old)
-		next := atomicload64(&node.next)
-		if cas64(head, old, next) {
+		next := atomic.Load64(&node.next)
+		if atomic.Cas64(head, old, next) {
 			return unsafe.Pointer(node)
 		}
 	}
diff --git a/src/runtime/lfstack_linux_mips64x.go b/src/runtime/lfstack_linux_mips64x.go
new file mode 100644
index 0000000..49b6558
--- /dev/null
+++ b/src/runtime/lfstack_linux_mips64x.go
@@ -0,0 +1,32 @@
+// Copyright 2015 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.
+
+// +build mips64 mips64le
+// +build linux
+
+package runtime
+
+import "unsafe"
+
+// On mips64, Linux limits the user address space to 40 bits (see
+// TASK_SIZE64 in the Linux kernel).  This has grown over time,
+// so here we allow 48 bit addresses.
+//
+// In addition to the 16 bits taken from the top, we can take 3 from the
+// bottom, because node must be pointer-aligned, giving a total of 19 bits
+// of count.
+const (
+	addrBits = 48
+	cntBits  = 64 - addrBits + 3
+)
+
+func lfstackPack(node *lfnode, cnt uintptr) uint64 {
+	return uint64(uintptr(unsafe.Pointer(node)))<<(64-addrBits) | uint64(cnt&(1<<cntBits-1))
+}
+
+func lfstackUnpack(val uint64) (node *lfnode, cnt uintptr) {
+	node = (*lfnode)(unsafe.Pointer(uintptr(val >> cntBits << 3)))
+	cnt = uintptr(val & (1<<cntBits - 1))
+	return
+}
diff --git a/src/runtime/lock_futex.go b/src/runtime/lock_futex.go
index 768fd57..fc48029 100644
--- a/src/runtime/lock_futex.go
+++ b/src/runtime/lock_futex.go
@@ -6,7 +6,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"unsafe"
+)
 
 // This implementation depends on OS-specific implementations of
 //
@@ -48,7 +51,7 @@ func lock(l *mutex) {
 	gp.m.locks++
 
 	// Speculative grab for lock.
-	v := xchg(key32(&l.key), mutex_locked)
+	v := atomic.Xchg(key32(&l.key), mutex_locked)
 	if v == mutex_unlocked {
 		return
 	}
@@ -72,7 +75,7 @@ func lock(l *mutex) {
 		// Try for lock, spinning.
 		for i := 0; i < spin; i++ {
 			for l.key == mutex_unlocked {
-				if cas(key32(&l.key), mutex_unlocked, wait) {
+				if atomic.Cas(key32(&l.key), mutex_unlocked, wait) {
 					return
 				}
 			}
@@ -82,7 +85,7 @@ func lock(l *mutex) {
 		// Try for lock, rescheduling.
 		for i := 0; i < passive_spin; i++ {
 			for l.key == mutex_unlocked {
-				if cas(key32(&l.key), mutex_unlocked, wait) {
+				if atomic.Cas(key32(&l.key), mutex_unlocked, wait) {
 					return
 				}
 			}
@@ -90,7 +93,7 @@ func lock(l *mutex) {
 		}
 
 		// Sleep.
-		v = xchg(key32(&l.key), mutex_sleeping)
+		v = atomic.Xchg(key32(&l.key), mutex_sleeping)
 		if v == mutex_unlocked {
 			return
 		}
@@ -100,7 +103,7 @@ func lock(l *mutex) {
 }
 
 func unlock(l *mutex) {
-	v := xchg(key32(&l.key), mutex_unlocked)
+	v := atomic.Xchg(key32(&l.key), mutex_unlocked)
 	if v == mutex_unlocked {
 		throw("unlock of unlocked lock")
 	}
@@ -124,7 +127,7 @@ func noteclear(n *note) {
 }
 
 func notewakeup(n *note) {
-	old := xchg(key32(&n.key), 1)
+	old := atomic.Xchg(key32(&n.key), 1)
 	if old != 0 {
 		print("notewakeup - double wakeup (", old, ")\n")
 		throw("notewakeup - double wakeup")
@@ -137,7 +140,7 @@ func notesleep(n *note) {
 	if gp != gp.m.g0 {
 		throw("notesleep not on g0")
 	}
-	for atomicload(key32(&n.key)) == 0 {
+	for atomic.Load(key32(&n.key)) == 0 {
 		gp.m.blocked = true
 		futexsleep(key32(&n.key), 0, -1)
 		gp.m.blocked = false
@@ -153,7 +156,7 @@ func notetsleep_internal(n *note, ns int64) bool {
 	gp := getg()
 
 	if ns < 0 {
-		for atomicload(key32(&n.key)) == 0 {
+		for atomic.Load(key32(&n.key)) == 0 {
 			gp.m.blocked = true
 			futexsleep(key32(&n.key), 0, -1)
 			gp.m.blocked = false
@@ -161,7 +164,7 @@ func notetsleep_internal(n *note, ns int64) bool {
 		return true
 	}
 
-	if atomicload(key32(&n.key)) != 0 {
+	if atomic.Load(key32(&n.key)) != 0 {
 		return true
 	}
 
@@ -170,7 +173,7 @@ func notetsleep_internal(n *note, ns int64) bool {
 		gp.m.blocked = true
 		futexsleep(key32(&n.key), 0, ns)
 		gp.m.blocked = false
-		if atomicload(key32(&n.key)) != 0 {
+		if atomic.Load(key32(&n.key)) != 0 {
 			break
 		}
 		now := nanotime()
@@ -179,7 +182,7 @@ func notetsleep_internal(n *note, ns int64) bool {
 		}
 		ns = deadline - now
 	}
-	return atomicload(key32(&n.key)) != 0
+	return atomic.Load(key32(&n.key)) != 0
 }
 
 func notetsleep(n *note, ns int64) bool {
diff --git a/src/runtime/lock_sema.go b/src/runtime/lock_sema.go
index d9d91c9..d39b010 100644
--- a/src/runtime/lock_sema.go
+++ b/src/runtime/lock_sema.go
@@ -6,22 +6,23 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"unsafe"
+)
 
 // This implementation depends on OS-specific implementations of
 //
-//	uintptr runtime·semacreate(void)
-//		Create a semaphore, which will be assigned to m->waitsema.
-//		The zero value is treated as absence of any semaphore,
-//		so be sure to return a non-zero value.
+//	func semacreate(mp *m)
+//		Create a semaphore for mp, if it does not already have one.
 //
-//	int32 runtime·semasleep(int64 ns)
-//		If ns < 0, acquire m->waitsema and return 0.
-//		If ns >= 0, try to acquire m->waitsema for at most ns nanoseconds.
+//	func semasleep(ns int64) int32
+//		If ns < 0, acquire m's semaphore and return 0.
+//		If ns >= 0, try to acquire m's semaphore for at most ns nanoseconds.
 //		Return 0 if the semaphore was acquired, -1 if interrupted or timed out.
 //
-//	int32 runtime·semawakeup(M *mp)
-//		Wake up mp, which is or will soon be sleeping on mp->waitsema.
+//	func semawakeup(mp *m)
+//		Wake up mp, which is or will soon be sleeping on its semaphore.
 //
 const (
 	locked uintptr = 1
@@ -39,12 +40,10 @@ func lock(l *mutex) {
 	gp.m.locks++
 
 	// Speculative grab for lock.
-	if casuintptr(&l.key, 0, locked) {
+	if atomic.Casuintptr(&l.key, 0, locked) {
 		return
 	}
-	if gp.m.waitsema == 0 {
-		gp.m.waitsema = semacreate()
-	}
+	semacreate(gp.m)
 
 	// On uniprocessor's, no point spinning.
 	// On multiprocessors, spin for ACTIVE_SPIN attempts.
@@ -54,10 +53,10 @@ func lock(l *mutex) {
 	}
 Loop:
 	for i := 0; ; i++ {
-		v := atomicloaduintptr(&l.key)
+		v := atomic.Loaduintptr(&l.key)
 		if v&locked == 0 {
 			// Unlocked. Try to lock.
-			if casuintptr(&l.key, v, v|locked) {
+			if atomic.Casuintptr(&l.key, v, v|locked) {
 				return
 			}
 			i = 0
@@ -73,10 +72,10 @@ Loop:
 			// Queue this M.
 			for {
 				gp.m.nextwaitm = v &^ locked
-				if casuintptr(&l.key, v, uintptr(unsafe.Pointer(gp.m))|locked) {
+				if atomic.Casuintptr(&l.key, v, uintptr(unsafe.Pointer(gp.m))|locked) {
 					break
 				}
-				v = atomicloaduintptr(&l.key)
+				v = atomic.Loaduintptr(&l.key)
 				if v&locked == 0 {
 					continue Loop
 				}
@@ -96,16 +95,16 @@ func unlock(l *mutex) {
 	gp := getg()
 	var mp *m
 	for {
-		v := atomicloaduintptr(&l.key)
+		v := atomic.Loaduintptr(&l.key)
 		if v == locked {
-			if casuintptr(&l.key, locked, 0) {
+			if atomic.Casuintptr(&l.key, locked, 0) {
 				break
 			}
 		} else {
 			// Other M's are waiting for the lock.
 			// Dequeue an M.
-			mp = (*m)((unsafe.Pointer)(v &^ locked))
-			if casuintptr(&l.key, v, mp.nextwaitm) {
+			mp = (*m)(unsafe.Pointer(v &^ locked))
+			if atomic.Casuintptr(&l.key, v, mp.nextwaitm) {
 				// Dequeued an M.  Wake it.
 				semawakeup(mp)
 				break
@@ -129,8 +128,8 @@ func noteclear(n *note) {
 func notewakeup(n *note) {
 	var v uintptr
 	for {
-		v = atomicloaduintptr(&n.key)
-		if casuintptr(&n.key, v, locked) {
+		v = atomic.Loaduintptr(&n.key)
+		if atomic.Casuintptr(&n.key, v, locked) {
 			break
 		}
 	}
@@ -154,10 +153,8 @@ func notesleep(n *note) {
 	if gp != gp.m.g0 {
 		throw("notesleep not on g0")
 	}
-	if gp.m.waitsema == 0 {
-		gp.m.waitsema = semacreate()
-	}
-	if !casuintptr(&n.key, 0, uintptr(unsafe.Pointer(gp.m))) {
+	semacreate(gp.m)
+	if !atomic.Casuintptr(&n.key, 0, uintptr(unsafe.Pointer(gp.m))) {
 		// Must be locked (got wakeup).
 		if n.key != locked {
 			throw("notesleep - waitm out of sync")
@@ -179,7 +176,7 @@ func notetsleep_internal(n *note, ns int64, gp *g, deadline int64) bool {
 	gp = getg()
 
 	// Register for wakeup on n->waitm.
-	if !casuintptr(&n.key, 0, uintptr(unsafe.Pointer(gp.m))) {
+	if !atomic.Casuintptr(&n.key, 0, uintptr(unsafe.Pointer(gp.m))) {
 		// Must be locked (got wakeup).
 		if n.key != locked {
 			throw("notetsleep - waitm out of sync")
@@ -218,11 +215,11 @@ func notetsleep_internal(n *note, ns int64, gp *g, deadline int64) bool {
 	// so that any notewakeup racing with the return does not
 	// try to grant us the semaphore when we don't expect it.
 	for {
-		v := atomicloaduintptr(&n.key)
+		v := atomic.Loaduintptr(&n.key)
 		switch v {
 		case uintptr(unsafe.Pointer(gp.m)):
 			// No wakeup yet; unregister if possible.
-			if casuintptr(&n.key, v, 0) {
+			if atomic.Casuintptr(&n.key, v, 0) {
 				return false
 			}
 		case locked:
@@ -245,9 +242,7 @@ func notetsleep(n *note, ns int64) bool {
 	if gp != gp.m.g0 && gp.m.preemptoff != "" {
 		throw("notetsleep not on g0")
 	}
-	if gp.m.waitsema == 0 {
-		gp.m.waitsema = semacreate()
-	}
+	semacreate(gp.m)
 	return notetsleep_internal(n, ns, nil, 0)
 }
 
@@ -258,9 +253,7 @@ func notetsleepg(n *note, ns int64) bool {
 	if gp == gp.m.g0 {
 		throw("notetsleepg on g0")
 	}
-	if gp.m.waitsema == 0 {
-		gp.m.waitsema = semacreate()
-	}
+	semacreate(gp.m)
 	entersyscallblock(0)
 	ok := notetsleep_internal(n, ns, nil, 0)
 	exitsyscall(0)
diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go
index b966eed..b520c68 100644
--- a/src/runtime/malloc.go
+++ b/src/runtime/malloc.go
@@ -76,13 +76,13 @@
 //	   or the page heap can avoid zeroing altogether.
 //	2. the cost of zeroing when reusing a small object is
 //	   charged to the mutator, not the garbage collector.
-//
-// This code was written with an eye toward translating to Go
-// in the future.  Methods have the form Type_Method(Type *t, ...).
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 const (
 	debugMalloc = false
@@ -146,7 +146,7 @@ const (
 	//   windows/32       | 4KB        | 3
 	//   windows/64       | 8KB        | 2
 	//   plan9            | 4KB        | 3
-	_NumStackOrders = 4 - ptrSize/4*goos_windows - 1*goos_plan9
+	_NumStackOrders = 4 - sys.PtrSize/4*sys.GoosWindows - 1*sys.GoosPlan9
 
 	// Number of bits in page to span calculations (4k pages).
 	// On Windows 64-bit we limit the arena to 32GB or 35 bits.
@@ -158,7 +158,7 @@ const (
 	// On Darwin/arm64, we cannot reserve more than ~5GB of virtual memory,
 	// but as most devices have less than 4GB of physical memory anyway, we
 	// try to be conservative here, and only ask for a 2GB heap.
-	_MHeapMap_TotalBits = (_64bit*goos_windows)*35 + (_64bit*(1-goos_windows)*(1-goos_darwin*goarch_arm64))*39 + goos_darwin*goarch_arm64*31 + (1-_64bit)*32
+	_MHeapMap_TotalBits = (_64bit*sys.GoosWindows)*35 + (_64bit*(1-sys.GoosWindows)*(1-sys.GoosDarwin*sys.GoarchArm64))*39 + sys.GoosDarwin*sys.GoarchArm64*31 + (1-_64bit)*32
 	_MHeapMap_Bits      = _MHeapMap_TotalBits - _PageShift
 
 	_MaxMem = uintptr(1<<_MHeapMap_TotalBits - 1)
@@ -231,7 +231,7 @@ func mallocinit() {
 	// Set up the allocation arena, a contiguous area of memory where
 	// allocated data will be found.  The arena begins with a bitmap large
 	// enough to hold 4 bits per allocated word.
-	if ptrSize == 8 && (limit == 0 || limit > 1<<30) {
+	if sys.PtrSize == 8 && (limit == 0 || limit > 1<<30) {
 		// On a 64-bit machine, allocate from a single contiguous reservation.
 		// 512 GB (MaxMem) should be big enough for now.
 		//
@@ -262,8 +262,8 @@ func mallocinit() {
 		// translation buffers, the user address space is limited to 39 bits
 		// On darwin/arm64, the address space is even smaller.
 		arenaSize := round(_MaxMem, _PageSize)
-		bitmapSize = arenaSize / (ptrSize * 8 / 4)
-		spansSize = arenaSize / _PageSize * ptrSize
+		bitmapSize = arenaSize / (sys.PtrSize * 8 / 4)
+		spansSize = arenaSize / _PageSize * sys.PtrSize
 		spansSize = round(spansSize, _PageSize)
 		for i := 0; i <= 0x7f; i++ {
 			switch {
@@ -311,12 +311,12 @@ func mallocinit() {
 		}
 
 		for _, arenaSize := range arenaSizes {
-			bitmapSize = _MaxArena32 / (ptrSize * 8 / 4)
-			spansSize = _MaxArena32 / _PageSize * ptrSize
+			bitmapSize = _MaxArena32 / (sys.PtrSize * 8 / 4)
+			spansSize = _MaxArena32 / _PageSize * sys.PtrSize
 			if limit > 0 && arenaSize+bitmapSize+spansSize > limit {
 				bitmapSize = (limit / 9) &^ ((1 << _PageShift) - 1)
 				arenaSize = bitmapSize * 8
-				spansSize = arenaSize / _PageSize * ptrSize
+				spansSize = arenaSize / _PageSize * sys.PtrSize
 			}
 			spansSize = round(spansSize, _PageSize)
 
@@ -359,7 +359,7 @@ func mallocinit() {
 	}
 
 	// Initialize the rest of the allocator.
-	mHeap_Init(&mheap_, spansSize)
+	mheap_.init(spansSize)
 	_g_ := getg()
 	_g_.m.mcache = allocmcache()
 }
@@ -371,7 +371,7 @@ func mallocinit() {
 // needed. This doesn't work well with the "let the kernel pick an address"
 // mode, so don't do that. Pick a high address instead.
 func sysReserveHigh(n uintptr, reserved *bool) unsafe.Pointer {
-	if ptrSize == 4 {
+	if sys.PtrSize == 4 {
 		return sysReserve(nil, n, reserved)
 	}
 
@@ -387,17 +387,20 @@ func sysReserveHigh(n uintptr, reserved *bool) unsafe.Pointer {
 	return sysReserve(nil, n, reserved)
 }
 
-func mHeap_SysAlloc(h *mheap, n uintptr) unsafe.Pointer {
-	if n > uintptr(h.arena_end)-uintptr(h.arena_used) {
+func (h *mheap) sysAlloc(n uintptr) unsafe.Pointer {
+	if n > h.arena_end-h.arena_used {
 		// We are in 32-bit mode, maybe we didn't use all possible address space yet.
 		// Reserve some more space.
 		p_size := round(n+_PageSize, 256<<20)
-		new_end := h.arena_end + p_size
-		if new_end <= h.arena_start+_MaxArena32 {
+		new_end := h.arena_end + p_size // Careful: can overflow
+		if h.arena_end <= new_end && new_end <= h.arena_start+_MaxArena32 {
 			// TODO: It would be bad if part of the arena
 			// is reserved and part is not.
 			var reserved bool
-			p := uintptr(sysReserve((unsafe.Pointer)(h.arena_end), p_size, &reserved))
+			p := uintptr(sysReserve(unsafe.Pointer(h.arena_end), p_size, &reserved))
+			if p == 0 {
+				return nil
+			}
 			if p == h.arena_end {
 				h.arena_end = new_end
 				h.arena_reserved = reserved
@@ -406,8 +409,8 @@ func mHeap_SysAlloc(h *mheap, n uintptr) unsafe.Pointer {
 				// Our pages are bigger than hardware pages.
 				h.arena_end = p + p_size
 				used := p + (-uintptr(p) & (_PageSize - 1))
-				mHeap_MapBits(h, used)
-				mHeap_MapSpans(h, used)
+				h.mapBits(used)
+				h.mapSpans(used)
 				h.arena_used = used
 				h.arena_reserved = reserved
 			} else {
@@ -415,30 +418,30 @@ func mHeap_SysAlloc(h *mheap, n uintptr) unsafe.Pointer {
 				// the stats, so subtract it from a
 				// fake stat (but avoid underflow).
 				stat := uint64(p_size)
-				sysFree((unsafe.Pointer)(p), p_size, &stat)
+				sysFree(unsafe.Pointer(p), p_size, &stat)
 			}
 		}
 	}
 
-	if n <= uintptr(h.arena_end)-uintptr(h.arena_used) {
+	if n <= h.arena_end-h.arena_used {
 		// Keep taking from our reservation.
 		p := h.arena_used
-		sysMap((unsafe.Pointer)(p), n, h.arena_reserved, &memstats.heap_sys)
-		mHeap_MapBits(h, p+n)
-		mHeap_MapSpans(h, p+n)
+		sysMap(unsafe.Pointer(p), n, h.arena_reserved, &memstats.heap_sys)
+		h.mapBits(p + n)
+		h.mapSpans(p + n)
 		h.arena_used = p + n
 		if raceenabled {
-			racemapshadow((unsafe.Pointer)(p), n)
+			racemapshadow(unsafe.Pointer(p), n)
 		}
 
 		if uintptr(p)&(_PageSize-1) != 0 {
 			throw("misrounded allocation in MHeap_SysAlloc")
 		}
-		return (unsafe.Pointer)(p)
+		return unsafe.Pointer(p)
 	}
 
 	// If using 64-bit, our reservation is all we have.
-	if uintptr(h.arena_end)-uintptr(h.arena_start) >= _MaxArena32 {
+	if h.arena_end-h.arena_start >= _MaxArena32 {
 		return nil
 	}
 
@@ -451,30 +454,34 @@ func mHeap_SysAlloc(h *mheap, n uintptr) unsafe.Pointer {
 		return nil
 	}
 
-	if p < h.arena_start || uintptr(p)+p_size-uintptr(h.arena_start) >= _MaxArena32 {
-		print("runtime: memory allocated by OS (", p, ") not in usable range [", hex(h.arena_start), ",", hex(h.arena_start+_MaxArena32), ")\n")
-		sysFree((unsafe.Pointer)(p), p_size, &memstats.heap_sys)
+	if p < h.arena_start || uintptr(p)+p_size-h.arena_start >= _MaxArena32 {
+		top := ^uintptr(0)
+		if top-h.arena_start > _MaxArena32 {
+			top = h.arena_start + _MaxArena32
+		}
+		print("runtime: memory allocated by OS (", hex(p), ") not in usable range [", hex(h.arena_start), ",", hex(top), ")\n")
+		sysFree(unsafe.Pointer(p), p_size, &memstats.heap_sys)
 		return nil
 	}
 
 	p_end := p + p_size
 	p += -p & (_PageSize - 1)
-	if uintptr(p)+n > uintptr(h.arena_used) {
-		mHeap_MapBits(h, p+n)
-		mHeap_MapSpans(h, p+n)
+	if uintptr(p)+n > h.arena_used {
+		h.mapBits(p + n)
+		h.mapSpans(p + n)
 		h.arena_used = p + n
 		if p_end > h.arena_end {
 			h.arena_end = p_end
 		}
 		if raceenabled {
-			racemapshadow((unsafe.Pointer)(p), n)
+			racemapshadow(unsafe.Pointer(p), n)
 		}
 	}
 
 	if uintptr(p)&(_PageSize-1) != 0 {
 		throw("misrounded allocation in MHeap_SysAlloc")
 	}
-	return (unsafe.Pointer)(p)
+	return unsafe.Pointer(p)
 }
 
 // base address for all 0-byte allocations
@@ -510,6 +517,27 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
 		return persistentalloc(size, align, &memstats.other_sys)
 	}
 
+	// assistG is the G to charge for this allocation, or nil if
+	// GC is not currently active.
+	var assistG *g
+	if gcBlackenEnabled != 0 {
+		// Charge the current user G for this allocation.
+		assistG = getg()
+		if assistG.m.curg != nil {
+			assistG = assistG.m.curg
+		}
+		// Charge the allocation against the G. We'll account
+		// for internal fragmentation at the end of mallocgc.
+		assistG.gcAssistBytes -= int64(size)
+
+		if assistG.gcAssistBytes < 0 {
+			// This G is in debt. Assist the GC to correct
+			// this before allocating. This must happen
+			// before disabling preemption.
+			gcAssistAlloc(assistG)
+		}
+	}
+
 	// Set mp.mallocing to keep from being preempted by GC.
 	mp := acquirem()
 	if mp.mallocing != 0 {
@@ -565,9 +593,9 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
 			} else if size&1 == 0 {
 				off = round(off, 2)
 			}
-			if off+size <= maxTinySize && c.tiny != nil {
+			if off+size <= maxTinySize && c.tiny != 0 {
 				// The object fits into existing tiny block.
-				x = add(c.tiny, off)
+				x = unsafe.Pointer(c.tiny + off)
 				c.tinyoffset = off + size
 				c.local_tinyallocs++
 				mp.mallocing = 0
@@ -579,7 +607,7 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
 			v := s.freelist
 			if v.ptr() == nil {
 				systemstack(func() {
-					mCache_Refill(c, tinySizeClass)
+					c.refill(tinySizeClass)
 				})
 				shouldhelpgc = true
 				s = c.alloc[tinySizeClass]
@@ -594,8 +622,8 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
 			(*[2]uint64)(x)[1] = 0
 			// See if we need to replace the existing tiny block with the new one
 			// based on amount of remaining free space.
-			if size < c.tinyoffset {
-				c.tiny = x
+			if size < c.tinyoffset || c.tiny == 0 {
+				c.tiny = uintptr(x)
 				c.tinyoffset = size
 			}
 			size = maxTinySize
@@ -611,7 +639,7 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
 			v := s.freelist
 			if v.ptr() == nil {
 				systemstack(func() {
-					mCache_Refill(c, int32(sizeclass))
+					c.refill(int32(sizeclass))
 				})
 				shouldhelpgc = true
 				s = c.alloc[sizeclass]
@@ -624,12 +652,11 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
 			x = unsafe.Pointer(v)
 			if flags&flagNoZero == 0 {
 				v.ptr().next = 0
-				if size > 2*ptrSize && ((*[2]uintptr)(x))[1] != 0 {
+				if size > 2*sys.PtrSize && ((*[2]uintptr)(x))[1] != 0 {
 					memclr(unsafe.Pointer(v), size)
 				}
 			}
 		}
-		c.local_cachealloc += size
 	} else {
 		var s *mspan
 		shouldhelpgc = true
@@ -686,6 +713,9 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
 	if raceenabled {
 		racemalloc(x, size)
 	}
+	if msanenabled {
+		msanmalloc(x, size)
+	}
 
 	mp.mallocing = 0
 	releasem(mp)
@@ -704,26 +734,14 @@ func mallocgc(size uintptr, typ *_type, flags uint32) unsafe.Pointer {
 		}
 	}
 
-	if shouldhelpgc && shouldtriggergc() {
-		startGC(gcBackgroundMode, false)
-	} else if gcBlackenEnabled != 0 {
-		// Assist garbage collector. We delay this until the
-		// epilogue so that it doesn't interfere with the
-		// inner working of malloc such as mcache refills that
-		// might happen while doing the gcAssistAlloc.
-		gcAssistAlloc(size, shouldhelpgc)
-	} else if shouldhelpgc && bggc.working != 0 {
-		// The GC is starting up or shutting down, so we can't
-		// assist, but we also can't allocate unabated. Slow
-		// down this G's allocation and help the GC stay
-		// scheduled by yielding.
-		//
-		// TODO: This is a workaround. Either help the GC make
-		// the transition or block.
-		gp := getg()
-		if gp != gp.m.g0 && gp.m.locks == 0 && gp.m.preemptoff == "" {
-			Gosched()
-		}
+	if assistG != nil {
+		// Account for internal fragmentation in the assist
+		// debt now that we know it.
+		assistG.gcAssistBytes -= int64(size - dataSize)
+	}
+
+	if shouldhelpgc && gcShouldStart(false) {
+		gcStart(gcBackgroundMode, false)
 	}
 
 	return x
@@ -745,7 +763,7 @@ func largeAlloc(size uintptr, flag uint32) *mspan {
 	// pays the debt down to npage pages.
 	deductSweepCredit(npages*_PageSize, npages)
 
-	s := mHeap_Alloc(&mheap_, npages, 0, true, flag&_FlagNoZero == 0)
+	s := mheap_.alloc(npages, 0, true, flag&_FlagNoZero == 0)
 	if s == nil {
 		throw("out of memory")
 	}
@@ -792,26 +810,64 @@ func rawmem(size uintptr) unsafe.Pointer {
 }
 
 func profilealloc(mp *m, x unsafe.Pointer, size uintptr) {
-	c := mp.mcache
-	rate := MemProfileRate
-	if size < uintptr(rate) {
-		// pick next profile time
-		// If you change this, also change allocmcache.
-		if rate > 0x3fffffff { // make 2*rate not overflow
-			rate = 0x3fffffff
-		}
-		next := int32(fastrand1()) % (2 * int32(rate))
-		// Subtract the "remainder" of the current allocation.
-		// Otherwise objects that are close in size to sampling rate
-		// will be under-sampled, because we consistently discard this remainder.
-		next -= (int32(size) - c.next_sample)
-		if next < 0 {
-			next = 0
+	mp.mcache.next_sample = nextSample()
+	mProf_Malloc(x, size)
+}
+
+// nextSample returns the next sampling point for heap profiling.
+// It produces a random variable with a geometric distribution and
+// mean MemProfileRate. This is done by generating a uniformly
+// distributed random number and applying the cumulative distribution
+// function for an exponential.
+func nextSample() int32 {
+	if GOOS == "plan9" {
+		// Plan 9 doesn't support floating point in note handler.
+		if g := getg(); g == g.m.gsignal {
+			return nextSampleNoFP()
 		}
-		c.next_sample = next
 	}
 
-	mProf_Malloc(x, size)
+	period := MemProfileRate
+
+	// make nextSample not overflow. Maximum possible step is
+	// -ln(1/(1<<kRandomBitCount)) * period, approximately 20 * period.
+	switch {
+	case period > 0x7000000:
+		period = 0x7000000
+	case period == 0:
+		return 0
+	}
+
+	// Let m be the sample rate,
+	// the probability distribution function is m*exp(-mx), so the CDF is
+	// p = 1 - exp(-mx), so
+	// q = 1 - p == exp(-mx)
+	// log_e(q) = -mx
+	// -log_e(q)/m = x
+	// x = -log_e(q) * period
+	// x = log_2(q) * (-log_e(2)) * period    ; Using log_2 for efficiency
+	const randomBitCount = 26
+	q := uint32(fastrand1())%(1<<randomBitCount) + 1
+	qlog := fastlog2(float64(q)) - randomBitCount
+	if qlog > 0 {
+		qlog = 0
+	}
+	const minusLog2 = -0.6931471805599453 // -ln(2)
+	return int32(qlog*(minusLog2*float64(period))) + 1
+}
+
+// nextSampleNoFP is similar to nextSample, but uses older,
+// simpler code to avoid floating point.
+func nextSampleNoFP() int32 {
+	// Set first allocation sample size.
+	rate := MemProfileRate
+	if rate > 0x3fffffff { // make 2*rate not overflow
+		rate = 0x3fffffff
+	}
+	if rate != 0 {
+		return int32(int(fastrand1()) % (2 * rate))
+	}
+	return 0
 }
 
 type persistentAlloc struct {
diff --git a/src/runtime/malloc_test.go b/src/runtime/malloc_test.go
index f0e73ba..767b51f 100644
--- a/src/runtime/malloc_test.go
+++ b/src/runtime/malloc_test.go
@@ -17,13 +17,14 @@ func TestMemStats(t *testing.T) {
 	st := new(MemStats)
 	ReadMemStats(st)
 
-	// Everything except HeapReleased and HeapIdle, because they indeed can be 0.
+	// Everything except HeapReleased, HeapIdle, and NumGC,
+	// because they indeed can be 0.
 	if st.Alloc == 0 || st.TotalAlloc == 0 || st.Sys == 0 || st.Lookups == 0 ||
 		st.Mallocs == 0 || st.Frees == 0 || st.HeapAlloc == 0 || st.HeapSys == 0 ||
 		st.HeapInuse == 0 || st.HeapObjects == 0 || st.StackInuse == 0 ||
 		st.StackSys == 0 || st.MSpanInuse == 0 || st.MSpanSys == 0 || st.MCacheInuse == 0 ||
 		st.MCacheSys == 0 || st.BuckHashSys == 0 || st.GCSys == 0 || st.OtherSys == 0 ||
-		st.NextGC == 0 || st.NumGC == 0 {
+		st.NextGC == 0 {
 		t.Fatalf("Zero value: %+v", *st)
 	}
 
@@ -58,6 +59,14 @@ func TestMemStats(t *testing.T) {
 		if st.PauseTotalNs != pauseTotal {
 			t.Fatalf("PauseTotalNs(%d) != sum PauseNs(%d)", st.PauseTotalNs, pauseTotal)
 		}
+		for i := int(st.NumGC); i < len(st.PauseNs); i++ {
+			if st.PauseNs[i] != 0 {
+				t.Fatalf("Non-zero PauseNs[%d]: %+v", i, st)
+			}
+			if st.PauseEnd[i] != 0 {
+				t.Fatalf("Non-zero PauseEnd[%d]: %+v", i, st)
+			}
+		}
 	} else {
 		if st.PauseTotalNs < pauseTotal {
 			t.Fatalf("PauseTotalNs(%d) < sum PauseNs(%d)", st.PauseTotalNs, pauseTotal)
@@ -82,6 +91,23 @@ func TestStringConcatenationAllocs(t *testing.T) {
 	}
 }
 
+func TestTinyAlloc(t *testing.T) {
+	const N = 16
+	var v [N]unsafe.Pointer
+	for i := range v {
+		v[i] = unsafe.Pointer(new(byte))
+	}
+
+	chunks := make(map[uintptr]bool, N)
+	for _, p := range v {
+		chunks[uintptr(p)&^7] = true
+	}
+
+	if len(chunks) == N {
+		t.Fatal("no bytes allocated within the same 8-byte chunk")
+	}
+}
+
 var mallocSink uintptr
 
 func BenchmarkMalloc8(b *testing.B) {
diff --git a/src/runtime/mbarrier.go b/src/runtime/mbarrier.go
index 0dbe1ff..45086c4 100644
--- a/src/runtime/mbarrier.go
+++ b/src/runtime/mbarrier.go
@@ -13,7 +13,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 // markwb is the mark-phase write barrier, the only barrier we have.
 // The rest of this file exists only to make calls to this function.
@@ -31,12 +34,12 @@ import "unsafe"
 // Dealing with memory ordering:
 //
 // Dijkstra pointed out that maintaining the no black to white
-// pointers means that white to white pointers not need
+// pointers means that white to white pointers do not need
 // to be noted by the write barrier. Furthermore if either
 // white object dies before it is reached by the
 // GC then the object can be collected during this GC cycle
 // instead of waiting for the next cycle. Unfortunately the cost of
-// ensure that the object holding the slot doesn't concurrently
+// ensuring that the object holding the slot doesn't concurrently
 // change to black without the mutator noticing seems prohibitive.
 //
 // Consider the following example where the mutator writes into
@@ -84,9 +87,9 @@ import "unsafe"
 // frames that have potentially been active since the concurrent scan,
 // so it depends on write barriers to track changes to pointers in
 // stack frames that have not been active.
-//go:nowritebarrier
+//go:nowritebarrierrec
 func gcmarkwb_m(slot *uintptr, ptr uintptr) {
-	if writeBarrierEnabled {
+	if writeBarrier.needed {
 		if ptr != 0 && inheap(ptr) {
 			shade(ptr)
 		}
@@ -125,10 +128,13 @@ func writebarrierptr_nostore1(dst *uintptr, src uintptr) {
 //go:nosplit
 func writebarrierptr(dst *uintptr, src uintptr) {
 	*dst = src
-	if !writeBarrierEnabled {
+	if writeBarrier.cgo {
+		cgoCheckWriteBarrier(dst, src)
+	}
+	if !writeBarrier.needed {
 		return
 	}
-	if src != 0 && (src < _PhysPageSize || src == poisonStack) {
+	if src != 0 && (src < sys.PhysPageSize || src == poisonStack) {
 		systemstack(func() {
 			print("runtime: writebarrierptr *", dst, " = ", hex(src), "\n")
 			throw("bad pointer in write barrier")
@@ -141,10 +147,13 @@ func writebarrierptr(dst *uintptr, src uintptr) {
 // Do not reapply.
 //go:nosplit
 func writebarrierptr_nostore(dst *uintptr, src uintptr) {
-	if !writeBarrierEnabled {
+	if writeBarrier.cgo {
+		cgoCheckWriteBarrier(dst, src)
+	}
+	if !writeBarrier.needed {
 		return
 	}
-	if src != 0 && (src < _PhysPageSize || src == poisonStack) {
+	if src != 0 && (src < sys.PhysPageSize || src == poisonStack) {
 		systemstack(func() { throw("bad pointer in write barrier") })
 	}
 	writebarrierptr_nostore1(dst, src)
@@ -179,6 +188,9 @@ func writebarrieriface(dst *[2]uintptr, src [2]uintptr) {
 //go:nosplit
 func typedmemmove(typ *_type, dst, src unsafe.Pointer) {
 	memmove(dst, src, typ.size)
+	if writeBarrier.cgo {
+		cgoCheckMemmove(typ, dst, src, 0, typ.size)
+	}
 	if typ.kind&kindNoPointers != 0 {
 		return
 	}
@@ -195,15 +207,18 @@ func reflect_typedmemmove(typ *_type, dst, src unsafe.Pointer) {
 //go:linkname reflect_typedmemmovepartial reflect.typedmemmovepartial
 func reflect_typedmemmovepartial(typ *_type, dst, src unsafe.Pointer, off, size uintptr) {
 	memmove(dst, src, size)
-	if !writeBarrierEnabled || typ.kind&kindNoPointers != 0 || size < ptrSize || !inheap(uintptr(dst)) {
+	if writeBarrier.cgo {
+		cgoCheckMemmove(typ, dst, src, off, size)
+	}
+	if !writeBarrier.needed || typ.kind&kindNoPointers != 0 || size < sys.PtrSize || !inheap(uintptr(dst)) {
 		return
 	}
 
-	if frag := -off & (ptrSize - 1); frag != 0 {
+	if frag := -off & (sys.PtrSize - 1); frag != 0 {
 		dst = add(dst, frag)
 		size -= frag
 	}
-	heapBitsBulkBarrier(uintptr(dst), size&^(ptrSize-1))
+	heapBitsBulkBarrier(uintptr(dst), size&^(sys.PtrSize-1))
 }
 
 // callwritebarrier is invoked at the end of reflectcall, to execute
@@ -215,7 +230,7 @@ func reflect_typedmemmovepartial(typ *_type, dst, src unsafe.Pointer, off, size
 // not to be preempted before the write barriers have been run.
 //go:nosplit
 func callwritebarrier(typ *_type, frame unsafe.Pointer, framesize, retoffset uintptr) {
-	if !writeBarrierEnabled || typ == nil || typ.kind&kindNoPointers != 0 || framesize-retoffset < ptrSize || !inheap(uintptr(frame)) {
+	if !writeBarrier.needed || typ == nil || typ.kind&kindNoPointers != 0 || framesize-retoffset < sys.PtrSize || !inheap(uintptr(frame)) {
 		return
 	}
 	heapBitsBulkBarrier(uintptr(add(frame, retoffset)), framesize-retoffset)
@@ -241,12 +256,20 @@ func typedslicecopy(typ *_type, dst, src slice) int {
 		racewriterangepc(dstp, uintptr(n)*typ.size, callerpc, pc)
 		racereadrangepc(srcp, uintptr(n)*typ.size, callerpc, pc)
 	}
+	if msanenabled {
+		msanwrite(dstp, uintptr(n)*typ.size)
+		msanread(srcp, uintptr(n)*typ.size)
+	}
+
+	if writeBarrier.cgo {
+		cgoCheckSliceCopy(typ, dst, src, n)
+	}
 
 	// Note: No point in checking typ.kind&kindNoPointers here:
 	// compiler only emits calls to typedslicecopy for types with pointers,
 	// and growslice and reflect_typedslicecopy check for pointers
 	// before calling typedslicecopy.
-	if !writeBarrierEnabled {
+	if !writeBarrier.needed {
 		memmove(dstp, srcp, uintptr(n)*typ.size)
 		return n
 	}
diff --git a/src/runtime/mbitmap.go b/src/runtime/mbitmap.go
index fd6b4b1..336d4d8 100644
--- a/src/runtime/mbitmap.go
+++ b/src/runtime/mbitmap.go
@@ -66,14 +66,18 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 const (
 	bitPointer = 1 << 0
 	bitMarked  = 1 << 4
 
-	heapBitsShift   = 1                 // shift offset between successive bitPointer or bitMarked entries
-	heapBitmapScale = ptrSize * (8 / 2) // number of data bytes described by one heap bitmap byte
+	heapBitsShift   = 1                     // shift offset between successive bitPointer or bitMarked entries
+	heapBitmapScale = sys.PtrSize * (8 / 2) // number of data bytes described by one heap bitmap byte
 
 	// all mark/pointer bits in a byte
 	bitMarkedAll  = bitMarked | bitMarked<<heapBitsShift | bitMarked<<(2*heapBitsShift) | bitMarked<<(3*heapBitsShift)
@@ -128,7 +132,7 @@ func subtract1(p *byte) *byte {
 // after observing the change to arena_used.
 //
 //go:nowritebarrier
-func mHeap_MapBits(h *mheap, arena_used uintptr) {
+func (h *mheap) mapBits(arena_used uintptr) {
 	// Caller has added extra mappings to the arena.
 	// Add extra mappings of bitmap words as needed.
 	// We allocate extra bitmap pieces in chunks of bitmapChunk.
@@ -136,7 +140,7 @@ func mHeap_MapBits(h *mheap, arena_used uintptr) {
 
 	n := (arena_used - mheap_.arena_start) / heapBitmapScale
 	n = round(n, bitmapChunk)
-	n = round(n, _PhysPageSize)
+	n = round(n, sys.PhysPageSize)
 	if h.bitmap_mapped >= n {
 		return
 	}
@@ -161,7 +165,7 @@ type heapBits struct {
 //go:nosplit
 func heapBitsForAddr(addr uintptr) heapBits {
 	// 2 bits per work, 4 pairs per byte, and a mask is hard coded.
-	off := (addr - mheap_.arena_start) / ptrSize
+	off := (addr - mheap_.arena_start) / sys.PtrSize
 	return heapBits{(*uint8)(unsafe.Pointer(mheap_.arena_start - off/4 - 1)), uint32(off & 3)}
 }
 
@@ -182,7 +186,11 @@ func heapBitsForSpan(base uintptr) (hbits heapBits) {
 // If p does not point into a heap object,
 // return base == 0
 // otherwise return the base of the object.
-func heapBitsForObject(p uintptr) (base uintptr, hbits heapBits, s *mspan) {
+//
+// refBase and refOff optionally give the base address of the object
+// in which the pointer p was found and the byte offset at which it
+// was found. These are used for error reporting.
+func heapBitsForObject(p, refBase, refOff uintptr) (base uintptr, hbits heapBits, s *mspan) {
 	arenaStart := mheap_.arena_start
 	if p < arenaStart || p >= mheap_.arena_used {
 		return
@@ -203,18 +211,28 @@ func heapBitsForObject(p uintptr) (base uintptr, hbits heapBits, s *mspan) {
 
 		// The following ensures that we are rigorous about what data
 		// structures hold valid pointers.
-		// TODO(rsc): Check if this still happens.
 		if debug.invalidptr != 0 {
-			// Still happens sometimes. We don't know why.
+			// Typically this indicates an incorrect use
+			// of unsafe or cgo to store a bad pointer in
+			// the Go heap. It may also indicate a runtime
+			// bug.
+			//
+			// TODO(austin): We could be more aggressive
+			// and detect pointers to unallocated objects
+			// in allocated spans.
 			printlock()
-			print("runtime:objectstart Span weird: p=", hex(p), " k=", hex(k))
-			if s == nil {
-				print(" s=nil\n")
+			print("runtime: pointer ", hex(p))
+			if s.state != mSpanInUse {
+				print(" to unallocated span")
 			} else {
-				print(" s.start=", hex(s.start<<_PageShift), " s.limit=", hex(s.limit), " s.state=", s.state, "\n")
+				print(" to unused region of span")
+			}
+			print("idx=", hex(idx), " span.start=", hex(s.start<<_PageShift), " span.limit=", hex(s.limit), " span.state=", s.state, "\n")
+			if refBase != 0 {
+				print("runtime: found in object at *(", hex(refBase), "+", hex(refOff), ")\n")
+				gcDumpObject("object", refBase, refOff)
 			}
-			printunlock()
-			throw("objectstart: bad pointer in unexpected span")
+			throw("found bad pointer in Go heap (incorrect use of unsafe or cgo?)")
 		}
 		return
 	}
@@ -288,7 +306,7 @@ func (h heapBits) setMarked() {
 	// Might be racing with other updates, so use atomic update always.
 	// We used to be clever here and use a non-atomic update in certain
 	// cases, but it's not worth the risk.
-	atomicor8(h.bitp, bitMarked<<h.shift)
+	atomic.Or8(h.bitp, bitMarked<<h.shift)
 }
 
 // setMarkedNonAtomic sets the marked bit in the heap bits, non-atomically.
@@ -311,18 +329,18 @@ func (h heapBits) isPointer() bool {
 // far into the bitmap.
 // h must describe the initial word of the object.
 func (h heapBits) hasPointers(size uintptr) bool {
-	if size == ptrSize { // 1-word objects are always pointers
+	if size == sys.PtrSize { // 1-word objects are always pointers
 		return true
 	}
 	// Otherwise, at least a 2-word object, and at least 2-word aligned,
-	// so h.shift is either 0 or 4, so we know we can get the bits for the
+	// so h.shift is either 0 or 2, so we know we can get the bits for the
 	// first two words out of *h.bitp.
 	// If either of the first two words is a pointer, not pointer free.
 	b := uint32(*h.bitp >> h.shift)
 	if b&(bitPointer|bitPointer<<heapBitsShift) != 0 {
 		return true
 	}
-	if size == 2*ptrSize {
+	if size == 2*sys.PtrSize {
 		return false
 	}
 	// At least a 4-word object. Check scan bit (aka marked bit) in third word.
@@ -337,7 +355,7 @@ func (h heapBits) hasPointers(size uintptr) bool {
 // checkmark bit varies by size.
 // h must describe the initial word of the object.
 func (h heapBits) isCheckmarked(size uintptr) bool {
-	if size == ptrSize {
+	if size == sys.PtrSize {
 		return (*h.bitp>>h.shift)&bitPointer != 0
 	}
 	// All multiword objects are 2-word aligned,
@@ -352,11 +370,11 @@ func (h heapBits) isCheckmarked(size uintptr) bool {
 // checkmark bit varies by size.
 // h must describe the initial word of the object.
 func (h heapBits) setCheckmarked(size uintptr) {
-	if size == ptrSize {
-		atomicor8(h.bitp, bitPointer<<h.shift)
+	if size == sys.PtrSize {
+		atomic.Or8(h.bitp, bitPointer<<h.shift)
 		return
 	}
-	atomicor8(h.bitp, bitMarked<<(heapBitsShift+h.shift))
+	atomic.Or8(h.bitp, bitMarked<<(heapBitsShift+h.shift))
 }
 
 // heapBitsBulkBarrier executes writebarrierptr_nostore
@@ -378,10 +396,10 @@ func (h heapBits) setCheckmarked(size uintptr) {
 //
 //go:nosplit
 func heapBitsBulkBarrier(p, size uintptr) {
-	if (p|size)&(ptrSize-1) != 0 {
+	if (p|size)&(sys.PtrSize-1) != 0 {
 		throw("heapBitsBulkBarrier: unaligned arguments")
 	}
-	if !writeBarrierEnabled {
+	if !writeBarrier.needed {
 		return
 	}
 	if !inheap(p) {
@@ -413,7 +431,7 @@ func heapBitsBulkBarrier(p, size uintptr) {
 	}
 
 	h := heapBitsForAddr(p)
-	for i := uintptr(0); i < size; i += ptrSize {
+	for i := uintptr(0); i < size; i += sys.PtrSize {
 		if h.isPointer() {
 			x := (*uintptr)(unsafe.Pointer(p + i))
 			writebarrierptr_nostore(x, *x)
@@ -448,13 +466,13 @@ func typeBitsBulkBarrier(typ *_type, p, size uintptr) {
 		println("runtime: typeBitsBulkBarrier with type ", *typ._string, " with GC prog")
 		throw("runtime: invalid typeBitsBulkBarrier")
 	}
-	if !writeBarrierEnabled {
+	if !writeBarrier.needed {
 		return
 	}
 	ptrmask := typ.gcdata
 	var bits uint32
-	for i := uintptr(0); i < typ.ptrdata; i += ptrSize {
-		if i&(ptrSize*8-1) == 0 {
+	for i := uintptr(0); i < typ.ptrdata; i += sys.PtrSize {
+		if i&(sys.PtrSize*8-1) == 0 {
 			bits = uint32(*ptrmask)
 			ptrmask = addb(ptrmask, 1)
 		} else {
@@ -481,7 +499,7 @@ func (h heapBits) initSpan(size, n, total uintptr) {
 		throw("initSpan: unaligned length")
 	}
 	nbyte := total / heapBitmapScale
-	if ptrSize == 8 && size == ptrSize {
+	if sys.PtrSize == 8 && size == sys.PtrSize {
 		end := h.bitp
 		bitp := subtractb(end, nbyte-1)
 		for {
@@ -500,7 +518,7 @@ func (h heapBits) initSpan(size, n, total uintptr) {
 // It clears the checkmark bits, which are set to 1 in normal operation.
 func (h heapBits) initCheckmarkSpan(size, n, total uintptr) {
 	// The ptrSize == 8 is a compile-time constant false on 32-bit and eliminates this code entirely.
-	if ptrSize == 8 && size == ptrSize {
+	if sys.PtrSize == 8 && size == sys.PtrSize {
 		// Checkmark bit is type bit, bottom bit of every 2-bit entry.
 		// Only possible on 64-bit system, since minimum size is 8.
 		// Must clear type bit (checkmark bit) of every word.
@@ -514,7 +532,7 @@ func (h heapBits) initCheckmarkSpan(size, n, total uintptr) {
 	}
 	for i := uintptr(0); i < n; i++ {
 		*h.bitp &^= bitMarked << (heapBitsShift + h.shift)
-		h = h.forward(size / ptrSize)
+		h = h.forward(size / sys.PtrSize)
 	}
 }
 
@@ -524,7 +542,7 @@ func (h heapBits) initCheckmarkSpan(size, n, total uintptr) {
 // but consulted by typedmemmove.)
 func (h heapBits) clearCheckmarkSpan(size, n, total uintptr) {
 	// The ptrSize == 8 is a compile-time constant false on 32-bit and eliminates this code entirely.
-	if ptrSize == 8 && size == ptrSize {
+	if sys.PtrSize == 8 && size == sys.PtrSize {
 		// Checkmark bit is type bit, bottom bit of every 2-bit entry.
 		// Only possible on 64-bit system, since minimum size is 8.
 		// Must clear type bit (checkmark bit) of every word.
@@ -549,7 +567,7 @@ func heapBitsSweepSpan(base, size, n uintptr, f func(uintptr)) {
 	switch {
 	default:
 		throw("heapBitsSweepSpan")
-	case ptrSize == 8 && size == ptrSize:
+	case sys.PtrSize == 8 && size == sys.PtrSize:
 		// Consider mark bits in all four 2-bit entries of each bitmap byte.
 		bitp := h.bitp
 		for i := uintptr(0); i < n; i += 4 {
@@ -562,28 +580,28 @@ func heapBitsSweepSpan(base, size, n uintptr, f func(uintptr)) {
 			if x&bitMarked != 0 {
 				x &^= bitMarked
 			} else {
-				f(base + i*ptrSize)
+				f(base + i*sys.PtrSize)
 			}
 			if x&(bitMarked<<heapBitsShift) != 0 {
 				x &^= bitMarked << heapBitsShift
 			} else {
-				f(base + (i+1)*ptrSize)
+				f(base + (i+1)*sys.PtrSize)
 			}
 			if x&(bitMarked<<(2*heapBitsShift)) != 0 {
 				x &^= bitMarked << (2 * heapBitsShift)
 			} else {
-				f(base + (i+2)*ptrSize)
+				f(base + (i+2)*sys.PtrSize)
 			}
 			if x&(bitMarked<<(3*heapBitsShift)) != 0 {
 				x &^= bitMarked << (3 * heapBitsShift)
 			} else {
-				f(base + (i+3)*ptrSize)
+				f(base + (i+3)*sys.PtrSize)
 			}
 			*bitp = uint8(x)
 			bitp = subtract1(bitp)
 		}
 
-	case size%(4*ptrSize) == 0:
+	case size%(4*sys.PtrSize) == 0:
 		// Mark bit is in first word of each object.
 		// Each object starts at bit 0 of a heap bitmap byte.
 		bitp := h.bitp
@@ -600,7 +618,7 @@ func heapBitsSweepSpan(base, size, n uintptr, f func(uintptr)) {
 			bitp = subtractb(bitp, step)
 		}
 
-	case size%(4*ptrSize) == 2*ptrSize:
+	case size%(4*sys.PtrSize) == 2*sys.PtrSize:
 		// Mark bit is in first word of each object,
 		// but every other object starts halfway through a heap bitmap byte.
 		// Unroll loop 2x to handle alternating shift count and step size.
@@ -614,7 +632,7 @@ func heapBitsSweepSpan(base, size, n uintptr, f func(uintptr)) {
 			} else {
 				x &^= bitMarked | bitPointer | (bitMarked|bitPointer)<<heapBitsShift
 				f(base + i*size)
-				if size > 2*ptrSize {
+				if size > 2*sys.PtrSize {
 					x = 0
 				}
 			}
@@ -629,7 +647,7 @@ func heapBitsSweepSpan(base, size, n uintptr, f func(uintptr)) {
 			} else {
 				x &^= (bitMarked|bitPointer)<<(2*heapBitsShift) | (bitMarked|bitPointer)<<(3*heapBitsShift)
 				f(base + (i+1)*size)
-				if size > 2*ptrSize {
+				if size > 2*sys.PtrSize {
 					*subtract1(bitp) = 0
 				}
 			}
@@ -669,7 +687,7 @@ func heapBitsSetType(x, size, dataSize uintptr, typ *_type) {
 	// The checks for size == ptrSize and size == 2*ptrSize can therefore
 	// assume that dataSize == size without checking it explicitly.
 
-	if ptrSize == 8 && size == ptrSize {
+	if sys.PtrSize == 8 && size == sys.PtrSize {
 		// It's one word and it has pointers, it must be a pointer.
 		// In general we'd need an atomic update here if the
 		// concurrent GC were marking objects in this span,
@@ -695,8 +713,8 @@ func heapBitsSetType(x, size, dataSize uintptr, typ *_type) {
 	// This is called out as a special case primarily for 32-bit systems,
 	// so that on 32-bit systems the code below can assume all objects
 	// are 4-word aligned (because they're all 16-byte aligned).
-	if size == 2*ptrSize {
-		if typ.size == ptrSize {
+	if size == 2*sys.PtrSize {
+		if typ.size == sys.PtrSize {
 			// We're allocating a block big enough to hold two pointers.
 			// On 64-bit, that means the actual object must be two pointers,
 			// or else we'd have used the one-pointer-sized block.
@@ -705,26 +723,26 @@ func heapBitsSetType(x, size, dataSize uintptr, typ *_type) {
 			// just the smallest block available. Distinguish by checking dataSize.
 			// (In general the number of instances of typ being allocated is
 			// dataSize/typ.size.)
-			if ptrSize == 4 && dataSize == ptrSize {
+			if sys.PtrSize == 4 && dataSize == sys.PtrSize {
 				// 1 pointer.
 				if gcphase == _GCoff {
 					*h.bitp |= bitPointer << h.shift
 				} else {
-					atomicor8(h.bitp, bitPointer<<h.shift)
+					atomic.Or8(h.bitp, bitPointer<<h.shift)
 				}
 			} else {
 				// 2-element slice of pointer.
 				if gcphase == _GCoff {
 					*h.bitp |= (bitPointer | bitPointer<<heapBitsShift) << h.shift
 				} else {
-					atomicor8(h.bitp, (bitPointer|bitPointer<<heapBitsShift)<<h.shift)
+					atomic.Or8(h.bitp, (bitPointer|bitPointer<<heapBitsShift)<<h.shift)
 				}
 			}
 			return
 		}
 		// Otherwise typ.size must be 2*ptrSize, and typ.kind&kindGCProg == 0.
 		if doubleCheck {
-			if typ.size != 2*ptrSize || typ.kind&kindGCProg != 0 {
+			if typ.size != 2*sys.PtrSize || typ.kind&kindGCProg != 0 {
 				print("runtime: heapBitsSetType size=", size, " but typ.size=", typ.size, " gcprog=", typ.kind&kindGCProg != 0, "\n")
 				throw("heapBitsSetType")
 			}
@@ -734,7 +752,7 @@ func heapBitsSetType(x, size, dataSize uintptr, typ *_type) {
 		if gcphase == _GCoff {
 			*h.bitp |= uint8(hb << h.shift)
 		} else {
-			atomicor8(h.bitp, uint8(hb<<h.shift))
+			atomic.Or8(h.bitp, uint8(hb<<h.shift))
 		}
 		return
 	}
@@ -825,8 +843,8 @@ func heapBitsSetType(x, size, dataSize uintptr, typ *_type) {
 		// Filling in bits for an array of typ.
 		// Set up for repetition of ptrmask during main loop.
 		// Note that ptrmask describes only a prefix of
-		const maxBits = ptrSize*8 - 7
-		if typ.ptrdata/ptrSize <= maxBits {
+		const maxBits = sys.PtrSize*8 - 7
+		if typ.ptrdata/sys.PtrSize <= maxBits {
 			// Entire ptrmask fits in uintptr with room for a byte fragment.
 			// Load into pbits and never read from ptrmask again.
 			// This is especially important when the ptrmask has
@@ -837,12 +855,12 @@ func heapBitsSetType(x, size, dataSize uintptr, typ *_type) {
 			// Accumulate ptrmask into b.
 			// ptrmask is sized to describe only typ.ptrdata, but we record
 			// it as describing typ.size bytes, since all the high bits are zero.
-			nb = typ.ptrdata / ptrSize
+			nb = typ.ptrdata / sys.PtrSize
 			for i := uintptr(0); i < nb; i += 8 {
 				b |= uintptr(*p) << i
 				p = add1(p)
 			}
-			nb = typ.size / ptrSize
+			nb = typ.size / sys.PtrSize
 
 			// Replicate ptrmask to fill entire pbits uintptr.
 			// Doubling and truncating is fewer steps than
@@ -853,7 +871,7 @@ func heapBitsSetType(x, size, dataSize uintptr, typ *_type) {
 			pbits = b
 			endnb = nb
 			if nb+nb <= maxBits {
-				for endnb <= ptrSize*8 {
+				for endnb <= sys.PtrSize*8 {
 					pbits |= pbits << endnb
 					endnb += endnb
 				}
@@ -870,9 +888,9 @@ func heapBitsSetType(x, size, dataSize uintptr, typ *_type) {
 			endp = nil
 		} else {
 			// Ptrmask is larger. Read it multiple times.
-			n := (typ.ptrdata/ptrSize+7)/8 - 1
+			n := (typ.ptrdata/sys.PtrSize+7)/8 - 1
 			endp = addb(ptrmask, n)
-			endnb = typ.size/ptrSize - n*8
+			endnb = typ.size/sys.PtrSize - n*8
 		}
 	}
 	if p != nil {
@@ -883,12 +901,12 @@ func heapBitsSetType(x, size, dataSize uintptr, typ *_type) {
 
 	if typ.size == dataSize {
 		// Single entry: can stop once we reach the non-pointer data.
-		nw = typ.ptrdata / ptrSize
+		nw = typ.ptrdata / sys.PtrSize
 	} else {
 		// Repeated instances of typ in an array.
 		// Have to process first N-1 entries in full, but can stop
 		// once we reach the non-pointer data in the final entry.
-		nw = ((dataSize/typ.size-1)*typ.size + typ.ptrdata) / ptrSize
+		nw = ((dataSize/typ.size-1)*typ.size + typ.ptrdata) / sys.PtrSize
 	}
 	if nw == 0 {
 		// No pointers! Caller was supposed to check.
@@ -928,7 +946,7 @@ func heapBitsSetType(x, size, dataSize uintptr, typ *_type) {
 		b >>= 4
 		nb -= 4
 
-	case ptrSize == 8 && h.shift == 2:
+	case sys.PtrSize == 8 && h.shift == 2:
 		// Ptrmask and heap bitmap are misaligned.
 		// The bits for the first two words are in a byte shared with another object
 		// and must be updated atomically.
@@ -946,7 +964,7 @@ func heapBitsSetType(x, size, dataSize uintptr, typ *_type) {
 		if gcphase == _GCoff {
 			*hbitp |= uint8(hb)
 		} else {
-			atomicor8(hbitp, uint8(hb))
+			atomic.Or8(hbitp, uint8(hb))
 		}
 		hbitp = subtract1(hbitp)
 		if w += 2; w >= nw {
@@ -1041,7 +1059,7 @@ Phase3:
 	}
 
 	// Change nw from counting possibly-pointer words to total words in allocation.
-	nw = size / ptrSize
+	nw = size / sys.PtrSize
 
 	// Write whole bitmap bytes.
 	// The first is hb, the rest are zero.
@@ -1066,8 +1084,8 @@ Phase3:
 		if gcphase == _GCoff {
 			*hbitp = *hbitp&^(bitPointer|bitMarked|(bitPointer|bitMarked)<<heapBitsShift) | uint8(hb)
 		} else {
-			atomicand8(hbitp, ^uint8(bitPointer|bitMarked|(bitPointer|bitMarked)<<heapBitsShift))
-			atomicor8(hbitp, uint8(hb))
+			atomic.And8(hbitp, ^uint8(bitPointer|bitMarked|(bitPointer|bitMarked)<<heapBitsShift))
+			atomic.Or8(hbitp, uint8(hb))
 		}
 	}
 
@@ -1088,11 +1106,11 @@ Phase4:
 		// Double-check that bits to be written were written correctly.
 		// Does not check that other bits were not written, unfortunately.
 		h := heapBitsForAddr(x)
-		nptr := typ.ptrdata / ptrSize
-		ndata := typ.size / ptrSize
+		nptr := typ.ptrdata / sys.PtrSize
+		ndata := typ.size / sys.PtrSize
 		count := dataSize / typ.size
-		totalptr := ((count-1)*typ.size + typ.ptrdata) / ptrSize
-		for i := uintptr(0); i < size/ptrSize; i++ {
+		totalptr := ((count-1)*typ.size + typ.ptrdata) / sys.PtrSize
+		for i := uintptr(0); i < size/sys.PtrSize; i++ {
 			j := i % ndata
 			var have, want uint8
 			have = (*h.bitp >> h.shift) & (bitPointer | bitMarked)
@@ -1120,7 +1138,7 @@ Phase4:
 				print("initial bits h0.bitp=", h0.bitp, " h0.shift=", h0.shift, "\n")
 				print("current bits h.bitp=", h.bitp, " h.shift=", h.shift, " *h.bitp=", hex(*h.bitp), "\n")
 				print("ptrmask=", ptrmask, " p=", p, " endp=", endp, " endnb=", endnb, " pbits=", hex(pbits), " b=", hex(b), " nb=", nb, "\n")
-				println("at word", i, "offset", i*ptrSize, "have", have, "want", want)
+				println("at word", i, "offset", i*sys.PtrSize, "have", have, "want", want)
 				if typ.kind&kindGCProg != 0 {
 					println("GC program:")
 					dumpGCProg(addb(typ.gcdata, 4))
@@ -1151,14 +1169,14 @@ var debugPtrmask struct {
 // so that the relevant bitmap bytes are not shared with surrounding
 // objects and need not be accessed with atomic instructions.
 func heapBitsSetTypeGCProg(h heapBits, progSize, elemSize, dataSize, allocSize uintptr, prog *byte) {
-	if ptrSize == 8 && allocSize%(4*ptrSize) != 0 {
+	if sys.PtrSize == 8 && allocSize%(4*sys.PtrSize) != 0 {
 		// Alignment will be wrong.
 		throw("heapBitsSetTypeGCProg: small allocation")
 	}
 	var totalBits uintptr
 	if elemSize == dataSize {
 		totalBits = runGCProg(prog, nil, h.bitp, 2)
-		if totalBits*ptrSize != progSize {
+		if totalBits*sys.PtrSize != progSize {
 			println("runtime: heapBitsSetTypeGCProg: total bits", totalBits, "but progSize", progSize)
 			throw("heapBitsSetTypeGCProg: unexpected bit count")
 		}
@@ -1173,7 +1191,7 @@ func heapBitsSetTypeGCProg(h heapBits, progSize, elemSize, dataSize, allocSize u
 		// repeats that first element to fill the array.
 		var trailer [40]byte // 3 varints (max 10 each) + some bytes
 		i := 0
-		if n := elemSize/ptrSize - progSize/ptrSize; n > 0 {
+		if n := elemSize/sys.PtrSize - progSize/sys.PtrSize; n > 0 {
 			// literal(0)
 			trailer[i] = 0x01
 			i++
@@ -1195,7 +1213,7 @@ func heapBitsSetTypeGCProg(h heapBits, progSize, elemSize, dataSize, allocSize u
 		// repeat(elemSize/ptrSize, count-1)
 		trailer[i] = 0x80
 		i++
-		n := elemSize / ptrSize
+		n := elemSize / sys.PtrSize
 		for ; n >= 0x80; n >>= 7 {
 			trailer[i] = byte(n | 0x80)
 			i++
@@ -1219,7 +1237,7 @@ func heapBitsSetTypeGCProg(h heapBits, progSize, elemSize, dataSize, allocSize u
 		// last element. This will cause the code below to
 		// memclr the dead section of the final array element,
 		// so that scanobject can stop early in the final element.
-		totalBits = (elemSize*(count-1) + progSize) / ptrSize
+		totalBits = (elemSize*(count-1) + progSize) / sys.PtrSize
 	}
 	endProg := unsafe.Pointer(subtractb(h.bitp, (totalBits+3)/4))
 	endAlloc := unsafe.Pointer(subtractb(h.bitp, allocSize/heapBitmapScale))
@@ -1230,7 +1248,7 @@ func heapBitsSetTypeGCProg(h heapBits, progSize, elemSize, dataSize, allocSize u
 // size the size of the region described by prog, in bytes.
 // The resulting bitvector will have no more than size/ptrSize bits.
 func progToPointerMask(prog *byte, size uintptr) bitvector {
-	n := (size/ptrSize + 7) / 8
+	n := (size/sys.PtrSize + 7) / 8
 	x := (*[1 << 30]byte)(persistentalloc(n+1, 1, &memstats.buckhash_sys))[:n+1]
 	x[len(x)-1] = 0xa1 // overflow check sentinel
 	n = runGCProg(prog, nil, &x[0], 1)
@@ -1368,7 +1386,7 @@ Run:
 		// the pattern to a bit buffer holding at most 7 bits (a partial byte)
 		// it will not overflow.
 		src := dst
-		const maxBits = ptrSize*8 - 7
+		const maxBits = sys.PtrSize*8 - 7
 		if n <= maxBits {
 			// Start with bits in output buffer.
 			pattern := bits
@@ -1421,7 +1439,7 @@ Run:
 				nb := npattern
 				if nb+nb <= maxBits {
 					// Double pattern until the whole uintptr is filled.
-					for nb <= ptrSize*8 {
+					for nb <= sys.PtrSize*8 {
 						b |= b << nb
 						nb += nb
 					}
@@ -1609,8 +1627,8 @@ func getgcmaskcb(frame *stkframe, ctxt unsafe.Pointer) bool {
 //go:linkname reflect_gcbits reflect.gcbits
 func reflect_gcbits(x interface{}) []byte {
 	ret := getgcmask(x)
-	typ := (*ptrtype)(unsafe.Pointer((*eface)(unsafe.Pointer(&x))._type)).elem
-	nptr := typ.ptrdata / ptrSize
+	typ := (*ptrtype)(unsafe.Pointer(efaceOf(&x)._type)).elem
+	nptr := typ.ptrdata / sys.PtrSize
 	for uintptr(len(ret)) > nptr && ret[len(ret)-1] == 0 {
 		ret = ret[:len(ret)-1]
 	}
@@ -1619,7 +1637,7 @@ func reflect_gcbits(x interface{}) []byte {
 
 // Returns GC type info for object p for testing.
 func getgcmask(ep interface{}) (mask []byte) {
-	e := *(*eface)(unsafe.Pointer(&ep))
+	e := *efaceOf(&ep)
 	p := e.data
 	t := e._type
 	// data or bss
@@ -1628,10 +1646,10 @@ func getgcmask(ep interface{}) (mask []byte) {
 		if datap.data <= uintptr(p) && uintptr(p) < datap.edata {
 			bitmap := datap.gcdatamask.bytedata
 			n := (*ptrtype)(unsafe.Pointer(t)).elem.size
-			mask = make([]byte, n/ptrSize)
-			for i := uintptr(0); i < n; i += ptrSize {
-				off := (uintptr(p) + i - datap.data) / ptrSize
-				mask[i/ptrSize] = (*addb(bitmap, off/8) >> (off % 8)) & 1
+			mask = make([]byte, n/sys.PtrSize)
+			for i := uintptr(0); i < n; i += sys.PtrSize {
+				off := (uintptr(p) + i - datap.data) / sys.PtrSize
+				mask[i/sys.PtrSize] = (*addb(bitmap, off/8) >> (off % 8)) & 1
 			}
 			return
 		}
@@ -1640,10 +1658,10 @@ func getgcmask(ep interface{}) (mask []byte) {
 		if datap.bss <= uintptr(p) && uintptr(p) < datap.ebss {
 			bitmap := datap.gcbssmask.bytedata
 			n := (*ptrtype)(unsafe.Pointer(t)).elem.size
-			mask = make([]byte, n/ptrSize)
-			for i := uintptr(0); i < n; i += ptrSize {
-				off := (uintptr(p) + i - datap.bss) / ptrSize
-				mask[i/ptrSize] = (*addb(bitmap, off/8) >> (off % 8)) & 1
+			mask = make([]byte, n/sys.PtrSize)
+			for i := uintptr(0); i < n; i += sys.PtrSize {
+				off := (uintptr(p) + i - datap.bss) / sys.PtrSize
+				mask[i/sys.PtrSize] = (*addb(bitmap, off/8) >> (off % 8)) & 1
 			}
 			return
 		}
@@ -1653,14 +1671,14 @@ func getgcmask(ep interface{}) (mask []byte) {
 	var n uintptr
 	var base uintptr
 	if mlookup(uintptr(p), &base, &n, nil) != 0 {
-		mask = make([]byte, n/ptrSize)
-		for i := uintptr(0); i < n; i += ptrSize {
+		mask = make([]byte, n/sys.PtrSize)
+		for i := uintptr(0); i < n; i += sys.PtrSize {
 			hbits := heapBitsForAddr(base + i)
 			if hbits.isPointer() {
-				mask[i/ptrSize] = 1
+				mask[i/sys.PtrSize] = 1
 			}
-			if i >= 2*ptrSize && !hbits.isMarked() {
-				mask = mask[:i/ptrSize]
+			if i >= 2*sys.PtrSize && !hbits.isMarked() {
+				mask = mask[:i/sys.PtrSize]
 				break
 			}
 		}
@@ -1682,7 +1700,7 @@ func getgcmask(ep interface{}) (mask []byte) {
 			if targetpc != f.entry {
 				targetpc--
 			}
-			pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc)
+			pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, nil)
 			if pcdata == -1 {
 				return
 			}
@@ -1691,13 +1709,13 @@ func getgcmask(ep interface{}) (mask []byte) {
 				return
 			}
 			bv := stackmapdata(stkmap, pcdata)
-			size := uintptr(bv.n) * ptrSize
+			size := uintptr(bv.n) * sys.PtrSize
 			n := (*ptrtype)(unsafe.Pointer(t)).elem.size
-			mask = make([]byte, n/ptrSize)
-			for i := uintptr(0); i < n; i += ptrSize {
+			mask = make([]byte, n/sys.PtrSize)
+			for i := uintptr(0); i < n; i += sys.PtrSize {
 				bitmap := bv.bytedata
-				off := (uintptr(p) + i - frame.varp + size) / ptrSize
-				mask[i/ptrSize] = (*addb(bitmap, off/8) >> (off % 8)) & 1
+				off := (uintptr(p) + i - frame.varp + size) / sys.PtrSize
+				mask[i/sys.PtrSize] = (*addb(bitmap, off/8) >> (off % 8)) & 1
 			}
 		}
 		return
diff --git a/src/runtime/mcache.go b/src/runtime/mcache.go
index 8c2a6b0..b06d354 100644
--- a/src/runtime/mcache.go
+++ b/src/runtime/mcache.go
@@ -8,15 +8,25 @@ import "unsafe"
 
 // Per-thread (in Go, per-P) cache for small objects.
 // No locking needed because it is per-thread (per-P).
+//
+// mcaches are allocated from non-GC'd memory, so any heap pointers
+// must be specially handled.
 type mcache struct {
 	// The following members are accessed on every malloc,
 	// so they are grouped here for better caching.
-	next_sample      int32   // trigger heap sample after allocating this many bytes
-	local_cachealloc uintptr // bytes allocated from cache since last lock of heap
-	local_scan       uintptr // bytes of scannable heap allocated
+	next_sample int32   // trigger heap sample after allocating this many bytes
+	local_scan  uintptr // bytes of scannable heap allocated
+
 	// Allocator cache for tiny objects w/o pointers.
 	// See "Tiny allocator" comment in malloc.go.
-	tiny             unsafe.Pointer
+
+	// tiny points to the beginning of the current tiny block, or
+	// nil if there is no current tiny block.
+	//
+	// tiny is a heap pointer. Since mcache is in non-GC'd memory,
+	// we handle it by clearing it in releaseAll during mark
+	// termination.
+	tiny             uintptr
 	tinyoffset       uintptr
 	local_tinyallocs uintptr // number of tiny allocs not counted in other stats
 
@@ -63,28 +73,19 @@ var emptymspan mspan
 
 func allocmcache() *mcache {
 	lock(&mheap_.lock)
-	c := (*mcache)(fixAlloc_Alloc(&mheap_.cachealloc))
+	c := (*mcache)(mheap_.cachealloc.alloc())
 	unlock(&mheap_.lock)
 	memclr(unsafe.Pointer(c), unsafe.Sizeof(*c))
 	for i := 0; i < _NumSizeClasses; i++ {
 		c.alloc[i] = &emptymspan
 	}
-
-	// Set first allocation sample size.
-	rate := MemProfileRate
-	if rate > 0x3fffffff { // make 2*rate not overflow
-		rate = 0x3fffffff
-	}
-	if rate != 0 {
-		c.next_sample = int32(int(fastrand1()) % (2 * rate))
-	}
-
+	c.next_sample = nextSample()
 	return c
 }
 
 func freemcache(c *mcache) {
 	systemstack(func() {
-		mCache_ReleaseAll(c)
+		c.releaseAll()
 		stackcache_clear(c)
 
 		// NOTE(rsc,rlh): If gcworkbuffree comes back, we need to coordinate
@@ -94,14 +95,14 @@ func freemcache(c *mcache) {
 
 		lock(&mheap_.lock)
 		purgecachedstats(c)
-		fixAlloc_Free(&mheap_.cachealloc, unsafe.Pointer(c))
+		mheap_.cachealloc.free(unsafe.Pointer(c))
 		unlock(&mheap_.lock)
 	})
 }
 
 // Gets a span that has a free object in it and assigns it
 // to be the cached span for the given sizeclass.  Returns this span.
-func mCache_Refill(c *mcache, sizeclass int32) *mspan {
+func (c *mcache) refill(sizeclass int32) *mspan {
 	_g_ := getg()
 
 	_g_.m.locks++
@@ -115,7 +116,7 @@ func mCache_Refill(c *mcache, sizeclass int32) *mspan {
 	}
 
 	// Get a new cached span from the central lists.
-	s = mCentral_CacheSpan(&mheap_.central[sizeclass].mcentral)
+	s = mheap_.central[sizeclass].mcentral.cacheSpan()
 	if s == nil {
 		throw("out of memory")
 	}
@@ -128,12 +129,15 @@ func mCache_Refill(c *mcache, sizeclass int32) *mspan {
 	return s
 }
 
-func mCache_ReleaseAll(c *mcache) {
+func (c *mcache) releaseAll() {
 	for i := 0; i < _NumSizeClasses; i++ {
 		s := c.alloc[i]
 		if s != &emptymspan {
-			mCentral_UncacheSpan(&mheap_.central[i].mcentral, s)
+			mheap_.central[i].mcentral.uncacheSpan(s)
 			c.alloc[i] = &emptymspan
 		}
 	}
+	// Clear tinyalloc pool.
+	c.tiny = 0
+	c.tinyoffset = 0
 }
diff --git a/src/runtime/mcentral.go b/src/runtime/mcentral.go
index 161af99..29a7b77 100644
--- a/src/runtime/mcentral.go
+++ b/src/runtime/mcentral.go
@@ -12,36 +12,39 @@
 
 package runtime
 
+import "runtime/internal/atomic"
+
 // Central list of free objects of a given size.
 type mcentral struct {
 	lock      mutex
 	sizeclass int32
-	nonempty  mspan // list of spans with a free object
-	empty     mspan // list of spans with no free objects (or cached in an mcache)
+	nonempty  mSpanList // list of spans with a free object
+	empty     mSpanList // list of spans with no free objects (or cached in an mcache)
 }
 
 // Initialize a single central free list.
-func mCentral_Init(c *mcentral, sizeclass int32) {
+func (c *mcentral) init(sizeclass int32) {
 	c.sizeclass = sizeclass
-	mSpanList_Init(&c.nonempty)
-	mSpanList_Init(&c.empty)
+	c.nonempty.init()
+	c.empty.init()
 }
 
 // Allocate a span to use in an MCache.
-func mCentral_CacheSpan(c *mcentral) *mspan {
+func (c *mcentral) cacheSpan() *mspan {
 	// Deduct credit for this span allocation and sweep if necessary.
-	deductSweepCredit(uintptr(class_to_size[c.sizeclass]), 0)
+	spanBytes := uintptr(class_to_allocnpages[c.sizeclass]) * _PageSize
+	deductSweepCredit(spanBytes, 0)
 
 	lock(&c.lock)
 	sg := mheap_.sweepgen
 retry:
 	var s *mspan
-	for s = c.nonempty.next; s != &c.nonempty; s = s.next {
-		if s.sweepgen == sg-2 && cas(&s.sweepgen, sg-2, sg-1) {
-			mSpanList_Remove(s)
-			mSpanList_InsertBack(&c.empty, s)
+	for s = c.nonempty.first; s != nil; s = s.next {
+		if s.sweepgen == sg-2 && atomic.Cas(&s.sweepgen, sg-2, sg-1) {
+			c.nonempty.remove(s)
+			c.empty.insertBack(s)
 			unlock(&c.lock)
-			mSpan_Sweep(s, true)
+			s.sweep(true)
 			goto havespan
 		}
 		if s.sweepgen == sg-1 {
@@ -49,21 +52,21 @@ retry:
 			continue
 		}
 		// we have a nonempty span that does not require sweeping, allocate from it
-		mSpanList_Remove(s)
-		mSpanList_InsertBack(&c.empty, s)
+		c.nonempty.remove(s)
+		c.empty.insertBack(s)
 		unlock(&c.lock)
 		goto havespan
 	}
 
-	for s = c.empty.next; s != &c.empty; s = s.next {
-		if s.sweepgen == sg-2 && cas(&s.sweepgen, sg-2, sg-1) {
+	for s = c.empty.first; s != nil; s = s.next {
+		if s.sweepgen == sg-2 && atomic.Cas(&s.sweepgen, sg-2, sg-1) {
 			// we have an empty span that requires sweeping,
 			// sweep it and see if we can free some space in it
-			mSpanList_Remove(s)
+			c.empty.remove(s)
 			// swept spans are at the end of the list
-			mSpanList_InsertBack(&c.empty, s)
+			c.empty.insertBack(s)
 			unlock(&c.lock)
-			mSpan_Sweep(s, true)
+			s.sweep(true)
 			if s.freelist.ptr() != nil {
 				goto havespan
 			}
@@ -83,12 +86,12 @@ retry:
 	unlock(&c.lock)
 
 	// Replenish central list if empty.
-	s = mCentral_Grow(c)
+	s = c.grow()
 	if s == nil {
 		return nil
 	}
 	lock(&c.lock)
-	mSpanList_InsertBack(&c.empty, s)
+	c.empty.insertBack(s)
 	unlock(&c.lock)
 
 	// At this point s is a non-empty span, queued at the end of the empty list,
@@ -99,6 +102,19 @@ havespan:
 	if n == 0 {
 		throw("empty span")
 	}
+	usedBytes := uintptr(s.ref) * s.elemsize
+	if usedBytes > 0 {
+		reimburseSweepCredit(usedBytes)
+	}
+	atomic.Xadd64(&memstats.heap_live, int64(spanBytes)-int64(usedBytes))
+	if trace.enabled {
+		// heap_live changed.
+		traceHeapAlloc()
+	}
+	if gcBlackenEnabled != 0 {
+		// heap_live changed.
+		gcController.revise()
+	}
 	if s.freelist.ptr() == nil {
 		throw("freelist empty")
 	}
@@ -107,7 +123,7 @@ havespan:
 }
 
 // Return span from an MCache.
-func mCentral_UncacheSpan(c *mcentral, s *mspan) {
+func (c *mcentral) uncacheSpan(s *mspan) {
 	lock(&c.lock)
 
 	s.incache = false
@@ -119,8 +135,11 @@ func mCentral_UncacheSpan(c *mcentral, s *mspan) {
 	cap := int32((s.npages << _PageShift) / s.elemsize)
 	n := cap - int32(s.ref)
 	if n > 0 {
-		mSpanList_Remove(s)
-		mSpanList_Insert(&c.nonempty, s)
+		c.empty.remove(s)
+		c.nonempty.insert(s)
+		// mCentral_CacheSpan conservatively counted
+		// unallocated slots in heap_live. Undo this.
+		atomic.Xadd64(&memstats.heap_live, -int64(n)*int64(s.elemsize))
 	}
 	unlock(&c.lock)
 }
@@ -131,7 +150,7 @@ func mCentral_UncacheSpan(c *mcentral, s *mspan) {
 // the latest generation.
 // If preserve=true, don't return the span to heap nor relink in MCentral lists;
 // caller takes care of it.
-func mCentral_FreeSpan(c *mcentral, s *mspan, n int32, start gclinkptr, end gclinkptr, preserve bool) bool {
+func (c *mcentral) freeSpan(s *mspan, n int32, start gclinkptr, end gclinkptr, preserve bool) bool {
 	if s.incache {
 		throw("freespan into cached span")
 	}
@@ -145,10 +164,10 @@ func mCentral_FreeSpan(c *mcentral, s *mspan, n int32, start gclinkptr, end gcli
 	if preserve {
 		// preserve is set only when called from MCentral_CacheSpan above,
 		// the span must be in the empty list.
-		if s.next == nil {
+		if !s.inList() {
 			throw("can't preserve unlinked span")
 		}
-		atomicstore(&s.sweepgen, mheap_.sweepgen)
+		atomic.Store(&s.sweepgen, mheap_.sweepgen)
 		return false
 	}
 
@@ -156,15 +175,15 @@ func mCentral_FreeSpan(c *mcentral, s *mspan, n int32, start gclinkptr, end gcli
 
 	// Move to nonempty if necessary.
 	if wasempty {
-		mSpanList_Remove(s)
-		mSpanList_Insert(&c.nonempty, s)
+		c.empty.remove(s)
+		c.nonempty.insert(s)
 	}
 
 	// delay updating sweepgen until here.  This is the signal that
 	// the span may be used in an MCache, so it must come after the
 	// linked list operations above (actually, just after the
 	// lock of c above.)
-	atomicstore(&s.sweepgen, mheap_.sweepgen)
+	atomic.Store(&s.sweepgen, mheap_.sweepgen)
 
 	if s.ref != 0 {
 		unlock(&c.lock)
@@ -172,22 +191,22 @@ func mCentral_FreeSpan(c *mcentral, s *mspan, n int32, start gclinkptr, end gcli
 	}
 
 	// s is completely freed, return it to the heap.
-	mSpanList_Remove(s)
+	c.nonempty.remove(s)
 	s.needzero = 1
 	s.freelist = 0
 	unlock(&c.lock)
 	heapBitsForSpan(s.base()).initSpan(s.layout())
-	mHeap_Free(&mheap_, s, 0)
+	mheap_.freeSpan(s, 0)
 	return true
 }
 
 // Fetch a new span from the heap and carve into objects for the free list.
-func mCentral_Grow(c *mcentral) *mspan {
+func (c *mcentral) grow() *mspan {
 	npages := uintptr(class_to_allocnpages[c.sizeclass])
 	size := uintptr(class_to_size[c.sizeclass])
 	n := (npages << _PageShift) / size
 
-	s := mHeap_Alloc(&mheap_, npages, c.sizeclass, false, true)
+	s := mheap_.alloc(npages, c.sizeclass, false, true)
 	if s == nil {
 		return nil
 	}
diff --git a/src/runtime/mem_bsd.go b/src/runtime/mem_bsd.go
index ecab584..c3fe610 100644
--- a/src/runtime/mem_bsd.go
+++ b/src/runtime/mem_bsd.go
@@ -6,7 +6,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 // Don't split the stack as this function may be invoked without a valid G,
 // which prevents us from allocating more stack.
@@ -43,7 +46,7 @@ func sysReserve(v unsafe.Pointer, n uintptr, reserved *bool) unsafe.Pointer {
 	// On 64-bit, people with ulimit -v set complain if we reserve too
 	// much address space.  Instead, assume that the reservation is okay
 	// and check the assumption in SysMap.
-	if ptrSize == 8 && uint64(n) > 1<<32 || goos_nacl != 0 {
+	if sys.PtrSize == 8 && uint64(n) > 1<<32 || sys.GoosNacl != 0 {
 		*reserved = false
 		return v
 	}
@@ -56,9 +59,9 @@ func sysReserve(v unsafe.Pointer, n uintptr, reserved *bool) unsafe.Pointer {
 	return p
 }
 
-func sysMap(v unsafe.Pointer, n uintptr, reserved bool, sysStat *uint64) {
-	const _ENOMEM = 12
+const _ENOMEM = 12
 
+func sysMap(v unsafe.Pointer, n uintptr, reserved bool, sysStat *uint64) {
 	mSysStatInc(sysStat, n)
 
 	// On 64-bit, we don't actually have v reserved, so tread carefully.
diff --git a/src/runtime/mem_darwin.go b/src/runtime/mem_darwin.go
index 3bebd97..65b1b48 100644
--- a/src/runtime/mem_darwin.go
+++ b/src/runtime/mem_darwin.go
@@ -10,7 +10,7 @@ import "unsafe"
 // which prevents us from allocating more stack.
 //go:nosplit
 func sysAlloc(n uintptr, sysStat *uint64) unsafe.Pointer {
-	v := (unsafe.Pointer)(mmap(nil, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_PRIVATE, -1, 0))
+	v := unsafe.Pointer(mmap(nil, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_PRIVATE, -1, 0))
 	if uintptr(v) < 4096 {
 		return nil
 	}
@@ -40,7 +40,7 @@ func sysFault(v unsafe.Pointer, n uintptr) {
 
 func sysReserve(v unsafe.Pointer, n uintptr, reserved *bool) unsafe.Pointer {
 	*reserved = true
-	p := (unsafe.Pointer)(mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE, -1, 0))
+	p := unsafe.Pointer(mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE, -1, 0))
 	if uintptr(p) < 4096 {
 		return nil
 	}
@@ -53,7 +53,7 @@ const (
 
 func sysMap(v unsafe.Pointer, n uintptr, reserved bool, sysStat *uint64) {
 	mSysStatInc(sysStat, n)
-	p := (unsafe.Pointer)(mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0))
+	p := unsafe.Pointer(mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0))
 	if uintptr(p) == _ENOMEM {
 		throw("runtime: out of memory")
 	}
diff --git a/src/runtime/mem_linux.go b/src/runtime/mem_linux.go
index e8c8999..330504b 100644
--- a/src/runtime/mem_linux.go
+++ b/src/runtime/mem_linux.go
@@ -4,10 +4,13 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 const (
-	_PAGE_SIZE = _PhysPageSize
+	_PAGE_SIZE = sys.PhysPageSize
 	_EACCES    = 13
 )
 
@@ -94,8 +97,8 @@ func sysUnused(v unsafe.Pointer, n uintptr) {
 	// gets most of the benefit of huge pages while keeping the
 	// number of VMAs under control. With hugePageSize = 2MB, even
 	// a pessimal heap can reach 128GB before running out of VMAs.
-	if hugePageSize != 0 {
-		var s uintptr = hugePageSize // division by constant 0 is a compile-time error :(
+	if sys.HugePageSize != 0 {
+		var s uintptr = sys.HugePageSize // division by constant 0 is a compile-time error :(
 
 		// If it's a large allocation, we want to leave huge
 		// pages enabled. Hence, we only adjust the huge page
@@ -114,17 +117,17 @@ func sysUnused(v unsafe.Pointer, n uintptr) {
 		// Note that madvise will return EINVAL if the flag is
 		// already set, which is quite likely. We ignore
 		// errors.
-		if head != 0 && head+hugePageSize == tail {
+		if head != 0 && head+sys.HugePageSize == tail {
 			// head and tail are different but adjacent,
 			// so do this in one call.
-			madvise(unsafe.Pointer(head), 2*hugePageSize, _MADV_NOHUGEPAGE)
+			madvise(unsafe.Pointer(head), 2*sys.HugePageSize, _MADV_NOHUGEPAGE)
 		} else {
 			// Advise the huge pages containing v and v+n-1.
 			if head != 0 {
-				madvise(unsafe.Pointer(head), hugePageSize, _MADV_NOHUGEPAGE)
+				madvise(unsafe.Pointer(head), sys.HugePageSize, _MADV_NOHUGEPAGE)
 			}
 			if tail != 0 && tail != head {
-				madvise(unsafe.Pointer(tail), hugePageSize, _MADV_NOHUGEPAGE)
+				madvise(unsafe.Pointer(tail), sys.HugePageSize, _MADV_NOHUGEPAGE)
 			}
 		}
 	}
@@ -133,7 +136,7 @@ func sysUnused(v unsafe.Pointer, n uintptr) {
 }
 
 func sysUsed(v unsafe.Pointer, n uintptr) {
-	if hugePageSize != 0 {
+	if sys.HugePageSize != 0 {
 		// Partially undo the NOHUGEPAGE marks from sysUnused
 		// for whole huge pages between v and v+n. This may
 		// leave huge pages off at the end points v and v+n
@@ -142,7 +145,7 @@ func sysUsed(v unsafe.Pointer, n uintptr) {
 		// the end points as well, but it's probably not worth
 		// the cost because when neighboring allocations are
 		// freed sysUnused will just set NOHUGEPAGE again.
-		var s uintptr = hugePageSize
+		var s uintptr = sys.HugePageSize
 
 		// Round v up to a huge page boundary.
 		beg := (uintptr(v) + (s - 1)) &^ (s - 1)
@@ -172,7 +175,7 @@ func sysReserve(v unsafe.Pointer, n uintptr, reserved *bool) unsafe.Pointer {
 	// much address space.  Instead, assume that the reservation is okay
 	// if we can reserve at least 64K and check the assumption in SysMap.
 	// Only user-mode Linux (UML) rejects these requests.
-	if ptrSize == 8 && uint64(n) > 1<<32 {
+	if sys.PtrSize == 8 && uint64(n) > 1<<32 {
 		p := mmap_fixed(v, 64<<10, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE, -1, 0)
 		if p != v {
 			if uintptr(p) >= 4096 {
diff --git a/src/runtime/mem_plan9.go b/src/runtime/mem_plan9.go
index 755887f..cf9e99c 100644
--- a/src/runtime/mem_plan9.go
+++ b/src/runtime/mem_plan9.go
@@ -12,16 +12,21 @@ var bloc uintptr
 var memlock mutex
 
 type memHdr struct {
-	next *memHdr
+	next memHdrPtr
 	size uintptr
 }
 
-var memFreelist *memHdr // sorted in ascending order
+var memFreelist memHdrPtr // sorted in ascending order
+
+type memHdrPtr uintptr
+
+func (p memHdrPtr) ptr() *memHdr   { return (*memHdr)(unsafe.Pointer(p)) }
+func (p *memHdrPtr) set(x *memHdr) { *p = memHdrPtr(unsafe.Pointer(x)) }
 
 func memAlloc(n uintptr) unsafe.Pointer {
 	n = memRound(n)
 	var prevp *memHdr
-	for p := memFreelist; p != nil; p = p.next {
+	for p := memFreelist.ptr(); p != nil; p = p.next.ptr() {
 		if p.size >= n {
 			if p.size == n {
 				if prevp != nil {
@@ -47,31 +52,31 @@ func memFree(ap unsafe.Pointer, n uintptr) {
 	bp := (*memHdr)(ap)
 	bp.size = n
 	bpn := uintptr(ap)
-	if memFreelist == nil {
-		bp.next = nil
-		memFreelist = bp
+	if memFreelist == 0 {
+		bp.next = 0
+		memFreelist.set(bp)
 		return
 	}
-	p := memFreelist
+	p := memFreelist.ptr()
 	if bpn < uintptr(unsafe.Pointer(p)) {
-		memFreelist = bp
+		memFreelist.set(bp)
 		if bpn+bp.size == uintptr(unsafe.Pointer(p)) {
 			bp.size += p.size
 			bp.next = p.next
 			memclr(unsafe.Pointer(p), unsafe.Sizeof(memHdr{}))
 		} else {
-			bp.next = p
+			bp.next.set(p)
 		}
 		return
 	}
-	for ; p.next != nil; p = p.next {
+	for ; p.next != 0; p = p.next.ptr() {
 		if bpn > uintptr(unsafe.Pointer(p)) && bpn < uintptr(unsafe.Pointer(p.next)) {
 			break
 		}
 	}
 	if bpn+bp.size == uintptr(unsafe.Pointer(p.next)) {
-		bp.size += p.next.size
-		bp.next = p.next.next
+		bp.size += p.next.ptr().size
+		bp.next = p.next.ptr().next
 		memclr(unsafe.Pointer(p.next), unsafe.Sizeof(memHdr{}))
 	} else {
 		bp.next = p.next
@@ -81,7 +86,7 @@ func memFree(ap unsafe.Pointer, n uintptr) {
 		p.next = bp.next
 		memclr(unsafe.Pointer(bp), unsafe.Sizeof(memHdr{}))
 	} else {
-		p.next = bp
+		p.next.set(bp)
 	}
 }
 
@@ -89,7 +94,7 @@ func memCheck() {
 	if memDebug == false {
 		return
 	}
-	for p := memFreelist; p != nil && p.next != nil; p = p.next {
+	for p := memFreelist.ptr(); p != nil && p.next != 0; p = p.next.ptr() {
 		if uintptr(unsafe.Pointer(p)) == uintptr(unsafe.Pointer(p.next)) {
 			print("runtime: ", unsafe.Pointer(p), " == ", unsafe.Pointer(p.next), "\n")
 			throw("mem: infinite loop")
diff --git a/src/runtime/mem_windows.go b/src/runtime/mem_windows.go
index 42aa7fb..71be0e6 100644
--- a/src/runtime/mem_windows.go
+++ b/src/runtime/mem_windows.go
@@ -48,6 +48,7 @@ func sysUnused(v unsafe.Pointer, n uintptr) {
 			small &^= 4096 - 1
 		}
 		if small < 4096 {
+			print("runtime: VirtualFree of ", small, " bytes failed with errno=", getlasterror(), "\n")
 			throw("runtime: failed to decommit pages")
 		}
 		v = add(v, small)
@@ -57,8 +58,8 @@ func sysUnused(v unsafe.Pointer, n uintptr) {
 
 func sysUsed(v unsafe.Pointer, n uintptr) {
 	r := stdcall4(_VirtualAlloc, uintptr(v), n, _MEM_COMMIT, _PAGE_READWRITE)
-	if r != uintptr(v) {
-		throw("runtime: failed to commit pages")
+	if r == uintptr(v) {
+		return
 	}
 
 	// Commit failed. See SysUnused.
@@ -69,7 +70,8 @@ func sysUsed(v unsafe.Pointer, n uintptr) {
 			small &^= 4096 - 1
 		}
 		if small < 4096 {
-			throw("runtime: failed to decommit pages")
+			print("runtime: VirtualAlloc of ", small, " bytes failed with errno=", getlasterror(), "\n")
+			throw("runtime: failed to commit pages")
 		}
 		v = add(v, small)
 		n -= small
@@ -83,6 +85,7 @@ func sysFree(v unsafe.Pointer, n uintptr, sysStat *uint64) {
 	mSysStatDec(sysStat, n)
 	r := stdcall3(_VirtualFree, uintptr(v), 0, _MEM_RELEASE)
 	if r == 0 {
+		print("runtime: VirtualFree of ", n, " bytes failed with errno=", getlasterror(), "\n")
 		throw("runtime: failed to release pages")
 	}
 }
@@ -109,6 +112,7 @@ func sysMap(v unsafe.Pointer, n uintptr, reserved bool, sysStat *uint64) {
 	mSysStatInc(sysStat, n)
 	p := stdcall4(_VirtualAlloc, uintptr(v), n, _MEM_COMMIT, _PAGE_READWRITE)
 	if p != uintptr(v) {
+		print("runtime: VirtualAlloc of ", n, " bytes failed with errno=", getlasterror(), "\n")
 		throw("runtime: cannot map pages in arena address space")
 	}
 }
diff --git a/src/runtime/memclr_amd64.s b/src/runtime/memclr_amd64.s
index 3e2c4b2..c257d59 100644
--- a/src/runtime/memclr_amd64.s
+++ b/src/runtime/memclr_amd64.s
@@ -36,8 +36,10 @@ tail:
 	JBE	_65through128
 	CMPQ	BX, $256
 	JBE	_129through256
+	CMPB	runtime·support_avx2(SB), $1
+	JE loop_preheader_avx2
 	// TODO: use branch table and BSR to make this just a single dispatch
-	// TODO: for really big clears, use MOVNTDQ.
+	// TODO: for really big clears, use MOVNTDQ, even without AVX2.
 
 loop:
 	MOVOU	X0, 0(DI)
@@ -62,6 +64,57 @@ loop:
 	JAE	loop
 	JMP	tail
 
+loop_preheader_avx2:
+	VPXOR Y0, Y0, Y0
+	// For smaller sizes MOVNTDQ may be faster or slower depending on hardware.
+	// For larger sizes it is always faster, even on dual Xeons with 30M cache.
+	// TODO take into account actual LLC size. E. g. glibc uses LLC size/2.
+	CMPQ    BX, $0x2000000
+	JAE     loop_preheader_avx2_huge
+loop_avx2:
+	VMOVDQU	Y0, 0(DI)
+	VMOVDQU	Y0, 32(DI)
+	VMOVDQU	Y0, 64(DI)
+	VMOVDQU	Y0, 96(DI)
+	SUBQ	$128, BX
+	ADDQ	$128, DI
+	CMPQ	BX, $128
+	JAE	loop_avx2
+	VMOVDQU  Y0, -32(DI)(BX*1)
+	VMOVDQU  Y0, -64(DI)(BX*1)
+	VMOVDQU  Y0, -96(DI)(BX*1)
+	VMOVDQU  Y0, -128(DI)(BX*1)
+	VZEROUPPER
+	RET
+loop_preheader_avx2_huge:
+	// Align to 32 byte boundary
+	VMOVDQU  Y0, 0(DI)
+	MOVQ	DI, SI
+	ADDQ	$32, DI
+	ANDQ	$~31, DI
+	SUBQ	DI, SI
+	ADDQ	SI, BX
+loop_avx2_huge:
+	VMOVNTDQ	Y0, 0(DI)
+	VMOVNTDQ	Y0, 32(DI)
+	VMOVNTDQ	Y0, 64(DI)
+	VMOVNTDQ	Y0, 96(DI)
+	SUBQ	$128, BX
+	ADDQ	$128, DI
+	CMPQ	BX, $128
+	JAE	loop_avx2_huge
+	// In the desciption of MOVNTDQ in [1]
+	// "... fencing operation implemented with the SFENCE or MFENCE instruction
+	// should be used in conjunction with MOVNTDQ instructions..."
+	// [1] 64-ia-32-architectures-software-developer-manual-325462.pdf
+	SFENCE
+	VMOVDQU  Y0, -32(DI)(BX*1)
+	VMOVDQU  Y0, -64(DI)(BX*1)
+	VMOVDQU  Y0, -96(DI)(BX*1)
+	VMOVDQU  Y0, -128(DI)(BX*1)
+	VZEROUPPER
+	RET
+
 _1or2:
 	MOVB	AX, (DI)
 	MOVB	AX, -1(DI)(BX*1)
diff --git a/src/runtime/memclr_mips64x.s b/src/runtime/memclr_mips64x.s
new file mode 100644
index 0000000..30a4af3
--- /dev/null
+++ b/src/runtime/memclr_mips64x.s
@@ -0,0 +1,42 @@
+// Copyright 2015 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.
+
+// +build mips64 mips64le
+
+#include "textflag.h"
+
+// void runtime·memclr(void*, uintptr)
+TEXT runtime·memclr(SB),NOSPLIT,$0-16
+	MOVV	ptr+0(FP), R1
+	MOVV	n+8(FP), R2
+	ADDV	R1, R2, R4
+
+	// if less than 8 bytes, do one byte at a time
+	SGTU	$8, R2, R3
+	BNE	R3, out
+
+	// do one byte at a time until 8-aligned
+	AND	$7, R1, R3
+	BEQ	R3, words
+	MOVB	R0, (R1)
+	ADDV	$1, R1
+	JMP	-4(PC)
+
+words:
+	// do 8 bytes at a time if there is room
+	ADDV	$-7, R4, R2
+
+	SGTU	R2, R1, R3
+	BEQ	R3, out
+	MOVV	R0, (R1)
+	ADDV	$8, R1
+	JMP	-4(PC)
+
+out:
+	BEQ	R1, R4, done
+	MOVB	R0, (R1)
+	ADDV	$1, R1
+	JMP	-3(PC)
+done:
+	RET
diff --git a/src/runtime/memclr_ppc64x.s b/src/runtime/memclr_ppc64x.s
index 90e2748..442faa2 100644
--- a/src/runtime/memclr_ppc64x.s
+++ b/src/runtime/memclr_ppc64x.s
@@ -7,7 +7,7 @@
 #include "textflag.h"
 
 // void runtime·memclr(void*, uintptr)
-TEXT runtime·memclr(SB),NOSPLIT,$0-16
+TEXT runtime·memclr(SB),NOSPLIT|NOFRAME,$0-16
 	MOVD	ptr+0(FP), R3
 	MOVD	n+8(FP), R4
 	SRADCC	$3, R4, R6	// R6 is the number of words to zero
diff --git a/src/runtime/memmove_mips64x.s b/src/runtime/memmove_mips64x.s
new file mode 100644
index 0000000..f0f6852
--- /dev/null
+++ b/src/runtime/memmove_mips64x.s
@@ -0,0 +1,105 @@
+// Copyright 2015 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.
+
+// +build mips64 mips64le
+
+#include "textflag.h"
+
+// void runtime·memmove(void*, void*, uintptr)
+TEXT runtime·memmove(SB), NOSPLIT, $-8-24
+	MOVV	to+0(FP), R1
+	MOVV	from+8(FP), R2
+	MOVV	n+16(FP), R3
+	BNE	R3, check
+	RET
+
+check:
+	SGTU	R1, R2, R4
+	BNE	R4, backward
+
+	ADDV	R1, R3, R6 // end pointer
+
+	// if the two pointers are not of same alignments, do byte copying
+	SUBVU	R2, R1, R4
+	AND	$7, R4
+	BNE	R4, out
+
+	// if less than 8 bytes, do byte copying
+	SGTU	$8, R3, R4
+	BNE	R4, out
+
+	// do one byte at a time until 8-aligned
+	AND	$7, R1, R5
+	BEQ	R5, words
+	MOVB	(R2), R4
+	ADDV	$1, R2
+	MOVB	R4, (R1)
+	ADDV	$1, R1
+	JMP	-6(PC)
+
+words:
+	// do 8 bytes at a time if there is room
+	ADDV	$-7, R6, R3 // R3 is end pointer-7
+
+	SGTU	R3, R1, R5
+	BEQ	R5, out
+	MOVV	(R2), R4
+	ADDV	$8, R2
+	MOVV	R4, (R1)
+	ADDV	$8, R1
+	JMP	-6(PC)
+
+out:
+	BEQ	R1, R6, done
+	MOVB	(R2), R4
+	ADDV	$1, R2
+	MOVB	R4, (R1)
+	ADDV	$1, R1
+	JMP	-5(PC)
+done:
+	RET
+
+backward:
+	ADDV	R3, R2 // from-end pointer
+	ADDV	R1, R3, R6 // to-end pointer
+
+	// if the two pointers are not of same alignments, do byte copying
+	SUBVU	R6, R2, R4
+	AND	$7, R4
+	BNE	R4, out1
+
+	// if less than 8 bytes, do byte copying
+	SGTU	$8, R3, R4
+	BNE	R4, out1
+
+	// do one byte at a time until 8-aligned
+	AND	$7, R6, R5
+	BEQ	R5, words1
+	ADDV	$-1, R2
+	MOVB	(R2), R4
+	ADDV	$-1, R6
+	MOVB	R4, (R6)
+	JMP	-6(PC)
+
+words1:
+	// do 8 bytes at a time if there is room
+	ADDV	$7, R1, R3 // R3 is start pointer+7
+
+	SGTU	R6, R3, R5
+	BEQ	R5, out1
+	ADDV	$-8, R2
+	MOVV	(R2), R4
+	ADDV	$-8, R6
+	MOVV	R4, (R6)
+	JMP	-6(PC)
+
+out1:
+	BEQ	R1, R6, done1
+	ADDV	$-1, R2
+	MOVB	(R2), R4
+	ADDV	$-1, R6
+	MOVB	R4, (R6)
+	JMP	-5(PC)
+done1:
+	RET
diff --git a/src/runtime/memmove_ppc64x.s b/src/runtime/memmove_ppc64x.s
index 72c90de..b6d0b85 100644
--- a/src/runtime/memmove_ppc64x.s
+++ b/src/runtime/memmove_ppc64x.s
@@ -7,7 +7,7 @@
 #include "textflag.h"
 
 // void runtime·memmove(void*, void*, uintptr)
-TEXT runtime·memmove(SB), NOSPLIT, $-8-24
+TEXT runtime·memmove(SB), NOSPLIT|NOFRAME, $0-24
 	MOVD	to+0(FP), R3
 	MOVD	from+8(FP), R4
 	MOVD	n+16(FP), R5
diff --git a/src/runtime/memmove_test.go b/src/runtime/memmove_test.go
index d5a2ad8..7f9d3f1 100644
--- a/src/runtime/memmove_test.go
+++ b/src/runtime/memmove_test.go
@@ -196,6 +196,11 @@ func BenchmarkMemclr64(b *testing.B)    { bmMemclr(b, 64) }
 func BenchmarkMemclr256(b *testing.B)   { bmMemclr(b, 256) }
 func BenchmarkMemclr4096(b *testing.B)  { bmMemclr(b, 4096) }
 func BenchmarkMemclr65536(b *testing.B) { bmMemclr(b, 65536) }
+func BenchmarkMemclr1M(b *testing.B)    { bmMemclr(b, 1<<20) }
+func BenchmarkMemclr4M(b *testing.B)    { bmMemclr(b, 4<<20) }
+func BenchmarkMemclr8M(b *testing.B)    { bmMemclr(b, 8<<20) }
+func BenchmarkMemclr16M(b *testing.B)   { bmMemclr(b, 16<<20) }
+func BenchmarkMemclr64M(b *testing.B)   { bmMemclr(b, 64<<20) }
 
 func bmGoMemclr(b *testing.B, n int) {
 	x := make([]byte, n)
diff --git a/src/runtime/mfinal.go b/src/runtime/mfinal.go
index 7e1773c..512edef 100644
--- a/src/runtime/mfinal.go
+++ b/src/runtime/mfinal.go
@@ -6,21 +6,25 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 type finblock struct {
 	alllink *finblock
 	next    *finblock
 	cnt     int32
 	_       int32
-	fin     [(_FinBlockSize - 2*ptrSize - 2*4) / unsafe.Sizeof(finalizer{})]finalizer
+	fin     [(_FinBlockSize - 2*sys.PtrSize - 2*4) / unsafe.Sizeof(finalizer{})]finalizer
 }
 
 var finlock mutex  // protects the following variables
 var fing *g        // goroutine that runs finalizers
 var finq *finblock // list of finalizers that are to be executed
 var finc *finblock // cache of free blocks
-var finptrmask [_FinBlockSize / ptrSize / 8]byte
+var finptrmask [_FinBlockSize / sys.PtrSize / 8]byte
 var fingwait bool
 var fingwake bool
 var allfin *finblock // list of all blocks
@@ -73,12 +77,12 @@ func queuefinalizer(p unsafe.Pointer, fn *funcval, nret uintptr, fint *_type, ot
 			if finptrmask[0] == 0 {
 				// Build pointer mask for Finalizer array in block.
 				// Check assumptions made in finalizer1 array above.
-				if (unsafe.Sizeof(finalizer{}) != 5*ptrSize ||
+				if (unsafe.Sizeof(finalizer{}) != 5*sys.PtrSize ||
 					unsafe.Offsetof(finalizer{}.fn) != 0 ||
-					unsafe.Offsetof(finalizer{}.arg) != ptrSize ||
-					unsafe.Offsetof(finalizer{}.nret) != 2*ptrSize ||
-					unsafe.Offsetof(finalizer{}.fint) != 3*ptrSize ||
-					unsafe.Offsetof(finalizer{}.ot) != 4*ptrSize) {
+					unsafe.Offsetof(finalizer{}.arg) != sys.PtrSize ||
+					unsafe.Offsetof(finalizer{}.nret) != 2*sys.PtrSize ||
+					unsafe.Offsetof(finalizer{}.fint) != 3*sys.PtrSize ||
+					unsafe.Offsetof(finalizer{}.ot) != 4*sys.PtrSize) {
 					throw("finalizer out of sync")
 				}
 				for i := range finptrmask {
@@ -131,7 +135,7 @@ var (
 
 func createfing() {
 	// start the finalizer goroutine exactly once
-	if fingCreate == 0 && cas(&fingCreate, 0, 1) {
+	if fingCreate == 0 && atomic.Cas(&fingCreate, 0, 1) {
 		go runfinq()
 	}
 }
@@ -160,7 +164,7 @@ func runfinq() {
 		}
 		for fb != nil {
 			for i := fb.cnt; i > 0; i-- {
-				f := (*finalizer)(add(unsafe.Pointer(&fb.fin), uintptr(i-1)*unsafe.Sizeof(finalizer{})))
+				f := &fb.fin[i-1]
 
 				framesz := unsafe.Sizeof((interface{})(nil)) + uintptr(f.nret)
 				if framecap < framesz {
@@ -187,7 +191,7 @@ func runfinq() {
 					if len(ityp.mhdr) != 0 {
 						// convert to interface with methods
 						// this conversion is guaranteed to succeed - we checked in SetFinalizer
-						assertE2I(ityp, *(*interface{})(frame), (*fInterface)(frame))
+						assertE2I(ityp, *(*eface)(frame), (*iface)(frame))
 					}
 				default:
 					throw("bad kind in runfinq")
@@ -264,7 +268,7 @@ func SetFinalizer(obj interface{}, finalizer interface{}) {
 		// (and we don't have the data structures to record them).
 		return
 	}
-	e := (*eface)(unsafe.Pointer(&obj))
+	e := efaceOf(&obj)
 	etyp := e._type
 	if etyp == nil {
 		throw("runtime.SetFinalizer: first argument is nil")
@@ -313,7 +317,7 @@ func SetFinalizer(obj interface{}, finalizer interface{}) {
 		}
 	}
 
-	f := (*eface)(unsafe.Pointer(&finalizer))
+	f := efaceOf(&finalizer)
 	ftyp := f._type
 	if ftyp == nil {
 		// switch to system stack and remove finalizer
@@ -327,11 +331,10 @@ func SetFinalizer(obj interface{}, finalizer interface{}) {
 		throw("runtime.SetFinalizer: second argument is " + *ftyp._string + ", not a function")
 	}
 	ft := (*functype)(unsafe.Pointer(ftyp))
-	ins := *(*[]*_type)(unsafe.Pointer(&ft.in))
-	if ft.dotdotdot || len(ins) != 1 {
+	if ft.dotdotdot || len(ft.in) != 1 {
 		throw("runtime.SetFinalizer: cannot pass " + *etyp._string + " to finalizer " + *ftyp._string)
 	}
-	fint := ins[0]
+	fint := ft.in[0]
 	switch {
 	case fint == etyp:
 		// ok - same type
@@ -348,7 +351,7 @@ func SetFinalizer(obj interface{}, finalizer interface{}) {
 			// ok - satisfies empty interface
 			goto okarg
 		}
-		if assertE2I2(ityp, obj, nil) {
+		if assertE2I2(ityp, *efaceOf(&obj), nil) {
 			goto okarg
 		}
 	}
@@ -356,10 +359,10 @@ func SetFinalizer(obj interface{}, finalizer interface{}) {
 okarg:
 	// compute size needed for return parameters
 	nret := uintptr(0)
-	for _, t := range *(*[]*_type)(unsafe.Pointer(&ft.out)) {
+	for _, t := range ft.out {
 		nret = round(nret, uintptr(t.align)) + uintptr(t.size)
 	}
-	nret = round(nret, ptrSize)
+	nret = round(nret, sys.PtrSize)
 
 	// make sure we have a finalizer goroutine
 	createfing()
@@ -377,7 +380,7 @@ okarg:
 func findObject(v unsafe.Pointer) (s *mspan, x unsafe.Pointer, n uintptr) {
 	c := gomcache()
 	c.local_nlookup++
-	if ptrSize == 4 && c.local_nlookup >= 1<<30 {
+	if sys.PtrSize == 4 && c.local_nlookup >= 1<<30 {
 		// purge cache stats to prevent overflow
 		lock(&mheap_.lock)
 		purgecachedstats(c)
@@ -385,14 +388,14 @@ func findObject(v unsafe.Pointer) (s *mspan, x unsafe.Pointer, n uintptr) {
 	}
 
 	// find span
-	arena_start := uintptr(unsafe.Pointer(mheap_.arena_start))
-	arena_used := uintptr(unsafe.Pointer(mheap_.arena_used))
+	arena_start := mheap_.arena_start
+	arena_used := mheap_.arena_used
 	if uintptr(v) < arena_start || uintptr(v) >= arena_used {
 		return
 	}
 	p := uintptr(v) >> pageShift
 	q := p - arena_start>>pageShift
-	s = *(**mspan)(add(unsafe.Pointer(mheap_.spans), q*ptrSize))
+	s = *(**mspan)(add(unsafe.Pointer(mheap_.spans), q*sys.PtrSize))
 	if s == nil {
 		return
 	}
diff --git a/src/runtime/mfixalloc.go b/src/runtime/mfixalloc.go
index bb2f4e7..8653a6a 100644
--- a/src/runtime/mfixalloc.go
+++ b/src/runtime/mfixalloc.go
@@ -20,10 +20,10 @@ import "unsafe"
 // smashed by freeing and reallocating.
 type fixalloc struct {
 	size   uintptr
-	first  unsafe.Pointer // go func(unsafe.pointer, unsafe.pointer); f(arg, p) called first time p is returned
+	first  func(arg, p unsafe.Pointer) // called first time p is returned
 	arg    unsafe.Pointer
 	list   *mlink
-	chunk  *byte
+	chunk  unsafe.Pointer
 	nchunk uint32
 	inuse  uintptr // in-use bytes now
 	stat   *uint64
@@ -40,9 +40,9 @@ type mlink struct {
 
 // Initialize f to allocate objects of the given size,
 // using the allocator to obtain chunks of memory.
-func fixAlloc_Init(f *fixalloc, size uintptr, first func(unsafe.Pointer, unsafe.Pointer), arg unsafe.Pointer, stat *uint64) {
+func (f *fixalloc) init(size uintptr, first func(arg, p unsafe.Pointer), arg unsafe.Pointer, stat *uint64) {
 	f.size = size
-	f.first = *(*unsafe.Pointer)(unsafe.Pointer(&first))
+	f.first = first
 	f.arg = arg
 	f.list = nil
 	f.chunk = nil
@@ -51,7 +51,7 @@ func fixAlloc_Init(f *fixalloc, size uintptr, first func(unsafe.Pointer, unsafe.
 	f.stat = stat
 }
 
-func fixAlloc_Alloc(f *fixalloc) unsafe.Pointer {
+func (f *fixalloc) alloc() unsafe.Pointer {
 	if f.size == 0 {
 		print("runtime: use of FixAlloc_Alloc before FixAlloc_Init\n")
 		throw("runtime: internal error")
@@ -64,22 +64,21 @@ func fixAlloc_Alloc(f *fixalloc) unsafe.Pointer {
 		return v
 	}
 	if uintptr(f.nchunk) < f.size {
-		f.chunk = (*uint8)(persistentalloc(_FixAllocChunk, 0, f.stat))
+		f.chunk = persistentalloc(_FixAllocChunk, 0, f.stat)
 		f.nchunk = _FixAllocChunk
 	}
 
-	v := (unsafe.Pointer)(f.chunk)
+	v := f.chunk
 	if f.first != nil {
-		fn := *(*func(unsafe.Pointer, unsafe.Pointer))(unsafe.Pointer(&f.first))
-		fn(f.arg, v)
+		f.first(f.arg, v)
 	}
-	f.chunk = (*byte)(add(unsafe.Pointer(f.chunk), f.size))
+	f.chunk = add(f.chunk, f.size)
 	f.nchunk -= uint32(f.size)
 	f.inuse += f.size
 	return v
 }
 
-func fixAlloc_Free(f *fixalloc, p unsafe.Pointer) {
+func (f *fixalloc) free(p unsafe.Pointer) {
 	f.inuse -= f.size
 	v := (*mlink)(p)
 	v.next = f.list
diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go
index 82b12b6..94301c6 100644
--- a/src/runtime/mgc.go
+++ b/src/runtime/mgc.go
@@ -120,20 +120,16 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 const (
 	_DebugGC         = 0
 	_ConcurrentSweep = true
 	_FinBlockSize    = 4 * 1024
-	_RootData        = 0
-	_RootBss         = 1
-	_RootFinalizers  = 2
-	_RootSpans       = 3
-	_RootFlushCaches = 4
-	_RootCount       = 5
-
-	debugStackBarrier = false
 
 	// sweepMinHeapDistance is a lower bound on the heap distance
 	// (in bytes) reserved for concurrent sweeping between GC
@@ -141,18 +137,6 @@ const (
 	sweepMinHeapDistance = 1024 * 1024
 )
 
-// firstStackBarrierOffset is the approximate byte offset at
-// which to place the first stack barrier from the current SP.
-// This is a lower bound on how much stack will have to be
-// re-scanned during mark termination. Subsequent barriers are
-// placed at firstStackBarrierOffset * 2^n offsets.
-//
-// For debugging, this can be set to 0, which will install a
-// stack barrier at every frame. If you do this, you may also
-// have to raise _StackMin, since the stack barrier
-// bookkeeping will use a large amount of each stack.
-var firstStackBarrierOffset = 1024
-
 // heapminimum is the minimum heap size at which to trigger GC.
 // For small heaps, this overrides the usual GOGC*live set rule.
 //
@@ -178,13 +162,14 @@ func gcinit() {
 		throw("size of Workbuf is suboptimal")
 	}
 
-	work.markfor = parforalloc(_MaxGcproc)
 	_ = setGCPercent(readgogc())
 	for datap := &firstmoduledata; datap != nil; datap = datap.next {
 		datap.gcdatamask = progToPointerMask((*byte)(unsafe.Pointer(datap.gcdata)), datap.edata-datap.data)
 		datap.gcbssmask = progToPointerMask((*byte)(unsafe.Pointer(datap.gcbss)), datap.ebss-datap.bss)
 	}
 	memstats.next_gc = heapminimum
+	work.startSema = 1
+	work.markDoneSema = 1
 }
 
 func readgogc() int32 {
@@ -208,6 +193,7 @@ func gcenable() {
 	memstats.enablegc = true // now that runtime is initialized, GC is okay
 }
 
+//go:linkname setGCPercent runtime/debug.setGCPercent
 func setGCPercent(in int32) (out int32) {
 	lock(&mheap_.lock)
 	out = gcpercent
@@ -216,6 +202,9 @@ func setGCPercent(in int32) (out int32) {
 	}
 	gcpercent = in
 	heapminimum = defaultHeapMinimum * uint64(gcpercent) / 100
+	if gcController.triggerRatio > float64(gcpercent)/100 {
+		gcController.triggerRatio = float64(gcpercent) / 100
+	}
 	unlock(&mheap_.lock)
 	return out
 }
@@ -223,7 +212,14 @@ func setGCPercent(in int32) (out int32) {
 // Garbage collector phase.
 // Indicates to write barrier and sychronization task to preform.
 var gcphase uint32
-var writeBarrierEnabled bool // compiler emits references to this in write barriers
+
+// The compiler knows about this variable.
+// If you change it, you must change the compiler too.
+var writeBarrier struct {
+	enabled bool // compiler emits a check of this before calling write barrier
+	needed  bool // whether we need a write barrier for current GC phase
+	cgo     bool // whether we need a write barrier for a cgo check
+}
 
 // gcBlackenEnabled is 1 if mutator assists and background mark
 // workers are allowed to blacken objects. This must only be set when
@@ -247,16 +243,15 @@ var gcBlackenPromptly bool
 
 const (
 	_GCoff             = iota // GC not running; sweeping in background, write barrier disabled
-	_GCstw                    // unused state
-	_GCscan                   // GC collecting roots into workbufs, write barrier ENABLED
-	_GCmark                   // GC marking from workbufs, write barrier ENABLED
+	_GCmark                   // GC marking roots and workbufs, write barrier ENABLED
 	_GCmarktermination        // GC mark termination: allocate black, P's help GC, write barrier ENABLED
 )
 
 //go:nosplit
 func setGCPhase(x uint32) {
-	atomicstore(&gcphase, x)
-	writeBarrierEnabled = gcphase == _GCmark || gcphase == _GCmarktermination || gcphase == _GCscan
+	atomic.Store(&gcphase, x)
+	writeBarrier.needed = gcphase == _GCmark || gcphase == _GCmarktermination
+	writeBarrier.enabled = writeBarrier.needed || writeBarrier.cgo
 }
 
 // gcMarkWorkerMode represents the mode that a concurrent mark worker
@@ -271,8 +266,7 @@ type gcMarkWorkerMode int
 const (
 	// gcMarkWorkerDedicatedMode indicates that the P of a mark
 	// worker is dedicated to running that mark worker. The mark
-	// worker should run without preemption until concurrent mark
-	// is done.
+	// worker should run without preemption.
 	gcMarkWorkerDedicatedMode gcMarkWorkerMode = iota
 
 	// gcMarkWorkerFractionalMode indicates that a P is currently
@@ -307,9 +301,9 @@ var gcController = gcControllerState{
 
 type gcControllerState struct {
 	// scanWork is the total scan work performed this cycle. This
-	// is updated atomically during the cycle. Updates may be
-	// batched arbitrarily, since the value is only read at the
-	// end of the cycle.
+	// is updated atomically during the cycle. Updates occur in
+	// bounded batches, since it is both written and read
+	// throughout the cycle.
 	//
 	// Currently this is the bytes of heap scanned. For most uses,
 	// this is an opaque unit of work, but for estimation the
@@ -363,11 +357,14 @@ type gcControllerState struct {
 	// dedicated mark workers get started.
 	dedicatedMarkWorkersNeeded int64
 
-	// assistRatio is the ratio of allocated bytes to scan work
-	// that should be performed by mutator assists. This is
+	// assistWorkPerByte is the ratio of scan work to allocated
+	// bytes that should be performed by mutator assists. This is
 	// computed at the beginning of each cycle and updated every
 	// time heap_scan is updated.
-	assistRatio float64
+	assistWorkPerByte float64
+
+	// assistBytesPerWork is 1/assistWorkPerByte.
+	assistBytesPerWork float64
 
 	// fractionalUtilizationGoal is the fraction of wall clock
 	// time that should be spent in the fractional mark worker.
@@ -385,7 +382,7 @@ type gcControllerState struct {
 	// at the end of of each cycle.
 	triggerRatio float64
 
-	_ [_CacheLineSize]byte
+	_ [sys.CacheLineSize]byte
 
 	// fractionalMarkWorkersNeeded is the number of fractional
 	// mark workers that need to be started. This is either 0 or
@@ -393,7 +390,7 @@ type gcControllerState struct {
 	// scheduling point (hence it gets its own cache line).
 	fractionalMarkWorkersNeeded int64
 
-	_ [_CacheLineSize]byte
+	_ [sys.CacheLineSize]byte
 }
 
 // startCycle resets the GC controller's state and computes estimates
@@ -420,6 +417,17 @@ func (c *gcControllerState) startCycle() {
 	// Compute the heap goal for this cycle
 	c.heapGoal = memstats.heap_reachable + memstats.heap_reachable*uint64(gcpercent)/100
 
+	// Ensure that the heap goal is at least a little larger than
+	// the current live heap size. This may not be the case if GC
+	// start is delayed or if the allocation that pushed heap_live
+	// over next_gc is large or if the trigger is really close to
+	// GOGC. Assist is proportional to this distance, so enforce a
+	// minimum distance, even if it means going over the GOGC goal
+	// by a tiny bit.
+	if c.heapGoal < memstats.heap_live+1024*1024 {
+		c.heapGoal = memstats.heap_live + 1024*1024
+	}
+
 	// Compute the total mark utilization goal and divide it among
 	// dedicated and fractional workers.
 	totalUtilizationGoal := float64(gomaxprocs) * gcGoalUtilization
@@ -444,7 +452,7 @@ func (c *gcControllerState) startCycle() {
 	c.revise()
 
 	if debug.gcpacertrace > 0 {
-		print("pacer: assist ratio=", c.assistRatio,
+		print("pacer: assist ratio=", c.assistWorkPerByte,
 			" (scan ", memstats.heap_scan>>20, " MB in ",
 			work.initialHeapLive>>20, "->",
 			c.heapGoal>>20, " MB)",
@@ -455,33 +463,55 @@ func (c *gcControllerState) startCycle() {
 
 // revise updates the assist ratio during the GC cycle to account for
 // improved estimates. This should be called either under STW or
-// whenever memstats.heap_scan is updated (with mheap_.lock held).
+// whenever memstats.heap_scan or memstats.heap_live is updated (with
+// mheap_.lock held).
+//
+// It should only be called when gcBlackenEnabled != 0 (because this
+// is when assists are enabled and the necessary statistics are
+// available).
 func (c *gcControllerState) revise() {
-	// Compute the expected scan work. This is a strict upper
-	// bound on the possible scan work in the current heap.
+	// Compute the expected scan work remaining.
+	//
+	// Note that the scannable heap size is likely to increase
+	// during the GC cycle. This is why it's important to revise
+	// the assist ratio throughout the cycle: if the scannable
+	// heap size increases, the assist ratio based on the initial
+	// scannable heap size may target too little scan work.
 	//
+	// This particular estimate is a strict upper bound on the
+	// possible remaining scan work for the current heap.
 	// You might consider dividing this by 2 (or by
 	// (100+GOGC)/100) to counter this over-estimation, but
 	// benchmarks show that this has almost no effect on mean
 	// mutator utilization, heap size, or assist time and it
 	// introduces the danger of under-estimating and letting the
 	// mutator outpace the garbage collector.
-	scanWorkExpected := memstats.heap_scan
+	scanWorkExpected := int64(memstats.heap_scan) - c.scanWork
+	if scanWorkExpected < 1000 {
+		// We set a somewhat arbitrary lower bound on
+		// remaining scan work since if we aim a little high,
+		// we can miss by a little.
+		//
+		// We *do* need to enforce that this is at least 1,
+		// since marking is racy and double-scanning objects
+		// may legitimately make the expected scan work
+		// negative.
+		scanWorkExpected = 1000
+	}
+
+	// Compute the heap distance remaining.
+	heapDistance := int64(c.heapGoal) - int64(memstats.heap_live)
+	if heapDistance <= 0 {
+		// This shouldn't happen, but if it does, avoid
+		// dividing by zero or setting the assist negative.
+		heapDistance = 1
+	}
 
 	// Compute the mutator assist ratio so by the time the mutator
 	// allocates the remaining heap bytes up to next_gc, it will
-	// have done (or stolen) the estimated amount of scan work.
-	heapDistance := int64(c.heapGoal) - int64(work.initialHeapLive)
-	if heapDistance <= 1024*1024 {
-		// heapDistance can be negative if GC start is delayed
-		// or if the allocation that pushed heap_live over
-		// next_gc is large or if the trigger is really close
-		// to GOGC. We don't want to set the assist negative
-		// (or divide by zero, or set it really high), so
-		// enforce a minimum on the distance.
-		heapDistance = 1024 * 1024
-	}
-	c.assistRatio = float64(scanWorkExpected) / float64(heapDistance)
+	// have done (or stolen) the remaining amount of scan work.
+	c.assistWorkPerByte = float64(scanWorkExpected) / float64(heapDistance)
+	c.assistBytesPerWork = float64(heapDistance) / float64(scanWorkExpected)
 }
 
 // endCycle updates the GC controller state at the end of the
@@ -560,31 +590,67 @@ func (c *gcControllerState) endCycle() {
 	}
 }
 
+// enlistWorker encourages another dedicated mark worker to start on
+// another P if there are spare worker slots. It is used by putfull
+// when more work is made available.
+//
+//go:nowritebarrier
+func (c *gcControllerState) enlistWorker() {
+	if c.dedicatedMarkWorkersNeeded <= 0 {
+		return
+	}
+	// Pick a random other P to preempt.
+	if gomaxprocs <= 1 {
+		return
+	}
+	gp := getg()
+	if gp == nil || gp.m == nil || gp.m.p == 0 {
+		return
+	}
+	myID := gp.m.p.ptr().id
+	for tries := 0; tries < 5; tries++ {
+		id := int32(fastrand1() % uint32(gomaxprocs-1))
+		if id >= myID {
+			id++
+		}
+		p := allp[id]
+		if p.status != _Prunning {
+			continue
+		}
+		if preemptone(p) {
+			return
+		}
+	}
+}
+
 // findRunnableGCWorker returns the background mark worker for _p_ if it
 // should be run. This must only be called when gcBlackenEnabled != 0.
 func (c *gcControllerState) findRunnableGCWorker(_p_ *p) *g {
 	if gcBlackenEnabled == 0 {
 		throw("gcControllerState.findRunnable: blackening not enabled")
 	}
-	if _p_.gcBgMarkWorker == nil {
-		throw("gcControllerState.findRunnable: no background mark worker")
+	if _p_.gcBgMarkWorker == 0 {
+		// The mark worker associated with this P is blocked
+		// performing a mark transition. We can't run it
+		// because it may be on some other run or wait queue.
+		return nil
 	}
-	if work.bgMark1.done != 0 && work.bgMark2.done != 0 {
-		// Background mark is done. Don't schedule background
-		// mark worker any more. (This is not just an
-		// optimization. Without this we can spin scheduling
-		// the background worker and having it return
-		// immediately with no work to do.)
+
+	if !gcMarkWorkAvailable(_p_) {
+		// No work to be done right now. This can happen at
+		// the end of the mark phase when there are still
+		// assists tapering off. Don't bother running a worker
+		// now because it'll just return immediately.
 		return nil
 	}
 
 	decIfPositive := func(ptr *int64) bool {
 		if *ptr > 0 {
-			if xaddint64(ptr, -1) >= 0 {
+			if atomic.Xaddint64(ptr, -1) >= 0 {
 				return true
 			}
 			// We lost a race
-			xaddint64(ptr, +1)
+			atomic.Xaddint64(ptr, +1)
 		}
 		return false
 	}
@@ -597,36 +663,6 @@ func (c *gcControllerState) findRunnableGCWorker(_p_ *p) *g {
 		// else for a while, so kick everything out of its run
 		// queue.
 	} else {
-		if _p_.gcw.wbuf == 0 && work.full == 0 && work.partial == 0 {
-			// No work to be done right now. This can
-			// happen at the end of the mark phase when
-			// there are still assists tapering off. Don't
-			// bother running background mark because
-			// it'll just return immediately.
-			if work.nwait == work.nproc {
-				// There are also no workers, which
-				// means we've reached a completion point.
-				// There may not be any workers to
-				// signal it, so signal it here.
-				readied := false
-				if gcBlackenPromptly {
-					if work.bgMark1.done == 0 {
-						throw("completing mark 2, but bgMark1.done == 0")
-					}
-					readied = work.bgMark2.complete()
-				} else {
-					readied = work.bgMark1.complete()
-				}
-				if readied {
-					// complete just called ready,
-					// but we're inside the
-					// scheduler. Let it know that
-					// that's okay.
-					resetspinning()
-				}
-			}
-			return nil
-		}
 		if !decIfPositive(&c.fractionalMarkWorkersNeeded) {
 			// No more workers are need right now.
 			return nil
@@ -668,14 +704,14 @@ func (c *gcControllerState) findRunnableGCWorker(_p_ *p) *g {
 		timeUsed := c.fractionalMarkTime + gcForcePreemptNS
 		if then > 0 && float64(timeUsed)/float64(then) > c.fractionalUtilizationGoal {
 			// Nope, we'd overshoot the utilization goal
-			xaddint64(&c.fractionalMarkWorkersNeeded, +1)
+			atomic.Xaddint64(&c.fractionalMarkWorkersNeeded, +1)
 			return nil
 		}
 		_p_.gcMarkWorkerMode = gcMarkWorkerFractionalMode
 	}
 
 	// Run the background mark worker
-	gp := _p_.gcBgMarkWorker
+	gp := _p_.gcBgMarkWorker.ptr()
 	casgstatus(gp, _Gwaiting, _Grunnable)
 	if trace.enabled {
 		traceGoUnpark(gp, 0)
@@ -687,101 +723,72 @@ func (c *gcControllerState) findRunnableGCWorker(_p_ *p) *g {
 // marking as a fraction of GOMAXPROCS.
 const gcGoalUtilization = 0.25
 
-// gcBgCreditSlack is the amount of scan work credit background
-// scanning can accumulate locally before updating
-// gcController.bgScanCredit. Lower values give mutator assists more
-// accurate accounting of background scanning. Higher values reduce
-// memory contention.
-const gcBgCreditSlack = 2000
+// gcCreditSlack is the amount of scan work credit that can can
+// accumulate locally before updating gcController.scanWork and,
+// optionally, gcController.bgScanCredit. Lower values give a more
+// accurate assist ratio and make it more likely that assists will
+// successfully steal background credit. Higher values reduce memory
+// contention.
+const gcCreditSlack = 2000
 
 // gcAssistTimeSlack is the nanoseconds of mutator assist time that
 // can accumulate on a P before updating gcController.assistTime.
 const gcAssistTimeSlack = 5000
 
-// Determine whether to initiate a GC.
-// If the GC is already working no need to trigger another one.
-// This should establish a feedback loop where if the GC does not
-// have sufficient time to complete then more memory will be
-// requested from the OS increasing heap size thus allow future
-// GCs more time to complete.
-// memstat.heap_live read has a benign race.
-// A false negative simple does not start a GC, a false positive
-// will start a GC needlessly. Neither have correctness issues.
-func shouldtriggergc() bool {
-	return memstats.heap_live >= memstats.next_gc && atomicloaduint(&bggc.working) == 0
-}
-
-// bgMarkSignal synchronizes the GC coordinator and background mark workers.
-type bgMarkSignal struct {
-	// Workers race to cas to 1. Winner signals coordinator.
-	done uint32
-	// Coordinator to wake up.
-	lock mutex
-	g    *g
-	wake bool
-}
-
-func (s *bgMarkSignal) wait() {
-	lock(&s.lock)
-	if s.wake {
-		// Wakeup already happened
-		unlock(&s.lock)
-	} else {
-		s.g = getg()
-		goparkunlock(&s.lock, "mark wait (idle)", traceEvGoBlock, 1)
-	}
-	s.wake = false
-	s.g = nil
-}
+// gcOverAssistBytes determines how many extra allocation bytes of
+// assist credit a GC assist builds up when an assist happens. This
+// amortizes the cost of an assist by pre-paying for this many bytes
+// of future allocations.
+const gcOverAssistBytes = 1 << 20
 
-// complete signals the completion of this phase of marking. This can
-// be called multiple times during a cycle; only the first call has
-// any effect.
-//
-// The caller should arrange to deschedule itself as soon as possible
-// after calling complete in order to let the coordinator goroutine
-// run.
-func (s *bgMarkSignal) complete() bool {
-	if cas(&s.done, 0, 1) {
-		// This is the first worker to reach this completion point.
-		// Signal the main GC goroutine.
-		lock(&s.lock)
-		if s.g == nil {
-			// It hasn't parked yet.
-			s.wake = true
-		} else {
-			ready(s.g, 0)
-		}
-		unlock(&s.lock)
-		return true
-	}
-	return false
-}
+var work struct {
+	full  uint64                   // lock-free list of full blocks workbuf
+	empty uint64                   // lock-free list of empty blocks workbuf
+	pad0  [sys.CacheLineSize]uint8 // prevents false-sharing between full/empty and nproc/nwait
 
-func (s *bgMarkSignal) clear() {
-	s.done = 0
-}
+	markrootNext uint32 // next markroot job
+	markrootJobs uint32 // number of markroot jobs
 
-var work struct {
-	full  uint64 // lock-free list of full blocks workbuf
-	empty uint64 // lock-free list of empty blocks workbuf
-	// TODO(rlh): partial no longer used, remove. (issue #11922)
-	partial uint64                // lock-free list of partially filled blocks workbuf
-	pad0    [_CacheLineSize]uint8 // prevents false-sharing between full/empty and nproc/nwait
 	nproc   uint32
 	tstart  int64
 	nwait   uint32
 	ndone   uint32
 	alldone note
-	markfor *parfor
+
+	// Number of roots of various root types. Set by gcMarkRootPrepare.
+	nDataRoots, nBSSRoots, nSpanRoots, nStackRoots int
+
+	// finalizersDone indicates that finalizers and objects with
+	// finalizers have been scanned by markroot. During concurrent
+	// GC, this happens during the concurrent scan phase. During
+	// STW GC, this happens during mark termination.
+	finalizersDone bool
+
+	// Each type of GC state transition is protected by a lock.
+	// Since multiple threads can simultaneously detect the state
+	// transition condition, any thread that detects a transition
+	// condition must acquire the appropriate transition lock,
+	// re-check the transition condition and return if it no
+	// longer holds or perform the transition if it does.
+	// Likewise, any transition must invalidate the transition
+	// condition before releasing the lock. This ensures that each
+	// transition is performed by exactly one thread and threads
+	// that need the transition to happen block until it has
+	// happened.
+	//
+	// startSema protects the transition from "off" to mark or
+	// mark termination.
+	startSema uint32
+	// markDoneSema protects transitions from mark 1 to mark 2 and
+	// from mark 2 to mark termination.
+	markDoneSema uint32
 
 	bgMarkReady note   // signal background mark worker has started
 	bgMarkDone  uint32 // cas to 1 when at a background mark completion point
 	// Background mark completion signaling
 
-	// Coordination for the 2 parts of the mark phase.
-	bgMark1 bgMarkSignal
-	bgMark2 bgMarkSignal
+	// mode is the concurrency mode of the current GC cycle.
+	mode gcMode
 
 	// Copy of mheap.allspans for marker or sweeper.
 	spans []*mspan
@@ -806,115 +813,72 @@ var work struct {
 	// initialHeapLive is the value of memstats.heap_live at the
 	// beginning of this GC cycle.
 	initialHeapLive uint64
+
+	// assistQueue is a queue of assists that are blocked because
+	// there was neither enough credit to steal or enough work to
+	// do.
+	assistQueue struct {
+		lock       mutex
+		head, tail guintptr
+	}
+
+	// Timing/utilization stats for this cycle.
+	stwprocs, maxprocs                 int32
+	tSweepTerm, tMark, tMarkTerm, tEnd int64 // nanotime() of phase start
+
+	pauseNS    int64 // total STW time this cycle
+	pauseStart int64 // nanotime() of last STW
+
+	// debug.gctrace heap sizes for this cycle.
+	heap0, heap1, heap2, heapGoal uint64
 }
 
 // GC runs a garbage collection and blocks the caller until the
 // garbage collection is complete. It may also block the entire
 // program.
 func GC() {
-	startGC(gcForceBlockMode, false)
+	gcStart(gcForceBlockMode, false)
 }
 
+// gcMode indicates how concurrent a GC cycle should be.
+type gcMode int
+
 const (
-	gcBackgroundMode = iota // concurrent GC
-	gcForceMode             // stop-the-world GC now
-	gcForceBlockMode        // stop-the-world GC now and wait for sweep
+	gcBackgroundMode gcMode = iota // concurrent GC and sweep
+	gcForceMode                    // stop-the-world GC now, concurrent sweep
+	gcForceBlockMode               // stop-the-world GC now and STW sweep
 )
 
-// startGC starts a GC cycle. If mode is gcBackgroundMode, this will
-// start GC in the background and return. Otherwise, this will block
-// until the new GC cycle is started and finishes. If forceTrigger is
-// true, it indicates that GC should be started regardless of the
-// current heap size.
-func startGC(mode int, forceTrigger bool) {
-	// The gc is turned off (via enablegc) until the bootstrap has completed.
-	// Also, malloc gets called in the guts of a number of libraries that might be
-	// holding locks. To avoid deadlocks during stop-the-world, don't bother
-	// trying to run gc while holding a lock. The next mallocgc without a lock
-	// will do the gc instead.
+// gcShouldStart returns true if the exit condition for the _GCoff
+// phase has been met. The exit condition should be tested when
+// allocating.
+//
+// If forceTrigger is true, it ignores the current heap size, but
+// checks all other conditions. In general this should be false.
+func gcShouldStart(forceTrigger bool) bool {
+	return gcphase == _GCoff && (forceTrigger || memstats.heap_live >= memstats.next_gc) && memstats.enablegc && panicking == 0 && gcpercent >= 0
+}
+
+// gcStart transitions the GC from _GCoff to _GCmark (if mode ==
+// gcBackgroundMode) or _GCmarktermination (if mode !=
+// gcBackgroundMode) by performing sweep termination and GC
+// initialization.
+//
+// This may return without performing this transition in some cases,
+// such as when called on a system stack or with locks held.
+func gcStart(mode gcMode, forceTrigger bool) {
+	// Since this is called from malloc and malloc is called in
+	// the guts of a number of libraries that might be holding
+	// locks, don't attempt to start GC in non-preemptible or
+	// potentially unstable situations.
 	mp := acquirem()
-	if gp := getg(); gp == mp.g0 || mp.locks > 1 || mp.preemptoff != "" || !memstats.enablegc || panicking != 0 || gcpercent < 0 {
+	if gp := getg(); gp == mp.g0 || mp.locks > 1 || mp.preemptoff != "" {
 		releasem(mp)
 		return
 	}
 	releasem(mp)
 	mp = nil
 
-	if debug.gcstoptheworld == 1 {
-		mode = gcForceMode
-	} else if debug.gcstoptheworld == 2 {
-		mode = gcForceBlockMode
-	}
-
-	if mode != gcBackgroundMode {
-		// special synchronous cases
-		gc(mode)
-		return
-	}
-
-	// trigger concurrent GC
-	readied := false
-	lock(&bggc.lock)
-	// The trigger was originally checked speculatively, so
-	// recheck that this really should trigger GC. (For example,
-	// we may have gone through a whole GC cycle since the
-	// speculative check.)
-	if !(forceTrigger || shouldtriggergc()) {
-		unlock(&bggc.lock)
-		return
-	}
-	if !bggc.started {
-		bggc.working = 1
-		bggc.started = true
-		readied = true
-		go backgroundgc()
-	} else if bggc.working == 0 {
-		bggc.working = 1
-		readied = true
-		ready(bggc.g, 0)
-	}
-	unlock(&bggc.lock)
-	if readied {
-		// This G just started or ready()d the GC goroutine.
-		// Switch directly to it by yielding.
-		Gosched()
-	}
-}
-
-// State of the background concurrent GC goroutine.
-var bggc struct {
-	lock    mutex
-	g       *g
-	working uint
-	started bool
-}
-
-// backgroundgc is running in a goroutine and does the concurrent GC work.
-// bggc holds the state of the backgroundgc.
-func backgroundgc() {
-	bggc.g = getg()
-	for {
-		gc(gcBackgroundMode)
-		lock(&bggc.lock)
-		bggc.working = 0
-		goparkunlock(&bggc.lock, "Concurrent GC wait", traceEvGoBlock, 1)
-	}
-}
-
-func gc(mode int) {
-	// Timing/utilization tracking
-	var stwprocs, maxprocs int32
-	var tSweepTerm, tScan, tInstallWB, tMark, tMarkTerm int64
-
-	// debug.gctrace variables
-	var heap0, heap1, heap2, heapGoal uint64
-
-	// memstats statistics
-	var now, pauseStart, pauseNS int64
-
-	// Ok, we're doing it!  Stop everybody else
-	semacquire(&worldsema, false)
-
 	// Pick up the remaining unswept/not being swept spans concurrently
 	//
 	// This shouldn't happen if we're being invoked in background
@@ -922,10 +886,45 @@ func gc(mode int) {
 	// sweeping everything, but rounding errors, etc, may leave a
 	// few spans unswept. In forced mode, this is necessary since
 	// GC can be forced at any point in the sweeping cycle.
-	for gosweepone() != ^uintptr(0) {
+	//
+	// We check the transition condition continuously here in case
+	// this G gets delayed in to the next GC cycle.
+	for (mode != gcBackgroundMode || gcShouldStart(forceTrigger)) && gosweepone() != ^uintptr(0) {
 		sweep.nbgsweep++
 	}
 
+	// Perform GC initialization and the sweep termination
+	// transition.
+	//
+	// If this is a forced GC, don't acquire the transition lock
+	// or re-check the transition condition because we
+	// specifically *don't* want to share the transition with
+	// another thread.
+	useStartSema := mode == gcBackgroundMode
+	if useStartSema {
+		semacquire(&work.startSema, false)
+		// Re-check transition condition under transition lock.
+		if !gcShouldStart(forceTrigger) {
+			semrelease(&work.startSema)
+			return
+		}
+	}
+
+	// In gcstoptheworld debug mode, upgrade the mode accordingly.
+	// We do this after re-checking the transition condition so
+	// that multiple goroutines that detect the heap trigger don't
+	// start multiple STW GCs.
+	if mode == gcBackgroundMode {
+		if debug.gcstoptheworld == 1 {
+			mode = gcForceMode
+		} else if debug.gcstoptheworld == 2 {
+			mode = gcForceBlockMode
+		}
+	}
+
+	// Ok, we're doing it!  Stop everybody else
+	semacquire(&worldsema, false)
+
 	if trace.enabled {
 		traceGCStart()
 	}
@@ -933,143 +932,228 @@ func gc(mode int) {
 	if mode == gcBackgroundMode {
 		gcBgMarkStartWorkers()
 	}
-	now = nanotime()
-	stwprocs, maxprocs = gcprocs(), gomaxprocs
-	tSweepTerm = now
-	heap0 = memstats.heap_live
+	now := nanotime()
+	work.stwprocs, work.maxprocs = gcprocs(), gomaxprocs
+	work.tSweepTerm = now
+	work.heap0 = memstats.heap_live
+	work.pauseNS = 0
+	work.mode = mode
 
-	pauseStart = now
+	work.pauseStart = now
 	systemstack(stopTheWorldWithSema)
-	systemstack(finishsweep_m) // finish sweep before we start concurrent scan.
+	// Finish sweep before we start concurrent scan.
+	systemstack(func() {
+		finishsweep_m(true)
+	})
 	// clearpools before we start the GC. If we wait they memory will not be
 	// reclaimed until the next GC cycle.
 	clearpools()
 
 	gcResetMarkState()
 
+	work.finalizersDone = false
+
 	if mode == gcBackgroundMode { // Do as much work concurrently as possible
 		gcController.startCycle()
-		heapGoal = gcController.heapGoal
+		work.heapGoal = gcController.heapGoal
+
+		// Enter concurrent mark phase and enable
+		// write barriers.
+		//
+		// Because the world is stopped, all Ps will
+		// observe that write barriers are enabled by
+		// the time we start the world and begin
+		// scanning.
+		//
+		// It's necessary to enable write barriers
+		// during the scan phase for several reasons:
+		//
+		// They must be enabled for writes to higher
+		// stack frames before we scan stacks and
+		// install stack barriers because this is how
+		// we track writes to inactive stack frames.
+		// (Alternatively, we could not install stack
+		// barriers over frame boundaries with
+		// up-pointers).
+		//
+		// They must be enabled before assists are
+		// enabled because they must be enabled before
+		// any non-leaf heap objects are marked. Since
+		// allocations are blocked until assists can
+		// happen, we want enable assists as early as
+		// possible.
+		setGCPhase(_GCmark)
+
+		// markrootSpans uses work.spans, so make sure
+		// it is up to date.
+		gcCopySpans()
+
+		gcBgMarkPrepare() // Must happen before assist enable.
+		gcMarkRootPrepare()
+
+		// At this point all Ps have enabled the write
+		// barrier, thus maintaining the no white to
+		// black invariant. Enable mutator assists to
+		// put back-pressure on fast allocating
+		// mutators.
+		atomic.Store(&gcBlackenEnabled, 1)
+
+		// Assists and workers can start the moment we start
+		// the world.
+		gcController.assistStartTime = now
+		gcController.bgMarkStartTime = now
 
-		systemstack(func() {
-			// Enter scan phase. This enables write
-			// barriers to track changes to stack frames
-			// above the stack barrier.
-			//
-			// TODO: This has evolved to the point where
-			// we carefully ensure invariants we no longer
-			// depend on. Either:
-			//
-			// 1) Enable full write barriers for the scan,
-			// but eliminate the ragged barrier below
-			// (since the start the world ensures all Ps
-			// have observed the write barrier enable) and
-			// consider draining during the scan.
-			//
-			// 2) Only enable write barriers for writes to
-			// the stack at this point, and then enable
-			// write barriers for heap writes when we
-			// enter the mark phase. This means we cannot
-			// drain in the scan phase and must perform a
-			// ragged barrier to ensure all Ps have
-			// enabled heap write barriers before we drain
-			// or enable assists.
-			//
-			// 3) Don't install stack barriers over frame
-			// boundaries where there are up-pointers.
-			setGCPhase(_GCscan)
-
-			gcBgMarkPrepare() // Must happen before assist enable.
-
-			// At this point all Ps have enabled the write
-			// barrier, thus maintaining the no white to
-			// black invariant. Enable mutator assists to
-			// put back-pressure on fast allocating
-			// mutators.
-			atomicstore(&gcBlackenEnabled, 1)
-
-			// Concurrent scan.
-			startTheWorldWithSema()
-			now = nanotime()
-			pauseNS += now - pauseStart
-			tScan = now
-			gcController.assistStartTime = now
-			gcscan_m()
-
-			// Enter mark phase.
-			tInstallWB = nanotime()
-			setGCPhase(_GCmark)
-			// Ensure all Ps have observed the phase
-			// change and have write barriers enabled
-			// before any blackening occurs.
-			forEachP(func(*p) {})
-		})
 		// Concurrent mark.
-		tMark = nanotime()
+		systemstack(startTheWorldWithSema)
+		now = nanotime()
+		work.pauseNS += now - work.pauseStart
+		work.tMark = now
+	} else {
+		t := nanotime()
+		work.tMark, work.tMarkTerm = t, t
+		work.heapGoal = work.heap0
 
-		// Enable background mark workers and wait for
-		// background mark completion.
-		gcController.bgMarkStartTime = nanotime()
-		work.bgMark1.clear()
-		work.bgMark1.wait()
+		// Perform mark termination. This will restart the world.
+		gcMarkTermination()
+	}
 
+	if useStartSema {
+		semrelease(&work.startSema)
+	}
+}
+
+// gcMarkDone transitions the GC from mark 1 to mark 2 and from mark 2
+// to mark termination.
+//
+// This should be called when all mark work has been drained. In mark
+// 1, this includes all root marking jobs, global work buffers, and
+// active work buffers in assists and background workers; however,
+// work may still be cached in per-P work buffers. In mark 2, per-P
+// caches are disabled.
+//
+// The calling context must be preemptible.
+//
+// Note that it is explicitly okay to have write barriers in this
+// function because completion of concurrent mark is best-effort
+// anyway. Any work created by write barriers here will be cleaned up
+// by mark termination.
+func gcMarkDone() {
+top:
+	semacquire(&work.markDoneSema, false)
+
+	// Re-check transition condition under transition lock.
+	if !(gcphase == _GCmark && work.nwait == work.nproc && !gcMarkWorkAvailable(nil)) {
+		semrelease(&work.markDoneSema)
+		return
+	}
+
+	// Disallow starting new workers so that any remaining workers
+	// in the current mark phase will drain out.
+	//
+	// TODO(austin): Should dedicated workers keep an eye on this
+	// and exit gcDrain promptly?
+	atomic.Xaddint64(&gcController.dedicatedMarkWorkersNeeded, -0xffffffff)
+	atomic.Xaddint64(&gcController.fractionalMarkWorkersNeeded, -0xffffffff)
+
+	if !gcBlackenPromptly {
+		// Transition from mark 1 to mark 2.
+		//
 		// The global work list is empty, but there can still be work
 		// sitting in the per-P work caches and there can be more
 		// objects reachable from global roots since they don't have write
 		// barriers. Rescan some roots and flush work caches.
-		systemstack(func() {
-			// rescan global data and bss.
-			markroot(nil, _RootData)
-			markroot(nil, _RootBss)
 
-			// Disallow caching workbufs.
-			gcBlackenPromptly = true
+		gcMarkRootCheck()
+
+		// Disallow caching workbufs and indicate that we're in mark 2.
+		gcBlackenPromptly = true
 
-			// Flush all currently cached workbufs. This
-			// also forces any remaining background
-			// workers out of their loop.
+		// Prevent completion of mark 2 until we've flushed
+		// cached workbufs.
+		atomic.Xadd(&work.nwait, -1)
+
+		// Rescan global data and BSS. There may still work
+		// workers running at this point, so bump "jobs" down
+		// before "next" so they won't try running root jobs
+		// until we set next.
+		atomic.Store(&work.markrootJobs, uint32(fixedRootCount+work.nDataRoots+work.nBSSRoots))
+		atomic.Store(&work.markrootNext, fixedRootCount)
+
+		// GC is set up for mark 2. Let Gs blocked on the
+		// transition lock go while we flush caches.
+		semrelease(&work.markDoneSema)
+
+		systemstack(func() {
+			// Flush all currently cached workbufs and
+			// ensure all Ps see gcBlackenPromptly. This
+			// also blocks until any remaining mark 1
+			// workers have exited their loop so we can
+			// start new mark 2 workers that will observe
+			// the new root marking jobs.
 			forEachP(func(_p_ *p) {
 				_p_.gcw.dispose()
 			})
 		})
 
-		// Wait for this more aggressive background mark to complete.
-		work.bgMark2.clear()
-		work.bgMark2.wait()
+		// Now we can start up mark 2 workers.
+		atomic.Xaddint64(&gcController.dedicatedMarkWorkersNeeded, 0xffffffff)
+		atomic.Xaddint64(&gcController.fractionalMarkWorkersNeeded, 0xffffffff)
 
-		// Begin mark termination.
-		now = nanotime()
-		tMarkTerm = now
-		pauseStart = now
+		incnwait := atomic.Xadd(&work.nwait, +1)
+		if incnwait == work.nproc && !gcMarkWorkAvailable(nil) {
+			// This loop will make progress because
+			// gcBlackenPromptly is now true, so it won't
+			// take this same "if" branch.
+			goto top
+		}
+	} else {
+		// Transition to mark termination.
+		now := nanotime()
+		work.tMarkTerm = now
+		work.pauseStart = now
+		getg().m.preemptoff = "gcing"
 		systemstack(stopTheWorldWithSema)
 		// The gcphase is _GCmark, it will transition to _GCmarktermination
 		// below. The important thing is that the wb remains active until
 		// all marking is complete. This includes writes made by the GC.
 
+		// markroot is done now, so record that objects with
+		// finalizers have been scanned.
+		work.finalizersDone = true
+
+		// Disable assists and background workers. We must do
+		// this before waking blocked assists.
+		atomic.Store(&gcBlackenEnabled, 0)
+
 		// Flush the gcWork caches. This must be done before
 		// endCycle since endCycle depends on statistics kept
 		// in these caches.
 		gcFlushGCWork()
 
+		// Wake all blocked assists. These will run when we
+		// start the world again.
+		gcWakeAllAssists()
+
+		// Likewise, release the transition lock. Blocked
+		// workers and assists will run when we start the
+		// world again.
+		semrelease(&work.markDoneSema)
+
 		gcController.endCycle()
-	} else {
-		// For non-concurrent GC (mode != gcBackgroundMode)
-		// The g stacks have not been scanned so clear g state
-		// such that mark termination scans all stacks.
-		gcResetGState()
 
-		t := nanotime()
-		tScan, tInstallWB, tMark, tMarkTerm = t, t, t, t
-		heapGoal = heap0
+		// Perform mark termination. This will restart the world.
+		gcMarkTermination()
 	}
+}
 
+func gcMarkTermination() {
 	// World is stopped.
 	// Start marktermination which includes enabling the write barrier.
-	atomicstore(&gcBlackenEnabled, 0)
+	atomic.Store(&gcBlackenEnabled, 0)
 	gcBlackenPromptly = false
 	setGCPhase(_GCmarktermination)
 
-	heap1 = memstats.heap_live
+	work.heap1 = memstats.heap_live
 	startTime := nanotime()
 
 	mp := acquirem()
@@ -1097,12 +1181,11 @@ func gc(mode int) {
 	})
 
 	systemstack(func() {
-		heap2 = work.bytesMarked
+		work.heap2 = work.bytesMarked
 		if debug.gccheckmark > 0 {
 			// Run a full stop-the-world mark using checkmark bits,
 			// to check that we didn't forget to mark anything during
 			// the concurrent mark process.
-			gcResetGState() // Rescan stacks
 			gcResetMarkState()
 			initCheckmarks()
 			gcMark(startTime)
@@ -1111,16 +1194,15 @@ func gc(mode int) {
 
 		// marking is complete so we can turn the write barrier off
 		setGCPhase(_GCoff)
-		gcSweep(mode)
+		gcSweep(work.mode)
 
 		if debug.gctrace > 1 {
 			startTime = nanotime()
 			// The g stacks have been scanned so
 			// they have gcscanvalid==true and gcworkdone==true.
 			// Reset these so that all stacks will be rescanned.
-			gcResetGState()
 			gcResetMarkState()
-			finishsweep_m()
+			finishsweep_m(true)
 
 			// Still in STW but gcphase is _GCoff, reset to _GCmarktermination
 			// At this point all objects will be found during the gcMark which
@@ -1128,7 +1210,7 @@ func gc(mode int) {
 			setGCPhase(_GCmarktermination)
 			gcMark(startTime)
 			setGCPhase(_GCoff) // marking is done, turn off wb.
-			gcSweep(mode)
+			gcSweep(work.mode)
 		}
 	})
 
@@ -1148,21 +1230,20 @@ func gc(mode int) {
 
 	// Update timing memstats
 	now, unixNow := nanotime(), unixnanotime()
-	pauseNS += now - pauseStart
-	atomicstore64(&memstats.last_gc, uint64(unixNow)) // must be Unix time to make sense to user
-	memstats.pause_ns[memstats.numgc%uint32(len(memstats.pause_ns))] = uint64(pauseNS)
+	work.pauseNS += now - work.pauseStart
+	work.tEnd = now
+	atomic.Store64(&memstats.last_gc, uint64(unixNow)) // must be Unix time to make sense to user
+	memstats.pause_ns[memstats.numgc%uint32(len(memstats.pause_ns))] = uint64(work.pauseNS)
 	memstats.pause_end[memstats.numgc%uint32(len(memstats.pause_end))] = uint64(unixNow)
-	memstats.pause_total_ns += uint64(pauseNS)
+	memstats.pause_total_ns += uint64(work.pauseNS)
 
 	// Update work.totaltime.
-	sweepTermCpu := int64(stwprocs) * (tScan - tSweepTerm)
-	scanCpu := tInstallWB - tScan
-	installWBCpu := int64(0)
+	sweepTermCpu := int64(work.stwprocs) * (work.tMark - work.tSweepTerm)
 	// We report idle marking time below, but omit it from the
 	// overall utilization here since it's "free".
 	markCpu := gcController.assistTime + gcController.dedicatedMarkTime + gcController.fractionalMarkTime
-	markTermCpu := int64(stwprocs) * (now - tMarkTerm)
-	cycleCpu := sweepTermCpu + scanCpu + installWBCpu + markCpu + markTermCpu
+	markTermCpu := int64(work.stwprocs) * (work.tEnd - work.tMarkTerm)
+	cycleCpu := sweepTermCpu + markCpu + markTermCpu
 	work.totaltime += cycleCpu
 
 	// Compute overall GC CPU utilization.
@@ -1171,23 +1252,28 @@ func gc(mode int) {
 
 	memstats.numgc++
 
+	// Reset sweep state.
+	sweep.nbgsweep = 0
+	sweep.npausesweep = 0
+
 	systemstack(startTheWorldWithSema)
-	semrelease(&worldsema)
 
-	releasem(mp)
-	mp = nil
+	// Free stack spans. This must be done between GC cycles.
+	systemstack(freeStackSpans)
 
+	// Print gctrace before dropping worldsema. As soon as we drop
+	// worldsema another cycle could start and smash the stats
+	// we're trying to print.
 	if debug.gctrace > 0 {
-		tEnd := now
 		util := int(memstats.gc_cpu_fraction * 100)
 
 		var sbuf [24]byte
 		printlock()
 		print("gc ", memstats.numgc,
-			" @", string(itoaDiv(sbuf[:], uint64(tSweepTerm-runtimeInitTime)/1e6, 3)), "s ",
+			" @", string(itoaDiv(sbuf[:], uint64(work.tSweepTerm-runtimeInitTime)/1e6, 3)), "s ",
 			util, "%: ")
-		prev := tSweepTerm
-		for i, ns := range []int64{tScan, tInstallWB, tMark, tMarkTerm, tEnd} {
+		prev := work.tSweepTerm
+		for i, ns := range []int64{work.tMark, work.tMarkTerm, work.tEnd} {
 			if i != 0 {
 				print("+")
 			}
@@ -1195,8 +1281,8 @@ func gc(mode int) {
 			prev = ns
 		}
 		print(" ms clock, ")
-		for i, ns := range []int64{sweepTermCpu, scanCpu, installWBCpu, gcController.assistTime, gcController.dedicatedMarkTime + gcController.fractionalMarkTime, gcController.idleMarkTime, markTermCpu} {
-			if i == 4 || i == 5 {
+		for i, ns := range []int64{sweepTermCpu, gcController.assistTime, gcController.dedicatedMarkTime + gcController.fractionalMarkTime, gcController.idleMarkTime, markTermCpu} {
+			if i == 2 || i == 3 {
 				// Separate mark time components with /.
 				print("/")
 			} else if i != 0 {
@@ -1205,17 +1291,21 @@ func gc(mode int) {
 			print(string(fmtNSAsMS(sbuf[:], uint64(ns))))
 		}
 		print(" ms cpu, ",
-			heap0>>20, "->", heap1>>20, "->", heap2>>20, " MB, ",
-			heapGoal>>20, " MB goal, ",
-			maxprocs, " P")
-		if mode != gcBackgroundMode {
+			work.heap0>>20, "->", work.heap1>>20, "->", work.heap2>>20, " MB, ",
+			work.heapGoal>>20, " MB goal, ",
+			work.maxprocs, " P")
+		if work.mode != gcBackgroundMode {
 			print(" (forced)")
 		}
 		print("\n")
 		printunlock()
 	}
-	sweep.nbgsweep = 0
-	sweep.npausesweep = 0
+
+	semrelease(&worldsema)
+	// Careful: another GC cycle may start now.
+
+	releasem(mp)
+	mp = nil
 
 	// now that gc is done, kick off finalizer thread if needed
 	if !concurrentSweep {
@@ -1235,7 +1325,7 @@ func gcBgMarkStartWorkers() {
 		if p == nil || p.status == _Pdead {
 			break
 		}
-		if p.gcBgMarkWorker == nil {
+		if p.gcBgMarkWorker == 0 {
 			go gcBgMarkWorker(p)
 			notetsleepg(&work.bgMarkReady, -1)
 			noteclear(&work.bgMarkReady)
@@ -1257,21 +1347,19 @@ func gcBgMarkPrepare() {
 	// there are no workers.
 	work.nproc = ^uint32(0)
 	work.nwait = ^uint32(0)
-
-	// Reset background mark completion points.
-	work.bgMark1.done = 1
-	work.bgMark2.done = 1
 }
 
-func gcBgMarkWorker(p *p) {
-	// Register this G as the background mark worker for p.
-	if p.gcBgMarkWorker != nil {
-		throw("P already has a background mark worker")
+func gcBgMarkWorker(_p_ *p) {
+	type parkInfo struct {
+		m      *m // Release this m on park.
+		attach *p // If non-nil, attach to this p on park.
 	}
-	gp := getg()
+	var park parkInfo
 
-	mp := acquirem()
-	p.gcBgMarkWorker = gp
+	gp := getg()
+	park.m = acquirem()
+	park.attach = _p_
+	// Inform gcBgMarkStartWorkers that this worker is ready.
 	// After this point, the background mark worker is scheduled
 	// cooperatively by gcController.findRunnable. Hence, it must
 	// never be preempted, as this would put it into _Grunnable
@@ -1279,26 +1367,51 @@ func gcBgMarkWorker(p *p) {
 	// is set, this puts itself into _Gwaiting to be woken up by
 	// gcController.findRunnable at the appropriate time.
 	notewakeup(&work.bgMarkReady)
+
 	for {
 		// Go to sleep until woken by gcContoller.findRunnable.
 		// We can't releasem yet since even the call to gopark
 		// may be preempted.
-		gopark(func(g *g, mp unsafe.Pointer) bool {
-			releasem((*m)(mp))
+		gopark(func(g *g, parkp unsafe.Pointer) bool {
+			park := (*parkInfo)(parkp)
+
+			// The worker G is no longer running, so it's
+			// now safe to allow preemption.
+			releasem(park.m)
+
+			// If the worker isn't attached to its P,
+			// attach now. During initialization and after
+			// a phase change, the worker may have been
+			// running on a different P. As soon as we
+			// attach, the owner P may schedule the
+			// worker, so this must be done after the G is
+			// stopped.
+			if park.attach != nil {
+				p := park.attach
+				park.attach = nil
+				// cas the worker because we may be
+				// racing with a new worker starting
+				// on this P.
+				if !p.gcBgMarkWorker.cas(0, guintptr(unsafe.Pointer(g))) {
+					// The P got a new worker.
+					// Exit this worker.
+					return false
+				}
+			}
 			return true
-		}, unsafe.Pointer(mp), "mark worker (idle)", traceEvGoBlock, 0)
+		}, noescape(unsafe.Pointer(&park)), "GC worker (idle)", traceEvGoBlock, 0)
 
 		// Loop until the P dies and disassociates this
-		// worker. (The P may later be reused, in which case
-		// it will get a new worker.)
-		if p.gcBgMarkWorker != gp {
+		// worker (the P may later be reused, in which case
+		// it will get a new worker) or we failed to associate.
+		if _p_.gcBgMarkWorker.ptr() != gp {
 			break
 		}
 
 		// Disable preemption so we can use the gcw. If the
 		// scheduler wants to preempt us, we'll stop draining,
 		// dispose the gcw, and then preempt.
-		mp = acquirem()
+		park.m = acquirem()
 
 		if gcBlackenEnabled == 0 {
 			throw("gcBgMarkWorker: blackening not enabled")
@@ -1306,85 +1419,90 @@ func gcBgMarkWorker(p *p) {
 
 		startTime := nanotime()
 
-		decnwait := xadd(&work.nwait, -1)
+		decnwait := atomic.Xadd(&work.nwait, -1)
 		if decnwait == work.nproc {
 			println("runtime: work.nwait=", decnwait, "work.nproc=", work.nproc)
 			throw("work.nwait was > work.nproc")
 		}
 
-		done := false
-		switch p.gcMarkWorkerMode {
+		switch _p_.gcMarkWorkerMode {
 		default:
 			throw("gcBgMarkWorker: unexpected gcMarkWorkerMode")
 		case gcMarkWorkerDedicatedMode:
-			gcDrain(&p.gcw, gcBgCreditSlack)
-			// gcDrain did the xadd(&work.nwait +1) to
-			// match the decrement above. It only returns
-			// at a mark completion point.
-			done = true
-			if !p.gcw.empty() {
-				throw("gcDrain returned with buffer")
-			}
+			gcDrain(&_p_.gcw, gcDrainNoBlock|gcDrainFlushBgCredit)
 		case gcMarkWorkerFractionalMode, gcMarkWorkerIdleMode:
-			gcDrainUntilPreempt(&p.gcw, gcBgCreditSlack)
-
-			// If we are nearing the end of mark, dispose
-			// of the cache promptly. We must do this
-			// before signaling that we're no longer
-			// working so that other workers can't observe
-			// no workers and no work while we have this
-			// cached, and before we compute done.
-			if gcBlackenPromptly {
-				p.gcw.dispose()
-			}
-
-			// Was this the last worker and did we run out
-			// of work?
-			incnwait := xadd(&work.nwait, +1)
-			if incnwait > work.nproc {
-				println("runtime: p.gcMarkWorkerMode=", p.gcMarkWorkerMode,
-					"work.nwait=", incnwait, "work.nproc=", work.nproc)
-				throw("work.nwait > work.nproc")
-			}
-			done = incnwait == work.nproc && work.full == 0 && work.partial == 0
+			gcDrain(&_p_.gcw, gcDrainUntilPreempt|gcDrainFlushBgCredit)
 		}
 
-		// If this worker reached a background mark completion
-		// point, signal the main GC goroutine.
-		if done {
-			if gcBlackenPromptly {
-				if work.bgMark1.done == 0 {
-					throw("completing mark 2, but bgMark1.done == 0")
-				}
-				work.bgMark2.complete()
-			} else {
-				work.bgMark1.complete()
-			}
+		// If we are nearing the end of mark, dispose
+		// of the cache promptly. We must do this
+		// before signaling that we're no longer
+		// working so that other workers can't observe
+		// no workers and no work while we have this
+		// cached, and before we compute done.
+		if gcBlackenPromptly {
+			_p_.gcw.dispose()
 		}
 
+		// Account for time.
 		duration := nanotime() - startTime
-		switch p.gcMarkWorkerMode {
+		switch _p_.gcMarkWorkerMode {
 		case gcMarkWorkerDedicatedMode:
-			xaddint64(&gcController.dedicatedMarkTime, duration)
-			xaddint64(&gcController.dedicatedMarkWorkersNeeded, 1)
+			atomic.Xaddint64(&gcController.dedicatedMarkTime, duration)
+			atomic.Xaddint64(&gcController.dedicatedMarkWorkersNeeded, 1)
 		case gcMarkWorkerFractionalMode:
-			xaddint64(&gcController.fractionalMarkTime, duration)
-			xaddint64(&gcController.fractionalMarkWorkersNeeded, 1)
+			atomic.Xaddint64(&gcController.fractionalMarkTime, duration)
+			atomic.Xaddint64(&gcController.fractionalMarkWorkersNeeded, 1)
 		case gcMarkWorkerIdleMode:
-			xaddint64(&gcController.idleMarkTime, duration)
+			atomic.Xaddint64(&gcController.idleMarkTime, duration)
+		}
+
+		// Was this the last worker and did we run out
+		// of work?
+		incnwait := atomic.Xadd(&work.nwait, +1)
+		if incnwait > work.nproc {
+			println("runtime: p.gcMarkWorkerMode=", _p_.gcMarkWorkerMode,
+				"work.nwait=", incnwait, "work.nproc=", work.nproc)
+			throw("work.nwait > work.nproc")
+		}
+
+		// If this worker reached a background mark completion
+		// point, signal the main GC goroutine.
+		if incnwait == work.nproc && !gcMarkWorkAvailable(nil) {
+			// Make this G preemptible and disassociate it
+			// as the worker for this P so
+			// findRunnableGCWorker doesn't try to
+			// schedule it.
+			_p_.gcBgMarkWorker.set(nil)
+			releasem(park.m)
+
+			gcMarkDone()
+
+			// Disable preemption and prepare to reattach
+			// to the P.
+			//
+			// We may be running on a different P at this
+			// point, so we can't reattach until this G is
+			// parked.
+			park.m = acquirem()
+			park.attach = _p_
 		}
 	}
 }
 
 // gcMarkWorkAvailable returns true if executing a mark worker
-// on p is potentially useful.
+// on p is potentially useful. p may be nil, in which case it only
+// checks the global sources of work.
 func gcMarkWorkAvailable(p *p) bool {
-	if !p.gcw.empty() {
+	if p != nil && !p.gcw.empty() {
 		return true
 	}
-	if atomicload64(&work.full) != 0 || atomicload64(&work.partial) != 0 {
+	if atomic.Load64(&work.full) != 0 {
 		return true // global work available
 	}
+	if work.markrootNext < work.markrootJobs {
+		return true // root scan work available
+	}
 	return false
 }
 
@@ -1419,6 +1537,9 @@ func gcMark(start_time int64) {
 	// but must be disposed to the global lists immediately.
 	gcFlushGCWork()
 
+	// Queue root marking jobs.
+	gcMarkRootPrepare()
+
 	work.nwait = 0
 	work.ndone = 0
 	work.nproc = uint32(gcprocs())
@@ -1427,32 +1548,32 @@ func gcMark(start_time int64) {
 		traceGCScanStart()
 	}
 
-	parforsetup(work.markfor, work.nproc, uint32(_RootCount+allglen), false, markroot)
 	if work.nproc > 1 {
 		noteclear(&work.alldone)
 		helpgc(int32(work.nproc))
 	}
 
 	gchelperstart()
-	parfordo(work.markfor)
 
 	var gcw gcWork
-	gcDrain(&gcw, -1)
+	gcDrain(&gcw, gcDrainBlock)
 	gcw.dispose()
 
+	gcMarkRootCheck()
 	if work.full != 0 {
 		throw("work.full != 0")
 	}
-	if work.partial != 0 {
-		throw("work.partial != 0")
-	}
 
 	if work.nproc > 1 {
 		notesleep(&work.alldone)
 	}
 
+	// markroot is done now, so record that objects with
+	// finalizers have been scanned.
+	work.finalizersDone = true
+
 	for i := 0; i < int(gomaxprocs); i++ {
-		if allp[i].gcw.wbuf != 0 {
+		if !allp[i].gcw.empty() {
 			throw("P has cached GC work at end of mark termination")
 		}
 	}
@@ -1461,12 +1582,6 @@ func gcMark(start_time int64) {
 		traceGCScanDone()
 	}
 
-	// TODO(austin): This doesn't have to be done during STW, as
-	// long as we block the next GC cycle until this is done. Move
-	// it after we start the world, but before dropping worldsema.
-	// (See issue #11465.)
-	freeStackSpans()
-
 	cachestats()
 
 	// Compute the reachable heap size at the beginning of the
@@ -1476,6 +1591,11 @@ func gcMark(start_time int64) {
 	// is approximately the amount of heap that was allocated
 	// since marking began).
 	allocatedDuringCycle := memstats.heap_live - work.initialHeapLive
+	if memstats.heap_live < work.initialHeapLive {
+		// This can happen if mCentral_UncacheSpan tightens
+		// the heap_live approximation.
+		allocatedDuringCycle = 0
+	}
 	if work.bytesMarked >= allocatedDuringCycle {
 		memstats.heap_reachable = work.bytesMarked - allocatedDuringCycle
 	} else {
@@ -1499,7 +1619,9 @@ func gcMark(start_time int64) {
 		throw("next_gc underflow")
 	}
 
-	// Update other GC heap size stats.
+	// Update other GC heap size stats. This must happen after
+	// cachestats (which flushes local statistics to these) and
+	// flushallmcaches (which modifies heap_live).
 	memstats.heap_live = work.bytesMarked
 	memstats.heap_marked = work.bytesMarked
 	memstats.heap_scan = uint64(gcController.scanWork)
@@ -1525,7 +1647,7 @@ func gcMark(start_time int64) {
 	}
 }
 
-func gcSweep(mode int) {
+func gcSweep(mode gcMode) {
 	if gcphase != _GCoff {
 		throw("gcSweep being done but phase is not GCoff")
 	}
@@ -1554,14 +1676,9 @@ func gcSweep(mode int) {
 		return
 	}
 
-	// Account how much sweeping needs to be done before the next
-	// GC cycle and set up proportional sweep statistics.
-	var pagesToSweep uintptr
-	for _, s := range work.spans {
-		if s.state == mSpanInUse {
-			pagesToSweep += s.npages
-		}
-	}
+	// Concurrent sweep needs to sweep all of the in-use pages by
+	// the time the allocated heap reaches the GC trigger. Compute
+	// the ratio of in-use pages to sweep per byte allocated.
 	heapDistance := int64(memstats.next_gc) - int64(memstats.heap_live)
 	// Add a little margin so rounding errors and concurrent
 	// sweep are less likely to leave pages unswept when GC starts.
@@ -1571,7 +1688,7 @@ func gcSweep(mode int) {
 		heapDistance = _PageSize
 	}
 	lock(&mheap_.lock)
-	mheap_.sweepPagesPerByte = float64(pagesToSweep) / float64(heapDistance)
+	mheap_.sweepPagesPerByte = float64(mheap_.pagesInUse) / float64(heapDistance)
 	mheap_.pagesSwept = 0
 	mheap_.spanBytesAlloc = 0
 	unlock(&mheap_.lock)
@@ -1605,27 +1722,20 @@ func gcCopySpans() {
 	unlock(&mheap_.lock)
 }
 
-// gcResetGState resets the GC state of all G's and returns the length
-// of allgs.
-func gcResetGState() (numgs int) {
+// gcResetMarkState resets global state prior to marking (concurrent
+// or STW) and resets the stack scan state of all Gs. Any Gs created
+// after this will also be in the reset state.
+func gcResetMarkState() {
 	// This may be called during a concurrent phase, so make sure
 	// allgs doesn't change.
 	lock(&allglock)
 	for _, gp := range allgs {
 		gp.gcscandone = false  // set to true in gcphasework
 		gp.gcscanvalid = false // stack has not been scanned
-		gp.gcalloc = 0
-		gp.gcscanwork = 0
+		gp.gcAssistBytes = 0
 	}
-	numgs = len(allgs)
 	unlock(&allglock)
-	return
-}
 
-// gcResetMarkState resets state prior to marking (concurrent or STW).
-//
-// TODO(austin): Merge with gcResetGState. See issue #11427.
-func gcResetMarkState() {
 	work.bytesMarked = 0
 	work.initialHeapLive = memstats.heap_live
 }
@@ -1672,17 +1782,6 @@ func clearpools() {
 		sched.deferpool[i] = nil
 	}
 	unlock(&sched.deferlock)
-
-	for _, p := range &allp {
-		if p == nil {
-			break
-		}
-		// clear tinyalloc pool
-		if c := p.mcache; c != nil {
-			c.tiny = nil
-			c.tinyoffset = 0
-		}
-	}
 }
 
 // Timing
@@ -1697,11 +1796,10 @@ func gchelper() {
 		traceGCScanStart()
 	}
 
-	// parallel mark for over GC roots
-	parfordo(work.markfor)
-	if gcphase != _GCscan {
+	// Parallel mark over GC roots and heap
+	if gcphase == _GCmarktermination {
 		var gcw gcWork
-		gcDrain(&gcw, -1) // blocks in getfull
+		gcDrain(&gcw, gcDrainBlock) // blocks in getfull
 		gcw.dispose()
 	}
 
@@ -1710,7 +1808,7 @@ func gchelper() {
 	}
 
 	nproc := work.nproc // work.nproc can change right after we increment work.ndone
-	if xadd(&work.ndone, +1) == nproc-1 {
+	if atomic.Xadd(&work.ndone, +1) == nproc-1 {
 		notewakeup(&work.alldone)
 	}
 	_g_.m.traceback = 0
diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go
index 151a8bd..eac45ec 100644
--- a/src/runtime/mgcmark.go
+++ b/src/runtime/mgcmark.go
@@ -6,114 +6,139 @@
 
 package runtime
 
-import "unsafe"
-
-// Scan all of the stacks, greying (or graying if in America) the referents
-// but not blackening them since the mark write barrier isn't installed.
+import (
+	"runtime/internal/atomic"
+	"runtime/internal/sys"
+	"unsafe"
+)
+
+const (
+	fixedRootFinalizers = iota
+	fixedRootFlushCaches
+	fixedRootCount
+
+	// rootBlockBytes is the number of bytes to scan per data or
+	// BSS root.
+	rootBlockBytes = 256 << 10
+
+	// rootBlockSpans is the number of spans to scan per span
+	// root.
+	rootBlockSpans = 8 * 1024 // 64MB worth of spans
+)
+
+// gcMarkRootPrepare queues root scanning jobs (stacks, globals, and
+// some miscellany) and initializes scanning-related state.
+//
+// The caller must have call gcCopySpans().
+//
 //go:nowritebarrier
-func gcscan_m() {
-	_g_ := getg()
-
-	// Grab the g that called us and potentially allow rescheduling.
-	// This allows it to be scanned like other goroutines.
-	mastergp := _g_.m.curg
-	casgstatus(mastergp, _Grunning, _Gwaiting)
-	mastergp.waitreason = "garbage collection scan"
-
-	// Span sweeping has been done by finishsweep_m.
-	// Long term we will want to make this goroutine runnable
-	// by placing it onto a scanenqueue state and then calling
-	// runtime·restartg(mastergp) to make it Grunnable.
-	// At the bottom we will want to return this p back to the scheduler.
-
-	// Prepare flag indicating that the scan has not been completed.
-	local_allglen := gcResetGState()
-
-	work.ndone = 0
-	useOneP := uint32(1) // For now do not do this in parallel.
-	//	ackgcphase is not needed since we are not scanning running goroutines.
-	parforsetup(work.markfor, useOneP, uint32(_RootCount+local_allglen), false, markroot)
-	parfordo(work.markfor)
+func gcMarkRootPrepare() {
+	// Compute how many data and BSS root blocks there are.
+	nBlocks := func(bytes uintptr) int {
+		return int((bytes + rootBlockBytes - 1) / rootBlockBytes)
+	}
+
+	work.nDataRoots = 0
+	for datap := &firstmoduledata; datap != nil; datap = datap.next {
+		nDataRoots := nBlocks(datap.edata - datap.data)
+		if nDataRoots > work.nDataRoots {
+			work.nDataRoots = nDataRoots
+		}
+	}
+
+	work.nBSSRoots = 0
+	for datap := &firstmoduledata; datap != nil; datap = datap.next {
+		nBSSRoots := nBlocks(datap.ebss - datap.bss)
+		if nBSSRoots > work.nBSSRoots {
+			work.nBSSRoots = nBSSRoots
+		}
+	}
+
+	// Compute number of span roots.
+	work.nSpanRoots = (len(work.spans) + rootBlockSpans - 1) / rootBlockSpans
+
+	// Snapshot of allglen. During concurrent scan, we just need
+	// to be consistent about how many markroot jobs we create and
+	// how many Gs we check. Gs may be created after this point,
+	// but it's okay that we ignore them because they begin life
+	// without any roots, so there's nothing to scan, and any
+	// roots they create during the concurrent phase will be
+	// scanned during mark termination. During mark termination,
+	// allglen isn't changing, so we'll scan all Gs.
+	work.nStackRoots = int(atomic.Loaduintptr(&allglen))
+
+	work.markrootNext = 0
+	work.markrootJobs = uint32(fixedRootCount + work.nDataRoots + work.nBSSRoots + work.nSpanRoots + work.nStackRoots)
+}
+
+// gcMarkRootCheck checks that all roots have been scanned. It is
+// purely for debugging.
+func gcMarkRootCheck() {
+	if work.markrootNext < work.markrootJobs {
+		print(work.markrootNext, " of ", work.markrootJobs, " markroot jobs done\n")
+		throw("left over markroot jobs")
+	}
 
 	lock(&allglock)
 	// Check that gc work is done.
-	for i := 0; i < local_allglen; i++ {
+	for i := 0; i < work.nStackRoots; i++ {
 		gp := allgs[i]
 		if !gp.gcscandone {
 			throw("scan missed a g")
 		}
 	}
 	unlock(&allglock)
-
-	casgstatus(mastergp, _Gwaiting, _Grunning)
-	// Let the g that called us continue to run.
 }
 
 // ptrmask for an allocation containing a single pointer.
 var oneptrmask = [...]uint8{1}
 
+// markroot scans the i'th root.
+//
+// Preemption must be disabled (because this uses a gcWork).
+//
 //go:nowritebarrier
-func markroot(desc *parfor, i uint32) {
+func markroot(i uint32) {
 	// TODO: Consider using getg().m.p.ptr().gcw.
 	var gcw gcWork
 
+	baseData := uint32(fixedRootCount)
+	baseBSS := baseData + uint32(work.nDataRoots)
+	baseSpans := baseBSS + uint32(work.nBSSRoots)
+	baseStacks := baseSpans + uint32(work.nSpanRoots)
+
 	// Note: if you add a case here, please also update heapdump.go:dumproots.
-	switch i {
-	case _RootData:
+	switch {
+	case baseData <= i && i < baseBSS:
 		for datap := &firstmoduledata; datap != nil; datap = datap.next {
-			scanblock(datap.data, datap.edata-datap.data, datap.gcdatamask.bytedata, &gcw)
+			markrootBlock(datap.data, datap.edata-datap.data, datap.gcdatamask.bytedata, &gcw, int(i-baseData))
 		}
 
-	case _RootBss:
+	case baseBSS <= i && i < baseSpans:
 		for datap := &firstmoduledata; datap != nil; datap = datap.next {
-			scanblock(datap.bss, datap.ebss-datap.bss, datap.gcbssmask.bytedata, &gcw)
+			markrootBlock(datap.bss, datap.ebss-datap.bss, datap.gcbssmask.bytedata, &gcw, int(i-baseBSS))
 		}
 
-	case _RootFinalizers:
+	case i == fixedRootFinalizers:
 		for fb := allfin; fb != nil; fb = fb.alllink {
 			scanblock(uintptr(unsafe.Pointer(&fb.fin[0])), uintptr(fb.cnt)*unsafe.Sizeof(fb.fin[0]), &finptrmask[0], &gcw)
 		}
 
-	case _RootSpans:
-		// mark MSpan.specials
-		sg := mheap_.sweepgen
-		for spanidx := uint32(0); spanidx < uint32(len(work.spans)); spanidx++ {
-			s := work.spans[spanidx]
-			if s.state != mSpanInUse {
-				continue
-			}
-			if !useCheckmark && s.sweepgen != sg {
-				// sweepgen was updated (+2) during non-checkmark GC pass
-				print("sweep ", s.sweepgen, " ", sg, "\n")
-				throw("gc: unswept span")
-			}
-			for sp := s.specials; sp != nil; sp = sp.next {
-				if sp.kind != _KindSpecialFinalizer {
-					continue
-				}
-				// don't mark finalized object, but scan it so we
-				// retain everything it points to.
-				spf := (*specialfinalizer)(unsafe.Pointer(sp))
-				// A finalizer can be set for an inner byte of an object, find object beginning.
-				p := uintptr(s.start<<_PageShift) + uintptr(spf.special.offset)/s.elemsize*s.elemsize
-				if gcphase != _GCscan {
-					scanobject(p, &gcw) // scanned during mark termination
-				}
-				scanblock(uintptr(unsafe.Pointer(&spf.fn)), ptrSize, &oneptrmask[0], &gcw)
-			}
-		}
-
-	case _RootFlushCaches:
-		if gcphase != _GCscan { // Do not flush mcaches during GCscan phase.
+	case i == fixedRootFlushCaches:
+		if gcphase == _GCmarktermination { // Do not flush mcaches during concurrent phase.
 			flushallmcaches()
 		}
 
+	case baseSpans <= i && i < baseStacks:
+		// mark MSpan.specials
+		markrootSpans(&gcw, int(i-baseSpans))
+
 	default:
 		// the rest is scanning goroutine stacks
-		if uintptr(i-_RootCount) >= allglen {
+		if uintptr(i-baseStacks) >= allglen {
 			throw("markroot: bad index")
 		}
-		gp := allgs[i-_RootCount]
+		gp := allgs[i-baseStacks]
 
 		// remember when we've first observed the G blocked
 		// needed only to output in traceback
@@ -130,39 +155,165 @@ func markroot(desc *parfor, i uint32) {
 			shrinkstack(gp)
 		}
 
-		scang(gp)
+		if gcphase != _GCmarktermination && gp.startpc == gcBgMarkWorkerPC {
+			// GC background workers may be
+			// non-preemptible, so we may deadlock if we
+			// try to scan them during a concurrent phase.
+			// They also have tiny stacks, so just ignore
+			// them until mark termination.
+			gp.gcscandone = true
+			break
+		}
+
+		// scang must be done on the system stack in case
+		// we're trying to scan our own stack.
+		systemstack(func() {
+			// If this is a self-scan, put the user G in
+			// _Gwaiting to prevent self-deadlock. It may
+			// already be in _Gwaiting if this is mark
+			// termination.
+			userG := getg().m.curg
+			selfScan := gp == userG && readgstatus(userG) == _Grunning
+			if selfScan {
+				casgstatus(userG, _Grunning, _Gwaiting)
+				userG.waitreason = "garbage collection scan"
+			}
+
+			// TODO: scang blocks until gp's stack has
+			// been scanned, which may take a while for
+			// running goroutines. Consider doing this in
+			// two phases where the first is non-blocking:
+			// we scan the stacks we can and ask running
+			// goroutines to scan themselves; and the
+			// second blocks.
+			scang(gp)
+
+			if selfScan {
+				casgstatus(userG, _Gwaiting, _Grunning)
+			}
+		})
 	}
 
 	gcw.dispose()
 }
 
-// gcAssistAlloc records and allocation of size bytes and, if
-// allowAssist is true, may assist GC scanning in proportion to the
-// allocations performed by this mutator since the last assist.
-//
-// It should only be called if gcAssistAlloc != 0.
+// markrootBlock scans the shard'th shard of the block of memory [b0,
+// b0+n0), with the given pointer mask.
 //
-// This must be called with preemption disabled.
 //go:nowritebarrier
-func gcAssistAlloc(size uintptr, allowAssist bool) {
-	// Find the G responsible for this assist.
-	gp := getg()
-	if gp.m.curg != nil {
-		gp = gp.m.curg
+func markrootBlock(b0, n0 uintptr, ptrmask0 *uint8, gcw *gcWork, shard int) {
+	if rootBlockBytes%(8*sys.PtrSize) != 0 {
+		// This is necessary to pick byte offsets in ptrmask0.
+		throw("rootBlockBytes must be a multiple of 8*ptrSize")
 	}
 
-	// Record allocation.
-	if gp.gcalloc+size < gp.gcalloc {
-		// gcalloc would overflow, or it's set to a sentinel
-		// value to prevent recursive assist.
+	b := b0 + uintptr(shard)*rootBlockBytes
+	if b >= b0+n0 {
 		return
 	}
-	gp.gcalloc += size
+	ptrmask := (*uint8)(add(unsafe.Pointer(ptrmask0), uintptr(shard)*(rootBlockBytes/(8*sys.PtrSize))))
+	n := uintptr(rootBlockBytes)
+	if b+n > b0+n0 {
+		n = b0 + n0 - b
+	}
+
+	// Scan this shard.
+	scanblock(b, n, ptrmask, gcw)
+}
 
-	if !allowAssist {
+// markrootSpans marks roots for one shard of work.spans.
+//
+//go:nowritebarrier
+func markrootSpans(gcw *gcWork, shard int) {
+	// Objects with finalizers have two GC-related invariants:
+	//
+	// 1) Everything reachable from the object must be marked.
+	// This ensures that when we pass the object to its finalizer,
+	// everything the finalizer can reach will be retained.
+	//
+	// 2) Finalizer specials (which are not in the garbage
+	// collected heap) are roots. In practice, this means the fn
+	// field must be scanned.
+	//
+	// TODO(austin): There are several ideas for making this more
+	// efficient in issue #11485.
+
+	// We process objects with finalizers only during the first
+	// markroot pass. In concurrent GC, this happens during
+	// concurrent scan and we depend on addfinalizer to ensure the
+	// above invariants for objects that get finalizers after
+	// concurrent scan. In STW GC, this will happen during mark
+	// termination.
+	if work.finalizersDone {
 		return
 	}
 
+	sg := mheap_.sweepgen
+	startSpan := shard * rootBlockSpans
+	endSpan := (shard + 1) * rootBlockSpans
+	if endSpan > len(work.spans) {
+		endSpan = len(work.spans)
+	}
+	// Note that work.spans may not include spans that were
+	// allocated between entering the scan phase and now. This is
+	// okay because any objects with finalizers in those spans
+	// must have been allocated and given finalizers after we
+	// entered the scan phase, so addfinalizer will have ensured
+	// the above invariants for them.
+	for _, s := range work.spans[startSpan:endSpan] {
+		if s.state != mSpanInUse {
+			continue
+		}
+		if !useCheckmark && s.sweepgen != sg {
+			// sweepgen was updated (+2) during non-checkmark GC pass
+			print("sweep ", s.sweepgen, " ", sg, "\n")
+			throw("gc: unswept span")
+		}
+
+		// Speculatively check if there are any specials
+		// without acquiring the span lock. This may race with
+		// adding the first special to a span, but in that
+		// case addfinalizer will observe that the GC is
+		// active (which is globally synchronized) and ensure
+		// the above invariants. We may also ensure the
+		// invariants, but it's okay to scan an object twice.
+		if s.specials == nil {
+			continue
+		}
+
+		// Lock the specials to prevent a special from being
+		// removed from the list while we're traversing it.
+		lock(&s.speciallock)
+
+		for sp := s.specials; sp != nil; sp = sp.next {
+			if sp.kind != _KindSpecialFinalizer {
+				continue
+			}
+			// don't mark finalized object, but scan it so we
+			// retain everything it points to.
+			spf := (*specialfinalizer)(unsafe.Pointer(sp))
+			// A finalizer can be set for an inner byte of an object, find object beginning.
+			p := uintptr(s.start<<_PageShift) + uintptr(spf.special.offset)/s.elemsize*s.elemsize
+
+			// Mark everything that can be reached from
+			// the object (but *not* the object itself or
+			// we'll never collect it).
+			scanobject(p, gcw)
+
+			// The special itself is a root.
+			scanblock(uintptr(unsafe.Pointer(&spf.fn)), sys.PtrSize, &oneptrmask[0], gcw)
+		}
+
+		unlock(&s.speciallock)
+	}
+}
+
+// gcAssistAlloc performs GC work to make gp's assist debt positive.
+// gp must be the calling user gorountine.
+//
+// This must be called with preemption enabled.
+//go:nowritebarrier
+func gcAssistAlloc(gp *g) {
 	// Don't assist in non-preemptible contexts. These are
 	// generally fragile and won't allow the assist to block.
 	if getg() == gp.m.g0 {
@@ -172,13 +323,11 @@ func gcAssistAlloc(size uintptr, allowAssist bool) {
 		return
 	}
 
-	// Compute the amount of assist scan work we need to do.
-	scanWork := int64(gcController.assistRatio*float64(gp.gcalloc)) - gp.gcscanwork
-	// scanWork can be negative if the last assist scanned a large
-	// object and we're still ahead of our assist goal.
-	if scanWork <= 0 {
-		return
-	}
+	// Compute the amount of scan work we need to do to make the
+	// balance positive. We over-assist to build up credit for
+	// future allocations and amortize the cost of assisting.
+	debtBytes := -gp.gcAssistBytes + gcOverAssistBytes
+	scanWork := int64(gcController.assistWorkPerByte * float64(debtBytes))
 
 retry:
 	// Steal as much credit as we can from the background GC's
@@ -187,20 +336,23 @@ retry:
 	// will just cause steals to fail until credit is accumulated
 	// again, so in the long run it doesn't really matter, but we
 	// do have to handle the negative credit case.
-	bgScanCredit := atomicloadint64(&gcController.bgScanCredit)
+	bgScanCredit := atomic.Loadint64(&gcController.bgScanCredit)
 	stolen := int64(0)
 	if bgScanCredit > 0 {
 		if bgScanCredit < scanWork {
 			stolen = bgScanCredit
+			gp.gcAssistBytes += 1 + int64(gcController.assistBytesPerWork*float64(stolen))
 		} else {
 			stolen = scanWork
+			gp.gcAssistBytes += debtBytes
 		}
-		xaddint64(&gcController.bgScanCredit, -stolen)
+		atomic.Xaddint64(&gcController.bgScanCredit, -stolen)
 
 		scanWork -= stolen
-		gp.gcscanwork += stolen
 
 		if scanWork == 0 {
+			// We were able to steal all of the credit we
+			// needed.
 			return
 		}
 	}
@@ -208,7 +360,7 @@ retry:
 	// Perform assist work
 	completed := false
 	systemstack(func() {
-		if atomicload(&gcBlackenEnabled) == 0 {
+		if atomic.Load(&gcBlackenEnabled) == 0 {
 			// The gcBlackenEnabled check in malloc races with the
 			// store that clears it but an atomic check in every malloc
 			// would be a performance hit.
@@ -216,7 +368,7 @@ retry:
 			// stack to determine if we should preform an assist.
 
 			// GC is done, so ignore any remaining debt.
-			scanWork = 0
+			gp.gcAssistBytes = 0
 			return
 		}
 		// Track time spent in this assist. Since we're on the
@@ -224,7 +376,7 @@ retry:
 		// just measure start and end time.
 		startTime := nanotime()
 
-		decnwait := xadd(&work.nwait, -1)
+		decnwait := atomic.Xadd(&work.nwait, -1)
 		if decnwait == work.nproc {
 			println("runtime: work.nwait =", decnwait, "work.nproc=", work.nproc)
 			throw("nwait > work.nprocs")
@@ -233,20 +385,24 @@ retry:
 		// drain own cached work first in the hopes that it
 		// will be more cache friendly.
 		gcw := &getg().m.p.ptr().gcw
-		startScanWork := gcw.scanWork
-		gcDrainN(gcw, scanWork)
-		// Record that we did this much scan work.
-		workDone := gcw.scanWork - startScanWork
-		gp.gcscanwork += workDone
-		scanWork -= workDone
+		workDone := gcDrainN(gcw, scanWork)
 		// If we are near the end of the mark phase
 		// dispose of the gcw.
 		if gcBlackenPromptly {
 			gcw.dispose()
 		}
+
+		// Record that we did this much scan work.
+		//
+		// Back out the number of bytes of assist credit that
+		// this scan work counts for. The "1+" is a poor man's
+		// round-up, to ensure this adds credit even if
+		// assistBytesPerWork is very low.
+		gp.gcAssistBytes += 1 + int64(gcController.assistBytesPerWork*float64(workDone))
+
 		// If this is the last worker and we ran out of work,
 		// signal a completion point.
-		incnwait := xadd(&work.nwait, +1)
+		incnwait := atomic.Xadd(&work.nwait, +1)
 		if incnwait > work.nproc {
 			println("runtime: work.nwait=", incnwait,
 				"work.nproc=", work.nproc,
@@ -254,59 +410,165 @@ retry:
 			throw("work.nwait > work.nproc")
 		}
 
-		if incnwait == work.nproc && work.full == 0 && work.partial == 0 {
+		if incnwait == work.nproc && !gcMarkWorkAvailable(nil) {
 			// This has reached a background completion
 			// point.
-			if gcBlackenPromptly {
-				if work.bgMark1.done == 0 {
-					throw("completing mark 2, but bgMark1.done == 0")
-				}
-				work.bgMark2.complete()
-			} else {
-				work.bgMark1.complete()
-			}
 			completed = true
 		}
 		duration := nanotime() - startTime
 		_p_ := gp.m.p.ptr()
 		_p_.gcAssistTime += duration
 		if _p_.gcAssistTime > gcAssistTimeSlack {
-			xaddint64(&gcController.assistTime, _p_.gcAssistTime)
+			atomic.Xaddint64(&gcController.assistTime, _p_.gcAssistTime)
 			_p_.gcAssistTime = 0
 		}
 	})
 
 	if completed {
-		// We called complete() above, so we should yield to
-		// the now-runnable GC coordinator.
-		Gosched()
-
-		// It's likely that this assist wasn't able to pay off
-		// its debt, but it's also likely that the Gosched let
-		// the GC finish this cycle and there's no point in
-		// waiting. If the GC finished, skip the delay below.
-		if atomicload(&gcBlackenEnabled) == 0 {
-			scanWork = 0
-		}
+		gcMarkDone()
 	}
 
-	if scanWork > 0 {
+	if gp.gcAssistBytes < 0 {
 		// We were unable steal enough credit or perform
 		// enough work to pay off the assist debt. We need to
 		// do one of these before letting the mutator allocate
-		// more, so go around again after performing an
-		// interruptible sleep for 100 us (the same as the
-		// getfull barrier) to let other mutators run.
-
-		// timeSleep may allocate, so avoid recursive assist.
-		gcalloc := gp.gcalloc
-		gp.gcalloc = ^uintptr(0)
-		timeSleep(100 * 1000)
-		gp.gcalloc = gcalloc
-		goto retry
+		// more to prevent over-allocation.
+		//
+		// If this is because we were preempted, reschedule
+		// and try some more.
+		if gp.preempt {
+			Gosched()
+			goto retry
+		}
+
+		// Add this G to an assist queue and park. When the GC
+		// has more background credit, it will satisfy queued
+		// assists before flushing to the global credit pool.
+		//
+		// Note that this does *not* get woken up when more
+		// work is added to the work list. The theory is that
+		// there wasn't enough work to do anyway, so we might
+		// as well let background marking take care of the
+		// work that is available.
+		lock(&work.assistQueue.lock)
+
+		// If the GC cycle is over, just return. This is the
+		// likely path if we completed above. We do this
+		// under the lock to prevent a GC cycle from ending
+		// between this check and queuing the assist.
+		if atomic.Load(&gcBlackenEnabled) == 0 {
+			unlock(&work.assistQueue.lock)
+			return
+		}
+
+		oldHead, oldTail := work.assistQueue.head, work.assistQueue.tail
+		if oldHead == 0 {
+			work.assistQueue.head.set(gp)
+		} else {
+			oldTail.ptr().schedlink.set(gp)
+		}
+		work.assistQueue.tail.set(gp)
+		gp.schedlink.set(nil)
+		// Recheck for background credit now that this G is in
+		// the queue, but can still back out. This avoids a
+		// race in case background marking has flushed more
+		// credit since we checked above.
+		if atomic.Loadint64(&gcController.bgScanCredit) > 0 {
+			work.assistQueue.head = oldHead
+			work.assistQueue.tail = oldTail
+			if oldTail != 0 {
+				oldTail.ptr().schedlink.set(nil)
+			}
+			unlock(&work.assistQueue.lock)
+			goto retry
+		}
+		// Park for real.
+		goparkunlock(&work.assistQueue.lock, "GC assist wait", traceEvGoBlock, 2)
+
+		// At this point either background GC has satisfied
+		// this G's assist debt, or the GC cycle is over.
 	}
 }
 
+// gcWakeAllAssists wakes all currently blocked assists. This is used
+// at the end of a GC cycle. gcBlackenEnabled must be false to prevent
+// new assists from going to sleep after this point.
+func gcWakeAllAssists() {
+	lock(&work.assistQueue.lock)
+	injectglist(work.assistQueue.head.ptr())
+	work.assistQueue.head.set(nil)
+	work.assistQueue.tail.set(nil)
+	unlock(&work.assistQueue.lock)
+}
+
+// gcFlushBgCredit flushes scanWork units of background scan work
+// credit. This first satisfies blocked assists on the
+// work.assistQueue and then flushes any remaining credit to
+// gcController.bgScanCredit.
+//
+// Write barriers are disallowed because this is used by gcDrain after
+// it has ensured that all work is drained and this must preserve that
+// condition.
+//
+//go:nowritebarrierrec
+func gcFlushBgCredit(scanWork int64) {
+	if work.assistQueue.head == 0 {
+		// Fast path; there are no blocked assists. There's a
+		// small window here where an assist may add itself to
+		// the blocked queue and park. If that happens, we'll
+		// just get it on the next flush.
+		atomic.Xaddint64(&gcController.bgScanCredit, scanWork)
+		return
+	}
+
+	scanBytes := int64(float64(scanWork) * gcController.assistBytesPerWork)
+
+	lock(&work.assistQueue.lock)
+	gp := work.assistQueue.head.ptr()
+	for gp != nil && scanBytes > 0 {
+		// Note that gp.gcAssistBytes is negative because gp
+		// is in debt. Think carefully about the signs below.
+		if scanBytes+gp.gcAssistBytes >= 0 {
+			// Satisfy this entire assist debt.
+			scanBytes += gp.gcAssistBytes
+			gp.gcAssistBytes = 0
+			xgp := gp
+			gp = gp.schedlink.ptr()
+			ready(xgp, 0)
+		} else {
+			// Partially satisfy this assist.
+			gp.gcAssistBytes += scanBytes
+			scanBytes = 0
+			// As a heuristic, we move this assist to the
+			// back of the queue so that large assists
+			// can't clog up the assist queue and
+			// substantially delay small assists.
+			xgp := gp
+			gp = gp.schedlink.ptr()
+			if gp == nil {
+				// gp is the only assist in the queue.
+				gp = xgp
+			} else {
+				xgp.schedlink = 0
+				work.assistQueue.tail.ptr().schedlink.set(xgp)
+				work.assistQueue.tail.set(xgp)
+			}
+			break
+		}
+	}
+	work.assistQueue.head.set(gp)
+	if gp == nil {
+		work.assistQueue.tail.set(nil)
+	}
+
+	if scanBytes > 0 {
+		// Convert from scan bytes back to work.
+		scanWork = int64(float64(scanBytes) * gcController.assistWorkPerByte)
+		atomic.Xaddint64(&gcController.bgScanCredit, scanWork)
+	}
+	unlock(&work.assistQueue.lock)
+}
+
 //go:nowritebarrier
 func scanstack(gp *g) {
 	if gp.gcscanvalid {
@@ -349,7 +611,7 @@ func scanstack(gp *g) {
 		sp = gp.sched.sp
 	}
 	switch gcphase {
-	case _GCscan:
+	case _GCmark:
 		// Install stack barriers during stack scan.
 		barrierOffset = uintptr(firstStackBarrierOffset)
 		nextBarrier = sp + barrierOffset
@@ -375,7 +637,7 @@ func scanstack(gp *g) {
 		} else {
 			// Only re-scan up to the lowest un-hit
 			// barrier. Any frames above this have not
-			// executed since the _GCscan scan of gp and
+			// executed since the concurrent scan of gp and
 			// any writes through up-pointers to above
 			// this barrier had write barriers.
 			nextBarrier = gp.stkbar[gp.stkbarPos].savedLRPtr
@@ -390,16 +652,17 @@ func scanstack(gp *g) {
 		throw("scanstack in wrong phase")
 	}
 
+	var cache pcvalueCache
 	gcw := &getg().m.p.ptr().gcw
 	n := 0
 	scanframe := func(frame *stkframe, unused unsafe.Pointer) bool {
-		scanframeworker(frame, unused, gcw)
+		scanframeworker(frame, &cache, gcw)
 
 		if frame.fp > nextBarrier {
 			// We skip installing a barrier on bottom-most
 			// frame because on LR machines this LR is not
 			// on the stack.
-			if gcphase == _GCscan && n != 0 {
+			if gcphase == _GCmark && n != 0 {
 				if gcInstallStackBarrier(gp, frame) {
 					barrierOffset *= 2
 					nextBarrier = sp + barrierOffset
@@ -421,7 +684,7 @@ func scanstack(gp *g) {
 	if gcphase == _GCmarktermination {
 		gcw.dispose()
 	}
-	if gcphase == _GCscan {
+	if gcphase == _GCmark {
 		gcUnlockStackBarriers(gp)
 	}
 	gp.gcscanvalid = true
@@ -429,7 +692,7 @@ func scanstack(gp *g) {
 
 // Scan a stack frame: local variables and function arguments/results.
 //go:nowritebarrier
-func scanframeworker(frame *stkframe, unused unsafe.Pointer, gcw *gcWork) {
+func scanframeworker(frame *stkframe, cache *pcvalueCache, gcw *gcWork) {
 
 	f := frame.fn
 	targetpc := frame.continpc
@@ -443,7 +706,7 @@ func scanframeworker(frame *stkframe, unused unsafe.Pointer, gcw *gcWork) {
 	if targetpc != f.entry {
 		targetpc--
 	}
-	pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc)
+	pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, cache)
 	if pcdata == -1 {
 		// We do not have a valid pcdata value but there might be a
 		// stackmap for this function.  It is likely that we are looking
@@ -454,13 +717,11 @@ func scanframeworker(frame *stkframe, unused unsafe.Pointer, gcw *gcWork) {
 	// Scan local variables if stack frame has been allocated.
 	size := frame.varp - frame.sp
 	var minsize uintptr
-	switch thechar {
-	case '6', '8':
-		minsize = 0
+	switch sys.TheChar {
 	case '7':
-		minsize = spAlign
+		minsize = sys.SpAlign
 	default:
-		minsize = ptrSize
+		minsize = sys.MinFrameSize
 	}
 	if size > minsize {
 		stkmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
@@ -476,7 +737,7 @@ func scanframeworker(frame *stkframe, unused unsafe.Pointer, gcw *gcWork) {
 			throw("scanframe: bad symbol table")
 		}
 		bv := stackmapdata(stkmap, pcdata)
-		size = uintptr(bv.n) * ptrSize
+		size = uintptr(bv.n) * sys.PtrSize
 		scanblock(frame.varp-size, size, bv.bytedata, gcw)
 	}
 
@@ -498,345 +759,159 @@ func scanframeworker(frame *stkframe, unused unsafe.Pointer, gcw *gcWork) {
 			}
 			bv = stackmapdata(stkmap, pcdata)
 		}
-		scanblock(frame.argp, uintptr(bv.n)*ptrSize, bv.bytedata, gcw)
-	}
-}
-
-// gcMaxStackBarriers returns the maximum number of stack barriers
-// that can be installed in a stack of stackSize bytes.
-func gcMaxStackBarriers(stackSize int) (n int) {
-	if firstStackBarrierOffset == 0 {
-		// Special debugging case for inserting stack barriers
-		// at every frame. Steal half of the stack for the
-		// []stkbar. Technically, if the stack were to consist
-		// solely of return PCs we would need two thirds of
-		// the stack, but stealing that much breaks things and
-		// this doesn't happen in practice.
-		return stackSize / 2 / int(unsafe.Sizeof(stkbar{}))
-	}
-
-	offset := firstStackBarrierOffset
-	for offset < stackSize {
-		n++
-		offset *= 2
-	}
-	return n + 1
-}
-
-// gcInstallStackBarrier installs a stack barrier over the return PC of frame.
-//go:nowritebarrier
-func gcInstallStackBarrier(gp *g, frame *stkframe) bool {
-	if frame.lr == 0 {
-		if debugStackBarrier {
-			print("not installing stack barrier with no LR, goid=", gp.goid, "\n")
-		}
-		return false
-	}
-
-	if frame.fn.entry == cgocallback_gofuncPC {
-		// cgocallback_gofunc doesn't return to its LR;
-		// instead, its return path puts LR in g.sched.pc and
-		// switches back to the system stack on which
-		// cgocallback_gofunc was originally called. We can't
-		// have a stack barrier in g.sched.pc, so don't
-		// install one in this frame.
-		if debugStackBarrier {
-			print("not installing stack barrier over LR of cgocallback_gofunc, goid=", gp.goid, "\n")
-		}
-		return false
-	}
-
-	// Save the return PC and overwrite it with stackBarrier.
-	var lrUintptr uintptr
-	if usesLR {
-		lrUintptr = frame.sp
-	} else {
-		lrUintptr = frame.fp - regSize
-	}
-	lrPtr := (*uintreg)(unsafe.Pointer(lrUintptr))
-	if debugStackBarrier {
-		print("install stack barrier at ", hex(lrUintptr), " over ", hex(*lrPtr), ", goid=", gp.goid, "\n")
-		if uintptr(*lrPtr) != frame.lr {
-			print("frame.lr=", hex(frame.lr))
-			throw("frame.lr differs from stack LR")
-		}
+		scanblock(frame.argp, uintptr(bv.n)*sys.PtrSize, bv.bytedata, gcw)
 	}
-
-	gp.stkbar = gp.stkbar[:len(gp.stkbar)+1]
-	stkbar := &gp.stkbar[len(gp.stkbar)-1]
-	stkbar.savedLRPtr = lrUintptr
-	stkbar.savedLRVal = uintptr(*lrPtr)
-	*lrPtr = uintreg(stackBarrierPC)
-	return true
 }
 
-// gcRemoveStackBarriers removes all stack barriers installed in gp's stack.
-//go:nowritebarrier
-func gcRemoveStackBarriers(gp *g) {
-	if debugStackBarrier && gp.stkbarPos != 0 {
-		print("hit ", gp.stkbarPos, " stack barriers, goid=", gp.goid, "\n")
-	}
+type gcDrainFlags int
 
-	gcLockStackBarriers(gp)
+const (
+	gcDrainUntilPreempt gcDrainFlags = 1 << iota
+	gcDrainNoBlock
+	gcDrainFlushBgCredit
 
-	// Remove stack barriers that we didn't hit.
-	for _, stkbar := range gp.stkbar[gp.stkbarPos:] {
-		gcRemoveStackBarrier(gp, stkbar)
-	}
-
-	// Clear recorded stack barriers so copystack doesn't try to
-	// adjust them.
-	gp.stkbarPos = 0
-	gp.stkbar = gp.stkbar[:0]
-
-	gcUnlockStackBarriers(gp)
-}
+	// gcDrainBlock means neither gcDrainUntilPreempt or
+	// gcDrainNoBlock. It is the default, but callers should use
+	// the constant for documentation purposes.
+	gcDrainBlock gcDrainFlags = 0
+)
 
-// gcRemoveStackBarrier removes a single stack barrier. It is the
-// inverse operation of gcInstallStackBarrier.
+// gcDrain scans roots and objects in work buffers, blackening grey
+// objects until all roots and work buffers have been drained.
 //
-// This is nosplit to ensure gp's stack does not move.
+// If flags&gcDrainUntilPreempt != 0, gcDrain returns when g.preempt
+// is set. This implies gcDrainNoBlock.
 //
-//go:nowritebarrier
-//go:nosplit
-func gcRemoveStackBarrier(gp *g, stkbar stkbar) {
-	if debugStackBarrier {
-		print("remove stack barrier at ", hex(stkbar.savedLRPtr), " with ", hex(stkbar.savedLRVal), ", goid=", gp.goid, "\n")
-	}
-	lrPtr := (*uintreg)(unsafe.Pointer(stkbar.savedLRPtr))
-	if val := *lrPtr; val != uintreg(stackBarrierPC) {
-		printlock()
-		print("at *", hex(stkbar.savedLRPtr), " expected stack barrier PC ", hex(stackBarrierPC), ", found ", hex(val), ", goid=", gp.goid, "\n")
-		print("gp.stkbar=")
-		gcPrintStkbars(gp, -1)
-		print(", gp.stack=[", hex(gp.stack.lo), ",", hex(gp.stack.hi), ")\n")
-		throw("stack barrier lost")
-	}
-	*lrPtr = uintreg(stkbar.savedLRVal)
-}
-
-// gcPrintStkbars prints the stack barriers of gp for debugging. It
-// places a "@@@" marker at gp.stkbarPos. If marker >= 0, it will also
-// place a "==>" marker before the marker'th entry.
-func gcPrintStkbars(gp *g, marker int) {
-	print("[")
-	for i, s := range gp.stkbar {
-		if i > 0 {
-			print(" ")
-		}
-		if i == int(gp.stkbarPos) {
-			print("@@@ ")
-		}
-		if i == marker {
-			print("==> ")
-		}
-		print("*", hex(s.savedLRPtr), "=", hex(s.savedLRVal))
-	}
-	if int(gp.stkbarPos) == len(gp.stkbar) {
-		print(" @@@")
-	}
-	if marker == len(gp.stkbar) {
-		print(" ==>")
-	}
-	print("]")
-}
-
-// gcUnwindBarriers marks all stack barriers up the frame containing
-// sp as hit and removes them. This is used during stack unwinding for
-// panic/recover and by heapBitsBulkBarrier to force stack re-scanning
-// when its destination is on the stack.
+// If flags&gcDrainNoBlock != 0, gcDrain returns as soon as it is
+// unable to get more work. Otherwise, it will block until all
+// blocking calls are blocked in gcDrain.
 //
-// This is nosplit to ensure gp's stack does not move.
+// If flags&gcDrainFlushBgCredit != 0, gcDrain flushes scan work
+// credit to gcController.bgScanCredit every gcCreditSlack units of
+// scan work.
 //
-//go:nosplit
-func gcUnwindBarriers(gp *g, sp uintptr) {
-	gcLockStackBarriers(gp)
-	// On LR machines, if there is a stack barrier on the return
-	// from the frame containing sp, this will mark it as hit even
-	// though it isn't, but it's okay to be conservative.
-	before := gp.stkbarPos
-	for int(gp.stkbarPos) < len(gp.stkbar) && gp.stkbar[gp.stkbarPos].savedLRPtr < sp {
-		gcRemoveStackBarrier(gp, gp.stkbar[gp.stkbarPos])
-		gp.stkbarPos++
-	}
-	gcUnlockStackBarriers(gp)
-	if debugStackBarrier && gp.stkbarPos != before {
-		print("skip barriers below ", hex(sp), " in goid=", gp.goid, ": ")
-		// We skipped barriers between the "==>" marker
-		// (before) and the "@@@" marker (gp.stkbarPos).
-		gcPrintStkbars(gp, int(before))
-		print("\n")
-	}
-}
-
-// nextBarrierPC returns the original return PC of the next stack barrier.
-// Used by getcallerpc, so it must be nosplit.
-//go:nosplit
-func nextBarrierPC() uintptr {
-	gp := getg()
-	return gp.stkbar[gp.stkbarPos].savedLRVal
-}
-
-// setNextBarrierPC sets the return PC of the next stack barrier.
-// Used by setcallerpc, so it must be nosplit.
-//go:nosplit
-func setNextBarrierPC(pc uintptr) {
-	gp := getg()
-	gp.stkbar[gp.stkbarPos].savedLRVal = pc
-}
-
-// gcLockStackBarriers synchronizes with tracebacks of gp's stack
-// during sigprof for installation or removal of stack barriers. It
-// blocks until any current sigprof is done tracebacking gp's stack
-// and then disallows profiling tracebacks of gp's stack.
-//
-// This is necessary because a sigprof during barrier installation or
-// removal could observe inconsistencies between the stkbar array and
-// the stack itself and crash.
-func gcLockStackBarriers(gp *g) {
-	for !cas(&gp.stackLock, 0, 1) {
-		osyield()
-	}
-}
-
-func gcTryLockStackBarriers(gp *g) bool {
-	return cas(&gp.stackLock, 0, 1)
-}
-
-func gcUnlockStackBarriers(gp *g) {
-	atomicstore(&gp.stackLock, 0)
-}
-
-// TODO(austin): Can we consolidate the gcDrain* functions?
-
-// gcDrain scans objects in work buffers, blackening grey
-// objects until all work buffers have been drained.
-// If flushScanCredit != -1, gcDrain flushes accumulated scan work
-// credit to gcController.bgScanCredit whenever gcw's local scan work
-// credit exceeds flushScanCredit.
 //go:nowritebarrier
-func gcDrain(gcw *gcWork, flushScanCredit int64) {
-	if !writeBarrierEnabled {
+func gcDrain(gcw *gcWork, flags gcDrainFlags) {
+	if !writeBarrier.needed {
 		throw("gcDrain phase incorrect")
 	}
 
-	var lastScanFlush, nextScanFlush int64
-	if flushScanCredit != -1 {
-		lastScanFlush = gcw.scanWork
-		nextScanFlush = lastScanFlush + flushScanCredit
-	} else {
-		nextScanFlush = int64(^uint64(0) >> 1)
+	gp := getg()
+	preemptible := flags&gcDrainUntilPreempt != 0
+	blocking := flags&(gcDrainUntilPreempt|gcDrainNoBlock) == 0
+	flushBgCredit := flags&gcDrainFlushBgCredit != 0
+
+	// Drain root marking jobs.
+	if work.markrootNext < work.markrootJobs {
+		for blocking || !gp.preempt {
+			job := atomic.Xadd(&work.markrootNext, +1) - 1
+			if job >= work.markrootJobs {
+				break
+			}
+			// TODO: Pass in gcw.
+			markroot(job)
+		}
 	}
 
-	for {
-		// If another proc wants a pointer, give it some.
-		if work.nwait > 0 && work.full == 0 {
+	initScanWork := gcw.scanWork
+
+	// Drain heap marking jobs.
+	for !(preemptible && gp.preempt) {
+		// Try to keep work available on the global queue. We used to
+		// check if there were waiting workers, but it's better to
+		// just keep work available than to make workers wait. In the
+		// worst case, we'll do O(log(_WorkbufSize)) unnecessary
+		// balances.
+		if work.full == 0 {
 			gcw.balance()
 		}
 
-		b := gcw.get()
+		var b uintptr
+		if blocking {
+			b = gcw.get()
+		} else {
+			b = gcw.tryGet()
+		}
 		if b == 0 {
-			// work barrier reached
+			// work barrier reached or tryGet failed.
 			break
 		}
-		// If the current wbuf is filled by the scan a new wbuf might be
-		// returned that could possibly hold only a single object. This
-		// could result in each iteration draining only a single object
-		// out of the wbuf passed in + a single object placed
-		// into an empty wbuf in scanobject so there could be
-		// a performance hit as we keep fetching fresh wbufs.
 		scanobject(b, gcw)
 
 		// Flush background scan work credit to the global
 		// account if we've accumulated enough locally so
 		// mutator assists can draw on it.
-		if gcw.scanWork >= nextScanFlush {
-			credit := gcw.scanWork - lastScanFlush
-			xaddint64(&gcController.bgScanCredit, credit)
-			lastScanFlush = gcw.scanWork
-			nextScanFlush = lastScanFlush + flushScanCredit
+		if gcw.scanWork >= gcCreditSlack {
+			atomic.Xaddint64(&gcController.scanWork, gcw.scanWork)
+			if flushBgCredit {
+				gcFlushBgCredit(gcw.scanWork - initScanWork)
+				initScanWork = 0
+			}
+			gcw.scanWork = 0
 		}
 	}
-	if flushScanCredit != -1 {
-		credit := gcw.scanWork - lastScanFlush
-		xaddint64(&gcController.bgScanCredit, credit)
-	}
-}
 
-// gcDrainUntilPreempt blackens grey objects until g.preempt is set.
-// This is best-effort, so it will return as soon as it is unable to
-// get work, even though there may be more work in the system.
-//go:nowritebarrier
-func gcDrainUntilPreempt(gcw *gcWork, flushScanCredit int64) {
-	if !writeBarrierEnabled {
-		println("gcphase =", gcphase)
-		throw("gcDrainUntilPreempt phase incorrect")
-	}
+	// In blocking mode, write barriers are not allowed after this
+	// point because we must preserve the condition that the work
+	// buffers are empty.
 
-	var lastScanFlush, nextScanFlush int64
-	if flushScanCredit != -1 {
-		lastScanFlush = gcw.scanWork
-		nextScanFlush = lastScanFlush + flushScanCredit
-	} else {
-		nextScanFlush = int64(^uint64(0) >> 1)
-	}
-
-	gp := getg()
-	for !gp.preempt {
-		// If the work queue is empty, balance. During
-		// concurrent mark we don't really know if anyone else
-		// can make use of this work, but even if we're the
-		// only worker, the total cost of this per cycle is
-		// only O(_WorkbufSize) pointer copies.
-		if work.full == 0 && work.partial == 0 {
-			gcw.balance()
+	// Flush remaining scan work credit.
+	if gcw.scanWork > 0 {
+		atomic.Xaddint64(&gcController.scanWork, gcw.scanWork)
+		if flushBgCredit {
+			gcFlushBgCredit(gcw.scanWork - initScanWork)
 		}
-
-		b := gcw.tryGet()
-		if b == 0 {
-			// No more work
-			break
-		}
-		scanobject(b, gcw)
-
-		// Flush background scan work credit to the global
-		// account if we've accumulated enough locally so
-		// mutator assists can draw on it.
-		if gcw.scanWork >= nextScanFlush {
-			credit := gcw.scanWork - lastScanFlush
-			xaddint64(&gcController.bgScanCredit, credit)
-			lastScanFlush = gcw.scanWork
-			nextScanFlush = lastScanFlush + flushScanCredit
-		}
-	}
-	if flushScanCredit != -1 {
-		credit := gcw.scanWork - lastScanFlush
-		xaddint64(&gcController.bgScanCredit, credit)
+		gcw.scanWork = 0
 	}
 }
 
 // gcDrainN blackens grey objects until it has performed roughly
-// scanWork units of scan work. This is best-effort, so it may perform
-// less work if it fails to get a work buffer. Otherwise, it will
-// perform at least n units of work, but may perform more because
-// scanning is always done in whole object increments.
+// scanWork units of scan work or the G is preempted. This is
+// best-effort, so it may perform less work if it fails to get a work
+// buffer. Otherwise, it will perform at least n units of work, but
+// may perform more because scanning is always done in whole object
+// increments. It returns the amount of scan work performed.
 //go:nowritebarrier
-func gcDrainN(gcw *gcWork, scanWork int64) {
-	if !writeBarrierEnabled {
+func gcDrainN(gcw *gcWork, scanWork int64) int64 {
+	if !writeBarrier.needed {
 		throw("gcDrainN phase incorrect")
 	}
-	targetScanWork := gcw.scanWork + scanWork
-	for gcw.scanWork < targetScanWork {
+
+	// There may already be scan work on the gcw, which we don't
+	// want to claim was done by this call.
+	workFlushed := -gcw.scanWork
+
+	gp := getg().m.curg
+	for !gp.preempt && workFlushed+gcw.scanWork < scanWork {
+		// See gcDrain comment.
+		if work.full == 0 {
+			gcw.balance()
+		}
+
 		// This might be a good place to add prefetch code...
 		// if(wbuf.nobj > 4) {
 		//         PREFETCH(wbuf->obj[wbuf.nobj - 3];
 		//  }
+		//
 		b := gcw.tryGet()
 		if b == 0 {
-			return
+			break
 		}
 		scanobject(b, gcw)
+
+		// Flush background scan work credit.
+		if gcw.scanWork >= gcCreditSlack {
+			atomic.Xaddint64(&gcController.scanWork, gcw.scanWork)
+			workFlushed += gcw.scanWork
+			gcw.scanWork = 0
+		}
 	}
+
+	// Unlike gcDrain, there's no need to flush remaining work
+	// here because this never flushes to bgScanCredit and
+	// gcw.dispose will flush any remaining work to scanWork.
+
+	return workFlushed + gcw.scanWork
 }
 
 // scanblock scans b as scanobject would, but using an explicit
@@ -858,9 +933,9 @@ func scanblock(b0, n0 uintptr, ptrmask *uint8, gcw *gcWork) {
 
 	for i := uintptr(0); i < n; {
 		// Find bits for the next word.
-		bits := uint32(*addb(ptrmask, i/(ptrSize*8)))
+		bits := uint32(*addb(ptrmask, i/(sys.PtrSize*8)))
 		if bits == 0 {
-			i += ptrSize * 8
+			i += sys.PtrSize * 8
 			continue
 		}
 		for j := 0; j < 8 && i < n; j++ {
@@ -868,13 +943,13 @@ func scanblock(b0, n0 uintptr, ptrmask *uint8, gcw *gcWork) {
 				// Same work as in scanobject; see comments there.
 				obj := *(*uintptr)(unsafe.Pointer(b + i))
 				if obj != 0 && arena_start <= obj && obj < arena_used {
-					if obj, hbits, span := heapBitsForObject(obj); obj != 0 {
+					if obj, hbits, span := heapBitsForObject(obj, b, i); obj != 0 {
 						greyobject(obj, b, i, hbits, span, gcw)
 					}
 				}
 			}
 			bits >>= 1
-			i += ptrSize
+			i += sys.PtrSize
 		}
 	}
 }
@@ -908,7 +983,7 @@ func scanobject(b uintptr, gcw *gcWork) {
 	}
 
 	var i uintptr
-	for i = 0; i < n; i += ptrSize {
+	for i = 0; i < n; i += sys.PtrSize {
 		// Find bits for this word.
 		if i != 0 {
 			// Avoid needless hbits.next() on last iteration.
@@ -919,7 +994,7 @@ func scanobject(b uintptr, gcw *gcWork) {
 		// are pointers, or else they'd be merged with other non-pointer
 		// data into larger allocations.
 		bits := hbits.bits()
-		if i >= 2*ptrSize && bits&bitMarked == 0 {
+		if i >= 2*sys.PtrSize && bits&bitMarked == 0 {
 			break // no more pointers in this object
 		}
 		if bits&bitPointer == 0 {
@@ -934,7 +1009,7 @@ func scanobject(b uintptr, gcw *gcWork) {
 		// Check if it points into heap and not back at the current object.
 		if obj != 0 && arena_start <= obj && obj < arena_used && obj-b >= n {
 			// Mark the object.
-			if obj, hbits, span := heapBitsForObject(obj); obj != 0 {
+			if obj, hbits, span := heapBitsForObject(obj, b, i); obj != 0 {
 				greyobject(obj, b, i, hbits, span, gcw)
 			}
 		}
@@ -948,7 +1023,7 @@ func scanobject(b uintptr, gcw *gcWork) {
 // Preemption must be disabled.
 //go:nowritebarrier
 func shade(b uintptr) {
-	if obj, hbits, span := heapBitsForObject(b); obj != 0 {
+	if obj, hbits, span := heapBitsForObject(b, 0, 0); obj != 0 {
 		gcw := &getg().m.p.ptr().gcw
 		greyobject(obj, 0, 0, hbits, span, gcw)
 		if gcphase == _GCmarktermination || gcBlackenPromptly {
@@ -962,10 +1037,10 @@ func shade(b uintptr) {
 // obj is the start of an object with mark mbits.
 // If it isn't already marked, mark it and enqueue into gcw.
 // base and off are for debugging only and could be removed.
-//go:nowritebarrier
+//go:nowritebarrierrec
 func greyobject(obj, base, off uintptr, hbits heapBits, span *mspan, gcw *gcWork) {
 	// obj should be start of allocation, and so must be at least pointer-aligned.
-	if obj&(ptrSize-1) != 0 {
+	if obj&(sys.PtrSize-1) != 0 {
 		throw("greyobject: obj not pointer-aligned")
 	}
 
@@ -1019,7 +1094,7 @@ func greyobject(obj, base, off uintptr, hbits heapBits, span *mspan, gcw *gcWork
 // field at byte offset off in obj.
 func gcDumpObject(label string, obj, off uintptr) {
 	if obj < mheap_.arena_start || obj >= mheap_.arena_used {
-		print(label, "=", hex(obj), " is not a heap object\n")
+		print(label, "=", hex(obj), " is not in the Go heap\n")
 		return
 	}
 	k := obj >> _PageShift
@@ -1032,13 +1107,28 @@ func gcDumpObject(label string, obj, off uintptr) {
 		return
 	}
 	print(" s.start*_PageSize=", hex(s.start*_PageSize), " s.limit=", hex(s.limit), " s.sizeclass=", s.sizeclass, " s.elemsize=", s.elemsize, "\n")
-	for i := uintptr(0); i < s.elemsize; i += ptrSize {
+	skipped := false
+	for i := uintptr(0); i < s.elemsize; i += sys.PtrSize {
+		// For big objects, just print the beginning (because
+		// that usually hints at the object's type) and the
+		// fields around off.
+		if !(i < 128*sys.PtrSize || off-16*sys.PtrSize < i && i < off+16*sys.PtrSize) {
+			skipped = true
+			continue
+		}
+		if skipped {
+			print(" ...\n")
+			skipped = false
+		}
 		print(" *(", label, "+", i, ") = ", hex(*(*uintptr)(unsafe.Pointer(obj + uintptr(i)))))
 		if i == off {
 			print(" <==")
 		}
 		print("\n")
 	}
+	if skipped {
+		print(" ...\n")
+	}
 }
 
 // If gcBlackenPromptly is true we are in the second mark phase phase so we allocate black.
@@ -1048,7 +1138,7 @@ func gcmarknewobject_m(obj, size uintptr) {
 		throw("gcmarknewobject called while doing checkmark")
 	}
 	heapBitsForAddr(obj).setMarked()
-	xadd64(&work.bytesMarked, int64(size))
+	atomic.Xadd64(&work.bytesMarked, int64(size))
 }
 
 // Checkmarking
diff --git a/src/runtime/mgcsweep.go b/src/runtime/mgcsweep.go
index eaa4463..b00ceb0 100644
--- a/src/runtime/mgcsweep.go
+++ b/src/runtime/mgcsweep.go
@@ -6,7 +6,11 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 var sweep sweepdata
 
@@ -24,20 +28,28 @@ type sweepdata struct {
 }
 
 //go:nowritebarrier
-func finishsweep_m() {
-	// The world is stopped so we should be able to complete the sweeps
-	// quickly.
+func finishsweep_m(stw bool) {
+	// Sweeping must be complete before marking commences, so
+	// sweep any unswept spans. If this is a concurrent GC, there
+	// shouldn't be any spans left to sweep, so this should finish
+	// instantly. If GC was forced before the concurrent sweep
+	// finished, there may be spans to sweep.
 	for sweepone() != ^uintptr(0) {
 		sweep.npausesweep++
 	}
 
 	// There may be some other spans being swept concurrently that
 	// we need to wait for. If finishsweep_m is done with the world stopped
-	// this code is not required.
-	sg := mheap_.sweepgen
-	for _, s := range work.spans {
-		if s.sweepgen != sg && s.state == _MSpanInUse {
-			mSpan_EnsureSwept(s)
+	// this is not required because the STW must have waited for sweeps.
+	//
+	// TODO(austin): As of this writing, we always pass true for stw.
+	// Consider removing this code.
+	if !stw {
+		sg := mheap_.sweepgen
+		for _, s := range work.spans {
+			if s.sweepgen != sg && s.state == _MSpanInUse {
+				s.ensureSwept()
+			}
 		}
 	}
 }
@@ -79,10 +91,13 @@ func sweepone() uintptr {
 	_g_.m.locks++
 	sg := mheap_.sweepgen
 	for {
-		idx := xadd(&sweep.spanidx, 1) - 1
+		idx := atomic.Xadd(&sweep.spanidx, 1) - 1
 		if idx >= uint32(len(work.spans)) {
 			mheap_.sweepdone = 1
 			_g_.m.locks--
+			if debug.gcpacertrace > 0 && idx == uint32(len(work.spans)) {
+				print("pacer: sweep done at heap size ", memstats.heap_live>>20, "MB; allocated ", mheap_.spanBytesAlloc>>20, "MB of spans; swept ", mheap_.pagesSwept, " pages\n")
+			}
 			return ^uintptr(0)
 		}
 		s := work.spans[idx]
@@ -90,11 +105,11 @@ func sweepone() uintptr {
 			s.sweepgen = sg
 			continue
 		}
-		if s.sweepgen != sg-2 || !cas(&s.sweepgen, sg-2, sg-1) {
+		if s.sweepgen != sg-2 || !atomic.Cas(&s.sweepgen, sg-2, sg-1) {
 			continue
 		}
 		npages := s.npages
-		if !mSpan_Sweep(s, false) {
+		if !s.sweep(false) {
 			npages = 0
 		}
 		_g_.m.locks--
@@ -118,7 +133,7 @@ func gosweepdone() bool {
 
 // Returns only when span s has been swept.
 //go:nowritebarrier
-func mSpan_EnsureSwept(s *mspan) {
+func (s *mspan) ensureSwept() {
 	// Caller must disable preemption.
 	// Otherwise when this function returns the span can become unswept again
 	// (if GC is triggered on another goroutine).
@@ -128,16 +143,16 @@ func mSpan_EnsureSwept(s *mspan) {
 	}
 
 	sg := mheap_.sweepgen
-	if atomicload(&s.sweepgen) == sg {
+	if atomic.Load(&s.sweepgen) == sg {
 		return
 	}
 	// The caller must be sure that the span is a MSpanInUse span.
-	if cas(&s.sweepgen, sg-2, sg-1) {
-		mSpan_Sweep(s, false)
+	if atomic.Cas(&s.sweepgen, sg-2, sg-1) {
+		s.sweep(false)
 		return
 	}
 	// unfortunate condition, and we don't have efficient means to wait
-	for atomicload(&s.sweepgen) != sg {
+	for atomic.Load(&s.sweepgen) != sg {
 		osyield()
 	}
 }
@@ -148,7 +163,7 @@ func mSpan_EnsureSwept(s *mspan) {
 // If preserve=true, don't return it to heap nor relink in MCentral lists;
 // caller takes care of it.
 //TODO go:nowritebarrier
-func mSpan_Sweep(s *mspan, preserve bool) bool {
+func (s *mspan) sweep(preserve bool) bool {
 	// It's critical that we enter this function with preemption disabled,
 	// GC must not start while we are in the middle of this function.
 	_g_ := getg()
@@ -165,7 +180,7 @@ func mSpan_Sweep(s *mspan, preserve bool) bool {
 		traceGCSweepStart()
 	}
 
-	xadd64(&mheap_.pagesSwept, int64(s.npages))
+	atomic.Xadd64(&mheap_.pagesSwept, int64(s.npages))
 
 	cl := s.sizeclass
 	size := s.elemsize
@@ -189,6 +204,13 @@ func mSpan_Sweep(s *mspan, preserve bool) bool {
 	}
 
 	// Unlink & free special records for any objects we're about to free.
+	// Two complications here:
+	// 1. An object can have both finalizer and profile special records.
+	//    In such case we need to queue finalizer for execution,
+	//    mark the object as live and preserve the profile special.
+	// 2. A tiny object can have several finalizers setup for different offsets.
+	//    If such object is not marked, we need to queue all finalizers at once.
+	// Both 1 and 2 are possible at the same time.
 	specialp := &s.specials
 	special := *specialp
 	for special != nil {
@@ -196,16 +218,35 @@ func mSpan_Sweep(s *mspan, preserve bool) bool {
 		p := uintptr(s.start<<_PageShift) + uintptr(special.offset)/size*size
 		hbits := heapBitsForAddr(p)
 		if !hbits.isMarked() {
-			// Find the exact byte for which the special was setup
-			// (as opposed to object beginning).
-			p := uintptr(s.start<<_PageShift) + uintptr(special.offset)
-			// about to free object: splice out special record
-			y := special
-			special = special.next
-			*specialp = special
-			if !freespecial(y, unsafe.Pointer(p), size, false) {
-				// stop freeing of object if it has a finalizer
-				hbits.setMarkedNonAtomic()
+			// This object is not marked and has at least one special record.
+			// Pass 1: see if it has at least one finalizer.
+			hasFin := false
+			endOffset := p - uintptr(s.start<<_PageShift) + size
+			for tmp := special; tmp != nil && uintptr(tmp.offset) < endOffset; tmp = tmp.next {
+				if tmp.kind == _KindSpecialFinalizer {
+					// Stop freeing of object if it has a finalizer.
+					hbits.setMarkedNonAtomic()
+					hasFin = true
+					break
+				}
+			}
+			// Pass 2: queue all finalizers _or_ handle profile record.
+			for special != nil && uintptr(special.offset) < endOffset {
+				// Find the exact byte for which the special was setup
+				// (as opposed to object beginning).
+				p := uintptr(s.start<<_PageShift) + uintptr(special.offset)
+				if special.kind == _KindSpecialFinalizer || !hasFin {
+					// Splice out special record.
+					y := special
+					special = special.next
+					*specialp = special
+					freespecial(y, unsafe.Pointer(p), size)
+				} else {
+					// This is profile record, but the object has finalizers (so kept alive).
+					// Keep special record.
+					specialp = &special.next
+					special = *specialp
+				}
 			}
 		} else {
 			// object is still live: keep special record
@@ -225,6 +266,9 @@ func mSpan_Sweep(s *mspan, preserve bool) bool {
 		if debug.allocfreetrace != 0 {
 			tracefree(unsafe.Pointer(p), size)
 		}
+		if msanenabled {
+			msanfree(unsafe.Pointer(p), size)
+		}
 
 		// Reset to allocated+noscan.
 		if cl == 0 {
@@ -235,18 +279,15 @@ func mSpan_Sweep(s *mspan, preserve bool) bool {
 			heapBitsForSpan(p).initSpan(s.layout())
 			s.needzero = 1
 
-			// important to set sweepgen before returning it to heap
-			atomicstore(&s.sweepgen, sweepgen)
-
 			// Free the span after heapBitsSweepSpan
 			// returns, since it's not done with the span.
 			freeToHeap = true
 		} else {
 			// Free small object.
-			if size > 2*ptrSize {
-				*(*uintptr)(unsafe.Pointer(p + ptrSize)) = uintptrMask & 0xdeaddeaddeaddead // mark as "needs to be zeroed"
-			} else if size > ptrSize {
-				*(*uintptr)(unsafe.Pointer(p + ptrSize)) = 0
+			if size > 2*sys.PtrSize {
+				*(*uintptr)(unsafe.Pointer(p + sys.PtrSize)) = uintptrMask & 0xdeaddeaddeaddead // mark as "needs to be zeroed"
+			} else if size > sys.PtrSize {
+				*(*uintptr)(unsafe.Pointer(p + sys.PtrSize)) = 0
 			}
 			if head.ptr() == nil {
 				head = gclinkptr(p)
@@ -264,21 +305,18 @@ func mSpan_Sweep(s *mspan, preserve bool) bool {
 	// But we need to set it before we make the span available for allocation
 	// (return it to heap or mcentral), because allocation code assumes that a
 	// span is already swept if available for allocation.
-	//
-	// TODO(austin): Clean this up by consolidating atomicstore in
-	// large span path above with this.
-	if !freeToHeap && nfree == 0 {
+	if freeToHeap || nfree == 0 {
 		// The span must be in our exclusive ownership until we update sweepgen,
 		// check for potential races.
 		if s.state != mSpanInUse || s.sweepgen != sweepgen-1 {
 			print("MSpan_Sweep: state=", s.state, " sweepgen=", s.sweepgen, " mheap.sweepgen=", sweepgen, "\n")
 			throw("MSpan_Sweep: bad span state after sweep")
 		}
-		atomicstore(&s.sweepgen, sweepgen)
+		atomic.Store(&s.sweepgen, sweepgen)
 	}
 	if nfree > 0 {
 		c.local_nsmallfree[cl] += uintptr(nfree)
-		res = mCentral_FreeSpan(&mheap_.central[cl].mcentral, s, int32(nfree), head, end, preserve)
+		res = mheap_.central[cl].mcentral.freeSpan(s, int32(nfree), head, end, preserve)
 		// MCentral_FreeSpan updates sweepgen
 	} else if freeToHeap {
 		// Free large span to heap
@@ -301,7 +339,7 @@ func mSpan_Sweep(s *mspan, preserve bool) bool {
 			s.limit = 0 // prevent mlookup from finding this span
 			sysFault(unsafe.Pointer(uintptr(s.start<<_PageShift)), size)
 		} else {
-			mHeap_Free(&mheap_, s, 1)
+			mheap_.freeSpan(s, 1)
 		}
 		c.local_nlargefree++
 		c.local_largefree += size
@@ -320,6 +358,11 @@ func mSpan_Sweep(s *mspan, preserve bool) bool {
 // also sweep pages (e.g., for a large allocation), it can pass a
 // non-zero callerSweepPages to leave that many pages unswept.
 //
+// deductSweepCredit makes a worst-case assumption that all spanBytes
+// bytes of the ultimately allocated span will be available for object
+// allocation. The caller should call reimburseSweepCredit if that
+// turns out not to be the case once the span is allocated.
+//
 // deductSweepCredit is the core of the "proportional sweep" system.
 // It uses statistics gathered by the garbage collector to perform
 // enough sweeping so that all pages are swept during the concurrent
@@ -333,11 +376,11 @@ func deductSweepCredit(spanBytes uintptr, callerSweepPages uintptr) {
 	}
 
 	// Account for this span allocation.
-	spanBytesAlloc := xadd64(&mheap_.spanBytesAlloc, int64(spanBytes))
+	spanBytesAlloc := atomic.Xadd64(&mheap_.spanBytesAlloc, int64(spanBytes))
 
 	// Fix debt if necessary.
 	pagesOwed := int64(mheap_.sweepPagesPerByte * float64(spanBytesAlloc))
-	for pagesOwed-int64(atomicload64(&mheap_.pagesSwept)) > int64(callerSweepPages) {
+	for pagesOwed-int64(atomic.Load64(&mheap_.pagesSwept)) > int64(callerSweepPages) {
 		if gosweepone() == ^uintptr(0) {
 			mheap_.sweepPagesPerByte = 0
 			break
@@ -345,6 +388,19 @@ func deductSweepCredit(spanBytes uintptr, callerSweepPages uintptr) {
 	}
 }
 
+// reimburseSweepCredit records that unusableBytes bytes of a
+// just-allocated span are not available for object allocation. This
+// offsets the worst-case charge performed by deductSweepCredit.
+func reimburseSweepCredit(unusableBytes uintptr) {
+	if mheap_.sweepPagesPerByte == 0 {
+		// Nobody cares about the credit. Avoid the atomic.
+		return
+	}
+	if int64(atomic.Xadd64(&mheap_.spanBytesAlloc, -int64(unusableBytes))) < 0 {
+		throw("spanBytesAlloc underflow")
+	}
+}
+
 func dumpFreeList(s *mspan) {
 	printlock()
 	print("runtime: free list of span ", s, ":\n")
diff --git a/src/runtime/mgcwork.go b/src/runtime/mgcwork.go
index b18eaaf..0a0285d 100644
--- a/src/runtime/mgcwork.go
+++ b/src/runtime/mgcwork.go
@@ -4,11 +4,15 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 const (
-	_Debugwbufs  = false   // if true check wbufs consistency
-	_WorkbufSize = 1 * 256 // in bytes - if small wbufs are passed to GC in a timely fashion.
+	_Debugwbufs  = false // if true check wbufs consistency
+	_WorkbufSize = 2048  // in bytes; larger values result in less contention
 )
 
 // Garbage collector work pool abstraction.
@@ -51,7 +55,7 @@ func (wp wbufptr) ptr() *workbuf {
 //     (preemption must be disabled)
 //     gcw := &getg().m.p.ptr().gcw
 //     .. call gcw.put() to produce and gcw.get() to consume ..
-//     if gcphase == _GCmarktermination {
+//     if gcBlackenPromptly {
 //         gcw.dispose()
 //     }
 //
@@ -60,37 +64,67 @@ func (wp wbufptr) ptr() *workbuf {
 // gcWork may locally hold GC work buffers. This can be done by
 // disabling preemption (systemstack or acquirem).
 type gcWork struct {
-	// Invariant: wbuf is never full or empty
-	wbuf wbufptr
+	// wbuf1 and wbuf2 are the primary and secondary work buffers.
+	//
+	// This can be thought of as a stack of both work buffers'
+	// pointers concatenated. When we pop the last pointer, we
+	// shift the stack up by one work buffer by bringing in a new
+	// full buffer and discarding an empty one. When we fill both
+	// buffers, we shift the stack down by one work buffer by
+	// bringing in a new empty buffer and discarding a full one.
+	// This way we have one buffer's worth of hysteresis, which
+	// amortizes the cost of getting or putting a work buffer over
+	// at least one buffer of work and reduces contention on the
+	// global work lists.
+	//
+	// wbuf1 is always the buffer we're currently pushing to and
+	// popping from and wbuf2 is the buffer that will be discarded
+	// next.
+	//
+	// Invariant: Both wbuf1 and wbuf2 are nil or neither are.
+	wbuf1, wbuf2 wbufptr
 
 	// Bytes marked (blackened) on this gcWork. This is aggregated
 	// into work.bytesMarked by dispose.
 	bytesMarked uint64
 
 	// Scan work performed on this gcWork. This is aggregated into
-	// gcController by dispose.
+	// gcController by dispose and may also be flushed by callers.
 	scanWork int64
 }
 
+func (w *gcWork) init() {
+	w.wbuf1 = wbufptrOf(getempty(101))
+	wbuf2 := trygetfull(102)
+	if wbuf2 == nil {
+		wbuf2 = getempty(103)
+	}
+	w.wbuf2 = wbufptrOf(wbuf2)
+}
+
 // put enqueues a pointer for the garbage collector to trace.
 // obj must point to the beginning of a heap object.
 //go:nowritebarrier
 func (ww *gcWork) put(obj uintptr) {
 	w := (*gcWork)(noescape(unsafe.Pointer(ww))) // TODO: remove when escape analysis is fixed
 
-	wbuf := w.wbuf.ptr()
+	wbuf := w.wbuf1.ptr()
 	if wbuf == nil {
-		wbuf = getpartialorempty(42)
-		w.wbuf = wbufptrOf(wbuf)
+		w.init()
+		wbuf = w.wbuf1.ptr()
+		// wbuf is empty at this point.
+	} else if wbuf.nobj == len(wbuf.obj) {
+		w.wbuf1, w.wbuf2 = w.wbuf2, w.wbuf1
+		wbuf = w.wbuf1.ptr()
+		if wbuf.nobj == len(wbuf.obj) {
+			putfull(wbuf, 132)
+			wbuf = getempty(133)
+			w.wbuf1 = wbufptrOf(wbuf)
+		}
 	}
 
 	wbuf.obj[wbuf.nobj] = obj
 	wbuf.nobj++
-
-	if wbuf.nobj == len(wbuf.obj) {
-		putfull(wbuf, 50)
-		w.wbuf = 0
-	}
 }
 
 // tryGet dequeues a pointer for the garbage collector to trace.
@@ -102,24 +136,28 @@ func (ww *gcWork) put(obj uintptr) {
 func (ww *gcWork) tryGet() uintptr {
 	w := (*gcWork)(noescape(unsafe.Pointer(ww))) // TODO: remove when escape analysis is fixed
 
-	wbuf := w.wbuf.ptr()
+	wbuf := w.wbuf1.ptr()
 	if wbuf == nil {
-		wbuf = trygetfull(74)
-		if wbuf == nil {
-			return 0
-		}
-		w.wbuf = wbufptrOf(wbuf)
+		w.init()
+		wbuf = w.wbuf1.ptr()
+		// wbuf is empty at this point.
 	}
-
-	wbuf.nobj--
-	obj := wbuf.obj[wbuf.nobj]
-
 	if wbuf.nobj == 0 {
-		putempty(wbuf, 86)
-		w.wbuf = 0
+		w.wbuf1, w.wbuf2 = w.wbuf2, w.wbuf1
+		wbuf = w.wbuf1.ptr()
+		if wbuf.nobj == 0 {
+			owbuf := wbuf
+			wbuf = trygetfull(167)
+			if wbuf == nil {
+				return 0
+			}
+			putempty(owbuf, 166)
+			w.wbuf1 = wbufptrOf(wbuf)
+		}
 	}
 
-	return obj
+	wbuf.nobj--
+	return wbuf.obj[wbuf.nobj]
 }
 
 // get dequeues a pointer for the garbage collector to trace, blocking
@@ -129,27 +167,30 @@ func (ww *gcWork) tryGet() uintptr {
 func (ww *gcWork) get() uintptr {
 	w := (*gcWork)(noescape(unsafe.Pointer(ww))) // TODO: remove when escape analysis is fixed
 
-	wbuf := w.wbuf.ptr()
+	wbuf := w.wbuf1.ptr()
 	if wbuf == nil {
-		wbuf = getfull(103)
-		if wbuf == nil {
-			return 0
+		w.init()
+		wbuf = w.wbuf1.ptr()
+		// wbuf is empty at this point.
+	}
+	if wbuf.nobj == 0 {
+		w.wbuf1, w.wbuf2 = w.wbuf2, w.wbuf1
+		wbuf = w.wbuf1.ptr()
+		if wbuf.nobj == 0 {
+			owbuf := wbuf
+			wbuf = getfull(185)
+			if wbuf == nil {
+				return 0
+			}
+			putempty(owbuf, 184)
+			w.wbuf1 = wbufptrOf(wbuf)
 		}
-		wbuf.checknonempty()
-		w.wbuf = wbufptrOf(wbuf)
 	}
 
 	// TODO: This might be a good place to add prefetch code
 
 	wbuf.nobj--
-	obj := wbuf.obj[wbuf.nobj]
-
-	if wbuf.nobj == 0 {
-		putempty(wbuf, 115)
-		w.wbuf = 0
-	}
-
-	return obj
+	return wbuf.obj[wbuf.nobj]
 }
 
 // dispose returns any cached pointers to the global queue.
@@ -160,23 +201,32 @@ func (ww *gcWork) get() uintptr {
 //
 //go:nowritebarrier
 func (w *gcWork) dispose() {
-	if wbuf := w.wbuf; wbuf != 0 {
-		if wbuf.ptr().nobj == 0 {
-			throw("dispose: workbuf is empty")
+	if wbuf := w.wbuf1.ptr(); wbuf != nil {
+		if wbuf.nobj == 0 {
+			putempty(wbuf, 212)
+		} else {
+			putfull(wbuf, 214)
 		}
-		putfull(wbuf.ptr(), 166)
-		w.wbuf = 0
+		w.wbuf1 = 0
+
+		wbuf = w.wbuf2.ptr()
+		if wbuf.nobj == 0 {
+			putempty(wbuf, 218)
+		} else {
+			putfull(wbuf, 220)
+		}
+		w.wbuf2 = 0
 	}
 	if w.bytesMarked != 0 {
 		// dispose happens relatively infrequently. If this
 		// atomic becomes a problem, we should first try to
 		// dispose less and if necessary aggregate in a per-P
 		// counter.
-		xadd64(&work.bytesMarked, int64(w.bytesMarked))
+		atomic.Xadd64(&work.bytesMarked, int64(w.bytesMarked))
 		w.bytesMarked = 0
 	}
 	if w.scanWork != 0 {
-		xaddint64(&gcController.scanWork, w.scanWork)
+		atomic.Xaddint64(&gcController.scanWork, w.scanWork)
 		w.scanWork = 0
 	}
 }
@@ -185,16 +235,21 @@ func (w *gcWork) dispose() {
 // global queue.
 //go:nowritebarrier
 func (w *gcWork) balance() {
-	if wbuf := w.wbuf; wbuf != 0 && wbuf.ptr().nobj > 4 {
-		w.wbuf = wbufptrOf(handoff(wbuf.ptr()))
+	if w.wbuf1 == 0 {
+		return
+	}
+	if wbuf := w.wbuf2.ptr(); wbuf.nobj != 0 {
+		putfull(wbuf, 246)
+		w.wbuf2 = wbufptrOf(getempty(247))
+	} else if wbuf := w.wbuf1.ptr(); wbuf.nobj > 4 {
+		w.wbuf1 = wbufptrOf(handoff(wbuf))
 	}
 }
 
 // empty returns true if w has no mark work available.
 //go:nowritebarrier
 func (w *gcWork) empty() bool {
-	wbuf := w.wbuf
-	return wbuf == 0 || wbuf.ptr().nobj == 0
+	return w.wbuf1 == 0 || (w.wbuf1.ptr().nobj == 0 && w.wbuf2.ptr().nobj == 0)
 }
 
 // Internally, the GC work pool is kept in arrays in work buffers.
@@ -204,20 +259,20 @@ func (w *gcWork) empty() bool {
 type workbufhdr struct {
 	node  lfnode // must be first
 	nobj  int
-	inuse bool   // This workbuf is in use by some gorotuine and is not on the work.empty/partial/full queues.
+	inuse bool   // This workbuf is in use by some gorotuine and is not on the work.empty/full queues.
 	log   [4]int // line numbers forming a history of ownership changes to workbuf
 }
 
 type workbuf struct {
 	workbufhdr
 	// account for the above fields
-	obj [(_WorkbufSize - unsafe.Sizeof(workbufhdr{})) / ptrSize]uintptr
+	obj [(_WorkbufSize - unsafe.Sizeof(workbufhdr{})) / sys.PtrSize]uintptr
 }
 
 // workbuf factory routines. These funcs are used to manage the
 // workbufs.
 // If the GC asks for some work these are the only routines that
-// make partially full wbufs available to the GC.
+// make wbufs available to the GC.
 // Each of the gets and puts also take an distinct integer that is used
 // to record a brief history of changes to ownership of the workbuf.
 // The convention is to use a unique line number but any encoding
@@ -289,7 +344,7 @@ func getempty(entry int) *workbuf {
 		}
 	}
 	if b == nil {
-		b = (*workbuf)(persistentalloc(unsafe.Sizeof(*b), _CacheLineSize, &memstats.gc_sys))
+		b = (*workbuf)(persistentalloc(unsafe.Sizeof(*b), sys.CacheLineSize, &memstats.gc_sys))
 	}
 	b.logget(entry)
 	return b
@@ -312,45 +367,11 @@ func putfull(b *workbuf, entry int) {
 	b.checknonempty()
 	b.logput(entry)
 	lfstackpush(&work.full, &b.node)
-}
-
-// getpartialorempty tries to return a partially empty
-// and if none are available returns an empty one.
-// entry is used to provide a brief history of ownership
-// using entry + xxx00000 to
-// indicating that two line numbers in the call chain.
-//go:nowritebarrier
-func getpartialorempty(entry int) *workbuf {
-	b := (*workbuf)(lfstackpop(&work.partial))
-	if b != nil {
-		b.logget(entry)
-		return b
-	}
-	// Let getempty do the logget check but
-	// use the entry to encode that it passed
-	// through this routine.
-	b = getempty(entry + 80700000)
-	return b
-}
 
-// putpartial puts empty buffers on the work.empty queue,
-// full buffers on the work.full queue and
-// others on the work.partial queue.
-// entry is used to provide a brief history of ownership
-// using entry + xxx00000 to
-// indicating that two call chain line numbers.
-//go:nowritebarrier
-func putpartial(b *workbuf, entry int) {
-	if b.nobj == 0 {
-		putempty(b, entry+81500000)
-	} else if b.nobj < len(b.obj) {
-		b.logput(entry)
-		lfstackpush(&work.partial, &b.node)
-	} else if b.nobj == len(b.obj) {
-		b.logput(entry)
-		lfstackpush(&work.full, &b.node)
-	} else {
-		throw("putpartial: bad Workbuf b.nobj")
+	// We just made more work available. Let the GC controller
+	// know so it can encourage more workers to run.
+	if gcphase == _GCmark {
+		gcController.enlistWorker()
 	}
 }
 
@@ -359,9 +380,6 @@ func putpartial(b *workbuf, entry int) {
 //go:nowritebarrier
 func trygetfull(entry int) *workbuf {
 	b := (*workbuf)(lfstackpop(&work.full))
-	if b == nil {
-		b = (*workbuf)(lfstackpop(&work.partial))
-	}
 	if b != nil {
 		b.logget(entry)
 		b.checknonempty()
@@ -370,10 +388,9 @@ func trygetfull(entry int) *workbuf {
 	return b
 }
 
-// Get a full work buffer off the work.full or a partially
-// filled one off the work.partial list. If nothing is available
-// wait until all the other gc helpers have finished and then
-// return nil.
+// Get a full work buffer off the work.full list.
+// If nothing is available wait until all the other gc helpers have
+// finished and then return nil.
 // getfull acts as a barrier for work.nproc helpers. As long as one
 // gchelper is actively marking objects it
 // may create a workbuffer that the other helpers can work on.
@@ -390,40 +407,32 @@ func getfull(entry int) *workbuf {
 		b.checknonempty()
 		return b
 	}
-	b = (*workbuf)(lfstackpop(&work.partial))
-	if b != nil {
-		b.logget(entry)
-		return b
-	}
 
-	incnwait := xadd(&work.nwait, +1)
+	incnwait := atomic.Xadd(&work.nwait, +1)
 	if incnwait > work.nproc {
 		println("runtime: work.nwait=", incnwait, "work.nproc=", work.nproc)
 		throw("work.nwait > work.nproc")
 	}
 	for i := 0; ; i++ {
-		if work.full != 0 || work.partial != 0 {
-			decnwait := xadd(&work.nwait, -1)
+		if work.full != 0 {
+			decnwait := atomic.Xadd(&work.nwait, -1)
 			if decnwait == work.nproc {
 				println("runtime: work.nwait=", decnwait, "work.nproc=", work.nproc)
 				throw("work.nwait > work.nproc")
 			}
 			b = (*workbuf)(lfstackpop(&work.full))
-			if b == nil {
-				b = (*workbuf)(lfstackpop(&work.partial))
-			}
 			if b != nil {
 				b.logget(entry)
 				b.checknonempty()
 				return b
 			}
-			incnwait := xadd(&work.nwait, +1)
+			incnwait := atomic.Xadd(&work.nwait, +1)
 			if incnwait > work.nproc {
 				println("runtime: work.nwait=", incnwait, "work.nproc=", work.nproc)
 				throw("work.nwait > work.nproc")
 			}
 		}
-		if work.nwait == work.nproc {
+		if work.nwait == work.nproc && work.markrootNext >= work.markrootJobs {
 			return nil
 		}
 		_g_ := getg()
diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go
index bc4e7c1..e818954 100644
--- a/src/runtime/mheap.go
+++ b/src/runtime/mheap.go
@@ -8,19 +8,23 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 // Main malloc heap.
 // The heap itself is the "free[]" and "large" arrays,
 // but all the other global data is here too.
 type mheap struct {
 	lock      mutex
-	free      [_MaxMHeapList]mspan // free lists of given length
-	freelarge mspan                // free lists length >= _MaxMHeapList
-	busy      [_MaxMHeapList]mspan // busy lists of large objects of given length
-	busylarge mspan                // busy lists of large objects length >= _MaxMHeapList
-	allspans  **mspan              // all spans out there
-	gcspans   **mspan              // copy of allspans referenced by gc marker or sweeper
+	free      [_MaxMHeapList]mSpanList // free lists of given length
+	freelarge mSpanList                // free lists length >= _MaxMHeapList
+	busy      [_MaxMHeapList]mSpanList // busy lists of large objects of given length
+	busylarge mSpanList                // busy lists of large objects length >= _MaxMHeapList
+	allspans  **mspan                  // all spans out there
+	gcspans   **mspan                  // copy of allspans referenced by gc marker or sweeper
 	nspan     uint32
 	sweepgen  uint32 // sweep generation, see comment in mspan
 	sweepdone uint32 // all spans are swept
@@ -29,9 +33,12 @@ type mheap struct {
 	spans_mapped uintptr
 
 	// Proportional sweep
+	pagesInUse        uint64  // pages of spans in stats _MSpanInUse; R/W with mheap.lock
 	spanBytesAlloc    uint64  // bytes of spans allocated this cycle; updated atomically
 	pagesSwept        uint64  // pages swept this cycle; updated atomically
 	sweepPagesPerByte float64 // proportional sweep ratio; written with lock, read without
+	// TODO(austin): pagesInUse should be a uintptr, but the 386
+	// compiler can't 8-byte align fields.
 
 	// Malloc stats.
 	largefree  uint64                  // bytes freed for large objects (>maxsmallsize)
@@ -52,7 +59,7 @@ type mheap struct {
 	// gets its own cache line.
 	central [_NumSizeClasses]struct {
 		mcentral mcentral
-		pad      [_CacheLineSize]byte
+		pad      [sys.CacheLineSize]byte
 	}
 
 	spanalloc             fixalloc // allocator for span*
@@ -74,7 +81,7 @@ var mheap_ mheap
 
 // Every MSpan is in one doubly-linked list,
 // either one of the MHeap's free lists or one of the
-// MCentral's span lists.  We use empty MSpan structures as list heads.
+// MCentral's span lists.
 
 // An MSpan representing actual memory has state _MSpanInUse,
 // _MSpanStack, or _MSpanFree. Transitions between these states are
@@ -94,13 +101,22 @@ const (
 	_MSpanInUse = iota // allocated for garbage collected heap
 	_MSpanStack        // allocated for use by stack allocator
 	_MSpanFree
-	_MSpanListHead
 	_MSpanDead
 )
 
+// mSpanList heads a linked list of spans.
+//
+// Linked list structure is based on BSD's "tail queue" data structure.
+type mSpanList struct {
+	first *mspan  // first span in list, or nil if none
+	last  **mspan // last span's next field, or first if none
+}
+
 type mspan struct {
-	next     *mspan    // in a span linked list
-	prev     *mspan    // in a span linked list
+	next *mspan     // next span in list, or nil if none
+	prev **mspan    // previous span's next field, or list head's first field if none
+	list *mSpanList // For debugging. TODO: Remove.
+
 	start    pageID    // starting page number
 	npages   uintptr   // number of pages in span
 	freelist gclinkptr // list of free objects
@@ -154,13 +170,13 @@ func recordspan(vh unsafe.Pointer, p unsafe.Pointer) {
 	h := (*mheap)(vh)
 	s := (*mspan)(p)
 	if len(h_allspans) >= cap(h_allspans) {
-		n := 64 * 1024 / ptrSize
+		n := 64 * 1024 / sys.PtrSize
 		if n < cap(h_allspans)*3/2 {
 			n = cap(h_allspans) * 3 / 2
 		}
 		var new []*mspan
 		sp := (*slice)(unsafe.Pointer(&new))
-		sp.array = sysAlloc(uintptr(n)*ptrSize, &memstats.other_sys)
+		sp.array = sysAlloc(uintptr(n)*sys.PtrSize, &memstats.other_sys)
 		if sp.array == nil {
 			throw("runtime: cannot allocate memory")
 		}
@@ -171,7 +187,7 @@ func recordspan(vh unsafe.Pointer, p unsafe.Pointer) {
 			// Don't free the old array if it's referenced by sweep.
 			// See the comment in mgc.go.
 			if h.allspans != mheap_.gcspans {
-				sysFree(unsafe.Pointer(h.allspans), uintptr(cap(h_allspans))*ptrSize, &memstats.other_sys)
+				sysFree(unsafe.Pointer(h.allspans), uintptr(cap(h_allspans))*sys.PtrSize, &memstats.other_sys)
 			}
 		}
 		h_allspans = new
@@ -224,14 +240,14 @@ func mlookup(v uintptr, base *uintptr, size *uintptr, sp **mspan) int32 {
 	_g_ := getg()
 
 	_g_.m.mcache.local_nlookup++
-	if ptrSize == 4 && _g_.m.mcache.local_nlookup >= 1<<30 {
+	if sys.PtrSize == 4 && _g_.m.mcache.local_nlookup >= 1<<30 {
 		// purge cache stats to prevent overflow
 		lock(&mheap_.lock)
 		purgecachedstats(_g_.m.mcache)
 		unlock(&mheap_.lock)
 	}
 
-	s := mHeap_LookupMaybe(&mheap_, unsafe.Pointer(v))
+	s := mheap_.lookupMaybe(unsafe.Pointer(v))
 	if sp != nil {
 		*sp = s
 	}
@@ -270,28 +286,28 @@ func mlookup(v uintptr, base *uintptr, size *uintptr, sp **mspan) int32 {
 }
 
 // Initialize the heap.
-func mHeap_Init(h *mheap, spans_size uintptr) {
-	fixAlloc_Init(&h.spanalloc, unsafe.Sizeof(mspan{}), recordspan, unsafe.Pointer(h), &memstats.mspan_sys)
-	fixAlloc_Init(&h.cachealloc, unsafe.Sizeof(mcache{}), nil, nil, &memstats.mcache_sys)
-	fixAlloc_Init(&h.specialfinalizeralloc, unsafe.Sizeof(specialfinalizer{}), nil, nil, &memstats.other_sys)
-	fixAlloc_Init(&h.specialprofilealloc, unsafe.Sizeof(specialprofile{}), nil, nil, &memstats.other_sys)
+func (h *mheap) init(spans_size uintptr) {
+	h.spanalloc.init(unsafe.Sizeof(mspan{}), recordspan, unsafe.Pointer(h), &memstats.mspan_sys)
+	h.cachealloc.init(unsafe.Sizeof(mcache{}), nil, nil, &memstats.mcache_sys)
+	h.specialfinalizeralloc.init(unsafe.Sizeof(specialfinalizer{}), nil, nil, &memstats.other_sys)
+	h.specialprofilealloc.init(unsafe.Sizeof(specialprofile{}), nil, nil, &memstats.other_sys)
 
 	// h->mapcache needs no init
 	for i := range h.free {
-		mSpanList_Init(&h.free[i])
-		mSpanList_Init(&h.busy[i])
+		h.free[i].init()
+		h.busy[i].init()
 	}
 
-	mSpanList_Init(&h.freelarge)
-	mSpanList_Init(&h.busylarge)
+	h.freelarge.init()
+	h.busylarge.init()
 	for i := range h.central {
-		mCentral_Init(&h.central[i].mcentral, int32(i))
+		h.central[i].mcentral.init(int32(i))
 	}
 
 	sp := (*slice)(unsafe.Pointer(&h_spans))
 	sp.array = unsafe.Pointer(h.spans)
-	sp.len = int(spans_size / ptrSize)
-	sp.cap = int(spans_size / ptrSize)
+	sp.len = int(spans_size / sys.PtrSize)
+	sp.cap = int(spans_size / sys.PtrSize)
 }
 
 // mHeap_MapSpans makes sure that the spans are mapped
@@ -302,12 +318,12 @@ func mHeap_Init(h *mheap, spans_size uintptr) {
 // Waiting to update arena_used until after the memory has been mapped
 // avoids faults when other threads try access the bitmap immediately
 // after observing the change to arena_used.
-func mHeap_MapSpans(h *mheap, arena_used uintptr) {
+func (h *mheap) mapSpans(arena_used uintptr) {
 	// Map spans array, PageSize at a time.
 	n := arena_used
 	n -= h.arena_start
-	n = n / _PageSize * ptrSize
-	n = round(n, _PhysPageSize)
+	n = n / _PageSize * sys.PtrSize
+	n = round(n, sys.PhysPageSize)
 	if h.spans_mapped >= n {
 		return
 	}
@@ -317,18 +333,18 @@ func mHeap_MapSpans(h *mheap, arena_used uintptr) {
 
 // Sweeps spans in list until reclaims at least npages into heap.
 // Returns the actual number of pages reclaimed.
-func mHeap_ReclaimList(h *mheap, list *mspan, npages uintptr) uintptr {
+func (h *mheap) reclaimList(list *mSpanList, npages uintptr) uintptr {
 	n := uintptr(0)
 	sg := mheap_.sweepgen
 retry:
-	for s := list.next; s != list; s = s.next {
-		if s.sweepgen == sg-2 && cas(&s.sweepgen, sg-2, sg-1) {
-			mSpanList_Remove(s)
+	for s := list.first; s != nil; s = s.next {
+		if s.sweepgen == sg-2 && atomic.Cas(&s.sweepgen, sg-2, sg-1) {
+			list.remove(s)
 			// swept spans are at the end of the list
-			mSpanList_InsertBack(list, s)
+			list.insertBack(s)
 			unlock(&h.lock)
 			snpages := s.npages
-			if mSpan_Sweep(s, false) {
+			if s.sweep(false) {
 				n += snpages
 			}
 			lock(&h.lock)
@@ -351,17 +367,17 @@ retry:
 
 // Sweeps and reclaims at least npage pages into heap.
 // Called before allocating npage pages.
-func mHeap_Reclaim(h *mheap, npage uintptr) {
+func (h *mheap) reclaim(npage uintptr) {
 	// First try to sweep busy spans with large objects of size >= npage,
 	// this has good chances of reclaiming the necessary space.
 	for i := int(npage); i < len(h.busy); i++ {
-		if mHeap_ReclaimList(h, &h.busy[i], npage) != 0 {
+		if h.reclaimList(&h.busy[i], npage) != 0 {
 			return // Bingo!
 		}
 	}
 
 	// Then -- even larger objects.
-	if mHeap_ReclaimList(h, &h.busylarge, npage) != 0 {
+	if h.reclaimList(&h.busylarge, npage) != 0 {
 		return // Bingo!
 	}
 
@@ -369,7 +385,7 @@ func mHeap_Reclaim(h *mheap, npage uintptr) {
 	// One such object is not enough, so we need to reclaim several of them.
 	reclaimed := uintptr(0)
 	for i := 0; i < int(npage) && i < len(h.busy); i++ {
-		reclaimed += mHeap_ReclaimList(h, &h.busy[i], npage-reclaimed)
+		reclaimed += h.reclaimList(&h.busy[i], npage-reclaimed)
 		if reclaimed >= npage {
 			return
 		}
@@ -392,7 +408,7 @@ func mHeap_Reclaim(h *mheap, npage uintptr) {
 
 // Allocate a new span of npage pages from the heap for GC'd memory
 // and record its size class in the HeapMap and HeapMapCache.
-func mHeap_Alloc_m(h *mheap, npage uintptr, sizeclass int32, large bool) *mspan {
+func (h *mheap) alloc_m(npage uintptr, sizeclass int32, large bool) *mspan {
 	_g_ := getg()
 	if _g_ != _g_.m.g0 {
 		throw("_mheap_alloc not on g0 stack")
@@ -409,24 +425,20 @@ func mHeap_Alloc_m(h *mheap, npage uintptr, sizeclass int32, large bool) *mspan
 		// If GC kept a bit for whether there were any marks
 		// in a span, we could release these free spans
 		// at the end of GC and eliminate this entirely.
-		mHeap_Reclaim(h, npage)
+		h.reclaim(npage)
 	}
 
 	// transfer stats from cache to global
-	memstats.heap_live += uint64(_g_.m.mcache.local_cachealloc)
-	_g_.m.mcache.local_cachealloc = 0
 	memstats.heap_scan += uint64(_g_.m.mcache.local_scan)
 	_g_.m.mcache.local_scan = 0
 	memstats.tinyallocs += uint64(_g_.m.mcache.local_tinyallocs)
 	_g_.m.mcache.local_tinyallocs = 0
 
-	gcController.revise()
-
-	s := mHeap_AllocSpanLocked(h, npage)
+	s := h.allocSpanLocked(npage)
 	if s != nil {
 		// Record span info, because gc needs to be
 		// able to map interior pointer to containing span.
-		atomicstore(&s.sweepgen, h.sweepgen)
+		atomic.Store(&s.sweepgen, h.sweepgen)
 		s.state = _MSpanInUse
 		s.freelist = 0
 		s.ref = 0
@@ -447,17 +459,23 @@ func mHeap_Alloc_m(h *mheap, npage uintptr, sizeclass int32, large bool) *mspan
 		}
 
 		// update stats, sweep lists
+		h.pagesInUse += uint64(npage)
 		if large {
 			memstats.heap_objects++
-			memstats.heap_live += uint64(npage << _PageShift)
+			atomic.Xadd64(&memstats.heap_live, int64(npage<<_PageShift))
 			// Swept spans are at the end of lists.
 			if s.npages < uintptr(len(h.free)) {
-				mSpanList_InsertBack(&h.busy[s.npages], s)
+				h.busy[s.npages].insertBack(s)
 			} else {
-				mSpanList_InsertBack(&h.busylarge, s)
+				h.busylarge.insertBack(s)
 			}
 		}
 	}
+	// heap_scan and heap_live were updated.
+	if gcBlackenEnabled != 0 {
+		gcController.revise()
+	}
+
 	if trace.enabled {
 		traceHeapAlloc()
 	}
@@ -475,13 +493,13 @@ func mHeap_Alloc_m(h *mheap, npage uintptr, sizeclass int32, large bool) *mspan
 	return s
 }
 
-func mHeap_Alloc(h *mheap, npage uintptr, sizeclass int32, large bool, needzero bool) *mspan {
+func (h *mheap) alloc(npage uintptr, sizeclass int32, large bool, needzero bool) *mspan {
 	// Don't do any operations that lock the heap on the G stack.
 	// It might trigger stack growth, and the stack growth code needs
 	// to be able to allocate heap.
 	var s *mspan
 	systemstack(func() {
-		s = mHeap_Alloc_m(h, npage, sizeclass, large)
+		s = h.alloc_m(npage, sizeclass, large)
 	})
 
 	if s != nil {
@@ -493,13 +511,13 @@ func mHeap_Alloc(h *mheap, npage uintptr, sizeclass int32, large bool, needzero
 	return s
 }
 
-func mHeap_AllocStack(h *mheap, npage uintptr) *mspan {
+func (h *mheap) allocStack(npage uintptr) *mspan {
 	_g_ := getg()
 	if _g_ != _g_.m.g0 {
 		throw("mheap_allocstack not on g0 stack")
 	}
 	lock(&h.lock)
-	s := mHeap_AllocSpanLocked(h, npage)
+	s := h.allocSpanLocked(npage)
 	if s != nil {
 		s.state = _MSpanStack
 		s.freelist = 0
@@ -515,24 +533,27 @@ func mHeap_AllocStack(h *mheap, npage uintptr) *mspan {
 // Allocates a span of the given size.  h must be locked.
 // The returned span has been removed from the
 // free list, but its state is still MSpanFree.
-func mHeap_AllocSpanLocked(h *mheap, npage uintptr) *mspan {
+func (h *mheap) allocSpanLocked(npage uintptr) *mspan {
+	var list *mSpanList
 	var s *mspan
 
 	// Try in fixed-size lists up to max.
 	for i := int(npage); i < len(h.free); i++ {
-		if !mSpanList_IsEmpty(&h.free[i]) {
-			s = h.free[i].next
+		list = &h.free[i]
+		if !list.isEmpty() {
+			s = list.first
 			goto HaveSpan
 		}
 	}
 
 	// Best fit in list of large spans.
-	s = mHeap_AllocLarge(h, npage)
+	list = &h.freelarge
+	s = h.allocLarge(npage)
 	if s == nil {
-		if !mHeap_Grow(h, npage) {
+		if !h.grow(npage) {
 			return nil
 		}
-		s = mHeap_AllocLarge(h, npage)
+		s = h.allocLarge(npage)
 		if s == nil {
 			return nil
 		}
@@ -546,23 +567,23 @@ HaveSpan:
 	if s.npages < npage {
 		throw("MHeap_AllocLocked - bad npages")
 	}
-	mSpanList_Remove(s)
-	if s.next != nil || s.prev != nil {
+	list.remove(s)
+	if s.inList() {
 		throw("still in list")
 	}
 	if s.npreleased > 0 {
-		sysUsed((unsafe.Pointer)(s.start<<_PageShift), s.npages<<_PageShift)
+		sysUsed(unsafe.Pointer(s.start<<_PageShift), s.npages<<_PageShift)
 		memstats.heap_released -= uint64(s.npreleased << _PageShift)
 		s.npreleased = 0
 	}
 
 	if s.npages > npage {
 		// Trim extra and put it back in the heap.
-		t := (*mspan)(fixAlloc_Alloc(&h.spanalloc))
-		mSpan_Init(t, s.start+pageID(npage), s.npages-npage)
+		t := (*mspan)(h.spanalloc.alloc())
+		t.init(s.start+pageID(npage), s.npages-npage)
 		s.npages = npage
 		p := uintptr(t.start)
-		p -= (uintptr(unsafe.Pointer(h.arena_start)) >> _PageShift)
+		p -= (h.arena_start >> _PageShift)
 		if p > 0 {
 			h_spans[p-1] = s
 		}
@@ -571,13 +592,13 @@ HaveSpan:
 		t.needzero = s.needzero
 		s.state = _MSpanStack // prevent coalescing with s
 		t.state = _MSpanStack
-		mHeap_FreeSpanLocked(h, t, false, false, s.unusedsince)
+		h.freeSpanLocked(t, false, false, s.unusedsince)
 		s.state = _MSpanFree
 	}
 	s.unusedsince = 0
 
 	p := uintptr(s.start)
-	p -= (uintptr(unsafe.Pointer(h.arena_start)) >> _PageShift)
+	p -= (h.arena_start >> _PageShift)
 	for n := uintptr(0); n < npage; n++ {
 		h_spans[p+n] = s
 	}
@@ -586,22 +607,22 @@ HaveSpan:
 	memstats.heap_idle -= uint64(npage << _PageShift)
 
 	//println("spanalloc", hex(s.start<<_PageShift))
-	if s.next != nil || s.prev != nil {
+	if s.inList() {
 		throw("still in list")
 	}
 	return s
 }
 
 // Allocate a span of exactly npage pages from the list of large spans.
-func mHeap_AllocLarge(h *mheap, npage uintptr) *mspan {
+func (h *mheap) allocLarge(npage uintptr) *mspan {
 	return bestFit(&h.freelarge, npage, nil)
 }
 
 // Search list for smallest span with >= npage pages.
 // If there are multiple smallest spans, take the one
 // with the earliest starting address.
-func bestFit(list *mspan, npage uintptr, best *mspan) *mspan {
-	for s := list.next; s != list; s = s.next {
+func bestFit(list *mSpanList, npage uintptr, best *mspan) *mspan {
+	for s := list.first; s != nil; s = s.next {
 		if s.npages < npage {
 			continue
 		}
@@ -614,7 +635,9 @@ func bestFit(list *mspan, npage uintptr, best *mspan) *mspan {
 
 // Try to add at least npage pages of memory to the heap,
 // returning whether it worked.
-func mHeap_Grow(h *mheap, npage uintptr) bool {
+//
+// h must be locked.
+func (h *mheap) grow(npage uintptr) bool {
 	// Ask for a big chunk, to reduce the number of mappings
 	// the operating system needs to track; also amortizes
 	// the overhead of an operating system mapping.
@@ -625,11 +648,11 @@ func mHeap_Grow(h *mheap, npage uintptr) bool {
 		ask = _HeapAllocChunk
 	}
 
-	v := mHeap_SysAlloc(h, ask)
+	v := h.sysAlloc(ask)
 	if v == nil {
 		if ask > npage<<_PageShift {
 			ask = npage << _PageShift
-			v = mHeap_SysAlloc(h, ask)
+			v = h.sysAlloc(ask)
 		}
 		if v == nil {
 			print("runtime: out of memory: cannot allocate ", ask, "-byte block (", memstats.heap_sys, " in use)\n")
@@ -639,25 +662,26 @@ func mHeap_Grow(h *mheap, npage uintptr) bool {
 
 	// Create a fake "in use" span and free it, so that the
 	// right coalescing happens.
-	s := (*mspan)(fixAlloc_Alloc(&h.spanalloc))
-	mSpan_Init(s, pageID(uintptr(v)>>_PageShift), ask>>_PageShift)
+	s := (*mspan)(h.spanalloc.alloc())
+	s.init(pageID(uintptr(v)>>_PageShift), ask>>_PageShift)
 	p := uintptr(s.start)
-	p -= (uintptr(unsafe.Pointer(h.arena_start)) >> _PageShift)
+	p -= (h.arena_start >> _PageShift)
 	for i := p; i < p+s.npages; i++ {
 		h_spans[i] = s
 	}
-	atomicstore(&s.sweepgen, h.sweepgen)
+	atomic.Store(&s.sweepgen, h.sweepgen)
 	s.state = _MSpanInUse
-	mHeap_FreeSpanLocked(h, s, false, true, 0)
+	h.pagesInUse += uint64(npage)
+	h.freeSpanLocked(s, false, true, 0)
 	return true
 }
 
 // Look up the span at the given address.
 // Address is guaranteed to be in map
 // and is guaranteed to be start or end of span.
-func mHeap_Lookup(h *mheap, v unsafe.Pointer) *mspan {
+func (h *mheap) lookup(v unsafe.Pointer) *mspan {
 	p := uintptr(v)
-	p -= uintptr(unsafe.Pointer(h.arena_start))
+	p -= h.arena_start
 	return h_spans[p>>_PageShift]
 }
 
@@ -668,13 +692,13 @@ func mHeap_Lookup(h *mheap, v unsafe.Pointer) *mspan {
 // valid for allocated spans.  Free spans may have
 // other garbage in their middles, so we have to
 // check for that.
-func mHeap_LookupMaybe(h *mheap, v unsafe.Pointer) *mspan {
-	if uintptr(v) < uintptr(unsafe.Pointer(h.arena_start)) || uintptr(v) >= uintptr(unsafe.Pointer(h.arena_used)) {
+func (h *mheap) lookupMaybe(v unsafe.Pointer) *mspan {
+	if uintptr(v) < h.arena_start || uintptr(v) >= h.arena_used {
 		return nil
 	}
 	p := uintptr(v) >> _PageShift
 	q := p
-	q -= uintptr(unsafe.Pointer(h.arena_start)) >> _PageShift
+	q -= h.arena_start >> _PageShift
 	s := h_spans[q]
 	if s == nil || p < uintptr(s.start) || uintptr(v) >= uintptr(unsafe.Pointer(s.limit)) || s.state != _MSpanInUse {
 		return nil
@@ -683,12 +707,10 @@ func mHeap_LookupMaybe(h *mheap, v unsafe.Pointer) *mspan {
 }
 
 // Free the span back into the heap.
-func mHeap_Free(h *mheap, s *mspan, acct int32) {
+func (h *mheap) freeSpan(s *mspan, acct int32) {
 	systemstack(func() {
 		mp := getg().m
 		lock(&h.lock)
-		memstats.heap_live += uint64(mp.mcache.local_cachealloc)
-		mp.mcache.local_cachealloc = 0
 		memstats.heap_scan += uint64(mp.mcache.local_scan)
 		mp.mcache.local_scan = 0
 		memstats.tinyallocs += uint64(mp.mcache.local_tinyallocs)
@@ -696,16 +718,16 @@ func mHeap_Free(h *mheap, s *mspan, acct int32) {
 		if acct != 0 {
 			memstats.heap_objects--
 		}
-		gcController.revise()
-		mHeap_FreeSpanLocked(h, s, true, true, 0)
-		if trace.enabled {
-			traceHeapAlloc()
+		if gcBlackenEnabled != 0 {
+			// heap_scan changed.
+			gcController.revise()
 		}
+		h.freeSpanLocked(s, true, true, 0)
 		unlock(&h.lock)
 	})
 }
 
-func mHeap_FreeStack(h *mheap, s *mspan) {
+func (h *mheap) freeStack(s *mspan) {
 	_g_ := getg()
 	if _g_ != _g_.m.g0 {
 		throw("mheap_freestack not on g0 stack")
@@ -713,11 +735,12 @@ func mHeap_FreeStack(h *mheap, s *mspan) {
 	s.needzero = 1
 	lock(&h.lock)
 	memstats.stacks_inuse -= uint64(s.npages << _PageShift)
-	mHeap_FreeSpanLocked(h, s, true, true, 0)
+	h.freeSpanLocked(s, true, true, 0)
 	unlock(&h.lock)
 }
 
-func mHeap_FreeSpanLocked(h *mheap, s *mspan, acctinuse, acctidle bool, unusedsince int64) {
+// s must be on a busy list (h.busy or h.busylarge) or unlinked.
+func (h *mheap) freeSpanLocked(s *mspan, acctinuse, acctidle bool, unusedsince int64) {
 	switch s.state {
 	case _MSpanStack:
 		if s.ref != 0 {
@@ -728,6 +751,7 @@ func mHeap_FreeSpanLocked(h *mheap, s *mspan, acctinuse, acctidle bool, unusedsi
 			print("MHeap_FreeSpanLocked - span ", s, " ptr ", hex(s.start<<_PageShift), " ref ", s.ref, " sweepgen ", s.sweepgen, "/", h.sweepgen, "\n")
 			throw("MHeap_FreeSpanLocked - invalid free")
 		}
+		h.pagesInUse -= uint64(s.npages)
 	default:
 		throw("MHeap_FreeSpanLocked - invalid span state")
 	}
@@ -739,7 +763,9 @@ func mHeap_FreeSpanLocked(h *mheap, s *mspan, acctinuse, acctidle bool, unusedsi
 		memstats.heap_idle += uint64(s.npages << _PageShift)
 	}
 	s.state = _MSpanFree
-	mSpanList_Remove(s)
+	if s.inList() {
+		h.busyList(s.npages).remove(s)
+	}
 
 	// Stamp newly unused spans. The scavenger will use that
 	// info to potentially give back some pages to the OS.
@@ -751,44 +777,54 @@ func mHeap_FreeSpanLocked(h *mheap, s *mspan, acctinuse, acctidle bool, unusedsi
 
 	// Coalesce with earlier, later spans.
 	p := uintptr(s.start)
-	p -= uintptr(unsafe.Pointer(h.arena_start)) >> _PageShift
+	p -= h.arena_start >> _PageShift
 	if p > 0 {
 		t := h_spans[p-1]
-		if t != nil && t.state != _MSpanInUse && t.state != _MSpanStack {
+		if t != nil && t.state == _MSpanFree {
 			s.start = t.start
 			s.npages += t.npages
 			s.npreleased = t.npreleased // absorb released pages
 			s.needzero |= t.needzero
 			p -= t.npages
 			h_spans[p] = s
-			mSpanList_Remove(t)
+			h.freeList(t.npages).remove(t)
 			t.state = _MSpanDead
-			fixAlloc_Free(&h.spanalloc, (unsafe.Pointer)(t))
+			h.spanalloc.free(unsafe.Pointer(t))
 		}
 	}
-	if (p+s.npages)*ptrSize < h.spans_mapped {
+	if (p+s.npages)*sys.PtrSize < h.spans_mapped {
 		t := h_spans[p+s.npages]
-		if t != nil && t.state != _MSpanInUse && t.state != _MSpanStack {
+		if t != nil && t.state == _MSpanFree {
 			s.npages += t.npages
 			s.npreleased += t.npreleased
 			s.needzero |= t.needzero
 			h_spans[p+s.npages-1] = s
-			mSpanList_Remove(t)
+			h.freeList(t.npages).remove(t)
 			t.state = _MSpanDead
-			fixAlloc_Free(&h.spanalloc, (unsafe.Pointer)(t))
+			h.spanalloc.free(unsafe.Pointer(t))
 		}
 	}
 
 	// Insert s into appropriate list.
-	if s.npages < uintptr(len(h.free)) {
-		mSpanList_Insert(&h.free[s.npages], s)
-	} else {
-		mSpanList_Insert(&h.freelarge, s)
+	h.freeList(s.npages).insert(s)
+}
+
+func (h *mheap) freeList(npages uintptr) *mSpanList {
+	if npages < uintptr(len(h.free)) {
+		return &h.free[npages]
+	}
+	return &h.freelarge
+}
+
+func (h *mheap) busyList(npages uintptr) *mSpanList {
+	if npages < uintptr(len(h.free)) {
+		return &h.busy[npages]
 	}
+	return &h.busylarge
 }
 
-func scavengelist(list *mspan, now, limit uint64) uintptr {
-	if _PhysPageSize > _PageSize {
+func scavengelist(list *mSpanList, now, limit uint64) uintptr {
+	if sys.PhysPageSize > _PageSize {
 		// golang.org/issue/9993
 		// If the physical page size of the machine is larger than
 		// our logical heap page size the kernel may round up the
@@ -797,25 +833,24 @@ func scavengelist(list *mspan, now, limit uint64) uintptr {
 		return 0
 	}
 
-	if mSpanList_IsEmpty(list) {
+	if list.isEmpty() {
 		return 0
 	}
 
 	var sumreleased uintptr
-	for s := list.next; s != list; s = s.next {
+	for s := list.first; s != nil; s = s.next {
 		if (now-uint64(s.unusedsince)) > limit && s.npreleased != s.npages {
 			released := (s.npages - s.npreleased) << _PageShift
 			memstats.heap_released += uint64(released)
 			sumreleased += released
 			s.npreleased = s.npages
-			sysUnused((unsafe.Pointer)(s.start<<_PageShift), s.npages<<_PageShift)
+			sysUnused(unsafe.Pointer(s.start<<_PageShift), s.npages<<_PageShift)
 		}
 	}
 	return sumreleased
 }
 
-func mHeap_Scavenge(k int32, now, limit uint64) {
-	h := &mheap_
+func (h *mheap) scavenge(k int32, now, limit uint64) {
 	lock(&h.lock)
 	var sumreleased uintptr
 	for i := 0; i < len(h.free); i++ {
@@ -836,14 +871,15 @@ func mHeap_Scavenge(k int32, now, limit uint64) {
 
 //go:linkname runtime_debug_freeOSMemory runtime/debug.freeOSMemory
 func runtime_debug_freeOSMemory() {
-	startGC(gcForceBlockMode, false)
-	systemstack(func() { mHeap_Scavenge(-1, ^uint64(0), 0) })
+	gcStart(gcForceBlockMode, false)
+	systemstack(func() { mheap_.scavenge(-1, ^uint64(0), 0) })
 }
 
 // Initialize a new span with the given start and npages.
-func mSpan_Init(span *mspan, start pageID, npages uintptr) {
+func (span *mspan) init(start pageID, npages uintptr) {
 	span.next = nil
 	span.prev = nil
+	span.list = nil
 	span.start = start
 	span.npages = npages
 	span.freelist = 0
@@ -859,47 +895,64 @@ func mSpan_Init(span *mspan, start pageID, npages uintptr) {
 	span.needzero = 0
 }
 
+func (span *mspan) inList() bool {
+	return span.prev != nil
+}
+
 // Initialize an empty doubly-linked list.
-func mSpanList_Init(list *mspan) {
-	list.state = _MSpanListHead
-	list.next = list
-	list.prev = list
+func (list *mSpanList) init() {
+	list.first = nil
+	list.last = &list.first
 }
 
-func mSpanList_Remove(span *mspan) {
-	if span.prev == nil && span.next == nil {
-		return
+func (list *mSpanList) remove(span *mspan) {
+	if span.prev == nil || span.list != list {
+		println("failed MSpanList_Remove", span, span.prev, span.list, list)
+		throw("MSpanList_Remove")
 	}
-	span.prev.next = span.next
-	span.next.prev = span.prev
-	span.prev = nil
+	if span.next != nil {
+		span.next.prev = span.prev
+	} else {
+		// TODO: After we remove the span.list != list check above,
+		// we could at least still check list.last == &span.next here.
+		list.last = span.prev
+	}
+	*span.prev = span.next
 	span.next = nil
+	span.prev = nil
+	span.list = nil
 }
 
-func mSpanList_IsEmpty(list *mspan) bool {
-	return list.next == list
+func (list *mSpanList) isEmpty() bool {
+	return list.first == nil
 }
 
-func mSpanList_Insert(list *mspan, span *mspan) {
-	if span.next != nil || span.prev != nil {
-		println("failed MSpanList_Insert", span, span.next, span.prev)
+func (list *mSpanList) insert(span *mspan) {
+	if span.next != nil || span.prev != nil || span.list != nil {
+		println("failed MSpanList_Insert", span, span.next, span.prev, span.list)
 		throw("MSpanList_Insert")
 	}
-	span.next = list.next
-	span.prev = list
-	span.next.prev = span
-	span.prev.next = span
+	span.next = list.first
+	if list.first != nil {
+		list.first.prev = &span.next
+	} else {
+		list.last = &span.next
+	}
+	list.first = span
+	span.prev = &list.first
+	span.list = list
 }
 
-func mSpanList_InsertBack(list *mspan, span *mspan) {
-	if span.next != nil || span.prev != nil {
-		println("failed MSpanList_InsertBack", span, span.next, span.prev)
+func (list *mSpanList) insertBack(span *mspan) {
+	if span.next != nil || span.prev != nil || span.list != nil {
+		println("failed MSpanList_InsertBack", span, span.next, span.prev, span.list)
 		throw("MSpanList_InsertBack")
 	}
-	span.next = list
-	span.prev = list.prev
-	span.next.prev = span
-	span.prev.next = span
+	span.next = nil
+	span.prev = list.last
+	*list.last = span
+	list.last = &span.next
+	span.list = list
 }
 
 const (
@@ -924,15 +977,16 @@ type special struct {
 // (The add will fail only if a record with the same p and s->kind
 //  already exists.)
 func addspecial(p unsafe.Pointer, s *special) bool {
-	span := mHeap_LookupMaybe(&mheap_, p)
+	span := mheap_.lookupMaybe(p)
 	if span == nil {
 		throw("addspecial on invalid pointer")
 	}
 
 	// Ensure that the span is swept.
-	// GC accesses specials list w/o locks. And it's just much safer.
+	// Sweeping accesses the specials list w/o locks, so we have
+	// to synchronize with it. And it's just much safer.
 	mp := acquirem()
-	mSpan_EnsureSwept(span)
+	span.ensureSwept()
 
 	offset := uintptr(p) - uintptr(span.start<<_PageShift)
 	kind := s.kind
@@ -971,15 +1025,16 @@ func addspecial(p unsafe.Pointer, s *special) bool {
 // Returns the record if the record existed, nil otherwise.
 // The caller must FixAlloc_Free the result.
 func removespecial(p unsafe.Pointer, kind uint8) *special {
-	span := mHeap_LookupMaybe(&mheap_, p)
+	span := mheap_.lookupMaybe(p)
 	if span == nil {
 		throw("removespecial on invalid pointer")
 	}
 
 	// Ensure that the span is swept.
-	// GC accesses specials list w/o locks. And it's just much safer.
+	// Sweeping accesses the specials list w/o locks, so we have
+	// to synchronize with it. And it's just much safer.
 	mp := acquirem()
-	mSpan_EnsureSwept(span)
+	span.ensureSwept()
 
 	offset := uintptr(p) - uintptr(span.start<<_PageShift)
 
@@ -1017,7 +1072,7 @@ type specialfinalizer struct {
 // Adds a finalizer to the object p.  Returns true if it succeeded.
 func addfinalizer(p unsafe.Pointer, f *funcval, nret uintptr, fint *_type, ot *ptrtype) bool {
 	lock(&mheap_.speciallock)
-	s := (*specialfinalizer)(fixAlloc_Alloc(&mheap_.specialfinalizeralloc))
+	s := (*specialfinalizer)(mheap_.specialfinalizeralloc.alloc())
 	unlock(&mheap_.speciallock)
 	s.special.kind = _KindSpecialFinalizer
 	s.fn = f
@@ -1025,12 +1080,31 @@ func addfinalizer(p unsafe.Pointer, f *funcval, nret uintptr, fint *_type, ot *p
 	s.fint = fint
 	s.ot = ot
 	if addspecial(p, &s.special) {
+		// This is responsible for maintaining the same
+		// GC-related invariants as markrootSpans in any
+		// situation where it's possible that markrootSpans
+		// has already run but mark termination hasn't yet.
+		if gcphase != _GCoff {
+			_, base, _ := findObject(p)
+			mp := acquirem()
+			gcw := &mp.p.ptr().gcw
+			// Mark everything reachable from the object
+			// so it's retained for the finalizer.
+			scanobject(uintptr(base), gcw)
+			// Mark the finalizer itself, since the
+			// special isn't part of the GC'd heap.
+			scanblock(uintptr(unsafe.Pointer(&s.fn)), sys.PtrSize, &oneptrmask[0], gcw)
+			if gcBlackenPromptly {
+				gcw.dispose()
+			}
+			releasem(mp)
+		}
 		return true
 	}
 
 	// There was an old finalizer
 	lock(&mheap_.speciallock)
-	fixAlloc_Free(&mheap_.specialfinalizeralloc, (unsafe.Pointer)(s))
+	mheap_.specialfinalizeralloc.free(unsafe.Pointer(s))
 	unlock(&mheap_.speciallock)
 	return false
 }
@@ -1042,7 +1116,7 @@ func removefinalizer(p unsafe.Pointer) {
 		return // there wasn't a finalizer to remove
 	}
 	lock(&mheap_.speciallock)
-	fixAlloc_Free(&mheap_.specialfinalizeralloc, (unsafe.Pointer)(s))
+	mheap_.specialfinalizeralloc.free(unsafe.Pointer(s))
 	unlock(&mheap_.speciallock)
 }
 
@@ -1055,7 +1129,7 @@ type specialprofile struct {
 // Set the heap profile bucket associated with addr to b.
 func setprofilebucket(p unsafe.Pointer, b *bucket) {
 	lock(&mheap_.speciallock)
-	s := (*specialprofile)(fixAlloc_Alloc(&mheap_.specialprofilealloc))
+	s := (*specialprofile)(mheap_.specialprofilealloc.alloc())
 	unlock(&mheap_.speciallock)
 	s.special.kind = _KindSpecialProfile
 	s.b = b
@@ -1066,23 +1140,20 @@ func setprofilebucket(p unsafe.Pointer, b *bucket) {
 
 // Do whatever cleanup needs to be done to deallocate s.  It has
 // already been unlinked from the MSpan specials list.
-// Returns true if we should keep working on deallocating p.
-func freespecial(s *special, p unsafe.Pointer, size uintptr, freed bool) bool {
+func freespecial(s *special, p unsafe.Pointer, size uintptr) {
 	switch s.kind {
 	case _KindSpecialFinalizer:
 		sf := (*specialfinalizer)(unsafe.Pointer(s))
 		queuefinalizer(p, sf.fn, sf.nret, sf.fint, sf.ot)
 		lock(&mheap_.speciallock)
-		fixAlloc_Free(&mheap_.specialfinalizeralloc, (unsafe.Pointer)(sf))
+		mheap_.specialfinalizeralloc.free(unsafe.Pointer(sf))
 		unlock(&mheap_.speciallock)
-		return false // don't free p until finalizer is done
 	case _KindSpecialProfile:
 		sp := (*specialprofile)(unsafe.Pointer(s))
-		mProf_Free(sp.b, size, freed)
+		mProf_Free(sp.b, size)
 		lock(&mheap_.speciallock)
-		fixAlloc_Free(&mheap_.specialprofilealloc, (unsafe.Pointer)(sp))
+		mheap_.specialprofilealloc.free(unsafe.Pointer(sp))
 		unlock(&mheap_.speciallock)
-		return true
 	default:
 		throw("bad special kind")
 		panic("not reached")
diff --git a/src/runtime/mkduff.go b/src/runtime/mkduff.go
index dc94cee..0e7cc66 100644
--- a/src/runtime/mkduff.go
+++ b/src/runtime/mkduff.go
@@ -37,6 +37,7 @@ func main() {
 	gen("arm", notags, zeroARM, copyARM)
 	gen("arm64", notags, zeroARM64, copyARM64)
 	gen("ppc64x", tagsPPC64x, zeroPPC64x, copyPPC64x)
+	gen("mips64x", tagsMIPS64x, zeroMIPS64x, copyMIPS64x)
 }
 
 func gen(arch string, tags, zero, copy func(io.Writer)) {
@@ -60,21 +61,18 @@ func gen(arch string, tags, zero, copy func(io.Writer)) {
 func notags(w io.Writer) { fmt.Fprintln(w) }
 
 func zeroAMD64(w io.Writer) {
-	// AX: zero
+	// X0: zero
 	// DI: ptr to memory to be zeroed
 	// DI is updated as a side effect.
 	fmt.Fprintln(w, "TEXT runtime·duffzero(SB), NOSPLIT, $0-0")
-	for i := 0; i < 31; i++ {
-		fmt.Fprintln(w, "\tMOVQ\tAX,(DI)")
-		fmt.Fprintln(w, "\tMOVQ\tAX,8(DI)")
-		fmt.Fprintln(w, "\tMOVQ\tAX,16(DI)")
-		fmt.Fprintln(w, "\tMOVQ\tAX,24(DI)")
-		fmt.Fprintln(w, "\tADDQ\t$32,DI")
+	for i := 0; i < 16; i++ {
+		fmt.Fprintln(w, "\tMOVUPS\tX0,(DI)")
+		fmt.Fprintln(w, "\tMOVUPS\tX0,16(DI)")
+		fmt.Fprintln(w, "\tMOVUPS\tX0,32(DI)")
+		fmt.Fprintln(w, "\tMOVUPS\tX0,48(DI)")
+		fmt.Fprintln(w, "\tADDQ\t$64,DI")
 		fmt.Fprintln(w)
 	}
-	for i := 0; i < 4; i++ {
-		fmt.Fprintln(w, "\tSTOSQ")
-	}
 	fmt.Fprintln(w, "\tRET")
 }
 
@@ -87,11 +85,11 @@ func copyAMD64(w io.Writer) {
 	// for some reason that is 3.5x slower than this code.
 	// The STOSQ in duffzero seem fine, though.
 	fmt.Fprintln(w, "TEXT runtime·duffcopy(SB), NOSPLIT, $0-0")
-	for i := 0; i < 128; i++ {
-		fmt.Fprintln(w, "\tMOVQ\t(SI), CX")
-		fmt.Fprintln(w, "\tADDQ\t$8, SI")
-		fmt.Fprintln(w, "\tMOVQ\tCX, (DI)")
-		fmt.Fprintln(w, "\tADDQ\t$8, DI")
+	for i := 0; i < 64; i++ {
+		fmt.Fprintln(w, "\tMOVUPS\t(SI), X0")
+		fmt.Fprintln(w, "\tADDQ\t$16, SI")
+		fmt.Fprintln(w, "\tMOVUPS\tX0, (DI)")
+		fmt.Fprintln(w, "\tADDQ\t$16, DI")
 		fmt.Fprintln(w)
 	}
 	fmt.Fprintln(w, "\tRET")
@@ -176,13 +174,35 @@ func zeroPPC64x(w io.Writer) {
 	// R0: always zero
 	// R3 (aka REGRT1): ptr to memory to be zeroed - 8
 	// On return, R3 points to the last zeroed dword.
-	fmt.Fprintln(w, "TEXT runtime·duffzero(SB), NOSPLIT, $-8-0")
+	fmt.Fprintln(w, "TEXT runtime·duffzero(SB), NOSPLIT|NOFRAME, $0-0")
 	for i := 0; i < 128; i++ {
 		fmt.Fprintln(w, "\tMOVDU\tR0, 8(R3)")
 	}
-	fmt.Fprintln(w, "\tRETURN")
+	fmt.Fprintln(w, "\tRET")
 }
 
 func copyPPC64x(w io.Writer) {
 	fmt.Fprintln(w, "// TODO: Implement runtime·duffcopy.")
 }
+
+func tagsMIPS64x(w io.Writer) {
+	fmt.Fprintln(w)
+	fmt.Fprintln(w, "// +build mips64 mips64le")
+	fmt.Fprintln(w)
+}
+
+func zeroMIPS64x(w io.Writer) {
+	// R0: always zero
+	// R1 (aka REGRT1): ptr to memory to be zeroed - 8
+	// On return, R1 points to the last zeroed dword.
+	fmt.Fprintln(w, "TEXT runtime·duffzero(SB), NOSPLIT, $-8-0")
+	for i := 0; i < 128; i++ {
+		fmt.Fprintln(w, "\tMOVV\tR0, 8(R1)")
+		fmt.Fprintln(w, "\tADDV\t$8, R1")
+	}
+	fmt.Fprintln(w, "\tRET")
+}
+
+func copyMIPS64x(w io.Writer) {
+	fmt.Fprintln(w, "// TODO: Implement runtime·duffcopy.")
+}
diff --git a/src/runtime/mkfastlog2table.go b/src/runtime/mkfastlog2table.go
new file mode 100644
index 0000000..587ebf4
--- /dev/null
+++ b/src/runtime/mkfastlog2table.go
@@ -0,0 +1,52 @@
+// Copyright 2015 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.
+
+// +build ignore
+
+// fastlog2Table contains log2 approximations for 5 binary digits.
+// This is used to implement fastlog2, which is used for heap sampling.
+
+package main
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"log"
+	"math"
+)
+
+func main() {
+	var buf bytes.Buffer
+
+	fmt.Fprintln(&buf, "// AUTO-GENERATED by mkfastlog2table.go")
+	fmt.Fprintln(&buf, "// Run go generate from src/runtime to update.")
+	fmt.Fprintln(&buf, "// See mkfastlog2table.go for comments.")
+	fmt.Fprintln(&buf)
+	fmt.Fprintln(&buf, "package runtime")
+	fmt.Fprintln(&buf)
+	fmt.Fprintln(&buf, "const fastlogNumBits =", fastlogNumBits)
+	fmt.Fprintln(&buf)
+
+	fmt.Fprintln(&buf, "var fastlog2Table = [1<<fastlogNumBits + 1]float64{")
+	table := computeTable()
+	for _, t := range table {
+		fmt.Fprintf(&buf, "\t%v,\n", t)
+	}
+	fmt.Fprintln(&buf, "}")
+
+	if err := ioutil.WriteFile("fastlog2table.go", buf.Bytes(), 0644); err != nil {
+		log.Fatalln(err)
+	}
+}
+
+const fastlogNumBits = 5
+
+func computeTable() []float64 {
+	fastlog2Table := make([]float64, 1<<fastlogNumBits+1)
+	for i := 0; i <= (1 << fastlogNumBits); i++ {
+		fastlog2Table[i] = math.Log2(1.0 + float64(i)/(1<<fastlogNumBits))
+	}
+	return fastlog2Table
+}
diff --git a/src/runtime/mmap.go b/src/runtime/mmap.go
new file mode 100644
index 0000000..a076842
--- /dev/null
+++ b/src/runtime/mmap.go
@@ -0,0 +1,16 @@
+// Copyright 2015 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.
+
+// +build !plan9
+// +build !solaris
+// +build !windows
+// +build !nacl
+// +build !linux !amd64
+
+package runtime
+
+import "unsafe"
+
+// mmap calls the mmap system call.  It is implemented in assembly.
+func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer
diff --git a/src/runtime/mprof.go b/src/runtime/mprof.go
index a618bd5..fc73bbf 100644
--- a/src/runtime/mprof.go
+++ b/src/runtime/mprof.go
@@ -8,6 +8,7 @@
 package runtime
 
 import (
+	"runtime/internal/atomic"
 	"unsafe"
 )
 
@@ -250,16 +251,11 @@ func mProf_Malloc(p unsafe.Pointer, size uintptr) {
 }
 
 // Called when freeing a profiled block.
-func mProf_Free(b *bucket, size uintptr, freed bool) {
+func mProf_Free(b *bucket, size uintptr) {
 	lock(&proflock)
 	mp := b.mp()
-	if freed {
-		mp.recent_frees++
-		mp.recent_free_bytes += size
-	} else {
-		mp.prev_frees++
-		mp.prev_free_bytes += size
-	}
+	mp.prev_frees++
+	mp.prev_free_bytes += size
 	unlock(&proflock)
 }
 
@@ -285,14 +281,14 @@ func SetBlockProfileRate(rate int) {
 		}
 	}
 
-	atomicstore64(&blockprofilerate, uint64(r))
+	atomic.Store64(&blockprofilerate, uint64(r))
 }
 
 func blockevent(cycles int64, skip int) {
 	if cycles <= 0 {
 		cycles = 1
 	}
-	rate := int64(atomicload64(&blockprofilerate))
+	rate := int64(atomic.Load64(&blockprofilerate))
 	if rate <= 0 || (rate > cycles && int64(fastrand1())%rate > cycles) {
 		return
 	}
@@ -372,6 +368,9 @@ func (r *MemProfileRecord) Stack() []uintptr {
 	return r.Stack0[0:]
 }
 
+// MemProfile returns a profile of memory allocated and freed per allocation
+// site.
+//
 // MemProfile returns n, the number of records in the current memory profile.
 // If len(p) >= n, MemProfile copies the profile into p and returns n, true.
 // If len(p) < n, MemProfile does not change p and returns n, false.
@@ -381,6 +380,12 @@ func (r *MemProfileRecord) Stack() []uintptr {
 // These are sites where memory was allocated, but it has all
 // been released back to the runtime.
 //
+// The returned profile may be up to two garbage collection cycles old.
+// This is to avoid skewing the profile toward allocations; because
+// allocations happen in real time but frees are delayed until the garbage
+// collector performs sweeping, the profile only accounts for allocations
+// that have had a chance to be freed by the garbage collector.
+//
 // Most clients should use the runtime/pprof package or
 // the testing package's -test.memprofile flag instead
 // of calling MemProfile directly.
@@ -493,7 +498,7 @@ func BlockProfile(p []BlockProfileRecord) (n int, ok bool) {
 // Most clients should use the runtime/pprof package instead
 // of calling ThreadCreateProfile directly.
 func ThreadCreateProfile(p []StackRecord) (n int, ok bool) {
-	first := (*m)(atomicloadp(unsafe.Pointer(&allm)))
+	first := (*m)(atomic.Loadp(unsafe.Pointer(&allm)))
 	for mp := first; mp != nil; mp = mp.alllink {
 		n++
 	}
@@ -517,34 +522,51 @@ func ThreadCreateProfile(p []StackRecord) (n int, ok bool) {
 // Most clients should use the runtime/pprof package instead
 // of calling GoroutineProfile directly.
 func GoroutineProfile(p []StackRecord) (n int, ok bool) {
+	gp := getg()
+
+	isOK := func(gp1 *g) bool {
+		// Checking isSystemGoroutine here makes GoroutineProfile
+		// consistent with both NumGoroutine and Stack.
+		return gp1 != gp && readgstatus(gp1) != _Gdead && !isSystemGoroutine(gp1)
+	}
+
+	stopTheWorld("profile")
+
+	n = 1
+	for _, gp1 := range allgs {
+		if isOK(gp1) {
+			n++
+		}
+	}
 
-	n = NumGoroutine()
 	if n <= len(p) {
-		gp := getg()
-		stopTheWorld("profile")
-
-		n = NumGoroutine()
-		if n <= len(p) {
-			ok = true
-			r := p
-			sp := getcallersp(unsafe.Pointer(&p))
-			pc := getcallerpc(unsafe.Pointer(&p))
-			systemstack(func() {
-				saveg(pc, sp, gp, &r[0])
-			})
-			r = r[1:]
-			for _, gp1 := range allgs {
-				if gp1 == gp || readgstatus(gp1) == _Gdead {
-					continue
+		ok = true
+		r := p
+
+		// Save current goroutine.
+		sp := getcallersp(unsafe.Pointer(&p))
+		pc := getcallerpc(unsafe.Pointer(&p))
+		systemstack(func() {
+			saveg(pc, sp, gp, &r[0])
+		})
+		r = r[1:]
+
+		// Save other goroutines.
+		for _, gp1 := range allgs {
+			if isOK(gp1) {
+				if len(r) == 0 {
+					// Should be impossible, but better to return a
+					// truncated profile than to crash the entire process.
+					break
 				}
 				saveg(^uintptr(0), ^uintptr(0), gp1, &r[0])
 				r = r[1:]
 			}
 		}
-
-		startTheWorld()
 	}
 
+	startTheWorld()
+
 	return n, ok
 }
 
@@ -571,12 +593,17 @@ func Stack(buf []byte, all bool) int {
 		pc := getcallerpc(unsafe.Pointer(&buf))
 		systemstack(func() {
 			g0 := getg()
+			// Force traceback=1 to override GOTRACEBACK setting,
+			// so that Stack's results are consistent.
+			// GOTRACEBACK is only about crash dumps.
+			g0.m.traceback = 1
 			g0.writebuf = buf[0:0:len(buf)]
 			goroutineheader(gp)
 			traceback(pc, sp, 0, gp)
 			if all {
 				tracebackothers(gp)
 			}
+			g0.m.traceback = 0
 			n = len(g0.writebuf)
 			g0.writebuf = nil
 		})
diff --git a/src/runtime/msan.go b/src/runtime/msan.go
new file mode 100644
index 0000000..4dbdf05
--- /dev/null
+++ b/src/runtime/msan.go
@@ -0,0 +1,55 @@
+// Copyright 2015 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.
+
+// +build msan
+
+package runtime
+
+import (
+	"unsafe"
+)
+
+// Public memory sanitizer API.
+
+func MSanRead(addr unsafe.Pointer, len int) {
+	msanread(addr, uintptr(len))
+}
+
+func MSanWrite(addr unsafe.Pointer, len int) {
+	msanwrite(addr, uintptr(len))
+}
+
+// Private interface for the runtime.
+const msanenabled = true
+
+// If we are running on the system stack, the C program may have
+// marked part of that stack as uninitialized.  We don't instrument
+// the runtime, but operations like a slice copy can call msanread
+// anyhow for values on the stack.  Just ignore msanread when running
+// on the system stack.  The other msan functions are fine.
+func msanread(addr unsafe.Pointer, sz uintptr) {
+	g := getg()
+	if g == g.m.g0 || g == g.m.gsignal {
+		return
+	}
+	domsanread(addr, sz)
+}
+
+//go:noescape
+func domsanread(addr unsafe.Pointer, sz uintptr)
+
+//go:noescape
+func msanwrite(addr unsafe.Pointer, sz uintptr)
+
+//go:noescape
+func msanmalloc(addr unsafe.Pointer, sz uintptr)
+
+//go:noescape
+func msanfree(addr unsafe.Pointer, sz uintptr)
+
+// These are called from msan_amd64.s
+//go:cgo_import_static __msan_read_go
+//go:cgo_import_static __msan_write_go
+//go:cgo_import_static __msan_malloc_go
+//go:cgo_import_static __msan_free_go
diff --git a/src/runtime/msan/msan.go b/src/runtime/msan/msan.go
new file mode 100644
index 0000000..b6ea3f0
--- /dev/null
+++ b/src/runtime/msan/msan.go
@@ -0,0 +1,32 @@
+// Copyright 2015 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.
+
+// +build msan,linux,amd64
+
+package msan
+
+/*
+#cgo CFLAGS: -fsanitize=memory
+#cgo LDFLAGS: -fsanitize=memory
+
+#include <stdint.h>
+#include <sanitizer/msan_interface.h>
+
+void __msan_read_go(void *addr, uintptr_t sz) {
+	__msan_check_mem_is_initialized(addr, sz);
+}
+
+void __msan_write_go(void *addr, uintptr_t sz) {
+	__msan_unpoison(addr, sz);
+}
+
+void __msan_malloc_go(void *addr, uintptr_t sz) {
+	__msan_unpoison(addr, sz);
+}
+
+void __msan_free_go(void *addr, uintptr_t sz) {
+	__msan_poison(addr, sz);
+}
+*/
+import "C"
diff --git a/src/runtime/msan0.go b/src/runtime/msan0.go
new file mode 100644
index 0000000..e206720
--- /dev/null
+++ b/src/runtime/msan0.go
@@ -0,0 +1,22 @@
+// Copyright 2015 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.
+
+// +build !msan
+
+// Dummy MSan support API, used when not built with -msan.
+
+package runtime
+
+import (
+	"unsafe"
+)
+
+const msanenabled = false
+
+// Because msanenabled is false, none of these functions should be called.
+
+func msanread(addr unsafe.Pointer, sz uintptr)   { throw("msan") }
+func msanwrite(addr unsafe.Pointer, sz uintptr)  { throw("msan") }
+func msanmalloc(addr unsafe.Pointer, sz uintptr) { throw("msan") }
+func msanfree(addr unsafe.Pointer, sz uintptr)   { throw("msan") }
diff --git a/src/runtime/msan_amd64.s b/src/runtime/msan_amd64.s
new file mode 100644
index 0000000..6131495
--- /dev/null
+++ b/src/runtime/msan_amd64.s
@@ -0,0 +1,76 @@
+// Copyright 2015 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.
+
+// +build msan
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "funcdata.h"
+#include "textflag.h"
+
+// This is like race_amd64.s, but for the msan calls.
+// See race_amd64.s for detailed comments.
+
+#ifdef GOOS_windows
+#define RARG0 CX
+#define RARG1 DX
+#define RARG2 R8
+#define RARG3 R9
+#else
+#define RARG0 DI
+#define RARG1 SI
+#define RARG2 DX
+#define RARG3 CX
+#endif
+
+// func runtime·domsanread(addr unsafe.Pointer, sz uintptr)
+// Called from msanread.
+TEXT	runtime·domsanread(SB), NOSPLIT, $0-16
+	MOVQ	addr+0(FP), RARG0
+	MOVQ	size+8(FP), RARG1
+	// void __msan_read_go(void *addr, uintptr_t sz);
+	MOVQ	$__msan_read_go(SB), AX
+	JMP	msancall<>(SB)
+
+// func runtime·msanwrite(addr unsafe.Pointer, sz uintptr)
+// Called from instrumented code.
+TEXT	runtime·msanwrite(SB), NOSPLIT, $0-16
+	MOVQ	addr+0(FP), RARG0
+	MOVQ	size+8(FP), RARG1
+	// void __msan_write_go(void *addr, uintptr_t sz);
+	MOVQ	$__msan_write_go(SB), AX
+	JMP	msancall<>(SB)
+
+// func runtime·msanmalloc(addr unsafe.Pointer, sz uintptr)
+TEXT	runtime·msanmalloc(SB), NOSPLIT, $0-16
+	MOVQ	addr+0(FP), RARG0
+	MOVQ	size+8(FP), RARG1
+	// void __msan_malloc_go(void *addr, uintptr_t sz);
+	MOVQ	$__msan_malloc_go(SB), AX
+	JMP	msancall<>(SB)
+
+// func runtime·msanfree(addr unsafe.Pointer, sz uintptr)
+TEXT	runtime·msanfree(SB), NOSPLIT, $0-16
+	MOVQ	addr+0(FP), RARG0
+	MOVQ	size+8(FP), RARG1
+	// void __msan_free_go(void *addr, uintptr_t sz);
+	MOVQ	$__msan_free_go(SB), AX
+	JMP	msancall<>(SB)
+
+// Switches SP to g0 stack and calls (AX). Arguments already set.
+TEXT	msancall<>(SB), NOSPLIT, $0-0
+	get_tls(R12)
+	MOVQ	g(R12), R14
+	MOVQ	g_m(R14), R13
+	// Switch to g0 stack.
+	MOVQ	SP, R12		// callee-saved, preserved across the CALL
+	MOVQ	m_g0(R13), R10
+	CMPQ	R10, R14
+	JE	call	// already on g0
+	MOVQ	(g_sched+gobuf_sp)(R10), SP
+call:
+	ANDQ	$~15, SP	// alignment for gcc ABI
+	CALL	AX
+	MOVQ	R12, SP
+	RET
diff --git a/src/runtime/mstats.go b/src/runtime/mstats.go
index 08b82e0..368687d 100644
--- a/src/runtime/mstats.go
+++ b/src/runtime/mstats.go
@@ -6,7 +6,11 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 // Statistics.
 // If you edit this structure, also edit type MemStats below.
@@ -42,7 +46,7 @@ type mstats struct {
 
 	// Statistics about garbage collector.
 	// Protected by mheap or stopping the world during GC.
-	next_gc         uint64 // next gc (in heap_alloc time)
+	next_gc         uint64 // next gc (in heap_live time)
 	last_gc         uint64 // last gc (in absolute time)
 	pause_total_ns  uint64
 	pause_ns        [256]uint64 // circular buffer of recent gc pause lengths
@@ -66,13 +70,33 @@ type mstats struct {
 
 	// heap_live is the number of bytes considered live by the GC.
 	// That is: retained by the most recent GC plus allocated
-	// since then. heap_live <= heap_alloc, since heap_live
-	// excludes unmarked objects that have not yet been swept.
+	// since then. heap_live <= heap_alloc, since heap_alloc
+	// includes unmarked objects that have not yet been swept (and
+	// hence goes up as we allocate and down as we sweep) while
+	// heap_live excludes these objects (and hence only goes up
+	// between GCs).
+	//
+	// This is updated atomically without locking. To reduce
+	// contention, this is updated only when obtaining a span from
+	// an mcentral and at this point it counts all of the
+	// unallocated slots in that span (which will be allocated
+	// before that mcache obtains another span from that
+	// mcentral). Hence, it slightly overestimates the "true" live
+	// heap size. It's better to overestimate than to
+	// underestimate because 1) this triggers the GC earlier than
+	// necessary rather than potentially too late and 2) this
+	// leads to a conservative GC rate rather than a GC rate that
+	// is potentially too low.
+	//
+	// Whenever this is updated, call traceHeapAlloc() and
+	// gcController.revise().
 	heap_live uint64
 
 	// heap_scan is the number of bytes of "scannable" heap. This
 	// is the live heap (as counted by heap_live), but omitting
 	// no-scan objects and no-scan tails of objects.
+	//
+	// Whenever this is updated, call gcController.revise().
 	heap_scan uint64
 
 	// heap_marked is the number of bytes marked by the previous
@@ -322,7 +346,7 @@ func flushallmcaches() {
 		if c == nil {
 			continue
 		}
-		mCache_ReleaseAll(c)
+		c.releaseAll()
 		stackcache_clear(c)
 	}
 }
@@ -331,11 +355,6 @@ func flushallmcaches() {
 func purgecachedstats(c *mcache) {
 	// Protected by either heap or GC lock.
 	h := &mheap_
-	memstats.heap_live += uint64(c.local_cachealloc)
-	c.local_cachealloc = 0
-	if trace.enabled {
-		traceHeapAlloc()
-	}
 	memstats.heap_scan += uint64(c.local_scan)
 	c.local_scan = 0
 	memstats.tinyallocs += uint64(c.local_tinyallocs)
@@ -366,11 +385,11 @@ func purgecachedstats(c *mcache) {
 // overflow errors.
 //go:nosplit
 func mSysStatInc(sysStat *uint64, n uintptr) {
-	if _BigEndian != 0 {
-		xadd64(sysStat, int64(n))
+	if sys.BigEndian != 0 {
+		atomic.Xadd64(sysStat, int64(n))
 		return
 	}
-	if val := xadduintptr((*uintptr)(unsafe.Pointer(sysStat)), n); val < n {
+	if val := atomic.Xadduintptr((*uintptr)(unsafe.Pointer(sysStat)), n); val < n {
 		print("runtime: stat overflow: val ", val, ", n ", n, "\n")
 		exit(2)
 	}
@@ -380,11 +399,11 @@ func mSysStatInc(sysStat *uint64, n uintptr) {
 // mSysStatInc apply.
 //go:nosplit
 func mSysStatDec(sysStat *uint64, n uintptr) {
-	if _BigEndian != 0 {
-		xadd64(sysStat, -int64(n))
+	if sys.BigEndian != 0 {
+		atomic.Xadd64(sysStat, -int64(n))
 		return
 	}
-	if val := xadduintptr((*uintptr)(unsafe.Pointer(sysStat)), uintptr(-int64(n))); val+n < n {
+	if val := atomic.Xadduintptr((*uintptr)(unsafe.Pointer(sysStat)), uintptr(-int64(n))); val+n < n {
 		print("runtime: stat underflow: val ", val, ", n ", n, "\n")
 		exit(2)
 	}
diff --git a/src/runtime/mstkbar.go b/src/runtime/mstkbar.go
new file mode 100644
index 0000000..016625a
--- /dev/null
+++ b/src/runtime/mstkbar.go
@@ -0,0 +1,365 @@
+// Copyright 2015 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.
+
+// Garbage collector: stack barriers
+//
+// Stack barriers enable the garbage collector to determine how much
+// of a gorountine stack has changed between when a stack is scanned
+// during the concurrent scan phase and when it is re-scanned during
+// the stop-the-world mark termination phase. Mark termination only
+// needs to re-scan the changed part, so for deep stacks this can
+// significantly reduce GC pause time compared to the alternative of
+// re-scanning whole stacks. The deeper the stacks, the more stack
+// barriers help.
+//
+// When stacks are scanned during the concurrent scan phase, the stack
+// scan installs stack barriers by selecting stack frames and
+// overwriting the saved return PCs (or link registers) of these
+// frames with the PC of a "stack barrier trampoline". Later, when a
+// selected frame returns, it "returns" to this trampoline instead of
+// returning to its actual caller. The trampoline records that the
+// stack has unwound past this frame and jumps to the original return
+// PC recorded when the stack barrier was installed. Mark termination
+// re-scans only as far as the first frame that hasn't hit a stack
+// barrier and then removes and un-hit stack barriers.
+//
+// This scheme is very lightweight. No special code is required in the
+// mutator to record stack unwinding and the trampoline is only a few
+// assembly instructions.
+//
+// Book-keeping
+// ------------
+//
+// The primary cost of stack barriers is book-keeping: the runtime has
+// to record the locations of all stack barriers and the original
+// return PCs in order to return to the correct caller when a stack
+// barrier is hit and so it can remove un-hit stack barriers. In order
+// to minimize this cost, the Go runtime places stack barriers in
+// exponentially-spaced frames, starting 1K past the current frame.
+// The book-keeping structure hence grows logarithmically with the
+// size of the stack and mark termination re-scans at most twice as
+// much stack as necessary.
+//
+// The runtime reserves space for this book-keeping structure at the
+// top of the stack allocation itself (just above the outermost
+// frame). This is necessary because the regular memory allocator can
+// itself grow the stack, and hence can't be used when allocating
+// stack-related structures.
+//
+// For debugging, the runtime also supports installing stack barriers
+// at every frame. However, this requires significantly more
+// book-keeping space.
+//
+// Correctness
+// -----------
+//
+// The runtime and the compiler cooperate to ensure that all objects
+// reachable from the stack as of mark termination are marked.
+// Anything unchanged since the concurrent scan phase will be marked
+// because it is marked by the concurrent scan. After the concurrent
+// scan, there are three possible classes of stack modifications that
+// must be tracked:
+//
+// 1) Mutator writes below the lowest un-hit stack barrier. This
+// includes all writes performed by an executing function to its own
+// stack frame. This part of the stack will be re-scanned by mark
+// termination, which will mark any objects made reachable from
+// modifications to this part of the stack.
+//
+// 2) Mutator writes above the lowest un-hit stack barrier. It's
+// possible for a mutator to modify the stack above the lowest un-hit
+// stack barrier if a higher frame has passed down a pointer to a
+// stack variable in its frame. This is called an "up-pointer". The
+// compiler ensures that writes through up-pointers have an
+// accompanying write barrier (it simply doesn't distinguish between
+// writes through up-pointers and writes through heap pointers). This
+// write barrier marks any object made reachable from modifications to
+// this part of the stack.
+//
+// 3) Runtime writes to the stack. Various runtime operations such as
+// sends to unbuffered channels can write to arbitrary parts of the
+// stack, including above the lowest un-hit stack barrier. We solve
+// this in two ways. In many cases, the runtime can perform an
+// explicit write barrier operation like in case 2. However, in the
+// case of bulk memory move (typedmemmove), the runtime doesn't
+// necessary have ready access to a pointer bitmap for the memory
+// being copied, so it simply unwinds any stack barriers below the
+// destination.
+//
+// Gotchas
+// -------
+//
+// Anything that inspects or manipulates the stack potentially needs
+// to understand stack barriers. The most obvious case is that
+// gentraceback needs to use the original return PC when it encounters
+// the stack barrier trampoline. Anything that unwinds the stack such
+// as panic/recover must unwind stack barriers in tandem with
+// unwinding the stack.
+//
+// Stack barriers require that any goroutine whose stack has been
+// scanned must execute write barriers. Go solves this by simply
+// enabling write barriers globally during the concurrent scan phase.
+// However, traditionally, write barriers are not enabled during this
+// phase.
+//
+// Synchronization
+// ---------------
+//
+// For the most part, accessing and modifying stack barriers is
+// synchronized around GC safe points. Installing stack barriers
+// forces the G to a safe point, while all other operations that
+// modify stack barriers run on the G and prevent it from reaching a
+// safe point.
+//
+// Subtlety arises when a G may be tracebacked when *not* at a safe
+// point. This happens during sigprof. For this, each G has a "stack
+// barrier lock" (see gcLockStackBarriers, gcUnlockStackBarriers).
+// Operations that manipulate stack barriers acquire this lock, while
+// sigprof tries to acquire it and simply skips the traceback if it
+// can't acquire it. There is one exception for performance and
+// complexity reasons: hitting a stack barrier manipulates the stack
+// barrier list without acquiring the stack barrier lock. For this,
+// gentraceback performs a special fix up if the traceback starts in
+// the stack barrier function.
+
+package runtime
+
+import (
+	"runtime/internal/atomic"
+	"runtime/internal/sys"
+	"unsafe"
+)
+
+const debugStackBarrier = false
+
+// firstStackBarrierOffset is the approximate byte offset at
+// which to place the first stack barrier from the current SP.
+// This is a lower bound on how much stack will have to be
+// re-scanned during mark termination. Subsequent barriers are
+// placed at firstStackBarrierOffset * 2^n offsets.
+//
+// For debugging, this can be set to 0, which will install a
+// stack barrier at every frame. If you do this, you may also
+// have to raise _StackMin, since the stack barrier
+// bookkeeping will use a large amount of each stack.
+var firstStackBarrierOffset = 1024
+
+// gcMaxStackBarriers returns the maximum number of stack barriers
+// that can be installed in a stack of stackSize bytes.
+func gcMaxStackBarriers(stackSize int) (n int) {
+	if firstStackBarrierOffset == 0 {
+		// Special debugging case for inserting stack barriers
+		// at every frame. Steal half of the stack for the
+		// []stkbar. Technically, if the stack were to consist
+		// solely of return PCs we would need two thirds of
+		// the stack, but stealing that much breaks things and
+		// this doesn't happen in practice.
+		return stackSize / 2 / int(unsafe.Sizeof(stkbar{}))
+	}
+
+	offset := firstStackBarrierOffset
+	for offset < stackSize {
+		n++
+		offset *= 2
+	}
+	return n + 1
+}
+
+// gcInstallStackBarrier installs a stack barrier over the return PC of frame.
+//go:nowritebarrier
+func gcInstallStackBarrier(gp *g, frame *stkframe) bool {
+	if frame.lr == 0 {
+		if debugStackBarrier {
+			print("not installing stack barrier with no LR, goid=", gp.goid, "\n")
+		}
+		return false
+	}
+
+	if frame.fn.entry == cgocallback_gofuncPC {
+		// cgocallback_gofunc doesn't return to its LR;
+		// instead, its return path puts LR in g.sched.pc and
+		// switches back to the system stack on which
+		// cgocallback_gofunc was originally called. We can't
+		// have a stack barrier in g.sched.pc, so don't
+		// install one in this frame.
+		if debugStackBarrier {
+			print("not installing stack barrier over LR of cgocallback_gofunc, goid=", gp.goid, "\n")
+		}
+		return false
+	}
+
+	// Save the return PC and overwrite it with stackBarrier.
+	var lrUintptr uintptr
+	if usesLR {
+		lrUintptr = frame.sp
+	} else {
+		lrUintptr = frame.fp - sys.RegSize
+	}
+	lrPtr := (*sys.Uintreg)(unsafe.Pointer(lrUintptr))
+	if debugStackBarrier {
+		print("install stack barrier at ", hex(lrUintptr), " over ", hex(*lrPtr), ", goid=", gp.goid, "\n")
+		if uintptr(*lrPtr) != frame.lr {
+			print("frame.lr=", hex(frame.lr))
+			throw("frame.lr differs from stack LR")
+		}
+	}
+
+	gp.stkbar = gp.stkbar[:len(gp.stkbar)+1]
+	stkbar := &gp.stkbar[len(gp.stkbar)-1]
+	stkbar.savedLRPtr = lrUintptr
+	stkbar.savedLRVal = uintptr(*lrPtr)
+	*lrPtr = sys.Uintreg(stackBarrierPC)
+	return true
+}
+
+// gcRemoveStackBarriers removes all stack barriers installed in gp's stack.
+//go:nowritebarrier
+func gcRemoveStackBarriers(gp *g) {
+	if debugStackBarrier && gp.stkbarPos != 0 {
+		print("hit ", gp.stkbarPos, " stack barriers, goid=", gp.goid, "\n")
+	}
+
+	gcLockStackBarriers(gp)
+
+	// Remove stack barriers that we didn't hit.
+	for _, stkbar := range gp.stkbar[gp.stkbarPos:] {
+		gcRemoveStackBarrier(gp, stkbar)
+	}
+
+	// Clear recorded stack barriers so copystack doesn't try to
+	// adjust them.
+	gp.stkbarPos = 0
+	gp.stkbar = gp.stkbar[:0]
+
+	gcUnlockStackBarriers(gp)
+}
+
+// gcRemoveStackBarrier removes a single stack barrier. It is the
+// inverse operation of gcInstallStackBarrier.
+//
+// This is nosplit to ensure gp's stack does not move.
+//
+//go:nowritebarrier
+//go:nosplit
+func gcRemoveStackBarrier(gp *g, stkbar stkbar) {
+	if debugStackBarrier {
+		print("remove stack barrier at ", hex(stkbar.savedLRPtr), " with ", hex(stkbar.savedLRVal), ", goid=", gp.goid, "\n")
+	}
+	lrPtr := (*sys.Uintreg)(unsafe.Pointer(stkbar.savedLRPtr))
+	if val := *lrPtr; val != sys.Uintreg(stackBarrierPC) {
+		printlock()
+		print("at *", hex(stkbar.savedLRPtr), " expected stack barrier PC ", hex(stackBarrierPC), ", found ", hex(val), ", goid=", gp.goid, "\n")
+		print("gp.stkbar=")
+		gcPrintStkbars(gp, -1)
+		print(", gp.stack=[", hex(gp.stack.lo), ",", hex(gp.stack.hi), ")\n")
+		throw("stack barrier lost")
+	}
+	*lrPtr = sys.Uintreg(stkbar.savedLRVal)
+}
+
+// gcPrintStkbars prints the stack barriers of gp for debugging. It
+// places a "@@@" marker at gp.stkbarPos. If marker >= 0, it will also
+// place a "==>" marker before the marker'th entry.
+func gcPrintStkbars(gp *g, marker int) {
+	print("[")
+	for i, s := range gp.stkbar {
+		if i > 0 {
+			print(" ")
+		}
+		if i == int(gp.stkbarPos) {
+			print("@@@ ")
+		}
+		if i == marker {
+			print("==> ")
+		}
+		print("*", hex(s.savedLRPtr), "=", hex(s.savedLRVal))
+	}
+	if int(gp.stkbarPos) == len(gp.stkbar) {
+		print(" @@@")
+	}
+	if marker == len(gp.stkbar) {
+		print(" ==>")
+	}
+	print("]")
+}
+
+// gcUnwindBarriers marks all stack barriers up the frame containing
+// sp as hit and removes them. This is used during stack unwinding for
+// panic/recover and by heapBitsBulkBarrier to force stack re-scanning
+// when its destination is on the stack.
+//
+// This is nosplit to ensure gp's stack does not move.
+//
+//go:nosplit
+func gcUnwindBarriers(gp *g, sp uintptr) {
+	gcLockStackBarriers(gp)
+	// On LR machines, if there is a stack barrier on the return
+	// from the frame containing sp, this will mark it as hit even
+	// though it isn't, but it's okay to be conservative.
+	before := gp.stkbarPos
+	for int(gp.stkbarPos) < len(gp.stkbar) && gp.stkbar[gp.stkbarPos].savedLRPtr < sp {
+		gcRemoveStackBarrier(gp, gp.stkbar[gp.stkbarPos])
+		gp.stkbarPos++
+	}
+	gcUnlockStackBarriers(gp)
+	if debugStackBarrier && gp.stkbarPos != before {
+		print("skip barriers below ", hex(sp), " in goid=", gp.goid, ": ")
+		// We skipped barriers between the "==>" marker
+		// (before) and the "@@@" marker (gp.stkbarPos).
+		gcPrintStkbars(gp, int(before))
+		print("\n")
+	}
+}
+
+// nextBarrierPC returns the original return PC of the next stack barrier.
+// Used by getcallerpc, so it must be nosplit.
+//go:nosplit
+func nextBarrierPC() uintptr {
+	gp := getg()
+	return gp.stkbar[gp.stkbarPos].savedLRVal
+}
+
+// setNextBarrierPC sets the return PC of the next stack barrier.
+// Used by setcallerpc, so it must be nosplit.
+//go:nosplit
+func setNextBarrierPC(pc uintptr) {
+	gp := getg()
+	gcLockStackBarriers(gp)
+	gp.stkbar[gp.stkbarPos].savedLRVal = pc
+	gcUnlockStackBarriers(gp)
+}
+
+// gcLockStackBarriers synchronizes with tracebacks of gp's stack
+// during sigprof for installation or removal of stack barriers. It
+// blocks until any current sigprof is done tracebacking gp's stack
+// and then disallows profiling tracebacks of gp's stack.
+//
+// This is necessary because a sigprof during barrier installation or
+// removal could observe inconsistencies between the stkbar array and
+// the stack itself and crash.
+//
+//go:nosplit
+func gcLockStackBarriers(gp *g) {
+	// Disable preemption so scanstack cannot run while the caller
+	// is manipulating the stack barriers.
+	acquirem()
+	for !atomic.Cas(&gp.stackLock, 0, 1) {
+		osyield()
+	}
+}
+
+//go:nosplit
+func gcTryLockStackBarriers(gp *g) bool {
+	mp := acquirem()
+	result := atomic.Cas(&gp.stackLock, 0, 1)
+	if !result {
+		releasem(mp)
+	}
+	return result
+}
+
+func gcUnlockStackBarriers(gp *g) {
+	atomic.Store(&gp.stackLock, 0)
+	releasem(getg().m)
+}
diff --git a/src/runtime/netpoll.go b/src/runtime/netpoll.go
index 7c6e3fa..19adeff 100644
--- a/src/runtime/netpoll.go
+++ b/src/runtime/netpoll.go
@@ -6,7 +6,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"unsafe"
+)
 
 // Integrated network poller (platform-independent part).
 // A particular implementation (epoll/kqueue) must define the following functions:
@@ -77,11 +80,11 @@ var (
 //go:linkname net_runtime_pollServerInit net.runtime_pollServerInit
 func net_runtime_pollServerInit() {
 	netpollinit()
-	atomicstore(&netpollInited, 1)
+	atomic.Store(&netpollInited, 1)
 }
 
 func netpollinited() bool {
-	return atomicload(&netpollInited) != 0
+	return atomic.Load(&netpollInited) != 0
 }
 
 //go:linkname net_runtime_pollOpen net.runtime_pollOpen
@@ -305,7 +308,7 @@ func netpollcheckerr(pd *pollDesc, mode int32) int {
 }
 
 func netpollblockcommit(gp *g, gpp unsafe.Pointer) bool {
-	return casuintptr((*uintptr)(gpp), pdWait, uintptr(unsafe.Pointer(gp)))
+	return atomic.Casuintptr((*uintptr)(gpp), pdWait, uintptr(unsafe.Pointer(gp)))
 }
 
 // returns true if IO is ready, or false if timedout or closed
@@ -326,7 +329,7 @@ func netpollblock(pd *pollDesc, mode int32, waitio bool) bool {
 		if old != 0 {
 			throw("netpollblock: double wait")
 		}
-		if casuintptr(gpp, 0, pdWait) {
+		if atomic.Casuintptr(gpp, 0, pdWait) {
 			break
 		}
 	}
@@ -338,7 +341,7 @@ func netpollblock(pd *pollDesc, mode int32, waitio bool) bool {
 		gopark(netpollblockcommit, unsafe.Pointer(gpp), "IO wait", traceEvGoBlockNet, 5)
 	}
 	// be careful to not lose concurrent READY notification
-	old := xchguintptr(gpp, 0)
+	old := atomic.Xchguintptr(gpp, 0)
 	if old > pdWait {
 		throw("netpollblock: corrupted state")
 	}
@@ -365,7 +368,7 @@ func netpollunblock(pd *pollDesc, mode int32, ioready bool) *g {
 		if ioready {
 			new = pdReady
 		}
-		if casuintptr(gpp, old, new) {
+		if atomic.Casuintptr(gpp, old, new) {
 			if old == pdReady || old == pdWait {
 				old = 0
 			}
diff --git a/src/runtime/netpoll_epoll.go b/src/runtime/netpoll_epoll.go
index 7b4052a..e06eff8 100644
--- a/src/runtime/netpoll_epoll.go
+++ b/src/runtime/netpoll_epoll.go
@@ -19,8 +19,7 @@ func epollwait(epfd int32, ev *epollevent, nev, timeout int32) int32
 func closeonexec(fd int32)
 
 var (
-	epfd           int32 = -1 // epoll descriptor
-	netpolllasterr int32
+	epfd int32 = -1 // epoll descriptor
 )
 
 func netpollinit() {
@@ -67,9 +66,9 @@ func netpoll(block bool) *g {
 retry:
 	n := epollwait(epfd, &events[0], int32(len(events)), waitms)
 	if n < 0 {
-		if n != -_EINTR && n != netpolllasterr {
-			netpolllasterr = n
+		if n != -_EINTR {
 			println("runtime: epollwait on fd", epfd, "failed with", -n)
+			throw("epollwait failed")
 		}
 		goto retry
 	}
diff --git a/src/runtime/netpoll_kqueue.go b/src/runtime/netpoll_kqueue.go
index 01445dc..36956ba 100644
--- a/src/runtime/netpoll_kqueue.go
+++ b/src/runtime/netpoll_kqueue.go
@@ -17,8 +17,7 @@ func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timesp
 func closeonexec(fd int32)
 
 var (
-	kq             int32 = -1
-	netpolllasterr int32
+	kq int32 = -1
 )
 
 func netpollinit() {
@@ -75,9 +74,9 @@ func netpoll(block bool) *g {
 retry:
 	n := kevent(kq, nil, 0, &events[0], int32(len(events)), tp)
 	if n < 0 {
-		if n != -_EINTR && n != netpolllasterr {
-			netpolllasterr = n
+		if n != -_EINTR {
 			println("runtime: kevent on fd", kq, "failed with", -n)
+			throw("kevent failed")
 		}
 		goto retry
 	}
diff --git a/src/runtime/netpoll_solaris.go b/src/runtime/netpoll_solaris.go
index e4652d8..86e9b99 100644
--- a/src/runtime/netpoll_solaris.go
+++ b/src/runtime/netpoll_solaris.go
@@ -174,9 +174,6 @@ func netpollarm(pd *pollDesc, mode int) {
 	unlock(&pd.lock)
 }
 
-// netpolllasterr holds the last error code returned by port_getn to prevent log spamming
-var netpolllasterr int32
-
 // polls for ready network connections
 // returns list of goroutines that become runnable
 func netpoll(block bool) *g {
@@ -194,9 +191,9 @@ func netpoll(block bool) *g {
 retry:
 	var n uint32 = 1
 	if port_getn(portfd, &events[0], uint32(len(events)), &n, wait) < 0 {
-		if e := errno(); e != _EINTR && e != netpolllasterr {
-			netpolllasterr = e
+		if e := errno(); e != _EINTR {
 			print("runtime: port_getn on fd ", portfd, " failed with ", e, "\n")
+			throw("port_getn failed")
 		}
 		goto retry
 	}
diff --git a/src/runtime/noasm.go b/src/runtime/noasm.go
index 9a6dbee..351e325 100644
--- a/src/runtime/noasm.go
+++ b/src/runtime/noasm.go
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Routines that are implemented in assembly in asm_{amd64,386,arm,arm64}.s
+// Routines that are implemented in assembly in asm_{amd64,386,arm,arm64,ppc64x}.s
 
-// +build ppc64 ppc64le
+// +build mips64 mips64le
 
 package runtime
 
@@ -39,6 +39,9 @@ func bytes_Compare(s1, s2 []byte) int {
 	if len(s2) < l {
 		l = len(s2)
 	}
+	if l == 0 || &s1[0] == &s2[0] {
+		goto samebytes
+	}
 	for i := 0; i < l; i++ {
 		c1, c2 := s1[i], s2[i]
 		if c1 < c2 {
@@ -48,6 +51,7 @@ func bytes_Compare(s1, s2 []byte) int {
 			return +1
 		}
 	}
+samebytes:
 	if len(s1) < len(s2) {
 		return -1
 	}
diff --git a/src/runtime/os1_darwin.go b/src/runtime/os1_darwin.go
index c9dba15..5c00407 100644
--- a/src/runtime/os1_darwin.go
+++ b/src/runtime/os1_darwin.go
@@ -8,7 +8,9 @@ import "unsafe"
 
 //extern SigTabTT runtime·sigtab[];
 
-var sigset_all = ^uint32(0)
+type sigset uint32
+
+var sigset_all = ^sigset(0)
 
 func unimplemented(name string) {
 	println(name, "not implemented")
@@ -17,16 +19,17 @@ func unimplemented(name string) {
 
 //go:nosplit
 func semawakeup(mp *m) {
-	mach_semrelease(uint32(mp.waitsema))
+	mach_semrelease(mp.waitsema)
 }
 
 //go:nosplit
-func semacreate() uintptr {
-	var x uintptr
+func semacreate(mp *m) {
+	if mp.waitsema != 0 {
+		return
+	}
 	systemstack(func() {
-		x = uintptr(mach_semcreate())
+		mp.waitsema = mach_semcreate()
 	})
-	return x
 }
 
 // BSD interface for threading.
@@ -78,12 +81,11 @@ func goenvs() {
 // May run with m.p==nil, so write barriers are not allowed.
 //go:nowritebarrier
 func newosproc(mp *m, stk unsafe.Pointer) {
-	mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
 	if false {
-		print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, "/", int(mp.tls[0]), " ostk=", &mp, "\n")
+		print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, " ostk=", &mp, "\n")
 	}
 
-	var oset uint32
+	var oset sigset
 	sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
 	errno := bsdthread_create(stk, unsafe.Pointer(mp), funcPC(mstart))
 	sigprocmask(_SIG_SETMASK, &oset, nil)
@@ -109,7 +111,7 @@ func newosproc0(stacksize uintptr, fn unsafe.Pointer, fnarg uintptr) {
 	}
 	stk := unsafe.Pointer(uintptr(stack) + stacksize)
 
-	var oset uint32
+	var oset sigset
 	sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
 	errno := bsdthread_create(stk, fn, fnarg)
 	sigprocmask(_SIG_SETMASK, &oset, nil)
@@ -123,6 +125,15 @@ func newosproc0(stacksize uintptr, fn unsafe.Pointer, fnarg uintptr) {
 var failallocatestack = []byte("runtime: failed to allocate stack for the new OS thread\n")
 var failthreadcreate = []byte("runtime: failed to create new OS thread\n")
 
+// Called to do synchronous initialization of Go code built with
+// -buildmode=c-archive or -buildmode=c-shared.
+// None of the Go runtime is initialized.
+//go:nosplit
+//go:nowritebarrierrec
+func libpreinit() {
+	initsig(true)
+}
+
 // Called to initialize a new m (including the bootstrap m).
 // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
 func mpreinit(mp *m) {
@@ -132,17 +143,12 @@ func mpreinit(mp *m) {
 
 //go:nosplit
 func msigsave(mp *m) {
-	smask := (*uint32)(unsafe.Pointer(&mp.sigmask))
-	if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
-		throw("insufficient storage for signal mask")
-	}
-	sigprocmask(_SIG_SETMASK, nil, smask)
+	sigprocmask(_SIG_SETMASK, nil, &mp.sigmask)
 }
 
 //go:nosplit
-func msigrestore(mp *m) {
-	smask := (*uint32)(unsafe.Pointer(&mp.sigmask))
-	sigprocmask(_SIG_SETMASK, smask, nil)
+func msigrestore(sigmask sigset) {
+	sigprocmask(_SIG_SETMASK, &sigmask, nil)
 }
 
 //go:nosplit
@@ -155,10 +161,30 @@ func sigblock() {
 func minit() {
 	// Initialize signal handling.
 	_g_ := getg()
-	signalstack(&_g_.m.gsignal.stack)
+
+	// The alternate signal stack is buggy on arm and arm64.
+	// The signal handler handles it directly.
+	// The sigaltstack assembly function does nothing.
+	if GOARCH != "arm" && GOARCH != "arm64" {
+		var st stackt
+		sigaltstack(nil, &st)
+		if st.ss_flags&_SS_DISABLE != 0 {
+			signalstack(&_g_.m.gsignal.stack)
+			_g_.m.newSigstack = true
+		} else {
+			// Use existing signal stack.
+			stsp := uintptr(unsafe.Pointer(st.ss_sp))
+			_g_.m.gsignal.stack.lo = stsp
+			_g_.m.gsignal.stack.hi = stsp + st.ss_size
+			_g_.m.gsignal.stackguard0 = stsp + _StackGuard
+			_g_.m.gsignal.stackguard1 = stsp + _StackGuard
+			_g_.m.gsignal.stackAlloc = st.ss_size
+			_g_.m.newSigstack = false
+		}
+	}
 
 	// restore signal mask from m.sigmask and unblock essential signals
-	nmask := *(*uint32)(unsafe.Pointer(&_g_.m.sigmask))
+	nmask := _g_.m.sigmask
 	for i := range sigtable {
 		if sigtable[i].flags&_SigUnblock != 0 {
 			nmask &^= 1 << (uint32(i) - 1)
@@ -170,7 +196,9 @@ func minit() {
 // Called from dropm to undo the effect of an minit.
 //go:nosplit
 func unminit() {
-	signalstack(nil)
+	if getg().m.newSigstack {
+		signalstack(nil)
+	}
 }
 
 // Mach IPC, to get at semaphores
@@ -381,7 +409,7 @@ func semasleep1(ns int64) int32 {
 	if ns >= 0 {
 		var nsecs int32
 		secs := timediv(ns, 1000000000, &nsecs)
-		r := mach_semaphore_timedwait(uint32(_g_.m.waitsema), uint32(secs), uint32(nsecs))
+		r := mach_semaphore_timedwait(_g_.m.waitsema, uint32(secs), uint32(nsecs))
 		if r == _KERN_ABORTED || r == _KERN_OPERATION_TIMED_OUT {
 			return -1
 		}
@@ -392,7 +420,7 @@ func semasleep1(ns int64) int32 {
 	}
 
 	for {
-		r := mach_semaphore_wait(uint32(_g_.m.waitsema))
+		r := mach_semaphore_wait(_g_.m.waitsema)
 		if r == 0 {
 			break
 		}
@@ -445,9 +473,10 @@ func memlimit() uintptr {
 	return 0
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsig(i int32, fn uintptr, restart bool) {
 	var sa sigactiont
-	memclr(unsafe.Pointer(&sa), unsafe.Sizeof(sa))
 	sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
 	if restart {
 		sa.sa_flags |= _SA_RESTART
@@ -458,13 +487,27 @@ func setsig(i int32, fn uintptr, restart bool) {
 	sigaction(uint32(i), &sa, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsigstack(i int32) {
-	throw("setsigstack")
+	var osa usigactiont
+	sigaction(uint32(i), nil, &osa)
+	handler := *(*uintptr)(unsafe.Pointer(&osa.__sigaction_u))
+	if handler == 0 || handler == _SIG_DFL || handler == _SIG_IGN || osa.sa_flags&_SA_ONSTACK != 0 {
+		return
+	}
+	var sa sigactiont
+	*(*uintptr)(unsafe.Pointer(&sa.__sigaction_u)) = handler
+	sa.sa_tramp = unsafe.Pointer(funcPC(sigtramp))
+	sa.sa_mask = osa.sa_mask
+	sa.sa_flags = osa.sa_flags | _SA_ONSTACK
+	sigaction(uint32(i), &sa, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func getsig(i int32) uintptr {
-	var sa sigactiont
-	memclr(unsafe.Pointer(&sa), unsafe.Sizeof(sa))
+	var sa usigactiont
 	sigaction(uint32(i), nil, &sa)
 	return *(*uintptr)(unsafe.Pointer(&sa.__sigaction_u))
 }
@@ -482,11 +525,14 @@ func signalstack(s *stack) {
 	sigaltstack(&st, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func updatesigmask(m sigmask) {
-	sigprocmask(_SIG_SETMASK, &m[0], nil)
+	s := sigset(m[0])
+	sigprocmask(_SIG_SETMASK, &s, nil)
 }
 
 func unblocksig(sig int32) {
-	mask := uint32(1) << (uint32(sig) - 1)
+	mask := sigset(1) << (uint32(sig) - 1)
 	sigprocmask(_SIG_UNBLOCK, &mask, nil)
 }
diff --git a/src/runtime/os1_dragonfly.go b/src/runtime/os1_dragonfly.go
index da70014..bf3e1cc 100644
--- a/src/runtime/os1_dragonfly.go
+++ b/src/runtime/os1_dragonfly.go
@@ -74,7 +74,7 @@ func lwp_start(uintptr)
 //go:nowritebarrier
 func newosproc(mp *m, stk unsafe.Pointer) {
 	if false {
-		print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " lwp_start=", funcPC(lwp_start), " id=", mp.id, "/", mp.tls[0], " ostk=", &mp, "\n")
+		print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " lwp_start=", funcPC(lwp_start), " id=", mp.id, " ostk=", &mp, "\n")
 	}
 
 	var oset sigset
@@ -88,8 +88,6 @@ func newosproc(mp *m, stk unsafe.Pointer) {
 		tid2:       nil,
 	}
 
-	mp.tls[0] = uintptr(mp.id) // XXX so 386 asm can find it
-
 	lwp_create(&params)
 	sigprocmask(_SIG_SETMASK, &oset, nil)
 }
@@ -121,17 +119,12 @@ func mpreinit(mp *m) {
 
 //go:nosplit
 func msigsave(mp *m) {
-	smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
-	if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
-		throw("insufficient storage for signal mask")
-	}
-	sigprocmask(_SIG_SETMASK, nil, smask)
+	sigprocmask(_SIG_SETMASK, nil, &mp.sigmask)
 }
 
 //go:nosplit
-func msigrestore(mp *m) {
-	smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
-	sigprocmask(_SIG_SETMASK, smask, nil)
+func msigrestore(sigmask sigset) {
+	sigprocmask(_SIG_SETMASK, &sigmask, nil)
 }
 
 //go:nosplit
@@ -147,11 +140,20 @@ func minit() {
 	// m.procid is a uint64, but lwp_start writes an int32. Fix it up.
 	_g_.m.procid = uint64(*(*int32)(unsafe.Pointer(&_g_.m.procid)))
 
-	// Initialize signal handling
+	// Initialize signal handling.
+
+	// On DragonFly a thread created by pthread_create inherits
+	// the signal stack of the creating thread.  We always create
+	// a new signal stack here, to avoid having two Go threads
+	// using the same signal stack.  This breaks the case of a
+	// thread created in C that calls sigaltstack and then calls a
+	// Go function, because we will lose track of the C code's
+	// sigaltstack, but it's the best we can do.
 	signalstack(&_g_.m.gsignal.stack)
+	_g_.m.newSigstack = true
 
 	// restore signal mask from m.sigmask and unblock essential signals
-	nmask := *(*sigset)(unsafe.Pointer(&_g_.m.sigmask))
+	nmask := _g_.m.sigmask
 	for i := range sigtable {
 		if sigtable[i].flags&_SigUnblock != 0 {
 			nmask.__bits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
@@ -161,8 +163,11 @@ func minit() {
 }
 
 // Called from dropm to undo the effect of an minit.
+//go:nosplit
 func unminit() {
-	signalstack(nil)
+	if getg().m.newSigstack {
+		signalstack(nil)
+	}
 }
 
 func memlimit() uintptr {
@@ -204,6 +209,8 @@ type sigactiont struct {
 	sa_mask      sigset
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsig(i int32, fn uintptr, restart bool) {
 	var sa sigactiont
 	sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
@@ -218,10 +225,14 @@ func setsig(i int32, fn uintptr, restart bool) {
 	sigaction(i, &sa, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsigstack(i int32) {
 	throw("setsigstack")
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func getsig(i int32) uintptr {
 	var sa sigactiont
 	sigaction(i, nil, &sa)
@@ -244,6 +255,8 @@ func signalstack(s *stack) {
 	sigaltstack(&st, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func updatesigmask(m sigmask) {
 	var mask sigset
 	copy(mask.__bits[:], m[:])
diff --git a/src/runtime/os1_freebsd.go b/src/runtime/os1_freebsd.go
index b18e60f..79d9954 100644
--- a/src/runtime/os1_freebsd.go
+++ b/src/runtime/os1_freebsd.go
@@ -4,7 +4,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 // From FreeBSD's <sys/sysctl.h>
 const (
@@ -70,7 +73,7 @@ func thr_start()
 //go:nowritebarrier
 func newosproc(mp *m, stk unsafe.Pointer) {
 	if false {
-		print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " thr_start=", funcPC(thr_start), " id=", mp.id, "/", mp.tls[0], " ostk=", &mp, "\n")
+		print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " thr_start=", funcPC(thr_start), " id=", mp.id, " ostk=", &mp, "\n")
 	}
 
 	// NOTE(rsc): This code is confused. stackbase is the top of the stack
@@ -85,7 +88,6 @@ func newosproc(mp *m, stk unsafe.Pointer) {
 		tls_base:   unsafe.Pointer(&mp.tls[0]),
 		tls_size:   unsafe.Sizeof(mp.tls),
 	}
-	mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
 
 	var oset sigset
 	sigprocmask(_SIG_SETMASK, &sigset_all, &oset)
@@ -120,17 +122,12 @@ func mpreinit(mp *m) {
 
 //go:nosplit
 func msigsave(mp *m) {
-	smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
-	if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
-		throw("insufficient storage for signal mask")
-	}
-	sigprocmask(_SIG_SETMASK, nil, smask)
+	sigprocmask(_SIG_SETMASK, nil, &mp.sigmask)
 }
 
 //go:nosplit
-func msigrestore(mp *m) {
-	smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
-	sigprocmask(_SIG_SETMASK, smask, nil)
+func msigrestore(sigmask sigset) {
+	sigprocmask(_SIG_SETMASK, &sigmask, nil)
 }
 
 //go:nosplit
@@ -145,15 +142,29 @@ func minit() {
 
 	// m.procid is a uint64, but thr_new writes a uint32 on 32-bit systems.
 	// Fix it up. (Only matters on big-endian, but be clean anyway.)
-	if ptrSize == 4 {
+	if sys.PtrSize == 4 {
 		_g_.m.procid = uint64(*(*uint32)(unsafe.Pointer(&_g_.m.procid)))
 	}
 
 	// Initialize signal handling.
-	signalstack(&_g_.m.gsignal.stack)
+	var st stackt
+	sigaltstack(nil, &st)
+	if st.ss_flags&_SS_DISABLE != 0 {
+		signalstack(&_g_.m.gsignal.stack)
+		_g_.m.newSigstack = true
+	} else {
+		// Use existing signal stack.
+		stsp := uintptr(unsafe.Pointer(st.ss_sp))
+		_g_.m.gsignal.stack.lo = stsp
+		_g_.m.gsignal.stack.hi = stsp + st.ss_size
+		_g_.m.gsignal.stackguard0 = stsp + _StackGuard
+		_g_.m.gsignal.stackguard1 = stsp + _StackGuard
+		_g_.m.gsignal.stackAlloc = st.ss_size
+		_g_.m.newSigstack = false
+	}
 
 	// restore signal mask from m.sigmask and unblock essential signals
-	nmask := *(*sigset)(unsafe.Pointer(&_g_.m.sigmask))
+	nmask := _g_.m.sigmask
 	for i := range sigtable {
 		if sigtable[i].flags&_SigUnblock != 0 {
 			nmask.__bits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
@@ -165,7 +176,9 @@ func minit() {
 // Called from dropm to undo the effect of an minit.
 //go:nosplit
 func unminit() {
-	signalstack(nil)
+	if getg().m.newSigstack {
+		signalstack(nil)
+	}
 }
 
 func memlimit() uintptr {
@@ -207,6 +220,8 @@ type sigactiont struct {
 	sa_mask    sigset
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsig(i int32, fn uintptr, restart bool) {
 	var sa sigactiont
 	sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
@@ -221,10 +236,14 @@ func setsig(i int32, fn uintptr, restart bool) {
 	sigaction(i, &sa, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsigstack(i int32) {
 	throw("setsigstack")
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func getsig(i int32) uintptr {
 	var sa sigactiont
 	sigaction(i, nil, &sa)
@@ -247,6 +266,8 @@ func signalstack(s *stack) {
 	sigaltstack(&st, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func updatesigmask(m [(_NSIG + 31) / 32]uint32) {
 	var mask sigset
 	copy(mask.__bits[:], m[:])
diff --git a/src/runtime/os1_linux.go b/src/runtime/os1_linux.go
index 166014b..b38cfc1 100644
--- a/src/runtime/os1_linux.go
+++ b/src/runtime/os1_linux.go
@@ -4,9 +4,10 @@
 
 package runtime
 
-import "unsafe"
-
-var sigset_all sigset = sigset{^uint32(0), ^uint32(0)}
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 // Linux futex.
 //
@@ -46,7 +47,7 @@ func futexsleep(addr *uint32, val uint32, ns int64) {
 	// But on real 64-bit systems, where words are larger but the stack limit
 	// is not, even timediv is too heavy, and we really need to use just an
 	// ordinary machine instruction.
-	if ptrSize == 8 {
+	if sys.PtrSize == 8 {
 		ts.set_sec(ns / 1000000000)
 		ts.set_nsec(int32(ns % 1000000000))
 	} else {
@@ -76,18 +77,17 @@ func futexwakeup(addr *uint32, cnt uint32) {
 
 func getproccount() int32 {
 	// This buffer is huge (8 kB) but we are on the system stack
-	// and there should be plenty of space (64 kB) -- except on ARM where
-	// the system stack itself is only 8kb (see golang.org/issue/11873).
+	// and there should be plenty of space (64 kB).
 	// Also this is a leaf, so we're not holding up the memory for long.
 	// See golang.org/issue/11823.
 	// The suggested behavior here is to keep trying with ever-larger
 	// buffers, but we don't have a dynamic memory allocator at the
 	// moment, so that's a bit tricky and seems like overkill.
-	const maxCPUs = 64*1024*(1-goarch_arm) + 1024*goarch_arm
-	var buf [maxCPUs / (ptrSize * 8)]uintptr
+	const maxCPUs = 64 * 1024
+	var buf [maxCPUs / (sys.PtrSize * 8)]uintptr
 	r := sched_getaffinity(0, unsafe.Sizeof(buf), &buf[0])
 	n := int32(0)
-	for _, v := range buf[:r/ptrSize] {
+	for _, v := range buf[:r/sys.PtrSize] {
 		for v != 0 {
 			n += int32(v & 1)
 			v >>= 1
@@ -133,9 +133,8 @@ func newosproc(mp *m, stk unsafe.Pointer) {
 	/*
 	 * note: strace gets confused if we use CLONE_PTRACE here.
 	 */
-	mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
 	if false {
-		print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " clone=", funcPC(clone), " id=", mp.id, "/", mp.tls[0], " ostk=", &mp, "\n")
+		print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " clone=", funcPC(clone), " id=", mp.id, " ostk=", &mp, "\n")
 	}
 
 	// Disable signals during clone, so that the new thread starts
@@ -191,6 +190,15 @@ func goenvs() {
 	goenvs_unix()
 }
 
+// Called to do synchronous initialization of Go code built with
+// -buildmode=c-archive or -buildmode=c-shared.
+// None of the Go runtime is initialized.
+//go:nosplit
+//go:nowritebarrierrec
+func libpreinit() {
+	initsig(true)
+}
+
 // Called to initialize a new m (including the bootstrap m).
 // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
 func mpreinit(mp *m) {
@@ -200,17 +208,13 @@ func mpreinit(mp *m) {
 
 //go:nosplit
 func msigsave(mp *m) {
-	smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
-	if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
-		throw("insufficient storage for signal mask")
-	}
+	smask := &mp.sigmask
 	rtsigprocmask(_SIG_SETMASK, nil, smask, int32(unsafe.Sizeof(*smask)))
 }
 
 //go:nosplit
-func msigrestore(mp *m) {
-	smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
-	rtsigprocmask(_SIG_SETMASK, smask, nil, int32(unsafe.Sizeof(*smask)))
+func msigrestore(sigmask sigset) {
+	rtsigprocmask(_SIG_SETMASK, &sigmask, nil, int32(unsafe.Sizeof(sigmask)))
 }
 
 //go:nosplit
@@ -225,16 +229,31 @@ func gettid() uint32
 func minit() {
 	// Initialize signal handling.
 	_g_ := getg()
-	signalstack(&_g_.m.gsignal.stack)
+
+	var st sigaltstackt
+	sigaltstack(nil, &st)
+	if st.ss_flags&_SS_DISABLE != 0 {
+		signalstack(&_g_.m.gsignal.stack)
+		_g_.m.newSigstack = true
+	} else {
+		// Use existing signal stack.
+		stsp := uintptr(unsafe.Pointer(st.ss_sp))
+		_g_.m.gsignal.stack.lo = stsp
+		_g_.m.gsignal.stack.hi = stsp + st.ss_size
+		_g_.m.gsignal.stackguard0 = stsp + _StackGuard
+		_g_.m.gsignal.stackguard1 = stsp + _StackGuard
+		_g_.m.gsignal.stackAlloc = st.ss_size
+		_g_.m.newSigstack = false
+	}
 
 	// for debuggers, in case cgo created the thread
 	_g_.m.procid = uint64(gettid())
 
 	// restore signal mask from m.sigmask and unblock essential signals
-	nmask := *(*sigset)(unsafe.Pointer(&_g_.m.sigmask))
+	nmask := _g_.m.sigmask
 	for i := range sigtable {
 		if sigtable[i].flags&_SigUnblock != 0 {
-			nmask[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
+			sigdelset(&nmask, i)
 		}
 	}
 	rtsigprocmask(_SIG_SETMASK, &nmask, nil, int32(unsafe.Sizeof(nmask)))
@@ -243,7 +262,9 @@ func minit() {
 // Called from dropm to undo the effect of an minit.
 //go:nosplit
 func unminit() {
-	signalstack(nil)
+	if getg().m.newSigstack {
+		signalstack(nil)
+	}
 }
 
 func memlimit() uintptr {
@@ -285,6 +306,8 @@ func memlimit() uintptr {
 func sigreturn()
 func sigtramp()
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsig(i int32, fn uintptr, restart bool) {
 	var sa sigactiont
 	memclr(unsafe.Pointer(&sa), unsafe.Sizeof(sa))
@@ -292,7 +315,7 @@ func setsig(i int32, fn uintptr, restart bool) {
 	if restart {
 		sa.sa_flags |= _SA_RESTART
 	}
-	sa.sa_mask = ^uint64(0)
+	sigfillset(&sa.sa_mask)
 	// Although Linux manpage says "sa_restorer element is obsolete and
 	// should not be used". x86_64 kernel requires it. Only use it on
 	// x86.
@@ -303,12 +326,11 @@ func setsig(i int32, fn uintptr, restart bool) {
 		fn = funcPC(sigtramp)
 	}
 	sa.sa_handler = fn
-	// Qemu rejects rt_sigaction of SIGRTMAX (64).
-	if rt_sigaction(uintptr(i), &sa, nil, unsafe.Sizeof(sa.sa_mask)) != 0 && i != 64 {
-		throw("rt_sigaction failure")
-	}
+	rt_sigaction(uintptr(i), &sa, nil, unsafe.Sizeof(sa.sa_mask))
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsigstack(i int32) {
 	var sa sigactiont
 	if rt_sigaction(uintptr(i), nil, &sa, unsafe.Sizeof(sa.sa_mask)) != 0 {
@@ -323,6 +345,8 @@ func setsigstack(i int32) {
 	}
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func getsig(i int32) uintptr {
 	var sa sigactiont
 
@@ -349,14 +373,16 @@ func signalstack(s *stack) {
 	sigaltstack(&st, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func updatesigmask(m sigmask) {
 	var mask sigset
-	copy(mask[:], m[:])
+	sigcopyset(&mask, m)
 	rtsigprocmask(_SIG_SETMASK, &mask, nil, int32(unsafe.Sizeof(mask)))
 }
 
 func unblocksig(sig int32) {
 	var mask sigset
-	mask[(sig-1)/32] |= 1 << ((uint32(sig) - 1) & 31)
+	sigaddset(&mask, int(sig))
 	rtsigprocmask(_SIG_UNBLOCK, &mask, nil, int32(unsafe.Sizeof(mask)))
 }
diff --git a/src/runtime/os1_linux_generic.go b/src/runtime/os1_linux_generic.go
new file mode 100644
index 0000000..2c8b743
--- /dev/null
+++ b/src/runtime/os1_linux_generic.go
@@ -0,0 +1,27 @@
+// Copyright 2009 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.
+
+// +build !mips64
+// +build !mips64le
+// +build linux
+
+package runtime
+
+var sigset_all = sigset{^uint32(0), ^uint32(0)}
+
+func sigaddset(mask *sigset, i int) {
+	(*mask)[(i-1)/32] |= 1 << ((uint32(i) - 1) & 31)
+}
+
+func sigdelset(mask *sigset, i int) {
+	(*mask)[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
+}
+
+func sigfillset(mask *uint64) {
+	*mask = ^uint64(0)
+}
+
+func sigcopyset(mask *sigset, m sigmask) {
+	copy((*mask)[:], m[:])
+}
diff --git a/src/runtime/os1_linux_mips64x.go b/src/runtime/os1_linux_mips64x.go
new file mode 100644
index 0000000..701e979
--- /dev/null
+++ b/src/runtime/os1_linux_mips64x.go
@@ -0,0 +1,26 @@
+// Copyright 2015 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.
+
+// +build mips64 mips64le
+// +build linux
+
+package runtime
+
+var sigset_all = sigset{^uint64(0), ^uint64(0)}
+
+func sigaddset(mask *sigset, i int) {
+	(*mask)[(i-1)/64] |= 1 << ((uint32(i) - 1) & 63)
+}
+
+func sigdelset(mask *sigset, i int) {
+	(*mask)[(i-1)/64] &^= 1 << ((uint32(i) - 1) & 63)
+}
+
+func sigfillset(mask *[2]uint64) {
+	(*mask)[0], (*mask)[1] = ^uint64(0), ^uint64(0)
+}
+
+func sigcopyset(mask *sigset, m sigmask) {
+	(*mask)[0] = uint64(m[0]) | uint64(m[1])<<32
+}
diff --git a/src/runtime/os1_nacl.go b/src/runtime/os1_nacl.go
index 30c3529..dab205d 100644
--- a/src/runtime/os1_nacl.go
+++ b/src/runtime/os1_nacl.go
@@ -6,6 +6,8 @@ package runtime
 
 import "unsafe"
 
+type sigset struct{}
+
 // Called to initialize a new m (including the bootstrap m).
 // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
 func mpreinit(mp *m) {
@@ -20,7 +22,7 @@ func msigsave(mp *m) {
 }
 
 //go:nosplit
-func msigrestore(mp *m) {
+func msigrestore(sigmask sigset) {
 }
 
 //go:nosplit
@@ -65,7 +67,7 @@ func goenvs() {
 	goenvs_unix()
 }
 
-func initsig() {
+func initsig(preinit bool) {
 }
 
 //go:nosplit
@@ -92,8 +94,10 @@ func newosproc(mp *m, stk unsafe.Pointer) {
 }
 
 //go:nosplit
-func semacreate() uintptr {
-	var cond uintptr
+func semacreate(mp *m) {
+	if mp.waitsema != 0 {
+		return
+	}
 	systemstack(func() {
 		mu := nacl_mutex_create(0)
 		if mu < 0 {
@@ -102,14 +106,12 @@ func semacreate() uintptr {
 		}
 		c := nacl_cond_create(0)
 		if c < 0 {
-			print("nacl_cond_create: error ", -cond, "\n")
+			print("nacl_cond_create: error ", -c, "\n")
 			throw("semacreate")
 		}
-		cond = uintptr(c)
-		_g_ := getg()
-		_g_.m.waitsemalock = uint32(mu)
+		mp.waitsema = c
+		mp.waitsemalock = mu
 	})
-	return cond
 }
 
 //go:nosplit
@@ -118,13 +120,13 @@ func semasleep(ns int64) int32 {
 
 	systemstack(func() {
 		_g_ := getg()
-		if nacl_mutex_lock(int32(_g_.m.waitsemalock)) < 0 {
+		if nacl_mutex_lock(_g_.m.waitsemalock) < 0 {
 			throw("semasleep")
 		}
 
 		for _g_.m.waitsemacount == 0 {
 			if ns < 0 {
-				if nacl_cond_wait(int32(_g_.m.waitsema), int32(_g_.m.waitsemalock)) < 0 {
+				if nacl_cond_wait(_g_.m.waitsema, _g_.m.waitsemalock) < 0 {
 					throw("semasleep")
 				}
 			} else {
@@ -132,9 +134,9 @@ func semasleep(ns int64) int32 {
 				end := ns + nanotime()
 				ts.tv_sec = end / 1e9
 				ts.tv_nsec = int32(end % 1e9)
-				r := nacl_cond_timed_wait_abs(int32(_g_.m.waitsema), int32(_g_.m.waitsemalock), &ts)
+				r := nacl_cond_timed_wait_abs(_g_.m.waitsema, _g_.m.waitsemalock, &ts)
 				if r == -_ETIMEDOUT {
-					nacl_mutex_unlock(int32(_g_.m.waitsemalock))
+					nacl_mutex_unlock(_g_.m.waitsemalock)
 					ret = -1
 					return
 				}
@@ -145,7 +147,7 @@ func semasleep(ns int64) int32 {
 		}
 
 		_g_.m.waitsemacount = 0
-		nacl_mutex_unlock(int32(_g_.m.waitsemalock))
+		nacl_mutex_unlock(_g_.m.waitsemalock)
 		ret = 0
 	})
 	return ret
@@ -154,15 +156,15 @@ func semasleep(ns int64) int32 {
 //go:nosplit
 func semawakeup(mp *m) {
 	systemstack(func() {
-		if nacl_mutex_lock(int32(mp.waitsemalock)) < 0 {
+		if nacl_mutex_lock(mp.waitsemalock) < 0 {
 			throw("semawakeup")
 		}
 		if mp.waitsemacount != 0 {
 			throw("semawakeup")
 		}
 		mp.waitsemacount = 1
-		nacl_cond_signal(int32(mp.waitsema))
-		nacl_mutex_unlock(int32(mp.waitsemalock))
+		nacl_cond_signal(mp.waitsema)
+		nacl_mutex_unlock(mp.waitsemalock)
 	})
 }
 
diff --git a/src/runtime/os1_netbsd.go b/src/runtime/os1_netbsd.go
index f4c5ca4..eab8eb8 100644
--- a/src/runtime/os1_netbsd.go
+++ b/src/runtime/os1_netbsd.go
@@ -4,7 +4,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"unsafe"
+)
 
 const (
 	_ESRCH     = 3
@@ -37,8 +40,7 @@ func getncpu() int32 {
 }
 
 //go:nosplit
-func semacreate() uintptr {
-	return 1
+func semacreate(mp *m) {
 }
 
 //go:nosplit
@@ -57,9 +59,9 @@ func semasleep(ns int64) int32 {
 	}
 
 	for {
-		v := atomicload(&_g_.m.waitsemacount)
+		v := atomic.Load(&_g_.m.waitsemacount)
 		if v > 0 {
-			if cas(&_g_.m.waitsemacount, v, v-1) {
+			if atomic.Cas(&_g_.m.waitsemacount, v, v-1) {
 				return 0 // semaphore acquired
 			}
 			continue
@@ -75,7 +77,7 @@ func semasleep(ns int64) int32 {
 
 //go:nosplit
 func semawakeup(mp *m) {
-	xadd(&mp.waitsemacount, 1)
+	atomic.Xadd(&mp.waitsemacount, 1)
 	// From NetBSD's _lwp_unpark(2) manual:
 	// "If the target LWP is not currently waiting, it will return
 	// immediately upon the next call to _lwp_park()."
@@ -92,11 +94,9 @@ func semawakeup(mp *m) {
 //go:nowritebarrier
 func newosproc(mp *m, stk unsafe.Pointer) {
 	if false {
-		print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, "/", int32(mp.tls[0]), " ostk=", &mp, "\n")
+		print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, " ostk=", &mp, "\n")
 	}
 
-	mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
-
 	var uc ucontextt
 	getcontext(unsafe.Pointer(&uc))
 
@@ -104,7 +104,7 @@ func newosproc(mp *m, stk unsafe.Pointer) {
 	uc.uc_link = nil
 	uc.uc_sigmask = sigset_all
 
-	lwp_mcontext_init(&uc.uc_mcontext, stk, mp, mp.g0, funcPC(mstart))
+	lwp_mcontext_init(&uc.uc_mcontext, stk, mp, mp.g0, funcPC(netbsdMstart))
 
 	ret := lwp_create(unsafe.Pointer(&uc), 0, unsafe.Pointer(&mp.procid))
 	if ret < 0 {
@@ -113,6 +113,19 @@ func newosproc(mp *m, stk unsafe.Pointer) {
 	}
 }
 
+// netbsdMStart is the function call that starts executing a newly
+// created thread.  On NetBSD, a new thread inherits the signal stack
+// of the creating thread.  That confuses minit, so we remove that
+// signal stack here before calling the regular mstart.  It's a bit
+// baroque to remove a signal stack here only to add one in minit, but
+// it's a simple change that keeps NetBSD working like other OS's.
+// At this point all signals are blocked, so there is no race.
+//go:nosplit
+func netbsdMstart() {
+	signalstack(nil)
+	mstart()
+}
+
 func osinit() {
 	ncpu = getncpu()
 }
@@ -140,17 +153,12 @@ func mpreinit(mp *m) {
 
 //go:nosplit
 func msigsave(mp *m) {
-	smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
-	if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
-		throw("insufficient storage for signal mask")
-	}
-	sigprocmask(_SIG_SETMASK, nil, smask)
+	sigprocmask(_SIG_SETMASK, nil, &mp.sigmask)
 }
 
 //go:nosplit
-func msigrestore(mp *m) {
-	smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
-	sigprocmask(_SIG_SETMASK, smask, nil)
+func msigrestore(sigmask sigset) {
+	sigprocmask(_SIG_SETMASK, &sigmask, nil)
 }
 
 //go:nosplit
@@ -164,11 +172,20 @@ func minit() {
 	_g_ := getg()
 	_g_.m.procid = uint64(lwp_self())
 
-	// Initialize signal handling
+	// Initialize signal handling.
+
+	// On NetBSD a thread created by pthread_create inherits the
+	// signal stack of the creating thread.  We always create a
+	// new signal stack here, to avoid having two Go threads using
+	// the same signal stack.  This breaks the case of a thread
+	// created in C that calls sigaltstack and then calls a Go
+	// function, because we will lose track of the C code's
+	// sigaltstack, but it's the best we can do.
 	signalstack(&_g_.m.gsignal.stack)
+	_g_.m.newSigstack = true
 
 	// restore signal mask from m.sigmask and unblock essential signals
-	nmask := *(*sigset)(unsafe.Pointer(&_g_.m.sigmask))
+	nmask := _g_.m.sigmask
 	for i := range sigtable {
 		if sigtable[i].flags&_SigUnblock != 0 {
 			nmask.__bits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
@@ -180,7 +197,9 @@ func minit() {
 // Called from dropm to undo the effect of an minit.
 //go:nosplit
 func unminit() {
-	signalstack(nil)
+	if getg().m.newSigstack {
+		signalstack(nil)
+	}
 }
 
 func memlimit() uintptr {
@@ -195,6 +214,8 @@ type sigactiont struct {
 	sa_flags     int32
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsig(i int32, fn uintptr, restart bool) {
 	var sa sigactiont
 	sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
@@ -209,10 +230,14 @@ func setsig(i int32, fn uintptr, restart bool) {
 	sigaction(i, &sa, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsigstack(i int32) {
 	throw("setsigstack")
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func getsig(i int32) uintptr {
 	var sa sigactiont
 	sigaction(i, nil, &sa)
@@ -235,6 +260,8 @@ func signalstack(s *stack) {
 	sigaltstack(&st, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func updatesigmask(m sigmask) {
 	var mask sigset
 	copy(mask.__bits[:], m[:])
diff --git a/src/runtime/os1_openbsd.go b/src/runtime/os1_openbsd.go
index 88f6aef..a6cefa2 100644
--- a/src/runtime/os1_openbsd.go
+++ b/src/runtime/os1_openbsd.go
@@ -4,7 +4,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"unsafe"
+)
 
 const (
 	_ESRCH       = 3
@@ -19,9 +22,11 @@ const (
 	_CLOCK_MONOTONIC = 3
 )
 
+type sigset uint32
+
 const (
-	sigset_none = uint32(0)
-	sigset_all  = ^uint32(0)
+	sigset_none = sigset(0)
+	sigset_all  = ^sigset(0)
 )
 
 // From OpenBSD's <sys/sysctl.h>
@@ -44,8 +49,7 @@ func getncpu() int32 {
 }
 
 //go:nosplit
-func semacreate() uintptr {
-	return 1
+func semacreate(mp *m) {
 }
 
 //go:nosplit
@@ -64,9 +68,9 @@ func semasleep(ns int64) int32 {
 	}
 
 	for {
-		v := atomicload(&_g_.m.waitsemacount)
+		v := atomic.Load(&_g_.m.waitsemacount)
 		if v > 0 {
-			if cas(&_g_.m.waitsemacount, v, v-1) {
+			if atomic.Cas(&_g_.m.waitsemacount, v, v-1) {
 				return 0 // semaphore acquired
 			}
 			continue
@@ -88,7 +92,7 @@ func semasleep(ns int64) int32 {
 
 //go:nosplit
 func semawakeup(mp *m) {
-	xadd(&mp.waitsemacount, 1)
+	atomic.Xadd(&mp.waitsemacount, 1)
 	ret := thrwakeup(uintptr(unsafe.Pointer(&mp.waitsemacount)), 1)
 	if ret != 0 && ret != _ESRCH {
 		// semawakeup can be called on signal stack.
@@ -102,11 +106,9 @@ func semawakeup(mp *m) {
 //go:nowritebarrier
 func newosproc(mp *m, stk unsafe.Pointer) {
 	if false {
-		print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, "/", int32(mp.tls[0]), " ostk=", &mp, "\n")
+		print("newosproc stk=", stk, " m=", mp, " g=", mp.g0, " id=", mp.id, " ostk=", &mp, "\n")
 	}
 
-	mp.tls[0] = uintptr(mp.id) // so 386 asm can find it
-
 	param := tforkt{
 		tf_tcb:   unsafe.Pointer(&mp.tls[0]),
 		tf_tid:   (*int32)(unsafe.Pointer(&mp.procid)),
@@ -150,17 +152,12 @@ func mpreinit(mp *m) {
 
 //go:nosplit
 func msigsave(mp *m) {
-	smask := (*uint32)(unsafe.Pointer(&mp.sigmask))
-	if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
-		throw("insufficient storage for signal mask")
-	}
-	*smask = sigprocmask(_SIG_BLOCK, 0)
+	mp.sigmask = sigprocmask(_SIG_BLOCK, 0)
 }
 
 //go:nosplit
-func msigrestore(mp *m) {
-	smask := *(*uint32)(unsafe.Pointer(&mp.sigmask))
-	sigprocmask(_SIG_SETMASK, smask)
+func msigrestore(sigmask sigset) {
+	sigprocmask(_SIG_SETMASK, sigmask)
 }
 
 //go:nosplit
@@ -177,10 +174,24 @@ func minit() {
 	_g_.m.procid = uint64(*(*int32)(unsafe.Pointer(&_g_.m.procid)))
 
 	// Initialize signal handling
-	signalstack(&_g_.m.gsignal.stack)
+	var st stackt
+	sigaltstack(nil, &st)
+	if st.ss_flags&_SS_DISABLE != 0 {
+		signalstack(&_g_.m.gsignal.stack)
+		_g_.m.newSigstack = true
+	} else {
+		// Use existing signal stack.
+		stsp := uintptr(unsafe.Pointer(st.ss_sp))
+		_g_.m.gsignal.stack.lo = stsp
+		_g_.m.gsignal.stack.hi = stsp + st.ss_size
+		_g_.m.gsignal.stackguard0 = stsp + _StackGuard
+		_g_.m.gsignal.stackguard1 = stsp + _StackGuard
+		_g_.m.gsignal.stackAlloc = st.ss_size
+		_g_.m.newSigstack = false
+	}
 
 	// restore signal mask from m.sigmask and unblock essential signals
-	nmask := *(*uint32)(unsafe.Pointer(&_g_.m.sigmask))
+	nmask := _g_.m.sigmask
 	for i := range sigtable {
 		if sigtable[i].flags&_SigUnblock != 0 {
 			nmask &^= 1 << (uint32(i) - 1)
@@ -192,7 +203,9 @@ func minit() {
 // Called from dropm to undo the effect of an minit.
 //go:nosplit
 func unminit() {
-	signalstack(nil)
+	if getg().m.newSigstack {
+		signalstack(nil)
+	}
 }
 
 func memlimit() uintptr {
@@ -207,13 +220,15 @@ type sigactiont struct {
 	sa_flags     int32
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsig(i int32, fn uintptr, restart bool) {
 	var sa sigactiont
 	sa.sa_flags = _SA_SIGINFO | _SA_ONSTACK
 	if restart {
 		sa.sa_flags |= _SA_RESTART
 	}
-	sa.sa_mask = sigset_all
+	sa.sa_mask = uint32(sigset_all)
 	if fn == funcPC(sighandler) {
 		fn = funcPC(sigtramp)
 	}
@@ -221,10 +236,14 @@ func setsig(i int32, fn uintptr, restart bool) {
 	sigaction(i, &sa, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsigstack(i int32) {
 	throw("setsigstack")
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func getsig(i int32) uintptr {
 	var sa sigactiont
 	sigaction(i, nil, &sa)
@@ -247,11 +266,13 @@ func signalstack(s *stack) {
 	sigaltstack(&st, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func updatesigmask(m sigmask) {
-	sigprocmask(_SIG_SETMASK, m[0])
+	sigprocmask(_SIG_SETMASK, sigset(m[0]))
 }
 
 func unblocksig(sig int32) {
-	mask := uint32(1) << (uint32(sig) - 1)
+	mask := sigset(1) << (uint32(sig) - 1)
 	sigprocmask(_SIG_UNBLOCK, mask)
 }
diff --git a/src/runtime/os1_plan9.go b/src/runtime/os1_plan9.go
index 38125a0..7506d59 100644
--- a/src/runtime/os1_plan9.go
+++ b/src/runtime/os1_plan9.go
@@ -4,7 +4,12 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"unsafe"
+)
+
+type sigset struct{}
 
 // Called to initialize a new m (including the bootstrap m).
 // Called on the parent thread (main thread in case of bootstrap), can allocate memory.
@@ -21,7 +26,7 @@ func mpreinit(mp *m) {
 func msigsave(mp *m) {
 }
 
-func msigrestore(mp *m) {
+func msigrestore(sigmask sigset) {
 }
 
 func sigblock() {
@@ -102,7 +107,7 @@ func getRandomData(r []byte) {
 func goenvs() {
 }
 
-func initsig() {
+func initsig(preinit bool) {
 }
 
 //go:nosplit
@@ -149,7 +154,7 @@ func goexitsall(status *byte) {
 	n := copy(buf[:], goexits)
 	n = copy(buf[n:], gostringnocopy(status))
 	pid := getpid()
-	for mp := (*m)(atomicloadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
+	for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
 		if mp.procid != pid {
 			postnote(mp.procid, buf[:])
 		}
@@ -170,7 +175,7 @@ func postnote(pid uint64, msg []byte) int {
 		return -1
 	}
 	len := findnull(&msg[0])
-	if write(uintptr(fd), (unsafe.Pointer)(&msg[0]), int32(len)) != int64(len) {
+	if write(uintptr(fd), unsafe.Pointer(&msg[0]), int32(len)) != int64(len) {
 		closefd(fd)
 		return -1
 	}
@@ -208,8 +213,7 @@ func newosproc(mp *m, stk unsafe.Pointer) {
 }
 
 //go:nosplit
-func semacreate() uintptr {
-	return 1
+func semacreate(mp *m) {
 }
 
 //go:nosplit
diff --git a/src/runtime/os1_windows.go b/src/runtime/os1_windows.go
index d012034..a28e11e 100644
--- a/src/runtime/os1_windows.go
+++ b/src/runtime/os1_windows.go
@@ -5,6 +5,7 @@
 package runtime
 
 import (
+	"runtime/internal/atomic"
 	"unsafe"
 )
 
@@ -20,8 +21,10 @@ import (
 //go:cgo_import_dynamic runtime._DuplicateHandle DuplicateHandle%7 "kernel32.dll"
 //go:cgo_import_dynamic runtime._ExitProcess ExitProcess%1 "kernel32.dll"
 //go:cgo_import_dynamic runtime._FreeEnvironmentStringsW FreeEnvironmentStringsW%1 "kernel32.dll"
+//go:cgo_import_dynamic runtime._GetConsoleMode GetConsoleMode%2 "kernel32.dll"
 //go:cgo_import_dynamic runtime._GetEnvironmentStringsW GetEnvironmentStringsW%0 "kernel32.dll"
 //go:cgo_import_dynamic runtime._GetProcAddress GetProcAddress%2 "kernel32.dll"
+//go:cgo_import_dynamic runtime._GetProcessAffinityMask GetProcessAffinityMask%3 "kernel32.dll"
 //go:cgo_import_dynamic runtime._GetQueuedCompletionStatus GetQueuedCompletionStatus%5 "kernel32.dll"
 //go:cgo_import_dynamic runtime._GetStdHandle GetStdHandle%1 "kernel32.dll"
 //go:cgo_import_dynamic runtime._GetSystemInfo GetSystemInfo%1 "kernel32.dll"
@@ -42,8 +45,8 @@ import (
 //go:cgo_import_dynamic runtime._VirtualFree VirtualFree%3 "kernel32.dll"
 //go:cgo_import_dynamic runtime._WSAGetOverlappedResult WSAGetOverlappedResult%5 "ws2_32.dll"
 //go:cgo_import_dynamic runtime._WaitForSingleObject WaitForSingleObject%2 "kernel32.dll"
+//go:cgo_import_dynamic runtime._WriteConsoleW WriteConsoleW%5 "kernel32.dll"
 //go:cgo_import_dynamic runtime._WriteFile WriteFile%5 "kernel32.dll"
-//go:cgo_import_dynamic runtime._timeBeginPeriod timeBeginPeriod%1 "winmm.dll"
 
 var (
 	// Following syscalls are available on every Windows PC.
@@ -61,8 +64,10 @@ var (
 	_DuplicateHandle,
 	_ExitProcess,
 	_FreeEnvironmentStringsW,
+	_GetConsoleMode,
 	_GetEnvironmentStringsW,
 	_GetProcAddress,
+	_GetProcessAffinityMask,
 	_GetQueuedCompletionStatus,
 	_GetStdHandle,
 	_GetSystemInfo,
@@ -83,8 +88,8 @@ var (
 	_VirtualFree,
 	_WSAGetOverlappedResult,
 	_WaitForSingleObject,
-	_WriteFile,
-	_timeBeginPeriod stdFunction
+	_WriteConsoleW,
+	_WriteFile stdFunction
 
 	// Following syscalls are only available on some Windows PCs.
 	// We will load syscalls, if available, before using them.
@@ -92,6 +97,8 @@ var (
 	_GetQueuedCompletionStatusEx stdFunction
 )
 
+type sigset struct{}
+
 // Call a Windows function with stdcall conventions,
 // and switch to os stack during the call.
 func asmstdcall(fn unsafe.Pointer)
@@ -126,6 +133,21 @@ func getGetProcAddress() uintptr {
 }
 
 func getproccount() int32 {
+	var mask, sysmask uintptr
+	ret := stdcall3(_GetProcessAffinityMask, currentProcess, uintptr(unsafe.Pointer(&mask)), uintptr(unsafe.Pointer(&sysmask)))
+	if ret != 0 {
+		n := 0
+		maskbits := int(unsafe.Sizeof(mask) * 8)
+		for i := 0; i < maskbits; i++ {
+			if mask&(1<<uint(i)) != 0 {
+				n++
+			}
+		}
+		if n != 0 {
+			return int32(n)
+		}
+	}
+	// use GetSystemInfo if GetProcessAffinityMask fails
 	var info systeminfo
 	stdcall1(_GetSystemInfo, uintptr(unsafe.Pointer(&info)))
 	return int32(info.dwnumberofprocessors)
@@ -154,8 +176,6 @@ func osinit() {
 
 	stdcall2(_SetConsoleCtrlHandler, funcPC(ctrlhandler), 1)
 
-	stdcall1(_timeBeginPeriod, 1)
-
 	ncpu = getproccount()
 
 	// Windows dynamic priority boosting assumes that a process has different types
@@ -234,11 +254,90 @@ func write(fd uintptr, buf unsafe.Pointer, n int32) int32 {
 		// assume fd is real windows handle.
 		handle = fd
 	}
+	isASCII := true
+	b := (*[1 << 30]byte)(buf)[:n]
+	for _, x := range b {
+		if x >= 0x80 {
+			isASCII = false
+			break
+		}
+	}
+
+	if !isASCII {
+		var m uint32
+		isConsole := stdcall2(_GetConsoleMode, handle, uintptr(unsafe.Pointer(&m))) != 0
+		// If this is a console output, various non-unicode code pages can be in use.
+		// Use the dedicated WriteConsole call to ensure unicode is printed correctly.
+		if isConsole {
+			return int32(writeConsole(handle, buf, n))
+		}
+	}
 	var written uint32
 	stdcall5(_WriteFile, handle, uintptr(buf), uintptr(n), uintptr(unsafe.Pointer(&written)), 0)
 	return int32(written)
 }
 
+var (
+	utf16ConsoleBack     [1000]uint16
+	utf16ConsoleBackLock mutex
+)
+
+// writeConsole writes bufLen bytes from buf to the console File.
+// It returns the number of bytes written.
+func writeConsole(handle uintptr, buf unsafe.Pointer, bufLen int32) int {
+	const surr2 = (surrogateMin + surrogateMax + 1) / 2
+
+	// Do not use defer for unlock. May cause issues when printing a panic.
+	lock(&utf16ConsoleBackLock)
+
+	b := (*[1 << 30]byte)(buf)[:bufLen]
+	s := *(*string)(unsafe.Pointer(&b))
+
+	utf16tmp := utf16ConsoleBack[:]
+
+	total := len(s)
+	w := 0
+	for len(s) > 0 {
+		if w >= len(utf16tmp)-2 {
+			writeConsoleUTF16(handle, utf16tmp[:w])
+			w = 0
+		}
+		r, n := charntorune(s)
+		s = s[n:]
+		if r < 0x10000 {
+			utf16tmp[w] = uint16(r)
+			w++
+		} else {
+			r -= 0x10000
+			utf16tmp[w] = surrogateMin + uint16(r>>10)&0x3ff
+			utf16tmp[w+1] = surr2 + uint16(r)&0x3ff
+			w += 2
+		}
+	}
+	writeConsoleUTF16(handle, utf16tmp[:w])
+	unlock(&utf16ConsoleBackLock)
+	return total
+}
+
+// writeConsoleUTF16 is the dedicated windows calls that correctly prints
+// to the console regardless of the current code page. Input is utf-16 code points.
+// The handle must be a console handle.
+func writeConsoleUTF16(handle uintptr, b []uint16) {
+	l := uint32(len(b))
+	if l == 0 {
+		return
+	}
+	var written uint32
+	stdcall5(_WriteConsoleW,
+		handle,
+		uintptr(unsafe.Pointer(&b[0])),
+		uintptr(l),
+		uintptr(unsafe.Pointer(&written)),
+		0,
+	)
+	return
+}
+
 //go:nosplit
 func semasleep(ns int64) int32 {
 	// store ms in ns to save stack space
@@ -262,8 +361,11 @@ func semawakeup(mp *m) {
 }
 
 //go:nosplit
-func semacreate() uintptr {
-	return stdcall4(_CreateEventA, 0, 0, 0, 0)
+func semacreate(mp *m) {
+	if mp.waitsema != 0 {
+		return
+	}
+	mp.waitsema = stdcall4(_CreateEventA, 0, 0, 0, 0)
 }
 
 // May run with m.p==nil, so write barriers are not allowed.
@@ -289,7 +391,7 @@ func msigsave(mp *m) {
 }
 
 //go:nosplit
-func msigrestore(mp *m) {
+func msigrestore(sigmask sigset) {
 }
 
 //go:nosplit
@@ -301,7 +403,7 @@ func sigblock() {
 func minit() {
 	var thandle uintptr
 	stdcall7(_DuplicateHandle, currentProcess, currentThread, currentProcess, uintptr(unsafe.Pointer(&thandle)), 0, 0, _DUPLICATE_SAME_ACCESS)
-	atomicstoreuintptr(&getg().m.thread, thandle)
+	atomic.Storeuintptr(&getg().m.thread, thandle)
 }
 
 // Called from dropm to undo the effect of an minit.
@@ -484,9 +586,6 @@ func profilem(mp *m) {
 	rbuf := make([]byte, unsafe.Sizeof(*r)+15)
 
 	tls := &mp.tls[0]
-	if mp == &m0 {
-		tls = &tls0[0]
-	}
 	gp := *((**g)(unsafe.Pointer(tls)))
 
 	// align Context to 16 bytes
@@ -501,9 +600,9 @@ func profileloop1(param uintptr) uint32 {
 
 	for {
 		stdcall2(_WaitForSingleObject, profiletimer, _INFINITE)
-		first := (*m)(atomicloadp(unsafe.Pointer(&allm)))
+		first := (*m)(atomic.Loadp(unsafe.Pointer(&allm)))
 		for mp := first; mp != nil; mp = mp.alllink {
-			thread := atomicloaduintptr(&mp.thread)
+			thread := atomic.Loaduintptr(&mp.thread)
 			// Do not profile threads blocked on Notes,
 			// this includes idle worker threads,
 			// idle timer thread, idle heap scavenger, etc.
@@ -525,7 +624,7 @@ func resetcpuprofiler(hz int32) {
 	lock(&cpuprofilerlock)
 	if profiletimer == 0 {
 		timer := stdcall3(_CreateWaitableTimerA, 0, 0, 0)
-		atomicstoreuintptr(&profiletimer, timer)
+		atomic.Storeuintptr(&profiletimer, timer)
 		thread := stdcall6(_CreateThread, 0, 0, funcPC(profileloop), 0, 0, 0)
 		stdcall2(_SetThreadPriority, thread, _THREAD_PRIORITY_HIGHEST)
 		stdcall1(_CloseHandle, thread)
@@ -542,7 +641,7 @@ func resetcpuprofiler(hz int32) {
 		due = int64(ms) * -10000
 	}
 	stdcall6(_SetWaitableTimer, profiletimer, uintptr(unsafe.Pointer(&due)), uintptr(ms), 0, 0, 0)
-	atomicstore((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz))
+	atomic.Store((*uint32)(unsafe.Pointer(&getg().m.profilehz)), uint32(hz))
 }
 
 func memlimit() uintptr {
diff --git a/src/runtime/os2_dragonfly.go b/src/runtime/os2_dragonfly.go
index ccad82f..6ea2da0 100644
--- a/src/runtime/os2_dragonfly.go
+++ b/src/runtime/os2_dragonfly.go
@@ -6,7 +6,7 @@ package runtime
 
 const (
 	_NSIG        = 33
-	_SI_USER     = 0x10001
+	_SI_USER     = 0
 	_SS_DISABLE  = 4
 	_RLIMIT_AS   = 10
 	_SIG_BLOCK   = 1
diff --git a/src/runtime/os2_linux.go b/src/runtime/os2_linux.go
deleted file mode 100644
index 71f36eb..0000000
--- a/src/runtime/os2_linux.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2009 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 runtime
-
-const (
-	_SS_DISABLE  = 2
-	_NSIG        = 65
-	_SI_USER     = 0
-	_SIG_BLOCK   = 0
-	_SIG_UNBLOCK = 1
-	_SIG_SETMASK = 2
-	_RLIMIT_AS   = 9
-)
-
-// It's hard to tease out exactly how big a Sigset is, but
-// rt_sigprocmask crashes if we get it wrong, so if binaries
-// are running, this is right.
-type sigset [2]uint32
-
-type rlimit struct {
-	rlim_cur uintptr
-	rlim_max uintptr
-}
diff --git a/src/runtime/os2_linux_generic.go b/src/runtime/os2_linux_generic.go
new file mode 100644
index 0000000..01e6c8a
--- /dev/null
+++ b/src/runtime/os2_linux_generic.go
@@ -0,0 +1,29 @@
+// Copyright 2009 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.
+
+// +build !mips64
+// +build !mips64le
+// +build linux
+
+package runtime
+
+const (
+	_SS_DISABLE  = 2
+	_NSIG        = 65
+	_SI_USER     = 0
+	_SIG_BLOCK   = 0
+	_SIG_UNBLOCK = 1
+	_SIG_SETMASK = 2
+	_RLIMIT_AS   = 9
+)
+
+// It's hard to tease out exactly how big a Sigset is, but
+// rt_sigprocmask crashes if we get it wrong, so if binaries
+// are running, this is right.
+type sigset [2]uint32
+
+type rlimit struct {
+	rlim_cur uintptr
+	rlim_max uintptr
+}
diff --git a/src/runtime/os2_linux_mips64x.go b/src/runtime/os2_linux_mips64x.go
new file mode 100644
index 0000000..9a6a92a
--- /dev/null
+++ b/src/runtime/os2_linux_mips64x.go
@@ -0,0 +1,25 @@
+// Copyright 2015 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.
+
+// +build linux
+// +build mips64 mips64le
+
+package runtime
+
+const (
+	_SS_DISABLE  = 2
+	_NSIG        = 65
+	_SI_USER     = 0
+	_SIG_BLOCK   = 1
+	_SIG_UNBLOCK = 2
+	_SIG_SETMASK = 3
+	_RLIMIT_AS   = 6
+)
+
+type sigset [2]uint64
+
+type rlimit struct {
+	rlim_cur uintptr
+	rlim_max uintptr
+}
diff --git a/src/runtime/os2_nacl.go b/src/runtime/os2_nacl.go
index 0c91e0f..d8c88db 100644
--- a/src/runtime/os2_nacl.go
+++ b/src/runtime/os2_nacl.go
@@ -10,18 +10,19 @@ const (
 
 	// native_client/src/trusted/service_runtime/include/sys/errno.h
 	// The errors are mainly copied from Linux.
-	_EPERM           = 1        /* Operation not permitted */
-	_ENOENT          = 2        /* No such file or directory */
-	_ESRCH           = 3        /* No such process */
-	_EINTR           = 4        /* Interrupted system call */
-	_EIO             = 5        /* I/O error */
-	_ENXIO           = 6        /* No such device or address */
-	_E2BIG           = 7        /* Argument list too long */
-	_ENOEXEC         = 8        /* Exec format error */
-	_EBADF           = 9        /* Bad file number */
-	_ECHILD          = 10       /* No child processes */
-	_EAGAIN          = 11       /* Try again */
-	_ENOMEM          = 12       /* Out of memory */
+	_EPERM   = 1  /* Operation not permitted */
+	_ENOENT  = 2  /* No such file or directory */
+	_ESRCH   = 3  /* No such process */
+	_EINTR   = 4  /* Interrupted system call */
+	_EIO     = 5  /* I/O error */
+	_ENXIO   = 6  /* No such device or address */
+	_E2BIG   = 7  /* Argument list too long */
+	_ENOEXEC = 8  /* Exec format error */
+	_EBADF   = 9  /* Bad file number */
+	_ECHILD  = 10 /* No child processes */
+	_EAGAIN  = 11 /* Try again */
+	// _ENOMEM is defined in mem_bsd.go for nacl.
+	// _ENOMEM          = 12       /* Out of memory */
 	_EACCES          = 13       /* Permission denied */
 	_EFAULT          = 14       /* Bad address */
 	_EBUSY           = 16       /* Device or resource busy */
diff --git a/src/runtime/os3_plan9.go b/src/runtime/os3_plan9.go
index 03e9410..edd66c5 100644
--- a/src/runtime/os3_plan9.go
+++ b/src/runtime/os3_plan9.go
@@ -4,16 +4,21 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 // May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
+//
+//go:nowritebarrierrec
 func sighandler(_ureg *ureg, note *byte, gp *g) int {
 	_g_ := getg()
 	var t sigTabT
 	var docrash bool
 	var sig int
 	var flags int
+	var level int32
 
 	c := &sigctxt{_ureg}
 	notestr := gostringnocopy(note)
@@ -68,11 +73,11 @@ func sighandler(_ureg *ureg, note *byte, gp *g) int {
 		// to sigpanic instead. (Otherwise the trace will end at
 		// sigpanic and we won't get to see who faulted).
 		if pc != 0 {
-			if regSize > ptrSize {
-				sp -= ptrSize
+			if sys.RegSize > sys.PtrSize {
+				sp -= sys.PtrSize
 				*(*uintptr)(unsafe.Pointer(sp)) = 0
 			}
-			sp -= ptrSize
+			sp -= sys.PtrSize
 			*(*uintptr)(unsafe.Pointer(sp)) = pc
 			c.setsp(sp)
 		}
@@ -97,7 +102,8 @@ Throw:
 	print(notestr, "\n")
 	print("PC=", hex(c.pc()), "\n")
 	print("\n")
-	if gotraceback(&docrash) > 0 {
+	level, _, docrash = gotraceback()
+	if level > 0 {
 		goroutineheader(gp)
 		tracebacktrap(c.pc(), c.sp(), 0, gp)
 		tracebackothers(gp)
diff --git a/src/runtime/os3_solaris.go b/src/runtime/os3_solaris.go
index b27a675..7ebb35c 100644
--- a/src/runtime/os3_solaris.go
+++ b/src/runtime/os3_solaris.go
@@ -194,17 +194,12 @@ func miniterrno()
 
 //go:nosplit
 func msigsave(mp *m) {
-	smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
-	if unsafe.Sizeof(*smask) > unsafe.Sizeof(mp.sigmask) {
-		throw("insufficient storage for signal mask")
-	}
-	sigprocmask(_SIG_SETMASK, nil, smask)
+	sigprocmask(_SIG_SETMASK, nil, &mp.sigmask)
 }
 
 //go:nosplit
-func msigrestore(mp *m) {
-	smask := (*sigset)(unsafe.Pointer(&mp.sigmask))
-	sigprocmask(_SIG_SETMASK, smask, nil)
+func msigrestore(sigmask sigset) {
+	sigprocmask(_SIG_SETMASK, &sigmask, nil)
 }
 
 //go:nosplit
@@ -218,10 +213,24 @@ func minit() {
 	_g_ := getg()
 	asmcgocall(unsafe.Pointer(funcPC(miniterrno)), unsafe.Pointer(&libc____errno))
 	// Initialize signal handling
-	signalstack(&_g_.m.gsignal.stack)
+	var st sigaltstackt
+	sigaltstack(nil, &st)
+	if st.ss_flags&_SS_DISABLE != 0 {
+		signalstack(&_g_.m.gsignal.stack)
+		_g_.m.newSigstack = true
+	} else {
+		// Use existing signal stack.
+		stsp := uintptr(unsafe.Pointer(st.ss_sp))
+		_g_.m.gsignal.stack.lo = stsp
+		_g_.m.gsignal.stack.hi = stsp + uintptr(st.ss_size)
+		_g_.m.gsignal.stackguard0 = stsp + _StackGuard
+		_g_.m.gsignal.stackguard1 = stsp + _StackGuard
+		_g_.m.gsignal.stackAlloc = uintptr(st.ss_size)
+		_g_.m.newSigstack = false
+	}
 
 	// restore signal mask from m.sigmask and unblock essential signals
-	nmask := *(*sigset)(unsafe.Pointer(&_g_.m.sigmask))
+	nmask := _g_.m.sigmask
 	for i := range sigtable {
 		if sigtable[i].flags&_SigUnblock != 0 {
 			nmask.__sigbits[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
@@ -232,7 +241,9 @@ func minit() {
 
 // Called from dropm to undo the effect of an minit.
 func unminit() {
-	signalstack(nil)
+	if getg().m.newSigstack {
+		signalstack(nil)
+	}
 }
 
 func memlimit() uintptr {
@@ -268,6 +279,8 @@ func memlimit() uintptr {
 
 func sigtramp()
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsig(i int32, fn uintptr, restart bool) {
 	var sa sigactiont
 
@@ -284,10 +297,21 @@ func setsig(i int32, fn uintptr, restart bool) {
 	sigaction(i, &sa, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func setsigstack(i int32) {
-	throw("setsigstack")
+	var sa sigactiont
+	sigaction(i, nil, &sa)
+	handler := *((*uintptr)(unsafe.Pointer(&sa._funcptr)))
+	if handler == 0 || handler == _SIG_DFL || handler == _SIG_IGN || sa.sa_flags&_SA_ONSTACK != 0 {
+		return
+	}
+	sa.sa_flags |= _SA_ONSTACK
+	sigaction(i, &sa, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func getsig(i int32) uintptr {
 	var sa sigactiont
 	sigaction(i, nil, &sa)
@@ -310,6 +334,8 @@ func signalstack(s *stack) {
 	sigaltstack(&st, nil)
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func updatesigmask(m sigmask) {
 	var mask sigset
 	copy(mask.__sigbits[:], m[:])
@@ -323,7 +349,11 @@ func unblocksig(sig int32) {
 }
 
 //go:nosplit
-func semacreate() uintptr {
+func semacreate(mp *m) {
+	if mp.waitsema != 0 {
+		return
+	}
+
 	var sem *semt
 	_g_ := getg()
 
@@ -340,7 +370,7 @@ func semacreate() uintptr {
 	if sem_init(sem, 0, 0) != 0 {
 		throw("sem_init")
 	}
-	return uintptr(unsafe.Pointer(sem))
+	mp.waitsema = uintptr(unsafe.Pointer(sem))
 }
 
 //go:nosplit
@@ -412,7 +442,21 @@ func madvise(addr unsafe.Pointer, n uintptr, flags int32) {
 
 //go:nosplit
 func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer {
-	return unsafe.Pointer(sysvicall6(&libc_mmap, uintptr(addr), uintptr(n), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(off)))
+	p, err := doMmap(uintptr(addr), n, uintptr(prot), uintptr(flags), uintptr(fd), uintptr(off))
+	if p == ^uintptr(0) {
+		return unsafe.Pointer(err)
+	}
+	return unsafe.Pointer(p)
+}
+
+//go:nosplit
+func doMmap(addr, n, prot, flags, fd, off uintptr) (uintptr, uintptr) {
+	var libcall libcall
+	libcall.fn = uintptr(unsafe.Pointer(&libc_mmap))
+	libcall.n = 6
+	libcall.args = uintptr(noescape(unsafe.Pointer(&addr)))
+	asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall))
+	return libcall.r1, libcall.err
 }
 
 //go:nosplit
@@ -456,6 +500,8 @@ func pthread_create(thread *pthread, attr *pthreadattr, fn uintptr, arg unsafe.P
 	return int32(sysvicall4(&libc_pthread_create, uintptr(unsafe.Pointer(thread)), uintptr(unsafe.Pointer(attr)), uintptr(fn), uintptr(arg)))
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func raise(sig int32) /* int32 */ {
 	sysvicall1(&libc_raise, uintptr(sig))
 }
@@ -494,15 +540,20 @@ func setitimer(which int32, value *itimerval, ovalue *itimerval) /* int32 */ {
 	sysvicall3(&libc_setitimer, uintptr(which), uintptr(unsafe.Pointer(value)), uintptr(unsafe.Pointer(ovalue)))
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func sigaction(sig int32, act *sigactiont, oact *sigactiont) /* int32 */ {
 	sysvicall3(&libc_sigaction, uintptr(sig), uintptr(unsafe.Pointer(act)), uintptr(unsafe.Pointer(oact)))
 }
 
+//go:nosplit
+//go:nowritebarrierrec
 func sigaltstack(ss *sigaltstackt, oss *sigaltstackt) /* int32 */ {
 	sysvicall2(&libc_sigaltstack, uintptr(unsafe.Pointer(ss)), uintptr(unsafe.Pointer(oss)))
 }
 
 //go:nosplit
+//go:nowritebarrierrec
 func sigprocmask(how int32, set *sigset, oset *sigset) /* int32 */ {
 	sysvicall3(&libc_sigprocmask, uintptr(how), uintptr(unsafe.Pointer(set)), uintptr(unsafe.Pointer(oset)))
 }
diff --git a/src/runtime/os_android_arm.go b/src/runtime/os_android.go
similarity index 100%
rename from src/runtime/os_android_arm.go
rename to src/runtime/os_android.go
diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go
index 3deafd5..b825776 100644
--- a/src/runtime/os_darwin.go
+++ b/src/runtime/os_darwin.go
@@ -6,6 +6,10 @@ package runtime
 
 import "unsafe"
 
+type mOS struct {
+	waitsema uint32 // semaphore for parking on locks
+}
+
 func bsdthread_create(stk, arg unsafe.Pointer, fn uintptr) int32
 func bsdthread_register() int32
 
@@ -20,10 +24,10 @@ func mach_thread_self() uint32
 func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
 
 //go:noescape
-func sigprocmask(how uint32, new, old *uint32)
+func sigprocmask(how uint32, new, old *sigset)
 
 //go:noescape
-func sigaction(mode uint32, new, old *sigactiont)
+func sigaction(mode uint32, new *sigactiont, old *usigactiont)
 
 //go:noescape
 func sigaltstack(new, old *stackt)
diff --git a/src/runtime/os_dragonfly.go b/src/runtime/os_dragonfly.go
index b19270a..d6856f1 100644
--- a/src/runtime/os_dragonfly.go
+++ b/src/runtime/os_dragonfly.go
@@ -6,6 +6,8 @@ package runtime
 
 import "unsafe"
 
+type mOS struct{}
+
 //go:noescape
 func lwp_create(param *lwpparams) int32
 
@@ -13,9 +15,6 @@ func lwp_create(param *lwpparams) int32
 func sigaltstack(new, old *sigaltstackt)
 
 //go:noescape
-func sigfwd(fn uintptr, sig uint32, info *siginfo, ctx unsafe.Pointer)
-
-//go:noescape
 func sigaction(sig int32, new, old *sigactiont)
 
 //go:noescape
diff --git a/src/runtime/os_freebsd.go b/src/runtime/os_freebsd.go
index 8c8a106..61f8fae 100644
--- a/src/runtime/os_freebsd.go
+++ b/src/runtime/os_freebsd.go
@@ -6,6 +6,8 @@ package runtime
 
 import "unsafe"
 
+type mOS struct{}
+
 //go:noescape
 func thr_new(param *thrparam, size int32)
 
@@ -13,9 +15,6 @@ func thr_new(param *thrparam, size int32)
 func sigaltstack(new, old *stackt)
 
 //go:noescape
-func sigfwd(fn uintptr, sig uint32, info *siginfo, ctx unsafe.Pointer)
-
-//go:noescape
 func sigaction(sig int32, new, old *sigactiont)
 
 //go:noescape
diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go
index bd492f5..51a7fa0 100644
--- a/src/runtime/os_linux.go
+++ b/src/runtime/os_linux.go
@@ -6,6 +6,8 @@ package runtime
 
 import "unsafe"
 
+type mOS struct{}
+
 //go:noescape
 func futex(addr unsafe.Pointer, op int32, val uint32, ts, addr2 unsafe.Pointer, val3 uint32) int32
 
@@ -19,9 +21,6 @@ func rt_sigaction(sig uintptr, new, old *sigactiont, size uintptr) int32
 func sigaltstack(new, old *sigaltstackt)
 
 //go:noescape
-func sigfwd(fn uintptr, sig uint32, info *siginfo, ctx unsafe.Pointer)
-
-//go:noescape
 func setitimer(mode int32, new, old *itimerval)
 
 //go:noescape
diff --git a/src/runtime/os_linux_386.go b/src/runtime/os_linux_386.go
index e2120da..3577a24 100644
--- a/src/runtime/os_linux_386.go
+++ b/src/runtime/os_linux_386.go
@@ -4,7 +4,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 const (
 	_AT_NULL    = 0
@@ -21,7 +24,7 @@ func sysargs(argc int32, argv **byte) {
 		n++
 	}
 	n++
-	auxv := (*[1 << 28]uint32)(add(unsafe.Pointer(argv), uintptr(n)*ptrSize))
+	auxv := (*[1 << 28]uint32)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize))
 
 	for i := 0; auxv[i] != _AT_NULL; i += 2 {
 		switch auxv[i] {
diff --git a/src/runtime/os_linux_arm.go b/src/runtime/os_linux_arm.go
index 3749640..8fdfb58 100644
--- a/src/runtime/os_linux_arm.go
+++ b/src/runtime/os_linux_arm.go
@@ -4,7 +4,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 const (
 	_AT_NULL     = 0
@@ -40,7 +43,7 @@ func sysargs(argc int32, argv **byte) {
 		n++
 	}
 	n++
-	auxv := (*[1 << 28]uint32)(add(unsafe.Pointer(argv), uintptr(n)*ptrSize))
+	auxv := (*[1 << 28]uint32)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize))
 
 	for i := 0; auxv[i] != _AT_NULL; i += 2 {
 		switch auxv[i] {
diff --git a/src/runtime/os_linux_mips64x.go b/src/runtime/os_linux_mips64x.go
new file mode 100644
index 0000000..4d2e9e8
--- /dev/null
+++ b/src/runtime/os_linux_mips64x.go
@@ -0,0 +1,18 @@
+// Copyright 2015 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.
+
+// +build mips64 mips64le
+// +build linux
+
+package runtime
+
+var randomNumber uint32
+
+//go:nosplit
+func cputicks() int64 {
+	// Currently cputicks() is used in blocking profiler and to seed fastrand1().
+	// nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
+	// randomNumber provides better seeding of fastrand1.
+	return nanotime() + int64(randomNumber)
+}
diff --git a/src/runtime/os_nacl.go b/src/runtime/os_nacl.go
index 3b4c136..c7cc0a9 100644
--- a/src/runtime/os_nacl.go
+++ b/src/runtime/os_nacl.go
@@ -6,6 +6,12 @@ package runtime
 
 import "unsafe"
 
+type mOS struct {
+	waitsema      int32 // semaphore for parking on locks
+	waitsemacount int32
+	waitsemalock  int32
+}
+
 func nacl_exception_stack(p uintptr, size int32) int32
 func nacl_exception_handler(fn uintptr, arg unsafe.Pointer) int32
 func nacl_sem_create(flag int32) int32
@@ -39,6 +45,10 @@ func os_sigpipe() {
 	throw("too many writes on closed pipe")
 }
 
+func dieFromSignal(sig int32) {
+	exit(2)
+}
+
 func sigpanic() {
 	g := getg()
 	if !canpanic(g) {
@@ -50,10 +60,6 @@ func sigpanic() {
 	panicmem()
 }
 
-func sigfwd(fn uintptr, sig uint32, info *siginfo, ctx unsafe.Pointer) {
-	throw("sigfwd not implemented")
-}
-
 func raiseproc(sig int32) {
 }
 
diff --git a/src/runtime/os_netbsd.go b/src/runtime/os_netbsd.go
index af52099..9883741 100644
--- a/src/runtime/os_netbsd.go
+++ b/src/runtime/os_netbsd.go
@@ -6,6 +6,10 @@ package runtime
 
 import "unsafe"
 
+type mOS struct {
+	waitsemacount uint32
+}
+
 //go:noescape
 func setitimer(mode int32, new, old *itimerval)
 
@@ -15,10 +19,6 @@ func sigaction(sig int32, new, old *sigactiont)
 //go:noescape
 func sigaltstack(new, old *sigaltstackt)
 
-func sigfwd(fn uintptr, sig uint32, info *siginfo, ctx unsafe.Pointer) {
-	throw("sigfwd not implemented")
-}
-
 //go:noescape
 func sigprocmask(mode int32, new, old *sigset)
 
diff --git a/src/runtime/os_openbsd.go b/src/runtime/os_openbsd.go
index f94b490..b6285e4 100644
--- a/src/runtime/os_openbsd.go
+++ b/src/runtime/os_openbsd.go
@@ -4,7 +4,9 @@
 
 package runtime
 
-import "unsafe"
+type mOS struct {
+	waitsemacount uint32
+}
 
 //go:noescape
 func setitimer(mode int32, new, old *itimerval)
@@ -16,10 +18,7 @@ func sigaction(sig int32, new, old *sigactiont)
 func sigaltstack(new, old *stackt)
 
 //go:noescape
-func sigfwd(fn uintptr, sig uint32, info *siginfo, ctx unsafe.Pointer)
-
-//go:noescape
-func sigprocmask(mode int32, new uint32) uint32
+func sigprocmask(mode int32, new sigset) sigset
 
 //go:noescape
 func sysctl(mib *uint32, miblen uint32, out *byte, size *uintptr, dst *byte, ndst uintptr) int32
diff --git a/src/runtime/os_plan9.go b/src/runtime/os_plan9.go
index 6def35c..6e6a55e 100644
--- a/src/runtime/os_plan9.go
+++ b/src/runtime/os_plan9.go
@@ -6,6 +6,12 @@ package runtime
 
 import "unsafe"
 
+type mOS struct {
+	waitsemacount uint32
+	notesig       *int8
+	errstr        *byte
+}
+
 func closefd(fd int32) int32
 
 //go:noescape
diff --git a/src/runtime/os_solaris.go b/src/runtime/os_solaris.go
index 95269a7..fbf2886 100644
--- a/src/runtime/os_solaris.go
+++ b/src/runtime/os_solaris.go
@@ -6,13 +6,29 @@ package runtime
 
 import "unsafe"
 
+type mts struct {
+	tv_sec  int64
+	tv_nsec int64
+}
+
+type mscratch struct {
+	v [6]uintptr
+}
+
+type mOS struct {
+	waitsema uintptr // semaphore for parking on locks
+	perrno   *int32  // pointer to tls errno
+	// these are here because they are too large to be on the stack
+	// of low-level NOSPLIT functions.
+	//LibCall       libcall;
+	ts      mts
+	scratch mscratch
+}
+
 type libcFunc uintptr
 
 var asmsysvicall6 libcFunc
 
-//go:noescape
-func sigfwd(fn uintptr, sig uint32, info *siginfo, ctx unsafe.Pointer)
-
 //go:nosplit
 func sysvicall0(fn *libcFunc) uintptr {
 	var libcall libcall
diff --git a/src/runtime/os_windows.go b/src/runtime/os_windows.go
index 545b416..5dab1de 100644
--- a/src/runtime/os_windows.go
+++ b/src/runtime/os_windows.go
@@ -6,6 +6,10 @@ package runtime
 
 import "unsafe"
 
+type mOS struct {
+	waitsema uintptr // semaphore for parking on locks
+}
+
 type stdFunction *byte
 
 //go:linkname os_sigpipe os.sigpipe
diff --git a/src/runtime/panic.go b/src/runtime/panic.go
index a166281..ba07330 100644
--- a/src/runtime/panic.go
+++ b/src/runtime/panic.go
@@ -4,7 +4,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"unsafe"
+)
 
 var indexError = error(errorString("index out of range"))
 
@@ -417,7 +420,7 @@ func gopanic(e interface{}) {
 		// Record the panic that is running the defer.
 		// If there is a new panic during the deferred call, that panic
 		// will find d in the list and will mark d._panic (this panic) aborted.
-		d._panic = (*_panic)(noescape((unsafe.Pointer)(&p)))
+		d._panic = (*_panic)(noescape(unsafe.Pointer(&p)))
 
 		p.argp = unsafe.Pointer(getargp(0))
 		reflectcall(nil, unsafe.Pointer(d.fn), deferArgs(d), uint32(d.siz), uint32(d.siz))
@@ -527,3 +530,144 @@ func throw(s string) {
 	dopanic(0)
 	*(*int)(nil) = 0 // not reached
 }
+
+//uint32 runtime·panicking;
+var paniclk mutex
+
+// Unwind the stack after a deferred function calls recover
+// after a panic.  Then arrange to continue running as though
+// the caller of the deferred function returned normally.
+func recovery(gp *g) {
+	// Info about defer passed in G struct.
+	sp := gp.sigcode0
+	pc := gp.sigcode1
+
+	// d's arguments need to be in the stack.
+	if sp != 0 && (sp < gp.stack.lo || gp.stack.hi < sp) {
+		print("recover: ", hex(sp), " not in [", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n")
+		throw("bad recovery")
+	}
+
+	// Make the deferproc for this d return again,
+	// this time returning 1.  The calling function will
+	// jump to the standard return epilogue.
+	gcUnwindBarriers(gp, sp)
+	gp.sched.sp = sp
+	gp.sched.pc = pc
+	gp.sched.lr = 0
+	gp.sched.ret = 1
+	gogo(&gp.sched)
+}
+
+func startpanic_m() {
+	_g_ := getg()
+	if mheap_.cachealloc.size == 0 { // very early
+		print("runtime: panic before malloc heap initialized\n")
+		_g_.m.mallocing = 1 // tell rest of panic not to try to malloc
+	} else if _g_.m.mcache == nil { // can happen if called from signal handler or throw
+		_g_.m.mcache = allocmcache()
+	}
+
+	switch _g_.m.dying {
+	case 0:
+		_g_.m.dying = 1
+		_g_.writebuf = nil
+		atomic.Xadd(&panicking, 1)
+		lock(&paniclk)
+		if debug.schedtrace > 0 || debug.scheddetail > 0 {
+			schedtrace(true)
+		}
+		freezetheworld()
+		return
+	case 1:
+		// Something failed while panicing, probably the print of the
+		// argument to panic().  Just print a stack trace and exit.
+		_g_.m.dying = 2
+		print("panic during panic\n")
+		dopanic(0)
+		exit(3)
+		fallthrough
+	case 2:
+		// This is a genuine bug in the runtime, we couldn't even
+		// print the stack trace successfully.
+		_g_.m.dying = 3
+		print("stack trace unavailable\n")
+		exit(4)
+		fallthrough
+	default:
+		// Can't even print!  Just exit.
+		exit(5)
+	}
+}
+
+var didothers bool
+var deadlock mutex
+
+func dopanic_m(gp *g, pc, sp uintptr) {
+	if gp.sig != 0 {
+		print("[signal ", hex(gp.sig), " code=", hex(gp.sigcode0), " addr=", hex(gp.sigcode1), " pc=", hex(gp.sigpc), "]\n")
+	}
+
+	level, all, docrash := gotraceback()
+	_g_ := getg()
+	if level > 0 {
+		if gp != gp.m.curg {
+			all = true
+		}
+		if gp != gp.m.g0 {
+			print("\n")
+			goroutineheader(gp)
+			traceback(pc, sp, 0, gp)
+		} else if level >= 2 || _g_.m.throwing > 0 {
+			print("\nruntime stack:\n")
+			traceback(pc, sp, 0, gp)
+		}
+		if !didothers && all {
+			didothers = true
+			tracebackothers(gp)
+		}
+	}
+	unlock(&paniclk)
+
+	if atomic.Xadd(&panicking, -1) != 0 {
+		// Some other m is panicking too.
+		// Let it print what it needs to print.
+		// Wait forever without chewing up cpu.
+		// It will exit when it's done.
+		lock(&deadlock)
+		lock(&deadlock)
+	}
+
+	if docrash {
+		crash()
+	}
+
+	exit(2)
+}
+
+//go:nosplit
+func canpanic(gp *g) bool {
+	// Note that g is m->gsignal, different from gp.
+	// Note also that g->m can change at preemption, so m can go stale
+	// if this function ever makes a function call.
+	_g_ := getg()
+	_m_ := _g_.m
+
+	// Is it okay for gp to panic instead of crashing the program?
+	// Yes, as long as it is running Go code, not runtime code,
+	// and not stuck in a system call.
+	if gp == nil || gp != _m_.curg {
+		return false
+	}
+	if _m_.locks-_m_.softfloat != 0 || _m_.mallocing != 0 || _m_.throwing != 0 || _m_.preemptoff != "" || _m_.dying != 0 {
+		return false
+	}
+	status := readgstatus(gp)
+	if status&^_Gscan != _Grunning || gp.syscallsp != 0 {
+		return false
+	}
+	if GOOS == "windows" && _m_.libcallsp != 0 {
+		return false
+	}
+	return true
+}
diff --git a/src/runtime/panic1.go b/src/runtime/panic1.go
deleted file mode 100644
index 1a71d09..0000000
--- a/src/runtime/panic1.go
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright 2012 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 runtime
-
-// Code related to defer, panic and recover.
-// TODO: Merge into panic.go.
-
-//uint32 runtime·panicking;
-var paniclk mutex
-
-const hasLinkRegister = GOARCH == "arm" || GOARCH == "arm64" || GOARCH == "ppc64" || GOARCH == "ppc64le"
-
-// Unwind the stack after a deferred function calls recover
-// after a panic.  Then arrange to continue running as though
-// the caller of the deferred function returned normally.
-func recovery(gp *g) {
-	// Info about defer passed in G struct.
-	sp := gp.sigcode0
-	pc := gp.sigcode1
-
-	// d's arguments need to be in the stack.
-	if sp != 0 && (sp < gp.stack.lo || gp.stack.hi < sp) {
-		print("recover: ", hex(sp), " not in [", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n")
-		throw("bad recovery")
-	}
-
-	// Make the deferproc for this d return again,
-	// this time returning 1.  The calling function will
-	// jump to the standard return epilogue.
-	gcUnwindBarriers(gp, sp)
-	gp.sched.sp = sp
-	gp.sched.pc = pc
-	gp.sched.lr = 0
-	gp.sched.ret = 1
-	gogo(&gp.sched)
-}
-
-func startpanic_m() {
-	_g_ := getg()
-	if mheap_.cachealloc.size == 0 { // very early
-		print("runtime: panic before malloc heap initialized\n")
-		_g_.m.mallocing = 1 // tell rest of panic not to try to malloc
-	} else if _g_.m.mcache == nil { // can happen if called from signal handler or throw
-		_g_.m.mcache = allocmcache()
-	}
-
-	switch _g_.m.dying {
-	case 0:
-		_g_.m.dying = 1
-		if _g_ != nil {
-			_g_.writebuf = nil
-		}
-		xadd(&panicking, 1)
-		lock(&paniclk)
-		if debug.schedtrace > 0 || debug.scheddetail > 0 {
-			schedtrace(true)
-		}
-		freezetheworld()
-		return
-	case 1:
-		// Something failed while panicing, probably the print of the
-		// argument to panic().  Just print a stack trace and exit.
-		_g_.m.dying = 2
-		print("panic during panic\n")
-		dopanic(0)
-		exit(3)
-		fallthrough
-	case 2:
-		// This is a genuine bug in the runtime, we couldn't even
-		// print the stack trace successfully.
-		_g_.m.dying = 3
-		print("stack trace unavailable\n")
-		exit(4)
-		fallthrough
-	default:
-		// Can't even print!  Just exit.
-		exit(5)
-	}
-}
-
-var didothers bool
-var deadlock mutex
-
-func dopanic_m(gp *g, pc, sp uintptr) {
-	if gp.sig != 0 {
-		print("[signal ", hex(gp.sig), " code=", hex(gp.sigcode0), " addr=", hex(gp.sigcode1), " pc=", hex(gp.sigpc), "]\n")
-	}
-
-	var docrash bool
-	_g_ := getg()
-	if t := gotraceback(&docrash); t > 0 {
-		if gp != gp.m.g0 {
-			print("\n")
-			goroutineheader(gp)
-			traceback(pc, sp, 0, gp)
-		} else if t >= 2 || _g_.m.throwing > 0 {
-			print("\nruntime stack:\n")
-			traceback(pc, sp, 0, gp)
-		}
-		if !didothers {
-			didothers = true
-			tracebackothers(gp)
-		}
-	}
-	unlock(&paniclk)
-
-	if xadd(&panicking, -1) != 0 {
-		// Some other m is panicking too.
-		// Let it print what it needs to print.
-		// Wait forever without chewing up cpu.
-		// It will exit when it's done.
-		lock(&deadlock)
-		lock(&deadlock)
-	}
-
-	if docrash {
-		crash()
-	}
-
-	exit(2)
-}
-
-//go:nosplit
-func canpanic(gp *g) bool {
-	// Note that g is m->gsignal, different from gp.
-	// Note also that g->m can change at preemption, so m can go stale
-	// if this function ever makes a function call.
-	_g_ := getg()
-	_m_ := _g_.m
-
-	// Is it okay for gp to panic instead of crashing the program?
-	// Yes, as long as it is running Go code, not runtime code,
-	// and not stuck in a system call.
-	if gp == nil || gp != _m_.curg {
-		return false
-	}
-	if _m_.locks-_m_.softfloat != 0 || _m_.mallocing != 0 || _m_.throwing != 0 || _m_.preemptoff != "" || _m_.dying != 0 {
-		return false
-	}
-	status := readgstatus(gp)
-	if status&^_Gscan != _Grunning || gp.syscallsp != 0 {
-		return false
-	}
-	if GOOS == "windows" && _m_.libcallsp != 0 {
-		return false
-	}
-	return true
-}
diff --git a/src/runtime/parfor.go b/src/runtime/parfor.go
index c82beee..9e11cb3 100644
--- a/src/runtime/parfor.go
+++ b/src/runtime/parfor.go
@@ -6,6 +6,11 @@
 
 package runtime
 
+import (
+	"runtime/internal/atomic"
+	"runtime/internal/sys"
+)
+
 // A parfor holds state for the parallel for operation.
 type parfor struct {
 	body   func(*parfor, uint32) // executed for each element
@@ -36,7 +41,7 @@ type parforthread struct {
 	nprocyield uint64
 	nosyield   uint64
 	nsleep     uint64
-	pad        [_CacheLineSize]byte
+	pad        [sys.CacheLineSize]byte
 }
 
 func parforalloc(nthrmax uint32) *parfor {
@@ -82,7 +87,7 @@ func parforsetup(desc *parfor, nthr, n uint32, wait bool, body func(*parfor, uin
 
 func parfordo(desc *parfor) {
 	// Obtain 0-based thread index.
-	tid := xadd(&desc.thrseq, 1) - 1
+	tid := atomic.Xadd(&desc.thrseq, 1) - 1
 	if tid >= desc.nthr {
 		print("tid=", tid, " nthr=", desc.nthr, "\n")
 		throw("parfor: invalid tid")
@@ -103,7 +108,7 @@ func parfordo(desc *parfor) {
 		for {
 			// While there is local work,
 			// bump low index and execute the iteration.
-			pos := xadd64(mypos, 1)
+			pos := atomic.Xadd64(mypos, 1)
 			begin := uint32(pos) - 1
 			end := uint32(pos >> 32)
 			if begin < end {
@@ -120,7 +125,7 @@ func parfordo(desc *parfor) {
 			// increment the done counter...
 			if try > desc.nthr*4 && !idle {
 				idle = true
-				xadd(&desc.done, 1)
+				atomic.Xadd(&desc.done, 1)
 			}
 
 			// ...if all threads have incremented the counter,
@@ -131,7 +136,7 @@ func parfordo(desc *parfor) {
 			}
 			if desc.done+extra == desc.nthr {
 				if !idle {
-					xadd(&desc.done, 1)
+					atomic.Xadd(&desc.done, 1)
 				}
 				goto exit
 			}
@@ -145,7 +150,7 @@ func parfordo(desc *parfor) {
 			victimpos := &desc.thr[victim].pos
 			for {
 				// See if it has any work.
-				pos := atomicload64(victimpos)
+				pos := atomic.Load64(victimpos)
 				begin = uint32(pos)
 				end = uint32(pos >> 32)
 				if begin+1 >= end {
@@ -154,12 +159,12 @@ func parfordo(desc *parfor) {
 					break
 				}
 				if idle {
-					xadd(&desc.done, -1)
+					atomic.Xadd(&desc.done, -1)
 					idle = false
 				}
 				begin2 := begin + (end-begin)/2
 				newpos := uint64(begin) | uint64(begin2)<<32
-				if cas64(victimpos, pos, newpos) {
+				if atomic.Cas64(victimpos, pos, newpos) {
 					begin = begin2
 					break
 				}
@@ -169,7 +174,7 @@ func parfordo(desc *parfor) {
 				if idle {
 					throw("parfor: should not be idle")
 				}
-				atomicstore64(mypos, uint64(begin)|uint64(end)<<32)
+				atomic.Store64(mypos, uint64(begin)|uint64(end)<<32)
 				me.nsteal++
 				me.nstealcnt += uint64(end) - uint64(begin)
 				break
@@ -185,7 +190,7 @@ func parfordo(desc *parfor) {
 				// If a caller asked not to wait for the others, exit now
 				// (assume that most work is already done at this point).
 				if !idle {
-					xadd(&desc.done, 1)
+					atomic.Xadd(&desc.done, 1)
 				}
 				goto exit
 			} else if try < 6*desc.nthr {
@@ -199,11 +204,11 @@ func parfordo(desc *parfor) {
 	}
 
 exit:
-	xadd64(&desc.nsteal, int64(me.nsteal))
-	xadd64(&desc.nstealcnt, int64(me.nstealcnt))
-	xadd64(&desc.nprocyield, int64(me.nprocyield))
-	xadd64(&desc.nosyield, int64(me.nosyield))
-	xadd64(&desc.nsleep, int64(me.nsleep))
+	atomic.Xadd64(&desc.nsteal, int64(me.nsteal))
+	atomic.Xadd64(&desc.nstealcnt, int64(me.nstealcnt))
+	atomic.Xadd64(&desc.nprocyield, int64(me.nprocyield))
+	atomic.Xadd64(&desc.nosyield, int64(me.nosyield))
+	atomic.Xadd64(&desc.nsleep, int64(me.nsleep))
 	me.nsteal = 0
 	me.nstealcnt = 0
 	me.nprocyield = 0
diff --git a/src/runtime/pprof/mprof_test.go b/src/runtime/pprof/mprof_test.go
index ebf53dd..d14fb58 100644
--- a/src/runtime/pprof/mprof_test.go
+++ b/src/runtime/pprof/mprof_test.go
@@ -22,11 +22,8 @@ func allocateTransient1M() {
 	}
 }
 
+//go:noinline
 func allocateTransient2M() {
-	// prevent inlining
-	if memSink == nil {
-		panic("bad")
-	}
 	memSink = make([]byte, 2<<20)
 }
 
@@ -76,18 +73,18 @@ func TestMemoryProfiler(t *testing.T) {
 
 	tests := []string{
 		fmt.Sprintf(`%v: %v \[%v: %v\] @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
-#	0x[0-9,a-f]+	runtime/pprof_test\.allocatePersistent1K\+0x[0-9,a-f]+	.*/runtime/pprof/mprof_test\.go:43
-#	0x[0-9,a-f]+	runtime/pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+	.*/runtime/pprof/mprof_test\.go:66
+#	0x[0-9,a-f]+	runtime/pprof_test\.allocatePersistent1K\+0x[0-9,a-f]+	.*/runtime/pprof/mprof_test\.go:40
+#	0x[0-9,a-f]+	runtime/pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+	.*/runtime/pprof/mprof_test\.go:63
 `, 32*memoryProfilerRun, 1024*memoryProfilerRun, 32*memoryProfilerRun, 1024*memoryProfilerRun),
 
 		fmt.Sprintf(`0: 0 \[%v: %v\] @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
 #	0x[0-9,a-f]+	runtime/pprof_test\.allocateTransient1M\+0x[0-9,a-f]+	.*/runtime/pprof/mprof_test.go:21
-#	0x[0-9,a-f]+	runtime/pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+	.*/runtime/pprof/mprof_test.go:64
+#	0x[0-9,a-f]+	runtime/pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+	.*/runtime/pprof/mprof_test.go:61
 `, (1<<10)*memoryProfilerRun, (1<<20)*memoryProfilerRun),
 
 		fmt.Sprintf(`0: 0 \[%v: %v\] @ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+ 0x[0-9,a-f]+
-#	0x[0-9,a-f]+	runtime/pprof_test\.allocateTransient2M\+0x[0-9,a-f]+	.*/runtime/pprof/mprof_test.go:30
-#	0x[0-9,a-f]+	runtime/pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+	.*/runtime/pprof/mprof_test.go:65
+#	0x[0-9,a-f]+	runtime/pprof_test\.allocateTransient2M\+0x[0-9,a-f]+	.*/runtime/pprof/mprof_test.go:27
+#	0x[0-9,a-f]+	runtime/pprof_test\.TestMemoryProfiler\+0x[0-9,a-f]+	.*/runtime/pprof/mprof_test.go:62
 `, memoryProfilerRun, (2<<20)*memoryProfilerRun),
 	}
 
diff --git a/src/runtime/pprof/pprof.go b/src/runtime/pprof/pprof.go
index 23fc850..e09a33d 100644
--- a/src/runtime/pprof/pprof.go
+++ b/src/runtime/pprof/pprof.go
@@ -20,8 +20,8 @@ import (
 	"text/tabwriter"
 )
 
-// BUG(rsc): Profiles are incomplete and inaccurate on NetBSD and OS X.
-// See https://golang.org/issue/6047 for details.
+// BUG(rsc): Profiles are only as good as the kernel support used to generate them.
+// See https://golang.org/issue/13841 for details about known problems.
 
 // A Profile is a collection of stack traces showing the call sequences
 // that led to instances of a particular event, such as allocation.
@@ -346,7 +346,7 @@ func printStackRecord(w io.Writer, stk []uintptr, allFrames bool) {
 			name := f.Name()
 			// Hide runtime.goexit and any runtime functions at the beginning.
 			// This is useful mainly for allocation traces.
-			wasPanic = name == "runtime.panic"
+			wasPanic = name == "runtime.gopanic"
 			if name == "runtime.goexit" || !show && strings.HasPrefix(name, "runtime.") {
 				continue
 			}
@@ -567,6 +567,14 @@ var cpu struct {
 // StartCPUProfile enables CPU profiling for the current process.
 // While profiling, the profile will be buffered and written to w.
 // StartCPUProfile returns an error if profiling is already enabled.
+//
+// On Unix-like systems, StartCPUProfile does not work by default for
+// Go code built with -buildmode=c-archive or -buildmode=c-shared.
+// StartCPUProfile relies on the SIGPROF signal, but that signal will
+// be delivered to the main program's SIGPROF signal handler (if any)
+// not to the one used by Go.  To make it work, call os/signal.Notify
+// for syscall.SIGPROF, but note that doing so may break any profiling
+// being done by the main program.
 func StartCPUProfile(w io.Writer) error {
 	// The runtime routines allow a variable profiling rate,
 	// but in practice operating systems cannot trigger signals
diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go
index 785d75a..ab6b183 100644
--- a/src/runtime/pprof/pprof_test.go
+++ b/src/runtime/pprof/pprof_test.go
@@ -23,14 +23,14 @@ import (
 	"unsafe"
 )
 
-func cpuHogger(f func()) {
+func cpuHogger(f func(), dur time.Duration) {
 	// We only need to get one 100 Hz clock tick, so we've got
-	// a 25x safety buffer.
+	// a large safety buffer.
 	// But do at least 500 iterations (which should take about 100ms),
 	// otherwise TestCPUProfileMultithreaded can fail if only one
-	// thread is scheduled during the 250ms period.
+	// thread is scheduled during the testing period.
 	t0 := time.Now()
-	for i := 0; i < 500 || time.Since(t0) < 250*time.Millisecond; i++ {
+	for i := 0; i < 500 || time.Since(t0) < dur; i++ {
 		f()
 	}
 }
@@ -68,20 +68,20 @@ func cpuHog2() {
 }
 
 func TestCPUProfile(t *testing.T) {
-	testCPUProfile(t, []string{"runtime/pprof_test.cpuHog1"}, func() {
-		cpuHogger(cpuHog1)
+	testCPUProfile(t, []string{"runtime/pprof_test.cpuHog1"}, func(dur time.Duration) {
+		cpuHogger(cpuHog1, dur)
 	})
 }
 
 func TestCPUProfileMultithreaded(t *testing.T) {
 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
-	testCPUProfile(t, []string{"runtime/pprof_test.cpuHog1", "runtime/pprof_test.cpuHog2"}, func() {
+	testCPUProfile(t, []string{"runtime/pprof_test.cpuHog1", "runtime/pprof_test.cpuHog2"}, func(dur time.Duration) {
 		c := make(chan int)
 		go func() {
-			cpuHogger(cpuHog1)
+			cpuHogger(cpuHog1, dur)
 			c <- 1
 		}()
-		cpuHogger(cpuHog2)
+		cpuHogger(cpuHog2, dur)
 		<-c
 	})
 }
@@ -92,11 +92,11 @@ func parseProfile(t *testing.T, bytes []byte, f func(uintptr, []uintptr)) {
 	val := *(*[]uintptr)(unsafe.Pointer(&bytes))
 	val = val[:l]
 
-	// 5 for the header, 2 for the per-sample header on at least one sample, 3 for the trailer.
-	if l < 5+2+3 {
+	// 5 for the header, 3 for the trailer.
+	if l < 5+3 {
 		t.Logf("profile too short: %#x", val)
 		if badOS[runtime.GOOS] {
-			t.Skipf("ignoring failure on %s; see golang.org/issue/6047", runtime.GOOS)
+			t.Skipf("ignoring failure on %s; see golang.org/issue/13841", runtime.GOOS)
 			return
 		}
 		t.FailNow()
@@ -120,7 +120,7 @@ func parseProfile(t *testing.T, bytes []byte, f func(uintptr, []uintptr)) {
 	}
 }
 
-func testCPUProfile(t *testing.T, need []string, f func()) {
+func testCPUProfile(t *testing.T, need []string, f func(dur time.Duration)) {
 	switch runtime.GOOS {
 	case "darwin":
 		switch runtime.GOARCH {
@@ -138,12 +138,55 @@ func testCPUProfile(t *testing.T, need []string, f func()) {
 		t.Skip("skipping on plan9")
 	}
 
-	var prof bytes.Buffer
-	if err := StartCPUProfile(&prof); err != nil {
-		t.Fatal(err)
+	const maxDuration = 5 * time.Second
+	// If we're running a long test, start with a long duration
+	// because some of the tests (e.g., TestStackBarrierProfiling)
+	// are trying to make sure something *doesn't* happen.
+	duration := 5 * time.Second
+	if testing.Short() {
+		duration = 200 * time.Millisecond
+	}
+
+	// Profiling tests are inherently flaky, especially on a
+	// loaded system, such as when this test is running with
+	// several others under go test std. If a test fails in a way
+	// that could mean it just didn't run long enough, try with a
+	// longer duration.
+	for duration <= maxDuration {
+		var prof bytes.Buffer
+		if err := StartCPUProfile(&prof); err != nil {
+			t.Fatal(err)
+		}
+		f(duration)
+		StopCPUProfile()
+
+		if profileOk(t, need, prof, duration) {
+			return
+		}
+
+		duration *= 2
+		if duration <= maxDuration {
+			t.Logf("retrying with %s duration", duration)
+		}
+	}
+
+	if badOS[runtime.GOOS] {
+		t.Skipf("ignoring failure on %s; see golang.org/issue/13841", runtime.GOOS)
+		return
 	}
-	f()
-	StopCPUProfile()
+	// Ignore the failure if the tests are running in a QEMU-based emulator,
+	// QEMU is not perfect at emulating everything.
+	// IN_QEMU environmental variable is set by some of the Go builders.
+	// IN_QEMU=1 indicates that the tests are running in QEMU. See issue 9605.
+	if os.Getenv("IN_QEMU") == "1" {
+		t.Skip("ignore the failure in QEMU; see golang.org/issue/9605")
+		return
+	}
+	t.FailNow()
+}
+
+func profileOk(t *testing.T, need []string, prof bytes.Buffer, duration time.Duration) (ok bool) {
+	ok = true
 
 	// Check that profile is well formed and contains need.
 	have := make([]uintptr, len(need))
@@ -160,6 +203,10 @@ func testCPUProfile(t *testing.T, need []string, f func()) {
 					have[i] += count
 				}
 			}
+			if strings.Contains(f.Name(), "stackBarrier") {
+				// The runtime should have unwound this.
+				t.Fatalf("profile includes stackBarrier")
+			}
 		}
 	})
 	t.Logf("total %d CPU profile samples collected", samples)
@@ -168,11 +215,18 @@ func testCPUProfile(t *testing.T, need []string, f func()) {
 		// On some windows machines we end up with
 		// not enough samples due to coarse timer
 		// resolution. Let it go.
-		t.Skip("too few samples on Windows (golang.org/issue/10842)")
+		t.Log("too few samples on Windows (golang.org/issue/10842)")
+		return false
+	}
+
+	// Check that we got a reasonable number of samples.
+	if ideal := uintptr(duration * 100 / time.Second); samples == 0 || samples < ideal/4 {
+		t.Logf("too few samples; got %d, want at least %d, ideally %d", samples, ideal/4, ideal)
+		ok = false
 	}
 
 	if len(need) == 0 {
-		return
+		return ok
 	}
 
 	var total uintptr
@@ -180,9 +234,8 @@ func testCPUProfile(t *testing.T, need []string, f func()) {
 		total += have[i]
 		t.Logf("%s: %d\n", name, have[i])
 	}
-	ok := true
 	if total == 0 {
-		t.Logf("no CPU profile samples collected")
+		t.Logf("no samples in expected functions")
 		ok = false
 	}
 	// We'd like to check a reasonable minimum, like
@@ -196,22 +249,7 @@ func testCPUProfile(t *testing.T, need []string, f func()) {
 			ok = false
 		}
 	}
-
-	if !ok {
-		if badOS[runtime.GOOS] {
-			t.Skipf("ignoring failure on %s; see golang.org/issue/6047", runtime.GOOS)
-			return
-		}
-		// Ignore the failure if the tests are running in a QEMU-based emulator,
-		// QEMU is not perfect at emulating everything.
-		// IN_QEMU environmental variable is set by some of the Go builders.
-		// IN_QEMU=1 indicates that the tests are running in QEMU. See issue 9605.
-		if os.Getenv("IN_QEMU") == "1" {
-			t.Skip("ignore the failure in QEMU; see golang.org/issue/9605")
-			return
-		}
-		t.FailNow()
-	}
+	return ok
 }
 
 // Fork can hang if preempted with signals frequently enough (see issue 5517).
@@ -306,8 +344,8 @@ func TestGoroutineSwitch(t *testing.T) {
 
 // Test that profiling of division operations is okay, especially on ARM. See issue 6681.
 func TestMathBigDivide(t *testing.T) {
-	testCPUProfile(t, nil, func() {
-		t := time.After(5 * time.Second)
+	testCPUProfile(t, nil, func(duration time.Duration) {
+		t := time.After(duration)
 		pi := new(big.Int)
 		for {
 			for i := 0; i < 100; i++ {
@@ -324,11 +362,71 @@ func TestMathBigDivide(t *testing.T) {
 	})
 }
 
-// Operating systems that are expected to fail the tests. See issue 6047.
+func TestStackBarrierProfiling(t *testing.T) {
+	if (runtime.GOOS == "linux" && runtime.GOARCH == "arm") || runtime.GOOS == "openbsd" || runtime.GOOS == "solaris" || runtime.GOOS == "dragonfly" || runtime.GOOS == "freebsd" {
+		// This test currently triggers a large number of
+		// usleep(100)s. These kernels/arches have poor
+		// resolution timers, so this gives up a whole
+		// scheduling quantum. On Linux and the BSDs (and
+		// probably Solaris), profiling signals are only
+		// generated when a process completes a whole
+		// scheduling quantum, so this test often gets zero
+		// profiling signals and fails.
+		t.Skipf("low resolution timers inhibit profiling signals (golang.org/issue/13405)")
+		return
+	}
+
+	if !strings.Contains(os.Getenv("GODEBUG"), "gcstackbarrierall=1") {
+		// Re-execute this test with constant GC and stack
+		// barriers at every frame.
+		testenv.MustHaveExec(t)
+		if runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" {
+			t.Skip("gcstackbarrierall doesn't work on ppc64")
+		}
+		args := []string{"-test.run=TestStackBarrierProfiling"}
+		if testing.Short() {
+			args = append(args, "-test.short")
+		}
+		cmd := exec.Command(os.Args[0], args...)
+		cmd.Env = append([]string{"GODEBUG=gcstackbarrierall=1", "GOGC=1"}, os.Environ()...)
+		if out, err := cmd.CombinedOutput(); err != nil {
+			t.Fatalf("subprocess failed with %v:\n%s", err, out)
+		}
+		return
+	}
+
+	testCPUProfile(t, nil, func(duration time.Duration) {
+		// In long mode, we're likely to get one or two
+		// samples in stackBarrier.
+		t := time.After(duration)
+		for {
+			deepStack(1000)
+			select {
+			case <-t:
+				return
+			default:
+			}
+		}
+	})
+}
+
+var x []byte
+
+func deepStack(depth int) int {
+	if depth == 0 {
+		return 0
+	}
+	x = make([]byte, 1024)
+	return deepStack(depth-1) + 1
+}
+
+// Operating systems that are expected to fail the tests. See issue 13841.
 var badOS = map[string]bool{
-	"darwin": true,
-	"netbsd": true,
-	"plan9":  true,
+	"darwin":    true,
+	"netbsd":    true,
+	"plan9":     true,
+	"dragonfly": true,
+	"solaris":   true,
 }
 
 func TestBlockProfile(t *testing.T) {
diff --git a/src/runtime/print.go b/src/runtime/print.go
new file mode 100644
index 0000000..f789f89
--- /dev/null
+++ b/src/runtime/print.go
@@ -0,0 +1,221 @@
+// Copyright 2009 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 runtime
+
+import "unsafe"
+
+// The compiler knows that a print of a value of this type
+// should use printhex instead of printuint (decimal).
+type hex uint64
+
+func bytes(s string) (ret []byte) {
+	rp := (*slice)(unsafe.Pointer(&ret))
+	sp := stringStructOf(&s)
+	rp.array = sp.str
+	rp.len = sp.len
+	rp.cap = sp.len
+	return
+}
+
+var debuglock mutex
+
+// The compiler emits calls to printlock and printunlock around
+// the multiple calls that implement a single Go print or println
+// statement. Some of the print helpers (printsp, for example)
+// call print recursively. There is also the problem of a crash
+// happening during the print routines and needing to acquire
+// the print lock to print information about the crash.
+// For both these reasons, let a thread acquire the printlock 'recursively'.
+
+func printlock() {
+	mp := getg().m
+	mp.locks++ // do not reschedule between printlock++ and lock(&debuglock).
+	mp.printlock++
+	if mp.printlock == 1 {
+		lock(&debuglock)
+	}
+	mp.locks-- // now we know debuglock is held and holding up mp.locks for us.
+}
+
+func printunlock() {
+	mp := getg().m
+	mp.printlock--
+	if mp.printlock == 0 {
+		unlock(&debuglock)
+	}
+}
+
+// write to goroutine-local buffer if diverting output,
+// or else standard error.
+func gwrite(b []byte) {
+	if len(b) == 0 {
+		return
+	}
+	gp := getg()
+	if gp == nil || gp.writebuf == nil {
+		writeErr(b)
+		return
+	}
+
+	n := copy(gp.writebuf[len(gp.writebuf):cap(gp.writebuf)], b)
+	gp.writebuf = gp.writebuf[:len(gp.writebuf)+n]
+}
+
+func printsp() {
+	print(" ")
+}
+
+func printnl() {
+	print("\n")
+}
+
+func printbool(v bool) {
+	if v {
+		print("true")
+	} else {
+		print("false")
+	}
+}
+
+func printfloat(v float64) {
+	switch {
+	case v != v:
+		print("NaN")
+		return
+	case v+v == v && v > 0:
+		print("+Inf")
+		return
+	case v+v == v && v < 0:
+		print("-Inf")
+		return
+	}
+
+	const n = 7 // digits printed
+	var buf [n + 7]byte
+	buf[0] = '+'
+	e := 0 // exp
+	if v == 0 {
+		if 1/v < 0 {
+			buf[0] = '-'
+		}
+	} else {
+		if v < 0 {
+			v = -v
+			buf[0] = '-'
+		}
+
+		// normalize
+		for v >= 10 {
+			e++
+			v /= 10
+		}
+		for v < 1 {
+			e--
+			v *= 10
+		}
+
+		// round
+		h := 5.0
+		for i := 0; i < n; i++ {
+			h /= 10
+		}
+		v += h
+		if v >= 10 {
+			e++
+			v /= 10
+		}
+	}
+
+	// format +d.dddd+edd
+	for i := 0; i < n; i++ {
+		s := int(v)
+		buf[i+2] = byte(s + '0')
+		v -= float64(s)
+		v *= 10
+	}
+	buf[1] = buf[2]
+	buf[2] = '.'
+
+	buf[n+2] = 'e'
+	buf[n+3] = '+'
+	if e < 0 {
+		e = -e
+		buf[n+3] = '-'
+	}
+
+	buf[n+4] = byte(e/100) + '0'
+	buf[n+5] = byte(e/10)%10 + '0'
+	buf[n+6] = byte(e%10) + '0'
+	gwrite(buf[:])
+}
+
+func printcomplex(c complex128) {
+	print("(", real(c), imag(c), "i)")
+}
+
+func printuint(v uint64) {
+	var buf [100]byte
+	i := len(buf)
+	for i--; i > 0; i-- {
+		buf[i] = byte(v%10 + '0')
+		if v < 10 {
+			break
+		}
+		v /= 10
+	}
+	gwrite(buf[i:])
+}
+
+func printint(v int64) {
+	if v < 0 {
+		print("-")
+		v = -v
+	}
+	printuint(uint64(v))
+}
+
+func printhex(v uint64) {
+	const dig = "0123456789abcdef"
+	var buf [100]byte
+	i := len(buf)
+	for i--; i > 0; i-- {
+		buf[i] = dig[v%16]
+		if v < 16 {
+			break
+		}
+		v /= 16
+	}
+	i--
+	buf[i] = 'x'
+	i--
+	buf[i] = '0'
+	gwrite(buf[i:])
+}
+
+func printpointer(p unsafe.Pointer) {
+	printhex(uint64(uintptr(p)))
+}
+
+func printstring(s string) {
+	if uintptr(len(s)) > maxstring {
+		gwrite(bytes("[string too long]"))
+		return
+	}
+	gwrite(bytes(s))
+}
+
+func printslice(s []byte) {
+	sp := (*slice)(unsafe.Pointer(&s))
+	print("[", len(s), "/", cap(s), "]")
+	printpointer(unsafe.Pointer(sp.array))
+}
+
+func printeface(e eface) {
+	print("(", e._type, ",", e.data, ")")
+}
+
+func printiface(i iface) {
+	print("(", i.tab, ",", i.data, ")")
+}
diff --git a/src/runtime/print1.go b/src/runtime/print1.go
deleted file mode 100644
index 6eff381..0000000
--- a/src/runtime/print1.go
+++ /dev/null
@@ -1,231 +0,0 @@
-// Copyright 2009 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 runtime
-
-import "unsafe"
-
-// The compiler knows that a print of a value of this type
-// should use printhex instead of printuint (decimal).
-type hex uint64
-
-func bytes(s string) (ret []byte) {
-	rp := (*slice)(unsafe.Pointer(&ret))
-	sp := (*_string)(noescape(unsafe.Pointer(&s)))
-	rp.array = unsafe.Pointer(sp.str)
-	rp.len = sp.len
-	rp.cap = sp.len
-	return
-}
-
-var debuglock mutex
-
-// The compiler emits calls to printlock and printunlock around
-// the multiple calls that implement a single Go print or println
-// statement. Some of the print helpers (printsp, for example)
-// call print recursively. There is also the problem of a crash
-// happening during the print routines and needing to acquire
-// the print lock to print information about the crash.
-// For both these reasons, let a thread acquire the printlock 'recursively'.
-
-func printlock() {
-	mp := getg().m
-	mp.locks++ // do not reschedule between printlock++ and lock(&debuglock).
-	mp.printlock++
-	if mp.printlock == 1 {
-		lock(&debuglock)
-	}
-	mp.locks-- // now we know debuglock is held and holding up mp.locks for us.
-}
-
-func printunlock() {
-	mp := getg().m
-	mp.printlock--
-	if mp.printlock == 0 {
-		unlock(&debuglock)
-	}
-}
-
-// write to goroutine-local buffer if diverting output,
-// or else standard error.
-func gwrite(b []byte) {
-	if len(b) == 0 {
-		return
-	}
-	gp := getg()
-	if gp == nil || gp.writebuf == nil {
-		writeErr(b)
-		return
-	}
-
-	n := copy(gp.writebuf[len(gp.writebuf):cap(gp.writebuf)], b)
-	gp.writebuf = gp.writebuf[:len(gp.writebuf)+n]
-}
-
-func printsp() {
-	print(" ")
-}
-
-func printnl() {
-	print("\n")
-}
-
-func printpc(p unsafe.Pointer) {
-	print("PC=", hex(uintptr(p)))
-}
-
-func printbool(v bool) {
-	if v {
-		print("true")
-	} else {
-		print("false")
-	}
-}
-
-func printbyte(c byte) {
-	gwrite((*[1]byte)(unsafe.Pointer(&c))[:])
-}
-
-func printfloat(v float64) {
-	switch {
-	case v != v:
-		print("NaN")
-		return
-	case v+v == v && v > 0:
-		print("+Inf")
-		return
-	case v+v == v && v < 0:
-		print("-Inf")
-		return
-	}
-
-	const n = 7 // digits printed
-	var buf [n + 7]byte
-	buf[0] = '+'
-	e := 0 // exp
-	if v == 0 {
-		if 1/v < 0 {
-			buf[0] = '-'
-		}
-	} else {
-		if v < 0 {
-			v = -v
-			buf[0] = '-'
-		}
-
-		// normalize
-		for v >= 10 {
-			e++
-			v /= 10
-		}
-		for v < 1 {
-			e--
-			v *= 10
-		}
-
-		// round
-		h := 5.0
-		for i := 0; i < n; i++ {
-			h /= 10
-		}
-		v += h
-		if v >= 10 {
-			e++
-			v /= 10
-		}
-	}
-
-	// format +d.dddd+edd
-	for i := 0; i < n; i++ {
-		s := int(v)
-		buf[i+2] = byte(s + '0')
-		v -= float64(s)
-		v *= 10
-	}
-	buf[1] = buf[2]
-	buf[2] = '.'
-
-	buf[n+2] = 'e'
-	buf[n+3] = '+'
-	if e < 0 {
-		e = -e
-		buf[n+3] = '-'
-	}
-
-	buf[n+4] = byte(e/100) + '0'
-	buf[n+5] = byte(e/10)%10 + '0'
-	buf[n+6] = byte(e%10) + '0'
-	gwrite(buf[:])
-}
-
-func printcomplex(c complex128) {
-	print("(", real(c), imag(c), "i)")
-}
-
-func printuint(v uint64) {
-	var buf [100]byte
-	i := len(buf)
-	for i--; i > 0; i-- {
-		buf[i] = byte(v%10 + '0')
-		if v < 10 {
-			break
-		}
-		v /= 10
-	}
-	gwrite(buf[i:])
-}
-
-func printint(v int64) {
-	if v < 0 {
-		print("-")
-		v = -v
-	}
-	printuint(uint64(v))
-}
-
-func printhex(v uint64) {
-	const dig = "0123456789abcdef"
-	var buf [100]byte
-	i := len(buf)
-	for i--; i > 0; i-- {
-		buf[i] = dig[v%16]
-		if v < 16 {
-			break
-		}
-		v /= 16
-	}
-	i--
-	buf[i] = 'x'
-	i--
-	buf[i] = '0'
-	gwrite(buf[i:])
-}
-
-func printpointer(p unsafe.Pointer) {
-	printhex(uint64(uintptr(p)))
-}
-
-func printstring(s string) {
-	if uintptr(len(s)) > maxstring {
-		gwrite(bytes("[string too long]"))
-		return
-	}
-	gwrite(bytes(s))
-}
-
-func printslice(s []byte) {
-	sp := (*slice)(unsafe.Pointer(&s))
-	print("[", len(s), "/", cap(s), "]")
-	printpointer(unsafe.Pointer(sp.array))
-}
-
-func printeface(e interface{}) {
-	ep := (*eface)(unsafe.Pointer(&e))
-	print("(", ep._type, ",", ep.data, ")")
-}
-
-func printiface(i fInterface) {
-	ip := (*iface)(unsafe.Pointer(&i))
-	print("(", ip.tab, ",", ip.data, ")")
-}
diff --git a/src/runtime/print1_write_android.go b/src/runtime/print1_write_android.go
deleted file mode 100644
index 54d4826..0000000
--- a/src/runtime/print1_write_android.go
+++ /dev/null
@@ -1,160 +0,0 @@
-// 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 runtime
-
-import "unsafe"
-
-var (
-	writeHeader = []byte{6 /* ANDROID_LOG_ERROR */, 'G', 'o', 0}
-	writePath   = []byte("/dev/log/main\x00")
-	writeLogd   = []byte("/dev/socket/logdw\x00")
-
-	// guarded by printlock/printunlock.
-	writeFD  uintptr
-	writeBuf [1024]byte
-	writePos int
-)
-
-// Prior to Android-L, logging was done through writes to /dev/log files implemented
-// in kernel ring buffers. In Android-L, those /dev/log files are no longer
-// accessible and logging is done through a centralized user-mode logger, logd.
-//
-// https://android.googlesource.com/platform/system/core/+/master/liblog/logd_write.c
-type loggerType int32
-
-const (
-	unknown loggerType = iota
-	legacy
-	logd
-	// TODO(hakim): logging for emulator?
-)
-
-var logger loggerType
-
-func writeErr(b []byte) {
-	if logger == unknown {
-		// Use logd if /dev/socket/logdw is available.
-		if v := uintptr(access(&writeLogd[0], 0x02 /* W_OK */)); v == 0 {
-			logger = logd
-			initLogd()
-		} else {
-			logger = legacy
-			initLegacy()
-		}
-	}
-
-	// Write to stderr for command-line programs.
-	write(2, unsafe.Pointer(&b[0]), int32(len(b)))
-
-	// Log format: "<header>\x00<message m bytes>\x00"
-	//
-	// <header>
-	//   In legacy mode: "<priority 1 byte><tag n bytes>".
-	//   In logd mode: "<android_log_header_t 11 bytes><priority 1 byte><tag n bytes>"
-	//
-	// The entire log needs to be delivered in a single syscall (the NDK
-	// does this with writev). Each log is its own line, so we need to
-	// buffer writes until we see a newline.
-	var hlen int
-	switch logger {
-	case logd:
-		hlen = writeLogdHeader()
-	case legacy:
-		hlen = len(writeHeader)
-	}
-
-	dst := writeBuf[hlen:]
-	for _, v := range b {
-		if v == 0 { // android logging won't print a zero byte
-			v = '0'
-		}
-		dst[writePos] = v
-		writePos++
-		if v == '\n' || writePos == len(dst)-1 {
-			dst[writePos] = 0
-			write(writeFD, unsafe.Pointer(&writeBuf[0]), int32(hlen+writePos))
-			memclrBytes(dst)
-			writePos = 0
-		}
-	}
-}
-
-func initLegacy() {
-	// In legacy mode, logs are written to /dev/log/main
-	writeFD = uintptr(open(&writePath[0], 0x1 /* O_WRONLY */, 0))
-	if writeFD == 0 {
-		// It is hard to do anything here. Write to stderr just
-		// in case user has root on device and has run
-		//	adb shell setprop log.redirect-stdio true
-		msg := []byte("runtime: cannot open /dev/log/main\x00")
-		write(2, unsafe.Pointer(&msg[0]), int32(len(msg)))
-		exit(2)
-	}
-
-	// Prepopulate the invariant header part.
-	copy(writeBuf[:len(writeHeader)], writeHeader)
-}
-
-// used in initLogdWrite but defined here to avoid heap allocation.
-var logdAddr sockaddr_un
-
-func initLogd() {
-	// In logd mode, logs are sent to the logd via a unix domain socket.
-	logdAddr.family = _AF_UNIX
-	copy(logdAddr.path[:], writeLogd)
-
-	// We are not using non-blocking I/O because writes taking this path
-	// are most likely triggered by panic, we cannot think of the advantage of
-	// non-blocking I/O for panic but see disadvantage (dropping panic message),
-	// and blocking I/O simplifies the code a lot.
-	fd := socket(_AF_UNIX, _SOCK_DGRAM|_O_CLOEXEC, 0)
-	if fd < 0 {
-		msg := []byte("runtime: cannot create a socket for logging\x00")
-		write(2, unsafe.Pointer(&msg[0]), int32(len(msg)))
-		exit(2)
-	}
-
-	errno := connect(uintptr(fd), unsafe.Pointer(&logdAddr), int32(unsafe.Sizeof(logdAddr)))
-	if errno < 0 {
-		msg := []byte("runtime: cannot connect to /dev/socket/logdw\x00")
-		write(2, unsafe.Pointer(&msg[0]), int32(len(msg)))
-		// TODO(hakim): or should we just close fd and hope for better luck next time?
-		exit(2)
-	}
-	writeFD = uintptr(fd)
-
-	// Prepopulate invariant part of the header.
-	// The first 11 bytes will be populated later in writeLogdHeader.
-	copy(writeBuf[11:11+len(writeHeader)], writeHeader)
-}
-
-// writeLogdHeader populates the header and returns the length of the payload.
-func writeLogdHeader() int {
-	hdr := writeBuf[:11]
-
-	// The first 11 bytes of the header corresponds to android_log_header_t
-	// as defined in system/core/include/private/android_logger.h
-	//   hdr[0] log type id (unsigned char), defined in <log/log.h>
-	//   hdr[1:2] tid (uint16_t)
-	//   hdr[3:11] log_time defined in <log/log_read.h>
-	//      hdr[3:7] sec unsigned uint32, little endian.
-	//      hdr[7:11] nsec unsigned uint32, little endian.
-	hdr[0] = 0 // LOG_ID_MAIN
-	sec, nsec := time_now()
-	packUint32(hdr[3:7], uint32(sec))
-	packUint32(hdr[7:11], uint32(nsec))
-
-	// TODO(hakim):  hdr[1:2] = gettid?
-
-	return 11 + len(writeHeader)
-}
-
-func packUint32(b []byte, v uint32) {
-	// little-endian.
-	b[0] = byte(v)
-	b[1] = byte(v >> 8)
-	b[2] = byte(v >> 16)
-	b[3] = byte(v >> 24)
-}
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index c5b4a8c..d1f5088 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -4,7 +4,81 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"runtime/internal/sys"
+	"unsafe"
+)
+
+var buildVersion = sys.TheVersion
+
+// Goroutine scheduler
+// The scheduler's job is to distribute ready-to-run goroutines over worker threads.
+//
+// The main concepts are:
+// G - goroutine.
+// M - worker thread, or machine.
+// P - processor, a resource that is required to execute Go code.
+//     M must have an associated P to execute Go code, however it can be
+//     blocked or in a syscall w/o an associated P.
+//
+// Design doc at https://golang.org/s/go11sched.
+
+// Worker thread parking/unparking.
+// We need to balance between keeping enough running worker threads to utilize
+// available hardware parallelism and parking excessive running worker threads
+// to conserve CPU resources and power. This is not simple for two reasons:
+// (1) scheduler state is intentionally distributed (in particular, per-P work
+// queues), so it is not possible to compute global predicates on fast paths;
+// (2) for optimal thread management we would need to know the future (don't park
+// a worker thread when a new goroutine will be readied in near future).
+//
+// Three rejected approaches that would work badly:
+// 1. Centralize all scheduler state (would inhibit scalability).
+// 2. Direct goroutine handoff. That is, when we ready a new goroutine and there
+//    is a spare P, unpark a thread and handoff it the thread and the goroutine.
+//    This would lead to thread state thrashing, as the thread that readied the
+//    goroutine can be out of work the very next moment, we will need to park it.
+//    Also, it would destroy locality of computation as we want to preserve
+//    dependent goroutines on the same thread; and introduce additional latency.
+// 3. Unpark an additional thread whenever we ready a goroutine and there is an
+//    idle P, but don't do handoff. This would lead to excessive thread parking/
+//    unparking as the additional threads will instantly park without discovering
+//    any work to do.
+//
+// The current approach:
+// We unpark an additional thread when we ready a goroutine if (1) there is an
+// idle P and there are no "spinning" worker threads. A worker thread is considered
+// spinning if it is out of local work and did not find work in global run queue/
+// netpoller; the spinning state is denoted in m.spinning and in sched.nmspinning.
+// Threads unparked this way are also considered spinning; we don't do goroutine
+// handoff so such threads are out of work initially. Spinning threads do some
+// spinning looking for work in per-P run queues before parking. If a spinning
+// thread finds work it takes itself out of the spinning state and proceeds to
+// execution. If it does not find work it takes itself out of the spinning state
+// and then parks.
+// If there is at least one spinning thread (sched.nmspinning>1), we don't unpark
+// new threads when readying goroutines. To compensate for that, if the last spinning
+// thread finds work and stops spinning, it must unpark a new spinning thread.
+// This approach smooths out unjustified spikes of thread unparking,
+// but at the same time guarantees eventual maximal CPU parallelism utilization.
+//
+// The main implementation complication is that we need to be very careful during
+// spinning->non-spinning thread transition. This transition can race with submission
+// of a new goroutine, and either one part or another needs to unpark another worker
+// thread. If they both fail to do that, we can end up with semi-persistent CPU
+// underutilization. The general pattern for goroutine readying is: submit a goroutine
+// to local work queue, #StoreLoad-style memory barrier, check sched.nmspinning.
+// The general pattern for spinning->non-spinning transition is: decrement nmspinning,
+// #StoreLoad-style memory barrier, check all per-P work queues for new work.
+// Note that all this complexity does not apply to global run queue as we are not
+// sloppy about thread unparking when submitting to global queue. Also see comments
+// for nmspinning manipulation.
+
+var (
+	m0 m
+	g0 g
+)
 
 //go:linkname runtime_init runtime.init
 func runtime_init()
@@ -24,6 +98,9 @@ func main_main()
 // runtimeInitTime is the nanotime() at which the runtime started.
 var runtimeInitTime int64
 
+// Value to use for signal mask for newly created M's.
+var initSigmask sigset
+
 // The main goroutine.
 func main() {
 	g := getg()
@@ -35,7 +112,7 @@ func main() {
 	// Max stack size is 1 GB on 64-bit, 250 MB on 32-bit.
 	// Using decimal instead of binary GB and MB because
 	// they look nicer in the stack overflow failure message.
-	if ptrSize == 8 {
+	if sys.PtrSize == 8 {
 		maxstacksize = 1000000000
 	} else {
 		maxstacksize = 250000000
@@ -148,13 +225,13 @@ func forcegchelper() {
 		if forcegc.idle != 0 {
 			throw("forcegc: phase error")
 		}
-		atomicstore(&forcegc.idle, 1)
+		atomic.Store(&forcegc.idle, 1)
 		goparkunlock(&forcegc.lock, "force gc (idle)", traceEvGoBlock, 1)
 		// this goroutine is explicitly resumed by sysmon
 		if debug.gctrace > 0 {
 			println("GC forced")
 		}
-		startGC(gcBackgroundMode, true)
+		gcStart(gcBackgroundMode, true)
 	}
 }
 
@@ -286,7 +363,7 @@ func releaseSudog(s *sudog) {
 // It assumes that f is a func value. Otherwise the behavior is undefined.
 //go:nosplit
 func funcPC(f interface{}) uintptr {
-	return **(**uintptr)(add(unsafe.Pointer(&f), ptrSize))
+	return **(**uintptr)(add(unsafe.Pointer(&f), sys.PtrSize))
 }
 
 // called from assembly
@@ -319,7 +396,3808 @@ func allgadd(gp *g) {
 
 	lock(&allglock)
 	allgs = append(allgs, gp)
-	allg = &allgs[0]
 	allglen = uintptr(len(allgs))
 	unlock(&allglock)
 }
+
+const (
+	// Number of goroutine ids to grab from sched.goidgen to local per-P cache at once.
+	// 16 seems to provide enough amortization, but other than that it's mostly arbitrary number.
+	_GoidCacheBatch = 16
+)
+
+// The bootstrap sequence is:
+//
+//	call osinit
+//	call schedinit
+//	make & queue new G
+//	call runtime·mstart
+//
+// The new G calls runtime·main.
+func schedinit() {
+	// raceinit must be the first call to race detector.
+	// In particular, it must be done before mallocinit below calls racemapshadow.
+	_g_ := getg()
+	if raceenabled {
+		_g_.racectx = raceinit()
+	}
+
+	sched.maxmcount = 10000
+
+	// Cache the framepointer experiment.  This affects stack unwinding.
+	framepointer_enabled = haveexperiment("framepointer")
+
+	tracebackinit()
+	moduledataverify()
+	stackinit()
+	mallocinit()
+	mcommoninit(_g_.m)
+
+	msigsave(_g_.m)
+	initSigmask = _g_.m.sigmask
+
+	goargs()
+	goenvs()
+	parsedebugvars()
+	gcinit()
+
+	sched.lastpoll = uint64(nanotime())
+	procs := int(ncpu)
+	if n := atoi(gogetenv("GOMAXPROCS")); n > 0 {
+		if n > _MaxGomaxprocs {
+			n = _MaxGomaxprocs
+		}
+		procs = n
+	}
+	if procresize(int32(procs)) != nil {
+		throw("unknown runnable goroutine during bootstrap")
+	}
+
+	if buildVersion == "" {
+		// Condition should never trigger.  This code just serves
+		// to ensure runtime·buildVersion is kept in the resulting binary.
+		buildVersion = "unknown"
+	}
+}
+
+func dumpgstatus(gp *g) {
+	_g_ := getg()
+	print("runtime: gp: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", readgstatus(gp), "\n")
+	print("runtime:  g:  g=", _g_, ", goid=", _g_.goid, ",  g->atomicstatus=", readgstatus(_g_), "\n")
+}
+
+func checkmcount() {
+	// sched lock is held
+	if sched.mcount > sched.maxmcount {
+		print("runtime: program exceeds ", sched.maxmcount, "-thread limit\n")
+		throw("thread exhaustion")
+	}
+}
+
+func mcommoninit(mp *m) {
+	_g_ := getg()
+
+	// g0 stack won't make sense for user (and is not necessary unwindable).
+	if _g_ != _g_.m.g0 {
+		callers(1, mp.createstack[:])
+	}
+
+	mp.fastrand = 0x49f6428a + uint32(mp.id) + uint32(cputicks())
+	if mp.fastrand == 0 {
+		mp.fastrand = 0x49f6428a
+	}
+
+	lock(&sched.lock)
+	mp.id = sched.mcount
+	sched.mcount++
+	checkmcount()
+	mpreinit(mp)
+	if mp.gsignal != nil {
+		mp.gsignal.stackguard1 = mp.gsignal.stack.lo + _StackGuard
+	}
+
+	// Add to allm so garbage collector doesn't free g->m
+	// when it is just in a register or thread-local storage.
+	mp.alllink = allm
+
+	// NumCgoCall() iterates over allm w/o schedlock,
+	// so we need to publish it safely.
+	atomicstorep(unsafe.Pointer(&allm), unsafe.Pointer(mp))
+	unlock(&sched.lock)
+}
+
+// Mark gp ready to run.
+func ready(gp *g, traceskip int) {
+	if trace.enabled {
+		traceGoUnpark(gp, traceskip)
+	}
+
+	status := readgstatus(gp)
+
+	// Mark runnable.
+	_g_ := getg()
+	_g_.m.locks++ // disable preemption because it can be holding p in a local var
+	if status&^_Gscan != _Gwaiting {
+		dumpgstatus(gp)
+		throw("bad g->status in ready")
+	}
+
+	// status is Gwaiting or Gscanwaiting, make Grunnable and put on runq
+	casgstatus(gp, _Gwaiting, _Grunnable)
+	runqput(_g_.m.p.ptr(), gp, true)
+	if atomic.Load(&sched.npidle) != 0 && atomic.Load(&sched.nmspinning) == 0 { // TODO: fast atomic
+		wakep()
+	}
+	_g_.m.locks--
+	if _g_.m.locks == 0 && _g_.preempt { // restore the preemption request in Case we've cleared it in newstack
+		_g_.stackguard0 = stackPreempt
+	}
+}
+
+func gcprocs() int32 {
+	// Figure out how many CPUs to use during GC.
+	// Limited by gomaxprocs, number of actual CPUs, and MaxGcproc.
+	lock(&sched.lock)
+	n := gomaxprocs
+	if n > ncpu {
+		n = ncpu
+	}
+	if n > _MaxGcproc {
+		n = _MaxGcproc
+	}
+	if n > sched.nmidle+1 { // one M is currently running
+		n = sched.nmidle + 1
+	}
+	unlock(&sched.lock)
+	return n
+}
+
+func needaddgcproc() bool {
+	lock(&sched.lock)
+	n := gomaxprocs
+	if n > ncpu {
+		n = ncpu
+	}
+	if n > _MaxGcproc {
+		n = _MaxGcproc
+	}
+	n -= sched.nmidle + 1 // one M is currently running
+	unlock(&sched.lock)
+	return n > 0
+}
+
+func helpgc(nproc int32) {
+	_g_ := getg()
+	lock(&sched.lock)
+	pos := 0
+	for n := int32(1); n < nproc; n++ { // one M is currently running
+		if allp[pos].mcache == _g_.m.mcache {
+			pos++
+		}
+		mp := mget()
+		if mp == nil {
+			throw("gcprocs inconsistency")
+		}
+		mp.helpgc = n
+		mp.p.set(allp[pos])
+		mp.mcache = allp[pos].mcache
+		pos++
+		notewakeup(&mp.park)
+	}
+	unlock(&sched.lock)
+}
+
+// freezeStopWait is a large value that freezetheworld sets
+// sched.stopwait to in order to request that all Gs permanently stop.
+const freezeStopWait = 0x7fffffff
+
+// Similar to stopTheWorld but best-effort and can be called several times.
+// There is no reverse operation, used during crashing.
+// This function must not lock any mutexes.
+func freezetheworld() {
+	// stopwait and preemption requests can be lost
+	// due to races with concurrently executing threads,
+	// so try several times
+	for i := 0; i < 5; i++ {
+		// this should tell the scheduler to not start any new goroutines
+		sched.stopwait = freezeStopWait
+		atomic.Store(&sched.gcwaiting, 1)
+		// this should stop running goroutines
+		if !preemptall() {
+			break // no running goroutines
+		}
+		usleep(1000)
+	}
+	// to be sure
+	usleep(1000)
+	preemptall()
+	usleep(1000)
+}
+
+func isscanstatus(status uint32) bool {
+	if status == _Gscan {
+		throw("isscanstatus: Bad status Gscan")
+	}
+	return status&_Gscan == _Gscan
+}
+
+// All reads and writes of g's status go through readgstatus, casgstatus
+// castogscanstatus, casfrom_Gscanstatus.
+//go:nosplit
+func readgstatus(gp *g) uint32 {
+	return atomic.Load(&gp.atomicstatus)
+}
+
+// Ownership of gscanvalid:
+//
+// If gp is running (meaning status == _Grunning or _Grunning|_Gscan),
+// then gp owns gp.gscanvalid, and other goroutines must not modify it.
+//
+// Otherwise, a second goroutine can lock the scan state by setting _Gscan
+// in the status bit and then modify gscanvalid, and then unlock the scan state.
+//
+// Note that the first condition implies an exception to the second:
+// if a second goroutine changes gp's status to _Grunning|_Gscan,
+// that second goroutine still does not have the right to modify gscanvalid.
+
+// The Gscanstatuses are acting like locks and this releases them.
+// If it proves to be a performance hit we should be able to make these
+// simple atomic stores but for now we are going to throw if
+// we see an inconsistent state.
+func casfrom_Gscanstatus(gp *g, oldval, newval uint32) {
+	success := false
+
+	// Check that transition is valid.
+	switch oldval {
+	default:
+		print("runtime: casfrom_Gscanstatus bad oldval gp=", gp, ", oldval=", hex(oldval), ", newval=", hex(newval), "\n")
+		dumpgstatus(gp)
+		throw("casfrom_Gscanstatus:top gp->status is not in scan state")
+	case _Gscanrunnable,
+		_Gscanwaiting,
+		_Gscanrunning,
+		_Gscansyscall:
+		if newval == oldval&^_Gscan {
+			success = atomic.Cas(&gp.atomicstatus, oldval, newval)
+		}
+	case _Gscanenqueue:
+		if newval == _Gwaiting {
+			success = atomic.Cas(&gp.atomicstatus, oldval, newval)
+		}
+	}
+	if !success {
+		print("runtime: casfrom_Gscanstatus failed gp=", gp, ", oldval=", hex(oldval), ", newval=", hex(newval), "\n")
+		dumpgstatus(gp)
+		throw("casfrom_Gscanstatus: gp->status is not in scan state")
+	}
+	if newval == _Grunning {
+		gp.gcscanvalid = false
+	}
+}
+
+// This will return false if the gp is not in the expected status and the cas fails.
+// This acts like a lock acquire while the casfromgstatus acts like a lock release.
+func castogscanstatus(gp *g, oldval, newval uint32) bool {
+	switch oldval {
+	case _Grunnable,
+		_Gwaiting,
+		_Gsyscall:
+		if newval == oldval|_Gscan {
+			return atomic.Cas(&gp.atomicstatus, oldval, newval)
+		}
+	case _Grunning:
+		if newval == _Gscanrunning || newval == _Gscanenqueue {
+			return atomic.Cas(&gp.atomicstatus, oldval, newval)
+		}
+	}
+	print("runtime: castogscanstatus oldval=", hex(oldval), " newval=", hex(newval), "\n")
+	throw("castogscanstatus")
+	panic("not reached")
+}
+
+// If asked to move to or from a Gscanstatus this will throw. Use the castogscanstatus
+// and casfrom_Gscanstatus instead.
+// casgstatus will loop if the g->atomicstatus is in a Gscan status until the routine that
+// put it in the Gscan state is finished.
+//go:nosplit
+func casgstatus(gp *g, oldval, newval uint32) {
+	if (oldval&_Gscan != 0) || (newval&_Gscan != 0) || oldval == newval {
+		systemstack(func() {
+			print("runtime: casgstatus: oldval=", hex(oldval), " newval=", hex(newval), "\n")
+			throw("casgstatus: bad incoming values")
+		})
+	}
+
+	if oldval == _Grunning && gp.gcscanvalid {
+		// If oldvall == _Grunning, then the actual status must be
+		// _Grunning or _Grunning|_Gscan; either way,
+		// we own gp.gcscanvalid, so it's safe to read.
+		// gp.gcscanvalid must not be true when we are running.
+		print("runtime: casgstatus ", hex(oldval), "->", hex(newval), " gp.status=", hex(gp.atomicstatus), " gp.gcscanvalid=true\n")
+		throw("casgstatus")
+	}
+
+	// loop if gp->atomicstatus is in a scan state giving
+	// GC time to finish and change the state to oldval.
+	for !atomic.Cas(&gp.atomicstatus, oldval, newval) {
+		if oldval == _Gwaiting && gp.atomicstatus == _Grunnable {
+			systemstack(func() {
+				throw("casgstatus: waiting for Gwaiting but is Grunnable")
+			})
+		}
+		// Help GC if needed.
+		// if gp.preemptscan && !gp.gcworkdone && (oldval == _Grunning || oldval == _Gsyscall) {
+		// 	gp.preemptscan = false
+		// 	systemstack(func() {
+		// 		gcphasework(gp)
+		// 	})
+		// }
+	}
+	if newval == _Grunning {
+		gp.gcscanvalid = false
+	}
+}
+
+// casgstatus(gp, oldstatus, Gcopystack), assuming oldstatus is Gwaiting or Grunnable.
+// Returns old status. Cannot call casgstatus directly, because we are racing with an
+// async wakeup that might come in from netpoll. If we see Gwaiting from the readgstatus,
+// it might have become Grunnable by the time we get to the cas. If we called casgstatus,
+// it would loop waiting for the status to go back to Gwaiting, which it never will.
+//go:nosplit
+func casgcopystack(gp *g) uint32 {
+	for {
+		oldstatus := readgstatus(gp) &^ _Gscan
+		if oldstatus != _Gwaiting && oldstatus != _Grunnable {
+			throw("copystack: bad status, not Gwaiting or Grunnable")
+		}
+		if atomic.Cas(&gp.atomicstatus, oldstatus, _Gcopystack) {
+			return oldstatus
+		}
+	}
+}
+
+// scang blocks until gp's stack has been scanned.
+// It might be scanned by scang or it might be scanned by the goroutine itself.
+// Either way, the stack scan has completed when scang returns.
+func scang(gp *g) {
+	// Invariant; we (the caller, markroot for a specific goroutine) own gp.gcscandone.
+	// Nothing is racing with us now, but gcscandone might be set to true left over
+	// from an earlier round of stack scanning (we scan twice per GC).
+	// We use gcscandone to record whether the scan has been done during this round.
+	// It is important that the scan happens exactly once: if called twice,
+	// the installation of stack barriers will detect the double scan and die.
+
+	gp.gcscandone = false
+
+	// Endeavor to get gcscandone set to true,
+	// either by doing the stack scan ourselves or by coercing gp to scan itself.
+	// gp.gcscandone can transition from false to true when we're not looking
+	// (if we asked for preemption), so any time we lock the status using
+	// castogscanstatus we have to double-check that the scan is still not done.
+	for !gp.gcscandone {
+		switch s := readgstatus(gp); s {
+		default:
+			dumpgstatus(gp)
+			throw("stopg: invalid status")
+
+		case _Gdead:
+			// No stack.
+			gp.gcscandone = true
+
+		case _Gcopystack:
+		// Stack being switched. Go around again.
+
+		case _Grunnable, _Gsyscall, _Gwaiting:
+			// Claim goroutine by setting scan bit.
+			// Racing with execution or readying of gp.
+			// The scan bit keeps them from running
+			// the goroutine until we're done.
+			if castogscanstatus(gp, s, s|_Gscan) {
+				if !gp.gcscandone {
+					scanstack(gp)
+					gp.gcscandone = true
+				}
+				restartg(gp)
+			}
+
+		case _Gscanwaiting:
+		// newstack is doing a scan for us right now. Wait.
+
+		case _Grunning:
+			// Goroutine running. Try to preempt execution so it can scan itself.
+			// The preemption handler (in newstack) does the actual scan.
+
+			// Optimization: if there is already a pending preemption request
+			// (from the previous loop iteration), don't bother with the atomics.
+			if gp.preemptscan && gp.preempt && gp.stackguard0 == stackPreempt {
+				break
+			}
+
+			// Ask for preemption and self scan.
+			if castogscanstatus(gp, _Grunning, _Gscanrunning) {
+				if !gp.gcscandone {
+					gp.preemptscan = true
+					gp.preempt = true
+					gp.stackguard0 = stackPreempt
+				}
+				casfrom_Gscanstatus(gp, _Gscanrunning, _Grunning)
+			}
+		}
+	}
+
+	gp.preemptscan = false // cancel scan request if no longer needed
+}
+
+// The GC requests that this routine be moved from a scanmumble state to a mumble state.
+func restartg(gp *g) {
+	s := readgstatus(gp)
+	switch s {
+	default:
+		dumpgstatus(gp)
+		throw("restartg: unexpected status")
+
+	case _Gdead:
+	// ok
+
+	case _Gscanrunnable,
+		_Gscanwaiting,
+		_Gscansyscall:
+		casfrom_Gscanstatus(gp, s, s&^_Gscan)
+
+	// Scan is now completed.
+	// Goroutine now needs to be made runnable.
+	// We put it on the global run queue; ready blocks on the global scheduler lock.
+	case _Gscanenqueue:
+		casfrom_Gscanstatus(gp, _Gscanenqueue, _Gwaiting)
+		if gp != getg().m.curg {
+			throw("processing Gscanenqueue on wrong m")
+		}
+		dropg()
+		ready(gp, 0)
+	}
+}
+
+// stopTheWorld stops all P's from executing goroutines, interrupting
+// all goroutines at GC safe points and records reason as the reason
+// for the stop. On return, only the current goroutine's P is running.
+// stopTheWorld must not be called from a system stack and the caller
+// must not hold worldsema. The caller must call startTheWorld when
+// other P's should resume execution.
+//
+// stopTheWorld is safe for multiple goroutines to call at the
+// same time. Each will execute its own stop, and the stops will
+// be serialized.
+//
+// This is also used by routines that do stack dumps. If the system is
+// in panic or being exited, this may not reliably stop all
+// goroutines.
+func stopTheWorld(reason string) {
+	semacquire(&worldsema, false)
+	getg().m.preemptoff = reason
+	systemstack(stopTheWorldWithSema)
+}
+
+// startTheWorld undoes the effects of stopTheWorld.
+func startTheWorld() {
+	systemstack(startTheWorldWithSema)
+	// worldsema must be held over startTheWorldWithSema to ensure
+	// gomaxprocs cannot change while worldsema is held.
+	semrelease(&worldsema)
+	getg().m.preemptoff = ""
+}
+
+// Holding worldsema grants an M the right to try to stop the world
+// and prevents gomaxprocs from changing concurrently.
+var worldsema uint32 = 1
+
+// stopTheWorldWithSema is the core implementation of stopTheWorld.
+// The caller is responsible for acquiring worldsema and disabling
+// preemption first and then should stopTheWorldWithSema on the system
+// stack:
+//
+//	semacquire(&worldsema, false)
+//	m.preemptoff = "reason"
+//	systemstack(stopTheWorldWithSema)
+//
+// When finished, the caller must either call startTheWorld or undo
+// these three operations separately:
+//
+//	m.preemptoff = ""
+//	systemstack(startTheWorldWithSema)
+//	semrelease(&worldsema)
+//
+// It is allowed to acquire worldsema once and then execute multiple
+// startTheWorldWithSema/stopTheWorldWithSema pairs.
+// Other P's are able to execute between successive calls to
+// startTheWorldWithSema and stopTheWorldWithSema.
+// Holding worldsema causes any other goroutines invoking
+// stopTheWorld to block.
+func stopTheWorldWithSema() {
+	_g_ := getg()
+
+	// If we hold a lock, then we won't be able to stop another M
+	// that is blocked trying to acquire the lock.
+	if _g_.m.locks > 0 {
+		throw("stopTheWorld: holding locks")
+	}
+
+	lock(&sched.lock)
+	sched.stopwait = gomaxprocs
+	atomic.Store(&sched.gcwaiting, 1)
+	preemptall()
+	// stop current P
+	_g_.m.p.ptr().status = _Pgcstop // Pgcstop is only diagnostic.
+	sched.stopwait--
+	// try to retake all P's in Psyscall status
+	for i := 0; i < int(gomaxprocs); i++ {
+		p := allp[i]
+		s := p.status
+		if s == _Psyscall && atomic.Cas(&p.status, s, _Pgcstop) {
+			if trace.enabled {
+				traceGoSysBlock(p)
+				traceProcStop(p)
+			}
+			p.syscalltick++
+			sched.stopwait--
+		}
+	}
+	// stop idle P's
+	for {
+		p := pidleget()
+		if p == nil {
+			break
+		}
+		p.status = _Pgcstop
+		sched.stopwait--
+	}
+	wait := sched.stopwait > 0
+	unlock(&sched.lock)
+
+	// wait for remaining P's to stop voluntarily
+	if wait {
+		for {
+			// wait for 100us, then try to re-preempt in case of any races
+			if notetsleep(&sched.stopnote, 100*1000) {
+				noteclear(&sched.stopnote)
+				break
+			}
+			preemptall()
+		}
+	}
+	if sched.stopwait != 0 {
+		throw("stopTheWorld: not stopped")
+	}
+	for i := 0; i < int(gomaxprocs); i++ {
+		p := allp[i]
+		if p.status != _Pgcstop {
+			throw("stopTheWorld: not stopped")
+		}
+	}
+}
+
+func mhelpgc() {
+	_g_ := getg()
+	_g_.m.helpgc = -1
+}
+
+func startTheWorldWithSema() {
+	_g_ := getg()
+
+	_g_.m.locks++        // disable preemption because it can be holding p in a local var
+	gp := netpoll(false) // non-blocking
+	injectglist(gp)
+	add := needaddgcproc()
+	lock(&sched.lock)
+
+	procs := gomaxprocs
+	if newprocs != 0 {
+		procs = newprocs
+		newprocs = 0
+	}
+	p1 := procresize(procs)
+	sched.gcwaiting = 0
+	if sched.sysmonwait != 0 {
+		sched.sysmonwait = 0
+		notewakeup(&sched.sysmonnote)
+	}
+	unlock(&sched.lock)
+
+	for p1 != nil {
+		p := p1
+		p1 = p1.link.ptr()
+		if p.m != 0 {
+			mp := p.m.ptr()
+			p.m = 0
+			if mp.nextp != 0 {
+				throw("startTheWorld: inconsistent mp->nextp")
+			}
+			mp.nextp.set(p)
+			notewakeup(&mp.park)
+		} else {
+			// Start M to run P.  Do not start another M below.
+			newm(nil, p)
+			add = false
+		}
+	}
+
+	// Wakeup an additional proc in case we have excessive runnable goroutines
+	// in local queues or in the global queue. If we don't, the proc will park itself.
+	// If we have lots of excessive work, resetspinning will unpark additional procs as necessary.
+	if atomic.Load(&sched.npidle) != 0 && atomic.Load(&sched.nmspinning) == 0 {
+		wakep()
+	}
+
+	if add {
+		// If GC could have used another helper proc, start one now,
+		// in the hope that it will be available next time.
+		// It would have been even better to start it before the collection,
+		// but doing so requires allocating memory, so it's tricky to
+		// coordinate.  This lazy approach works out in practice:
+		// we don't mind if the first couple gc rounds don't have quite
+		// the maximum number of procs.
+		newm(mhelpgc, nil)
+	}
+	_g_.m.locks--
+	if _g_.m.locks == 0 && _g_.preempt { // restore the preemption request in case we've cleared it in newstack
+		_g_.stackguard0 = stackPreempt
+	}
+}
+
+// Called to start an M.
+//go:nosplit
+func mstart() {
+	_g_ := getg()
+
+	if _g_.stack.lo == 0 {
+		// Initialize stack bounds from system stack.
+		// Cgo may have left stack size in stack.hi.
+		size := _g_.stack.hi
+		if size == 0 {
+			size = 8192 * sys.StackGuardMultiplier
+		}
+		_g_.stack.hi = uintptr(noescape(unsafe.Pointer(&size)))
+		_g_.stack.lo = _g_.stack.hi - size + 1024
+	}
+	// Initialize stack guards so that we can start calling
+	// both Go and C functions with stack growth prologues.
+	_g_.stackguard0 = _g_.stack.lo + _StackGuard
+	_g_.stackguard1 = _g_.stackguard0
+	mstart1()
+}
+
+func mstart1() {
+	_g_ := getg()
+
+	if _g_ != _g_.m.g0 {
+		throw("bad runtime·mstart")
+	}
+
+	// Record top of stack for use by mcall.
+	// Once we call schedule we're never coming back,
+	// so other calls can reuse this stack space.
+	gosave(&_g_.m.g0.sched)
+	_g_.m.g0.sched.pc = ^uintptr(0) // make sure it is never used
+	asminit()
+	minit()
+
+	// Install signal handlers; after minit so that minit can
+	// prepare the thread to be able to handle the signals.
+	if _g_.m == &m0 {
+		// Create an extra M for callbacks on threads not created by Go.
+		if iscgo && !cgoHasExtraM {
+			cgoHasExtraM = true
+			newextram()
+		}
+		initsig(false)
+	}
+
+	if fn := _g_.m.mstartfn; fn != nil {
+		fn()
+	}
+
+	if _g_.m.helpgc != 0 {
+		_g_.m.helpgc = 0
+		stopm()
+	} else if _g_.m != &m0 {
+		acquirep(_g_.m.nextp.ptr())
+		_g_.m.nextp = 0
+	}
+	schedule()
+}
+
+// forEachP calls fn(p) for every P p when p reaches a GC safe point.
+// If a P is currently executing code, this will bring the P to a GC
+// safe point and execute fn on that P. If the P is not executing code
+// (it is idle or in a syscall), this will call fn(p) directly while
+// preventing the P from exiting its state. This does not ensure that
+// fn will run on every CPU executing Go code, but it acts as a global
+// memory barrier. GC uses this as a "ragged barrier."
+//
+// The caller must hold worldsema.
+//
+//go:systemstack
+func forEachP(fn func(*p)) {
+	mp := acquirem()
+	_p_ := getg().m.p.ptr()
+
+	lock(&sched.lock)
+	if sched.safePointWait != 0 {
+		throw("forEachP: sched.safePointWait != 0")
+	}
+	sched.safePointWait = gomaxprocs - 1
+	sched.safePointFn = fn
+
+	// Ask all Ps to run the safe point function.
+	for _, p := range allp[:gomaxprocs] {
+		if p != _p_ {
+			atomic.Store(&p.runSafePointFn, 1)
+		}
+	}
+	preemptall()
+
+	// Any P entering _Pidle or _Psyscall from now on will observe
+	// p.runSafePointFn == 1 and will call runSafePointFn when
+	// changing its status to _Pidle/_Psyscall.
+
+	// Run safe point function for all idle Ps. sched.pidle will
+	// not change because we hold sched.lock.
+	for p := sched.pidle.ptr(); p != nil; p = p.link.ptr() {
+		if atomic.Cas(&p.runSafePointFn, 1, 0) {
+			fn(p)
+			sched.safePointWait--
+		}
+	}
+
+	wait := sched.safePointWait > 0
+	unlock(&sched.lock)
+
+	// Run fn for the current P.
+	fn(_p_)
+
+	// Force Ps currently in _Psyscall into _Pidle and hand them
+	// off to induce safe point function execution.
+	for i := 0; i < int(gomaxprocs); i++ {
+		p := allp[i]
+		s := p.status
+		if s == _Psyscall && p.runSafePointFn == 1 && atomic.Cas(&p.status, s, _Pidle) {
+			if trace.enabled {
+				traceGoSysBlock(p)
+				traceProcStop(p)
+			}
+			p.syscalltick++
+			handoffp(p)
+		}
+	}
+
+	// Wait for remaining Ps to run fn.
+	if wait {
+		for {
+			// Wait for 100us, then try to re-preempt in
+			// case of any races.
+			//
+			// Requires system stack.
+			if notetsleep(&sched.safePointNote, 100*1000) {
+				noteclear(&sched.safePointNote)
+				break
+			}
+			preemptall()
+		}
+	}
+	if sched.safePointWait != 0 {
+		throw("forEachP: not done")
+	}
+	for i := 0; i < int(gomaxprocs); i++ {
+		p := allp[i]
+		if p.runSafePointFn != 0 {
+			throw("forEachP: P did not run fn")
+		}
+	}
+
+	lock(&sched.lock)
+	sched.safePointFn = nil
+	unlock(&sched.lock)
+	releasem(mp)
+}
+
+// runSafePointFn runs the safe point function, if any, for this P.
+// This should be called like
+//
+//     if getg().m.p.runSafePointFn != 0 {
+//         runSafePointFn()
+//     }
+//
+// runSafePointFn must be checked on any transition in to _Pidle or
+// _Psyscall to avoid a race where forEachP sees that the P is running
+// just before the P goes into _Pidle/_Psyscall and neither forEachP
+// nor the P run the safe-point function.
+func runSafePointFn() {
+	p := getg().m.p.ptr()
+	// Resolve the race between forEachP running the safe-point
+	// function on this P's behalf and this P running the
+	// safe-point function directly.
+	if !atomic.Cas(&p.runSafePointFn, 1, 0) {
+		return
+	}
+	sched.safePointFn(p)
+	lock(&sched.lock)
+	sched.safePointWait--
+	if sched.safePointWait == 0 {
+		notewakeup(&sched.safePointNote)
+	}
+	unlock(&sched.lock)
+}
+
+// When running with cgo, we call _cgo_thread_start
+// to start threads for us so that we can play nicely with
+// foreign code.
+var cgoThreadStart unsafe.Pointer
+
+type cgothreadstart struct {
+	g   guintptr
+	tls *uint64
+	fn  unsafe.Pointer
+}
+
+// Allocate a new m unassociated with any thread.
+// Can use p for allocation context if needed.
+// fn is recorded as the new m's m.mstartfn.
+//
+// This function it known to the compiler to inhibit the
+// go:nowritebarrierrec annotation because it uses P for allocation.
+func allocm(_p_ *p, fn func()) *m {
+	_g_ := getg()
+	_g_.m.locks++ // disable GC because it can be called from sysmon
+	if _g_.m.p == 0 {
+		acquirep(_p_) // temporarily borrow p for mallocs in this function
+	}
+	mp := new(m)
+	mp.mstartfn = fn
+	mcommoninit(mp)
+
+	// In case of cgo or Solaris, pthread_create will make us a stack.
+	// Windows and Plan 9 will layout sched stack on OS stack.
+	if iscgo || GOOS == "solaris" || GOOS == "windows" || GOOS == "plan9" {
+		mp.g0 = malg(-1)
+	} else {
+		mp.g0 = malg(8192 * sys.StackGuardMultiplier)
+	}
+	mp.g0.m = mp
+
+	if _p_ == _g_.m.p.ptr() {
+		releasep()
+	}
+	_g_.m.locks--
+	if _g_.m.locks == 0 && _g_.preempt { // restore the preemption request in case we've cleared it in newstack
+		_g_.stackguard0 = stackPreempt
+	}
+
+	return mp
+}
+
+// needm is called when a cgo callback happens on a
+// thread without an m (a thread not created by Go).
+// In this case, needm is expected to find an m to use
+// and return with m, g initialized correctly.
+// Since m and g are not set now (likely nil, but see below)
+// needm is limited in what routines it can call. In particular
+// it can only call nosplit functions (textflag 7) and cannot
+// do any scheduling that requires an m.
+//
+// In order to avoid needing heavy lifting here, we adopt
+// the following strategy: there is a stack of available m's
+// that can be stolen. Using compare-and-swap
+// to pop from the stack has ABA races, so we simulate
+// a lock by doing an exchange (via casp) to steal the stack
+// head and replace the top pointer with MLOCKED (1).
+// This serves as a simple spin lock that we can use even
+// without an m. The thread that locks the stack in this way
+// unlocks the stack by storing a valid stack head pointer.
+//
+// In order to make sure that there is always an m structure
+// available to be stolen, we maintain the invariant that there
+// is always one more than needed. At the beginning of the
+// program (if cgo is in use) the list is seeded with a single m.
+// If needm finds that it has taken the last m off the list, its job
+// is - once it has installed its own m so that it can do things like
+// allocate memory - to create a spare m and put it on the list.
+//
+// Each of these extra m's also has a g0 and a curg that are
+// pressed into service as the scheduling stack and current
+// goroutine for the duration of the cgo callback.
+//
+// When the callback is done with the m, it calls dropm to
+// put the m back on the list.
+//go:nosplit
+func needm(x byte) {
+	if iscgo && !cgoHasExtraM {
+		// Can happen if C/C++ code calls Go from a global ctor.
+		// Can not throw, because scheduler is not initialized yet.
+		write(2, unsafe.Pointer(&earlycgocallback[0]), int32(len(earlycgocallback)))
+		exit(1)
+	}
+
+	// Lock extra list, take head, unlock popped list.
+	// nilokay=false is safe here because of the invariant above,
+	// that the extra list always contains or will soon contain
+	// at least one m.
+	mp := lockextra(false)
+
+	// Set needextram when we've just emptied the list,
+	// so that the eventual call into cgocallbackg will
+	// allocate a new m for the extra list. We delay the
+	// allocation until then so that it can be done
+	// after exitsyscall makes sure it is okay to be
+	// running at all (that is, there's no garbage collection
+	// running right now).
+	mp.needextram = mp.schedlink == 0
+	unlockextra(mp.schedlink.ptr())
+
+	// Save and block signals before installing g.
+	// Once g is installed, any incoming signals will try to execute,
+	// but we won't have the sigaltstack settings and other data
+	// set up appropriately until the end of minit, which will
+	// unblock the signals. This is the same dance as when
+	// starting a new m to run Go code via newosproc.
+	msigsave(mp)
+	sigblock()
+
+	// Install g (= m->g0) and set the stack bounds
+	// to match the current stack. We don't actually know
+	// how big the stack is, like we don't know how big any
+	// scheduling stack is, but we assume there's at least 32 kB,
+	// which is more than enough for us.
+	setg(mp.g0)
+	_g_ := getg()
+	_g_.stack.hi = uintptr(noescape(unsafe.Pointer(&x))) + 1024
+	_g_.stack.lo = uintptr(noescape(unsafe.Pointer(&x))) - 32*1024
+	_g_.stackguard0 = _g_.stack.lo + _StackGuard
+
+	// Initialize this thread to use the m.
+	asminit()
+	minit()
+}
+
+var earlycgocallback = []byte("fatal error: cgo callback before cgo call\n")
+
+// newextram allocates an m and puts it on the extra list.
+// It is called with a working local m, so that it can do things
+// like call schedlock and allocate.
+func newextram() {
+	// Create extra goroutine locked to extra m.
+	// The goroutine is the context in which the cgo callback will run.
+	// The sched.pc will never be returned to, but setting it to
+	// goexit makes clear to the traceback routines where
+	// the goroutine stack ends.
+	mp := allocm(nil, nil)
+	gp := malg(4096)
+	gp.sched.pc = funcPC(goexit) + sys.PCQuantum
+	gp.sched.sp = gp.stack.hi
+	gp.sched.sp -= 4 * sys.RegSize // extra space in case of reads slightly beyond frame
+	gp.sched.lr = 0
+	gp.sched.g = guintptr(unsafe.Pointer(gp))
+	gp.syscallpc = gp.sched.pc
+	gp.syscallsp = gp.sched.sp
+	gp.stktopsp = gp.sched.sp
+	// malg returns status as Gidle, change to Gsyscall before adding to allg
+	// where GC will see it.
+	casgstatus(gp, _Gidle, _Gsyscall)
+	gp.m = mp
+	mp.curg = gp
+	mp.locked = _LockInternal
+	mp.lockedg = gp
+	gp.lockedm = mp
+	gp.goid = int64(atomic.Xadd64(&sched.goidgen, 1))
+	if raceenabled {
+		gp.racectx = racegostart(funcPC(newextram))
+	}
+	// put on allg for garbage collector
+	allgadd(gp)
+
+	// Add m to the extra list.
+	mnext := lockextra(true)
+	mp.schedlink.set(mnext)
+	unlockextra(mp)
+}
+
+// dropm is called when a cgo callback has called needm but is now
+// done with the callback and returning back into the non-Go thread.
+// It puts the current m back onto the extra list.
+//
+// The main expense here is the call to signalstack to release the
+// m's signal stack, and then the call to needm on the next callback
+// from this thread. It is tempting to try to save the m for next time,
+// which would eliminate both these costs, but there might not be
+// a next time: the current thread (which Go does not control) might exit.
+// If we saved the m for that thread, there would be an m leak each time
+// such a thread exited. Instead, we acquire and release an m on each
+// call. These should typically not be scheduling operations, just a few
+// atomics, so the cost should be small.
+//
+// TODO(rsc): An alternative would be to allocate a dummy pthread per-thread
+// variable using pthread_key_create. Unlike the pthread keys we already use
+// on OS X, this dummy key would never be read by Go code. It would exist
+// only so that we could register at thread-exit-time destructor.
+// That destructor would put the m back onto the extra list.
+// This is purely a performance optimization. The current version,
+// in which dropm happens on each cgo call, is still correct too.
+// We may have to keep the current version on systems with cgo
+// but without pthreads, like Windows.
+func dropm() {
+	// Clear m and g, and return m to the extra list.
+	// After the call to setg we can only call nosplit functions
+	// with no pointer manipulation.
+	mp := getg().m
+
+	// Block signals before unminit.
+	// Unminit unregisters the signal handling stack (but needs g on some systems).
+	// Setg(nil) clears g, which is the signal handler's cue not to run Go handlers.
+	// It's important not to try to handle a signal between those two steps.
+	sigmask := mp.sigmask
+	sigblock()
+	unminit()
+
+	mnext := lockextra(true)
+	mp.schedlink.set(mnext)
+
+	setg(nil)
+
+	// Commit the release of mp.
+	unlockextra(mp)
+
+	msigrestore(sigmask)
+}
+
+// A helper function for EnsureDropM.
+func getm() uintptr {
+	return uintptr(unsafe.Pointer(getg().m))
+}
+
+var extram uintptr
+
+// lockextra locks the extra list and returns the list head.
+// The caller must unlock the list by storing a new list head
+// to extram. If nilokay is true, then lockextra will
+// return a nil list head if that's what it finds. If nilokay is false,
+// lockextra will keep waiting until the list head is no longer nil.
+//go:nosplit
+func lockextra(nilokay bool) *m {
+	const locked = 1
+
+	for {
+		old := atomic.Loaduintptr(&extram)
+		if old == locked {
+			yield := osyield
+			yield()
+			continue
+		}
+		if old == 0 && !nilokay {
+			usleep(1)
+			continue
+		}
+		if atomic.Casuintptr(&extram, old, locked) {
+			return (*m)(unsafe.Pointer(old))
+		}
+		yield := osyield
+		yield()
+		continue
+	}
+}
+
+//go:nosplit
+func unlockextra(mp *m) {
+	atomic.Storeuintptr(&extram, uintptr(unsafe.Pointer(mp)))
+}
+
+// Create a new m.  It will start off with a call to fn, or else the scheduler.
+// fn needs to be static and not a heap allocated closure.
+// May run with m.p==nil, so write barriers are not allowed.
+//go:nowritebarrier
+func newm(fn func(), _p_ *p) {
+	mp := allocm(_p_, fn)
+	mp.nextp.set(_p_)
+	mp.sigmask = initSigmask
+	if iscgo {
+		var ts cgothreadstart
+		if _cgo_thread_start == nil {
+			throw("_cgo_thread_start missing")
+		}
+		ts.g.set(mp.g0)
+		ts.tls = (*uint64)(unsafe.Pointer(&mp.tls[0]))
+		ts.fn = unsafe.Pointer(funcPC(mstart))
+		if msanenabled {
+			msanwrite(unsafe.Pointer(&ts), unsafe.Sizeof(ts))
+		}
+		asmcgocall(_cgo_thread_start, unsafe.Pointer(&ts))
+		return
+	}
+	newosproc(mp, unsafe.Pointer(mp.g0.stack.hi))
+}
+
+// Stops execution of the current m until new work is available.
+// Returns with acquired P.
+func stopm() {
+	_g_ := getg()
+
+	if _g_.m.locks != 0 {
+		throw("stopm holding locks")
+	}
+	if _g_.m.p != 0 {
+		throw("stopm holding p")
+	}
+	if _g_.m.spinning {
+		throw("stopm spinning")
+	}
+
+retry:
+	lock(&sched.lock)
+	mput(_g_.m)
+	unlock(&sched.lock)
+	notesleep(&_g_.m.park)
+	noteclear(&_g_.m.park)
+	if _g_.m.helpgc != 0 {
+		gchelper()
+		_g_.m.helpgc = 0
+		_g_.m.mcache = nil
+		_g_.m.p = 0
+		goto retry
+	}
+	acquirep(_g_.m.nextp.ptr())
+	_g_.m.nextp = 0
+}
+
+func mspinning() {
+	// startm's caller incremented nmspinning. Set the new M's spinning.
+	getg().m.spinning = true
+}
+
+// Schedules some M to run the p (creates an M if necessary).
+// If p==nil, tries to get an idle P, if no idle P's does nothing.
+// May run with m.p==nil, so write barriers are not allowed.
+// If spinning is set, the caller has incremented nmspinning and startm will
+// either decrement nmspinning or set m.spinning in the newly started M.
+//go:nowritebarrier
+func startm(_p_ *p, spinning bool) {
+	lock(&sched.lock)
+	if _p_ == nil {
+		_p_ = pidleget()
+		if _p_ == nil {
+			unlock(&sched.lock)
+			if spinning {
+				// The caller incremented nmspinning, but there are no idle Ps,
+				// so it's okay to just undo the increment and give up.
+				if int32(atomic.Xadd(&sched.nmspinning, -1)) < 0 {
+					throw("startm: negative nmspinning")
+				}
+			}
+			return
+		}
+	}
+	mp := mget()
+	unlock(&sched.lock)
+	if mp == nil {
+		var fn func()
+		if spinning {
+			// The caller incremented nmspinning, so set m.spinning in the new M.
+			fn = mspinning
+		}
+		newm(fn, _p_)
+		return
+	}
+	if mp.spinning {
+		throw("startm: m is spinning")
+	}
+	if mp.nextp != 0 {
+		throw("startm: m has p")
+	}
+	if spinning && !runqempty(_p_) {
+		throw("startm: p has runnable gs")
+	}
+	// The caller incremented nmspinning, so set m.spinning in the new M.
+	mp.spinning = spinning
+	mp.nextp.set(_p_)
+	notewakeup(&mp.park)
+}
+
+// Hands off P from syscall or locked M.
+// Always runs without a P, so write barriers are not allowed.
+//go:nowritebarrier
+func handoffp(_p_ *p) {
+	// handoffp must start an M in any situation where
+	// findrunnable would return a G to run on _p_.
+
+	// if it has local work, start it straight away
+	if !runqempty(_p_) || sched.runqsize != 0 {
+		startm(_p_, false)
+		return
+	}
+	// if it has GC work, start it straight away
+	if gcBlackenEnabled != 0 && gcMarkWorkAvailable(_p_) {
+		startm(_p_, false)
+		return
+	}
+	// no local work, check that there are no spinning/idle M's,
+	// otherwise our help is not required
+	if atomic.Load(&sched.nmspinning)+atomic.Load(&sched.npidle) == 0 && atomic.Cas(&sched.nmspinning, 0, 1) { // TODO: fast atomic
+		startm(_p_, true)
+		return
+	}
+	lock(&sched.lock)
+	if sched.gcwaiting != 0 {
+		_p_.status = _Pgcstop
+		sched.stopwait--
+		if sched.stopwait == 0 {
+			notewakeup(&sched.stopnote)
+		}
+		unlock(&sched.lock)
+		return
+	}
+	if _p_.runSafePointFn != 0 && atomic.Cas(&_p_.runSafePointFn, 1, 0) {
+		sched.safePointFn(_p_)
+		sched.safePointWait--
+		if sched.safePointWait == 0 {
+			notewakeup(&sched.safePointNote)
+		}
+	}
+	if sched.runqsize != 0 {
+		unlock(&sched.lock)
+		startm(_p_, false)
+		return
+	}
+	// If this is the last running P and nobody is polling network,
+	// need to wakeup another M to poll network.
+	if sched.npidle == uint32(gomaxprocs-1) && atomic.Load64(&sched.lastpoll) != 0 {
+		unlock(&sched.lock)
+		startm(_p_, false)
+		return
+	}
+	pidleput(_p_)
+	unlock(&sched.lock)
+}
+
+// Tries to add one more P to execute G's.
+// Called when a G is made runnable (newproc, ready).
+func wakep() {
+	// be conservative about spinning threads
+	if !atomic.Cas(&sched.nmspinning, 0, 1) {
+		return
+	}
+	startm(nil, true)
+}
+
+// Stops execution of the current m that is locked to a g until the g is runnable again.
+// Returns with acquired P.
+func stoplockedm() {
+	_g_ := getg()
+
+	if _g_.m.lockedg == nil || _g_.m.lockedg.lockedm != _g_.m {
+		throw("stoplockedm: inconsistent locking")
+	}
+	if _g_.m.p != 0 {
+		// Schedule another M to run this p.
+		_p_ := releasep()
+		handoffp(_p_)
+	}
+	incidlelocked(1)
+	// Wait until another thread schedules lockedg again.
+	notesleep(&_g_.m.park)
+	noteclear(&_g_.m.park)
+	status := readgstatus(_g_.m.lockedg)
+	if status&^_Gscan != _Grunnable {
+		print("runtime:stoplockedm: g is not Grunnable or Gscanrunnable\n")
+		dumpgstatus(_g_)
+		throw("stoplockedm: not runnable")
+	}
+	acquirep(_g_.m.nextp.ptr())
+	_g_.m.nextp = 0
+}
+
+// Schedules the locked m to run the locked gp.
+// May run during STW, so write barriers are not allowed.
+//go:nowritebarrier
+func startlockedm(gp *g) {
+	_g_ := getg()
+
+	mp := gp.lockedm
+	if mp == _g_.m {
+		throw("startlockedm: locked to me")
+	}
+	if mp.nextp != 0 {
+		throw("startlockedm: m has p")
+	}
+	// directly handoff current P to the locked m
+	incidlelocked(-1)
+	_p_ := releasep()
+	mp.nextp.set(_p_)
+	notewakeup(&mp.park)
+	stopm()
+}
+
+// Stops the current m for stopTheWorld.
+// Returns when the world is restarted.
+func gcstopm() {
+	_g_ := getg()
+
+	if sched.gcwaiting == 0 {
+		throw("gcstopm: not waiting for gc")
+	}
+	if _g_.m.spinning {
+		_g_.m.spinning = false
+		// OK to just drop nmspinning here,
+		// startTheWorld will unpark threads as necessary.
+		if int32(atomic.Xadd(&sched.nmspinning, -1)) < 0 {
+			throw("gcstopm: negative nmspinning")
+		}
+	}
+	_p_ := releasep()
+	lock(&sched.lock)
+	_p_.status = _Pgcstop
+	sched.stopwait--
+	if sched.stopwait == 0 {
+		notewakeup(&sched.stopnote)
+	}
+	unlock(&sched.lock)
+	stopm()
+}
+
+// Schedules gp to run on the current M.
+// If inheritTime is true, gp inherits the remaining time in the
+// current time slice. Otherwise, it starts a new time slice.
+// Never returns.
+func execute(gp *g, inheritTime bool) {
+	_g_ := getg()
+
+	casgstatus(gp, _Grunnable, _Grunning)
+	gp.waitsince = 0
+	gp.preempt = false
+	gp.stackguard0 = gp.stack.lo + _StackGuard
+	if !inheritTime {
+		_g_.m.p.ptr().schedtick++
+	}
+	_g_.m.curg = gp
+	gp.m = _g_.m
+
+	// Check whether the profiler needs to be turned on or off.
+	hz := sched.profilehz
+	if _g_.m.profilehz != hz {
+		resetcpuprofiler(hz)
+	}
+
+	if trace.enabled {
+		// GoSysExit has to happen when we have a P, but before GoStart.
+		// So we emit it here.
+		if gp.syscallsp != 0 && gp.sysblocktraced {
+			// Since gp.sysblocktraced is true, we must emit an event.
+			// There is a race between the code that initializes sysexitseq
+			// and sysexitticks (in exitsyscall, which runs without a P,
+			// and therefore is not stopped with the rest of the world)
+			// and the code that initializes a new trace.
+			// The recorded sysexitseq and sysexitticks must therefore
+			// be treated as "best effort". If they are valid for this trace,
+			// then great, use them for greater accuracy.
+			// But if they're not valid for this trace, assume that the
+			// trace was started after the actual syscall exit (but before
+			// we actually managed to start the goroutine, aka right now),
+			// and assign a fresh time stamp to keep the log consistent.
+			seq, ts := gp.sysexitseq, gp.sysexitticks
+			if seq == 0 || int64(seq)-int64(trace.seqStart) < 0 {
+				seq, ts = tracestamp()
+			}
+			traceGoSysExit(seq, ts)
+		}
+		traceGoStart()
+	}
+
+	gogo(&gp.sched)
+}
+
+// Finds a runnable goroutine to execute.
+// Tries to steal from other P's, get g from global queue, poll network.
+func findrunnable() (gp *g, inheritTime bool) {
+	_g_ := getg()
+
+	// The conditions here and in handoffp must agree: if
+	// findrunnable would return a G to run, handoffp must start
+	// an M.
+
+top:
+	if sched.gcwaiting != 0 {
+		gcstopm()
+		goto top
+	}
+	if _g_.m.p.ptr().runSafePointFn != 0 {
+		runSafePointFn()
+	}
+	if fingwait && fingwake {
+		if gp := wakefing(); gp != nil {
+			ready(gp, 0)
+		}
+	}
+
+	// local runq
+	if gp, inheritTime := runqget(_g_.m.p.ptr()); gp != nil {
+		return gp, inheritTime
+	}
+
+	// global runq
+	if sched.runqsize != 0 {
+		lock(&sched.lock)
+		gp := globrunqget(_g_.m.p.ptr(), 0)
+		unlock(&sched.lock)
+		if gp != nil {
+			return gp, false
+		}
+	}
+
+	// Poll network.
+	// This netpoll is only an optimization before we resort to stealing.
+	// We can safely skip it if there a thread blocked in netpoll already.
+	// If there is any kind of logical race with that blocked thread
+	// (e.g. it has already returned from netpoll, but does not set lastpoll yet),
+	// this thread will do blocking netpoll below anyway.
+	if netpollinited() && sched.lastpoll != 0 {
+		if gp := netpoll(false); gp != nil { // non-blocking
+			// netpoll returns list of goroutines linked by schedlink.
+			injectglist(gp.schedlink.ptr())
+			casgstatus(gp, _Gwaiting, _Grunnable)
+			if trace.enabled {
+				traceGoUnpark(gp, 0)
+			}
+			return gp, false
+		}
+	}
+
+	// If number of spinning M's >= number of busy P's, block.
+	// This is necessary to prevent excessive CPU consumption
+	// when GOMAXPROCS>>1 but the program parallelism is low.
+	if !_g_.m.spinning && 2*atomic.Load(&sched.nmspinning) >= uint32(gomaxprocs)-atomic.Load(&sched.npidle) { // TODO: fast atomic
+		goto stop
+	}
+	if !_g_.m.spinning {
+		_g_.m.spinning = true
+		atomic.Xadd(&sched.nmspinning, 1)
+	}
+	// random steal from other P's
+	for i := 0; i < int(4*gomaxprocs); i++ {
+		if sched.gcwaiting != 0 {
+			goto top
+		}
+		_p_ := allp[fastrand1()%uint32(gomaxprocs)]
+		var gp *g
+		if _p_ == _g_.m.p.ptr() {
+			gp, _ = runqget(_p_)
+		} else {
+			stealRunNextG := i > 2*int(gomaxprocs) // first look for ready queues with more than 1 g
+			gp = runqsteal(_g_.m.p.ptr(), _p_, stealRunNextG)
+		}
+		if gp != nil {
+			return gp, false
+		}
+	}
+
+stop:
+
+	// We have nothing to do. If we're in the GC mark phase, can
+	// safely scan and blacken objects, and have work to do, run
+	// idle-time marking rather than give up the P.
+	if _p_ := _g_.m.p.ptr(); gcBlackenEnabled != 0 && _p_.gcBgMarkWorker != 0 && gcMarkWorkAvailable(_p_) {
+		_p_.gcMarkWorkerMode = gcMarkWorkerIdleMode
+		gp := _p_.gcBgMarkWorker.ptr()
+		casgstatus(gp, _Gwaiting, _Grunnable)
+		if trace.enabled {
+			traceGoUnpark(gp, 0)
+		}
+		return gp, false
+	}
+
+	// return P and block
+	lock(&sched.lock)
+	if sched.gcwaiting != 0 || _g_.m.p.ptr().runSafePointFn != 0 {
+		unlock(&sched.lock)
+		goto top
+	}
+	if sched.runqsize != 0 {
+		gp := globrunqget(_g_.m.p.ptr(), 0)
+		unlock(&sched.lock)
+		return gp, false
+	}
+	_p_ := releasep()
+	pidleput(_p_)
+	unlock(&sched.lock)
+
+	// Delicate dance: thread transitions from spinning to non-spinning state,
+	// potentially concurrently with submission of new goroutines. We must
+	// drop nmspinning first and then check all per-P queues again (with
+	// #StoreLoad memory barrier in between). If we do it the other way around,
+	// another thread can submit a goroutine after we've checked all run queues
+	// but before we drop nmspinning; as the result nobody will unpark a thread
+	// to run the goroutine.
+	// If we discover new work below, we need to restore m.spinning as a signal
+	// for resetspinning to unpark a new worker thread (because there can be more
+	// than one starving goroutine). However, if after discovering new work
+	// we also observe no idle Ps, it is OK to just park the current thread:
+	// the system is fully loaded so no spinning threads are required.
+	// Also see "Worker thread parking/unparking" comment at the top of the file.
+	wasSpinning := _g_.m.spinning
+	if _g_.m.spinning {
+		_g_.m.spinning = false
+		if int32(atomic.Xadd(&sched.nmspinning, -1)) < 0 {
+			throw("findrunnable: negative nmspinning")
+		}
+	}
+
+	// check all runqueues once again
+	for i := 0; i < int(gomaxprocs); i++ {
+		_p_ := allp[i]
+		if _p_ != nil && !runqempty(_p_) {
+			lock(&sched.lock)
+			_p_ = pidleget()
+			unlock(&sched.lock)
+			if _p_ != nil {
+				acquirep(_p_)
+				if wasSpinning {
+					_g_.m.spinning = true
+					atomic.Xadd(&sched.nmspinning, 1)
+				}
+				goto top
+			}
+			break
+		}
+	}
+
+	// poll network
+	if netpollinited() && atomic.Xchg64(&sched.lastpoll, 0) != 0 {
+		if _g_.m.p != 0 {
+			throw("findrunnable: netpoll with p")
+		}
+		if _g_.m.spinning {
+			throw("findrunnable: netpoll with spinning")
+		}
+		gp := netpoll(true) // block until new work is available
+		atomic.Store64(&sched.lastpoll, uint64(nanotime()))
+		if gp != nil {
+			lock(&sched.lock)
+			_p_ = pidleget()
+			unlock(&sched.lock)
+			if _p_ != nil {
+				acquirep(_p_)
+				injectglist(gp.schedlink.ptr())
+				casgstatus(gp, _Gwaiting, _Grunnable)
+				if trace.enabled {
+					traceGoUnpark(gp, 0)
+				}
+				return gp, false
+			}
+			injectglist(gp)
+		}
+	}
+	stopm()
+	goto top
+}
+
+func resetspinning() {
+	_g_ := getg()
+	if !_g_.m.spinning {
+		throw("resetspinning: not a spinning m")
+	}
+	_g_.m.spinning = false
+	nmspinning := atomic.Xadd(&sched.nmspinning, -1)
+	if int32(nmspinning) < 0 {
+		throw("findrunnable: negative nmspinning")
+	}
+	// M wakeup policy is deliberately somewhat conservative, so check if we
+	// need to wakeup another P here. See "Worker thread parking/unparking"
+	// comment at the top of the file for details.
+	if nmspinning == 0 && atomic.Load(&sched.npidle) > 0 {
+		wakep()
+	}
+}
+
+// Injects the list of runnable G's into the scheduler.
+// Can run concurrently with GC.
+func injectglist(glist *g) {
+	if glist == nil {
+		return
+	}
+	if trace.enabled {
+		for gp := glist; gp != nil; gp = gp.schedlink.ptr() {
+			traceGoUnpark(gp, 0)
+		}
+	}
+	lock(&sched.lock)
+	var n int
+	for n = 0; glist != nil; n++ {
+		gp := glist
+		glist = gp.schedlink.ptr()
+		casgstatus(gp, _Gwaiting, _Grunnable)
+		globrunqput(gp)
+	}
+	unlock(&sched.lock)
+	for ; n != 0 && sched.npidle != 0; n-- {
+		startm(nil, false)
+	}
+}
+
+// One round of scheduler: find a runnable goroutine and execute it.
+// Never returns.
+func schedule() {
+	_g_ := getg()
+
+	if _g_.m.locks != 0 {
+		throw("schedule: holding locks")
+	}
+
+	if _g_.m.lockedg != nil {
+		stoplockedm()
+		execute(_g_.m.lockedg, false) // Never returns.
+	}
+
+top:
+	if sched.gcwaiting != 0 {
+		gcstopm()
+		goto top
+	}
+	if _g_.m.p.ptr().runSafePointFn != 0 {
+		runSafePointFn()
+	}
+
+	var gp *g
+	var inheritTime bool
+	if trace.enabled || trace.shutdown {
+		gp = traceReader()
+		if gp != nil {
+			casgstatus(gp, _Gwaiting, _Grunnable)
+			traceGoUnpark(gp, 0)
+		}
+	}
+	if gp == nil && gcBlackenEnabled != 0 {
+		gp = gcController.findRunnableGCWorker(_g_.m.p.ptr())
+	}
+	if gp == nil {
+		// Check the global runnable queue once in a while to ensure fairness.
+		// Otherwise two goroutines can completely occupy the local runqueue
+		// by constantly respawning each other.
+		if _g_.m.p.ptr().schedtick%61 == 0 && sched.runqsize > 0 {
+			lock(&sched.lock)
+			gp = globrunqget(_g_.m.p.ptr(), 1)
+			unlock(&sched.lock)
+		}
+	}
+	if gp == nil {
+		gp, inheritTime = runqget(_g_.m.p.ptr())
+		if gp != nil && _g_.m.spinning {
+			throw("schedule: spinning with local work")
+		}
+	}
+	if gp == nil {
+		gp, inheritTime = findrunnable() // blocks until work is available
+	}
+
+	// This thread is going to run a goroutine and is not spinning anymore,
+	// so if it was marked as spinning we need to reset it now and potentially
+	// start a new spinning M.
+	if _g_.m.spinning {
+		resetspinning()
+	}
+
+	if gp.lockedm != nil {
+		// Hands off own p to the locked m,
+		// then blocks waiting for a new p.
+		startlockedm(gp)
+		goto top
+	}
+
+	execute(gp, inheritTime)
+}
+
+// dropg removes the association between m and the current goroutine m->curg (gp for short).
+// Typically a caller sets gp's status away from Grunning and then
+// immediately calls dropg to finish the job. The caller is also responsible
+// for arranging that gp will be restarted using ready at an
+// appropriate time. After calling dropg and arranging for gp to be
+// readied later, the caller can do other work but eventually should
+// call schedule to restart the scheduling of goroutines on this m.
+func dropg() {
+	_g_ := getg()
+
+	if _g_.m.lockedg == nil {
+		_g_.m.curg.m = nil
+		_g_.m.curg = nil
+	}
+}
+
+func parkunlock_c(gp *g, lock unsafe.Pointer) bool {
+	unlock((*mutex)(lock))
+	return true
+}
+
+// park continuation on g0.
+func park_m(gp *g) {
+	_g_ := getg()
+
+	if trace.enabled {
+		traceGoPark(_g_.m.waittraceev, _g_.m.waittraceskip, gp)
+	}
+
+	casgstatus(gp, _Grunning, _Gwaiting)
+	dropg()
+
+	if _g_.m.waitunlockf != nil {
+		fn := *(*func(*g, unsafe.Pointer) bool)(unsafe.Pointer(&_g_.m.waitunlockf))
+		ok := fn(gp, _g_.m.waitlock)
+		_g_.m.waitunlockf = nil
+		_g_.m.waitlock = nil
+		if !ok {
+			if trace.enabled {
+				traceGoUnpark(gp, 2)
+			}
+			casgstatus(gp, _Gwaiting, _Grunnable)
+			execute(gp, true) // Schedule it back, never returns.
+		}
+	}
+	schedule()
+}
+
+func goschedImpl(gp *g) {
+	status := readgstatus(gp)
+	if status&^_Gscan != _Grunning {
+		dumpgstatus(gp)
+		throw("bad g status")
+	}
+	casgstatus(gp, _Grunning, _Grunnable)
+	dropg()
+	lock(&sched.lock)
+	globrunqput(gp)
+	unlock(&sched.lock)
+
+	schedule()
+}
+
+// Gosched continuation on g0.
+func gosched_m(gp *g) {
+	if trace.enabled {
+		traceGoSched()
+	}
+	goschedImpl(gp)
+}
+
+func gopreempt_m(gp *g) {
+	if trace.enabled {
+		traceGoPreempt()
+	}
+	goschedImpl(gp)
+}
+
+// Finishes execution of the current goroutine.
+func goexit1() {
+	if raceenabled {
+		racegoend()
+	}
+	if trace.enabled {
+		traceGoEnd()
+	}
+	mcall(goexit0)
+}
+
+// goexit continuation on g0.
+func goexit0(gp *g) {
+	_g_ := getg()
+
+	casgstatus(gp, _Grunning, _Gdead)
+	if isSystemGoroutine(gp) {
+		atomic.Xadd(&sched.ngsys, -1)
+	}
+	gp.m = nil
+	gp.lockedm = nil
+	_g_.m.lockedg = nil
+	gp.paniconfault = false
+	gp._defer = nil // should be true already but just in case.
+	gp._panic = nil // non-nil for Goexit during panic. points at stack-allocated data.
+	gp.writebuf = nil
+	gp.waitreason = ""
+	gp.param = nil
+
+	dropg()
+
+	if _g_.m.locked&^_LockExternal != 0 {
+		print("invalid m->locked = ", _g_.m.locked, "\n")
+		throw("internal lockOSThread error")
+	}
+	_g_.m.locked = 0
+	gfput(_g_.m.p.ptr(), gp)
+	schedule()
+}
+
+//go:nosplit
+//go:nowritebarrier
+func save(pc, sp uintptr) {
+	_g_ := getg()
+
+	_g_.sched.pc = pc
+	_g_.sched.sp = sp
+	_g_.sched.lr = 0
+	_g_.sched.ret = 0
+	_g_.sched.ctxt = nil
+	_g_.sched.g = guintptr(unsafe.Pointer(_g_))
+}
+
+// The goroutine g is about to enter a system call.
+// Record that it's not using the cpu anymore.
+// This is called only from the go syscall library and cgocall,
+// not from the low-level system calls used by the runtime.
+//
+// Entersyscall cannot split the stack: the gosave must
+// make g->sched refer to the caller's stack segment, because
+// entersyscall is going to return immediately after.
+//
+// Nothing entersyscall calls can split the stack either.
+// We cannot safely move the stack during an active call to syscall,
+// because we do not know which of the uintptr arguments are
+// really pointers (back into the stack).
+// In practice, this means that we make the fast path run through
+// entersyscall doing no-split things, and the slow path has to use systemstack
+// to run bigger things on the system stack.
+//
+// reentersyscall is the entry point used by cgo callbacks, where explicitly
+// saved SP and PC are restored. This is needed when exitsyscall will be called
+// from a function further up in the call stack than the parent, as g->syscallsp
+// must always point to a valid stack frame. entersyscall below is the normal
+// entry point for syscalls, which obtains the SP and PC from the caller.
+//
+// Syscall tracing:
+// At the start of a syscall we emit traceGoSysCall to capture the stack trace.
+// If the syscall does not block, that is it, we do not emit any other events.
+// If the syscall blocks (that is, P is retaken), retaker emits traceGoSysBlock;
+// when syscall returns we emit traceGoSysExit and when the goroutine starts running
+// (potentially instantly, if exitsyscallfast returns true) we emit traceGoStart.
+// To ensure that traceGoSysExit is emitted strictly after traceGoSysBlock,
+// we remember current value of syscalltick in m (_g_.m.syscalltick = _g_.m.p.ptr().syscalltick),
+// whoever emits traceGoSysBlock increments p.syscalltick afterwards;
+// and we wait for the increment before emitting traceGoSysExit.
+// Note that the increment is done even if tracing is not enabled,
+// because tracing can be enabled in the middle of syscall. We don't want the wait to hang.
+//
+//go:nosplit
+func reentersyscall(pc, sp uintptr) {
+	_g_ := getg()
+
+	// Disable preemption because during this function g is in Gsyscall status,
+	// but can have inconsistent g->sched, do not let GC observe it.
+	_g_.m.locks++
+
+	// Entersyscall must not call any function that might split/grow the stack.
+	// (See details in comment above.)
+	// Catch calls that might, by replacing the stack guard with something that
+	// will trip any stack check and leaving a flag to tell newstack to die.
+	_g_.stackguard0 = stackPreempt
+	_g_.throwsplit = true
+
+	// Leave SP around for GC and traceback.
+	save(pc, sp)
+	_g_.syscallsp = sp
+	_g_.syscallpc = pc
+	casgstatus(_g_, _Grunning, _Gsyscall)
+	if _g_.syscallsp < _g_.stack.lo || _g_.stack.hi < _g_.syscallsp {
+		systemstack(func() {
+			print("entersyscall inconsistent ", hex(_g_.syscallsp), " [", hex(_g_.stack.lo), ",", hex(_g_.stack.hi), "]\n")
+			throw("entersyscall")
+		})
+	}
+
+	if trace.enabled {
+		systemstack(traceGoSysCall)
+		// systemstack itself clobbers g.sched.{pc,sp} and we might
+		// need them later when the G is genuinely blocked in a
+		// syscall
+		save(pc, sp)
+	}
+
+	if atomic.Load(&sched.sysmonwait) != 0 { // TODO: fast atomic
+		systemstack(entersyscall_sysmon)
+		save(pc, sp)
+	}
+
+	if _g_.m.p.ptr().runSafePointFn != 0 {
+		// runSafePointFn may stack split if run on this stack
+		systemstack(runSafePointFn)
+		save(pc, sp)
+	}
+
+	_g_.m.syscalltick = _g_.m.p.ptr().syscalltick
+	_g_.sysblocktraced = true
+	_g_.m.mcache = nil
+	_g_.m.p.ptr().m = 0
+	atomic.Store(&_g_.m.p.ptr().status, _Psyscall)
+	if sched.gcwaiting != 0 {
+		systemstack(entersyscall_gcwait)
+		save(pc, sp)
+	}
+
+	// Goroutines must not split stacks in Gsyscall status (it would corrupt g->sched).
+	// We set _StackGuard to StackPreempt so that first split stack check calls morestack.
+	// Morestack detects this case and throws.
+	_g_.stackguard0 = stackPreempt
+	_g_.m.locks--
+}
+
+// Standard syscall entry used by the go syscall library and normal cgo calls.
+//go:nosplit
+func entersyscall(dummy int32) {
+	reentersyscall(getcallerpc(unsafe.Pointer(&dummy)), getcallersp(unsafe.Pointer(&dummy)))
+}
+
+func entersyscall_sysmon() {
+	lock(&sched.lock)
+	if atomic.Load(&sched.sysmonwait) != 0 {
+		atomic.Store(&sched.sysmonwait, 0)
+		notewakeup(&sched.sysmonnote)
+	}
+	unlock(&sched.lock)
+}
+
+func entersyscall_gcwait() {
+	_g_ := getg()
+	_p_ := _g_.m.p.ptr()
+
+	lock(&sched.lock)
+	if sched.stopwait > 0 && atomic.Cas(&_p_.status, _Psyscall, _Pgcstop) {
+		if trace.enabled {
+			traceGoSysBlock(_p_)
+			traceProcStop(_p_)
+		}
+		_p_.syscalltick++
+		if sched.stopwait--; sched.stopwait == 0 {
+			notewakeup(&sched.stopnote)
+		}
+	}
+	unlock(&sched.lock)
+}
+
+// The same as entersyscall(), but with a hint that the syscall is blocking.
+//go:nosplit
+func entersyscallblock(dummy int32) {
+	_g_ := getg()
+
+	_g_.m.locks++ // see comment in entersyscall
+	_g_.throwsplit = true
+	_g_.stackguard0 = stackPreempt // see comment in entersyscall
+	_g_.m.syscalltick = _g_.m.p.ptr().syscalltick
+	_g_.sysblocktraced = true
+	_g_.m.p.ptr().syscalltick++
+
+	// Leave SP around for GC and traceback.
+	pc := getcallerpc(unsafe.Pointer(&dummy))
+	sp := getcallersp(unsafe.Pointer(&dummy))
+	save(pc, sp)
+	_g_.syscallsp = _g_.sched.sp
+	_g_.syscallpc = _g_.sched.pc
+	if _g_.syscallsp < _g_.stack.lo || _g_.stack.hi < _g_.syscallsp {
+		sp1 := sp
+		sp2 := _g_.sched.sp
+		sp3 := _g_.syscallsp
+		systemstack(func() {
+			print("entersyscallblock inconsistent ", hex(sp1), " ", hex(sp2), " ", hex(sp3), " [", hex(_g_.stack.lo), ",", hex(_g_.stack.hi), "]\n")
+			throw("entersyscallblock")
+		})
+	}
+	casgstatus(_g_, _Grunning, _Gsyscall)
+	if _g_.syscallsp < _g_.stack.lo || _g_.stack.hi < _g_.syscallsp {
+		systemstack(func() {
+			print("entersyscallblock inconsistent ", hex(sp), " ", hex(_g_.sched.sp), " ", hex(_g_.syscallsp), " [", hex(_g_.stack.lo), ",", hex(_g_.stack.hi), "]\n")
+			throw("entersyscallblock")
+		})
+	}
+
+	systemstack(entersyscallblock_handoff)
+
+	// Resave for traceback during blocked call.
+	save(getcallerpc(unsafe.Pointer(&dummy)), getcallersp(unsafe.Pointer(&dummy)))
+
+	_g_.m.locks--
+}
+
+func entersyscallblock_handoff() {
+	if trace.enabled {
+		traceGoSysCall()
+		traceGoSysBlock(getg().m.p.ptr())
+	}
+	handoffp(releasep())
+}
+
+// The goroutine g exited its system call.
+// Arrange for it to run on a cpu again.
+// This is called only from the go syscall library, not
+// from the low-level system calls used by the
+//go:nosplit
+func exitsyscall(dummy int32) {
+	_g_ := getg()
+
+	_g_.m.locks++ // see comment in entersyscall
+	if getcallersp(unsafe.Pointer(&dummy)) > _g_.syscallsp {
+		throw("exitsyscall: syscall frame is no longer valid")
+	}
+
+	_g_.waitsince = 0
+	oldp := _g_.m.p.ptr()
+	if exitsyscallfast() {
+		if _g_.m.mcache == nil {
+			throw("lost mcache")
+		}
+		if trace.enabled {
+			if oldp != _g_.m.p.ptr() || _g_.m.syscalltick != _g_.m.p.ptr().syscalltick {
+				systemstack(traceGoStart)
+			}
+		}
+		// There's a cpu for us, so we can run.
+		_g_.m.p.ptr().syscalltick++
+		// We need to cas the status and scan before resuming...
+		casgstatus(_g_, _Gsyscall, _Grunning)
+
+		// Garbage collector isn't running (since we are),
+		// so okay to clear syscallsp.
+		_g_.syscallsp = 0
+		_g_.m.locks--
+		if _g_.preempt {
+			// restore the preemption request in case we've cleared it in newstack
+			_g_.stackguard0 = stackPreempt
+		} else {
+			// otherwise restore the real _StackGuard, we've spoiled it in entersyscall/entersyscallblock
+			_g_.stackguard0 = _g_.stack.lo + _StackGuard
+		}
+		_g_.throwsplit = false
+		return
+	}
+
+	_g_.sysexitticks = 0
+	_g_.sysexitseq = 0
+	if trace.enabled {
+		// Wait till traceGoSysBlock event is emitted.
+		// This ensures consistency of the trace (the goroutine is started after it is blocked).
+		for oldp != nil && oldp.syscalltick == _g_.m.syscalltick {
+			osyield()
+		}
+		// We can't trace syscall exit right now because we don't have a P.
+		// Tracing code can invoke write barriers that cannot run without a P.
+		// So instead we remember the syscall exit time and emit the event
+		// in execute when we have a P.
+		_g_.sysexitseq, _g_.sysexitticks = tracestamp()
+	}
+
+	_g_.m.locks--
+
+	// Call the scheduler.
+	mcall(exitsyscall0)
+
+	if _g_.m.mcache == nil {
+		throw("lost mcache")
+	}
+
+	// Scheduler returned, so we're allowed to run now.
+	// Delete the syscallsp information that we left for
+	// the garbage collector during the system call.
+	// Must wait until now because until gosched returns
+	// we don't know for sure that the garbage collector
+	// is not running.
+	_g_.syscallsp = 0
+	_g_.m.p.ptr().syscalltick++
+	_g_.throwsplit = false
+}
+
+//go:nosplit
+func exitsyscallfast() bool {
+	_g_ := getg()
+
+	// Freezetheworld sets stopwait but does not retake P's.
+	if sched.stopwait == freezeStopWait {
+		_g_.m.mcache = nil
+		_g_.m.p = 0
+		return false
+	}
+
+	// Try to re-acquire the last P.
+	if _g_.m.p != 0 && _g_.m.p.ptr().status == _Psyscall && atomic.Cas(&_g_.m.p.ptr().status, _Psyscall, _Prunning) {
+		// There's a cpu for us, so we can run.
+		_g_.m.mcache = _g_.m.p.ptr().mcache
+		_g_.m.p.ptr().m.set(_g_.m)
+		if _g_.m.syscalltick != _g_.m.p.ptr().syscalltick {
+			if trace.enabled {
+				// The p was retaken and then enter into syscall again (since _g_.m.syscalltick has changed).
+				// traceGoSysBlock for this syscall was already emitted,
+				// but here we effectively retake the p from the new syscall running on the same p.
+				systemstack(func() {
+					// Denote blocking of the new syscall.
+					traceGoSysBlock(_g_.m.p.ptr())
+					// Denote completion of the current syscall.
+					traceGoSysExit(tracestamp())
+				})
+			}
+			_g_.m.p.ptr().syscalltick++
+		}
+		return true
+	}
+
+	// Try to get any other idle P.
+	oldp := _g_.m.p.ptr()
+	_g_.m.mcache = nil
+	_g_.m.p = 0
+	if sched.pidle != 0 {
+		var ok bool
+		systemstack(func() {
+			ok = exitsyscallfast_pidle()
+			if ok && trace.enabled {
+				if oldp != nil {
+					// Wait till traceGoSysBlock event is emitted.
+					// This ensures consistency of the trace (the goroutine is started after it is blocked).
+					for oldp.syscalltick == _g_.m.syscalltick {
+						osyield()
+					}
+				}
+				traceGoSysExit(tracestamp())
+			}
+		})
+		if ok {
+			return true
+		}
+	}
+	return false
+}
+
+func exitsyscallfast_pidle() bool {
+	lock(&sched.lock)
+	_p_ := pidleget()
+	if _p_ != nil && atomic.Load(&sched.sysmonwait) != 0 {
+		atomic.Store(&sched.sysmonwait, 0)
+		notewakeup(&sched.sysmonnote)
+	}
+	unlock(&sched.lock)
+	if _p_ != nil {
+		acquirep(_p_)
+		return true
+	}
+	return false
+}
+
+// exitsyscall slow path on g0.
+// Failed to acquire P, enqueue gp as runnable.
+func exitsyscall0(gp *g) {
+	_g_ := getg()
+
+	casgstatus(gp, _Gsyscall, _Grunnable)
+	dropg()
+	lock(&sched.lock)
+	_p_ := pidleget()
+	if _p_ == nil {
+		globrunqput(gp)
+	} else if atomic.Load(&sched.sysmonwait) != 0 {
+		atomic.Store(&sched.sysmonwait, 0)
+		notewakeup(&sched.sysmonnote)
+	}
+	unlock(&sched.lock)
+	if _p_ != nil {
+		acquirep(_p_)
+		execute(gp, false) // Never returns.
+	}
+	if _g_.m.lockedg != nil {
+		// Wait until another thread schedules gp and so m again.
+		stoplockedm()
+		execute(gp, false) // Never returns.
+	}
+	stopm()
+	schedule() // Never returns.
+}
+
+func beforefork() {
+	gp := getg().m.curg
+
+	// Fork can hang if preempted with signals frequently enough (see issue 5517).
+	// Ensure that we stay on the same M where we disable profiling.
+	gp.m.locks++
+	if gp.m.profilehz != 0 {
+		resetcpuprofiler(0)
+	}
+
+	// This function is called before fork in syscall package.
+	// Code between fork and exec must not allocate memory nor even try to grow stack.
+	// Here we spoil g->_StackGuard to reliably detect any attempts to grow stack.
+	// runtime_AfterFork will undo this in parent process, but not in child.
+	gp.stackguard0 = stackFork
+}
+
+// Called from syscall package before fork.
+//go:linkname syscall_runtime_BeforeFork syscall.runtime_BeforeFork
+//go:nosplit
+func syscall_runtime_BeforeFork() {
+	systemstack(beforefork)
+}
+
+func afterfork() {
+	gp := getg().m.curg
+
+	// See the comment in beforefork.
+	gp.stackguard0 = gp.stack.lo + _StackGuard
+
+	hz := sched.profilehz
+	if hz != 0 {
+		resetcpuprofiler(hz)
+	}
+	gp.m.locks--
+}
+
+// Called from syscall package after fork in parent.
+//go:linkname syscall_runtime_AfterFork syscall.runtime_AfterFork
+//go:nosplit
+func syscall_runtime_AfterFork() {
+	systemstack(afterfork)
+}
+
+// Allocate a new g, with a stack big enough for stacksize bytes.
+func malg(stacksize int32) *g {
+	newg := new(g)
+	if stacksize >= 0 {
+		stacksize = round2(_StackSystem + stacksize)
+		systemstack(func() {
+			newg.stack, newg.stkbar = stackalloc(uint32(stacksize))
+		})
+		newg.stackguard0 = newg.stack.lo + _StackGuard
+		newg.stackguard1 = ^uintptr(0)
+		newg.stackAlloc = uintptr(stacksize)
+	}
+	return newg
+}
+
+// Create a new g running fn with siz bytes of arguments.
+// Put it on the queue of g's waiting to run.
+// The compiler turns a go statement into a call to this.
+// Cannot split the stack because it assumes that the arguments
+// are available sequentially after &fn; they would not be
+// copied if a stack split occurred.
+//go:nosplit
+func newproc(siz int32, fn *funcval) {
+	argp := add(unsafe.Pointer(&fn), sys.PtrSize)
+	pc := getcallerpc(unsafe.Pointer(&siz))
+	systemstack(func() {
+		newproc1(fn, (*uint8)(argp), siz, 0, pc)
+	})
+}
+
+// Create a new g running fn with narg bytes of arguments starting
+// at argp and returning nret bytes of results.  callerpc is the
+// address of the go statement that created this.  The new g is put
+// on the queue of g's waiting to run.
+func newproc1(fn *funcval, argp *uint8, narg int32, nret int32, callerpc uintptr) *g {
+	_g_ := getg()
+
+	if fn == nil {
+		_g_.m.throwing = -1 // do not dump full stacks
+		throw("go of nil func value")
+	}
+	_g_.m.locks++ // disable preemption because it can be holding p in a local var
+	siz := narg + nret
+	siz = (siz + 7) &^ 7
+
+	// We could allocate a larger initial stack if necessary.
+	// Not worth it: this is almost always an error.
+	// 4*sizeof(uintreg): extra space added below
+	// sizeof(uintreg): caller's LR (arm) or return address (x86, in gostartcall).
+	if siz >= _StackMin-4*sys.RegSize-sys.RegSize {
+		throw("newproc: function arguments too large for new goroutine")
+	}
+
+	_p_ := _g_.m.p.ptr()
+	newg := gfget(_p_)
+	if newg == nil {
+		newg = malg(_StackMin)
+		casgstatus(newg, _Gidle, _Gdead)
+		allgadd(newg) // publishes with a g->status of Gdead so GC scanner doesn't look at uninitialized stack.
+	}
+	if newg.stack.hi == 0 {
+		throw("newproc1: newg missing stack")
+	}
+
+	if readgstatus(newg) != _Gdead {
+		throw("newproc1: new g is not Gdead")
+	}
+
+	totalSize := 4*sys.RegSize + uintptr(siz) + sys.MinFrameSize // extra space in case of reads slightly beyond frame
+	totalSize += -totalSize & (sys.SpAlign - 1)                  // align to spAlign
+	sp := newg.stack.hi - totalSize
+	spArg := sp
+	if usesLR {
+		// caller's LR
+		*(*unsafe.Pointer)(unsafe.Pointer(sp)) = nil
+		prepGoExitFrame(sp)
+		spArg += sys.MinFrameSize
+	}
+	memmove(unsafe.Pointer(spArg), unsafe.Pointer(argp), uintptr(narg))
+
+	memclr(unsafe.Pointer(&newg.sched), unsafe.Sizeof(newg.sched))
+	newg.sched.sp = sp
+	newg.stktopsp = sp
+	newg.sched.pc = funcPC(goexit) + sys.PCQuantum // +PCQuantum so that previous instruction is in same function
+	newg.sched.g = guintptr(unsafe.Pointer(newg))
+	gostartcallfn(&newg.sched, fn)
+	newg.gopc = callerpc
+	newg.startpc = fn.fn
+	if isSystemGoroutine(newg) {
+		atomic.Xadd(&sched.ngsys, +1)
+	}
+	casgstatus(newg, _Gdead, _Grunnable)
+
+	if _p_.goidcache == _p_.goidcacheend {
+		// Sched.goidgen is the last allocated id,
+		// this batch must be [sched.goidgen+1, sched.goidgen+GoidCacheBatch].
+		// At startup sched.goidgen=0, so main goroutine receives goid=1.
+		_p_.goidcache = atomic.Xadd64(&sched.goidgen, _GoidCacheBatch)
+		_p_.goidcache -= _GoidCacheBatch - 1
+		_p_.goidcacheend = _p_.goidcache + _GoidCacheBatch
+	}
+	newg.goid = int64(_p_.goidcache)
+	_p_.goidcache++
+	if raceenabled {
+		newg.racectx = racegostart(callerpc)
+	}
+	if trace.enabled {
+		traceGoCreate(newg, newg.startpc)
+	}
+	runqput(_p_, newg, true)
+
+	if atomic.Load(&sched.npidle) != 0 && atomic.Load(&sched.nmspinning) == 0 && unsafe.Pointer(fn.fn) != unsafe.Pointer(funcPC(main)) { // TODO: fast atomic
+		wakep()
+	}
+	_g_.m.locks--
+	if _g_.m.locks == 0 && _g_.preempt { // restore the preemption request in case we've cleared it in newstack
+		_g_.stackguard0 = stackPreempt
+	}
+	return newg
+}
+
+// Put on gfree list.
+// If local list is too long, transfer a batch to the global list.
+func gfput(_p_ *p, gp *g) {
+	if readgstatus(gp) != _Gdead {
+		throw("gfput: bad status (not Gdead)")
+	}
+
+	stksize := gp.stackAlloc
+
+	if stksize != _FixedStack {
+		// non-standard stack size - free it.
+		stackfree(gp.stack, gp.stackAlloc)
+		gp.stack.lo = 0
+		gp.stack.hi = 0
+		gp.stackguard0 = 0
+		gp.stkbar = nil
+		gp.stkbarPos = 0
+	} else {
+		// Reset stack barriers.
+		gp.stkbar = gp.stkbar[:0]
+		gp.stkbarPos = 0
+	}
+
+	gp.schedlink.set(_p_.gfree)
+	_p_.gfree = gp
+	_p_.gfreecnt++
+	if _p_.gfreecnt >= 64 {
+		lock(&sched.gflock)
+		for _p_.gfreecnt >= 32 {
+			_p_.gfreecnt--
+			gp = _p_.gfree
+			_p_.gfree = gp.schedlink.ptr()
+			gp.schedlink.set(sched.gfree)
+			sched.gfree = gp
+			sched.ngfree++
+		}
+		unlock(&sched.gflock)
+	}
+}
+
+// Get from gfree list.
+// If local list is empty, grab a batch from global list.
+func gfget(_p_ *p) *g {
+retry:
+	gp := _p_.gfree
+	if gp == nil && sched.gfree != nil {
+		lock(&sched.gflock)
+		for _p_.gfreecnt < 32 && sched.gfree != nil {
+			_p_.gfreecnt++
+			gp = sched.gfree
+			sched.gfree = gp.schedlink.ptr()
+			sched.ngfree--
+			gp.schedlink.set(_p_.gfree)
+			_p_.gfree = gp
+		}
+		unlock(&sched.gflock)
+		goto retry
+	}
+	if gp != nil {
+		_p_.gfree = gp.schedlink.ptr()
+		_p_.gfreecnt--
+		if gp.stack.lo == 0 {
+			// Stack was deallocated in gfput.  Allocate a new one.
+			systemstack(func() {
+				gp.stack, gp.stkbar = stackalloc(_FixedStack)
+			})
+			gp.stackguard0 = gp.stack.lo + _StackGuard
+			gp.stackAlloc = _FixedStack
+		} else {
+			if raceenabled {
+				racemalloc(unsafe.Pointer(gp.stack.lo), gp.stackAlloc)
+			}
+			if msanenabled {
+				msanmalloc(unsafe.Pointer(gp.stack.lo), gp.stackAlloc)
+			}
+		}
+	}
+	return gp
+}
+
+// Purge all cached G's from gfree list to the global list.
+func gfpurge(_p_ *p) {
+	lock(&sched.gflock)
+	for _p_.gfreecnt != 0 {
+		_p_.gfreecnt--
+		gp := _p_.gfree
+		_p_.gfree = gp.schedlink.ptr()
+		gp.schedlink.set(sched.gfree)
+		sched.gfree = gp
+		sched.ngfree++
+	}
+	unlock(&sched.gflock)
+}
+
+// Breakpoint executes a breakpoint trap.
+func Breakpoint() {
+	breakpoint()
+}
+
+// dolockOSThread is called by LockOSThread and lockOSThread below
+// after they modify m.locked. Do not allow preemption during this call,
+// or else the m might be different in this function than in the caller.
+//go:nosplit
+func dolockOSThread() {
+	_g_ := getg()
+	_g_.m.lockedg = _g_
+	_g_.lockedm = _g_.m
+}
+
+//go:nosplit
+
+// LockOSThread wires the calling goroutine to its current operating system thread.
+// Until the calling goroutine exits or calls UnlockOSThread, it will always
+// execute in that thread, and no other goroutine can.
+func LockOSThread() {
+	getg().m.locked |= _LockExternal
+	dolockOSThread()
+}
+
+//go:nosplit
+func lockOSThread() {
+	getg().m.locked += _LockInternal
+	dolockOSThread()
+}
+
+// dounlockOSThread is called by UnlockOSThread and unlockOSThread below
+// after they update m->locked. Do not allow preemption during this call,
+// or else the m might be in different in this function than in the caller.
+//go:nosplit
+func dounlockOSThread() {
+	_g_ := getg()
+	if _g_.m.locked != 0 {
+		return
+	}
+	_g_.m.lockedg = nil
+	_g_.lockedm = nil
+}
+
+//go:nosplit
+
+// UnlockOSThread unwires the calling goroutine from its fixed operating system thread.
+// If the calling goroutine has not called LockOSThread, UnlockOSThread is a no-op.
+func UnlockOSThread() {
+	getg().m.locked &^= _LockExternal
+	dounlockOSThread()
+}
+
+//go:nosplit
+func unlockOSThread() {
+	_g_ := getg()
+	if _g_.m.locked < _LockInternal {
+		systemstack(badunlockosthread)
+	}
+	_g_.m.locked -= _LockInternal
+	dounlockOSThread()
+}
+
+func badunlockosthread() {
+	throw("runtime: internal error: misuse of lockOSThread/unlockOSThread")
+}
+
+func gcount() int32 {
+	n := int32(allglen) - sched.ngfree - int32(atomic.Load(&sched.ngsys))
+	for i := 0; ; i++ {
+		_p_ := allp[i]
+		if _p_ == nil {
+			break
+		}
+		n -= _p_.gfreecnt
+	}
+
+	// All these variables can be changed concurrently, so the result can be inconsistent.
+	// But at least the current goroutine is running.
+	if n < 1 {
+		n = 1
+	}
+	return n
+}
+
+func mcount() int32 {
+	return sched.mcount
+}
+
+var prof struct {
+	lock uint32
+	hz   int32
+}
+
+func _System()       { _System() }
+func _ExternalCode() { _ExternalCode() }
+func _GC()           { _GC() }
+
+// Called if we receive a SIGPROF signal.
+func sigprof(pc, sp, lr uintptr, gp *g, mp *m) {
+	if prof.hz == 0 {
+		return
+	}
+
+	// Profiling runs concurrently with GC, so it must not allocate.
+	mp.mallocing++
+
+	// Define that a "user g" is a user-created goroutine, and a "system g"
+	// is one that is m->g0 or m->gsignal.
+	//
+	// We might be interrupted for profiling halfway through a
+	// goroutine switch. The switch involves updating three (or four) values:
+	// g, PC, SP, and (on arm) LR. The PC must be the last to be updated,
+	// because once it gets updated the new g is running.
+	//
+	// When switching from a user g to a system g, LR is not considered live,
+	// so the update only affects g, SP, and PC. Since PC must be last, there
+	// the possible partial transitions in ordinary execution are (1) g alone is updated,
+	// (2) both g and SP are updated, and (3) SP alone is updated.
+	// If SP or g alone is updated, we can detect the partial transition by checking
+	// whether the SP is within g's stack bounds. (We could also require that SP
+	// be changed only after g, but the stack bounds check is needed by other
+	// cases, so there is no need to impose an additional requirement.)
+	//
+	// There is one exceptional transition to a system g, not in ordinary execution.
+	// When a signal arrives, the operating system starts the signal handler running
+	// with an updated PC and SP. The g is updated last, at the beginning of the
+	// handler. There are two reasons this is okay. First, until g is updated the
+	// g and SP do not match, so the stack bounds check detects the partial transition.
+	// Second, signal handlers currently run with signals disabled, so a profiling
+	// signal cannot arrive during the handler.
+	//
+	// When switching from a system g to a user g, there are three possibilities.
+	//
+	// First, it may be that the g switch has no PC update, because the SP
+	// either corresponds to a user g throughout (as in asmcgocall)
+	// or because it has been arranged to look like a user g frame
+	// (as in cgocallback_gofunc). In this case, since the entire
+	// transition is a g+SP update, a partial transition updating just one of
+	// those will be detected by the stack bounds check.
+	//
+	// Second, when returning from a signal handler, the PC and SP updates
+	// are performed by the operating system in an atomic update, so the g
+	// update must be done before them. The stack bounds check detects
+	// the partial transition here, and (again) signal handlers run with signals
+	// disabled, so a profiling signal cannot arrive then anyway.
+	//
+	// Third, the common case: it may be that the switch updates g, SP, and PC
+	// separately. If the PC is within any of the functions that does this,
+	// we don't ask for a traceback. C.F. the function setsSP for more about this.
+	//
+	// There is another apparently viable approach, recorded here in case
+	// the "PC within setsSP function" check turns out not to be usable.
+	// It would be possible to delay the update of either g or SP until immediately
+	// before the PC update instruction. Then, because of the stack bounds check,
+	// the only problematic interrupt point is just before that PC update instruction,
+	// and the sigprof handler can detect that instruction and simulate stepping past
+	// it in order to reach a consistent state. On ARM, the update of g must be made
+	// in two places (in R10 and also in a TLS slot), so the delayed update would
+	// need to be the SP update. The sigprof handler must read the instruction at
+	// the current PC and if it was the known instruction (for example, JMP BX or
+	// MOV R2, PC), use that other register in place of the PC value.
+	// The biggest drawback to this solution is that it requires that we can tell
+	// whether it's safe to read from the memory pointed at by PC.
+	// In a correct program, we can test PC == nil and otherwise read,
+	// but if a profiling signal happens at the instant that a program executes
+	// a bad jump (before the program manages to handle the resulting fault)
+	// the profiling handler could fault trying to read nonexistent memory.
+	//
+	// To recap, there are no constraints on the assembly being used for the
+	// transition. We simply require that g and SP match and that the PC is not
+	// in gogo.
+	traceback := true
+	if gp == nil || sp < gp.stack.lo || gp.stack.hi < sp || setsSP(pc) {
+		traceback = false
+	}
+	var stk [maxCPUProfStack]uintptr
+	var haveStackLock *g
+	n := 0
+	if mp.ncgo > 0 && mp.curg != nil && mp.curg.syscallpc != 0 && mp.curg.syscallsp != 0 {
+		// Cgo, we can't unwind and symbolize arbitrary C code,
+		// so instead collect Go stack that leads to the cgo call.
+		// This is especially important on windows, since all syscalls are cgo calls.
+		if gcTryLockStackBarriers(mp.curg) {
+			haveStackLock = mp.curg
+			n = gentraceback(mp.curg.syscallpc, mp.curg.syscallsp, 0, mp.curg, 0, &stk[0], len(stk), nil, nil, 0)
+		}
+	} else if traceback {
+		var flags uint = _TraceTrap
+		if gp.m.curg != nil && gcTryLockStackBarriers(gp.m.curg) {
+			// It's safe to traceback the user stack.
+			haveStackLock = gp.m.curg
+			flags |= _TraceJumpStack
+		}
+		// Traceback is safe if we're on the system stack (if
+		// necessary, flags will stop it before switching to
+		// the user stack), or if we locked the user stack.
+		if gp != gp.m.curg || haveStackLock != nil {
+			n = gentraceback(pc, sp, lr, gp, 0, &stk[0], len(stk), nil, nil, flags)
+		}
+	}
+	if haveStackLock != nil {
+		gcUnlockStackBarriers(haveStackLock)
+	}
+
+	if n <= 0 {
+		// Normal traceback is impossible or has failed.
+		// See if it falls into several common cases.
+		n = 0
+		if GOOS == "windows" && mp.libcallg != 0 && mp.libcallpc != 0 && mp.libcallsp != 0 {
+			// Libcall, i.e. runtime syscall on windows.
+			// Collect Go stack that leads to the call.
+			if gcTryLockStackBarriers(mp.libcallg.ptr()) {
+				n = gentraceback(mp.libcallpc, mp.libcallsp, 0, mp.libcallg.ptr(), 0, &stk[0], len(stk), nil, nil, 0)
+				gcUnlockStackBarriers(mp.libcallg.ptr())
+			}
+		}
+		if n == 0 {
+			// If all of the above has failed, account it against abstract "System" or "GC".
+			n = 2
+			// "ExternalCode" is better than "etext".
+			if pc > firstmoduledata.etext {
+				pc = funcPC(_ExternalCode) + sys.PCQuantum
+			}
+			stk[0] = pc
+			if mp.preemptoff != "" || mp.helpgc != 0 {
+				stk[1] = funcPC(_GC) + sys.PCQuantum
+			} else {
+				stk[1] = funcPC(_System) + sys.PCQuantum
+			}
+		}
+	}
+
+	if prof.hz != 0 {
+		// Simple cas-lock to coordinate with setcpuprofilerate.
+		for !atomic.Cas(&prof.lock, 0, 1) {
+			osyield()
+		}
+		if prof.hz != 0 {
+			cpuprof.add(stk[:n])
+		}
+		atomic.Store(&prof.lock, 0)
+	}
+	mp.mallocing--
+}
+
+// Reports whether a function will set the SP
+// to an absolute value. Important that
+// we don't traceback when these are at the bottom
+// of the stack since we can't be sure that we will
+// find the caller.
+//
+// If the function is not on the bottom of the stack
+// we assume that it will have set it up so that traceback will be consistent,
+// either by being a traceback terminating function
+// or putting one on the stack at the right offset.
+func setsSP(pc uintptr) bool {
+	f := findfunc(pc)
+	if f == nil {
+		// couldn't find the function for this PC,
+		// so assume the worst and stop traceback
+		return true
+	}
+	switch f.entry {
+	case gogoPC, systemstackPC, mcallPC, morestackPC:
+		return true
+	}
+	return false
+}
+
+// Arrange to call fn with a traceback hz times a second.
+func setcpuprofilerate_m(hz int32) {
+	// Force sane arguments.
+	if hz < 0 {
+		hz = 0
+	}
+
+	// Disable preemption, otherwise we can be rescheduled to another thread
+	// that has profiling enabled.
+	_g_ := getg()
+	_g_.m.locks++
+
+	// Stop profiler on this thread so that it is safe to lock prof.
+	// if a profiling signal came in while we had prof locked,
+	// it would deadlock.
+	resetcpuprofiler(0)
+
+	for !atomic.Cas(&prof.lock, 0, 1) {
+		osyield()
+	}
+	prof.hz = hz
+	atomic.Store(&prof.lock, 0)
+
+	lock(&sched.lock)
+	sched.profilehz = hz
+	unlock(&sched.lock)
+
+	if hz != 0 {
+		resetcpuprofiler(hz)
+	}
+
+	_g_.m.locks--
+}
+
+// Change number of processors.  The world is stopped, sched is locked.
+// gcworkbufs are not being modified by either the GC or
+// the write barrier code.
+// Returns list of Ps with local work, they need to be scheduled by the caller.
+func procresize(nprocs int32) *p {
+	old := gomaxprocs
+	if old < 0 || old > _MaxGomaxprocs || nprocs <= 0 || nprocs > _MaxGomaxprocs {
+		throw("procresize: invalid arg")
+	}
+	if trace.enabled {
+		traceGomaxprocs(nprocs)
+	}
+
+	// update statistics
+	now := nanotime()
+	if sched.procresizetime != 0 {
+		sched.totaltime += int64(old) * (now - sched.procresizetime)
+	}
+	sched.procresizetime = now
+
+	// initialize new P's
+	for i := int32(0); i < nprocs; i++ {
+		pp := allp[i]
+		if pp == nil {
+			pp = new(p)
+			pp.id = i
+			pp.status = _Pgcstop
+			pp.sudogcache = pp.sudogbuf[:0]
+			for i := range pp.deferpool {
+				pp.deferpool[i] = pp.deferpoolbuf[i][:0]
+			}
+			atomicstorep(unsafe.Pointer(&allp[i]), unsafe.Pointer(pp))
+		}
+		if pp.mcache == nil {
+			if old == 0 && i == 0 {
+				if getg().m.mcache == nil {
+					throw("missing mcache?")
+				}
+				pp.mcache = getg().m.mcache // bootstrap
+			} else {
+				pp.mcache = allocmcache()
+			}
+		}
+	}
+
+	// free unused P's
+	for i := nprocs; i < old; i++ {
+		p := allp[i]
+		if trace.enabled {
+			if p == getg().m.p.ptr() {
+				// moving to p[0], pretend that we were descheduled
+				// and then scheduled again to keep the trace sane.
+				traceGoSched()
+				traceProcStop(p)
+			}
+		}
+		// move all runnable goroutines to the global queue
+		for p.runqhead != p.runqtail {
+			// pop from tail of local queue
+			p.runqtail--
+			gp := p.runq[p.runqtail%uint32(len(p.runq))].ptr()
+			// push onto head of global queue
+			globrunqputhead(gp)
+		}
+		if p.runnext != 0 {
+			globrunqputhead(p.runnext.ptr())
+			p.runnext = 0
+		}
+		// if there's a background worker, make it runnable and put
+		// it on the global queue so it can clean itself up
+		if gp := p.gcBgMarkWorker.ptr(); gp != nil {
+			casgstatus(gp, _Gwaiting, _Grunnable)
+			if trace.enabled {
+				traceGoUnpark(gp, 0)
+			}
+			globrunqput(gp)
+			// This assignment doesn't race because the
+			// world is stopped.
+			p.gcBgMarkWorker.set(nil)
+		}
+		for i := range p.sudogbuf {
+			p.sudogbuf[i] = nil
+		}
+		p.sudogcache = p.sudogbuf[:0]
+		for i := range p.deferpool {
+			for j := range p.deferpoolbuf[i] {
+				p.deferpoolbuf[i][j] = nil
+			}
+			p.deferpool[i] = p.deferpoolbuf[i][:0]
+		}
+		freemcache(p.mcache)
+		p.mcache = nil
+		gfpurge(p)
+		traceProcFree(p)
+		p.status = _Pdead
+		// can't free P itself because it can be referenced by an M in syscall
+	}
+
+	_g_ := getg()
+	if _g_.m.p != 0 && _g_.m.p.ptr().id < nprocs {
+		// continue to use the current P
+		_g_.m.p.ptr().status = _Prunning
+	} else {
+		// release the current P and acquire allp[0]
+		if _g_.m.p != 0 {
+			_g_.m.p.ptr().m = 0
+		}
+		_g_.m.p = 0
+		_g_.m.mcache = nil
+		p := allp[0]
+		p.m = 0
+		p.status = _Pidle
+		acquirep(p)
+		if trace.enabled {
+			traceGoStart()
+		}
+	}
+	var runnablePs *p
+	for i := nprocs - 1; i >= 0; i-- {
+		p := allp[i]
+		if _g_.m.p.ptr() == p {
+			continue
+		}
+		p.status = _Pidle
+		if runqempty(p) {
+			pidleput(p)
+		} else {
+			p.m.set(mget())
+			p.link.set(runnablePs)
+			runnablePs = p
+		}
+	}
+	var int32p *int32 = &gomaxprocs // make compiler check that gomaxprocs is an int32
+	atomic.Store((*uint32)(unsafe.Pointer(int32p)), uint32(nprocs))
+	return runnablePs
+}
+
+// Associate p and the current m.
+func acquirep(_p_ *p) {
+	acquirep1(_p_)
+
+	// have p; write barriers now allowed
+	_g_ := getg()
+	_g_.m.mcache = _p_.mcache
+
+	if trace.enabled {
+		traceProcStart()
+	}
+}
+
+// May run during STW, so write barriers are not allowed.
+//go:nowritebarrier
+func acquirep1(_p_ *p) {
+	_g_ := getg()
+
+	if _g_.m.p != 0 || _g_.m.mcache != nil {
+		throw("acquirep: already in go")
+	}
+	if _p_.m != 0 || _p_.status != _Pidle {
+		id := int32(0)
+		if _p_.m != 0 {
+			id = _p_.m.ptr().id
+		}
+		print("acquirep: p->m=", _p_.m, "(", id, ") p->status=", _p_.status, "\n")
+		throw("acquirep: invalid p state")
+	}
+	_g_.m.p.set(_p_)
+	_p_.m.set(_g_.m)
+	_p_.status = _Prunning
+}
+
+// Disassociate p and the current m.
+func releasep() *p {
+	_g_ := getg()
+
+	if _g_.m.p == 0 || _g_.m.mcache == nil {
+		throw("releasep: invalid arg")
+	}
+	_p_ := _g_.m.p.ptr()
+	if _p_.m.ptr() != _g_.m || _p_.mcache != _g_.m.mcache || _p_.status != _Prunning {
+		print("releasep: m=", _g_.m, " m->p=", _g_.m.p.ptr(), " p->m=", _p_.m, " m->mcache=", _g_.m.mcache, " p->mcache=", _p_.mcache, " p->status=", _p_.status, "\n")
+		throw("releasep: invalid p state")
+	}
+	if trace.enabled {
+		traceProcStop(_g_.m.p.ptr())
+	}
+	_g_.m.p = 0
+	_g_.m.mcache = nil
+	_p_.m = 0
+	_p_.status = _Pidle
+	return _p_
+}
+
+func incidlelocked(v int32) {
+	lock(&sched.lock)
+	sched.nmidlelocked += v
+	if v > 0 {
+		checkdead()
+	}
+	unlock(&sched.lock)
+}
+
+// Check for deadlock situation.
+// The check is based on number of running M's, if 0 -> deadlock.
+func checkdead() {
+	// For -buildmode=c-shared or -buildmode=c-archive it's OK if
+	// there are no running goroutines.  The calling program is
+	// assumed to be running.
+	if islibrary || isarchive {
+		return
+	}
+
+	// If we are dying because of a signal caught on an already idle thread,
+	// freezetheworld will cause all running threads to block.
+	// And runtime will essentially enter into deadlock state,
+	// except that there is a thread that will call exit soon.
+	if panicking > 0 {
+		return
+	}
+
+	// -1 for sysmon
+	run := sched.mcount - sched.nmidle - sched.nmidlelocked - 1
+	if run > 0 {
+		return
+	}
+	if run < 0 {
+		print("runtime: checkdead: nmidle=", sched.nmidle, " nmidlelocked=", sched.nmidlelocked, " mcount=", sched.mcount, "\n")
+		throw("checkdead: inconsistent counts")
+	}
+
+	grunning := 0
+	lock(&allglock)
+	for i := 0; i < len(allgs); i++ {
+		gp := allgs[i]
+		if isSystemGoroutine(gp) {
+			continue
+		}
+		s := readgstatus(gp)
+		switch s &^ _Gscan {
+		case _Gwaiting:
+			grunning++
+		case _Grunnable,
+			_Grunning,
+			_Gsyscall:
+			unlock(&allglock)
+			print("runtime: checkdead: find g ", gp.goid, " in status ", s, "\n")
+			throw("checkdead: runnable g")
+		}
+	}
+	unlock(&allglock)
+	if grunning == 0 { // possible if main goroutine calls runtime·Goexit()
+		throw("no goroutines (main called runtime.Goexit) - deadlock!")
+	}
+
+	// Maybe jump time forward for playground.
+	gp := timejump()
+	if gp != nil {
+		casgstatus(gp, _Gwaiting, _Grunnable)
+		globrunqput(gp)
+		_p_ := pidleget()
+		if _p_ == nil {
+			throw("checkdead: no p for timer")
+		}
+		mp := mget()
+		if mp == nil {
+			// There should always be a free M since
+			// nothing is running.
+			throw("checkdead: no m for timer")
+		}
+		mp.nextp.set(_p_)
+		notewakeup(&mp.park)
+		return
+	}
+
+	getg().m.throwing = -1 // do not dump full stacks
+	throw("all goroutines are asleep - deadlock!")
+}
+
+// forcegcperiod is the maximum time in nanoseconds between garbage
+// collections. If we go this long without a garbage collection, one
+// is forced to run.
+//
+// This is a variable for testing purposes. It normally doesn't change.
+var forcegcperiod int64 = 2 * 60 * 1e9
+
+// Always runs without a P, so write barriers are not allowed.
+//
+//go:nowritebarrierrec
+func sysmon() {
+	// If a heap span goes unused for 5 minutes after a garbage collection,
+	// we hand it back to the operating system.
+	scavengelimit := int64(5 * 60 * 1e9)
+
+	if debug.scavenge > 0 {
+		// Scavenge-a-lot for testing.
+		forcegcperiod = 10 * 1e6
+		scavengelimit = 20 * 1e6
+	}
+
+	lastscavenge := nanotime()
+	nscavenge := 0
+
+	lasttrace := int64(0)
+	idle := 0 // how many cycles in succession we had not wokeup somebody
+	delay := uint32(0)
+	for {
+		if idle == 0 { // start with 20us sleep...
+			delay = 20
+		} else if idle > 50 { // start doubling the sleep after 1ms...
+			delay *= 2
+		}
+		if delay > 10*1000 { // up to 10ms
+			delay = 10 * 1000
+		}
+		usleep(delay)
+		if debug.schedtrace <= 0 && (sched.gcwaiting != 0 || atomic.Load(&sched.npidle) == uint32(gomaxprocs)) { // TODO: fast atomic
+			lock(&sched.lock)
+			if atomic.Load(&sched.gcwaiting) != 0 || atomic.Load(&sched.npidle) == uint32(gomaxprocs) {
+				atomic.Store(&sched.sysmonwait, 1)
+				unlock(&sched.lock)
+				// Make wake-up period small enough
+				// for the sampling to be correct.
+				maxsleep := forcegcperiod / 2
+				if scavengelimit < forcegcperiod {
+					maxsleep = scavengelimit / 2
+				}
+				notetsleep(&sched.sysmonnote, maxsleep)
+				lock(&sched.lock)
+				atomic.Store(&sched.sysmonwait, 0)
+				noteclear(&sched.sysmonnote)
+				idle = 0
+				delay = 20
+			}
+			unlock(&sched.lock)
+		}
+		// poll network if not polled for more than 10ms
+		lastpoll := int64(atomic.Load64(&sched.lastpoll))
+		now := nanotime()
+		unixnow := unixnanotime()
+		if lastpoll != 0 && lastpoll+10*1000*1000 < now {
+			atomic.Cas64(&sched.lastpoll, uint64(lastpoll), uint64(now))
+			gp := netpoll(false) // non-blocking - returns list of goroutines
+			if gp != nil {
+				// Need to decrement number of idle locked M's
+				// (pretending that one more is running) before injectglist.
+				// Otherwise it can lead to the following situation:
+				// injectglist grabs all P's but before it starts M's to run the P's,
+				// another M returns from syscall, finishes running its G,
+				// observes that there is no work to do and no other running M's
+				// and reports deadlock.
+				incidlelocked(-1)
+				injectglist(gp)
+				incidlelocked(1)
+			}
+		}
+		// retake P's blocked in syscalls
+		// and preempt long running G's
+		if retake(now) != 0 {
+			idle = 0
+		} else {
+			idle++
+		}
+		// check if we need to force a GC
+		lastgc := int64(atomic.Load64(&memstats.last_gc))
+		if gcphase == _GCoff && lastgc != 0 && unixnow-lastgc > forcegcperiod && atomic.Load(&forcegc.idle) != 0 {
+			lock(&forcegc.lock)
+			forcegc.idle = 0
+			forcegc.g.schedlink = 0
+			injectglist(forcegc.g)
+			unlock(&forcegc.lock)
+		}
+		// scavenge heap once in a while
+		if lastscavenge+scavengelimit/2 < now {
+			mheap_.scavenge(int32(nscavenge), uint64(now), uint64(scavengelimit))
+			lastscavenge = now
+			nscavenge++
+		}
+		if debug.schedtrace > 0 && lasttrace+int64(debug.schedtrace)*1000000 <= now {
+			lasttrace = now
+			schedtrace(debug.scheddetail > 0)
+		}
+	}
+}
+
+var pdesc [_MaxGomaxprocs]struct {
+	schedtick   uint32
+	schedwhen   int64
+	syscalltick uint32
+	syscallwhen int64
+}
+
+// forcePreemptNS is the time slice given to a G before it is
+// preempted.
+const forcePreemptNS = 10 * 1000 * 1000 // 10ms
+
+func retake(now int64) uint32 {
+	n := 0
+	for i := int32(0); i < gomaxprocs; i++ {
+		_p_ := allp[i]
+		if _p_ == nil {
+			continue
+		}
+		pd := &pdesc[i]
+		s := _p_.status
+		if s == _Psyscall {
+			// Retake P from syscall if it's there for more than 1 sysmon tick (at least 20us).
+			t := int64(_p_.syscalltick)
+			if int64(pd.syscalltick) != t {
+				pd.syscalltick = uint32(t)
+				pd.syscallwhen = now
+				continue
+			}
+			// On the one hand we don't want to retake Ps if there is no other work to do,
+			// but on the other hand we want to retake them eventually
+			// because they can prevent the sysmon thread from deep sleep.
+			if runqempty(_p_) && atomic.Load(&sched.nmspinning)+atomic.Load(&sched.npidle) > 0 && pd.syscallwhen+10*1000*1000 > now {
+				continue
+			}
+			// Need to decrement number of idle locked M's
+			// (pretending that one more is running) before the CAS.
+			// Otherwise the M from which we retake can exit the syscall,
+			// increment nmidle and report deadlock.
+			incidlelocked(-1)
+			if atomic.Cas(&_p_.status, s, _Pidle) {
+				if trace.enabled {
+					traceGoSysBlock(_p_)
+					traceProcStop(_p_)
+				}
+				n++
+				_p_.syscalltick++
+				handoffp(_p_)
+			}
+			incidlelocked(1)
+		} else if s == _Prunning {
+			// Preempt G if it's running for too long.
+			t := int64(_p_.schedtick)
+			if int64(pd.schedtick) != t {
+				pd.schedtick = uint32(t)
+				pd.schedwhen = now
+				continue
+			}
+			if pd.schedwhen+forcePreemptNS > now {
+				continue
+			}
+			preemptone(_p_)
+		}
+	}
+	return uint32(n)
+}
+
+// Tell all goroutines that they have been preempted and they should stop.
+// This function is purely best-effort.  It can fail to inform a goroutine if a
+// processor just started running it.
+// No locks need to be held.
+// Returns true if preemption request was issued to at least one goroutine.
+func preemptall() bool {
+	res := false
+	for i := int32(0); i < gomaxprocs; i++ {
+		_p_ := allp[i]
+		if _p_ == nil || _p_.status != _Prunning {
+			continue
+		}
+		if preemptone(_p_) {
+			res = true
+		}
+	}
+	return res
+}
+
+// Tell the goroutine running on processor P to stop.
+// This function is purely best-effort.  It can incorrectly fail to inform the
+// goroutine.  It can send inform the wrong goroutine.  Even if it informs the
+// correct goroutine, that goroutine might ignore the request if it is
+// simultaneously executing newstack.
+// No lock needs to be held.
+// Returns true if preemption request was issued.
+// The actual preemption will happen at some point in the future
+// and will be indicated by the gp->status no longer being
+// Grunning
+func preemptone(_p_ *p) bool {
+	mp := _p_.m.ptr()
+	if mp == nil || mp == getg().m {
+		return false
+	}
+	gp := mp.curg
+	if gp == nil || gp == mp.g0 {
+		return false
+	}
+
+	gp.preempt = true
+
+	// Every call in a go routine checks for stack overflow by
+	// comparing the current stack pointer to gp->stackguard0.
+	// Setting gp->stackguard0 to StackPreempt folds
+	// preemption into the normal stack overflow check.
+	gp.stackguard0 = stackPreempt
+	return true
+}
+
+var starttime int64
+
+func schedtrace(detailed bool) {
+	now := nanotime()
+	if starttime == 0 {
+		starttime = now
+	}
+
+	lock(&sched.lock)
+	print("SCHED ", (now-starttime)/1e6, "ms: gomaxprocs=", gomaxprocs, " idleprocs=", sched.npidle, " threads=", sched.mcount, " spinningthreads=", sched.nmspinning, " idlethreads=", sched.nmidle, " runqueue=", sched.runqsize)
+	if detailed {
+		print(" gcwaiting=", sched.gcwaiting, " nmidlelocked=", sched.nmidlelocked, " stopwait=", sched.stopwait, " sysmonwait=", sched.sysmonwait, "\n")
+	}
+	// We must be careful while reading data from P's, M's and G's.
+	// Even if we hold schedlock, most data can be changed concurrently.
+	// E.g. (p->m ? p->m->id : -1) can crash if p->m changes from non-nil to nil.
+	for i := int32(0); i < gomaxprocs; i++ {
+		_p_ := allp[i]
+		if _p_ == nil {
+			continue
+		}
+		mp := _p_.m.ptr()
+		h := atomic.Load(&_p_.runqhead)
+		t := atomic.Load(&_p_.runqtail)
+		if detailed {
+			id := int32(-1)
+			if mp != nil {
+				id = mp.id
+			}
+			print("  P", i, ": status=", _p_.status, " schedtick=", _p_.schedtick, " syscalltick=", _p_.syscalltick, " m=", id, " runqsize=", t-h, " gfreecnt=", _p_.gfreecnt, "\n")
+		} else {
+			// In non-detailed mode format lengths of per-P run queues as:
+			// [len1 len2 len3 len4]
+			print(" ")
+			if i == 0 {
+				print("[")
+			}
+			print(t - h)
+			if i == gomaxprocs-1 {
+				print("]\n")
+			}
+		}
+	}
+
+	if !detailed {
+		unlock(&sched.lock)
+		return
+	}
+
+	for mp := allm; mp != nil; mp = mp.alllink {
+		_p_ := mp.p.ptr()
+		gp := mp.curg
+		lockedg := mp.lockedg
+		id1 := int32(-1)
+		if _p_ != nil {
+			id1 = _p_.id
+		}
+		id2 := int64(-1)
+		if gp != nil {
+			id2 = gp.goid
+		}
+		id3 := int64(-1)
+		if lockedg != nil {
+			id3 = lockedg.goid
+		}
+		print("  M", mp.id, ": p=", id1, " curg=", id2, " mallocing=", mp.mallocing, " throwing=", mp.throwing, " preemptoff=", mp.preemptoff, ""+" locks=", mp.locks, " dying=", mp.dying, " helpgc=", mp.helpgc, " spinning=", mp.spinning, " blocked=", getg().m.blocked, " lockedg=", id3, "\n")
+	}
+
+	lock(&allglock)
+	for gi := 0; gi < len(allgs); gi++ {
+		gp := allgs[gi]
+		mp := gp.m
+		lockedm := gp.lockedm
+		id1 := int32(-1)
+		if mp != nil {
+			id1 = mp.id
+		}
+		id2 := int32(-1)
+		if lockedm != nil {
+			id2 = lockedm.id
+		}
+		print("  G", gp.goid, ": status=", readgstatus(gp), "(", gp.waitreason, ") m=", id1, " lockedm=", id2, "\n")
+	}
+	unlock(&allglock)
+	unlock(&sched.lock)
+}
+
+// Put mp on midle list.
+// Sched must be locked.
+// May run during STW, so write barriers are not allowed.
+//go:nowritebarrier
+func mput(mp *m) {
+	mp.schedlink = sched.midle
+	sched.midle.set(mp)
+	sched.nmidle++
+	checkdead()
+}
+
+// Try to get an m from midle list.
+// Sched must be locked.
+// May run during STW, so write barriers are not allowed.
+//go:nowritebarrier
+func mget() *m {
+	mp := sched.midle.ptr()
+	if mp != nil {
+		sched.midle = mp.schedlink
+		sched.nmidle--
+	}
+	return mp
+}
+
+// Put gp on the global runnable queue.
+// Sched must be locked.
+// May run during STW, so write barriers are not allowed.
+//go:nowritebarrier
+func globrunqput(gp *g) {
+	gp.schedlink = 0
+	if sched.runqtail != 0 {
+		sched.runqtail.ptr().schedlink.set(gp)
+	} else {
+		sched.runqhead.set(gp)
+	}
+	sched.runqtail.set(gp)
+	sched.runqsize++
+}
+
+// Put gp at the head of the global runnable queue.
+// Sched must be locked.
+// May run during STW, so write barriers are not allowed.
+//go:nowritebarrier
+func globrunqputhead(gp *g) {
+	gp.schedlink = sched.runqhead
+	sched.runqhead.set(gp)
+	if sched.runqtail == 0 {
+		sched.runqtail.set(gp)
+	}
+	sched.runqsize++
+}
+
+// Put a batch of runnable goroutines on the global runnable queue.
+// Sched must be locked.
+func globrunqputbatch(ghead *g, gtail *g, n int32) {
+	gtail.schedlink = 0
+	if sched.runqtail != 0 {
+		sched.runqtail.ptr().schedlink.set(ghead)
+	} else {
+		sched.runqhead.set(ghead)
+	}
+	sched.runqtail.set(gtail)
+	sched.runqsize += n
+}
+
+// Try get a batch of G's from the global runnable queue.
+// Sched must be locked.
+func globrunqget(_p_ *p, max int32) *g {
+	if sched.runqsize == 0 {
+		return nil
+	}
+
+	n := sched.runqsize/gomaxprocs + 1
+	if n > sched.runqsize {
+		n = sched.runqsize
+	}
+	if max > 0 && n > max {
+		n = max
+	}
+	if n > int32(len(_p_.runq))/2 {
+		n = int32(len(_p_.runq)) / 2
+	}
+
+	sched.runqsize -= n
+	if sched.runqsize == 0 {
+		sched.runqtail = 0
+	}
+
+	gp := sched.runqhead.ptr()
+	sched.runqhead = gp.schedlink
+	n--
+	for ; n > 0; n-- {
+		gp1 := sched.runqhead.ptr()
+		sched.runqhead = gp1.schedlink
+		runqput(_p_, gp1, false)
+	}
+	return gp
+}
+
+// Put p to on _Pidle list.
+// Sched must be locked.
+// May run during STW, so write barriers are not allowed.
+//go:nowritebarrier
+func pidleput(_p_ *p) {
+	if !runqempty(_p_) {
+		throw("pidleput: P has non-empty run queue")
+	}
+	_p_.link = sched.pidle
+	sched.pidle.set(_p_)
+	atomic.Xadd(&sched.npidle, 1) // TODO: fast atomic
+}
+
+// Try get a p from _Pidle list.
+// Sched must be locked.
+// May run during STW, so write barriers are not allowed.
+//go:nowritebarrier
+func pidleget() *p {
+	_p_ := sched.pidle.ptr()
+	if _p_ != nil {
+		sched.pidle = _p_.link
+		atomic.Xadd(&sched.npidle, -1) // TODO: fast atomic
+	}
+	return _p_
+}
+
+// runqempty returns true if _p_ has no Gs on its local run queue.
+// Note that this test is generally racy.
+func runqempty(_p_ *p) bool {
+	return _p_.runqhead == _p_.runqtail && _p_.runnext == 0
+}
+
+// To shake out latent assumptions about scheduling order,
+// we introduce some randomness into scheduling decisions
+// when running with the race detector.
+// The need for this was made obvious by changing the
+// (deterministic) scheduling order in Go 1.5 and breaking
+// many poorly-written tests.
+// With the randomness here, as long as the tests pass
+// consistently with -race, they shouldn't have latent scheduling
+// assumptions.
+const randomizeScheduler = raceenabled
+
+// runqput tries to put g on the local runnable queue.
+// If next if false, runqput adds g to the tail of the runnable queue.
+// If next is true, runqput puts g in the _p_.runnext slot.
+// If the run queue is full, runnext puts g on the global queue.
+// Executed only by the owner P.
+func runqput(_p_ *p, gp *g, next bool) {
+	if randomizeScheduler && next && fastrand1()%2 == 0 {
+		next = false
+	}
+
+	if next {
+	retryNext:
+		oldnext := _p_.runnext
+		if !_p_.runnext.cas(oldnext, guintptr(unsafe.Pointer(gp))) {
+			goto retryNext
+		}
+		if oldnext == 0 {
+			return
+		}
+		// Kick the old runnext out to the regular run queue.
+		gp = oldnext.ptr()
+	}
+
+retry:
+	h := atomic.Load(&_p_.runqhead) // load-acquire, synchronize with consumers
+	t := _p_.runqtail
+	if t-h < uint32(len(_p_.runq)) {
+		_p_.runq[t%uint32(len(_p_.runq))].set(gp)
+		atomic.Store(&_p_.runqtail, t+1) // store-release, makes the item available for consumption
+		return
+	}
+	if runqputslow(_p_, gp, h, t) {
+		return
+	}
+	// the queue is not full, now the put above must suceed
+	goto retry
+}
+
+// Put g and a batch of work from local runnable queue on global queue.
+// Executed only by the owner P.
+func runqputslow(_p_ *p, gp *g, h, t uint32) bool {
+	var batch [len(_p_.runq)/2 + 1]*g
+
+	// First, grab a batch from local queue.
+	n := t - h
+	n = n / 2
+	if n != uint32(len(_p_.runq)/2) {
+		throw("runqputslow: queue is not full")
+	}
+	for i := uint32(0); i < n; i++ {
+		batch[i] = _p_.runq[(h+i)%uint32(len(_p_.runq))].ptr()
+	}
+	if !atomic.Cas(&_p_.runqhead, h, h+n) { // cas-release, commits consume
+		return false
+	}
+	batch[n] = gp
+
+	if randomizeScheduler {
+		for i := uint32(1); i <= n; i++ {
+			j := fastrand1() % (i + 1)
+			batch[i], batch[j] = batch[j], batch[i]
+		}
+	}
+
+	// Link the goroutines.
+	for i := uint32(0); i < n; i++ {
+		batch[i].schedlink.set(batch[i+1])
+	}
+
+	// Now put the batch on global queue.
+	lock(&sched.lock)
+	globrunqputbatch(batch[0], batch[n], int32(n+1))
+	unlock(&sched.lock)
+	return true
+}
+
+// Get g from local runnable queue.
+// If inheritTime is true, gp should inherit the remaining time in the
+// current time slice. Otherwise, it should start a new time slice.
+// Executed only by the owner P.
+func runqget(_p_ *p) (gp *g, inheritTime bool) {
+	// If there's a runnext, it's the next G to run.
+	for {
+		next := _p_.runnext
+		if next == 0 {
+			break
+		}
+		if _p_.runnext.cas(next, 0) {
+			return next.ptr(), true
+		}
+	}
+
+	for {
+		h := atomic.Load(&_p_.runqhead) // load-acquire, synchronize with other consumers
+		t := _p_.runqtail
+		if t == h {
+			return nil, false
+		}
+		gp := _p_.runq[h%uint32(len(_p_.runq))].ptr()
+		if atomic.Cas(&_p_.runqhead, h, h+1) { // cas-release, commits consume
+			return gp, false
+		}
+	}
+}
+
+// Grabs a batch of goroutines from _p_'s runnable queue into batch.
+// Batch is a ring buffer starting at batchHead.
+// Returns number of grabbed goroutines.
+// Can be executed by any P.
+func runqgrab(_p_ *p, batch *[256]guintptr, batchHead uint32, stealRunNextG bool) uint32 {
+	for {
+		h := atomic.Load(&_p_.runqhead) // load-acquire, synchronize with other consumers
+		t := atomic.Load(&_p_.runqtail) // load-acquire, synchronize with the producer
+		n := t - h
+		n = n - n/2
+		if n == 0 {
+			if stealRunNextG {
+				// Try to steal from _p_.runnext.
+				if next := _p_.runnext; next != 0 {
+					// Sleep to ensure that _p_ isn't about to run the g we
+					// are about to steal.
+					// The important use case here is when the g running on _p_
+					// ready()s another g and then almost immediately blocks.
+					// Instead of stealing runnext in this window, back off
+					// to give _p_ a chance to schedule runnext. This will avoid
+					// thrashing gs between different Ps.
+					usleep(100)
+					if !_p_.runnext.cas(next, 0) {
+						continue
+					}
+					batch[batchHead%uint32(len(batch))] = next
+					return 1
+				}
+			}
+			return 0
+		}
+		if n > uint32(len(_p_.runq)/2) { // read inconsistent h and t
+			continue
+		}
+		for i := uint32(0); i < n; i++ {
+			g := _p_.runq[(h+i)%uint32(len(_p_.runq))]
+			batch[(batchHead+i)%uint32(len(batch))] = g
+		}
+		if atomic.Cas(&_p_.runqhead, h, h+n) { // cas-release, commits consume
+			return n
+		}
+	}
+}
+
+// Steal half of elements from local runnable queue of p2
+// and put onto local runnable queue of p.
+// Returns one of the stolen elements (or nil if failed).
+func runqsteal(_p_, p2 *p, stealRunNextG bool) *g {
+	t := _p_.runqtail
+	n := runqgrab(p2, &_p_.runq, t, stealRunNextG)
+	if n == 0 {
+		return nil
+	}
+	n--
+	gp := _p_.runq[(t+n)%uint32(len(_p_.runq))].ptr()
+	if n == 0 {
+		return gp
+	}
+	h := atomic.Load(&_p_.runqhead) // load-acquire, synchronize with consumers
+	if t-h+n >= uint32(len(_p_.runq)) {
+		throw("runqsteal: runq overflow")
+	}
+	atomic.Store(&_p_.runqtail, t+n) // store-release, makes the item available for consumption
+	return gp
+}
+
+func testSchedLocalQueue() {
+	_p_ := new(p)
+	gs := make([]g, len(_p_.runq))
+	for i := 0; i < len(_p_.runq); i++ {
+		if g, _ := runqget(_p_); g != nil {
+			throw("runq is not empty initially")
+		}
+		for j := 0; j < i; j++ {
+			runqput(_p_, &gs[i], false)
+		}
+		for j := 0; j < i; j++ {
+			if g, _ := runqget(_p_); g != &gs[i] {
+				print("bad element at iter ", i, "/", j, "\n")
+				throw("bad element")
+			}
+		}
+		if g, _ := runqget(_p_); g != nil {
+			throw("runq is not empty afterwards")
+		}
+	}
+}
+
+func testSchedLocalQueueSteal() {
+	p1 := new(p)
+	p2 := new(p)
+	gs := make([]g, len(p1.runq))
+	for i := 0; i < len(p1.runq); i++ {
+		for j := 0; j < i; j++ {
+			gs[j].sig = 0
+			runqput(p1, &gs[j], false)
+		}
+		gp := runqsteal(p2, p1, true)
+		s := 0
+		if gp != nil {
+			s++
+			gp.sig++
+		}
+		for {
+			gp, _ = runqget(p2)
+			if gp == nil {
+				break
+			}
+			s++
+			gp.sig++
+		}
+		for {
+			gp, _ = runqget(p1)
+			if gp == nil {
+				break
+			}
+			gp.sig++
+		}
+		for j := 0; j < i; j++ {
+			if gs[j].sig != 1 {
+				print("bad element ", j, "(", gs[j].sig, ") at iter ", i, "\n")
+				throw("bad element")
+			}
+		}
+		if s != i/2 && s != i/2+1 {
+			print("bad steal ", s, ", want ", i/2, " or ", i/2+1, ", iter ", i, "\n")
+			throw("bad steal")
+		}
+	}
+}
+
+//go:linkname setMaxThreads runtime/debug.setMaxThreads
+func setMaxThreads(in int) (out int) {
+	lock(&sched.lock)
+	out = int(sched.maxmcount)
+	sched.maxmcount = int32(in)
+	checkmcount()
+	unlock(&sched.lock)
+	return
+}
+
+func haveexperiment(name string) bool {
+	x := sys.Goexperiment
+	for x != "" {
+		xname := ""
+		i := index(x, ",")
+		if i < 0 {
+			xname, x = x, ""
+		} else {
+			xname, x = x[:i], x[i+1:]
+		}
+		if xname == name {
+			return true
+		}
+	}
+	return false
+}
+
+//go:nosplit
+func procPin() int {
+	_g_ := getg()
+	mp := _g_.m
+
+	mp.locks++
+	return int(mp.p.ptr().id)
+}
+
+//go:nosplit
+func procUnpin() {
+	_g_ := getg()
+	_g_.m.locks--
+}
+
+//go:linkname sync_runtime_procPin sync.runtime_procPin
+//go:nosplit
+func sync_runtime_procPin() int {
+	return procPin()
+}
+
+//go:linkname sync_runtime_procUnpin sync.runtime_procUnpin
+//go:nosplit
+func sync_runtime_procUnpin() {
+	procUnpin()
+}
+
+//go:linkname sync_atomic_runtime_procPin sync/atomic.runtime_procPin
+//go:nosplit
+func sync_atomic_runtime_procPin() int {
+	return procPin()
+}
+
+//go:linkname sync_atomic_runtime_procUnpin sync/atomic.runtime_procUnpin
+//go:nosplit
+func sync_atomic_runtime_procUnpin() {
+	procUnpin()
+}
+
+// Active spinning for sync.Mutex.
+//go:linkname sync_runtime_canSpin sync.runtime_canSpin
+//go:nosplit
+func sync_runtime_canSpin(i int) bool {
+	// sync.Mutex is cooperative, so we are conservative with spinning.
+	// Spin only few times and only if running on a multicore machine and
+	// GOMAXPROCS>1 and there is at least one other running P and local runq is empty.
+	// As opposed to runtime mutex we don't do passive spinning here,
+	// because there can be work on global runq on on other Ps.
+	if i >= active_spin || ncpu <= 1 || gomaxprocs <= int32(sched.npidle+sched.nmspinning)+1 {
+		return false
+	}
+	if p := getg().m.p.ptr(); !runqempty(p) {
+		return false
+	}
+	return true
+}
+
+//go:linkname sync_runtime_doSpin sync.runtime_doSpin
+//go:nosplit
+func sync_runtime_doSpin() {
+	procyield(active_spin_cnt)
+}
diff --git a/src/runtime/proc1.go b/src/runtime/proc1.go
deleted file mode 100644
index 72ab524..0000000
--- a/src/runtime/proc1.go
+++ /dev/null
@@ -1,3747 +0,0 @@
-// Copyright 2009 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 runtime
-
-import "unsafe"
-
-var (
-	m0 m
-	g0 g
-)
-
-// Goroutine scheduler
-// The scheduler's job is to distribute ready-to-run goroutines over worker threads.
-//
-// The main concepts are:
-// G - goroutine.
-// M - worker thread, or machine.
-// P - processor, a resource that is required to execute Go code.
-//     M must have an associated P to execute Go code, however it can be
-//     blocked or in a syscall w/o an associated P.
-//
-// Design doc at https://golang.org/s/go11sched.
-
-const (
-	// Number of goroutine ids to grab from sched.goidgen to local per-P cache at once.
-	// 16 seems to provide enough amortization, but other than that it's mostly arbitrary number.
-	_GoidCacheBatch = 16
-)
-
-// The bootstrap sequence is:
-//
-//	call osinit
-//	call schedinit
-//	make & queue new G
-//	call runtime·mstart
-//
-// The new G calls runtime·main.
-func schedinit() {
-	// raceinit must be the first call to race detector.
-	// In particular, it must be done before mallocinit below calls racemapshadow.
-	_g_ := getg()
-	if raceenabled {
-		_g_.racectx = raceinit()
-	}
-
-	sched.maxmcount = 10000
-
-	// Cache the framepointer experiment.  This affects stack unwinding.
-	framepointer_enabled = haveexperiment("framepointer")
-
-	tracebackinit()
-	moduledataverify()
-	stackinit()
-	mallocinit()
-	mcommoninit(_g_.m)
-
-	goargs()
-	goenvs()
-	parsedebugvars()
-	gcinit()
-
-	sched.lastpoll = uint64(nanotime())
-	procs := int(ncpu)
-	if n := atoi(gogetenv("GOMAXPROCS")); n > 0 {
-		if n > _MaxGomaxprocs {
-			n = _MaxGomaxprocs
-		}
-		procs = n
-	}
-	if procresize(int32(procs)) != nil {
-		throw("unknown runnable goroutine during bootstrap")
-	}
-
-	if buildVersion == "" {
-		// Condition should never trigger.  This code just serves
-		// to ensure runtime·buildVersion is kept in the resulting binary.
-		buildVersion = "unknown"
-	}
-}
-
-func dumpgstatus(gp *g) {
-	_g_ := getg()
-	print("runtime: gp: gp=", gp, ", goid=", gp.goid, ", gp->atomicstatus=", readgstatus(gp), "\n")
-	print("runtime:  g:  g=", _g_, ", goid=", _g_.goid, ",  g->atomicstatus=", readgstatus(_g_), "\n")
-}
-
-func checkmcount() {
-	// sched lock is held
-	if sched.mcount > sched.maxmcount {
-		print("runtime: program exceeds ", sched.maxmcount, "-thread limit\n")
-		throw("thread exhaustion")
-	}
-}
-
-func mcommoninit(mp *m) {
-	_g_ := getg()
-
-	// g0 stack won't make sense for user (and is not necessary unwindable).
-	if _g_ != _g_.m.g0 {
-		callers(1, mp.createstack[:])
-	}
-
-	mp.fastrand = 0x49f6428a + uint32(mp.id) + uint32(cputicks())
-	if mp.fastrand == 0 {
-		mp.fastrand = 0x49f6428a
-	}
-
-	lock(&sched.lock)
-	mp.id = sched.mcount
-	sched.mcount++
-	checkmcount()
-	mpreinit(mp)
-	if mp.gsignal != nil {
-		mp.gsignal.stackguard1 = mp.gsignal.stack.lo + _StackGuard
-	}
-
-	// Add to allm so garbage collector doesn't free g->m
-	// when it is just in a register or thread-local storage.
-	mp.alllink = allm
-
-	// NumCgoCall() iterates over allm w/o schedlock,
-	// so we need to publish it safely.
-	atomicstorep(unsafe.Pointer(&allm), unsafe.Pointer(mp))
-	unlock(&sched.lock)
-}
-
-// Mark gp ready to run.
-func ready(gp *g, traceskip int) {
-	if trace.enabled {
-		traceGoUnpark(gp, traceskip)
-	}
-
-	status := readgstatus(gp)
-
-	// Mark runnable.
-	_g_ := getg()
-	_g_.m.locks++ // disable preemption because it can be holding p in a local var
-	if status&^_Gscan != _Gwaiting {
-		dumpgstatus(gp)
-		throw("bad g->status in ready")
-	}
-
-	// status is Gwaiting or Gscanwaiting, make Grunnable and put on runq
-	casgstatus(gp, _Gwaiting, _Grunnable)
-	runqput(_g_.m.p.ptr(), gp, true)
-	if atomicload(&sched.npidle) != 0 && atomicload(&sched.nmspinning) == 0 { // TODO: fast atomic
-		wakep()
-	}
-	_g_.m.locks--
-	if _g_.m.locks == 0 && _g_.preempt { // restore the preemption request in case we've cleared it in newstack
-		_g_.stackguard0 = stackPreempt
-	}
-}
-
-func gcprocs() int32 {
-	// Figure out how many CPUs to use during GC.
-	// Limited by gomaxprocs, number of actual CPUs, and MaxGcproc.
-	lock(&sched.lock)
-	n := gomaxprocs
-	if n > ncpu {
-		n = ncpu
-	}
-	if n > _MaxGcproc {
-		n = _MaxGcproc
-	}
-	if n > sched.nmidle+1 { // one M is currently running
-		n = sched.nmidle + 1
-	}
-	unlock(&sched.lock)
-	return n
-}
-
-func needaddgcproc() bool {
-	lock(&sched.lock)
-	n := gomaxprocs
-	if n > ncpu {
-		n = ncpu
-	}
-	if n > _MaxGcproc {
-		n = _MaxGcproc
-	}
-	n -= sched.nmidle + 1 // one M is currently running
-	unlock(&sched.lock)
-	return n > 0
-}
-
-func helpgc(nproc int32) {
-	_g_ := getg()
-	lock(&sched.lock)
-	pos := 0
-	for n := int32(1); n < nproc; n++ { // one M is currently running
-		if allp[pos].mcache == _g_.m.mcache {
-			pos++
-		}
-		mp := mget()
-		if mp == nil {
-			throw("gcprocs inconsistency")
-		}
-		mp.helpgc = n
-		mp.p.set(allp[pos])
-		mp.mcache = allp[pos].mcache
-		pos++
-		notewakeup(&mp.park)
-	}
-	unlock(&sched.lock)
-}
-
-// freezeStopWait is a large value that freezetheworld sets
-// sched.stopwait to in order to request that all Gs permanently stop.
-const freezeStopWait = 0x7fffffff
-
-// Similar to stopTheWorld but best-effort and can be called several times.
-// There is no reverse operation, used during crashing.
-// This function must not lock any mutexes.
-func freezetheworld() {
-	// stopwait and preemption requests can be lost
-	// due to races with concurrently executing threads,
-	// so try several times
-	for i := 0; i < 5; i++ {
-		// this should tell the scheduler to not start any new goroutines
-		sched.stopwait = freezeStopWait
-		atomicstore(&sched.gcwaiting, 1)
-		// this should stop running goroutines
-		if !preemptall() {
-			break // no running goroutines
-		}
-		usleep(1000)
-	}
-	// to be sure
-	usleep(1000)
-	preemptall()
-	usleep(1000)
-}
-
-func isscanstatus(status uint32) bool {
-	if status == _Gscan {
-		throw("isscanstatus: Bad status Gscan")
-	}
-	return status&_Gscan == _Gscan
-}
-
-// All reads and writes of g's status go through readgstatus, casgstatus
-// castogscanstatus, casfrom_Gscanstatus.
-//go:nosplit
-func readgstatus(gp *g) uint32 {
-	return atomicload(&gp.atomicstatus)
-}
-
-// Ownership of gscanvalid:
-//
-// If gp is running (meaning status == _Grunning or _Grunning|_Gscan),
-// then gp owns gp.gscanvalid, and other goroutines must not modify it.
-//
-// Otherwise, a second goroutine can lock the scan state by setting _Gscan
-// in the status bit and then modify gscanvalid, and then unlock the scan state.
-//
-// Note that the first condition implies an exception to the second:
-// if a second goroutine changes gp's status to _Grunning|_Gscan,
-// that second goroutine still does not have the right to modify gscanvalid.
-
-// The Gscanstatuses are acting like locks and this releases them.
-// If it proves to be a performance hit we should be able to make these
-// simple atomic stores but for now we are going to throw if
-// we see an inconsistent state.
-func casfrom_Gscanstatus(gp *g, oldval, newval uint32) {
-	success := false
-
-	// Check that transition is valid.
-	switch oldval {
-	default:
-		print("runtime: casfrom_Gscanstatus bad oldval gp=", gp, ", oldval=", hex(oldval), ", newval=", hex(newval), "\n")
-		dumpgstatus(gp)
-		throw("casfrom_Gscanstatus:top gp->status is not in scan state")
-	case _Gscanrunnable,
-		_Gscanwaiting,
-		_Gscanrunning,
-		_Gscansyscall:
-		if newval == oldval&^_Gscan {
-			success = cas(&gp.atomicstatus, oldval, newval)
-		}
-	case _Gscanenqueue:
-		if newval == _Gwaiting {
-			success = cas(&gp.atomicstatus, oldval, newval)
-		}
-	}
-	if !success {
-		print("runtime: casfrom_Gscanstatus failed gp=", gp, ", oldval=", hex(oldval), ", newval=", hex(newval), "\n")
-		dumpgstatus(gp)
-		throw("casfrom_Gscanstatus: gp->status is not in scan state")
-	}
-	if newval == _Grunning {
-		gp.gcscanvalid = false
-	}
-}
-
-// This will return false if the gp is not in the expected status and the cas fails.
-// This acts like a lock acquire while the casfromgstatus acts like a lock release.
-func castogscanstatus(gp *g, oldval, newval uint32) bool {
-	switch oldval {
-	case _Grunnable,
-		_Gwaiting,
-		_Gsyscall:
-		if newval == oldval|_Gscan {
-			return cas(&gp.atomicstatus, oldval, newval)
-		}
-	case _Grunning:
-		if newval == _Gscanrunning || newval == _Gscanenqueue {
-			return cas(&gp.atomicstatus, oldval, newval)
-		}
-	}
-	print("runtime: castogscanstatus oldval=", hex(oldval), " newval=", hex(newval), "\n")
-	throw("castogscanstatus")
-	panic("not reached")
-}
-
-// If asked to move to or from a Gscanstatus this will throw. Use the castogscanstatus
-// and casfrom_Gscanstatus instead.
-// casgstatus will loop if the g->atomicstatus is in a Gscan status until the routine that
-// put it in the Gscan state is finished.
-//go:nosplit
-func casgstatus(gp *g, oldval, newval uint32) {
-	if (oldval&_Gscan != 0) || (newval&_Gscan != 0) || oldval == newval {
-		systemstack(func() {
-			print("runtime: casgstatus: oldval=", hex(oldval), " newval=", hex(newval), "\n")
-			throw("casgstatus: bad incoming values")
-		})
-	}
-
-	if oldval == _Grunning && gp.gcscanvalid {
-		// If oldvall == _Grunning, then the actual status must be
-		// _Grunning or _Grunning|_Gscan; either way,
-		// we own gp.gcscanvalid, so it's safe to read.
-		// gp.gcscanvalid must not be true when we are running.
-		print("runtime: casgstatus ", hex(oldval), "->", hex(newval), " gp.status=", hex(gp.atomicstatus), " gp.gcscanvalid=true\n")
-		throw("casgstatus")
-	}
-
-	// loop if gp->atomicstatus is in a scan state giving
-	// GC time to finish and change the state to oldval.
-	for !cas(&gp.atomicstatus, oldval, newval) {
-		if oldval == _Gwaiting && gp.atomicstatus == _Grunnable {
-			systemstack(func() {
-				throw("casgstatus: waiting for Gwaiting but is Grunnable")
-			})
-		}
-		// Help GC if needed.
-		// if gp.preemptscan && !gp.gcworkdone && (oldval == _Grunning || oldval == _Gsyscall) {
-		// 	gp.preemptscan = false
-		// 	systemstack(func() {
-		// 		gcphasework(gp)
-		// 	})
-		// }
-	}
-	if newval == _Grunning {
-		gp.gcscanvalid = false
-	}
-}
-
-// casgstatus(gp, oldstatus, Gcopystack), assuming oldstatus is Gwaiting or Grunnable.
-// Returns old status. Cannot call casgstatus directly, because we are racing with an
-// async wakeup that might come in from netpoll. If we see Gwaiting from the readgstatus,
-// it might have become Grunnable by the time we get to the cas. If we called casgstatus,
-// it would loop waiting for the status to go back to Gwaiting, which it never will.
-//go:nosplit
-func casgcopystack(gp *g) uint32 {
-	for {
-		oldstatus := readgstatus(gp) &^ _Gscan
-		if oldstatus != _Gwaiting && oldstatus != _Grunnable {
-			throw("copystack: bad status, not Gwaiting or Grunnable")
-		}
-		if cas(&gp.atomicstatus, oldstatus, _Gcopystack) {
-			return oldstatus
-		}
-	}
-}
-
-// scang blocks until gp's stack has been scanned.
-// It might be scanned by scang or it might be scanned by the goroutine itself.
-// Either way, the stack scan has completed when scang returns.
-func scang(gp *g) {
-	// Invariant; we (the caller, markroot for a specific goroutine) own gp.gcscandone.
-	// Nothing is racing with us now, but gcscandone might be set to true left over
-	// from an earlier round of stack scanning (we scan twice per GC).
-	// We use gcscandone to record whether the scan has been done during this round.
-	// It is important that the scan happens exactly once: if called twice,
-	// the installation of stack barriers will detect the double scan and die.
-
-	gp.gcscandone = false
-
-	// Endeavor to get gcscandone set to true,
-	// either by doing the stack scan ourselves or by coercing gp to scan itself.
-	// gp.gcscandone can transition from false to true when we're not looking
-	// (if we asked for preemption), so any time we lock the status using
-	// castogscanstatus we have to double-check that the scan is still not done.
-	for !gp.gcscandone {
-		switch s := readgstatus(gp); s {
-		default:
-			dumpgstatus(gp)
-			throw("stopg: invalid status")
-
-		case _Gdead:
-			// No stack.
-			gp.gcscandone = true
-
-		case _Gcopystack:
-			// Stack being switched. Go around again.
-
-		case _Grunnable, _Gsyscall, _Gwaiting:
-			// Claim goroutine by setting scan bit.
-			// Racing with execution or readying of gp.
-			// The scan bit keeps them from running
-			// the goroutine until we're done.
-			if castogscanstatus(gp, s, s|_Gscan) {
-				if !gp.gcscandone {
-					scanstack(gp)
-					gp.gcscandone = true
-				}
-				restartg(gp)
-			}
-
-		case _Gscanwaiting:
-			// newstack is doing a scan for us right now. Wait.
-
-		case _Grunning:
-			// Goroutine running. Try to preempt execution so it can scan itself.
-			// The preemption handler (in newstack) does the actual scan.
-
-			// Optimization: if there is already a pending preemption request
-			// (from the previous loop iteration), don't bother with the atomics.
-			if gp.preemptscan && gp.preempt && gp.stackguard0 == stackPreempt {
-				break
-			}
-
-			// Ask for preemption and self scan.
-			if castogscanstatus(gp, _Grunning, _Gscanrunning) {
-				if !gp.gcscandone {
-					gp.preemptscan = true
-					gp.preempt = true
-					gp.stackguard0 = stackPreempt
-				}
-				casfrom_Gscanstatus(gp, _Gscanrunning, _Grunning)
-			}
-		}
-	}
-
-	gp.preemptscan = false // cancel scan request if no longer needed
-}
-
-// The GC requests that this routine be moved from a scanmumble state to a mumble state.
-func restartg(gp *g) {
-	s := readgstatus(gp)
-	switch s {
-	default:
-		dumpgstatus(gp)
-		throw("restartg: unexpected status")
-
-	case _Gdead:
-		// ok
-
-	case _Gscanrunnable,
-		_Gscanwaiting,
-		_Gscansyscall:
-		casfrom_Gscanstatus(gp, s, s&^_Gscan)
-
-	// Scan is now completed.
-	// Goroutine now needs to be made runnable.
-	// We put it on the global run queue; ready blocks on the global scheduler lock.
-	case _Gscanenqueue:
-		casfrom_Gscanstatus(gp, _Gscanenqueue, _Gwaiting)
-		if gp != getg().m.curg {
-			throw("processing Gscanenqueue on wrong m")
-		}
-		dropg()
-		ready(gp, 0)
-	}
-}
-
-// stopTheWorld stops all P's from executing goroutines, interrupting
-// all goroutines at GC safe points and records reason as the reason
-// for the stop. On return, only the current goroutine's P is running.
-// stopTheWorld must not be called from a system stack and the caller
-// must not hold worldsema. The caller must call startTheWorld when
-// other P's should resume execution.
-//
-// stopTheWorld is safe for multiple goroutines to call at the
-// same time. Each will execute its own stop, and the stops will
-// be serialized.
-//
-// This is also used by routines that do stack dumps. If the system is
-// in panic or being exited, this may not reliably stop all
-// goroutines.
-func stopTheWorld(reason string) {
-	semacquire(&worldsema, false)
-	getg().m.preemptoff = reason
-	systemstack(stopTheWorldWithSema)
-}
-
-// startTheWorld undoes the effects of stopTheWorld.
-func startTheWorld() {
-	systemstack(startTheWorldWithSema)
-	// worldsema must be held over startTheWorldWithSema to ensure
-	// gomaxprocs cannot change while worldsema is held.
-	semrelease(&worldsema)
-	getg().m.preemptoff = ""
-}
-
-// Holding worldsema grants an M the right to try to stop the world
-// and prevents gomaxprocs from changing concurrently.
-var worldsema uint32 = 1
-
-// stopTheWorldWithSema is the core implementation of stopTheWorld.
-// The caller is responsible for acquiring worldsema and disabling
-// preemption first and then should stopTheWorldWithSema on the system
-// stack:
-//
-//	semacquire(&worldsema, false)
-//	m.preemptoff = "reason"
-//	systemstack(stopTheWorldWithSema)
-//
-// When finished, the caller must either call startTheWorld or undo
-// these three operations separately:
-//
-//	m.preemptoff = ""
-//	systemstack(startTheWorldWithSema)
-//	semrelease(&worldsema)
-//
-// It is allowed to acquire worldsema once and then execute multiple
-// startTheWorldWithSema/stopTheWorldWithSema pairs.
-// Other P's are able to execute between successive calls to
-// startTheWorldWithSema and stopTheWorldWithSema.
-// Holding worldsema causes any other goroutines invoking
-// stopTheWorld to block.
-func stopTheWorldWithSema() {
-	_g_ := getg()
-
-	// If we hold a lock, then we won't be able to stop another M
-	// that is blocked trying to acquire the lock.
-	if _g_.m.locks > 0 {
-		throw("stopTheWorld: holding locks")
-	}
-
-	lock(&sched.lock)
-	sched.stopwait = gomaxprocs
-	atomicstore(&sched.gcwaiting, 1)
-	preemptall()
-	// stop current P
-	_g_.m.p.ptr().status = _Pgcstop // Pgcstop is only diagnostic.
-	sched.stopwait--
-	// try to retake all P's in Psyscall status
-	for i := 0; i < int(gomaxprocs); i++ {
-		p := allp[i]
-		s := p.status
-		if s == _Psyscall && cas(&p.status, s, _Pgcstop) {
-			if trace.enabled {
-				traceGoSysBlock(p)
-				traceProcStop(p)
-			}
-			p.syscalltick++
-			sched.stopwait--
-		}
-	}
-	// stop idle P's
-	for {
-		p := pidleget()
-		if p == nil {
-			break
-		}
-		p.status = _Pgcstop
-		sched.stopwait--
-	}
-	wait := sched.stopwait > 0
-	unlock(&sched.lock)
-
-	// wait for remaining P's to stop voluntarily
-	if wait {
-		for {
-			// wait for 100us, then try to re-preempt in case of any races
-			if notetsleep(&sched.stopnote, 100*1000) {
-				noteclear(&sched.stopnote)
-				break
-			}
-			preemptall()
-		}
-	}
-	if sched.stopwait != 0 {
-		throw("stopTheWorld: not stopped")
-	}
-	for i := 0; i < int(gomaxprocs); i++ {
-		p := allp[i]
-		if p.status != _Pgcstop {
-			throw("stopTheWorld: not stopped")
-		}
-	}
-}
-
-func mhelpgc() {
-	_g_ := getg()
-	_g_.m.helpgc = -1
-}
-
-func startTheWorldWithSema() {
-	_g_ := getg()
-
-	_g_.m.locks++        // disable preemption because it can be holding p in a local var
-	gp := netpoll(false) // non-blocking
-	injectglist(gp)
-	add := needaddgcproc()
-	lock(&sched.lock)
-
-	procs := gomaxprocs
-	if newprocs != 0 {
-		procs = newprocs
-		newprocs = 0
-	}
-	p1 := procresize(procs)
-	sched.gcwaiting = 0
-	if sched.sysmonwait != 0 {
-		sched.sysmonwait = 0
-		notewakeup(&sched.sysmonnote)
-	}
-	unlock(&sched.lock)
-
-	for p1 != nil {
-		p := p1
-		p1 = p1.link.ptr()
-		if p.m != 0 {
-			mp := p.m.ptr()
-			p.m = 0
-			if mp.nextp != 0 {
-				throw("startTheWorld: inconsistent mp->nextp")
-			}
-			mp.nextp.set(p)
-			notewakeup(&mp.park)
-		} else {
-			// Start M to run P.  Do not start another M below.
-			newm(nil, p)
-			add = false
-		}
-	}
-
-	// Wakeup an additional proc in case we have excessive runnable goroutines
-	// in local queues or in the global queue. If we don't, the proc will park itself.
-	// If we have lots of excessive work, resetspinning will unpark additional procs as necessary.
-	if atomicload(&sched.npidle) != 0 && atomicload(&sched.nmspinning) == 0 {
-		wakep()
-	}
-
-	if add {
-		// If GC could have used another helper proc, start one now,
-		// in the hope that it will be available next time.
-		// It would have been even better to start it before the collection,
-		// but doing so requires allocating memory, so it's tricky to
-		// coordinate.  This lazy approach works out in practice:
-		// we don't mind if the first couple gc rounds don't have quite
-		// the maximum number of procs.
-		newm(mhelpgc, nil)
-	}
-	_g_.m.locks--
-	if _g_.m.locks == 0 && _g_.preempt { // restore the preemption request in case we've cleared it in newstack
-		_g_.stackguard0 = stackPreempt
-	}
-}
-
-// Called to start an M.
-//go:nosplit
-func mstart() {
-	_g_ := getg()
-
-	if _g_.stack.lo == 0 {
-		// Initialize stack bounds from system stack.
-		// Cgo may have left stack size in stack.hi.
-		size := _g_.stack.hi
-		if size == 0 {
-			size = 8192 * stackGuardMultiplier
-		}
-		_g_.stack.hi = uintptr(noescape(unsafe.Pointer(&size)))
-		_g_.stack.lo = _g_.stack.hi - size + 1024
-	}
-	// Initialize stack guards so that we can start calling
-	// both Go and C functions with stack growth prologues.
-	_g_.stackguard0 = _g_.stack.lo + _StackGuard
-	_g_.stackguard1 = _g_.stackguard0
-	mstart1()
-}
-
-func mstart1() {
-	_g_ := getg()
-
-	if _g_ != _g_.m.g0 {
-		throw("bad runtime·mstart")
-	}
-
-	// Record top of stack for use by mcall.
-	// Once we call schedule we're never coming back,
-	// so other calls can reuse this stack space.
-	gosave(&_g_.m.g0.sched)
-	_g_.m.g0.sched.pc = ^uintptr(0) // make sure it is never used
-	asminit()
-	minit()
-
-	// Install signal handlers; after minit so that minit can
-	// prepare the thread to be able to handle the signals.
-	if _g_.m == &m0 {
-		// Create an extra M for callbacks on threads not created by Go.
-		if iscgo && !cgoHasExtraM {
-			cgoHasExtraM = true
-			newextram()
-		}
-		initsig()
-	}
-
-	if fn := _g_.m.mstartfn; fn != nil {
-		fn()
-	}
-
-	if _g_.m.helpgc != 0 {
-		_g_.m.helpgc = 0
-		stopm()
-	} else if _g_.m != &m0 {
-		acquirep(_g_.m.nextp.ptr())
-		_g_.m.nextp = 0
-	}
-	schedule()
-}
-
-// forEachP calls fn(p) for every P p when p reaches a GC safe point.
-// If a P is currently executing code, this will bring the P to a GC
-// safe point and execute fn on that P. If the P is not executing code
-// (it is idle or in a syscall), this will call fn(p) directly while
-// preventing the P from exiting its state. This does not ensure that
-// fn will run on every CPU executing Go code, but it acts as a global
-// memory barrier. GC uses this as a "ragged barrier."
-//
-// The caller must hold worldsema.
-func forEachP(fn func(*p)) {
-	mp := acquirem()
-	_p_ := getg().m.p.ptr()
-
-	lock(&sched.lock)
-	if sched.safePointWait != 0 {
-		throw("forEachP: sched.safePointWait != 0")
-	}
-	sched.safePointWait = gomaxprocs - 1
-	sched.safePointFn = fn
-
-	// Ask all Ps to run the safe point function.
-	for _, p := range allp[:gomaxprocs] {
-		if p != _p_ {
-			atomicstore(&p.runSafePointFn, 1)
-		}
-	}
-	preemptall()
-
-	// Any P entering _Pidle or _Psyscall from now on will observe
-	// p.runSafePointFn == 1 and will call runSafePointFn when
-	// changing its status to _Pidle/_Psyscall.
-
-	// Run safe point function for all idle Ps. sched.pidle will
-	// not change because we hold sched.lock.
-	for p := sched.pidle.ptr(); p != nil; p = p.link.ptr() {
-		if cas(&p.runSafePointFn, 1, 0) {
-			fn(p)
-			sched.safePointWait--
-		}
-	}
-
-	wait := sched.safePointWait > 0
-	unlock(&sched.lock)
-
-	// Run fn for the current P.
-	fn(_p_)
-
-	// Force Ps currently in _Psyscall into _Pidle and hand them
-	// off to induce safe point function execution.
-	for i := 0; i < int(gomaxprocs); i++ {
-		p := allp[i]
-		s := p.status
-		if s == _Psyscall && p.runSafePointFn == 1 && cas(&p.status, s, _Pidle) {
-			if trace.enabled {
-				traceGoSysBlock(p)
-				traceProcStop(p)
-			}
-			p.syscalltick++
-			handoffp(p)
-		}
-	}
-
-	// Wait for remaining Ps to run fn.
-	if wait {
-		for {
-			// Wait for 100us, then try to re-preempt in
-			// case of any races.
-			if notetsleep(&sched.safePointNote, 100*1000) {
-				noteclear(&sched.safePointNote)
-				break
-			}
-			preemptall()
-		}
-	}
-	if sched.safePointWait != 0 {
-		throw("forEachP: not done")
-	}
-	for i := 0; i < int(gomaxprocs); i++ {
-		p := allp[i]
-		if p.runSafePointFn != 0 {
-			throw("forEachP: P did not run fn")
-		}
-	}
-
-	lock(&sched.lock)
-	sched.safePointFn = nil
-	unlock(&sched.lock)
-	releasem(mp)
-}
-
-// runSafePointFn runs the safe point function, if any, for this P.
-// This should be called like
-//
-//     if getg().m.p.runSafePointFn != 0 {
-//         runSafePointFn()
-//     }
-//
-// runSafePointFn must be checked on any transition in to _Pidle or
-// _Psyscall to avoid a race where forEachP sees that the P is running
-// just before the P goes into _Pidle/_Psyscall and neither forEachP
-// nor the P run the safe-point function.
-func runSafePointFn() {
-	p := getg().m.p.ptr()
-	// Resolve the race between forEachP running the safe-point
-	// function on this P's behalf and this P running the
-	// safe-point function directly.
-	if !cas(&p.runSafePointFn, 1, 0) {
-		return
-	}
-	sched.safePointFn(p)
-	lock(&sched.lock)
-	sched.safePointWait--
-	if sched.safePointWait == 0 {
-		notewakeup(&sched.safePointNote)
-	}
-	unlock(&sched.lock)
-}
-
-// When running with cgo, we call _cgo_thread_start
-// to start threads for us so that we can play nicely with
-// foreign code.
-var cgoThreadStart unsafe.Pointer
-
-type cgothreadstart struct {
-	g   guintptr
-	tls *uint64
-	fn  unsafe.Pointer
-}
-
-// Allocate a new m unassociated with any thread.
-// Can use p for allocation context if needed.
-// fn is recorded as the new m's m.mstartfn.
-func allocm(_p_ *p, fn func()) *m {
-	_g_ := getg()
-	_g_.m.locks++ // disable GC because it can be called from sysmon
-	if _g_.m.p == 0 {
-		acquirep(_p_) // temporarily borrow p for mallocs in this function
-	}
-	mp := new(m)
-	mp.mstartfn = fn
-	mcommoninit(mp)
-
-	// In case of cgo or Solaris, pthread_create will make us a stack.
-	// Windows and Plan 9 will layout sched stack on OS stack.
-	if iscgo || GOOS == "solaris" || GOOS == "windows" || GOOS == "plan9" {
-		mp.g0 = malg(-1)
-	} else {
-		mp.g0 = malg(8192 * stackGuardMultiplier)
-	}
-	mp.g0.m = mp
-
-	if _p_ == _g_.m.p.ptr() {
-		releasep()
-	}
-	_g_.m.locks--
-	if _g_.m.locks == 0 && _g_.preempt { // restore the preemption request in case we've cleared it in newstack
-		_g_.stackguard0 = stackPreempt
-	}
-
-	return mp
-}
-
-// needm is called when a cgo callback happens on a
-// thread without an m (a thread not created by Go).
-// In this case, needm is expected to find an m to use
-// and return with m, g initialized correctly.
-// Since m and g are not set now (likely nil, but see below)
-// needm is limited in what routines it can call. In particular
-// it can only call nosplit functions (textflag 7) and cannot
-// do any scheduling that requires an m.
-//
-// In order to avoid needing heavy lifting here, we adopt
-// the following strategy: there is a stack of available m's
-// that can be stolen. Using compare-and-swap
-// to pop from the stack has ABA races, so we simulate
-// a lock by doing an exchange (via casp) to steal the stack
-// head and replace the top pointer with MLOCKED (1).
-// This serves as a simple spin lock that we can use even
-// without an m. The thread that locks the stack in this way
-// unlocks the stack by storing a valid stack head pointer.
-//
-// In order to make sure that there is always an m structure
-// available to be stolen, we maintain the invariant that there
-// is always one more than needed. At the beginning of the
-// program (if cgo is in use) the list is seeded with a single m.
-// If needm finds that it has taken the last m off the list, its job
-// is - once it has installed its own m so that it can do things like
-// allocate memory - to create a spare m and put it on the list.
-//
-// Each of these extra m's also has a g0 and a curg that are
-// pressed into service as the scheduling stack and current
-// goroutine for the duration of the cgo callback.
-//
-// When the callback is done with the m, it calls dropm to
-// put the m back on the list.
-//go:nosplit
-func needm(x byte) {
-	if iscgo && !cgoHasExtraM {
-		// Can happen if C/C++ code calls Go from a global ctor.
-		// Can not throw, because scheduler is not initialized yet.
-		write(2, unsafe.Pointer(&earlycgocallback[0]), int32(len(earlycgocallback)))
-		exit(1)
-	}
-
-	// Lock extra list, take head, unlock popped list.
-	// nilokay=false is safe here because of the invariant above,
-	// that the extra list always contains or will soon contain
-	// at least one m.
-	mp := lockextra(false)
-
-	// Set needextram when we've just emptied the list,
-	// so that the eventual call into cgocallbackg will
-	// allocate a new m for the extra list. We delay the
-	// allocation until then so that it can be done
-	// after exitsyscall makes sure it is okay to be
-	// running at all (that is, there's no garbage collection
-	// running right now).
-	mp.needextram = mp.schedlink == 0
-	unlockextra(mp.schedlink.ptr())
-
-	// Save and block signals before installing g.
-	// Once g is installed, any incoming signals will try to execute,
-	// but we won't have the sigaltstack settings and other data
-	// set up appropriately until the end of minit, which will
-	// unblock the signals. This is the same dance as when
-	// starting a new m to run Go code via newosproc.
-	msigsave(mp)
-	sigblock()
-
-	// Install g (= m->g0) and set the stack bounds
-	// to match the current stack. We don't actually know
-	// how big the stack is, like we don't know how big any
-	// scheduling stack is, but we assume there's at least 32 kB,
-	// which is more than enough for us.
-	setg(mp.g0)
-	_g_ := getg()
-	_g_.stack.hi = uintptr(noescape(unsafe.Pointer(&x))) + 1024
-	_g_.stack.lo = uintptr(noescape(unsafe.Pointer(&x))) - 32*1024
-	_g_.stackguard0 = _g_.stack.lo + _StackGuard
-
-	// Initialize this thread to use the m.
-	asminit()
-	minit()
-}
-
-var earlycgocallback = []byte("fatal error: cgo callback before cgo call\n")
-
-// newextram allocates an m and puts it on the extra list.
-// It is called with a working local m, so that it can do things
-// like call schedlock and allocate.
-func newextram() {
-	// Create extra goroutine locked to extra m.
-	// The goroutine is the context in which the cgo callback will run.
-	// The sched.pc will never be returned to, but setting it to
-	// goexit makes clear to the traceback routines where
-	// the goroutine stack ends.
-	mp := allocm(nil, nil)
-	gp := malg(4096)
-	gp.sched.pc = funcPC(goexit) + _PCQuantum
-	gp.sched.sp = gp.stack.hi
-	gp.sched.sp -= 4 * regSize // extra space in case of reads slightly beyond frame
-	gp.sched.lr = 0
-	gp.sched.g = guintptr(unsafe.Pointer(gp))
-	gp.syscallpc = gp.sched.pc
-	gp.syscallsp = gp.sched.sp
-	// malg returns status as Gidle, change to Gsyscall before adding to allg
-	// where GC will see it.
-	casgstatus(gp, _Gidle, _Gsyscall)
-	gp.m = mp
-	mp.curg = gp
-	mp.locked = _LockInternal
-	mp.lockedg = gp
-	gp.lockedm = mp
-	gp.goid = int64(xadd64(&sched.goidgen, 1))
-	if raceenabled {
-		gp.racectx = racegostart(funcPC(newextram))
-	}
-	// put on allg for garbage collector
-	allgadd(gp)
-
-	// Add m to the extra list.
-	mnext := lockextra(true)
-	mp.schedlink.set(mnext)
-	unlockextra(mp)
-}
-
-// dropm is called when a cgo callback has called needm but is now
-// done with the callback and returning back into the non-Go thread.
-// It puts the current m back onto the extra list.
-//
-// The main expense here is the call to signalstack to release the
-// m's signal stack, and then the call to needm on the next callback
-// from this thread. It is tempting to try to save the m for next time,
-// which would eliminate both these costs, but there might not be
-// a next time: the current thread (which Go does not control) might exit.
-// If we saved the m for that thread, there would be an m leak each time
-// such a thread exited. Instead, we acquire and release an m on each
-// call. These should typically not be scheduling operations, just a few
-// atomics, so the cost should be small.
-//
-// TODO(rsc): An alternative would be to allocate a dummy pthread per-thread
-// variable using pthread_key_create. Unlike the pthread keys we already use
-// on OS X, this dummy key would never be read by Go code. It would exist
-// only so that we could register at thread-exit-time destructor.
-// That destructor would put the m back onto the extra list.
-// This is purely a performance optimization. The current version,
-// in which dropm happens on each cgo call, is still correct too.
-// We may have to keep the current version on systems with cgo
-// but without pthreads, like Windows.
-func dropm() {
-	// Clear m and g, and return m to the extra list.
-	// After the call to setg we can only call nosplit functions
-	// with no pointer manipulation.
-	mp := getg().m
-	mnext := lockextra(true)
-	mp.schedlink.set(mnext)
-
-	// Block signals before unminit.
-	// Unminit unregisters the signal handling stack (but needs g on some systems).
-	// Setg(nil) clears g, which is the signal handler's cue not to run Go handlers.
-	// It's important not to try to handle a signal between those two steps.
-	sigblock()
-	unminit()
-	setg(nil)
-	msigrestore(mp)
-
-	// Commit the release of mp.
-	unlockextra(mp)
-}
-
-var extram uintptr
-
-// lockextra locks the extra list and returns the list head.
-// The caller must unlock the list by storing a new list head
-// to extram. If nilokay is true, then lockextra will
-// return a nil list head if that's what it finds. If nilokay is false,
-// lockextra will keep waiting until the list head is no longer nil.
-//go:nosplit
-func lockextra(nilokay bool) *m {
-	const locked = 1
-
-	for {
-		old := atomicloaduintptr(&extram)
-		if old == locked {
-			yield := osyield
-			yield()
-			continue
-		}
-		if old == 0 && !nilokay {
-			usleep(1)
-			continue
-		}
-		if casuintptr(&extram, old, locked) {
-			return (*m)(unsafe.Pointer(old))
-		}
-		yield := osyield
-		yield()
-		continue
-	}
-}
-
-//go:nosplit
-func unlockextra(mp *m) {
-	atomicstoreuintptr(&extram, uintptr(unsafe.Pointer(mp)))
-}
-
-// Create a new m.  It will start off with a call to fn, or else the scheduler.
-// fn needs to be static and not a heap allocated closure.
-// May run with m.p==nil, so write barriers are not allowed.
-//go:nowritebarrier
-func newm(fn func(), _p_ *p) {
-	mp := allocm(_p_, fn)
-	mp.nextp.set(_p_)
-	msigsave(mp)
-	if iscgo {
-		var ts cgothreadstart
-		if _cgo_thread_start == nil {
-			throw("_cgo_thread_start missing")
-		}
-		ts.g.set(mp.g0)
-		ts.tls = (*uint64)(unsafe.Pointer(&mp.tls[0]))
-		ts.fn = unsafe.Pointer(funcPC(mstart))
-		asmcgocall(_cgo_thread_start, unsafe.Pointer(&ts))
-		return
-	}
-	newosproc(mp, unsafe.Pointer(mp.g0.stack.hi))
-}
-
-// Stops execution of the current m until new work is available.
-// Returns with acquired P.
-func stopm() {
-	_g_ := getg()
-
-	if _g_.m.locks != 0 {
-		throw("stopm holding locks")
-	}
-	if _g_.m.p != 0 {
-		throw("stopm holding p")
-	}
-	if _g_.m.spinning {
-		_g_.m.spinning = false
-		xadd(&sched.nmspinning, -1)
-	}
-
-retry:
-	lock(&sched.lock)
-	mput(_g_.m)
-	unlock(&sched.lock)
-	notesleep(&_g_.m.park)
-	noteclear(&_g_.m.park)
-	if _g_.m.helpgc != 0 {
-		gchelper()
-		_g_.m.helpgc = 0
-		_g_.m.mcache = nil
-		_g_.m.p = 0
-		goto retry
-	}
-	acquirep(_g_.m.nextp.ptr())
-	_g_.m.nextp = 0
-}
-
-func mspinning() {
-	gp := getg()
-	if !runqempty(gp.m.nextp.ptr()) {
-		// Something (presumably the GC) was readied while the
-		// runtime was starting up this M, so the M is no
-		// longer spinning.
-		if int32(xadd(&sched.nmspinning, -1)) < 0 {
-			throw("mspinning: nmspinning underflowed")
-		}
-	} else {
-		gp.m.spinning = true
-	}
-}
-
-// Schedules some M to run the p (creates an M if necessary).
-// If p==nil, tries to get an idle P, if no idle P's does nothing.
-// May run with m.p==nil, so write barriers are not allowed.
-//go:nowritebarrier
-func startm(_p_ *p, spinning bool) {
-	lock(&sched.lock)
-	if _p_ == nil {
-		_p_ = pidleget()
-		if _p_ == nil {
-			unlock(&sched.lock)
-			if spinning {
-				xadd(&sched.nmspinning, -1)
-			}
-			return
-		}
-	}
-	mp := mget()
-	unlock(&sched.lock)
-	if mp == nil {
-		var fn func()
-		if spinning {
-			fn = mspinning
-		}
-		newm(fn, _p_)
-		return
-	}
-	if mp.spinning {
-		throw("startm: m is spinning")
-	}
-	if mp.nextp != 0 {
-		throw("startm: m has p")
-	}
-	if spinning && !runqempty(_p_) {
-		throw("startm: p has runnable gs")
-	}
-	mp.spinning = spinning
-	mp.nextp.set(_p_)
-	notewakeup(&mp.park)
-}
-
-// Hands off P from syscall or locked M.
-// Always runs without a P, so write barriers are not allowed.
-//go:nowritebarrier
-func handoffp(_p_ *p) {
-	// if it has local work, start it straight away
-	if !runqempty(_p_) || sched.runqsize != 0 {
-		startm(_p_, false)
-		return
-	}
-	// no local work, check that there are no spinning/idle M's,
-	// otherwise our help is not required
-	if atomicload(&sched.nmspinning)+atomicload(&sched.npidle) == 0 && cas(&sched.nmspinning, 0, 1) { // TODO: fast atomic
-		startm(_p_, true)
-		return
-	}
-	lock(&sched.lock)
-	if sched.gcwaiting != 0 {
-		_p_.status = _Pgcstop
-		sched.stopwait--
-		if sched.stopwait == 0 {
-			notewakeup(&sched.stopnote)
-		}
-		unlock(&sched.lock)
-		return
-	}
-	if _p_.runSafePointFn != 0 && cas(&_p_.runSafePointFn, 1, 0) {
-		sched.safePointFn(_p_)
-		sched.safePointWait--
-		if sched.safePointWait == 0 {
-			notewakeup(&sched.safePointNote)
-		}
-	}
-	if sched.runqsize != 0 {
-		unlock(&sched.lock)
-		startm(_p_, false)
-		return
-	}
-	// If this is the last running P and nobody is polling network,
-	// need to wakeup another M to poll network.
-	if sched.npidle == uint32(gomaxprocs-1) && atomicload64(&sched.lastpoll) != 0 {
-		unlock(&sched.lock)
-		startm(_p_, false)
-		return
-	}
-	pidleput(_p_)
-	unlock(&sched.lock)
-}
-
-// Tries to add one more P to execute G's.
-// Called when a G is made runnable (newproc, ready).
-func wakep() {
-	// be conservative about spinning threads
-	if !cas(&sched.nmspinning, 0, 1) {
-		return
-	}
-	startm(nil, true)
-}
-
-// Stops execution of the current m that is locked to a g until the g is runnable again.
-// Returns with acquired P.
-func stoplockedm() {
-	_g_ := getg()
-
-	if _g_.m.lockedg == nil || _g_.m.lockedg.lockedm != _g_.m {
-		throw("stoplockedm: inconsistent locking")
-	}
-	if _g_.m.p != 0 {
-		// Schedule another M to run this p.
-		_p_ := releasep()
-		handoffp(_p_)
-	}
-	incidlelocked(1)
-	// Wait until another thread schedules lockedg again.
-	notesleep(&_g_.m.park)
-	noteclear(&_g_.m.park)
-	status := readgstatus(_g_.m.lockedg)
-	if status&^_Gscan != _Grunnable {
-		print("runtime:stoplockedm: g is not Grunnable or Gscanrunnable\n")
-		dumpgstatus(_g_)
-		throw("stoplockedm: not runnable")
-	}
-	acquirep(_g_.m.nextp.ptr())
-	_g_.m.nextp = 0
-}
-
-// Schedules the locked m to run the locked gp.
-// May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
-func startlockedm(gp *g) {
-	_g_ := getg()
-
-	mp := gp.lockedm
-	if mp == _g_.m {
-		throw("startlockedm: locked to me")
-	}
-	if mp.nextp != 0 {
-		throw("startlockedm: m has p")
-	}
-	// directly handoff current P to the locked m
-	incidlelocked(-1)
-	_p_ := releasep()
-	mp.nextp.set(_p_)
-	notewakeup(&mp.park)
-	stopm()
-}
-
-// Stops the current m for stopTheWorld.
-// Returns when the world is restarted.
-func gcstopm() {
-	_g_ := getg()
-
-	if sched.gcwaiting == 0 {
-		throw("gcstopm: not waiting for gc")
-	}
-	if _g_.m.spinning {
-		_g_.m.spinning = false
-		xadd(&sched.nmspinning, -1)
-	}
-	_p_ := releasep()
-	lock(&sched.lock)
-	_p_.status = _Pgcstop
-	sched.stopwait--
-	if sched.stopwait == 0 {
-		notewakeup(&sched.stopnote)
-	}
-	unlock(&sched.lock)
-	stopm()
-}
-
-// Schedules gp to run on the current M.
-// If inheritTime is true, gp inherits the remaining time in the
-// current time slice. Otherwise, it starts a new time slice.
-// Never returns.
-func execute(gp *g, inheritTime bool) {
-	_g_ := getg()
-
-	casgstatus(gp, _Grunnable, _Grunning)
-	gp.waitsince = 0
-	gp.preempt = false
-	gp.stackguard0 = gp.stack.lo + _StackGuard
-	if !inheritTime {
-		_g_.m.p.ptr().schedtick++
-	}
-	_g_.m.curg = gp
-	gp.m = _g_.m
-
-	// Check whether the profiler needs to be turned on or off.
-	hz := sched.profilehz
-	if _g_.m.profilehz != hz {
-		resetcpuprofiler(hz)
-	}
-
-	if trace.enabled {
-		// GoSysExit has to happen when we have a P, but before GoStart.
-		// So we emit it here.
-		if gp.syscallsp != 0 && gp.sysblocktraced {
-			// Since gp.sysblocktraced is true, we must emit an event.
-			// There is a race between the code that initializes sysexitseq
-			// and sysexitticks (in exitsyscall, which runs without a P,
-			// and therefore is not stopped with the rest of the world)
-			// and the code that initializes a new trace.
-			// The recorded sysexitseq and sysexitticks must therefore
-			// be treated as "best effort". If they are valid for this trace,
-			// then great, use them for greater accuracy.
-			// But if they're not valid for this trace, assume that the
-			// trace was started after the actual syscall exit (but before
-			// we actually managed to start the goroutine, aka right now),
-			// and assign a fresh time stamp to keep the log consistent.
-			seq, ts := gp.sysexitseq, gp.sysexitticks
-			if seq == 0 || int64(seq)-int64(trace.seqStart) < 0 {
-				seq, ts = tracestamp()
-			}
-			traceGoSysExit(seq, ts)
-		}
-		traceGoStart()
-	}
-
-	gogo(&gp.sched)
-}
-
-// Finds a runnable goroutine to execute.
-// Tries to steal from other P's, get g from global queue, poll network.
-func findrunnable() (gp *g, inheritTime bool) {
-	_g_ := getg()
-
-top:
-	if sched.gcwaiting != 0 {
-		gcstopm()
-		goto top
-	}
-	if _g_.m.p.ptr().runSafePointFn != 0 {
-		runSafePointFn()
-	}
-	if fingwait && fingwake {
-		if gp := wakefing(); gp != nil {
-			ready(gp, 0)
-		}
-	}
-
-	// local runq
-	if gp, inheritTime := runqget(_g_.m.p.ptr()); gp != nil {
-		return gp, inheritTime
-	}
-
-	// global runq
-	if sched.runqsize != 0 {
-		lock(&sched.lock)
-		gp := globrunqget(_g_.m.p.ptr(), 0)
-		unlock(&sched.lock)
-		if gp != nil {
-			return gp, false
-		}
-	}
-
-	// Poll network.
-	// This netpoll is only an optimization before we resort to stealing.
-	// We can safely skip it if there a thread blocked in netpoll already.
-	// If there is any kind of logical race with that blocked thread
-	// (e.g. it has already returned from netpoll, but does not set lastpoll yet),
-	// this thread will do blocking netpoll below anyway.
-	if netpollinited() && sched.lastpoll != 0 {
-		if gp := netpoll(false); gp != nil { // non-blocking
-			// netpoll returns list of goroutines linked by schedlink.
-			injectglist(gp.schedlink.ptr())
-			casgstatus(gp, _Gwaiting, _Grunnable)
-			if trace.enabled {
-				traceGoUnpark(gp, 0)
-			}
-			return gp, false
-		}
-	}
-
-	// If number of spinning M's >= number of busy P's, block.
-	// This is necessary to prevent excessive CPU consumption
-	// when GOMAXPROCS>>1 but the program parallelism is low.
-	if !_g_.m.spinning && 2*atomicload(&sched.nmspinning) >= uint32(gomaxprocs)-atomicload(&sched.npidle) { // TODO: fast atomic
-		goto stop
-	}
-	if !_g_.m.spinning {
-		_g_.m.spinning = true
-		xadd(&sched.nmspinning, 1)
-	}
-	// random steal from other P's
-	for i := 0; i < int(4*gomaxprocs); i++ {
-		if sched.gcwaiting != 0 {
-			goto top
-		}
-		_p_ := allp[fastrand1()%uint32(gomaxprocs)]
-		var gp *g
-		if _p_ == _g_.m.p.ptr() {
-			gp, _ = runqget(_p_)
-		} else {
-			stealRunNextG := i > 2*int(gomaxprocs) // first look for ready queues with more than 1 g
-			gp = runqsteal(_g_.m.p.ptr(), _p_, stealRunNextG)
-		}
-		if gp != nil {
-			return gp, false
-		}
-	}
-
-stop:
-
-	// We have nothing to do. If we're in the GC mark phase and can
-	// safely scan and blacken objects, run idle-time marking
-	// rather than give up the P.
-	if _p_ := _g_.m.p.ptr(); gcBlackenEnabled != 0 && _p_.gcBgMarkWorker != nil && gcMarkWorkAvailable(_p_) {
-		_p_.gcMarkWorkerMode = gcMarkWorkerIdleMode
-		gp := _p_.gcBgMarkWorker
-		casgstatus(gp, _Gwaiting, _Grunnable)
-		if trace.enabled {
-			traceGoUnpark(gp, 0)
-		}
-		return gp, false
-	}
-
-	// return P and block
-	lock(&sched.lock)
-	if sched.gcwaiting != 0 || _g_.m.p.ptr().runSafePointFn != 0 {
-		unlock(&sched.lock)
-		goto top
-	}
-	if sched.runqsize != 0 {
-		gp := globrunqget(_g_.m.p.ptr(), 0)
-		unlock(&sched.lock)
-		return gp, false
-	}
-	_p_ := releasep()
-	pidleput(_p_)
-	unlock(&sched.lock)
-	if _g_.m.spinning {
-		_g_.m.spinning = false
-		xadd(&sched.nmspinning, -1)
-	}
-
-	// check all runqueues once again
-	for i := 0; i < int(gomaxprocs); i++ {
-		_p_ := allp[i]
-		if _p_ != nil && !runqempty(_p_) {
-			lock(&sched.lock)
-			_p_ = pidleget()
-			unlock(&sched.lock)
-			if _p_ != nil {
-				acquirep(_p_)
-				goto top
-			}
-			break
-		}
-	}
-
-	// poll network
-	if netpollinited() && xchg64(&sched.lastpoll, 0) != 0 {
-		if _g_.m.p != 0 {
-			throw("findrunnable: netpoll with p")
-		}
-		if _g_.m.spinning {
-			throw("findrunnable: netpoll with spinning")
-		}
-		gp := netpoll(true) // block until new work is available
-		atomicstore64(&sched.lastpoll, uint64(nanotime()))
-		if gp != nil {
-			lock(&sched.lock)
-			_p_ = pidleget()
-			unlock(&sched.lock)
-			if _p_ != nil {
-				acquirep(_p_)
-				injectglist(gp.schedlink.ptr())
-				casgstatus(gp, _Gwaiting, _Grunnable)
-				if trace.enabled {
-					traceGoUnpark(gp, 0)
-				}
-				return gp, false
-			}
-			injectglist(gp)
-		}
-	}
-	stopm()
-	goto top
-}
-
-func resetspinning() {
-	_g_ := getg()
-
-	var nmspinning uint32
-	if _g_.m.spinning {
-		_g_.m.spinning = false
-		nmspinning = xadd(&sched.nmspinning, -1)
-		if nmspinning < 0 {
-			throw("findrunnable: negative nmspinning")
-		}
-	} else {
-		nmspinning = atomicload(&sched.nmspinning)
-	}
-
-	// M wakeup policy is deliberately somewhat conservative (see nmspinning handling),
-	// so see if we need to wakeup another P here.
-	if nmspinning == 0 && atomicload(&sched.npidle) > 0 {
-		wakep()
-	}
-}
-
-// Injects the list of runnable G's into the scheduler.
-// Can run concurrently with GC.
-func injectglist(glist *g) {
-	if glist == nil {
-		return
-	}
-	if trace.enabled {
-		for gp := glist; gp != nil; gp = gp.schedlink.ptr() {
-			traceGoUnpark(gp, 0)
-		}
-	}
-	lock(&sched.lock)
-	var n int
-	for n = 0; glist != nil; n++ {
-		gp := glist
-		glist = gp.schedlink.ptr()
-		casgstatus(gp, _Gwaiting, _Grunnable)
-		globrunqput(gp)
-	}
-	unlock(&sched.lock)
-	for ; n != 0 && sched.npidle != 0; n-- {
-		startm(nil, false)
-	}
-}
-
-// One round of scheduler: find a runnable goroutine and execute it.
-// Never returns.
-func schedule() {
-	_g_ := getg()
-
-	if _g_.m.locks != 0 {
-		throw("schedule: holding locks")
-	}
-
-	if _g_.m.lockedg != nil {
-		stoplockedm()
-		execute(_g_.m.lockedg, false) // Never returns.
-	}
-
-top:
-	if sched.gcwaiting != 0 {
-		gcstopm()
-		goto top
-	}
-	if _g_.m.p.ptr().runSafePointFn != 0 {
-		runSafePointFn()
-	}
-
-	var gp *g
-	var inheritTime bool
-	if trace.enabled || trace.shutdown {
-		gp = traceReader()
-		if gp != nil {
-			casgstatus(gp, _Gwaiting, _Grunnable)
-			traceGoUnpark(gp, 0)
-			resetspinning()
-		}
-	}
-	if gp == nil && gcBlackenEnabled != 0 {
-		gp = gcController.findRunnableGCWorker(_g_.m.p.ptr())
-		if gp != nil {
-			resetspinning()
-		}
-	}
-	if gp == nil {
-		// Check the global runnable queue once in a while to ensure fairness.
-		// Otherwise two goroutines can completely occupy the local runqueue
-		// by constantly respawning each other.
-		if _g_.m.p.ptr().schedtick%61 == 0 && sched.runqsize > 0 {
-			lock(&sched.lock)
-			gp = globrunqget(_g_.m.p.ptr(), 1)
-			unlock(&sched.lock)
-			if gp != nil {
-				resetspinning()
-			}
-		}
-	}
-	if gp == nil {
-		gp, inheritTime = runqget(_g_.m.p.ptr())
-		if gp != nil && _g_.m.spinning {
-			throw("schedule: spinning with local work")
-		}
-	}
-	if gp == nil {
-		gp, inheritTime = findrunnable() // blocks until work is available
-		resetspinning()
-	}
-
-	if gp.lockedm != nil {
-		// Hands off own p to the locked m,
-		// then blocks waiting for a new p.
-		startlockedm(gp)
-		goto top
-	}
-
-	execute(gp, inheritTime)
-}
-
-// dropg removes the association between m and the current goroutine m->curg (gp for short).
-// Typically a caller sets gp's status away from Grunning and then
-// immediately calls dropg to finish the job. The caller is also responsible
-// for arranging that gp will be restarted using ready at an
-// appropriate time. After calling dropg and arranging for gp to be
-// readied later, the caller can do other work but eventually should
-// call schedule to restart the scheduling of goroutines on this m.
-func dropg() {
-	_g_ := getg()
-
-	if _g_.m.lockedg == nil {
-		_g_.m.curg.m = nil
-		_g_.m.curg = nil
-	}
-}
-
-func parkunlock_c(gp *g, lock unsafe.Pointer) bool {
-	unlock((*mutex)(lock))
-	return true
-}
-
-// park continuation on g0.
-func park_m(gp *g) {
-	_g_ := getg()
-
-	if trace.enabled {
-		traceGoPark(_g_.m.waittraceev, _g_.m.waittraceskip, gp)
-	}
-
-	casgstatus(gp, _Grunning, _Gwaiting)
-	dropg()
-
-	if _g_.m.waitunlockf != nil {
-		fn := *(*func(*g, unsafe.Pointer) bool)(unsafe.Pointer(&_g_.m.waitunlockf))
-		ok := fn(gp, _g_.m.waitlock)
-		_g_.m.waitunlockf = nil
-		_g_.m.waitlock = nil
-		if !ok {
-			if trace.enabled {
-				traceGoUnpark(gp, 2)
-			}
-			casgstatus(gp, _Gwaiting, _Grunnable)
-			execute(gp, true) // Schedule it back, never returns.
-		}
-	}
-	schedule()
-}
-
-func goschedImpl(gp *g) {
-	status := readgstatus(gp)
-	if status&^_Gscan != _Grunning {
-		dumpgstatus(gp)
-		throw("bad g status")
-	}
-	casgstatus(gp, _Grunning, _Grunnable)
-	dropg()
-	lock(&sched.lock)
-	globrunqput(gp)
-	unlock(&sched.lock)
-
-	schedule()
-}
-
-// Gosched continuation on g0.
-func gosched_m(gp *g) {
-	if trace.enabled {
-		traceGoSched()
-	}
-	goschedImpl(gp)
-}
-
-func gopreempt_m(gp *g) {
-	if trace.enabled {
-		traceGoPreempt()
-	}
-	goschedImpl(gp)
-}
-
-// Finishes execution of the current goroutine.
-func goexit1() {
-	if raceenabled {
-		racegoend()
-	}
-	if trace.enabled {
-		traceGoEnd()
-	}
-	mcall(goexit0)
-}
-
-// goexit continuation on g0.
-func goexit0(gp *g) {
-	_g_ := getg()
-
-	casgstatus(gp, _Grunning, _Gdead)
-	gp.m = nil
-	gp.lockedm = nil
-	_g_.m.lockedg = nil
-	gp.paniconfault = false
-	gp._defer = nil // should be true already but just in case.
-	gp._panic = nil // non-nil for Goexit during panic. points at stack-allocated data.
-	gp.writebuf = nil
-	gp.waitreason = ""
-	gp.param = nil
-
-	dropg()
-
-	if _g_.m.locked&^_LockExternal != 0 {
-		print("invalid m->locked = ", _g_.m.locked, "\n")
-		throw("internal lockOSThread error")
-	}
-	_g_.m.locked = 0
-	gfput(_g_.m.p.ptr(), gp)
-	schedule()
-}
-
-//go:nosplit
-//go:nowritebarrier
-func save(pc, sp uintptr) {
-	_g_ := getg()
-
-	_g_.sched.pc = pc
-	_g_.sched.sp = sp
-	_g_.sched.lr = 0
-	_g_.sched.ret = 0
-	_g_.sched.ctxt = nil
-	_g_.sched.g = guintptr(unsafe.Pointer(_g_))
-}
-
-// The goroutine g is about to enter a system call.
-// Record that it's not using the cpu anymore.
-// This is called only from the go syscall library and cgocall,
-// not from the low-level system calls used by the
-//
-// Entersyscall cannot split the stack: the gosave must
-// make g->sched refer to the caller's stack segment, because
-// entersyscall is going to return immediately after.
-//
-// Nothing entersyscall calls can split the stack either.
-// We cannot safely move the stack during an active call to syscall,
-// because we do not know which of the uintptr arguments are
-// really pointers (back into the stack).
-// In practice, this means that we make the fast path run through
-// entersyscall doing no-split things, and the slow path has to use systemstack
-// to run bigger things on the system stack.
-//
-// reentersyscall is the entry point used by cgo callbacks, where explicitly
-// saved SP and PC are restored. This is needed when exitsyscall will be called
-// from a function further up in the call stack than the parent, as g->syscallsp
-// must always point to a valid stack frame. entersyscall below is the normal
-// entry point for syscalls, which obtains the SP and PC from the caller.
-//
-// Syscall tracing:
-// At the start of a syscall we emit traceGoSysCall to capture the stack trace.
-// If the syscall does not block, that is it, we do not emit any other events.
-// If the syscall blocks (that is, P is retaken), retaker emits traceGoSysBlock;
-// when syscall returns we emit traceGoSysExit and when the goroutine starts running
-// (potentially instantly, if exitsyscallfast returns true) we emit traceGoStart.
-// To ensure that traceGoSysExit is emitted strictly after traceGoSysBlock,
-// we remember current value of syscalltick in m (_g_.m.syscalltick = _g_.m.p.ptr().syscalltick),
-// whoever emits traceGoSysBlock increments p.syscalltick afterwards;
-// and we wait for the increment before emitting traceGoSysExit.
-// Note that the increment is done even if tracing is not enabled,
-// because tracing can be enabled in the middle of syscall. We don't want the wait to hang.
-//
-//go:nosplit
-func reentersyscall(pc, sp uintptr) {
-	_g_ := getg()
-
-	// Disable preemption because during this function g is in Gsyscall status,
-	// but can have inconsistent g->sched, do not let GC observe it.
-	_g_.m.locks++
-
-	if trace.enabled {
-		systemstack(traceGoSysCall)
-	}
-
-	// Entersyscall must not call any function that might split/grow the stack.
-	// (See details in comment above.)
-	// Catch calls that might, by replacing the stack guard with something that
-	// will trip any stack check and leaving a flag to tell newstack to die.
-	_g_.stackguard0 = stackPreempt
-	_g_.throwsplit = true
-
-	// Leave SP around for GC and traceback.
-	save(pc, sp)
-	_g_.syscallsp = sp
-	_g_.syscallpc = pc
-	casgstatus(_g_, _Grunning, _Gsyscall)
-	if _g_.syscallsp < _g_.stack.lo || _g_.stack.hi < _g_.syscallsp {
-		systemstack(func() {
-			print("entersyscall inconsistent ", hex(_g_.syscallsp), " [", hex(_g_.stack.lo), ",", hex(_g_.stack.hi), "]\n")
-			throw("entersyscall")
-		})
-	}
-
-	if atomicload(&sched.sysmonwait) != 0 { // TODO: fast atomic
-		systemstack(entersyscall_sysmon)
-		save(pc, sp)
-	}
-
-	if _g_.m.p.ptr().runSafePointFn != 0 {
-		// runSafePointFn may stack split if run on this stack
-		systemstack(runSafePointFn)
-		save(pc, sp)
-	}
-
-	_g_.m.syscalltick = _g_.m.p.ptr().syscalltick
-	_g_.sysblocktraced = true
-	_g_.m.mcache = nil
-	_g_.m.p.ptr().m = 0
-	atomicstore(&_g_.m.p.ptr().status, _Psyscall)
-	if sched.gcwaiting != 0 {
-		systemstack(entersyscall_gcwait)
-		save(pc, sp)
-	}
-
-	// Goroutines must not split stacks in Gsyscall status (it would corrupt g->sched).
-	// We set _StackGuard to StackPreempt so that first split stack check calls morestack.
-	// Morestack detects this case and throws.
-	_g_.stackguard0 = stackPreempt
-	_g_.m.locks--
-}
-
-// Standard syscall entry used by the go syscall library and normal cgo calls.
-//go:nosplit
-func entersyscall(dummy int32) {
-	reentersyscall(getcallerpc(unsafe.Pointer(&dummy)), getcallersp(unsafe.Pointer(&dummy)))
-}
-
-func entersyscall_sysmon() {
-	lock(&sched.lock)
-	if atomicload(&sched.sysmonwait) != 0 {
-		atomicstore(&sched.sysmonwait, 0)
-		notewakeup(&sched.sysmonnote)
-	}
-	unlock(&sched.lock)
-}
-
-func entersyscall_gcwait() {
-	_g_ := getg()
-	_p_ := _g_.m.p.ptr()
-
-	lock(&sched.lock)
-	if sched.stopwait > 0 && cas(&_p_.status, _Psyscall, _Pgcstop) {
-		if trace.enabled {
-			traceGoSysBlock(_p_)
-			traceProcStop(_p_)
-		}
-		_p_.syscalltick++
-		if sched.stopwait--; sched.stopwait == 0 {
-			notewakeup(&sched.stopnote)
-		}
-	}
-	unlock(&sched.lock)
-}
-
-// The same as entersyscall(), but with a hint that the syscall is blocking.
-//go:nosplit
-func entersyscallblock(dummy int32) {
-	_g_ := getg()
-
-	_g_.m.locks++ // see comment in entersyscall
-	_g_.throwsplit = true
-	_g_.stackguard0 = stackPreempt // see comment in entersyscall
-	_g_.m.syscalltick = _g_.m.p.ptr().syscalltick
-	_g_.sysblocktraced = true
-	_g_.m.p.ptr().syscalltick++
-
-	// Leave SP around for GC and traceback.
-	pc := getcallerpc(unsafe.Pointer(&dummy))
-	sp := getcallersp(unsafe.Pointer(&dummy))
-	save(pc, sp)
-	_g_.syscallsp = _g_.sched.sp
-	_g_.syscallpc = _g_.sched.pc
-	if _g_.syscallsp < _g_.stack.lo || _g_.stack.hi < _g_.syscallsp {
-		sp1 := sp
-		sp2 := _g_.sched.sp
-		sp3 := _g_.syscallsp
-		systemstack(func() {
-			print("entersyscallblock inconsistent ", hex(sp1), " ", hex(sp2), " ", hex(sp3), " [", hex(_g_.stack.lo), ",", hex(_g_.stack.hi), "]\n")
-			throw("entersyscallblock")
-		})
-	}
-	casgstatus(_g_, _Grunning, _Gsyscall)
-	if _g_.syscallsp < _g_.stack.lo || _g_.stack.hi < _g_.syscallsp {
-		systemstack(func() {
-			print("entersyscallblock inconsistent ", hex(sp), " ", hex(_g_.sched.sp), " ", hex(_g_.syscallsp), " [", hex(_g_.stack.lo), ",", hex(_g_.stack.hi), "]\n")
-			throw("entersyscallblock")
-		})
-	}
-
-	systemstack(entersyscallblock_handoff)
-
-	// Resave for traceback during blocked call.
-	save(getcallerpc(unsafe.Pointer(&dummy)), getcallersp(unsafe.Pointer(&dummy)))
-
-	_g_.m.locks--
-}
-
-func entersyscallblock_handoff() {
-	if trace.enabled {
-		traceGoSysCall()
-		traceGoSysBlock(getg().m.p.ptr())
-	}
-	handoffp(releasep())
-}
-
-// The goroutine g exited its system call.
-// Arrange for it to run on a cpu again.
-// This is called only from the go syscall library, not
-// from the low-level system calls used by the
-//go:nosplit
-func exitsyscall(dummy int32) {
-	_g_ := getg()
-
-	_g_.m.locks++ // see comment in entersyscall
-	if getcallersp(unsafe.Pointer(&dummy)) > _g_.syscallsp {
-		throw("exitsyscall: syscall frame is no longer valid")
-	}
-
-	_g_.waitsince = 0
-	oldp := _g_.m.p.ptr()
-	if exitsyscallfast() {
-		if _g_.m.mcache == nil {
-			throw("lost mcache")
-		}
-		if trace.enabled {
-			if oldp != _g_.m.p.ptr() || _g_.m.syscalltick != _g_.m.p.ptr().syscalltick {
-				systemstack(traceGoStart)
-			}
-		}
-		// There's a cpu for us, so we can run.
-		_g_.m.p.ptr().syscalltick++
-		// We need to cas the status and scan before resuming...
-		casgstatus(_g_, _Gsyscall, _Grunning)
-
-		// Garbage collector isn't running (since we are),
-		// so okay to clear syscallsp.
-		_g_.syscallsp = 0
-		_g_.m.locks--
-		if _g_.preempt {
-			// restore the preemption request in case we've cleared it in newstack
-			_g_.stackguard0 = stackPreempt
-		} else {
-			// otherwise restore the real _StackGuard, we've spoiled it in entersyscall/entersyscallblock
-			_g_.stackguard0 = _g_.stack.lo + _StackGuard
-		}
-		_g_.throwsplit = false
-		return
-	}
-
-	_g_.sysexitticks = 0
-	_g_.sysexitseq = 0
-	if trace.enabled {
-		// Wait till traceGoSysBlock event is emitted.
-		// This ensures consistency of the trace (the goroutine is started after it is blocked).
-		for oldp != nil && oldp.syscalltick == _g_.m.syscalltick {
-			osyield()
-		}
-		// We can't trace syscall exit right now because we don't have a P.
-		// Tracing code can invoke write barriers that cannot run without a P.
-		// So instead we remember the syscall exit time and emit the event
-		// in execute when we have a P.
-		_g_.sysexitseq, _g_.sysexitticks = tracestamp()
-	}
-
-	_g_.m.locks--
-
-	// Call the scheduler.
-	mcall(exitsyscall0)
-
-	if _g_.m.mcache == nil {
-		throw("lost mcache")
-	}
-
-	// Scheduler returned, so we're allowed to run now.
-	// Delete the syscallsp information that we left for
-	// the garbage collector during the system call.
-	// Must wait until now because until gosched returns
-	// we don't know for sure that the garbage collector
-	// is not running.
-	_g_.syscallsp = 0
-	_g_.m.p.ptr().syscalltick++
-	_g_.throwsplit = false
-}
-
-//go:nosplit
-func exitsyscallfast() bool {
-	_g_ := getg()
-
-	// Freezetheworld sets stopwait but does not retake P's.
-	if sched.stopwait == freezeStopWait {
-		_g_.m.mcache = nil
-		_g_.m.p = 0
-		return false
-	}
-
-	// Try to re-acquire the last P.
-	if _g_.m.p != 0 && _g_.m.p.ptr().status == _Psyscall && cas(&_g_.m.p.ptr().status, _Psyscall, _Prunning) {
-		// There's a cpu for us, so we can run.
-		_g_.m.mcache = _g_.m.p.ptr().mcache
-		_g_.m.p.ptr().m.set(_g_.m)
-		if _g_.m.syscalltick != _g_.m.p.ptr().syscalltick {
-			if trace.enabled {
-				// The p was retaken and then enter into syscall again (since _g_.m.syscalltick has changed).
-				// traceGoSysBlock for this syscall was already emitted,
-				// but here we effectively retake the p from the new syscall running on the same p.
-				systemstack(func() {
-					// Denote blocking of the new syscall.
-					traceGoSysBlock(_g_.m.p.ptr())
-					// Denote completion of the current syscall.
-					traceGoSysExit(tracestamp())
-				})
-			}
-			_g_.m.p.ptr().syscalltick++
-		}
-		return true
-	}
-
-	// Try to get any other idle P.
-	oldp := _g_.m.p.ptr()
-	_g_.m.mcache = nil
-	_g_.m.p = 0
-	if sched.pidle != 0 {
-		var ok bool
-		systemstack(func() {
-			ok = exitsyscallfast_pidle()
-			if ok && trace.enabled {
-				if oldp != nil {
-					// Wait till traceGoSysBlock event is emitted.
-					// This ensures consistency of the trace (the goroutine is started after it is blocked).
-					for oldp.syscalltick == _g_.m.syscalltick {
-						osyield()
-					}
-				}
-				traceGoSysExit(tracestamp())
-			}
-		})
-		if ok {
-			return true
-		}
-	}
-	return false
-}
-
-func exitsyscallfast_pidle() bool {
-	lock(&sched.lock)
-	_p_ := pidleget()
-	if _p_ != nil && atomicload(&sched.sysmonwait) != 0 {
-		atomicstore(&sched.sysmonwait, 0)
-		notewakeup(&sched.sysmonnote)
-	}
-	unlock(&sched.lock)
-	if _p_ != nil {
-		acquirep(_p_)
-		return true
-	}
-	return false
-}
-
-// exitsyscall slow path on g0.
-// Failed to acquire P, enqueue gp as runnable.
-func exitsyscall0(gp *g) {
-	_g_ := getg()
-
-	casgstatus(gp, _Gsyscall, _Grunnable)
-	dropg()
-	lock(&sched.lock)
-	_p_ := pidleget()
-	if _p_ == nil {
-		globrunqput(gp)
-	} else if atomicload(&sched.sysmonwait) != 0 {
-		atomicstore(&sched.sysmonwait, 0)
-		notewakeup(&sched.sysmonnote)
-	}
-	unlock(&sched.lock)
-	if _p_ != nil {
-		acquirep(_p_)
-		execute(gp, false) // Never returns.
-	}
-	if _g_.m.lockedg != nil {
-		// Wait until another thread schedules gp and so m again.
-		stoplockedm()
-		execute(gp, false) // Never returns.
-	}
-	stopm()
-	schedule() // Never returns.
-}
-
-func beforefork() {
-	gp := getg().m.curg
-
-	// Fork can hang if preempted with signals frequently enough (see issue 5517).
-	// Ensure that we stay on the same M where we disable profiling.
-	gp.m.locks++
-	if gp.m.profilehz != 0 {
-		resetcpuprofiler(0)
-	}
-
-	// This function is called before fork in syscall package.
-	// Code between fork and exec must not allocate memory nor even try to grow stack.
-	// Here we spoil g->_StackGuard to reliably detect any attempts to grow stack.
-	// runtime_AfterFork will undo this in parent process, but not in child.
-	gp.stackguard0 = stackFork
-}
-
-// Called from syscall package before fork.
-//go:linkname syscall_runtime_BeforeFork syscall.runtime_BeforeFork
-//go:nosplit
-func syscall_runtime_BeforeFork() {
-	systemstack(beforefork)
-}
-
-func afterfork() {
-	gp := getg().m.curg
-
-	// See the comment in beforefork.
-	gp.stackguard0 = gp.stack.lo + _StackGuard
-
-	hz := sched.profilehz
-	if hz != 0 {
-		resetcpuprofiler(hz)
-	}
-	gp.m.locks--
-}
-
-// Called from syscall package after fork in parent.
-//go:linkname syscall_runtime_AfterFork syscall.runtime_AfterFork
-//go:nosplit
-func syscall_runtime_AfterFork() {
-	systemstack(afterfork)
-}
-
-// Allocate a new g, with a stack big enough for stacksize bytes.
-func malg(stacksize int32) *g {
-	newg := new(g)
-	if stacksize >= 0 {
-		stacksize = round2(_StackSystem + stacksize)
-		systemstack(func() {
-			newg.stack, newg.stkbar = stackalloc(uint32(stacksize))
-		})
-		newg.stackguard0 = newg.stack.lo + _StackGuard
-		newg.stackguard1 = ^uintptr(0)
-		newg.stackAlloc = uintptr(stacksize)
-	}
-	return newg
-}
-
-// Create a new g running fn with siz bytes of arguments.
-// Put it on the queue of g's waiting to run.
-// The compiler turns a go statement into a call to this.
-// Cannot split the stack because it assumes that the arguments
-// are available sequentially after &fn; they would not be
-// copied if a stack split occurred.
-//go:nosplit
-func newproc(siz int32, fn *funcval) {
-	argp := add(unsafe.Pointer(&fn), ptrSize)
-	pc := getcallerpc(unsafe.Pointer(&siz))
-	systemstack(func() {
-		newproc1(fn, (*uint8)(argp), siz, 0, pc)
-	})
-}
-
-// Create a new g running fn with narg bytes of arguments starting
-// at argp and returning nret bytes of results.  callerpc is the
-// address of the go statement that created this.  The new g is put
-// on the queue of g's waiting to run.
-func newproc1(fn *funcval, argp *uint8, narg int32, nret int32, callerpc uintptr) *g {
-	_g_ := getg()
-
-	if fn == nil {
-		_g_.m.throwing = -1 // do not dump full stacks
-		throw("go of nil func value")
-	}
-	_g_.m.locks++ // disable preemption because it can be holding p in a local var
-	siz := narg + nret
-	siz = (siz + 7) &^ 7
-
-	// We could allocate a larger initial stack if necessary.
-	// Not worth it: this is almost always an error.
-	// 4*sizeof(uintreg): extra space added below
-	// sizeof(uintreg): caller's LR (arm) or return address (x86, in gostartcall).
-	if siz >= _StackMin-4*regSize-regSize {
-		throw("newproc: function arguments too large for new goroutine")
-	}
-
-	_p_ := _g_.m.p.ptr()
-	newg := gfget(_p_)
-	if newg == nil {
-		newg = malg(_StackMin)
-		casgstatus(newg, _Gidle, _Gdead)
-		allgadd(newg) // publishes with a g->status of Gdead so GC scanner doesn't look at uninitialized stack.
-	}
-	if newg.stack.hi == 0 {
-		throw("newproc1: newg missing stack")
-	}
-
-	if readgstatus(newg) != _Gdead {
-		throw("newproc1: new g is not Gdead")
-	}
-
-	totalSize := 4*regSize + uintptr(siz) // extra space in case of reads slightly beyond frame
-	if hasLinkRegister {
-		totalSize += ptrSize
-	}
-	totalSize += -totalSize & (spAlign - 1) // align to spAlign
-	sp := newg.stack.hi - totalSize
-	spArg := sp
-	if hasLinkRegister {
-		// caller's LR
-		*(*unsafe.Pointer)(unsafe.Pointer(sp)) = nil
-		spArg += ptrSize
-	}
-	memmove(unsafe.Pointer(spArg), unsafe.Pointer(argp), uintptr(narg))
-
-	memclr(unsafe.Pointer(&newg.sched), unsafe.Sizeof(newg.sched))
-	newg.sched.sp = sp
-	newg.sched.pc = funcPC(goexit) + _PCQuantum // +PCQuantum so that previous instruction is in same function
-	newg.sched.g = guintptr(unsafe.Pointer(newg))
-	gostartcallfn(&newg.sched, fn)
-	newg.gopc = callerpc
-	newg.startpc = fn.fn
-	casgstatus(newg, _Gdead, _Grunnable)
-
-	if _p_.goidcache == _p_.goidcacheend {
-		// Sched.goidgen is the last allocated id,
-		// this batch must be [sched.goidgen+1, sched.goidgen+GoidCacheBatch].
-		// At startup sched.goidgen=0, so main goroutine receives goid=1.
-		_p_.goidcache = xadd64(&sched.goidgen, _GoidCacheBatch)
-		_p_.goidcache -= _GoidCacheBatch - 1
-		_p_.goidcacheend = _p_.goidcache + _GoidCacheBatch
-	}
-	newg.goid = int64(_p_.goidcache)
-	_p_.goidcache++
-	if raceenabled {
-		newg.racectx = racegostart(callerpc)
-	}
-	if trace.enabled {
-		traceGoCreate(newg, newg.startpc)
-	}
-	runqput(_p_, newg, true)
-
-	if atomicload(&sched.npidle) != 0 && atomicload(&sched.nmspinning) == 0 && unsafe.Pointer(fn.fn) != unsafe.Pointer(funcPC(main)) { // TODO: fast atomic
-		wakep()
-	}
-	_g_.m.locks--
-	if _g_.m.locks == 0 && _g_.preempt { // restore the preemption request in case we've cleared it in newstack
-		_g_.stackguard0 = stackPreempt
-	}
-	return newg
-}
-
-// Put on gfree list.
-// If local list is too long, transfer a batch to the global list.
-func gfput(_p_ *p, gp *g) {
-	if readgstatus(gp) != _Gdead {
-		throw("gfput: bad status (not Gdead)")
-	}
-
-	stksize := gp.stackAlloc
-
-	if stksize != _FixedStack {
-		// non-standard stack size - free it.
-		stackfree(gp.stack, gp.stackAlloc)
-		gp.stack.lo = 0
-		gp.stack.hi = 0
-		gp.stackguard0 = 0
-		gp.stkbar = nil
-		gp.stkbarPos = 0
-	} else {
-		// Reset stack barriers.
-		gp.stkbar = gp.stkbar[:0]
-		gp.stkbarPos = 0
-	}
-
-	gp.schedlink.set(_p_.gfree)
-	_p_.gfree = gp
-	_p_.gfreecnt++
-	if _p_.gfreecnt >= 64 {
-		lock(&sched.gflock)
-		for _p_.gfreecnt >= 32 {
-			_p_.gfreecnt--
-			gp = _p_.gfree
-			_p_.gfree = gp.schedlink.ptr()
-			gp.schedlink.set(sched.gfree)
-			sched.gfree = gp
-			sched.ngfree++
-		}
-		unlock(&sched.gflock)
-	}
-}
-
-// Get from gfree list.
-// If local list is empty, grab a batch from global list.
-func gfget(_p_ *p) *g {
-retry:
-	gp := _p_.gfree
-	if gp == nil && sched.gfree != nil {
-		lock(&sched.gflock)
-		for _p_.gfreecnt < 32 && sched.gfree != nil {
-			_p_.gfreecnt++
-			gp = sched.gfree
-			sched.gfree = gp.schedlink.ptr()
-			sched.ngfree--
-			gp.schedlink.set(_p_.gfree)
-			_p_.gfree = gp
-		}
-		unlock(&sched.gflock)
-		goto retry
-	}
-	if gp != nil {
-		_p_.gfree = gp.schedlink.ptr()
-		_p_.gfreecnt--
-		if gp.stack.lo == 0 {
-			// Stack was deallocated in gfput.  Allocate a new one.
-			systemstack(func() {
-				gp.stack, gp.stkbar = stackalloc(_FixedStack)
-			})
-			gp.stackguard0 = gp.stack.lo + _StackGuard
-			gp.stackAlloc = _FixedStack
-		} else {
-			if raceenabled {
-				racemalloc(unsafe.Pointer(gp.stack.lo), gp.stackAlloc)
-			}
-		}
-	}
-	return gp
-}
-
-// Purge all cached G's from gfree list to the global list.
-func gfpurge(_p_ *p) {
-	lock(&sched.gflock)
-	for _p_.gfreecnt != 0 {
-		_p_.gfreecnt--
-		gp := _p_.gfree
-		_p_.gfree = gp.schedlink.ptr()
-		gp.schedlink.set(sched.gfree)
-		sched.gfree = gp
-		sched.ngfree++
-	}
-	unlock(&sched.gflock)
-}
-
-// Breakpoint executes a breakpoint trap.
-func Breakpoint() {
-	breakpoint()
-}
-
-// dolockOSThread is called by LockOSThread and lockOSThread below
-// after they modify m.locked. Do not allow preemption during this call,
-// or else the m might be different in this function than in the caller.
-//go:nosplit
-func dolockOSThread() {
-	_g_ := getg()
-	_g_.m.lockedg = _g_
-	_g_.lockedm = _g_.m
-}
-
-//go:nosplit
-
-// LockOSThread wires the calling goroutine to its current operating system thread.
-// Until the calling goroutine exits or calls UnlockOSThread, it will always
-// execute in that thread, and no other goroutine can.
-func LockOSThread() {
-	getg().m.locked |= _LockExternal
-	dolockOSThread()
-}
-
-//go:nosplit
-func lockOSThread() {
-	getg().m.locked += _LockInternal
-	dolockOSThread()
-}
-
-// dounlockOSThread is called by UnlockOSThread and unlockOSThread below
-// after they update m->locked. Do not allow preemption during this call,
-// or else the m might be in different in this function than in the caller.
-//go:nosplit
-func dounlockOSThread() {
-	_g_ := getg()
-	if _g_.m.locked != 0 {
-		return
-	}
-	_g_.m.lockedg = nil
-	_g_.lockedm = nil
-}
-
-//go:nosplit
-
-// UnlockOSThread unwires the calling goroutine from its fixed operating system thread.
-// If the calling goroutine has not called LockOSThread, UnlockOSThread is a no-op.
-func UnlockOSThread() {
-	getg().m.locked &^= _LockExternal
-	dounlockOSThread()
-}
-
-//go:nosplit
-func unlockOSThread() {
-	_g_ := getg()
-	if _g_.m.locked < _LockInternal {
-		systemstack(badunlockosthread)
-	}
-	_g_.m.locked -= _LockInternal
-	dounlockOSThread()
-}
-
-func badunlockosthread() {
-	throw("runtime: internal error: misuse of lockOSThread/unlockOSThread")
-}
-
-func gcount() int32 {
-	n := int32(allglen) - sched.ngfree
-	for i := 0; ; i++ {
-		_p_ := allp[i]
-		if _p_ == nil {
-			break
-		}
-		n -= _p_.gfreecnt
-	}
-
-	// All these variables can be changed concurrently, so the result can be inconsistent.
-	// But at least the current goroutine is running.
-	if n < 1 {
-		n = 1
-	}
-	return n
-}
-
-func mcount() int32 {
-	return sched.mcount
-}
-
-var prof struct {
-	lock uint32
-	hz   int32
-}
-
-func _System()       { _System() }
-func _ExternalCode() { _ExternalCode() }
-func _GC()           { _GC() }
-
-// Called if we receive a SIGPROF signal.
-func sigprof(pc, sp, lr uintptr, gp *g, mp *m) {
-	if prof.hz == 0 {
-		return
-	}
-
-	// Profiling runs concurrently with GC, so it must not allocate.
-	mp.mallocing++
-
-	// Define that a "user g" is a user-created goroutine, and a "system g"
-	// is one that is m->g0 or m->gsignal.
-	//
-	// We might be interrupted for profiling halfway through a
-	// goroutine switch. The switch involves updating three (or four) values:
-	// g, PC, SP, and (on arm) LR. The PC must be the last to be updated,
-	// because once it gets updated the new g is running.
-	//
-	// When switching from a user g to a system g, LR is not considered live,
-	// so the update only affects g, SP, and PC. Since PC must be last, there
-	// the possible partial transitions in ordinary execution are (1) g alone is updated,
-	// (2) both g and SP are updated, and (3) SP alone is updated.
-	// If SP or g alone is updated, we can detect the partial transition by checking
-	// whether the SP is within g's stack bounds. (We could also require that SP
-	// be changed only after g, but the stack bounds check is needed by other
-	// cases, so there is no need to impose an additional requirement.)
-	//
-	// There is one exceptional transition to a system g, not in ordinary execution.
-	// When a signal arrives, the operating system starts the signal handler running
-	// with an updated PC and SP. The g is updated last, at the beginning of the
-	// handler. There are two reasons this is okay. First, until g is updated the
-	// g and SP do not match, so the stack bounds check detects the partial transition.
-	// Second, signal handlers currently run with signals disabled, so a profiling
-	// signal cannot arrive during the handler.
-	//
-	// When switching from a system g to a user g, there are three possibilities.
-	//
-	// First, it may be that the g switch has no PC update, because the SP
-	// either corresponds to a user g throughout (as in asmcgocall)
-	// or because it has been arranged to look like a user g frame
-	// (as in cgocallback_gofunc). In this case, since the entire
-	// transition is a g+SP update, a partial transition updating just one of
-	// those will be detected by the stack bounds check.
-	//
-	// Second, when returning from a signal handler, the PC and SP updates
-	// are performed by the operating system in an atomic update, so the g
-	// update must be done before them. The stack bounds check detects
-	// the partial transition here, and (again) signal handlers run with signals
-	// disabled, so a profiling signal cannot arrive then anyway.
-	//
-	// Third, the common case: it may be that the switch updates g, SP, and PC
-	// separately. If the PC is within any of the functions that does this,
-	// we don't ask for a traceback. C.F. the function setsSP for more about this.
-	//
-	// There is another apparently viable approach, recorded here in case
-	// the "PC within setsSP function" check turns out not to be usable.
-	// It would be possible to delay the update of either g or SP until immediately
-	// before the PC update instruction. Then, because of the stack bounds check,
-	// the only problematic interrupt point is just before that PC update instruction,
-	// and the sigprof handler can detect that instruction and simulate stepping past
-	// it in order to reach a consistent state. On ARM, the update of g must be made
-	// in two places (in R10 and also in a TLS slot), so the delayed update would
-	// need to be the SP update. The sigprof handler must read the instruction at
-	// the current PC and if it was the known instruction (for example, JMP BX or
-	// MOV R2, PC), use that other register in place of the PC value.
-	// The biggest drawback to this solution is that it requires that we can tell
-	// whether it's safe to read from the memory pointed at by PC.
-	// In a correct program, we can test PC == nil and otherwise read,
-	// but if a profiling signal happens at the instant that a program executes
-	// a bad jump (before the program manages to handle the resulting fault)
-	// the profiling handler could fault trying to read nonexistent memory.
-	//
-	// To recap, there are no constraints on the assembly being used for the
-	// transition. We simply require that g and SP match and that the PC is not
-	// in gogo.
-	traceback := true
-	haveStackLock := false
-	if gp == nil || sp < gp.stack.lo || gp.stack.hi < sp || setsSP(pc) {
-		traceback = false
-	} else if gp.m.curg != nil {
-		if gcTryLockStackBarriers(gp.m.curg) {
-			haveStackLock = true
-		} else {
-			// Stack barriers are being inserted or
-			// removed, so we can't get a consistent
-			// traceback right now.
-			traceback = false
-		}
-	}
-	var stk [maxCPUProfStack]uintptr
-	n := 0
-	if mp.ncgo > 0 && mp.curg != nil && mp.curg.syscallpc != 0 && mp.curg.syscallsp != 0 {
-		// Cgo, we can't unwind and symbolize arbitrary C code,
-		// so instead collect Go stack that leads to the cgo call.
-		// This is especially important on windows, since all syscalls are cgo calls.
-		n = gentraceback(mp.curg.syscallpc, mp.curg.syscallsp, 0, mp.curg, 0, &stk[0], len(stk), nil, nil, 0)
-	} else if traceback {
-		flags := uint(_TraceTrap | _TraceJumpStack)
-		if gp.m.curg != nil && readgstatus(gp.m.curg) == _Gcopystack {
-			// We can traceback the system stack, but
-			// don't jump to the potentially inconsistent
-			// user stack.
-			flags &^= _TraceJumpStack
-		}
-		n = gentraceback(pc, sp, lr, gp, 0, &stk[0], len(stk), nil, nil, flags)
-	}
-	if !traceback || n <= 0 {
-		// Normal traceback is impossible or has failed.
-		// See if it falls into several common cases.
-		n = 0
-		if GOOS == "windows" && n == 0 && mp.libcallg != 0 && mp.libcallpc != 0 && mp.libcallsp != 0 {
-			// Libcall, i.e. runtime syscall on windows.
-			// Collect Go stack that leads to the call.
-			n = gentraceback(mp.libcallpc, mp.libcallsp, 0, mp.libcallg.ptr(), 0, &stk[0], len(stk), nil, nil, 0)
-		}
-		if n == 0 {
-			// If all of the above has failed, account it against abstract "System" or "GC".
-			n = 2
-			// "ExternalCode" is better than "etext".
-			if pc > firstmoduledata.etext {
-				pc = funcPC(_ExternalCode) + _PCQuantum
-			}
-			stk[0] = pc
-			if mp.preemptoff != "" || mp.helpgc != 0 {
-				stk[1] = funcPC(_GC) + _PCQuantum
-			} else {
-				stk[1] = funcPC(_System) + _PCQuantum
-			}
-		}
-	}
-	if haveStackLock {
-		gcUnlockStackBarriers(gp.m.curg)
-	}
-
-	if prof.hz != 0 {
-		// Simple cas-lock to coordinate with setcpuprofilerate.
-		for !cas(&prof.lock, 0, 1) {
-			osyield()
-		}
-		if prof.hz != 0 {
-			cpuprof.add(stk[:n])
-		}
-		atomicstore(&prof.lock, 0)
-	}
-	mp.mallocing--
-}
-
-// Reports whether a function will set the SP
-// to an absolute value. Important that
-// we don't traceback when these are at the bottom
-// of the stack since we can't be sure that we will
-// find the caller.
-//
-// If the function is not on the bottom of the stack
-// we assume that it will have set it up so that traceback will be consistent,
-// either by being a traceback terminating function
-// or putting one on the stack at the right offset.
-func setsSP(pc uintptr) bool {
-	f := findfunc(pc)
-	if f == nil {
-		// couldn't find the function for this PC,
-		// so assume the worst and stop traceback
-		return true
-	}
-	switch f.entry {
-	case gogoPC, systemstackPC, mcallPC, morestackPC:
-		return true
-	}
-	return false
-}
-
-// Arrange to call fn with a traceback hz times a second.
-func setcpuprofilerate_m(hz int32) {
-	// Force sane arguments.
-	if hz < 0 {
-		hz = 0
-	}
-
-	// Disable preemption, otherwise we can be rescheduled to another thread
-	// that has profiling enabled.
-	_g_ := getg()
-	_g_.m.locks++
-
-	// Stop profiler on this thread so that it is safe to lock prof.
-	// if a profiling signal came in while we had prof locked,
-	// it would deadlock.
-	resetcpuprofiler(0)
-
-	for !cas(&prof.lock, 0, 1) {
-		osyield()
-	}
-	prof.hz = hz
-	atomicstore(&prof.lock, 0)
-
-	lock(&sched.lock)
-	sched.profilehz = hz
-	unlock(&sched.lock)
-
-	if hz != 0 {
-		resetcpuprofiler(hz)
-	}
-
-	_g_.m.locks--
-}
-
-// Change number of processors.  The world is stopped, sched is locked.
-// gcworkbufs are not being modified by either the GC or
-// the write barrier code.
-// Returns list of Ps with local work, they need to be scheduled by the caller.
-func procresize(nprocs int32) *p {
-	old := gomaxprocs
-	if old < 0 || old > _MaxGomaxprocs || nprocs <= 0 || nprocs > _MaxGomaxprocs {
-		throw("procresize: invalid arg")
-	}
-	if trace.enabled {
-		traceGomaxprocs(nprocs)
-	}
-
-	// update statistics
-	now := nanotime()
-	if sched.procresizetime != 0 {
-		sched.totaltime += int64(old) * (now - sched.procresizetime)
-	}
-	sched.procresizetime = now
-
-	// initialize new P's
-	for i := int32(0); i < nprocs; i++ {
-		pp := allp[i]
-		if pp == nil {
-			pp = new(p)
-			pp.id = i
-			pp.status = _Pgcstop
-			pp.sudogcache = pp.sudogbuf[:0]
-			for i := range pp.deferpool {
-				pp.deferpool[i] = pp.deferpoolbuf[i][:0]
-			}
-			atomicstorep(unsafe.Pointer(&allp[i]), unsafe.Pointer(pp))
-		}
-		if pp.mcache == nil {
-			if old == 0 && i == 0 {
-				if getg().m.mcache == nil {
-					throw("missing mcache?")
-				}
-				pp.mcache = getg().m.mcache // bootstrap
-			} else {
-				pp.mcache = allocmcache()
-			}
-		}
-	}
-
-	// free unused P's
-	for i := nprocs; i < old; i++ {
-		p := allp[i]
-		if trace.enabled {
-			if p == getg().m.p.ptr() {
-				// moving to p[0], pretend that we were descheduled
-				// and then scheduled again to keep the trace sane.
-				traceGoSched()
-				traceProcStop(p)
-			}
-		}
-		// move all runnable goroutines to the global queue
-		for p.runqhead != p.runqtail {
-			// pop from tail of local queue
-			p.runqtail--
-			gp := p.runq[p.runqtail%uint32(len(p.runq))]
-			// push onto head of global queue
-			globrunqputhead(gp)
-		}
-		if p.runnext != 0 {
-			globrunqputhead(p.runnext.ptr())
-			p.runnext = 0
-		}
-		// if there's a background worker, make it runnable and put
-		// it on the global queue so it can clean itself up
-		if p.gcBgMarkWorker != nil {
-			casgstatus(p.gcBgMarkWorker, _Gwaiting, _Grunnable)
-			if trace.enabled {
-				traceGoUnpark(p.gcBgMarkWorker, 0)
-			}
-			globrunqput(p.gcBgMarkWorker)
-			p.gcBgMarkWorker = nil
-		}
-		for i := range p.sudogbuf {
-			p.sudogbuf[i] = nil
-		}
-		p.sudogcache = p.sudogbuf[:0]
-		for i := range p.deferpool {
-			for j := range p.deferpoolbuf[i] {
-				p.deferpoolbuf[i][j] = nil
-			}
-			p.deferpool[i] = p.deferpoolbuf[i][:0]
-		}
-		freemcache(p.mcache)
-		p.mcache = nil
-		gfpurge(p)
-		traceProcFree(p)
-		p.status = _Pdead
-		// can't free P itself because it can be referenced by an M in syscall
-	}
-
-	_g_ := getg()
-	if _g_.m.p != 0 && _g_.m.p.ptr().id < nprocs {
-		// continue to use the current P
-		_g_.m.p.ptr().status = _Prunning
-	} else {
-		// release the current P and acquire allp[0]
-		if _g_.m.p != 0 {
-			_g_.m.p.ptr().m = 0
-		}
-		_g_.m.p = 0
-		_g_.m.mcache = nil
-		p := allp[0]
-		p.m = 0
-		p.status = _Pidle
-		acquirep(p)
-		if trace.enabled {
-			traceGoStart()
-		}
-	}
-	var runnablePs *p
-	for i := nprocs - 1; i >= 0; i-- {
-		p := allp[i]
-		if _g_.m.p.ptr() == p {
-			continue
-		}
-		p.status = _Pidle
-		if runqempty(p) {
-			pidleput(p)
-		} else {
-			p.m.set(mget())
-			p.link.set(runnablePs)
-			runnablePs = p
-		}
-	}
-	var int32p *int32 = &gomaxprocs // make compiler check that gomaxprocs is an int32
-	atomicstore((*uint32)(unsafe.Pointer(int32p)), uint32(nprocs))
-	return runnablePs
-}
-
-// Associate p and the current m.
-func acquirep(_p_ *p) {
-	acquirep1(_p_)
-
-	// have p; write barriers now allowed
-	_g_ := getg()
-	_g_.m.mcache = _p_.mcache
-
-	if trace.enabled {
-		traceProcStart()
-	}
-}
-
-// May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
-func acquirep1(_p_ *p) {
-	_g_ := getg()
-
-	if _g_.m.p != 0 || _g_.m.mcache != nil {
-		throw("acquirep: already in go")
-	}
-	if _p_.m != 0 || _p_.status != _Pidle {
-		id := int32(0)
-		if _p_.m != 0 {
-			id = _p_.m.ptr().id
-		}
-		print("acquirep: p->m=", _p_.m, "(", id, ") p->status=", _p_.status, "\n")
-		throw("acquirep: invalid p state")
-	}
-	_g_.m.p.set(_p_)
-	_p_.m.set(_g_.m)
-	_p_.status = _Prunning
-}
-
-// Disassociate p and the current m.
-func releasep() *p {
-	_g_ := getg()
-
-	if _g_.m.p == 0 || _g_.m.mcache == nil {
-		throw("releasep: invalid arg")
-	}
-	_p_ := _g_.m.p.ptr()
-	if _p_.m.ptr() != _g_.m || _p_.mcache != _g_.m.mcache || _p_.status != _Prunning {
-		print("releasep: m=", _g_.m, " m->p=", _g_.m.p.ptr(), " p->m=", _p_.m, " m->mcache=", _g_.m.mcache, " p->mcache=", _p_.mcache, " p->status=", _p_.status, "\n")
-		throw("releasep: invalid p state")
-	}
-	if trace.enabled {
-		traceProcStop(_g_.m.p.ptr())
-	}
-	_g_.m.p = 0
-	_g_.m.mcache = nil
-	_p_.m = 0
-	_p_.status = _Pidle
-	return _p_
-}
-
-func incidlelocked(v int32) {
-	lock(&sched.lock)
-	sched.nmidlelocked += v
-	if v > 0 {
-		checkdead()
-	}
-	unlock(&sched.lock)
-}
-
-// Check for deadlock situation.
-// The check is based on number of running M's, if 0 -> deadlock.
-func checkdead() {
-	// For -buildmode=c-shared or -buildmode=c-archive it's OK if
-	// there are no running goroutines.  The calling program is
-	// assumed to be running.
-	if islibrary || isarchive {
-		return
-	}
-
-	// If we are dying because of a signal caught on an already idle thread,
-	// freezetheworld will cause all running threads to block.
-	// And runtime will essentially enter into deadlock state,
-	// except that there is a thread that will call exit soon.
-	if panicking > 0 {
-		return
-	}
-
-	// -1 for sysmon
-	run := sched.mcount - sched.nmidle - sched.nmidlelocked - 1
-	if run > 0 {
-		return
-	}
-	if run < 0 {
-		print("runtime: checkdead: nmidle=", sched.nmidle, " nmidlelocked=", sched.nmidlelocked, " mcount=", sched.mcount, "\n")
-		throw("checkdead: inconsistent counts")
-	}
-
-	grunning := 0
-	lock(&allglock)
-	for i := 0; i < len(allgs); i++ {
-		gp := allgs[i]
-		if isSystemGoroutine(gp) {
-			continue
-		}
-		s := readgstatus(gp)
-		switch s &^ _Gscan {
-		case _Gwaiting:
-			grunning++
-		case _Grunnable,
-			_Grunning,
-			_Gsyscall:
-			unlock(&allglock)
-			print("runtime: checkdead: find g ", gp.goid, " in status ", s, "\n")
-			throw("checkdead: runnable g")
-		}
-	}
-	unlock(&allglock)
-	if grunning == 0 { // possible if main goroutine calls runtime·Goexit()
-		throw("no goroutines (main called runtime.Goexit) - deadlock!")
-	}
-
-	// Maybe jump time forward for playground.
-	gp := timejump()
-	if gp != nil {
-		casgstatus(gp, _Gwaiting, _Grunnable)
-		globrunqput(gp)
-		_p_ := pidleget()
-		if _p_ == nil {
-			throw("checkdead: no p for timer")
-		}
-		mp := mget()
-		if mp == nil {
-			newm(nil, _p_)
-		} else {
-			mp.nextp.set(_p_)
-			notewakeup(&mp.park)
-		}
-		return
-	}
-
-	getg().m.throwing = -1 // do not dump full stacks
-	throw("all goroutines are asleep - deadlock!")
-}
-
-func sysmon() {
-	// If we go two minutes without a garbage collection, force one to run.
-	forcegcperiod := int64(2 * 60 * 1e9)
-
-	// If a heap span goes unused for 5 minutes after a garbage collection,
-	// we hand it back to the operating system.
-	scavengelimit := int64(5 * 60 * 1e9)
-
-	if debug.scavenge > 0 {
-		// Scavenge-a-lot for testing.
-		forcegcperiod = 10 * 1e6
-		scavengelimit = 20 * 1e6
-	}
-
-	lastscavenge := nanotime()
-	nscavenge := 0
-
-	// Make wake-up period small enough for the sampling to be correct.
-	maxsleep := forcegcperiod / 2
-	if scavengelimit < forcegcperiod {
-		maxsleep = scavengelimit / 2
-	}
-
-	lasttrace := int64(0)
-	idle := 0 // how many cycles in succession we had not wokeup somebody
-	delay := uint32(0)
-	for {
-		if idle == 0 { // start with 20us sleep...
-			delay = 20
-		} else if idle > 50 { // start doubling the sleep after 1ms...
-			delay *= 2
-		}
-		if delay > 10*1000 { // up to 10ms
-			delay = 10 * 1000
-		}
-		usleep(delay)
-		if debug.schedtrace <= 0 && (sched.gcwaiting != 0 || atomicload(&sched.npidle) == uint32(gomaxprocs)) { // TODO: fast atomic
-			lock(&sched.lock)
-			if atomicload(&sched.gcwaiting) != 0 || atomicload(&sched.npidle) == uint32(gomaxprocs) {
-				atomicstore(&sched.sysmonwait, 1)
-				unlock(&sched.lock)
-				notetsleep(&sched.sysmonnote, maxsleep)
-				lock(&sched.lock)
-				atomicstore(&sched.sysmonwait, 0)
-				noteclear(&sched.sysmonnote)
-				idle = 0
-				delay = 20
-			}
-			unlock(&sched.lock)
-		}
-		// poll network if not polled for more than 10ms
-		lastpoll := int64(atomicload64(&sched.lastpoll))
-		now := nanotime()
-		unixnow := unixnanotime()
-		if lastpoll != 0 && lastpoll+10*1000*1000 < now {
-			cas64(&sched.lastpoll, uint64(lastpoll), uint64(now))
-			gp := netpoll(false) // non-blocking - returns list of goroutines
-			if gp != nil {
-				// Need to decrement number of idle locked M's
-				// (pretending that one more is running) before injectglist.
-				// Otherwise it can lead to the following situation:
-				// injectglist grabs all P's but before it starts M's to run the P's,
-				// another M returns from syscall, finishes running its G,
-				// observes that there is no work to do and no other running M's
-				// and reports deadlock.
-				incidlelocked(-1)
-				injectglist(gp)
-				incidlelocked(1)
-			}
-		}
-		// retake P's blocked in syscalls
-		// and preempt long running G's
-		if retake(now) != 0 {
-			idle = 0
-		} else {
-			idle++
-		}
-		// check if we need to force a GC
-		lastgc := int64(atomicload64(&memstats.last_gc))
-		if lastgc != 0 && unixnow-lastgc > forcegcperiod && atomicload(&forcegc.idle) != 0 && atomicloaduint(&bggc.working) == 0 {
-			lock(&forcegc.lock)
-			forcegc.idle = 0
-			forcegc.g.schedlink = 0
-			injectglist(forcegc.g)
-			unlock(&forcegc.lock)
-		}
-		// scavenge heap once in a while
-		if lastscavenge+scavengelimit/2 < now {
-			mHeap_Scavenge(int32(nscavenge), uint64(now), uint64(scavengelimit))
-			lastscavenge = now
-			nscavenge++
-		}
-		if debug.schedtrace > 0 && lasttrace+int64(debug.schedtrace*1000000) <= now {
-			lasttrace = now
-			schedtrace(debug.scheddetail > 0)
-		}
-	}
-}
-
-var pdesc [_MaxGomaxprocs]struct {
-	schedtick   uint32
-	schedwhen   int64
-	syscalltick uint32
-	syscallwhen int64
-}
-
-// forcePreemptNS is the time slice given to a G before it is
-// preempted.
-const forcePreemptNS = 10 * 1000 * 1000 // 10ms
-
-func retake(now int64) uint32 {
-	n := 0
-	for i := int32(0); i < gomaxprocs; i++ {
-		_p_ := allp[i]
-		if _p_ == nil {
-			continue
-		}
-		pd := &pdesc[i]
-		s := _p_.status
-		if s == _Psyscall {
-			// Retake P from syscall if it's there for more than 1 sysmon tick (at least 20us).
-			t := int64(_p_.syscalltick)
-			if int64(pd.syscalltick) != t {
-				pd.syscalltick = uint32(t)
-				pd.syscallwhen = now
-				continue
-			}
-			// On the one hand we don't want to retake Ps if there is no other work to do,
-			// but on the other hand we want to retake them eventually
-			// because they can prevent the sysmon thread from deep sleep.
-			if runqempty(_p_) && atomicload(&sched.nmspinning)+atomicload(&sched.npidle) > 0 && pd.syscallwhen+10*1000*1000 > now {
-				continue
-			}
-			// Need to decrement number of idle locked M's
-			// (pretending that one more is running) before the CAS.
-			// Otherwise the M from which we retake can exit the syscall,
-			// increment nmidle and report deadlock.
-			incidlelocked(-1)
-			if cas(&_p_.status, s, _Pidle) {
-				if trace.enabled {
-					traceGoSysBlock(_p_)
-					traceProcStop(_p_)
-				}
-				n++
-				_p_.syscalltick++
-				handoffp(_p_)
-			}
-			incidlelocked(1)
-		} else if s == _Prunning {
-			// Preempt G if it's running for too long.
-			t := int64(_p_.schedtick)
-			if int64(pd.schedtick) != t {
-				pd.schedtick = uint32(t)
-				pd.schedwhen = now
-				continue
-			}
-			if pd.schedwhen+forcePreemptNS > now {
-				continue
-			}
-			preemptone(_p_)
-		}
-	}
-	return uint32(n)
-}
-
-// Tell all goroutines that they have been preempted and they should stop.
-// This function is purely best-effort.  It can fail to inform a goroutine if a
-// processor just started running it.
-// No locks need to be held.
-// Returns true if preemption request was issued to at least one goroutine.
-func preemptall() bool {
-	res := false
-	for i := int32(0); i < gomaxprocs; i++ {
-		_p_ := allp[i]
-		if _p_ == nil || _p_.status != _Prunning {
-			continue
-		}
-		if preemptone(_p_) {
-			res = true
-		}
-	}
-	return res
-}
-
-// Tell the goroutine running on processor P to stop.
-// This function is purely best-effort.  It can incorrectly fail to inform the
-// goroutine.  It can send inform the wrong goroutine.  Even if it informs the
-// correct goroutine, that goroutine might ignore the request if it is
-// simultaneously executing newstack.
-// No lock needs to be held.
-// Returns true if preemption request was issued.
-// The actual preemption will happen at some point in the future
-// and will be indicated by the gp->status no longer being
-// Grunning
-func preemptone(_p_ *p) bool {
-	mp := _p_.m.ptr()
-	if mp == nil || mp == getg().m {
-		return false
-	}
-	gp := mp.curg
-	if gp == nil || gp == mp.g0 {
-		return false
-	}
-
-	gp.preempt = true
-
-	// Every call in a go routine checks for stack overflow by
-	// comparing the current stack pointer to gp->stackguard0.
-	// Setting gp->stackguard0 to StackPreempt folds
-	// preemption into the normal stack overflow check.
-	gp.stackguard0 = stackPreempt
-	return true
-}
-
-var starttime int64
-
-func schedtrace(detailed bool) {
-	now := nanotime()
-	if starttime == 0 {
-		starttime = now
-	}
-
-	lock(&sched.lock)
-	print("SCHED ", (now-starttime)/1e6, "ms: gomaxprocs=", gomaxprocs, " idleprocs=", sched.npidle, " threads=", sched.mcount, " spinningthreads=", sched.nmspinning, " idlethreads=", sched.nmidle, " runqueue=", sched.runqsize)
-	if detailed {
-		print(" gcwaiting=", sched.gcwaiting, " nmidlelocked=", sched.nmidlelocked, " stopwait=", sched.stopwait, " sysmonwait=", sched.sysmonwait, "\n")
-	}
-	// We must be careful while reading data from P's, M's and G's.
-	// Even if we hold schedlock, most data can be changed concurrently.
-	// E.g. (p->m ? p->m->id : -1) can crash if p->m changes from non-nil to nil.
-	for i := int32(0); i < gomaxprocs; i++ {
-		_p_ := allp[i]
-		if _p_ == nil {
-			continue
-		}
-		mp := _p_.m.ptr()
-		h := atomicload(&_p_.runqhead)
-		t := atomicload(&_p_.runqtail)
-		if detailed {
-			id := int32(-1)
-			if mp != nil {
-				id = mp.id
-			}
-			print("  P", i, ": status=", _p_.status, " schedtick=", _p_.schedtick, " syscalltick=", _p_.syscalltick, " m=", id, " runqsize=", t-h, " gfreecnt=", _p_.gfreecnt, "\n")
-		} else {
-			// In non-detailed mode format lengths of per-P run queues as:
-			// [len1 len2 len3 len4]
-			print(" ")
-			if i == 0 {
-				print("[")
-			}
-			print(t - h)
-			if i == gomaxprocs-1 {
-				print("]\n")
-			}
-		}
-	}
-
-	if !detailed {
-		unlock(&sched.lock)
-		return
-	}
-
-	for mp := allm; mp != nil; mp = mp.alllink {
-		_p_ := mp.p.ptr()
-		gp := mp.curg
-		lockedg := mp.lockedg
-		id1 := int32(-1)
-		if _p_ != nil {
-			id1 = _p_.id
-		}
-		id2 := int64(-1)
-		if gp != nil {
-			id2 = gp.goid
-		}
-		id3 := int64(-1)
-		if lockedg != nil {
-			id3 = lockedg.goid
-		}
-		print("  M", mp.id, ": p=", id1, " curg=", id2, " mallocing=", mp.mallocing, " throwing=", mp.throwing, " preemptoff=", mp.preemptoff, ""+" locks=", mp.locks, " dying=", mp.dying, " helpgc=", mp.helpgc, " spinning=", mp.spinning, " blocked=", getg().m.blocked, " lockedg=", id3, "\n")
-	}
-
-	lock(&allglock)
-	for gi := 0; gi < len(allgs); gi++ {
-		gp := allgs[gi]
-		mp := gp.m
-		lockedm := gp.lockedm
-		id1 := int32(-1)
-		if mp != nil {
-			id1 = mp.id
-		}
-		id2 := int32(-1)
-		if lockedm != nil {
-			id2 = lockedm.id
-		}
-		print("  G", gp.goid, ": status=", readgstatus(gp), "(", gp.waitreason, ") m=", id1, " lockedm=", id2, "\n")
-	}
-	unlock(&allglock)
-	unlock(&sched.lock)
-}
-
-// Put mp on midle list.
-// Sched must be locked.
-// May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
-func mput(mp *m) {
-	mp.schedlink = sched.midle
-	sched.midle.set(mp)
-	sched.nmidle++
-	checkdead()
-}
-
-// Try to get an m from midle list.
-// Sched must be locked.
-// May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
-func mget() *m {
-	mp := sched.midle.ptr()
-	if mp != nil {
-		sched.midle = mp.schedlink
-		sched.nmidle--
-	}
-	return mp
-}
-
-// Put gp on the global runnable queue.
-// Sched must be locked.
-// May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
-func globrunqput(gp *g) {
-	gp.schedlink = 0
-	if sched.runqtail != 0 {
-		sched.runqtail.ptr().schedlink.set(gp)
-	} else {
-		sched.runqhead.set(gp)
-	}
-	sched.runqtail.set(gp)
-	sched.runqsize++
-}
-
-// Put gp at the head of the global runnable queue.
-// Sched must be locked.
-// May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
-func globrunqputhead(gp *g) {
-	gp.schedlink = sched.runqhead
-	sched.runqhead.set(gp)
-	if sched.runqtail == 0 {
-		sched.runqtail.set(gp)
-	}
-	sched.runqsize++
-}
-
-// Put a batch of runnable goroutines on the global runnable queue.
-// Sched must be locked.
-func globrunqputbatch(ghead *g, gtail *g, n int32) {
-	gtail.schedlink = 0
-	if sched.runqtail != 0 {
-		sched.runqtail.ptr().schedlink.set(ghead)
-	} else {
-		sched.runqhead.set(ghead)
-	}
-	sched.runqtail.set(gtail)
-	sched.runqsize += n
-}
-
-// Try get a batch of G's from the global runnable queue.
-// Sched must be locked.
-func globrunqget(_p_ *p, max int32) *g {
-	if sched.runqsize == 0 {
-		return nil
-	}
-
-	n := sched.runqsize/gomaxprocs + 1
-	if n > sched.runqsize {
-		n = sched.runqsize
-	}
-	if max > 0 && n > max {
-		n = max
-	}
-	if n > int32(len(_p_.runq))/2 {
-		n = int32(len(_p_.runq)) / 2
-	}
-
-	sched.runqsize -= n
-	if sched.runqsize == 0 {
-		sched.runqtail = 0
-	}
-
-	gp := sched.runqhead.ptr()
-	sched.runqhead = gp.schedlink
-	n--
-	for ; n > 0; n-- {
-		gp1 := sched.runqhead.ptr()
-		sched.runqhead = gp1.schedlink
-		runqput(_p_, gp1, false)
-	}
-	return gp
-}
-
-// Put p to on _Pidle list.
-// Sched must be locked.
-// May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
-func pidleput(_p_ *p) {
-	if !runqempty(_p_) {
-		throw("pidleput: P has non-empty run queue")
-	}
-	_p_.link = sched.pidle
-	sched.pidle.set(_p_)
-	xadd(&sched.npidle, 1) // TODO: fast atomic
-}
-
-// Try get a p from _Pidle list.
-// Sched must be locked.
-// May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
-func pidleget() *p {
-	_p_ := sched.pidle.ptr()
-	if _p_ != nil {
-		sched.pidle = _p_.link
-		xadd(&sched.npidle, -1) // TODO: fast atomic
-	}
-	return _p_
-}
-
-// runqempty returns true if _p_ has no Gs on its local run queue.
-// Note that this test is generally racy.
-func runqempty(_p_ *p) bool {
-	return _p_.runqhead == _p_.runqtail && _p_.runnext == 0
-}
-
-// To shake out latent assumptions about scheduling order,
-// we introduce some randomness into scheduling decisions
-// when running with the race detector.
-// The need for this was made obvious by changing the
-// (deterministic) scheduling order in Go 1.5 and breaking
-// many poorly-written tests.
-// With the randomness here, as long as the tests pass
-// consistently with -race, they shouldn't have latent scheduling
-// assumptions.
-const randomizeScheduler = raceenabled
-
-// runqput tries to put g on the local runnable queue.
-// If next if false, runqput adds g to the tail of the runnable queue.
-// If next is true, runqput puts g in the _p_.runnext slot.
-// If the run queue is full, runnext puts g on the global queue.
-// Executed only by the owner P.
-func runqput(_p_ *p, gp *g, next bool) {
-	if randomizeScheduler && next && fastrand1()%2 == 0 {
-		next = false
-	}
-
-	if next {
-	retryNext:
-		oldnext := _p_.runnext
-		if !_p_.runnext.cas(oldnext, guintptr(unsafe.Pointer(gp))) {
-			goto retryNext
-		}
-		if oldnext == 0 {
-			return
-		}
-		// Kick the old runnext out to the regular run queue.
-		gp = oldnext.ptr()
-	}
-
-retry:
-	h := atomicload(&_p_.runqhead) // load-acquire, synchronize with consumers
-	t := _p_.runqtail
-	if t-h < uint32(len(_p_.runq)) {
-		_p_.runq[t%uint32(len(_p_.runq))] = gp
-		atomicstore(&_p_.runqtail, t+1) // store-release, makes the item available for consumption
-		return
-	}
-	if runqputslow(_p_, gp, h, t) {
-		return
-	}
-	// the queue is not full, now the put above must suceed
-	goto retry
-}
-
-// Put g and a batch of work from local runnable queue on global queue.
-// Executed only by the owner P.
-func runqputslow(_p_ *p, gp *g, h, t uint32) bool {
-	var batch [len(_p_.runq)/2 + 1]*g
-
-	// First, grab a batch from local queue.
-	n := t - h
-	n = n / 2
-	if n != uint32(len(_p_.runq)/2) {
-		throw("runqputslow: queue is not full")
-	}
-	for i := uint32(0); i < n; i++ {
-		batch[i] = _p_.runq[(h+i)%uint32(len(_p_.runq))]
-	}
-	if !cas(&_p_.runqhead, h, h+n) { // cas-release, commits consume
-		return false
-	}
-	batch[n] = gp
-
-	if randomizeScheduler {
-		for i := uint32(1); i <= n; i++ {
-			j := fastrand1() % (i + 1)
-			batch[i], batch[j] = batch[j], batch[i]
-		}
-	}
-
-	// Link the goroutines.
-	for i := uint32(0); i < n; i++ {
-		batch[i].schedlink.set(batch[i+1])
-	}
-
-	// Now put the batch on global queue.
-	lock(&sched.lock)
-	globrunqputbatch(batch[0], batch[n], int32(n+1))
-	unlock(&sched.lock)
-	return true
-}
-
-// Get g from local runnable queue.
-// If inheritTime is true, gp should inherit the remaining time in the
-// current time slice. Otherwise, it should start a new time slice.
-// Executed only by the owner P.
-func runqget(_p_ *p) (gp *g, inheritTime bool) {
-	// If there's a runnext, it's the next G to run.
-	for {
-		next := _p_.runnext
-		if next == 0 {
-			break
-		}
-		if _p_.runnext.cas(next, 0) {
-			return next.ptr(), true
-		}
-	}
-
-	for {
-		h := atomicload(&_p_.runqhead) // load-acquire, synchronize with other consumers
-		t := _p_.runqtail
-		if t == h {
-			return nil, false
-		}
-		gp := _p_.runq[h%uint32(len(_p_.runq))]
-		if cas(&_p_.runqhead, h, h+1) { // cas-release, commits consume
-			return gp, false
-		}
-	}
-}
-
-// Grabs a batch of goroutines from _p_'s runnable queue into batch.
-// Batch is a ring buffer starting at batchHead.
-// Returns number of grabbed goroutines.
-// Can be executed by any P.
-func runqgrab(_p_ *p, batch *[256]*g, batchHead uint32, stealRunNextG bool) uint32 {
-	for {
-		h := atomicload(&_p_.runqhead) // load-acquire, synchronize with other consumers
-		t := atomicload(&_p_.runqtail) // load-acquire, synchronize with the producer
-		n := t - h
-		n = n - n/2
-		if n == 0 {
-			if stealRunNextG {
-				// Try to steal from _p_.runnext.
-				if next := _p_.runnext; next != 0 {
-					// Sleep to ensure that _p_ isn't about to run the g we
-					// are about to steal.
-					// The important use case here is when the g running on _p_
-					// ready()s another g and then almost immediately blocks.
-					// Instead of stealing runnext in this window, back off
-					// to give _p_ a chance to schedule runnext. This will avoid
-					// thrashing gs between different Ps.
-					usleep(100)
-					if !_p_.runnext.cas(next, 0) {
-						continue
-					}
-					batch[batchHead%uint32(len(batch))] = next.ptr()
-					return 1
-				}
-			}
-			return 0
-		}
-		if n > uint32(len(_p_.runq)/2) { // read inconsistent h and t
-			continue
-		}
-		for i := uint32(0); i < n; i++ {
-			g := _p_.runq[(h+i)%uint32(len(_p_.runq))]
-			batch[(batchHead+i)%uint32(len(batch))] = g
-		}
-		if cas(&_p_.runqhead, h, h+n) { // cas-release, commits consume
-			return n
-		}
-	}
-}
-
-// Steal half of elements from local runnable queue of p2
-// and put onto local runnable queue of p.
-// Returns one of the stolen elements (or nil if failed).
-func runqsteal(_p_, p2 *p, stealRunNextG bool) *g {
-	t := _p_.runqtail
-	n := runqgrab(p2, &_p_.runq, t, stealRunNextG)
-	if n == 0 {
-		return nil
-	}
-	n--
-	gp := _p_.runq[(t+n)%uint32(len(_p_.runq))]
-	if n == 0 {
-		return gp
-	}
-	h := atomicload(&_p_.runqhead) // load-acquire, synchronize with consumers
-	if t-h+n >= uint32(len(_p_.runq)) {
-		throw("runqsteal: runq overflow")
-	}
-	atomicstore(&_p_.runqtail, t+n) // store-release, makes the item available for consumption
-	return gp
-}
-
-func testSchedLocalQueue() {
-	_p_ := new(p)
-	gs := make([]g, len(_p_.runq))
-	for i := 0; i < len(_p_.runq); i++ {
-		if g, _ := runqget(_p_); g != nil {
-			throw("runq is not empty initially")
-		}
-		for j := 0; j < i; j++ {
-			runqput(_p_, &gs[i], false)
-		}
-		for j := 0; j < i; j++ {
-			if g, _ := runqget(_p_); g != &gs[i] {
-				print("bad element at iter ", i, "/", j, "\n")
-				throw("bad element")
-			}
-		}
-		if g, _ := runqget(_p_); g != nil {
-			throw("runq is not empty afterwards")
-		}
-	}
-}
-
-func testSchedLocalQueueSteal() {
-	p1 := new(p)
-	p2 := new(p)
-	gs := make([]g, len(p1.runq))
-	for i := 0; i < len(p1.runq); i++ {
-		for j := 0; j < i; j++ {
-			gs[j].sig = 0
-			runqput(p1, &gs[j], false)
-		}
-		gp := runqsteal(p2, p1, true)
-		s := 0
-		if gp != nil {
-			s++
-			gp.sig++
-		}
-		for {
-			gp, _ = runqget(p2)
-			if gp == nil {
-				break
-			}
-			s++
-			gp.sig++
-		}
-		for {
-			gp, _ = runqget(p1)
-			if gp == nil {
-				break
-			}
-			gp.sig++
-		}
-		for j := 0; j < i; j++ {
-			if gs[j].sig != 1 {
-				print("bad element ", j, "(", gs[j].sig, ") at iter ", i, "\n")
-				throw("bad element")
-			}
-		}
-		if s != i/2 && s != i/2+1 {
-			print("bad steal ", s, ", want ", i/2, " or ", i/2+1, ", iter ", i, "\n")
-			throw("bad steal")
-		}
-	}
-}
-
-func setMaxThreads(in int) (out int) {
-	lock(&sched.lock)
-	out = int(sched.maxmcount)
-	sched.maxmcount = int32(in)
-	checkmcount()
-	unlock(&sched.lock)
-	return
-}
-
-func haveexperiment(name string) bool {
-	x := goexperiment
-	for x != "" {
-		xname := ""
-		i := index(x, ",")
-		if i < 0 {
-			xname, x = x, ""
-		} else {
-			xname, x = x[:i], x[i+1:]
-		}
-		if xname == name {
-			return true
-		}
-	}
-	return false
-}
-
-//go:nosplit
-func procPin() int {
-	_g_ := getg()
-	mp := _g_.m
-
-	mp.locks++
-	return int(mp.p.ptr().id)
-}
-
-//go:nosplit
-func procUnpin() {
-	_g_ := getg()
-	_g_.m.locks--
-}
-
-//go:linkname sync_runtime_procPin sync.runtime_procPin
-//go:nosplit
-func sync_runtime_procPin() int {
-	return procPin()
-}
-
-//go:linkname sync_runtime_procUnpin sync.runtime_procUnpin
-//go:nosplit
-func sync_runtime_procUnpin() {
-	procUnpin()
-}
-
-//go:linkname sync_atomic_runtime_procPin sync/atomic.runtime_procPin
-//go:nosplit
-func sync_atomic_runtime_procPin() int {
-	return procPin()
-}
-
-//go:linkname sync_atomic_runtime_procUnpin sync/atomic.runtime_procUnpin
-//go:nosplit
-func sync_atomic_runtime_procUnpin() {
-	procUnpin()
-}
-
-// Active spinning for sync.Mutex.
-//go:linkname sync_runtime_canSpin sync.runtime_canSpin
-//go:nosplit
-func sync_runtime_canSpin(i int) bool {
-	// sync.Mutex is cooperative, so we are conservative with spinning.
-	// Spin only few times and only if running on a multicore machine and
-	// GOMAXPROCS>1 and there is at least one other running P and local runq is empty.
-	// As opposed to runtime mutex we don't do passive spinning here,
-	// because there can be work on global runq on on other Ps.
-	if i >= active_spin || ncpu <= 1 || gomaxprocs <= int32(sched.npidle+sched.nmspinning)+1 {
-		return false
-	}
-	if p := getg().m.p.ptr(); !runqempty(p) {
-		return false
-	}
-	return true
-}
-
-//go:linkname sync_runtime_doSpin sync.runtime_doSpin
-//go:nosplit
-func sync_runtime_doSpin() {
-	procyield(active_spin_cnt)
-}
diff --git a/src/runtime/proc_test.go b/src/runtime/proc_test.go
index 2be103e..9e5960b 100644
--- a/src/runtime/proc_test.go
+++ b/src/runtime/proc_test.go
@@ -6,8 +6,10 @@ package runtime_test
 
 import (
 	"math"
+	"net"
 	"runtime"
 	"runtime/debug"
+	"strings"
 	"sync"
 	"sync/atomic"
 	"syscall"
@@ -132,6 +134,79 @@ func TestGoroutineParallelism(t *testing.T) {
 	}
 }
 
+// Test that all runnable goroutines are scheduled at the same time.
+func TestGoroutineParallelism2(t *testing.T) {
+	//testGoroutineParallelism2(t, false, false)
+	testGoroutineParallelism2(t, true, false)
+	testGoroutineParallelism2(t, false, true)
+	testGoroutineParallelism2(t, true, true)
+}
+
+func testGoroutineParallelism2(t *testing.T, load, netpoll bool) {
+	if runtime.NumCPU() == 1 {
+		// Takes too long, too easy to deadlock, etc.
+		t.Skip("skipping on uniprocessor")
+	}
+	P := 4
+	N := 10
+	if testing.Short() {
+		N = 3
+	}
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(P))
+	// If runtime triggers a forced GC during this test then it will deadlock,
+	// since the goroutines can't be stopped/preempted.
+	// Disable GC for this test (see issue #10958).
+	defer debug.SetGCPercent(debug.SetGCPercent(-1))
+	for try := 0; try < N; try++ {
+		if load {
+			// Create P goroutines and wait until they all run.
+			// When we run the actual test below, worker threads
+			// running the goroutines will start parking.
+			done := make(chan bool)
+			x := uint32(0)
+			for p := 0; p < P; p++ {
+				go func() {
+					if atomic.AddUint32(&x, 1) == uint32(P) {
+						done <- true
+						return
+					}
+					for atomic.LoadUint32(&x) != uint32(P) {
+					}
+				}()
+			}
+			<-done
+		}
+		if netpoll {
+			// Enable netpoller, affects schedler behavior.
+			ln, err := net.Listen("tcp", "localhost:0")
+			if err != nil {
+				defer ln.Close() // yup, defer in a loop
+			}
+		}
+		done := make(chan bool)
+		x := uint32(0)
+		// Spawn P goroutines in a nested fashion just to differ from TestGoroutineParallelism.
+		for p := 0; p < P/2; p++ {
+			go func(p int) {
+				for p2 := 0; p2 < 2; p2++ {
+					go func(p2 int) {
+						for i := 0; i < 3; i++ {
+							expected := uint32(P*i + p*2 + p2)
+							for atomic.LoadUint32(&x) != expected {
+							}
+							atomic.StoreUint32(&x, expected+1)
+						}
+						done <- true
+					}(p2)
+				}
+			}(p)
+		}
+		for p := 0; p < P; p++ {
+			<-done
+		}
+	}
+}
+
 func TestBlockLocked(t *testing.T) {
 	const N = 10
 	c := make(chan bool)
@@ -255,47 +330,44 @@ func TestPreemptionGC(t *testing.T) {
 }
 
 func TestGCFairness(t *testing.T) {
-	output := executeTest(t, testGCFairnessSource, nil)
+	output := runTestProg(t, "testprog", "GCFairness")
 	want := "OK\n"
 	if output != want {
 		t.Fatalf("want %s, got %s\n", want, output)
 	}
 }
 
-const testGCFairnessSource = `
-package main
+func TestNumGoroutine(t *testing.T) {
+	output := runTestProg(t, "testprog", "NumGoroutine")
+	want := "1\n"
+	if output != want {
+		t.Fatalf("want %q, got %q", want, output)
+	}
 
-import (
-	"fmt"
-	"os"
-	"runtime"
-	"time"
-)
+	buf := make([]byte, 1<<20)
 
-func main() {
-	runtime.GOMAXPROCS(1)
-	f, err := os.Open("/dev/null")
-	if os.IsNotExist(err) {
-		// This test tests what it is intended to test only if writes are fast.
-		// If there is no /dev/null, we just don't execute the test.
-		fmt.Println("OK")
-		return
-	}
-	if err != nil {
-		fmt.Println(err)
-		os.Exit(1)
-	}
-	for i := 0; i < 2; i++ {
-		go func() {
-			for {
-				f.Write([]byte("."))
-			}
-		}()
+	// Try up to 10 times for a match before giving up.
+	// This is a fundamentally racy check but it's important
+	// to notice if NumGoroutine and Stack are _always_ out of sync.
+	for i := 0; ; i++ {
+		// Give goroutines about to exit a chance to exit.
+		// The NumGoroutine and Stack below need to see
+		// the same state of the world, so anything we can do
+		// to keep it quiet is good.
+		runtime.Gosched()
+
+		n := runtime.NumGoroutine()
+		buf = buf[:runtime.Stack(buf, true)]
+
+		nstk := strings.Count(string(buf), "goroutine ")
+		if n == nstk {
+			break
+		}
+		if i >= 10 {
+			t.Fatalf("NumGoroutine=%d, but found %d goroutines in stack dump: %s", n, nstk, buf)
+		}
 	}
-	time.Sleep(10 * time.Millisecond)
-	fmt.Println("OK")
 }
-`
 
 func TestPingPongHog(t *testing.T) {
 	if testing.Short() {
diff --git a/src/runtime/race.go b/src/runtime/race.go
index 923d611..6ee1475 100644
--- a/src/runtime/race.go
+++ b/src/runtime/race.go
@@ -90,3 +90,308 @@ func racesymbolize(ctx *symbolizeContext) {
 	ctx.res = 1
 	return
 }
+
+// Race runtime functions called via runtime·racecall.
+//go:linkname __tsan_init __tsan_init
+var __tsan_init byte
+
+//go:linkname __tsan_fini __tsan_fini
+var __tsan_fini byte
+
+//go:linkname __tsan_map_shadow __tsan_map_shadow
+var __tsan_map_shadow byte
+
+//go:linkname __tsan_finalizer_goroutine __tsan_finalizer_goroutine
+var __tsan_finalizer_goroutine byte
+
+//go:linkname __tsan_go_start __tsan_go_start
+var __tsan_go_start byte
+
+//go:linkname __tsan_go_end __tsan_go_end
+var __tsan_go_end byte
+
+//go:linkname __tsan_malloc __tsan_malloc
+var __tsan_malloc byte
+
+//go:linkname __tsan_acquire __tsan_acquire
+var __tsan_acquire byte
+
+//go:linkname __tsan_release __tsan_release
+var __tsan_release byte
+
+//go:linkname __tsan_release_merge __tsan_release_merge
+var __tsan_release_merge byte
+
+//go:linkname __tsan_go_ignore_sync_begin __tsan_go_ignore_sync_begin
+var __tsan_go_ignore_sync_begin byte
+
+//go:linkname __tsan_go_ignore_sync_end __tsan_go_ignore_sync_end
+var __tsan_go_ignore_sync_end byte
+
+// Mimic what cmd/cgo would do.
+//go:cgo_import_static __tsan_init
+//go:cgo_import_static __tsan_fini
+//go:cgo_import_static __tsan_map_shadow
+//go:cgo_import_static __tsan_finalizer_goroutine
+//go:cgo_import_static __tsan_go_start
+//go:cgo_import_static __tsan_go_end
+//go:cgo_import_static __tsan_malloc
+//go:cgo_import_static __tsan_acquire
+//go:cgo_import_static __tsan_release
+//go:cgo_import_static __tsan_release_merge
+//go:cgo_import_static __tsan_go_ignore_sync_begin
+//go:cgo_import_static __tsan_go_ignore_sync_end
+
+// These are called from race_amd64.s.
+//go:cgo_import_static __tsan_read
+//go:cgo_import_static __tsan_read_pc
+//go:cgo_import_static __tsan_read_range
+//go:cgo_import_static __tsan_write
+//go:cgo_import_static __tsan_write_pc
+//go:cgo_import_static __tsan_write_range
+//go:cgo_import_static __tsan_func_enter
+//go:cgo_import_static __tsan_func_exit
+
+//go:cgo_import_static __tsan_go_atomic32_load
+//go:cgo_import_static __tsan_go_atomic64_load
+//go:cgo_import_static __tsan_go_atomic32_store
+//go:cgo_import_static __tsan_go_atomic64_store
+//go:cgo_import_static __tsan_go_atomic32_exchange
+//go:cgo_import_static __tsan_go_atomic64_exchange
+//go:cgo_import_static __tsan_go_atomic32_fetch_add
+//go:cgo_import_static __tsan_go_atomic64_fetch_add
+//go:cgo_import_static __tsan_go_atomic32_compare_exchange
+//go:cgo_import_static __tsan_go_atomic64_compare_exchange
+
+// start/end of global data (data+bss).
+var racedatastart uintptr
+var racedataend uintptr
+
+// start/end of heap for race_amd64.s
+var racearenastart uintptr
+var racearenaend uintptr
+
+func racefuncenter(uintptr)
+func racefuncexit()
+func racereadrangepc1(uintptr, uintptr, uintptr)
+func racewriterangepc1(uintptr, uintptr, uintptr)
+func racesymbolizethunk(uintptr)
+
+// racecall allows calling an arbitrary function f from C race runtime
+// with up to 4 uintptr arguments.
+func racecall(*byte, uintptr, uintptr, uintptr, uintptr)
+
+// checks if the address has shadow (i.e. heap or data/bss)
+//go:nosplit
+func isvalidaddr(addr unsafe.Pointer) bool {
+	return racearenastart <= uintptr(addr) && uintptr(addr) < racearenaend ||
+		racedatastart <= uintptr(addr) && uintptr(addr) < racedataend
+}
+
+//go:nosplit
+func raceinit() uintptr {
+	// cgo is required to initialize libc, which is used by race runtime
+	if !iscgo {
+		throw("raceinit: race build must use cgo")
+	}
+
+	var racectx uintptr
+	racecall(&__tsan_init, uintptr(unsafe.Pointer(&racectx)), funcPC(racesymbolizethunk), 0, 0)
+
+	// Round data segment to page boundaries, because it's used in mmap().
+	start := ^uintptr(0)
+	end := uintptr(0)
+	if start > firstmoduledata.noptrdata {
+		start = firstmoduledata.noptrdata
+	}
+	if start > firstmoduledata.data {
+		start = firstmoduledata.data
+	}
+	if start > firstmoduledata.noptrbss {
+		start = firstmoduledata.noptrbss
+	}
+	if start > firstmoduledata.bss {
+		start = firstmoduledata.bss
+	}
+	if end < firstmoduledata.enoptrdata {
+		end = firstmoduledata.enoptrdata
+	}
+	if end < firstmoduledata.edata {
+		end = firstmoduledata.edata
+	}
+	if end < firstmoduledata.enoptrbss {
+		end = firstmoduledata.enoptrbss
+	}
+	if end < firstmoduledata.ebss {
+		end = firstmoduledata.ebss
+	}
+	size := round(end-start, _PageSize)
+	racecall(&__tsan_map_shadow, start, size, 0, 0)
+	racedatastart = start
+	racedataend = start + size
+
+	return racectx
+}
+
+//go:nosplit
+func racefini() {
+	racecall(&__tsan_fini, 0, 0, 0, 0)
+}
+
+//go:nosplit
+func racemapshadow(addr unsafe.Pointer, size uintptr) {
+	if racearenastart == 0 {
+		racearenastart = uintptr(addr)
+	}
+	if racearenaend < uintptr(addr)+size {
+		racearenaend = uintptr(addr) + size
+	}
+	racecall(&__tsan_map_shadow, uintptr(addr), size, 0, 0)
+}
+
+//go:nosplit
+func racemalloc(p unsafe.Pointer, sz uintptr) {
+	racecall(&__tsan_malloc, uintptr(p), sz, 0, 0)
+}
+
+//go:nosplit
+func racegostart(pc uintptr) uintptr {
+	_g_ := getg()
+	var spawng *g
+	if _g_.m.curg != nil {
+		spawng = _g_.m.curg
+	} else {
+		spawng = _g_
+	}
+
+	var racectx uintptr
+	racecall(&__tsan_go_start, spawng.racectx, uintptr(unsafe.Pointer(&racectx)), pc, 0)
+	return racectx
+}
+
+//go:nosplit
+func racegoend() {
+	racecall(&__tsan_go_end, getg().racectx, 0, 0, 0)
+}
+
+//go:nosplit
+func racewriterangepc(addr unsafe.Pointer, sz, callpc, pc uintptr) {
+	_g_ := getg()
+	if _g_ != _g_.m.curg {
+		// The call is coming from manual instrumentation of Go code running on g0/gsignal.
+		// Not interesting.
+		return
+	}
+	if callpc != 0 {
+		racefuncenter(callpc)
+	}
+	racewriterangepc1(uintptr(addr), sz, pc)
+	if callpc != 0 {
+		racefuncexit()
+	}
+}
+
+//go:nosplit
+func racereadrangepc(addr unsafe.Pointer, sz, callpc, pc uintptr) {
+	_g_ := getg()
+	if _g_ != _g_.m.curg {
+		// The call is coming from manual instrumentation of Go code running on g0/gsignal.
+		// Not interesting.
+		return
+	}
+	if callpc != 0 {
+		racefuncenter(callpc)
+	}
+	racereadrangepc1(uintptr(addr), sz, pc)
+	if callpc != 0 {
+		racefuncexit()
+	}
+}
+
+//go:nosplit
+func raceacquire(addr unsafe.Pointer) {
+	raceacquireg(getg(), addr)
+}
+
+//go:nosplit
+func raceacquireg(gp *g, addr unsafe.Pointer) {
+	if getg().raceignore != 0 || !isvalidaddr(addr) {
+		return
+	}
+	racecall(&__tsan_acquire, gp.racectx, uintptr(addr), 0, 0)
+}
+
+//go:nosplit
+func racerelease(addr unsafe.Pointer) {
+	_g_ := getg()
+	if _g_.raceignore != 0 || !isvalidaddr(addr) {
+		return
+	}
+	racereleaseg(_g_, addr)
+}
+
+//go:nosplit
+func racereleaseg(gp *g, addr unsafe.Pointer) {
+	if getg().raceignore != 0 || !isvalidaddr(addr) {
+		return
+	}
+	racecall(&__tsan_release, gp.racectx, uintptr(addr), 0, 0)
+}
+
+//go:nosplit
+func racereleasemerge(addr unsafe.Pointer) {
+	racereleasemergeg(getg(), addr)
+}
+
+//go:nosplit
+func racereleasemergeg(gp *g, addr unsafe.Pointer) {
+	if getg().raceignore != 0 || !isvalidaddr(addr) {
+		return
+	}
+	racecall(&__tsan_release_merge, gp.racectx, uintptr(addr), 0, 0)
+}
+
+//go:nosplit
+func racefingo() {
+	racecall(&__tsan_finalizer_goroutine, getg().racectx, 0, 0, 0)
+}
+
+//go:nosplit
+
+func RaceAcquire(addr unsafe.Pointer) {
+	raceacquire(addr)
+}
+
+//go:nosplit
+
+func RaceRelease(addr unsafe.Pointer) {
+	racerelease(addr)
+}
+
+//go:nosplit
+
+func RaceReleaseMerge(addr unsafe.Pointer) {
+	racereleasemerge(addr)
+}
+
+//go:nosplit
+
+// RaceDisable disables handling of race events in the current goroutine.
+func RaceDisable() {
+	_g_ := getg()
+	if _g_.raceignore == 0 {
+		racecall(&__tsan_go_ignore_sync_begin, _g_.racectx, 0, 0, 0)
+	}
+	_g_.raceignore++
+}
+
+//go:nosplit
+
+// RaceEnable re-enables handling of race events in the current goroutine.
+func RaceEnable() {
+	_g_ := getg()
+	_g_.raceignore--
+	if _g_.raceignore == 0 {
+		racecall(&__tsan_go_ignore_sync_end, _g_.racectx, 0, 0, 0)
+	}
+}
diff --git a/src/runtime/race/README b/src/runtime/race/README
index 52dd38e..1831699 100644
--- a/src/runtime/race/README
+++ b/src/runtime/race/README
@@ -1,12 +1,7 @@
 runtime/race package contains the data race detector runtime library.
 It is based on ThreadSanitizer race detector, that is currently a part of
-the LLVM project.
+the LLVM project (http://llvm.org/git/compiler-rt.git).
 
-To update the .syso files you need to:
-$ svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk
-$ cd compiler-rt/lib/tsan/go
-$ ./buildgo.sh
+To update the .syso files use golang.org/x/build/cmd/racebuild.
 
-Tested with gcc 4.6.1 and 4.7.0.  On Windows it's built with 64-bit MinGW.
-
-Current runtime is built on rev 229396.
+Current runtime is built on rev 389d49d4943780efbfcd2a434f4462b6d0f23c44.
diff --git a/src/runtime/race/output_test.go b/src/runtime/race/output_test.go
index a9f9f0f..0c71a01 100644
--- a/src/runtime/race/output_test.go
+++ b/src/runtime/race/output_test.go
@@ -51,7 +51,10 @@ func TestOutput(t *testing.T) {
 			}
 			cmd.Env = append(cmd.Env, env)
 		}
-		cmd.Env = append(cmd.Env, "GORACE="+test.gorace)
+		cmd.Env = append(cmd.Env,
+			"GOMAXPROCS=1", // see comment in race_test.go
+			"GORACE="+test.gorace,
+		)
 		got, _ := cmd.CombinedOutput()
 		if !regexp.MustCompile(test.re).MatchString(string(got)) {
 			t.Fatalf("failed test case %v, expect:\n%v\ngot:\n%s",
diff --git a/src/runtime/race/race.go b/src/runtime/race/race.go
index 31deedd..15e2011 100644
--- a/src/runtime/race/race.go
+++ b/src/runtime/race/race.go
@@ -9,7 +9,7 @@ package race
 // This file merely ensures that we link in runtime/cgo in race build,
 // this is turn ensures that runtime uses pthread_create to create threads.
 // The prebuilt race runtime lives in race_GOOS_GOARCH.syso.
-// Calls to the runtime are done directly from src/runtime/race.c.
+// Calls to the runtime are done directly from src/runtime/race.go.
 
 // void __race_unused_func(void);
 import "C"
diff --git a/src/runtime/race/race_darwin_amd64.syso b/src/runtime/race/race_darwin_amd64.syso
index 9cf1ecc..745d970 100644
Binary files a/src/runtime/race/race_darwin_amd64.syso and b/src/runtime/race/race_darwin_amd64.syso differ
diff --git a/src/runtime/race/race_freebsd_amd64.syso b/src/runtime/race/race_freebsd_amd64.syso
index 50ae2d3..074b676 100644
Binary files a/src/runtime/race/race_freebsd_amd64.syso and b/src/runtime/race/race_freebsd_amd64.syso differ
diff --git a/src/runtime/race/race_linux_amd64.syso b/src/runtime/race/race_linux_amd64.syso
index a141051..042ca59 100644
Binary files a/src/runtime/race/race_linux_amd64.syso and b/src/runtime/race/race_linux_amd64.syso differ
diff --git a/src/runtime/race/race_test.go b/src/runtime/race/race_test.go
index 6898e74..748f338 100644
--- a/src/runtime/race/race_test.go
+++ b/src/runtime/race/race_test.go
@@ -155,7 +155,20 @@ func runTests() ([]byte, error) {
 		}
 		cmd.Env = append(cmd.Env, env)
 	}
-	cmd.Env = append(cmd.Env, `GORACE=suppress_equal_stacks=0 suppress_equal_addresses=0 exitcode=0`)
+	// We set GOMAXPROCS=1 to prevent test flakiness.
+	// There are two sources of flakiness:
+	// 1. Some tests rely on particular execution order.
+	//    If the order is different, race does not happen at all.
+	// 2. Ironically, ThreadSanitizer runtime contains a logical race condition
+	//    that can lead to false negatives if racy accesses happen literally at the same time.
+	// Tests used to work reliably in the good old days of GOMAXPROCS=1.
+	// So let's set it for now. A more reliable solution is to explicitly annotate tests
+	// with required execution order by means of a special "invisible" synchronization primitive
+	// (that's what is done for C++ ThreadSanitizer tests). This is issue #14119.
+	cmd.Env = append(cmd.Env,
+		"GOMAXPROCS=1",
+		"GORACE=suppress_equal_stacks=0 suppress_equal_addresses=0 exitcode=0",
+	)
 	return cmd.CombinedOutput()
 }
 
diff --git a/src/runtime/race/race_windows_amd64.syso b/src/runtime/race/race_windows_amd64.syso
index 125115e..cb4446b 100644
Binary files a/src/runtime/race/race_windows_amd64.syso and b/src/runtime/race/race_windows_amd64.syso differ
diff --git a/src/runtime/race/testdata/chan_test.go b/src/runtime/race/testdata/chan_test.go
index eabd81f..cddd9a6 100644
--- a/src/runtime/race/testdata/chan_test.go
+++ b/src/runtime/race/testdata/chan_test.go
@@ -657,3 +657,42 @@ func TestNoRaceChanWaitGroup(t *testing.T) {
 		_ = data[i]
 	}
 }
+
+// Test that sender synchronizes with receiver even if the sender was blocked.
+func TestNoRaceBlockedSendSync(t *testing.T) {
+	c := make(chan *int, 1)
+	c <- nil
+	go func() {
+		i := 42
+		c <- &i
+	}()
+	// Give the sender time to actually block.
+	// This sleep is completely optional: race report must not be printed
+	// regardless of whether the sender actually blocks or not.
+	// It cannot lead to flakiness.
+	time.Sleep(10 * time.Millisecond)
+	<-c
+	p := <-c
+	if *p != 42 {
+		t.Fatal()
+	}
+}
+
+// The same as TestNoRaceBlockedSendSync above, but sender unblock happens in a select.
+func TestNoRaceBlockedSelectSendSync(t *testing.T) {
+	c := make(chan *int, 1)
+	c <- nil
+	go func() {
+		i := 42
+		c <- &i
+	}()
+	time.Sleep(10 * time.Millisecond)
+	<-c
+	select {
+	case p := <-c:
+		if *p != 42 {
+			t.Fatal()
+		}
+	case <-make(chan int):
+	}
+}
diff --git a/src/runtime/race/testdata/issue12225_test.go b/src/runtime/race/testdata/issue12225_test.go
index 3b0b8ec..0494493 100644
--- a/src/runtime/race/testdata/issue12225_test.go
+++ b/src/runtime/race/testdata/issue12225_test.go
@@ -4,9 +4,16 @@
 
 package race_test
 
+import "unsafe"
+
 // golang.org/issue/12225
 // The test is that this compiles at all.
 
+//go:noinline
+func convert(s string) []byte {
+	return []byte(s)
+}
+
 func issue12225() {
 	println(*(*int)(unsafe.Pointer(&convert("")[0])))
 	println(*(*int)(unsafe.Pointer(&[]byte("")[0])))
diff --git a/src/runtime/race/testdata/issue12664_test.go b/src/runtime/race/testdata/issue12664_test.go
new file mode 100644
index 0000000..c9f790e
--- /dev/null
+++ b/src/runtime/race/testdata/issue12664_test.go
@@ -0,0 +1,76 @@
+// Copyright 2015 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 race_test
+
+import (
+	"fmt"
+	"testing"
+)
+
+var issue12664 = "hi"
+
+func TestRaceIssue12664(t *testing.T) {
+	c := make(chan struct{})
+	go func() {
+		issue12664 = "bye"
+		close(c)
+	}()
+	fmt.Println(issue12664)
+	<-c
+}
+
+type MyI interface {
+	foo()
+}
+
+type MyT int
+
+func (MyT) foo() {
+}
+
+var issue12664_2 MyT = 0
+
+func TestRaceIssue12664_2(t *testing.T) {
+	c := make(chan struct{})
+	go func() {
+		issue12664_2 = 1
+		close(c)
+	}()
+	func(x MyI) {
+		// Never true, but prevents inlining.
+		if x.(MyT) == -1 {
+			close(c)
+		}
+	}(issue12664_2)
+	<-c
+}
+
+var issue12664_3 MyT = 0
+
+func TestRaceIssue12664_3(t *testing.T) {
+	c := make(chan struct{})
+	go func() {
+		issue12664_3 = 1
+		close(c)
+	}()
+	var r MyT
+	var i interface{} = r
+	issue12664_3 = i.(MyT)
+	<-c
+}
+
+var issue12664_4 MyT = 0
+
+func TestRaceIssue12664_4(t *testing.T) {
+	c := make(chan struct{})
+	go func() {
+		issue12664_4 = 1
+		close(c)
+	}()
+	var r MyT
+	var i MyI = r
+	issue12664_4 = i.(MyT)
+	<-c
+}
diff --git a/src/runtime/race/testdata/issue13264_test.go b/src/runtime/race/testdata/issue13264_test.go
new file mode 100644
index 0000000..d42290d
--- /dev/null
+++ b/src/runtime/race/testdata/issue13264_test.go
@@ -0,0 +1,13 @@
+// Copyright 2015 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 race_test
+
+// golang.org/issue/13264
+// The test is that this compiles at all.
+
+func issue13264() {
+	for ; ; []map[int]int{}[0][0] = 0 {
+	}
+}
diff --git a/src/runtime/race/testdata/mop_test.go b/src/runtime/race/testdata/mop_test.go
index d7cbc98..c96acb9 100644
--- a/src/runtime/race/testdata/mop_test.go
+++ b/src/runtime/race/testdata/mop_test.go
@@ -1356,14 +1356,8 @@ type InterImpl struct {
 	x, y int
 }
 
+//go:noinline
 func (p InterImpl) Foo(x int) {
-	// prevent inlining
-	z := 42
-	x = 85
-	y := x / z
-	z = y * z
-	x = z * y
-	_, _, _ = x, y, z
 }
 
 type InterImpl2 InterImpl
diff --git a/src/runtime/race/testdata/regression_test.go b/src/runtime/race/testdata/regression_test.go
index d461269..6a7802f 100644
--- a/src/runtime/race/testdata/regression_test.go
+++ b/src/runtime/race/testdata/regression_test.go
@@ -65,10 +65,8 @@ type Image struct {
 	min, max Rect
 }
 
+//go:noinline
 func NewImage() Image {
-	var pleaseDoNotInlineMe stack
-	pleaseDoNotInlineMe.push(1)
-	_ = pleaseDoNotInlineMe.pop()
 	return Image{}
 }
 
@@ -113,11 +111,8 @@ type RpcChan struct {
 
 var makeChanCalls int
 
+//go:noinline
 func makeChan() *RpcChan {
-	var pleaseDoNotInlineMe stack
-	pleaseDoNotInlineMe.push(1)
-	_ = pleaseDoNotInlineMe.pop()
-
 	makeChanCalls++
 	c := &RpcChan{make(chan bool, 1)}
 	c.c <- true
diff --git a/src/runtime/race/testdata/select_test.go b/src/runtime/race/testdata/select_test.go
index b4b1991..9969f47 100644
--- a/src/runtime/race/testdata/select_test.go
+++ b/src/runtime/race/testdata/select_test.go
@@ -19,7 +19,7 @@ func TestNoRaceSelect1(t *testing.T) {
 		x = 1
 		// At least two channels are needed because
 		// otherwise the compiler optimizes select out.
-		// See comment in runtime/chan.c:^selectgo.
+		// See comment in runtime/select.go:^func selectgoImpl.
 		select {
 		case c <- true:
 		case c1 <- true:
diff --git a/src/runtime/race1.go b/src/runtime/race1.go
deleted file mode 100644
index 38afca7..0000000
--- a/src/runtime/race1.go
+++ /dev/null
@@ -1,315 +0,0 @@
-// Copyright 2011 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.
-
-// Implementation of the race detector API.
-// +build race
-
-package runtime
-
-import "unsafe"
-
-// Race runtime functions called via runtime·racecall.
-//go:linkname __tsan_init __tsan_init
-var __tsan_init byte
-
-//go:linkname __tsan_fini __tsan_fini
-var __tsan_fini byte
-
-//go:linkname __tsan_map_shadow __tsan_map_shadow
-var __tsan_map_shadow byte
-
-//go:linkname __tsan_finalizer_goroutine __tsan_finalizer_goroutine
-var __tsan_finalizer_goroutine byte
-
-//go:linkname __tsan_go_start __tsan_go_start
-var __tsan_go_start byte
-
-//go:linkname __tsan_go_end __tsan_go_end
-var __tsan_go_end byte
-
-//go:linkname __tsan_malloc __tsan_malloc
-var __tsan_malloc byte
-
-//go:linkname __tsan_acquire __tsan_acquire
-var __tsan_acquire byte
-
-//go:linkname __tsan_release __tsan_release
-var __tsan_release byte
-
-//go:linkname __tsan_release_merge __tsan_release_merge
-var __tsan_release_merge byte
-
-//go:linkname __tsan_go_ignore_sync_begin __tsan_go_ignore_sync_begin
-var __tsan_go_ignore_sync_begin byte
-
-//go:linkname __tsan_go_ignore_sync_end __tsan_go_ignore_sync_end
-var __tsan_go_ignore_sync_end byte
-
-// Mimic what cmd/cgo would do.
-//go:cgo_import_static __tsan_init
-//go:cgo_import_static __tsan_fini
-//go:cgo_import_static __tsan_map_shadow
-//go:cgo_import_static __tsan_finalizer_goroutine
-//go:cgo_import_static __tsan_go_start
-//go:cgo_import_static __tsan_go_end
-//go:cgo_import_static __tsan_malloc
-//go:cgo_import_static __tsan_acquire
-//go:cgo_import_static __tsan_release
-//go:cgo_import_static __tsan_release_merge
-//go:cgo_import_static __tsan_go_ignore_sync_begin
-//go:cgo_import_static __tsan_go_ignore_sync_end
-
-// These are called from race_amd64.s.
-//go:cgo_import_static __tsan_read
-//go:cgo_import_static __tsan_read_pc
-//go:cgo_import_static __tsan_read_range
-//go:cgo_import_static __tsan_write
-//go:cgo_import_static __tsan_write_pc
-//go:cgo_import_static __tsan_write_range
-//go:cgo_import_static __tsan_func_enter
-//go:cgo_import_static __tsan_func_exit
-
-//go:cgo_import_static __tsan_go_atomic32_load
-//go:cgo_import_static __tsan_go_atomic64_load
-//go:cgo_import_static __tsan_go_atomic32_store
-//go:cgo_import_static __tsan_go_atomic64_store
-//go:cgo_import_static __tsan_go_atomic32_exchange
-//go:cgo_import_static __tsan_go_atomic64_exchange
-//go:cgo_import_static __tsan_go_atomic32_fetch_add
-//go:cgo_import_static __tsan_go_atomic64_fetch_add
-//go:cgo_import_static __tsan_go_atomic32_compare_exchange
-//go:cgo_import_static __tsan_go_atomic64_compare_exchange
-
-// start/end of global data (data+bss).
-var racedatastart uintptr
-var racedataend uintptr
-
-// start/end of heap for race_amd64.s
-var racearenastart uintptr
-var racearenaend uintptr
-
-func racefuncenter(uintptr)
-func racefuncexit()
-func racereadrangepc1(uintptr, uintptr, uintptr)
-func racewriterangepc1(uintptr, uintptr, uintptr)
-func racesymbolizethunk(uintptr)
-
-// racecall allows calling an arbitrary function f from C race runtime
-// with up to 4 uintptr arguments.
-func racecall(*byte, uintptr, uintptr, uintptr, uintptr)
-
-// checks if the address has shadow (i.e. heap or data/bss)
-//go:nosplit
-func isvalidaddr(addr unsafe.Pointer) bool {
-	return racearenastart <= uintptr(addr) && uintptr(addr) < racearenaend ||
-		racedatastart <= uintptr(addr) && uintptr(addr) < racedataend
-}
-
-//go:nosplit
-func raceinit() uintptr {
-	// cgo is required to initialize libc, which is used by race runtime
-	if !iscgo {
-		throw("raceinit: race build must use cgo")
-	}
-
-	var racectx uintptr
-	racecall(&__tsan_init, uintptr(unsafe.Pointer(&racectx)), funcPC(racesymbolizethunk), 0, 0)
-
-	// Round data segment to page boundaries, because it's used in mmap().
-	start := ^uintptr(0)
-	end := uintptr(0)
-	if start > firstmoduledata.noptrdata {
-		start = firstmoduledata.noptrdata
-	}
-	if start > firstmoduledata.data {
-		start = firstmoduledata.data
-	}
-	if start > firstmoduledata.noptrbss {
-		start = firstmoduledata.noptrbss
-	}
-	if start > firstmoduledata.bss {
-		start = firstmoduledata.bss
-	}
-	if end < firstmoduledata.enoptrdata {
-		end = firstmoduledata.enoptrdata
-	}
-	if end < firstmoduledata.edata {
-		end = firstmoduledata.edata
-	}
-	if end < firstmoduledata.enoptrbss {
-		end = firstmoduledata.enoptrbss
-	}
-	if end < firstmoduledata.ebss {
-		end = firstmoduledata.ebss
-	}
-	size := round(end-start, _PageSize)
-	racecall(&__tsan_map_shadow, start, size, 0, 0)
-	racedatastart = start
-	racedataend = start + size
-
-	return racectx
-}
-
-//go:nosplit
-func racefini() {
-	racecall(&__tsan_fini, 0, 0, 0, 0)
-}
-
-//go:nosplit
-func racemapshadow(addr unsafe.Pointer, size uintptr) {
-	if racearenastart == 0 {
-		racearenastart = uintptr(addr)
-	}
-	if racearenaend < uintptr(addr)+size {
-		racearenaend = uintptr(addr) + size
-	}
-	racecall(&__tsan_map_shadow, uintptr(addr), size, 0, 0)
-}
-
-//go:nosplit
-func racemalloc(p unsafe.Pointer, sz uintptr) {
-	racecall(&__tsan_malloc, uintptr(p), sz, 0, 0)
-}
-
-//go:nosplit
-func racegostart(pc uintptr) uintptr {
-	_g_ := getg()
-	var spawng *g
-	if _g_.m.curg != nil {
-		spawng = _g_.m.curg
-	} else {
-		spawng = _g_
-	}
-
-	var racectx uintptr
-	racecall(&__tsan_go_start, spawng.racectx, uintptr(unsafe.Pointer(&racectx)), pc, 0)
-	return racectx
-}
-
-//go:nosplit
-func racegoend() {
-	racecall(&__tsan_go_end, getg().racectx, 0, 0, 0)
-}
-
-//go:nosplit
-func racewriterangepc(addr unsafe.Pointer, sz, callpc, pc uintptr) {
-	_g_ := getg()
-	if _g_ != _g_.m.curg {
-		// The call is coming from manual instrumentation of Go code running on g0/gsignal.
-		// Not interesting.
-		return
-	}
-	if callpc != 0 {
-		racefuncenter(callpc)
-	}
-	racewriterangepc1(uintptr(addr), sz, pc)
-	if callpc != 0 {
-		racefuncexit()
-	}
-}
-
-//go:nosplit
-func racereadrangepc(addr unsafe.Pointer, sz, callpc, pc uintptr) {
-	_g_ := getg()
-	if _g_ != _g_.m.curg {
-		// The call is coming from manual instrumentation of Go code running on g0/gsignal.
-		// Not interesting.
-		return
-	}
-	if callpc != 0 {
-		racefuncenter(callpc)
-	}
-	racereadrangepc1(uintptr(addr), sz, pc)
-	if callpc != 0 {
-		racefuncexit()
-	}
-}
-
-//go:nosplit
-func raceacquire(addr unsafe.Pointer) {
-	raceacquireg(getg(), addr)
-}
-
-//go:nosplit
-func raceacquireg(gp *g, addr unsafe.Pointer) {
-	if getg().raceignore != 0 || !isvalidaddr(addr) {
-		return
-	}
-	racecall(&__tsan_acquire, gp.racectx, uintptr(addr), 0, 0)
-}
-
-//go:nosplit
-func racerelease(addr unsafe.Pointer) {
-	_g_ := getg()
-	if _g_.raceignore != 0 || !isvalidaddr(addr) {
-		return
-	}
-	racereleaseg(_g_, addr)
-}
-
-//go:nosplit
-func racereleaseg(gp *g, addr unsafe.Pointer) {
-	if getg().raceignore != 0 || !isvalidaddr(addr) {
-		return
-	}
-	racecall(&__tsan_release, gp.racectx, uintptr(addr), 0, 0)
-}
-
-//go:nosplit
-func racereleasemerge(addr unsafe.Pointer) {
-	racereleasemergeg(getg(), addr)
-}
-
-//go:nosplit
-func racereleasemergeg(gp *g, addr unsafe.Pointer) {
-	if getg().raceignore != 0 || !isvalidaddr(addr) {
-		return
-	}
-	racecall(&__tsan_release_merge, gp.racectx, uintptr(addr), 0, 0)
-}
-
-//go:nosplit
-func racefingo() {
-	racecall(&__tsan_finalizer_goroutine, getg().racectx, 0, 0, 0)
-}
-
-//go:nosplit
-
-func RaceAcquire(addr unsafe.Pointer) {
-	raceacquire(addr)
-}
-
-//go:nosplit
-
-func RaceRelease(addr unsafe.Pointer) {
-	racerelease(addr)
-}
-
-//go:nosplit
-
-func RaceReleaseMerge(addr unsafe.Pointer) {
-	racereleasemerge(addr)
-}
-
-//go:nosplit
-
-// RaceDisable disables handling of race events in the current goroutine.
-func RaceDisable() {
-	_g_ := getg()
-	if _g_.raceignore == 0 {
-		racecall(&__tsan_go_ignore_sync_begin, _g_.racectx, 0, 0, 0)
-	}
-	_g_.raceignore++
-}
-
-//go:nosplit
-
-// RaceEnable re-enables handling of race events in the current goroutine.
-func RaceEnable() {
-	_g_ := getg()
-	_g_.raceignore--
-	if _g_.raceignore == 0 {
-		racecall(&__tsan_go_ignore_sync_end, _g_.racectx, 0, 0, 0)
-	}
-}
diff --git a/src/runtime/rdebug.go b/src/runtime/rdebug.go
index f2766d7..ad7b976 100644
--- a/src/runtime/rdebug.go
+++ b/src/runtime/rdebug.go
@@ -4,12 +4,16 @@
 
 package runtime
 
+import _ "unsafe" // for go:linkname
+
+//go:linkname setMaxStack runtime/debug.setMaxStack
 func setMaxStack(in int) (out int) {
 	out = int(maxstacksize)
 	maxstacksize = uintptr(in)
 	return out
 }
 
+//go:linkname setPanicOnFault runtime/debug.setPanicOnFault
 func setPanicOnFault(new bool) (old bool) {
 	mp := acquirem()
 	old = mp.curg.paniconfault
diff --git a/src/runtime/rt0_android_386.s b/src/runtime/rt0_android_386.s
new file mode 100644
index 0000000..9d20fc8
--- /dev/null
+++ b/src/runtime/rt0_android_386.s
@@ -0,0 +1,32 @@
+// Copyright 2015 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"
+
+TEXT _rt0_386_android(SB),NOSPLIT,$8
+	MOVL	8(SP), AX  // argc
+	LEAL	12(SP), BX  // argv
+	MOVL	AX, 0(SP)
+	MOVL	BX, 4(SP)
+	CALL	main(SB)
+	INT	$3
+
+TEXT _rt0_386_android_lib(SB),NOSPLIT,$0
+	PUSHL	$_rt0_386_android_argv(SB)  // argv
+	PUSHL	$1  // argc
+	CALL	_rt0_386_linux_lib(SB)
+	POPL	AX
+	POPL	AX
+	RET
+
+DATA _rt0_386_android_argv+0x00(SB)/4,$_rt0_386_android_argv0(SB)
+DATA _rt0_386_android_argv+0x04(SB)/4,$0  // argv terminate
+DATA _rt0_386_android_argv+0x08(SB)/4,$0  // envp terminate
+DATA _rt0_386_android_argv+0x0c(SB)/4,$0  // auxv terminate
+GLOBL _rt0_386_android_argv(SB),NOPTR,$0x10
+
+// TODO: wire up necessary VDSO (see os_linux_386.go)
+
+DATA _rt0_386_android_argv0(SB)/8, $"gojni"
+GLOBL _rt0_386_android_argv0(SB),RODATA,$8
diff --git a/src/runtime/rt0_android_amd64.s b/src/runtime/rt0_android_amd64.s
new file mode 100644
index 0000000..9af6cab
--- /dev/null
+++ b/src/runtime/rt0_android_amd64.s
@@ -0,0 +1,33 @@
+// Copyright 2015 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"
+
+TEXT _rt0_amd64_android(SB),NOSPLIT,$-8
+	MOVQ	0(SP), DI // argc
+	LEAQ	8(SP), SI // argv
+	MOVQ	$main(SB), AX
+	JMP	AX
+
+TEXT _rt0_amd64_android_lib(SB),NOSPLIT,$0
+	MOVQ	$1, DI // argc
+	MOVQ	$_rt0_amd64_android_argv(SB), SI  // argv
+	MOVQ	$_rt0_amd64_linux_lib(SB), AX
+	JMP	AX
+
+DATA _rt0_amd64_android_argv+0x00(SB)/8,$_rt0_amd64_android_argv0(SB)
+DATA _rt0_amd64_android_argv+0x08(SB)/8,$0
+DATA _rt0_amd64_android_argv+0x10(SB)/8,$0
+DATA _rt0_amd64_android_argv+0x18(SB)/8,$15  // AT_PLATFORM
+DATA _rt0_amd64_android_argv+0x20(SB)/8,$_rt0_amd64_android_auxv0(SB)
+DATA _rt0_amd64_android_argv+0x28(SB)/8,$0
+GLOBL _rt0_amd64_android_argv(SB),NOPTR,$0x30
+
+// TODO: AT_HWCAP necessary? If so, what value?
+
+DATA _rt0_amd64_android_argv0(SB)/8, $"gojni"
+GLOBL _rt0_amd64_android_argv0(SB),RODATA,$8
+
+DATA _rt0_amd64_android_auxv0(SB)/8, $"x86_64"
+GLOBL _rt0_amd64_android_auxv0(SB),RODATA,$8
diff --git a/src/runtime/rt0_android_arm64.s b/src/runtime/rt0_android_arm64.s
new file mode 100644
index 0000000..582fc5a
--- /dev/null
+++ b/src/runtime/rt0_android_arm64.s
@@ -0,0 +1,25 @@
+// Copyright 2015 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"
+
+TEXT _rt0_arm64_android(SB),NOSPLIT,$-8
+	MOVD	$_rt0_arm64_linux(SB), R4
+	B	(R4)
+
+// When building with -buildmode=c-shared, this symbol is called when the shared
+// library is loaded.
+TEXT _rt0_arm64_android_lib(SB),NOSPLIT,$-8
+	MOVW	$1, R0                            // argc
+	MOVD	$_rt0_arm64_android_argv(SB), R1  // **argv
+	MOVD	$_rt0_arm64_linux_lib(SB), R4
+	B	(R4)
+
+DATA _rt0_arm64_android_argv+0x00(SB)/8,$_rt0_arm64_android_argv0(SB)
+DATA _rt0_arm64_android_argv+0x08(SB)/8,$0
+DATA _rt0_arm64_android_argv+0x10(SB)/8,$0
+GLOBL _rt0_arm64_android_argv(SB),NOPTR,$0x18
+
+DATA _rt0_arm64_android_argv0(SB)/8, $"gojni"
+GLOBL _rt0_arm64_android_argv0(SB),RODATA,$8
diff --git a/src/runtime/rt0_darwin_386.s b/src/runtime/rt0_darwin_386.s
index 4c8c92d..6b404db 100644
--- a/src/runtime/rt0_darwin_386.s
+++ b/src/runtime/rt0_darwin_386.s
@@ -12,5 +12,64 @@ TEXT _rt0_386_darwin(SB),NOSPLIT,$8
 	CALL	main(SB)
 	INT	$3
 
+// With -buildmode=c-archive, this symbol is called from a global constructor.
+TEXT _rt0_386_darwin_lib(SB),NOSPLIT,$0
+	PUSHL	BP
+	MOVL	SP, BP
+	PUSHL	BX
+	PUSHL	SI
+	PUSHL	DI
+
+	MOVL	8(BP), AX
+	MOVL	AX, _rt0_386_darwin_lib_argc<>(SB)
+	MOVL	12(BP), AX
+	MOVL	AX, _rt0_386_darwin_lib_argv<>(SB)
+
+	// Synchronous initialization.
+	MOVL	$runtime·libpreinit(SB), AX
+	CALL	AX
+
+	SUBL	$12, SP
+
+	// Create a new thread to do the runtime initialization and return.
+	MOVL	_cgo_sys_thread_create(SB), AX
+	TESTL	AX, AX
+	JZ	nocgo
+	MOVL	$_rt0_386_darwin_lib_go(SB), BX
+	MOVL	BX, 0(SP)
+	MOVL	$0, 4(SP)
+	CALL	AX
+	JMP     restore
+
+nocgo:
+	MOVL	$0x800000, 0(SP)               // stacksize = 8192KB
+	MOVL	$_rt0_386_darwin_lib_go(SB), AX
+	MOVL	AX, 4(SP)                      // fn
+	MOVL	$0, 8(SP)                      // fnarg
+	MOVL	$runtime·newosproc0(SB), AX
+	CALL	AX
+
+restore:
+	ADDL	$12, SP
+	POPL	DI
+	POPL	SI
+	POPL	BX
+	POPL	BP
+	RET
+
+TEXT _rt0_386_darwin_lib_go(SB),NOSPLIT,$12
+	MOVL	_rt0_386_darwin_lib_argc<>(SB), AX
+	MOVL	AX, 0(SP)
+	MOVL	_rt0_386_darwin_lib_argv<>(SB), AX
+	MOVL	AX, 4(SP)
+	MOVL	$runtime·rt0_go(SB), AX
+	CALL	AX
+	RET
+
+DATA _rt0_386_darwin_lib_argc<>(SB)/4, $0
+GLOBL _rt0_386_darwin_lib_argc<>(SB),NOPTR, $4
+DATA _rt0_386_darwin_lib_argv<>(SB)/4, $0
+GLOBL _rt0_386_darwin_lib_argv<>(SB),NOPTR, $4
+
 TEXT main(SB),NOSPLIT,$0
 	JMP	runtime·rt0_go(SB)
diff --git a/src/runtime/rt0_darwin_amd64.s b/src/runtime/rt0_darwin_amd64.s
index 8d50e96..ad46fd4 100644
--- a/src/runtime/rt0_darwin_amd64.s
+++ b/src/runtime/rt0_darwin_amd64.s
@@ -12,10 +12,21 @@ TEXT _rt0_amd64_darwin(SB),NOSPLIT,$-8
 
 // When linking with -shared, this symbol is called when the shared library
 // is loaded.
-TEXT _rt0_amd64_darwin_lib(SB),NOSPLIT,$40
+TEXT _rt0_amd64_darwin_lib(SB),NOSPLIT,$0x48
+	MOVQ	BX, 0x18(SP)
+	MOVQ	BP, 0x20(SP)
+	MOVQ	R12, 0x28(SP)
+	MOVQ	R13, 0x30(SP)
+	MOVQ	R14, 0x38(SP)
+	MOVQ	R15, 0x40(SP)
+
 	MOVQ	DI, _rt0_amd64_darwin_lib_argc<>(SB)
 	MOVQ	SI, _rt0_amd64_darwin_lib_argv<>(SB)
 
+	// Synchronous initialization.
+	MOVQ	$runtime·libpreinit(SB), AX
+	CALL	AX
+
 	// Create a new thread to do the runtime initialization and return.
 	MOVQ	_cgo_sys_thread_create(SB), AX
 	TESTQ	AX, AX
@@ -23,7 +34,8 @@ TEXT _rt0_amd64_darwin_lib(SB),NOSPLIT,$40
 	MOVQ	$_rt0_amd64_darwin_lib_go(SB), DI
 	MOVQ	$0, SI
 	CALL	AX
-	RET
+	JMP	restore
+
 nocgo:
 	MOVQ	$8388608, 0(SP)                    // stacksize
 	MOVQ	$_rt0_amd64_darwin_lib_go(SB), AX
@@ -31,6 +43,14 @@ nocgo:
 	MOVQ	$0, 16(SP)                         // fnarg
 	MOVQ	$runtime·newosproc0(SB), AX
 	CALL	AX
+
+restore:
+	MOVQ	0x18(SP), BX
+	MOVQ	0x20(SP), BP
+	MOVQ	0x28(SP), R12
+	MOVQ	0x30(SP), R13
+	MOVQ	0x38(SP), R14
+	MOVQ	0x40(SP), R15
 	RET
 
 TEXT _rt0_amd64_darwin_lib_go(SB),NOSPLIT,$0
diff --git a/src/runtime/rt0_darwin_arm.s b/src/runtime/rt0_darwin_arm.s
index d609850..cbbea80 100644
--- a/src/runtime/rt0_darwin_arm.s
+++ b/src/runtime/rt0_darwin_arm.s
@@ -25,6 +25,10 @@ TEXT _rt0_arm_darwin_lib(SB),NOSPLIT,$0
 	MOVW  R0, _rt0_arm_darwin_lib_argc<>(SB)
 	MOVW  R1, _rt0_arm_darwin_lib_argv<>(SB)
 
+	// Synchronous initialization.
+	MOVW	$runtime·libpreinit(SB), R3
+	CALL	(R3)
+
 	// Create a new thread to do the runtime initialization and return.
 	MOVW  _cgo_sys_thread_create(SB), R3
 	CMP   $0, R3
diff --git a/src/runtime/rt0_darwin_arm64.s b/src/runtime/rt0_darwin_arm64.s
index e4e4a30..fa676c0 100644
--- a/src/runtime/rt0_darwin_arm64.s
+++ b/src/runtime/rt0_darwin_arm64.s
@@ -25,6 +25,11 @@ TEXT _rt0_arm64_darwin_lib(SB),NOSPLIT,$0
 
 	MOVD  R0, _rt0_arm64_darwin_lib_argc<>(SB)
 	MOVD  R1, _rt0_arm64_darwin_lib_argv<>(SB)
+
+	// Synchronous initialization.
+	MOVD	$runtime·libpreinit(SB), R4
+	BL	(R4)
+
 	// Create a new thread to do the runtime initialization and return.
 	MOVD  _cgo_sys_thread_create(SB), R4
 	MOVD  $_rt0_arm64_darwin_lib_go(SB), R0
diff --git a/src/runtime/rt0_linux_386.s b/src/runtime/rt0_linux_386.s
index 633e806..59a30b4 100644
--- a/src/runtime/rt0_linux_386.s
+++ b/src/runtime/rt0_linux_386.s
@@ -26,6 +26,10 @@ TEXT _rt0_386_linux_lib(SB),NOSPLIT,$0
 	MOVL	12(BP), AX
 	MOVL	AX, _rt0_386_linux_lib_argv<>(SB)
 
+	// Synchronous initialization.
+	MOVL	$runtime·libpreinit(SB), AX
+	CALL	AX
+
 	SUBL	$8, SP
 
 	// Create a new thread to do the runtime initialization.
diff --git a/src/runtime/rt0_linux_amd64.s b/src/runtime/rt0_linux_amd64.s
index 726b550..564b51c 100644
--- a/src/runtime/rt0_linux_amd64.s
+++ b/src/runtime/rt0_linux_amd64.s
@@ -23,6 +23,10 @@ TEXT _rt0_amd64_linux_lib(SB),NOSPLIT,$0x48
 	MOVQ	DI, _rt0_amd64_linux_lib_argc<>(SB)
 	MOVQ	SI, _rt0_amd64_linux_lib_argv<>(SB)
 
+	// Synchronous initialization.
+	MOVQ	$runtime·libpreinit(SB), AX
+	CALL	AX
+
 	// Create a new thread to do the runtime initialization and return.
 	MOVQ	_cgo_sys_thread_create(SB), AX
 	TESTQ	AX, AX
diff --git a/src/runtime/rt0_linux_arm.s b/src/runtime/rt0_linux_arm.s
index b71a3f9..d28c15a 100644
--- a/src/runtime/rt0_linux_arm.s
+++ b/src/runtime/rt0_linux_arm.s
@@ -26,6 +26,10 @@ TEXT _rt0_arm_linux_lib(SB),NOSPLIT,$32
 	MOVW	R0, _rt0_arm_linux_lib_argc<>(SB)
 	MOVW	R1, _rt0_arm_linux_lib_argv<>(SB)
 
+	// Synchronous initialization.
+	MOVW	$runtime·libpreinit(SB), R2
+	CALL	(R2)
+
 	// Create a new thread to do the runtime initialization.
 	MOVW	_cgo_sys_thread_create(SB), R2
 	CMP	$0, R2
diff --git a/src/runtime/rt0_linux_arm64.s b/src/runtime/rt0_linux_arm64.s
index 1eb0352..2b32e35 100644
--- a/src/runtime/rt0_linux_arm64.s
+++ b/src/runtime/rt0_linux_arm64.s
@@ -9,6 +9,54 @@ TEXT _rt0_arm64_linux(SB),NOSPLIT,$-8
 	ADD	$8, RSP, R1	// argv
 	BL	main(SB)
 
+// When building with -buildmode=c-shared, this symbol is called when the shared
+// library is loaded.
+TEXT _rt0_arm64_linux_lib(SB),NOSPLIT,$40
+	// R27 is REGTMP, reserved for liblink. It is used below to
+	// move R0/R1 into globals. However in the standard ARM64 calling
+	// convention, it is a callee-saved register.
+	MOVD	R27, 24(RSP)
+
+	MOVD	R0, _rt0_arm64_linux_lib_argc<>(SB)
+	MOVD	R1, _rt0_arm64_linux_lib_argv<>(SB)
+
+	// Synchronous initialization.
+	MOVD	$runtime·libpreinit(SB), R4
+	BL	(R4)
+
+	// Create a new thread to do the runtime initialization and return.
+	MOVD	_cgo_sys_thread_create(SB), R4
+	CMP	$0, R4
+	BEQ	nocgo
+	MOVD	$_rt0_arm64_linux_lib_go(SB), R0
+	MOVD	$0, R1
+	BL	(R4)
+	B	restore
+
+nocgo:
+	MOVD	$0x800000, R0                     // stacksize = 8192KB
+	MOVD	$_rt0_arm64_linux_lib_go(SB), R1
+	MOVD	R0, 8(RSP)
+	MOVD	R1, 16(RSP)
+	MOVD	$runtime·newosproc0(SB),R4
+	BL	(R4)
+
+restore:
+	MOVD	24(RSP), R27
+	RET
+
+TEXT _rt0_arm64_linux_lib_go(SB),NOSPLIT,$0
+	MOVD	_rt0_arm64_linux_lib_argc<>(SB), R0
+	MOVD	_rt0_arm64_linux_lib_argv<>(SB), R1
+	MOVD	$runtime·rt0_go(SB),R4
+	B       (R4)
+
+DATA _rt0_arm64_linux_lib_argc<>(SB)/8, $0
+GLOBL _rt0_arm64_linux_lib_argc<>(SB),NOPTR, $8
+DATA _rt0_arm64_linux_lib_argv<>(SB)/8, $0
+GLOBL _rt0_arm64_linux_lib_argv<>(SB),NOPTR, $8
+
+
 TEXT main(SB),NOSPLIT,$-8
 	MOVD	$runtime·rt0_go(SB), R2
 	BL	(R2)
diff --git a/src/runtime/rt0_linux_mips64x.s b/src/runtime/rt0_linux_mips64x.s
new file mode 100644
index 0000000..c7e35f5
--- /dev/null
+++ b/src/runtime/rt0_linux_mips64x.s
@@ -0,0 +1,31 @@
+// Copyright 2015 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.
+
+// +build linux
+// +build mips64 mips64le
+
+#include "textflag.h"
+
+TEXT _rt0_mips64_linux(SB),NOSPLIT,$0
+	JMP	_main<>(SB)
+
+TEXT _rt0_mips64le_linux(SB),NOSPLIT,$0
+	JMP	_main<>(SB)
+
+TEXT _main<>(SB),NOSPLIT,$-8
+	// In a statically linked binary, the stack contains argc,
+	// argv as argc string pointers followed by a NULL, envv as a
+	// sequence of string pointers followed by a NULL, and auxv.
+	// There is no TLS base pointer.
+#ifdef GOARCH_mips64
+	MOVW 4(R29), R1 // argc, big-endian ABI places int32 at offset 4
+#else
+	MOVW 0(R29), R1 // argc
+#endif
+	ADDV $8, R29, R2 // argv
+	JMP main(SB)
+
+TEXT main(SB),NOSPLIT,$-8
+	MOVV	$runtime·rt0_go(SB), R4
+	JMP	(R4)
diff --git a/src/runtime/rt0_linux_ppc64.s b/src/runtime/rt0_linux_ppc64.s
index 33e973d..f814515 100644
--- a/src/runtime/rt0_linux_ppc64.s
+++ b/src/runtime/rt0_linux_ppc64.s
@@ -18,6 +18,6 @@ TEXT _main<>(SB),NOSPLIT,$-8
 	BR main(SB)
 
 TEXT main(SB),NOSPLIT,$-8
-	MOVD	$runtime·rt0_go(SB), R31
-	MOVD	R31, CTR
+	MOVD	$runtime·rt0_go(SB), R12
+	MOVD	R12, CTR
 	BR	(CTR)
diff --git a/src/runtime/rt0_linux_ppc64le.s b/src/runtime/rt0_linux_ppc64le.s
index f5c0af5..ac7b922 100644
--- a/src/runtime/rt0_linux_ppc64le.s
+++ b/src/runtime/rt0_linux_ppc64le.s
@@ -1,3 +1,4 @@
+#include "go_asm.h"
 #include "textflag.h"
 
 TEXT _rt0_ppc64le_linux(SB),NOSPLIT,$0
@@ -22,13 +23,13 @@ TEXT _main<>(SB),NOSPLIT,$-8
 	// Statically linked
 	MOVD	0(R1), R3 // argc
 	ADD	$8, R1, R4 // argv
-	MOVD	$runtime·tls0(SB), R13 // TLS
+	MOVD	$runtime·m0+m_tls(SB), R13 // TLS
 	ADD	$0x7000, R13
 
 dlink:
 	BR	main(SB)
 
 TEXT main(SB),NOSPLIT,$-8
-	MOVD	$runtime·rt0_go(SB), R31
-	MOVD	R31, CTR
+	MOVD	$runtime·rt0_go(SB), R12
+	MOVD	R12, CTR
 	BR	(CTR)
diff --git a/src/runtime/rt0_plan9_386.s b/src/runtime/rt0_plan9_386.s
index c451299..cbbf245 100644
--- a/src/runtime/rt0_plan9_386.s
+++ b/src/runtime/rt0_plan9_386.s
@@ -16,8 +16,6 @@ TEXT _rt0_386_plan9(SB),NOSPLIT,$12
 	MOVL	AX, 4(SP)
 	CALL	runtime·rt0_go(SB)
 
-DATA  runtime·isplan9(SB)/4, $1
-GLOBL runtime·isplan9(SB), NOPTR, $4
 GLOBL _tos(SB), NOPTR, $4
 GLOBL _privates(SB), NOPTR, $4
 GLOBL _nprivates(SB), NOPTR, $4
diff --git a/src/runtime/rt0_plan9_amd64.s b/src/runtime/rt0_plan9_amd64.s
index ec2d9ec..6fd493a 100644
--- a/src/runtime/rt0_plan9_amd64.s
+++ b/src/runtime/rt0_plan9_amd64.s
@@ -14,8 +14,6 @@ TEXT _rt0_amd64_plan9(SB),NOSPLIT,$24
 	MOVQ	$runtime·rt0_go(SB), AX
 	JMP	AX
 
-DATA runtime·isplan9(SB)/4, $1
-GLOBL runtime·isplan9(SB), NOPTR, $4
 GLOBL _tos(SB), NOPTR, $8
 GLOBL _privates(SB), NOPTR, $8
 GLOBL _nprivates(SB), NOPTR, $4
diff --git a/src/runtime/rt0_solaris_amd64.s b/src/runtime/rt0_solaris_amd64.s
index 5997cbf..e2d1e71 100644
--- a/src/runtime/rt0_solaris_amd64.s
+++ b/src/runtime/rt0_solaris_amd64.s
@@ -13,6 +13,3 @@ TEXT _rt0_amd64_solaris(SB),NOSPLIT,$-8
 TEXT main(SB),NOSPLIT,$-8
 	MOVQ	$runtime·rt0_go(SB), AX
 	JMP	AX
-
-DATA runtime·issolaris(SB)/4, $1
-GLOBL runtime·issolaris(SB), NOPTR, $4
diff --git a/src/runtime/rt0_windows_386.s b/src/runtime/rt0_windows_386.s
index 03f95d1..0150cc2 100644
--- a/src/runtime/rt0_windows_386.s
+++ b/src/runtime/rt0_windows_386.s
@@ -14,7 +14,3 @@ TEXT _rt0_386_windows(SB),NOSPLIT,$12
 
 TEXT _main(SB),NOSPLIT,$0
 	JMP	runtime·rt0_go(SB)
-
-
-DATA  runtime·iswindows(SB)/4, $1
-GLOBL runtime·iswindows(SB), NOPTR, $4
diff --git a/src/runtime/rt0_windows_amd64.s b/src/runtime/rt0_windows_amd64.s
index df956ba..95dce06 100644
--- a/src/runtime/rt0_windows_amd64.s
+++ b/src/runtime/rt0_windows_amd64.s
@@ -15,6 +15,3 @@ TEXT _rt0_amd64_windows(SB),NOSPLIT,$-8
 TEXT main(SB),NOSPLIT,$-8
 	MOVQ	$runtime·rt0_go(SB), AX
 	JMP	AX
-
-DATA  runtime·iswindows(SB)/4, $1
-GLOBL runtime·iswindows(SB), NOPTR, $4
diff --git a/src/runtime/runtime-gdb_test.go b/src/runtime/runtime-gdb_test.go
index 2843633..6ebc69a 100644
--- a/src/runtime/runtime-gdb_test.go
+++ b/src/runtime/runtime-gdb_test.go
@@ -60,6 +60,9 @@ func TestGdbPython(t *testing.T) {
 	if runtime.GOOS == "darwin" {
 		t.Skip("gdb does not work on darwin")
 	}
+	if final := os.Getenv("GOROOT_FINAL"); final != "" && runtime.GOROOT() != final {
+		t.Skip("gdb test can fail with GOROOT_FINAL pending")
+	}
 
 	checkGdbPython(t)
 
@@ -84,6 +87,7 @@ func TestGdbPython(t *testing.T) {
 
 	args := []string{"-nx", "-q", "--batch", "-iex",
 		fmt.Sprintf("add-auto-load-safe-path %s/src/runtime", runtime.GOROOT()),
+		"-ex", "info auto-load python-scripts",
 		"-ex", "br main.go:10",
 		"-ex", "run",
 		"-ex", "echo BEGIN info goroutines\n",
@@ -103,7 +107,7 @@ func TestGdbPython(t *testing.T) {
 	// stack frames on RISC architectures.
 	canBackTrace := false
 	switch runtime.GOARCH {
-	case "amd64", "386", "ppc64", "ppc64le", "arm", "arm64":
+	case "amd64", "386", "ppc64", "ppc64le", "arm", "arm64", "mips64", "mips64le":
 		canBackTrace = true
 		args = append(args,
 			"-ex", "echo BEGIN goroutine 2 bt\n",
@@ -126,7 +130,10 @@ func TestGdbPython(t *testing.T) {
 			t.Skipf("skipping because GOROOT=%s does not exist", runtime.GOROOT())
 		}
 
-		t.Fatalf("failed to load Go runtime support: %s", firstLine)
+		_, file, _, _ := runtime.Caller(1)
+
+		t.Logf("package testing source file: %s", file)
+		t.Fatalf("failed to load Go runtime support: %s\n%s", firstLine, got)
 	}
 
 	// Extract named BEGIN...END blocks from output
diff --git a/src/runtime/runtime-lldb_test.go b/src/runtime/runtime-lldb_test.go
new file mode 100644
index 0000000..2bd91c1
--- /dev/null
+++ b/src/runtime/runtime-lldb_test.go
@@ -0,0 +1,262 @@
+// 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 runtime_test
+
+import (
+	"debug/elf"
+	"debug/macho"
+	"encoding/binary"
+	"internal/testenv"
+	"io"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"testing"
+)
+
+var lldbPath string
+
+func checkLldbPython(t *testing.T) {
+	cmd := exec.Command("lldb", "-P")
+	out, err := cmd.CombinedOutput()
+	if err != nil {
+		t.Skipf("skipping due to issue running lldb: %v\n%s", err, out)
+	}
+	lldbPath = strings.TrimSpace(string(out))
+
+	cmd = exec.Command("/usr/bin/python2.7", "-c", "import sys;sys.path.append(sys.argv[1]);import lldb; print('go lldb python support')", lldbPath)
+	out, err = cmd.CombinedOutput()
+
+	if err != nil {
+		t.Skipf("skipping due to issue running python: %v\n%s", err, out)
+	}
+	if string(out) != "go lldb python support\n" {
+		t.Skipf("skipping due to lack of python lldb support: %s", out)
+	}
+
+	if runtime.GOOS == "darwin" {
+		// Try to see if we have debugging permissions.
+		cmd = exec.Command("/usr/sbin/DevToolsSecurity", "-status")
+		out, err = cmd.CombinedOutput()
+		if err != nil {
+			t.Skipf("DevToolsSecurity failed: %v", err)
+		} else if !strings.Contains(string(out), "enabled") {
+			t.Skip(string(out))
+		}
+		cmd = exec.Command("/usr/bin/groups")
+		out, err = cmd.CombinedOutput()
+		if err != nil {
+			t.Skipf("groups failed: %v", err)
+		} else if !strings.Contains(string(out), "_developer") {
+			t.Skip("Not in _developer group")
+		}
+	}
+}
+
+const lldbHelloSource = `
+package main
+import "fmt"
+func main() {
+	mapvar := make(map[string]string,5)
+	mapvar["abc"] = "def"
+	mapvar["ghi"] = "jkl"
+	intvar := 42
+	ptrvar := &intvar
+	fmt.Println("hi") // line 10
+	_ = ptrvar
+}
+`
+
+const lldbScriptSource = `
+import sys
+sys.path.append(sys.argv[1])
+import lldb
+import os
+
+TIMEOUT_SECS = 5
+
+debugger = lldb.SBDebugger.Create()
+debugger.SetAsync(True)
+target = debugger.CreateTargetWithFileAndArch("a.exe", None)
+if target:
+  print "Created target"
+  main_bp = target.BreakpointCreateByLocation("main.go", 10)
+  if main_bp:
+    print "Created breakpoint"
+  process = target.LaunchSimple(None, None, os.getcwd())
+  if process:
+    print "Process launched"
+    listener = debugger.GetListener()
+    process.broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged)
+    while True:
+      event = lldb.SBEvent()
+      if listener.WaitForEvent(TIMEOUT_SECS, event):
+        if lldb.SBProcess.GetRestartedFromEvent(event):
+          continue
+        state = process.GetState()
+        if state in [lldb.eStateUnloaded, lldb.eStateLaunching, lldb.eStateRunning]:
+          continue
+      else:
+        print "Timeout launching"
+      break
+    if state == lldb.eStateStopped:
+      for t in process.threads:
+        if t.GetStopReason() == lldb.eStopReasonBreakpoint:
+          print "Hit breakpoint"
+          frame = t.GetFrameAtIndex(0)
+          if frame:
+            if frame.line_entry:
+              print "Stopped at %s:%d" % (frame.line_entry.file.basename, frame.line_entry.line)
+            if frame.function:
+              print "Stopped in %s" % (frame.function.name,)
+            var = frame.FindVariable('intvar')
+            if var:
+              print "intvar = %s" % (var.GetValue(),)
+            else:
+              print "no intvar"
+    else:
+      print "Process state", state
+    process.Destroy()
+else:
+  print "Failed to create target a.exe"
+
+lldb.SBDebugger.Destroy(debugger)
+sys.exit()
+`
+
+const expectedLldbOutput = `Created target
+Created breakpoint
+Process launched
+Hit breakpoint
+Stopped at main.go:10
+Stopped in main.main
+intvar = 42
+`
+
+func TestLldbPython(t *testing.T) {
+	testenv.MustHaveGoBuild(t)
+	if final := os.Getenv("GOROOT_FINAL"); final != "" && runtime.GOROOT() != final {
+		t.Skip("gdb test can fail with GOROOT_FINAL pending")
+	}
+
+	checkLldbPython(t)
+
+	dir, err := ioutil.TempDir("", "go-build")
+	if err != nil {
+		t.Fatalf("failed to create temp directory: %v", err)
+	}
+	defer os.RemoveAll(dir)
+
+	src := filepath.Join(dir, "main.go")
+	err = ioutil.WriteFile(src, []byte(lldbHelloSource), 0644)
+	if err != nil {
+		t.Fatalf("failed to create file: %v", err)
+	}
+
+	cmd := exec.Command("go", "build", "-gcflags", "-N -l", "-o", "a.exe")
+	cmd.Dir = dir
+	out, err := cmd.CombinedOutput()
+	if err != nil {
+		t.Fatalf("building source %v\n%s", err, out)
+	}
+
+	src = filepath.Join(dir, "script.py")
+	err = ioutil.WriteFile(src, []byte(lldbScriptSource), 0755)
+	if err != nil {
+		t.Fatalf("failed to create script: %v", err)
+	}
+
+	cmd = exec.Command("/usr/bin/python2.7", "script.py", lldbPath)
+	cmd.Dir = dir
+	got, _ := cmd.CombinedOutput()
+
+	if string(got) != expectedLldbOutput {
+		if strings.Contains(string(got), "Timeout launching") {
+			t.Skip("Timeout launching")
+		}
+		t.Fatalf("Unexpected lldb output:\n%s", got)
+	}
+}
+
+// Check that aranges are valid even when lldb isn't installed.
+func TestDwarfAranges(t *testing.T) {
+	testenv.MustHaveGoBuild(t)
+	dir, err := ioutil.TempDir("", "go-build")
+	if err != nil {
+		t.Fatalf("failed to create temp directory: %v", err)
+	}
+	defer os.RemoveAll(dir)
+
+	src := filepath.Join(dir, "main.go")
+	err = ioutil.WriteFile(src, []byte(lldbHelloSource), 0644)
+	if err != nil {
+		t.Fatalf("failed to create file: %v", err)
+	}
+
+	cmd := exec.Command("go", "build", "-o", "a.exe")
+	cmd.Dir = dir
+	out, err := cmd.CombinedOutput()
+	if err != nil {
+		t.Fatalf("building source %v\n%s", err, out)
+	}
+
+	filename := filepath.Join(dir, "a.exe")
+	if f, err := elf.Open(filename); err == nil {
+		sect := f.Section(".debug_aranges")
+		if sect == nil {
+			t.Fatal("Missing aranges section")
+		}
+		verifyAranges(t, f.ByteOrder, sect.Open())
+	} else if f, err := macho.Open(filename); err == nil {
+		sect := f.Section("__debug_aranges")
+		if sect == nil {
+			t.Fatal("Missing aranges section")
+		}
+		verifyAranges(t, f.ByteOrder, sect.Open())
+	} else {
+		t.Skip("Not an elf or macho binary.")
+	}
+}
+
+func verifyAranges(t *testing.T, byteorder binary.ByteOrder, data io.ReadSeeker) {
+	var header struct {
+		UnitLength  uint32 // does not include the UnitLength field
+		Version     uint16
+		Offset      uint32
+		AddressSize uint8
+		SegmentSize uint8
+	}
+	for {
+		offset, err := data.Seek(0, 1)
+		if err != nil {
+			t.Fatalf("Seek error: %v", err)
+		}
+		if err = binary.Read(data, byteorder, &header); err == io.EOF {
+			return
+		} else if err != nil {
+			t.Fatalf("Error reading arange header: %v", err)
+		}
+		tupleSize := int64(header.SegmentSize) + 2*int64(header.AddressSize)
+		lastTupleOffset := offset + int64(header.UnitLength) + 4 - tupleSize
+		if lastTupleOffset%tupleSize != 0 {
+			t.Fatalf("Invalid arange length %d, (addr %d, seg %d)", header.UnitLength, header.AddressSize, header.SegmentSize)
+		}
+		if _, err = data.Seek(lastTupleOffset, 0); err != nil {
+			t.Fatalf("Seek error: %v", err)
+		}
+		buf := make([]byte, tupleSize)
+		if n, err := data.Read(buf); err != nil || int64(n) < tupleSize {
+			t.Fatalf("Read error: %v", err)
+		}
+		for _, val := range buf {
+			if val != 0 {
+				t.Fatalf("Invalid terminator")
+			}
+		}
+	}
+}
diff --git a/src/runtime/runtime.go b/src/runtime/runtime.go
index 2387d9a..265edf2 100644
--- a/src/runtime/runtime.go
+++ b/src/runtime/runtime.go
@@ -4,10 +4,14 @@
 
 package runtime
 
-import _ "unsafe" // for go:linkname
+import (
+	"runtime/internal/atomic"
+	_ "unsafe" // for go:linkname
+)
 
 //go:generate go run wincallback.go
 //go:generate go run mkduff.go
+//go:generate go run mkfastlog2table.go
 
 var ticks struct {
 	lock mutex
@@ -15,11 +19,9 @@ var ticks struct {
 	val  uint64
 }
 
-var tls0 [8]uintptr // available storage for m0's TLS; not necessarily used; opaque to GC
-
 // Note: Called by runtime/pprof in addition to runtime code.
 func tickspersecond() int64 {
-	r := int64(atomicload64(&ticks.val))
+	r := int64(atomic.Load64(&ticks.val))
 	if r != 0 {
 		return r
 	}
@@ -38,7 +40,7 @@ func tickspersecond() int64 {
 		if r == 0 {
 			r++
 		}
-		atomicstore64(&ticks.val, uint64(r))
+		atomic.Store64(&ticks.val, uint64(r))
 	}
 	unlock(&ticks.lock)
 	return r
diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go
index 134c999..f63e09c 100644
--- a/src/runtime/runtime1.go
+++ b/src/runtime/runtime1.go
@@ -4,34 +4,47 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 // Keep a cached value to make gotraceback fast,
 // since we call it on every call to gentraceback.
-// The cached value is a uint32 in which the low bit
-// is the "crash" setting and the top 31 bits are the
-// gotraceback value.
-var traceback_cache uint32 = 2 << 1
-
-// The GOTRACEBACK environment variable controls the
-// behavior of a Go program that is crashing and exiting.
-//	GOTRACEBACK=0   suppress all tracebacks
-//	GOTRACEBACK=1   default behavior - show tracebacks but exclude runtime frames
-//	GOTRACEBACK=2   show tracebacks including runtime frames
-//	GOTRACEBACK=crash   show tracebacks including runtime frames, then crash (core dump etc)
+// The cached value is a uint32 in which the low bits
+// are the "crash" and "all" settings and the remaining
+// bits are the traceback value (0 off, 1 on, 2 include system).
+const (
+	tracebackCrash = 1 << iota
+	tracebackAll
+	tracebackShift = iota
+)
+
+var traceback_cache uint32 = 2 << tracebackShift
+var traceback_env uint32
+
+// gotraceback returns the current traceback settings.
+//
+// If level is 0, suppress all tracebacks.
+// If level is 1, show tracebacks, but exclude runtime frames.
+// If level is 2, show tracebacks including runtime frames.
+// If all is set, print all goroutine stacks. Otherwise, print just the current goroutine.
+// If crash is set, crash (core dump, etc) after tracebacking.
+//
 //go:nosplit
-func gotraceback(crash *bool) int32 {
+func gotraceback() (level int32, all, crash bool) {
 	_g_ := getg()
-	if crash != nil {
-		*crash = false
-	}
+	all = _g_.m.throwing > 0
 	if _g_.m.traceback != 0 {
-		return int32(_g_.m.traceback)
-	}
-	if crash != nil {
-		*crash = traceback_cache&1 != 0
+		level = int32(_g_.m.traceback)
+		return
 	}
-	return int32(traceback_cache >> 1)
+	t := atomic.Load(&traceback_cache)
+	crash = t&tracebackCrash != 0
+	all = all || t&tracebackAll != 0
+	level = int32(t >> tracebackShift)
+	return
 }
 
 var (
@@ -42,7 +55,7 @@ var (
 // nosplit for use in linux/386 startup linux_setup_vdso
 //go:nosplit
 func argv_index(argv **byte, i int32) *byte {
-	return *(**byte)(add(unsafe.Pointer(argv), uintptr(i)*ptrSize))
+	return *(**byte)(add(unsafe.Pointer(argv), uintptr(i)*sys.PtrSize))
 }
 
 func args(c int32, v **byte) {
@@ -51,13 +64,6 @@ func args(c int32, v **byte) {
 	sysargs(c, v)
 }
 
-var (
-	// TODO: Retire in favor of GOOS== checks.
-	isplan9   int32
-	issolaris int32
-	iswindows int32
-)
-
 func goargs() {
 	if GOOS == "windows" {
 		return
@@ -99,36 +105,36 @@ func testAtomic64() {
 	prefetcht1(uintptr(unsafe.Pointer(&test_z64)))
 	prefetcht2(uintptr(unsafe.Pointer(&test_z64)))
 	prefetchnta(uintptr(unsafe.Pointer(&test_z64)))
-	if cas64(&test_z64, test_x64, 1) {
+	if atomic.Cas64(&test_z64, test_x64, 1) {
 		throw("cas64 failed")
 	}
 	if test_x64 != 0 {
 		throw("cas64 failed")
 	}
 	test_x64 = 42
-	if !cas64(&test_z64, test_x64, 1) {
+	if !atomic.Cas64(&test_z64, test_x64, 1) {
 		throw("cas64 failed")
 	}
 	if test_x64 != 42 || test_z64 != 1 {
 		throw("cas64 failed")
 	}
-	if atomicload64(&test_z64) != 1 {
+	if atomic.Load64(&test_z64) != 1 {
 		throw("load64 failed")
 	}
-	atomicstore64(&test_z64, (1<<40)+1)
-	if atomicload64(&test_z64) != (1<<40)+1 {
+	atomic.Store64(&test_z64, (1<<40)+1)
+	if atomic.Load64(&test_z64) != (1<<40)+1 {
 		throw("store64 failed")
 	}
-	if xadd64(&test_z64, (1<<40)+1) != (2<<40)+2 {
+	if atomic.Xadd64(&test_z64, (1<<40)+1) != (2<<40)+2 {
 		throw("xadd64 failed")
 	}
-	if atomicload64(&test_z64) != (2<<40)+2 {
+	if atomic.Load64(&test_z64) != (2<<40)+2 {
 		throw("xadd64 failed")
 	}
-	if xchg64(&test_z64, (3<<40)+3) != (2<<40)+2 {
+	if atomic.Xchg64(&test_z64, (3<<40)+3) != (2<<40)+2 {
 		throw("xchg64 failed")
 	}
-	if atomicload64(&test_z64) != (3<<40)+3 {
+	if atomic.Load64(&test_z64) != (3<<40)+3 {
 		throw("xchg64 failed")
 	}
 }
@@ -189,10 +195,10 @@ func check() {
 	if unsafe.Sizeof(j) != 8 {
 		throw("bad j")
 	}
-	if unsafe.Sizeof(k) != ptrSize {
+	if unsafe.Sizeof(k) != sys.PtrSize {
 		throw("bad k")
 	}
-	if unsafe.Sizeof(l) != ptrSize {
+	if unsafe.Sizeof(l) != sys.PtrSize {
 		throw("bad l")
 	}
 	if unsafe.Sizeof(x1) != 1 {
@@ -211,7 +217,7 @@ func check() {
 
 	var z uint32
 	z = 1
-	if !cas(&z, 1, 2) {
+	if !atomic.Cas(&z, 1, 2) {
 		throw("cas1")
 	}
 	if z != 2 {
@@ -219,7 +225,7 @@ func check() {
 	}
 
 	z = 4
-	if cas(&z, 5, 6) {
+	if atomic.Cas(&z, 5, 6) {
 		throw("cas3")
 	}
 	if z != 4 {
@@ -227,7 +233,7 @@ func check() {
 	}
 
 	z = 0xffffffff
-	if !cas(&z, 0xffffffff, 0xfffffffe) {
+	if !atomic.Cas(&z, 0xffffffff, 0xfffffffe) {
 		throw("cas5")
 	}
 	if z != 0xfffffffe {
@@ -235,7 +241,7 @@ func check() {
 	}
 
 	k = unsafe.Pointer(uintptr(0xfedcb123))
-	if ptrSize == 8 {
+	if sys.PtrSize == 8 {
 		k = unsafe.Pointer(uintptr(unsafe.Pointer(k)) << 10)
 	}
 	if casp(&k, nil, nil) {
@@ -250,7 +256,7 @@ func check() {
 	}
 
 	m = [4]byte{1, 1, 1, 1}
-	atomicor8(&m[1], 0xf0)
+	atomic.Or8(&m[1], 0xf0)
 	if m[0] != 1 || m[1] != 0xf1 || m[2] != 1 || m[3] != 1 {
 		throw("atomicor8")
 	}
@@ -292,6 +298,10 @@ func check() {
 	if _FixedStack != round2(_FixedStack) {
 		throw("FixedStack is not power-of-2")
 	}
+
+	if !checkASM() {
+		throw("assembly checks failed")
+	}
 }
 
 type dbgVar struct {
@@ -305,6 +315,7 @@ type dbgVar struct {
 // already have an initial value.
 var debug struct {
 	allocfreetrace    int32
+	cgocheck          int32
 	efence            int32
 	gccheckmark       int32
 	gcpacertrace      int32
@@ -323,6 +334,7 @@ var debug struct {
 
 var dbgvars = []dbgVar{
 	{"allocfreetrace", &debug.allocfreetrace},
+	{"cgocheck", &debug.cgocheck},
 	{"efence", &debug.efence},
 	{"gccheckmark", &debug.gccheckmark},
 	{"gcpacertrace", &debug.gcpacertrace},
@@ -341,6 +353,7 @@ var dbgvars = []dbgVar{
 
 func parsedebugvars() {
 	// defaults
+	debug.cgocheck = 1
 	debug.invalidptr = 1
 
 	for p := gogetenv("GODEBUG"); p != ""; {
@@ -371,23 +384,47 @@ func parsedebugvars() {
 		}
 	}
 
-	switch p := gogetenv("GOTRACEBACK"); p {
-	case "":
-		traceback_cache = 1 << 1
+	setTraceback(gogetenv("GOTRACEBACK"))
+	traceback_env = traceback_cache
+
+	if debug.gcstackbarrierall > 0 {
+		firstStackBarrierOffset = 0
+	}
+
+	// For cgocheck > 1, we turn on the write barrier at all times
+	// and check all pointer writes.
+	if debug.cgocheck > 1 {
+		writeBarrier.cgo = true
+		writeBarrier.enabled = true
+	}
+}
+
+//go:linkname setTraceback runtime/debug.SetTraceback
+func setTraceback(level string) {
+	var t uint32
+	switch level {
+	case "none":
+		t = 0
+	case "single", "":
+		t = 1 << tracebackShift
+	case "all":
+		t = 1<<tracebackShift | tracebackAll
+	case "system":
+		t = 2<<tracebackShift | tracebackAll
 	case "crash":
-		traceback_cache = 2<<1 | 1
+		t = 2<<tracebackShift | tracebackAll | tracebackCrash
 	default:
-		traceback_cache = uint32(atoi(p)) << 1
+		t = uint32(atoi(level))<<tracebackShift | tracebackAll
 	}
 	// when C owns the process, simply exit'ing the process on fatal errors
 	// and panics is surprising. Be louder and abort instead.
 	if islibrary || isarchive {
-		traceback_cache |= 1
+		t |= tracebackCrash
 	}
 
-	if debug.gcstackbarrierall > 0 {
-		firstStackBarrierOffset = 0
-	}
+	t |= traceback_env
+
+	atomic.Store(&traceback_cache, t)
 }
 
 // Poor mans 64-bit division.
@@ -440,7 +477,6 @@ func gomcache() *mcache {
 }
 
 //go:linkname reflect_typelinks reflect.typelinks
-//go:nosplit
 func reflect_typelinks() [][]*_type {
 	ret := [][]*_type{firstmoduledata.typelinks}
 	for datap := firstmoduledata.next; datap != nil; datap = datap.next {
diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go
index 57cd869..917fe89 100644
--- a/src/runtime/runtime2.go
+++ b/src/runtime/runtime2.go
@@ -4,7 +4,11 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 /*
  * defined constants
@@ -45,14 +49,6 @@ const (
 	_Pdead
 )
 
-// The next line makes 'go generate' write the zgen_*.go files with
-// per-OS and per-arch information, including constants
-// named goos_$GOOS and goarch_$GOARCH for every
-// known GOOS and GOARCH. The constant is 1 on the
-// current system, 0 otherwise; multiplying by them is
-// useful for defining GOOS- or GOARCH-specific constants.
-//go:generate go run gengoos.go
-
 type mutex struct {
 	// Futex-based impl treats it as uint32 key,
 	// while sema-based impl as M* waitm.
@@ -67,11 +63,6 @@ type note struct {
 	key uintptr
 }
 
-type _string struct {
-	str *byte
-	len int
-}
-
 type funcval struct {
 	fn uintptr
 	// variable-size, fn-specific data here
@@ -87,6 +78,10 @@ type eface struct {
 	data  unsafe.Pointer
 }
 
+func efaceOf(ep *interface{}) *eface {
+	return (*eface)(unsafe.Pointer(ep))
+}
+
 // The guintptr, muintptr, and puintptr are all used to bypass write barriers.
 // It is particularly important to avoid write barriers when the current P has
 // been released, because the GC thinks the world is stopped, and an
@@ -127,20 +122,31 @@ type eface struct {
 // alternate arena. Using guintptr doesn't make that problem any worse.
 type guintptr uintptr
 
-func (gp guintptr) ptr() *g   { return (*g)(unsafe.Pointer(gp)) }
+//go:nosplit
+func (gp guintptr) ptr() *g { return (*g)(unsafe.Pointer(gp)) }
+
+//go:nosplit
 func (gp *guintptr) set(g *g) { *gp = guintptr(unsafe.Pointer(g)) }
+
+//go:nosplit
 func (gp *guintptr) cas(old, new guintptr) bool {
-	return casuintptr((*uintptr)(unsafe.Pointer(gp)), uintptr(old), uintptr(new))
+	return atomic.Casuintptr((*uintptr)(unsafe.Pointer(gp)), uintptr(old), uintptr(new))
 }
 
 type puintptr uintptr
 
-func (pp puintptr) ptr() *p   { return (*p)(unsafe.Pointer(pp)) }
+//go:nosplit
+func (pp puintptr) ptr() *p { return (*p)(unsafe.Pointer(pp)) }
+
+//go:nosplit
 func (pp *puintptr) set(p *p) { *pp = puintptr(unsafe.Pointer(p)) }
 
 type muintptr uintptr
 
-func (mp muintptr) ptr() *m   { return (*m)(unsafe.Pointer(mp)) }
+//go:nosplit
+func (mp muintptr) ptr() *m { return (*m)(unsafe.Pointer(mp)) }
+
+//go:nosplit
 func (mp *muintptr) set(m *m) { *mp = muintptr(unsafe.Pointer(m)) }
 
 type gobuf struct {
@@ -149,7 +155,7 @@ type gobuf struct {
 	pc   uintptr
 	g    guintptr
 	ctxt unsafe.Pointer // this has to be a pointer so that gc scans it
-	ret  uintreg
+	ret  sys.Uintreg
 	lr   uintptr
 	bp   uintptr // for GOEXPERIMENT=framepointer
 }
@@ -227,8 +233,9 @@ type g struct {
 	sched          gobuf
 	syscallsp      uintptr        // if status==Gsyscall, syscallsp = sched.sp to use during gc
 	syscallpc      uintptr        // if status==Gsyscall, syscallpc = sched.pc to use during gc
-	stkbar         []stkbar       // stack barriers, from low to high
+	stkbar         []stkbar       // stack barriers, from low to high (see top of mstkbar.go)
 	stkbarPos      uintptr        // index of lowest stack barrier not hit
+	stktopsp       uintptr        // expected sp at top of stack, to check in traceback
 	param          unsafe.Pointer // passed parameter on wakeup
 	atomicstatus   uint32
 	stackLock      uint32 // sigprof/scang lock; TODO: fold in to atomicstatus
@@ -256,20 +263,17 @@ type g struct {
 	startpc        uintptr // pc of goroutine function
 	racectx        uintptr
 	waiting        *sudog // sudog structures this g is waiting on (that have a valid elem ptr)
-	readyg         *g     // scratch for readyExecute
 
 	// Per-G gcController state
-	gcalloc    uintptr // bytes allocated during this GC cycle
-	gcscanwork int64   // scan work done (or stolen) this GC cycle
-}
-
-type mts struct {
-	tv_sec  int64
-	tv_nsec int64
-}
 
-type mscratch struct {
-	v [6]uintptr
+	// gcAssistBytes is this G's GC assist credit in terms of
+	// bytes allocated. If this is positive, then the G has credit
+	// to allocate gcAssistBytes bytes without assisting. If this
+	// is negative, then the G must correct this by performing
+	// scan work. We track this in bytes to make it fast to update
+	// and check for debt in the malloc hot path. The assist ratio
+	// determines how this corresponds to scan work debt.
+	gcAssistBytes int64
 }
 
 type m struct {
@@ -280,8 +284,8 @@ type m struct {
 	// Fields not known to debuggers.
 	procid        uint64     // for debuggers, but offset not hard-coded
 	gsignal       *g         // signal-handling g
-	sigmask       [4]uintptr // storage for saved signal mask
-	tls           [4]uintptr // thread-local storage (for x86 extern register)
+	sigmask       sigset     // storage for saved signal mask
+	tls           [6]uintptr // thread-local storage (for x86 extern register)
 	mstartfn      func()
 	curg          *g       // current running goroutine
 	caughtsig     guintptr // goroutine running during fatal signal
@@ -299,6 +303,7 @@ type m struct {
 	spinning      bool // m is out of work and is actively looking for work
 	blocked       bool // m is blocked on a note
 	inwb          bool // m is executing a write barrier
+	newSigstack   bool // minit on C thread called sigaltstack
 	printlock     int8
 	fastrand      uint32
 	ncgocall      uint64 // number of cgo calls in total
@@ -315,9 +320,6 @@ type m struct {
 	fflag         uint32      // floating point compare flags
 	locked        uint32      // tracking for lockosthread
 	nextwaitm     uintptr     // next m waiting for lock
-	waitsema      uintptr     // semaphore for parking on locks
-	waitsemacount uint32
-	waitsemalock  uint32
 	gcstats       gcstats
 	needextram    bool
 	traceback     uint8
@@ -337,18 +339,7 @@ type m struct {
 	libcallg  guintptr
 	syscall   libcall // stores syscall parameters on windows
 	//#endif
-	//#ifdef GOOS_solaris
-	perrno *int32 // pointer to tls errno
-	// these are here because they are too large to be on the stack
-	// of low-level NOSPLIT functions.
-	//LibCall	libcall;
-	ts      mts
-	scratch mscratch
-	//#endif
-	//#ifdef GOOS_plan9
-	notesig *int8
-	errstr  *byte
-	//#endif
+	mOS
 }
 
 type p struct {
@@ -372,7 +363,7 @@ type p struct {
 	// Queue of runnable goroutines. Accessed without lock.
 	runqhead uint32
 	runqtail uint32
-	runq     [256]*g
+	runq     [256]guintptr
 	// runnext, if non-nil, is a runnable G that was ready'd by
 	// the current G and should be run next instead of what's in
 	// runq if there's time remaining in the running G's time
@@ -391,13 +382,13 @@ type p struct {
 	sudogcache []*sudog
 	sudogbuf   [128]*sudog
 
-	tracebuf *traceBuf
+	tracebuf traceBufPtr
 
 	palloc persistentAlloc // per-P to avoid mutex
 
 	// Per-P GC state
 	gcAssistTime     int64 // Nanoseconds in assistAlloc
-	gcBgMarkWorker   *g
+	gcBgMarkWorker   guintptr
 	gcMarkWorkerMode gcMarkWorkerMode
 
 	// gcw is this P's GC work buffer cache. The work buffer is
@@ -417,9 +408,11 @@ const (
 )
 
 type schedt struct {
-	lock mutex
+	// accessed atomically. keep at top to ensure alignment on 32-bit systems.
+	goidgen  uint64
+	lastpoll uint64
 
-	goidgen uint64
+	lock mutex
 
 	midle        muintptr // idle m's waiting for work
 	nmidle       int32    // number of idle m's waiting for work
@@ -427,9 +420,11 @@ type schedt struct {
 	mcount       int32    // number of m's that have been created
 	maxmcount    int32    // maximum number of m's allowed (or die)
 
+	ngsys uint32 // number of system goroutines; updated atomically
+
 	pidle      puintptr // idle p's
 	npidle     uint32
-	nmspinning uint32
+	nmspinning uint32 // See "Worker thread parking/unparking" comment in proc.go.
 
 	// Global runnable queue.
 	runqhead guintptr
@@ -454,7 +449,6 @@ type schedt struct {
 	stopnote   note
 	sysmonwait uint32
 	sysmonnote note
-	lastpoll   uint64
 
 	// safepointFn should be called on each P at the next GC
 	// safepoint if p.runSafePointFn is set.
@@ -492,7 +486,6 @@ const (
 	_SigPanic                // if the signal is from the kernel, panic
 	_SigDefault              // if the signal isn't explicitly requested, don't monitor it
 	_SigHandling             // our signal handler is registered
-	_SigIgnored              // the signal was ignored before we registered for it
 	_SigGoExit               // cause all runtime procs to exit (only used on Plan 9).
 	_SigSetStack             // add SA_ONSTACK to libc handler
 	_SigUnblock              // unblocked in minit
@@ -506,8 +499,8 @@ type _func struct {
 	entry   uintptr // start pc
 	nameoff int32   // function name
 
-	args  int32 // in/out args size
-	frame int32 // legacy frame size; use pcsp if possible
+	args int32 // in/out args size
+	_    int32 // previously legacy frame size; kept for layout compatibility
 
 	pcsp      int32
 	pcfile    int32
@@ -544,7 +537,7 @@ type forcegcstate struct {
  * known to compiler
  */
 const (
-	_Structrnd = regSize
+	_Structrnd = sys.RegSize
 )
 
 // startup_random_data holds random bytes initialized at startup.  These come from
@@ -564,7 +557,7 @@ func extendRandom(r []byte, n int) {
 			w = 16
 		}
 		h := memhash(unsafe.Pointer(&r[n-w]), uintptr(nanotime()), uintptr(w))
-		for i := 0; i < ptrSize && n < len(r); i++ {
+		for i := 0; i < sys.PtrSize && n < len(r); i++ {
 			r[n] = byte(h)
 			n++
 			h >>= 8
@@ -626,16 +619,12 @@ const (
 
 var (
 	emptystring string
-	allg        **g
 	allglen     uintptr
-	lastg       *g
 	allm        *m
 	allp        [_MaxGomaxprocs + 1]*p
 	gomaxprocs  int32
 	panicking   uint32
-	goos        *int8
 	ncpu        int32
-	signote     note
 	forcegc     forcegcstate
 	sched       schedt
 	newprocs    int32
@@ -645,6 +634,8 @@ var (
 	cpuid_ecx         uint32
 	cpuid_edx         uint32
 	lfenceBeforeRdtsc bool
+	support_avx       bool
+	support_avx2      bool
 
 	goarm uint8 // set by cmd/link on arm systems
 )
diff --git a/src/runtime/runtime_linux_test.go b/src/runtime/runtime_linux_test.go
index 5344ed2..58c797f 100644
--- a/src/runtime/runtime_linux_test.go
+++ b/src/runtime/runtime_linux_test.go
@@ -8,6 +8,7 @@ import (
 	. "runtime"
 	"syscall"
 	"testing"
+	"unsafe"
 )
 
 var pid, tid int
@@ -27,3 +28,15 @@ func TestLockOSThread(t *testing.T) {
 		t.Fatalf("pid=%d but tid=%d", pid, tid)
 	}
 }
+
+// Test that error values are negative. Use address 1 (a misaligned
+// pointer) to get -EINVAL.
+func TestMincoreErrorSign(t *testing.T) {
+	var dst byte
+	v := Mincore(unsafe.Pointer(uintptr(1)), 1, &dst)
+
+	const EINVAL = 0x16
+	if v != -EINVAL {
+		t.Errorf("mincore = %v, want %v", v, -EINVAL)
+	}
+}
diff --git a/src/runtime/runtime_mmap_test.go b/src/runtime/runtime_mmap_test.go
new file mode 100644
index 0000000..ff5e733
--- /dev/null
+++ b/src/runtime/runtime_mmap_test.go
@@ -0,0 +1,30 @@
+// 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.
+
+// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
+
+package runtime_test
+
+import (
+	"runtime"
+	"runtime/internal/sys"
+	"testing"
+)
+
+// Test that the error value returned by mmap is positive, as that is
+// what the code in mem_bsd.go, mem_darwin.go, and mem_linux.go expects.
+// See the uses of ENOMEM in sysMap in those files.
+func TestMmapErrorSign(t *testing.T) {
+	p := runtime.Mmap(nil, ^uintptr(0)&^(sys.PhysPageSize-1), 0, runtime.MAP_ANON|runtime.MAP_PRIVATE, -1, 0)
+
+	// The runtime.mmap function is nosplit, but t.Errorf is not.
+	// Reset the pointer so that we don't get an "invalid stack
+	// pointer" error from t.Errorf if we call it.
+	v := uintptr(p)
+	p = nil
+
+	if v != runtime.ENOMEM {
+		t.Errorf("mmap = %v, want %v", v, runtime.ENOMEM)
+	}
+}
diff --git a/src/runtime/runtime_test.go b/src/runtime/runtime_test.go
index 75fc9bc..a6150a7 100644
--- a/src/runtime/runtime_test.go
+++ b/src/runtime/runtime_test.go
@@ -12,6 +12,13 @@ import (
 	"unsafe"
 )
 
+func init() {
+	// We're testing the runtime, so make tracebacks show things
+	// in the runtime. This only raises the level, so it won't
+	// override GOTRACEBACK=crash from the user.
+	SetTracebackEnv("system")
+}
+
 var errf error
 
 func errfn() error {
@@ -301,3 +308,24 @@ func TestAppendSliceGrowth(t *testing.T) {
 		}
 	}
 }
+
+func TestGoroutineProfileTrivial(t *testing.T) {
+	// Calling GoroutineProfile twice in a row should find the same number of goroutines,
+	// but it's possible there are goroutines just about to exit, so we might end up
+	// with fewer in the second call. Try a few times; it should converge once those
+	// zombies are gone.
+	for i := 0; ; i++ {
+		n1, ok := GoroutineProfile(nil) // should fail, there's at least 1 goroutine
+		if n1 < 1 || ok {
+			t.Fatalf("GoroutineProfile(nil) = %d, %v, want >0, false", n1, ok)
+		}
+		n2, ok := GoroutineProfile(make([]StackRecord, n1))
+		if n2 == n1 && ok {
+			break
+		}
+		t.Logf("GoroutineProfile(%d) = %d, %v, want %d, true", n1, n2, ok, n1)
+		if i >= 10 {
+			t.Fatalf("GoroutineProfile not converging")
+		}
+	}
+}
diff --git a/src/runtime/select.go b/src/runtime/select.go
index b18b44c..b6c3fea 100644
--- a/src/runtime/select.go
+++ b/src/runtime/select.go
@@ -6,7 +6,10 @@ package runtime
 
 // This file contains the implementation of Go select statements.
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 const (
 	debugSelect = false
@@ -51,7 +54,7 @@ func selectsize(size uintptr) uintptr {
 		(size-1)*unsafe.Sizeof(hselect{}.scase[0]) +
 		size*unsafe.Sizeof(*hselect{}.lockorder) +
 		size*unsafe.Sizeof(*hselect{}.pollorder)
-	return round(selsize, _Int64Align)
+	return round(selsize, sys.Int64Align)
 }
 
 func newselect(sel *hselect, selsize int64, size int32) {
@@ -304,7 +307,7 @@ func selectgoImpl(sel *hselect) (uintptr, uint16) {
 		k      *scase
 		sglist *sudog
 		sgnext *sudog
-		futile byte
+		qp     unsafe.Pointer
 	)
 
 loop:
@@ -317,15 +320,12 @@ loop:
 
 		switch cas.kind {
 		case caseRecv:
-			if c.dataqsiz > 0 {
-				if c.qcount > 0 {
-					goto asyncrecv
-				}
-			} else {
-				sg = c.sendq.dequeue()
-				if sg != nil {
-					goto syncrecv
-				}
+			sg = c.sendq.dequeue()
+			if sg != nil {
+				goto recv
+			}
+			if c.qcount > 0 {
+				goto bufrecv
 			}
 			if c.closed != 0 {
 				goto rclose
@@ -338,15 +338,12 @@ loop:
 			if c.closed != 0 {
 				goto sclose
 			}
-			if c.dataqsiz > 0 {
-				if c.qcount < c.dataqsiz {
-					goto asyncsend
-				}
-			} else {
-				sg = c.recvq.dequeue()
-				if sg != nil {
-					goto syncsend
-				}
+			sg = c.recvq.dequeue()
+			if sg != nil {
+				goto send
+			}
+			if c.qcount < c.dataqsiz {
+				goto bufsend
 			}
 
 		case caseDefault:
@@ -363,6 +360,9 @@ loop:
 	// pass 2 - enqueue on all chans
 	gp = getg()
 	done = 0
+	if gp.waiting != nil {
+		throw("gp.waiting != nil")
+	}
 	for i := 0; i < int(sel.ncase); i++ {
 		cas = &scases[pollorder[i]]
 		c = cas.c
@@ -389,7 +389,7 @@ loop:
 
 	// wait for someone to wake us up
 	gp.param = nil
-	gopark(selparkcommit, unsafe.Pointer(sel), "select", traceEvGoBlockSelect|futile, 2)
+	gopark(selparkcommit, unsafe.Pointer(sel), "select", traceEvGoBlockSelect, 2)
 
 	// someone woke us up
 	sellock(sel)
@@ -432,16 +432,13 @@ loop:
 	}
 
 	if cas == nil {
-		futile = traceFutileWakeup
+		// This can happen if we were woken up by a close().
+		// TODO: figure that out explicitly so we don't need this loop.
 		goto loop
 	}
 
 	c = cas.c
 
-	if c.dataqsiz > 0 {
-		throw("selectgo: shouldn't happen")
-	}
-
 	if debugSelect {
 		print("wait-return: sel=", sel, " c=", c, " cas=", cas, " kind=", cas.kind, "\n")
 	}
@@ -459,11 +456,18 @@ loop:
 			raceReadObjectPC(c.elemtype, cas.elem, cas.pc, chansendpc)
 		}
 	}
+	if msanenabled {
+		if cas.kind == caseRecv && cas.elem != nil {
+			msanwrite(cas.elem, c.elemtype.size)
+		} else if cas.kind == caseSend {
+			msanread(cas.elem, c.elemtype.size)
+		}
+	}
 
 	selunlock(sel)
 	goto retc
 
-asyncrecv:
+bufrecv:
 	// can receive from buffer
 	if raceenabled {
 		if cas.elem != nil {
@@ -472,82 +476,53 @@ asyncrecv:
 		raceacquire(chanbuf(c, c.recvx))
 		racerelease(chanbuf(c, c.recvx))
 	}
+	if msanenabled && cas.elem != nil {
+		msanwrite(cas.elem, c.elemtype.size)
+	}
 	if cas.receivedp != nil {
 		*cas.receivedp = true
 	}
+	qp = chanbuf(c, c.recvx)
 	if cas.elem != nil {
-		typedmemmove(c.elemtype, cas.elem, chanbuf(c, c.recvx))
+		typedmemmove(c.elemtype, cas.elem, qp)
 	}
-	memclr(chanbuf(c, c.recvx), uintptr(c.elemsize))
+	memclr(qp, uintptr(c.elemsize))
 	c.recvx++
 	if c.recvx == c.dataqsiz {
 		c.recvx = 0
 	}
 	c.qcount--
-	sg = c.sendq.dequeue()
-	if sg != nil {
-		gp = sg.g
-		selunlock(sel)
-		if sg.releasetime != 0 {
-			sg.releasetime = cputicks()
-		}
-		goready(gp, 3)
-	} else {
-		selunlock(sel)
-	}
+	selunlock(sel)
 	goto retc
 
-asyncsend:
+bufsend:
 	// can send to buffer
 	if raceenabled {
 		raceacquire(chanbuf(c, c.sendx))
 		racerelease(chanbuf(c, c.sendx))
 		raceReadObjectPC(c.elemtype, cas.elem, cas.pc, chansendpc)
 	}
+	if msanenabled {
+		msanread(cas.elem, c.elemtype.size)
+	}
 	typedmemmove(c.elemtype, chanbuf(c, c.sendx), cas.elem)
 	c.sendx++
 	if c.sendx == c.dataqsiz {
 		c.sendx = 0
 	}
 	c.qcount++
-	sg = c.recvq.dequeue()
-	if sg != nil {
-		gp = sg.g
-		selunlock(sel)
-		if sg.releasetime != 0 {
-			sg.releasetime = cputicks()
-		}
-		goready(gp, 3)
-	} else {
-		selunlock(sel)
-	}
+	selunlock(sel)
 	goto retc
 
-syncrecv:
+recv:
 	// can receive from sleeping sender (sg)
-	if raceenabled {
-		if cas.elem != nil {
-			raceWriteObjectPC(c.elemtype, cas.elem, cas.pc, chanrecvpc)
-		}
-		racesync(c, sg)
-	}
-	selunlock(sel)
+	recv(c, sg, cas.elem, func() { selunlock(sel) })
 	if debugSelect {
 		print("syncrecv: sel=", sel, " c=", c, "\n")
 	}
 	if cas.receivedp != nil {
 		*cas.receivedp = true
 	}
-	if cas.elem != nil {
-		typedmemmove(c.elemtype, cas.elem, sg.elem)
-	}
-	sg.elem = nil
-	gp = sg.g
-	gp.param = unsafe.Pointer(sg)
-	if sg.releasetime != 0 {
-		sg.releasetime = cputicks()
-	}
-	goready(gp, 3)
 	goto retc
 
 rclose:
@@ -564,26 +539,19 @@ rclose:
 	}
 	goto retc
 
-syncsend:
-	// can send to sleeping receiver (sg)
+send:
+	// can send to a sleeping receiver (sg)
 	if raceenabled {
 		raceReadObjectPC(c.elemtype, cas.elem, cas.pc, chansendpc)
-		racesync(c, sg)
 	}
-	selunlock(sel)
+	if msanenabled {
+		msanread(cas.elem, c.elemtype.size)
+	}
+	send(c, sg, cas.elem, func() { selunlock(sel) })
 	if debugSelect {
 		print("syncsend: sel=", sel, " c=", c, "\n")
 	}
-	if sg.elem != nil {
-		syncsend(c, sg, cas.elem)
-	}
-	sg.elem = nil
-	gp = sg.g
-	gp.param = unsafe.Pointer(sg)
-	if sg.releasetime != 0 {
-		sg.releasetime = cputicks()
-	}
-	goready(gp, 3)
+	goto retc
 
 retc:
 	if cas.releasetime > 0 {
diff --git a/src/runtime/sema.go b/src/runtime/sema.go
index 8ae51b4..b54621b 100644
--- a/src/runtime/sema.go
+++ b/src/runtime/sema.go
@@ -19,7 +19,11 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 // Asynchronous semaphore for sync.Mutex.
 
@@ -35,7 +39,7 @@ const semTabSize = 251
 
 var semtable [semTabSize]struct {
 	root semaRoot
-	pad  [_CacheLineSize - unsafe.Sizeof(semaRoot{})]byte
+	pad  [sys.CacheLineSize - unsafe.Sizeof(semaRoot{})]byte
 }
 
 //go:linkname sync_runtime_Semacquire sync.runtime_Semacquire
@@ -87,10 +91,10 @@ func semacquire(addr *uint32, profile bool) {
 	for {
 		lock(&root.lock)
 		// Add ourselves to nwait to disable "easy case" in semrelease.
-		xadd(&root.nwait, 1)
+		atomic.Xadd(&root.nwait, 1)
 		// Check cansemacquire to avoid missed wakeup.
 		if cansemacquire(addr) {
-			xadd(&root.nwait, -1)
+			atomic.Xadd(&root.nwait, -1)
 			unlock(&root.lock)
 			break
 		}
@@ -110,18 +114,18 @@ func semacquire(addr *uint32, profile bool) {
 
 func semrelease(addr *uint32) {
 	root := semroot(addr)
-	xadd(addr, 1)
+	atomic.Xadd(addr, 1)
 
 	// Easy case: no waiters?
 	// This check must happen after the xadd, to avoid a missed wakeup
 	// (see loop in semacquire).
-	if atomicload(&root.nwait) == 0 {
+	if atomic.Load(&root.nwait) == 0 {
 		return
 	}
 
 	// Harder case: search for a waiter and wake it.
 	lock(&root.lock)
-	if atomicload(&root.nwait) == 0 {
+	if atomic.Load(&root.nwait) == 0 {
 		// The count is already consumed by another goroutine,
 		// so no need to wake up another goroutine.
 		unlock(&root.lock)
@@ -130,7 +134,7 @@ func semrelease(addr *uint32) {
 	s := root.head
 	for ; s != nil; s = s.next {
 		if s.elem == unsafe.Pointer(addr) {
-			xadd(&root.nwait, -1)
+			atomic.Xadd(&root.nwait, -1)
 			root.dequeue(s)
 			break
 		}
@@ -150,11 +154,11 @@ func semroot(addr *uint32) *semaRoot {
 
 func cansemacquire(addr *uint32) bool {
 	for {
-		v := atomicload(addr)
+		v := atomic.Load(addr)
 		if v == 0 {
 			return false
 		}
-		if cas(addr, v, v-1) {
+		if atomic.Cas(addr, v, v-1) {
 			return true
 		}
 	}
diff --git a/src/runtime/signal1_unix.go b/src/runtime/signal1_unix.go
index 56d9755..abb9639 100644
--- a/src/runtime/signal1_unix.go
+++ b/src/runtime/signal1_unix.go
@@ -6,6 +6,8 @@
 
 package runtime
 
+import "runtime/internal/sys"
+
 const (
 	_SIG_DFL uintptr = 0
 	_SIG_IGN uintptr = 1
@@ -16,7 +18,7 @@ const (
 // handle a particular signal (e.g., signal occurred on a non-Go thread).
 // See sigfwdgo() for more information on when the signals are forwarded.
 //
-// Signal forwarding is currently available only on Linux.
+// Signal forwarding is currently available only on Darwin and Linux.
 var fwdSig [_NSIG]uintptr
 
 // sigmask represents a general signal mask compatible with the GOOS
@@ -32,34 +34,46 @@ var (
 	maskUpdatedChan chan struct{}
 )
 
-func initsig() {
+func init() {
 	// _NSIG is the number of signals on this operating system.
 	// sigtable should describe what to do for all the possible signals.
 	if len(sigtable) != _NSIG {
 		print("runtime: len(sigtable)=", len(sigtable), " _NSIG=", _NSIG, "\n")
-		throw("initsig")
+		throw("bad sigtable len")
+	}
+}
+
+var signalsOK bool
+
+// Initialize signals.
+// Called by libpreinit so runtime may not be initialized.
+//go:nosplit
+//go:nowritebarrierrec
+func initsig(preinit bool) {
+	if !preinit {
+		// It's now OK for signal handlers to run.
+		signalsOK = true
+	}
+
+	// For c-archive/c-shared this is called by libpreinit with
+	// preinit == true.
+	if (isarchive || islibrary) && !preinit {
+		return
 	}
 
-	// First call: basic setup.
 	for i := int32(0); i < _NSIG; i++ {
 		t := &sigtable[i]
 		if t.flags == 0 || t.flags&_SigDefault != 0 {
 			continue
 		}
 		fwdSig[i] = getsig(i)
-		// For some signals, we respect an inherited SIG_IGN handler
-		// rather than insist on installing our own default handler.
-		// Even these signals can be fetched using the os/signal package.
-		switch i {
-		case _SIGHUP, _SIGINT:
-			if getsig(i) == _SIG_IGN {
-				t.flags = _SigNotify | _SigIgnored
-				continue
-			}
-		}
 
-		if t.flags&_SigSetStack != 0 {
-			setsigstack(i)
+		if !sigInstallGoHandler(i) {
+			// Even if we are not installing a signal handler,
+			// set SA_ONSTACK if necessary.
+			if fwdSig[i] != _SIG_DFL && fwdSig[i] != _SIG_IGN {
+				setsigstack(i)
+			}
 			continue
 		}
 
@@ -68,6 +82,33 @@ func initsig() {
 	}
 }
 
+//go:nosplit
+//go:nowritebarrierrec
+func sigInstallGoHandler(sig int32) bool {
+	// For some signals, we respect an inherited SIG_IGN handler
+	// rather than insist on installing our own default handler.
+	// Even these signals can be fetched using the os/signal package.
+	switch sig {
+	case _SIGHUP, _SIGINT:
+		if fwdSig[sig] == _SIG_IGN {
+			return false
+		}
+	}
+
+	t := &sigtable[sig]
+	if t.flags&_SigSetStack != 0 {
+		return false
+	}
+
+	// When built using c-archive or c-shared, only install signal
+	// handlers for synchronous signals.
+	if (isarchive || islibrary) && t.flags&_SigPanic == 0 {
+		return false
+	}
+
+	return true
+}
+
 func sigenable(sig uint32) {
 	if sig >= uint32(len(sigtable)) {
 		return
@@ -80,9 +121,7 @@ func sigenable(sig uint32) {
 		<-maskUpdatedChan
 		if t.flags&_SigHandling == 0 {
 			t.flags |= _SigHandling
-			if getsig(int32(sig)) == _SIG_IGN {
-				t.flags |= _SigIgnored
-			}
+			fwdSig[sig] = getsig(int32(sig))
 			setsig(int32(sig), funcPC(sighandler), true)
 		}
 	}
@@ -98,13 +137,13 @@ func sigdisable(sig uint32) {
 		ensureSigM()
 		disableSigChan <- sig
 		<-maskUpdatedChan
-		if t.flags&_SigHandling != 0 {
+
+		// If initsig does not install a signal handler for a
+		// signal, then to go back to the state before Notify
+		// we should remove the one we installed.
+		if !sigInstallGoHandler(int32(sig)) {
 			t.flags &^= _SigHandling
-			if t.flags&_SigIgnored != 0 {
-				setsig(int32(sig), _SIG_IGN, true)
-			} else {
-				setsig(int32(sig), _SIG_DFL, true)
-			}
+			setsig(int32(sig), fwdSig[sig], true)
 		}
 	}
 }
@@ -136,8 +175,23 @@ func resetcpuprofiler(hz int32) {
 }
 
 func sigpipe() {
-	setsig(_SIGPIPE, _SIG_DFL, false)
-	raise(_SIGPIPE)
+	if sigsend(_SIGPIPE) {
+		return
+	}
+	dieFromSignal(_SIGPIPE)
+}
+
+// dieFromSignal kills the program with a signal.
+// This provides the expected exit status for the shell.
+// This is only called with fatal signals expected to kill the process.
+//go:nosplit
+//go:nowritebarrierrec
+func dieFromSignal(sig int32) {
+	setsig(sig, _SIG_DFL, false)
+	updatesigmask(sigmask{})
+	raise(sig)
+	// That should have killed us; call exit just in case.
+	exit(2)
 }
 
 // raisebadsignal is called when a signal is received on a non-Go
@@ -185,17 +239,15 @@ func crash() {
 		// this means the OS X core file will be >128 GB and even on a zippy
 		// workstation can take OS X well over an hour to write (uninterruptible).
 		// Save users from making that mistake.
-		if ptrSize == 8 {
+		if sys.PtrSize == 8 {
 			return
 		}
 	}
 
-	updatesigmask(sigmask{})
-	setsig(_SIGABRT, _SIG_DFL, false)
-	raise(_SIGABRT)
+	dieFromSignal(_SIGABRT)
 }
 
-// createSigM starts one global, sleeping thread to make sure at least one thread
+// ensureSigM starts one global, sleeping thread to make sure at least one thread
 // is available to catch signals enabled for os/signal.
 func ensureSigM() {
 	if maskUpdatedChan != nil {
@@ -226,11 +278,11 @@ func ensureSigM() {
 		for {
 			select {
 			case sig := <-enableSigChan:
-				if b := sig - 1; b >= 0 {
+				if b := sig - 1; sig > 0 {
 					sigBlocked[b/32] &^= (1 << (b & 31))
 				}
 			case sig := <-disableSigChan:
-				if b := sig - 1; b >= 0 {
+				if b := sig - 1; sig > 0 {
 					sigBlocked[b/32] |= (1 << (b & 31))
 				}
 			}
@@ -239,3 +291,19 @@ func ensureSigM() {
 		}
 	}()
 }
+
+// This is called when we receive a signal when there is no signal stack.
+// This can only happen if non-Go code calls sigaltstack to disable the
+// signal stack.  This is called via cgocallback to establish a stack.
+func noSignalStack(sig uint32) {
+	println("signal", sig, "received on thread with no signal stack")
+	throw("non-Go code disabled sigaltstack")
+}
+
+// This is called if we receive a signal when there is a signal stack
+// but we are not on it.  This can only happen if non-Go code called
+// sigaction without setting the SS_ONSTACK flag.
+func sigNotOnStack(sig uint32) {
+	println("signal", sig, "received but handler not on signal stack")
+	throw("non-Go code set up signal handler without SA_ONSTACK flag")
+}
diff --git a/src/runtime/signal2_unix.go b/src/runtime/signal2_unix.go
new file mode 100644
index 0000000..3fe625f
--- /dev/null
+++ b/src/runtime/signal2_unix.go
@@ -0,0 +1,69 @@
+// Copyright 2012 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.
+
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package runtime
+
+import "unsafe"
+
+//go:noescape
+func sigfwd(fn uintptr, sig uint32, info *siginfo, ctx unsafe.Pointer)
+
+// Determines if the signal should be handled by Go and if not, forwards the
+// signal to the handler that was installed before Go's.  Returns whether the
+// signal was forwarded.
+// This is called by the signal handler, and the world may be stopped.
+//go:nosplit
+//go:nowritebarrierrec
+func sigfwdgo(sig uint32, info *siginfo, ctx unsafe.Pointer) bool {
+	if sig >= uint32(len(sigtable)) {
+		return false
+	}
+	fwdFn := fwdSig[sig]
+
+	if !signalsOK {
+		// The only way we can get here is if we are in a
+		// library or archive, we installed a signal handler
+		// at program startup, but the Go runtime has not yet
+		// been initialized.
+		if fwdFn == _SIG_DFL {
+			dieFromSignal(int32(sig))
+		} else {
+			sigfwd(fwdFn, sig, info, ctx)
+		}
+		return true
+	}
+
+	flags := sigtable[sig].flags
+
+	// If there is no handler to forward to, no need to forward.
+	if fwdFn == _SIG_DFL {
+		return false
+	}
+
+	// If we aren't handling the signal, forward it.
+	if flags&_SigHandling == 0 {
+		sigfwd(fwdFn, sig, info, ctx)
+		return true
+	}
+
+	// Only forward synchronous signals.
+	c := &sigctxt{info, ctx}
+	if c.sigcode() == _SI_USER || flags&_SigPanic == 0 {
+		return false
+	}
+	// Determine if the signal occurred inside Go code.  We test that:
+	//   (1) we were in a goroutine (i.e., m.curg != nil), and
+	//   (2) we weren't in CGO (i.e., m.curg.syscallsp == 0).
+	g := getg()
+	if g != nil && g.m != nil && g.m.curg != nil && g.m.curg.syscallsp == 0 {
+		return false
+	}
+	// Signal not handled by Go, forward it.
+	if fwdFn != _SIG_IGN {
+		sigfwd(fwdFn, sig, info, ctx)
+	}
+	return true
+}
diff --git a/src/runtime/signal_386.go b/src/runtime/signal_386.go
index ca18942..0374f4a 100644
--- a/src/runtime/signal_386.go
+++ b/src/runtime/signal_386.go
@@ -6,7 +6,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 func dumpregs(c *sigctxt) {
 	print("eax    ", hex(c.eax()), "\n")
@@ -27,7 +30,8 @@ func dumpregs(c *sigctxt) {
 var crashing int32
 
 // May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
+//
+//go:nowritebarrierrec
 func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
 	_g_ := getg()
 	c := &sigctxt{info, ctxt}
@@ -85,11 +89,11 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
 		// (Otherwise the trace will end at runtime.sigpanic and we
 		// won't get to see who faulted.)
 		if pc != 0 {
-			if regSize > ptrSize {
-				sp -= ptrSize
+			if sys.RegSize > sys.PtrSize {
+				sp -= sys.PtrSize
 				*(*uintptr)(unsafe.Pointer(sp)) = 0
 			}
-			sp -= ptrSize
+			sp -= sys.PtrSize
 			*(*uintptr)(unsafe.Pointer(sp)) = pc
 			c.set_esp(uint32(sp))
 		}
@@ -103,8 +107,12 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
 		}
 	}
 
+	if c.sigcode() == _SI_USER && signal_ignored(sig) {
+		return
+	}
+
 	if flags&_SigKill != 0 {
-		exit(2)
+		dieFromSignal(int32(sig))
 	}
 
 	if flags&_SigThrow == 0 {
@@ -131,8 +139,8 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
 	}
 	print("\n")
 
-	var docrash bool
-	if gotraceback(&docrash) > 0 {
+	level, _, docrash := gotraceback()
+	if level > 0 {
 		goroutineheader(gp)
 
 		// On Linux/386, all system calls go through the vdso kernel_vsyscall routine.
diff --git a/src/runtime/signal_amd64x.go b/src/runtime/signal_amd64x.go
index 3e14480..0f6700d 100644
--- a/src/runtime/signal_amd64x.go
+++ b/src/runtime/signal_amd64x.go
@@ -8,6 +8,7 @@
 package runtime
 
 import (
+	"runtime/internal/sys"
 	"unsafe"
 )
 
@@ -38,7 +39,8 @@ func dumpregs(c *sigctxt) {
 var crashing int32
 
 // May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
+//
+//go:nowritebarrierrec
 func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
 	_g_ := getg()
 	c := &sigctxt{info, ctxt}
@@ -119,11 +121,11 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
 		// (Otherwise the trace will end at runtime.sigpanic and we
 		// won't get to see who faulted.)
 		if pc != 0 {
-			if regSize > ptrSize {
-				sp -= ptrSize
+			if sys.RegSize > sys.PtrSize {
+				sp -= sys.PtrSize
 				*(*uintptr)(unsafe.Pointer(sp)) = 0
 			}
-			sp -= ptrSize
+			sp -= sys.PtrSize
 			*(*uintptr)(unsafe.Pointer(sp)) = pc
 			c.set_rsp(uint64(sp))
 		}
@@ -137,8 +139,12 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
 		}
 	}
 
+	if c.sigcode() == _SI_USER && signal_ignored(sig) {
+		return
+	}
+
 	if flags&_SigKill != 0 {
-		exit(2)
+		dieFromSignal(int32(sig))
 	}
 
 	if flags&_SigThrow == 0 {
@@ -165,8 +171,8 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
 	}
 	print("\n")
 
-	var docrash bool
-	if gotraceback(&docrash) > 0 {
+	level, _, docrash := gotraceback()
+	if level > 0 {
 		goroutineheader(gp)
 		tracebacktrap(uintptr(c.rip()), uintptr(c.rsp()), 0, gp)
 		if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning {
diff --git a/src/runtime/signal_arm.go b/src/runtime/signal_arm.go
index 1b8a2f5..3ea3938 100644
--- a/src/runtime/signal_arm.go
+++ b/src/runtime/signal_arm.go
@@ -35,7 +35,8 @@ func dumpregs(c *sigctxt) {
 var crashing int32
 
 // May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
+//
+//go:nowritebarrierrec
 func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
 	_g_ := getg()
 	c := &sigctxt{info, ctxt}
@@ -98,8 +99,12 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
 		}
 	}
 
+	if c.sigcode() == _SI_USER && signal_ignored(sig) {
+		return
+	}
+
 	if flags&_SigKill != 0 {
-		exit(2)
+		dieFromSignal(int32(sig))
 	}
 
 	if flags&_SigThrow == 0 {
@@ -126,8 +131,8 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
 	}
 	print("\n")
 
-	var docrash bool
-	if gotraceback(&docrash) > 0 {
+	level, _, docrash := gotraceback()
+	if level > 0 {
 		goroutineheader(gp)
 		tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.lr()), gp)
 		if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning {
diff --git a/src/runtime/signal_arm64.go b/src/runtime/signal_arm64.go
index 4a7c8b9..e647c76 100644
--- a/src/runtime/signal_arm64.go
+++ b/src/runtime/signal_arm64.go
@@ -6,7 +6,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 func dumpregs(c *sigctxt) {
 	print("r0      ", hex(c.r0()), "\n")
@@ -48,7 +51,8 @@ func dumpregs(c *sigctxt) {
 var crashing int32
 
 // May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
+//
+//go:nowritebarrierrec
 func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
 	_g_ := getg()
 	c := &sigctxt{info, ctxt}
@@ -78,7 +82,7 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
 		// functions are correctly handled. This smashes
 		// the stack frame but we're not going back there
 		// anyway.
-		sp := c.sp() - spAlign // needs only sizeof uint64, but must align the stack
+		sp := c.sp() - sys.SpAlign // needs only sizeof uint64, but must align the stack
 		c.set_sp(sp)
 		*(*uint64)(unsafe.Pointer(uintptr(sp))) = c.lr()
 
@@ -111,8 +115,12 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
 		}
 	}
 
+	if c.sigcode() == _SI_USER && signal_ignored(sig) {
+		return
+	}
+
 	if flags&_SigKill != 0 {
-		exit(2)
+		dieFromSignal(int32(sig))
 	}
 
 	if flags&_SigThrow == 0 {
@@ -139,8 +147,8 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
 	}
 	print("\n")
 
-	var docrash bool
-	if gotraceback(&docrash) > 0 {
+	level, _, docrash := gotraceback()
+	if level > 0 {
 		goroutineheader(gp)
 		tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.lr()), gp)
 		if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning {
diff --git a/src/runtime/signal_darwin.go b/src/runtime/signal_darwin.go
index 6cd1865..8d43724 100644
--- a/src/runtime/signal_darwin.go
+++ b/src/runtime/signal_darwin.go
@@ -31,7 +31,7 @@ var sigtable = [...]sigTabT{
 	/* 16 */ {_SigNotify, "SIGURG: urgent condition on socket"},
 	/* 17 */ {0, "SIGSTOP: stop"},
 	/* 18 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
-	/* 19 */ {0, "SIGCONT: continue after stop"},
+	/* 19 */ {_SigNotify + _SigDefault, "SIGCONT: continue after stop"},
 	/* 20 */ {_SigNotify + _SigUnblock, "SIGCHLD: child status has changed"},
 	/* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
 	/* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
@@ -47,12 +47,10 @@ var sigtable = [...]sigTabT{
 }
 
 //go:noescape
-func sigfwd(fn uintptr, sig uint32, info *siginfo, ctx unsafe.Pointer)
-
-//go:noescape
 func sigreturn(ctx unsafe.Pointer, infostyle uint32)
 
 //go:nosplit
+//go:nowritebarrierrec
 func sigtrampgo(fn uintptr, infostyle, sig uint32, info *siginfo, ctx unsafe.Pointer) {
 	if sigfwdgo(sig, info, ctx) {
 		sigreturn(ctx, infostyle)
@@ -64,7 +62,32 @@ func sigtrampgo(fn uintptr, infostyle, sig uint32, info *siginfo, ctx unsafe.Poi
 		sigreturn(ctx, infostyle)
 		return
 	}
+
+	// If some non-Go code called sigaltstack, adjust.
+	sp := uintptr(unsafe.Pointer(&sig))
+	if sp < g.m.gsignal.stack.lo || sp >= g.m.gsignal.stack.hi {
+		var st stackt
+		sigaltstack(nil, &st)
+		if st.ss_flags&_SS_DISABLE != 0 {
+			setg(nil)
+			cgocallback(unsafe.Pointer(funcPC(noSignalStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig))
+		}
+		stsp := uintptr(unsafe.Pointer(st.ss_sp))
+		if sp < stsp || sp >= stsp+st.ss_size {
+			setg(nil)
+			cgocallback(unsafe.Pointer(funcPC(sigNotOnStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig))
+		}
+		g.m.gsignal.stack.lo = stsp
+		g.m.gsignal.stack.hi = stsp + st.ss_size
+		g.m.gsignal.stackguard0 = stsp + _StackGuard
+		g.m.gsignal.stackguard1 = stsp + _StackGuard
+		g.m.gsignal.stackAlloc = st.ss_size
+		g.m.gsignal.stktopsp = getcallersp(unsafe.Pointer(&sig))
+	}
+
 	setg(g.m.gsignal)
+	c := &sigctxt{info, ctx}
+	c.fixsigcode(sig)
 	sighandler(sig, info, ctx, g)
 	setg(g)
 	sigreturn(ctx, infostyle)
diff --git a/src/runtime/signal_darwin_386.go b/src/runtime/signal_darwin_386.go
index 302b3aa..7f7c22a 100644
--- a/src/runtime/signal_darwin_386.go
+++ b/src/runtime/signal_darwin_386.go
@@ -32,3 +32,25 @@ func (c *sigctxt) set_eip(x uint32)     { c.regs().eip = x }
 func (c *sigctxt) set_esp(x uint32)     { c.regs().esp = x }
 func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
 func (c *sigctxt) set_sigaddr(x uint32) { c.info.si_addr = x }
+
+func (c *sigctxt) fixsigcode(sig uint32) {
+	switch sig {
+	case _SIGTRAP:
+		// OS X sets c.sigcode() == TRAP_BRKPT unconditionally for all SIGTRAPs,
+		// leaving no way to distinguish a breakpoint-induced SIGTRAP
+		// from an asynchronous signal SIGTRAP.
+		// They all look breakpoint-induced by default.
+		// Try looking at the code to see if it's a breakpoint.
+		// The assumption is that we're very unlikely to get an
+		// asynchronous SIGTRAP at just the moment that the
+		// PC started to point at unmapped memory.
+		pc := uintptr(c.eip())
+		// OS X will leave the pc just after the INT 3 instruction.
+		// INT 3 is usually 1 byte, but there is a 2-byte form.
+		code := (*[2]byte)(unsafe.Pointer(pc - 2))
+		if code[1] != 0xCC && (code[0] != 0xCD || code[1] != 3) {
+			// SIGTRAP on something other than INT 3.
+			c.set_sigcode(_SI_USER)
+		}
+	}
+}
diff --git a/src/runtime/signal_darwin_amd64.go b/src/runtime/signal_darwin_amd64.go
index dbf0448..c9ac293 100644
--- a/src/runtime/signal_darwin_amd64.go
+++ b/src/runtime/signal_darwin_amd64.go
@@ -40,3 +40,25 @@ func (c *sigctxt) set_rip(x uint64)     { c.regs().rip = x }
 func (c *sigctxt) set_rsp(x uint64)     { c.regs().rsp = x }
 func (c *sigctxt) set_sigcode(x uint64) { c.info.si_code = int32(x) }
 func (c *sigctxt) set_sigaddr(x uint64) { c.info.si_addr = x }
+
+func (c *sigctxt) fixsigcode(sig uint32) {
+	switch sig {
+	case _SIGTRAP:
+		// OS X sets c.sigcode() == TRAP_BRKPT unconditionally for all SIGTRAPs,
+		// leaving no way to distinguish a breakpoint-induced SIGTRAP
+		// from an asynchronous signal SIGTRAP.
+		// They all look breakpoint-induced by default.
+		// Try looking at the code to see if it's a breakpoint.
+		// The assumption is that we're very unlikely to get an
+		// asynchronous SIGTRAP at just the moment that the
+		// PC started to point at unmapped memory.
+		pc := uintptr(c.rip())
+		// OS X will leave the pc just after the INT 3 instruction.
+		// INT 3 is usually 1 byte, but there is a 2-byte form.
+		code := (*[2]byte)(unsafe.Pointer(pc - 2))
+		if code[1] != 0xCC && (code[0] != 0xCD || code[1] != 3) {
+			// SIGTRAP on something other than INT 3.
+			c.set_sigcode(_SI_USER)
+		}
+	}
+}
diff --git a/src/runtime/signal_darwin_arm.go b/src/runtime/signal_darwin_arm.go
index 0f10971..24c5f5a 100644
--- a/src/runtime/signal_darwin_arm.go
+++ b/src/runtime/signal_darwin_arm.go
@@ -42,3 +42,24 @@ func (c *sigctxt) set_r10(x uint32) { c.regs().r[10] = x }
 
 func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
 func (c *sigctxt) set_sigaddr(x uint32) { c.info.si_addr = x }
+
+func (c *sigctxt) fixsigcode(sig uint32) {
+	switch sig {
+	case _SIGTRAP:
+		// OS X sets c.sigcode() == TRAP_BRKPT unconditionally for all SIGTRAPs,
+		// leaving no way to distinguish a breakpoint-induced SIGTRAP
+		// from an asynchronous signal SIGTRAP.
+		// They all look breakpoint-induced by default.
+		// Try looking at the code to see if it's a breakpoint.
+		// The assumption is that we're very unlikely to get an
+		// asynchronous SIGTRAP at just the moment that the
+		// PC started to point at unmapped memory.
+		pc := uintptr(c.pc())
+		// OS X will leave the pc just after the instruction.
+		code := (*uint32)(unsafe.Pointer(pc - 4))
+		if *code != 0xe7f001f0 {
+			// SIGTRAP on something other than breakpoint.
+			c.set_sigcode(_SI_USER)
+		}
+	}
+}
diff --git a/src/runtime/signal_darwin_arm64.go b/src/runtime/signal_darwin_arm64.go
index 2df4229..82f4a82 100644
--- a/src/runtime/signal_darwin_arm64.go
+++ b/src/runtime/signal_darwin_arm64.go
@@ -55,6 +55,28 @@ func (c *sigctxt) set_sp(x uint64)  { c.regs().sp = x }
 func (c *sigctxt) set_lr(x uint64)  { c.regs().lr = x }
 func (c *sigctxt) set_r28(x uint64) { c.regs().x[28] = x }
 
+func (c *sigctxt) set_sigcode(x uint64) { c.info.si_code = int32(x) }
 func (c *sigctxt) set_sigaddr(x uint64) {
 	c.info.si_addr = (*byte)(unsafe.Pointer(uintptr(x)))
 }
+
+func (c *sigctxt) fixsigcode(sig uint32) {
+	switch sig {
+	case _SIGTRAP:
+		// OS X sets c.sigcode() == TRAP_BRKPT unconditionally for all SIGTRAPs,
+		// leaving no way to distinguish a breakpoint-induced SIGTRAP
+		// from an asynchronous signal SIGTRAP.
+		// They all look breakpoint-induced by default.
+		// Try looking at the code to see if it's a breakpoint.
+		// The assumption is that we're very unlikely to get an
+		// asynchronous SIGTRAP at just the moment that the
+		// PC started to point at unmapped memory.
+		pc := uintptr(c.pc())
+		// OS X will leave the pc just after the instruction.
+		code := (*uint32)(unsafe.Pointer(pc - 4))
+		if *code != 0xd4200000 {
+			// SIGTRAP on something other than breakpoint.
+			c.set_sigcode(_SI_USER)
+		}
+	}
+}
diff --git a/src/runtime/signal_dragonfly.go b/src/runtime/signal_dragonfly.go
index d37e11a..f507a07 100644
--- a/src/runtime/signal_dragonfly.go
+++ b/src/runtime/signal_dragonfly.go
@@ -29,7 +29,7 @@ var sigtable = [...]sigTabT{
 	/* 16 */ {_SigNotify, "SIGURG: urgent condition on socket"},
 	/* 17 */ {0, "SIGSTOP: stop"},
 	/* 18 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
-	/* 19 */ {0, "SIGCONT: continue after stop"},
+	/* 19 */ {_SigNotify + _SigDefault, "SIGCONT: continue after stop"},
 	/* 20 */ {_SigNotify, "SIGCHLD: child status has changed"},
 	/* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
 	/* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
diff --git a/src/runtime/signal_freebsd.go b/src/runtime/signal_freebsd.go
index 1dbdb1b..f3411aa 100644
--- a/src/runtime/signal_freebsd.go
+++ b/src/runtime/signal_freebsd.go
@@ -4,6 +4,8 @@
 
 package runtime
 
+import "unsafe"
+
 type sigTabT struct {
 	flags int32
 	name  string
@@ -29,7 +31,7 @@ var sigtable = [...]sigTabT{
 	/* 16 */ {_SigNotify, "SIGURG: urgent condition on socket"},
 	/* 17 */ {0, "SIGSTOP: stop"},
 	/* 18 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
-	/* 19 */ {0, "SIGCONT: continue after stop"},
+	/* 19 */ {_SigNotify + _SigDefault, "SIGCONT: continue after stop"},
 	/* 20 */ {_SigNotify, "SIGCHLD: child status has changed"},
 	/* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
 	/* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
@@ -44,3 +46,42 @@ var sigtable = [...]sigTabT{
 	/* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
 	/* 32 */ {_SigNotify, "SIGTHR: reserved"},
 }
+
+//go:nosplit
+//go:nowritebarrierrec
+func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
+	if sigfwdgo(sig, info, ctx) {
+		return
+	}
+	g := getg()
+	if g == nil {
+		badsignal(uintptr(sig))
+		return
+	}
+
+	// If some non-Go code called sigaltstack, adjust.
+	sp := uintptr(unsafe.Pointer(&sig))
+	if sp < g.m.gsignal.stack.lo || sp >= g.m.gsignal.stack.hi {
+		var st stackt
+		sigaltstack(nil, &st)
+		if st.ss_flags&_SS_DISABLE != 0 {
+			setg(nil)
+			cgocallback(unsafe.Pointer(funcPC(noSignalStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig))
+		}
+		stsp := uintptr(unsafe.Pointer(st.ss_sp))
+		if sp < stsp || sp >= stsp+st.ss_size {
+			setg(nil)
+			cgocallback(unsafe.Pointer(funcPC(sigNotOnStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig))
+		}
+		g.m.gsignal.stack.lo = stsp
+		g.m.gsignal.stack.hi = stsp + st.ss_size
+		g.m.gsignal.stackguard0 = stsp + _StackGuard
+		g.m.gsignal.stackguard1 = stsp + _StackGuard
+		g.m.gsignal.stackAlloc = st.ss_size
+		g.m.gsignal.stktopsp = getcallersp(unsafe.Pointer(&sig))
+	}
+
+	setg(g.m.gsignal)
+	sighandler(sig, info, ctx, g)
+	setg(g)
+}
diff --git a/src/runtime/signal_linux.go b/src/runtime/signal_linux.go
deleted file mode 100644
index 2cc76b2..0000000
--- a/src/runtime/signal_linux.go
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2009 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 runtime
-
-import "unsafe"
-
-type sigTabT struct {
-	flags int32
-	name  string
-}
-
-var sigtable = [...]sigTabT{
-	/* 0 */ {0, "SIGNONE: no trap"},
-	/* 1 */ {_SigNotify + _SigKill, "SIGHUP: terminal line hangup"},
-	/* 2 */ {_SigNotify + _SigKill, "SIGINT: interrupt"},
-	/* 3 */ {_SigNotify + _SigThrow, "SIGQUIT: quit"},
-	/* 4 */ {_SigThrow + _SigUnblock, "SIGILL: illegal instruction"},
-	/* 5 */ {_SigThrow + _SigUnblock, "SIGTRAP: trace trap"},
-	/* 6 */ {_SigNotify + _SigThrow, "SIGABRT: abort"},
-	/* 7 */ {_SigPanic + _SigUnblock, "SIGBUS: bus error"},
-	/* 8 */ {_SigPanic + _SigUnblock, "SIGFPE: floating-point exception"},
-	/* 9 */ {0, "SIGKILL: kill"},
-	/* 10 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
-	/* 11 */ {_SigPanic + _SigUnblock, "SIGSEGV: segmentation violation"},
-	/* 12 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
-	/* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
-	/* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
-	/* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
-	/* 16 */ {_SigThrow + _SigUnblock, "SIGSTKFLT: stack fault"},
-	/* 17 */ {_SigNotify + _SigUnblock, "SIGCHLD: child status has changed"},
-	/* 18 */ {0, "SIGCONT: continue"},
-	/* 19 */ {0, "SIGSTOP: stop, unblockable"},
-	/* 20 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
-	/* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
-	/* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
-	/* 23 */ {_SigNotify, "SIGURG: urgent condition on socket"},
-	/* 24 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
-	/* 25 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
-	/* 26 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"},
-	/* 27 */ {_SigNotify + _SigUnblock, "SIGPROF: profiling alarm clock"},
-	/* 28 */ {_SigNotify, "SIGWINCH: window size change"},
-	/* 29 */ {_SigNotify, "SIGIO: i/o now possible"},
-	/* 30 */ {_SigNotify, "SIGPWR: power failure restart"},
-	/* 31 */ {_SigNotify, "SIGSYS: bad system call"},
-	/* 32 */ {_SigSetStack + _SigUnblock, "signal 32"}, /* SIGCANCEL; see issue 6997 */
-	/* 33 */ {_SigSetStack + _SigUnblock, "signal 33"}, /* SIGSETXID; see issues 3871, 9400, 12498 */
-	/* 34 */ {_SigNotify, "signal 34"},
-	/* 35 */ {_SigNotify, "signal 35"},
-	/* 36 */ {_SigNotify, "signal 36"},
-	/* 37 */ {_SigNotify, "signal 37"},
-	/* 38 */ {_SigNotify, "signal 38"},
-	/* 39 */ {_SigNotify, "signal 39"},
-	/* 40 */ {_SigNotify, "signal 40"},
-	/* 41 */ {_SigNotify, "signal 41"},
-	/* 42 */ {_SigNotify, "signal 42"},
-	/* 43 */ {_SigNotify, "signal 43"},
-	/* 44 */ {_SigNotify, "signal 44"},
-	/* 45 */ {_SigNotify, "signal 45"},
-	/* 46 */ {_SigNotify, "signal 46"},
-	/* 47 */ {_SigNotify, "signal 47"},
-	/* 48 */ {_SigNotify, "signal 48"},
-	/* 49 */ {_SigNotify, "signal 49"},
-	/* 50 */ {_SigNotify, "signal 50"},
-	/* 51 */ {_SigNotify, "signal 51"},
-	/* 52 */ {_SigNotify, "signal 52"},
-	/* 53 */ {_SigNotify, "signal 53"},
-	/* 54 */ {_SigNotify, "signal 54"},
-	/* 55 */ {_SigNotify, "signal 55"},
-	/* 56 */ {_SigNotify, "signal 56"},
-	/* 57 */ {_SigNotify, "signal 57"},
-	/* 58 */ {_SigNotify, "signal 58"},
-	/* 59 */ {_SigNotify, "signal 59"},
-	/* 60 */ {_SigNotify, "signal 60"},
-	/* 61 */ {_SigNotify, "signal 61"},
-	/* 62 */ {_SigNotify, "signal 62"},
-	/* 63 */ {_SigNotify, "signal 63"},
-	/* 64 */ {_SigNotify, "signal 64"},
-}
-
-// Continuation of the (assembly) sigtramp() logic.
-//go:nosplit
-func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
-	if sigfwdgo(sig, info, ctx) {
-		return
-	}
-	g := getg()
-	if g == nil {
-		badsignal(uintptr(sig))
-		return
-	}
-	setg(g.m.gsignal)
-	sighandler(sig, info, ctx, g)
-	setg(g)
-}
diff --git a/src/runtime/signal_linux_386.go b/src/runtime/signal_linux_386.go
index 085f66e..45074f9 100644
--- a/src/runtime/signal_linux_386.go
+++ b/src/runtime/signal_linux_386.go
@@ -4,7 +4,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 type sigctxt struct {
 	info *siginfo
@@ -32,5 +35,5 @@ func (c *sigctxt) set_eip(x uint32)     { c.regs().eip = x }
 func (c *sigctxt) set_esp(x uint32)     { c.regs().esp = x }
 func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
 func (c *sigctxt) set_sigaddr(x uint32) {
-	*(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize)) = uintptr(x)
+	*(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x)
 }
diff --git a/src/runtime/signal_linux_amd64.go b/src/runtime/signal_linux_amd64.go
index 5e339b8..b8b38cc 100644
--- a/src/runtime/signal_linux_amd64.go
+++ b/src/runtime/signal_linux_amd64.go
@@ -4,7 +4,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 type sigctxt struct {
 	info *siginfo
@@ -42,5 +45,5 @@ func (c *sigctxt) set_rip(x uint64)     { c.regs().rip = x }
 func (c *sigctxt) set_rsp(x uint64)     { c.regs().rsp = x }
 func (c *sigctxt) set_sigcode(x uint64) { c.info.si_code = int32(x) }
 func (c *sigctxt) set_sigaddr(x uint64) {
-	*(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize)) = uintptr(x)
+	*(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x)
 }
diff --git a/src/runtime/signal_linux_arm.go b/src/runtime/signal_linux_arm.go
index bdb4314..469f47c 100644
--- a/src/runtime/signal_linux_arm.go
+++ b/src/runtime/signal_linux_arm.go
@@ -4,7 +4,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 type sigctxt struct {
 	info *siginfo
@@ -44,5 +47,5 @@ func (c *sigctxt) set_r10(x uint32) { c.regs().r10 = x }
 
 func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
 func (c *sigctxt) set_sigaddr(x uint32) {
-	*(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize)) = uintptr(x)
+	*(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x)
 }
diff --git a/src/runtime/signal_linux_arm64.go b/src/runtime/signal_linux_arm64.go
index 7d8b010..465fc4f 100644
--- a/src/runtime/signal_linux_arm64.go
+++ b/src/runtime/signal_linux_arm64.go
@@ -4,7 +4,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 type sigctxt struct {
 	info *siginfo
@@ -57,5 +60,5 @@ func (c *sigctxt) set_lr(x uint64)  { c.regs().regs[30] = x }
 func (c *sigctxt) set_r28(x uint64) { c.regs().regs[28] = x }
 
 func (c *sigctxt) set_sigaddr(x uint64) {
-	*(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize)) = uintptr(x)
+	*(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x)
 }
diff --git a/src/runtime/signal_linux_mips64x.go b/src/runtime/signal_linux_mips64x.go
new file mode 100644
index 0000000..671b916
--- /dev/null
+++ b/src/runtime/signal_linux_mips64x.go
@@ -0,0 +1,70 @@
+// Copyright 2015 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.
+
+// +build linux
+// +build mips64 mips64le
+
+package runtime
+
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
+
+type sigctxt struct {
+	info *siginfo
+	ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *sigcontext { return &(*ucontext)(c.ctxt).uc_mcontext }
+func (c *sigctxt) r0() uint64        { return c.regs().sc_regs[0] }
+func (c *sigctxt) r1() uint64        { return c.regs().sc_regs[1] }
+func (c *sigctxt) r2() uint64        { return c.regs().sc_regs[2] }
+func (c *sigctxt) r3() uint64        { return c.regs().sc_regs[3] }
+func (c *sigctxt) r4() uint64        { return c.regs().sc_regs[4] }
+func (c *sigctxt) r5() uint64        { return c.regs().sc_regs[5] }
+func (c *sigctxt) r6() uint64        { return c.regs().sc_regs[6] }
+func (c *sigctxt) r7() uint64        { return c.regs().sc_regs[7] }
+func (c *sigctxt) r8() uint64        { return c.regs().sc_regs[8] }
+func (c *sigctxt) r9() uint64        { return c.regs().sc_regs[9] }
+func (c *sigctxt) r10() uint64       { return c.regs().sc_regs[10] }
+func (c *sigctxt) r11() uint64       { return c.regs().sc_regs[11] }
+func (c *sigctxt) r12() uint64       { return c.regs().sc_regs[12] }
+func (c *sigctxt) r13() uint64       { return c.regs().sc_regs[13] }
+func (c *sigctxt) r14() uint64       { return c.regs().sc_regs[14] }
+func (c *sigctxt) r15() uint64       { return c.regs().sc_regs[15] }
+func (c *sigctxt) r16() uint64       { return c.regs().sc_regs[16] }
+func (c *sigctxt) r17() uint64       { return c.regs().sc_regs[17] }
+func (c *sigctxt) r18() uint64       { return c.regs().sc_regs[18] }
+func (c *sigctxt) r19() uint64       { return c.regs().sc_regs[19] }
+func (c *sigctxt) r20() uint64       { return c.regs().sc_regs[20] }
+func (c *sigctxt) r21() uint64       { return c.regs().sc_regs[21] }
+func (c *sigctxt) r22() uint64       { return c.regs().sc_regs[22] }
+func (c *sigctxt) r23() uint64       { return c.regs().sc_regs[23] }
+func (c *sigctxt) r24() uint64       { return c.regs().sc_regs[24] }
+func (c *sigctxt) r25() uint64       { return c.regs().sc_regs[25] }
+func (c *sigctxt) r26() uint64       { return c.regs().sc_regs[26] }
+func (c *sigctxt) r27() uint64       { return c.regs().sc_regs[27] }
+func (c *sigctxt) r28() uint64       { return c.regs().sc_regs[28] }
+func (c *sigctxt) r29() uint64       { return c.regs().sc_regs[29] }
+func (c *sigctxt) r30() uint64       { return c.regs().sc_regs[30] }
+func (c *sigctxt) r31() uint64       { return c.regs().sc_regs[31] }
+func (c *sigctxt) sp() uint64        { return c.regs().sc_regs[29] }
+func (c *sigctxt) pc() uint64        { return c.regs().sc_pc }
+func (c *sigctxt) link() uint64      { return c.regs().sc_regs[31] }
+func (c *sigctxt) lo() uint64        { return c.regs().sc_mdlo }
+func (c *sigctxt) hi() uint64        { return c.regs().sc_mdhi }
+
+func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) }
+func (c *sigctxt) sigaddr() uint64 { return c.info.si_addr }
+
+func (c *sigctxt) set_r30(x uint64)  { c.regs().sc_regs[30] = x }
+func (c *sigctxt) set_pc(x uint64)   { c.regs().sc_pc = x }
+func (c *sigctxt) set_sp(x uint64)   { c.regs().sc_regs[29] = x }
+func (c *sigctxt) set_link(x uint64) { c.regs().sc_regs[31] = x }
+
+func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint64) {
+	*(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x)
+}
diff --git a/src/runtime/signal_linux_ppc64x.go b/src/runtime/signal_linux_ppc64x.go
index da3afc9..49e97a4 100644
--- a/src/runtime/signal_linux_ppc64x.go
+++ b/src/runtime/signal_linux_ppc64x.go
@@ -7,7 +7,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 type sigctxt struct {
 	info *siginfo
@@ -60,6 +63,7 @@ func (c *sigctxt) sigaddr() uint64 { return c.info.si_addr }
 func (c *sigctxt) fault() uint64   { return c.regs().dar }
 
 func (c *sigctxt) set_r0(x uint64)   { c.regs().gpr[0] = x }
+func (c *sigctxt) set_r12(x uint64)  { c.regs().gpr[12] = x }
 func (c *sigctxt) set_r30(x uint64)  { c.regs().gpr[30] = x }
 func (c *sigctxt) set_pc(x uint64)   { c.regs().nip = x }
 func (c *sigctxt) set_sp(x uint64)   { c.regs().gpr[1] = x }
@@ -67,5 +71,5 @@ func (c *sigctxt) set_link(x uint64) { c.regs().link = x }
 
 func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
 func (c *sigctxt) set_sigaddr(x uint64) {
-	*(*uintptr)(add(unsafe.Pointer(c.info), 2*ptrSize)) = uintptr(x)
+	*(*uintptr)(add(unsafe.Pointer(c.info), 2*sys.PtrSize)) = uintptr(x)
 }
diff --git a/src/runtime/signal_mips64x.go b/src/runtime/signal_mips64x.go
new file mode 100644
index 0000000..77c2714
--- /dev/null
+++ b/src/runtime/signal_mips64x.go
@@ -0,0 +1,188 @@
+// Copyright 2015 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.
+
+// +build linux
+// +build mips64 mips64le
+
+package runtime
+
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
+
+func dumpregs(c *sigctxt) {
+	print("r0   ", hex(c.r0()), "\t")
+	print("r1   ", hex(c.r1()), "\n")
+	print("r2   ", hex(c.r2()), "\t")
+	print("r3   ", hex(c.r3()), "\n")
+	print("r4   ", hex(c.r4()), "\t")
+	print("r5   ", hex(c.r5()), "\n")
+	print("r6   ", hex(c.r6()), "\t")
+	print("r7   ", hex(c.r7()), "\n")
+	print("r8   ", hex(c.r8()), "\t")
+	print("r9   ", hex(c.r9()), "\n")
+	print("r10  ", hex(c.r10()), "\t")
+	print("r11  ", hex(c.r11()), "\n")
+	print("r12  ", hex(c.r12()), "\t")
+	print("r13  ", hex(c.r13()), "\n")
+	print("r14  ", hex(c.r14()), "\t")
+	print("r15  ", hex(c.r15()), "\n")
+	print("r16  ", hex(c.r16()), "\t")
+	print("r17  ", hex(c.r17()), "\n")
+	print("r18  ", hex(c.r18()), "\t")
+	print("r19  ", hex(c.r19()), "\n")
+	print("r20  ", hex(c.r20()), "\t")
+	print("r21  ", hex(c.r21()), "\n")
+	print("r22  ", hex(c.r22()), "\t")
+	print("r23  ", hex(c.r23()), "\n")
+	print("r24  ", hex(c.r24()), "\t")
+	print("r25  ", hex(c.r25()), "\n")
+	print("r26  ", hex(c.r26()), "\t")
+	print("r27  ", hex(c.r27()), "\n")
+	print("r28  ", hex(c.r28()), "\t")
+	print("r29  ", hex(c.r29()), "\n")
+	print("r30  ", hex(c.r30()), "\t")
+	print("r31  ", hex(c.r31()), "\n")
+	print("pc   ", hex(c.pc()), "\t")
+	print("link ", hex(c.link()), "\n")
+	print("lo   ", hex(c.lo()), "\t")
+	print("hi   ", hex(c.hi()), "\n")
+}
+
+var crashing int32
+
+// May run during STW, so write barriers are not allowed.
+//
+//go:nowritebarrierrec
+func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
+	_g_ := getg()
+	c := &sigctxt{info, ctxt}
+
+	if sig == _SIGPROF {
+		sigprof(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.link()), gp, _g_.m)
+		return
+	}
+	flags := int32(_SigThrow)
+	if sig < uint32(len(sigtable)) {
+		flags = sigtable[sig].flags
+	}
+	if c.sigcode() != _SI_USER && flags&_SigPanic != 0 {
+		// Make it look like a call to the signal func.
+		// Have to pass arguments out of band since
+		// augmenting the stack frame would break
+		// the unwinding code.
+		gp.sig = sig
+		gp.sigcode0 = uintptr(c.sigcode())
+		gp.sigcode1 = uintptr(c.sigaddr())
+		gp.sigpc = uintptr(c.pc())
+
+		// We arrange link, and pc to pretend the panicking
+		// function calls sigpanic directly.
+		// Always save LINK to stack so that panics in leaf
+		// functions are correctly handled. This smashes
+		// the stack frame but we're not going back there
+		// anyway.
+		sp := c.sp() - sys.PtrSize
+		c.set_sp(sp)
+		*(*uint64)(unsafe.Pointer(uintptr(sp))) = c.link()
+
+		pc := uintptr(gp.sigpc)
+
+		// If we don't recognize the PC as code
+		// but we do recognize the link register as code,
+		// then assume this was a call to non-code and treat like
+		// pc == 0, to make unwinding show the context.
+		if pc != 0 && findfunc(pc) == nil && findfunc(uintptr(c.link())) != nil {
+			pc = 0
+		}
+
+		// Don't bother saving PC if it's zero, which is
+		// probably a call to a nil func: the old link register
+		// is more useful in the stack trace.
+		if pc != 0 {
+			c.set_link(uint64(pc))
+		}
+
+		// In case we are panicking from external C code
+		c.set_r30(uint64(uintptr(unsafe.Pointer(gp))))
+		c.set_pc(uint64(funcPC(sigpanic)))
+		return
+	}
+
+	if c.sigcode() == _SI_USER || flags&_SigNotify != 0 {
+		if sigsend(sig) {
+			return
+		}
+	}
+
+	if c.sigcode() == _SI_USER && signal_ignored(sig) {
+		return
+	}
+
+	if flags&_SigKill != 0 {
+		dieFromSignal(int32(sig))
+	}
+
+	if flags&_SigThrow == 0 {
+		return
+	}
+
+	_g_.m.throwing = 1
+	_g_.m.caughtsig.set(gp)
+
+	if crashing == 0 {
+		startpanic()
+	}
+
+	if sig < uint32(len(sigtable)) {
+		print(sigtable[sig].name, "\n")
+	} else {
+		print("Signal ", sig, "\n")
+	}
+
+	print("PC=", hex(c.pc()), " m=", _g_.m.id, "\n")
+	if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
+		print("signal arrived during cgo execution\n")
+		gp = _g_.m.lockedg
+	}
+	print("\n")
+
+	level, _, docrash := gotraceback()
+	if level > 0 {
+		goroutineheader(gp)
+		tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.link()), gp)
+		if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning {
+			// tracebackothers on original m skipped this one; trace it now.
+			goroutineheader(_g_.m.curg)
+			traceback(^uintptr(0), ^uintptr(0), 0, gp)
+		} else if crashing == 0 {
+			tracebackothers(gp)
+			print("\n")
+		}
+		dumpregs(c)
+	}
+
+	if docrash {
+		crashing++
+		if crashing < sched.mcount {
+			// There are other m's that need to dump their stacks.
+			// Relay SIGQUIT to the next m by sending it to the current process.
+			// All m's that have already received SIGQUIT have signal masks blocking
+			// receipt of any signals, so the SIGQUIT will go to an m that hasn't seen it yet.
+			// When the last m receives the SIGQUIT, it will fall through to the call to
+			// crash below. Just in case the relaying gets botched, each m involved in
+			// the relay sleeps for 5 seconds and then does the crash/exit itself.
+			// In expected operation, the last m has received the SIGQUIT and run
+			// crash/exit and the process is gone, all long before any of the
+			// 5-second sleeps have finished.
+			print("\n-----\n\n")
+			raiseproc(_SIGQUIT)
+			usleep(5 * 1000 * 1000)
+		}
+		crash()
+	}
+
+	exit(2)
+}
diff --git a/src/runtime/signal_nacl.go b/src/runtime/signal_nacl.go
index 122648b..4793075 100644
--- a/src/runtime/signal_nacl.go
+++ b/src/runtime/signal_nacl.go
@@ -29,7 +29,7 @@ var sigtable = [...]sigTabT{
 	/* 16 */ {_SigNotify, "SIGURG: urgent condition on socket"},
 	/* 17 */ {0, "SIGSTOP: stop"},
 	/* 18 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
-	/* 19 */ {0, "SIGCONT: continue after stop"},
+	/* 19 */ {_SigNotify + _SigDefault, "SIGCONT: continue after stop"},
 	/* 20 */ {_SigNotify, "SIGCHLD: child status has changed"},
 	/* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
 	/* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
diff --git a/src/runtime/signal_netbsd.go b/src/runtime/signal_netbsd.go
index d93a450..30a3b8e 100644
--- a/src/runtime/signal_netbsd.go
+++ b/src/runtime/signal_netbsd.go
@@ -29,7 +29,7 @@ var sigtable = [...]sigTabT{
 	/* 16 */ {_SigNotify, "SIGURG: urgent condition on socket"},
 	/* 17 */ {0, "SIGSTOP: stop"},
 	/* 18 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
-	/* 19 */ {0, "SIGCONT: continue after stop"},
+	/* 19 */ {_SigNotify + _SigDefault, "SIGCONT: continue after stop"},
 	/* 20 */ {_SigNotify + _SigUnblock, "SIGCHLD: child status has changed"},
 	/* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
 	/* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
diff --git a/src/runtime/signal_openbsd.go b/src/runtime/signal_openbsd.go
index 78afc59..d0239b1 100644
--- a/src/runtime/signal_openbsd.go
+++ b/src/runtime/signal_openbsd.go
@@ -4,6 +4,8 @@
 
 package runtime
 
+import "unsafe"
+
 type sigTabT struct {
 	flags int32
 	name  string
@@ -29,7 +31,7 @@ var sigtable = [...]sigTabT{
 	/* 16 */ {_SigNotify, "SIGURG: urgent condition on socket"},
 	/* 17 */ {0, "SIGSTOP: stop"},
 	/* 18 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
-	/* 19 */ {0, "SIGCONT: continue after stop"},
+	/* 19 */ {_SigNotify + _SigDefault, "SIGCONT: continue after stop"},
 	/* 20 */ {_SigNotify, "SIGCHLD: child status has changed"},
 	/* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
 	/* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
@@ -44,3 +46,42 @@ var sigtable = [...]sigTabT{
 	/* 31 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
 	/* 32 */ {_SigNotify, "SIGTHR: reserved"},
 }
+
+//go:nosplit
+//go:nowritebarrierrec
+func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
+	if sigfwdgo(sig, info, ctx) {
+		return
+	}
+	g := getg()
+	if g == nil {
+		badsignal(uintptr(sig))
+		return
+	}
+
+	// If some non-Go code called sigaltstack, adjust.
+	sp := uintptr(unsafe.Pointer(&sig))
+	if sp < g.m.gsignal.stack.lo || sp >= g.m.gsignal.stack.hi {
+		var st stackt
+		sigaltstack(nil, &st)
+		if st.ss_flags&_SS_DISABLE != 0 {
+			setg(nil)
+			cgocallback(unsafe.Pointer(funcPC(noSignalStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig))
+		}
+		stsp := uintptr(unsafe.Pointer(st.ss_sp))
+		if sp < stsp || sp >= stsp+st.ss_size {
+			setg(nil)
+			cgocallback(unsafe.Pointer(funcPC(sigNotOnStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig))
+		}
+		g.m.gsignal.stack.lo = stsp
+		g.m.gsignal.stack.hi = stsp + st.ss_size
+		g.m.gsignal.stackguard0 = stsp + _StackGuard
+		g.m.gsignal.stackguard1 = stsp + _StackGuard
+		g.m.gsignal.stackAlloc = st.ss_size
+		g.m.gsignal.stktopsp = getcallersp(unsafe.Pointer(&sig))
+	}
+
+	setg(g.m.gsignal)
+	sighandler(sig, info, ctx, g)
+	setg(g)
+}
diff --git a/src/runtime/signal_plan9.go b/src/runtime/signal_plan9.go
index 302f156..19247f2 100644
--- a/src/runtime/signal_plan9.go
+++ b/src/runtime/signal_plan9.go
@@ -51,4 +51,7 @@ var sigtable = [...]sigTabT{
 
 	// Alarms can be handled if desired, otherwise they're ignored.
 	{_SigNotify, "alarm"},
+
+	// Aborts can be handled if desired, otherwise they cause a stack trace.
+	{_SigNotify + _SigThrow, "abort"},
 }
diff --git a/src/runtime/signal_ppc64x.go b/src/runtime/signal_ppc64x.go
index bad9fe6..1c868b8 100644
--- a/src/runtime/signal_ppc64x.go
+++ b/src/runtime/signal_ppc64x.go
@@ -7,7 +7,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 func dumpregs(c *sigctxt) {
 	print("r0   ", hex(c.r0()), "\t")
@@ -53,7 +56,8 @@ func dumpregs(c *sigctxt) {
 var crashing int32
 
 // May run during STW, so write barriers are not allowed.
-//go:nowritebarrier
+//
+//go:nowritebarrierrec
 func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
 	_g_ := getg()
 	c := &sigctxt{info, ctxt}
@@ -82,7 +86,7 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
 		// functions are correctly handled. This smashes
 		// the stack frame but we're not going back there
 		// anyway.
-		sp := c.sp() - ptrSize
+		sp := c.sp() - sys.MinFrameSize
 		c.set_sp(sp)
 		*(*uint64)(unsafe.Pointer(uintptr(sp))) = c.link()
 
@@ -106,6 +110,7 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
 		// In case we are panicking from external C code
 		c.set_r0(0)
 		c.set_r30(uint64(uintptr(unsafe.Pointer(gp))))
+		c.set_r12(uint64(funcPC(sigpanic)))
 		c.set_pc(uint64(funcPC(sigpanic)))
 		return
 	}
@@ -116,8 +121,12 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
 		}
 	}
 
+	if c.sigcode() == _SI_USER && signal_ignored(sig) {
+		return
+	}
+
 	if flags&_SigKill != 0 {
-		exit(2)
+		dieFromSignal(int32(sig))
 	}
 
 	if flags&_SigThrow == 0 {
@@ -144,8 +153,8 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
 	}
 	print("\n")
 
-	var docrash bool
-	if gotraceback(&docrash) > 0 {
+	level, _, docrash := gotraceback()
+	if level > 0 {
 		goroutineheader(gp)
 		tracebacktrap(uintptr(c.pc()), uintptr(c.sp()), uintptr(c.link()), gp)
 		if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning {
diff --git a/src/runtime/signal_sigtramp.go b/src/runtime/signal_sigtramp.go
new file mode 100644
index 0000000..00ab038
--- /dev/null
+++ b/src/runtime/signal_sigtramp.go
@@ -0,0 +1,50 @@
+// Copyright 2009 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.
+
+// +build dragonfly linux netbsd
+
+package runtime
+
+import "unsafe"
+
+// Continuation of the (assembly) sigtramp() logic.
+// This may be called with the world stopped.
+//go:nosplit
+//go:nowritebarrierrec
+func sigtrampgo(sig uint32, info *siginfo, ctx unsafe.Pointer) {
+	if sigfwdgo(sig, info, ctx) {
+		return
+	}
+	g := getg()
+	if g == nil {
+		badsignal(uintptr(sig))
+		return
+	}
+
+	// If some non-Go code called sigaltstack, adjust.
+	sp := uintptr(unsafe.Pointer(&sig))
+	if sp < g.m.gsignal.stack.lo || sp >= g.m.gsignal.stack.hi {
+		var st sigaltstackt
+		sigaltstack(nil, &st)
+		if st.ss_flags&_SS_DISABLE != 0 {
+			setg(nil)
+			cgocallback(unsafe.Pointer(funcPC(noSignalStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig))
+		}
+		stsp := uintptr(unsafe.Pointer(st.ss_sp))
+		if sp < stsp || sp >= stsp+st.ss_size {
+			setg(nil)
+			cgocallback(unsafe.Pointer(funcPC(sigNotOnStack)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig))
+		}
+		g.m.gsignal.stack.lo = stsp
+		g.m.gsignal.stack.hi = stsp + st.ss_size
+		g.m.gsignal.stackguard0 = stsp + _StackGuard
+		g.m.gsignal.stackguard1 = stsp + _StackGuard
+		g.m.gsignal.stackAlloc = st.ss_size
+		g.m.gsignal.stktopsp = getcallersp(unsafe.Pointer(&sig))
+	}
+
+	setg(g.m.gsignal)
+	sighandler(sig, info, ctx, g)
+	setg(g)
+}
diff --git a/src/runtime/signal_solaris.go b/src/runtime/signal_solaris.go
index d8ac676..2cab5b8 100644
--- a/src/runtime/signal_solaris.go
+++ b/src/runtime/signal_solaris.go
@@ -34,8 +34,8 @@ var sigtable = [...]sigTabT{
 	/* 21 */ {_SigNotify, "SIGURG: urgent socket condition"},
 	/* 22 */ {_SigNotify, "SIGPOLL: pollable event occured"},
 	/* 23 */ {_SigNotify + _SigDefault, "SIGSTOP: stop (cannot be caught or ignored)"},
-	/* 24 */ {0, "SIGTSTP: user stop requested from tty"},
-	/* 25 */ {0, "SIGCONT: stopped process has been continued"},
+	/* 24 */ {_SigNotify + _SigDefault, "SIGTSTP: user stop requested from tty"},
+	/* 25 */ {_SigNotify + _SigDefault, "SIGCONT: stopped process has been continued"},
 	/* 26 */ {_SigNotify + _SigDefault, "SIGTTIN: background tty read attempted"},
 	/* 27 */ {_SigNotify + _SigDefault, "SIGTTOU: background tty write attempted"},
 	/* 28 */ {_SigNotify, "SIGVTALRM: virtual timer expired"},
@@ -46,7 +46,7 @@ var sigtable = [...]sigTabT{
 	/* 33 */ {_SigNotify, "SIGLWP: reserved signal no longer used by"},
 	/* 34 */ {_SigNotify, "SIGFREEZE: special signal used by CPR"},
 	/* 35 */ {_SigNotify, "SIGTHAW: special signal used by CPR"},
-	/* 36 */ {0, "SIGCANCEL: reserved signal for thread cancellation"},
+	/* 36 */ {_SigSetStack + _SigUnblock, "SIGCANCEL: reserved signal for thread cancellation"}, // Oracle's spelling of cancelation.
 	/* 37 */ {_SigNotify, "SIGLOST: resource lost (eg, record-lock lost)"},
 	/* 38 */ {_SigNotify, "SIGXRES: resource control exceeded"},
 	/* 39 */ {_SigNotify, "SIGJVM1: reserved signal for Java Virtual Machine"},
diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go
index ad3ab31..8834e51 100644
--- a/src/runtime/signal_unix.go
+++ b/src/runtime/signal_unix.go
@@ -6,43 +6,9 @@
 
 package runtime
 
-import "unsafe"
+import _ "unsafe" // for go:linkname
 
 //go:linkname os_sigpipe os.sigpipe
 func os_sigpipe() {
 	systemstack(sigpipe)
 }
-
-// Determines if the signal should be handled by Go and if not, forwards the
-// signal to the handler that was installed before Go's.  Returns whether the
-// signal was forwarded.
-//go:nosplit
-func sigfwdgo(sig uint32, info *siginfo, ctx unsafe.Pointer) bool {
-	g := getg()
-	c := &sigctxt{info, ctx}
-	if sig >= uint32(len(sigtable)) {
-		return false
-	}
-	fwdFn := fwdSig[sig]
-	flags := sigtable[sig].flags
-
-	// If there is no handler to forward to, no need to forward.
-	if fwdFn == _SIG_DFL {
-		return false
-	}
-	// Only forward synchronous signals.
-	if c.sigcode() == _SI_USER || flags&_SigPanic == 0 {
-		return false
-	}
-	// Determine if the signal occurred inside Go code.  We test that:
-	//   (1) we were in a goroutine (i.e., m.curg != nil), and
-	//   (2) we weren't in CGO (i.e., m.curg.syscallsp == 0).
-	if g != nil && g.m != nil && g.m.curg != nil && g.m.curg.syscallsp == 0 {
-		return false
-	}
-	// Signal not handled by Go, forward it.
-	if fwdFn != _SIG_IGN {
-		sigfwd(fwdFn, sig, info, ctx)
-	}
-	return true
-}
diff --git a/src/runtime/signal_windows.go b/src/runtime/signal_windows.go
index d80cc97..ab7183f 100644
--- a/src/runtime/signal_windows.go
+++ b/src/runtime/signal_windows.go
@@ -134,8 +134,8 @@ func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 {
 	}
 	print("\n")
 
-	var docrash bool
-	if gotraceback(&docrash) > 0 {
+	level, _, docrash := gotraceback()
+	if level > 0 {
 		tracebacktrap(r.ip(), r.sp(), 0, gp)
 		tracebackothers(gp)
 		dumpregs(r)
@@ -191,7 +191,7 @@ func setBadSignalMsg() {
 
 // Following are not implemented.
 
-func initsig() {
+func initsig(preinit bool) {
 }
 
 func sigenable(sig uint32) {
diff --git a/src/runtime/sigqueue.go b/src/runtime/sigqueue.go
index 3f50a59..546d3ab 100644
--- a/src/runtime/sigqueue.go
+++ b/src/runtime/sigqueue.go
@@ -28,15 +28,19 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"unsafe"
+)
 
 var sig struct {
-	note   note
-	mask   [(_NSIG + 31) / 32]uint32
-	wanted [(_NSIG + 31) / 32]uint32
-	recv   [(_NSIG + 31) / 32]uint32
-	state  uint32
-	inuse  bool
+	note    note
+	mask    [(_NSIG + 31) / 32]uint32
+	wanted  [(_NSIG + 31) / 32]uint32
+	ignored [(_NSIG + 31) / 32]uint32
+	recv    [(_NSIG + 31) / 32]uint32
+	state   uint32
+	inuse   bool
 }
 
 const (
@@ -49,7 +53,7 @@ const (
 // Reports whether the signal was sent. If not, the caller typically crashes the program.
 func sigsend(s uint32) bool {
 	bit := uint32(1) << uint(s&31)
-	if !sig.inuse || s < 0 || int(s) >= 32*len(sig.wanted) || sig.wanted[s/32]&bit == 0 {
+	if !sig.inuse || s >= uint32(32*len(sig.wanted)) || sig.wanted[s/32]&bit == 0 {
 		return false
 	}
 
@@ -59,7 +63,7 @@ func sigsend(s uint32) bool {
 		if mask&bit != 0 {
 			return true // signal already in queue
 		}
-		if cas(&sig.mask[s/32], mask, mask|bit) {
+		if atomic.Cas(&sig.mask[s/32], mask, mask|bit) {
 			break
 		}
 	}
@@ -67,18 +71,18 @@ func sigsend(s uint32) bool {
 	// Notify receiver that queue has new bit.
 Send:
 	for {
-		switch atomicload(&sig.state) {
+		switch atomic.Load(&sig.state) {
 		default:
 			throw("sigsend: inconsistent state")
 		case sigIdle:
-			if cas(&sig.state, sigIdle, sigSending) {
+			if atomic.Cas(&sig.state, sigIdle, sigSending) {
 				break Send
 			}
 		case sigSending:
 			// notification already pending
 			break Send
 		case sigReceiving:
-			if cas(&sig.state, sigReceiving, sigIdle) {
+			if atomic.Cas(&sig.state, sigReceiving, sigIdle) {
 				notewakeup(&sig.note)
 				break Send
 			}
@@ -90,6 +94,7 @@ Send:
 
 // Called to receive the next queued signal.
 // Must only be called from a single goroutine at a time.
+//go:linkname signal_recv os/signal.signal_recv
 func signal_recv() uint32 {
 	for {
 		// Serve any signals from local copy.
@@ -103,17 +108,17 @@ func signal_recv() uint32 {
 		// Wait for updates to be available from signal sender.
 	Receive:
 		for {
-			switch atomicload(&sig.state) {
+			switch atomic.Load(&sig.state) {
 			default:
 				throw("signal_recv: inconsistent state")
 			case sigIdle:
-				if cas(&sig.state, sigIdle, sigReceiving) {
+				if atomic.Cas(&sig.state, sigIdle, sigReceiving) {
 					notetsleepg(&sig.note, -1)
 					noteclear(&sig.note)
 					break Receive
 				}
 			case sigSending:
-				if cas(&sig.state, sigSending, sigIdle) {
+				if atomic.Cas(&sig.state, sigSending, sigIdle) {
 					break Receive
 				}
 			}
@@ -121,12 +126,13 @@ func signal_recv() uint32 {
 
 		// Incorporate updates from sender into local copy.
 		for i := range sig.mask {
-			sig.recv[i] = xchg(&sig.mask[i], 0)
+			sig.recv[i] = atomic.Xchg(&sig.mask[i], 0)
 		}
 	}
 }
 
 // Must only be called from a single goroutine at a time.
+//go:linkname signal_enable os/signal.signal_enable
 func signal_enable(s uint32) {
 	if !sig.inuse {
 		// The first call to signal_enable is for us
@@ -137,16 +143,18 @@ func signal_enable(s uint32) {
 		return
 	}
 
-	if int(s) >= len(sig.wanted)*32 {
+	if s >= uint32(len(sig.wanted)*32) {
 		return
 	}
 	sig.wanted[s/32] |= 1 << (s & 31)
+	sig.ignored[s/32] &^= 1 << (s & 31)
 	sigenable(s)
 }
 
 // Must only be called from a single goroutine at a time.
+//go:linkname signal_disable os/signal.signal_disable
 func signal_disable(s uint32) {
-	if int(s) >= len(sig.wanted)*32 {
+	if s >= uint32(len(sig.wanted)*32) {
 		return
 	}
 	sig.wanted[s/32] &^= 1 << (s & 31)
@@ -154,17 +162,25 @@ func signal_disable(s uint32) {
 }
 
 // Must only be called from a single goroutine at a time.
+//go:linkname signal_ignore os/signal.signal_ignore
 func signal_ignore(s uint32) {
-	if int(s) >= len(sig.wanted)*32 {
+	if s >= uint32(len(sig.wanted)*32) {
 		return
 	}
 	sig.wanted[s/32] &^= 1 << (s & 31)
+	sig.ignored[s/32] |= 1 << (s & 31)
 	sigignore(s)
 }
 
+// Checked by signal handlers.
+func signal_ignored(s uint32) bool {
+	return sig.ignored[s/32]&(1<<(s&31)) != 0
+}
+
 // This runs on a foreign stack, without an m or a g.  No stack split.
 //go:nosplit
 //go:norace
+//go:nowritebarrierrec
 func badsignal(sig uintptr) {
 	cgocallback(unsafe.Pointer(funcPC(badsignalgo)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig))
 }
diff --git a/src/runtime/sigqueue_plan9.go b/src/runtime/sigqueue_plan9.go
index f000fab..89f96be 100644
--- a/src/runtime/sigqueue_plan9.go
+++ b/src/runtime/sigqueue_plan9.go
@@ -6,6 +6,8 @@
 
 package runtime
 
+import _ "unsafe"
+
 const qsize = 64
 
 var sig struct {
@@ -92,6 +94,7 @@ func sendNote(s *byte) bool {
 
 // Called to receive the next queued signal.
 // Must only be called from a single goroutine at a time.
+//go:linkname signal_recv os/signal.signal_recv
 func signal_recv() string {
 	for {
 		note := sig.q.pop()
@@ -108,6 +111,7 @@ func signal_recv() string {
 }
 
 // Must only be called from a single goroutine at a time.
+//go:linkname signal_enable os/signal.signal_enable
 func signal_enable(s uint32) {
 	if !sig.inuse {
 		// The first call to signal_enable is for us
@@ -120,9 +124,11 @@ func signal_enable(s uint32) {
 }
 
 // Must only be called from a single goroutine at a time.
+//go:linkname signal_disable os/signal.signal_disable
 func signal_disable(s uint32) {
 }
 
 // Must only be called from a single goroutine at a time.
+//go:linkname signal_ignore os/signal.signal_ignore
 func signal_ignore(s uint32) {
 }
diff --git a/src/runtime/sigtab_linux_generic.go b/src/runtime/sigtab_linux_generic.go
new file mode 100644
index 0000000..32c40c4
--- /dev/null
+++ b/src/runtime/sigtab_linux_generic.go
@@ -0,0 +1,82 @@
+// Copyright 2009 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.
+
+// +build !mips64
+// +build !mips64le
+// +build linux
+
+package runtime
+
+type sigTabT struct {
+	flags int32
+	name  string
+}
+
+var sigtable = [...]sigTabT{
+	/* 0 */ {0, "SIGNONE: no trap"},
+	/* 1 */ {_SigNotify + _SigKill, "SIGHUP: terminal line hangup"},
+	/* 2 */ {_SigNotify + _SigKill, "SIGINT: interrupt"},
+	/* 3 */ {_SigNotify + _SigThrow, "SIGQUIT: quit"},
+	/* 4 */ {_SigThrow + _SigUnblock, "SIGILL: illegal instruction"},
+	/* 5 */ {_SigThrow + _SigUnblock, "SIGTRAP: trace trap"},
+	/* 6 */ {_SigNotify + _SigThrow, "SIGABRT: abort"},
+	/* 7 */ {_SigPanic + _SigUnblock, "SIGBUS: bus error"},
+	/* 8 */ {_SigPanic + _SigUnblock, "SIGFPE: floating-point exception"},
+	/* 9 */ {0, "SIGKILL: kill"},
+	/* 10 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
+	/* 11 */ {_SigPanic + _SigUnblock, "SIGSEGV: segmentation violation"},
+	/* 12 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
+	/* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
+	/* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
+	/* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
+	/* 16 */ {_SigThrow + _SigUnblock, "SIGSTKFLT: stack fault"},
+	/* 17 */ {_SigNotify + _SigUnblock, "SIGCHLD: child status has changed"},
+	/* 18 */ {_SigNotify + _SigDefault, "SIGCONT: continue"},
+	/* 19 */ {0, "SIGSTOP: stop, unblockable"},
+	/* 20 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
+	/* 21 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
+	/* 22 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
+	/* 23 */ {_SigNotify, "SIGURG: urgent condition on socket"},
+	/* 24 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
+	/* 25 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
+	/* 26 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"},
+	/* 27 */ {_SigNotify + _SigUnblock, "SIGPROF: profiling alarm clock"},
+	/* 28 */ {_SigNotify, "SIGWINCH: window size change"},
+	/* 29 */ {_SigNotify, "SIGIO: i/o now possible"},
+	/* 30 */ {_SigNotify, "SIGPWR: power failure restart"},
+	/* 31 */ {_SigNotify, "SIGSYS: bad system call"},
+	/* 32 */ {_SigSetStack + _SigUnblock, "signal 32"}, /* SIGCANCEL; see issue 6997 */
+	/* 33 */ {_SigSetStack + _SigUnblock, "signal 33"}, /* SIGSETXID; see issues 3871, 9400, 12498 */
+	/* 34 */ {_SigNotify, "signal 34"},
+	/* 35 */ {_SigNotify, "signal 35"},
+	/* 36 */ {_SigNotify, "signal 36"},
+	/* 37 */ {_SigNotify, "signal 37"},
+	/* 38 */ {_SigNotify, "signal 38"},
+	/* 39 */ {_SigNotify, "signal 39"},
+	/* 40 */ {_SigNotify, "signal 40"},
+	/* 41 */ {_SigNotify, "signal 41"},
+	/* 42 */ {_SigNotify, "signal 42"},
+	/* 43 */ {_SigNotify, "signal 43"},
+	/* 44 */ {_SigNotify, "signal 44"},
+	/* 45 */ {_SigNotify, "signal 45"},
+	/* 46 */ {_SigNotify, "signal 46"},
+	/* 47 */ {_SigNotify, "signal 47"},
+	/* 48 */ {_SigNotify, "signal 48"},
+	/* 49 */ {_SigNotify, "signal 49"},
+	/* 50 */ {_SigNotify, "signal 50"},
+	/* 51 */ {_SigNotify, "signal 51"},
+	/* 52 */ {_SigNotify, "signal 52"},
+	/* 53 */ {_SigNotify, "signal 53"},
+	/* 54 */ {_SigNotify, "signal 54"},
+	/* 55 */ {_SigNotify, "signal 55"},
+	/* 56 */ {_SigNotify, "signal 56"},
+	/* 57 */ {_SigNotify, "signal 57"},
+	/* 58 */ {_SigNotify, "signal 58"},
+	/* 59 */ {_SigNotify, "signal 59"},
+	/* 60 */ {_SigNotify, "signal 60"},
+	/* 61 */ {_SigNotify, "signal 61"},
+	/* 62 */ {_SigNotify, "signal 62"},
+	/* 63 */ {_SigNotify, "signal 63"},
+	/* 64 */ {_SigNotify, "signal 64"},
+}
diff --git a/src/runtime/sigtab_linux_mips64x.go b/src/runtime/sigtab_linux_mips64x.go
new file mode 100644
index 0000000..dbd50f7
--- /dev/null
+++ b/src/runtime/sigtab_linux_mips64x.go
@@ -0,0 +1,81 @@
+// Copyright 2015 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.
+
+// +build mips64 mips64le
+// +build linux
+
+package runtime
+
+type sigTabT struct {
+	flags int32
+	name  string
+}
+
+var sigtable = [...]sigTabT{
+	/* 0 */ {0, "SIGNONE: no trap"},
+	/* 1 */ {_SigNotify + _SigKill, "SIGHUP: terminal line hangup"},
+	/* 2 */ {_SigNotify + _SigKill, "SIGINT: interrupt"},
+	/* 3 */ {_SigNotify + _SigThrow, "SIGQUIT: quit"},
+	/* 4 */ {_SigThrow + _SigUnblock, "SIGILL: illegal instruction"},
+	/* 5 */ {_SigThrow + _SigUnblock, "SIGTRAP: trace trap"},
+	/* 6 */ {_SigNotify + _SigThrow, "SIGABRT: abort"},
+	/* 7 */ {_SigThrow, "SIGEMT"},
+	/* 8 */ {_SigPanic + _SigUnblock, "SIGFPE: floating-point exception"},
+	/* 9 */ {0, "SIGKILL: kill"},
+	/* 10 */ {_SigPanic + _SigUnblock, "SIGBUS: bus error"},
+	/* 11 */ {_SigPanic + _SigUnblock, "SIGSEGV: segmentation violation"},
+	/* 12 */ {_SigNotify, "SIGSYS: bad system call"},
+	/* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
+	/* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
+	/* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
+	/* 16 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
+	/* 17 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
+	/* 18 */ {_SigNotify + _SigUnblock, "SIGCHLD: child status has changed"},
+	/* 19 */ {_SigNotify, "SIGPWR: power failure restart"},
+	/* 20 */ {_SigNotify, "SIGWINCH: window size change"},
+	/* 21 */ {_SigNotify, "SIGURG: urgent condition on socket"},
+	/* 22 */ {_SigNotify, "SIGIO: i/o now possible"},
+	/* 23 */ {0, "SIGSTOP: stop, unblockable"},
+	/* 24 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
+	/* 25 */ {_SigNotify + _SigDefault, "SIGCONT: continue"},
+	/* 26 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
+	/* 27 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
+	/* 28 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"},
+	/* 29 */ {_SigNotify + _SigUnblock, "SIGPROF: profiling alarm clock"},
+	/* 30 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
+	/* 31 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
+	/* 32 */ {_SigSetStack + _SigUnblock, "signal 32"}, /* SIGCANCEL; see issue 6997 */
+	/* 33 */ {_SigSetStack + _SigUnblock, "signal 33"}, /* SIGSETXID; see issues 3871, 9400, 12498 */
+	/* 34 */ {_SigNotify, "signal 34"},
+	/* 35 */ {_SigNotify, "signal 35"},
+	/* 36 */ {_SigNotify, "signal 36"},
+	/* 37 */ {_SigNotify, "signal 37"},
+	/* 38 */ {_SigNotify, "signal 38"},
+	/* 39 */ {_SigNotify, "signal 39"},
+	/* 40 */ {_SigNotify, "signal 40"},
+	/* 41 */ {_SigNotify, "signal 41"},
+	/* 42 */ {_SigNotify, "signal 42"},
+	/* 43 */ {_SigNotify, "signal 43"},
+	/* 44 */ {_SigNotify, "signal 44"},
+	/* 45 */ {_SigNotify, "signal 45"},
+	/* 46 */ {_SigNotify, "signal 46"},
+	/* 47 */ {_SigNotify, "signal 47"},
+	/* 48 */ {_SigNotify, "signal 48"},
+	/* 49 */ {_SigNotify, "signal 49"},
+	/* 50 */ {_SigNotify, "signal 50"},
+	/* 51 */ {_SigNotify, "signal 51"},
+	/* 52 */ {_SigNotify, "signal 52"},
+	/* 53 */ {_SigNotify, "signal 53"},
+	/* 54 */ {_SigNotify, "signal 54"},
+	/* 55 */ {_SigNotify, "signal 55"},
+	/* 56 */ {_SigNotify, "signal 56"},
+	/* 57 */ {_SigNotify, "signal 57"},
+	/* 58 */ {_SigNotify, "signal 58"},
+	/* 59 */ {_SigNotify, "signal 59"},
+	/* 60 */ {_SigNotify, "signal 60"},
+	/* 61 */ {_SigNotify, "signal 61"},
+	/* 62 */ {_SigNotify, "signal 62"},
+	/* 63 */ {_SigNotify, "signal 63"},
+	/* 64 */ {_SigNotify, "signal 64"},
+}
diff --git a/src/runtime/slice.go b/src/runtime/slice.go
index 5cda11d..943ecdc 100644
--- a/src/runtime/slice.go
+++ b/src/runtime/slice.go
@@ -57,6 +57,9 @@ func growslice(t *slicetype, old slice, cap int) slice {
 		callerpc := getcallerpc(unsafe.Pointer(&t))
 		racereadrangepc(old.array, uintptr(old.len*int(t.elem.size)), callerpc, funcPC(growslice))
 	}
+	if msanenabled {
+		msanread(old.array, uintptr(old.len*int(t.elem.size)))
+	}
 
 	et := t.elem
 	if et.size == 0 {
@@ -95,7 +98,7 @@ func growslice(t *slicetype, old slice, cap int) slice {
 	} else {
 		// Note: can't use rawmem (which avoids zeroing of memory), because then GC can scan uninitialized memory.
 		p = newarray(et, uintptr(newcap))
-		if !writeBarrierEnabled {
+		if !writeBarrier.enabled {
 			memmove(p, old.array, lenmem)
 		} else {
 			for i := uintptr(0); i < lenmem; i += et.size {
@@ -127,6 +130,10 @@ func slicecopy(to, fm slice, width uintptr) int {
 		racewriterangepc(to.array, uintptr(n*int(width)), callerpc, pc)
 		racereadrangepc(fm.array, uintptr(n*int(width)), callerpc, pc)
 	}
+	if msanenabled {
+		msanwrite(to.array, uintptr(n*int(width)))
+		msanread(fm.array, uintptr(n*int(width)))
+	}
 
 	size := uintptr(n) * width
 	if size == 1 { // common case worth about 2x to do here
@@ -153,7 +160,10 @@ func slicestringcopy(to []byte, fm string) int {
 		pc := funcPC(slicestringcopy)
 		racewriterangepc(unsafe.Pointer(&to[0]), uintptr(n), callerpc, pc)
 	}
+	if msanenabled {
+		msanwrite(unsafe.Pointer(&to[0]), uintptr(n))
+	}
 
-	memmove(unsafe.Pointer(&to[0]), unsafe.Pointer((*stringStruct)(unsafe.Pointer(&fm)).str), uintptr(n))
+	memmove(unsafe.Pointer(&to[0]), unsafe.Pointer(stringStructOf(&fm).str), uintptr(n))
 	return n
 }
diff --git a/src/runtime/softfloat_arm.go b/src/runtime/softfloat_arm.go
index c6eba58..202e7bb 100644
--- a/src/runtime/softfloat_arm.go
+++ b/src/runtime/softfloat_arm.go
@@ -157,6 +157,17 @@ execute:
 		}
 		return 1
 	}
+	if i == 0xe08fb00b {
+		// add pc to r11
+		// might be part of a PIC floating point move
+		// (or might not, but again no harm done).
+		regs[11] += uint32(uintptr(unsafe.Pointer(pc))) + 8
+
+		if fptrace > 0 {
+			print("*** cpu R[11] += pc ", hex(regs[11]), "\n")
+		}
+		return 1
+	}
 	if i == 0xe08bb00d {
 		// add sp to r11.
 		// might be part of a large stack offset address
diff --git a/src/runtime/sqrt.go b/src/runtime/sqrt.go
index 7452a61..1b130e3 100644
--- a/src/runtime/sqrt.go
+++ b/src/runtime/sqrt.go
@@ -117,7 +117,7 @@ func sqrt(ix uint64) uint64 {
 	// normalize x
 	exp := int((ix >> float64Shift) & float64Mask)
 	if exp == 0 { // subnormal x
-		for ix&1<<float64Shift == 0 {
+		for ix&(1<<float64Shift) == 0 {
 			ix <<= 1
 			exp--
 		}
diff --git a/src/runtime/sqrt_test.go b/src/runtime/sqrt_test.go
index d5ccc7f..54539e1 100644
--- a/src/runtime/sqrt_test.go
+++ b/src/runtime/sqrt_test.go
@@ -74,6 +74,7 @@ var vfsqrtSC = []float64{
 	0,
 	math.Inf(1),
 	math.NaN(),
+	math.Float64frombits(2),
 }
 var sqrtSC = []float64{
 	math.NaN(),
@@ -82,4 +83,5 @@ var sqrtSC = []float64{
 	0,
 	math.Inf(1),
 	math.NaN(),
+	3.1434555694052576e-162,
 }
diff --git a/src/runtime/stack.go b/src/runtime/stack.go
new file mode 100644
index 0000000..8105996
--- /dev/null
+++ b/src/runtime/stack.go
@@ -0,0 +1,1068 @@
+// Copyright 2013 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 runtime
+
+import (
+	"runtime/internal/atomic"
+	"runtime/internal/sys"
+	"unsafe"
+)
+
+/*
+Stack layout parameters.
+Included both by runtime (compiled via 6c) and linkers (compiled via gcc).
+
+The per-goroutine g->stackguard is set to point StackGuard bytes
+above the bottom of the stack.  Each function compares its stack
+pointer against g->stackguard to check for overflow.  To cut one
+instruction from the check sequence for functions with tiny frames,
+the stack is allowed to protrude StackSmall bytes below the stack
+guard.  Functions with large frames don't bother with the check and
+always call morestack.  The sequences are (for amd64, others are
+similar):
+
+	guard = g->stackguard
+	frame = function's stack frame size
+	argsize = size of function arguments (call + return)
+
+	stack frame size <= StackSmall:
+		CMPQ guard, SP
+		JHI 3(PC)
+		MOVQ m->morearg, $(argsize << 32)
+		CALL morestack(SB)
+
+	stack frame size > StackSmall but < StackBig
+		LEAQ (frame-StackSmall)(SP), R0
+		CMPQ guard, R0
+		JHI 3(PC)
+		MOVQ m->morearg, $(argsize << 32)
+		CALL morestack(SB)
+
+	stack frame size >= StackBig:
+		MOVQ m->morearg, $((argsize << 32) | frame)
+		CALL morestack(SB)
+
+The bottom StackGuard - StackSmall bytes are important: there has
+to be enough room to execute functions that refuse to check for
+stack overflow, either because they need to be adjacent to the
+actual caller's frame (deferproc) or because they handle the imminent
+stack overflow (morestack).
+
+For example, deferproc might call malloc, which does one of the
+above checks (without allocating a full frame), which might trigger
+a call to morestack.  This sequence needs to fit in the bottom
+section of the stack.  On amd64, morestack's frame is 40 bytes, and
+deferproc's frame is 56 bytes.  That fits well within the
+StackGuard - StackSmall bytes at the bottom.
+The linkers explore all possible call traces involving non-splitting
+functions to make sure that this limit cannot be violated.
+*/
+
+const (
+	// StackSystem is a number of additional bytes to add
+	// to each stack below the usual guard area for OS-specific
+	// purposes like signal handling. Used on Windows, Plan 9,
+	// and Darwin/ARM because they do not use a separate stack.
+	_StackSystem = sys.GoosWindows*512*sys.PtrSize + sys.GoosPlan9*512 + sys.GoosDarwin*sys.GoarchArm*1024
+
+	// The minimum size of stack used by Go code
+	_StackMin = 2048
+
+	// The minimum stack size to allocate.
+	// The hackery here rounds FixedStack0 up to a power of 2.
+	_FixedStack0 = _StackMin + _StackSystem
+	_FixedStack1 = _FixedStack0 - 1
+	_FixedStack2 = _FixedStack1 | (_FixedStack1 >> 1)
+	_FixedStack3 = _FixedStack2 | (_FixedStack2 >> 2)
+	_FixedStack4 = _FixedStack3 | (_FixedStack3 >> 4)
+	_FixedStack5 = _FixedStack4 | (_FixedStack4 >> 8)
+	_FixedStack6 = _FixedStack5 | (_FixedStack5 >> 16)
+	_FixedStack  = _FixedStack6 + 1
+
+	// Functions that need frames bigger than this use an extra
+	// instruction to do the stack split check, to avoid overflow
+	// in case SP - framesize wraps below zero.
+	// This value can be no bigger than the size of the unmapped
+	// space at zero.
+	_StackBig = 4096
+
+	// The stack guard is a pointer this many bytes above the
+	// bottom of the stack.
+	_StackGuard = 720*sys.StackGuardMultiplier + _StackSystem
+
+	// After a stack split check the SP is allowed to be this
+	// many bytes below the stack guard.  This saves an instruction
+	// in the checking sequence for tiny frames.
+	_StackSmall = 128
+
+	// The maximum number of bytes that a chain of NOSPLIT
+	// functions can use.
+	_StackLimit = _StackGuard - _StackSystem - _StackSmall
+)
+
+// Goroutine preemption request.
+// Stored into g->stackguard0 to cause split stack check failure.
+// Must be greater than any real sp.
+// 0xfffffade in hex.
+const (
+	_StackPreempt = uintptrMask & -1314
+	_StackFork    = uintptrMask & -1234
+)
+
+const (
+	// stackDebug == 0: no logging
+	//            == 1: logging of per-stack operations
+	//            == 2: logging of per-frame operations
+	//            == 3: logging of per-word updates
+	//            == 4: logging of per-word reads
+	stackDebug       = 0
+	stackFromSystem  = 0 // allocate stacks from system memory instead of the heap
+	stackFaultOnFree = 0 // old stacks are mapped noaccess to detect use after free
+	stackPoisonCopy  = 0 // fill stack that should not be accessed with garbage, to detect bad dereferences during copy
+
+	stackCache = 1
+)
+
+const (
+	uintptrMask = 1<<(8*sys.PtrSize) - 1
+	poisonStack = uintptrMask & 0x6868686868686868
+
+	// Goroutine preemption request.
+	// Stored into g->stackguard0 to cause split stack check failure.
+	// Must be greater than any real sp.
+	// 0xfffffade in hex.
+	stackPreempt = uintptrMask & -1314
+
+	// Thread is forking.
+	// Stored into g->stackguard0 to cause split stack check failure.
+	// Must be greater than any real sp.
+	stackFork = uintptrMask & -1234
+)
+
+// Global pool of spans that have free stacks.
+// Stacks are assigned an order according to size.
+//     order = log_2(size/FixedStack)
+// There is a free list for each order.
+// TODO: one lock per order?
+var stackpool [_NumStackOrders]mSpanList
+var stackpoolmu mutex
+
+// Global pool of large stack spans.
+var stackLarge struct {
+	lock mutex
+	free [_MHeapMap_Bits]mSpanList // free lists by log_2(s.npages)
+}
+
+// Cached value of haveexperiment("framepointer")
+var framepointer_enabled bool
+
+func stackinit() {
+	if _StackCacheSize&_PageMask != 0 {
+		throw("cache size must be a multiple of page size")
+	}
+	for i := range stackpool {
+		stackpool[i].init()
+	}
+	for i := range stackLarge.free {
+		stackLarge.free[i].init()
+	}
+}
+
+// stacklog2 returns ⌊log_2(n)⌋.
+func stacklog2(n uintptr) int {
+	log2 := 0
+	for n > 1 {
+		n >>= 1
+		log2++
+	}
+	return log2
+}
+
+// Allocates a stack from the free pool.  Must be called with
+// stackpoolmu held.
+func stackpoolalloc(order uint8) gclinkptr {
+	list := &stackpool[order]
+	s := list.first
+	if s == nil {
+		// no free stacks.  Allocate another span worth.
+		s = mheap_.allocStack(_StackCacheSize >> _PageShift)
+		if s == nil {
+			throw("out of memory")
+		}
+		if s.ref != 0 {
+			throw("bad ref")
+		}
+		if s.freelist.ptr() != nil {
+			throw("bad freelist")
+		}
+		for i := uintptr(0); i < _StackCacheSize; i += _FixedStack << order {
+			x := gclinkptr(uintptr(s.start)<<_PageShift + i)
+			x.ptr().next = s.freelist
+			s.freelist = x
+		}
+		list.insert(s)
+	}
+	x := s.freelist
+	if x.ptr() == nil {
+		throw("span has no free stacks")
+	}
+	s.freelist = x.ptr().next
+	s.ref++
+	if s.freelist.ptr() == nil {
+		// all stacks in s are allocated.
+		list.remove(s)
+	}
+	return x
+}
+
+// Adds stack x to the free pool.  Must be called with stackpoolmu held.
+func stackpoolfree(x gclinkptr, order uint8) {
+	s := mheap_.lookup(unsafe.Pointer(x))
+	if s.state != _MSpanStack {
+		throw("freeing stack not in a stack span")
+	}
+	if s.freelist.ptr() == nil {
+		// s will now have a free stack
+		stackpool[order].insert(s)
+	}
+	x.ptr().next = s.freelist
+	s.freelist = x
+	s.ref--
+	if gcphase == _GCoff && s.ref == 0 {
+		// Span is completely free. Return it to the heap
+		// immediately if we're sweeping.
+		//
+		// If GC is active, we delay the free until the end of
+		// GC to avoid the following type of situation:
+		//
+		// 1) GC starts, scans a SudoG but does not yet mark the SudoG.elem pointer
+		// 2) The stack that pointer points to is copied
+		// 3) The old stack is freed
+		// 4) The containing span is marked free
+		// 5) GC attempts to mark the SudoG.elem pointer. The
+		//    marking fails because the pointer looks like a
+		//    pointer into a free span.
+		//
+		// By not freeing, we prevent step #4 until GC is done.
+		stackpool[order].remove(s)
+		s.freelist = 0
+		mheap_.freeStack(s)
+	}
+}
+
+// stackcacherefill/stackcacherelease implement a global pool of stack segments.
+// The pool is required to prevent unlimited growth of per-thread caches.
+func stackcacherefill(c *mcache, order uint8) {
+	if stackDebug >= 1 {
+		print("stackcacherefill order=", order, "\n")
+	}
+
+	// Grab some stacks from the global cache.
+	// Grab half of the allowed capacity (to prevent thrashing).
+	var list gclinkptr
+	var size uintptr
+	lock(&stackpoolmu)
+	for size < _StackCacheSize/2 {
+		x := stackpoolalloc(order)
+		x.ptr().next = list
+		list = x
+		size += _FixedStack << order
+	}
+	unlock(&stackpoolmu)
+	c.stackcache[order].list = list
+	c.stackcache[order].size = size
+}
+
+func stackcacherelease(c *mcache, order uint8) {
+	if stackDebug >= 1 {
+		print("stackcacherelease order=", order, "\n")
+	}
+	x := c.stackcache[order].list
+	size := c.stackcache[order].size
+	lock(&stackpoolmu)
+	for size > _StackCacheSize/2 {
+		y := x.ptr().next
+		stackpoolfree(x, order)
+		x = y
+		size -= _FixedStack << order
+	}
+	unlock(&stackpoolmu)
+	c.stackcache[order].list = x
+	c.stackcache[order].size = size
+}
+
+func stackcache_clear(c *mcache) {
+	if stackDebug >= 1 {
+		print("stackcache clear\n")
+	}
+	lock(&stackpoolmu)
+	for order := uint8(0); order < _NumStackOrders; order++ {
+		x := c.stackcache[order].list
+		for x.ptr() != nil {
+			y := x.ptr().next
+			stackpoolfree(x, order)
+			x = y
+		}
+		c.stackcache[order].list = 0
+		c.stackcache[order].size = 0
+	}
+	unlock(&stackpoolmu)
+}
+
+func stackalloc(n uint32) (stack, []stkbar) {
+	// Stackalloc must be called on scheduler stack, so that we
+	// never try to grow the stack during the code that stackalloc runs.
+	// Doing so would cause a deadlock (issue 1547).
+	thisg := getg()
+	if thisg != thisg.m.g0 {
+		throw("stackalloc not on scheduler stack")
+	}
+	if n&(n-1) != 0 {
+		throw("stack size not a power of 2")
+	}
+	if stackDebug >= 1 {
+		print("stackalloc ", n, "\n")
+	}
+
+	// Compute the size of stack barrier array.
+	maxstkbar := gcMaxStackBarriers(int(n))
+	nstkbar := unsafe.Sizeof(stkbar{}) * uintptr(maxstkbar)
+
+	if debug.efence != 0 || stackFromSystem != 0 {
+		v := sysAlloc(round(uintptr(n), _PageSize), &memstats.stacks_sys)
+		if v == nil {
+			throw("out of memory (stackalloc)")
+		}
+		top := uintptr(n) - nstkbar
+		stkbarSlice := slice{add(v, top), 0, maxstkbar}
+		return stack{uintptr(v), uintptr(v) + top}, *(*[]stkbar)(unsafe.Pointer(&stkbarSlice))
+	}
+
+	// Small stacks are allocated with a fixed-size free-list allocator.
+	// If we need a stack of a bigger size, we fall back on allocating
+	// a dedicated span.
+	var v unsafe.Pointer
+	if stackCache != 0 && n < _FixedStack<<_NumStackOrders && n < _StackCacheSize {
+		order := uint8(0)
+		n2 := n
+		for n2 > _FixedStack {
+			order++
+			n2 >>= 1
+		}
+		var x gclinkptr
+		c := thisg.m.mcache
+		if c == nil || thisg.m.preemptoff != "" || thisg.m.helpgc != 0 {
+			// c == nil can happen in the guts of exitsyscall or
+			// procresize. Just get a stack from the global pool.
+			// Also don't touch stackcache during gc
+			// as it's flushed concurrently.
+			lock(&stackpoolmu)
+			x = stackpoolalloc(order)
+			unlock(&stackpoolmu)
+		} else {
+			x = c.stackcache[order].list
+			if x.ptr() == nil {
+				stackcacherefill(c, order)
+				x = c.stackcache[order].list
+			}
+			c.stackcache[order].list = x.ptr().next
+			c.stackcache[order].size -= uintptr(n)
+		}
+		v = unsafe.Pointer(x)
+	} else {
+		var s *mspan
+		npage := uintptr(n) >> _PageShift
+		log2npage := stacklog2(npage)
+
+		// Try to get a stack from the large stack cache.
+		lock(&stackLarge.lock)
+		if !stackLarge.free[log2npage].isEmpty() {
+			s = stackLarge.free[log2npage].first
+			stackLarge.free[log2npage].remove(s)
+		}
+		unlock(&stackLarge.lock)
+
+		if s == nil {
+			// Allocate a new stack from the heap.
+			s = mheap_.allocStack(npage)
+			if s == nil {
+				throw("out of memory")
+			}
+		}
+		v = unsafe.Pointer(s.start << _PageShift)
+	}
+
+	if raceenabled {
+		racemalloc(v, uintptr(n))
+	}
+	if msanenabled {
+		msanmalloc(v, uintptr(n))
+	}
+	if stackDebug >= 1 {
+		print("  allocated ", v, "\n")
+	}
+	top := uintptr(n) - nstkbar
+	stkbarSlice := slice{add(v, top), 0, maxstkbar}
+	return stack{uintptr(v), uintptr(v) + top}, *(*[]stkbar)(unsafe.Pointer(&stkbarSlice))
+}
+
+func stackfree(stk stack, n uintptr) {
+	gp := getg()
+	v := unsafe.Pointer(stk.lo)
+	if n&(n-1) != 0 {
+		throw("stack not a power of 2")
+	}
+	if stk.lo+n < stk.hi {
+		throw("bad stack size")
+	}
+	if stackDebug >= 1 {
+		println("stackfree", v, n)
+		memclr(v, n) // for testing, clobber stack data
+	}
+	if debug.efence != 0 || stackFromSystem != 0 {
+		if debug.efence != 0 || stackFaultOnFree != 0 {
+			sysFault(v, n)
+		} else {
+			sysFree(v, n, &memstats.stacks_sys)
+		}
+		return
+	}
+	if msanenabled {
+		msanfree(v, n)
+	}
+	if stackCache != 0 && n < _FixedStack<<_NumStackOrders && n < _StackCacheSize {
+		order := uint8(0)
+		n2 := n
+		for n2 > _FixedStack {
+			order++
+			n2 >>= 1
+		}
+		x := gclinkptr(v)
+		c := gp.m.mcache
+		if c == nil || gp.m.preemptoff != "" || gp.m.helpgc != 0 {
+			lock(&stackpoolmu)
+			stackpoolfree(x, order)
+			unlock(&stackpoolmu)
+		} else {
+			if c.stackcache[order].size >= _StackCacheSize {
+				stackcacherelease(c, order)
+			}
+			x.ptr().next = c.stackcache[order].list
+			c.stackcache[order].list = x
+			c.stackcache[order].size += n
+		}
+	} else {
+		s := mheap_.lookup(v)
+		if s.state != _MSpanStack {
+			println(hex(s.start<<_PageShift), v)
+			throw("bad span state")
+		}
+		if gcphase == _GCoff {
+			// Free the stack immediately if we're
+			// sweeping.
+			mheap_.freeStack(s)
+		} else {
+			// If the GC is running, we can't return a
+			// stack span to the heap because it could be
+			// reused as a heap span, and this state
+			// change would race with GC. Add it to the
+			// large stack cache instead.
+			log2npage := stacklog2(s.npages)
+			lock(&stackLarge.lock)
+			stackLarge.free[log2npage].insert(s)
+			unlock(&stackLarge.lock)
+		}
+	}
+}
+
+var maxstacksize uintptr = 1 << 20 // enough until runtime.main sets it for real
+
+var ptrnames = []string{
+	0: "scalar",
+	1: "ptr",
+}
+
+// Stack frame layout
+//
+// (x86)
+// +------------------+
+// | args from caller |
+// +------------------+ <- frame->argp
+// |  return address  |
+// +------------------+
+// |  caller's BP (*) | (*) if framepointer_enabled && varp < sp
+// +------------------+ <- frame->varp
+// |     locals       |
+// +------------------+
+// |  args to callee  |
+// +------------------+ <- frame->sp
+//
+// (arm)
+// +------------------+
+// | args from caller |
+// +------------------+ <- frame->argp
+// | caller's retaddr |
+// +------------------+ <- frame->varp
+// |     locals       |
+// +------------------+
+// |  args to callee  |
+// +------------------+
+// |  return address  |
+// +------------------+ <- frame->sp
+
+type adjustinfo struct {
+	old   stack
+	delta uintptr // ptr distance from old to new stack (newbase - oldbase)
+	cache pcvalueCache
+}
+
+// Adjustpointer checks whether *vpp is in the old stack described by adjinfo.
+// If so, it rewrites *vpp to point into the new stack.
+func adjustpointer(adjinfo *adjustinfo, vpp unsafe.Pointer) {
+	pp := (*unsafe.Pointer)(vpp)
+	p := *pp
+	if stackDebug >= 4 {
+		print("        ", pp, ":", p, "\n")
+	}
+	if adjinfo.old.lo <= uintptr(p) && uintptr(p) < adjinfo.old.hi {
+		*pp = add(p, adjinfo.delta)
+		if stackDebug >= 3 {
+			print("        adjust ptr ", pp, ":", p, " -> ", *pp, "\n")
+		}
+	}
+}
+
+// Information from the compiler about the layout of stack frames.
+type bitvector struct {
+	n        int32 // # of bits
+	bytedata *uint8
+}
+
+type gobitvector struct {
+	n        uintptr
+	bytedata []uint8
+}
+
+func gobv(bv bitvector) gobitvector {
+	return gobitvector{
+		uintptr(bv.n),
+		(*[1 << 30]byte)(unsafe.Pointer(bv.bytedata))[:(bv.n+7)/8],
+	}
+}
+
+func ptrbit(bv *gobitvector, i uintptr) uint8 {
+	return (bv.bytedata[i/8] >> (i % 8)) & 1
+}
+
+// bv describes the memory starting at address scanp.
+// Adjust any pointers contained therein.
+func adjustpointers(scanp unsafe.Pointer, cbv *bitvector, adjinfo *adjustinfo, f *_func) {
+	bv := gobv(*cbv)
+	minp := adjinfo.old.lo
+	maxp := adjinfo.old.hi
+	delta := adjinfo.delta
+	num := uintptr(bv.n)
+	for i := uintptr(0); i < num; i++ {
+		if stackDebug >= 4 {
+			print("        ", add(scanp, i*sys.PtrSize), ":", ptrnames[ptrbit(&bv, i)], ":", hex(*(*uintptr)(add(scanp, i*sys.PtrSize))), " # ", i, " ", bv.bytedata[i/8], "\n")
+		}
+		if ptrbit(&bv, i) == 1 {
+			pp := (*uintptr)(add(scanp, i*sys.PtrSize))
+			p := *pp
+			if f != nil && 0 < p && p < _PageSize && debug.invalidptr != 0 || p == poisonStack {
+				// Looks like a junk value in a pointer slot.
+				// Live analysis wrong?
+				getg().m.traceback = 2
+				print("runtime: bad pointer in frame ", funcname(f), " at ", pp, ": ", hex(p), "\n")
+				throw("invalid stack pointer")
+			}
+			if minp <= p && p < maxp {
+				if stackDebug >= 3 {
+					print("adjust ptr ", p, " ", funcname(f), "\n")
+				}
+				*pp = p + delta
+			}
+		}
+	}
+}
+
+// Note: the argument/return area is adjusted by the callee.
+func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
+	adjinfo := (*adjustinfo)(arg)
+	targetpc := frame.continpc
+	if targetpc == 0 {
+		// Frame is dead.
+		return true
+	}
+	f := frame.fn
+	if stackDebug >= 2 {
+		print("    adjusting ", funcname(f), " frame=[", hex(frame.sp), ",", hex(frame.fp), "] pc=", hex(frame.pc), " continpc=", hex(frame.continpc), "\n")
+	}
+	if f.entry == systemstack_switchPC {
+		// A special routine at the bottom of stack of a goroutine that does an systemstack call.
+		// We will allow it to be copied even though we don't
+		// have full GC info for it (because it is written in asm).
+		return true
+	}
+	if targetpc != f.entry {
+		targetpc--
+	}
+	pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc, &adjinfo.cache)
+	if pcdata == -1 {
+		pcdata = 0 // in prologue
+	}
+
+	// Adjust local variables if stack frame has been allocated.
+	size := frame.varp - frame.sp
+	var minsize uintptr
+	switch sys.TheChar {
+	case '7':
+		minsize = sys.SpAlign
+	default:
+		minsize = sys.MinFrameSize
+	}
+	if size > minsize {
+		var bv bitvector
+		stackmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
+		if stackmap == nil || stackmap.n <= 0 {
+			print("runtime: frame ", funcname(f), " untyped locals ", hex(frame.varp-size), "+", hex(size), "\n")
+			throw("missing stackmap")
+		}
+		// Locals bitmap information, scan just the pointers in locals.
+		if pcdata < 0 || pcdata >= stackmap.n {
+			// don't know where we are
+			print("runtime: pcdata is ", pcdata, " and ", stackmap.n, " locals stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n")
+			throw("bad symbol table")
+		}
+		bv = stackmapdata(stackmap, pcdata)
+		size = uintptr(bv.n) * sys.PtrSize
+		if stackDebug >= 3 {
+			print("      locals ", pcdata, "/", stackmap.n, " ", size/sys.PtrSize, " words ", bv.bytedata, "\n")
+		}
+		adjustpointers(unsafe.Pointer(frame.varp-size), &bv, adjinfo, f)
+	}
+
+	// Adjust saved base pointer if there is one.
+	if sys.TheChar == '6' && frame.argp-frame.varp == 2*sys.RegSize {
+		if !framepointer_enabled {
+			print("runtime: found space for saved base pointer, but no framepointer experiment\n")
+			print("argp=", hex(frame.argp), " varp=", hex(frame.varp), "\n")
+			throw("bad frame layout")
+		}
+		if stackDebug >= 3 {
+			print("      saved bp\n")
+		}
+		adjustpointer(adjinfo, unsafe.Pointer(frame.varp))
+	}
+
+	// Adjust arguments.
+	if frame.arglen > 0 {
+		var bv bitvector
+		if frame.argmap != nil {
+			bv = *frame.argmap
+		} else {
+			stackmap := (*stackmap)(funcdata(f, _FUNCDATA_ArgsPointerMaps))
+			if stackmap == nil || stackmap.n <= 0 {
+				print("runtime: frame ", funcname(f), " untyped args ", frame.argp, "+", uintptr(frame.arglen), "\n")
+				throw("missing stackmap")
+			}
+			if pcdata < 0 || pcdata >= stackmap.n {
+				// don't know where we are
+				print("runtime: pcdata is ", pcdata, " and ", stackmap.n, " args stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n")
+				throw("bad symbol table")
+			}
+			bv = stackmapdata(stackmap, pcdata)
+		}
+		if stackDebug >= 3 {
+			print("      args\n")
+		}
+		adjustpointers(unsafe.Pointer(frame.argp), &bv, adjinfo, nil)
+	}
+	return true
+}
+
+func adjustctxt(gp *g, adjinfo *adjustinfo) {
+	adjustpointer(adjinfo, unsafe.Pointer(&gp.sched.ctxt))
+}
+
+func adjustdefers(gp *g, adjinfo *adjustinfo) {
+	// Adjust defer argument blocks the same way we adjust active stack frames.
+	tracebackdefers(gp, adjustframe, noescape(unsafe.Pointer(adjinfo)))
+
+	// Adjust pointers in the Defer structs.
+	// Defer structs themselves are never on the stack.
+	for d := gp._defer; d != nil; d = d.link {
+		adjustpointer(adjinfo, unsafe.Pointer(&d.fn))
+		adjustpointer(adjinfo, unsafe.Pointer(&d.sp))
+		adjustpointer(adjinfo, unsafe.Pointer(&d._panic))
+	}
+}
+
+func adjustpanics(gp *g, adjinfo *adjustinfo) {
+	// Panics are on stack and already adjusted.
+	// Update pointer to head of list in G.
+	adjustpointer(adjinfo, unsafe.Pointer(&gp._panic))
+}
+
+func adjustsudogs(gp *g, adjinfo *adjustinfo) {
+	// the data elements pointed to by a SudoG structure
+	// might be in the stack.
+	for s := gp.waiting; s != nil; s = s.waitlink {
+		adjustpointer(adjinfo, unsafe.Pointer(&s.elem))
+		adjustpointer(adjinfo, unsafe.Pointer(&s.selectdone))
+	}
+}
+
+func adjuststkbar(gp *g, adjinfo *adjustinfo) {
+	for i := int(gp.stkbarPos); i < len(gp.stkbar); i++ {
+		adjustpointer(adjinfo, unsafe.Pointer(&gp.stkbar[i].savedLRPtr))
+	}
+}
+
+func fillstack(stk stack, b byte) {
+	for p := stk.lo; p < stk.hi; p++ {
+		*(*byte)(unsafe.Pointer(p)) = b
+	}
+}
+
+// Copies gp's stack to a new stack of a different size.
+// Caller must have changed gp status to Gcopystack.
+func copystack(gp *g, newsize uintptr) {
+	if gp.syscallsp != 0 {
+		throw("stack growth not allowed in system call")
+	}
+	old := gp.stack
+	if old.lo == 0 {
+		throw("nil stackbase")
+	}
+	used := old.hi - gp.sched.sp
+
+	// allocate new stack
+	new, newstkbar := stackalloc(uint32(newsize))
+	if stackPoisonCopy != 0 {
+		fillstack(new, 0xfd)
+	}
+	if stackDebug >= 1 {
+		print("copystack gp=", gp, " [", hex(old.lo), " ", hex(old.hi-used), " ", hex(old.hi), "]/", gp.stackAlloc, " -> [", hex(new.lo), " ", hex(new.hi-used), " ", hex(new.hi), "]/", newsize, "\n")
+	}
+
+	// Disallow sigprof scans of this stack and block if there's
+	// one in progress.
+	gcLockStackBarriers(gp)
+
+	// adjust pointers in the to-be-copied frames
+	var adjinfo adjustinfo
+	adjinfo.old = old
+	adjinfo.delta = new.hi - old.hi
+	gentraceback(^uintptr(0), ^uintptr(0), 0, gp, 0, nil, 0x7fffffff, adjustframe, noescape(unsafe.Pointer(&adjinfo)), 0)
+
+	// adjust other miscellaneous things that have pointers into stacks.
+	adjustctxt(gp, &adjinfo)
+	adjustdefers(gp, &adjinfo)
+	adjustpanics(gp, &adjinfo)
+	adjustsudogs(gp, &adjinfo)
+	adjuststkbar(gp, &adjinfo)
+
+	// copy the stack to the new location
+	if stackPoisonCopy != 0 {
+		fillstack(new, 0xfb)
+	}
+	memmove(unsafe.Pointer(new.hi-used), unsafe.Pointer(old.hi-used), used)
+
+	// copy old stack barriers to new stack barrier array
+	newstkbar = newstkbar[:len(gp.stkbar)]
+	copy(newstkbar, gp.stkbar)
+
+	// Swap out old stack for new one
+	gp.stack = new
+	gp.stackguard0 = new.lo + _StackGuard // NOTE: might clobber a preempt request
+	gp.sched.sp = new.hi - used
+	oldsize := gp.stackAlloc
+	gp.stackAlloc = newsize
+	gp.stkbar = newstkbar
+	gp.stktopsp += adjinfo.delta
+
+	gcUnlockStackBarriers(gp)
+
+	// free old stack
+	if stackPoisonCopy != 0 {
+		fillstack(old, 0xfc)
+	}
+	stackfree(old, oldsize)
+}
+
+// round x up to a power of 2.
+func round2(x int32) int32 {
+	s := uint(0)
+	for 1<<s < x {
+		s++
+	}
+	return 1 << s
+}
+
+// Called from runtime·morestack when more stack is needed.
+// Allocate larger stack and relocate to new stack.
+// Stack growth is multiplicative, for constant amortized cost.
+//
+// g->atomicstatus will be Grunning or Gscanrunning upon entry.
+// If the GC is trying to stop this g then it will set preemptscan to true.
+func newstack() {
+	thisg := getg()
+	// TODO: double check all gp. shouldn't be getg().
+	if thisg.m.morebuf.g.ptr().stackguard0 == stackFork {
+		throw("stack growth after fork")
+	}
+	if thisg.m.morebuf.g.ptr() != thisg.m.curg {
+		print("runtime: newstack called from g=", hex(thisg.m.morebuf.g), "\n"+"\tm=", thisg.m, " m->curg=", thisg.m.curg, " m->g0=", thisg.m.g0, " m->gsignal=", thisg.m.gsignal, "\n")
+		morebuf := thisg.m.morebuf
+		traceback(morebuf.pc, morebuf.sp, morebuf.lr, morebuf.g.ptr())
+		throw("runtime: wrong goroutine in newstack")
+	}
+	if thisg.m.curg.throwsplit {
+		gp := thisg.m.curg
+		// Update syscallsp, syscallpc in case traceback uses them.
+		morebuf := thisg.m.morebuf
+		gp.syscallsp = morebuf.sp
+		gp.syscallpc = morebuf.pc
+		print("runtime: newstack sp=", hex(gp.sched.sp), " stack=[", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n",
+			"\tmorebuf={pc:", hex(morebuf.pc), " sp:", hex(morebuf.sp), " lr:", hex(morebuf.lr), "}\n",
+			"\tsched={pc:", hex(gp.sched.pc), " sp:", hex(gp.sched.sp), " lr:", hex(gp.sched.lr), " ctxt:", gp.sched.ctxt, "}\n")
+
+		traceback(morebuf.pc, morebuf.sp, morebuf.lr, gp)
+		throw("runtime: stack split at bad time")
+	}
+
+	gp := thisg.m.curg
+	morebuf := thisg.m.morebuf
+	thisg.m.morebuf.pc = 0
+	thisg.m.morebuf.lr = 0
+	thisg.m.morebuf.sp = 0
+	thisg.m.morebuf.g = 0
+	rewindmorestack(&gp.sched)
+
+	// NOTE: stackguard0 may change underfoot, if another thread
+	// is about to try to preempt gp. Read it just once and use that same
+	// value now and below.
+	preempt := atomic.Loaduintptr(&gp.stackguard0) == stackPreempt
+
+	// Be conservative about where we preempt.
+	// We are interested in preempting user Go code, not runtime code.
+	// If we're holding locks, mallocing, or preemption is disabled, don't
+	// preempt.
+	// This check is very early in newstack so that even the status change
+	// from Grunning to Gwaiting and back doesn't happen in this case.
+	// That status change by itself can be viewed as a small preemption,
+	// because the GC might change Gwaiting to Gscanwaiting, and then
+	// this goroutine has to wait for the GC to finish before continuing.
+	// If the GC is in some way dependent on this goroutine (for example,
+	// it needs a lock held by the goroutine), that small preemption turns
+	// into a real deadlock.
+	if preempt {
+		if thisg.m.locks != 0 || thisg.m.mallocing != 0 || thisg.m.preemptoff != "" || thisg.m.p.ptr().status != _Prunning {
+			// Let the goroutine keep running for now.
+			// gp->preempt is set, so it will be preempted next time.
+			gp.stackguard0 = gp.stack.lo + _StackGuard
+			gogo(&gp.sched) // never return
+		}
+	}
+
+	// The goroutine must be executing in order to call newstack,
+	// so it must be Grunning (or Gscanrunning).
+	casgstatus(gp, _Grunning, _Gwaiting)
+	gp.waitreason = "stack growth"
+
+	if gp.stack.lo == 0 {
+		throw("missing stack in newstack")
+	}
+	sp := gp.sched.sp
+	if sys.TheChar == '6' || sys.TheChar == '8' {
+		// The call to morestack cost a word.
+		sp -= sys.PtrSize
+	}
+	if stackDebug >= 1 || sp < gp.stack.lo {
+		print("runtime: newstack sp=", hex(sp), " stack=[", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n",
+			"\tmorebuf={pc:", hex(morebuf.pc), " sp:", hex(morebuf.sp), " lr:", hex(morebuf.lr), "}\n",
+			"\tsched={pc:", hex(gp.sched.pc), " sp:", hex(gp.sched.sp), " lr:", hex(gp.sched.lr), " ctxt:", gp.sched.ctxt, "}\n")
+	}
+	if sp < gp.stack.lo {
+		print("runtime: gp=", gp, ", gp->status=", hex(readgstatus(gp)), "\n ")
+		print("runtime: split stack overflow: ", hex(sp), " < ", hex(gp.stack.lo), "\n")
+		throw("runtime: split stack overflow")
+	}
+
+	if gp.sched.ctxt != nil {
+		// morestack wrote sched.ctxt on its way in here,
+		// without a write barrier. Run the write barrier now.
+		// It is not possible to be preempted between then
+		// and now, so it's okay.
+		writebarrierptr_nostore((*uintptr)(unsafe.Pointer(&gp.sched.ctxt)), uintptr(gp.sched.ctxt))
+	}
+
+	if preempt {
+		if gp == thisg.m.g0 {
+			throw("runtime: preempt g0")
+		}
+		if thisg.m.p == 0 && thisg.m.locks == 0 {
+			throw("runtime: g is running but p is not")
+		}
+		if gp.preemptscan {
+			for !castogscanstatus(gp, _Gwaiting, _Gscanwaiting) {
+				// Likely to be racing with the GC as
+				// it sees a _Gwaiting and does the
+				// stack scan. If so, gcworkdone will
+				// be set and gcphasework will simply
+				// return.
+			}
+			if !gp.gcscandone {
+				scanstack(gp)
+				gp.gcscandone = true
+			}
+			gp.preemptscan = false
+			gp.preempt = false
+			casfrom_Gscanstatus(gp, _Gscanwaiting, _Gwaiting)
+			casgstatus(gp, _Gwaiting, _Grunning)
+			gp.stackguard0 = gp.stack.lo + _StackGuard
+			gogo(&gp.sched) // never return
+		}
+
+		// Act like goroutine called runtime.Gosched.
+		casgstatus(gp, _Gwaiting, _Grunning)
+		gopreempt_m(gp) // never return
+	}
+
+	// Allocate a bigger segment and move the stack.
+	oldsize := int(gp.stackAlloc)
+	newsize := oldsize * 2
+	if uintptr(newsize) > maxstacksize {
+		print("runtime: goroutine stack exceeds ", maxstacksize, "-byte limit\n")
+		throw("stack overflow")
+	}
+
+	casgstatus(gp, _Gwaiting, _Gcopystack)
+
+	// The concurrent GC will not scan the stack while we are doing the copy since
+	// the gp is in a Gcopystack status.
+	copystack(gp, uintptr(newsize))
+	if stackDebug >= 1 {
+		print("stack grow done\n")
+	}
+	casgstatus(gp, _Gcopystack, _Grunning)
+	gogo(&gp.sched)
+}
+
+//go:nosplit
+func nilfunc() {
+	*(*uint8)(nil) = 0
+}
+
+// adjust Gobuf as if it executed a call to fn
+// and then did an immediate gosave.
+func gostartcallfn(gobuf *gobuf, fv *funcval) {
+	var fn unsafe.Pointer
+	if fv != nil {
+		fn = unsafe.Pointer(fv.fn)
+	} else {
+		fn = unsafe.Pointer(funcPC(nilfunc))
+	}
+	gostartcall(gobuf, fn, unsafe.Pointer(fv))
+}
+
+// Maybe shrink the stack being used by gp.
+// Called at garbage collection time.
+func shrinkstack(gp *g) {
+	if readgstatus(gp) == _Gdead {
+		if gp.stack.lo != 0 {
+			// Free whole stack - it will get reallocated
+			// if G is used again.
+			stackfree(gp.stack, gp.stackAlloc)
+			gp.stack.lo = 0
+			gp.stack.hi = 0
+			gp.stkbar = nil
+			gp.stkbarPos = 0
+		}
+		return
+	}
+	if gp.stack.lo == 0 {
+		throw("missing stack in shrinkstack")
+	}
+
+	if debug.gcshrinkstackoff > 0 {
+		return
+	}
+
+	oldsize := gp.stackAlloc
+	newsize := oldsize / 2
+	// Don't shrink the allocation below the minimum-sized stack
+	// allocation.
+	if newsize < _FixedStack {
+		return
+	}
+	// Compute how much of the stack is currently in use and only
+	// shrink the stack if gp is using less than a quarter of its
+	// current stack. The currently used stack includes everything
+	// down to the SP plus the stack guard space that ensures
+	// there's room for nosplit functions.
+	avail := gp.stack.hi - gp.stack.lo
+	if used := gp.stack.hi - gp.sched.sp + _StackLimit; used >= avail/4 {
+		return
+	}
+
+	// We can't copy the stack if we're in a syscall.
+	// The syscall might have pointers into the stack.
+	if gp.syscallsp != 0 {
+		return
+	}
+	if sys.GoosWindows != 0 && gp.m != nil && gp.m.libcallsp != 0 {
+		return
+	}
+
+	if stackDebug > 0 {
+		print("shrinking stack ", oldsize, "->", newsize, "\n")
+	}
+
+	oldstatus := casgcopystack(gp)
+	copystack(gp, newsize)
+	casgstatus(gp, _Gcopystack, oldstatus)
+}
+
+// freeStackSpans frees unused stack spans at the end of GC.
+func freeStackSpans() {
+	lock(&stackpoolmu)
+
+	// Scan stack pools for empty stack spans.
+	for order := range stackpool {
+		list := &stackpool[order]
+		for s := list.first; s != nil; {
+			next := s.next
+			if s.ref == 0 {
+				list.remove(s)
+				s.freelist = 0
+				mheap_.freeStack(s)
+			}
+			s = next
+		}
+	}
+
+	unlock(&stackpoolmu)
+
+	// Free large stack spans.
+	lock(&stackLarge.lock)
+	for i := range stackLarge.free {
+		for s := stackLarge.free[i].first; s != nil; {
+			next := s.next
+			stackLarge.free[i].remove(s)
+			mheap_.freeStack(s)
+			s = next
+		}
+	}
+	unlock(&stackLarge.lock)
+}
+
+//go:nosplit
+func morestackc() {
+	systemstack(func() {
+		throw("attempt to execute C code on Go stack")
+	})
+}
diff --git a/src/runtime/stack1.go b/src/runtime/stack1.go
deleted file mode 100644
index 19634ef..0000000
--- a/src/runtime/stack1.go
+++ /dev/null
@@ -1,923 +0,0 @@
-// Copyright 2013 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 runtime
-
-import "unsafe"
-
-const (
-	// stackDebug == 0: no logging
-	//            == 1: logging of per-stack operations
-	//            == 2: logging of per-frame operations
-	//            == 3: logging of per-word updates
-	//            == 4: logging of per-word reads
-	stackDebug       = 0
-	stackFromSystem  = 0 // allocate stacks from system memory instead of the heap
-	stackFaultOnFree = 0 // old stacks are mapped noaccess to detect use after free
-	stackPoisonCopy  = 0 // fill stack that should not be accessed with garbage, to detect bad dereferences during copy
-
-	stackCache = 1
-)
-
-const (
-	uintptrMask = 1<<(8*ptrSize) - 1
-	poisonStack = uintptrMask & 0x6868686868686868
-
-	// Goroutine preemption request.
-	// Stored into g->stackguard0 to cause split stack check failure.
-	// Must be greater than any real sp.
-	// 0xfffffade in hex.
-	stackPreempt = uintptrMask & -1314
-
-	// Thread is forking.
-	// Stored into g->stackguard0 to cause split stack check failure.
-	// Must be greater than any real sp.
-	stackFork = uintptrMask & -1234
-)
-
-// Global pool of spans that have free stacks.
-// Stacks are assigned an order according to size.
-//     order = log_2(size/FixedStack)
-// There is a free list for each order.
-// TODO: one lock per order?
-var stackpool [_NumStackOrders]mspan
-var stackpoolmu mutex
-
-// List of stack spans to be freed at the end of GC. Protected by
-// stackpoolmu.
-var stackFreeQueue mspan
-
-// Cached value of haveexperiment("framepointer")
-var framepointer_enabled bool
-
-func stackinit() {
-	if _StackCacheSize&_PageMask != 0 {
-		throw("cache size must be a multiple of page size")
-	}
-	for i := range stackpool {
-		mSpanList_Init(&stackpool[i])
-	}
-	mSpanList_Init(&stackFreeQueue)
-}
-
-// Allocates a stack from the free pool.  Must be called with
-// stackpoolmu held.
-func stackpoolalloc(order uint8) gclinkptr {
-	list := &stackpool[order]
-	s := list.next
-	if s == list {
-		// no free stacks.  Allocate another span worth.
-		s = mHeap_AllocStack(&mheap_, _StackCacheSize>>_PageShift)
-		if s == nil {
-			throw("out of memory")
-		}
-		if s.ref != 0 {
-			throw("bad ref")
-		}
-		if s.freelist.ptr() != nil {
-			throw("bad freelist")
-		}
-		for i := uintptr(0); i < _StackCacheSize; i += _FixedStack << order {
-			x := gclinkptr(uintptr(s.start)<<_PageShift + i)
-			x.ptr().next = s.freelist
-			s.freelist = x
-		}
-		mSpanList_Insert(list, s)
-	}
-	x := s.freelist
-	if x.ptr() == nil {
-		throw("span has no free stacks")
-	}
-	s.freelist = x.ptr().next
-	s.ref++
-	if s.freelist.ptr() == nil {
-		// all stacks in s are allocated.
-		mSpanList_Remove(s)
-	}
-	return x
-}
-
-// Adds stack x to the free pool.  Must be called with stackpoolmu held.
-func stackpoolfree(x gclinkptr, order uint8) {
-	s := mHeap_Lookup(&mheap_, (unsafe.Pointer)(x))
-	if s.state != _MSpanStack {
-		throw("freeing stack not in a stack span")
-	}
-	if s.freelist.ptr() == nil {
-		// s will now have a free stack
-		mSpanList_Insert(&stackpool[order], s)
-	}
-	x.ptr().next = s.freelist
-	s.freelist = x
-	s.ref--
-	if gcphase == _GCoff && s.ref == 0 {
-		// Span is completely free. Return it to the heap
-		// immediately if we're sweeping.
-		//
-		// If GC is active, we delay the free until the end of
-		// GC to avoid the following type of situation:
-		//
-		// 1) GC starts, scans a SudoG but does not yet mark the SudoG.elem pointer
-		// 2) The stack that pointer points to is copied
-		// 3) The old stack is freed
-		// 4) The containing span is marked free
-		// 5) GC attempts to mark the SudoG.elem pointer. The
-		//    marking fails because the pointer looks like a
-		//    pointer into a free span.
-		//
-		// By not freeing, we prevent step #4 until GC is done.
-		mSpanList_Remove(s)
-		s.freelist = 0
-		mHeap_FreeStack(&mheap_, s)
-	}
-}
-
-// stackcacherefill/stackcacherelease implement a global pool of stack segments.
-// The pool is required to prevent unlimited growth of per-thread caches.
-func stackcacherefill(c *mcache, order uint8) {
-	if stackDebug >= 1 {
-		print("stackcacherefill order=", order, "\n")
-	}
-
-	// Grab some stacks from the global cache.
-	// Grab half of the allowed capacity (to prevent thrashing).
-	var list gclinkptr
-	var size uintptr
-	lock(&stackpoolmu)
-	for size < _StackCacheSize/2 {
-		x := stackpoolalloc(order)
-		x.ptr().next = list
-		list = x
-		size += _FixedStack << order
-	}
-	unlock(&stackpoolmu)
-	c.stackcache[order].list = list
-	c.stackcache[order].size = size
-}
-
-func stackcacherelease(c *mcache, order uint8) {
-	if stackDebug >= 1 {
-		print("stackcacherelease order=", order, "\n")
-	}
-	x := c.stackcache[order].list
-	size := c.stackcache[order].size
-	lock(&stackpoolmu)
-	for size > _StackCacheSize/2 {
-		y := x.ptr().next
-		stackpoolfree(x, order)
-		x = y
-		size -= _FixedStack << order
-	}
-	unlock(&stackpoolmu)
-	c.stackcache[order].list = x
-	c.stackcache[order].size = size
-}
-
-func stackcache_clear(c *mcache) {
-	if stackDebug >= 1 {
-		print("stackcache clear\n")
-	}
-	lock(&stackpoolmu)
-	for order := uint8(0); order < _NumStackOrders; order++ {
-		x := c.stackcache[order].list
-		for x.ptr() != nil {
-			y := x.ptr().next
-			stackpoolfree(x, order)
-			x = y
-		}
-		c.stackcache[order].list = 0
-		c.stackcache[order].size = 0
-	}
-	unlock(&stackpoolmu)
-}
-
-func stackalloc(n uint32) (stack, []stkbar) {
-	// Stackalloc must be called on scheduler stack, so that we
-	// never try to grow the stack during the code that stackalloc runs.
-	// Doing so would cause a deadlock (issue 1547).
-	thisg := getg()
-	if thisg != thisg.m.g0 {
-		throw("stackalloc not on scheduler stack")
-	}
-	if n&(n-1) != 0 {
-		throw("stack size not a power of 2")
-	}
-	if stackDebug >= 1 {
-		print("stackalloc ", n, "\n")
-	}
-
-	// Compute the size of stack barrier array.
-	maxstkbar := gcMaxStackBarriers(int(n))
-	nstkbar := unsafe.Sizeof(stkbar{}) * uintptr(maxstkbar)
-
-	if debug.efence != 0 || stackFromSystem != 0 {
-		v := sysAlloc(round(uintptr(n), _PageSize), &memstats.stacks_sys)
-		if v == nil {
-			throw("out of memory (stackalloc)")
-		}
-		top := uintptr(n) - nstkbar
-		stkbarSlice := slice{add(v, top), 0, maxstkbar}
-		return stack{uintptr(v), uintptr(v) + top}, *(*[]stkbar)(unsafe.Pointer(&stkbarSlice))
-	}
-
-	// Small stacks are allocated with a fixed-size free-list allocator.
-	// If we need a stack of a bigger size, we fall back on allocating
-	// a dedicated span.
-	var v unsafe.Pointer
-	if stackCache != 0 && n < _FixedStack<<_NumStackOrders && n < _StackCacheSize {
-		order := uint8(0)
-		n2 := n
-		for n2 > _FixedStack {
-			order++
-			n2 >>= 1
-		}
-		var x gclinkptr
-		c := thisg.m.mcache
-		if c == nil || thisg.m.preemptoff != "" || thisg.m.helpgc != 0 {
-			// c == nil can happen in the guts of exitsyscall or
-			// procresize. Just get a stack from the global pool.
-			// Also don't touch stackcache during gc
-			// as it's flushed concurrently.
-			lock(&stackpoolmu)
-			x = stackpoolalloc(order)
-			unlock(&stackpoolmu)
-		} else {
-			x = c.stackcache[order].list
-			if x.ptr() == nil {
-				stackcacherefill(c, order)
-				x = c.stackcache[order].list
-			}
-			c.stackcache[order].list = x.ptr().next
-			c.stackcache[order].size -= uintptr(n)
-		}
-		v = (unsafe.Pointer)(x)
-	} else {
-		s := mHeap_AllocStack(&mheap_, round(uintptr(n), _PageSize)>>_PageShift)
-		if s == nil {
-			throw("out of memory")
-		}
-		v = (unsafe.Pointer)(s.start << _PageShift)
-	}
-
-	if raceenabled {
-		racemalloc(v, uintptr(n))
-	}
-	if stackDebug >= 1 {
-		print("  allocated ", v, "\n")
-	}
-	top := uintptr(n) - nstkbar
-	stkbarSlice := slice{add(v, top), 0, maxstkbar}
-	return stack{uintptr(v), uintptr(v) + top}, *(*[]stkbar)(unsafe.Pointer(&stkbarSlice))
-}
-
-func stackfree(stk stack, n uintptr) {
-	gp := getg()
-	v := (unsafe.Pointer)(stk.lo)
-	if n&(n-1) != 0 {
-		throw("stack not a power of 2")
-	}
-	if stk.lo+n < stk.hi {
-		throw("bad stack size")
-	}
-	if stackDebug >= 1 {
-		println("stackfree", v, n)
-		memclr(v, n) // for testing, clobber stack data
-	}
-	if debug.efence != 0 || stackFromSystem != 0 {
-		if debug.efence != 0 || stackFaultOnFree != 0 {
-			sysFault(v, n)
-		} else {
-			sysFree(v, n, &memstats.stacks_sys)
-		}
-		return
-	}
-	if stackCache != 0 && n < _FixedStack<<_NumStackOrders && n < _StackCacheSize {
-		order := uint8(0)
-		n2 := n
-		for n2 > _FixedStack {
-			order++
-			n2 >>= 1
-		}
-		x := gclinkptr(v)
-		c := gp.m.mcache
-		if c == nil || gp.m.preemptoff != "" || gp.m.helpgc != 0 {
-			lock(&stackpoolmu)
-			stackpoolfree(x, order)
-			unlock(&stackpoolmu)
-		} else {
-			if c.stackcache[order].size >= _StackCacheSize {
-				stackcacherelease(c, order)
-			}
-			x.ptr().next = c.stackcache[order].list
-			c.stackcache[order].list = x
-			c.stackcache[order].size += n
-		}
-	} else {
-		s := mHeap_Lookup(&mheap_, v)
-		if s.state != _MSpanStack {
-			println(hex(s.start<<_PageShift), v)
-			throw("bad span state")
-		}
-		if gcphase == _GCoff {
-			// Free the stack immediately if we're
-			// sweeping.
-			mHeap_FreeStack(&mheap_, s)
-		} else {
-			// Otherwise, add it to a list of stack spans
-			// to be freed at the end of GC.
-			//
-			// TODO(austin): Make it possible to re-use
-			// these spans as stacks, like we do for small
-			// stack spans. (See issue #11466.)
-			lock(&stackpoolmu)
-			mSpanList_Insert(&stackFreeQueue, s)
-			unlock(&stackpoolmu)
-		}
-	}
-}
-
-var maxstacksize uintptr = 1 << 20 // enough until runtime.main sets it for real
-
-var ptrnames = []string{
-	0: "scalar",
-	1: "ptr",
-}
-
-// Stack frame layout
-//
-// (x86)
-// +------------------+
-// | args from caller |
-// +------------------+ <- frame->argp
-// |  return address  |
-// +------------------+
-// |  caller's BP (*) | (*) if framepointer_enabled && varp < sp
-// +------------------+ <- frame->varp
-// |     locals       |
-// +------------------+
-// |  args to callee  |
-// +------------------+ <- frame->sp
-//
-// (arm)
-// +------------------+
-// | args from caller |
-// +------------------+ <- frame->argp
-// | caller's retaddr |
-// +------------------+ <- frame->varp
-// |     locals       |
-// +------------------+
-// |  args to callee  |
-// +------------------+
-// |  return address  |
-// +------------------+ <- frame->sp
-
-type adjustinfo struct {
-	old   stack
-	delta uintptr // ptr distance from old to new stack (newbase - oldbase)
-}
-
-// Adjustpointer checks whether *vpp is in the old stack described by adjinfo.
-// If so, it rewrites *vpp to point into the new stack.
-func adjustpointer(adjinfo *adjustinfo, vpp unsafe.Pointer) {
-	pp := (*unsafe.Pointer)(vpp)
-	p := *pp
-	if stackDebug >= 4 {
-		print("        ", pp, ":", p, "\n")
-	}
-	if adjinfo.old.lo <= uintptr(p) && uintptr(p) < adjinfo.old.hi {
-		*pp = add(p, adjinfo.delta)
-		if stackDebug >= 3 {
-			print("        adjust ptr ", pp, ":", p, " -> ", *pp, "\n")
-		}
-	}
-}
-
-// Information from the compiler about the layout of stack frames.
-type bitvector struct {
-	n        int32 // # of bits
-	bytedata *uint8
-}
-
-type gobitvector struct {
-	n        uintptr
-	bytedata []uint8
-}
-
-func gobv(bv bitvector) gobitvector {
-	return gobitvector{
-		uintptr(bv.n),
-		(*[1 << 30]byte)(unsafe.Pointer(bv.bytedata))[:(bv.n+7)/8],
-	}
-}
-
-func ptrbit(bv *gobitvector, i uintptr) uint8 {
-	return (bv.bytedata[i/8] >> (i % 8)) & 1
-}
-
-// bv describes the memory starting at address scanp.
-// Adjust any pointers contained therein.
-func adjustpointers(scanp unsafe.Pointer, cbv *bitvector, adjinfo *adjustinfo, f *_func) {
-	bv := gobv(*cbv)
-	minp := adjinfo.old.lo
-	maxp := adjinfo.old.hi
-	delta := adjinfo.delta
-	num := uintptr(bv.n)
-	for i := uintptr(0); i < num; i++ {
-		if stackDebug >= 4 {
-			print("        ", add(scanp, i*ptrSize), ":", ptrnames[ptrbit(&bv, i)], ":", hex(*(*uintptr)(add(scanp, i*ptrSize))), " # ", i, " ", bv.bytedata[i/8], "\n")
-		}
-		if ptrbit(&bv, i) == 1 {
-			pp := (*uintptr)(add(scanp, i*ptrSize))
-			p := *pp
-			if f != nil && 0 < p && p < _PageSize && debug.invalidptr != 0 || p == poisonStack {
-				// Looks like a junk value in a pointer slot.
-				// Live analysis wrong?
-				getg().m.traceback = 2
-				print("runtime: bad pointer in frame ", funcname(f), " at ", pp, ": ", hex(p), "\n")
-				throw("invalid stack pointer")
-			}
-			if minp <= p && p < maxp {
-				if stackDebug >= 3 {
-					print("adjust ptr ", p, " ", funcname(f), "\n")
-				}
-				*pp = p + delta
-			}
-		}
-	}
-}
-
-// Note: the argument/return area is adjusted by the callee.
-func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
-	adjinfo := (*adjustinfo)(arg)
-	targetpc := frame.continpc
-	if targetpc == 0 {
-		// Frame is dead.
-		return true
-	}
-	f := frame.fn
-	if stackDebug >= 2 {
-		print("    adjusting ", funcname(f), " frame=[", hex(frame.sp), ",", hex(frame.fp), "] pc=", hex(frame.pc), " continpc=", hex(frame.continpc), "\n")
-	}
-	if f.entry == systemstack_switchPC {
-		// A special routine at the bottom of stack of a goroutine that does an systemstack call.
-		// We will allow it to be copied even though we don't
-		// have full GC info for it (because it is written in asm).
-		return true
-	}
-	if targetpc != f.entry {
-		targetpc--
-	}
-	pcdata := pcdatavalue(f, _PCDATA_StackMapIndex, targetpc)
-	if pcdata == -1 {
-		pcdata = 0 // in prologue
-	}
-
-	// Adjust local variables if stack frame has been allocated.
-	size := frame.varp - frame.sp
-	var minsize uintptr
-	switch thechar {
-	case '6', '8':
-		minsize = 0
-	case '7':
-		minsize = spAlign
-	default:
-		minsize = ptrSize
-	}
-	if size > minsize {
-		var bv bitvector
-		stackmap := (*stackmap)(funcdata(f, _FUNCDATA_LocalsPointerMaps))
-		if stackmap == nil || stackmap.n <= 0 {
-			print("runtime: frame ", funcname(f), " untyped locals ", hex(frame.varp-size), "+", hex(size), "\n")
-			throw("missing stackmap")
-		}
-		// Locals bitmap information, scan just the pointers in locals.
-		if pcdata < 0 || pcdata >= stackmap.n {
-			// don't know where we are
-			print("runtime: pcdata is ", pcdata, " and ", stackmap.n, " locals stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n")
-			throw("bad symbol table")
-		}
-		bv = stackmapdata(stackmap, pcdata)
-		size = uintptr(bv.n) * ptrSize
-		if stackDebug >= 3 {
-			print("      locals ", pcdata, "/", stackmap.n, " ", size/ptrSize, " words ", bv.bytedata, "\n")
-		}
-		adjustpointers(unsafe.Pointer(frame.varp-size), &bv, adjinfo, f)
-	}
-
-	// Adjust saved base pointer if there is one.
-	if thechar == '6' && frame.argp-frame.varp == 2*regSize {
-		if !framepointer_enabled {
-			print("runtime: found space for saved base pointer, but no framepointer experiment\n")
-			print("argp=", hex(frame.argp), " varp=", hex(frame.varp), "\n")
-			throw("bad frame layout")
-		}
-		if stackDebug >= 3 {
-			print("      saved bp\n")
-		}
-		adjustpointer(adjinfo, unsafe.Pointer(frame.varp))
-	}
-
-	// Adjust arguments.
-	if frame.arglen > 0 {
-		var bv bitvector
-		if frame.argmap != nil {
-			bv = *frame.argmap
-		} else {
-			stackmap := (*stackmap)(funcdata(f, _FUNCDATA_ArgsPointerMaps))
-			if stackmap == nil || stackmap.n <= 0 {
-				print("runtime: frame ", funcname(f), " untyped args ", frame.argp, "+", uintptr(frame.arglen), "\n")
-				throw("missing stackmap")
-			}
-			if pcdata < 0 || pcdata >= stackmap.n {
-				// don't know where we are
-				print("runtime: pcdata is ", pcdata, " and ", stackmap.n, " args stack map entries for ", funcname(f), " (targetpc=", targetpc, ")\n")
-				throw("bad symbol table")
-			}
-			bv = stackmapdata(stackmap, pcdata)
-		}
-		if stackDebug >= 3 {
-			print("      args\n")
-		}
-		adjustpointers(unsafe.Pointer(frame.argp), &bv, adjinfo, nil)
-	}
-	return true
-}
-
-func adjustctxt(gp *g, adjinfo *adjustinfo) {
-	adjustpointer(adjinfo, (unsafe.Pointer)(&gp.sched.ctxt))
-}
-
-func adjustdefers(gp *g, adjinfo *adjustinfo) {
-	// Adjust defer argument blocks the same way we adjust active stack frames.
-	tracebackdefers(gp, adjustframe, noescape(unsafe.Pointer(adjinfo)))
-
-	// Adjust pointers in the Defer structs.
-	// Defer structs themselves are never on the stack.
-	for d := gp._defer; d != nil; d = d.link {
-		adjustpointer(adjinfo, (unsafe.Pointer)(&d.fn))
-		adjustpointer(adjinfo, (unsafe.Pointer)(&d.sp))
-		adjustpointer(adjinfo, (unsafe.Pointer)(&d._panic))
-	}
-}
-
-func adjustpanics(gp *g, adjinfo *adjustinfo) {
-	// Panics are on stack and already adjusted.
-	// Update pointer to head of list in G.
-	adjustpointer(adjinfo, (unsafe.Pointer)(&gp._panic))
-}
-
-func adjustsudogs(gp *g, adjinfo *adjustinfo) {
-	// the data elements pointed to by a SudoG structure
-	// might be in the stack.
-	for s := gp.waiting; s != nil; s = s.waitlink {
-		adjustpointer(adjinfo, (unsafe.Pointer)(&s.elem))
-		adjustpointer(adjinfo, (unsafe.Pointer)(&s.selectdone))
-	}
-}
-
-func adjuststkbar(gp *g, adjinfo *adjustinfo) {
-	for i := int(gp.stkbarPos); i < len(gp.stkbar); i++ {
-		adjustpointer(adjinfo, (unsafe.Pointer)(&gp.stkbar[i].savedLRPtr))
-	}
-}
-
-func fillstack(stk stack, b byte) {
-	for p := stk.lo; p < stk.hi; p++ {
-		*(*byte)(unsafe.Pointer(p)) = b
-	}
-}
-
-// Copies gp's stack to a new stack of a different size.
-// Caller must have changed gp status to Gcopystack.
-func copystack(gp *g, newsize uintptr) {
-	if gp.syscallsp != 0 {
-		throw("stack growth not allowed in system call")
-	}
-	old := gp.stack
-	if old.lo == 0 {
-		throw("nil stackbase")
-	}
-	used := old.hi - gp.sched.sp
-
-	// allocate new stack
-	new, newstkbar := stackalloc(uint32(newsize))
-	if stackPoisonCopy != 0 {
-		fillstack(new, 0xfd)
-	}
-	if stackDebug >= 1 {
-		print("copystack gp=", gp, " [", hex(old.lo), " ", hex(old.hi-used), " ", hex(old.hi), "]/", gp.stackAlloc, " -> [", hex(new.lo), " ", hex(new.hi-used), " ", hex(new.hi), "]/", newsize, "\n")
-	}
-
-	// Disallow sigprof scans of this stack and block if there's
-	// one in progress.
-	gcLockStackBarriers(gp)
-
-	// adjust pointers in the to-be-copied frames
-	var adjinfo adjustinfo
-	adjinfo.old = old
-	adjinfo.delta = new.hi - old.hi
-	gentraceback(^uintptr(0), ^uintptr(0), 0, gp, 0, nil, 0x7fffffff, adjustframe, noescape(unsafe.Pointer(&adjinfo)), 0)
-
-	// adjust other miscellaneous things that have pointers into stacks.
-	adjustctxt(gp, &adjinfo)
-	adjustdefers(gp, &adjinfo)
-	adjustpanics(gp, &adjinfo)
-	adjustsudogs(gp, &adjinfo)
-	adjuststkbar(gp, &adjinfo)
-
-	// copy the stack to the new location
-	if stackPoisonCopy != 0 {
-		fillstack(new, 0xfb)
-	}
-	memmove(unsafe.Pointer(new.hi-used), unsafe.Pointer(old.hi-used), used)
-
-	// copy old stack barriers to new stack barrier array
-	newstkbar = newstkbar[:len(gp.stkbar)]
-	copy(newstkbar, gp.stkbar)
-
-	// Swap out old stack for new one
-	gp.stack = new
-	gp.stackguard0 = new.lo + _StackGuard // NOTE: might clobber a preempt request
-	gp.sched.sp = new.hi - used
-	oldsize := gp.stackAlloc
-	gp.stackAlloc = newsize
-	gp.stkbar = newstkbar
-
-	gcUnlockStackBarriers(gp)
-
-	// free old stack
-	if stackPoisonCopy != 0 {
-		fillstack(old, 0xfc)
-	}
-	stackfree(old, oldsize)
-}
-
-// round x up to a power of 2.
-func round2(x int32) int32 {
-	s := uint(0)
-	for 1<<s < x {
-		s++
-	}
-	return 1 << s
-}
-
-// Called from runtime·morestack when more stack is needed.
-// Allocate larger stack and relocate to new stack.
-// Stack growth is multiplicative, for constant amortized cost.
-//
-// g->atomicstatus will be Grunning or Gscanrunning upon entry.
-// If the GC is trying to stop this g then it will set preemptscan to true.
-func newstack() {
-	thisg := getg()
-	// TODO: double check all gp. shouldn't be getg().
-	if thisg.m.morebuf.g.ptr().stackguard0 == stackFork {
-		throw("stack growth after fork")
-	}
-	if thisg.m.morebuf.g.ptr() != thisg.m.curg {
-		print("runtime: newstack called from g=", thisg.m.morebuf.g, "\n"+"\tm=", thisg.m, " m->curg=", thisg.m.curg, " m->g0=", thisg.m.g0, " m->gsignal=", thisg.m.gsignal, "\n")
-		morebuf := thisg.m.morebuf
-		traceback(morebuf.pc, morebuf.sp, morebuf.lr, morebuf.g.ptr())
-		throw("runtime: wrong goroutine in newstack")
-	}
-	if thisg.m.curg.throwsplit {
-		gp := thisg.m.curg
-		// Update syscallsp, syscallpc in case traceback uses them.
-		morebuf := thisg.m.morebuf
-		gp.syscallsp = morebuf.sp
-		gp.syscallpc = morebuf.pc
-		print("runtime: newstack sp=", hex(gp.sched.sp), " stack=[", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n",
-			"\tmorebuf={pc:", hex(morebuf.pc), " sp:", hex(morebuf.sp), " lr:", hex(morebuf.lr), "}\n",
-			"\tsched={pc:", hex(gp.sched.pc), " sp:", hex(gp.sched.sp), " lr:", hex(gp.sched.lr), " ctxt:", gp.sched.ctxt, "}\n")
-
-		traceback(morebuf.pc, morebuf.sp, morebuf.lr, gp)
-		throw("runtime: stack split at bad time")
-	}
-
-	gp := thisg.m.curg
-	morebuf := thisg.m.morebuf
-	thisg.m.morebuf.pc = 0
-	thisg.m.morebuf.lr = 0
-	thisg.m.morebuf.sp = 0
-	thisg.m.morebuf.g = 0
-	rewindmorestack(&gp.sched)
-
-	// NOTE: stackguard0 may change underfoot, if another thread
-	// is about to try to preempt gp. Read it just once and use that same
-	// value now and below.
-	preempt := atomicloaduintptr(&gp.stackguard0) == stackPreempt
-
-	// Be conservative about where we preempt.
-	// We are interested in preempting user Go code, not runtime code.
-	// If we're holding locks, mallocing, or preemption is disabled, don't
-	// preempt.
-	// This check is very early in newstack so that even the status change
-	// from Grunning to Gwaiting and back doesn't happen in this case.
-	// That status change by itself can be viewed as a small preemption,
-	// because the GC might change Gwaiting to Gscanwaiting, and then
-	// this goroutine has to wait for the GC to finish before continuing.
-	// If the GC is in some way dependent on this goroutine (for example,
-	// it needs a lock held by the goroutine), that small preemption turns
-	// into a real deadlock.
-	if preempt {
-		if thisg.m.locks != 0 || thisg.m.mallocing != 0 || thisg.m.preemptoff != "" || thisg.m.p.ptr().status != _Prunning {
-			// Let the goroutine keep running for now.
-			// gp->preempt is set, so it will be preempted next time.
-			gp.stackguard0 = gp.stack.lo + _StackGuard
-			gogo(&gp.sched) // never return
-		}
-	}
-
-	// The goroutine must be executing in order to call newstack,
-	// so it must be Grunning (or Gscanrunning).
-	casgstatus(gp, _Grunning, _Gwaiting)
-	gp.waitreason = "stack growth"
-
-	if gp.stack.lo == 0 {
-		throw("missing stack in newstack")
-	}
-	sp := gp.sched.sp
-	if thechar == '6' || thechar == '8' {
-		// The call to morestack cost a word.
-		sp -= ptrSize
-	}
-	if stackDebug >= 1 || sp < gp.stack.lo {
-		print("runtime: newstack sp=", hex(sp), " stack=[", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n",
-			"\tmorebuf={pc:", hex(morebuf.pc), " sp:", hex(morebuf.sp), " lr:", hex(morebuf.lr), "}\n",
-			"\tsched={pc:", hex(gp.sched.pc), " sp:", hex(gp.sched.sp), " lr:", hex(gp.sched.lr), " ctxt:", gp.sched.ctxt, "}\n")
-	}
-	if sp < gp.stack.lo {
-		print("runtime: gp=", gp, ", gp->status=", hex(readgstatus(gp)), "\n ")
-		print("runtime: split stack overflow: ", hex(sp), " < ", hex(gp.stack.lo), "\n")
-		throw("runtime: split stack overflow")
-	}
-
-	if gp.sched.ctxt != nil {
-		// morestack wrote sched.ctxt on its way in here,
-		// without a write barrier. Run the write barrier now.
-		// It is not possible to be preempted between then
-		// and now, so it's okay.
-		writebarrierptr_nostore((*uintptr)(unsafe.Pointer(&gp.sched.ctxt)), uintptr(gp.sched.ctxt))
-	}
-
-	if preempt {
-		if gp == thisg.m.g0 {
-			throw("runtime: preempt g0")
-		}
-		if thisg.m.p == 0 && thisg.m.locks == 0 {
-			throw("runtime: g is running but p is not")
-		}
-		if gp.preemptscan {
-			for !castogscanstatus(gp, _Gwaiting, _Gscanwaiting) {
-				// Likely to be racing with the GC as
-				// it sees a _Gwaiting and does the
-				// stack scan. If so, gcworkdone will
-				// be set and gcphasework will simply
-				// return.
-			}
-			if !gp.gcscandone {
-				scanstack(gp)
-				gp.gcscandone = true
-			}
-			gp.preemptscan = false
-			gp.preempt = false
-			casfrom_Gscanstatus(gp, _Gscanwaiting, _Gwaiting)
-			casgstatus(gp, _Gwaiting, _Grunning)
-			gp.stackguard0 = gp.stack.lo + _StackGuard
-			gogo(&gp.sched) // never return
-		}
-
-		// Act like goroutine called runtime.Gosched.
-		casgstatus(gp, _Gwaiting, _Grunning)
-		gopreempt_m(gp) // never return
-	}
-
-	// Allocate a bigger segment and move the stack.
-	oldsize := int(gp.stackAlloc)
-	newsize := oldsize * 2
-	if uintptr(newsize) > maxstacksize {
-		print("runtime: goroutine stack exceeds ", maxstacksize, "-byte limit\n")
-		throw("stack overflow")
-	}
-
-	casgstatus(gp, _Gwaiting, _Gcopystack)
-
-	// The concurrent GC will not scan the stack while we are doing the copy since
-	// the gp is in a Gcopystack status.
-	copystack(gp, uintptr(newsize))
-	if stackDebug >= 1 {
-		print("stack grow done\n")
-	}
-	casgstatus(gp, _Gcopystack, _Grunning)
-	gogo(&gp.sched)
-}
-
-//go:nosplit
-func nilfunc() {
-	*(*uint8)(nil) = 0
-}
-
-// adjust Gobuf as if it executed a call to fn
-// and then did an immediate gosave.
-func gostartcallfn(gobuf *gobuf, fv *funcval) {
-	var fn unsafe.Pointer
-	if fv != nil {
-		fn = (unsafe.Pointer)(fv.fn)
-	} else {
-		fn = unsafe.Pointer(funcPC(nilfunc))
-	}
-	gostartcall(gobuf, fn, (unsafe.Pointer)(fv))
-}
-
-// Maybe shrink the stack being used by gp.
-// Called at garbage collection time.
-func shrinkstack(gp *g) {
-	if readgstatus(gp) == _Gdead {
-		if gp.stack.lo != 0 {
-			// Free whole stack - it will get reallocated
-			// if G is used again.
-			stackfree(gp.stack, gp.stackAlloc)
-			gp.stack.lo = 0
-			gp.stack.hi = 0
-			gp.stkbar = nil
-			gp.stkbarPos = 0
-		}
-		return
-	}
-	if gp.stack.lo == 0 {
-		throw("missing stack in shrinkstack")
-	}
-
-	if debug.gcshrinkstackoff > 0 {
-		return
-	}
-
-	oldsize := gp.stackAlloc
-	newsize := oldsize / 2
-	// Don't shrink the allocation below the minimum-sized stack
-	// allocation.
-	if newsize < _FixedStack {
-		return
-	}
-	// Compute how much of the stack is currently in use and only
-	// shrink the stack if gp is using less than a quarter of its
-	// current stack. The currently used stack includes everything
-	// down to the SP plus the stack guard space that ensures
-	// there's room for nosplit functions.
-	avail := gp.stack.hi - gp.stack.lo
-	if used := gp.stack.hi - gp.sched.sp + _StackLimit; used >= avail/4 {
-		return
-	}
-
-	// We can't copy the stack if we're in a syscall.
-	// The syscall might have pointers into the stack.
-	if gp.syscallsp != 0 {
-		return
-	}
-	if goos_windows != 0 && gp.m != nil && gp.m.libcallsp != 0 {
-		return
-	}
-
-	if stackDebug > 0 {
-		print("shrinking stack ", oldsize, "->", newsize, "\n")
-	}
-
-	oldstatus := casgcopystack(gp)
-	copystack(gp, newsize)
-	casgstatus(gp, _Gcopystack, oldstatus)
-}
-
-// freeStackSpans frees unused stack spans at the end of GC.
-func freeStackSpans() {
-	lock(&stackpoolmu)
-
-	// Scan stack pools for empty stack spans.
-	for order := range stackpool {
-		list := &stackpool[order]
-		for s := list.next; s != list; {
-			next := s.next
-			if s.ref == 0 {
-				mSpanList_Remove(s)
-				s.freelist = 0
-				mHeap_FreeStack(&mheap_, s)
-			}
-			s = next
-		}
-	}
-
-	// Free queued stack spans.
-	for stackFreeQueue.next != &stackFreeQueue {
-		s := stackFreeQueue.next
-		mSpanList_Remove(s)
-		mHeap_FreeStack(&mheap_, s)
-	}
-
-	unlock(&stackpoolmu)
-}
-
-//go:nosplit
-func morestackc() {
-	systemstack(func() {
-		throw("attempt to execute C code on Go stack")
-	})
-}
diff --git a/src/runtime/stack2.go b/src/runtime/stack2.go
deleted file mode 100644
index 5ec8d8d..0000000
--- a/src/runtime/stack2.go
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2011 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 runtime
-
-/*
-Stack layout parameters.
-Included both by runtime (compiled via 6c) and linkers (compiled via gcc).
-
-The per-goroutine g->stackguard is set to point StackGuard bytes
-above the bottom of the stack.  Each function compares its stack
-pointer against g->stackguard to check for overflow.  To cut one
-instruction from the check sequence for functions with tiny frames,
-the stack is allowed to protrude StackSmall bytes below the stack
-guard.  Functions with large frames don't bother with the check and
-always call morestack.  The sequences are (for amd64, others are
-similar):
-
-	guard = g->stackguard
-	frame = function's stack frame size
-	argsize = size of function arguments (call + return)
-
-	stack frame size <= StackSmall:
-		CMPQ guard, SP
-		JHI 3(PC)
-		MOVQ m->morearg, $(argsize << 32)
-		CALL morestack(SB)
-
-	stack frame size > StackSmall but < StackBig
-		LEAQ (frame-StackSmall)(SP), R0
-		CMPQ guard, R0
-		JHI 3(PC)
-		MOVQ m->morearg, $(argsize << 32)
-		CALL morestack(SB)
-
-	stack frame size >= StackBig:
-		MOVQ m->morearg, $((argsize << 32) | frame)
-		CALL morestack(SB)
-
-The bottom StackGuard - StackSmall bytes are important: there has
-to be enough room to execute functions that refuse to check for
-stack overflow, either because they need to be adjacent to the
-actual caller's frame (deferproc) or because they handle the imminent
-stack overflow (morestack).
-
-For example, deferproc might call malloc, which does one of the
-above checks (without allocating a full frame), which might trigger
-a call to morestack.  This sequence needs to fit in the bottom
-section of the stack.  On amd64, morestack's frame is 40 bytes, and
-deferproc's frame is 56 bytes.  That fits well within the
-StackGuard - StackSmall bytes at the bottom.
-The linkers explore all possible call traces involving non-splitting
-functions to make sure that this limit cannot be violated.
-*/
-
-const (
-	// StackSystem is a number of additional bytes to add
-	// to each stack below the usual guard area for OS-specific
-	// purposes like signal handling. Used on Windows, Plan 9,
-	// and Darwin/ARM because they do not use a separate stack.
-	_StackSystem = goos_windows*512*ptrSize + goos_plan9*512 + goos_darwin*goarch_arm*1024
-
-	// The minimum size of stack used by Go code
-	_StackMin = 2048
-
-	// The minimum stack size to allocate.
-	// The hackery here rounds FixedStack0 up to a power of 2.
-	_FixedStack0 = _StackMin + _StackSystem
-	_FixedStack1 = _FixedStack0 - 1
-	_FixedStack2 = _FixedStack1 | (_FixedStack1 >> 1)
-	_FixedStack3 = _FixedStack2 | (_FixedStack2 >> 2)
-	_FixedStack4 = _FixedStack3 | (_FixedStack3 >> 4)
-	_FixedStack5 = _FixedStack4 | (_FixedStack4 >> 8)
-	_FixedStack6 = _FixedStack5 | (_FixedStack5 >> 16)
-	_FixedStack  = _FixedStack6 + 1
-
-	// Functions that need frames bigger than this use an extra
-	// instruction to do the stack split check, to avoid overflow
-	// in case SP - framesize wraps below zero.
-	// This value can be no bigger than the size of the unmapped
-	// space at zero.
-	_StackBig = 4096
-
-	// The stack guard is a pointer this many bytes above the
-	// bottom of the stack.
-	_StackGuard = 640*stackGuardMultiplier + _StackSystem
-
-	// After a stack split check the SP is allowed to be this
-	// many bytes below the stack guard.  This saves an instruction
-	// in the checking sequence for tiny frames.
-	_StackSmall = 128
-
-	// The maximum number of bytes that a chain of NOSPLIT
-	// functions can use.
-	_StackLimit = _StackGuard - _StackSystem - _StackSmall
-)
-
-// Goroutine preemption request.
-// Stored into g->stackguard0 to cause split stack check failure.
-// Must be greater than any real sp.
-// 0xfffffade in hex.
-const (
-	_StackPreempt = uintptrMask & -1314
-	_StackFork    = uintptrMask & -1234
-)
diff --git a/src/runtime/stack_test.go b/src/runtime/stack_test.go
index fa073f1..928d1ec 100644
--- a/src/runtime/stack_test.go
+++ b/src/runtime/stack_test.go
@@ -111,7 +111,8 @@ func TestStackGrowth(t *testing.T) {
 		select {
 		case <-done:
 		case <-time.After(20 * time.Second):
-			t.Fatal("finalizer did not run")
+			t.Error("finalizer did not run")
+			return
 		}
 	}()
 	wg.Wait()
@@ -191,7 +192,6 @@ func TestStackGrowthCallback(t *testing.T) {
 			<-done
 		})
 	}()
-
 	wg.Wait()
 }
 
diff --git a/src/runtime/string.go b/src/runtime/string.go
index a5851b7..dd04bda 100644
--- a/src/runtime/string.go
+++ b/src/runtime/string.go
@@ -5,6 +5,7 @@
 package runtime
 
 import (
+	"runtime/internal/atomic"
 	"unsafe"
 )
 
@@ -86,6 +87,9 @@ func slicebytetostring(buf *tmpBuf, b []byte) string {
 			getcallerpc(unsafe.Pointer(&b)),
 			funcPC(slicebytetostring))
 	}
+	if msanenabled && l > 0 {
+		msanread(unsafe.Pointer(&b[0]), uintptr(l))
+	}
 	s, c := rawstringtmp(buf, l)
 	copy(c, b)
 	return s
@@ -94,7 +98,7 @@ func slicebytetostring(buf *tmpBuf, b []byte) string {
 // stringDataOnStack reports whether the string's data is
 // stored on the current goroutine's stack.
 func stringDataOnStack(s string) bool {
-	ptr := uintptr((*stringStruct)(unsafe.Pointer(&s)).str)
+	ptr := uintptr(stringStructOf(&s).str)
 	stk := getg().stack
 	return stk.lo <= ptr && ptr < stk.hi
 }
@@ -126,13 +130,16 @@ func slicebytetostringtmp(b []byte) string {
 			getcallerpc(unsafe.Pointer(&b)),
 			funcPC(slicebytetostringtmp))
 	}
+	if msanenabled && len(b) > 0 {
+		msanread(unsafe.Pointer(&b[0]), uintptr(len(b)))
+	}
 	return *(*string)(unsafe.Pointer(&b))
 }
 
 func stringtoslicebyte(buf *tmpBuf, s string) []byte {
 	var b []byte
 	if buf != nil && len(s) <= len(buf) {
-		b = buf[:len(s)]
+		b = buf[:len(s):len(s)]
 	} else {
 		b = rawbyteslice(len(s))
 	}
@@ -147,7 +154,7 @@ func stringtoslicebytetmp(s string) []byte {
 	// The only such case today is:
 	// for i, c := range []byte(str)
 
-	str := (*stringStruct)(unsafe.Pointer(&s))
+	str := stringStructOf(&s)
 	ret := slice{array: unsafe.Pointer(str.str), len: str.len, cap: str.len}
 	return *(*[]byte)(unsafe.Pointer(&ret))
 }
@@ -164,7 +171,7 @@ func stringtoslicerune(buf *[tmpStringBufSize]rune, s string) []rune {
 	}
 	var a []rune
 	if buf != nil && n <= len(buf) {
-		a = buf[:n]
+		a = buf[:n:n]
 	} else {
 		a = rawruneslice(n)
 	}
@@ -185,6 +192,9 @@ func slicerunetostring(buf *tmpBuf, a []rune) string {
 			getcallerpc(unsafe.Pointer(&a)),
 			funcPC(slicerunetostring))
 	}
+	if msanenabled && len(a) > 0 {
+		msanread(unsafe.Pointer(&a[0]), uintptr(len(a))*unsafe.Sizeof(a[0]))
+	}
 	var dum [4]byte
 	size1 := 0
 	for _, r := range a {
@@ -207,6 +217,16 @@ type stringStruct struct {
 	len int
 }
 
+// Variant with *byte pointer type for DWARF debugging.
+type stringStructDWARF struct {
+	str *byte
+	len int
+}
+
+func stringStructOf(sp *string) *stringStruct {
+	return (*stringStruct)(unsafe.Pointer(sp))
+}
+
 func intstring(buf *[4]byte, v int64) string {
 	var s string
 	var b []byte
@@ -263,14 +283,14 @@ func stringiter2(s string, k int) (int, rune) {
 func rawstring(size int) (s string, b []byte) {
 	p := mallocgc(uintptr(size), nil, flagNoScan|flagNoZero)
 
-	(*stringStruct)(unsafe.Pointer(&s)).str = p
-	(*stringStruct)(unsafe.Pointer(&s)).len = size
+	stringStructOf(&s).str = p
+	stringStructOf(&s).len = size
 
 	*(*slice)(unsafe.Pointer(&b)) = slice{p, size, size}
 
 	for {
 		ms := maxstring
-		if uintptr(size) <= uintptr(ms) || casuintptr((*uintptr)(unsafe.Pointer(&maxstring)), uintptr(ms), uintptr(size)) {
+		if uintptr(size) <= uintptr(ms) || atomic.Casuintptr((*uintptr)(unsafe.Pointer(&maxstring)), uintptr(ms), uintptr(size)) {
 			return
 		}
 	}
@@ -360,3 +380,63 @@ func atoi(s string) int {
 	}
 	return n
 }
+
+//go:nosplit
+func findnull(s *byte) int {
+	if s == nil {
+		return 0
+	}
+	p := (*[_MaxMem/2 - 1]byte)(unsafe.Pointer(s))
+	l := 0
+	for p[l] != 0 {
+		l++
+	}
+	return l
+}
+
+func findnullw(s *uint16) int {
+	if s == nil {
+		return 0
+	}
+	p := (*[_MaxMem/2/2 - 1]uint16)(unsafe.Pointer(s))
+	l := 0
+	for p[l] != 0 {
+		l++
+	}
+	return l
+}
+
+var maxstring uintptr = 256 // a hint for print
+
+//go:nosplit
+func gostringnocopy(str *byte) string {
+	ss := stringStruct{str: unsafe.Pointer(str), len: findnull(str)}
+	s := *(*string)(unsafe.Pointer(&ss))
+	for {
+		ms := maxstring
+		if uintptr(len(s)) <= ms || atomic.Casuintptr(&maxstring, ms, uintptr(len(s))) {
+			break
+		}
+	}
+	return s
+}
+
+func gostringw(strw *uint16) string {
+	var buf [8]byte
+	str := (*[_MaxMem/2/2 - 1]uint16)(unsafe.Pointer(strw))
+	n1 := 0
+	for i := 0; str[i] != 0; i++ {
+		n1 += runetochar(buf[:], rune(str[i]))
+	}
+	s, b := rawstring(n1 + 4)
+	n2 := 0
+	for i := 0; str[i] != 0; i++ {
+		// check for race
+		if n2 >= n1 {
+			break
+		}
+		n2 += runetochar(b[n2:], rune(str[i]))
+	}
+	b[n2] = 0 // for luck
+	return s[:n2]
+}
diff --git a/src/runtime/string1.go b/src/runtime/string1.go
deleted file mode 100644
index 4bfa3d9..0000000
--- a/src/runtime/string1.go
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2009 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 runtime
-
-import "unsafe"
-
-//go:nosplit
-func findnull(s *byte) int {
-	if s == nil {
-		return 0
-	}
-	p := (*[_MaxMem/2 - 1]byte)(unsafe.Pointer(s))
-	l := 0
-	for p[l] != 0 {
-		l++
-	}
-	return l
-}
-
-func findnullw(s *uint16) int {
-	if s == nil {
-		return 0
-	}
-	p := (*[_MaxMem/2/2 - 1]uint16)(unsafe.Pointer(s))
-	l := 0
-	for p[l] != 0 {
-		l++
-	}
-	return l
-}
-
-var maxstring uintptr = 256 // a hint for print
-
-//go:nosplit
-func gostringnocopy(str *byte) string {
-	ss := stringStruct{str: unsafe.Pointer(str), len: findnull(str)}
-	s := *(*string)(unsafe.Pointer(&ss))
-	for {
-		ms := maxstring
-		if uintptr(len(s)) <= ms || casuintptr(&maxstring, ms, uintptr(len(s))) {
-			break
-		}
-	}
-	return s
-}
-
-func gostringw(strw *uint16) string {
-	var buf [8]byte
-	str := (*[_MaxMem/2/2 - 1]uint16)(unsafe.Pointer(strw))
-	n1 := 0
-	for i := 0; str[i] != 0; i++ {
-		n1 += runetochar(buf[:], rune(str[i]))
-	}
-	s, b := rawstring(n1 + 4)
-	n2 := 0
-	for i := 0; str[i] != 0; i++ {
-		// check for race
-		if n2 >= n1 {
-			break
-		}
-		n2 += runetochar(b[n2:], rune(str[i]))
-	}
-	b[n2] = 0 // for luck
-	return s[:n2]
-}
diff --git a/src/runtime/string_test.go b/src/runtime/string_test.go
index dfda950..150a255 100644
--- a/src/runtime/string_test.go
+++ b/src/runtime/string_test.go
@@ -125,7 +125,7 @@ func TestStringW(t *testing.T) {
 }
 
 func TestLargeStringConcat(t *testing.T) {
-	output := executeTest(t, largeStringConcatSource, nil)
+	output := runTestProg(t, "testprog", "stringconcat")
 	want := "panic: " + strings.Repeat("0", 1<<10) + strings.Repeat("1", 1<<10) +
 		strings.Repeat("2", 1<<10) + strings.Repeat("3", 1<<10)
 	if !strings.HasPrefix(output, want) {
@@ -133,19 +133,6 @@ func TestLargeStringConcat(t *testing.T) {
 	}
 }
 
-var largeStringConcatSource = `
-package main
-import "strings"
-func main() {
-	s0 := strings.Repeat("0", 1<<10)
-	s1 := strings.Repeat("1", 1<<10)
-	s2 := strings.Repeat("2", 1<<10)
-	s3 := strings.Repeat("3", 1<<10)
-	s := s0 + s1 + s2 + s3
-	panic(s)
-}
-`
-
 func TestGostringnocopy(t *testing.T) {
 	max := *runtime.Maxstring
 	b := make([]byte, max+10)
@@ -235,3 +222,18 @@ func TestRangeStringCast(t *testing.T) {
 		t.Fatalf("want 0 allocs, got %v", n)
 	}
 }
+
+func TestString2Slice(t *testing.T) {
+	// Make sure we don't return slices that expose
+	// an unzeroed section of stack-allocated temp buf
+	// between len and cap.  See issue 14232.
+	s := "foož"
+	b := ([]byte)(s)
+	if cap(b) != 5 {
+		t.Errorf("want cap of 5, got %d", cap(b))
+	}
+	r := ([]rune)(s)
+	if cap(r) != 4 {
+		t.Errorf("want cap of 4, got %d", cap(r))
+	}
+}
diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go
index d725bb1..f060182 100644
--- a/src/runtime/stubs.go
+++ b/src/runtime/stubs.go
@@ -6,12 +6,6 @@ package runtime
 
 import "unsafe"
 
-// Declarations for runtime services implemented in C or assembly.
-
-const ptrSize = 4 << (^uintptr(0) >> 63)             // unsafe.Sizeof(uintptr(0)) but an ideal const
-const regSize = 4 << (^uintreg(0) >> 63)             // unsafe.Sizeof(uintreg(0)) but an ideal const
-const spAlign = 1*(1-goarch_arm64) + 16*goarch_arm64 // SP alignment: 1 normally, 16 for ARM64
-
 // Should be a built-in for unsafe.Pointer?
 //go:nosplit
 func add(p unsafe.Pointer, x uintptr) unsafe.Pointer {
@@ -151,42 +145,6 @@ func goexit(neverCallThisFunction)
 // See the assembly implementations for more details.
 func cgocallback_gofunc(fv uintptr, frame uintptr, framesize uintptr)
 
-//go:noescape
-func cas(ptr *uint32, old, new uint32) bool
-
-// NO go:noescape annotation; see atomic_pointer.go.
-func casp1(ptr *unsafe.Pointer, old, new unsafe.Pointer) bool
-
-func nop() // call to prevent inlining of function body
-
-//go:noescape
-func casuintptr(ptr *uintptr, old, new uintptr) bool
-
-//go:noescape
-func atomicstoreuintptr(ptr *uintptr, new uintptr)
-
-//go:noescape
-func atomicloaduintptr(ptr *uintptr) uintptr
-
-//go:noescape
-func atomicloaduint(ptr *uint) uint
-
-// TODO: Write native implementations of int64 atomic ops (or improve
-// inliner). These portable ones can't be inlined right now, so we're
-// taking an extra function call hit.
-
-func atomicstoreint64(ptr *int64, new int64) {
-	atomicstore64((*uint64)(unsafe.Pointer(ptr)), uint64(new))
-}
-
-func atomicloadint64(ptr *int64) int64 {
-	return int64(atomicload64((*uint64)(unsafe.Pointer(ptr))))
-}
-
-func xaddint64(ptr *int64, delta int64) int64 {
-	return int64(xadd64((*uint64)(unsafe.Pointer(ptr)), delta))
-}
-
 // publicationBarrier performs a store/store barrier (a "publication"
 // or "export" barrier). Some form of synchronization is required
 // between initializing an object and making that object accessible to
@@ -312,3 +270,6 @@ func unixnanotime() int64 {
 func round(n, a uintptr) uintptr {
 	return (n + a - 1) &^ (a - 1)
 }
+
+// checkASM returns whether assembly runtime checks have passed.
+func checkASM() bool
diff --git a/src/runtime/stubs2.go b/src/runtime/stubs2.go
index 1cb6f91..95db924 100644
--- a/src/runtime/stubs2.go
+++ b/src/runtime/stubs2.go
@@ -18,7 +18,6 @@ func exit(code int32)
 func nanotime() int64
 func usleep(usec uint32)
 
-func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer
 func munmap(addr unsafe.Pointer, n uintptr)
 
 //go:noescape
diff --git a/src/runtime/stubs_android.go b/src/runtime/stubs_android.go
index e372377..0380dca 100644
--- a/src/runtime/stubs_android.go
+++ b/src/runtime/stubs_android.go
@@ -2,9 +2,15 @@ package runtime
 
 import "unsafe"
 
+// Return values of access/connect/socket are the return values of the syscall
+// (may encode error numbers).
+
+// int access(const char *, int)
 //go:noescape
 func access(name *byte, mode int32) int32
 
-func connect(fd uintptr, addr unsafe.Pointer, len int32) int32
+// int connect(int, const struct sockaddr*, socklen_t)
+func connect(fd int32, addr unsafe.Pointer, len int32) int32
 
+// int socket(int, int, int)
 func socket(domain int32, typ int32, prot int32) int32
diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go
index 400ab6d..00b0a85 100644
--- a/src/runtime/symtab.go
+++ b/src/runtime/symtab.go
@@ -4,7 +4,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 // NOTE: Func does not expose the actual unexported fields, because we return *Func
 // values to users, and we want to keep them from being able to overwrite the data
@@ -25,7 +28,6 @@ const (
 	_PCDATA_StackMapIndex       = 0
 	_FUNCDATA_ArgsPointerMaps   = 0
 	_FUNCDATA_LocalsPointerMaps = 1
-	_FUNCDATA_DeadValueMaps     = 2
 	_ArgsSizeUnknown            = -0x80000000
 )
 
@@ -106,13 +108,14 @@ func moduledataverify1(datap *moduledata) {
 	// and a byte giving the pointer width in bytes.
 	pcln := *(**[8]byte)(unsafe.Pointer(&datap.pclntable))
 	pcln32 := *(**[2]uint32)(unsafe.Pointer(&datap.pclntable))
-	if pcln32[0] != 0xfffffffb || pcln[4] != 0 || pcln[5] != 0 || pcln[6] != _PCQuantum || pcln[7] != ptrSize {
+	if pcln32[0] != 0xfffffffb || pcln[4] != 0 || pcln[5] != 0 || pcln[6] != sys.PCQuantum || pcln[7] != sys.PtrSize {
 		println("runtime: function symbol table header:", hex(pcln32[0]), hex(pcln[4]), hex(pcln[5]), hex(pcln[6]), hex(pcln[7]))
 		throw("invalid function symbol table\n")
 	}
 
 	// ftab is lookup table for function by program counter.
 	nftab := len(datap.ftab) - 1
+	var pcCache pcvalueCache
 	for i := 0; i < nftab; i++ {
 		// NOTE: ftab[nftab].entry is legal; it is the address beyond the final function.
 		if datap.ftab[i].entry > datap.ftab[i+1].entry {
@@ -148,9 +151,9 @@ func moduledataverify1(datap *moduledata) {
 					}
 				}
 			}
-			pcvalue(f, f.pcfile, end, true)
-			pcvalue(f, f.pcln, end, true)
-			pcvalue(f, f.pcsp, end, true)
+			pcvalue(f, f.pcfile, end, &pcCache, true)
+			pcvalue(f, f.pcln, end, &pcCache, true)
+			pcvalue(f, f.pcsp, end, &pcCache, true)
 		}
 	}
 
@@ -227,10 +230,42 @@ func findfunc(pc uintptr) *_func {
 	return (*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[idx].funcoff]))
 }
 
-func pcvalue(f *_func, off int32, targetpc uintptr, strict bool) int32 {
+type pcvalueCache struct {
+	entries [16]pcvalueCacheEnt
+}
+
+type pcvalueCacheEnt struct {
+	// targetpc and off together are the key of this cache entry.
+	targetpc uintptr
+	off      int32
+	// val is the value of this cached pcvalue entry.
+	val int32
+}
+
+func pcvalue(f *_func, off int32, targetpc uintptr, cache *pcvalueCache, strict bool) int32 {
 	if off == 0 {
 		return -1
 	}
+
+	// Check the cache. This speeds up walks of deep stacks, which
+	// tend to have the same recursive functions over and over.
+	//
+	// This cache is small enough that full associativity is
+	// cheaper than doing the hashing for a less associative
+	// cache.
+	if cache != nil {
+		for _, ent := range cache.entries {
+			// We check off first because we're more
+			// likely to have multiple entries with
+			// different offsets for the same targetpc
+			// than the other way around, so we'll usually
+			// fail in the first clause.
+			if ent.off == off && ent.targetpc == targetpc {
+				return ent.val
+			}
+		}
+	}
+
 	datap := findmoduledatap(f.entry) // inefficient
 	if datap == nil {
 		if strict && panicking == 0 {
@@ -249,6 +284,19 @@ func pcvalue(f *_func, off int32, targetpc uintptr, strict bool) int32 {
 			break
 		}
 		if targetpc < pc {
+			// Replace a random entry in the cache. Random
+			// replacement prevents a performance cliff if
+			// a recursive stack's cycle is slightly
+			// larger than the cache.
+			if cache != nil {
+				ci := fastrand1() % uint32(len(cache.entries))
+				cache.entries[ci] = pcvalueCacheEnt{
+					targetpc: targetpc,
+					off:      off,
+					val:      val,
+				}
+			}
+
 			return val
 		}
 	}
@@ -285,7 +333,7 @@ func cfuncname(f *_func) *byte {
 	if datap == nil {
 		return nil
 	}
-	return (*byte)(unsafe.Pointer(&datap.pclntable[f.nameoff]))
+	return &datap.pclntable[f.nameoff]
 }
 
 func funcname(f *_func) string {
@@ -297,8 +345,8 @@ func funcline1(f *_func, targetpc uintptr, strict bool) (file string, line int32
 	if datap == nil {
 		return "?", 0
 	}
-	fileno := int(pcvalue(f, f.pcfile, targetpc, strict))
-	line = pcvalue(f, f.pcln, targetpc, strict)
+	fileno := int(pcvalue(f, f.pcfile, targetpc, nil, strict))
+	line = pcvalue(f, f.pcln, targetpc, nil, strict)
 	if fileno == -1 || line == -1 || fileno >= len(datap.filetab) {
 		// print("looking for ", hex(targetpc), " in ", funcname(f), " got file=", fileno, " line=", lineno, "\n")
 		return "?", 0
@@ -311,20 +359,20 @@ func funcline(f *_func, targetpc uintptr) (file string, line int32) {
 	return funcline1(f, targetpc, true)
 }
 
-func funcspdelta(f *_func, targetpc uintptr) int32 {
-	x := pcvalue(f, f.pcsp, targetpc, true)
-	if x&(ptrSize-1) != 0 {
+func funcspdelta(f *_func, targetpc uintptr, cache *pcvalueCache) int32 {
+	x := pcvalue(f, f.pcsp, targetpc, cache, true)
+	if x&(sys.PtrSize-1) != 0 {
 		print("invalid spdelta ", funcname(f), " ", hex(f.entry), " ", hex(targetpc), " ", hex(f.pcsp), " ", x, "\n")
 	}
 	return x
 }
 
-func pcdatavalue(f *_func, table int32, targetpc uintptr) int32 {
+func pcdatavalue(f *_func, table int32, targetpc uintptr, cache *pcvalueCache) int32 {
 	if table < 0 || table >= f.npcdata {
 		return -1
 	}
 	off := *(*int32)(add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(table)*4))
-	return pcvalue(f, off, targetpc, true)
+	return pcvalue(f, off, targetpc, cache, true)
 }
 
 func funcdata(f *_func, i int32) unsafe.Pointer {
@@ -332,13 +380,13 @@ func funcdata(f *_func, i int32) unsafe.Pointer {
 		return nil
 	}
 	p := add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(f.npcdata)*4)
-	if ptrSize == 8 && uintptr(p)&4 != 0 {
+	if sys.PtrSize == 8 && uintptr(p)&4 != 0 {
 		if uintptr(unsafe.Pointer(f))&4 != 0 {
 			println("runtime: misaligned func", f)
 		}
 		p = add(p, 4)
 	}
-	return *(*unsafe.Pointer)(add(p, uintptr(i)*ptrSize))
+	return *(*unsafe.Pointer)(add(p, uintptr(i)*sys.PtrSize))
 }
 
 // step advances to the next pc, value pair in the encoded table.
@@ -354,7 +402,7 @@ func step(p []byte, pc *uintptr, val *int32, first bool) (newp []byte, ok bool)
 	}
 	vdelta := int32(uvdelta)
 	p, pcdelta := readvarint(p)
-	*pc += uintptr(pcdelta * _PCQuantum)
+	*pc += uintptr(pcdelta * sys.PCQuantum)
 	*val += vdelta
 	return p, true
 }
diff --git a/src/runtime/sys_darwin_386.s b/src/runtime/sys_darwin_386.s
index abc5d32..ad3dca4 100644
--- a/src/runtime/sys_darwin_386.s
+++ b/src/runtime/sys_darwin_386.s
@@ -242,53 +242,55 @@ TEXT runtime·sigaction(SB),NOSPLIT,$0
 	MOVL	$0xf1, 0xf1  // crash
 	RET
 
-// Sigtramp's job is to call the actual signal handler.
-// It is called with the following arguments on the stack:
-//	0(FP)	"return address" - ignored
-//	4(FP)	actual handler
-//	8(FP)	signal number
-//	12(FP)	siginfo style
-//	16(FP)	siginfo
-//	20(FP)	context
-TEXT runtime·sigtramp(SB),NOSPLIT,$40
-	get_tls(CX)
-	
-	// check that g exists
-	MOVL	g(CX), DI
-	CMPL	DI, $0
-	JNE	6(PC)
-	MOVL	sig+8(FP), BX
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
+	MOVL	fn+0(FP), AX
+	MOVL	sig+4(FP), BX
+	MOVL	info+8(FP), CX
+	MOVL	ctx+12(FP), DX
+	MOVL	SP, SI
+	SUBL	$32, SP		// align stack; handler might be C code
+	ANDL	$~15, SP
 	MOVL	BX, 0(SP)
-	MOVL	$runtime·badsignal(SB), AX
+	MOVL	CX, 4(SP)
+	MOVL	DX, 8(SP)
+	MOVL	SI, 12(SP)
 	CALL	AX
-	JMP 	ret
-
-	// save g
-	MOVL	DI, 20(SP)
+	MOVL	12(SP), AX
+	MOVL	AX, SP
+	RET
 
-	// g = m->gsignal
-	MOVL	g_m(DI), BP
-	MOVL	m_gsignal(BP), BP
-	MOVL	BP, g(CX)
+TEXT runtime·sigreturn(SB),NOSPLIT,$12-8
+	MOVL	ctx+0(FP), CX
+	MOVL	infostyle+4(FP), BX
+	MOVL	$0, 0(SP)	// "caller PC" - ignored
+	MOVL	CX, 4(SP)
+	MOVL	BX, 8(SP)
+	MOVL	$184, AX	// sigreturn(ucontext, infostyle)
+	INT	$0x80
+	MOVL	$0xf1, 0xf1  // crash
+	RET
 
-	// copy arguments to sighandler
-	MOVL	sig+8(FP), BX
+// Sigtramp's job is to call the actual signal handler.
+// It is called with the following arguments on the stack:
+//	0(SP)	"return address" - ignored
+//	4(SP)	actual handler
+//	8(SP)	signal number
+//	12(SP)	siginfo style
+//	16(SP)	siginfo
+//	20(SP)	context
+TEXT runtime·sigtramp(SB),NOSPLIT,$20
+	MOVL	fn+0(FP), BX
 	MOVL	BX, 0(SP)
-	MOVL	info+12(FP), BX
+	MOVL	style+4(FP), BX
 	MOVL	BX, 4(SP)
-	MOVL	context+16(FP), BX
+	MOVL	sig+8(FP), BX
 	MOVL	BX, 8(SP)
-	MOVL	DI, 12(SP)
-
-	MOVL	handler+0(FP), BX
-	CALL	BX
-
-	// restore g
-	get_tls(CX)
-	MOVL	20(SP), DI
-	MOVL	DI, g(CX)
+	MOVL	info+12(FP), BX
+	MOVL	BX, 12(SP)
+	MOVL	context+16(FP), BX
+	MOVL	BX, 16(SP)
+	CALL	runtime·sigtrampgo(SB)
 
-ret:
 	// call sigreturn
 	MOVL	context+16(FP), CX
 	MOVL	style+4(FP), BX
@@ -361,10 +363,8 @@ TEXT runtime·bsdthread_create(SB),NOSPLIT,$32
 //	SP = stack - C_32_STK_ALIGN
 TEXT runtime·bsdthread_start(SB),NOSPLIT,$0
 	// set up ldt 7+id to point at m->tls.
-	// m->tls is at m+40.  newosproc left
-	// the m->id in tls[0].
 	LEAL	m_tls(DX), BP
-	MOVL	0(BP), DI
+	MOVL	m_id(DX), DI
 	ADDL	$7, DI	// m0 is LDT#7. count up.
 	// setldt(tls#, &tls, sizeof tls)
 	PUSHAL	// save registers
diff --git a/src/runtime/sys_darwin_amd64.s b/src/runtime/sys_darwin_amd64.s
index 692dbca..7b9cf6a 100644
--- a/src/runtime/sys_darwin_amd64.s
+++ b/src/runtime/sys_darwin_amd64.s
@@ -214,10 +214,14 @@ TEXT runtime·sigaction(SB),NOSPLIT,$0-24
 
 TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
 	MOVQ fn+0(FP),    AX
-	MOVQ sig+8(FP),   DI
+	MOVL sig+8(FP),   DI
 	MOVQ info+16(FP), SI
 	MOVQ ctx+24(FP),  DX
+	MOVQ SP, BP
+	SUBQ $64, SP
+	ANDQ $~15, SP     // alignment for x86_64 ABI
 	CALL AX
+	MOVQ BP, SP
 	RET
 
 TEXT runtime·sigreturn(SB),NOSPLIT,$0-12
diff --git a/src/runtime/sys_darwin_arm.s b/src/runtime/sys_darwin_arm.s
index 087dec5..82a8db9 100644
--- a/src/runtime/sys_darwin_arm.s
+++ b/src/runtime/sys_darwin_arm.s
@@ -24,9 +24,9 @@
 #define	SYS_kill           37
 #define	SYS_getpid         20
 #define	SYS___pthread_kill 328
+#define	SYS_pthread_sigmask 329
 #define	SYS_setitimer      83
 #define	SYS___sysctl       202
-#define	SYS_sigprocmask    48
 #define	SYS_sigaction      46
 #define	SYS_sigreturn      184
 #define	SYS_select         93
@@ -194,6 +194,18 @@ TEXT runtime·nanotime(SB),NOSPLIT,$32
 	MOVW	R1, ret_hi+4(FP)
 	RET
 
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
+	MOVW	sig+4(FP), R0
+	MOVW	info+8(FP), R1
+	MOVW	ctx+12(FP), R2
+	MOVW	fn+0(FP), R11
+	MOVW	R13, R4
+	SUB	$24, R13
+	BIC	$0x7, R13 // alignment for ELF ABI
+	BL	(R11)
+	MOVW	R4, R13
+	RET
+
 // Sigtramp's job is to call the actual signal handler.
 // It is called with the following arguments on the stack:
 //	 LR  	"return address" - ignored
@@ -268,7 +280,7 @@ TEXT runtime·sigprocmask(SB),NOSPLIT,$0
 	MOVW	sig+0(FP), R0
 	MOVW	new+4(FP), R1
 	MOVW	old+8(FP), R2
-	MOVW	$SYS_sigprocmask, R12
+	MOVW	$SYS_pthread_sigmask, R12
 	SWI	$0x80
 	BL.CS	notok<>(SB)
 	RET
@@ -297,12 +309,6 @@ TEXT runtime·usleep(SB),NOSPLIT,$12
 	SWI	$0x80
 	RET
 
-TEXT runtime·cas(SB),NOSPLIT,$0
-	B	runtime·armcas(SB)
-
-TEXT runtime·casp1(SB),NOSPLIT,$0
-	B	runtime·cas(SB)
-
 TEXT ·publicationBarrier(SB),NOSPLIT,$-4-0
 	B	runtime·armPublicationBarrier(SB)
 
diff --git a/src/runtime/sys_darwin_arm64.s b/src/runtime/sys_darwin_arm64.s
index 0f9da85..d0034d5 100644
--- a/src/runtime/sys_darwin_arm64.s
+++ b/src/runtime/sys_darwin_arm64.s
@@ -24,9 +24,9 @@
 #define	SYS_kill           37
 #define	SYS_getpid         20
 #define	SYS___pthread_kill 328
+#define	SYS_pthread_sigmask 329
 #define	SYS_setitimer      83
 #define	SYS___sysctl       202
-#define	SYS_sigprocmask    48
 #define	SYS_sigaction      46
 #define	SYS_sigreturn      184
 #define	SYS_select         93
@@ -180,6 +180,14 @@ TEXT runtime·nanotime(SB),NOSPLIT,$40
 	MOVD	R0, ret+0(FP)
 	RET
 
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
+	MOVW	sig+8(FP), R0
+	MOVD	info+16(FP), R1
+	MOVD	ctx+24(FP), R2
+	MOVD	fn+0(FP), R11
+	BL	(R11)
+	RET
+
 // Sigtramp's job is to call the actual signal handler.
 // It is called with the following arguments on the stack:
 //	LR	"return address" - ignored
@@ -256,7 +264,7 @@ TEXT runtime·sigprocmask(SB),NOSPLIT,$0
 	MOVW	sig+0(FP), R0
 	MOVD	new+8(FP), R1
 	MOVD	old+16(FP), R2
-	MOVW	$SYS_sigprocmask, R16
+	MOVW	$SYS_pthread_sigmask, R16
 	SVC	$0x80
 	BCC	2(PC)
 	BL	notok<>(SB)
diff --git a/src/runtime/sys_dragonfly_amd64.s b/src/runtime/sys_dragonfly_amd64.s
index 26c9784..4e4d793 100644
--- a/src/runtime/sys_dragonfly_amd64.s
+++ b/src/runtime/sys_dragonfly_amd64.s
@@ -51,6 +51,18 @@ TEXT runtime·lwp_start(SB),NOSPLIT,$0
 	MOVQ	R13, g_m(DI)
 	MOVQ	DI, g(CX)
 
+	// On DragonFly, a new thread inherits the signal stack of the
+	// creating thread.  That confuses minit, so we remove that
+	// signal stack here before calling the regular mstart.  It's
+	// a bit baroque to remove a signal stack here only to add one
+	// in minit, but it's a simple change that keeps DragonFly
+	// working like other OS's.  At this point all signals are
+	// blocked, so there is no race.
+	SUBQ	$8, SP
+	MOVQ	$0, 0(SP)
+	CALL	runtime·signalstack(SB)
+	ADDQ	$8, SP
+
 	CALL	runtime·stackcheck(SB)
 	CALL	runtime·mstart(SB)
 
@@ -187,37 +199,19 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-8
 	MOVL	$0xf1, 0xf1  // crash
 	RET
 
-TEXT runtime·sigtramp(SB),NOSPLIT,$64
-	get_tls(BX)
-
-	// check that g exists
-	MOVQ	g(BX), R10
-	CMPQ	R10, $0
-	JNE	5(PC)
-	MOVQ	DI, 0(SP)
-	MOVQ	$runtime·badsignal(SB), AX
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
+	MOVL	sig+8(FP), DI
+	MOVQ	info+16(FP), SI
+	MOVQ	ctx+24(FP), DX
+	MOVQ	fn+0(FP), AX
 	CALL	AX
 	RET
 
-	// save g
-	MOVQ	R10, 40(SP)
-	
-	// g = m->signal
-	MOVQ	g_m(R10), AX
-	MOVQ	m_gsignal(AX), AX
-	MOVQ	AX, g(BX)
-	
+TEXT runtime·sigtramp(SB),NOSPLIT,$24
 	MOVQ	DI, 0(SP)
 	MOVQ	SI, 8(SP)
 	MOVQ	DX, 16(SP)
-	MOVQ	R10, 24(SP)
-
-	CALL	runtime·sighandler(SB)
-
-	// restore g
-	get_tls(BX)
-	MOVQ	40(SP), R10
-	MOVQ	R10, g(BX)
+	CALL	runtime·sigtrampgo(SB)
 	RET
 
 TEXT runtime·mmap(SB),NOSPLIT,$0
diff --git a/src/runtime/sys_freebsd_386.s b/src/runtime/sys_freebsd_386.s
index b2dd780..b37abce 100644
--- a/src/runtime/sys_freebsd_386.s
+++ b/src/runtime/sys_freebsd_386.s
@@ -25,7 +25,7 @@ TEXT runtime·thr_start(SB),NOSPLIT,$0
 	MOVL	mm+0(FP), AX
 	MOVL	m_g0(AX), BX
 	LEAL	m_tls(AX), BP
-	MOVL	0(BP), DI
+	MOVL	m_id(AX), DI
 	ADDL	$7, DI
 	PUSHAL
 	PUSHL	$32
@@ -207,44 +207,26 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-4
 	MOVL	$0xf1, 0xf1  // crash
 	RET
 
-TEXT runtime·sigtramp(SB),NOSPLIT,$44
-	get_tls(CX)
-
-	// check that g exists
-	MOVL	g(CX), DI
-	CMPL	DI, $0
-	JNE	6(PC)
-	MOVL	signo+0(FP), BX
-	MOVL	BX, 0(SP)
-	MOVL	$runtime·badsignal(SB), AX
+TEXT runtime·sigfwd(SB),NOSPLIT,$12-16
+	MOVL	sig+4(FP), AX
+	MOVL	AX, 0(SP)
+	MOVL	info+8(FP), AX
+	MOVL	AX, 4(SP)
+	MOVL	ctx+12(FP), AX
+	MOVL	AX, 8(SP)
+	MOVL	fn+0(FP), AX
 	CALL	AX
-	JMP 	ret
-
-	// save g
-	MOVL	DI, 20(SP)
-	
-	// g = m->gsignal
-	MOVL	g_m(DI), BX
-	MOVL	m_gsignal(BX), BX
-	MOVL	BX, g(CX)
+	RET
 
-	// copy arguments for call to sighandler
+TEXT runtime·sigtramp(SB),NOSPLIT,$12
 	MOVL	signo+0(FP), BX
 	MOVL	BX, 0(SP)
 	MOVL	info+4(FP), BX
 	MOVL	BX, 4(SP)
 	MOVL	context+8(FP), BX
 	MOVL	BX, 8(SP)
-	MOVL	DI, 12(SP)
-
-	CALL	runtime·sighandler(SB)
-
-	// restore g
-	get_tls(CX)
-	MOVL	20(SP), BX
-	MOVL	BX, g(CX)
+	CALL	runtime·sigtrampgo(SB)
 
-ret:
 	// call sigreturn
 	MOVL	context+8(FP), AX
 	MOVL	$0, 0(SP)	// syscall gap
diff --git a/src/runtime/sys_freebsd_amd64.s b/src/runtime/sys_freebsd_amd64.s
index b1c67c7..9700117 100644
--- a/src/runtime/sys_freebsd_amd64.s
+++ b/src/runtime/sys_freebsd_amd64.s
@@ -183,37 +183,19 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-8
 	MOVL	$0xf1, 0xf1  // crash
 	RET
 
-TEXT runtime·sigtramp(SB),NOSPLIT,$64
-	get_tls(BX)
-
-	// check that g exists
-	MOVQ	g(BX), R10
-	CMPQ	R10, $0
-	JNE	5(PC)
-	MOVQ	DI, 0(SP)
-	MOVQ	$runtime·badsignal(SB), AX
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
+	MOVL	sig+8(FP), DI
+	MOVQ	info+16(FP), SI
+	MOVQ	ctx+24(FP), DX
+	MOVQ	fn+0(FP), AX
 	CALL	AX
 	RET
 
-	// save g
-	MOVQ	R10, 40(SP)
-	
-	// g = m->signal
-	MOVQ	g_m(R10), AX
-	MOVQ	m_gsignal(AX), AX
-	MOVQ	AX, g(BX)
-	
+TEXT runtime·sigtramp(SB),NOSPLIT,$24
 	MOVQ	DI, 0(SP)
 	MOVQ	SI, 8(SP)
 	MOVQ	DX, 16(SP)
-	MOVQ	R10, 24(SP)
-
-	CALL	runtime·sighandler(SB)
-
-	// restore g
-	get_tls(BX)
-	MOVQ	40(SP), R10
-	MOVQ	R10, g(BX)
+	CALL	runtime·sigtrampgo(SB)
 	RET
 
 TEXT runtime·mmap(SB),NOSPLIT,$0
diff --git a/src/runtime/sys_freebsd_arm.s b/src/runtime/sys_freebsd_arm.s
index bd6ff96..e7dfb28 100644
--- a/src/runtime/sys_freebsd_arm.s
+++ b/src/runtime/sys_freebsd_arm.s
@@ -216,7 +216,7 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-8
 	MOVW.CS R8, (R8)
 	RET
 
-TEXT runtime·sigtramp(SB),NOSPLIT,$24
+TEXT runtime·sigtramp(SB),NOSPLIT,$12
 	// this might be called in external code context,
 	// where g is not set.
 	// first save R0, because runtime·load_g will clobber it
@@ -225,30 +225,9 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$24
 	CMP 	$0, R0
 	BL.NE	runtime·load_g(SB)
 
-	CMP $0, g
-	BNE 4(PC)
-	// signal number is already prepared in 4(R13)
-	MOVW $runtime·badsignal(SB), R11
-	BL (R11)
-	RET
-
-	// save g
-	MOVW g, R4
-	MOVW g, 20(R13)
-
-	// g = m->signal
-	MOVW g_m(g), R8
-	MOVW m_gsignal(R8), g
-
-	// R0 is already saved
-	MOVW R1, 8(R13) // info
-	MOVW R2, 12(R13) // context
-	MOVW R4, 16(R13) // oldg
-
-	BL runtime·sighandler(SB)
-
-	// restore g
-	MOVW 20(R13), g
+	MOVW	R1, 8(R13)
+	MOVW	R2, 12(R13)
+	BL	runtime·sigtrampgo(SB)
 	RET
 
 TEXT runtime·mmap(SB),NOSPLIT,$16
@@ -300,6 +279,18 @@ TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
 	MOVW.CS R8, (R8)
 	RET
 
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
+	MOVW	sig+4(FP), R0
+	MOVW	info+8(FP), R1
+	MOVW	ctx+12(FP), R2
+	MOVW	fn+0(FP), R11
+	MOVW	R13, R4
+	SUB	$24, R13
+	BIC	$0x7, R13 // alignment for ELF ABI
+	BL	(R11)
+	MOVW	R4, R13
+	RET
+
 TEXT runtime·usleep(SB),NOSPLIT,$16
 	MOVW usec+0(FP), R0
 	CALL runtime·usplitR0(SB)
@@ -377,20 +368,6 @@ TEXT runtime·closeonexec(SB),NOSPLIT,$0
 	SWI $0
 	RET
 
-TEXT runtime·casp1(SB),NOSPLIT,$0
-	B	runtime·cas(SB)
-
-// TODO(minux): this is only valid for ARMv6+
-// bool armcas(int32 *val, int32 old, int32 new)
-// Atomically:
-//	if(*val == old){
-//		*val = new;
-//		return 1;
-//	}else
-//		return 0;
-TEXT runtime·cas(SB),NOSPLIT,$0
-	B runtime·armcas(SB)
-
 // TODO: this is only valid for ARMv7+
 TEXT ·publicationBarrier(SB),NOSPLIT,$-4-0
 	B	runtime·armPublicationBarrier(SB)
diff --git a/src/runtime/sys_linux_386.s b/src/runtime/sys_linux_386.s
index 98a1a0e..1a3aaf0 100644
--- a/src/runtime/sys_linux_386.s
+++ b/src/runtime/sys_linux_386.s
@@ -10,17 +10,30 @@
 #include "go_tls.h"
 #include "textflag.h"
 
+// Most linux systems use glibc's dynamic linker, which puts the
+// __kernel_vsyscall vdso helper at 0x10(GS) for easy access from position
+// independent code and setldt in this file does the same in the statically
+// linked case. Android, however, uses bionic's dynamic linker, which does not
+// save the helper anywhere, and so the only way to invoke a syscall from
+// position independent code is boring old int $0x80 (which is also what
+// bionic's syscall wrappers use).
+#ifdef GOOS_android
+#define INVOKE_SYSCALL	INT	$0x80
+#else
+#define INVOKE_SYSCALL	CALL	0x10(GS)
+#endif
+
 TEXT runtime·exit(SB),NOSPLIT,$0
 	MOVL	$252, AX	// syscall number
 	MOVL	code+0(FP), BX
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	INT $3	// not reached
 	RET
 
 TEXT runtime·exit1(SB),NOSPLIT,$0
 	MOVL	$1, AX	// exit - exit the current os thread
 	MOVL	code+0(FP), BX
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	INT $3	// not reached
 	RET
 
@@ -29,7 +42,7 @@ TEXT runtime·open(SB),NOSPLIT,$0
 	MOVL	name+0(FP), BX
 	MOVL	mode+4(FP), CX
 	MOVL	perm+8(FP), DX
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	CMPL	AX, $0xfffff001
 	JLS	2(PC)
 	MOVL	$-1, AX
@@ -39,7 +52,7 @@ TEXT runtime·open(SB),NOSPLIT,$0
 TEXT runtime·closefd(SB),NOSPLIT,$0
 	MOVL	$6, AX		// syscall - close
 	MOVL	fd+0(FP), BX
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	CMPL	AX, $0xfffff001
 	JLS	2(PC)
 	MOVL	$-1, AX
@@ -51,7 +64,7 @@ TEXT runtime·write(SB),NOSPLIT,$0
 	MOVL	fd+0(FP), BX
 	MOVL	p+4(FP), CX
 	MOVL	n+8(FP), DX
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	CMPL	AX, $0xfffff001
 	JLS	2(PC)
 	MOVL	$-1, AX
@@ -63,7 +76,7 @@ TEXT runtime·read(SB),NOSPLIT,$0
 	MOVL	fd+0(FP), BX
 	MOVL	p+4(FP), CX
 	MOVL	n+8(FP), DX
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	CMPL	AX, $0xfffff001
 	JLS	2(PC)
 	MOVL	$-1, AX
@@ -74,7 +87,7 @@ TEXT runtime·getrlimit(SB),NOSPLIT,$0
 	MOVL	$191, AX		// syscall - ugetrlimit
 	MOVL	kind+0(FP), BX
 	MOVL	limit+4(FP), CX
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	MOVL	AX, ret+8(FP)
 	RET
 
@@ -93,31 +106,31 @@ TEXT runtime·usleep(SB),NOSPLIT,$8
 	MOVL	$0, DX
 	MOVL	$0, SI
 	LEAL	0(SP), DI
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	RET
 
 TEXT runtime·gettid(SB),NOSPLIT,$0-4
 	MOVL	$224, AX	// syscall - gettid
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	MOVL	AX, ret+0(FP)
 	RET
 
 TEXT runtime·raise(SB),NOSPLIT,$12
 	MOVL	$224, AX	// syscall - gettid
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	MOVL	AX, BX	// arg 1 tid
 	MOVL	sig+0(FP), CX	// arg 2 signal
 	MOVL	$238, AX	// syscall - tkill
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	RET
 
 TEXT runtime·raiseproc(SB),NOSPLIT,$12
 	MOVL	$20, AX	// syscall - getpid
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	MOVL	AX, BX	// arg 1 pid
 	MOVL	sig+0(FP), CX	// arg 2 signal
 	MOVL	$37, AX	// syscall - kill
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	RET
 
 TEXT runtime·setitimer(SB),NOSPLIT,$0-12
@@ -125,7 +138,7 @@ TEXT runtime·setitimer(SB),NOSPLIT,$0-12
 	MOVL	mode+0(FP), BX
 	MOVL	new+4(FP), CX
 	MOVL	old+8(FP), DX
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	RET
 
 TEXT runtime·mincore(SB),NOSPLIT,$0-16
@@ -133,7 +146,7 @@ TEXT runtime·mincore(SB),NOSPLIT,$0-16
 	MOVL	addr+0(FP), BX
 	MOVL	n+4(FP), CX
 	MOVL	dst+8(FP), DX
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	MOVL	AX, ret+12(FP)
 	RET
 
@@ -143,7 +156,7 @@ TEXT time·now(SB), NOSPLIT, $32
 	MOVL	$0, BX		// CLOCK_REALTIME
 	LEAL	8(SP), CX
 	MOVL	$0, DX
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	MOVL	8(SP), AX	// sec
 	MOVL	12(SP), BX	// nsec
 
@@ -160,7 +173,7 @@ TEXT runtime·nanotime(SB), NOSPLIT, $32
 	MOVL	$1, BX		// CLOCK_MONOTONIC
 	LEAL	8(SP), CX
 	MOVL	$0, DX
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	MOVL	8(SP), AX	// sec
 	MOVL	12(SP), BX	// nsec
 
@@ -181,7 +194,7 @@ TEXT runtime·rtsigprocmask(SB),NOSPLIT,$0
 	MOVL	new+4(FP), CX
 	MOVL	old+8(FP), DX
 	MOVL	size+12(FP), SI
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	CMPL	AX, $0xfffff001
 	JLS	2(PC)
 	INT $3
@@ -193,7 +206,7 @@ TEXT runtime·rt_sigaction(SB),NOSPLIT,$0
 	MOVL	new+4(FP), CX
 	MOVL	old+8(FP), DX
 	MOVL	size+12(FP), SI
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	MOVL	AX, ret+16(FP)
 	RET
 
@@ -221,9 +234,9 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$12
 TEXT runtime·sigreturn(SB),NOSPLIT,$0
 	MOVL	$173, AX	// rt_sigreturn
 	// Sigreturn expects same SP as signal handler,
-	// so cannot CALL *runtime._vsdo(SB) here.
+	// so cannot CALL 0x10(GS) here.
 	INT	$0x80
-	INT $3	// not reached
+	INT	$3	// not reached
 	RET
 
 TEXT runtime·mmap(SB),NOSPLIT,$0
@@ -235,7 +248,7 @@ TEXT runtime·mmap(SB),NOSPLIT,$0
 	MOVL	fd+16(FP), DI
 	MOVL	off+20(FP), BP
 	SHRL	$12, BP
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	CMPL	AX, $0xfffff001
 	JLS	3(PC)
 	NOTL	AX
@@ -247,7 +260,7 @@ TEXT runtime·munmap(SB),NOSPLIT,$0
 	MOVL	$91, AX	// munmap
 	MOVL	addr+0(FP), BX
 	MOVL	n+4(FP), CX
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	CMPL	AX, $0xfffff001
 	JLS	2(PC)
 	INT $3
@@ -258,7 +271,7 @@ TEXT runtime·madvise(SB),NOSPLIT,$0
 	MOVL	addr+0(FP), BX
 	MOVL	n+4(FP), CX
 	MOVL	flags+8(FP), DX
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	// ignore failure - maybe pages are locked
 	RET
 
@@ -272,7 +285,7 @@ TEXT runtime·futex(SB),NOSPLIT,$0
 	MOVL	ts+12(FP), SI
 	MOVL	addr2+16(FP), DI
 	MOVL	val3+20(FP), BP
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	MOVL	AX, ret+24(FP)
 	RET
 
@@ -294,10 +307,9 @@ TEXT runtime·clone(SB),NOSPLIT,$0
 	MOVL	SI, 8(CX)
 	MOVL	$1234, 12(CX)
 
-	// cannot use CALL *runtime·_vdso(SB) here, because
-	// the stack changes during the system call (after
-	// CALL *runtime·_vdso(SB), the child is still using
-	// the parent's stack when executing its RET instruction).
+	// cannot use CALL 0x10(GS) here, because the stack changes during the
+	// system call (after CALL 0x10(GS), the child is still using the
+	// parent's stack when executing its RET instruction).
 	INT	$0x80
 
 	// In parent, return.
@@ -314,7 +326,7 @@ TEXT runtime·clone(SB),NOSPLIT,$0
 
 	// Initialize AX to Linux tid
 	MOVL	$224, AX
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 
 	MOVL	0(SP), BX	    // m
 	MOVL	4(SP), DX	    // g
@@ -328,9 +340,8 @@ TEXT runtime·clone(SB),NOSPLIT,$0
 	MOVL	AX, m_procid(BX)	// save tid as m->procid
 
 	// set up ldt 7+id to point at m->tls.
-	// newosproc left the id in tls[0].
 	LEAL	m_tls(BX), BP
-	MOVL	0(BP), DI
+	MOVL	m_id(BX), DI
 	ADDL	$7, DI	// m0 is LDT#7. count up.
 	// setldt(tls#, &tls, sizeof tls)
 	PUSHAL	// save registers
@@ -366,7 +377,7 @@ TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
 	MOVL	$186, AX	// sigaltstack
 	MOVL	new+4(SP), BX
 	MOVL	old+8(SP), CX
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	CMPL	AX, $0xfffff001
 	JLS	2(PC)
 	INT	$3
@@ -397,8 +408,17 @@ TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
 // setldt(int entry, int address, int limit)
 TEXT runtime·setldt(SB),NOSPLIT,$32
 	MOVL	entry+0(FP), BX	// entry
-	MOVL	address+4(FP), CX	// base address
+	MOVL	address+4(FP), DX	// base address
 
+#ifdef GOOS_android
+	/*
+	 * Same as in sys_darwin_386.s:/ugliness, different constant.
+	 * address currently holds m->tls, which must be %gs:0xf8.
+	 * See cgo/gcc_android_386.c for the derivation of the constant.
+	 */
+	SUBL	$0xf8, DX
+	MOVL	DX, 0(DX)
+#else
 	/*
 	 * When linking against the system libraries,
 	 * we use its pthread_create and let it set up %gs
@@ -409,16 +429,23 @@ TEXT runtime·setldt(SB),NOSPLIT,$32
 	 * To accommodate that rewrite, we translate
 	 * the address here and bump the limit to 0xffffffff (no limit)
 	 * so that -4(GS) maps to 0(address).
-	 * Also, the final 0(GS) (current 4(CX)) has to point
+	 * Also, the final 0(GS) (current 4(DX)) has to point
 	 * to itself, to mimic ELF.
 	 */
-	ADDL	$0x4, CX	// address
-	MOVL	CX, 0(CX)
+	ADDL	$0x4, DX	// address
+	MOVL	DX, 0(DX)
+        // We copy the glibc dynamic linker behaviour of storing the
+        // __kernel_vsyscall entry point at 0x10(GS) so that it can be invoked
+        // by "CALL 0x10(GS)" in all situations, not only those where the
+        // binary is actually dynamically linked.
+	MOVL	runtime·_vdso(SB), AX
+	MOVL	AX, 0x10(DX)
+#endif
 
 	// set up user_desc
 	LEAL	16(SP), AX	// struct user_desc
 	MOVL	BX, 0(AX)
-	MOVL	CX, 4(AX)
+	MOVL	DX, 4(AX)
 	MOVL	$0xfffff, 8(AX)
 	MOVL	$(SEG_32BIT|LIMIT_IN_PAGES|USEABLE|CONTENTS_DATA), 12(AX)	// flag bits
 
@@ -427,7 +454,8 @@ TEXT runtime·setldt(SB),NOSPLIT,$32
 	MOVL	AX, CX	// user_desc
 	MOVL	$16, DX	// sizeof(user_desc)
 	MOVL	$123, AX	// syscall - modify_ldt
-	CALL	*runtime·_vdso(SB)
+	// We can't call this via 0x10(GS) because this is called from setldt0 to set that up.
+	INT     $0x80
 
 	// breakpoint on error
 	CMPL AX, $0xfffff001
@@ -444,7 +472,7 @@ TEXT runtime·setldt(SB),NOSPLIT,$32
 
 TEXT runtime·osyield(SB),NOSPLIT,$0
 	MOVL	$158, AX
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	RET
 
 TEXT runtime·sched_getaffinity(SB),NOSPLIT,$0
@@ -452,7 +480,7 @@ TEXT runtime·sched_getaffinity(SB),NOSPLIT,$0
 	MOVL	pid+0(FP), BX
 	MOVL	len+4(FP), CX
 	MOVL	buf+8(FP), DX
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	MOVL	AX, ret+12(FP)
 	RET
 
@@ -460,7 +488,7 @@ TEXT runtime·sched_getaffinity(SB),NOSPLIT,$0
 TEXT runtime·epollcreate(SB),NOSPLIT,$0
 	MOVL    $254, AX
 	MOVL	size+0(FP), BX
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	MOVL	AX, ret+4(FP)
 	RET
 
@@ -468,7 +496,7 @@ TEXT runtime·epollcreate(SB),NOSPLIT,$0
 TEXT runtime·epollcreate1(SB),NOSPLIT,$0
 	MOVL    $329, AX
 	MOVL	flags+0(FP), BX
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	MOVL	AX, ret+4(FP)
 	RET
 
@@ -479,7 +507,7 @@ TEXT runtime·epollctl(SB),NOSPLIT,$0
 	MOVL	op+4(FP), CX
 	MOVL	fd+8(FP), DX
 	MOVL	ev+12(FP), SI
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	MOVL	AX, ret+16(FP)
 	RET
 
@@ -490,7 +518,7 @@ TEXT runtime·epollwait(SB),NOSPLIT,$0
 	MOVL	ev+4(FP), CX
 	MOVL	nev+8(FP), DX
 	MOVL	timeout+12(FP), SI
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	MOVL	AX, ret+16(FP)
 	RET
 
@@ -500,5 +528,36 @@ TEXT runtime·closeonexec(SB),NOSPLIT,$0
 	MOVL	fd+0(FP), BX  // fd
 	MOVL	$2, CX  // F_SETFD
 	MOVL	$1, DX  // FD_CLOEXEC
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
+	RET
+
+// int access(const char *name, int mode)
+TEXT runtime·access(SB),NOSPLIT,$0
+	MOVL	$33, AX  // syscall - access
+	MOVL	name+0(FP), BX
+	MOVL	mode+4(FP), CX
+	INVOKE_SYSCALL
+	MOVL	AX, ret+8(FP)
+	RET
+
+// int connect(int fd, const struct sockaddr *addr, socklen_t addrlen)
+TEXT runtime·connect(SB),NOSPLIT,$0-16
+	// connect is implemented as socketcall(NR_socket, 3, *(rest of args))
+	// stack already should have fd, addr, addrlen.
+	MOVL	$102, AX  // syscall - socketcall
+	MOVL	$3, BX  // connect
+	LEAL	fd+0(FP), CX
+	INVOKE_SYSCALL
+	MOVL	AX, ret+12(FP)
+	RET
+
+// int socket(int domain, int type, int protocol)
+TEXT runtime·socket(SB),NOSPLIT,$0-16
+	// socket is implemented as socketcall(NR_socket, 1, *(rest of args))
+	// stack already should have domain, type, protocol.
+	MOVL	$102, AX  // syscall - socketcall
+	MOVL	$1, BX  // socket
+	LEAL	domain+0(FP), CX
+	INVOKE_SYSCALL
+	MOVL	AX, ret+12(FP)
 	RET
diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s
index 59c21c5..aed85cb 100644
--- a/src/runtime/sys_linux_amd64.s
+++ b/src/runtime/sys_linux_amd64.s
@@ -239,7 +239,7 @@ TEXT runtime·sigreturn(SB),NOSPLIT,$0
 	SYSCALL
 	INT $3	// not reached
 
-TEXT runtime·mmap(SB),NOSPLIT,$0
+TEXT runtime·sysMmap(SB),NOSPLIT,$0
 	MOVQ	addr+0(FP), DI
 	MOVQ	n+8(FP), SI
 	MOVL	prot+16(FP), DX
@@ -256,6 +256,20 @@ TEXT runtime·mmap(SB),NOSPLIT,$0
 	MOVQ	AX, ret+32(FP)
 	RET
 
+// Call the function stored in _cgo_mmap using the GCC calling convention.
+// This must be called on the system stack.
+TEXT runtime·callCgoMmap(SB),NOSPLIT,$0
+	MOVQ	addr+0(FP), DI
+	MOVQ	n+8(FP), SI
+	MOVL	prot+16(FP), DX
+	MOVL	flags+20(FP), CX
+	MOVL	fd+24(FP), R8
+	MOVL	off+28(FP), R9
+	MOVQ	_cgo_mmap(SB), AX
+	CALL	AX
+	MOVQ	AX, ret+32(FP)
+	RET
+
 TEXT runtime·munmap(SB),NOSPLIT,$0
 	MOVQ	addr+0(FP), DI
 	MOVQ	n+8(FP), SI
@@ -357,8 +371,14 @@ TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
 
 // set tls base to DI
 TEXT runtime·settls(SB),NOSPLIT,$32
+#ifdef GOOS_android
+	// Same as in sys_darwin_386.s:/ugliness, different constant.
+	// DI currently holds m->tls, which must be fs:0x1d0.
+	// See cgo/gcc_android_amd64.c for the derivation of the constant.
+	SUBQ	$0x1d0, DI  // In android, the tls base 
+#else
 	ADDQ	$8, DI	// ELF wants to use -8(FS)
-
+#endif
 	MOVQ	DI, SI
 	MOVQ	$0x1002, DI	// ARCH_SET_FS
 	MOVQ	$158, AX	// arch_prctl
@@ -428,3 +448,33 @@ TEXT runtime·closeonexec(SB),NOSPLIT,$0
 	MOVL	$72, AX  // fcntl
 	SYSCALL
 	RET
+
+
+// int access(const char *name, int mode)
+TEXT runtime·access(SB),NOSPLIT,$0
+	MOVQ	name+0(FP), DI
+	MOVL	mode+8(FP), SI
+	MOVL	$21, AX  // syscall entry
+	SYSCALL
+	MOVL	AX, ret+16(FP)
+	RET
+
+// int connect(int fd, const struct sockaddr *addr, socklen_t addrlen)
+TEXT runtime·connect(SB),NOSPLIT,$0-28
+	MOVL	fd+0(FP), DI
+	MOVQ	addr+8(FP), SI
+	MOVL	addrlen+16(FP), DX
+	MOVL	$42, AX  // syscall entry
+	SYSCALL
+	MOVL	AX, ret+24(FP)
+	RET
+
+// int socket(int domain, int type, int protocol)
+TEXT runtime·socket(SB),NOSPLIT,$0-20
+	MOVL	domain+0(FP), DI
+	MOVL	type+4(FP), SI
+	MOVL	protocol+8(FP), DX
+	MOVL	$41, AX  // syscall entry
+	SYSCALL
+	MOVL	AX, ret+16(FP)
+	RET
diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s
index 29eb8eb..6a3b924 100644
--- a/src/runtime/sys_linux_arm.s
+++ b/src/runtime/sys_linux_arm.s
@@ -339,7 +339,11 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
 	MOVW	info+8(FP), R1
 	MOVW	ctx+12(FP), R2
 	MOVW	fn+0(FP), R11
+	MOVW	R13, R4
+	SUB	$24, R13
+	BIC	$0x7, R13 // alignment for ELF ABI
 	BL	(R11)
+	MOVW	R4, R13
 	RET
 
 TEXT runtime·sigtramp(SB),NOSPLIT,$12
@@ -390,35 +394,6 @@ TEXT runtime·usleep(SB),NOSPLIT,$12
 	SWI	$0
 	RET
 
-// Use kernel version instead of native armcas in asm_arm.s.
-// See ../sync/atomic/asm_linux_arm.s for details.
-TEXT cas<>(SB),NOSPLIT,$0
-	MOVW	$0xffff0fc0, R15 // R15 is hardware PC.
-
-TEXT runtime·cas(SB),NOSPLIT,$0
-	MOVW	ptr+0(FP), R2
-	MOVW	old+4(FP), R0
-loop:
-	MOVW	new+8(FP), R1
-	BL	cas<>(SB)
-	BCC	check
-	MOVW	$1, R0
-	MOVB	R0, ret+12(FP)
-	RET
-check:
-	// Kernel lies; double-check.
-	MOVW	ptr+0(FP), R2
-	MOVW	old+4(FP), R0
-	MOVW	0(R2), R3
-	CMP	R0, R3
-	BEQ	loop
-	MOVW	$0, R0
-	MOVB	R0, ret+12(FP)
-	RET
-
-TEXT runtime·casp1(SB),NOSPLIT,$0
-	B	runtime·cas(SB)
-
 // As for cas, memory barriers are complicated on ARM, but the kernel
 // provides a user helper. ARMv5 does not support SMP and has no
 // memory barrier instruction at all. ARMv6 added SMP support and has
diff --git a/src/runtime/sys_linux_arm64.s b/src/runtime/sys_linux_arm64.s
index 7b58d67..94c101a 100644
--- a/src/runtime/sys_linux_arm64.s
+++ b/src/runtime/sys_linux_arm64.s
@@ -43,6 +43,9 @@
 #define SYS_epoll_ctl		21
 #define SYS_epoll_pwait		22
 #define SYS_clock_gettime	113
+#define SYS_faccessat		48
+#define SYS_socket		198
+#define SYS_connect		203
 
 TEXT runtime·exit(SB),NOSPLIT,$-8-4
 	MOVW	code+0(FP), R0
@@ -266,6 +269,9 @@ TEXT runtime·mmap(SB),NOSPLIT,$-8
 
 	MOVD	$SYS_mmap, R8
 	SVC
+	CMN	$4095, R0
+	BCC	2(PC)
+	NEG	R0,R0
 	MOVD	R0, ret+32(FP)
 	RET
 
@@ -445,3 +451,33 @@ TEXT runtime·closeonexec(SB),NOSPLIT,$-8
 	MOVD	$SYS_fcntl, R8
 	SVC
 	RET
+
+// int access(const char *name, int mode)
+TEXT runtime·access(SB),NOSPLIT,$0-20
+	MOVD	$AT_FDCWD, R0
+	MOVD	name+0(FP), R1
+	MOVW	mode+8(FP), R2
+	MOVD	$SYS_faccessat, R8
+	SVC
+	MOVW	R0, ret+16(FP)
+	RET
+
+// int connect(int fd, const struct sockaddr *addr, socklen_t len)
+TEXT runtime·connect(SB),NOSPLIT,$0-28
+	MOVW	fd+0(FP), R0
+	MOVD	addr+8(FP), R1
+	MOVW	len+16(FP), R2
+	MOVD	$SYS_connect, R8
+	SVC
+	MOVW	R0, ret+24(FP)
+	RET
+
+// int socket(int domain, int typ, int prot)
+TEXT runtime·socket(SB),NOSPLIT,$0-20
+	MOVW	domain+0(FP), R0
+	MOVW	typ+4(FP), R1
+	MOVW	prot+8(FP), R2
+	MOVD	$SYS_socket, R8
+	SVC
+	MOVW	R0, ret+16(FP)
+	RET
diff --git a/src/runtime/sys_linux_mips64x.s b/src/runtime/sys_linux_mips64x.s
new file mode 100644
index 0000000..26437dd
--- /dev/null
+++ b/src/runtime/sys_linux_mips64x.s
@@ -0,0 +1,428 @@
+// Copyright 2015 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.
+
+// +build linux
+// +build mips64 mips64le
+
+//
+// System calls and other sys.stuff for mips64, Linux
+//
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "textflag.h"
+
+#define SYS_exit		5058
+#define SYS_read		5000
+#define SYS_write		5001
+#define SYS_open		5002
+#define SYS_close		5003
+#define SYS_getpid		5038
+#define SYS_kill		5060
+#define SYS_fcntl		5080
+#define SYS_gettimeofday	5094
+#define SYS_mmap		5009
+#define SYS_munmap		5011
+#define SYS_setitimer		5036
+#define SYS_clone		5055
+#define SYS_newselect		5022
+#define SYS_sched_yield		5023
+#define SYS_rt_sigreturn	5211
+#define SYS_rt_sigaction	5013
+#define SYS_rt_sigprocmask	5014
+#define SYS_sigaltstack		5129
+#define SYS_getrlimit		5095
+#define SYS_madvise		5027
+#define SYS_mincore		5026
+#define SYS_gettid		5178
+#define SYS_tkill		5192
+#define SYS_futex		5194
+#define SYS_sched_getaffinity	5196
+#define SYS_exit_group		5205
+#define SYS_epoll_create	5207
+#define SYS_epoll_ctl		5208
+#define SYS_epoll_wait		5209
+#define SYS_clock_gettime	5222
+#define SYS_epoll_create1	5285
+
+TEXT runtime·exit(SB),NOSPLIT,$-8-4
+	MOVW	code+0(FP), R4
+	MOVV	$SYS_exit_group, R2
+	SYSCALL
+	RET
+
+TEXT runtime·exit1(SB),NOSPLIT,$-8-4
+	MOVW	code+0(FP), R4
+	MOVV	$SYS_exit, R2
+	SYSCALL
+	RET
+
+TEXT runtime·open(SB),NOSPLIT,$-8-20
+	MOVV	name+0(FP), R4
+	MOVW	mode+8(FP), R5
+	MOVW	perm+12(FP), R6
+	MOVV	$SYS_open, R2
+	SYSCALL
+	BEQ	R7, 2(PC)
+	MOVW	$-1, R2
+	MOVW	R2, ret+16(FP)
+	RET
+
+TEXT runtime·closefd(SB),NOSPLIT,$-8-12
+	MOVW	fd+0(FP), R4
+	MOVV	$SYS_close, R2
+	SYSCALL
+	BEQ	R7, 2(PC)
+	MOVW	$-1, R2
+	MOVW	R2, ret+8(FP)
+	RET
+
+TEXT runtime·write(SB),NOSPLIT,$-8-28
+	MOVV	fd+0(FP), R4
+	MOVV	p+8(FP), R5
+	MOVW	n+16(FP), R6
+	MOVV	$SYS_write, R2
+	SYSCALL
+	BEQ	R7, 2(PC)
+	MOVW	$-1, R2
+	MOVW	R2, ret+24(FP)
+	RET
+
+TEXT runtime·read(SB),NOSPLIT,$-8-28
+	MOVW	fd+0(FP), R4
+	MOVV	p+8(FP), R5
+	MOVW	n+16(FP), R6
+	MOVV	$SYS_read, R2
+	SYSCALL
+	BEQ	R7, 2(PC)
+	MOVW	$-1, R2
+	MOVW	R2, ret+24(FP)
+	RET
+
+TEXT runtime·getrlimit(SB),NOSPLIT,$-8-20
+	MOVW	kind+0(FP), R4	// _RLIMIT_AS = 6 on linux/mips
+	MOVV	limit+8(FP), R5
+	MOVV	$SYS_getrlimit, R2
+	SYSCALL
+	MOVW	R2, ret+16(FP)
+	RET
+
+TEXT runtime·usleep(SB),NOSPLIT,$16-4
+	MOVWU	usec+0(FP), R3
+	MOVV	R3, R5
+	MOVW	$1000000, R4
+	DIVVU	R4, R3
+	MOVV	LO, R3
+	MOVV	R3, 8(R29)
+	MULVU	R3, R4
+	MOVV	LO, R4
+	SUBVU	R4, R5
+	MOVV	R5, 16(R29)
+
+	// select(0, 0, 0, 0, &tv)
+	MOVW	$0, R4
+	MOVW	$0, R5
+	MOVW	$0, R6
+	MOVW	$0, R7
+	ADDV	$8, R29, R8
+	MOVV	$SYS_newselect, R2
+	SYSCALL
+	RET
+
+TEXT runtime·gettid(SB),NOSPLIT,$0-4
+	MOVV	$SYS_gettid, R2
+	SYSCALL
+	MOVW	R2, ret+0(FP)
+	RET
+
+TEXT runtime·raise(SB),NOSPLIT,$-8
+	MOVV	$SYS_gettid, R2
+	SYSCALL
+	MOVW	R2, R4	// arg 1 tid
+	MOVW	sig+0(FP), R5	// arg 2
+	MOVV	$SYS_tkill, R2
+	SYSCALL
+	RET
+
+TEXT runtime·raiseproc(SB),NOSPLIT,$-8
+	MOVV	$SYS_getpid, R2
+	SYSCALL
+	MOVW	R2, R4	// arg 1 pid
+	MOVW	sig+0(FP), R5	// arg 2
+	MOVV	$SYS_kill, R2
+	SYSCALL
+	RET
+
+TEXT runtime·setitimer(SB),NOSPLIT,$-8-24
+	MOVW	mode+0(FP), R4
+	MOVV	new+8(FP), R5
+	MOVV	old+16(FP), R6
+	MOVV	$SYS_setitimer, R2
+	SYSCALL
+	RET
+
+TEXT runtime·mincore(SB),NOSPLIT,$-8-28
+	MOVV	addr+0(FP), R4
+	MOVV	n+8(FP), R5
+	MOVV	dst+16(FP), R6
+	MOVV	$SYS_mincore, R2
+	SYSCALL
+	SUBVU	R2, R0, R2	// caller expects negative errno
+	MOVW	R2, ret+24(FP)
+	RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB),NOSPLIT,$16
+	MOVV	$0(R29), R4
+	MOVV	$0, R5
+	MOVV	$SYS_gettimeofday, R2
+	SYSCALL
+	MOVV	0(R29), R3	// sec
+	MOVV	8(R29), R5	// usec
+	MOVV	$1000, R4
+	MULVU	R4, R5
+	MOVV	LO, R5
+	MOVV	R3, sec+0(FP)
+	MOVW	R5, nsec+8(FP)
+	RET
+
+TEXT runtime·nanotime(SB),NOSPLIT,$16
+	MOVW	$1, R4 // CLOCK_MONOTONIC
+	MOVV	$0(R29), R5
+	MOVV	$SYS_clock_gettime, R2
+	SYSCALL
+	MOVV	0(R29), R3	// sec
+	MOVV	8(R29), R5	// nsec
+	// sec is in R3, nsec in R5
+	// return nsec in R3
+	MOVV	$1000000000, R4
+	MULVU	R4, R3
+	MOVV	LO, R3
+	ADDVU	R5, R3
+	MOVV	R3, ret+0(FP)
+	RET
+
+TEXT runtime·rtsigprocmask(SB),NOSPLIT,$-8-28
+	MOVW	sig+0(FP), R4
+	MOVV	new+8(FP), R5
+	MOVV	old+16(FP), R6
+	MOVW	size+24(FP), R7
+	MOVV	$SYS_rt_sigprocmask, R2
+	SYSCALL
+	BEQ	R7, 2(PC)
+	MOVV	R0, 0xf1(R0)	// crash
+	RET
+
+TEXT runtime·rt_sigaction(SB),NOSPLIT,$-8-36
+	MOVV	sig+0(FP), R4
+	MOVV	new+8(FP), R5
+	MOVV	old+16(FP), R6
+	MOVV	size+24(FP), R7
+	MOVV	$SYS_rt_sigaction, R2
+	SYSCALL
+	MOVW	R2, ret+32(FP)
+	RET
+
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
+	MOVW	sig+8(FP), R4
+	MOVV	info+16(FP), R5
+	MOVV	ctx+24(FP), R6
+	MOVV	fn+0(FP), R1
+	JAL	(R1)
+	RET
+
+TEXT runtime·sigtramp(SB),NOSPLIT,$64
+	// initialize essential registers (just in case)
+	JAL	runtime·reginit(SB)
+
+	// this might be called in external code context,
+	// where g is not set.
+	MOVB	runtime·iscgo(SB), R1
+	BEQ	R1, 2(PC)
+	JAL	runtime·load_g(SB)
+
+	MOVW	R4, 8(R29)
+	MOVV	R5, 16(R29)
+	MOVV	R6, 24(R29)
+	MOVV	$runtime·sigtrampgo(SB), R1
+	JAL	(R1)
+	RET
+
+TEXT runtime·mmap(SB),NOSPLIT,$-8
+	MOVV	addr+0(FP), R4
+	MOVV	n+8(FP), R5
+	MOVW	prot+16(FP), R6
+	MOVW	flags+20(FP), R7
+	MOVW	fd+24(FP), R8
+	MOVW	off+28(FP), R9
+
+	MOVV	$SYS_mmap, R2
+	SYSCALL
+	MOVV	R2, ret+32(FP)
+	RET
+
+TEXT runtime·munmap(SB),NOSPLIT,$-8
+	MOVV	addr+0(FP), R4
+	MOVV	n+8(FP), R5
+	MOVV	$SYS_munmap, R2
+	SYSCALL
+	BEQ	R7, 2(PC)
+	MOVV	R0, 0xf3(R0)	// crash
+	RET
+
+TEXT runtime·madvise(SB),NOSPLIT,$-8
+	MOVV	addr+0(FP), R4
+	MOVV	n+8(FP), R5
+	MOVW	flags+16(FP), R6
+	MOVV	$SYS_madvise, R2
+	SYSCALL
+	// ignore failure - maybe pages are locked
+	RET
+
+// int64 futex(int32 *uaddr, int32 op, int32 val,
+//	struct timespec *timeout, int32 *uaddr2, int32 val2);
+TEXT runtime·futex(SB),NOSPLIT,$-8
+	MOVV	addr+0(FP), R4
+	MOVW	op+8(FP), R5
+	MOVW	val+12(FP), R6
+	MOVV	ts+16(FP), R7
+	MOVV	addr2+24(FP), R8
+	MOVW	val3+32(FP), R9
+	MOVV	$SYS_futex, R2
+	SYSCALL
+	MOVW	R2, ret+40(FP)
+	RET
+
+// int64 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
+TEXT runtime·clone(SB),NOSPLIT,$-8
+	MOVW	flags+0(FP), R4
+	MOVV	stk+8(FP), R5
+
+	// Copy mp, gp, fn off parent stack for use by child.
+	// Careful: Linux system call clobbers ???.
+	MOVV	mm+16(FP), R16
+	MOVV	gg+24(FP), R17
+	MOVV	fn+32(FP), R18
+
+	MOVV	R16, -8(R5)
+	MOVV	R17, -16(R5)
+	MOVV	R18, -24(R5)
+	MOVV	$1234, R16
+	MOVV	R16, -32(R5)
+
+	MOVV	$SYS_clone, R2
+	SYSCALL
+
+	// In parent, return.
+	BEQ	R2, 3(PC)
+	MOVW	R2, ret+40(FP)
+	RET
+
+	// In child, on new stack.
+	// initialize essential registers
+	JAL	runtime·reginit(SB)
+	MOVV	-32(R29), R16
+	MOVV	$1234, R1
+	BEQ	R16, R1, 2(PC)
+	MOVV	R0, 0(R0)
+
+	// Initialize m->procid to Linux tid
+	MOVV	$SYS_gettid, R2
+	SYSCALL
+
+	MOVV	-24(R29), R18		// fn
+	MOVV	-16(R29), R17		// g
+	MOVV	-8(R29), R16		// m
+
+	BEQ	R16, nog
+	BEQ	R17, nog
+
+	MOVV	R2, m_procid(R16)
+
+	// TODO: setup TLS.
+
+	// In child, set up new stack
+	MOVV	R16, g_m(R17)
+	MOVV	R17, g
+	//CALL	runtime·stackcheck(SB)
+
+nog:
+	// Call fn
+	JAL	(R18)
+
+	// It shouldn't return.	 If it does, exit that thread.
+	MOVW	$111, R4
+	MOVV	$SYS_exit, R2
+	SYSCALL
+	JMP	-3(PC)	// keep exiting
+
+TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
+	MOVV	new+0(FP), R4
+	MOVV	old+8(FP), R5
+	MOVV	$SYS_sigaltstack, R2
+	SYSCALL
+	BEQ	R7, 2(PC)
+	MOVV	R0, 0xf1(R0)	// crash
+	RET
+
+TEXT runtime·osyield(SB),NOSPLIT,$-8
+	MOVV	$SYS_sched_yield, R2
+	SYSCALL
+	RET
+
+TEXT runtime·sched_getaffinity(SB),NOSPLIT,$-8
+	MOVV	pid+0(FP), R4
+	MOVV	len+8(FP), R5
+	MOVV	buf+16(FP), R6
+	MOVV	$SYS_sched_getaffinity, R2
+	SYSCALL
+	MOVW	R2, ret+24(FP)
+	RET
+
+// int32 runtime·epollcreate(int32 size);
+TEXT runtime·epollcreate(SB),NOSPLIT,$-8
+	MOVW    size+0(FP), R4
+	MOVV	$SYS_epoll_create, R2
+	SYSCALL
+	MOVW	R2, ret+8(FP)
+	RET
+
+// int32 runtime·epollcreate1(int32 flags);
+TEXT runtime·epollcreate1(SB),NOSPLIT,$-8
+	MOVW	flags+0(FP), R4
+	MOVV	$SYS_epoll_create1, R2
+	SYSCALL
+	MOVW	R2, ret+8(FP)
+	RET
+
+// func epollctl(epfd, op, fd int32, ev *epollEvent) int
+TEXT runtime·epollctl(SB),NOSPLIT,$-8
+	MOVW	epfd+0(FP), R4
+	MOVW	op+4(FP), R5
+	MOVW	fd+8(FP), R6
+	MOVV	ev+16(FP), R7
+	MOVV	$SYS_epoll_ctl, R2
+	SYSCALL
+	MOVW	R2, ret+24(FP)
+	RET
+
+// int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
+TEXT runtime·epollwait(SB),NOSPLIT,$-8
+	MOVW	epfd+0(FP), R4
+	MOVV	ev+8(FP), R5
+	MOVW	nev+16(FP), R6
+	MOVW	timeout+20(FP), R7
+	MOVV	$SYS_epoll_wait, R2
+	SYSCALL
+	MOVW	R2, ret+24(FP)
+	RET
+
+// void runtime·closeonexec(int32 fd);
+TEXT runtime·closeonexec(SB),NOSPLIT,$-8
+	MOVW    fd+0(FP), R4  // fd
+	MOVV    $2, R5  // F_SETFD
+	MOVV    $1, R6  // FD_CLOEXEC
+	MOVV	$SYS_fcntl, R2
+	SYSCALL
+	RET
diff --git a/src/runtime/sys_linux_ppc64x.s b/src/runtime/sys_linux_ppc64x.s
index 01575f8..d063e02 100644
--- a/src/runtime/sys_linux_ppc64x.s
+++ b/src/runtime/sys_linux_ppc64x.s
@@ -12,6 +12,7 @@
 #include "go_asm.h"
 #include "go_tls.h"
 #include "textflag.h"
+#include "asm_ppc64x.h"
 
 #define SYS_exit		  1
 #define SYS_read		  3
@@ -47,17 +48,17 @@
 #define SYS_clock_gettime	246
 #define SYS_epoll_create1	315
 
-TEXT runtime·exit(SB),NOSPLIT,$-8-4
+TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4
 	MOVW	code+0(FP), R3
 	SYSCALL	$SYS_exit_group
 	RET
 
-TEXT runtime·exit1(SB),NOSPLIT,$-8-4
+TEXT runtime·exit1(SB),NOSPLIT|NOFRAME,$0-4
 	MOVW	code+0(FP), R3
 	SYSCALL	$SYS_exit
 	RET
 
-TEXT runtime·open(SB),NOSPLIT,$-8-20
+TEXT runtime·open(SB),NOSPLIT|NOFRAME,$0-20
 	MOVD	name+0(FP), R3
 	MOVW	mode+8(FP), R4
 	MOVW	perm+12(FP), R5
@@ -67,7 +68,7 @@ TEXT runtime·open(SB),NOSPLIT,$-8-20
 	MOVW	R3, ret+16(FP)
 	RET
 
-TEXT runtime·closefd(SB),NOSPLIT,$-8-12
+TEXT runtime·closefd(SB),NOSPLIT|NOFRAME,$0-12
 	MOVW	fd+0(FP), R3
 	SYSCALL	$SYS_close
 	BVC	2(PC)
@@ -75,7 +76,7 @@ TEXT runtime·closefd(SB),NOSPLIT,$-8-12
 	MOVW	R3, ret+8(FP)
 	RET
 
-TEXT runtime·write(SB),NOSPLIT,$-8-28
+TEXT runtime·write(SB),NOSPLIT|NOFRAME,$0-28
 	MOVD	fd+0(FP), R3
 	MOVD	p+8(FP), R4
 	MOVW	n+16(FP), R5
@@ -85,7 +86,7 @@ TEXT runtime·write(SB),NOSPLIT,$-8-28
 	MOVW	R3, ret+24(FP)
 	RET
 
-TEXT runtime·read(SB),NOSPLIT,$-8-28
+TEXT runtime·read(SB),NOSPLIT|NOFRAME,$0-28
 	MOVW	fd+0(FP), R3
 	MOVD	p+8(FP), R4
 	MOVW	n+16(FP), R5
@@ -95,7 +96,7 @@ TEXT runtime·read(SB),NOSPLIT,$-8-28
 	MOVW	R3, ret+24(FP)
 	RET
 
-TEXT runtime·getrlimit(SB),NOSPLIT,$-8-20
+TEXT runtime·getrlimit(SB),NOSPLIT|NOFRAME,$0-20
 	MOVW	kind+0(FP), R3
 	MOVD	limit+8(FP), R4
 	SYSCALL	$SYS_ugetrlimit
@@ -126,32 +127,33 @@ TEXT runtime·gettid(SB),NOSPLIT,$0-4
 	MOVW	R3, ret+0(FP)
 	RET
 
-TEXT runtime·raise(SB),NOSPLIT,$-8
+TEXT runtime·raise(SB),NOSPLIT|NOFRAME,$0
 	SYSCALL	$SYS_gettid
 	MOVW	R3, R3	// arg 1 tid
 	MOVW	sig+0(FP), R4	// arg 2
 	SYSCALL	$SYS_tkill
 	RET
 
-TEXT runtime·raiseproc(SB),NOSPLIT,$-8
+TEXT runtime·raiseproc(SB),NOSPLIT|NOFRAME,$0
 	SYSCALL	$SYS_getpid
 	MOVW	R3, R3	// arg 1 pid
 	MOVW	sig+0(FP), R4	// arg 2
 	SYSCALL	$SYS_kill
 	RET
 
-TEXT runtime·setitimer(SB),NOSPLIT,$-8-24
+TEXT runtime·setitimer(SB),NOSPLIT|NOFRAME,$0-24
 	MOVW	mode+0(FP), R3
 	MOVD	new+8(FP), R4
 	MOVD	old+16(FP), R5
 	SYSCALL	$SYS_setitimer
 	RET
 
-TEXT runtime·mincore(SB),NOSPLIT,$-8-28
+TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28
 	MOVD	addr+0(FP), R3
 	MOVD	n+8(FP), R4
 	MOVD	dst+16(FP), R5
 	SYSCALL	$SYS_mincore
+	NEG	R3		// caller expects negative errno
 	MOVW	R3, ret+24(FP)
 	RET
 
@@ -182,7 +184,7 @@ TEXT runtime·nanotime(SB),NOSPLIT,$16
 	MOVD	R3, ret+0(FP)
 	RET
 
-TEXT runtime·rtsigprocmask(SB),NOSPLIT,$-8-28
+TEXT runtime·rtsigprocmask(SB),NOSPLIT|NOFRAME,$0-28
 	MOVW	sig+0(FP), R3
 	MOVD	new+8(FP), R4
 	MOVD	old+16(FP), R5
@@ -192,7 +194,7 @@ TEXT runtime·rtsigprocmask(SB),NOSPLIT,$-8-28
 	MOVD	R0, 0xf1(R0)	// crash
 	RET
 
-TEXT runtime·rt_sigaction(SB),NOSPLIT,$-8-36
+TEXT runtime·rt_sigaction(SB),NOSPLIT|NOFRAME,$0-36
 	MOVD	sig+0(FP), R3
 	MOVD	new+8(FP), R4
 	MOVD	old+16(FP), R5
@@ -205,9 +207,10 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
 	MOVW	sig+8(FP), R3
 	MOVD	info+16(FP), R4
 	MOVD	ctx+24(FP), R5
-	MOVD	fn+0(FP), R31
-	MOVD	R31, CTR
+	MOVD	fn+0(FP), R12
+	MOVD	R12, CTR
 	BL	(CTR)
+	MOVD	24(R1), R2
 	RET
 
 #ifdef GOARCH_ppc64le
@@ -215,7 +218,7 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
 TEXT runtime·sigtramp(SB),NOSPLIT,$64
 #else
 // function descriptor for the real sigtramp
-TEXT runtime·sigtramp(SB),NOSPLIT,$-8
+TEXT runtime·sigtramp(SB),NOSPLIT|NOFRAME,$0
 	DWORD	$runtime·_sigtramp(SB)
 	DWORD	$0
 	DWORD	$0
@@ -231,15 +234,16 @@ TEXT runtime·_sigtramp(SB),NOSPLIT,$64
 	BEQ	2(PC)
 	BL	runtime·load_g(SB)
 
-	MOVW	R3, 8(R1)
-	MOVD	R4, 16(R1)
-	MOVD	R5, 24(R1)
-	MOVD	$runtime·sigtrampgo(SB), R31
-	MOVD	R31, CTR
+	MOVW	R3, FIXED_FRAME+0(R1)
+	MOVD	R4, FIXED_FRAME+8(R1)
+	MOVD	R5, FIXED_FRAME+16(R1)
+	MOVD	$runtime·sigtrampgo(SB), R12
+	MOVD	R12, CTR
 	BL	(CTR)
+	MOVD	24(R1), R2
 	RET
 
-TEXT runtime·mmap(SB),NOSPLIT,$-8
+TEXT runtime·mmap(SB),NOSPLIT|NOFRAME,$0
 	MOVD	addr+0(FP), R3
 	MOVD	n+8(FP), R4
 	MOVW	prot+16(FP), R5
@@ -251,7 +255,7 @@ TEXT runtime·mmap(SB),NOSPLIT,$-8
 	MOVD	R3, ret+32(FP)
 	RET
 
-TEXT runtime·munmap(SB),NOSPLIT,$-8
+TEXT runtime·munmap(SB),NOSPLIT|NOFRAME,$0
 	MOVD	addr+0(FP), R3
 	MOVD	n+8(FP), R4
 	SYSCALL	$SYS_munmap
@@ -259,7 +263,7 @@ TEXT runtime·munmap(SB),NOSPLIT,$-8
 	MOVD	R0, 0xf3(R0)
 	RET
 
-TEXT runtime·madvise(SB),NOSPLIT,$-8
+TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0
 	MOVD	addr+0(FP), R3
 	MOVD	n+8(FP), R4
 	MOVW	flags+16(FP), R5
@@ -269,7 +273,7 @@ TEXT runtime·madvise(SB),NOSPLIT,$-8
 
 // int64 futex(int32 *uaddr, int32 op, int32 val,
 //	struct timespec *timeout, int32 *uaddr2, int32 val2);
-TEXT runtime·futex(SB),NOSPLIT,$-8
+TEXT runtime·futex(SB),NOSPLIT|NOFRAME,$0
 	MOVD	addr+0(FP), R3
 	MOVW	op+8(FP), R4
 	MOVW	val+12(FP), R5
@@ -281,7 +285,7 @@ TEXT runtime·futex(SB),NOSPLIT,$-8
 	RET
 
 // int64 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
-TEXT runtime·clone(SB),NOSPLIT,$-8
+TEXT runtime·clone(SB),NOSPLIT|NOFRAME,$0
 	MOVW	flags+0(FP), R3
 	MOVD	stk+8(FP), R4
 
@@ -344,7 +348,7 @@ nog:
 	SYSCALL	$SYS_exit
 	BR	-2(PC)	// keep exiting
 
-TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
+TEXT runtime·sigaltstack(SB),NOSPLIT|NOFRAME,$0
 	MOVD	new+0(FP), R3
 	MOVD	old+8(FP), R4
 	SYSCALL	$SYS_sigaltstack
@@ -352,11 +356,11 @@ TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
 	MOVD	R0, 0xf1(R0)  // crash
 	RET
 
-TEXT runtime·osyield(SB),NOSPLIT,$-8
+TEXT runtime·osyield(SB),NOSPLIT|NOFRAME,$0
 	SYSCALL	$SYS_sched_yield
 	RET
 
-TEXT runtime·sched_getaffinity(SB),NOSPLIT,$-8
+TEXT runtime·sched_getaffinity(SB),NOSPLIT|NOFRAME,$0
 	MOVD	pid+0(FP), R3
 	MOVD	len+8(FP), R4
 	MOVD	buf+16(FP), R5
@@ -365,21 +369,21 @@ TEXT runtime·sched_getaffinity(SB),NOSPLIT,$-8
 	RET
 
 // int32 runtime·epollcreate(int32 size);
-TEXT runtime·epollcreate(SB),NOSPLIT,$-8
+TEXT runtime·epollcreate(SB),NOSPLIT|NOFRAME,$0
 	MOVW    size+0(FP), R3
 	SYSCALL	$SYS_epoll_create
 	MOVW	R3, ret+8(FP)
 	RET
 
 // int32 runtime·epollcreate1(int32 flags);
-TEXT runtime·epollcreate1(SB),NOSPLIT,$-8
+TEXT runtime·epollcreate1(SB),NOSPLIT|NOFRAME,$0
 	MOVW	flags+0(FP), R3
 	SYSCALL	$SYS_epoll_create1
 	MOVW	R3, ret+8(FP)
 	RET
 
 // func epollctl(epfd, op, fd int32, ev *epollEvent) int
-TEXT runtime·epollctl(SB),NOSPLIT,$-8
+TEXT runtime·epollctl(SB),NOSPLIT|NOFRAME,$0
 	MOVW	epfd+0(FP), R3
 	MOVW	op+4(FP), R4
 	MOVW	fd+8(FP), R5
@@ -389,7 +393,7 @@ TEXT runtime·epollctl(SB),NOSPLIT,$-8
 	RET
 
 // int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
-TEXT runtime·epollwait(SB),NOSPLIT,$-8
+TEXT runtime·epollwait(SB),NOSPLIT|NOFRAME,$0
 	MOVW	epfd+0(FP), R3
 	MOVD	ev+8(FP), R4
 	MOVW	nev+16(FP), R5
@@ -399,7 +403,7 @@ TEXT runtime·epollwait(SB),NOSPLIT,$-8
 	RET
 
 // void runtime·closeonexec(int32 fd);
-TEXT runtime·closeonexec(SB),NOSPLIT,$-8
+TEXT runtime·closeonexec(SB),NOSPLIT|NOFRAME,$0
 	MOVW    fd+0(FP), R3  // fd
 	MOVD    $2, R4  // F_SETFD
 	MOVD    $1, R5  // FD_CLOEXEC
diff --git a/src/runtime/sys_mips64x.go b/src/runtime/sys_mips64x.go
new file mode 100644
index 0000000..9e7d805
--- /dev/null
+++ b/src/runtime/sys_mips64x.go
@@ -0,0 +1,43 @@
+// Copyright 2015 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.
+
+// +build mips64 mips64le
+
+package runtime
+
+import "unsafe"
+
+// adjust Gobuf as if it executed a call to fn with context ctxt
+// and then did an immediate Gosave.
+func gostartcall(buf *gobuf, fn, ctxt unsafe.Pointer) {
+	if buf.lr != 0 {
+		throw("invalid use of gostartcall")
+	}
+	buf.lr = buf.pc
+	buf.pc = uintptr(fn)
+	buf.ctxt = ctxt
+}
+
+// Called to rewind context saved during morestack back to beginning of function.
+// To help us, the linker emits a jmp back to the beginning right after the
+// call to morestack. We just have to decode and apply that jump.
+func rewindmorestack(buf *gobuf) {
+	var inst uint32
+	if buf.pc&3 == 0 && buf.pc != 0 {
+		inst = *(*uint32)(unsafe.Pointer(buf.pc))
+		if inst>>26 == 2 { // JMP addr
+			//print("runtime: rewind pc=", hex(buf.pc), " to pc=", hex(buf.pc &^ uintptr(1<<28-1) | uintptr((inst&^0xfc000000)<<2)), "\n");
+			buf.pc &^= 1<<28 - 1
+			buf.pc |= uintptr((inst &^ 0xfc000000) << 2)
+			return
+		}
+		if inst>>16 == 0x1000 { // BEQ	R0, R0, offset
+			//print("runtime: rewind pc=", hex(buf.pc), " to pc=", hex(buf.pc + uintptr(int32(int16(inst&0xffff))<<2 + 4)), "\n");
+			buf.pc += uintptr(int32(int16(inst&0xffff))<<2 + 4)
+			return
+		}
+	}
+	print("runtime: pc=", hex(buf.pc), " ", hex(inst), "\n")
+	throw("runtime: misuse of rewindmorestack")
+}
diff --git a/src/runtime/sys_nacl_386.s b/src/runtime/sys_nacl_386.s
index bf2d36e..e69a0b7 100644
--- a/src/runtime/sys_nacl_386.s
+++ b/src/runtime/sys_nacl_386.s
@@ -227,6 +227,9 @@ TEXT runtime·mmap(SB),NOSPLIT,$32
 	LEAL	24(SP), AX
 	MOVL	AX, 20(SP)
 	NACL_SYSCALL(SYS_mmap)
+	CMPL	AX, $-4095
+	JNA	2(PC)
+	NEGL	AX
 	MOVL	AX, ret+24(FP)
 	RET
 
diff --git a/src/runtime/sys_nacl_arm.s b/src/runtime/sys_nacl_arm.s
index cf4804f..474d9fe 100644
--- a/src/runtime/sys_nacl_arm.s
+++ b/src/runtime/sys_nacl_arm.s
@@ -308,21 +308,6 @@ TEXT runtime·getRandomData(SB),NOSPLIT,$0-12
 	NACL_SYSCALL(SYS_get_random_bytes)
 	RET
 
-TEXT runtime·casp1(SB),NOSPLIT,$0
-	B	runtime·cas(SB)
-
-// This is only valid for ARMv6+, however, NaCl/ARM is only defined
-// for ARMv7A anyway.
-// bool armcas(int32 *val, int32 old, int32 new)
-// AtomiBLy:
-//	if(*val == old){
-//		*val = new;
-//		return 1;
-//	}else
-//		return 0;
-TEXT runtime·cas(SB),NOSPLIT,$0
-	B runtime·armcas(SB)
-
 // Likewise, this is only valid for ARMv7+, but that's okay.
 TEXT ·publicationBarrier(SB),NOSPLIT,$-4-0
 	B	runtime·armPublicationBarrier(SB)
diff --git a/src/runtime/sys_netbsd_386.s b/src/runtime/sys_netbsd_386.s
index 13b8428..3b3c109 100644
--- a/src/runtime/sys_netbsd_386.s
+++ b/src/runtime/sys_netbsd_386.s
@@ -215,42 +215,25 @@ TEXT runtime·sigaction(SB),NOSPLIT,$24
 	MOVL	$0xf1, 0xf1		// crash
 	RET
 
-TEXT runtime·sigtramp(SB),NOSPLIT,$44
-	get_tls(CX)
-
-	// check that g exists
-	MOVL	g(CX), DI
-	CMPL	DI, $0
-	JNE	6(PC)
-	MOVL	signo+0(FP), BX
-	MOVL	BX, 0(SP)
-	MOVL	$runtime·badsignal(SB), AX
+TEXT runtime·sigfwd(SB),NOSPLIT,$12-16
+	MOVL	sig+4(FP), AX
+	MOVL	AX, 0(SP)
+	MOVL	info+8(FP), AX
+	MOVL	AX, 4(SP)
+	MOVL	ctx+12(FP), AX
+	MOVL	AX, 8(SP)
+	MOVL	fn+0(FP), AX
 	CALL	AX
 	RET
 
-	// save g
-	MOVL	DI, 20(SP)
-
-	// g = m->gsignal
-	MOVL	g_m(DI), BX
-	MOVL	m_gsignal(BX), BX
-	MOVL	BX, g(CX)
-
-	// copy arguments for call to sighandler
+TEXT runtime·sigtramp(SB),NOSPLIT,$12
 	MOVL	signo+0(FP), BX
 	MOVL	BX, 0(SP)
 	MOVL	info+4(FP), BX
 	MOVL	BX, 4(SP)
 	MOVL	context+8(FP), BX
 	MOVL	BX, 8(SP)
-	MOVL	DI, 12(SP)
-
-	CALL	runtime·sighandler(SB)
-
-	// restore g
-	get_tls(CX)
-	MOVL	20(SP), BX
-	MOVL	BX, g(CX)
+	CALL	runtime·sigtrampgo(SB)
 	RET
 
 // int32 lwp_create(void *context, uintptr flags, void *lwpid);
diff --git a/src/runtime/sys_netbsd_amd64.s b/src/runtime/sys_netbsd_amd64.s
index d0640db..fb21f11 100644
--- a/src/runtime/sys_netbsd_amd64.s
+++ b/src/runtime/sys_netbsd_amd64.s
@@ -237,37 +237,21 @@ TEXT runtime·sigaction(SB),NOSPLIT,$-8
 	MOVL	$0xf1, 0xf1		// crash
 	RET
 
-TEXT runtime·sigtramp(SB),NOSPLIT,$64
-	get_tls(BX)
-
-	// check that g exists
-	MOVQ	g(BX), R10
-	CMPQ	R10, $0
-	JNE	5(PC)
-	MOVQ	DI, 0(SP)
-	MOVQ	$runtime·badsignal(SB), AX
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
+	MOVL	sig+8(FP), DI
+	MOVQ	info+16(FP), SI
+	MOVQ	ctx+24(FP), DX
+	MOVQ	fn+0(FP), AX
 	CALL	AX
 	RET
 
-	// save g
-	MOVQ	R10, 40(SP)
-
-	// g = m->signal
-	MOVQ	g_m(R10), AX
-	MOVQ	m_gsignal(AX), AX
-	MOVQ	AX, g(BX)
-
-	MOVQ	DI, 0(SP)
-	MOVQ	SI, 8(SP)
-	MOVQ	DX, 16(SP)
-	MOVQ	R10, 24(SP)
-
-	CALL	runtime·sighandler(SB)
-
-	// restore g
-	get_tls(BX)
-	MOVQ	40(SP), R10
-	MOVQ	R10, g(BX)
+TEXT runtime·sigtramp(SB),NOSPLIT,$32
+	MOVQ	DI, 0(SP)   // signum
+	MOVQ	SI, 8(SP)   // info
+	MOVQ	DX, 16(SP)  // ctx
+	MOVQ	R15, 24(SP) // for sigreturn
+	CALL	runtime·sigtrampgo(SB)
+	MOVQ	24(SP), R15
 	RET
 
 TEXT runtime·mmap(SB),NOSPLIT,$0
diff --git a/src/runtime/sys_netbsd_arm.s b/src/runtime/sys_netbsd_arm.s
index ae669ce..3d3b65f 100644
--- a/src/runtime/sys_netbsd_arm.s
+++ b/src/runtime/sys_netbsd_arm.s
@@ -213,7 +213,19 @@ TEXT runtime·sigaction(SB),NOSPLIT,$4
 	MOVW.CS R8, (R8)
 	RET
 
-TEXT runtime·sigtramp(SB),NOSPLIT,$24
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
+	MOVW	sig+4(FP), R0
+	MOVW	info+8(FP), R1
+	MOVW	ctx+12(FP), R2
+	MOVW	fn+0(FP), R11
+	MOVW	R13, R4
+	SUB	$24, R13
+	BIC	$0x7, R13 // alignment for ELF ABI
+	BL	(R11)
+	MOVW	R4, R13
+	RET
+
+TEXT runtime·sigtramp(SB),NOSPLIT,$12
 	// this might be called in external code context,
 	// where g is not set.
 	// first save R0, because runtime·load_g will clobber it
@@ -222,30 +234,9 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$24
 	CMP 	$0, R0
 	BL.NE	runtime·load_g(SB)
 
-	CMP $0, g
-	BNE 4(PC)
-	// signal number is already prepared in 4(R13)
-	MOVW $runtime·badsignal(SB), R11
-	BL (R11)
-	RET
-
-	// save g
-	MOVW g, R4
-	MOVW g, 20(R13)
-
-	// g = m->signal
-	MOVW g_m(g), R8
-	MOVW m_gsignal(R8), g
-
-	// R0 is already saved
-	MOVW R1, 8(R13) // info
-	MOVW R2, 12(R13) // context
-	MOVW R4, 16(R13) // gp
-
-	BL runtime·sighandler(SB)
-
-	// restore g
-	MOVW 20(R13), g
+	MOVW	R1, 8(R13)
+	MOVW	R2, 12(R13)
+	BL	runtime·sigtrampgo(SB)
 	RET
 
 TEXT runtime·mmap(SB),NOSPLIT,$12
@@ -338,20 +329,6 @@ TEXT runtime·closeonexec(SB),NOSPLIT,$0
 	SWI $0xa0005c	// sys_fcntl
 	RET
 
-TEXT runtime·casp1(SB),NOSPLIT,$0
-	B	runtime·cas(SB)
-
-// TODO(minux): this is only valid for ARMv6+
-// bool armcas(int32 *val, int32 old, int32 new)
-// Atomically:
-//	if(*val == old){
-//		*val = new;
-//		return 1;
-//	}else
-//		return 0;
-TEXT runtime·cas(SB),NOSPLIT,$0
-	B runtime·armcas(SB)
-
 // TODO: this is only valid for ARMv7+
 TEXT ·publicationBarrier(SB),NOSPLIT,$-4-0
 	B	runtime·armPublicationBarrier(SB)
diff --git a/src/runtime/sys_nonppc64x.go b/src/runtime/sys_nonppc64x.go
new file mode 100644
index 0000000..4409374
--- /dev/null
+++ b/src/runtime/sys_nonppc64x.go
@@ -0,0 +1,10 @@
+// Copyright 2015 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.
+
+// +build !ppc64,!ppc64le
+
+package runtime
+
+func prepGoExitFrame(sp uintptr) {
+}
diff --git a/src/runtime/sys_openbsd_386.s b/src/runtime/sys_openbsd_386.s
index bdf18d8..769b2f9 100644
--- a/src/runtime/sys_openbsd_386.s
+++ b/src/runtime/sys_openbsd_386.s
@@ -195,44 +195,26 @@ TEXT runtime·sigprocmask(SB),NOSPLIT,$-4
 	MOVL	AX, ret+8(FP)
 	RET
 
-TEXT runtime·sigtramp(SB),NOSPLIT,$44
-	get_tls(CX)
-
-	// check that g exists
-	MOVL	g(CX), DI
-	CMPL	DI, $0
-	JNE	6(PC)
-	MOVL	signo+0(FP), BX
-	MOVL	BX, 0(SP)
-	MOVL	$runtime·badsignal(SB), AX
+TEXT runtime·sigfwd(SB),NOSPLIT,$12-16
+	MOVL	sig+4(FP), AX
+	MOVL	AX, 0(SP)
+	MOVL	info+8(FP), AX
+	MOVL	AX, 4(SP)
+	MOVL	ctx+12(FP), AX
+	MOVL	AX, 8(SP)
+	MOVL	fn+0(FP), AX
 	CALL	AX
-	JMP 	ret
-
-	// save g
-	MOVL	DI, 20(SP)
-	
-	// g = m->gsignal
-	MOVL	g_m(DI), BX
-	MOVL	m_gsignal(BX), BX
-	MOVL	BX, g(CX)
+	RET
 
-	// copy arguments for call to sighandler
+TEXT runtime·sigtramp(SB),NOSPLIT,$12
 	MOVL	signo+0(FP), BX
 	MOVL	BX, 0(SP)
 	MOVL	info+4(FP), BX
 	MOVL	BX, 4(SP)
 	MOVL	context+8(FP), BX
 	MOVL	BX, 8(SP)
-	MOVL	DI, 12(SP)
-
-	CALL	runtime·sighandler(SB)
-
-	// restore g
-	get_tls(CX)
-	MOVL	20(SP), BX
-	MOVL	BX, g(CX)
+	CALL	runtime·sigtrampgo(SB)
 
-ret:
 	// call sigreturn
 	MOVL	context+8(FP), AX
 	MOVL	$0, 0(SP)		// syscall gap
diff --git a/src/runtime/sys_openbsd_amd64.s b/src/runtime/sys_openbsd_amd64.s
index 213ffc1..ed368ba 100644
--- a/src/runtime/sys_openbsd_amd64.s
+++ b/src/runtime/sys_openbsd_amd64.s
@@ -228,37 +228,19 @@ TEXT runtime·sigprocmask(SB),NOSPLIT,$0
 	MOVL	AX, ret+8(FP)
 	RET
 
-TEXT runtime·sigtramp(SB),NOSPLIT,$64
-	get_tls(BX)
-	
-	// check that g exists
-	MOVQ	g(BX), R10
-	CMPQ	R10, $0
-	JNE	5(PC)
-	MOVQ	DI, 0(SP)
-	MOVQ	$runtime·badsignal(SB), AX
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
+	MOVL	sig+8(FP), DI
+	MOVQ	info+16(FP), SI
+	MOVQ	ctx+24(FP), DX
+	MOVQ	fn+0(FP), AX
 	CALL	AX
 	RET
 
-	// save g
-	MOVQ	R10, 40(SP)
-	
-	// g = m->signal
-	MOVQ	g_m(R10), AX
-	MOVQ	m_gsignal(AX), AX
-	MOVQ	AX, g(BX)
-	
+TEXT runtime·sigtramp(SB),NOSPLIT,$24
 	MOVQ	DI, 0(SP)
 	MOVQ	SI, 8(SP)
 	MOVQ	DX, 16(SP)
-	MOVQ	R10, 24(SP)
-	
-	CALL	runtime·sighandler(SB)
-
-	// restore g
-	get_tls(BX)
-	MOVQ	40(SP), R10
-	MOVQ	R10, g(BX)
+	CALL	runtime·sigtrampgo(SB)
 	RET
 
 TEXT runtime·mmap(SB),NOSPLIT,$0
@@ -306,7 +288,7 @@ TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
 
 // set tls base to DI
 TEXT runtime·settls(SB),NOSPLIT,$0
-	// adjust for ELF: wants to use -16(FS) and -8(FS) for g and m
+	// adjust for ELF: wants to use -8(FS) for g
 	ADDQ	$8, DI
 	MOVQ	$329, AX		// sys___settcb
 	SYSCALL
diff --git a/src/runtime/sys_openbsd_arm.s b/src/runtime/sys_openbsd_arm.s
index 60deb8f..29e8971 100644
--- a/src/runtime/sys_openbsd_arm.s
+++ b/src/runtime/sys_openbsd_arm.s
@@ -208,7 +208,19 @@ TEXT runtime·sigprocmask(SB),NOSPLIT,$0
 	MOVW	R0, ret+8(FP)
 	RET
 
-TEXT runtime·sigtramp(SB),NOSPLIT,$24
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
+	MOVW	sig+4(FP), R0
+	MOVW	info+8(FP), R1
+	MOVW	ctx+12(FP), R2
+	MOVW	fn+0(FP), R11
+	MOVW	R13, R4
+	SUB	$24, R13
+	BIC	$0x7, R13 // alignment for ELF ABI
+	BL	(R11)
+	MOVW	R4, R13
+	RET
+
+TEXT runtime·sigtramp(SB),NOSPLIT,$12
 	// If called from an external code context, g will not be set.
 	// Save R0, since runtime·load_g will clobber it.
 	MOVW	R0, 4(R13)		// signum
@@ -216,30 +228,9 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$24
 	CMP	$0, R0
 	BL.NE	runtime·load_g(SB)
 
-	CMP	$0, g
-	BNE	4(PC)
-	// Signal number saved in 4(R13).
-	MOVW	runtime·badsignal(SB), R11
-	BL	(R11)
-	RET
-
-	// Save g.
-	MOVW	g, R3
-	MOVW	g, 20(R13)
-
-	// g = m->signal
-	MOVW	g_m(g), R8
-	MOVW	m_gsignal(R8), g
-
-	// R0 already saved.
-	MOVW	R1, 8(R13)		// info
-	MOVW	R2, 12(R13)		// context
-	MOVW	R3, 16(R13)		// gp (original g)
-
-	BL	runtime·sighandler(SB)
-
-	// Restore g.
-	MOVW	20(R13), g
+	MOVW	R1, 8(R13)
+	MOVW	R2, 12(R13)
+	BL	runtime·sigtrampgo(SB)
 	RET
 
 // int32 tfork(void *param, uintptr psize, M *mp, G *gp, void (*fn)(void));
@@ -373,13 +364,6 @@ TEXT runtime·closeonexec(SB),NOSPLIT,$0
 	MOVW	R0, ret+4(FP)
 	RET
 
-TEXT runtime·casp1(SB),NOSPLIT,$0
-	//B	runtime·armcas(SB)
-	B	runtime·cas(SB)
-
-TEXT runtime·cas(SB),NOSPLIT,$0
-	B	runtime·armcas(SB)
-
 TEXT ·publicationBarrier(SB),NOSPLIT,$-4-0
 	B	runtime·armPublicationBarrier(SB)
 
diff --git a/src/runtime/sys_plan9_386.s b/src/runtime/sys_plan9_386.s
index cae326a..1af3cb1 100644
--- a/src/runtime/sys_plan9_386.s
+++ b/src/runtime/sys_plan9_386.s
@@ -238,7 +238,7 @@ TEXT runtime·errstr(SB),NOSPLIT,$8-8
 	get_tls(AX)
 	MOVL	g(AX), BX
 	MOVL	g_m(BX), BX
-	MOVL	m_errstr(BX), CX
+	MOVL	(m_mOS+mOS_errstr)(BX), CX
 	MOVL	CX, 0(SP)
 	MOVL	$ERRMAX, 4(SP)
 	CALL	errstr<>(SB)
diff --git a/src/runtime/sys_plan9_amd64.s b/src/runtime/sys_plan9_amd64.s
index 6aefe5f..1492ef2 100644
--- a/src/runtime/sys_plan9_amd64.s
+++ b/src/runtime/sys_plan9_amd64.s
@@ -243,7 +243,7 @@ TEXT runtime·errstr(SB),NOSPLIT,$16-16
 	get_tls(AX)
 	MOVQ	g(AX), BX
 	MOVQ	g_m(BX), BX
-	MOVQ	m_errstr(BX), CX
+	MOVQ	(m_mOS+mOS_errstr)(BX), CX
 	MOVQ	CX, 0(SP)
 	MOVQ	$ERRMAX, 8(SP)
 	CALL	errstr<>(SB)
diff --git a/src/runtime/sys_ppc64x.go b/src/runtime/sys_ppc64x.go
index bd182e3..2ea1f81 100644
--- a/src/runtime/sys_ppc64x.go
+++ b/src/runtime/sys_ppc64x.go
@@ -35,3 +35,5 @@ func rewindmorestack(buf *gobuf) {
 	print("runtime: pc=", hex(buf.pc), " ", hex(inst), "\n")
 	throw("runtime: misuse of rewindmorestack")
 }
+
+func prepGoExitFrame(sp uintptr)
diff --git a/src/runtime/sys_solaris_amd64.s b/src/runtime/sys_solaris_amd64.s
index 18098d2..3a82674 100644
--- a/src/runtime/sys_solaris_amd64.s
+++ b/src/runtime/sys_solaris_amd64.s
@@ -26,7 +26,7 @@ TEXT runtime·miniterrno(SB),NOSPLIT,$0
 	get_tls(CX)
 	MOVQ	g(CX), BX
 	MOVQ	g_m(BX), BX
-	MOVQ	AX,	m_perrno(BX)
+	MOVQ	AX,	(m_mOS+mOS_perrno)(BX)
 	RET
 
 // int64 runtime·nanotime1(void);
@@ -83,7 +83,7 @@ TEXT runtime·asmsysvicall6(SB),NOSPLIT,$0
 	CMPQ	BX, $0
 	JEQ	skiperrno1
 	MOVQ	g_m(BX), BX
-	MOVQ	m_perrno(BX), DX
+	MOVQ	(m_mOS+mOS_perrno)(BX), DX
 	CMPQ	DX, $0
 	JEQ	skiperrno1
 	MOVL	$0, 0(DX)
@@ -113,7 +113,7 @@ skipargs:
 	CMPQ	BX, $0
 	JEQ	skiperrno2
 	MOVQ	g_m(BX), BX
-	MOVQ	m_perrno(BX), AX
+	MOVQ	(m_mOS+mOS_perrno)(BX), AX
 	CMPQ	AX, $0
 	JEQ	skiperrno2
 	MOVL	0(AX), AX
@@ -200,7 +200,7 @@ allgood:
 	MOVQ    R10, 176(SP)
 
 	// save m->scratch
-	LEAQ	m_scratch(BP), R11
+	LEAQ	(m_mOS+mOS_scratch)(BP), R11
 	MOVQ	0(R11), R10
 	MOVQ	R10, 112(SP)
 	MOVQ	8(R11), R10
@@ -215,7 +215,7 @@ allgood:
 	MOVQ	R10, 152(SP)
 
 	// save errno, it might be EINTR; stuff we do here might reset it.
-	MOVQ	m_perrno(BP), R10
+	MOVQ	(m_mOS+mOS_perrno)(BP), R10
 	MOVL	0(R10), R10
 	MOVQ	R10, 160(SP)
 
@@ -224,6 +224,8 @@ allgood:
 	MOVQ	m_gsignal(BP), BP
 	MOVQ	BP, g(BX)
 
+	// TODO: If current SP is not in gsignal.stack, then adjust.
+
 	// prepare call
 	MOVQ	DI, 0(SP)
 	MOVQ	SI, 8(SP)
@@ -248,7 +250,7 @@ allgood:
 	MOVQ    R10, libcall_r2(R11)
 
 	// restore scratch
-	LEAQ	m_scratch(BP), R11
+	LEAQ	(m_mOS+mOS_scratch)(BP), R11
 	MOVQ	112(SP), R10
 	MOVQ	R10, 0(R11)
 	MOVQ	120(SP), R10
@@ -263,7 +265,7 @@ allgood:
 	MOVQ	R10, 40(R11)
 
 	// restore errno
-	MOVQ	m_perrno(BP), R11
+	MOVQ	(m_mOS+mOS_perrno)(BP), R11
 	MOVQ	160(SP), R10
 	MOVL	R10, 0(R11)
 
diff --git a/src/runtime/sys_windows_386.s b/src/runtime/sys_windows_386.s
index e5fe88a..55cdcf4 100644
--- a/src/runtime/sys_windows_386.s
+++ b/src/runtime/sys_windows_386.s
@@ -206,7 +206,8 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0
 	CALL	runtime·memclr(SB)	// smashes AX,BX,CX
 	LEAL	g__size(SP), BX
 	MOVL	BX, g_m(SP)
-	LEAL	-8192(SP), CX
+
+	LEAL	-32768(SP), CX		// must be less than SizeOfStackReserve set by linker
 	MOVL	CX, (g_stack+stack_lo)(SP)
 	ADDL	$const__StackGuard, CX
 	MOVL	CX, g_stackguard0(SP)
diff --git a/src/runtime/sys_windows_amd64.s b/src/runtime/sys_windows_amd64.s
index ea4f3e0..caa18e6 100644
--- a/src/runtime/sys_windows_amd64.s
+++ b/src/runtime/sys_windows_amd64.s
@@ -243,7 +243,7 @@ TEXT runtime·externalthreadhandler(SB),NOSPLIT,$0
 	LEAQ	g__size(SP), BX
 	MOVQ	BX, g_m(SP)
 
-	LEAQ	-8192(SP), CX
+	LEAQ	-32768(SP), CX		// must be less than SizeOfStackReserve set by linker
 	MOVQ	CX, (g_stack+stack_lo)(SP)
 	ADDQ	$const__StackGuard, CX
 	MOVQ	CX, g_stackguard0(SP)
@@ -428,19 +428,21 @@ ret:
 	RET
 
 // Runs on OS stack. duration (in 100ns units) is in BX.
-TEXT runtime·usleep2(SB),NOSPLIT,$16
+// The function leaves room for 4 syscall parameters
+// (as per windows amd64 calling convention).
+TEXT runtime·usleep2(SB),NOSPLIT,$48
 	MOVQ	SP, AX
 	ANDQ	$~15, SP	// alignment as per Windows requirement
-	MOVQ	AX, 8(SP)
+	MOVQ	AX, 40(SP)
 	// Want negative 100ns units.
 	NEGQ	BX
-	MOVQ	SP, R8 // ptime
+	LEAQ	32(SP), R8  // ptime
 	MOVQ	BX, (R8)
 	MOVQ	$-1, CX // handle
 	MOVQ	$0, DX // alertable
 	MOVQ	runtime·_NtWaitForSingleObject(SB), AX
 	CALL	AX
-	MOVQ	8(SP), SP
+	MOVQ	40(SP), SP
 	RET
 
 // func now() (sec int64, nsec int32)
diff --git a/src/runtime/sys_x86.go b/src/runtime/sys_x86.go
index 3f0771f..137e706 100644
--- a/src/runtime/sys_x86.go
+++ b/src/runtime/sys_x86.go
@@ -6,17 +6,20 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 // adjust Gobuf as it if executed a call to fn with context ctxt
 // and then did an immediate gosave.
 func gostartcall(buf *gobuf, fn, ctxt unsafe.Pointer) {
 	sp := buf.sp
-	if regSize > ptrSize {
-		sp -= ptrSize
+	if sys.RegSize > sys.PtrSize {
+		sp -= sys.PtrSize
 		*(*uintptr)(unsafe.Pointer(sp)) = 0
 	}
-	sp -= ptrSize
+	sp -= sys.PtrSize
 	*(*uintptr)(unsafe.Pointer(sp)) = buf.pc
 	buf.sp = sp
 	buf.pc = uintptr(fn)
diff --git a/src/runtime/syscall2_solaris.go b/src/runtime/syscall2_solaris.go
index df72996..e19035a 100644
--- a/src/runtime/syscall2_solaris.go
+++ b/src/runtime/syscall2_solaris.go
@@ -9,9 +9,6 @@ import _ "unsafe" // for go:linkname
 //go:cgo_import_dynamic libc_chdir chdir "libc.so"
 //go:cgo_import_dynamic libc_chroot chroot "libc.so"
 //go:cgo_import_dynamic libc_close close "libc.so"
-//go:cgo_import_dynamic libc_dlclose dlclose "libc.so"
-//go:cgo_import_dynamic libc_dlopen dlopen "libc.so"
-//go:cgo_import_dynamic libc_dlsym dlsym "libc.so"
 //go:cgo_import_dynamic libc_execve execve "libc.so"
 //go:cgo_import_dynamic libc_fcntl fcntl "libc.so"
 //go:cgo_import_dynamic libc_gethostname gethostname "libc.so"
@@ -30,9 +27,6 @@ import _ "unsafe" // for go:linkname
 //go:linkname libc_chdir libc_chdir
 //go:linkname libc_chroot libc_chroot
 //go:linkname libc_close libc_close
-//go:linkname libc_dlclose libc_dlclose
-//go:linkname libc_dlopen libc_dlopen
-//go:linkname libc_dlsym libc_dlsym
 //go:linkname libc_execve libc_execve
 //go:linkname libc_fcntl libc_fcntl
 //go:linkname libc_gethostname libc_gethostname
diff --git a/src/runtime/syscall_windows.go b/src/runtime/syscall_windows.go
index 8e069cd..e2ff7a8 100644
--- a/src/runtime/syscall_windows.go
+++ b/src/runtime/syscall_windows.go
@@ -45,16 +45,16 @@ func compileCallback(fn eface, cleanstack bool) (code uintptr) {
 		panic("compileCallback: not a function")
 	}
 	ft := (*functype)(unsafe.Pointer(fn._type))
-	if ft.out.len != 1 {
+	if len(ft.out) != 1 {
 		panic("compileCallback: function must have one output parameter")
 	}
 	uintptrSize := unsafe.Sizeof(uintptr(0))
-	if t := (**_type)(unsafe.Pointer(ft.out.array)); (*t).size != uintptrSize {
+	if ft.out[0].size != uintptrSize {
 		panic("compileCallback: output parameter size is wrong")
 	}
 	argsize := uintptr(0)
-	for _, t := range (*[1024](*_type))(unsafe.Pointer(ft.in.array))[:ft.in.len] {
-		if (*t).size > uintptrSize {
+	for _, t := range ft.in {
+		if t.size > uintptrSize {
 			panic("compileCallback: input parameter size is wrong")
 		}
 		argsize += uintptrSize
diff --git a/src/runtime/syscall_windows_test.go b/src/runtime/syscall_windows_test.go
index 677eb5f..7980703 100644
--- a/src/runtime/syscall_windows_test.go
+++ b/src/runtime/syscall_windows_test.go
@@ -5,6 +5,7 @@
 package runtime_test
 
 import (
+	"bytes"
 	"fmt"
 	"io/ioutil"
 	"os"
@@ -499,7 +500,7 @@ func TestOutputDebugString(t *testing.T) {
 }
 
 func TestRaiseException(t *testing.T) {
-	o := executeTest(t, raiseExceptionSource, nil)
+	o := runTestProg(t, "testprog", "RaiseException")
 	if strings.Contains(o, "RaiseException should not return") {
 		t.Fatalf("RaiseException did not crash program: %v", o)
 	}
@@ -508,35 +509,13 @@ func TestRaiseException(t *testing.T) {
 	}
 }
 
-const raiseExceptionSource = `
-package main
-import "syscall"
-func main() {
-	const EXCEPTION_NONCONTINUABLE = 1
-	mod := syscall.MustLoadDLL("kernel32.dll")
-	proc := mod.MustFindProc("RaiseException")
-	proc.Call(0xbad, EXCEPTION_NONCONTINUABLE, 0, 0)
-	println("RaiseException should not return")
-}
-`
-
 func TestZeroDivisionException(t *testing.T) {
-	o := executeTest(t, zeroDivisionExceptionSource, nil)
+	o := runTestProg(t, "testprog", "ZeroDivisionException")
 	if !strings.Contains(o, "panic: runtime error: integer divide by zero") {
 		t.Fatalf("No stack trace: %v", o)
 	}
 }
 
-const zeroDivisionExceptionSource = `
-package main
-func main() {
-	x := 1
-	y := 0
-	z := x / y
-	println(z)
-}
-`
-
 func TestWERDialogue(t *testing.T) {
 	if os.Getenv("TESTING_WER_DIALOGUE") == "1" {
 		defer os.Exit(0)
@@ -640,3 +619,155 @@ uintptr_t cfunc(callback f, uintptr_t n) {
 		t.Errorf("got %d want %d", got, want)
 	}
 }
+
+// removeOneCPU removes one (any) cpu from affinity mask.
+// It returns new affinity mask.
+func removeOneCPU(mask uintptr) (uintptr, error) {
+	if mask == 0 {
+		return 0, fmt.Errorf("cpu affinity mask is empty")
+	}
+	maskbits := int(unsafe.Sizeof(mask) * 8)
+	for i := 0; i < maskbits; i++ {
+		newmask := mask & ^(1 << uint(i))
+		if newmask != mask {
+			return newmask, nil
+		}
+
+	}
+	panic("not reached")
+}
+
+func resumeChildThread(kernel32 *syscall.DLL, childpid int) error {
+	_OpenThread := kernel32.MustFindProc("OpenThread")
+	_ResumeThread := kernel32.MustFindProc("ResumeThread")
+	_Thread32First := kernel32.MustFindProc("Thread32First")
+	_Thread32Next := kernel32.MustFindProc("Thread32Next")
+
+	snapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPTHREAD, 0)
+	if err != nil {
+		return err
+	}
+	defer syscall.CloseHandle(snapshot)
+
+	const _THREAD_SUSPEND_RESUME = 0x0002
+
+	type ThreadEntry32 struct {
+		Size           uint32
+		tUsage         uint32
+		ThreadID       uint32
+		OwnerProcessID uint32
+		BasePri        int32
+		DeltaPri       int32
+		Flags          uint32
+	}
+
+	var te ThreadEntry32
+	te.Size = uint32(unsafe.Sizeof(te))
+	ret, _, err := _Thread32First.Call(uintptr(snapshot), uintptr(unsafe.Pointer(&te)))
+	if ret == 0 {
+		return err
+	}
+	for te.OwnerProcessID != uint32(childpid) {
+		ret, _, err = _Thread32Next.Call(uintptr(snapshot), uintptr(unsafe.Pointer(&te)))
+		if ret == 0 {
+			return err
+		}
+	}
+	h, _, err := _OpenThread.Call(_THREAD_SUSPEND_RESUME, 1, uintptr(te.ThreadID))
+	if h == 0 {
+		return err
+	}
+	defer syscall.Close(syscall.Handle(h))
+
+	ret, _, err = _ResumeThread.Call(h)
+	if ret == 0xffffffff {
+		return err
+	}
+	return nil
+}
+
+func TestNumCPU(t *testing.T) {
+	if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
+		// in child process
+		fmt.Fprintf(os.Stderr, "%d", runtime.NumCPU())
+		os.Exit(0)
+	}
+
+	switch n := runtime.NumberOfProcessors(); {
+	case n < 1:
+		t.Fatalf("system cannot have %d cpu(s)", n)
+	case n == 1:
+		if runtime.NumCPU() != 1 {
+			t.Fatalf("runtime.NumCPU() returns %d on single cpu system", runtime.NumCPU())
+		}
+		return
+	}
+
+	const (
+		_CREATE_SUSPENDED   = 0x00000004
+		_PROCESS_ALL_ACCESS = syscall.STANDARD_RIGHTS_REQUIRED | syscall.SYNCHRONIZE | 0xfff
+	)
+
+	kernel32 := syscall.MustLoadDLL("kernel32.dll")
+	_GetProcessAffinityMask := kernel32.MustFindProc("GetProcessAffinityMask")
+	_SetProcessAffinityMask := kernel32.MustFindProc("SetProcessAffinityMask")
+
+	cmd := exec.Command(os.Args[0], "-test.run=TestNumCPU")
+	cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1")
+	var buf bytes.Buffer
+	cmd.Stdout = &buf
+	cmd.Stderr = &buf
+	cmd.SysProcAttr = &syscall.SysProcAttr{CreationFlags: _CREATE_SUSPENDED}
+	err := cmd.Start()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer func() {
+		err = cmd.Wait()
+		childOutput := string(buf.Bytes())
+		if err != nil {
+			t.Fatalf("child failed: %v: %v", err, childOutput)
+		}
+		// removeOneCPU should have decreased child cpu count by 1
+		want := fmt.Sprintf("%d", runtime.NumCPU()-1)
+		if childOutput != want {
+			t.Fatalf("child output: want %q, got %q", want, childOutput)
+		}
+	}()
+
+	defer func() {
+		err = resumeChildThread(kernel32, cmd.Process.Pid)
+		if err != nil {
+			t.Fatal(err)
+		}
+	}()
+
+	ph, err := syscall.OpenProcess(_PROCESS_ALL_ACCESS, false, uint32(cmd.Process.Pid))
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer syscall.CloseHandle(ph)
+
+	var mask, sysmask uintptr
+	ret, _, err := _GetProcessAffinityMask.Call(uintptr(ph), uintptr(unsafe.Pointer(&mask)), uintptr(unsafe.Pointer(&sysmask)))
+	if ret == 0 {
+		t.Fatal(err)
+	}
+
+	newmask, err := removeOneCPU(mask)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	ret, _, err = _SetProcessAffinityMask.Call(uintptr(ph), newmask)
+	if ret == 0 {
+		t.Fatal(err)
+	}
+	ret, _, err = _GetProcessAffinityMask.Call(uintptr(ph), uintptr(unsafe.Pointer(&mask)), uintptr(unsafe.Pointer(&sysmask)))
+	if ret == 0 {
+		t.Fatal(err)
+	}
+	if newmask != mask {
+		t.Fatalf("SetProcessAffinityMask didn't set newmask of 0x%x. Current mask is 0x%x.", newmask, mask)
+	}
+}
diff --git a/src/runtime/testdata/testprog/crash.go b/src/runtime/testdata/testprog/crash.go
new file mode 100644
index 0000000..3d7c7c6
--- /dev/null
+++ b/src/runtime/testdata/testprog/crash.go
@@ -0,0 +1,45 @@
+// Copyright 2015 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 (
+	"fmt"
+	"runtime"
+)
+
+func init() {
+	register("Crash", Crash)
+}
+
+func test(name string) {
+	defer func() {
+		if x := recover(); x != nil {
+			fmt.Printf(" recovered")
+		}
+		fmt.Printf(" done\n")
+	}()
+	fmt.Printf("%s:", name)
+	var s *string
+	_ = *s
+	fmt.Print("SHOULD NOT BE HERE")
+}
+
+func testInNewThread(name string) {
+	c := make(chan bool)
+	go func() {
+		runtime.LockOSThread()
+		test(name)
+		c <- true
+	}()
+	<-c
+}
+
+func Crash() {
+	runtime.LockOSThread()
+	test("main")
+	testInNewThread("new-thread")
+	testInNewThread("second-new-thread")
+	test("main-again")
+}
diff --git a/src/runtime/testdata/testprog/deadlock.go b/src/runtime/testdata/testprog/deadlock.go
new file mode 100644
index 0000000..73fbf62
--- /dev/null
+++ b/src/runtime/testdata/testprog/deadlock.go
@@ -0,0 +1,191 @@
+// Copyright 2015 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 (
+	"fmt"
+	"runtime"
+	"runtime/debug"
+	"time"
+)
+
+func init() {
+	registerInit("InitDeadlock", InitDeadlock)
+	registerInit("NoHelperGoroutines", NoHelperGoroutines)
+
+	register("SimpleDeadlock", SimpleDeadlock)
+	register("LockedDeadlock", LockedDeadlock)
+	register("LockedDeadlock2", LockedDeadlock2)
+	register("GoexitDeadlock", GoexitDeadlock)
+	register("StackOverflow", StackOverflow)
+	register("ThreadExhaustion", ThreadExhaustion)
+	register("RecursivePanic", RecursivePanic)
+	register("GoexitExit", GoexitExit)
+	register("GoNil", GoNil)
+	register("MainGoroutineID", MainGoroutineID)
+	register("Breakpoint", Breakpoint)
+	register("GoexitInPanic", GoexitInPanic)
+	register("PanicAfterGoexit", PanicAfterGoexit)
+	register("RecoveredPanicAfterGoexit", RecoveredPanicAfterGoexit)
+	register("PanicTraceback", PanicTraceback)
+}
+
+func SimpleDeadlock() {
+	select {}
+	panic("not reached")
+}
+
+func InitDeadlock() {
+	select {}
+	panic("not reached")
+}
+
+func LockedDeadlock() {
+	runtime.LockOSThread()
+	select {}
+}
+
+func LockedDeadlock2() {
+	go func() {
+		runtime.LockOSThread()
+		select {}
+	}()
+	time.Sleep(time.Millisecond)
+	select {}
+}
+
+func GoexitDeadlock() {
+	F := func() {
+		for i := 0; i < 10; i++ {
+		}
+	}
+
+	go F()
+	go F()
+	runtime.Goexit()
+}
+
+func StackOverflow() {
+	var f func() byte
+	f = func() byte {
+		var buf [64 << 10]byte
+		return buf[0] + f()
+	}
+	debug.SetMaxStack(1474560)
+	f()
+}
+
+func ThreadExhaustion() {
+	debug.SetMaxThreads(10)
+	c := make(chan int)
+	for i := 0; i < 100; i++ {
+		go func() {
+			runtime.LockOSThread()
+			c <- 0
+			select {}
+		}()
+		<-c
+	}
+}
+
+func RecursivePanic() {
+	func() {
+		defer func() {
+			fmt.Println(recover())
+		}()
+		var x [8192]byte
+		func(x [8192]byte) {
+			defer func() {
+				if err := recover(); err != nil {
+					panic("wrap: " + err.(string))
+				}
+			}()
+			panic("bad")
+		}(x)
+	}()
+	panic("again")
+}
+
+func GoexitExit() {
+	go func() {
+		time.Sleep(time.Millisecond)
+	}()
+	i := 0
+	runtime.SetFinalizer(&i, func(p *int) {})
+	runtime.GC()
+	runtime.Goexit()
+}
+
+func GoNil() {
+	defer func() {
+		recover()
+	}()
+	var f func()
+	go f()
+	select {}
+}
+
+func MainGoroutineID() {
+	panic("test")
+}
+
+func NoHelperGoroutines() {
+	i := 0
+	runtime.SetFinalizer(&i, func(p *int) {})
+	time.AfterFunc(time.Hour, func() {})
+	panic("oops")
+}
+
+func Breakpoint() {
+	runtime.Breakpoint()
+}
+
+func GoexitInPanic() {
+	go func() {
+		defer func() {
+			runtime.Goexit()
+		}()
+		panic("hello")
+	}()
+	runtime.Goexit()
+}
+
+func PanicAfterGoexit() {
+	defer func() {
+		panic("hello")
+	}()
+	runtime.Goexit()
+}
+
+func RecoveredPanicAfterGoexit() {
+	defer func() {
+		defer func() {
+			r := recover()
+			if r == nil {
+				panic("bad recover")
+			}
+		}()
+		panic("hello")
+	}()
+	runtime.Goexit()
+}
+
+func PanicTraceback() {
+	pt1()
+}
+
+func pt1() {
+	defer func() {
+		panic("panic pt1")
+	}()
+	pt2()
+}
+
+func pt2() {
+	defer func() {
+		panic("panic pt2")
+	}()
+	panic("hello")
+}
diff --git a/src/runtime/testdata/testprog/gc.go b/src/runtime/testdata/testprog/gc.go
new file mode 100644
index 0000000..9bb367c
--- /dev/null
+++ b/src/runtime/testdata/testprog/gc.go
@@ -0,0 +1,74 @@
+// Copyright 2015 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 (
+	"fmt"
+	"os"
+	"runtime"
+	"time"
+)
+
+func init() {
+	register("GCFairness", GCFairness)
+	register("GCSys", GCSys)
+}
+
+func GCSys() {
+	runtime.GOMAXPROCS(1)
+	memstats := new(runtime.MemStats)
+	runtime.GC()
+	runtime.ReadMemStats(memstats)
+	sys := memstats.Sys
+
+	runtime.MemProfileRate = 0 // disable profiler
+
+	itercount := 100000
+	for i := 0; i < itercount; i++ {
+		workthegc()
+	}
+
+	// Should only be using a few MB.
+	// We allocated 100 MB or (if not short) 1 GB.
+	runtime.ReadMemStats(memstats)
+	if sys > memstats.Sys {
+		sys = 0
+	} else {
+		sys = memstats.Sys - sys
+	}
+	if sys > 16<<20 {
+		fmt.Printf("using too much memory: %d bytes\n", sys)
+		return
+	}
+	fmt.Printf("OK\n")
+}
+
+func workthegc() []byte {
+	return make([]byte, 1029)
+}
+
+func GCFairness() {
+	runtime.GOMAXPROCS(1)
+	f, err := os.Open("/dev/null")
+	if os.IsNotExist(err) {
+		// This test tests what it is intended to test only if writes are fast.
+		// If there is no /dev/null, we just don't execute the test.
+		fmt.Println("OK")
+		return
+	}
+	if err != nil {
+		fmt.Println(err)
+		os.Exit(1)
+	}
+	for i := 0; i < 2; i++ {
+		go func() {
+			for {
+				f.Write([]byte("."))
+			}
+		}()
+	}
+	time.Sleep(10 * time.Millisecond)
+	fmt.Println("OK")
+}
diff --git a/src/runtime/testdata/testprog/main.go b/src/runtime/testdata/testprog/main.go
new file mode 100644
index 0000000..9c227bb
--- /dev/null
+++ b/src/runtime/testdata/testprog/main.go
@@ -0,0 +1,35 @@
+// Copyright 2015 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 "os"
+
+var cmds = map[string]func(){}
+
+func register(name string, f func()) {
+	if cmds[name] != nil {
+		panic("duplicate registration: " + name)
+	}
+	cmds[name] = f
+}
+
+func registerInit(name string, f func()) {
+	if len(os.Args) >= 2 && os.Args[1] == name {
+		f()
+	}
+}
+
+func main() {
+	if len(os.Args) < 2 {
+		println("usage: " + os.Args[0] + " name-of-test")
+		return
+	}
+	f := cmds[os.Args[1]]
+	if f == nil {
+		println("unknown function: " + os.Args[1])
+		return
+	}
+	f()
+}
diff --git a/src/runtime/testdata/testprog/misc.go b/src/runtime/testdata/testprog/misc.go
new file mode 100644
index 0000000..237680f
--- /dev/null
+++ b/src/runtime/testdata/testprog/misc.go
@@ -0,0 +1,15 @@
+// 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 main
+
+import "runtime"
+
+func init() {
+	register("NumGoroutine", NumGoroutine)
+}
+
+func NumGoroutine() {
+	println(runtime.NumGoroutine())
+}
diff --git a/src/runtime/testdata/testprog/signal.go b/src/runtime/testdata/testprog/signal.go
new file mode 100644
index 0000000..ac2d3e8
--- /dev/null
+++ b/src/runtime/testdata/testprog/signal.go
@@ -0,0 +1,17 @@
+// Copyright 2015 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.
+
+// +build !windows,!plan9,!nacl
+
+package main
+
+import "syscall"
+
+func init() {
+	register("SignalExitStatus", SignalExitStatus)
+}
+
+func SignalExitStatus() {
+	syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
+}
diff --git a/src/runtime/testdata/testprog/stringconcat.go b/src/runtime/testdata/testprog/stringconcat.go
new file mode 100644
index 0000000..9dddf19
--- /dev/null
+++ b/src/runtime/testdata/testprog/stringconcat.go
@@ -0,0 +1,20 @@
+// Copyright 2015 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 "strings"
+
+func init() {
+	register("stringconcat", stringconcat)
+}
+
+func stringconcat() {
+	s0 := strings.Repeat("0", 1<<10)
+	s1 := strings.Repeat("1", 1<<10)
+	s2 := strings.Repeat("2", 1<<10)
+	s3 := strings.Repeat("3", 1<<10)
+	s := s0 + s1 + s2 + s3
+	panic(s)
+}
diff --git a/src/runtime/testdata/testprog/syscall_windows.go b/src/runtime/testdata/testprog/syscall_windows.go
new file mode 100644
index 0000000..73165be
--- /dev/null
+++ b/src/runtime/testdata/testprog/syscall_windows.go
@@ -0,0 +1,27 @@
+// Copyright 2015 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 "syscall"
+
+func init() {
+	register("RaiseException", RaiseException)
+	register("ZeroDivisionException", ZeroDivisionException)
+}
+
+func RaiseException() {
+	const EXCEPTION_NONCONTINUABLE = 1
+	mod := syscall.MustLoadDLL("kernel32.dll")
+	proc := mod.MustFindProc("RaiseException")
+	proc.Call(0xbad, EXCEPTION_NONCONTINUABLE, 0, 0)
+	println("RaiseException should not return")
+}
+
+func ZeroDivisionException() {
+	x := 1
+	y := 0
+	z := x / y
+	println(z)
+}
diff --git a/src/runtime/testdata/testprogcgo/callback.go b/src/runtime/testdata/testprogcgo/callback.go
new file mode 100644
index 0000000..10e248a
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/callback.go
@@ -0,0 +1,89 @@
+// Copyright 2015 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.
+
+// +build !plan9,!windows
+
+package main
+
+/*
+#include <pthread.h>
+
+void go_callback();
+
+static void *thr(void *arg) {
+    go_callback();
+    return 0;
+}
+
+static void foo() {
+    pthread_t th;
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setstacksize(&attr, 256 << 10);
+    pthread_create(&th, &attr, thr, 0);
+    pthread_join(th, 0);
+}
+*/
+import "C"
+
+import (
+	"fmt"
+	"runtime"
+)
+
+func init() {
+	register("CgoCallbackGC", CgoCallbackGC)
+}
+
+//export go_callback
+func go_callback() {
+	runtime.GC()
+	grow()
+	runtime.GC()
+}
+
+var cnt int
+
+func grow() {
+	x := 10000
+	sum := 0
+	if grow1(&x, &sum) == 0 {
+		panic("bad")
+	}
+}
+
+func grow1(x, sum *int) int {
+	if *x == 0 {
+		return *sum + 1
+	}
+	*x--
+	sum1 := *sum + *x
+	return grow1(x, &sum1)
+}
+
+func CgoCallbackGC() {
+	const P = 100
+	done := make(chan bool)
+	// allocate a bunch of stack frames and spray them with pointers
+	for i := 0; i < P; i++ {
+		go func() {
+			grow()
+			done <- true
+		}()
+	}
+	for i := 0; i < P; i++ {
+		<-done
+	}
+	// now give these stack frames to cgo callbacks
+	for i := 0; i < P; i++ {
+		go func() {
+			C.foo()
+			done <- true
+		}()
+	}
+	for i := 0; i < P; i++ {
+		<-done
+	}
+	fmt.Printf("OK\n")
+}
diff --git a/src/runtime/testdata/testprogcgo/cgo.go b/src/runtime/testdata/testprogcgo/cgo.go
new file mode 100644
index 0000000..cf1af82
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/cgo.go
@@ -0,0 +1,80 @@
+// Copyright 2015 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
+
+/*
+void foo1(void) {}
+*/
+import "C"
+import (
+	"fmt"
+	"runtime"
+	"time"
+)
+
+func init() {
+	register("CgoSignalDeadlock", CgoSignalDeadlock)
+	register("CgoTraceback", CgoTraceback)
+}
+
+func CgoSignalDeadlock() {
+	runtime.GOMAXPROCS(100)
+	ping := make(chan bool)
+	go func() {
+		for i := 0; ; i++ {
+			runtime.Gosched()
+			select {
+			case done := <-ping:
+				if done {
+					ping <- true
+					return
+				}
+				ping <- true
+			default:
+			}
+			func() {
+				defer func() {
+					recover()
+				}()
+				var s *string
+				*s = ""
+			}()
+		}
+	}()
+	time.Sleep(time.Millisecond)
+	for i := 0; i < 64; i++ {
+		go func() {
+			runtime.LockOSThread()
+			select {}
+		}()
+		go func() {
+			runtime.LockOSThread()
+			select {}
+		}()
+		time.Sleep(time.Millisecond)
+		ping <- false
+		select {
+		case <-ping:
+		case <-time.After(time.Second):
+			fmt.Printf("HANG\n")
+			return
+		}
+	}
+	ping <- true
+	select {
+	case <-ping:
+	case <-time.After(time.Second):
+		fmt.Printf("HANG\n")
+		return
+	}
+	fmt.Printf("OK\n")
+}
+
+func CgoTraceback() {
+	C.foo1()
+	buf := make([]byte, 1)
+	runtime.Stack(buf, true)
+	fmt.Printf("OK\n")
+}
diff --git a/src/runtime/testdata/testprogcgo/crash.go b/src/runtime/testdata/testprogcgo/crash.go
new file mode 100644
index 0000000..3d7c7c6
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/crash.go
@@ -0,0 +1,45 @@
+// Copyright 2015 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 (
+	"fmt"
+	"runtime"
+)
+
+func init() {
+	register("Crash", Crash)
+}
+
+func test(name string) {
+	defer func() {
+		if x := recover(); x != nil {
+			fmt.Printf(" recovered")
+		}
+		fmt.Printf(" done\n")
+	}()
+	fmt.Printf("%s:", name)
+	var s *string
+	_ = *s
+	fmt.Print("SHOULD NOT BE HERE")
+}
+
+func testInNewThread(name string) {
+	c := make(chan bool)
+	go func() {
+		runtime.LockOSThread()
+		test(name)
+		c <- true
+	}()
+	<-c
+}
+
+func Crash() {
+	runtime.LockOSThread()
+	test("main")
+	testInNewThread("new-thread")
+	testInNewThread("second-new-thread")
+	test("main-again")
+}
diff --git a/src/runtime/testdata/testprogcgo/dll_windows.go b/src/runtime/testdata/testprogcgo/dll_windows.go
new file mode 100644
index 0000000..a0647ef
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/dll_windows.go
@@ -0,0 +1,25 @@
+// Copyright 2015 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
+
+/*
+#include <windows.h>
+
+DWORD getthread() {
+	return GetCurrentThreadId();
+}
+*/
+import "C"
+import "./windows"
+
+func init() {
+	register("CgoDLLImportsMain", CgoDLLImportsMain)
+}
+
+func CgoDLLImportsMain() {
+	C.getthread()
+	windows.GetThread()
+	println("OK")
+}
diff --git a/src/runtime/testdata/testprogcgo/dropm.go b/src/runtime/testdata/testprogcgo/dropm.go
new file mode 100644
index 0000000..75984ea
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/dropm.go
@@ -0,0 +1,59 @@
+// 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.
+
+// +build !plan9,!windows
+
+// Test that a sequence of callbacks from C to Go get the same m.
+// This failed to be true on arm and arm64, which was the root cause
+// of issue 13881.
+
+package main
+
+/*
+#include <stddef.h>
+#include <pthread.h>
+
+extern void GoCheckM();
+
+static void* thread(void* arg __attribute__ ((unused))) {
+	GoCheckM();
+	return NULL;
+}
+
+static void CheckM() {
+	pthread_t tid;
+	pthread_create(&tid, NULL, thread, NULL);
+	pthread_join(tid, NULL);
+	pthread_create(&tid, NULL, thread, NULL);
+	pthread_join(tid, NULL);
+}
+*/
+import "C"
+
+import (
+	"fmt"
+	"os"
+)
+
+func init() {
+	register("EnsureDropM", EnsureDropM)
+}
+
+var savedM uintptr
+
+//export GoCheckM
+func GoCheckM() {
+	m := runtime_getm_for_test()
+	if savedM == 0 {
+		savedM = m
+	} else if savedM != m {
+		fmt.Printf("m == %x want %x\n", m, savedM)
+		os.Exit(1)
+	}
+}
+
+func EnsureDropM() {
+	C.CheckM()
+	fmt.Println("OK")
+}
diff --git a/src/runtime/testdata/testprogcgo/dropm_stub.go b/src/runtime/testdata/testprogcgo/dropm_stub.go
new file mode 100644
index 0000000..4c3f46a
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/dropm_stub.go
@@ -0,0 +1,11 @@
+// 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 main
+
+import _ "unsafe" // for go:linkname
+
+// Defined in the runtime package.
+//go:linkname runtime_getm_for_test runtime.getm
+func runtime_getm_for_test() uintptr
diff --git a/src/runtime/testdata/testprogcgo/exec.go b/src/runtime/testdata/testprogcgo/exec.go
new file mode 100644
index 0000000..8dc1d51
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/exec.go
@@ -0,0 +1,89 @@
+// Copyright 2015 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.
+
+// +build !plan9,!windows
+
+package main
+
+/*
+#include <stddef.h>
+#include <signal.h>
+#include <pthread.h>
+
+// Save the signal mask at startup so that we see what it is before
+// the Go runtime starts setting up signals.
+
+static sigset_t mask;
+
+static void init(void) __attribute__ ((constructor));
+
+static void init() {
+	sigemptyset(&mask);
+	pthread_sigmask(SIG_SETMASK, NULL, &mask);
+}
+
+int SIGINTBlocked() {
+	return sigismember(&mask, SIGINT);
+}
+*/
+import "C"
+
+import (
+	"fmt"
+	"os"
+	"os/exec"
+	"os/signal"
+	"sync"
+	"syscall"
+)
+
+func init() {
+	register("CgoExecSignalMask", CgoExecSignalMask)
+}
+
+func CgoExecSignalMask() {
+	if len(os.Args) > 2 && os.Args[2] == "testsigint" {
+		if C.SIGINTBlocked() != 0 {
+			os.Exit(1)
+		}
+		os.Exit(0)
+	}
+
+	c := make(chan os.Signal, 1)
+	signal.Notify(c, syscall.SIGTERM)
+	go func() {
+		for range c {
+		}
+	}()
+
+	const goCount = 10
+	const execCount = 10
+	var wg sync.WaitGroup
+	wg.Add(goCount*execCount + goCount)
+	for i := 0; i < goCount; i++ {
+		go func() {
+			defer wg.Done()
+			for j := 0; j < execCount; j++ {
+				c2 := make(chan os.Signal, 1)
+				signal.Notify(c2, syscall.SIGUSR1)
+				syscall.Kill(os.Getpid(), syscall.SIGTERM)
+				go func(j int) {
+					defer wg.Done()
+					cmd := exec.Command(os.Args[0], "CgoExecSignalMask", "testsigint")
+					cmd.Stdin = os.Stdin
+					cmd.Stdout = os.Stdout
+					cmd.Stderr = os.Stderr
+					if err := cmd.Run(); err != nil {
+						fmt.Printf("iteration %d: %v\n", j, err)
+						os.Exit(1)
+					}
+				}(j)
+				signal.Stop(c2)
+			}
+		}()
+	}
+	wg.Wait()
+
+	fmt.Println("OK")
+}
diff --git a/src/runtime/testdata/testprogcgo/main.go b/src/runtime/testdata/testprogcgo/main.go
new file mode 100644
index 0000000..9c227bb
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/main.go
@@ -0,0 +1,35 @@
+// Copyright 2015 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 "os"
+
+var cmds = map[string]func(){}
+
+func register(name string, f func()) {
+	if cmds[name] != nil {
+		panic("duplicate registration: " + name)
+	}
+	cmds[name] = f
+}
+
+func registerInit(name string, f func()) {
+	if len(os.Args) >= 2 && os.Args[1] == name {
+		f()
+	}
+}
+
+func main() {
+	if len(os.Args) < 2 {
+		println("usage: " + os.Args[0] + " name-of-test")
+		return
+	}
+	f := cmds[os.Args[1]]
+	if f == nil {
+		println("unknown function: " + os.Args[1])
+		return
+	}
+	f()
+}
diff --git a/src/runtime/testdata/testprogcgo/threadpanic.go b/src/runtime/testdata/testprogcgo/threadpanic.go
new file mode 100644
index 0000000..3c9baba
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/threadpanic.go
@@ -0,0 +1,24 @@
+// Copyright 2015 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.
+
+// +build !plan9
+
+package main
+
+// void start(void);
+import "C"
+
+func init() {
+	register("CgoExternalThreadPanic", CgoExternalThreadPanic)
+}
+
+func CgoExternalThreadPanic() {
+	C.start()
+	select {}
+}
+
+//export gopanic
+func gopanic() {
+	panic("BOOM")
+}
diff --git a/src/runtime/testdata/testprogcgo/threadpanic_unix.c b/src/runtime/testdata/testprogcgo/threadpanic_unix.c
new file mode 100644
index 0000000..dea8160
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/threadpanic_unix.c
@@ -0,0 +1,26 @@
+// Copyright 2015 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.
+
+// +build !plan9,!windows
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <pthread.h>
+
+void gopanic(void);
+
+static void*
+die(void* x)
+{
+	gopanic();
+	return 0;
+}
+
+void
+start(void)
+{
+	pthread_t t;
+	if(pthread_create(&t, 0, die, 0) != 0)
+		printf("pthread_create failed\n");
+}
diff --git a/src/runtime/testdata/testprogcgo/threadpanic_windows.c b/src/runtime/testdata/testprogcgo/threadpanic_windows.c
new file mode 100644
index 0000000..0a19ffa
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/threadpanic_windows.c
@@ -0,0 +1,22 @@
+// Copyright 2015 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 <stdlib.h>
+#include <stdio.h>
+
+void gopanic(void);
+
+static void*
+die(void* x)
+{
+	gopanic();
+	return 0;
+}
+
+void
+start(void)
+{
+	if(_beginthreadex(0, 0, die, 0, 0, 0) != 0)
+		printf("_beginthreadex failed\n");
+}
diff --git a/src/runtime/testdata/testprogcgo/threadprof.go b/src/runtime/testdata/testprogcgo/threadprof.go
new file mode 100644
index 0000000..03e35d2
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/threadprof.go
@@ -0,0 +1,93 @@
+// Copyright 2015 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.
+
+// +build !plan9,!windows
+
+package main
+
+/*
+#include <stdint.h>
+#include <signal.h>
+#include <pthread.h>
+
+volatile int32_t spinlock;
+
+static void *thread1(void *p) {
+	(void)p;
+	while (spinlock == 0)
+		;
+	pthread_kill(pthread_self(), SIGPROF);
+	spinlock = 0;
+	return NULL;
+}
+__attribute__((constructor)) void issue9456() {
+	pthread_t tid;
+	pthread_create(&tid, 0, thread1, NULL);
+}
+
+void **nullptr;
+
+void *crash(void *p) {
+	*nullptr = p;
+	return 0;
+}
+
+int start_crashing_thread(void) {
+	pthread_t tid;
+	return pthread_create(&tid, 0, crash, 0);
+}
+*/
+import "C"
+
+import (
+	"fmt"
+	"os"
+	"os/exec"
+	"runtime"
+	"sync/atomic"
+	"time"
+	"unsafe"
+)
+
+func init() {
+	register("CgoExternalThreadSIGPROF", CgoExternalThreadSIGPROF)
+	register("CgoExternalThreadSignal", CgoExternalThreadSignal)
+}
+
+func CgoExternalThreadSIGPROF() {
+	// This test intends to test that sending SIGPROF to foreign threads
+	// before we make any cgo call will not abort the whole process, so
+	// we cannot make any cgo call here. See https://golang.org/issue/9456.
+	atomic.StoreInt32((*int32)(unsafe.Pointer(&C.spinlock)), 1)
+	for atomic.LoadInt32((*int32)(unsafe.Pointer(&C.spinlock))) == 1 {
+		runtime.Gosched()
+	}
+	println("OK")
+}
+
+func CgoExternalThreadSignal() {
+	if len(os.Args) > 2 && os.Args[2] == "crash" {
+		i := C.start_crashing_thread()
+		if i != 0 {
+			fmt.Println("pthread_create failed:", i)
+			// Exit with 0 because parent expects us to crash.
+			return
+		}
+
+		// We should crash immediately, but give it plenty of
+		// time before failing (by exiting 0) in case we are
+		// running on a slow system.
+		time.Sleep(5 * time.Second)
+		return
+	}
+
+	out, err := exec.Command(os.Args[0], "CgoExternalThreadSignal", "crash").CombinedOutput()
+	if err == nil {
+		fmt.Println("C signal did not crash as expected\n")
+		fmt.Printf("%s\n", out)
+		os.Exit(1)
+	}
+
+	fmt.Println("OK")
+}
diff --git a/src/runtime/testdata/testprogcgo/windows/win.go b/src/runtime/testdata/testprogcgo/windows/win.go
new file mode 100644
index 0000000..f2eabb9
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/windows/win.go
@@ -0,0 +1,16 @@
+package windows
+
+/*
+#cgo CFLAGS: -mnop-fun-dllimport
+
+#include <windows.h>
+
+DWORD agetthread() {
+	return GetCurrentThreadId();
+}
+*/
+import "C"
+
+func GetThread() uint32 {
+	return uint32(C.agetthread())
+}
diff --git a/src/runtime/testdata/testprognet/main.go b/src/runtime/testdata/testprognet/main.go
new file mode 100644
index 0000000..9c227bb
--- /dev/null
+++ b/src/runtime/testdata/testprognet/main.go
@@ -0,0 +1,35 @@
+// Copyright 2015 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 "os"
+
+var cmds = map[string]func(){}
+
+func register(name string, f func()) {
+	if cmds[name] != nil {
+		panic("duplicate registration: " + name)
+	}
+	cmds[name] = f
+}
+
+func registerInit(name string, f func()) {
+	if len(os.Args) >= 2 && os.Args[1] == name {
+		f()
+	}
+}
+
+func main() {
+	if len(os.Args) < 2 {
+		println("usage: " + os.Args[0] + " name-of-test")
+		return
+	}
+	f := cmds[os.Args[1]]
+	if f == nil {
+		println("unknown function: " + os.Args[1])
+		return
+	}
+	f()
+}
diff --git a/src/runtime/testdata/testprognet/net.go b/src/runtime/testdata/testprognet/net.go
new file mode 100644
index 0000000..c1a7f3f
--- /dev/null
+++ b/src/runtime/testdata/testprognet/net.go
@@ -0,0 +1,29 @@
+// Copyright 2015 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 (
+	"fmt"
+	"net"
+)
+
+func init() {
+	registerInit("NetpollDeadlock", NetpollDeadlockInit)
+	register("NetpollDeadlock", NetpollDeadlock)
+}
+
+func NetpollDeadlockInit() {
+	fmt.Println("dialing")
+	c, err := net.Dial("tcp", "localhost:14356")
+	if err == nil {
+		c.Close()
+	} else {
+		fmt.Println("error: ", err)
+	}
+}
+
+func NetpollDeadlock() {
+	fmt.Println("done")
+}
diff --git a/src/runtime/testdata/testprognet/signal.go b/src/runtime/testdata/testprognet/signal.go
new file mode 100644
index 0000000..24d1424
--- /dev/null
+++ b/src/runtime/testdata/testprognet/signal.go
@@ -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.
+
+// +build !windows,!plan9,!nacl
+
+// This is in testprognet instead of testprog because testprog
+// must not import anything (like net, but also like os/signal)
+// that kicks off background goroutines during init.
+
+package main
+
+import (
+	"os/signal"
+	"syscall"
+)
+
+func init() {
+	register("SignalIgnoreSIGTRAP", SignalIgnoreSIGTRAP)
+}
+
+func SignalIgnoreSIGTRAP() {
+	signal.Ignore(syscall.SIGTRAP)
+	syscall.Kill(syscall.Getpid(), syscall.SIGTRAP)
+	println("OK")
+}
diff --git a/src/runtime/textflag.h b/src/runtime/textflag.h
index 2a76e76..dbf3d99 100644
--- a/src/runtime/textflag.h
+++ b/src/runtime/textflag.h
@@ -21,3 +21,10 @@
 #define WRAPPER 32
 // This function uses its incoming context register.
 #define NEEDCTXT 64
+// Allocate a word of thread local storage and store the offset from the
+// thread local base to the thread local storage in this variable.
+#define TLSBSS	256
+// Do not insert instructions to allocate a stack frame for this function.
+// Only valid on functions that declare a frame size of 0.
+// TODO(mwhudson): only implemented for ppc64x at present.
+#define NOFRAME 512
diff --git a/src/runtime/time.go b/src/runtime/time.go
index ffe7590..3f8f696 100644
--- a/src/runtime/time.go
+++ b/src/runtime/time.go
@@ -16,7 +16,7 @@ type timer struct {
 	i int // heap index
 
 	// Timer wakes up at when, and then at when+period, ... (period > 0 only)
-	// each time calling f(now, arg) in the timer goroutine, so f must be
+	// each time calling f(arg, now) in the timer goroutine, so f must be
 	// a well-behaved function and not block.
 	when   int64
 	period int64
diff --git a/src/runtime/tls_arm.s b/src/runtime/tls_arm.s
index d37970e..00ca469 100644
--- a/src/runtime/tls_arm.s
+++ b/src/runtime/tls_arm.s
@@ -15,7 +15,7 @@
 // Note: both functions will clobber R0 and R11 and
 // can be called from 5c ABI code.
 
-// On android and darwin, runtime.tlsg is a normal variable.
+// On android and darwin, runtime.tls_g is a normal variable.
 // TLS offset is computed in x_cgo_inittls.
 #ifdef GOOS_android
 #define TLSG_IS_VARIABLE
@@ -41,14 +41,7 @@ TEXT runtime·save_g(SB),NOSPLIT,$-4
 	// The replacement function saves LR in R11 over the call to read_tls_fallback.
 	MRC	15, 0, R0, C13, C0, 3 // fetch TLS base pointer
 	BIC $3, R0 // Darwin/ARM might return unaligned pointer
-	// $runtime.tlsg(SB) is a special linker symbol.
-	// It is the offset from the TLS base pointer to our
-	// thread-local storage for g.
-#ifdef TLSG_IS_VARIABLE
-	MOVW	runtime·tlsg(SB), R11
-#else
-	MOVW	$runtime·tlsg(SB), R11
-#endif
+	MOVW	runtime·tls_g(SB), R11
 	ADD	R11, R0
 	MOVW	g, 0(R0)
 	MOVW	g, R0 // preserve R0 across call to setg<>
@@ -65,14 +58,7 @@ TEXT runtime·load_g(SB),NOSPLIT,$0
 	// See save_g
 	MRC	15, 0, R0, C13, C0, 3 // fetch TLS base pointer
 	BIC $3, R0 // Darwin/ARM might return unaligned pointer
-	// $runtime.tlsg(SB) is a special linker symbol.
-	// It is the offset from the TLS base pointer to our
-	// thread-local storage for g.
-#ifdef TLSG_IS_VARIABLE
-	MOVW	runtime·tlsg(SB), R11
-#else
-	MOVW	$runtime·tlsg(SB), R11
-#endif
+	MOVW	runtime·tls_g(SB), R11
 	ADD	R11, R0
 	MOVW	0(R0), g
 	RET
@@ -95,7 +81,11 @@ TEXT runtime·_initcgo(SB),NOSPLIT,$4
 	B.EQ	nocgo
 	MRC     15, 0, R0, C13, C0, 3 	// load TLS base pointer
 	MOVW 	R0, R3 			// arg 3: TLS base pointer
-	MOVW 	$runtime·tlsg(SB), R2 	// arg 2: tlsg
+#ifdef TLSG_IS_VARIABLE
+	MOVW 	$runtime·tls_g(SB), R2 	// arg 2: &tls_g
+#else
+        MOVW	$0, R2			// arg 2: not used when using platform tls
+#endif
 	MOVW	$setg_gcc<>(SB), R1 	// arg 1: setg
 	MOVW	g, R0 			// arg 0: G
 	BL	(R4) // will clobber R0-R3
@@ -109,5 +99,7 @@ TEXT setg_gcc<>(SB),NOSPLIT,$0
 	B		runtime·save_g(SB)
 
 #ifdef TLSG_IS_VARIABLE
-GLOBL runtime·tlsg+0(SB), NOPTR, $4
+GLOBL runtime·tls_g+0(SB), NOPTR, $4
+#else
+GLOBL runtime·tls_g+0(SB), TLSBSS, $4
 #endif
diff --git a/src/runtime/tls_arm64.h b/src/runtime/tls_arm64.h
index d5676ab..c29fa7f 100644
--- a/src/runtime/tls_arm64.h
+++ b/src/runtime/tls_arm64.h
@@ -2,7 +2,14 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+#ifdef GOOS_android
+#define TLS_linux
+#define TLSG_IS_VARIABLE
+#endif
 #ifdef GOOS_linux
+#define TLS_linux
+#endif
+#ifdef TLS_linux
 #define TPIDR TPIDR_EL0
 #define MRS_TPIDR_R0 WORD $0xd53bd040 // MRS TPIDR_EL0, R0
 #endif
diff --git a/src/runtime/tls_arm64.s b/src/runtime/tls_arm64.s
index a5f86c4..62ae6fa 100644
--- a/src/runtime/tls_arm64.s
+++ b/src/runtime/tls_arm64.s
@@ -18,13 +18,8 @@ TEXT runtime·load_g(SB),NOSPLIT,$0
 	// Darwin sometimes returns unaligned pointers
 	AND	$0xfffffffffffffff8, R0
 #endif
-#ifdef TLSG_IS_VARIABLE
 	MOVD	runtime·tls_g(SB), R27
 	ADD	R27, R0
-#else
-	// TODO(minux): use real TLS relocation, instead of hard-code for Linux
-	ADD	$0x10, R0
-#endif
 	MOVD	0(R0), g
 
 nocgo:
@@ -40,21 +35,15 @@ TEXT runtime·save_g(SB),NOSPLIT,$0
 	// Darwin sometimes returns unaligned pointers
 	AND	$0xfffffffffffffff8, R0
 #endif
-#ifdef TLSG_IS_VARIABLE
 	MOVD	runtime·tls_g(SB), R27
 	ADD	R27, R0
-#else
-	// TODO(minux): use real TLS relocation, instead of hard-code for Linux
-	ADD	$0x10, R0
-#endif
 	MOVD	g, 0(R0)
 
 nocgo:
 	RET
 
 #ifdef TLSG_IS_VARIABLE
-// The runtime.tlsg name is being handled specially in the
-// linker. As we just need a regular variable here, don't
-// use that name.
 GLOBL runtime·tls_g+0(SB), NOPTR, $8
+#else
+GLOBL runtime·tls_g+0(SB), TLSBSS, $8
 #endif
diff --git a/src/runtime/tls_mips64x.s b/src/runtime/tls_mips64x.s
new file mode 100644
index 0000000..c6f5bfa
--- /dev/null
+++ b/src/runtime/tls_mips64x.s
@@ -0,0 +1,23 @@
+// Copyright 2015 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.
+
+// +build mips64 mips64le
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "funcdata.h"
+#include "textflag.h"
+
+// If !iscgo, this is a no-op.
+//
+// NOTE: mcall() assumes this clobbers only R28 (REGTMP).
+TEXT runtime·save_g(SB),NOSPLIT,$-8-0
+	MOVB	runtime·iscgo(SB), R28
+	BEQ	R28, nocgo
+
+nocgo:
+	RET
+
+TEXT runtime·load_g(SB),NOSPLIT,$-8-0
+	RET
diff --git a/src/runtime/tls_ppc64x.s b/src/runtime/tls_ppc64x.s
index fc1718f..c79c97d 100644
--- a/src/runtime/tls_ppc64x.s
+++ b/src/runtime/tls_ppc64x.s
@@ -22,21 +22,12 @@
 // If !iscgo, this is a no-op.
 //
 // NOTE: setg_gcc<> assume this clobbers only R31.
-TEXT runtime·save_g(SB),NOSPLIT,$-8-0
+TEXT runtime·save_g(SB),NOSPLIT|NOFRAME,$0-0
 	MOVB	runtime·iscgo(SB), R31
 	CMP	R31, $0
 	BEQ	nocgo
-
-	// $runtime.tlsg(SB) is a special linker symbol.
-	// It is the offset from the start of TLS to our
-	// thread-local storage for g.
-	MOVD	$runtime·tlsg(SB), R31
-	ADD	R13, R31
-	// The actual TLS base is 0x7000 below R13
-	SUB	$0x7000, R31
-
-	// Store g in TLS
-	MOVD	g, 0(R31)
+	MOVD	runtime·tls_g(SB), R31
+	MOVD	g, 0(R13)(R31*1)
 
 nocgo:
 	RET
@@ -50,11 +41,9 @@ nocgo:
 // usual Go registers aren't set up.
 //
 // NOTE: _cgo_topofstack assumes this only clobbers g (R30), and R31.
-TEXT runtime·load_g(SB),NOSPLIT,$-8-0
-	MOVD	$runtime·tlsg(SB), R31
-	// R13 is the C ABI TLS base pointer + 0x7000
-	ADD	R13, R31
-	SUB	$0x7000, R31
-
-	MOVD	0(R31), g
+TEXT runtime·load_g(SB),NOSPLIT|NOFRAME,$0-0
+	MOVD	runtime·tls_g(SB), R31
+	MOVD	0(R13)(R31*1), g
 	RET
+
+GLOBL runtime·tls_g+0(SB), TLSBSS, $8
diff --git a/src/runtime/trace.go b/src/runtime/trace.go
index c818462..805c34f 100644
--- a/src/runtime/trace.go
+++ b/src/runtime/trace.go
@@ -12,7 +12,11 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/atomic"
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 // Event types in the trace, args are given in square brackets.
 const (
@@ -66,7 +70,7 @@ const (
 	// and ppc64le.
 	// Tracing won't work reliably for architectures where cputicks is emulated
 	// by nanotime, so the value doesn't matter for those architectures.
-	traceTickDiv = 16 + 48*(goarch_386|goarch_amd64|goarch_amd64p32)
+	traceTickDiv = 16 + 48*(sys.Goarch386|sys.GoarchAmd64|sys.GoarchAmd64p32)
 	// Maximum number of PCs in a single stack trace.
 	// Since events contain only stack id rather than whole stack trace,
 	// we can allow quite large values here.
@@ -88,27 +92,27 @@ const (
 
 // trace is global tracing context.
 var trace struct {
-	lock          mutex     // protects the following members
-	lockOwner     *g        // to avoid deadlocks during recursive lock locks
-	enabled       bool      // when set runtime traces events
-	shutdown      bool      // set when we are waiting for trace reader to finish after setting enabled to false
-	headerWritten bool      // whether ReadTrace has emitted trace header
-	footerWritten bool      // whether ReadTrace has emitted trace footer
-	shutdownSema  uint32    // used to wait for ReadTrace completion
-	seqStart      uint64    // sequence number when tracing was started
-	ticksStart    int64     // cputicks when tracing was started
-	ticksEnd      int64     // cputicks when tracing was stopped
-	timeStart     int64     // nanotime when tracing was started
-	timeEnd       int64     // nanotime when tracing was stopped
-	reading       *traceBuf // buffer currently handed off to user
-	empty         *traceBuf // stack of empty buffers
-	fullHead      *traceBuf // queue of full buffers
-	fullTail      *traceBuf
+	lock          mutex       // protects the following members
+	lockOwner     *g          // to avoid deadlocks during recursive lock locks
+	enabled       bool        // when set runtime traces events
+	shutdown      bool        // set when we are waiting for trace reader to finish after setting enabled to false
+	headerWritten bool        // whether ReadTrace has emitted trace header
+	footerWritten bool        // whether ReadTrace has emitted trace footer
+	shutdownSema  uint32      // used to wait for ReadTrace completion
+	seqStart      uint64      // sequence number when tracing was started
+	ticksStart    int64       // cputicks when tracing was started
+	ticksEnd      int64       // cputicks when tracing was stopped
+	timeStart     int64       // nanotime when tracing was started
+	timeEnd       int64       // nanotime when tracing was stopped
+	reading       traceBufPtr // buffer currently handed off to user
+	empty         traceBufPtr // stack of empty buffers
+	fullHead      traceBufPtr // queue of full buffers
+	fullTail      traceBufPtr
 	reader        *g              // goroutine that called ReadTrace, or nil
 	stackTab      traceStackTable // maps stack traces to unique ids
 
-	bufLock mutex     // protects buf
-	buf     *traceBuf // global trace buffer, used when running without a p
+	bufLock mutex       // protects buf
+	buf     traceBufPtr // global trace buffer, used when running without a p
 }
 
 var traceseq uint64 // global trace sequence number
@@ -123,21 +127,21 @@ var traceseq uint64 // global trace sequence number
 // that used to call xadd64 and cputicks are sensitive to that.
 //go:nosplit
 func tracestamp() (seq uint64, ts int64) {
-	seq = atomicload64(&traceseq)
-	for seq&1 != 0 || !cas64(&traceseq, seq, seq+1) {
-		seq = atomicload64(&traceseq)
+	seq = atomic.Load64(&traceseq)
+	for seq&1 != 0 || !atomic.Cas64(&traceseq, seq, seq+1) {
+		seq = atomic.Load64(&traceseq)
 	}
 	ts = cputicks()
-	atomicstore64(&traceseq, seq+2)
+	atomic.Store64(&traceseq, seq+2)
 	return seq >> 1, ts
 }
 
 // traceBufHeader is per-P tracing buffer.
 type traceBufHeader struct {
-	link      *traceBuf               // in trace.empty/full
+	link      traceBufPtr             // in trace.empty/full
 	lastSeq   uint64                  // sequence number of last event
 	lastTicks uint64                  // when we wrote the last event
-	buf       []byte                  // trace data, always points to traceBuf.arr
+	pos       int                     // next write offset in arr
 	stk       [traceStackSize]uintptr // scratch buffer for traceback
 }
 
@@ -147,6 +151,19 @@ type traceBuf struct {
 	arr [64<<10 - unsafe.Sizeof(traceBufHeader{})]byte // underlying buffer for traceBufHeader.buf
 }
 
+// traceBufPtr is a *traceBuf that is not traced by the garbage
+// collector and doesn't have write barriers. traceBufs are not
+// allocated from the GC'd heap, so this is safe, and are often
+// manipulated in contexts where write barriers are not allowed, so
+// this is necessary.
+type traceBufPtr uintptr
+
+func (tp traceBufPtr) ptr() *traceBuf   { return (*traceBuf)(unsafe.Pointer(tp)) }
+func (tp *traceBufPtr) set(b *traceBuf) { *tp = traceBufPtr(unsafe.Pointer(b)) }
+func traceBufPtrOf(b *traceBuf) traceBufPtr {
+	return traceBufPtr(unsafe.Pointer(b))
+}
+
 // StartTrace enables tracing for the current process.
 // While tracing, the data will be buffered and available via ReadTrace.
 // StartTrace returns an error if tracing is already enabled.
@@ -232,14 +249,14 @@ func StopTrace() {
 			break
 		}
 		buf := p.tracebuf
-		if buf != nil {
+		if buf != 0 {
 			traceFullQueue(buf)
-			p.tracebuf = nil
+			p.tracebuf = 0
 		}
 	}
-	if trace.buf != nil && len(trace.buf.buf) != 0 {
+	if trace.buf != 0 && trace.buf.ptr().pos != 0 {
 		buf := trace.buf
-		trace.buf = nil
+		trace.buf = 0
 		traceFullQueue(buf)
 	}
 
@@ -274,23 +291,23 @@ func StopTrace() {
 		if p == nil {
 			break
 		}
-		if p.tracebuf != nil {
+		if p.tracebuf != 0 {
 			throw("trace: non-empty trace buffer in proc")
 		}
 	}
-	if trace.buf != nil {
+	if trace.buf != 0 {
 		throw("trace: non-empty global trace buffer")
 	}
-	if trace.fullHead != nil || trace.fullTail != nil {
+	if trace.fullHead != 0 || trace.fullTail != 0 {
 		throw("trace: non-empty full trace buffer")
 	}
-	if trace.reading != nil || trace.reader != nil {
+	if trace.reading != 0 || trace.reader != nil {
 		throw("trace: reading after shutdown")
 	}
-	for trace.empty != nil {
+	for trace.empty != 0 {
 		buf := trace.empty
-		trace.empty = buf.link
-		sysFree(unsafe.Pointer(buf), unsafe.Sizeof(*buf), &memstats.other_sys)
+		trace.empty = buf.ptr().link
+		sysFree(unsafe.Pointer(buf), unsafe.Sizeof(*buf.ptr()), &memstats.other_sys)
 	}
 	trace.shutdown = false
 	unlock(&trace.lock)
@@ -321,10 +338,10 @@ func ReadTrace() []byte {
 		return nil
 	}
 	// Recycle the old buffer.
-	if buf := trace.reading; buf != nil {
-		buf.link = trace.empty
+	if buf := trace.reading; buf != 0 {
+		buf.ptr().link = trace.empty
 		trace.empty = buf
-		trace.reading = nil
+		trace.reading = 0
 	}
 	// Write trace header.
 	if !trace.headerWritten {
@@ -334,18 +351,18 @@ func ReadTrace() []byte {
 		return []byte("go 1.5 trace\x00\x00\x00\x00")
 	}
 	// Wait for new data.
-	if trace.fullHead == nil && !trace.shutdown {
+	if trace.fullHead == 0 && !trace.shutdown {
 		trace.reader = getg()
 		goparkunlock(&trace.lock, "trace reader (blocked)", traceEvGoBlock, 2)
 		lock(&trace.lock)
 	}
 	// Write a buffer.
-	if trace.fullHead != nil {
+	if trace.fullHead != 0 {
 		buf := traceFullDequeue()
 		trace.reading = buf
 		trace.lockOwner = nil
 		unlock(&trace.lock)
-		return buf.buf
+		return buf.ptr().arr[:buf.ptr().pos]
 	}
 	// Write footer with timer frequency.
 	if !trace.footerWritten {
@@ -388,11 +405,11 @@ func ReadTrace() []byte {
 
 // traceReader returns the trace reader that should be woken up, if any.
 func traceReader() *g {
-	if trace.reader == nil || (trace.fullHead == nil && !trace.shutdown) {
+	if trace.reader == nil || (trace.fullHead == 0 && !trace.shutdown) {
 		return nil
 	}
 	lock(&trace.lock)
-	if trace.reader == nil || (trace.fullHead == nil && !trace.shutdown) {
+	if trace.reader == nil || (trace.fullHead == 0 && !trace.shutdown) {
 		unlock(&trace.lock)
 		return nil
 	}
@@ -405,8 +422,8 @@ func traceReader() *g {
 // traceProcFree frees trace buffer associated with pp.
 func traceProcFree(pp *p) {
 	buf := pp.tracebuf
-	pp.tracebuf = nil
-	if buf == nil {
+	pp.tracebuf = 0
+	if buf == 0 {
 		return
 	}
 	lock(&trace.lock)
@@ -415,27 +432,27 @@ func traceProcFree(pp *p) {
 }
 
 // traceFullQueue queues buf into queue of full buffers.
-func traceFullQueue(buf *traceBuf) {
-	buf.link = nil
-	if trace.fullHead == nil {
+func traceFullQueue(buf traceBufPtr) {
+	buf.ptr().link = 0
+	if trace.fullHead == 0 {
 		trace.fullHead = buf
 	} else {
-		trace.fullTail.link = buf
+		trace.fullTail.ptr().link = buf
 	}
 	trace.fullTail = buf
 }
 
 // traceFullDequeue dequeues from queue of full buffers.
-func traceFullDequeue() *traceBuf {
+func traceFullDequeue() traceBufPtr {
 	buf := trace.fullHead
-	if buf == nil {
-		return nil
+	if buf == 0 {
+		return 0
 	}
-	trace.fullHead = buf.link
-	if trace.fullHead == nil {
-		trace.fullTail = nil
+	trace.fullHead = buf.ptr().link
+	if trace.fullHead == 0 {
+		trace.fullTail = 0
 	}
-	buf.link = nil
+	buf.ptr().link = 0
 	return buf
 }
 
@@ -459,24 +476,22 @@ func traceEvent(ev byte, skip int, args ...uint64) {
 		traceReleaseBuffer(pid)
 		return
 	}
-	buf := *bufp
+	buf := (*bufp).ptr()
 	const maxSize = 2 + 5*traceBytesPerNumber // event type, length, sequence, timestamp, stack id and two add params
-	if buf == nil || cap(buf.buf)-len(buf.buf) < maxSize {
-		buf = traceFlush(buf)
-		*bufp = buf
+	if buf == nil || len(buf.arr)-buf.pos < maxSize {
+		buf = traceFlush(traceBufPtrOf(buf)).ptr()
+		(*bufp).set(buf)
 	}
 
 	seq, ticksraw := tracestamp()
 	seqDiff := seq - buf.lastSeq
 	ticks := uint64(ticksraw) / traceTickDiv
 	tickDiff := ticks - buf.lastTicks
-	if len(buf.buf) == 0 {
-		data := buf.buf
-		data = append(data, traceEvBatch|1<<traceArgCountShift)
-		data = traceAppend(data, uint64(pid))
-		data = traceAppend(data, seq)
-		data = traceAppend(data, ticks)
-		buf.buf = data
+	if buf.pos == 0 {
+		buf.byte(traceEvBatch | 1<<traceArgCountShift)
+		buf.varint(uint64(pid))
+		buf.varint(seq)
+		buf.varint(ticks)
 		seqDiff = 0
 		tickDiff = 0
 	}
@@ -491,21 +506,21 @@ func traceEvent(ev byte, skip int, args ...uint64) {
 	if narg > 3 {
 		narg = 3
 	}
-	data := buf.buf
-	data = append(data, ev|narg<<traceArgCountShift)
+	startPos := buf.pos
+	buf.byte(ev | narg<<traceArgCountShift)
 	var lenp *byte
 	if narg == 3 {
 		// Reserve the byte for length assuming that length < 128.
-		data = append(data, 0)
-		lenp = &data[len(data)-1]
+		buf.varint(0)
+		lenp = &buf.arr[buf.pos-1]
 	}
-	data = traceAppend(data, seqDiff)
-	data = traceAppend(data, tickDiff)
+	buf.varint(seqDiff)
+	buf.varint(tickDiff)
 	for _, a := range args {
-		data = traceAppend(data, a)
+		buf.varint(a)
 	}
 	if skip == 0 {
-		data = append(data, 0)
+		buf.varint(0)
 	} else if skip > 0 {
 		_g_ := getg()
 		gp := mp.curg
@@ -514,7 +529,12 @@ func traceEvent(ev byte, skip int, args ...uint64) {
 			nstk = callers(skip, buf.stk[:])
 		} else if gp != nil {
 			gp = mp.curg
-			nstk = gcallers(gp, skip, buf.stk[:])
+			// This may happen when tracing a system call,
+			// so we must lock the stack.
+			if gcTryLockStackBarriers(gp) {
+				nstk = gcallers(gp, skip, buf.stk[:])
+				gcUnlockStackBarriers(gp)
+			}
 		}
 		if nstk > 0 {
 			nstk-- // skip runtime.goexit
@@ -523,9 +543,9 @@ func traceEvent(ev byte, skip int, args ...uint64) {
 			nstk-- // skip runtime.main
 		}
 		id := trace.stackTab.put(buf.stk[:nstk])
-		data = traceAppend(data, uint64(id))
+		buf.varint(uint64(id))
 	}
-	evSize := len(data) - len(buf.buf)
+	evSize := buf.pos - startPos
 	if evSize > maxSize {
 		throw("invalid length of trace event")
 	}
@@ -533,12 +553,11 @@ func traceEvent(ev byte, skip int, args ...uint64) {
 		// Fill in actual length.
 		*lenp = byte(evSize - 2)
 	}
-	buf.buf = data
 	traceReleaseBuffer(pid)
 }
 
 // traceAcquireBuffer returns trace buffer to use and, if necessary, locks it.
-func traceAcquireBuffer() (mp *m, pid int32, bufp **traceBuf) {
+func traceAcquireBuffer() (mp *m, pid int32, bufp *traceBufPtr) {
 	mp = acquirem()
 	if p := mp.p.ptr(); p != nil {
 		return mp, p.id, &p.tracebuf
@@ -556,30 +575,28 @@ func traceReleaseBuffer(pid int32) {
 }
 
 // traceFlush puts buf onto stack of full buffers and returns an empty buffer.
-func traceFlush(buf *traceBuf) *traceBuf {
+func traceFlush(buf traceBufPtr) traceBufPtr {
 	owner := trace.lockOwner
 	dolock := owner == nil || owner != getg().m.curg
 	if dolock {
 		lock(&trace.lock)
 	}
-	if buf != nil {
-		if &buf.buf[0] != &buf.arr[0] {
-			throw("trace buffer overflow")
-		}
+	if buf != 0 {
 		traceFullQueue(buf)
 	}
-	if trace.empty != nil {
+	if trace.empty != 0 {
 		buf = trace.empty
-		trace.empty = buf.link
+		trace.empty = buf.ptr().link
 	} else {
-		buf = (*traceBuf)(sysAlloc(unsafe.Sizeof(traceBuf{}), &memstats.other_sys))
-		if buf == nil {
+		buf = traceBufPtr(sysAlloc(unsafe.Sizeof(traceBuf{}), &memstats.other_sys))
+		if buf == 0 {
 			throw("trace: out of memory")
 		}
 	}
-	buf.link = nil
-	buf.buf = buf.arr[:0]
-	buf.lastTicks = 0
+	bufp := buf.ptr()
+	bufp.link.set(nil)
+	bufp.pos = 0
+	bufp.lastTicks = 0
 	if dolock {
 		unlock(&trace.lock)
 	}
@@ -595,24 +612,46 @@ func traceAppend(buf []byte, v uint64) []byte {
 	return buf
 }
 
+// varint appends v to buf in little-endian-base-128 encoding.
+func (buf *traceBuf) varint(v uint64) {
+	pos := buf.pos
+	for ; v >= 0x80; v >>= 7 {
+		buf.arr[pos] = 0x80 | byte(v)
+		pos++
+	}
+	buf.arr[pos] = byte(v)
+	pos++
+	buf.pos = pos
+}
+
+// byte appends v to buf.
+func (buf *traceBuf) byte(v byte) {
+	buf.arr[buf.pos] = v
+	buf.pos++
+}
+
 // traceStackTable maps stack traces (arrays of PC's) to unique uint32 ids.
 // It is lock-free for reading.
 type traceStackTable struct {
 	lock mutex
 	seq  uint32
 	mem  traceAlloc
-	tab  [1 << 13]*traceStack
+	tab  [1 << 13]traceStackPtr
 }
 
 // traceStack is a single stack in traceStackTable.
 type traceStack struct {
-	link *traceStack
+	link traceStackPtr
 	hash uintptr
 	id   uint32
 	n    int
 	stk  [0]uintptr // real type [n]uintptr
 }
 
+type traceStackPtr uintptr
+
+func (tp traceStackPtr) ptr() *traceStack { return (*traceStack)(unsafe.Pointer(tp)) }
+
 // stack returns slice of PCs.
 func (ts *traceStack) stack() []uintptr {
 	return (*[traceStackSize]uintptr)(unsafe.Pointer(&ts.stk))[:ts.n]
@@ -624,7 +663,7 @@ func (tab *traceStackTable) put(pcs []uintptr) uint32 {
 	if len(pcs) == 0 {
 		return 0
 	}
-	hash := memhash(unsafe.Pointer(&pcs[0]), uintptr(len(pcs))*unsafe.Sizeof(pcs[0]), 0)
+	hash := memhash(unsafe.Pointer(&pcs[0]), 0, uintptr(len(pcs))*unsafe.Sizeof(pcs[0]))
 	// First, search the hashtable w/o the mutex.
 	if id := tab.find(pcs, hash); id != 0 {
 		return id
@@ -656,7 +695,7 @@ func (tab *traceStackTable) put(pcs []uintptr) uint32 {
 func (tab *traceStackTable) find(pcs []uintptr, hash uintptr) uint32 {
 	part := int(hash % uintptr(len(tab.tab)))
 Search:
-	for stk := tab.tab[part]; stk != nil; stk = stk.link {
+	for stk := tab.tab[part].ptr(); stk != nil; stk = stk.link.ptr() {
 		if stk.hash == hash && stk.n == len(pcs) {
 			for i, stkpc := range stk.stack() {
 				if stkpc != pcs[i] {
@@ -671,19 +710,20 @@ Search:
 
 // newStack allocates a new stack of size n.
 func (tab *traceStackTable) newStack(n int) *traceStack {
-	return (*traceStack)(tab.mem.alloc(unsafe.Sizeof(traceStack{}) + uintptr(n)*ptrSize))
+	return (*traceStack)(tab.mem.alloc(unsafe.Sizeof(traceStack{}) + uintptr(n)*sys.PtrSize))
 }
 
 // dump writes all previously cached stacks to trace buffers,
 // releases all memory and resets state.
 func (tab *traceStackTable) dump() {
 	var tmp [(2 + traceStackSize) * traceBytesPerNumber]byte
-	buf := traceFlush(nil)
+	buf := traceFlush(0).ptr()
 	for _, stk := range tab.tab {
-		for ; stk != nil; stk = stk.link {
+		stk := stk.ptr()
+		for ; stk != nil; stk = stk.link.ptr() {
 			maxSize := 1 + (3+stk.n)*traceBytesPerNumber
-			if cap(buf.buf)-len(buf.buf) < maxSize {
-				buf = traceFlush(buf)
+			if len(buf.arr)-buf.pos < maxSize {
+				buf = traceFlush(traceBufPtrOf(buf)).ptr()
 			}
 			// Form the event in the temp buffer, we need to know the actual length.
 			tmpbuf := tmp[:0]
@@ -693,16 +733,14 @@ func (tab *traceStackTable) dump() {
 				tmpbuf = traceAppend(tmpbuf, uint64(pc))
 			}
 			// Now copy to the buffer.
-			data := buf.buf
-			data = append(data, traceEvStack|3<<traceArgCountShift)
-			data = traceAppend(data, uint64(len(tmpbuf)))
-			data = append(data, tmpbuf...)
-			buf.buf = data
+			buf.byte(traceEvStack | 3<<traceArgCountShift)
+			buf.varint(uint64(len(tmpbuf)))
+			buf.pos += copy(buf.arr[buf.pos:], tmpbuf)
 		}
 	}
 
 	lock(&trace.lock)
-	traceFullQueue(buf)
+	traceFullQueue(traceBufPtrOf(buf))
 	unlock(&trace.lock)
 
 	tab.mem.drop()
@@ -712,41 +750,50 @@ func (tab *traceStackTable) dump() {
 // traceAlloc is a non-thread-safe region allocator.
 // It holds a linked list of traceAllocBlock.
 type traceAlloc struct {
-	head *traceAllocBlock
+	head traceAllocBlockPtr
 	off  uintptr
 }
 
 // traceAllocBlock is a block in traceAlloc.
+//
+// traceAllocBlock is allocated from non-GC'd memory, so it must not
+// contain heap pointers. Writes to pointers to traceAllocBlocks do
+// not need write barriers.
 type traceAllocBlock struct {
-	next *traceAllocBlock
-	data [64<<10 - ptrSize]byte
+	next traceAllocBlockPtr
+	data [64<<10 - sys.PtrSize]byte
 }
 
+type traceAllocBlockPtr uintptr
+
+func (p traceAllocBlockPtr) ptr() *traceAllocBlock   { return (*traceAllocBlock)(unsafe.Pointer(p)) }
+func (p *traceAllocBlockPtr) set(x *traceAllocBlock) { *p = traceAllocBlockPtr(unsafe.Pointer(x)) }
+
 // alloc allocates n-byte block.
 func (a *traceAlloc) alloc(n uintptr) unsafe.Pointer {
-	n = round(n, ptrSize)
-	if a.head == nil || a.off+n > uintptr(len(a.head.data)) {
-		if n > uintptr(len(a.head.data)) {
+	n = round(n, sys.PtrSize)
+	if a.head == 0 || a.off+n > uintptr(len(a.head.ptr().data)) {
+		if n > uintptr(len(a.head.ptr().data)) {
 			throw("trace: alloc too large")
 		}
 		block := (*traceAllocBlock)(sysAlloc(unsafe.Sizeof(traceAllocBlock{}), &memstats.other_sys))
 		if block == nil {
 			throw("trace: out of memory")
 		}
-		block.next = a.head
-		a.head = block
+		block.next.set(a.head.ptr())
+		a.head.set(block)
 		a.off = 0
 	}
-	p := &a.head.data[a.off]
+	p := &a.head.ptr().data[a.off]
 	a.off += n
 	return unsafe.Pointer(p)
 }
 
 // drop frees all previously allocated memory and resets the allocator.
 func (a *traceAlloc) drop() {
-	for a.head != nil {
-		block := a.head
-		a.head = block.next
+	for a.head != 0 {
+		block := a.head.ptr()
+		a.head.set(block.next.ptr())
 		sysFree(unsafe.Pointer(block), unsafe.Sizeof(traceAllocBlock{}), &memstats.other_sys)
 	}
 }
@@ -773,7 +820,7 @@ func traceProcStop(pp *p) {
 }
 
 func traceGCStart() {
-	traceEvent(traceEvGCStart, 4)
+	traceEvent(traceEvGCStart, 3)
 }
 
 func traceGCDone() {
@@ -828,7 +875,7 @@ func traceGoUnpark(gp *g, skip int) {
 }
 
 func traceGoSysCall() {
-	traceEvent(traceEvGoSysCall, 4)
+	traceEvent(traceEvGoSysCall, 1)
 }
 
 func traceGoSysExit(seq uint64, ts int64) {
diff --git a/src/runtime/trace/trace_stack_test.go b/src/runtime/trace/trace_stack_test.go
index 3fe1747..b5fe7c3 100644
--- a/src/runtime/trace/trace_stack_test.go
+++ b/src/runtime/trace/trace_stack_test.go
@@ -144,107 +144,107 @@ func TestTraceSymbolize(t *testing.T) {
 		Stk  []frame
 	}
 	want := []eventDesc{
-		eventDesc{trace.EvGCStart, []frame{
-			frame{"runtime.GC", 0},
-			frame{"runtime/trace_test.TestTraceSymbolize", 106},
-			frame{"testing.tRunner", 0},
+		{trace.EvGCStart, []frame{
+			{"runtime.GC", 0},
+			{"runtime/trace_test.TestTraceSymbolize", 106},
+			{"testing.tRunner", 0},
 		}},
-		eventDesc{trace.EvGoSched, []frame{
-			frame{"runtime/trace_test.TestTraceSymbolize", 107},
-			frame{"testing.tRunner", 0},
+		{trace.EvGoSched, []frame{
+			{"runtime/trace_test.TestTraceSymbolize", 107},
+			{"testing.tRunner", 0},
 		}},
-		eventDesc{trace.EvGoCreate, []frame{
-			frame{"runtime/trace_test.TestTraceSymbolize", 39},
-			frame{"testing.tRunner", 0},
+		{trace.EvGoCreate, []frame{
+			{"runtime/trace_test.TestTraceSymbolize", 39},
+			{"testing.tRunner", 0},
 		}},
-		eventDesc{trace.EvGoStop, []frame{
-			frame{"runtime.block", 0},
-			frame{"runtime/trace_test.TestTraceSymbolize.func1", 38},
+		{trace.EvGoStop, []frame{
+			{"runtime.block", 0},
+			{"runtime/trace_test.TestTraceSymbolize.func1", 38},
 		}},
-		eventDesc{trace.EvGoStop, []frame{
-			frame{"runtime.chansend1", 0},
-			frame{"runtime/trace_test.TestTraceSymbolize.func2", 42},
+		{trace.EvGoStop, []frame{
+			{"runtime.chansend1", 0},
+			{"runtime/trace_test.TestTraceSymbolize.func2", 42},
 		}},
-		eventDesc{trace.EvGoStop, []frame{
-			frame{"runtime.chanrecv1", 0},
-			frame{"runtime/trace_test.TestTraceSymbolize.func3", 46},
+		{trace.EvGoStop, []frame{
+			{"runtime.chanrecv1", 0},
+			{"runtime/trace_test.TestTraceSymbolize.func3", 46},
 		}},
-		eventDesc{trace.EvGoBlockRecv, []frame{
-			frame{"runtime.chanrecv1", 0},
-			frame{"runtime/trace_test.TestTraceSymbolize.func4", 50},
+		{trace.EvGoBlockRecv, []frame{
+			{"runtime.chanrecv1", 0},
+			{"runtime/trace_test.TestTraceSymbolize.func4", 50},
 		}},
-		eventDesc{trace.EvGoUnblock, []frame{
-			frame{"runtime.chansend1", 0},
-			frame{"runtime/trace_test.TestTraceSymbolize", 109},
-			frame{"testing.tRunner", 0},
+		{trace.EvGoUnblock, []frame{
+			{"runtime.chansend1", 0},
+			{"runtime/trace_test.TestTraceSymbolize", 109},
+			{"testing.tRunner", 0},
 		}},
-		eventDesc{trace.EvGoBlockSend, []frame{
-			frame{"runtime.chansend1", 0},
-			frame{"runtime/trace_test.TestTraceSymbolize.func5", 54},
+		{trace.EvGoBlockSend, []frame{
+			{"runtime.chansend1", 0},
+			{"runtime/trace_test.TestTraceSymbolize.func5", 54},
 		}},
-		eventDesc{trace.EvGoUnblock, []frame{
-			frame{"runtime.chanrecv1", 0},
-			frame{"runtime/trace_test.TestTraceSymbolize", 110},
-			frame{"testing.tRunner", 0},
+		{trace.EvGoUnblock, []frame{
+			{"runtime.chanrecv1", 0},
+			{"runtime/trace_test.TestTraceSymbolize", 110},
+			{"testing.tRunner", 0},
 		}},
-		eventDesc{trace.EvGoBlockSelect, []frame{
-			frame{"runtime.selectgo", 0},
-			frame{"runtime/trace_test.TestTraceSymbolize.func6", 59},
+		{trace.EvGoBlockSelect, []frame{
+			{"runtime.selectgo", 0},
+			{"runtime/trace_test.TestTraceSymbolize.func6", 59},
 		}},
-		eventDesc{trace.EvGoUnblock, []frame{
-			frame{"runtime.selectgo", 0},
-			frame{"runtime/trace_test.TestTraceSymbolize", 111},
-			frame{"testing.tRunner", 0},
+		{trace.EvGoUnblock, []frame{
+			{"runtime.selectgo", 0},
+			{"runtime/trace_test.TestTraceSymbolize", 111},
+			{"testing.tRunner", 0},
 		}},
-		eventDesc{trace.EvGoBlockSync, []frame{
-			frame{"sync.(*Mutex).Lock", 0},
-			frame{"runtime/trace_test.TestTraceSymbolize.func7", 67},
+		{trace.EvGoBlockSync, []frame{
+			{"sync.(*Mutex).Lock", 0},
+			{"runtime/trace_test.TestTraceSymbolize.func7", 67},
 		}},
-		eventDesc{trace.EvGoUnblock, []frame{
-			frame{"sync.(*Mutex).Unlock", 0},
-			frame{"runtime/trace_test.TestTraceSymbolize", 115},
-			frame{"testing.tRunner", 0},
+		{trace.EvGoUnblock, []frame{
+			{"sync.(*Mutex).Unlock", 0},
+			{"runtime/trace_test.TestTraceSymbolize", 115},
+			{"testing.tRunner", 0},
 		}},
-		eventDesc{trace.EvGoBlockSync, []frame{
-			frame{"sync.(*WaitGroup).Wait", 0},
-			frame{"runtime/trace_test.TestTraceSymbolize.func8", 73},
+		{trace.EvGoBlockSync, []frame{
+			{"sync.(*WaitGroup).Wait", 0},
+			{"runtime/trace_test.TestTraceSymbolize.func8", 73},
 		}},
-		eventDesc{trace.EvGoUnblock, []frame{
-			frame{"sync.(*WaitGroup).Add", 0},
-			frame{"sync.(*WaitGroup).Done", 0},
-			frame{"runtime/trace_test.TestTraceSymbolize", 116},
-			frame{"testing.tRunner", 0},
+		{trace.EvGoUnblock, []frame{
+			{"sync.(*WaitGroup).Add", 0},
+			{"sync.(*WaitGroup).Done", 0},
+			{"runtime/trace_test.TestTraceSymbolize", 116},
+			{"testing.tRunner", 0},
 		}},
-		eventDesc{trace.EvGoBlockCond, []frame{
-			frame{"sync.(*Cond).Wait", 0},
-			frame{"runtime/trace_test.TestTraceSymbolize.func9", 78},
+		{trace.EvGoBlockCond, []frame{
+			{"sync.(*Cond).Wait", 0},
+			{"runtime/trace_test.TestTraceSymbolize.func9", 78},
 		}},
-		eventDesc{trace.EvGoUnblock, []frame{
-			frame{"sync.(*Cond).Signal", 0},
-			frame{"runtime/trace_test.TestTraceSymbolize", 117},
-			frame{"testing.tRunner", 0},
+		{trace.EvGoUnblock, []frame{
+			{"sync.(*Cond).Signal", 0},
+			{"runtime/trace_test.TestTraceSymbolize", 117},
+			{"testing.tRunner", 0},
 		}},
-		eventDesc{trace.EvGoSleep, []frame{
-			frame{"time.Sleep", 0},
-			frame{"runtime/trace_test.TestTraceSymbolize", 108},
-			frame{"testing.tRunner", 0},
+		{trace.EvGoSleep, []frame{
+			{"time.Sleep", 0},
+			{"runtime/trace_test.TestTraceSymbolize", 108},
+			{"testing.tRunner", 0},
 		}},
 	}
 	// Stacks for the following events are OS-dependent due to OS-specific code in net package.
 	if runtime.GOOS != "windows" && runtime.GOOS != "plan9" {
 		want = append(want, []eventDesc{
-			eventDesc{trace.EvGoBlockNet, []frame{
-				frame{"net.(*netFD).accept", 0},
-				frame{"net.(*TCPListener).AcceptTCP", 0},
-				frame{"net.(*TCPListener).Accept", 0},
-				frame{"runtime/trace_test.TestTraceSymbolize.func10", 86},
+			{trace.EvGoBlockNet, []frame{
+				{"net.(*netFD).accept", 0},
+				{"net.(*TCPListener).AcceptTCP", 0},
+				{"net.(*TCPListener).Accept", 0},
+				{"runtime/trace_test.TestTraceSymbolize.func10", 86},
 			}},
-			eventDesc{trace.EvGoSysCall, []frame{
-				frame{"syscall.read", 0},
-				frame{"syscall.Read", 0},
-				frame{"os.(*File).read", 0},
-				frame{"os.(*File).Read", 0},
-				frame{"runtime/trace_test.TestTraceSymbolize.func11", 101},
+			{trace.EvGoSysCall, []frame{
+				{"syscall.read", 0},
+				{"syscall.Read", 0},
+				{"os.(*File).read", 0},
+				{"os.(*File).Read", 0},
+				{"runtime/trace_test.TestTraceSymbolize.func11", 101},
 			}},
 		}...)
 	}
diff --git a/src/runtime/trace/trace_test.go b/src/runtime/trace/trace_test.go
index 0a8957f..f4791c2 100644
--- a/src/runtime/trace/trace_test.go
+++ b/src/runtime/trace/trace_test.go
@@ -129,7 +129,13 @@ func TestTraceStress(t *testing.T) {
 
 	runtime.GC()
 	// Trigger GC from malloc.
-	for i := 0; i < 1e3; i++ {
+	n := int(1e3)
+	if runtime.GOOS == "openbsd" && runtime.GOARCH == "arm" {
+		// Reduce allocation to avoid running out of
+		// memory on the builder - see issue/12032.
+		n = 512
+	}
+	for i := 0; i < n; i++ {
 		_ = make([]byte, 1<<20)
 	}
 
@@ -260,7 +266,13 @@ func TestTraceStressStartStop(t *testing.T) {
 
 		runtime.GC()
 		// Trigger GC from malloc.
-		for i := 0; i < 1e3; i++ {
+		n := int(1e3)
+		if runtime.GOOS == "openbsd" && runtime.GOARCH == "arm" {
+			// Reduce allocation to avoid running out of
+			// memory on the builder - see issue/12032.
+			n = 512
+		}
+		for i := 0; i < n; i++ {
 			_ = make([]byte, 1<<20)
 		}
 
diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go
index fa13713..b4bfe71 100644
--- a/src/runtime/traceback.go
+++ b/src/runtime/traceback.go
@@ -4,7 +4,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 // The code in this file implements stack trace walking for all architectures.
 // The most important fact about a given architecture is whether it uses a link register.
@@ -26,9 +29,10 @@ import "unsafe"
 // stores an 8-byte return PC onto the stack. To accommodate this, we use regSize
 // as the size of the architecture-pushed return PC.
 //
-// usesLR is defined below. ptrSize and regSize are defined in stubs.go.
+// usesLR is defined below in terms of minFrameSize, which is defined in
+// arch_$GOARCH.go. ptrSize and regSize are defined in stubs.go.
 
-const usesLR = GOARCH != "amd64" && GOARCH != "amd64p32" && GOARCH != "386"
+const usesLR = sys.MinFrameSize > 0
 
 var (
 	// initialized in tracebackinit
@@ -40,7 +44,6 @@ var (
 	rt0_goPC             uintptr
 	sigpanicPC           uintptr
 	runfinqPC            uintptr
-	backgroundgcPC       uintptr
 	bgsweepPC            uintptr
 	forcegchelperPC      uintptr
 	timerprocPC          uintptr
@@ -68,7 +71,6 @@ func tracebackinit() {
 	rt0_goPC = funcPC(rt0_go)
 	sigpanicPC = funcPC(sigpanic)
 	runfinqPC = funcPC(runfinq)
-	backgroundgcPC = funcPC(backgroundgc)
 	bgsweepPC = funcPC(bgsweep)
 	forcegchelperPC = funcPC(forcegchelper)
 	timerprocPC = funcPC(timerproc)
@@ -104,7 +106,7 @@ func tracebackdefers(gp *g, callback func(*stkframe, unsafe.Pointer) bool, v uns
 			}
 			frame.fn = f
 			frame.argp = uintptr(deferArgs(d))
-			setArgInfo(&frame, f, true)
+			frame.arglen, frame.argmap = getArgInfo(&frame, f, true)
 		}
 		frame.continpc = frame.pc
 		if !callback((*stkframe)(noescape(unsafe.Pointer(&frame))), v) {
@@ -138,7 +140,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
 		// instead on the g0 stack.
 		throw("gentraceback cannot trace user goroutine on its own stack")
 	}
-	gotraceback := gotraceback(nil)
+	level, _, _ := gotraceback()
 
 	// Fix up returns to the stack barrier by fetching the
 	// original return PC from gp.stkbar.
@@ -183,8 +185,8 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
 			frame.pc = *(*uintptr)(unsafe.Pointer(frame.sp))
 			frame.lr = 0
 		} else {
-			frame.pc = uintptr(*(*uintreg)(unsafe.Pointer(frame.sp)))
-			frame.sp += regSize
+			frame.pc = uintptr(*(*sys.Uintreg)(unsafe.Pointer(frame.sp)))
+			frame.sp += sys.RegSize
 		}
 	}
 
@@ -226,6 +228,8 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
 	}
 	frame.fn = f
 
+	var cache pcvalueCache
+
 	n := 0
 	for n < max {
 		// Typically:
@@ -248,10 +252,10 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
 				stkbarG = gp.m.curg
 				stkbar = stkbarG.stkbar[stkbarG.stkbarPos:]
 			}
-			frame.fp = sp + uintptr(funcspdelta(f, frame.pc))
+			frame.fp = sp + uintptr(funcspdelta(f, frame.pc, &cache))
 			if !usesLR {
 				// On x86, call instruction pushes return PC before entering new function.
-				frame.fp += regSize
+				frame.fp += sys.RegSize
 			}
 		}
 		var flr *_func
@@ -278,8 +282,8 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
 				}
 			} else {
 				if frame.lr == 0 {
-					lrPtr = frame.fp - regSize
-					frame.lr = uintptr(*(*uintreg)(unsafe.Pointer(lrPtr)))
+					lrPtr = frame.fp - sys.RegSize
+					frame.lr = uintptr(*(*sys.Uintreg)(unsafe.Pointer(lrPtr)))
 				}
 			}
 			if frame.lr == stackBarrierPC {
@@ -309,13 +313,13 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
 		frame.varp = frame.fp
 		if !usesLR {
 			// On x86, call instruction pushes return PC before entering new function.
-			frame.varp -= regSize
+			frame.varp -= sys.RegSize
 		}
 
 		// If framepointer_enabled and there's a frame, then
 		// there's a saved bp here.
 		if framepointer_enabled && GOARCH == "amd64" && frame.varp > frame.sp {
-			frame.varp -= regSize
+			frame.varp -= sys.RegSize
 		}
 
 		// Derive size of arguments.
@@ -325,11 +329,8 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
 		// in package runtime and reflect, and for those we use call-specific
 		// metadata recorded by f's caller.
 		if callback != nil || printing {
-			frame.argp = frame.fp
-			if usesLR {
-				frame.argp += ptrSize
-			}
-			setArgInfo(&frame, f, callback != nil)
+			frame.argp = frame.fp + sys.MinFrameSize
+			frame.arglen, frame.argmap = getArgInfo(&frame, f, callback != nil)
 		}
 
 		// Determine frame's 'continuation PC', where it can continue.
@@ -379,9 +380,13 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
 				if (n > 0 || flags&_TraceTrap == 0) && frame.pc > f.entry && !waspanic {
 					tracepc--
 				}
-				print(funcname(f), "(")
+				name := funcname(f)
+				if name == "runtime.gopanic" {
+					name = "panic"
+				}
+				print(name, "(")
 				argp := (*[100]uintptr)(unsafe.Pointer(frame.argp))
-				for i := uintptr(0); i < frame.arglen/ptrSize; i++ {
+				for i := uintptr(0); i < frame.arglen/sys.PtrSize; i++ {
 					if i >= 10 {
 						print(", ...")
 						break
@@ -397,7 +402,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
 				if frame.pc > f.entry {
 					print(" +", hex(frame.pc-f.entry))
 				}
-				if g.m.throwing > 0 && gp == g.m.curg || gotraceback >= 2 {
+				if g.m.throwing > 0 && gp == g.m.curg || level >= 2 {
 					print(" fp=", hex(frame.fp), " sp=", hex(frame.sp))
 				}
 				print("\n")
@@ -426,16 +431,16 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
 		// before faking a call to sigpanic.
 		if usesLR && waspanic {
 			x := *(*uintptr)(unsafe.Pointer(frame.sp))
-			frame.sp += ptrSize
+			frame.sp += sys.MinFrameSize
 			if GOARCH == "arm64" {
 				// arm64 needs 16-byte aligned SP, always
-				frame.sp += ptrSize
+				frame.sp += sys.PtrSize
 			}
 			f = findfunc(frame.pc)
 			frame.fn = f
 			if f == nil {
 				frame.pc = x
-			} else if funcspdelta(f, frame.pc) == 0 {
+			} else if funcspdelta(f, frame.pc, &cache) == 0 {
 				frame.lr = x
 			}
 		}
@@ -511,29 +516,33 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
 		throw("traceback has leftover stack barriers")
 	}
 
+	if callback != nil && n < max && frame.sp != gp.stktopsp {
+		print("runtime: g", gp.goid, ": frame.sp=", hex(frame.sp), " top=", hex(gp.stktopsp), "\n")
+		print("\tstack=[", hex(gp.stack.lo), "-", hex(gp.stack.hi), "] n=", n, " max=", max, "\n")
+		throw("traceback did not unwind completely")
+	}
+
 	return n
 }
 
-func setArgInfo(frame *stkframe, f *_func, needArgMap bool) {
-	frame.arglen = uintptr(f.args)
+func getArgInfo(frame *stkframe, f *_func, needArgMap bool) (arglen uintptr, argmap *bitvector) {
+	arglen = uintptr(f.args)
 	if needArgMap && f.args == _ArgsSizeUnknown {
 		// Extract argument bitmaps for reflect stubs from the calls they made to reflect.
 		switch funcname(f) {
 		case "reflect.makeFuncStub", "reflect.methodValueCall":
-			arg0 := frame.sp
-			if usesLR {
-				arg0 += ptrSize
-			}
+			arg0 := frame.sp + sys.MinFrameSize
 			fn := *(**[2]uintptr)(unsafe.Pointer(arg0))
 			if fn[0] != f.entry {
 				print("runtime: confused by ", funcname(f), "\n")
 				throw("reflect mismatch")
 			}
 			bv := (*bitvector)(unsafe.Pointer(fn[1]))
-			frame.arglen = uintptr(bv.n * ptrSize)
-			frame.argmap = bv
+			arglen = uintptr(bv.n * sys.PtrSize)
+			argmap = bv
 		}
 	}
+	return
 }
 
 func printcreatedby(gp *g) {
@@ -544,7 +553,7 @@ func printcreatedby(gp *g) {
 		print("created by ", funcname(f), "\n")
 		tracepc := pc // back up to CALL instruction for funcline.
 		if pc > f.entry {
-			tracepc -= _PCQuantum
+			tracepc -= sys.PCQuantum
 		}
 		file, line := funcline(f, tracepc)
 		print("\t", file, ":", line)
@@ -609,17 +618,17 @@ func showframe(f *_func, gp *g) bool {
 	if g.m.throwing > 0 && gp != nil && (gp == g.m.curg || gp == g.m.caughtsig.ptr()) {
 		return true
 	}
-	traceback := gotraceback(nil)
+	level, _, _ := gotraceback()
 	name := funcname(f)
 
-	// Special case: always show runtime.panic frame, so that we can
+	// Special case: always show runtime.gopanic frame, so that we can
 	// see where a panic started in the middle of a stack trace.
 	// See golang.org/issue/5832.
-	if name == "runtime.panic" {
+	if name == "runtime.gopanic" {
 		return true
 	}
 
-	return traceback > 1 || f != nil && contains(name, ".") && (!hasprefix(name, "runtime.") || isExportedRuntime(name))
+	return level > 1 || f != nil && contains(name, ".") && (!hasprefix(name, "runtime.") || isExportedRuntime(name))
 }
 
 // isExportedRuntime reports whether name is an exported runtime function.
@@ -640,41 +649,34 @@ var gStatusStrings = [...]string{
 	_Gcopystack: "copystack",
 }
 
-var gScanStatusStrings = [...]string{
-	0:          "scan",
-	_Grunnable: "scanrunnable",
-	_Grunning:  "scanrunning",
-	_Gsyscall:  "scansyscall",
-	_Gwaiting:  "scanwaiting",
-	_Gdead:     "scandead",
-	_Genqueue:  "scanenqueue",
-}
-
 func goroutineheader(gp *g) {
 	gpstatus := readgstatus(gp)
 
+	isScan := gpstatus&_Gscan != 0
+	gpstatus &^= _Gscan // drop the scan bit
+
 	// Basic string status
 	var status string
 	if 0 <= gpstatus && gpstatus < uint32(len(gStatusStrings)) {
 		status = gStatusStrings[gpstatus]
-	} else if gpstatus&_Gscan != 0 && 0 <= gpstatus&^_Gscan && gpstatus&^_Gscan < uint32(len(gStatusStrings)) {
-		status = gStatusStrings[gpstatus&^_Gscan]
 	} else {
 		status = "???"
 	}
 
 	// Override.
-	if (gpstatus == _Gwaiting || gpstatus == _Gscanwaiting) && gp.waitreason != "" {
+	if gpstatus == _Gwaiting && gp.waitreason != "" {
 		status = gp.waitreason
 	}
 
 	// approx time the G is blocked, in minutes
 	var waitfor int64
-	gpstatus &^= _Gscan // drop the scan bit
 	if (gpstatus == _Gwaiting || gpstatus == _Gsyscall) && gp.waitsince != 0 {
 		waitfor = (nanotime() - gp.waitsince) / 60e9
 	}
 	print("goroutine ", gp.goid, " [", status)
+	if isScan {
+		print(" (scan)")
+	}
 	if waitfor >= 1 {
 		print(", ", waitfor, " minutes")
 	}
@@ -685,7 +687,7 @@ func goroutineheader(gp *g) {
 }
 
 func tracebackothers(me *g) {
-	level := gotraceback(nil)
+	level, _, _ := gotraceback()
 
 	// Show the current goroutine first, if we haven't already.
 	g := getg()
@@ -733,7 +735,6 @@ func topofstack(f *_func) bool {
 func isSystemGoroutine(gp *g) bool {
 	pc := gp.startpc
 	return pc == runfinqPC && !fingRunning ||
-		pc == backgroundgcPC ||
 		pc == bgsweepPC ||
 		pc == forcegchelperPC ||
 		pc == timerprocPC ||
diff --git a/src/runtime/type.go b/src/runtime/type.go
index 45bdac8..d5f3bb1 100644
--- a/src/runtime/type.go
+++ b/src/runtime/type.go
@@ -8,8 +8,8 @@ package runtime
 
 import "unsafe"
 
-// Needs to be in sync with ../cmd/internal/ld/decodesym.go:/^func.commonsize,
-// ../cmd/internal/gc/reflect.go:/^func.dcommontype and
+// Needs to be in sync with ../cmd/compile/internal/ld/decodesym.go:/^func.commonsize,
+// ../cmd/compile/internal/gc/reflect.go:/^func.dcommontype and
 // ../reflect/type.go:/^type.rtype.
 type _type struct {
 	size       uintptr
@@ -27,7 +27,6 @@ type _type struct {
 	_string *string
 	x       *uncommontype
 	ptrto   *_type
-	zero    *byte // ptr to the zero value for this type
 }
 
 type method struct {
@@ -68,6 +67,14 @@ type maptype struct {
 	indirectvalue bool   // store ptr to value instead of value itself
 	bucketsize    uint16 // size of bucket
 	reflexivekey  bool   // true if k==k for all keys
+	needkeyupdate bool   // true if we need to update key on an overwrite
+}
+
+type arraytype struct {
+	typ   _type
+	elem  *_type
+	slice *_type
+	len   uintptr
 }
 
 type chantype struct {
@@ -84,11 +91,24 @@ type slicetype struct {
 type functype struct {
 	typ       _type
 	dotdotdot bool
-	in        slice
-	out       slice
+	in        []*_type
+	out       []*_type
 }
 
 type ptrtype struct {
 	typ  _type
 	elem *_type
 }
+
+type structfield struct {
+	name    *string
+	pkgpath *string
+	typ     *_type
+	tag     *string
+	offset  uintptr
+}
+
+type structtype struct {
+	typ    _type
+	fields []structfield
+}
diff --git a/src/runtime/typekind.go b/src/runtime/typekind.go
index b64ec44..d146dca 100644
--- a/src/runtime/typekind.go
+++ b/src/runtime/typekind.go
@@ -5,37 +5,37 @@
 package runtime
 
 const (
-	kindBool          = _KindBool
-	kindInt           = _KindInt
-	kindInt8          = _KindInt8
-	kindInt16         = _KindInt16
-	kindInt32         = _KindInt32
-	kindInt64         = _KindInt64
-	kindUint          = _KindUint
-	kindUint8         = _KindUint8
-	kindUint16        = _KindUint16
-	kindUint32        = _KindUint32
-	kindUint64        = _KindUint64
-	kindUintptr       = _KindUintptr
-	kindFloat32       = _KindFloat32
-	kindFloat64       = _KindFloat64
-	kindComplex64     = _KindComplex64
-	kindComplex128    = _KindComplex128
-	kindArray         = _KindArray
-	kindChan          = _KindChan
-	kindFunc          = _KindFunc
-	kindInterface     = _KindInterface
-	kindMap           = _KindMap
-	kindPtr           = _KindPtr
-	kindSlice         = _KindSlice
-	kindString        = _KindString
-	kindStruct        = _KindStruct
-	kindUnsafePointer = _KindUnsafePointer
+	kindBool = 1 + iota
+	kindInt
+	kindInt8
+	kindInt16
+	kindInt32
+	kindInt64
+	kindUint
+	kindUint8
+	kindUint16
+	kindUint32
+	kindUint64
+	kindUintptr
+	kindFloat32
+	kindFloat64
+	kindComplex64
+	kindComplex128
+	kindArray
+	kindChan
+	kindFunc
+	kindInterface
+	kindMap
+	kindPtr
+	kindSlice
+	kindString
+	kindStruct
+	kindUnsafePointer
 
-	kindDirectIface = _KindDirectIface
-	kindGCProg      = _KindGCProg
-	kindNoPointers  = _KindNoPointers
-	kindMask        = _KindMask
+	kindDirectIface = 1 << 5
+	kindGCProg      = 1 << 6
+	kindNoPointers  = 1 << 7
+	kindMask        = (1 << 5) - 1
 )
 
 // isDirectIface reports whether t is stored directly in an interface value.
diff --git a/src/runtime/typekind1.go b/src/runtime/typekind1.go
deleted file mode 100644
index 73028d6..0000000
--- a/src/runtime/typekind1.go
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2012 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 runtime
-
-const (
-	_KindBool = 1 + iota
-	_KindInt
-	_KindInt8
-	_KindInt16
-	_KindInt32
-	_KindInt64
-	_KindUint
-	_KindUint8
-	_KindUint16
-	_KindUint32
-	_KindUint64
-	_KindUintptr
-	_KindFloat32
-	_KindFloat64
-	_KindComplex64
-	_KindComplex128
-	_KindArray
-	_KindChan
-	_KindFunc
-	_KindInterface
-	_KindMap
-	_KindPtr
-	_KindSlice
-	_KindString
-	_KindStruct
-	_KindUnsafePointer
-
-	_KindDirectIface = 1 << 5
-	_KindGCProg      = 1 << 6 // Type.gc points to GC program
-	_KindNoPointers  = 1 << 7
-	_KindMask        = (1 << 5) - 1
-)
diff --git a/src/runtime/unaligned2.go b/src/runtime/unaligned2.go
index 4fc7917..1ec1d16 100644
--- a/src/runtime/unaligned2.go
+++ b/src/runtime/unaligned2.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.
 
-// +build arm ppc64 ppc64le
+// +build arm ppc64 ppc64le mips64 mips64le
 
 package runtime
 
diff --git a/src/runtime/vdso_linux_amd64.go b/src/runtime/vdso_linux_amd64.go
index 2440015..38914bb 100644
--- a/src/runtime/vdso_linux_amd64.go
+++ b/src/runtime/vdso_linux_amd64.go
@@ -4,7 +4,10 @@
 
 package runtime
 
-import "unsafe"
+import (
+	"runtime/internal/sys"
+	"unsafe"
+)
 
 // Look up symbols in the Linux vDSO.
 
@@ -303,7 +306,7 @@ func sysargs(argc int32, argv **byte) {
 	n++
 
 	// now argv+n is auxv
-	auxv := (*[1 << 32]elf64Auxv)(add(unsafe.Pointer(argv), uintptr(n)*ptrSize))
+	auxv := (*[1 << 32]elf64Auxv)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize))
 
 	for i := 0; auxv[i].a_type != _AT_NULL; i++ {
 		av := &auxv[i]
diff --git a/src/runtime/print1_write.go b/src/runtime/write_err.go
similarity index 100%
rename from src/runtime/print1_write.go
rename to src/runtime/write_err.go
diff --git a/src/runtime/write_err_android.go b/src/runtime/write_err_android.go
new file mode 100644
index 0000000..4411a14
--- /dev/null
+++ b/src/runtime/write_err_android.go
@@ -0,0 +1,160 @@
+// 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 runtime
+
+import "unsafe"
+
+var (
+	writeHeader = []byte{6 /* ANDROID_LOG_ERROR */, 'G', 'o', 0}
+	writePath   = []byte("/dev/log/main\x00")
+	writeLogd   = []byte("/dev/socket/logdw\x00")
+
+	// guarded by printlock/printunlock.
+	writeFD  uintptr
+	writeBuf [1024]byte
+	writePos int
+)
+
+// Prior to Android-L, logging was done through writes to /dev/log files implemented
+// in kernel ring buffers. In Android-L, those /dev/log files are no longer
+// accessible and logging is done through a centralized user-mode logger, logd.
+//
+// https://android.googlesource.com/platform/system/core/+/master/liblog/logd_write.c
+type loggerType int32
+
+const (
+	unknown loggerType = iota
+	legacy
+	logd
+	// TODO(hakim): logging for emulator?
+)
+
+var logger loggerType
+
+func writeErr(b []byte) {
+	if logger == unknown {
+		// Use logd if /dev/socket/logdw is available.
+		if v := uintptr(access(&writeLogd[0], 0x02 /* W_OK */)); v == 0 {
+			logger = logd
+			initLogd()
+		} else {
+			logger = legacy
+			initLegacy()
+		}
+	}
+
+	// Write to stderr for command-line programs.
+	write(2, unsafe.Pointer(&b[0]), int32(len(b)))
+
+	// Log format: "<header>\x00<message m bytes>\x00"
+	//
+	// <header>
+	//   In legacy mode: "<priority 1 byte><tag n bytes>".
+	//   In logd mode: "<android_log_header_t 11 bytes><priority 1 byte><tag n bytes>"
+	//
+	// The entire log needs to be delivered in a single syscall (the NDK
+	// does this with writev). Each log is its own line, so we need to
+	// buffer writes until we see a newline.
+	var hlen int
+	switch logger {
+	case logd:
+		hlen = writeLogdHeader()
+	case legacy:
+		hlen = len(writeHeader)
+	}
+
+	dst := writeBuf[hlen:]
+	for _, v := range b {
+		if v == 0 { // android logging won't print a zero byte
+			v = '0'
+		}
+		dst[writePos] = v
+		writePos++
+		if v == '\n' || writePos == len(dst)-1 {
+			dst[writePos] = 0
+			write(writeFD, unsafe.Pointer(&writeBuf[0]), int32(hlen+writePos))
+			memclrBytes(dst)
+			writePos = 0
+		}
+	}
+}
+
+func initLegacy() {
+	// In legacy mode, logs are written to /dev/log/main
+	writeFD = uintptr(open(&writePath[0], 0x1 /* O_WRONLY */, 0))
+	if writeFD == 0 {
+		// It is hard to do anything here. Write to stderr just
+		// in case user has root on device and has run
+		//	adb shell setprop log.redirect-stdio true
+		msg := []byte("runtime: cannot open /dev/log/main\x00")
+		write(2, unsafe.Pointer(&msg[0]), int32(len(msg)))
+		exit(2)
+	}
+
+	// Prepopulate the invariant header part.
+	copy(writeBuf[:len(writeHeader)], writeHeader)
+}
+
+// used in initLogdWrite but defined here to avoid heap allocation.
+var logdAddr sockaddr_un
+
+func initLogd() {
+	// In logd mode, logs are sent to the logd via a unix domain socket.
+	logdAddr.family = _AF_UNIX
+	copy(logdAddr.path[:], writeLogd)
+
+	// We are not using non-blocking I/O because writes taking this path
+	// are most likely triggered by panic, we cannot think of the advantage of
+	// non-blocking I/O for panic but see disadvantage (dropping panic message),
+	// and blocking I/O simplifies the code a lot.
+	fd := socket(_AF_UNIX, _SOCK_DGRAM|_O_CLOEXEC, 0)
+	if fd < 0 {
+		msg := []byte("runtime: cannot create a socket for logging\x00")
+		write(2, unsafe.Pointer(&msg[0]), int32(len(msg)))
+		exit(2)
+	}
+
+	errno := connect(fd, unsafe.Pointer(&logdAddr), int32(unsafe.Sizeof(logdAddr)))
+	if errno < 0 {
+		msg := []byte("runtime: cannot connect to /dev/socket/logdw\x00")
+		write(2, unsafe.Pointer(&msg[0]), int32(len(msg)))
+		// TODO(hakim): or should we just close fd and hope for better luck next time?
+		exit(2)
+	}
+	writeFD = uintptr(fd)
+
+	// Prepopulate invariant part of the header.
+	// The first 11 bytes will be populated later in writeLogdHeader.
+	copy(writeBuf[11:11+len(writeHeader)], writeHeader)
+}
+
+// writeLogdHeader populates the header and returns the length of the payload.
+func writeLogdHeader() int {
+	hdr := writeBuf[:11]
+
+	// The first 11 bytes of the header corresponds to android_log_header_t
+	// as defined in system/core/include/private/android_logger.h
+	//   hdr[0] log type id (unsigned char), defined in <log/log.h>
+	//   hdr[1:2] tid (uint16_t)
+	//   hdr[3:11] log_time defined in <log/log_read.h>
+	//      hdr[3:7] sec unsigned uint32, little endian.
+	//      hdr[7:11] nsec unsigned uint32, little endian.
+	hdr[0] = 0 // LOG_ID_MAIN
+	sec, nsec := time_now()
+	packUint32(hdr[3:7], uint32(sec))
+	packUint32(hdr[7:11], uint32(nsec))
+
+	// TODO(hakim):  hdr[1:2] = gettid?
+
+	return 11 + len(writeHeader)
+}
+
+func packUint32(b []byte, v uint32) {
+	// little-endian.
+	b[0] = byte(v)
+	b[1] = byte(v >> 8)
+	b[2] = byte(v >> 16)
+	b[3] = byte(v >> 24)
+}
diff --git a/src/runtime/zgoarch_386.go b/src/runtime/zgoarch_386.go
deleted file mode 100644
index 79053f1..0000000
--- a/src/runtime/zgoarch_386.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoarch = `386`
-
-const goarch_386 = 1
-const goarch_amd64 = 0
-const goarch_amd64p32 = 0
-const goarch_arm = 0
-const goarch_arm64 = 0
-const goarch_ppc64 = 0
-const goarch_ppc64le = 0
diff --git a/src/runtime/zgoarch_amd64.go b/src/runtime/zgoarch_amd64.go
deleted file mode 100644
index 70095f5..0000000
--- a/src/runtime/zgoarch_amd64.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoarch = `amd64`
-
-const goarch_386 = 0
-const goarch_amd64 = 1
-const goarch_amd64p32 = 0
-const goarch_arm = 0
-const goarch_arm64 = 0
-const goarch_ppc64 = 0
-const goarch_ppc64le = 0
diff --git a/src/runtime/zgoarch_amd64p32.go b/src/runtime/zgoarch_amd64p32.go
deleted file mode 100644
index 9ac3f0b..0000000
--- a/src/runtime/zgoarch_amd64p32.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoarch = `amd64p32`
-
-const goarch_386 = 0
-const goarch_amd64 = 0
-const goarch_amd64p32 = 1
-const goarch_arm = 0
-const goarch_arm64 = 0
-const goarch_ppc64 = 0
-const goarch_ppc64le = 0
diff --git a/src/runtime/zgoarch_arm.go b/src/runtime/zgoarch_arm.go
deleted file mode 100644
index c865dc0..0000000
--- a/src/runtime/zgoarch_arm.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoarch = `arm`
-
-const goarch_386 = 0
-const goarch_amd64 = 0
-const goarch_amd64p32 = 0
-const goarch_arm = 1
-const goarch_arm64 = 0
-const goarch_ppc64 = 0
-const goarch_ppc64le = 0
diff --git a/src/runtime/zgoarch_arm64.go b/src/runtime/zgoarch_arm64.go
deleted file mode 100644
index cde5e9f..0000000
--- a/src/runtime/zgoarch_arm64.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoarch = `arm64`
-
-const goarch_386 = 0
-const goarch_amd64 = 0
-const goarch_amd64p32 = 0
-const goarch_arm = 0
-const goarch_arm64 = 1
-const goarch_ppc64 = 0
-const goarch_ppc64le = 0
diff --git a/src/runtime/zgoarch_ppc64.go b/src/runtime/zgoarch_ppc64.go
deleted file mode 100644
index 13d87d9..0000000
--- a/src/runtime/zgoarch_ppc64.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoarch = `ppc64`
-
-const goarch_386 = 0
-const goarch_amd64 = 0
-const goarch_amd64p32 = 0
-const goarch_arm = 0
-const goarch_arm64 = 0
-const goarch_ppc64 = 1
-const goarch_ppc64le = 0
diff --git a/src/runtime/zgoarch_ppc64le.go b/src/runtime/zgoarch_ppc64le.go
deleted file mode 100644
index 5d088aa..0000000
--- a/src/runtime/zgoarch_ppc64le.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoarch = `ppc64le`
-
-const goarch_386 = 0
-const goarch_amd64 = 0
-const goarch_amd64p32 = 0
-const goarch_arm = 0
-const goarch_arm64 = 0
-const goarch_ppc64 = 0
-const goarch_ppc64le = 1
diff --git a/src/runtime/zgoos_android.go b/src/runtime/zgoos_android.go
deleted file mode 100644
index 0590bd9..0000000
--- a/src/runtime/zgoos_android.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoos = `android`
-
-const goos_android = 1
-const goos_darwin = 0
-const goos_dragonfly = 0
-const goos_freebsd = 0
-const goos_linux = 0
-const goos_nacl = 0
-const goos_netbsd = 0
-const goos_openbsd = 0
-const goos_plan9 = 0
-const goos_solaris = 0
-const goos_windows = 0
diff --git a/src/runtime/zgoos_darwin.go b/src/runtime/zgoos_darwin.go
deleted file mode 100644
index c0a7cd6..0000000
--- a/src/runtime/zgoos_darwin.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoos = `darwin`
-
-const goos_android = 0
-const goos_darwin = 1
-const goos_dragonfly = 0
-const goos_freebsd = 0
-const goos_linux = 0
-const goos_nacl = 0
-const goos_netbsd = 0
-const goos_openbsd = 0
-const goos_plan9 = 0
-const goos_solaris = 0
-const goos_windows = 0
diff --git a/src/runtime/zgoos_dragonfly.go b/src/runtime/zgoos_dragonfly.go
deleted file mode 100644
index 008d6de..0000000
--- a/src/runtime/zgoos_dragonfly.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoos = `dragonfly`
-
-const goos_android = 0
-const goos_darwin = 0
-const goos_dragonfly = 1
-const goos_freebsd = 0
-const goos_linux = 0
-const goos_nacl = 0
-const goos_netbsd = 0
-const goos_openbsd = 0
-const goos_plan9 = 0
-const goos_solaris = 0
-const goos_windows = 0
diff --git a/src/runtime/zgoos_freebsd.go b/src/runtime/zgoos_freebsd.go
deleted file mode 100644
index 2478940..0000000
--- a/src/runtime/zgoos_freebsd.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoos = `freebsd`
-
-const goos_android = 0
-const goos_darwin = 0
-const goos_dragonfly = 0
-const goos_freebsd = 1
-const goos_linux = 0
-const goos_nacl = 0
-const goos_netbsd = 0
-const goos_openbsd = 0
-const goos_plan9 = 0
-const goos_solaris = 0
-const goos_windows = 0
diff --git a/src/runtime/zgoos_linux.go b/src/runtime/zgoos_linux.go
deleted file mode 100644
index c775ab5..0000000
--- a/src/runtime/zgoos_linux.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// generated by gengoos.go using 'go generate'
-
-// +build !android
-
-package runtime
-
-const theGoos = `linux`
-
-const goos_android = 0
-const goos_darwin = 0
-const goos_dragonfly = 0
-const goos_freebsd = 0
-const goos_linux = 1
-const goos_nacl = 0
-const goos_netbsd = 0
-const goos_openbsd = 0
-const goos_plan9 = 0
-const goos_solaris = 0
-const goos_windows = 0
diff --git a/src/runtime/zgoos_nacl.go b/src/runtime/zgoos_nacl.go
deleted file mode 100644
index d9d88f4..0000000
--- a/src/runtime/zgoos_nacl.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoos = `nacl`
-
-const goos_android = 0
-const goos_darwin = 0
-const goos_dragonfly = 0
-const goos_freebsd = 0
-const goos_linux = 0
-const goos_nacl = 1
-const goos_netbsd = 0
-const goos_openbsd = 0
-const goos_plan9 = 0
-const goos_solaris = 0
-const goos_windows = 0
diff --git a/src/runtime/zgoos_netbsd.go b/src/runtime/zgoos_netbsd.go
deleted file mode 100644
index ff2c5cb..0000000
--- a/src/runtime/zgoos_netbsd.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoos = `netbsd`
-
-const goos_android = 0
-const goos_darwin = 0
-const goos_dragonfly = 0
-const goos_freebsd = 0
-const goos_linux = 0
-const goos_nacl = 0
-const goos_netbsd = 1
-const goos_openbsd = 0
-const goos_plan9 = 0
-const goos_solaris = 0
-const goos_windows = 0
diff --git a/src/runtime/zgoos_openbsd.go b/src/runtime/zgoos_openbsd.go
deleted file mode 100644
index b071dc6..0000000
--- a/src/runtime/zgoos_openbsd.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoos = `openbsd`
-
-const goos_android = 0
-const goos_darwin = 0
-const goos_dragonfly = 0
-const goos_freebsd = 0
-const goos_linux = 0
-const goos_nacl = 0
-const goos_netbsd = 0
-const goos_openbsd = 1
-const goos_plan9 = 0
-const goos_solaris = 0
-const goos_windows = 0
diff --git a/src/runtime/zgoos_plan9.go b/src/runtime/zgoos_plan9.go
deleted file mode 100644
index 4306b0f..0000000
--- a/src/runtime/zgoos_plan9.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoos = `plan9`
-
-const goos_android = 0
-const goos_darwin = 0
-const goos_dragonfly = 0
-const goos_freebsd = 0
-const goos_linux = 0
-const goos_nacl = 0
-const goos_netbsd = 0
-const goos_openbsd = 0
-const goos_plan9 = 1
-const goos_solaris = 0
-const goos_windows = 0
diff --git a/src/runtime/zgoos_solaris.go b/src/runtime/zgoos_solaris.go
deleted file mode 100644
index 10f9537..0000000
--- a/src/runtime/zgoos_solaris.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoos = `solaris`
-
-const goos_android = 0
-const goos_darwin = 0
-const goos_dragonfly = 0
-const goos_freebsd = 0
-const goos_linux = 0
-const goos_nacl = 0
-const goos_netbsd = 0
-const goos_openbsd = 0
-const goos_plan9 = 0
-const goos_solaris = 1
-const goos_windows = 0
diff --git a/src/runtime/zgoos_windows.go b/src/runtime/zgoos_windows.go
deleted file mode 100644
index 56f5c58..0000000
--- a/src/runtime/zgoos_windows.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// generated by gengoos.go using 'go generate'
-
-package runtime
-
-const theGoos = `windows`
-
-const goos_android = 0
-const goos_darwin = 0
-const goos_dragonfly = 0
-const goos_freebsd = 0
-const goos_linux = 0
-const goos_nacl = 0
-const goos_netbsd = 0
-const goos_openbsd = 0
-const goos_plan9 = 0
-const goos_solaris = 0
-const goos_windows = 1
diff --git a/src/sort/example_multi_test.go b/src/sort/example_multi_test.go
index ac31654..40d1215 100644
--- a/src/sort/example_multi_test.go
+++ b/src/sort/example_multi_test.go
@@ -122,10 +122,10 @@ func Example_sortMultiKeys() {
 	fmt.Println("By language,<lines,user:", changes)
 
 	// Output:
-	// By user: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken Go 200} {ken C 150} {r Go 100} {r C 150} {rsc Go 200}]
+	// By user: [{dmr C 100} {glenda Go 200} {gri Go 100} {gri Smalltalk 80} {ken C 150} {ken Go 200} {r Go 100} {r C 150} {rsc Go 200}]
 	// By user,<lines: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken C 150} {ken Go 200} {r Go 100} {r C 150} {rsc Go 200}]
 	// By user,>lines: [{dmr C 100} {glenda Go 200} {gri Go 100} {gri Smalltalk 80} {ken Go 200} {ken C 150} {r C 150} {r Go 100} {rsc Go 200}]
-	// By language,<lines: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {ken Go 200} {glenda Go 200} {rsc Go 200} {gri Smalltalk 80}]
+	// By language,<lines: [{dmr C 100} {ken C 150} {r C 150} {r Go 100} {gri Go 100} {ken Go 200} {glenda Go 200} {rsc Go 200} {gri Smalltalk 80}]
 	// By language,<lines,user: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {glenda Go 200} {ken Go 200} {rsc Go 200} {gri Smalltalk 80}]
 
 }
diff --git a/src/sort/search.go b/src/sort/search.go
index 8a2c1c3..de8178f 100644
--- a/src/sort/search.go
+++ b/src/sort/search.go
@@ -13,7 +13,7 @@ package sort
 // and then true for the (possibly empty) remainder; Search returns
 // the first true index.  If there is no such index, Search returns n.
 // (Note that the "not found" return value is not -1 as in, for instance,
-// strings.Index).
+// strings.Index.)
 // Search calls f(i) only for i in the range [0, n).
 //
 // A common use of Search is to find the index i for a value x in
diff --git a/src/sort/sort.go b/src/sort/sort.go
index c7c3042..ac8f4a6 100644
--- a/src/sort/sort.go
+++ b/src/sort/sort.go
@@ -72,7 +72,7 @@ func heapSort(data Interface, a, b int) {
 	}
 }
 
-// Quicksort, following Bentley and McIlroy,
+// Quicksort, loosely following Bentley and McIlroy,
 // ``Engineering a Sort Function,'' SP&E November 1993.
 
 // medianOfThree moves the median of the three values data[m0], data[m1], data[m2] into data[m1].
@@ -111,59 +111,82 @@ func doPivot(data Interface, lo, hi int) (midlo, midhi int) {
 
 	// Invariants are:
 	//	data[lo] = pivot (set up by ChoosePivot)
-	//	data[lo <= i < a] = pivot
-	//	data[a <= i < b] < pivot
-	//	data[b <= i < c] is unexamined
-	//	data[c <= i < d] > pivot
-	//	data[d <= i < hi] = pivot
-	//
-	// Once b meets c, can swap the "= pivot" sections
-	// into the middle of the slice.
+	//	data[lo < i < a] < pivot
+	//	data[a <= i < b] <= pivot
+	//	data[b <= i < c] unexamined
+	//	data[c <= i < hi-1] > pivot
+	//	data[hi-1] >= pivot
 	pivot := lo
-	a, b, c, d := lo+1, lo+1, hi, hi
+	a, c := lo+1, hi-1
+
+	for ; a != c && data.Less(a, pivot); a++ {
+	}
+	b := a
 	for {
-		for b < c {
-			if data.Less(b, pivot) { // data[b] < pivot
-				b++
-			} else if !data.Less(pivot, b) { // data[b] = pivot
-				data.Swap(a, b)
-				a++
-				b++
-			} else {
-				break
-			}
+		for ; b != c && !data.Less(pivot, b); b++ { // data[b] <= pivot
 		}
-		for b < c {
-			if data.Less(pivot, c-1) { // data[c-1] > pivot
-				c--
-			} else if !data.Less(c-1, pivot) { // data[c-1] = pivot
-				data.Swap(c-1, d-1)
-				c--
-				d--
-			} else {
-				break
-			}
+		for ; b != c && data.Less(pivot, c-1); c-- { // data[c-1] > pivot
 		}
-		if b >= c {
+		if b == c {
 			break
 		}
-		// data[b] > pivot; data[c-1] < pivot
+		// data[b] > pivot; data[c-1] <= pivot
 		data.Swap(b, c-1)
 		b++
 		c--
 	}
-
-	n := min(b-a, a-lo)
-	swapRange(data, lo, b-n, n)
-
-	n = min(hi-d, d-c)
-	swapRange(data, c, hi-n, n)
-
-	return lo + b - a, hi - (d - c)
+	// If hi-c<3 then there are duplicates (by property of median of nine).
+	// Let be a bit more conservative, and set border to 5.
+	protect := hi-c < 5
+	if !protect && hi-c < (hi-lo)/4 {
+		// Lets test some points for equality to pivot
+		dups := 0
+		if !data.Less(pivot, hi-1) { // data[hi-1] = pivot
+			data.Swap(c, hi-1)
+			c++
+			dups++
+		}
+		if !data.Less(b-1, pivot) { // data[b-1] = pivot
+			b--
+			dups++
+		}
+		// m-lo = (hi-lo)/2 > 6
+		// b-lo > (hi-lo)*3/4-1 > 8
+		// ==> m < b ==> data[m] <= pivot
+		if !data.Less(m, pivot) { // data[m] = pivot
+			data.Swap(m, b-1)
+			b--
+			dups++
+		}
+		// if at least 2 points are equal to pivot, assume skewed distribution
+		protect = dups > 1
+	}
+	if protect {
+		// Protect against a lot of duplicates
+		// Add invariant:
+		//	data[a <= i < b] unexamined
+		//	data[b <= i < c] = pivot
+		for {
+			for ; a != b && !data.Less(b-1, pivot); b-- { // data[b] == pivot
+			}
+			for ; a != b && data.Less(a, pivot); a++ { // data[a] < pivot
+			}
+			if a == b {
+				break
+			}
+			// data[a] == pivot; data[b-1] < pivot
+			data.Swap(a, b-1)
+			a++
+			b--
+		}
+	}
+	// Swap pivot into middle
+	data.Swap(pivot, b-1)
+	return b - 1, c
 }
 
 func quickSort(data Interface, a, b, maxDepth int) {
-	for b-a > 7 {
+	for b-a > 12 { // Use ShellSort for slices <= 12 elements
 		if maxDepth == 0 {
 			heapSort(data, a, b)
 			return
@@ -181,6 +204,13 @@ func quickSort(data Interface, a, b, maxDepth int) {
 		}
 	}
 	if b-a > 1 {
+		// Do ShellSort pass with gap 6
+		// It could be written in this simplified form cause b-a <= 12
+		for i := a + 6; i < b; i++ {
+			if data.Less(i, i-6) {
+				data.Swap(i, i-6)
+			}
+		}
 		insertionSort(data, a, b)
 	}
 }
diff --git a/src/strconv/ftoa.go b/src/strconv/ftoa.go
index 468c37f..9ff5d10 100644
--- a/src/strconv/ftoa.go
+++ b/src/strconv/ftoa.go
@@ -286,25 +286,23 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
 	// Now we can figure out the minimum number of digits required.
 	// Walk along until d has distinguished itself from upper and lower.
 	for i := 0; i < d.nd; i++ {
-		var l, m, u byte // lower, middle, upper digits
+		l := byte('0') // lower digit
 		if i < lower.nd {
 			l = lower.d[i]
-		} else {
-			l = '0'
 		}
-		m = d.d[i]
+		m := d.d[i]    // middle digit
+		u := byte('0') // upper digit
 		if i < upper.nd {
 			u = upper.d[i]
-		} else {
-			u = '0'
 		}
 
 		// Okay to round down (truncate) if lower has a different digit
-		// or if lower is inclusive and is exactly the result of rounding down.
-		okdown := l != m || (inclusive && l == m && i+1 == lower.nd)
+		// or if lower is inclusive and is exactly the result of rounding
+		// down (i.e., and we have reached the final digit of lower).
+		okdown := l != m || inclusive && i+1 == lower.nd
 
-		// Okay to round up if upper has a different digit and
-		// either upper is inclusive or upper is bigger than the result of rounding up.
+		// Okay to round up if upper has a different digit and either upper
+		// is inclusive or upper is bigger than the result of rounding up.
 		okup := m != u && (inclusive || m+1 < u || i+1 < upper.nd)
 
 		// If it's okay to do either, then round to the nearest one.
diff --git a/src/strconv/ftoa_test.go b/src/strconv/ftoa_test.go
index 1b4dcd9..0b9f0fe 100644
--- a/src/strconv/ftoa_test.go
+++ b/src/strconv/ftoa_test.go
@@ -18,7 +18,7 @@ type ftoaTest struct {
 	s    string
 }
 
-func fdiv(a, b float64) float64 { return a / b } // keep compiler in the dark
+func fdiv(a, b float64) float64 { return a / b }
 
 const (
 	below1e23 = 99999999999999974834176
@@ -94,8 +94,8 @@ var ftoatests = []ftoaTest{
 	{above1e23, 'f', -1, "100000000000000010000000"},
 	{above1e23, 'g', -1, "1.0000000000000001e+23"},
 
-	{fdiv(5e-304, 1e20), 'g', -1, "5e-324"},
-	{fdiv(-5e-304, 1e20), 'g', -1, "-5e-324"},
+	{fdiv(5e-304, 1e20), 'g', -1, "5e-324"},   // avoid constant arithmetic
+	{fdiv(-5e-304, 1e20), 'g', -1, "-5e-324"}, // avoid constant arithmetic
 
 	{32, 'g', -1, "32"},
 	{32, 'g', 0, "3e+01"},
diff --git a/src/strconv/isprint.go b/src/strconv/isprint.go
index 0cf363c..20a02de 100644
--- a/src/strconv/isprint.go
+++ b/src/strconv/isprint.go
@@ -635,3 +635,23 @@ var isNotPrint32 = []uint16{ // add 0x10000 to each entry
 	0xf57a,
 	0xf5a4,
 }
+
+// isGraphic lists the graphic runes not matched by IsPrint.
+var isGraphic = []uint16{
+	0x00a0,
+	0x1680,
+	0x2000,
+	0x2001,
+	0x2002,
+	0x2003,
+	0x2004,
+	0x2005,
+	0x2006,
+	0x2007,
+	0x2008,
+	0x2009,
+	0x200a,
+	0x202f,
+	0x205f,
+	0x3000,
+}
diff --git a/src/strconv/itoa.go b/src/strconv/itoa.go
index e6f6303..f50d877 100644
--- a/src/strconv/itoa.go
+++ b/src/strconv/itoa.go
@@ -20,7 +20,7 @@ func FormatInt(i int64, base int) string {
 	return s
 }
 
-// Itoa is shorthand for FormatInt(i, 10).
+// Itoa is shorthand for FormatInt(int64(i), 10).
 func Itoa(i int) string {
 	return FormatInt(int64(i), 10)
 }
diff --git a/src/strconv/makeisprint.go b/src/strconv/makeisprint.go
index 588d0a0..5142580 100644
--- a/src/strconv/makeisprint.go
+++ b/src/strconv/makeisprint.go
@@ -174,6 +174,23 @@ func main() {
 		}
 		fmt.Fprintf(&buf, "\t%#04x,\n", r-0x10000)
 	}
+	fmt.Fprintf(&buf, "}\n\n")
+
+	// The list of graphic but not "printable" runes is short. Just make one easy table.
+	fmt.Fprintf(&buf, "// isGraphic lists the graphic runes not matched by IsPrint.\n")
+	fmt.Fprintf(&buf, "var isGraphic = []uint16{\n")
+	for r := rune(0); r <= unicode.MaxRune; r++ {
+		if unicode.IsPrint(r) != unicode.IsGraphic(r) {
+			// Sanity check.
+			if !unicode.IsGraphic(r) {
+				log.Fatalf("%U is printable but not graphic\n", r)
+			}
+			if r > 0xFFFF { // We expect only 16-bit values.
+				log.Fatalf("%U too big for isGraphic\n", r)
+			}
+			fmt.Fprintf(&buf, "\t%#04x,\n", r)
+		}
+	}
 	fmt.Fprintf(&buf, "}\n")
 
 	data, err := format.Source(buf.Bytes())
diff --git a/src/strconv/quote.go b/src/strconv/quote.go
index 53d51b5..40d0667 100644
--- a/src/strconv/quote.go
+++ b/src/strconv/quote.go
@@ -12,7 +12,7 @@ import (
 
 const lowerhex = "0123456789abcdef"
 
-func quoteWith(s string, quote byte, ASCIIonly bool) string {
+func quoteWith(s string, quote byte, ASCIIonly, graphicOnly bool) string {
 	var runeTmp [utf8.UTFMax]byte
 	buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations.
 	buf = append(buf, quote)
@@ -38,7 +38,7 @@ func quoteWith(s string, quote byte, ASCIIonly bool) string {
 				buf = append(buf, byte(r))
 				continue
 			}
-		} else if IsPrint(r) {
+		} else if IsPrint(r) || graphicOnly && isInGraphicList(r) {
 			n := utf8.EncodeRune(runeTmp[:], r)
 			buf = append(buf, runeTmp[:n]...)
 			continue
@@ -90,7 +90,7 @@ func quoteWith(s string, quote byte, ASCIIonly bool) string {
 // control characters and non-printable characters as defined by
 // IsPrint.
 func Quote(s string) string {
-	return quoteWith(s, '"', false)
+	return quoteWith(s, '"', false, false)
 }
 
 // AppendQuote appends a double-quoted Go string literal representing s,
@@ -103,7 +103,7 @@ func AppendQuote(dst []byte, s string) []byte {
 // The returned string uses Go escape sequences (\t, \n, \xFF, \u0100) for
 // non-ASCII characters and non-printable characters as defined by IsPrint.
 func QuoteToASCII(s string) string {
-	return quoteWith(s, '"', true)
+	return quoteWith(s, '"', true, false)
 }
 
 // AppendQuoteToASCII appends a double-quoted Go string literal representing s,
@@ -112,12 +112,25 @@ func AppendQuoteToASCII(dst []byte, s string) []byte {
 	return append(dst, QuoteToASCII(s)...)
 }
 
+// QuoteToGraphic returns a double-quoted Go string literal representing s.
+// The returned string uses Go escape sequences (\t, \n, \xFF, \u0100) for
+// non-ASCII characters and non-printable characters as defined by IsGraphic.
+func QuoteToGraphic(s string) string {
+	return quoteWith(s, '"', false, true)
+}
+
+// AppendQuoteToGraphic appends a double-quoted Go string literal representing s,
+// as generated by QuoteToGraphic, to dst and returns the extended buffer.
+func AppendQuoteToGraphic(dst []byte, s string) []byte {
+	return append(dst, QuoteToGraphic(s)...)
+}
+
 // QuoteRune returns a single-quoted Go character literal representing the
-// rune.  The returned string uses Go escape sequences (\t, \n, \xFF, \u0100)
+// rune. The returned string uses Go escape sequences (\t, \n, \xFF, \u0100)
 // for control characters and non-printable characters as defined by IsPrint.
 func QuoteRune(r rune) string {
 	// TODO: avoid the allocation here.
-	return quoteWith(string(r), '\'', false)
+	return quoteWith(string(r), '\'', false, false)
 }
 
 // AppendQuoteRune appends a single-quoted Go character literal representing the rune,
@@ -127,12 +140,12 @@ func AppendQuoteRune(dst []byte, r rune) []byte {
 }
 
 // QuoteRuneToASCII returns a single-quoted Go character literal representing
-// the rune.  The returned string uses Go escape sequences (\t, \n, \xFF,
+// the rune. The returned string uses Go escape sequences (\t, \n, \xFF,
 // \u0100) for non-ASCII characters and non-printable characters as defined
 // by IsPrint.
 func QuoteRuneToASCII(r rune) string {
 	// TODO: avoid the allocation here.
-	return quoteWith(string(r), '\'', true)
+	return quoteWith(string(r), '\'', true, false)
 }
 
 // AppendQuoteRuneToASCII appends a single-quoted Go character literal representing the rune,
@@ -141,6 +154,21 @@ func AppendQuoteRuneToASCII(dst []byte, r rune) []byte {
 	return append(dst, QuoteRuneToASCII(r)...)
 }
 
+// QuoteRuneToGraphic returns a single-quoted Go character literal representing
+// the rune. The returned string uses Go escape sequences (\t, \n, \xFF,
+// \u0100) for non-ASCII characters and non-printable characters as defined
+// by IsGraphic.
+func QuoteRuneToGraphic(r rune) string {
+	// TODO: avoid the allocation here.
+	return quoteWith(string(r), '\'', false, true)
+}
+
+// AppendQuoteRuneToGraphic appends a single-quoted Go character literal representing the rune,
+// as generated by QuoteRuneToGraphic, to dst and returns the extended buffer.
+func AppendQuoteRuneToGraphic(dst []byte, r rune) []byte {
+	return append(dst, QuoteRuneToGraphic(r)...)
+}
+
 // CanBackquote reports whether the string s can be represented
 // unchanged as a single-line backquoted string without control
 // characters other than tab.
@@ -453,3 +481,26 @@ func IsPrint(r rune) bool {
 	j := bsearch16(isNotPrint, uint16(r))
 	return j >= len(isNotPrint) || isNotPrint[j] != uint16(r)
 }
+
+// IsGraphic reports whether the rune is defined as a Graphic by Unicode. Such
+// characters include letters, marks, numbers, punctuation, symbols, and
+// spaces, from categories L, M, N, P, S, and Zs.
+func IsGraphic(r rune) bool {
+	if IsPrint(r) {
+		return true
+	}
+	return isInGraphicList(r)
+}
+
+// isInGraphicList reports whether the rune is in the isGraphic list. This separation
+// from IsGraphic allows quoteWith to avoid two calls to IsPrint.
+// Should be called only if IsPrint fails.
+func isInGraphicList(r rune) bool {
+	// We know r must fit in 16 bits - see makeisprint.go.
+	if r > 0xFFFF {
+		return false
+	}
+	rr := uint16(r)
+	i := bsearch16(isGraphic, rr)
+	return i < len(isGraphic) && rr == isGraphic[i]
+}
diff --git a/src/strconv/quote_test.go b/src/strconv/quote_test.go
index 3bf162f..3e8ec2c 100644
--- a/src/strconv/quote_test.go
+++ b/src/strconv/quote_test.go
@@ -10,7 +10,7 @@ import (
 	"unicode"
 )
 
-// Verify that our isPrint agrees with unicode.IsPrint
+// Verify that our IsPrint agrees with unicode.IsPrint.
 func TestIsPrint(t *testing.T) {
 	n := 0
 	for r := rune(0); r <= unicode.MaxRune; r++ {
@@ -24,19 +24,36 @@ func TestIsPrint(t *testing.T) {
 	}
 }
 
+// Verify that our IsGraphic agrees with unicode.IsGraphic.
+func TestIsGraphic(t *testing.T) {
+	n := 0
+	for r := rune(0); r <= unicode.MaxRune; r++ {
+		if IsGraphic(r) != unicode.IsGraphic(r) {
+			t.Errorf("IsGraphic(%U)=%t incorrect", r, IsGraphic(r))
+			n++
+			if n > 10 {
+				return
+			}
+		}
+	}
+}
+
 type quoteTest struct {
-	in    string
-	out   string
-	ascii string
+	in      string
+	out     string
+	ascii   string
+	graphic string
 }
 
 var quotetests = []quoteTest{
-	{"\a\b\f\r\n\t\v", `"\a\b\f\r\n\t\v"`, `"\a\b\f\r\n\t\v"`},
-	{"\\", `"\\"`, `"\\"`},
-	{"abc\xffdef", `"abc\xffdef"`, `"abc\xffdef"`},
-	{"\u263a", `"☺"`, `"\u263a"`},
-	{"\U0010ffff", `"\U0010ffff"`, `"\U0010ffff"`},
-	{"\x04", `"\x04"`, `"\x04"`},
+	{"\a\b\f\r\n\t\v", `"\a\b\f\r\n\t\v"`, `"\a\b\f\r\n\t\v"`, `"\a\b\f\r\n\t\v"`},
+	{"\\", `"\\"`, `"\\"`, `"\\"`},
+	{"abc\xffdef", `"abc\xffdef"`, `"abc\xffdef"`, `"abc\xffdef"`},
+	{"\u263a", `"☺"`, `"\u263a"`, `"☺"`},
+	{"\U0010ffff", `"\U0010ffff"`, `"\U0010ffff"`, `"\U0010ffff"`},
+	{"\x04", `"\x04"`, `"\x04"`, `"\x04"`},
+	// Some non-printable but graphic runes. Final column is double-quoted.
+	{"!\u00a0!\u2000!\u3000!", `"!\u00a0!\u2000!\u3000!"`, `"!\u00a0!\u2000!\u3000!"`, "\"!\u00a0!\u2000!\u3000!\""},
 }
 
 func TestQuote(t *testing.T) {
@@ -61,22 +78,38 @@ func TestQuoteToASCII(t *testing.T) {
 	}
 }
 
+func TestQuoteToGraphic(t *testing.T) {
+	for _, tt := range quotetests {
+		if out := QuoteToGraphic(tt.in); out != tt.graphic {
+			t.Errorf("QuoteToGraphic(%s) = %s, want %s", tt.in, out, tt.graphic)
+		}
+		if out := AppendQuoteToGraphic([]byte("abc"), tt.in); string(out) != "abc"+tt.graphic {
+			t.Errorf("AppendQuoteToGraphic(%q, %s) = %s, want %s", "abc", tt.in, out, "abc"+tt.graphic)
+		}
+	}
+}
+
 type quoteRuneTest struct {
-	in    rune
-	out   string
-	ascii string
+	in      rune
+	out     string
+	ascii   string
+	graphic string
 }
 
 var quoterunetests = []quoteRuneTest{
-	{'a', `'a'`, `'a'`},
-	{'\a', `'\a'`, `'\a'`},
-	{'\\', `'\\'`, `'\\'`},
-	{0xFF, `'ÿ'`, `'\u00ff'`},
-	{0x263a, `'☺'`, `'\u263a'`},
-	{0xfffd, `'�'`, `'\ufffd'`},
-	{0x0010ffff, `'\U0010ffff'`, `'\U0010ffff'`},
-	{0x0010ffff + 1, `'�'`, `'\ufffd'`},
-	{0x04, `'\x04'`, `'\x04'`},
+	{'a', `'a'`, `'a'`, `'a'`},
+	{'\a', `'\a'`, `'\a'`, `'\a'`},
+	{'\\', `'\\'`, `'\\'`, `'\\'`},
+	{0xFF, `'ÿ'`, `'\u00ff'`, `'ÿ'`},
+	{0x263a, `'☺'`, `'\u263a'`, `'☺'`},
+	{0xfffd, `'�'`, `'\ufffd'`, `'�'`},
+	{0x0010ffff, `'\U0010ffff'`, `'\U0010ffff'`, `'\U0010ffff'`},
+	{0x0010ffff + 1, `'�'`, `'\ufffd'`, `'�'`},
+	{0x04, `'\x04'`, `'\x04'`, `'\x04'`},
+	// Some differences between graphic and printable. Note the last column is double-quoted.
+	{'\u00a0', `'\u00a0'`, `'\u00a0'`, "'\u00a0'"},
+	{'\u2000', `'\u2000'`, `'\u2000'`, "'\u2000'"},
+	{'\u3000', `'\u3000'`, `'\u3000'`, "'\u3000'"},
 }
 
 func TestQuoteRune(t *testing.T) {
@@ -101,6 +134,17 @@ func TestQuoteRuneToASCII(t *testing.T) {
 	}
 }
 
+func TestQuoteRuneToGraphic(t *testing.T) {
+	for _, tt := range quoterunetests {
+		if out := QuoteRuneToGraphic(tt.in); out != tt.graphic {
+			t.Errorf("QuoteRuneToGraphic(%U) = %s, want %s", tt.in, out, tt.graphic)
+		}
+		if out := AppendQuoteRuneToGraphic([]byte("abc"), tt.in); string(out) != "abc"+tt.graphic {
+			t.Errorf("AppendQuoteRuneToGraphic(%q, %U) = %s, want %s", "abc", tt.in, out, "abc"+tt.graphic)
+		}
+	}
+}
+
 type canBackquoteTest struct {
 	in  string
 	out bool
diff --git a/src/strings/example_test.go b/src/strings/example_test.go
index 7243e16..3f9d63b 100644
--- a/src/strings/example_test.go
+++ b/src/strings/example_test.go
@@ -60,6 +60,28 @@ func ExampleEqualFold() {
 	// Output: true
 }
 
+func ExampleHasPrefix() {
+	fmt.Println(strings.HasPrefix("Gopher", "Go"))
+	fmt.Println(strings.HasPrefix("Gopher", "C"))
+	fmt.Println(strings.HasPrefix("Gopher", ""))
+	// Output:
+	// true
+	// false
+	// true
+}
+
+func ExampleHasSuffix() {
+	fmt.Println(strings.HasSuffix("Amigo", "go"))
+	fmt.Println(strings.HasSuffix("Amigo", "O"))
+	fmt.Println(strings.HasSuffix("Amigo", "Ami"))
+	fmt.Println(strings.HasSuffix("Amigo", ""))
+	// Output:
+	// true
+	// false
+	// false
+	// true
+}
+
 func ExampleIndex() {
 	fmt.Println(strings.Index("chicken", "ken"))
 	fmt.Println(strings.Index("chicken", "dmr"))
diff --git a/src/strings/strings.go b/src/strings/strings.go
index dd51dab..37d5647 100644
--- a/src/strings/strings.go
+++ b/src/strings/strings.go
@@ -143,43 +143,6 @@ func ContainsRune(s string, r rune) bool {
 	return IndexRune(s, r) >= 0
 }
 
-// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
-func Index(s, sep string) int {
-	n := len(sep)
-	switch {
-	case n == 0:
-		return 0
-	case n == 1:
-		return IndexByte(s, sep[0])
-	case n == len(s):
-		if sep == s {
-			return 0
-		}
-		return -1
-	case n > len(s):
-		return -1
-	}
-	// Rabin-Karp search
-	hashsep, pow := hashStr(sep)
-	var h uint32
-	for i := 0; i < n; i++ {
-		h = h*primeRK + uint32(s[i])
-	}
-	if h == hashsep && s[:n] == sep {
-		return 0
-	}
-	for i := n; i < len(s); {
-		h *= primeRK
-		h += uint32(s[i])
-		h -= pow * uint32(s[i-n])
-		i++
-		if h == hashsep && s[i-n:i] == sep {
-			return i - n
-		}
-	}
-	return -1
-}
-
 // LastIndex returns the index of the last instance of sep in s, or -1 if sep is not present in s.
 func LastIndex(s, sep string) int {
 	n := len(sep)
diff --git a/src/strings/strings_amd64.go b/src/strings/strings_amd64.go
new file mode 100644
index 0000000..376113f
--- /dev/null
+++ b/src/strings/strings_amd64.go
@@ -0,0 +1,49 @@
+// Copyright 2015 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 strings
+
+// indexShortStr returns the index of the first instance of c in s, or -1 if c is not present in s.
+// indexShortStr requires 2 <= len(c) <= shortStringLen
+func indexShortStr(s, c string) int // ../runtime/asm_$GOARCH.s
+const shortStringLen = 31
+
+// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
+func Index(s, sep string) int {
+	n := len(sep)
+	switch {
+	case n == 0:
+		return 0
+	case n == 1:
+		return IndexByte(s, sep[0])
+	case n <= shortStringLen:
+		return indexShortStr(s, sep)
+	case n == len(s):
+		if sep == s {
+			return 0
+		}
+		return -1
+	case n > len(s):
+		return -1
+	}
+	// Rabin-Karp search
+	hashsep, pow := hashStr(sep)
+	var h uint32
+	for i := 0; i < n; i++ {
+		h = h*primeRK + uint32(s[i])
+	}
+	if h == hashsep && s[:n] == sep {
+		return 0
+	}
+	for i := n; i < len(s); {
+		h *= primeRK
+		h += uint32(s[i])
+		h -= pow * uint32(s[i-n])
+		i++
+		if h == hashsep && s[i-n:i] == sep {
+			return i - n
+		}
+	}
+	return -1
+}
diff --git a/src/strings/strings_generic.go b/src/strings/strings_generic.go
new file mode 100644
index 0000000..811cb80
--- /dev/null
+++ b/src/strings/strings_generic.go
@@ -0,0 +1,47 @@
+// Copyright 2015 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.
+
+// +build !amd64
+
+package strings
+
+// TODO: implements short string optimization on non amd64 platforms
+// and get rid of strings_amd64.go
+
+// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s.
+func Index(s, sep string) int {
+	n := len(sep)
+	switch {
+	case n == 0:
+		return 0
+	case n == 1:
+		return IndexByte(s, sep[0])
+	case n == len(s):
+		if sep == s {
+			return 0
+		}
+		return -1
+	case n > len(s):
+		return -1
+	}
+	// Rabin-Karp search
+	hashsep, pow := hashStr(sep)
+	var h uint32
+	for i := 0; i < n; i++ {
+		h = h*primeRK + uint32(s[i])
+	}
+	if h == hashsep && s[:n] == sep {
+		return 0
+	}
+	for i := n; i < len(s); {
+		h *= primeRK
+		h += uint32(s[i])
+		h -= pow * uint32(s[i-n])
+		i++
+		if h == hashsep && s[i-n:i] == sep {
+			return i - n
+		}
+	}
+	return -1
+}
diff --git a/src/strings/strings_test.go b/src/strings/strings_test.go
index 4e21dea..49f55fe 100644
--- a/src/strings/strings_test.go
+++ b/src/strings/strings_test.go
@@ -59,6 +59,59 @@ var indexTests = []IndexTest{
 	{"abc", "b", 1},
 	{"abc", "c", 2},
 	{"abc", "x", -1},
+	// test special cases in Index() for short strings
+	{"", "ab", -1},
+	{"bc", "ab", -1},
+	{"ab", "ab", 0},
+	{"xab", "ab", 1},
+	{"xab"[:2], "ab", -1},
+	{"", "abc", -1},
+	{"xbc", "abc", -1},
+	{"abc", "abc", 0},
+	{"xabc", "abc", 1},
+	{"xabc"[:3], "abc", -1},
+	{"xabxc", "abc", -1},
+	{"", "abcd", -1},
+	{"xbcd", "abcd", -1},
+	{"abcd", "abcd", 0},
+	{"xabcd", "abcd", 1},
+	{"xyabcd"[:5], "abcd", -1},
+	{"xbcqq", "abcqq", -1},
+	{"abcqq", "abcqq", 0},
+	{"xabcqq", "abcqq", 1},
+	{"xyabcqq"[:6], "abcqq", -1},
+	{"xabxcqq", "abcqq", -1},
+	{"xabcqxq", "abcqq", -1},
+	{"", "01234567", -1},
+	{"32145678", "01234567", -1},
+	{"01234567", "01234567", 0},
+	{"x01234567", "01234567", 1},
+	{"xx01234567"[:9], "01234567", -1},
+	{"", "0123456789", -1},
+	{"3214567844", "0123456789", -1},
+	{"0123456789", "0123456789", 0},
+	{"x0123456789", "0123456789", 1},
+	{"xyz0123456789"[:12], "0123456789", -1},
+	{"x01234567x89", "0123456789", -1},
+	{"", "0123456789012345", -1},
+	{"3214567889012345", "0123456789012345", -1},
+	{"0123456789012345", "0123456789012345", 0},
+	{"x0123456789012345", "0123456789012345", 1},
+	{"", "01234567890123456789", -1},
+	{"32145678890123456789", "01234567890123456789", -1},
+	{"01234567890123456789", "01234567890123456789", 0},
+	{"x01234567890123456789", "01234567890123456789", 1},
+	{"xyz01234567890123456789"[:22], "01234567890123456789", -1},
+	{"", "0123456789012345678901234567890", -1},
+	{"321456788901234567890123456789012345678911", "0123456789012345678901234567890", -1},
+	{"0123456789012345678901234567890", "0123456789012345678901234567890", 0},
+	{"x0123456789012345678901234567890", "0123456789012345678901234567890", 1},
+	{"xyz0123456789012345678901234567890"[:33], "0123456789012345678901234567890", -1},
+	{"", "01234567890123456789012345678901", -1},
+	{"32145678890123456789012345678901234567890211", "01234567890123456789012345678901", -1},
+	{"01234567890123456789012345678901", "01234567890123456789012345678901", 0},
+	{"x01234567890123456789012345678901", "01234567890123456789012345678901", 1},
+	{"xyz01234567890123456789012345678901"[:34], "01234567890123456789012345678901", -1},
 }
 
 var lastIndexTests = []IndexTest{
diff --git a/src/sync/atomic/asm_linux_arm.s b/src/sync/atomic/asm_linux_arm.s
index 631c105..97b7b57 100644
--- a/src/sync/atomic/asm_linux_arm.s
+++ b/src/sync/atomic/asm_linux_arm.s
@@ -116,7 +116,7 @@ TEXT kernelCAS64<>(SB),NOSPLIT,$0-21
 	RET
 
 TEXT ·generalCAS64(SB),NOSPLIT,$0-21
-	B  	runtime·cas64(SB)
+	B  	runtime∕internal∕atomic·Cas64(SB)
 
 GLOBL armCAS64(SB), NOPTR, $4
 
diff --git a/src/sync/atomic/asm_mips64x.s b/src/sync/atomic/asm_mips64x.s
new file mode 100644
index 0000000..608ff21
--- /dev/null
+++ b/src/sync/atomic/asm_mips64x.s
@@ -0,0 +1,181 @@
+// Copyright 2015 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.
+
+// +build mips64 mips64le
+
+#include "textflag.h"
+
+#define LL(base, rt)	WORD	$((060<<26)|((base)<<21)|((rt)<<16))
+#define LLV(base, rt)	WORD	$((064<<26)|((base)<<21)|((rt)<<16))
+#define SC(base, rt)	WORD	$((070<<26)|((base)<<21)|((rt)<<16))
+#define SCV(base, rt)	WORD	$((074<<26)|((base)<<21)|((rt)<<16))
+#define SYNC	WORD $0xf
+
+TEXT ·SwapInt32(SB),NOSPLIT,$0-20
+	JMP	·SwapUint32(SB)
+
+TEXT ·SwapUint32(SB),NOSPLIT,$0-20
+	MOVV	addr+0(FP), R2
+	MOVW	new+8(FP), R5
+	SYNC
+	MOVV	R5, R3
+	LL(2, 1)	// R1 = *R2
+	SC(2, 3)	// *R2 = R3
+	BEQ	R3, -3(PC)
+	MOVW	R1, old+16(FP)
+	SYNC
+	RET
+
+TEXT ·SwapInt64(SB),NOSPLIT,$0-24
+	JMP	·SwapUint64(SB)
+
+TEXT ·SwapUint64(SB),NOSPLIT,$0-24
+	MOVV	addr+0(FP), R2
+	MOVV	new+8(FP), R5
+	SYNC
+	MOVV	R5, R3
+	LLV(2, 1)	// R1 = *R2
+	SCV(2, 3)	// *R2 = R3
+	BEQ	R3, -3(PC)
+	MOVV	R1, old+16(FP)
+	SYNC
+	RET
+
+TEXT ·SwapUintptr(SB),NOSPLIT,$0-24
+	JMP	·SwapUint64(SB)
+
+TEXT ·CompareAndSwapInt32(SB),NOSPLIT,$0-17
+	JMP	·CompareAndSwapUint32(SB)
+
+TEXT ·CompareAndSwapUint32(SB),NOSPLIT,$0-17
+	MOVV	addr+0(FP), R1
+	MOVW	old+8(FP), R2
+	MOVW	new+12(FP), R5
+	SYNC
+cas_again:
+	MOVV	R5, R3
+	LL(1, 4)	// R4 = *R1
+	BNE	R2, R4, cas_fail
+	SC(1, 3)	// *R1 = R3
+	BEQ	R3, cas_again
+	MOVV	$1, R1
+	MOVB	R1, swapped+16(FP)
+	SYNC
+	RET
+cas_fail:
+	MOVV	$0, R1
+	JMP	-4(PC)
+
+TEXT ·CompareAndSwapUintptr(SB),NOSPLIT,$0-25
+	JMP	·CompareAndSwapUint64(SB)
+
+TEXT ·CompareAndSwapInt64(SB),NOSPLIT,$0-25
+	JMP	·CompareAndSwapUint64(SB)
+
+TEXT ·CompareAndSwapUint64(SB),NOSPLIT,$0-25
+	MOVV	addr+0(FP), R1
+	MOVV	old+8(FP), R2
+	MOVV	new+16(FP), R5
+	SYNC
+cas64_again:
+	MOVV	R5, R3
+	LLV(1, 4)	// R4 = *R1
+	BNE	R2, R4, cas64_fail
+	SCV(1, 3)	// *R1 = R3
+	BEQ	R3, cas64_again
+	MOVV	$1, R1
+	MOVB	R1, swapped+24(FP)
+	SYNC
+	RET
+cas64_fail:
+	MOVV	$0, R1
+	JMP	-4(PC)
+
+TEXT ·AddInt32(SB),NOSPLIT,$0-20
+	JMP	·AddUint32(SB)
+
+TEXT ·AddUint32(SB),NOSPLIT,$0-20
+	MOVV	addr+0(FP), R2
+	MOVW	delta+8(FP), R3
+	SYNC
+	LL(2, 1)	// R1 = *R2
+	ADDU	R1, R3, R4
+	MOVV	R4, R1
+	SC(2, 4)	// *R2 = R4
+	BEQ	R4, -4(PC)
+	MOVW	R1, ret+16(FP)
+	SYNC
+	RET
+
+TEXT ·AddUintptr(SB),NOSPLIT,$0-24
+	JMP	·AddUint64(SB)
+
+TEXT ·AddInt64(SB),NOSPLIT,$0-24
+	JMP	·AddUint64(SB)
+
+TEXT ·AddUint64(SB),NOSPLIT,$0-24
+	MOVV	addr+0(FP), R2
+	MOVV	delta+8(FP), R3
+	SYNC
+	LLV(2, 1)	// R1 = *R2
+	ADDVU	R1, R3, R4
+	MOVV	R4, R1
+	SCV(2, 4)	// *R2 = R4
+	BEQ	R4, -4(PC)
+	MOVV	R1, ret+16(FP)
+	SYNC
+	RET
+
+TEXT ·LoadInt32(SB),NOSPLIT,$0-12
+	JMP	·LoadUint32(SB)
+
+TEXT ·LoadUint32(SB),NOSPLIT,$0-12
+	MOVV	addr+0(FP), R1
+	SYNC
+	MOVWU	0(R1), R1
+	SYNC
+	MOVW	R1, val+8(FP)
+	RET
+
+TEXT ·LoadInt64(SB),NOSPLIT,$0-16
+	JMP	·LoadUint64(SB)
+
+TEXT ·LoadUint64(SB),NOSPLIT,$0-16
+	MOVV	addr+0(FP), R1
+	SYNC
+	MOVV	0(R1), R1
+	SYNC
+	MOVV	R1, val+8(FP)
+	RET
+
+TEXT ·LoadUintptr(SB),NOSPLIT,$0-16
+	JMP	·LoadPointer(SB)
+
+TEXT ·LoadPointer(SB),NOSPLIT,$0-16
+	JMP	·LoadUint64(SB)
+
+TEXT ·StoreInt32(SB),NOSPLIT,$0-12
+	JMP	·StoreUint32(SB)
+
+TEXT ·StoreUint32(SB),NOSPLIT,$0-12
+	MOVV	addr+0(FP), R1
+	MOVW	val+8(FP), R2
+	SYNC
+	MOVW	R2, 0(R1)
+	SYNC
+	RET
+
+TEXT ·StoreInt64(SB),NOSPLIT,$0-16
+	JMP	·StoreUint64(SB)
+
+TEXT ·StoreUint64(SB),NOSPLIT,$0-16
+	MOVV	addr+0(FP), R1
+	MOVV	val+8(FP), R2
+	SYNC
+	MOVV	R2, 0(R1)
+	SYNC
+	RET
+
+TEXT ·StoreUintptr(SB),NOSPLIT,$0-16
+	JMP	·StoreUint64(SB)
diff --git a/src/sync/cond.go b/src/sync/cond.go
index 9e6bc17..0aefcda 100644
--- a/src/sync/cond.go
+++ b/src/sync/cond.go
@@ -5,6 +5,7 @@
 package sync
 
 import (
+	"internal/race"
 	"sync/atomic"
 	"unsafe"
 )
@@ -51,12 +52,12 @@ func NewCond(l Locker) *Cond {
 //
 func (c *Cond) Wait() {
 	c.checker.check()
-	if raceenabled {
-		raceDisable()
+	if race.Enabled {
+		race.Disable()
 	}
 	atomic.AddUint32(&c.waiters, 1)
-	if raceenabled {
-		raceEnable()
+	if race.Enabled {
+		race.Enable()
 	}
 	c.L.Unlock()
 	runtime_Syncsemacquire(&c.sema)
@@ -81,14 +82,14 @@ func (c *Cond) Broadcast() {
 
 func (c *Cond) signalImpl(all bool) {
 	c.checker.check()
-	if raceenabled {
-		raceDisable()
+	if race.Enabled {
+		race.Disable()
 	}
 	for {
 		old := atomic.LoadUint32(&c.waiters)
 		if old == 0 {
-			if raceenabled {
-				raceEnable()
+			if race.Enabled {
+				race.Enable()
 			}
 			return
 		}
@@ -97,8 +98,8 @@ func (c *Cond) signalImpl(all bool) {
 			new = 0
 		}
 		if atomic.CompareAndSwapUint32(&c.waiters, old, new) {
-			if raceenabled {
-				raceEnable()
+			if race.Enabled {
+				race.Enable()
 			}
 			runtime_Syncsemrelease(&c.sema, old-new)
 			return
diff --git a/src/sync/export_test.go b/src/sync/export_test.go
index 6f49b3b..fa5983a 100644
--- a/src/sync/export_test.go
+++ b/src/sync/export_test.go
@@ -7,5 +7,3 @@ package sync
 // Export for testing.
 var Runtime_Semacquire = runtime_Semacquire
 var Runtime_Semrelease = runtime_Semrelease
-
-const RaceEnabled = raceenabled
diff --git a/src/sync/mutex.go b/src/sync/mutex.go
index 3f280ad..eb52614 100644
--- a/src/sync/mutex.go
+++ b/src/sync/mutex.go
@@ -11,6 +11,7 @@
 package sync
 
 import (
+	"internal/race"
 	"sync/atomic"
 	"unsafe"
 )
@@ -41,8 +42,8 @@ const (
 func (m *Mutex) Lock() {
 	// Fast path: grab unlocked mutex.
 	if atomic.CompareAndSwapInt32(&m.state, 0, mutexLocked) {
-		if raceenabled {
-			raceAcquire(unsafe.Pointer(m))
+		if race.Enabled {
+			race.Acquire(unsafe.Pointer(m))
 		}
 		return
 	}
@@ -85,8 +86,8 @@ func (m *Mutex) Lock() {
 		}
 	}
 
-	if raceenabled {
-		raceAcquire(unsafe.Pointer(m))
+	if race.Enabled {
+		race.Acquire(unsafe.Pointer(m))
 	}
 }
 
@@ -97,9 +98,9 @@ func (m *Mutex) Lock() {
 // It is allowed for one goroutine to lock a Mutex and then
 // arrange for another goroutine to unlock it.
 func (m *Mutex) Unlock() {
-	if raceenabled {
+	if race.Enabled {
 		_ = m.state
-		raceRelease(unsafe.Pointer(m))
+		race.Release(unsafe.Pointer(m))
 	}
 
 	// Fast path: drop lock bit.
diff --git a/src/sync/pool.go b/src/sync/pool.go
index 0cf0637..381af0b 100644
--- a/src/sync/pool.go
+++ b/src/sync/pool.go
@@ -5,6 +5,7 @@
 package sync
 
 import (
+	"internal/race"
 	"runtime"
 	"sync/atomic"
 	"unsafe"
@@ -59,7 +60,7 @@ type poolLocal struct {
 
 // Put adds x to the pool.
 func (p *Pool) Put(x interface{}) {
-	if raceenabled {
+	if race.Enabled {
 		// Under race detector the Pool degenerates into no-op.
 		// It's conforming, simple and does not introduce excessive
 		// happens-before edges between unrelated goroutines.
@@ -91,7 +92,7 @@ func (p *Pool) Put(x interface{}) {
 // If Get would otherwise return nil and p.New is non-nil, Get returns
 // the result of calling p.New.
 func (p *Pool) Get() interface{} {
-	if raceenabled {
+	if race.Enabled {
 		if p.New != nil {
 			return p.New()
 		}
diff --git a/src/sync/race.go b/src/sync/race.go
deleted file mode 100644
index fd0277d..0000000
--- a/src/sync/race.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2012 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.
-
-// +build race
-
-package sync
-
-import (
-	"runtime"
-	"unsafe"
-)
-
-const raceenabled = true
-
-func raceAcquire(addr unsafe.Pointer) {
-	runtime.RaceAcquire(addr)
-}
-
-func raceRelease(addr unsafe.Pointer) {
-	runtime.RaceRelease(addr)
-}
-
-func raceReleaseMerge(addr unsafe.Pointer) {
-	runtime.RaceReleaseMerge(addr)
-}
-
-func raceDisable() {
-	runtime.RaceDisable()
-}
-
-func raceEnable() {
-	runtime.RaceEnable()
-}
-
-func raceRead(addr unsafe.Pointer) {
-	runtime.RaceRead(addr)
-}
-
-func raceWrite(addr unsafe.Pointer) {
-	runtime.RaceWrite(addr)
-}
diff --git a/src/sync/race0.go b/src/sync/race0.go
deleted file mode 100644
index 65ada1c..0000000
--- a/src/sync/race0.go
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2012 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.
-
-// +build !race
-
-package sync
-
-import (
-	"unsafe"
-)
-
-const raceenabled = false
-
-func raceAcquire(addr unsafe.Pointer) {
-}
-
-func raceRelease(addr unsafe.Pointer) {
-}
-
-func raceReleaseMerge(addr unsafe.Pointer) {
-}
-
-func raceDisable() {
-}
-
-func raceEnable() {
-}
-
-func raceRead(addr unsafe.Pointer) {
-}
-
-func raceWrite(addr unsafe.Pointer) {
-}
diff --git a/src/sync/rwmutex.go b/src/sync/rwmutex.go
index 0e8a58e..d438c93 100644
--- a/src/sync/rwmutex.go
+++ b/src/sync/rwmutex.go
@@ -5,6 +5,7 @@
 package sync
 
 import (
+	"internal/race"
 	"sync/atomic"
 	"unsafe"
 )
@@ -27,17 +28,17 @@ const rwmutexMaxReaders = 1 << 30
 
 // RLock locks rw for reading.
 func (rw *RWMutex) RLock() {
-	if raceenabled {
+	if race.Enabled {
 		_ = rw.w.state
-		raceDisable()
+		race.Disable()
 	}
 	if atomic.AddInt32(&rw.readerCount, 1) < 0 {
 		// A writer is pending, wait for it.
 		runtime_Semacquire(&rw.readerSem)
 	}
-	if raceenabled {
-		raceEnable()
-		raceAcquire(unsafe.Pointer(&rw.readerSem))
+	if race.Enabled {
+		race.Enable()
+		race.Acquire(unsafe.Pointer(&rw.readerSem))
 	}
 }
 
@@ -46,14 +47,14 @@ func (rw *RWMutex) RLock() {
 // It is a run-time error if rw is not locked for reading
 // on entry to RUnlock.
 func (rw *RWMutex) RUnlock() {
-	if raceenabled {
+	if race.Enabled {
 		_ = rw.w.state
-		raceReleaseMerge(unsafe.Pointer(&rw.writerSem))
-		raceDisable()
+		race.ReleaseMerge(unsafe.Pointer(&rw.writerSem))
+		race.Disable()
 	}
 	if r := atomic.AddInt32(&rw.readerCount, -1); r < 0 {
 		if r+1 == 0 || r+1 == -rwmutexMaxReaders {
-			raceEnable()
+			race.Enable()
 			panic("sync: RUnlock of unlocked RWMutex")
 		}
 		// A writer is pending.
@@ -62,8 +63,8 @@ func (rw *RWMutex) RUnlock() {
 			runtime_Semrelease(&rw.writerSem)
 		}
 	}
-	if raceenabled {
-		raceEnable()
+	if race.Enabled {
+		race.Enable()
 	}
 }
 
@@ -74,9 +75,9 @@ func (rw *RWMutex) RUnlock() {
 // a blocked Lock call excludes new readers from acquiring
 // the lock.
 func (rw *RWMutex) Lock() {
-	if raceenabled {
+	if race.Enabled {
 		_ = rw.w.state
-		raceDisable()
+		race.Disable()
 	}
 	// First, resolve competition with other writers.
 	rw.w.Lock()
@@ -86,10 +87,10 @@ func (rw *RWMutex) Lock() {
 	if r != 0 && atomic.AddInt32(&rw.readerWait, r) != 0 {
 		runtime_Semacquire(&rw.writerSem)
 	}
-	if raceenabled {
-		raceEnable()
-		raceAcquire(unsafe.Pointer(&rw.readerSem))
-		raceAcquire(unsafe.Pointer(&rw.writerSem))
+	if race.Enabled {
+		race.Enable()
+		race.Acquire(unsafe.Pointer(&rw.readerSem))
+		race.Acquire(unsafe.Pointer(&rw.writerSem))
 	}
 }
 
@@ -100,17 +101,17 @@ func (rw *RWMutex) Lock() {
 // goroutine.  One goroutine may RLock (Lock) an RWMutex and then
 // arrange for another goroutine to RUnlock (Unlock) it.
 func (rw *RWMutex) Unlock() {
-	if raceenabled {
+	if race.Enabled {
 		_ = rw.w.state
-		raceRelease(unsafe.Pointer(&rw.readerSem))
-		raceRelease(unsafe.Pointer(&rw.writerSem))
-		raceDisable()
+		race.Release(unsafe.Pointer(&rw.readerSem))
+		race.Release(unsafe.Pointer(&rw.writerSem))
+		race.Disable()
 	}
 
 	// Announce to readers there is no active writer.
 	r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders)
 	if r >= rwmutexMaxReaders {
-		raceEnable()
+		race.Enable()
 		panic("sync: Unlock of unlocked RWMutex")
 	}
 	// Unblock blocked readers, if any.
@@ -119,8 +120,8 @@ func (rw *RWMutex) Unlock() {
 	}
 	// Allow other writers to proceed.
 	rw.w.Unlock()
-	if raceenabled {
-		raceEnable()
+	if race.Enabled {
+		race.Enable()
 	}
 }
 
diff --git a/src/sync/waitgroup.go b/src/sync/waitgroup.go
index de399e6..c77fec3 100644
--- a/src/sync/waitgroup.go
+++ b/src/sync/waitgroup.go
@@ -5,6 +5,7 @@
 package sync
 
 import (
+	"internal/race"
 	"sync/atomic"
 	"unsafe"
 )
@@ -46,24 +47,24 @@ func (wg *WaitGroup) state() *uint64 {
 // See the WaitGroup example.
 func (wg *WaitGroup) Add(delta int) {
 	statep := wg.state()
-	if raceenabled {
+	if race.Enabled {
 		_ = *statep // trigger nil deref early
 		if delta < 0 {
 			// Synchronize decrements with Wait.
-			raceReleaseMerge(unsafe.Pointer(wg))
+			race.ReleaseMerge(unsafe.Pointer(wg))
 		}
-		raceDisable()
-		defer raceEnable()
+		race.Disable()
+		defer race.Enable()
 	}
 	state := atomic.AddUint64(statep, uint64(delta)<<32)
 	v := int32(state >> 32)
 	w := uint32(state)
-	if raceenabled {
+	if race.Enabled {
 		if delta > 0 && v == int32(delta) {
 			// The first increment must be synchronized with Wait.
 			// Need to model this as a read, because there can be
 			// several concurrent wg.counter transitions from 0.
-			raceRead(unsafe.Pointer(&wg.sema))
+			race.Read(unsafe.Pointer(&wg.sema))
 		}
 	}
 	if v < 0 {
@@ -98,9 +99,9 @@ func (wg *WaitGroup) Done() {
 // Wait blocks until the WaitGroup counter is zero.
 func (wg *WaitGroup) Wait() {
 	statep := wg.state()
-	if raceenabled {
+	if race.Enabled {
 		_ = *statep // trigger nil deref early
-		raceDisable()
+		race.Disable()
 	}
 	for {
 		state := atomic.LoadUint64(statep)
@@ -108,28 +109,28 @@ func (wg *WaitGroup) Wait() {
 		w := uint32(state)
 		if v == 0 {
 			// Counter is 0, no need to wait.
-			if raceenabled {
-				raceEnable()
-				raceAcquire(unsafe.Pointer(wg))
+			if race.Enabled {
+				race.Enable()
+				race.Acquire(unsafe.Pointer(wg))
 			}
 			return
 		}
 		// Increment waiters count.
 		if atomic.CompareAndSwapUint64(statep, state, state+1) {
-			if raceenabled && w == 0 {
+			if race.Enabled && w == 0 {
 				// Wait must be synchronized with the first Add.
 				// Need to model this is as a write to race with the read in Add.
 				// As a consequence, can do the write only for the first waiter,
 				// otherwise concurrent Waits will race with each other.
-				raceWrite(unsafe.Pointer(&wg.sema))
+				race.Write(unsafe.Pointer(&wg.sema))
 			}
 			runtime_Semacquire(&wg.sema)
 			if *statep != 0 {
 				panic("sync: WaitGroup is reused before previous Wait has returned")
 			}
-			if raceenabled {
-				raceEnable()
-				raceAcquire(unsafe.Pointer(wg))
+			if race.Enabled {
+				race.Enable()
+				race.Acquire(unsafe.Pointer(wg))
 			}
 			return
 		}
diff --git a/src/sync/waitgroup_test.go b/src/sync/waitgroup_test.go
index 3e3e3bf..8ec34fd 100644
--- a/src/sync/waitgroup_test.go
+++ b/src/sync/waitgroup_test.go
@@ -5,6 +5,7 @@
 package sync_test
 
 import (
+	"internal/race"
 	"runtime"
 	. "sync"
 	"sync/atomic"
@@ -48,7 +49,7 @@ func TestWaitGroup(t *testing.T) {
 }
 
 func knownRacy(t *testing.T) {
-	if RaceEnabled {
+	if race.Enabled {
 		t.Skip("skipping known-racy test under the race detector")
 	}
 }
@@ -127,13 +128,16 @@ func TestWaitGroupMisuse3(t *testing.T) {
 		}
 	}()
 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
-	done := make(chan interface{}, 1)
+	done := make(chan interface{}, 2)
 	// The detection is opportunistically, so we want it to panic
 	// at least in one run out of a million.
 	for i := 0; i < 1e6; i++ {
 		var wg WaitGroup
 		wg.Add(1)
 		go func() {
+			defer func() {
+				done <- recover()
+			}()
 			wg.Done()
 		}()
 		go func() {
@@ -149,8 +153,10 @@ func TestWaitGroupMisuse3(t *testing.T) {
 			wg.Wait()
 		}()
 		wg.Wait()
-		if err := <-done; err != nil {
-			panic(err)
+		for j := 0; j < 2; j++ {
+			if err := <-done; err != nil {
+				panic(err)
+			}
 		}
 	}
 	t.Fatal("Should panic")
diff --git a/src/syscall/asm_linux_386.s b/src/syscall/asm_linux_386.s
index ec7487b..c940605 100644
--- a/src/syscall/asm_linux_386.s
+++ b/src/syscall/asm_linux_386.s
@@ -12,6 +12,19 @@
 // func Syscall(trap uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr);
 // Trap # in AX, args in BX CX DX SI DI, return in AX
 
+// Most linux systems use glibc's dynamic linker, which puts the
+// __kernel_vsyscall vdso helper at 0x10(GS) for easy access from position
+// independent code and setldt in runtime does the same in the statically
+// linked case. Android, however, uses bionic's dynamic linker, which does not
+// save the helper anywhere, and so the only way to invoke a syscall from
+// position independent code is boring old int $0x80 (which is also what
+// bionic's syscall wrappers use).
+#ifdef GOOS_android
+#define INVOKE_SYSCALL	INT	$0x80
+#else
+#define INVOKE_SYSCALL	CALL	0x10(GS)
+#endif
+
 TEXT	·Syscall(SB),NOSPLIT,$0-28
 	CALL	runtime·entersyscall(SB)
 	MOVL	trap+0(FP), AX	// syscall entry
@@ -20,7 +33,7 @@ TEXT	·Syscall(SB),NOSPLIT,$0-28
 	MOVL	a3+12(FP), DX
 	MOVL	$0, SI
 	MOVL	$0,  DI
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	CMPL	AX, $0xfffff001
 	JLS	ok
 	MOVL	$-1, r1+16(FP)
@@ -46,7 +59,7 @@ TEXT	·Syscall6(SB),NOSPLIT,$0-40
 	MOVL	a4+16(FP), SI
 	MOVL	a5+20(FP), DI
 	MOVL	a6+24(FP), BP
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	CMPL	AX, $0xfffff001
 	JLS	ok6
 	MOVL	$-1, r1+28(FP)
@@ -70,7 +83,7 @@ TEXT ·RawSyscall(SB),NOSPLIT,$0-28
 	MOVL	a3+12(FP), DX
 	MOVL	$0, SI
 	MOVL	$0,  DI
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	CMPL	AX, $0xfffff001
 	JLS	ok1
 	MOVL	$-1, r1+16(FP)
@@ -93,7 +106,7 @@ TEXT	·RawSyscall6(SB),NOSPLIT,$0-40
 	MOVL	a4+16(FP), SI
 	MOVL	a5+20(FP), DI
 	MOVL	a6+24(FP), BP
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	CMPL	AX, $0xfffff001
 	JLS	ok2
 	MOVL	$-1, r1+28(FP)
@@ -119,7 +132,7 @@ TEXT ·socketcall(SB),NOSPLIT,$0-36
 	MOVL	$0, DX
 	MOVL	$0, SI
 	MOVL	$0,  DI
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	CMPL	AX, $0xfffff001
 	JLS	oksock
 	MOVL	$-1, n+28(FP)
@@ -142,7 +155,7 @@ TEXT ·rawsocketcall(SB),NOSPLIT,$0-36
 	MOVL	$0, DX
 	MOVL	$0, SI
 	MOVL	$0,  DI
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	CMPL	AX, $0xfffff001
 	JLS	oksock1
 	MOVL	$-1, n+28(FP)
@@ -168,7 +181,7 @@ TEXT ·seek(SB),NOSPLIT,$0-28
 	MOVL	offset_lo+4(FP), DX
 	LEAL	newoffset_lo+16(FP), SI	// result pointer
 	MOVL	whence+12(FP),  DI
-	CALL	*runtime·_vdso(SB)
+	INVOKE_SYSCALL
 	CMPL	AX, $0xfffff001
 	JLS	okseek
 	MOVL	$-1, newoffset_lo+16(FP)
diff --git a/src/syscall/asm_linux_mips64x.s b/src/syscall/asm_linux_mips64x.s
new file mode 100644
index 0000000..81717d2
--- /dev/null
+++ b/src/syscall/asm_linux_mips64x.s
@@ -0,0 +1,104 @@
+// 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.
+
+// +build linux
+// +build mips64 mips64le
+
+#include "textflag.h"
+
+//
+// System calls for mips64, Linux
+//
+
+// func Syscall(trap int64, a1, a2, a3 int64) (r1, r2, err int64);
+
+TEXT	·Syscall(SB),NOSPLIT,$0-56
+	JAL	runtime·entersyscall(SB)
+	MOVV	a1+8(FP), R4
+	MOVV	a2+16(FP), R5
+	MOVV	a3+24(FP), R6
+	MOVV	R0, R7
+	MOVV	R0, R8
+	MOVV	R0, R9
+	MOVV	trap+0(FP), R2	// syscall entry
+	SYSCALL
+	BEQ	R7, ok
+	MOVV	$-1, R1
+	MOVV	R1, r1+32(FP)	// r1
+	MOVV	R0, r2+40(FP)	// r2
+	MOVV	R2, err+48(FP)	// errno
+	JAL	runtime·exitsyscall(SB)
+	RET
+ok:
+	MOVV	R2, r1+32(FP)	// r1
+	MOVV	R3, r2+40(FP)	// r2
+	MOVV	R0, err+48(FP)	// errno
+	JAL	runtime·exitsyscall(SB)
+	RET
+
+TEXT ·Syscall6(SB),NOSPLIT,$0-80
+	JAL	runtime·entersyscall(SB)
+	MOVV	a1+8(FP), R4
+	MOVV	a2+16(FP), R5
+	MOVV	a3+24(FP), R6
+	MOVV	a4+32(FP), R7
+	MOVV	a5+40(FP), R8
+	MOVV	a6+48(FP), R9
+	MOVV	trap+0(FP), R2	// syscall entry
+	SYSCALL
+	BEQ	R7, ok6
+	MOVV	$-1, R1
+	MOVV	R1, r1+56(FP)	// r1
+	MOVV	R0, r2+64(FP)	// r2
+	MOVV	R2, err+72(FP)	// errno
+	JAL	runtime·exitsyscall(SB)
+	RET
+ok6:
+	MOVV	R2, r1+56(FP)	// r1
+	MOVV	R3, r2+64(FP)	// r2
+	MOVV	R0, err+72(FP)	// errno
+	JAL	runtime·exitsyscall(SB)
+	RET
+
+TEXT ·RawSyscall(SB),NOSPLIT,$0-56
+	MOVV	a1+8(FP), R4
+	MOVV	a2+16(FP), R5
+	MOVV	a3+24(FP), R6
+	MOVV	R0, R7
+	MOVV	R0, R8
+	MOVV	R0, R9
+	MOVV	trap+0(FP), R2	// syscall entry
+	SYSCALL
+	BEQ	R7, ok1
+	MOVV	$-1, R1
+	MOVV	R1, r1+32(FP)	// r1
+	MOVV	R0, r2+40(FP)	// r2
+	MOVV	R2, err+48(FP)	// errno
+	RET
+ok1:
+	MOVV	R2, r1+32(FP)	// r1
+	MOVV	R3, r2+40(FP)	// r2
+	MOVV	R0, err+48(FP)	// errno
+	RET
+
+TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
+	MOVV	a1+8(FP), R4
+	MOVV	a2+16(FP), R5
+	MOVV	a3+24(FP), R6
+	MOVV	a4+32(FP), R7
+	MOVV	a5+40(FP), R8
+	MOVV	a6+48(FP), R9
+	MOVV	trap+0(FP), R2	// syscall entry
+	SYSCALL
+	BEQ	R7, ok2
+	MOVV	$-1, R1
+	MOVV	R1, r1+56(FP)	// r1
+	MOVV	R0, r2+64(FP)	// r2
+	MOVV	R2, err+72(FP)	// errno
+	RET
+ok2:
+	MOVV	R2, r1+56(FP)	// r1
+	MOVV	R3, r2+64(FP)	// r2
+	MOVV	R0, err+72(FP)	// errno
+	RET
diff --git a/src/syscall/asm_solaris_amd64.s b/src/syscall/asm_solaris_amd64.s
index cc69caa..2547cdb 100644
--- a/src/syscall/asm_solaris_amd64.s
+++ b/src/syscall/asm_solaris_amd64.s
@@ -23,15 +23,6 @@ TEXT ·chroot1(SB),NOSPLIT,$0
 TEXT ·close(SB),NOSPLIT,$0
 	JMP	runtime·syscall_close(SB)
 
-TEXT ·dlopen(SB),NOSPLIT,$0
-	JMP	runtime·syscall_dlopen(SB)
-
-TEXT ·dlclose(SB),NOSPLIT,$0
-	JMP	runtime·syscall_dlclose(SB)
-
-TEXT ·dlsym(SB),NOSPLIT,$0
-	JMP	runtime·syscall_dlsym(SB)
-
 TEXT ·execve(SB),NOSPLIT,$0
 	JMP	runtime·syscall_execve(SB)
 
diff --git a/src/syscall/dll_windows.go b/src/syscall/dll_windows.go
index c157e6d..3cf4b1b 100644
--- a/src/syscall/dll_windows.go
+++ b/src/syscall/dll_windows.go
@@ -115,7 +115,7 @@ func (p *Proc) Addr() uintptr {
 	return p.addr
 }
 
-// Call executes procedure p with arguments a. It will panic, if more then 15 arguments
+// Call executes procedure p with arguments a. It will panic, if more than 15 arguments
 // are supplied.
 //
 // The returned error is always non-nil, constructed from the result of GetLastError.
@@ -267,7 +267,7 @@ func (p *LazyProc) Addr() uintptr {
 	return p.proc.Addr()
 }
 
-// Call executes procedure p with arguments a. It will panic, if more then 15 arguments
+// Call executes procedure p with arguments a. It will panic, if more than 15 arguments
 // are supplied.
 //
 // The returned error is always non-nil, constructed from the result of GetLastError.
diff --git a/src/syscall/errors_plan9.go b/src/syscall/errors_plan9.go
index ede3d6a..d7634c9 100644
--- a/src/syscall/errors_plan9.go
+++ b/src/syscall/errors_plan9.go
@@ -46,3 +46,13 @@ var (
 	EACCES       = NewError("access permission denied")
 	EAFNOSUPPORT = NewError("address family not supported by protocol")
 )
+
+// Notes
+const (
+	SIGABRT = Note("abort")
+	SIGALRM = Note("alarm")
+	SIGHUP  = Note("hangup")
+	SIGINT  = Note("interrupt")
+	SIGKILL = Note("kill")
+	SIGTERM = Note("interrupt")
+)
diff --git a/src/syscall/exec_bsd.go b/src/syscall/exec_bsd.go
index 4b5774b..d182896 100644
--- a/src/syscall/exec_bsd.go
+++ b/src/syscall/exec_bsd.go
@@ -37,6 +37,7 @@ func runtime_AfterFork()
 // For the same reason compiler does not race instrument it.
 // The calls to RawSyscall are okay because they are assembly
 // functions that do not grow the stack.
+//go:norace
 func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
 	// Declare all variables at top in case any
 	// declarations require heap allocation (e.g., err1).
diff --git a/src/syscall/exec_linux.go b/src/syscall/exec_linux.go
index 9bac042..3e08d43 100644
--- a/src/syscall/exec_linux.go
+++ b/src/syscall/exec_linux.go
@@ -53,6 +53,7 @@ func runtime_AfterFork()
 // For the same reason compiler does not race instrument it.
 // The calls to RawSyscall are okay because they are assembly
 // functions that do not grow the stack.
+//go:norace
 func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
 	// Declare all variables at top in case any
 	// declarations require heap allocation (e.g., err1).
@@ -191,13 +192,12 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
 	// User and groups
 	if cred := sys.Credential; cred != nil {
 		ngroups := uintptr(len(cred.Groups))
-		var groups unsafe.Pointer
 		if ngroups > 0 {
-			groups = unsafe.Pointer(&cred.Groups[0])
-		}
-		_, _, err1 = RawSyscall(SYS_SETGROUPS, ngroups, uintptr(groups), 0)
-		if err1 != 0 {
-			goto childerror
+			groups := unsafe.Pointer(&cred.Groups[0])
+			_, _, err1 = RawSyscall(SYS_SETGROUPS, ngroups, uintptr(groups), 0)
+			if err1 != 0 {
+				goto childerror
+			}
 		}
 		_, _, err1 = RawSyscall(SYS_SETGID, uintptr(cred.Gid), 0, 0)
 		if err1 != 0 {
diff --git a/src/syscall/exec_linux_test.go b/src/syscall/exec_linux_test.go
index 60d2734..6d31941 100644
--- a/src/syscall/exec_linux_test.go
+++ b/src/syscall/exec_linux_test.go
@@ -10,13 +10,22 @@ import (
 	"io/ioutil"
 	"os"
 	"os/exec"
-	"regexp"
-	"strconv"
 	"strings"
 	"syscall"
 	"testing"
 )
 
+// Check if we are in a chroot by checking if the inode of / is
+// different from 2 (there is no better test available to non-root on
+// linux).
+func isChrooted(t *testing.T) bool {
+	root, err := os.Stat("/")
+	if err != nil {
+		t.Fatalf("cannot stat /: %v", err)
+	}
+	return root.Sys().(*syscall.Stat_t).Ino != 2
+}
+
 func whoamiCmd(t *testing.T, uid, gid int, setgroups bool) *exec.Cmd {
 	if _, err := os.Stat("/proc/self/ns/user"); err != nil {
 		if os.IsNotExist(err) {
@@ -24,6 +33,26 @@ func whoamiCmd(t *testing.T, uid, gid int, setgroups bool) *exec.Cmd {
 		}
 		t.Fatalf("Failed to stat /proc/self/ns/user: %v", err)
 	}
+	if isChrooted(t) {
+		// create_user_ns in the kernel (see
+		// https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/kernel/user_namespace.c)
+		// forbids the creation of user namespaces when chrooted.
+		t.Skip("cannot create user namespaces when chrooted")
+	}
+	// On some systems, there is a sysctl setting.
+	if os.Getuid() != 0 {
+		data, errRead := ioutil.ReadFile("/proc/sys/kernel/unprivileged_userns_clone")
+		if errRead == nil && data[0] == '0' {
+			t.Skip("kernel prohibits user namespace in unprivileged process")
+		}
+	}
+	// When running under the Go continuous build, skip tests for
+	// now when under Kubernetes. (where things are root but not quite)
+	// Both of these are our own environment variables.
+	// See Issue 12815.
+	if os.Getenv("GO_BUILDER_NAME") != "" && os.Getenv("IN_KUBERNETES") == "1" {
+		t.Skip("skipping test on Kubernetes-based builders; see Issue 12815")
+	}
 	cmd := exec.Command("whoami")
 	cmd.SysProcAttr = &syscall.SysProcAttr{
 		Cloneflags: syscall.CLONE_NEWUSER,
@@ -42,14 +71,6 @@ func testNEWUSERRemap(t *testing.T, uid, gid int, setgroups bool) {
 	cmd := whoamiCmd(t, uid, gid, setgroups)
 	out, err := cmd.CombinedOutput()
 	if err != nil {
-		// On some systems, there is a sysctl setting.
-		if os.IsPermission(err) && os.Getuid() != 0 {
-			data, errRead := ioutil.ReadFile("/proc/sys/kernel/unprivileged_userns_clone")
-			if errRead == nil && data[0] == '0' {
-				t.Skip("kernel prohibits user namespace in unprivileged process")
-			}
-		}
-
 		t.Fatalf("Cmd failed with err %v, output: %s", err, out)
 	}
 	sout := strings.TrimSpace(string(out))
@@ -73,22 +94,6 @@ func TestCloneNEWUSERAndRemapRootEnableSetgroups(t *testing.T) {
 	testNEWUSERRemap(t, 0, 0, false)
 }
 
-// kernelVersion returns the major and minor versions of the Linux
-// kernel version.  It calls t.Skip if it can't figure it out.
-func kernelVersion(t *testing.T) (int, int) {
-	bytes, err := ioutil.ReadFile("/proc/version")
-	if err != nil {
-		t.Skipf("can't get kernel version: %v", err)
-	}
-	matches := regexp.MustCompile("([0-9]+).([0-9]+)").FindSubmatch(bytes)
-	if len(matches) < 3 {
-		t.Skipf("can't get kernel version from %s", bytes)
-	}
-	major, _ := strconv.Atoi(string(matches[1]))
-	minor, _ := strconv.Atoi(string(matches[2]))
-	return major, minor
-}
-
 func TestCloneNEWUSERAndRemapNoRootDisableSetgroups(t *testing.T) {
 	if os.Getuid() == 0 {
 		t.Skip("skipping unprivileged user only test")
@@ -109,3 +114,11 @@ func TestCloneNEWUSERAndRemapNoRootSetgroupsEnableSetgroups(t *testing.T) {
 		t.Fatalf("Unprivileged gid_map rewriting with GidMappingsEnableSetgroups must fail")
 	}
 }
+
+func TestEmptyCredGroupsDisableSetgroups(t *testing.T) {
+	cmd := whoamiCmd(t, os.Getuid(), os.Getgid(), false)
+	cmd.SysProcAttr.Credential = &syscall.Credential{}
+	if err := cmd.Run(); err != nil {
+		t.Fatal(err)
+	}
+}
diff --git a/src/syscall/exec_plan9.go b/src/syscall/exec_plan9.go
index 7a415fd..d342cb0 100644
--- a/src/syscall/exec_plan9.go
+++ b/src/syscall/exec_plan9.go
@@ -173,6 +173,7 @@ func init() {
 // no rescheduling, no malloc calls, and no new stack segments.
 // The calls to RawSyscall are okay because they are assembly
 // functions that do not grow the stack.
+//go:norace
 func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, dir *byte, attr *ProcAttr, fdsToClose []int, pipe int, rflag int) (pid int, err error) {
 	// Declare all variables at top in case any
 	// declarations require heap allocation (e.g., errbuf).
@@ -218,10 +219,7 @@ func forkAndExecInChild(argv0 *byte, argv []*byte, envv []envItem, dir *byte, at
 
 	// Close fds we don't need.
 	for i = 0; i < len(fdsToClose); i++ {
-		r1, _, _ = RawSyscall(SYS_CLOSE, uintptr(fdsToClose[i]), 0, 0)
-		if int32(r1) == -1 {
-			goto childerror
-		}
+		RawSyscall(SYS_CLOSE, uintptr(fdsToClose[i]), 0, 0)
 	}
 
 	if envv != nil {
diff --git a/src/syscall/exec_solaris.go b/src/syscall/exec_solaris.go
index 3e949f1..63fa848 100644
--- a/src/syscall/exec_solaris.go
+++ b/src/syscall/exec_solaris.go
@@ -52,6 +52,7 @@ func write1(fd uintptr, buf uintptr, nbyte uintptr) (n uintptr, err Errno)
 // because we need to avoid lazy-loading the functions (might malloc,
 // split the stack, or acquire mutexes). We can't call RawSyscall
 // because it's not safe even for BSD-subsystem calls.
+//go:norace
 func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err Errno) {
 	// Declare all variables at top in case any
 	// declarations require heap allocation (e.g., err1).
diff --git a/src/syscall/mkerrors.sh b/src/syscall/mkerrors.sh
index 438de6e..b59a46b 100755
--- a/src/syscall/mkerrors.sh
+++ b/src/syscall/mkerrors.sh
@@ -13,6 +13,11 @@ export LC_CTYPE=C
 
 CC=${CC:-gcc}
 
+if [[ "$GOOS" -eq "solaris" ]]; then
+	# Assumes GNU versions of utilities in PATH.
+	export PATH=/usr/gnu/bin:$PATH
+fi
+
 uname=$(uname)
 
 includes_Darwin='
@@ -195,6 +200,7 @@ includes_OpenBSD='
 '
 
 includes_SunOS='
+#include <limits.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
diff --git a/src/syscall/mksyscall_solaris.pl b/src/syscall/mksyscall_solaris.pl
index f5eb4b3..cd69ebc 100755
--- a/src/syscall/mksyscall_solaris.pl
+++ b/src/syscall/mksyscall_solaris.pl
@@ -38,6 +38,11 @@ if($ARGV[0] =~ /^-/) {
 	exit 1;
 }
 
+if($ENV{'GOARCH'} eq "" || $ENV{'GOOS'} eq "") {
+	print STDERR "GOARCH or GOOS not defined in environment\n";
+	exit 1;
+}
+
 sub parseparamlist($) {
 	my ($list) = @_;
 	$list =~ s/^\s*//;
@@ -60,9 +65,9 @@ sub parseparam($) {
 
 my $package = "";
 my $text = "";
-my $vars = "";
 my $dynimports = "";
 my $linknames = "";
+my @vars = ();
 while(<>) {
 	chomp;
 	s/\s+/ /g;
@@ -100,20 +105,19 @@ while(<>) {
 	}
 
 	# System call pointer variable name.
-	my $sysvarname = "libc_$sysname";
+	my $sysvarname = "libc_${sysname}";
 
 	my $strconvfunc = "BytePtrFromString";
 	my $strconvtype = "*byte";
 
-	# Library proc address variable.
 	$sysname =~ y/A-Z/a-z/; # All libc functions are lowercase.
-	if($vars eq "") {
-		$vars .= "\t$sysvarname";
-	} else {
-		$vars .= ",\n\t$sysvarname";
-	}
-	$dynimports .= "//go:cgo_import_dynamic $sysvarname $sysname \"$modname.so\"\n";
-	$linknames .= "//go:linkname $sysvarname $sysvarname\n";
+
+	# Runtime import of function to allow cross-platform builds.
+	$dynimports .= "//go:cgo_import_dynamic ${sysvarname} ${sysname} \"$modname.so\"\n";
+	# Link symbol to proc address variable.
+	$linknames .= "//go:linkname ${sysvarname} ${sysvarname}\n";
+	# Library proc address variable.
+	push @vars, $sysvarname;
 
 	# Go function header.
 	$out = join(', ', @out);
@@ -264,6 +268,8 @@ print <<EOF;
 // $cmdline
 // MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
 
+// +build $ENV{'GOARCH'},$ENV{'GOOS'}
+
 package $package
 
 import "unsafe"
@@ -271,17 +277,20 @@ EOF
 
 print "import \"syscall\"\n" if $package ne "syscall";
 
-print <<EOF;
+my $vardecls = "\t" . join(",\n\t", @vars);
+$vardecls .= " libcFunc";
+
+chomp($_=<<EOF);
 
 $dynimports
 $linknames
 type libcFunc uintptr
 
 var (
-$vars libcFunc
+$vardecls
 )
 
 $text
-
 EOF
+print $_;
 exit 0;
diff --git a/src/syscall/mksysnum_plan9.sh b/src/syscall/mksysnum_plan9.sh
index fc619f0..cd29dd5 100755
--- a/src/syscall/mksysnum_plan9.sh
+++ b/src/syscall/mksysnum_plan9.sh
@@ -1,8 +1,6 @@
 #!/bin/sh
 # Copyright 2009 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.# Copyright 2009 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.
 
 COMMAND="mksysnum_plan9.sh $@"
diff --git a/src/syscall/msan.go b/src/syscall/msan.go
new file mode 100644
index 0000000..edd8d1e
--- /dev/null
+++ b/src/syscall/msan.go
@@ -0,0 +1,22 @@
+// Copyright 2015 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.
+
+// +build msan
+
+package syscall
+
+import (
+	"runtime"
+	"unsafe"
+)
+
+const msanenabled = true
+
+func msanRead(addr unsafe.Pointer, len int) {
+	runtime.MSanRead(addr, len)
+}
+
+func msanWrite(addr unsafe.Pointer, len int) {
+	runtime.MSanWrite(addr, len)
+}
diff --git a/src/syscall/msan0.go b/src/syscall/msan0.go
new file mode 100644
index 0000000..7617494
--- /dev/null
+++ b/src/syscall/msan0.go
@@ -0,0 +1,19 @@
+// Copyright 2015 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.
+
+// +build !msan
+
+package syscall
+
+import (
+	"unsafe"
+)
+
+const msanenabled = false
+
+func msanRead(addr unsafe.Pointer, len int) {
+}
+
+func msanWrite(addr unsafe.Pointer, len int) {
+}
diff --git a/src/syscall/net_nacl.go b/src/syscall/net_nacl.go
index b5cb530..d3378f9 100644
--- a/src/syscall/net_nacl.go
+++ b/src/syscall/net_nacl.go
@@ -526,8 +526,8 @@ func (f *netFile) listen(backlog int) error {
 	if f.listener != nil {
 		return EINVAL
 	}
-	_, ok := net.listener[netAddr{f.proto, f.sotype, f.addr.key()}]
-	if ok {
+	old, ok := net.listener[netAddr{f.proto, f.sotype, f.addr.key()}]
+	if ok && !old.listenerClosed() {
 		return EADDRINUSE
 	}
 	net.listener[netAddr{f.proto, f.sotype, f.addr.key()}] = f
@@ -577,7 +577,7 @@ func (f *netFile) connect(sa Sockaddr) error {
 		return EISCONN
 	}
 	l, ok := net.listener[netAddr{f.proto, f.sotype, sa.key()}]
-	if !ok {
+	if !ok || l.listenerClosed() {
 		net.Unlock()
 		return ECONNREFUSED
 	}
@@ -676,6 +676,12 @@ func (f *netFile) sendto(p []byte, flags int, to Sockaddr) error {
 	return nil
 }
 
+func (f *netFile) listenerClosed() bool {
+	f.listener.Lock()
+	defer f.listener.Unlock()
+	return f.listener.closed
+}
+
 func (f *netFile) close() error {
 	if f.listener != nil {
 		f.listener.close()
diff --git a/src/syscall/race.go b/src/syscall/race.go
deleted file mode 100644
index e69c111..0000000
--- a/src/syscall/race.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2012 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.
-
-// +build race
-
-package syscall
-
-import (
-	"runtime"
-	"unsafe"
-)
-
-const raceenabled = true
-
-func raceAcquire(addr unsafe.Pointer) {
-	runtime.RaceAcquire(addr)
-}
-
-func raceReleaseMerge(addr unsafe.Pointer) {
-	runtime.RaceReleaseMerge(addr)
-}
-
-func raceReadRange(addr unsafe.Pointer, len int) {
-	runtime.RaceReadRange(addr, len)
-}
-
-func raceWriteRange(addr unsafe.Pointer, len int) {
-	runtime.RaceWriteRange(addr, len)
-}
diff --git a/src/syscall/race0.go b/src/syscall/race0.go
deleted file mode 100644
index b02f882..0000000
--- a/src/syscall/race0.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2012 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.
-
-// +build !race
-
-package syscall
-
-import (
-	"unsafe"
-)
-
-const raceenabled = false
-
-func raceAcquire(addr unsafe.Pointer) {
-}
-
-func raceReleaseMerge(addr unsafe.Pointer) {
-}
-
-func raceReadRange(addr unsafe.Pointer, len int) {
-}
-
-func raceWriteRange(addr unsafe.Pointer, len int) {
-}
diff --git a/src/syscall/route_bsd.go b/src/syscall/route_bsd.go
index c62fdc3..c635a13 100644
--- a/src/syscall/route_bsd.go
+++ b/src/syscall/route_bsd.go
@@ -44,6 +44,9 @@ func rsaAlignOf(salen int) int {
 
 // parseSockaddrLink parses b as a datalink socket address.
 func parseSockaddrLink(b []byte) (*SockaddrDatalink, error) {
+	if len(b) < 8 {
+		return nil, EINVAL
+	}
 	sa, _, err := parseLinkLayerAddr(b[4:])
 	if err != nil {
 		return nil, err
@@ -77,16 +80,16 @@ func parseLinkLayerAddr(b []byte) (*SockaddrDatalink, int, error) {
 		Slen byte
 	}
 	lla := (*linkLayerAddr)(unsafe.Pointer(&b[0]))
-	l := rsaAlignOf(int(4 + lla.Nlen + lla.Alen + lla.Slen))
+	l := 4 + int(lla.Nlen) + int(lla.Alen) + int(lla.Slen)
 	if len(b) < l {
 		return nil, 0, EINVAL
 	}
 	b = b[4:]
 	sa := &SockaddrDatalink{Type: lla.Type, Nlen: lla.Nlen, Alen: lla.Alen, Slen: lla.Slen}
-	for i := 0; len(sa.Data) > i && i < int(lla.Nlen+lla.Alen+lla.Slen); i++ {
+	for i := 0; len(sa.Data) > i && i < l-4; i++ {
 		sa.Data[i] = int8(b[i])
 	}
-	return sa, l, nil
+	return sa, rsaAlignOf(l), nil
 }
 
 // parseSockaddrInet parses b as an internet socket address.
@@ -336,7 +339,7 @@ func ParseRoutingMessage(b []byte) (msgs []RoutingMessage, err error) {
 	return msgs, nil
 }
 
-// ParseRoutingMessage parses msg's payload as raw sockaddrs and
+// ParseRoutingSockaddr parses msg's payload as raw sockaddrs and
 // returns the slice containing the Sockaddr interfaces.
 func ParseRoutingSockaddr(msg RoutingMessage) ([]Sockaddr, error) {
 	sas, err := msg.sockaddr()
diff --git a/src/syscall/route_bsd_test.go b/src/syscall/route_bsd_test.go
index 8617663..74d11f9 100644
--- a/src/syscall/route_bsd_test.go
+++ b/src/syscall/route_bsd_test.go
@@ -119,6 +119,41 @@ func TestRouteMonitor(t *testing.T) {
 	<-tmo
 }
 
+var parseInterfaceMessageTests = []*syscall.InterfaceMessage{
+	// with link-layer address
+	{
+		Header: syscall.IfMsghdr{Version: syscall.RTM_VERSION, Addrs: syscall.RTA_IFP},
+		Data: []uint8{
+			0x11, 0x12, 0x2, 0x0, 0x6, 0x3, 0x6, 0x0,
+			0x77, 0x6d, 0x31, 0x01, 0x23, 0x45, 0xab, 0xcd,
+			0xef, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+		},
+	},
+	// without link-layer address
+	{
+		Header: syscall.IfMsghdr{Version: syscall.RTM_VERSION, Addrs: syscall.RTA_IFP},
+		Data: []uint8{
+			0xe, 0x12, 0x4, 0x0, 0xf5, 0x6, 0x0, 0x0,
+			0x70, 0x66, 0x6c, 0x6f, 0x67, 0x30, 0x0, 0x0,
+		},
+	},
+	// no data
+	{
+		Header: syscall.IfMsghdr{Version: syscall.RTM_VERSION, Addrs: syscall.RTA_IFP},
+		Data: []uint8{
+			0x8, 0xa, 0xb, 0xc, 0xd, 0x0, 0x0, 0x0,
+		},
+	},
+}
+
+func TestParseInterfaceMessage(t *testing.T) {
+	for i, tt := range parseInterfaceMessageTests {
+		if _, err := syscall.ParseRoutingSockaddr(tt); err != nil {
+			t.Errorf("#%d: %v", i, err)
+		}
+	}
+}
+
 type addrFamily byte
 
 func (f addrFamily) String() string {
diff --git a/src/syscall/sockcmsg_unix.go b/src/syscall/sockcmsg_unix.go
index 045a012..4724275 100644
--- a/src/syscall/sockcmsg_unix.go
+++ b/src/syscall/sockcmsg_unix.go
@@ -77,10 +77,10 @@ func UnixRights(fds ...int) []byte {
 	h.Level = SOL_SOCKET
 	h.Type = SCM_RIGHTS
 	h.SetLen(CmsgLen(datalen))
-	data := uintptr(cmsgData(h))
+	data := cmsgData(h)
 	for _, fd := range fds {
-		*(*int32)(unsafe.Pointer(data)) = int32(fd)
-		data += 4
+		*(*int32)(data) = int32(fd)
+		data = unsafe.Pointer(uintptr(data) + 4)
 	}
 	return b
 }
diff --git a/src/syscall/srpc_nacl.go b/src/syscall/srpc_nacl.go
deleted file mode 100644
index dd07373..0000000
--- a/src/syscall/srpc_nacl.go
+++ /dev/null
@@ -1,822 +0,0 @@
-// Copyright 2013 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.
-
-// Native Client SRPC message passing.
-// This code is needed to invoke SecureRandom, the NaCl equivalent of /dev/random.
-
-package syscall
-
-import (
-	"errors"
-	"sync"
-	"unsafe"
-)
-
-// An srpcClient represents the client side of an SRPC connection.
-type srpcClient struct {
-	fd      int // to server
-	r       msgReceiver
-	s       msgSender
-	service map[string]srpcService // services by name
-
-	outMu sync.Mutex // protects writing to connection
-
-	mu      sync.Mutex // protects following fields
-	muxer   bool       // is someone reading and muxing responses
-	pending map[uint32]*srpc
-	idGen   uint32 // generator for request IDs
-}
-
-// An srpcService is a single method that the server offers.
-type srpcService struct {
-	num uint32 // method number
-	fmt string // argument format; see "parsing of RPC messages" below
-}
-
-// An srpc represents a single srpc issued by a client.
-type srpc struct {
-	Ret  []interface{}
-	Done chan *srpc
-	Err  error
-	c    *srpcClient
-	id   uint32
-}
-
-// newClient allocates a new SRPC client using the file descriptor fd.
-func newClient(fd int) (*srpcClient, error) {
-	c := new(srpcClient)
-	c.fd = fd
-	c.r.fd = fd
-	c.s.fd = fd
-	c.service = make(map[string]srpcService)
-	c.pending = make(map[uint32]*srpc)
-
-	// service discovery request
-	m := &msg{
-		isRequest: 1,
-		template:  []interface{}{[]byte(nil)},
-		size:      []int{4000}, // max size to accept for returned byte slice
-	}
-	if err := m.pack(); err != nil {
-		return nil, errors.New("Native Client SRPC service_discovery: preparing request: " + err.Error())
-	}
-	c.s.send(m)
-	m, err := c.r.recv()
-	if err != nil {
-		return nil, err
-	}
-	m.unpack()
-	if m.status != uint32(srpcOK) {
-		return nil, errors.New("Native Client SRPC service_discovery: " + srpcErrno(m.status).Error())
-	}
-	list := m.value[0].([]byte)
-	var n uint32
-	for len(list) > 0 {
-		var line []byte
-		i := byteIndex(list, '\n')
-		if i < 0 {
-			line, list = list, nil
-		} else {
-			line, list = list[:i], list[i+1:]
-		}
-		i = byteIndex(line, ':')
-		if i >= 0 {
-			c.service[string(line)] = srpcService{n, string(line[i+1:])}
-		}
-		n++
-	}
-
-	return c, nil
-}
-
-func byteIndex(b []byte, c byte) int {
-	for i, bi := range b {
-		if bi == c {
-			return i
-		}
-	}
-	return -1
-}
-
-var yourTurn srpc
-
-func (c *srpcClient) wait(r *srpc) {
-	var rx *srpc
-	for rx = range r.Done {
-		if rx != &yourTurn {
-			break
-		}
-		c.input()
-	}
-	return
-}
-
-func (c *srpcClient) input() {
-	// read message
-	m, err := c.r.recv()
-	if err != nil {
-		println("Native Client SRPC receive error:", err.Error())
-		return
-	}
-	if m.unpack(); m.status != uint32(srpcOK) {
-		println("Native Client SRPC receive error: invalid message: ", srpcErrno(m.status).Error())
-		return
-	}
-
-	// deliver to intended recipient
-	c.mu.Lock()
-	rpc, ok := c.pending[m.id]
-	if ok {
-		delete(c.pending, m.id)
-	}
-
-	// wake a new muxer if there are more RPCs to read
-	c.muxer = false
-	for _, rpc := range c.pending {
-		c.muxer = true
-		rpc.Done <- &yourTurn
-		break
-	}
-	c.mu.Unlock()
-	if !ok {
-		println("Native Client: unexpected response for ID", m.id)
-		return
-	}
-	rpc.Ret = m.value
-	rpc.Done <- rpc
-}
-
-// Wait blocks until the RPC has finished.
-func (r *srpc) Wait() {
-	r.c.wait(r)
-}
-
-// Start issues an RPC request for method name with the given arguments.
-// The RPC r must not be in use for another pending request.
-// To wait for the RPC to finish, receive from r.Done and then
-// inspect r.Ret and r.Errno.
-func (r *srpc) Start(name string, arg []interface{}) {
-	r.Err = nil
-	r.c.mu.Lock()
-	srv, ok := r.c.service[name]
-	if !ok {
-		r.c.mu.Unlock()
-		r.Err = srpcErrBadRPCNumber
-		r.Done <- r
-		return
-	}
-	r.c.pending[r.id] = r
-	if !r.c.muxer {
-		r.c.muxer = true
-		r.Done <- &yourTurn
-	}
-	r.c.mu.Unlock()
-
-	var m msg
-	m.id = r.id
-	m.isRequest = 1
-	m.rpc = srv.num
-	m.value = arg
-
-	// Fill in the return values and sizes to generate
-	// the right type chars.  We'll take most any size.
-
-	// Skip over input arguments.
-	// We could check them against arg, but the server
-	// will do that anyway.
-	i := 0
-	for srv.fmt[i] != ':' {
-		i++
-	}
-	format := srv.fmt[i+1:]
-
-	// Now the return prototypes.
-	m.template = make([]interface{}, len(format))
-	m.size = make([]int, len(format))
-	for i := 0; i < len(format); i++ {
-		switch format[i] {
-		default:
-			println("Native Client SRPC: unexpected service type " + string(format[i]))
-			r.Err = srpcErrBadRPCNumber
-			r.Done <- r
-			return
-		case 'b':
-			m.template[i] = false
-		case 'C':
-			m.template[i] = []byte(nil)
-			m.size[i] = 1 << 30
-		case 'd':
-			m.template[i] = float64(0)
-		case 'D':
-			m.template[i] = []float64(nil)
-			m.size[i] = 1 << 30
-		case 'h':
-			m.template[i] = int(-1)
-		case 'i':
-			m.template[i] = int32(0)
-		case 'I':
-			m.template[i] = []int32(nil)
-			m.size[i] = 1 << 30
-		case 's':
-			m.template[i] = ""
-			m.size[i] = 1 << 30
-		}
-	}
-
-	if err := m.pack(); err != nil {
-		r.Err = errors.New("Native Client RPC Start " + name + ": preparing request: " + err.Error())
-		r.Done <- r
-		return
-	}
-
-	r.c.outMu.Lock()
-	r.c.s.send(&m)
-	r.c.outMu.Unlock()
-}
-
-// Call is a convenience wrapper that starts the RPC request,
-// waits for it to finish, and then returns the results.
-// Its implementation is:
-//
-//	r.Start(name, arg)
-//	r.Wait()
-//	return r.Ret, r.Errno
-//
-func (c *srpcClient) Call(name string, arg ...interface{}) (ret []interface{}, err error) {
-	r := c.NewRPC(nil)
-	r.Start(name, arg)
-	r.Wait()
-	return r.Ret, r.Err
-}
-
-// NewRPC creates a new RPC on the client connection.
-func (c *srpcClient) NewRPC(done chan *srpc) *srpc {
-	if done == nil {
-		done = make(chan *srpc, 1)
-	}
-	c.mu.Lock()
-	id := c.idGen
-	c.idGen++
-	c.mu.Unlock()
-	return &srpc{Done: done, c: c, id: id}
-}
-
-// The current protocol number.
-// Kind of useless, since there have been backwards-incompatible changes
-// to the wire protocol that did not update the protocol number.
-// At this point it's really just a sanity check.
-const protocol = 0xc0da0002
-
-// An srpcErrno is an SRPC status code.
-type srpcErrno uint32
-
-const (
-	srpcOK srpcErrno = 256 + iota
-	srpcErrBreak
-	srpcErrMessageTruncated
-	srpcErrNoMemory
-	srpcErrProtocolMismatch
-	srpcErrBadRPCNumber
-	srpcErrBadArgType
-	srpcErrTooFewArgs
-	srpcErrTooManyArgs
-	srpcErrInArgTypeMismatch
-	srpcErrOutArgTypeMismatch
-	srpcErrInternalError
-	srpcErrAppError
-)
-
-var srpcErrstr = [...]string{
-	srpcOK - srpcOK:                    "ok",
-	srpcErrBreak - srpcOK:              "break",
-	srpcErrMessageTruncated - srpcOK:   "message truncated",
-	srpcErrNoMemory - srpcOK:           "out of memory",
-	srpcErrProtocolMismatch - srpcOK:   "protocol mismatch",
-	srpcErrBadRPCNumber - srpcOK:       "invalid RPC method number",
-	srpcErrBadArgType - srpcOK:         "unexpected argument type",
-	srpcErrTooFewArgs - srpcOK:         "too few arguments",
-	srpcErrTooManyArgs - srpcOK:        "too many arguments",
-	srpcErrInArgTypeMismatch - srpcOK:  "input argument type mismatch",
-	srpcErrOutArgTypeMismatch - srpcOK: "output argument type mismatch",
-	srpcErrInternalError - srpcOK:      "internal error",
-	srpcErrAppError - srpcOK:           "application error",
-}
-
-func (e srpcErrno) Error() string {
-	if e < srpcOK || int(e-srpcOK) >= len(srpcErrstr) {
-		return "srpcErrno(" + itoa(int(e)) + ")"
-	}
-	return srpcErrstr[e-srpcOK]
-}
-
-// A msgHdr is the data argument to the imc_recvmsg
-// and imc_sendmsg system calls.
-type msgHdr struct {
-	iov   *iov
-	niov  int32
-	desc  *int32
-	ndesc int32
-	flags uint32
-}
-
-// A single region for I/O.
-type iov struct {
-	base *byte
-	len  int32
-}
-
-const maxMsgSize = 1<<16 - 4*4
-
-// A msgReceiver receives messages from a file descriptor.
-type msgReceiver struct {
-	fd   int
-	data [maxMsgSize]byte
-	desc [8]int32
-	hdr  msgHdr
-	iov  iov
-}
-
-func (r *msgReceiver) recv() (*msg, error) {
-	// Init pointers to buffers where syscall recvmsg can write.
-	r.iov.base = &r.data[0]
-	r.iov.len = int32(len(r.data))
-	r.hdr.iov = &r.iov
-	r.hdr.niov = 1
-	r.hdr.desc = &r.desc[0]
-	r.hdr.ndesc = int32(len(r.desc))
-	n, _, e := Syscall(sys_imc_recvmsg, uintptr(r.fd), uintptr(unsafe.Pointer(&r.hdr)), 0)
-	if e != 0 {
-		println("Native Client imc_recvmsg: ", e.Error())
-		return nil, e
-	}
-
-	// Make a copy of the data so that the next recvmsg doesn't
-	// smash it.  The system call did not update r.iov.len.  Instead it
-	// returned the total byte count as n.
-	m := new(msg)
-	m.data = make([]byte, n)
-	copy(m.data, r.data[0:])
-
-	// Make a copy of the desc too.
-	// The system call *did* update r.hdr.ndesc.
-	if r.hdr.ndesc > 0 {
-		m.desc = make([]int32, r.hdr.ndesc)
-		copy(m.desc, r.desc[:])
-	}
-
-	return m, nil
-}
-
-// A msgSender sends messages on a file descriptor.
-type msgSender struct {
-	fd  int
-	hdr msgHdr
-	iov iov
-}
-
-func (s *msgSender) send(m *msg) error {
-	if len(m.data) > 0 {
-		s.iov.base = &m.data[0]
-	}
-	s.iov.len = int32(len(m.data))
-	s.hdr.iov = &s.iov
-	s.hdr.niov = 1
-	s.hdr.desc = nil
-	s.hdr.ndesc = 0
-	_, _, e := Syscall(sys_imc_sendmsg, uintptr(s.fd), uintptr(unsafe.Pointer(&s.hdr)), 0)
-	if e != 0 {
-		println("Native Client imc_sendmsg: ", e.Error())
-		return e
-	}
-	return nil
-}
-
-// A msg is the Go representation of an SRPC message.
-type msg struct {
-	data []byte  // message data
-	desc []int32 // message file descriptors
-
-	// parsed version of message
-	id        uint32
-	isRequest uint32
-	rpc       uint32
-	status    uint32
-	value     []interface{}
-	template  []interface{}
-	size      []int
-	format    string
-	broken    bool
-}
-
-// reading from a msg
-
-func (m *msg) uint32() uint32 {
-	if m.broken {
-		return 0
-	}
-	if len(m.data) < 4 {
-		m.broken = true
-		return 0
-	}
-	b := m.data[:4]
-	x := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
-	m.data = m.data[4:]
-	return x
-}
-
-func (m *msg) uint64() uint64 {
-	x := uint64(m.uint32()) | uint64(m.uint32())<<32
-	if m.broken {
-		return 0
-	}
-	return x
-}
-
-func (m *msg) bytes(n int) []byte {
-	if m.broken {
-		return nil
-	}
-	if len(m.data) < n {
-		m.broken = true
-		return nil
-	}
-	x := m.data[0:n]
-	m.data = m.data[n:]
-	return x
-}
-
-// writing to a msg
-
-func (m *msg) wuint32(x uint32) {
-	m.data = append(m.data, byte(x), byte(x>>8), byte(x>>16), byte(x>>24))
-}
-
-func (m *msg) wuint64(x uint64) {
-	lo := uint32(x)
-	hi := uint32(x >> 32)
-	m.data = append(m.data, byte(lo), byte(lo>>8), byte(lo>>16), byte(lo>>24), byte(hi), byte(hi>>8), byte(hi>>16), byte(hi>>24))
-}
-
-func (m *msg) wbytes(p []byte) {
-	m.data = append(m.data, p...)
-}
-
-func (m *msg) wstring(s string) {
-	m.data = append(m.data, s...)
-}
-
-// Parsing of RPC messages.
-//
-// Each message begins with
-//	total_size uint32
-//	total_descs uint32
-//	fragment_size uint32
-//	fragment_descs uint32
-//
-// If fragment_size < total_size or fragment_descs < total_descs, the actual
-// message is broken up in multiple messages; follow-up messages omit
-// the "total" fields and begin with the "fragment" fields.
-// We do not support putting fragmented messages back together.
-// To do this we would need to change the message receiver.
-//
-// After that size information, the message header follows:
-//	protocol uint32
-//	requestID uint32
-//	isRequest uint32
-//	rpcNumber uint32
-//	status uint32
-//	numValue uint32
-//	numTemplate uint32
-//
-// After the header come numTemplate fixed-size arguments,
-// numValue fixed-size arguments, and then the variable-sized
-// part of the values. The templates describe the expected results
-// and have no associated variable sized data in the request.
-//
-// Each fixed-size argument has the form:
-//	tag uint32 // really a char, like 'b' or 'C'
-//	pad uint32 // unused
-//	val1 uint32
-//	val2 uint32
-//
-// The tags are:
-//	'b':	bool; val1 == 0 or 1
-//	'C':	[]byte; val1 == len, data in variable-sized section
-//	'd':	float64; (val1, val2) is data
-//	'D':	[]float64; val1 == len, data in variable-sized section
-//	'h':	int; val1 == file descriptor
-//	'i':	int32; descriptor in next entry in m.desc
-//	'I':	[]int; val1 == len, data in variable-sized section
-//	's':	string; val1 == len, data in variable-sized section
-//
-
-func (m *msg) pack() error {
-	m.data = m.data[:0]
-	m.desc = m.desc[:0]
-
-	// sizes, to fill in later
-	m.wuint32(0)
-	m.wuint32(0)
-	m.wuint32(0)
-	m.wuint32(0)
-
-	// message header
-	m.wuint32(protocol)
-	m.wuint32(m.id)
-	m.wuint32(m.isRequest)
-	m.wuint32(m.rpc)
-	m.wuint32(m.status)
-	m.wuint32(uint32(len(m.value)))
-	m.wuint32(uint32(len(m.template)))
-
-	// fixed-size templates
-	for i, x := range m.template {
-		var tag, val1, val2 uint32
-		switch x.(type) {
-		default:
-			return errors.New("unexpected template type")
-		case bool:
-			tag = 'b'
-		case []byte:
-			tag = 'C'
-			val1 = uint32(m.size[i])
-		case float64:
-			tag = 'd'
-		case []float64:
-			tag = 'D'
-			val1 = uint32(m.size[i])
-		case int:
-			tag = 'h'
-		case int32:
-			tag = 'i'
-		case []int32:
-			tag = 'I'
-			val1 = uint32(m.size[i])
-		case string:
-			tag = 's'
-			val1 = uint32(m.size[i])
-		}
-		m.wuint32(tag)
-		m.wuint32(0)
-		m.wuint32(val1)
-		m.wuint32(val2)
-	}
-
-	// fixed-size values
-	for _, x := range m.value {
-		var tag, val1, val2 uint32
-		switch x := x.(type) {
-		default:
-			return errors.New("unexpected value type")
-		case bool:
-			tag = 'b'
-			if x {
-				val1 = 1
-			}
-		case []byte:
-			tag = 'C'
-			val1 = uint32(len(x))
-		case float64:
-			tag = 'd'
-			v := float64bits(x)
-			val1 = uint32(v)
-			val2 = uint32(v >> 32)
-		case []float64:
-			tag = 'D'
-			val1 = uint32(len(x))
-		case int32:
-			tag = 'i'
-			m.desc = append(m.desc, x)
-		case []int32:
-			tag = 'I'
-			val1 = uint32(len(x))
-		case string:
-			tag = 's'
-			val1 = uint32(len(x) + 1)
-		}
-		m.wuint32(tag)
-		m.wuint32(0)
-		m.wuint32(val1)
-		m.wuint32(val2)
-	}
-
-	// variable-length data for values
-	for _, x := range m.value {
-		switch x := x.(type) {
-		case []byte:
-			m.wbytes(x)
-		case []float64:
-			for _, f := range x {
-				m.wuint64(float64bits(f))
-			}
-		case []int32:
-			for _, j := range x {
-				m.wuint32(uint32(j))
-			}
-		case string:
-			m.wstring(x)
-			m.wstring("\x00")
-		}
-	}
-
-	// fill in sizes
-	data := m.data
-	m.data = m.data[:0]
-	m.wuint32(uint32(len(data)))
-	m.wuint32(uint32(len(m.desc)))
-	m.wuint32(uint32(len(data)))
-	m.wuint32(uint32(len(m.desc)))
-	m.data = data
-
-	return nil
-}
-
-func (m *msg) unpack() error {
-	totalSize := m.uint32()
-	totalDesc := m.uint32()
-	fragSize := m.uint32()
-	fragDesc := m.uint32()
-	if totalSize != fragSize || totalDesc != fragDesc {
-		return errors.New("Native Client: fragmented RPC messages not supported")
-	}
-	if m.uint32() != protocol {
-		return errors.New("Native Client: RPC protocol mismatch")
-	}
-
-	// message header
-	m.id = m.uint32()
-	m.isRequest = m.uint32()
-	m.rpc = m.uint32()
-	m.status = m.uint32()
-	m.value = make([]interface{}, m.uint32())
-	m.template = make([]interface{}, m.uint32())
-	m.size = make([]int, len(m.template))
-	if m.broken {
-		return errors.New("Native Client: malformed message")
-	}
-
-	// fixed-size templates
-	for i := range m.template {
-		tag := m.uint32()
-		m.uint32() // padding
-		val1 := m.uint32()
-		m.uint32() // val2
-		switch tag {
-		default:
-			return errors.New("Native Client: unexpected template type " + string(rune(tag)))
-		case 'b':
-			m.template[i] = false
-		case 'C':
-			m.template[i] = []byte(nil)
-			m.size[i] = int(val1)
-		case 'd':
-			m.template[i] = float64(0)
-		case 'D':
-			m.template[i] = []float64(nil)
-			m.size[i] = int(val1)
-		case 'i':
-			m.template[i] = int32(0)
-		case 'I':
-			m.template[i] = []int32(nil)
-			m.size[i] = int(val1)
-		case 'h':
-			m.template[i] = int(0)
-		case 's':
-			m.template[i] = ""
-			m.size[i] = int(val1)
-		}
-	}
-
-	// fixed-size values
-	var (
-		strsize []uint32
-		d       int
-	)
-	for i := range m.value {
-		tag := m.uint32()
-		m.uint32() // padding
-		val1 := m.uint32()
-		val2 := m.uint32()
-		switch tag {
-		default:
-			return errors.New("Native Client: unexpected value type " + string(rune(tag)))
-		case 'b':
-			m.value[i] = val1 > 0
-		case 'C':
-			m.value[i] = []byte(nil)
-			strsize = append(strsize, val1)
-		case 'd':
-			m.value[i] = float64frombits(uint64(val1) | uint64(val2)<<32)
-		case 'D':
-			m.value[i] = make([]float64, val1)
-		case 'i':
-			m.value[i] = int32(val1)
-		case 'I':
-			m.value[i] = make([]int32, val1)
-		case 'h':
-			m.value[i] = int(m.desc[d])
-			d++
-		case 's':
-			m.value[i] = ""
-			strsize = append(strsize, val1)
-		}
-	}
-
-	// variable-sized parts of values
-	for i, x := range m.value {
-		switch x := x.(type) {
-		case []byte:
-			m.value[i] = m.bytes(int(strsize[0]))
-			strsize = strsize[1:]
-		case []float64:
-			for i := range x {
-				x[i] = float64frombits(m.uint64())
-			}
-		case []int32:
-			for i := range x {
-				x[i] = int32(m.uint32())
-			}
-		case string:
-			m.value[i] = string(m.bytes(int(strsize[0])))
-			strsize = strsize[1:]
-		}
-	}
-
-	if len(m.data) > 0 {
-		return errors.New("Native Client: junk at end of message")
-	}
-	return nil
-}
-
-func float64bits(x float64) uint64 {
-	return *(*uint64)(unsafe.Pointer(&x))
-}
-
-func float64frombits(x uint64) float64 {
-	return *(*float64)(unsafe.Pointer(&x))
-}
-
-// At startup, connect to the name service.
-var nsClient = nsConnect()
-
-func nsConnect() *srpcClient {
-	var ns int32 = -1
-	_, _, errno := Syscall(sys_nameservice, uintptr(unsafe.Pointer(&ns)), 0, 0)
-	if errno != 0 {
-		println("Native Client nameservice:", errno.Error())
-		return nil
-	}
-
-	sock, _, errno := Syscall(sys_imc_connect, uintptr(ns), 0, 0)
-	if errno != 0 {
-		println("Native Client nameservice connect:", errno.Error())
-		return nil
-	}
-
-	c, err := newClient(int(sock))
-	if err != nil {
-		println("Native Client nameservice init:", err.Error())
-		return nil
-	}
-
-	return c
-}
-
-const (
-	nsSuccess               = 0
-	nsNameNotFound          = 1
-	nsDuplicateName         = 2
-	nsInsufficientResources = 3
-	nsPermissionDenied      = 4
-	nsInvalidArgument       = 5
-)
-
-func openNamedService(name string, mode int32) (fd int, err error) {
-	if nsClient == nil {
-		return 0, errors.New("no name service")
-	}
-	ret, err := nsClient.Call("lookup:si:ih", name, int32(mode))
-	if err != nil {
-		return 0, err
-	}
-	status := ret[0].(int32)
-	fd = ret[1].(int)
-	switch status {
-	case nsSuccess:
-		// ok
-	case nsNameNotFound:
-		return -1, ENOENT
-	case nsDuplicateName:
-		return -1, EEXIST
-	case nsInsufficientResources:
-		return -1, EWOULDBLOCK
-	case nsPermissionDenied:
-		return -1, EPERM
-	case nsInvalidArgument:
-		return -1, EINVAL
-	default:
-		return -1, EINVAL
-	}
-	return fd, nil
-}
diff --git a/src/syscall/syscall.go b/src/syscall/syscall.go
index 791bcbb..769e6b9 100644
--- a/src/syscall/syscall.go
+++ b/src/syscall/syscall.go
@@ -95,5 +95,8 @@ func (tv *Timeval) Nano() int64 {
 
 // use is a no-op, but the compiler cannot see that it is.
 // Calling use(p) ensures that p is kept live until that point.
+// This was needed until Go 1.6 to call syscall.Syscall correctly.
+// As of Go 1.6 the compiler handles that case automatically.
+// The uses and definition of use can be removed early in the Go 1.7 cycle.
 //go:noescape
 func use(p unsafe.Pointer)
diff --git a/src/syscall/syscall_linux.go b/src/syscall/syscall_linux.go
index 4f88d51..2875067 100644
--- a/src/syscall/syscall_linux.go
+++ b/src/syscall/syscall_linux.go
@@ -837,7 +837,7 @@ func Mount(source string, target string, fstype string, flags uintptr, data stri
 //sys	Fdatasync(fd int) (err error)
 //sys	Flock(fd int, how int) (err error)
 //sys	Fsync(fd int) (err error)
-//sys	Getdents(fd int, buf []byte) (n int, err error) = SYS_GETDENTS64
+//sys	Getdents(fd int, buf []byte) (n int, err error) = _SYS_getdents
 //sysnb	Getpgid(pid int) (pgid int, err error)
 
 func Getpgrp() (pid int) {
@@ -881,7 +881,7 @@ func Setuid(uid int) (err error) {
 	return EOPNOTSUPP
 }
 
-func Setgid(uid int) (err error) {
+func Setgid(gid int) (err error) {
 	return EOPNOTSUPP
 }
 
diff --git a/src/syscall/syscall_linux_386.go b/src/syscall/syscall_linux_386.go
index 9ee1c1c..0e637b4 100644
--- a/src/syscall/syscall_linux_386.go
+++ b/src/syscall/syscall_linux_386.go
@@ -9,7 +9,10 @@ package syscall
 
 import "unsafe"
 
-const _SYS_dup = SYS_DUP2
+const (
+	_SYS_dup      = SYS_DUP2
+	_SYS_getdents = SYS_GETDENTS64
+)
 
 func Getpagesize() int { return 4096 }
 
diff --git a/src/syscall/syscall_linux_amd64.go b/src/syscall/syscall_linux_amd64.go
index 6fbef21..d1bda29 100644
--- a/src/syscall/syscall_linux_amd64.go
+++ b/src/syscall/syscall_linux_amd64.go
@@ -4,7 +4,10 @@
 
 package syscall
 
-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)
diff --git a/src/syscall/syscall_linux_arm.go b/src/syscall/syscall_linux_arm.go
index 218d6b8..7c78254 100644
--- a/src/syscall/syscall_linux_arm.go
+++ b/src/syscall/syscall_linux_arm.go
@@ -6,7 +6,10 @@ package syscall
 
 import "unsafe"
 
-const _SYS_dup = SYS_DUP2
+const (
+	_SYS_dup      = SYS_DUP2
+	_SYS_getdents = SYS_GETDENTS64
+)
 
 func Getpagesize() int { return 4096 }
 
diff --git a/src/syscall/syscall_linux_arm64.go b/src/syscall/syscall_linux_arm64.go
index 3d55181..5f1478c 100644
--- a/src/syscall/syscall_linux_arm64.go
+++ b/src/syscall/syscall_linux_arm64.go
@@ -4,7 +4,10 @@
 
 package syscall
 
-const _SYS_dup = SYS_DUP3
+const (
+	_SYS_dup      = SYS_DUP3
+	_SYS_getdents = SYS_GETDENTS64
+)
 
 //sys	Fchown(fd int, uid int, gid int) (err error)
 //sys	Fstat(fd int, stat *Stat_t) (err error)
diff --git a/src/syscall/syscall_linux_mips64x.go b/src/syscall/syscall_linux_mips64x.go
new file mode 100644
index 0000000..a14485a
--- /dev/null
+++ b/src/syscall/syscall_linux_mips64x.go
@@ -0,0 +1,210 @@
+// Copyright 2009 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.
+
+// +build linux
+// +build mips64 mips64le
+
+package syscall
+
+const (
+	_SYS_dup = SYS_DUP2
+
+	// Linux introduced getdents64 syscall for N64 ABI only in 3.10
+	// (May 21 2013, rev dec33abaafc89bcbd78f85fad0513170415a26d5),
+	// to support older kernels, we have to use getdents for mips64.
+	// Also note that struct dirent is different for these two.
+	// Lookup linux_dirent{,64} in kernel source code for details.
+	_SYS_getdents = SYS_GETDENTS
+)
+
+//sys	Dup2(oldfd int, newfd int) (err error)
+//sys	Fchown(fd int, uid int, gid int) (err error)
+//sys	Fstatfs(fd int, buf *Statfs_t) (err error)
+//sys	Ftruncate(fd int, length int64) (err error)
+//sysnb	Getegid() (egid int)
+//sysnb	Geteuid() (euid int)
+//sysnb	Getgid() (gid int)
+//sysnb	Getrlimit(resource int, rlim *Rlimit) (err error)
+//sysnb	Getuid() (uid int)
+//sysnb	InotifyInit() (fd int, err error)
+//sys	Lchown(path string, uid int, gid int) (err error)
+//sys	Listen(s int, n int) (err error)
+//sys	Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
+//sys	Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
+//sys	Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
+//sys	Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS_PSELECT6
+//sys	sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
+//sys	Setfsgid(gid int) (err error)
+//sys	Setfsuid(uid int) (err error)
+//sysnb	Setregid(rgid int, egid int) (err error)
+//sysnb	Setresgid(rgid int, egid int, sgid int) (err error)
+//sysnb	Setresuid(ruid int, euid int, suid int) (err error)
+//sysnb	Setrlimit(resource int, rlim *Rlimit) (err error)
+//sysnb	Setreuid(ruid int, euid int) (err error)
+//sys	Shutdown(fd int, how int) (err error)
+//sys	Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
+//sys	Statfs(path string, buf *Statfs_t) (err error)
+//sys	SyncFileRange(fd int, off int64, n int64, flags int) (err error)
+//sys	Truncate(path string, length int64) (err error)
+//sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
+//sys	accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error)
+//sys	bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
+//sys	connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
+//sysnb	getgroups(n int, list *_Gid_t) (nn int, err error)
+//sysnb	setgroups(n int, list *_Gid_t) (err error)
+//sys	getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
+//sys	setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
+//sysnb	socket(domain int, typ int, proto int) (fd int, err error)
+//sysnb	socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
+//sysnb	getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
+//sysnb	getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
+//sys	recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
+//sys	sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
+//sys	recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
+//sys	sendmsg(s int, msg *Msghdr, flags int) (n int, err error)
+//sys	mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error)
+
+func Getpagesize() int { return 65536 }
+
+//sysnb	Gettimeofday(tv *Timeval) (err error)
+
+func Time(t *Time_t) (tt Time_t, err error) {
+	var tv Timeval
+	err = Gettimeofday(&tv)
+	if err != nil {
+		return 0, err
+	}
+	if t != nil {
+		*t = Time_t(tv.Sec)
+	}
+	return Time_t(tv.Sec), nil
+}
+
+func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
+
+func NsecToTimespec(nsec int64) (ts Timespec) {
+	ts.Sec = nsec / 1e9
+	ts.Nsec = nsec % 1e9
+	return
+}
+
+func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
+
+func NsecToTimeval(nsec int64) (tv Timeval) {
+	nsec += 999 // round up to microsecond
+	tv.Sec = nsec / 1e9
+	tv.Usec = nsec % 1e9 / 1e3
+	return
+}
+
+func Pipe(p []int) (err error) {
+	if len(p) != 2 {
+		return EINVAL
+	}
+	var pp [2]_C_int
+	err = pipe2(&pp, 0)
+	p[0] = int(pp[0])
+	p[1] = int(pp[1])
+	return
+}
+
+//sysnb pipe2(p *[2]_C_int, flags int) (err error)
+
+func Pipe2(p []int, flags int) (err error) {
+	if len(p) != 2 {
+		return EINVAL
+	}
+	var pp [2]_C_int
+	err = pipe2(&pp, flags)
+	p[0] = int(pp[0])
+	p[1] = int(pp[1])
+	return
+}
+
+func Ioperm(from int, num int, on int) (err error) {
+	return ENOSYS
+}
+
+func Iopl(level int) (err error) {
+	return ENOSYS
+}
+
+type stat_t struct {
+	Dev        uint32
+	Pad0       [3]int32
+	Ino        uint64
+	Mode       uint32
+	Nlink      uint32
+	Uid        uint32
+	Gid        uint32
+	Rdev       uint32
+	Pad1       [3]uint32
+	Size       int64
+	Atime      uint32
+	Atime_nsec uint32
+	Mtime      uint32
+	Mtime_nsec uint32
+	Ctime      uint32
+	Ctime_nsec uint32
+	Blksize    uint32
+	Pad2       uint32
+	Blocks     int64
+}
+
+//sys	fstat(fd int, st *stat_t) (err error)
+//sys	lstat(path string, st *stat_t) (err error)
+//sys	stat(path string, st *stat_t) (err error)
+
+func Fstat(fd int, s *Stat_t) (err error) {
+	st := &stat_t{}
+	err = fstat(fd, st)
+	fillStat_t(s, st)
+	return
+}
+
+func Lstat(path string, s *Stat_t) (err error) {
+	st := &stat_t{}
+	err = lstat(path, st)
+	fillStat_t(s, st)
+	return
+}
+
+func Stat(path string, s *Stat_t) (err error) {
+	st := &stat_t{}
+	err = stat(path, st)
+	fillStat_t(s, st)
+	return
+}
+
+func fillStat_t(s *Stat_t, st *stat_t) {
+	s.Dev = st.Dev
+	s.Ino = st.Ino
+	s.Mode = st.Mode
+	s.Nlink = st.Nlink
+	s.Uid = st.Uid
+	s.Gid = st.Gid
+	s.Rdev = st.Rdev
+	s.Size = st.Size
+	s.Atim = Timespec{int64(st.Atime), int64(st.Atime_nsec)}
+	s.Mtim = Timespec{int64(st.Mtime), int64(st.Mtime_nsec)}
+	s.Ctim = Timespec{int64(st.Ctime), int64(st.Ctime_nsec)}
+	s.Blksize = st.Blksize
+	s.Blocks = st.Blocks
+}
+
+func (r *PtraceRegs) PC() uint64 { return r.Regs[64] }
+
+func (r *PtraceRegs) SetPC(pc uint64) { r.Regs[64] = pc }
+
+func (iov *Iovec) SetLen(length int) {
+	iov.Len = uint64(length)
+}
+
+func (msghdr *Msghdr) SetControllen(length int) {
+	msghdr.Controllen = uint64(length)
+}
+
+func (cmsg *Cmsghdr) SetLen(length int) {
+	cmsg.Len = uint64(length)
+}
diff --git a/src/syscall/syscall_linux_ppc64x.go b/src/syscall/syscall_linux_ppc64x.go
index 10489d9..9f1c07e 100644
--- a/src/syscall/syscall_linux_ppc64x.go
+++ b/src/syscall/syscall_linux_ppc64x.go
@@ -7,7 +7,10 @@
 
 package syscall
 
-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)
diff --git a/src/syscall/syscall_linux_test.go b/src/syscall/syscall_linux_test.go
index 40fce6d..4cabf6c 100644
--- a/src/syscall/syscall_linux_test.go
+++ b/src/syscall/syscall_linux_test.go
@@ -66,11 +66,11 @@ func TestLinuxDeathSignal(t *testing.T) {
 	cmd.Env = []string{"GO_DEATHSIG_PARENT=1"}
 	chldStdin, err := cmd.StdinPipe()
 	if err != nil {
-		t.Fatal("failed to create new stdin pipe: %v", err)
+		t.Fatalf("failed to create new stdin pipe: %v", err)
 	}
 	chldStdout, err := cmd.StdoutPipe()
 	if err != nil {
-		t.Fatal("failed to create new stdout pipe: %v", err)
+		t.Fatalf("failed to create new stdout pipe: %v", err)
 	}
 	cmd.Stderr = os.Stderr
 
@@ -114,7 +114,7 @@ func deathSignalParent() {
 
 	err := cmd.Start()
 	if err != nil {
-		fmt.Fprintf(os.Stderr, "death signal parent error: %v\n")
+		fmt.Fprintf(os.Stderr, "death signal parent error: %v\n", err)
 		os.Exit(1)
 	}
 	cmd.Wait()
diff --git a/src/syscall/syscall_solaris.go b/src/syscall/syscall_solaris.go
index 0f60e21..2f68760 100644
--- a/src/syscall/syscall_solaris.go
+++ b/src/syscall/syscall_solaris.go
@@ -142,12 +142,23 @@ func Getsockname(fd int) (sa Sockaddr, err error) {
 	return anyToSockaddr(&rsa)
 }
 
-// The const provides a compile-time constant so clients
-// can adjust to whether there is a working Getwd and avoid
-// even linking this function into the binary.  See ../os/getwd.go.
-const ImplementsGetwd = false
+const ImplementsGetwd = true
 
-func Getwd() (string, error) { return "", ENOTSUP }
+//sys	Getcwd(buf []byte) (n int, err error)
+
+func Getwd() (wd string, err error) {
+	var buf [PathMax]byte
+	// Getcwd will return an error if it failed for any reason.
+	_, err = Getcwd(buf[0:])
+	if err != nil {
+		return "", err
+	}
+	n := clen(buf[:])
+	if n < 1 {
+		return "", EINVAL
+	}
+	return string(buf[:n]), nil
+}
 
 /*
  * Wrapped
diff --git a/src/syscall/syscall_unix.go b/src/syscall/syscall_unix.go
index b133ea7..5703133 100644
--- a/src/syscall/syscall_unix.go
+++ b/src/syscall/syscall_unix.go
@@ -7,6 +7,7 @@
 package syscall
 
 import (
+	"internal/race"
 	"runtime"
 	"sync"
 	"unsafe"
@@ -158,24 +159,30 @@ func (s Signal) String() string {
 
 func Read(fd int, p []byte) (n int, err error) {
 	n, err = read(fd, p)
-	if raceenabled {
+	if race.Enabled {
 		if n > 0 {
-			raceWriteRange(unsafe.Pointer(&p[0]), n)
+			race.WriteRange(unsafe.Pointer(&p[0]), n)
 		}
 		if err == nil {
-			raceAcquire(unsafe.Pointer(&ioSync))
+			race.Acquire(unsafe.Pointer(&ioSync))
 		}
 	}
+	if msanenabled && n > 0 {
+		msanWrite(unsafe.Pointer(&p[0]), n)
+	}
 	return
 }
 
 func Write(fd int, p []byte) (n int, err error) {
-	if raceenabled {
-		raceReleaseMerge(unsafe.Pointer(&ioSync))
+	if race.Enabled {
+		race.ReleaseMerge(unsafe.Pointer(&ioSync))
 	}
 	n, err = write(fd, p)
-	if raceenabled && n > 0 {
-		raceReadRange(unsafe.Pointer(&p[0]), n)
+	if race.Enabled && n > 0 {
+		race.ReadRange(unsafe.Pointer(&p[0]), n)
+	}
+	if msanenabled && n > 0 {
+		msanRead(unsafe.Pointer(&p[0]), n)
 	}
 	return
 }
@@ -314,8 +321,8 @@ func Socketpair(domain, typ, proto int) (fd [2]int, err error) {
 }
 
 func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
-	if raceenabled {
-		raceReleaseMerge(unsafe.Pointer(&ioSync))
+	if race.Enabled {
+		race.ReleaseMerge(unsafe.Pointer(&ioSync))
 	}
 	return sendfile(outfd, infd, offset, count)
 }
diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go
index 1006a9b..6416655 100644
--- a/src/syscall/syscall_windows.go
+++ b/src/syscall/syscall_windows.go
@@ -8,6 +8,7 @@ package syscall
 
 import (
 	errorspkg "errors"
+	"internal/race"
 	"sync"
 	"unicode/utf16"
 	"unsafe"
@@ -304,26 +305,32 @@ func Read(fd Handle, p []byte) (n int, err error) {
 		}
 		return 0, e
 	}
-	if raceenabled {
+	if race.Enabled {
 		if done > 0 {
-			raceWriteRange(unsafe.Pointer(&p[0]), int(done))
+			race.WriteRange(unsafe.Pointer(&p[0]), int(done))
 		}
-		raceAcquire(unsafe.Pointer(&ioSync))
+		race.Acquire(unsafe.Pointer(&ioSync))
+	}
+	if msanenabled && done > 0 {
+		msanWrite(unsafe.Pointer(&p[0]), int(done))
 	}
 	return int(done), nil
 }
 
 func Write(fd Handle, p []byte) (n int, err error) {
-	if raceenabled {
-		raceReleaseMerge(unsafe.Pointer(&ioSync))
+	if race.Enabled {
+		race.ReleaseMerge(unsafe.Pointer(&ioSync))
 	}
 	var done uint32
 	e := WriteFile(fd, p, &done, nil)
 	if e != nil {
 		return 0, e
 	}
-	if raceenabled && done > 0 {
-		raceReadRange(unsafe.Pointer(&p[0]), int(done))
+	if race.Enabled && done > 0 {
+		race.ReadRange(unsafe.Pointer(&p[0]), int(done))
+	}
+	if msanenabled && done > 0 {
+		msanRead(unsafe.Pointer(&p[0]), int(done))
 	}
 	return int(done), nil
 }
diff --git a/src/syscall/types_linux.go b/src/syscall/types_linux.go
index 0ebdc7c..cff4069 100644
--- a/src/syscall/types_linux.go
+++ b/src/syscall/types_linux.go
@@ -91,6 +91,8 @@ typedef struct user_regs PtraceRegs;
 typedef struct user_pt_regs PtraceRegs;
 #elif defined(__powerpc64__)
 typedef struct pt_regs PtraceRegs;
+#elif defined(__mips__)
+typedef struct user PtraceRegs;
 #else
 typedef struct user_regs_struct PtraceRegs;
 #endif
diff --git a/src/syscall/types_solaris.go b/src/syscall/types_solaris.go
index 53fa350..7246434 100644
--- a/src/syscall/types_solaris.go
+++ b/src/syscall/types_solaris.go
@@ -15,8 +15,14 @@ package syscall
 
 /*
 #define KERNEL
+// These defines ensure that builds done on newer versions of Solaris are
+// backwards-compatible with older versions of Solaris and
+// OpenSolaris-based derivatives.
+#define __USE_SUNOS_SOCKETS__          // msghdr
+#define __USE_LEGACY_PROTOTYPES__      // iovec
 #include <dirent.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <signal.h>
 #include <termios.h>
 #include <stdio.h>
@@ -69,6 +75,7 @@ const (
 	sizeofInt      = C.sizeof_int
 	sizeofLong     = C.sizeof_long
 	sizeofLongLong = C.sizeof_longlong
+	PathMax        = C.PATH_MAX
 )
 
 // Basic types
diff --git a/src/syscall/zerrors_linux_mips64.go b/src/syscall/zerrors_linux_mips64.go
new file mode 100644
index 0000000..e6399dd
--- /dev/null
+++ b/src/syscall/zerrors_linux_mips64.go
@@ -0,0 +1,1817 @@
+// mkerrors.sh
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs _const.go
+
+package syscall
+
+const (
+	AF_ALG                           = 0x26
+	AF_APPLETALK                     = 0x5
+	AF_ASH                           = 0x12
+	AF_ATMPVC                        = 0x8
+	AF_ATMSVC                        = 0x14
+	AF_AX25                          = 0x3
+	AF_BLUETOOTH                     = 0x1f
+	AF_BRIDGE                        = 0x7
+	AF_CAIF                          = 0x25
+	AF_CAN                           = 0x1d
+	AF_DECnet                        = 0xc
+	AF_ECONET                        = 0x13
+	AF_FILE                          = 0x1
+	AF_IEEE802154                    = 0x24
+	AF_INET                          = 0x2
+	AF_INET6                         = 0xa
+	AF_IPX                           = 0x4
+	AF_IRDA                          = 0x17
+	AF_ISDN                          = 0x22
+	AF_IUCV                          = 0x20
+	AF_KEY                           = 0xf
+	AF_LLC                           = 0x1a
+	AF_LOCAL                         = 0x1
+	AF_MAX                           = 0x28
+	AF_NETBEUI                       = 0xd
+	AF_NETLINK                       = 0x10
+	AF_NETROM                        = 0x6
+	AF_NFC                           = 0x27
+	AF_PACKET                        = 0x11
+	AF_PHONET                        = 0x23
+	AF_PPPOX                         = 0x18
+	AF_RDS                           = 0x15
+	AF_ROSE                          = 0xb
+	AF_ROUTE                         = 0x10
+	AF_RXRPC                         = 0x21
+	AF_SECURITY                      = 0xe
+	AF_SNA                           = 0x16
+	AF_TIPC                          = 0x1e
+	AF_UNIX                          = 0x1
+	AF_UNSPEC                        = 0x0
+	AF_WANPIPE                       = 0x19
+	AF_X25                           = 0x9
+	ARPHRD_ADAPT                     = 0x108
+	ARPHRD_APPLETLK                  = 0x8
+	ARPHRD_ARCNET                    = 0x7
+	ARPHRD_ASH                       = 0x30d
+	ARPHRD_ATM                       = 0x13
+	ARPHRD_AX25                      = 0x3
+	ARPHRD_BIF                       = 0x307
+	ARPHRD_CAIF                      = 0x336
+	ARPHRD_CAN                       = 0x118
+	ARPHRD_CHAOS                     = 0x5
+	ARPHRD_CISCO                     = 0x201
+	ARPHRD_CSLIP                     = 0x101
+	ARPHRD_CSLIP6                    = 0x103
+	ARPHRD_DDCMP                     = 0x205
+	ARPHRD_DLCI                      = 0xf
+	ARPHRD_ECONET                    = 0x30e
+	ARPHRD_EETHER                    = 0x2
+	ARPHRD_ETHER                     = 0x1
+	ARPHRD_EUI64                     = 0x1b
+	ARPHRD_FCAL                      = 0x311
+	ARPHRD_FCFABRIC                  = 0x313
+	ARPHRD_FCPL                      = 0x312
+	ARPHRD_FCPP                      = 0x310
+	ARPHRD_FDDI                      = 0x306
+	ARPHRD_FRAD                      = 0x302
+	ARPHRD_HDLC                      = 0x201
+	ARPHRD_HIPPI                     = 0x30c
+	ARPHRD_HWX25                     = 0x110
+	ARPHRD_IEEE1394                  = 0x18
+	ARPHRD_IEEE802                   = 0x6
+	ARPHRD_IEEE80211                 = 0x321
+	ARPHRD_IEEE80211_PRISM           = 0x322
+	ARPHRD_IEEE80211_RADIOTAP        = 0x323
+	ARPHRD_IEEE802154                = 0x324
+	ARPHRD_IEEE802154_MONITOR        = 0x325
+	ARPHRD_IEEE802_TR                = 0x320
+	ARPHRD_INFINIBAND                = 0x20
+	ARPHRD_IP6GRE                    = 0x337
+	ARPHRD_IPDDP                     = 0x309
+	ARPHRD_IPGRE                     = 0x30a
+	ARPHRD_IRDA                      = 0x30f
+	ARPHRD_LAPB                      = 0x204
+	ARPHRD_LOCALTLK                  = 0x305
+	ARPHRD_LOOPBACK                  = 0x304
+	ARPHRD_METRICOM                  = 0x17
+	ARPHRD_NETLINK                   = 0x338
+	ARPHRD_NETROM                    = 0x0
+	ARPHRD_NONE                      = 0xfffe
+	ARPHRD_PHONET                    = 0x334
+	ARPHRD_PHONET_PIPE               = 0x335
+	ARPHRD_PIMREG                    = 0x30b
+	ARPHRD_PPP                       = 0x200
+	ARPHRD_PRONET                    = 0x4
+	ARPHRD_RAWHDLC                   = 0x206
+	ARPHRD_ROSE                      = 0x10e
+	ARPHRD_RSRVD                     = 0x104
+	ARPHRD_SIT                       = 0x308
+	ARPHRD_SKIP                      = 0x303
+	ARPHRD_SLIP                      = 0x100
+	ARPHRD_SLIP6                     = 0x102
+	ARPHRD_TUNNEL                    = 0x300
+	ARPHRD_TUNNEL6                   = 0x301
+	ARPHRD_VOID                      = 0xffff
+	ARPHRD_X25                       = 0x10f
+	B0                               = 0x0
+	B1000000                         = 0x1008
+	B110                             = 0x3
+	B115200                          = 0x1002
+	B1152000                         = 0x1009
+	B1200                            = 0x9
+	B134                             = 0x4
+	B150                             = 0x5
+	B1500000                         = 0x100a
+	B1800                            = 0xa
+	B19200                           = 0xe
+	B200                             = 0x6
+	B2000000                         = 0x100b
+	B230400                          = 0x1003
+	B2400                            = 0xb
+	B2500000                         = 0x100c
+	B300                             = 0x7
+	B3000000                         = 0x100d
+	B3500000                         = 0x100e
+	B38400                           = 0xf
+	B4000000                         = 0x100f
+	B460800                          = 0x1004
+	B4800                            = 0xc
+	B50                              = 0x1
+	B500000                          = 0x1005
+	B57600                           = 0x1001
+	B576000                          = 0x1006
+	B600                             = 0x8
+	B75                              = 0x2
+	B921600                          = 0x1007
+	B9600                            = 0xd
+	BPF_A                            = 0x10
+	BPF_ABS                          = 0x20
+	BPF_ADD                          = 0x0
+	BPF_ALU                          = 0x4
+	BPF_AND                          = 0x50
+	BPF_B                            = 0x10
+	BPF_DIV                          = 0x30
+	BPF_H                            = 0x8
+	BPF_IMM                          = 0x0
+	BPF_IND                          = 0x40
+	BPF_JA                           = 0x0
+	BPF_JEQ                          = 0x10
+	BPF_JGE                          = 0x30
+	BPF_JGT                          = 0x20
+	BPF_JMP                          = 0x5
+	BPF_JSET                         = 0x40
+	BPF_K                            = 0x0
+	BPF_LD                           = 0x0
+	BPF_LDX                          = 0x1
+	BPF_LEN                          = 0x80
+	BPF_LSH                          = 0x60
+	BPF_MAJOR_VERSION                = 0x1
+	BPF_MAXINSNS                     = 0x1000
+	BPF_MEM                          = 0x60
+	BPF_MEMWORDS                     = 0x10
+	BPF_MINOR_VERSION                = 0x1
+	BPF_MISC                         = 0x7
+	BPF_MOD                          = 0x90
+	BPF_MSH                          = 0xa0
+	BPF_MUL                          = 0x20
+	BPF_NEG                          = 0x80
+	BPF_OR                           = 0x40
+	BPF_RET                          = 0x6
+	BPF_RSH                          = 0x70
+	BPF_ST                           = 0x2
+	BPF_STX                          = 0x3
+	BPF_SUB                          = 0x10
+	BPF_TAX                          = 0x0
+	BPF_TXA                          = 0x80
+	BPF_W                            = 0x0
+	BPF_X                            = 0x8
+	BPF_XOR                          = 0xa0
+	BRKINT                           = 0x2
+	CFLUSH                           = 0xf
+	CLOCAL                           = 0x800
+	CLONE_CHILD_CLEARTID             = 0x200000
+	CLONE_CHILD_SETTID               = 0x1000000
+	CLONE_DETACHED                   = 0x400000
+	CLONE_FILES                      = 0x400
+	CLONE_FS                         = 0x200
+	CLONE_IO                         = 0x80000000
+	CLONE_NEWIPC                     = 0x8000000
+	CLONE_NEWNET                     = 0x40000000
+	CLONE_NEWNS                      = 0x20000
+	CLONE_NEWPID                     = 0x20000000
+	CLONE_NEWUSER                    = 0x10000000
+	CLONE_NEWUTS                     = 0x4000000
+	CLONE_PARENT                     = 0x8000
+	CLONE_PARENT_SETTID              = 0x100000
+	CLONE_PTRACE                     = 0x2000
+	CLONE_SETTLS                     = 0x80000
+	CLONE_SIGHAND                    = 0x800
+	CLONE_SYSVSEM                    = 0x40000
+	CLONE_THREAD                     = 0x10000
+	CLONE_UNTRACED                   = 0x800000
+	CLONE_VFORK                      = 0x4000
+	CLONE_VM                         = 0x100
+	CREAD                            = 0x80
+	CS5                              = 0x0
+	CS6                              = 0x10
+	CS7                              = 0x20
+	CS8                              = 0x30
+	CSIGNAL                          = 0xff
+	CSIZE                            = 0x30
+	CSTART                           = 0x11
+	CSTATUS                          = 0x0
+	CSTOP                            = 0x13
+	CSTOPB                           = 0x40
+	CSUSP                            = 0x1a
+	DT_BLK                           = 0x6
+	DT_CHR                           = 0x2
+	DT_DIR                           = 0x4
+	DT_FIFO                          = 0x1
+	DT_LNK                           = 0xa
+	DT_REG                           = 0x8
+	DT_SOCK                          = 0xc
+	DT_UNKNOWN                       = 0x0
+	DT_WHT                           = 0xe
+	ECHO                             = 0x8
+	ECHOCTL                          = 0x200
+	ECHOE                            = 0x10
+	ECHOK                            = 0x20
+	ECHOKE                           = 0x800
+	ECHONL                           = 0x40
+	ECHOPRT                          = 0x400
+	ENCODING_DEFAULT                 = 0x0
+	ENCODING_FM_MARK                 = 0x3
+	ENCODING_FM_SPACE                = 0x4
+	ENCODING_MANCHESTER              = 0x5
+	ENCODING_NRZ                     = 0x1
+	ENCODING_NRZI                    = 0x2
+	EPOLLERR                         = 0x8
+	EPOLLET                          = 0x80000000
+	EPOLLHUP                         = 0x10
+	EPOLLIN                          = 0x1
+	EPOLLMSG                         = 0x400
+	EPOLLONESHOT                     = 0x40000000
+	EPOLLOUT                         = 0x4
+	EPOLLPRI                         = 0x2
+	EPOLLRDBAND                      = 0x80
+	EPOLLRDHUP                       = 0x2000
+	EPOLLRDNORM                      = 0x40
+	EPOLLWAKEUP                      = 0x20000000
+	EPOLLWRBAND                      = 0x200
+	EPOLLWRNORM                      = 0x100
+	EPOLL_CLOEXEC                    = 0x80000
+	EPOLL_CTL_ADD                    = 0x1
+	EPOLL_CTL_DEL                    = 0x2
+	EPOLL_CTL_MOD                    = 0x3
+	EPOLL_NONBLOCK                   = 0x80
+	ETH_P_1588                       = 0x88f7
+	ETH_P_8021AD                     = 0x88a8
+	ETH_P_8021AH                     = 0x88e7
+	ETH_P_8021Q                      = 0x8100
+	ETH_P_802_2                      = 0x4
+	ETH_P_802_3                      = 0x1
+	ETH_P_802_3_MIN                  = 0x600
+	ETH_P_802_EX1                    = 0x88b5
+	ETH_P_AARP                       = 0x80f3
+	ETH_P_AF_IUCV                    = 0xfbfb
+	ETH_P_ALL                        = 0x3
+	ETH_P_AOE                        = 0x88a2
+	ETH_P_ARCNET                     = 0x1a
+	ETH_P_ARP                        = 0x806
+	ETH_P_ATALK                      = 0x809b
+	ETH_P_ATMFATE                    = 0x8884
+	ETH_P_ATMMPOA                    = 0x884c
+	ETH_P_AX25                       = 0x2
+	ETH_P_BATMAN                     = 0x4305
+	ETH_P_BPQ                        = 0x8ff
+	ETH_P_CAIF                       = 0xf7
+	ETH_P_CAN                        = 0xc
+	ETH_P_CANFD                      = 0xd
+	ETH_P_CONTROL                    = 0x16
+	ETH_P_CUST                       = 0x6006
+	ETH_P_DDCMP                      = 0x6
+	ETH_P_DEC                        = 0x6000
+	ETH_P_DIAG                       = 0x6005
+	ETH_P_DNA_DL                     = 0x6001
+	ETH_P_DNA_RC                     = 0x6002
+	ETH_P_DNA_RT                     = 0x6003
+	ETH_P_DSA                        = 0x1b
+	ETH_P_ECONET                     = 0x18
+	ETH_P_EDSA                       = 0xdada
+	ETH_P_FCOE                       = 0x8906
+	ETH_P_FIP                        = 0x8914
+	ETH_P_HDLC                       = 0x19
+	ETH_P_IEEE802154                 = 0xf6
+	ETH_P_IEEEPUP                    = 0xa00
+	ETH_P_IEEEPUPAT                  = 0xa01
+	ETH_P_IP                         = 0x800
+	ETH_P_IPV6                       = 0x86dd
+	ETH_P_IPX                        = 0x8137
+	ETH_P_IRDA                       = 0x17
+	ETH_P_LAT                        = 0x6004
+	ETH_P_LINK_CTL                   = 0x886c
+	ETH_P_LOCALTALK                  = 0x9
+	ETH_P_LOOP                       = 0x60
+	ETH_P_MOBITEX                    = 0x15
+	ETH_P_MPLS_MC                    = 0x8848
+	ETH_P_MPLS_UC                    = 0x8847
+	ETH_P_MVRP                       = 0x88f5
+	ETH_P_PAE                        = 0x888e
+	ETH_P_PAUSE                      = 0x8808
+	ETH_P_PHONET                     = 0xf5
+	ETH_P_PPPTALK                    = 0x10
+	ETH_P_PPP_DISC                   = 0x8863
+	ETH_P_PPP_MP                     = 0x8
+	ETH_P_PPP_SES                    = 0x8864
+	ETH_P_PUP                        = 0x200
+	ETH_P_PUPAT                      = 0x201
+	ETH_P_QINQ1                      = 0x9100
+	ETH_P_QINQ2                      = 0x9200
+	ETH_P_QINQ3                      = 0x9300
+	ETH_P_RARP                       = 0x8035
+	ETH_P_SCA                        = 0x6007
+	ETH_P_SLOW                       = 0x8809
+	ETH_P_SNAP                       = 0x5
+	ETH_P_TDLS                       = 0x890d
+	ETH_P_TEB                        = 0x6558
+	ETH_P_TIPC                       = 0x88ca
+	ETH_P_TRAILER                    = 0x1c
+	ETH_P_TR_802_2                   = 0x11
+	ETH_P_WAN_PPP                    = 0x7
+	ETH_P_WCCP                       = 0x883e
+	ETH_P_X25                        = 0x805
+	EXTA                             = 0xe
+	EXTB                             = 0xf
+	EXTPROC                          = 0x10000
+	FD_CLOEXEC                       = 0x1
+	FD_SETSIZE                       = 0x400
+	FLUSHO                           = 0x2000
+	F_DUPFD                          = 0x0
+	F_DUPFD_CLOEXEC                  = 0x406
+	F_EXLCK                          = 0x4
+	F_GETFD                          = 0x1
+	F_GETFL                          = 0x3
+	F_GETLEASE                       = 0x401
+	F_GETLK                          = 0xe
+	F_GETLK64                        = 0xe
+	F_GETOWN                         = 0x17
+	F_GETOWN_EX                      = 0x10
+	F_GETPIPE_SZ                     = 0x408
+	F_GETSIG                         = 0xb
+	F_LOCK                           = 0x1
+	F_NOTIFY                         = 0x402
+	F_OK                             = 0x0
+	F_RDLCK                          = 0x0
+	F_SETFD                          = 0x2
+	F_SETFL                          = 0x4
+	F_SETLEASE                       = 0x400
+	F_SETLK                          = 0x6
+	F_SETLK64                        = 0x6
+	F_SETLKW                         = 0x7
+	F_SETLKW64                       = 0x7
+	F_SETOWN                         = 0x18
+	F_SETOWN_EX                      = 0xf
+	F_SETPIPE_SZ                     = 0x407
+	F_SETSIG                         = 0xa
+	F_SHLCK                          = 0x8
+	F_TEST                           = 0x3
+	F_TLOCK                          = 0x2
+	F_ULOCK                          = 0x0
+	F_UNLCK                          = 0x2
+	F_WRLCK                          = 0x1
+	HUPCL                            = 0x400
+	ICANON                           = 0x2
+	ICMPV6_FILTER                    = 0x1
+	ICRNL                            = 0x100
+	IEXTEN                           = 0x100
+	IFA_F_DADFAILED                  = 0x8
+	IFA_F_DEPRECATED                 = 0x20
+	IFA_F_HOMEADDRESS                = 0x10
+	IFA_F_NODAD                      = 0x2
+	IFA_F_OPTIMISTIC                 = 0x4
+	IFA_F_PERMANENT                  = 0x80
+	IFA_F_SECONDARY                  = 0x1
+	IFA_F_TEMPORARY                  = 0x1
+	IFA_F_TENTATIVE                  = 0x40
+	IFA_MAX                          = 0x7
+	IFF_802_1Q_VLAN                  = 0x1
+	IFF_ALLMULTI                     = 0x200
+	IFF_ATTACH_QUEUE                 = 0x200
+	IFF_AUTOMEDIA                    = 0x4000
+	IFF_BONDING                      = 0x20
+	IFF_BRIDGE_PORT                  = 0x4000
+	IFF_BROADCAST                    = 0x2
+	IFF_DEBUG                        = 0x4
+	IFF_DETACH_QUEUE                 = 0x400
+	IFF_DISABLE_NETPOLL              = 0x1000
+	IFF_DONT_BRIDGE                  = 0x800
+	IFF_DORMANT                      = 0x20000
+	IFF_DYNAMIC                      = 0x8000
+	IFF_EBRIDGE                      = 0x2
+	IFF_ECHO                         = 0x40000
+	IFF_ISATAP                       = 0x80
+	IFF_LIVE_ADDR_CHANGE             = 0x100000
+	IFF_LOOPBACK                     = 0x8
+	IFF_LOWER_UP                     = 0x10000
+	IFF_MACVLAN_PORT                 = 0x2000
+	IFF_MASTER                       = 0x400
+	IFF_MASTER_8023AD                = 0x8
+	IFF_MASTER_ALB                   = 0x10
+	IFF_MASTER_ARPMON                = 0x100
+	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
+	IFF_RUNNING                      = 0x40
+	IFF_SLAVE                        = 0x800
+	IFF_SLAVE_INACTIVE               = 0x4
+	IFF_SLAVE_NEEDARP                = 0x40
+	IFF_SUPP_NOFCS                   = 0x80000
+	IFF_TAP                          = 0x2
+	IFF_TEAM_PORT                    = 0x40000
+	IFF_TUN                          = 0x1
+	IFF_TUN_EXCL                     = 0x8000
+	IFF_TX_SKB_SHARING               = 0x10000
+	IFF_UNICAST_FLT                  = 0x20000
+	IFF_UP                           = 0x1
+	IFF_VNET_HDR                     = 0x4000
+	IFF_VOLATILE                     = 0x70c5a
+	IFF_WAN_HDLC                     = 0x200
+	IFF_XMIT_DST_RELEASE             = 0x400
+	IFNAMSIZ                         = 0x10
+	IGNBRK                           = 0x1
+	IGNCR                            = 0x80
+	IGNPAR                           = 0x4
+	IMAXBEL                          = 0x2000
+	INLCR                            = 0x40
+	INPCK                            = 0x10
+	IN_ACCESS                        = 0x1
+	IN_ALL_EVENTS                    = 0xfff
+	IN_ATTRIB                        = 0x4
+	IN_CLASSA_HOST                   = 0xffffff
+	IN_CLASSA_MAX                    = 0x80
+	IN_CLASSA_NET                    = 0xff000000
+	IN_CLASSA_NSHIFT                 = 0x18
+	IN_CLASSB_HOST                   = 0xffff
+	IN_CLASSB_MAX                    = 0x10000
+	IN_CLASSB_NET                    = 0xffff0000
+	IN_CLASSB_NSHIFT                 = 0x10
+	IN_CLASSC_HOST                   = 0xff
+	IN_CLASSC_NET                    = 0xffffff00
+	IN_CLASSC_NSHIFT                 = 0x8
+	IN_CLOEXEC                       = 0x80000
+	IN_CLOSE                         = 0x18
+	IN_CLOSE_NOWRITE                 = 0x10
+	IN_CLOSE_WRITE                   = 0x8
+	IN_CREATE                        = 0x100
+	IN_DELETE                        = 0x200
+	IN_DELETE_SELF                   = 0x400
+	IN_DONT_FOLLOW                   = 0x2000000
+	IN_EXCL_UNLINK                   = 0x4000000
+	IN_IGNORED                       = 0x8000
+	IN_ISDIR                         = 0x40000000
+	IN_LOOPBACKNET                   = 0x7f
+	IN_MASK_ADD                      = 0x20000000
+	IN_MODIFY                        = 0x2
+	IN_MOVE                          = 0xc0
+	IN_MOVED_FROM                    = 0x40
+	IN_MOVED_TO                      = 0x80
+	IN_MOVE_SELF                     = 0x800
+	IN_NONBLOCK                      = 0x80
+	IN_ONESHOT                       = 0x80000000
+	IN_ONLYDIR                       = 0x1000000
+	IN_OPEN                          = 0x20
+	IN_Q_OVERFLOW                    = 0x4000
+	IN_UNMOUNT                       = 0x2000
+	IPPROTO_AH                       = 0x33
+	IPPROTO_COMP                     = 0x6c
+	IPPROTO_DCCP                     = 0x21
+	IPPROTO_DSTOPTS                  = 0x3c
+	IPPROTO_EGP                      = 0x8
+	IPPROTO_ENCAP                    = 0x62
+	IPPROTO_ESP                      = 0x32
+	IPPROTO_FRAGMENT                 = 0x2c
+	IPPROTO_GRE                      = 0x2f
+	IPPROTO_HOPOPTS                  = 0x0
+	IPPROTO_ICMP                     = 0x1
+	IPPROTO_ICMPV6                   = 0x3a
+	IPPROTO_IDP                      = 0x16
+	IPPROTO_IGMP                     = 0x2
+	IPPROTO_IP                       = 0x0
+	IPPROTO_IPIP                     = 0x4
+	IPPROTO_IPV6                     = 0x29
+	IPPROTO_MTP                      = 0x5c
+	IPPROTO_NONE                     = 0x3b
+	IPPROTO_PIM                      = 0x67
+	IPPROTO_PUP                      = 0xc
+	IPPROTO_RAW                      = 0xff
+	IPPROTO_ROUTING                  = 0x2b
+	IPPROTO_RSVP                     = 0x2e
+	IPPROTO_SCTP                     = 0x84
+	IPPROTO_TCP                      = 0x6
+	IPPROTO_TP                       = 0x1d
+	IPPROTO_UDP                      = 0x11
+	IPPROTO_UDPLITE                  = 0x88
+	IPV6_2292DSTOPTS                 = 0x4
+	IPV6_2292HOPLIMIT                = 0x8
+	IPV6_2292HOPOPTS                 = 0x3
+	IPV6_2292PKTINFO                 = 0x2
+	IPV6_2292PKTOPTIONS              = 0x6
+	IPV6_2292RTHDR                   = 0x5
+	IPV6_ADDRFORM                    = 0x1
+	IPV6_ADD_MEMBERSHIP              = 0x14
+	IPV6_AUTHHDR                     = 0xa
+	IPV6_CHECKSUM                    = 0x7
+	IPV6_DROP_MEMBERSHIP             = 0x15
+	IPV6_DSTOPTS                     = 0x3b
+	IPV6_HOPLIMIT                    = 0x34
+	IPV6_HOPOPTS                     = 0x36
+	IPV6_IPSEC_POLICY                = 0x22
+	IPV6_JOIN_ANYCAST                = 0x1b
+	IPV6_JOIN_GROUP                  = 0x14
+	IPV6_LEAVE_ANYCAST               = 0x1c
+	IPV6_LEAVE_GROUP                 = 0x15
+	IPV6_MTU                         = 0x18
+	IPV6_MTU_DISCOVER                = 0x17
+	IPV6_MULTICAST_HOPS              = 0x12
+	IPV6_MULTICAST_IF                = 0x11
+	IPV6_MULTICAST_LOOP              = 0x13
+	IPV6_NEXTHOP                     = 0x9
+	IPV6_PKTINFO                     = 0x32
+	IPV6_PMTUDISC_DO                 = 0x2
+	IPV6_PMTUDISC_DONT               = 0x0
+	IPV6_PMTUDISC_PROBE              = 0x3
+	IPV6_PMTUDISC_WANT               = 0x1
+	IPV6_RECVDSTOPTS                 = 0x3a
+	IPV6_RECVERR                     = 0x19
+	IPV6_RECVHOPLIMIT                = 0x33
+	IPV6_RECVHOPOPTS                 = 0x35
+	IPV6_RECVPKTINFO                 = 0x31
+	IPV6_RECVRTHDR                   = 0x38
+	IPV6_RECVTCLASS                  = 0x42
+	IPV6_ROUTER_ALERT                = 0x16
+	IPV6_RTHDR                       = 0x39
+	IPV6_RTHDRDSTOPTS                = 0x37
+	IPV6_RTHDR_LOOSE                 = 0x0
+	IPV6_RTHDR_STRICT                = 0x1
+	IPV6_RTHDR_TYPE_0                = 0x0
+	IPV6_RXDSTOPTS                   = 0x3b
+	IPV6_RXHOPOPTS                   = 0x36
+	IPV6_TCLASS                      = 0x43
+	IPV6_UNICAST_HOPS                = 0x10
+	IPV6_V6ONLY                      = 0x1a
+	IPV6_XFRM_POLICY                 = 0x23
+	IP_ADD_MEMBERSHIP                = 0x23
+	IP_ADD_SOURCE_MEMBERSHIP         = 0x27
+	IP_BLOCK_SOURCE                  = 0x26
+	IP_DEFAULT_MULTICAST_LOOP        = 0x1
+	IP_DEFAULT_MULTICAST_TTL         = 0x1
+	IP_DF                            = 0x4000
+	IP_DROP_MEMBERSHIP               = 0x24
+	IP_DROP_SOURCE_MEMBERSHIP        = 0x28
+	IP_FREEBIND                      = 0xf
+	IP_HDRINCL                       = 0x3
+	IP_IPSEC_POLICY                  = 0x10
+	IP_MAXPACKET                     = 0xffff
+	IP_MAX_MEMBERSHIPS               = 0x14
+	IP_MF                            = 0x2000
+	IP_MINTTL                        = 0x15
+	IP_MSFILTER                      = 0x29
+	IP_MSS                           = 0x240
+	IP_MTU                           = 0xe
+	IP_MTU_DISCOVER                  = 0xa
+	IP_MULTICAST_ALL                 = 0x31
+	IP_MULTICAST_IF                  = 0x20
+	IP_MULTICAST_LOOP                = 0x22
+	IP_MULTICAST_TTL                 = 0x21
+	IP_OFFMASK                       = 0x1fff
+	IP_OPTIONS                       = 0x4
+	IP_ORIGDSTADDR                   = 0x14
+	IP_PASSSEC                       = 0x12
+	IP_PKTINFO                       = 0x8
+	IP_PKTOPTIONS                    = 0x9
+	IP_PMTUDISC                      = 0xa
+	IP_PMTUDISC_DO                   = 0x2
+	IP_PMTUDISC_DONT                 = 0x0
+	IP_PMTUDISC_PROBE                = 0x3
+	IP_PMTUDISC_WANT                 = 0x1
+	IP_RECVERR                       = 0xb
+	IP_RECVOPTS                      = 0x6
+	IP_RECVORIGDSTADDR               = 0x14
+	IP_RECVRETOPTS                   = 0x7
+	IP_RECVTOS                       = 0xd
+	IP_RECVTTL                       = 0xc
+	IP_RETOPTS                       = 0x7
+	IP_RF                            = 0x8000
+	IP_ROUTER_ALERT                  = 0x5
+	IP_TOS                           = 0x1
+	IP_TRANSPARENT                   = 0x13
+	IP_TTL                           = 0x2
+	IP_UNBLOCK_SOURCE                = 0x25
+	IP_UNICAST_IF                    = 0x32
+	IP_XFRM_POLICY                   = 0x11
+	ISIG                             = 0x1
+	ISTRIP                           = 0x20
+	IUTF8                            = 0x4000
+	IXANY                            = 0x800
+	IXOFF                            = 0x1000
+	IXON                             = 0x400
+	LINUX_REBOOT_CMD_CAD_OFF         = 0x0
+	LINUX_REBOOT_CMD_CAD_ON          = 0x89abcdef
+	LINUX_REBOOT_CMD_HALT            = 0xcdef0123
+	LINUX_REBOOT_CMD_KEXEC           = 0x45584543
+	LINUX_REBOOT_CMD_POWER_OFF       = 0x4321fedc
+	LINUX_REBOOT_CMD_RESTART         = 0x1234567
+	LINUX_REBOOT_CMD_RESTART2        = 0xa1b2c3d4
+	LINUX_REBOOT_CMD_SW_SUSPEND      = 0xd000fce2
+	LINUX_REBOOT_MAGIC1              = 0xfee1dead
+	LINUX_REBOOT_MAGIC2              = 0x28121969
+	LOCK_EX                          = 0x2
+	LOCK_NB                          = 0x4
+	LOCK_SH                          = 0x1
+	LOCK_UN                          = 0x8
+	MADV_DODUMP                      = 0x11
+	MADV_DOFORK                      = 0xb
+	MADV_DONTDUMP                    = 0x10
+	MADV_DONTFORK                    = 0xa
+	MADV_DONTNEED                    = 0x4
+	MADV_HUGEPAGE                    = 0xe
+	MADV_HWPOISON                    = 0x64
+	MADV_MERGEABLE                   = 0xc
+	MADV_NOHUGEPAGE                  = 0xf
+	MADV_NORMAL                      = 0x0
+	MADV_RANDOM                      = 0x1
+	MADV_REMOVE                      = 0x9
+	MADV_SEQUENTIAL                  = 0x2
+	MADV_UNMERGEABLE                 = 0xd
+	MADV_WILLNEED                    = 0x3
+	MAP_ANON                         = 0x800
+	MAP_ANONYMOUS                    = 0x800
+	MAP_DENYWRITE                    = 0x2000
+	MAP_EXECUTABLE                   = 0x4000
+	MAP_FILE                         = 0x0
+	MAP_FIXED                        = 0x10
+	MAP_GROWSDOWN                    = 0x1000
+	MAP_HUGETLB                      = 0x80000
+	MAP_LOCKED                       = 0x8000
+	MAP_NONBLOCK                     = 0x20000
+	MAP_NORESERVE                    = 0x400
+	MAP_POPULATE                     = 0x10000
+	MAP_PRIVATE                      = 0x2
+	MAP_RENAME                       = 0x800
+	MAP_SHARED                       = 0x1
+	MAP_STACK                        = 0x40000
+	MAP_TYPE                         = 0xf
+	MCL_CURRENT                      = 0x1
+	MCL_FUTURE                       = 0x2
+	MNT_DETACH                       = 0x2
+	MNT_EXPIRE                       = 0x4
+	MNT_FORCE                        = 0x1
+	MSG_CMSG_CLOEXEC                 = 0x40000000
+	MSG_CONFIRM                      = 0x800
+	MSG_CTRUNC                       = 0x8
+	MSG_DONTROUTE                    = 0x4
+	MSG_DONTWAIT                     = 0x40
+	MSG_EOR                          = 0x80
+	MSG_ERRQUEUE                     = 0x2000
+	MSG_FASTOPEN                     = 0x20000000
+	MSG_FIN                          = 0x200
+	MSG_MORE                         = 0x8000
+	MSG_NOSIGNAL                     = 0x4000
+	MSG_OOB                          = 0x1
+	MSG_PEEK                         = 0x2
+	MSG_PROXY                        = 0x10
+	MSG_RST                          = 0x1000
+	MSG_SYN                          = 0x400
+	MSG_TRUNC                        = 0x20
+	MSG_TRYHARD                      = 0x4
+	MSG_WAITALL                      = 0x100
+	MSG_WAITFORONE                   = 0x10000
+	MS_ACTIVE                        = 0x40000000
+	MS_ASYNC                         = 0x1
+	MS_BIND                          = 0x1000
+	MS_DIRSYNC                       = 0x80
+	MS_INVALIDATE                    = 0x2
+	MS_I_VERSION                     = 0x800000
+	MS_KERNMOUNT                     = 0x400000
+	MS_MANDLOCK                      = 0x40
+	MS_MGC_MSK                       = 0xffff0000
+	MS_MGC_VAL                       = 0xc0ed0000
+	MS_MOVE                          = 0x2000
+	MS_NOATIME                       = 0x400
+	MS_NODEV                         = 0x4
+	MS_NODIRATIME                    = 0x800
+	MS_NOEXEC                        = 0x8
+	MS_NOSUID                        = 0x2
+	MS_NOUSER                        = -0x80000000
+	MS_POSIXACL                      = 0x10000
+	MS_PRIVATE                       = 0x40000
+	MS_RDONLY                        = 0x1
+	MS_REC                           = 0x4000
+	MS_RELATIME                      = 0x200000
+	MS_REMOUNT                       = 0x20
+	MS_RMT_MASK                      = 0x800051
+	MS_SHARED                        = 0x100000
+	MS_SILENT                        = 0x8000
+	MS_SLAVE                         = 0x80000
+	MS_STRICTATIME                   = 0x1000000
+	MS_SYNC                          = 0x4
+	MS_SYNCHRONOUS                   = 0x10
+	MS_UNBINDABLE                    = 0x20000
+	NAME_MAX                         = 0xff
+	NETLINK_ADD_MEMBERSHIP           = 0x1
+	NETLINK_AUDIT                    = 0x9
+	NETLINK_BROADCAST_ERROR          = 0x4
+	NETLINK_CONNECTOR                = 0xb
+	NETLINK_CRYPTO                   = 0x15
+	NETLINK_DNRTMSG                  = 0xe
+	NETLINK_DROP_MEMBERSHIP          = 0x2
+	NETLINK_ECRYPTFS                 = 0x13
+	NETLINK_FIB_LOOKUP               = 0xa
+	NETLINK_FIREWALL                 = 0x3
+	NETLINK_GENERIC                  = 0x10
+	NETLINK_INET_DIAG                = 0x4
+	NETLINK_IP6_FW                   = 0xd
+	NETLINK_ISCSI                    = 0x8
+	NETLINK_KOBJECT_UEVENT           = 0xf
+	NETLINK_NETFILTER                = 0xc
+	NETLINK_NFLOG                    = 0x5
+	NETLINK_NO_ENOBUFS               = 0x5
+	NETLINK_PKTINFO                  = 0x3
+	NETLINK_RDMA                     = 0x14
+	NETLINK_ROUTE                    = 0x0
+	NETLINK_RX_RING                  = 0x6
+	NETLINK_SCSITRANSPORT            = 0x12
+	NETLINK_SELINUX                  = 0x7
+	NETLINK_SOCK_DIAG                = 0x4
+	NETLINK_TX_RING                  = 0x7
+	NETLINK_UNUSED                   = 0x1
+	NETLINK_USERSOCK                 = 0x2
+	NETLINK_XFRM                     = 0x6
+	NLA_ALIGNTO                      = 0x4
+	NLA_F_NESTED                     = 0x8000
+	NLA_F_NET_BYTEORDER              = 0x4000
+	NLA_HDRLEN                       = 0x4
+	NLMSG_ALIGNTO                    = 0x4
+	NLMSG_DONE                       = 0x3
+	NLMSG_ERROR                      = 0x2
+	NLMSG_HDRLEN                     = 0x10
+	NLMSG_MIN_TYPE                   = 0x10
+	NLMSG_NOOP                       = 0x1
+	NLMSG_OVERRUN                    = 0x4
+	NLM_F_ACK                        = 0x4
+	NLM_F_APPEND                     = 0x800
+	NLM_F_ATOMIC                     = 0x400
+	NLM_F_CREATE                     = 0x400
+	NLM_F_DUMP                       = 0x300
+	NLM_F_DUMP_INTR                  = 0x10
+	NLM_F_ECHO                       = 0x8
+	NLM_F_EXCL                       = 0x200
+	NLM_F_MATCH                      = 0x200
+	NLM_F_MULTI                      = 0x2
+	NLM_F_REPLACE                    = 0x100
+	NLM_F_REQUEST                    = 0x1
+	NLM_F_ROOT                       = 0x100
+	NOFLSH                           = 0x80
+	OCRNL                            = 0x8
+	OFDEL                            = 0x80
+	OFILL                            = 0x40
+	ONLCR                            = 0x4
+	ONLRET                           = 0x20
+	ONOCR                            = 0x10
+	OPOST                            = 0x1
+	O_ACCMODE                        = 0x3
+	O_APPEND                         = 0x8
+	O_ASYNC                          = 0x1000
+	O_CLOEXEC                        = 0x80000
+	O_CREAT                          = 0x100
+	O_DIRECT                         = 0x8000
+	O_DIRECTORY                      = 0x10000
+	O_DSYNC                          = 0x10
+	O_EXCL                           = 0x400
+	O_FSYNC                          = 0x4010
+	O_LARGEFILE                      = 0x0
+	O_NDELAY                         = 0x80
+	O_NOATIME                        = 0x40000
+	O_NOCTTY                         = 0x800
+	O_NOFOLLOW                       = 0x20000
+	O_NONBLOCK                       = 0x80
+	O_PATH                           = 0x200000
+	O_RDONLY                         = 0x0
+	O_RDWR                           = 0x2
+	O_RSYNC                          = 0x4010
+	O_SYNC                           = 0x4010
+	O_TRUNC                          = 0x200
+	O_WRONLY                         = 0x1
+	PACKET_ADD_MEMBERSHIP            = 0x1
+	PACKET_AUXDATA                   = 0x8
+	PACKET_BROADCAST                 = 0x1
+	PACKET_COPY_THRESH               = 0x7
+	PACKET_DROP_MEMBERSHIP           = 0x2
+	PACKET_FANOUT                    = 0x12
+	PACKET_FANOUT_CPU                = 0x2
+	PACKET_FANOUT_FLAG_DEFRAG        = 0x8000
+	PACKET_FANOUT_FLAG_ROLLOVER      = 0x1000
+	PACKET_FANOUT_HASH               = 0x0
+	PACKET_FANOUT_LB                 = 0x1
+	PACKET_FANOUT_RND                = 0x4
+	PACKET_FANOUT_ROLLOVER           = 0x3
+	PACKET_FASTROUTE                 = 0x6
+	PACKET_HDRLEN                    = 0xb
+	PACKET_HOST                      = 0x0
+	PACKET_LOOPBACK                  = 0x5
+	PACKET_LOSS                      = 0xe
+	PACKET_MR_ALLMULTI               = 0x2
+	PACKET_MR_MULTICAST              = 0x0
+	PACKET_MR_PROMISC                = 0x1
+	PACKET_MR_UNICAST                = 0x3
+	PACKET_MULTICAST                 = 0x2
+	PACKET_ORIGDEV                   = 0x9
+	PACKET_OTHERHOST                 = 0x3
+	PACKET_OUTGOING                  = 0x4
+	PACKET_RECV_OUTPUT               = 0x3
+	PACKET_RESERVE                   = 0xc
+	PACKET_RX_RING                   = 0x5
+	PACKET_STATISTICS                = 0x6
+	PACKET_TIMESTAMP                 = 0x11
+	PACKET_TX_HAS_OFF                = 0x13
+	PACKET_TX_RING                   = 0xd
+	PACKET_TX_TIMESTAMP              = 0x10
+	PACKET_VERSION                   = 0xa
+	PACKET_VNET_HDR                  = 0xf
+	PARENB                           = 0x100
+	PARITY_CRC16_PR0                 = 0x2
+	PARITY_CRC16_PR0_CCITT           = 0x4
+	PARITY_CRC16_PR1                 = 0x3
+	PARITY_CRC16_PR1_CCITT           = 0x5
+	PARITY_CRC32_PR0_CCITT           = 0x6
+	PARITY_CRC32_PR1_CCITT           = 0x7
+	PARITY_DEFAULT                   = 0x0
+	PARITY_NONE                      = 0x1
+	PARMRK                           = 0x8
+	PARODD                           = 0x200
+	PENDIN                           = 0x4000
+	PRIO_PGRP                        = 0x1
+	PRIO_PROCESS                     = 0x0
+	PRIO_USER                        = 0x2
+	PROT_EXEC                        = 0x4
+	PROT_GROWSDOWN                   = 0x1000000
+	PROT_GROWSUP                     = 0x2000000
+	PROT_NONE                        = 0x0
+	PROT_READ                        = 0x1
+	PROT_WRITE                       = 0x2
+	PR_CAPBSET_DROP                  = 0x18
+	PR_CAPBSET_READ                  = 0x17
+	PR_ENDIAN_BIG                    = 0x0
+	PR_ENDIAN_LITTLE                 = 0x1
+	PR_ENDIAN_PPC_LITTLE             = 0x2
+	PR_FPEMU_NOPRINT                 = 0x1
+	PR_FPEMU_SIGFPE                  = 0x2
+	PR_FP_EXC_ASYNC                  = 0x2
+	PR_FP_EXC_DISABLED               = 0x0
+	PR_FP_EXC_DIV                    = 0x10000
+	PR_FP_EXC_INV                    = 0x100000
+	PR_FP_EXC_NONRECOV               = 0x1
+	PR_FP_EXC_OVF                    = 0x20000
+	PR_FP_EXC_PRECISE                = 0x3
+	PR_FP_EXC_RES                    = 0x80000
+	PR_FP_EXC_SW_ENABLE              = 0x80
+	PR_FP_EXC_UND                    = 0x40000
+	PR_GET_CHILD_SUBREAPER           = 0x25
+	PR_GET_DUMPABLE                  = 0x3
+	PR_GET_ENDIAN                    = 0x13
+	PR_GET_FPEMU                     = 0x9
+	PR_GET_FPEXC                     = 0xb
+	PR_GET_KEEPCAPS                  = 0x7
+	PR_GET_NAME                      = 0x10
+	PR_GET_NO_NEW_PRIVS              = 0x27
+	PR_GET_PDEATHSIG                 = 0x2
+	PR_GET_SECCOMP                   = 0x15
+	PR_GET_SECUREBITS                = 0x1b
+	PR_GET_TID_ADDRESS               = 0x28
+	PR_GET_TIMERSLACK                = 0x1e
+	PR_GET_TIMING                    = 0xd
+	PR_GET_TSC                       = 0x19
+	PR_GET_UNALIGN                   = 0x5
+	PR_MCE_KILL                      = 0x21
+	PR_MCE_KILL_CLEAR                = 0x0
+	PR_MCE_KILL_DEFAULT              = 0x2
+	PR_MCE_KILL_EARLY                = 0x1
+	PR_MCE_KILL_GET                  = 0x22
+	PR_MCE_KILL_LATE                 = 0x0
+	PR_MCE_KILL_SET                  = 0x1
+	PR_SET_CHILD_SUBREAPER           = 0x24
+	PR_SET_DUMPABLE                  = 0x4
+	PR_SET_ENDIAN                    = 0x14
+	PR_SET_FPEMU                     = 0xa
+	PR_SET_FPEXC                     = 0xc
+	PR_SET_KEEPCAPS                  = 0x8
+	PR_SET_MM                        = 0x23
+	PR_SET_MM_ARG_END                = 0x9
+	PR_SET_MM_ARG_START              = 0x8
+	PR_SET_MM_AUXV                   = 0xc
+	PR_SET_MM_BRK                    = 0x7
+	PR_SET_MM_END_CODE               = 0x2
+	PR_SET_MM_END_DATA               = 0x4
+	PR_SET_MM_ENV_END                = 0xb
+	PR_SET_MM_ENV_START              = 0xa
+	PR_SET_MM_EXE_FILE               = 0xd
+	PR_SET_MM_START_BRK              = 0x6
+	PR_SET_MM_START_CODE             = 0x1
+	PR_SET_MM_START_DATA             = 0x3
+	PR_SET_MM_START_STACK            = 0x5
+	PR_SET_NAME                      = 0xf
+	PR_SET_NO_NEW_PRIVS              = 0x26
+	PR_SET_PDEATHSIG                 = 0x1
+	PR_SET_PTRACER                   = 0x59616d61
+	PR_SET_PTRACER_ANY               = -0x1
+	PR_SET_SECCOMP                   = 0x16
+	PR_SET_SECUREBITS                = 0x1c
+	PR_SET_TIMERSLACK                = 0x1d
+	PR_SET_TIMING                    = 0xe
+	PR_SET_TSC                       = 0x1a
+	PR_SET_UNALIGN                   = 0x6
+	PR_TASK_PERF_EVENTS_DISABLE      = 0x1f
+	PR_TASK_PERF_EVENTS_ENABLE       = 0x20
+	PR_TIMING_STATISTICAL            = 0x0
+	PR_TIMING_TIMESTAMP              = 0x1
+	PR_TSC_ENABLE                    = 0x1
+	PR_TSC_SIGSEGV                   = 0x2
+	PR_UNALIGN_NOPRINT               = 0x1
+	PR_UNALIGN_SIGBUS                = 0x2
+	PTRACE_ATTACH                    = 0x10
+	PTRACE_CONT                      = 0x7
+	PTRACE_DETACH                    = 0x11
+	PTRACE_EVENT_CLONE               = 0x3
+	PTRACE_EVENT_EXEC                = 0x4
+	PTRACE_EVENT_EXIT                = 0x6
+	PTRACE_EVENT_FORK                = 0x1
+	PTRACE_EVENT_SECCOMP             = 0x7
+	PTRACE_EVENT_STOP                = 0x80
+	PTRACE_EVENT_VFORK               = 0x2
+	PTRACE_EVENT_VFORK_DONE          = 0x5
+	PTRACE_GETEVENTMSG               = 0x4201
+	PTRACE_GETFPREGS                 = 0xe
+	PTRACE_GETREGS                   = 0xc
+	PTRACE_GETREGSET                 = 0x4204
+	PTRACE_GETSIGINFO                = 0x4202
+	PTRACE_GETSIGMASK                = 0x420a
+	PTRACE_GET_THREAD_AREA           = 0x19
+	PTRACE_GET_THREAD_AREA_3264      = 0xc4
+	PTRACE_GET_WATCH_REGS            = 0xd0
+	PTRACE_INTERRUPT                 = 0x4207
+	PTRACE_KILL                      = 0x8
+	PTRACE_LISTEN                    = 0x4208
+	PTRACE_OLDSETOPTIONS             = 0x15
+	PTRACE_O_EXITKILL                = 0x100000
+	PTRACE_O_MASK                    = 0x1000ff
+	PTRACE_O_TRACECLONE              = 0x8
+	PTRACE_O_TRACEEXEC               = 0x10
+	PTRACE_O_TRACEEXIT               = 0x40
+	PTRACE_O_TRACEFORK               = 0x2
+	PTRACE_O_TRACESECCOMP            = 0x80
+	PTRACE_O_TRACESYSGOOD            = 0x1
+	PTRACE_O_TRACEVFORK              = 0x4
+	PTRACE_O_TRACEVFORKDONE          = 0x20
+	PTRACE_PEEKDATA                  = 0x2
+	PTRACE_PEEKDATA_3264             = 0xc1
+	PTRACE_PEEKSIGINFO               = 0x4209
+	PTRACE_PEEKSIGINFO_SHARED        = 0x1
+	PTRACE_PEEKTEXT                  = 0x1
+	PTRACE_PEEKTEXT_3264             = 0xc0
+	PTRACE_PEEKUSR                   = 0x3
+	PTRACE_POKEDATA                  = 0x5
+	PTRACE_POKEDATA_3264             = 0xc3
+	PTRACE_POKETEXT                  = 0x4
+	PTRACE_POKETEXT_3264             = 0xc2
+	PTRACE_POKEUSR                   = 0x6
+	PTRACE_SEIZE                     = 0x4206
+	PTRACE_SETFPREGS                 = 0xf
+	PTRACE_SETOPTIONS                = 0x4200
+	PTRACE_SETREGS                   = 0xd
+	PTRACE_SETREGSET                 = 0x4205
+	PTRACE_SETSIGINFO                = 0x4203
+	PTRACE_SETSIGMASK                = 0x420b
+	PTRACE_SET_THREAD_AREA           = 0x1a
+	PTRACE_SET_WATCH_REGS            = 0xd1
+	PTRACE_SINGLESTEP                = 0x9
+	PTRACE_SYSCALL                   = 0x18
+	PTRACE_TRACEME                   = 0x0
+	RLIMIT_AS                        = 0x6
+	RLIMIT_CORE                      = 0x4
+	RLIMIT_CPU                       = 0x0
+	RLIMIT_DATA                      = 0x2
+	RLIMIT_FSIZE                     = 0x1
+	RLIMIT_NOFILE                    = 0x5
+	RLIMIT_STACK                     = 0x3
+	RLIM_INFINITY                    = -0x1
+	RTAX_ADVMSS                      = 0x8
+	RTAX_CWND                        = 0x7
+	RTAX_FEATURES                    = 0xc
+	RTAX_FEATURE_ALLFRAG             = 0x8
+	RTAX_FEATURE_ECN                 = 0x1
+	RTAX_FEATURE_SACK                = 0x2
+	RTAX_FEATURE_TIMESTAMP           = 0x4
+	RTAX_HOPLIMIT                    = 0xa
+	RTAX_INITCWND                    = 0xb
+	RTAX_INITRWND                    = 0xe
+	RTAX_LOCK                        = 0x1
+	RTAX_MAX                         = 0xf
+	RTAX_MTU                         = 0x2
+	RTAX_QUICKACK                    = 0xf
+	RTAX_REORDERING                  = 0x9
+	RTAX_RTO_MIN                     = 0xd
+	RTAX_RTT                         = 0x4
+	RTAX_RTTVAR                      = 0x5
+	RTAX_SSTHRESH                    = 0x6
+	RTAX_UNSPEC                      = 0x0
+	RTAX_WINDOW                      = 0x3
+	RTA_ALIGNTO                      = 0x4
+	RTA_MAX                          = 0x11
+	RTCF_DIRECTSRC                   = 0x4000000
+	RTCF_DOREDIRECT                  = 0x1000000
+	RTCF_LOG                         = 0x2000000
+	RTCF_MASQ                        = 0x400000
+	RTCF_NAT                         = 0x800000
+	RTCF_VALVE                       = 0x200000
+	RTF_ADDRCLASSMASK                = 0xf8000000
+	RTF_ADDRCONF                     = 0x40000
+	RTF_ALLONLINK                    = 0x20000
+	RTF_BROADCAST                    = 0x10000000
+	RTF_CACHE                        = 0x1000000
+	RTF_DEFAULT                      = 0x10000
+	RTF_DYNAMIC                      = 0x10
+	RTF_FLOW                         = 0x2000000
+	RTF_GATEWAY                      = 0x2
+	RTF_HOST                         = 0x4
+	RTF_INTERFACE                    = 0x40000000
+	RTF_IRTT                         = 0x100
+	RTF_LINKRT                       = 0x100000
+	RTF_LOCAL                        = 0x80000000
+	RTF_MODIFIED                     = 0x20
+	RTF_MSS                          = 0x40
+	RTF_MTU                          = 0x40
+	RTF_MULTICAST                    = 0x20000000
+	RTF_NAT                          = 0x8000000
+	RTF_NOFORWARD                    = 0x1000
+	RTF_NONEXTHOP                    = 0x200000
+	RTF_NOPMTUDISC                   = 0x4000
+	RTF_POLICY                       = 0x4000000
+	RTF_REINSTATE                    = 0x8
+	RTF_REJECT                       = 0x200
+	RTF_STATIC                       = 0x400
+	RTF_THROW                        = 0x2000
+	RTF_UP                           = 0x1
+	RTF_WINDOW                       = 0x80
+	RTF_XRESOLVE                     = 0x800
+	RTM_BASE                         = 0x10
+	RTM_DELACTION                    = 0x31
+	RTM_DELADDR                      = 0x15
+	RTM_DELADDRLABEL                 = 0x49
+	RTM_DELLINK                      = 0x11
+	RTM_DELMDB                       = 0x55
+	RTM_DELNEIGH                     = 0x1d
+	RTM_DELQDISC                     = 0x25
+	RTM_DELROUTE                     = 0x19
+	RTM_DELRULE                      = 0x21
+	RTM_DELTCLASS                    = 0x29
+	RTM_DELTFILTER                   = 0x2d
+	RTM_F_CLONED                     = 0x200
+	RTM_F_EQUALIZE                   = 0x400
+	RTM_F_NOTIFY                     = 0x100
+	RTM_F_PREFIX                     = 0x800
+	RTM_GETACTION                    = 0x32
+	RTM_GETADDR                      = 0x16
+	RTM_GETADDRLABEL                 = 0x4a
+	RTM_GETANYCAST                   = 0x3e
+	RTM_GETDCB                       = 0x4e
+	RTM_GETLINK                      = 0x12
+	RTM_GETMDB                       = 0x56
+	RTM_GETMULTICAST                 = 0x3a
+	RTM_GETNEIGH                     = 0x1e
+	RTM_GETNEIGHTBL                  = 0x42
+	RTM_GETNETCONF                   = 0x52
+	RTM_GETQDISC                     = 0x26
+	RTM_GETROUTE                     = 0x1a
+	RTM_GETRULE                      = 0x22
+	RTM_GETTCLASS                    = 0x2a
+	RTM_GETTFILTER                   = 0x2e
+	RTM_MAX                          = 0x57
+	RTM_NEWACTION                    = 0x30
+	RTM_NEWADDR                      = 0x14
+	RTM_NEWADDRLABEL                 = 0x48
+	RTM_NEWLINK                      = 0x10
+	RTM_NEWMDB                       = 0x54
+	RTM_NEWNDUSEROPT                 = 0x44
+	RTM_NEWNEIGH                     = 0x1c
+	RTM_NEWNEIGHTBL                  = 0x40
+	RTM_NEWNETCONF                   = 0x50
+	RTM_NEWPREFIX                    = 0x34
+	RTM_NEWQDISC                     = 0x24
+	RTM_NEWROUTE                     = 0x18
+	RTM_NEWRULE                      = 0x20
+	RTM_NEWTCLASS                    = 0x28
+	RTM_NEWTFILTER                   = 0x2c
+	RTM_NR_FAMILIES                  = 0x12
+	RTM_NR_MSGTYPES                  = 0x48
+	RTM_SETDCB                       = 0x4f
+	RTM_SETLINK                      = 0x13
+	RTM_SETNEIGHTBL                  = 0x43
+	RTNH_ALIGNTO                     = 0x4
+	RTNH_F_DEAD                      = 0x1
+	RTNH_F_ONLINK                    = 0x4
+	RTNH_F_PERVASIVE                 = 0x2
+	RTN_MAX                          = 0xb
+	RTPROT_BIRD                      = 0xc
+	RTPROT_BOOT                      = 0x3
+	RTPROT_DHCP                      = 0x10
+	RTPROT_DNROUTED                  = 0xd
+	RTPROT_GATED                     = 0x8
+	RTPROT_KERNEL                    = 0x2
+	RTPROT_MROUTED                   = 0x11
+	RTPROT_MRT                       = 0xa
+	RTPROT_NTK                       = 0xf
+	RTPROT_RA                        = 0x9
+	RTPROT_REDIRECT                  = 0x1
+	RTPROT_STATIC                    = 0x4
+	RTPROT_UNSPEC                    = 0x0
+	RTPROT_XORP                      = 0xe
+	RTPROT_ZEBRA                     = 0xb
+	RT_CLASS_DEFAULT                 = 0xfd
+	RT_CLASS_LOCAL                   = 0xff
+	RT_CLASS_MAIN                    = 0xfe
+	RT_CLASS_MAX                     = 0xff
+	RT_CLASS_UNSPEC                  = 0x0
+	RUSAGE_CHILDREN                  = -0x1
+	RUSAGE_SELF                      = 0x0
+	RUSAGE_THREAD                    = 0x1
+	SCM_CREDENTIALS                  = 0x2
+	SCM_RIGHTS                       = 0x1
+	SCM_TIMESTAMP                    = 0x1d
+	SCM_TIMESTAMPING                 = 0x25
+	SCM_TIMESTAMPNS                  = 0x23
+	SCM_WIFI_STATUS                  = 0x29
+	SHUT_RD                          = 0x0
+	SHUT_RDWR                        = 0x2
+	SHUT_WR                          = 0x1
+	SIOCADDDLCI                      = 0x8980
+	SIOCADDMULTI                     = 0x8931
+	SIOCADDRT                        = 0x890b
+	SIOCATMARK                       = 0x40047307
+	SIOCDARP                         = 0x8953
+	SIOCDELDLCI                      = 0x8981
+	SIOCDELMULTI                     = 0x8932
+	SIOCDELRT                        = 0x890c
+	SIOCDEVPRIVATE                   = 0x89f0
+	SIOCDIFADDR                      = 0x8936
+	SIOCDRARP                        = 0x8960
+	SIOCGARP                         = 0x8954
+	SIOCGIFADDR                      = 0x8915
+	SIOCGIFBR                        = 0x8940
+	SIOCGIFBRDADDR                   = 0x8919
+	SIOCGIFCONF                      = 0x8912
+	SIOCGIFCOUNT                     = 0x8938
+	SIOCGIFDSTADDR                   = 0x8917
+	SIOCGIFENCAP                     = 0x8925
+	SIOCGIFFLAGS                     = 0x8913
+	SIOCGIFHWADDR                    = 0x8927
+	SIOCGIFINDEX                     = 0x8933
+	SIOCGIFMAP                       = 0x8970
+	SIOCGIFMEM                       = 0x891f
+	SIOCGIFMETRIC                    = 0x891d
+	SIOCGIFMTU                       = 0x8921
+	SIOCGIFNAME                      = 0x8910
+	SIOCGIFNETMASK                   = 0x891b
+	SIOCGIFPFLAGS                    = 0x8935
+	SIOCGIFSLAVE                     = 0x8929
+	SIOCGIFTXQLEN                    = 0x8942
+	SIOCGPGRP                        = 0x40047309
+	SIOCGRARP                        = 0x8961
+	SIOCGSTAMP                       = 0x8906
+	SIOCGSTAMPNS                     = 0x8907
+	SIOCPROTOPRIVATE                 = 0x89e0
+	SIOCRTMSG                        = 0x890d
+	SIOCSARP                         = 0x8955
+	SIOCSIFADDR                      = 0x8916
+	SIOCSIFBR                        = 0x8941
+	SIOCSIFBRDADDR                   = 0x891a
+	SIOCSIFDSTADDR                   = 0x8918
+	SIOCSIFENCAP                     = 0x8926
+	SIOCSIFFLAGS                     = 0x8914
+	SIOCSIFHWADDR                    = 0x8924
+	SIOCSIFHWBROADCAST               = 0x8937
+	SIOCSIFLINK                      = 0x8911
+	SIOCSIFMAP                       = 0x8971
+	SIOCSIFMEM                       = 0x8920
+	SIOCSIFMETRIC                    = 0x891e
+	SIOCSIFMTU                       = 0x8922
+	SIOCSIFNAME                      = 0x8923
+	SIOCSIFNETMASK                   = 0x891c
+	SIOCSIFPFLAGS                    = 0x8934
+	SIOCSIFSLAVE                     = 0x8930
+	SIOCSIFTXQLEN                    = 0x8943
+	SIOCSPGRP                        = 0x80047308
+	SIOCSRARP                        = 0x8962
+	SOCK_CLOEXEC                     = 0x80000
+	SOCK_DCCP                        = 0x6
+	SOCK_DGRAM                       = 0x1
+	SOCK_NONBLOCK                    = 0x80
+	SOCK_PACKET                      = 0xa
+	SOCK_RAW                         = 0x3
+	SOCK_RDM                         = 0x4
+	SOCK_SEQPACKET                   = 0x5
+	SOCK_STREAM                      = 0x2
+	SOL_AAL                          = 0x109
+	SOL_ATM                          = 0x108
+	SOL_DECNET                       = 0x105
+	SOL_ICMPV6                       = 0x3a
+	SOL_IP                           = 0x0
+	SOL_IPV6                         = 0x29
+	SOL_IRDA                         = 0x10a
+	SOL_PACKET                       = 0x107
+	SOL_RAW                          = 0xff
+	SOL_SOCKET                       = 0xffff
+	SOL_TCP                          = 0x6
+	SOL_X25                          = 0x106
+	SOMAXCONN                        = 0x80
+	SO_ACCEPTCONN                    = 0x1009
+	SO_ATTACH_FILTER                 = 0x1a
+	SO_BINDTODEVICE                  = 0x19
+	SO_BROADCAST                     = 0x20
+	SO_BSDCOMPAT                     = 0xe
+	SO_BUSY_POLL                     = 0x2e
+	SO_DEBUG                         = 0x1
+	SO_DETACH_FILTER                 = 0x1b
+	SO_DOMAIN                        = 0x1029
+	SO_DONTROUTE                     = 0x10
+	SO_ERROR                         = 0x1007
+	SO_GET_FILTER                    = 0x1a
+	SO_KEEPALIVE                     = 0x8
+	SO_LINGER                        = 0x80
+	SO_LOCK_FILTER                   = 0x2c
+	SO_MARK                          = 0x24
+	SO_NOFCS                         = 0x2b
+	SO_NO_CHECK                      = 0xb
+	SO_OOBINLINE                     = 0x100
+	SO_PASSCRED                      = 0x11
+	SO_PASSSEC                       = 0x22
+	SO_PEEK_OFF                      = 0x2a
+	SO_PEERCRED                      = 0x12
+	SO_PEERNAME                      = 0x1c
+	SO_PEERSEC                       = 0x1e
+	SO_PRIORITY                      = 0xc
+	SO_PROTOCOL                      = 0x1028
+	SO_RCVBUF                        = 0x1002
+	SO_RCVBUFFORCE                   = 0x21
+	SO_RCVLOWAT                      = 0x1004
+	SO_RCVTIMEO                      = 0x1006
+	SO_REUSEADDR                     = 0x4
+	SO_REUSEPORT                     = 0x200
+	SO_RXQ_OVFL                      = 0x28
+	SO_SECURITY_AUTHENTICATION       = 0x16
+	SO_SECURITY_ENCRYPTION_NETWORK   = 0x18
+	SO_SECURITY_ENCRYPTION_TRANSPORT = 0x17
+	SO_SELECT_ERR_QUEUE              = 0x2d
+	SO_SNDBUF                        = 0x1001
+	SO_SNDBUFFORCE                   = 0x1f
+	SO_SNDLOWAT                      = 0x1003
+	SO_SNDTIMEO                      = 0x1005
+	SO_STYLE                         = 0x1008
+	SO_TIMESTAMP                     = 0x1d
+	SO_TIMESTAMPING                  = 0x25
+	SO_TIMESTAMPNS                   = 0x23
+	SO_TYPE                          = 0x1008
+	SO_WIFI_STATUS                   = 0x29
+	S_BLKSIZE                        = 0x200
+	S_IEXEC                          = 0x40
+	S_IFBLK                          = 0x6000
+	S_IFCHR                          = 0x2000
+	S_IFDIR                          = 0x4000
+	S_IFIFO                          = 0x1000
+	S_IFLNK                          = 0xa000
+	S_IFMT                           = 0xf000
+	S_IFREG                          = 0x8000
+	S_IFSOCK                         = 0xc000
+	S_IREAD                          = 0x100
+	S_IRGRP                          = 0x20
+	S_IROTH                          = 0x4
+	S_IRUSR                          = 0x100
+	S_IRWXG                          = 0x38
+	S_IRWXO                          = 0x7
+	S_IRWXU                          = 0x1c0
+	S_ISGID                          = 0x400
+	S_ISUID                          = 0x800
+	S_ISVTX                          = 0x200
+	S_IWGRP                          = 0x10
+	S_IWOTH                          = 0x2
+	S_IWRITE                         = 0x80
+	S_IWUSR                          = 0x80
+	S_IXGRP                          = 0x8
+	S_IXOTH                          = 0x1
+	S_IXUSR                          = 0x40
+	TCFLSH                           = 0x5407
+	TCIFLUSH                         = 0x0
+	TCIOFLUSH                        = 0x2
+	TCOFLUSH                         = 0x1
+	TCP_CONGESTION                   = 0xd
+	TCP_CORK                         = 0x3
+	TCP_DEFER_ACCEPT                 = 0x9
+	TCP_INFO                         = 0xb
+	TCP_KEEPCNT                      = 0x6
+	TCP_KEEPIDLE                     = 0x4
+	TCP_KEEPINTVL                    = 0x5
+	TCP_LINGER2                      = 0x8
+	TCP_MAXSEG                       = 0x2
+	TCP_MAXWIN                       = 0xffff
+	TCP_MAX_WINSHIFT                 = 0xe
+	TCP_MD5SIG                       = 0xe
+	TCP_MD5SIG_MAXKEYLEN             = 0x50
+	TCP_MSS                          = 0x200
+	TCP_NODELAY                      = 0x1
+	TCP_QUICKACK                     = 0xc
+	TCP_SYNCNT                       = 0x7
+	TCP_WINDOW_CLAMP                 = 0xa
+	TCSAFLUSH                        = 0x5410
+	TIOCCBRK                         = 0x5428
+	TIOCCONS                         = 0x80047478
+	TIOCEXCL                         = 0x740d
+	TIOCGDEV                         = 0x40045432
+	TIOCGETD                         = 0x7400
+	TIOCGETP                         = 0x7408
+	TIOCGEXCL                        = 0x40045440
+	TIOCGICOUNT                      = 0x5492
+	TIOCGLCKTRMIOS                   = 0x548b
+	TIOCGLTC                         = 0x7474
+	TIOCGPGRP                        = 0x40047477
+	TIOCGPKT                         = 0x40045438
+	TIOCGPTLCK                       = 0x40045439
+	TIOCGPTN                         = 0x40045430
+	TIOCGSERIAL                      = 0x5484
+	TIOCGSID                         = 0x7416
+	TIOCGSOFTCAR                     = 0x5481
+	TIOCGWINSZ                       = 0x40087468
+	TIOCINQ                          = 0x467f
+	TIOCLINUX                        = 0x5483
+	TIOCMBIC                         = 0x741c
+	TIOCMBIS                         = 0x741b
+	TIOCMGET                         = 0x741d
+	TIOCMIWAIT                       = 0x5491
+	TIOCMSET                         = 0x741a
+	TIOCM_CAR                        = 0x100
+	TIOCM_CD                         = 0x100
+	TIOCM_CTS                        = 0x40
+	TIOCM_DSR                        = 0x400
+	TIOCM_DTR                        = 0x2
+	TIOCM_LE                         = 0x1
+	TIOCM_RI                         = 0x200
+	TIOCM_RNG                        = 0x200
+	TIOCM_RTS                        = 0x4
+	TIOCM_SR                         = 0x20
+	TIOCM_ST                         = 0x10
+	TIOCNOTTY                        = 0x5471
+	TIOCNXCL                         = 0x740e
+	TIOCOUTQ                         = 0x7472
+	TIOCPKT                          = 0x5470
+	TIOCPKT_DATA                     = 0x0
+	TIOCPKT_DOSTOP                   = 0x20
+	TIOCPKT_FLUSHREAD                = 0x1
+	TIOCPKT_FLUSHWRITE               = 0x2
+	TIOCPKT_IOCTL                    = 0x40
+	TIOCPKT_NOSTOP                   = 0x10
+	TIOCPKT_START                    = 0x8
+	TIOCPKT_STOP                     = 0x4
+	TIOCSBRK                         = 0x5427
+	TIOCSCTTY                        = 0x5480
+	TIOCSERCONFIG                    = 0x5488
+	TIOCSERGETLSR                    = 0x548e
+	TIOCSERGETMULTI                  = 0x548f
+	TIOCSERGSTRUCT                   = 0x548d
+	TIOCSERGWILD                     = 0x5489
+	TIOCSERSETMULTI                  = 0x5490
+	TIOCSERSWILD                     = 0x548a
+	TIOCSER_TEMT                     = 0x1
+	TIOCSETD                         = 0x7401
+	TIOCSETN                         = 0x740a
+	TIOCSETP                         = 0x7409
+	TIOCSIG                          = 0x80045436
+	TIOCSLCKTRMIOS                   = 0x548c
+	TIOCSLTC                         = 0x7475
+	TIOCSPGRP                        = 0x80047476
+	TIOCSPTLCK                       = 0x80045431
+	TIOCSSERIAL                      = 0x5485
+	TIOCSSOFTCAR                     = 0x5482
+	TIOCSTI                          = 0x5472
+	TIOCSWINSZ                       = 0x80087467
+	TIOCVHANGUP                      = 0x5437
+	TOSTOP                           = 0x8000
+	TUNATTACHFILTER                  = 0x801054d5
+	TUNDETACHFILTER                  = 0x801054d6
+	TUNGETFEATURES                   = 0x400454cf
+	TUNGETFILTER                     = 0x401054db
+	TUNGETIFF                        = 0x400454d2
+	TUNGETSNDBUF                     = 0x400454d3
+	TUNGETVNETHDRSZ                  = 0x400454d7
+	TUNSETDEBUG                      = 0x800454c9
+	TUNSETGROUP                      = 0x800454ce
+	TUNSETIFF                        = 0x800454ca
+	TUNSETIFINDEX                    = 0x800454da
+	TUNSETLINK                       = 0x800454cd
+	TUNSETNOCSUM                     = 0x800454c8
+	TUNSETOFFLOAD                    = 0x800454d0
+	TUNSETOWNER                      = 0x800454cc
+	TUNSETPERSIST                    = 0x800454cb
+	TUNSETQUEUE                      = 0x800454d9
+	TUNSETSNDBUF                     = 0x800454d4
+	TUNSETTXFILTER                   = 0x800454d1
+	TUNSETVNETHDRSZ                  = 0x800454d8
+	VDISCARD                         = 0xd
+	VEOF                             = 0x10
+	VEOL                             = 0x11
+	VEOL2                            = 0x6
+	VERASE                           = 0x2
+	VINTR                            = 0x0
+	VKILL                            = 0x3
+	VLNEXT                           = 0xf
+	VMIN                             = 0x4
+	VQUIT                            = 0x1
+	VREPRINT                         = 0xc
+	VSTART                           = 0x8
+	VSTOP                            = 0x9
+	VSUSP                            = 0xa
+	VSWTC                            = 0x7
+	VSWTCH                           = 0x7
+	VT0                              = 0x0
+	VT1                              = 0x4000
+	VTDLY                            = 0x4000
+	VTIME                            = 0x5
+	VWERASE                          = 0xe
+	WALL                             = 0x40000000
+	WCLONE                           = 0x80000000
+	WCONTINUED                       = 0x8
+	WEXITED                          = 0x4
+	WNOHANG                          = 0x1
+	WNOTHREAD                        = 0x20000000
+	WNOWAIT                          = 0x1000000
+	WORDSIZE                         = 0x40
+	WSTOPPED                         = 0x2
+	WUNTRACED                        = 0x2
+)
+
+// Errors
+const (
+	E2BIG           = Errno(0x7)
+	EACCES          = Errno(0xd)
+	EADDRINUSE      = Errno(0x7d)
+	EADDRNOTAVAIL   = Errno(0x7e)
+	EADV            = Errno(0x44)
+	EAFNOSUPPORT    = Errno(0x7c)
+	EAGAIN          = Errno(0xb)
+	EALREADY        = Errno(0x95)
+	EBADE           = Errno(0x32)
+	EBADF           = Errno(0x9)
+	EBADFD          = Errno(0x51)
+	EBADMSG         = Errno(0x4d)
+	EBADR           = Errno(0x33)
+	EBADRQC         = Errno(0x36)
+	EBADSLT         = Errno(0x37)
+	EBFONT          = Errno(0x3b)
+	EBUSY           = Errno(0x10)
+	ECANCELED       = Errno(0x9e)
+	ECHILD          = Errno(0xa)
+	ECHRNG          = Errno(0x25)
+	ECOMM           = Errno(0x46)
+	ECONNABORTED    = Errno(0x82)
+	ECONNREFUSED    = Errno(0x92)
+	ECONNRESET      = Errno(0x83)
+	EDEADLK         = Errno(0x2d)
+	EDEADLOCK       = Errno(0x38)
+	EDESTADDRREQ    = Errno(0x60)
+	EDOM            = Errno(0x21)
+	EDOTDOT         = Errno(0x49)
+	EDQUOT          = Errno(0x46d)
+	EEXIST          = Errno(0x11)
+	EFAULT          = Errno(0xe)
+	EFBIG           = Errno(0x1b)
+	EHOSTDOWN       = Errno(0x93)
+	EHOSTUNREACH    = Errno(0x94)
+	EHWPOISON       = Errno(0xa8)
+	EIDRM           = Errno(0x24)
+	EILSEQ          = Errno(0x58)
+	EINIT           = Errno(0x8d)
+	EINPROGRESS     = Errno(0x96)
+	EINTR           = Errno(0x4)
+	EINVAL          = Errno(0x16)
+	EIO             = Errno(0x5)
+	EISCONN         = Errno(0x85)
+	EISDIR          = Errno(0x15)
+	EISNAM          = Errno(0x8b)
+	EKEYEXPIRED     = Errno(0xa2)
+	EKEYREJECTED    = Errno(0xa4)
+	EKEYREVOKED     = Errno(0xa3)
+	EL2HLT          = Errno(0x2c)
+	EL2NSYNC        = Errno(0x26)
+	EL3HLT          = Errno(0x27)
+	EL3RST          = Errno(0x28)
+	ELIBACC         = Errno(0x53)
+	ELIBBAD         = Errno(0x54)
+	ELIBEXEC        = Errno(0x57)
+	ELIBMAX         = Errno(0x56)
+	ELIBSCN         = Errno(0x55)
+	ELNRNG          = Errno(0x29)
+	ELOOP           = Errno(0x5a)
+	EMEDIUMTYPE     = Errno(0xa0)
+	EMFILE          = Errno(0x18)
+	EMLINK          = Errno(0x1f)
+	EMSGSIZE        = Errno(0x61)
+	EMULTIHOP       = Errno(0x4a)
+	ENAMETOOLONG    = Errno(0x4e)
+	ENAVAIL         = Errno(0x8a)
+	ENETDOWN        = Errno(0x7f)
+	ENETRESET       = Errno(0x81)
+	ENETUNREACH     = Errno(0x80)
+	ENFILE          = Errno(0x17)
+	ENOANO          = Errno(0x35)
+	ENOBUFS         = Errno(0x84)
+	ENOCSI          = Errno(0x2b)
+	ENODATA         = Errno(0x3d)
+	ENODEV          = Errno(0x13)
+	ENOENT          = Errno(0x2)
+	ENOEXEC         = Errno(0x8)
+	ENOKEY          = Errno(0xa1)
+	ENOLCK          = Errno(0x2e)
+	ENOLINK         = Errno(0x43)
+	ENOMEDIUM       = Errno(0x9f)
+	ENOMEM          = Errno(0xc)
+	ENOMSG          = Errno(0x23)
+	ENONET          = Errno(0x40)
+	ENOPKG          = Errno(0x41)
+	ENOPROTOOPT     = Errno(0x63)
+	ENOSPC          = Errno(0x1c)
+	ENOSR           = Errno(0x3f)
+	ENOSTR          = Errno(0x3c)
+	ENOSYS          = Errno(0x59)
+	ENOTBLK         = Errno(0xf)
+	ENOTCONN        = Errno(0x86)
+	ENOTDIR         = Errno(0x14)
+	ENOTEMPTY       = Errno(0x5d)
+	ENOTNAM         = Errno(0x89)
+	ENOTRECOVERABLE = Errno(0xa6)
+	ENOTSOCK        = Errno(0x5f)
+	ENOTSUP         = Errno(0x7a)
+	ENOTTY          = Errno(0x19)
+	ENOTUNIQ        = Errno(0x50)
+	ENXIO           = Errno(0x6)
+	EOPNOTSUPP      = Errno(0x7a)
+	EOVERFLOW       = Errno(0x4f)
+	EOWNERDEAD      = Errno(0xa5)
+	EPERM           = Errno(0x1)
+	EPFNOSUPPORT    = Errno(0x7b)
+	EPIPE           = Errno(0x20)
+	EPROTO          = Errno(0x47)
+	EPROTONOSUPPORT = Errno(0x78)
+	EPROTOTYPE      = Errno(0x62)
+	ERANGE          = Errno(0x22)
+	EREMCHG         = Errno(0x52)
+	EREMDEV         = Errno(0x8e)
+	EREMOTE         = Errno(0x42)
+	EREMOTEIO       = Errno(0x8c)
+	ERESTART        = Errno(0x5b)
+	ERFKILL         = Errno(0xa7)
+	EROFS           = Errno(0x1e)
+	ESHUTDOWN       = Errno(0x8f)
+	ESOCKTNOSUPPORT = Errno(0x79)
+	ESPIPE          = Errno(0x1d)
+	ESRCH           = Errno(0x3)
+	ESRMNT          = Errno(0x45)
+	ESTALE          = Errno(0x97)
+	ESTRPIPE        = Errno(0x5c)
+	ETIME           = Errno(0x3e)
+	ETIMEDOUT       = Errno(0x91)
+	ETOOMANYREFS    = Errno(0x90)
+	ETXTBSY         = Errno(0x1a)
+	EUCLEAN         = Errno(0x87)
+	EUNATCH         = Errno(0x2a)
+	EUSERS          = Errno(0x5e)
+	EWOULDBLOCK     = Errno(0xb)
+	EXDEV           = Errno(0x12)
+	EXFULL          = Errno(0x34)
+)
+
+// Signals
+const (
+	SIGABRT   = Signal(0x6)
+	SIGALRM   = Signal(0xe)
+	SIGBUS    = Signal(0xa)
+	SIGCHLD   = Signal(0x12)
+	SIGCLD    = Signal(0x12)
+	SIGCONT   = Signal(0x19)
+	SIGEMT    = Signal(0x7)
+	SIGFPE    = Signal(0x8)
+	SIGHUP    = Signal(0x1)
+	SIGILL    = Signal(0x4)
+	SIGINT    = Signal(0x2)
+	SIGIO     = Signal(0x16)
+	SIGIOT    = Signal(0x6)
+	SIGKILL   = Signal(0x9)
+	SIGPIPE   = Signal(0xd)
+	SIGPOLL   = Signal(0x16)
+	SIGPROF   = Signal(0x1d)
+	SIGPWR    = Signal(0x13)
+	SIGQUIT   = Signal(0x3)
+	SIGSEGV   = Signal(0xb)
+	SIGSTOP   = Signal(0x17)
+	SIGSYS    = Signal(0xc)
+	SIGTERM   = Signal(0xf)
+	SIGTRAP   = Signal(0x5)
+	SIGTSTP   = Signal(0x18)
+	SIGTTIN   = Signal(0x1a)
+	SIGTTOU   = Signal(0x1b)
+	SIGURG    = Signal(0x15)
+	SIGUSR1   = Signal(0x10)
+	SIGUSR2   = Signal(0x11)
+	SIGVTALRM = Signal(0x1c)
+	SIGWINCH  = Signal(0x14)
+	SIGXCPU   = Signal(0x1e)
+	SIGXFSZ   = Signal(0x1f)
+)
+
+// Error table
+var errors = [...]string{
+	1:    "operation not permitted",
+	2:    "no such file or directory",
+	3:    "no such process",
+	4:    "interrupted system call",
+	5:    "input/output error",
+	6:    "no such device or address",
+	7:    "argument list too long",
+	8:    "exec format error",
+	9:    "bad file descriptor",
+	10:   "no child processes",
+	11:   "resource temporarily unavailable",
+	12:   "cannot allocate memory",
+	13:   "permission denied",
+	14:   "bad address",
+	15:   "block device required",
+	16:   "device or resource busy",
+	17:   "file exists",
+	18:   "invalid cross-device link",
+	19:   "no such device",
+	20:   "not a directory",
+	21:   "is a directory",
+	22:   "invalid argument",
+	23:   "too many open files in system",
+	24:   "too many open files",
+	25:   "inappropriate ioctl for device",
+	26:   "text file busy",
+	27:   "file too large",
+	28:   "no space left on device",
+	29:   "illegal seek",
+	30:   "read-only file system",
+	31:   "too many links",
+	32:   "broken pipe",
+	33:   "numerical argument out of domain",
+	34:   "numerical result out of range",
+	35:   "no message of desired type",
+	36:   "identifier removed",
+	37:   "channel number out of range",
+	38:   "level 2 not synchronized",
+	39:   "level 3 halted",
+	40:   "level 3 reset",
+	41:   "link number out of range",
+	42:   "protocol driver not attached",
+	43:   "no CSI structure available",
+	44:   "level 2 halted",
+	45:   "resource deadlock avoided",
+	46:   "no locks available",
+	50:   "invalid exchange",
+	51:   "invalid request descriptor",
+	52:   "exchange full",
+	53:   "no anode",
+	54:   "invalid request code",
+	55:   "invalid slot",
+	56:   "file locking deadlock error",
+	59:   "bad font file format",
+	60:   "device not a stream",
+	61:   "no data available",
+	62:   "timer expired",
+	63:   "out of streams resources",
+	64:   "machine is not on the network",
+	65:   "package not installed",
+	66:   "object is remote",
+	67:   "link has been severed",
+	68:   "advertise error",
+	69:   "srmount error",
+	70:   "communication error on send",
+	71:   "protocol error",
+	73:   "RFS specific error",
+	74:   "multihop attempted",
+	77:   "bad message",
+	78:   "file name too long",
+	79:   "value too large for defined data type",
+	80:   "name not unique on network",
+	81:   "file descriptor in bad state",
+	82:   "remote address changed",
+	83:   "can not access a needed shared library",
+	84:   "accessing a corrupted shared library",
+	85:   ".lib section in a.out corrupted",
+	86:   "attempting to link in too many shared libraries",
+	87:   "cannot exec a shared library directly",
+	88:   "invalid or incomplete multibyte or wide character",
+	89:   "function not implemented",
+	90:   "too many levels of symbolic links",
+	91:   "interrupted system call should be restarted",
+	92:   "streams pipe error",
+	93:   "directory not empty",
+	94:   "too many users",
+	95:   "socket operation on non-socket",
+	96:   "destination address required",
+	97:   "message too long",
+	98:   "protocol wrong type for socket",
+	99:   "protocol not available",
+	120:  "protocol not supported",
+	121:  "socket type not supported",
+	122:  "operation not supported",
+	123:  "protocol family not supported",
+	124:  "address family not supported by protocol",
+	125:  "address already in use",
+	126:  "cannot assign requested address",
+	127:  "network is down",
+	128:  "network is unreachable",
+	129:  "network dropped connection on reset",
+	130:  "software caused connection abort",
+	131:  "connection reset by peer",
+	132:  "no buffer space available",
+	133:  "transport endpoint is already connected",
+	134:  "transport endpoint is not connected",
+	135:  "structure needs cleaning",
+	137:  "not a XENIX named type file",
+	138:  "no XENIX semaphores available",
+	139:  "is a named type file",
+	140:  "remote I/O error",
+	141:  "unknown error 141",
+	142:  "unknown error 142",
+	143:  "cannot send after transport endpoint shutdown",
+	144:  "too many references: cannot splice",
+	145:  "connection timed out",
+	146:  "connection refused",
+	147:  "host is down",
+	148:  "no route to host",
+	149:  "operation already in progress",
+	150:  "operation now in progress",
+	151:  "stale NFS file handle",
+	158:  "operation canceled",
+	159:  "no medium found",
+	160:  "wrong medium type",
+	161:  "required key not available",
+	162:  "key has expired",
+	163:  "key has been revoked",
+	164:  "key was rejected by service",
+	165:  "owner died",
+	166:  "state not recoverable",
+	167:  "operation not possible due to RF-kill",
+	168:  "memory page has hardware error",
+	1133: "disk quota exceeded",
+}
+
+// Signal table
+var signals = [...]string{
+	1:  "hangup",
+	2:  "interrupt",
+	3:  "quit",
+	4:  "illegal instruction",
+	5:  "trace/breakpoint trap",
+	6:  "aborted",
+	7:  "EMT trap",
+	8:  "floating point exception",
+	9:  "killed",
+	10: "bus error",
+	11: "segmentation fault",
+	12: "bad system call",
+	13: "broken pipe",
+	14: "alarm clock",
+	15: "terminated",
+	16: "user defined signal 1",
+	17: "user defined signal 2",
+	18: "child exited",
+	19: "power failure",
+	20: "window changed",
+	21: "urgent I/O condition",
+	22: "I/O possible",
+	23: "stopped (signal)",
+	24: "stopped",
+	25: "continued",
+	26: "stopped (tty input)",
+	27: "stopped (tty output)",
+	28: "virtual timer expired",
+	29: "profiling timer expired",
+	30: "CPU time limit exceeded",
+	31: "file size limit exceeded",
+}
diff --git a/src/syscall/zerrors_linux_mips64le.go b/src/syscall/zerrors_linux_mips64le.go
new file mode 100644
index 0000000..e6399dd
--- /dev/null
+++ b/src/syscall/zerrors_linux_mips64le.go
@@ -0,0 +1,1817 @@
+// mkerrors.sh
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs _const.go
+
+package syscall
+
+const (
+	AF_ALG                           = 0x26
+	AF_APPLETALK                     = 0x5
+	AF_ASH                           = 0x12
+	AF_ATMPVC                        = 0x8
+	AF_ATMSVC                        = 0x14
+	AF_AX25                          = 0x3
+	AF_BLUETOOTH                     = 0x1f
+	AF_BRIDGE                        = 0x7
+	AF_CAIF                          = 0x25
+	AF_CAN                           = 0x1d
+	AF_DECnet                        = 0xc
+	AF_ECONET                        = 0x13
+	AF_FILE                          = 0x1
+	AF_IEEE802154                    = 0x24
+	AF_INET                          = 0x2
+	AF_INET6                         = 0xa
+	AF_IPX                           = 0x4
+	AF_IRDA                          = 0x17
+	AF_ISDN                          = 0x22
+	AF_IUCV                          = 0x20
+	AF_KEY                           = 0xf
+	AF_LLC                           = 0x1a
+	AF_LOCAL                         = 0x1
+	AF_MAX                           = 0x28
+	AF_NETBEUI                       = 0xd
+	AF_NETLINK                       = 0x10
+	AF_NETROM                        = 0x6
+	AF_NFC                           = 0x27
+	AF_PACKET                        = 0x11
+	AF_PHONET                        = 0x23
+	AF_PPPOX                         = 0x18
+	AF_RDS                           = 0x15
+	AF_ROSE                          = 0xb
+	AF_ROUTE                         = 0x10
+	AF_RXRPC                         = 0x21
+	AF_SECURITY                      = 0xe
+	AF_SNA                           = 0x16
+	AF_TIPC                          = 0x1e
+	AF_UNIX                          = 0x1
+	AF_UNSPEC                        = 0x0
+	AF_WANPIPE                       = 0x19
+	AF_X25                           = 0x9
+	ARPHRD_ADAPT                     = 0x108
+	ARPHRD_APPLETLK                  = 0x8
+	ARPHRD_ARCNET                    = 0x7
+	ARPHRD_ASH                       = 0x30d
+	ARPHRD_ATM                       = 0x13
+	ARPHRD_AX25                      = 0x3
+	ARPHRD_BIF                       = 0x307
+	ARPHRD_CAIF                      = 0x336
+	ARPHRD_CAN                       = 0x118
+	ARPHRD_CHAOS                     = 0x5
+	ARPHRD_CISCO                     = 0x201
+	ARPHRD_CSLIP                     = 0x101
+	ARPHRD_CSLIP6                    = 0x103
+	ARPHRD_DDCMP                     = 0x205
+	ARPHRD_DLCI                      = 0xf
+	ARPHRD_ECONET                    = 0x30e
+	ARPHRD_EETHER                    = 0x2
+	ARPHRD_ETHER                     = 0x1
+	ARPHRD_EUI64                     = 0x1b
+	ARPHRD_FCAL                      = 0x311
+	ARPHRD_FCFABRIC                  = 0x313
+	ARPHRD_FCPL                      = 0x312
+	ARPHRD_FCPP                      = 0x310
+	ARPHRD_FDDI                      = 0x306
+	ARPHRD_FRAD                      = 0x302
+	ARPHRD_HDLC                      = 0x201
+	ARPHRD_HIPPI                     = 0x30c
+	ARPHRD_HWX25                     = 0x110
+	ARPHRD_IEEE1394                  = 0x18
+	ARPHRD_IEEE802                   = 0x6
+	ARPHRD_IEEE80211                 = 0x321
+	ARPHRD_IEEE80211_PRISM           = 0x322
+	ARPHRD_IEEE80211_RADIOTAP        = 0x323
+	ARPHRD_IEEE802154                = 0x324
+	ARPHRD_IEEE802154_MONITOR        = 0x325
+	ARPHRD_IEEE802_TR                = 0x320
+	ARPHRD_INFINIBAND                = 0x20
+	ARPHRD_IP6GRE                    = 0x337
+	ARPHRD_IPDDP                     = 0x309
+	ARPHRD_IPGRE                     = 0x30a
+	ARPHRD_IRDA                      = 0x30f
+	ARPHRD_LAPB                      = 0x204
+	ARPHRD_LOCALTLK                  = 0x305
+	ARPHRD_LOOPBACK                  = 0x304
+	ARPHRD_METRICOM                  = 0x17
+	ARPHRD_NETLINK                   = 0x338
+	ARPHRD_NETROM                    = 0x0
+	ARPHRD_NONE                      = 0xfffe
+	ARPHRD_PHONET                    = 0x334
+	ARPHRD_PHONET_PIPE               = 0x335
+	ARPHRD_PIMREG                    = 0x30b
+	ARPHRD_PPP                       = 0x200
+	ARPHRD_PRONET                    = 0x4
+	ARPHRD_RAWHDLC                   = 0x206
+	ARPHRD_ROSE                      = 0x10e
+	ARPHRD_RSRVD                     = 0x104
+	ARPHRD_SIT                       = 0x308
+	ARPHRD_SKIP                      = 0x303
+	ARPHRD_SLIP                      = 0x100
+	ARPHRD_SLIP6                     = 0x102
+	ARPHRD_TUNNEL                    = 0x300
+	ARPHRD_TUNNEL6                   = 0x301
+	ARPHRD_VOID                      = 0xffff
+	ARPHRD_X25                       = 0x10f
+	B0                               = 0x0
+	B1000000                         = 0x1008
+	B110                             = 0x3
+	B115200                          = 0x1002
+	B1152000                         = 0x1009
+	B1200                            = 0x9
+	B134                             = 0x4
+	B150                             = 0x5
+	B1500000                         = 0x100a
+	B1800                            = 0xa
+	B19200                           = 0xe
+	B200                             = 0x6
+	B2000000                         = 0x100b
+	B230400                          = 0x1003
+	B2400                            = 0xb
+	B2500000                         = 0x100c
+	B300                             = 0x7
+	B3000000                         = 0x100d
+	B3500000                         = 0x100e
+	B38400                           = 0xf
+	B4000000                         = 0x100f
+	B460800                          = 0x1004
+	B4800                            = 0xc
+	B50                              = 0x1
+	B500000                          = 0x1005
+	B57600                           = 0x1001
+	B576000                          = 0x1006
+	B600                             = 0x8
+	B75                              = 0x2
+	B921600                          = 0x1007
+	B9600                            = 0xd
+	BPF_A                            = 0x10
+	BPF_ABS                          = 0x20
+	BPF_ADD                          = 0x0
+	BPF_ALU                          = 0x4
+	BPF_AND                          = 0x50
+	BPF_B                            = 0x10
+	BPF_DIV                          = 0x30
+	BPF_H                            = 0x8
+	BPF_IMM                          = 0x0
+	BPF_IND                          = 0x40
+	BPF_JA                           = 0x0
+	BPF_JEQ                          = 0x10
+	BPF_JGE                          = 0x30
+	BPF_JGT                          = 0x20
+	BPF_JMP                          = 0x5
+	BPF_JSET                         = 0x40
+	BPF_K                            = 0x0
+	BPF_LD                           = 0x0
+	BPF_LDX                          = 0x1
+	BPF_LEN                          = 0x80
+	BPF_LSH                          = 0x60
+	BPF_MAJOR_VERSION                = 0x1
+	BPF_MAXINSNS                     = 0x1000
+	BPF_MEM                          = 0x60
+	BPF_MEMWORDS                     = 0x10
+	BPF_MINOR_VERSION                = 0x1
+	BPF_MISC                         = 0x7
+	BPF_MOD                          = 0x90
+	BPF_MSH                          = 0xa0
+	BPF_MUL                          = 0x20
+	BPF_NEG                          = 0x80
+	BPF_OR                           = 0x40
+	BPF_RET                          = 0x6
+	BPF_RSH                          = 0x70
+	BPF_ST                           = 0x2
+	BPF_STX                          = 0x3
+	BPF_SUB                          = 0x10
+	BPF_TAX                          = 0x0
+	BPF_TXA                          = 0x80
+	BPF_W                            = 0x0
+	BPF_X                            = 0x8
+	BPF_XOR                          = 0xa0
+	BRKINT                           = 0x2
+	CFLUSH                           = 0xf
+	CLOCAL                           = 0x800
+	CLONE_CHILD_CLEARTID             = 0x200000
+	CLONE_CHILD_SETTID               = 0x1000000
+	CLONE_DETACHED                   = 0x400000
+	CLONE_FILES                      = 0x400
+	CLONE_FS                         = 0x200
+	CLONE_IO                         = 0x80000000
+	CLONE_NEWIPC                     = 0x8000000
+	CLONE_NEWNET                     = 0x40000000
+	CLONE_NEWNS                      = 0x20000
+	CLONE_NEWPID                     = 0x20000000
+	CLONE_NEWUSER                    = 0x10000000
+	CLONE_NEWUTS                     = 0x4000000
+	CLONE_PARENT                     = 0x8000
+	CLONE_PARENT_SETTID              = 0x100000
+	CLONE_PTRACE                     = 0x2000
+	CLONE_SETTLS                     = 0x80000
+	CLONE_SIGHAND                    = 0x800
+	CLONE_SYSVSEM                    = 0x40000
+	CLONE_THREAD                     = 0x10000
+	CLONE_UNTRACED                   = 0x800000
+	CLONE_VFORK                      = 0x4000
+	CLONE_VM                         = 0x100
+	CREAD                            = 0x80
+	CS5                              = 0x0
+	CS6                              = 0x10
+	CS7                              = 0x20
+	CS8                              = 0x30
+	CSIGNAL                          = 0xff
+	CSIZE                            = 0x30
+	CSTART                           = 0x11
+	CSTATUS                          = 0x0
+	CSTOP                            = 0x13
+	CSTOPB                           = 0x40
+	CSUSP                            = 0x1a
+	DT_BLK                           = 0x6
+	DT_CHR                           = 0x2
+	DT_DIR                           = 0x4
+	DT_FIFO                          = 0x1
+	DT_LNK                           = 0xa
+	DT_REG                           = 0x8
+	DT_SOCK                          = 0xc
+	DT_UNKNOWN                       = 0x0
+	DT_WHT                           = 0xe
+	ECHO                             = 0x8
+	ECHOCTL                          = 0x200
+	ECHOE                            = 0x10
+	ECHOK                            = 0x20
+	ECHOKE                           = 0x800
+	ECHONL                           = 0x40
+	ECHOPRT                          = 0x400
+	ENCODING_DEFAULT                 = 0x0
+	ENCODING_FM_MARK                 = 0x3
+	ENCODING_FM_SPACE                = 0x4
+	ENCODING_MANCHESTER              = 0x5
+	ENCODING_NRZ                     = 0x1
+	ENCODING_NRZI                    = 0x2
+	EPOLLERR                         = 0x8
+	EPOLLET                          = 0x80000000
+	EPOLLHUP                         = 0x10
+	EPOLLIN                          = 0x1
+	EPOLLMSG                         = 0x400
+	EPOLLONESHOT                     = 0x40000000
+	EPOLLOUT                         = 0x4
+	EPOLLPRI                         = 0x2
+	EPOLLRDBAND                      = 0x80
+	EPOLLRDHUP                       = 0x2000
+	EPOLLRDNORM                      = 0x40
+	EPOLLWAKEUP                      = 0x20000000
+	EPOLLWRBAND                      = 0x200
+	EPOLLWRNORM                      = 0x100
+	EPOLL_CLOEXEC                    = 0x80000
+	EPOLL_CTL_ADD                    = 0x1
+	EPOLL_CTL_DEL                    = 0x2
+	EPOLL_CTL_MOD                    = 0x3
+	EPOLL_NONBLOCK                   = 0x80
+	ETH_P_1588                       = 0x88f7
+	ETH_P_8021AD                     = 0x88a8
+	ETH_P_8021AH                     = 0x88e7
+	ETH_P_8021Q                      = 0x8100
+	ETH_P_802_2                      = 0x4
+	ETH_P_802_3                      = 0x1
+	ETH_P_802_3_MIN                  = 0x600
+	ETH_P_802_EX1                    = 0x88b5
+	ETH_P_AARP                       = 0x80f3
+	ETH_P_AF_IUCV                    = 0xfbfb
+	ETH_P_ALL                        = 0x3
+	ETH_P_AOE                        = 0x88a2
+	ETH_P_ARCNET                     = 0x1a
+	ETH_P_ARP                        = 0x806
+	ETH_P_ATALK                      = 0x809b
+	ETH_P_ATMFATE                    = 0x8884
+	ETH_P_ATMMPOA                    = 0x884c
+	ETH_P_AX25                       = 0x2
+	ETH_P_BATMAN                     = 0x4305
+	ETH_P_BPQ                        = 0x8ff
+	ETH_P_CAIF                       = 0xf7
+	ETH_P_CAN                        = 0xc
+	ETH_P_CANFD                      = 0xd
+	ETH_P_CONTROL                    = 0x16
+	ETH_P_CUST                       = 0x6006
+	ETH_P_DDCMP                      = 0x6
+	ETH_P_DEC                        = 0x6000
+	ETH_P_DIAG                       = 0x6005
+	ETH_P_DNA_DL                     = 0x6001
+	ETH_P_DNA_RC                     = 0x6002
+	ETH_P_DNA_RT                     = 0x6003
+	ETH_P_DSA                        = 0x1b
+	ETH_P_ECONET                     = 0x18
+	ETH_P_EDSA                       = 0xdada
+	ETH_P_FCOE                       = 0x8906
+	ETH_P_FIP                        = 0x8914
+	ETH_P_HDLC                       = 0x19
+	ETH_P_IEEE802154                 = 0xf6
+	ETH_P_IEEEPUP                    = 0xa00
+	ETH_P_IEEEPUPAT                  = 0xa01
+	ETH_P_IP                         = 0x800
+	ETH_P_IPV6                       = 0x86dd
+	ETH_P_IPX                        = 0x8137
+	ETH_P_IRDA                       = 0x17
+	ETH_P_LAT                        = 0x6004
+	ETH_P_LINK_CTL                   = 0x886c
+	ETH_P_LOCALTALK                  = 0x9
+	ETH_P_LOOP                       = 0x60
+	ETH_P_MOBITEX                    = 0x15
+	ETH_P_MPLS_MC                    = 0x8848
+	ETH_P_MPLS_UC                    = 0x8847
+	ETH_P_MVRP                       = 0x88f5
+	ETH_P_PAE                        = 0x888e
+	ETH_P_PAUSE                      = 0x8808
+	ETH_P_PHONET                     = 0xf5
+	ETH_P_PPPTALK                    = 0x10
+	ETH_P_PPP_DISC                   = 0x8863
+	ETH_P_PPP_MP                     = 0x8
+	ETH_P_PPP_SES                    = 0x8864
+	ETH_P_PUP                        = 0x200
+	ETH_P_PUPAT                      = 0x201
+	ETH_P_QINQ1                      = 0x9100
+	ETH_P_QINQ2                      = 0x9200
+	ETH_P_QINQ3                      = 0x9300
+	ETH_P_RARP                       = 0x8035
+	ETH_P_SCA                        = 0x6007
+	ETH_P_SLOW                       = 0x8809
+	ETH_P_SNAP                       = 0x5
+	ETH_P_TDLS                       = 0x890d
+	ETH_P_TEB                        = 0x6558
+	ETH_P_TIPC                       = 0x88ca
+	ETH_P_TRAILER                    = 0x1c
+	ETH_P_TR_802_2                   = 0x11
+	ETH_P_WAN_PPP                    = 0x7
+	ETH_P_WCCP                       = 0x883e
+	ETH_P_X25                        = 0x805
+	EXTA                             = 0xe
+	EXTB                             = 0xf
+	EXTPROC                          = 0x10000
+	FD_CLOEXEC                       = 0x1
+	FD_SETSIZE                       = 0x400
+	FLUSHO                           = 0x2000
+	F_DUPFD                          = 0x0
+	F_DUPFD_CLOEXEC                  = 0x406
+	F_EXLCK                          = 0x4
+	F_GETFD                          = 0x1
+	F_GETFL                          = 0x3
+	F_GETLEASE                       = 0x401
+	F_GETLK                          = 0xe
+	F_GETLK64                        = 0xe
+	F_GETOWN                         = 0x17
+	F_GETOWN_EX                      = 0x10
+	F_GETPIPE_SZ                     = 0x408
+	F_GETSIG                         = 0xb
+	F_LOCK                           = 0x1
+	F_NOTIFY                         = 0x402
+	F_OK                             = 0x0
+	F_RDLCK                          = 0x0
+	F_SETFD                          = 0x2
+	F_SETFL                          = 0x4
+	F_SETLEASE                       = 0x400
+	F_SETLK                          = 0x6
+	F_SETLK64                        = 0x6
+	F_SETLKW                         = 0x7
+	F_SETLKW64                       = 0x7
+	F_SETOWN                         = 0x18
+	F_SETOWN_EX                      = 0xf
+	F_SETPIPE_SZ                     = 0x407
+	F_SETSIG                         = 0xa
+	F_SHLCK                          = 0x8
+	F_TEST                           = 0x3
+	F_TLOCK                          = 0x2
+	F_ULOCK                          = 0x0
+	F_UNLCK                          = 0x2
+	F_WRLCK                          = 0x1
+	HUPCL                            = 0x400
+	ICANON                           = 0x2
+	ICMPV6_FILTER                    = 0x1
+	ICRNL                            = 0x100
+	IEXTEN                           = 0x100
+	IFA_F_DADFAILED                  = 0x8
+	IFA_F_DEPRECATED                 = 0x20
+	IFA_F_HOMEADDRESS                = 0x10
+	IFA_F_NODAD                      = 0x2
+	IFA_F_OPTIMISTIC                 = 0x4
+	IFA_F_PERMANENT                  = 0x80
+	IFA_F_SECONDARY                  = 0x1
+	IFA_F_TEMPORARY                  = 0x1
+	IFA_F_TENTATIVE                  = 0x40
+	IFA_MAX                          = 0x7
+	IFF_802_1Q_VLAN                  = 0x1
+	IFF_ALLMULTI                     = 0x200
+	IFF_ATTACH_QUEUE                 = 0x200
+	IFF_AUTOMEDIA                    = 0x4000
+	IFF_BONDING                      = 0x20
+	IFF_BRIDGE_PORT                  = 0x4000
+	IFF_BROADCAST                    = 0x2
+	IFF_DEBUG                        = 0x4
+	IFF_DETACH_QUEUE                 = 0x400
+	IFF_DISABLE_NETPOLL              = 0x1000
+	IFF_DONT_BRIDGE                  = 0x800
+	IFF_DORMANT                      = 0x20000
+	IFF_DYNAMIC                      = 0x8000
+	IFF_EBRIDGE                      = 0x2
+	IFF_ECHO                         = 0x40000
+	IFF_ISATAP                       = 0x80
+	IFF_LIVE_ADDR_CHANGE             = 0x100000
+	IFF_LOOPBACK                     = 0x8
+	IFF_LOWER_UP                     = 0x10000
+	IFF_MACVLAN_PORT                 = 0x2000
+	IFF_MASTER                       = 0x400
+	IFF_MASTER_8023AD                = 0x8
+	IFF_MASTER_ALB                   = 0x10
+	IFF_MASTER_ARPMON                = 0x100
+	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
+	IFF_RUNNING                      = 0x40
+	IFF_SLAVE                        = 0x800
+	IFF_SLAVE_INACTIVE               = 0x4
+	IFF_SLAVE_NEEDARP                = 0x40
+	IFF_SUPP_NOFCS                   = 0x80000
+	IFF_TAP                          = 0x2
+	IFF_TEAM_PORT                    = 0x40000
+	IFF_TUN                          = 0x1
+	IFF_TUN_EXCL                     = 0x8000
+	IFF_TX_SKB_SHARING               = 0x10000
+	IFF_UNICAST_FLT                  = 0x20000
+	IFF_UP                           = 0x1
+	IFF_VNET_HDR                     = 0x4000
+	IFF_VOLATILE                     = 0x70c5a
+	IFF_WAN_HDLC                     = 0x200
+	IFF_XMIT_DST_RELEASE             = 0x400
+	IFNAMSIZ                         = 0x10
+	IGNBRK                           = 0x1
+	IGNCR                            = 0x80
+	IGNPAR                           = 0x4
+	IMAXBEL                          = 0x2000
+	INLCR                            = 0x40
+	INPCK                            = 0x10
+	IN_ACCESS                        = 0x1
+	IN_ALL_EVENTS                    = 0xfff
+	IN_ATTRIB                        = 0x4
+	IN_CLASSA_HOST                   = 0xffffff
+	IN_CLASSA_MAX                    = 0x80
+	IN_CLASSA_NET                    = 0xff000000
+	IN_CLASSA_NSHIFT                 = 0x18
+	IN_CLASSB_HOST                   = 0xffff
+	IN_CLASSB_MAX                    = 0x10000
+	IN_CLASSB_NET                    = 0xffff0000
+	IN_CLASSB_NSHIFT                 = 0x10
+	IN_CLASSC_HOST                   = 0xff
+	IN_CLASSC_NET                    = 0xffffff00
+	IN_CLASSC_NSHIFT                 = 0x8
+	IN_CLOEXEC                       = 0x80000
+	IN_CLOSE                         = 0x18
+	IN_CLOSE_NOWRITE                 = 0x10
+	IN_CLOSE_WRITE                   = 0x8
+	IN_CREATE                        = 0x100
+	IN_DELETE                        = 0x200
+	IN_DELETE_SELF                   = 0x400
+	IN_DONT_FOLLOW                   = 0x2000000
+	IN_EXCL_UNLINK                   = 0x4000000
+	IN_IGNORED                       = 0x8000
+	IN_ISDIR                         = 0x40000000
+	IN_LOOPBACKNET                   = 0x7f
+	IN_MASK_ADD                      = 0x20000000
+	IN_MODIFY                        = 0x2
+	IN_MOVE                          = 0xc0
+	IN_MOVED_FROM                    = 0x40
+	IN_MOVED_TO                      = 0x80
+	IN_MOVE_SELF                     = 0x800
+	IN_NONBLOCK                      = 0x80
+	IN_ONESHOT                       = 0x80000000
+	IN_ONLYDIR                       = 0x1000000
+	IN_OPEN                          = 0x20
+	IN_Q_OVERFLOW                    = 0x4000
+	IN_UNMOUNT                       = 0x2000
+	IPPROTO_AH                       = 0x33
+	IPPROTO_COMP                     = 0x6c
+	IPPROTO_DCCP                     = 0x21
+	IPPROTO_DSTOPTS                  = 0x3c
+	IPPROTO_EGP                      = 0x8
+	IPPROTO_ENCAP                    = 0x62
+	IPPROTO_ESP                      = 0x32
+	IPPROTO_FRAGMENT                 = 0x2c
+	IPPROTO_GRE                      = 0x2f
+	IPPROTO_HOPOPTS                  = 0x0
+	IPPROTO_ICMP                     = 0x1
+	IPPROTO_ICMPV6                   = 0x3a
+	IPPROTO_IDP                      = 0x16
+	IPPROTO_IGMP                     = 0x2
+	IPPROTO_IP                       = 0x0
+	IPPROTO_IPIP                     = 0x4
+	IPPROTO_IPV6                     = 0x29
+	IPPROTO_MTP                      = 0x5c
+	IPPROTO_NONE                     = 0x3b
+	IPPROTO_PIM                      = 0x67
+	IPPROTO_PUP                      = 0xc
+	IPPROTO_RAW                      = 0xff
+	IPPROTO_ROUTING                  = 0x2b
+	IPPROTO_RSVP                     = 0x2e
+	IPPROTO_SCTP                     = 0x84
+	IPPROTO_TCP                      = 0x6
+	IPPROTO_TP                       = 0x1d
+	IPPROTO_UDP                      = 0x11
+	IPPROTO_UDPLITE                  = 0x88
+	IPV6_2292DSTOPTS                 = 0x4
+	IPV6_2292HOPLIMIT                = 0x8
+	IPV6_2292HOPOPTS                 = 0x3
+	IPV6_2292PKTINFO                 = 0x2
+	IPV6_2292PKTOPTIONS              = 0x6
+	IPV6_2292RTHDR                   = 0x5
+	IPV6_ADDRFORM                    = 0x1
+	IPV6_ADD_MEMBERSHIP              = 0x14
+	IPV6_AUTHHDR                     = 0xa
+	IPV6_CHECKSUM                    = 0x7
+	IPV6_DROP_MEMBERSHIP             = 0x15
+	IPV6_DSTOPTS                     = 0x3b
+	IPV6_HOPLIMIT                    = 0x34
+	IPV6_HOPOPTS                     = 0x36
+	IPV6_IPSEC_POLICY                = 0x22
+	IPV6_JOIN_ANYCAST                = 0x1b
+	IPV6_JOIN_GROUP                  = 0x14
+	IPV6_LEAVE_ANYCAST               = 0x1c
+	IPV6_LEAVE_GROUP                 = 0x15
+	IPV6_MTU                         = 0x18
+	IPV6_MTU_DISCOVER                = 0x17
+	IPV6_MULTICAST_HOPS              = 0x12
+	IPV6_MULTICAST_IF                = 0x11
+	IPV6_MULTICAST_LOOP              = 0x13
+	IPV6_NEXTHOP                     = 0x9
+	IPV6_PKTINFO                     = 0x32
+	IPV6_PMTUDISC_DO                 = 0x2
+	IPV6_PMTUDISC_DONT               = 0x0
+	IPV6_PMTUDISC_PROBE              = 0x3
+	IPV6_PMTUDISC_WANT               = 0x1
+	IPV6_RECVDSTOPTS                 = 0x3a
+	IPV6_RECVERR                     = 0x19
+	IPV6_RECVHOPLIMIT                = 0x33
+	IPV6_RECVHOPOPTS                 = 0x35
+	IPV6_RECVPKTINFO                 = 0x31
+	IPV6_RECVRTHDR                   = 0x38
+	IPV6_RECVTCLASS                  = 0x42
+	IPV6_ROUTER_ALERT                = 0x16
+	IPV6_RTHDR                       = 0x39
+	IPV6_RTHDRDSTOPTS                = 0x37
+	IPV6_RTHDR_LOOSE                 = 0x0
+	IPV6_RTHDR_STRICT                = 0x1
+	IPV6_RTHDR_TYPE_0                = 0x0
+	IPV6_RXDSTOPTS                   = 0x3b
+	IPV6_RXHOPOPTS                   = 0x36
+	IPV6_TCLASS                      = 0x43
+	IPV6_UNICAST_HOPS                = 0x10
+	IPV6_V6ONLY                      = 0x1a
+	IPV6_XFRM_POLICY                 = 0x23
+	IP_ADD_MEMBERSHIP                = 0x23
+	IP_ADD_SOURCE_MEMBERSHIP         = 0x27
+	IP_BLOCK_SOURCE                  = 0x26
+	IP_DEFAULT_MULTICAST_LOOP        = 0x1
+	IP_DEFAULT_MULTICAST_TTL         = 0x1
+	IP_DF                            = 0x4000
+	IP_DROP_MEMBERSHIP               = 0x24
+	IP_DROP_SOURCE_MEMBERSHIP        = 0x28
+	IP_FREEBIND                      = 0xf
+	IP_HDRINCL                       = 0x3
+	IP_IPSEC_POLICY                  = 0x10
+	IP_MAXPACKET                     = 0xffff
+	IP_MAX_MEMBERSHIPS               = 0x14
+	IP_MF                            = 0x2000
+	IP_MINTTL                        = 0x15
+	IP_MSFILTER                      = 0x29
+	IP_MSS                           = 0x240
+	IP_MTU                           = 0xe
+	IP_MTU_DISCOVER                  = 0xa
+	IP_MULTICAST_ALL                 = 0x31
+	IP_MULTICAST_IF                  = 0x20
+	IP_MULTICAST_LOOP                = 0x22
+	IP_MULTICAST_TTL                 = 0x21
+	IP_OFFMASK                       = 0x1fff
+	IP_OPTIONS                       = 0x4
+	IP_ORIGDSTADDR                   = 0x14
+	IP_PASSSEC                       = 0x12
+	IP_PKTINFO                       = 0x8
+	IP_PKTOPTIONS                    = 0x9
+	IP_PMTUDISC                      = 0xa
+	IP_PMTUDISC_DO                   = 0x2
+	IP_PMTUDISC_DONT                 = 0x0
+	IP_PMTUDISC_PROBE                = 0x3
+	IP_PMTUDISC_WANT                 = 0x1
+	IP_RECVERR                       = 0xb
+	IP_RECVOPTS                      = 0x6
+	IP_RECVORIGDSTADDR               = 0x14
+	IP_RECVRETOPTS                   = 0x7
+	IP_RECVTOS                       = 0xd
+	IP_RECVTTL                       = 0xc
+	IP_RETOPTS                       = 0x7
+	IP_RF                            = 0x8000
+	IP_ROUTER_ALERT                  = 0x5
+	IP_TOS                           = 0x1
+	IP_TRANSPARENT                   = 0x13
+	IP_TTL                           = 0x2
+	IP_UNBLOCK_SOURCE                = 0x25
+	IP_UNICAST_IF                    = 0x32
+	IP_XFRM_POLICY                   = 0x11
+	ISIG                             = 0x1
+	ISTRIP                           = 0x20
+	IUTF8                            = 0x4000
+	IXANY                            = 0x800
+	IXOFF                            = 0x1000
+	IXON                             = 0x400
+	LINUX_REBOOT_CMD_CAD_OFF         = 0x0
+	LINUX_REBOOT_CMD_CAD_ON          = 0x89abcdef
+	LINUX_REBOOT_CMD_HALT            = 0xcdef0123
+	LINUX_REBOOT_CMD_KEXEC           = 0x45584543
+	LINUX_REBOOT_CMD_POWER_OFF       = 0x4321fedc
+	LINUX_REBOOT_CMD_RESTART         = 0x1234567
+	LINUX_REBOOT_CMD_RESTART2        = 0xa1b2c3d4
+	LINUX_REBOOT_CMD_SW_SUSPEND      = 0xd000fce2
+	LINUX_REBOOT_MAGIC1              = 0xfee1dead
+	LINUX_REBOOT_MAGIC2              = 0x28121969
+	LOCK_EX                          = 0x2
+	LOCK_NB                          = 0x4
+	LOCK_SH                          = 0x1
+	LOCK_UN                          = 0x8
+	MADV_DODUMP                      = 0x11
+	MADV_DOFORK                      = 0xb
+	MADV_DONTDUMP                    = 0x10
+	MADV_DONTFORK                    = 0xa
+	MADV_DONTNEED                    = 0x4
+	MADV_HUGEPAGE                    = 0xe
+	MADV_HWPOISON                    = 0x64
+	MADV_MERGEABLE                   = 0xc
+	MADV_NOHUGEPAGE                  = 0xf
+	MADV_NORMAL                      = 0x0
+	MADV_RANDOM                      = 0x1
+	MADV_REMOVE                      = 0x9
+	MADV_SEQUENTIAL                  = 0x2
+	MADV_UNMERGEABLE                 = 0xd
+	MADV_WILLNEED                    = 0x3
+	MAP_ANON                         = 0x800
+	MAP_ANONYMOUS                    = 0x800
+	MAP_DENYWRITE                    = 0x2000
+	MAP_EXECUTABLE                   = 0x4000
+	MAP_FILE                         = 0x0
+	MAP_FIXED                        = 0x10
+	MAP_GROWSDOWN                    = 0x1000
+	MAP_HUGETLB                      = 0x80000
+	MAP_LOCKED                       = 0x8000
+	MAP_NONBLOCK                     = 0x20000
+	MAP_NORESERVE                    = 0x400
+	MAP_POPULATE                     = 0x10000
+	MAP_PRIVATE                      = 0x2
+	MAP_RENAME                       = 0x800
+	MAP_SHARED                       = 0x1
+	MAP_STACK                        = 0x40000
+	MAP_TYPE                         = 0xf
+	MCL_CURRENT                      = 0x1
+	MCL_FUTURE                       = 0x2
+	MNT_DETACH                       = 0x2
+	MNT_EXPIRE                       = 0x4
+	MNT_FORCE                        = 0x1
+	MSG_CMSG_CLOEXEC                 = 0x40000000
+	MSG_CONFIRM                      = 0x800
+	MSG_CTRUNC                       = 0x8
+	MSG_DONTROUTE                    = 0x4
+	MSG_DONTWAIT                     = 0x40
+	MSG_EOR                          = 0x80
+	MSG_ERRQUEUE                     = 0x2000
+	MSG_FASTOPEN                     = 0x20000000
+	MSG_FIN                          = 0x200
+	MSG_MORE                         = 0x8000
+	MSG_NOSIGNAL                     = 0x4000
+	MSG_OOB                          = 0x1
+	MSG_PEEK                         = 0x2
+	MSG_PROXY                        = 0x10
+	MSG_RST                          = 0x1000
+	MSG_SYN                          = 0x400
+	MSG_TRUNC                        = 0x20
+	MSG_TRYHARD                      = 0x4
+	MSG_WAITALL                      = 0x100
+	MSG_WAITFORONE                   = 0x10000
+	MS_ACTIVE                        = 0x40000000
+	MS_ASYNC                         = 0x1
+	MS_BIND                          = 0x1000
+	MS_DIRSYNC                       = 0x80
+	MS_INVALIDATE                    = 0x2
+	MS_I_VERSION                     = 0x800000
+	MS_KERNMOUNT                     = 0x400000
+	MS_MANDLOCK                      = 0x40
+	MS_MGC_MSK                       = 0xffff0000
+	MS_MGC_VAL                       = 0xc0ed0000
+	MS_MOVE                          = 0x2000
+	MS_NOATIME                       = 0x400
+	MS_NODEV                         = 0x4
+	MS_NODIRATIME                    = 0x800
+	MS_NOEXEC                        = 0x8
+	MS_NOSUID                        = 0x2
+	MS_NOUSER                        = -0x80000000
+	MS_POSIXACL                      = 0x10000
+	MS_PRIVATE                       = 0x40000
+	MS_RDONLY                        = 0x1
+	MS_REC                           = 0x4000
+	MS_RELATIME                      = 0x200000
+	MS_REMOUNT                       = 0x20
+	MS_RMT_MASK                      = 0x800051
+	MS_SHARED                        = 0x100000
+	MS_SILENT                        = 0x8000
+	MS_SLAVE                         = 0x80000
+	MS_STRICTATIME                   = 0x1000000
+	MS_SYNC                          = 0x4
+	MS_SYNCHRONOUS                   = 0x10
+	MS_UNBINDABLE                    = 0x20000
+	NAME_MAX                         = 0xff
+	NETLINK_ADD_MEMBERSHIP           = 0x1
+	NETLINK_AUDIT                    = 0x9
+	NETLINK_BROADCAST_ERROR          = 0x4
+	NETLINK_CONNECTOR                = 0xb
+	NETLINK_CRYPTO                   = 0x15
+	NETLINK_DNRTMSG                  = 0xe
+	NETLINK_DROP_MEMBERSHIP          = 0x2
+	NETLINK_ECRYPTFS                 = 0x13
+	NETLINK_FIB_LOOKUP               = 0xa
+	NETLINK_FIREWALL                 = 0x3
+	NETLINK_GENERIC                  = 0x10
+	NETLINK_INET_DIAG                = 0x4
+	NETLINK_IP6_FW                   = 0xd
+	NETLINK_ISCSI                    = 0x8
+	NETLINK_KOBJECT_UEVENT           = 0xf
+	NETLINK_NETFILTER                = 0xc
+	NETLINK_NFLOG                    = 0x5
+	NETLINK_NO_ENOBUFS               = 0x5
+	NETLINK_PKTINFO                  = 0x3
+	NETLINK_RDMA                     = 0x14
+	NETLINK_ROUTE                    = 0x0
+	NETLINK_RX_RING                  = 0x6
+	NETLINK_SCSITRANSPORT            = 0x12
+	NETLINK_SELINUX                  = 0x7
+	NETLINK_SOCK_DIAG                = 0x4
+	NETLINK_TX_RING                  = 0x7
+	NETLINK_UNUSED                   = 0x1
+	NETLINK_USERSOCK                 = 0x2
+	NETLINK_XFRM                     = 0x6
+	NLA_ALIGNTO                      = 0x4
+	NLA_F_NESTED                     = 0x8000
+	NLA_F_NET_BYTEORDER              = 0x4000
+	NLA_HDRLEN                       = 0x4
+	NLMSG_ALIGNTO                    = 0x4
+	NLMSG_DONE                       = 0x3
+	NLMSG_ERROR                      = 0x2
+	NLMSG_HDRLEN                     = 0x10
+	NLMSG_MIN_TYPE                   = 0x10
+	NLMSG_NOOP                       = 0x1
+	NLMSG_OVERRUN                    = 0x4
+	NLM_F_ACK                        = 0x4
+	NLM_F_APPEND                     = 0x800
+	NLM_F_ATOMIC                     = 0x400
+	NLM_F_CREATE                     = 0x400
+	NLM_F_DUMP                       = 0x300
+	NLM_F_DUMP_INTR                  = 0x10
+	NLM_F_ECHO                       = 0x8
+	NLM_F_EXCL                       = 0x200
+	NLM_F_MATCH                      = 0x200
+	NLM_F_MULTI                      = 0x2
+	NLM_F_REPLACE                    = 0x100
+	NLM_F_REQUEST                    = 0x1
+	NLM_F_ROOT                       = 0x100
+	NOFLSH                           = 0x80
+	OCRNL                            = 0x8
+	OFDEL                            = 0x80
+	OFILL                            = 0x40
+	ONLCR                            = 0x4
+	ONLRET                           = 0x20
+	ONOCR                            = 0x10
+	OPOST                            = 0x1
+	O_ACCMODE                        = 0x3
+	O_APPEND                         = 0x8
+	O_ASYNC                          = 0x1000
+	O_CLOEXEC                        = 0x80000
+	O_CREAT                          = 0x100
+	O_DIRECT                         = 0x8000
+	O_DIRECTORY                      = 0x10000
+	O_DSYNC                          = 0x10
+	O_EXCL                           = 0x400
+	O_FSYNC                          = 0x4010
+	O_LARGEFILE                      = 0x0
+	O_NDELAY                         = 0x80
+	O_NOATIME                        = 0x40000
+	O_NOCTTY                         = 0x800
+	O_NOFOLLOW                       = 0x20000
+	O_NONBLOCK                       = 0x80
+	O_PATH                           = 0x200000
+	O_RDONLY                         = 0x0
+	O_RDWR                           = 0x2
+	O_RSYNC                          = 0x4010
+	O_SYNC                           = 0x4010
+	O_TRUNC                          = 0x200
+	O_WRONLY                         = 0x1
+	PACKET_ADD_MEMBERSHIP            = 0x1
+	PACKET_AUXDATA                   = 0x8
+	PACKET_BROADCAST                 = 0x1
+	PACKET_COPY_THRESH               = 0x7
+	PACKET_DROP_MEMBERSHIP           = 0x2
+	PACKET_FANOUT                    = 0x12
+	PACKET_FANOUT_CPU                = 0x2
+	PACKET_FANOUT_FLAG_DEFRAG        = 0x8000
+	PACKET_FANOUT_FLAG_ROLLOVER      = 0x1000
+	PACKET_FANOUT_HASH               = 0x0
+	PACKET_FANOUT_LB                 = 0x1
+	PACKET_FANOUT_RND                = 0x4
+	PACKET_FANOUT_ROLLOVER           = 0x3
+	PACKET_FASTROUTE                 = 0x6
+	PACKET_HDRLEN                    = 0xb
+	PACKET_HOST                      = 0x0
+	PACKET_LOOPBACK                  = 0x5
+	PACKET_LOSS                      = 0xe
+	PACKET_MR_ALLMULTI               = 0x2
+	PACKET_MR_MULTICAST              = 0x0
+	PACKET_MR_PROMISC                = 0x1
+	PACKET_MR_UNICAST                = 0x3
+	PACKET_MULTICAST                 = 0x2
+	PACKET_ORIGDEV                   = 0x9
+	PACKET_OTHERHOST                 = 0x3
+	PACKET_OUTGOING                  = 0x4
+	PACKET_RECV_OUTPUT               = 0x3
+	PACKET_RESERVE                   = 0xc
+	PACKET_RX_RING                   = 0x5
+	PACKET_STATISTICS                = 0x6
+	PACKET_TIMESTAMP                 = 0x11
+	PACKET_TX_HAS_OFF                = 0x13
+	PACKET_TX_RING                   = 0xd
+	PACKET_TX_TIMESTAMP              = 0x10
+	PACKET_VERSION                   = 0xa
+	PACKET_VNET_HDR                  = 0xf
+	PARENB                           = 0x100
+	PARITY_CRC16_PR0                 = 0x2
+	PARITY_CRC16_PR0_CCITT           = 0x4
+	PARITY_CRC16_PR1                 = 0x3
+	PARITY_CRC16_PR1_CCITT           = 0x5
+	PARITY_CRC32_PR0_CCITT           = 0x6
+	PARITY_CRC32_PR1_CCITT           = 0x7
+	PARITY_DEFAULT                   = 0x0
+	PARITY_NONE                      = 0x1
+	PARMRK                           = 0x8
+	PARODD                           = 0x200
+	PENDIN                           = 0x4000
+	PRIO_PGRP                        = 0x1
+	PRIO_PROCESS                     = 0x0
+	PRIO_USER                        = 0x2
+	PROT_EXEC                        = 0x4
+	PROT_GROWSDOWN                   = 0x1000000
+	PROT_GROWSUP                     = 0x2000000
+	PROT_NONE                        = 0x0
+	PROT_READ                        = 0x1
+	PROT_WRITE                       = 0x2
+	PR_CAPBSET_DROP                  = 0x18
+	PR_CAPBSET_READ                  = 0x17
+	PR_ENDIAN_BIG                    = 0x0
+	PR_ENDIAN_LITTLE                 = 0x1
+	PR_ENDIAN_PPC_LITTLE             = 0x2
+	PR_FPEMU_NOPRINT                 = 0x1
+	PR_FPEMU_SIGFPE                  = 0x2
+	PR_FP_EXC_ASYNC                  = 0x2
+	PR_FP_EXC_DISABLED               = 0x0
+	PR_FP_EXC_DIV                    = 0x10000
+	PR_FP_EXC_INV                    = 0x100000
+	PR_FP_EXC_NONRECOV               = 0x1
+	PR_FP_EXC_OVF                    = 0x20000
+	PR_FP_EXC_PRECISE                = 0x3
+	PR_FP_EXC_RES                    = 0x80000
+	PR_FP_EXC_SW_ENABLE              = 0x80
+	PR_FP_EXC_UND                    = 0x40000
+	PR_GET_CHILD_SUBREAPER           = 0x25
+	PR_GET_DUMPABLE                  = 0x3
+	PR_GET_ENDIAN                    = 0x13
+	PR_GET_FPEMU                     = 0x9
+	PR_GET_FPEXC                     = 0xb
+	PR_GET_KEEPCAPS                  = 0x7
+	PR_GET_NAME                      = 0x10
+	PR_GET_NO_NEW_PRIVS              = 0x27
+	PR_GET_PDEATHSIG                 = 0x2
+	PR_GET_SECCOMP                   = 0x15
+	PR_GET_SECUREBITS                = 0x1b
+	PR_GET_TID_ADDRESS               = 0x28
+	PR_GET_TIMERSLACK                = 0x1e
+	PR_GET_TIMING                    = 0xd
+	PR_GET_TSC                       = 0x19
+	PR_GET_UNALIGN                   = 0x5
+	PR_MCE_KILL                      = 0x21
+	PR_MCE_KILL_CLEAR                = 0x0
+	PR_MCE_KILL_DEFAULT              = 0x2
+	PR_MCE_KILL_EARLY                = 0x1
+	PR_MCE_KILL_GET                  = 0x22
+	PR_MCE_KILL_LATE                 = 0x0
+	PR_MCE_KILL_SET                  = 0x1
+	PR_SET_CHILD_SUBREAPER           = 0x24
+	PR_SET_DUMPABLE                  = 0x4
+	PR_SET_ENDIAN                    = 0x14
+	PR_SET_FPEMU                     = 0xa
+	PR_SET_FPEXC                     = 0xc
+	PR_SET_KEEPCAPS                  = 0x8
+	PR_SET_MM                        = 0x23
+	PR_SET_MM_ARG_END                = 0x9
+	PR_SET_MM_ARG_START              = 0x8
+	PR_SET_MM_AUXV                   = 0xc
+	PR_SET_MM_BRK                    = 0x7
+	PR_SET_MM_END_CODE               = 0x2
+	PR_SET_MM_END_DATA               = 0x4
+	PR_SET_MM_ENV_END                = 0xb
+	PR_SET_MM_ENV_START              = 0xa
+	PR_SET_MM_EXE_FILE               = 0xd
+	PR_SET_MM_START_BRK              = 0x6
+	PR_SET_MM_START_CODE             = 0x1
+	PR_SET_MM_START_DATA             = 0x3
+	PR_SET_MM_START_STACK            = 0x5
+	PR_SET_NAME                      = 0xf
+	PR_SET_NO_NEW_PRIVS              = 0x26
+	PR_SET_PDEATHSIG                 = 0x1
+	PR_SET_PTRACER                   = 0x59616d61
+	PR_SET_PTRACER_ANY               = -0x1
+	PR_SET_SECCOMP                   = 0x16
+	PR_SET_SECUREBITS                = 0x1c
+	PR_SET_TIMERSLACK                = 0x1d
+	PR_SET_TIMING                    = 0xe
+	PR_SET_TSC                       = 0x1a
+	PR_SET_UNALIGN                   = 0x6
+	PR_TASK_PERF_EVENTS_DISABLE      = 0x1f
+	PR_TASK_PERF_EVENTS_ENABLE       = 0x20
+	PR_TIMING_STATISTICAL            = 0x0
+	PR_TIMING_TIMESTAMP              = 0x1
+	PR_TSC_ENABLE                    = 0x1
+	PR_TSC_SIGSEGV                   = 0x2
+	PR_UNALIGN_NOPRINT               = 0x1
+	PR_UNALIGN_SIGBUS                = 0x2
+	PTRACE_ATTACH                    = 0x10
+	PTRACE_CONT                      = 0x7
+	PTRACE_DETACH                    = 0x11
+	PTRACE_EVENT_CLONE               = 0x3
+	PTRACE_EVENT_EXEC                = 0x4
+	PTRACE_EVENT_EXIT                = 0x6
+	PTRACE_EVENT_FORK                = 0x1
+	PTRACE_EVENT_SECCOMP             = 0x7
+	PTRACE_EVENT_STOP                = 0x80
+	PTRACE_EVENT_VFORK               = 0x2
+	PTRACE_EVENT_VFORK_DONE          = 0x5
+	PTRACE_GETEVENTMSG               = 0x4201
+	PTRACE_GETFPREGS                 = 0xe
+	PTRACE_GETREGS                   = 0xc
+	PTRACE_GETREGSET                 = 0x4204
+	PTRACE_GETSIGINFO                = 0x4202
+	PTRACE_GETSIGMASK                = 0x420a
+	PTRACE_GET_THREAD_AREA           = 0x19
+	PTRACE_GET_THREAD_AREA_3264      = 0xc4
+	PTRACE_GET_WATCH_REGS            = 0xd0
+	PTRACE_INTERRUPT                 = 0x4207
+	PTRACE_KILL                      = 0x8
+	PTRACE_LISTEN                    = 0x4208
+	PTRACE_OLDSETOPTIONS             = 0x15
+	PTRACE_O_EXITKILL                = 0x100000
+	PTRACE_O_MASK                    = 0x1000ff
+	PTRACE_O_TRACECLONE              = 0x8
+	PTRACE_O_TRACEEXEC               = 0x10
+	PTRACE_O_TRACEEXIT               = 0x40
+	PTRACE_O_TRACEFORK               = 0x2
+	PTRACE_O_TRACESECCOMP            = 0x80
+	PTRACE_O_TRACESYSGOOD            = 0x1
+	PTRACE_O_TRACEVFORK              = 0x4
+	PTRACE_O_TRACEVFORKDONE          = 0x20
+	PTRACE_PEEKDATA                  = 0x2
+	PTRACE_PEEKDATA_3264             = 0xc1
+	PTRACE_PEEKSIGINFO               = 0x4209
+	PTRACE_PEEKSIGINFO_SHARED        = 0x1
+	PTRACE_PEEKTEXT                  = 0x1
+	PTRACE_PEEKTEXT_3264             = 0xc0
+	PTRACE_PEEKUSR                   = 0x3
+	PTRACE_POKEDATA                  = 0x5
+	PTRACE_POKEDATA_3264             = 0xc3
+	PTRACE_POKETEXT                  = 0x4
+	PTRACE_POKETEXT_3264             = 0xc2
+	PTRACE_POKEUSR                   = 0x6
+	PTRACE_SEIZE                     = 0x4206
+	PTRACE_SETFPREGS                 = 0xf
+	PTRACE_SETOPTIONS                = 0x4200
+	PTRACE_SETREGS                   = 0xd
+	PTRACE_SETREGSET                 = 0x4205
+	PTRACE_SETSIGINFO                = 0x4203
+	PTRACE_SETSIGMASK                = 0x420b
+	PTRACE_SET_THREAD_AREA           = 0x1a
+	PTRACE_SET_WATCH_REGS            = 0xd1
+	PTRACE_SINGLESTEP                = 0x9
+	PTRACE_SYSCALL                   = 0x18
+	PTRACE_TRACEME                   = 0x0
+	RLIMIT_AS                        = 0x6
+	RLIMIT_CORE                      = 0x4
+	RLIMIT_CPU                       = 0x0
+	RLIMIT_DATA                      = 0x2
+	RLIMIT_FSIZE                     = 0x1
+	RLIMIT_NOFILE                    = 0x5
+	RLIMIT_STACK                     = 0x3
+	RLIM_INFINITY                    = -0x1
+	RTAX_ADVMSS                      = 0x8
+	RTAX_CWND                        = 0x7
+	RTAX_FEATURES                    = 0xc
+	RTAX_FEATURE_ALLFRAG             = 0x8
+	RTAX_FEATURE_ECN                 = 0x1
+	RTAX_FEATURE_SACK                = 0x2
+	RTAX_FEATURE_TIMESTAMP           = 0x4
+	RTAX_HOPLIMIT                    = 0xa
+	RTAX_INITCWND                    = 0xb
+	RTAX_INITRWND                    = 0xe
+	RTAX_LOCK                        = 0x1
+	RTAX_MAX                         = 0xf
+	RTAX_MTU                         = 0x2
+	RTAX_QUICKACK                    = 0xf
+	RTAX_REORDERING                  = 0x9
+	RTAX_RTO_MIN                     = 0xd
+	RTAX_RTT                         = 0x4
+	RTAX_RTTVAR                      = 0x5
+	RTAX_SSTHRESH                    = 0x6
+	RTAX_UNSPEC                      = 0x0
+	RTAX_WINDOW                      = 0x3
+	RTA_ALIGNTO                      = 0x4
+	RTA_MAX                          = 0x11
+	RTCF_DIRECTSRC                   = 0x4000000
+	RTCF_DOREDIRECT                  = 0x1000000
+	RTCF_LOG                         = 0x2000000
+	RTCF_MASQ                        = 0x400000
+	RTCF_NAT                         = 0x800000
+	RTCF_VALVE                       = 0x200000
+	RTF_ADDRCLASSMASK                = 0xf8000000
+	RTF_ADDRCONF                     = 0x40000
+	RTF_ALLONLINK                    = 0x20000
+	RTF_BROADCAST                    = 0x10000000
+	RTF_CACHE                        = 0x1000000
+	RTF_DEFAULT                      = 0x10000
+	RTF_DYNAMIC                      = 0x10
+	RTF_FLOW                         = 0x2000000
+	RTF_GATEWAY                      = 0x2
+	RTF_HOST                         = 0x4
+	RTF_INTERFACE                    = 0x40000000
+	RTF_IRTT                         = 0x100
+	RTF_LINKRT                       = 0x100000
+	RTF_LOCAL                        = 0x80000000
+	RTF_MODIFIED                     = 0x20
+	RTF_MSS                          = 0x40
+	RTF_MTU                          = 0x40
+	RTF_MULTICAST                    = 0x20000000
+	RTF_NAT                          = 0x8000000
+	RTF_NOFORWARD                    = 0x1000
+	RTF_NONEXTHOP                    = 0x200000
+	RTF_NOPMTUDISC                   = 0x4000
+	RTF_POLICY                       = 0x4000000
+	RTF_REINSTATE                    = 0x8
+	RTF_REJECT                       = 0x200
+	RTF_STATIC                       = 0x400
+	RTF_THROW                        = 0x2000
+	RTF_UP                           = 0x1
+	RTF_WINDOW                       = 0x80
+	RTF_XRESOLVE                     = 0x800
+	RTM_BASE                         = 0x10
+	RTM_DELACTION                    = 0x31
+	RTM_DELADDR                      = 0x15
+	RTM_DELADDRLABEL                 = 0x49
+	RTM_DELLINK                      = 0x11
+	RTM_DELMDB                       = 0x55
+	RTM_DELNEIGH                     = 0x1d
+	RTM_DELQDISC                     = 0x25
+	RTM_DELROUTE                     = 0x19
+	RTM_DELRULE                      = 0x21
+	RTM_DELTCLASS                    = 0x29
+	RTM_DELTFILTER                   = 0x2d
+	RTM_F_CLONED                     = 0x200
+	RTM_F_EQUALIZE                   = 0x400
+	RTM_F_NOTIFY                     = 0x100
+	RTM_F_PREFIX                     = 0x800
+	RTM_GETACTION                    = 0x32
+	RTM_GETADDR                      = 0x16
+	RTM_GETADDRLABEL                 = 0x4a
+	RTM_GETANYCAST                   = 0x3e
+	RTM_GETDCB                       = 0x4e
+	RTM_GETLINK                      = 0x12
+	RTM_GETMDB                       = 0x56
+	RTM_GETMULTICAST                 = 0x3a
+	RTM_GETNEIGH                     = 0x1e
+	RTM_GETNEIGHTBL                  = 0x42
+	RTM_GETNETCONF                   = 0x52
+	RTM_GETQDISC                     = 0x26
+	RTM_GETROUTE                     = 0x1a
+	RTM_GETRULE                      = 0x22
+	RTM_GETTCLASS                    = 0x2a
+	RTM_GETTFILTER                   = 0x2e
+	RTM_MAX                          = 0x57
+	RTM_NEWACTION                    = 0x30
+	RTM_NEWADDR                      = 0x14
+	RTM_NEWADDRLABEL                 = 0x48
+	RTM_NEWLINK                      = 0x10
+	RTM_NEWMDB                       = 0x54
+	RTM_NEWNDUSEROPT                 = 0x44
+	RTM_NEWNEIGH                     = 0x1c
+	RTM_NEWNEIGHTBL                  = 0x40
+	RTM_NEWNETCONF                   = 0x50
+	RTM_NEWPREFIX                    = 0x34
+	RTM_NEWQDISC                     = 0x24
+	RTM_NEWROUTE                     = 0x18
+	RTM_NEWRULE                      = 0x20
+	RTM_NEWTCLASS                    = 0x28
+	RTM_NEWTFILTER                   = 0x2c
+	RTM_NR_FAMILIES                  = 0x12
+	RTM_NR_MSGTYPES                  = 0x48
+	RTM_SETDCB                       = 0x4f
+	RTM_SETLINK                      = 0x13
+	RTM_SETNEIGHTBL                  = 0x43
+	RTNH_ALIGNTO                     = 0x4
+	RTNH_F_DEAD                      = 0x1
+	RTNH_F_ONLINK                    = 0x4
+	RTNH_F_PERVASIVE                 = 0x2
+	RTN_MAX                          = 0xb
+	RTPROT_BIRD                      = 0xc
+	RTPROT_BOOT                      = 0x3
+	RTPROT_DHCP                      = 0x10
+	RTPROT_DNROUTED                  = 0xd
+	RTPROT_GATED                     = 0x8
+	RTPROT_KERNEL                    = 0x2
+	RTPROT_MROUTED                   = 0x11
+	RTPROT_MRT                       = 0xa
+	RTPROT_NTK                       = 0xf
+	RTPROT_RA                        = 0x9
+	RTPROT_REDIRECT                  = 0x1
+	RTPROT_STATIC                    = 0x4
+	RTPROT_UNSPEC                    = 0x0
+	RTPROT_XORP                      = 0xe
+	RTPROT_ZEBRA                     = 0xb
+	RT_CLASS_DEFAULT                 = 0xfd
+	RT_CLASS_LOCAL                   = 0xff
+	RT_CLASS_MAIN                    = 0xfe
+	RT_CLASS_MAX                     = 0xff
+	RT_CLASS_UNSPEC                  = 0x0
+	RUSAGE_CHILDREN                  = -0x1
+	RUSAGE_SELF                      = 0x0
+	RUSAGE_THREAD                    = 0x1
+	SCM_CREDENTIALS                  = 0x2
+	SCM_RIGHTS                       = 0x1
+	SCM_TIMESTAMP                    = 0x1d
+	SCM_TIMESTAMPING                 = 0x25
+	SCM_TIMESTAMPNS                  = 0x23
+	SCM_WIFI_STATUS                  = 0x29
+	SHUT_RD                          = 0x0
+	SHUT_RDWR                        = 0x2
+	SHUT_WR                          = 0x1
+	SIOCADDDLCI                      = 0x8980
+	SIOCADDMULTI                     = 0x8931
+	SIOCADDRT                        = 0x890b
+	SIOCATMARK                       = 0x40047307
+	SIOCDARP                         = 0x8953
+	SIOCDELDLCI                      = 0x8981
+	SIOCDELMULTI                     = 0x8932
+	SIOCDELRT                        = 0x890c
+	SIOCDEVPRIVATE                   = 0x89f0
+	SIOCDIFADDR                      = 0x8936
+	SIOCDRARP                        = 0x8960
+	SIOCGARP                         = 0x8954
+	SIOCGIFADDR                      = 0x8915
+	SIOCGIFBR                        = 0x8940
+	SIOCGIFBRDADDR                   = 0x8919
+	SIOCGIFCONF                      = 0x8912
+	SIOCGIFCOUNT                     = 0x8938
+	SIOCGIFDSTADDR                   = 0x8917
+	SIOCGIFENCAP                     = 0x8925
+	SIOCGIFFLAGS                     = 0x8913
+	SIOCGIFHWADDR                    = 0x8927
+	SIOCGIFINDEX                     = 0x8933
+	SIOCGIFMAP                       = 0x8970
+	SIOCGIFMEM                       = 0x891f
+	SIOCGIFMETRIC                    = 0x891d
+	SIOCGIFMTU                       = 0x8921
+	SIOCGIFNAME                      = 0x8910
+	SIOCGIFNETMASK                   = 0x891b
+	SIOCGIFPFLAGS                    = 0x8935
+	SIOCGIFSLAVE                     = 0x8929
+	SIOCGIFTXQLEN                    = 0x8942
+	SIOCGPGRP                        = 0x40047309
+	SIOCGRARP                        = 0x8961
+	SIOCGSTAMP                       = 0x8906
+	SIOCGSTAMPNS                     = 0x8907
+	SIOCPROTOPRIVATE                 = 0x89e0
+	SIOCRTMSG                        = 0x890d
+	SIOCSARP                         = 0x8955
+	SIOCSIFADDR                      = 0x8916
+	SIOCSIFBR                        = 0x8941
+	SIOCSIFBRDADDR                   = 0x891a
+	SIOCSIFDSTADDR                   = 0x8918
+	SIOCSIFENCAP                     = 0x8926
+	SIOCSIFFLAGS                     = 0x8914
+	SIOCSIFHWADDR                    = 0x8924
+	SIOCSIFHWBROADCAST               = 0x8937
+	SIOCSIFLINK                      = 0x8911
+	SIOCSIFMAP                       = 0x8971
+	SIOCSIFMEM                       = 0x8920
+	SIOCSIFMETRIC                    = 0x891e
+	SIOCSIFMTU                       = 0x8922
+	SIOCSIFNAME                      = 0x8923
+	SIOCSIFNETMASK                   = 0x891c
+	SIOCSIFPFLAGS                    = 0x8934
+	SIOCSIFSLAVE                     = 0x8930
+	SIOCSIFTXQLEN                    = 0x8943
+	SIOCSPGRP                        = 0x80047308
+	SIOCSRARP                        = 0x8962
+	SOCK_CLOEXEC                     = 0x80000
+	SOCK_DCCP                        = 0x6
+	SOCK_DGRAM                       = 0x1
+	SOCK_NONBLOCK                    = 0x80
+	SOCK_PACKET                      = 0xa
+	SOCK_RAW                         = 0x3
+	SOCK_RDM                         = 0x4
+	SOCK_SEQPACKET                   = 0x5
+	SOCK_STREAM                      = 0x2
+	SOL_AAL                          = 0x109
+	SOL_ATM                          = 0x108
+	SOL_DECNET                       = 0x105
+	SOL_ICMPV6                       = 0x3a
+	SOL_IP                           = 0x0
+	SOL_IPV6                         = 0x29
+	SOL_IRDA                         = 0x10a
+	SOL_PACKET                       = 0x107
+	SOL_RAW                          = 0xff
+	SOL_SOCKET                       = 0xffff
+	SOL_TCP                          = 0x6
+	SOL_X25                          = 0x106
+	SOMAXCONN                        = 0x80
+	SO_ACCEPTCONN                    = 0x1009
+	SO_ATTACH_FILTER                 = 0x1a
+	SO_BINDTODEVICE                  = 0x19
+	SO_BROADCAST                     = 0x20
+	SO_BSDCOMPAT                     = 0xe
+	SO_BUSY_POLL                     = 0x2e
+	SO_DEBUG                         = 0x1
+	SO_DETACH_FILTER                 = 0x1b
+	SO_DOMAIN                        = 0x1029
+	SO_DONTROUTE                     = 0x10
+	SO_ERROR                         = 0x1007
+	SO_GET_FILTER                    = 0x1a
+	SO_KEEPALIVE                     = 0x8
+	SO_LINGER                        = 0x80
+	SO_LOCK_FILTER                   = 0x2c
+	SO_MARK                          = 0x24
+	SO_NOFCS                         = 0x2b
+	SO_NO_CHECK                      = 0xb
+	SO_OOBINLINE                     = 0x100
+	SO_PASSCRED                      = 0x11
+	SO_PASSSEC                       = 0x22
+	SO_PEEK_OFF                      = 0x2a
+	SO_PEERCRED                      = 0x12
+	SO_PEERNAME                      = 0x1c
+	SO_PEERSEC                       = 0x1e
+	SO_PRIORITY                      = 0xc
+	SO_PROTOCOL                      = 0x1028
+	SO_RCVBUF                        = 0x1002
+	SO_RCVBUFFORCE                   = 0x21
+	SO_RCVLOWAT                      = 0x1004
+	SO_RCVTIMEO                      = 0x1006
+	SO_REUSEADDR                     = 0x4
+	SO_REUSEPORT                     = 0x200
+	SO_RXQ_OVFL                      = 0x28
+	SO_SECURITY_AUTHENTICATION       = 0x16
+	SO_SECURITY_ENCRYPTION_NETWORK   = 0x18
+	SO_SECURITY_ENCRYPTION_TRANSPORT = 0x17
+	SO_SELECT_ERR_QUEUE              = 0x2d
+	SO_SNDBUF                        = 0x1001
+	SO_SNDBUFFORCE                   = 0x1f
+	SO_SNDLOWAT                      = 0x1003
+	SO_SNDTIMEO                      = 0x1005
+	SO_STYLE                         = 0x1008
+	SO_TIMESTAMP                     = 0x1d
+	SO_TIMESTAMPING                  = 0x25
+	SO_TIMESTAMPNS                   = 0x23
+	SO_TYPE                          = 0x1008
+	SO_WIFI_STATUS                   = 0x29
+	S_BLKSIZE                        = 0x200
+	S_IEXEC                          = 0x40
+	S_IFBLK                          = 0x6000
+	S_IFCHR                          = 0x2000
+	S_IFDIR                          = 0x4000
+	S_IFIFO                          = 0x1000
+	S_IFLNK                          = 0xa000
+	S_IFMT                           = 0xf000
+	S_IFREG                          = 0x8000
+	S_IFSOCK                         = 0xc000
+	S_IREAD                          = 0x100
+	S_IRGRP                          = 0x20
+	S_IROTH                          = 0x4
+	S_IRUSR                          = 0x100
+	S_IRWXG                          = 0x38
+	S_IRWXO                          = 0x7
+	S_IRWXU                          = 0x1c0
+	S_ISGID                          = 0x400
+	S_ISUID                          = 0x800
+	S_ISVTX                          = 0x200
+	S_IWGRP                          = 0x10
+	S_IWOTH                          = 0x2
+	S_IWRITE                         = 0x80
+	S_IWUSR                          = 0x80
+	S_IXGRP                          = 0x8
+	S_IXOTH                          = 0x1
+	S_IXUSR                          = 0x40
+	TCFLSH                           = 0x5407
+	TCIFLUSH                         = 0x0
+	TCIOFLUSH                        = 0x2
+	TCOFLUSH                         = 0x1
+	TCP_CONGESTION                   = 0xd
+	TCP_CORK                         = 0x3
+	TCP_DEFER_ACCEPT                 = 0x9
+	TCP_INFO                         = 0xb
+	TCP_KEEPCNT                      = 0x6
+	TCP_KEEPIDLE                     = 0x4
+	TCP_KEEPINTVL                    = 0x5
+	TCP_LINGER2                      = 0x8
+	TCP_MAXSEG                       = 0x2
+	TCP_MAXWIN                       = 0xffff
+	TCP_MAX_WINSHIFT                 = 0xe
+	TCP_MD5SIG                       = 0xe
+	TCP_MD5SIG_MAXKEYLEN             = 0x50
+	TCP_MSS                          = 0x200
+	TCP_NODELAY                      = 0x1
+	TCP_QUICKACK                     = 0xc
+	TCP_SYNCNT                       = 0x7
+	TCP_WINDOW_CLAMP                 = 0xa
+	TCSAFLUSH                        = 0x5410
+	TIOCCBRK                         = 0x5428
+	TIOCCONS                         = 0x80047478
+	TIOCEXCL                         = 0x740d
+	TIOCGDEV                         = 0x40045432
+	TIOCGETD                         = 0x7400
+	TIOCGETP                         = 0x7408
+	TIOCGEXCL                        = 0x40045440
+	TIOCGICOUNT                      = 0x5492
+	TIOCGLCKTRMIOS                   = 0x548b
+	TIOCGLTC                         = 0x7474
+	TIOCGPGRP                        = 0x40047477
+	TIOCGPKT                         = 0x40045438
+	TIOCGPTLCK                       = 0x40045439
+	TIOCGPTN                         = 0x40045430
+	TIOCGSERIAL                      = 0x5484
+	TIOCGSID                         = 0x7416
+	TIOCGSOFTCAR                     = 0x5481
+	TIOCGWINSZ                       = 0x40087468
+	TIOCINQ                          = 0x467f
+	TIOCLINUX                        = 0x5483
+	TIOCMBIC                         = 0x741c
+	TIOCMBIS                         = 0x741b
+	TIOCMGET                         = 0x741d
+	TIOCMIWAIT                       = 0x5491
+	TIOCMSET                         = 0x741a
+	TIOCM_CAR                        = 0x100
+	TIOCM_CD                         = 0x100
+	TIOCM_CTS                        = 0x40
+	TIOCM_DSR                        = 0x400
+	TIOCM_DTR                        = 0x2
+	TIOCM_LE                         = 0x1
+	TIOCM_RI                         = 0x200
+	TIOCM_RNG                        = 0x200
+	TIOCM_RTS                        = 0x4
+	TIOCM_SR                         = 0x20
+	TIOCM_ST                         = 0x10
+	TIOCNOTTY                        = 0x5471
+	TIOCNXCL                         = 0x740e
+	TIOCOUTQ                         = 0x7472
+	TIOCPKT                          = 0x5470
+	TIOCPKT_DATA                     = 0x0
+	TIOCPKT_DOSTOP                   = 0x20
+	TIOCPKT_FLUSHREAD                = 0x1
+	TIOCPKT_FLUSHWRITE               = 0x2
+	TIOCPKT_IOCTL                    = 0x40
+	TIOCPKT_NOSTOP                   = 0x10
+	TIOCPKT_START                    = 0x8
+	TIOCPKT_STOP                     = 0x4
+	TIOCSBRK                         = 0x5427
+	TIOCSCTTY                        = 0x5480
+	TIOCSERCONFIG                    = 0x5488
+	TIOCSERGETLSR                    = 0x548e
+	TIOCSERGETMULTI                  = 0x548f
+	TIOCSERGSTRUCT                   = 0x548d
+	TIOCSERGWILD                     = 0x5489
+	TIOCSERSETMULTI                  = 0x5490
+	TIOCSERSWILD                     = 0x548a
+	TIOCSER_TEMT                     = 0x1
+	TIOCSETD                         = 0x7401
+	TIOCSETN                         = 0x740a
+	TIOCSETP                         = 0x7409
+	TIOCSIG                          = 0x80045436
+	TIOCSLCKTRMIOS                   = 0x548c
+	TIOCSLTC                         = 0x7475
+	TIOCSPGRP                        = 0x80047476
+	TIOCSPTLCK                       = 0x80045431
+	TIOCSSERIAL                      = 0x5485
+	TIOCSSOFTCAR                     = 0x5482
+	TIOCSTI                          = 0x5472
+	TIOCSWINSZ                       = 0x80087467
+	TIOCVHANGUP                      = 0x5437
+	TOSTOP                           = 0x8000
+	TUNATTACHFILTER                  = 0x801054d5
+	TUNDETACHFILTER                  = 0x801054d6
+	TUNGETFEATURES                   = 0x400454cf
+	TUNGETFILTER                     = 0x401054db
+	TUNGETIFF                        = 0x400454d2
+	TUNGETSNDBUF                     = 0x400454d3
+	TUNGETVNETHDRSZ                  = 0x400454d7
+	TUNSETDEBUG                      = 0x800454c9
+	TUNSETGROUP                      = 0x800454ce
+	TUNSETIFF                        = 0x800454ca
+	TUNSETIFINDEX                    = 0x800454da
+	TUNSETLINK                       = 0x800454cd
+	TUNSETNOCSUM                     = 0x800454c8
+	TUNSETOFFLOAD                    = 0x800454d0
+	TUNSETOWNER                      = 0x800454cc
+	TUNSETPERSIST                    = 0x800454cb
+	TUNSETQUEUE                      = 0x800454d9
+	TUNSETSNDBUF                     = 0x800454d4
+	TUNSETTXFILTER                   = 0x800454d1
+	TUNSETVNETHDRSZ                  = 0x800454d8
+	VDISCARD                         = 0xd
+	VEOF                             = 0x10
+	VEOL                             = 0x11
+	VEOL2                            = 0x6
+	VERASE                           = 0x2
+	VINTR                            = 0x0
+	VKILL                            = 0x3
+	VLNEXT                           = 0xf
+	VMIN                             = 0x4
+	VQUIT                            = 0x1
+	VREPRINT                         = 0xc
+	VSTART                           = 0x8
+	VSTOP                            = 0x9
+	VSUSP                            = 0xa
+	VSWTC                            = 0x7
+	VSWTCH                           = 0x7
+	VT0                              = 0x0
+	VT1                              = 0x4000
+	VTDLY                            = 0x4000
+	VTIME                            = 0x5
+	VWERASE                          = 0xe
+	WALL                             = 0x40000000
+	WCLONE                           = 0x80000000
+	WCONTINUED                       = 0x8
+	WEXITED                          = 0x4
+	WNOHANG                          = 0x1
+	WNOTHREAD                        = 0x20000000
+	WNOWAIT                          = 0x1000000
+	WORDSIZE                         = 0x40
+	WSTOPPED                         = 0x2
+	WUNTRACED                        = 0x2
+)
+
+// Errors
+const (
+	E2BIG           = Errno(0x7)
+	EACCES          = Errno(0xd)
+	EADDRINUSE      = Errno(0x7d)
+	EADDRNOTAVAIL   = Errno(0x7e)
+	EADV            = Errno(0x44)
+	EAFNOSUPPORT    = Errno(0x7c)
+	EAGAIN          = Errno(0xb)
+	EALREADY        = Errno(0x95)
+	EBADE           = Errno(0x32)
+	EBADF           = Errno(0x9)
+	EBADFD          = Errno(0x51)
+	EBADMSG         = Errno(0x4d)
+	EBADR           = Errno(0x33)
+	EBADRQC         = Errno(0x36)
+	EBADSLT         = Errno(0x37)
+	EBFONT          = Errno(0x3b)
+	EBUSY           = Errno(0x10)
+	ECANCELED       = Errno(0x9e)
+	ECHILD          = Errno(0xa)
+	ECHRNG          = Errno(0x25)
+	ECOMM           = Errno(0x46)
+	ECONNABORTED    = Errno(0x82)
+	ECONNREFUSED    = Errno(0x92)
+	ECONNRESET      = Errno(0x83)
+	EDEADLK         = Errno(0x2d)
+	EDEADLOCK       = Errno(0x38)
+	EDESTADDRREQ    = Errno(0x60)
+	EDOM            = Errno(0x21)
+	EDOTDOT         = Errno(0x49)
+	EDQUOT          = Errno(0x46d)
+	EEXIST          = Errno(0x11)
+	EFAULT          = Errno(0xe)
+	EFBIG           = Errno(0x1b)
+	EHOSTDOWN       = Errno(0x93)
+	EHOSTUNREACH    = Errno(0x94)
+	EHWPOISON       = Errno(0xa8)
+	EIDRM           = Errno(0x24)
+	EILSEQ          = Errno(0x58)
+	EINIT           = Errno(0x8d)
+	EINPROGRESS     = Errno(0x96)
+	EINTR           = Errno(0x4)
+	EINVAL          = Errno(0x16)
+	EIO             = Errno(0x5)
+	EISCONN         = Errno(0x85)
+	EISDIR          = Errno(0x15)
+	EISNAM          = Errno(0x8b)
+	EKEYEXPIRED     = Errno(0xa2)
+	EKEYREJECTED    = Errno(0xa4)
+	EKEYREVOKED     = Errno(0xa3)
+	EL2HLT          = Errno(0x2c)
+	EL2NSYNC        = Errno(0x26)
+	EL3HLT          = Errno(0x27)
+	EL3RST          = Errno(0x28)
+	ELIBACC         = Errno(0x53)
+	ELIBBAD         = Errno(0x54)
+	ELIBEXEC        = Errno(0x57)
+	ELIBMAX         = Errno(0x56)
+	ELIBSCN         = Errno(0x55)
+	ELNRNG          = Errno(0x29)
+	ELOOP           = Errno(0x5a)
+	EMEDIUMTYPE     = Errno(0xa0)
+	EMFILE          = Errno(0x18)
+	EMLINK          = Errno(0x1f)
+	EMSGSIZE        = Errno(0x61)
+	EMULTIHOP       = Errno(0x4a)
+	ENAMETOOLONG    = Errno(0x4e)
+	ENAVAIL         = Errno(0x8a)
+	ENETDOWN        = Errno(0x7f)
+	ENETRESET       = Errno(0x81)
+	ENETUNREACH     = Errno(0x80)
+	ENFILE          = Errno(0x17)
+	ENOANO          = Errno(0x35)
+	ENOBUFS         = Errno(0x84)
+	ENOCSI          = Errno(0x2b)
+	ENODATA         = Errno(0x3d)
+	ENODEV          = Errno(0x13)
+	ENOENT          = Errno(0x2)
+	ENOEXEC         = Errno(0x8)
+	ENOKEY          = Errno(0xa1)
+	ENOLCK          = Errno(0x2e)
+	ENOLINK         = Errno(0x43)
+	ENOMEDIUM       = Errno(0x9f)
+	ENOMEM          = Errno(0xc)
+	ENOMSG          = Errno(0x23)
+	ENONET          = Errno(0x40)
+	ENOPKG          = Errno(0x41)
+	ENOPROTOOPT     = Errno(0x63)
+	ENOSPC          = Errno(0x1c)
+	ENOSR           = Errno(0x3f)
+	ENOSTR          = Errno(0x3c)
+	ENOSYS          = Errno(0x59)
+	ENOTBLK         = Errno(0xf)
+	ENOTCONN        = Errno(0x86)
+	ENOTDIR         = Errno(0x14)
+	ENOTEMPTY       = Errno(0x5d)
+	ENOTNAM         = Errno(0x89)
+	ENOTRECOVERABLE = Errno(0xa6)
+	ENOTSOCK        = Errno(0x5f)
+	ENOTSUP         = Errno(0x7a)
+	ENOTTY          = Errno(0x19)
+	ENOTUNIQ        = Errno(0x50)
+	ENXIO           = Errno(0x6)
+	EOPNOTSUPP      = Errno(0x7a)
+	EOVERFLOW       = Errno(0x4f)
+	EOWNERDEAD      = Errno(0xa5)
+	EPERM           = Errno(0x1)
+	EPFNOSUPPORT    = Errno(0x7b)
+	EPIPE           = Errno(0x20)
+	EPROTO          = Errno(0x47)
+	EPROTONOSUPPORT = Errno(0x78)
+	EPROTOTYPE      = Errno(0x62)
+	ERANGE          = Errno(0x22)
+	EREMCHG         = Errno(0x52)
+	EREMDEV         = Errno(0x8e)
+	EREMOTE         = Errno(0x42)
+	EREMOTEIO       = Errno(0x8c)
+	ERESTART        = Errno(0x5b)
+	ERFKILL         = Errno(0xa7)
+	EROFS           = Errno(0x1e)
+	ESHUTDOWN       = Errno(0x8f)
+	ESOCKTNOSUPPORT = Errno(0x79)
+	ESPIPE          = Errno(0x1d)
+	ESRCH           = Errno(0x3)
+	ESRMNT          = Errno(0x45)
+	ESTALE          = Errno(0x97)
+	ESTRPIPE        = Errno(0x5c)
+	ETIME           = Errno(0x3e)
+	ETIMEDOUT       = Errno(0x91)
+	ETOOMANYREFS    = Errno(0x90)
+	ETXTBSY         = Errno(0x1a)
+	EUCLEAN         = Errno(0x87)
+	EUNATCH         = Errno(0x2a)
+	EUSERS          = Errno(0x5e)
+	EWOULDBLOCK     = Errno(0xb)
+	EXDEV           = Errno(0x12)
+	EXFULL          = Errno(0x34)
+)
+
+// Signals
+const (
+	SIGABRT   = Signal(0x6)
+	SIGALRM   = Signal(0xe)
+	SIGBUS    = Signal(0xa)
+	SIGCHLD   = Signal(0x12)
+	SIGCLD    = Signal(0x12)
+	SIGCONT   = Signal(0x19)
+	SIGEMT    = Signal(0x7)
+	SIGFPE    = Signal(0x8)
+	SIGHUP    = Signal(0x1)
+	SIGILL    = Signal(0x4)
+	SIGINT    = Signal(0x2)
+	SIGIO     = Signal(0x16)
+	SIGIOT    = Signal(0x6)
+	SIGKILL   = Signal(0x9)
+	SIGPIPE   = Signal(0xd)
+	SIGPOLL   = Signal(0x16)
+	SIGPROF   = Signal(0x1d)
+	SIGPWR    = Signal(0x13)
+	SIGQUIT   = Signal(0x3)
+	SIGSEGV   = Signal(0xb)
+	SIGSTOP   = Signal(0x17)
+	SIGSYS    = Signal(0xc)
+	SIGTERM   = Signal(0xf)
+	SIGTRAP   = Signal(0x5)
+	SIGTSTP   = Signal(0x18)
+	SIGTTIN   = Signal(0x1a)
+	SIGTTOU   = Signal(0x1b)
+	SIGURG    = Signal(0x15)
+	SIGUSR1   = Signal(0x10)
+	SIGUSR2   = Signal(0x11)
+	SIGVTALRM = Signal(0x1c)
+	SIGWINCH  = Signal(0x14)
+	SIGXCPU   = Signal(0x1e)
+	SIGXFSZ   = Signal(0x1f)
+)
+
+// Error table
+var errors = [...]string{
+	1:    "operation not permitted",
+	2:    "no such file or directory",
+	3:    "no such process",
+	4:    "interrupted system call",
+	5:    "input/output error",
+	6:    "no such device or address",
+	7:    "argument list too long",
+	8:    "exec format error",
+	9:    "bad file descriptor",
+	10:   "no child processes",
+	11:   "resource temporarily unavailable",
+	12:   "cannot allocate memory",
+	13:   "permission denied",
+	14:   "bad address",
+	15:   "block device required",
+	16:   "device or resource busy",
+	17:   "file exists",
+	18:   "invalid cross-device link",
+	19:   "no such device",
+	20:   "not a directory",
+	21:   "is a directory",
+	22:   "invalid argument",
+	23:   "too many open files in system",
+	24:   "too many open files",
+	25:   "inappropriate ioctl for device",
+	26:   "text file busy",
+	27:   "file too large",
+	28:   "no space left on device",
+	29:   "illegal seek",
+	30:   "read-only file system",
+	31:   "too many links",
+	32:   "broken pipe",
+	33:   "numerical argument out of domain",
+	34:   "numerical result out of range",
+	35:   "no message of desired type",
+	36:   "identifier removed",
+	37:   "channel number out of range",
+	38:   "level 2 not synchronized",
+	39:   "level 3 halted",
+	40:   "level 3 reset",
+	41:   "link number out of range",
+	42:   "protocol driver not attached",
+	43:   "no CSI structure available",
+	44:   "level 2 halted",
+	45:   "resource deadlock avoided",
+	46:   "no locks available",
+	50:   "invalid exchange",
+	51:   "invalid request descriptor",
+	52:   "exchange full",
+	53:   "no anode",
+	54:   "invalid request code",
+	55:   "invalid slot",
+	56:   "file locking deadlock error",
+	59:   "bad font file format",
+	60:   "device not a stream",
+	61:   "no data available",
+	62:   "timer expired",
+	63:   "out of streams resources",
+	64:   "machine is not on the network",
+	65:   "package not installed",
+	66:   "object is remote",
+	67:   "link has been severed",
+	68:   "advertise error",
+	69:   "srmount error",
+	70:   "communication error on send",
+	71:   "protocol error",
+	73:   "RFS specific error",
+	74:   "multihop attempted",
+	77:   "bad message",
+	78:   "file name too long",
+	79:   "value too large for defined data type",
+	80:   "name not unique on network",
+	81:   "file descriptor in bad state",
+	82:   "remote address changed",
+	83:   "can not access a needed shared library",
+	84:   "accessing a corrupted shared library",
+	85:   ".lib section in a.out corrupted",
+	86:   "attempting to link in too many shared libraries",
+	87:   "cannot exec a shared library directly",
+	88:   "invalid or incomplete multibyte or wide character",
+	89:   "function not implemented",
+	90:   "too many levels of symbolic links",
+	91:   "interrupted system call should be restarted",
+	92:   "streams pipe error",
+	93:   "directory not empty",
+	94:   "too many users",
+	95:   "socket operation on non-socket",
+	96:   "destination address required",
+	97:   "message too long",
+	98:   "protocol wrong type for socket",
+	99:   "protocol not available",
+	120:  "protocol not supported",
+	121:  "socket type not supported",
+	122:  "operation not supported",
+	123:  "protocol family not supported",
+	124:  "address family not supported by protocol",
+	125:  "address already in use",
+	126:  "cannot assign requested address",
+	127:  "network is down",
+	128:  "network is unreachable",
+	129:  "network dropped connection on reset",
+	130:  "software caused connection abort",
+	131:  "connection reset by peer",
+	132:  "no buffer space available",
+	133:  "transport endpoint is already connected",
+	134:  "transport endpoint is not connected",
+	135:  "structure needs cleaning",
+	137:  "not a XENIX named type file",
+	138:  "no XENIX semaphores available",
+	139:  "is a named type file",
+	140:  "remote I/O error",
+	141:  "unknown error 141",
+	142:  "unknown error 142",
+	143:  "cannot send after transport endpoint shutdown",
+	144:  "too many references: cannot splice",
+	145:  "connection timed out",
+	146:  "connection refused",
+	147:  "host is down",
+	148:  "no route to host",
+	149:  "operation already in progress",
+	150:  "operation now in progress",
+	151:  "stale NFS file handle",
+	158:  "operation canceled",
+	159:  "no medium found",
+	160:  "wrong medium type",
+	161:  "required key not available",
+	162:  "key has expired",
+	163:  "key has been revoked",
+	164:  "key was rejected by service",
+	165:  "owner died",
+	166:  "state not recoverable",
+	167:  "operation not possible due to RF-kill",
+	168:  "memory page has hardware error",
+	1133: "disk quota exceeded",
+}
+
+// Signal table
+var signals = [...]string{
+	1:  "hangup",
+	2:  "interrupt",
+	3:  "quit",
+	4:  "illegal instruction",
+	5:  "trace/breakpoint trap",
+	6:  "aborted",
+	7:  "EMT trap",
+	8:  "floating point exception",
+	9:  "killed",
+	10: "bus error",
+	11: "segmentation fault",
+	12: "bad system call",
+	13: "broken pipe",
+	14: "alarm clock",
+	15: "terminated",
+	16: "user defined signal 1",
+	17: "user defined signal 2",
+	18: "child exited",
+	19: "power failure",
+	20: "window changed",
+	21: "urgent I/O condition",
+	22: "I/O possible",
+	23: "stopped (signal)",
+	24: "stopped",
+	25: "continued",
+	26: "stopped (tty input)",
+	27: "stopped (tty output)",
+	28: "virtual timer expired",
+	29: "profiling timer expired",
+	30: "CPU time limit exceeded",
+	31: "file size limit exceeded",
+}
diff --git a/src/syscall/zsyscall_linux_386.go b/src/syscall/zsyscall_linux_386.go
index 620fba2..82834fd 100644
--- a/src/syscall/zsyscall_linux_386.go
+++ b/src/syscall/zsyscall_linux_386.go
@@ -505,7 +505,7 @@ func Getdents(fd int, buf []byte) (n int, err error) {
 	} 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)
diff --git a/src/syscall/zsyscall_linux_amd64.go b/src/syscall/zsyscall_linux_amd64.go
index 16cafbf..e7f754e 100644
--- a/src/syscall/zsyscall_linux_amd64.go
+++ b/src/syscall/zsyscall_linux_amd64.go
@@ -505,7 +505,7 @@ func Getdents(fd int, buf []byte) (n int, err error) {
 	} 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)
diff --git a/src/syscall/zsyscall_linux_arm.go b/src/syscall/zsyscall_linux_arm.go
index 9bc3a54..aed89cd 100644
--- a/src/syscall/zsyscall_linux_arm.go
+++ b/src/syscall/zsyscall_linux_arm.go
@@ -505,7 +505,7 @@ func Getdents(fd int, buf []byte) (n int, err error) {
 	} 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)
diff --git a/src/syscall/zsyscall_linux_arm64.go b/src/syscall/zsyscall_linux_arm64.go
index 041e770..69df407 100644
--- a/src/syscall/zsyscall_linux_arm64.go
+++ b/src/syscall/zsyscall_linux_arm64.go
@@ -505,7 +505,7 @@ func Getdents(fd int, buf []byte) (n int, err error) {
 	} 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)
diff --git a/src/syscall/zsyscall_linux_mips64.go b/src/syscall/zsyscall_linux_mips64.go
new file mode 100644
index 0000000..d1d5f24
--- /dev/null
+++ b/src/syscall/zsyscall_linux_mips64.go
@@ -0,0 +1,1765 @@
+// mksyscall.pl syscall_linux.go syscall_linux_mips64x.go
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+package syscall
+
+import "unsafe"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(oldpath)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(newpath)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_LINKAT, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0)
+	use(unsafe.Pointer(_p0))
+	use(unsafe.Pointer(_p1))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mode), 0, 0)
+	use(unsafe.Pointer(_p0))
+	fd = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
+	if len(buf) > 0 {
+		_p1 = unsafe.Pointer(&buf[0])
+	} else {
+		_p1 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_READLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0)
+	use(unsafe.Pointer(_p0))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func symlinkat(oldpath string, newdirfd int, newpath string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(oldpath)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(newpath)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SYMLINKAT, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)))
+	use(unsafe.Pointer(_p0))
+	use(unsafe.Pointer(_p1))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func unlinkat(dirfd int, path string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags))
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func utimes(path string, times *[2]Timeval) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func utimensat(dirfd int, path string, times *[2]Timespec) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)))
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func futimesat(dirfd int, path *byte, times *[2]Timeval) (err error) {
+	_, _, e1 := Syscall(SYS_FUTIMESAT, uintptr(dirfd), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(times)))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getcwd(buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_GETCWD, uintptr(_p0), uintptr(len(buf)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) {
+	r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
+	wpid = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
+	_, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(arg)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_REBOOT, uintptr(magic1), uintptr(magic2), uintptr(cmd), uintptr(unsafe.Pointer(_p0)), 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func mount(source string, target string, fstype string, flags uintptr, data *byte) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(source)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(target)
+	if err != nil {
+		return
+	}
+	var _p2 *byte
+	_p2, err = BytePtrFromString(fstype)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_MOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(_p2)), uintptr(flags), uintptr(unsafe.Pointer(data)), 0)
+	use(unsafe.Pointer(_p0))
+	use(unsafe.Pointer(_p1))
+	use(unsafe.Pointer(_p2))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Acct(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_ACCT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Adjtimex(buf *Timex) (state int, err error) {
+	r0, _, e1 := Syscall(SYS_ADJTIMEX, uintptr(unsafe.Pointer(buf)), 0, 0)
+	state = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chdir(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chroot(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Close(fd int) (err error) {
+	_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup(oldfd int) (fd int, err error) {
+	r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup3(oldfd int, newfd int, flags int) (err error) {
+	_, _, e1 := Syscall(SYS_DUP3, uintptr(oldfd), uintptr(newfd), uintptr(flags))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollCreate(size int) (fd int, err error) {
+	r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollCreate1(flag int) (fd int, err error) {
+	r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE1, uintptr(flag), 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) {
+	_, _, e1 := RawSyscall6(SYS_EPOLL_CTL, uintptr(epfd), uintptr(op), uintptr(fd), uintptr(unsafe.Pointer(event)), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(events) > 0 {
+		_p0 = unsafe.Pointer(&events[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Exit(code int) {
+	Syscall(SYS_EXIT_GROUP, uintptr(code), 0, 0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fallocate(fd int, mode uint32, off int64, len int64) (err error) {
+	_, _, e1 := Syscall6(SYS_FALLOCATE, uintptr(fd), uintptr(mode), uintptr(off), uintptr(len), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchdir(fd int) (err error) {
+	_, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchmod(fd int, mode uint32) (err error) {
+	_, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func fcntl(fd int, cmd int, arg int) (val int, err error) {
+	r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
+	val = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fdatasync(fd int) (err error) {
+	_, _, e1 := Syscall(SYS_FDATASYNC, uintptr(fd), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Flock(fd int, how int) (err error) {
+	_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fsync(fd int) (err error) {
+	_, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getdents(fd int, buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpgid(pid int) (pgid int, err error) {
+	r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0)
+	pgid = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpid() (pid int) {
+	r0, _, _ := RawSyscall(SYS_GETPID, 0, 0, 0)
+	pid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getppid() (ppid int) {
+	r0, _, _ := RawSyscall(SYS_GETPPID, 0, 0, 0)
+	ppid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpriority(which int, who int) (prio int, err error) {
+	r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0)
+	prio = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getrusage(who int, rusage *Rusage) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Gettid() (tid int) {
+	r0, _, _ := RawSyscall(SYS_GETTID, 0, 0, 0)
+	tid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getxattr(path string, attr string, dest []byte) (sz int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	var _p2 unsafe.Pointer
+	if len(dest) > 0 {
+		_p2 = unsafe.Pointer(&dest[0])
+	} else {
+		_p2 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0)
+	use(unsafe.Pointer(_p0))
+	use(unsafe.Pointer(_p1))
+	sz = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(pathname)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_INOTIFY_ADD_WATCH, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mask))
+	use(unsafe.Pointer(_p0))
+	watchdesc = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyInit1(flags int) (fd int, err error) {
+	r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT1, uintptr(flags), 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) {
+	r0, _, e1 := RawSyscall(SYS_INOTIFY_RM_WATCH, uintptr(fd), uintptr(watchdesc), 0)
+	success = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Kill(pid int, sig Signal) (err error) {
+	_, _, e1 := RawSyscall(SYS_KILL, uintptr(pid), uintptr(sig), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Klogctl(typ int, buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_SYSLOG, uintptr(typ), uintptr(_p0), uintptr(len(buf)))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Listxattr(path string, dest []byte) (sz int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
+	if len(dest) > 0 {
+		_p1 = unsafe.Pointer(&dest[0])
+	} else {
+		_p1 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)))
+	use(unsafe.Pointer(_p0))
+	sz = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mkdirat(dirfd int, path string, mode uint32) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode))
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
+	_, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pause() (err error) {
+	_, _, e1 := Syscall(SYS_PAUSE, 0, 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func PivotRoot(newroot string, putold string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(newroot)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(putold)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_PIVOT_ROOT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+	use(unsafe.Pointer(_p0))
+	use(unsafe.Pointer(_p1))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) {
+	_, _, e1 := RawSyscall6(SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(newlimit)), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func read(fd int, p []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Removexattr(path string, attr string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+	use(unsafe.Pointer(_p0))
+	use(unsafe.Pointer(_p1))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(oldpath)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(newpath)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), 0, 0)
+	use(unsafe.Pointer(_p0))
+	use(unsafe.Pointer(_p1))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setdomainname(p []byte) (err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_SETDOMAINNAME, uintptr(_p0), uintptr(len(p)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Sethostname(p []byte) (err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_SETHOSTNAME, uintptr(_p0), uintptr(len(p)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setpgid(pid int, pgid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setsid() (pid int, err error) {
+	r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
+	pid = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Settimeofday(tv *Timeval) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setpriority(which int, who int, prio int) (err error) {
+	_, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setxattr(path string, attr string, data []byte, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	var _p2 unsafe.Pointer
+	if len(data) > 0 {
+		_p2 = unsafe.Pointer(&data[0])
+	} else {
+		_p2 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall6(SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0)
+	use(unsafe.Pointer(_p0))
+	use(unsafe.Pointer(_p1))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Sync() {
+	Syscall(SYS_SYNC, 0, 0, 0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Sysinfo(info *Sysinfo_t) (err error) {
+	_, _, e1 := RawSyscall(SYS_SYSINFO, uintptr(unsafe.Pointer(info)), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
+	r0, _, e1 := Syscall6(SYS_TEE, uintptr(rfd), uintptr(wfd), uintptr(len), uintptr(flags), 0, 0)
+	n = int64(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Tgkill(tgid int, tid int, sig Signal) (err error) {
+	_, _, e1 := RawSyscall(SYS_TGKILL, uintptr(tgid), uintptr(tid), uintptr(sig))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Times(tms *Tms) (ticks uintptr, err error) {
+	r0, _, e1 := RawSyscall(SYS_TIMES, uintptr(unsafe.Pointer(tms)), 0, 0)
+	ticks = uintptr(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Umask(mask int) (oldmask int) {
+	r0, _, _ := RawSyscall(SYS_UMASK, uintptr(mask), 0, 0)
+	oldmask = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Uname(buf *Utsname) (err error) {
+	_, _, e1 := RawSyscall(SYS_UNAME, uintptr(unsafe.Pointer(buf)), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Unmount(target string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(target)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UMOUNT2, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Unshare(flags int) (err error) {
+	_, _, e1 := Syscall(SYS_UNSHARE, uintptr(flags), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Ustat(dev int, ubuf *Ustat_t) (err error) {
+	_, _, e1 := Syscall(SYS_USTAT, uintptr(dev), uintptr(unsafe.Pointer(ubuf)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Utime(path string, buf *Utimbuf) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func write(fd int, p []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func exitThread(code int) (err error) {
+	_, _, e1 := Syscall(SYS_EXIT, uintptr(code), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func readlen(fd int, p *byte, np int) (n int, err error) {
+	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func writelen(fd int, p *byte, np int) (n int, err error) {
+	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func munmap(addr uintptr, length uintptr) (err error) {
+	_, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Madvise(b []byte, advice int) (err error) {
+	var _p0 unsafe.Pointer
+	if len(b) > 0 {
+		_p0 = unsafe.Pointer(&b[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_MADVISE, uintptr(_p0), uintptr(len(b)), uintptr(advice))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mprotect(b []byte, prot int) (err error) {
+	var _p0 unsafe.Pointer
+	if len(b) > 0 {
+		_p0 = unsafe.Pointer(&b[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mlock(b []byte) (err error) {
+	var _p0 unsafe.Pointer
+	if len(b) > 0 {
+		_p0 = unsafe.Pointer(&b[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_MLOCK, uintptr(_p0), uintptr(len(b)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Munlock(b []byte) (err error) {
+	var _p0 unsafe.Pointer
+	if len(b) > 0 {
+		_p0 = unsafe.Pointer(&b[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_MUNLOCK, uintptr(_p0), uintptr(len(b)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mlockall(flags int) (err error) {
+	_, _, e1 := Syscall(SYS_MLOCKALL, uintptr(flags), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Munlockall() (err error) {
+	_, _, e1 := Syscall(SYS_MUNLOCKALL, 0, 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup2(oldfd int, newfd int) (err error) {
+	_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchown(fd int, uid int, gid int) (err error) {
+	_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fstatfs(fd int, buf *Statfs_t) (err error) {
+	_, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(buf)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Ftruncate(fd int, length int64) (err error) {
+	_, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getegid() (egid int) {
+	r0, _, _ := RawSyscall(SYS_GETEGID, 0, 0, 0)
+	egid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Geteuid() (euid int) {
+	r0, _, _ := RawSyscall(SYS_GETEUID, 0, 0, 0)
+	euid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getgid() (gid int) {
+	r0, _, _ := RawSyscall(SYS_GETGID, 0, 0, 0)
+	gid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getrlimit(resource int, rlim *Rlimit) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getuid() (uid int) {
+	r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0)
+	uid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyInit() (fd int, err error) {
+	r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Lchown(path string, uid int, gid int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Listen(s int, n int) (err error) {
+	_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(n), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_PREAD64, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_PWRITE64, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Seek(fd int, offset int64, whence int) (off int64, err error) {
+	r0, _, e1 := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence))
+	off = int64(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) {
+	r0, _, e1 := Syscall6(SYS_PSELECT6, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+	r0, _, e1 := Syscall6(SYS_SENDFILE, uintptr(outfd), uintptr(infd), uintptr(unsafe.Pointer(offset)), uintptr(count), 0, 0)
+	written = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setfsgid(gid int) (err error) {
+	_, _, e1 := Syscall(SYS_SETFSGID, uintptr(gid), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setfsuid(uid int) (err error) {
+	_, _, e1 := Syscall(SYS_SETFSUID, uintptr(uid), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setregid(rgid int, egid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setresgid(rgid int, egid int, sgid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setresuid(ruid int, euid int, suid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setrlimit(resource int, rlim *Rlimit) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setreuid(ruid int, euid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Shutdown(fd int, how int) (err error) {
+	_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) {
+	r0, _, e1 := Syscall6(SYS_SPLICE, uintptr(rfd), uintptr(unsafe.Pointer(roff)), uintptr(wfd), uintptr(unsafe.Pointer(woff)), uintptr(len), uintptr(flags))
+	n = int64(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Statfs(path string, buf *Statfs_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func SyncFileRange(fd int, off int64, n int64, flags int) (err error) {
+	_, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE, uintptr(fd), uintptr(off), uintptr(n), uintptr(flags), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Truncate(path string, length int64) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
+	r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+	fd = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) {
+	r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
+	_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
+	_, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getgroups(n int, list *_Gid_t) (nn int, err error) {
+	r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0)
+	nn = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setgroups(n int, list *_Gid_t) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) {
+	_, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) {
+	_, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func socket(domain int, typ int, proto int) (fd int, err error) {
+	r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto))
+	fd = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
+	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
+	r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) {
+	r0, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
+	r0, _, e1 := Syscall6(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(offset))
+	xaddr = uintptr(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Gettimeofday(tv *Timeval) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func pipe2(p *[2]_C_int, flags int) (err error) {
+	_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func fstat(fd int, stat *stat_t) (err error) {
+	_, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func lstat(path string, stat *stat_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func stat(path string, stat *stat_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
diff --git a/src/syscall/zsyscall_linux_mips64le.go b/src/syscall/zsyscall_linux_mips64le.go
new file mode 100644
index 0000000..d1d5f24
--- /dev/null
+++ b/src/syscall/zsyscall_linux_mips64le.go
@@ -0,0 +1,1765 @@
+// mksyscall.pl syscall_linux.go syscall_linux_mips64x.go
+// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
+
+package syscall
+
+import "unsafe"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(oldpath)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(newpath)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_LINKAT, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0)
+	use(unsafe.Pointer(_p0))
+	use(unsafe.Pointer(_p1))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall6(SYS_OPENAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mode), 0, 0)
+	use(unsafe.Pointer(_p0))
+	fd = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func readlinkat(dirfd int, path string, buf []byte) (n int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
+	if len(buf) > 0 {
+		_p1 = unsafe.Pointer(&buf[0])
+	} else {
+		_p1 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_READLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0)
+	use(unsafe.Pointer(_p0))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func symlinkat(oldpath string, newdirfd int, newpath string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(oldpath)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(newpath)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_SYMLINKAT, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)))
+	use(unsafe.Pointer(_p0))
+	use(unsafe.Pointer(_p1))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func unlinkat(dirfd int, path string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags))
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func utimes(path string, times *[2]Timeval) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIMES, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)), 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func utimensat(dirfd int, path string, times *[2]Timespec) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIMENSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(times)))
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func futimesat(dirfd int, path *byte, times *[2]Timeval) (err error) {
+	_, _, e1 := Syscall(SYS_FUTIMESAT, uintptr(dirfd), uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(times)))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getcwd(buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_GETCWD, uintptr(_p0), uintptr(len(buf)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func wait4(pid int, wstatus *_C_int, options int, rusage *Rusage) (wpid int, err error) {
+	r0, _, e1 := Syscall6(SYS_WAIT4, uintptr(pid), uintptr(unsafe.Pointer(wstatus)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0)
+	wpid = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) {
+	_, _, e1 := Syscall6(SYS_PTRACE, uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func reboot(magic1 uint, magic2 uint, cmd int, arg string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(arg)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_REBOOT, uintptr(magic1), uintptr(magic2), uintptr(cmd), uintptr(unsafe.Pointer(_p0)), 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func mount(source string, target string, fstype string, flags uintptr, data *byte) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(source)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(target)
+	if err != nil {
+		return
+	}
+	var _p2 *byte
+	_p2, err = BytePtrFromString(fstype)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_MOUNT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(unsafe.Pointer(_p2)), uintptr(flags), uintptr(unsafe.Pointer(data)), 0)
+	use(unsafe.Pointer(_p0))
+	use(unsafe.Pointer(_p1))
+	use(unsafe.Pointer(_p2))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Acct(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_ACCT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Adjtimex(buf *Timex) (state int, err error) {
+	r0, _, e1 := Syscall(SYS_ADJTIMEX, uintptr(unsafe.Pointer(buf)), 0, 0)
+	state = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chdir(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Chroot(path string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_CHROOT, uintptr(unsafe.Pointer(_p0)), 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Close(fd int) (err error) {
+	_, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup(oldfd int) (fd int, err error) {
+	r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup3(oldfd int, newfd int, flags int) (err error) {
+	_, _, e1 := Syscall(SYS_DUP3, uintptr(oldfd), uintptr(newfd), uintptr(flags))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollCreate(size int) (fd int, err error) {
+	r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE, uintptr(size), 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollCreate1(flag int) (fd int, err error) {
+	r0, _, e1 := RawSyscall(SYS_EPOLL_CREATE1, uintptr(flag), 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) {
+	_, _, e1 := RawSyscall6(SYS_EPOLL_CTL, uintptr(epfd), uintptr(op), uintptr(fd), uintptr(unsafe.Pointer(event)), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(events) > 0 {
+		_p0 = unsafe.Pointer(&events[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_EPOLL_WAIT, uintptr(epfd), uintptr(_p0), uintptr(len(events)), uintptr(msec), 0, 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Exit(code int) {
+	Syscall(SYS_EXIT_GROUP, uintptr(code), 0, 0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fallocate(fd int, mode uint32, off int64, len int64) (err error) {
+	_, _, e1 := Syscall6(SYS_FALLOCATE, uintptr(fd), uintptr(mode), uintptr(off), uintptr(len), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchdir(fd int) (err error) {
+	_, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchmod(fd int, mode uint32) (err error) {
+	_, _, e1 := Syscall(SYS_FCHMOD, uintptr(fd), uintptr(mode), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FCHMODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func fcntl(fd int, cmd int, arg int) (val int, err error) {
+	r0, _, e1 := Syscall(SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg))
+	val = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fdatasync(fd int) (err error) {
+	_, _, e1 := Syscall(SYS_FDATASYNC, uintptr(fd), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Flock(fd int, how int) (err error) {
+	_, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fsync(fd int) (err error) {
+	_, _, e1 := Syscall(SYS_FSYNC, uintptr(fd), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getdents(fd int, buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(_SYS_getdents, uintptr(fd), uintptr(_p0), uintptr(len(buf)))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpgid(pid int) (pgid int, err error) {
+	r0, _, e1 := RawSyscall(SYS_GETPGID, uintptr(pid), 0, 0)
+	pgid = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpid() (pid int) {
+	r0, _, _ := RawSyscall(SYS_GETPID, 0, 0, 0)
+	pid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getppid() (ppid int) {
+	r0, _, _ := RawSyscall(SYS_GETPPID, 0, 0, 0)
+	ppid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getpriority(which int, who int) (prio int, err error) {
+	r0, _, e1 := Syscall(SYS_GETPRIORITY, uintptr(which), uintptr(who), 0)
+	prio = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getrusage(who int, rusage *Rusage) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Gettid() (tid int) {
+	r0, _, _ := RawSyscall(SYS_GETTID, 0, 0, 0)
+	tid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getxattr(path string, attr string, dest []byte) (sz int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	var _p2 unsafe.Pointer
+	if len(dest) > 0 {
+		_p2 = unsafe.Pointer(&dest[0])
+	} else {
+		_p2 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(dest)), 0, 0)
+	use(unsafe.Pointer(_p0))
+	use(unsafe.Pointer(_p1))
+	sz = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(pathname)
+	if err != nil {
+		return
+	}
+	r0, _, e1 := Syscall(SYS_INOTIFY_ADD_WATCH, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mask))
+	use(unsafe.Pointer(_p0))
+	watchdesc = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyInit1(flags int) (fd int, err error) {
+	r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT1, uintptr(flags), 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyRmWatch(fd int, watchdesc uint32) (success int, err error) {
+	r0, _, e1 := RawSyscall(SYS_INOTIFY_RM_WATCH, uintptr(fd), uintptr(watchdesc), 0)
+	success = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Kill(pid int, sig Signal) (err error) {
+	_, _, e1 := RawSyscall(SYS_KILL, uintptr(pid), uintptr(sig), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Klogctl(typ int, buf []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_SYSLOG, uintptr(typ), uintptr(_p0), uintptr(len(buf)))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Listxattr(path string, dest []byte) (sz int, err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 unsafe.Pointer
+	if len(dest) > 0 {
+		_p1 = unsafe.Pointer(&dest[0])
+	} else {
+		_p1 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_LISTXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(dest)))
+	use(unsafe.Pointer(_p0))
+	sz = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mkdirat(dirfd int, path string, mode uint32) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode))
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Nanosleep(time *Timespec, leftover *Timespec) (err error) {
+	_, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pause() (err error) {
+	_, _, e1 := Syscall(SYS_PAUSE, 0, 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func PivotRoot(newroot string, putold string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(newroot)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(putold)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_PIVOT_ROOT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+	use(unsafe.Pointer(_p0))
+	use(unsafe.Pointer(_p1))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) {
+	_, _, e1 := RawSyscall6(SYS_PRLIMIT64, uintptr(pid), uintptr(resource), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(newlimit)), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func read(fd int, p []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Removexattr(path string, attr string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_REMOVEXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), 0)
+	use(unsafe.Pointer(_p0))
+	use(unsafe.Pointer(_p1))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(oldpath)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(newpath)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(olddirfd), uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1)), 0, 0)
+	use(unsafe.Pointer(_p0))
+	use(unsafe.Pointer(_p1))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setdomainname(p []byte) (err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_SETDOMAINNAME, uintptr(_p0), uintptr(len(p)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Sethostname(p []byte) (err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_SETHOSTNAME, uintptr(_p0), uintptr(len(p)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setpgid(pid int, pgid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETPGID, uintptr(pid), uintptr(pgid), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setsid() (pid int, err error) {
+	r0, _, e1 := RawSyscall(SYS_SETSID, 0, 0, 0)
+	pid = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Settimeofday(tv *Timeval) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setpriority(which int, who int, prio int) (err error) {
+	_, _, e1 := Syscall(SYS_SETPRIORITY, uintptr(which), uintptr(who), uintptr(prio))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setxattr(path string, attr string, data []byte, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(attr)
+	if err != nil {
+		return
+	}
+	var _p2 unsafe.Pointer
+	if len(data) > 0 {
+		_p2 = unsafe.Pointer(&data[0])
+	} else {
+		_p2 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall6(SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(_p2), uintptr(len(data)), uintptr(flags), 0)
+	use(unsafe.Pointer(_p0))
+	use(unsafe.Pointer(_p1))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Sync() {
+	Syscall(SYS_SYNC, 0, 0, 0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Sysinfo(info *Sysinfo_t) (err error) {
+	_, _, e1 := RawSyscall(SYS_SYSINFO, uintptr(unsafe.Pointer(info)), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Tee(rfd int, wfd int, len int, flags int) (n int64, err error) {
+	r0, _, e1 := Syscall6(SYS_TEE, uintptr(rfd), uintptr(wfd), uintptr(len), uintptr(flags), 0, 0)
+	n = int64(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Tgkill(tgid int, tid int, sig Signal) (err error) {
+	_, _, e1 := RawSyscall(SYS_TGKILL, uintptr(tgid), uintptr(tid), uintptr(sig))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Times(tms *Tms) (ticks uintptr, err error) {
+	r0, _, e1 := RawSyscall(SYS_TIMES, uintptr(unsafe.Pointer(tms)), 0, 0)
+	ticks = uintptr(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Umask(mask int) (oldmask int) {
+	r0, _, _ := RawSyscall(SYS_UMASK, uintptr(mask), 0, 0)
+	oldmask = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Uname(buf *Utsname) (err error) {
+	_, _, e1 := RawSyscall(SYS_UNAME, uintptr(unsafe.Pointer(buf)), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Unmount(target string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(target)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UMOUNT2, uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Unshare(flags int) (err error) {
+	_, _, e1 := Syscall(SYS_UNSHARE, uintptr(flags), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Ustat(dev int, ubuf *Ustat_t) (err error) {
+	_, _, e1 := Syscall(SYS_USTAT, uintptr(dev), uintptr(unsafe.Pointer(ubuf)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Utime(path string, buf *Utimbuf) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_UTIME, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func write(fd int, p []byte) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func exitThread(code int) (err error) {
+	_, _, e1 := Syscall(SYS_EXIT, uintptr(code), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func readlen(fd int, p *byte, np int) (n int, err error) {
+	r0, _, e1 := Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func writelen(fd int, p *byte, np int) (n int, err error) {
+	r0, _, e1 := Syscall(SYS_WRITE, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(np))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func munmap(addr uintptr, length uintptr) (err error) {
+	_, _, e1 := Syscall(SYS_MUNMAP, uintptr(addr), uintptr(length), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Madvise(b []byte, advice int) (err error) {
+	var _p0 unsafe.Pointer
+	if len(b) > 0 {
+		_p0 = unsafe.Pointer(&b[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_MADVISE, uintptr(_p0), uintptr(len(b)), uintptr(advice))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mprotect(b []byte, prot int) (err error) {
+	var _p0 unsafe.Pointer
+	if len(b) > 0 {
+		_p0 = unsafe.Pointer(&b[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_MPROTECT, uintptr(_p0), uintptr(len(b)), uintptr(prot))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mlock(b []byte) (err error) {
+	var _p0 unsafe.Pointer
+	if len(b) > 0 {
+		_p0 = unsafe.Pointer(&b[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_MLOCK, uintptr(_p0), uintptr(len(b)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Munlock(b []byte) (err error) {
+	var _p0 unsafe.Pointer
+	if len(b) > 0 {
+		_p0 = unsafe.Pointer(&b[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall(SYS_MUNLOCK, uintptr(_p0), uintptr(len(b)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Mlockall(flags int) (err error) {
+	_, _, e1 := Syscall(SYS_MLOCKALL, uintptr(flags), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Munlockall() (err error) {
+	_, _, e1 := Syscall(SYS_MUNLOCKALL, 0, 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Dup2(oldfd int, newfd int) (err error) {
+	_, _, e1 := Syscall(SYS_DUP2, uintptr(oldfd), uintptr(newfd), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fchown(fd int, uid int, gid int) (err error) {
+	_, _, e1 := Syscall(SYS_FCHOWN, uintptr(fd), uintptr(uid), uintptr(gid))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Fstatfs(fd int, buf *Statfs_t) (err error) {
+	_, _, e1 := Syscall(SYS_FSTATFS, uintptr(fd), uintptr(unsafe.Pointer(buf)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Ftruncate(fd int, length int64) (err error) {
+	_, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getegid() (egid int) {
+	r0, _, _ := RawSyscall(SYS_GETEGID, 0, 0, 0)
+	egid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Geteuid() (euid int) {
+	r0, _, _ := RawSyscall(SYS_GETEUID, 0, 0, 0)
+	euid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getgid() (gid int) {
+	r0, _, _ := RawSyscall(SYS_GETGID, 0, 0, 0)
+	gid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getrlimit(resource int, rlim *Rlimit) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Getuid() (uid int) {
+	r0, _, _ := RawSyscall(SYS_GETUID, 0, 0, 0)
+	uid = int(r0)
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func InotifyInit() (fd int, err error) {
+	r0, _, e1 := RawSyscall(SYS_INOTIFY_INIT, 0, 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Lchown(path string, uid int, gid int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LCHOWN, uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid))
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Listen(s int, n int) (err error) {
+	_, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(n), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pread(fd int, p []byte, offset int64) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_PREAD64, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Pwrite(fd int, p []byte, offset int64) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_PWRITE64, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), 0, 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Seek(fd int, offset int64, whence int) (off int64, err error) {
+	r0, _, e1 := Syscall(SYS_LSEEK, uintptr(fd), uintptr(offset), uintptr(whence))
+	off = int64(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) {
+	r0, _, e1 := Syscall6(SYS_PSELECT6, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
+	r0, _, e1 := Syscall6(SYS_SENDFILE, uintptr(outfd), uintptr(infd), uintptr(unsafe.Pointer(offset)), uintptr(count), 0, 0)
+	written = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setfsgid(gid int) (err error) {
+	_, _, e1 := Syscall(SYS_SETFSGID, uintptr(gid), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setfsuid(uid int) (err error) {
+	_, _, e1 := Syscall(SYS_SETFSUID, uintptr(uid), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setregid(rgid int, egid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETREGID, uintptr(rgid), uintptr(egid), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setresgid(rgid int, egid int, sgid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETRESGID, uintptr(rgid), uintptr(egid), uintptr(sgid))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setresuid(ruid int, euid int, suid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETRESUID, uintptr(ruid), uintptr(euid), uintptr(suid))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setrlimit(resource int, rlim *Rlimit) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETRLIMIT, uintptr(resource), uintptr(unsafe.Pointer(rlim)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Setreuid(ruid int, euid int) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETREUID, uintptr(ruid), uintptr(euid), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Shutdown(fd int, how int) (err error) {
+	_, _, e1 := Syscall(SYS_SHUTDOWN, uintptr(fd), uintptr(how), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error) {
+	r0, _, e1 := Syscall6(SYS_SPLICE, uintptr(rfd), uintptr(unsafe.Pointer(roff)), uintptr(wfd), uintptr(unsafe.Pointer(woff)), uintptr(len), uintptr(flags))
+	n = int64(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Statfs(path string, buf *Statfs_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STATFS, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(buf)), 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func SyncFileRange(fd int, off int64, n int64, flags int) (err error) {
+	_, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE, uintptr(fd), uintptr(off), uintptr(n), uintptr(flags), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Truncate(path string, length int64) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_TRUNCATE, uintptr(unsafe.Pointer(_p0)), uintptr(length), 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error) {
+	r0, _, e1 := Syscall(SYS_ACCEPT, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+	fd = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error) {
+	r0, _, e1 := Syscall6(SYS_ACCEPT4, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), uintptr(flags), 0, 0)
+	fd = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
+	_, _, e1 := Syscall(SYS_BIND, uintptr(s), uintptr(addr), uintptr(addrlen))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error) {
+	_, _, e1 := Syscall(SYS_CONNECT, uintptr(s), uintptr(addr), uintptr(addrlen))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getgroups(n int, list *_Gid_t) (nn int, err error) {
+	r0, _, e1 := RawSyscall(SYS_GETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0)
+	nn = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setgroups(n int, list *_Gid_t) (err error) {
+	_, _, e1 := RawSyscall(SYS_SETGROUPS, uintptr(n), uintptr(unsafe.Pointer(list)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error) {
+	_, _, e1 := Syscall6(SYS_GETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(unsafe.Pointer(vallen)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error) {
+	_, _, e1 := Syscall6(SYS_SETSOCKOPT, uintptr(s), uintptr(level), uintptr(name), uintptr(val), uintptr(vallen), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func socket(domain int, typ int, proto int) (fd int, err error) {
+	r0, _, e1 := RawSyscall(SYS_SOCKET, uintptr(domain), uintptr(typ), uintptr(proto))
+	fd = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func socketpair(domain int, typ int, proto int, fd *[2]int32) (err error) {
+	_, _, e1 := RawSyscall6(SYS_SOCKETPAIR, uintptr(domain), uintptr(typ), uintptr(proto), uintptr(unsafe.Pointer(fd)), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETPEERNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETSOCKNAME, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(p) > 0 {
+		_p0 = unsafe.Pointer(&p[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_RECVFROM, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	_, _, e1 := Syscall6(SYS_SENDTO, uintptr(s), uintptr(_p0), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(addrlen))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func recvmsg(s int, msg *Msghdr, flags int) (n int, err error) {
+	r0, _, e1 := Syscall(SYS_RECVMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func sendmsg(s int, msg *Msghdr, flags int) (n int, err error) {
+	r0, _, e1 := Syscall(SYS_SENDMSG, uintptr(s), uintptr(unsafe.Pointer(msg)), uintptr(flags))
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
+	r0, _, e1 := Syscall6(SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(offset))
+	xaddr = uintptr(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Gettimeofday(tv *Timeval) (err error) {
+	_, _, e1 := RawSyscall(SYS_GETTIMEOFDAY, uintptr(unsafe.Pointer(tv)), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func pipe2(p *[2]_C_int, flags int) (err error) {
+	_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func fstat(fd int, stat *stat_t) (err error) {
+	_, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func lstat(path string, stat *stat_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_LSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func stat(path string, stat *stat_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), 0)
+	use(unsafe.Pointer(_p0))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
diff --git a/src/syscall/zsyscall_linux_ppc64.go b/src/syscall/zsyscall_linux_ppc64.go
index 4f61114..352525f 100644
--- a/src/syscall/zsyscall_linux_ppc64.go
+++ b/src/syscall/zsyscall_linux_ppc64.go
@@ -505,7 +505,7 @@ func Getdents(fd int, buf []byte) (n int, err error) {
 	} 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)
diff --git a/src/syscall/zsyscall_linux_ppc64le.go b/src/syscall/zsyscall_linux_ppc64le.go
index 4073a0f..ac49c5c 100644
--- a/src/syscall/zsyscall_linux_ppc64le.go
+++ b/src/syscall/zsyscall_linux_ppc64le.go
@@ -505,7 +505,7 @@ func Getdents(fd int, buf []byte) (n int, err error) {
 	} 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)
diff --git a/src/syscall/zsyscall_solaris_amd64.go b/src/syscall/zsyscall_solaris_amd64.go
index cabab7e..ebdeb92 100644
--- a/src/syscall/zsyscall_solaris_amd64.go
+++ b/src/syscall/zsyscall_solaris_amd64.go
@@ -7,6 +7,7 @@ package syscall
 
 import "unsafe"
 
+//go:cgo_import_dynamic libc_Getcwd getcwd "libc.so"
 //go:cgo_import_dynamic libc_getgroups getgroups "libc.so"
 //go:cgo_import_dynamic libc_setgroups setgroups "libc.so"
 //go:cgo_import_dynamic libc_fcntl fcntl "libc.so"
@@ -89,6 +90,7 @@ import "unsafe"
 //go:cgo_import_dynamic libc_recvfrom recvfrom "libsocket.so"
 //go:cgo_import_dynamic libc_recvmsg recvmsg "libsocket.so"
 
+//go:linkname libc_Getcwd libc_Getcwd
 //go:linkname libc_getgroups libc_getgroups
 //go:linkname libc_setgroups libc_setgroups
 //go:linkname libc_fcntl libc_fcntl
@@ -174,6 +176,7 @@ import "unsafe"
 type libcFunc uintptr
 
 var (
+	libc_Getcwd,
 	libc_getgroups,
 	libc_setgroups,
 	libc_fcntl,
@@ -257,6 +260,19 @@ var (
 	libc_recvmsg libcFunc
 )
 
+func Getcwd(buf []byte) (n int, err error) {
+	var _p0 *byte
+	if len(buf) > 0 {
+		_p0 = &buf[0]
+	}
+	r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&libc_Getcwd)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), 0, 0, 0, 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
 func getgroups(ngid int, gid *_Gid_t) (n int, err error) {
 	r0, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&libc_getgroups)), 2, uintptr(ngid), uintptr(unsafe.Pointer(gid)), 0, 0, 0, 0)
 	n = int(r0)
diff --git a/src/syscall/zsysnum_linux_mips64.go b/src/syscall/zsysnum_linux_mips64.go
new file mode 100644
index 0000000..a51ecfe
--- /dev/null
+++ b/src/syscall/zsysnum_linux_mips64.go
@@ -0,0 +1,323 @@
+// mksysnum_linux.pl /usr/include/asm/unistd.h
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package syscall
+
+const (
+	SYS_READ                   = 5000
+	SYS_WRITE                  = 5001
+	SYS_OPEN                   = 5002
+	SYS_CLOSE                  = 5003
+	SYS_STAT                   = 5004
+	SYS_FSTAT                  = 5005
+	SYS_LSTAT                  = 5006
+	SYS_POLL                   = 5007
+	SYS_LSEEK                  = 5008
+	SYS_MMAP                   = 5009
+	SYS_MPROTECT               = 5010
+	SYS_MUNMAP                 = 5011
+	SYS_BRK                    = 5012
+	SYS_RT_SIGACTION           = 5013
+	SYS_RT_SIGPROCMASK         = 5014
+	SYS_IOCTL                  = 5015
+	SYS_PREAD64                = 5016
+	SYS_PWRITE64               = 5017
+	SYS_READV                  = 5018
+	SYS_WRITEV                 = 5019
+	SYS_ACCESS                 = 5020
+	SYS_PIPE                   = 5021
+	SYS__NEWSELECT             = 5022
+	SYS_SCHED_YIELD            = 5023
+	SYS_MREMAP                 = 5024
+	SYS_MSYNC                  = 5025
+	SYS_MINCORE                = 5026
+	SYS_MADVISE                = 5027
+	SYS_SHMGET                 = 5028
+	SYS_SHMAT                  = 5029
+	SYS_SHMCTL                 = 5030
+	SYS_DUP                    = 5031
+	SYS_DUP2                   = 5032
+	SYS_PAUSE                  = 5033
+	SYS_NANOSLEEP              = 5034
+	SYS_GETITIMER              = 5035
+	SYS_SETITIMER              = 5036
+	SYS_ALARM                  = 5037
+	SYS_GETPID                 = 5038
+	SYS_SENDFILE               = 5039
+	SYS_SOCKET                 = 5040
+	SYS_CONNECT                = 5041
+	SYS_ACCEPT                 = 5042
+	SYS_SENDTO                 = 5043
+	SYS_RECVFROM               = 5044
+	SYS_SENDMSG                = 5045
+	SYS_RECVMSG                = 5046
+	SYS_SHUTDOWN               = 5047
+	SYS_BIND                   = 5048
+	SYS_LISTEN                 = 5049
+	SYS_GETSOCKNAME            = 5050
+	SYS_GETPEERNAME            = 5051
+	SYS_SOCKETPAIR             = 5052
+	SYS_SETSOCKOPT             = 5053
+	SYS_GETSOCKOPT             = 5054
+	SYS_CLONE                  = 5055
+	SYS_FORK                   = 5056
+	SYS_EXECVE                 = 5057
+	SYS_EXIT                   = 5058
+	SYS_WAIT4                  = 5059
+	SYS_KILL                   = 5060
+	SYS_UNAME                  = 5061
+	SYS_SEMGET                 = 5062
+	SYS_SEMOP                  = 5063
+	SYS_SEMCTL                 = 5064
+	SYS_SHMDT                  = 5065
+	SYS_MSGGET                 = 5066
+	SYS_MSGSND                 = 5067
+	SYS_MSGRCV                 = 5068
+	SYS_MSGCTL                 = 5069
+	SYS_FCNTL                  = 5070
+	SYS_FLOCK                  = 5071
+	SYS_FSYNC                  = 5072
+	SYS_FDATASYNC              = 5073
+	SYS_TRUNCATE               = 5074
+	SYS_FTRUNCATE              = 5075
+	SYS_GETDENTS               = 5076
+	SYS_GETCWD                 = 5077
+	SYS_CHDIR                  = 5078
+	SYS_FCHDIR                 = 5079
+	SYS_RENAME                 = 5080
+	SYS_MKDIR                  = 5081
+	SYS_RMDIR                  = 5082
+	SYS_CREAT                  = 5083
+	SYS_LINK                   = 5084
+	SYS_UNLINK                 = 5085
+	SYS_SYMLINK                = 5086
+	SYS_READLINK               = 5087
+	SYS_CHMOD                  = 5088
+	SYS_FCHMOD                 = 5089
+	SYS_CHOWN                  = 5090
+	SYS_FCHOWN                 = 5091
+	SYS_LCHOWN                 = 5092
+	SYS_UMASK                  = 5093
+	SYS_GETTIMEOFDAY           = 5094
+	SYS_GETRLIMIT              = 5095
+	SYS_GETRUSAGE              = 5096
+	SYS_SYSINFO                = 5097
+	SYS_TIMES                  = 5098
+	SYS_PTRACE                 = 5099
+	SYS_GETUID                 = 5100
+	SYS_SYSLOG                 = 5101
+	SYS_GETGID                 = 5102
+	SYS_SETUID                 = 5103
+	SYS_SETGID                 = 5104
+	SYS_GETEUID                = 5105
+	SYS_GETEGID                = 5106
+	SYS_SETPGID                = 5107
+	SYS_GETPPID                = 5108
+	SYS_GETPGRP                = 5109
+	SYS_SETSID                 = 5110
+	SYS_SETREUID               = 5111
+	SYS_SETREGID               = 5112
+	SYS_GETGROUPS              = 5113
+	SYS_SETGROUPS              = 5114
+	SYS_SETRESUID              = 5115
+	SYS_GETRESUID              = 5116
+	SYS_SETRESGID              = 5117
+	SYS_GETRESGID              = 5118
+	SYS_GETPGID                = 5119
+	SYS_SETFSUID               = 5120
+	SYS_SETFSGID               = 5121
+	SYS_GETSID                 = 5122
+	SYS_CAPGET                 = 5123
+	SYS_CAPSET                 = 5124
+	SYS_RT_SIGPENDING          = 5125
+	SYS_RT_SIGTIMEDWAIT        = 5126
+	SYS_RT_SIGQUEUEINFO        = 5127
+	SYS_RT_SIGSUSPEND          = 5128
+	SYS_SIGALTSTACK            = 5129
+	SYS_UTIME                  = 5130
+	SYS_MKNOD                  = 5131
+	SYS_PERSONALITY            = 5132
+	SYS_USTAT                  = 5133
+	SYS_STATFS                 = 5134
+	SYS_FSTATFS                = 5135
+	SYS_SYSFS                  = 5136
+	SYS_GETPRIORITY            = 5137
+	SYS_SETPRIORITY            = 5138
+	SYS_SCHED_SETPARAM         = 5139
+	SYS_SCHED_GETPARAM         = 5140
+	SYS_SCHED_SETSCHEDULER     = 5141
+	SYS_SCHED_GETSCHEDULER     = 5142
+	SYS_SCHED_GET_PRIORITY_MAX = 5143
+	SYS_SCHED_GET_PRIORITY_MIN = 5144
+	SYS_SCHED_RR_GET_INTERVAL  = 5145
+	SYS_MLOCK                  = 5146
+	SYS_MUNLOCK                = 5147
+	SYS_MLOCKALL               = 5148
+	SYS_MUNLOCKALL             = 5149
+	SYS_VHANGUP                = 5150
+	SYS_PIVOT_ROOT             = 5151
+	SYS__SYSCTL                = 5152
+	SYS_PRCTL                  = 5153
+	SYS_ADJTIMEX               = 5154
+	SYS_SETRLIMIT              = 5155
+	SYS_CHROOT                 = 5156
+	SYS_SYNC                   = 5157
+	SYS_ACCT                   = 5158
+	SYS_SETTIMEOFDAY           = 5159
+	SYS_MOUNT                  = 5160
+	SYS_UMOUNT2                = 5161
+	SYS_SWAPON                 = 5162
+	SYS_SWAPOFF                = 5163
+	SYS_REBOOT                 = 5164
+	SYS_SETHOSTNAME            = 5165
+	SYS_SETDOMAINNAME          = 5166
+	SYS_CREATE_MODULE          = 5167
+	SYS_INIT_MODULE            = 5168
+	SYS_DELETE_MODULE          = 5169
+	SYS_GET_KERNEL_SYMS        = 5170
+	SYS_QUERY_MODULE           = 5171
+	SYS_QUOTACTL               = 5172
+	SYS_NFSSERVCTL             = 5173
+	SYS_GETPMSG                = 5174
+	SYS_PUTPMSG                = 5175
+	SYS_AFS_SYSCALL            = 5176
+	SYS_RESERVED177            = 5177
+	SYS_GETTID                 = 5178
+	SYS_READAHEAD              = 5179
+	SYS_SETXATTR               = 5180
+	SYS_LSETXATTR              = 5181
+	SYS_FSETXATTR              = 5182
+	SYS_GETXATTR               = 5183
+	SYS_LGETXATTR              = 5184
+	SYS_FGETXATTR              = 5185
+	SYS_LISTXATTR              = 5186
+	SYS_LLISTXATTR             = 5187
+	SYS_FLISTXATTR             = 5188
+	SYS_REMOVEXATTR            = 5189
+	SYS_LREMOVEXATTR           = 5190
+	SYS_FREMOVEXATTR           = 5191
+	SYS_TKILL                  = 5192
+	SYS_RESERVED193            = 5193
+	SYS_FUTEX                  = 5194
+	SYS_SCHED_SETAFFINITY      = 5195
+	SYS_SCHED_GETAFFINITY      = 5196
+	SYS_CACHEFLUSH             = 5197
+	SYS_CACHECTL               = 5198
+	SYS_SYSMIPS                = 5199
+	SYS_IO_SETUP               = 5200
+	SYS_IO_DESTROY             = 5201
+	SYS_IO_GETEVENTS           = 5202
+	SYS_IO_SUBMIT              = 5203
+	SYS_IO_CANCEL              = 5204
+	SYS_EXIT_GROUP             = 5205
+	SYS_LOOKUP_DCOOKIE         = 5206
+	SYS_EPOLL_CREATE           = 5207
+	SYS_EPOLL_CTL              = 5208
+	SYS_EPOLL_WAIT             = 5209
+	SYS_REMAP_FILE_PAGES       = 5210
+	SYS_RT_SIGRETURN           = 5211
+	SYS_SET_TID_ADDRESS        = 5212
+	SYS_RESTART_SYSCALL        = 5213
+	SYS_SEMTIMEDOP             = 5214
+	SYS_FADVISE64              = 5215
+	SYS_TIMER_CREATE           = 5216
+	SYS_TIMER_SETTIME          = 5217
+	SYS_TIMER_GETTIME          = 5218
+	SYS_TIMER_GETOVERRUN       = 5219
+	SYS_TIMER_DELETE           = 5220
+	SYS_CLOCK_SETTIME          = 5221
+	SYS_CLOCK_GETTIME          = 5222
+	SYS_CLOCK_GETRES           = 5223
+	SYS_CLOCK_NANOSLEEP        = 5224
+	SYS_TGKILL                 = 5225
+	SYS_UTIMES                 = 5226
+	SYS_MBIND                  = 5227
+	SYS_GET_MEMPOLICY          = 5228
+	SYS_SET_MEMPOLICY          = 5229
+	SYS_MQ_OPEN                = 5230
+	SYS_MQ_UNLINK              = 5231
+	SYS_MQ_TIMEDSEND           = 5232
+	SYS_MQ_TIMEDRECEIVE        = 5233
+	SYS_MQ_NOTIFY              = 5234
+	SYS_MQ_GETSETATTR          = 5235
+	SYS_VSERVER                = 5236
+	SYS_WAITID                 = 5237
+	SYS_ADD_KEY                = 5239
+	SYS_REQUEST_KEY            = 5240
+	SYS_KEYCTL                 = 5241
+	SYS_SET_THREAD_AREA        = 5242
+	SYS_INOTIFY_INIT           = 5243
+	SYS_INOTIFY_ADD_WATCH      = 5244
+	SYS_INOTIFY_RM_WATCH       = 5245
+	SYS_MIGRATE_PAGES          = 5246
+	SYS_OPENAT                 = 5247
+	SYS_MKDIRAT                = 5248
+	SYS_MKNODAT                = 5249
+	SYS_FCHOWNAT               = 5250
+	SYS_FUTIMESAT              = 5251
+	SYS_NEWFSTATAT             = 5252
+	SYS_UNLINKAT               = 5253
+	SYS_RENAMEAT               = 5254
+	SYS_LINKAT                 = 5255
+	SYS_SYMLINKAT              = 5256
+	SYS_READLINKAT             = 5257
+	SYS_FCHMODAT               = 5258
+	SYS_FACCESSAT              = 5259
+	SYS_PSELECT6               = 5260
+	SYS_PPOLL                  = 5261
+	SYS_UNSHARE                = 5262
+	SYS_SPLICE                 = 5263
+	SYS_SYNC_FILE_RANGE        = 5264
+	SYS_TEE                    = 5265
+	SYS_VMSPLICE               = 5266
+	SYS_MOVE_PAGES             = 5267
+	SYS_SET_ROBUST_LIST        = 5268
+	SYS_GET_ROBUST_LIST        = 5269
+	SYS_KEXEC_LOAD             = 5270
+	SYS_GETCPU                 = 5271
+	SYS_EPOLL_PWAIT            = 5272
+	SYS_IOPRIO_SET             = 5273
+	SYS_IOPRIO_GET             = 5274
+	SYS_UTIMENSAT              = 5275
+	SYS_SIGNALFD               = 5276
+	SYS_TIMERFD                = 5277
+	SYS_EVENTFD                = 5278
+	SYS_FALLOCATE              = 5279
+	SYS_TIMERFD_CREATE         = 5280
+	SYS_TIMERFD_GETTIME        = 5281
+	SYS_TIMERFD_SETTIME        = 5282
+	SYS_SIGNALFD4              = 5283
+	SYS_EVENTFD2               = 5284
+	SYS_EPOLL_CREATE1          = 5285
+	SYS_DUP3                   = 5286
+	SYS_PIPE2                  = 5287
+	SYS_INOTIFY_INIT1          = 5288
+	SYS_PREADV                 = 5289
+	SYS_PWRITEV                = 5290
+	SYS_RT_TGSIGQUEUEINFO      = 5291
+	SYS_PERF_EVENT_OPEN        = 5292
+	SYS_ACCEPT4                = 5293
+	SYS_RECVMMSG               = 5294
+	SYS_FANOTIFY_INIT          = 5295
+	SYS_FANOTIFY_MARK          = 5296
+	SYS_PRLIMIT64              = 5297
+	SYS_NAME_TO_HANDLE_AT      = 5298
+	SYS_OPEN_BY_HANDLE_AT      = 5299
+	SYS_CLOCK_ADJTIME          = 5300
+	SYS_SYNCFS                 = 5301
+	SYS_SENDMMSG               = 5302
+	SYS_SETNS                  = 5303
+	SYS_PROCESS_VM_READV       = 5304
+	SYS_PROCESS_VM_WRITEV      = 5305
+	SYS_KCMP                   = 5306
+	SYS_FINIT_MODULE           = 5307
+	SYS_GETDENTS64             = 5308
+	SYS_SCHED_SETATTR          = 5309
+	SYS_SCHED_GETATTR          = 5310
+	SYS_RENAMEAT2              = 5311
+	SYS_SECCOMP                = 5312
+	SYS_GETRANDOM              = 5313
+	SYS_MEMFD_CREATE           = 5314
+	SYS_BPF                    = 5315
+	SYS_EXECVEAT               = 5316
+)
diff --git a/src/syscall/zsysnum_linux_mips64le.go b/src/syscall/zsysnum_linux_mips64le.go
new file mode 100644
index 0000000..a51ecfe
--- /dev/null
+++ b/src/syscall/zsysnum_linux_mips64le.go
@@ -0,0 +1,323 @@
+// mksysnum_linux.pl /usr/include/asm/unistd.h
+// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT
+
+package syscall
+
+const (
+	SYS_READ                   = 5000
+	SYS_WRITE                  = 5001
+	SYS_OPEN                   = 5002
+	SYS_CLOSE                  = 5003
+	SYS_STAT                   = 5004
+	SYS_FSTAT                  = 5005
+	SYS_LSTAT                  = 5006
+	SYS_POLL                   = 5007
+	SYS_LSEEK                  = 5008
+	SYS_MMAP                   = 5009
+	SYS_MPROTECT               = 5010
+	SYS_MUNMAP                 = 5011
+	SYS_BRK                    = 5012
+	SYS_RT_SIGACTION           = 5013
+	SYS_RT_SIGPROCMASK         = 5014
+	SYS_IOCTL                  = 5015
+	SYS_PREAD64                = 5016
+	SYS_PWRITE64               = 5017
+	SYS_READV                  = 5018
+	SYS_WRITEV                 = 5019
+	SYS_ACCESS                 = 5020
+	SYS_PIPE                   = 5021
+	SYS__NEWSELECT             = 5022
+	SYS_SCHED_YIELD            = 5023
+	SYS_MREMAP                 = 5024
+	SYS_MSYNC                  = 5025
+	SYS_MINCORE                = 5026
+	SYS_MADVISE                = 5027
+	SYS_SHMGET                 = 5028
+	SYS_SHMAT                  = 5029
+	SYS_SHMCTL                 = 5030
+	SYS_DUP                    = 5031
+	SYS_DUP2                   = 5032
+	SYS_PAUSE                  = 5033
+	SYS_NANOSLEEP              = 5034
+	SYS_GETITIMER              = 5035
+	SYS_SETITIMER              = 5036
+	SYS_ALARM                  = 5037
+	SYS_GETPID                 = 5038
+	SYS_SENDFILE               = 5039
+	SYS_SOCKET                 = 5040
+	SYS_CONNECT                = 5041
+	SYS_ACCEPT                 = 5042
+	SYS_SENDTO                 = 5043
+	SYS_RECVFROM               = 5044
+	SYS_SENDMSG                = 5045
+	SYS_RECVMSG                = 5046
+	SYS_SHUTDOWN               = 5047
+	SYS_BIND                   = 5048
+	SYS_LISTEN                 = 5049
+	SYS_GETSOCKNAME            = 5050
+	SYS_GETPEERNAME            = 5051
+	SYS_SOCKETPAIR             = 5052
+	SYS_SETSOCKOPT             = 5053
+	SYS_GETSOCKOPT             = 5054
+	SYS_CLONE                  = 5055
+	SYS_FORK                   = 5056
+	SYS_EXECVE                 = 5057
+	SYS_EXIT                   = 5058
+	SYS_WAIT4                  = 5059
+	SYS_KILL                   = 5060
+	SYS_UNAME                  = 5061
+	SYS_SEMGET                 = 5062
+	SYS_SEMOP                  = 5063
+	SYS_SEMCTL                 = 5064
+	SYS_SHMDT                  = 5065
+	SYS_MSGGET                 = 5066
+	SYS_MSGSND                 = 5067
+	SYS_MSGRCV                 = 5068
+	SYS_MSGCTL                 = 5069
+	SYS_FCNTL                  = 5070
+	SYS_FLOCK                  = 5071
+	SYS_FSYNC                  = 5072
+	SYS_FDATASYNC              = 5073
+	SYS_TRUNCATE               = 5074
+	SYS_FTRUNCATE              = 5075
+	SYS_GETDENTS               = 5076
+	SYS_GETCWD                 = 5077
+	SYS_CHDIR                  = 5078
+	SYS_FCHDIR                 = 5079
+	SYS_RENAME                 = 5080
+	SYS_MKDIR                  = 5081
+	SYS_RMDIR                  = 5082
+	SYS_CREAT                  = 5083
+	SYS_LINK                   = 5084
+	SYS_UNLINK                 = 5085
+	SYS_SYMLINK                = 5086
+	SYS_READLINK               = 5087
+	SYS_CHMOD                  = 5088
+	SYS_FCHMOD                 = 5089
+	SYS_CHOWN                  = 5090
+	SYS_FCHOWN                 = 5091
+	SYS_LCHOWN                 = 5092
+	SYS_UMASK                  = 5093
+	SYS_GETTIMEOFDAY           = 5094
+	SYS_GETRLIMIT              = 5095
+	SYS_GETRUSAGE              = 5096
+	SYS_SYSINFO                = 5097
+	SYS_TIMES                  = 5098
+	SYS_PTRACE                 = 5099
+	SYS_GETUID                 = 5100
+	SYS_SYSLOG                 = 5101
+	SYS_GETGID                 = 5102
+	SYS_SETUID                 = 5103
+	SYS_SETGID                 = 5104
+	SYS_GETEUID                = 5105
+	SYS_GETEGID                = 5106
+	SYS_SETPGID                = 5107
+	SYS_GETPPID                = 5108
+	SYS_GETPGRP                = 5109
+	SYS_SETSID                 = 5110
+	SYS_SETREUID               = 5111
+	SYS_SETREGID               = 5112
+	SYS_GETGROUPS              = 5113
+	SYS_SETGROUPS              = 5114
+	SYS_SETRESUID              = 5115
+	SYS_GETRESUID              = 5116
+	SYS_SETRESGID              = 5117
+	SYS_GETRESGID              = 5118
+	SYS_GETPGID                = 5119
+	SYS_SETFSUID               = 5120
+	SYS_SETFSGID               = 5121
+	SYS_GETSID                 = 5122
+	SYS_CAPGET                 = 5123
+	SYS_CAPSET                 = 5124
+	SYS_RT_SIGPENDING          = 5125
+	SYS_RT_SIGTIMEDWAIT        = 5126
+	SYS_RT_SIGQUEUEINFO        = 5127
+	SYS_RT_SIGSUSPEND          = 5128
+	SYS_SIGALTSTACK            = 5129
+	SYS_UTIME                  = 5130
+	SYS_MKNOD                  = 5131
+	SYS_PERSONALITY            = 5132
+	SYS_USTAT                  = 5133
+	SYS_STATFS                 = 5134
+	SYS_FSTATFS                = 5135
+	SYS_SYSFS                  = 5136
+	SYS_GETPRIORITY            = 5137
+	SYS_SETPRIORITY            = 5138
+	SYS_SCHED_SETPARAM         = 5139
+	SYS_SCHED_GETPARAM         = 5140
+	SYS_SCHED_SETSCHEDULER     = 5141
+	SYS_SCHED_GETSCHEDULER     = 5142
+	SYS_SCHED_GET_PRIORITY_MAX = 5143
+	SYS_SCHED_GET_PRIORITY_MIN = 5144
+	SYS_SCHED_RR_GET_INTERVAL  = 5145
+	SYS_MLOCK                  = 5146
+	SYS_MUNLOCK                = 5147
+	SYS_MLOCKALL               = 5148
+	SYS_MUNLOCKALL             = 5149
+	SYS_VHANGUP                = 5150
+	SYS_PIVOT_ROOT             = 5151
+	SYS__SYSCTL                = 5152
+	SYS_PRCTL                  = 5153
+	SYS_ADJTIMEX               = 5154
+	SYS_SETRLIMIT              = 5155
+	SYS_CHROOT                 = 5156
+	SYS_SYNC                   = 5157
+	SYS_ACCT                   = 5158
+	SYS_SETTIMEOFDAY           = 5159
+	SYS_MOUNT                  = 5160
+	SYS_UMOUNT2                = 5161
+	SYS_SWAPON                 = 5162
+	SYS_SWAPOFF                = 5163
+	SYS_REBOOT                 = 5164
+	SYS_SETHOSTNAME            = 5165
+	SYS_SETDOMAINNAME          = 5166
+	SYS_CREATE_MODULE          = 5167
+	SYS_INIT_MODULE            = 5168
+	SYS_DELETE_MODULE          = 5169
+	SYS_GET_KERNEL_SYMS        = 5170
+	SYS_QUERY_MODULE           = 5171
+	SYS_QUOTACTL               = 5172
+	SYS_NFSSERVCTL             = 5173
+	SYS_GETPMSG                = 5174
+	SYS_PUTPMSG                = 5175
+	SYS_AFS_SYSCALL            = 5176
+	SYS_RESERVED177            = 5177
+	SYS_GETTID                 = 5178
+	SYS_READAHEAD              = 5179
+	SYS_SETXATTR               = 5180
+	SYS_LSETXATTR              = 5181
+	SYS_FSETXATTR              = 5182
+	SYS_GETXATTR               = 5183
+	SYS_LGETXATTR              = 5184
+	SYS_FGETXATTR              = 5185
+	SYS_LISTXATTR              = 5186
+	SYS_LLISTXATTR             = 5187
+	SYS_FLISTXATTR             = 5188
+	SYS_REMOVEXATTR            = 5189
+	SYS_LREMOVEXATTR           = 5190
+	SYS_FREMOVEXATTR           = 5191
+	SYS_TKILL                  = 5192
+	SYS_RESERVED193            = 5193
+	SYS_FUTEX                  = 5194
+	SYS_SCHED_SETAFFINITY      = 5195
+	SYS_SCHED_GETAFFINITY      = 5196
+	SYS_CACHEFLUSH             = 5197
+	SYS_CACHECTL               = 5198
+	SYS_SYSMIPS                = 5199
+	SYS_IO_SETUP               = 5200
+	SYS_IO_DESTROY             = 5201
+	SYS_IO_GETEVENTS           = 5202
+	SYS_IO_SUBMIT              = 5203
+	SYS_IO_CANCEL              = 5204
+	SYS_EXIT_GROUP             = 5205
+	SYS_LOOKUP_DCOOKIE         = 5206
+	SYS_EPOLL_CREATE           = 5207
+	SYS_EPOLL_CTL              = 5208
+	SYS_EPOLL_WAIT             = 5209
+	SYS_REMAP_FILE_PAGES       = 5210
+	SYS_RT_SIGRETURN           = 5211
+	SYS_SET_TID_ADDRESS        = 5212
+	SYS_RESTART_SYSCALL        = 5213
+	SYS_SEMTIMEDOP             = 5214
+	SYS_FADVISE64              = 5215
+	SYS_TIMER_CREATE           = 5216
+	SYS_TIMER_SETTIME          = 5217
+	SYS_TIMER_GETTIME          = 5218
+	SYS_TIMER_GETOVERRUN       = 5219
+	SYS_TIMER_DELETE           = 5220
+	SYS_CLOCK_SETTIME          = 5221
+	SYS_CLOCK_GETTIME          = 5222
+	SYS_CLOCK_GETRES           = 5223
+	SYS_CLOCK_NANOSLEEP        = 5224
+	SYS_TGKILL                 = 5225
+	SYS_UTIMES                 = 5226
+	SYS_MBIND                  = 5227
+	SYS_GET_MEMPOLICY          = 5228
+	SYS_SET_MEMPOLICY          = 5229
+	SYS_MQ_OPEN                = 5230
+	SYS_MQ_UNLINK              = 5231
+	SYS_MQ_TIMEDSEND           = 5232
+	SYS_MQ_TIMEDRECEIVE        = 5233
+	SYS_MQ_NOTIFY              = 5234
+	SYS_MQ_GETSETATTR          = 5235
+	SYS_VSERVER                = 5236
+	SYS_WAITID                 = 5237
+	SYS_ADD_KEY                = 5239
+	SYS_REQUEST_KEY            = 5240
+	SYS_KEYCTL                 = 5241
+	SYS_SET_THREAD_AREA        = 5242
+	SYS_INOTIFY_INIT           = 5243
+	SYS_INOTIFY_ADD_WATCH      = 5244
+	SYS_INOTIFY_RM_WATCH       = 5245
+	SYS_MIGRATE_PAGES          = 5246
+	SYS_OPENAT                 = 5247
+	SYS_MKDIRAT                = 5248
+	SYS_MKNODAT                = 5249
+	SYS_FCHOWNAT               = 5250
+	SYS_FUTIMESAT              = 5251
+	SYS_NEWFSTATAT             = 5252
+	SYS_UNLINKAT               = 5253
+	SYS_RENAMEAT               = 5254
+	SYS_LINKAT                 = 5255
+	SYS_SYMLINKAT              = 5256
+	SYS_READLINKAT             = 5257
+	SYS_FCHMODAT               = 5258
+	SYS_FACCESSAT              = 5259
+	SYS_PSELECT6               = 5260
+	SYS_PPOLL                  = 5261
+	SYS_UNSHARE                = 5262
+	SYS_SPLICE                 = 5263
+	SYS_SYNC_FILE_RANGE        = 5264
+	SYS_TEE                    = 5265
+	SYS_VMSPLICE               = 5266
+	SYS_MOVE_PAGES             = 5267
+	SYS_SET_ROBUST_LIST        = 5268
+	SYS_GET_ROBUST_LIST        = 5269
+	SYS_KEXEC_LOAD             = 5270
+	SYS_GETCPU                 = 5271
+	SYS_EPOLL_PWAIT            = 5272
+	SYS_IOPRIO_SET             = 5273
+	SYS_IOPRIO_GET             = 5274
+	SYS_UTIMENSAT              = 5275
+	SYS_SIGNALFD               = 5276
+	SYS_TIMERFD                = 5277
+	SYS_EVENTFD                = 5278
+	SYS_FALLOCATE              = 5279
+	SYS_TIMERFD_CREATE         = 5280
+	SYS_TIMERFD_GETTIME        = 5281
+	SYS_TIMERFD_SETTIME        = 5282
+	SYS_SIGNALFD4              = 5283
+	SYS_EVENTFD2               = 5284
+	SYS_EPOLL_CREATE1          = 5285
+	SYS_DUP3                   = 5286
+	SYS_PIPE2                  = 5287
+	SYS_INOTIFY_INIT1          = 5288
+	SYS_PREADV                 = 5289
+	SYS_PWRITEV                = 5290
+	SYS_RT_TGSIGQUEUEINFO      = 5291
+	SYS_PERF_EVENT_OPEN        = 5292
+	SYS_ACCEPT4                = 5293
+	SYS_RECVMMSG               = 5294
+	SYS_FANOTIFY_INIT          = 5295
+	SYS_FANOTIFY_MARK          = 5296
+	SYS_PRLIMIT64              = 5297
+	SYS_NAME_TO_HANDLE_AT      = 5298
+	SYS_OPEN_BY_HANDLE_AT      = 5299
+	SYS_CLOCK_ADJTIME          = 5300
+	SYS_SYNCFS                 = 5301
+	SYS_SENDMMSG               = 5302
+	SYS_SETNS                  = 5303
+	SYS_PROCESS_VM_READV       = 5304
+	SYS_PROCESS_VM_WRITEV      = 5305
+	SYS_KCMP                   = 5306
+	SYS_FINIT_MODULE           = 5307
+	SYS_GETDENTS64             = 5308
+	SYS_SCHED_SETATTR          = 5309
+	SYS_SCHED_GETATTR          = 5310
+	SYS_RENAMEAT2              = 5311
+	SYS_SECCOMP                = 5312
+	SYS_GETRANDOM              = 5313
+	SYS_MEMFD_CREATE           = 5314
+	SYS_BPF                    = 5315
+	SYS_EXECVEAT               = 5316
+)
diff --git a/src/syscall/ztypes_linux_mips64.go b/src/syscall/ztypes_linux_mips64.go
new file mode 100644
index 0000000..9093086
--- /dev/null
+++ b/src/syscall/ztypes_linux_mips64.go
@@ -0,0 +1,602 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_linux.go
+
+package syscall
+
+const (
+	sizeofPtr      = 0x8
+	sizeofShort    = 0x2
+	sizeofInt      = 0x4
+	sizeofLong     = 0x8
+	sizeofLongLong = 0x8
+	PathMax        = 0x1000
+)
+
+type (
+	_C_short     int16
+	_C_int       int32
+	_C_long      int64
+	_C_long_long int64
+)
+
+type Timespec struct {
+	Sec  int64
+	Nsec int64
+}
+
+type Timeval struct {
+	Sec  int64
+	Usec int64
+}
+
+type Timex struct {
+	Modes     uint32
+	Pad_cgo_0 [4]byte
+	Offset    int64
+	Freq      int64
+	Maxerror  int64
+	Esterror  int64
+	Status    int32
+	Pad_cgo_1 [4]byte
+	Constant  int64
+	Precision int64
+	Tolerance int64
+	Time      Timeval
+	Tick      int64
+	Ppsfreq   int64
+	Jitter    int64
+	Shift     int32
+	Pad_cgo_2 [4]byte
+	Stabil    int64
+	Jitcnt    int64
+	Calcnt    int64
+	Errcnt    int64
+	Stbcnt    int64
+	Tai       int32
+	Pad_cgo_3 [44]byte
+}
+
+type Time_t int64
+
+type Tms struct {
+	Utime  int64
+	Stime  int64
+	Cutime int64
+	Cstime int64
+}
+
+type Utimbuf struct {
+	Actime  int64
+	Modtime int64
+}
+
+type Rusage struct {
+	Utime    Timeval
+	Stime    Timeval
+	Maxrss   int64
+	Ixrss    int64
+	Idrss    int64
+	Isrss    int64
+	Minflt   int64
+	Majflt   int64
+	Nswap    int64
+	Inblock  int64
+	Oublock  int64
+	Msgsnd   int64
+	Msgrcv   int64
+	Nsignals int64
+	Nvcsw    int64
+	Nivcsw   int64
+}
+
+type Rlimit struct {
+	Cur uint64
+	Max uint64
+}
+
+type _Gid_t uint32
+
+type Stat_t struct {
+	Dev     uint32
+	Pad1    [3]int32
+	Ino     uint64
+	Mode    uint32
+	Nlink   uint32
+	Uid     uint32
+	Gid     uint32
+	Rdev    uint32
+	Pad2    [3]uint32
+	Size    int64
+	Atim    Timespec
+	Mtim    Timespec
+	Ctim    Timespec
+	Blksize uint32
+	Pad4    uint32
+	Blocks  int64
+}
+
+type Statfs_t struct {
+	Type    int64
+	Bsize   int64
+	Frsize  int64
+	Blocks  uint64
+	Bfree   uint64
+	Files   uint64
+	Ffree   uint64
+	Bavail  uint64
+	Fsid    Fsid
+	Namelen int64
+	Flags   int64
+	Spare   [5]int64
+}
+
+// Note: on mips64, we're using the getdents syscall,
+// so the Dirent struct is different.
+
+type Dirent struct {
+	Ino       uint64
+	Off       int64
+	Reclen    uint16
+	Name      [256]int8
+	Type      uint8
+	Pad_cgo_0 [5]byte
+}
+
+type Fsid struct {
+	X__val [2]int32
+}
+
+type Flock_t struct {
+	Type      int16
+	Whence    int16
+	Pad_cgo_0 [4]byte
+	Start     int64
+	Len       int64
+	Pid       int32
+	Pad_cgo_1 [4]byte
+}
+
+type RawSockaddrInet4 struct {
+	Family uint16
+	Port   uint16
+	Addr   [4]byte /* in_addr */
+	Zero   [8]uint8
+}
+
+type RawSockaddrInet6 struct {
+	Family   uint16
+	Port     uint16
+	Flowinfo uint32
+	Addr     [16]byte /* in6_addr */
+	Scope_id uint32
+}
+
+type RawSockaddrUnix struct {
+	Family uint16
+	Path   [108]int8
+}
+
+type RawSockaddrLinklayer struct {
+	Family   uint16
+	Protocol uint16
+	Ifindex  int32
+	Hatype   uint16
+	Pkttype  uint8
+	Halen    uint8
+	Addr     [8]uint8
+}
+
+type RawSockaddrNetlink struct {
+	Family uint16
+	Pad    uint16
+	Pid    uint32
+	Groups uint32
+}
+
+type RawSockaddr struct {
+	Family uint16
+	Data   [14]int8
+}
+
+type RawSockaddrAny struct {
+	Addr RawSockaddr
+	Pad  [96]int8
+}
+
+type _Socklen uint32
+
+type Linger struct {
+	Onoff  int32
+	Linger int32
+}
+
+type Iovec struct {
+	Base *byte
+	Len  uint64
+}
+
+type IPMreq struct {
+	Multiaddr [4]byte /* in_addr */
+	Interface [4]byte /* in_addr */
+}
+
+type IPMreqn struct {
+	Multiaddr [4]byte /* in_addr */
+	Address   [4]byte /* in_addr */
+	Ifindex   int32
+}
+
+type IPv6Mreq struct {
+	Multiaddr [16]byte /* in6_addr */
+	Interface uint32
+}
+
+type Msghdr struct {
+	Name       *byte
+	Namelen    uint32
+	Pad_cgo_0  [4]byte
+	Iov        *Iovec
+	Iovlen     uint64
+	Control    *byte
+	Controllen uint64
+	Flags      int32
+	Pad_cgo_1  [4]byte
+}
+
+type Cmsghdr struct {
+	Len          uint64
+	Level        int32
+	Type         int32
+	X__cmsg_data [0]uint8
+}
+
+type Inet4Pktinfo struct {
+	Ifindex  int32
+	Spec_dst [4]byte /* in_addr */
+	Addr     [4]byte /* in_addr */
+}
+
+type Inet6Pktinfo struct {
+	Addr    [16]byte /* in6_addr */
+	Ifindex uint32
+}
+
+type IPv6MTUInfo struct {
+	Addr RawSockaddrInet6
+	Mtu  uint32
+}
+
+type ICMPv6Filter struct {
+	Data [8]uint32
+}
+
+type Ucred struct {
+	Pid int32
+	Uid uint32
+	Gid uint32
+}
+
+type TCPInfo struct {
+	State          uint8
+	Ca_state       uint8
+	Retransmits    uint8
+	Probes         uint8
+	Backoff        uint8
+	Options        uint8
+	Pad_cgo_0      [2]byte
+	Rto            uint32
+	Ato            uint32
+	Snd_mss        uint32
+	Rcv_mss        uint32
+	Unacked        uint32
+	Sacked         uint32
+	Lost           uint32
+	Retrans        uint32
+	Fackets        uint32
+	Last_data_sent uint32
+	Last_ack_sent  uint32
+	Last_data_recv uint32
+	Last_ack_recv  uint32
+	Pmtu           uint32
+	Rcv_ssthresh   uint32
+	Rtt            uint32
+	Rttvar         uint32
+	Snd_ssthresh   uint32
+	Snd_cwnd       uint32
+	Advmss         uint32
+	Reordering     uint32
+	Rcv_rtt        uint32
+	Rcv_space      uint32
+	Total_retrans  uint32
+}
+
+const (
+	SizeofSockaddrInet4     = 0x10
+	SizeofSockaddrInet6     = 0x1c
+	SizeofSockaddrAny       = 0x70
+	SizeofSockaddrUnix      = 0x6e
+	SizeofSockaddrLinklayer = 0x14
+	SizeofSockaddrNetlink   = 0xc
+	SizeofLinger            = 0x8
+	SizeofIPMreq            = 0x8
+	SizeofIPMreqn           = 0xc
+	SizeofIPv6Mreq          = 0x14
+	SizeofMsghdr            = 0x38
+	SizeofCmsghdr           = 0x10
+	SizeofInet4Pktinfo      = 0xc
+	SizeofInet6Pktinfo      = 0x14
+	SizeofIPv6MTUInfo       = 0x20
+	SizeofICMPv6Filter      = 0x20
+	SizeofUcred             = 0xc
+	SizeofTCPInfo           = 0x68
+)
+
+const (
+	IFA_UNSPEC          = 0x0
+	IFA_ADDRESS         = 0x1
+	IFA_LOCAL           = 0x2
+	IFA_LABEL           = 0x3
+	IFA_BROADCAST       = 0x4
+	IFA_ANYCAST         = 0x5
+	IFA_CACHEINFO       = 0x6
+	IFA_MULTICAST       = 0x7
+	IFLA_UNSPEC         = 0x0
+	IFLA_ADDRESS        = 0x1
+	IFLA_BROADCAST      = 0x2
+	IFLA_IFNAME         = 0x3
+	IFLA_MTU            = 0x4
+	IFLA_LINK           = 0x5
+	IFLA_QDISC          = 0x6
+	IFLA_STATS          = 0x7
+	IFLA_COST           = 0x8
+	IFLA_PRIORITY       = 0x9
+	IFLA_MASTER         = 0xa
+	IFLA_WIRELESS       = 0xb
+	IFLA_PROTINFO       = 0xc
+	IFLA_TXQLEN         = 0xd
+	IFLA_MAP            = 0xe
+	IFLA_WEIGHT         = 0xf
+	IFLA_OPERSTATE      = 0x10
+	IFLA_LINKMODE       = 0x11
+	IFLA_LINKINFO       = 0x12
+	IFLA_NET_NS_PID     = 0x13
+	IFLA_IFALIAS        = 0x14
+	IFLA_MAX            = 0x22
+	RT_SCOPE_UNIVERSE   = 0x0
+	RT_SCOPE_SITE       = 0xc8
+	RT_SCOPE_LINK       = 0xfd
+	RT_SCOPE_HOST       = 0xfe
+	RT_SCOPE_NOWHERE    = 0xff
+	RT_TABLE_UNSPEC     = 0x0
+	RT_TABLE_COMPAT     = 0xfc
+	RT_TABLE_DEFAULT    = 0xfd
+	RT_TABLE_MAIN       = 0xfe
+	RT_TABLE_LOCAL      = 0xff
+	RT_TABLE_MAX        = 0xffffffff
+	RTA_UNSPEC          = 0x0
+	RTA_DST             = 0x1
+	RTA_SRC             = 0x2
+	RTA_IIF             = 0x3
+	RTA_OIF             = 0x4
+	RTA_GATEWAY         = 0x5
+	RTA_PRIORITY        = 0x6
+	RTA_PREFSRC         = 0x7
+	RTA_METRICS         = 0x8
+	RTA_MULTIPATH       = 0x9
+	RTA_FLOW            = 0xb
+	RTA_CACHEINFO       = 0xc
+	RTA_TABLE           = 0xf
+	RTN_UNSPEC          = 0x0
+	RTN_UNICAST         = 0x1
+	RTN_LOCAL           = 0x2
+	RTN_BROADCAST       = 0x3
+	RTN_ANYCAST         = 0x4
+	RTN_MULTICAST       = 0x5
+	RTN_BLACKHOLE       = 0x6
+	RTN_UNREACHABLE     = 0x7
+	RTN_PROHIBIT        = 0x8
+	RTN_THROW           = 0x9
+	RTN_NAT             = 0xa
+	RTN_XRESOLVE        = 0xb
+	RTNLGRP_NONE        = 0x0
+	RTNLGRP_LINK        = 0x1
+	RTNLGRP_NOTIFY      = 0x2
+	RTNLGRP_NEIGH       = 0x3
+	RTNLGRP_TC          = 0x4
+	RTNLGRP_IPV4_IFADDR = 0x5
+	RTNLGRP_IPV4_MROUTE = 0x6
+	RTNLGRP_IPV4_ROUTE  = 0x7
+	RTNLGRP_IPV4_RULE   = 0x8
+	RTNLGRP_IPV6_IFADDR = 0x9
+	RTNLGRP_IPV6_MROUTE = 0xa
+	RTNLGRP_IPV6_ROUTE  = 0xb
+	RTNLGRP_IPV6_IFINFO = 0xc
+	RTNLGRP_IPV6_PREFIX = 0x12
+	RTNLGRP_IPV6_RULE   = 0x13
+	RTNLGRP_ND_USEROPT  = 0x14
+	SizeofNlMsghdr      = 0x10
+	SizeofNlMsgerr      = 0x14
+	SizeofRtGenmsg      = 0x1
+	SizeofNlAttr        = 0x4
+	SizeofRtAttr        = 0x4
+	SizeofIfInfomsg     = 0x10
+	SizeofIfAddrmsg     = 0x8
+	SizeofRtMsg         = 0xc
+	SizeofRtNexthop     = 0x8
+)
+
+type NlMsghdr struct {
+	Len   uint32
+	Type  uint16
+	Flags uint16
+	Seq   uint32
+	Pid   uint32
+}
+
+type NlMsgerr struct {
+	Error int32
+	Msg   NlMsghdr
+}
+
+type RtGenmsg struct {
+	Family uint8
+}
+
+type NlAttr struct {
+	Len  uint16
+	Type uint16
+}
+
+type RtAttr struct {
+	Len  uint16
+	Type uint16
+}
+
+type IfInfomsg struct {
+	Family     uint8
+	X__ifi_pad uint8
+	Type       uint16
+	Index      int32
+	Flags      uint32
+	Change     uint32
+}
+
+type IfAddrmsg struct {
+	Family    uint8
+	Prefixlen uint8
+	Flags     uint8
+	Scope     uint8
+	Index     uint32
+}
+
+type RtMsg struct {
+	Family   uint8
+	Dst_len  uint8
+	Src_len  uint8
+	Tos      uint8
+	Table    uint8
+	Protocol uint8
+	Scope    uint8
+	Type     uint8
+	Flags    uint32
+}
+
+type RtNexthop struct {
+	Len     uint16
+	Flags   uint8
+	Hops    uint8
+	Ifindex int32
+}
+
+const (
+	SizeofSockFilter = 0x8
+	SizeofSockFprog  = 0x10
+)
+
+type SockFilter struct {
+	Code uint16
+	Jt   uint8
+	Jf   uint8
+	K    uint32
+}
+
+type SockFprog struct {
+	Len       uint16
+	Pad_cgo_0 [6]byte
+	Filter    *SockFilter
+}
+
+type InotifyEvent struct {
+	Wd     int32
+	Mask   uint32
+	Cookie uint32
+	Len    uint32
+	Name   [0]int8
+}
+
+const SizeofInotifyEvent = 0x10
+
+type PtraceRegs struct {
+	Regs        [102]uint64
+	U_tsize     uint64
+	U_dsize     uint64
+	U_ssize     uint64
+	Start_code  uint64
+	Start_data  uint64
+	Start_stack uint64
+	Signal      int64
+	U_ar0       uint64
+	Magic       uint64
+	U_comm      [32]int8
+}
+
+type FdSet struct {
+	Bits [16]int64
+}
+
+type Sysinfo_t struct {
+	Uptime    int64
+	Loads     [3]uint64
+	Totalram  uint64
+	Freeram   uint64
+	Sharedram uint64
+	Bufferram uint64
+	Totalswap uint64
+	Freeswap  uint64
+	Procs     uint16
+	Pad       uint16
+	Pad_cgo_0 [4]byte
+	Totalhigh uint64
+	Freehigh  uint64
+	Unit      uint32
+	X_f       [0]int8
+	Pad_cgo_1 [4]byte
+}
+
+type Utsname struct {
+	Sysname    [65]int8
+	Nodename   [65]int8
+	Release    [65]int8
+	Version    [65]int8
+	Machine    [65]int8
+	Domainname [65]int8
+}
+
+type Ustat_t struct {
+	Tfree     int32
+	Pad_cgo_0 [4]byte
+	Tinode    uint64
+	Fname     [6]int8
+	Fpack     [6]int8
+	Pad_cgo_1 [4]byte
+}
+
+type EpollEvent struct {
+	Events uint32
+	Fd     int32
+	Pad    int32
+}
+
+const (
+	_AT_FDCWD            = -0x64
+	_AT_REMOVEDIR        = 0x200
+	_AT_SYMLINK_NOFOLLOW = 0x100
+)
+
+type Termios struct {
+	Iflag     uint32
+	Oflag     uint32
+	Cflag     uint32
+	Lflag     uint32
+	Line      uint8
+	Cc        [32]uint8
+	Pad_cgo_0 [3]byte
+}
+
+const (
+	IUCLC  = 0x200
+	OLCUC  = 0x2
+	TCGETS = 0x540d
+	TCSETS = 0x540e
+	XCASE  = 0x4
+)
diff --git a/src/syscall/ztypes_linux_mips64le.go b/src/syscall/ztypes_linux_mips64le.go
new file mode 100644
index 0000000..9093086
--- /dev/null
+++ b/src/syscall/ztypes_linux_mips64le.go
@@ -0,0 +1,602 @@
+// Created by cgo -godefs - DO NOT EDIT
+// cgo -godefs types_linux.go
+
+package syscall
+
+const (
+	sizeofPtr      = 0x8
+	sizeofShort    = 0x2
+	sizeofInt      = 0x4
+	sizeofLong     = 0x8
+	sizeofLongLong = 0x8
+	PathMax        = 0x1000
+)
+
+type (
+	_C_short     int16
+	_C_int       int32
+	_C_long      int64
+	_C_long_long int64
+)
+
+type Timespec struct {
+	Sec  int64
+	Nsec int64
+}
+
+type Timeval struct {
+	Sec  int64
+	Usec int64
+}
+
+type Timex struct {
+	Modes     uint32
+	Pad_cgo_0 [4]byte
+	Offset    int64
+	Freq      int64
+	Maxerror  int64
+	Esterror  int64
+	Status    int32
+	Pad_cgo_1 [4]byte
+	Constant  int64
+	Precision int64
+	Tolerance int64
+	Time      Timeval
+	Tick      int64
+	Ppsfreq   int64
+	Jitter    int64
+	Shift     int32
+	Pad_cgo_2 [4]byte
+	Stabil    int64
+	Jitcnt    int64
+	Calcnt    int64
+	Errcnt    int64
+	Stbcnt    int64
+	Tai       int32
+	Pad_cgo_3 [44]byte
+}
+
+type Time_t int64
+
+type Tms struct {
+	Utime  int64
+	Stime  int64
+	Cutime int64
+	Cstime int64
+}
+
+type Utimbuf struct {
+	Actime  int64
+	Modtime int64
+}
+
+type Rusage struct {
+	Utime    Timeval
+	Stime    Timeval
+	Maxrss   int64
+	Ixrss    int64
+	Idrss    int64
+	Isrss    int64
+	Minflt   int64
+	Majflt   int64
+	Nswap    int64
+	Inblock  int64
+	Oublock  int64
+	Msgsnd   int64
+	Msgrcv   int64
+	Nsignals int64
+	Nvcsw    int64
+	Nivcsw   int64
+}
+
+type Rlimit struct {
+	Cur uint64
+	Max uint64
+}
+
+type _Gid_t uint32
+
+type Stat_t struct {
+	Dev     uint32
+	Pad1    [3]int32
+	Ino     uint64
+	Mode    uint32
+	Nlink   uint32
+	Uid     uint32
+	Gid     uint32
+	Rdev    uint32
+	Pad2    [3]uint32
+	Size    int64
+	Atim    Timespec
+	Mtim    Timespec
+	Ctim    Timespec
+	Blksize uint32
+	Pad4    uint32
+	Blocks  int64
+}
+
+type Statfs_t struct {
+	Type    int64
+	Bsize   int64
+	Frsize  int64
+	Blocks  uint64
+	Bfree   uint64
+	Files   uint64
+	Ffree   uint64
+	Bavail  uint64
+	Fsid    Fsid
+	Namelen int64
+	Flags   int64
+	Spare   [5]int64
+}
+
+// Note: on mips64, we're using the getdents syscall,
+// so the Dirent struct is different.
+
+type Dirent struct {
+	Ino       uint64
+	Off       int64
+	Reclen    uint16
+	Name      [256]int8
+	Type      uint8
+	Pad_cgo_0 [5]byte
+}
+
+type Fsid struct {
+	X__val [2]int32
+}
+
+type Flock_t struct {
+	Type      int16
+	Whence    int16
+	Pad_cgo_0 [4]byte
+	Start     int64
+	Len       int64
+	Pid       int32
+	Pad_cgo_1 [4]byte
+}
+
+type RawSockaddrInet4 struct {
+	Family uint16
+	Port   uint16
+	Addr   [4]byte /* in_addr */
+	Zero   [8]uint8
+}
+
+type RawSockaddrInet6 struct {
+	Family   uint16
+	Port     uint16
+	Flowinfo uint32
+	Addr     [16]byte /* in6_addr */
+	Scope_id uint32
+}
+
+type RawSockaddrUnix struct {
+	Family uint16
+	Path   [108]int8
+}
+
+type RawSockaddrLinklayer struct {
+	Family   uint16
+	Protocol uint16
+	Ifindex  int32
+	Hatype   uint16
+	Pkttype  uint8
+	Halen    uint8
+	Addr     [8]uint8
+}
+
+type RawSockaddrNetlink struct {
+	Family uint16
+	Pad    uint16
+	Pid    uint32
+	Groups uint32
+}
+
+type RawSockaddr struct {
+	Family uint16
+	Data   [14]int8
+}
+
+type RawSockaddrAny struct {
+	Addr RawSockaddr
+	Pad  [96]int8
+}
+
+type _Socklen uint32
+
+type Linger struct {
+	Onoff  int32
+	Linger int32
+}
+
+type Iovec struct {
+	Base *byte
+	Len  uint64
+}
+
+type IPMreq struct {
+	Multiaddr [4]byte /* in_addr */
+	Interface [4]byte /* in_addr */
+}
+
+type IPMreqn struct {
+	Multiaddr [4]byte /* in_addr */
+	Address   [4]byte /* in_addr */
+	Ifindex   int32
+}
+
+type IPv6Mreq struct {
+	Multiaddr [16]byte /* in6_addr */
+	Interface uint32
+}
+
+type Msghdr struct {
+	Name       *byte
+	Namelen    uint32
+	Pad_cgo_0  [4]byte
+	Iov        *Iovec
+	Iovlen     uint64
+	Control    *byte
+	Controllen uint64
+	Flags      int32
+	Pad_cgo_1  [4]byte
+}
+
+type Cmsghdr struct {
+	Len          uint64
+	Level        int32
+	Type         int32
+	X__cmsg_data [0]uint8
+}
+
+type Inet4Pktinfo struct {
+	Ifindex  int32
+	Spec_dst [4]byte /* in_addr */
+	Addr     [4]byte /* in_addr */
+}
+
+type Inet6Pktinfo struct {
+	Addr    [16]byte /* in6_addr */
+	Ifindex uint32
+}
+
+type IPv6MTUInfo struct {
+	Addr RawSockaddrInet6
+	Mtu  uint32
+}
+
+type ICMPv6Filter struct {
+	Data [8]uint32
+}
+
+type Ucred struct {
+	Pid int32
+	Uid uint32
+	Gid uint32
+}
+
+type TCPInfo struct {
+	State          uint8
+	Ca_state       uint8
+	Retransmits    uint8
+	Probes         uint8
+	Backoff        uint8
+	Options        uint8
+	Pad_cgo_0      [2]byte
+	Rto            uint32
+	Ato            uint32
+	Snd_mss        uint32
+	Rcv_mss        uint32
+	Unacked        uint32
+	Sacked         uint32
+	Lost           uint32
+	Retrans        uint32
+	Fackets        uint32
+	Last_data_sent uint32
+	Last_ack_sent  uint32
+	Last_data_recv uint32
+	Last_ack_recv  uint32
+	Pmtu           uint32
+	Rcv_ssthresh   uint32
+	Rtt            uint32
+	Rttvar         uint32
+	Snd_ssthresh   uint32
+	Snd_cwnd       uint32
+	Advmss         uint32
+	Reordering     uint32
+	Rcv_rtt        uint32
+	Rcv_space      uint32
+	Total_retrans  uint32
+}
+
+const (
+	SizeofSockaddrInet4     = 0x10
+	SizeofSockaddrInet6     = 0x1c
+	SizeofSockaddrAny       = 0x70
+	SizeofSockaddrUnix      = 0x6e
+	SizeofSockaddrLinklayer = 0x14
+	SizeofSockaddrNetlink   = 0xc
+	SizeofLinger            = 0x8
+	SizeofIPMreq            = 0x8
+	SizeofIPMreqn           = 0xc
+	SizeofIPv6Mreq          = 0x14
+	SizeofMsghdr            = 0x38
+	SizeofCmsghdr           = 0x10
+	SizeofInet4Pktinfo      = 0xc
+	SizeofInet6Pktinfo      = 0x14
+	SizeofIPv6MTUInfo       = 0x20
+	SizeofICMPv6Filter      = 0x20
+	SizeofUcred             = 0xc
+	SizeofTCPInfo           = 0x68
+)
+
+const (
+	IFA_UNSPEC          = 0x0
+	IFA_ADDRESS         = 0x1
+	IFA_LOCAL           = 0x2
+	IFA_LABEL           = 0x3
+	IFA_BROADCAST       = 0x4
+	IFA_ANYCAST         = 0x5
+	IFA_CACHEINFO       = 0x6
+	IFA_MULTICAST       = 0x7
+	IFLA_UNSPEC         = 0x0
+	IFLA_ADDRESS        = 0x1
+	IFLA_BROADCAST      = 0x2
+	IFLA_IFNAME         = 0x3
+	IFLA_MTU            = 0x4
+	IFLA_LINK           = 0x5
+	IFLA_QDISC          = 0x6
+	IFLA_STATS          = 0x7
+	IFLA_COST           = 0x8
+	IFLA_PRIORITY       = 0x9
+	IFLA_MASTER         = 0xa
+	IFLA_WIRELESS       = 0xb
+	IFLA_PROTINFO       = 0xc
+	IFLA_TXQLEN         = 0xd
+	IFLA_MAP            = 0xe
+	IFLA_WEIGHT         = 0xf
+	IFLA_OPERSTATE      = 0x10
+	IFLA_LINKMODE       = 0x11
+	IFLA_LINKINFO       = 0x12
+	IFLA_NET_NS_PID     = 0x13
+	IFLA_IFALIAS        = 0x14
+	IFLA_MAX            = 0x22
+	RT_SCOPE_UNIVERSE   = 0x0
+	RT_SCOPE_SITE       = 0xc8
+	RT_SCOPE_LINK       = 0xfd
+	RT_SCOPE_HOST       = 0xfe
+	RT_SCOPE_NOWHERE    = 0xff
+	RT_TABLE_UNSPEC     = 0x0
+	RT_TABLE_COMPAT     = 0xfc
+	RT_TABLE_DEFAULT    = 0xfd
+	RT_TABLE_MAIN       = 0xfe
+	RT_TABLE_LOCAL      = 0xff
+	RT_TABLE_MAX        = 0xffffffff
+	RTA_UNSPEC          = 0x0
+	RTA_DST             = 0x1
+	RTA_SRC             = 0x2
+	RTA_IIF             = 0x3
+	RTA_OIF             = 0x4
+	RTA_GATEWAY         = 0x5
+	RTA_PRIORITY        = 0x6
+	RTA_PREFSRC         = 0x7
+	RTA_METRICS         = 0x8
+	RTA_MULTIPATH       = 0x9
+	RTA_FLOW            = 0xb
+	RTA_CACHEINFO       = 0xc
+	RTA_TABLE           = 0xf
+	RTN_UNSPEC          = 0x0
+	RTN_UNICAST         = 0x1
+	RTN_LOCAL           = 0x2
+	RTN_BROADCAST       = 0x3
+	RTN_ANYCAST         = 0x4
+	RTN_MULTICAST       = 0x5
+	RTN_BLACKHOLE       = 0x6
+	RTN_UNREACHABLE     = 0x7
+	RTN_PROHIBIT        = 0x8
+	RTN_THROW           = 0x9
+	RTN_NAT             = 0xa
+	RTN_XRESOLVE        = 0xb
+	RTNLGRP_NONE        = 0x0
+	RTNLGRP_LINK        = 0x1
+	RTNLGRP_NOTIFY      = 0x2
+	RTNLGRP_NEIGH       = 0x3
+	RTNLGRP_TC          = 0x4
+	RTNLGRP_IPV4_IFADDR = 0x5
+	RTNLGRP_IPV4_MROUTE = 0x6
+	RTNLGRP_IPV4_ROUTE  = 0x7
+	RTNLGRP_IPV4_RULE   = 0x8
+	RTNLGRP_IPV6_IFADDR = 0x9
+	RTNLGRP_IPV6_MROUTE = 0xa
+	RTNLGRP_IPV6_ROUTE  = 0xb
+	RTNLGRP_IPV6_IFINFO = 0xc
+	RTNLGRP_IPV6_PREFIX = 0x12
+	RTNLGRP_IPV6_RULE   = 0x13
+	RTNLGRP_ND_USEROPT  = 0x14
+	SizeofNlMsghdr      = 0x10
+	SizeofNlMsgerr      = 0x14
+	SizeofRtGenmsg      = 0x1
+	SizeofNlAttr        = 0x4
+	SizeofRtAttr        = 0x4
+	SizeofIfInfomsg     = 0x10
+	SizeofIfAddrmsg     = 0x8
+	SizeofRtMsg         = 0xc
+	SizeofRtNexthop     = 0x8
+)
+
+type NlMsghdr struct {
+	Len   uint32
+	Type  uint16
+	Flags uint16
+	Seq   uint32
+	Pid   uint32
+}
+
+type NlMsgerr struct {
+	Error int32
+	Msg   NlMsghdr
+}
+
+type RtGenmsg struct {
+	Family uint8
+}
+
+type NlAttr struct {
+	Len  uint16
+	Type uint16
+}
+
+type RtAttr struct {
+	Len  uint16
+	Type uint16
+}
+
+type IfInfomsg struct {
+	Family     uint8
+	X__ifi_pad uint8
+	Type       uint16
+	Index      int32
+	Flags      uint32
+	Change     uint32
+}
+
+type IfAddrmsg struct {
+	Family    uint8
+	Prefixlen uint8
+	Flags     uint8
+	Scope     uint8
+	Index     uint32
+}
+
+type RtMsg struct {
+	Family   uint8
+	Dst_len  uint8
+	Src_len  uint8
+	Tos      uint8
+	Table    uint8
+	Protocol uint8
+	Scope    uint8
+	Type     uint8
+	Flags    uint32
+}
+
+type RtNexthop struct {
+	Len     uint16
+	Flags   uint8
+	Hops    uint8
+	Ifindex int32
+}
+
+const (
+	SizeofSockFilter = 0x8
+	SizeofSockFprog  = 0x10
+)
+
+type SockFilter struct {
+	Code uint16
+	Jt   uint8
+	Jf   uint8
+	K    uint32
+}
+
+type SockFprog struct {
+	Len       uint16
+	Pad_cgo_0 [6]byte
+	Filter    *SockFilter
+}
+
+type InotifyEvent struct {
+	Wd     int32
+	Mask   uint32
+	Cookie uint32
+	Len    uint32
+	Name   [0]int8
+}
+
+const SizeofInotifyEvent = 0x10
+
+type PtraceRegs struct {
+	Regs        [102]uint64
+	U_tsize     uint64
+	U_dsize     uint64
+	U_ssize     uint64
+	Start_code  uint64
+	Start_data  uint64
+	Start_stack uint64
+	Signal      int64
+	U_ar0       uint64
+	Magic       uint64
+	U_comm      [32]int8
+}
+
+type FdSet struct {
+	Bits [16]int64
+}
+
+type Sysinfo_t struct {
+	Uptime    int64
+	Loads     [3]uint64
+	Totalram  uint64
+	Freeram   uint64
+	Sharedram uint64
+	Bufferram uint64
+	Totalswap uint64
+	Freeswap  uint64
+	Procs     uint16
+	Pad       uint16
+	Pad_cgo_0 [4]byte
+	Totalhigh uint64
+	Freehigh  uint64
+	Unit      uint32
+	X_f       [0]int8
+	Pad_cgo_1 [4]byte
+}
+
+type Utsname struct {
+	Sysname    [65]int8
+	Nodename   [65]int8
+	Release    [65]int8
+	Version    [65]int8
+	Machine    [65]int8
+	Domainname [65]int8
+}
+
+type Ustat_t struct {
+	Tfree     int32
+	Pad_cgo_0 [4]byte
+	Tinode    uint64
+	Fname     [6]int8
+	Fpack     [6]int8
+	Pad_cgo_1 [4]byte
+}
+
+type EpollEvent struct {
+	Events uint32
+	Fd     int32
+	Pad    int32
+}
+
+const (
+	_AT_FDCWD            = -0x64
+	_AT_REMOVEDIR        = 0x200
+	_AT_SYMLINK_NOFOLLOW = 0x100
+)
+
+type Termios struct {
+	Iflag     uint32
+	Oflag     uint32
+	Cflag     uint32
+	Lflag     uint32
+	Line      uint8
+	Cc        [32]uint8
+	Pad_cgo_0 [3]byte
+}
+
+const (
+	IUCLC  = 0x200
+	OLCUC  = 0x2
+	TCGETS = 0x540d
+	TCSETS = 0x540e
+	XCASE  = 0x4
+)
diff --git a/src/syscall/ztypes_solaris_amd64.go b/src/syscall/ztypes_solaris_amd64.go
index 2471519..4cf07ed 100644
--- a/src/syscall/ztypes_solaris_amd64.go
+++ b/src/syscall/ztypes_solaris_amd64.go
@@ -11,6 +11,7 @@ const (
 	sizeofInt      = 0x4
 	sizeofLong     = 0x8
 	sizeofLongLong = 0x8
+	PathMax        = 0x400
 )
 
 type (
diff --git a/src/testing/benchmark.go b/src/testing/benchmark.go
index 62e696d..85178c2 100644
--- a/src/testing/benchmark.go
+++ b/src/testing/benchmark.go
@@ -33,6 +33,17 @@ type InternalBenchmark struct {
 
 // B is a type passed to Benchmark functions to manage benchmark
 // timing and to specify the number of iterations to run.
+//
+// A benchmark ends when its Benchmark function returns or calls any of the methods
+// FailNow, Fatal, Fatalf, SkipNow, Skip, or Skipf. Those methods must be called
+// only from the goroutine running the Benchmark function.
+// The other reporting methods, such as the variations of Log and Error,
+// may be called simultaneously from multiple goroutines.
+//
+// Like in tests, benchmark logs are accumulated during execution
+// and dumped to standard error when done. Unlike in tests, benchmark logs
+// are always printed, so as not to hide output whose existence may be
+// affecting benchmark results.
 type B struct {
 	common
 	N                int
diff --git a/src/testing/quick/quick.go b/src/testing/quick/quick.go
index 13c56cd..187195c 100644
--- a/src/testing/quick/quick.go
+++ b/src/testing/quick/quick.go
@@ -52,8 +52,15 @@ const complexSize = 50
 // If the type implements the Generator interface, that will be used.
 // Note: To create arbitrary values for structs, all the fields must be exported.
 func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
+	return sizedValue(t, rand, complexSize)
+}
+
+// sizedValue returns an arbitrary value of the given type. The size
+// hint is used for shrinking as a function of indirection level so
+// that recursive data structures will terminate.
+func sizedValue(t reflect.Type, rand *rand.Rand, size int) (value reflect.Value, ok bool) {
 	if m, ok := reflect.Zero(t).Interface().(Generator); ok {
-		return m.Generate(rand, complexSize), true
+		return m.Generate(rand, size), true
 	}
 
 	v := reflect.New(t).Elem()
@@ -91,21 +98,21 @@ func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
 	case reflect.Uintptr:
 		v.SetUint(uint64(randInt64(rand)))
 	case reflect.Map:
-		numElems := rand.Intn(complexSize)
+		numElems := rand.Intn(size)
 		v.Set(reflect.MakeMap(concrete))
 		for i := 0; i < numElems; i++ {
-			key, ok1 := Value(concrete.Key(), rand)
-			value, ok2 := Value(concrete.Elem(), rand)
+			key, ok1 := sizedValue(concrete.Key(), rand, size)
+			value, ok2 := sizedValue(concrete.Elem(), rand, size)
 			if !ok1 || !ok2 {
 				return reflect.Value{}, false
 			}
 			v.SetMapIndex(key, value)
 		}
 	case reflect.Ptr:
-		if rand.Intn(complexSize) == 0 {
+		if rand.Intn(size) == 0 {
 			v.Set(reflect.Zero(concrete)) // Generate nil pointer.
 		} else {
-			elem, ok := Value(concrete.Elem(), rand)
+			elem, ok := sizedValue(concrete.Elem(), rand, size)
 			if !ok {
 				return reflect.Value{}, false
 			}
@@ -113,10 +120,11 @@ func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
 			v.Elem().Set(elem)
 		}
 	case reflect.Slice:
-		numElems := rand.Intn(complexSize)
+		numElems := rand.Intn(size)
+		sizeLeft := size - numElems
 		v.Set(reflect.MakeSlice(concrete, numElems, numElems))
 		for i := 0; i < numElems; i++ {
-			elem, ok := Value(concrete.Elem(), rand)
+			elem, ok := sizedValue(concrete.Elem(), rand, sizeLeft)
 			if !ok {
 				return reflect.Value{}, false
 			}
@@ -124,7 +132,7 @@ func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
 		}
 	case reflect.Array:
 		for i := 0; i < v.Len(); i++ {
-			elem, ok := Value(concrete.Elem(), rand)
+			elem, ok := sizedValue(concrete.Elem(), rand, size)
 			if !ok {
 				return reflect.Value{}, false
 			}
@@ -138,8 +146,16 @@ func Value(t reflect.Type, rand *rand.Rand) (value reflect.Value, ok bool) {
 		}
 		v.SetString(string(codePoints))
 	case reflect.Struct:
-		for i := 0; i < v.NumField(); i++ {
-			elem, ok := Value(concrete.Field(i).Type, rand)
+		n := v.NumField()
+		// Divide sizeLeft evenly among the struct fields.
+		sizeLeft := size
+		if n > sizeLeft {
+			sizeLeft = 1
+		} else if n > 0 {
+			sizeLeft /= n
+		}
+		for i := 0; i < n; i++ {
+			elem, ok := sizedValue(concrete.Field(i).Type, rand, sizeLeft)
 			if !ok {
 				return reflect.Value{}, false
 			}
diff --git a/src/testing/quick/quick_test.go b/src/testing/quick/quick_test.go
index c79f30e..fe44359 100644
--- a/src/testing/quick/quick_test.go
+++ b/src/testing/quick/quick_test.go
@@ -259,16 +259,51 @@ func TestFailure(t *testing.T) {
 	}
 }
 
-// The following test didn't terminate because nil pointers were not
-// generated.
-// Issue 8818.
-func TestNilPointers(t *testing.T) {
-	type Recursive struct {
-		Next *Recursive
+// Recursive data structures didn't terminate.
+// Issues 8818 and 11148.
+func TestRecursive(t *testing.T) {
+	type R struct {
+		Ptr      *R
+		SliceP   []*R
+		Slice    []R
+		Map      map[int]R
+		MapP     map[int]*R
+		MapR     map[*R]*R
+		SliceMap []map[int]R
 	}
 
-	f := func(rec Recursive) bool {
-		return true
-	}
+	f := func(r R) bool { return true }
+	Check(f, nil)
+}
+
+func TestEmptyStruct(t *testing.T) {
+	f := func(struct{}) bool { return true }
+	Check(f, nil)
+}
+
+type (
+	A struct{ B *B }
+	B struct{ A *A }
+)
+
+func TestMutuallyRecursive(t *testing.T) {
+	f := func(a A) bool { return true }
 	Check(f, nil)
 }
+
+// Some serialization formats (e.g. encoding/pem) cannot distinguish
+// between a nil and an empty map or slice, so avoid generating the
+// zero value for these.
+func TestNonZeroSliceAndMap(t *testing.T) {
+	type Q struct {
+		M map[int]int
+		S []int
+	}
+	f := func(q Q) bool {
+		return q.M != nil && q.S != nil
+	}
+	err := Check(f, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+}
diff --git a/src/testing/testing.go b/src/testing/testing.go
index 1dcc35e..e4c4772 100644
--- a/src/testing/testing.go
+++ b/src/testing/testing.go
@@ -149,6 +149,7 @@ import (
 	"fmt"
 	"os"
 	"runtime"
+	"runtime/debug"
 	"runtime/pprof"
 	"runtime/trace"
 	"strconv"
@@ -282,9 +283,18 @@ var _ TB = (*B)(nil)
 
 // T is a type passed to Test functions to manage test state and support formatted test logs.
 // Logs are accumulated during execution and dumped to standard error when done.
+//
+// A test ends when its Test function returns or calls any of the methods
+// FailNow, Fatal, Fatalf, SkipNow, Skip, or Skipf. Those methods, as well as
+// the Parallel method, must be called only from the goroutine running the
+// Test function.
+//
+// The other reporting methods, such as the variations of Log and Error,
+// may be called simultaneously from multiple goroutines.
 type T struct {
 	common
-	name          string    // Name of test.
+	name          string // Name of test.
+	isParallel    bool
 	startParallel chan bool // Parallel tests will wait on this.
 }
 
@@ -418,10 +428,17 @@ func (c *common) Skipped() bool {
 // Parallel signals that this test is to be run in parallel with (and only with)
 // other parallel tests.
 func (t *T) Parallel() {
+	if t.isParallel {
+		panic("testing: t.Parallel called multiple times")
+	}
+	t.isParallel = true
+
+	// We don't want to include the time we spend waiting for serial tests
+	// in the test duration. Record the elapsed time thus far and reset the
+	// timer afterwards.
+	t.duration += time.Since(t.start)
 	t.signal <- (*T)(nil) // Release main testing loop
 	<-t.startParallel     // Wait for serial tests to finish
-	// Assuming Parallel is the first thing a test does, which is reasonable,
-	// reinitialize the test's start time because it's actually starting now.
 	t.start = time.Now()
 }
 
@@ -438,7 +455,7 @@ func tRunner(t *T, test *InternalTest) {
 	// a call to runtime.Goexit, record the duration and send
 	// a signal saying that the test is done.
 	defer func() {
-		t.duration = time.Now().Sub(t.start)
+		t.duration += time.Now().Sub(t.start)
 		// If the test panicked, print any test output before dying.
 		err := recover()
 		if !t.finished && err == nil {
@@ -485,7 +502,11 @@ func MainStart(matchString func(pat, str string) (bool, error), tests []Internal
 
 // Run runs the tests. It returns an exit code to pass to os.Exit.
 func (m *M) Run() int {
-	flag.Parse()
+	// TestMain may have already called flag.Parse.
+	if !flag.Parsed() {
+		flag.Parse()
+	}
+
 	parseCpuList()
 
 	before()
@@ -700,6 +721,7 @@ var timer *time.Timer
 func startAlarm() {
 	if *timeout > 0 {
 		timer = time.AfterFunc(*timeout, func() {
+			debug.SetTraceback("all")
 			panic(fmt.Sprintf("test timed out after %v", *timeout))
 		})
 	}
diff --git a/src/text/scanner/scanner.go b/src/text/scanner/scanner.go
index 3ab01ed..0155800 100644
--- a/src/text/scanner/scanner.go
+++ b/src/text/scanner/scanner.go
@@ -73,7 +73,7 @@ const (
 	GoTokens       = ScanIdents | ScanFloats | ScanChars | ScanStrings | ScanRawStrings | ScanComments | SkipComments
 )
 
-// The result of Scan is one of the following tokens or a Unicode character.
+// The result of Scan is one of these tokens or a Unicode character.
 const (
 	EOF = -(iota + 1)
 	Ident
diff --git a/src/text/template/doc.go b/src/text/template/doc.go
index 0ce63f6..df8c95f 100644
--- a/src/text/template/doc.go
+++ b/src/text/template/doc.go
@@ -36,10 +36,35 @@ Here is a trivial example that prints "17 items are made of wool".
 
 More intricate examples appear below.
 
+Text and spaces
+
+By default, all text between actions is copied verbatim when the template is
+executed. For example, the string " items are made of " in the example above appears
+on standard output when the program is run.
+
+However, to aid in formatting template source code, if an action's left delimiter
+(by default "{{") is followed immediately by a minus sign and ASCII space character
+("{{- "), all trailing white space is trimmed from the immediately preceding text.
+Similarly, if the right delimiter ("}}") is preceded by a space and minus sign
+(" -}}"), all leading white space is trimmed from the immediately following text.
+In these trim markers, the ASCII space must be present; "{{-3}}" parses as an
+action containing the number -3.
+
+For instance, when executing the template whose source is
+
+	"{{23 -}} < {{- 45}}"
+
+the generated output would be
+
+	"23<45"
+
+For this trimming, the definition of white space characters is the same as in Go:
+space, horizontal tab, carriage return, and newline.
+
 Actions
 
 Here is the list of actions. "Arguments" and "pipelines" are evaluations of
-data, defined in detail below.
+data, defined in detail in the corresponding sections that follow.
 
 */
 //	{{/* a comment */}}
@@ -90,6 +115,14 @@ data, defined in detail below.
 		The template with the specified name is executed with dot set
 		to the value of the pipeline.
 
+	{{block "name" pipeline}} T1 {{end}}
+		A block is shorthand for defining a template
+			{{define "name"}} T1 {{end}}
+		and then executing it in place
+			{{template "name" .}}
+		The typical use is to define a set of root templates that are
+		then customized by redefining the block templates within.
+
 	{{with pipeline}} T1 {{end}}
 		If the value of the pipeline is empty, no output is generated;
 		otherwise, dot is set to the value of the pipeline and T1 is
@@ -167,6 +200,8 @@ field of a struct, the function is not invoked automatically, but it
 can be used as a truth value for an if action and the like. To invoke
 it, use the call function, defined below.
 
+Pipelines
+
 A pipeline is a possibly chained sequence of "commands". A command is a simple
 value (argument) or a function or method call, possibly with multiple arguments:
 
@@ -184,8 +219,6 @@ value (argument) or a function or method call, possibly with multiple arguments:
 			function(Argument1, etc.)
 		Functions and function names are described below.
 
-Pipelines
-
 A pipeline may be "chained" by separating a sequence of commands with pipeline
 characters '|'. In a chained pipeline, the result of the each command is
 passed as the last argument of the following command. The output of the final
diff --git a/src/text/template/example_test.go b/src/text/template/example_test.go
index de1d518..9cab2e8 100644
--- a/src/text/template/example_test.go
+++ b/src/text/template/example_test.go
@@ -7,6 +7,7 @@ package template_test
 import (
 	"log"
 	"os"
+	"strings"
 	"text/template"
 )
 
@@ -15,9 +16,12 @@ func ExampleTemplate() {
 	const letter = `
 Dear {{.Name}},
 {{if .Attended}}
-It was a pleasure to see you at the wedding.{{else}}
-It is a shame you couldn't make it to the wedding.{{end}}
-{{with .Gift}}Thank you for the lovely {{.}}.
+It was a pleasure to see you at the wedding.
+{{- else}}
+It is a shame you couldn't make it to the wedding.
+{{- end}}
+{{with .Gift -}}
+Thank you for the lovely {{.}}.
 {{end}}
 Best wishes,
 Josie
@@ -69,3 +73,38 @@ Josie
 	// Best wishes,
 	// Josie
 }
+
+// The following example is duplicated in html/template; keep them in sync.
+
+func ExampleTemplate_block() {
+	const (
+		master  = `Names:{{block "list" .}}{{"\n"}}{{range .}}{{println "-" .}}{{end}}{{end}}`
+		overlay = `{{define "list"}} {{join . ", "}}{{end}} `
+	)
+	var (
+		funcs     = template.FuncMap{"join": strings.Join}
+		guardians = []string{"Gamora", "Groot", "Nebula", "Rocket", "Star-Lord"}
+	)
+	masterTmpl, err := template.New("master").Funcs(funcs).Parse(master)
+	if err != nil {
+		log.Fatal(err)
+	}
+	overlayTmpl, err := template.Must(masterTmpl.Clone()).Parse(overlay)
+	if err != nil {
+		log.Fatal(err)
+	}
+	if err := masterTmpl.Execute(os.Stdout, guardians); err != nil {
+		log.Fatal(err)
+	}
+	if err := overlayTmpl.Execute(os.Stdout, guardians); err != nil {
+		log.Fatal(err)
+	}
+	// Output:
+	// Names:
+	// - Gamora
+	// - Groot
+	// - Nebula
+	// - Rocket
+	// - Star-Lord
+	// Names: Gamora, Groot, Nebula, Rocket, Star-Lord
+}
diff --git a/src/text/template/exec.go b/src/text/template/exec.go
index daba788..efe1817 100644
--- a/src/text/template/exec.go
+++ b/src/text/template/exec.go
@@ -78,7 +78,23 @@ func doublePercent(str string) string {
 	return str
 }
 
-// errorf formats the error and terminates processing.
+// TODO: It would be nice if ExecError was more broken down, but
+// the way ErrorContext embeds the template name makes the
+// processing too clumsy.
+
+// ExecError is the custom error type returned when Execute has an
+// error evaluating its template. (If a write error occurs, the actual
+// error is returned; it will not be of type ExecError.)
+type ExecError struct {
+	Name string // Name of template.
+	Err  error  // Pre-formatted error.
+}
+
+func (e ExecError) Error() string {
+	return e.Err.Error()
+}
+
+// errorf records an ExecError and terminates processing.
 func (s *state) errorf(format string, args ...interface{}) {
 	name := doublePercent(s.tmpl.Name())
 	if s.node == nil {
@@ -87,7 +103,24 @@ func (s *state) errorf(format string, args ...interface{}) {
 		location, context := s.tmpl.ErrorContext(s.node)
 		format = fmt.Sprintf("template: %s: executing %q at <%s>: %s", location, name, doublePercent(context), format)
 	}
-	panic(fmt.Errorf(format, args...))
+	panic(ExecError{
+		Name: s.tmpl.Name(),
+		Err:  fmt.Errorf(format, args...),
+	})
+}
+
+// writeError is the wrapper type used internally when Execute has an
+// error writing to its output. We strip the wrapper in errRecover.
+// Note that this is not an implementation of error, so it cannot escape
+// from the package as an error value.
+type writeError struct {
+	Err error // Original error.
+}
+
+func (s *state) writeError(err error) {
+	panic(writeError{
+		Err: err,
+	})
 }
 
 // errRecover is the handler that turns panics into returns from the top
@@ -98,8 +131,10 @@ func errRecover(errp *error) {
 		switch err := e.(type) {
 		case runtime.Error:
 			panic(e)
-		case error:
-			*errp = err
+		case writeError:
+			*errp = err.Err // Strip the wrapper.
+		case ExecError:
+			*errp = err // Keep the wrapper.
 		default:
 			panic(e)
 		}
@@ -145,7 +180,7 @@ func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
 }
 
 // DefinedTemplates returns a string listing the defined templates,
-// prefixed by the string "defined templates are: ". If there are none,
+// prefixed by the string "; defined templates are: ". If there are none,
 // it returns the empty string. For generating an error message here
 // and in html/template.
 func (t *Template) DefinedTemplates() string {
@@ -193,7 +228,7 @@ func (s *state) walk(dot reflect.Value, node parse.Node) {
 		s.walkTemplate(dot, node)
 	case *parse.TextNode:
 		if _, err := s.wr.Write(node.Text); err != nil {
-			s.errorf("%s", err)
+			s.writeError(err)
 		}
 	case *parse.WithNode:
 		s.walkIfOrWith(parse.NodeWith, dot, node.Pipe, node.List, node.ElseList)
@@ -222,8 +257,13 @@ func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse.
 	}
 }
 
-// isTrue reports whether the value is 'true', in the sense of not the zero of its type,
-// and whether the value has a meaningful truth value.
+// IsTrue reports whether the value is 'true', in the sense of not the zero of its type,
+// and whether the value has a meaningful truth value. This is the definition of
+// truth used by if and other such actions.
+func IsTrue(val interface{}) (truth, ok bool) {
+	return isTrue(reflect.ValueOf(val))
+}
+
 func isTrue(val reflect.Value) (truth, ok bool) {
 	if !val.IsValid() {
 		// Something like var x interface{}, never set. It's a form of nil.
@@ -483,7 +523,7 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node,
 		return zero
 	}
 	typ := receiver.Type()
-	receiver, _ = indirect(receiver)
+	receiver, isNil := indirect(receiver)
 	// Unless it's an interface, need to get to a value of type *T to guarantee
 	// we see all methods of T and *T.
 	ptr := receiver
@@ -495,7 +535,6 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node,
 	}
 	hasArgs := len(args) > 1 || final.IsValid()
 	// It's not a method; must be a field of a struct or an element of a map. The receiver must not be nil.
-	receiver, isNil := indirect(receiver)
 	if isNil {
 		s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
 	}
@@ -789,16 +828,11 @@ func (s *state) evalEmptyInterface(dot reflect.Value, n parse.Node) reflect.Valu
 }
 
 // indirect returns the item at the end of indirection, and a bool to indicate if it's nil.
-// We indirect through pointers and empty interfaces (only) because
-// non-empty interfaces have methods we might need.
 func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
 	for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() {
 		if v.IsNil() {
 			return v, true
 		}
-		if v.Kind() == reflect.Interface && v.NumMethod() > 0 {
-			break
-		}
 	}
 	return v, false
 }
@@ -811,7 +845,10 @@ func (s *state) printValue(n parse.Node, v reflect.Value) {
 	if !ok {
 		s.errorf("can't print %s of type %s", n, v.Type())
 	}
-	fmt.Fprint(s.wr, iface)
+	_, err := fmt.Fprint(s.wr, iface)
+	if err != nil {
+		s.writeError(err)
+	}
 }
 
 // printableValue returns the, possibly indirected, interface value inside v that
diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go
index ba0e434..e507e91 100644
--- a/src/text/template/exec_test.go
+++ b/src/text/template/exec_test.go
@@ -9,6 +9,7 @@ import (
 	"errors"
 	"flag"
 	"fmt"
+	"io/ioutil"
 	"reflect"
 	"strings"
 	"testing"
@@ -50,8 +51,9 @@ type T struct {
 	Empty2 interface{}
 	Empty3 interface{}
 	Empty4 interface{}
-	// Non-empty interface.
-	NonEmptyInterface I
+	// Non-empty interfaces.
+	NonEmptyInterface    I
+	NonEmptyInterfacePtS *I
 	// Stringer.
 	Str fmt.Stringer
 	Err error
@@ -72,6 +74,12 @@ type T struct {
 	unexported int
 }
 
+type S []string
+
+func (S) Method0() string {
+	return "M0"
+}
+
 type U struct {
 	V string
 }
@@ -98,6 +106,8 @@ func (w *W) Error() string {
 	return fmt.Sprintf("[%d]", w.k)
 }
 
+var siVal = I(S{"a", "b"})
+
 var tVal = &T{
 	True:   true,
 	I:      17,
@@ -118,22 +128,23 @@ var tVal = &T{
 		{"one": 1, "two": 2},
 		{"eleven": 11, "twelve": 12},
 	},
-	Empty1:            3,
-	Empty2:            "empty2",
-	Empty3:            []int{7, 8},
-	Empty4:            &U{"UinEmpty"},
-	NonEmptyInterface: new(T),
-	Str:               bytes.NewBuffer([]byte("foozle")),
-	Err:               errors.New("erroozle"),
-	PI:                newInt(23),
-	PS:                newString("a string"),
-	PSI:               newIntSlice(21, 22, 23),
-	BinaryFunc:        func(a, b string) string { return fmt.Sprintf("[%s=%s]", a, b) },
-	VariadicFunc:      func(s ...string) string { return fmt.Sprint("<", strings.Join(s, "+"), ">") },
-	VariadicFuncInt:   func(a int, s ...string) string { return fmt.Sprint(a, "=<", strings.Join(s, "+"), ">") },
-	NilOKFunc:         func(s *int) bool { return s == nil },
-	ErrFunc:           func() (string, error) { return "bla", nil },
-	Tmpl:              Must(New("x").Parse("test template")), // "x" is the value of .X
+	Empty1:               3,
+	Empty2:               "empty2",
+	Empty3:               []int{7, 8},
+	Empty4:               &U{"UinEmpty"},
+	NonEmptyInterface:    &T{X: "x"},
+	NonEmptyInterfacePtS: &siVal,
+	Str:                  bytes.NewBuffer([]byte("foozle")),
+	Err:                  errors.New("erroozle"),
+	PI:                   newInt(23),
+	PS:                   newString("a string"),
+	PSI:                  newIntSlice(21, 22, 23),
+	BinaryFunc:           func(a, b string) string { return fmt.Sprintf("[%s=%s]", a, b) },
+	VariadicFunc:         func(s ...string) string { return fmt.Sprint("<", strings.Join(s, "+"), ">") },
+	VariadicFuncInt:      func(a int, s ...string) string { return fmt.Sprint(a, "=<", strings.Join(s, "+"), ">") },
+	NilOKFunc:            func(s *int) bool { return s == nil },
+	ErrFunc:              func() (string, error) { return "bla", nil },
+	Tmpl:                 Must(New("x").Parse("test template")), // "x" is the value of .X
 }
 
 // A non-empty interface.
@@ -336,6 +347,7 @@ var execTests = []execTest{
 	{"if not .BinaryFunc call", "{{ if not .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{else}}No{{end}}", "No", tVal, true},
 	{"Interface Call", `{{stringer .S}}`, "foozle", map[string]interface{}{"S": bytes.NewBufferString("foozle")}, true},
 	{".ErrFunc", "{{call .ErrFunc}}", "bla", tVal, true},
+	{"call nil", "{{call nil}}", "", tVal, false},
 
 	// Erroneous function calls (check args).
 	{".BinaryFuncTooFew", "{{call .BinaryFunc `1`}}", "", tVal, false},
@@ -424,12 +436,15 @@ var execTests = []execTest{
 	{"slice[1]", "{{index .SI 1}}", "4", tVal, true},
 	{"slice[HUGE]", "{{index .SI 10}}", "", tVal, false},
 	{"slice[WRONG]", "{{index .SI `hello`}}", "", tVal, false},
+	{"slice[nil]", "{{index .SI nil}}", "", tVal, false},
 	{"map[one]", "{{index .MSI `one`}}", "1", tVal, true},
 	{"map[two]", "{{index .MSI `two`}}", "2", tVal, true},
 	{"map[NO]", "{{index .MSI `XXX`}}", "0", tVal, true},
-	{"map[nil]", "{{index .MSI nil}}", "0", tVal, true},
+	{"map[nil]", "{{index .MSI nil}}", "", tVal, false},
+	{"map[``]", "{{index .MSI ``}}", "0", tVal, true},
 	{"map[WRONG]", "{{index .MSI 10}}", "", tVal, false},
 	{"double index", "{{index .SMSI 1 `eleven`}}", "11", tVal, true},
+	{"nil[1]", "{{index nil 1}}", "", tVal, false},
 
 	// Len.
 	{"slice", "{{len .SI}}", "3", tVal, true},
@@ -545,6 +560,11 @@ var execTests = []execTest{
 	{"bug16i", "{{\"aaa\"|oneArg}}", "oneArg=aaa", tVal, true},
 	{"bug16j", "{{1+2i|printf \"%v\"}}", "(1+2i)", tVal, true},
 	{"bug16k", "{{\"aaa\"|printf }}", "aaa", tVal, true},
+	{"bug17a", "{{.NonEmptyInterface.X}}", "x", tVal, true},
+	{"bug17b", "-{{.NonEmptyInterface.Method1 1234}}-", "-1234-", tVal, true},
+	{"bug17c", "{{len .NonEmptyInterfacePtS}}", "2", tVal, true},
+	{"bug17d", "{{index .NonEmptyInterfacePtS 0}}", "a", tVal, true},
+	{"bug17e", "{{range .NonEmptyInterfacePtS}}-{{.}}-{{end}}", "-a--b-", tVal, true},
 }
 
 func zeroArgs() string {
@@ -796,18 +816,19 @@ type Tree struct {
 }
 
 // Use different delimiters to test Set.Delims.
+// Also test the trimming of leading and trailing spaces.
 const treeTemplate = `
-	(define "tree")
+	(- define "tree" -)
 	[
-		(.Val)
-		(with .Left)
-			(template "tree" .)
-		(end)
-		(with .Right)
-			(template "tree" .)
-		(end)
+		(- .Val -)
+		(- with .Left -)
+			(template "tree" . -)
+		(- end -)
+		(- with .Right -)
+			(- template "tree" . -)
+		(- end -)
 	]
-	(end)
+	(- end -)
 `
 
 func TestTree(t *testing.T) {
@@ -852,19 +873,13 @@ func TestTree(t *testing.T) {
 		t.Fatal("parse error:", err)
 	}
 	var b bytes.Buffer
-	stripSpace := func(r rune) rune {
-		if r == '\t' || r == '\n' {
-			return -1
-		}
-		return r
-	}
 	const expect = "[1[2[3[4]][5[6]]][7[8[9]][10[11]]]]"
 	// First by looking up the template.
 	err = tmpl.Lookup("tree").Execute(&b, tree)
 	if err != nil {
 		t.Fatal("exec error:", err)
 	}
-	result := strings.Map(stripSpace, b.String())
+	result := b.String()
 	if result != expect {
 		t.Errorf("expected %q got %q", expect, result)
 	}
@@ -874,7 +889,7 @@ func TestTree(t *testing.T) {
 	if err != nil {
 		t.Fatal("exec error:", err)
 	}
-	result = strings.Map(stripSpace, b.String())
+	result = b.String()
 	if result != expect {
 		t.Errorf("expected %q got %q", expect, result)
 	}
@@ -1141,3 +1156,127 @@ func TestUnterminatedStringError(t *testing.T) {
 		t.Fatalf("unexpected error: %s", str)
 	}
 }
+
+const alwaysErrorText = "always be failing"
+
+var alwaysError = errors.New(alwaysErrorText)
+
+type ErrorWriter int
+
+func (e ErrorWriter) Write(p []byte) (int, error) {
+	return 0, alwaysError
+}
+
+func TestExecuteGivesExecError(t *testing.T) {
+	// First, a non-execution error shouldn't be an ExecError.
+	tmpl, err := New("X").Parse("hello")
+	if err != nil {
+		t.Fatal(err)
+	}
+	err = tmpl.Execute(ErrorWriter(0), 0)
+	if err == nil {
+		t.Fatal("expected error; got none")
+	}
+	if err.Error() != alwaysErrorText {
+		t.Errorf("expected %q error; got %q", alwaysErrorText, err)
+	}
+	// This one should be an ExecError.
+	tmpl, err = New("X").Parse("hello, {{.X.Y}}")
+	if err != nil {
+		t.Fatal(err)
+	}
+	err = tmpl.Execute(ioutil.Discard, 0)
+	if err == nil {
+		t.Fatal("expected error; got none")
+	}
+	eerr, ok := err.(ExecError)
+	if !ok {
+		t.Fatalf("did not expect ExecError %s", eerr)
+	}
+	expect := "field X in type int"
+	if !strings.Contains(err.Error(), expect) {
+		t.Errorf("expected %q; got %q", expect, err)
+	}
+}
+
+func funcNameTestFunc() int {
+	return 0
+}
+
+func TestGoodFuncNames(t *testing.T) {
+	names := []string{
+		"_",
+		"a",
+		"a1",
+		"a1",
+		"Ӵ",
+	}
+	for _, name := range names {
+		tmpl := New("X").Funcs(
+			FuncMap{
+				name: funcNameTestFunc,
+			},
+		)
+		if tmpl == nil {
+			t.Fatalf("nil result for %q", name)
+		}
+	}
+}
+
+func TestBadFuncNames(t *testing.T) {
+	names := []string{
+		"",
+		"2",
+		"a-b",
+	}
+	for _, name := range names {
+		testBadFuncName(name, t)
+	}
+}
+
+func testBadFuncName(name string, t *testing.T) {
+	defer func() {
+		recover()
+	}()
+	New("X").Funcs(
+		FuncMap{
+			name: funcNameTestFunc,
+		},
+	)
+	// If we get here, the name did not cause a panic, which is how Funcs
+	// reports an error.
+	t.Errorf("%q succeeded incorrectly as function name", name)
+}
+
+func TestBlock(t *testing.T) {
+	const (
+		input   = `a({{block "inner" .}}bar({{.}})baz{{end}})b`
+		want    = `a(bar(hello)baz)b`
+		overlay = `{{define "inner"}}foo({{.}})bar{{end}}`
+		want2   = `a(foo(goodbye)bar)b`
+	)
+	tmpl, err := New("outer").Parse(input)
+	if err != nil {
+		t.Fatal(err)
+	}
+	tmpl2, err := Must(tmpl.Clone()).Parse(overlay)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var buf bytes.Buffer
+	if err := tmpl.Execute(&buf, "hello"); err != nil {
+		t.Fatal(err)
+	}
+	if got := buf.String(); got != want {
+		t.Errorf("got %q, want %q", got, want)
+	}
+
+	buf.Reset()
+	if err := tmpl2.Execute(&buf, "goodbye"); err != nil {
+		t.Fatal(err)
+	}
+	if got := buf.String(); got != want2 {
+		t.Errorf("got %q, want %q", got, want2)
+	}
+}
diff --git a/src/text/template/funcs.go b/src/text/template/funcs.go
index ccd0dfc..49e9e74 100644
--- a/src/text/template/funcs.go
+++ b/src/text/template/funcs.go
@@ -58,6 +58,9 @@ func createValueFuncs(funcMap FuncMap) map[string]reflect.Value {
 // addValueFuncs adds to values the functions in funcs, converting them to reflect.Values.
 func addValueFuncs(out map[string]reflect.Value, in FuncMap) {
 	for name, fn := range in {
+		if !goodName(name) {
+			panic(fmt.Errorf("function name %s is not a valid identifier", name))
+		}
 		v := reflect.ValueOf(fn)
 		if v.Kind() != reflect.Func {
 			panic("value for " + name + " not a function")
@@ -77,7 +80,7 @@ func addFuncs(out, in FuncMap) {
 	}
 }
 
-// goodFunc checks that the function or method has the right result signature.
+// goodFunc reports whether the function or method has the right result signature.
 func goodFunc(typ reflect.Type) bool {
 	// We allow functions with 1 result or 2 results where the second is an error.
 	switch {
@@ -89,6 +92,23 @@ func goodFunc(typ reflect.Type) bool {
 	return false
 }
 
+// goodName reports whether the function name is a valid identifier.
+func goodName(name string) bool {
+	if name == "" {
+		return false
+	}
+	for i, r := range name {
+		switch {
+		case r == '_':
+		case i == 0 && !unicode.IsLetter(r):
+			return false
+		case !unicode.IsLetter(r) && !unicode.IsDigit(r):
+			return false
+		}
+	}
+	return true
+}
+
 // findFunction looks for a function in the template, and global map.
 func findFunction(name string, tmpl *Template) (reflect.Value, bool) {
 	if tmpl != nil && tmpl.common != nil {
@@ -104,6 +124,21 @@ func findFunction(name string, tmpl *Template) (reflect.Value, bool) {
 	return reflect.Value{}, false
 }
 
+// prepareArg checks if value can be used as an argument of type argType, and
+// converts an invalid value to appropriate zero if possible.
+func prepareArg(value reflect.Value, argType reflect.Type) (reflect.Value, error) {
+	if !value.IsValid() {
+		if !canBeNil(argType) {
+			return reflect.Value{}, fmt.Errorf("value is nil; should be of type %s", argType)
+		}
+		value = reflect.Zero(argType)
+	}
+	if !value.Type().AssignableTo(argType) {
+		return reflect.Value{}, fmt.Errorf("value has type %s; should be %s", value.Type(), argType)
+	}
+	return value, nil
+}
+
 // Indexing.
 
 // index returns the result of indexing its first argument by the following
@@ -111,6 +146,9 @@ func findFunction(name string, tmpl *Template) (reflect.Value, bool) {
 // indexed item must be a map, slice, or array.
 func index(item interface{}, indices ...interface{}) (interface{}, error) {
 	v := reflect.ValueOf(item)
+	if !v.IsValid() {
+		return nil, fmt.Errorf("index of untyped nil")
+	}
 	for _, i := range indices {
 		index := reflect.ValueOf(i)
 		var isNil bool
@@ -125,6 +163,8 @@ func index(item interface{}, indices ...interface{}) (interface{}, error) {
 				x = index.Int()
 			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
 				x = int64(index.Uint())
+			case reflect.Invalid:
+				return nil, fmt.Errorf("cannot index slice/array with nil")
 			default:
 				return nil, fmt.Errorf("cannot index slice/array with type %s", index.Type())
 			}
@@ -133,17 +173,18 @@ func index(item interface{}, indices ...interface{}) (interface{}, error) {
 			}
 			v = v.Index(int(x))
 		case reflect.Map:
-			if !index.IsValid() {
-				index = reflect.Zero(v.Type().Key())
-			}
-			if !index.Type().AssignableTo(v.Type().Key()) {
-				return nil, fmt.Errorf("%s is not index type for %s", index.Type(), v.Type())
+			index, err := prepareArg(index, v.Type().Key())
+			if err != nil {
+				return nil, err
 			}
 			if x := v.MapIndex(index); x.IsValid() {
 				v = x
 			} else {
 				v = reflect.Zero(v.Type().Elem())
 			}
+		case reflect.Invalid:
+			// the loop holds invariant: v.IsValid()
+			panic("unreachable")
 		default:
 			return nil, fmt.Errorf("can't index item of type %s", v.Type())
 		}
@@ -155,7 +196,11 @@ func index(item interface{}, indices ...interface{}) (interface{}, error) {
 
 // length returns the length of the item, with an error if it has no defined length.
 func length(item interface{}) (int, error) {
-	v, isNil := indirect(reflect.ValueOf(item))
+	v := reflect.ValueOf(item)
+	if !v.IsValid() {
+		return 0, fmt.Errorf("len of untyped nil")
+	}
+	v, isNil := indirect(v)
 	if isNil {
 		return 0, fmt.Errorf("len of nil pointer")
 	}
@@ -172,6 +217,9 @@ func length(item interface{}) (int, error) {
 // The function must return 1 result, or 2 results, the second of which is an error.
 func call(fn interface{}, args ...interface{}) (interface{}, error) {
 	v := reflect.ValueOf(fn)
+	if !v.IsValid() {
+		return nil, fmt.Errorf("call of nil")
+	}
 	typ := v.Type()
 	if typ.Kind() != reflect.Func {
 		return nil, fmt.Errorf("non-function of type %s", typ)
@@ -201,13 +249,11 @@ func call(fn interface{}, args ...interface{}) (interface{}, error) {
 		} else {
 			argType = dddType
 		}
-		if !value.IsValid() && canBeNil(argType) {
-			value = reflect.Zero(argType)
-		}
-		if !value.Type().AssignableTo(argType) {
-			return nil, fmt.Errorf("arg %d has type %s; should be %s", i, value.Type(), argType)
+
+		var err error
+		if argv[i], err = prepareArg(value, argType); err != nil {
+			return nil, fmt.Errorf("arg %d: %s", i, err)
 		}
-		argv[i] = value
 	}
 	result := v.Call(argv)
 	if len(result) == 2 && !result[1].IsNil() {
@@ -219,7 +265,7 @@ func call(fn interface{}, args ...interface{}) (interface{}, error) {
 // Boolean logic.
 
 func truth(a interface{}) bool {
-	t, _ := isTrue(reflect.ValueOf(a))
+	t, _ := IsTrue(a)
 	return t
 }
 
@@ -254,9 +300,8 @@ func or(arg0 interface{}, args ...interface{}) interface{} {
 }
 
 // not returns the Boolean negation of its argument.
-func not(arg interface{}) (truth bool) {
-	truth, _ = isTrue(reflect.ValueOf(arg))
-	return !truth
+func not(arg interface{}) bool {
+	return !truth(arg)
 }
 
 // Comparison.
diff --git a/src/text/template/multi_test.go b/src/text/template/multi_test.go
index ea01875..a8342f5 100644
--- a/src/text/template/multi_test.go
+++ b/src/text/template/multi_test.go
@@ -9,7 +9,6 @@ package template
 import (
 	"bytes"
 	"fmt"
-	"strings"
 	"testing"
 	"text/template/parse"
 )
@@ -277,17 +276,11 @@ func TestRedefinition(t *testing.T) {
 	if tmpl, err = New("tmpl1").Parse(`{{define "test"}}foo{{end}}`); err != nil {
 		t.Fatalf("parse 1: %v", err)
 	}
-	if _, err = tmpl.Parse(`{{define "test"}}bar{{end}}`); err == nil {
-		t.Fatal("expected error")
+	if _, err = tmpl.Parse(`{{define "test"}}bar{{end}}`); err != nil {
+		t.Fatalf("got error %v, expected nil", err)
 	}
-	if !strings.Contains(err.Error(), "redefinition") {
-		t.Fatalf("expected redefinition error; got %v", err)
-	}
-	if _, err = tmpl.New("tmpl2").Parse(`{{define "test"}}bar{{end}}`); err == nil {
-		t.Fatal("expected error")
-	}
-	if !strings.Contains(err.Error(), "redefinition") {
-		t.Fatalf("expected redefinition error; got %v", err)
+	if _, err = tmpl.New("tmpl2").Parse(`{{define "test"}}bar{{end}}`); err != nil {
+		t.Fatalf("got error %v, expected nil", err)
 	}
 }
 
@@ -345,7 +338,6 @@ func TestNew(t *testing.T) {
 func TestParse(t *testing.T) {
 	// In multiple calls to Parse with the same receiver template, only one call
 	// can contain text other than space, comments, and template definitions
-	var err error
 	t1 := New("test")
 	if _, err := t1.Parse(`{{define "test"}}{{end}}`); err != nil {
 		t.Fatalf("parsing test: %s", err)
@@ -356,10 +348,4 @@ func TestParse(t *testing.T) {
 	if _, err := t1.Parse(`{{define "test"}}foo{{end}}`); err != nil {
 		t.Fatalf("parsing test: %s", err)
 	}
-	if _, err = t1.Parse(`{{define "test"}}foo{{end}}`); err == nil {
-		t.Fatal("no error from redefining a template")
-	}
-	if !strings.Contains(err.Error(), "redefinition") {
-		t.Fatalf("expected redefinition error; got %v", err)
-	}
 }
diff --git a/src/text/template/parse/lex.go b/src/text/template/parse/lex.go
index 8f9fe1d..ea93e05 100644
--- a/src/text/template/parse/lex.go
+++ b/src/text/template/parse/lex.go
@@ -58,6 +58,7 @@ const (
 	itemVariable   // variable starting with '$', such as '$' or  '$1' or '$hello'
 	// Keywords appear after all the rest.
 	itemKeyword  // used only to delimit the keywords
+	itemBlock    // block keyword
 	itemDot      // the cursor, spelled '.'
 	itemDefine   // define keyword
 	itemElse     // else keyword
@@ -71,6 +72,7 @@ const (
 
 var key = map[string]itemType{
 	".":        itemDot,
+	"block":    itemBlock,
 	"define":   itemDefine,
 	"else":     itemElse,
 	"end":      itemEnd,
@@ -83,6 +85,21 @@ var key = map[string]itemType{
 
 const eof = -1
 
+// Trimming spaces.
+// If the action begins "{{- " rather than "{{", then all space/tab/newlines
+// preceding the action are trimmed; conversely if it ends " -}}" the
+// leading spaces are trimmed. This is done entirely in the lexer; the
+// parser never sees it happen. We require an ASCII space to be
+// present to avoid ambiguity with things like "{{-3}}". It reads
+// better with the space present anyway. For simplicity, only ASCII
+// space does the job.
+const (
+	spaceChars      = " \t\r\n" // These are the space characters defined by Go itself.
+	leftTrimMarker  = "- "      // Attached to left delimiter, trims trailing spaces from preceding text.
+	rightTrimMarker = " -"      // Attached to right delimiter, trims leading spaces from following text.
+	trimMarkerLen   = Pos(len(leftTrimMarker))
+)
+
 // stateFn represents the state of the scanner as a function that returns the next state.
 type stateFn func(*lexer) stateFn
 
@@ -220,10 +237,18 @@ const (
 // lexText scans until an opening action delimiter, "{{".
 func lexText(l *lexer) stateFn {
 	for {
-		if strings.HasPrefix(l.input[l.pos:], l.leftDelim) {
+		delim, trimSpace := l.atLeftDelim()
+		if delim {
+			trimLength := Pos(0)
+			if trimSpace {
+				trimLength = rightTrimLength(l.input[l.start:l.pos])
+			}
+			l.pos -= trimLength
 			if l.pos > l.start {
 				l.emit(itemText)
 			}
+			l.pos += trimLength
+			l.ignore()
 			return lexLeftDelim
 		}
 		if l.next() == eof {
@@ -238,13 +263,56 @@ func lexText(l *lexer) stateFn {
 	return nil
 }
 
-// lexLeftDelim scans the left delimiter, which is known to be present.
+// atLeftDelim reports whether the lexer is at a left delimiter, possibly followed by a trim marker.
+func (l *lexer) atLeftDelim() (delim, trimSpaces bool) {
+	if !strings.HasPrefix(l.input[l.pos:], l.leftDelim) {
+		return false, false
+	}
+	// The left delim might have the marker afterwards.
+	trimSpaces = strings.HasPrefix(l.input[l.pos+Pos(len(l.leftDelim)):], leftTrimMarker)
+	return true, trimSpaces
+}
+
+// rightTrimLength returns the length of the spaces at the end of the string.
+func rightTrimLength(s string) Pos {
+	return Pos(len(s) - len(strings.TrimRight(s, spaceChars)))
+}
+
+// atRightDelim reports whether the lexer is at a right delimiter, possibly preceded by a trim marker.
+func (l *lexer) atRightDelim() (delim, trimSpaces bool) {
+	if strings.HasPrefix(l.input[l.pos:], l.rightDelim) {
+		return true, false
+	}
+	// The right delim might have the marker before.
+	if strings.HasPrefix(l.input[l.pos:], rightTrimMarker) {
+		if strings.HasPrefix(l.input[l.pos+trimMarkerLen:], l.rightDelim) {
+			return true, true
+		}
+	}
+	return false, false
+}
+
+// leftTrimLength returns the length of the spaces at the beginning of the string.
+func leftTrimLength(s string) Pos {
+	return Pos(len(s) - len(strings.TrimLeft(s, spaceChars)))
+}
+
+// lexLeftDelim scans the left delimiter, which is known to be present, possibly with a trim marker.
 func lexLeftDelim(l *lexer) stateFn {
 	l.pos += Pos(len(l.leftDelim))
-	if strings.HasPrefix(l.input[l.pos:], leftComment) {
+	trimSpace := strings.HasPrefix(l.input[l.pos:], leftTrimMarker)
+	afterMarker := Pos(0)
+	if trimSpace {
+		afterMarker = trimMarkerLen
+	}
+	if strings.HasPrefix(l.input[l.pos+afterMarker:], leftComment) {
+		l.pos += afterMarker
+		l.ignore()
 		return lexComment
 	}
 	l.emit(itemLeftDelim)
+	l.pos += afterMarker
+	l.ignore()
 	l.parenDepth = 0
 	return lexInsideAction
 }
@@ -257,19 +325,34 @@ func lexComment(l *lexer) stateFn {
 		return l.errorf("unclosed comment")
 	}
 	l.pos += Pos(i + len(rightComment))
-	if !strings.HasPrefix(l.input[l.pos:], l.rightDelim) {
+	delim, trimSpace := l.atRightDelim()
+	if !delim {
 		return l.errorf("comment ends before closing delimiter")
-
+	}
+	if trimSpace {
+		l.pos += trimMarkerLen
 	}
 	l.pos += Pos(len(l.rightDelim))
+	if trimSpace {
+		l.pos += leftTrimLength(l.input[l.pos:])
+	}
 	l.ignore()
 	return lexText
 }
 
-// lexRightDelim scans the right delimiter, which is known to be present.
+// lexRightDelim scans the right delimiter, which is known to be present, possibly with a trim marker.
 func lexRightDelim(l *lexer) stateFn {
+	trimSpace := strings.HasPrefix(l.input[l.pos:], rightTrimMarker)
+	if trimSpace {
+		l.pos += trimMarkerLen
+		l.ignore()
+	}
 	l.pos += Pos(len(l.rightDelim))
 	l.emit(itemRightDelim)
+	if trimSpace {
+		l.pos += leftTrimLength(l.input[l.pos:])
+		l.ignore()
+	}
 	return lexText
 }
 
@@ -278,7 +361,8 @@ func lexInsideAction(l *lexer) stateFn {
 	// Either number, quoted string, or identifier.
 	// Spaces separate arguments; runs of spaces turn into itemSpace.
 	// Pipe symbols separate and are emitted.
-	if strings.HasPrefix(l.input[l.pos:], l.rightDelim) {
+	delim, _ := l.atRightDelim()
+	if delim {
 		if l.parenDepth == 0 {
 			return lexRightDelim
 		}
diff --git a/src/text/template/parse/lex_test.go b/src/text/template/parse/lex_test.go
index be551d8..e35ebf1 100644
--- a/src/text/template/parse/lex_test.go
+++ b/src/text/template/parse/lex_test.go
@@ -33,6 +33,7 @@ var itemName = map[itemType]string{
 
 	// keywords
 	itemDot:      ".",
+	itemBlock:    "block",
 	itemDefine:   "define",
 	itemElse:     "else",
 	itemIf:       "if",
@@ -58,6 +59,8 @@ type lexTest struct {
 }
 
 var (
+	tDot        = item{itemDot, 0, "."}
+	tBlock      = item{itemBlock, 0, "block"}
 	tEOF        = item{itemEOF, 0, ""}
 	tFor        = item{itemIdentifier, 0, "for"}
 	tLeft       = item{itemLeftDelim, 0, "{{"}
@@ -104,6 +107,9 @@ var lexTests = []lexTest{
 	}},
 	{"empty action", `{{}}`, []item{tLeft, tRight, tEOF}},
 	{"for", `{{for}}`, []item{tLeft, tFor, tRight, tEOF}},
+	{"block", `{{block "foo" .}}`, []item{
+		tLeft, tBlock, tSpace, {itemString, 0, `"foo"`}, tSpace, tDot, tRight, tEOF,
+	}},
 	{"quote", `{{"abc \n\t\" "}}`, []item{tLeft, tQuote, tRight, tEOF}},
 	{"raw quote", "{{" + raw + "}}", []item{tLeft, tRawQuote, tRight, tEOF}},
 	{"raw quote with newline", "{{" + rawNL + "}}", []item{tLeft, tRawQuoteNL, tRight, tEOF}},
@@ -155,7 +161,7 @@ var lexTests = []lexTest{
 	}},
 	{"dot", "{{.}}", []item{
 		tLeft,
-		{itemDot, 0, "."},
+		tDot,
 		tRight,
 		tEOF,
 	}},
@@ -169,7 +175,7 @@ var lexTests = []lexTest{
 		tLeft,
 		{itemField, 0, ".x"},
 		tSpace,
-		{itemDot, 0, "."},
+		tDot,
 		tSpace,
 		{itemNumber, 0, ".2"},
 		tSpace,
@@ -278,6 +284,19 @@ var lexTests = []lexTest{
 		tRight,
 		tEOF,
 	}},
+	{"trimming spaces before and after", "hello- {{- 3 -}} -world", []item{
+		{itemText, 0, "hello-"},
+		tLeft,
+		{itemNumber, 0, "3"},
+		tRight,
+		{itemText, 0, "-world"},
+		tEOF,
+	}},
+	{"trimming spaces before and after comment", "hello- {{- /* hello */ -}} -world", []item{
+		{itemText, 0, "hello-"},
+		{itemText, 0, "-world"},
+		tEOF,
+	}},
 	// errors
 	{"badchar", "#{{\x01}}", []item{
 		{itemText, 0, "#"},
@@ -339,7 +358,7 @@ var lexTests = []lexTest{
 		{itemText, 0, "hello-"},
 		{itemError, 0, `unclosed comment`},
 	}},
-	{"text with comment close separted from delim", "hello-{{/* */ }}-world", []item{
+	{"text with comment close separated from delim", "hello-{{/* */ }}-world", []item{
 		{itemText, 0, "hello-"},
 		{itemError, 0, `comment ends before closing delimiter`},
 	}},
@@ -488,9 +507,9 @@ func TestShutdown(t *testing.T) {
 func (t *Tree) parseLexer(lex *lexer, text string) (tree *Tree, err error) {
 	defer t.recover(&err)
 	t.ParseName = t.Name
-	t.startParse(nil, lex)
-	t.parse(nil)
-	t.add(nil)
+	t.startParse(nil, lex, map[string]*Tree{})
+	t.parse()
+	t.add()
 	t.stopParse()
 	return t, nil
 }
diff --git a/src/text/template/parse/parse.go b/src/text/template/parse/parse.go
index 88aacd1..dc56cf7 100644
--- a/src/text/template/parse/parse.go
+++ b/src/text/template/parse/parse.go
@@ -28,6 +28,7 @@ type Tree struct {
 	token     [3]item // three-token lookahead for parser.
 	peekCount int
 	vars      []string // variables defined at the moment.
+	treeSet   map[string]*Tree
 }
 
 // Copy returns a copy of the Tree. Any parsing state is discarded.
@@ -205,11 +206,12 @@ func (t *Tree) recover(errp *error) {
 }
 
 // startParse initializes the parser, using the lexer.
-func (t *Tree) startParse(funcs []map[string]interface{}, lex *lexer) {
+func (t *Tree) startParse(funcs []map[string]interface{}, lex *lexer, treeSet map[string]*Tree) {
 	t.Root = nil
 	t.lex = lex
 	t.vars = []string{"$"}
 	t.funcs = funcs
+	t.treeSet = treeSet
 }
 
 // stopParse terminates parsing.
@@ -217,6 +219,7 @@ func (t *Tree) stopParse() {
 	t.lex = nil
 	t.vars = nil
 	t.funcs = nil
+	t.treeSet = nil
 }
 
 // Parse parses the template definition string to construct a representation of
@@ -226,19 +229,19 @@ func (t *Tree) stopParse() {
 func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error) {
 	defer t.recover(&err)
 	t.ParseName = t.Name
-	t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim))
+	t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim), treeSet)
 	t.text = text
-	t.parse(treeSet)
-	t.add(treeSet)
+	t.parse()
+	t.add()
 	t.stopParse()
 	return t, nil
 }
 
-// add adds tree to the treeSet.
-func (t *Tree) add(treeSet map[string]*Tree) {
-	tree := treeSet[t.Name]
+// add adds tree to t.treeSet.
+func (t *Tree) add() {
+	tree := t.treeSet[t.Name]
 	if tree == nil || IsEmptyTree(tree.Root) {
-		treeSet[t.Name] = t
+		t.treeSet[t.Name] = t
 		return
 	}
 	if !IsEmptyTree(t.Root) {
@@ -274,7 +277,7 @@ func IsEmptyTree(n Node) bool {
 // parse is the top-level parser for a template, essentially the same
 // as itemList except it also parses {{define}} actions.
 // It runs to EOF.
-func (t *Tree) parse(treeSet map[string]*Tree) (next Node) {
+func (t *Tree) parse() (next Node) {
 	t.Root = t.newList(t.peek().pos)
 	for t.peek().typ != itemEOF {
 		if t.peek().typ == itemLeftDelim {
@@ -283,8 +286,8 @@ func (t *Tree) parse(treeSet map[string]*Tree) (next Node) {
 				newT := New("definition") // name will be updated once we know it.
 				newT.text = t.text
 				newT.ParseName = t.ParseName
-				newT.startParse(t.funcs, t.lex)
-				newT.parseDefinition(treeSet)
+				newT.startParse(t.funcs, t.lex, t.treeSet)
+				newT.parseDefinition()
 				continue
 			}
 			t.backup2(delim)
@@ -300,9 +303,9 @@ func (t *Tree) parse(treeSet map[string]*Tree) (next Node) {
 }
 
 // parseDefinition parses a {{define}} ...  {{end}} template definition and
-// installs the definition in the treeSet map.  The "define" keyword has already
+// installs the definition in t.treeSet. The "define" keyword has already
 // been scanned.
-func (t *Tree) parseDefinition(treeSet map[string]*Tree) {
+func (t *Tree) parseDefinition() {
 	const context = "define clause"
 	name := t.expectOneOf(itemString, itemRawString, context)
 	var err error
@@ -316,7 +319,7 @@ func (t *Tree) parseDefinition(treeSet map[string]*Tree) {
 	if end.Type() != nodeEnd {
 		t.errorf("unexpected %s in %s", end, context)
 	}
-	t.add(treeSet)
+	t.add()
 	t.stopParse()
 }
 
@@ -358,6 +361,8 @@ func (t *Tree) textOrAction() Node {
 // First word could be a keyword such as range.
 func (t *Tree) action() (n Node) {
 	switch token := t.nextNonSpace(); token.typ {
+	case itemBlock:
+		return t.blockControl()
 	case itemElse:
 		return t.elseControl()
 	case itemEnd:
@@ -522,13 +527,51 @@ func (t *Tree) elseControl() Node {
 	return t.newElse(t.expect(itemRightDelim, "else").pos, t.lex.lineNumber())
 }
 
+// Block:
+//	{{block stringValue pipeline}}
+// Block keyword is past.
+// The name must be something that can evaluate to a string.
+// The pipeline is mandatory.
+func (t *Tree) blockControl() Node {
+	const context = "block clause"
+
+	token := t.nextNonSpace()
+	name := t.parseTemplateName(token, context)
+	pipe := t.pipeline(context)
+
+	block := New(name) // name will be updated once we know it.
+	block.text = t.text
+	block.ParseName = t.ParseName
+	block.startParse(t.funcs, t.lex, t.treeSet)
+	var end Node
+	block.Root, end = block.itemList()
+	if end.Type() != nodeEnd {
+		t.errorf("unexpected %s in %s", end, context)
+	}
+	block.add()
+	block.stopParse()
+
+	return t.newTemplate(token.pos, t.lex.lineNumber(), name, pipe)
+}
+
 // Template:
 //	{{template stringValue pipeline}}
 // Template keyword is past.  The name must be something that can evaluate
 // to a string.
 func (t *Tree) templateControl() Node {
-	var name string
+	const context = "template clause"
 	token := t.nextNonSpace()
+	name := t.parseTemplateName(token, context)
+	var pipe *PipeNode
+	if t.nextNonSpace().typ != itemRightDelim {
+		t.backup()
+		// Do not pop variables; they persist until "end".
+		pipe = t.pipeline(context)
+	}
+	return t.newTemplate(token.pos, t.lex.lineNumber(), name, pipe)
+}
+
+func (t *Tree) parseTemplateName(token item, context string) (name string) {
 	switch token.typ {
 	case itemString, itemRawString:
 		s, err := strconv.Unquote(token.val)
@@ -537,15 +580,9 @@ func (t *Tree) templateControl() Node {
 		}
 		name = s
 	default:
-		t.unexpected(token, "template invocation")
-	}
-	var pipe *PipeNode
-	if t.nextNonSpace().typ != itemRightDelim {
-		t.backup()
-		// Do not pop variables; they persist until "end".
-		pipe = t.pipeline("template")
+		t.unexpected(token, context)
 	}
-	return t.newTemplate(token.pos, t.lex.lineNumber(), name, pipe)
+	return
 }
 
 // command:
diff --git a/src/text/template/parse/parse_test.go b/src/text/template/parse/parse_test.go
index 200d50c..b4512d3 100644
--- a/src/text/template/parse/parse_test.go
+++ b/src/text/template/parse/parse_test.go
@@ -228,6 +228,15 @@ var parseTests = []parseTest{
 		`{{with .X}}"hello"{{end}}`},
 	{"with with else", "{{with .X}}hello{{else}}goodbye{{end}}", noError,
 		`{{with .X}}"hello"{{else}}"goodbye"{{end}}`},
+	// Trimming spaces.
+	{"trim left", "x \r\n\t{{- 3}}", noError, `"x"{{3}}`},
+	{"trim right", "{{3 -}}\n\n\ty", noError, `{{3}}"y"`},
+	{"trim left and right", "x \r\n\t{{- 3 -}}\n\n\ty", noError, `"x"{{3}}"y"`},
+	{"comment trim left", "x \r\n\t{{- /* hi */}}", noError, `"x"`},
+	{"comment trim right", "{{/* hi */ -}}\n\n\ty", noError, `"y"`},
+	{"comment trim left and right", "x \r\n\t{{- /* */ -}}\n\n\ty", noError, `"x""y"`},
+	{"block definition", `{{block "foo" .}}hello{{end}}`, noError,
+		`{{template "foo" .}}`},
 	// Errors.
 	{"unclosed action", "hello{{range", hasError, ""},
 	{"unmatched end", "{{end}}", hasError, ""},
@@ -277,6 +286,8 @@ var parseTests = []parseTest{
 	{"wrong pipeline boolean", "{{.|true}}", hasError, ""},
 	{"wrong pipeline nil", "{{'c'|nil}}", hasError, ""},
 	{"empty pipeline", `{{printf "%d" ( ) }}`, hasError, ""},
+	// Missing pipeline in block
+	{"block definition", `{{block "foo"}}hello{{end}}`, hasError, ""},
 }
 
 var builtins = map[string]interface{}{
@@ -450,3 +461,26 @@ func TestErrors(t *testing.T) {
 		}
 	}
 }
+
+func TestBlock(t *testing.T) {
+	const (
+		input = `a{{block "inner" .}}bar{{.}}baz{{end}}b`
+		outer = `a{{template "inner" .}}b`
+		inner = `bar{{.}}baz`
+	)
+	treeSet := make(map[string]*Tree)
+	tmpl, err := New("outer").Parse(input, "", "", treeSet, nil)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if g, w := tmpl.Root.String(), outer; g != w {
+		t.Errorf("outer template = %q, want %q", g, w)
+	}
+	inTmpl := treeSet["inner"]
+	if inTmpl == nil {
+		t.Fatal("block did not define template")
+	}
+	if g, w := inTmpl.Root.String(), inner; g != w {
+		t.Errorf("inner template = %q, want %q", g, w)
+	}
+}
diff --git a/src/text/template/template.go b/src/text/template/template.go
index 3e80982..7a7f42a 100644
--- a/src/text/template/template.go
+++ b/src/text/template/template.go
@@ -5,7 +5,6 @@
 package template
 
 import (
-	"fmt"
 	"reflect"
 	"sync"
 	"text/template/parse"
@@ -117,11 +116,10 @@ func (t *Template) copy(c *common) *Template {
 
 // AddParseTree adds parse tree for template with given name and associates it with t.
 // If the template does not already exist, it will create a new one.
-// It is an error to reuse a name except to overwrite an empty template.
+// If the template does exist, it will be replaced.
 func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) {
 	t.init()
 	// If the name is the name of this template, overwrite this template.
-	// The associate method checks it's not a redefinition.
 	nt := t
 	if name != t.name {
 		nt = t.New(name)
@@ -162,8 +160,9 @@ func (t *Template) Delims(left, right string) *Template {
 
 // Funcs adds the elements of the argument map to the template's function map.
 // It panics if a value in the map is not a function with appropriate return
-// type. However, it is legal to overwrite elements of the map. The return
-// value is the template, so calls can be chained.
+// type or if the name cannot be used syntactically as a function in a template.
+// It is legal to overwrite elements of the map. The return value is the template,
+// so calls can be chained.
 func (t *Template) Funcs(funcMap FuncMap) *Template {
 	t.init()
 	t.muFuncs.Lock()
@@ -184,11 +183,7 @@ func (t *Template) Lookup(name string) *Template {
 
 // Parse defines the template by parsing the text. Nested template definitions will be
 // associated with the top-level template t. Parse may be called multiple times
-// to parse definitions of templates to associate with t. It is an error if a
-// resulting template is non-empty (contains content other than template
-// definitions) and would replace a non-empty template with the same name.
-// (In multiple calls to Parse with the same receiver template, only one call
-// can contain text other than space, comments, and template definitions.)
+// to parse definitions of templates to associate with t.
 func (t *Template) Parse(text string) (*Template, error) {
 	t.init()
 	t.muFuncs.RLock()
@@ -207,25 +202,17 @@ func (t *Template) Parse(text string) (*Template, error) {
 }
 
 // associate installs the new template into the group of templates associated
-// with t. It is an error to reuse a name except to overwrite an empty
-// template. The two are already known to share the common structure.
-// The boolean return value reports wither to store this tree as t.Tree.
+// with t. The two are already known to share the common structure.
+// The boolean return value reports whether to store this tree as t.Tree.
 func (t *Template) associate(new *Template, tree *parse.Tree) (bool, error) {
 	if new.common != t.common {
 		panic("internal error: associate not common")
 	}
-	name := new.name
-	if old := t.tmpl[name]; old != nil {
-		oldIsEmpty := parse.IsEmptyTree(old.Root)
-		newIsEmpty := parse.IsEmptyTree(tree.Root)
-		if newIsEmpty {
-			// Whether old is empty or not, new is empty; no reason to replace old.
-			return false, nil
-		}
-		if !oldIsEmpty {
-			return false, fmt.Errorf("template: redefinition of template %q", name)
-		}
+	if t.tmpl[new.name] != nil && parse.IsEmptyTree(tree.Root) {
+		// If a template by that name exists,
+		// don't replace it with an empty template.
+		return false, nil
 	}
-	t.tmpl[name] = new
+	t.tmpl[new.name] = new
 	return true, nil
 }
diff --git a/src/time/format.go b/src/time/format.go
index 873d3ff..e616feb 100644
--- a/src/time/format.go
+++ b/src/time/format.go
@@ -34,14 +34,23 @@ import "errors"
 // Numeric time zone offsets format as follows:
 //	-0700  ±hhmm
 //	-07:00 ±hh:mm
+//	-07    ±hh
 // Replacing the sign in the format with a Z triggers
 // the ISO 8601 behavior of printing Z instead of an
 // offset for the UTC zone.  Thus:
 //	Z0700  Z or ±hhmm
 //	Z07:00 Z or ±hh:mm
+//	Z07    Z or ±hh
 //
 // The executable example for time.Format demonstrates the working
 // of the layout string in detail and is a good reference.
+//
+// Note that the RFC822, RFC850, and RFC1123 formats should be applied
+// only to local times. Applying them to UTC times will use "UTC" as the
+// time zone abbreviation, while strictly speaking those RFCs require the
+// use of "GMT" in that case.
+// In general RFC1123Z should be used instead of RFC1123 for servers
+// that insist on that format, and RFC3339 should be preferred for new protocols.
 const (
 	ANSIC       = "Mon Jan _2 15:04:05 2006"
 	UnixDate    = "Mon Jan _2 15:04:05 MST 2006"
@@ -86,6 +95,7 @@ const (
 	stdTZ                    = iota                // "MST"
 	stdISO8601TZ                                   // "Z0700"  // prints Z for UTC
 	stdISO8601SecondsTZ                            // "Z070000"
+	stdISO8601ShortTZ                              // "Z07"
 	stdISO8601ColonTZ                              // "Z07:00" // prints Z for UTC
 	stdISO8601ColonSecondsTZ                       // "Z07:00:00"
 	stdNumTZ                                       // "-0700"  // always numeric
@@ -162,8 +172,12 @@ func nextStdChunk(layout string) (prefix string, std int, suffix string) {
 			}
 			return layout[0:i], stdDay, layout[i+1:]
 
-		case '_': // _2
+		case '_': // _2, _2006
 			if len(layout) >= i+2 && layout[i+1] == '2' {
+				//_2006 is really a literal _, followed by stdLongYear
+				if len(layout) >= i+5 && layout[i+1:i+5] == "2006" {
+					return layout[0 : i+1], stdLongYear, layout[i+5:]
+				}
 				return layout[0:i], stdUnderDay, layout[i+2:]
 			}
 
@@ -216,6 +230,9 @@ func nextStdChunk(layout string) (prefix string, std int, suffix string) {
 			if len(layout) >= i+6 && layout[i:i+6] == "Z07:00" {
 				return layout[0:i], stdISO8601ColonTZ, layout[i+6:]
 			}
+			if len(layout) >= i+3 && layout[i:i+3] == "Z07" {
+				return layout[0:i], stdISO8601ShortTZ, layout[i+3:]
+			}
 
 		case '.': // .000 or .999 - repeated digits for fractional seconds.
 			if i+1 < len(layout) && (layout[i+1] == '0' || layout[i+1] == '9') {
@@ -518,7 +535,7 @@ func (t Time) AppendFormat(b []byte, layout string) []byte {
 		case stdZeroMinute:
 			b = appendInt(b, min, 2)
 		case stdSecond:
-			b = appendInt(b, sec, 2)
+			b = appendInt(b, sec, 0)
 		case stdZeroSecond:
 			b = appendInt(b, sec, 2)
 		case stdPM:
@@ -533,10 +550,10 @@ func (t Time) AppendFormat(b []byte, layout string) []byte {
 			} else {
 				b = append(b, "am"...)
 			}
-		case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumColonTZ, stdNumSecondsTz, stdNumColonSecondsTZ:
+		case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ShortTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumColonTZ, stdNumSecondsTz, stdNumShortTZ, stdNumColonSecondsTZ:
 			// Ugly special case.  We cheat and take the "Z" variants
 			// to mean "the time zone as formatted for ISO 8601".
-			if offset == 0 && (std == stdISO8601TZ || std == stdISO8601ColonTZ || std == stdISO8601SecondsTZ || std == stdISO8601ColonSecondsTZ) {
+			if offset == 0 && (std == stdISO8601TZ || std == stdISO8601ColonTZ || std == stdISO8601SecondsTZ || std == stdISO8601ShortTZ || std == stdISO8601ColonSecondsTZ) {
 				b = append(b, 'Z')
 				break
 			}
@@ -553,7 +570,9 @@ func (t Time) AppendFormat(b []byte, layout string) []byte {
 			if std == stdISO8601ColonTZ || std == stdNumColonTZ || std == stdISO8601ColonSecondsTZ || std == stdNumColonSecondsTZ {
 				b = append(b, ':')
 			}
-			b = appendInt(b, zone%60, 2)
+			if std != stdNumShortTZ && std != stdISO8601ShortTZ {
+				b = appendInt(b, zone%60, 2)
+			}
 
 			// append seconds if appropriate
 			if std == stdISO8601SecondsTZ || std == stdNumSecondsTz || std == stdNumColonSecondsTZ || std == stdISO8601ColonSecondsTZ {
@@ -696,6 +715,11 @@ func skip(value, prefix string) (string, error) {
 // location and zone in the returned time. Otherwise it records the time as
 // being in a fabricated location with time fixed at the given zone offset.
 //
+// No checking is done that the day of the month is within the month's
+// valid dates; any one- or two-digit value is accepted. For example
+// February 31 and even February 99 are valid dates, specifying dates
+// in March and May. This behavior is consistent with time.Date.
+//
 // When parsing a time with a zone abbreviation like MST, if the zone abbreviation
 // has a defined offset in the current location, then that offset is used.
 // The zone abbreviation "UTC" is recognized as UTC regardless of location.
@@ -794,7 +818,8 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
 				value = value[1:]
 			}
 			day, value, err = getnum(value, std == stdZeroDay)
-			if day < 0 || 31 < day {
+			if day < 0 {
+				// Note that we allow any one- or two-digit day here.
 				rangeErrString = "day"
 			}
 		case stdHour:
@@ -861,8 +886,8 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
 			default:
 				err = errBad
 			}
-		case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumShortTZ, stdNumColonTZ, stdNumSecondsTz, stdNumColonSecondsTZ:
-			if (std == stdISO8601TZ || std == stdISO8601ColonTZ) && len(value) >= 1 && value[0] == 'Z' {
+		case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ShortTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumShortTZ, stdNumColonTZ, stdNumSecondsTz, stdNumColonSecondsTZ:
+			if (std == stdISO8601TZ || std == stdISO8601ShortTZ || std == stdISO8601ColonTZ) && len(value) >= 1 && value[0] == 'Z' {
 				value = value[1:]
 				z = UTC
 				break
@@ -878,7 +903,7 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
 					break
 				}
 				sign, hour, min, seconds, value = value[0:1], value[1:3], value[4:6], "00", value[6:]
-			} else if std == stdNumShortTZ {
+			} else if std == stdNumShortTZ || std == stdISO8601ShortTZ {
 				if len(value) < 3 {
 					err = errBad
 					break
@@ -975,6 +1000,11 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error)
 		hour = 0
 	}
 
+	// Validate the day of the month.
+	if day > daysIn(Month(month), year) {
+		return Time{}, &ParseError{alayout, avalue, "", value, ": day out of range"}
+	}
+
 	if z != nil {
 		return Date(year, Month(month), day, hour, min, sec, nsec, z), nil
 	}
diff --git a/src/time/format_test.go b/src/time/format_test.go
index ecc5c8f..af950a7 100644
--- a/src/time/format_test.go
+++ b/src/time/format_test.go
@@ -74,6 +74,16 @@ func TestFormat(t *testing.T) {
 	}
 }
 
+// issue 12440.
+func TestFormatSingleDigits(t *testing.T) {
+	time := Date(2001, 2, 3, 4, 5, 6, 700000000, UTC)
+	test := FormatTest{"single digit format", "3:4:5", "4:5:6"}
+	result := time.Format(test.format)
+	if result != test.result {
+		t.Errorf("%s expected %q got %q", test.name, test.result, result)
+	}
+}
+
 func TestFormatShortYear(t *testing.T) {
 	years := []int{
 		-100001, -100000, -99999,
@@ -183,6 +193,57 @@ func TestParse(t *testing.T) {
 	}
 }
 
+// All parsed with ANSIC.
+var dayOutOfRangeTests = []struct {
+	date string
+	ok   bool
+}{
+	{"Thu Jan 99 21:00:57 2010", false},
+	{"Thu Jan 31 21:00:57 2010", true},
+	{"Thu Jan 32 21:00:57 2010", false},
+	{"Thu Feb 28 21:00:57 2012", true},
+	{"Thu Feb 29 21:00:57 2012", true},
+	{"Thu Feb 29 21:00:57 2010", false},
+	{"Thu Mar 31 21:00:57 2010", true},
+	{"Thu Mar 32 21:00:57 2010", false},
+	{"Thu Apr 30 21:00:57 2010", true},
+	{"Thu Apr 31 21:00:57 2010", false},
+	{"Thu May 31 21:00:57 2010", true},
+	{"Thu May 32 21:00:57 2010", false},
+	{"Thu Jun 30 21:00:57 2010", true},
+	{"Thu Jun 31 21:00:57 2010", false},
+	{"Thu Jul 31 21:00:57 2010", true},
+	{"Thu Jul 32 21:00:57 2010", false},
+	{"Thu Aug 31 21:00:57 2010", true},
+	{"Thu Aug 32 21:00:57 2010", false},
+	{"Thu Sep 30 21:00:57 2010", true},
+	{"Thu Sep 31 21:00:57 2010", false},
+	{"Thu Oct 31 21:00:57 2010", true},
+	{"Thu Oct 32 21:00:57 2010", false},
+	{"Thu Nov 30 21:00:57 2010", true},
+	{"Thu Nov 31 21:00:57 2010", false},
+	{"Thu Dec 31 21:00:57 2010", true},
+	{"Thu Dec 32 21:00:57 2010", false},
+}
+
+func TestParseDayOutOfRange(t *testing.T) {
+	for _, test := range dayOutOfRangeTests {
+		_, err := Parse(ANSIC, test.date)
+		switch {
+		case test.ok && err == nil:
+			// OK
+		case !test.ok && err != nil:
+			if !strings.Contains(err.Error(), "day out of range") {
+				t.Errorf("%q: expected 'day' error, got %v", test.date, err)
+			}
+		case test.ok && err != nil:
+			t.Errorf("%q: unexpected error: %v", test.date, err)
+		case !test.ok && err == nil:
+			t.Errorf("%q: expected 'day' error, got none", test.date)
+		}
+	}
+}
+
 func TestParseInLocation(t *testing.T) {
 	// Check that Parse (and ParseInLocation) understand that
 	// Feb 01 AST (Arabia Standard Time) and Feb 01 AST (Atlantic Standard Time)
@@ -491,6 +552,9 @@ var secondsTimeZoneOffsetTests = []SecondsTimeZoneOffsetTest{
 	{"2006-01-02T15:04:05-07:00:00", "1871-01-01T05:33:02+00:34:08", 34*60 + 8},
 	{"2006-01-02T15:04:05Z070000", "1871-01-01T05:33:02-003408", -(34*60 + 8)},
 	{"2006-01-02T15:04:05Z07:00:00", "1871-01-01T05:33:02+00:34:08", 34*60 + 8},
+	{"2006-01-02T15:04:05-07", "1871-01-01T05:33:02+01", 1 * 60 * 60},
+	{"2006-01-02T15:04:05-07", "1871-01-01T05:33:02-02", -2 * 60 * 60},
+	{"2006-01-02T15:04:05Z07", "1871-01-01T05:33:02-02", -2 * 60 * 60},
 }
 
 func TestParseSecondsInTimeZone(t *testing.T) {
@@ -516,3 +580,22 @@ func TestFormatSecondsInTimeZone(t *testing.T) {
 		}
 	}
 }
+
+// Issue 11334.
+func TestUnderscoreTwoThousand(t *testing.T) {
+	format := "15:04_20060102"
+	input := "14:38_20150618"
+	time, err := Parse(format, input)
+	if err != nil {
+		t.Error(err)
+	}
+	if y, m, d := time.Date(); y != 2015 || m != 6 || d != 18 {
+		t.Errorf("Incorrect y/m/d, got %d/%d/%d", y, m, d)
+	}
+	if h := time.Hour(); h != 14 {
+		t.Errorf("Incorrect hour, got %d", h)
+	}
+	if m := time.Minute(); m != 38 {
+		t.Errorf("Incorrect minute, got %d", m)
+	}
+}
diff --git a/src/time/time.go b/src/time/time.go
index 294cc77..ef4ba58 100644
--- a/src/time/time.go
+++ b/src/time/time.go
@@ -180,7 +180,7 @@ func (d Weekday) String() string { return days[d] }
 // everywhere.
 //
 // The calendar runs on an exact 400 year cycle: a 400-year calendar
-// printed for 1970-2469 will apply as well to 2470-2869.  Even the days
+// printed for 1970-2469 will apply as well to 2370-2769.  Even the days
 // of the week match up.  It simplifies the computations to choose the
 // cycle boundaries so that the exceptional years are always delayed as
 // long as possible.  That means choosing a year equal to 1 mod 400, so
@@ -935,7 +935,12 @@ func (t Time) MarshalJSON() ([]byte, error) {
 		// See golang.org/issue/4556#c15 for more discussion.
 		return nil, errors.New("Time.MarshalJSON: year outside of range [0,9999]")
 	}
-	return []byte(t.Format(`"` + RFC3339Nano + `"`)), nil
+
+	b := make([]byte, 0, len(RFC3339Nano)+2)
+	b = append(b, '"')
+	b = t.AppendFormat(b, RFC3339Nano)
+	b = append(b, '"')
+	return b, nil
 }
 
 // UnmarshalJSON implements the json.Unmarshaler interface.
@@ -952,7 +957,9 @@ func (t Time) MarshalText() ([]byte, error) {
 	if y := t.Year(); y < 0 || y >= 10000 {
 		return nil, errors.New("Time.MarshalText: year outside of range [0,9999]")
 	}
-	return []byte(t.Format(RFC3339Nano)), nil
+
+	b := make([]byte, 0, len(RFC3339Nano))
+	return t.AppendFormat(b, RFC3339Nano), nil
 }
 
 // UnmarshalText implements the encoding.TextUnmarshaler interface.
diff --git a/src/time/time_test.go b/src/time/time_test.go
index 2d16ea5..a925e98 100644
--- a/src/time/time_test.go
+++ b/src/time/time_test.go
@@ -1060,6 +1060,20 @@ func BenchmarkFormatNow(b *testing.B) {
 	}
 }
 
+func BenchmarkMarshalJSON(b *testing.B) {
+	t := Now()
+	for i := 0; i < b.N; i++ {
+		t.MarshalJSON()
+	}
+}
+
+func BenchmarkMarshalText(b *testing.B) {
+	t := Now()
+	for i := 0; i < b.N; i++ {
+		t.MarshalText()
+	}
+}
+
 func BenchmarkParse(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 		Parse(ANSIC, "Mon Jan  2 15:04:05 2006")
diff --git a/src/time/zoneinfo.go b/src/time/zoneinfo.go
index c8e53a2..c567439 100644
--- a/src/time/zoneinfo.go
+++ b/src/time/zoneinfo.go
@@ -21,7 +21,7 @@ type Location struct {
 	// To avoid the binary search through tx, keep a
 	// static one-element cache that gives the correct
 	// zone for the time when the Location was created.
-	// if cacheStart <= t <= cacheEnd,
+	// if cacheStart <= t < cacheEnd,
 	// lookup can return cacheZone.
 	// The units for cacheStart and cacheEnd are seconds
 	// since January 1, 1970 UTC, to match the argument
diff --git a/src/time/zoneinfo_windows.go b/src/time/zoneinfo_windows.go
index d04ebec..bcb8ccd 100644
--- a/src/time/zoneinfo_windows.go
+++ b/src/time/zoneinfo_windows.go
@@ -20,8 +20,9 @@ import (
 // The implementation assumes that this year's rules for daylight savings
 // time apply to all previous and future years as well.
 
-// matchZoneKey checks if stdname and dstname match the corresponding "Std"
-// and "Dlt" key values in the kname key stored under the open registry key zones.
+// matchZoneKey checks if stdname and dstname match the corresponding key
+// values "MUI_Std" and MUI_Dlt" or "Std" and "Dlt" (the latter down-level
+// from Vista) in the kname key stored under the open registry key zones.
 func matchZoneKey(zones registry.Key, kname string, stdname, dstname string) (matched bool, err2 error) {
 	k, err := registry.OpenKey(zones, kname, registry.READ)
 	if err != nil {
@@ -29,18 +30,27 @@ func matchZoneKey(zones registry.Key, kname string, stdname, dstname string) (ma
 	}
 	defer k.Close()
 
-	s, _, err := k.GetStringValue("Std")
-	if err != nil {
-		return false, err
+	var std, dlt string
+	if err = registry.LoadRegLoadMUIString(); err == nil {
+		// Try MUI_Std and MUI_Dlt first, fallback to Std and Dlt if *any* error occurs
+		std, err = k.GetMUIStringValue("MUI_Std")
+		if err == nil {
+			dlt, err = k.GetMUIStringValue("MUI_Dlt")
+		}
 	}
-	if s != stdname {
-		return false, nil
+	if err != nil { // Fallback to Std and Dlt
+		if std, _, err = k.GetStringValue("Std"); err != nil {
+			return false, err
+		}
+		if dlt, _, err = k.GetStringValue("Dlt"); err != nil {
+			return false, err
+		}
 	}
-	s, _, err = k.GetStringValue("Dlt")
-	if err != nil {
-		return false, err
+
+	if std != stdname {
+		return false, nil
 	}
-	if s != dstname && dstname != stdname {
+	if dlt != dstname && dstname != stdname {
 		return false, nil
 	}
 	return true, nil
diff --git a/src/time/zoneinfo_windows_test.go b/src/time/zoneinfo_windows_test.go
index 5f1141d..7ac1e86 100644
--- a/src/time/zoneinfo_windows_test.go
+++ b/src/time/zoneinfo_windows_test.go
@@ -42,14 +42,24 @@ func TestToEnglishName(t *testing.T) {
 		t.Fatalf("cannot open CEST time zone information from registry: %s", err)
 	}
 	defer k.Close()
-	std, _, err := k.GetStringValue("Std")
-	if err != nil {
-		t.Fatalf("cannot read CEST Std registry key: %s", err)
+
+	var std, dlt string
+	if err = registry.LoadRegLoadMUIString(); err == nil {
+		// Try MUI_Std and MUI_Dlt first, fallback to Std and Dlt if *any* error occurs
+		std, err = k.GetMUIStringValue("MUI_Std")
+		if err == nil {
+			dlt, err = k.GetMUIStringValue("MUI_Dlt")
+		}
 	}
-	dlt, _, err := k.GetStringValue("Dlt")
-	if err != nil {
-		t.Fatalf("cannot read CEST Dlt registry key: %s", err)
+	if err != nil { // Fallback to Std and Dlt
+		if std, _, err = k.GetStringValue("Std"); err != nil {
+			t.Fatalf("cannot read CEST Std registry key: %s", err)
+		}
+		if dlt, _, err = k.GetStringValue("Dlt"); err != nil {
+			t.Fatalf("cannot read CEST Dlt registry key: %s", err)
+		}
 	}
+
 	name, err := ToEnglishName(std, dlt)
 	if err != nil {
 		t.Fatalf("toEnglishName failed: %s", err)
diff --git a/src/unicode/example_test.go b/src/unicode/example_test.go
new file mode 100644
index 0000000..50c5b18
--- /dev/null
+++ b/src/unicode/example_test.go
@@ -0,0 +1,196 @@
+// Copyright 2015 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 unicode_test
+
+import (
+	"fmt"
+	"unicode"
+)
+
+// Functions starting with "Is" can be used to inspect which table of range a
+// rune belongs to. Note that runes may fit into more than one range.
+func Example_is() {
+
+	// constant with mixed type runes
+	const mixed = "\b5Ὂg̀9! ℃ᾭG"
+	for _, c := range mixed {
+		fmt.Printf("For %q:\n", c)
+		if unicode.IsControl(c) {
+			fmt.Println("\tis control rune")
+		}
+		if unicode.IsDigit(c) {
+			fmt.Println("\tis digit rune")
+		}
+		if unicode.IsGraphic(c) {
+			fmt.Println("\tis graphic rune")
+		}
+		if unicode.IsLetter(c) {
+			fmt.Println("\tis letter rune")
+		}
+		if unicode.IsLower(c) {
+			fmt.Println("\tis lower case rune")
+		}
+		if unicode.IsMark(c) {
+			fmt.Println("\tis mark rune")
+		}
+		if unicode.IsNumber(c) {
+			fmt.Println("\tis number rune")
+		}
+		if unicode.IsPrint(c) {
+			fmt.Println("\tis printable rune")
+		}
+		if !unicode.IsPrint(c) {
+			fmt.Println("\tis not printable rune")
+		}
+		if unicode.IsPunct(c) {
+			fmt.Println("\tis punct rune")
+		}
+		if unicode.IsSpace(c) {
+			fmt.Println("\tis space rune")
+		}
+		if unicode.IsSymbol(c) {
+			fmt.Println("\tis symbol rune")
+		}
+		if unicode.IsTitle(c) {
+			fmt.Println("\tis title case rune")
+		}
+		if unicode.IsUpper(c) {
+			fmt.Println("\tis upper case rune")
+		}
+	}
+
+	// Output:
+	// For '\b':
+	// 	is control rune
+	// 	is not printable rune
+	// For '5':
+	// 	is digit rune
+	// 	is graphic rune
+	// 	is number rune
+	// 	is printable rune
+	// For 'Ὂ':
+	// 	is graphic rune
+	// 	is letter rune
+	// 	is printable rune
+	// 	is upper case rune
+	// For 'g':
+	// 	is graphic rune
+	// 	is letter rune
+	// 	is lower case rune
+	// 	is printable rune
+	// For '̀':
+	// 	is graphic rune
+	// 	is mark rune
+	// 	is printable rune
+	// For '9':
+	// 	is digit rune
+	// 	is graphic rune
+	// 	is number rune
+	// 	is printable rune
+	// For '!':
+	// 	is graphic rune
+	// 	is printable rune
+	// 	is punct rune
+	// For ' ':
+	// 	is graphic rune
+	// 	is printable rune
+	// 	is space rune
+	// For '℃':
+	// 	is graphic rune
+	// 	is printable rune
+	// 	is symbol rune
+	// For 'ᾭ':
+	// 	is graphic rune
+	// 	is letter rune
+	// 	is printable rune
+	// 	is title case rune
+	// For 'G':
+	// 	is graphic rune
+	// 	is letter rune
+	// 	is printable rune
+	// 	is upper case rune
+}
+
+func ExampleSimpleFold() {
+	fmt.Printf("%#U\n", unicode.SimpleFold('A'))      // 'a'
+	fmt.Printf("%#U\n", unicode.SimpleFold('a'))      // 'A'
+	fmt.Printf("%#U\n", unicode.SimpleFold('K'))      // 'k'
+	fmt.Printf("%#U\n", unicode.SimpleFold('k'))      // '\u212A' (Kelvin symbol, K)
+	fmt.Printf("%#U\n", unicode.SimpleFold('\u212A')) // 'K'
+	fmt.Printf("%#U\n", unicode.SimpleFold('1'))      // '1'
+
+	// Output:
+	// U+0061 'a'
+	// U+0041 'A'
+	// U+006B 'k'
+	// U+212A 'K'
+	// U+004B 'K'
+	// U+0031 '1'
+}
+
+func ExampleTo() {
+	const lcG = 'g'
+	fmt.Printf("%#U\n", unicode.To(unicode.UpperCase, lcG))
+	fmt.Printf("%#U\n", unicode.To(unicode.LowerCase, lcG))
+	fmt.Printf("%#U\n", unicode.To(unicode.TitleCase, lcG))
+
+	const ucG = 'G'
+	fmt.Printf("%#U\n", unicode.To(unicode.UpperCase, ucG))
+	fmt.Printf("%#U\n", unicode.To(unicode.LowerCase, ucG))
+	fmt.Printf("%#U\n", unicode.To(unicode.TitleCase, ucG))
+
+	// Output:
+	// U+0047 'G'
+	// U+0067 'g'
+	// U+0047 'G'
+	// U+0047 'G'
+	// U+0067 'g'
+	// U+0047 'G'
+}
+
+func ExampleToLower() {
+	const ucG = 'G'
+	fmt.Printf("%#U\n", unicode.ToLower(ucG))
+
+	// Output:
+	// U+0067 'g'
+}
+func ExampleToTitle() {
+	const ucG = 'g'
+	fmt.Printf("%#U\n", unicode.ToTitle(ucG))
+
+	// Output:
+	// U+0047 'G'
+}
+
+func ExampleToUpper() {
+	const ucG = 'g'
+	fmt.Printf("%#U\n", unicode.ToUpper(ucG))
+
+	// Output:
+	// U+0047 'G'
+}
+
+func ExampleSpecialCase() {
+	t := unicode.TurkishCase
+
+	const lci = 'i'
+	fmt.Printf("%#U\n", t.ToLower(lci))
+	fmt.Printf("%#U\n", t.ToTitle(lci))
+	fmt.Printf("%#U\n", t.ToUpper(lci))
+
+	const uci = 'İ'
+	fmt.Printf("%#U\n", t.ToLower(uci))
+	fmt.Printf("%#U\n", t.ToTitle(uci))
+	fmt.Printf("%#U\n", t.ToUpper(uci))
+
+	// Output:
+	// U+0069 'i'
+	// U+0130 'İ'
+	// U+0130 'İ'
+	// U+0069 'i'
+	// U+0130 'İ'
+	// U+0130 'İ'
+}
diff --git a/src/unicode/maketables.go b/src/unicode/maketables.go
index 9fccdec..e0110c9 100644
--- a/src/unicode/maketables.go
+++ b/src/unicode/maketables.go
@@ -261,9 +261,6 @@ func parseCategory(line string) (state State) {
 		logger.Fatalf("%.5s...: %s", line, err)
 	}
 	lastChar = rune(point)
-	if point == 0 {
-		return // not interesting and we use 0 as unset
-	}
 	if point > MaxChar {
 		return
 	}
diff --git a/src/unicode/tables.go b/src/unicode/tables.go
index 370a9d1..8bb4206 100644
--- a/src/unicode/tables.go
+++ b/src/unicode/tables.go
@@ -53,7 +53,7 @@ var Categories = map[string]*RangeTable{
 
 var _C = &RangeTable{
 	R16: []Range16{
-		{0x0001, 0x001f, 1},
+		{0x0000, 0x001f, 1},
 		{0x007f, 0x009f, 1},
 		{0x00ad, 0x0600, 1363},
 		{0x0601, 0x0605, 1},
@@ -81,7 +81,7 @@ var _C = &RangeTable{
 
 var _Cc = &RangeTable{
 	R16: []Range16{
-		{0x0001, 0x001f, 1},
+		{0x0000, 0x001f, 1},
 		{0x007f, 0x009f, 1},
 	},
 	LatinOffset: 2,
diff --git a/src/unicode/utf8/utf8.go b/src/unicode/utf8/utf8.go
index 9ac3718..bbaf14a 100644
--- a/src/unicode/utf8/utf8.go
+++ b/src/unicode/utf8/utf8.go
@@ -40,206 +40,208 @@ const (
 	rune1Max = 1<<7 - 1
 	rune2Max = 1<<11 - 1
 	rune3Max = 1<<16 - 1
-)
-
-func decodeRuneInternal(p []byte) (r rune, size int, short bool) {
-	n := len(p)
-	if n < 1 {
-		return RuneError, 0, true
-	}
-	c0 := p[0]
-
-	// 1-byte, 7-bit sequence?
-	if c0 < tx {
-		return rune(c0), 1, false
-	}
-
-	// unexpected continuation byte?
-	if c0 < t2 {
-		return RuneError, 1, false
-	}
-
-	// need first continuation byte
-	if n < 2 {
-		return RuneError, 1, true
-	}
-	c1 := p[1]
-	if c1 < tx || t2 <= c1 {
-		return RuneError, 1, false
-	}
-
-	// 2-byte, 11-bit sequence?
-	if c0 < t3 {
-		r = rune(c0&mask2)<<6 | rune(c1&maskx)
-		if r <= rune1Max {
-			return RuneError, 1, false
-		}
-		return r, 2, false
-	}
 
-	// need second continuation byte
-	if n < 3 {
-		return RuneError, 1, true
-	}
-	c2 := p[2]
-	if c2 < tx || t2 <= c2 {
-		return RuneError, 1, false
-	}
-
-	// 3-byte, 16-bit sequence?
-	if c0 < t4 {
-		r = rune(c0&mask3)<<12 | rune(c1&maskx)<<6 | rune(c2&maskx)
-		if r <= rune2Max {
-			return RuneError, 1, false
-		}
-		if surrogateMin <= r && r <= surrogateMax {
-			return RuneError, 1, false
-		}
-		return r, 3, false
-	}
-
-	// need third continuation byte
-	if n < 4 {
-		return RuneError, 1, true
-	}
-	c3 := p[3]
-	if c3 < tx || t2 <= c3 {
-		return RuneError, 1, false
-	}
-
-	// 4-byte, 21-bit sequence?
-	if c0 < t5 {
-		r = rune(c0&mask4)<<18 | rune(c1&maskx)<<12 | rune(c2&maskx)<<6 | rune(c3&maskx)
-		if r <= rune3Max || MaxRune < r {
-			return RuneError, 1, false
-		}
-		return r, 4, false
-	}
+	// The default lowest and highest continuation byte.
+	locb = 0x80 // 1000 0000
+	hicb = 0xBF // 1011 1111
+
+	// These names of these constants are chosen to give nice alignment in the
+	// table below. The first nibble is an index into acceptRanges or F for
+	// special one-byte cases. The second nibble is the Rune length or the
+	// Status for the special one-byte case.
+	xx = 0xF1 // invalid: size 1
+	as = 0xF0 // ASCII: size 1
+	s1 = 0x02 // accept 0, size 2
+	s2 = 0x13 // accept 1, size 3
+	s3 = 0x03 // accept 0, size 3
+	s4 = 0x23 // accept 2, size 3
+	s5 = 0x34 // accept 3, size 4
+	s6 = 0x04 // accept 0, size 4
+	s7 = 0x44 // accept 4, size 4
+)
 
-	// error
-	return RuneError, 1, false
+// first is information about the first byte in a UTF-8 sequence.
+var first = [256]uint8{
+	//   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+	as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x00-0x0F
+	as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x10-0x1F
+	as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x20-0x2F
+	as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x30-0x3F
+	as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x40-0x4F
+	as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x50-0x5F
+	as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x60-0x6F
+	as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x70-0x7F
+	//   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+	xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x80-0x8F
+	xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x90-0x9F
+	xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xA0-0xAF
+	xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xB0-0xBF
+	xx, xx, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xC0-0xCF
+	s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xD0-0xDF
+	s2, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s4, s3, s3, // 0xE0-0xEF
+	s5, s6, s6, s6, s7, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xF0-0xFF
 }
 
-func decodeRuneInStringInternal(s string) (r rune, size int, short bool) {
-	n := len(s)
-	if n < 1 {
-		return RuneError, 0, true
-	}
-	c0 := s[0]
-
-	// 1-byte, 7-bit sequence?
-	if c0 < tx {
-		return rune(c0), 1, false
-	}
-
-	// unexpected continuation byte?
-	if c0 < t2 {
-		return RuneError, 1, false
-	}
-
-	// need first continuation byte
-	if n < 2 {
-		return RuneError, 1, true
-	}
-	c1 := s[1]
-	if c1 < tx || t2 <= c1 {
-		return RuneError, 1, false
-	}
-
-	// 2-byte, 11-bit sequence?
-	if c0 < t3 {
-		r = rune(c0&mask2)<<6 | rune(c1&maskx)
-		if r <= rune1Max {
-			return RuneError, 1, false
-		}
-		return r, 2, false
-	}
-
-	// need second continuation byte
-	if n < 3 {
-		return RuneError, 1, true
-	}
-	c2 := s[2]
-	if c2 < tx || t2 <= c2 {
-		return RuneError, 1, false
-	}
-
-	// 3-byte, 16-bit sequence?
-	if c0 < t4 {
-		r = rune(c0&mask3)<<12 | rune(c1&maskx)<<6 | rune(c2&maskx)
-		if r <= rune2Max {
-			return RuneError, 1, false
-		}
-		if surrogateMin <= r && r <= surrogateMax {
-			return RuneError, 1, false
-		}
-		return r, 3, false
-	}
-
-	// need third continuation byte
-	if n < 4 {
-		return RuneError, 1, true
-	}
-	c3 := s[3]
-	if c3 < tx || t2 <= c3 {
-		return RuneError, 1, false
-	}
-
-	// 4-byte, 21-bit sequence?
-	if c0 < t5 {
-		r = rune(c0&mask4)<<18 | rune(c1&maskx)<<12 | rune(c2&maskx)<<6 | rune(c3&maskx)
-		if r <= rune3Max || MaxRune < r {
-			return RuneError, 1, false
-		}
-		return r, 4, false
-	}
+// acceptRange gives the range of valid values for the second byte in a UTF-8
+// sequence.
+type acceptRange struct {
+	lo uint8 // lowest value for second byte.
+	hi uint8 // highest value for second byte.
+}
 
-	// error
-	return RuneError, 1, false
+var acceptRanges = [...]acceptRange{
+	0: {locb, hicb},
+	1: {0xA0, hicb},
+	2: {locb, 0x9F},
+	3: {0x90, hicb},
+	4: {locb, 0x8F},
 }
 
 // FullRune reports whether the bytes in p begin with a full UTF-8 encoding of a rune.
 // An invalid encoding is considered a full Rune since it will convert as a width-1 error rune.
 func FullRune(p []byte) bool {
-	_, _, short := decodeRuneInternal(p)
-	return !short
+	n := len(p)
+	if n == 0 {
+		return false
+	}
+	x := first[p[0]]
+	if n >= int(x&7) {
+		return true // ASCII, invalid or valid.
+	}
+	// Must be short or invalid.
+	accept := acceptRanges[x>>4]
+	if n > 1 {
+		if c := p[1]; c < accept.lo || accept.hi < c {
+			return true
+		} else if n > 2 && (p[2] < locb || hicb < p[2]) {
+			return true
+		}
+	}
+	return false
 }
 
 // FullRuneInString is like FullRune but its input is a string.
 func FullRuneInString(s string) bool {
-	_, _, short := decodeRuneInStringInternal(s)
-	return !short
+	n := len(s)
+	if n == 0 {
+		return false
+	}
+	x := first[s[0]]
+	if n >= int(x&7) {
+		return true // ASCII, invalid, or valid.
+	}
+	// Must be short or invalid.
+	accept := acceptRanges[x>>4]
+	if n > 1 {
+		if c := s[1]; c < accept.lo || accept.hi < c {
+			return true
+		} else if n > 2 && (s[2] < locb || hicb < s[2]) {
+			return true
+		}
+	}
+	return false
 }
 
 // DecodeRune unpacks the first UTF-8 encoding in p and returns the rune and
 // its width in bytes. If p is empty it returns (RuneError, 0). Otherwise, if
 // the encoding is invalid, it returns (RuneError, 1). Both are impossible
-// results for correct UTF-8.
+// results for correct, non-empty UTF-8.
 //
 // An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
 // out of range, or is not the shortest possible UTF-8 encoding for the
 // value. No other validation is performed.
 func DecodeRune(p []byte) (r rune, size int) {
-	r, size, _ = decodeRuneInternal(p)
-	return
+	n := len(p)
+	if n < 1 {
+		return RuneError, 0
+	}
+	p0 := p[0]
+	x := first[p0]
+	if x >= as {
+		// The following code simulates an additional check for x == xx and
+		// handling the ASCII and invalid cases accordingly. This mask-and-or
+		// approach prevents an additional branch.
+		mask := rune(x) << 31 >> 31 // Create 0x0000 or 0xFFFF.
+		return rune(p[0])&^mask | RuneError&mask, 1
+	}
+	sz := x & 7
+	accept := acceptRanges[x>>4]
+	if n < int(sz) {
+		return RuneError, 1
+	}
+	b1 := p[1]
+	if b1 < accept.lo || accept.hi < b1 {
+		return RuneError, 1
+	}
+	if sz == 2 {
+		return rune(p0&mask2)<<6 | rune(b1&maskx), 2
+	}
+	b2 := p[2]
+	if b2 < locb || hicb < b2 {
+		return RuneError, 1
+	}
+	if sz == 3 {
+		return rune(p0&mask3)<<12 | rune(b1&maskx)<<6 | rune(b2&maskx), 3
+	}
+	b3 := p[3]
+	if b3 < locb || hicb < b3 {
+		return RuneError, 1
+	}
+	return rune(p0&mask4)<<18 | rune(b1&maskx)<<12 | rune(b2&maskx)<<6 | rune(b3&maskx), 4
 }
 
 // DecodeRuneInString is like DecodeRune but its input is a string. If s is
 // empty it returns (RuneError, 0). Otherwise, if the encoding is invalid, it
-// returns (RuneError, 1). Both are impossible results for correct UTF-8.
+// returns (RuneError, 1). Both are impossible results for correct, non-empty
+// UTF-8.
 //
 // An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
 // out of range, or is not the shortest possible UTF-8 encoding for the
 // value. No other validation is performed.
 func DecodeRuneInString(s string) (r rune, size int) {
-	r, size, _ = decodeRuneInStringInternal(s)
-	return
+	n := len(s)
+	if n < 1 {
+		return RuneError, 0
+	}
+	s0 := s[0]
+	x := first[s0]
+	if x >= as {
+		// The following code simulates an additional check for x == xx and
+		// handling the ASCII and invalid cases accordingly. This mask-and-or
+		// approach prevents an additional branch.
+		mask := rune(x) << 31 >> 31 // Create 0x0000 or 0xFFFF.
+		return rune(s[0])&^mask | RuneError&mask, 1
+	}
+	sz := x & 7
+	accept := acceptRanges[x>>4]
+	if n < int(sz) {
+		return RuneError, 1
+	}
+	s1 := s[1]
+	if s1 < accept.lo || accept.hi < s1 {
+		return RuneError, 1
+	}
+	if sz == 2 {
+		return rune(s0&mask2)<<6 | rune(s1&maskx), 2
+	}
+	s2 := s[2]
+	if s2 < locb || hicb < s2 {
+		return RuneError, 1
+	}
+	if sz == 3 {
+		return rune(s0&mask3)<<12 | rune(s1&maskx)<<6 | rune(s2&maskx), 3
+	}
+	s3 := s[3]
+	if s3 < locb || hicb < s3 {
+		return RuneError, 1
+	}
+	return rune(s0&mask4)<<18 | rune(s1&maskx)<<12 | rune(s2&maskx)<<6 | rune(s3&maskx), 4
 }
 
 // DecodeLastRune unpacks the last UTF-8 encoding in p and returns the rune and
 // its width in bytes. If p is empty it returns (RuneError, 0). Otherwise, if
 // the encoding is invalid, it returns (RuneError, 1). Both are impossible
-// results for correct UTF-8.
+// results for correct, non-empty UTF-8.
 //
 // An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
 // out of range, or is not the shortest possible UTF-8 encoding for the
@@ -278,7 +280,8 @@ func DecodeLastRune(p []byte) (r rune, size int) {
 
 // DecodeLastRuneInString is like DecodeLastRune but its input is a string. If
 // s is empty it returns (RuneError, 0). Otherwise, if the encoding is invalid,
-// it returns (RuneError, 1). Both are impossible results for correct UTF-8.
+// it returns (RuneError, 1). Both are impossible results for correct,
+// non-empty UTF-8.
 //
 // An encoding is invalid if it is incorrect UTF-8, encodes a rune that is
 // out of range, or is not the shortest possible UTF-8 encoding for the
@@ -367,65 +370,141 @@ func EncodeRune(p []byte, r rune) int {
 // RuneCount returns the number of runes in p.  Erroneous and short
 // encodings are treated as single runes of width 1 byte.
 func RuneCount(p []byte) int {
-	i := 0
+	np := len(p)
 	var n int
-	for n = 0; i < len(p); n++ {
-		if p[i] < RuneSelf {
+	for i := 0; i < np; {
+		n++
+		c := p[i]
+		if c < RuneSelf {
+			// ASCII fast path
 			i++
-		} else {
-			_, size := DecodeRune(p[i:])
-			i += size
+			continue
+		}
+		x := first[c]
+		if x == xx {
+			i++ // invalid.
+			continue
+		}
+		size := int(x & 7)
+		if i+size > np {
+			i++ // Short or invalid.
+			continue
 		}
+		accept := acceptRanges[x>>4]
+		if c := p[i+1]; c < accept.lo || accept.hi < c {
+			size = 1
+		} else if size == 2 {
+		} else if c := p[i+2]; c < locb || hicb < c {
+			size = 1
+		} else if size == 3 {
+		} else if c := p[i+3]; c < locb || hicb < c {
+			size = 1
+		}
+		i += size
 	}
 	return n
 }
 
 // RuneCountInString is like RuneCount but its input is a string.
 func RuneCountInString(s string) (n int) {
-	for range s {
-		n++
+	ns := len(s)
+	for i := 0; i < ns; n++ {
+		c := s[i]
+		if c < RuneSelf {
+			// ASCII fast path
+			i++
+			continue
+		}
+		x := first[c]
+		if x == xx {
+			i++ // invalid.
+			continue
+		}
+		size := int(x & 7)
+		if i+size > ns {
+			i++ // Short or invalid.
+			continue
+		}
+		accept := acceptRanges[x>>4]
+		if c := s[i+1]; c < accept.lo || accept.hi < c {
+			size = 1
+		} else if size == 2 {
+		} else if c := s[i+2]; c < locb || hicb < c {
+			size = 1
+		} else if size == 3 {
+		} else if c := s[i+3]; c < locb || hicb < c {
+			size = 1
+		}
+		i += size
 	}
-	return
+	return n
 }
 
-// RuneStart reports whether the byte could be the first byte of
-// an encoded rune.  Second and subsequent bytes always have the top
-// two bits set to 10.
+// RuneStart reports whether the byte could be the first byte of an encoded,
+// possibly invalid rune.  Second and subsequent bytes always have the top two
+// bits set to 10.
 func RuneStart(b byte) bool { return b&0xC0 != 0x80 }
 
 // Valid reports whether p consists entirely of valid UTF-8-encoded runes.
 func Valid(p []byte) bool {
-	i := 0
-	for i < len(p) {
-		if p[i] < RuneSelf {
+	n := len(p)
+	for i := 0; i < n; {
+		pi := p[i]
+		if pi < RuneSelf {
 			i++
-		} else {
-			_, size := DecodeRune(p[i:])
-			if size == 1 {
-				// All valid runes of size 1 (those
-				// below RuneSelf) were handled above.
-				// This must be a RuneError.
-				return false
-			}
-			i += size
+			continue
+		}
+		x := first[pi]
+		if x == xx {
+			return false // Illegal starter byte.
 		}
+		size := int(x & 7)
+		if i+size > n {
+			return false // Short or invalid.
+		}
+		accept := acceptRanges[x>>4]
+		if c := p[i+1]; c < accept.lo || accept.hi < c {
+			return false
+		} else if size == 2 {
+		} else if c := p[i+2]; c < locb || hicb < c {
+			return false
+		} else if size == 3 {
+		} else if c := p[i+3]; c < locb || hicb < c {
+			return false
+		}
+		i += size
 	}
 	return true
 }
 
 // ValidString reports whether s consists entirely of valid UTF-8-encoded runes.
 func ValidString(s string) bool {
-	for i, r := range s {
-		if r == RuneError {
-			// The RuneError value can be an error
-			// sentinel value (if it's size 1) or the same
-			// value encoded properly. Decode it to see if
-			// it's the 1 byte sentinel value.
-			_, size := DecodeRuneInString(s[i:])
-			if size == 1 {
-				return false
-			}
+	n := len(s)
+	for i := 0; i < n; {
+		si := s[i]
+		if si < RuneSelf {
+			i++
+			continue
+		}
+		x := first[si]
+		if x == xx {
+			return false // Illegal starter byte.
+		}
+		size := int(x & 7)
+		if i+size > n {
+			return false // Short or invalid.
+		}
+		accept := acceptRanges[x>>4]
+		if c := s[i+1]; c < accept.lo || accept.hi < c {
+			return false
+		} else if size == 2 {
+		} else if c := s[i+2]; c < locb || hicb < c {
+			return false
+		} else if size == 3 {
+		} else if c := s[i+3]; c < locb || hicb < c {
+			return false
 		}
+		i += size
 	}
 	return true
 }
diff --git a/src/unicode/utf8/utf8_test.go b/src/unicode/utf8/utf8_test.go
index 758d7a0..51571b6 100644
--- a/src/unicode/utf8/utf8_test.go
+++ b/src/unicode/utf8/utf8_test.go
@@ -100,6 +100,15 @@ func TestFullRune(t *testing.T) {
 			t.Errorf("FullRune(%q) = true, want false", s1)
 		}
 	}
+	for _, s := range []string{"\xc0", "\xc1"} {
+		b := []byte(s)
+		if !FullRune(b) {
+			t.Errorf("FullRune(%q) = false, want true", s)
+		}
+		if !FullRuneInString(s) {
+			t.Errorf("FullRuneInString(%q) = false, want true", s)
+		}
+	}
 }
 
 func TestEncodeRune(t *testing.T) {
@@ -300,6 +309,8 @@ var runecounttests = []RuneCountTest{
 	{"☺☻☹", 3},
 	{"1,2,3,4", 7},
 	{"\xe2\x00", 2},
+	{"\xe2\x80", 2},
+	{"a\xe2\x80", 3},
 }
 
 func TestRuneCount(t *testing.T) {
@@ -352,6 +363,7 @@ var validTests = []ValidTest{
 	{"ЖЖ", true},
 	{"брэд-ЛГТМ", true},
 	{"☺☻☹", true},
+	{"aa\xe2", false},
 	{string([]byte{66, 250}), false},
 	{string([]byte{66, 250, 67}), false},
 	{"a\uFFFDb", true},
@@ -404,17 +416,57 @@ func TestValidRune(t *testing.T) {
 }
 
 func BenchmarkRuneCountTenASCIIChars(b *testing.B) {
+	s := []byte("0123456789")
 	for i := 0; i < b.N; i++ {
-		RuneCountInString("0123456789")
+		RuneCount(s)
 	}
 }
 
 func BenchmarkRuneCountTenJapaneseChars(b *testing.B) {
+	s := []byte("日本語日本語日本語日")
+	for i := 0; i < b.N; i++ {
+		RuneCount(s)
+	}
+}
+
+func BenchmarkRuneCountInStringTenASCIIChars(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		RuneCountInString("0123456789")
+	}
+}
+
+func BenchmarkRuneCountInStringTenJapaneseChars(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 		RuneCountInString("日本語日本語日本語日")
 	}
 }
 
+func BenchmarkValidTenASCIIChars(b *testing.B) {
+	s := []byte("0123456789")
+	for i := 0; i < b.N; i++ {
+		Valid(s)
+	}
+}
+
+func BenchmarkValidTenJapaneseChars(b *testing.B) {
+	s := []byte("日本語日本語日本語日")
+	for i := 0; i < b.N; i++ {
+		Valid(s)
+	}
+}
+
+func BenchmarkValidStringTenASCIIChars(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ValidString("0123456789")
+	}
+}
+
+func BenchmarkValidStringTenJapaneseChars(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		ValidString("日本語日本語日本語日")
+	}
+}
+
 func BenchmarkEncodeASCIIRune(b *testing.B) {
 	buf := make([]byte, UTFMax)
 	for i := 0; i < b.N; i++ {
@@ -442,3 +494,17 @@ func BenchmarkDecodeJapaneseRune(b *testing.B) {
 		DecodeRune(nihon)
 	}
 }
+
+func BenchmarkFullASCIIRune(b *testing.B) {
+	a := []byte{'a'}
+	for i := 0; i < b.N; i++ {
+		FullRune(a)
+	}
+}
+
+func BenchmarkFullJapaneseRune(b *testing.B) {
+	nihon := []byte("本")
+	for i := 0; i < b.N; i++ {
+		FullRune(nihon)
+	}
+}
diff --git a/src/unsafe/unsafe.go b/src/unsafe/unsafe.go
index 752792f..532fa4a 100644
--- a/src/unsafe/unsafe.go
+++ b/src/unsafe/unsafe.go
@@ -15,13 +15,160 @@ package unsafe
 type ArbitraryType int
 
 // Pointer represents a pointer to an arbitrary type.  There are four special operations
-// available for type Pointer that are not available for other types.
-//	1) A pointer value of any type can be converted to a Pointer.
-//	2) A Pointer can be converted to a pointer value of any type.
-//	3) A uintptr can be converted to a Pointer.
-//	4) A Pointer can be converted to a uintptr.
+// available for type Pointer that are not available for other types:
+//	- A pointer value of any type can be converted to a Pointer.
+//	- A Pointer can be converted to a pointer value of any type.
+//	- A uintptr can be converted to a Pointer.
+//	- A Pointer can be converted to a uintptr.
 // Pointer therefore allows a program to defeat the type system and read and write
 // arbitrary memory. It should be used with extreme care.
+//
+// The following patterns involving Pointer are valid.
+// Code not using these patterns is likely to be invalid today
+// or to become invalid in the future.
+// Even the valid patterns below come with important caveats.
+//
+// Running "go vet" can help find uses of Pointer that do not conform to these patterns,
+// but silence from "go vet" is not a guarantee that the code is valid.
+//
+// (1) Conversion of a *T1 to Pointer to *T2.
+//
+// Provided that T2 is no larger than T1 and that the two share an equivalent
+// memory layout, this conversion allows reinterpreting data of one type as
+// data of another type. An example is the implementation of
+// math.Float64bits:
+//
+//	func Float64bits(f float64) uint64 {
+//		return *(*uint64)(unsafe.Pointer(&f))
+//	}
+//
+// (2) Conversion of a Pointer to a uintptr (but not back to Pointer).
+//
+// Converting a Pointer to a uintptr produces the memory address of the value
+// pointed at, as an integer. The usual use for such a uintptr is to print it.
+//
+// Conversion of a uintptr back to Pointer is not valid in general.
+//
+// A uintptr is an integer, not a reference.
+// Converting a Pointer to a uintptr creates an integer value
+// with no pointer semantics.
+// Even if a uintptr holds the address of some object,
+// the garbage collector will not update that uintptr's value
+// if the object moves, nor will that uintptr keep the object
+// from being reclaimed.
+//
+// The remaining patterns enumerate the only valid conversions
+// from uintptr to Pointer.
+//
+// (3) Conversion of a Pointer to a uintptr and back, with arithmetic.
+//
+// If p points into an allocated object, it can be advanced through the object
+// by conversion to uintptr, addition of an offset, and conversion back to Pointer.
+//
+//	p = unsafe.Pointer(uintptr(p) + offset)
+//
+// The most common use of this pattern is to access fields in a struct
+// or elements of an array:
+//
+//	// equivalent to f := unsafe.Pointer(&s.f)
+//	f := unsafe.Pointer(uintptr(unsafe.Pointer(&s)) + unsafe.Offsetof(s.f))
+//
+//	// equivalent to e := unsafe.Pointer(&x[i])
+//	e := unsafe.Pointer(uintptr(unsafe.Pointer(&x[0])) + i*unsafe.Sizeof(x[0]))
+//
+// It is valid both to add and to subtract offsets from a pointer in this way,
+// but the result must continue to point into the original allocated object.
+// Unlike in C, it is not valid to advance a pointer just beyond the end of
+// its original allocation:
+//
+//	// INVALID: end points outside allocated space.
+//	var s thing
+//	end = unsafe.Pointer(uintptr(unsafe.Pointer(&s)) + unsafe.Sizeof(s))
+//
+//	// INVALID: end points outside allocated space.
+//	b := make([]byte, n)
+//	end = unsafe.Pointer(uintptr(unsafe.Pointer(&b[0])) + uintptr(n))
+//
+// Note that both conversions must appear in the same expression, with only
+// the intervening arithmetic between them:
+//
+//	// INVALID: uintptr cannot be stored in variable
+//	// before conversion back to Pointer.
+//	u := uintptr(p)
+//	p = unsafe.Pointer(u + offset)
+//
+// (4) Conversion of a Pointer to a uintptr when calling syscall.Syscall.
+//
+// The Syscall functions in package syscall pass their uintptr arguments directly
+// to the operating system, which then may, depending on the details of the call,
+// reinterpret some of them as pointers.
+// That is, the system call implementation is implicitly converting certain arguments
+// back from uintptr to pointer.
+//
+// If a pointer argument must be converted to uintptr for use as an argument,
+// that conversion must appear in the call expression itself:
+//
+//	syscall.Syscall(SYS_READ, uintptr(fd), uintptr(unsafe.Pointer(p)), uintptr(n))
+//
+// The compiler handles a Pointer converted to a uintptr in the argument list of
+// a call to a function implemented in assembly by arranging that the referenced
+// allocated object, if any, is retained and not moved until the call completes,
+// even though from the types alone it would appear that the object is no longer
+// needed during the call.
+//
+// For the compiler to recognize this pattern,
+// the conversion must appear in the argument list:
+//
+//	// INVALID: uintptr cannot be stored in variable
+//	// before implicit conversion back to Pointer during system call.
+//	u := uintptr(unsafe.Pointer(p))
+//	syscall.Syscall(SYS_READ, uintptr(fd), u, uintptr(n))
+//
+// (5) Conversion of the result of reflect.Value.Pointer or reflect.Value.UnsafeAddr
+// from uintptr to Pointer.
+//
+// Package reflect's Value methods named Pointer and UnsafeAddr return type uintptr
+// instead of unsafe.Pointer to keep callers from changing the result to an arbitrary
+// type without first importing "unsafe". However, this means that the result is
+// fragile and must be converted to Pointer immediately after making the call,
+// in the same expression:
+//
+//	p := (*int)(unsafe.Pointer(reflect.ValueOf(new(int)).Pointer()))
+//
+// As in the cases above, it is invalid to store the result before the conversion:
+//
+//	// INVALID: uintptr cannot be stored in variable
+//	// before conversion back to Pointer.
+//	u := reflect.ValueOf(new(int)).Pointer()
+//	p := (*int)(unsafe.Pointer(u))
+//
+// (6) Conversion of a reflect.SliceHeader or reflect.StringHeader Data field to or from Pointer.
+//
+// As in the previous case, the reflect data structures SliceHeader and StringHeader
+// declare the field Data as a uintptr to keep callers from changing the result to
+// an arbitrary type without first importing "unsafe". However, this means that
+// SliceHeader and StringHeader are only valid when interpreting the content
+// of an actual slice or string value.
+//
+//	var s string
+//	hdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) // case 1
+//	hdr.Data = uintptr(unsafe.Pointer(p))              // case 6 (this case)
+//	hdr.Len = uintptr(n)
+//
+// In this usage hdr.Data is really an alternate way to refer to the underlying
+// pointer in the slice header, not a uintptr variable itself.
+//
+// In general, reflect.SliceHeader and reflect.StringHeader should be used
+// only as *reflect.SliceHeader and *reflect.StringHeader pointing at actual
+// slices or strings, never as plain structs.
+// A program should not declare or allocate variables of these struct types.
+//
+//	// INVALID: a directly-declared header will not hold Data as a reference.
+//	var hdr reflect.StringHeader
+//	hdr.Data = uintptr(unsafe.Pointer(p))
+//	hdr.Len = uintptr(n)
+//	s := *(*string)(unsafe.Pointer(&hdr)) // p possibly already lost
+//
 type Pointer *ArbitraryType
 
 // Sizeof takes an expression x of any type and returns the size in bytes
@@ -36,7 +183,12 @@ func Sizeof(x ArbitraryType) uintptr
 // number of bytes between the start of the struct and the start of the field.
 func Offsetof(x ArbitraryType) uintptr
 
-// Alignof takes an expression x of any type and returns the alignment
+// Alignof takes an expression x of any type and returns the required alignment
 // of a hypothetical variable v as if v was declared via var v = x.
-// It is the largest value m such that the address of v is zero mod m.
+// It is the largest value m such that the address of v is always zero mod m.
+// It is the same as the value returned by reflect.TypeOf(x).Align().
+// As a special case, if a variable s is of struct type and f is a field
+// within that struct, then Alignof(s.f) will return the required alignment
+// of a field of that type within a struct.  This case is the same as the
+// value returned by reflect.TypeOf(s.f).FieldAlign().
 func Alignof(x ArbitraryType) uintptr
diff --git a/src/vendor/README b/src/vendor/README
new file mode 100644
index 0000000..e540318
--- /dev/null
+++ b/src/vendor/README
@@ -0,0 +1,8 @@
+This file needs to exist because the vendor directory needs
+to exist for some go/build tests to pass, and git can't track
+empty directories.
+
+In Go 1.7 we'll use this directory again. (In Go 1.6 we tried but
+reverted).
+
+See http://golang.org/issue/14047 for details.
diff --git a/test/bench/go1/jsondata_test.go b/test/bench/go1/jsondata_test.go
index cf0fac1..59afe13 100644
--- a/test/bench/go1/jsondata_test.go
+++ b/test/bench/go1/jsondata_test.go
@@ -1816,4 +1816,4 @@ zJE6zEudHD27ZzbOeSgpk/HnkQbT7twqaaJXNvUzMuUt1hyhU7ceZcph42+VTlXU
 cZ9UZZJyYojLjaeJHfJU1UZUEmBfLumu8yW5skuyE9uh2BmVxJZi6KxaXBNwSolw
 BqBcQLj3ucNZIYZLYtirLu3brW6UYgZgZJiDIGiwpsgg7g1AITkgM6FHITxDDnGt
 4SDHzZbL5s8fec5PCq5DOzDRdWS+0h5Y2INZak1D29cpVyb2aVrV3Wlt7rQhLa3e
-m3ZwPNcXywE2Qesk1XN24HvZ2Xa6nlm8Pf/xdyRThQkO1NjuAA== `)
+m3ZwPNcXywE2Qesk1XN24HvZ2Xa6nlm8Pf/xdyRThQkO1NjuAA==`)
diff --git a/test/bench/shootout/binary-tree-freelist.go b/test/bench/shootout/binary-tree-freelist.go
deleted file mode 100644
index 071a4e0..0000000
--- a/test/bench/shootout/binary-tree-freelist.go
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * based on C program by Kevin Carson
- */
-
-package main
-
-import (
-	"flag"
-	"fmt"
-)
-
-var n = flag.Int("n", 15, "depth")
-
-type Node struct {
-	item        int
-	left, right *Node
-}
-
-type Arena struct {
-	head *Node
-}
-
-var arena Arena
-
-func (n *Node) free() {
-	if n.left != nil {
-		n.left.free()
-	}
-	if n.right != nil {
-		n.right.free()
-	}
-	n.left = arena.head
-	arena.head = n
-}
-
-func (a *Arena) New(item int, left, right *Node) *Node {
-	if a.head == nil {
-		nodes := make([]Node, 3<<uint(*n))
-		for i := 0; i < len(nodes)-1; i++ {
-			nodes[i].left = &nodes[i+1]
-		}
-		a.head = &nodes[0]
-	}
-	n := a.head
-	a.head = a.head.left
-	n.item = item
-	n.left = left
-	n.right = right
-	return n
-}
-
-func bottomUpTree(item, depth int) *Node {
-	if depth <= 0 {
-		return arena.New(item, nil, nil)
-	}
-	return arena.New(item, bottomUpTree(2*item-1, depth-1), bottomUpTree(2*item, depth-1))
-}
-
-func (n *Node) itemCheck() int {
-	if n.left == nil {
-		return n.item
-	}
-	return n.item + n.left.itemCheck() - n.right.itemCheck()
-}
-
-const minDepth = 4
-
-func main() {
-	flag.Parse()
-
-	maxDepth := *n
-	if minDepth+2 > *n {
-		maxDepth = minDepth + 2
-	}
-	stretchDepth := maxDepth + 1
-
-	check := bottomUpTree(0, stretchDepth).itemCheck()
-	fmt.Printf("stretch tree of depth %d\t check: %d\n", stretchDepth, check)
-
-	longLivedTree := bottomUpTree(0, maxDepth)
-
-	for depth := minDepth; depth <= maxDepth; depth += 2 {
-		iterations := 1 << uint(maxDepth-depth+minDepth)
-		check = 0
-
-		for i := 1; i <= iterations; i++ {
-			t := bottomUpTree(i, depth)
-			check += t.itemCheck()
-			t.free()
-			t = bottomUpTree(-i, depth)
-			check += t.itemCheck()
-			t.free()
-		}
-		fmt.Printf("%d\t trees of depth %d\t check: %d\n", iterations*2, depth, check)
-	}
-	fmt.Printf("long lived tree of depth %d\t check: %d\n", maxDepth, longLivedTree.itemCheck())
-}
diff --git a/test/bench/shootout/binary-tree-freelist.txt b/test/bench/shootout/binary-tree-freelist.txt
deleted file mode 100644
index f8286dd..0000000
--- a/test/bench/shootout/binary-tree-freelist.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-stretch tree of depth 16	 check: -1
-65536	 trees of depth 4	 check: -65536
-16384	 trees of depth 6	 check: -16384
-4096	 trees of depth 8	 check: -4096
-1024	 trees of depth 10	 check: -1024
-256	 trees of depth 12	 check: -256
-64	 trees of depth 14	 check: -64
-long lived tree of depth 15	 check: -1
diff --git a/test/bench/shootout/binary-tree.c b/test/bench/shootout/binary-tree.c
deleted file mode 100644
index 9c35ac5..0000000
--- a/test/bench/shootout/binary-tree.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Shootout Benchmarks
-   http://shootout.alioth.debian.org/
-
-   contributed by Kevin Carson
-   compilation:
-       gcc -O3 -fomit-frame-pointer -funroll-loops -static binary-trees.c -lm
-       icc -O3 -ip -unroll -static binary-trees.c -lm
-*/
-
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-
-typedef struct tn {
-    struct tn*    left;
-    struct tn*    right;
-    long          item;
-} treeNode;
-
-
-treeNode* NewTreeNode(treeNode* left, treeNode* right, long item)
-{
-    treeNode*    new;
-
-    new = (treeNode*)malloc(sizeof(treeNode));
-
-    new->left = left;
-    new->right = right;
-    new->item = item;
-
-    return new;
-} /* NewTreeNode() */
-
-
-long ItemCheck(treeNode* tree)
-{
-    if (tree->left == NULL)
-        return tree->item;
-    else
-        return tree->item + ItemCheck(tree->left) - ItemCheck(tree->right);
-} /* ItemCheck() */
-
-
-treeNode* BottomUpTree(long item, unsigned depth)
-{
-    if (depth > 0)
-        return NewTreeNode
-        (
-            BottomUpTree(2 * item - 1, depth - 1),
-            BottomUpTree(2 * item, depth - 1),
-            item
-        );
-    else
-        return NewTreeNode(NULL, NULL, item);
-} /* BottomUpTree() */
-
-
-void DeleteTree(treeNode* tree)
-{
-    if (tree->left != NULL)
-    {
-        DeleteTree(tree->left);
-        DeleteTree(tree->right);
-    }
-
-    free(tree);
-} /* DeleteTree() */
-
-
-int main(int argc, char* argv[])
-{
-    unsigned   N, depth, minDepth, maxDepth, stretchDepth;
-    treeNode   *stretchTree, *longLivedTree, *tempTree;
-
-    N = atol(argv[1]);
-
-    minDepth = 4;
-
-    if ((minDepth + 2) > N)
-        maxDepth = minDepth + 2;
-    else
-        maxDepth = N;
-
-    stretchDepth = maxDepth + 1;
-
-    stretchTree = BottomUpTree(0, stretchDepth);
-    printf
-    (
-        "stretch tree of depth %u\t check: %li\n",
-        stretchDepth,
-        ItemCheck(stretchTree)
-    );
-
-    DeleteTree(stretchTree);
-
-    longLivedTree = BottomUpTree(0, maxDepth);
-
-    for (depth = minDepth; depth <= maxDepth; depth += 2)
-    {
-        long    i, iterations, check;
-
-        iterations = pow(2, maxDepth - depth + minDepth);
-
-        check = 0;
-
-        for (i = 1; i <= iterations; i++)
-        {
-            tempTree = BottomUpTree(i, depth);
-            check += ItemCheck(tempTree);
-            DeleteTree(tempTree);
-
-            tempTree = BottomUpTree(-i, depth);
-            check += ItemCheck(tempTree);
-            DeleteTree(tempTree);
-        } /* for(i = 1...) */
-
-        printf
-        (
-            "%li\t trees of depth %u\t check: %li\n",
-            iterations * 2,
-            depth,
-            check
-        );
-    } /* for(depth = minDepth...) */
-
-    printf
-    (
-        "long lived tree of depth %u\t check: %li\n",
-        maxDepth,
-        ItemCheck(longLivedTree)
-    );
-
-    return 0;
-} /* main() */
diff --git a/test/bench/shootout/binary-tree.go b/test/bench/shootout/binary-tree.go
deleted file mode 100644
index 9f867d1..0000000
--- a/test/bench/shootout/binary-tree.go
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * based on C program by Kevin Carson
- */
-
-package main
-
-import (
-	"flag"
-	"fmt"
-)
-
-var n = flag.Int("n", 15, "depth")
-
-type Node struct {
-	item        int
-	left, right *Node
-}
-
-func bottomUpTree(item, depth int) *Node {
-	if depth <= 0 {
-		return &Node{item: item}
-	}
-	return &Node{item, bottomUpTree(2*item-1, depth-1), bottomUpTree(2*item, depth-1)}
-}
-
-func (n *Node) itemCheck() int {
-	if n.left == nil {
-		return n.item
-	}
-	return n.item + n.left.itemCheck() - n.right.itemCheck()
-}
-
-const minDepth = 4
-
-func main() {
-	flag.Parse()
-
-	maxDepth := *n
-	if minDepth+2 > *n {
-		maxDepth = minDepth + 2
-	}
-	stretchDepth := maxDepth + 1
-
-	check := bottomUpTree(0, stretchDepth).itemCheck()
-	fmt.Printf("stretch tree of depth %d\t check: %d\n", stretchDepth, check)
-
-	longLivedTree := bottomUpTree(0, maxDepth)
-
-	for depth := minDepth; depth <= maxDepth; depth += 2 {
-		iterations := 1 << uint(maxDepth-depth+minDepth)
-		check = 0
-
-		for i := 1; i <= iterations; i++ {
-			check += bottomUpTree(i, depth).itemCheck()
-			check += bottomUpTree(-i, depth).itemCheck()
-		}
-		fmt.Printf("%d\t trees of depth %d\t check: %d\n", iterations*2, depth, check)
-	}
-	fmt.Printf("long lived tree of depth %d\t check: %d\n", maxDepth, longLivedTree.itemCheck())
-}
diff --git a/test/bench/shootout/binary-tree.txt b/test/bench/shootout/binary-tree.txt
deleted file mode 100644
index f8286dd..0000000
--- a/test/bench/shootout/binary-tree.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-stretch tree of depth 16	 check: -1
-65536	 trees of depth 4	 check: -65536
-16384	 trees of depth 6	 check: -16384
-4096	 trees of depth 8	 check: -4096
-1024	 trees of depth 10	 check: -1024
-256	 trees of depth 12	 check: -256
-64	 trees of depth 14	 check: -64
-long lived tree of depth 15	 check: -1
diff --git a/test/bench/shootout/chameneosredux.c b/test/bench/shootout/chameneosredux.c
deleted file mode 100644
index ed78c31..0000000
--- a/test/bench/shootout/chameneosredux.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
-   http://shootout.alioth.debian.org/
-
-   contributed by Michael Barker
-   based on a Java contribution by Luzius Meisser
-
-   convert to C by dualamd
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <pthread.h>
-
-
-enum Colour
-{
-   blue      = 0,
-   red      = 1,
-   yellow   = 2,
-   Invalid   = 3
-};
-
-const char* ColourName[] = {"blue", "red", "yellow"};
-const int STACK_SIZE   = 32*1024;
-
-typedef unsigned int BOOL;
-const BOOL TRUE = 1;
-const BOOL FALSE = 0;
-
-int CreatureID = 0;
-
-
-enum Colour doCompliment(enum Colour c1, enum Colour c2)
-{
-   switch (c1)
-   {
-   case blue:
-      switch (c2)
-      {
-      case blue:
-         return blue;
-      case red:
-         return yellow;
-      case yellow:
-         return red;
-      default:
-         goto errlb;
-      }
-   case red:
-      switch (c2)
-      {
-      case blue:
-         return yellow;
-      case red:
-         return red;
-      case yellow:
-         return blue;
-      default:
-         goto errlb;
-      }
-   case yellow:
-      switch (c2)
-      {
-      case blue:
-         return red;
-      case red:
-         return blue;
-      case yellow:
-         return yellow;
-      default:
-         goto errlb;
-      }
-   default:
-      break;
-   }
-
-errlb:
-   printf("Invalid colour\n");
-   exit( 1 );
-}
-
-/* convert integer to number string: 1234 -> "one two three four" */
-char* formatNumber(int n, char* outbuf)
-{
-   int ochar = 0, ichar = 0;
-   int i;
-   char tmp[64];
-
-   const char* NUMBERS[] =
-   {
-      "zero", "one", "two", "three", "four", "five",
-      "six", "seven", "eight", "nine"
-   };
-
-   ichar = sprintf(tmp, "%d", n);
-
-   for (i = 0; i < ichar; i++)
-      ochar += sprintf( outbuf + ochar, " %s", NUMBERS[ tmp[i] - '0' ] );
-
-   return outbuf;
-}
-
-
-struct MeetingPlace
-{
-   pthread_mutex_t   mutex;
-   int             meetingsLeft;
-   struct Creature*   firstCreature;
-};
-
-struct Creature
-{
-   pthread_t         ht;
-   pthread_attr_t      stack_att;
-
-   struct MeetingPlace* place;
-   int         count;
-   int         sameCount;
-
-   enum Colour   colour;
-   int          id;
-
-   BOOL      two_met;
-   BOOL      sameid;
-};
-
-
-void MeetingPlace_Init(struct MeetingPlace* m, int meetings )
-{
-   pthread_mutex_init( &m->mutex, 0 );
-   m->meetingsLeft = meetings;
-   m->firstCreature = 0;
-}
-
-
-BOOL Meet( struct Creature* cr)
-{
-   BOOL retval = TRUE;
-
-   struct MeetingPlace* mp = cr->place;
-   pthread_mutex_lock( &(mp->mutex) );
-
-   if ( mp->meetingsLeft > 0 )
-   {
-      if ( mp->firstCreature == 0 )
-      {
-         cr->two_met = FALSE;
-         mp->firstCreature = cr;
-      }
-      else
-      {
-         struct Creature* first;
-         enum Colour newColour;
-
-         first = mp->firstCreature;
-         newColour = doCompliment( cr->colour, first->colour );
-
-         cr->sameid = cr->id == first->id;
-         cr->colour = newColour;
-         cr->two_met = TRUE;
-
-         first->sameid = cr->sameid;
-         first->colour = newColour;
-         first->two_met = TRUE;
-
-         mp->firstCreature = 0;
-         mp->meetingsLeft--;
-      }
-   }
-   else
-      retval = FALSE;
-
-   pthread_mutex_unlock( &(mp->mutex) );
-   return retval;
-}
-
-
-void* CreatureThreadRun(void* param)
-{
-   struct Creature* cr = (struct Creature*)param;
-
-   while (TRUE)
-   {
-      if ( Meet(cr) )
-      {
-         while (cr->two_met == FALSE)
-            sched_yield();
-
-         if (cr->sameid)
-            cr->sameCount++;
-         cr->count++;
-      }
-      else
-         break;
-   }
-
-   return 0;
-}
-
-void Creature_Init( struct Creature *cr, struct MeetingPlace* place, enum Colour colour )
-{
-   cr->place = place;
-   cr->count = cr->sameCount = 0;
-
-   cr->id = ++CreatureID;
-   cr->colour = colour;
-   cr->two_met = FALSE;
-
-   pthread_attr_init( &cr->stack_att );
-   pthread_attr_setstacksize( &cr->stack_att, STACK_SIZE );
-   pthread_create( &cr->ht, &cr->stack_att, &CreatureThreadRun, (void*)(cr) );
-}
-
-/* format meeting times of each creature to string */
-char* Creature_getResult(struct Creature* cr, char* str)
-{
-   char numstr[256];
-   formatNumber(cr->sameCount, numstr);
-
-   sprintf( str, "%u%s", cr->count, numstr );
-   return str;
-}
-
-
-void runGame( int n_meeting, int ncolor, const enum Colour* colours )
-{
-   int i;
-   int total = 0;
-   char str[256];
-
-   struct MeetingPlace place;
-   struct Creature *creatures = (struct Creature*) calloc( ncolor, sizeof(struct Creature) );
-
-   MeetingPlace_Init( &place, n_meeting );
-
-   /* print initial color of each creature */
-   for (i = 0; i < ncolor; i++)
-   {
-      printf( "%s ", ColourName[ colours[i] ] );
-      Creature_Init( &(creatures[i]), &place, colours[i] );
-   }
-   printf("\n");
-
-   /* wait for them to meet */
-   for (i = 0; i < ncolor; i++)
-      pthread_join( creatures[i].ht, 0 );
-
-   /* print meeting times of each creature */
-   for (i = 0; i < ncolor; i++)
-   {
-      printf( "%s\n", Creature_getResult(&(creatures[i]), str) );
-      total += creatures[i].count;
-   }
-
-   /* print total meeting times, should equal n_meeting */
-   printf( "%s\n\n", formatNumber(total, str) );
-
-   /* cleaup & quit */
-   pthread_mutex_destroy( &place.mutex );
-   free( creatures );
-}
-
-
-void printColours( enum Colour c1, enum Colour c2 )
-{
-   printf( "%s + %s -> %s\n",
-      ColourName[c1],
-      ColourName[c2],
-      ColourName[doCompliment(c1, c2)]   );
-}
-
-void printColoursTable(void)
-{
-   printColours(blue, blue);
-   printColours(blue, red);
-   printColours(blue, yellow);
-   printColours(red, blue);
-   printColours(red, red);
-   printColours(red, yellow);
-   printColours(yellow, blue);
-   printColours(yellow, red);
-   printColours(yellow, yellow);
-}
-
-int main(int argc, char** argv)
-{
-   int n = (argc == 2) ? atoi(argv[1]) : 600;
-
-   printColoursTable();
-   printf("\n");
-
-   const enum Colour r1[] = {   blue, red, yellow   };
-   const enum Colour r2[] = {   blue, red, yellow,
-               red, yellow, blue,
-               red, yellow, red, blue   };
-
-   runGame( n, sizeof(r1) / sizeof(r1[0]), r1 );
-   runGame( n, sizeof(r2) / sizeof(r2[0]), r2 );
-
-   return 0;
-}
diff --git a/test/bench/shootout/chameneosredux.go b/test/bench/shootout/chameneosredux.go
deleted file mode 100644
index 72ce7dd..0000000
--- a/test/bench/shootout/chameneosredux.go
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- */
-
-package main
-
-import (
-	"flag"
-	"fmt"
-	"strconv"
-)
-
-const (
-	blue = iota
-	red
-	yellow
-	ncol
-)
-
-var complement = [...]int{
-	red | red<<2:       red,
-	red | yellow<<2:    blue,
-	red | blue<<2:      yellow,
-	yellow | red<<2:    blue,
-	yellow | yellow<<2: yellow,
-	yellow | blue<<2:   red,
-	blue | red<<2:      yellow,
-	blue | yellow<<2:   red,
-	blue | blue<<2:     blue,
-}
-
-var colname = [...]string{
-	blue:   "blue",
-	red:    "red",
-	yellow: "yellow",
-}
-
-// information about the current state of a creature.
-type info struct {
-	colour int // creature's current colour.
-	name   int // creature's name.
-}
-
-// exclusive access data-structure kept inside meetingplace.
-// if mate is nil, it indicates there's no creature currently waiting;
-// otherwise the creature's info is stored in info, and
-// it is waiting to receive its mate's information on the mate channel.
-type rendez struct {
-	n    int         // current number of encounters.
-	mate chan<- info // creature waiting when non-nil.
-	info info        // info about creature waiting.
-}
-
-// result sent by each creature at the end of processing.
-type result struct {
-	met  int
-	same int
-}
-
-var n = 600
-
-func main() {
-	flag.Parse()
-	if flag.NArg() > 0 {
-		n, _ = strconv.Atoi(flag.Arg(0))
-	}
-
-	for c0 := 0; c0 < ncol; c0++ {
-		for c1 := 0; c1 < ncol; c1++ {
-			fmt.Printf("%s + %s -> %s\n", colname[c0], colname[c1], colname[complement[c0|c1<<2]])
-		}
-	}
-	fmt.Print("\n")
-
-	pallmall([]int{blue, red, yellow})
-	pallmall([]int{blue, red, yellow, red, yellow, blue, red, yellow, red, blue})
-}
-
-func pallmall(cols []int) {
-
-	// invariant: meetingplace always contains a value unless a creature
-	// is currently dealing with it (whereupon it must put it back).
-	meetingplace := make(chan rendez, 1)
-	meetingplace <- rendez{n: 0}
-
-	ended := make(chan result)
-	msg := ""
-	for i, col := range cols {
-		go creature(info{col, i}, meetingplace, ended)
-		msg += " " + colname[col]
-	}
-	fmt.Println(msg)
-	tot := 0
-	// wait for all results
-	for range cols {
-		result := <-ended
-		tot += result.met
-		fmt.Printf("%v%v\n", result.met, spell(result.same, true))
-	}
-	fmt.Printf("%v\n\n", spell(tot, true))
-}
-
-// in this function, variables ending in 0 refer to the local creature,
-// variables ending in 1 to the creature we've met.
-func creature(info0 info, meetingplace chan rendez, ended chan result) {
-	c0 := make(chan info)
-	met := 0
-	same := 0
-	for {
-		var othername int
-		// get access to rendez data and decide what to do.
-		switch r := <-meetingplace; {
-		case r.n >= n:
-			// if no more meetings left, then send our result data and exit.
-			meetingplace <- rendez{n: r.n}
-			ended <- result{met, same}
-			return
-		case r.mate == nil:
-			// no creature waiting; wait for someone to meet us,
-			// get their info and send our info in reply.
-			meetingplace <- rendez{n: r.n, info: info0, mate: c0}
-			info1 := <-c0
-			othername = info1.name
-			info0.colour = complement[info0.colour|info1.colour<<2]
-		default:
-			// another creature is waiting for us with its info;
-			// increment meeting count,
-			// send them our info in reply.
-			r.n++
-			meetingplace <- rendez{n: r.n, mate: nil}
-			r.mate <- info0
-			othername = r.info.name
-			info0.colour = complement[info0.colour|r.info.colour<<2]
-		}
-		if othername == info0.name {
-			same++
-		}
-		met++
-	}
-}
-
-var digits = [...]string{"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}
-
-func spell(n int, required bool) string {
-	if n == 0 && !required {
-		return ""
-	}
-	return spell(n/10, false) + " " + digits[n%10]
-}
diff --git a/test/bench/shootout/chameneosredux.txt b/test/bench/shootout/chameneosredux.txt
deleted file mode 100644
index 6016d59..0000000
--- a/test/bench/shootout/chameneosredux.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-blue + blue -> blue
-blue + red -> yellow
-blue + yellow -> red
-red + blue -> yellow
-red + red -> red
-red + yellow -> blue
-yellow + blue -> red
-yellow + red -> blue
-yellow + yellow -> yellow
-
- blue red yellow
-400 zero
-400 zero
-400 zero
- one two zero zero
-
- blue red yellow red yellow blue red yellow red blue
-120 zero
-120 zero
-120 zero
-120 zero
-120 zero
-120 zero
-120 zero
-120 zero
-120 zero
-120 zero
- one two zero zero
-
diff --git a/test/bench/shootout/fannkuch-parallel.go b/test/bench/shootout/fannkuch-parallel.go
deleted file mode 100644
index 7e9b98d..0000000
--- a/test/bench/shootout/fannkuch-parallel.go
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*
- * The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * Based on fannkuch.scala by Rex Kerr
- */
-
-package main
-
-import (
-	"flag"
-	"fmt"
-	"runtime"
-)
-
-var n = flag.Int("n", 7, "count")
-var nCPU = flag.Int("ncpu", 4, "number of cpus")
-
-type Job struct {
-	start []int
-	n     int
-}
-
-type Found struct {
-	who *Kucher
-	k   int
-}
-
-type Kucher struct {
-	perm []int
-	temp []int
-	flip []int
-	in   chan Job
-}
-
-func NewKucher(length int) *Kucher {
-	return &Kucher{
-		perm: make([]int, length),
-		temp: make([]int, length),
-		flip: make([]int, length),
-		in:   make(chan Job),
-	}
-}
-
-func (k *Kucher) permute(n int) bool {
-	i := 0
-	for ; i < n-1 && k.flip[i] == 0; i++ {
-		t := k.perm[0]
-		j := 0
-		for ; j <= i; j++ {
-			k.perm[j] = k.perm[j+1]
-		}
-		k.perm[j] = t
-	}
-	k.flip[i]--
-	for i > 0 {
-		i--
-		k.flip[i] = i
-	}
-	return k.flip[n-1] >= 0
-}
-
-func (k *Kucher) count() int {
-	K := 0
-	copy(k.temp, k.perm)
-	for k.temp[0] != 0 {
-		m := k.temp[0]
-		for i := 0; i < m; i++ {
-			k.temp[i], k.temp[m] = k.temp[m], k.temp[i]
-			m--
-		}
-		K++
-	}
-	return K
-}
-
-func (k *Kucher) Run(foreman chan<- Found) {
-	for job := range k.in {
-		verbose := 30
-		copy(k.perm, job.start)
-		for i, v := range k.perm {
-			if v != i {
-				verbose = 0
-			}
-			k.flip[i] = i
-		}
-		K := 0
-		for {
-			if verbose > 0 {
-				for _, p := range k.perm {
-					fmt.Print(p + 1)
-				}
-				fmt.Println()
-				verbose--
-			}
-			count := k.count()
-			if count > K {
-				K = count
-			}
-			if !k.permute(job.n) {
-				break
-			}
-		}
-		foreman <- Found{k, K}
-	}
-}
-
-type Fanner struct {
-	jobind   int
-	jobsdone int
-	k        int
-	jobs     []Job
-	workers  []*Kucher
-	in       chan Found
-	result   chan int
-}
-
-func NewFanner(jobs []Job, workers []*Kucher) *Fanner {
-	return &Fanner{
-		jobs: jobs, workers: workers,
-		in:     make(chan Found),
-		result: make(chan int),
-	}
-}
-
-func (f *Fanner) Run(N int) {
-	for msg := range f.in {
-		if msg.k > f.k {
-			f.k = msg.k
-		}
-		if msg.k >= 0 {
-			f.jobsdone++
-		}
-		if f.jobind < len(f.jobs) {
-			msg.who.in <- f.jobs[f.jobind]
-			f.jobind++
-		} else if f.jobsdone == len(f.jobs) {
-			f.result <- f.k
-			return
-		}
-	}
-}
-
-func swapped(a []int, i, j int) []int {
-	b := make([]int, len(a))
-	copy(b, a)
-	b[i], b[j] = a[j], a[i]
-	return b
-}
-
-func main() {
-	flag.Parse()
-	runtime.GOMAXPROCS(*nCPU)
-	N := *n
-	base := make([]int, N)
-	for i := range base {
-		base[i] = i
-	}
-
-	njobs := 1
-	if N > 8 {
-		njobs += (N*(N-1))/2 - 28 // njobs = 1 + sum(8..N-1) = 1 + sum(1..N-1) - sum(1..7)
-	}
-	jobs := make([]Job, njobs)
-	jobsind := 0
-
-	firstN := N
-	if firstN > 8 {
-		firstN = 8
-	}
-	jobs[jobsind] = Job{base, firstN}
-	jobsind++
-	for i := N - 1; i >= 8; i-- {
-		for j := 0; j < i; j++ {
-			jobs[jobsind] = Job{swapped(base, i, j), i}
-			jobsind++
-		}
-	}
-
-	nworkers := *nCPU
-	if njobs < nworkers {
-		nworkers = njobs
-	}
-	workers := make([]*Kucher, nworkers)
-	foreman := NewFanner(jobs, workers)
-	go foreman.Run(N)
-	for i := range workers {
-		k := NewKucher(N)
-		workers[i] = k
-		go k.Run(foreman.in)
-		foreman.in <- Found{k, -1}
-	}
-	fmt.Printf("Pfannkuchen(%d) = %d\n", N, <-foreman.result)
-}
diff --git a/test/bench/shootout/fannkuch-parallel.txt b/test/bench/shootout/fannkuch-parallel.txt
deleted file mode 100644
index e66f779..0000000
--- a/test/bench/shootout/fannkuch-parallel.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-1234567
-2134567
-2314567
-3214567
-3124567
-1324567
-2341567
-3241567
-3421567
-4321567
-4231567
-2431567
-3412567
-4312567
-4132567
-1432567
-1342567
-3142567
-4123567
-1423567
-1243567
-2143567
-2413567
-4213567
-2345167
-3245167
-3425167
-4325167
-4235167
-2435167
-Pfannkuchen(7) = 16
diff --git a/test/bench/shootout/fannkuch.c b/test/bench/shootout/fannkuch.c
deleted file mode 100644
index e576b54..0000000
--- a/test/bench/shootout/fannkuch.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*
- * The Computer Language Shootout
- * http://shootout.alioth.debian.org/
- * Contributed by Heiner Marxen
- *
- * "fannkuch"	for C gcc
- *
- * $Id: fannkuch.1.gcc.code,v 1.15 2009-04-28 15:39:31 igouy-guest Exp $
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#define Int	int
-#define Aint	int
-
-    static long
-fannkuch( int n )
-{
-    Aint*	perm;
-    Aint*	perm1;
-    Aint*	count;
-    long	flips;
-    long	flipsMax;
-    Int		r;
-    Int		i;
-    Int		k;
-    Int		didpr;
-    const Int	n1	= n - 1;
-
-    if( n < 1 ) return 0;
-
-    perm  = calloc(n, sizeof(*perm ));
-    perm1 = calloc(n, sizeof(*perm1));
-    count = calloc(n, sizeof(*count));
-
-    for( i=0 ; i<n ; ++i ) perm1[i] = i;	/* initial (trivial) permu */
-
-    r = n; didpr = 0; flipsMax = 0;
-    for(;;) {
-	if( didpr < 30 ) {
-	    for( i=0 ; i<n ; ++i ) printf("%d", (int)(1+perm1[i]));
-	    printf("\n");
-	    ++didpr;
-	}
-	for( ; r!=1 ; --r ) {
-	    count[r-1] = r;
-	}
-
-#define XCH(x,y)	{ Aint t_mp; t_mp=(x); (x)=(y); (y)=t_mp; }
-
-	if( ! (perm1[0]==0 || perm1[n1]==n1) ) {
-	    flips = 0;
-	    for( i=1 ; i<n ; ++i ) {	/* perm = perm1 */
-		perm[i] = perm1[i];
-	    }
-	    k = perm1[0];		/* cache perm[0] in k */
-	    do {			/* k!=0 ==> k>0 */
-		Int	j;
-		for( i=1, j=k-1 ; i<j ; ++i, --j ) {
-		    XCH(perm[i], perm[j])
-		}
-		++flips;
-		/*
-		 * Now exchange k (caching perm[0]) and perm[k]... with care!
-		 * XCH(k, perm[k]) does NOT work!
-		 */
-		j=perm[k]; perm[k]=k ; k=j;
-	    }while( k );
-	    if( flipsMax < flips ) {
-		flipsMax = flips;
-	    }
-	}
-
-	for(;;) {
-	    if( r == n ) {
-		return flipsMax;
-	    }
-	    /* rotate down perm[0..r] by one */
-	    {
-		Int	perm0 = perm1[0];
-		i = 0;
-		while( i < r ) {
-		    k = i+1;
-		    perm1[i] = perm1[k];
-		    i = k;
-		}
-		perm1[r] = perm0;
-	    }
-	    if( (count[r] -= 1) > 0 ) {
-		break;
-	    }
-	    ++r;
-	}
-    }
-}
-
-    int
-main( int argc, char* argv[] )
-{
-    int		n = (argc>1) ? atoi(argv[1]) : 0;
-
-    printf("Pfannkuchen(%d) = %ld\n", n, fannkuch(n));
-    return 0;
-}
diff --git a/test/bench/shootout/fannkuch.go b/test/bench/shootout/fannkuch.go
deleted file mode 100644
index b554c77..0000000
--- a/test/bench/shootout/fannkuch.go
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*
- * The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * Based on fannkuch.c by Heiner Marxen
- */
-
-package main
-
-import (
-	"flag"
-	"fmt"
-)
-
-var n = flag.Int("n", 7, "count")
-
-func fannkuch(n int) int {
-	if n < 1 {
-		return 0
-	}
-
-	n1 := n - 1
-	perm := make([]int, n)
-	perm1 := make([]int, n)
-	count := make([]int, n)
-
-	for i := 0; i < n; i++ {
-		perm1[i] = i // initial (trivial) permutation
-	}
-
-	r := n
-	didpr := 0
-	flipsMax := 0
-	for {
-		if didpr < 30 {
-			for i := 0; i < n; i++ {
-				fmt.Printf("%d", 1+perm1[i])
-			}
-			fmt.Printf("\n")
-			didpr++
-		}
-		for ; r != 1; r-- {
-			count[r-1] = r
-		}
-
-		if perm1[0] != 0 && perm1[n1] != n1 {
-			flips := 0
-			for i := 1; i < n; i++ { // perm = perm1
-				perm[i] = perm1[i]
-			}
-			k := perm1[0] // cache perm[0] in k
-			for {         // k!=0 ==> k>0
-				for i, j := 1, k-1; i < j; i, j = i+1, j-1 {
-					perm[i], perm[j] = perm[j], perm[i]
-				}
-				flips++
-				// Now exchange k (caching perm[0]) and perm[k]... with care!
-				j := perm[k]
-				perm[k] = k
-				k = j
-				if k == 0 {
-					break
-				}
-			}
-			if flipsMax < flips {
-				flipsMax = flips
-			}
-		}
-
-		for ; r < n; r++ {
-			// rotate down perm[0..r] by one
-			perm0 := perm1[0]
-			for i := 0; i < r; i++ {
-				perm1[i] = perm1[i+1]
-			}
-			perm1[r] = perm0
-			count[r]--
-			if count[r] > 0 {
-				break
-			}
-		}
-		if r == n {
-			return flipsMax
-		}
-	}
-	return 0
-}
-
-func main() {
-	flag.Parse()
-	fmt.Printf("Pfannkuchen(%d) = %d\n", *n, fannkuch(*n))
-}
diff --git a/test/bench/shootout/fannkuch.txt b/test/bench/shootout/fannkuch.txt
deleted file mode 100644
index e66f779..0000000
--- a/test/bench/shootout/fannkuch.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-1234567
-2134567
-2314567
-3214567
-3124567
-1324567
-2341567
-3241567
-3421567
-4321567
-4231567
-2431567
-3412567
-4312567
-4132567
-1432567
-1342567
-3142567
-4123567
-1423567
-1243567
-2143567
-2413567
-4213567
-2345167
-3245167
-3425167
-4325167
-4235167
-2435167
-Pfannkuchen(7) = 16
diff --git a/test/bench/shootout/fasta-1000.txt b/test/bench/shootout/fasta-1000.txt
deleted file mode 100644
index f1caba0..0000000
--- a/test/bench/shootout/fasta-1000.txt
+++ /dev/null
@@ -1,171 +0,0 @@
->ONE Homo sapiens alu
-GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA
-TCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACT
-AAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAG
-GCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCG
-CCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGT
-GGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCA
-GGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAA
-TTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAG
-AATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCA
-GCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGT
-AATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACC
-AGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTG
-GTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACC
-CGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAG
-AGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTT
-TGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACA
-TGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCT
-GTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGG
-TTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGT
-CTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGG
-CGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCG
-TCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTA
-CTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCG
-AGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCG
-GGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACC
-TGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAA
-TACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGA
-GGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACT
-GCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTC
-ACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGT
-TCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGC
-CGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCG
-CTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTG
-GGCGACAGAGCGAGACTCCG
->TWO IUB ambiguity codes
-cttBtatcatatgctaKggNcataaaSatgtaaaDcDRtBggDtctttataattcBgtcg
-tactDtDagcctatttSVHtHttKtgtHMaSattgWaHKHttttagacatWatgtRgaaa
-NtactMcSMtYtcMgRtacttctWBacgaaatatagScDtttgaagacacatagtVgYgt
-cattHWtMMWcStgttaggKtSgaYaaccWStcgBttgcgaMttBYatcWtgacaYcaga
-gtaBDtRacttttcWatMttDBcatWtatcttactaBgaYtcttgttttttttYaaScYa
-HgtgttNtSatcMtcVaaaStccRcctDaataataStcYtRDSaMtDttgttSagtRRca
-tttHatSttMtWgtcgtatSSagactYaaattcaMtWatttaSgYttaRgKaRtccactt
-tattRggaMcDaWaWagttttgacatgttctacaaaRaatataataaMttcgDacgaSSt
-acaStYRctVaNMtMgtaggcKatcttttattaaaaagVWaHKYagtttttatttaacct
-tacgtVtcVaattVMBcttaMtttaStgacttagattWWacVtgWYagWVRctDattBYt
-gtttaagaagattattgacVatMaacattVctgtBSgaVtgWWggaKHaatKWcBScSWa
-accRVacacaaactaccScattRatatKVtactatatttHttaagtttSKtRtacaaagt
-RDttcaaaaWgcacatWaDgtDKacgaacaattacaRNWaatHtttStgttattaaMtgt
-tgDcgtMgcatBtgcttcgcgaDWgagctgcgaggggVtaaScNatttacttaatgacag
-cccccacatYScaMgtaggtYaNgttctgaMaacNaMRaacaaacaKctacatagYWctg
-ttWaaataaaataRattagHacacaagcgKatacBttRttaagtatttccgatctHSaat
-actcNttMaagtattMtgRtgaMgcataatHcMtaBSaRattagttgatHtMttaaKagg
-YtaaBataSaVatactWtataVWgKgttaaaacagtgcgRatatacatVtHRtVYataSa
-KtWaStVcNKHKttactatccctcatgWHatWaRcttactaggatctataDtDHBttata
-aaaHgtacVtagaYttYaKcctattcttcttaataNDaaggaaaDYgcggctaaWSctBa
-aNtgctggMBaKctaMVKagBaactaWaDaMaccYVtNtaHtVWtKgRtcaaNtYaNacg
-gtttNattgVtttctgtBaWgtaattcaagtcaVWtactNggattctttaYtaaagccgc
-tcttagHVggaYtgtNcDaVagctctctKgacgtatagYcctRYHDtgBattDaaDgccK
-tcHaaStttMcctagtattgcRgWBaVatHaaaataYtgtttagMDMRtaataaggatMt
-ttctWgtNtgtgaaaaMaatatRtttMtDgHHtgtcattttcWattRSHcVagaagtacg
-ggtaKVattKYagactNaatgtttgKMMgYNtcccgSKttctaStatatNVataYHgtNa
-BKRgNacaactgatttcctttaNcgatttctctataScaHtataRagtcRVttacDSDtt
-aRtSatacHgtSKacYagttMHtWataggatgactNtatSaNctataVtttRNKtgRacc
-tttYtatgttactttttcctttaaacatacaHactMacacggtWataMtBVacRaSaatc
-cgtaBVttccagccBcttaRKtgtgcctttttRtgtcagcRttKtaaacKtaaatctcac
-aattgcaNtSBaaccgggttattaaBcKatDagttactcttcattVtttHaaggctKKga
-tacatcBggScagtVcacattttgaHaDSgHatRMaHWggtatatRgccDttcgtatcga
-aacaHtaagttaRatgaVacttagattVKtaaYttaaatcaNatccRttRRaMScNaaaD
-gttVHWgtcHaaHgacVaWtgttScactaagSgttatcttagggDtaccagWattWtRtg
-ttHWHacgattBtgVcaYatcggttgagKcWtKKcaVtgaYgWctgYggVctgtHgaNcV
-taBtWaaYatcDRaaRtSctgaHaYRttagatMatgcatttNattaDttaattgttctaa
-ccctcccctagaWBtttHtBccttagaVaatMcBHagaVcWcagBVttcBtaYMccagat
-gaaaaHctctaacgttagNWRtcggattNatcRaNHttcagtKttttgWatWttcSaNgg
-gaWtactKKMaacatKatacNattgctWtatctaVgagctatgtRaHtYcWcttagccaa
-tYttWttaWSSttaHcaaaaagVacVgtaVaRMgattaVcDactttcHHggHRtgNcctt
-tYatcatKgctcctctatVcaaaaKaaaagtatatctgMtWtaaaacaStttMtcgactt
-taSatcgDataaactaaacaagtaaVctaggaSccaatMVtaaSKNVattttgHccatca
-cBVctgcaVatVttRtactgtVcaattHgtaaattaaattttYtatattaaRSgYtgBag
-aHSBDgtagcacRHtYcBgtcacttacactaYcgctWtattgSHtSatcataaatataHt
-cgtYaaMNgBaatttaRgaMaatatttBtttaaaHHKaatctgatWatYaacttMctctt
-ttVctagctDaaagtaVaKaKRtaacBgtatccaaccactHHaagaagaaggaNaaatBW
-attccgStaMSaMatBttgcatgRSacgttVVtaaDMtcSgVatWcaSatcttttVatag
-ttactttacgatcaccNtaDVgSRcgVcgtgaacgaNtaNatatagtHtMgtHcMtagaa
-attBgtataRaaaacaYKgtRccYtatgaagtaataKgtaaMttgaaRVatgcagaKStc
-tHNaaatctBBtcttaYaBWHgtVtgacagcaRcataWctcaBcYacYgatDgtDHccta
->THREE Homo sapiens frequency
-aacacttcaccaggtatcgtgaaggctcaagattacccagagaacctttgcaatataaga
-atatgtatgcagcattaccctaagtaattatattctttttctgactcaaagtgacaagcc
-ctagtgtatattaaatcggtatatttgggaaattcctcaaactatcctaatcaggtagcc
-atgaaagtgatcaaaaaagttcgtacttataccatacatgaattctggccaagtaaaaaa
-tagattgcgcaaaattcgtaccttaagtctctcgccaagatattaggatcctattactca
-tatcgtgtttttctttattgccgccatccccggagtatctcacccatccttctcttaaag
-gcctaatattacctatgcaaataaacatatattgttgaaaattgagaacctgatcgtgat
-tcttatgtgtaccatatgtatagtaatcacgcgactatatagtgctttagtatcgcccgt
-gggtgagtgaatattctgggctagcgtgagatagtttcttgtcctaatatttttcagatc
-gaatagcttctatttttgtgtttattgacatatgtcgaaactccttactcagtgaaagtc
-atgaccagatccacgaacaatcttcggaatcagtctcgttttacggcggaatcttgagtc
-taacttatatcccgtcgcttactttctaacaccccttatgtatttttaaaattacgttta
-ttcgaacgtacttggcggaagcgttattttttgaagtaagttacattgggcagactcttg
-acattttcgatacgactttctttcatccatcacaggactcgttcgtattgatatcagaag
-ctcgtgatgattagttgtcttctttaccaatactttgaggcctattctgcgaaatttttg
-ttgccctgcgaacttcacataccaaggaacacctcgcaacatgccttcatatccatcgtt
-cattgtaattcttacacaatgaatcctaagtaattacatccctgcgtaaaagatggtagg
-ggcactgaggatatattaccaagcatttagttatgagtaatcagcaatgtttcttgtatt
-aagttctctaaaatagttacatcgtaatgttatctcgggttccgcgaataaacgagatag
-attcattatatatggccctaagcaaaaacctcctcgtattctgttggtaattagaatcac
-acaatacgggttgagatattaattatttgtagtacgaagagatataaaaagatgaacaat
-tactcaagtcaagatgtatacgggatttataataaaaatcgggtagagatctgctttgca
-attcagacgtgccactaaatcgtaatatgtcgcgttacatcagaaagggtaactattatt
-aattaataaagggcttaatcactacatattagatcttatccgatagtcttatctattcgt
-tgtatttttaagcggttctaattcagtcattatatcagtgctccgagttctttattattg
-ttttaaggatgacaaaatgcctcttgttataacgctgggagaagcagactaagagtcgga
-gcagttggtagaatgaggctgcaaaagacggtctcgacgaatggacagactttactaaac
-caatgaaagacagaagtagagcaaagtctgaagtggtatcagcttaattatgacaaccct
-taatacttccctttcgccgaatactggcgtggaaaggttttaaaagtcgaagtagttaga
-ggcatctctcgctcataaataggtagactactcgcaatccaatgtgactatgtaatactg
-ggaacatcagtccgcgatgcagcgtgtttatcaaccgtccccactcgcctggggagacat
-gagaccacccccgtggggattattagtccgcagtaatcgactcttgacaatccttttcga
-ttatgtcatagcaatttacgacagttcagcgaagtgactactcggcgaaatggtattact
-aaagcattcgaacccacatgaatgtgattcttggcaatttctaatccactaaagcttttc
-cgttgaatctggttgtagatatttatataagttcactaattaagatcacggtagtatatt
-gatagtgatgtctttgcaagaggttggccgaggaatttacggattctctattgatacaat
-ttgtctggcttataactcttaaggctgaaccaggcgtttttagacgacttgatcagctgt
-tagaatggtttggactccctctttcatgtcagtaacatttcagccgttattgttacgata
-tgcttgaacaatattgatctaccacacacccatagtatattttataggtcatgctgttac
-ctacgagcatggtattccacttcccattcaatgagtattcaacatcactagcctcagaga
-tgatgacccacctctaataacgtcacgttgcggccatgtgaaacctgaacttgagtagac
-gatatcaagcgctttaaattgcatataacatttgagggtaaagctaagcggatgctttat
-ataatcaatactcaataataagatttgattgcattttagagttatgacacgacatagttc
-actaacgagttactattcccagatctagactgaagtactgatcgagacgatccttacgtc
-gatgatcgttagttatcgacttaggtcgggtctctagcggtattggtacttaaccggaca
-ctatactaataacccatgatcaaagcataacagaatacagacgataatttcgccaacata
-tatgtacagaccccaagcatgagaagctcattgaaagctatcattgaagtcccgctcaca
-atgtgtcttttccagacggtttaactggttcccgggagtcctggagtttcgacttacata
-aatggaaacaatgtattttgctaatttatctatagcgtcatttggaccaatacagaatat
-tatgttgcctagtaatccactataacccgcaagtgctgatagaaaatttttagacgattt
-ataaatgccccaagtatccctcccgtgaatcctccgttatactaattagtattcgttcat
-acgtataccgcgcatatatgaacatttggcgataaggcgcgtgaattgttacgtgacaga
-gatagcagtttcttgtgatatggttaacagacgtacatgaagggaaactttatatctata
-gtgatgcttccgtagaaataccgccactggtctgccaatgatgaagtatgtagctttagg
-tttgtactatgaggctttcgtttgtttgcagagtataacagttgcgagtgaaaaaccgac
-gaatttatactaatacgctttcactattggctacaaaatagggaagagtttcaatcatga
-gagggagtatatggatgctttgtagctaaaggtagaacgtatgtatatgctgccgttcat
-tcttgaaagatacataagcgataagttacgacaattataagcaacatccctaccttcgta
-acgatttcactgttactgcgcttgaaatacactatggggctattggcggagagaagcaga
-tcgcgccgagcatatacgagacctataatgttgatgatagagaaggcgtctgaattgata
-catcgaagtacactttctttcgtagtatctctcgtcctctttctatctccggacacaaga
-attaagttatatatatagagtcttaccaatcatgttgaatcctgattctcagagttcttt
-ggcgggccttgtgatgactgagaaacaatgcaatattgctccaaatttcctaagcaaatt
-ctcggttatgttatgttatcagcaaagcgttacgttatgttatttaaatctggaatgacg
-gagcgaagttcttatgtcggtgtgggaataattcttttgaagacagcactccttaaataa
-tatcgctccgtgtttgtatttatcgaatgggtctgtaaccttgcacaagcaaatcggtgg
-tgtatatatcggataacaattaatacgatgttcatagtgacagtatactgatcgagtcct
-ctaaagtcaattacctcacttaacaatctcattgatgttgtgtcattcccggtatcgccc
-gtagtatgtgctctgattgaccgagtgtgaaccaaggaacatctactaatgcctttgtta
-ggtaagatctctctgaattccttcgtgccaacttaaaacattatcaaaatttcttctact
-tggattaactacttttacgagcatggcaaattcccctgtggaagacggttcattattatc
-ggaaaccttatagaaattgcgtgttgactgaaattagatttttattgtaagagttgcatc
-tttgcgattcctctggtctagcttccaatgaacagtcctcccttctattcgacatcgggt
-ccttcgtacatgtctttgcgatgtaataattaggttcggagtgtggccttaatgggtgca
-actaggaatacaacgcaaatttgctgacatgatagcaaatcggtatgccggcaccaaaac
-gtgctccttgcttagcttgtgaatgagactcagtagttaaataaatccatatctgcaatc
-gattccacaggtattgtccactatctttgaactactctaagagatacaagcttagctgag
-accgaggtgtatatgactacgctgatatctgtaaggtaccaatgcaggcaaagtatgcga
-gaagctaataccggctgtttccagctttataagattaaaatttggctgtcctggcggcct
-cagaattgttctatcgtaatcagttggttcattaattagctaagtacgaggtacaactta
-tctgtcccagaacagctccacaagtttttttacagccgaaacccctgtgtgaatcttaat
-atccaagcgcgttatctgattagagtttacaactcagtattttatcagtacgttttgttt
-ccaacattacccggtatgacaaaatgacgccacgtgtcgaataatggtctgaccaatgta
-ggaagtgaaaagataaatat
diff --git a/test/bench/shootout/fasta.c b/test/bench/shootout/fasta.c
deleted file mode 100644
index 64c1c52..0000000
--- a/test/bench/shootout/fasta.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*
- * http://shootout.alioth.debian.org/u32/program.php?test=fasta&lang=gcc&id=3
- */
-
-/*  The Computer Language Benchmarks Game
- *  http://shootout.alioth.debian.org/
- *
- *  contributed by Petr Prokhorenkov
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifndef fwrite_unlocked
-// not available on OS X 
-#define fwrite_unlocked fwrite
-#define fputc_unlocked fputc
-#define fputs_unlocked fputs
-#endif
-
-#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
-#define unlikely(x) __builtin_expect((x), 0)
-
-#define IM 139968
-#define IA 3877
-#define IC 29573
-
-#define LINE_LEN 60
-#define LOOKUP_SIZE 4096
-#define LOOKUP_SCALE ((float)(LOOKUP_SIZE - 1))
-
-typedef unsigned random_t;
-
-void
-random_init(random_t *random) {
-    *random = 42;
-}
-
-// Special version with result rescaled to LOOKUP_SCALE.
-static inline
-float
-random_next_lookup(random_t *random) {
-    *random = (*random*IA + IC)%IM;
-
-    return (*random)*(LOOKUP_SCALE/IM);
-}
-
-struct amino_acid {
-   char sym;
-   float prob;
-   float cprob_lookup;
-};
-
-void
-repeat(const char *alu, const char *title, int n) {
-    int len = strlen(alu);
-    char buffer[len + LINE_LEN];
-    int pos = 0;
-
-    memcpy(buffer, alu, len);
-    memcpy(buffer + len, alu, LINE_LEN);
-
-    fputs_unlocked(title, stdout);
-    while (n > 0) {
-        int bytes = n > LINE_LEN ? LINE_LEN : n;
-
-        fwrite_unlocked(buffer + pos, bytes, 1, stdout);
-        pos += bytes;
-        if (pos > len) {
-            pos -= len;
-        }
-        fputc_unlocked('\n', stdout);
-        n -= bytes;
-    }
-}
-
-/*
- * Lookup table contains mapping from real values to cumulative
- * probabilities. Careful selection of table size allows lookup
- * virtually in constant time.
- *
- * All cumulative probabilities are rescaled to LOOKUP_SCALE,
- * this allows to save one multiplication operation on each iteration
- * in randomize().
- */
-
-void *
-fill_lookup(struct amino_acid **lookup, struct amino_acid *amino_acid, int amino_acid_size) {
-    float p = 0;
-    int i, j;
-
-    for (i = 0; i < amino_acid_size; i++) {
-        p += amino_acid[i].prob;
-        amino_acid[i].cprob_lookup = p*LOOKUP_SCALE;
-    }
-
-    // Prevent rounding error.
-    amino_acid[amino_acid_size - 1].cprob_lookup = LOOKUP_SIZE - 1;
-
-    for (i = 0, j = 0; i < LOOKUP_SIZE; i++) {
-        while (amino_acid[j].cprob_lookup < i) {
-            j++;
-        }
-        lookup[i] = &amino_acid[j];
-    }
-
-    return 0;
-}
-
-void
-randomize(struct amino_acid *amino_acid, int amino_acid_size,
-        const char *title, int n, random_t *rand) {
-    struct amino_acid *lookup[LOOKUP_SIZE];
-    char line_buffer[LINE_LEN + 1];
-    int i, j;
-
-    line_buffer[LINE_LEN] = '\n';
-
-    fill_lookup(lookup, amino_acid, amino_acid_size);
-
-    fputs_unlocked(title, stdout);
-
-    for (i = 0, j = 0; i < n; i++, j++) {
-        if (j == LINE_LEN) {
-            fwrite_unlocked(line_buffer, LINE_LEN + 1, 1, stdout);
-            j = 0;
-        }
-
-        float r = random_next_lookup(rand);
-        struct amino_acid *u = lookup[(short)r];
-        while (unlikely(u->cprob_lookup < r)) {
-            ++u;
-        }
-        line_buffer[j] = u->sym;
-    }
-    line_buffer[j] = '\n';
-    fwrite_unlocked(line_buffer, j + 1, 1, stdout);
-}
-
-struct amino_acid amino_acid[] = {
-   { 'a', 0.27 },
-   { 'c', 0.12 },
-   { 'g', 0.12 },
-   { 't', 0.27 },
-
-   { 'B', 0.02 },
-   { 'D', 0.02 },
-   { 'H', 0.02 },
-   { 'K', 0.02 },
-   { 'M', 0.02 },
-   { 'N', 0.02 },
-   { 'R', 0.02 },
-   { 'S', 0.02 },
-   { 'V', 0.02 },
-   { 'W', 0.02 },
-   { 'Y', 0.02 },
-};
-
-struct amino_acid homo_sapiens[] = {
-   { 'a', 0.3029549426680 },
-   { 'c', 0.1979883004921 },
-   { 'g', 0.1975473066391 },
-   { 't', 0.3015094502008 },
-};
-
-static const char alu[] =
-   "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTG"
-   "GGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGA"
-   "GACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAA"
-   "AATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT"
-   "CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAAC"
-   "CCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTG"
-   "CACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";
-
-int
-main(int argc, const char **argv) {
-    int n = argc > 1 ? atoi( argv[1] ) : 512;
-    random_t rand;
-
-    random_init(&rand);
-
-    repeat(alu, ">ONE Homo sapiens alu\n", n*2);
-    randomize(amino_acid, ARRAY_SIZE(amino_acid),
-            ">TWO IUB ambiguity codes\n", n*3, &rand);
-    randomize(homo_sapiens, ARRAY_SIZE(homo_sapiens),
-            ">THREE Homo sapiens frequency\n", n*5, &rand);
-
-    return 0;
-}
diff --git a/test/bench/shootout/fasta.go b/test/bench/shootout/fasta.go
deleted file mode 100644
index 17ff5da..0000000
--- a/test/bench/shootout/fasta.go
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * Based on C program by by Petr Prokhorenkov.
- */
-
-package main
-
-import (
-	"flag"
-	"os"
-)
-
-var out = make(buffer, 0, 32768)
-
-var n = flag.Int("n", 1000, "length of result")
-
-const Line = 60
-
-func Repeat(alu []byte, n int) {
-	buf := append(alu, alu...)
-	off := 0
-	for n > 0 {
-		m := n
-		if m > Line {
-			m = Line
-		}
-		buf1 := out.NextWrite(m + 1)
-		copy(buf1, buf[off:])
-		buf1[m] = '\n'
-		if off += m; off >= len(alu) {
-			off -= len(alu)
-		}
-		n -= m
-	}
-}
-
-const (
-	IM = 139968
-	IA = 3877
-	IC = 29573
-
-	LookupSize          = 4096
-	LookupScale float64 = LookupSize - 1
-)
-
-var rand uint32 = 42
-
-type Acid struct {
-	sym   byte
-	prob  float64
-	cprob float64
-	next  *Acid
-}
-
-func computeLookup(acid []Acid) *[LookupSize]*Acid {
-	var lookup [LookupSize]*Acid
-	var p float64
-	for i := range acid {
-		p += acid[i].prob
-		acid[i].cprob = p * LookupScale
-		if i > 0 {
-			acid[i-1].next = &acid[i]
-		}
-	}
-	acid[len(acid)-1].cprob = 1.0 * LookupScale
-
-	j := 0
-	for i := range lookup {
-		for acid[j].cprob < float64(i) {
-			j++
-		}
-		lookup[i] = &acid[j]
-	}
-
-	return &lookup
-}
-
-func Random(acid []Acid, n int) {
-	lookup := computeLookup(acid)
-	for n > 0 {
-		m := n
-		if m > Line {
-			m = Line
-		}
-		buf := out.NextWrite(m + 1)
-		f := LookupScale / IM
-		myrand := rand
-		for i := 0; i < m; i++ {
-			myrand = (myrand*IA + IC) % IM
-			r := float64(int(myrand)) * f
-			a := lookup[int(r)]
-			for a.cprob < r {
-				a = a.next
-			}
-			buf[i] = a.sym
-		}
-		rand = myrand
-		buf[m] = '\n'
-		n -= m
-	}
-}
-
-func main() {
-	defer out.Flush()
-
-	flag.Parse()
-
-	iub := []Acid{
-		{prob: 0.27, sym: 'a'},
-		{prob: 0.12, sym: 'c'},
-		{prob: 0.12, sym: 'g'},
-		{prob: 0.27, sym: 't'},
-		{prob: 0.02, sym: 'B'},
-		{prob: 0.02, sym: 'D'},
-		{prob: 0.02, sym: 'H'},
-		{prob: 0.02, sym: 'K'},
-		{prob: 0.02, sym: 'M'},
-		{prob: 0.02, sym: 'N'},
-		{prob: 0.02, sym: 'R'},
-		{prob: 0.02, sym: 'S'},
-		{prob: 0.02, sym: 'V'},
-		{prob: 0.02, sym: 'W'},
-		{prob: 0.02, sym: 'Y'},
-	}
-
-	homosapiens := []Acid{
-		{prob: 0.3029549426680, sym: 'a'},
-		{prob: 0.1979883004921, sym: 'c'},
-		{prob: 0.1975473066391, sym: 'g'},
-		{prob: 0.3015094502008, sym: 't'},
-	}
-
-	alu := []byte(
-		"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" +
-			"GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" +
-			"CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" +
-			"ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" +
-			"GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" +
-			"AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" +
-			"AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA")
-
-	out.WriteString(">ONE Homo sapiens alu\n")
-	Repeat(alu, 2**n)
-	out.WriteString(">TWO IUB ambiguity codes\n")
-	Random(iub, 3**n)
-	out.WriteString(">THREE Homo sapiens frequency\n")
-	Random(homosapiens, 5**n)
-}
-
-type buffer []byte
-
-func (b *buffer) Flush() {
-	p := *b
-	if len(p) > 0 {
-		os.Stdout.Write(p)
-	}
-	*b = p[0:0]
-}
-
-func (b *buffer) WriteString(s string) {
-	p := b.NextWrite(len(s))
-	copy(p, s)
-}
-
-func (b *buffer) NextWrite(n int) []byte {
-	p := *b
-	if len(p)+n > cap(p) {
-		b.Flush()
-		p = *b
-	}
-	out := p[len(p) : len(p)+n]
-	*b = p[:len(p)+n]
-	return out
-}
diff --git a/test/bench/shootout/fasta.txt b/test/bench/shootout/fasta.txt
deleted file mode 100644
index f1caba0..0000000
--- a/test/bench/shootout/fasta.txt
+++ /dev/null
@@ -1,171 +0,0 @@
->ONE Homo sapiens alu
-GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA
-TCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACT
-AAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAG
-GCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCG
-CCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGT
-GGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCA
-GGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAA
-TTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAG
-AATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCA
-GCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGT
-AATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACC
-AGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTG
-GTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACC
-CGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAG
-AGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTT
-TGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACA
-TGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCT
-GTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGG
-TTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGT
-CTCAAAAAGGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGG
-CGGGCGGATCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCG
-TCTCTACTAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTA
-CTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCG
-AGATCGCGCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCG
-GGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACC
-TGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAA
-TACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGA
-GGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACT
-GCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGTGGCTC
-ACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGT
-TCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAATTAGC
-CGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCG
-CTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCAGCCTG
-GGCGACAGAGCGAGACTCCG
->TWO IUB ambiguity codes
-cttBtatcatatgctaKggNcataaaSatgtaaaDcDRtBggDtctttataattcBgtcg
-tactDtDagcctatttSVHtHttKtgtHMaSattgWaHKHttttagacatWatgtRgaaa
-NtactMcSMtYtcMgRtacttctWBacgaaatatagScDtttgaagacacatagtVgYgt
-cattHWtMMWcStgttaggKtSgaYaaccWStcgBttgcgaMttBYatcWtgacaYcaga
-gtaBDtRacttttcWatMttDBcatWtatcttactaBgaYtcttgttttttttYaaScYa
-HgtgttNtSatcMtcVaaaStccRcctDaataataStcYtRDSaMtDttgttSagtRRca
-tttHatSttMtWgtcgtatSSagactYaaattcaMtWatttaSgYttaRgKaRtccactt
-tattRggaMcDaWaWagttttgacatgttctacaaaRaatataataaMttcgDacgaSSt
-acaStYRctVaNMtMgtaggcKatcttttattaaaaagVWaHKYagtttttatttaacct
-tacgtVtcVaattVMBcttaMtttaStgacttagattWWacVtgWYagWVRctDattBYt
-gtttaagaagattattgacVatMaacattVctgtBSgaVtgWWggaKHaatKWcBScSWa
-accRVacacaaactaccScattRatatKVtactatatttHttaagtttSKtRtacaaagt
-RDttcaaaaWgcacatWaDgtDKacgaacaattacaRNWaatHtttStgttattaaMtgt
-tgDcgtMgcatBtgcttcgcgaDWgagctgcgaggggVtaaScNatttacttaatgacag
-cccccacatYScaMgtaggtYaNgttctgaMaacNaMRaacaaacaKctacatagYWctg
-ttWaaataaaataRattagHacacaagcgKatacBttRttaagtatttccgatctHSaat
-actcNttMaagtattMtgRtgaMgcataatHcMtaBSaRattagttgatHtMttaaKagg
-YtaaBataSaVatactWtataVWgKgttaaaacagtgcgRatatacatVtHRtVYataSa
-KtWaStVcNKHKttactatccctcatgWHatWaRcttactaggatctataDtDHBttata
-aaaHgtacVtagaYttYaKcctattcttcttaataNDaaggaaaDYgcggctaaWSctBa
-aNtgctggMBaKctaMVKagBaactaWaDaMaccYVtNtaHtVWtKgRtcaaNtYaNacg
-gtttNattgVtttctgtBaWgtaattcaagtcaVWtactNggattctttaYtaaagccgc
-tcttagHVggaYtgtNcDaVagctctctKgacgtatagYcctRYHDtgBattDaaDgccK
-tcHaaStttMcctagtattgcRgWBaVatHaaaataYtgtttagMDMRtaataaggatMt
-ttctWgtNtgtgaaaaMaatatRtttMtDgHHtgtcattttcWattRSHcVagaagtacg
-ggtaKVattKYagactNaatgtttgKMMgYNtcccgSKttctaStatatNVataYHgtNa
-BKRgNacaactgatttcctttaNcgatttctctataScaHtataRagtcRVttacDSDtt
-aRtSatacHgtSKacYagttMHtWataggatgactNtatSaNctataVtttRNKtgRacc
-tttYtatgttactttttcctttaaacatacaHactMacacggtWataMtBVacRaSaatc
-cgtaBVttccagccBcttaRKtgtgcctttttRtgtcagcRttKtaaacKtaaatctcac
-aattgcaNtSBaaccgggttattaaBcKatDagttactcttcattVtttHaaggctKKga
-tacatcBggScagtVcacattttgaHaDSgHatRMaHWggtatatRgccDttcgtatcga
-aacaHtaagttaRatgaVacttagattVKtaaYttaaatcaNatccRttRRaMScNaaaD
-gttVHWgtcHaaHgacVaWtgttScactaagSgttatcttagggDtaccagWattWtRtg
-ttHWHacgattBtgVcaYatcggttgagKcWtKKcaVtgaYgWctgYggVctgtHgaNcV
-taBtWaaYatcDRaaRtSctgaHaYRttagatMatgcatttNattaDttaattgttctaa
-ccctcccctagaWBtttHtBccttagaVaatMcBHagaVcWcagBVttcBtaYMccagat
-gaaaaHctctaacgttagNWRtcggattNatcRaNHttcagtKttttgWatWttcSaNgg
-gaWtactKKMaacatKatacNattgctWtatctaVgagctatgtRaHtYcWcttagccaa
-tYttWttaWSSttaHcaaaaagVacVgtaVaRMgattaVcDactttcHHggHRtgNcctt
-tYatcatKgctcctctatVcaaaaKaaaagtatatctgMtWtaaaacaStttMtcgactt
-taSatcgDataaactaaacaagtaaVctaggaSccaatMVtaaSKNVattttgHccatca
-cBVctgcaVatVttRtactgtVcaattHgtaaattaaattttYtatattaaRSgYtgBag
-aHSBDgtagcacRHtYcBgtcacttacactaYcgctWtattgSHtSatcataaatataHt
-cgtYaaMNgBaatttaRgaMaatatttBtttaaaHHKaatctgatWatYaacttMctctt
-ttVctagctDaaagtaVaKaKRtaacBgtatccaaccactHHaagaagaaggaNaaatBW
-attccgStaMSaMatBttgcatgRSacgttVVtaaDMtcSgVatWcaSatcttttVatag
-ttactttacgatcaccNtaDVgSRcgVcgtgaacgaNtaNatatagtHtMgtHcMtagaa
-attBgtataRaaaacaYKgtRccYtatgaagtaataKgtaaMttgaaRVatgcagaKStc
-tHNaaatctBBtcttaYaBWHgtVtgacagcaRcataWctcaBcYacYgatDgtDHccta
->THREE Homo sapiens frequency
-aacacttcaccaggtatcgtgaaggctcaagattacccagagaacctttgcaatataaga
-atatgtatgcagcattaccctaagtaattatattctttttctgactcaaagtgacaagcc
-ctagtgtatattaaatcggtatatttgggaaattcctcaaactatcctaatcaggtagcc
-atgaaagtgatcaaaaaagttcgtacttataccatacatgaattctggccaagtaaaaaa
-tagattgcgcaaaattcgtaccttaagtctctcgccaagatattaggatcctattactca
-tatcgtgtttttctttattgccgccatccccggagtatctcacccatccttctcttaaag
-gcctaatattacctatgcaaataaacatatattgttgaaaattgagaacctgatcgtgat
-tcttatgtgtaccatatgtatagtaatcacgcgactatatagtgctttagtatcgcccgt
-gggtgagtgaatattctgggctagcgtgagatagtttcttgtcctaatatttttcagatc
-gaatagcttctatttttgtgtttattgacatatgtcgaaactccttactcagtgaaagtc
-atgaccagatccacgaacaatcttcggaatcagtctcgttttacggcggaatcttgagtc
-taacttatatcccgtcgcttactttctaacaccccttatgtatttttaaaattacgttta
-ttcgaacgtacttggcggaagcgttattttttgaagtaagttacattgggcagactcttg
-acattttcgatacgactttctttcatccatcacaggactcgttcgtattgatatcagaag
-ctcgtgatgattagttgtcttctttaccaatactttgaggcctattctgcgaaatttttg
-ttgccctgcgaacttcacataccaaggaacacctcgcaacatgccttcatatccatcgtt
-cattgtaattcttacacaatgaatcctaagtaattacatccctgcgtaaaagatggtagg
-ggcactgaggatatattaccaagcatttagttatgagtaatcagcaatgtttcttgtatt
-aagttctctaaaatagttacatcgtaatgttatctcgggttccgcgaataaacgagatag
-attcattatatatggccctaagcaaaaacctcctcgtattctgttggtaattagaatcac
-acaatacgggttgagatattaattatttgtagtacgaagagatataaaaagatgaacaat
-tactcaagtcaagatgtatacgggatttataataaaaatcgggtagagatctgctttgca
-attcagacgtgccactaaatcgtaatatgtcgcgttacatcagaaagggtaactattatt
-aattaataaagggcttaatcactacatattagatcttatccgatagtcttatctattcgt
-tgtatttttaagcggttctaattcagtcattatatcagtgctccgagttctttattattg
-ttttaaggatgacaaaatgcctcttgttataacgctgggagaagcagactaagagtcgga
-gcagttggtagaatgaggctgcaaaagacggtctcgacgaatggacagactttactaaac
-caatgaaagacagaagtagagcaaagtctgaagtggtatcagcttaattatgacaaccct
-taatacttccctttcgccgaatactggcgtggaaaggttttaaaagtcgaagtagttaga
-ggcatctctcgctcataaataggtagactactcgcaatccaatgtgactatgtaatactg
-ggaacatcagtccgcgatgcagcgtgtttatcaaccgtccccactcgcctggggagacat
-gagaccacccccgtggggattattagtccgcagtaatcgactcttgacaatccttttcga
-ttatgtcatagcaatttacgacagttcagcgaagtgactactcggcgaaatggtattact
-aaagcattcgaacccacatgaatgtgattcttggcaatttctaatccactaaagcttttc
-cgttgaatctggttgtagatatttatataagttcactaattaagatcacggtagtatatt
-gatagtgatgtctttgcaagaggttggccgaggaatttacggattctctattgatacaat
-ttgtctggcttataactcttaaggctgaaccaggcgtttttagacgacttgatcagctgt
-tagaatggtttggactccctctttcatgtcagtaacatttcagccgttattgttacgata
-tgcttgaacaatattgatctaccacacacccatagtatattttataggtcatgctgttac
-ctacgagcatggtattccacttcccattcaatgagtattcaacatcactagcctcagaga
-tgatgacccacctctaataacgtcacgttgcggccatgtgaaacctgaacttgagtagac
-gatatcaagcgctttaaattgcatataacatttgagggtaaagctaagcggatgctttat
-ataatcaatactcaataataagatttgattgcattttagagttatgacacgacatagttc
-actaacgagttactattcccagatctagactgaagtactgatcgagacgatccttacgtc
-gatgatcgttagttatcgacttaggtcgggtctctagcggtattggtacttaaccggaca
-ctatactaataacccatgatcaaagcataacagaatacagacgataatttcgccaacata
-tatgtacagaccccaagcatgagaagctcattgaaagctatcattgaagtcccgctcaca
-atgtgtcttttccagacggtttaactggttcccgggagtcctggagtttcgacttacata
-aatggaaacaatgtattttgctaatttatctatagcgtcatttggaccaatacagaatat
-tatgttgcctagtaatccactataacccgcaagtgctgatagaaaatttttagacgattt
-ataaatgccccaagtatccctcccgtgaatcctccgttatactaattagtattcgttcat
-acgtataccgcgcatatatgaacatttggcgataaggcgcgtgaattgttacgtgacaga
-gatagcagtttcttgtgatatggttaacagacgtacatgaagggaaactttatatctata
-gtgatgcttccgtagaaataccgccactggtctgccaatgatgaagtatgtagctttagg
-tttgtactatgaggctttcgtttgtttgcagagtataacagttgcgagtgaaaaaccgac
-gaatttatactaatacgctttcactattggctacaaaatagggaagagtttcaatcatga
-gagggagtatatggatgctttgtagctaaaggtagaacgtatgtatatgctgccgttcat
-tcttgaaagatacataagcgataagttacgacaattataagcaacatccctaccttcgta
-acgatttcactgttactgcgcttgaaatacactatggggctattggcggagagaagcaga
-tcgcgccgagcatatacgagacctataatgttgatgatagagaaggcgtctgaattgata
-catcgaagtacactttctttcgtagtatctctcgtcctctttctatctccggacacaaga
-attaagttatatatatagagtcttaccaatcatgttgaatcctgattctcagagttcttt
-ggcgggccttgtgatgactgagaaacaatgcaatattgctccaaatttcctaagcaaatt
-ctcggttatgttatgttatcagcaaagcgttacgttatgttatttaaatctggaatgacg
-gagcgaagttcttatgtcggtgtgggaataattcttttgaagacagcactccttaaataa
-tatcgctccgtgtttgtatttatcgaatgggtctgtaaccttgcacaagcaaatcggtgg
-tgtatatatcggataacaattaatacgatgttcatagtgacagtatactgatcgagtcct
-ctaaagtcaattacctcacttaacaatctcattgatgttgtgtcattcccggtatcgccc
-gtagtatgtgctctgattgaccgagtgtgaaccaaggaacatctactaatgcctttgtta
-ggtaagatctctctgaattccttcgtgccaacttaaaacattatcaaaatttcttctact
-tggattaactacttttacgagcatggcaaattcccctgtggaagacggttcattattatc
-ggaaaccttatagaaattgcgtgttgactgaaattagatttttattgtaagagttgcatc
-tttgcgattcctctggtctagcttccaatgaacagtcctcccttctattcgacatcgggt
-ccttcgtacatgtctttgcgatgtaataattaggttcggagtgtggccttaatgggtgca
-actaggaatacaacgcaaatttgctgacatgatagcaaatcggtatgccggcaccaaaac
-gtgctccttgcttagcttgtgaatgagactcagtagttaaataaatccatatctgcaatc
-gattccacaggtattgtccactatctttgaactactctaagagatacaagcttagctgag
-accgaggtgtatatgactacgctgatatctgtaaggtaccaatgcaggcaaagtatgcga
-gaagctaataccggctgtttccagctttataagattaaaatttggctgtcctggcggcct
-cagaattgttctatcgtaatcagttggttcattaattagctaagtacgaggtacaactta
-tctgtcccagaacagctccacaagtttttttacagccgaaacccctgtgtgaatcttaat
-atccaagcgcgttatctgattagagtttacaactcagtattttatcagtacgttttgttt
-ccaacattacccggtatgacaaaatgacgccacgtgtcgaataatggtctgaccaatgta
-ggaagtgaaaagataaatat
diff --git a/test/bench/shootout/k-nucleotide-parallel.go b/test/bench/shootout/k-nucleotide-parallel.go
deleted file mode 100644
index 96c80d8..0000000
--- a/test/bench/shootout/k-nucleotide-parallel.go
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- */
-
-package main
-
-import (
-	"bufio"
-	"bytes"
-	"fmt"
-	"io/ioutil"
-	"os"
-	"runtime"
-	"sort"
-)
-
-func count(data string, n int) map[string]int {
-	counts := make(map[string]int)
-	top := len(data) - n
-	for i := 0; i <= top; i++ {
-		s := data[i : i+n]
-		counts[s]++
-	}
-	return counts
-}
-
-func countOne(data string, s string) int {
-	return count(data, len(s))[s]
-}
-
-type kNuc struct {
-	name  string
-	count int
-}
-
-type kNucArray []kNuc
-
-func (kn kNucArray) Len() int      { return len(kn) }
-func (kn kNucArray) Swap(i, j int) { kn[i], kn[j] = kn[j], kn[i] }
-func (kn kNucArray) Less(i, j int) bool {
-	if kn[i].count == kn[j].count {
-		return kn[i].name > kn[j].name // sort down
-	}
-	return kn[i].count > kn[j].count
-}
-
-func sortedArray(m map[string]int) kNucArray {
-	kn := make(kNucArray, len(m))
-	i := 0
-	for k, v := range m {
-		kn[i] = kNuc{k, v}
-		i++
-	}
-	sort.Sort(kn)
-	return kn
-}
-
-func printKnucs(a kNucArray) {
-	sum := 0
-	for _, kn := range a {
-		sum += kn.count
-	}
-	for _, kn := range a {
-		fmt.Printf("%s %.3f\n", kn.name, 100*float64(kn.count)/float64(sum))
-	}
-	fmt.Print("\n")
-}
-
-func main() {
-	runtime.GOMAXPROCS(4)
-	in := bufio.NewReader(os.Stdin)
-	three := []byte(">THREE ")
-	for {
-		line, err := in.ReadSlice('\n')
-		if err != nil {
-			fmt.Fprintln(os.Stderr, "ReadLine err:", err)
-			os.Exit(2)
-		}
-		if line[0] == '>' && bytes.Equal(line[0:len(three)], three) {
-			break
-		}
-	}
-	data, err := ioutil.ReadAll(in)
-	if err != nil {
-		fmt.Fprintln(os.Stderr, "ReadAll err:", err)
-		os.Exit(2)
-	}
-	// delete the newlines and convert to upper case
-	j := 0
-	for i := 0; i < len(data); i++ {
-		if data[i] != '\n' {
-			data[j] = data[i] &^ ' ' // upper case
-			j++
-		}
-	}
-	str := string(data[0:j])
-
-	var arr1, arr2 kNucArray
-	countsdone := make(chan bool)
-	go func() {
-		arr1 = sortedArray(count(str, 1))
-		countsdone <- true
-	}()
-	go func() {
-		arr2 = sortedArray(count(str, 2))
-		countsdone <- true
-	}()
-
-	interests := []string{"GGT", "GGTA", "GGTATT", "GGTATTTTAATT", "GGTATTTTAATTTATAGT"}
-	results := make([]chan string, len(interests))
-	for i, s := range interests {
-		ch := make(chan string)
-		results[i] = ch
-		go func(result chan string, ss string) {
-			result <- fmt.Sprintf("%d %s\n", countOne(str, ss), ss)
-		}(ch, s)
-	}
-	<-countsdone
-	<-countsdone
-	printKnucs(arr1)
-	printKnucs(arr2)
-	for _, rc := range results {
-		fmt.Print(<-rc)
-	}
-
-}
diff --git a/test/bench/shootout/k-nucleotide-parallel.txt b/test/bench/shootout/k-nucleotide-parallel.txt
deleted file mode 100644
index 84169b8..0000000
--- a/test/bench/shootout/k-nucleotide-parallel.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-T 31.520
-A 29.600
-C 19.480
-G 19.400
-
-AT 9.922
-TT 9.602
-TA 9.402
-AA 8.402
-GA 6.321
-TC 6.301
-TG 6.201
-GT 6.041
-CT 5.961
-AG 5.841
-CA 5.461
-AC 5.441
-CC 4.041
-CG 4.021
-GC 3.701
-GG 3.341
-
-54 GGT
-24 GGTA
-4 GGTATT
-0 GGTATTTTAATT
-0 GGTATTTTAATTTATAGT
diff --git a/test/bench/shootout/k-nucleotide.c b/test/bench/shootout/k-nucleotide.c
deleted file mode 100644
index 9c30620..0000000
--- a/test/bench/shootout/k-nucleotide.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <glib.h>
-
-typedef struct stat_s stat_t;
-struct stat_s
-{
-   const gchar *key;
-   long stat;
-};
-
-#define MAX_ELM (8192 / sizeof (stat_t))
-
-static int
-generate_frequencies (int fl, char *buffer, long buflen,
-		      GHashTable *ht, GTrashStack **ts, GPtrArray *roots, GStringChunk *sc)
-{
-   gchar *key;
-   long i;
-
-   if (fl > buflen) return 0;
-   if (fl == 0) return 0;
-
-   for (i = 0; i < buflen - fl + 1; ++i)
-     {
-	char nulled;
-	stat_t *stat;
-
-	nulled = buffer[i + fl];
-	buffer[i + fl] = '\0';
-
-	key = g_string_chunk_insert_const(sc, buffer + i);
-
-	stat = g_hash_table_lookup(ht, key);
-	if (!stat)
-	  {
-	     stat = g_trash_stack_pop(ts);
-	     if (!stat)
-	       {
-		  int j;
-
-		  stat = malloc(sizeof (stat_t) * MAX_ELM);
-		  g_ptr_array_add(roots, stat);
-
-		  for (j = 1; j < MAX_ELM; ++j)
-		    g_trash_stack_push(ts, stat + j);
-	       }
-	     stat->stat = 1;
-	     stat->key = key;
-
-	     g_hash_table_insert(ht, key, stat);
-	  }
-	else
-	  stat->stat++;
-
-	buffer[i + fl] = nulled;
-     }
-
-   return buflen - fl + 1;
-}
-
-static int
-cmp_func(gconstpointer a, gconstpointer b)
-{
-   const stat_t *left = a;
-   const stat_t *right = b;
-
-   return right->stat - left->stat;
-}
-
-static void
-sorted_list(gpointer key, gpointer value, gpointer user_data)
-{
-   stat_t *data = value;
-   GList **lst = user_data;
-
-   *lst = g_list_insert_sorted(*lst, data, cmp_func);
-}
-
-static void
-display_stat(gpointer data, gpointer user_data)
-{
-   long *total = user_data;
-   stat_t *st = data;
-
-   printf("%s %.3f\n", st->key, 100 * (float) st->stat / *total);
-}
-
-void
-write_frequencies (int fl, char *buffer, long buflen, GTrashStack **ts, GPtrArray *roots)
-{
-   GStringChunk *sc;
-   GHashTable *ht;
-   GList *lst;
-   long total;
-
-   ht = g_hash_table_new_full(g_str_hash, g_str_equal, NULL /* free key */, NULL /* free value */);
-   sc = g_string_chunk_new(buflen);
-   lst = NULL;
-
-   total = generate_frequencies (fl, buffer, buflen, ht, ts, roots, sc);
-
-   if (!total) goto on_error;
-
-   g_hash_table_foreach(ht, sorted_list, &lst);
-   g_list_foreach(lst, display_stat, &total);
-   g_list_free(lst);
-
- on_error:
-   g_hash_table_destroy(ht);
-   g_string_chunk_free(sc);
-}
-
-void
-write_count (char *searchFor, char *buffer, long buflen, GTrashStack **ts, GPtrArray *roots)
-{
-   GStringChunk *sc;
-   GHashTable *ht;
-   stat_t *result;
-   GList *lst;
-   long total;
-   long fl;
-
-   fl = strlen(searchFor);
-
-   ht = g_hash_table_new_full(g_str_hash, g_str_equal, NULL /* free key */, NULL /* free value */);
-   sc = g_string_chunk_new(buflen);
-   lst = NULL;
-   result = NULL;
-
-   total = generate_frequencies (fl, buffer, buflen, ht, ts, roots, sc);
-
-   if (!total) goto on_error;
-
-   result = g_hash_table_lookup(ht, searchFor);
-
- on_error:
-   printf("%ld\t%s\n", result ? result->stat : 0, searchFor);
-
-   g_hash_table_destroy(ht);
-   g_string_chunk_free(sc);
-}
-
-int
-main ()
-{
-   char buffer[4096];
-   GTrashStack *ts;
-   GPtrArray *roots;
-   GString *stuff;
-   gchar *s;
-   int len;
-
-   roots = g_ptr_array_new();
-   ts = NULL;
-
-   while (fgets(buffer, sizeof (buffer), stdin))
-     if (strncmp(buffer, ">THREE", 6) == 0)
-       break;
-
-   stuff = g_string_new(NULL);
-
-   while (fgets(buffer, sizeof (buffer), stdin))
-     {
-	size_t sz;
-
-	if (buffer[0] == '>')
-	  break;
-
-	sz = strlen(buffer);
-	if (buffer[sz - 1] == '\n')
-	  --sz;
-
-	stuff = g_string_append_len(stuff, buffer, sz);
-     }
-
-   stuff = g_string_ascii_up(stuff);
-   len = stuff->len;
-   s = g_string_free(stuff, FALSE);
-
-   write_frequencies(1, s, len, &ts, roots);
-   printf("\n");
-   write_frequencies(2, s, len, &ts, roots);
-   printf("\n");
-   write_count("GGT", s, len, &ts, roots);
-   write_count("GGTA", s, len, &ts, roots);
-   write_count("GGTATT", s, len, &ts, roots);
-   write_count("GGTATTTTAATT", s, len, &ts, roots);
-   write_count("GGTATTTTAATTTATAGT", s, len, &ts, roots);
-
-   free(s);
-
-   g_ptr_array_foreach(roots, (GFunc)free, NULL);
-   g_ptr_array_free(roots, TRUE);
-
-   return 0;
-}
diff --git a/test/bench/shootout/k-nucleotide.go b/test/bench/shootout/k-nucleotide.go
deleted file mode 100644
index fdc98ed..0000000
--- a/test/bench/shootout/k-nucleotide.go
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- */
-
-package main
-
-import (
-	"bufio"
-	"bytes"
-	"fmt"
-	"io/ioutil"
-	"os"
-	"sort"
-)
-
-var in *bufio.Reader
-
-func count(data string, n int) map[string]int {
-	counts := make(map[string]int)
-	top := len(data) - n
-	for i := 0; i <= top; i++ {
-		s := data[i : i+n]
-		counts[s]++
-	}
-	return counts
-}
-
-func countOne(data string, s string) int {
-	return count(data, len(s))[s]
-}
-
-type kNuc struct {
-	name  string
-	count int
-}
-
-type kNucArray []kNuc
-
-func (kn kNucArray) Len() int      { return len(kn) }
-func (kn kNucArray) Swap(i, j int) { kn[i], kn[j] = kn[j], kn[i] }
-func (kn kNucArray) Less(i, j int) bool {
-	if kn[i].count == kn[j].count {
-		return kn[i].name > kn[j].name // sort down
-	}
-	return kn[i].count > kn[j].count
-}
-
-func sortedArray(m map[string]int) kNucArray {
-	kn := make(kNucArray, len(m))
-	i := 0
-	for k, v := range m {
-		kn[i].name = k
-		kn[i].count = v
-		i++
-	}
-	sort.Sort(kn)
-	return kn
-}
-
-func print(m map[string]int) {
-	a := sortedArray(m)
-	sum := 0
-	for _, kn := range a {
-		sum += kn.count
-	}
-	for _, kn := range a {
-		fmt.Printf("%s %.3f\n", kn.name, 100*float64(kn.count)/float64(sum))
-	}
-}
-
-func main() {
-	in = bufio.NewReader(os.Stdin)
-	three := []byte(">THREE ")
-	for {
-		line, err := in.ReadSlice('\n')
-		if err != nil {
-			fmt.Fprintln(os.Stderr, "ReadLine err:", err)
-			os.Exit(2)
-		}
-		if line[0] == '>' && bytes.Equal(line[0:len(three)], three) {
-			break
-		}
-	}
-	data, err := ioutil.ReadAll(in)
-	if err != nil {
-		fmt.Fprintln(os.Stderr, "ReadAll err:", err)
-		os.Exit(2)
-	}
-	// delete the newlines and convert to upper case
-	j := 0
-	for i := 0; i < len(data); i++ {
-		if data[i] != '\n' {
-			data[j] = data[i] &^ ' ' // upper case
-			j++
-		}
-	}
-	str := string(data[0:j])
-
-	print(count(str, 1))
-	fmt.Print("\n")
-
-	print(count(str, 2))
-	fmt.Print("\n")
-
-	interests := []string{"GGT", "GGTA", "GGTATT", "GGTATTTTAATT", "GGTATTTTAATTTATAGT"}
-	for _, s := range interests {
-		fmt.Printf("%d %s\n", countOne(str, s), s)
-	}
-}
diff --git a/test/bench/shootout/k-nucleotide.txt b/test/bench/shootout/k-nucleotide.txt
deleted file mode 100644
index 84169b8..0000000
--- a/test/bench/shootout/k-nucleotide.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-T 31.520
-A 29.600
-C 19.480
-G 19.400
-
-AT 9.922
-TT 9.602
-TA 9.402
-AA 8.402
-GA 6.321
-TC 6.301
-TG 6.201
-GT 6.041
-CT 5.961
-AG 5.841
-CA 5.461
-AC 5.441
-CC 4.041
-CG 4.021
-GC 3.701
-GG 3.341
-
-54 GGT
-24 GGTA
-4 GGTATT
-0 GGTATTTTAATT
-0 GGTATTTTAATTTATAGT
diff --git a/test/bench/shootout/mandelbrot.c b/test/bench/shootout/mandelbrot.c
deleted file mode 100644
index c177c08..0000000
--- a/test/bench/shootout/mandelbrot.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Shootout
-   http://shootout.alioth.debian.org/
-
-   contributed by Greg Buchholz
-
-   for the debian (AMD) machine...
-   compile flags:  -O3 -ffast-math -march=athlon-xp -funroll-loops
-
-   for the gp4 (Intel) machine...
-   compile flags:  -O3 -ffast-math -march=pentium4 -funroll-loops
-*/
-
-#include<stdio.h>
-
-int main (int argc, char **argv)
-{
-    int w, h, bit_num = 0;
-    char byte_acc = 0;
-    int i, iter = 50;
-    double x, y, limit = 2.0;
-    double Zr, Zi, Cr, Ci, Tr, Ti;
-
-    w = h = atoi(argv[1]);
-
-    printf("P4\n%d %d\n",w,h);
-
-    for(y=0;y<h;++y)
-    {
-        for(x=0;x<w;++x)
-        {
-            Zr = Zi = Tr = Ti = 0.0;
-            Cr = (2.0*x/w - 1.5); Ci=(2.0*y/h - 1.0);
-
-            for (i=0;i<iter && (Tr+Ti <= limit*limit);++i)
-            {
-                Zi = 2.0*Zr*Zi + Ci;
-                Zr = Tr - Ti + Cr;
-                Tr = Zr * Zr;
-                Ti = Zi * Zi;
-            }
-
-            byte_acc <<= 1;
-            if(Tr+Ti <= limit*limit) byte_acc |= 0x01;
-
-            ++bit_num;
-
-            if(bit_num == 8)
-            {
-                putc(byte_acc,stdout);
-                byte_acc = 0;
-                bit_num = 0;
-            }
-            else if(x == w-1)
-            {
-                byte_acc <<= (8-w%8);
-                putc(byte_acc,stdout);
-                byte_acc = 0;
-                bit_num = 0;
-            }
-        }
-    }
-}
diff --git a/test/bench/shootout/mandelbrot.go b/test/bench/shootout/mandelbrot.go
deleted file mode 100644
index df60343..0000000
--- a/test/bench/shootout/mandelbrot.go
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * Based on mandelbrot.c contributed by Greg Buchholz
- */
-
-package main
-
-import (
-	"bufio"
-	"flag"
-	"fmt"
-	"os"
-)
-
-var n = flag.Int("n", 200, "size")
-
-func main() {
-	flag.Parse()
-	out := bufio.NewWriter(os.Stdout)
-	defer out.Flush()
-
-	w := float64(*n)
-	h := float64(*n)
-	bit_num := 0
-	byte_acc := byte(0)
-	const Iter = 50
-	const Zero float64 = 0
-	const Limit = 2.0
-
-	fmt.Fprintf(out, "P4\n%d %d\n", *n, *n)
-
-	for y := 0.0; y < h; y++ {
-		for x := 0.0; x < w; x++ {
-			Zr, Zi, Tr, Ti := Zero, Zero, Zero, Zero
-			Cr := (2*x/w - 1.5)
-			Ci := (2*y/h - 1.0)
-
-			for i := 0; i < Iter && (Tr+Ti <= Limit*Limit); i++ {
-				Zi = 2*Zr*Zi + Ci
-				Zr = Tr - Ti + Cr
-				Tr = Zr * Zr
-				Ti = Zi * Zi
-			}
-
-			byte_acc <<= 1
-			if Tr+Ti <= Limit*Limit {
-				byte_acc |= 0x01
-			}
-
-			bit_num++
-
-			if bit_num == 8 {
-				out.WriteByte(byte_acc)
-				byte_acc = 0
-				bit_num = 0
-			} else if x == w-1 {
-				byte_acc <<= uint(8 - uint(*n)%8)
-				out.WriteByte(byte_acc)
-				byte_acc = 0
-				bit_num = 0
-			}
-		}
-	}
-}
diff --git a/test/bench/shootout/mandelbrot.txt b/test/bench/shootout/mandelbrot.txt
deleted file mode 100644
index 2f7bbbc..0000000
Binary files a/test/bench/shootout/mandelbrot.txt and /dev/null differ
diff --git a/test/bench/shootout/meteor-contest.c b/test/bench/shootout/meteor-contest.c
deleted file mode 100644
index 19c4340..0000000
--- a/test/bench/shootout/meteor-contest.c
+++ /dev/null
@@ -1,626 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by Christian Vosteen
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#define TRUE 1
-#define FALSE 0
-
-/* The board is a 50 cell hexagonal pattern.  For    . . . . .
- * maximum speed the board will be implemented as     . . . . .
- * 50 bits, which will fit into a 64 bit long long   . . . . .
- * int.                                               . . . . .
- *                                                   . . . . .
- * I will represent 0's as empty cells and 1's        . . . . .
- * as full cells.                                    . . . . .
- *                                                    . . . . .
- *                                                   . . . . .
- *                                                    . . . . .
- */
-
-unsigned long long board = 0xFFFC000000000000ULL;
-
-/* The puzzle pieces must be specified by the path followed
- * from one end to the other along 12 hexagonal directions.
- *
- *   Piece 0   Piece 1   Piece 2   Piece 3   Piece 4
- *
- *  O O O O    O   O O   O O O     O O O     O   O
- *         O    O O           O       O       O O
- *                           O         O         O
- *
- *   Piece 5   Piece 6   Piece 7   Piece 8   Piece 9
- *
- *    O O O     O O       O O     O O        O O O O
- *       O O       O O       O       O O O        O
- *                  O       O O
- *
- * I had to make it 12 directions because I wanted all of the
- * piece definitions to fit into the same size arrays.  It is
- * not possible to define piece 4 in terms of the 6 cardinal
- * directions in 4 moves.
- */
-
-#define E     0
-#define ESE   1
-#define SE    2
-#define S     3
-#define SW    4
-#define WSW   5
-#define W     6
-#define WNW   7
-#define NW    8
-#define N     9
-#define NE    10
-#define ENE   11
-#define PIVOT 12
-
-char piece_def[10][4] = {
-   {  E,  E,  E, SE},
-   { SE,  E, NE,  E},
-   {  E,  E, SE, SW},
-   {  E,  E, SW, SE},
-   { SE,  E, NE,  S},
-   {  E,  E, SW,  E},
-   {  E, SE, SE, NE},
-   {  E, SE, SE,  W},
-   {  E, SE,  E,  E},
-   {  E,  E,  E, SW}
-};
-
-
-/* To minimize the amount of work done in the recursive solve function below,
- * I'm going to allocate enough space for all legal rotations of each piece
- * at each position on the board. That's 10 pieces x 50 board positions x
- * 12 rotations.  However, not all 12 rotations will fit on every cell, so
- * I'll have to keep count of the actual number that do.
- * The pieces are going to be unsigned long long ints just like the board so
- * they can be bitwise-anded with the board to determine if they fit.
- * I'm also going to record the next possible open cell for each piece and
- * location to reduce the burden on the solve function.
- */
-unsigned long long pieces[10][50][12];
-int piece_counts[10][50];
-char next_cell[10][50][12];
-
-/* Returns the direction rotated 60 degrees clockwise */
-char rotate(char dir) {
-   return (dir + 2) % PIVOT;
-}
-
-/* Returns the direction flipped on the horizontal axis */
-char flip(char dir) {
-   return (PIVOT - dir) % PIVOT;
-}
-
-
-/* Returns the new cell index from the specified cell in the
- * specified direction.  The index is only valid if the
- * starting cell and direction have been checked by the
- * out_of_bounds function first.
- */
-char shift(char cell, char dir) {
-   switch(dir) {
-      case E:
-         return cell + 1;
-      case ESE:
-         if((cell / 5) % 2)
-            return cell + 7;
-         else
-            return cell + 6;
-      case SE:
-         if((cell / 5) % 2)
-            return cell + 6;
-         else
-            return cell + 5;
-      case S:
-         return cell + 10;
-      case SW:
-         if((cell / 5) % 2)
-            return cell + 5;
-         else
-            return cell + 4;
-      case WSW:
-         if((cell / 5) % 2)
-            return cell + 4;
-         else
-            return cell + 3;
-      case W:
-         return cell - 1;
-      case WNW:
-         if((cell / 5) % 2)
-            return cell - 6;
-         else
-            return cell - 7;
-      case NW:
-         if((cell / 5) % 2)
-            return cell - 5;
-         else
-            return cell - 6;
-      case N:
-         return cell - 10;
-      case NE:
-         if((cell / 5) % 2)
-            return cell - 4;
-         else
-            return cell - 5;
-      case ENE:
-         if((cell / 5) % 2)
-            return cell - 3;
-         else
-            return cell - 4;
-      default:
-         return cell;
-   }
-}
-
-/* Returns wether the specified cell and direction will land outside
- * of the board.  Used to determine if a piece is at a legal board
- * location or not.
- */
-char out_of_bounds(char cell, char dir) {
-   char i;
-   switch(dir) {
-      case E:
-         return cell % 5 == 4;
-      case ESE:
-         i = cell % 10;
-         return i == 4 || i == 8 || i == 9 || cell >= 45;
-      case SE:
-         return cell % 10 == 9 || cell >= 45;
-      case S:
-         return cell >= 40;
-      case SW:
-         return cell % 10 == 0 || cell >= 45;
-      case WSW:
-         i = cell % 10;
-         return i == 0 || i == 1 || i == 5 || cell >= 45;
-      case W:
-         return cell % 5 == 0;
-      case WNW:
-         i = cell % 10;
-         return i == 0 || i == 1 || i == 5 || cell < 5;
-      case NW:
-         return cell % 10 == 0 || cell < 5;
-      case N:
-         return cell < 10;
-      case NE:
-         return cell % 10 == 9 || cell < 5;
-      case ENE:
-         i = cell % 10;
-         return i == 4 || i == 8 || i == 9 || cell < 5;
-      default:
-         return FALSE;
-   }
-}
-
-/* Rotate a piece 60 degrees clockwise */
-void rotate_piece(int piece) {
-   int i;
-   for(i = 0; i < 4; i++)
-      piece_def[piece][i] = rotate(piece_def[piece][i]);
-}
-
-/* Flip a piece along the horizontal axis */
-void flip_piece(int piece) {
-   int i;
-   for(i = 0; i < 4; i++)
-      piece_def[piece][i] = flip(piece_def[piece][i]);
-}
-
-/* Convenience function to quickly calculate all of the indices for a piece */
-void calc_cell_indices(char *cell, int piece, char index) {
-   cell[0] = index;
-   cell[1] = shift(cell[0], piece_def[piece][0]);
-   cell[2] = shift(cell[1], piece_def[piece][1]);
-   cell[3] = shift(cell[2], piece_def[piece][2]);
-   cell[4] = shift(cell[3], piece_def[piece][3]);
-}
-
-/* Convenience function to quickly calculate if a piece fits on the board */
-int cells_fit_on_board(char *cell, int piece) {
-   return (!out_of_bounds(cell[0], piece_def[piece][0]) &&
-         !out_of_bounds(cell[1], piece_def[piece][1]) &&
-         !out_of_bounds(cell[2], piece_def[piece][2]) &&
-         !out_of_bounds(cell[3], piece_def[piece][3]));
-}
-
-/* Returns the lowest index of the cells of a piece.
- * I use the lowest index that a piece occupies as the index for looking up
- * the piece in the solve function.
- */
-char minimum_of_cells(char *cell) {
-   char minimum = cell[0];
-   minimum = cell[1] < minimum ? cell[1] : minimum;
-   minimum = cell[2] < minimum ? cell[2] : minimum;
-   minimum = cell[3] < minimum ? cell[3] : minimum;
-   minimum = cell[4] < minimum ? cell[4] : minimum;
-   return minimum;
-}
-
-/* Calculate the lowest possible open cell if the piece is placed on the board.
- * Used to later reduce the amount of time searching for open cells in the
- * solve function.
- */
-char first_empty_cell(char *cell, char minimum) {
-   char first_empty = minimum;
-   while(first_empty == cell[0] || first_empty == cell[1] ||
-         first_empty == cell[2] || first_empty == cell[3] ||
-         first_empty == cell[4])
-      first_empty++;
-   return first_empty;
-}
-
-/* Generate the unsigned long long int that will later be anded with the
- * board to determine if it fits.
- */
-unsigned long long bitmask_from_cells(char *cell) {
-   unsigned long long piece_mask = 0ULL;
-   int i;
-   for(i = 0; i < 5; i++)
-      piece_mask |= 1ULL << cell[i];
-   return piece_mask;
-}
-
-/* Record the piece and other important information in arrays that will
- * later be used by the solve function.
- */
-void record_piece(int piece, int minimum, char first_empty,
-      unsigned long long piece_mask) {
-   pieces[piece][minimum][piece_counts[piece][minimum]] = piece_mask;
-   next_cell[piece][minimum][piece_counts[piece][minimum]] = first_empty;
-   piece_counts[piece][minimum]++;
-}
-
-
-/* Fill the entire board going cell by cell.  If any cells are "trapped"
- * they will be left alone.
- */
-void fill_contiguous_space(char *board, int index) {
-   if(board[index] == 1)
-      return;
-   board[index] = 1;
-   if(!out_of_bounds(index, E))
-      fill_contiguous_space(board, shift(index, E));
-   if(!out_of_bounds(index, SE))
-      fill_contiguous_space(board, shift(index, SE));
-   if(!out_of_bounds(index, SW))
-      fill_contiguous_space(board, shift(index, SW));
-   if(!out_of_bounds(index, W))
-      fill_contiguous_space(board, shift(index, W));
-   if(!out_of_bounds(index, NW))
-      fill_contiguous_space(board, shift(index, NW));
-   if(!out_of_bounds(index, NE))
-      fill_contiguous_space(board, shift(index, NE));
-}
-
-
-/* To thin the number of pieces, I calculate if any of them trap any empty
- * cells at the edges.  There are only a handful of exceptions where the
- * the board can be solved with the trapped cells.  For example:  piece 8 can
- * trap 5 cells in the corner, but piece 3 can fit in those cells, or piece 0
- * can split the board in half where both halves are viable.
- */
-int has_island(char *cell, int piece) {
-   char temp_board[50];
-   char c;
-   int i;
-   for(i = 0; i < 50; i++)
-      temp_board[i] = 0;
-   for(i = 0; i < 5; i++)
-      temp_board[((int)cell[i])] = 1;
-   i = 49;
-   while(temp_board[i] == 1)
-      i--;
-   fill_contiguous_space(temp_board, i);
-   c = 0;
-   for(i = 0; i < 50; i++)
-      if(temp_board[i] == 0)
-         c++;
-   if(c == 0 || (c == 5 && piece == 8) || (c == 40 && piece == 8) ||
-         (c % 5 == 0 && piece == 0))
-      return FALSE;
-   else
-      return TRUE;
-}
-
-
-/* Calculate all six rotations of the specified piece at the specified index.
- * We calculate only half of piece 3's rotations.  This is because any solution
- * found has an identical solution rotated 180 degrees.  Thus we can reduce the
- * number of attempted pieces in the solve algorithm by not including the 180-
- * degree-rotated pieces of ONE of the pieces.  I chose piece 3 because it gave
- * me the best time ;)
- */
- void calc_six_rotations(char piece, char index) {
-   char rotation, cell[5];
-   char minimum, first_empty;
-   unsigned long long piece_mask;
-
-   for(rotation = 0; rotation < 6; rotation++) {
-      if(piece != 3 || rotation < 3) {
-         calc_cell_indices(cell, piece, index);
-         if(cells_fit_on_board(cell, piece) && !has_island(cell, piece)) {
-            minimum = minimum_of_cells(cell);
-            first_empty = first_empty_cell(cell, minimum);
-            piece_mask = bitmask_from_cells(cell);
-            record_piece(piece, minimum, first_empty, piece_mask);
-         }
-      }
-      rotate_piece(piece);
-   }
-}
-
-/* Calculate every legal rotation for each piece at each board location. */
-void calc_pieces(void) {
-   char piece, index;
-
-   for(piece = 0; piece < 10; piece++) {
-      for(index = 0; index < 50; index++) {
-         calc_six_rotations(piece, index);
-         flip_piece(piece);
-         calc_six_rotations(piece, index);
-      }
-   }
-}
-
-
-
-/* Calculate all 32 possible states for a 5-bit row and all rows that will
- * create islands that follow any of the 32 possible rows.  These pre-
- * calculated 5-bit rows will be used to find islands in a partially solved
- * board in the solve function.
- */
-#define ROW_MASK 0x1F
-#define TRIPLE_MASK 0x7FFF
-char all_rows[32] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
-      17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
-int bad_even_rows[32][32];
-int bad_odd_rows[32][32];
-int bad_even_triple[32768];
-int bad_odd_triple[32768];
-
-int rows_bad(char row1, char row2, int even) {
-   /* even is referring to row1 */
-   int i, in_zeroes, group_okay;
-   char block, row2_shift;
-   /* Test for blockages at same index and shifted index */
-   if(even)
-      row2_shift = ((row2 << 1) & ROW_MASK) | 0x01;
-   else
-      row2_shift = (row2 >> 1) | 0x10;
-   block = ((row1 ^ row2) & row2) & ((row1 ^ row2_shift) & row2_shift);
-   /* Test for groups of 0's */
-   in_zeroes = FALSE;
-   group_okay = FALSE;
-   for(i = 0; i < 5; i++) {
-      if(row1 & (1 << i)) {
-         if(in_zeroes) {
-            if(!group_okay)
-               return TRUE;
-            in_zeroes = FALSE;
-            group_okay = FALSE;
-         }
-      } else {
-         if(!in_zeroes)
-            in_zeroes = TRUE;
-         if(!(block & (1 << i)))
-            group_okay = TRUE;
-      }
-   }
-   if(in_zeroes)
-      return !group_okay;
-   else
-      return FALSE;
-}
-
-/* Check for cases where three rows checked sequentially cause a false
- * positive.  One scenario is when 5 cells may be surrounded where piece 5
- * or 7 can fit.  The other scenario is when piece 2 creates a hook shape.
- */
-int triple_is_okay(char row1, char row2, char row3, int even) {
-   if(even) {
-      /* There are four cases:
-       * row1: 00011  00001  11001  10101
-       * row2: 01011  00101  10001  10001
-       * row3: 011??  00110  ?????  ?????
-       */
-      return ((row1 == 0x03) && (row2 == 0x0B) && ((row3 & 0x1C) == 0x0C)) ||
-            ((row1 == 0x01) && (row2 == 0x05) && (row3 == 0x06)) ||
-            ((row1 == 0x19) && (row2 == 0x11)) ||
-            ((row1 == 0x15) && (row2 == 0x11));
-   } else {
-      /* There are two cases:
-       * row1: 10011  10101
-       * row2: 10001  10001
-       * row3: ?????  ?????
-       */
-      return ((row1 == 0x13) && (row2 == 0x11)) ||
-            ((row1 == 0x15) && (row2 == 0x11));
-   }
-}
-
-
-void calc_rows(void) {
-   int row1, row2, row3;
-   int result1, result2;
-   for(row1 = 0; row1 < 32; row1++) {
-      for(row2 = 0; row2 < 32; row2++) {
-         bad_even_rows[row1][row2] = rows_bad(row1, row2, TRUE);
-         bad_odd_rows[row1][row2] = rows_bad(row1, row2, FALSE);
-      }
-   }
-   for(row1 = 0; row1 < 32; row1++) {
-      for(row2 = 0; row2 < 32; row2++) {
-         for(row3 = 0; row3 < 32; row3++) {
-            result1 = bad_even_rows[row1][row2];
-            result2 = bad_odd_rows[row2][row3];
-            if(result1 == FALSE && result2 == TRUE
-                  && triple_is_okay(row1, row2, row3, TRUE))
-               bad_even_triple[row1+(row2*32)+(row3*1024)] = FALSE;
-            else
-               bad_even_triple[row1+(row2*32)+(row3*1024)] = result1 || result2;
-
-            result1 = bad_odd_rows[row1][row2];
-            result2 = bad_even_rows[row2][row3];
-            if(result1 == FALSE && result2 == TRUE
-                  && triple_is_okay(row1, row2, row3, FALSE))
-               bad_odd_triple[row1+(row2*32)+(row3*1024)] = FALSE;
-            else
-               bad_odd_triple[row1+(row2*32)+(row3*1024)] = result1 || result2;
-         }
-      }
-   }
-}
-
-
-
-/* Calculate islands while solving the board.
- */
-int boardHasIslands(char cell) {
-   /* Too low on board, don't bother checking */
-   if(cell >= 40)
-      return FALSE;
-   int current_triple = (board >> ((cell / 5) * 5)) & TRIPLE_MASK;
-   if((cell / 5) % 2)
-      return bad_odd_triple[current_triple];
-   else
-      return bad_even_triple[current_triple];
-}
-
-
-/* The recursive solve algorithm.  Try to place each permutation in the upper-
- * leftmost empty cell.  Mark off available pieces as it goes along.
- * Because the board is a bit mask, the piece number and bit mask must be saved
- * at each successful piece placement.  This data is used to create a 50 char
- * array if a solution is found.
- */
-short avail = 0x03FF;
-char sol_nums[10];
-unsigned long long sol_masks[10];
-signed char solutions[2100][50];
-int solution_count = 0;
-int max_solutions = 2100;
-
-void record_solution(void) {
-   int sol_no, index;
-   unsigned long long sol_mask;
-   for(sol_no = 0; sol_no < 10; sol_no++) {
-      sol_mask = sol_masks[sol_no];
-      for(index = 0; index < 50; index++) {
-         if(sol_mask & 1ULL) {
-            solutions[solution_count][index] = sol_nums[sol_no];
-            /* Board rotated 180 degrees is a solution too! */
-            solutions[solution_count+1][49-index] = sol_nums[sol_no];
-         }
-         sol_mask = sol_mask >> 1;
-      }
-   }
-   solution_count += 2;
-}
-
-void solve(int depth, int cell) {
-   int piece, rotation, max_rots;
-   unsigned long long *piece_mask;
-   short piece_no_mask;
-
-   if(solution_count >= max_solutions)
-      return;
-
-   while(board & (1ULL << cell))
-      cell++;
-
-   for(piece = 0; piece < 10; piece++) {
-      piece_no_mask = 1 << piece;
-      if(!(avail & piece_no_mask))
-         continue;
-      avail ^= piece_no_mask;
-      max_rots = piece_counts[piece][cell];
-      piece_mask = pieces[piece][cell];
-      for(rotation = 0; rotation < max_rots; rotation++) {
-         if(!(board & *(piece_mask + rotation))) {
-            sol_nums[depth] = piece;
-            sol_masks[depth] = *(piece_mask + rotation);
-            if(depth == 9) {
-               /* Solution found!!!!!11!!ONE! */
-               record_solution();
-               avail ^= piece_no_mask;
-               return;
-            }
-            board |= *(piece_mask + rotation);
-            if(!boardHasIslands(next_cell[piece][cell][rotation]))
-               solve(depth + 1, next_cell[piece][cell][rotation]);
-            board ^= *(piece_mask + rotation);
-         }
-      }
-      avail ^= piece_no_mask;
-   }
-}
-
-
-/* qsort comparator - used to find first and last solutions */
-int solution_sort(const void *elem1, const void *elem2) {
-   signed char *char1 = (signed char *) elem1;
-   signed char *char2 = (signed char *) elem2;
-   int i = 0;
-   while(i < 50 && char1[i] == char2[i])
-      i++;
-   return char1[i] - char2[i];
-}
-
-
-/* pretty print a board in the specified hexagonal format */
-void pretty(signed char *b) {
-   int i;
-   for(i = 0; i < 50; i += 10) {
-      printf("%c %c %c %c %c \n %c %c %c %c %c \n", b[i]+'0', b[i+1]+'0',
-            b[i+2]+'0', b[i+3]+'0', b[i+4]+'0', b[i+5]+'0', b[i+6]+'0',
-            b[i+7]+'0', b[i+8]+'0', b[i+9]+'0');
-   }
-   printf("\n");
-}
-
-int main(int argc, char **argv) {
-   if(argc > 1)
-      max_solutions = atoi(argv[1]);
-   calc_pieces();
-   calc_rows();
-   solve(0, 0);
-   printf("%d solutions found\n\n", solution_count);
-   qsort(solutions, solution_count, 50 * sizeof(signed char), solution_sort);
-   pretty(solutions[0]);
-   pretty(solutions[solution_count-1]);
-   return 0;
-}
diff --git a/test/bench/shootout/meteor-contest.go b/test/bench/shootout/meteor-contest.go
deleted file mode 100644
index 34a4e23..0000000
--- a/test/bench/shootout/meteor-contest.go
+++ /dev/null
@@ -1,656 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * based on meteor-contest.c by Christian Vosteen
- */
-
-package main
-
-import (
-	"flag"
-	"fmt"
-)
-
-var max_solutions = flag.Int("n", 2100, "maximum number of solutions")
-
-func boolInt(b bool) int8 {
-	if b {
-		return 1
-	}
-	return 0
-}
-
-/* The board is a 50 cell hexagonal pattern.  For    . . . . .
- * maximum speed the board will be implemented as     . . . . .
- * 50 bits, which will fit into a 64 bit long long   . . . . .
- * int.                                               . . . . .
- *                                                   . . . . .
- * I will represent 0's as empty cells and 1's        . . . . .
- * as full cells.                                    . . . . .
- *                                                    . . . . .
- *                                                   . . . . .
- *                                                    . . . . .
- */
-
-var board uint64 = 0xFFFC000000000000
-
-/* The puzzle pieces must be specified by the path followed
- * from one end to the other along 12 hexagonal directions.
- *
- *   Piece 0   Piece 1   Piece 2   Piece 3   Piece 4
- *
- *  O O O O    O   O O   O O O     O O O     O   O
- *         O    O O           O       O       O O
- *                           O         O         O
- *
- *   Piece 5   Piece 6   Piece 7   Piece 8   Piece 9
- *
- *    O O O     O O       O O     O O        O O O O
- *       O O       O O       O       O O O        O
- *                  O       O O
- *
- * I had to make it 12 directions because I wanted all of the
- * piece definitions to fit into the same size arrays.  It is
- * not possible to define piece 4 in terms of the 6 cardinal
- * directions in 4 moves.
- */
-
-const (
-	E = iota
-	ESE
-	SE
-	S
-	SW
-	WSW
-	W
-	WNW
-	NW
-	N
-	NE
-	ENE
-	PIVOT
-)
-
-var piece_def = [10][4]int8{
-	[4]int8{E, E, E, SE},
-	[4]int8{SE, E, NE, E},
-	[4]int8{E, E, SE, SW},
-	[4]int8{E, E, SW, SE},
-	[4]int8{SE, E, NE, S},
-	[4]int8{E, E, SW, E},
-	[4]int8{E, SE, SE, NE},
-	[4]int8{E, SE, SE, W},
-	[4]int8{E, SE, E, E},
-	[4]int8{E, E, E, SW},
-}
-
-/* To minimize the amount of work done in the recursive solve function below,
- * I'm going to allocate enough space for all legal rotations of each piece
- * at each position on the board. That's 10 pieces x 50 board positions x
- * 12 rotations.  However, not all 12 rotations will fit on every cell, so
- * I'll have to keep count of the actual number that do.
- * The pieces are going to be unsigned long long ints just like the board so
- * they can be bitwise-anded with the board to determine if they fit.
- * I'm also going to record the next possible open cell for each piece and
- * location to reduce the burden on the solve function.
- */
-var (
-	pieces       [10][50][12]uint64
-	piece_counts [10][50]int
-	next_cell    [10][50][12]int8
-)
-
-/* Returns the direction rotated 60 degrees clockwise */
-func rotate(dir int8) int8 { return (dir + 2) % PIVOT }
-
-/* Returns the direction flipped on the horizontal axis */
-func flip(dir int8) int8 { return (PIVOT - dir) % PIVOT }
-
-/* Returns the new cell index from the specified cell in the
- * specified direction.  The index is only valid if the
- * starting cell and direction have been checked by the
- * out_of_bounds function first.
- */
-func shift(cell, dir int8) int8 {
-	switch dir {
-	case E:
-		return cell + 1
-	case ESE:
-		if ((cell / 5) % 2) != 0 {
-			return cell + 7
-		} else {
-			return cell + 6
-		}
-	case SE:
-		if ((cell / 5) % 2) != 0 {
-			return cell + 6
-		} else {
-			return cell + 5
-		}
-	case S:
-		return cell + 10
-	case SW:
-		if ((cell / 5) % 2) != 0 {
-			return cell + 5
-		} else {
-			return cell + 4
-		}
-	case WSW:
-		if ((cell / 5) % 2) != 0 {
-			return cell + 4
-		} else {
-			return cell + 3
-		}
-	case W:
-		return cell - 1
-	case WNW:
-		if ((cell / 5) % 2) != 0 {
-			return cell - 6
-		} else {
-			return cell - 7
-		}
-	case NW:
-		if ((cell / 5) % 2) != 0 {
-			return cell - 5
-		} else {
-			return cell - 6
-		}
-	case N:
-		return cell - 10
-	case NE:
-		if ((cell / 5) % 2) != 0 {
-			return cell - 4
-		} else {
-			return cell - 5
-		}
-	case ENE:
-		if ((cell / 5) % 2) != 0 {
-			return cell - 3
-		} else {
-			return cell - 4
-		}
-	}
-	return cell
-}
-
-/* Returns wether the specified cell and direction will land outside
- * of the board.  Used to determine if a piece is at a legal board
- * location or not.
- */
-func out_of_bounds(cell, dir int8) bool {
-	switch dir {
-	case E:
-		return cell%5 == 4
-	case ESE:
-		i := cell % 10
-		return i == 4 || i == 8 || i == 9 || cell >= 45
-	case SE:
-		return cell%10 == 9 || cell >= 45
-	case S:
-		return cell >= 40
-	case SW:
-		return cell%10 == 0 || cell >= 45
-	case WSW:
-		i := cell % 10
-		return i == 0 || i == 1 || i == 5 || cell >= 45
-	case W:
-		return cell%5 == 0
-	case WNW:
-		i := cell % 10
-		return i == 0 || i == 1 || i == 5 || cell < 5
-	case NW:
-		return cell%10 == 0 || cell < 5
-	case N:
-		return cell < 10
-	case NE:
-		return cell%10 == 9 || cell < 5
-	case ENE:
-		i := cell % 10
-		return i == 4 || i == 8 || i == 9 || cell < 5
-	}
-	return false
-}
-
-/* Rotate a piece 60 degrees clockwise */
-func rotate_piece(piece int) {
-	for i := 0; i < 4; i++ {
-		piece_def[piece][i] = rotate(piece_def[piece][i])
-	}
-}
-
-/* Flip a piece along the horizontal axis */
-func flip_piece(piece int) {
-	for i := 0; i < 4; i++ {
-		piece_def[piece][i] = flip(piece_def[piece][i])
-	}
-}
-
-/* Convenience function to quickly calculate all of the indices for a piece */
-func calc_cell_indices(cell []int8, piece int, index int8) {
-	cell[0] = index
-	for i := 1; i < 5; i++ {
-		cell[i] = shift(cell[i-1], piece_def[piece][i-1])
-	}
-}
-
-/* Convenience function to quickly calculate if a piece fits on the board */
-func cells_fit_on_board(cell []int8, piece int) bool {
-	return !out_of_bounds(cell[0], piece_def[piece][0]) &&
-		!out_of_bounds(cell[1], piece_def[piece][1]) &&
-		!out_of_bounds(cell[2], piece_def[piece][2]) &&
-		!out_of_bounds(cell[3], piece_def[piece][3])
-}
-
-/* Returns the lowest index of the cells of a piece.
- * I use the lowest index that a piece occupies as the index for looking up
- * the piece in the solve function.
- */
-func minimum_of_cells(cell []int8) int8 {
-	minimum := cell[0]
-	for i := 1; i < 5; i++ {
-		if cell[i] < minimum {
-			minimum = cell[i]
-		}
-	}
-	return minimum
-}
-
-/* Calculate the lowest possible open cell if the piece is placed on the board.
- * Used to later reduce the amount of time searching for open cells in the
- * solve function.
- */
-func first_empty_cell(cell []int8, minimum int8) int8 {
-	first_empty := minimum
-	for first_empty == cell[0] || first_empty == cell[1] ||
-		first_empty == cell[2] || first_empty == cell[3] ||
-		first_empty == cell[4] {
-		first_empty++
-	}
-	return first_empty
-}
-
-/* Generate the unsigned long long int that will later be anded with the
- * board to determine if it fits.
- */
-func bitmask_from_cells(cell []int8) uint64 {
-	var piece_mask uint64
-	for i := 0; i < 5; i++ {
-		piece_mask |= 1 << uint(cell[i])
-	}
-	return piece_mask
-}
-
-/* Record the piece and other important information in arrays that will
- * later be used by the solve function.
- */
-func record_piece(piece int, minimum int8, first_empty int8, piece_mask uint64) {
-	pieces[piece][minimum][piece_counts[piece][minimum]] = piece_mask
-	next_cell[piece][minimum][piece_counts[piece][minimum]] = first_empty
-	piece_counts[piece][minimum]++
-}
-
-/* Fill the entire board going cell by cell.  If any cells are "trapped"
- * they will be left alone.
- */
-func fill_contiguous_space(board []int8, index int8) {
-	if board[index] == 1 {
-		return
-	}
-	board[index] = 1
-	if !out_of_bounds(index, E) {
-		fill_contiguous_space(board, shift(index, E))
-	}
-	if !out_of_bounds(index, SE) {
-		fill_contiguous_space(board, shift(index, SE))
-	}
-	if !out_of_bounds(index, SW) {
-		fill_contiguous_space(board, shift(index, SW))
-	}
-	if !out_of_bounds(index, W) {
-		fill_contiguous_space(board, shift(index, W))
-	}
-	if !out_of_bounds(index, NW) {
-		fill_contiguous_space(board, shift(index, NW))
-	}
-	if !out_of_bounds(index, NE) {
-		fill_contiguous_space(board, shift(index, NE))
-	}
-}
-
-/* To thin the number of pieces, I calculate if any of them trap any empty
- * cells at the edges.  There are only a handful of exceptions where the
- * the board can be solved with the trapped cells.  For example:  piece 8 can
- * trap 5 cells in the corner, but piece 3 can fit in those cells, or piece 0
- * can split the board in half where both halves are viable.
- */
-func has_island(cell []int8, piece int) bool {
-	temp_board := make([]int8, 50)
-	var i int
-	for i = 0; i < 5; i++ {
-		temp_board[cell[i]] = 1
-	}
-	i = 49
-	for temp_board[i] == 1 {
-		i--
-	}
-	fill_contiguous_space(temp_board, int8(i))
-	c := 0
-	for i = 0; i < 50; i++ {
-		if temp_board[i] == 0 {
-			c++
-		}
-	}
-	if c == 0 || (c == 5 && piece == 8) || (c == 40 && piece == 8) ||
-		(c%5 == 0 && piece == 0) {
-		return false
-	}
-	return true
-}
-
-/* Calculate all six rotations of the specified piece at the specified index.
- * We calculate only half of piece 3's rotations.  This is because any solution
- * found has an identical solution rotated 180 degrees.  Thus we can reduce the
- * number of attempted pieces in the solve algorithm by not including the 180-
- * degree-rotated pieces of ONE of the pieces.  I chose piece 3 because it gave
- * me the best time ;)
- */
-func calc_six_rotations(piece, index int) {
-	cell := make([]int8, 5)
-	for rotation := 0; rotation < 6; rotation++ {
-		if piece != 3 || rotation < 3 {
-			calc_cell_indices(cell, piece, int8(index))
-			if cells_fit_on_board(cell, piece) && !has_island(cell, piece) {
-				minimum := minimum_of_cells(cell)
-				first_empty := first_empty_cell(cell, minimum)
-				piece_mask := bitmask_from_cells(cell)
-				record_piece(piece, minimum, first_empty, piece_mask)
-			}
-		}
-		rotate_piece(piece)
-	}
-}
-
-/* Calculate every legal rotation for each piece at each board location. */
-func calc_pieces() {
-	for piece := 0; piece < 10; piece++ {
-		for index := 0; index < 50; index++ {
-			calc_six_rotations(piece, index)
-			flip_piece(piece)
-			calc_six_rotations(piece, index)
-		}
-	}
-}
-
-/* Calculate all 32 possible states for a 5-bit row and all rows that will
- * create islands that follow any of the 32 possible rows.  These pre-
- * calculated 5-bit rows will be used to find islands in a partially solved
- * board in the solve function.
- */
-const (
-	ROW_MASK    = 0x1F
-	TRIPLE_MASK = 0x7FFF
-)
-
-var (
-	all_rows = [32]int8{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
-		17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
-	}
-	bad_even_rows   [32][32]int8
-	bad_odd_rows    [32][32]int8
-	bad_even_triple [32768]int8
-	bad_odd_triple  [32768]int8
-)
-
-func rows_bad(row1, row2 int8, even bool) int8 {
-	/* even is referring to row1 */
-	var row2_shift int8
-	/* Test for blockages at same index and shifted index */
-	if even {
-		row2_shift = ((row2 << 1) & ROW_MASK) | 0x01
-	} else {
-		row2_shift = (row2 >> 1) | 0x10
-	}
-	block := ((row1 ^ row2) & row2) & ((row1 ^ row2_shift) & row2_shift)
-	/* Test for groups of 0's */
-	in_zeroes := false
-	group_okay := false
-	for i := uint8(0); i < 5; i++ {
-		if row1&(1<<i) != 0 {
-			if in_zeroes {
-				if !group_okay {
-					return 1
-				}
-				in_zeroes = false
-				group_okay = false
-			}
-		} else {
-			if !in_zeroes {
-				in_zeroes = true
-			}
-			if (block & (1 << i)) == 0 {
-				group_okay = true
-			}
-		}
-	}
-	if in_zeroes {
-		return boolInt(!group_okay)
-	}
-	return 0
-}
-
-/* Check for cases where three rows checked sequentially cause a false
- * positive.  One scenario is when 5 cells may be surrounded where piece 5
- * or 7 can fit.  The other scenario is when piece 2 creates a hook shape.
- */
-func triple_is_okay(row1, row2, row3 int, even bool) bool {
-	if even {
-		/* There are four cases:
-		 * row1: 00011  00001  11001  10101
-		 * row2: 01011  00101  10001  10001
-		 * row3: 011??  00110  ?????  ?????
-		 */
-		return ((row1 == 0x03) && (row2 == 0x0B) && ((row3 & 0x1C) == 0x0C)) ||
-			((row1 == 0x01) && (row2 == 0x05) && (row3 == 0x06)) ||
-			((row1 == 0x19) && (row2 == 0x11)) ||
-			((row1 == 0x15) && (row2 == 0x11))
-	}
-	/* There are two cases:
-	 * row1: 10011  10101
-	 * row2: 10001  10001
-	 * row3: ?????  ?????
-	 */
-	return ((row1 == 0x13) && (row2 == 0x11)) ||
-		((row1 == 0x15) && (row2 == 0x11))
-}
-
-func calc_rows() {
-	for row1 := int8(0); row1 < 32; row1++ {
-		for row2 := int8(0); row2 < 32; row2++ {
-			bad_even_rows[row1][row2] = rows_bad(row1, row2, true)
-			bad_odd_rows[row1][row2] = rows_bad(row1, row2, false)
-		}
-	}
-	for row1 := 0; row1 < 32; row1++ {
-		for row2 := 0; row2 < 32; row2++ {
-			for row3 := 0; row3 < 32; row3++ {
-				result1 := bad_even_rows[row1][row2]
-				result2 := bad_odd_rows[row2][row3]
-				if result1 == 0 && result2 != 0 && triple_is_okay(row1, row2, row3, true) {
-					bad_even_triple[row1+(row2*32)+(row3*1024)] = 0
-				} else {
-					bad_even_triple[row1+(row2*32)+(row3*1024)] = boolInt(result1 != 0 || result2 != 0)
-				}
-
-				result1 = bad_odd_rows[row1][row2]
-				result2 = bad_even_rows[row2][row3]
-				if result1 == 0 && result2 != 0 && triple_is_okay(row1, row2, row3, false) {
-					bad_odd_triple[row1+(row2*32)+(row3*1024)] = 0
-				} else {
-					bad_odd_triple[row1+(row2*32)+(row3*1024)] = boolInt(result1 != 0 || result2 != 0)
-				}
-			}
-		}
-	}
-}
-
-/* Calculate islands while solving the board.
- */
-func boardHasIslands(cell int8) int8 {
-	/* Too low on board, don't bother checking */
-	if cell >= 40 {
-		return 0
-	}
-	current_triple := (board >> uint((cell/5)*5)) & TRIPLE_MASK
-	if (cell/5)%2 != 0 {
-		return bad_odd_triple[current_triple]
-	}
-	return bad_even_triple[current_triple]
-}
-
-/* The recursive solve algorithm.  Try to place each permutation in the upper-
- * leftmost empty cell.  Mark off available pieces as it goes along.
- * Because the board is a bit mask, the piece number and bit mask must be saved
- * at each successful piece placement.  This data is used to create a 50 char
- * array if a solution is found.
- */
-var (
-	avail          uint16 = 0x03FF
-	sol_nums       [10]int8
-	sol_masks      [10]uint64
-	solutions      [2100][50]int8
-	solution_count = 0
-)
-
-func record_solution() {
-	for sol_no := 0; sol_no < 10; sol_no++ {
-		sol_mask := sol_masks[sol_no]
-		for index := 0; index < 50; index++ {
-			if sol_mask&1 == 1 {
-				solutions[solution_count][index] = sol_nums[sol_no]
-				/* Board rotated 180 degrees is a solution too! */
-				solutions[solution_count+1][49-index] = sol_nums[sol_no]
-			}
-			sol_mask = sol_mask >> 1
-		}
-	}
-	solution_count += 2
-}
-
-func solve(depth, cell int8) {
-	if solution_count >= *max_solutions {
-		return
-	}
-
-	for board&(1<<uint(cell)) != 0 {
-		cell++
-	}
-
-	for piece := int8(0); piece < 10; piece++ {
-		var piece_no_mask uint16 = 1 << uint(piece)
-		if avail&piece_no_mask == 0 {
-			continue
-		}
-		avail ^= piece_no_mask
-		max_rots := piece_counts[piece][cell]
-		piece_mask := pieces[piece][cell]
-		for rotation := 0; rotation < max_rots; rotation++ {
-			if board&piece_mask[rotation] == 0 {
-				sol_nums[depth] = piece
-				sol_masks[depth] = piece_mask[rotation]
-				if depth == 9 {
-					/* Solution found!!!!!11!!ONE! */
-					record_solution()
-					avail ^= piece_no_mask
-					return
-				}
-				board |= piece_mask[rotation]
-				if boardHasIslands(next_cell[piece][cell][rotation]) == 0 {
-					solve(depth+1, next_cell[piece][cell][rotation])
-				}
-				board ^= piece_mask[rotation]
-			}
-		}
-		avail ^= piece_no_mask
-	}
-}
-
-/* pretty print a board in the specified hexagonal format */
-func pretty(b *[50]int8) {
-	for i := 0; i < 50; i += 10 {
-		fmt.Printf("%c %c %c %c %c \n %c %c %c %c %c \n", b[i]+'0', b[i+1]+'0',
-			b[i+2]+'0', b[i+3]+'0', b[i+4]+'0', b[i+5]+'0', b[i+6]+'0',
-			b[i+7]+'0', b[i+8]+'0', b[i+9]+'0')
-	}
-	fmt.Printf("\n")
-}
-
-/* Find smallest and largest solutions */
-func smallest_largest() (smallest, largest *[50]int8) {
-	smallest = &solutions[0]
-	largest = &solutions[0]
-	for i := 1; i < solution_count; i++ {
-		candidate := &solutions[i]
-		for j, s := range *smallest {
-			c := candidate[j]
-			if c == s {
-				continue
-			}
-			if c < s {
-				smallest = candidate
-			}
-			break
-		}
-		for j, s := range *largest {
-			c := candidate[j]
-			if c == s {
-				continue
-			}
-			if c > s {
-				largest = candidate
-			}
-			break
-		}
-	}
-	return
-}
-
-func main() {
-	flag.Parse()
-	calc_pieces()
-	calc_rows()
-	solve(0, 0)
-	fmt.Printf("%d solutions found\n\n", solution_count)
-	smallest, largest := smallest_largest()
-	pretty(smallest)
-	pretty(largest)
-}
diff --git a/test/bench/shootout/meteor-contest.txt b/test/bench/shootout/meteor-contest.txt
deleted file mode 100644
index 38d9783..0000000
--- a/test/bench/shootout/meteor-contest.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-2098 solutions found
-
-0 0 0 0 1 
- 2 2 2 0 1 
-2 6 6 1 1 
- 2 6 1 5 5 
-8 6 5 5 5 
- 8 6 3 3 3 
-4 8 8 9 3 
- 4 4 8 9 3 
-4 7 4 7 9 
- 7 7 7 9 9 
-
-9 9 9 9 8 
- 9 6 6 8 5 
-6 6 8 8 5 
- 6 8 2 5 5 
-7 7 7 2 5 
- 7 4 7 2 0 
-1 4 2 2 0 
- 1 4 4 0 3 
-1 4 0 0 3 
- 1 1 3 3 3 
-
diff --git a/test/bench/shootout/nbody.c b/test/bench/shootout/nbody.c
deleted file mode 100644
index 3b95b05..0000000
--- a/test/bench/shootout/nbody.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*
- * The Great Computer Language Shootout
- * http://shootout.alioth.debian.org/
- *
- * contributed by Christoph Bauer
- *
- */
-
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#define pi 3.141592653589793
-#define solar_mass (4 * pi * pi)
-#define days_per_year 365.24
-
-struct planet {
-  double x, y, z;
-  double vx, vy, vz;
-  double mass;
-};
-
-void advance(int nbodies, struct planet * bodies, double dt)
-{
-  int i, j;
-
-  for (i = 0; i < nbodies; i++) {
-    struct planet * b = &(bodies[i]);
-    for (j = i + 1; j < nbodies; j++) {
-      struct planet * b2 = &(bodies[j]);
-      double dx = b->x - b2->x;
-      double dy = b->y - b2->y;
-      double dz = b->z - b2->z;
-      double distance = sqrt(dx * dx + dy * dy + dz * dz);
-      double mag = dt / (distance * distance * distance);
-      b->vx -= dx * b2->mass * mag;
-      b->vy -= dy * b2->mass * mag;
-      b->vz -= dz * b2->mass * mag;
-      b2->vx += dx * b->mass * mag;
-      b2->vy += dy * b->mass * mag;
-      b2->vz += dz * b->mass * mag;
-    }
-  }
-  for (i = 0; i < nbodies; i++) {
-    struct planet * b = &(bodies[i]);
-    b->x += dt * b->vx;
-    b->y += dt * b->vy;
-    b->z += dt * b->vz;
-  }
-}
-
-double energy(int nbodies, struct planet * bodies)
-{
-  double e;
-  int i, j;
-
-  e = 0.0;
-  for (i = 0; i < nbodies; i++) {
-    struct planet * b = &(bodies[i]);
-    e += 0.5 * b->mass * (b->vx * b->vx + b->vy * b->vy + b->vz * b->vz);
-    for (j = i + 1; j < nbodies; j++) {
-      struct planet * b2 = &(bodies[j]);
-      double dx = b->x - b2->x;
-      double dy = b->y - b2->y;
-      double dz = b->z - b2->z;
-      double distance = sqrt(dx * dx + dy * dy + dz * dz);
-      e -= (b->mass * b2->mass) / distance;
-    }
-  }
-  return e;
-}
-
-void offset_momentum(int nbodies, struct planet * bodies)
-{
-  double px = 0.0, py = 0.0, pz = 0.0;
-  int i;
-  for (i = 0; i < nbodies; i++) {
-    px += bodies[i].vx * bodies[i].mass;
-    py += bodies[i].vy * bodies[i].mass;
-    pz += bodies[i].vz * bodies[i].mass;
-  }
-  bodies[0].vx = - px / solar_mass;
-  bodies[0].vy = - py / solar_mass;
-  bodies[0].vz = - pz / solar_mass;
-}
-
-#define NBODIES 5
-struct planet bodies[NBODIES] = {
-  {                               /* sun */
-    0, 0, 0, 0, 0, 0, solar_mass
-  },
-  {                               /* jupiter */
-    4.84143144246472090e+00,
-    -1.16032004402742839e+00,
-    -1.03622044471123109e-01,
-    1.66007664274403694e-03 * days_per_year,
-    7.69901118419740425e-03 * days_per_year,
-    -6.90460016972063023e-05 * days_per_year,
-    9.54791938424326609e-04 * solar_mass
-  },
-  {                               /* saturn */
-    8.34336671824457987e+00,
-    4.12479856412430479e+00,
-    -4.03523417114321381e-01,
-    -2.76742510726862411e-03 * days_per_year,
-    4.99852801234917238e-03 * days_per_year,
-    2.30417297573763929e-05 * days_per_year,
-    2.85885980666130812e-04 * solar_mass
-  },
-  {                               /* uranus */
-    1.28943695621391310e+01,
-    -1.51111514016986312e+01,
-    -2.23307578892655734e-01,
-    2.96460137564761618e-03 * days_per_year,
-    2.37847173959480950e-03 * days_per_year,
-    -2.96589568540237556e-05 * days_per_year,
-    4.36624404335156298e-05 * solar_mass
-  },
-  {                               /* neptune */
-    1.53796971148509165e+01,
-    -2.59193146099879641e+01,
-    1.79258772950371181e-01,
-    2.68067772490389322e-03 * days_per_year,
-    1.62824170038242295e-03 * days_per_year,
-    -9.51592254519715870e-05 * days_per_year,
-    5.15138902046611451e-05 * solar_mass
-  }
-};
-
-int main(int argc, char ** argv)
-{
-  int n = atoi(argv[1]);
-  int i;
-
-  offset_momentum(NBODIES, bodies);
-  printf ("%.9f\n", energy(NBODIES, bodies));
-  for (i = 1; i <= n; i++)
-    advance(NBODIES, bodies, 0.01);
-  printf ("%.9f\n", energy(NBODIES, bodies));
-  return 0;
-}
diff --git a/test/bench/shootout/nbody.go b/test/bench/shootout/nbody.go
deleted file mode 100644
index 988f3ba..0000000
--- a/test/bench/shootout/nbody.go
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * based on C program by Christoph Bauer
- */
-
-package main
-
-import (
-	"flag"
-	"fmt"
-	"math"
-)
-
-var n = flag.Int("n", 1000, "number of iterations")
-
-type Body struct {
-	x, y, z, vx, vy, vz, mass float64
-}
-
-const (
-	solarMass   = 4 * math.Pi * math.Pi
-	daysPerYear = 365.24
-)
-
-func (b *Body) offsetMomentum(px, py, pz float64) {
-	b.vx = -px / solarMass
-	b.vy = -py / solarMass
-	b.vz = -pz / solarMass
-}
-
-type System []*Body
-
-func NewSystem(body []Body) System {
-	n := make(System, len(body))
-	for i := 0; i < len(body); i++ {
-		n[i] = new(Body) // copy to avoid overwriting the inputs
-		*n[i] = body[i]
-	}
-	var px, py, pz float64
-	for _, body := range n {
-		px += body.vx * body.mass
-		py += body.vy * body.mass
-		pz += body.vz * body.mass
-	}
-	n[0].offsetMomentum(px, py, pz)
-	return n
-}
-
-func (sys System) energy() float64 {
-	var e float64
-	for i, body := range sys {
-		e += 0.5 * body.mass *
-			(body.vx*body.vx + body.vy*body.vy + body.vz*body.vz)
-		for j := i + 1; j < len(sys); j++ {
-			body2 := sys[j]
-			dx := body.x - body2.x
-			dy := body.y - body2.y
-			dz := body.z - body2.z
-			distance := math.Sqrt(dx*dx + dy*dy + dz*dz)
-			e -= (body.mass * body2.mass) / distance
-		}
-	}
-	return e
-}
-
-func (sys System) advance(dt float64) {
-	for i, body := range sys {
-		for j := i + 1; j < len(sys); j++ {
-			body2 := sys[j]
-			dx := body.x - body2.x
-			dy := body.y - body2.y
-			dz := body.z - body2.z
-
-			dSquared := dx*dx + dy*dy + dz*dz
-			distance := math.Sqrt(dSquared)
-			mag := dt / (dSquared * distance)
-
-			body.vx -= dx * body2.mass * mag
-			body.vy -= dy * body2.mass * mag
-			body.vz -= dz * body2.mass * mag
-
-			body2.vx += dx * body.mass * mag
-			body2.vy += dy * body.mass * mag
-			body2.vz += dz * body.mass * mag
-		}
-	}
-
-	for _, body := range sys {
-		body.x += dt * body.vx
-		body.y += dt * body.vy
-		body.z += dt * body.vz
-	}
-}
-
-var (
-	jupiter = Body{
-		x:    4.84143144246472090e+00,
-		y:    -1.16032004402742839e+00,
-		z:    -1.03622044471123109e-01,
-		vx:   1.66007664274403694e-03 * daysPerYear,
-		vy:   7.69901118419740425e-03 * daysPerYear,
-		vz:   -6.90460016972063023e-05 * daysPerYear,
-		mass: 9.54791938424326609e-04 * solarMass,
-	}
-	saturn = Body{
-		x:    8.34336671824457987e+00,
-		y:    4.12479856412430479e+00,
-		z:    -4.03523417114321381e-01,
-		vx:   -2.76742510726862411e-03 * daysPerYear,
-		vy:   4.99852801234917238e-03 * daysPerYear,
-		vz:   2.30417297573763929e-05 * daysPerYear,
-		mass: 2.85885980666130812e-04 * solarMass,
-	}
-	uranus = Body{
-		x:    1.28943695621391310e+01,
-		y:    -1.51111514016986312e+01,
-		z:    -2.23307578892655734e-01,
-		vx:   2.96460137564761618e-03 * daysPerYear,
-		vy:   2.37847173959480950e-03 * daysPerYear,
-		vz:   -2.96589568540237556e-05 * daysPerYear,
-		mass: 4.36624404335156298e-05 * solarMass,
-	}
-	neptune = Body{
-		x:    1.53796971148509165e+01,
-		y:    -2.59193146099879641e+01,
-		z:    1.79258772950371181e-01,
-		vx:   2.68067772490389322e-03 * daysPerYear,
-		vy:   1.62824170038242295e-03 * daysPerYear,
-		vz:   -9.51592254519715870e-05 * daysPerYear,
-		mass: 5.15138902046611451e-05 * solarMass,
-	}
-	sun = Body{
-		mass: solarMass,
-	}
-)
-
-func main() {
-	flag.Parse()
-
-	system := NewSystem([]Body{sun, jupiter, saturn, uranus, neptune})
-	fmt.Printf("%.9f\n", system.energy())
-	for i := 0; i < *n; i++ {
-		system.advance(0.01)
-	}
-	fmt.Printf("%.9f\n", system.energy())
-}
diff --git a/test/bench/shootout/nbody.txt b/test/bench/shootout/nbody.txt
deleted file mode 100644
index 1731557..0000000
--- a/test/bench/shootout/nbody.txt
+++ /dev/null
@@ -1,2 +0,0 @@
--0.169075164
--0.169087605
diff --git a/test/bench/shootout/pidigits.c b/test/bench/shootout/pidigits.c
deleted file mode 100644
index c064da0..0000000
--- a/test/bench/shootout/pidigits.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
-  http://shootout.alioth.debian.org/
-
-  contributed by Paolo Bonzini & Sean Bartlett
-  modified by Michael Mellor
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <gmp.h>
-
-static mpz_t numer, accum, denom, tmp1, tmp2;
-
-static int extract_digit()
-{
-  if (mpz_cmp(numer, accum) > 0)
-    return -1;
-
-  /* Compute (numer * 3 + accum) / denom */
-  mpz_mul_2exp(tmp1, numer, 1);
-  mpz_add(tmp1, tmp1, numer);
-  mpz_add(tmp1, tmp1, accum);
-  mpz_fdiv_qr(tmp1, tmp2, tmp1, denom);
-
-  /* Now, if (numer * 4 + accum) % denom... */
-  mpz_add(tmp2, tmp2, numer);
-
-  /* ... is normalized, then the two divisions have the same result.  */
-  if (mpz_cmp(tmp2, denom) >= 0)
-    return -1;
-
-  return mpz_get_ui(tmp1);
-}
-
-static void next_term(unsigned int k)
-{
-  unsigned int y2 = k*2 + 1;
-
-  mpz_mul_2exp(tmp1, numer, 1);
-  mpz_add(accum, accum, tmp1);
-  mpz_mul_ui(accum, accum, y2);
-  mpz_mul_ui(numer, numer, k);
-  mpz_mul_ui(denom, denom, y2);
-}
-
-static void eliminate_digit(unsigned int d)
-{
-  mpz_submul_ui(accum, denom, d);
-  mpz_mul_ui(accum, accum, 10);
-  mpz_mul_ui(numer, numer, 10);
-}
-
-static void pidigits(unsigned int n)
-{
-  int d;
-  unsigned int i = 0, k = 0, m;
-  mpz_init(tmp1);
-  mpz_init(tmp2);
-  mpz_init_set_ui(numer, 1);
-  mpz_init_set_ui(accum, 0);
-  mpz_init_set_ui(denom, 1);
-
-  for(;;)
-  {
-    do {
-      k++;
-      next_term(k);
-      d = extract_digit();
-    } while(d == -1);
-
-    putchar(d + '0');
-
-    i++;
-    m = i%10;
-    if(m == 0)
-      printf("\t:%d\n", i);
-    if(i >= n)
-      break;
-    eliminate_digit(d);
-  }
-
-  if(m) {
-    m = 10 - m;
-    while(m--)
-      putchar(' ');
-    printf("\t:%d\n", n);
-  }
-}
-
-int main(int argc, char **argv)
-{
-  pidigits(argc > 1 ? atoi(argv[1]) : 27);
-  return 0;
-}
diff --git a/test/bench/shootout/pidigits.go b/test/bench/shootout/pidigits.go
deleted file mode 100644
index a0f21a9..0000000
--- a/test/bench/shootout/pidigits.go
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * based on pidigits.c (by Paolo Bonzini & Sean Bartlett,
- *                      modified by Michael Mellor)
- */
-
-package main
-
-import (
-	"flag"
-	"fmt"
-	"math/big"
-)
-
-var n = flag.Int("n", 27, "number of digits")
-var silent = flag.Bool("s", false, "don't print result")
-
-var (
-	tmp1  = big.NewInt(0)
-	tmp2  = big.NewInt(0)
-	tmp3  = big.NewInt(0)
-	y2    = big.NewInt(0)
-	bigk  = big.NewInt(0)
-	numer = big.NewInt(1)
-	accum = big.NewInt(0)
-	denom = big.NewInt(1)
-	ten   = big.NewInt(10)
-)
-
-func extract_digit() int64 {
-	if numer.Cmp(accum) > 0 {
-		return -1
-	}
-
-	// Compute (numer * 3 + accum) / denom
-	tmp1.Lsh(numer, 1)
-	tmp1.Add(tmp1, numer)
-	tmp1.Add(tmp1, accum)
-	tmp1.DivMod(tmp1, denom, tmp2)
-
-	// Now, if (numer * 4 + accum) % denom...
-	tmp2.Add(tmp2, numer)
-
-	// ... is normalized, then the two divisions have the same result.
-	if tmp2.Cmp(denom) >= 0 {
-		return -1
-	}
-
-	return tmp1.Int64()
-}
-
-func next_term(k int64) {
-	y2.SetInt64(k*2 + 1)
-	bigk.SetInt64(k)
-
-	tmp1.Lsh(numer, 1)
-	accum.Add(accum, tmp1)
-	accum.Mul(accum, y2)
-	numer.Mul(numer, bigk)
-	denom.Mul(denom, y2)
-}
-
-func eliminate_digit(d int64) {
-	tmp3.SetInt64(d)
-	accum.Sub(accum, tmp3.Mul(denom, tmp3))
-	accum.Mul(accum, ten)
-	numer.Mul(numer, ten)
-}
-
-func printf(s string, arg ...interface{}) {
-	if !*silent {
-		fmt.Printf(s, arg...)
-	}
-}
-
-func main() {
-	flag.Parse()
-
-	var m int // 0 <= m < 10
-	for i, k := 0, int64(0); ; {
-		d := int64(-1)
-		for d < 0 {
-			k++
-			next_term(k)
-			d = extract_digit()
-		}
-
-		printf("%c", d+'0')
-
-		i++
-		m = i % 10
-		if m == 0 {
-			printf("\t:%d\n", i)
-		}
-		if i >= *n {
-			break
-		}
-		eliminate_digit(d)
-	}
-
-	if m > 0 {
-		printf("%s\t:%d\n", "          "[m:10], *n)
-	}
-}
diff --git a/test/bench/shootout/pidigits.txt b/test/bench/shootout/pidigits.txt
deleted file mode 100644
index ad946a9..0000000
--- a/test/bench/shootout/pidigits.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-3141592653	:10
-5897932384	:20
-6264338   	:27
diff --git a/test/bench/shootout/regex-dna-parallel.go b/test/bench/shootout/regex-dna-parallel.go
deleted file mode 100644
index 9c6d421..0000000
--- a/test/bench/shootout/regex-dna-parallel.go
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- */
-
-package main
-
-import (
-	"fmt"
-	"io/ioutil"
-	"os"
-	"regexp"
-	"runtime"
-)
-
-var variants = []string{
-	"agggtaaa|tttaccct",
-	"[cgt]gggtaaa|tttaccc[acg]",
-	"a[act]ggtaaa|tttacc[agt]t",
-	"ag[act]gtaaa|tttac[agt]ct",
-	"agg[act]taaa|ttta[agt]cct",
-	"aggg[acg]aaa|ttt[cgt]ccct",
-	"agggt[cgt]aa|tt[acg]accct",
-	"agggta[cgt]a|t[acg]taccct",
-	"agggtaa[cgt]|[acg]ttaccct",
-}
-
-type Subst struct {
-	pat, repl string
-}
-
-var substs = []Subst{
-	Subst{"B", "(c|g|t)"},
-	Subst{"D", "(a|g|t)"},
-	Subst{"H", "(a|c|t)"},
-	Subst{"K", "(g|t)"},
-	Subst{"M", "(a|c)"},
-	Subst{"N", "(a|c|g|t)"},
-	Subst{"R", "(a|g)"},
-	Subst{"S", "(c|g)"},
-	Subst{"V", "(a|c|g)"},
-	Subst{"W", "(a|t)"},
-	Subst{"Y", "(c|t)"},
-}
-
-func countMatches(pat string, bytes []byte) int {
-	re := regexp.MustCompile(pat)
-	n := 0
-	for {
-		e := re.FindIndex(bytes)
-		if e == nil {
-			break
-		}
-		n++
-		bytes = bytes[e[1]:]
-	}
-	return n
-}
-
-func main() {
-	runtime.GOMAXPROCS(4)
-	bytes, err := ioutil.ReadAll(os.Stdin)
-	if err != nil {
-		fmt.Fprintf(os.Stderr, "can't read input: %s\n", err)
-		os.Exit(2)
-	}
-	ilen := len(bytes)
-	// Delete the comment lines and newlines
-	bytes = regexp.MustCompile("(>[^\n]+)?\n").ReplaceAll(bytes, []byte{})
-	clen := len(bytes)
-
-	mresults := make([]chan int, len(variants))
-	for i, s := range variants {
-		ch := make(chan int)
-		mresults[i] = ch
-		go func(ss string) {
-			ch <- countMatches(ss, bytes)
-		}(s)
-	}
-
-	lenresult := make(chan int)
-	bb := bytes
-	go func() {
-		for _, sub := range substs {
-			bb = regexp.MustCompile(sub.pat).ReplaceAll(bb, []byte(sub.repl))
-		}
-		lenresult <- len(bb)
-	}()
-
-	for i, s := range variants {
-		fmt.Printf("%s %d\n", s, <-mresults[i])
-	}
-	fmt.Printf("\n%d\n%d\n%d\n", ilen, clen, <-lenresult)
-}
diff --git a/test/bench/shootout/regex-dna-parallel.txt b/test/bench/shootout/regex-dna-parallel.txt
deleted file mode 100644
index e23e71f..0000000
--- a/test/bench/shootout/regex-dna-parallel.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-agggtaaa|tttaccct 1
-[cgt]gggtaaa|tttaccc[acg] 0
-a[act]ggtaaa|tttacc[agt]t 0
-ag[act]gtaaa|tttac[agt]ct 0
-agg[act]taaa|ttta[agt]cct 1
-aggg[acg]aaa|ttt[cgt]ccct 0
-agggt[cgt]aa|tt[acg]accct 0
-agggta[cgt]a|t[acg]taccct 0
-agggtaa[cgt]|[acg]ttaccct 2
-
-10245
-10000
-13348
diff --git a/test/bench/shootout/regex-dna.c b/test/bench/shootout/regex-dna.c
deleted file mode 100644
index 134f821..0000000
--- a/test/bench/shootout/regex-dna.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*
-** The Computer Language Shootout
-** http://shootout.alioth.debian.org/
-** contributed by Mike Pall
-**
-** regex-dna benchmark using PCRE
-**
-** compile with:
-**   gcc -O3 -fomit-frame-pointer -o regexdna regexdna.c -lpcre
-*/
-
-#define __USE_STRING_INLINES
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <pcre.h>
-
-typedef struct fbuf {
-  char *buf;
-  size_t size, len;
-} fbuf_t;
-
-static void fb_init(fbuf_t *b)
-{
-  b->buf = NULL;
-  b->len = b->size = 0;
-}
-
-static char *fb_need(fbuf_t *b, size_t need)
-{
-  need += b->len;
-  if (need > b->size) {
-    if (b->size == 0) b->size = need;
-    else while (need > b->size) b->size += b->size;
-    if (!(b->buf = realloc(b->buf, b->size))) exit(1);
-  }
-  return b->buf+b->len;
-}
-
-#define FB_MINREAD	(3<<16)
-
-/* Read all of a stdio stream into dst buffer. */
-static size_t fb_readall(fbuf_t *dst, FILE *fp)
-{
-  char *dp;
-  int n;
-  for (dp = fb_need(dst, FB_MINREAD);
-       (n = fread(dp, 1, dst->size-dst->len, fp)) > 0;
-       dp = fb_need(dst, FB_MINREAD)) dst->len += n;
-  if (ferror(fp)) exit(1);
-  return dst->len;
-}
-
-/* Substitute pattern p with replacement r, copying from src to dst buffer. */
-static size_t fb_subst(fbuf_t *dst, fbuf_t *src, const char *p, const char *r)
-{
-  pcre *re;
-  pcre_extra *re_ex;
-  const char *re_e;
-  char *dp;
-  int re_eo, m[3], pos, rlen, clen;
-  if (!(re = pcre_compile(p, PCRE_CASELESS, &re_e, &re_eo, NULL))) exit(1);
-  re_ex = pcre_study(re, 0, &re_e);
-  for (dst->len = 0, rlen = strlen(r), pos = 0;
-       pcre_exec(re, re_ex, src->buf, src->len, pos, 0, m, 3) >= 0;
-       pos = m[1]) {
-    clen = m[0]-pos;
-    dp = fb_need(dst, clen+rlen);
-    dst->len += clen+rlen;
-    memcpy(dp, src->buf+pos, clen);
-    memcpy(dp+clen, r, rlen);
-  }
-  clen = src->len-pos;
-  dp = fb_need(dst, clen);
-  dst->len += clen;
-  memcpy(dp, src->buf+pos, clen);
-  return dst->len;
-}
-
-/* Count all matches with pattern p in src buffer. */
-static int fb_countmatches(fbuf_t *src, const char *p)
-{
-  pcre *re;
-  pcre_extra *re_ex;
-  const char *re_e;
-  int re_eo, m[3], pos, count;
-  if (!(re = pcre_compile(p, PCRE_CASELESS, &re_e, &re_eo, NULL))) exit(1);
-  re_ex = pcre_study(re, 0, &re_e);
-  for (count = 0, pos = 0;
-       pcre_exec(re, re_ex, src->buf, src->len, pos, 0, m, 3) >= 0;
-       pos = m[1]) count++;
-  return count;
-}
-
-static const char *variants[] = {
-  "agggtaaa|tttaccct",         "[cgt]gggtaaa|tttaccc[acg]",
-  "a[act]ggtaaa|tttacc[agt]t", "ag[act]gtaaa|tttac[agt]ct",
-  "agg[act]taaa|ttta[agt]cct", "aggg[acg]aaa|ttt[cgt]ccct",
-  "agggt[cgt]aa|tt[acg]accct", "agggta[cgt]a|t[acg]taccct",
-  "agggtaa[cgt]|[acg]ttaccct", NULL
-};
-
-static const char *subst[] = {
-  "B", "(c|g|t)", "D", "(a|g|t)",   "H", "(a|c|t)", "K", "(g|t)",
-  "M", "(a|c)",   "N", "(a|c|g|t)", "R", "(a|g)",   "S", "(c|g)",
-  "V", "(a|c|g)", "W", "(a|t)",     "Y", "(c|t)",   NULL
-};
-
-int main(int argc, char **argv)
-{
-  fbuf_t seq[2];
-  const char **pp;
-  size_t ilen, clen, slen;
-  int flip;
-  fb_init(&seq[0]);
-  fb_init(&seq[1]);
-  ilen = fb_readall(&seq[0], stdin);
-  clen = fb_subst(&seq[1], &seq[0], ">.*|\n", "");
-  for (pp = variants; *pp; pp++)
-    printf("%s %d\n", *pp, fb_countmatches(&seq[1], *pp));
-  for (slen = 0, flip = 1, pp = subst; *pp; pp += 2, flip = 1-flip)
-    slen = fb_subst(&seq[1-flip], &seq[flip], *pp, pp[1]);
-  printf("\n%zu\n%zu\n%zu\n", ilen, clen, slen);
-  return 0;
-}
diff --git a/test/bench/shootout/regex-dna.go b/test/bench/shootout/regex-dna.go
deleted file mode 100644
index 042d7f2..0000000
--- a/test/bench/shootout/regex-dna.go
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- */
-
-package main
-
-import (
-	"fmt"
-	"io/ioutil"
-	"os"
-	"regexp"
-)
-
-var variants = []string{
-	"agggtaaa|tttaccct",
-	"[cgt]gggtaaa|tttaccc[acg]",
-	"a[act]ggtaaa|tttacc[agt]t",
-	"ag[act]gtaaa|tttac[agt]ct",
-	"agg[act]taaa|ttta[agt]cct",
-	"aggg[acg]aaa|ttt[cgt]ccct",
-	"agggt[cgt]aa|tt[acg]accct",
-	"agggta[cgt]a|t[acg]taccct",
-	"agggtaa[cgt]|[acg]ttaccct",
-}
-
-type Subst struct {
-	pat, repl string
-}
-
-var substs = []Subst{
-	Subst{"B", "(c|g|t)"},
-	Subst{"D", "(a|g|t)"},
-	Subst{"H", "(a|c|t)"},
-	Subst{"K", "(g|t)"},
-	Subst{"M", "(a|c)"},
-	Subst{"N", "(a|c|g|t)"},
-	Subst{"R", "(a|g)"},
-	Subst{"S", "(c|g)"},
-	Subst{"V", "(a|c|g)"},
-	Subst{"W", "(a|t)"},
-	Subst{"Y", "(c|t)"},
-}
-
-func countMatches(pat string, bytes []byte) int {
-	re := regexp.MustCompile(pat)
-	n := 0
-	for {
-		e := re.FindIndex(bytes)
-		if len(e) == 0 {
-			break
-		}
-		n++
-		bytes = bytes[e[1]:]
-	}
-	return n
-}
-
-func main() {
-	bytes, err := ioutil.ReadAll(os.Stdin)
-	if err != nil {
-		fmt.Fprintf(os.Stderr, "can't read input: %s\n", err)
-		os.Exit(2)
-	}
-	ilen := len(bytes)
-	// Delete the comment lines and newlines
-	bytes = regexp.MustCompile("(>[^\n]+)?\n").ReplaceAll(bytes, []byte{})
-	clen := len(bytes)
-	for _, s := range variants {
-		fmt.Printf("%s %d\n", s, countMatches(s, bytes))
-	}
-	for _, sub := range substs {
-		bytes = regexp.MustCompile(sub.pat).ReplaceAll(bytes, []byte(sub.repl))
-	}
-	fmt.Printf("\n%d\n%d\n%d\n", ilen, clen, len(bytes))
-}
diff --git a/test/bench/shootout/regex-dna.txt b/test/bench/shootout/regex-dna.txt
deleted file mode 100644
index e23e71f..0000000
--- a/test/bench/shootout/regex-dna.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-agggtaaa|tttaccct 1
-[cgt]gggtaaa|tttaccc[acg] 0
-a[act]ggtaaa|tttacc[agt]t 0
-ag[act]gtaaa|tttac[agt]ct 0
-agg[act]taaa|ttta[agt]cct 1
-aggg[acg]aaa|ttt[cgt]ccct 0
-agggt[cgt]aa|tt[acg]accct 0
-agggta[cgt]a|t[acg]taccct 0
-agggtaa[cgt]|[acg]ttaccct 2
-
-10245
-10000
-13348
diff --git a/test/bench/shootout/reverse-complement.c b/test/bench/shootout/reverse-complement.c
deleted file mode 100644
index b34c846..0000000
--- a/test/bench/shootout/reverse-complement.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*
- * The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org
- *
- * contributed by Bob W
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#define JBFSIZE 82      // line input buffer size
-#define QBFSIZE 5200     // output buffer initial size
-#define Z16     "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
-#define V32     "\0TVGH\0\0CD\0\0M\0KN\0\0\0YSA\0BW\0R\0\0\0\0\0\0"
-#define VALL    Z16 Z16 Z16 Z16 V32 V32 Z16 Z16 Z16 Z16 Z16 Z16 Z16 Z16
-
-int errex(char *s, int n) {      // error message+value, return 1
-  fprintf(stderr,"\n*** Error: %s [%d]!\n", s, n);
-  return 1;
-}
-
-int main () {                    // ***** main *****
-  char *pj, *pq, *pr;            // buffer pointers: inp,out,/out
-  char *jjj = malloc(JBFSIZE);   // allocate input line buffer
-  char *qqq = malloc(QBFSIZE);   // output buffer (dyn. size)
-  char *pqstop = qqq+QBFSIZE;    // end-of-buffer pointer
-  char xtab[256] = VALL;         // char conversion table
-
-  if (!jjj || !qqq)
-    return errex("Buffer allocation", !jjj + !qqq);
-  pj = fgets(jjj,JBFSIZE,stdin);         // fetch 1st line
-  if (!pj)
-    return errex("No input data",0);
-  if (*jjj != '>')
-    return errex("1st char not '>'", 0);
-
-  while (pj) {                           // MAIN LOOP: process data
-    fputs(jjj, stdout);                  // output ID line
-
-    for (pq=qqq+1, pr=pqstop; ; pq++) {  // LOOP: fill output buffer
-      pj = fgets(jjj, JBFSIZE, stdin);   // get line from stdin
-      if (!pj || (*jjj=='>'))  break;    // EOF or new ID line
-      if (pr <= (pq+61)) {               // need to resize buffer
-        char *newstop = pqstop + 12777888;
-        char *newptr  = realloc(qqq, newstop-qqq);
-        if (!newptr)
-          return errex("Out of memory", 0);
-        if (newptr != qqq) {             // new base: adj. pointers
-          size_t x = newptr-qqq;         // offset for pointer update
-          pq+=x;  pr+=x;  qqq+=x;
-          newstop+=x;  pqstop+=x;
-        }
-        pr = __builtin_memmove(newstop-(pqstop-pr), pr, pqstop-pr);
-        pqstop = newstop;                // buffer resize complete
-      }
-      while (*pj) {                      // LOOP: conv. & revert line
-        char c = xtab[(unsigned char)(*pj++)];
-        if (c)                           // conversion valid
-          *(--pr) = c;
-      }
-    }
-
-    for (pq = qqq; pr<pqstop; ) {        // LOOP: format output
-      size_t x = (pqstop-pr)<60 ? pqstop-pr : 60;
-      __builtin_memmove(pq,pr,x);        // move line to free space
-      pr+=x;  pq+=x;  *(pq++) = 0xA;     // adjust pointers, add LF
-    }
-    fwrite(qqq, 1, pq-qqq, stdout);      // output converted data
-  }
-  return 0;
-}
diff --git a/test/bench/shootout/reverse-complement.go b/test/bench/shootout/reverse-complement.go
deleted file mode 100644
index baa30ff..0000000
--- a/test/bench/shootout/reverse-complement.go
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- */
-
-package main
-
-import (
-	"bufio"
-	"os"
-)
-
-const lineSize = 60
-
-var complement = [256]uint8{
-	'A': 'T', 'a': 'T',
-	'C': 'G', 'c': 'G',
-	'G': 'C', 'g': 'C',
-	'T': 'A', 't': 'A',
-	'U': 'A', 'u': 'A',
-	'M': 'K', 'm': 'K',
-	'R': 'Y', 'r': 'Y',
-	'W': 'W', 'w': 'W',
-	'S': 'S', 's': 'S',
-	'Y': 'R', 'y': 'R',
-	'K': 'M', 'k': 'M',
-	'V': 'B', 'v': 'B',
-	'H': 'D', 'h': 'D',
-	'D': 'H', 'd': 'H',
-	'B': 'V', 'b': 'V',
-	'N': 'N', 'n': 'N',
-}
-
-func main() {
-	in := bufio.NewReader(os.Stdin)
-	buf := make([]byte, 1024*1024)
-	line, err := in.ReadSlice('\n')
-	for err == nil {
-		os.Stdout.Write(line)
-
-		// Accumulate reversed complement in buf[w:]
-		nchar := 0
-		w := len(buf)
-		for {
-			line, err = in.ReadSlice('\n')
-			if err != nil || line[0] == '>' {
-				break
-			}
-			line = line[0 : len(line)-1]
-			nchar += len(line)
-			if len(line)+nchar/60+128 >= w {
-				nbuf := make([]byte, len(buf)*5)
-				copy(nbuf[len(nbuf)-len(buf):], buf)
-				w += len(nbuf) - len(buf)
-				buf = nbuf
-			}
-
-			// This loop is the bottleneck.
-			for _, c := range line {
-				w--
-				buf[w] = complement[c]
-			}
-		}
-
-		// Copy down to beginning of buffer, inserting newlines.
-		// The loop left room for the newlines and 128 bytes of padding.
-		i := 0
-		for j := w; j < len(buf); j += 60 {
-			n := copy(buf[i:i+60], buf[j:])
-			buf[i+n] = '\n'
-			i += n + 1
-		}
-		os.Stdout.Write(buf[0:i])
-	}
-}
diff --git a/test/bench/shootout/reverse-complement.txt b/test/bench/shootout/reverse-complement.txt
deleted file mode 100644
index 14d792a..0000000
--- a/test/bench/shootout/reverse-complement.txt
+++ /dev/null
@@ -1,171 +0,0 @@
->ONE Homo sapiens alu
-CGGAGTCTCGCTCTGTCGCCCAGGCTGGAGTGCAGTGGCGCGATCTCGGCTCACTGCAAC
-CTCCGCCTCCCGGGTTCAAGCGATTCTCCTGCCTCAGCCTCCCGAGTAGCTGGGATTACA
-GGCGCGCGCCACCACGCCCGGCTAATTTTTGTATTTTTAGTAGAGACGGGGTTTCACCAT
-GTTGGCCAGGCTGGTCTCGAACTCCTGACCTCAGGTGATCCGCCCGCCTCGGCCTCCCAA
-AGTGCTGGGATTACAGGCGTGAGCCACCGCGCCCGGCCTTTTTGAGACGGAGTCTCGCTC
-TGTCGCCCAGGCTGGAGTGCAGTGGCGCGATCTCGGCTCACTGCAACCTCCGCCTCCCGG
-GTTCAAGCGATTCTCCTGCCTCAGCCTCCCGAGTAGCTGGGATTACAGGCGCGCGCCACC
-ACGCCCGGCTAATTTTTGTATTTTTAGTAGAGACGGGGTTTCACCATGTTGGCCAGGCTG
-GTCTCGAACTCCTGACCTCAGGTGATCCGCCCGCCTCGGCCTCCCAAAGTGCTGGGATTA
-CAGGCGTGAGCCACCGCGCCCGGCCTTTTTGAGACGGAGTCTCGCTCTGTCGCCCAGGCT
-GGAGTGCAGTGGCGCGATCTCGGCTCACTGCAACCTCCGCCTCCCGGGTTCAAGCGATTC
-TCCTGCCTCAGCCTCCCGAGTAGCTGGGATTACAGGCGCGCGCCACCACGCCCGGCTAAT
-TTTTGTATTTTTAGTAGAGACGGGGTTTCACCATGTTGGCCAGGCTGGTCTCGAACTCCT
-GACCTCAGGTGATCCGCCCGCCTCGGCCTCCCAAAGTGCTGGGATTACAGGCGTGAGCCA
-CCGCGCCCGGCCTTTTTGAGACGGAGTCTCGCTCTGTCGCCCAGGCTGGAGTGCAGTGGC
-GCGATCTCGGCTCACTGCAACCTCCGCCTCCCGGGTTCAAGCGATTCTCCTGCCTCAGCC
-TCCCGAGTAGCTGGGATTACAGGCGCGCGCCACCACGCCCGGCTAATTTTTGTATTTTTA
-GTAGAGACGGGGTTTCACCATGTTGGCCAGGCTGGTCTCGAACTCCTGACCTCAGGTGAT
-CCGCCCGCCTCGGCCTCCCAAAGTGCTGGGATTACAGGCGTGAGCCACCGCGCCCGGCCT
-TTTTGAGACGGAGTCTCGCTCTGTCGCCCAGGCTGGAGTGCAGTGGCGCGATCTCGGCTC
-ACTGCAACCTCCGCCTCCCGGGTTCAAGCGATTCTCCTGCCTCAGCCTCCCGAGTAGCTG
-GGATTACAGGCGCGCGCCACCACGCCCGGCTAATTTTTGTATTTTTAGTAGAGACGGGGT
-TTCACCATGTTGGCCAGGCTGGTCTCGAACTCCTGACCTCAGGTGATCCGCCCGCCTCGG
-CCTCCCAAAGTGCTGGGATTACAGGCGTGAGCCACCGCGCCCGGCCTTTTTGAGACGGAG
-TCTCGCTCTGTCGCCCAGGCTGGAGTGCAGTGGCGCGATCTCGGCTCACTGCAACCTCCG
-CCTCCCGGGTTCAAGCGATTCTCCTGCCTCAGCCTCCCGAGTAGCTGGGATTACAGGCGC
-GCGCCACCACGCCCGGCTAATTTTTGTATTTTTAGTAGAGACGGGGTTTCACCATGTTGG
-CCAGGCTGGTCTCGAACTCCTGACCTCAGGTGATCCGCCCGCCTCGGCCTCCCAAAGTGC
-TGGGATTACAGGCGTGAGCCACCGCGCCCGGCCTTTTTGAGACGGAGTCTCGCTCTGTCG
-CCCAGGCTGGAGTGCAGTGGCGCGATCTCGGCTCACTGCAACCTCCGCCTCCCGGGTTCA
-AGCGATTCTCCTGCCTCAGCCTCCCGAGTAGCTGGGATTACAGGCGCGCGCCACCACGCC
-CGGCTAATTTTTGTATTTTTAGTAGAGACGGGGTTTCACCATGTTGGCCAGGCTGGTCTC
-GAACTCCTGACCTCAGGTGATCCGCCCGCCTCGGCCTCCCAAAGTGCTGGGATTACAGGC
-GTGAGCCACCGCGCCCGGCC
->TWO IUB ambiguity codes
-TAGGDHACHATCRGTRGVTGAGWTATGYTGCTGTCABACDWVTRTAAGAVVAGATTTNDA
-GASMTCTGCATBYTTCAAKTTACMTATTACTTCATARGGYACMRTGTTTTYTATACVAAT
-TTCTAKGDACKADACTATATNTANTCGTTCACGBCGYSCBHTANGGTGATCGTAAAGTAA
-CTATBAAAAGATSTGWATBCSGAKHTTABBAACGTSYCATGCAAVATKTSKTASCGGAAT
-WVATTTNTCCTTCTTCTTDDAGTGGTTGGATACVGTTAYMTMTBTACTTTHAGCTAGBAA
-AAGAGKAAGTTRATWATCAGATTMDDTTTAAAVAAATATTKTCYTAAATTVCNKTTRACG
-ADTATATTTATGATSADSCAATAWAGCGRTAGTGTAAGTGACVGRADYGTGCTACHVSDT
-CTVCARCSYTTAATATARAAAATTTAATTTACDAATTGBACAGTAYAABATBTGCAGBVG
-TGATGGDCAAAATBNMSTTABKATTGGSTCCTAGBTTACTTGTTTAGTTTATHCGATSTA
-AAGTCGAKAAASTGTTTTAWAKCAGATATACTTTTMTTTTGBATAGAGGAGCMATGATRA
-AAGGNCAYDCCDDGAAAGTHGBTAATCKYTBTACBGTBCTTTTTGDTAASSWTAAWAARA
-TTGGCTAAGWGRADTYACATAGCTCBTAGATAWAGCAATNGTATMATGTTKMMAGTAWTC
-CCNTSGAAWATWCAAAAMACTGAADNTYGATNAATCCGAYWNCTAACGTTAGAGDTTTTC
-ATCTGGKRTAVGAABVCTGWGBTCTDVGKATTBTCTAAGGVADAAAVWTCTAGGGGAGGG
-TTAGAACAATTAAHTAATNAAATGCATKATCTAAYRTDTCAGSAYTTYHGATRTTWAVTA
-BGNTCDACAGBCCRCAGWCRTCABTGMMAWGMCTCAACCGATRTGBCAVAATCGTDWDAA
-CAYAWAATWCTGGTAHCCCTAAGATAACSCTTAGTGSAACAWTBGTCDTTDGACWDBAAC
-HTTTNGSKTYYAAYGGATNTGATTTAARTTAMBAATCTAAGTBTCATYTAACTTADTGTT
-TCGATACGAAHGGCYATATACCWDTKYATDCSHTDTCAAAATGTGBACTGSCCVGATGTA
-TCMMAGCCTTDAAABAATGAAGAGTAACTHATMGVTTAATAACCCGGTTVSANTGCAATT
-GTGAGATTTAMGTTTAMAAYGCTGACAYAAAAAGGCACAMYTAAGVGGCTGGAABVTACG
-GATTSTYGTBVAKTATWACCGTGTKAGTDTGTATGTTTAAAGGAAAAAGTAACATARAAA
-GGTYCAMNYAAABTATAGNTSATANAGTCATCCTATWADKAACTRGTMSACDGTATSAYT
-AAHSHGTAABYGACTYTATADTGSTATAGAGAAATCGNTAAAGGAAATCAGTTGTNCYMV
-TNACDRTATBNATATASTAGAAMSCGGGANRCKKMCAAACATTNAGTCTRMAATBMTACC
-CGTACTTCTBGDSYAATWGAAAATGACADDCHAKAAAYATATTKTTTTCACANACWAGAA
-AKATCCTTATTAYKHKCTAAACARTATTTTDATBTVWCYGCAATACTAGGKAAASTTDGA
-MGGCHTTHAATVCAHDRYAGGRCTATACGTCMAGAGAGCTBTHGNACARTCCBDCTAAGA
-GCGGCTTTARTAAAGAATCCNAGTAWBTGACTTGAATTACWTVACAGAAABCAATNAAAC
-CGTNTRANTTGAYCMAWBADTANABRGGTKTHTWTAGTTVCTMBKTAGMTVKCCAGCANT
-TVAGSWTTAGCCGCRHTTTCCTTHNTATTAAGAAGAATAGGMTRAARTCTABGTACDTTT
-TATAAVDHAHTATAGATCCTAGTAAGYTWATDWCATGAGGGATAGTAAMDMNGBASTWAM
-TSTATRBAYDABATGTATATYCGCACTGTTTTAACMCWBTATAWAGTATBTSTATVTTAR
-CCTMTTAAKADATCAACTAATYTSVTAKGDATTATGCKTCAYCAKAATACTTKAANGAGT
-ATTSDAGATCGGAAATACTTAAYAAVGTATMCGCTTGTGTDCTAATYTATTTTATTTWAA
-CAGWRCTATGTAGMTGTTTGTTYKTNGTTKTCAGAACNTRACCTACKTGSRATGTGGGGG
-CTGTCATTAAGTAAATNGSTTABCCCCTCGCAGCTCWHTCGCGAAGCAVATGCKACGHCA
-ACAKTTAATAACASAAADATTWNYTGTAATTGTTCGTMHACHTWATGTGCWTTTTGAAHY
-ACTTTGTAYAMSAAACTTAADAAATATAGTABMATATYAATGSGGTAGTTTGTGTBYGGT
-TWSGSVGWMATTDMTCCWWCABTCSVACAGBAATGTTKATBGTCAATAATCTTCTTAAAC
-ARVAATHAGYBWCTRWCABGTWWAATCTAAGTCASTAAAKTAAGVKBAATTBGABACGTA
-AGGTTAAATAAAAACTRMDTWBCTTTTTAATAAAAGATMGCCTACKAKNTBAGYRASTGT
-ASSTCGTHCGAAKTTATTATATTYTTTGTAGAACATGTCAAAACTWTWTHGKTCCYAATA
-AAGTGGAYTMCYTAARCSTAAATWAKTGAATTTRAGTCTSSATACGACWAKAASATDAAA
-TGYYACTSAACAAHAKTSHYARGASTATTATTHAGGYGGASTTTBGAKGATSANAACACD
-TRGSTTRAAAAAAAACAAGARTCVTAGTAAGATAWATGVHAAKATWGAAAAGTYAHVTAC
-TCTGRTGTCAWGATRVAAKTCGCAAVCGASWGGTTRTCSAMCCTAACASGWKKAWDAATG
-ACRCBACTATGTGTCTTCAAAHGSCTATATTTCGTVWAGAAGTAYCKGARAKSGKAGTAN
-TTTCYACATWATGTCTAAAADMDTWCAATSTKDACAMAADADBSAAATAGGCTHAHAGTA
-CGACVGAATTATAAAGAHCCVAYHGHTTTACATSTTTATGNCCMTAGCATATGATAVAAG
->THREE Homo sapiens frequency
-ATATTTATCTTTTCACTTCCTACATTGGTCAGACCATTATTCGACACGTGGCGTCATTTT
-GTCATACCGGGTAATGTTGGAAACAAAACGTACTGATAAAATACTGAGTTGTAAACTCTA
-ATCAGATAACGCGCTTGGATATTAAGATTCACACAGGGGTTTCGGCTGTAAAAAAACTTG
-TGGAGCTGTTCTGGGACAGATAAGTTGTACCTCGTACTTAGCTAATTAATGAACCAACTG
-ATTACGATAGAACAATTCTGAGGCCGCCAGGACAGCCAAATTTTAATCTTATAAAGCTGG
-AAACAGCCGGTATTAGCTTCTCGCATACTTTGCCTGCATTGGTACCTTACAGATATCAGC
-GTAGTCATATACACCTCGGTCTCAGCTAAGCTTGTATCTCTTAGAGTAGTTCAAAGATAG
-TGGACAATACCTGTGGAATCGATTGCAGATATGGATTTATTTAACTACTGAGTCTCATTC
-ACAAGCTAAGCAAGGAGCACGTTTTGGTGCCGGCATACCGATTTGCTATCATGTCAGCAA
-ATTTGCGTTGTATTCCTAGTTGCACCCATTAAGGCCACACTCCGAACCTAATTATTACAT
-CGCAAAGACATGTACGAAGGACCCGATGTCGAATAGAAGGGAGGACTGTTCATTGGAAGC
-TAGACCAGAGGAATCGCAAAGATGCAACTCTTACAATAAAAATCTAATTTCAGTCAACAC
-GCAATTTCTATAAGGTTTCCGATAATAATGAACCGTCTTCCACAGGGGAATTTGCCATGC
-TCGTAAAAGTAGTTAATCCAAGTAGAAGAAATTTTGATAATGTTTTAAGTTGGCACGAAG
-GAATTCAGAGAGATCTTACCTAACAAAGGCATTAGTAGATGTTCCTTGGTTCACACTCGG
-TCAATCAGAGCACATACTACGGGCGATACCGGGAATGACACAACATCAATGAGATTGTTA
-AGTGAGGTAATTGACTTTAGAGGACTCGATCAGTATACTGTCACTATGAACATCGTATTA
-ATTGTTATCCGATATATACACCACCGATTTGCTTGTGCAAGGTTACAGACCCATTCGATA
-AATACAAACACGGAGCGATATTATTTAAGGAGTGCTGTCTTCAAAAGAATTATTCCCACA
-CCGACATAAGAACTTCGCTCCGTCATTCCAGATTTAAATAACATAACGTAACGCTTTGCT
-GATAACATAACATAACCGAGAATTTGCTTAGGAAATTTGGAGCAATATTGCATTGTTTCT
-CAGTCATCACAAGGCCCGCCAAAGAACTCTGAGAATCAGGATTCAACATGATTGGTAAGA
-CTCTATATATATAACTTAATTCTTGTGTCCGGAGATAGAAAGAGGACGAGAGATACTACG
-AAAGAAAGTGTACTTCGATGTATCAATTCAGACGCCTTCTCTATCATCAACATTATAGGT
-CTCGTATATGCTCGGCGCGATCTGCTTCTCTCCGCCAATAGCCCCATAGTGTATTTCAAG
-CGCAGTAACAGTGAAATCGTTACGAAGGTAGGGATGTTGCTTATAATTGTCGTAACTTAT
-CGCTTATGTATCTTTCAAGAATGAACGGCAGCATATACATACGTTCTACCTTTAGCTACA
-AAGCATCCATATACTCCCTCTCATGATTGAAACTCTTCCCTATTTTGTAGCCAATAGTGA
-AAGCGTATTAGTATAAATTCGTCGGTTTTTCACTCGCAACTGTTATACTCTGCAAACAAA
-CGAAAGCCTCATAGTACAAACCTAAAGCTACATACTTCATCATTGGCAGACCAGTGGCGG
-TATTTCTACGGAAGCATCACTATAGATATAAAGTTTCCCTTCATGTACGTCTGTTAACCA
-TATCACAAGAAACTGCTATCTCTGTCACGTAACAATTCACGCGCCTTATCGCCAAATGTT
-CATATATGCGCGGTATACGTATGAACGAATACTAATTAGTATAACGGAGGATTCACGGGA
-GGGATACTTGGGGCATTTATAAATCGTCTAAAAATTTTCTATCAGCACTTGCGGGTTATA
-GTGGATTACTAGGCAACATAATATTCTGTATTGGTCCAAATGACGCTATAGATAAATTAG
-CAAAATACATTGTTTCCATTTATGTAAGTCGAAACTCCAGGACTCCCGGGAACCAGTTAA
-ACCGTCTGGAAAAGACACATTGTGAGCGGGACTTCAATGATAGCTTTCAATGAGCTTCTC
-ATGCTTGGGGTCTGTACATATATGTTGGCGAAATTATCGTCTGTATTCTGTTATGCTTTG
-ATCATGGGTTATTAGTATAGTGTCCGGTTAAGTACCAATACCGCTAGAGACCCGACCTAA
-GTCGATAACTAACGATCATCGACGTAAGGATCGTCTCGATCAGTACTTCAGTCTAGATCT
-GGGAATAGTAACTCGTTAGTGAACTATGTCGTGTCATAACTCTAAAATGCAATCAAATCT
-TATTATTGAGTATTGATTATATAAAGCATCCGCTTAGCTTTACCCTCAAATGTTATATGC
-AATTTAAAGCGCTTGATATCGTCTACTCAAGTTCAGGTTTCACATGGCCGCAACGTGACG
-TTATTAGAGGTGGGTCATCATCTCTGAGGCTAGTGATGTTGAATACTCATTGAATGGGAA
-GTGGAATACCATGCTCGTAGGTAACAGCATGACCTATAAAATATACTATGGGTGTGTGGT
-AGATCAATATTGTTCAAGCATATCGTAACAATAACGGCTGAAATGTTACTGACATGAAAG
-AGGGAGTCCAAACCATTCTAACAGCTGATCAAGTCGTCTAAAAACGCCTGGTTCAGCCTT
-AAGAGTTATAAGCCAGACAAATTGTATCAATAGAGAATCCGTAAATTCCTCGGCCAACCT
-CTTGCAAAGACATCACTATCAATATACTACCGTGATCTTAATTAGTGAACTTATATAAAT
-ATCTACAACCAGATTCAACGGAAAAGCTTTAGTGGATTAGAAATTGCCAAGAATCACATT
-CATGTGGGTTCGAATGCTTTAGTAATACCATTTCGCCGAGTAGTCACTTCGCTGAACTGT
-CGTAAATTGCTATGACATAATCGAAAAGGATTGTCAAGAGTCGATTACTGCGGACTAATA
-ATCCCCACGGGGGTGGTCTCATGTCTCCCCAGGCGAGTGGGGACGGTTGATAAACACGCT
-GCATCGCGGACTGATGTTCCCAGTATTACATAGTCACATTGGATTGCGAGTAGTCTACCT
-ATTTATGAGCGAGAGATGCCTCTAACTACTTCGACTTTTAAAACCTTTCCACGCCAGTAT
-TCGGCGAAAGGGAAGTATTAAGGGTTGTCATAATTAAGCTGATACCACTTCAGACTTTGC
-TCTACTTCTGTCTTTCATTGGTTTAGTAAAGTCTGTCCATTCGTCGAGACCGTCTTTTGC
-AGCCTCATTCTACCAACTGCTCCGACTCTTAGTCTGCTTCTCCCAGCGTTATAACAAGAG
-GCATTTTGTCATCCTTAAAACAATAATAAAGAACTCGGAGCACTGATATAATGACTGAAT
-TAGAACCGCTTAAAAATACAACGAATAGATAAGACTATCGGATAAGATCTAATATGTAGT
-GATTAAGCCCTTTATTAATTAATAATAGTTACCCTTTCTGATGTAACGCGACATATTACG
-ATTTAGTGGCACGTCTGAATTGCAAAGCAGATCTCTACCCGATTTTTATTATAAATCCCG
-TATACATCTTGACTTGAGTAATTGTTCATCTTTTTATATCTCTTCGTACTACAAATAATT
-AATATCTCAACCCGTATTGTGTGATTCTAATTACCAACAGAATACGAGGAGGTTTTTGCT
-TAGGGCCATATATAATGAATCTATCTCGTTTATTCGCGGAACCCGAGATAACATTACGAT
-GTAACTATTTTAGAGAACTTAATACAAGAAACATTGCTGATTACTCATAACTAAATGCTT
-GGTAATATATCCTCAGTGCCCCTACCATCTTTTACGCAGGGATGTAATTACTTAGGATTC
-ATTGTGTAAGAATTACAATGAACGATGGATATGAAGGCATGTTGCGAGGTGTTCCTTGGT
-ATGTGAAGTTCGCAGGGCAACAAAAATTTCGCAGAATAGGCCTCAAAGTATTGGTAAAGA
-AGACAACTAATCATCACGAGCTTCTGATATCAATACGAACGAGTCCTGTGATGGATGAAA
-GAAAGTCGTATCGAAAATGTCAAGAGTCTGCCCAATGTAACTTACTTCAAAAAATAACGC
-TTCCGCCAAGTACGTTCGAATAAACGTAATTTTAAAAATACATAAGGGGTGTTAGAAAGT
-AAGCGACGGGATATAAGTTAGACTCAAGATTCCGCCGTAAAACGAGACTGATTCCGAAGA
-TTGTTCGTGGATCTGGTCATGACTTTCACTGAGTAAGGAGTTTCGACATATGTCAATAAA
-CACAAAAATAGAAGCTATTCGATCTGAAAAATATTAGGACAAGAAACTATCTCACGCTAG
-CCCAGAATATTCACTCACCCACGGGCGATACTAAAGCACTATATAGTCGCGTGATTACTA
-TACATATGGTACACATAAGAATCACGATCAGGTTCTCAATTTTCAACAATATATGTTTAT
-TTGCATAGGTAATATTAGGCCTTTAAGAGAAGGATGGGTGAGATACTCCGGGGATGGCGG
-CAATAAAGAAAAACACGATATGAGTAATAGGATCCTAATATCTTGGCGAGAGACTTAAGG
-TACGAATTTTGCGCAATCTATTTTTTACTTGGCCAGAATTCATGTATGGTATAAGTACGA
-ACTTTTTTGATCACTTTCATGGCTACCTGATTAGGATAGTTTGAGGAATTTCCCAAATAT
-ACCGATTTAATATACACTAGGGCTTGTCACTTTGAGTCAGAAAAAGAATATAATTACTTA
-GGGTAATGCTGCATACATATTCTTATATTGCAAAGGTTCTCTGGGTAATCTTGAGCCTTC
-ACGATACCTGGTGAAGTGTT
diff --git a/test/bench/shootout/spectral-norm-parallel.go b/test/bench/shootout/spectral-norm-parallel.go
deleted file mode 100644
index 2706f39..0000000
--- a/test/bench/shootout/spectral-norm-parallel.go
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * Based on spectral-norm.c by Sebastien Loisel
- */
-
-package main
-
-import (
-	"flag"
-	"fmt"
-	"math"
-	"runtime"
-)
-
-var n = flag.Int("n", 2000, "count")
-var nCPU = flag.Int("ncpu", 4, "number of cpus")
-
-func evalA(i, j int) float64 { return 1 / float64(((i+j)*(i+j+1)/2 + i + 1)) }
-
-type Vec []float64
-
-func (v Vec) Times(i, n int, u Vec, c chan int) {
-	for ; i < n; i++ {
-		v[i] = 0
-		for j := 0; j < len(u); j++ {
-			v[i] += evalA(i, j) * u[j]
-		}
-	}
-	c <- 1
-}
-
-func (v Vec) TimesTransp(i, n int, u Vec, c chan int) {
-	for ; i < n; i++ {
-		v[i] = 0
-		for j := 0; j < len(u); j++ {
-			v[i] += evalA(j, i) * u[j]
-		}
-	}
-	c <- 1
-}
-
-func wait(c chan int) {
-	for i := 0; i < *nCPU; i++ {
-		<-c
-	}
-}
-
-func (v Vec) ATimesTransp(u Vec) {
-	x := make(Vec, len(u))
-	c := make(chan int, *nCPU)
-	for i := 0; i < *nCPU; i++ {
-		go x.Times(i*len(v) / *nCPU, (i+1)*len(v) / *nCPU, u, c)
-	}
-	wait(c)
-	for i := 0; i < *nCPU; i++ {
-		go v.TimesTransp(i*len(v) / *nCPU, (i+1)*len(v) / *nCPU, x, c)
-	}
-	wait(c)
-}
-
-func main() {
-	flag.Parse()
-	runtime.GOMAXPROCS(*nCPU)
-	N := *n
-	u := make(Vec, N)
-	for i := 0; i < N; i++ {
-		u[i] = 1
-	}
-	v := make(Vec, N)
-	for i := 0; i < 10; i++ {
-		v.ATimesTransp(u)
-		u.ATimesTransp(v)
-	}
-	var vBv, vv float64
-	for i := 0; i < N; i++ {
-		vBv += u[i] * v[i]
-		vv += v[i] * v[i]
-	}
-	fmt.Printf("%0.9f\n", math.Sqrt(vBv/vv))
-}
diff --git a/test/bench/shootout/spectral-norm.c b/test/bench/shootout/spectral-norm.c
deleted file mode 100644
index 832eb3d..0000000
--- a/test/bench/shootout/spectral-norm.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* -*- mode: c -*-
- *
- * The Great Computer Language Shootout
- * http://shootout.alioth.debian.org/
- *
- * Contributed by Sebastien Loisel
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-double eval_A(int i, int j) { return 1.0/((i+j)*(i+j+1)/2+i+1); }
-
-void eval_A_times_u(int N, const double u[], double Au[])
-{
-  int i,j;
-  for(i=0;i<N;i++)
-    {
-      Au[i]=0;
-      for(j=0;j<N;j++) Au[i]+=eval_A(i,j)*u[j];
-    }
-}
-
-void eval_At_times_u(int N, const double u[], double Au[])
-{
-  int i,j;
-  for(i=0;i<N;i++)
-    {
-      Au[i]=0;
-      for(j=0;j<N;j++) Au[i]+=eval_A(j,i)*u[j];
-    }
-}
-
-void eval_AtA_times_u(int N, const double u[], double AtAu[])
-{ double v[N]; eval_A_times_u(N,u,v); eval_At_times_u(N,v,AtAu); }
-
-int main(int argc, char *argv[])
-{
-  int i;
-  int N = ((argc == 2) ? atoi(argv[1]) : 2000);
-  double u[N],v[N],vBv,vv;
-  for(i=0;i<N;i++) u[i]=1;
-  for(i=0;i<10;i++)
-    {
-      eval_AtA_times_u(N,u,v);
-      eval_AtA_times_u(N,v,u);
-    }
-  vBv=vv=0;
-  for(i=0;i<N;i++) { vBv+=u[i]*v[i]; vv+=v[i]*v[i]; }
-  printf("%0.9f\n",sqrt(vBv/vv));
-  return 0;
-}
diff --git a/test/bench/shootout/spectral-norm.go b/test/bench/shootout/spectral-norm.go
deleted file mode 100644
index 6667f3e..0000000
--- a/test/bench/shootout/spectral-norm.go
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- * Based on spectral-norm.c by Sebastien Loisel
- */
-
-package main
-
-import (
-	"flag"
-	"fmt"
-	"math"
-)
-
-var n = flag.Int("n", 2000, "count")
-
-func evalA(i, j int) float64 { return 1 / float64(((i+j)*(i+j+1)/2 + i + 1)) }
-
-type Vec []float64
-
-func (v Vec) Times(u Vec) {
-	for i := 0; i < len(v); i++ {
-		v[i] = 0
-		for j := 0; j < len(u); j++ {
-			v[i] += evalA(i, j) * u[j]
-		}
-	}
-}
-
-func (v Vec) TimesTransp(u Vec) {
-	for i := 0; i < len(v); i++ {
-		v[i] = 0
-		for j := 0; j < len(u); j++ {
-			v[i] += evalA(j, i) * u[j]
-		}
-	}
-}
-
-func (v Vec) ATimesTransp(u Vec) {
-	x := make(Vec, len(u))
-	x.Times(u)
-	v.TimesTransp(x)
-}
-
-func main() {
-	flag.Parse()
-	N := *n
-	u := make(Vec, N)
-	for i := 0; i < N; i++ {
-		u[i] = 1
-	}
-	v := make(Vec, N)
-	for i := 0; i < 10; i++ {
-		v.ATimesTransp(u)
-		u.ATimesTransp(v)
-	}
-	var vBv, vv float64
-	for i := 0; i < N; i++ {
-		vBv += u[i] * v[i]
-		vv += v[i] * v[i]
-	}
-	fmt.Printf("%0.9f\n", math.Sqrt(vBv/vv))
-}
diff --git a/test/bench/shootout/spectral-norm.txt b/test/bench/shootout/spectral-norm.txt
deleted file mode 100644
index b988598..0000000
--- a/test/bench/shootout/spectral-norm.txt
+++ /dev/null
@@ -1 +0,0 @@
-1.274224152
diff --git a/test/bench/shootout/threadring.c b/test/bench/shootout/threadring.c
deleted file mode 100644
index 606db71..0000000
--- a/test/bench/shootout/threadring.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/*
-* The Computer Language Benchmarks Game
-* http://shootout.alioth.debian.org/
-
-* contributed by Premysl Hruby
-*/
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <pthread.h>
-#include <string.h>
-#include <limits.h>
-
-// PTHREAD_STACK_MIN undeclared on mingw
-#ifndef PTHREAD_STACK_MIN
-#define PTHREAD_STACK_MIN 65535
-#endif
-
-#define THREADS (503)
-
-struct stack {
-   char x[PTHREAD_STACK_MIN];
-};
-
-
-/* staticaly initialize mutex[0] mutex */
-static pthread_mutex_t mutex[THREADS];
-static int data[THREADS];
-static struct stack stacks[THREADS];
-/* stacks must be defined staticaly, or my i386 box run of virtual memory for this
- * process while creating thread +- #400 */
-
-static void* thread(void *num)
-{
-   int l = (int)(uintptr_t)num;
-   int r = (l+1) % THREADS;
-   int token;
-
-   while(1) {
-      pthread_mutex_lock(mutex + l);
-      token = data[l];
-      if (token) {
-         data[r] = token - 1;
-         pthread_mutex_unlock(mutex + r);
-      }
-      else {
-         printf("%i\n", l+1);
-         exit(0);
-      }
-   }
-}
-
-
-
-int main(int argc, char **argv)
-{
-   int i;
-   pthread_t cthread;
-   pthread_attr_t stack_attr;
-
-   if (argc != 2)
-      exit(255);
-   data[0] = atoi(argv[1]);
-
-   pthread_attr_init(&stack_attr);
-
-   for (i = 0; i < THREADS; i++) {
-      pthread_mutex_init(mutex + i, NULL);
-      pthread_mutex_lock(mutex + i);
-
-#if defined(__MINGW32__) || defined(__MINGW64__)
-      pthread_attr_setstackaddr(&stack_attr, &stacks[i]);
-      pthread_attr_setstacksize(&stack_attr, sizeof(struct stack));
-#else
-      pthread_attr_setstack(&stack_attr, &stacks[i], sizeof(struct stack));
-#endif
-
-      pthread_create(&cthread, &stack_attr, thread, (void*)(uintptr_t)i);
-   }
-
-   pthread_mutex_unlock(mutex + 0);
-   pthread_join(cthread, NULL);
-}
diff --git a/test/bench/shootout/threadring.go b/test/bench/shootout/threadring.go
deleted file mode 100644
index e76dd0b..0000000
--- a/test/bench/shootout/threadring.go
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
-
-    * Neither the name of "The Computer Language Benchmarks Game" nor the
-    name of "The Computer Language Shootout Benchmarks" nor the names of
-    its contributors may be used to endorse or promote products derived
-    from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
-*/
-
-/* The Computer Language Benchmarks Game
- * http://shootout.alioth.debian.org/
- *
- * contributed by The Go Authors.
- */
-
-package main
-
-import (
-	"flag"
-	"fmt"
-	"os"
-)
-
-var n = flag.Int("n", 1000, "how many passes")
-
-const Nthread = 503
-
-func f(i int, in <-chan int, out chan<- int) {
-	for {
-		n := <-in
-		if n == 0 {
-			fmt.Printf("%d\n", i)
-			os.Exit(0)
-		}
-		out <- n - 1
-	}
-}
-
-func main() {
-	flag.Parse()
-
-	one := make(chan int) // will be input to thread 1
-	var in, out chan int = nil, one
-	for i := 1; i <= Nthread-1; i++ {
-		in, out = out, make(chan int)
-		go f(i, in, out)
-	}
-	go f(Nthread, out, one)
-	one <- *n
-	<-make(chan int) // hang until ring completes
-}
diff --git a/test/bench/shootout/threadring.txt b/test/bench/shootout/threadring.txt
deleted file mode 100644
index f9aaa4d..0000000
--- a/test/bench/shootout/threadring.txt
+++ /dev/null
@@ -1 +0,0 @@
-498
diff --git a/test/bench/shootout/timing.log b/test/bench/shootout/timing.log
deleted file mode 100644
index 4e7d17a..0000000
--- a/test/bench/shootout/timing.log
+++ /dev/null
@@ -1,1254 +0,0 @@
-All tests on r45 or r70
-
-Aug 3 2009
-
-First version of fasta. Translation of fasta.c, fetched from
-	http://shootout.alioth.debian.org/u32q/benchmark.php?test=fasta&lang=gpp&id=4
-
-fasta -n 25000000
-	gcc -O2 fasta.c	5.98u 0.00s 6.01r
-	gccgo -O2 fasta.go	8.82u 0.02s 8.85r
-	6g fasta.go	13.50u 0.02s 13.53r
-	6g -B fata.go	12.99u 0.02s 13.02r
-
-Aug 4 2009
-[added timing.sh]
-
-# myrandom:
-#   hand-written optimization of integer division
-#   use int32->float conversion
-fasta -n 25000000
-	# probably I/O library inefficiencies
-	gcc -O2 fasta.c	5.99u 0.00s 6.00r 
-	gccgo -O2 fasta.go	8.82u 0.02s 8.85r
-	gc fasta	10.70u 0.00s 10.77r
-	gc_B fasta	10.09u 0.03s 10.12r
-
-reverse-complement < output-of-fasta-25000000
-	# we don't know - memory cache behavior?
-	gcc -O2 reverse-complement.c	2.04u 0.94s 10.54r
-	gccgo -O2 reverse-complement.go	6.54u 0.63s 7.17r
-	gc reverse-complement	6.55u 0.70s 7.26r
-	gc_B reverse-complement	6.32u 0.70s 7.10r
-
-nbody 50000000
-	# math.Sqrt needs to be in assembly; inlining is probably the other 50%
-	gcc -O2 nbody.c	21.61u 0.01s 24.80r
-	gccgo -O2 nbody.go	118.55u 0.02s 120.32r
-	gc nbody	100.84u 0.00s 100.85r
-	gc_B nbody	103.33u 0.00s 103.39r
-[
-hacked Sqrt in assembler
-	gc nbody	31.97u 0.00s 32.01r
-]
-
-binary-tree 15 # too slow to use 20
-	# memory allocation and garbage collection
-	gcc -O2 binary-tree.c -lm	0.86u 0.00s 0.87r
-	gccgo -O2 binary-tree.go	1.69u 0.46s 2.15r
-	gccgo -O2 binary-tree-freelist.go	8.48u 0.00s 8.48r
-	gc binary-tree	9.60u 0.01s 9.62r
-	gc binary-tree-freelist	0.48u 0.01s 0.50r
-
-August 5, 2009
-
-fannkuch 12
-	# bounds checking is half the difference
-	# rest might be registerization
-	gcc -O2 fannkuch.c	60.09u 0.01s 60.32r
-	gccgo -O2 fannkuch.go	64.89u 0.00s 64.92r
-	gc fannkuch	124.59u 0.00s 124.67r
-	gc_B fannkuch	91.14u 0.00s 91.16r
-
-regex-dna 100000
-	# regexp code is slow on trivial regexp
-	gcc -O2 regex-dna.c -lpcre	0.92u 0.00s 0.99r
-	gc regexp-dna	26.94u 0.18s 28.75r
-	gc_B regexp-dna	26.51u 0.09s 26.75r
-
-spectral-norm 5500
-	gcc -O2 spectral-norm.c -lm	11.54u 0.00s 11.55r
-	gccgo -O2 spectral-norm.go	12.20u 0.00s 12.23r
-	gc spectral-norm	50.23u 0.00s 50.36r
-	gc_B spectral-norm	49.69u 0.01s 49.83r
-	gc spectral-norm-parallel	24.47u 0.03s 11.05r  # has shift >>1 not div /2
-	[using >>1 instead of /2 : gc gives 24.33u 0.00s 24.33r]
-
-August 6, 2009
-
-k-nucleotide 5000000
-	# string maps are slower than glib string maps
-	gcc -O2 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include k-nucleotide.c -lglib-2.0	k-nucleotide.c: 10.72u 0.01s 10.74r
-	gccgo -O2 k-nucleotide.go	21.64u 0.83s 22.78r
-	gc k-nucleotide	16.08u 0.06s 16.50r
-	gc_B k-nucleotide	17.32u 0.02s 17.37r
-
-mandelbrot 5500
-	# floating point code generator should use more registers
-	gcc -O2 mandelbrot.c	56.13u 0.02s 56.17r
-	gccgo -O2 mandelbrot.go	57.49u 0.01s 57.51r
-	gc mandelbrot	74.32u 0.00s 74.35r
-	gc_B mandelbrot	74.28u 0.01s 74.31r
-
-meteor 2100
-	# we don't know
-	gcc -O2 meteor-contest.c	0.10u 0.00s 0.10r
-	gccgo -O2 meteor-contest.go	0.12u 0.00s 0.14r
-	gc meteor-contest	0.24u 0.00s 0.26r
-	gc_B meteor-contest	0.23u 0.00s 0.24r
-
-pidigits 10000
-	# bignum is slower than gmp
-	gcc -O2 pidigits.c -lgmp	2.60u 0.00s 2.62r
-	gc pidigits	77.69u 0.14s 78.18r
-	gc_B pidigits	74.26u 0.18s 75.41r
-	gc_B pidigits	68.48u 0.20s 69.31r   # special case: no bounds checking in bignum
-
-August 7 2009
-
-# New gc does better division by powers of 2.  Significant improvements:
-
-spectral-norm 5500
-	# floating point code generator should use more registers; possibly inline evalA
-	gcc -O2 spectral-norm.c -lm	11.50u 0.00s 11.50r
-	gccgo -O2 spectral-norm.go	12.02u 0.00s 12.02r
-	gc spectral-norm	23.98u 0.00s 24.00r	# new time is 0.48 times old time, 52% faster
-	gc_B spectral-norm	23.71u 0.01s 23.72r	# ditto
-	gc spectral-norm-parallel	24.04u 0.00s 6.26r  # /2 put back.  note: 4x faster (on r70, idle)
-
-k-nucleotide 1000000
-	# string maps are slower than glib string maps
-	gcc -O2 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include k-nucleotide.c -lglib-2.0	10.82u 0.04s 10.87r
-	gccgo -O2 k-nucleotide.go	22.73u 0.89s 23.63r
-	gc k-nucleotide	15.97u 0.03s 16.04r
-	gc_B k-nucleotide	15.86u 0.06s 15.93r	# 8.5% faster, but probably due to weird cache effeccts in previous version
-
-pidigits 10000
-	# bignum is slower than gmp
-	gcc -O2 pidigits.c -lgmp	2.58u 0.00s 2.58r
-	gc pidigits	71.24u 0.04s 71.28r	# 8.5% faster
-	gc_B pidigits	71.25u 0.03s 71.29r	# 4% faster
-
-threadring 50000000
-	gcc -O2 threadring.c -lpthread	35.51u 160.21s 199.50r
-	gccgo -O2 threadring.go	90.33u 459.95s 448.03r
-	gc threadring	33.11u 0.00s 33.14r
-	GOMAXPROCS=4 gc threadring	114.48u 226.65s 371.59r
-	# change wait code to do <-make(chan int) instead of time.Sleep
-	gc threadring	28.41u 0.01s 29.35r
-	GOMAXPROCS=4 gc threadring	112.59u 232.83s 384.72r
-	
-chameneos 6000000
-	gcc -O2 chameneosredux.c -lpthread	18.14u 276.52s 76.93r
-	gc chameneosredux	20.19u 0.01s 20.23r
-
-Aug 10 2009
-
-# new 6g with better fp registers, fast div and mod of integers
-# complete set of timings listed. significant changes marked ***
-
-fasta -n 25000000
-	# probably I/O library inefficiencies
-	gcc -O2 fasta.c	5.96u 0.00s 5.97r
-	gc fasta	10.59u 0.01s 10.61r
-	gc_B fasta	9.92u 0.02s 9.95r
-
-reverse-complement < output-of-fasta-25000000
-	# we don't know - memory cache behavior?
-	gcc -O2 reverse-complement.c	1.96u 1.56s 16.23r
-	gccgo -O2 reverse-complement.go	6.41u 0.62s 7.05r
-	gc reverse-complement	6.46u 0.70s 7.17r
-	gc_B reverse-complement	6.22u 0.72s 6.95r
-
-nbody 50000000
-	# math.Sqrt needs to be in assembly; inlining is probably the other 50%
-	gcc -O2 nbody.c	21.26u 0.01s 21.28r
-	gccgo -O2 nbody.go	116.68u 0.07s 116.80r
-	gc nbody	86.64u 0.01s 86.68r	# -14%
-	gc_B nbody	85.72u 0.02s 85.77r	# *** -17%
-
-binary-tree 15 # too slow to use 20
-	# memory allocation and garbage collection
-	gcc -O2 binary-tree.c -lm	0.87u 0.00s 0.87r
-	gccgo -O2 binary-tree.go	1.61u 0.47s 2.09r
-	gccgo -O2 binary-tree-freelist.go	0.00u 0.00s 0.01r
-	gc binary-tree	9.11u 0.01s 9.13r	# *** -5%
-	gc binary-tree-freelist	0.47u 0.01s 0.48r
-
-fannkuch 12
-	# bounds checking is half the difference
-	# rest might be registerization
-	gcc -O2 fannkuch.c	59.92u 0.00s 59.94r
-	gccgo -O2 fannkuch.go	65.54u 0.00s 65.58r
-	gc fannkuch	123.98u 0.01s 124.04r
-	gc_B fannkuch	90.75u 0.00s 90.78r
-
-regex-dna 100000
-	# regexp code is slow on trivial regexp
-	gcc -O2 regex-dna.c -lpcre	0.91u 0.00s 0.92r
-	gc regex-dna	27.25u 0.02s 27.28r
-	gc_B regex-dna	29.51u 0.03s 29.55r
-
-spectral-norm 5500
-	# possibly inline evalA
-	gcc -O2 spectral-norm.c -lm	11.57u 0.00s 11.57r
-	gccgo -O2 spectral-norm.go	12.07u 0.01s 12.08r
-	gc spectral-norm	23.99u 0.00s 24.00r
-	gc_B spectral-norm	23.73u 0.00s 23.75r
-
-k-nucleotide 1000000
-	# string maps are slower than glib string maps
-	gcc -O2 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include k-nucleotide.c -lglib-2.0	10.63u 0.02s 10.69r
-	gccgo -O2 k-nucleotide.go	23.19u 0.91s 24.12r
-	gc k-nucleotide	16.73u 0.04s 16.78r	# *** +5% (but this one seems to vary by more than that)
-	gc_B k-nucleotide	16.46u 0.04s 16.51r	# *** +5%
-
-mandelbrot 16000
-	gcc -O2 mandelbrot.c	56.16u 0.00s 56.16r
-	gccgo -O2 mandelbrot.go	57.41u 0.01s 57.42r
-	gc mandelbrot	64.05u 0.02s 64.08r	# *** -14%
-	gc_B mandelbrot	64.10u 0.02s 64.14r	# *** -14%
-
-meteor 2100
-	# we don't know
-	gcc -O2 meteor-contest.c	0.10u 0.00s 0.10r
-	gccgo -O2 meteor-contest.go	0.12u 0.00s 0.12r
-	gc meteor-contest	0.18u 0.00s 0.20r	# *** -25%
-	gc_B meteor-contest	0.17u 0.00s 0.18r	# *** -24%
-
-pidigits 10000
-	# bignum is slower than gmp
-	gcc -O2 pidigits.c -lgmp	2.57u 0.00s 2.57r
-	gc pidigits	71.82u 0.04s 71.89r
-	gc_B pidigits	71.84u 0.08s 71.98r
-
-threadring 50000000
-	gcc -O2 threadring.c -lpthread	30.91u 164.33s 204.57r
-	gccgo -O2 threadring.go	87.12u 460.04s 447.61r
-	gc threadring	38.55u 0.00s 38.56r	# *** +16%
-
-chameneos 6000000
-	gcc -O2 chameneosredux.c -lpthread	17.93u 323.65s 88.47r
-	gc chameneosredux	21.72u 0.00s 21.73r
-
-August 10 2009
-
-# In-place versions for some bignum operations.
-pidigits 10000
-	gcc -O2 pidigits.c -lgmp	2.56u 0.00s 2.57r
-	gc pidigits	55.22u 0.04s 55.29r	# *** -23%
-	gc_B pidigits	55.49u 0.02s 55.60r	# *** -23%
-
-September 3 2009
-
-# New 6g inlines slices, has a few other tweaks.
-# Complete rerun. Significant changes marked.
-
-fasta -n 25000000
-	# probably I/O library inefficiencies
-	gcc -O2 fasta.c	5.96u 0.00s 5.96r
-	gc fasta	10.63u 0.02s 10.66r
-	gc_B fasta	9.92u 0.01s 9.94r
-
-reverse-complement < output-of-fasta-25000000
-	# we don't know - memory cache behavior?
-	gcc -O2 reverse-complement.c	1.92u 0.33s 2.93r
-	gccgo -O2 reverse-complement.go	6.76u 0.72s 7.58r	# +5%
-	gc reverse-complement	6.59u 0.70s 7.29r	# +2%
-	gc_B reverse-complement	5.57u 0.80s 6.37r	# -10%
-
-nbody 50000000
-	# math.Sqrt needs to be in assembly; inlining is probably the other 50%
-	# also loop alignment appears to be critical
-	gcc -O2 nbody.c	21.28u 0.00s 21.28r
-	gccgo -O2 nbody.go	119.21u 0.00s 119.22r	# +2%
-	gc nbody	109.72u 0.00s 109.78r	# + 28% *****
-	gc_B nbody	85.90u 0.00s 85.91r
-
-binary-tree 15 # too slow to use 20
-	# memory allocation and garbage collection
-	gcc -O2 binary-tree.c -lm	0.86u 0.00s 0.87r
-	gccgo -O2 binary-tree.go	1.88u 0.54s 2.42r	# +17%
-	gccgo -O2 binary-tree-freelist.go	0.01u 0.01s 0.02r
-	gc binary-tree	8.94u 0.01s 8.96r	# -2%
-	gc binary-tree-freelist	0.47u 0.01s 0.48r
-
-fannkuch 12
-	# bounds checking is half the difference
-	# rest might be registerization
-	gcc -O2 fannkuch.c	60.12u 0.00s 60.12r
-	gccgo -O2 fannkuch.go	92.62u 0.00s 92.66r		# +41% ***
-	gc fannkuch	123.90u 0.00s 123.92r
-	gc_B fannkuch	89.71u 0.00s 89.74r	# -1%
-
-regex-dna 100000
-	# regexp code is slow on trivial regexp
-	gcc -O2 regex-dna.c -lpcre	0.88u 0.00s 0.88r
-	gc regex-dna	25.77u 0.01s 25.79r		# -5%
-	gc_B regex-dna	26.05u 0.02s 26.09r	# -12% ***
-
-spectral-norm 5500
-	# possibly inline evalA
-	gcc -O2 spectral-norm.c -lm	11.51u 0.00s 11.51r
-	gccgo -O2 spectral-norm.go	11.95u 0.00s 11.96r
-	gc spectral-norm	24.23u 0.00s 24.23r
-	gc_B spectral-norm	23.83u 0.00s 23.84r
-
-k-nucleotide 1000000
-	# string maps are slower than glib string maps
-	gcc -O2 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include k-nucleotide.c -lglib-2.0	10.68u 0.04s 10.72r
-	gccgo -O2 k-nucleotide.go	23.03u 0.88s 23.92r
-	gc k-nucleotide	15.79u 0.05s 15.85r	# -5% (but this one seems to vary by more than that)
-	gc_B k-nucleotide	17.88u 0.05s 17.95r # +8% (ditto)
-
-mandelbrot 16000
-	gcc -O2 mandelbrot.c	56.17u 0.02s 56.20r
-	gccgo -O2 mandelbrot.go	56.74u 0.02s 56.79r	 # -1%
-	gc mandelbrot	63.31u 0.01s 63.35r	# -1%
-	gc_B mandelbrot	63.29u 0.00s 63.31r	# -1%
-
-meteor 2100
-	# we don't know
-	gcc -O2 meteor-contest.c	0.10u 0.00s 0.10r
-	gccgo -O2 meteor-contest.go	0.11u 0.00s 0.12r
-	gc meteor-contest	0.18u 0.00s 0.19r
-	gc_B meteor-contest	0.17u 0.00s 0.18r
-
-pidigits 10000
-	# bignum is slower than gmp
-	gcc -O2 pidigits.c -lgmp	2.56u 0.00s 2.57r
-	gc pidigits	55.87u 0.03s 55.91r
-	gc_B pidigits	55.93u 0.03s 55.99r
-
-# these tests are compared using real time, since they run multiple processors
-# accuracy probably low
-threadring 50000000
-	gcc -O2 threadring.c -lpthread	26.31u 164.69s 199.92r	# -2%
-	gccgo -O2 threadring.go	87.90u 487.26s 472.81r	# +6%
-	gc threadring	28.89u 0.00s 28.90r	# -25% ***
-
-chameneos 6000000
-	gcc -O2 chameneosredux.c -lpthread	16.41u 296.91s 81.17r	# -8%
-	gc chameneosredux	19.97u 0.00s 19.97r	# -8%
-
-Sep 22, 2009
-
-# 6g inlines sliceslice in most cases.
-
-fasta -n 25000000
-	# probably I/O library inefficiencies
-	gc fasta	10.24u 0.00s 10.25r	# -4%
-	gc_B fasta	9.68u 0.01s 9.69r	# -3%
-
-reverse-complement < output-of-fasta-25000000
-	# we don't know - memory cache behavior?
-	gc reverse-complement	6.67u 0.69s 7.37r	# +1%
-	gc_B reverse-complement	6.00u 0.64s 6.65r	# +7%
-
-nbody -n 50000000
-	# math.Sqrt needs to be in assembly; inlining is probably the other 50%
-	# also loop alignment appears to be critical
-	gc nbody	86.27u 0.00s 86.29r	# -21%
-	gc_B nbody	104.52u 0.00s 104.54r	# +22%
-
-fannkuch 12
-	# bounds checking is half the difference
-	# rest might be registerization
-	gc fannkuch	128.36u 0.00s 128.37r	# +4%
-	gc_B fannkuch	89.32u 0.00s 89.34r
-
-regex-dna 100000
-	# regexp code is slow on trivial regexp
-	gc regex-dna	24.82u 0.01s 24.86r	# -4%
-	gc_B regex-dna	24.55u 0.01s 24.57r	# -6%
-
-spectral-norm 5500
-	# possibly inline evalA
-	gc spectral-norm	24.05u 0.00s 24.07r	# -1%
-	gc_B spectral-norm	23.60u 0.00s 23.65r	 # -1%
-
-k-nucleotide 1000000
-	# string maps are slower than glib string maps
-	gc k-nucleotide	17.84u 0.04s 17.89r	# +13% but mysterious variation continues
-	gc_B k-nucleotide	15.56u 0.08s 15.65r	# -13% (ditto)
-
-mandelbrot 16000
-	gc mandelbrot	64.08u 0.01s 64.11r	# +1%
-	gc_B mandelbrot	64.04u 0.00s 64.05r	# +1%
-
-pidigits 10000
-	# bignum is slower than gmp
-	gc pidigits	58.68u 0.02s 58.72r	# +5%
-	gc_B pidigits	58.86u 0.05s 58.99r	# +5%
-
-# these tests are compared using real time, since they run multiple processors
-# accuracy probably low
-threadring 50000000
-	gc threadring	32.70u 0.02s 32.77r	# +13%
-
-chameneos 6000000
-	gc chameneosredux	26.62u 0.00s 26.63r	# +13%
-
-Sep 24, 2009
-
-# Sqrt now in assembler for 6g.
-nbody -n 50000000
-	# remember, at least for 6g, alignment of loops may be important
-	gcc -O2 nbody.c	21.24u 0.00s 21.25r
-	gccgo -O2 nbody.go	121.03u 0.00s 121.04r
-	gc nbody	30.26u 0.00s 30.27r	# -65% ***
-	gc_B nbody	30.20u 0.02s 30.22r	# -72% *** 
-
-Nov 13 2009
-
-# fix bug in regexp; take performance hit.  good regexps will come in time.
-regex-dna 100000
-	gcc -O2 regex-dna.c -lpcre	0.92u 0.00s 0.94r
-	gc regex-dna	29.78u 0.03s 29.83r
-	gc_B regex-dna	32.63u 0.03s 32.74r
-
-Nov 24 2009
-
-# Roger Peppe's rewrite of the benchmark
-chameneos 6000000
-	gcc -O2 chameneosredux.c -lpthread	18.00u 303.29s 83.64r
-	gc chameneosredux	12.10u 0.00s 12.10r  # 2.22X faster
-
-Jan 6, 2010
-
-# Long-overdue update.  All numbers included in this complete run.
-# Some programs (e.g. reverse-complement) rewritten for speed.
-# Regular expressions much faster in common cases (although still far behind PCRE)
-# Bignum stuff improved
-# Better (but sometimes slower) locking in channels.
-
-fasta -n 25000000
-	gcc -O2 fasta.c	5.99u 0.01s 6.00r
-	gc fasta	9.11u 0.00s 9.12r	# -11%
-	gc_B fasta	8.60u 0.00s 8.62r	# +12% ??
-
-reverse-complement < output-of-fasta-25000000
-	gcc -O2 reverse-complement.c	2.00u 0.80s 9.54r
-#	gccgo -O2 reverse-complement.go	4.57u 0.35s 4.94r	# 33% faster
-	gc reverse-complement	2.01u 0.38s 2.40r	# 3.3X faster
-	gc_B reverse-complement	1.88u 0.36s 2.24r	# 3.2X faster
-GOGC=off
-	gc reverse-complement	2.01u 0.35s 2.37r
-	gc_B reverse-complement	1.86u 0.32s 2.19r
-
-nbody -n 50000000
-	gcc -O2 nbody.c	21.28u 0.00s 21.31r
-	gccgo -O2 nbody.go	80.02u 0.00s 80.05r	# 33% faster
-	gc nbody	30.13u 0.00s 30.13r
-	gc_B nbody	29.89u 0.01s 29.91r
-
-binary-tree 15 # too slow to use 20
-	gcc -O2 binary-tree.c -lm	0.86u 0.00s 0.87r
-	gccgo -O2 binary-tree.go	4.82u 0.41s 5.24r	# 2.5X slower
-	gc binary-tree	7.23u 0.01s 7.25r	# # -19%
-	gc binary-tree-freelist	0.43u 0.00s 0.44r	# -9%
-
-fannkuch 12
-	gcc -O2 fannkuch.c	60.17u 0.00s 60.17r
-	gccgo -O2 fannkuch.go	78.47u 0.01s 78.49r
-	gc fannkuch	128.86u 0.00s 128.96r
-	gc_B fannkuch	90.17u 0.00s 90.21r
-
-regex-dna 100000
-	gcc -O2 regex-dna.c -lpcre	0.90u 0.00s 0.92r
-	gc regex-dna	9.48u 0.01s 9.50r	# 3.1X faster
-	gc_B regex-dna	9.08u 0.00s 9.10r	# 3.6X faster
-
-spectral-norm 5500
-	gcc -O2 spectral-norm.c -lm	11.48u 0.00s 11.48r
-	gccgo -O2 spectral-norm.go	11.68u 0.00s 11.70r
-	gc spectral-norm	23.98u 0.00s 23.99r
-	gc_B spectral-norm	23.68u 0.00s 23.69r
-
-k-nucleotide 1000000
-	gcc -O2 k-nucleotide.c	10.85u 0.04s 10.90r
-	gccgo -O2 k-nucleotide.go	25.26u 0.87s 26.14r
-	gc k-nucleotide	15.28u 0.06s 15.37r	# restored; mysterious variation continues
-	gc_B k-nucleotide	15.97u 0.03s 16.00r
-
-mandelbrot 16000
-	gcc -O2 mandelbrot.c	56.12u 0.01s 56.15r
-	gccgo -O2 mandelbrot.go	56.86u 0.01s 56.89r
-	gc mandelbrot	66.05u 0.00s 66.07r	# -3%
-	gc_B mandelbrot	66.06u 0.00s 66.07r	# -3%
-
-meteor 2100
-	gcc -O2 meteor-contest.c	0.10u 0.00s 0.10r
-	gccgo -O2 meteor-contest.go	0.12u 0.00s 0.12r
-	gc meteor-contest	0.17u 0.00s 0.17r
-	gc_B meteor-contest	0.15u 0.00s 0.16r
-
-pidigits 10000
-	gcc -O2 pidigits.c -lgmp	2.57u 0.00s 2.59r
-	gc pidigits	38.27u 0.02s 38.30r	# 1.5X faster
-	gc_B pidigits	38.27u 0.02s 38.31r	# 1.5X faster
-
-threadring 50000000
-	gcc -O2 threadring.c	37.11u 170.59s 212.75r
-	gccgo -O2 threadring.go	89.67u 447.56s 442.55r	# -6.5%
-	gc threadring	36.08u 0.04s 36.15r	# +10%
-
-chameneos 6000000
-	gcc -O2 chameneosredux.c -lpthread	19.02u 331.08s 90.79r
-	gc chameneosredux	12.54u 0.00s 12.55r
-
-Oct 19, 2010
-
-# Another long-overdue update. Some of the code is new; parallel versions
-# of some are added.  A few significant improvements.
-
-fasta -n 25000000
-	gcc -O2 fasta.c	4.92u 0.00s 4.93r
-	gccgo -O2 fasta.go	3.31u 0.00s 3.34r  # new code
-	gc fasta	3.68u 0.00s 3.69r  # 2.5X faster with no code
-	gc_B fasta	3.68u 0.00s 3.69r  # 2.3X faster with no code
-
-reverse-complement < output-of-fasta-25000000
-	gcc -O2 reverse-complement.c	1.93u 0.81s 11.24r
-	gccgo -O2 reverse-complement.go	1.58u 0.43s 2.04r  # first run with new code?
-	gc reverse-complement	1.84u 0.34s 2.20r  # 10% faster
-	gc_B reverse-complement	1.85u 0.32s 2.18r
-
-nbody -n 50000000
-	gcc -O2 nbody.c	21.35u 0.00s 21.36r
-	gccgo -O2 nbody.go	21.62u 0.00s 21.66r  # 3.7X faster - why??
-	gc nbody	29.78u 0.00s 29.79r
-	gc_B nbody	29.72u 0.00s 29.72r
-
-binary-tree 15 # too slow to use 20
-	gcc -O2 binary-tree.c -lm	0.86u 0.00s 0.88r
-	gccgo -O2 binary-tree.go	4.05u 0.02s 4.08r  # 28% faster
-	gccgo -O2 binary-tree-freelist	0.34u 0.08s 0.34r
-	gc binary-tree	5.94u 0.00s 5.95r  # 20% faster
-	gc binary-tree-freelist	0.50u 0.01s 0.54r
-
-fannkuch 12
-	gcc -O2 fannkuch.c	60.45u 0.00s 60.45r
-	gccgo -O2 fannkuch.go	64.64u 0.00s 64.64r
-	gccgo -O2 fannkuch-parallel.go	115.63u 0.00s 31.58r
-	gc fannkuch	126.52u 0.04s 126.68r
-	gc fannkuch-parallel	238.82u 0.10s 65.93r  # GOMAXPROCS=4
-	gc_B fannkuch	88.99u 0.00s 89.02r
-
-regex-dna 100000
-	gcc -O2 regex-dna.c -lpcre	0.89u 0.00s 0.89r
-	gc regex-dna	8.99u 0.02s 9.03r
-	gc regex-dna-parallel	8.94u 0.02s 3.68r  # GOMAXPROCS=4
-	gc_B regex-dna	9.12u 0.00s 9.14r
-
-spectral-norm 5500
-	gcc -O2 spectral-norm.c -lm	11.55u 0.00s 11.57r
-	gccgo -O2 spectral-norm.go	11.73u 0.00s 11.75r
-	gc spectral-norm	23.74u 0.00s 23.79r
-	gc_B spectral-norm	24.49u 0.02s 24.54r
-
-k-nucleotide 1000000
-	gcc -O2 k-nucleotide.c	11.44u 0.06s 11.50r
-	gccgo -O2 k-nucleotide.go	8.65u 0.04s 8.71r
-	gccgo -O2 k-nucleotide-parallel.go	8.75u 0.03s 2.97r # set GOMAXPROCS=4
-	gc k-nucleotide	14.92u 0.05s 15.01r
-	gc k-nucleotide-parallel	16.96u 0.06s 6.53r  # set GOMAXPROCS=4
-	gc_B k-nucleotide	15.97u 0.03s 16.08r
-
-mandelbrot 16000
-	gcc -O2 mandelbrot.c	56.32u 0.00s 56.35r
-	gccgo -O2 mandelbrot.go	55.62u 0.02s 55.77r
-	gc mandelbrot	64.85u 0.01s 64.94r
-	gc_B mandelbrot	65.02u 0.01s 65.14r
-
-meteor 2100
-	gcc -O2 meteor-contest.c	0.10u 0.00s 0.10r
-	gccgo -O2 meteor-contest.go	0.10u 0.00s 0.11r
-	gc meteor-contest	0.17u 0.00s 0.18r
-	gc_B meteor-contest	0.16u 0.00s 0.16r
-
-pidigits 10000
-	gcc -O2 pidigits.c -lgmp	2.58u 0.00s 2.59r
-	gccgo -O2 pidigits.go	14.06u 0.01s 14.09r # first run?
-	gc pidigits	8.47u 0.05s 8.55r # 4.5X faster due to package big
-	gc_B pidigits	8.33u 0.01s 8.36r # 4.5X faster due to package big
-
-threadring 50000000
-	gcc -O2 threadring.c	28.18u 153.19s 186.47r
-	gccgo -O2 threadring.go	110.10u 516.48s 515.25r
-	gc threadring	40.39u 0.00s 40.40r
-
-chameneos 6000000
-	gcc -O2 chameneosredux.c -lpthread	18.20u 301.55s 83.10r
-	gccgo -O2 chameneosredux.go	52.22u 324.54s 201.21r
-	gc chameneosredux	13.52u 0.00s 13.54r
-
-Dec 14, 2010
-
-# Improved regex code (same algorithm) gets ~30%.
-
-regex-dna 100000
-	gcc -O2 regex-dna.c -lpcre	0.77u 0.01s 0.78r
-	gc regex-dna	6.80u 0.00s 6.81r
-	gc regex-dna-parallel	6.82u 0.01s 2.75r
-	gc_B regex-dna	6.69u 0.02s 6.70r
-
-Feb 15, 2011
-
-# Improved GC, still single-threaded but more efficient
-
-fasta -n 25000000
-	gcc -O2 fasta.c	3.40u 0.00s 3.40r
-	gccgo -O2 fasta.go	3.51u 0.00s 3.50r
-	gc fasta	3.66u 0.01s 3.66r
-	gc_B fasta	3.66u 0.00s 3.66r
-
-reverse-complement < output-of-fasta-25000000
-	gcc -O2 reverse-complement.c	1.86u 1.29s 4.93r
-	gccgo -O2 reverse-complement.go	2.18u 0.41s 2.60r
-	gc reverse-complement	1.67u 0.48s 2.15r
-	gc_B reverse-complement	1.71u 0.45s 2.15r
-
-nbody -n 50000000
-	gcc -O2 -lm nbody.c	21.64u 0.00s 21.64r
-	gccgo -O2 nbody.go	21.46u 0.00s 21.45r
-	gc nbody	29.07u 0.00s 29.06r
-	gc_B nbody	31.61u 0.00s 31.61r
-
-binary-tree 15 # too slow to use 20
-	gcc -O2 binary-tree.c -lm	0.88u 0.00s 0.87r
-	gccgo -O2 binary-tree.go	2.74u 0.07s 2.81r
-	gccgo -O2 binary-tree-freelist.go	0.01u 0.00s 0.00r
-	gc binary-tree	4.22u 0.02s 4.24r
-	gc binary-tree-freelist	0.54u 0.02s 0.55r
-
-fannkuch 12
-	gcc -O2 fannkuch.c	57.64u 0.00s 57.64r
-	gccgo -O2 fannkuch.go	65.79u 0.00s 65.82r
-	gccgo -O2 fannkuch-parallel.go	160.91u 0.02s 43.90r
-	gc fannkuch	126.36u 0.03s 126.53r
-	gc fannkuch-parallel	175.23u 0.04s 45.49r
-	gc_B fannkuch	89.23u 0.00s 89.24r
-
-regex-dna 100000
-	gcc -O2 regex-dna.c -lpcre	0.77u 0.01s 0.80r
-	gccgo -O2 regex-dna.go	12.38u 0.10s 12.52r
-	gccgo -O2 regex-dna-parallel.go	43.96u 4.64s 15.11r
-	gc regex-dna	7.03u 0.01s 7.05r
-	gc regex-dna-parallel	6.85u 0.05s 2.70r
-	gc_B regex-dna	6.87u 0.02s 6.89r
-
-spectral-norm 5500
-	gcc -O2 spectral-norm.c -lm	12.29u 0.00s 12.28r
-	gccgo -O2 spectral-norm.go	11.79u 0.00s 11.79r
-	gc spectral-norm	24.00u 0.02s 24.05r
-	gc_B spectral-norm	24.59u 0.01s 24.59r
-
-k-nucleotide 1000000
-	gcc -O2 k-nucleotide.c	9.75u 0.07s 9.82r
-	gccgo -O2 k-nucleotide.go	8.92u 0.06s 8.98r
-	gccgo -O2 k-nucleotide-parallel.go	8.40u 0.04s 2.76r
-	gc k-nucleotide	17.01u 0.03s 17.04r
-	gc k-nucleotide-parallel	16.51u 0.08s 6.21r
-	gc_B k-nucleotide	16.94u 0.08s 17.02r
-
-mandelbrot 16000
-	gcc -O2 mandelbrot.c	54.60u 0.00s 54.66r
-	gccgo -O2 mandelbrot.go	59.38u 0.00s 59.41r
-	gc mandelbrot	64.93u 0.04s 65.08r
-	gc_B mandelbrot	64.85u 0.03s 64.92r
-
-meteor 2098
-	gcc -O2 meteor-contest.c	0.10u 0.01s 0.10r
-	gccgo -O2 meteor-contest.go	0.11u 0.00s 0.11r
-	gc meteor-contest	0.18u 0.00s 0.17r
-	gc_B meteor-contest	0.17u 0.00s 0.16r
-
-pidigits 10000
-	gcc -O2 pidigits.c -lgmp	2.24u 0.00s 2.23r
-	gccgo -O2 pidigits.go	14.05u 0.00s 14.06r
-	gc pidigits	6.34u 0.05s 6.38r
-	gc_B pidigits	6.37u 0.02s 6.38r
-
-threadring 50000000
-	gcc -O2 threadring.c	30.50u 258.05s 325.72r
-	gccgo -O2 threadring.go	92.87u 748.39s 728.46r
-	gc threadring	38.03u 0.01s 38.04r
-
-# Apr 15, 2011
-# Move to new machine, Intel Xeon E5520 at 2.27GHz.
-# (Was Opteron(tm) Processor 8214 HE)
-
-fasta -n 25000000
-OLD:
-	gcc -O2 fasta.c	3.39u 0.04s 3.42r
-	gccgo -O2 fasta.go	3.52u 0.00s 3.52r
-	gc fasta	3.63u 0.04s 3.67r
-	gc_B fasta	3.66u 0.00s 3.66r
-NEW:
-	gcc -O2 fasta.c	1.45u 0.02s 1.47r
-	gccgo -O2 fasta.go	1.51u 0.01s 1.51r
-	gc fasta	2.04u 0.00s 2.04r
-	gc_B fasta	2.05u 0.00s 2.04r
-
-reverse-complement < output-of-fasta-25000000
-OLD:
-	gcc -O2 reverse-complement.c	1.87u 1.51s 7.02r
-	gccgo -O2 reverse-complement.go	1.56u 0.54s 3.37r
-	gc reverse-complement	1.73u 0.36s 2.08r
-	gc_B reverse-complement	1.75u 0.37s 2.12r
-NEW:
-	gcc -O2 reverse-complement.c	1.20u 0.47s 12.96r
-	gccgo -O2 reverse-complement.go	0.88u 0.14s 1.01r
-	gc reverse-complement	1.13u 0.17s 1.30r
-	gc_B reverse-complement	1.11u 0.09s 1.20r
-
-nbody -n 50000000
-OLD:
-	gcc -O2 -lm nbody.c	21.90u 0.00s 21.92r
-	gccgo -O2 nbody.go	23.12u 0.03s 23.19r
-	gc nbody	29.07u 0.00s 29.07r
-	gc_B nbody	31.84u 0.00s 31.85r
-NEW:
-	gcc -O2 -lm nbody.c	13.01u 0.00s 13.03r
-	gccgo -O2 nbody.go	13.35u 0.00s 13.37r
-	gc nbody	21.78u 0.00s 21.82r
-	gc_B nbody	21.72u 0.00s 21.76r
-
-binary-tree 15 # too slow to use 20
-OLD:
-	gcc -O2 binary-tree.c -lm	0.83u 0.02s 0.84r
-	gccgo -O2 binary-tree.go	2.61u 0.02s 2.62r
-	gccgo -O2 binary-tree-freelist.go	0.32u 0.01s 0.32r
-	gc binary-tree	3.93u 0.04s 3.97r
-	gc binary-tree-freelist	0.47u 0.03s 0.50r
-NEW:
-	gcc -O2 binary-tree.c -lm	0.60u 0.00s 0.59r
-	gccgo -O2 binary-tree.go	1.53u 0.00s 1.52r
-	gccgo -O2 binary-tree-freelist.go	0.01u 0.00s 0.00r
-	gc binary-tree	1.93u 0.02s 1.95r
-	gc binary-tree-freelist	0.32u 0.01s 0.32r
-
-fannkuch 12
-OLD:
-	gcc -O2 fannkuch.c	57.64u 0.00s 57.64r
-	gccgo -O2 fannkuch.go	65.56u 0.01s 65.65r
-	gccgo -O2 fannkuch-parallel.go	179.12u 0.00s 49.82r
-	gc fannkuch	126.39u 0.00s 126.39r
-	gc fannkuch-parallel	172.49u 0.02s 45.44r
-	gc_B fannkuch	89.30u 0.00s 89.28r
-NEW:
-	gcc -O2 fannkuch.c	45.17u 0.00s 45.26r
-	gccgo -O2 fannkuch.go	53.63u 0.00s 53.73r
-	gccgo -O2 fannkuch-parallel.go	216.72u 0.00s 58.42r
-	gc fannkuch	108.21u 0.00s 108.44r
-	gc fannkuch-parallel	227.20u 0.00s 57.27r
-	gc_B fannkuch	56.14u 0.00s 56.26r
-
-regex-dna 100000
-OLD:
-	gcc -O2 regex-dna.c -lpcre	0.77u 0.01s 0.78r
-	gccgo -O2 regex-dna.go	10.15u 0.02s 10.23r
-	gccgo -O2 regex-dna-parallel.go	33.81u 3.22s 11.62r
-	gc regex-dna	6.52u 0.04s 6.56r
-	gc regex-dna-parallel	6.84u 0.03s 2.70r
-	gc_B regex-dna	6.83u 0.01s 6.84r
-NEW:
-	gcc -O2 regex-dna.c -lpcre	0.47u 0.00s 0.47r
-	gccgo -O2 regex-dna.go	6.00u 0.00s 6.00r
-	gccgo -O2 regex-dna-parallel.go	44.54u 1.57s 6.51r
-	gc regex-dna	5.41u 0.01s 5.42r
-	gc regex-dna-parallel	5.62u 0.01s 2.20r
-	gc_B regex-dna	5.50u 0.00s 5.50r
-
-spectral-norm 5500
-OLD:
-	gcc -O2 spectral-norm.c -lm	12.29u 0.00s 12.28r
-	gccgo -O2 spectral-norm.go	11.56u 0.00s 11.55r
-	gc spectral-norm	23.98u 0.00s 24.00r
-	gc_B spectral-norm	24.62u 0.00s 24.65r
-NEW:
-	gcc -O2 spectral-norm.c -lm	15.79u 0.00s 15.82r
-	gccgo -O2 spectral-norm.go	15.32u 0.00s 15.35r
-	gc spectral-norm	19.62u 0.01s 19.67r
-	gc_B spectral-norm	19.62u 0.00s 19.66r
-
-k-nucleotide 1000000
-OLD:
-	gcc -O2 k-nucleotide.c	9.82u 0.06s 9.87r
-	gccgo -O2 k-nucleotide.go	8.30u 0.02s 8.32r
-	gccgo -O2 k-nucleotide-parallel.go	8.84u 0.05s 3.02r
-	gc k-nucleotide	15.38u 0.07s 15.44r
-	gc k-nucleotide-parallel	16.40u 0.03s 5.93r
-	gc_B k-nucleotide	15.19u 0.05s 15.23r
-NEW:
-	gcc -O2 -k-nucleotide.c	4.88u 0.03s 4.92r
-	gccgo -O2 k-nucleotide.go	5.94u 0.01s 5.96r
-	gccgo -O2 k-nucleotide-parallel.go	6.44u 0.03s 1.47r
-	gc k-nucleotide	9.61u 0.01s 9.63r
-	gc k-nucleotide-parallel	9.70u 0.00s 3.39r
-	gc_B k-nucleotide	9.19u 0.03s 9.23r
-
-mandelbrot 16000
-OLD:
-	gcc -O2 mandelbrot.c	54.54u 0.00s 54.56r
-	gccgo -O2 mandelbrot.go	59.63u 0.03s 59.67r
-	gc mandelbrot	64.82u 0.00s 64.83r
-	gc_B mandelbrot	64.84u 0.00s 64.91r
-NEW:
-	gcc -O2 mandelbrot.c	36.07u 0.01s 36.15r
-	gccgo -O2 mandelbrot.go	43.57u 0.00s 43.66r
-	gc mandelbrot	60.66u 0.00s 60.79r
-	gc_B mandelbrot	60.90u 0.00s 61.03r
-
-meteor 2098
-OLD:
-	gcc -O2 meteor-contest.c	0.11u 0.00s 0.10r
-	gccgo -O2 meteor-contest.go	0.10u 0.01s 0.10r
-	gc meteor-contest	0.18u 0.00s 0.17r
-	gc_B meteor-contest	0.17u 0.00s 0.16r
-NEW:
-	gcc -O2 meteor-contest.c	0.10u 0.00s 0.09r
-	gccgo -O2 meteor-contest.go	0.10u 0.00s 0.09r
-	gc meteor-contest	0.14u 0.00s 0.14r
-	gc_B meteor-contest	0.13u 0.00s 0.13r
-
-pidigits 10000
-OLD:
-	gcc -O2 pidigits.c -lgmp	2.22u 0.00s 2.21r
-	gccgo -O2 pidigits.go	13.39u 0.00s 13.40r
-	gc pidigits	6.42u 0.04s 6.45r
-	gc_B pidigits	6.45u 0.02s 6.47r
-NEW:
-	gcc -O2 pidigits.c -lgmp	2.27u 0.00s 2.29r
-	gccgo -O2 pidigits.go	9.21u 0.00s 9.22r
-	gc pidigits	3.60u 0.00s 3.60r
-	gc_B pidigits	3.56u 0.02s 3.58r
-
-threadring 50000000
-OLD:
-	gcc -O2 threadring.c -lpthread	34.51u 267.95s 336.12r
-	gccgo -O2 threadring.go	103.51u 588.57s 627.16r
-	gc threadring	54.68u 0.00s 54.73r
-NEW:
-	gcc -O2 threadring.c 32.00u 259.39s 369.74r
-	gccgo -O2 threadring.go	133.06u 546.02s 595.33r
-	gc threadring	16.75u 0.02s 16.80r
-
-chameneos 6000000
-OLD:
-	gcc -O2 chameneosredux.c -lpthread	12.65u 31.02s 13.33r
-	gccgo -O2 chameneosredux.go	47.04u 302.84s 252.29r
-	gc chameneosredux	14.14u 0.00s 14.14r
-NEW:
-	gcc -O2 chameneosredux.c -lpthread	8.05u 63.43s 11.16r
-	gccgo -O2 chameneosredux.go	82.95u 304.37s 207.64r
-	gc chameneosredux	9.42u 0.00s 9.43r
-
-# May 13, 2011
-# after gc update to inline append when possible - 35% faster
-
-regex-dna 100000
-	gc regex-dna	3.94u 0.00s 3.95r
-	gc regex-dna-parallel	4.15u 0.01s 1.63r
-	gc_B regex-dna	4.01u 0.01s 4.02r
-
-# Aug 4, 2011
-# After various updates to locking code and some runtime changes.
-# Slowdowns believed due to slower (but more correct) memmove.
-
-fannkuch 12
-	gccgo -O2 fannkuch.go	51.59u 0.00s 51.69r # -4%
-	gccgo -O2 fannkuch-parallel.go	253.17u 0.00s 64.67r # -11%
-	gc fannkuch	103.14u 0.00s 103.36r # -5%
-	gc fannkuch-parallel	189.63u 0.00s 49.37r # +9%
-	gc_B fannkuch	49.19u 0.00s 49.29r # -14%
-
-regex-dna 100000
-	gc regex-dna	3.78u 0.00s 3.78r # -43%
-	gc regex-dna-parallel	3.84u 0.02s 1.48r # -49%
-	gc_B regex-dna	3.62u 0.00s 3.63r # -52%
-
-k-nucleotide 1000000
-	gc k-nucleotide	12.23u 0.02s 12.27r # +27%
-	gc k-nucleotide-parallel	12.76u 0.02s 4.37r # +29%
-	gc_B k-nucleotide	12.18u 0.01s 12.21r # +33%
-
-threadring 50000000
-	gc threadring	17.49u 0.00s 17.53r # +4%
-
-chameneos 6000000
-	gc chameneosredux	7.61u 0.00s 7.63r # -24%
-
-Aug 9, 2011
-# After custom algorithms for 1- 2- 4- 8-byte scalars.
-
-fannkuch 12
-	gc fannkuch-parallel	157.17u 0.00s 41.08r # -17%
-
-k-nucleotide 1000000
-	gc k-nucleotide	8.72u 0.03s 8.76r # -39%
-	gc k-nucleotide-parallel	8.79u 0.01s 3.14r # -39%
-	gc_B k-nucleotide	8.65u 0.03s 8.69r # -39%
-
-pidigits 10000
-	gc pidigits	3.71u 0.02s 3.73r # +4%
-	gc_B pidigits	3.73u 0.00s 3.73r # +4%
-
-threadring 50000000
-	gc threadring	14.51u 0.00s 14.54r # -17%
-
-chameneos 6000000
-	gc chameneosredux	7.41u 0.00s 7.42r # -3%
-
-# A complete run at the Go 1 release.
-# Significant changes:
-# - gccgo is now enabled for all tests (goroutines are cheap enough)
-# - threadring and chameneos are 14% faster, probably due to runtime changes
-# - regex-dna 36% faster
-# - fannkuch-parallel (only) slowed down 40%
-# - gccgo on binary-tree-freelist is still optimized to nothing
-# Other changes are modest.
-
-fasta -n 25000000
-	gcc -O2 fasta.c	1.45u 0.02s 1.48r
-	gccgo -O2 fasta.go	1.46u 0.00s 1.47r
-	gc fasta	1.99u 0.01s 2.00r
-	gc_B fasta	1.99u 0.01s 2.01r
-
-reverse-complement < output-of-fasta-25000000
-	gcc -O2 reverse-complement.c	0.95u 0.48s 4.99r
-	gccgo -O2 reverse-complement.go	0.93u 0.16s 1.09r
-	gc reverse-complement	1.20u 0.19s 1.39r
-	gc_B reverse-complement	1.04u 0.16s 1.20r
-
-nbody -n 50000000
-	gcc -O2 -lm nbody.c	13.02u 0.00s 13.05r
-	gccgo -O2 nbody.go	14.46u 0.00s 14.49r
-	gc nbody	21.79u 0.00s 21.84r
-	gc_B nbody	21.74u 0.00s 21.79r
-
-binary-tree 15 # too slow to use 20
-	gcc -O2 binary-tree.c -lm	0.60u 0.01s 0.61r
-	gccgo -O2 binary-tree.go	1.30u 0.01s 1.32r
-	gccgo -O2 binary-tree-freelist.go	0.00u 0.00s 0.00r
-	gc binary-tree	1.84u 0.01s 1.86r
-	gc binary-tree-freelist	0.33u 0.00s 0.33r
-
-fannkuch 12
-	gcc -O2 fannkuch.c	45.24u 0.00s 45.34r
-	gccgo -O2 fannkuch.go	59.76u 0.01s 59.90r
-	gccgo -O2 fannkuch-parallel.go	218.20u 0.01s 61.60r
-	gc fannkuch	103.92u 0.00s 104.16r
-	gc fannkuch-parallel	221.61u 0.00s 60.49r
-	gc_B fannkuch	53.17u 0.00s 53.30r
-
-regex-dna 100000
-	gcc -O2 regex-dna.c -lpcre	0.47u 0.00s 0.48r
-	gccgo -O2 regex-dna.go	6.52u 0.00s 6.54r
-	gccgo -O2 regex-dna-parallel.go	14.40u 0.73s 4.35r
-	gc regex-dna	2.63u 0.02s 2.66r # -36%
-	gc regex-dna-parallel	2.87u 0.01s 1.11r
-	gc_B regex-dna	2.65u 0.00s 2.66r
-
-spectral-norm 5500
-	gcc -O2 spectral-norm.c -lm	15.78u 0.00s 15.82r
-	gccgo -O2 spectral-norm.go	15.79u 0.00s 15.83r
-	gc spectral-norm	19.76u 0.00s 19.80r
-	gc_B spectral-norm	19.73u 0.01s 19.78r
-
-k-nucleotide 1000000
-	gcc -O2  k-nucleotide.c	5.59u 0.03s 5.63r
-	gccgo -O2 k-nucleotide.go	4.09u 0.03s 4.13r
-	gccgo -O2 k-nucleotide-parallel.go	4.50u 0.06s 1.63r
-	gc k-nucleotide	9.23u 0.02s 9.27r
-	gc k-nucleotide-parallel	9.87u 0.03s 3.55r
-	gc_B k-nucleotide	9.20u 0.00s 9.22r
-
-mandelbrot 16000
-	gcc -O2 mandelbrot.c	36.09u 0.00s 36.18r
-	gccgo -O2 mandelbrot.go	41.69u 0.01s 41.80r
-	gc mandelbrot	60.91u 0.02s 61.07r
-	gc_B mandelbrot	60.90u 0.00s 61.04r
-
-meteor 2098
-	gcc -O2 meteor-contest.c	0.09u 0.00s 0.09r
-	gccgo -O2 meteor-contest.go	0.09u 0.00s 0.09r
-	gc meteor-contest	0.14u 0.00s 0.15r
-	gc_B meteor-contest	0.14u 0.00s 0.14r
-
-pidigits 10000
-	gcc -O2 pidigits.c -lgmp	2.27u 0.00s 2.27r
-	gccgo -O2 pidigits.go	8.65u 0.00s 8.67r
-	gc pidigits	3.70u 0.04s 3.75r
-	gc_B pidigits	3.72u 0.02s 3.75r
-
-threadring 50000000
-	gcc -O2 threadring.c	40.91u 369.85s 323.31r
-	gccgo -O2 threadring.go	26.97u 30.82s 57.93r
-	gc threadring	12.81u 0.01s 12.85r # -13%
-
-chameneos 6000000
-	gcc -O2 chameneosredux.c -lpthread	9.44u 72.90s 12.65r
-	gccgo -O2 chameneosredux.go	7.73u 7.53s 15.30r
-	gc chameneosredux	6.51u 0.00s 6.53r # - 14%
-
-# After http://codereview.appspot.com/6248049, moving panicindex
-# calls out of line (putting the likely code into a single path and shortening
-# loops). Significant changes since the last run (note: some are slower for
-# unrelated and as yet undiagnosed reasons):
-
-nbody -n 50000000
-	gc nbody	19.10u 0.01s 19.19r # -12%
-	gc_B nbody	19.19u 0.00s 19.23r # -12%
-
-binary-tree 15 # too slow to use 20
-	gc binary-tree	1.49u 0.01s 1.51r # -19%
-	
-fannkuch 12
-	gc fannkuch	60.79u 0.00s 60.92r # -41%
-	gc fannkuch-parallel	183.51u 0.01s 51.75r # -14%
-	gc_B fannkuch	51.68u 0.00s 51.79r # -3%
-
-k-nucleotide 1000000
-	gc k-nucleotide	9.74u 0.04s 9.80r # +6%
-	gc k-nucleotide-parallel	9.89u 0.05s 3.59r # +1%
-	gc_B k-nucleotide	9.39u 0.02s 9.43r # +2%
-
-mandelbrot (much slower, due to unrelated http://codereview.appspot.com/6209077)
-	gc mandelbrot	100.98u 0.00s 101.20r # +65%
-	gc_B mandelbrot	100.90u 0.01s 101.17r # +65%
-
-meteor 2098
-	gc meteor-contest	0.13u 0.00s 0.13r # -13%
-	gc_B meteor-contest	0.13u 0.00s 0.13r # -7%
-
-# May 30, 2012.
-# After http://codereview.appspot.com/6261051, restoring old code generated
-# for floating-point constants. Mandelbrot is back to its previous numbers.
-
-mandelbrot 16000
-	gcc -O2 mandelbrot.c	36.07u 0.00s 36.16r
-	gccgo -O2 mandelbrot.go	41.72u 0.01s 41.90r
-	gc mandelbrot	60.62u 0.00s 60.76r
-	gc_B mandelbrot	60.68u 0.00s 60.82r
-
-# May 30, 2012.
-# After http://codereview.appspot.com/6248068, better FP code
-# by avoiding MOVSD between registers.
-# Plus some other timing changes that have crept in from other speedups,
-# from garbage collection to Printf.
-
-fasta -n 25000000
-	gc fasta	1.76u 0.00s 1.76r # -12%
-	gc_B fasta	1.71u 0.00s 1.72r # -12%
-
-nbody -n 50000000
-	gc nbody	17.56u 0.00s 17.60r # -8%
-	gc_B nbody	17.30u 0.00s 17.34r # -10%
-
-fannkuch 12
-	gc fannkuch-parallel	155.92u 0.01s 44.05r # -15%
-
-k-nucleotide 1000000
-	gc k-nucleotide	9.22u 0.01s 9.26r # -5%
-	gc k-nucleotide-parallel	9.23u 0.03s 3.26r # -9%
-	gc_B k-nucleotide	9.22u 0.03s 9.28r # -2%
-
-mandelbrot 16000
-	gc mandelbrot	44.80u 0.00s 44.90r # -27%
-	gc_B mandelbrot	44.81u 0.00s 44.92r # -26%
-
-pidigits 10000
-	gc pidigits	3.51u 0.00s 3.52r # -6%
-	gc_B pidigits	3.51u 0.00s 3.52r # -6%
-
-# Aug 28, 2012
-# After some assembler work in package big.
-pidigits 10000
-	gc pidigits	2.85u 0.02s 2.88r # -22%
-	gc_B pidigits	2.88u 0.01s 2.90r # -21%
-
-# Sep 26, 2012
-# 64-bit ints, plus significantly better floating-point code.
-# Interesting details:
-# 	Generally something in the 0-10% slower range, some (binary tree) more
-#	Floating-point noticeably faster:
-#		nbody -25%
-#		mandelbrot -37% relative to Go 1.
-#	Other:
-#		regex-dna +47%
-fasta -n 25000000
-	gcc -O2 fasta.c	1.43u 0.03s 1.46r
-	gccgo -O2 fasta.go	1.47u 0.00s 1.47r
-	gc fasta	1.78u 0.01s 1.80r
-	gc_B fasta	1.76u 0.00s 1.76r
-
-reverse-complement < output-of-fasta-25000000
-	gcc -O2 reverse-complement.c	1.14u 0.39s 11.19r
-	gccgo -O2 reverse-complement.go	0.91u 0.17s 1.09r
-	gc reverse-complement	1.12u 0.18s 1.31r
-	gc_B reverse-complement	1.12u 0.15s 1.28r
-
-nbody -n 50000000
-	gcc -O2 nbody.c -lm	13.02u 0.00s 13.05r
-	gccgo -O2 nbody.go	13.90u 0.00s 13.93r
-	gc nbody	17.05u 0.00s 17.09r
-	gc_B nbody	16.30u 0.00s 16.34r
-
-binary-tree 15 # too slow to use 20
-	gcc -O2 binary-tree.c -lm	0.61u 0.00s 0.61r
-	gccgo -O2 binary-tree.go	1.24u 0.04s 1.29r
-	gccgo -O2 binary-tree-freelist.go	0.21u 0.01s 0.22r
-	gc binary-tree	1.93u 0.02s 1.96r
-	gc binary-tree-freelist	0.32u 0.00s 0.33r
-
-fannkuch 12
-	gcc -O2 fannkuch.c	45.19u 0.00s 45.29r
-	gccgo -O2 fannkuch.go	60.32u 0.00s 60.45r
-	gccgo -O2 fannkuch-parallel.go	185.59u 0.00s 59.49r
-	gc fannkuch	72.14u 0.00s 72.30r
-	gc fannkuch-parallel	172.54u 0.00s 43.59r
-	gc_B fannkuch	53.55u 0.00s 53.67r
-
-regex-dna 100000
-	gcc -O2 regex-dna.c -lpcre	0.47u 0.00s 0.47r
-	gccgo -O2 regex-dna.go	6.49u 0.05s 6.56r
-	gccgo -O2 regex-dna-parallel.go	14.60u 0.67s 4.42r
-	gc regex-dna	3.91u 0.00s 3.92r
-	gc regex-dna-parallel	4.01u 0.03s 1.56r
-	gc_B regex-dna	3.91u 0.00s 3.92r
-
-spectral-norm 5500
-	gcc -O2 spectral-norm.c -lm	15.85u 0.00s 15.89r
-	gccgo -O2 spectral-norm.go	15.86u 0.00s 15.89r
-	gc spectral-norm	19.72u 0.00s 19.76r
-	gc_B spectral-norm	19.68u 0.01s 19.74r
-
-k-nucleotide 1000000
-	gcc -O2 k-nucleotide.c -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -lglib-2.0 	4.90u 0.01s 4.93r
-	gccgo -O2 k-nucleotide.go	4.78u 0.01s 4.80r
-	gccgo -O2 k-nucleotide-parallel.go	6.49u 0.02s 2.18r
-	gc k-nucleotide	9.05u 0.02s 9.09r
-	gc k-nucleotide-parallel	9.27u 0.01s 3.29r
-	gc_B k-nucleotide	8.95u 0.03s 9.00r
-
-mandelbrot 16000
-	gcc -O2 mandelbrot.c	36.11u 0.00s 36.19r
-	gccgo -O2 mandelbrot.go	43.67u 0.00s 43.77r
-	gc mandelbrot	38.57u 0.00s 38.66r
-	gc_B mandelbrot	38.59u 0.00s 38.68r
-
-meteor 2098
-	gcc -O2 meteor-contest.c	0.09u 0.00s 0.09r
-	gccgo -O2 meteor-contest.go	0.09u 0.00s 0.09r
-	gc meteor-contest	0.13u 0.00s 0.14r
-	gc_B meteor-contest	0.12u 0.00s 0.13r
-
-pidigits 10000
-	gcc -O2 pidigits.c -lgmp	2.26u 0.00s 2.27r
-	gccgo -O2 pidigits.go	9.05u 0.00s 9.07r
-	gc pidigits	2.88u 0.02s 2.90r
-	gc_B pidigits	2.89u 0.00s 2.90r
-
-threadring 50000000
-	gcc -O2 threadring.c -lpthread	37.30u 327.81s 289.28r
-	gccgo -O2 threadring.go	42.83u 26.15s 69.14r
-	gc threadring	13.00u 0.00s 13.03r
-
-chameneos 6000000
-	gcc -O2 chameneosredux.c -lpthread	8.80u 71.67s 12.19r
-	gccgo -O2 chameneosredux.go	11.28u 6.68s 18.00r
-	gc chameneosredux	6.94u 0.00s 6.96r
-
-# May 23, 2013
-# Go 1.1, which includes precise GC, new scheduler, faster maps.
-# 20%-ish speedups across many benchmarks.
-# gccgo showing significant improvement (even though it's not yet up to Go 1.1)
-#
-# Standouts:
-#	fannkuch, regex-dna, k-nucleotide, threadring, chameneos
-
-fasta -n 25000000
-	gcc -m64 -O2 fasta.c	1.54u 0.01s 1.55r
-	gccgo -O2 fasta.go	1.42u 0.00s 1.43r
-	gc fasta	1.50u 0.01s 1.52r # -16%
-	gc_B fasta	1.46u 0.00s 1.46r # -17%
-
-reverse-complement < output-of-fasta-25000000
-	gcc -m64 -O2 reverse-complement.c	0.87u 0.37s 4.36r
-	gccgo -O2 reverse-complement.go	0.77u 0.15s 0.93r # -15%
-	gc reverse-complement	0.99u 0.12s 1.12r # -15%
-	gc_B reverse-complement	0.85u 0.17s 1.02r # -21%
-
-nbody -n 50000000
-	gcc -m64 -O2 nbody.c -lm	13.50u 0.00s 13.53r
-	gccgo -O2 nbody.go	13.98u 0.01s 14.02r
-	gc nbody	16.63u 0.01s 16.67r
-	gc_B nbody	15.74u 0.00s 15.76r
-
-binary-tree 15 # too slow to use 20
-	gcc -m64 -O2 binary-tree.c -lm	0.61u 0.00s 0.61r
-	gccgo -O2 binary-tree.go	1.11u 0.01s 1.12r # -13%
-	gccgo -O2 binary-tree-freelist.go	0.22u 0.01s 0.23r
-	gc binary-tree	1.83u 0.02s 1.83r # -7%
-	gc binary-tree-freelist	0.32u 0.00s 0.32r
-
-fannkuch 12
-	gcc -m64 -O2 fannkuch.c	45.56u 0.00s 45.67r
-	gccgo -O2 fannkuch.go	57.71u 0.00s 57.85r # -4%
-	gccgo -O2 fannkuch-parallel.go	146.31u 0.00s 37.50r #-37%
-	gc fannkuch	70.06u 0.03s 70.17r # -3%
-	gc fannkuch-parallel	131.88u 0.06s 33.59r # -23%
-	gc_B fannkuch	45.55u 0.02s 45.63r # -15%
-
-regex-dna 100000
-	gcc -m64 -O2 regex-dna.c -lpcre	0.44u 0.01s 0.45r
-	gccgo -O2 regex-dna.go	5.59u 0.00s 5.61r # -14%
-	gccgo -O2 regex-dna-parallel.go	10.85u 0.30s 3.34r # -24%
-	gc regex-dna	2.23u 0.01s 2.25r # -43%
-	gc regex-dna-parallel	2.35u 0.00s 0.93r # -40%
-	gc_B regex-dna	2.24u 0.01s 2.25r # -43%
-
-spectral-norm 5500
-	gcc -m64 -O2 spectral-norm.c -lm	14.84u 0.00s 14.88r
-	gccgo -O2 spectral-norm.go	15.33u 0.00s 15.37r
-	gc spectral-norm	16.75u 0.02s 16.79r # -15%
-	gc_B spectral-norm	16.77u 0.01s 16.79r # -15%
-
-k-nucleotide 1000000
-	gcc -O2 k-nucleotide.c -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -lglib-2.0 	4.50u 0.00s 4.52r
-	gccgo -O2 k-nucleotide.go	3.72u 0.04s 3.77r # -21%
-	gccgo -O2 k-nucleotide-parallel.go	3.88u 0.03s 1.42r # -35%
-	gc k-nucleotide	6.32u 0.01s 6.33r # -31%
-	gc k-nucleotide-parallel	6.47u 0.05s 2.13r # -33%
-	gc_B k-nucleotide	6.45u 0.01s 6.47r # - 28%
-
-mandelbrot 16000
-	gcc -m64 -O2 mandelbrot.c	36.03u 0.00s 36.11r
-	gccgo -O2 mandelbrot.go	37.61u 0.00s 37.74r # -14%
-	gc mandelbrot	38.19u 0.05s 38.29r
-	gc_B mandelbrot	38.19u 0.03s 38.26r
-
-meteor 2098
-	gcc -m64 -O2 meteor-contest.c	0.08u 0.00s 0.08r
-	gccgo -O2 meteor-contest.go	0.09u 0.01s 0.10r
-	gc meteor-contest	0.12u 0.00s 0.12r # -15% although perhaps just noise
-	gc_B meteor-contest	0.11u 0.00s 0.12r # -8% although perhaps just noise
-
-pidigits 10000
-	gcc -m64 -O2 pidigits.c -lgmp	2.27u 0.00s 2.28r
-	gccgo -O2 pidigits.go	8.95u 0.02s 8.99r
-	gc pidigits	2.88u 0.14s 2.91r
-	gc_B pidigits	2.92u 0.10s 2.91r
-
-threadring 50000000
-	gcc -m64 -O2 threadring.c -lpthread	14.75u 167.88s 212.23r
-	gccgo -O2 threadring.go	36.72u 12.08s 48.91r # -29%
-	gc threadring	10.93u 0.01s 10.95r # -16%
-
-chameneos 6000000
-	gcc -m64 -O2 chameneosredux.c -lpthread	8.89u 56.62s 9.75r
-	gccgo -O2 chameneosredux.go	9.48u 2.48s 11.99r # -33%
-	gc chameneosredux	5.80u 0.00s 5.81r # -16%
-
diff --git a/test/bench/shootout/timing.sh b/test/bench/shootout/timing.sh
deleted file mode 100755
index 9abcf78..0000000
--- a/test/bench/shootout/timing.sh
+++ /dev/null
@@ -1,252 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2009 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.
-
-set -e
-
-eval $(go tool dist env)
-GC="go tool compile"
-LD="go tool link"
-
-gccm=""
-case "$O" in
-8)
-	gccm=-m32;;
-6)
-	gccm=-m64;;
-esac
-
-EXE="out"
-havepcre=true
-haveglib=true
-havegmp=true
-case "$(uname)" in
-*MINGW* | *WIN32* | *CYGWIN*)
-	havepcre=false
-	haveglib=false
-	havegmp=false
-	if which pkg-config >/dev/null 2>&1; then
-		if pkg-config --cflags libpcre >/dev/null 2>&1
-		then
-			echo "havepcre"
-			havepcre=true
-		fi
-		if pkg-config --cflags glib-2.0 >/dev/null 2>&1
-		then
-			haveglib=true
-		fi
-		if pkg-config --cflags gmp >/dev/null 2>&1
-		then
-			havegmp=true
-		fi
-	fi
-	EXE=exe;;
-esac
-
-PATH=.:$PATH
-
-havegccgo=false
-if which gccgo >/dev/null 2>&1
-then
-	havegccgo=true
-fi
-
-mode=run
-case X"$1" in
-X-test)
-	mode=test
-	shift
-esac
-
-gc() {
-	$GC $1.go; $LD -o a.$EXE $1.o
-}
-
-gc_B() {
-	$GC -B $1.go; $LD -o a.$EXE $1.o
-}
-
-runonly() {
-	if [ $mode = run ]
-	then
-		"$@"
-	fi
-}
-
-run() {
-	if [ $mode = test ]
-	then
-		if echo $1 | grep -q '^gc '
-		then
-			$1	# compile the program
-			program=$(echo $1 | sed 's/gc //')
-			shift
-			echo $program
-			$1 <fasta-1000.txt > /tmp/$$
-			case $program in
-			chameneosredux)
-				# exact numbers may vary but non-numbers should match
-				grep -v '[0-9]' /tmp/$$ > /tmp/$$x
-				grep -v '[0-9]' chameneosredux.txt > /tmp/$$y
-				cmp /tmp/$$x /tmp/$$y
-				rm -f /tmp/$$ /tmp/$$x /tmp/$$y
-				;;
-			*)
-				cmp /tmp/$$ $program.txt
-				rm -f /tmp/$$
-			esac
-		fi
-		return
-	fi
-	if ! $havegccgo && echo $1 | grep -q '^gccgo '
-	then
-		return
-	fi
-	echo -n '	'$1'	'
-	$1
-	shift
-	
-	echo $((time -p $* >/dev/null) 2>&1) | awk '{print $4 "u " $6 "s " $2 "r"}'
-}
-
-fasta() {
-	runonly echo 'fasta -n 25000000'
-	run "gcc $gccm -O2 fasta.c" a.$EXE 25000000
-	run 'gccgo -O2 fasta.go' a.$EXE -n 25000000	#commented out until WriteString is in bufio
-	run 'gc fasta' a.$EXE -n 25000000
-	run 'gc_B fasta' a.$EXE -n 25000000
-}
-
-revcomp() {
-	runonly gcc -O2 fasta.c
-	runonly a.$EXE 25000000 > x
-	runonly echo 'reverse-complement < output-of-fasta-25000000'
-	run "gcc $gccm -O2 reverse-complement.c" a.$EXE < x
-	run 'gccgo -O2 reverse-complement.go' a.$EXE < x
-	run 'gc reverse-complement' a.$EXE < x
-	run 'gc_B reverse-complement' a.$EXE < x
-	rm x
-}
-
-nbody() {
-	runonly echo 'nbody -n 50000000'
-	run "gcc $gccm -O2 nbody.c -lm" a.$EXE 50000000
-	run 'gccgo -O2 nbody.go' a.$EXE -n 50000000
-	run 'gc nbody' a.$EXE -n 50000000
-	run 'gc_B nbody' a.$EXE -n 50000000
-}
-
-binarytree() {
-	runonly echo 'binary-tree 15 # too slow to use 20'
-	run "gcc $gccm -O2 binary-tree.c -lm" a.$EXE 15
-	run 'gccgo -O2 binary-tree.go' a.$EXE -n 15
-	run 'gccgo -O2 binary-tree-freelist.go' a.$EXE -n 15
-	run 'gc binary-tree' a.$EXE -n 15
-	run 'gc binary-tree-freelist' a.$EXE -n 15
-}
-
-fannkuch() {
-	runonly echo 'fannkuch 12'
-	run "gcc $gccm -O2 fannkuch.c" a.$EXE 12
-	run 'gccgo -O2 fannkuch.go' a.$EXE -n 12
-	run 'gccgo -O2 fannkuch-parallel.go' a.$EXE -n 12
-	run 'gc fannkuch' a.$EXE -n 12
-	run 'gc fannkuch-parallel' a.$EXE -n 12
-	run 'gc_B fannkuch' a.$EXE -n 12
-}
-
-regexdna() {
-	runonly gcc -O2 fasta.c
-	runonly a.$EXE 100000 > x
-	runonly echo 'regex-dna 100000'
-	if  $havepcre; then
-		run "gcc $gccm -O2 regex-dna.c $(pkg-config libpcre --cflags --libs)" a.$EXE <x
-	fi
-	run 'gccgo -O2 regex-dna.go' a.$EXE <x
-	run 'gccgo -O2 regex-dna-parallel.go' a.$EXE <x
-	run 'gc regex-dna' a.$EXE <x
-	run 'gc regex-dna-parallel' a.$EXE <x
-	run 'gc_B regex-dna' a.$EXE <x
-	rm x
-}
-
-spectralnorm() {
-	runonly echo 'spectral-norm 5500'
-	run "gcc $gccm -O2 spectral-norm.c -lm" a.$EXE 5500
-	run 'gccgo -O2 spectral-norm.go' a.$EXE -n 5500
-	run 'gc spectral-norm' a.$EXE -n 5500
-	run 'gc_B spectral-norm' a.$EXE -n 5500
-}
-
-knucleotide() {
-	runonly gcc -O2 fasta.c
-	runonly a.$EXE 1000000 > x  # should be using 25000000
-	runonly echo 'k-nucleotide 1000000'
-	if [ $mode = run ] && $haveglib; then
-		run "gcc -O2 k-nucleotide.c $(pkg-config glib-2.0 --cflags --libs)" a.$EXE <x
-	fi
-	run 'gccgo -O2 k-nucleotide.go' a.$EXE <x
-	run 'gccgo -O2 k-nucleotide-parallel.go' a.$EXE <x
-	run 'gc k-nucleotide' a.$EXE <x
-	run 'gc k-nucleotide-parallel' a.$EXE <x
-	run 'gc_B k-nucleotide' a.$EXE <x
-	rm x
-}
-
-mandelbrot() {
-	runonly echo 'mandelbrot 16000'
-	run "gcc $gccm -O2 mandelbrot.c" a.$EXE 16000
-	run 'gccgo -O2 mandelbrot.go' a.$EXE -n 16000
-	run 'gc mandelbrot' a.$EXE -n 16000
-	run 'gc_B mandelbrot' a.$EXE -n 16000
-}
-
-meteor() {
-	runonly echo 'meteor 2098'
-	run "gcc $gccm -O2 meteor-contest.c" a.$EXE 2098
-	run 'gccgo -O2 meteor-contest.go' a.$EXE -n 2098
-	run 'gc meteor-contest' a.$EXE -n 2098
-	run 'gc_B  meteor-contest' a.$EXE -n 2098
-}
-
-pidigits() {
-	runonly echo 'pidigits 10000'
-	if  $havegmp; then
-		run "gcc $gccm -O2 pidigits.c -lgmp" a.$EXE 10000
-	fi
-	run 'gccgo -O2 pidigits.go' a.$EXE -n 10000
-	run 'gc pidigits' a.$EXE -n 10000
-	run 'gc_B  pidigits' a.$EXE -n 10000
-}
-
-threadring() {
-	runonly echo 'threadring 50000000'
-	run "gcc $gccm -O2 threadring.c -lpthread" a.$EXE 50000000
-	run 'gccgo -O2 threadring.go' a.$EXE -n 50000000
-	run 'gc threadring' a.$EXE -n 50000000
-}
-
-chameneos() {
-	runonly echo 'chameneos 6000000'
-	run "gcc $gccm -O2 chameneosredux.c -lpthread" a.$EXE 6000000
-	run 'gccgo -O2 chameneosredux.go' a.$EXE 6000000
-	run 'gc chameneosredux' a.$EXE 6000000
-}
-
-case $# in
-0)
-	run="fasta revcomp nbody binarytree fannkuch regexdna spectralnorm knucleotide mandelbrot meteor pidigits threadring chameneos"
-	;;
-*)
-	run=$*
-esac
-
-for i in $run
-do
-	$i
-	runonly echo
-done
-
-rm *.o *.$EXE # Clean up
-
diff --git a/test/blank1.go b/test/blank1.go
index 54a7297..bf94d1a 100644
--- a/test/blank1.go
+++ b/test/blank1.go
@@ -13,6 +13,10 @@ var t struct {
 	_ int
 }
 
+func (x int) _() { // ERROR "cannot define new methods on non-local type"
+	println(x)
+}
+
 type T struct {
       _ []int
 }
diff --git a/test/const.go b/test/const.go
index d583659..6c29336 100644
--- a/test/const.go
+++ b/test/const.go
@@ -19,6 +19,9 @@ const (
 	c3div2  = 3 / 2
 	c1e3    = 1e3
 
+	rsh1 = 1e100 >> 1000
+	rsh2 = 1e302 >> 1000
+
 	ctrue  = true
 	cfalse = !ctrue
 )
@@ -48,6 +51,8 @@ func ints() {
 	assert(c3div2 == 1, "3/2")
 	assert(c1e3 == 1000, "c1e3 int")
 	assert(c1e3 == 1e3, "c1e3 float")
+	assert(rsh1 == 0, "rsh1")
+	assert(rsh2 == 9, "rsh2")
 
 	// verify that all (in range) are assignable as ints
 	var i int
diff --git a/test/escape2.go b/test/escape2.go
index 46cfde4..6940a09 100644
--- a/test/escape2.go
+++ b/test/escape2.go
@@ -620,15 +620,15 @@ func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "leaking param:
 }
 
 func foo75(z *int) { // ERROR "foo75 z does not escape$"
-	myprint(z, 1, 2, 3) // ERROR "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "foo75 ... argument does not escape$"
+	myprint(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo75 ... argument does not escape$"
 }
 
 func foo75a(z *int) { // ERROR "foo75a z does not escape$"
-	myprint1(z, 1, 2, 3) // ERROR "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "foo75a ... argument does not escape$"
+	myprint1(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo75a ... argument does not escape$"
 }
 
 func foo75esc(z *int) { // ERROR "leaking param: z$"
-	gxx = myprint(z, 1, 2, 3) // ERROR "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "foo75esc ... argument does not escape$"
+	gxx = myprint(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo75esc ... argument does not escape$"
 }
 
 func foo75aesc(z *int) { // ERROR "foo75aesc z does not escape$"
@@ -640,30 +640,28 @@ func foo75aesc1(z *int) { // ERROR "foo75aesc1 z does not escape$"
 	sink = myprint1(z, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "myprint1\(z, 1, 2, 3\) escapes to heap$"
 }
 
-// BAD: z does not escape here
-func foo76(z *int) { // ERROR "leaking param: z$"
-	myprint(nil, z) // ERROR "foo76 ... argument does not escape$" "z escapes to heap$"
+func foo76(z *int) { // ERROR "z does not escape"
+	myprint(nil, z) // ERROR "foo76 ... argument does not escape$" "z does not escape"
 }
 
-// BAD: z does not escape here
-func foo76a(z *int) { // ERROR "leaking param: z$"
-	myprint1(nil, z) // ERROR "foo76a ... argument does not escape$" "z escapes to heap$"
+func foo76a(z *int) { // ERROR "z does not escape"
+	myprint1(nil, z) // ERROR "foo76a ... argument does not escape$" "z does not escape"
 }
 
 func foo76b() {
-	myprint(nil, 1, 2, 3) // ERROR "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "foo76b ... argument does not escape$"
+	myprint(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76b ... argument does not escape$"
 }
 
 func foo76c() {
-	myprint1(nil, 1, 2, 3) // ERROR "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "foo76c ... argument does not escape$"
+	myprint1(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76c ... argument does not escape$"
 }
 
 func foo76d() {
-	defer myprint(nil, 1, 2, 3) // ERROR "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "foo76d ... argument does not escape$"
+	defer myprint(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76d ... argument does not escape$"
 }
 
 func foo76e() {
-	defer myprint1(nil, 1, 2, 3) // ERROR "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "foo76e ... argument does not escape$"
+	defer myprint1(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76e ... argument does not escape$"
 }
 
 func foo76f() {
@@ -697,13 +695,11 @@ func foo77c(z []interface{}) { // ERROR "leaking param: z$"
 }
 
 func dotdotdot() {
-	// BAD: i should not escape here
-	i := 0           // ERROR "moved to heap: i$"
-	myprint(nil, &i) // ERROR "&i escapes to heap$" "dotdotdot ... argument does not escape$"
+	i := 0
+	myprint(nil, &i) // ERROR "&i does not escape" "dotdotdot ... argument does not escape$"
 
-	// BAD: j should not escape here
-	j := 0            // ERROR "moved to heap: j$"
-	myprint1(nil, &j) // ERROR "&j escapes to heap$" "dotdotdot ... argument does not escape$"
+	j := 0
+	myprint1(nil, &j) // ERROR "&j does not escape" "dotdotdot ... argument does not escape$"
 }
 
 func foo78(z int) *int { // ERROR "moved to heap: z$"
@@ -1208,7 +1204,7 @@ func foo126() {
 		// loopdepth 1
 		var i int // ERROR "moved to heap: i$"
 		func() {  // ERROR "foo126 func literal does not escape$"
-			px = &i // ERROR "&i escapes to heap$"
+			px = &i // ERROR "&i escapes to heap$"  "leaking closure reference i"
 		}()
 	}
 	_ = px
diff --git a/test/escape2n.go b/test/escape2n.go
index c328773..25b5a9b 100644
--- a/test/escape2n.go
+++ b/test/escape2n.go
@@ -620,15 +620,15 @@ func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "leaking param:
 }
 
 func foo75(z *int) { // ERROR "foo75 z does not escape$"
-	myprint(z, 1, 2, 3) // ERROR "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "foo75 ... argument does not escape$"
+	myprint(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo75 ... argument does not escape$"
 }
 
 func foo75a(z *int) { // ERROR "foo75a z does not escape$"
-	myprint1(z, 1, 2, 3) // ERROR "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "foo75a ... argument does not escape$"
+	myprint1(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo75a ... argument does not escape$"
 }
 
 func foo75esc(z *int) { // ERROR "leaking param: z$"
-	gxx = myprint(z, 1, 2, 3) // ERROR "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "foo75esc ... argument does not escape$"
+	gxx = myprint(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo75esc ... argument does not escape$"
 }
 
 func foo75aesc(z *int) { // ERROR "foo75aesc z does not escape$"
@@ -640,30 +640,28 @@ func foo75aesc1(z *int) { // ERROR "foo75aesc1 z does not escape$"
 	sink = myprint1(z, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "myprint1\(z, 1, 2, 3\) escapes to heap$"
 }
 
-// BAD: z does not escape here
-func foo76(z *int) { // ERROR "leaking param: z$"
-	myprint(nil, z) // ERROR "foo76 ... argument does not escape$" "z escapes to heap$"
+func foo76(z *int) { // ERROR "z does not escape"
+	myprint(nil, z) // ERROR "foo76 ... argument does not escape$" "z does not escape"
 }
 
-// BAD: z does not escape here
-func foo76a(z *int) { // ERROR "leaking param: z$"
-	myprint1(nil, z) // ERROR "foo76a ... argument does not escape$" "z escapes to heap$"
+func foo76a(z *int) { // ERROR "z does not escape"
+	myprint1(nil, z) // ERROR "foo76a ... argument does not escape$" "z does not escape"
 }
 
 func foo76b() {
-	myprint(nil, 1, 2, 3) // ERROR "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "foo76b ... argument does not escape$"
+	myprint(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76b ... argument does not escape$"
 }
 
 func foo76c() {
-	myprint1(nil, 1, 2, 3) // ERROR "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "foo76c ... argument does not escape$"
+	myprint1(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76c ... argument does not escape$"
 }
 
 func foo76d() {
-	defer myprint(nil, 1, 2, 3) // ERROR "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "foo76d ... argument does not escape$"
+	defer myprint(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76d ... argument does not escape$"
 }
 
 func foo76e() {
-	defer myprint1(nil, 1, 2, 3) // ERROR "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "foo76e ... argument does not escape$"
+	defer myprint1(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76e ... argument does not escape$"
 }
 
 func foo76f() {
@@ -697,13 +695,11 @@ func foo77c(z []interface{}) { // ERROR "leaking param: z$"
 }
 
 func dotdotdot() {
-	// BAD: i should not escape here
-	i := 0           // ERROR "moved to heap: i$"
-	myprint(nil, &i) // ERROR "&i escapes to heap$" "dotdotdot ... argument does not escape$"
+	i := 0
+	myprint(nil, &i) // ERROR "&i does not escape" "dotdotdot ... argument does not escape$"
 
-	// BAD: j should not escape here
-	j := 0            // ERROR "moved to heap: j$"
-	myprint1(nil, &j) // ERROR "&j escapes to heap$" "dotdotdot ... argument does not escape$"
+	j := 0
+	myprint1(nil, &j) // ERROR "&j does not escape" "dotdotdot ... argument does not escape$"
 }
 
 func foo78(z int) *int { // ERROR "moved to heap: z$"
@@ -1208,7 +1204,7 @@ func foo126() {
 		// loopdepth 1
 		var i int // ERROR "moved to heap: i$"
 		func() {  // ERROR "foo126 func literal does not escape$"
-			px = &i // ERROR "&i escapes to heap$"
+			px = &i // ERROR "&i escapes to heap$" "leaking closure reference i"
 		}()
 	}
 	_ = px
diff --git a/test/finprofiled.go b/test/finprofiled.go
new file mode 100644
index 0000000..0eb801a
--- /dev/null
+++ b/test/finprofiled.go
@@ -0,0 +1,74 @@
+// run
+
+// Copyright 2015 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 that tiny allocations with finalizers are correctly profiled.
+// Previously profile special records could have been processed prematurely
+// (while the object is still live).
+
+package main
+
+import (
+	"runtime"
+	"time"
+	"unsafe"
+)
+
+func main() {
+	runtime.MemProfileRate = 1
+	// Allocate 1M 4-byte objects and set a finalizer for every third object.
+	// Assuming that tiny block size is 16, some objects get finalizers setup
+	// only for middle bytes. The finalizer resurrects that object.
+	// As the result, all allocated memory must stay alive.
+	const (
+		N = 1 << 20
+		tinyBlockSize = 16 // runtime._TinySize
+	)
+	hold := make([]*int32, 0, N)
+	for i := 0; i < N; i++ {
+		x := new(int32)
+		if i%3 == 0 {
+			runtime.SetFinalizer(x, func(p *int32) {
+				hold = append(hold, p)
+			})
+		}
+	}
+	// Finalize as much as possible.
+	// Note: the sleep only increases probility of bug detection,
+	// it cannot lead to false failure.
+	for i := 0; i < 5; i++ {
+		runtime.GC()
+		time.Sleep(10 * time.Millisecond)
+	}
+	// Read memory profile.
+	var prof []runtime.MemProfileRecord
+	for {
+		if n, ok := runtime.MemProfile(prof, false); ok {
+			prof = prof[:n]
+			break
+		} else {
+			prof = make([]runtime.MemProfileRecord, n+10)
+		}
+	}
+	// See how much memory in tiny objects is profiled.
+	var totalBytes int64
+	for _, p := range prof {
+		bytes := p.AllocBytes - p.FreeBytes
+		nobj := p.AllocObjects - p.FreeObjects
+		size := bytes / nobj
+		if size == tinyBlockSize {
+			totalBytes += bytes
+		}
+	}
+	// 2*tinyBlockSize slack is for any boundary effects.
+	if want := N*int64(unsafe.Sizeof(int32(0))) - 2*tinyBlockSize; totalBytes < want {
+		println("got", totalBytes, "want >=", want)
+		panic("some of the tiny objects are not profiled")
+	}
+	// Just to keep hold alive.
+	if len(hold) != 0 && hold[0] == nil {
+		panic("bad")
+	}
+}
diff --git a/test/fixedbugs/bug13343.go b/test/fixedbugs/bug13343.go
new file mode 100644
index 0000000..4c30dac
--- /dev/null
+++ b/test/fixedbugs/bug13343.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2015 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
+
+var (
+	a, b = f() // ERROR "initialization loop|depends upon itself"
+	c    = b
+)
+
+func f() (int, int) {
+	return c, c
+}
+
+func main() {}
diff --git a/test/fixedbugs/bug358.go b/test/fixedbugs/bug358.go
index 063c2e0..6f9d73c 100644
--- a/test/fixedbugs/bug358.go
+++ b/test/fixedbugs/bug358.go
@@ -10,13 +10,14 @@
 package main
 
 import (
-	"io/ioutil"	// GCCGO_ERROR "imported and not used"
+	// avoid imported and not used errors
+	// "io/ioutil"
 	"net/http"
-	"os"		// GCCGO_ERROR "imported and not used"
+	// "os"
 )
 
 func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
-	return func(w http.ResponseWriter, r *http.Request)  // ERROR "syntax error|invalid use of type"
+	return func(w http.ResponseWriter, r *http.Request)  // ERROR "syntax error|not an expression|invalid use of type"
 }
 
 type Page struct {
diff --git a/test/fixedbugs/bug401.go b/test/fixedbugs/bug401.go
index 5589b5b..c58e1ca 100644
--- a/test/fixedbugs/bug401.go
+++ b/test/fixedbugs/bug401.go
@@ -9,9 +9,8 @@ package main
 
 type T struct{}
 
+//go:noinline
 func (T) cplx() complex128 {
-	for false {
-	} // avoid inlining
 	return complex(1, 0)
 }
 
diff --git a/test/fixedbugs/bug484.go b/test/fixedbugs/bug484.go
index c664b83..7025aff 100644
--- a/test/fixedbugs/bug484.go
+++ b/test/fixedbugs/bug484.go
@@ -23,20 +23,14 @@ package main
 
 import "runtime"
 
-var c bool
-
+//go:noinline
 func f() interface{} {
-	if c { // disable inlining
-		f()
-	}
 	runtime.GC()
 	return nil
 }
 
+//go:noinline
 func g() {
-	if c { // disable inlining
-		g()
-	}
 	var s interface{}
 	_ = func() {
 		s := f()
@@ -47,31 +41,25 @@ func g() {
 	useiface(s)
 }
 
+//go:noinline
 func useiface(x interface{}) {
-	if c {	// disable inlining
-		useiface(x)
-	}
 }
 
+//go:noinline
 func h() {
-	if c { // disable inlining
-		h()
-	}
 	var x [16]uintptr
 	for i := range x {
 		x[i] = 1
 	}
-	
+
 	useint(x[0])
 	useint(x[1])
 	useint(x[2])
 	useint(x[3])
 }
 
+//go:noinline
 func useint(x uintptr) {
-	if c {	// disable inlining
-		useint(x)
-	}
 }
 
 func main() {
@@ -85,6 +73,6 @@ func main() {
 
 func big(x int) {
 	if x >= 0 {
-		big(x-1)
+		big(x - 1)
 	}
 }
diff --git a/test/fixedbugs/bug496.go b/test/fixedbugs/bug496.go
new file mode 100644
index 0000000..4307c75
--- /dev/null
+++ b/test/fixedbugs/bug496.go
@@ -0,0 +1,29 @@
+// compile
+
+// Copyright 2015 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.
+
+// Gccgo used to give an error:
+// <built-in>: error: redefinition of ‘s$F$hash’
+// <built-in>: note: previous definition of ‘s$F$hash’ was here
+// <built-in>: error: redefinition of ‘s$F$equal’
+// <built-in>: note: previous definition of ‘s$F$equal’ was here
+
+package p
+
+type T1 int
+
+func (t T1) F() {
+	type s struct {
+		f string
+	}
+}
+
+type T2 int
+
+func (t T2) F() {
+	type s struct {
+		f string
+	}
+}
diff --git a/test/fixedbugs/bug497.go b/test/fixedbugs/bug497.go
new file mode 100644
index 0000000..7081b1c
--- /dev/null
+++ b/test/fixedbugs/bug497.go
@@ -0,0 +1,28 @@
+// run
+
+// Copyright 2015 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.
+
+// Gccgo used to miscompile passing a global variable with a
+// zero-sized type to a function.
+
+package main
+
+type T struct {
+	field s
+}
+
+type s struct{}
+
+var X T
+
+func F(_ T, c interface{}) int {
+	return len(c.(string))
+}
+
+func main() {
+	if v := F(X, "hi"); v != 2 {
+		panic(v)
+	}
+}
diff --git a/test/fixedbugs/gcc67968.dir/a.go b/test/fixedbugs/gcc67968.dir/a.go
new file mode 100644
index 0000000..9f51a7a
--- /dev/null
+++ b/test/fixedbugs/gcc67968.dir/a.go
@@ -0,0 +1,12 @@
+// Copyright 2015 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 a
+
+type T int
+
+func (a *T) Foo() [1]string {
+	var r [1]string
+	return r
+}
diff --git a/test/fixedbugs/gcc67968.dir/b.go b/test/fixedbugs/gcc67968.dir/b.go
new file mode 100644
index 0000000..41b62d2
--- /dev/null
+++ b/test/fixedbugs/gcc67968.dir/b.go
@@ -0,0 +1,12 @@
+// Copyright 2015 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 b
+
+import "./a"
+
+func F() (interface{}) {
+     var v *a.T
+     return v.Foo()
+}
diff --git a/test/fixedbugs/gcc67968.go b/test/fixedbugs/gcc67968.go
new file mode 100644
index 0000000..8db3dd8
--- /dev/null
+++ b/test/fixedbugs/gcc67968.go
@@ -0,0 +1,14 @@
+// compiledir
+
+// Copyright 2015 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.
+
+// https://gcc.gnu.org/PR67968
+
+// gccgo compiler crash building the equality and hash functions for a
+// type when a return statement requires a conversion to interface
+// type of a call of function defined in a different package that
+// returns an unnamed type.
+
+package ignored
diff --git a/test/fixedbugs/issue10441.go b/test/fixedbugs/issue10441.go
index 25832fa..9bc4948 100644
--- a/test/fixedbugs/issue10441.go
+++ b/test/fixedbugs/issue10441.go
@@ -11,7 +11,7 @@ func bar() {
 	foo(&f)
 }
 
+//go:noinline
 func foo(f *func()) func() {
-	defer func() {}() // prevent inlining of foo
 	return *f
 }
diff --git a/test/fixedbugs/issue10607.go b/test/fixedbugs/issue10607.go
index bf527d0..a1a65a7 100644
--- a/test/fixedbugs/issue10607.go
+++ b/test/fixedbugs/issue10607.go
@@ -1,4 +1,4 @@
-// +build linux,!ppc64,!ppc64le
+// +build linux,!ppc64,!ppc64le,!mips64,!mips64le
 // run
 
 // Copyright 2015 The Go Authors. All rights reserved.
diff --git a/test/fixedbugs/issue10975.go b/test/fixedbugs/issue10975.go
new file mode 100644
index 0000000..1aa7d89
--- /dev/null
+++ b/test/fixedbugs/issue10975.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2015 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 10975: Returning an invalid interface would cause
+// `internal compiler error: getinarg: not a func`.
+
+package main
+
+type I interface {
+	int // ERROR "interface contains embedded non-interface int"
+}
+
+func New() I {
+	return struct{}{}
+}
diff --git a/test/fixedbugs/issue11326.go b/test/fixedbugs/issue11326.go
index fd1fab3..3a4fbff 100644
--- a/test/fixedbugs/issue11326.go
+++ b/test/fixedbugs/issue11326.go
@@ -4,25 +4,28 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package main
+// Tests for golang.org/issue/11326.
 
-import "fmt"
+package main
 
 func main() {
-	var g = 1e81391777742999 // ERROR "exponent too large"
-	// The next should only cause a problem when converted to float64
-	// by the assignment, but instead the compiler rejects it outright,
-	// rather than mishandle it. Specifically, when handled, 'var h' prints:
-	//	issue11326.go:N: constant 0.93342e+536870911 overflows float64
-	// The rejection of 'var i' is just insurance. It seems to work correctly.
-	// See golang.org/issue/11326.
-	// var h = 1e2147483647     // should be "1.00000e+2147483647 overflows float64"
-	var h = 1e2147483647 // ERROR "exponent too large"
-	// var i = 1e214748364  // should be "1.00000e\+214748364 overflows float64"
-	var i = 1e214748364 // ERROR "exponent too large"
-	var j = 1e21474836  // ERROR "1.00000e\+21474836 overflows float64"
-	var k = 1e2147483   // ERROR "1.00000e\+2147483 overflows float64"
-	var l = 1e214748    // ERROR "1.00000e\+214748 overflows float64"
-	var m = 1e21474     // ERROR "1.00000e\+21474 overflows float64"
-	fmt.Println(g)
+	// The gc compiler implementation uses the minimally required 32bit
+	// binary exponent, so these constants cannot be represented anymore
+	// internally. However, the language spec does not preclude other
+	// implementations from handling these. Don't check the error.
+	// var _ = 1e2147483647 // "constant too large"
+	// var _ = 1e646456993  // "constant too large"
+
+	// Any implementation must be able to handle these constants at
+	// compile time (even though they cannot be assigned to a float64).
+	var _ = 1e646456992  // ERROR "1e\+646456992 overflows float64"
+	var _ = 1e64645699   // ERROR "1e\+64645699 overflows float64"
+	var _ = 1e6464569    // ERROR "1e\+6464569 overflows float64"
+	var _ = 1e646456     // ERROR "1e\+646456 overflows float64"
+	var _ = 1e64645      // ERROR "1e\+64645 overflows float64"
+	var _ = 1e6464       // ERROR "1e\+6464 overflows float64"
+	var _ = 1e646        // ERROR "1e\+646 overflows float64"
+	var _ = 1e309        // ERROR "1e\+309 overflows float64"
+
+	var _ = 1e308
 }
diff --git a/test/fixedbugs/issue11326b.go b/test/fixedbugs/issue11326b.go
index 00effbc..6a6ae2f 100644
--- a/test/fixedbugs/issue11326b.go
+++ b/test/fixedbugs/issue11326b.go
@@ -6,36 +6,36 @@
 
 package main
 
+// Tests for golang.org/issue/11326.
+
 func main() {
-	/* TODO(rsc): Should work but does not. See golang.org/issue/11326.
 	{
-		const n = 1e2147483647
-		const d = 1e2147483646
+		const n = 1e646456992
+		const d = 1e646456991
 		x := n / d
 		if x != 10.0 {
 			println("incorrect value:", x)
 		}
 	}
 	{
-		const n = 1e214748364
-		const d = 1e214748363
+		const n = 1e64645699
+		const d = 1e64645698
 		x := n / d
 		if x != 10.0 {
 			println("incorrect value:", x)
 		}
 	}
-	*/
 	{
-		const n = 1e21474836
-		const d = 1e21474835
+		const n = 1e6464569
+		const d = 1e6464568
 		x := n / d
 		if x != 10.0 {
 			println("incorrect value:", x)
 		}
 	}
 	{
-		const n = 1e2147483
-		const d = 1e2147482
+		const n = 1e646456
+		const d = 1e646455
 		x := n / d
 		if x != 10.0 {
 			println("incorrect value:", x)
diff --git a/test/fixedbugs/issue11359.go b/test/fixedbugs/issue11359.go
new file mode 100644
index 0000000..6ffffed
--- /dev/null
+++ b/test/fixedbugs/issue11359.go
@@ -0,0 +1,11 @@
+// errorcheck
+
+// Copyright 2015 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.
+
+// identifiers beginning with non-ASCII digits were incorrectly accepted.
+// issue 11359.
+
+package p
+var ۶ = 0 // ERROR "identifier cannot begin with digit"
diff --git a/test/fixedbugs/issue11362.go b/test/fixedbugs/issue11362.go
new file mode 100644
index 0000000..680b0e5
--- /dev/null
+++ b/test/fixedbugs/issue11362.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// Copyright 2015 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 11362: prints empty canonical import path
+
+package main
+
+import _ "unicode//utf8" // ERROR "non-canonical import path .unicode//utf8. \(should be .unicode/utf8.\)" "can't find import: .unicode//utf8."
+
+func main() {
+}
+
diff --git a/test/fixedbugs/issue11590.go b/test/fixedbugs/issue11590.go
new file mode 100644
index 0000000..f3032fc
--- /dev/null
+++ b/test/fixedbugs/issue11590.go
@@ -0,0 +1,11 @@
+// errorcheck
+
+// Copyright 2015 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 p
+
+var _ = int8(4) * 300         // ERROR "constant 300 overflows int8" "constant 1200 overflows int8"
+var _ = complex64(1) * 1e200  // ERROR "constant 1e\+200 overflows complex64"
+var _ = complex128(1) * 1e500 // ERROR "constant 1e\+500 overflows complex128"
diff --git a/test/fixedbugs/issue11610.go b/test/fixedbugs/issue11610.go
new file mode 100644
index 0000000..a326249
--- /dev/null
+++ b/test/fixedbugs/issue11610.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2015 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 an internal compiler error on ? symbol in declaration
+// following an empty import.
+
+package a
+import""  // ERROR "import path is empty"
+var?      // ERROR "invalid declaration"
+
+var x int // ERROR "unexpected var"
+
+func main() {
+}
diff --git a/test/fixedbugs/issue11614.go b/test/fixedbugs/issue11614.go
new file mode 100644
index 0000000..959643a
--- /dev/null
+++ b/test/fixedbugs/issue11614.go
@@ -0,0 +1,26 @@
+// errorcheck
+
+// Copyright 2015 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 that incorrect expressions involving wrong anonymous interface
+// do not generate panics in Type Stringer.
+// Does not compile.
+
+package main
+
+type I interface {
+	int // ERROR "interface contains embedded non-interface int"
+}
+
+func n() {
+	(I) // ERROR "type I is not an expression"
+}
+
+func m() {
+	(interface{int}) // ERROR "interface contains embedded non-interface int" "type interface { int } is not an expression"
+}
+
+func main() {
+}
diff --git a/test/fixedbugs/issue11656.go b/test/fixedbugs/issue11656.go
index 90385bb..565e796 100644
--- a/test/fixedbugs/issue11656.go
+++ b/test/fixedbugs/issue11656.go
@@ -4,26 +4,15 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// darwin/386 seems to mangle the PC and SP before
-// it manages to invoke the signal handler, so this test fails there.
-// +build !darwin !386
-//
-// openbsd/386 and netbsd/386 don't work, not sure why.
-// +build !openbsd !386
-// +build !netbsd !386
-//
 // windows doesn't work, because Windows exception handling
 // delivers signals based on the current PC, and that current PC
 // doesn't go into the Go runtime.
 // +build !windows
-//
-// arm64 gets "illegal instruction" (why is the data executable?)
-// and is unable to do the traceback correctly (why?).
-// +build !arm64
 
 package main
 
 import (
+	"encoding/binary"
 	"runtime"
 	"runtime/debug"
 	"unsafe"
@@ -56,7 +45,31 @@ func f(n int) {
 	var f struct {
 		x uintptr
 	}
-	f.x = uintptr(unsafe.Pointer(&f))
+
+	// We want to force an illegal instruction, to get a crash
+	// at a PC value != 0.
+	// Not all systems make the data section non-executable.
+	ill := make([]byte, 64)
+	switch runtime.GOARCH {
+	case "386", "amd64":
+		binary.LittleEndian.PutUint16(ill, 0x0b0f) // ud2
+	case "arm":
+		binary.LittleEndian.PutUint32(ill, 0xe7f000f0) // no name, but permanently undefined
+	case "arm64":
+		binary.LittleEndian.PutUint32(ill, 0xd4207d00) // brk #1000
+	case "ppc64":
+		binary.BigEndian.PutUint32(ill, 0x7fe00008) // trap
+	case "ppc64le":
+		binary.LittleEndian.PutUint32(ill, 0x7fe00008) // trap
+	case "mips64":
+		binary.BigEndian.PutUint32(ill, 0x00000034) // trap
+	case "mips64le":
+		binary.LittleEndian.PutUint32(ill, 0x00000034) // trap
+	default:
+		// Just leave it as 0 and hope for the best.
+	}
+
+	f.x = uintptr(unsafe.Pointer(&ill[0]))
 	fn := *(*func())(unsafe.Pointer(&f))
 	fn()
 }
diff --git a/test/fixedbugs/issue11699.go b/test/fixedbugs/issue11699.go
new file mode 100644
index 0000000..965c87f
--- /dev/null
+++ b/test/fixedbugs/issue11699.go
@@ -0,0 +1,12 @@
+// compile
+
+// Copyright 2015 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 11699; used to fail with duplicate _.args_stackmap symbols.
+
+package p
+
+func _()
+func _()
diff --git a/test/fixedbugs/issue11737.go b/test/fixedbugs/issue11737.go
new file mode 100644
index 0000000..01ef096
--- /dev/null
+++ b/test/fixedbugs/issue11737.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2015 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 11737 - invalid == not being caught until generated switch code was compiled
+
+package p
+
+func f()
+
+func s(x interface{}) {
+	switch x {
+	case f: // ERROR "invalid case f \(type func\(\)\) in switch \(incomparable type\)"
+	}
+}
diff --git a/test/fixedbugs/issue12006.go b/test/fixedbugs/issue12006.go
new file mode 100644
index 0000000..01dced3
--- /dev/null
+++ b/test/fixedbugs/issue12006.go
@@ -0,0 +1,174 @@
+// errorcheck -0 -m -l
+
+// Copyright 2015 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 escape analysis through ... parameters.
+
+package foo
+
+func FooN(vals ...*int) (s int) { // ERROR "FooN vals does not escape"
+	for _, v := range vals {
+		s += *v
+	}
+	return s
+}
+
+// Append forces heap allocation and copies entries in vals to heap, therefore they escape to heap.
+func FooNx(x *int, vals ...*int) (s int) { // ERROR "leaking param: x" "leaking param content: vals"
+	vals = append(vals, x)
+	return FooN(vals...)
+}
+
+var sink []*int
+
+func FooNy(x *int, vals ...*int) (s int) { // ERROR "leaking param: x" "leaking param: vals" "leaking param content: vals"
+	vals = append(vals, x)
+	sink = vals
+	return FooN(vals...)
+}
+
+func FooNz(vals ...*int) (s int) { // ERROR "leaking param: vals"
+	sink = vals
+	return FooN(vals...)
+}
+
+func TFooN() {
+	for i := 0; i < 1000; i++ {
+		var i, j int
+		FooN(&i, &j) // ERROR "TFooN &i does not escape" "TFooN &j does not escape" "TFooN ... argument does not escape"
+	}
+}
+
+func TFooNx() {
+	for i := 0; i < 1000; i++ {
+		var i, j, k int   // ERROR "moved to heap: i" "moved to heap: j" "moved to heap: k"
+		FooNx(&k, &i, &j) // ERROR "&k escapes to heap" "&i escapes to heap" "&j escapes to heap" "TFooNx ... argument does not escape"
+	}
+}
+
+func TFooNy() {
+	for i := 0; i < 1000; i++ {
+		var i, j, k int   // ERROR "moved to heap: i" "moved to heap: j" "moved to heap: k"
+		FooNy(&k, &i, &j) // ERROR "&i escapes to heap" "&j escapes to heap" "&k escapes to heap" "... argument escapes to heap"
+	}
+}
+
+func TFooNz() {
+	for i := 0; i < 1000; i++ {
+		var i, j int  // ERROR "moved to heap: i" "moved to heap: j"
+		FooNz(&i, &j) // ERROR "&i escapes to heap" "&j escapes to heap" "... argument escapes to heap"
+	}
+}
+
+var isink *int32
+
+func FooI(args ...interface{}) { // ERROR "leaking param content: args"
+	for i := 0; i < len(args); i++ {
+		switch x := args[i].(type) {
+		case nil:
+			println("is nil")
+		case int32:
+			println("is int32")
+		case *int32:
+			println("is *int32")
+			isink = x
+		case string:
+			println("is string")
+		}
+	}
+}
+
+func TFooI() {
+	a := int32(1) // ERROR "moved to heap: a"
+	b := "cat"
+	c := &a       // ERROR "&a escapes to heap"
+	FooI(a, b, c) // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooI ... argument does not escape"
+}
+
+func FooJ(args ...interface{}) *int32 { // ERROR "leaking param: args to result ~r1 level=1"
+	for i := 0; i < len(args); i++ {
+		switch x := args[i].(type) {
+		case nil:
+			println("is nil")
+		case int32:
+			println("is int32")
+		case *int32:
+			println("is *int32")
+			return x
+		case string:
+			println("is string")
+		}
+	}
+	return nil
+}
+
+func TFooJ1() {
+	a := int32(1)
+	b := "cat"
+	c := &a       // ERROR "TFooJ1 &a does not escape"
+	FooJ(a, b, c) // ERROR "TFooJ1 a does not escape" "TFooJ1 b does not escape" "TFooJ1 c does not escape" "TFooJ1 ... argument does not escape"
+}
+
+func TFooJ2() {
+	a := int32(1) // ERROR "moved to heap: a"
+	b := "cat"
+	c := &a               // ERROR "&a escapes to heap"
+	isink = FooJ(a, b, c) // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooJ2 ... argument does not escape"
+}
+
+type fakeSlice struct {
+	l int
+	a *[4]interface{}
+}
+
+func FooK(args fakeSlice) *int32 { // ERROR "leaking param: args to result ~r1 level=1"
+	for i := 0; i < args.l; i++ {
+		switch x := (*args.a)[i].(type) {
+		case nil:
+			println("is nil")
+		case int32:
+			println("is int32")
+		case *int32:
+			println("is *int32")
+			return x
+		case string:
+			println("is string")
+		}
+	}
+	return nil
+}
+
+func TFooK2() {
+	a := int32(1) // ERROR "moved to heap: a"
+	b := "cat"
+	c := &a                                           // ERROR "&a escapes to heap"
+	fs := fakeSlice{3, &[4]interface{}{a, b, c, nil}} // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooK2 &\[4\]interface {} literal does not escape"
+	isink = FooK(fs)
+}
+
+func FooL(args []interface{}) *int32 { // ERROR "leaking param: args to result ~r1 level=1"
+	for i := 0; i < len(args); i++ {
+		switch x := args[i].(type) {
+		case nil:
+			println("is nil")
+		case int32:
+			println("is int32")
+		case *int32:
+			println("is *int32")
+			return x
+		case string:
+			println("is string")
+		}
+	}
+	return nil
+}
+
+func TFooL2() {
+	a := int32(1) // ERROR "moved to heap: a"
+	b := "cat"
+	c := &a                     // ERROR "&a escapes to heap"
+	s := []interface{}{a, b, c} // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooL2 \[\]interface {} literal does not escape"
+	isink = FooL(s)
+}
diff --git a/test/fixedbugs/issue12108.go b/test/fixedbugs/issue12108.go
new file mode 100644
index 0000000..c7a7425
--- /dev/null
+++ b/test/fixedbugs/issue12108.go
@@ -0,0 +1,37 @@
+// run
+
+// Copyright 2015 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.
+
+// A generated method with a return value large enough to be
+// initialized by duffzero is not a leaf method, which violated
+// assumptions made by cmd/internal/obj/ppc64.
+
+package main
+
+const N = 9 // values > 8 cause (Super).Method to use duffzero
+
+type Base struct {
+}
+
+func (b *Base) Method() (x [N]uintptr) {
+	return
+}
+
+type Super struct {
+	Base
+}
+
+type T interface {
+	Method() [N]uintptr
+}
+
+func f(q T) {
+	q.Method()
+}
+
+func main() {
+	var s Super
+	f(&s)
+}
diff --git a/test/fixedbugs/issue12133.go b/test/fixedbugs/issue12133.go
index 0b66c56..7b02a47 100644
--- a/test/fixedbugs/issue12133.go
+++ b/test/fixedbugs/issue12133.go
@@ -19,8 +19,8 @@ func main() {
 		panic("bad")
 	}
 }
+
+//go:noinline
 func f1(v1 uint) uint {
-	switch {
-	} // prevent inlining
 	return v1 >> ((1 >> v1) + (1 >> v1))
 }
diff --git a/test/fixedbugs/issue12411.go b/test/fixedbugs/issue12411.go
new file mode 100644
index 0000000..0a8b7c3
--- /dev/null
+++ b/test/fixedbugs/issue12411.go
@@ -0,0 +1,24 @@
+// +build !386
+// run
+
+// Copyright 2015 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 12411. Loss of AX during %.
+
+package main
+
+func main() {
+	x := f(4)
+	if x != 0 {
+		println("BUG: x=", x)
+	}
+}
+
+//go:noinline
+func f(x int) int {
+	// AX was live on entry to one of the % code generations,
+	// and the % code generation smashed it.
+	return ((2 * x) % 3) % (2 % ((x << 2) ^ (x % 3)))
+}
diff --git a/test/fixedbugs/issue12413.go b/test/fixedbugs/issue12413.go
new file mode 100644
index 0000000..a054765
--- /dev/null
+++ b/test/fixedbugs/issue12413.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2015 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 12413: invalid variable name x in type switch: code would fail
+// to compile if the variable used in the short variable declaration was
+// previously declared as a constant.
+
+package main
+
+func main() {
+	const x = 42
+	switch x := interface{}(nil).(type) {
+	default:
+		_ = x
+	}
+}
diff --git a/test/fixedbugs/issue12577.go b/test/fixedbugs/issue12577.go
new file mode 100644
index 0000000..249b4f2
--- /dev/null
+++ b/test/fixedbugs/issue12577.go
@@ -0,0 +1,66 @@
+// run
+
+// Copyright 2015 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 12577: Test that there are no -0 floating-point constants.
+
+package main
+
+import "math"
+
+const (
+	z0 = 0.0
+	z1 = -0.0
+	z2 = -z0
+	z3 = -z2
+)
+
+var (
+	x0 float32 = z0
+	x1 float32 = z1
+	x2 float32 = z2
+	x3 float32 = z3
+
+	y0 float64 = z0
+	y1 float64 = z1
+	y2 float64 = z2
+	y3 float64 = z3
+)
+
+func test32(f float32) {
+	if f != 0 || math.Signbit(float64(f)) {
+		println("BUG: got", f, "want 0.0")
+		return
+	}
+}
+
+func test64(f float64) {
+	if f != 0 || math.Signbit(f) {
+		println("BUG: got", f, "want 0.0")
+		return
+	}
+}
+
+func main() {
+	if f := -x0; f != 0 || !math.Signbit(float64(f)) {
+		println("BUG: got", f, "want -0.0")
+	}
+
+	test32(-0.0)
+	test32(x0)
+	test32(x1)
+	test32(x2)
+	test32(x3)
+
+	if f := -y0; f != 0 || !math.Signbit(f) {
+		println("BUG: got", f, "want -0.0")
+	}
+
+	test64(-0.0)
+	test64(y0)
+	test64(y1)
+	test64(y2)
+	test64(y3)
+}
diff --git a/test/fixedbugs/issue12588.go b/test/fixedbugs/issue12588.go
new file mode 100644
index 0000000..3022f48
--- /dev/null
+++ b/test/fixedbugs/issue12588.go
@@ -0,0 +1,88 @@
+// errorcheck -0 -m -l
+
+// Copyright 2015 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.
+
+// Tests escape analysis for range of arrays.
+// Compiles but need not run.  Inlining is disabled.
+
+package main
+
+type A struct {
+	b [3]uint64
+}
+
+type B struct {
+	b [3]*uint64
+}
+
+func f(a A) int {
+	for i, x := range &a.b { // ERROR "f &a.b does not escape"
+		if x != 0 {
+			return 64*i + int(x)
+		}
+	}
+	return 0
+}
+
+func g(a *A) int { // ERROR "g a does not escape"
+	for i, x := range &a.b { // ERROR "g &a.b does not escape"
+		if x != 0 {
+			return 64*i + int(x)
+		}
+	}
+	return 0
+}
+
+func h(a *B) *uint64 { // ERROR "leaking param: a to result ~r1 level=1"
+	for i, x := range &a.b { // ERROR "h &a.b does not escape"
+		if i == 0 {
+			return x
+		}
+	}
+	return nil
+}
+
+func h2(a *B) *uint64 { // ERROR "leaking param: a to result ~r1 level=1"
+	p := &a.b // ERROR "h2 &a.b does not escape"
+	for i, x := range p {
+		if i == 0 {
+			return x
+		}
+	}
+	return nil
+}
+
+// Seems like below should be level=1, not 0.
+func k(a B) *uint64 { // ERROR "leaking param: a to result ~r1 level=0"
+	for i, x := range &a.b { // ERROR "k &a.b does not escape"
+		if i == 0 {
+			return x
+		}
+	}
+	return nil
+}
+
+var sink *uint64
+
+func main() {
+	var a1, a2 A
+	var b1, b2, b3, b4 B
+	var x1, x2, x3, x4 uint64 // ERROR "moved to heap: x1" "moved to heap: x3"
+	b1.b[0] = &x1             // ERROR "&x1 escapes to heap"
+	b2.b[0] = &x2             // ERROR "main &x2 does not escape"
+	b3.b[0] = &x3             // ERROR "&x3 escapes to heap"
+	b4.b[0] = &x4             // ERROR "main &x4 does not escape"
+	f(a1)
+	g(&a2)         // ERROR "main &a2 does not escape"
+	sink = h(&b1)  // ERROR "main &b1 does not escape"
+	h(&b2)         // ERROR "main &b2 does not escape"
+	sink = h2(&b1) // ERROR "main &b1 does not escape"
+	h2(&b4)        // ERROR "main &b4 does not escape"
+	x1 = 17
+	println("*sink=", *sink) // Verify that sink addresses x1
+	x3 = 42
+	sink = k(b3)
+	println("*sink=", *sink) // Verify that sink addresses x3
+}
diff --git a/test/fixedbugs/issue12677.dir/p.go b/test/fixedbugs/issue12677.dir/p.go
new file mode 100644
index 0000000..e395071
--- /dev/null
+++ b/test/fixedbugs/issue12677.dir/p.go
@@ -0,0 +1,8 @@
+// Copyright 2015 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 p
+func Baz(f int) float64 {
+    return 1 / float64(int(1)<<(uint(f)))
+}
diff --git a/test/fixedbugs/issue12677.dir/q.go b/test/fixedbugs/issue12677.dir/q.go
new file mode 100644
index 0000000..fd39c8a
--- /dev/null
+++ b/test/fixedbugs/issue12677.dir/q.go
@@ -0,0 +1,7 @@
+// Copyright 2015 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 q
+import "./p"
+func f() { println(p.Baz(2)) }
diff --git a/test/fixedbugs/issue12677.go b/test/fixedbugs/issue12677.go
new file mode 100644
index 0000000..6ad7161
--- /dev/null
+++ b/test/fixedbugs/issue12677.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// Copyright 2015 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 12677: Type loss during export/import of inlined function body.
+
+package ignored
diff --git a/test/fixedbugs/issue12944.go b/test/fixedbugs/issue12944.go
new file mode 100644
index 0000000..59379f1
--- /dev/null
+++ b/test/fixedbugs/issue12944.go
@@ -0,0 +1,13 @@
+// errorcheck
+
+// Copyright 2015 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 "unsafe"
+
+const (
+	_ = unsafe.Sizeof([0]byte{}[0]) // ERROR "out of bounds"
+)
diff --git a/test/fixedbugs/issue13169.go b/test/fixedbugs/issue13169.go
new file mode 100644
index 0000000..77767cd
--- /dev/null
+++ b/test/fixedbugs/issue13169.go
@@ -0,0 +1,49 @@
+// run
+
+// Copyright 2015 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
+
+type T struct {
+	a, b, c int
+}
+
+func usestack() {
+	usestack1(32)
+}
+func usestack1(d int) byte {
+	if d == 0 {
+		return 0
+	}
+	var b [1024]byte
+	usestack1(d - 1)
+	return b[3]
+}
+
+const n = 100000
+
+func main() {
+	c := make(chan interface{})
+	done := make(chan bool)
+
+	for i := 0; i < 10; i++ {
+		go func() {
+			for j := 0; j < n; j++ {
+				c <- new(T)
+			}
+			done <- true
+		}()
+		go func() {
+			for j := 0; j < n; j++ {
+				_ = (<-c).(*T)
+				usestack()
+			}
+			done <- true
+		}()
+	}
+	for i := 0; i < 20; i++ {
+		<-done
+	}
+}
diff --git a/test/fixedbugs/issue13171.go b/test/fixedbugs/issue13171.go
new file mode 100644
index 0000000..5d127a5
--- /dev/null
+++ b/test/fixedbugs/issue13171.go
@@ -0,0 +1,34 @@
+// run
+
+// Copyright 2015 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
+
+// Make sure the compiler knows that DUFFCOPY clobbers X0
+
+import "fmt"
+
+//go:noinline
+func f(x float64) float64 {
+	// y is allocated to X0
+	y := x + 5
+	// marshals z before y.  Marshalling z
+	// calls DUFFCOPY.
+	return g(z, y)
+}
+
+//go:noinline
+func g(b [64]byte, y float64) float64 {
+	return y
+}
+
+var z [64]byte
+
+func main() {
+	got := f(5)
+	if got != 10 {
+		panic(fmt.Sprintf("want 10, got %f", got))
+	}
+}
diff --git a/test/fixedbugs/issue13248.go b/test/fixedbugs/issue13248.go
new file mode 100644
index 0000000..d01b823
--- /dev/null
+++ b/test/fixedbugs/issue13248.go
@@ -0,0 +1,13 @@
+// errorcheck
+
+// Copyright 2015 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 caused an infinite loop with the recursive-descent parser.
+
+package main
+
+func main() {
+    foo(
+} // ERROR "unexpected }"
diff --git a/test/fixedbugs/issue13261.go b/test/fixedbugs/issue13261.go
new file mode 100644
index 0000000..c73062c
--- /dev/null
+++ b/test/fixedbugs/issue13261.go
@@ -0,0 +1,29 @@
+// compile
+
+// Copyright 2015 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.
+
+// Taking the address of a parenthesized composite literal is permitted.
+
+package main
+
+type T struct{}
+
+func main() {
+	_ = &T{}
+	_ = &(T{})
+	_ = &((T{}))
+
+	_ = &struct{}{}
+	_ = &(struct{}{})
+	_ = &((struct{}{}))
+
+	switch (&T{}) {}
+	switch &(T{}) {}
+	switch &((T{})) {}
+
+	switch &struct{}{} {}
+	switch &(struct{}{}) {}
+	switch &((struct{}{})) {}
+}
diff --git a/test/fixedbugs/issue13266.go b/test/fixedbugs/issue13266.go
new file mode 100644
index 0000000..3c4f74b
--- /dev/null
+++ b/test/fixedbugs/issue13266.go
@@ -0,0 +1,10 @@
+// errorcheck
+
+// Copyright 2015 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.
+
+// Offending character % must not be interpreted as
+// start of format verb when emitting error message.
+
+package% // ERROR "unexpected %"
diff --git a/test/fixedbugs/issue13268.go b/test/fixedbugs/issue13268.go
new file mode 100644
index 0000000..2a063fa
--- /dev/null
+++ b/test/fixedbugs/issue13268.go
@@ -0,0 +1,48 @@
+// run
+
+// Copyright 2015 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 error message when EOF is encountered in the
+// middle of a BOM.
+//
+// Since the error requires an EOF, we cannot use the
+// errorcheckoutput mechanism.
+
+package main
+
+import (
+	"io/ioutil"
+	"log"
+	"os"
+	"os/exec"
+	"runtime"
+	"strings"
+)
+
+func main() {
+	// cannot use temp file on nacl via child process
+	if runtime.GOOS == "nacl" {
+		return
+	}
+
+	// create source
+	f, err := ioutil.TempFile("", "issue13268-")
+	if err != nil {
+		log.Fatalf("could not create source file: %v", err)
+	}
+	f.Write([]byte("package p\n\nfunc \xef\xef")) // if this fails, we will die later
+	f.Close()
+	defer os.Remove(f.Name())
+
+	// compile and test output
+	cmd := exec.Command("go", "tool", "compile", f.Name())
+	out, err := cmd.CombinedOutput()
+	if err == nil {
+		log.Fatalf("expected cmd/compile to fail")
+	}
+	if strings.HasPrefix(string(out), "illegal UTF-8 sequence") {
+		log.Fatalf("error %q not found", out)
+	}
+}
diff --git a/test/fixedbugs/issue13273.go b/test/fixedbugs/issue13273.go
new file mode 100644
index 0000000..fa3815f
--- /dev/null
+++ b/test/fixedbugs/issue13273.go
@@ -0,0 +1,55 @@
+// errorcheck
+
+// Copyright 2015 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.
+
+// Check that we correctly construct (and report errors)
+// for unary expressions of the form <-x where we only
+// know after parsing x whether <-x is a receive operation
+// or a channel type.
+
+package n
+
+func f() {
+	// test case from issue 13273
+	<-chan int((chan int)(nil))
+
+	<-chan int(nil)
+	<-chan chan int(nil)
+	<-chan chan chan int(nil)
+	<-chan chan chan chan int(nil)
+	<-chan chan chan chan chan int(nil)
+
+	<-chan<-chan int(nil)
+	<-chan<-chan<-chan int(nil)
+	<-chan<-chan<-chan<-chan int(nil)
+	<-chan<-chan<-chan<-chan<-chan int(nil)
+
+	<-chan (<-chan int)(nil)
+	<-chan (<-chan (<-chan int))(nil)
+	<-chan (<-chan (<-chan (<-chan int)))(nil)
+	<-chan (<-chan (<-chan (<-chan (<-chan int))))(nil)
+
+	<-(<-chan int)(nil)
+	<-(<-chan chan int)(nil)
+	<-(<-chan chan chan int)(nil)
+	<-(<-chan chan chan chan int)(nil)
+	<-(<-chan chan chan chan chan int)(nil)
+
+	<-(<-chan<-chan int)(nil)
+	<-(<-chan<-chan<-chan int)(nil)
+	<-(<-chan<-chan<-chan<-chan int)(nil)
+	<-(<-chan<-chan<-chan<-chan<-chan int)(nil)
+
+	<-(<-chan (<-chan int))(nil)
+	<-(<-chan (<-chan (<-chan int)))(nil)
+	<-(<-chan (<-chan (<-chan (<-chan int))))(nil)
+	<-(<-chan (<-chan (<-chan (<-chan (<-chan int)))))(nil)
+
+	type _ <-<-chan int // ERROR "unexpected <-, expecting chan"
+	<-<-chan int // ERROR "unexpected <-, expecting chan|expecting {" (new parser: same error as for type decl)
+
+	type _ <-chan<-int // ERROR "unexpected int, expecting chan|expecting chan"
+	<-chan<-int // ERROR "unexpected int, expecting chan|expecting {" (new parser: same error as for type decl)
+}
diff --git a/test/fixedbugs/issue13274.go b/test/fixedbugs/issue13274.go
new file mode 100644
index 0000000..a93c63f
--- /dev/null
+++ b/test/fixedbugs/issue13274.go
@@ -0,0 +1,11 @@
+// errorcheck
+
+// Copyright 2015 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.
+
+// Check that we don't ignore EOF.
+
+package p
+
+var f = func() { // ERROR "unexpected EOF"
\ No newline at end of file
diff --git a/test/fixedbugs/issue13319.go b/test/fixedbugs/issue13319.go
new file mode 100644
index 0000000..fc35870
--- /dev/null
+++ b/test/fixedbugs/issue13319.go
@@ -0,0 +1,18 @@
+// errorcheck
+
+// Copyright 2015 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
+
+func f(int, int) {
+    switch x {
+    case 1:
+        f(1, g()   // ERROR "expecting \)|expecting comma or \)"
+    case 2:
+        f()
+    case 3:
+        f(1, g()   // ERROR "expecting \)|expecting comma or \)"
+    }
+}
diff --git a/test/fixedbugs/issue13365.go b/test/fixedbugs/issue13365.go
new file mode 100644
index 0000000..379f9b6
--- /dev/null
+++ b/test/fixedbugs/issue13365.go
@@ -0,0 +1,25 @@
+// errorcheck
+
+// Copyright 2015 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 13365: confusing error message (array vs slice)
+
+package main
+
+var t struct{}
+
+func main() {
+	_ = []int{-1: 0}    // ERROR "index must be non\-negative integer constant"
+	_ = [10]int{-1: 0}  // ERROR "index must be non\-negative integer constant"
+	_ = [...]int{-1: 0} // ERROR "index must be non\-negative integer constant"
+
+	_ = []int{100: 0}
+	_ = [10]int{100: 0} // ERROR "array index 100 out of bounds"
+	_ = [...]int{100: 0}
+
+	_ = []int{t}    // ERROR "cannot use .* as type int in array or slice literal"
+	_ = [10]int{t}  // ERROR "cannot use .* as type int in array or slice literal"
+	_ = [...]int{t} // ERROR "cannot use .* as type int in array or slice literal"
+}
diff --git a/test/fixedbugs/issue13415.go b/test/fixedbugs/issue13415.go
new file mode 100644
index 0000000..989a1ed
--- /dev/null
+++ b/test/fixedbugs/issue13415.go
@@ -0,0 +1,19 @@
+// errorcheck
+
+// Copyright 2015 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.
+
+// Verify that error message regarding := appears on
+// correct line (and not on the line of the 2nd :=).
+
+package p
+
+func f() {
+    select {
+    case x, x := <-func() chan int { // ERROR "x repeated on left side of :="
+            c := make(chan int)
+            return c
+    }():
+    }
+}
diff --git a/test/fixedbugs/issue13471.go b/test/fixedbugs/issue13471.go
new file mode 100644
index 0000000..eee4081
--- /dev/null
+++ b/test/fixedbugs/issue13471.go
@@ -0,0 +1,25 @@
+// errorcheck
+
+// Copyright 2015 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.
+
+// Tests for golang.org/issue/13471
+
+package main
+
+func main() {
+	const _ int64 = 1e646456992 // ERROR "1e\+646456992 overflows integer"
+	const _ int32 = 1e64645699  // ERROR "1e\+64645699 overflows integer"
+	const _ int16 = 1e6464569   // ERROR "1e\+6464569 overflows integer"
+	const _ int8 = 1e646456     // ERROR "1e\+646456 overflows integer"
+	const _ int = 1e64645       // ERROR "1e\+64645 overflows integer"
+
+	const _ uint64 = 1e646456992 // ERROR "1e\+646456992 overflows integer"
+	const _ uint32 = 1e64645699  // ERROR "1e\+64645699 overflows integer"
+	const _ uint16 = 1e6464569   // ERROR "1e\+6464569 overflows integer"
+	const _ uint8 = 1e646456     // ERROR "1e\+646456 overflows integer"
+	const _ uint = 1e64645       // ERROR "1e\+64645 overflows integer"
+
+	const _ rune = 1e64645 // ERROR "1e\+64645 overflows integer"
+}
diff --git a/test/fixedbugs/issue13480.go b/test/fixedbugs/issue13480.go
new file mode 100644
index 0000000..cd2f05d
--- /dev/null
+++ b/test/fixedbugs/issue13480.go
@@ -0,0 +1,38 @@
+// errorcheck
+
+// Copyright 2015 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.
+
+// Verify that comparisons of slice/map/func values against converted nil
+// values are properly rejected.
+
+package p
+
+func bug() {
+	type S []byte
+	type M map[int]int
+	type F func()
+
+	var s S
+	var m M
+	var f F
+
+	_ = s == S(nil) // ERROR "compare.*to nil"
+	_ = S(nil) == s // ERROR "compare.*to nil"
+	switch s {
+	case S(nil): // ERROR "compare.*to nil"
+	}
+
+	_ = m == M(nil) // ERROR "compare.*to nil"
+	_ = M(nil) == m // ERROR "compare.*to nil"
+	switch m {
+	case M(nil): // ERROR "compare.*to nil"
+	}
+
+	_ = f == F(nil) // ERROR "compare.*to nil"
+	_ = F(nil) == f // ERROR "compare.*to nil"
+	switch f {
+	case F(nil): // ERROR "compare.*to nil"
+	}
+}
diff --git a/test/fixedbugs/issue13539.go b/test/fixedbugs/issue13539.go
new file mode 100644
index 0000000..72c3ab0
--- /dev/null
+++ b/test/fixedbugs/issue13539.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2015 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.
+
+// Verify that a label named like a package is recognized
+// as a label rather than a package and that the package
+// remains unused.
+
+package main
+
+import "math" // ERROR "imported and not used"
+
+func main() {
+math:
+	for {
+		break math
+	}
+}
diff --git a/test/fixedbugs/issue13559.go b/test/fixedbugs/issue13559.go
new file mode 100644
index 0000000..4783c62
--- /dev/null
+++ b/test/fixedbugs/issue13559.go
@@ -0,0 +1,89 @@
+// errorcheck
+
+// Copyright 2015 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.
+
+// Verify that error messages print meaningful values
+// for various extreme floating-point constants.
+
+package p
+
+// failure case in issue
+const _ int64 = 1e-10000 // ERROR "1e\-10000 truncated"
+
+const (
+	_ int64 = 1e10000000 // ERROR "1e\+10000000 overflows"
+	_ int64 = 1e1000000  // ERROR "1e\+1000000 overflows"
+	_ int64 = 1e100000   // ERROR "1e\+100000 overflows"
+	_ int64 = 1e10000    // ERROR "1e\+10000 overflows"
+	_ int64 = 1e1000     // ERROR "1e\+1000 overflows"
+	_ int64 = 1e100      // ERROR "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 overflows"
+	_ int64 = 1e10
+	_ int64 = 1e1
+	_ int64 = 1e0
+	_ int64 = 1e-1       // ERROR "0\.1 truncated"
+	_ int64 = 1e-10      // ERROR "1e\-10 truncated"
+	_ int64 = 1e-100     // ERROR "1e\-100 truncated"
+	_ int64 = 1e-1000    // ERROR "1e\-1000 truncated"
+	_ int64 = 1e-10000   // ERROR "1e\-10000 truncated"
+	_ int64 = 1e-100000  // ERROR "1e\-100000 truncated"
+	_ int64 = 1e-1000000 // ERROR "1e\-1000000 truncated"
+)
+
+const (
+	_ int64 = -1e10000000 // ERROR "\-1e\+10000000 overflows"
+	_ int64 = -1e1000000  // ERROR "\-1e\+1000000 overflows"
+	_ int64 = -1e100000   // ERROR "\-1e\+100000 overflows"
+	_ int64 = -1e10000    // ERROR "\-1e\+10000 overflows"
+	_ int64 = -1e1000     // ERROR "\-1e\+1000 overflows"
+	_ int64 = -1e100      // ERROR "\-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 overflows"
+	_ int64 = -1e10
+	_ int64 = -1e1
+	_ int64 = -1e0
+	_ int64 = -1e-1       // ERROR "\-0\.1 truncated"
+	_ int64 = -1e-10      // ERROR "\-1e\-10 truncated"
+	_ int64 = -1e-100     // ERROR "\-1e\-100 truncated"
+	_ int64 = -1e-1000    // ERROR "\-1e\-1000 truncated"
+	_ int64 = -1e-10000   // ERROR "\-1e\-10000 truncated"
+	_ int64 = -1e-100000  // ERROR "\-1e\-100000 truncated"
+	_ int64 = -1e-1000000 // ERROR "\-1e\-1000000 truncated"
+)
+
+const (
+	_ int64 = 1.23456789e10000000 // ERROR "1\.23457e\+10000000 overflows"
+	_ int64 = 1.23456789e1000000  // ERROR "1\.23457e\+1000000 overflows"
+	_ int64 = 1.23456789e100000   // ERROR "1\.23457e\+100000 overflows"
+	_ int64 = 1.23456789e10000    // ERROR "1\.23457e\+10000 overflows"
+	_ int64 = 1.23456789e1000     // ERROR "1\.23457e\+1000 overflows"
+	_ int64 = 1.23456789e100      // ERROR "12345678900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 overflows"
+	_ int64 = 1.23456789e10
+	_ int64 = 1.23456789e1        // ERROR "12\.3457 truncated"
+	_ int64 = 1.23456789e0        // ERROR "1\.23457 truncated"
+	_ int64 = 1.23456789e-1       // ERROR "0\.123457 truncated"
+	_ int64 = 1.23456789e-10      // ERROR "1\.23457e\-10 truncated"
+	_ int64 = 1.23456789e-100     // ERROR "1\.23457e\-100 truncated"
+	_ int64 = 1.23456789e-1000    // ERROR "1\.23457e\-1000 truncated"
+	_ int64 = 1.23456789e-10000   // ERROR "1\.23457e\-10000 truncated"
+	_ int64 = 1.23456789e-100000  // ERROR "1\.23457e\-100000 truncated"
+	_ int64 = 1.23456789e-1000000 // ERROR "1\.23457e\-1000000 truncated"
+)
+
+const (
+	_ int64 = -1.23456789e10000000 // ERROR "\-1\.23457e\+10000000 overflows"
+	_ int64 = -1.23456789e1000000  // ERROR "\-1\.23457e\+1000000 overflows"
+	_ int64 = -1.23456789e100000   // ERROR "\-1\.23457e\+100000 overflows"
+	_ int64 = -1.23456789e10000    // ERROR "\-1\.23457e\+10000 overflows"
+	_ int64 = -1.23456789e1000     // ERROR "\-1\.23457e\+1000 overflows"
+	_ int64 = -1.23456789e100      // ERROR "\-12345678900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 overflows"
+	_ int64 = -1.23456789e10
+	_ int64 = -1.23456789e1        // ERROR "\-12\.3457 truncated"
+	_ int64 = -1.23456789e0        // ERROR "\-1\.23457 truncated"
+	_ int64 = -1.23456789e-1       // ERROR "\-0\.123457 truncated"
+	_ int64 = -1.23456789e-10      // ERROR "\-1\.23457e\-10 truncated"
+	_ int64 = -1.23456789e-100     // ERROR "\-1\.23457e\-100 truncated"
+	_ int64 = -1.23456789e-1000    // ERROR "\-1\.23457e\-1000 truncated"
+	_ int64 = -1.23456789e-10000   // ERROR "\-1\.23457e\-10000 truncated"
+	_ int64 = -1.23456789e-100000  // ERROR "\-1\.23457e\-100000 truncated"
+	_ int64 = -1.23456789e-1000000 // ERROR "\-1\.23457e\-1000000 truncated"
+)
diff --git a/test/fixedbugs/issue13587.go b/test/fixedbugs/issue13587.go
new file mode 100644
index 0000000..eea5502
--- /dev/null
+++ b/test/fixedbugs/issue13587.go
@@ -0,0 +1,19 @@
+// errorcheck -0 -l -d=wb
+
+// Copyright 2015 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 write barrier for implicit assignments to result parameters
+// that have escaped to the heap.
+
+package issue13587
+
+import "errors"
+
+func escape(p *error)
+
+func F() (err error) {
+	escape(&err)
+	return errors.New("error") // ERROR "write barrier"
+}
diff --git a/test/fixedbugs/issue13684.go b/test/fixedbugs/issue13684.go
new file mode 100644
index 0000000..eda92a3
--- /dev/null
+++ b/test/fixedbugs/issue13684.go
@@ -0,0 +1,17 @@
+// run
+
+// Copyright 2015 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.
+
+// Verify that a label name matching a constant name
+// is permitted.
+
+package main
+
+const labelname = 1
+
+func main() {
+	goto labelname
+labelname:
+}
diff --git a/test/fixedbugs/issue13777.dir/burnin.go b/test/fixedbugs/issue13777.dir/burnin.go
new file mode 100644
index 0000000..5125639
--- /dev/null
+++ b/test/fixedbugs/issue13777.dir/burnin.go
@@ -0,0 +1,19 @@
+package burnin
+
+type sendCmdFunc func(string)
+
+func sendCommand(c string) {}
+
+func NewSomething() {
+	// This works...
+	// var sendCmd sendCmdFunc
+	// sendCmd = sendCommand
+
+	// So does this...
+	//sendCmd := sendCmdFunc(sendCommand)
+
+	// This fails...
+	sendCmd := sendCommand
+
+	_ = sendCmd
+}
diff --git a/test/fixedbugs/issue13777.dir/main.go b/test/fixedbugs/issue13777.dir/main.go
new file mode 100644
index 0000000..2512b93
--- /dev/null
+++ b/test/fixedbugs/issue13777.dir/main.go
@@ -0,0 +1,11 @@
+// build
+
+package main
+
+import (
+	x "./burnin"
+)
+
+func main() {
+	x.NewSomething()
+}
diff --git a/test/fixedbugs/issue13777.go b/test/fixedbugs/issue13777.go
new file mode 100644
index 0000000..8f83c13
--- /dev/null
+++ b/test/fixedbugs/issue13777.go
@@ -0,0 +1,7 @@
+// rundir
+
+// Copyright 2015 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 ignored
diff --git a/test/fixedbugs/issue13799.go b/test/fixedbugs/issue13799.go
new file mode 100644
index 0000000..e1b96f7
--- /dev/null
+++ b/test/fixedbugs/issue13799.go
@@ -0,0 +1,190 @@
+// errorcheck -0 -m -l
+
+// Copyright 2015 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, using compiler diagnostic flags, that the escape analysis is working.
+// Compiles but does not run.  Inlining is disabled.
+// Registerization is disabled too (-N), which should
+// have no effect on escape analysis.
+
+package main
+
+import "fmt"
+
+func main() {
+	// Just run test over and over again. This main func is just for
+	// convenience; if test were the main func, we could also trigger
+	// the panic just by running the program over and over again
+	// (sometimes it takes 1 time, sometimes it takes ~4,000+).
+	for iter := 0; ; iter++ {
+		if iter%50 == 0 {
+			fmt.Println(iter) // ERROR "iter escapes to heap$" "main ... argument does not escape$"
+		}
+		test1(iter)
+		test2(iter)
+		test3(iter)
+		test4(iter)
+		test5(iter)
+		test6(iter)
+	}
+}
+
+func test1(iter int) {
+
+	const maxI = 500
+	m := make(map[int][]int) // ERROR "make\(map\[int\]\[\]int\) escapes to heap$"
+
+	// The panic seems to be triggered when m is modified inside a
+	// closure that is both recursively called and reassigned to in a
+	// loop.
+
+	// Cause of bug -- escape of closure failed to escape (shared) data structures
+	// of map.  Assign to fn declared outside of loop triggers escape of closure.
+	// Heap -> stack pointer eventually causes badness when stack reallocation
+	// occurs.
+
+	var fn func()               // ERROR "moved to heap: fn$"
+	for i := 0; i < maxI; i++ { // ERROR "moved to heap: i$"
+		// var fn func() // this makes it work, because fn stays off heap
+		j := 0        // ERROR "moved to heap: j$"
+		fn = func() { // ERROR "func literal escapes to heap$"
+			m[i] = append(m[i], 0) // ERROR "&i escapes to heap$"
+			if j < 25 {            // ERROR "&j escapes to heap$"
+				j++
+				fn() // ERROR "&fn escapes to heap$"
+			}
+		}
+		fn()
+	}
+
+	if len(m) != maxI {
+		panic(fmt.Sprintf("iter %d: maxI = %d, len(m) = %d", iter, maxI, len(m))) // ERROR "iter escapes to heap$" "len\(m\) escapes to heap$" "maxI escapes to heap$" "test1 ... argument does not escape$"
+	}
+}
+
+func test2(iter int) {
+
+	const maxI = 500
+	m := make(map[int][]int) // ERROR "test2 make\(map\[int\]\[\]int\) does not escape$"
+
+	// var fn func()
+	for i := 0; i < maxI; i++ {
+		var fn func() // this makes it work, because fn stays off heap
+		j := 0
+		fn = func() { // ERROR "test2 func literal does not escape$"
+			m[i] = append(m[i], 0)
+			if j < 25 {
+				j++
+				fn()
+			}
+		}
+		fn()
+	}
+
+	if len(m) != maxI {
+		panic(fmt.Sprintf("iter %d: maxI = %d, len(m) = %d", iter, maxI, len(m))) // ERROR "iter escapes to heap$" "len\(m\) escapes to heap$" "maxI escapes to heap$" "test2 ... argument does not escape$"
+	}
+}
+
+func test3(iter int) {
+
+	const maxI = 500
+	var x int // ERROR "moved to heap: x$"
+	m := &x   // ERROR "&x escapes to heap$"
+
+	var fn func() // ERROR "moved to heap: fn$"
+	for i := 0; i < maxI; i++ {
+		// var fn func() // this makes it work, because fn stays off heap
+		j := 0        // ERROR "moved to heap: j$"
+		fn = func() { // ERROR "func literal escapes to heap$"
+			if j < 100 { // ERROR "&j escapes to heap$"
+				j++
+				fn() // ERROR "&fn escapes to heap$"
+			} else {
+				*m = *m + 1
+			}
+		}
+		fn()
+	}
+
+	if *m != maxI {
+		panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "test3 ... argument does not escape$"
+	}
+}
+
+func test4(iter int) {
+
+	const maxI = 500
+	var x int
+	m := &x // ERROR "test4 &x does not escape$"
+
+	// var fn func()
+	for i := 0; i < maxI; i++ {
+		var fn func() // this makes it work, because fn stays off heap
+		j := 0
+		fn = func() { // ERROR "test4 func literal does not escape$"
+			if j < 100 {
+				j++
+				fn()
+			} else {
+				*m = *m + 1
+			}
+		}
+		fn()
+	}
+
+	if *m != maxI {
+		panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "test4 ... argument does not escape$"
+	}
+}
+
+type str struct {
+	m *int
+}
+
+func recur1(j int, s *str) { // ERROR "recur1 s does not escape"
+	if j < 100 {
+		j++
+		recur1(j, s)
+	} else {
+		*s.m++
+	}
+}
+
+func test5(iter int) {
+
+	const maxI = 500
+	var x int // ERROR "moved to heap: x$"
+	m := &x   // ERROR "&x escapes to heap$"
+
+	var fn *str
+	for i := 0; i < maxI; i++ {
+		// var fn *str // this makes it work, because fn stays off heap
+		fn = &str{m} // ERROR "&str literal escapes to heap"
+		recur1(0, fn)
+	}
+
+	if *m != maxI {
+		panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "test5 ... argument does not escape$"
+	}
+}
+
+func test6(iter int) {
+
+	const maxI = 500
+	var x int
+	m := &x // ERROR "&x does not escape$"
+
+	// var fn *str
+	for i := 0; i < maxI; i++ {
+		var fn *str  // this makes it work, because fn stays off heap
+		fn = &str{m} // ERROR "&str literal does not escape"
+		recur1(0, fn)
+	}
+
+	if *m != maxI {
+		panic(fmt.Sprintf("iter %d: maxI = %d, *m = %d", iter, maxI, *m)) // ERROR "\*m escapes to heap$" "iter escapes to heap$" "maxI escapes to heap$" "test6 ... argument does not escape$"
+	}
+}
diff --git a/test/fixedbugs/issue13821.go b/test/fixedbugs/issue13821.go
new file mode 100644
index 0000000..7d50248
--- /dev/null
+++ b/test/fixedbugs/issue13821.go
@@ -0,0 +1,15 @@
+// compile
+
+// Copyright 2015 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 13821.  Compiler rejected "bool(true)" as not a constant.
+
+package p
+
+const (
+	A = true
+	B = bool(A)
+	C = bool(true)
+)
diff --git a/test/fixedbugs/issue13821b.go b/test/fixedbugs/issue13821b.go
new file mode 100644
index 0000000..0950fde
--- /dev/null
+++ b/test/fixedbugs/issue13821b.go
@@ -0,0 +1,24 @@
+// errorcheck
+
+// Copyright 2015 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 13821.  Additional regress tests.
+
+package p
+
+type B bool
+type B2 bool
+
+var b B
+var b2 B2
+var x1 = b && 1 < 2 // x1 has type B, not ideal bool
+var x2 = 1 < 2 && b // x2 has type B, not ideal bool
+var x3 = b && b2    // ERROR "mismatched types B and B2"
+var x4 = x1 && b2   // ERROR "mismatched types B and B2"
+var x5 = x2 && b2   // ERROR "mismatched types B and B2"
+var x6 = b2 && x1   // ERROR "mismatched types B2 and B"
+var x7 = b2 && x2   // ERROR "mismatched types B2 and B"
+
+var x8 = b && !B2(true) // ERROR "mismatched types B and B2"
diff --git a/test/fixedbugs/issue14006.go b/test/fixedbugs/issue14006.go
new file mode 100644
index 0000000..b56ed73
--- /dev/null
+++ b/test/fixedbugs/issue14006.go
@@ -0,0 +1,64 @@
+// errorcheck
+
+// 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.
+
+// Literals that happen to resolve to named constants
+// may be used as label names (see issue 13684). Make
+// sure that other literals don't crash the compiler.
+
+package main
+
+const labelname = 1
+
+func main() {
+	goto labelname
+labelname:
+}
+
+func f() {
+	var x int
+	switch x {
+	case 1:
+		2:	// ERROR "unexpected :"
+	case 2:
+	}
+
+	switch x {
+	case 1:
+		2: ;	// ERROR "unexpected :"
+	case 2:
+	}
+
+	var y string
+	switch y {
+	case "foo":
+		"bar":	// ERROR "unexpected :"
+	case "bar":
+	}
+
+	switch y {
+	case "foo":
+		"bar": ;	// ERROR "unexpected :"
+	case "bar":
+	}
+
+	var z bool
+	switch {
+	case z:
+		labelname:	// ERROR "missing statement after label"
+	case false:
+	}
+
+	switch {
+	case z:
+		labelname:
+	}
+
+	switch {
+	case z:
+		labelname: ;
+	case false:
+	}
+}
\ No newline at end of file
diff --git a/test/fixedbugs/issue14010.go b/test/fixedbugs/issue14010.go
new file mode 100644
index 0000000..4fdbf76
--- /dev/null
+++ b/test/fixedbugs/issue14010.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// 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.
+
+// Verify that built-in types don't get printed with
+// (empty) package qualification.
+
+package main
+
+func main() {
+	true = false // ERROR "cannot assign to true"
+	byte = 0     // ERROR "not an expression" "cannot assign to byte"
+}
diff --git a/test/fixedbugs/issue14164.dir/a.go b/test/fixedbugs/issue14164.dir/a.go
new file mode 100644
index 0000000..bf03051
--- /dev/null
+++ b/test/fixedbugs/issue14164.dir/a.go
@@ -0,0 +1,47 @@
+// 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 a
+
+// F is an exported function, small enough to be inlined.
+// It defines a local interface with an unexported method
+// f, which will appear with a package-qualified method
+// name in the export data.
+func F(x interface{}) bool {
+	_, ok := x.(interface {
+		f()
+	})
+	return ok
+}
+
+// Like F but with the unexported interface method f
+// defined via an embedded interface t. The compiler
+// always flattens embedded interfaces so there should
+// be no difference between F and G. Alas, currently
+// G is not inlineable (at least via export data), so
+// the issue is moot, here.
+func G(x interface{}) bool {
+	type t0 interface {
+		f()
+	}
+	_, ok := x.(interface {
+		t0
+	})
+	return ok
+}
+
+// Like G but now the embedded interface is declared
+// at package level. This function is inlineable via
+// export data. The export data representation is like
+// for F.
+func H(x interface{}) bool {
+	_, ok := x.(interface {
+		t1
+	})
+	return ok
+}
+
+type t1 interface {
+	f()
+}
diff --git a/test/fixedbugs/issue14164.dir/main.go b/test/fixedbugs/issue14164.dir/main.go
new file mode 100644
index 0000000..bcc6a63
--- /dev/null
+++ b/test/fixedbugs/issue14164.dir/main.go
@@ -0,0 +1,12 @@
+// 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 main
+
+// Verify that we can import package "a" containing an inlineable
+// function F that declares a local interface with a non-exported
+// method f.
+import _ "./a"
+
+func main() {}
diff --git a/test/fixedbugs/issue14164.go b/test/fixedbugs/issue14164.go
new file mode 100644
index 0000000..5247599
--- /dev/null
+++ b/test/fixedbugs/issue14164.go
@@ -0,0 +1,7 @@
+// compiledir
+
+// 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.
+
+ignored
diff --git a/test/fixedbugs/issue14331.dir/a.go b/test/fixedbugs/issue14331.dir/a.go
new file mode 100644
index 0000000..1b7f853
--- /dev/null
+++ b/test/fixedbugs/issue14331.dir/a.go
@@ -0,0 +1,14 @@
+// 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 a
+
+var S struct {
+	Str string `tag`
+}
+
+func F() string {
+	v := S
+	return v.Str
+}
diff --git a/test/fixedbugs/issue14331.dir/b.go b/test/fixedbugs/issue14331.dir/b.go
new file mode 100644
index 0000000..7a0abb2
--- /dev/null
+++ b/test/fixedbugs/issue14331.dir/b.go
@@ -0,0 +1,11 @@
+// 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 b
+
+import "./a"
+
+func G() string {
+	return a.F()
+}
diff --git a/test/fixedbugs/issue14331.go b/test/fixedbugs/issue14331.go
new file mode 100644
index 0000000..32f3e51
--- /dev/null
+++ b/test/fixedbugs/issue14331.go
@@ -0,0 +1,9 @@
+// compiledir
+
+// 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.
+
+// Inline function misses struct tags.
+
+package ignored
diff --git a/test/fixedbugs/issue4468.go b/test/fixedbugs/issue4468.go
index ef0b46b..f882105 100644
--- a/test/fixedbugs/issue4468.go
+++ b/test/fixedbugs/issue4468.go
@@ -19,8 +19,12 @@ type S struct {
 }
 
 func F() {
-	go (F())	// ERROR "must be function call"
-	defer (F())	// ERROR "must be function call"
+	go F            // ERROR "must be function call"
+	defer F         // ERROR "must be function call"
+	go (F)		// ERROR "must be function call|must not be parenthesized"
+	defer (F)	// ERROR "must be function call|must not be parenthesized"
+	go (F())	// ERROR "must be function call|must not be parenthesized"
+	defer (F())	// ERROR "must be function call|must not be parenthesized"
 	var s S
 	(&s.t).F()
 	go (&s.t).F()
diff --git a/test/fixedbugs/issue4518.go b/test/fixedbugs/issue4518.go
index e64b069..5c3a178 100644
--- a/test/fixedbugs/issue4518.go
+++ b/test/fixedbugs/issue4518.go
@@ -10,15 +10,13 @@
 
 package main
 
-func DontInline() {}
-
+//go:noinline
 func F(e interface{}) (int, int) {
-	DontInline()
 	return 3, 7
 }
 
+//go:noinline
 func G() (int, int) {
-	DontInline()
 	return 3, 7
 }
 
diff --git a/test/fixedbugs/issue4964.dir/a.go b/test/fixedbugs/issue4964.dir/a.go
index 2b9e44e..216f352 100644
--- a/test/fixedbugs/issue4964.dir/a.go
+++ b/test/fixedbugs/issue4964.dir/a.go
@@ -10,16 +10,14 @@ type T struct {
 	Pointer *int
 }
 
-func dontinline() {}
-
+//go:noinline
 func Store(t *T) {
 	global = t.Pointer
-	dontinline()
 }
 
+//go:noinline
 func Store2(t *T) {
 	global2 = t.Pointer
-	dontinline()
 }
 
 func Get() *int {
diff --git a/test/fixedbugs/issue5957.dir/c.go b/test/fixedbugs/issue5957.dir/c.go
index a1781d4..d115eac 100644
--- a/test/fixedbugs/issue5957.dir/c.go
+++ b/test/fixedbugs/issue5957.dir/c.go
@@ -2,7 +2,7 @@ package p
 
 import (
 	"./a" // ERROR "imported and not used: \x22a\x22 as surprise|imported and not used: surprise"
-	"./b" // GC_ERROR "imported and not used: \x22b\x22 as surprise2|imported and not used: surprise2"
+	"./b" // ERROR "imported and not used: \x22b\x22 as surprise2|imported and not used: surprise2"
 	b "./b" // ERROR "imported and not used: \x22b\x22$|imported and not used: surprise2"
 	foo "math" // ERROR "imported and not used: \x22math\x22 as foo|imported and not used: math"
 	"fmt" // actually used
diff --git a/test/fixedbugs/issue7150.go b/test/fixedbugs/issue7150.go
index 264958a..05e8d75 100644
--- a/test/fixedbugs/issue7150.go
+++ b/test/fixedbugs/issue7150.go
@@ -9,9 +9,9 @@
 package main
 
 func main() {
-	_ = [0]int{-1: 50}              // ERROR "array index must be non-negative integer constant"
-	_ = [0]int{0: 0}                // ERROR "array index 0 out of bounds \[0:0\]"
-	_ = [0]int{5: 25}               // ERROR "array index 5 out of bounds \[0:0\]"
-	_ = [10]int{2: 10, 15: 30}      // ERROR "array index 15 out of bounds \[0:10\]"
-	_ = [10]int{5: 5, 1: 1, 12: 12} // ERROR "array index 12 out of bounds \[0:10\]"
+	_ = [0]int{-1: 50}              // ERROR "index must be non-negative integer constant"
+	_ = [0]int{0: 0}                // ERROR "index 0 out of bounds \[0:0\]"
+	_ = [0]int{5: 25}               // ERROR "index 5 out of bounds \[0:0\]"
+	_ = [10]int{2: 10, 15: 30}      // ERROR "index 15 out of bounds \[0:10\]"
+	_ = [10]int{5: 5, 1: 1, 12: 12} // ERROR "index 12 out of bounds \[0:10\]"
 }
diff --git a/test/fixedbugs/issue7153.go b/test/fixedbugs/issue7153.go
index d70d858..f238f78 100644
--- a/test/fixedbugs/issue7153.go
+++ b/test/fixedbugs/issue7153.go
@@ -8,4 +8,4 @@
 
 package p
 
-var _ = []int{a: true, true} // ERROR "undefined: a" "cannot use true \(type bool\) as type int in array element"
+var _ = []int{a: true, true} // ERROR "undefined: a" "cannot use true \(type bool\) as type int in array or slice literal"
diff --git a/test/fixedbugs/issue7995b.dir/x1.go b/test/fixedbugs/issue7995b.dir/x1.go
index 075911b..bafecf5 100644
--- a/test/fixedbugs/issue7995b.dir/x1.go
+++ b/test/fixedbugs/issue7995b.dir/x1.go
@@ -4,12 +4,8 @@ import "fmt"
 
 var P int
 
-var b bool
-
+//go:noinline
 func F(x *int) string {
-	if b { // avoid inlining
-		F(x)
-	}
 	P = 50
 	*x = 100
 	return fmt.Sprintln(P, *x)
diff --git a/test/fixedbugs/issue8036.go b/test/fixedbugs/issue8036.go
index f32fde8..f052cf9 100644
--- a/test/fixedbugs/issue8036.go
+++ b/test/fixedbugs/issue8036.go
@@ -18,19 +18,19 @@ type T struct {
 
 type TI [3]uintptr
 
+//go:noinline
 func G() (t TI) {
 	t[0] = 1
 	t[1] = 2
 	t[2] = 3
-	runtime.GC() // prevent inlining
 	return
 }
 
+//go:noinline
 func F() (t T) {
 	t.X = newint()
 	t.Y = t.X
 	t.Z = t.Y
-	runtime.GC() // prevent inlining
 	return
 }
 
diff --git a/test/func8.go b/test/func8.go
index 1305180..09ca020 100644
--- a/test/func8.go
+++ b/test/func8.go
@@ -21,16 +21,14 @@ func g() int {
 
 var xy string
 
+//go:noinline
 func x() bool {
-	for false {
-	} // no inlining
 	xy += "x"
 	return false
 }
 
+//go:noinline
 func y() string {
-	for false {
-	} // no inlining
 	xy += "y"
 	return "abc"
 }
diff --git a/test/heapsampling.go b/test/heapsampling.go
new file mode 100644
index 0000000..c00b866
--- /dev/null
+++ b/test/heapsampling.go
@@ -0,0 +1,172 @@
+// run
+
+// Copyright 2009 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 heap sampling logic.
+
+package main
+
+import (
+	"fmt"
+	"math"
+	"runtime"
+)
+
+var a16 *[16]byte
+var a512 *[512]byte
+var a256 *[256]byte
+var a1k *[1024]byte
+var a64k *[64 * 1024]byte
+
+// This test checks that heap sampling produces reasonable
+// results. Note that heap sampling uses randomization, so the results
+// vary for run to run. This test only checks that the resulting
+// values appear reasonable.
+func main() {
+	const countInterleaved = 10000
+	allocInterleaved(countInterleaved)
+	checkAllocations(getMemProfileRecords(), "main.allocInterleaved", countInterleaved, []int64{256 * 1024, 1024, 256 * 1024, 512, 256 * 1024, 256})
+
+	const count = 100000
+	alloc(count)
+	checkAllocations(getMemProfileRecords(), "main.alloc", count, []int64{1024, 512, 256})
+}
+
+// allocInterleaved stress-tests the heap sampling logic by
+// interleaving large and small allocations.
+func allocInterleaved(n int) {
+	for i := 0; i < n; i++ {
+		// Test verification depends on these lines being contiguous.
+		a64k = new([64 * 1024]byte)
+		a1k = new([1024]byte)
+		a64k = new([64 * 1024]byte)
+		a512 = new([512]byte)
+		a64k = new([64 * 1024]byte)
+		a256 = new([256]byte)
+	}
+}
+
+// alloc performs only small allocations for sanity testing.
+func alloc(n int) {
+	for i := 0; i < n; i++ {
+		// Test verification depends on these lines being contiguous.
+		a1k = new([1024]byte)
+		a512 = new([512]byte)
+		a256 = new([256]byte)
+	}
+}
+
+// checkAllocations validates that the profile records collected for
+// the named function are consistent with count contiguous allocations
+// of the specified sizes.
+func checkAllocations(records []runtime.MemProfileRecord, fname string, count int64, size []int64) {
+	a := allocObjects(records, fname)
+	firstLine := 0
+	for ln := range a {
+		if firstLine == 0 || firstLine > ln {
+			firstLine = ln
+		}
+	}
+	var totalcount int64
+	for i, w := range size {
+		ln := firstLine + i
+		s := a[ln]
+		checkValue(fname, ln, "objects", count, s.objects)
+		checkValue(fname, ln, "bytes", count*w, s.bytes)
+		totalcount += s.objects
+	}
+	// Check the total number of allocations, to ensure some sampling occurred.
+	if totalwant := count * int64(len(size)); totalcount <= 0 || totalcount > totalwant*1024 {
+		panic(fmt.Sprintf("%s want total count > 0 && <= %d, got %d", fname, totalwant*1024, totalcount))
+	}
+}
+
+// checkValue checks an unsampled value against a range.
+func checkValue(fname string, ln int, name string, want, got int64) {
+	if got < 0 || got > 1024*want {
+		panic(fmt.Sprintf("%s:%d want %s >= 0 && <= %d, got %d", fname, ln, name, 1024*want, got))
+	}
+}
+
+func getMemProfileRecords() []runtime.MemProfileRecord {
+	// Force the runtime to update the object and byte counts.
+	// This can take up to two GC cycles to get a complete
+	// snapshot of the current point in time.
+	runtime.GC()
+	runtime.GC()
+
+	// Find out how many records there are (MemProfile(nil, true)),
+	// allocate that many records, and get the data.
+	// There's a race—more records might be added between
+	// the two calls—so allocate a few extra records for safety
+	// and also try again if we're very unlucky.
+	// The loop should only execute one iteration in the common case.
+	var p []runtime.MemProfileRecord
+	n, ok := runtime.MemProfile(nil, true)
+	for {
+		// Allocate room for a slightly bigger profile,
+		// in case a few more entries have been added
+		// since the call to MemProfile.
+		p = make([]runtime.MemProfileRecord, n+50)
+		n, ok = runtime.MemProfile(p, true)
+		if ok {
+			p = p[0:n]
+			break
+		}
+		// Profile grew; try again.
+	}
+	return p
+}
+
+type allocStat struct {
+	bytes, objects int64
+}
+
+// allocObjects examines the profile records for the named function
+// and returns the allocation stats aggregated by source line number.
+func allocObjects(records []runtime.MemProfileRecord, function string) map[int]allocStat {
+	a := make(map[int]allocStat)
+	for _, r := range records {
+		for _, s := range r.Stack0 {
+			if s == 0 {
+				break
+			}
+			if f := runtime.FuncForPC(s); f != nil {
+				name := f.Name()
+				_, line := f.FileLine(s)
+				if name == function {
+					allocStat := a[line]
+					allocStat.bytes += r.AllocBytes
+					allocStat.objects += r.AllocObjects
+					a[line] = allocStat
+				}
+			}
+		}
+	}
+	for line, stats := range a {
+		objects, bytes := scaleHeapSample(stats.objects, stats.bytes, int64(runtime.MemProfileRate))
+		a[line] = allocStat{bytes, objects}
+	}
+	return a
+}
+
+// scaleHeapSample unsamples heap allocations.
+// Taken from src/cmd/pprof/internal/profile/legacy_profile.go
+func scaleHeapSample(count, size, rate int64) (int64, int64) {
+	if count == 0 || size == 0 {
+		return 0, 0
+	}
+
+	if rate <= 1 {
+		// if rate==1 all samples were collected so no adjustment is needed.
+		// if rate<1 treat as unknown and skip scaling.
+		return count, size
+	}
+
+	avgSize := float64(size) / float64(count)
+	scale := 1 / (1 - math.Exp(-avgSize/float64(rate)))
+
+	return int64(float64(count) * scale), int64(float64(size) * scale)
+}
diff --git a/test/import4.dir/import4.go b/test/import4.dir/import4.go
index f92c663..b9f973f 100644
--- a/test/import4.dir/import4.go
+++ b/test/import4.dir/import4.go
@@ -18,7 +18,7 @@ import X "math"	// ERROR "imported and not used.*math"
 import . "bufio"	// ERROR "imported and not used.*bufio"
 
 // again, package without anything in it
-import "./empty"	// GC_ERROR "imported and not used.*empty"
-import Z "./empty"	// GC_ERROR "imported and not used.*empty"
+import "./empty"	// ERROR "imported and not used.*empty"
+import Z "./empty"	// ERROR "imported and not used.*empty"
 import . "./empty"	// ERROR "imported and not used.*empty"
 
diff --git a/test/initloop.go b/test/initloop.go
new file mode 100644
index 0000000..d90395d
--- /dev/null
+++ b/test/initloop.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2015 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.
+
+// Verify that initialization loops are caught
+// and that the errors print correctly.
+
+package main
+
+var (
+	x int = a
+	a int = b // ERROR "a refers to\n.*b refers to\n.*c refers to\n.*a"
+	b int = c
+	c int = a
+)
diff --git a/test/inline.go b/test/inline.go
index 54f7b3e..fb20fab 100644
--- a/test/inline.go
+++ b/test/inline.go
@@ -22,3 +22,12 @@ func add1(p unsafe.Pointer, x uintptr) unsafe.Pointer { // ERROR "can inline add
 func f(x *byte) *byte { // ERROR "can inline f" "leaking param: x to result"
 	return add2(x, 1) // ERROR "inlining call to add2" "inlining call to add1"
 }
+
+//go:noinline
+func g(x int) int {
+	return x + 1
+}
+
+func h(x int) int { // ERROR "can inline h"
+	return x + 2
+}
diff --git a/test/linkmain.go b/test/linkmain.go
new file mode 100644
index 0000000..dcfbf50
--- /dev/null
+++ b/test/linkmain.go
@@ -0,0 +1,12 @@
+// +build ignore
+
+// Copyright 2015 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.
+
+// For linkmain_run.go.
+
+package notmain
+
+func main() {
+}
diff --git a/test/linkmain_run.go b/test/linkmain_run.go
new file mode 100644
index 0000000..55de481
--- /dev/null
+++ b/test/linkmain_run.go
@@ -0,0 +1,66 @@
+// +build !nacl
+// run
+
+// 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.
+
+// Run the sinit test.
+
+package main
+
+import (
+	"fmt"
+	"os"
+	"os/exec"
+	"strings"
+)
+
+func cleanup() {
+	os.Remove("linkmain.o")
+	os.Remove("linkmain.a")
+	os.Remove("linkmain1.o")
+	os.Remove("linkmain1.a")
+	os.Remove("linkmain.exe")
+}
+
+func run(cmdline string) {
+	args := strings.Fields(cmdline)
+	cmd := exec.Command(args[0], args[1:]...)
+	out, err := cmd.CombinedOutput()
+	if err != nil {
+		fmt.Printf("$ %s\n", cmdline)
+		fmt.Println(string(out))
+		fmt.Println(err)
+		cleanup()
+		os.Exit(1)
+	}
+}
+
+func runFail(cmdline string) {
+	args := strings.Fields(cmdline)
+	cmd := exec.Command(args[0], args[1:]...)
+	out, err := cmd.CombinedOutput()
+	if err == nil {
+		fmt.Printf("$ %s\n", cmdline)
+		fmt.Println(string(out))
+		fmt.Println("SHOULD HAVE FAILED!")
+		cleanup()
+		os.Exit(1)
+	}
+}
+
+func main() {
+	// helloworld.go is package main
+	run("go tool compile -o linkmain.o helloworld.go")
+	run("go tool compile -pack -o linkmain.a helloworld.go")
+	run("go tool link -o linkmain.exe linkmain.o")
+	run("go tool link -o linkmain.exe linkmain.a")
+
+	// linkmain.go is not
+	run("go tool compile -o linkmain1.o linkmain.go")
+	run("go tool compile -pack -o linkmain1.a linkmain.go")
+	runFail("go tool link -o linkmain.exe linkmain1.o")
+	runFail("go tool link -o linkmain.exe linkmain1.a")
+	cleanup()
+}
diff --git a/test/live_syscall.go b/test/live_syscall.go
new file mode 100644
index 0000000..c9bf0f2
--- /dev/null
+++ b/test/live_syscall.go
@@ -0,0 +1,28 @@
+// errorcheck -0 -m -live
+
+// +build !windows
+
+// Copyright 2015 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 escape analysis and liveness inferred for syscall.Syscall-like functions.
+
+package p
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+func f(uintptr) // ERROR "f assuming arg#1 is unsafe uintptr"
+
+func g() {
+	var t int
+	f(uintptr(unsafe.Pointer(&t))) // ERROR "live at call to f: autotmp" "g &t does not escape"
+}
+
+func h() {
+	var v int
+	syscall.Syscall(0, 1, uintptr(unsafe.Pointer(&v)), 2) // ERROR "live at call to Syscall: autotmp" "h &v does not escape"
+}
diff --git a/test/nilptr3.go b/test/nilptr3.go
index 607c6fb..6c8aab3 100644
--- a/test/nilptr3.go
+++ b/test/nilptr3.go
@@ -1,7 +1,8 @@
 // errorcheck -0 -d=nil
 // Fails on ppc64x because of incomplete optimization.
 // See issues 9058.
-// +build !ppc64,!ppc64le
+// Same reason for mips64x.
+// +build !ppc64,!ppc64le,!mips64,!mips64le
 
 // Copyright 2013 The Go Authors.  All rights reserved.
 // Use of this source code is governed by a BSD-style
diff --git a/test/nosplit.go b/test/nosplit.go
index e5c2a9f..3c4ae10 100644
--- a/test/nosplit.go
+++ b/test/nosplit.go
@@ -115,10 +115,15 @@ main 132
 main 136
 
 # A nosplit leaf can use the whole 128-CallSize bytes available on entry.
-main 112 nosplit
-main 116 nosplit
-main 120 nosplit
-main 124 nosplit
+# (CallSize is 32 on ppc64)
+main 96 nosplit
+main 100 nosplit; REJECT ppc64 ppc64le
+main 104 nosplit; REJECT ppc64 ppc64le
+main 108 nosplit; REJECT ppc64 ppc64le
+main 112 nosplit; REJECT ppc64 ppc64le
+main 116 nosplit; REJECT ppc64 ppc64le
+main 120 nosplit; REJECT ppc64 ppc64le
+main 124 nosplit; REJECT ppc64 ppc64le
 main 128 nosplit; REJECT
 main 132 nosplit; REJECT
 main 136 nosplit; REJECT
@@ -126,11 +131,16 @@ main 136 nosplit; REJECT
 # Calling a nosplit function from a nosplit function requires
 # having room for the saved caller PC and the called frame.
 # Because ARM doesn't save LR in the leaf, it gets an extra 4 bytes.
-# Because ppc64 doesn't save LR in the leaf, it gets an extra 8 bytes.
-main 112 nosplit call f; f 0 nosplit
-main 116 nosplit call f; f 0 nosplit
-main 120 nosplit call f; f 0 nosplit; REJECT amd64
-main 124 nosplit call f; f 0 nosplit; REJECT amd64 386
+# Because arm64 doesn't save LR in the leaf, it gets an extra 8 bytes.
+# ppc64 doesn't save LR in the leaf, but CallSize is 32, so it gets 24 fewer bytes than amd64.
+main 96 nosplit call f; f 0 nosplit
+main 100 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le
+main 104 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le
+main 108 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le
+main 112 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le
+main 116 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le
+main 120 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le amd64
+main 124 nosplit call f; f 0 nosplit; REJECT ppc64 ppc64le amd64 386
 main 128 nosplit call f; f 0 nosplit; REJECT
 main 132 nosplit call f; f 0 nosplit; REJECT
 main 136 nosplit call f; f 0 nosplit; REJECT
@@ -138,24 +148,28 @@ main 136 nosplit call f; f 0 nosplit; REJECT
 # Calling a splitting function from a nosplit function requires
 # having room for the saved caller PC of the call but also the
 # saved caller PC for the call to morestack.
-# Again the ARM and ppc64 work in less space.
-main 104 nosplit call f; f 0 call f
-main 108 nosplit call f; f 0 call f
-main 112 nosplit call f; f 0 call f; REJECT amd64
-main 116 nosplit call f; f 0 call f; REJECT amd64
-main 120 nosplit call f; f 0 call f; REJECT amd64 386
-main 124 nosplit call f; f 0 call f; REJECT amd64 386
+# RISC architectures differ in the same way as before.
+main 96 nosplit call f; f 0 call f
+main 100 nosplit call f; f 0 call f; REJECT ppc64 ppc64le
+main 104 nosplit call f; f 0 call f; REJECT ppc64 ppc64le
+main 108 nosplit call f; f 0 call f; REJECT ppc64 ppc64le
+main 112 nosplit call f; f 0 call f; REJECT ppc64 ppc64le amd64
+main 116 nosplit call f; f 0 call f; REJECT ppc64 ppc64le amd64
+main 120 nosplit call f; f 0 call f; REJECT ppc64 ppc64le amd64 386
+main 124 nosplit call f; f 0 call f; REJECT ppc64 ppc64le amd64 386
 main 128 nosplit call f; f 0 call f; REJECT
 main 132 nosplit call f; f 0 call f; REJECT
 main 136 nosplit call f; f 0 call f; REJECT
 
 # Indirect calls are assumed to be splitting functions.
-main 104 nosplit callind
-main 108 nosplit callind
-main 112 nosplit callind; REJECT amd64
-main 116 nosplit callind; REJECT amd64
-main 120 nosplit callind; REJECT amd64 386
-main 124 nosplit callind; REJECT amd64 386
+main 96 nosplit callind
+main 100 nosplit callind; REJECT ppc64 ppc64le
+main 104 nosplit callind; REJECT ppc64 ppc64le
+main 108 nosplit callind; REJECT ppc64 ppc64le
+main 112 nosplit callind; REJECT ppc64 ppc64le amd64
+main 116 nosplit callind; REJECT ppc64 ppc64le amd64
+main 120 nosplit callind; REJECT ppc64 ppc64le amd64 386
+main 124 nosplit callind; REJECT ppc64 ppc64le amd64 386
 main 128 nosplit callind; REJECT
 main 132 nosplit callind; REJECT
 main 136 nosplit callind; REJECT
@@ -247,6 +261,9 @@ TestCases:
 		var buf bytes.Buffer
 		ptrSize := 4
 		switch goarch {
+		case "mips64", "mips64le":
+			ptrSize = 8
+			fmt.Fprintf(&buf, "#define CALL JAL\n#define REGISTER (R0)\n")
 		case "ppc64", "ppc64le":
 			ptrSize = 8
 			fmt.Fprintf(&buf, "#define CALL BL\n#define REGISTER (CTR)\n")
@@ -281,16 +298,16 @@ TestCases:
 				name := m[1]
 				size, _ := strconv.Atoi(m[2])
 
-				// The limit was originally 128 but is now 512.
+				// The limit was originally 128 but is now 592.
 				// Instead of rewriting the test cases above, adjust
 				// the first stack frame to use up the extra bytes.
 				if i == 0 {
-					size += 512 - 128
+					size += 592 - 128
 					// Noopt builds have a larger stackguard.
 					// See ../cmd/dist/buildruntime.go:stackGuardMultiplier
 					for _, s := range strings.Split(os.Getenv("GO_GCFLAGS"), " ") {
 						if s == "-N" {
-							size += 640
+							size += 720
 						}
 					}
 				}
diff --git a/test/recover4.go b/test/recover4.go
index cda0813..4c50260 100644
--- a/test/recover4.go
+++ b/test/recover4.go
@@ -52,6 +52,8 @@ func main() {
 		log.Fatalf("mmap: %v", err)
 	}
 
+	other := make([]byte, 16*size)
+
 	// Note: Cannot call syscall.Munmap, because Munmap checks
 	// that you are unmapping a whole region returned by Mmap.
 	// We are trying to unmap just a hole in the middle.
@@ -59,8 +61,6 @@ func main() {
 		log.Fatalf("munmap: %v", err)
 	}
 
-	other := make([]byte, 16*size)
-
 	// Check that memcopy returns the actual amount copied
 	// before the fault (8*size - 5, the offset we skip in the argument).
 	n, err := memcopy(data[5:], other)
diff --git a/test/reorder2.go b/test/reorder2.go
index e56be2b..3e87998 100644
--- a/test/reorder2.go
+++ b/test/reorder2.go
@@ -58,9 +58,8 @@ func f(x, y string) {
 	log += "f(" + x + ", " + y + ")"
 }
 
+//go:noinline
 func ff(x, y string) {
-	for false {
-	} // prevent inl
 	log += "ff(" + x + ", " + y + ")"
 }
 
@@ -69,9 +68,8 @@ func h(x string) string {
 	return x
 }
 
+//go:noinline
 func g(x string) string {
-	for false {
-	} // prevent inl
 	log += "g(" + x + ")"
 	return x
 }
@@ -167,7 +165,7 @@ func main() {
 		err++
 	}
 	log = ""
-	
+
 	x := 0
 	switch x {
 	case 0:
@@ -176,7 +174,7 @@ func main() {
 			err++
 		}
 		log = ""
-	
+
 		if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
 			println("in switch, expecting a(1)b(2)a(2), got ", log)
 			err++
@@ -194,7 +192,7 @@ func main() {
 		}
 		log = ""
 	}
-	
+
 	c := make(chan int, 1)
 	c <- 1
 	select {
@@ -206,7 +204,7 @@ func main() {
 			err++
 		}
 		log = ""
-	
+
 		if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
 			println("in select1, expecting a(1)b(2)a(2), got ", log)
 			err++
@@ -233,7 +231,7 @@ func main() {
 			err++
 		}
 		log = ""
-	
+
 		if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
 			println("in select2, expecting a(1)b(2)a(2), got ", log)
 			err++
@@ -255,14 +253,14 @@ func main() {
 	c <- 1
 	select {
 	default:
-	case c<-1:
+	case c <- 1:
 	case <-c:
 		if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
 			println("in select3, expecting a(1)a(2)a(3) , got ", log)
 			err++
 		}
 		log = ""
-	
+
 		if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
 			println("in select3, expecting a(1)b(2)a(2), got ", log)
 			err++
@@ -290,7 +288,7 @@ func main() {
 			err++
 		}
 		log = ""
-	
+
 		if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
 			println("in select4, expecting a(1)b(2)a(2), got ", log)
 			err++
@@ -318,7 +316,7 @@ func main() {
 			err++
 		}
 		log = ""
-	
+
 		if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
 			println("in select5, expecting a(1)b(2)a(2), got ", log)
 			err++
diff --git a/test/run.go b/test/run.go
index 6e1cde9..52230ef 100644
--- a/test/run.go
+++ b/test/run.go
@@ -37,6 +37,7 @@ var (
 	numParallel    = flag.Int("n", runtime.NumCPU(), "number of parallel tests to run")
 	summary        = flag.Bool("summary", false, "show summary of results")
 	showSkips      = flag.Bool("show_skips", false, "show skipped tests")
+	linkshared     = flag.Bool("linkshared", false, "")
 	updateErrors   = flag.Bool("update_errors", false, "update error messages in test file based on compiler output")
 	runoutputLimit = flag.Int("l", defaultRunOutputLimit(), "number of parallel runoutput tests to run")
 
@@ -132,9 +133,6 @@ func main() {
 			failed = true
 		}
 		resCount[status]++
-		if status == "skip" && !*verbose && !*showSkips {
-			continue
-		}
 		dt := fmt.Sprintf("%.3fs", test.dt.Seconds())
 		if status == "FAIL" {
 			fmt.Printf("# go run run.go -- %s\n%s\nFAIL\t%s\t%s\n",
@@ -194,11 +192,19 @@ func goFiles(dir string) []string {
 type runCmd func(...string) ([]byte, error)
 
 func compileFile(runcmd runCmd, longname string) (out []byte, err error) {
-	return runcmd("go", "tool", "compile", "-e", longname)
+	cmd := []string{"go", "tool", "compile", "-e"}
+	if *linkshared {
+		cmd = append(cmd, "-dynlink", "-installsuffix=dynlink")
+	}
+	cmd = append(cmd, longname)
+	return runcmd(cmd...)
 }
 
 func compileInDir(runcmd runCmd, dir string, names ...string) (out []byte, err error) {
 	cmd := []string{"go", "tool", "compile", "-e", "-D", ".", "-I", "."}
+	if *linkshared {
+		cmd = append(cmd, "-dynlink", "-installsuffix=dynlink")
+	}
 	for _, name := range names {
 		cmd = append(cmd, filepath.Join(dir, name))
 	}
@@ -207,7 +213,12 @@ func compileInDir(runcmd runCmd, dir string, names ...string) (out []byte, err e
 
 func linkFile(runcmd runCmd, goname string) (err error) {
 	pfile := strings.Replace(goname, ".go", ".o", -1)
-	_, err = runcmd("go", "tool", "link", "-w", "-o", "a.exe", "-L", ".", pfile)
+	cmd := []string{"go", "tool", "link", "-w", "-o", "a.exe", "-L", "."}
+	if *linkshared {
+		cmd = append(cmd, "-linkshared", "-installsuffix=dynlink")
+	}
+	cmd = append(cmd, pfile)
+	_, err = runcmd(cmd...)
 	return
 }
 
@@ -389,6 +400,10 @@ func (ctxt *context) match(name string) bool {
 		return true
 	}
 
+	if name == "test_run" {
+		return true
+	}
+
 	return false
 }
 
@@ -516,6 +531,7 @@ func (t *test) run() {
 
 	case "errorcheck":
 		cmdline := []string{"go", "tool", "compile", "-e", "-o", "a.o"}
+		// No need to add -dynlink even if linkshared if we're just checking for errors...
 		cmdline = append(cmdline, flags...)
 		cmdline = append(cmdline, long)
 		out, err := runcmd(cmdline...)
@@ -631,7 +647,12 @@ func (t *test) run() {
 
 	case "run":
 		useTmp = false
-		out, err := runcmd(append([]string{"go", "run", t.goFileName()}, args...)...)
+		cmd := []string{"go", "run"}
+		if *linkshared {
+			cmd = append(cmd, "-linkshared")
+		}
+		cmd = append(cmd, t.goFileName())
+		out, err := runcmd(append(cmd, args...)...)
 		if err != nil {
 			t.err = err
 			return
@@ -646,7 +667,12 @@ func (t *test) run() {
 			<-rungatec
 		}()
 		useTmp = false
-		out, err := runcmd(append([]string{"go", "run", t.goFileName()}, args...)...)
+		cmd := []string{"go", "run"}
+		if *linkshared {
+			cmd = append(cmd, "-linkshared")
+		}
+		cmd = append(cmd, t.goFileName())
+		out, err := runcmd(append(cmd, args...)...)
 		if err != nil {
 			t.err = err
 			return
@@ -656,7 +682,12 @@ func (t *test) run() {
 			t.err = fmt.Errorf("write tempfile:%s", err)
 			return
 		}
-		out, err = runcmd("go", "run", tfile)
+		cmd = []string{"go", "run"}
+		if *linkshared {
+			cmd = append(cmd, "-linkshared")
+		}
+		cmd = append(cmd, tfile)
+		out, err = runcmd(cmd...)
 		if err != nil {
 			t.err = err
 			return
@@ -667,7 +698,12 @@ func (t *test) run() {
 
 	case "errorcheckoutput":
 		useTmp = false
-		out, err := runcmd(append([]string{"go", "run", t.goFileName()}, args...)...)
+		cmd := []string{"go", "run"}
+		if *linkshared {
+			cmd = append(cmd, "-linkshared")
+		}
+		cmd = append(cmd, t.goFileName())
+		out, err := runcmd(append(cmd, args...)...)
 		if err != nil {
 			t.err = err
 			return
diff --git a/test/switch2.go b/test/switch2.go
new file mode 100644
index 0000000..11ff5c5
--- /dev/null
+++ b/test/switch2.go
@@ -0,0 +1,39 @@
+// errorcheck
+
+// Copyright 2015 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.
+
+// Verify that erroneous switch statements are detected by the compiler.
+// Does not compile.
+
+package main
+
+func f() {
+	switch {
+	case 0; // ERROR "expecting := or = or : or comma"
+	}
+
+	switch {
+	case 0; // ERROR "expecting := or = or : or comma"
+	default:
+	}
+
+	switch {
+	case 0: case 0: default:
+	}
+
+	switch {
+	case 0: f(); case 0:
+	case 0: f() case 0: // ERROR "unexpected case at end of statement"
+	}
+
+	switch {
+	case 0: f(); default:
+	case 0: f() default: // ERROR "unexpected default at end of statement"
+	}
+
+	switch {
+	if x: // ERROR "expecting case or default or }"
+	}
+}
diff --git a/test/syntax/chan.go b/test/syntax/chan.go
index 3b68bda..b016790 100644
--- a/test/syntax/chan.go
+++ b/test/syntax/chan.go
@@ -8,10 +8,10 @@ package main
 
 type xyz struct {
     ch chan
-} // ERROR "unexpected .*}.* in channel type"
+} // ERROR "unexpected .*}.* in channel type|missing channel element type"
 
-func Foo(y chan) { // ERROR "unexpected .*\).* in channel type"
+func Foo(y chan) { // ERROR "unexpected .*\).* in channel type|missing channel element type"
 }
 
-func Bar(x chan, y int) { // ERROR "unexpected comma in channel type"
+func Bar(x chan, y int) { // ERROR "unexpected comma in channel type|missing channel element type"
 }
diff --git a/test/syntax/composite.go b/test/syntax/composite.go
index 6565334..722805a 100644
--- a/test/syntax/composite.go
+++ b/test/syntax/composite.go
@@ -7,5 +7,5 @@
 package main
 
 var a = []int{
-	3 // ERROR "need trailing comma before newline in composite literal"
+	3 // ERROR "need trailing comma before newline in composite literal|expecting comma or }"
 }
diff --git a/test/syntax/forvar.go b/test/syntax/forvar.go
index dc592d2..043c299 100644
--- a/test/syntax/forvar.go
+++ b/test/syntax/forvar.go
@@ -7,4 +7,5 @@
 package main
 
 func main() {
+	var x int // avoid undefined: x error below with recursive-descent parser
 	for var x = 0; x < 10; x++ {	// ERROR "var declaration not allowed in for initializer"
diff --git a/test/syntax/semi4.go b/test/syntax/semi4.go
index 99c2d22..1f4e679 100644
--- a/test/syntax/semi4.go
+++ b/test/syntax/semi4.go
@@ -8,7 +8,7 @@ package main
 
 func main() {
 	for x		// GCCGO_ERROR "undefined"
-	{		// ERROR "missing .*{.* after for clause"
+	{		// ERROR "missing .*{.* after for clause|missing operand"
 		z	// GCCGO_ERROR "undefined"
 
 
diff --git a/test/syntax/semi6.go b/test/syntax/semi6.go
index c1e1cc3..1b51d8b 100644
--- a/test/syntax/semi6.go
+++ b/test/syntax/semi6.go
@@ -7,7 +7,5 @@
 package main
 
 type T	// ERROR "unexpected semicolon or newline in type declaration"
-{
-
-
-
+// line below uncommented to avoid follow-up error
+// {
\ No newline at end of file
diff --git a/test/syntax/semi7.go b/test/syntax/semi7.go
index 6c9ade8..357352d 100644
--- a/test/syntax/semi7.go
+++ b/test/syntax/semi7.go
@@ -8,7 +8,7 @@ package main
 
 func main() {
 	if x { }	// GCCGO_ERROR "undefined"
-	else { }	// ERROR "unexpected semicolon or newline before .?else.?"
+	else { }	// ERROR "unexpected semicolon or newline before .?else.?|unexpected else"
 }
 
 
diff --git a/test/syntax/vareq1.go b/test/syntax/vareq1.go
index e900eab..d4952fe 100644
--- a/test/syntax/vareq1.go
+++ b/test/syntax/vareq1.go
@@ -6,5 +6,5 @@
 
 package main
 
-var x map[string]string{"a":"b"}		// ERROR "unexpected { at end of statement|expected ';' or newline after top level declaration"
+var x map[string]string{"a":"b"}		// ERROR "unexpected { at end of statement|unexpected { after top level declaration|expected ';' or newline after top level declaration"
 
diff --git a/test/tinyfin.go b/test/tinyfin.go
index 8fb109f..5171dfc 100644
--- a/test/tinyfin.go
+++ b/test/tinyfin.go
@@ -10,53 +10,55 @@ package main
 
 import (
 	"runtime"
-	"sync/atomic"
 	"time"
 )
 
 func main() {
-	// Does not work on 32-bits due to partially conservative GC.
+	// Does not work on gccgo due to partially conservative GC.
 	// Try to enable when we have fully precise GC.
-	if runtime.GOARCH != "amd64" {
-		return
-	}
-	// Likewise for gccgo.
 	if runtime.Compiler == "gccgo" {
 		return
 	}
-	N := int32(100)
-	count := N
-	done := make([]bool, N)
-	for i := int32(0); i < N; i++ {
-		x := i // subject to tiny alloc
+	const N = 100
+	finalized := make(chan int32, N)
+	for i := 0; i < N; i++ {
+		x := new(int32) // subject to tiny alloc
+		*x = int32(i)
 		// the closure must be big enough to be combined
-		runtime.SetFinalizer(&x, func(p *int32) {
+		runtime.SetFinalizer(x, func(p *int32) {
+			finalized <- *p
+		})
+	}
+	runtime.GC()
+	count := 0
+	done := make([]bool, N)
+	timeout := time.After(5*time.Second)
+	for {
+		select {
+		case <-timeout:
+			println("timeout,", count, "finalized so far")
+			panic("not all finalizers are called")
+		case x := <-finalized:
 			// Check that p points to the correct subobject of the tiny allocation.
 			// It's a bit tricky, because we can't capture another variable
 			// with the expected value (it would be combined as well).
-			if *p < 0 || *p >= N {
-				println("got", *p)
+			if x < 0 || x >= N {
+				println("got", x)
 				panic("corrupted")
 			}
-			if done[*p] {
-				println("got", *p)
+			if done[x] {
+				println("got", x)
 				panic("already finalized")
 			}
-			done[*p] = true
-			atomic.AddInt32(&count, -1)
-		})
-	}
-	for i := 0; i < 4; i++ {
-		runtime.GC()
-		time.Sleep(10 * time.Millisecond)
-	}
-	// Some of the finalizers may not be executed,
-	// if the outermost allocations are combined with something persistent.
-	// Currently 4 int32's are combined into a 16-byte block,
-	// ensure that most of them are finalized.
-	if count >= N/4 {
-		println(count, "out of", N, "finalizer are not called")
-		panic("not all finalizers are called")
+			done[x] = true
+			count++
+			if count > N/10*9 {
+				// Some of the finalizers may not be executed,
+				// if the outermost allocations are combined with something persistent.
+				// Currently 4 int32's are combined into a 16-byte block,
+				// ensure that most of them are finalized.
+				return
+			}
+		}
 	}
 }
-
diff --git a/test/typecheckloop.go b/test/typecheckloop.go
new file mode 100644
index 0000000..3b3e788
--- /dev/null
+++ b/test/typecheckloop.go
@@ -0,0 +1,14 @@
+// errorcheck
+
+// Copyright 2015 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.
+
+// Verify that constant definition loops are caught during
+// typechecking and that the errors print correctly.
+
+package main
+
+const A = 1 + B // ERROR "constant definition loop\n.*A uses B\n.*B uses C\n.*C uses A"
+const B = C - 1 // ERROR "constant definition loop\n.*B uses C\n.*C uses B"
+const C = A + B + 1
diff --git a/test/writebarrier.go b/test/writebarrier.go
index 9b741a6..dcd20a0 100644
--- a/test/writebarrier.go
+++ b/test/writebarrier.go
@@ -144,3 +144,17 @@ type T8 struct {
 func f16(x []T8, y T8) []T8 {
 	return append(x, y) // ERROR "write barrier"
 }
+
+func t1(i interface{}) **int {
+	// From issue 14306, make sure we have write barriers in a type switch
+	// where the assigned variable escapes.
+	switch x := i.(type) { // ERROR "write barrier"
+	case *int:
+		return &x
+	}
+	switch y := i.(type) { // no write barrier here
+	case **int:
+		return y
+	}
+	return nil
+}

-- 
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